mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-06 19:06:02 +03:00
Debug info: better handling of static aggregate members with DIFlagStaticMember
Once again closer to GDC and Clang's output, and attaching static variables to the module scope prevents an assert from triggering in IR/DIBuilder.cpp: checkGlobalVariableScope(): Assertion `CT->getIdentifier().empty() && "Context of a global variable should not be a type with identifier"'
This commit is contained in:
parent
2cdae62b0e
commit
9facf5ad28
2 changed files with 77 additions and 6 deletions
|
@ -29,6 +29,9 @@
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
#include "mtype.h"
|
#include "mtype.h"
|
||||||
#include "nspace.h"
|
#include "nspace.h"
|
||||||
|
#include "template.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -108,6 +111,17 @@ ldc::DIScope ldc::DIBuilder::GetSymbolScope(Dsymbol* s) {
|
||||||
|
|
||||||
auto parent = s->toParent();
|
auto parent = s->toParent();
|
||||||
|
|
||||||
|
auto vd = s->isVarDeclaration();
|
||||||
|
if (vd && vd->isDataseg()) {
|
||||||
|
// static variables get attached to the module scope, but their
|
||||||
|
// parent composite types have to get declared
|
||||||
|
while (!parent->isModule()) {
|
||||||
|
if (parent->isAggregateDeclaration())
|
||||||
|
CreateCompositeTypeDescription(parent->getType());
|
||||||
|
parent = parent->toParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (auto tempinst = parent->isTemplateInstance()) {
|
if (auto tempinst = parent->isTemplateInstance()) {
|
||||||
return GetSymbolScope(tempinst->tempdecl);
|
return GetSymbolScope(tempinst->tempdecl);
|
||||||
} else if (auto m = parent->isModule()) {
|
} else if (auto m = parent->isModule()) {
|
||||||
|
@ -391,7 +405,8 @@ ldc::DIType ldc::DIBuilder::CreateComplexType(Type *type) {
|
||||||
ldc::DIType ldc::DIBuilder::CreateMemberType(unsigned linnum, Type *type,
|
ldc::DIType ldc::DIBuilder::CreateMemberType(unsigned linnum, Type *type,
|
||||||
ldc::DIFile file,
|
ldc::DIFile file,
|
||||||
const char *c_name,
|
const char *c_name,
|
||||||
unsigned offset, Prot::Kind prot) {
|
unsigned offset, Prot::Kind prot,
|
||||||
|
bool isStatic, DIScope scope) {
|
||||||
Type *t = type->toBasetype();
|
Type *t = type->toBasetype();
|
||||||
|
|
||||||
// translate functions to function pointers
|
// translate functions to function pointers
|
||||||
|
@ -418,7 +433,10 @@ ldc::DIType ldc::DIBuilder::CreateMemberType(unsigned linnum, Type *type,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DBuilder.createMemberType(GetCU(),
|
if (isStatic)
|
||||||
|
Flags |= DIFlags::FlagStaticMember;
|
||||||
|
|
||||||
|
return DBuilder.createMemberType(scope,
|
||||||
c_name, // name
|
c_name, // name
|
||||||
file, // file
|
file, // file
|
||||||
linnum, // line number
|
linnum, // line number
|
||||||
|
@ -441,6 +459,34 @@ void ldc::DIBuilder::AddFields(AggregateDeclaration *ad, ldc::DIFile file,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ldc::DIBuilder::AddStaticMembers(AggregateDeclaration *ad, ldc::DIFile file,
|
||||||
|
llvm::SmallVector<LLMetadata *, 16> &elems) {
|
||||||
|
auto scope = CreateCompositeTypeDescription(ad->getType());
|
||||||
|
|
||||||
|
std::function<void(Dsymbols*)> visitMembers = [&] (Dsymbols* members) {
|
||||||
|
for (auto s : *members) {
|
||||||
|
if (auto attrib = s->isAttribDeclaration()) {
|
||||||
|
if (Dsymbols *d = attrib->include(nullptr))
|
||||||
|
visitMembers(d);
|
||||||
|
} else if (auto tmixin = s->isTemplateMixin()) {
|
||||||
|
visitMembers(tmixin->members); // FIXME: static variables inside a template mixin need to be put inside a child DICompositeType for their value to become accessible (mangling issue).
|
||||||
|
// Also DWARF supports imported declarations, but LLVM currently does nothing with DIImportedEntity except at CU-level.
|
||||||
|
} else if (auto vd = s->isVarDeclaration())
|
||||||
|
if (vd->isDataseg() && !vd->aliassym /* TODO: tuples*/) {
|
||||||
|
llvm::MDNode* elem = CreateMemberType(vd->loc.linnum, vd->type, file,
|
||||||
|
vd->toChars(), 0,
|
||||||
|
vd->prot().kind,
|
||||||
|
/*isStatic = */true, scope);
|
||||||
|
elems.push_back(elem);
|
||||||
|
StaticDataMemberCache[vd].reset(elem);
|
||||||
|
|
||||||
|
}
|
||||||
|
} /*else if (auto fd = s->isFuncDeclaration())*/ // Clang also adds static functions as declarations,
|
||||||
|
// but they already work without adding them.
|
||||||
|
};
|
||||||
|
visitMembers(ad->members);
|
||||||
|
}
|
||||||
|
|
||||||
ldc::DIType ldc::DIBuilder::CreateCompositeType(Type *type) {
|
ldc::DIType ldc::DIBuilder::CreateCompositeType(Type *type) {
|
||||||
Type *t = type->toBasetype();
|
Type *t = type->toBasetype();
|
||||||
assert((t->ty == Tstruct || t->ty == Tclass) &&
|
assert((t->ty == Tstruct || t->ty == Tclass) &&
|
||||||
|
@ -522,6 +568,7 @@ ldc::DIType ldc::DIBuilder::CreateCompositeType(Type *type) {
|
||||||
}
|
}
|
||||||
AddFields(ad, file, elems);
|
AddFields(ad, file, elems);
|
||||||
}
|
}
|
||||||
|
AddStaticMembers(ad, file, elems);
|
||||||
|
|
||||||
auto elemsArray = DBuilder.getOrCreateArray(elems);
|
auto elemsArray = DBuilder.getOrCreateArray(elems);
|
||||||
|
|
||||||
|
@ -739,6 +786,12 @@ ldc::DIType ldc::DIBuilder::CreateTypeDescription(Type *type) {
|
||||||
llvm_unreachable("Unsupported type in debug info");
|
llvm_unreachable("Unsupported type in debug info");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ldc::DICompositeType ldc::DIBuilder::CreateCompositeTypeDescription(Type *type) {
|
||||||
|
DIType ret = type->toBasetype()->ty == Tclass
|
||||||
|
? CreateCompositeType(type) : CreateTypeDescription(type);
|
||||||
|
return llvm::cast<llvm::DICompositeType>(ret);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
llvm::DICompileUnit::DebugEmissionKind getDebugEmissionKind()
|
llvm::DICompileUnit::DebugEmissionKind getDebugEmissionKind()
|
||||||
|
@ -1171,6 +1224,15 @@ void ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *llVar,
|
||||||
assert(vd->isDataseg() ||
|
assert(vd->isDataseg() ||
|
||||||
(vd->storage_class & (STCconst | STCimmutable) && vd->_init));
|
(vd->storage_class & (STCconst | STCimmutable) && vd->_init));
|
||||||
|
|
||||||
|
DIScope scope = GetSymbolScope(vd);
|
||||||
|
llvm::MDNode* Decl = nullptr;
|
||||||
|
|
||||||
|
if (vd->isDataseg() && vd->toParent()->isAggregateDeclaration()) {
|
||||||
|
// static aggregate member
|
||||||
|
Decl = StaticDataMemberCache[vd];
|
||||||
|
assert(Decl && "static aggregate member not declared");
|
||||||
|
}
|
||||||
|
|
||||||
OutBuffer mangleBuf;
|
OutBuffer mangleBuf;
|
||||||
mangleToBuffer(vd, &mangleBuf);
|
mangleToBuffer(vd, &mangleBuf);
|
||||||
|
|
||||||
|
@ -1179,7 +1241,7 @@ void ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *llVar,
|
||||||
#else
|
#else
|
||||||
DBuilder.createGlobalVariable(
|
DBuilder.createGlobalVariable(
|
||||||
#endif
|
#endif
|
||||||
GetSymbolScope(vd), // context
|
scope, // context
|
||||||
vd->toChars(), // name
|
vd->toChars(), // name
|
||||||
mangleBuf.peekString(), // linkage name
|
mangleBuf.peekString(), // linkage name
|
||||||
CreateFile(vd), // file
|
CreateFile(vd), // file
|
||||||
|
@ -1187,10 +1249,11 @@ void ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *llVar,
|
||||||
CreateTypeDescription(vd->type), // type
|
CreateTypeDescription(vd->type), // type
|
||||||
vd->protection.kind == Prot::private_, // is local to unit
|
vd->protection.kind == Prot::private_, // is local to unit
|
||||||
#if LDC_LLVM_VER >= 400
|
#if LDC_LLVM_VER >= 400
|
||||||
nullptr // relative location of field
|
nullptr, // relative location of field
|
||||||
#else
|
#else
|
||||||
llVar // value
|
llVar, // value
|
||||||
#endif
|
#endif
|
||||||
|
Decl // declaration
|
||||||
);
|
);
|
||||||
|
|
||||||
#if LDC_LLVM_VER >= 400
|
#if LDC_LLVM_VER >= 400
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#ifndef LDC_GEN_DIBUILDER_H
|
#ifndef LDC_GEN_DIBUILDER_H
|
||||||
#define LDC_GEN_DIBUILDER_H
|
#define LDC_GEN_DIBUILDER_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/IR/Constants.h"
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/Type.h"
|
#include "llvm/IR/Type.h"
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/DataLayout.h"
|
||||||
|
@ -45,6 +46,7 @@ namespace ldc {
|
||||||
|
|
||||||
// Define some basic types
|
// Define some basic types
|
||||||
typedef llvm::DIType *DIType;
|
typedef llvm::DIType *DIType;
|
||||||
|
typedef llvm::DICompositeType *DICompositeType;
|
||||||
typedef llvm::DIFile *DIFile;
|
typedef llvm::DIFile *DIFile;
|
||||||
typedef llvm::DIGlobalVariable *DIGlobalVariable;
|
typedef llvm::DIGlobalVariable *DIGlobalVariable;
|
||||||
typedef llvm::DILocalVariable *DILocalVariable;
|
typedef llvm::DILocalVariable *DILocalVariable;
|
||||||
|
@ -64,6 +66,8 @@ class DIBuilder {
|
||||||
|
|
||||||
const bool isTargetMSVCx64;
|
const bool isTargetMSVCx64;
|
||||||
|
|
||||||
|
llvm::DenseMap<Declaration*, llvm::TypedTrackingMDRef<llvm::MDNode>> StaticDataMemberCache;
|
||||||
|
|
||||||
DICompileUnit GetCU() {
|
DICompileUnit GetCU() {
|
||||||
return CUNode;
|
return CUNode;
|
||||||
}
|
}
|
||||||
|
@ -163,6 +167,8 @@ private:
|
||||||
ldc::DIExpression diexpr);
|
ldc::DIExpression diexpr);
|
||||||
void AddFields(AggregateDeclaration *sd, ldc::DIFile file,
|
void AddFields(AggregateDeclaration *sd, ldc::DIFile file,
|
||||||
llvm::SmallVector<llvm::Metadata *, 16> &elems);
|
llvm::SmallVector<llvm::Metadata *, 16> &elems);
|
||||||
|
void AddStaticMembers(AggregateDeclaration *sd, ldc::DIFile file,
|
||||||
|
llvm::SmallVector<llvm::Metadata *, 16> &elems);
|
||||||
DIFile CreateFile(Loc &loc);
|
DIFile CreateFile(Loc &loc);
|
||||||
DIFile CreateFile();
|
DIFile CreateFile();
|
||||||
DIFile CreateFile(Dsymbol* decl);
|
DIFile CreateFile(Dsymbol* decl);
|
||||||
|
@ -172,7 +178,8 @@ private:
|
||||||
DIType CreateVectorType(Type *type);
|
DIType CreateVectorType(Type *type);
|
||||||
DIType CreateComplexType(Type *type);
|
DIType CreateComplexType(Type *type);
|
||||||
DIType CreateMemberType(unsigned linnum, Type *type, DIFile file,
|
DIType CreateMemberType(unsigned linnum, Type *type, DIFile file,
|
||||||
const char *c_name, unsigned offset, Prot::Kind);
|
const char *c_name, unsigned offset, Prot::Kind,
|
||||||
|
bool isStatic = false, DIScope scope = nullptr);
|
||||||
DIType CreateCompositeType(Type *type);
|
DIType CreateCompositeType(Type *type);
|
||||||
DIType CreateArrayType(Type *type);
|
DIType CreateArrayType(Type *type);
|
||||||
DIType CreateSArrayType(Type *type);
|
DIType CreateSArrayType(Type *type);
|
||||||
|
@ -181,6 +188,7 @@ private:
|
||||||
DISubroutineType CreateEmptyFunctionType();
|
DISubroutineType CreateEmptyFunctionType();
|
||||||
DIType CreateDelegateType(Type *type);
|
DIType CreateDelegateType(Type *type);
|
||||||
DIType CreateTypeDescription(Type *type);
|
DIType CreateTypeDescription(Type *type);
|
||||||
|
DICompositeType CreateCompositeTypeDescription(Type *type);
|
||||||
|
|
||||||
bool mustEmitFullDebugInfo();
|
bool mustEmitFullDebugInfo();
|
||||||
bool mustEmitLocationsDebugInfo();
|
bool mustEmitLocationsDebugInfo();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue