Emit debug info for variables that are used in nested functions

This commit is contained in:
Alexey Prokhin 2011-12-03 23:38:31 +04:00
parent cedb4c0e68
commit b8721a8515
7 changed files with 103 additions and 25 deletions

View file

@ -361,6 +361,7 @@ struct VarDeclaration : Declaration
// debug description // debug description
llvm::DIVariable debugVariable; llvm::DIVariable debugVariable;
llvm::DISubprogram debugFunc;
#endif #endif
}; };

View file

@ -729,6 +729,15 @@ void DtoDefineFunction(FuncDeclaration* fd)
#endif #endif
} }
// give the 'nestArg' storage
if (f->fty.arg_nest)
{
LLValue *nestArg = irfunction->nestArg;
LLValue *val = DtoRawAlloca(nestArg->getType(), 0, "nestedFrame");
DtoStore(nestArg, val);
irfunction->nestArg = val;
}
// give arguments storage // give arguments storage
// and debug info // and debug info
if (fd->parameters) if (fd->parameters)

View file

@ -519,7 +519,7 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs, int op)
DVarValue *var = lhs->isVar(); DVarValue *var = lhs->isVar();
VarDeclaration *varDecl = var ? var->var : 0; VarDeclaration *varDecl = var ? var->var : 0;
if (global.params.symdebug && varDecl && varDecl->debugVariable) if (global.params.symdebug && varDecl && varDecl->debugVariable)
DtoDwarfValue(rhs->getRVal(), lhs->isVar()->var); DtoDwarfValue(lhs->getRVal(), varDecl);
#endif #endif
} }

View file

