aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGDebugInfo.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:08 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:08 +0000
commitbab175ec4b075c8076ba14c762900392533f6ee4 (patch)
tree01f4f29419a2cb10abe13c1e63cd2a66068b0137 /lib/CodeGen/CGDebugInfo.cpp
parent8b7a8012d223fac5d17d16a66bb39168a9a1dfc0 (diff)
downloadsrc-bab175ec4b075c8076ba14c762900392533f6ee4.tar.gz
src-bab175ec4b075c8076ba14c762900392533f6ee4.zip
Vendor import of clang trunk r290819:vendor/clang/clang-trunk-r290819
Notes
Notes: svn path=/vendor/clang/dist/; revision=311118 svn path=/vendor/clang/clang-trunk-r290819/; revision=311119; tag=vendor/clang/clang-trunk-r290819
Diffstat (limited to 'lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp593
1 files changed, 404 insertions, 189 deletions
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 0607a5157a6f..12a68036b09c 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -13,9 +13,9 @@
#include "CGDebugInfo.h"
#include "CGBlocks.h"
-#include "CGRecordLayout.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
+#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
@@ -31,6 +31,7 @@
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Constants.h"
@@ -40,10 +41,24 @@
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"
using namespace clang;
using namespace clang::CodeGen;
+static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) {
+ auto TI = Ctx.getTypeInfo(Ty);
+ return TI.AlignIsRequired ? TI.Align : 0;
+}
+
+static uint32_t getTypeAlignIfRequired(QualType Ty, const ASTContext &Ctx) {
+ return getTypeAlignIfRequired(Ty.getTypePtr(), Ctx);
+}
+
+static uint32_t getDeclAlignIfRequired(const Decl *D, const ASTContext &Ctx) {
+ return D->hasAttr<AlignedAttr>() ? D->getMaxAlignment() : 0;
+}
+
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
: CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()),
DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs),
@@ -306,11 +321,36 @@ StringRef CGDebugInfo::getClassName(const RecordDecl *RD) {
return StringRef();
}
+llvm::DIFile::ChecksumKind
+CGDebugInfo::computeChecksum(FileID FID, SmallString<32> &Checksum) const {
+ Checksum.clear();
+
+ if (!CGM.getCodeGenOpts().EmitCodeView)
+ return llvm::DIFile::CSK_None;
+
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ bool Invalid;
+ llvm::MemoryBuffer *MemBuffer = SM.getBuffer(FID, &Invalid);
+ if (Invalid)
+ return llvm::DIFile::CSK_None;
+
+ llvm::MD5 Hash;
+ llvm::MD5::MD5Result Result;
+
+ Hash.update(MemBuffer->getBuffer());
+ Hash.final(Result);
+
+ Hash.stringifyResult(Result, Checksum);
+ return llvm::DIFile::CSK_MD5;
+}
+
llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (!Loc.isValid())
// If Location is not valid then use main input file.
return DBuilder.createFile(remapDIPath(TheCU->getFilename()),
- remapDIPath(TheCU->getDirectory()));
+ remapDIPath(TheCU->getDirectory()),
+ TheCU->getFile()->getChecksumKind(),
+ TheCU->getFile()->getChecksum());
SourceManager &SM = CGM.getContext().getSourceManager();
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
@@ -318,7 +358,9 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty())
// If the location is not valid then use main input file.
return DBuilder.createFile(remapDIPath(TheCU->getFilename()),
- remapDIPath(TheCU->getDirectory()));
+ remapDIPath(TheCU->getDirectory()),
+ TheCU->getFile()->getChecksumKind(),
+ TheCU->getFile()->getChecksum());
// Cache the results.
const char *fname = PLoc.getFilename();
@@ -330,8 +372,13 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
return cast<llvm::DIFile>(V);
}
+ SmallString<32> Checksum;
+ llvm::DIFile::ChecksumKind CSKind =
+ computeChecksum(SM.getFileID(Loc), Checksum);
+
llvm::DIFile *F = DBuilder.createFile(remapDIPath(PLoc.getFilename()),
- remapDIPath(getCurrentDirname()));
+ remapDIPath(getCurrentDirname()),
+ CSKind, Checksum);
DIFileCache[fname].reset(F);
return F;
@@ -339,7 +386,9 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
llvm::DIFile *CGDebugInfo::getOrCreateMainFile() {
return DBuilder.createFile(remapDIPath(TheCU->getFilename()),
- remapDIPath(TheCU->getDirectory()));
+ remapDIPath(TheCU->getDirectory()),
+ TheCU->getFile()->getChecksumKind(),
+ TheCU->getFile()->getChecksum());
}
std::string CGDebugInfo::remapDIPath(StringRef Path) const {
@@ -382,6 +431,8 @@ StringRef CGDebugInfo::getCurrentDirname() {
}
void CGDebugInfo::CreateCompileUnit() {
+ SmallString<32> Checksum;
+ llvm::DIFile::ChecksumKind CSKind = llvm::DIFile::CSK_None;
// Should we be asking the SourceManager for the main file name, instead of
// accepting it as an argument? This just causes the main file name to
@@ -408,6 +459,7 @@ void CGDebugInfo::CreateCompileUnit() {
llvm::sys::path::append(MainFileDirSS, MainFileName);
MainFileName = MainFileDirSS.str();
}
+ CSKind = computeChecksum(SM.getMainFileID(), Checksum);
}
llvm::dwarf::SourceLanguage LangTag;
@@ -452,9 +504,12 @@ void CGDebugInfo::CreateCompileUnit() {
// Create new compile unit.
// FIXME - Eliminate TheCU.
TheCU = DBuilder.createCompileUnit(
- LangTag, remapDIPath(MainFileName), remapDIPath(getCurrentDirname()),
+ LangTag, DBuilder.createFile(remapDIPath(MainFileName),
+ remapDIPath(getCurrentDirname()), CSKind,
+ Checksum),
Producer, LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers,
- CGM.getCodeGenOpts().SplitDwarfFile, EmissionKind, 0 /* DWOid */);
+ CGM.getCodeGenOpts().SplitDwarfFile, EmissionKind, 0 /* DWOid */,
+ CGM.getCodeGenOpts().SplitDwarfInlining);
}
llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
@@ -494,14 +549,14 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
auto *ISATy = DBuilder.createPointerType(ClassTy, Size);
- ObjTy =
- DBuilder.createStructType(TheCU, "objc_object", getOrCreateMainFile(),
- 0, 0, 0, 0, nullptr, llvm::DINodeArray());
+ ObjTy = DBuilder.createStructType(
+ TheCU, "objc_object", getOrCreateMainFile(), 0, 0, 0,
+ llvm::DINode::FlagZero, nullptr, llvm::DINodeArray());
DBuilder.replaceArrays(
- ObjTy,
- DBuilder.getOrCreateArray(&*DBuilder.createMemberType(
- ObjTy, "isa", getOrCreateMainFile(), 0, Size, 0, 0, 0, ISATy)));
+ ObjTy, DBuilder.getOrCreateArray(&*DBuilder.createMemberType(
+ ObjTy, "isa", getOrCreateMainFile(), 0, Size, 0, 0,
+ llvm::DINode::FlagZero, ISATy)));
return ObjTy;
}
case BuiltinType::ObjCSel: {
@@ -518,9 +573,8 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
SingletonId);
#include "clang/Basic/OpenCLImageTypes.def"
case BuiltinType::OCLSampler:
- return DBuilder.createBasicType(
- "opencl_sampler_t", CGM.getContext().getTypeSize(BT),
- CGM.getContext().getTypeAlign(BT), llvm::dwarf::DW_ATE_unsigned);
+ return getOrCreateStructPtrType("opencl_sampler_t",
+ OCLSamplerDITy);
case BuiltinType::OCLEvent:
return getOrCreateStructPtrType("opencl_event_t", OCLEventDITy);
case BuiltinType::OCLClkEvent:
@@ -594,21 +648,19 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
BTName = BT->getName(CGM.getLangOpts());
break;
}
- // Bit size, align and offset of the type.
+ // Bit size and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(BT);
- uint64_t Align = CGM.getContext().getTypeAlign(BT);
- return DBuilder.createBasicType(BTName, Size, Align, Encoding);
+ return DBuilder.createBasicType(BTName, Size, Encoding);
}
llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) {
- // Bit size, align and offset of the type.
+ // Bit size and offset of the type.
llvm::dwarf::TypeKind Encoding = llvm::dwarf::DW_ATE_complex_float;
if (Ty->isComplexIntegerType())
Encoding = llvm::dwarf::DW_ATE_lo_user;
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- return DBuilder.createBasicType("complex", Size, Align, Encoding);
+ return DBuilder.createBasicType("complex", Size, Encoding);
}
llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty,
@@ -721,13 +773,7 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
StringRef RDName = getClassName(RD);
uint64_t Size = 0;
- uint64_t Align = 0;
-
- const RecordDecl *D = RD->getDefinition();
- if (D && D->isCompleteDefinition()) {
- Size = CGM.getContext().getTypeSize(Ty);
- Align = CGM.getContext().getTypeAlign(Ty);
- }
+ uint32_t Align = 0;
// Create the type.
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
@@ -749,7 +795,7 @@ llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
// because that does not return the correct value for references.
unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
uint64_t Size = CGM.getTarget().getPointerWidth(AS);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+ auto Align = getTypeAlignIfRequired(Ty, CGM.getContext());
if (Tag == llvm::dwarf::DW_TAG_reference_type ||
Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
@@ -776,7 +822,7 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
SmallVector<llvm::Metadata *, 8> EltTys;
QualType FType;
uint64_t FieldSize, FieldOffset;
- unsigned FieldAlign;
+ uint32_t FieldAlign;
llvm::DINodeArray Elements;
FieldOffset = 0;
@@ -787,7 +833,7 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
Elements = DBuilder.getOrCreateArray(EltTys);
EltTys.clear();
- unsigned Flags = llvm::DINode::FlagAppleBlock;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagAppleBlock;
unsigned LineNo = 0;
auto *EltTy =
@@ -811,9 +857,9 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
FieldSize = CGM.getContext().getTypeSize(Ty);
FieldAlign = CGM.getContext().getTypeAlign(Ty);
- EltTys.push_back(DBuilder.createMemberType(Unit, "__descriptor", nullptr, LineNo,
- FieldSize, FieldAlign, FieldOffset,
- 0, DescTy));
+ EltTys.push_back(DBuilder.createMemberType(
+ Unit, "__descriptor", nullptr, LineNo, FieldSize, FieldAlign, FieldOffset,
+ llvm::DINode::FlagZero, DescTy));
FieldOffset += FieldSize;
Elements = DBuilder.getOrCreateArray(EltTys);
@@ -893,6 +939,7 @@ static unsigned getDwarfCC(CallingConv CC) {
case CC_Swift:
case CC_PreserveMost:
case CC_PreserveAll:
+ case CC_X86RegCall:
return 0;
}
return 0;
@@ -917,14 +964,15 @@ llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty,
}
llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys);
- return DBuilder.createSubroutineType(EltTypeArray, 0,
+ return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero,
getDwarfCC(Ty->getCallConv()));
}
/// Convert an AccessSpecifier into the corresponding DINode flag.
/// As an optimization, return 0 if the access specifier equals the
/// default for the containing type.
-static unsigned getAccessFlag(AccessSpecifier Access, const RecordDecl *RD) {
+static llvm::DINode::DIFlags getAccessFlag(AccessSpecifier Access,
+ const RecordDecl *RD) {
AccessSpecifier Default = clang::AS_none;
if (RD && RD->isClass())
Default = clang::AS_private;
@@ -932,7 +980,7 @@ static unsigned getAccessFlag(AccessSpecifier Access, const RecordDecl *RD) {
Default = clang::AS_public;
if (Access == Default)
- return 0;
+ return llvm::DINode::FlagZero;
switch (Access) {
case clang::AS_private:
@@ -942,7 +990,7 @@ static unsigned getAccessFlag(AccessSpecifier Access, const RecordDecl *RD) {
case clang::AS_public:
return llvm::DINode::FlagPublic;
case clang::AS_none:
- return 0;
+ return llvm::DINode::FlagZero;
}
llvm_unreachable("unexpected access enumerator");
}
@@ -964,21 +1012,20 @@ llvm::DIType *CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl,
CGM.getTypes().getCGRecordLayout(RD).getBitFieldInfo(BitFieldDecl);
uint64_t SizeInBits = BitFieldInfo.Size;
assert(SizeInBits > 0 && "found named 0-width bitfield");
- unsigned AlignInBits = CGM.getContext().getTypeAlign(Ty);
uint64_t StorageOffsetInBits =
CGM.getContext().toBits(BitFieldInfo.StorageOffset);
uint64_t OffsetInBits = StorageOffsetInBits + BitFieldInfo.Offset;
- unsigned Flags = getAccessFlag(BitFieldDecl->getAccess(), RD);
+ llvm::DINode::DIFlags Flags = getAccessFlag(BitFieldDecl->getAccess(), RD);
return DBuilder.createBitFieldMemberType(
- RecordTy, Name, File, Line, SizeInBits, AlignInBits, OffsetInBits,
- StorageOffsetInBits, Flags, DebugType);
+ RecordTy, Name, File, Line, SizeInBits, OffsetInBits, StorageOffsetInBits,
+ Flags, DebugType);
}
llvm::DIType *
CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc,
AccessSpecifier AS, uint64_t offsetInBits,
- llvm::DIFile *tunit, llvm::DIScope *scope,
- const RecordDecl *RD) {
+ uint32_t AlignInBits, llvm::DIFile *tunit,
+ llvm::DIScope *scope, const RecordDecl *RD) {
llvm::DIType *debugType = getOrCreateType(type, tunit);
// Get the location for the field.
@@ -986,16 +1033,17 @@ CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc,
unsigned line = getLineNumber(loc);
uint64_t SizeInBits = 0;
- unsigned AlignInBits = 0;
+ auto Align = AlignInBits;
if (!type->isIncompleteArrayType()) {
TypeInfo TI = CGM.getContext().getTypeInfo(type);
SizeInBits = TI.Width;
- AlignInBits = TI.Align;
+ if (!Align)
+ Align = getTypeAlignIfRequired(type, CGM.getContext());
}
- unsigned flags = getAccessFlag(AS, RD);
+ llvm::DINode::DIFlags flags = getAccessFlag(AS, RD);
return DBuilder.createMemberType(scope, name, file, line, SizeInBits,
- AlignInBits, offsetInBits, flags, debugType);
+ Align, offsetInBits, flags, debugType);
}
void CGDebugInfo::CollectRecordLambdaFields(
@@ -1017,9 +1065,10 @@ void CGDebugInfo::CollectRecordLambdaFields(
VarDecl *V = C.getCapturedVar();
StringRef VName = V->getName();
llvm::DIFile *VUnit = getOrCreateFile(Loc);
+ auto Align = getDeclAlignIfRequired(V, CGM.getContext());
llvm::DIType *FieldType = createFieldType(
VName, Field->getType(), Loc, Field->getAccess(),
- layout.getFieldOffset(fieldno), VUnit, RecordTy, CXXDecl);
+ layout.getFieldOffset(fieldno), Align, VUnit, RecordTy, CXXDecl);
elements.push_back(FieldType);
} else if (C.capturesThis()) {
// TODO: Need to handle 'this' in some way by probably renaming the
@@ -1060,9 +1109,10 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
}
}
- unsigned Flags = getAccessFlag(Var->getAccess(), RD);
+ llvm::DINode::DIFlags Flags = getAccessFlag(Var->getAccess(), RD);
+ auto Align = getDeclAlignIfRequired(Var, CGM.getContext());
llvm::DIDerivedType *GV = DBuilder.createStaticMemberType(
- RecordTy, VName, VUnit, LineNumber, VTy, Flags, C);
+ RecordTy, VName, VUnit, LineNumber, VTy, Flags, C, Align);
StaticDataMemberCache[Var->getCanonicalDecl()].reset(GV);
return GV;
}
@@ -1082,14 +1132,26 @@ void CGDebugInfo::CollectRecordNormalField(
if (field->isBitField()) {
FieldType = createBitFieldType(field, RecordTy, RD);
} else {
+ auto Align = getDeclAlignIfRequired(field, CGM.getContext());
FieldType =
createFieldType(name, type, field->getLocation(), field->getAccess(),
- OffsetInBits, tunit, RecordTy, RD);
+ OffsetInBits, Align, tunit, RecordTy, RD);
}
elements.push_back(FieldType);
}
+void CGDebugInfo::CollectRecordNestedRecord(
+ const RecordDecl *RD, SmallVectorImpl<llvm::Metadata *> &elements) {
+ QualType Ty = CGM.getContext().getTypeDeclType(RD);
+ // Injected class names are not considered nested records.
+ if (isa<InjectedClassNameType>(Ty))
+ return;
+ SourceLocation Loc = RD->getLocation();
+ llvm::DIType *nestedType = getOrCreateType(Ty, getOrCreateFile(Loc));
+ elements.push_back(nestedType);
+}
+
void CGDebugInfo::CollectRecordFields(
const RecordDecl *record, llvm::DIFile *tunit,
SmallVectorImpl<llvm::Metadata *> &elements,
@@ -1101,6 +1163,10 @@ void CGDebugInfo::CollectRecordFields(
else {
const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);
+ // Debug info for nested records is included in the member list only for
+ // CodeView.
+ bool IncludeNestedRecords = CGM.getCodeGenOpts().EmitCodeView;
+
// Field number for non-static fields.
unsigned fieldNo = 0;
@@ -1126,7 +1192,10 @@ void CGDebugInfo::CollectRecordFields(
// Bump field number for next field.
++fieldNo;
- }
+ } else if (const auto *nestedRec = dyn_cast<CXXRecordDecl>(I))
+ if (IncludeNestedRecords && !nestedRec->isImplicit() &&
+ nestedRec->getDeclContext() == record)
+ CollectRecordNestedRecord(nestedRec, elements);
}
}
@@ -1162,7 +1231,7 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType(
QualType PointeeTy = ThisPtrTy->getPointeeType();
unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
uint64_t Size = CGM.getTarget().getPointerWidth(AS);
- uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy);
+ auto Align = getTypeAlignIfRequired(ThisPtrTy, CGM.getContext());
llvm::DIType *PointeeType = getOrCreateType(PointeeTy, Unit);
llvm::DIType *ThisPtrType =
DBuilder.createPointerType(PointeeType, Size, Align);
@@ -1185,7 +1254,7 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType(
llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts);
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
if (Func->getExtProtoInfo().RefQualifier == RQ_LValue)
Flags |= llvm::DINode::FlagLValueReference;
if (Func->getExtProtoInfo().RefQualifier == RQ_RValue)
@@ -1236,7 +1305,7 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
llvm::DIType *ContainingType = nullptr;
unsigned Virtuality = 0;
unsigned VIndex = 0;
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
int ThisAdjustment = 0;
if (Method->isVirtual()) {
@@ -1347,13 +1416,33 @@ void CGDebugInfo::CollectCXXMemberFunctions(
void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit,
SmallVectorImpl<llvm::Metadata *> &EltTys,
llvm::DIType *RecordTy) {
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
- for (const auto &BI : RD->bases()) {
- unsigned BFlags = 0;
- uint64_t BaseOffset;
+ llvm::DenseSet<CanonicalDeclPtr<const CXXRecordDecl>> SeenTypes;
+ CollectCXXBasesAux(RD, Unit, EltTys, RecordTy, RD->bases(), SeenTypes,
+ llvm::DINode::FlagZero);
+
+ // If we are generating CodeView debug info, we also need to emit records for
+ // indirect virtual base classes.
+ if (CGM.getCodeGenOpts().EmitCodeView) {
+ CollectCXXBasesAux(RD, Unit, EltTys, RecordTy, RD->vbases(), SeenTypes,
+ llvm::DINode::FlagIndirectVirtualBase);
+ }
+}
+void CGDebugInfo::CollectCXXBasesAux(
+ const CXXRecordDecl *RD, llvm::DIFile *Unit,
+ SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy,
+ const CXXRecordDecl::base_class_const_range &Bases,
+ llvm::DenseSet<CanonicalDeclPtr<const CXXRecordDecl>> &SeenTypes,
+ llvm::DINode::DIFlags StartingFlags) {
+ const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+ for (const auto &BI : Bases) {
const auto *Base =
cast<CXXRecordDecl>(BI.getType()->getAs<RecordType>()->getDecl());
+ if (!SeenTypes.insert(Base).second)
+ continue;
+ auto *BaseTy = getOrCreateType(BI.getType(), Unit);
+ llvm::DINode::DIFlags BFlags = StartingFlags;
+ uint64_t BaseOffset;
if (BI.isVirtual()) {
if (CGM.getTarget().getCXXABI().isItaniumFamily()) {
@@ -1368,15 +1457,15 @@ void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit,
BaseOffset =
4 * CGM.getMicrosoftVTableContext().getVBTableIndex(RD, Base);
}
- BFlags = llvm::DINode::FlagVirtual;
+ BFlags |= llvm::DINode::FlagVirtual;
} else
BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base));
// FIXME: Inconsistent units for BaseOffset. It is in bytes when
// BI->isVirtual() and bits when not.
BFlags |= getAccessFlag(BI.getAccessSpecifier(), RD);
- llvm::DIType *DTy = DBuilder.createInheritance(
- RecordTy, getOrCreateType(BI.getType(), Unit), BaseOffset, BFlags);
+ llvm::DIType *DTy =
+ DBuilder.createInheritance(RecordTy, BaseTy, BaseOffset, BFlags);
EltTys.push_back(DTy);
}
}
@@ -1531,22 +1620,56 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
}
void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit,
- SmallVectorImpl<llvm::Metadata *> &EltTys) {
+ SmallVectorImpl<llvm::Metadata *> &EltTys,
+ llvm::DICompositeType *RecordTy) {
+ // If this class is not dynamic then there is not any vtable info to collect.
+ if (!RD->isDynamicClass())
+ return;
+
+ // Don't emit any vtable shape or vptr info if this class doesn't have an
+ // extendable vfptr. This can happen if the class doesn't have virtual
+ // methods, or in the MS ABI if those virtual methods only come from virtually
+ // inherited bases.
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+ if (!RL.hasExtendableVFPtr())
+ return;
- // If there is a primary base then it will hold vtable info.
+ // CodeView needs to know how large the vtable of every dynamic class is, so
+ // emit a special named pointer type into the element list. The vptr type
+ // points to this type as well.
+ llvm::DIType *VPtrTy = nullptr;
+ bool NeedVTableShape = CGM.getCodeGenOpts().EmitCodeView &&
+ CGM.getTarget().getCXXABI().isMicrosoft();
+ if (NeedVTableShape) {
+ uint64_t PtrWidth =
+ CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
+ const VTableLayout &VFTLayout =
+ CGM.getMicrosoftVTableContext().getVFTableLayout(RD, CharUnits::Zero());
+ unsigned VSlotCount =
+ VFTLayout.vtable_components().size() - CGM.getLangOpts().RTTIData;
+ unsigned VTableWidth = PtrWidth * VSlotCount;
+
+ // Create a very wide void* type and insert it directly in the element list.
+ llvm::DIType *VTableType =
+ DBuilder.createPointerType(nullptr, VTableWidth, 0, "__vtbl_ptr_type");
+ EltTys.push_back(VTableType);
+
+ // The vptr is a pointer to this special vtable type.
+ VPtrTy = DBuilder.createPointerType(VTableType, PtrWidth);
+ }
+
+ // If there is a primary base then the artificial vptr member lives there.
if (RL.getPrimaryBase())
return;
- // If this class is not dynamic then there is not any vtable info to collect.
- if (!RD->isDynamicClass())
- return;
+ if (!VPtrTy)
+ VPtrTy = getOrCreateVTablePtrType(Unit);
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
- llvm::DIType *VPTR = DBuilder.createMemberType(
+ llvm::DIType *VPtrMember = DBuilder.createMemberType(
Unit, getVTableName(RD), Unit, 0, Size, 0, 0,
- llvm::DINode::FlagArtificial, getOrCreateVTablePtrType(Unit));
- EltTys.push_back(VPTR);
+ llvm::DINode::FlagArtificial, VPtrTy);
+ EltTys.push_back(VPtrMember);
}
llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy,
@@ -1591,23 +1714,6 @@ void CGDebugInfo::completeType(const RecordDecl *RD) {
completeRequiredType(RD);
}
-void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {
- if (DebugKind <= codegenoptions::DebugLineTablesOnly)
- return;
-
- if (const auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD))
- if (CXXDecl->isDynamicClass())
- return;
-
- if (DebugTypeExtRefs && RD->isFromASTFile())
- return;
-
- QualType Ty = CGM.getContext().getRecordType(RD);
- llvm::DIType *T = getTypeOrNull(Ty);
- if (T && T->isForwardDecl())
- completeClassData(RD);
-}
-
void CGDebugInfo::completeClassData(const RecordDecl *RD) {
if (DebugKind <= codegenoptions::DebugLineTablesOnly)
return;
@@ -1633,21 +1739,37 @@ static bool hasExplicitMemberDefinition(CXXRecordDecl::method_iterator I,
/// Does a type definition exist in an imported clang module?
static bool isDefinedInClangModule(const RecordDecl *RD) {
+ // Only definitions that where imported from an AST file come from a module.
if (!RD || !RD->isFromASTFile())
return false;
+ // Anonymous entities cannot be addressed. Treat them as not from module.
if (!RD->isExternallyVisible() && RD->getName().empty())
return false;
if (auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) {
- assert(CXXDecl->isCompleteDefinition() && "incomplete record definition");
- if (CXXDecl->getTemplateSpecializationKind() != TSK_Undeclared)
- // Make sure the instantiation is actually in a module.
- if (CXXDecl->field_begin() != CXXDecl->field_end())
- return CXXDecl->field_begin()->isFromASTFile();
+ if (!CXXDecl->isCompleteDefinition())
+ return false;
+ auto TemplateKind = CXXDecl->getTemplateSpecializationKind();
+ if (TemplateKind != TSK_Undeclared) {
+ // This is a template, check the origin of the first member.
+ if (CXXDecl->field_begin() == CXXDecl->field_end())
+ return TemplateKind == TSK_ExplicitInstantiationDeclaration;
+ if (!CXXDecl->field_begin()->isFromASTFile())
+ return false;
+ }
}
-
return true;
}
+/// Return true if the class or any of its methods are marked dllimport.
+static bool isClassOrMethodDLLImport(const CXXRecordDecl *RD) {
+ if (RD->hasAttr<DLLImportAttr>())
+ return true;
+ for (const CXXMethodDecl *MD : RD->methods())
+ if (MD->hasAttr<DLLImportAttr>())
+ return true;
+ return false;
+}
+
static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind,
bool DebugTypeExtRefs, const RecordDecl *RD,
const LangOptions &LangOpts) {
@@ -1668,7 +1790,14 @@ static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind,
if (!CXXDecl)
return false;
- if (CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())
+ // Only emit complete debug info for a dynamic class when its vtable is
+ // emitted. However, Microsoft debuggers don't resolve type information
+ // across DLL boundaries, so skip this optimization if the class or any of its
+ // methods are marked dllimport. This isn't a complete solution, since objects
+ // without any dllimport methods can be used in one DLL and constructed in
+ // another, but it is the current behavior of LimitedDebugInfo.
+ if (CXXDecl->hasDefinition() && CXXDecl->isDynamicClass() &&
+ !isClassOrMethodDLLImport(CXXDecl))
return true;
TemplateSpecializationKind Spec = TSK_Undeclared;
@@ -1683,6 +1812,16 @@ static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind,
return false;
}
+void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {
+ if (shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, CGM.getLangOpts()))
+ return;
+
+ QualType Ty = CGM.getContext().getRecordType(RD);
+ llvm::DIType *T = getTypeOrNull(Ty);
+ if (T && T->isForwardDecl())
+ completeClassData(RD);
+}
+
llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0)));
@@ -1732,7 +1871,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
const auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
if (CXXDecl) {
CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl);
- CollectVTableInfo(CXXDecl, DefUnit, EltTys);
+ CollectVTableInfo(CXXDecl, DefUnit, EltTys, FwdDecl);
}
// Collect data fields (including static variables and any initializers).
@@ -1760,6 +1899,18 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectType *Ty,
return getOrCreateType(Ty->getBaseType(), Unit);
}
+llvm::DIType *CGDebugInfo::CreateType(const ObjCTypeParamType *Ty,
+ llvm::DIFile *Unit) {
+ // Ignore protocols.
+ SourceLocation Loc = Ty->getDecl()->getLocation();
+
+ // Use Typedefs to represent ObjCTypeParamType.
+ return DBuilder.createTypedef(
+ getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit),
+ Ty->getDecl()->getName(), getOrCreateFile(Loc), getLineNumber(Loc),
+ getDeclContextDescriptor(Ty->getDecl()));
+}
+
/// \return true if Getter has the default name for the property PD.
static bool hasDefaultGetterName(const ObjCPropertyDecl *PD,
const ObjCMethodDecl *Getter) {
@@ -1860,10 +2011,11 @@ CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod,
// but LLVM detects skeleton CUs by looking for a non-zero DWO id.
uint64_t Signature = Mod.getSignature() ? Mod.getSignature() : ~1ULL;
llvm::DIBuilder DIB(CGM.getModule());
- DIB.createCompileUnit(TheCU->getSourceLanguage(), Mod.getModuleName(),
- Mod.getPath(), TheCU->getProducer(), true,
- StringRef(), 0, Mod.getASTFile(),
- llvm::DICompileUnit::FullDebug, Signature);
+ DIB.createCompileUnit(TheCU->getSourceLanguage(),
+ DIB.createFile(Mod.getModuleName(), Mod.getPath()),
+ TheCU->getProducer(), true, StringRef(), 0,
+ Mod.getASTFile(), llvm::DICompileUnit::FullDebug,
+ Signature);
DIB.finalize();
}
llvm::DIModule *Parent =
@@ -1887,9 +2039,9 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+ auto Align = getTypeAlignIfRequired(Ty, CGM.getContext());
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
if (ID->getImplementation())
Flags |= llvm::DINode::FlagObjcClassComplete;
@@ -1915,7 +2067,8 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
if (!SClassTy)
return nullptr;
- llvm::DIType *InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0, 0);
+ llvm::DIType *InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0,
+ llvm::DINode::FlagZero);
EltTys.push_back(InhTag);
}
@@ -1970,7 +2123,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
unsigned FieldLine = getLineNumber(Field->getLocation());
QualType FType = Field->getType();
uint64_t FieldSize = 0;
- unsigned FieldAlign = 0;
+ uint32_t FieldAlign = 0;
if (!FType->isIncompleteArrayType()) {
@@ -1978,7 +2131,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
FieldSize = Field->isBitField()
? Field->getBitWidthValue(CGM.getContext())
: CGM.getContext().getTypeSize(FType);
- FieldAlign = CGM.getContext().getTypeAlign(FType);
+ FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext());
}
uint64_t FieldOffset;
@@ -1997,7 +2150,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
FieldOffset = RL.getFieldOffset(FieldNo);
}
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
if (Field->getAccessControl() == ObjCIvarDecl::Protected)
Flags = llvm::DINode::FlagProtected;
else if (Field->getAccessControl() == ObjCIvarDecl::Private)
@@ -2052,33 +2205,33 @@ llvm::DIType *CGDebugInfo::CreateType(const VectorType *Ty,
llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+ auto Align = getTypeAlignIfRequired(Ty, CGM.getContext());
return DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);
}
llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) {
uint64_t Size;
- uint64_t Align;
+ uint32_t Align;
// FIXME: make getTypeAlign() aware of VLAs and incomplete array types
if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) {
Size = 0;
- Align =
- CGM.getContext().getTypeAlign(CGM.getContext().getBaseElementType(VAT));
+ Align = getTypeAlignIfRequired(CGM.getContext().getBaseElementType(VAT),
+ CGM.getContext());
} else if (Ty->isIncompleteArrayType()) {
Size = 0;
if (Ty->getElementType()->isIncompleteType())
Align = 0;
else
- Align = CGM.getContext().getTypeAlign(Ty->getElementType());
+ Align = getTypeAlignIfRequired(Ty->getElementType(), CGM.getContext());
} else if (Ty->isIncompleteType()) {
Size = 0;
Align = 0;
} else {
// Size and align of the whole array, not the element type.
Size = CGM.getContext().getTypeSize(Ty);
- Align = CGM.getContext().getTypeAlign(Ty);
+ Align = getTypeAlignIfRequired(Ty, CGM.getContext());
}
// Add the dimensions of the array. FIXME: This loses CV qualifiers from
@@ -2097,6 +2250,13 @@ llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) {
int64_t Count = -1; // Count == -1 is an unbounded array.
if (const auto *CAT = dyn_cast<ConstantArrayType>(Ty))
Count = CAT->getSize().getZExtValue();
+ else if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) {
+ if (Expr *Size = VAT->getSizeExpr()) {
+ llvm::APSInt V;
+ if (Size->EvaluateAsInt(V, CGM.getContext()))
+ Count = V.getExtValue();
+ }
+ }
// FIXME: Verify this is right for VLAs.
Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count));
@@ -2123,7 +2283,7 @@ llvm::DIType *CGDebugInfo::CreateType(const RValueReferenceType *Ty,
llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty,
llvm::DIFile *U) {
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
uint64_t Size = 0;
if (!Ty->isIncompleteType()) {
@@ -2163,9 +2323,8 @@ llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty,
}
llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) {
- // Ignore the atomic wrapping
- // FIXME: What is the correct representation?
- return getOrCreateType(Ty->getValueType(), U);
+ auto *FromTy = getOrCreateType(Ty->getValueType(), U);
+ return DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_atomic_type, FromTy);
}
llvm::DIType* CGDebugInfo::CreateType(const PipeType *Ty,
@@ -2177,10 +2336,10 @@ llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
const EnumDecl *ED = Ty->getDecl();
uint64_t Size = 0;
- uint64_t Align = 0;
+ uint32_t Align = 0;
if (!ED->getTypeForDecl()->isIncompleteType()) {
Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
- Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
+ Align = getDeclAlignIfRequired(ED, CGM.getContext());
}
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
@@ -2220,10 +2379,10 @@ llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
const EnumDecl *ED = Ty->getDecl();
uint64_t Size = 0;
- uint64_t Align = 0;
+ uint32_t Align = 0;
if (!ED->getTypeForDecl()->isIncompleteType()) {
Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
- Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
+ Align = getDeclAlignIfRequired(ED, CGM.getContext());
}
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
@@ -2292,12 +2451,18 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
case Type::SubstTemplateTypeParm:
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
break;
- case Type::Auto:
+ case Type::Auto: {
QualType DT = cast<AutoType>(T)->getDeducedType();
assert(!DT.isNull() && "Undeduced types shouldn't reach here.");
T = DT;
break;
}
+ case Type::Adjusted:
+ case Type::Decayed:
+ // Decayed and adjusted types use the adjusted type in LLVM and DWARF.
+ T = cast<AdjustedType>(T)->getAdjustedType();
+ break;
+ }
assert(T != LastT && "Type unwrapping failed to unwrap!");
(void)LastT;
@@ -2406,6 +2571,8 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
return CreateType(cast<ObjCObjectPointerType>(Ty), Unit);
case Type::ObjCObject:
return CreateType(cast<ObjCObjectType>(Ty), Unit);
+ case Type::ObjCTypeParam:
+ return CreateType(cast<ObjCTypeParamType>(Ty), Unit);
case Type::ObjCInterface:
return CreateType(cast<ObjCInterfaceType>(Ty), Unit);
case Type::Builtin:
@@ -2414,11 +2581,6 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
return CreateType(cast<ComplexType>(Ty));
case Type::Pointer:
return CreateType(cast<PointerType>(Ty), Unit);
- case Type::Adjusted:
- case Type::Decayed:
- // Decayed and adjusted types use the adjusted type in LLVM and DWARF.
- return CreateType(
- cast<PointerType>(cast<AdjustedType>(Ty)->getAdjustedType()), Unit);
case Type::BlockPointer:
return CreateType(cast<BlockPointerType>(Ty), Unit);
case Type::Typedef:
@@ -2454,6 +2616,8 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::Auto:
case Type::Attributed:
+ case Type::Adjusted:
+ case Type::Decayed:
case Type::Elaborated:
case Type::Paren:
case Type::SubstTemplateTypeParm:
@@ -2518,13 +2682,13 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
return getOrCreateRecordFwdDecl(Ty, RDContext);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+ auto Align = getDeclAlignIfRequired(D, CGM.getContext());
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
llvm::DICompositeType *RealDecl = DBuilder.createReplaceableCompositeType(
- getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align, 0,
- FullName);
+ getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align,
+ llvm::DINode::FlagZero, FullName);
// Elements of composite types usually have back to the type, creating
// uniquing cycles. Distinct nodes are more efficient.
@@ -2587,9 +2751,10 @@ llvm::DIType *CGDebugInfo::CreateMemberType(llvm::DIFile *Unit, QualType FType,
StringRef Name, uint64_t *Offset) {
llvm::DIType *FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
- unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);
- llvm::DIType *Ty = DBuilder.createMemberType(Unit, Name, Unit, 0, FieldSize,
- FieldAlign, *Offset, 0, FieldTy);
+ auto FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext());
+ llvm::DIType *Ty =
+ DBuilder.createMemberType(Unit, Name, Unit, 0, FieldSize, FieldAlign,
+ *Offset, llvm::DINode::FlagZero, FieldTy);
*Offset += FieldSize;
return Ty;
}
@@ -2599,7 +2764,7 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit,
StringRef &LinkageName,
llvm::DIScope *&FDContext,
llvm::DINodeArray &TParamsArray,
- unsigned &Flags) {
+ llvm::DINode::DIFlags &Flags) {
const auto *FD = cast<FunctionDecl>(GD.getDecl());
Name = getFunctionName(FD);
// Use mangled name as linkage name for C/C++ functions.
@@ -2624,6 +2789,9 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit,
llvm::DIScope *Mod = getParentModuleOrNull(RDecl);
FDContext = getContextDescriptor(RDecl, Mod ? Mod : TheCU);
}
+ // Check if it is a noreturn-marked function
+ if (FD->isNoReturn())
+ Flags |= llvm::DINode::FlagNoReturn;
// Collect template parameters.
TParamsArray = CollectFunctionTemplateParams(FD, Unit);
}
@@ -2680,7 +2848,7 @@ llvm::DISubprogram *
CGDebugInfo::getFunctionForwardDeclaration(const FunctionDecl *FD) {
llvm::DINodeArray TParamsArray;
StringRef Name, LinkageName;
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
SourceLocation Loc = FD->getLocation();
llvm::DIFile *Unit = getOrCreateFile(Loc);
llvm::DIScope *DContext = Unit;
@@ -2717,9 +2885,10 @@ CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) {
unsigned Line = getLineNumber(Loc);
collectVarDeclProps(VD, Unit, Line, T, Name, LinkageName, DContext);
+ auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
auto *GV = DBuilder.createTempGlobalVariableFwdDecl(
DContext, Name, LinkageName, Unit, Line, getOrCreateType(T, Unit),
- !VD->isExternallyVisible(), nullptr, nullptr);
+ !VD->isExternallyVisible(), nullptr, Align);
FwdDeclReplaceMap.emplace_back(
std::piecewise_construct,
std::make_tuple(cast<VarDecl>(VD->getCanonicalDecl())),
@@ -2737,8 +2906,12 @@ llvm::DINode *CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
getOrCreateFile(TD->getLocation()));
auto I = DeclCache.find(D->getCanonicalDecl());
- if (I != DeclCache.end())
- return dyn_cast_or_null<llvm::DINode>(I->second);
+ if (I != DeclCache.end()) {
+ auto N = I->second;
+ if (auto *GVE = dyn_cast_or_null<llvm::DIGlobalVariableExpression>(N))
+ return GVE->getVariable();
+ return dyn_cast_or_null<llvm::DINode>(N);
+ }
// No definition for now. Emit a forward definition that might be
// merged with a potential upcoming definition.
@@ -2834,7 +3007,8 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
Elts.push_back(DBuilder.createUnspecifiedParameter());
llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts);
- return DBuilder.createSubroutineType(EltTypeArray, 0, getDwarfCC(CC));
+ return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero,
+ getDwarfCC(CC));
}
// Handle variadic function types; they need an additional
@@ -2848,7 +3022,8 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
EltTys.push_back(getOrCreateType(ParamType, F));
EltTys.push_back(DBuilder.createUnspecifiedParameter());
llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys);
- return DBuilder.createSubroutineType(EltTypeArray, 0, getDwarfCC(CC));
+ return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero,
+ getDwarfCC(CC));
}
return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F));
@@ -2866,7 +3041,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
const Decl *D = GD.getDecl();
bool HasDecl = (D != nullptr);
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
llvm::DIFile *Unit = getOrCreateFile(Loc);
llvm::DIScope *FDContext = Unit;
llvm::DINodeArray TParamsArray;
@@ -2899,9 +3074,8 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
if (!HasDecl || D->isImplicit()) {
Flags |= llvm::DINode::FlagArtificial;
- // Artificial functions without a location should not silently reuse CurLoc.
- if (Loc.isInvalid())
- CurLoc = SourceLocation();
+ // Artificial functions should not silently reuse CurLoc.
+ CurLoc = SourceLocation();
}
unsigned LineNo = getLineNumber(Loc);
unsigned ScopeLine = getLineNumber(ScopeLoc);
@@ -2939,7 +3113,7 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
if (!D)
return;
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
llvm::DIFile *Unit = getOrCreateFile(Loc);
llvm::DIScope *FDContext = getDeclContextDescriptor(D);
llvm::DINodeArray TParamsArray;
@@ -3042,7 +3216,7 @@ llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
SmallVector<llvm::Metadata *, 5> EltTys;
QualType FType;
uint64_t FieldSize, FieldOffset;
- unsigned FieldAlign;
+ uint32_t FieldAlign;
llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
QualType Type = VD->getType();
@@ -3096,13 +3270,14 @@ llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
*XOffset = FieldOffset;
FieldTy = DBuilder.createMemberType(Unit, VD->getName(), Unit, 0, FieldSize,
- FieldAlign, FieldOffset, 0, FieldTy);
+ FieldAlign, FieldOffset,
+ llvm::DINode::FlagZero, FieldTy);
EltTys.push_back(FieldTy);
FieldOffset += FieldSize;
llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
- unsigned Flags = llvm::DINode::FlagBlockByrefStruct;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagBlockByrefStruct;
return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
nullptr, Elements);
@@ -3142,9 +3317,12 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
Column = getColumnNumber(VD->getLocation());
}
SmallVector<int64_t, 9> Expr;
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
if (VD->isImplicit())
Flags |= llvm::DINode::FlagArtificial;
+
+ auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
+
// If this is the first argument and it is implicit then
// give it an object pointer flag.
// FIXME: There has to be a better way to do this, but for static
@@ -3179,7 +3357,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
? DBuilder.createParameterVariable(Scope, VD->getName(),
*ArgNo, Unit, Line, Ty)
: DBuilder.createAutoVariable(Scope, VD->getName(), Unit,
- Line, Ty);
+ Line, Ty, Align);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
@@ -3209,9 +3387,10 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
continue;
// Use VarDecl's Tag, Scope and Line number.
+ auto FieldAlign = getDeclAlignIfRequired(Field, CGM.getContext());
auto *D = DBuilder.createAutoVariable(
Scope, FieldName, Unit, Line, FieldTy, CGM.getLangOpts().Optimize,
- Flags | llvm::DINode::FlagArtificial);
+ Flags | llvm::DINode::FlagArtificial, FieldAlign);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
@@ -3222,13 +3401,13 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
}
// Create the descriptor for the variable.
- auto *D =
- ArgNo
- ? DBuilder.createParameterVariable(Scope, Name, *ArgNo, Unit, Line,
- Ty, CGM.getLangOpts().Optimize,
- Flags)
- : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty,
- CGM.getLangOpts().Optimize, Flags);
+ auto *D = ArgNo
+ ? DBuilder.createParameterVariable(
+ Scope, Name, *ArgNo, Unit, Line, Ty,
+ CGM.getLangOpts().Optimize, Flags)
+ : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty,
+ CGM.getLangOpts().Optimize, Flags,
+ Align);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
@@ -3307,9 +3486,10 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
}
// Create the descriptor for the variable.
+ auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
auto *D = DBuilder.createAutoVariable(
cast<llvm::DILocalScope>(LexicalBlockStack.back()), VD->getName(), Unit,
- Line, Ty);
+ Line, Ty, false, llvm::DINode::FlagZero, Align);
// Insert an llvm.dbg.declare into the current block.
auto DL = llvm::DebugLoc::get(Line, Column, LexicalBlockStack.back());
@@ -3438,17 +3618,19 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::DIType *fieldType;
if (capture->isByRef()) {
TypeInfo PtrInfo = C.getTypeInfo(C.VoidPtrTy);
+ auto Align = PtrInfo.AlignIsRequired ? PtrInfo.Align : 0;
// FIXME: this creates a second copy of this type!
uint64_t xoffset;
fieldType = EmitTypeForVarWithBlocksAttr(variable, &xoffset);
fieldType = DBuilder.createPointerType(fieldType, PtrInfo.Width);
- fieldType =
- DBuilder.createMemberType(tunit, name, tunit, line, PtrInfo.Width,
- PtrInfo.Align, offsetInBits, 0, fieldType);
+ fieldType = DBuilder.createMemberType(tunit, name, tunit, line,
+ PtrInfo.Width, Align, offsetInBits,
+ llvm::DINode::FlagZero, fieldType);
} else {
+ auto Align = getDeclAlignIfRequired(variable, CGM.getContext());
fieldType = createFieldType(name, variable->getType(), loc, AS_public,
- offsetInBits, tunit, tunit);
+ offsetInBits, Align, tunit, tunit);
}
fields.push_back(fieldType);
}
@@ -3459,14 +3641,14 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::DINodeArray fieldsArray = DBuilder.getOrCreateArray(fields);
- llvm::DIType *type = DBuilder.createStructType(
- tunit, typeName.str(), tunit, line,
- CGM.getContext().toBits(block.BlockSize),
- CGM.getContext().toBits(block.BlockAlign), 0, nullptr, fieldsArray);
+ llvm::DIType *type =
+ DBuilder.createStructType(tunit, typeName.str(), tunit, line,
+ CGM.getContext().toBits(block.BlockSize), 0,
+ llvm::DINode::FlagZero, nullptr, fieldsArray);
type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);
// Get overall information about the block.
- unsigned flags = llvm::DINode::FlagArtificial;
+ llvm::DINode::DIFlags flags = llvm::DINode::FlagArtificial;
auto *scope = cast<llvm::DILocalScope>(LexicalBlockStack.back());
// Create the descriptor for the parameter.
@@ -3505,10 +3687,10 @@ CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
return CreateRecordStaticField(D, Ctxt, cast<RecordDecl>(DC));
}
-llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls(
+llvm::DIGlobalVariableExpression *CGDebugInfo::CollectAnonRecordDecls(
const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo,
StringRef LinkageName, llvm::GlobalVariable *Var, llvm::DIScope *DContext) {
- llvm::DIGlobalVariable *GV = nullptr;
+ llvm::DIGlobalVariableExpression *GVE = nullptr;
for (const auto *Field : RD->fields()) {
llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit);
@@ -3517,16 +3699,17 @@ llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls(
// Ignore unnamed fields, but recurse into anonymous records.
if (FieldName.empty()) {
if (const auto *RT = dyn_cast<RecordType>(Field->getType()))
- GV = CollectAnonRecordDecls(RT->getDecl(), Unit, LineNo, LinkageName,
+ GVE = CollectAnonRecordDecls(RT->getDecl(), Unit, LineNo, LinkageName,
Var, DContext);
continue;
}
// Use VarDecl's Tag, Scope and Line number.
- GV = DBuilder.createGlobalVariable(DContext, FieldName, LinkageName, Unit,
- LineNo, FieldTy,
- Var->hasLocalLinkage(), Var, nullptr);
+ GVE = DBuilder.createGlobalVariableExpression(
+ DContext, FieldName, LinkageName, Unit, LineNo, FieldTy,
+ Var->hasLocalLinkage());
+ Var->addDebugInfo(GVE);
}
- return GV;
+ return GVE;
}
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
@@ -3534,6 +3717,14 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
assert(DebugKind >= codegenoptions::LimitedDebugInfo);
if (D->hasAttr<NoDebugAttr>())
return;
+
+ // If we already created a DIGlobalVariable for this declaration, just attach
+ // it to the llvm::GlobalVariable.
+ auto Cached = DeclCache.find(D->getCanonicalDecl());
+ if (Cached != DeclCache.end())
+ return Var->addDebugInfo(
+ cast<llvm::DIGlobalVariableExpression>(Cached->second));
+
// Create global variable debug descriptor.
llvm::DIFile *Unit = nullptr;
llvm::DIScope *DContext = nullptr;
@@ -3544,7 +3735,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
// Attempt to store one global variable for the declaration - even if we
// emit a lot of fields.
- llvm::DIGlobalVariable *GV = nullptr;
+ llvm::DIGlobalVariableExpression *GVE = nullptr;
// If this is an anonymous union then we'll want to emit a global
// variable for each member of the anonymous union so that it's possible
@@ -3553,21 +3744,23 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
const RecordDecl *RD = T->castAs<RecordType>()->getDecl();
assert(RD->isAnonymousStructOrUnion() &&
"unnamed non-anonymous struct or union?");
- GV = CollectAnonRecordDecls(RD, Unit, LineNo, LinkageName, Var, DContext);
+ GVE = CollectAnonRecordDecls(RD, Unit, LineNo, LinkageName, Var, DContext);
} else {
- GV = DBuilder.createGlobalVariable(
+ auto Align = getDeclAlignIfRequired(D, CGM.getContext());
+ GVE = DBuilder.createGlobalVariableExpression(
DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
- Var->hasLocalLinkage(), Var,
- getOrCreateStaticDataMemberDeclarationOrNull(D));
+ Var->hasLocalLinkage(), /*Expr=*/nullptr,
+ getOrCreateStaticDataMemberDeclarationOrNull(D), Align);
+ Var->addDebugInfo(GVE);
}
- DeclCache[D->getCanonicalDecl()].reset(GV);
+ DeclCache[D->getCanonicalDecl()].reset(GVE);
}
-void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
- llvm::Constant *Init) {
+void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
assert(DebugKind >= codegenoptions::LimitedDebugInfo);
if (VD->hasAttr<NoDebugAttr>())
return;
+ auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
// Create the descriptor for the variable.
llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
StringRef Name = VD->getName();
@@ -3604,9 +3797,20 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
auto &GV = DeclCache[VD];
if (GV)
return;
- GV.reset(DBuilder.createGlobalVariable(
+ llvm::DIExpression *InitExpr = nullptr;
+ if (CGM.getContext().getTypeSize(VD->getType()) <= 64) {
+ // FIXME: Add a representation for integer constants wider than 64 bits.
+ if (Init.isInt())
+ InitExpr =
+ DBuilder.createConstantValueExpression(Init.getInt().getExtValue());
+ else if (Init.isFloat())
+ InitExpr = DBuilder.createConstantValueExpression(
+ Init.getFloat().bitcastToAPInt().getZExtValue());
+ }
+ GV.reset(DBuilder.createGlobalVariableExpression(
DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty,
- true, Init, getOrCreateStaticDataMemberDeclarationOrNull(VarD)));
+ true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VarD),
+ Align));
}
llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {
@@ -3620,8 +3824,8 @@ void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) {
if (CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo)
return;
const NamespaceDecl *NSDecl = UD.getNominatedNamespace();
- if (!NSDecl->isAnonymousNamespace() ||
- CGM.getCodeGenOpts().DebugExplicitImport) {
+ if (!NSDecl->isAnonymousNamespace() ||
+ CGM.getCodeGenOpts().DebugExplicitImport) {
DBuilder.createImportedModule(
getCurrentContextDescriptor(cast<Decl>(UD.getDeclContext())),
getOrCreateNameSpace(NSDecl),
@@ -3700,8 +3904,8 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
unsigned LineNo = getLineNumber(NSDecl->getLocation());
llvm::DIFile *FileD = getOrCreateFile(NSDecl->getLocation());
llvm::DIScope *Context = getDeclContextDescriptor(NSDecl);
- llvm::DINamespace *NS =
- DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
+ llvm::DINamespace *NS = DBuilder.createNameSpace(
+ Context, NSDecl->getName(), FileD, LineNo, NSDecl->isInline());
NameSpaceCache[NSDecl].reset(NS);
return NS;
}
@@ -3750,6 +3954,8 @@ void CGDebugInfo::finalize() {
else
Repl = it->second;
+ if (auto *GVE = dyn_cast_or_null<llvm::DIGlobalVariableExpression>(Repl))
+ Repl = GVE->getVariable();
DBuilder.replaceTemporary(std::move(FwdDecl), cast<llvm::MDNode>(Repl));
}
@@ -3770,3 +3976,12 @@ void CGDebugInfo::EmitExplicitCastType(QualType Ty) {
// Don't ignore in case of explicit cast where it is referenced indirectly.
DBuilder.retainType(DieTy);
}
+
+llvm::DebugLoc CGDebugInfo::SourceLocToDebugLoc(SourceLocation Loc) {
+ if (LexicalBlockStack.empty())
+ return llvm::DebugLoc();
+
+ llvm::MDNode *Scope = LexicalBlockStack.back();
+ return llvm::DebugLoc::get(
+ getLineNumber(Loc), getColumnNumber(Loc), Scope);
+}