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-12-07 02:00:51 +08:00
|
|
|
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
|
2010-03-09 08:44:50 +08:00
|
|
|
: CGM(CGM), DebugFactory(CGM.getModule()),
|
2009-05-14 10:03:51 +08:00
|
|
|
BlockLiteralGenericSet(false) {
|
2010-03-09 08:44:50 +08:00
|
|
|
CreateCompileUnit();
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
CGDebugInfo::~CGDebugInfo() {
|
2008-10-18 00:15:48 +08:00
|
|
|
assert(RegionStack.empty() && "Region stack mismatch, stack not empty!");
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::setLocation(SourceLocation Loc) {
|
|
|
|
if (Loc.isValid())
|
2009-12-07 02:00:51 +08:00
|
|
|
CurLoc = CGM.getContext().getSourceManager().getInstantiationLoc(Loc);
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2010-01-29 07:15:27 +08:00
|
|
|
/// getContextDescriptor - Get context info for the decl.
|
2010-02-02 05:34:11 +08:00
|
|
|
llvm::DIDescriptor CGDebugInfo::getContextDescriptor(const Decl *Context,
|
2010-01-29 07:15:27 +08:00
|
|
|
llvm::DIDescriptor &CompileUnit) {
|
2010-02-02 05:34:11 +08:00
|
|
|
if (!Context)
|
|
|
|
return CompileUnit;
|
|
|
|
|
|
|
|
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
|
|
|
|
I = RegionMap.find(Context);
|
|
|
|
if (I != RegionMap.end())
|
|
|
|
return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(I->second));
|
2010-02-02 06:40:08 +08:00
|
|
|
|
2010-02-02 05:34:11 +08:00
|
|
|
// Check namespace.
|
|
|
|
if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context))
|
|
|
|
return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl, CompileUnit));
|
|
|
|
|
2009-10-06 08:35:31 +08:00
|
|
|
return CompileUnit;
|
|
|
|
}
|
|
|
|
|
2010-01-14 08:36:21 +08:00
|
|
|
/// getFunctionName - Get function name for the given FunctionDecl. If the
|
|
|
|
/// name is constructred on demand (e.g. C++ destructor) then the name
|
|
|
|
/// is stored on the side.
|
|
|
|
llvm::StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
|
|
|
|
assert (FD && "Invalid FunctionDecl!");
|
|
|
|
IdentifierInfo *FII = FD->getIdentifier();
|
|
|
|
if (FII)
|
|
|
|
return FII->getName();
|
|
|
|
|
|
|
|
// Otherwise construct human readable name for debug info.
|
|
|
|
std::string NS = FD->getNameAsString();
|
|
|
|
|
|
|
|
// Copy this name on the side and use its reference.
|
2010-01-29 02:21:00 +08:00
|
|
|
char *StrPtr = DebugInfoNames.Allocate<char>(NS.length());
|
2010-01-24 02:16:07 +08:00
|
|
|
memcpy(StrPtr, NS.data(), NS.length());
|
|
|
|
return llvm::StringRef(StrPtr, NS.length());
|
2010-01-14 08:36:21 +08:00
|
|
|
}
|
|
|
|
|
2010-03-09 08:44:50 +08:00
|
|
|
/// getOrCreateFile - Get the file debug info descriptor for the input location.
|
|
|
|
llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
|
|
|
|
if (!Loc.isValid())
|
|
|
|
// If Location is not valid then use main input file.
|
|
|
|
return DebugFactory.CreateFile(TheCU.getFilename(), TheCU.getDirectory(),
|
|
|
|
TheCU);
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2010-03-09 08:44:50 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
|
|
|
|
llvm::sys::Path AbsFileName(PLoc.getFilename());
|
|
|
|
AbsFileName.makeAbsolute();
|
|
|
|
|
2010-03-10 03:14:07 +08:00
|
|
|
return DebugFactory.CreateFile(AbsFileName.getLast(),
|
2010-03-09 08:44:50 +08:00
|
|
|
AbsFileName.getDirname(), TheCU);
|
|
|
|
}
|
|
|
|
/// CreateCompileUnit - Create new compile unit.
|
|
|
|
void CGDebugInfo::CreateCompileUnit() {
|
2009-04-08 13:11:16 +08:00
|
|
|
|
2009-04-18 05:06:59 +08:00
|
|
|
// Get absolute path name.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::sys::Path AbsFileName(CGM.getCodeGenOpts().MainFileName);
|
2009-12-08 19:02:29 +08:00
|
|
|
AbsFileName.makeAbsolute();
|
2009-04-18 05:06:59 +08:00
|
|
|
|
2009-03-25 11:28:08 +08:00
|
|
|
unsigned LangTag;
|
2010-03-09 08:44:50 +08:00
|
|
|
const LangOptions &LO = CGM.getLangOptions();
|
2009-03-25 11:28:08 +08:00
|
|
|
if (LO.CPlusPlus) {
|
|
|
|
if (LO.ObjC1)
|
|
|
|
LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
|
|
|
|
else
|
|
|
|
LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
|
|
|
|
} else if (LO.ObjC1) {
|
2009-03-25 04:35:51 +08:00
|
|
|
LangTag = llvm::dwarf::DW_LANG_ObjC;
|
2009-03-25 11:28:08 +08:00
|
|
|
} else if (LO.C99) {
|
2009-03-25 04:35:51 +08:00
|
|
|
LangTag = llvm::dwarf::DW_LANG_C99;
|
2009-03-25 11:28:08 +08:00
|
|
|
} else {
|
|
|
|
LangTag = llvm::dwarf::DW_LANG_C89;
|
|
|
|
}
|
2009-04-18 05:06:59 +08:00
|
|
|
|
2009-12-08 19:02:29 +08:00
|
|
|
const char *Producer =
|
2009-10-10 02:38:12 +08:00
|
|
|
#ifdef CLANG_VENDOR
|
|
|
|
CLANG_VENDOR
|
|
|
|
#endif
|
|
|
|
"clang " CLANG_VERSION_STRING;
|
2009-05-02 09:00:04 +08:00
|
|
|
|
|
|
|
// Figure out which version of the ObjC runtime we have.
|
|
|
|
unsigned RuntimeVers = 0;
|
|
|
|
if (LO.ObjC1)
|
|
|
|
RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Create new compile unit.
|
2010-03-09 08:44:50 +08:00
|
|
|
TheCU = DebugFactory.CreateCompileUnit(
|
|
|
|
LangTag, AbsFileName.getLast(), AbsFileName.getDirname(), Producer, true,
|
2009-12-18 10:43:17 +08:00
|
|
|
LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers);
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2009-02-25 09:36:11 +08:00
|
|
|
/// CreateType - Get the Basic type from the cache or create a new
|
2008-05-25 13:15:42 +08:00
|
|
|
/// one if necessary.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2008-05-25 13:15:42 +08:00
|
|
|
unsigned Encoding = 0;
|
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.
|
2009-12-07 02:00:51 +08:00
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(BT);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(BT);
|
2008-05-25 13:15:42 +08:00
|
|
|
uint64_t Offset = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
|
|
|
DebugFactory.CreateBasicType(Unit,
|
2009-12-07 02:00:51 +08:00
|
|
|
BT->getName(CGM.getContext().getLangOptions()),
|
2009-10-21 03:55:01 +08:00
|
|
|
Unit, 0, Size, Align,
|
|
|
|
Offset, /*flags*/ 0, Encoding);
|
|
|
|
return DbgTy;
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2009-04-23 14:13:01 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-04-23 14:13:01 +08:00
|
|
|
// Bit size, align and offset of the type.
|
|
|
|
unsigned Encoding = llvm::dwarf::DW_ATE_complex_float;
|
|
|
|
if (Ty->isComplexIntegerType())
|
|
|
|
Encoding = llvm::dwarf::DW_ATE_lo_user;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
2009-04-23 14:13:01 +08:00
|
|
|
uint64_t Offset = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
|
|
|
DebugFactory.CreateBasicType(Unit, "complex",
|
|
|
|
Unit, 0, Size, Align,
|
|
|
|
Offset, /*flags*/ 0, Encoding);
|
|
|
|
return DbgTy;
|
2009-04-23 14:13:01 +08:00
|
|
|
}
|
|
|
|
|
2009-09-25 09:40:47 +08:00
|
|
|
/// CreateCVRType - Get the qualified type from the cache or create
|
2008-11-10 14:08:34 +08:00
|
|
|
/// a new one if necessary.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
|
2009-09-25 09:40:47 +08:00
|
|
|
QualifierCollector Qc;
|
|
|
|
const Type *T = Qc.strip(Ty);
|
|
|
|
|
|
|
|
// Ignore these qualifiers for now.
|
|
|
|
Qc.removeObjCGCAttr();
|
|
|
|
Qc.removeAddressSpace();
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// We will create one Derived type for one qualifier and recurse to handle any
|
|
|
|
// additional ones.
|
|
|
|
unsigned Tag;
|
2009-09-25 09:40:47 +08:00
|
|
|
if (Qc.hasConst()) {
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_const_type;
|
2009-09-25 09:40:47 +08:00
|
|
|
Qc.removeConst();
|
|
|
|
} else if (Qc.hasVolatile()) {
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_volatile_type;
|
2009-09-25 09:40:47 +08:00
|
|
|
Qc.removeVolatile();
|
|
|
|
} else if (Qc.hasRestrict()) {
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_restrict_type;
|
2009-09-25 09:40:47 +08:00
|
|
|
Qc.removeRestrict();
|
|
|
|
} else {
|
|
|
|
assert(Qc.empty() && "Unknown type qualifier for debug info");
|
|
|
|
return getOrCreateType(QualType(T, 0), Unit);
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-25 09:40:47 +08:00
|
|
|
llvm::DIType FromTy = getOrCreateType(Qc.apply(T), Unit);
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// No need to fill in the Name, Line, Size, Alignment, Offset in case of
|
|
|
|
// CVR derived types.
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
2010-03-09 08:44:50 +08:00
|
|
|
DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DIFile(),
|
2009-10-21 03:55:01 +08:00
|
|
|
0, 0, 0, 0, 0, FromTy);
|
|
|
|
return DbgTy;
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2009-07-14 09:20:56 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
2009-11-07 03:19:55 +08:00
|
|
|
CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
|
|
|
|
Ty->getPointeeType(), Unit);
|
2009-10-21 03:55:01 +08:00
|
|
|
return DbgTy;
|
2009-07-14 09:20:56 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-11-07 03:19:55 +08:00
|
|
|
return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
|
|
|
|
Ty->getPointeeType(), Unit);
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
|
|
|
|
const Type *Ty,
|
|
|
|
QualType PointeeTy,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-11-07 03:19:55 +08:00
|
|
|
llvm::DIType EltTy = getOrCreateType(PointeeTy, Unit);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
// Bit size, align and offset of the type.
|
2009-11-07 03:19:55 +08:00
|
|
|
|
|
|
|
// Size is always the size of a pointer. We can't use getTypeSize here
|
|
|
|
// because that does not return the correct value for references.
|
|
|
|
uint64_t Size =
|
2009-12-07 02:00:51 +08:00
|
|
|
CGM.getContext().Target.getPointerWidth(PointeeTy.getAddressSpace());
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
return
|
2010-03-09 08:44:50 +08:00
|
|
|
DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DIFile(),
|
2009-10-21 03:55:01 +08:00
|
|
|
0, Size, Align, 0, 0, EltTy);
|
2009-11-07 03:19:55 +08:00
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2009-05-14 10:03:51 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-05-14 10:03:51 +08:00
|
|
|
if (BlockLiteralGenericSet)
|
|
|
|
return BlockLiteralGeneric;
|
|
|
|
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile DefUnit;
|
2009-05-14 10:03:51 +08:00
|
|
|
unsigned Tag = llvm::dwarf::DW_TAG_structure_type;
|
|
|
|
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 5> EltTys;
|
|
|
|
|
|
|
|
llvm::DIType FieldTy;
|
|
|
|
|
|
|
|
QualType FType;
|
|
|
|
uint64_t FieldSize, FieldOffset;
|
|
|
|
unsigned FieldAlign;
|
|
|
|
|
|
|
|
llvm::DIArray Elements;
|
|
|
|
llvm::DIType EltTy, DescTy;
|
|
|
|
|
|
|
|
FieldOffset = 0;
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().UnsignedLongTy;
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"reserved", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().UnsignedLongTy;
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2009-05-14 10:03:51 +08:00
|
|
|
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.
|
2009-12-07 02:00:51 +08:00
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-14 10:03:51 +08:00
|
|
|
DescTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type,
|
2010-03-09 08:44:50 +08:00
|
|
|
Unit, "", llvm::DIFile(),
|
2009-05-14 10:03:51 +08:00
|
|
|
0, Size, Align, 0, 0, EltTy);
|
|
|
|
|
|
|
|
FieldOffset = 0;
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__isa", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().IntTy;
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__flags", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().IntTy;
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__reserved", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__FuncPtr", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = DescTy;
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(Ty);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(Ty);
|
2009-05-14 10:03:51 +08:00
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__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,
|
2010-03-09 08:44:50 +08:00
|
|
|
"", llvm::DIFile(),
|
2009-05-14 10:03:51 +08:00
|
|
|
0, Size, Align, 0, 0, EltTy);
|
|
|
|
return BlockLiteralGeneric;
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2008-11-10 14:08:34 +08:00
|
|
|
// Typedefs are derived from some other type. If we have a typedef of a
|
|
|
|
// typedef, make sure to emit the whole chain.
|
|
|
|
llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// We don't set size information, but do specify where the typedef was
|
|
|
|
// declared.
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2010-01-30 06:29:31 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Ty->getDecl()->getLocation());
|
2009-04-18 05:35:15 +08:00
|
|
|
unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2010-02-02 05:34:11 +08:00
|
|
|
llvm::DIDescriptor TyContext
|
|
|
|
= getContextDescriptor(dyn_cast<Decl>(Ty->getDecl()->getDeclContext()),
|
|
|
|
Unit);
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
2010-01-30 06:29:31 +08:00
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef,
|
2010-02-02 05:34:11 +08:00
|
|
|
TyContext,
|
2010-01-30 06:29:31 +08:00
|
|
|
Ty->getDecl()->getName(), Unit,
|
|
|
|
Line, 0, 0, 0, 0, Src);
|
2009-10-21 03:55:01 +08:00
|
|
|
return DbgTy;
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Add the result type at least.
|
|
|
|
EltTys.push_back(getOrCreateType(Ty->getResultType(), Unit));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Set up remainder of arguments if there is a prototype.
|
|
|
|
// FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'!
|
2009-02-27 07:50:07 +08:00
|
|
|
if (const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(Ty)) {
|
2008-11-10 14:08:34 +08:00
|
|
|
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
|
|
|
|
EltTys.push_back(getOrCreateType(FTP->getArgType(i), Unit));
|
|
|
|
} else {
|
|
|
|
// FIXME: Handle () case in C. llvm-gcc doesn't do it either.
|
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIArray EltTypeArray =
|
2009-05-27 03:40:20 +08:00
|
|
|
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
|
|
|
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
|
2010-03-09 08:44:50 +08:00
|
|
|
Unit, "", llvm::DIFile(),
|
2009-10-21 03:55:01 +08:00
|
|
|
0, 0, 0, 0, 0,
|
|
|
|
llvm::DIType(), EltTypeArray);
|
|
|
|
return DbgTy;
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2010-01-19 08:00:59 +08:00
|
|
|
/// CollectRecordFields - A helper function to collect debug info for
|
|
|
|
/// record fields. This is used while creating debug info entry for a Record.
|
|
|
|
void CGDebugInfo::
|
2010-03-09 08:44:50 +08:00
|
|
|
CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit,
|
2010-01-19 08:00:59 +08:00
|
|
|
llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys) {
|
|
|
|
unsigned FieldNo = 0;
|
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2010-02-02 05:39:52 +08:00
|
|
|
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
|
|
|
|
for (RecordDecl::field_iterator I = RD->field_begin(),
|
|
|
|
E = RD->field_end();
|
2010-01-19 08:00:59 +08:00
|
|
|
I != E; ++I, ++FieldNo) {
|
|
|
|
FieldDecl *Field = *I;
|
|
|
|
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
|
|
|
|
|
|
|
|
llvm::StringRef FieldName = Field->getName();
|
|
|
|
|
2010-02-12 09:31:06 +08:00
|
|
|
// Ignore unnamed fields. Do not ignore unnamed records.
|
|
|
|
if (FieldName.empty() && !isa<RecordType>(Field->getType()))
|
2010-01-19 08:00:59 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Get the location for the field.
|
|
|
|
SourceLocation FieldDefLoc = Field->getLocation();
|
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(FieldDefLoc);
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile FieldDefUnit;
|
2010-01-19 08:00:59 +08:00
|
|
|
unsigned FieldLine = 0;
|
|
|
|
|
|
|
|
if (!PLoc.isInvalid()) {
|
2010-03-09 08:44:50 +08:00
|
|
|
FieldDefUnit = getOrCreateFile(FieldDefLoc);
|
2010-01-19 08:00:59 +08:00
|
|
|
FieldLine = PLoc.getLine();
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType FType = Field->getType();
|
|
|
|
uint64_t FieldSize = 0;
|
|
|
|
unsigned FieldAlign = 0;
|
|
|
|
if (!FType->isIncompleteArrayType()) {
|
|
|
|
|
|
|
|
// Bit size, align and offset of the type.
|
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
Expr *BitWidth = Field->getBitWidth();
|
|
|
|
if (BitWidth)
|
|
|
|
FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
|
|
|
|
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t FieldOffset = RL.getFieldOffset(FieldNo);
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-28 08:28:01 +08:00
|
|
|
/// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This
|
|
|
|
/// function type is not updated to include implicit "this" pointer. Use this
|
|
|
|
/// routine to get a method type which includes "this" pointer.
|
|
|
|
llvm::DIType
|
|
|
|
CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2010-01-28 08:28:01 +08:00
|
|
|
llvm::DIType FnTy = getOrCreateType(Method->getType(), Unit);
|
2010-01-29 05:43:50 +08:00
|
|
|
|
|
|
|
// Static methods do not need "this" pointer argument.
|
|
|
|
if (Method->isStatic())
|
|
|
|
return FnTy;
|
|
|
|
|
2010-01-28 08:28:01 +08:00
|
|
|
// Add "this" pointer.
|
|
|
|
|
|
|
|
llvm::DIArray Args = llvm::DICompositeType(FnTy.getNode()).getTypeArray();
|
|
|
|
assert (Args.getNumElements() && "Invalid number of arguments!");
|
|
|
|
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 16> Elts;
|
|
|
|
|
|
|
|
// First element is always return type. For 'void' functions it is NULL.
|
|
|
|
Elts.push_back(Args.getElement(0));
|
|
|
|
|
|
|
|
// "this" pointer is always first argument.
|
|
|
|
ASTContext &Context = CGM.getContext();
|
|
|
|
QualType ThisPtr =
|
|
|
|
Context.getPointerType(Context.getTagDeclType(Method->getParent()));
|
2010-02-10 01:57:50 +08:00
|
|
|
llvm::DIType ThisPtrType =
|
|
|
|
DebugFactory.CreateArtificialType(getOrCreateType(ThisPtr, Unit));
|
|
|
|
TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType.getNode();
|
|
|
|
Elts.push_back(ThisPtrType);
|
2010-01-28 08:28:01 +08:00
|
|
|
|
|
|
|
// Copy rest of the arguments.
|
|
|
|
for (unsigned i = 1, e = Args.getNumElements(); i != e; ++i)
|
|
|
|
Elts.push_back(Args.getElement(i));
|
|
|
|
|
|
|
|
llvm::DIArray EltTypeArray =
|
|
|
|
DebugFactory.GetOrCreateArray(Elts.data(), Elts.size());
|
|
|
|
|
|
|
|
return
|
|
|
|
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
|
2010-03-09 08:44:50 +08:00
|
|
|
Unit, "", llvm::DIFile(),
|
2010-01-28 08:28:01 +08:00
|
|
|
0, 0, 0, 0, 0,
|
|
|
|
llvm::DIType(), EltTypeArray);
|
|
|
|
}
|
|
|
|
|
2010-01-26 12:49:33 +08:00
|
|
|
/// CreateCXXMemberFunction - A helper function to create a DISubprogram for
|
|
|
|
/// a single member function GlobalDecl.
|
|
|
|
llvm::DISubprogram
|
2010-01-26 13:19:50 +08:00
|
|
|
CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit,
|
2010-01-26 12:49:33 +08:00
|
|
|
llvm::DICompositeType &RecordTy) {
|
2010-01-26 13:19:50 +08:00
|
|
|
bool IsCtorOrDtor =
|
|
|
|
isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
|
|
|
|
|
|
|
|
llvm::StringRef MethodName = getFunctionName(Method);
|
2010-01-26 12:49:33 +08:00
|
|
|
llvm::StringRef MethodLinkageName;
|
2010-01-28 08:28:01 +08:00
|
|
|
llvm::DIType MethodTy = getOrCreateMethodType(Method, Unit);
|
2010-01-26 13:19:50 +08:00
|
|
|
|
|
|
|
// Since a single ctor/dtor corresponds to multiple functions, it doesn't
|
|
|
|
// make sense to give a single ctor/dtor a linkage name.
|
|
|
|
if (!IsCtorOrDtor)
|
2010-01-26 12:49:33 +08:00
|
|
|
MethodLinkageName = CGM.getMangledName(Method);
|
2010-01-26 13:19:50 +08:00
|
|
|
|
2010-01-26 12:49:33 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
|
|
|
|
|
|
|
// Get the location for the method.
|
|
|
|
SourceLocation MethodDefLoc = Method->getLocation();
|
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(MethodDefLoc);
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile MethodDefUnit;
|
2010-01-26 12:49:33 +08:00
|
|
|
unsigned MethodLine = 0;
|
|
|
|
|
|
|
|
if (!PLoc.isInvalid()) {
|
2010-03-09 08:44:50 +08:00
|
|
|
MethodDefUnit = getOrCreateFile(MethodDefLoc);
|
2010-01-26 12:49:33 +08:00
|
|
|
MethodLine = PLoc.getLine();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Collect virtual method info.
|
|
|
|
llvm::DIType ContainingType;
|
|
|
|
unsigned Virtuality = 0;
|
|
|
|
unsigned VIndex = 0;
|
2010-01-26 13:19:50 +08:00
|
|
|
|
2010-01-26 12:49:33 +08:00
|
|
|
if (Method->isVirtual()) {
|
2010-01-26 13:19:50 +08:00
|
|
|
if (Method->isPure())
|
|
|
|
Virtuality = llvm::dwarf::DW_VIRTUALITY_pure_virtual;
|
|
|
|
else
|
|
|
|
Virtuality = llvm::dwarf::DW_VIRTUALITY_virtual;
|
|
|
|
|
|
|
|
// It doesn't make sense to give a virtual destructor a vtable index,
|
|
|
|
// since a single destructor has two entries in the vtable.
|
|
|
|
if (!isa<CXXDestructorDecl>(Method))
|
|
|
|
VIndex = CGM.getVtableInfo().getMethodVtableIndex(Method);
|
2010-01-26 12:49:33 +08:00
|
|
|
ContainingType = RecordTy;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::DISubprogram SP =
|
|
|
|
DebugFactory.CreateSubprogram(RecordTy , MethodName, MethodName,
|
|
|
|
MethodLinkageName,
|
|
|
|
MethodDefUnit, MethodLine,
|
|
|
|
MethodTy, /*isLocalToUnit=*/false,
|
|
|
|
Method->isThisDeclarationADefinition(),
|
|
|
|
Virtuality, VIndex, ContainingType);
|
2010-01-26 13:19:50 +08:00
|
|
|
|
|
|
|
// Don't cache ctors or dtors since we have to emit multiple functions for
|
|
|
|
// a single ctor or dtor.
|
|
|
|
if (!IsCtorOrDtor && Method->isThisDeclarationADefinition())
|
|
|
|
SPCache[Method] = llvm::WeakVH(SP.getNode());
|
2010-01-26 12:49:33 +08:00
|
|
|
|
|
|
|
return SP;
|
|
|
|
}
|
|
|
|
|
2010-01-19 09:54:44 +08:00
|
|
|
/// CollectCXXMemberFunctions - A helper function to collect debug info for
|
|
|
|
/// C++ member functions.This is used while creating debug info entry for
|
|
|
|
/// a Record.
|
|
|
|
void CGDebugInfo::
|
2010-03-09 08:44:50 +08:00
|
|
|
CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
|
2010-01-19 09:54:44 +08:00
|
|
|
llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys,
|
|
|
|
llvm::DICompositeType &RecordTy) {
|
2010-02-02 05:39:52 +08:00
|
|
|
for(CXXRecordDecl::method_iterator I = RD->method_begin(),
|
|
|
|
E = RD->method_end(); I != E; ++I) {
|
2010-01-26 12:49:33 +08:00
|
|
|
const CXXMethodDecl *Method = *I;
|
2010-01-26 12:40:11 +08:00
|
|
|
|
2010-02-10 03:09:28 +08:00
|
|
|
if (Method->isImplicit() && !Method->isUsed())
|
2010-01-26 12:40:11 +08:00
|
|
|
continue;
|
2010-01-26 07:17:15 +08:00
|
|
|
|
2010-01-26 12:49:33 +08:00
|
|
|
EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));
|
2010-01-19 09:54:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-26 07:32:18 +08:00
|
|
|
/// CollectCXXBases - A helper function to collect debug info for
|
|
|
|
/// C++ base classes. This is used while creating debug info entry for
|
|
|
|
/// a Record.
|
|
|
|
void CGDebugInfo::
|
2010-03-09 08:44:50 +08:00
|
|
|
CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
|
2010-01-26 07:32:18 +08:00
|
|
|
llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys,
|
|
|
|
llvm::DICompositeType &RecordTy) {
|
|
|
|
|
2010-02-02 05:39:52 +08:00
|
|
|
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
|
|
|
|
for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(),
|
|
|
|
BE = RD->bases_end(); BI != BE; ++BI) {
|
2010-01-29 05:54:15 +08:00
|
|
|
unsigned BFlags = 0;
|
|
|
|
uint64_t BaseOffset;
|
|
|
|
|
|
|
|
const CXXRecordDecl *Base =
|
|
|
|
cast<CXXRecordDecl>(BI->getType()->getAs<RecordType>()->getDecl());
|
|
|
|
|
|
|
|
if (BI->isVirtual()) {
|
2010-02-10 03:09:28 +08:00
|
|
|
// virtual base offset index is -ve. The code generator emits dwarf
|
|
|
|
// expression where it expects +ve number.
|
|
|
|
BaseOffset = 0 - CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base);
|
2010-01-29 05:54:15 +08:00
|
|
|
BFlags = llvm::DIType::FlagVirtual;
|
|
|
|
} else
|
|
|
|
BaseOffset = RL.getBaseClassOffset(Base);
|
|
|
|
|
|
|
|
AccessSpecifier Access = BI->getAccessSpecifier();
|
|
|
|
if (Access == clang::AS_private)
|
|
|
|
BFlags |= llvm::DIType::FlagPrivate;
|
|
|
|
else if (Access == clang::AS_protected)
|
|
|
|
BFlags |= llvm::DIType::FlagProtected;
|
|
|
|
|
|
|
|
llvm::DIType DTy =
|
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_inheritance,
|
|
|
|
RecordTy, llvm::StringRef(),
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile(), 0, 0, 0,
|
2010-01-29 05:54:15 +08:00
|
|
|
BaseOffset, BFlags,
|
|
|
|
getOrCreateType(BI->getType(),
|
|
|
|
Unit));
|
|
|
|
EltTys.push_back(DTy);
|
|
|
|
}
|
2010-01-26 07:32:18 +08:00
|
|
|
}
|
|
|
|
|
2010-01-29 02:11:52 +08:00
|
|
|
/// getOrCreateVTablePtrType - Return debug info descriptor for vtable.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) {
|
2010-03-09 04:53:17 +08:00
|
|
|
if (VTablePtrType.isValid())
|
2010-01-29 02:11:52 +08:00
|
|
|
return VTablePtrType;
|
|
|
|
|
|
|
|
ASTContext &Context = CGM.getContext();
|
|
|
|
|
|
|
|
/* Function type */
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 16> STys;
|
|
|
|
STys.push_back(getOrCreateType(Context.IntTy, Unit));
|
|
|
|
llvm::DIArray SElements =
|
|
|
|
DebugFactory.GetOrCreateArray(STys.data(), STys.size());
|
|
|
|
llvm::DIType SubTy =
|
|
|
|
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
|
2010-03-09 08:44:50 +08:00
|
|
|
Unit, "", llvm::DIFile(),
|
2010-01-29 02:11:52 +08:00
|
|
|
0, 0, 0, 0, 0, llvm::DIType(), SElements);
|
|
|
|
|
|
|
|
unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
|
|
|
|
llvm::DIType vtbl_ptr_type
|
|
|
|
= DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type,
|
2010-03-09 08:44:50 +08:00
|
|
|
Unit, "__vtbl_ptr_type", llvm::DIFile(),
|
2010-01-29 02:11:52 +08:00
|
|
|
0, Size, 0, 0, 0, SubTy);
|
|
|
|
|
|
|
|
VTablePtrType = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type,
|
2010-03-09 08:44:50 +08:00
|
|
|
Unit, "", llvm::DIFile(),
|
2010-01-29 02:11:52 +08:00
|
|
|
0, Size, 0, 0, 0, vtbl_ptr_type);
|
|
|
|
return VTablePtrType;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getVtableName - Get vtable name for the given Class.
|
2010-02-02 05:39:52 +08:00
|
|
|
llvm::StringRef CGDebugInfo::getVtableName(const CXXRecordDecl *RD) {
|
2010-01-29 02:11:52 +08:00
|
|
|
// Otherwise construct gdb compatible name name.
|
2010-02-02 05:39:52 +08:00
|
|
|
std::string Name = "_vptr$" + RD->getNameAsString();
|
2010-01-29 02:11:52 +08:00
|
|
|
|
|
|
|
// Copy this name on the side and use its reference.
|
2010-01-29 02:21:00 +08:00
|
|
|
char *StrPtr = DebugInfoNames.Allocate<char>(Name.length());
|
2010-01-29 02:11:52 +08:00
|
|
|
memcpy(StrPtr, Name.data(), Name.length());
|
|
|
|
return llvm::StringRef(StrPtr, Name.length());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// CollectVtableInfo - If the C++ class has vtable info then insert appropriate
|
|
|
|
/// debug info entry in EltTys vector.
|
|
|
|
void CGDebugInfo::
|
2010-03-09 08:44:50 +08:00
|
|
|
CollectVtableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
|
2010-01-29 02:11:52 +08:00
|
|
|
llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys) {
|
2010-02-02 05:39:52 +08:00
|
|
|
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
|
2010-01-29 02:11:52 +08:00
|
|
|
|
|
|
|
// If there is a primary base then it will hold vtable info.
|
|
|
|
if (RL.getPrimaryBase())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If this class is not dynamic then there is not any vtable info to collect.
|
2010-02-02 05:39:52 +08:00
|
|
|
if (!RD->isDynamicClass())
|
2010-01-29 02:11:52 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
|
|
|
|
llvm::DIType VPTR
|
|
|
|
= DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
2010-03-09 08:44:50 +08:00
|
|
|
getVtableName(RD), llvm::DIFile(),
|
2010-01-29 02:11:52 +08:00
|
|
|
0, Size, 0, 0, 0,
|
|
|
|
getOrCreateVTablePtrType(Unit));
|
|
|
|
EltTys.push_back(VPTR);
|
|
|
|
}
|
|
|
|
|
2009-02-25 09:36:11 +08:00
|
|
|
/// CreateType - get structure or union type.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2010-02-02 05:52:22 +08:00
|
|
|
RecordDecl *RD = Ty->getDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
unsigned Tag;
|
2010-02-02 05:52:22 +08:00
|
|
|
if (RD->isStruct())
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_structure_type;
|
2010-02-02 05:52:22 +08:00
|
|
|
else if (RD->isUnion())
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_union_type;
|
|
|
|
else {
|
2010-02-02 05:52:22 +08:00
|
|
|
assert(RD->isClass() && "Unknown RecordType!");
|
2008-11-10 14:08:34 +08:00
|
|
|
Tag = llvm::dwarf::DW_TAG_class_type;
|
2008-06-07 12:46:53 +08:00
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2008-06-07 12:46:53 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Get overall information about the record type for the debug info.
|
2010-02-02 05:52:22 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(RD->getLocation());
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile DefUnit;
|
2009-05-05 13:16:17 +08:00
|
|
|
unsigned Line = 0;
|
|
|
|
if (!PLoc.isInvalid()) {
|
2010-03-09 08:44:50 +08:00
|
|
|
DefUnit = getOrCreateFile(RD->getLocation());
|
2009-05-05 13:16:17 +08:00
|
|
|
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.
|
2010-01-21 07:56:40 +08:00
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
// A RD->getName() is not unique. However, the debug info descriptors
|
2010-02-02 06:51:29 +08:00
|
|
|
// are uniqued so use type name to ensure uniquness.
|
2010-01-21 07:56:40 +08:00
|
|
|
std::string STy = QualType(Ty, 0).getAsString();
|
2010-02-02 06:40:08 +08:00
|
|
|
llvm::DIDescriptor FDContext =
|
|
|
|
getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()), Unit);
|
2009-07-23 02:57:00 +08:00
|
|
|
llvm::DICompositeType FwdDecl =
|
2010-02-02 06:40:08 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, FDContext,
|
|
|
|
STy.c_str(),
|
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.
|
2010-02-11 09:04:33 +08:00
|
|
|
if (!RD->getDefinition())
|
2008-11-10 14:08:34 +08:00
|
|
|
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;
|
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
|
2010-01-29 05:41:35 +08:00
|
|
|
if (CXXDecl) {
|
|
|
|
CollectCXXBases(CXXDecl, Unit, EltTys, FwdDecl);
|
2010-01-29 02:11:52 +08:00
|
|
|
CollectVtableInfo(CXXDecl, Unit, EltTys);
|
2010-01-29 05:41:35 +08:00
|
|
|
}
|
2010-02-02 05:52:22 +08:00
|
|
|
CollectRecordFields(RD, Unit, EltTys);
|
2010-01-28 08:54:21 +08:00
|
|
|
llvm::MDNode *ContainingType = NULL;
|
2010-01-29 02:11:52 +08:00
|
|
|
if (CXXDecl) {
|
2010-01-19 09:54:44 +08:00
|
|
|
CollectCXXMemberFunctions(CXXDecl, Unit, EltTys, FwdDecl);
|
2010-01-28 08:54:21 +08:00
|
|
|
|
|
|
|
// A class's primary base or the class itself contains the vtable.
|
2010-02-02 05:52:22 +08:00
|
|
|
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
|
2010-01-28 08:54:21 +08:00
|
|
|
if (const CXXRecordDecl *PBase = RL.getPrimaryBase())
|
|
|
|
ContainingType =
|
|
|
|
getOrCreateType(QualType(PBase->getTypeForDecl(), 0), Unit).getNode();
|
|
|
|
else if (CXXDecl->isDynamicClass())
|
|
|
|
ContainingType = FwdDecl.getNode();
|
2010-01-26 07:32:18 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIArray Elements =
|
2009-05-27 03:40:20 +08:00
|
|
|
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
2008-06-07 12:46:53 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Bit size, align and offset of the type.
|
2009-12-07 02:00:51 +08:00
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-02 06:40:08 +08:00
|
|
|
llvm::DIDescriptor RDContext =
|
|
|
|
getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()), Unit);
|
2009-07-23 02:57:00 +08:00
|
|
|
llvm::DICompositeType RealDecl =
|
2010-02-02 06:40:08 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, RDContext,
|
|
|
|
RD->getName(),
|
2009-11-12 08:51:46 +08:00
|
|
|
DefUnit, Line, Size, Align, 0, 0,
|
2010-01-28 08:54:21 +08:00
|
|
|
llvm::DIType(), Elements,
|
|
|
|
0, ContainingType);
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
// Now that we have a real decl for the struct, replace anything using the
|
|
|
|
// old decl with the new one. This will recursively update the debug info.
|
2009-11-17 05:04:30 +08:00
|
|
|
llvm::DIDerivedType(FwdDeclNode).replaceAllUsesWith(RealDecl);
|
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,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2010-02-02 05:52:22 +08:00
|
|
|
ObjCInterfaceDecl *ID = 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;
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
// Get overall information about the record type for the debug info.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation());
|
2010-02-02 05:52:22 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(ID->getLocation());
|
2009-04-18 05:35:15 +08:00
|
|
|
unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-03-09 08:44:50 +08:00
|
|
|
unsigned RuntimeLang = TheCU.getLanguage();
|
2009-05-02 09:13:16 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// To handle recursive interface, we
|
|
|
|
// first generate a debug descriptor for the struct as a forward declaration.
|
|
|
|
// Then (if it is a definition) we go through and get debug info for all of
|
|
|
|
// its members. Finally, we create a descriptor for the complete type (which
|
|
|
|
// may refer to the forward decl if the struct is recursive) and replace all
|
|
|
|
// uses of the forward declaration with the final definition.
|
2009-07-28 02:42:03 +08:00
|
|
|
llvm::DICompositeType FwdDecl =
|
2010-02-02 05:52:22 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, ID->getName(),
|
2009-11-12 08:51:46 +08:00
|
|
|
DefUnit, Line, 0, 0, 0, 0,
|
2009-05-02 09:13:16 +08:00
|
|
|
llvm::DIType(), llvm::DIArray(),
|
|
|
|
RuntimeLang);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// If this is just a forward declaration, return it.
|
2010-02-02 05:52:22 +08:00
|
|
|
if (ID->isForwardDecl())
|
2009-02-27 05:10:26 +08:00
|
|
|
return FwdDecl;
|
|
|
|
|
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;
|
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
ObjCInterfaceDecl *SClass = ID->getSuperClass();
|
2009-03-11 05:30:26 +08:00
|
|
|
if (SClass) {
|
2009-09-09 23:08:12 +08:00
|
|
|
llvm::DIType SClassTy =
|
2009-12-07 02:00:51 +08:00
|
|
|
getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit);
|
2009-09-09 23:08:12 +08:00
|
|
|
llvm::DIType InhTag =
|
2009-03-11 05:30:26 +08:00
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_inheritance,
|
2010-03-09 08:44:50 +08:00
|
|
|
Unit, "", llvm::DIFile(), 0, 0, 0,
|
2009-03-11 05:30:26 +08:00
|
|
|
0 /* offset */, 0, SClassTy);
|
|
|
|
EltTys.push_back(InhTag);
|
|
|
|
}
|
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID);
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
unsigned FieldNo = 0;
|
2010-02-02 05:52:22 +08:00
|
|
|
for (ObjCInterfaceDecl::ivar_iterator I = ID->ivar_begin(),
|
|
|
|
E = ID->ivar_end(); I != E; ++I, ++FieldNo) {
|
2009-02-27 05:10:26 +08:00
|
|
|
ObjCIvarDecl *Field = *I;
|
|
|
|
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
|
|
|
|
|
2009-11-26 01:37:31 +08:00
|
|
|
llvm::StringRef FieldName = Field->getName();
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2009-04-28 06:40:36 +08:00
|
|
|
// Ignore unnamed fields.
|
2009-11-26 01:37:31 +08:00
|
|
|
if (FieldName.empty())
|
2009-04-28 06:40:36 +08:00
|
|
|
continue;
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// Get the location for the field.
|
|
|
|
SourceLocation FieldDefLoc = Field->getLocation();
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile FieldDefUnit = getOrCreateFile(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.
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
2009-03-21 02:24:39 +08:00
|
|
|
Expr *BitWidth = Field->getBitWidth();
|
|
|
|
if (BitWidth)
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
|
2009-04-27 03:19:15 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2009-03-21 02:24:39 +08:00
|
|
|
}
|
2009-03-19 08:23:53 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
uint64_t FieldOffset = RL.getFieldOffset(FieldNo);
|
|
|
|
|
2009-03-19 08:23:53 +08:00
|
|
|
unsigned Flags = 0;
|
|
|
|
if (Field->getAccessControl() == ObjCIvarDecl::Protected)
|
|
|
|
Flags = llvm::DIType::FlagProtected;
|
|
|
|
else if (Field->getAccessControl() == ObjCIvarDecl::Private)
|
|
|
|
Flags = llvm::DIType::FlagPrivate;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// Create a DW_TAG_member node to remember the offset of this field in the
|
|
|
|
// struct. FIXME: This is an absolutely insane way to capture this
|
|
|
|
// information. When we gut debug info, this should be fixed.
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
FieldName, FieldDefUnit,
|
|
|
|
FieldLine, FieldSize, FieldAlign,
|
2009-03-19 08:23:53 +08:00
|
|
|
FieldOffset, Flags, FieldTy);
|
2009-02-27 05:10:26 +08:00
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
llvm::DIArray Elements =
|
2009-05-21 17:52:38 +08:00
|
|
|
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
// Bit size, align and offset of the type.
|
2009-12-07 02:00:51 +08:00
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-28 02:42:03 +08:00
|
|
|
llvm::DICompositeType RealDecl =
|
2010-02-02 05:52:22 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, ID->getName(), DefUnit,
|
2009-11-12 08:51:46 +08:00
|
|
|
Line, Size, Align, 0, 0, llvm::DIType(),
|
|
|
|
Elements, RuntimeLang);
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
// Now that we have a real decl for the struct, replace anything using the
|
|
|
|
// old decl with the new one. This will recursively update the debug info.
|
2009-11-17 04:09:38 +08:00
|
|
|
llvm::DIDerivedType(FwdDeclNode).replaceAllUsesWith(RealDecl);
|
2009-07-14 01:03:14 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
return RealDecl;
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2010-02-02 05:52:22 +08:00
|
|
|
EnumDecl *ED = Ty->getDecl();
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 32> Enumerators;
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Create DIEnumerator elements for each enumerator.
|
2009-09-09 23:08:12 +08:00
|
|
|
for (EnumDecl::enumerator_iterator
|
2010-02-02 05:52:22 +08:00
|
|
|
Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end();
|
2008-12-12 00:49:14 +08:00
|
|
|
Enum != EnumEnd; ++Enum) {
|
2009-11-26 01:37:31 +08:00
|
|
|
Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getName(),
|
2008-12-12 00:49:14 +08:00
|
|
|
Enum->getInitVal().getZExtValue()));
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Return a CompositeType for the enum itself.
|
|
|
|
llvm::DIArray EltArray =
|
2009-05-21 17:52:38 +08:00
|
|
|
DebugFactory.GetOrCreateArray(Enumerators.data(), Enumerators.size());
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
SourceLocation DefLoc = ED->getLocation();
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile DefUnit = getOrCreateFile(DefLoc);
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.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()) {
|
2009-12-07 02:00:51 +08:00
|
|
|
Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
Align = CGM.getContext().getTypeAlign(Ty);
|
2009-05-04 12:39:55 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
|
|
|
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
|
2010-02-02 05:52:22 +08:00
|
|
|
Unit, ED->getName(), DefUnit, Line,
|
2009-10-21 03:55:01 +08:00
|
|
|
Size, Align, 0, 0,
|
|
|
|
llvm::DIType(), EltArray);
|
|
|
|
return DbgTy;
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const TagType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2008-11-10 14:08:34 +08:00
|
|
|
if (const RecordType *RT = dyn_cast<RecordType>(Ty))
|
|
|
|
return CreateType(RT, Unit);
|
|
|
|
else if (const EnumType *ET = dyn_cast<EnumType>(Ty))
|
|
|
|
return CreateType(ET, Unit);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
return llvm::DIType();
|
|
|
|
}
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2010-02-24 06:59:39 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2010-02-24 06:59:39 +08:00
|
|
|
llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit);
|
|
|
|
uint64_t NumElems = Ty->getNumElements();
|
|
|
|
if (NumElems > 0)
|
|
|
|
--NumElems;
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 8> Subscripts;
|
|
|
|
Subscripts.push_back(DebugFactory.GetOrCreateSubrange(0, NumElems));
|
|
|
|
|
|
|
|
llvm::DIArray SubscriptArray =
|
|
|
|
DebugFactory.GetOrCreateArray(Subscripts.data(), Subscripts.size());
|
|
|
|
|
|
|
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
|
|
|
|
|
|
|
return
|
|
|
|
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_vector_type,
|
2010-03-09 08:44:50 +08:00
|
|
|
Unit, "", llvm::DIFile(),
|
2010-02-24 06:59:39 +08:00
|
|
|
0, Size, Align, 0, 0,
|
|
|
|
ElementTy, SubscriptArray);
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-01-05 09:23:29 +08:00
|
|
|
uint64_t Size;
|
|
|
|
uint64_t Align;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
2009-01-28 08:35:17 +08:00
|
|
|
// FIXME: make getTypeAlign() aware of VLAs and incomplete array types
|
2009-01-05 09:23:29 +08:00
|
|
|
if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(Ty)) {
|
|
|
|
Size = 0;
|
|
|
|
Align =
|
2009-12-07 02:00:51 +08:00
|
|
|
CGM.getContext().getTypeAlign(CGM.getContext().getBaseElementType(VAT));
|
2009-01-28 08:35:17 +08:00
|
|
|
} else if (Ty->isIncompleteArrayType()) {
|
|
|
|
Size = 0;
|
2009-12-07 02:00:51 +08:00
|
|
|
Align = CGM.getContext().getTypeAlign(Ty->getElementType());
|
2009-01-05 09:23:29 +08:00
|
|
|
} else {
|
|
|
|
// Size and align of the whole array, not the element type.
|
2009-12-07 02:00:51 +08:00
|
|
|
Size = CGM.getContext().getTypeSize(Ty);
|
|
|
|
Align = CGM.getContext().getTypeAlign(Ty);
|
2009-01-05 09:23:29 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Add the dimensions of the array. FIXME: This loses CV qualifiers from
|
|
|
|
// interior arrays, do we care? Why aren't nested arrays represented the
|
|
|
|
// obvious/recursive way?
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 8> Subscripts;
|
|
|
|
QualType EltTy(Ty, 0);
|
|
|
|
while ((Ty = dyn_cast<ArrayType>(EltTy))) {
|
2008-06-09 18:47:41 +08:00
|
|
|
uint64_t Upper = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty))
|
2009-08-15 04:57:45 +08:00
|
|
|
if (CAT->getSize().getZExtValue())
|
2009-09-09 23:08:12 +08:00
|
|
|
Upper = CAT->getSize().getZExtValue() - 1;
|
2008-11-10 14:08:34 +08:00
|
|
|
// FIXME: Verify this is right for VLAs.
|
|
|
|
Subscripts.push_back(DebugFactory.GetOrCreateSubrange(0, Upper));
|
|
|
|
EltTy = Ty->getElementType();
|
2008-06-09 18:47:41 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIArray SubscriptArray =
|
2009-05-27 03:40:20 +08:00
|
|
|
DebugFactory.GetOrCreateArray(Subscripts.data(), Subscripts.size());
|
2008-11-10 14:08:34 +08:00
|
|
|
|
2009-10-21 03:55:01 +08:00
|
|
|
llvm::DIType DbgTy =
|
|
|
|
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type,
|
2010-03-09 08:44:50 +08:00
|
|
|
Unit, "", llvm::DIFile(),
|
2009-10-21 03:55:01 +08:00
|
|
|
0, Size, Align, 0, 0,
|
|
|
|
getOrCreateType(EltTy, Unit),
|
|
|
|
SubscriptArray);
|
|
|
|
return DbgTy;
|
2008-06-09 18:47:41 +08:00
|
|
|
}
|
|
|
|
|
2009-11-07 03:19:55 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-11-07 03:19:55 +08:00
|
|
|
return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type,
|
|
|
|
Ty, Ty->getPointeeType(), Unit);
|
|
|
|
}
|
2008-06-07 12:46:53 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile U) {
|
2009-12-07 02:00:51 +08:00
|
|
|
QualType PointerDiffTy = CGM.getContext().getPointerDiffType();
|
|
|
|
llvm::DIType PointerDiffDITy = getOrCreateType(PointerDiffTy, U);
|
|
|
|
|
|
|
|
if (!Ty->getPointeeType()->isFunctionType()) {
|
|
|
|
// We have a data member pointer type.
|
|
|
|
return PointerDiffDITy;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We have a member function pointer type. Treat it as a struct with two
|
|
|
|
// ptrdiff_t members.
|
|
|
|
std::pair<uint64_t, unsigned> Info = CGM.getContext().getTypeInfo(Ty);
|
|
|
|
|
|
|
|
uint64_t FieldOffset = 0;
|
|
|
|
llvm::DIDescriptor ElementTypes[2];
|
|
|
|
|
|
|
|
// FIXME: This should probably be a function type instead.
|
|
|
|
ElementTypes[0] =
|
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, U,
|
2010-03-09 08:44:50 +08:00
|
|
|
"ptr", llvm::DIFile(), 0,
|
2009-12-07 02:00:51 +08:00
|
|
|
Info.first, Info.second, FieldOffset, 0,
|
|
|
|
PointerDiffDITy);
|
|
|
|
FieldOffset += Info.first;
|
|
|
|
|
|
|
|
ElementTypes[1] =
|
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, U,
|
2010-03-09 08:44:50 +08:00
|
|
|
"ptr", llvm::DIFile(), 0,
|
2009-12-07 02:00:51 +08:00
|
|
|
Info.first, Info.second, FieldOffset, 0,
|
|
|
|
PointerDiffDITy);
|
|
|
|
|
|
|
|
llvm::DIArray Elements =
|
|
|
|
DebugFactory.GetOrCreateArray(&ElementTypes[0],
|
|
|
|
llvm::array_lengthof(ElementTypes));
|
|
|
|
|
|
|
|
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type,
|
|
|
|
U, llvm::StringRef("test"),
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile(), 0, FieldOffset,
|
2009-12-07 02:00:51 +08:00
|
|
|
0, 0, 0, llvm::DIType(), Elements);
|
|
|
|
}
|
|
|
|
|
2009-12-22 04:18:30 +08:00
|
|
|
static QualType UnwrapTypeForDebugInfo(QualType T) {
|
|
|
|
do {
|
|
|
|
QualType LastT = T;
|
|
|
|
switch (T->getTypeClass()) {
|
|
|
|
default:
|
|
|
|
return T;
|
|
|
|
case Type::TemplateSpecialization:
|
|
|
|
T = cast<TemplateSpecializationType>(T)->desugar();
|
|
|
|
break;
|
|
|
|
case Type::TypeOfExpr: {
|
|
|
|
TypeOfExprType *Ty = cast<TypeOfExprType>(T);
|
|
|
|
T = Ty->getUnderlyingExpr()->getType();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Type::TypeOf:
|
|
|
|
T = cast<TypeOfType>(T)->getUnderlyingType();
|
|
|
|
break;
|
|
|
|
case Type::Decltype:
|
|
|
|
T = cast<DecltypeType>(T)->getUnderlyingType();
|
|
|
|
break;
|
|
|
|
case Type::QualifiedName:
|
|
|
|
T = cast<QualifiedNameType>(T)->getNamedType();
|
|
|
|
break;
|
|
|
|
case Type::SubstTemplateTypeParm:
|
|
|
|
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
|
|
|
|
break;
|
|
|
|
case Type::Elaborated:
|
|
|
|
T = cast<ElaboratedType>(T)->getUnderlyingType();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(T != LastT && "Type unwrapping failed to unwrap!");
|
|
|
|
if (T == LastT)
|
|
|
|
return T;
|
|
|
|
} while (true);
|
|
|
|
|
|
|
|
return T;
|
2009-11-15 05:08:12 +08:00
|
|
|
}
|
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
/// getOrCreateType - Get the type from the cache or create a new
|
|
|
|
/// one if necessary.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2008-11-10 14:08:34 +08:00
|
|
|
if (Ty.isNull())
|
|
|
|
return llvm::DIType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-22 04:18:30 +08:00
|
|
|
// Unwrap the type as needed for debug information.
|
|
|
|
Ty = UnwrapTypeForDebugInfo(Ty);
|
2009-11-15 05:08:12 +08:00
|
|
|
|
2009-09-20 03:27:24 +08:00
|
|
|
// Check for existing entry.
|
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,
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit) {
|
2009-09-25 09:40:47 +08:00
|
|
|
// Handle qualifiers, which recursively handles what they refer to.
|
First part of changes to eliminate problems with cv-qualifiers and
sugared types. The basic problem is that our qualifier accessors
(getQualifiers, getCVRQualifiers, isConstQualified, etc.) only look at
the current QualType and not at any qualifiers that come from sugared
types, meaning that we won't see these qualifiers through, e.g.,
typedefs:
typedef const int CInt;
typedef CInt Self;
Self.isConstQualified() currently returns false!
Various bugs (e.g., PR5383) have cropped up all over the front end due
to such problems. I'm addressing this problem by splitting each
qualifier accessor into two versions:
- the "local" version only returns qualifiers on this particular
QualType instance
- the "normal" version that will eventually combine qualifiers from this
QualType instance with the qualifiers on the canonical type to
produce the full set of qualifiers.
This commit adds the local versions and switches a few callers from
the "normal" version (e.g., isConstQualified) over to the "local"
version (e.g., isLocalConstQualified) when that is the right thing to
do, e.g., because we're printing or serializing the qualifiers. Also,
switch a bunch of
Context.getCanonicalType(T1).getUnqualifiedType() == Context.getCanonicalType(T2).getQualifiedType()
expressions over to
Context.hasSameUnqualifiedType(T1, T2)
llvm-svn: 88969
2009-11-17 05:35:15 +08:00
|
|
|
if (Ty.hasLocalQualifiers())
|
2009-09-25 09:40:47 +08:00
|
|
|
return CreateQualifiedType(Ty, Unit);
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2009-12-22 03:57:21 +08:00
|
|
|
const char *Diag = 0;
|
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
// Work out details of type.
|
2008-11-10 14:08:34 +08:00
|
|
|
switch (Ty->getTypeClass()) {
|
2009-02-27 07:50:07 +08:00
|
|
|
#define TYPE(Class, Base)
|
|
|
|
#define ABSTRACT_TYPE(Class, Base)
|
|
|
|
#define NON_CANONICAL_TYPE(Class, Base)
|
|
|
|
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
assert(false && "Dependent types cannot show up in debug information");
|
2009-08-19 09:28:17 +08:00
|
|
|
|
2009-11-07 02:24:04 +08:00
|
|
|
// FIXME: Handle these.
|
|
|
|
case Type::ExtVector:
|
|
|
|
return llvm::DIType();
|
2010-02-24 06:59:39 +08:00
|
|
|
|
|
|
|
case Type::Vector:
|
|
|
|
return CreateType(cast<VectorType>(Ty), Unit);
|
2009-07-14 09:20:56 +08:00
|
|
|
case Type::ObjCObjectPointer:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<ObjCObjectPointerType>(Ty), Unit);
|
2009-09-09 23:08:12 +08:00
|
|
|
case Type::ObjCInterface:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<ObjCInterfaceType>(Ty), Unit);
|
|
|
|
case Type::Builtin: return CreateType(cast<BuiltinType>(Ty), Unit);
|
|
|
|
case Type::Complex: return CreateType(cast<ComplexType>(Ty), Unit);
|
|
|
|
case Type::Pointer: return CreateType(cast<PointerType>(Ty), Unit);
|
2009-05-14 10:03:51 +08:00
|
|
|
case Type::BlockPointer:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<BlockPointerType>(Ty), Unit);
|
|
|
|
case Type::Typedef: return CreateType(cast<TypedefType>(Ty), Unit);
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::Record:
|
|
|
|
case Type::Enum:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<TagType>(Ty), Unit);
|
2008-11-10 14:08:34 +08:00
|
|
|
case Type::FunctionProto:
|
|
|
|
case Type::FunctionNoProto:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<FunctionType>(Ty), Unit);
|
2008-11-10 14:08:34 +08:00
|
|
|
case Type::ConstantArray:
|
|
|
|
case Type::VariableArray:
|
|
|
|
case Type::IncompleteArray:
|
2009-09-20 03:27:14 +08:00
|
|
|
return CreateType(cast<ArrayType>(Ty), Unit);
|
2009-11-07 03:19:55 +08:00
|
|
|
|
|
|
|
case Type::LValueReference:
|
|
|
|
return CreateType(cast<LValueReferenceType>(Ty), Unit);
|
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
case Type::MemberPointer:
|
|
|
|
return CreateType(cast<MemberPointerType>(Ty), Unit);
|
2009-12-22 03:57:21 +08:00
|
|
|
|
|
|
|
case Type::TemplateSpecialization:
|
|
|
|
case Type::Elaborated:
|
|
|
|
case Type::QualifiedName:
|
|
|
|
case Type::SubstTemplateTypeParm:
|
|
|
|
case Type::TypeOfExpr:
|
|
|
|
case Type::TypeOf:
|
2009-12-22 04:18:30 +08:00
|
|
|
case Type::Decltype:
|
|
|
|
llvm_unreachable("type should have been unwrapped!");
|
|
|
|
return llvm::DIType();
|
2009-12-22 03:57:21 +08:00
|
|
|
|
|
|
|
case Type::RValueReference:
|
|
|
|
// FIXME: Implement!
|
|
|
|
Diag = "rvalue references";
|
|
|
|
break;
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
2009-12-22 03:57:21 +08:00
|
|
|
|
|
|
|
assert(Diag && "Fall through without a diagnostic?");
|
|
|
|
unsigned DiagID = CGM.getDiags().getCustomDiagID(Diagnostic::Error,
|
|
|
|
"debug information for %0 is not yet supported");
|
|
|
|
CGM.getDiags().Report(FullSourceLoc(), DiagID)
|
|
|
|
<< Diag;
|
|
|
|
return llvm::DIType();
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitFunctionStart - Constructs the debug code for entering a function -
|
|
|
|
/// "llvm.dbg.func.start.".
|
2010-01-14 08:36:21 +08:00
|
|
|
void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
|
2008-05-25 13:15:42 +08:00
|
|
|
llvm::Function *Fn,
|
2008-11-10 14:08:34 +08:00
|
|
|
CGBuilderTy &Builder) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-14 08:36:21 +08:00
|
|
|
llvm::StringRef Name;
|
|
|
|
llvm::StringRef LinkageName;
|
|
|
|
|
|
|
|
const Decl *D = GD.getDecl();
|
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
2010-01-19 09:54:44 +08:00
|
|
|
// If there is a DISubprogram for this function available then use it.
|
|
|
|
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
|
|
|
|
FI = SPCache.find(FD);
|
|
|
|
if (FI != SPCache.end()) {
|
2010-03-09 04:53:17 +08:00
|
|
|
llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(FI->second));
|
|
|
|
if (SP.isSubprogram() && llvm::DISubprogram(SP.getNode()).isDefinition()) {
|
2010-01-19 09:54:44 +08:00
|
|
|
RegionStack.push_back(SP.getNode());
|
2010-01-30 02:11:03 +08:00
|
|
|
RegionMap[D] = llvm::WeakVH(SP.getNode());
|
2010-01-19 09:54:44 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-01-14 08:36:21 +08:00
|
|
|
Name = getFunctionName(FD);
|
2010-01-16 08:43:13 +08:00
|
|
|
if (!Name.empty() && Name[0] == '\01')
|
2010-01-15 05:46:57 +08:00
|
|
|
Name = Name.substr(1);
|
2010-01-14 08:36:21 +08:00
|
|
|
// Use mangled name as linkage name for c/c++ functions.
|
2010-01-15 05:46:57 +08:00
|
|
|
LinkageName = CGM.getMangledName(GD);
|
2010-01-14 08:36:21 +08:00
|
|
|
} else {
|
|
|
|
// Use llvm function name as linkage name.
|
|
|
|
Name = Fn->getName();
|
|
|
|
LinkageName = Name;
|
2010-01-19 08:25:12 +08:00
|
|
|
if (!Name.empty() && Name[0] == '\01')
|
|
|
|
Name = Name.substr(1);
|
2010-01-14 08:36:21 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-15 02:06:13 +08:00
|
|
|
// It is expected that CurLoc is set before using EmitFunctionStart.
|
|
|
|
// Usually, CurLoc points to the left bracket location of compound
|
|
|
|
// statement representing function body.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(CurLoc);
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.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());
|
2010-01-30 02:11:03 +08:00
|
|
|
RegionMap[D] = llvm::WeakVH(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.
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2009-09-09 23:08:12 +08:00
|
|
|
if (CurLoc == PrevLoc
|
2009-02-04 09:06:56 +08:00
|
|
|
|| (SM.getInstantiationLineNumber(CurLoc) ==
|
|
|
|
SM.getInstantiationLineNumber(PrevLoc)
|
2008-05-08 16:54:20 +08:00
|
|
|
&& SM.isFromSameFile(CurLoc, PrevLoc)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Update last state.
|
|
|
|
PrevLoc = CurLoc;
|
|
|
|
|
|
|
|
// Get the appropriate compile unit.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(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) {
|
2010-02-17 05:41:20 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(CurLoc);
|
2009-11-14 03:10:24 +08:00
|
|
|
llvm::DIDescriptor D =
|
|
|
|
DebugFactory.CreateLexicalBlock(RegionStack.empty() ?
|
|
|
|
llvm::DIDescriptor() :
|
2010-02-17 05:41:20 +08:00
|
|
|
llvm::DIDescriptor(RegionStack.back()),
|
|
|
|
PLoc.getLine(), PLoc.getColumn());
|
2009-11-14 03:10:24 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
|
|
|
|
// See BuildByRefType.
|
|
|
|
llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
|
|
|
|
uint64_t *XOffset) {
|
2008-10-17 09:07:56 +08:00
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 5> EltTys;
|
2009-03-28 07:16:32 +08:00
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
QualType FType;
|
|
|
|
uint64_t FieldSize, FieldOffset;
|
|
|
|
unsigned FieldAlign;
|
|
|
|
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
|
2010-02-11 02:49:08 +08:00
|
|
|
QualType Type = VD->getType();
|
2009-09-22 10:12:52 +08:00
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
FieldOffset = 0;
|
|
|
|
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
|
|
|
|
llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
2010-03-09 08:44:50 +08:00
|
|
|
"__isa", llvm::DIFile(),
|
2010-02-11 02:49:08 +08:00
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
2010-03-09 08:44:50 +08:00
|
|
|
"__forwarding", llvm::DIFile(),
|
2010-02-11 02:49:08 +08:00
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
FType = CGM.getContext().IntTy;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
2010-03-09 08:44:50 +08:00
|
|
|
"__flags", llvm::DIFile(),
|
2010-02-11 02:49:08 +08:00
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
FType = CGM.getContext().IntTy;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
2010-03-09 08:44:50 +08:00
|
|
|
"__size", llvm::DIFile(),
|
2010-02-11 02:49:08 +08:00
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
bool HasCopyAndDispose = CGM.BlockRequiresCopying(Type);
|
|
|
|
if (HasCopyAndDispose) {
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
|
2009-09-22 10:12:52 +08:00
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2009-09-22 10:12:52 +08:00
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
2010-02-11 02:49:08 +08:00
|
|
|
"__copy_helper",
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile(),
|
2009-09-22 10:12:52 +08:00
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
2010-02-11 02:49:08 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
|
2009-09-22 10:12:52 +08:00
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2009-09-22 10:12:52 +08:00
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
2010-02-11 02:49:08 +08:00
|
|
|
"__destroy_helper",
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile(),
|
2009-09-22 10:12:52 +08:00
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
2010-02-11 02:49:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CharUnits Align = CGM.getContext().getDeclAlign(VD);
|
|
|
|
if (Align > CharUnits::fromQuantity(
|
|
|
|
CGM.getContext().Target.getPointerAlign(0) / 8)) {
|
|
|
|
unsigned AlignedOffsetInBytes
|
|
|
|
= llvm::RoundUpToAlignment(FieldOffset/8, Align.getQuantity());
|
|
|
|
unsigned NumPaddingBytes
|
|
|
|
= AlignedOffsetInBytes - FieldOffset/8;
|
2009-09-22 10:12:52 +08:00
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
if (NumPaddingBytes > 0) {
|
|
|
|
llvm::APInt pad(32, NumPaddingBytes);
|
|
|
|
FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy,
|
|
|
|
pad, ArrayType::Normal, 0);
|
2009-09-22 10:12:52 +08:00
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
2009-12-07 02:00:51 +08:00
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = CGM.getContext().getTypeAlign(FType);
|
2010-02-11 02:49:08 +08:00
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member,
|
2010-03-09 08:44:50 +08:00
|
|
|
Unit, "", llvm::DIFile(),
|
2009-09-22 10:12:52 +08:00
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
}
|
2010-02-11 02:49:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FType = Type;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = CGM.getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = Align.getQuantity()*8;
|
2009-09-22 10:12:52 +08:00
|
|
|
|
2010-02-11 02:49:08 +08:00
|
|
|
*XOffset = FieldOffset;
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
2010-03-09 08:44:50 +08:00
|
|
|
VD->getName(), llvm::DIFile(),
|
2010-02-11 02:49:08 +08:00
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
|
|
|
|
llvm::DIArray Elements =
|
|
|
|
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
|
|
|
|
|
|
|
unsigned Flags = llvm::DIType::FlagBlockByrefStruct;
|
|
|
|
|
|
|
|
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type,
|
|
|
|
Unit, "",
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile(),
|
2009-09-22 10:12:52 +08:00
|
|
|
0, FieldOffset, 0, 0, Flags,
|
|
|
|
llvm::DIType(), Elements);
|
2010-02-11 02:49:08 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
/// EmitDeclare - Emit local variable declaration debug info.
|
|
|
|
void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
|
|
|
|
llvm::Value *Storage, CGBuilderTy &Builder) {
|
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
|
|
|
|
// 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 CodeGenOptions &CGO = CGM.getCodeGenOpts();
|
|
|
|
if (CGO.OptimizationLevel)
|
|
|
|
return;
|
|
|
|
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
|
2010-02-11 02:49:08 +08:00
|
|
|
llvm::DIType Ty;
|
|
|
|
uint64_t XOffset = 0;
|
|
|
|
if (VD->hasAttr<BlocksAttr>())
|
|
|
|
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
|
|
|
|
else
|
|
|
|
Ty = getOrCreateType(VD->getType(), Unit);
|
2009-05-05 12:57:08 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Get location information.
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2010-02-02 05:39:52 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(VD->getLocation());
|
2009-05-05 12:57:08 +08:00
|
|
|
unsigned Line = 0;
|
2009-11-17 04:33:31 +08:00
|
|
|
unsigned Column = 0;
|
2010-02-10 09:09:50 +08:00
|
|
|
if (PLoc.isInvalid())
|
|
|
|
PLoc = SM.getPresumedLoc(CurLoc);
|
|
|
|
if (PLoc.isValid()) {
|
2009-05-05 12:57:08 +08:00
|
|
|
Line = PLoc.getLine();
|
2009-11-17 04:33:31 +08:00
|
|
|
Column = PLoc.getColumn();
|
2010-03-09 08:44:50 +08:00
|
|
|
Unit = getOrCreateFile(CurLoc);
|
2009-11-17 04:33:31 +08:00
|
|
|
} else {
|
2010-03-09 08:44:50 +08:00
|
|
|
Unit = llvm::DIFile();
|
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()),
|
2010-02-02 05:39:52 +08:00
|
|
|
VD->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);
|
2009-12-29 05:44:41 +08:00
|
|
|
llvm::DILocation DL = DebugFactory.CreateLocation(Line, Column, DS, DO);
|
|
|
|
|
2009-12-29 07:41:39 +08:00
|
|
|
Call->setMetadata("dbg", 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) {
|
2010-02-02 05:52:22 +08:00
|
|
|
const ValueDecl *VD = BDRE->getDecl();
|
2009-09-30 10:43:10 +08:00
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
|
|
|
|
// 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-12-07 02:00:51 +08:00
|
|
|
const CodeGenOptions &CGO = CGM.getCodeGenOpts();
|
2009-11-13 01:24:48 +08:00
|
|
|
if (CGO.OptimizationLevel || Builder.GetInsertBlock() == 0)
|
2009-09-30 10:43:10 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
uint64_t XOffset = 0;
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
|
2010-02-11 02:49:08 +08:00
|
|
|
llvm::DIType Ty;
|
|
|
|
if (VD->hasAttr<BlocksAttr>())
|
|
|
|
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
|
|
|
|
else
|
|
|
|
Ty = getOrCreateType(VD->getType(), Unit);
|
2009-09-30 10:43:10 +08:00
|
|
|
|
|
|
|
// Get location information.
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2010-02-02 05:52:22 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(VD->getLocation());
|
2009-09-30 10:43:10 +08:00
|
|
|
unsigned Line = 0;
|
|
|
|
if (!PLoc.isInvalid())
|
|
|
|
Line = PLoc.getLine();
|
|
|
|
else
|
2010-03-09 08:44:50 +08:00
|
|
|
Unit = llvm::DIFile();
|
2009-09-30 10:43:10 +08:00
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
CharUnits offset = CGF->BlockDecls[VD];
|
2009-09-30 10:43:10 +08:00
|
|
|
llvm::SmallVector<llvm::Value *, 9> addr;
|
2010-01-25 11:29:35 +08:00
|
|
|
const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext());
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpDeref));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpPlus));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
|
2009-09-30 10:43:10 +08:00
|
|
|
if (BDRE->isByRef()) {
|
2010-01-25 11:29:35 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpDeref));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpPlus));
|
2010-01-12 01:06:35 +08:00
|
|
|
// offset of __forwarding field
|
|
|
|
offset = CharUnits::fromQuantity(CGF->LLVMPointerWidth/8);
|
2010-01-25 11:29:35 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpDeref));
|
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpPlus));
|
2010-01-12 01:06:35 +08:00
|
|
|
// offset of x field
|
|
|
|
offset = CharUnits::fromQuantity(XOffset/8);
|
2010-01-25 11:29:35 +08:00
|
|
|
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
|
2009-09-30 10:43:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create the descriptor for the variable.
|
|
|
|
llvm::DIVariable D =
|
2010-01-25 11:34:56 +08:00
|
|
|
DebugFactory.CreateComplexVariable(Tag,
|
|
|
|
llvm::DIDescriptor(RegionStack.back()),
|
2010-02-02 05:52:22 +08:00
|
|
|
VD->getName(), Unit, Line, Ty,
|
2009-09-30 10:43:10 +08:00
|
|
|
addr);
|
|
|
|
// Insert an llvm.dbg.declare into the current block.
|
2009-11-12 03:10:19 +08:00
|
|
|
llvm::Instruction *Call =
|
2010-01-25 11:34:56 +08:00
|
|
|
DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock());
|
2009-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);
|
2009-12-29 05:44:41 +08:00
|
|
|
|
2009-12-29 07:41:39 +08:00
|
|
|
Call->setMetadata("dbg", DL.getNode());
|
2009-09-30 10:43:10 +08:00
|
|
|
}
|
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::Value *Storage,
|
|
|
|
CGBuilderTy &Builder) {
|
2010-02-02 05:52:22 +08:00
|
|
|
EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder);
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2008-06-05 16:59:10 +08:00
|
|
|
|
2009-09-30 10:43:10 +08:00
|
|
|
void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
|
|
|
|
const BlockDeclRefExpr *BDRE, llvm::Value *Storage, CGBuilderTy &Builder,
|
|
|
|
CodeGenFunction *CGF) {
|
|
|
|
EmitDeclare(BDRE, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder, CGF);
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
|
|
|
|
/// variable declaration.
|
2010-02-02 05:52:22 +08:00
|
|
|
void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
|
2008-11-10 14:08:34 +08:00
|
|
|
CGBuilderTy &Builder) {
|
2010-02-02 05:52:22 +08:00
|
|
|
EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, Builder);
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
2008-06-05 16:59:10 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
/// EmitGlobalVariable - Emit information about a global variable.
|
2009-09-09 23:08:12 +08:00
|
|
|
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
|
2010-02-02 05:34:11 +08:00
|
|
|
const VarDecl *D) {
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Create global variable debug descriptor.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(D->getLocation());
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2010-02-02 05:34:11 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(D->getLocation());
|
2009-04-18 05:35:15 +08:00
|
|
|
unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
2008-11-24 11:54:41 +08:00
|
|
|
|
2010-02-02 05:34:11 +08:00
|
|
|
QualType T = D->getType();
|
2008-11-27 01:40:42 +08:00
|
|
|
if (T->isIncompleteArrayType()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-27 01:40:42 +08:00
|
|
|
// CodeGen turns int[] into int[1] so we'll do the same here.
|
|
|
|
llvm::APSInt ConstVal(32);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-27 01:40:42 +08:00
|
|
|
ConstVal = 1;
|
2009-12-07 02:00:51 +08:00
|
|
|
QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
T = CGM.getContext().getConstantArrayType(ET, ConstVal,
|
2008-11-27 01:40:42 +08:00
|
|
|
ArrayType::Normal, 0);
|
|
|
|
}
|
2010-02-25 13:20:44 +08:00
|
|
|
llvm::StringRef DeclName = Var->getName();
|
2010-02-02 05:34:11 +08:00
|
|
|
llvm::DIDescriptor DContext =
|
|
|
|
getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()), Unit);
|
|
|
|
DebugFactory.CreateGlobalVariable(DContext, DeclName,
|
2010-01-29 07:15:27 +08:00
|
|
|
DeclName, 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,
|
2010-02-02 05:52:22 +08:00
|
|
|
ObjCInterfaceDecl *ID) {
|
2009-02-27 05:10:26 +08:00
|
|
|
// Create global variable debug descriptor.
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile Unit = getOrCreateFile(ID->getLocation());
|
2009-12-07 02:00:51 +08:00
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
2010-02-02 05:52:22 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(ID->getLocation());
|
2009-04-18 05:35:15 +08:00
|
|
|
unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
llvm::StringRef Name = ID->getName();
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2010-02-02 05:52:22 +08:00
|
|
|
QualType T = CGM.getContext().getObjCInterfaceType(ID);
|
2009-02-27 05:10:26 +08:00
|
|
|
if (T->isIncompleteArrayType()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// CodeGen turns int[] into int[1] so we'll do the same here.
|
|
|
|
llvm::APSInt ConstVal(32);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
ConstVal = 1;
|
2009-12-07 02:00:51 +08:00
|
|
|
QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-07 02:00:51 +08:00
|
|
|
T = CGM.getContext().getConstantArrayType(ET, ConstVal,
|
2009-02-27 05:10:26 +08:00
|
|
|
ArrayType::Normal, 0);
|
|
|
|
}
|
|
|
|
|
2009-10-21 02:26:30 +08:00
|
|
|
DebugFactory.CreateGlobalVariable(Unit, Name, Name, Name, Unit, LineNo,
|
2009-02-27 05:10:26 +08:00
|
|
|
getOrCreateType(T, Unit),
|
|
|
|
Var->hasInternalLinkage(),
|
|
|
|
true/*definition*/, Var);
|
|
|
|
}
|
2010-02-02 03:16:32 +08:00
|
|
|
|
|
|
|
/// getOrCreateNamesSpace - Return namespace descriptor for the given
|
|
|
|
/// namespace decl.
|
|
|
|
llvm::DINameSpace
|
|
|
|
CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl,
|
|
|
|
llvm::DIDescriptor Unit) {
|
|
|
|
llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH>::iterator I =
|
|
|
|
NameSpaceCache.find(NSDecl);
|
|
|
|
if (I != NameSpaceCache.end())
|
|
|
|
return llvm::DINameSpace(cast<llvm::MDNode>(I->second));
|
|
|
|
|
|
|
|
SourceManager &SM = CGM.getContext().getSourceManager();
|
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(NSDecl->getLocation());
|
|
|
|
unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
|
|
|
|
|
|
|
llvm::DIDescriptor Context =
|
2010-02-02 05:34:11 +08:00
|
|
|
getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()), Unit);
|
2010-02-02 03:16:32 +08:00
|
|
|
llvm::DINameSpace NS =
|
|
|
|
DebugFactory.CreateNameSpace(Context, NSDecl->getName(),
|
2010-03-09 08:44:50 +08:00
|
|
|
llvm::DIFile(Unit.getNode()), LineNo);
|
2010-02-02 03:16:32 +08:00
|
|
|
NameSpaceCache[NSDecl] = llvm::WeakVH(NS.getNode());
|
|
|
|
return NS;
|
|
|
|
}
|