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"
|
2008-05-25 13:15:42 +08:00
|
|
|
#include "clang/AST/ASTContext.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"
|
2009-04-18 05:06:59 +08:00
|
|
|
#include "llvm/System/Path.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-03-09 08:44:50 +08:00
|
|
|
: CGM(CGM), DebugFactory(CGM.getModule()),
|
2010-03-10 05:32:27 +08:00
|
|
|
FwdDeclCount(0), BlockLiteralGenericSet(false) {
|
2010-03-09 08:44:50 +08:00
|
|
|
CreateCompileUnit();
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
CGDebugInfo::~CGDebugInfo() {
|
2008-10-18 00:15:48 +08:00
|
|
|
assert(RegionStack.empty() && "Region stack mismatch, stack not empty!");
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::setLocation(SourceLocation Loc) {
|
|
|
|
if (Loc.isValid())
|
2009-12-07 02:00:51 +08:00
|
|
|
CurLoc = CGM.getContext().getSourceManager().getInstantiationLoc(Loc);
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2010-01-29 07:15:27 +08:00
|
|
|
/// getContextDescriptor - Get context info for the decl.
|
2010-02-02 05:34:11 +08:00
|
|
|
llvm::DIDescriptor CGDebugInfo::getContextDescriptor(const Decl *Context,
|
2010-01-29 07:15:27 +08:00
|
|
|
llvm::DIDescriptor &CompileUnit) {
|
2010-02-02 05:34:11 +08:00
|
|
|
if (!Context)
|
|
|
|
return CompileUnit;
|
|
|
|
|
|
|
|
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));
|
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))
|
|
|
|
return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl, CompileUnit));
|
2010-05-14 07:52:37 +08:00
|
|
|
|
|
|
|
if (const RecordDecl *RDecl = dyn_cast<RecordDecl>(Context)) {
|
|
|
|
if (!RDecl->isDependentType()) {
|
|
|
|
llvm::DIType Ty = getOrCreateType(CGM.getContext().getTypeDeclType(RDecl),
|
|
|
|
llvm::DIFile(CompileUnit));
|
|
|
|
return llvm::DIDescriptor(Ty);
|
|
|
|
}
|
|
|
|
}
|
2009-10-06 08:35:31 +08:00
|
|
|
return CompileUnit;
|
|
|
|
}
|
|
|
|
|
2010-01-14 08:36:21 +08:00
|
|
|
/// getFunctionName - Get function name for the given FunctionDecl. If the
|
|
|
|
/// name is constructred on demand (e.g. C++ destructor) then the name
|
|
|
|
/// is stored on the side.
|
|
|
|
llvm::StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
|
|
|
|
assert (FD && "Invalid FunctionDecl!");
|
|
|
|
IdentifierInfo *FII = FD->getIdentifier();
|
|
|
|
if (FII)
|
|
|
|
return FII->getName();
|
|
|
|
|
|
|
|
// Otherwise construct human readable name for debug info.
|
|
|
|
std::string NS = FD->getNameAsString();
|
|
|
|
|
|
|
|
// Copy this name on the side and use its reference.
|
2010-01-29 02:21:00 +08:00
|
|
|
char *StrPtr = DebugInfoNames.Allocate<char>(NS.length());
|
2010-01-24 02:16:07 +08:00
|
|
|
memcpy(StrPtr, NS.data(), NS.length());
|
|
|
|
return llvm::StringRef(StrPtr, NS.length());
|
2010-01-14 08:36:21 +08:00
|
|
|
}
|
|
|
|
|
2010-07-21 04:24:18 +08:00
|
|
|
/// getClassName - Get class name including template argument list.
|
|
|
|
llvm::StringRef
|
|
|
|
CGDebugInfo::getClassName(RecordDecl *RD) {
|
|
|
|
ClassTemplateSpecializationDecl *Spec
|
|
|
|
= dyn_cast<ClassTemplateSpecializationDecl>(RD);
|
|
|
|
if (!Spec)
|
|
|
|
return RD->getName();
|
|
|
|
|
|
|
|
const TemplateArgument *Args;
|
|
|
|
unsigned NumArgs;
|
|
|
|
std::string Buffer;
|
|
|
|
if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
|
|
|
|
const TemplateSpecializationType *TST =
|
|
|
|
cast<TemplateSpecializationType>(TAW->getType());
|
|
|
|
Args = TST->getArgs();
|
|
|
|
NumArgs = TST->getNumArgs();
|
|
|
|
} else {
|
|
|
|
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
|
|
|
Args = TemplateArgs.getFlatArgumentList();
|
|
|
|
NumArgs = TemplateArgs.flat_size();
|
|
|
|
}
|
|
|
|
Buffer = RD->getIdentifier()->getNameStart();
|
|
|
|
PrintingPolicy Policy(CGM.getLangOptions());
|
|
|
|
Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
|
|
|
|
NumArgs,
|
|
|
|
Policy);
|
|
|
|
|
|
|
|
// Copy this name on the side and use its reference.
|
|
|
|
char *StrPtr = DebugInfoNames.Allocate<char>(Buffer.length());
|
|
|
|
memcpy(StrPtr, Buffer.data(), Buffer.length());
|
|
|
|
return llvm::StringRef(StrPtr, Buffer.length());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-03-09 08:44:50 +08:00
|
|
|
/// getOrCreateFile - Get the file debug info descriptor for the input location.
|
|
|
|
llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
|
2010-03-30 08:27:51 +08:00
|
|
|
if (!Loc.isValid())
|
2010-03-09 08:44:50 +08:00
|
|
|
// If Location is not valid then use main input file.
|
|
|
|
return DebugFactory.CreateFile(TheCU.getFilename(), TheCU.getDirectory(),
|
|
|
|
TheCU);
|
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
|
|
|
|
|
|
|
// 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));
|
|
|
|
}
|
|
|
|
|
2010-07-27 23:17:16 +08:00
|
|
|
llvm::DIFile F = DebugFactory.CreateFile(PLoc.getFilename(),
|
|
|
|
getCurrentDirname(), TheCU);
|
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
|
|
|
|
|
|
|
/// getLineNumber - Get line number for the location. If location is invalid
|
|
|
|
/// then use current location.
|
|
|
|
unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {
|
|
|
|
assert (CurLoc.isValid() && "Invalid current location!");
|
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc);
|
|
|
|
return PLoc.getLine();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getColumnNumber - Get column number for the location. If location is
|
|
|
|
/// invalid then use current location.
|
|
|
|
unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) {
|
|
|
|
assert (CurLoc.isValid() && "Invalid current location!");
|
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc);
|
|
|
|
return PLoc.getColumn();
|
|
|
|
}
|
|
|
|
|
2010-07-27 23:17:16 +08:00
|
|
|
llvm::StringRef CGDebugInfo::getCurrentDirname() {
|
|
|
|
if (!CWDName.empty())
|
|
|
|
return CWDName;
|
|
|
|
char *CompDirnamePtr = NULL;
|
|
|
|
llvm::sys::Path CWD = llvm::sys::Path::GetCurrentDirectory();
|
|
|
|
CompDirnamePtr = DebugInfoNames.Allocate<char>(CWD.size());
|
|
|
|
memcpy(CompDirnamePtr, CWD.c_str(), CWD.size());
|
|
|
|
return CWDName = llvm::StringRef(CompDirnamePtr, CWD.size());
|
|
|
|
}
|
|
|
|
|
2010-03-09 08:44:50 +08:00
|
|
|
/// CreateCompileUnit - Create new compile unit.
|
|
|
|
void CGDebugInfo::CreateCompileUnit() {
|
2009-04-08 13:11:16 +08:00
|
|
|
|
2009-04-18 05:06:59 +08:00
|
|
|
// Get absolute path name.
|
2010-03-19 07:46:43 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2010-03-19 22:49:09 +08:00
|
|
|
std::string MainFileName = CGM.getCodeGenOpts().MainFileName;
|
|
|
|
if (MainFileName.empty())
|
2010-03-13 05:04:27 +08:00
|
|
|
MainFileName = "<unknown>";
|
2010-03-19 22:49:09 +08:00
|
|
|
|
2010-03-23 05:28:29 +08:00
|
|
|
// The main file name provided via the "-main-file-name" option contains just
|
|
|
|
// the file name itself with no path information. This file name may have had
|
|
|
|
// a relative path, so we look into the actual file entry for the main
|
|
|
|
// file to determine the real absolute path for the file.
|
2010-07-24 07:04:28 +08:00
|
|
|
std::string MainFileDir;
|
2010-07-27 23:17:16 +08:00
|
|
|
if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
|
2010-03-19 22:49:09 +08:00
|
|
|
MainFileDir = MainFile->getDir()->getName();
|
2010-07-27 23:17:16 +08:00
|
|
|
if (MainFileDir != ".")
|
|
|
|
MainFileName = MainFileDir + "/" + MainFileName;
|
|
|
|
}
|
2010-03-19 22:49:09 +08:00
|
|
|
|
2010-07-27 23:17:16 +08:00
|
|
|
// Save filename string.
|
|
|
|
char *FilenamePtr = DebugInfoNames.Allocate<char>(MainFileName.length());
|
|
|
|
memcpy(FilenamePtr, MainFileName.c_str(), MainFileName.length());
|
|
|
|
llvm::StringRef Filename(FilenamePtr, MainFileName.length());
|
|
|
|
|
2009-03-25 11:28:08 +08:00
|
|
|
unsigned LangTag;
|
2010-03-09 08:44:50 +08:00
|
|
|
const LangOptions &LO = CGM.getLangOptions();
|
2009-03-25 11:28:08 +08:00
|
|
|
if (LO.CPlusPlus) {
|
|
|
|
if (LO.ObjC1)
|
|
|
|
LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
|
|
|
|
else
|
|
|
|
LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
|
|
|
|
} else if (LO.ObjC1) {
|
2009-03-25 04:35:51 +08:00
|
|
|
LangTag = llvm::dwarf::DW_LANG_ObjC;
|
2009-03-25 11:28:08 +08:00
|
|
|
} else if (LO.C99) {
|
2009-03-25 04:35:51 +08:00
|
|
|
LangTag = llvm::dwarf::DW_LANG_C99;
|
2009-03-25 11:28:08 +08:00
|
|
|
} else {
|
|
|
|
LangTag = llvm::dwarf::DW_LANG_C89;
|
|
|
|
}
|
2009-04-18 05:06:59 +08:00
|
|
|
|
2009-12-08 19:02:29 +08:00
|
|
|
const char *Producer =
|
2009-10-10 02:38:12 +08:00
|
|
|
#ifdef CLANG_VENDOR
|
|
|
|
CLANG_VENDOR
|
|
|
|
#endif
|
|
|
|
"clang " CLANG_VERSION_STRING;
|
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.
|
2010-03-09 08:44:50 +08:00
|
|
|
TheCU = DebugFactory.CreateCompileUnit(
|
2010-07-28 04:49:59 +08:00
|
|
|
LangTag, Filename, getCurrentDirname(),
|
2010-07-27 23:17:16 +08:00
|
|
|
Producer, true,
|
2009-12-18 10:43:17 +08:00
|
|
|
LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers);
|
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.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2008-05-25 13:15:42 +08:00
|
|
|
unsigned Encoding = 0;
|
2010-07-29 07:23:29 +08:00
|
|
|
const char *BTName = NULL;
|
2008-11-10 14:08:34 +08:00
|
|
|
switch (BT->getKind()) {
|
|
|
|
default:
|
|
|
|
case BuiltinType::Void:
|
|
|
|
return llvm::DIType();
|
2010-07-28 09:33:15 +08:00
|
|
|
case BuiltinType::ObjCClass:
|
2010-07-22 06:41:25 +08:00
|
|
|
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type,
|
2010-07-28 09:33:15 +08:00
|
|
|
Unit, "objc_class", Unit, 0, 0, 0, 0,
|
2010-07-22 06:41:25 +08:00
|
|
|
llvm::DIType::FlagFwdDecl,
|
|
|
|
llvm::DIType(), 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 =
|
|
|
|
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type,
|
|
|
|
Unit, "objc_class", Unit, 0, 0, 0, 0,
|
|
|
|
llvm::DIType::FlagFwdDecl,
|
|
|
|
llvm::DIType(), llvm::DIArray());
|
|
|
|
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
|
|
|
|
|
|
|
|
llvm::DIType ISATy =
|
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type,
|
|
|
|
Unit, "", Unit,
|
|
|
|
0, Size, 0, 0, 0, OCTy);
|
|
|
|
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
|
|
|
|
|
|
|
|
llvm::DIType FieldTy =
|
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"isa", Unit,
|
|
|
|
0,Size, 0, 0, 0, ISATy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
llvm::DIArray Elements =
|
|
|
|
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
|
|
|
|
|
|
|
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type,
|
|
|
|
Unit, "objc_object", Unit, 0, 0, 0, 0,
|
|
|
|
0,
|
|
|
|
llvm::DIType(), Elements);
|
|
|
|
}
|
2008-11-10 14:08:34 +08:00
|
|
|
case BuiltinType::UChar:
|
|
|
|
case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break;
|
|
|
|
case BuiltinType::Char_S:
|
|
|
|
case BuiltinType::SChar: Encoding = llvm::dwarf::DW_ATE_signed_char; break;
|
|
|
|
case BuiltinType::UShort:
|
|
|
|
case BuiltinType::UInt:
|
|
|
|
case BuiltinType::ULong:
|
|
|
|
case BuiltinType::ULongLong: Encoding = llvm::dwarf::DW_ATE_unsigned; break;
|
|
|
|
case BuiltinType::Short:
|
|
|
|
case BuiltinType::Int:
|
|
|
|
case BuiltinType::Long:
|
|
|
|
case BuiltinType::LongLong: Encoding = llvm::dwarf::DW_ATE_signed; break;
|
|
|
|
case BuiltinType::Bool: Encoding = llvm::dwarf::DW_ATE_boolean; break;
|
|
|
|
case BuiltinType::Float:
|
2009-10-13 06:28:31 +08:00
|
|
|
case BuiltinType::LongDouble:
|
2008-11-10 14:08:34 +08:00
|
|
|
case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2010-07-29 07:23:29 +08:00
|
|
|
|
|
|
|
switch (BT->getKind()) {
|
|
|
|
case BuiltinType::Long: BTName = "long int"; break;
|
|
|
|
case BuiltinType::LongLong: BTName = "long long int"; break;
|
|
|
|
case BuiltinType::ULong: BTName = "long unsigned int"; break;
|
|
|
|
case BuiltinType::ULongLong: BTName = "long long unsigned int"; break;
|
|
|
|
default:
|
|
|
|
BTName = BT->getName(CGM.getContext().getLangOptions());
|
|
|
|
break;
|
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
// Bit size, align and offset of the type.
|
2009-12-07 02:00:51 +08:00
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(BT);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(BT);
|
2008-05-25 13:15:42 +08:00
|
|
|
uint64_t Offset = 0;
|
2010-07-29 07:23:29 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
2010-07-29 07:23:29 +08:00
|
|
|
DebugFactory.CreateBasicType(Unit, BTName,
|
2009-10-21 03:55:01 +08:00
|
|
|
Unit, 0, Size, Align,
|
|
|
|
Offset, /*flags*/ 0, Encoding);
|
|
|
|
return DbgTy;
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2009-04-23 14:13:01 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
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-04-23 14:13:01 +08:00
|
|
|
uint64_t Offset = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
|
|
|
DebugFactory.CreateBasicType(Unit, "complex",
|
|
|
|
Unit, 0, Size, Align,
|
|
|
|
Offset, /*flags*/ 0, Encoding);
|
|
|
|
return DbgTy;
|
2009-04-23 14:13:01 +08:00
|
|
|
}
|
|
|
|
|
2009-09-25 09:40:47 +08:00
|
|
|
/// CreateCVRType - Get the qualified type from the cache or create
|
2008-11-10 14:08:34 +08:00
|
|
|
/// a new one if necessary.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
|
2009-09-25 09:40:47 +08:00
|
|
|
QualifierCollector Qc;
|
|
|
|
const Type *T = Qc.strip(Ty);
|
|
|
|
|
|
|
|
// Ignore these qualifiers for now.
|
|
|
|
Qc.removeObjCGCAttr();
|
|
|
|
Qc.removeAddressSpace();
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// We will create one Derived type for one qualifier and recurse to handle any
|
|
|
|
// additional ones.
|
|
|
|
unsigned Tag;
|
2009-09-25 09:40:47 +08:00
|
|
|
if (Qc.hasConst()) {
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_const_type;
|
2009-09-25 09:40:47 +08:00
|
|
|
Qc.removeConst();
|
|
|
|
} else if (Qc.hasVolatile()) {
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_volatile_type;
|
2009-09-25 09:40:47 +08:00
|
|
|
Qc.removeVolatile();
|
|
|
|
} else if (Qc.hasRestrict()) {
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_restrict_type;
|
2009-09-25 09:40:47 +08:00
|
|
|
Qc.removeRestrict();
|
|
|
|
} else {
|
|
|
|
assert(Qc.empty() && "Unknown type qualifier for debug info");
|
|
|
|
return getOrCreateType(QualType(T, 0), Unit);
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-25 09:40:47 +08:00
|
|
|
llvm::DIType FromTy = getOrCreateType(Qc.apply(T), Unit);
|
|
|
|
|
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.
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
2010-03-10 06:49:11 +08:00
|
|
|
DebugFactory.CreateDerivedType(Tag, Unit, "", Unit,
|
2009-10-21 03:55:01 +08:00
|
|
|
0, 0, 0, 0, 0, FromTy);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
|
|
|
|
const Type *Ty,
|
|
|
|
QualType PointeeTy,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-11-07 03:19:55 +08:00
|
|
|
llvm::DIType EltTy = getOrCreateType(PointeeTy, Unit);
|
2009-09-09 23:08:12 +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.
|
|
|
|
uint64_t Size =
|
2009-12-07 02:00:51 +08:00
|
|
|
CGM.getContext().Target.getPointerWidth(PointeeTy.getAddressSpace());
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
return
|
2010-03-10 06:49:11 +08:00
|
|
|
DebugFactory.CreateDerivedType(Tag, Unit, "", Unit,
|
2009-10-21 03:55:01 +08:00
|
|
|
0, Size, Align, 0, 0, EltTy);
|
2009-11-07 03:19:55 +08:00
|
|
|
|
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;
|
|
|
|
|
|
|
|
unsigned Tag = llvm::dwarf::DW_TAG_structure_type;
|
|
|
|
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 5> EltTys;
|
|
|
|
|
|
|
|
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
|
|
|
|
2009-05-27 03:40:20 +08:00
|
|
|
Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
2009-05-14 10:03:51 +08:00
|
|
|
EltTys.clear();
|
|
|
|
|
2009-10-02 10:30:50 +08:00
|
|
|
unsigned Flags = llvm::DIType::FlagAppleBlock;
|
2010-05-13 07:46:38 +08:00
|
|
|
unsigned LineNo = getLineNumber(CurLoc);
|
2009-10-02 10:30:50 +08:00
|
|
|
|
2009-05-14 10:03:51 +08:00
|
|
|
EltTy = DebugFactory.CreateCompositeType(Tag, Unit, "__block_descriptor",
|
2010-05-13 07:46:38 +08:00
|
|
|
Unit, LineNo, FieldOffset, 0, 0,
|
|
|
|
Flags, llvm::DIType(), 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);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-14 10:03:51 +08:00
|
|
|
DescTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type,
|
2010-03-10 06:49:11 +08:00
|
|
|
Unit, "", Unit,
|
2010-05-13 07:46:38 +08:00
|
|
|
LineNo, Size, Align, 0, 0, EltTy);
|
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);
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
2010-03-10 06:49:11 +08:00
|
|
|
"__descriptor", Unit,
|
2010-05-13 07:46:38 +08:00
|
|
|
LineNo, FieldSize, FieldAlign,
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
2009-05-27 03:40:20 +08:00
|
|
|
Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
2009-05-14 10:03:51 +08:00
|
|
|
|
|
|
|
EltTy = DebugFactory.CreateCompositeType(Tag, Unit, "__block_literal_generic",
|
2010-05-13 07:46:38 +08:00
|
|
|
Unit, LineNo, FieldOffset, 0, 0,
|
|
|
|
Flags, llvm::DIType(), Elements);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-14 10:03:51 +08:00
|
|
|
BlockLiteralGenericSet = true;
|
|
|
|
BlockLiteralGeneric
|
|
|
|
= DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
|
2010-03-10 06:49:11 +08:00
|
|
|
"", Unit,
|
2010-05-13 07:46:38 +08:00
|
|
|
LineNo, Size, Align, 0, 0, EltTy);
|
2009-05-14 10:03:51 +08:00
|
|
|
return BlockLiteralGeneric;
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2008-11-10 14:08:34 +08:00
|
|
|
// Typedefs are derived from some other type. If we have a typedef of a
|
|
|
|
// typedef, make sure to emit the whole chain.
|
|
|
|
llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
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());
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2010-02-02 05:34:11 +08:00
|
|
|
llvm::DIDescriptor TyContext
|
|
|
|
= getContextDescriptor(dyn_cast<Decl>(Ty->getDecl()->getDeclContext()),
|
|
|
|
Unit);
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
2010-01-30 06:29:31 +08:00
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef,
|
2010-02-02 05:34:11 +08:00
|
|
|
TyContext,
|
2010-01-30 06:29:31 +08:00
|
|
|
Ty->getDecl()->getName(), Unit,
|
|
|
|
Line, 0, 0, 0, 0, Src);
|
2009-10-21 03:55:01 +08:00
|
|
|
return DbgTy;
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 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 '...'!
|
2009-02-27 07:50:07 +08:00
|
|
|
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));
|
|
|
|
} else {
|
|
|
|
// FIXME: Handle () case in C. llvm-gcc doesn't do it either.
|
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIArray EltTypeArray =
|
2009-05-27 03:40:20 +08:00
|
|
|
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
|
|
|
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
|
2010-03-10 06:49:11 +08:00
|
|
|
Unit, "", Unit,
|
2009-10-21 03:55:01 +08:00
|
|
|
0, 0, 0, 0, 0,
|
|
|
|
llvm::DIType(), EltTypeArray);
|
|
|
|
return DbgTy;
|
2008-05-25 13:15:42 +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::
|
2010-03-09 08:44:50 +08:00
|
|
|
CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit,
|
2010-01-19 08:00:59 +08:00
|
|
|
llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys) {
|
|
|
|
unsigned FieldNo = 0;
|
2010-02-02 05:39:52 +08:00
|
|
|
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
|
|
|
|
for (RecordDecl::field_iterator I = RD->field_begin(),
|
|
|
|
E = RD->field_end();
|
2010-01-19 08:00:59 +08:00
|
|
|
I != E; ++I, ++FieldNo) {
|
|
|
|
FieldDecl *Field = *I;
|
|
|
|
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
|
|
|
|
llvm::StringRef FieldName = Field->getName();
|
|
|
|
|
2010-02-12 09:31:06 +08:00
|
|
|
// Ignore unnamed fields. Do not ignore unnamed records.
|
|
|
|
if (FieldName.empty() && !isa<RecordType>(Field->getType()))
|
2010-01-19 08:00:59 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// 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());
|
2010-01-19 08:00:59 +08:00
|
|
|
QualType FType = Field->getType();
|
|
|
|
uint64_t FieldSize = 0;
|
|
|
|
unsigned FieldAlign = 0;
|
|
|
|
if (!FType->isIncompleteArrayType()) {
|
|
|
|
|
|
|
|
// Bit size, align and offset of the type.
|
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
Expr *BitWidth = Field->getBitWidth();
|
|
|
|
if (BitWidth)
|
|
|
|
FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t FieldOffset = RL.getFieldOffset(FieldNo);
|
|
|
|
|
2010-04-22 07:12:37 +08:00
|
|
|
unsigned Flags = 0;
|
|
|
|
AccessSpecifier Access = I->getAccess();
|
|
|
|
if (Access == clang::AS_private)
|
|
|
|
Flags |= llvm::DIType::FlagPrivate;
|
|
|
|
else if (Access == clang::AS_protected)
|
|
|
|
Flags |= llvm::DIType::FlagProtected;
|
|
|
|
|
2010-01-19 08:00:59 +08:00
|
|
|
// Create a DW_TAG_member node to remember the offset of this field in the
|
|
|
|
// struct. FIXME: This is an absolutely insane way to capture this
|
|
|
|
// information. When we gut debug info, this should be fixed.
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
FieldName, FieldDefUnit,
|
|
|
|
FieldLine, FieldSize, FieldAlign,
|
2010-04-22 07:12:37 +08:00
|
|
|
FieldOffset, Flags, FieldTy);
|
2010-01-19 08:00:59 +08:00
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
// Static methods do not need "this" pointer argument.
|
|
|
|
if (Method->isStatic())
|
|
|
|
return FnTy;
|
|
|
|
|
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!");
|
|
|
|
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 16> Elts;
|
|
|
|
|
|
|
|
// First element is always return type. For 'void' functions it is NULL.
|
|
|
|
Elts.push_back(Args.getElement(0));
|
|
|
|
|
|
|
|
// "this" pointer is always first argument.
|
|
|
|
ASTContext &Context = CGM.getContext();
|
|
|
|
QualType ThisPtr =
|
|
|
|
Context.getPointerType(Context.getTagDeclType(Method->getParent()));
|
2010-02-10 01:57:50 +08:00
|
|
|
llvm::DIType ThisPtrType =
|
|
|
|
DebugFactory.CreateArtificialType(getOrCreateType(ThisPtr, Unit));
|
2010-07-13 08:24:30 +08:00
|
|
|
|
2010-05-08 02:12:35 +08:00
|
|
|
TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
|
2010-02-10 01:57:50 +08:00
|
|
|
Elts.push_back(ThisPtrType);
|
2010-01-28 08:28:01 +08:00
|
|
|
|
|
|
|
// Copy rest of the arguments.
|
|
|
|
for (unsigned i = 1, e = Args.getNumElements(); i != e; ++i)
|
|
|
|
Elts.push_back(Args.getElement(i));
|
|
|
|
|
|
|
|
llvm::DIArray EltTypeArray =
|
|
|
|
DebugFactory.GetOrCreateArray(Elts.data(), Elts.size());
|
|
|
|
|
|
|
|
return
|
|
|
|
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
|
2010-03-10 06:49:11 +08:00
|
|
|
Unit, "", Unit,
|
2010-01-28 08:28:01 +08:00
|
|
|
0, 0, 0, 0, 0,
|
|
|
|
llvm::DIType(), EltTypeArray);
|
|
|
|
}
|
|
|
|
|
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-01-26 12:49:33 +08:00
|
|
|
llvm::DICompositeType &RecordTy) {
|
2010-01-26 13:19:50 +08:00
|
|
|
bool IsCtorOrDtor =
|
|
|
|
isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
|
|
|
|
|
|
|
|
llvm::StringRef MethodName = getFunctionName(Method);
|
2010-01-28 08:28:01 +08:00
|
|
|
llvm::DIType MethodTy = getOrCreateMethodType(Method, Unit);
|
2010-01-26 13:19:50 +08:00
|
|
|
|
|
|
|
// Since a single ctor/dtor corresponds to multiple functions, it doesn't
|
|
|
|
// make sense to give a single ctor/dtor a linkage name.
|
2010-06-23 00:16:50 +08:00
|
|
|
llvm::StringRef MethodLinkageName;
|
2010-01-26 13:19:50 +08:00
|
|
|
if (!IsCtorOrDtor)
|
2010-06-23 00:16:50 +08:00
|
|
|
MethodLinkageName = CGM.getMangledName(Method);
|
2010-01-26 13:19:50 +08:00
|
|
|
|
2010-01-26 12:49:33 +08:00
|
|
|
// Get the location for the method.
|
2010-05-13 07:46:38 +08:00
|
|
|
llvm::DIFile MethodDefUnit = getOrCreateFile(Method->getLocation());
|
|
|
|
unsigned MethodLine = getLineNumber(Method->getLocation());
|
2010-01-26 12:49:33 +08:00
|
|
|
|
|
|
|
// Collect virtual method info.
|
|
|
|
llvm::DIType ContainingType;
|
|
|
|
unsigned Virtuality = 0;
|
|
|
|
unsigned VIndex = 0;
|
2010-01-26 13:19:50 +08:00
|
|
|
|
2010-01-26 12:49:33 +08:00
|
|
|
if (Method->isVirtual()) {
|
2010-01-26 13:19:50 +08:00
|
|
|
if (Method->isPure())
|
|
|
|
Virtuality = llvm::dwarf::DW_VIRTUALITY_pure_virtual;
|
|
|
|
else
|
|
|
|
Virtuality = llvm::dwarf::DW_VIRTUALITY_virtual;
|
|
|
|
|
|
|
|
// It doesn't make sense to give a virtual destructor a vtable index,
|
|
|
|
// since a single destructor has two entries in the vtable.
|
|
|
|
if (!isa<CXXDestructorDecl>(Method))
|
2010-04-18 04:15:18 +08:00
|
|
|
VIndex = CGM.getVTables().getMethodVTableIndex(Method);
|
2010-01-26 12:49:33 +08:00
|
|
|
ContainingType = RecordTy;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::DISubprogram SP =
|
|
|
|
DebugFactory.CreateSubprogram(RecordTy , MethodName, MethodName,
|
|
|
|
MethodLinkageName,
|
|
|
|
MethodDefUnit, MethodLine,
|
|
|
|
MethodTy, /*isLocalToUnit=*/false,
|
2010-07-13 06:54:41 +08:00
|
|
|
/* isDefintion=*/ false,
|
2010-07-16 06:57:00 +08:00
|
|
|
Virtuality, VIndex, ContainingType,
|
2010-07-16 07:09:46 +08:00
|
|
|
Method->isImplicit(),
|
|
|
|
CGM.getLangOptions().Optimize);
|
2010-01-26 13:19:50 +08:00
|
|
|
|
|
|
|
// Don't cache ctors or dtors since we have to emit multiple functions for
|
|
|
|
// a single ctor or dtor.
|
|
|
|
if (!IsCtorOrDtor && Method->isThisDeclarationADefinition())
|
2010-05-08 02:12:35 +08:00
|
|
|
SPCache[Method] = llvm::WeakVH(SP);
|
2010-01-26 12:49:33 +08:00
|
|
|
|
|
|
|
return SP;
|
|
|
|
}
|
|
|
|
|
2010-01-19 09:54:44 +08:00
|
|
|
/// CollectCXXMemberFunctions - A helper function to collect debug info for
|
|
|
|
/// C++ member functions.This is used while creating debug info entry for
|
|
|
|
/// a Record.
|
|
|
|
void CGDebugInfo::
|
2010-03-09 08:44:50 +08:00
|
|
|
CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
|
2010-01-19 09:54:44 +08:00
|
|
|
llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys,
|
|
|
|
llvm::DICompositeType &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-01-26 07:32:18 +08:00
|
|
|
/// CollectCXXBases - A helper function to collect debug info for
|
|
|
|
/// C++ base classes. This is used while creating debug info entry for
|
|
|
|
/// a Record.
|
|
|
|
void CGDebugInfo::
|
2010-03-09 08:44:50 +08:00
|
|
|
CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
|
2010-01-26 07:32:18 +08:00
|
|
|
llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys,
|
|
|
|
llvm::DICompositeType &RecordTy) {
|
|
|
|
|
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;
|
|
|
|
uint64_t BaseOffset;
|
|
|
|
|
|
|
|
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.
|
2010-03-23 12:11:45 +08:00
|
|
|
BaseOffset = 0 - CGM.getVTables().getVirtualBaseOffsetOffset(RD, Base);
|
2010-01-29 05:54:15 +08:00
|
|
|
BFlags = llvm::DIType::FlagVirtual;
|
|
|
|
} else
|
|
|
|
BaseOffset = RL.getBaseClassOffset(Base);
|
|
|
|
|
|
|
|
AccessSpecifier Access = BI->getAccessSpecifier();
|
|
|
|
if (Access == clang::AS_private)
|
|
|
|
BFlags |= llvm::DIType::FlagPrivate;
|
|
|
|
else if (Access == clang::AS_protected)
|
|
|
|
BFlags |= llvm::DIType::FlagProtected;
|
|
|
|
|
|
|
|
llvm::DIType DTy =
|
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_inheritance,
|
|
|
|
RecordTy, llvm::StringRef(),
|
2010-03-10 06:49:11 +08:00
|
|
|
Unit, 0, 0, 0,
|
2010-01-29 05:54:15 +08:00
|
|
|
BaseOffset, BFlags,
|
|
|
|
getOrCreateType(BI->getType(),
|
|
|
|
Unit));
|
|
|
|
EltTys.push_back(DTy);
|
|
|
|
}
|
2010-01-26 07:32:18 +08:00
|
|
|
}
|
|
|
|
|
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-03-30 19:36:44 +08:00
|
|
|
llvm::DIDescriptor STy = getOrCreateType(Context.IntTy, Unit);
|
|
|
|
llvm::DIArray SElements = DebugFactory.GetOrCreateArray(&STy, 1);
|
2010-01-29 02:11:52 +08:00
|
|
|
llvm::DIType SubTy =
|
|
|
|
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
|
2010-03-10 06:49:11 +08:00
|
|
|
Unit, "", Unit,
|
2010-01-29 02:11:52 +08:00
|
|
|
0, 0, 0, 0, 0, llvm::DIType(), SElements);
|
|
|
|
|
|
|
|
unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
|
|
|
|
llvm::DIType vtbl_ptr_type
|
|
|
|
= DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type,
|
2010-03-10 06:49:11 +08:00
|
|
|
Unit, "__vtbl_ptr_type", Unit,
|
2010-01-29 02:11:52 +08:00
|
|
|
0, Size, 0, 0, 0, SubTy);
|
|
|
|
|
2010-03-10 06:49:11 +08:00
|
|
|
VTablePtrType =
|
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type,
|
|
|
|
Unit, "", Unit,
|
|
|
|
0, Size, 0, 0, 0, vtbl_ptr_type);
|
2010-01-29 02:11:52 +08:00
|
|
|
return VTablePtrType;
|
|
|
|
}
|
|
|
|
|
2010-04-18 04:15:18 +08:00
|
|
|
/// getVTableName - Get vtable name for the given Class.
|
|
|
|
llvm::StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
|
2010-01-29 02:11:52 +08:00
|
|
|
// Otherwise construct gdb compatible name name.
|
2010-02-02 05:39:52 +08:00
|
|
|
std::string Name = "_vptr$" + RD->getNameAsString();
|
2010-01-29 02:11:52 +08:00
|
|
|
|
|
|
|
// Copy this name on the side and use its reference.
|
2010-01-29 02:21:00 +08:00
|
|
|
char *StrPtr = DebugInfoNames.Allocate<char>(Name.length());
|
2010-01-29 02:11:52 +08:00
|
|
|
memcpy(StrPtr, Name.data(), Name.length());
|
|
|
|
return llvm::StringRef(StrPtr, Name.length());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-18 04:15:18 +08:00
|
|
|
/// CollectVTableInfo - If the C++ class has vtable info then insert appropriate
|
2010-01-29 02:11:52 +08:00
|
|
|
/// debug info entry in EltTys vector.
|
|
|
|
void CGDebugInfo::
|
2010-04-18 04:15:18 +08:00
|
|
|
CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
|
2010-01-29 02:11:52 +08:00
|
|
|
llvm::SmallVectorImpl<llvm::DIDescriptor> &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
|
|
|
|
= DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
2010-04-18 04:15:18 +08:00
|
|
|
getVTableName(RD), Unit,
|
2010-01-29 02:11:52 +08:00
|
|
|
0, Size, 0, 0, 0,
|
|
|
|
getOrCreateVTablePtrType(Unit));
|
|
|
|
EltTys.push_back(VPTR);
|
|
|
|
}
|
|
|
|
|
2009-02-25 09:36:11 +08:00
|
|
|
/// CreateType - get structure or union type.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
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
|
|
|
unsigned Tag;
|
2010-02-02 05:52:22 +08:00
|
|
|
if (RD->isStruct())
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_structure_type;
|
2010-02-02 05:52:22 +08:00
|
|
|
else if (RD->isUnion())
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_union_type;
|
|
|
|
else {
|
2010-02-02 05:52:22 +08:00
|
|
|
assert(RD->isClass() && "Unknown RecordType!");
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_class_type;
|
2008-06-07 12:46:53 +08:00
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Get overall information about the record type for the debug info.
|
2010-05-13 07:46:38 +08:00
|
|
|
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
|
|
|
|
unsigned Line = getLineNumber(RD->getLocation());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Records and classes and unions can all be recursive. To handle them, we
|
|
|
|
// first generate a debug descriptor for the struct as a forward declaration.
|
|
|
|
// Then (if it is a definition) we go through and get debug info for all of
|
|
|
|
// its members. Finally, we create a descriptor for the complete type (which
|
|
|
|
// may refer to the forward decl if the struct is recursive) and replace all
|
|
|
|
// uses of the forward declaration with the final definition.
|
2010-07-09 03:56:29 +08:00
|
|
|
llvm::DIDescriptor FDContext =
|
|
|
|
getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()), Unit);
|
|
|
|
|
|
|
|
// If this is just a forward declaration, construct an appropriately
|
|
|
|
// marked node and just return it.
|
|
|
|
if (!RD->getDefinition()) {
|
|
|
|
llvm::DICompositeType FwdDecl =
|
|
|
|
DebugFactory.CreateCompositeType(Tag, FDContext, RD->getName(),
|
|
|
|
DefUnit, Line, 0, 0, 0,
|
|
|
|
llvm::DIType::FlagFwdDecl,
|
|
|
|
llvm::DIType(), llvm::DIArray());
|
|
|
|
|
|
|
|
return FwdDecl;
|
|
|
|
}
|
2010-01-21 07:56:40 +08:00
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
// A RD->getName() is not unique. However, the debug info descriptors
|
2010-02-02 06:51:29 +08:00
|
|
|
// are uniqued so use type name to ensure uniquness.
|
2010-03-13 20:06:51 +08:00
|
|
|
llvm::SmallString<128> FwdDeclName;
|
|
|
|
llvm::raw_svector_ostream(FwdDeclName) << "fwd.type." << FwdDeclCount++;
|
2009-07-23 02:57:00 +08:00
|
|
|
llvm::DICompositeType FwdDecl =
|
2010-03-10 05:32:27 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, FDContext, FwdDeclName,
|
2009-11-12 08:51:46 +08:00
|
|
|
DefUnit, Line, 0, 0, 0, 0,
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType(), llvm::DIArray());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-05-08 02:12:35 +08:00
|
|
|
llvm::MDNode *MN = FwdDecl;
|
|
|
|
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
|
2008-11-10 14:08:34 +08:00
|
|
|
// Otherwise, insert it into the TypeCache so that recursive uses will find
|
|
|
|
// it.
|
2010-05-08 02:12:35 +08:00
|
|
|
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
|
2010-03-12 04:01:48 +08:00
|
|
|
// Push the struct on region stack.
|
2010-05-08 02:12:35 +08:00
|
|
|
RegionStack.push_back(FwdDeclNode);
|
|
|
|
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
// Convert all the elements.
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
|
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
|
2010-01-29 05:41:35 +08:00
|
|
|
if (CXXDecl) {
|
|
|
|
CollectCXXBases(CXXDecl, Unit, EltTys, FwdDecl);
|
2010-04-18 04:15:18 +08:00
|
|
|
CollectVTableInfo(CXXDecl, Unit, EltTys);
|
2010-01-29 05:41:35 +08:00
|
|
|
}
|
2010-08-12 08:02:44 +08:00
|
|
|
|
|
|
|
// Collect static variables with initializers.
|
|
|
|
for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
|
|
|
|
I != E; ++I)
|
|
|
|
if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {
|
|
|
|
if (const Expr *Init = V->getInit()) {
|
|
|
|
Expr::EvalResult Result;
|
|
|
|
if (Init->Evaluate(Result, CGM.getContext()) && Result.Val.isInt()) {
|
|
|
|
llvm::ConstantInt *CI
|
|
|
|
= llvm::ConstantInt::get(CGM.getLLVMContext(), Result.Val.getInt());
|
|
|
|
|
|
|
|
// Create the descriptor for static variable.
|
|
|
|
llvm::DIFile VUnit = getOrCreateFile(V->getLocation());
|
|
|
|
llvm::StringRef VName = V->getName();
|
|
|
|
llvm::DIType VTy = getOrCreateType(V->getType(), VUnit);
|
|
|
|
// Do not use DIGlobalVariable for enums.
|
|
|
|
if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) {
|
|
|
|
DebugFactory.CreateGlobalVariable(FwdDecl, VName, VName, VName, VUnit,
|
|
|
|
getLineNumber(V->getLocation()),
|
|
|
|
VTy, true, true, CI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
CollectRecordFields(RD, Unit, EltTys);
|
2010-01-28 08:54:21 +08:00
|
|
|
llvm::MDNode *ContainingType = NULL;
|
2010-01-29 02:11:52 +08:00
|
|
|
if (CXXDecl) {
|
2010-01-19 09:54:44 +08:00
|
|
|
CollectCXXMemberFunctions(CXXDecl, Unit, EltTys, FwdDecl);
|
2010-01-28 08:54:21 +08:00
|
|
|
|
|
|
|
// A class's primary base or the class itself contains the vtable.
|
2010-02-02 05:52:22 +08:00
|
|
|
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
|
2010-01-28 08:54:21 +08:00
|
|
|
if (const CXXRecordDecl *PBase = RL.getPrimaryBase())
|
|
|
|
ContainingType =
|
2010-05-08 02:12:35 +08:00
|
|
|
getOrCreateType(QualType(PBase->getTypeForDecl(), 0), Unit);
|
2010-01-28 08:54:21 +08:00
|
|
|
else if (CXXDecl->isDynamicClass())
|
2010-05-08 02:12:35 +08:00
|
|
|
ContainingType = FwdDecl;
|
2010-01-26 07:32:18 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIArray Elements =
|
2009-05-27 03:40:20 +08:00
|
|
|
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
2008-06-07 12:46:53 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Bit size, align and offset of the type.
|
2009-12-07 02:00:51 +08:00
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-03-12 04:01:48 +08:00
|
|
|
RegionStack.pop_back();
|
|
|
|
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI =
|
|
|
|
RegionMap.find(Ty->getDecl());
|
|
|
|
if (RI != RegionMap.end())
|
|
|
|
RegionMap.erase(RI);
|
|
|
|
|
2010-02-02 06:40:08 +08:00
|
|
|
llvm::DIDescriptor RDContext =
|
|
|
|
getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()), Unit);
|
2010-07-21 04:24:18 +08:00
|
|
|
|
|
|
|
llvm::StringRef RDName = RD->getName();
|
|
|
|
// If this is a class, include the template arguments also.
|
|
|
|
if (Tag == llvm::dwarf::DW_TAG_class_type)
|
|
|
|
RDName = getClassName(RD);
|
|
|
|
|
2009-07-23 02:57:00 +08:00
|
|
|
llvm::DICompositeType RealDecl =
|
2010-02-02 06:40:08 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, RDContext,
|
2010-07-21 04:24:18 +08:00
|
|
|
RDName,
|
2009-11-12 08:51:46 +08:00
|
|
|
DefUnit, Line, Size, Align, 0, 0,
|
2010-01-28 08:54:21 +08:00
|
|
|
llvm::DIType(), Elements,
|
|
|
|
0, ContainingType);
|
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.
|
2009-11-17 05:04:30 +08:00
|
|
|
llvm::DIDerivedType(FwdDeclNode).replaceAllUsesWith(RealDecl);
|
2010-05-08 02:12:35 +08:00
|
|
|
RegionMap[RD] = llvm::WeakVH(RealDecl);
|
2008-11-10 14:08:34 +08:00
|
|
|
return 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();
|
2009-02-27 05:10:26 +08:00
|
|
|
unsigned Tag = llvm::dwarf::DW_TAG_structure_type;
|
|
|
|
|
|
|
|
// 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
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// To handle recursive interface, we
|
|
|
|
// first generate a debug descriptor for the struct as a forward declaration.
|
|
|
|
// Then (if it is a definition) we go through and get debug info for all of
|
|
|
|
// its members. Finally, we create a descriptor for the complete type (which
|
|
|
|
// may refer to the forward decl if the struct is recursive) and replace all
|
|
|
|
// uses of the forward declaration with the final definition.
|
2009-07-28 02:42:03 +08:00
|
|
|
llvm::DICompositeType FwdDecl =
|
2010-02-02 05:52:22 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, ID->getName(),
|
2009-11-12 08:51:46 +08:00
|
|
|
DefUnit, Line, 0, 0, 0, 0,
|
2009-05-02 09:13:16 +08:00
|
|
|
llvm::DIType(), llvm::DIArray(),
|
|
|
|
RuntimeLang);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// If this is just a forward declaration, return it.
|
2010-02-02 05:52:22 +08:00
|
|
|
if (ID->isForwardDecl())
|
2009-02-27 05:10:26 +08:00
|
|
|
return FwdDecl;
|
|
|
|
|
2010-05-08 02:12:35 +08:00
|
|
|
llvm::MDNode *MN = FwdDecl;
|
|
|
|
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
|
2009-02-27 05:10:26 +08:00
|
|
|
// Otherwise, insert it into the TypeCache so that recursive uses will find
|
|
|
|
// it.
|
2010-05-08 02:12:35 +08:00
|
|
|
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
|
2010-03-12 04:01:48 +08:00
|
|
|
// Push the struct on region stack.
|
2010-05-08 02:12:35 +08:00
|
|
|
RegionStack.push_back(FwdDeclNode);
|
|
|
|
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
// Convert all the elements.
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
|
|
|
|
|
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);
|
2009-09-09 23:08:12 +08:00
|
|
|
llvm::DIType InhTag =
|
2009-03-11 05:30:26 +08:00
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_inheritance,
|
2010-03-10 06:49:11 +08:00
|
|
|
Unit, "", Unit, 0, 0, 0,
|
2009-03-11 05:30:26 +08:00
|
|
|
0 /* offset */, 0, SClassTy);
|
|
|
|
EltTys.push_back(InhTag);
|
|
|
|
}
|
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID);
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
unsigned FieldNo = 0;
|
2010-02-02 05:52:22 +08:00
|
|
|
for (ObjCInterfaceDecl::ivar_iterator I = ID->ivar_begin(),
|
|
|
|
E = ID->ivar_end(); I != E; ++I, ++FieldNo) {
|
2009-02-27 05:10:26 +08:00
|
|
|
ObjCIvarDecl *Field = *I;
|
|
|
|
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
|
|
|
|
|
2009-11-26 01:37:31 +08:00
|
|
|
llvm::StringRef FieldName = Field->getName();
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2009-04-28 06:40:36 +08:00
|
|
|
// Ignore unnamed fields.
|
2009-11-26 01:37:31 +08:00
|
|
|
if (FieldName.empty())
|
2009-04-28 06:40:36 +08:00
|
|
|
continue;
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// Get the location for the field.
|
2010-05-13 07:46:38 +08:00
|
|
|
llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation());
|
|
|
|
unsigned FieldLine = getLineNumber(Field->getLocation());
|
2009-03-21 02:24:39 +08:00
|
|
|
QualType FType = Field->getType();
|
|
|
|
uint64_t FieldSize = 0;
|
|
|
|
unsigned FieldAlign = 0;
|
|
|
|
|
|
|
|
if (!FType->isIncompleteArrayType()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-21 02:24:39 +08:00
|
|
|
// Bit size, align and offset of the type.
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
2009-03-21 02:24:39 +08:00
|
|
|
Expr *BitWidth = Field->getBitWidth();
|
|
|
|
if (BitWidth)
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
|
2009-04-27 03:19:15 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2009-03-21 02:24:39 +08:00
|
|
|
}
|
2009-03-19 08:23:53 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
uint64_t FieldOffset = RL.getFieldOffset(FieldNo);
|
|
|
|
|
2009-03-19 08:23:53 +08:00
|
|
|
unsigned Flags = 0;
|
|
|
|
if (Field->getAccessControl() == ObjCIvarDecl::Protected)
|
|
|
|
Flags = llvm::DIType::FlagProtected;
|
|
|
|
else if (Field->getAccessControl() == ObjCIvarDecl::Private)
|
|
|
|
Flags = llvm::DIType::FlagPrivate;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// Create a DW_TAG_member node to remember the offset of this field in the
|
|
|
|
// struct. FIXME: This is an absolutely insane way to capture this
|
|
|
|
// information. When we gut debug info, this should be fixed.
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
FieldName, FieldDefUnit,
|
|
|
|
FieldLine, FieldSize, FieldAlign,
|
2009-03-19 08:23:53 +08:00
|
|
|
FieldOffset, Flags, FieldTy);
|
2009-02-27 05:10:26 +08:00
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
llvm::DIArray Elements =
|
2009-05-21 17:52:38 +08:00
|
|
|
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2010-03-12 04:01:48 +08:00
|
|
|
RegionStack.pop_back();
|
|
|
|
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI =
|
|
|
|
RegionMap.find(Ty->getDecl());
|
|
|
|
if (RI != RegionMap.end())
|
|
|
|
RegionMap.erase(RI);
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// Bit size, align and offset of the type.
|
2009-12-07 02:00:51 +08:00
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-28 02:42:03 +08:00
|
|
|
llvm::DICompositeType RealDecl =
|
2010-02-02 05:52:22 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, ID->getName(), DefUnit,
|
2009-11-12 08:51:46 +08:00
|
|
|
Line, Size, Align, 0, 0, llvm::DIType(),
|
|
|
|
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.
|
2009-11-17 04:09:38 +08:00
|
|
|
llvm::DIDerivedType(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;
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2010-02-02 05:52:22 +08:00
|
|
|
EnumDecl *ED = Ty->getDecl();
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 32> Enumerators;
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Create DIEnumerator elements for each enumerator.
|
2009-09-09 23:08:12 +08:00
|
|
|
for (EnumDecl::enumerator_iterator
|
2010-02-02 05:52:22 +08:00
|
|
|
Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end();
|
2008-12-12 00:49:14 +08:00
|
|
|
Enum != EnumEnd; ++Enum) {
|
2009-11-26 01:37:31 +08:00
|
|
|
Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getName(),
|
2008-12-12 00:49:14 +08:00
|
|
|
Enum->getInitVal().getZExtValue()));
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Return a CompositeType for the enum itself.
|
|
|
|
llvm::DIArray EltArray =
|
2009-05-21 17:52:38 +08:00
|
|
|
DebugFactory.GetOrCreateArray(Enumerators.data(), Enumerators.size());
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2010-05-13 07:46:38 +08:00
|
|
|
llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
|
|
|
|
unsigned Line = getLineNumber(ED->getLocation());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Size and align of the type.
|
2009-05-04 12:39:55 +08:00
|
|
|
uint64_t Size = 0;
|
|
|
|
unsigned Align = 0;
|
|
|
|
if (!Ty->isIncompleteType()) {
|
2009-12-07 02:00:51 +08:00
|
|
|
Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
Align = CGM.getContext().getTypeAlign(Ty);
|
2009-05-04 12:39:55 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
|
|
|
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
|
2010-02-02 05:52:22 +08:00
|
|
|
Unit, ED->getName(), DefUnit, Line,
|
2009-10-21 03:55:01 +08:00
|
|
|
Size, Align, 0, 0,
|
|
|
|
llvm::DIType(), EltArray);
|
|
|
|
return DbgTy;
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const TagType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2008-11-10 14:08:34 +08:00
|
|
|
if (const RecordType *RT = dyn_cast<RecordType>(Ty))
|
|
|
|
return CreateType(RT, Unit);
|
|
|
|
else if (const EnumType *ET = dyn_cast<EnumType>(Ty))
|
|
|
|
return CreateType(ET, Unit);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
return llvm::DIType();
|
|
|
|
}
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2010-02-24 06:59:39 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2010-02-24 06:59:39 +08:00
|
|
|
llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit);
|
|
|
|
uint64_t NumElems = Ty->getNumElements();
|
|
|
|
if (NumElems > 0)
|
|
|
|
--NumElems;
|
|
|
|
|
2010-03-30 19:36:44 +08:00
|
|
|
llvm::DIDescriptor Subscript = DebugFactory.GetOrCreateSubrange(0, NumElems);
|
|
|
|
llvm::DIArray SubscriptArray = DebugFactory.GetOrCreateArray(&Subscript, 1);
|
2010-02-24 06:59:39 +08:00
|
|
|
|
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
|
|
|
|
|
|
|
return
|
|
|
|
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_vector_type,
|
2010-03-10 06:49:11 +08:00
|
|
|
Unit, "", Unit,
|
2010-02-24 06:59:39 +08:00
|
|
|
0, Size, Align, 0, 0,
|
|
|
|
ElementTy, SubscriptArray);
|
|
|
|
}
|
|
|
|
|
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());
|
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?
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 8> Subscripts;
|
|
|
|
QualType EltTy(Ty, 0);
|
|
|
|
while ((Ty = dyn_cast<ArrayType>(EltTy))) {
|
2008-06-09 18:47:41 +08:00
|
|
|
uint64_t Upper = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty))
|
2009-08-15 04:57:45 +08:00
|
|
|
if (CAT->getSize().getZExtValue())
|
2009-09-09 23:08:12 +08:00
|
|
|
Upper = CAT->getSize().getZExtValue() - 1;
|
2008-11-10 14:08:34 +08:00
|
|
|
// FIXME: Verify this is right for VLAs.
|
|
|
|
Subscripts.push_back(DebugFactory.GetOrCreateSubrange(0, Upper));
|
|
|
|
EltTy = Ty->getElementType();
|
2008-06-09 18:47:41 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIArray SubscriptArray =
|
2009-05-27 03:40:20 +08:00
|
|
|
DebugFactory.GetOrCreateArray(Subscripts.data(), Subscripts.size());
|
2008-11-10 14:08:34 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
|
|
|
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type,
|
2010-03-10 06:49:11 +08:00
|
|
|
Unit, "", Unit,
|
2009-10-21 03:55:01 +08:00
|
|
|
0, Size, Align, 0, 0,
|
|
|
|
getOrCreateType(EltTy, Unit),
|
|
|
|
SubscriptArray);
|
|
|
|
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
|
|
|
|
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;
|
|
|
|
llvm::DIDescriptor ElementTypes[2];
|
|
|
|
|
|
|
|
// FIXME: This should probably be a function type instead.
|
|
|
|
ElementTypes[0] =
|
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, U,
|
2010-03-10 06:49:11 +08:00
|
|
|
"ptr", U, 0,
|
2009-12-07 02:00:51 +08:00
|
|
|
Info.first, Info.second, FieldOffset, 0,
|
|
|
|
PointerDiffDITy);
|
|
|
|
FieldOffset += Info.first;
|
|
|
|
|
|
|
|
ElementTypes[1] =
|
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, U,
|
2010-03-10 06:49:11 +08:00
|
|
|
"ptr", U, 0,
|
2009-12-07 02:00:51 +08:00
|
|
|
Info.first, Info.second, FieldOffset, 0,
|
|
|
|
PointerDiffDITy);
|
|
|
|
|
|
|
|
llvm::DIArray Elements =
|
|
|
|
DebugFactory.GetOrCreateArray(&ElementTypes[0],
|
|
|
|
llvm::array_lengthof(ElementTypes));
|
|
|
|
|
|
|
|
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type,
|
|
|
|
U, llvm::StringRef("test"),
|
2010-03-10 06:49:11 +08:00
|
|
|
U, 0, FieldOffset,
|
2009-12-07 02:00:51 +08:00
|
|
|
0, 0, 0, llvm::DIType(), Elements);
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
case Type::TypeOfExpr: {
|
|
|
|
TypeOfExprType *Ty = cast<TypeOfExprType>(T);
|
|
|
|
T = Ty->getUnderlyingExpr()->getType();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Type::TypeOf:
|
|
|
|
T = cast<TypeOfType>(T)->getUnderlyingType();
|
|
|
|
break;
|
|
|
|
case Type::Decltype:
|
|
|
|
T = cast<DecltypeType>(T)->getUnderlyingType();
|
|
|
|
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;
|
|
|
|
case Type::SubstTemplateTypeParm:
|
|
|
|
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(T != LastT && "Type unwrapping failed to unwrap!");
|
|
|
|
if (T == LastT)
|
|
|
|
return T;
|
|
|
|
} while (true);
|
|
|
|
|
|
|
|
return T;
|
2009-11-15 05:08:12 +08:00
|
|
|
}
|
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
/// getOrCreateType - Get the type from the cache or create a new
|
|
|
|
/// one if necessary.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2008-11-10 14:08:34 +08:00
|
|
|
if (Ty.isNull())
|
|
|
|
return llvm::DIType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-22 04:18:30 +08:00
|
|
|
// Unwrap the type as needed for debug information.
|
|
|
|
Ty = UnwrapTypeForDebugInfo(Ty);
|
2009-11-15 05:08:12 +08:00
|
|
|
|
2009-09-20 03:27:24 +08:00
|
|
|
// Check for existing entry.
|
2010-03-30 02:29:57 +08:00
|
|
|
llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
|
2009-09-20 03:27:24 +08:00
|
|
|
TypeCache.find(Ty.getAsOpaquePtr());
|
2009-09-20 04:17:48 +08:00
|
|
|
if (it != TypeCache.end()) {
|
|
|
|
// Verify that the debug info still exists.
|
|
|
|
if (&*it->second)
|
|
|
|
return llvm::DIType(cast<llvm::MDNode>(it->second));
|
|
|
|
}
|
2009-09-20 03:27:14 +08:00
|
|
|
|
2009-09-20 03:27:24 +08:00
|
|
|
// Otherwise create the type.
|
|
|
|
llvm::DIType Res = CreateTypeNode(Ty, Unit);
|
2009-11-15 04:52:05 +08:00
|
|
|
|
|
|
|
// And update the type cache.
|
2010-05-08 02:12:35 +08:00
|
|
|
TypeCache[Ty.getAsOpaquePtr()] = Res;
|
2009-09-20 03:27:24 +08:00
|
|
|
return Res;
|
2009-09-20 03:27:14 +08:00
|
|
|
}
|
|
|
|
|
2009-11-15 04:52:05 +08:00
|
|
|
/// CreateTypeNode - Create a new debug type node.
|
2009-09-20 03:27:14 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-09-25 09:40:47 +08:00
|
|
|
// Handle qualifiers, which recursively handles what they refer to.
|
First part of changes to eliminate problems with cv-qualifiers and
sugared types. The basic problem is that our qualifier accessors
(getQualifiers, getCVRQualifiers, isConstQualified, etc.) only look at
the current QualType and not at any qualifiers that come from sugared
types, meaning that we won't see these qualifiers through, e.g.,
typedefs:
typedef const int CInt;
typedef CInt Self;
Self.isConstQualified() currently returns false!
Various bugs (e.g., PR5383) have cropped up all over the front end due
to such problems. I'm addressing this problem by splitting each
qualifier accessor into two versions:
- the "local" version only returns qualifiers on this particular
QualType instance
- the "normal" version that will eventually combine qualifiers from this
QualType instance with the qualifiers on the canonical type to
produce the full set of qualifiers.
This commit adds the local versions and switches a few callers from
the "normal" version (e.g., isConstQualified) over to the "local"
version (e.g., isLocalConstQualified) when that is the right thing to
do, e.g., because we're printing or serializing the qualifiers. Also,
switch a bunch of
Context.getCanonicalType(T1).getUnqualifiedType() == Context.getCanonicalType(T2).getQualifiedType()
expressions over to
Context.hasSameUnqualifiedType(T1, T2)
llvm-svn: 88969
2009-11-17 05:35:15 +08:00
|
|
|
if (Ty.hasLocalQualifiers())
|
2009-09-25 09:40:47 +08:00
|
|
|
return CreateQualifiedType(Ty, Unit);
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2009-12-22 03:57:21 +08:00
|
|
|
const char *Diag = 0;
|
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
// Work out details of type.
|
2008-11-10 14:08:34 +08:00
|
|
|
switch (Ty->getTypeClass()) {
|
2009-02-27 07:50:07 +08:00
|
|
|
#define TYPE(Class, Base)
|
|
|
|
#define ABSTRACT_TYPE(Class, Base)
|
|
|
|
#define NON_CANONICAL_TYPE(Class, Base)
|
|
|
|
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
assert(false && "Dependent types cannot show up in debug information");
|
2009-08-19 09:28:17 +08:00
|
|
|
|
2009-11-07 02:24:04 +08:00
|
|
|
// FIXME: Handle these.
|
|
|
|
case Type::ExtVector:
|
|
|
|
return llvm::DIType();
|
2010-02-24 06:59:39 +08:00
|
|
|
|
|
|
|
case Type::Vector:
|
|
|
|
return CreateType(cast<VectorType>(Ty), Unit);
|
2009-07-14 09:20:56 +08:00
|
|
|
case Type::ObjCObjectPointer:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<ObjCObjectPointerType>(Ty), Unit);
|
2010-05-15 19:32:37 +08:00
|
|
|
case Type::ObjCObject:
|
|
|
|
return CreateType(cast<ObjCObjectType>(Ty), Unit);
|
2009-09-09 23:08:12 +08:00
|
|
|
case Type::ObjCInterface:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<ObjCInterfaceType>(Ty), Unit);
|
|
|
|
case Type::Builtin: return CreateType(cast<BuiltinType>(Ty), Unit);
|
|
|
|
case Type::Complex: return CreateType(cast<ComplexType>(Ty), Unit);
|
|
|
|
case Type::Pointer: return CreateType(cast<PointerType>(Ty), Unit);
|
2009-05-14 10:03:51 +08:00
|
|
|
case Type::BlockPointer:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<BlockPointerType>(Ty), Unit);
|
|
|
|
case Type::Typedef: return CreateType(cast<TypedefType>(Ty), Unit);
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::Record:
|
|
|
|
case Type::Enum:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<TagType>(Ty), Unit);
|
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);
|
|
|
|
|
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
|
|
|
|
|
|
|
case Type::TemplateSpecialization:
|
|
|
|
case Type::Elaborated:
|
|
|
|
case Type::SubstTemplateTypeParm:
|
|
|
|
case Type::TypeOfExpr:
|
|
|
|
case Type::TypeOf:
|
2009-12-22 04:18:30 +08:00
|
|
|
case Type::Decltype:
|
|
|
|
llvm_unreachable("type should have been unwrapped!");
|
|
|
|
return llvm::DIType();
|
2009-12-22 03:57:21 +08:00
|
|
|
|
|
|
|
case Type::RValueReference:
|
|
|
|
// FIXME: Implement!
|
|
|
|
Diag = "rvalue references";
|
|
|
|
break;
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
2009-12-22 03:57:21 +08:00
|
|
|
|
|
|
|
assert(Diag && "Fall through without a diagnostic?");
|
|
|
|
unsigned DiagID = CGM.getDiags().getCustomDiagID(Diagnostic::Error,
|
|
|
|
"debug information for %0 is not yet supported");
|
|
|
|
CGM.getDiags().Report(FullSourceLoc(), DiagID)
|
|
|
|
<< Diag;
|
|
|
|
return llvm::DIType();
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2010-04-25 04:19:58 +08:00
|
|
|
/// CreateMemberType - Create new member and increase Offset by FType's size.
|
|
|
|
llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
|
|
|
|
llvm::StringRef Name,
|
|
|
|
uint64_t *Offset) {
|
|
|
|
llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);
|
|
|
|
llvm::DIType Ty = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member,
|
|
|
|
Unit, Name, Unit, 0,
|
|
|
|
FieldSize, FieldAlign,
|
|
|
|
*Offset, 0, FieldTy);
|
|
|
|
*Offset += FieldSize;
|
|
|
|
return Ty;
|
|
|
|
}
|
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
/// EmitFunctionStart - Constructs the debug code for entering a function -
|
|
|
|
/// "llvm.dbg.func.start.".
|
2010-01-14 08:36:21 +08:00
|
|
|
void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
|
2008-05-25 13:15:42 +08:00
|
|
|
llvm::Function *Fn,
|
2008-11-10 14:08:34 +08:00
|
|
|
CGBuilderTy &Builder) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-14 08:36:21 +08:00
|
|
|
llvm::StringRef Name;
|
2010-06-23 00:16:50 +08:00
|
|
|
llvm::StringRef LinkageName;
|
2010-01-14 08:36:21 +08:00
|
|
|
|
2010-07-23 06:29:16 +08:00
|
|
|
FnBeginRegionCount.push_back(RegionStack.size());
|
|
|
|
|
2010-01-14 08:36:21 +08:00
|
|
|
const Decl *D = GD.getDecl();
|
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
2010-01-19 09:54:44 +08:00
|
|
|
// If there is a DISubprogram for this function available then use it.
|
|
|
|
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
|
|
|
|
FI = SPCache.find(FD);
|
|
|
|
if (FI != SPCache.end()) {
|
2010-03-09 04:53:17 +08:00
|
|
|
llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(FI->second));
|
2010-05-08 02:12:35 +08:00
|
|
|
if (SP.isSubprogram() && llvm::DISubprogram(SP).isDefinition()) {
|
|
|
|
llvm::MDNode *SPN = SP;
|
|
|
|
RegionStack.push_back(SPN);
|
|
|
|
RegionMap[D] = llvm::WeakVH(SP);
|
2010-01-19 09:54:44 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-01-14 08:36:21 +08:00
|
|
|
Name = getFunctionName(FD);
|
|
|
|
// Use mangled name as linkage name for c/c++ functions.
|
2010-06-23 00:16:50 +08:00
|
|
|
LinkageName = CGM.getMangledName(GD);
|
2010-01-14 08:36:21 +08:00
|
|
|
} else {
|
|
|
|
// Use llvm function name as linkage name.
|
|
|
|
Name = Fn->getName();
|
2010-06-23 00:16:50 +08:00
|
|
|
LinkageName = Name;
|
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.
|
|
|
|
llvm::DIFile Unit = getOrCreateFile(CurLoc);
|
2010-05-13 07:46:38 +08:00
|
|
|
unsigned LineNo = getLineNumber(CurLoc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DISubprogram SP =
|
2010-04-24 08:49:16 +08:00
|
|
|
DebugFactory.CreateSubprogram(Unit, Name, Name, LinkageName, Unit, LineNo,
|
2009-10-23 09:52:13 +08:00
|
|
|
getOrCreateType(FnType, Unit),
|
2010-07-16 07:09:46 +08:00
|
|
|
Fn->hasInternalLinkage(), true/*definition*/,
|
|
|
|
0, 0, llvm::DIType(),
|
|
|
|
D->isImplicit(),
|
|
|
|
CGM.getLangOptions().Optimize, Fn);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
// Push function on region stack.
|
2010-05-08 02:12:35 +08:00
|
|
|
llvm::MDNode *SPN = SP;
|
|
|
|
RegionStack.push_back(SPN);
|
|
|
|
RegionMap[D] = llvm::WeakVH(SP);
|
2010-07-23 06:29:16 +08:00
|
|
|
|
|
|
|
// Clear stack used to keep track of #line directives.
|
|
|
|
LineDirectiveFiles.clear();
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-07-21 06:20:10 +08:00
|
|
|
void CGDebugInfo::EmitStopPoint(CGBuilderTy &Builder) {
|
2008-05-22 09:40:10 +08:00
|
|
|
if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-08 16:54:20 +08:00
|
|
|
// Don't bother if things are the same as last time.
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2009-09-09 23:08:12 +08:00
|
|
|
if (CurLoc == PrevLoc
|
2009-02-04 09:06:56 +08:00
|
|
|
|| (SM.getInstantiationLineNumber(CurLoc) ==
|
|
|
|
SM.getInstantiationLineNumber(PrevLoc)
|
2008-05-08 16:54:20 +08:00
|
|
|
&& SM.isFromSameFile(CurLoc, PrevLoc)))
|
2010-04-06 05:09:15 +08:00
|
|
|
// New Builder may not be in sync with CGDebugInfo.
|
|
|
|
if (!Builder.getCurrentDebugLocation().isUnknown())
|
|
|
|
return;
|
2008-05-08 16:54:20 +08:00
|
|
|
|
|
|
|
// Update last state.
|
|
|
|
PrevLoc = CurLoc;
|
|
|
|
|
2010-04-01 14:31:43 +08:00
|
|
|
llvm::MDNode *Scope = RegionStack.back();
|
2010-05-13 07:46:38 +08:00
|
|
|
Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(CurLoc),
|
|
|
|
getColumnNumber(CurLoc),
|
2010-04-03 04:21:43 +08:00
|
|
|
Scope));
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2010-07-23 06:29:16 +08:00
|
|
|
/// UpdateLineDirectiveRegion - Update region stack only if #line directive
|
|
|
|
/// has introduced scope change.
|
|
|
|
void CGDebugInfo::UpdateLineDirectiveRegion(CGBuilderTy &Builder) {
|
|
|
|
if (CurLoc.isInvalid() || CurLoc.isMacroID() ||
|
|
|
|
PrevLoc.isInvalid() || PrevLoc.isMacroID())
|
|
|
|
return;
|
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
|
|
|
PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc);
|
|
|
|
PresumedLoc PPLoc = SM.getPresumedLoc(PrevLoc);
|
|
|
|
|
|
|
|
if (!strcmp(PPLoc.getFilename(), PCLoc.getFilename()))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If #line directive stack is empty then we are entering a new scope.
|
|
|
|
if (LineDirectiveFiles.empty()) {
|
|
|
|
EmitRegionStart(Builder);
|
|
|
|
LineDirectiveFiles.push_back(PCLoc.getFilename());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert (RegionStack.size() >= LineDirectiveFiles.size()
|
|
|
|
&& "error handling #line regions!");
|
|
|
|
|
|
|
|
bool SeenThisFile = false;
|
|
|
|
for(std::vector<const char *>::iterator I = LineDirectiveFiles.begin(),
|
|
|
|
E = LineDirectiveFiles.end(); I != E; ++I)
|
|
|
|
if (!strcmp(PPLoc.getFilename(), *I)) {
|
|
|
|
SeenThisFile = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If #line for this file is seen earlier then pop out #line regions.
|
|
|
|
if (SeenThisFile) {
|
|
|
|
while (!LineDirectiveFiles.empty()) {
|
|
|
|
const char *LastFile = LineDirectiveFiles.back();
|
|
|
|
RegionStack.pop_back();
|
|
|
|
LineDirectiveFiles.pop_back();
|
|
|
|
if (!strcmp(PPLoc.getFilename(), LastFile))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// .. otherwise insert new #line region.
|
|
|
|
EmitRegionStart(Builder);
|
|
|
|
LineDirectiveFiles.push_back(PCLoc.getFilename());
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2008-05-08 16:54:20 +08:00
|
|
|
/// EmitRegionStart- Constructs the debug code for entering a declarative
|
|
|
|
/// region - "llvm.dbg.region.start.".
|
2010-07-21 06:20:10 +08:00
|
|
|
void CGDebugInfo::EmitRegionStart(CGBuilderTy &Builder) {
|
2009-11-14 03:10:24 +08:00
|
|
|
llvm::DIDescriptor D =
|
|
|
|
DebugFactory.CreateLexicalBlock(RegionStack.empty() ?
|
|
|
|
llvm::DIDescriptor() :
|
2010-02-17 05:41:20 +08:00
|
|
|
llvm::DIDescriptor(RegionStack.back()),
|
2010-07-20 07:56:31 +08:00
|
|
|
getOrCreateFile(CurLoc),
|
2010-05-13 07:46:38 +08:00
|
|
|
getLineNumber(CurLoc),
|
|
|
|
getColumnNumber(CurLoc));
|
2010-05-08 02:12:35 +08:00
|
|
|
llvm::MDNode *DN = D;
|
|
|
|
RegionStack.push_back(DN);
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitRegionEnd - Constructs the debug code for exiting a declarative
|
|
|
|
/// region - "llvm.dbg.region.end."
|
2010-07-21 06:20:10 +08:00
|
|
|
void CGDebugInfo::EmitRegionEnd(CGBuilderTy &Builder) {
|
2008-10-17 09:07:56 +08:00
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
|
2008-05-08 16:54:20 +08:00
|
|
|
// Provide an region stop point.
|
2010-07-21 06:20:10 +08:00
|
|
|
EmitStopPoint(Builder);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
RegionStack.pop_back();
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2010-07-23 06:29:16 +08:00
|
|
|
/// EmitFunctionEnd - Constructs the debug code for exiting a function.
|
|
|
|
void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
|
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
unsigned RCount = FnBeginRegionCount.back();
|
|
|
|
assert(RCount <= RegionStack.size() && "Region stack mismatch");
|
|
|
|
|
|
|
|
// Pop all regions for this function.
|
|
|
|
while (RegionStack.size() != RCount)
|
|
|
|
EmitRegionEnd(Builder);
|
|
|
|
FnBeginRegionCount.pop_back();
|
|
|
|
}
|
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
|
|
|
|
// See BuildByRefType.
|
|
|
|
llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
|
|
|
|
uint64_t *XOffset) {
|
2008-10-17 09:07:56 +08:00
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 5> EltTys;
|
2009-03-28 07:16:32 +08:00
|
|
|
|
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));
|
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
bool HasCopyAndDispose = CGM.BlockRequiresCopying(Type);
|
|
|
|
if (HasCopyAndDispose) {
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
|
2010-04-25 04:19:58 +08:00
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "__copy_helper",
|
|
|
|
&FieldOffset));
|
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "__destroy_helper",
|
|
|
|
&FieldOffset));
|
2010-02-11 02:49:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CharUnits Align = CGM.getContext().getDeclAlign(VD);
|
|
|
|
if (Align > CharUnits::fromQuantity(
|
|
|
|
CGM.getContext().Target.getPointerAlign(0) / 8)) {
|
|
|
|
unsigned AlignedOffsetInBytes
|
|
|
|
= llvm::RoundUpToAlignment(FieldOffset/8, Align.getQuantity());
|
|
|
|
unsigned NumPaddingBytes
|
|
|
|
= AlignedOffsetInBytes - FieldOffset/8;
|
2009-09-22 10:12:52 +08:00
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
if (NumPaddingBytes > 0) {
|
|
|
|
llvm::APInt pad(32, NumPaddingBytes);
|
|
|
|
FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy,
|
|
|
|
pad, ArrayType::Normal, 0);
|
2010-04-25 04:19:58 +08:00
|
|
|
EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset));
|
2009-09-22 10:12:52 +08:00
|
|
|
}
|
2010-02-11 02:49:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FType = Type;
|
2010-04-25 04:19:58 +08:00
|
|
|
llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
2010-02-11 02:49:08 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = Align.getQuantity()*8;
|
2009-09-22 10:12:52 +08:00
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
*XOffset = FieldOffset;
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
2010-03-10 06:49:11 +08:00
|
|
|
VD->getName(), Unit,
|
2010-02-11 02:49:08 +08:00
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
llvm::DIArray Elements =
|
|
|
|
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
|
|
|
|
|
|
|
unsigned Flags = llvm::DIType::FlagBlockByrefStruct;
|
|
|
|
|
|
|
|
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type,
|
2010-03-10 06:49:11 +08:00
|
|
|
Unit, "", Unit,
|
2009-09-22 10:12:52 +08:00
|
|
|
0, FieldOffset, 0, 0, Flags,
|
|
|
|
llvm::DIType(), Elements);
|
2010-02-11 02:49:08 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
/// EmitDeclare - Emit local variable declaration debug info.
|
|
|
|
void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
|
|
|
|
llvm::Value *Storage, CGBuilderTy &Builder) {
|
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
|
2010-02-11 02:49:08 +08:00
|
|
|
llvm::DIType Ty;
|
|
|
|
uint64_t XOffset = 0;
|
|
|
|
if (VD->hasAttr<BlocksAttr>())
|
|
|
|
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
|
|
|
|
else
|
|
|
|
Ty = getOrCreateType(VD->getType(), Unit);
|
2009-05-05 12:57:08 +08:00
|
|
|
|
2010-05-08 07:05:55 +08:00
|
|
|
// If there is not any debug info for type then do not emit debug info
|
|
|
|
// for this variable.
|
|
|
|
if (!Ty)
|
|
|
|
return;
|
|
|
|
|
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());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Create the descriptor for the variable.
|
2009-09-09 23:08:12 +08:00
|
|
|
llvm::DIVariable D =
|
2009-11-14 03:10:24 +08:00
|
|
|
DebugFactory.CreateVariable(Tag, llvm::DIDescriptor(RegionStack.back()),
|
2010-02-02 05:39:52 +08:00
|
|
|
VD->getName(),
|
2010-06-05 09:14:40 +08:00
|
|
|
Unit, Line, Ty, CGM.getLangOptions().Optimize);
|
2008-11-10 14:08:34 +08:00
|
|
|
// Insert an llvm.dbg.declare into the current block.
|
2009-11-12 03:10:19 +08:00
|
|
|
llvm::Instruction *Call =
|
2009-11-11 07:07:24 +08:00
|
|
|
DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock());
|
2009-11-13 02:21:39 +08:00
|
|
|
|
2010-04-01 14:31:43 +08:00
|
|
|
llvm::MDNode *Scope = RegionStack.back();
|
2010-04-03 04:21:43 +08:00
|
|
|
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
|
2008-05-30 18:30:31 +08:00
|
|
|
}
|
|
|
|
|
2009-09-30 10:43:10 +08:00
|
|
|
/// EmitDeclare - Emit local variable declaration debug info.
|
|
|
|
void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag,
|
|
|
|
llvm::Value *Storage, CGBuilderTy &Builder,
|
|
|
|
CodeGenFunction *CGF) {
|
2010-02-02 05:52:22 +08:00
|
|
|
const ValueDecl *VD = BDRE->getDecl();
|
2009-09-30 10:43:10 +08:00
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
|
2010-04-27 07:28:46 +08:00
|
|
|
if (Builder.GetInsertBlock() == 0)
|
2009-09-30 10:43:10 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
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;
|
|
|
|
if (VD->hasAttr<BlocksAttr>())
|
|
|
|
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
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
CharUnits offset = CGF->BlockDecls[VD];
|
2009-09-30 10:43:10 +08:00
|
|
|
llvm::SmallVector<llvm::Value *, 9> addr;
|
2010-01-25 11:29:35 +08:00
|
|
|
const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext());
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpDeref));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpPlus));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
|
2009-09-30 10:43:10 +08:00
|
|
|
if (BDRE->isByRef()) {
|
2010-01-25 11:29:35 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpDeref));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpPlus));
|
2010-01-12 01:06:35 +08:00
|
|
|
// offset of __forwarding field
|
|
|
|
offset = CharUnits::fromQuantity(CGF->LLVMPointerWidth/8);
|
2010-01-25 11:29:35 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpDeref));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpPlus));
|
2010-01-12 01:06:35 +08:00
|
|
|
// offset of x field
|
|
|
|
offset = CharUnits::fromQuantity(XOffset/8);
|
2010-01-25 11:29:35 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
|
2009-09-30 10:43:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create the descriptor for the variable.
|
|
|
|
llvm::DIVariable D =
|
2010-01-25 11:34:56 +08:00
|
|
|
DebugFactory.CreateComplexVariable(Tag,
|
|
|
|
llvm::DIDescriptor(RegionStack.back()),
|
2010-02-02 05:52:22 +08:00
|
|
|
VD->getName(), Unit, Line, Ty,
|
2009-09-30 10:43:10 +08:00
|
|
|
addr);
|
|
|
|
// Insert an llvm.dbg.declare into the current block.
|
2009-11-12 03:10:19 +08:00
|
|
|
llvm::Instruction *Call =
|
2010-01-25 11:34:56 +08:00
|
|
|
DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock());
|
2009-12-29 05:44:41 +08:00
|
|
|
|
2010-04-01 14:31:43 +08:00
|
|
|
llvm::MDNode *Scope = RegionStack.back();
|
2010-05-11 07:48:38 +08:00
|
|
|
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
|
2009-09-30 10:43:10 +08:00
|
|
|
}
|
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::Value *Storage,
|
|
|
|
CGBuilderTy &Builder) {
|
2010-02-02 05:52:22 +08:00
|
|
|
EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder);
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2008-06-05 16:59:10 +08:00
|
|
|
|
2009-09-30 10:43:10 +08:00
|
|
|
void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
|
|
|
|
const BlockDeclRefExpr *BDRE, llvm::Value *Storage, CGBuilderTy &Builder,
|
|
|
|
CodeGenFunction *CGF) {
|
|
|
|
EmitDeclare(BDRE, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder, CGF);
|
|
|
|
}
|
|
|
|
|
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,
|
2008-11-10 14:08:34 +08:00
|
|
|
CGBuilderTy &Builder) {
|
2010-02-02 05:52:22 +08:00
|
|
|
EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, Builder);
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2008-06-05 16:59:10 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
/// EmitGlobalVariable - Emit information about a global variable.
|
2009-09-09 23:08:12 +08:00
|
|
|
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
|
2010-02-02 05:34:11 +08:00
|
|
|
const VarDecl *D) {
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Create global variable debug descriptor.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(D->getLocation());
|
2010-05-13 07:46:38 +08:00
|
|
|
unsigned LineNo = getLineNumber(D->getLocation());
|
2008-11-24 11:54:41 +08:00
|
|
|
|
2010-02-02 05:34:11 +08:00
|
|
|
QualType T = D->getType();
|
2008-11-27 01:40:42 +08:00
|
|
|
if (T->isIncompleteArrayType()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-27 01:40:42 +08:00
|
|
|
// CodeGen turns int[] into int[1] so we'll do the same here.
|
|
|
|
llvm::APSInt ConstVal(32);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-27 01:40:42 +08:00
|
|
|
ConstVal = 1;
|
2009-12-07 02:00:51 +08:00
|
|
|
QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
T = CGM.getContext().getConstantArrayType(ET, ConstVal,
|
2008-11-27 01:40:42 +08:00
|
|
|
ArrayType::Normal, 0);
|
|
|
|
}
|
2010-04-30 01:48:37 +08:00
|
|
|
llvm::StringRef DeclName = D->getName();
|
2010-05-14 07:52:37 +08:00
|
|
|
llvm::StringRef LinkageName;
|
2010-05-15 00:55:25 +08:00
|
|
|
if (D->getDeclContext() && !isa<FunctionDecl>(D->getDeclContext()))
|
2010-05-14 07:52:37 +08:00
|
|
|
LinkageName = Var->getName();
|
2010-02-02 05:34:11 +08:00
|
|
|
llvm::DIDescriptor DContext =
|
|
|
|
getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()), Unit);
|
2010-05-14 07:52:37 +08:00
|
|
|
DebugFactory.CreateGlobalVariable(DContext, DeclName, DeclName, LinkageName,
|
|
|
|
Unit, LineNo, getOrCreateType(T, Unit),
|
2008-11-10 14:08:34 +08:00
|
|
|
Var->hasInternalLinkage(),
|
|
|
|
true/*definition*/, Var);
|
2008-06-05 16:59:10 +08:00
|
|
|
}
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
/// EmitGlobalVariable - Emit information about an objective-c interface.
|
2009-09-09 23:08:12 +08:00
|
|
|
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
|
2010-02-02 05:52:22 +08:00
|
|
|
ObjCInterfaceDecl *ID) {
|
2009-02-27 05:10:26 +08:00
|
|
|
// Create global variable debug descriptor.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(ID->getLocation());
|
2010-05-13 07:46:38 +08:00
|
|
|
unsigned LineNo = getLineNumber(ID->getLocation());
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
llvm::StringRef Name = ID->getName();
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
QualType T = CGM.getContext().getObjCInterfaceType(ID);
|
2009-02-27 05:10:26 +08:00
|
|
|
if (T->isIncompleteArrayType()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// CodeGen turns int[] into int[1] so we'll do the same here.
|
|
|
|
llvm::APSInt ConstVal(32);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
ConstVal = 1;
|
2009-12-07 02:00:51 +08:00
|
|
|
QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
T = CGM.getContext().getConstantArrayType(ET, ConstVal,
|
2009-02-27 05:10:26 +08:00
|
|
|
ArrayType::Normal, 0);
|
|
|
|
}
|
|
|
|
|
2009-10-21 02:26:30 +08:00
|
|
|
DebugFactory.CreateGlobalVariable(Unit, Name, Name, Name, Unit, LineNo,
|
2009-02-27 05:10:26 +08:00
|
|
|
getOrCreateType(T, Unit),
|
|
|
|
Var->hasInternalLinkage(),
|
|
|
|
true/*definition*/, Var);
|
|
|
|
}
|
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,
|
|
|
|
llvm::ConstantInt *Init,
|
2010-08-10 15:24:25 +08:00
|
|
|
CGBuilderTy &Builder) {
|
|
|
|
// Create the descriptor for the variable.
|
|
|
|
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
|
|
|
|
llvm::StringRef Name = VD->getName();
|
2010-08-11 02:27:15 +08:00
|
|
|
llvm::DIType Ty = getOrCreateType(VD->getType(), Unit);
|
|
|
|
// Do not use DIGlobalVariable for enums.
|
|
|
|
if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
|
|
|
|
return;
|
2010-08-10 15:24:25 +08:00
|
|
|
DebugFactory.CreateGlobalVariable(Unit, Name, Name, Name, Unit,
|
|
|
|
getLineNumber(VD->getLocation()),
|
2010-08-11 04:16:57 +08:00
|
|
|
Ty, true, 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
|
|
|
|
CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl,
|
|
|
|
llvm::DIDescriptor Unit) {
|
|
|
|
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-02-02 03:16:32 +08:00
|
|
|
|
|
|
|
llvm::DIDescriptor Context =
|
2010-02-02 05:34:11 +08:00
|
|
|
getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()), Unit);
|
2010-02-02 03:16:32 +08:00
|
|
|
llvm::DINameSpace NS =
|
|
|
|
DebugFactory.CreateNameSpace(Context, NSDecl->getName(),
|
2010-05-08 02:12:35 +08:00
|
|
|
llvm::DIFile(Unit), LineNo);
|
|
|
|
NameSpaceCache[NSDecl] = llvm::WeakVH(NS);
|
2010-02-02 03:16:32 +08:00
|
|
|
return NS;
|
|
|
|
}
|