#include "gen/llvm.h" #include "llvm/Support/Dwarf.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/System/Path.h" #include "declaration.h" #include "module.h" #include "mars.h" #include "gen/todebug.h" #include "gen/irstate.h" #include "gen/tollvm.h" #include "gen/logger.h" #include "ir/irmodule.h" using namespace llvm::dwarf; #define DBG_NULL ( LLConstant::getNullValue(DBG_TYPE) ) #define DBG_TYPE ( getPtrToType(llvm::StructType::get(NULL,NULL)) ) #define DBG_CAST(X) ( llvm::ConstantExpr::getBitCast(X, DBG_TYPE) ) #define DBG_TAG(X) ( llvm::ConstantExpr::getAdd( DtoConstUint( X ), DtoConstUint( llvm::LLVMDebugVersion ) ) ) ////////////////////////////////////////////////////////////////////////////////////////////////// /** * Emits a global variable, LLVM Dwarf style. * @param type Type of variable. * @param values Initializers. * @param name Name. * @return The global variable. */ static LLGlobalVariable* emitDwarfGlobal(const LLStructType* type, const std::vector values, const char* name, bool linkonce=false) { LLConstant* c = llvm::ConstantStruct::get(type, values); LLGlobalValue::LinkageTypes linkage = linkonce ? LLGlobalValue::LinkOnceLinkage : LLGlobalValue::InternalLinkage; LLGlobalVariable* gv = new LLGlobalVariable(type, true, linkage, c, name, gIR->module); gv->setSection("llvm.metadata"); return gv; } /** * Emits a global variable, LLVM Dwarf style, only declares. * @param type Type of variable. * @param name Name. * @return The global variable. */ static LLGlobalVariable* emitDwarfGlobalDecl(const LLStructType* type, const char* name, bool linkonce=false) { LLGlobalValue::LinkageTypes linkage = linkonce ? LLGlobalValue::LinkOnceLinkage : LLGlobalValue::InternalLinkage; LLGlobalVariable* gv = new LLGlobalVariable(type, true, linkage, NULL, name, gIR->module); gv->setSection("llvm.metadata"); return gv; } ////////////////////////////////////////////////////////////////////////////////////////////////// /** * Emits the Dwarf anchors that are used repeatedly by LLVM debug info. */ static void emitDwarfAnchors() { const llvm::StructType* anchorTy = isaStruct(gIR->module->getTypeByName("llvm.dbg.anchor.type")); std::vector vals(2); vals[0] = DtoConstUint(llvm::LLVMDebugVersion); vals[1] = DtoConstUint(DW_TAG_compile_unit); gIR->dwarfCUs = emitDwarfGlobal(anchorTy, vals, "llvm.dbg.compile_units", true); vals[0] = DtoConstUint(llvm::LLVMDebugVersion); vals[1] = DtoConstUint(DW_TAG_variable); gIR->dwarfGVs = emitDwarfGlobal(anchorTy, vals, "llvm.dbg.global_variables", true); vals[0] = DtoConstUint(llvm::LLVMDebugVersion); vals[1] = DtoConstUint(DW_TAG_subprogram); gIR->dwarfSPs = emitDwarfGlobal(anchorTy, vals, "llvm.dbg.subprograms", true); } ////////////////////////////////////////////////////////////////////////////////////////////////// static LLConstant* getDwarfAnchor(dwarf_constants c) { if (!gIR->dwarfCUs) emitDwarfAnchors(); switch (c) { case DW_TAG_compile_unit: return gIR->dwarfCUs; case DW_TAG_variable: return gIR->dwarfGVs; case DW_TAG_subprogram: return gIR->dwarfSPs; default: assert(0); } } ////////////////////////////////////////////////////////////////////////////////////////////////// static const llvm::StructType* getDwarfCompileUnitType() { return isaStruct(gIR->module->getTypeByName("llvm.dbg.compile_unit.type")); } 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")); } static const llvm::StructType* getDwarfCompositeTypeType() { return isaStruct(gIR->module->getTypeByName("llvm.dbg.compositetype.type")); } static const llvm::StructType* getDwarfGlobalVariableType() { return isaStruct(gIR->module->getTypeByName("llvm.dbg.global_variable.type")); } ////////////////////////////////////////////////////////////////////////////////////////////////// static LLGlobalVariable* dwarfCompileUnit(Module* m) { std::vector vals(6); vals[0] = DBG_TAG(DW_TAG_compile_unit); vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_compile_unit)); vals[2] = DtoConstUint(DW_LANG_C);// _D)); // doesn't seem to work vals[3] = DtoConstStringPtr(FileName::name(m->srcfile->name->toChars()), "llvm.metadata"); std::string srcpath(FileName::path(m->srcfile->name->toChars())); if (!FileName::absolute(srcpath.c_str())) { llvm::sys::Path tmp = llvm::sys::Path::GetCurrentDirectory(); tmp.appendComponent(srcpath); srcpath = tmp.toString(); if (!srcpath.empty() && *srcpath.rbegin() != '/' && *srcpath.rbegin() != '\\') srcpath = srcpath + '/'; } vals[4] = DtoConstStringPtr(srcpath.c_str(), "llvm.metadata"); vals[5] = DtoConstStringPtr("LDC (http://www.dsource.org/projects/ldc)", "llvm.metadata"); LLGlobalVariable* gv = emitDwarfGlobal(getDwarfCompileUnitType(), vals, "llvm.dbg.compile_unit"); m->ir.irModule->dwarfCompileUnit = gv; return gv; } ////////////////////////////////////////////////////////////////////////////////////////////////// static LLGlobalVariable* dwarfSubProgram(llvm::GlobalVariable* emitUnit, llvm::GlobalVariable* defineUnit, const char* prettyname, const char* mangledname, unsigned int 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); vals[0] = DBG_TAG(DW_TAG_subprogram); vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_subprogram)); vals[2] = DBG_CAST(compileUnit); vals[3] = DtoConstStringPtr(fd->toPrettyChars(), "llvm.metadata"); vals[4] = vals[3]; vals[5] = DtoConstStringPtr(fd->mangle(), "llvm.metadata"); vals[6] = DBG_CAST( DtoDwarfCompileUnit(fd->getModule()) ); vals[7] = DtoConstUint(fd->loc.linnum); vals[8] = DBG_NULL; vals[9] = DtoConstBool(fd->protection == PROTprivate); vals[10] = DtoConstBool(fd->getModule() == gIR->dmodule); Logger::println("emitting subprogram global"); return emitDwarfGlobal(getDwarfSubProgramType(), vals, "llvm.dbg.subprogram"); }*/ ////////////////////////////////////////////////////////////////////////////////////////////////// static LLGlobalVariable* dwarfTypeDescription_impl(Type* type, LLGlobalVariable* cu, const char* c_name); static LLGlobalVariable* dwarfTypeDescription(Type* type, LLGlobalVariable* cu, const char* c_name); ////////////////////////////////////////////////////////////////////////////////////////////////// static LLGlobalVariable* dwarfBasicType(Type* type, llvm::GlobalVariable* compileUnit) { Type* t = type->toBasetype(); const LLType* T = DtoType(type); std::vector vals(10); // tag vals[0] = DBG_TAG(DW_TAG_base_type); // context vals[1] = DBG_CAST(compileUnit); // name vals[2] = DtoConstStringPtr(type->toChars(), "llvm.metadata"); // compile unit where defined vals[3] = DBG_NULL; // line number where defined vals[4] = DtoConstInt(0); // size in bits vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false); // alignment in bits vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false); // offset in bits vals[7] = LLConstantInt::get(LLType::Int64Ty, 0, false); // FIXME: dont know what this is vals[8] = DtoConstUint(0); // dwarf type unsigned id; if (t->isintegral()) { if (type->isunsigned()) id = DW_ATE_unsigned; else id = DW_ATE_signed; } else if (t->isfloating()) { id = DW_ATE_float; } else { assert(0 && "unsupported basictype for debug info"); } vals[9] = DtoConstUint(id); return emitDwarfGlobal(getDwarfBasicTypeType(), vals, "llvm.dbg.basictype"); } ////////////////////////////////////////////////////////////////////////////////////////////////// static LLGlobalVariable* dwarfDerivedType(Type* type, llvm::GlobalVariable* compileUnit) { const LLType* T = DtoType(type); Type* t = type->toBasetype(); // defaults LLConstant* name = getNullPtr(getVoidPtrType()); // find tag unsigned tag; if (t->ty == Tpointer) { tag = DW_TAG_pointer_type; } else { assert(0 && "unsupported derivedtype for debug info"); } std::vector vals(10); // tag vals[0] = DBG_TAG(tag); // context vals[1] = DBG_CAST(compileUnit); // name vals[2] = name; // compile unit where defined vals[3] = DBG_NULL; // line number where defined vals[4] = DtoConstInt(0); // size in bits vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false); // alignment in bits vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false); // offset in bits vals[7] = LLConstantInt::get(LLType::Int64Ty, 0, false); // FIXME: dont know what this is vals[8] = DtoConstUint(0); // base type Type* nt = t->nextOf(); LLGlobalVariable* nTD = dwarfTypeDescription_impl(nt, compileUnit, NULL); if (nt->ty == Tvoid || !nTD) vals[9] = DBG_NULL; else vals[9] = DBG_CAST(nTD); return emitDwarfGlobal(getDwarfDerivedTypeType(), vals, "llvm.dbg.derivedtype"); } ////////////////////////////////////////////////////////////////////////////////////////////////// static LLGlobalVariable* dwarfMemberType(unsigned linnum, Type* type, LLGlobalVariable* compileUnit, LLGlobalVariable* definedCU, const char* c_name, unsigned offset) { const LLType* T = DtoType(type); Type* t = type->toBasetype(); // defaults LLConstant* name; if (c_name) name = DtoConstStringPtr(c_name, "llvm.metadata"); else name = getNullPtr(getVoidPtrType()); std::vector vals(10); // tag vals[0] = DBG_TAG(DW_TAG_member); // context vals[1] = DBG_CAST(compileUnit); // name vals[2] = name; // compile unit where defined if (definedCU) vals[3] = DBG_CAST(definedCU); else vals[3] = DBG_NULL; // line number where defined vals[4] = DtoConstInt(linnum); // size in bits vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false); // alignment in bits vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false); // offset in bits vals[7] = LLConstantInt::get(LLType::Int64Ty, offset*8, false); // FIXME: dont know what this is vals[8] = DtoConstUint(0); // base type LLGlobalVariable* nTD = dwarfTypeDescription(t, compileUnit, NULL); if (t->ty == Tvoid || !nTD) vals[9] = DBG_NULL; else vals[9] = DBG_CAST(nTD); return emitDwarfGlobal(getDwarfDerivedTypeType(), vals, "llvm.dbg.derivedtype"); } ////////////////////////////////////////////////////////////////////////////////////////////////// static LLGlobalVariable* dwarfCompositeType(Type* type, llvm::GlobalVariable* compileUnit) { const LLType* T = DtoType(type); Type* t = type->toBasetype(); // defaults LLConstant* name = getNullPtr(getVoidPtrType()); LLGlobalVariable* members = NULL; unsigned linnum = 0; LLGlobalVariable* definedCU = NULL; // prepare tag and members unsigned tag; // declare final global variable LLGlobalVariable* gv = NULL; // dynamic array if (t->ty == Tarray) { tag = DW_TAG_structure_type; LLGlobalVariable* len = dwarfMemberType(0, Type::tsize_t, compileUnit, NULL, "length", 0); assert(len); LLGlobalVariable* ptr = dwarfMemberType(0, t->nextOf()->pointerTo(), compileUnit, NULL, "ptr", global.params.is64bit?8:4); assert(ptr); const LLArrayType* at = LLArrayType::get(DBG_TYPE, 2); std::vector elems(2); elems[0] = DBG_CAST(len); elems[1] = DBG_CAST(ptr); LLConstant* ca = LLConstantArray::get(at, elems); members = new LLGlobalVariable(ca->getType(), true, LLGlobalValue::InternalLinkage, ca, ".array", gIR->module); members->setSection("llvm.metadata"); name = DtoConstStringPtr(t->toChars(), "llvm.metadata"); } // struct/class else if (t->ty == Tstruct || t->ty == Tclass) { AggregateDeclaration* sd; if (t->ty == Tstruct) { TypeStruct* ts = (TypeStruct*)t; sd = ts->sym; } else { TypeClass* tc = (TypeClass*)t; sd = tc->sym; } assert(sd); IrStruct* ir = sd->ir.irStruct; assert(ir); if (ir->dwarfComposite) return ir->dwarfComposite; // set to handle recursive types properly gv = emitDwarfGlobalDecl(getDwarfCompositeTypeType(), "llvm.dbg.compositetype"); ir->dwarfComposite = gv; tag = DW_TAG_structure_type; name = DtoConstStringPtr(sd->toChars(), "llvm.metadata"); linnum = sd->loc.linnum; definedCU = DtoDwarfCompileUnit(sd->getModule()); std::vector elems; if (!ir->aggrdecl->isInterfaceDeclaration()) // plain interfaces don't have one { std::vector& arr = ir->varDecls; size_t narr = arr.size(); elems.reserve(narr); for (int k=0; kloc.linnum, vd->type, compileUnit, definedCU, vd->toChars(), vd->offset); elems.push_back(DBG_CAST(ptr)); } } const LLArrayType* at = LLArrayType::get(DBG_TYPE, elems.size()); LLConstant* ca = LLConstantArray::get(at, elems); members = new LLGlobalVariable(ca->getType(), true, LLGlobalValue::InternalLinkage, ca, ".array", gIR->module); members->setSection("llvm.metadata"); } // unsupported composite type else { assert(0 && "unsupported compositetype for debug info"); } std::vector vals(11); // tag vals[0] = DBG_TAG(tag); // context vals[1] = DBG_CAST(compileUnit); // name vals[2] = name; // compile unit where defined if (definedCU) vals[3] = DBG_CAST(definedCU); else vals[3] = DBG_NULL; // line number where defined vals[4] = DtoConstInt(linnum); // size in bits vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false); // alignment in bits vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false); // offset in bits vals[7] = LLConstantInt::get(LLType::Int64Ty, 0, false); // FIXME: dont know what this is vals[8] = DtoConstUint(0); // FIXME: ditto vals[9] = DBG_NULL; // members array if (members) vals[10] = DBG_CAST(members); else vals[10] = DBG_NULL; // set initializer if (!gv) gv = emitDwarfGlobalDecl(getDwarfCompositeTypeType(), "llvm.dbg.compositetype"); LLConstant* initia = LLConstantStruct::get(getDwarfCompositeTypeType(), vals); gv->setInitializer(initia); return gv; } ////////////////////////////////////////////////////////////////////////////////////////////////// static LLGlobalVariable* dwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd) { assert(vd->isDataseg()); LLGlobalVariable* compileUnit = DtoDwarfCompileUnit(gIR->dmodule); std::vector vals(12); vals[0] = DBG_TAG(DW_TAG_variable); vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_variable)); vals[2] = DBG_CAST(compileUnit); vals[3] = DtoConstStringPtr(vd->mangle(), "llvm.metadata"); vals[4] = DtoConstStringPtr(vd->toPrettyChars(), "llvm.metadata"); vals[5] = DtoConstStringPtr(vd->toChars(), "llvm.metadata"); vals[6] = DBG_CAST(DtoDwarfCompileUnit(vd->getModule())); vals[7] = DtoConstUint(vd->loc.linnum); LLGlobalVariable* TY = dwarfTypeDescription_impl(vd->type, compileUnit, NULL); vals[8] = TY ? DBG_CAST(TY) : DBG_NULL; vals[9] = DtoConstBool(vd->protection == PROTprivate); vals[10] = DtoConstBool(vd->getModule() == gIR->dmodule); vals[11] = DBG_CAST(ll); return emitDwarfGlobal(getDwarfGlobalVariableType(), vals, "llvm.dbg.global_variable"); } ////////////////////////////////////////////////////////////////////////////////////////////////// static LLGlobalVariable* dwarfVariable(VarDeclaration* vd, LLGlobalVariable* typeDescr) { assert(!vd->isDataseg() && "static variable"); unsigned tag; if (vd->isParameter()) tag = DW_TAG_arg_variable; else tag = DW_TAG_auto_variable; std::vector vals(6); // tag vals[0] = DBG_TAG(tag); // context vals[1] = DBG_CAST(gIR->func()->dwarfSubProg); // name vals[2] = DtoConstStringPtr(vd->toChars(), "llvm.metadata"); // compile unit where defined vals[3] = DBG_CAST(DtoDwarfCompileUnit(vd->getModule())); // line number where defined vals[4] = DtoConstUint(vd->loc.linnum); // type descriptor vals[5] = DBG_CAST(typeDescr); return emitDwarfGlobal(getDwarfVariableType(), vals, "llvm.dbg.variable"); } ////////////////////////////////////////////////////////////////////////////////////////////////// static void dwarfDeclare(LLValue* var, LLGlobalVariable* varDescr) { LLSmallVector args(2); args[0] = DtoBitCast(var, DBG_TYPE); args[1] = DBG_CAST(varDescr); gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.declare"), args.begin(), args.end()); } ////////////////////////////////////////////////////////////////////////////////////////////////// static LLGlobalVariable* dwarfTypeDescription_impl(Type* type, LLGlobalVariable* cu, const char* c_name) { Type* t = type->toBasetype(); if (t->ty == Tvoid) return NULL; else if (t->isintegral() || t->isfloating()) return dwarfBasicType(type, cu); else if (t->ty == Tpointer) return dwarfDerivedType(type, cu); else if (t->ty == Tarray || t->ty == Tstruct || t->ty == Tclass) return dwarfCompositeType(type, cu); return NULL; } static LLGlobalVariable* dwarfTypeDescription(Type* type, LLGlobalVariable* cu, const char* c_name) { Type* t = type->toBasetype(); if (t->ty == Tclass) return dwarfTypeDescription_impl(type->pointerTo(), cu, c_name); else return dwarfTypeDescription_impl(type, cu, c_name); } ////////////////////////////////////////////////////////////////////////////////////////////////// void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd) { Logger::println("D to dwarf local variable"); LOG_SCOPE; // 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 = dwarfTypeDescription(vd->type, thisCU, NULL); if (TD == NULL) return; // unsupported // get variable description LLGlobalVariable* VD; VD = dwarfVariable(vd, TD); // declare dwarfDeclare(ll, VD); } ////////////////////////////////////////////////////////////////////////////////////////////////// LLGlobalVariable* DtoDwarfCompileUnit(Module* m) { Logger::println("D to dwarf compile_unit"); LOG_SCOPE; // we might be generating for an import if (!m->ir.irModule) m->ir.irModule = new IrModule(m, m->srcfile->toChars()); else if (m->ir.irModule->dwarfCompileUnit) { if (m->ir.irModule->dwarfCompileUnit->getParent() == gIR->module) return m->ir.irModule->dwarfCompileUnit; } LLGlobalVariable* gv = dwarfCompileUnit(m); m->ir.irModule->dwarfCompileUnit = gv; return gv; } ////////////////////////////////////////////////////////////////////////////////////////////////// LLGlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd) { Logger::println("D to dwarf subprogram"); LOG_SCOPE; // FIXME: duplicates ? 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); } ////////////////////////////////////////////////////////////////////////////////////////////////// LLGlobalVariable* DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd) { Logger::println("D to dwarf global_variable"); LOG_SCOPE; // FIXME: duplicates ? return dwarfGlobalVariable(ll, vd); } ////////////////////////////////////////////////////////////////////////////////////////////////// void DtoDwarfFuncStart(FuncDeclaration* fd) { Logger::println("D to dwarf funcstart"); LOG_SCOPE; assert(fd->ir.irFunc->dwarfSubProg); gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(fd->ir.irFunc->dwarfSubProg)); } ////////////////////////////////////////////////////////////////////////////////////////////////// void DtoDwarfFuncEnd(FuncDeclaration* fd) { Logger::println("D to dwarf funcend"); LOG_SCOPE; assert(fd->ir.irFunc->dwarfSubProg); gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(fd->ir.irFunc->dwarfSubProg)); } ////////////////////////////////////////////////////////////////////////////////////////////////// void DtoDwarfStopPoint(unsigned ln) { Logger::println("D to dwarf stoppoint at line %u", ln); LOG_SCOPE; LLSmallVector args(3); args[0] = DtoConstUint(ln); args[1] = DtoConstUint(0); FuncDeclaration* fd = gIR->func()->decl; args[2] = DBG_CAST(DtoDwarfCompileUnit(fd->getModule())); gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.stoppoint"), args.begin(), args.end()); }