2008-05-08 16:54:20 +08:00
|
|
|
//===--- CGDebugInfo.cpp - Emit Debug Information for a Module ------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This coordinates the debug information generation while generating code.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "CGDebugInfo.h"
|
2009-09-30 10:43:10 +08:00
|
|
|
#include "CodeGenFunction.h"
|
2008-05-08 16:54:20 +08:00
|
|
|
#include "CodeGenModule.h"
|
2011-02-08 16:22:06 +08:00
|
|
|
#include "CGBlocks.h"
|
2008-05-25 13:15:42 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2010-08-28 01:47:47 +08:00
|
|
|
#include "clang/AST/DeclFriend.h"
|
2009-02-27 05:10:26 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2010-07-21 04:24:18 +08:00
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2008-11-11 15:01:36 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2009-07-19 03:43:29 +08:00
|
|
|
#include "clang/AST/RecordLayout.h"
|
2008-05-25 13:15:42 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
|
|
|
#include "clang/Basic/FileManager.h"
|
2009-09-16 05:48:34 +08:00
|
|
|
#include "clang/Basic/Version.h"
|
2010-06-16 07:19:56 +08:00
|
|
|
#include "clang/Frontend/CodeGenOptions.h"
|
2008-05-08 16:54:20 +08:00
|
|
|
#include "llvm/Constants.h"
|
|
|
|
#include "llvm/DerivedTypes.h"
|
|
|
|
#include "llvm/Instructions.h"
|
|
|
|
#include "llvm/Intrinsics.h"
|
|
|
|
#include "llvm/Module.h"
|
|
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2008-05-25 13:15:42 +08:00
|
|
|
#include "llvm/Support/Dwarf.h"
|
2010-11-30 02:12:39 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2011-02-07 18:33:21 +08:00
|
|
|
#include "llvm/Target/TargetData.h"
|
2008-05-25 13:15:42 +08:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2008-05-08 16:54:20 +08:00
|
|
|
using namespace clang;
|
|
|
|
using namespace clang::CodeGen;
|
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
|
2010-12-09 06:42:58 +08:00
|
|
|
: CGM(CGM), DBuilder(CGM.getModule()),
|
2010-08-21 06:02:57 +08:00
|
|
|
BlockLiteralGenericSet(false) {
|
2010-03-09 08:44:50 +08:00
|
|
|
CreateCompileUnit();
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
CGDebugInfo::~CGDebugInfo() {
|
2008-10-18 00:15:48 +08:00
|
|
|
assert(RegionStack.empty() && "Region stack mismatch, stack not empty!");
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::setLocation(SourceLocation Loc) {
|
|
|
|
if (Loc.isValid())
|
2009-12-07 02:00:51 +08:00
|
|
|
CurLoc = CGM.getContext().getSourceManager().getInstantiationLoc(Loc);
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2010-01-29 07:15:27 +08:00
|
|
|
/// getContextDescriptor - Get context info for the decl.
|
2010-12-09 08:33:05 +08:00
|
|
|
llvm::DIDescriptor CGDebugInfo::getContextDescriptor(const Decl *Context) {
|
2010-02-02 05:34:11 +08:00
|
|
|
if (!Context)
|
2010-12-09 08:33:05 +08:00
|
|
|
return TheCU;
|
2010-02-02 05:34:11 +08:00
|
|
|
|
|
|
|
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
|
|
|
|
I = RegionMap.find(Context);
|
|
|
|
if (I != RegionMap.end())
|
2010-09-18 21:00:17 +08:00
|
|
|
return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(&*I->second));
|
2010-02-02 06:40:08 +08:00
|
|
|
|
2010-02-02 05:34:11 +08:00
|
|
|
// Check namespace.
|
|
|
|
if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context))
|
2010-12-09 08:33:05 +08:00
|
|
|
return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl));
|
2010-05-14 07:52:37 +08:00
|
|
|
|
|
|
|
if (const RecordDecl *RDecl = dyn_cast<RecordDecl>(Context)) {
|
|
|
|
if (!RDecl->isDependentType()) {
|
2010-10-29 01:27:32 +08:00
|
|
|
llvm::DIType Ty = getOrCreateType(CGM.getContext().getTypeDeclType(RDecl),
|
2010-12-09 08:33:05 +08:00
|
|
|
getOrCreateMainFile());
|
2010-05-14 07:52:37 +08:00
|
|
|
return llvm::DIDescriptor(Ty);
|
|
|
|
}
|
|
|
|
}
|
2010-12-09 08:33:05 +08:00
|
|
|
return TheCU;
|
2009-10-06 08:35:31 +08:00
|
|
|
}
|
|
|
|
|
2010-01-14 08:36:21 +08:00
|
|
|
/// getFunctionName - Get function name for the given FunctionDecl. If the
|
|
|
|
/// name is constructred on demand (e.g. C++ destructor) then the name
|
|
|
|
/// is stored on the side.
|
|
|
|
llvm::StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
|
|
|
|
assert (FD && "Invalid FunctionDecl!");
|
|
|
|
IdentifierInfo *FII = FD->getIdentifier();
|
|
|
|
if (FII)
|
|
|
|
return FII->getName();
|
|
|
|
|
|
|
|
// Otherwise construct human readable name for debug info.
|
|
|
|
std::string NS = FD->getNameAsString();
|
|
|
|
|
|
|
|
// Copy this name on the side and use its reference.
|
2010-01-29 02:21:00 +08:00
|
|
|
char *StrPtr = DebugInfoNames.Allocate<char>(NS.length());
|
2010-01-24 02:16:07 +08:00
|
|
|
memcpy(StrPtr, NS.data(), NS.length());
|
|
|
|
return llvm::StringRef(StrPtr, NS.length());
|
2010-01-14 08:36:21 +08:00
|
|
|
}
|
|
|
|
|
2010-09-03 02:01:51 +08:00
|
|
|
llvm::StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
|
|
|
|
llvm::SmallString<256> MethodName;
|
|
|
|
llvm::raw_svector_ostream OS(MethodName);
|
|
|
|
OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
|
|
|
|
const DeclContext *DC = OMD->getDeclContext();
|
2010-10-29 01:27:32 +08:00
|
|
|
if (const ObjCImplementationDecl *OID =
|
|
|
|
dyn_cast<const ObjCImplementationDecl>(DC)) {
|
2010-09-03 02:01:51 +08:00
|
|
|
OS << OID->getName();
|
2010-10-29 01:27:32 +08:00
|
|
|
} else if (const ObjCInterfaceDecl *OID =
|
|
|
|
dyn_cast<const ObjCInterfaceDecl>(DC)) {
|
2010-10-19 01:51:06 +08:00
|
|
|
OS << OID->getName();
|
2010-10-29 01:27:32 +08:00
|
|
|
} else if (const ObjCCategoryImplDecl *OCD =
|
|
|
|
dyn_cast<const ObjCCategoryImplDecl>(DC)){
|
2010-09-03 02:01:51 +08:00
|
|
|
OS << ((NamedDecl *)OCD)->getIdentifier()->getNameStart() << '(' <<
|
|
|
|
OCD->getIdentifier()->getNameStart() << ')';
|
|
|
|
}
|
|
|
|
OS << ' ' << OMD->getSelector().getAsString() << ']';
|
|
|
|
|
|
|
|
char *StrPtr = DebugInfoNames.Allocate<char>(OS.tell());
|
|
|
|
memcpy(StrPtr, MethodName.begin(), OS.tell());
|
|
|
|
return llvm::StringRef(StrPtr, OS.tell());
|
|
|
|
}
|
|
|
|
|
2010-07-21 04:24:18 +08:00
|
|
|
/// getClassName - Get class name including template argument list.
|
|
|
|
llvm::StringRef
|
|
|
|
CGDebugInfo::getClassName(RecordDecl *RD) {
|
|
|
|
ClassTemplateSpecializationDecl *Spec
|
|
|
|
= dyn_cast<ClassTemplateSpecializationDecl>(RD);
|
|
|
|
if (!Spec)
|
|
|
|
return RD->getName();
|
|
|
|
|
|
|
|
const TemplateArgument *Args;
|
|
|
|
unsigned NumArgs;
|
|
|
|
std::string Buffer;
|
|
|
|
if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
|
|
|
|
const TemplateSpecializationType *TST =
|
|
|
|
cast<TemplateSpecializationType>(TAW->getType());
|
|
|
|
Args = TST->getArgs();
|
|
|
|
NumArgs = TST->getNumArgs();
|
|
|
|
} else {
|
|
|
|
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
2010-11-08 07:05:16 +08:00
|
|
|
Args = TemplateArgs.data();
|
|
|
|
NumArgs = TemplateArgs.size();
|
2010-07-21 04:24:18 +08:00
|
|
|
}
|
|
|
|
Buffer = RD->getIdentifier()->getNameStart();
|
|
|
|
PrintingPolicy Policy(CGM.getLangOptions());
|
|
|
|
Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
|
|
|
|
NumArgs,
|
|
|
|
Policy);
|
|
|
|
|
|
|
|
// Copy this name on the side and use its reference.
|
|
|
|
char *StrPtr = DebugInfoNames.Allocate<char>(Buffer.length());
|
|
|
|
memcpy(StrPtr, Buffer.data(), Buffer.length());
|
|
|
|
return llvm::StringRef(StrPtr, Buffer.length());
|
|
|
|
}
|
|
|
|
|
2010-03-09 08:44:50 +08:00
|
|
|
/// getOrCreateFile - Get the file debug info descriptor for the input location.
|
|
|
|
llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
|
2010-12-09 06:42:58 +08:00
|
|
|
if (!Loc.isValid())
|
|
|
|
// If Location is not valid then use main input file.
|
2011-02-23 02:56:36 +08:00
|
|
|
return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
|
2010-12-09 06:42:58 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2010-03-09 08:44:50 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
|
2010-03-30 08:27:51 +08:00
|
|
|
|
2011-02-17 02:40:36 +08:00
|
|
|
if (PLoc.isInvalid() || llvm::StringRef(PLoc.getFilename()).empty())
|
2010-11-12 04:45:16 +08:00
|
|
|
// If the location is not valid then use main input file.
|
2011-02-23 02:56:36 +08:00
|
|
|
return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
|
2010-11-12 04:45:16 +08:00
|
|
|
|
2010-03-30 08:27:51 +08:00
|
|
|
// Cache the results.
|
|
|
|
const char *fname = PLoc.getFilename();
|
|
|
|
llvm::DenseMap<const char *, llvm::WeakVH>::iterator it =
|
|
|
|
DIFileCache.find(fname);
|
|
|
|
|
|
|
|
if (it != DIFileCache.end()) {
|
|
|
|
// Verify that the information still exists.
|
|
|
|
if (&*it->second)
|
|
|
|
return llvm::DIFile(cast<llvm::MDNode>(it->second));
|
|
|
|
}
|
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
llvm::DIFile F = DBuilder.createFile(PLoc.getFilename(), getCurrentDirname());
|
2010-03-30 08:27:51 +08:00
|
|
|
|
2010-05-08 02:12:35 +08:00
|
|
|
DIFileCache[fname] = F;
|
2010-03-30 08:27:51 +08:00
|
|
|
return F;
|
|
|
|
|
2010-03-09 08:44:50 +08:00
|
|
|
}
|
2010-05-13 07:46:38 +08:00
|
|
|
|
2010-10-29 06:03:20 +08:00
|
|
|
/// getOrCreateMainFile - Get the file info for main compile unit.
|
|
|
|
llvm::DIFile CGDebugInfo::getOrCreateMainFile() {
|
2011-02-23 02:56:36 +08:00
|
|
|
return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
|
2010-10-29 06:03:20 +08:00
|
|
|
}
|
|
|
|
|
2010-05-13 07:46:38 +08:00
|
|
|
/// getLineNumber - Get line number for the location. If location is invalid
|
|
|
|
/// then use current location.
|
|
|
|
unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {
|
|
|
|
assert (CurLoc.isValid() && "Invalid current location!");
|
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc);
|
2010-11-12 04:45:16 +08:00
|
|
|
return PLoc.isValid()? PLoc.getLine() : 0;
|
2010-05-13 07:46:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// getColumnNumber - Get column number for the location. If location is
|
|
|
|
/// invalid then use current location.
|
|
|
|
unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) {
|
|
|
|
assert (CurLoc.isValid() && "Invalid current location!");
|
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc);
|
2010-11-12 04:45:16 +08:00
|
|
|
return PLoc.isValid()? PLoc.getColumn() : 0;
|
2010-05-13 07:46:38 +08:00
|
|
|
}
|
|
|
|
|
2010-07-27 23:17:16 +08:00
|
|
|
llvm::StringRef CGDebugInfo::getCurrentDirname() {
|
|
|
|
if (!CWDName.empty())
|
|
|
|
return CWDName;
|
|
|
|
char *CompDirnamePtr = NULL;
|
|
|
|
llvm::sys::Path CWD = llvm::sys::Path::GetCurrentDirectory();
|
|
|
|
CompDirnamePtr = DebugInfoNames.Allocate<char>(CWD.size());
|
|
|
|
memcpy(CompDirnamePtr, CWD.c_str(), CWD.size());
|
|
|
|
return CWDName = llvm::StringRef(CompDirnamePtr, CWD.size());
|
|
|
|
}
|
|
|
|
|
2010-03-09 08:44:50 +08:00
|
|
|
/// CreateCompileUnit - Create new compile unit.
|
|
|
|
void CGDebugInfo::CreateCompileUnit() {
|
2009-04-08 13:11:16 +08:00
|
|
|
|
2009-04-18 05:06:59 +08:00
|
|
|
// Get absolute path name.
|
2010-03-19 07:46:43 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2010-03-19 22:49:09 +08:00
|
|
|
std::string MainFileName = CGM.getCodeGenOpts().MainFileName;
|
|
|
|
if (MainFileName.empty())
|
2010-03-13 05:04:27 +08:00
|
|
|
MainFileName = "<unknown>";
|
2010-03-19 22:49:09 +08:00
|
|
|
|
2010-03-23 05:28:29 +08:00
|
|
|
// The main file name provided via the "-main-file-name" option contains just
|
|
|
|
// the file name itself with no path information. This file name may have had
|
|
|
|
// a relative path, so we look into the actual file entry for the main
|
|
|
|
// file to determine the real absolute path for the file.
|
2010-07-24 07:04:28 +08:00
|
|
|
std::string MainFileDir;
|
2010-07-27 23:17:16 +08:00
|
|
|
if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
|
2010-03-19 22:49:09 +08:00
|
|
|
MainFileDir = MainFile->getDir()->getName();
|
2010-07-27 23:17:16 +08:00
|
|
|
if (MainFileDir != ".")
|
|
|
|
MainFileName = MainFileDir + "/" + MainFileName;
|
|
|
|
}
|
2010-03-19 22:49:09 +08:00
|
|
|
|
2010-07-27 23:17:16 +08:00
|
|
|
// Save filename string.
|
|
|
|
char *FilenamePtr = DebugInfoNames.Allocate<char>(MainFileName.length());
|
|
|
|
memcpy(FilenamePtr, MainFileName.c_str(), MainFileName.length());
|
|
|
|
llvm::StringRef Filename(FilenamePtr, MainFileName.length());
|
|
|
|
|
2009-03-25 11:28:08 +08:00
|
|
|
unsigned LangTag;
|
2010-03-09 08:44:50 +08:00
|
|
|
const LangOptions &LO = CGM.getLangOptions();
|
2009-03-25 11:28:08 +08:00
|
|
|
if (LO.CPlusPlus) {
|
|
|
|
if (LO.ObjC1)
|
|
|
|
LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
|
|
|
|
else
|
|
|
|
LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
|
|
|
|
} else if (LO.ObjC1) {
|
2009-03-25 04:35:51 +08:00
|
|
|
LangTag = llvm::dwarf::DW_LANG_ObjC;
|
2009-03-25 11:28:08 +08:00
|
|
|
} else if (LO.C99) {
|
2009-03-25 04:35:51 +08:00
|
|
|
LangTag = llvm::dwarf::DW_LANG_C99;
|
2009-03-25 11:28:08 +08:00
|
|
|
} else {
|
|
|
|
LangTag = llvm::dwarf::DW_LANG_C89;
|
|
|
|
}
|
2009-04-18 05:06:59 +08:00
|
|
|
|
2010-08-25 01:41:09 +08:00
|
|
|
std::string Producer = getClangFullVersion();
|
2009-05-02 09:00:04 +08:00
|
|
|
|
|
|
|
// Figure out which version of the ObjC runtime we have.
|
|
|
|
unsigned RuntimeVers = 0;
|
|
|
|
if (LO.ObjC1)
|
|
|
|
RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Create new compile unit.
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createCompileUnit(
|
2010-07-28 04:49:59 +08:00
|
|
|
LangTag, Filename, getCurrentDirname(),
|
2010-12-09 06:42:58 +08:00
|
|
|
Producer,
|
2009-12-18 10:43:17 +08:00
|
|
|
LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers);
|
2010-12-09 06:42:58 +08:00
|
|
|
// FIXME - Eliminate TheCU.
|
|
|
|
TheCU = llvm::DICompileUnit(DBuilder.getCU());
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2009-02-25 09:36:11 +08:00
|
|
|
/// CreateType - Get the Basic type from the cache or create a new
|
2008-05-25 13:15:42 +08:00
|
|
|
/// one if necessary.
|
2010-11-02 00:52:40 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
|
2008-05-25 13:15:42 +08:00
|
|
|
unsigned Encoding = 0;
|
2010-07-29 07:23:29 +08:00
|
|
|
const char *BTName = NULL;
|
2008-11-10 14:08:34 +08:00
|
|
|
switch (BT->getKind()) {
|
|
|
|
default:
|
|
|
|
case BuiltinType::Void:
|
|
|
|
return llvm::DIType();
|
2010-07-28 09:33:15 +08:00
|
|
|
case BuiltinType::ObjCClass:
|
2011-02-23 02:56:36 +08:00
|
|
|
return DBuilder.createStructType(TheCU, "objc_class",
|
2010-12-09 06:42:58 +08:00
|
|
|
getOrCreateMainFile(), 0, 0, 0,
|
|
|
|
llvm::DIDescriptor::FlagFwdDecl,
|
|
|
|
llvm::DIArray());
|
2010-07-28 09:33:15 +08:00
|
|
|
case BuiltinType::ObjCId: {
|
|
|
|
// typedef struct objc_class *Class;
|
|
|
|
// typedef struct objc_object {
|
|
|
|
// Class isa;
|
|
|
|
// } *id;
|
|
|
|
|
|
|
|
llvm::DIType OCTy =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createStructType(TheCU, "objc_class",
|
2010-12-09 06:42:58 +08:00
|
|
|
getOrCreateMainFile(), 0, 0, 0,
|
|
|
|
llvm::DIDescriptor::FlagFwdDecl,
|
|
|
|
llvm::DIArray());
|
2010-07-28 09:33:15 +08:00
|
|
|
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
|
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
llvm::DIType ISATy = DBuilder.createPointerType(OCTy, Size);
|
2010-07-28 09:33:15 +08:00
|
|
|
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::SmallVector<llvm::Value *, 16> EltTys;
|
2010-07-28 09:33:15 +08:00
|
|
|
llvm::DIType FieldTy =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createMemberType("isa", getOrCreateMainFile(),
|
2010-12-09 06:42:58 +08:00
|
|
|
0,Size, 0, 0, 0, ISATy);
|
2010-07-28 09:33:15 +08:00
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
llvm::DIArray Elements =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
|
2010-07-28 09:33:15 +08:00
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
return DBuilder.createStructType(TheCU, "objc_object",
|
2010-12-09 06:42:58 +08:00
|
|
|
getOrCreateMainFile(),
|
|
|
|
0, 0, 0, 0, Elements);
|
2010-07-28 09:33:15 +08:00
|
|
|
}
|
2011-02-09 11:15:05 +08:00
|
|
|
case BuiltinType::ObjCSel: {
|
2011-02-23 02:56:36 +08:00
|
|
|
return DBuilder.createStructType(TheCU, "objc_selector",
|
2011-02-09 11:15:05 +08:00
|
|
|
getOrCreateMainFile(), 0, 0, 0,
|
|
|
|
llvm::DIDescriptor::FlagFwdDecl,
|
|
|
|
llvm::DIArray());
|
|
|
|
}
|
2008-11-10 14:08:34 +08:00
|
|
|
case BuiltinType::UChar:
|
|
|
|
case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break;
|
|
|
|
case BuiltinType::Char_S:
|
|
|
|
case BuiltinType::SChar: Encoding = llvm::dwarf::DW_ATE_signed_char; break;
|
|
|
|
case BuiltinType::UShort:
|
|
|
|
case BuiltinType::UInt:
|
|
|
|
case BuiltinType::ULong:
|
|
|
|
case BuiltinType::ULongLong: Encoding = llvm::dwarf::DW_ATE_unsigned; break;
|
|
|
|
case BuiltinType::Short:
|
|
|
|
case BuiltinType::Int:
|
|
|
|
case BuiltinType::Long:
|
|
|
|
case BuiltinType::LongLong: Encoding = llvm::dwarf::DW_ATE_signed; break;
|
|
|
|
case BuiltinType::Bool: Encoding = llvm::dwarf::DW_ATE_boolean; break;
|
|
|
|
case BuiltinType::Float:
|
2009-10-13 06:28:31 +08:00
|
|
|
case BuiltinType::LongDouble:
|
2008-11-10 14:08:34 +08:00
|
|
|
case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2010-07-29 07:23:29 +08:00
|
|
|
|
|
|
|
switch (BT->getKind()) {
|
|
|
|
case BuiltinType::Long: BTName = "long int"; break;
|
|
|
|
case BuiltinType::LongLong: BTName = "long long int"; break;
|
|
|
|
case BuiltinType::ULong: BTName = "long unsigned int"; break;
|
|
|
|
case BuiltinType::ULongLong: BTName = "long long unsigned int"; break;
|
|
|
|
default:
|
|
|
|
BTName = BT->getName(CGM.getContext().getLangOptions());
|
|
|
|
break;
|
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
// Bit size, align and offset of the type.
|
2009-12-07 02:00:51 +08:00
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(BT);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(BT);
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createBasicType(BTName, Size, Align, Encoding);
|
2009-10-21 03:55:01 +08:00
|
|
|
return DbgTy;
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2010-12-09 08:25:29 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) {
|
2009-04-23 14:13:01 +08:00
|
|
|
// Bit size, align and offset of the type.
|
|
|
|
unsigned Encoding = llvm::dwarf::DW_ATE_complex_float;
|
|
|
|
if (Ty->isComplexIntegerType())
|
|
|
|
Encoding = llvm::dwarf::DW_ATE_lo_user;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createBasicType("complex", Size, Align, Encoding);
|
2010-12-09 06:42:58 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
return DbgTy;
|
2009-04-23 14:13:01 +08:00
|
|
|
}
|
|
|
|
|
2009-09-25 09:40:47 +08:00
|
|
|
/// CreateCVRType - Get the qualified type from the cache or create
|
2008-11-10 14:08:34 +08:00
|
|
|
/// a new one if necessary.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
|
2009-09-25 09:40:47 +08:00
|
|
|
QualifierCollector Qc;
|
|
|
|
const Type *T = Qc.strip(Ty);
|
|
|
|
|
|
|
|
// Ignore these qualifiers for now.
|
|
|
|
Qc.removeObjCGCAttr();
|
|
|
|
Qc.removeAddressSpace();
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// We will create one Derived type for one qualifier and recurse to handle any
|
|
|
|
// additional ones.
|
|
|
|
unsigned Tag;
|
2009-09-25 09:40:47 +08:00
|
|
|
if (Qc.hasConst()) {
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_const_type;
|
2009-09-25 09:40:47 +08:00
|
|
|
Qc.removeConst();
|
|
|
|
} else if (Qc.hasVolatile()) {
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_volatile_type;
|
2009-09-25 09:40:47 +08:00
|
|
|
Qc.removeVolatile();
|
|
|
|
} else if (Qc.hasRestrict()) {
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_restrict_type;
|
2009-09-25 09:40:47 +08:00
|
|
|
Qc.removeRestrict();
|
|
|
|
} else {
|
|
|
|
assert(Qc.empty() && "Unknown type qualifier for debug info");
|
|
|
|
return getOrCreateType(QualType(T, 0), Unit);
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-12-10 19:01:00 +08:00
|
|
|
llvm::DIType FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit);
|
2009-09-25 09:40:47 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// No need to fill in the Name, Line, Size, Alignment, Offset in case of
|
|
|
|
// CVR derived types.
|
2011-02-23 02:56:36 +08:00
|
|
|
llvm::DIType DbgTy = DBuilder.createQualifiedType(Tag, FromTy);
|
2010-12-09 06:42:58 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
return DbgTy;
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2009-07-14 09:20:56 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
2009-11-07 03:19:55 +08:00
|
|
|
CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
|
|
|
|
Ty->getPointeeType(), Unit);
|
2009-10-21 03:55:01 +08:00
|
|
|
return DbgTy;
|
2009-07-14 09:20:56 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-11-07 03:19:55 +08:00
|
|
|
return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
|
|
|
|
Ty->getPointeeType(), Unit);
|
|
|
|
}
|
|
|
|
|
2010-10-01 03:05:55 +08:00
|
|
|
/// CreatePointeeType - Create PointTee type. If Pointee is a record
|
|
|
|
/// then emit record's fwd if debug info size reduction is enabled.
|
|
|
|
llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy,
|
|
|
|
llvm::DIFile Unit) {
|
|
|
|
if (!CGM.getCodeGenOpts().LimitDebugInfo)
|
|
|
|
return getOrCreateType(PointeeTy, Unit);
|
|
|
|
|
|
|
|
if (const RecordType *RTy = dyn_cast<RecordType>(PointeeTy)) {
|
|
|
|
RecordDecl *RD = RTy->getDecl();
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
|
|
|
|
unsigned Line = getLineNumber(RD->getLocation());
|
|
|
|
llvm::DIDescriptor FDContext =
|
2011-02-23 06:38:33 +08:00
|
|
|
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
|
2010-12-09 06:42:58 +08:00
|
|
|
|
2010-10-01 03:05:55 +08:00
|
|
|
if (RD->isStruct())
|
2011-02-23 02:56:36 +08:00
|
|
|
return DBuilder.createStructType(FDContext, RD->getName(), DefUnit,
|
2010-12-09 06:42:58 +08:00
|
|
|
Line, 0, 0, llvm::DIType::FlagFwdDecl,
|
|
|
|
llvm::DIArray());
|
2010-10-01 03:05:55 +08:00
|
|
|
else if (RD->isUnion())
|
2011-02-23 02:56:36 +08:00
|
|
|
return DBuilder.createUnionType(FDContext, RD->getName(), DefUnit,
|
2010-12-09 06:42:58 +08:00
|
|
|
Line, 0, 0, llvm::DIType::FlagFwdDecl,
|
|
|
|
llvm::DIArray());
|
2010-10-01 03:05:55 +08:00
|
|
|
else {
|
|
|
|
assert(RD->isClass() && "Unknown RecordType!");
|
2011-02-23 02:56:36 +08:00
|
|
|
return DBuilder.createClassType(FDContext, RD->getName(), DefUnit,
|
2010-12-09 06:42:58 +08:00
|
|
|
Line, 0, 0, 0, llvm::DIType::FlagFwdDecl,
|
|
|
|
llvm::DIType(), llvm::DIArray());
|
2010-10-01 03:05:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return getOrCreateType(PointeeTy, Unit);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-11-07 03:19:55 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
|
|
|
|
const Type *Ty,
|
|
|
|
QualType PointeeTy,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2010-12-09 06:42:58 +08:00
|
|
|
|
|
|
|
if (Tag == llvm::dwarf::DW_TAG_reference_type)
|
2011-02-23 02:56:36 +08:00
|
|
|
return DBuilder.createReferenceType(CreatePointeeType(PointeeTy, Unit));
|
2010-12-09 06:42:58 +08:00
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
// Bit size, align and offset of the type.
|
2009-11-07 03:19:55 +08:00
|
|
|
// Size is always the size of a pointer. We can't use getTypeSize here
|
|
|
|
// because that does not return the correct value for references.
|
2011-03-19 06:38:29 +08:00
|
|
|
unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
|
|
|
|
uint64_t Size = CGM.getContext().Target.getPointerWidth(AS);
|
2009-12-07 02:00:51 +08:00
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-12-09 06:42:58 +08:00
|
|
|
return
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit), Size, Align);
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2009-05-14 10:03:51 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-05-14 10:03:51 +08:00
|
|
|
if (BlockLiteralGenericSet)
|
|
|
|
return BlockLiteralGeneric;
|
|
|
|
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::SmallVector<llvm::Value *, 8> EltTys;
|
2009-05-14 10:03:51 +08:00
|
|
|
llvm::DIType FieldTy;
|
|
|
|
QualType FType;
|
|
|
|
uint64_t FieldSize, FieldOffset;
|
|
|
|
unsigned FieldAlign;
|
|
|
|
llvm::DIArray Elements;
|
|
|
|
llvm::DIType EltTy, DescTy;
|
|
|
|
|
|
|
|
FieldOffset = 0;
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().UnsignedLongTy;
|
2010-04-25 04:19:58 +08:00
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset));
|
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset));
|
2009-05-14 10:03:51 +08:00
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
Elements = DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
|
2009-05-14 10:03:51 +08:00
|
|
|
EltTys.clear();
|
|
|
|
|
2010-09-30 05:05:52 +08:00
|
|
|
unsigned Flags = llvm::DIDescriptor::FlagAppleBlock;
|
2010-05-13 07:46:38 +08:00
|
|
|
unsigned LineNo = getLineNumber(CurLoc);
|
2009-10-02 10:30:50 +08:00
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
EltTy = DBuilder.createStructType(Unit, "__block_descriptor",
|
2010-12-09 06:42:58 +08:00
|
|
|
Unit, LineNo, FieldOffset, 0,
|
|
|
|
Flags, Elements);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-14 10:03:51 +08:00
|
|
|
// Bit size, align and offset of the type.
|
2009-12-07 02:00:51 +08:00
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
DescTy = DBuilder.createPointerType(EltTy, Size);
|
2009-05-14 10:03:51 +08:00
|
|
|
|
|
|
|
FieldOffset = 0;
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
|
2010-04-25 04:19:58 +08:00
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().IntTy;
|
2010-04-25 04:19:58 +08:00
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
|
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "__reserved", &FieldOffset));
|
2010-04-25 04:26:20 +08:00
|
|
|
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
|
2010-04-25 04:19:58 +08:00
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset));
|
2009-05-14 10:03:51 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = DescTy;
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(Ty);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(Ty);
|
2011-02-23 02:56:36 +08:00
|
|
|
FieldTy = DBuilder.createMemberType("__descriptor", Unit,
|
2010-12-09 06:42:58 +08:00
|
|
|
LineNo, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
2009-05-14 10:03:51 +08:00
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
2011-02-23 02:56:36 +08:00
|
|
|
Elements = DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
|
2009-05-14 10:03:51 +08:00
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
EltTy = DBuilder.createStructType(Unit, "__block_literal_generic",
|
2010-12-09 06:42:58 +08:00
|
|
|
Unit, LineNo, FieldOffset, 0,
|
|
|
|
Flags, Elements);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-14 10:03:51 +08:00
|
|
|
BlockLiteralGenericSet = true;
|
2011-02-23 02:56:36 +08:00
|
|
|
BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size);
|
2009-05-14 10:03:51 +08:00
|
|
|
return BlockLiteralGeneric;
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2008-11-10 14:08:34 +08:00
|
|
|
// Typedefs are derived from some other type. If we have a typedef of a
|
|
|
|
// typedef, make sure to emit the whole chain.
|
|
|
|
llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
|
2010-12-09 06:42:58 +08:00
|
|
|
if (!Src.Verify())
|
|
|
|
return llvm::DIType();
|
2008-11-10 14:08:34 +08:00
|
|
|
// We don't set size information, but do specify where the typedef was
|
|
|
|
// declared.
|
2010-05-13 07:46:38 +08:00
|
|
|
unsigned Line = getLineNumber(Ty->getDecl()->getLocation());
|
2011-02-23 02:56:36 +08:00
|
|
|
llvm::DIType DbgTy = DBuilder.createTypedef(Src, Ty->getDecl()->getName(),
|
2010-12-09 06:42:58 +08:00
|
|
|
Unit, Line);
|
2009-10-21 03:55:01 +08:00
|
|
|
return DbgTy;
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::SmallVector<llvm::Value *, 16> EltTys;
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Add the result type at least.
|
|
|
|
EltTys.push_back(getOrCreateType(Ty->getResultType(), Unit));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Set up remainder of arguments if there is a prototype.
|
|
|
|
// FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'!
|
2010-10-07 04:51:45 +08:00
|
|
|
if (isa<FunctionNoProtoType>(Ty))
|
2011-02-23 02:56:36 +08:00
|
|
|
EltTys.push_back(DBuilder.createUnspecifiedParameter());
|
2010-10-07 04:51:45 +08:00
|
|
|
else if (const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(Ty)) {
|
2008-11-10 14:08:34 +08:00
|
|
|
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
|
|
|
|
EltTys.push_back(getOrCreateType(FTP->getArgType(i), Unit));
|
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIArray EltTypeArray =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
llvm::DIType DbgTy = DBuilder.createSubroutineType(Unit, EltTypeArray);
|
2009-10-21 03:55:01 +08:00
|
|
|
return DbgTy;
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2011-02-23 06:38:33 +08:00
|
|
|
llvm::DIType CGDebugInfo::createFieldType(llvm::StringRef name,
|
|
|
|
QualType type,
|
|
|
|
Expr *bitWidth,
|
|
|
|
SourceLocation loc,
|
|
|
|
AccessSpecifier AS,
|
|
|
|
uint64_t offsetInBits,
|
|
|
|
llvm::DIFile tunit) {
|
|
|
|
llvm::DIType debugType = getOrCreateType(type, tunit);
|
|
|
|
|
|
|
|
// Get the location for the field.
|
|
|
|
llvm::DIFile file = getOrCreateFile(loc);
|
|
|
|
unsigned line = getLineNumber(loc);
|
|
|
|
|
|
|
|
uint64_t sizeInBits = 0;
|
|
|
|
unsigned alignInBits = 0;
|
|
|
|
if (!type->isIncompleteArrayType()) {
|
|
|
|
llvm::tie(sizeInBits, alignInBits) = CGM.getContext().getTypeInfo(type);
|
|
|
|
|
|
|
|
if (bitWidth)
|
|
|
|
sizeInBits = bitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned flags = 0;
|
|
|
|
if (AS == clang::AS_private)
|
|
|
|
flags |= llvm::DIDescriptor::FlagPrivate;
|
|
|
|
else if (AS == clang::AS_protected)
|
|
|
|
flags |= llvm::DIDescriptor::FlagProtected;
|
|
|
|
|
|
|
|
return DBuilder.createMemberType(name, file, line, sizeInBits, alignInBits,
|
|
|
|
offsetInBits, flags, debugType);
|
|
|
|
}
|
|
|
|
|
2010-01-19 08:00:59 +08:00
|
|
|
/// CollectRecordFields - A helper function to collect debug info for
|
|
|
|
/// record fields. This is used while creating debug info entry for a Record.
|
|
|
|
void CGDebugInfo::
|
2011-02-23 06:38:33 +08:00
|
|
|
CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
|
|
|
|
llvm::SmallVectorImpl<llvm::Value *> &elements) {
|
|
|
|
unsigned fieldNo = 0;
|
|
|
|
const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);
|
|
|
|
for (RecordDecl::field_iterator I = record->field_begin(),
|
|
|
|
E = record->field_end();
|
|
|
|
I != E; ++I, ++fieldNo) {
|
|
|
|
FieldDecl *field = *I;
|
|
|
|
|
|
|
|
llvm::StringRef name = field->getName();
|
|
|
|
QualType type = field->getType();
|
|
|
|
|
|
|
|
// Ignore unnamed fields unless they're anonymous structs/unions.
|
|
|
|
if (name.empty() && !type->isRecordType())
|
2010-01-19 08:00:59 +08:00
|
|
|
continue;
|
|
|
|
|
2011-02-23 06:38:33 +08:00
|
|
|
llvm::DIType fieldType
|
|
|
|
= createFieldType(name, type, field->getBitWidth(),
|
|
|
|
field->getLocation(), field->getAccess(),
|
|
|
|
layout.getFieldOffset(fieldNo), tunit);
|
2010-04-22 07:12:37 +08:00
|
|
|
|
2011-02-23 06:38:33 +08:00
|
|
|
elements.push_back(fieldType);
|
2010-01-19 08:00:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-28 08:28:01 +08:00
|
|
|
/// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This
|
|
|
|
/// function type is not updated to include implicit "this" pointer. Use this
|
|
|
|
/// routine to get a method type which includes "this" pointer.
|
|
|
|
llvm::DIType
|
|
|
|
CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2010-05-05 02:18:31 +08:00
|
|
|
llvm::DIType FnTy
|
|
|
|
= getOrCreateType(QualType(Method->getType()->getAs<FunctionProtoType>(),
|
|
|
|
0),
|
|
|
|
Unit);
|
2010-01-29 05:43:50 +08:00
|
|
|
|
2010-01-28 08:28:01 +08:00
|
|
|
// Add "this" pointer.
|
|
|
|
|
2010-05-08 02:12:35 +08:00
|
|
|
llvm::DIArray Args = llvm::DICompositeType(FnTy).getTypeArray();
|
2010-01-28 08:28:01 +08:00
|
|
|
assert (Args.getNumElements() && "Invalid number of arguments!");
|
|
|
|
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::SmallVector<llvm::Value *, 16> Elts;
|
2010-01-28 08:28:01 +08:00
|
|
|
|
|
|
|
// First element is always return type. For 'void' functions it is NULL.
|
|
|
|
Elts.push_back(Args.getElement(0));
|
|
|
|
|
2010-08-28 01:47:47 +08:00
|
|
|
if (!Method->isStatic())
|
|
|
|
{
|
|
|
|
// "this" pointer is always first argument.
|
2011-04-06 07:26:36 +08:00
|
|
|
QualType ThisPtr = Method->getThisType(CGM.getContext());
|
2010-08-28 01:47:47 +08:00
|
|
|
llvm::DIType ThisPtrType =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createArtificialType(getOrCreateType(ThisPtr, Unit));
|
2010-08-28 01:47:47 +08:00
|
|
|
|
|
|
|
TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
|
|
|
|
Elts.push_back(ThisPtrType);
|
|
|
|
}
|
2010-01-28 08:28:01 +08:00
|
|
|
|
|
|
|
// Copy rest of the arguments.
|
|
|
|
for (unsigned i = 1, e = Args.getNumElements(); i != e; ++i)
|
|
|
|
Elts.push_back(Args.getElement(i));
|
|
|
|
|
|
|
|
llvm::DIArray EltTypeArray =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.getOrCreateArray(Elts.data(), Elts.size());
|
2010-01-28 08:28:01 +08:00
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
return DBuilder.createSubroutineType(Unit, EltTypeArray);
|
2010-01-28 08:28:01 +08:00
|
|
|
}
|
|
|
|
|
2010-10-23 01:11:50 +08:00
|
|
|
/// isFunctionLocalClass - Return true if CXXRecordDecl is defined
|
|
|
|
/// inside a function.
|
|
|
|
static bool isFunctionLocalClass(const CXXRecordDecl *RD) {
|
|
|
|
if (const CXXRecordDecl *NRD =
|
|
|
|
dyn_cast<CXXRecordDecl>(RD->getDeclContext()))
|
|
|
|
return isFunctionLocalClass(NRD);
|
|
|
|
else if (isa<FunctionDecl>(RD->getDeclContext()))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
2010-01-26 12:49:33 +08:00
|
|
|
/// CreateCXXMemberFunction - A helper function to create a DISubprogram for
|
|
|
|
/// a single member function GlobalDecl.
|
|
|
|
llvm::DISubprogram
|
2010-01-26 13:19:50 +08:00
|
|
|
CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit,
|
2010-08-21 06:02:57 +08:00
|
|
|
llvm::DIType RecordTy) {
|
2010-01-26 13:19:50 +08:00
|
|
|
bool IsCtorOrDtor =
|
|
|
|
isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
|
|
|
|
|
|
|
|
llvm::StringRef MethodName = getFunctionName(Method);
|
2010-01-28 08:28:01 +08:00
|
|
|
llvm::DIType MethodTy = getOrCreateMethodType(Method, Unit);
|
2010-01-26 13:19:50 +08:00
|
|
|
|
|
|
|
// Since a single ctor/dtor corresponds to multiple functions, it doesn't
|
|
|
|
// make sense to give a single ctor/dtor a linkage name.
|
2010-06-23 00:16:50 +08:00
|
|
|
llvm::StringRef MethodLinkageName;
|
2010-10-23 01:11:50 +08:00
|
|
|
if (!IsCtorOrDtor && !isFunctionLocalClass(Method->getParent()))
|
2010-06-23 00:16:50 +08:00
|
|
|
MethodLinkageName = CGM.getMangledName(Method);
|
2010-01-26 13:19:50 +08:00
|
|
|
|
2010-01-26 12:49:33 +08:00
|
|
|
// Get the location for the method.
|
2010-05-13 07:46:38 +08:00
|
|
|
llvm::DIFile MethodDefUnit = getOrCreateFile(Method->getLocation());
|
|
|
|
unsigned MethodLine = getLineNumber(Method->getLocation());
|
2010-01-26 12:49:33 +08:00
|
|
|
|
|
|
|
// Collect virtual method info.
|
|
|
|
llvm::DIType ContainingType;
|
|
|
|
unsigned Virtuality = 0;
|
|
|
|
unsigned VIndex = 0;
|
2010-01-26 13:19:50 +08:00
|
|
|
|
2010-01-26 12:49:33 +08:00
|
|
|
if (Method->isVirtual()) {
|
2010-01-26 13:19:50 +08:00
|
|
|
if (Method->isPure())
|
|
|
|
Virtuality = llvm::dwarf::DW_VIRTUALITY_pure_virtual;
|
|
|
|
else
|
|
|
|
Virtuality = llvm::dwarf::DW_VIRTUALITY_virtual;
|
|
|
|
|
|
|
|
// It doesn't make sense to give a virtual destructor a vtable index,
|
|
|
|
// since a single destructor has two entries in the vtable.
|
|
|
|
if (!isa<CXXDestructorDecl>(Method))
|
2010-04-18 04:15:18 +08:00
|
|
|
VIndex = CGM.getVTables().getMethodVTableIndex(Method);
|
2010-01-26 12:49:33 +08:00
|
|
|
ContainingType = RecordTy;
|
|
|
|
}
|
|
|
|
|
2010-09-30 05:05:52 +08:00
|
|
|
unsigned Flags = 0;
|
|
|
|
if (Method->isImplicit())
|
|
|
|
Flags |= llvm::DIDescriptor::FlagArtificial;
|
2010-09-30 05:46:16 +08:00
|
|
|
AccessSpecifier Access = Method->getAccess();
|
|
|
|
if (Access == clang::AS_private)
|
|
|
|
Flags |= llvm::DIDescriptor::FlagPrivate;
|
|
|
|
else if (Access == clang::AS_protected)
|
|
|
|
Flags |= llvm::DIDescriptor::FlagProtected;
|
2010-10-02 07:32:17 +08:00
|
|
|
if (const CXXConstructorDecl *CXXC = dyn_cast<CXXConstructorDecl>(Method)) {
|
|
|
|
if (CXXC->isExplicit())
|
|
|
|
Flags |= llvm::DIDescriptor::FlagExplicit;
|
|
|
|
} else if (const CXXConversionDecl *CXXC =
|
|
|
|
dyn_cast<CXXConversionDecl>(Method)) {
|
|
|
|
if (CXXC->isExplicit())
|
|
|
|
Flags |= llvm::DIDescriptor::FlagExplicit;
|
|
|
|
}
|
2010-10-08 06:03:49 +08:00
|
|
|
if (Method->hasPrototype())
|
|
|
|
Flags |= llvm::DIDescriptor::FlagPrototyped;
|
2010-10-02 07:32:17 +08:00
|
|
|
|
2010-01-26 12:49:33 +08:00
|
|
|
llvm::DISubprogram SP =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createMethod(RecordTy , MethodName, MethodLinkageName,
|
2010-12-09 06:42:58 +08:00
|
|
|
MethodDefUnit, MethodLine,
|
|
|
|
MethodTy, /*isLocalToUnit=*/false,
|
|
|
|
/* isDefinition=*/ false,
|
|
|
|
Virtuality, VIndex, ContainingType,
|
|
|
|
Flags, CGM.getLangOptions().Optimize);
|
2010-01-26 13:19:50 +08:00
|
|
|
|
|
|
|
// Don't cache ctors or dtors since we have to emit multiple functions for
|
|
|
|
// a single ctor or dtor.
|
|
|
|
if (!IsCtorOrDtor && Method->isThisDeclarationADefinition())
|
2010-05-08 02:12:35 +08:00
|
|
|
SPCache[Method] = llvm::WeakVH(SP);
|
2010-01-26 12:49:33 +08:00
|
|
|
|
|
|
|
return SP;
|
|
|
|
}
|
|
|
|
|
2010-01-19 09:54:44 +08:00
|
|
|
/// CollectCXXMemberFunctions - A helper function to collect debug info for
|
|
|
|
/// C++ member functions.This is used while creating debug info entry for
|
|
|
|
/// a Record.
|
|
|
|
void CGDebugInfo::
|
2010-03-09 08:44:50 +08:00
|
|
|
CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::SmallVectorImpl<llvm::Value *> &EltTys,
|
2010-08-21 06:02:57 +08:00
|
|
|
llvm::DIType RecordTy) {
|
2010-02-02 05:39:52 +08:00
|
|
|
for(CXXRecordDecl::method_iterator I = RD->method_begin(),
|
|
|
|
E = RD->method_end(); I != E; ++I) {
|
2010-01-26 12:49:33 +08:00
|
|
|
const CXXMethodDecl *Method = *I;
|
2010-01-26 12:40:11 +08:00
|
|
|
|
2010-02-10 03:09:28 +08:00
|
|
|
if (Method->isImplicit() && !Method->isUsed())
|
2010-01-26 12:40:11 +08:00
|
|
|
continue;
|
2010-01-26 07:17:15 +08:00
|
|
|
|
2010-01-26 12:49:33 +08:00
|
|
|
EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));
|
2010-01-19 09:54:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-28 01:47:47 +08:00
|
|
|
/// CollectCXXFriends - A helper function to collect debug info for
|
|
|
|
/// C++ base classes. This is used while creating debug info entry for
|
|
|
|
/// a Record.
|
|
|
|
void CGDebugInfo::
|
|
|
|
CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit,
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::SmallVectorImpl<llvm::Value *> &EltTys,
|
2010-08-28 01:47:47 +08:00
|
|
|
llvm::DIType RecordTy) {
|
|
|
|
|
|
|
|
for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(),
|
|
|
|
BE = RD->friend_end(); BI != BE; ++BI) {
|
2010-12-09 06:42:58 +08:00
|
|
|
if (TypeSourceInfo *TInfo = (*BI)->getFriendType())
|
2011-02-23 02:56:36 +08:00
|
|
|
EltTys.push_back(DBuilder.createFriend(RecordTy,
|
2010-12-09 06:42:58 +08:00
|
|
|
getOrCreateType(TInfo->getType(),
|
|
|
|
Unit)));
|
2010-08-28 01:47:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-26 07:32:18 +08:00
|
|
|
/// CollectCXXBases - A helper function to collect debug info for
|
|
|
|
/// C++ base classes. This is used while creating debug info entry for
|
|
|
|
/// a Record.
|
|
|
|
void CGDebugInfo::
|
2010-03-09 08:44:50 +08:00
|
|
|
CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::SmallVectorImpl<llvm::Value *> &EltTys,
|
2010-08-21 06:02:57 +08:00
|
|
|
llvm::DIType RecordTy) {
|
2010-01-26 07:32:18 +08:00
|
|
|
|
2010-02-02 05:39:52 +08:00
|
|
|
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
|
|
|
|
for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(),
|
|
|
|
BE = RD->bases_end(); BI != BE; ++BI) {
|
2010-01-29 05:54:15 +08:00
|
|
|
unsigned BFlags = 0;
|
2011-04-05 04:36:06 +08:00
|
|
|
uint64_t BaseOffset;
|
2010-01-29 05:54:15 +08:00
|
|
|
|
|
|
|
const CXXRecordDecl *Base =
|
|
|
|
cast<CXXRecordDecl>(BI->getType()->getAs<RecordType>()->getDecl());
|
|
|
|
|
|
|
|
if (BI->isVirtual()) {
|
2010-03-11 15:15:17 +08:00
|
|
|
// virtual base offset offset is -ve. The code generator emits dwarf
|
2010-02-10 03:09:28 +08:00
|
|
|
// expression where it expects +ve number.
|
2011-04-07 20:37:09 +08:00
|
|
|
BaseOffset =
|
|
|
|
0 - CGM.getVTables().getVirtualBaseOffsetOffset(RD, Base).getQuantity();
|
2010-09-30 05:05:52 +08:00
|
|
|
BFlags = llvm::DIDescriptor::FlagVirtual;
|
2010-01-29 05:54:15 +08:00
|
|
|
} else
|
2011-04-05 04:36:06 +08:00
|
|
|
BaseOffset = RL.getBaseClassOffsetInBits(Base);
|
2011-04-07 20:37:09 +08:00
|
|
|
// FIXME: Inconsistent units for BaseOffset. It is in bytes when
|
|
|
|
// BI->isVirtual() and bits when not.
|
2010-01-29 05:54:15 +08:00
|
|
|
|
|
|
|
AccessSpecifier Access = BI->getAccessSpecifier();
|
|
|
|
if (Access == clang::AS_private)
|
2010-09-30 05:05:52 +08:00
|
|
|
BFlags |= llvm::DIDescriptor::FlagPrivate;
|
2010-01-29 05:54:15 +08:00
|
|
|
else if (Access == clang::AS_protected)
|
2010-09-30 05:05:52 +08:00
|
|
|
BFlags |= llvm::DIDescriptor::FlagProtected;
|
2010-01-29 05:54:15 +08:00
|
|
|
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::DIType DTy =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createInheritance(RecordTy,
|
2010-12-09 06:42:58 +08:00
|
|
|
getOrCreateType(BI->getType(), Unit),
|
2011-04-05 04:36:06 +08:00
|
|
|
BaseOffset, BFlags);
|
2010-01-29 05:54:15 +08:00
|
|
|
EltTys.push_back(DTy);
|
|
|
|
}
|
2010-01-26 07:32:18 +08:00
|
|
|
}
|
|
|
|
|
2011-04-06 06:54:11 +08:00
|
|
|
/// CollectTemplateParams - A helper function to collect template parameters.
|
2011-04-06 01:30:54 +08:00
|
|
|
llvm::DIArray CGDebugInfo::
|
2011-04-06 06:54:11 +08:00
|
|
|
CollectTemplateParams(const TemplateParameterList *TPList,
|
|
|
|
const TemplateArgumentList &TAList,
|
|
|
|
llvm::DIFile Unit) {
|
2011-04-06 04:15:06 +08:00
|
|
|
llvm::SmallVector<llvm::Value *, 16> TemplateParams;
|
|
|
|
for (unsigned i = 0, e = TAList.size(); i != e; ++i) {
|
|
|
|
const TemplateArgument &TA = TAList[i];
|
2011-04-06 06:54:11 +08:00
|
|
|
const NamedDecl *ND = TPList->getParam(i);
|
2011-04-06 01:30:54 +08:00
|
|
|
if (TA.getKind() == TemplateArgument::Type) {
|
|
|
|
llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit);
|
|
|
|
llvm::DITemplateTypeParameter TTP =
|
2011-04-06 04:15:06 +08:00
|
|
|
DBuilder.createTemplateTypeParameter(TheCU, ND->getName(), TTy);
|
2011-04-06 01:30:54 +08:00
|
|
|
TemplateParams.push_back(TTP);
|
|
|
|
} else if (TA.getKind() == TemplateArgument::Integral) {
|
|
|
|
llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit);
|
|
|
|
llvm::DITemplateValueParameter TVP =
|
2011-04-06 04:15:06 +08:00
|
|
|
DBuilder.createTemplateValueParameter(TheCU, ND->getName(), TTy,
|
|
|
|
TA.getAsIntegral()->getZExtValue());
|
2011-04-06 01:30:54 +08:00
|
|
|
TemplateParams.push_back(TVP);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return DBuilder.getOrCreateArray(TemplateParams.data(), TemplateParams.size());
|
|
|
|
}
|
|
|
|
|
2011-04-06 06:54:11 +08:00
|
|
|
/// CollectFunctionTemplateParams - A helper function to collect debug
|
|
|
|
/// info for function template parameters.
|
|
|
|
llvm::DIArray CGDebugInfo::
|
|
|
|
CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit) {
|
|
|
|
if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplateSpecialization){
|
|
|
|
const TemplateParameterList *TList =
|
|
|
|
FD->getTemplateSpecializationInfo()->getTemplate()->getTemplateParameters();
|
|
|
|
return
|
|
|
|
CollectTemplateParams(TList, *FD->getTemplateSpecializationArgs(), Unit);
|
|
|
|
}
|
|
|
|
return llvm::DIArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// CollectCXXTemplateParams - A helper function to collect debug info for
|
|
|
|
/// template parameters.
|
|
|
|
llvm::DIArray CGDebugInfo::
|
|
|
|
CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TSpecial,
|
|
|
|
llvm::DIFile Unit) {
|
|
|
|
llvm::PointerUnion<ClassTemplateDecl *,
|
|
|
|
ClassTemplatePartialSpecializationDecl *>
|
|
|
|
PU = TSpecial->getSpecializedTemplateOrPartial();
|
|
|
|
|
|
|
|
TemplateParameterList *TPList = PU.is<ClassTemplateDecl *>() ?
|
|
|
|
PU.get<ClassTemplateDecl *>()->getTemplateParameters() :
|
|
|
|
PU.get<ClassTemplatePartialSpecializationDecl *>()->getTemplateParameters();
|
|
|
|
const TemplateArgumentList &TAList = TSpecial->getTemplateInstantiationArgs();
|
|
|
|
return CollectTemplateParams(TPList, TAList, Unit);
|
|
|
|
}
|
|
|
|
|
2010-01-29 02:11:52 +08:00
|
|
|
/// getOrCreateVTablePtrType - Return debug info descriptor for vtable.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) {
|
2010-03-09 04:53:17 +08:00
|
|
|
if (VTablePtrType.isValid())
|
2010-01-29 02:11:52 +08:00
|
|
|
return VTablePtrType;
|
|
|
|
|
|
|
|
ASTContext &Context = CGM.getContext();
|
|
|
|
|
|
|
|
/* Function type */
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::Value *STy = getOrCreateType(Context.IntTy, Unit);
|
2011-02-23 02:56:36 +08:00
|
|
|
llvm::DIArray SElements = DBuilder.getOrCreateArray(&STy, 1);
|
|
|
|
llvm::DIType SubTy = DBuilder.createSubroutineType(Unit, SElements);
|
2010-01-29 02:11:52 +08:00
|
|
|
unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
|
2011-02-23 02:56:36 +08:00
|
|
|
llvm::DIType vtbl_ptr_type = DBuilder.createPointerType(SubTy, Size, 0,
|
2010-12-09 06:42:58 +08:00
|
|
|
"__vtbl_ptr_type");
|
2011-02-23 02:56:36 +08:00
|
|
|
VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size);
|
2010-01-29 02:11:52 +08:00
|
|
|
return VTablePtrType;
|
|
|
|
}
|
|
|
|
|
2010-04-18 04:15:18 +08:00
|
|
|
/// getVTableName - Get vtable name for the given Class.
|
|
|
|
llvm::StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
|
2010-01-29 02:11:52 +08:00
|
|
|
// Otherwise construct gdb compatible name name.
|
2010-02-02 05:39:52 +08:00
|
|
|
std::string Name = "_vptr$" + RD->getNameAsString();
|
2010-01-29 02:11:52 +08:00
|
|
|
|
|
|
|
// Copy this name on the side and use its reference.
|
2010-01-29 02:21:00 +08:00
|
|
|
char *StrPtr = DebugInfoNames.Allocate<char>(Name.length());
|
2010-01-29 02:11:52 +08:00
|
|
|
memcpy(StrPtr, Name.data(), Name.length());
|
|
|
|
return llvm::StringRef(StrPtr, Name.length());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-18 04:15:18 +08:00
|
|
|
/// CollectVTableInfo - If the C++ class has vtable info then insert appropriate
|
2010-01-29 02:11:52 +08:00
|
|
|
/// debug info entry in EltTys vector.
|
|
|
|
void CGDebugInfo::
|
2010-04-18 04:15:18 +08:00
|
|
|
CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::SmallVectorImpl<llvm::Value *> &EltTys) {
|
2010-02-02 05:39:52 +08:00
|
|
|
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
|
2010-01-29 02:11:52 +08:00
|
|
|
|
|
|
|
// If there is a primary base then it will hold vtable info.
|
|
|
|
if (RL.getPrimaryBase())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If this class is not dynamic then there is not any vtable info to collect.
|
2010-02-02 05:39:52 +08:00
|
|
|
if (!RD->isDynamicClass())
|
2010-01-29 02:11:52 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
|
|
|
|
llvm::DIType VPTR
|
2011-02-23 02:56:36 +08:00
|
|
|
= DBuilder.createMemberType(getVTableName(RD), Unit,
|
2010-12-09 06:42:58 +08:00
|
|
|
0, Size, 0, 0, 0,
|
|
|
|
getOrCreateVTablePtrType(Unit));
|
2010-01-29 02:11:52 +08:00
|
|
|
EltTys.push_back(VPTR);
|
|
|
|
}
|
|
|
|
|
2010-10-01 03:05:55 +08:00
|
|
|
/// getOrCreateRecordType - Emit record type's standalone debug info.
|
|
|
|
llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
|
|
|
|
SourceLocation Loc) {
|
|
|
|
llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc));
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.retainType(T);
|
2010-10-01 03:05:55 +08:00
|
|
|
return T;
|
|
|
|
}
|
|
|
|
|
2009-02-25 09:36:11 +08:00
|
|
|
/// CreateType - get structure or union type.
|
2011-01-18 06:23:07 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
|
2010-02-02 05:52:22 +08:00
|
|
|
RecordDecl *RD = Ty->getDecl();
|
2011-01-18 06:23:07 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(RD->getLocation());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Get overall information about the record type for the debug info.
|
2010-05-13 07:46:38 +08:00
|
|
|
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
|
|
|
|
unsigned Line = getLineNumber(RD->getLocation());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Records and classes and unions can all be recursive. To handle them, we
|
|
|
|
// first generate a debug descriptor for the struct as a forward declaration.
|
|
|
|
// Then (if it is a definition) we go through and get debug info for all of
|
|
|
|
// its members. Finally, we create a descriptor for the complete type (which
|
|
|
|
// may refer to the forward decl if the struct is recursive) and replace all
|
|
|
|
// uses of the forward declaration with the final definition.
|
2010-07-09 03:56:29 +08:00
|
|
|
llvm::DIDescriptor FDContext =
|
2011-02-23 06:38:33 +08:00
|
|
|
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
|
2010-07-09 03:56:29 +08:00
|
|
|
|
|
|
|
// If this is just a forward declaration, construct an appropriately
|
|
|
|
// marked node and just return it.
|
|
|
|
if (!RD->getDefinition()) {
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::DIType FwdDecl =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createStructType(FDContext, RD->getName(),
|
2010-12-09 06:42:58 +08:00
|
|
|
DefUnit, Line, 0, 0,
|
|
|
|
llvm::DIDescriptor::FlagFwdDecl,
|
|
|
|
llvm::DIArray());
|
2010-07-09 03:56:29 +08:00
|
|
|
|
|
|
|
return FwdDecl;
|
|
|
|
}
|
2010-01-21 07:56:40 +08:00
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-05-08 02:12:35 +08:00
|
|
|
llvm::MDNode *MN = FwdDecl;
|
|
|
|
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
|
2008-11-10 14:08:34 +08:00
|
|
|
// Otherwise, insert it into the TypeCache so that recursive uses will find
|
|
|
|
// it.
|
2010-05-08 02:12:35 +08:00
|
|
|
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
|
2010-03-12 04:01:48 +08:00
|
|
|
// Push the struct on region stack.
|
2010-05-08 02:12:35 +08:00
|
|
|
RegionStack.push_back(FwdDeclNode);
|
|
|
|
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
// Convert all the elements.
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::SmallVector<llvm::Value *, 16> EltTys;
|
2008-11-10 14:08:34 +08:00
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
|
2010-01-29 05:41:35 +08:00
|
|
|
if (CXXDecl) {
|
|
|
|
CollectCXXBases(CXXDecl, Unit, EltTys, FwdDecl);
|
2010-04-18 04:15:18 +08:00
|
|
|
CollectVTableInfo(CXXDecl, Unit, EltTys);
|
2010-01-29 05:41:35 +08:00
|
|
|
}
|
2010-08-12 08:02:44 +08:00
|
|
|
|
|
|
|
// Collect static variables with initializers.
|
|
|
|
for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
|
|
|
|
I != E; ++I)
|
|
|
|
if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {
|
|
|
|
if (const Expr *Init = V->getInit()) {
|
|
|
|
Expr::EvalResult Result;
|
|
|
|
if (Init->Evaluate(Result, CGM.getContext()) && Result.Val.isInt()) {
|
|
|
|
llvm::ConstantInt *CI
|
|
|
|
= llvm::ConstantInt::get(CGM.getLLVMContext(), Result.Val.getInt());
|
|
|
|
|
|
|
|
// Create the descriptor for static variable.
|
|
|
|
llvm::DIFile VUnit = getOrCreateFile(V->getLocation());
|
|
|
|
llvm::StringRef VName = V->getName();
|
|
|
|
llvm::DIType VTy = getOrCreateType(V->getType(), VUnit);
|
|
|
|
// Do not use DIGlobalVariable for enums.
|
|
|
|
if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) {
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createStaticVariable(FwdDecl, VName, VName, VUnit,
|
2010-12-09 06:42:58 +08:00
|
|
|
getLineNumber(V->getLocation()),
|
|
|
|
VTy, true, CI);
|
2010-08-12 08:02:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
CollectRecordFields(RD, Unit, EltTys);
|
2011-04-06 01:30:54 +08:00
|
|
|
llvm::DIArray TParamsArray;
|
2010-01-29 02:11:52 +08:00
|
|
|
if (CXXDecl) {
|
2010-01-19 09:54:44 +08:00
|
|
|
CollectCXXMemberFunctions(CXXDecl, Unit, EltTys, FwdDecl);
|
2010-08-28 01:47:47 +08:00
|
|
|
CollectCXXFriends(CXXDecl, Unit, EltTys, FwdDecl);
|
2011-04-06 01:30:54 +08:00
|
|
|
if (const ClassTemplateSpecializationDecl *TSpecial
|
|
|
|
= dyn_cast<ClassTemplateSpecializationDecl>(RD))
|
|
|
|
TParamsArray = CollectCXXTemplateParams(TSpecial, Unit);
|
2010-12-09 06:42:58 +08:00
|
|
|
}
|
2010-01-28 08:54:21 +08:00
|
|
|
|
2010-12-09 06:42:58 +08:00
|
|
|
RegionStack.pop_back();
|
|
|
|
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI =
|
|
|
|
RegionMap.find(Ty->getDecl());
|
|
|
|
if (RI != RegionMap.end())
|
|
|
|
RegionMap.erase(RI);
|
|
|
|
|
|
|
|
llvm::DIDescriptor RDContext =
|
2011-02-23 06:38:33 +08:00
|
|
|
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::StringRef RDName = RD->getName();
|
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
|
|
|
llvm::DIArray Elements =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::MDNode *RealDecl = NULL;
|
|
|
|
|
2011-03-01 06:32:45 +08:00
|
|
|
if (RD->isUnion())
|
2011-02-23 02:56:36 +08:00
|
|
|
RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line,
|
2011-03-01 06:32:45 +08:00
|
|
|
Size, Align, 0, Elements);
|
|
|
|
else if (CXXDecl) {
|
2010-12-09 06:42:58 +08:00
|
|
|
RDName = getClassName(RD);
|
|
|
|
// A class's primary base or the class itself contains the vtable.
|
|
|
|
llvm::MDNode *ContainingType = NULL;
|
2010-02-02 05:52:22 +08:00
|
|
|
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
|
2010-10-15 06:59:23 +08:00
|
|
|
if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {
|
|
|
|
// Seek non virtual primary base root.
|
|
|
|
while (1) {
|
|
|
|
const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase);
|
|
|
|
const CXXRecordDecl *PBT = BRL.getPrimaryBase();
|
2010-11-25 07:12:57 +08:00
|
|
|
if (PBT && !BRL.isPrimaryBaseVirtual())
|
2010-10-15 06:59:23 +08:00
|
|
|
PBase = PBT;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2010-01-28 08:54:21 +08:00
|
|
|
ContainingType =
|
2010-05-08 02:12:35 +08:00
|
|
|
getOrCreateType(QualType(PBase->getTypeForDecl(), 0), Unit);
|
2010-10-15 06:59:23 +08:00
|
|
|
}
|
2010-01-28 08:54:21 +08:00
|
|
|
else if (CXXDecl->isDynamicClass())
|
2010-05-08 02:12:35 +08:00
|
|
|
ContainingType = FwdDecl;
|
2011-04-06 01:30:54 +08:00
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line,
|
2010-12-09 06:42:58 +08:00
|
|
|
Size, Align, 0, 0, llvm::DIType(),
|
2011-02-03 05:38:49 +08:00
|
|
|
Elements, ContainingType,
|
|
|
|
TParamsArray);
|
2011-03-01 06:32:45 +08:00
|
|
|
} else
|
|
|
|
RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line,
|
|
|
|
Size, Align, 0, Elements);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Now that we have a real decl for the struct, replace anything using the
|
|
|
|
// old decl with the new one. This will recursively update the debug info.
|
2010-08-21 06:02:57 +08:00
|
|
|
llvm::DIType(FwdDeclNode).replaceAllUsesWith(RealDecl);
|
2010-05-08 02:12:35 +08:00
|
|
|
RegionMap[RD] = llvm::WeakVH(RealDecl);
|
2010-12-09 06:42:58 +08:00
|
|
|
return llvm::DIType(RealDecl);
|
2008-06-07 12:46:53 +08:00
|
|
|
}
|
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
/// CreateType - get objective-c object type.
|
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ObjCObjectType *Ty,
|
|
|
|
llvm::DIFile Unit) {
|
|
|
|
// Ignore protocols.
|
|
|
|
return getOrCreateType(Ty->getBaseType(), Unit);
|
|
|
|
}
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
/// CreateType - get objective-c interface type.
|
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2010-02-02 05:52:22 +08:00
|
|
|
ObjCInterfaceDecl *ID = Ty->getDecl();
|
2010-11-30 14:38:09 +08:00
|
|
|
if (!ID)
|
|
|
|
return llvm::DIType();
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
// Get overall information about the record type for the debug info.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation());
|
2010-05-13 07:46:38 +08:00
|
|
|
unsigned Line = getLineNumber(ID->getLocation());
|
2010-03-09 08:44:50 +08:00
|
|
|
unsigned RuntimeLang = TheCU.getLanguage();
|
2009-05-02 09:13:16 +08:00
|
|
|
|
2010-08-24 05:15:56 +08:00
|
|
|
// If this is just a forward declaration, return a special forward-declaration
|
|
|
|
// debug type.
|
|
|
|
if (ID->isForwardDecl()) {
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::DIType FwdDecl =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createStructType(Unit, ID->getName(),
|
2010-12-09 06:42:58 +08:00
|
|
|
DefUnit, Line, 0, 0, 0,
|
|
|
|
llvm::DIArray(), RuntimeLang);
|
2010-08-24 05:15:56 +08:00
|
|
|
return FwdDecl;
|
|
|
|
}
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// To handle recursive interface, we
|
|
|
|
// first generate a debug descriptor for the struct as a forward declaration.
|
|
|
|
// Then (if it is a definition) we go through and get debug info for all of
|
|
|
|
// its members. Finally, we create a descriptor for the complete type (which
|
|
|
|
// may refer to the forward decl if the struct is recursive) and replace all
|
|
|
|
// uses of the forward declaration with the final definition.
|
2011-02-23 02:56:36 +08:00
|
|
|
llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-05-08 02:12:35 +08:00
|
|
|
llvm::MDNode *MN = FwdDecl;
|
|
|
|
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
|
2009-02-27 05:10:26 +08:00
|
|
|
// Otherwise, insert it into the TypeCache so that recursive uses will find
|
|
|
|
// it.
|
2010-05-08 02:12:35 +08:00
|
|
|
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
|
2010-03-12 04:01:48 +08:00
|
|
|
// Push the struct on region stack.
|
2010-05-08 02:12:35 +08:00
|
|
|
RegionStack.push_back(FwdDeclNode);
|
|
|
|
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
// Convert all the elements.
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::SmallVector<llvm::Value *, 16> EltTys;
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
ObjCInterfaceDecl *SClass = ID->getSuperClass();
|
2009-03-11 05:30:26 +08:00
|
|
|
if (SClass) {
|
2009-09-09 23:08:12 +08:00
|
|
|
llvm::DIType SClassTy =
|
2009-12-07 02:00:51 +08:00
|
|
|
getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit);
|
2010-11-30 14:38:09 +08:00
|
|
|
if (!SClassTy.isValid())
|
|
|
|
return llvm::DIType();
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
llvm::DIType InhTag =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createInheritance(FwdDecl, SClassTy, 0, 0);
|
2009-03-11 05:30:26 +08:00
|
|
|
EltTys.push_back(InhTag);
|
|
|
|
}
|
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID);
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
unsigned FieldNo = 0;
|
2010-10-01 08:01:53 +08:00
|
|
|
for (ObjCIvarDecl *Field = ID->all_declared_ivar_begin(); Field;
|
2010-10-12 07:55:47 +08:00
|
|
|
Field = Field->getNextIvar(), ++FieldNo) {
|
2009-02-27 05:10:26 +08:00
|
|
|
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
|
2010-11-30 14:38:09 +08:00
|
|
|
if (!FieldTy.isValid())
|
|
|
|
return llvm::DIType();
|
|
|
|
|
2009-11-26 01:37:31 +08:00
|
|
|
llvm::StringRef FieldName = Field->getName();
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2009-04-28 06:40:36 +08:00
|
|
|
// Ignore unnamed fields.
|
2009-11-26 01:37:31 +08:00
|
|
|
if (FieldName.empty())
|
2009-04-28 06:40:36 +08:00
|
|
|
continue;
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// Get the location for the field.
|
2010-05-13 07:46:38 +08:00
|
|
|
llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation());
|
|
|
|
unsigned FieldLine = getLineNumber(Field->getLocation());
|
2009-03-21 02:24:39 +08:00
|
|
|
QualType FType = Field->getType();
|
|
|
|
uint64_t FieldSize = 0;
|
|
|
|
unsigned FieldAlign = 0;
|
|
|
|
|
|
|
|
if (!FType->isIncompleteArrayType()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-21 02:24:39 +08:00
|
|
|
// Bit size, align and offset of the type.
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
2009-03-21 02:24:39 +08:00
|
|
|
Expr *BitWidth = Field->getBitWidth();
|
|
|
|
if (BitWidth)
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
|
2009-04-27 03:19:15 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2009-03-21 02:24:39 +08:00
|
|
|
}
|
2009-03-19 08:23:53 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
uint64_t FieldOffset = RL.getFieldOffset(FieldNo);
|
|
|
|
|
2009-03-19 08:23:53 +08:00
|
|
|
unsigned Flags = 0;
|
|
|
|
if (Field->getAccessControl() == ObjCIvarDecl::Protected)
|
2010-09-30 05:05:52 +08:00
|
|
|
Flags = llvm::DIDescriptor::FlagProtected;
|
2009-03-19 08:23:53 +08:00
|
|
|
else if (Field->getAccessControl() == ObjCIvarDecl::Private)
|
2010-09-30 05:05:52 +08:00
|
|
|
Flags = llvm::DIDescriptor::FlagPrivate;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
FieldTy = DBuilder.createMemberType(FieldName, FieldDefUnit,
|
2010-12-09 06:42:58 +08:00
|
|
|
FieldLine, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, Flags, FieldTy);
|
2009-02-27 05:10:26 +08:00
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
llvm::DIArray Elements =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2010-03-12 04:01:48 +08:00
|
|
|
RegionStack.pop_back();
|
|
|
|
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI =
|
|
|
|
RegionMap.find(Ty->getDecl());
|
|
|
|
if (RI != RegionMap.end())
|
|
|
|
RegionMap.erase(RI);
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// Bit size, align and offset of the type.
|
2009-12-07 02:00:51 +08:00
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::DIType RealDecl =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createStructType(Unit, ID->getName(), DefUnit,
|
2010-12-09 06:42:58 +08:00
|
|
|
Line, Size, Align, 0,
|
|
|
|
Elements, RuntimeLang);
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
// Now that we have a real decl for the struct, replace anything using the
|
|
|
|
// old decl with the new one. This will recursively update the debug info.
|
2010-08-21 06:02:57 +08:00
|
|
|
llvm::DIType(FwdDeclNode).replaceAllUsesWith(RealDecl);
|
2010-05-08 02:12:35 +08:00
|
|
|
RegionMap[ID] = llvm::WeakVH(RealDecl);
|
2009-07-14 01:03:14 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
return RealDecl;
|
|
|
|
}
|
|
|
|
|
2011-01-18 06:23:07 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const TagType *Ty) {
|
2008-11-10 14:08:34 +08:00
|
|
|
if (const RecordType *RT = dyn_cast<RecordType>(Ty))
|
2011-01-18 06:23:07 +08:00
|
|
|
return CreateType(RT);
|
2008-11-10 14:08:34 +08:00
|
|
|
else if (const EnumType *ET = dyn_cast<EnumType>(Ty))
|
2011-01-18 06:23:07 +08:00
|
|
|
return CreateEnumType(ET->getDecl());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
return llvm::DIType();
|
|
|
|
}
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2010-02-24 06:59:39 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty,
|
2010-08-22 09:00:03 +08:00
|
|
|
llvm::DIFile Unit) {
|
2010-02-24 06:59:39 +08:00
|
|
|
llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit);
|
2011-04-09 05:56:52 +08:00
|
|
|
int64_t NumElems = Ty->getNumElements();
|
|
|
|
int64_t LowerBound = 0;
|
|
|
|
if (NumElems == 0)
|
|
|
|
// If number of elements are not known then this is an unbounded array.
|
|
|
|
// Use Low = 1, Hi = 0 to express such arrays.
|
|
|
|
LowerBound = 1;
|
|
|
|
else
|
2010-02-24 06:59:39 +08:00
|
|
|
--NumElems;
|
|
|
|
|
2011-04-09 05:56:52 +08:00
|
|
|
llvm::Value *Subscript = DBuilder.getOrCreateSubrange(LowerBound, NumElems);
|
2011-02-23 02:56:36 +08:00
|
|
|
llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(&Subscript, 1);
|
2010-02-24 06:59:39 +08:00
|
|
|
|
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
|
|
|
|
|
|
|
return
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);
|
2010-02-24 06:59:39 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-01-05 09:23:29 +08:00
|
|
|
uint64_t Size;
|
|
|
|
uint64_t Align;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
2009-01-28 08:35:17 +08:00
|
|
|
// FIXME: make getTypeAlign() aware of VLAs and incomplete array types
|
2009-01-05 09:23:29 +08:00
|
|
|
if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(Ty)) {
|
|
|
|
Size = 0;
|
|
|
|
Align =
|
2009-12-07 02:00:51 +08:00
|
|
|
CGM.getContext().getTypeAlign(CGM.getContext().getBaseElementType(VAT));
|
2009-01-28 08:35:17 +08:00
|
|
|
} else if (Ty->isIncompleteArrayType()) {
|
|
|
|
Size = 0;
|
2009-12-07 02:00:51 +08:00
|
|
|
Align = CGM.getContext().getTypeAlign(Ty->getElementType());
|
2011-04-05 07:18:38 +08:00
|
|
|
} else if (Ty->isDependentSizedArrayType() || Ty->isIncompleteType()) {
|
2011-04-02 03:02:33 +08:00
|
|
|
Size = 0;
|
|
|
|
Align = 0;
|
2009-01-05 09:23:29 +08:00
|
|
|
} else {
|
|
|
|
// Size and align of the whole array, not the element type.
|
2009-12-07 02:00:51 +08:00
|
|
|
Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
Align = CGM.getContext().getTypeAlign(Ty);
|
2009-01-05 09:23:29 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Add the dimensions of the array. FIXME: This loses CV qualifiers from
|
|
|
|
// interior arrays, do we care? Why aren't nested arrays represented the
|
|
|
|
// obvious/recursive way?
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::SmallVector<llvm::Value *, 8> Subscripts;
|
2008-11-10 14:08:34 +08:00
|
|
|
QualType EltTy(Ty, 0);
|
2010-10-07 02:30:00 +08:00
|
|
|
if (Ty->isIncompleteArrayType())
|
2008-11-10 14:08:34 +08:00
|
|
|
EltTy = Ty->getElementType();
|
2010-10-07 02:30:00 +08:00
|
|
|
else {
|
|
|
|
while ((Ty = dyn_cast<ArrayType>(EltTy))) {
|
2011-04-09 05:56:52 +08:00
|
|
|
int64_t UpperBound = 0;
|
|
|
|
int64_t LowerBound = 0;
|
2011-04-09 08:25:15 +08:00
|
|
|
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty)) {
|
2010-10-07 02:30:00 +08:00
|
|
|
if (CAT->getSize().getZExtValue())
|
2011-04-09 05:56:52 +08:00
|
|
|
UpperBound = CAT->getSize().getZExtValue() - 1;
|
2011-04-09 08:25:15 +08:00
|
|
|
} else
|
2011-04-09 05:56:52 +08:00
|
|
|
// This is an unbounded array. Use Low = 1, Hi = 0 to express such
|
|
|
|
// arrays.
|
|
|
|
LowerBound = 1;
|
|
|
|
|
2010-10-07 02:30:00 +08:00
|
|
|
// FIXME: Verify this is right for VLAs.
|
2011-04-09 05:56:52 +08:00
|
|
|
Subscripts.push_back(DBuilder.getOrCreateSubrange(LowerBound, UpperBound));
|
2010-10-07 02:30:00 +08:00
|
|
|
EltTy = Ty->getElementType();
|
|
|
|
}
|
2008-06-09 18:47:41 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIArray SubscriptArray =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.getOrCreateArray(Subscripts.data(), Subscripts.size());
|
2008-11-10 14:08:34 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit),
|
2010-12-09 06:42:58 +08:00
|
|
|
SubscriptArray);
|
2009-10-21 03:55:01 +08:00
|
|
|
return DbgTy;
|
2008-06-09 18:47:41 +08:00
|
|
|
}
|
|
|
|
|
2009-11-07 03:19:55 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-11-07 03:19:55 +08:00
|
|
|
return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type,
|
|
|
|
Ty, Ty->getPointeeType(), Unit);
|
|
|
|
}
|
2008-06-07 12:46:53 +08:00
|
|
|
|
2011-01-22 09:58:15 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const RValueReferenceType *Ty,
|
|
|
|
llvm::DIFile Unit) {
|
|
|
|
return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type,
|
|
|
|
Ty, Ty->getPointeeType(), Unit);
|
|
|
|
}
|
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile U) {
|
2009-12-07 02:00:51 +08:00
|
|
|
QualType PointerDiffTy = CGM.getContext().getPointerDiffType();
|
|
|
|
llvm::DIType PointerDiffDITy = getOrCreateType(PointerDiffTy, U);
|
|
|
|
|
|
|
|
if (!Ty->getPointeeType()->isFunctionType()) {
|
|
|
|
// We have a data member pointer type.
|
|
|
|
return PointerDiffDITy;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We have a member function pointer type. Treat it as a struct with two
|
|
|
|
// ptrdiff_t members.
|
|
|
|
std::pair<uint64_t, unsigned> Info = CGM.getContext().getTypeInfo(Ty);
|
|
|
|
|
|
|
|
uint64_t FieldOffset = 0;
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::Value *ElementTypes[2];
|
2009-12-07 02:00:51 +08:00
|
|
|
|
|
|
|
// FIXME: This should probably be a function type instead.
|
|
|
|
ElementTypes[0] =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createMemberType("ptr", U, 0,
|
2010-12-09 06:42:58 +08:00
|
|
|
Info.first, Info.second, FieldOffset, 0,
|
|
|
|
PointerDiffDITy);
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldOffset += Info.first;
|
|
|
|
|
|
|
|
ElementTypes[1] =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createMemberType("ptr", U, 0,
|
2010-12-09 06:42:58 +08:00
|
|
|
Info.first, Info.second, FieldOffset, 0,
|
|
|
|
PointerDiffDITy);
|
2009-12-07 02:00:51 +08:00
|
|
|
|
|
|
|
llvm::DIArray Elements =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.getOrCreateArray(&ElementTypes[0],
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::array_lengthof(ElementTypes));
|
2009-12-07 02:00:51 +08:00
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
return DBuilder.createStructType(U, llvm::StringRef("test"),
|
2010-12-09 06:42:58 +08:00
|
|
|
U, 0, FieldOffset,
|
|
|
|
0, 0, Elements);
|
2009-12-07 02:00:51 +08:00
|
|
|
}
|
|
|
|
|
2010-08-24 06:07:25 +08:00
|
|
|
/// CreateEnumType - get enumeration type.
|
2011-01-18 06:23:07 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
|
|
|
|
llvm::DIFile Unit = getOrCreateFile(ED->getLocation());
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::SmallVector<llvm::Value *, 16> Enumerators;
|
2010-08-24 06:07:25 +08:00
|
|
|
|
|
|
|
// Create DIEnumerator elements for each enumerator.
|
|
|
|
for (EnumDecl::enumerator_iterator
|
|
|
|
Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end();
|
|
|
|
Enum != EnumEnd; ++Enum) {
|
2010-12-09 06:42:58 +08:00
|
|
|
Enumerators.push_back(
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createEnumerator(Enum->getName(),
|
2010-12-09 06:42:58 +08:00
|
|
|
Enum->getInitVal().getZExtValue()));
|
2010-08-24 06:07:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return a CompositeType for the enum itself.
|
|
|
|
llvm::DIArray EltArray =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.getOrCreateArray(Enumerators.data(), Enumerators.size());
|
2010-08-24 06:07:25 +08:00
|
|
|
|
|
|
|
llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
|
|
|
|
unsigned Line = getLineNumber(ED->getLocation());
|
|
|
|
uint64_t Size = 0;
|
2010-08-25 02:14:06 +08:00
|
|
|
uint64_t Align = 0;
|
|
|
|
if (!ED->getTypeForDecl()->isIncompleteType()) {
|
|
|
|
Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
|
|
|
|
Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
|
|
|
|
}
|
2010-10-28 07:23:58 +08:00
|
|
|
llvm::DIDescriptor EnumContext =
|
2011-02-23 06:38:33 +08:00
|
|
|
getContextDescriptor(cast<Decl>(ED->getDeclContext()));
|
2010-08-24 06:07:25 +08:00
|
|
|
llvm::DIType DbgTy =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line,
|
2010-12-09 06:42:58 +08:00
|
|
|
Size, Align, EltArray);
|
2010-08-24 06:07:25 +08:00
|
|
|
return DbgTy;
|
|
|
|
}
|
|
|
|
|
2009-12-22 04:18:30 +08:00
|
|
|
static QualType UnwrapTypeForDebugInfo(QualType T) {
|
|
|
|
do {
|
|
|
|
QualType LastT = T;
|
|
|
|
switch (T->getTypeClass()) {
|
|
|
|
default:
|
|
|
|
return T;
|
|
|
|
case Type::TemplateSpecialization:
|
|
|
|
T = cast<TemplateSpecializationType>(T)->desugar();
|
|
|
|
break;
|
2011-01-19 14:33:43 +08:00
|
|
|
case Type::TypeOfExpr:
|
|
|
|
T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType();
|
2009-12-22 04:18:30 +08:00
|
|
|
break;
|
|
|
|
case Type::TypeOf:
|
|
|
|
T = cast<TypeOfType>(T)->getUnderlyingType();
|
|
|
|
break;
|
|
|
|
case Type::Decltype:
|
|
|
|
T = cast<DecltypeType>(T)->getUnderlyingType();
|
|
|
|
break;
|
2011-01-06 09:58:22 +08:00
|
|
|
case Type::Attributed:
|
|
|
|
T = cast<AttributedType>(T)->getEquivalentType();
|
2011-03-04 12:00:19 +08:00
|
|
|
break;
|
2010-05-12 05:36:43 +08:00
|
|
|
case Type::Elaborated:
|
|
|
|
T = cast<ElaboratedType>(T)->getNamedType();
|
2009-12-22 04:18:30 +08:00
|
|
|
break;
|
2010-12-11 00:29:40 +08:00
|
|
|
case Type::Paren:
|
|
|
|
T = cast<ParenType>(T)->getInnerType();
|
|
|
|
break;
|
2009-12-22 04:18:30 +08:00
|
|
|
case Type::SubstTemplateTypeParm:
|
|
|
|
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
|
|
|
|
break;
|
2011-03-07 00:43:04 +08:00
|
|
|
case Type::Auto:
|
|
|
|
T = cast<AutoType>(T)->getDeducedType();
|
|
|
|
break;
|
2009-12-22 04:18:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
assert(T != LastT && "Type unwrapping failed to unwrap!");
|
|
|
|
if (T == LastT)
|
|
|
|
return T;
|
|
|
|
} while (true);
|
|
|
|
|
|
|
|
return T;
|
2009-11-15 05:08:12 +08:00
|
|
|
}
|
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
/// getOrCreateType - Get the type from the cache or create a new
|
|
|
|
/// one if necessary.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2008-11-10 14:08:34 +08:00
|
|
|
if (Ty.isNull())
|
|
|
|
return llvm::DIType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-22 04:18:30 +08:00
|
|
|
// Unwrap the type as needed for debug information.
|
|
|
|
Ty = UnwrapTypeForDebugInfo(Ty);
|
2011-03-24 00:29:39 +08:00
|
|
|
|
2009-09-20 03:27:24 +08:00
|
|
|
// Check for existing entry.
|
2010-03-30 02:29:57 +08:00
|
|
|
llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
|
2009-09-20 03:27:24 +08:00
|
|
|
TypeCache.find(Ty.getAsOpaquePtr());
|
2009-09-20 04:17:48 +08:00
|
|
|
if (it != TypeCache.end()) {
|
|
|
|
// Verify that the debug info still exists.
|
|
|
|
if (&*it->second)
|
|
|
|
return llvm::DIType(cast<llvm::MDNode>(it->second));
|
|
|
|
}
|
2009-09-20 03:27:14 +08:00
|
|
|
|
2009-09-20 03:27:24 +08:00
|
|
|
// Otherwise create the type.
|
|
|
|
llvm::DIType Res = CreateTypeNode(Ty, Unit);
|
2009-11-15 04:52:05 +08:00
|
|
|
|
|
|
|
// And update the type cache.
|
2010-05-08 02:12:35 +08:00
|
|
|
TypeCache[Ty.getAsOpaquePtr()] = Res;
|
2009-09-20 03:27:24 +08:00
|
|
|
return Res;
|
2009-09-20 03:27:14 +08:00
|
|
|
}
|
|
|
|
|
2009-11-15 04:52:05 +08:00
|
|
|
/// CreateTypeNode - Create a new debug type node.
|
2009-09-20 03:27:14 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-09-25 09:40:47 +08:00
|
|
|
// Handle qualifiers, which recursively handles what they refer to.
|
First part of changes to eliminate problems with cv-qualifiers and
sugared types. The basic problem is that our qualifier accessors
(getQualifiers, getCVRQualifiers, isConstQualified, etc.) only look at
the current QualType and not at any qualifiers that come from sugared
types, meaning that we won't see these qualifiers through, e.g.,
typedefs:
typedef const int CInt;
typedef CInt Self;
Self.isConstQualified() currently returns false!
Various bugs (e.g., PR5383) have cropped up all over the front end due
to such problems. I'm addressing this problem by splitting each
qualifier accessor into two versions:
- the "local" version only returns qualifiers on this particular
QualType instance
- the "normal" version that will eventually combine qualifiers from this
QualType instance with the qualifiers on the canonical type to
produce the full set of qualifiers.
This commit adds the local versions and switches a few callers from
the "normal" version (e.g., isConstQualified) over to the "local"
version (e.g., isLocalConstQualified) when that is the right thing to
do, e.g., because we're printing or serializing the qualifiers. Also,
switch a bunch of
Context.getCanonicalType(T1).getUnqualifiedType() == Context.getCanonicalType(T2).getQualifiedType()
expressions over to
Context.hasSameUnqualifiedType(T1, T2)
llvm-svn: 88969
2009-11-17 05:35:15 +08:00
|
|
|
if (Ty.hasLocalQualifiers())
|
2009-09-25 09:40:47 +08:00
|
|
|
return CreateQualifiedType(Ty, Unit);
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2009-12-22 03:57:21 +08:00
|
|
|
const char *Diag = 0;
|
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
// Work out details of type.
|
2008-11-10 14:08:34 +08:00
|
|
|
switch (Ty->getTypeClass()) {
|
2009-02-27 07:50:07 +08:00
|
|
|
#define TYPE(Class, Base)
|
|
|
|
#define ABSTRACT_TYPE(Class, Base)
|
|
|
|
#define NON_CANONICAL_TYPE(Class, Base)
|
|
|
|
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
assert(false && "Dependent types cannot show up in debug information");
|
2009-08-19 09:28:17 +08:00
|
|
|
|
2009-11-07 02:24:04 +08:00
|
|
|
// FIXME: Handle these.
|
|
|
|
case Type::ExtVector:
|
|
|
|
return llvm::DIType();
|
2010-02-24 06:59:39 +08:00
|
|
|
|
|
|
|
case Type::Vector:
|
|
|
|
return CreateType(cast<VectorType>(Ty), Unit);
|
2009-07-14 09:20:56 +08:00
|
|
|
case Type::ObjCObjectPointer:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<ObjCObjectPointerType>(Ty), Unit);
|
2010-05-15 19:32:37 +08:00
|
|
|
case Type::ObjCObject:
|
|
|
|
return CreateType(cast<ObjCObjectType>(Ty), Unit);
|
2009-09-09 23:08:12 +08:00
|
|
|
case Type::ObjCInterface:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<ObjCInterfaceType>(Ty), Unit);
|
2010-11-02 00:52:40 +08:00
|
|
|
case Type::Builtin: return CreateType(cast<BuiltinType>(Ty));
|
2010-12-09 08:25:29 +08:00
|
|
|
case Type::Complex: return CreateType(cast<ComplexType>(Ty));
|
2009-09-20 03:27:14 +08:00
|
|
|
case Type::Pointer: return CreateType(cast<PointerType>(Ty), Unit);
|
2009-05-14 10:03:51 +08:00
|
|
|
case Type::BlockPointer:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<BlockPointerType>(Ty), Unit);
|
|
|
|
case Type::Typedef: return CreateType(cast<TypedefType>(Ty), Unit);
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::Record:
|
|
|
|
case Type::Enum:
|
2011-01-18 06:23:07 +08:00
|
|
|
return CreateType(cast<TagType>(Ty));
|
2008-11-10 14:08:34 +08:00
|
|
|
case Type::FunctionProto:
|
|
|
|
case Type::FunctionNoProto:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<FunctionType>(Ty), Unit);
|
2008-11-10 14:08:34 +08:00
|
|
|
case Type::ConstantArray:
|
|
|
|
case Type::VariableArray:
|
|
|
|
case Type::IncompleteArray:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<ArrayType>(Ty), Unit);
|
2009-11-07 03:19:55 +08:00
|
|
|
|
|
|
|
case Type::LValueReference:
|
|
|
|
return CreateType(cast<LValueReferenceType>(Ty), Unit);
|
2011-01-22 09:58:15 +08:00
|
|
|
case Type::RValueReference:
|
|
|
|
return CreateType(cast<RValueReferenceType>(Ty), Unit);
|
2009-11-07 03:19:55 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
case Type::MemberPointer:
|
|
|
|
return CreateType(cast<MemberPointerType>(Ty), Unit);
|
2009-12-22 03:57:21 +08:00
|
|
|
|
2011-01-06 09:58:22 +08:00
|
|
|
case Type::Attributed:
|
2009-12-22 03:57:21 +08:00
|
|
|
case Type::TemplateSpecialization:
|
|
|
|
case Type::Elaborated:
|
2010-12-11 00:29:40 +08:00
|
|
|
case Type::Paren:
|
2009-12-22 03:57:21 +08:00
|
|
|
case Type::SubstTemplateTypeParm:
|
|
|
|
case Type::TypeOfExpr:
|
|
|
|
case Type::TypeOf:
|
2009-12-22 04:18:30 +08:00
|
|
|
case Type::Decltype:
|
2011-02-20 11:19:35 +08:00
|
|
|
case Type::Auto:
|
2009-12-22 04:18:30 +08:00
|
|
|
llvm_unreachable("type should have been unwrapped!");
|
2011-01-22 09:58:15 +08:00
|
|
|
return llvm::DIType();
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
2009-12-22 03:57:21 +08:00
|
|
|
|
|
|
|
assert(Diag && "Fall through without a diagnostic?");
|
|
|
|
unsigned DiagID = CGM.getDiags().getCustomDiagID(Diagnostic::Error,
|
|
|
|
"debug information for %0 is not yet supported");
|
2010-11-19 04:06:41 +08:00
|
|
|
CGM.getDiags().Report(DiagID)
|
2009-12-22 03:57:21 +08:00
|
|
|
<< Diag;
|
|
|
|
return llvm::DIType();
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2010-04-25 04:19:58 +08:00
|
|
|
/// CreateMemberType - Create new member and increase Offset by FType's size.
|
|
|
|
llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
|
|
|
|
llvm::StringRef Name,
|
|
|
|
uint64_t *Offset) {
|
|
|
|
llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2011-02-23 02:56:36 +08:00
|
|
|
llvm::DIType Ty = DBuilder.createMemberType(Name, Unit, 0,
|
2010-12-09 06:42:58 +08:00
|
|
|
FieldSize, FieldAlign,
|
|
|
|
*Offset, 0, FieldTy);
|
2010-04-25 04:19:58 +08:00
|
|
|
*Offset += FieldSize;
|
|
|
|
return Ty;
|
|
|
|
}
|
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
/// EmitFunctionStart - Constructs the debug code for entering a function -
|
|
|
|
/// "llvm.dbg.func.start.".
|
2010-01-14 08:36:21 +08:00
|
|
|
void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
|
2008-05-25 13:15:42 +08:00
|
|
|
llvm::Function *Fn,
|
2008-11-10 14:08:34 +08:00
|
|
|
CGBuilderTy &Builder) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-14 08:36:21 +08:00
|
|
|
llvm::StringRef Name;
|
2010-06-23 00:16:50 +08:00
|
|
|
llvm::StringRef LinkageName;
|
2010-01-14 08:36:21 +08:00
|
|
|
|
2010-07-23 06:29:16 +08:00
|
|
|
FnBeginRegionCount.push_back(RegionStack.size());
|
|
|
|
|
2010-01-14 08:36:21 +08:00
|
|
|
const Decl *D = GD.getDecl();
|
2011-04-06 04:28:21 +08:00
|
|
|
|
2010-10-08 06:03:49 +08:00
|
|
|
unsigned Flags = 0;
|
2010-10-12 05:58:41 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(CurLoc);
|
|
|
|
llvm::DIDescriptor FDContext(Unit);
|
2011-04-06 06:54:11 +08:00
|
|
|
llvm::DIArray TParamsArray;
|
2010-01-14 08:36:21 +08:00
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
2010-01-19 09:54:44 +08:00
|
|
|
// If there is a DISubprogram for this function available then use it.
|
|
|
|
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
|
|
|
|
FI = SPCache.find(FD);
|
|
|
|
if (FI != SPCache.end()) {
|
2010-09-18 21:00:17 +08:00
|
|
|
llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(&*FI->second));
|
2010-05-08 02:12:35 +08:00
|
|
|
if (SP.isSubprogram() && llvm::DISubprogram(SP).isDefinition()) {
|
|
|
|
llvm::MDNode *SPN = SP;
|
|
|
|
RegionStack.push_back(SPN);
|
|
|
|
RegionMap[D] = llvm::WeakVH(SP);
|
2010-01-19 09:54:44 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-01-14 08:36:21 +08:00
|
|
|
Name = getFunctionName(FD);
|
|
|
|
// Use mangled name as linkage name for c/c++ functions.
|
2010-06-23 00:16:50 +08:00
|
|
|
LinkageName = CGM.getMangledName(GD);
|
2010-10-23 01:11:50 +08:00
|
|
|
if (LinkageName == Name)
|
|
|
|
LinkageName = llvm::StringRef();
|
2010-10-08 06:03:49 +08:00
|
|
|
if (FD->hasPrototype())
|
|
|
|
Flags |= llvm::DIDescriptor::FlagPrototyped;
|
2010-10-12 05:58:41 +08:00
|
|
|
if (const NamespaceDecl *NSDecl =
|
|
|
|
dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
|
2010-12-09 08:33:05 +08:00
|
|
|
FDContext = getOrCreateNameSpace(NSDecl);
|
2011-04-06 06:54:11 +08:00
|
|
|
|
|
|
|
// Collect template parameters.
|
|
|
|
TParamsArray = CollectFunctionTemplateParams(FD, Unit);
|
2010-09-03 01:16:32 +08:00
|
|
|
} else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
|
2010-09-03 02:01:51 +08:00
|
|
|
Name = getObjCMethodName(OMD);
|
2010-10-08 06:03:49 +08:00
|
|
|
Flags |= llvm::DIDescriptor::FlagPrototyped;
|
2010-01-14 08:36:21 +08:00
|
|
|
} else {
|
2010-10-23 01:11:50 +08:00
|
|
|
// Use llvm function name.
|
2010-01-14 08:36:21 +08:00
|
|
|
Name = Fn->getName();
|
2010-10-08 06:03:49 +08:00
|
|
|
Flags |= llvm::DIDescriptor::FlagPrototyped;
|
2010-01-14 08:36:21 +08:00
|
|
|
}
|
2010-04-25 04:19:58 +08:00
|
|
|
if (!Name.empty() && Name[0] == '\01')
|
|
|
|
Name = Name.substr(1);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-04-24 08:49:16 +08:00
|
|
|
// It is expected that CurLoc is set before using EmitFunctionStart.
|
|
|
|
// Usually, CurLoc points to the left bracket location of compound
|
|
|
|
// statement representing function body.
|
2010-05-13 07:46:38 +08:00
|
|
|
unsigned LineNo = getLineNumber(CurLoc);
|
2010-09-30 05:05:52 +08:00
|
|
|
if (D->isImplicit())
|
|
|
|
Flags |= llvm::DIDescriptor::FlagArtificial;
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DISubprogram SP =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createFunction(FDContext, Name, LinkageName, Unit,
|
2010-12-09 06:42:58 +08:00
|
|
|
LineNo, getOrCreateType(FnType, Unit),
|
|
|
|
Fn->hasInternalLinkage(), true/*definition*/,
|
2011-04-06 06:54:11 +08:00
|
|
|
Flags, CGM.getLangOptions().Optimize, Fn,
|
|
|
|
TParamsArray);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
// Push function on region stack.
|
2010-05-08 02:12:35 +08:00
|
|
|
llvm::MDNode *SPN = SP;
|
|
|
|
RegionStack.push_back(SPN);
|
|
|
|
RegionMap[D] = llvm::WeakVH(SP);
|
2010-07-23 06:29:16 +08:00
|
|
|
|
|
|
|
// Clear stack used to keep track of #line directives.
|
|
|
|
LineDirectiveFiles.clear();
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-07-21 06:20:10 +08:00
|
|
|
void CGDebugInfo::EmitStopPoint(CGBuilderTy &Builder) {
|
2008-05-22 09:40:10 +08:00
|
|
|
if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-08 16:54:20 +08:00
|
|
|
// Don't bother if things are the same as last time.
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2009-09-09 23:08:12 +08:00
|
|
|
if (CurLoc == PrevLoc
|
2009-02-04 09:06:56 +08:00
|
|
|
|| (SM.getInstantiationLineNumber(CurLoc) ==
|
|
|
|
SM.getInstantiationLineNumber(PrevLoc)
|
2008-05-08 16:54:20 +08:00
|
|
|
&& SM.isFromSameFile(CurLoc, PrevLoc)))
|
2010-04-06 05:09:15 +08:00
|
|
|
// New Builder may not be in sync with CGDebugInfo.
|
|
|
|
if (!Builder.getCurrentDebugLocation().isUnknown())
|
|
|
|
return;
|
2008-05-08 16:54:20 +08:00
|
|
|
|
|
|
|
// Update last state.
|
|
|
|
PrevLoc = CurLoc;
|
|
|
|
|
2010-04-01 14:31:43 +08:00
|
|
|
llvm::MDNode *Scope = RegionStack.back();
|
2010-05-13 07:46:38 +08:00
|
|
|
Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(CurLoc),
|
|
|
|
getColumnNumber(CurLoc),
|
2010-04-03 04:21:43 +08:00
|
|
|
Scope));
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2010-07-23 06:29:16 +08:00
|
|
|
/// UpdateLineDirectiveRegion - Update region stack only if #line directive
|
|
|
|
/// has introduced scope change.
|
|
|
|
void CGDebugInfo::UpdateLineDirectiveRegion(CGBuilderTy &Builder) {
|
|
|
|
if (CurLoc.isInvalid() || CurLoc.isMacroID() ||
|
|
|
|
PrevLoc.isInvalid() || PrevLoc.isMacroID())
|
|
|
|
return;
|
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
|
|
|
PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc);
|
|
|
|
PresumedLoc PPLoc = SM.getPresumedLoc(PrevLoc);
|
|
|
|
|
2010-11-12 04:45:16 +08:00
|
|
|
if (PCLoc.isInvalid() || PPLoc.isInvalid() ||
|
|
|
|
!strcmp(PPLoc.getFilename(), PCLoc.getFilename()))
|
2010-07-23 06:29:16 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
// If #line directive stack is empty then we are entering a new scope.
|
|
|
|
if (LineDirectiveFiles.empty()) {
|
|
|
|
EmitRegionStart(Builder);
|
|
|
|
LineDirectiveFiles.push_back(PCLoc.getFilename());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert (RegionStack.size() >= LineDirectiveFiles.size()
|
|
|
|
&& "error handling #line regions!");
|
|
|
|
|
|
|
|
bool SeenThisFile = false;
|
2010-09-16 04:50:40 +08:00
|
|
|
// Chek if current file is already seen earlier.
|
2010-07-23 06:29:16 +08:00
|
|
|
for(std::vector<const char *>::iterator I = LineDirectiveFiles.begin(),
|
|
|
|
E = LineDirectiveFiles.end(); I != E; ++I)
|
2010-09-16 04:50:40 +08:00
|
|
|
if (!strcmp(PCLoc.getFilename(), *I)) {
|
2010-07-23 06:29:16 +08:00
|
|
|
SeenThisFile = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If #line for this file is seen earlier then pop out #line regions.
|
|
|
|
if (SeenThisFile) {
|
|
|
|
while (!LineDirectiveFiles.empty()) {
|
|
|
|
const char *LastFile = LineDirectiveFiles.back();
|
|
|
|
RegionStack.pop_back();
|
|
|
|
LineDirectiveFiles.pop_back();
|
|
|
|
if (!strcmp(PPLoc.getFilename(), LastFile))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// .. otherwise insert new #line region.
|
|
|
|
EmitRegionStart(Builder);
|
|
|
|
LineDirectiveFiles.push_back(PCLoc.getFilename());
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2008-05-08 16:54:20 +08:00
|
|
|
/// EmitRegionStart- Constructs the debug code for entering a declarative
|
|
|
|
/// region - "llvm.dbg.region.start.".
|
2010-07-21 06:20:10 +08:00
|
|
|
void CGDebugInfo::EmitRegionStart(CGBuilderTy &Builder) {
|
2009-11-14 03:10:24 +08:00
|
|
|
llvm::DIDescriptor D =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createLexicalBlock(RegionStack.empty() ?
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::DIDescriptor() :
|
|
|
|
llvm::DIDescriptor(RegionStack.back()),
|
|
|
|
getOrCreateFile(CurLoc),
|
|
|
|
getLineNumber(CurLoc),
|
|
|
|
getColumnNumber(CurLoc));
|
2010-05-08 02:12:35 +08:00
|
|
|
llvm::MDNode *DN = D;
|
|
|
|
RegionStack.push_back(DN);
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitRegionEnd - Constructs the debug code for exiting a declarative
|
|
|
|
/// region - "llvm.dbg.region.end."
|
2010-07-21 06:20:10 +08:00
|
|
|
void CGDebugInfo::EmitRegionEnd(CGBuilderTy &Builder) {
|
2008-10-17 09:07:56 +08:00
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
|
2008-05-08 16:54:20 +08:00
|
|
|
// Provide an region stop point.
|
2010-07-21 06:20:10 +08:00
|
|
|
EmitStopPoint(Builder);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
RegionStack.pop_back();
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2010-07-23 06:29:16 +08:00
|
|
|
/// EmitFunctionEnd - Constructs the debug code for exiting a function.
|
|
|
|
void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
|
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
unsigned RCount = FnBeginRegionCount.back();
|
|
|
|
assert(RCount <= RegionStack.size() && "Region stack mismatch");
|
|
|
|
|
|
|
|
// Pop all regions for this function.
|
|
|
|
while (RegionStack.size() != RCount)
|
|
|
|
EmitRegionEnd(Builder);
|
|
|
|
FnBeginRegionCount.pop_back();
|
|
|
|
}
|
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
|
|
|
|
// See BuildByRefType.
|
|
|
|
llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
|
|
|
|
uint64_t *XOffset) {
|
2008-10-17 09:07:56 +08:00
|
|
|
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::SmallVector<llvm::Value *, 5> EltTys;
|
2010-02-11 02:49:08 +08:00
|
|
|
QualType FType;
|
|
|
|
uint64_t FieldSize, FieldOffset;
|
|
|
|
unsigned FieldAlign;
|
|
|
|
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
|
2010-02-11 02:49:08 +08:00
|
|
|
QualType Type = VD->getType();
|
2009-09-22 10:12:52 +08:00
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
FieldOffset = 0;
|
|
|
|
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
|
2010-04-25 04:19:58 +08:00
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
|
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "__forwarding", &FieldOffset));
|
2010-02-11 02:49:08 +08:00
|
|
|
FType = CGM.getContext().IntTy;
|
2010-04-25 04:19:58 +08:00
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
|
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset));
|
|
|
|
|
2011-02-07 18:33:21 +08:00
|
|
|
bool HasCopyAndDispose = CGM.getContext().BlockRequiresCopying(Type);
|
2010-02-11 02:49:08 +08:00
|
|
|
if (HasCopyAndDispose) {
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
|
2010-04-25 04:19:58 +08:00
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "__copy_helper",
|
|
|
|
&FieldOffset));
|
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "__destroy_helper",
|
|
|
|
&FieldOffset));
|
2010-02-11 02:49:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CharUnits Align = CGM.getContext().getDeclAlign(VD);
|
|
|
|
if (Align > CharUnits::fromQuantity(
|
|
|
|
CGM.getContext().Target.getPointerAlign(0) / 8)) {
|
|
|
|
unsigned AlignedOffsetInBytes
|
|
|
|
= llvm::RoundUpToAlignment(FieldOffset/8, Align.getQuantity());
|
|
|
|
unsigned NumPaddingBytes
|
|
|
|
= AlignedOffsetInBytes - FieldOffset/8;
|
2009-09-22 10:12:52 +08:00
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
if (NumPaddingBytes > 0) {
|
|
|
|
llvm::APInt pad(32, NumPaddingBytes);
|
|
|
|
FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy,
|
|
|
|
pad, ArrayType::Normal, 0);
|
2010-04-25 04:19:58 +08:00
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset));
|
2009-09-22 10:12:52 +08:00
|
|
|
}
|
2010-02-11 02:49:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FType = Type;
|
2010-04-25 04:19:58 +08:00
|
|
|
llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
2010-02-11 02:49:08 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = Align.getQuantity()*8;
|
2009-09-22 10:12:52 +08:00
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
*XOffset = FieldOffset;
|
2011-02-23 02:56:36 +08:00
|
|
|
FieldTy = DBuilder.createMemberType(VD->getName(), Unit,
|
2010-12-09 06:42:58 +08:00
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
2010-02-11 02:49:08 +08:00
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
llvm::DIArray Elements =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
|
2010-02-11 02:49:08 +08:00
|
|
|
|
2010-09-30 05:05:52 +08:00
|
|
|
unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct;
|
2010-02-11 02:49:08 +08:00
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
|
2010-12-09 06:42:58 +08:00
|
|
|
Elements);
|
2010-02-11 02:49:08 +08:00
|
|
|
}
|
2010-12-09 06:42:58 +08:00
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
/// EmitDeclare - Emit local variable declaration debug info.
|
|
|
|
void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
|
2011-03-04 04:13:15 +08:00
|
|
|
llvm::Value *Storage,
|
|
|
|
unsigned ArgNo, CGBuilderTy &Builder) {
|
2010-02-11 02:49:08 +08:00
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
|
2010-02-11 02:49:08 +08:00
|
|
|
llvm::DIType Ty;
|
|
|
|
uint64_t XOffset = 0;
|
|
|
|
if (VD->hasAttr<BlocksAttr>())
|
|
|
|
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
|
|
|
|
else
|
|
|
|
Ty = getOrCreateType(VD->getType(), Unit);
|
2009-05-05 12:57:08 +08:00
|
|
|
|
2010-05-08 07:05:55 +08:00
|
|
|
// If there is not any debug info for type then do not emit debug info
|
|
|
|
// for this variable.
|
|
|
|
if (!Ty)
|
|
|
|
return;
|
|
|
|
|
2011-02-16 09:11:51 +08:00
|
|
|
if (llvm::Argument *Arg = dyn_cast<llvm::Argument>(Storage)) {
|
|
|
|
// If Storage is an aggregate returned as 'sret' then let debugger know
|
|
|
|
// about this.
|
2011-02-10 08:40:52 +08:00
|
|
|
if (Arg->hasStructRetAttr())
|
2011-02-23 02:56:36 +08:00
|
|
|
Ty = DBuilder.createReferenceType(Ty);
|
2011-02-16 09:11:51 +08:00
|
|
|
else if (CXXRecordDecl *Record = VD->getType()->getAsCXXRecordDecl()) {
|
|
|
|
// If an aggregate variable has non trivial destructor or non trivial copy
|
|
|
|
// constructor than it is pass indirectly. Let debug info know about this
|
|
|
|
// by using reference of the aggregate type as a argument type.
|
|
|
|
if (!Record->hasTrivialCopyConstructor() || !Record->hasTrivialDestructor())
|
2011-02-23 02:56:36 +08:00
|
|
|
Ty = DBuilder.createReferenceType(Ty);
|
2011-02-16 09:11:51 +08:00
|
|
|
}
|
|
|
|
}
|
2011-02-10 08:40:52 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Get location information.
|
2010-05-13 07:46:38 +08:00
|
|
|
unsigned Line = getLineNumber(VD->getLocation());
|
|
|
|
unsigned Column = getColumnNumber(VD->getLocation());
|
2010-09-30 07:09:21 +08:00
|
|
|
unsigned Flags = 0;
|
|
|
|
if (VD->isImplicit())
|
|
|
|
Flags |= llvm::DIDescriptor::FlagArtificial;
|
2010-04-01 14:31:43 +08:00
|
|
|
llvm::MDNode *Scope = RegionStack.back();
|
2010-10-13 07:24:54 +08:00
|
|
|
|
|
|
|
llvm::StringRef Name = VD->getName();
|
|
|
|
if (!Name.empty()) {
|
2011-01-11 08:30:27 +08:00
|
|
|
if (VD->hasAttr<BlocksAttr>()) {
|
|
|
|
CharUnits offset = CharUnits::fromQuantity(32);
|
|
|
|
llvm::SmallVector<llvm::Value *, 9> addr;
|
|
|
|
const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext());
|
2011-02-19 07:29:22 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
|
2011-01-11 08:30:27 +08:00
|
|
|
// offset of __forwarding field
|
|
|
|
offset =
|
|
|
|
CharUnits::fromQuantity(CGM.getContext().Target.getPointerWidth(0)/8);
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
|
2011-02-19 07:29:22 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
|
2011-01-11 08:30:27 +08:00
|
|
|
// offset of x field
|
|
|
|
offset = CharUnits::fromQuantity(XOffset/8);
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
|
|
|
|
|
|
|
|
// Create the descriptor for the variable.
|
|
|
|
llvm::DIVariable D =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createComplexVariable(Tag,
|
2011-01-11 08:30:27 +08:00
|
|
|
llvm::DIDescriptor(RegionStack.back()),
|
|
|
|
VD->getName(), Unit, Line, Ty,
|
2011-03-04 04:13:15 +08:00
|
|
|
addr.data(), addr.size(), ArgNo);
|
2011-01-11 08:30:27 +08:00
|
|
|
|
|
|
|
// Insert an llvm.dbg.declare into the current block.
|
|
|
|
llvm::Instruction *Call =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
|
2011-01-11 08:30:27 +08:00
|
|
|
|
|
|
|
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Create the descriptor for the variable.
|
2010-10-13 07:24:54 +08:00
|
|
|
llvm::DIVariable D =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
|
2010-12-09 06:42:58 +08:00
|
|
|
Name, Unit, Line, Ty,
|
2011-03-04 04:13:15 +08:00
|
|
|
CGM.getLangOptions().Optimize, Flags, ArgNo);
|
2010-10-13 07:24:54 +08:00
|
|
|
|
|
|
|
// Insert an llvm.dbg.declare into the current block.
|
|
|
|
llvm::Instruction *Call =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
|
2010-10-13 07:24:54 +08:00
|
|
|
|
|
|
|
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
|
2010-10-30 00:21:19 +08:00
|
|
|
return;
|
2010-10-13 07:24:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// If VD is an anonymous union then Storage represents value for
|
|
|
|
// all union fields.
|
2011-02-23 06:38:33 +08:00
|
|
|
if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) {
|
|
|
|
const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
|
|
|
|
if (RD->isUnion()) {
|
|
|
|
for (RecordDecl::field_iterator I = RD->field_begin(),
|
|
|
|
E = RD->field_end();
|
|
|
|
I != E; ++I) {
|
|
|
|
FieldDecl *Field = *I;
|
|
|
|
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
|
|
|
|
llvm::StringRef FieldName = Field->getName();
|
2010-10-13 07:24:54 +08:00
|
|
|
|
2011-02-23 06:38:33 +08:00
|
|
|
// Ignore unnamed fields. Do not ignore unnamed records.
|
|
|
|
if (FieldName.empty() && !isa<RecordType>(Field->getType()))
|
|
|
|
continue;
|
2010-10-13 07:24:54 +08:00
|
|
|
|
2011-02-23 06:38:33 +08:00
|
|
|
// Use VarDecl's Tag, Scope and Line number.
|
|
|
|
llvm::DIVariable D =
|
|
|
|
DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
|
|
|
|
FieldName, Unit, Line, FieldTy,
|
2011-03-04 04:13:15 +08:00
|
|
|
CGM.getLangOptions().Optimize, Flags,
|
|
|
|
ArgNo);
|
2010-10-13 07:24:54 +08:00
|
|
|
|
2011-02-23 06:38:33 +08:00
|
|
|
// Insert an llvm.dbg.declare into the current block.
|
|
|
|
llvm::Instruction *Call =
|
|
|
|
DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
|
2010-10-13 07:24:54 +08:00
|
|
|
|
2011-02-23 06:38:33 +08:00
|
|
|
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
|
2010-10-13 07:24:54 +08:00
|
|
|
}
|
2011-02-23 06:38:33 +08:00
|
|
|
}
|
|
|
|
}
|
2008-05-30 18:30:31 +08:00
|
|
|
}
|
|
|
|
|
2009-09-30 10:43:10 +08:00
|
|
|
/// EmitDeclare - Emit local variable declaration debug info.
|
2011-02-07 18:33:21 +08:00
|
|
|
void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
|
2009-09-30 10:43:10 +08:00
|
|
|
llvm::Value *Storage, CGBuilderTy &Builder,
|
2011-02-07 18:33:21 +08:00
|
|
|
const CGBlockInfo &blockInfo) {
|
2009-09-30 10:43:10 +08:00
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
|
2010-04-27 07:28:46 +08:00
|
|
|
if (Builder.GetInsertBlock() == 0)
|
2009-09-30 10:43:10 +08:00
|
|
|
return;
|
|
|
|
|
2011-02-07 18:33:21 +08:00
|
|
|
bool isByRef = VD->hasAttr<BlocksAttr>();
|
|
|
|
|
2009-09-30 10:43:10 +08:00
|
|
|
uint64_t XOffset = 0;
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
|
2010-02-11 02:49:08 +08:00
|
|
|
llvm::DIType Ty;
|
2011-02-07 18:33:21 +08:00
|
|
|
if (isByRef)
|
2010-02-11 02:49:08 +08:00
|
|
|
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
|
|
|
|
else
|
|
|
|
Ty = getOrCreateType(VD->getType(), Unit);
|
2009-09-30 10:43:10 +08:00
|
|
|
|
|
|
|
// Get location information.
|
2010-05-13 07:46:38 +08:00
|
|
|
unsigned Line = getLineNumber(VD->getLocation());
|
|
|
|
unsigned Column = getColumnNumber(VD->getLocation());
|
2009-09-30 10:43:10 +08:00
|
|
|
|
2011-02-07 18:33:21 +08:00
|
|
|
const llvm::TargetData &target = CGM.getTargetData();
|
|
|
|
|
|
|
|
CharUnits offset = CharUnits::fromQuantity(
|
|
|
|
target.getStructLayout(blockInfo.StructureType)
|
|
|
|
->getElementOffset(blockInfo.getCapture(VD).getIndex()));
|
|
|
|
|
2009-09-30 10:43:10 +08:00
|
|
|
llvm::SmallVector<llvm::Value *, 9> addr;
|
2010-01-25 11:29:35 +08:00
|
|
|
const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext());
|
2011-02-19 07:29:22 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
|
2010-01-25 11:29:35 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
|
2011-02-07 18:33:21 +08:00
|
|
|
if (isByRef) {
|
2011-02-19 07:29:22 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
|
2010-01-12 01:06:35 +08:00
|
|
|
// offset of __forwarding field
|
2011-02-07 18:33:21 +08:00
|
|
|
offset = CharUnits::fromQuantity(target.getPointerSize()/8);
|
2010-01-25 11:29:35 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
|
2011-02-19 07:29:22 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
|
2010-01-12 01:06:35 +08:00
|
|
|
// offset of x field
|
|
|
|
offset = CharUnits::fromQuantity(XOffset/8);
|
2010-01-25 11:29:35 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
|
2009-09-30 10:43:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create the descriptor for the variable.
|
|
|
|
llvm::DIVariable D =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()),
|
2010-12-09 06:42:58 +08:00
|
|
|
VD->getName(), Unit, Line, Ty,
|
|
|
|
addr.data(), addr.size());
|
2009-09-30 10:43:10 +08:00
|
|
|
// Insert an llvm.dbg.declare into the current block.
|
2009-11-12 03:10:19 +08:00
|
|
|
llvm::Instruction *Call =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
|
2009-12-29 05:44:41 +08:00
|
|
|
|
2010-04-01 14:31:43 +08:00
|
|
|
llvm::MDNode *Scope = RegionStack.back();
|
2010-05-11 07:48:38 +08:00
|
|
|
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
|
2009-09-30 10:43:10 +08:00
|
|
|
}
|
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::Value *Storage,
|
|
|
|
CGBuilderTy &Builder) {
|
2011-03-04 04:13:15 +08:00
|
|
|
EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder);
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2008-06-05 16:59:10 +08:00
|
|
|
|
2009-09-30 10:43:10 +08:00
|
|
|
void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
|
2011-02-07 18:33:21 +08:00
|
|
|
const VarDecl *variable, llvm::Value *Storage, CGBuilderTy &Builder,
|
|
|
|
const CGBlockInfo &blockInfo) {
|
|
|
|
EmitDeclare(variable, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder,
|
|
|
|
blockInfo);
|
2009-09-30 10:43:10 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
|
|
|
|
/// variable declaration.
|
2010-02-02 05:52:22 +08:00
|
|
|
void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
|
2011-03-04 04:13:15 +08:00
|
|
|
unsigned ArgNo,
|
2011-02-16 09:11:51 +08:00
|
|
|
CGBuilderTy &Builder) {
|
2011-03-04 04:13:15 +08:00
|
|
|
EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, ArgNo, Builder);
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2008-06-05 16:59:10 +08:00
|
|
|
|
2011-02-23 06:38:33 +08:00
|
|
|
namespace {
|
|
|
|
struct BlockLayoutChunk {
|
|
|
|
uint64_t OffsetInBits;
|
|
|
|
const BlockDecl::Capture *Capture;
|
|
|
|
};
|
|
|
|
bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) {
|
|
|
|
return l.OffsetInBits < r.OffsetInBits;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
|
|
|
|
llvm::Value *addr,
|
|
|
|
CGBuilderTy &Builder) {
|
|
|
|
ASTContext &C = CGM.getContext();
|
|
|
|
const BlockDecl *blockDecl = block.getBlockDecl();
|
|
|
|
|
|
|
|
// Collect some general information about the block's location.
|
|
|
|
SourceLocation loc = blockDecl->getCaretLocation();
|
|
|
|
llvm::DIFile tunit = getOrCreateFile(loc);
|
|
|
|
unsigned line = getLineNumber(loc);
|
|
|
|
unsigned column = getColumnNumber(loc);
|
|
|
|
|
|
|
|
// Build the debug-info type for the block literal.
|
|
|
|
llvm::DIDescriptor enclosingContext =
|
|
|
|
getContextDescriptor(cast<Decl>(blockDecl->getDeclContext()));
|
|
|
|
|
|
|
|
const llvm::StructLayout *blockLayout =
|
|
|
|
CGM.getTargetData().getStructLayout(block.StructureType);
|
|
|
|
|
|
|
|
llvm::SmallVector<llvm::Value*, 16> fields;
|
|
|
|
fields.push_back(createFieldType("__isa", C.VoidPtrTy, 0, loc, AS_public,
|
|
|
|
blockLayout->getElementOffsetInBits(0),
|
|
|
|
tunit));
|
|
|
|
fields.push_back(createFieldType("__flags", C.IntTy, 0, loc, AS_public,
|
|
|
|
blockLayout->getElementOffsetInBits(1),
|
|
|
|
tunit));
|
|
|
|
fields.push_back(createFieldType("__reserved", C.IntTy, 0, loc, AS_public,
|
|
|
|
blockLayout->getElementOffsetInBits(2),
|
|
|
|
tunit));
|
|
|
|
fields.push_back(createFieldType("__FuncPtr", C.VoidPtrTy, 0, loc, AS_public,
|
|
|
|
blockLayout->getElementOffsetInBits(3),
|
|
|
|
tunit));
|
|
|
|
fields.push_back(createFieldType("__descriptor",
|
|
|
|
C.getPointerType(block.NeedsCopyDispose ?
|
|
|
|
C.getBlockDescriptorExtendedType() :
|
|
|
|
C.getBlockDescriptorType()),
|
|
|
|
0, loc, AS_public,
|
|
|
|
blockLayout->getElementOffsetInBits(4),
|
|
|
|
tunit));
|
|
|
|
|
|
|
|
// We want to sort the captures by offset, not because DWARF
|
|
|
|
// requires this, but because we're paranoid about debuggers.
|
|
|
|
llvm::SmallVector<BlockLayoutChunk, 8> chunks;
|
|
|
|
|
|
|
|
// 'this' capture.
|
|
|
|
if (blockDecl->capturesCXXThis()) {
|
|
|
|
BlockLayoutChunk chunk;
|
|
|
|
chunk.OffsetInBits =
|
|
|
|
blockLayout->getElementOffsetInBits(block.CXXThisIndex);
|
|
|
|
chunk.Capture = 0;
|
|
|
|
chunks.push_back(chunk);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Variable captures.
|
|
|
|
for (BlockDecl::capture_const_iterator
|
|
|
|
i = blockDecl->capture_begin(), e = blockDecl->capture_end();
|
|
|
|
i != e; ++i) {
|
|
|
|
const BlockDecl::Capture &capture = *i;
|
|
|
|
const VarDecl *variable = capture.getVariable();
|
|
|
|
const CGBlockInfo::Capture &captureInfo = block.getCapture(variable);
|
2008-06-05 16:59:10 +08:00
|
|
|
|
2011-02-23 06:38:33 +08:00
|
|
|
// Ignore constant captures.
|
|
|
|
if (captureInfo.isConstant())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
BlockLayoutChunk chunk;
|
|
|
|
chunk.OffsetInBits =
|
|
|
|
blockLayout->getElementOffsetInBits(captureInfo.getIndex());
|
|
|
|
chunk.Capture = &capture;
|
|
|
|
chunks.push_back(chunk);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort by offset.
|
|
|
|
llvm::array_pod_sort(chunks.begin(), chunks.end());
|
|
|
|
|
|
|
|
for (llvm::SmallVectorImpl<BlockLayoutChunk>::iterator
|
|
|
|
i = chunks.begin(), e = chunks.end(); i != e; ++i) {
|
|
|
|
uint64_t offsetInBits = i->OffsetInBits;
|
|
|
|
const BlockDecl::Capture *capture = i->Capture;
|
|
|
|
|
|
|
|
// If we have a null capture, this must be the C++ 'this' capture.
|
|
|
|
if (!capture) {
|
|
|
|
const CXXMethodDecl *method =
|
|
|
|
cast<CXXMethodDecl>(blockDecl->getNonClosureContext());
|
|
|
|
QualType type = method->getThisType(C);
|
|
|
|
|
|
|
|
fields.push_back(createFieldType("this", type, 0, loc, AS_public,
|
|
|
|
offsetInBits, tunit));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const VarDecl *variable = capture->getVariable();
|
|
|
|
llvm::StringRef name = variable->getName();
|
2011-03-02 14:57:14 +08:00
|
|
|
|
|
|
|
llvm::DIType fieldType;
|
|
|
|
if (capture->isByRef()) {
|
|
|
|
std::pair<uint64_t,unsigned> ptrInfo = C.getTypeInfo(C.VoidPtrTy);
|
|
|
|
|
|
|
|
// FIXME: this creates a second copy of this type!
|
|
|
|
uint64_t xoffset;
|
|
|
|
fieldType = EmitTypeForVarWithBlocksAttr(variable, &xoffset);
|
|
|
|
fieldType = DBuilder.createPointerType(fieldType, ptrInfo.first);
|
|
|
|
fieldType = DBuilder.createMemberType(name, tunit, line,
|
|
|
|
ptrInfo.first, ptrInfo.second,
|
|
|
|
offsetInBits, 0, fieldType);
|
|
|
|
} else {
|
|
|
|
fieldType = createFieldType(name, variable->getType(), 0,
|
|
|
|
loc, AS_public, offsetInBits, tunit);
|
|
|
|
}
|
|
|
|
fields.push_back(fieldType);
|
2011-02-23 06:38:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm::SmallString<36> typeName;
|
|
|
|
llvm::raw_svector_ostream(typeName)
|
|
|
|
<< "__block_literal_" << CGM.getUniqueBlockCount();
|
|
|
|
|
|
|
|
llvm::DIArray fieldsArray =
|
|
|
|
DBuilder.getOrCreateArray(fields.data(), fields.size());
|
|
|
|
|
|
|
|
llvm::DIType type =
|
|
|
|
DBuilder.createStructType(tunit, typeName.str(), tunit, line,
|
|
|
|
CGM.getContext().toBits(block.BlockSize),
|
|
|
|
CGM.getContext().toBits(block.BlockAlign),
|
|
|
|
0, fieldsArray);
|
|
|
|
type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);
|
|
|
|
|
|
|
|
// Get overall information about the block.
|
|
|
|
unsigned flags = llvm::DIDescriptor::FlagArtificial;
|
|
|
|
llvm::MDNode *scope = RegionStack.back();
|
|
|
|
llvm::StringRef name = ".block_descriptor";
|
|
|
|
|
|
|
|
// Create the descriptor for the parameter.
|
|
|
|
llvm::DIVariable debugVar =
|
|
|
|
DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable,
|
|
|
|
llvm::DIDescriptor(scope),
|
|
|
|
name, tunit, line, type,
|
2011-03-04 04:13:15 +08:00
|
|
|
CGM.getLangOptions().Optimize, flags,
|
|
|
|
cast<llvm::Argument>(addr)->getArgNo() + 1);
|
2011-02-23 06:38:33 +08:00
|
|
|
|
|
|
|
// Insert an llvm.dbg.value into the current block.
|
|
|
|
llvm::Instruction *declare =
|
|
|
|
DBuilder.insertDbgValueIntrinsic(addr, 0, debugVar,
|
|
|
|
Builder.GetInsertBlock());
|
|
|
|
declare->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
|
|
|
|
}
|
2008-06-05 16:59:10 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
/// EmitGlobalVariable - Emit information about a global variable.
|
2009-09-09 23:08:12 +08:00
|
|
|
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
|
2010-02-02 05:34:11 +08:00
|
|
|
const VarDecl *D) {
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Create global variable debug descriptor.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(D->getLocation());
|
2010-05-13 07:46:38 +08:00
|
|
|
unsigned LineNo = getLineNumber(D->getLocation());
|
2008-11-24 11:54:41 +08:00
|
|
|
|
2010-02-02 05:34:11 +08:00
|
|
|
QualType T = D->getType();
|
2008-11-27 01:40:42 +08:00
|
|
|
if (T->isIncompleteArrayType()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-27 01:40:42 +08:00
|
|
|
// CodeGen turns int[] into int[1] so we'll do the same here.
|
|
|
|
llvm::APSInt ConstVal(32);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-27 01:40:42 +08:00
|
|
|
ConstVal = 1;
|
2009-12-07 02:00:51 +08:00
|
|
|
QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
T = CGM.getContext().getConstantArrayType(ET, ConstVal,
|
2008-11-27 01:40:42 +08:00
|
|
|
ArrayType::Normal, 0);
|
|
|
|
}
|
2010-04-30 01:48:37 +08:00
|
|
|
llvm::StringRef DeclName = D->getName();
|
2010-05-14 07:52:37 +08:00
|
|
|
llvm::StringRef LinkageName;
|
2011-02-10 03:16:38 +08:00
|
|
|
if (D->getDeclContext() && !isa<FunctionDecl>(D->getDeclContext())
|
|
|
|
&& !isa<ObjCMethodDecl>(D->getDeclContext()))
|
2010-05-14 07:52:37 +08:00
|
|
|
LinkageName = Var->getName();
|
2010-10-23 01:11:50 +08:00
|
|
|
if (LinkageName == DeclName)
|
|
|
|
LinkageName = llvm::StringRef();
|
2010-02-02 05:34:11 +08:00
|
|
|
llvm::DIDescriptor DContext =
|
2010-12-09 08:33:05 +08:00
|
|
|
getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createStaticVariable(DContext, DeclName, LinkageName,
|
2010-12-09 06:42:58 +08:00
|
|
|
Unit, LineNo, getOrCreateType(T, Unit),
|
|
|
|
Var->hasInternalLinkage(), Var);
|
2008-06-05 16:59:10 +08:00
|
|
|
}
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
/// EmitGlobalVariable - Emit information about an objective-c interface.
|
2009-09-09 23:08:12 +08:00
|
|
|
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
|
2010-02-02 05:52:22 +08:00
|
|
|
ObjCInterfaceDecl *ID) {
|
2009-02-27 05:10:26 +08:00
|
|
|
// Create global variable debug descriptor.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(ID->getLocation());
|
2010-05-13 07:46:38 +08:00
|
|
|
unsigned LineNo = getLineNumber(ID->getLocation());
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
llvm::StringRef Name = ID->getName();
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
QualType T = CGM.getContext().getObjCInterfaceType(ID);
|
2009-02-27 05:10:26 +08:00
|
|
|
if (T->isIncompleteArrayType()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// CodeGen turns int[] into int[1] so we'll do the same here.
|
|
|
|
llvm::APSInt ConstVal(32);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
ConstVal = 1;
|
2009-12-07 02:00:51 +08:00
|
|
|
QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
T = CGM.getContext().getConstantArrayType(ET, ConstVal,
|
2009-02-27 05:10:26 +08:00
|
|
|
ArrayType::Normal, 0);
|
|
|
|
}
|
|
|
|
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createGlobalVariable(Name, Unit, LineNo,
|
2010-12-09 06:42:58 +08:00
|
|
|
getOrCreateType(T, Unit),
|
|
|
|
Var->hasInternalLinkage(), Var);
|
2009-02-27 05:10:26 +08:00
|
|
|
}
|
2010-02-02 03:16:32 +08:00
|
|
|
|
2010-08-11 01:53:33 +08:00
|
|
|
/// EmitGlobalVariable - Emit global variable's debug info.
|
|
|
|
void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
|
2010-10-09 09:34:31 +08:00
|
|
|
llvm::Constant *Init) {
|
2010-08-10 15:24:25 +08:00
|
|
|
// Create the descriptor for the variable.
|
|
|
|
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
|
|
|
|
llvm::StringRef Name = VD->getName();
|
2010-08-11 02:27:15 +08:00
|
|
|
llvm::DIType Ty = getOrCreateType(VD->getType(), Unit);
|
2010-08-24 06:07:25 +08:00
|
|
|
if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(VD)) {
|
|
|
|
if (const EnumDecl *ED = dyn_cast<EnumDecl>(ECD->getDeclContext()))
|
2011-01-18 06:23:07 +08:00
|
|
|
Ty = CreateEnumType(ED);
|
2010-08-24 06:07:25 +08:00
|
|
|
}
|
2010-08-11 02:27:15 +08:00
|
|
|
// Do not use DIGlobalVariable for enums.
|
|
|
|
if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
|
|
|
|
return;
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createStaticVariable(Unit, Name, Name, Unit,
|
2010-12-09 06:42:58 +08:00
|
|
|
getLineNumber(VD->getLocation()),
|
|
|
|
Ty, true, Init);
|
2010-08-10 15:24:25 +08:00
|
|
|
}
|
|
|
|
|
2010-02-02 03:16:32 +08:00
|
|
|
/// getOrCreateNamesSpace - Return namespace descriptor for the given
|
|
|
|
/// namespace decl.
|
|
|
|
llvm::DINameSpace
|
2010-12-09 08:33:05 +08:00
|
|
|
CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
|
2010-02-02 03:16:32 +08:00
|
|
|
llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH>::iterator I =
|
|
|
|
NameSpaceCache.find(NSDecl);
|
|
|
|
if (I != NameSpaceCache.end())
|
|
|
|
return llvm::DINameSpace(cast<llvm::MDNode>(I->second));
|
|
|
|
|
2010-05-13 07:46:38 +08:00
|
|
|
unsigned LineNo = getLineNumber(NSDecl->getLocation());
|
2010-10-29 03:12:46 +08:00
|
|
|
llvm::DIFile FileD = getOrCreateFile(NSDecl->getLocation());
|
2010-02-02 03:16:32 +08:00
|
|
|
llvm::DIDescriptor Context =
|
2010-12-09 08:33:05 +08:00
|
|
|
getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
|
2010-02-02 03:16:32 +08:00
|
|
|
llvm::DINameSpace NS =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
|
2010-05-08 02:12:35 +08:00
|
|
|
NameSpaceCache[NSDecl] = llvm::WeakVH(NS);
|
2010-02-02 03:16:32 +08:00
|
|
|
return NS;
|
|
|
|
}
|
2011-03-24 00:29:39 +08:00
|
|
|
|
|
|
|
/// UpdateCompletedType - Update type cache because the type is now
|
|
|
|
/// translated.
|
|
|
|
void CGDebugInfo::UpdateCompletedType(const TagDecl *TD) {
|
|
|
|
QualType Ty = CGM.getContext().getTagDeclType(TD);
|
|
|
|
|
|
|
|
// If the type exist in type cache then remove it from the cache.
|
|
|
|
// There is no need to prepare debug info for the completed type
|
|
|
|
// right now. It will be generated on demand lazily.
|
|
|
|
llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
|
|
|
|
TypeCache.find(Ty.getAsOpaquePtr());
|
|
|
|
if (it != TypeCache.end())
|
|
|
|
TypeCache.erase(it);
|
|
|
|
}
|