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"
|
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"
|
2009-11-13 01:24:48 +08:00
|
|
|
#include "clang/CodeGen/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-07-15 05:31:22 +08:00
|
|
|
CGDebugInfo::CGDebugInfo(CodeGenModule *m)
|
2009-05-14 10:03:51 +08:00
|
|
|
: M(m), isMainCompileUnitCreated(false), DebugFactory(M->getModule()),
|
|
|
|
BlockLiteralGenericSet(false) {
|
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-01-16 15:36:28 +08:00
|
|
|
CurLoc = M->getContext().getSourceManager().getInstantiationLoc(Loc);
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2009-10-06 08:35:31 +08:00
|
|
|
/// getContext - Get context info for the decl.
|
|
|
|
llvm::DIDescriptor CGDebugInfo::getContext(const VarDecl *Decl,
|
|
|
|
llvm::DIDescriptor &CompileUnit) {
|
|
|
|
if (Decl->isFileVarDecl())
|
|
|
|
return CompileUnit;
|
|
|
|
if (Decl->getDeclContext()->isFunctionOrMethod()) {
|
|
|
|
// Find the last subprogram in region stack.
|
|
|
|
for (unsigned RI = RegionStack.size(), RE = 0; RI != RE; --RI) {
|
2009-11-14 03:10:24 +08:00
|
|
|
llvm::DIDescriptor R(RegionStack[RI - 1]);
|
2009-10-06 08:35:31 +08:00
|
|
|
if (R.isSubprogram())
|
|
|
|
return R;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return CompileUnit;
|
|
|
|
}
|
|
|
|
|
2008-05-08 16:54:20 +08:00
|
|
|
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a new
|
2008-10-24 16:38:36 +08:00
|
|
|
/// one if necessary. This returns null for invalid source locations.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) {
|
2009-04-18 05:06:59 +08:00
|
|
|
// Get source file information.
|
|
|
|
const char *FileName = "<unknown>";
|
2009-02-25 07:16:03 +08:00
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
2009-04-19 14:50:29 +08:00
|
|
|
unsigned FID = 0;
|
2009-01-22 08:09:25 +08:00
|
|
|
if (Loc.isValid()) {
|
2009-04-18 05:06:59 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
|
|
|
|
FileName = PLoc.getFilename();
|
|
|
|
FID = PLoc.getIncludeLoc().getRawEncoding();
|
2009-01-22 08:09:25 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-08 16:54:20 +08:00
|
|
|
// See if this compile unit has been used before.
|
2009-04-18 05:06:59 +08:00
|
|
|
llvm::DICompileUnit &Unit = CompileUnitCache[FID];
|
2008-11-10 14:08:34 +08:00
|
|
|
if (!Unit.isNull()) return Unit;
|
2009-04-08 13:11:16 +08:00
|
|
|
|
2009-04-18 05:06:59 +08:00
|
|
|
// Get absolute path name.
|
|
|
|
llvm::sys::Path AbsFileName(FileName);
|
|
|
|
if (!AbsFileName.isAbsolute()) {
|
|
|
|
llvm::sys::Path tmp = llvm::sys::Path::GetCurrentDirectory();
|
|
|
|
tmp.appendComponent(FileName);
|
|
|
|
AbsFileName = tmp;
|
|
|
|
}
|
|
|
|
|
2009-06-27 02:32:22 +08:00
|
|
|
// See if thie compile unit is representing main source file. Each source
|
|
|
|
// file has corresponding compile unit. There is only one main source
|
|
|
|
// file at a time.
|
|
|
|
bool isMain = false;
|
|
|
|
const LangOptions &LO = M->getLangOptions();
|
|
|
|
const char *MainFileName = LO.getMainFileName();
|
|
|
|
if (isMainCompileUnitCreated == false) {
|
|
|
|
if (MainFileName) {
|
|
|
|
if (!strcmp(AbsFileName.getLast().c_str(), MainFileName))
|
|
|
|
isMain = true;
|
|
|
|
} else {
|
|
|
|
if (Loc.isValid() && SM.isFromMainFile(Loc))
|
|
|
|
isMain = true;
|
|
|
|
}
|
|
|
|
if (isMain)
|
|
|
|
isMainCompileUnitCreated = true;
|
2009-04-18 05:06:59 +08:00
|
|
|
}
|
2009-04-08 13:11:16 +08:00
|
|
|
|
2009-03-25 11:28:08 +08:00
|
|
|
unsigned LangTag;
|
|
|
|
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-10-10 02:38:12 +08:00
|
|
|
std::string Producer =
|
|
|
|
#ifdef CLANG_VENDOR
|
|
|
|
CLANG_VENDOR
|
|
|
|
#endif
|
|
|
|
"clang " CLANG_VERSION_STRING;
|
2009-05-02 09:04:13 +08:00
|
|
|
bool isOptimized = LO.Optimize;
|
2009-05-02 09:00:04 +08:00
|
|
|
const char *Flags = ""; // FIXME: Encode command line options.
|
|
|
|
|
|
|
|
// 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.
|
2009-11-12 08:51:46 +08:00
|
|
|
return Unit = DebugFactory.CreateCompileUnit(LangTag,
|
|
|
|
AbsFileName.getLast().c_str(),
|
|
|
|
AbsFileName.getDirname().c_str(),
|
|
|
|
Producer.c_str(), isMain,
|
|
|
|
isOptimized, Flags, 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,
|
2009-02-25 09:36:11 +08:00
|
|
|
llvm::DICompileUnit Unit) {
|
2008-05-25 13:15:42 +08:00
|
|
|
unsigned Encoding = 0;
|
2008-11-10 14:08:34 +08:00
|
|
|
switch (BT->getKind()) {
|
|
|
|
default:
|
|
|
|
case BuiltinType::Void:
|
|
|
|
return llvm::DIType();
|
|
|
|
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
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
// Bit size, align and offset of the type.
|
2008-11-10 14:08:34 +08:00
|
|
|
uint64_t Size = M->getContext().getTypeSize(BT);
|
|
|
|
uint64_t Align = M->getContext().getTypeAlign(BT);
|
2008-05-25 13:15:42 +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,
|
|
|
|
BT->getName(M->getContext().getLangOptions()),
|
|
|
|
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,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
// 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-04-23 14:13:01 +08:00
|
|
|
uint64_t Size = M->getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
|
|
|
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.
|
2009-09-25 09:40:47 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DICompileUnit Unit) {
|
|
|
|
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 =
|
|
|
|
DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(),
|
|
|
|
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,
|
|
|
|
llvm::DICompileUnit 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,
|
|
|
|
llvm::DICompileUnit 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,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
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 =
|
|
|
|
M->getContext().Target.getPointerWidth(PointeeTy.getAddressSpace());
|
2008-11-10 14:08:34 +08:00
|
|
|
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
return
|
2009-11-07 03:19:55 +08:00
|
|
|
DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(),
|
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,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
if (BlockLiteralGenericSet)
|
|
|
|
return BlockLiteralGeneric;
|
|
|
|
|
|
|
|
llvm::DICompileUnit DefUnit;
|
|
|
|
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;
|
|
|
|
FType = M->getContext().UnsignedLongTy;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"reserved", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
FType = M->getContext().UnsignedLongTy;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"Size", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
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
|
|
|
EltTys.clear();
|
|
|
|
|
2009-10-02 10:30:50 +08:00
|
|
|
unsigned Flags = llvm::DIType::FlagAppleBlock;
|
|
|
|
|
2009-05-14 10:03:51 +08:00
|
|
|
EltTy = DebugFactory.CreateCompositeType(Tag, Unit, "__block_descriptor",
|
2009-10-02 10:30:50 +08:00
|
|
|
DefUnit, 0, FieldOffset, 0, 0, Flags,
|
2009-05-14 10:03:51 +08:00
|
|
|
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.
|
|
|
|
uint64_t Size = M->getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = M->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,
|
|
|
|
Unit, "", llvm::DICompileUnit(),
|
|
|
|
0, Size, Align, 0, 0, EltTy);
|
|
|
|
|
|
|
|
FieldOffset = 0;
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__isa", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
FType = M->getContext().IntTy;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__flags", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
FType = M->getContext().IntTy;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__reserved", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__FuncPtr", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = DescTy;
|
|
|
|
FieldSize = M->getContext().getTypeSize(Ty);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(Ty);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__descriptor", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
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",
|
2009-10-02 10:23:37 +08:00
|
|
|
DefUnit, 0, FieldOffset, 0, 0, Flags,
|
2009-05-14 10:03:51 +08:00
|
|
|
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,
|
|
|
|
"", llvm::DICompileUnit(),
|
|
|
|
0, Size, Align, 0, 0, EltTy);
|
|
|
|
return BlockLiteralGeneric;
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
// 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.
|
|
|
|
SourceLocation DefLoc = Ty->getDecl()->getLocation();
|
|
|
|
llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(DefLoc);
|
2008-05-25 13:15:42 +08:00
|
|
|
|
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(DefLoc);
|
|
|
|
unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit,
|
2009-11-26 01:37:31 +08:00
|
|
|
Ty->getDecl()->getName(),
|
2009-11-12 08:51:46 +08:00
|
|
|
DefUnit, 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,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
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,
|
|
|
|
Unit, "", llvm::DICompileUnit(),
|
|
|
|
0, 0, 0, 0, 0,
|
|
|
|
llvm::DIType(), EltTypeArray);
|
|
|
|
return DbgTy;
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
llvm::DICompileUnit Unit) {
|
2008-12-12 01:59:21 +08:00
|
|
|
RecordDecl *Decl = Ty->getDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
unsigned Tag;
|
|
|
|
if (Decl->isStruct())
|
|
|
|
Tag = llvm::dwarf::DW_TAG_structure_type;
|
|
|
|
else if (Decl->isUnion())
|
|
|
|
Tag = llvm::dwarf::DW_TAG_union_type;
|
|
|
|
else {
|
|
|
|
assert(Decl->isClass() && "Unknown RecordType!");
|
|
|
|
Tag = llvm::dwarf::DW_TAG_class_type;
|
2008-06-07 12:46:53 +08:00
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-06-07 12:46:53 +08:00
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Get overall information about the record type for the debug info.
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
|
2009-05-05 13:16:17 +08:00
|
|
|
llvm::DICompileUnit DefUnit;
|
|
|
|
unsigned Line = 0;
|
|
|
|
if (!PLoc.isInvalid()) {
|
|
|
|
DefUnit = getOrCreateCompileUnit(Decl->getLocation());
|
|
|
|
Line = PLoc.getLine();
|
|
|
|
}
|
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.
|
2009-07-23 02:57:00 +08:00
|
|
|
llvm::DICompositeType FwdDecl =
|
2009-11-26 01:37:31 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, Decl->getName(),
|
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
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// If this is just a forward declaration, return it.
|
|
|
|
if (!Decl->getDefinition(M->getContext()))
|
|
|
|
return FwdDecl;
|
|
|
|
|
2009-11-17 05:04:30 +08:00
|
|
|
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = FwdDecl.getNode();
|
2008-11-10 14:08:34 +08:00
|
|
|
// Otherwise, insert it into the TypeCache so that recursive uses will find
|
|
|
|
// it.
|
2009-09-20 03:27:24 +08:00
|
|
|
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl.getNode();
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
// Convert all the elements.
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
|
|
|
|
|
|
|
|
const ASTRecordLayout &RL = M->getContext().getASTRecordLayout(Decl);
|
|
|
|
|
|
|
|
unsigned FieldNo = 0;
|
2009-06-30 10:36:12 +08:00
|
|
|
for (RecordDecl::field_iterator I = Decl->field_begin(),
|
2009-09-09 23:08:12 +08:00
|
|
|
E = Decl->field_end();
|
2008-12-12 01:59:21 +08:00
|
|
|
I != E; ++I, ++FieldNo) {
|
2008-11-10 14:08:34 +08:00
|
|
|
FieldDecl *Field = *I;
|
|
|
|
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
|
2008-11-24 11:54:41 +08:00
|
|
|
|
2009-11-26 01:37:31 +08:00
|
|
|
llvm::StringRef FieldName = Field->getName();
|
2008-11-10 14:08:34 +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;
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Get the location for the field.
|
|
|
|
SourceLocation FieldDefLoc = Field->getLocation();
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(FieldDefLoc);
|
2009-05-05 13:16:17 +08:00
|
|
|
llvm::DICompileUnit FieldDefUnit;
|
|
|
|
unsigned FieldLine = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-05 13:16:17 +08:00
|
|
|
if (!PLoc.isInvalid()) {
|
|
|
|
FieldDefUnit = getOrCreateCompileUnit(FieldDefLoc);
|
|
|
|
FieldLine = PLoc.getLine();
|
|
|
|
}
|
2009-03-17 07:47:53 +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-17 07:47:53 +08:00
|
|
|
// Bit size, align and offset of the type.
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
Expr *BitWidth = Field->getBitWidth();
|
|
|
|
if (BitWidth)
|
2009-04-27 03:19:15 +08:00
|
|
|
FieldSize = BitWidth->EvaluateAsInt(M->getContext()).getZExtValue();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-17 07:47:53 +08:00
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
uint64_t FieldOffset = RL.getFieldOffset(FieldNo);
|
|
|
|
|
2008-11-10 14:08:34 +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,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
2008-06-07 12:46:53 +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.
|
|
|
|
uint64_t Size = M->getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-23 02:57:00 +08:00
|
|
|
llvm::DICompositeType RealDecl =
|
2009-11-26 01:37:31 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, Decl->getName(),
|
2009-11-12 08:51:46 +08:00
|
|
|
DefUnit, Line, Size, Align, 0, 0,
|
|
|
|
llvm::DIType(), Elements);
|
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);
|
2009-07-14 01:03:14 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
return RealDecl;
|
2008-06-07 12:46:53 +08:00
|
|
|
}
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
/// CreateType - get objective-c interface type.
|
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
ObjCInterfaceDecl *Decl = Ty->getDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
unsigned Tag = llvm::dwarf::DW_TAG_structure_type;
|
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
|
|
|
|
|
|
|
// Get overall information about the record type for the debug info.
|
|
|
|
llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(Decl->getLocation());
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
|
|
|
|
unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-19 04:51:58 +08:00
|
|
|
unsigned RuntimeLang = DefUnit.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 =
|
2009-11-26 01:37:31 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, Decl->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.
|
|
|
|
if (Decl->isForwardDecl())
|
|
|
|
return FwdDecl;
|
|
|
|
|
2009-11-17 04:09:38 +08:00
|
|
|
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = FwdDecl.getNode();
|
2009-02-27 05:10:26 +08:00
|
|
|
// Otherwise, insert it into the TypeCache so that recursive uses will find
|
|
|
|
// it.
|
2009-09-20 03:27:24 +08:00
|
|
|
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl.getNode();
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
// Convert all the elements.
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
|
|
|
|
|
2009-03-11 05:30:26 +08:00
|
|
|
ObjCInterfaceDecl *SClass = Decl->getSuperClass();
|
|
|
|
if (SClass) {
|
2009-09-09 23:08:12 +08:00
|
|
|
llvm::DIType SClassTy =
|
2009-03-11 05:30:26 +08:00
|
|
|
getOrCreateType(M->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,
|
2009-05-05 13:05:36 +08:00
|
|
|
Unit, "", llvm::DICompileUnit(), 0, 0, 0,
|
2009-03-11 05:30:26 +08:00
|
|
|
0 /* offset */, 0, SClassTy);
|
|
|
|
EltTys.push_back(InhTag);
|
|
|
|
}
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
const ASTRecordLayout &RL = M->getContext().getASTObjCInterfaceLayout(Decl);
|
|
|
|
|
|
|
|
unsigned FieldNo = 0;
|
|
|
|
for (ObjCInterfaceDecl::ivar_iterator I = Decl->ivar_begin(),
|
|
|
|
E = Decl->ivar_end(); I != E; ++I, ++FieldNo) {
|
|
|
|
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.
|
|
|
|
SourceLocation FieldDefLoc = Field->getLocation();
|
|
|
|
llvm::DICompileUnit FieldDefUnit = getOrCreateCompileUnit(FieldDefLoc);
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(FieldDefLoc);
|
|
|
|
unsigned FieldLine = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
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.
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
Expr *BitWidth = Field->getBitWidth();
|
|
|
|
if (BitWidth)
|
2009-04-27 03:19:15 +08:00
|
|
|
FieldSize = BitWidth->EvaluateAsInt(M->getContext()).getZExtValue();
|
|
|
|
|
2009-03-21 02:24:39 +08:00
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
}
|
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
|
|
|
|
|
|
|
// Bit size, align and offset of the type.
|
|
|
|
uint64_t Size = M->getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-28 02:42:03 +08:00
|
|
|
llvm::DICompositeType RealDecl =
|
2009-11-26 01:37:31 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, Decl->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);
|
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,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
EnumDecl *Decl = 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
|
2009-06-30 10:36:12 +08:00
|
|
|
Enum = Decl->enumerator_begin(), EnumEnd = Decl->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
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
SourceLocation DefLoc = Decl->getLocation();
|
|
|
|
llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(DefLoc);
|
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(DefLoc);
|
|
|
|
unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
|
|
|
|
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()) {
|
|
|
|
Size = M->getContext().getTypeSize(Ty);
|
|
|
|
Align = M->getContext().getTypeAlign(Ty);
|
|
|
|
}
|
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,
|
2009-11-26 01:37:31 +08:00
|
|
|
Unit, Decl->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,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
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
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
|
|
|
|
llvm::DICompileUnit 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-01-28 08:35:17 +08:00
|
|
|
M->getContext().getTypeAlign(M->getContext().getBaseElementType(VAT));
|
|
|
|
} else if (Ty->isIncompleteArrayType()) {
|
|
|
|
Size = 0;
|
|
|
|
Align = M->getContext().getTypeAlign(Ty->getElementType());
|
2009-01-05 09:23:29 +08:00
|
|
|
} else {
|
|
|
|
// Size and align of the whole array, not the element type.
|
|
|
|
Size = M->getContext().getTypeSize(Ty);
|
|
|
|
Align = M->getContext().getTypeAlign(Ty);
|
|
|
|
}
|
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,
|
|
|
|
Unit, "", llvm::DICompileUnit(),
|
|
|
|
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,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type,
|
|
|
|
Ty, Ty->getPointeeType(), Unit);
|
|
|
|
}
|
2008-06-07 12:46:53 +08:00
|
|
|
|
2009-11-15 05:08:12 +08:00
|
|
|
static QualType CanonicalizeTypeForDebugInfo(QualType T) {
|
|
|
|
switch (T->getTypeClass()) {
|
|
|
|
default:
|
|
|
|
return T;
|
|
|
|
case Type::TemplateSpecialization:
|
|
|
|
return cast<TemplateSpecializationType>(T)->desugar();
|
|
|
|
case Type::TypeOfExpr: {
|
|
|
|
TypeOfExprType *Ty = cast<TypeOfExprType>(T);
|
|
|
|
return CanonicalizeTypeForDebugInfo(Ty->getUnderlyingExpr()->getType());
|
|
|
|
}
|
|
|
|
case Type::TypeOf:
|
|
|
|
return cast<TypeOfType>(T)->getUnderlyingType();
|
|
|
|
case Type::Decltype:
|
|
|
|
return cast<DecltypeType>(T)->getUnderlyingType();
|
|
|
|
case Type::QualifiedName:
|
|
|
|
return cast<QualifiedNameType>(T)->getNamedType();
|
|
|
|
case Type::SubstTemplateTypeParm:
|
|
|
|
return cast<SubstTemplateTypeParmType>(T)->getReplacementType();
|
|
|
|
case Type::Elaborated:
|
|
|
|
return cast<ElaboratedType>(T)->getUnderlyingType();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
if (Ty.isNull())
|
|
|
|
return llvm::DIType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-15 05:08:12 +08:00
|
|
|
// Canonicalize the type.
|
|
|
|
Ty = CanonicalizeTypeForDebugInfo(Ty);
|
|
|
|
|
2009-09-20 03:27:24 +08:00
|
|
|
// Check for existing entry.
|
2009-09-20 04:17:48 +08:00
|
|
|
std::map<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.
|
|
|
|
TypeCache[Ty.getAsOpaquePtr()] = Res.getNode();
|
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,
|
|
|
|
llvm::DICompileUnit 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
|
|
|
|
|
|
|
// 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:
|
|
|
|
case Type::Vector:
|
2009-11-07 09:19:37 +08:00
|
|
|
case Type::FixedWidthInt:
|
2009-11-07 02:24:04 +08:00
|
|
|
return llvm::DIType();
|
2009-09-20 03:27:14 +08:00
|
|
|
default:
|
2009-11-07 09:19:37 +08:00
|
|
|
assert(false && "Unhandled type class!");
|
2008-11-10 14:08:34 +08:00
|
|
|
return llvm::DIType();
|
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);
|
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);
|
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitFunctionStart - Constructs the debug code for entering a function -
|
|
|
|
/// "llvm.dbg.func.start.".
|
2009-10-23 09:52:13 +08:00
|
|
|
void CGDebugInfo::EmitFunctionStart(const char *Name, QualType FnType,
|
2008-05-25 13:15:42 +08:00
|
|
|
llvm::Function *Fn,
|
2008-11-10 14:08:34 +08:00
|
|
|
CGBuilderTy &Builder) {
|
2009-07-15 05:31:22 +08:00
|
|
|
const char *LinkageName = Name;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-14 07:08:57 +08:00
|
|
|
// Skip the asm prefix if it exists.
|
2009-05-14 09:45:24 +08:00
|
|
|
//
|
|
|
|
// FIXME: This should probably be the unmangled name?
|
2009-05-14 07:08:57 +08:00
|
|
|
if (Name[0] == '\01')
|
|
|
|
++Name;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// FIXME: Why is this using CurLoc???
|
|
|
|
llvm::DICompileUnit Unit = getOrCreateCompileUnit(CurLoc);
|
2008-05-25 13:15:42 +08:00
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
2009-04-09 03:47:04 +08:00
|
|
|
unsigned LineNo = SM.getPresumedLoc(CurLoc).getLine();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DISubprogram SP =
|
2009-07-15 05:31:22 +08:00
|
|
|
DebugFactory.CreateSubprogram(Unit, Name, Name, LinkageName, Unit, LineNo,
|
2009-10-23 09:52:13 +08:00
|
|
|
getOrCreateType(FnType, Unit),
|
2008-11-10 14:08:34 +08:00
|
|
|
Fn->hasInternalLinkage(), true/*definition*/);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
// Push function on region stack.
|
2009-11-14 03:10:24 +08:00
|
|
|
RegionStack.push_back(SP.getNode());
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, 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.
|
|
|
|
SourceManager &SM = M->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)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Update last state.
|
|
|
|
PrevLoc = CurLoc;
|
|
|
|
|
|
|
|
// Get the appropriate compile unit.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DICompileUnit Unit = getOrCreateCompileUnit(CurLoc);
|
2009-04-09 03:47:04 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(CurLoc);
|
2009-10-07 02:36:08 +08:00
|
|
|
|
2009-11-14 03:10:24 +08:00
|
|
|
llvm::DIDescriptor DR(RegionStack.back());
|
2009-10-07 02:36:08 +08:00
|
|
|
llvm::DIScope DS = llvm::DIScope(DR.getNode());
|
|
|
|
llvm::DILocation DO(NULL);
|
|
|
|
llvm::DILocation DL =
|
|
|
|
DebugFactory.CreateLocation(PLoc.getLine(), PLoc.getColumn(),
|
|
|
|
DS, DO);
|
|
|
|
Builder.SetCurrentDebugLocation(DL.getNode());
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitRegionStart- Constructs the debug code for entering a declarative
|
|
|
|
/// region - "llvm.dbg.region.start.".
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, CGBuilderTy &Builder) {
|
2009-11-14 03:10:24 +08:00
|
|
|
llvm::DIDescriptor D =
|
|
|
|
DebugFactory.CreateLexicalBlock(RegionStack.empty() ?
|
|
|
|
llvm::DIDescriptor() :
|
|
|
|
llvm::DIDescriptor(RegionStack.back()));
|
|
|
|
RegionStack.push_back(D.getNode());
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitRegionEnd - Constructs the debug code for exiting a declarative
|
|
|
|
/// region - "llvm.dbg.region.end."
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, 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.
|
|
|
|
EmitStopPoint(Fn, 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
|
|
|
}
|
|
|
|
|
2008-05-30 18:30:31 +08:00
|
|
|
/// EmitDeclare - Emit local variable declaration debug info.
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::EmitDeclare(const VarDecl *Decl, unsigned Tag,
|
|
|
|
llvm::Value *Storage, CGBuilderTy &Builder) {
|
2008-10-17 09:07:56 +08:00
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
|
2009-03-28 07:16:32 +08:00
|
|
|
// Do not emit variable debug information while generating optimized code.
|
|
|
|
// The llvm optimizer and code generator are not yet ready to support
|
|
|
|
// optimized code debugging.
|
2009-11-13 01:24:48 +08:00
|
|
|
const CodeGenOptions &CGO = M->getCodeGenOpts();
|
|
|
|
if (CGO.OptimizationLevel)
|
2009-03-28 07:16:32 +08:00
|
|
|
return;
|
|
|
|
|
2009-05-05 12:57:08 +08:00
|
|
|
llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation());
|
2009-09-22 10:12:52 +08:00
|
|
|
QualType Type = Decl->getType();
|
|
|
|
llvm::DIType Ty = getOrCreateType(Type, Unit);
|
|
|
|
if (Decl->hasAttr<BlocksAttr>()) {
|
|
|
|
llvm::DICompileUnit DefUnit;
|
|
|
|
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;
|
|
|
|
|
|
|
|
// Build up structure for the byref. See BuildByRefType.
|
|
|
|
FieldOffset = 0;
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__isa", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__forwarding", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
FType = M->getContext().getFixedWidthIntType(32, true); // Int32Ty;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__flags", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
FType = M->getContext().getFixedWidthIntType(32, true); // Int32Ty;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__size", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
bool HasCopyAndDispose = M->BlockRequiresCopying(Type);
|
|
|
|
if (HasCopyAndDispose) {
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__copy_helper", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__destroy_helper", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned Align = M->getContext().getDeclAlignInBytes(Decl);
|
|
|
|
if (Align > M->getContext().Target.getPointerAlign(0) / 8) {
|
|
|
|
unsigned AlignedOffsetInBytes
|
2009-09-22 10:44:17 +08:00
|
|
|
= llvm::RoundUpToAlignment(FieldOffset/8, Align);
|
2009-09-22 10:12:52 +08:00
|
|
|
unsigned NumPaddingBytes
|
2009-09-22 10:44:17 +08:00
|
|
|
= AlignedOffsetInBytes - FieldOffset/8;
|
2009-09-22 10:12:52 +08:00
|
|
|
|
|
|
|
if (NumPaddingBytes > 0) {
|
|
|
|
llvm::APInt pad(32, NumPaddingBytes);
|
|
|
|
FType = M->getContext().getConstantArrayType(M->getContext().CharTy,
|
|
|
|
pad, ArrayType::Normal, 0);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member,
|
|
|
|
Unit, "", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FType = Type;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
2009-09-22 10:44:17 +08:00
|
|
|
FieldAlign = Align*8;
|
2009-09-22 10:12:52 +08:00
|
|
|
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
2009-11-26 01:37:31 +08:00
|
|
|
Decl->getName(), DefUnit,
|
2009-09-22 10:12:52 +08:00
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
|
|
|
|
|
|
|
unsigned Flags = llvm::DIType::FlagBlockByrefStruct;
|
|
|
|
|
|
|
|
Ty = DebugFactory.CreateCompositeType(Tag, Unit, "",
|
|
|
|
llvm::DICompileUnit(),
|
|
|
|
0, FieldOffset, 0, 0, Flags,
|
|
|
|
llvm::DIType(), Elements);
|
|
|
|
}
|
2009-05-05 12:57:08 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Get location information.
|
2008-05-30 18:30:31 +08:00
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
|
2009-05-05 12:57:08 +08:00
|
|
|
unsigned Line = 0;
|
2009-11-17 04:33:31 +08:00
|
|
|
unsigned Column = 0;
|
|
|
|
if (!PLoc.isInvalid()) {
|
2009-05-05 12:57:08 +08:00
|
|
|
Line = PLoc.getLine();
|
2009-11-17 04:33:31 +08:00
|
|
|
Column = PLoc.getColumn();
|
|
|
|
} else {
|
2009-05-05 12:57:08 +08:00
|
|
|
Unit = llvm::DICompileUnit();
|
2009-11-17 04:33:31 +08:00
|
|
|
}
|
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()),
|
2009-11-26 01:37:31 +08:00
|
|
|
Decl->getName(),
|
2009-05-05 12:57:08 +08:00
|
|
|
Unit, Line, Ty);
|
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
|
|
|
|
2009-11-14 03:10:24 +08:00
|
|
|
llvm::DIScope DS(RegionStack.back());
|
2009-11-13 02:21:39 +08:00
|
|
|
llvm::DILocation DO(NULL);
|
|
|
|
llvm::DILocation DL =
|
2009-11-17 04:33:31 +08:00
|
|
|
DebugFactory.CreateLocation(Line, Column, DS, DO);
|
2009-11-13 02:21:39 +08:00
|
|
|
Builder.SetDebugLocation(Call, DL.getNode());
|
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) {
|
|
|
|
const ValueDecl *Decl = BDRE->getDecl();
|
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
|
|
|
|
// Do not emit variable debug information while generating optimized code.
|
|
|
|
// The llvm optimizer and code generator are not yet ready to support
|
|
|
|
// optimized code debugging.
|
2009-11-13 01:24:48 +08:00
|
|
|
const CodeGenOptions &CGO = M->getCodeGenOpts();
|
|
|
|
if (CGO.OptimizationLevel || Builder.GetInsertBlock() == 0)
|
2009-09-30 10:43:10 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
uint64_t XOffset = 0;
|
|
|
|
llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation());
|
|
|
|
QualType Type = Decl->getType();
|
|
|
|
llvm::DIType Ty = getOrCreateType(Type, Unit);
|
|
|
|
if (Decl->hasAttr<BlocksAttr>()) {
|
|
|
|
llvm::DICompileUnit DefUnit;
|
|
|
|
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;
|
|
|
|
|
|
|
|
// Build up structure for the byref. See BuildByRefType.
|
|
|
|
FieldOffset = 0;
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__isa", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__forwarding", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
FType = M->getContext().getFixedWidthIntType(32, true); // Int32Ty;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__flags", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
FType = M->getContext().getFixedWidthIntType(32, true); // Int32Ty;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__size", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
bool HasCopyAndDispose = M->BlockRequiresCopying(Type);
|
|
|
|
if (HasCopyAndDispose) {
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__copy_helper", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__destroy_helper", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned Align = M->getContext().getDeclAlignInBytes(Decl);
|
|
|
|
if (Align > M->getContext().Target.getPointerAlign(0) / 8) {
|
|
|
|
unsigned AlignedOffsetInBytes
|
|
|
|
= llvm::RoundUpToAlignment(FieldOffset/8, Align);
|
|
|
|
unsigned NumPaddingBytes
|
|
|
|
= AlignedOffsetInBytes - FieldOffset/8;
|
|
|
|
|
|
|
|
if (NumPaddingBytes > 0) {
|
|
|
|
llvm::APInt pad(32, NumPaddingBytes);
|
|
|
|
FType = M->getContext().getConstantArrayType(M->getContext().CharTy,
|
|
|
|
pad, ArrayType::Normal, 0);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member,
|
|
|
|
Unit, "", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FType = Type;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = Align*8;
|
|
|
|
|
|
|
|
XOffset = FieldOffset;
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
2009-11-26 01:37:31 +08:00
|
|
|
Decl->getName(), DefUnit,
|
2009-09-30 10:43:10 +08:00
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
|
|
|
|
|
|
|
unsigned Flags = llvm::DIType::FlagBlockByrefStruct;
|
|
|
|
|
|
|
|
Ty = DebugFactory.CreateCompositeType(Tag, Unit, "",
|
|
|
|
llvm::DICompileUnit(),
|
|
|
|
0, FieldOffset, 0, 0, Flags,
|
|
|
|
llvm::DIType(), Elements);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get location information.
|
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
|
|
|
|
unsigned Line = 0;
|
|
|
|
if (!PLoc.isInvalid())
|
|
|
|
Line = PLoc.getLine();
|
|
|
|
else
|
|
|
|
Unit = llvm::DICompileUnit();
|
|
|
|
|
|
|
|
uint64_t offset = CGF->BlockDecls[Decl];
|
|
|
|
llvm::SmallVector<llvm::Value *, 9> addr;
|
|
|
|
llvm::LLVMContext &VMContext = M->getLLVMContext();
|
|
|
|
addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
|
|
|
llvm::DIFactory::OpDeref));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
|
|
|
llvm::DIFactory::OpPlus));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
|
|
|
offset));
|
|
|
|
if (BDRE->isByRef()) {
|
|
|
|
addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
|
|
|
llvm::DIFactory::OpDeref));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
|
|
|
llvm::DIFactory::OpPlus));
|
|
|
|
offset = CGF->LLVMPointerWidth/8; // offset of __forwarding field
|
|
|
|
addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
|
|
|
offset));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
|
|
|
llvm::DIFactory::OpDeref));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
|
|
|
llvm::DIFactory::OpPlus));
|
|
|
|
offset = XOffset/8; // offset of x field
|
|
|
|
addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
|
|
|
offset));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the descriptor for the variable.
|
|
|
|
llvm::DIVariable D =
|
2009-11-14 03:10:24 +08:00
|
|
|
DebugFactory.CreateComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()),
|
2009-11-26 01:37:31 +08:00
|
|
|
Decl->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 =
|
|
|
|
DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertPoint());
|
2009-11-13 02:21:39 +08:00
|
|
|
|
2009-11-14 03:10:24 +08:00
|
|
|
llvm::DIScope DS(RegionStack.back());
|
2009-11-13 02:21:39 +08:00
|
|
|
llvm::DILocation DO(NULL);
|
|
|
|
llvm::DILocation DL =
|
|
|
|
DebugFactory.CreateLocation(Line, PLoc.getColumn(), DS, DO);
|
|
|
|
Builder.SetDebugLocation(Call, DL.getNode());
|
2009-09-30 10:43:10 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *Decl,
|
|
|
|
llvm::Value *Storage,
|
|
|
|
CGBuilderTy &Builder) {
|
|
|
|
EmitDeclare(Decl, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder);
|
|
|
|
}
|
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.
|
|
|
|
void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
|
|
|
|
CGBuilderTy &Builder) {
|
|
|
|
EmitDeclare(Decl, llvm::dwarf::DW_TAG_arg_variable, AI, Builder);
|
|
|
|
}
|
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,
|
2008-11-10 14:08:34 +08:00
|
|
|
const VarDecl *Decl) {
|
2009-03-28 07:16:32 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Create global variable debug descriptor.
|
|
|
|
llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation());
|
2008-06-05 16:59:10 +08:00
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
|
|
|
|
unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
2008-11-24 11:54:41 +08:00
|
|
|
|
2008-11-27 01:40:42 +08:00
|
|
|
QualType T = Decl->getType();
|
|
|
|
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;
|
|
|
|
QualType ET = M->getContext().getAsArrayType(T)->getElementType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
T = M->getContext().getConstantArrayType(ET, ConstVal,
|
2008-11-27 01:40:42 +08:00
|
|
|
ArrayType::Normal, 0);
|
|
|
|
}
|
2009-11-26 01:37:31 +08:00
|
|
|
llvm::StringRef DeclName = Decl->getName();
|
2009-11-12 08:51:46 +08:00
|
|
|
DebugFactory.CreateGlobalVariable(getContext(Decl, Unit), DeclName, DeclName,
|
2009-11-26 01:37:31 +08:00
|
|
|
llvm::StringRef(), Unit, LineNo,
|
2008-11-27 01:40:42 +08:00
|
|
|
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,
|
2009-02-27 05:10:26 +08:00
|
|
|
ObjCInterfaceDecl *Decl) {
|
|
|
|
// Create global variable debug descriptor.
|
|
|
|
llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation());
|
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
|
|
|
|
unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2009-11-26 01:37:31 +08:00
|
|
|
llvm::StringRef Name = Decl->getName();
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2009-04-01 14:23:52 +08:00
|
|
|
QualType T = M->getContext().getObjCInterfaceType(Decl);
|
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;
|
|
|
|
QualType ET = M->getContext().getAsArrayType(T)->getElementType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
T = M->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);
|
|
|
|
}
|