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"
|
2011-10-15 02:45:11 +08:00
|
|
|
#include "llvm/Support/FileSystem.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() {
|
2011-10-12 07:00:51 +08:00
|
|
|
assert(LexicalBlockStack.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) {
|
2011-10-12 07:00:45 +08:00
|
|
|
// If the new location isn't valid return.
|
|
|
|
if (!Loc.isValid()) return;
|
|
|
|
|
|
|
|
CurLoc = CGM.getContext().getSourceManager().getExpansionLoc(Loc);
|
2011-10-14 05:45:18 +08:00
|
|
|
|
|
|
|
// If we've changed files in the middle of a lexical scope go ahead
|
|
|
|
// and create a new lexical scope with file node if it's different
|
|
|
|
// from the one in the scope.
|
|
|
|
if (LexicalBlockStack.empty()) return;
|
|
|
|
|
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
|
|
|
PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc);
|
|
|
|
PresumedLoc PPLoc = SM.getPresumedLoc(PrevLoc);
|
|
|
|
|
|
|
|
if (PCLoc.isInvalid() || PPLoc.isInvalid() ||
|
|
|
|
!strcmp(PPLoc.getFilename(), PCLoc.getFilename()))
|
|
|
|
return;
|
|
|
|
|
|
|
|
llvm::MDNode *LB = LexicalBlockStack.back();
|
|
|
|
llvm::DIScope Scope = llvm::DIScope(LB);
|
|
|
|
if (Scope.isLexicalBlockFile()) {
|
|
|
|
llvm::DILexicalBlockFile LBF = llvm::DILexicalBlockFile(LB);
|
|
|
|
llvm::DIDescriptor D
|
|
|
|
= DBuilder.createLexicalBlockFile(LBF.getScope(),
|
|
|
|
getOrCreateFile(CurLoc));
|
|
|
|
llvm::MDNode *N = D;
|
|
|
|
LexicalBlockStack.pop_back();
|
|
|
|
LexicalBlockStack.push_back(N);
|
|
|
|
} else if (Scope.isLexicalBlock()) {
|
|
|
|
llvm::DIDescriptor D
|
|
|
|
= DBuilder.createLexicalBlockFile(Scope, getOrCreateFile(CurLoc));
|
|
|
|
llvm::MDNode *N = D;
|
|
|
|
LexicalBlockStack.pop_back();
|
|
|
|
LexicalBlockStack.push_back(N);
|
|
|
|
}
|
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.
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
|
2010-01-14 08:36:21 +08:00
|
|
|
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());
|
2011-07-23 18:55:15 +08:00
|
|
|
return StringRef(StrPtr, NS.length());
|
2010-01-14 08:36:21 +08:00
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
|
2010-09-03 02:01:51 +08:00
|
|
|
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());
|
2011-07-23 18:55:15 +08:00
|
|
|
return StringRef(StrPtr, OS.tell());
|
2010-09-03 02:01:51 +08:00
|
|
|
}
|
|
|
|
|
2011-04-19 01:30:25 +08:00
|
|
|
/// getSelectorName - Return selector name. This is used for debugging
|
2011-04-16 08:37:51 +08:00
|
|
|
/// info.
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef CGDebugInfo::getSelectorName(Selector S) {
|
2011-10-15 02:45:16 +08:00
|
|
|
const std::string &SName = S.getAsString();
|
|
|
|
char *StrPtr = DebugInfoNames.Allocate<char>(SName.size());
|
|
|
|
memcpy(StrPtr, SName.data(), SName.size());
|
|
|
|
return StringRef(StrPtr, SName.size());
|
2011-04-16 08:37:51 +08:00
|
|
|
}
|
|
|
|
|
2010-07-21 04:24:18 +08:00
|
|
|
/// getClassName - Get class name including template argument list.
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef
|
2010-07-21 04:24:18 +08:00
|
|
|
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());
|
2011-07-23 18:55:15 +08:00
|
|
|
return StringRef(StrPtr, Buffer.length());
|
2010-07-21 04:24:18 +08:00
|
|
|
}
|
|
|
|
|
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-07-23 18:55:15 +08:00
|
|
|
if (PLoc.isInvalid() || 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) {
|
2011-10-15 02:45:06 +08:00
|
|
|
assert((Loc.isValid() || CurLoc.isValid()) && "Invalid current location!");
|
2010-05-13 07:46:38 +08:00
|
|
|
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) {
|
2011-10-15 02:45:06 +08:00
|
|
|
assert((Loc.isValid() || CurLoc.isValid()) && "Invalid current location!");
|
2010-05-13 07:46:38 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef CGDebugInfo::getCurrentDirname() {
|
2011-10-21 10:32:14 +08:00
|
|
|
if (!CGM.getCodeGenOpts().DebugCompilationDir.empty())
|
|
|
|
return CGM.getCodeGenOpts().DebugCompilationDir;
|
|
|
|
|
2010-07-27 23:17:16 +08:00
|
|
|
if (!CWDName.empty())
|
|
|
|
return CWDName;
|
2011-10-15 02:45:11 +08:00
|
|
|
llvm::SmallString<256> CWD;
|
|
|
|
llvm::sys::fs::current_path(CWD);
|
|
|
|
char *CompDirnamePtr = DebugInfoNames.Allocate<char>(CWD.size());
|
|
|
|
memcpy(CompDirnamePtr, CWD.data(), CWD.size());
|
2011-07-23 18:55:15 +08:00
|
|
|
return CWDName = StringRef(CompDirnamePtr, CWD.size());
|
2010-07-27 23:17:16 +08:00
|
|
|
}
|
|
|
|
|
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());
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef Filename(FilenamePtr, MainFileName.length());
|
2010-07-27 23:17:16 +08:00
|
|
|
|
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()) {
|
2011-10-19 05:02:43 +08:00
|
|
|
#define BUILTIN_TYPE(Id, SingletonId)
|
|
|
|
#define PLACEHOLDER_TYPE(Id, SingletonId) \
|
|
|
|
case BuiltinType::Id:
|
|
|
|
#include "clang/AST/BuiltinTypes.def"
|
2011-09-13 02:50:21 +08:00
|
|
|
case BuiltinType::Dependent:
|
2011-10-19 05:02:43 +08:00
|
|
|
llvm_unreachable("Unexpected builtin type");
|
2011-09-13 02:50:21 +08:00
|
|
|
case BuiltinType::NullPtr:
|
2011-09-15 07:14:14 +08:00
|
|
|
return DBuilder.
|
|
|
|
createNullPtrType(BT->getName(CGM.getContext().getLangOptions()));
|
2008-11-10 14:08:34 +08:00
|
|
|
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
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<llvm::Value *, 16> EltTys;
|
2010-07-28 09:33:15 +08:00
|
|
|
llvm::DIType FieldTy =
|
2011-06-25 06:00:59 +08:00
|
|
|
DBuilder.createMemberType(getOrCreateMainFile(), "isa",
|
|
|
|
getOrCreateMainFile(), 0, Size,
|
|
|
|
0, 0, 0, ISATy);
|
2010-07-28 09:33:15 +08:00
|
|
|
EltTys.push_back(FieldTy);
|
2011-04-24 18:11:03 +08:00
|
|
|
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
|
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;
|
2011-09-13 01:11:58 +08:00
|
|
|
case BuiltinType::Char16:
|
|
|
|
case BuiltinType::Char32: Encoding = llvm::dwarf::DW_ATE_UTF; break;
|
2008-11-10 14:08:34 +08:00
|
|
|
case BuiltinType::UShort:
|
|
|
|
case BuiltinType::UInt:
|
2011-05-06 01:06:30 +08:00
|
|
|
case BuiltinType::UInt128:
|
2008-11-10 14:08:34 +08:00
|
|
|
case BuiltinType::ULong:
|
2011-09-10 08:44:49 +08:00
|
|
|
case BuiltinType::WChar_U:
|
2008-11-10 14:08:34 +08:00
|
|
|
case BuiltinType::ULongLong: Encoding = llvm::dwarf::DW_ATE_unsigned; break;
|
|
|
|
case BuiltinType::Short:
|
|
|
|
case BuiltinType::Int:
|
2011-05-06 01:06:30 +08:00
|
|
|
case BuiltinType::Int128:
|
2008-11-10 14:08:34 +08:00
|
|
|
case BuiltinType::Long:
|
2011-09-10 08:44:49 +08:00
|
|
|
case BuiltinType::WChar_S:
|
2008-11-10 14:08:34 +08:00
|
|
|
case BuiltinType::LongLong: Encoding = llvm::dwarf::DW_ATE_signed; break;
|
|
|
|
case BuiltinType::Bool: Encoding = llvm::dwarf::DW_ATE_boolean; break;
|
2011-10-15 07:23:15 +08:00
|
|
|
case BuiltinType::Half:
|
2008-11-10 14:08:34 +08:00
|
|
|
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();
|
2011-06-16 07:02:42 +08:00
|
|
|
Qc.removeObjCLifetime();
|
2009-09-25 09:40:47 +08:00
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2012-01-25 10:06:59 +08:00
|
|
|
// Creates a forward declaration for a RecordDecl in the given context.
|
|
|
|
llvm::DIType CGDebugInfo::createRecordFwdDecl(const RecordDecl *RD,
|
|
|
|
llvm::DIDescriptor Ctx) {
|
|
|
|
|
|
|
|
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
|
|
|
|
unsigned Line = getLineNumber(RD->getLocation());
|
|
|
|
const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
|
|
|
|
|
|
|
|
if (CXXDecl)
|
|
|
|
return DBuilder.createClassType(Ctx, RD->getName(), DefUnit,
|
|
|
|
Line, 0, 0, 0,
|
|
|
|
llvm::DIType::FlagFwdDecl,
|
|
|
|
llvm::DIType(), llvm::DIArray());
|
|
|
|
else if (RD->isStruct())
|
|
|
|
return DBuilder.createStructType(Ctx, RD->getName(), DefUnit,
|
|
|
|
Line, 0, 0, llvm::DIType::FlagFwdDecl,
|
|
|
|
llvm::DIArray());
|
|
|
|
else if (RD->isUnion())
|
|
|
|
return DBuilder.createUnionType(Ctx, RD->getName(), DefUnit,
|
|
|
|
Line, 0, 0, llvm::DIType::FlagFwdDecl,
|
|
|
|
llvm::DIArray());
|
|
|
|
else
|
|
|
|
llvm_unreachable("Unknown RecordDecl type!");
|
|
|
|
}
|
|
|
|
|
2012-01-21 06:10:15 +08:00
|
|
|
// Walk up the context chain and create forward decls for record decls,
|
|
|
|
// and normal descriptors for namespaces.
|
|
|
|
llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) {
|
|
|
|
if (!Context)
|
|
|
|
return TheCU;
|
|
|
|
|
|
|
|
// See if we already have the parent.
|
|
|
|
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
|
|
|
|
I = RegionMap.find(Context);
|
|
|
|
if (I != RegionMap.end())
|
|
|
|
return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(&*I->second));
|
|
|
|
|
|
|
|
// Check namespace.
|
|
|
|
if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context))
|
|
|
|
return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl));
|
|
|
|
|
|
|
|
if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) {
|
|
|
|
if (!RD->isDependentType()) {
|
|
|
|
llvm::DIDescriptor FDContext =
|
|
|
|
createContextChain(cast<Decl>(RD->getDeclContext()));
|
2012-01-25 10:06:59 +08:00
|
|
|
llvm::DIType Ty = createRecordFwdDecl(RD, FDContext);
|
2012-01-21 06:10:15 +08:00
|
|
|
|
|
|
|
RegionMap[Context] = llvm::WeakVH(Ty);
|
|
|
|
return llvm::DIDescriptor(Ty);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TheCU;
|
|
|
|
}
|
|
|
|
|
2011-09-14 07:45:09 +08:00
|
|
|
/// CreatePointeeType - Create Pointee type. If Pointee is a record
|
2010-10-01 03:05:55 +08:00
|
|
|
/// 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);
|
2011-10-25 07:15:17 +08:00
|
|
|
|
|
|
|
// Limit debug info for the pointee type.
|
|
|
|
|
2011-12-17 07:40:18 +08:00
|
|
|
// If we have an existing type, use that, it's still smaller than creating
|
|
|
|
// a new type.
|
|
|
|
llvm::DIType Ty = getTypeOrNull(PointeeTy);
|
|
|
|
if (Ty.Verify()) return Ty;
|
|
|
|
|
2011-10-25 07:15:17 +08:00
|
|
|
// Handle qualifiers.
|
|
|
|
if (PointeeTy.hasLocalQualifiers())
|
|
|
|
return CreateQualifiedType(PointeeTy, Unit);
|
|
|
|
|
2010-10-01 03:05:55 +08:00
|
|
|
if (const RecordType *RTy = dyn_cast<RecordType>(PointeeTy)) {
|
|
|
|
RecordDecl *RD = RTy->getDecl();
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::DIDescriptor FDContext =
|
2011-02-23 06:38:33 +08:00
|
|
|
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
|
2012-01-25 10:06:59 +08:00
|
|
|
return createRecordFwdDecl(RD, FDContext);
|
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);
|
2011-09-02 08:18:52 +08:00
|
|
|
uint64_t Size = CGM.getContext().getTargetInfo().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
|
|
|
|
2011-11-10 08:34:02 +08:00
|
|
|
return 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;
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
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-04-24 18:11:03 +08:00
|
|
|
Elements = DBuilder.getOrCreateArray(EltTys);
|
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-06-25 06:00:59 +08:00
|
|
|
FieldTy = DBuilder.createMemberType(Unit, "__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-04-24 18:11:03 +08:00
|
|
|
Elements = DBuilder.getOrCreateArray(EltTys);
|
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;
|
|
|
|
}
|
|
|
|
|
2011-11-10 08:34:02 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, 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-06-04 01:23:47 +08:00
|
|
|
const TypedefNameDecl *TyDecl = Ty->getDecl();
|
2011-11-10 08:34:02 +08:00
|
|
|
llvm::DIDescriptor TypedefContext =
|
2011-06-04 01:23:47 +08:00
|
|
|
getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext()));
|
|
|
|
|
|
|
|
return
|
2011-11-10 08:34:02 +08:00
|
|
|
DBuilder.createTypedef(Src, TyDecl->getName(), Unit, Line, TypedefContext);
|
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) {
|
2011-07-23 18:55:15 +08:00
|
|
|
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
|
|
|
|
2011-04-24 18:11:03 +08:00
|
|
|
llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(EltTys);
|
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
|
|
|
}
|
|
|
|
|
2012-01-26 09:57:13 +08:00
|
|
|
|
|
|
|
void CGDebugInfo::
|
|
|
|
CollectRecordStaticVars(const RecordDecl *RD, llvm::DIType FwdDecl) {
|
|
|
|
|
|
|
|
for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
|
|
|
|
I != E; ++I)
|
|
|
|
if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {
|
|
|
|
if (V->getInit()) {
|
|
|
|
const APValue *Value = V->evaluateValue();
|
|
|
|
if (Value && Value->isInt()) {
|
|
|
|
llvm::ConstantInt *CI
|
|
|
|
= llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());
|
|
|
|
|
|
|
|
// Create the descriptor for static variable.
|
|
|
|
llvm::DIFile VUnit = getOrCreateFile(V->getLocation());
|
|
|
|
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) {
|
|
|
|
DBuilder.createStaticVariable(FwdDecl, VName, VName, VUnit,
|
|
|
|
getLineNumber(V->getLocation()),
|
|
|
|
VTy, true, CI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
llvm::DIType CGDebugInfo::createFieldType(StringRef name,
|
2011-02-23 06:38:33 +08:00
|
|
|
QualType type,
|
2011-10-11 02:28:20 +08:00
|
|
|
uint64_t sizeInBitsOverride,
|
2011-02-23 06:38:33 +08:00
|
|
|
SourceLocation loc,
|
|
|
|
AccessSpecifier AS,
|
|
|
|
uint64_t offsetInBits,
|
2011-06-25 06:00:59 +08:00
|
|
|
llvm::DIFile tunit,
|
|
|
|
llvm::DIDescriptor scope) {
|
2011-02-23 06:38:33 +08:00
|
|
|
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);
|
|
|
|
|
2011-10-11 02:28:20 +08:00
|
|
|
if (sizeInBitsOverride)
|
|
|
|
sizeInBits = sizeInBitsOverride;
|
2011-02-23 06:38:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned flags = 0;
|
|
|
|
if (AS == clang::AS_private)
|
|
|
|
flags |= llvm::DIDescriptor::FlagPrivate;
|
|
|
|
else if (AS == clang::AS_protected)
|
|
|
|
flags |= llvm::DIDescriptor::FlagProtected;
|
|
|
|
|
2011-06-25 06:00:59 +08:00
|
|
|
return DBuilder.createMemberType(scope, name, file, line, sizeInBits,
|
|
|
|
alignInBits, offsetInBits, flags, debugType);
|
2011-02-23 06:38:33 +08:00
|
|
|
}
|
|
|
|
|
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,
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVectorImpl<llvm::Value *> &elements,
|
2011-06-25 06:00:59 +08:00
|
|
|
llvm::DIType RecordTy) {
|
2011-02-23 06:38:33 +08:00
|
|
|
unsigned fieldNo = 0;
|
2011-04-29 07:43:23 +08:00
|
|
|
const FieldDecl *LastFD = 0;
|
|
|
|
bool IsMsStruct = record->hasAttr<MsStructAttr>();
|
|
|
|
|
2011-02-23 06:38:33 +08:00
|
|
|
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;
|
2011-04-29 07:43:23 +08:00
|
|
|
if (IsMsStruct) {
|
|
|
|
// Zero-length bitfields following non-bitfield members are ignored
|
2011-05-04 04:21:04 +08:00
|
|
|
if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD)) {
|
2011-04-29 07:43:23 +08:00
|
|
|
--fieldNo;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
LastFD = field;
|
|
|
|
}
|
2011-02-23 06:38:33 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef name = field->getName();
|
2011-02-23 06:38:33 +08:00
|
|
|
QualType type = field->getType();
|
|
|
|
|
|
|
|
// Ignore unnamed fields unless they're anonymous structs/unions.
|
2011-04-29 07:43:23 +08:00
|
|
|
if (name.empty() && !type->isRecordType()) {
|
|
|
|
LastFD = field;
|
2010-01-19 08:00:59 +08:00
|
|
|
continue;
|
2011-04-29 07:43:23 +08:00
|
|
|
}
|
2010-01-19 08:00:59 +08:00
|
|
|
|
2011-10-11 02:28:20 +08:00
|
|
|
uint64_t SizeInBitsOverride = 0;
|
|
|
|
if (field->isBitField()) {
|
|
|
|
SizeInBitsOverride = field->getBitWidthValue(CGM.getContext());
|
|
|
|
assert(SizeInBitsOverride && "found named 0-width bitfield");
|
|
|
|
}
|
|
|
|
|
2011-02-23 06:38:33 +08:00
|
|
|
llvm::DIType fieldType
|
2011-10-11 02:28:20 +08:00
|
|
|
= createFieldType(name, type, SizeInBitsOverride,
|
2011-02-23 06:38:33 +08:00
|
|
|
field->getLocation(), field->getAccess(),
|
2011-06-25 06:00:59 +08:00
|
|
|
layout.getFieldOffset(fieldNo), tunit, RecordTy);
|
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!");
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
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));
|
|
|
|
|
2011-09-14 09:10:50 +08:00
|
|
|
if (!Method->isStatic()) {
|
|
|
|
// "this" pointer is always first argument.
|
|
|
|
QualType ThisPtr = Method->getThisType(CGM.getContext());
|
2011-10-29 05:12:13 +08:00
|
|
|
|
|
|
|
const CXXRecordDecl *RD = Method->getParent();
|
|
|
|
if (isa<ClassTemplateSpecializationDecl>(RD)) {
|
|
|
|
// Create pointer type directly in this case.
|
|
|
|
const PointerType *ThisPtrTy = cast<PointerType>(ThisPtr);
|
|
|
|
QualType PointeeTy = ThisPtrTy->getPointeeType();
|
|
|
|
unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
|
|
|
|
uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy);
|
2011-11-09 12:25:21 +08:00
|
|
|
llvm::DIType PointeeType = getOrCreateType(PointeeTy, Unit);
|
2011-10-29 05:12:13 +08:00
|
|
|
llvm::DIType ThisPtrType =
|
|
|
|
DBuilder.createArtificialType
|
|
|
|
(DBuilder.createPointerType(PointeeType, Size, Align));
|
|
|
|
TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
|
|
|
|
Elts.push_back(ThisPtrType);
|
|
|
|
} else {
|
|
|
|
llvm::DIType ThisPtrType =
|
|
|
|
DBuilder.createArtificialType(getOrCreateType(ThisPtr, Unit));
|
|
|
|
TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
|
|
|
|
Elts.push_back(ThisPtrType);
|
|
|
|
}
|
2011-09-14 09:10:50 +08:00
|
|
|
}
|
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));
|
|
|
|
|
2011-04-24 18:11:03 +08:00
|
|
|
llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
|
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) {
|
2011-11-10 08:34:02 +08:00
|
|
|
if (const CXXRecordDecl *NRD = dyn_cast<CXXRecordDecl>(RD->getDeclContext()))
|
2010-10-23 01:11:50 +08:00
|
|
|
return isFunctionLocalClass(NRD);
|
2011-11-10 08:34:02 +08:00
|
|
|
if (isa<FunctionDecl>(RD->getDeclContext()))
|
2010-10-23 01:11:50 +08:00
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
2011-11-09 12:25:21 +08:00
|
|
|
|
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);
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
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.
|
2011-07-23 18:55:15 +08:00
|
|
|
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))
|
2011-09-26 09:56:30 +08:00
|
|
|
VIndex = CGM.getVTableContext().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-09-02 05:49:51 +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
|
|
|
|
2011-11-18 07:45:00 +08:00
|
|
|
SPCache[Method->getCanonicalDecl()] = 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
|
2012-01-12 09:26:51 +08:00
|
|
|
/// C++ member functions. This is used while creating debug info entry for
|
2010-01-19 09:54:44 +08:00
|
|
|
/// a Record.
|
|
|
|
void CGDebugInfo::
|
2010-03-09 08:44:50 +08:00
|
|
|
CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
|
2011-07-23 18:55:15 +08:00
|
|
|
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,
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVectorImpl<llvm::Value *> &EltTys,
|
2010-08-28 01:47:47 +08:00
|
|
|
llvm::DIType RecordTy) {
|
2012-01-12 09:26:58 +08:00
|
|
|
for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(),
|
2010-08-28 01:47:47 +08:00
|
|
|
BE = RD->friend_end(); BI != BE; ++BI) {
|
2011-09-02 05:49:51 +08:00
|
|
|
if ((*BI)->isUnsupportedFriend())
|
|
|
|
continue;
|
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,
|
2011-07-23 18:55:15 +08:00
|
|
|
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 =
|
2011-09-26 09:56:30 +08:00
|
|
|
0 - CGM.getVTableContext()
|
|
|
|
.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-07-23 18:55:15 +08:00
|
|
|
SmallVector<llvm::Value *, 16> TemplateParams;
|
2011-04-06 04:15:06 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2011-04-24 18:11:03 +08:00
|
|
|
return DBuilder.getOrCreateArray(TemplateParams);
|
2011-04-06 01:30:54 +08:00
|
|
|
}
|
|
|
|
|
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) {
|
2011-10-12 07:00:51 +08:00
|
|
|
if (FD->getTemplatedKind() ==
|
|
|
|
FunctionDecl::TK_FunctionTemplateSpecialization) {
|
2011-04-06 06:54:11 +08:00
|
|
|
const TemplateParameterList *TList =
|
2011-10-12 07:00:51 +08:00
|
|
|
FD->getTemplateSpecializationInfo()->getTemplate()
|
|
|
|
->getTemplateParameters();
|
2011-04-06 06:54:11 +08:00
|
|
|
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-04-24 18:11:03 +08:00
|
|
|
llvm::DIArray SElements = DBuilder.getOrCreateArray(STy);
|
2011-02-23 02:56:36 +08:00
|
|
|
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.
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
|
2012-01-26 05:47:09 +08:00
|
|
|
// 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());
|
2011-07-23 18:55:15 +08:00
|
|
|
return StringRef(StrPtr, Name.length());
|
2010-01-29 02:11:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
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,
|
2011-07-23 18:55:15 +08:00
|
|
|
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-06-25 06:00:59 +08:00
|
|
|
= DBuilder.createMemberType(Unit, 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) {
|
2011-11-09 12:25:21 +08:00
|
|
|
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();
|
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());
|
2012-01-26 10:05:28 +08:00
|
|
|
StringRef RDName = RD->getName();
|
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.
|
2012-01-21 06:10:15 +08:00
|
|
|
|
2012-01-26 10:05:28 +08:00
|
|
|
llvm::DIDescriptor RDContext;
|
2012-01-21 06:10:15 +08:00
|
|
|
if (CGM.getCodeGenOpts().LimitDebugInfo)
|
2012-01-26 10:05:28 +08:00
|
|
|
RDContext = createContextChain(cast<Decl>(RD->getDeclContext()));
|
2012-01-21 06:10:15 +08:00
|
|
|
else
|
2012-01-26 10:05:28 +08:00
|
|
|
RDContext = 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.
|
2012-01-26 15:11:58 +08:00
|
|
|
if (!RD->getDefinition())
|
|
|
|
return createRecordFwdDecl(RD, RDContext);
|
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.
|
2011-09-29 08:00:45 +08:00
|
|
|
LexicalBlockStack.push_back(FwdDeclNode);
|
2010-05-08 02:12:35 +08:00
|
|
|
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
// Convert all the elements.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<llvm::Value *, 16> EltTys;
|
2008-11-10 14:08:34 +08:00
|
|
|
|
2012-01-26 15:01:04 +08:00
|
|
|
// Note: The split of CXXDecl information here is intentional, the
|
|
|
|
// gdb tests will depend on a certain ordering at printout. The debug
|
|
|
|
// information offsets are still correct if we merge them all together
|
|
|
|
// though.
|
2012-01-26 09:57:29 +08:00
|
|
|
const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
|
2010-01-29 02:11:52 +08:00
|
|
|
if (CXXDecl) {
|
2012-01-26 14:20:57 +08:00
|
|
|
CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl);
|
|
|
|
CollectVTableInfo(CXXDecl, DefUnit, EltTys);
|
2012-01-26 15:01:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Collect static variables with initializers and other fields.
|
|
|
|
CollectRecordStaticVars(RD, FwdDecl);
|
|
|
|
CollectRecordFields(RD, DefUnit, EltTys, FwdDecl);
|
|
|
|
llvm::DIArray TParamsArray;
|
|
|
|
if (CXXDecl) {
|
2012-01-26 14:20:57 +08:00
|
|
|
CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl);
|
|
|
|
CollectCXXFriends(CXXDecl, DefUnit, EltTys, FwdDecl);
|
2011-04-06 01:30:54 +08:00
|
|
|
if (const ClassTemplateSpecializationDecl *TSpecial
|
|
|
|
= dyn_cast<ClassTemplateSpecializationDecl>(RD))
|
2012-01-26 14:20:57 +08:00
|
|
|
TParamsArray = CollectCXXTemplateParams(TSpecial, DefUnit);
|
2010-12-09 06:42:58 +08:00
|
|
|
}
|
2010-01-28 08:54:21 +08:00
|
|
|
|
2011-09-29 08:00:45 +08:00
|
|
|
LexicalBlockStack.pop_back();
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI =
|
|
|
|
RegionMap.find(Ty->getDecl());
|
|
|
|
if (RI != RegionMap.end())
|
|
|
|
RegionMap.erase(RI);
|
|
|
|
|
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
2011-04-24 18:11:03 +08:00
|
|
|
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
|
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 =
|
2012-01-26 14:20:57 +08:00
|
|
|
getOrCreateType(QualType(PBase->getTypeForDecl(), 0), DefUnit);
|
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-12-17 07:40:14 +08:00
|
|
|
// FIXME: This could be a struct type giving a default visibility different
|
|
|
|
// than C++ class type, but needs llvm metadata changes first.
|
|
|
|
RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line,
|
|
|
|
Size, Align, 0, 0, llvm::DIType(),
|
|
|
|
Elements, ContainingType,
|
|
|
|
TParamsArray);
|
|
|
|
} else
|
2011-03-01 06:32:45 +08:00
|
|
|
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);
|
2012-01-21 06:10:15 +08:00
|
|
|
RegionMap[Ty->getDecl()] = 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
|
|
|
|
2011-10-06 08:31:18 +08:00
|
|
|
// If this is just a forward declaration return a special forward-declaration
|
|
|
|
// debug type since we won't be able to lay out the entire type.
|
2011-12-16 07:32:29 +08:00
|
|
|
ObjCInterfaceDecl *Def = ID->getDefinition();
|
|
|
|
if (!Def) {
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::DIType FwdDecl =
|
2011-02-23 02:56:36 +08:00
|
|
|
DBuilder.createStructType(Unit, ID->getName(),
|
2011-11-30 07:57:40 +08:00
|
|
|
DefUnit, Line, 0, 0,
|
|
|
|
llvm::DIDescriptor::FlagFwdDecl,
|
2010-12-09 06:42:58 +08:00
|
|
|
llvm::DIArray(), RuntimeLang);
|
2010-08-24 05:15:56 +08:00
|
|
|
return FwdDecl;
|
|
|
|
}
|
2011-12-16 07:32:29 +08:00
|
|
|
ID = Def;
|
2010-08-24 05:15:56 +08:00
|
|
|
|
2011-10-06 08:30:52 +08:00
|
|
|
// To handle a 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.
|
2011-09-29 08:00:45 +08:00
|
|
|
LexicalBlockStack.push_back(FwdDeclNode);
|
2010-05-08 02:12:35 +08:00
|
|
|
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
// Convert all the elements.
|
2011-07-23 18:55:15 +08:00
|
|
|
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);
|
2011-09-20 02:54:16 +08:00
|
|
|
ObjCImplementationDecl *ImpD = ID->getImplementation();
|
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();
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
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.
|
2011-10-11 02:28:20 +08:00
|
|
|
FieldSize = Field->isBitField()
|
|
|
|
? Field->getBitWidthValue(CGM.getContext())
|
|
|
|
: CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2009-03-21 02:24:39 +08:00
|
|
|
}
|
2009-03-19 08:23:53 +08:00
|
|
|
|
2011-10-06 08:31:18 +08:00
|
|
|
// We can't know the offset of our ivar in the structure if we're using
|
|
|
|
// the non-fragile abi and the debugger should ignore the value anyways.
|
|
|
|
// Call it the FieldNo+1 due to how debuggers use the information,
|
|
|
|
// e.g. negating the value when it needs a lookup in the dynamic table.
|
|
|
|
uint64_t FieldOffset = CGM.getLangOptions().ObjCNonFragileABI ? FieldNo+1
|
|
|
|
: RL.getFieldOffset(FieldNo);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
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-07-23 18:55:15 +08:00
|
|
|
StringRef PropertyName;
|
|
|
|
StringRef PropertyGetter;
|
|
|
|
StringRef PropertySetter;
|
2011-04-17 14:40:15 +08:00
|
|
|
unsigned PropertyAttributes = 0;
|
2011-09-20 02:54:16 +08:00
|
|
|
ObjCPropertyDecl *PD = NULL;
|
|
|
|
if (ImpD)
|
|
|
|
if (ObjCPropertyImplDecl *PImpD =
|
2011-10-12 07:00:51 +08:00
|
|
|
ImpD->FindPropertyImplIvarDecl(Field->getIdentifier()))
|
|
|
|
PD = PImpD->getPropertyDecl();
|
2011-09-20 02:54:16 +08:00
|
|
|
if (PD) {
|
2011-04-16 08:12:55 +08:00
|
|
|
PropertyName = PD->getName();
|
2011-04-16 08:37:51 +08:00
|
|
|
PropertyGetter = getSelectorName(PD->getGetterName());
|
|
|
|
PropertySetter = getSelectorName(PD->getSetterName());
|
2011-04-16 08:12:55 +08:00
|
|
|
PropertyAttributes = PD->getPropertyAttributes();
|
2011-09-20 02:54:16 +08:00
|
|
|
}
|
2011-04-16 08:12:55 +08:00
|
|
|
FieldTy = DBuilder.createObjCIVar(FieldName, FieldDefUnit,
|
|
|
|
FieldLine, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, Flags, FieldTy,
|
|
|
|
PropertyName, PropertyGetter,
|
|
|
|
PropertySetter, PropertyAttributes);
|
2009-02-27 05:10:26 +08:00
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-04-24 18:11:03 +08:00
|
|
|
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2011-09-29 08:00:45 +08:00
|
|
|
LexicalBlockStack.pop_back();
|
2010-03-12 04:01:48 +08:00
|
|
|
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
|
|
|
|
2011-05-13 03:07:41 +08:00
|
|
|
unsigned Flags = 0;
|
2011-05-13 05:14:54 +08:00
|
|
|
if (ID->getImplementation())
|
2011-05-13 05:29:57 +08:00
|
|
|
Flags |= llvm::DIDescriptor::FlagObjcClassComplete;
|
2011-05-13 03:07:41 +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,
|
2011-05-13 03:07:41 +08:00
|
|
|
Line, Size, Align, Flags,
|
2010-12-09 06:42:58 +08:00
|
|
|
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-11-09 12:25:21 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, 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-04-24 18:11:03 +08:00
|
|
|
llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
|
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?
|
2011-07-23 18:55:15 +08:00
|
|
|
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-10-12 07:00:51 +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
|
|
|
|
2011-04-24 18:11:03 +08:00
|
|
|
llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts);
|
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-06-25 06:00:59 +08:00
|
|
|
DBuilder.createMemberType(U, "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-06-25 06:00:59 +08:00
|
|
|
DBuilder.createMemberType(U, "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
|
|
|
|
2011-04-24 18:11:03 +08:00
|
|
|
llvm::DIArray Elements = DBuilder.getOrCreateArray(ElementTypes);
|
2009-12-07 02:00:51 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
return DBuilder.createStructType(U, StringRef("test"),
|
2010-12-09 06:42:58 +08:00
|
|
|
U, 0, FieldOffset,
|
|
|
|
0, 0, Elements);
|
2009-12-07 02:00:51 +08:00
|
|
|
}
|
|
|
|
|
2011-10-07 07:00:33 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty,
|
|
|
|
llvm::DIFile U) {
|
|
|
|
// Ignore the atomic wrapping
|
|
|
|
// FIXME: What is the correct representation?
|
|
|
|
return getOrCreateType(Ty->getValueType(), U);
|
|
|
|
}
|
|
|
|
|
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());
|
2011-07-23 18:55:15 +08:00
|
|
|
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.
|
2011-04-24 18:11:03 +08:00
|
|
|
llvm::DIArray EltArray = DBuilder.getOrCreateArray(Enumerators);
|
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-05-25 06:41:36 +08:00
|
|
|
case Type::UnaryTransform:
|
|
|
|
T = cast<UnaryTransformType>(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);
|
2009-11-15 05:08:12 +08:00
|
|
|
}
|
|
|
|
|
2011-12-17 07:40:18 +08:00
|
|
|
/// getType - Get the type from the cache or return null type if it doesn't exist.
|
|
|
|
llvm::DIType CGDebugInfo::getTypeOrNull(QualType Ty) {
|
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-12-17 07:40:18 +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
|
|
|
|
2011-12-17 07:40:18 +08:00
|
|
|
return llvm::DIType();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getOrCreateType - Get the type from the cache or create a new
|
|
|
|
/// one if necessary.
|
|
|
|
llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
|
|
|
|
if (Ty.isNull())
|
|
|
|
return llvm::DIType();
|
|
|
|
|
|
|
|
// Unwrap the type as needed for debug information.
|
|
|
|
Ty = UnwrapTypeForDebugInfo(Ty);
|
|
|
|
|
|
|
|
llvm::DIType T = getTypeOrNull(Ty);
|
|
|
|
if (T.Verify()) return T;
|
|
|
|
|
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.
|
2011-11-09 12:27:23 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, 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"
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Dependent types cannot show up in debug information");
|
2009-08-19 09:28:17 +08:00
|
|
|
|
2009-11-07 02:24:04 +08:00
|
|
|
case Type::ExtVector:
|
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);
|
2011-11-09 12:25:21 +08:00
|
|
|
case Type::Builtin:
|
|
|
|
return CreateType(cast<BuiltinType>(Ty));
|
|
|
|
case Type::Complex:
|
|
|
|
return CreateType(cast<ComplexType>(Ty));
|
|
|
|
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);
|
2011-11-09 12:25:21 +08:00
|
|
|
case Type::Typedef:
|
|
|
|
return CreateType(cast<TypedefType>(Ty), Unit);
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::Record:
|
2011-11-09 12:25:21 +08:00
|
|
|
return CreateType(cast<RecordType>(Ty));
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::Enum:
|
2011-11-09 12:25:21 +08:00
|
|
|
return CreateEnumType(cast<EnumType>(Ty)->getDecl());
|
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-10-07 07:00:33 +08:00
|
|
|
case Type::Atomic:
|
|
|
|
return CreateType(cast<AtomicType>(Ty), Unit);
|
|
|
|
|
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-05-25 06:41:36 +08:00
|
|
|
case Type::UnaryTransform:
|
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!");
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
2009-12-22 03:57:21 +08:00
|
|
|
|
|
|
|
assert(Diag && "Fall through without a diagnostic?");
|
2011-09-26 07:23:43 +08:00
|
|
|
unsigned DiagID = CGM.getDiags().getCustomDiagID(DiagnosticsEngine::Error,
|
2009-12-22 03:57:21 +08:00
|
|
|
"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,
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef Name,
|
2010-04-25 04:19:58 +08:00
|
|
|
uint64_t *Offset) {
|
|
|
|
llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2011-06-25 06:00:59 +08:00
|
|
|
llvm::DIType Ty = DBuilder.createMemberType(Unit, 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;
|
|
|
|
}
|
|
|
|
|
2011-04-23 08:08:01 +08:00
|
|
|
/// getFunctionDeclaration - Return debug info descriptor to describe method
|
|
|
|
/// declaration for the given method definition.
|
|
|
|
llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) {
|
|
|
|
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
|
|
|
|
if (!FD) return llvm::DISubprogram();
|
|
|
|
|
|
|
|
// Setup context.
|
|
|
|
getContextDescriptor(cast<Decl>(D->getDeclContext()));
|
|
|
|
|
2011-04-30 07:42:32 +08:00
|
|
|
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
|
2011-11-18 07:45:00 +08:00
|
|
|
MI = SPCache.find(FD->getCanonicalDecl());
|
2011-04-30 07:42:32 +08:00
|
|
|
if (MI != SPCache.end()) {
|
|
|
|
llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(&*MI->second));
|
|
|
|
if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition())
|
|
|
|
return SP;
|
|
|
|
}
|
|
|
|
|
2011-04-23 08:08:01 +08:00
|
|
|
for (FunctionDecl::redecl_iterator I = FD->redecls_begin(),
|
|
|
|
E = FD->redecls_end(); I != E; ++I) {
|
|
|
|
const FunctionDecl *NextFD = *I;
|
|
|
|
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
|
2011-11-18 07:45:00 +08:00
|
|
|
MI = SPCache.find(NextFD->getCanonicalDecl());
|
2011-04-23 08:08:01 +08:00
|
|
|
if (MI != SPCache.end()) {
|
|
|
|
llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(&*MI->second));
|
|
|
|
if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition())
|
|
|
|
return SP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return llvm::DISubprogram();
|
|
|
|
}
|
|
|
|
|
2011-06-01 04:46:46 +08:00
|
|
|
// getOrCreateFunctionType - Construct DIType. If it is a c++ method, include
|
|
|
|
// implicit parameter "this".
|
2011-10-12 07:00:51 +08:00
|
|
|
llvm::DIType CGDebugInfo::getOrCreateFunctionType(const Decl * D,
|
|
|
|
QualType FnType,
|
2011-06-01 04:46:46 +08:00
|
|
|
llvm::DIFile F) {
|
|
|
|
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
|
|
|
|
return getOrCreateMethodType(Method, F);
|
2011-11-10 08:34:02 +08:00
|
|
|
if (const ObjCMethodDecl *OMethod = dyn_cast<ObjCMethodDecl>(D)) {
|
2011-06-01 05:18:50 +08:00
|
|
|
// Add "self" and "_cmd"
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<llvm::Value *, 16> Elts;
|
2011-06-01 05:18:50 +08:00
|
|
|
|
|
|
|
// First element is always return type. For 'void' functions it is NULL.
|
2011-06-01 06:21:11 +08:00
|
|
|
Elts.push_back(getOrCreateType(OMethod->getResultType(), F));
|
2011-06-01 05:18:50 +08:00
|
|
|
// "self" pointer is always first argument.
|
|
|
|
Elts.push_back(getOrCreateType(OMethod->getSelfDecl()->getType(), F));
|
|
|
|
// "cmd" pointer is always second argument.
|
|
|
|
Elts.push_back(getOrCreateType(OMethod->getCmdDecl()->getType(), F));
|
2011-06-01 06:21:11 +08:00
|
|
|
// Get rest of the arguments.
|
2011-10-03 14:37:04 +08:00
|
|
|
for (ObjCMethodDecl::param_const_iterator PI = OMethod->param_begin(),
|
2011-06-01 06:21:11 +08:00
|
|
|
PE = OMethod->param_end(); PI != PE; ++PI)
|
|
|
|
Elts.push_back(getOrCreateType((*PI)->getType(), F));
|
|
|
|
|
2011-06-01 05:18:50 +08:00
|
|
|
llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
|
|
|
|
return DBuilder.createSubroutineType(F, EltTypeArray);
|
|
|
|
}
|
2011-06-01 04:46:46 +08:00
|
|
|
return getOrCreateType(FnType, F);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef Name;
|
|
|
|
StringRef LinkageName;
|
2010-01-14 08:36:21 +08:00
|
|
|
|
2011-09-29 08:00:45 +08:00
|
|
|
FnBeginRegionCount.push_back(LexicalBlockStack.size());
|
2010-07-23 06:29:16 +08:00
|
|
|
|
2010-01-14 08:36:21 +08:00
|
|
|
const Decl *D = GD.getDecl();
|
2011-10-14 05:45:18 +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)) {
|
2011-11-15 02:55:02 +08:00
|
|
|
// If there is a DISubprogram for this function available then use it.
|
2010-01-19 09:54:44 +08:00
|
|
|
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
|
2011-11-18 07:45:00 +08:00
|
|
|
FI = SPCache.find(FD->getCanonicalDecl());
|
2010-01-19 09:54:44 +08:00
|
|
|
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;
|
2011-09-29 08:00:45 +08:00
|
|
|
LexicalBlockStack.push_back(SPN);
|
2010-05-08 02:12:35 +08:00
|
|
|
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.
|
2011-05-03 06:49:30 +08:00
|
|
|
if (!Fn->hasInternalLinkage())
|
2011-05-03 06:37:48 +08:00
|
|
|
LinkageName = CGM.getMangledName(GD);
|
2010-10-23 01:11:50 +08:00
|
|
|
if (LinkageName == Name)
|
2011-07-23 18:55:15 +08:00
|
|
|
LinkageName = 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-05-17 08:20:09 +08:00
|
|
|
else if (const RecordDecl *RDecl =
|
|
|
|
dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))
|
|
|
|
FDContext = getContextDescriptor(cast<Decl>(RDecl->getDeclContext()));
|
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;
|
2011-04-23 08:08:01 +08:00
|
|
|
llvm::DISubprogram SPDecl = getFunctionDeclaration(D);
|
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,
|
2011-06-01 04:46:46 +08:00
|
|
|
LineNo, getOrCreateFunctionType(D, FnType, Unit),
|
2010-12-09 06:42:58 +08:00
|
|
|
Fn->hasInternalLinkage(), true/*definition*/,
|
2011-04-06 06:54:11 +08:00
|
|
|
Flags, CGM.getLangOptions().Optimize, Fn,
|
2011-04-23 08:08:01 +08:00
|
|
|
TParamsArray, SPDecl);
|
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;
|
2011-09-29 08:00:45 +08:00
|
|
|
LexicalBlockStack.push_back(SPN);
|
2010-05-08 02:12:35 +08:00
|
|
|
RegionMap[D] = llvm::WeakVH(SP);
|
2010-07-23 06:29:16 +08:00
|
|
|
}
|
2011-09-29 08:00:31 +08:00
|
|
|
|
2011-09-29 08:00:41 +08:00
|
|
|
/// EmitLocation - Emit metadata to indicate a change in line/column
|
|
|
|
/// information in the source file.
|
2011-10-14 05:45:18 +08:00
|
|
|
void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
|
|
|
|
|
|
|
|
// Update our current location
|
|
|
|
setLocation(Loc);
|
|
|
|
|
2011-09-29 08:00:37 +08:00
|
|
|
if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;
|
|
|
|
|
|
|
|
// Don't bother if things are the same as last time.
|
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2011-10-14 05:45:18 +08:00
|
|
|
if (CurLoc == PrevLoc ||
|
2011-09-29 08:00:37 +08:00
|
|
|
SM.getExpansionLoc(CurLoc) == SM.getExpansionLoc(PrevLoc))
|
|
|
|
// New Builder may not be in sync with CGDebugInfo.
|
|
|
|
if (!Builder.getCurrentDebugLocation().isUnknown())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Update last state.
|
|
|
|
PrevLoc = CurLoc;
|
|
|
|
|
2011-09-29 08:00:45 +08:00
|
|
|
llvm::MDNode *Scope = LexicalBlockStack.back();
|
2011-09-29 08:00:37 +08:00
|
|
|
Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(CurLoc),
|
|
|
|
getColumnNumber(CurLoc),
|
|
|
|
Scope));
|
|
|
|
}
|
|
|
|
|
2011-10-14 05:45:18 +08:00
|
|
|
/// CreateLexicalBlock - Creates a new lexical block node and pushes it on
|
|
|
|
/// the stack.
|
|
|
|
void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) {
|
2009-11-14 03:10:24 +08:00
|
|
|
llvm::DIDescriptor D =
|
2011-10-14 05:45:18 +08:00
|
|
|
DBuilder.createLexicalBlock(LexicalBlockStack.empty() ?
|
|
|
|
llvm::DIDescriptor() :
|
|
|
|
llvm::DIDescriptor(LexicalBlockStack.back()),
|
|
|
|
getOrCreateFile(CurLoc),
|
|
|
|
getLineNumber(CurLoc),
|
|
|
|
getColumnNumber(CurLoc));
|
2010-05-08 02:12:35 +08:00
|
|
|
llvm::MDNode *DN = D;
|
2011-09-29 08:00:45 +08:00
|
|
|
LexicalBlockStack.push_back(DN);
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2011-10-14 05:45:18 +08:00
|
|
|
/// EmitLexicalBlockStart - Constructs the debug code for entering a declarative
|
|
|
|
/// region - beginning of a DW_TAG_lexical_block.
|
|
|
|
void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc) {
|
|
|
|
// Set our current location.
|
|
|
|
setLocation(Loc);
|
|
|
|
|
|
|
|
// Create a new lexical block and push it on the stack.
|
|
|
|
CreateLexicalBlock(Loc);
|
|
|
|
|
|
|
|
// Emit a line table change for the current location inside the new scope.
|
|
|
|
Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(Loc),
|
|
|
|
getColumnNumber(Loc),
|
|
|
|
LexicalBlockStack.back()));
|
|
|
|
}
|
|
|
|
|
2011-09-29 08:00:45 +08:00
|
|
|
/// EmitLexicalBlockEnd - Constructs the debug code for exiting a declarative
|
2011-09-26 23:03:22 +08:00
|
|
|
/// region - end of a DW_TAG_lexical_block.
|
2011-10-14 05:45:18 +08:00
|
|
|
void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc) {
|
2011-09-29 08:00:45 +08:00
|
|
|
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
|
2008-10-17 09:07:56 +08:00
|
|
|
|
2011-10-14 05:45:18 +08:00
|
|
|
// Provide an entry in the line table for the end of the block.
|
|
|
|
EmitLocation(Builder, Loc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-09-29 08:00:45 +08:00
|
|
|
LexicalBlockStack.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) {
|
2011-09-29 08:00:45 +08:00
|
|
|
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
|
2010-07-23 06:29:16 +08:00
|
|
|
unsigned RCount = FnBeginRegionCount.back();
|
2011-09-29 08:00:45 +08:00
|
|
|
assert(RCount <= LexicalBlockStack.size() && "Region stack mismatch");
|
2010-07-23 06:29:16 +08:00
|
|
|
|
|
|
|
// Pop all regions for this function.
|
2011-09-29 08:00:45 +08:00
|
|
|
while (LexicalBlockStack.size() != RCount)
|
2011-10-14 05:45:18 +08:00
|
|
|
EmitLexicalBlockEnd(Builder, CurLoc);
|
2010-07-23 06:29:16 +08:00
|
|
|
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
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
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);
|
2011-04-23 01:34:18 +08:00
|
|
|
if (Align > CGM.getContext().toCharUnitsFromBits(
|
2011-09-02 08:18:52 +08:00
|
|
|
CGM.getContext().getTargetInfo().getPointerAlign(0))) {
|
2011-04-23 01:34:18 +08:00
|
|
|
CharUnits FieldOffsetInBytes
|
|
|
|
= CGM.getContext().toCharUnitsFromBits(FieldOffset);
|
|
|
|
CharUnits AlignedOffsetInBytes
|
|
|
|
= FieldOffsetInBytes.RoundUpToAlignment(Align);
|
|
|
|
CharUnits NumPaddingBytes
|
|
|
|
= AlignedOffsetInBytes - FieldOffsetInBytes;
|
2009-09-22 10:12:52 +08:00
|
|
|
|
2011-04-23 01:34:18 +08:00
|
|
|
if (NumPaddingBytes.isPositive()) {
|
|
|
|
llvm::APInt pad(32, NumPaddingBytes.getQuantity());
|
2010-02-11 02:49:08 +08:00
|
|
|
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);
|
2011-04-23 01:34:18 +08:00
|
|
|
FieldAlign = CGM.getContext().toBits(Align);
|
2009-09-22 10:12:52 +08:00
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
*XOffset = FieldOffset;
|
2011-06-25 06:00:59 +08:00
|
|
|
FieldTy = DBuilder.createMemberType(Unit, 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;
|
|
|
|
|
2011-04-24 18:11:03 +08:00
|
|
|
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
|
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) {
|
2011-09-29 08:00:45 +08:00
|
|
|
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
|
2010-02-11 02:49:08 +08:00
|
|
|
|
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.
|
2011-10-12 07:00:51 +08:00
|
|
|
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;
|
2011-09-29 08:00:45 +08:00
|
|
|
llvm::MDNode *Scope = LexicalBlockStack.back();
|
2010-10-13 07:24:54 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef Name = VD->getName();
|
2010-10-13 07:24:54 +08:00
|
|
|
if (!Name.empty()) {
|
2011-01-11 08:30:27 +08:00
|
|
|
if (VD->hasAttr<BlocksAttr>()) {
|
|
|
|
CharUnits offset = CharUnits::fromQuantity(32);
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<llvm::Value *, 9> addr;
|
2011-07-18 12:24:23 +08:00
|
|
|
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
|
2011-04-23 01:41:34 +08:00
|
|
|
offset = CGM.getContext().toCharUnitsFromBits(
|
2011-09-02 08:18:52 +08:00
|
|
|
CGM.getContext().getTargetInfo().getPointerWidth(0));
|
2011-01-11 08:30:27 +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));
|
2011-01-11 08:30:27 +08:00
|
|
|
// offset of x field
|
2011-04-23 01:41:34 +08:00
|
|
|
offset = CGM.getContext().toCharUnitsFromBits(XOffset);
|
2011-01-11 08:30:27 +08:00
|
|
|
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-10-12 07:00:51 +08:00
|
|
|
llvm::DIDescriptor(Scope),
|
2011-01-11 08:30:27 +08:00
|
|
|
VD->getName(), Unit, Line, Ty,
|
2011-04-24 18:11:03 +08:00
|
|
|
addr, ArgNo);
|
2011-01-11 08:30:27 +08:00
|
|
|
|
2011-10-14 05:45:18 +08:00
|
|
|
// Insert an llvm.dbg.declare into the current block.
|
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);
|
2011-07-23 18:55:15 +08:00
|
|
|
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());
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2011-04-26 07:43:36 +08:00
|
|
|
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
|
|
|
|
llvm::Value *Storage,
|
|
|
|
CGBuilderTy &Builder) {
|
|
|
|
EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder);
|
|
|
|
}
|
2009-09-30 10:43:10 +08:00
|
|
|
|
2011-04-26 07:43:36 +08:00
|
|
|
void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
|
|
|
|
const VarDecl *VD, llvm::Value *Storage, CGBuilderTy &Builder,
|
|
|
|
const CGBlockInfo &blockInfo) {
|
2011-09-29 08:00:45 +08:00
|
|
|
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
|
2011-04-26 07:43:36 +08:00
|
|
|
|
2010-04-27 07:28:46 +08:00
|
|
|
if (Builder.GetInsertBlock() == 0)
|
2009-09-30 10:43:10 +08:00
|
|
|
return;
|
2011-04-26 07:43:36 +08:00
|
|
|
|
2011-02-07 18:33:21 +08:00
|
|
|
bool isByRef = VD->hasAttr<BlocksAttr>();
|
2011-04-26 07:43:36 +08:00
|
|
|
|
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()));
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<llvm::Value *, 9> addr;
|
2011-07-18 12:24:23 +08:00
|
|
|
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-10-12 07:00:51 +08:00
|
|
|
offset = CGM.getContext()
|
|
|
|
.toCharUnitsFromBits(target.getPointerSizeInBits());
|
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
|
2011-04-23 01:41:34 +08:00
|
|
|
offset = CGM.getContext().toCharUnitsFromBits(XOffset);
|
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-04-26 07:43:36 +08:00
|
|
|
DBuilder.createComplexVariable(llvm::dwarf::DW_TAG_auto_variable,
|
2011-09-29 08:00:45 +08:00
|
|
|
llvm::DIDescriptor(LexicalBlockStack.back()),
|
2011-04-24 18:11:03 +08:00
|
|
|
VD->getName(), Unit, Line, Ty, addr);
|
2009-09-30 10:43:10 +08:00
|
|
|
// Insert an llvm.dbg.declare into the current block.
|
2011-10-14 05:45:18 +08:00
|
|
|
llvm::Instruction *Call =
|
2011-04-26 07:52:27 +08:00
|
|
|
DBuilder.insertDeclare(Storage, D, Builder.GetInsertPoint());
|
2011-10-14 05:45:18 +08:00
|
|
|
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column,
|
|
|
|
LexicalBlockStack.back()));
|
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.
|
2011-05-02 09:41:48 +08:00
|
|
|
getContextDescriptor(cast<Decl>(blockDecl->getDeclContext()));
|
2011-02-23 06:38:33 +08:00
|
|
|
|
|
|
|
const llvm::StructLayout *blockLayout =
|
|
|
|
CGM.getTargetData().getStructLayout(block.StructureType);
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<llvm::Value*, 16> fields;
|
2011-02-23 06:38:33 +08:00
|
|
|
fields.push_back(createFieldType("__isa", C.VoidPtrTy, 0, loc, AS_public,
|
|
|
|
blockLayout->getElementOffsetInBits(0),
|
2011-06-25 06:00:59 +08:00
|
|
|
tunit, tunit));
|
2011-02-23 06:38:33 +08:00
|
|
|
fields.push_back(createFieldType("__flags", C.IntTy, 0, loc, AS_public,
|
|
|
|
blockLayout->getElementOffsetInBits(1),
|
2011-06-25 06:00:59 +08:00
|
|
|
tunit, tunit));
|
2011-02-23 06:38:33 +08:00
|
|
|
fields.push_back(createFieldType("__reserved", C.IntTy, 0, loc, AS_public,
|
|
|
|
blockLayout->getElementOffsetInBits(2),
|
2011-06-25 06:00:59 +08:00
|
|
|
tunit, tunit));
|
2011-02-23 06:38:33 +08:00
|
|
|
fields.push_back(createFieldType("__FuncPtr", C.VoidPtrTy, 0, loc, AS_public,
|
|
|
|
blockLayout->getElementOffsetInBits(3),
|
2011-06-25 06:00:59 +08:00
|
|
|
tunit, tunit));
|
2011-02-23 06:38:33 +08:00
|
|
|
fields.push_back(createFieldType("__descriptor",
|
|
|
|
C.getPointerType(block.NeedsCopyDispose ?
|
|
|
|
C.getBlockDescriptorExtendedType() :
|
|
|
|
C.getBlockDescriptorType()),
|
|
|
|
0, loc, AS_public,
|
|
|
|
blockLayout->getElementOffsetInBits(4),
|
2011-06-25 06:00:59 +08:00
|
|
|
tunit, tunit));
|
2011-02-23 06:38:33 +08:00
|
|
|
|
|
|
|
// We want to sort the captures by offset, not because DWARF
|
|
|
|
// requires this, but because we're paranoid about debuggers.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<BlockLayoutChunk, 8> chunks;
|
2011-02-23 06:38:33 +08:00
|
|
|
|
|
|
|
// '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());
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
for (SmallVectorImpl<BlockLayoutChunk>::iterator
|
2011-02-23 06:38:33 +08:00
|
|
|
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,
|
2011-06-25 06:00:59 +08:00
|
|
|
offsetInBits, tunit, tunit));
|
2011-02-23 06:38:33 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const VarDecl *variable = capture->getVariable();
|
2011-07-23 18:55:15 +08:00
|
|
|
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);
|
2011-06-25 06:00:59 +08:00
|
|
|
fieldType = DBuilder.createMemberType(tunit, name, tunit, line,
|
2011-03-02 14:57:14 +08:00
|
|
|
ptrInfo.first, ptrInfo.second,
|
|
|
|
offsetInBits, 0, fieldType);
|
|
|
|
} else {
|
|
|
|
fieldType = createFieldType(name, variable->getType(), 0,
|
2011-06-25 06:00:59 +08:00
|
|
|
loc, AS_public, offsetInBits, tunit, tunit);
|
2011-03-02 14:57:14 +08:00
|
|
|
}
|
|
|
|
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();
|
|
|
|
|
2011-04-24 18:11:03 +08:00
|
|
|
llvm::DIArray fieldsArray = DBuilder.getOrCreateArray(fields);
|
2011-02-23 06:38:33 +08:00
|
|
|
|
|
|
|
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;
|
2011-09-29 08:00:45 +08:00
|
|
|
llvm::MDNode *scope = LexicalBlockStack.back();
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef name = ".block_descriptor";
|
2011-02-23 06:38:33 +08:00
|
|
|
|
|
|
|
// 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());
|
2011-10-14 05:45:18 +08:00
|
|
|
|
|
|
|
setLocation(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,
|
2011-11-09 12:25:21 +08:00
|
|
|
ArrayType::Normal, 0);
|
2008-11-27 01:40:42 +08:00
|
|
|
}
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef DeclName = D->getName();
|
|
|
|
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)
|
2011-07-23 18:55:15 +08:00
|
|
|
LinkageName = 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
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
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());
|
2011-07-23 18:55:15 +08:00
|
|
|
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);
|
|
|
|
}
|