mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-05 09:31:03 +03:00
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:
parent
5c24f60cf9
commit
841146644b
6 changed files with 73 additions and 1 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue