diff --git a/dmd/declaration.c b/dmd/declaration.c index f9c0ebbe..ed49b291 100644 --- a/dmd/declaration.c +++ b/dmd/declaration.c @@ -573,6 +573,8 @@ Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init); sv->storage_class = storage_class; + // LLVMDC + sv->needsStorage = needsStorage; } #ifdef _DH // Syntax copy for header file diff --git a/dmd/func.c b/dmd/func.c index 8dd67eb1..2d67ea6f 100644 --- a/dmd/func.c +++ b/dmd/func.c @@ -781,6 +781,11 @@ void FuncDeclaration::semantic3(Scope *sc) if (v->storage_class & STClazy) v->storage_class |= STCin; v->semantic(sc2); + #if IN_LLVM + // LLVMDC: the argument needs an addres if we want to attach debug info to it. + if (global.params.symdebug) + v->needsStorage = true; + #endif if (!sc2->insert(v)) error("parameter %s.%s is already defined", toChars(), v->toChars()); else diff --git a/gen/functions.cpp b/gen/functions.cpp index ac9b2948..b01e759b 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -607,6 +607,10 @@ void DtoDefineFunc(FuncDeclaration* fd) s.append("_storage"); LLValue* v = new llvm::AllocaInst(a->getType(),s,allocaPoint); + + if (global.params.symdebug) + DtoDwarfLocalVariable(v, vd); + gIR->ir->CreateStore(a,v); vd->ir.irLocal->value = v; } diff --git a/gen/todebug.cpp b/gen/todebug.cpp index e6f7502d..6a1f7de3 100644 --- a/gen/todebug.cpp +++ b/gen/todebug.cpp @@ -100,17 +100,29 @@ LLConstant* GetDwarfAnchor(llvm::dwarf::dwarf_constants c) ////////////////////////////////////////////////////////////////////////////////////////////////// -const llvm::StructType* GetDwarfCompileUnitType() { +static const llvm::StructType* GetDwarfCompileUnitType() { return isaStruct(gIR->module->getTypeByName("llvm.dbg.compile_unit.type")); } -const llvm::StructType* GetDwarfSubProgramType() { +static const llvm::StructType* GetDwarfSubProgramType() { return isaStruct(gIR->module->getTypeByName("llvm.dbg.subprogram.type")); } +static const llvm::StructType* GetDwarfVariableType() { + return isaStruct(gIR->module->getTypeByName("llvm.dbg.variable.type")); +} + +static const llvm::StructType* GetDwarfDerivedTypeType() { + return isaStruct(gIR->module->getTypeByName("llvm.dbg.derivedtype.type")); +} + +static const llvm::StructType* GetDwarfBasicTypeType() { + return isaStruct(gIR->module->getTypeByName("llvm.dbg.basictype.type")); +} + ////////////////////////////////////////////////////////////////////////////////////////////////// -llvm::GlobalVariable* DtoDwarfCompileUnit(Module* m) +LLGlobalVariable* DtoDwarfCompileUnit(Module* m) { if (!m->ir.irModule) m->ir.irModule = new IrModule(m); @@ -204,14 +216,15 @@ void DtoDwarfStopPoint(unsigned ln) ////////////////////////////////////////////////////////////////////////////////////////////////// -const llvm::StructType* GetDwarfBasicTypeType() { - return isaStruct(gIR->module->getTypeByName("llvm.dbg.basictype.type")); -} +static LLGlobalVariable* DtoDwarfTypeDescription(Loc loc, Type* type, LLGlobalVariable* cu); ////////////////////////////////////////////////////////////////////////////////////////////////// -LLGlobalVariable* DtoDwarfBasicType(Type* type, llvm::GlobalVariable* compileUnit) +static LLGlobalVariable* DtoDwarfBasicType(Type* type, llvm::GlobalVariable* compileUnit) { + Type* t = type->toBasetype(); + + const LLType* T = DtoType(type); std::vector vals; @@ -237,14 +250,14 @@ LLGlobalVariable* DtoDwarfBasicType(Type* type, llvm::GlobalVariable* compileUni vals.push_back(DtoConstUint(0)); // dwarf type unsigned id; - if (type->isintegral()) + if (t->isintegral()) { if (type->isunsigned()) id = llvm::dwarf::DW_ATE_unsigned; else id = llvm::dwarf::DW_ATE_signed; } - else if (type->isfloating()) + else if (t->isfloating()) { id = llvm::dwarf::DW_ATE_float; } @@ -262,13 +275,63 @@ LLGlobalVariable* DtoDwarfBasicType(Type* type, llvm::GlobalVariable* compileUni ////////////////////////////////////////////////////////////////////////////////////////////////// -const llvm::StructType* GetDwarfVariableType() { - return isaStruct(gIR->module->getTypeByName("llvm.dbg.variable.type")); +static LLGlobalVariable* DtoDwarfDerivedType(Loc loc, Type* type, llvm::GlobalVariable* compileUnit) +{ + const LLType* T = DtoType(type); + Type* t = DtoDType(type); + + // defaults + LLConstant* name = getNullPtr(getVoidPtrType()); + + // find tag + unsigned tag; + if (t->ty == Tpointer) + { + tag = llvm::dwarf::DW_TAG_pointer_type; + } + else + { + assert(0 && "unsupported derivedtype for debug info"); + } + + std::vector vals; + // tag + vals.push_back(llvm::ConstantExpr::getAdd( + DtoConstUint(tag), + DtoConstUint(llvm::LLVMDebugVersion))); + // context + vals.push_back(dbgToArrTy(compileUnit)); + // name + vals.push_back(name); + // compile unit where defined + vals.push_back(getNullPtr(dbgArrTy())); + // line number where defined + vals.push_back(DtoConstInt(0)); + // size in bits + vals.push_back(LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false)); + // alignment in bits + vals.push_back(LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false)); + // offset in bits + vals.push_back(LLConstantInt::get(LLType::Int64Ty, 0, false)); + // FIXME: dont know what this is + vals.push_back(DtoConstUint(0)); + // base type + Type* nt = t->nextOf(); + LLGlobalVariable* nTD = DtoDwarfTypeDescription(loc, nt, compileUnit); + if (nt->ty == Tvoid || !nTD) + vals.push_back(getNullPtr(dbgArrTy())); + else + vals.push_back(dbgToArrTy(nTD)); + + LLConstant* c = llvm::ConstantStruct::get(GetDwarfDerivedTypeType(), vals); + LLGlobalVariable* gv = new LLGlobalVariable(c->getType(), true, LLGlobalValue::InternalLinkage, c, "llvm.dbg.derivedtype", gIR->module); + gv->setSection("llvm.metadata"); + return gv; } ////////////////////////////////////////////////////////////////////////////////////////////////// -LLGlobalVariable* DtoDwarfVariable(VarDeclaration* vd, LLGlobalVariable* typeDescr) +static LLGlobalVariable* DtoDwarfVariable(VarDeclaration* vd, LLGlobalVariable* typeDescr) { unsigned tag; if (vd->isParameter()) @@ -302,10 +365,60 @@ LLGlobalVariable* DtoDwarfVariable(VarDeclaration* vd, LLGlobalVariable* typeDes ////////////////////////////////////////////////////////////////////////////////////////////////// -void DtoDwarfDeclare(LLValue* var, LLGlobalVariable* varDescr) +static void DtoDwarfDeclare(LLValue* var, LLGlobalVariable* varDescr) { LLSmallVector args; args.push_back(DtoBitCast(var, dbgArrTy())); args.push_back(dbgToArrTy(varDescr)); gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.declare"), args.begin(), args.end()); } + +////////////////////////////////////////////////////////////////////////////////////////////////// + +static LLGlobalVariable* DtoDwarfTypeDescription(Loc loc, Type* type, LLGlobalVariable* cu) +{ + Type* t = type->toBasetype(); + if (t->isintegral() || t->isfloating()) + return DtoDwarfBasicType(type, cu); + else if (t->ty == Tpointer) + return DtoDwarfDerivedType(loc, type, cu); + + Logger::attention(loc, "unsupport type for debug info: %s", type->toChars()); + return NULL; +} + +void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd) +{ + // get compile units + LLGlobalVariable* thisCU = DtoDwarfCompileUnit(gIR->dmodule); + LLGlobalVariable* varCU = thisCU; + if (vd->getModule() != gIR->dmodule) + varCU = DtoDwarfCompileUnit(vd->getModule()); + + // get type description + Type* t = vd->type->toBasetype(); + LLGlobalVariable* TD = DtoDwarfTypeDescription(vd->loc, vd->type, thisCU); + if (TD == NULL) + return; // unsupported + + // get variable description + LLGlobalVariable* VD; + VD = DtoDwarfVariable(vd, TD); + + // declare + DtoDwarfDeclare(ll, VD); +} + + + + + + + + + + + + + + diff --git a/gen/todebug.h b/gen/todebug.h index 85c26cdf..8198876a 100644 --- a/gen/todebug.h +++ b/gen/todebug.h @@ -3,10 +3,6 @@ void RegisterDwarfSymbols(llvm::Module* mod); -const llvm::StructType* GetDwarfAnchorType(); -const llvm::StructType* GetDwarfCompileUnitType(); -const llvm::StructType* GetDwarfSubProgramType(); - llvm::GlobalVariable* DtoDwarfCompileUnit(Module* m); llvm::GlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd, llvm::GlobalVariable* compileUnit); @@ -15,12 +11,12 @@ void DtoDwarfFuncEnd(FuncDeclaration* fd); void DtoDwarfStopPoint(unsigned ln); -const llvm::StructType* GetDwarfBasicTypeType(); -LLGlobalVariable* DtoDwarfBasicType(Type* type, llvm::GlobalVariable* compileUnit); - -const llvm::StructType* GetDwarfVariableType(); -LLGlobalVariable* DtoDwarfVariable(VarDeclaration* vd, LLGlobalVariable* typeDescr); -void DtoDwarfDeclare(LLValue* var, LLGlobalVariable* varDescr); +/** + * 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. + */ +void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd); #endif // LLVMDC_GEN_TODEBUG_H diff --git a/gen/toir.cpp b/gen/toir.cpp index 8c11e56a..66bf9f70 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -78,12 +78,9 @@ DValue* DeclarationExp::toElem(IRState* p) vd->ir.irLocal = new IrLocal(vd); vd->ir.irLocal->value = allocainst; - if (global.params.symdebug && (vd->type->isintegral() || vd->type->isfloating())) + if (global.params.symdebug) { - LLGlobalVariable* cu = DtoDwarfCompileUnit(vd->getModule()); - LLGlobalVariable* bt = DtoDwarfBasicType(vd->type, cu); - LLGlobalVariable* vdesc = DtoDwarfVariable(vd, bt); - DtoDwarfDeclare(allocainst, vdesc); + DtoDwarfLocalVariable(allocainst, vd); } } diff --git a/llvmdc.kdevelop.filelist b/llvmdc.kdevelop.filelist index 09698010..a4975bfa 100644 --- a/llvmdc.kdevelop.filelist +++ b/llvmdc.kdevelop.filelist @@ -765,6 +765,10 @@ tangotests/c.d tangotests/classes1.d tangotests/constructors.d tangotests/debug1.d +tangotests/debug2.d +tangotests/debug3.d +tangotests/debug4.d +tangotests/debug5.d tangotests/e.d tangotests/f.d tangotests/files1.d diff --git a/tangotests/debug1.d b/tangotests/debug1.d new file mode 100644 index 00000000..77bb16dd --- /dev/null +++ b/tangotests/debug1.d @@ -0,0 +1,17 @@ +module tangotests.debug1; + +void main() +{ + int* ptr; + + // all these should be inspectable + int i = 1; + int j = 2; + long k = 3; + float l = 4.521; + ubyte m = 5; + + *ptr = 0;//cast(int)(i+j+k+l+m); +} + +extern(C) int printf(char*, ...); diff --git a/tangotests/debug2.d b/tangotests/debug2.d new file mode 100644 index 00000000..10b1e3db --- /dev/null +++ b/tangotests/debug2.d @@ -0,0 +1,15 @@ +module tangotests.debug2; + +import tango.stdc.stdlib : rand; + +void main() +{ + size_t iter; + while (iter < 25) + { + if (rand() % 20 == 10) + *cast(int*)null = 0; + ++iter; + } + assert(0); +} diff --git a/tangotests/debug3.d b/tangotests/debug3.d new file mode 100644 index 00000000..ca0c9fbc --- /dev/null +++ b/tangotests/debug3.d @@ -0,0 +1,10 @@ +module tangotests.debug3; + +void main() +{ + int i = 42; + int* ip = &i; + + int* fail; + *fail = 0; +} diff --git a/tangotests/debug4.d b/tangotests/debug4.d new file mode 100644 index 00000000..0c52560c --- /dev/null +++ b/tangotests/debug4.d @@ -0,0 +1,11 @@ +module tangotests.debug4; + +void main() +{ + char c = 'c'; + wchar wc = 'w'; + dchar dc = 'd'; + + int* fail; + *fail = 32; +} diff --git a/tangotests/debug5.d b/tangotests/debug5.d new file mode 100644 index 00000000..9a5a1180 --- /dev/null +++ b/tangotests/debug5.d @@ -0,0 +1,15 @@ +module tangotests.debug5; + +void main() +{ + int i = 32; + real r = 3.1415; + real* p = &r; + func(i,r,p); +} + +void func(int i, real r, real* p) +{ + int* fail; + *fail = 666; +}