mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-04-29 06:30:39 +03:00
Introduce a debug info builder.
Moves all code from todebug into a new class. Also caches the compilation unit in order to fix a LLVM 3.4 compile error.
This commit is contained in:
parent
4e8acf7eb6
commit
c28c7fb134
14 changed files with 521 additions and 493 deletions
|
@ -35,7 +35,6 @@
|
|||
#include "gen/dvalue.h"
|
||||
#include "gen/tollvm.h"
|
||||
#include "gen/logger.h"
|
||||
#include "gen/todebug.h"
|
||||
#include "gen/llvmhelpers.h"
|
||||
#include "gen/functions.h"
|
||||
|
||||
|
@ -230,7 +229,7 @@ AsmStatement::toIR(IRState * irs)
|
|||
assert(asmblock);
|
||||
|
||||
// debug info
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
gIR->DBuilder.EmitStopPoint(loc.linnum);
|
||||
|
||||
if (!asmcode)
|
||||
return;
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "gen/llvm.h"
|
||||
#include "gen/llvmhelpers.h"
|
||||
#include "gen/logger.h"
|
||||
#include "gen/todebug.h"
|
||||
#include "gen/tollvm.h"
|
||||
#include "ir/ir.h"
|
||||
#include "ir/irtype.h"
|
||||
|
@ -190,7 +189,7 @@ void VarDeclaration::codegen(Ir* p)
|
|||
gvar->setInitializer(initVal);
|
||||
|
||||
// Also set up the edbug info.
|
||||
DtoDwarfGlobalVariable(gvar, this);
|
||||
gIR->DBuilder.EmitGlobalVariable(gvar, this);
|
||||
}
|
||||
|
||||
// Set the alignment (it is important not to use type->alignsize because
|
||||
|
|
|
@ -1,92 +1,92 @@
|
|||
//===-- todebug.cpp -------------------------------------------------------===//
|
||||
//===-- gen/dibuilder.h - Debug information builder -------------*- C++ -*-===//
|
||||
//
|
||||
// LDC – the LLVM D compiler
|
||||
// LDC – the LLVM D compiler
|
||||
//
|
||||
// This file is distributed under the BSD-style LDC license. See the LICENSE
|
||||
// file for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gen/todebug.h"
|
||||
#include "arraytypes.h"
|
||||
#include "declaration.h"
|
||||
#include "dsymbol.h"
|
||||
#include "enum.h"
|
||||
#include "mars.h"
|
||||
#include "module.h"
|
||||
#include "mtype.h"
|
||||
#include "gen/dibuilder.h"
|
||||
#include "gen/irstate.h"
|
||||
#include "gen/linkage.h"
|
||||
#include "gen/llvm.h"
|
||||
#include "gen/llvmhelpers.h"
|
||||
#include "gen/logger.h"
|
||||
#include "gen/tollvm.h"
|
||||
#include "gen/utils.h"
|
||||
#include "ir/irmodule.h"
|
||||
#include "ir/irtypeaggr.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "enum.h"
|
||||
#include "module.h"
|
||||
#include "mtype.h"
|
||||
|
||||
using namespace llvm::dwarf;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// get the module the symbol is in, or - for template instances - the current module
|
||||
static Module* getDefinedModule(Dsymbol* s)
|
||||
Module *ldc::DIBuilder::getDefinedModule(Dsymbol *s)
|
||||
{
|
||||
// templates are defined in current module
|
||||
if (DtoIsTemplateInstance(s, true))
|
||||
{
|
||||
return gIR->dmodule;
|
||||
return IR->dmodule;
|
||||
}
|
||||
// array operations as well
|
||||
else if (FuncDeclaration* fd = s->isFuncDeclaration())
|
||||
{
|
||||
if (fd->isArrayOp == 1)
|
||||
return gIR->dmodule;
|
||||
return IR->dmodule;
|
||||
}
|
||||
// otherwise use the symbol's module
|
||||
return s->getModule();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::DIDescriptor getCurrentScope()
|
||||
ldc::DIBuilder::DIBuilder(IRState *const IR, llvm::Module &M)
|
||||
: IR(IR), DBuilder(M)
|
||||
{
|
||||
IrFunction *fn = gIR->func();
|
||||
if (fn->diLexicalBlocks.empty()) {
|
||||
assert(static_cast<llvm::MDNode*>(fn->diSubprogram) != 0);
|
||||
}
|
||||
|
||||
llvm::LLVMContext &ldc::DIBuilder::getContext()
|
||||
{
|
||||
return IR->context();
|
||||
}
|
||||
|
||||
llvm::DIDescriptor ldc::DIBuilder::GetCurrentScope()
|
||||
{
|
||||
IrFunction *fn = IR->func();
|
||||
if (fn->diLexicalBlocks.empty())
|
||||
{
|
||||
assert(static_cast<llvm::MDNode *>(fn->diSubprogram) != 0);
|
||||
return fn->diSubprogram;
|
||||
}
|
||||
return fn->diLexicalBlocks.top();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void ldc::DIBuilder::Declare(llvm::Value *var, llvm::DIVariable divar)
|
||||
{
|
||||
llvm::Instruction *instr = DBuilder.insertDeclare(var, divar, IR->scopebb());
|
||||
instr->setDebugLoc(IR->ir->getCurrentDebugLocation());
|
||||
}
|
||||
|
||||
static llvm::DIType dwarfTypeDescription_impl(Type* type, const char* c_name);
|
||||
static llvm::DIType dwarfTypeDescription(Type* type, const char* c_name);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::DIFile DtoDwarfFile(Loc loc)
|
||||
llvm::DIFile ldc::DIBuilder::CreateFile(Loc loc)
|
||||
{
|
||||
llvm::SmallString<128> path(loc.filename ? loc.filename : "");
|
||||
llvm::sys::fs::make_absolute(path);
|
||||
|
||||
return gIR->dibuilder.createFile(
|
||||
return DBuilder.createFile(
|
||||
llvm::sys::path::filename(path),
|
||||
llvm::sys::path::parent_path(path)
|
||||
);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::DIType dwarfBasicType(Type* type)
|
||||
llvm::DIType ldc::DIBuilder::CreateBasicType(Type *type)
|
||||
{
|
||||
Type* t = type->toBasetype();
|
||||
LLType* T = DtoType(type);
|
||||
using namespace llvm::dwarf;
|
||||
|
||||
Type *t = type->toBasetype();
|
||||
llvm::Type *T = DtoType(type);
|
||||
|
||||
// find encoding
|
||||
unsigned Encoding;
|
||||
|
@ -131,10 +131,10 @@ static llvm::DIType dwarfBasicType(Type* type)
|
|||
Encoding = DW_ATE_complex_float;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unsupported basic type for debug info");
|
||||
llvm_unreachable("Unsupported basic type for debug info in DIBuilder::CreateBasicType");
|
||||
}
|
||||
|
||||
return gIR->dibuilder.createBasicType(
|
||||
return DBuilder.createBasicType(
|
||||
type->toChars(), // name
|
||||
getTypeBitSize(T), // size (bits)
|
||||
getABITypeAlign(T)*8, // align (bits)
|
||||
|
@ -142,9 +142,7 @@ static llvm::DIType dwarfBasicType(Type* type)
|
|||
);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::DIType dwarfEnumType(Type *type)
|
||||
llvm::DIType ldc::DIBuilder::CreateEnumType(Type *type)
|
||||
{
|
||||
llvm::Type *T = DtoType(type);
|
||||
|
||||
|
@ -154,47 +152,44 @@ static llvm::DIType dwarfEnumType(Type *type)
|
|||
for (ArrayIter<Dsymbol> it(te->sym->members); it.more(); it.next())
|
||||
{
|
||||
EnumMember *em = it->isEnumMember();
|
||||
llvm::StringRef Name(em->toChars() /*em->ident->string*/);
|
||||
llvm::StringRef Name(em->toChars());
|
||||
uint64_t Val = em->value->toInteger();
|
||||
llvm::Value *Subscript = gIR->dibuilder.createEnumerator(Name, Val);
|
||||
llvm::Value *Subscript = DBuilder.createEnumerator(Name, Val);
|
||||
subscripts.push_back(Subscript);
|
||||
}
|
||||
|
||||
llvm::StringRef Name = te->toChars();
|
||||
unsigned LineNumber = te->sym->loc.linnum;
|
||||
llvm::DIFile File = DtoDwarfFile(te->sym->loc);
|
||||
llvm::DIFile File = CreateFile(te->sym->loc);
|
||||
|
||||
return gIR->dibuilder.createEnumerationType(
|
||||
llvm::DICompileUnit(gIR->dibuilder.getCU()),
|
||||
return DBuilder.createEnumerationType(
|
||||
llvm::DICompileUnit(GetCU()),
|
||||
Name,
|
||||
File,
|
||||
LineNumber,
|
||||
getTypeBitSize(T), // size (bits)
|
||||
getABITypeAlign(T)*8, // align (bits)
|
||||
gIR->dibuilder.getOrCreateArray(subscripts) // subscripts
|
||||
DBuilder.getOrCreateArray(subscripts) // subscripts
|
||||
#if LDC_LLVM_VER >= 302
|
||||
, dwarfTypeDescription_impl(te->sym->memtype, NULL)
|
||||
, CreateTypeDescription(te->sym->memtype, NULL)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::DIType dwarfPointerType(Type* type)
|
||||
llvm::DIType ldc::DIBuilder::CreatePointerType(Type *type)
|
||||
{
|
||||
LLType* T = DtoType(type);
|
||||
Type* t = type->toBasetype();
|
||||
llvm::Type *T = DtoType(type);
|
||||
Type *t = type->toBasetype();
|
||||
|
||||
assert(t->ty == Tpointer && "only pointers allowed for debug info in dwarfPointerType");
|
||||
assert(t->ty == Tpointer && "Only pointers allowed for debug info in DIBuilder::CreatePointerType");
|
||||
|
||||
// find base type
|
||||
llvm::DIType basetype;
|
||||
Type* nt = t->nextOf();
|
||||
basetype = dwarfTypeDescription_impl(nt, NULL);
|
||||
Type *nt = t->nextOf();
|
||||
llvm::DIType basetype = CreateTypeDescription(nt, NULL);
|
||||
if (nt->ty == Tvoid)
|
||||
basetype = llvm::DIType(NULL);
|
||||
|
||||
return gIR->dibuilder.createPointerType(
|
||||
return DBuilder.createPointerType(
|
||||
basetype,
|
||||
getTypeBitSize(T), // size (bits)
|
||||
getABITypeAlign(T)*8, // align (bits)
|
||||
|
@ -202,46 +197,44 @@ static llvm::DIType dwarfPointerType(Type* type)
|
|||
);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::DIType dwarfVectorType(Type* type)
|
||||
llvm::DIType ldc::DIBuilder::CreateVectorType(Type *type)
|
||||
{
|
||||
LLType* T = DtoType(type);
|
||||
Type* t = type->toBasetype();
|
||||
|
||||
assert(t->ty == Tvector && "only vectors allowed for debug info in dwarfVectorType");
|
||||
assert(t->ty == Tvector && "Only vectors allowed for debug info in DIBuilder::CreateVectorType");
|
||||
TypeVector *tv = static_cast<TypeVector *>(t);
|
||||
Type *te = tv->elementType();
|
||||
int64_t Dim = tv->size(Loc()) / te->size(Loc());
|
||||
llvm::Value *subscripts[] =
|
||||
{
|
||||
gIR->dibuilder.getOrCreateSubrange(0, Dim)
|
||||
DBuilder.getOrCreateSubrange(0, Dim)
|
||||
};
|
||||
llvm::DIType basetype = dwarfTypeDescription_impl(te, NULL);
|
||||
llvm::DIType basetype = CreateTypeDescription(te, NULL);
|
||||
|
||||
return gIR->dibuilder.createVectorType(
|
||||
return DBuilder.createVectorType(
|
||||
getTypeBitSize(T), // size (bits)
|
||||
getABITypeAlign(T)*8, // align (bits)
|
||||
basetype, // element type
|
||||
gIR->dibuilder.getOrCreateArray(subscripts) // subscripts
|
||||
DBuilder.getOrCreateArray(subscripts) // subscripts
|
||||
);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::DIType dwarfMemberType(unsigned linnum, Type* type, llvm::DIFile file, const char* c_name, unsigned offset)
|
||||
llvm::DIType ldc::DIBuilder::CreateMemberType(unsigned linnum, Type *type,
|
||||
llvm::DIFile file,
|
||||
const char* c_name,
|
||||
unsigned offset)
|
||||
{
|
||||
LLType* T = DtoType(type);
|
||||
Type* t = type->toBasetype();
|
||||
llvm::Type *T = DtoType(type);
|
||||
Type *t = type->toBasetype();
|
||||
|
||||
// find base type
|
||||
llvm::DIType basetype;
|
||||
basetype = dwarfTypeDescription(t, NULL);
|
||||
llvm::DIType basetype = CreateTypeDescription(t, NULL, true);
|
||||
if (t->ty == Tvoid)
|
||||
basetype = llvm::DIType(NULL);
|
||||
|
||||
return gIR->dibuilder.createMemberType(
|
||||
llvm::DICompileUnit(gIR->dibuilder.getCU()),
|
||||
return DBuilder.createMemberType(
|
||||
llvm::DICompileUnit(GetCU()),
|
||||
c_name, // name
|
||||
file, // file
|
||||
linnum, // line number
|
||||
|
@ -254,16 +247,12 @@ static llvm::DIType dwarfMemberType(unsigned linnum, Type* type, llvm::DIFile fi
|
|||
);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void add_base_fields(
|
||||
ClassDeclaration* sd,
|
||||
llvm::DIFile file,
|
||||
std::vector<llvm::Value*>& elems)
|
||||
void ldc::DIBuilder::AddBaseFields(ClassDeclaration *sd, llvm::DIFile file,
|
||||
std::vector<llvm::Value*> &elems)
|
||||
{
|
||||
if (sd->baseClass)
|
||||
{
|
||||
add_base_fields(sd->baseClass, file, elems);
|
||||
AddBaseFields(sd->baseClass, file, elems);
|
||||
}
|
||||
|
||||
ArrayIter<VarDeclaration> it(sd->fields);
|
||||
|
@ -272,16 +261,15 @@ static void add_base_fields(
|
|||
for (; !it.done(); it.next())
|
||||
{
|
||||
VarDeclaration* vd = it.get();
|
||||
elems.push_back(dwarfMemberType(vd->loc.linnum, vd->type, file, vd->toChars(), vd->offset));
|
||||
elems.push_back(CreateMemberType(vd->loc.linnum, vd->type, file, vd->toChars(), vd->offset));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static llvm::DIType dwarfCompositeType(Type* type)
|
||||
llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type)
|
||||
{
|
||||
Type* t = type->toBasetype();
|
||||
assert((t->ty == Tstruct || t->ty == Tclass) &&
|
||||
"unsupported type for dwarfCompositeType");
|
||||
"Unsupported type for debug info in DIBuilder::CreateCompositeType");
|
||||
AggregateDeclaration* sd;
|
||||
if (t->ty == Tstruct)
|
||||
{
|
||||
|
@ -296,12 +284,12 @@ static llvm::DIType dwarfCompositeType(Type* type)
|
|||
assert(sd);
|
||||
|
||||
// Use the actual type associated with the declaration, ignoring any
|
||||
// const/… wrappers.
|
||||
LLType* T = DtoType(sd->type);
|
||||
IrTypeAggr* ir = sd->type->irtype->isAggr();
|
||||
// const/… wrappers.
|
||||
LLType *T = DtoType(sd->type);
|
||||
IrTypeAggr *ir = sd->type->irtype->isAggr();
|
||||
assert(ir);
|
||||
|
||||
if (static_cast<llvm::MDNode*>(ir->diCompositeType) != 0)
|
||||
if (static_cast<llvm::MDNode *>(ir->diCompositeType) != 0)
|
||||
return ir->diCompositeType;
|
||||
|
||||
// if we don't know the aggregate's size, we don't know enough about it
|
||||
|
@ -310,22 +298,22 @@ static llvm::DIType dwarfCompositeType(Type* type)
|
|||
return llvm::DICompositeType(NULL);
|
||||
|
||||
// elements
|
||||
std::vector<llvm::Value*> elems;
|
||||
std::vector<llvm::Value *> elems;
|
||||
|
||||
// defaults
|
||||
llvm::StringRef name = sd->toChars();
|
||||
unsigned linnum = sd->loc.linnum;
|
||||
llvm::DICompileUnit CU(gIR->dibuilder.getCU());
|
||||
llvm::DICompileUnit CU(GetCU());
|
||||
assert(CU && CU.Verify() && "Compilation unit missing or corrupted");
|
||||
llvm::DIFile file = DtoDwarfFile(sd->loc);
|
||||
llvm::DIFile file = CreateFile(sd->loc);
|
||||
llvm::DIType derivedFrom;
|
||||
|
||||
// set diCompositeType to handle recursive types properly
|
||||
unsigned tag = (t->ty == Tstruct) ? llvm::dwarf::DW_TAG_structure_type
|
||||
: llvm::dwarf::DW_TAG_class_type;
|
||||
ir->diCompositeType = gIR->dibuilder.createForwardDecl(tag, name,
|
||||
ir->diCompositeType = DBuilder.createForwardDecl(tag, name,
|
||||
#if LDC_LLVM_VER >= 302
|
||||
llvm::DICompileUnit(gIR->dibuilder.getCU()),
|
||||
CU,
|
||||
#endif
|
||||
file, linnum);
|
||||
|
||||
|
@ -339,24 +327,24 @@ static llvm::DIType dwarfCompositeType(Type* type)
|
|||
for (; !it.done(); it.next())
|
||||
{
|
||||
VarDeclaration* vd = it.get();
|
||||
llvm::DIType dt = dwarfMemberType(vd->loc.linnum, vd->type, file, vd->toChars(), vd->offset);
|
||||
llvm::DIType dt = CreateMemberType(vd->loc.linnum, vd->type, file, vd->toChars(), vd->offset);
|
||||
elems.push_back(dt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ClassDeclaration *classDecl = sd->isClassDeclaration();
|
||||
add_base_fields(classDecl, file, elems);
|
||||
AddBaseFields(classDecl, file, elems);
|
||||
if (classDecl->baseClass)
|
||||
derivedFrom = dwarfCompositeType(classDecl->baseClass->getType());
|
||||
derivedFrom = CreateCompositeType(classDecl->baseClass->getType());
|
||||
}
|
||||
}
|
||||
|
||||
llvm::DIArray elemsArray = gIR->dibuilder.getOrCreateArray(elems);
|
||||
llvm::DIArray elemsArray = DBuilder.getOrCreateArray(elems);
|
||||
|
||||
llvm::DIType ret;
|
||||
if (t->ty == Tclass) {
|
||||
ret = gIR->dibuilder.createClassType(
|
||||
ret = DBuilder.createClassType(
|
||||
CU, // compile unit where defined
|
||||
name, // name
|
||||
file, // file where defined
|
||||
|
@ -369,7 +357,7 @@ static llvm::DIType dwarfCompositeType(Type* type)
|
|||
elemsArray
|
||||
);
|
||||
} else {
|
||||
ret = gIR->dibuilder.createStructType(
|
||||
ret = DBuilder.createStructType(
|
||||
CU, // compile unit where defined
|
||||
name, // name
|
||||
file, // file where defined
|
||||
|
@ -390,53 +378,25 @@ static llvm::DIType dwarfCompositeType(Type* type)
|
|||
return ret;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::DIGlobalVariable dwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd)
|
||||
llvm::DIType ldc::DIBuilder::CreateArrayType(Type *type)
|
||||
{
|
||||
assert(vd->isDataseg() || (vd->storage_class & (STCconst | STCimmutable) && vd->init));
|
||||
llvm::Type *T = DtoType(type);
|
||||
Type *t = type->toBasetype();
|
||||
|
||||
return gIR->dibuilder.createGlobalVariable(
|
||||
vd->toChars(), // name
|
||||
#if LDC_LLVM_VER >= 303
|
||||
vd->mangle(), // linkage name
|
||||
#endif
|
||||
DtoDwarfFile(vd->loc), // file
|
||||
vd->loc.linnum, // line num
|
||||
dwarfTypeDescription_impl(vd->type, NULL), // type
|
||||
vd->protection == PROTprivate, // is local to unit
|
||||
ll // value
|
||||
);
|
||||
}
|
||||
assert(t->ty == Tarray && "Only arrays allowed for debug info in DIBuilder::CreateArrayType");
|
||||
|
||||
llvm::DIFile file = CreateFile(Loc(IR->dmodule, 0));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void dwarfDeclare(LLValue* var, llvm::DIVariable divar)
|
||||
{
|
||||
llvm::Instruction *instr = gIR->dibuilder.insertDeclare(var, divar, gIR->scopebb());
|
||||
instr->setDebugLoc(gIR->ir->getCurrentDebugLocation());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static llvm::DIType dwarfArrayType(Type* type) {
|
||||
LLType* T = DtoType(type);
|
||||
Type* t = type->toBasetype();
|
||||
|
||||
llvm::DIFile file = DtoDwarfFile(Loc(gIR->dmodule, 0));
|
||||
|
||||
llvm::Value* elems[] = {
|
||||
dwarfMemberType(0, Type::tsize_t, file, "length", 0),
|
||||
dwarfMemberType(0, t->nextOf()->pointerTo(), file, "ptr",
|
||||
global.params.is64bit ? 8 : 4)
|
||||
llvm::Value *elems[] = {
|
||||
CreateMemberType(0, Type::tsize_t, file, "length", 0),
|
||||
CreateMemberType(0, t->nextOf()->pointerTo(), file, "ptr",
|
||||
global.params.is64bit ? 8 : 4)
|
||||
};
|
||||
|
||||
return gIR->dibuilder.createStructType
|
||||
return DBuilder.createStructType
|
||||
(
|
||||
llvm::DICompileUnit(gIR->dibuilder.getCU()),
|
||||
llvm::StringRef(), // Name TODO: Really no name for arrays?
|
||||
llvm::DICompileUnit(GetCU()),
|
||||
llvm::StringRef(), // Name TODO: Really no name for arrays? t->toChars()?
|
||||
file, // File
|
||||
0, // LineNo
|
||||
getTypeBitSize(T), // size in bits
|
||||
|
@ -445,14 +405,11 @@ static llvm::DIType dwarfArrayType(Type* type) {
|
|||
#if LDC_LLVM_VER >= 303
|
||||
llvm::DIType(), // DerivedFrom
|
||||
#endif
|
||||
gIR->dibuilder.getOrCreateArray(elems)
|
||||
DBuilder.getOrCreateArray(elems)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::DIType dwarfSArrayType(Type *type)
|
||||
llvm::DIType ldc::DIBuilder::CreateSArrayType(Type *type)
|
||||
{
|
||||
llvm::Type *T = DtoType(type);
|
||||
Type *t = type->toBasetype();
|
||||
|
@ -463,113 +420,56 @@ static llvm::DIType dwarfSArrayType(Type *type)
|
|||
{
|
||||
TypeSArray *tsa = static_cast<TypeSArray *>(t);
|
||||
int64_t Count = tsa->dim->toInteger();
|
||||
llvm::Value *subscript = gIR->dibuilder.getOrCreateSubrange(0, Count-1);
|
||||
llvm::Value *subscript = DBuilder.getOrCreateSubrange(0, Count-1);
|
||||
subscripts.push_back(subscript);
|
||||
t = t->nextOf();
|
||||
}
|
||||
llvm::DIType basetype = dwarfTypeDescription_impl(t, NULL);
|
||||
llvm::DIType basetype = CreateTypeDescription(t, NULL);
|
||||
|
||||
return gIR->dibuilder.createArrayType(
|
||||
return DBuilder.createArrayType(
|
||||
getTypeBitSize(T), // size (bits)
|
||||
getABITypeAlign(T)*8, // align (bits)
|
||||
basetype, // element type
|
||||
gIR->dibuilder.getOrCreateArray(subscripts) // subscripts
|
||||
DBuilder.getOrCreateArray(subscripts) // subscripts
|
||||
);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::DIType dwarfTypeDescription_impl(Type* type, const char* c_name)
|
||||
llvm::DIType ldc::DIBuilder::CreateTypeDescription(Type* type,
|
||||
const char* c_name,
|
||||
bool derefclass)
|
||||
{
|
||||
Type* t = type->toBasetype();
|
||||
Type *t = type->toBasetype();
|
||||
if (derefclass && t->ty == Tclass)
|
||||
{
|
||||
type = type->pointerTo();
|
||||
t = type->toBasetype();
|
||||
}
|
||||
|
||||
if (t->ty == Tvoid)
|
||||
return llvm::DIType(NULL);
|
||||
else if (t->isintegral() || t->isfloating())
|
||||
{
|
||||
if (t->ty == Tvector)
|
||||
return dwarfVectorType(type);
|
||||
return CreateVectorType(type);
|
||||
if (type->ty == Tenum)
|
||||
return dwarfEnumType(type);
|
||||
return dwarfBasicType(type);
|
||||
return CreateEnumType(type);
|
||||
return CreateBasicType(type);
|
||||
}
|
||||
else if (t->ty == Tpointer)
|
||||
return dwarfPointerType(type);
|
||||
return CreatePointerType(type);
|
||||
else if (t->ty == Tarray)
|
||||
return dwarfArrayType(type);
|
||||
return CreateArrayType(type);
|
||||
else if (t->ty == Tsarray)
|
||||
return dwarfSArrayType(type);
|
||||
return CreateSArrayType(type);
|
||||
else if (t->ty == Tstruct || t->ty == Tclass)
|
||||
return dwarfCompositeType(type);
|
||||
return CreateCompositeType(type);
|
||||
|
||||
return llvm::DIType(NULL);
|
||||
}
|
||||
|
||||
static llvm::DIType dwarfTypeDescription(Type* type, const char* c_name)
|
||||
{
|
||||
Type* t = type->toBasetype();
|
||||
if (t->ty == Tclass)
|
||||
return dwarfTypeDescription_impl(type->pointerTo(), c_name);
|
||||
else
|
||||
return dwarfTypeDescription_impl(type, c_name);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd, llvm::ArrayRef<LLValue*> addr)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
||||
Logger::println("D to dwarf local variable");
|
||||
LOG_SCOPE;
|
||||
|
||||
if (gIR->func()->diSubprogram == vd->debugFunc) // ensure that the debug variable is created only once
|
||||
return;
|
||||
|
||||
// get type description
|
||||
llvm::DIType TD = dwarfTypeDescription(vd->type, NULL);
|
||||
if (static_cast<llvm::MDNode*>(TD) == 0)
|
||||
return; // unsupported
|
||||
|
||||
// get variable description
|
||||
assert(!vd->isDataseg() && "static variable");
|
||||
|
||||
unsigned tag;
|
||||
if (vd->isParameter())
|
||||
tag = DW_TAG_arg_variable;
|
||||
else
|
||||
tag = DW_TAG_auto_variable;
|
||||
|
||||
if (addr.empty()) {
|
||||
vd->debugVariable = gIR->dibuilder.createLocalVariable(
|
||||
tag, // tag
|
||||
getCurrentScope(), // scope
|
||||
vd->toChars(), // name
|
||||
DtoDwarfFile(vd->loc), // file
|
||||
vd->loc.linnum, // line num
|
||||
TD, // type
|
||||
true // preserve
|
||||
);
|
||||
} else {
|
||||
vd->debugVariable = gIR->dibuilder.createComplexVariable(
|
||||
tag, // tag
|
||||
getCurrentScope(), // scope
|
||||
vd->toChars(), // name
|
||||
DtoDwarfFile(vd->loc), // file
|
||||
vd->loc.linnum, // line num
|
||||
TD, // type
|
||||
addr
|
||||
);
|
||||
}
|
||||
vd->debugFunc = gIR->func()->diSubprogram;
|
||||
|
||||
// declare
|
||||
dwarfDeclare(ll, vd->debugVariable);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDwarfCompileUnit(Module* m)
|
||||
void ldc::DIBuilder::EmitCompileUnit(Module *m)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
@ -581,8 +481,12 @@ void DtoDwarfCompileUnit(Module* m)
|
|||
llvm::SmallString<128> srcpath(m->srcfile->name->toChars());
|
||||
llvm::sys::fs::make_absolute(srcpath);
|
||||
|
||||
gIR->dibuilder.createCompileUnit(
|
||||
global.params.symdebug == 2 ? DW_LANG_C : DW_LANG_D,
|
||||
#if LDC_LLVM_VER >= 304
|
||||
CUNode =
|
||||
#endif
|
||||
DBuilder.createCompileUnit(
|
||||
global.params.symdebug == 2 ? llvm::dwarf::DW_LANG_C
|
||||
: llvm::dwarf::DW_LANG_D,
|
||||
llvm::sys::path::filename(srcpath),
|
||||
llvm::sys::path::parent_path(srcpath),
|
||||
"LDC (http://wiki.dlang.org/LDC)",
|
||||
|
@ -590,11 +494,12 @@ void DtoDwarfCompileUnit(Module* m)
|
|||
llvm::StringRef(), // Flags TODO
|
||||
1 // Runtime Version TODO
|
||||
);
|
||||
#if LDC_LLVM_VER < 304
|
||||
CUNode = DBuilder.getCU();
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd)
|
||||
llvm::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return llvm::DISubprogram();
|
||||
|
@ -602,25 +507,25 @@ llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd)
|
|||
Logger::println("D to dwarf subprogram");
|
||||
LOG_SCOPE;
|
||||
|
||||
llvm::DICompileUnit CU(gIR->dibuilder.getCU());
|
||||
assert(CU && CU.Verify() && "Compilation unit missing or corrupted");
|
||||
llvm::DICompileUnit CU(GetCU());
|
||||
assert(CU && CU.Verify() && "Compilation unit missing or corrupted in DIBuilder::EmitSubProgram");
|
||||
|
||||
llvm::DIFile file = DtoDwarfFile(fd->loc);
|
||||
llvm::DIFile file = CreateFile(fd->loc);
|
||||
Type *retType = static_cast<TypeFunction*>(fd->type)->next;
|
||||
|
||||
// Create "dummy" subroutine type for the return type
|
||||
llvm::SmallVector<llvm::Value*, 16> Elts;
|
||||
Elts.push_back(dwarfTypeDescription(retType, NULL));
|
||||
llvm::DIArray EltTypeArray = gIR->dibuilder.getOrCreateArray(Elts);
|
||||
Elts.push_back(CreateTypeDescription(retType, NULL, true));
|
||||
llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
|
||||
#if LDC_LLVM_VER >= 304
|
||||
llvm::DICompositeType
|
||||
#else
|
||||
llvm::DIType
|
||||
llvm::DIType
|
||||
#endif
|
||||
DIFnType = gIR->dibuilder.createSubroutineType(file, EltTypeArray);
|
||||
DIFnType = DBuilder.createSubroutineType(file, EltTypeArray);
|
||||
|
||||
// FIXME: duplicates ?
|
||||
return gIR->dibuilder.createFunction(
|
||||
return DBuilder.createFunction(
|
||||
CU, // context
|
||||
fd->toPrettyChars(), // name
|
||||
fd->mangle(), // linkage name
|
||||
|
@ -628,7 +533,7 @@ llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd)
|
|||
fd->loc.linnum, // line no
|
||||
DIFnType, // type
|
||||
fd->protection == PROTprivate, // is local to unit
|
||||
gIR->dmodule == getDefinedModule(fd), // isdefinition
|
||||
IR->dmodule == getDefinedModule(fd), // isdefinition
|
||||
fd->loc.linnum, // FIXME: scope line
|
||||
0, // Flags
|
||||
false, // isOptimized
|
||||
|
@ -636,9 +541,8 @@ llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd)
|
|||
);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char* mangledname)
|
||||
llvm::DISubprogram ldc::DIBuilder::EmitSubProgramInternal(llvm::StringRef prettyname,
|
||||
llvm::StringRef mangledname)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return llvm::DISubprogram();
|
||||
|
@ -646,21 +550,21 @@ llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char
|
|||
Logger::println("D to dwarf subprogram");
|
||||
LOG_SCOPE;
|
||||
|
||||
llvm::DIFile file(DtoDwarfFile(Loc(gIR->dmodule, 0)));
|
||||
llvm::DIFile file(CreateFile(Loc(IR->dmodule, 0)));
|
||||
|
||||
// Create "dummy" subroutine type for the return type
|
||||
llvm::SmallVector<llvm::Value*, 1> Elts;
|
||||
llvm::SmallVector<llvm::Value *, 1> Elts;
|
||||
Elts.push_back(llvm::DIType(NULL));
|
||||
llvm::DIArray EltTypeArray = gIR->dibuilder.getOrCreateArray(Elts);
|
||||
llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
|
||||
#if LDC_LLVM_VER >= 304
|
||||
llvm::DICompositeType
|
||||
llvm::DICompositeType
|
||||
#else
|
||||
llvm::DIType
|
||||
#endif
|
||||
DIFnType = gIR->dibuilder.createSubroutineType(file, EltTypeArray);
|
||||
DIFnType = DBuilder.createSubroutineType(file, EltTypeArray);
|
||||
|
||||
// FIXME: duplicates ?
|
||||
return gIR->dibuilder.createFunction(
|
||||
return DBuilder.createFunction(
|
||||
llvm::DIDescriptor(file), // context
|
||||
prettyname, // name
|
||||
mangledname, // linkage name
|
||||
|
@ -673,23 +577,7 @@ llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char
|
|||
);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return llvm::DIGlobalVariable();
|
||||
|
||||
Logger::println("D to dwarf global_variable");
|
||||
LOG_SCOPE;
|
||||
|
||||
// FIXME: duplicates ?
|
||||
return dwarfGlobalVariable(ll, vd);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDwarfFuncStart(FuncDeclaration* fd)
|
||||
void ldc::DIBuilder::EmitFuncStart(FuncDeclaration *fd)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
@ -697,13 +585,11 @@ void DtoDwarfFuncStart(FuncDeclaration* fd)
|
|||
Logger::println("D to dwarf funcstart");
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(static_cast<llvm::MDNode*>(fd->ir.irFunc->diSubprogram) != 0);
|
||||
DtoDwarfStopPoint(fd->loc.linnum);
|
||||
assert(static_cast<llvm::MDNode *>(fd->ir.irFunc->diSubprogram) != 0);
|
||||
EmitStopPoint(fd->loc.linnum);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDwarfFuncEnd(FuncDeclaration* fd)
|
||||
void ldc::DIBuilder::EmitFuncEnd(FuncDeclaration *fd)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
@ -711,12 +597,10 @@ void DtoDwarfFuncEnd(FuncDeclaration* fd)
|
|||
Logger::println("D to dwarf funcend");
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(static_cast<llvm::MDNode*>(fd->ir.irFunc->diSubprogram) != 0);
|
||||
assert(static_cast<llvm::MDNode *>(fd->ir.irFunc->diSubprogram) != 0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDwarfBlockStart(Loc loc)
|
||||
void ldc::DIBuilder::EmitBlockStart(Loc loc)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
@ -724,19 +608,17 @@ void DtoDwarfBlockStart(Loc loc)
|
|||
Logger::println("D to dwarf block start");
|
||||
LOG_SCOPE;
|
||||
|
||||
llvm::DILexicalBlock block = gIR->dibuilder.createLexicalBlock(
|
||||
getCurrentScope(), // scope
|
||||
DtoDwarfFile(loc), // file
|
||||
llvm::DILexicalBlock block = DBuilder.createLexicalBlock(
|
||||
GetCurrentScope(), // scope
|
||||
CreateFile(loc), // file
|
||||
loc.linnum, // line
|
||||
0 // column
|
||||
);
|
||||
gIR->func()->diLexicalBlocks.push(block);
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
IR->func()->diLexicalBlocks.push(block);
|
||||
EmitStopPoint(loc.linnum);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDwarfBlockEnd()
|
||||
void ldc::DIBuilder::EmitBlockEnd()
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
@ -744,41 +626,111 @@ void DtoDwarfBlockEnd()
|
|||
Logger::println("D to dwarf block end");
|
||||
LOG_SCOPE;
|
||||
|
||||
IrFunction *fn = gIR->func();
|
||||
IrFunction *fn = IR->func();
|
||||
assert(!fn->diLexicalBlocks.empty());
|
||||
fn->diLexicalBlocks.pop();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDwarfStopPoint(unsigned ln)
|
||||
void ldc::DIBuilder::EmitStopPoint(unsigned ln)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
||||
Logger::println("D to dwarf stoppoint at line %u", ln);
|
||||
LOG_SCOPE;
|
||||
llvm::DebugLoc loc = llvm::DebugLoc::get(ln, 0, getCurrentScope());
|
||||
gIR->ir->SetCurrentDebugLocation(loc);
|
||||
llvm::DebugLoc loc = llvm::DebugLoc::get(ln, 0, GetCurrentScope());
|
||||
IR->ir->SetCurrentDebugLocation(loc);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDwarfValue(LLValue *val, VarDeclaration* vd)
|
||||
void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd)
|
||||
{
|
||||
if (!global.params.symdebug || !vd->debugVariable)
|
||||
return;
|
||||
|
||||
llvm::Instruction *instr = gIR->dibuilder.insertDbgValueIntrinsic(val, 0, vd->debugVariable, gIR->scopebb());
|
||||
instr->setDebugLoc(gIR->ir->getCurrentDebugLocation());
|
||||
llvm::Instruction *instr = DBuilder.insertDbgValueIntrinsic(val, 0, vd->debugVariable, IR->scopebb());
|
||||
instr->setDebugLoc(IR->ir->getCurrentDebugLocation());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDwarfModuleEnd()
|
||||
void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
||||
llvm::ArrayRef<llvm::Value *> addr)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
||||
gIR->dibuilder.finalize();
|
||||
Logger::println("D to dwarf local variable");
|
||||
LOG_SCOPE;
|
||||
|
||||
if (IR->func()->diSubprogram == vd->debugFunc) // ensure that the debug variable is created only once
|
||||
return;
|
||||
|
||||
// get type description
|
||||
llvm::DIType TD = CreateTypeDescription(vd->type, NULL, true);
|
||||
if (static_cast<llvm::MDNode *>(TD) == 0)
|
||||
return; // unsupported
|
||||
|
||||
// get variable description
|
||||
assert(!vd->isDataseg() && "static variable");
|
||||
|
||||
unsigned tag;
|
||||
if (vd->isParameter())
|
||||
tag = llvm::dwarf::DW_TAG_arg_variable;
|
||||
else
|
||||
tag = llvm::dwarf::DW_TAG_auto_variable;
|
||||
|
||||
if (addr.empty()) {
|
||||
vd->debugVariable = DBuilder.createLocalVariable(
|
||||
tag, // tag
|
||||
GetCurrentScope(), // scope
|
||||
vd->toChars(), // name
|
||||
CreateFile(vd->loc), // file
|
||||
vd->loc.linnum, // line num
|
||||
TD, // type
|
||||
true // preserve
|
||||
);
|
||||
} else {
|
||||
vd->debugVariable = DBuilder.createComplexVariable(
|
||||
tag, // tag
|
||||
GetCurrentScope(), // scope
|
||||
vd->toChars(), // name
|
||||
CreateFile(vd->loc), // file
|
||||
vd->loc.linnum, // line num
|
||||
TD, // type
|
||||
addr
|
||||
);
|
||||
}
|
||||
vd->debugFunc = IR->func()->diSubprogram;
|
||||
|
||||
// declare
|
||||
Declare(ll, vd->debugVariable);
|
||||
}
|
||||
|
||||
llvm::DIGlobalVariable ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *ll, VarDeclaration *vd)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return llvm::DIGlobalVariable();
|
||||
|
||||
Logger::println("D to dwarf global_variable");
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(vd->isDataseg() || (vd->storage_class & (STCconst | STCimmutable) && vd->init));
|
||||
|
||||
return DBuilder.createGlobalVariable(
|
||||
vd->toChars(), // name
|
||||
#if LDC_LLVM_VER >= 303
|
||||
vd->mangle(), // linkage name
|
||||
#endif
|
||||
CreateFile(vd->loc), // file
|
||||
vd->loc.linnum, // line num
|
||||
CreateTypeDescription(vd->type, NULL), // type
|
||||
vd->protection == PROTprivate, // is local to unit
|
||||
ll // value
|
||||
);
|
||||
}
|
||||
|
||||
void ldc::DIBuilder::EmitModuleEnd()
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
||||
DBuilder.finalize();
|
||||
}
|
184
gen/dibuilder.h
Normal file
184
gen/dibuilder.h
Normal file
|
@ -0,0 +1,184 @@
|
|||
//===-- gen/dibuilder.h - Debug information builder -------------*- C++ -*-===//
|
||||
//
|
||||
// LDC – the LLVM D compiler
|
||||
//
|
||||
// This file is distributed under the BSD-style LDC license. See the LICENSE
|
||||
// file for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LDC_GEN_DIBUILDER_H
|
||||
#define LDC_GEN_DIBUILDER_H
|
||||
|
||||
#if LDC_LLVM_VER >= 303
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/DebugInfo.h"
|
||||
#include "llvm/DIBuilder.h"
|
||||
#else
|
||||
#if LDC_LLVM_VER == 302
|
||||
#include "llvm/DataLayout.h"
|
||||
#include "llvm/DebugInfo.h"
|
||||
#include "llvm/DIBuilder.h"
|
||||
#else
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/Type.h"
|
||||
#include "llvm/Analysis/DebugInfo.h"
|
||||
#include "llvm/Analysis/DIBuilder.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "gen/tollvm.h"
|
||||
#include "mars.h"
|
||||
|
||||
struct IRState;
|
||||
|
||||
struct ClassDeclaration;
|
||||
struct Dsymbol;
|
||||
struct FuncDeclaration;
|
||||
struct Module;
|
||||
struct Type;
|
||||
struct VarDeclaration;
|
||||
|
||||
namespace llvm {
|
||||
class GlobalVariable;
|
||||
class StructType;
|
||||
class LLVMContext;
|
||||
|
||||
// Only for the OpXXX templates, see below.
|
||||
#if LDC_LLVM_VER >= 302
|
||||
class DataLayout;
|
||||
#else
|
||||
class TargetData;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Only for the OpXXX templates, see below.
|
||||
#if LDC_LLVM_VER >= 302
|
||||
extern const llvm::DataLayout* gDataLayout;
|
||||
#else
|
||||
extern const llvm::TargetData* gDataLayout;
|
||||
#endif
|
||||
|
||||
namespace ldc {
|
||||
|
||||
class DIBuilder
|
||||
{
|
||||
IRState *const IR;
|
||||
const llvm::MDNode *CUNode;
|
||||
llvm::DIBuilder DBuilder;
|
||||
|
||||
const llvm::MDNode *GetCU()
|
||||
{
|
||||
return CUNode;
|
||||
}
|
||||
|
||||
public:
|
||||
DIBuilder(IRState *const IR, llvm::Module &M);
|
||||
|
||||
/// \brief Emit the Dwarf compile_unit global for a Module m.
|
||||
/// \param m Module to emit as compile unit.
|
||||
void EmitCompileUnit(Module *m);
|
||||
|
||||
/// \brief Emit the Dwarf subprogram global for a function declaration fd.
|
||||
/// \param fd Function declaration to emit as subprogram.
|
||||
/// \returns the Dwarf subprogram global.
|
||||
llvm::DISubprogram EmitSubProgram(FuncDeclaration *fd); // FIXME
|
||||
|
||||
/// \brief Emit the Dwarf subprogram global for a internal function.
|
||||
/// This is used for generated functions like moduleinfoctors,
|
||||
/// module ctors/dtors and unittests.
|
||||
/// \param prettyname The name as seen in the source.
|
||||
/// \param mangledname The mangled name in the object file.
|
||||
/// \returns the Dwarf subprogram global.
|
||||
llvm::DISubprogram EmitSubProgramInternal(llvm::StringRef prettyname, llvm::StringRef mangledname); // FIXME
|
||||
|
||||
/// \brief Emits debug info for function start
|
||||
void EmitFuncStart(FuncDeclaration *fd);
|
||||
|
||||
/// \brief Emits debug info for function end
|
||||
void EmitFuncEnd(FuncDeclaration *fd);
|
||||
|
||||
/// \brief Emits debug info for block start
|
||||
void EmitBlockStart(Loc loc);
|
||||
|
||||
/// \brief Emits debug info for block end
|
||||
void EmitBlockEnd();
|
||||
|
||||
void EmitStopPoint(unsigned ln);
|
||||
|
||||
void EmitValue(llvm::Value *val, VarDeclaration* vd);
|
||||
|
||||
/// \brief Emits all things necessary for making debug info for a local variable vd.
|
||||
/// \param ll LLVM Value of the variable.
|
||||
/// \param vd Variable declaration to emit debug info for.
|
||||
/// \param addr An array of complex address operations.
|
||||
void EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
||||
llvm::ArrayRef<llvm::Value *> addr = llvm::ArrayRef<llvm::Value *>());
|
||||
|
||||
/// \brief Emits all things necessary for making debug info for a global variable vd.
|
||||
/// \param ll LLVM global variable
|
||||
/// \param vd Variable declaration to emit debug info for.
|
||||
llvm::DIGlobalVariable EmitGlobalVariable(llvm::GlobalVariable *ll, VarDeclaration *vd); // FIXME
|
||||
|
||||
void EmitModuleEnd();
|
||||
|
||||
private:
|
||||
llvm::LLVMContext &getContext();
|
||||
Module *getDefinedModule(Dsymbol *s);
|
||||
llvm::DIDescriptor GetCurrentScope();
|
||||
void Declare(llvm::Value *var, llvm::DIVariable divar);
|
||||
void AddBaseFields(ClassDeclaration *sd, llvm::DIFile file,
|
||||
std::vector<llvm::Value*> &elems);
|
||||
llvm::DIFile CreateFile(Loc loc);
|
||||
llvm::DIType CreateBasicType(Type *type);
|
||||
llvm::DIType CreateEnumType(Type *type);
|
||||
llvm::DIType CreatePointerType(Type *type);
|
||||
llvm::DIType CreateVectorType(Type *type);
|
||||
llvm::DIType CreateMemberType(unsigned linnum, Type *type, llvm::DIFile file, const char* c_name, unsigned offset);
|
||||
llvm::DIType CreateCompositeType(Type *type);
|
||||
llvm::DIType CreateArrayType(Type *type);
|
||||
llvm::DIType CreateSArrayType(Type *type);
|
||||
llvm::DIType CreateTypeDescription(Type* type, const char* c_name, bool derefclass = false);
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
void OpOffset(T &addr, llvm::StructType *type, int index)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
||||
uint64_t offset = gDataLayout->getStructLayout(type)->getElementOffset(index);
|
||||
llvm::Type *int64Ty = llvm::Type::getInt64Ty(getContext());
|
||||
addr.push_back(llvm::ConstantInt::get(int64Ty, llvm::DIBuilder::OpPlus));
|
||||
addr.push_back(llvm::ConstantInt::get(int64Ty, offset));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void OpOffset(T &addr, llvm::Value *val, int index)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
||||
llvm::StructType *type = isaStruct(val->getType()->getContainedType(0));
|
||||
assert(type);
|
||||
OpOffset(addr, type, index);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void OpDeref(T &addr)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
||||
llvm::Type *int64Ty = llvm::Type::getInt64Ty(getContext());
|
||||
addr.push_back(llvm::ConstantInt::get(int64Ty, llvm::DIBuilder::OpDeref));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace ldc
|
||||
|
||||
#endif
|
|
@ -27,7 +27,6 @@
|
|||
#include "gen/nested.h"
|
||||
#include "gen/pragma.h"
|
||||
#include "gen/runtime.h"
|
||||
#include "gen/todebug.h"
|
||||
#include "gen/tollvm.h"
|
||||
#if LDC_LLVM_VER >= 303
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
|
@ -942,7 +941,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
|||
}
|
||||
|
||||
// debug info
|
||||
fd->ir.irFunc->diSubprogram = DtoDwarfSubProgram(fd);
|
||||
fd->ir.irFunc->diSubprogram = gIR->DBuilder.EmitSubProgram(fd);
|
||||
|
||||
Type* t = fd->type->toBasetype();
|
||||
TypeFunction* f = static_cast<TypeFunction*>(t);
|
||||
|
@ -995,7 +994,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
|||
irfunction->allocapoint = allocaPoint;
|
||||
|
||||
// debug info - after all allocas, but before any llvm.dbg.declare etc
|
||||
DtoDwarfFuncStart(fd);
|
||||
gIR->DBuilder.EmitFuncStart(fd);
|
||||
|
||||
// this hack makes sure the frame pointer elimination optimization is disabled.
|
||||
// this this eliminates a bunch of inline asm related issues.
|
||||
|
@ -1023,7 +1022,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
|||
assert(fd->vthis->ir.irParam->value == thisvar);
|
||||
fd->vthis->ir.irParam->value = thismem;
|
||||
|
||||
DtoDwarfLocalVariable(thismem, fd->vthis);
|
||||
gIR->DBuilder.EmitLocalVariable(thismem, fd->vthis);
|
||||
}
|
||||
|
||||
// give the 'nestArg' storage
|
||||
|
@ -1071,7 +1070,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
|||
}
|
||||
|
||||
if (global.params.symdebug && !(isaArgument(irparam->value) && isaArgument(irparam->value)->hasByValAttr()) && !refout)
|
||||
DtoDwarfLocalVariable(irparam->value, vd);
|
||||
gIR->DBuilder.EmitLocalVariable(irparam->value, vd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1120,7 +1119,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
|||
// in automatically, so we do it here.
|
||||
|
||||
// pass the previous block into this block
|
||||
DtoDwarfFuncEnd(fd);
|
||||
gIR->DBuilder.EmitFuncEnd(fd);
|
||||
if (func->getReturnType() == LLType::getVoidTy(gIR->context())) {
|
||||
llvm::ReturnInst::Create(gIR->context(), gIR->scopebb());
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ IRTargetScope::IRTargetScope(
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
IRState::IRState(llvm::Module* m)
|
||||
: module(m), dibuilder(*m)
|
||||
: module(m), DBuilder(this, *m)
|
||||
{
|
||||
interfaceInfoType = NULL;
|
||||
mutexType = NULL;
|
||||
|
|
|
@ -20,16 +20,12 @@
|
|||
#include "ir/irfunction.h"
|
||||
#include "ir/iraggr.h"
|
||||
#include "ir/irvar.h"
|
||||
#include "gen/dibuilder.h"
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#if LDC_LLVM_VER >= 302
|
||||
#include "llvm/DIBuilder.h"
|
||||
#else
|
||||
#include "llvm/Analysis/DIBuilder.h"
|
||||
#endif
|
||||
#include "llvm/Support/CallSite.h"
|
||||
|
||||
namespace llvm {
|
||||
|
@ -178,7 +174,7 @@ struct IRState
|
|||
IRBuilderHelper ir;
|
||||
|
||||
// debug info helper
|
||||
llvm::DIBuilder dibuilder;
|
||||
ldc::DIBuilder DBuilder;
|
||||
|
||||
// static ctors/dtors/unittests
|
||||
typedef std::list<FuncDeclaration*> FuncDeclList;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "gen/nested.h"
|
||||
#include "gen/pragma.h"
|
||||
#include "gen/runtime.h"
|
||||
#include "gen/todebug.h"
|
||||
#include "gen/tollvm.h"
|
||||
#include "gen/typeinf.h"
|
||||
#include "ir/irmodule.h"
|
||||
|
@ -208,7 +207,7 @@ void DtoAssert(Module* M, Loc loc, DValue* msg)
|
|||
gIR->CreateCallOrInvoke(fn, args);
|
||||
|
||||
// end debug info
|
||||
DtoDwarfFuncEnd(gIR->func()->decl);
|
||||
gIR->DBuilder.EmitFuncEnd(gIR->func()->decl);
|
||||
|
||||
// after assert is always unreachable
|
||||
gIR->ir->CreateUnreachable();
|
||||
|
@ -515,7 +514,7 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs, int op, bool canSkipPostblit)
|
|||
DVarValue *var = lhs->isVar();
|
||||
VarDeclaration *vd = var ? var->var : 0;
|
||||
if (vd)
|
||||
DtoDwarfValue(DtoLoad(var->getLVal()), vd);
|
||||
gIR->DBuilder.EmitValue(DtoLoad(var->getLVal()), vd);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
@ -1090,7 +1089,7 @@ void DtoVarDeclaration(VarDeclaration* vd)
|
|||
|
||||
vd->ir.irLocal->value = allocainst;
|
||||
|
||||
DtoDwarfLocalVariable(allocainst, vd);
|
||||
gIR->DBuilder.EmitLocalVariable(allocainst, vd);
|
||||
}
|
||||
|
||||
if (Logger::enabled())
|
||||
|
@ -1217,7 +1216,7 @@ LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr)
|
|||
{
|
||||
addr = DtoAlloca(var->type, var->toChars());
|
||||
// add debug info
|
||||
DtoDwarfLocalVariable(addr, var);
|
||||
gIR->DBuilder.EmitLocalVariable(addr, var);
|
||||
}
|
||||
|
||||
// referenced by nested function?
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "gen/rttibuilder.h"
|
||||
#include "gen/runtime.h"
|
||||
#include "gen/structs.h"
|
||||
#include "gen/todebug.h"
|
||||
#include "gen/tollvm.h"
|
||||
#include "ir/irdsymbol.h"
|
||||
#include "ir/irmodule.h"
|
||||
|
@ -78,7 +77,7 @@ static llvm::Function* build_module_function(const std::string &name, const std:
|
|||
IRBuilder<> builder(bb);
|
||||
|
||||
// debug info
|
||||
DtoDwarfSubProgramInternal(name.c_str(), symbolName.c_str());
|
||||
gIR->DBuilder.EmitSubProgramInternal(name.c_str(), symbolName.c_str());
|
||||
|
||||
// Call ctor's
|
||||
typedef std::list<FuncDeclaration*>::const_iterator FuncIterator;
|
||||
|
@ -193,7 +192,7 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
|
|||
IRBuilder<> builder(bb);
|
||||
|
||||
// debug info
|
||||
DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str());
|
||||
gIR->DBuilder.EmitSubProgramInternal(fname.c_str(), fname.c_str());
|
||||
|
||||
// get current beginning
|
||||
LLValue* curbeg = builder.CreateLoad(mref, "current");
|
||||
|
@ -262,7 +261,7 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir)
|
|||
gABI = TargetABI::getTarget();
|
||||
|
||||
// debug info
|
||||
DtoDwarfCompileUnit(this);
|
||||
gIR->DBuilder.EmitCompileUnit(this);
|
||||
|
||||
// handle invalid 'objectø module
|
||||
if (!ClassDeclaration::object) {
|
||||
|
@ -301,8 +300,8 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir)
|
|||
}
|
||||
}
|
||||
|
||||
// finilize debug info
|
||||
DtoDwarfModuleEnd();
|
||||
// finalize debug info
|
||||
gIR->DBuilder.EmitModuleEnd();
|
||||
|
||||
// generate ModuleInfo
|
||||
genmoduleinfo();
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "gen/irstate.h"
|
||||
#include "gen/llvmhelpers.h"
|
||||
#include "gen/logger.h"
|
||||
#include "gen/todebug.h"
|
||||
#include "gen/tollvm.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
@ -114,7 +113,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref)
|
|||
ctx = DtoLoad(irfunc->nestArg);
|
||||
dwarfValue = irfunc->nestArg;
|
||||
if (global.params.symdebug)
|
||||
dwarfOpDeref(dwarfAddr);
|
||||
gIR->DBuilder.OpDeref(dwarfAddr);
|
||||
}
|
||||
assert(ctx);
|
||||
|
||||
|
@ -143,8 +142,8 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref)
|
|||
} else {
|
||||
// Load frame pointer and index that...
|
||||
if (dwarfValue && global.params.symdebug) {
|
||||
dwarfOpOffset(dwarfAddr, val, vd->ir.irLocal->nestedDepth);
|
||||
dwarfOpDeref(dwarfAddr);
|
||||
gIR->DBuilder.OpOffset(dwarfAddr, val, vd->ir.irLocal->nestedDepth);
|
||||
gIR->DBuilder.OpDeref(dwarfAddr);
|
||||
}
|
||||
Logger::println("Lower depth");
|
||||
val = DtoGEPi(val, 0, vd->ir.irLocal->nestedDepth);
|
||||
|
@ -157,7 +156,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref)
|
|||
assert(idx != -1 && "Nested context not yet resolved for variable.");
|
||||
|
||||
if (dwarfValue && global.params.symdebug)
|
||||
dwarfOpOffset(dwarfAddr, val, idx);
|
||||
gIR->DBuilder.OpOffset(dwarfAddr, val, idx);
|
||||
|
||||
val = DtoGEPi(val, 0, idx, vd->toChars());
|
||||
Logger::cout() << "Addr: " << *val << '\n';
|
||||
|
@ -170,7 +169,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref)
|
|||
}
|
||||
|
||||
if (dwarfValue && global.params.symdebug)
|
||||
DtoDwarfLocalVariable(dwarfValue, vd, dwarfAddr);
|
||||
gIR->DBuilder.EmitLocalVariable(dwarfValue, vd, dwarfAddr);
|
||||
|
||||
return new DVarValue(astype, vd, val);
|
||||
}
|
||||
|
@ -493,8 +492,8 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
|
|||
|
||||
if (global.params.symdebug) {
|
||||
LLSmallVector<LLValue*, 2> addr;
|
||||
dwarfOpOffset(addr, frameType, vd->ir.irLocal->nestedIndex);
|
||||
DtoDwarfLocalVariable(frame, vd, addr);
|
||||
gIR->DBuilder.OpOffset(addr, frameType, vd->ir.irLocal->nestedIndex);
|
||||
gIR->DBuilder.EmitLocalVariable(frame, vd, addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "gen/llvmhelpers.h"
|
||||
#include "gen/logger.h"
|
||||
#include "gen/runtime.h"
|
||||
#include "gen/todebug.h"
|
||||
#include "gen/tollvm.h"
|
||||
#include "ir/irfunction.h"
|
||||
#include "ir/irlandingpad.h"
|
||||
|
@ -63,7 +62,7 @@ void ReturnStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// emit dwarf stop point
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
gIR->DBuilder.EmitStopPoint(loc.linnum);
|
||||
|
||||
// is there a return value expression?
|
||||
if (exp || (!exp && (p->topfunc() == p->mainFunc)) )
|
||||
|
@ -93,7 +92,7 @@ void ReturnStatement::toIR(IRState* p)
|
|||
DtoEnclosingHandlers(loc, NULL);
|
||||
|
||||
// emit dbg end function
|
||||
DtoDwarfFuncEnd(f->decl);
|
||||
gIR->DBuilder.EmitFuncEnd(f->decl);
|
||||
|
||||
// emit ret
|
||||
llvm::ReturnInst::Create(gIR->context(), p->scopebb());
|
||||
|
@ -159,7 +158,7 @@ void ReturnStatement::toIR(IRState* p)
|
|||
// emit scopes
|
||||
DtoEnclosingHandlers(loc, NULL);
|
||||
|
||||
DtoDwarfFuncEnd(p->func()->decl);
|
||||
gIR->DBuilder.EmitFuncEnd(p->func()->decl);
|
||||
llvm::ReturnInst::Create(gIR->context(), v, p->scopebb());
|
||||
}
|
||||
}
|
||||
|
@ -168,7 +167,7 @@ void ReturnStatement::toIR(IRState* p)
|
|||
{
|
||||
assert(p->topfunc()->getReturnType() == LLType::getVoidTy(gIR->context()));
|
||||
DtoEnclosingHandlers(loc, NULL);
|
||||
DtoDwarfFuncEnd(p->func()->decl);
|
||||
gIR->DBuilder.EmitFuncEnd(p->func()->decl);
|
||||
llvm::ReturnInst::Create(gIR->context(), p->scopebb());
|
||||
}
|
||||
|
||||
|
@ -186,7 +185,7 @@ void ExpStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// emit dwarf stop point
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
gIR->DBuilder.EmitStopPoint(loc.linnum);
|
||||
|
||||
if (exp) {
|
||||
elem* e;
|
||||
|
@ -232,7 +231,7 @@ void IfStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// start a dwarf lexical block
|
||||
DtoDwarfBlockStart(loc);
|
||||
gIR->DBuilder.EmitBlockStart(loc);
|
||||
if (match)
|
||||
DtoRawVarDeclaration(match);
|
||||
|
||||
|
@ -258,9 +257,9 @@ void IfStatement::toIR(IRState* p)
|
|||
// do scoped statements
|
||||
|
||||
if (ifbody) {
|
||||
DtoDwarfBlockStart(ifbody->loc);
|
||||
gIR->DBuilder.EmitBlockStart(ifbody->loc);
|
||||
ifbody->toIR(p);
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
}
|
||||
if (!gIR->scopereturned()) {
|
||||
llvm::BranchInst::Create(endbb,gIR->scopebb());
|
||||
|
@ -269,16 +268,16 @@ void IfStatement::toIR(IRState* p)
|
|||
if (elsebody) {
|
||||
//assert(0);
|
||||
gIR->scope() = IRScope(elsebb,endbb);
|
||||
DtoDwarfBlockStart(elsebody->loc);
|
||||
gIR->DBuilder.EmitBlockStart(elsebody->loc);
|
||||
elsebody->toIR(p);
|
||||
if (!gIR->scopereturned()) {
|
||||
llvm::BranchInst::Create(endbb,gIR->scopebb());
|
||||
}
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
}
|
||||
|
||||
// end the dwarf lexical block
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
|
||||
// rewrite the scope
|
||||
gIR->scope() = IRScope(endbb,oldend);
|
||||
|
@ -313,9 +312,9 @@ void ScopeStatement::toIR(IRState* p)
|
|||
p->scope().end = endbb;*/
|
||||
|
||||
if (statement) {
|
||||
DtoDwarfBlockStart(statement->loc);
|
||||
gIR->DBuilder.EmitBlockStart(statement->loc);
|
||||
statement->toIR(p);
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
}
|
||||
|
||||
/*p->scope().end = oldend;
|
||||
|
@ -331,7 +330,7 @@ void WhileStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// start a dwarf lexical block
|
||||
DtoDwarfBlockStart(loc);
|
||||
gIR->DBuilder.EmitBlockStart(loc);
|
||||
|
||||
// create while blocks
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
|
@ -371,7 +370,7 @@ void WhileStatement::toIR(IRState* p)
|
|||
gIR->scope() = IRScope(endbb,oldend);
|
||||
|
||||
// end the dwarf lexical block
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -382,7 +381,7 @@ void DoStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// start a dwarf lexical block
|
||||
DtoDwarfBlockStart(loc);
|
||||
gIR->DBuilder.EmitBlockStart(loc);
|
||||
|
||||
// create while blocks
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
|
@ -419,7 +418,7 @@ void DoStatement::toIR(IRState* p)
|
|||
gIR->scope() = IRScope(endbb,oldend);
|
||||
|
||||
// end the dwarf lexical block
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -430,7 +429,7 @@ void ForStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// start new dwarf lexical block
|
||||
DtoDwarfBlockStart(loc);
|
||||
gIR->DBuilder.EmitBlockStart(loc);
|
||||
|
||||
// create for blocks
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
|
@ -497,7 +496,7 @@ void ForStatement::toIR(IRState* p)
|
|||
gIR->scope() = IRScope(endbb,oldend);
|
||||
|
||||
// end the dwarf lexical block
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -513,7 +512,7 @@ void BreakStatement::toIR(IRState* p)
|
|||
return;
|
||||
|
||||
// emit dwarf stop point
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
gIR->DBuilder.EmitStopPoint(loc.linnum);
|
||||
|
||||
if (ident != 0) {
|
||||
Logger::println("ident = %s", ident->toChars());
|
||||
|
@ -568,7 +567,7 @@ void ContinueStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// emit dwarf stop point
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
gIR->DBuilder.EmitStopPoint(loc.linnum);
|
||||
|
||||
if (ident != 0) {
|
||||
Logger::println("ident = %s", ident->toChars());
|
||||
|
@ -634,21 +633,21 @@ void TryFinallyStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// emit dwarf stop point
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
gIR->DBuilder.EmitStopPoint(loc.linnum);
|
||||
|
||||
// if there's no finalbody or no body, things are simple
|
||||
if (!finalbody) {
|
||||
if (body) {
|
||||
DtoDwarfBlockStart(body->loc);
|
||||
gIR->DBuilder.EmitBlockStart(body->loc);
|
||||
body->toIR(p);
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!body) {
|
||||
DtoDwarfBlockStart(finalbody->loc);
|
||||
gIR->DBuilder.EmitBlockStart(finalbody->loc);
|
||||
finalbody->toIR(p);
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -690,9 +689,9 @@ void TryFinallyStatement::toIR(IRState* p)
|
|||
p->scope() = IRScope(trybb,finallybb);
|
||||
|
||||
assert(body);
|
||||
DtoDwarfBlockStart(body->loc);
|
||||
gIR->DBuilder.EmitBlockStart(body->loc);
|
||||
body->toIR(p);
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
|
||||
// terminate try BB
|
||||
if (!p->scopereturned())
|
||||
|
@ -705,9 +704,9 @@ void TryFinallyStatement::toIR(IRState* p)
|
|||
// do finally block
|
||||
//
|
||||
p->scope() = IRScope(finallybb,landingpadbb);
|
||||
DtoDwarfBlockStart(finalbody->loc);
|
||||
gIR->DBuilder.EmitBlockStart(finalbody->loc);
|
||||
finalbody->toIR(p);
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
|
||||
// terminate finally
|
||||
//TODO: isn't it an error to have a 'returned' finally block?
|
||||
|
@ -727,7 +726,7 @@ void TryCatchStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// emit dwarf stop point
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
gIR->DBuilder.EmitStopPoint(loc.linnum);
|
||||
|
||||
// create basic blocks
|
||||
llvm::BasicBlock* oldend = p->scopeend();
|
||||
|
@ -762,9 +761,9 @@ void TryCatchStatement::toIR(IRState* p)
|
|||
p->scope() = IRScope(trybb,landingpadbb);
|
||||
|
||||
assert(body);
|
||||
DtoDwarfBlockStart(body->loc);
|
||||
gIR->DBuilder.EmitBlockStart(body->loc);
|
||||
body->toIR(p);
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
|
||||
if (!gIR->scopereturned())
|
||||
llvm::BranchInst::Create(endbb, p->scopebb());
|
||||
|
@ -783,12 +782,12 @@ void ThrowStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// emit dwarf stop point
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
gIR->DBuilder.EmitStopPoint(loc.linnum);
|
||||
|
||||
assert(exp);
|
||||
DValue* e = exp->toElemDtor(p);
|
||||
|
||||
DtoDwarfFuncEnd(gIR->func()->decl);
|
||||
gIR->DBuilder.EmitFuncEnd(gIR->func()->decl);
|
||||
|
||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_throw_exception");
|
||||
//Logger::cout() << "calling: " << *fn << '\n';
|
||||
|
@ -865,7 +864,7 @@ void SwitchStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// emit dwarf stop point
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
gIR->DBuilder.EmitStopPoint(loc.linnum);
|
||||
|
||||
llvm::BasicBlock* oldbb = gIR->scopebb();
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
|
@ -1038,9 +1037,9 @@ void CaseStatement::toIR(IRState* p)
|
|||
p->scope() = IRScope(bodyBB, p->scopeend());
|
||||
|
||||
assert(statement);
|
||||
DtoDwarfBlockStart(statement->loc);
|
||||
gIR->DBuilder.EmitBlockStart(statement->loc);
|
||||
statement->toIR(p);
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1065,9 +1064,9 @@ void DefaultStatement::toIR(IRState* p)
|
|||
p->scope() = IRScope(bodyBB, p->scopeend());
|
||||
|
||||
assert(statement);
|
||||
DtoDwarfBlockStart(statement->loc);
|
||||
gIR->DBuilder.EmitBlockStart(statement->loc);
|
||||
statement->toIR(p);
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1082,7 +1081,7 @@ void UnrolledLoopStatement::toIR(IRState* p)
|
|||
return;
|
||||
|
||||
// start a dwarf lexical block
|
||||
DtoDwarfBlockStart(loc);
|
||||
gIR->DBuilder.EmitBlockStart(loc);
|
||||
|
||||
// DMD doesn't fold stuff like continue/break, and since this isn't really a loop
|
||||
// we have to keep track of each statement and jump to the next/end on continue/break
|
||||
|
@ -1140,7 +1139,7 @@ void UnrolledLoopStatement::toIR(IRState* p)
|
|||
p->scope() = IRScope(endbb,oldend);
|
||||
|
||||
// end the dwarf lexical block
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1151,7 +1150,7 @@ void ForeachStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// start a dwarf lexical block
|
||||
DtoDwarfBlockStart(loc);
|
||||
gIR->DBuilder.EmitBlockStart(loc);
|
||||
|
||||
//assert(arguments->dim == 1);
|
||||
assert(value != 0);
|
||||
|
@ -1267,7 +1266,7 @@ void ForeachStatement::toIR(IRState* p)
|
|||
llvm::BranchInst::Create(condbb, p->scopebb());
|
||||
|
||||
// end the dwarf lexical block
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
|
||||
// end
|
||||
p->scope() = IRScope(endbb,oldend);
|
||||
|
@ -1281,7 +1280,7 @@ void ForeachRangeStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// start a dwarf lexical block
|
||||
DtoDwarfBlockStart(loc);
|
||||
gIR->DBuilder.EmitBlockStart(loc);
|
||||
|
||||
// evaluate lwr/upr
|
||||
assert(lwr->type->isintegral());
|
||||
|
@ -1371,7 +1370,7 @@ void ForeachRangeStatement::toIR(IRState* p)
|
|||
llvm::BranchInst::Create(condbb, p->scopebb());
|
||||
|
||||
// end the dwarf lexical block
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
|
||||
// END
|
||||
p->scope() = IRScope(endbb,oldend);
|
||||
|
@ -1430,7 +1429,7 @@ void GotoStatement::toIR(IRState* p)
|
|||
Logger::println("GotoStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
gIR->DBuilder.EmitStopPoint(loc.linnum);
|
||||
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergoto", p->topfunc(), oldend);
|
||||
|
@ -1447,7 +1446,7 @@ void GotoDefaultStatement::toIR(IRState* p)
|
|||
Logger::println("GotoDefaultStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
gIR->DBuilder.EmitStopPoint(loc.linnum);
|
||||
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergotodefault", p->topfunc(), oldend);
|
||||
|
@ -1468,7 +1467,7 @@ void GotoCaseStatement::toIR(IRState* p)
|
|||
Logger::println("GotoCaseStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
gIR->DBuilder.EmitStopPoint(loc.linnum);
|
||||
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergotocase", p->topfunc(), oldend);
|
||||
|
@ -1492,7 +1491,7 @@ void WithStatement::toIR(IRState* p)
|
|||
Logger::println("WithStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
DtoDwarfBlockStart(loc);
|
||||
gIR->DBuilder.EmitBlockStart(loc);
|
||||
|
||||
assert(exp);
|
||||
|
||||
|
@ -1507,7 +1506,7 @@ void WithStatement::toIR(IRState* p)
|
|||
if (body)
|
||||
body->toIR(p);
|
||||
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1524,7 +1523,7 @@ void SynchronizedStatement::toIR(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
// emit dwarf stop point
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
gIR->DBuilder.EmitStopPoint(loc.linnum);
|
||||
|
||||
// enter lock
|
||||
if (exp)
|
||||
|
@ -1540,9 +1539,9 @@ void SynchronizedStatement::toIR(IRState* p)
|
|||
|
||||
// emit body
|
||||
p->func()->gen->targetScopes.push_back(IRTargetScope(this,new EnclosingSynchro(this),NULL,NULL));
|
||||
DtoDwarfBlockStart(body->loc);
|
||||
gIR->DBuilder.EmitBlockStart(body->loc);
|
||||
body->toIR(p);
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
p->func()->gen->targetScopes.pop_back();
|
||||
|
||||
// exit lock
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
//===-- gen/todebug.h - Symbolic debug information generation ---*- C++ -*-===//
|
||||
//
|
||||
// LDC – the LLVM D compiler
|
||||
//
|
||||
// This file is distributed under the BSD-style LDC license. See the LICENSE
|
||||
// file for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Handles generation of symbolic debug information using LLVM's DWARF support.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LDC_GEN_TODEBUG_H
|
||||
#define LDC_GEN_TODEBUG_H
|
||||
|
||||
#include "gen/irstate.h"
|
||||
#include "gen/tollvm.h"
|
||||
|
||||
|
||||
/// \brief Emit the Dwarf compile_unit global for a Module m.
|
||||
/// \param m Module to emit as compile unit.
|
||||
void DtoDwarfCompileUnit(Module* m);
|
||||
|
||||
/// \brief Emit the Dwarf subprogram global for a function declaration fd.
|
||||
/// \param fd Function declaration to emit as subprogram.
|
||||
/// \returns the Dwarf subprogram global.
|
||||
llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd);
|
||||
|
||||
/// \brief Emit the Dwarf subprogram global for a internal function.
|
||||
/// This is used for generated functions like moduleinfoctors,
|
||||
/// module ctors/dtors and unittests.
|
||||
/// \param prettyname The name as seen in the source.
|
||||
/// \param mangledname The mangled name in the object file.
|
||||
/// \returns the Dwarf subprogram global.
|
||||
llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char* mangledname);
|
||||
|
||||
void DtoDwarfFuncStart(FuncDeclaration* fd);
|
||||
void DtoDwarfFuncEnd(FuncDeclaration* fd);
|
||||
void DtoDwarfBlockStart(Loc loc);
|
||||
void DtoDwarfBlockEnd();
|
||||
|
||||
void DtoDwarfStopPoint(unsigned ln);
|
||||
|
||||
void DtoDwarfValue(LLValue *val, VarDeclaration* vd);
|
||||
|
||||
/// \brief Emits all things necessary for making debug info for a local variable vd.
|
||||
/// \param ll LLVM Value of the variable.
|
||||
/// \param vd Variable declaration to emit debug info for.
|
||||
/// \param addr An array of complex address operations.
|
||||
void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd,
|
||||
llvm::ArrayRef<LLValue*> addr = llvm::ArrayRef<LLValue*>());
|
||||
|
||||
/// \brief Emits all things necessary for making debug info for a global variable vd.
|
||||
/// \param ll LLVM global variable
|
||||
/// \param vd Variable declaration to emit debug info for.
|
||||
/// \returns Created debug info
|
||||
llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd);
|
||||
|
||||
void DtoDwarfModuleEnd();
|
||||
|
||||
template<typename T>
|
||||
void dwarfOpOffset(T &addr, LLStructType *type, int index)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
||||
uint64_t offset = gDataLayout->getStructLayout(type)->getElementOffset(index);
|
||||
LLType *int64Ty = LLType::getInt64Ty(gIR->context());
|
||||
addr.push_back(LLConstantInt::get(int64Ty, llvm::DIBuilder::OpPlus));
|
||||
addr.push_back(LLConstantInt::get(int64Ty, offset));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void dwarfOpOffset(T &addr, LLValue *val, int index)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
||||
LLStructType *type = isaStruct(val->getType()->getContainedType(0));
|
||||
assert(type);
|
||||
dwarfOpOffset(addr, type, index);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void dwarfOpDeref(T &addr)
|
||||
{
|
||||
if (!global.params.symdebug)
|
||||
return;
|
||||
|
||||
LLType *int64Ty = LLType::getInt64Ty(gIR->context());
|
||||
addr.push_back(LLConstantInt::get(int64Ty, llvm::DIBuilder::OpDeref));
|
||||
}
|
||||
|
||||
#endif // LDC_GEN_TODEBUG_H
|
|
@ -31,7 +31,6 @@
|
|||
#include "gen/pragma.h"
|
||||
#include "gen/runtime.h"
|
||||
#include "gen/structs.h"
|
||||
#include "gen/todebug.h"
|
||||
#include "gen/tollvm.h"
|
||||
#include "gen/typeinf.h"
|
||||
#include "gen/utils.h"
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "gen/llvmhelpers.h"
|
||||
#include "gen/logger.h"
|
||||
#include "gen/runtime.h"
|
||||
#include "gen/todebug.h"
|
||||
#include "gen/tollvm.h"
|
||||
#include "ir/irlandingpad.h"
|
||||
|
||||
|
@ -50,7 +49,7 @@ void IRLandingPadCatchInfo::toIR()
|
|||
return;
|
||||
|
||||
gIR->scope() = IRScope(target, target);
|
||||
DtoDwarfBlockStart(catchStmt->loc);
|
||||
gIR->DBuilder.EmitBlockStart(catchStmt->loc);
|
||||
|
||||
// assign storage to catch var
|
||||
if (catchStmt->var) {
|
||||
|
@ -81,7 +80,7 @@ void IRLandingPadCatchInfo::toIR()
|
|||
if (!gIR->scopereturned())
|
||||
gIR->ir->CreateBr(end);
|
||||
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
}
|
||||
|
||||
IRLandingPadFinallyStatementInfo::IRLandingPadFinallyStatementInfo(Statement *finallyBody_) :
|
||||
|
@ -107,13 +106,13 @@ void IRLandingPadFinallyStatementInfo::toIR(LLValue *eh_ptr)
|
|||
gIR->scope() = IRScope(bb, gIR->scopeend());
|
||||
|
||||
// set collision landing pad as unwind target and emit the body of the finally
|
||||
DtoDwarfBlockStart(finallyBody->loc);
|
||||
gIR->DBuilder.EmitBlockStart(finallyBody->loc);
|
||||
padInfo.scopeStack.push(IRLandingPadScope(collision));
|
||||
pad = collision;
|
||||
finallyBody->toIR(gIR);
|
||||
padInfo.scopeStack.pop();
|
||||
pad = padInfo.get();
|
||||
DtoDwarfBlockEnd();
|
||||
gIR->DBuilder.EmitBlockEnd();
|
||||
}
|
||||
|
||||
void IRLandingPad::addCatch(Catch* catchstmt, llvm::BasicBlock* end)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue