Debug info: emit llvm::DIModule and llvm::DIImportedEntity for modules and imports

Matches GDC's DWARF output and enables access to global and imported symbols from GDB.
This commit is contained in:
Elie Morisse 2018-08-19 14:07:50 -03:00 committed by Martin Kinkelin
parent 5c24f60cf9
commit 841146644b
6 changed files with 73 additions and 1 deletions

View file

@ -11,6 +11,7 @@
#include "declaration.h" #include "declaration.h"
#include "enum.h" #include "enum.h"
#include "id.h" #include "id.h"
#include "import.h"
#include "init.h" #include "init.h"
#include "nspace.h" #include "nspace.h"
#include "rmem.h" #include "rmem.h"
@ -50,6 +51,15 @@ public:
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void visit(Import *im) override {
IF_LOG Logger::println("Import::codegen for %s", im->toPrettyChars());
LOG_SCOPE
irs->DBuilder.EmitImport(im);
}
//////////////////////////////////////////////////////////////////////////
void visit(Nspace *ns) override { void visit(Nspace *ns) override {
IF_LOG Logger::println("Nspace::codegen for %s", ns->toPrettyChars()); IF_LOG Logger::println("Nspace::codegen for %s", ns->toPrettyChars());
LOG_SCOPE LOG_SCOPE

View file

@ -18,12 +18,14 @@
#include "gen/tollvm.h" #include "gen/tollvm.h"
#include "gen/optimizer.h" #include "gen/optimizer.h"
#include "ir/irfunction.h" #include "ir/irfunction.h"
#include "ir/irmodule.h"
#include "ir/irtypeaggr.h" #include "ir/irtypeaggr.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
#include "enum.h" #include "enum.h"
#include "ldcbindings.h" #include "ldcbindings.h"
#include "import.h"
#include "module.h" #include "module.h"
#include "mtype.h" #include "mtype.h"
@ -97,6 +99,8 @@ ldc::DIBuilder::DIBuilder(IRState *const IR)
llvm::LLVMContext &ldc::DIBuilder::getContext() { return IR->context(); } llvm::LLVMContext &ldc::DIBuilder::getContext() { return IR->context(); }
ldc::DIScope ldc::DIBuilder::GetCurrentScope() { ldc::DIScope ldc::DIBuilder::GetCurrentScope() {
if (IR->funcGenStates.empty())
return getIrModule(IR->dmodule)->diModule;
IrFunction *fn = IR->func(); IrFunction *fn = IR->func();
if (fn->diLexicalBlocks.empty()) { if (fn->diLexicalBlocks.empty()) {
assert(static_cast<llvm::MDNode *>(fn->diSubprogram) != 0); assert(static_cast<llvm::MDNode *>(fn->diSubprogram) != 0);
@ -775,6 +779,45 @@ void ldc::DIBuilder::EmitCompileUnit(Module *m) {
); );
} }
ldc::DIModule ldc::DIBuilder::EmitModule(Module *m)
{
if (!mustEmitFullDebugInfo()) {
return nullptr;
}
IrModule *irm = getIrModule(m);
if (irm->diModule)
return irm->diModule;
irm->diModule = DBuilder.createModule(
CUNode,
m->toPrettyChars(true), // qualified module name
llvm::StringRef(), // (clang modules specific) ConfigurationMacros
llvm::StringRef(), // (clang modules specific) IncludePath
llvm::StringRef() // (clang modules specific) ISysRoot
);
return irm->diModule;
}
void ldc::DIBuilder::EmitImport(Import *im)
{
if (!mustEmitFullDebugInfo()) {
return;
}
auto diModule = EmitModule(im->mod);
DBuilder.createImportedModule(
GetCurrentScope(),
diModule, // imported module
#if LDC_LLVM_VER >= 500
CreateFile(im), // file
#endif
im->loc.linnum // line num
);
}
ldc::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) { ldc::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) {
if (!mustEmitLocationsDebugInfo()) { if (!mustEmitLocationsDebugInfo()) {
return nullptr; return nullptr;

View file

@ -24,6 +24,7 @@ struct IRState;
class ClassDeclaration; class ClassDeclaration;
class Dsymbol; class Dsymbol;
class FuncDeclaration; class FuncDeclaration;
class Import;
class Module; class Module;
class Type; class Type;
class VarDeclaration; class VarDeclaration;
@ -52,6 +53,7 @@ typedef llvm::DILexicalBlock *DILexicalBlock;
typedef llvm::DIScope *DIScope; typedef llvm::DIScope *DIScope;
typedef llvm::DISubroutineType *DISubroutineType; typedef llvm::DISubroutineType *DISubroutineType;
typedef llvm::DISubprogram *DISubprogram; typedef llvm::DISubprogram *DISubprogram;
typedef llvm::DIModule *DIModule;
typedef llvm::DICompileUnit *DICompileUnit; typedef llvm::DICompileUnit *DICompileUnit;
class DIBuilder { class DIBuilder {
@ -75,6 +77,14 @@ public:
/// \param m Module to emit as compile unit. /// \param m Module to emit as compile unit.
void EmitCompileUnit(Module *m); void EmitCompileUnit(Module *m);
/// \brief Emit the Dwarf module global for a Module m.
/// \param m Module to emit (either as definition or declaration).
DIModule EmitModule(Module *m);
/// \brief Emit the Dwarf imported entity and module global for an Import im.
/// \param im Import to emit.
void EmitImport(Import *im);
/// \brief Emit the Dwarf subprogram global for a function declaration fd. /// \brief Emit the Dwarf subprogram global for a function declaration fd.
/// \param fd Function declaration to emit as subprogram. /// \param fd Function declaration to emit as subprogram.
/// \returns the Dwarf subprogram global. /// \returns the Dwarf subprogram global.

View file

@ -656,6 +656,8 @@ void codegenModule(IRState *irs, Module *m) {
assert(!gIR && "gIR not null, codegen already in progress?!"); assert(!gIR && "gIR not null, codegen already in progress?!");
gIR = irs; gIR = irs;
irs->DBuilder.EmitModule(m);
initRuntime(); initRuntime();
// Skip pseudo-modules for coverage analysis // Skip pseudo-modules for coverage analysis

View file

@ -7,6 +7,7 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "import.h"
#include "init.h" #include "init.h"
#include "mars.h" #include "mars.h"
#include "module.h" #include "module.h"
@ -1590,7 +1591,10 @@ public:
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void visit(ImportStatement *stmt) override { void visit(ImportStatement *stmt) override {
// Empty. for (auto s: *stmt->imports) {
assert(s->isImport());
irs->DBuilder.EmitImport(static_cast<Import*>(s));
}
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View file

@ -22,6 +22,7 @@ class Module;
namespace llvm { namespace llvm {
class GlobalVariable; class GlobalVariable;
class Function; class Function;
class DIModule;
} }
struct IrModule { struct IrModule {
@ -44,6 +45,8 @@ struct IrModule {
FuncDeclList unitTests; FuncDeclList unitTests;
llvm::Function *coverageCtor = nullptr; llvm::Function *coverageCtor = nullptr;
llvm::DIModule *diModule = nullptr;
private: private:
llvm::GlobalVariable *moduleInfoVar = nullptr; llvm::GlobalVariable *moduleInfoVar = nullptr;
}; };