diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index d1fce6e209..25a2042d4a 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -29,6 +29,9 @@ #include "module.h" #include "mtype.h" #include "nspace.h" +#include "template.h" + +#include //////////////////////////////////////////////////////////////////////////////// @@ -108,6 +111,17 @@ ldc::DIScope ldc::DIBuilder::GetSymbolScope(Dsymbol* s) { 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()) { return GetSymbolScope(tempinst->tempdecl); } 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::DIFile file, const char *c_name, - unsigned offset, Prot::Kind prot) { + unsigned offset, Prot::Kind prot, + bool isStatic, DIScope scope) { Type *t = type->toBasetype(); // translate functions to function pointers @@ -418,7 +433,10 @@ ldc::DIType ldc::DIBuilder::CreateMemberType(unsigned linnum, Type *type, break; } - return DBuilder.createMemberType(GetCU(), + if (isStatic) + Flags |= DIFlags::FlagStaticMember; + + return DBuilder.createMemberType(scope, c_name, // name file, // file 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 &elems) { + auto scope = CreateCompositeTypeDescription(ad->getType()); + + std::function 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) { Type *t = type->toBasetype(); assert((t->ty == Tstruct || t->ty == Tclass) && @@ -522,6 +568,7 @@ ldc::DIType ldc::DIBuilder::CreateCompositeType(Type *type) { } AddFields(ad, file, elems); } + AddStaticMembers(ad, file, elems); auto elemsArray = DBuilder.getOrCreateArray(elems); @@ -739,6 +786,12 @@ ldc::DIType ldc::DIBuilder::CreateTypeDescription(Type *type) { 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(ret); +} + //////////////////////////////////////////////////////////////////////////////// llvm::DICompileUnit::DebugEmissionKind getDebugEmissionKind() @@ -1171,6 +1224,15 @@ void ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *llVar, assert(vd->isDataseg() || (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; mangleToBuffer(vd, &mangleBuf); @@ -1179,7 +1241,7 @@ void ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *llVar, #else DBuilder.createGlobalVariable( #endif - GetSymbolScope(vd), // context + scope, // context vd->toChars(), // name mangleBuf.peekString(), // linkage name CreateFile(vd), // file @@ -1187,10 +1249,11 @@ void ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *llVar, CreateTypeDescription(vd->type), // type vd->protection.kind == Prot::private_, // is local to unit #if LDC_LLVM_VER >= 400 - nullptr // relative location of field + nullptr, // relative location of field #else - llVar // value + llVar, // value #endif + Decl // declaration ); #if LDC_LLVM_VER >= 400 diff --git a/gen/dibuilder.h b/gen/dibuilder.h index fb8b863e14..8a54bdb3b2 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -10,6 +10,7 @@ #ifndef LDC_GEN_DIBUILDER_H #define LDC_GEN_DIBUILDER_H +#include "llvm/ADT/DenseMap.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Type.h" #include "llvm/IR/DataLayout.h" @@ -45,6 +46,7 @@ namespace ldc { // Define some basic types typedef llvm::DIType *DIType; +typedef llvm::DICompositeType *DICompositeType; typedef llvm::DIFile *DIFile; typedef llvm::DIGlobalVariable *DIGlobalVariable; typedef llvm::DILocalVariable *DILocalVariable; @@ -64,6 +66,8 @@ class DIBuilder { const bool isTargetMSVCx64; + llvm::DenseMap> StaticDataMemberCache; + DICompileUnit GetCU() { return CUNode; } @@ -163,6 +167,8 @@ private: ldc::DIExpression diexpr); void AddFields(AggregateDeclaration *sd, ldc::DIFile file, llvm::SmallVector &elems); + void AddStaticMembers(AggregateDeclaration *sd, ldc::DIFile file, + llvm::SmallVector &elems); DIFile CreateFile(Loc &loc); DIFile CreateFile(); DIFile CreateFile(Dsymbol* decl); @@ -172,7 +178,8 @@ private: DIType CreateVectorType(Type *type); DIType CreateComplexType(Type *type); 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 CreateArrayType(Type *type); DIType CreateSArrayType(Type *type); @@ -181,6 +188,7 @@ private: DISubroutineType CreateEmptyFunctionType(); DIType CreateDelegateType(Type *type); DIType CreateTypeDescription(Type *type); + DICompositeType CreateCompositeTypeDescription(Type *type); bool mustEmitFullDebugInfo(); bool mustEmitLocationsDebugInfo();