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-03-28 07:16:32 +08:00
|
|
|
#include "clang/Frontend/CompileOptions.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) {
|
|
|
|
llvm::DIDescriptor R = RegionStack[RI - 1];
|
|
|
|
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-09-16 05:48:34 +08:00
|
|
|
std::string Producer = "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-06-27 02:32:22 +08:00
|
|
|
return Unit = DebugFactory.CreateCompileUnit(LangTag, AbsFileName.getLast(),
|
2009-09-09 23:08:12 +08:00
|
|
|
AbsFileName.getDirname(),
|
2009-06-27 02:32:22 +08:00
|
|
|
Producer, 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:
|
|
|
|
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
|
|
|
|
|
|
|
return DebugFactory.CreateBasicType(Unit,
|
2009-06-30 09:26:17 +08:00
|
|
|
BT->getName(M->getContext().getLangOptions()),
|
2009-05-30 04:38:28 +08:00
|
|
|
Unit, 0, Size, Align,
|
2008-11-10 14:08:34 +08:00
|
|
|
Offset, /*flags*/ 0, Encoding);
|
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-04-23 14:13:01 +08:00
|
|
|
return DebugFactory.CreateBasicType(Unit, "complex",
|
|
|
|
Unit, 0, Size, Align,
|
|
|
|
Offset, /*flags*/ 0, Encoding);
|
|
|
|
}
|
|
|
|
|
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.
|
|
|
|
return DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(),
|
|
|
|
0, 0, 0, 0, 0, FromTy);
|
|
|
|
}
|
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) {
|
|
|
|
llvm::DIType EltTy = getOrCreateType(Ty->getPointeeType(), Unit);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-14 09:20:56 +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-14 09:20:56 +08:00
|
|
|
return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
|
|
|
|
"", llvm::DICompileUnit(),
|
|
|
|
0, Size, Align, 0, 0, EltTy);
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
llvm::DIType EltTy = getOrCreateType(Ty->getPointeeType(), 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.
|
2008-11-10 14:08:34 +08:00
|
|
|
uint64_t Size = M->getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
|
|
|
|
"", llvm::DICompileUnit(),
|
|
|
|
0, Size, Align, 0, 0, EltTy);
|
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.
|
2008-11-24 11:54:41 +08:00
|
|
|
std::string TyName = Ty->getDecl()->getNameAsString();
|
2008-11-10 14:08:34 +08:00
|
|
|
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
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit,
|
|
|
|
TyName, DefUnit, Line, 0, 0, 0, 0, Src);
|
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
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
|
|
|
|
Unit, "", llvm::DICompileUnit(),
|
|
|
|
0, 0, 0, 0, 0,
|
|
|
|
llvm::DIType(), EltTypeArray);
|
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.
|
2008-11-24 11:54:41 +08:00
|
|
|
std::string Name = Decl->getNameAsString();
|
2008-11-10 14:08:34 +08:00
|
|
|
|
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 =
|
2008-11-10 14:08:34 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, 0, 0, 0, 0,
|
|
|
|
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;
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
|
|
std::string FieldName = Field->getNameAsString();
|
2008-11-10 14:08:34 +08:00
|
|
|
|
2009-04-28 06:40:36 +08:00
|
|
|
// Ignore unnamed fields.
|
|
|
|
if (FieldName.empty())
|
|
|
|
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 =
|
2008-11-10 14:08:34 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, Size,
|
|
|
|
Align, 0, 0, llvm::DIType(), Elements);
|
|
|
|
|
2009-09-20 03:27:24 +08:00
|
|
|
// Update TypeCache.
|
|
|
|
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl.getNode();
|
|
|
|
|
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-07-23 02:57:00 +08:00
|
|
|
FwdDecl.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.
|
|
|
|
std::string Name = Decl->getNameAsString();
|
|
|
|
|
|
|
|
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-02-27 05:10:26 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, Name, 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;
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
std::string FieldName = Field->getNameAsString();
|
|
|
|
|
2009-04-28 06:40:36 +08:00
|
|
|
// Ignore unnamed fields.
|
|
|
|
if (FieldName.empty())
|
|
|
|
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-02-27 05:10:26 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, Size,
|
2009-05-02 09:13:16 +08:00
|
|
|
Align, 0, 0, llvm::DIType(), Elements,
|
|
|
|
RuntimeLang);
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2009-09-20 03:27:24 +08:00
|
|
|
// Update TypeCache.
|
|
|
|
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl.getNode();
|
|
|
|
|
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-07-28 02:42:03 +08:00
|
|
|
FwdDecl.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) {
|
|
|
|
Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getNameAsString(),
|
|
|
|
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-24 11:54:41 +08:00
|
|
|
std::string EnumName = Decl->getNameAsString();
|
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
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
|
|
|
|
Unit, EnumName, DefUnit, Line,
|
|
|
|
Size, Align, 0, 0,
|
|
|
|
llvm::DIType(), EltArray);
|
|
|
|
}
|
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
|
|
|
|
|
|
|
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type,
|
|
|
|
Unit, "", llvm::DICompileUnit(),
|
|
|
|
0, Size, Align, 0, 0,
|
|
|
|
getOrCreateType(EltTy, Unit),
|
|
|
|
SubscriptArray);
|
2008-06-09 18:47:41 +08:00
|
|
|
}
|
|
|
|
|
2008-06-07 12:46:53 +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,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
if (Ty.isNull())
|
|
|
|
return llvm::DIType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
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);
|
|
|
|
TypeCache.insert(std::make_pair(Ty.getAsOpaquePtr(), Res.getNode()));
|
|
|
|
return Res;
|
2009-09-20 03:27:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// getOrCreateTypeNode - Get the type metadata node from the cache or create a
|
|
|
|
/// new one if necessary.
|
|
|
|
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.
|
|
|
|
if (Ty.hasQualifiers())
|
|
|
|
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-09-20 03:27:14 +08:00
|
|
|
default:
|
2009-03-17 07:22:08 +08:00
|
|
|
case Type::LValueReference:
|
|
|
|
case Type::RValueReference:
|
2008-11-10 14:08:34 +08:00
|
|
|
case Type::Vector:
|
|
|
|
case Type::ExtVector:
|
2009-02-28 07:15:07 +08:00
|
|
|
case Type::FixedWidthInt:
|
|
|
|
case Type::MemberPointer:
|
2009-03-31 06:58:21 +08:00
|
|
|
case Type::TemplateSpecialization:
|
Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
llvm-svn: 67265
2009-03-19 08:18:19 +08:00
|
|
|
case Type::QualifiedName:
|
2009-02-28 07:15:07 +08:00
|
|
|
// Unsupported types
|
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);
|
2009-09-05 08:15:47 +08:00
|
|
|
case Type::Elaborated:
|
2009-09-20 03:27:14 +08:00
|
|
|
return getOrCreateType(cast<ElaboratedType>(Ty)->getUnderlyingType(),
|
|
|
|
Unit);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
case Type::ConstantArray:
|
2009-07-06 23:59:29 +08:00
|
|
|
case Type::ConstantArrayWithExpr:
|
|
|
|
case Type::ConstantArrayWithoutExpr:
|
2008-11-10 14:08:34 +08:00
|
|
|
case Type::VariableArray:
|
|
|
|
case Type::IncompleteArray:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<ArrayType>(Ty), Unit);
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::TypeOfExpr:
|
2009-09-20 03:27:14 +08:00
|
|
|
return getOrCreateType(cast<TypeOfExprType>(Ty)->getUnderlyingExpr()
|
|
|
|
->getType(), Unit);
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::TypeOf:
|
2009-09-20 03:27:14 +08:00
|
|
|
return getOrCreateType(cast<TypeOfType>(Ty)->getUnderlyingType(), Unit);
|
2009-06-25 03:06:50 +08:00
|
|
|
case Type::Decltype:
|
2009-09-20 03:27:14 +08:00
|
|
|
return getOrCreateType(cast<DecltypeType>(Ty)->getUnderlyingType(), Unit);
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitFunctionStart - Constructs the debug code for entering a function -
|
|
|
|
/// "llvm.dbg.func.start.".
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType,
|
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,
|
2008-11-10 14:08:34 +08:00
|
|
|
getOrCreateType(ReturnType, Unit),
|
|
|
|
Fn->hasInternalLinkage(), true/*definition*/);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-07 02:36:08 +08:00
|
|
|
// DebugFactory.InsertSubprogramStart(SP, Builder.GetInsertBlock());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
// Push function on region stack.
|
2008-11-10 14:08:34 +08:00
|
|
|
RegionStack.push_back(SP);
|
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
|
|
|
|
|
|
|
#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
|
|
|
|
llvm::DIDescriptor DR = RegionStack.back();
|
|
|
|
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());
|
|
|
|
#else
|
2009-04-09 03:47:04 +08:00
|
|
|
DebugFactory.InsertStopPoint(Unit, PLoc.getLine(), PLoc.getColumn(),
|
2009-09-09 23:08:12 +08:00
|
|
|
Builder.GetInsertBlock());
|
2009-10-07 02:36:08 +08:00
|
|
|
#endif
|
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) {
|
|
|
|
llvm::DIDescriptor D;
|
2008-10-17 09:07:56 +08:00
|
|
|
if (!RegionStack.empty())
|
2008-11-10 14:08:34 +08:00
|
|
|
D = RegionStack.back();
|
2009-09-01 06:00:32 +08:00
|
|
|
D = DebugFactory.CreateLexicalBlock(D);
|
2008-11-10 14:08:34 +08:00
|
|
|
RegionStack.push_back(D);
|
2009-10-07 02:36:08 +08:00
|
|
|
#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN
|
2008-11-10 14:08:34 +08:00
|
|
|
DebugFactory.InsertRegionStart(D, Builder.GetInsertBlock());
|
2009-10-07 02:36:08 +08:00
|
|
|
#endif
|
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
|
|
|
|
2009-10-07 02:36:08 +08:00
|
|
|
#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN
|
2008-11-10 14:08:34 +08:00
|
|
|
DebugFactory.InsertRegionEnd(RegionStack.back(), Builder.GetInsertBlock());
|
2009-10-07 02:36:08 +08:00
|
|
|
#endif
|
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.
|
|
|
|
const CompileOptions &CO = M->getCompileOpts();
|
|
|
|
if (CO.OptimizationLevel)
|
|
|
|
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
|
|
|
std::string Name = Decl->getNameAsString();
|
|
|
|
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
Name, DefUnit,
|
|
|
|
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;
|
|
|
|
if (!PLoc.isInvalid())
|
|
|
|
Line = PLoc.getLine();
|
|
|
|
else
|
|
|
|
Unit = llvm::DICompileUnit();
|
|
|
|
|
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 =
|
2008-11-24 13:29:24 +08:00
|
|
|
DebugFactory.CreateVariable(Tag, RegionStack.back(),Decl->getNameAsString(),
|
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.
|
|
|
|
DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock());
|
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.
|
|
|
|
const CompileOptions &CO = M->getCompileOpts();
|
2009-10-02 06:29:41 +08:00
|
|
|
if (CO.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;
|
|
|
|
std::string Name = Decl->getNameAsString();
|
|
|
|
|
|
|
|
XOffset = FieldOffset;
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
Name, DefUnit,
|
|
|
|
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 =
|
|
|
|
DebugFactory.CreateComplexVariable(Tag, RegionStack.back(),
|
|
|
|
Decl->getNameAsString(), Unit, Line, Ty,
|
|
|
|
addr);
|
|
|
|
// Insert an llvm.dbg.declare into the current block.
|
2009-10-02 06:29:41 +08:00
|
|
|
DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertPoint());
|
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
|
|
|
|
|
|
|
// 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.
|
|
|
|
const CompileOptions &CO = M->getCompileOpts();
|
|
|
|
if (CO.OptimizationLevel)
|
|
|
|
return;
|
|
|
|
|
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
|
|
|
|
|
|
|
std::string Name = Decl->getNameAsString();
|
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-10-06 08:35:31 +08:00
|
|
|
DebugFactory.CreateGlobalVariable(getContext(Decl, Unit),
|
|
|
|
Name, Name, "", 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
|
|
|
|
|
|
|
std::string Name = Decl->getNameAsString();
|
|
|
|
|
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-07-15 05:31:22 +08:00
|
|
|
DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo,
|
2009-02-27 05:10:26 +08:00
|
|
|
getOrCreateType(T, Unit),
|
|
|
|
Var->hasInternalLinkage(),
|
|
|
|
true/*definition*/, Var);
|
|
|
|
}
|