From b413b9aa544ecb365c2510dd707846d843eab3d8 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Sun, 12 Oct 2008 14:38:55 +0200 Subject: [PATCH] Emit stub debug info for generated functions to work around LLVM bug 2172. --- gen/todebug.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++-- gen/todebug.h | 8 ++++++++ gen/toobj.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 2 deletions(-) diff --git a/gen/todebug.cpp b/gen/todebug.cpp index a3cbd1b3..f0712f22 100644 --- a/gen/todebug.cpp +++ b/gen/todebug.cpp @@ -149,6 +149,28 @@ static LLGlobalVariable* dwarfCompileUnit(Module* m) ////////////////////////////////////////////////////////////////////////////////////////////////// +static LLGlobalVariable* dwarfSubProgram(llvm::GlobalVariable* emitUnit, llvm::GlobalVariable* defineUnit, const char* prettyname, const char* mangledname, uint linenum, bool isprivate) +{ + std::vector vals(11); + vals[0] = DBG_TAG(DW_TAG_subprogram); + vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_subprogram)); + + vals[2] = DBG_CAST(emitUnit); + vals[3] = DtoConstStringPtr(prettyname, "llvm.metadata"); + vals[4] = vals[3]; + vals[5] = DtoConstStringPtr(mangledname, "llvm.metadata"); + vals[6] = DBG_CAST(defineUnit); + vals[7] = DtoConstUint(linenum); + vals[8] = DBG_NULL; + vals[9] = DtoConstBool(isprivate); + vals[10] = DtoConstBool(emitUnit == defineUnit); + + Logger::println("emitting subprogram global"); + + return emitDwarfGlobal(getDwarfSubProgramType(), vals, "llvm.dbg.subprogram"); +} + +/* static LLGlobalVariable* dwarfSubProgram(FuncDeclaration* fd, llvm::GlobalVariable* compileUnit) { std::vector vals(11); @@ -168,7 +190,7 @@ static LLGlobalVariable* dwarfSubProgram(FuncDeclaration* fd, llvm::GlobalVariab Logger::println("emitting subprogram global"); return emitDwarfGlobal(getDwarfSubProgramType(), vals, "llvm.dbg.subprogram"); -} +}*/ ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -648,7 +670,28 @@ LLGlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd) LOG_SCOPE; // FIXME: duplicates ? - return dwarfSubProgram(fd, DtoDwarfCompileUnit(gIR->dmodule)); + return dwarfSubProgram( + DtoDwarfCompileUnit(gIR->dmodule), + DtoDwarfCompileUnit(fd->getModule()), + fd->toPrettyChars(), fd->mangle(), + fd->loc.linnum, + fd->protection == PROTprivate); +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +LLGlobalVariable* DtoDwarfSubProgramInternal(const char* prettyname, const char* mangledname) +{ + Logger::println("D to dwarf subprogram"); + LOG_SCOPE; + + // FIXME: duplicates ? + return dwarfSubProgram( + DtoDwarfCompileUnit(gIR->dmodule), + DtoDwarfCompileUnit(gIR->dmodule), + prettyname, mangledname, + 0, + true); } ////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/todebug.h b/gen/todebug.h index 75dbe932..df1e9180 100644 --- a/gen/todebug.h +++ b/gen/todebug.h @@ -17,6 +17,14 @@ llvm::GlobalVariable* DtoDwarfCompileUnit(Module* m); */ llvm::GlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd); +/** + * Emit the Dwarf subprogram global for a internal function. + * This is used for generated functions like moduleinfoctors, + * module ctors/dtors and unittests. + * @return the Dwarf subprogram global. + */ +llvm::GlobalVariable* DtoDwarfSubProgramInternal(const char* prettyname, const char* mangledname); + void DtoDwarfFuncStart(FuncDeclaration* fd); void DtoDwarfFuncEnd(FuncDeclaration* fd); diff --git a/gen/toobj.cpp b/gen/toobj.cpp index ebf97669..41a68724 100644 --- a/gen/toobj.cpp +++ b/gen/toobj.cpp @@ -449,6 +449,12 @@ void assemble(const llvm::sys::Path& asmpath, const llvm::sys::Path& objpath, ch /* ================================================================== */ + +// the following code generates functions and needs to output +// debug info. these macros are useful for that +#define DBG_TYPE ( getPtrToType(llvm::StructType::get(NULL,NULL)) ) +#define DBG_CAST(X) ( llvm::ConstantExpr::getBitCast(X, DBG_TYPE) ) + // build module ctor llvm::Function* build_module_ctor() @@ -473,12 +479,23 @@ llvm::Function* build_module_ctor() llvm::BasicBlock* bb = llvm::BasicBlock::Create("entry", fn); IRBuilder<> builder(bb); + // debug info + LLGlobalVariable* subprog; + if(global.params.symdebug) { + subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()); + builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog)); + } + for (size_t i=0; ictors[i]->ir.irFunc->func; llvm::CallInst* call = builder.CreateCall(f,""); call->setCallingConv(llvm::CallingConv::Fast); } + // debug info end + if(global.params.symdebug) + builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog)); + builder.CreateRetVoid(); return fn; } @@ -507,12 +524,23 @@ static llvm::Function* build_module_dtor() llvm::BasicBlock* bb = llvm::BasicBlock::Create("entry", fn); IRBuilder<> builder(bb); + // debug info + LLGlobalVariable* subprog; + if(global.params.symdebug) { + subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()); + builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog)); + } + for (size_t i=0; idtors[i]->ir.irFunc->func; llvm::CallInst* call = builder.CreateCall(f,""); call->setCallingConv(llvm::CallingConv::Fast); } + // debug info end + if(global.params.symdebug) + builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog)); + builder.CreateRetVoid(); return fn; } @@ -541,12 +569,23 @@ static llvm::Function* build_module_unittest() llvm::BasicBlock* bb = llvm::BasicBlock::Create("entry", fn); IRBuilder<> builder(bb); + // debug info + LLGlobalVariable* subprog; + if(global.params.symdebug) { + subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()); + builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog)); + } + for (size_t i=0; iunitTests[i]->ir.irFunc->func; llvm::CallInst* call = builder.CreateCall(f,""); call->setCallingConv(llvm::CallingConv::Fast); } + // debug info end + if(global.params.symdebug) + builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog)); + builder.CreateRetVoid(); return fn; } @@ -587,6 +626,13 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) llvm::BasicBlock* bb = llvm::BasicBlock::Create("moduleinfoCtorEntry", ctor); IRBuilder<> builder(bb); + // debug info + LLGlobalVariable* subprog; + if(global.params.symdebug) { + subprog = DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str()); + builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog)); + } + // get current beginning LLValue* curbeg = builder.CreateLoad(mref, "current"); @@ -597,6 +643,10 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) // replace beginning builder.CreateStore(thismref, mref); + // debug info end + if(global.params.symdebug) + builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog)); + // return builder.CreateRetVoid();