@ -6,6 +6,7 @@
#include "gen/logger.h" #include "gen/logger.h"
#include "gen/tollvm.h" #include "gen/tollvm.h"
#include "gen/functions.h" #include "gen/functions.h"
#include "gen/todebug.h"
#include "llvm/Analysis/ValueTracking.h" #include "llvm/Analysis/ValueTracking.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
@ -120,6 +121,10 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref)
return new DVarValue(astype, vd, val); return new DVarValue(astype, vd, val);
} }
LLValue *dwarfValue = 0;
std::vector<LLValue*> dwarfAddr;
LLType *int64Ty = LLType::getInt64Ty(gIR->context());
// get the nested context // get the nested context
LLValue* ctx = 0; LLValue* ctx = 0;
if (irfunc->decl->isMember2()) if (irfunc->decl->isMember2())
@ -135,10 +140,15 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref)
#endif #endif
ctx = DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis")); ctx = DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis"));
} }
else if (irfunc->nestedVar) else if (irfunc->nestedVar) {
ctx = irfunc->nestedVar; ctx = irfunc->nestedVar;
else dwarfValue = ctx;
ctx = irfunc->nestArg; } else {
ctx = DtoLoad(irfunc->nestArg);
dwarfValue = irfunc->nestArg;
if (global.params.symdebug)
dwarfOpDeref(dwarfAddr);
}
assert(ctx); assert(ctx);
DtoCreateNestedContextType(vdparent->isFuncDeclaration()); DtoCreateNestedContextType(vdparent->isFuncDeclaration());
@ -174,21 +184,32 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref)
Logger::println("Same depth"); Logger::println("Same depth");
} else { } else {
// Load frame pointer and index that... // Load frame pointer and index that...
if (dwarfValue && global.params.symdebug) {
dwarfOpOffset(dwarfAddr, val, vd->ir.irLocal->nestedDepth);
dwarfOpDeref(dwarfAddr);
}
Logger::println("Lower depth"); Logger::println("Lower depth");
val = DtoGEPi(val, 0, vd->ir.irLocal->nestedDepth); val = DtoGEPi(val, 0, vd->ir.irLocal->nestedDepth);
Logger::cout() << "Frame index: " << *val << '\n'; Logger::cout() << "Frame index: " << *val << '\n';
val = DtoAlignedLoad(val, (std::string(".frame.") + vdparent->toChars()).c_str()); val = DtoAlignedLoad(val, (std::string(".frame.") + vdparent->toChars()).c_str());
Logger::cout() << "Frame: " << *val << '\n'; Logger::cout() << "Frame: " << *val << '\n';
} }
if (dwarfValue && global.params.symdebug)
dwarfOpOffset(dwarfAddr, val, vd->ir.irLocal->nestedIndex);
val = DtoGEPi(val, 0, vd->ir.irLocal->nestedIndex, vd->toChars()); val = DtoGEPi(val, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
Logger::cout() << "Addr: " << *val << '\n'; Logger::cout() << "Addr: " << *val << '\n';
Logger::cout() << "of type: " << *val->getType() << '\n'; Logger::cout() << "of type: " << *val->getType() << '\n';
if (vd->ir.irLocal->byref || byref) { if (vd->ir.irLocal->byref || byref) {
val = DtoAlignedLoad(val); val = DtoAlignedLoad(val);
//dwarfOpDeref(dwarfAddr);
Logger::cout() << "Was byref, now: " << *val << '\n'; Logger::cout() << "Was byref, now: " << *val << '\n';
Logger::cout() << "of type: " << *val->getType() << '\n'; Logger::cout() << "of type: " << *val->getType() << '\n';
} }
if (dwarfValue && global.params.symdebug)
DtoDwarfLocalVariable(dwarfValue, vd, dwarfAddr);
return new DVarValue(astype, vd, val); return new DVarValue(astype, vd, val);
} }
else { else {
@ -283,7 +304,7 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
} }
// otherwise, it may have gotten a context from the caller // otherwise, it may have gotten a context from the caller
else if (irfunc->nestArg) else if (irfunc->nestArg)
val = irfunc->nestArg; val = DtoLoad(irfunc->nestArg);
// or just have a this argument // or just have a this argument
else if (irfunc->thisArg) else if (irfunc->thisArg)
{ {
@ -532,7 +553,7 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
// copy parent frame into beginning // copy parent frame into beginning
if (nparelems) if (nparelems)
{ {
LLValue* src = irfunction->nestArg; LLValue* src = DtoLoad(irfunction->nestArg);
if (!src) if (!src)
{ {
assert(irfunction->thisArg); assert(irfunction->thisArg);
@ -594,7 +615,7 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
// copy parent frames into beginning // copy parent frames into beginning
if (depth != 0) { if (depth != 0) {
LLValue* src = irfunction->nestArg; LLValue* src = DtoLoad(irfunction->nestArg);
if (!src) { if (!src) {
assert(irfunction->thisArg); assert(irfunction->thisArg);
assert(fd->isMember2()); assert(fd->isMember2());
@ -669,6 +690,12 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
vd->ir.irLocal->value = gep; vd->ir.irLocal->value = gep;
vd->ir.irLocal->byref = false; vd->ir.irLocal->byref = false;
} }
if (global.params.symdebug) {
LLSmallVector<LLValue*, 2> addr;
dwarfOpOffset(addr, frameType, vd->ir.irLocal->nestedIndex);
DtoDwarfLocalVariable(frame, vd, addr);
}
} }
} else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) { } else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) {
// Propagate context arg properties if the context arg is passed on unmodified. // Propagate context arg properties if the context arg is passed on unmodified.

View file

@ -361,11 +361,14 @@ static llvm::DIType dwarfTypeDescription(Type* type, const char* c_name)
////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////
void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd) void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd, llvm::ArrayRef<LLValue*> addr)
{ {
Logger::println("D to dwarf local variable"); Logger::println("D to dwarf local variable");
LOG_SCOPE; LOG_SCOPE;
if (gIR->func()->diSubprogram == vd->debugFunc) // ensure that the debug variable is created only once
return;
// get type description // get type description
llvm::DIType TD = dwarfTypeDescription(vd->type, NULL); llvm::DIType TD = dwarfTypeDescription(vd->type, NULL);
if ((llvm::MDNode*)TD == 0) if ((llvm::MDNode*)TD == 0)
@ -380,6 +383,7 @@ void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd)
else else
tag = DW_TAG_auto_variable; tag = DW_TAG_auto_variable;
if (addr.empty()) {
vd->debugVariable = gIR->dibuilder.createLocalVariable( vd->debugVariable = gIR->dibuilder.createLocalVariable(
tag, // tag tag, // tag
gIR->func()->diSubprogram, // context gIR->func()->diSubprogram, // context
@ -389,6 +393,18 @@ void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd)
TD, // type TD, // type
true // preserve true // preserve
); );
} else {
vd->debugVariable = gIR->dibuilder.createComplexVariable(
tag, // tag
gIR->func()->diSubprogram, // context
vd->toChars(), // name
DtoDwarfFile(vd->loc), // file
vd->loc.linnum, // line num
TD, // type
addr
);
}
vd->debugFunc = gIR->func()->diSubprogram;
// declare // declare
dwarfDeclare(ll, vd->debugVariable); dwarfDeclare(ll, vd->debugVariable);
@ -522,12 +538,9 @@ void DtoDwarfStopPoint(unsigned ln)
////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////
void DtoDwarfValue(LLValue* var, VarDeclaration* vd) void DtoDwarfValue(LLValue *val, VarDeclaration* vd)
{ {
if (llvm::isa<llvm::AllocaInst>(vd->ir.irLocal->value) == 0) llvm::Instruction *instr = gIR->dibuilder.insertDbgValueIntrinsic(val, 0, vd->debugVariable, gIR->scopebb());
return;
llvm::Instruction *instr = gIR->dibuilder.insertDbgValueIntrinsic(vd->ir.irLocal->value, 0, vd->debugVariable, gIR->scopebb());
instr->setDebugLoc(gIR->ir->getCurrentDebugLocation()); instr->setDebugLoc(gIR->ir->getCurrentDebugLocation());
} }

View file

@ -3,6 +3,9 @@
#ifndef DISABLE_DEBUG_INFO #ifndef DISABLE_DEBUG_INFO
#include "gen/tollvm.h"
#include "gen/irstate.h"
void RegisterDwarfSymbols(llvm::Module* mod); void RegisterDwarfSymbols(llvm::Module* mod);
/** /**
@ -31,14 +34,15 @@ void DtoDwarfFuncEnd(FuncDeclaration* fd);
void DtoDwarfStopPoint(unsigned ln); void DtoDwarfStopPoint(unsigned ln);
void DtoDwarfValue(LLValue* var, VarDeclaration* vd); void DtoDwarfValue(LLValue *val, VarDeclaration* vd);
/** /**
* Emits all things necessary for making debug info for a local variable vd. * Emits all things necessary for making debug info for a local variable vd.
* @param ll LLVM Value of the variable. * @param ll LLVM Value of the variable.
* @param vd Variable declaration to emit debug info for. * @param vd Variable declaration to emit debug info for.
*/ */
void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd); void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd,
llvm::ArrayRef<LLValue*> addr = llvm::ArrayRef<LLValue*>());
/** /**
* Emits all things necessary for making debug info for a global variable vd. * Emits all things necessary for making debug info for a global variable vd.
@ -50,6 +54,30 @@ llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclarati
void DtoDwarfModuleEnd(); void DtoDwarfModuleEnd();
template<typename T>
void dwarfOpOffset(T &addr, LLStructType *type, int index)
{
uint64_t offset = gTargetData->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)
{
LLStructType *type = isaStruct(val->getType()->getContainedType(0));
assert(type);
dwarfOpOffset(addr, type, index);
}
template<typename T>
void dwarfOpDeref(T &addr)
{
LLType *int64Ty = LLType::getInt64Ty(gIR->context());
addr.push_back(LLConstantInt::get(int64Ty, llvm::DIBuilder::OpDeref));
}
#endif // DISABLE_DEBUG_INFO #endif // DISABLE_DEBUG_INFO

View file

@ -2553,7 +2553,7 @@ DValue* FuncExp::toElem(IRState* p)
) )
cval = irfn->nestedVar; cval = irfn->nestedVar;
else if (irfn->nestArg) else if (irfn->nestArg)
cval = irfn->nestArg; cval = DtoLoad(irfn->nestArg);
#if DMDV2 #if DMDV2
// TODO: should we enable that for D1 as well? // TODO: should we enable that for D1 as well?
else if (irfn->thisArg) else if (irfn->thisArg)