Mercurial > projects > ldc
changeset 82:d8dd47ef3973 trunk
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
Initial support for debug information. Very limited, but MUCH better than nothing :)
author | lindquist |
---|---|
date | Fri, 02 Nov 2007 01:17:26 +0100 |
parents | 3587401b6eeb |
children | 339422268de1 |
files | demos/readme.txt dmd/declaration.c dmd/declaration.h dmd/expression.c dmd/func.c gen/dwarftypes.c gen/irstate.c gen/irstate.h gen/statements.c gen/todebug.c gen/todebug.h gen/toir.c gen/tollvm.c gen/tollvm.h gen/toobj.c test/bug47.d test/fail1.d |
diffstat | 17 files changed, 507 insertions(+), 66 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demos/readme.txt Fri Nov 02 01:17:26 2007 +0100 @@ -0,0 +1,1 @@ +use rebuild with -dc=llvmdc-posix to build the demos
--- a/dmd/declaration.c Thu Nov 01 17:27:18 2007 +0100 +++ b/dmd/declaration.c Fri Nov 02 01:17:26 2007 +0100 @@ -552,6 +552,7 @@ llvmNestedIndex = -1; llvmFieldIndex = -1; llvmFieldIndexOffset = 0; + llvmNeedsStorage = false; } Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
--- a/dmd/declaration.h Thu Nov 01 17:27:18 2007 +0100 +++ b/dmd/declaration.h Fri Nov 02 01:17:26 2007 +0100 @@ -262,6 +262,7 @@ int llvmNestedIndex; int llvmFieldIndex; size_t llvmFieldIndexOffset; + bool llvmNeedsStorage; }; /**************************************************************/ @@ -525,6 +526,7 @@ llvm::Value* llvmNested; llvm::Value* llvmArguments; llvm::Value* llvmArgPtr; + llvm::Constant* llvmDwarfSubProgram; }; struct FuncAliasDeclaration : FuncDeclaration
--- a/dmd/expression.c Thu Nov 01 17:27:18 2007 +0100 +++ b/dmd/expression.c Fri Nov 02 01:17:26 2007 +0100 @@ -3445,7 +3445,10 @@ type = var->type->pointerTo(); VarDeclaration *v = var->isVarDeclaration(); if (v) - v->checkNestedReference(sc, loc); + { + v->checkNestedReference(sc, loc); + v->llvmNeedsStorage = true; + } return this; } @@ -3589,6 +3592,7 @@ if (v && v->canassign == 0 && (var->isConst() || (global.params.Dversion > 1 && var->isFinal()))) error("cannot modify final variable '%s'", var->toChars()); + v->llvmNeedsStorage = true; if (var->isCtorinit()) { // It's only modifiable if inside the right constructor
--- a/dmd/func.c Thu Nov 01 17:27:18 2007 +0100 +++ b/dmd/func.c Fri Nov 02 01:17:26 2007 +0100 @@ -78,6 +78,7 @@ llvmNested = NULL; llvmArguments = NULL; llvmArgPtr = NULL; + llvmDwarfSubProgram = NULL; } Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/dwarftypes.c Fri Nov 02 01:17:26 2007 +0100 @@ -0,0 +1,187 @@ +// Generated by llvm2cpp - DO NOT MODIFY! + +#include <llvm/Module.h> +#include <llvm/DerivedTypes.h> +#include <llvm/Constants.h> +#include <llvm/GlobalVariable.h> +#include <llvm/Function.h> +#include <llvm/CallingConv.h> +#include <llvm/BasicBlock.h> +#include <llvm/Instructions.h> +#include <llvm/InlineAsm.h> +#include <llvm/ParameterAttributes.h> +#include <llvm/Support/MathExtras.h> +#include <llvm/Pass.h> +#include <llvm/PassManager.h> +#include <llvm/Analysis/Verifier.h> +#include <llvm/Assembly/PrintModulePass.h> +#include <algorithm> +#include <iostream> + +void RegisterDwarfSymbols(llvm::Module* mod) { + using namespace llvm; + // Type Definitions + std::vector<const Type*>StructTy_llvm_dbg_anchor_type_fields; + StructTy_llvm_dbg_anchor_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_anchor_type_fields.push_back(IntegerType::get(32)); + StructType* StructTy_llvm_dbg_anchor_type = StructType::get(StructTy_llvm_dbg_anchor_type_fields, /*isPacked=*/false); + mod->addTypeName("llvm.dbg.anchor.type", StructTy_llvm_dbg_anchor_type); + + std::vector<const Type*>StructTy_llvm_dbg_basictype_type_fields; + StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(32)); + std::vector<const Type*>StructTy_1_fields; + StructType* StructTy_1 = StructType::get(StructTy_1_fields, /*isPacked=*/false); + + PointerType* PointerTy_0 = PointerType::get(StructTy_1); + + StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_0); + PointerType* PointerTy_2 = PointerType::get(IntegerType::get(8)); + + StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_2); + StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(64)); + StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(64)); + StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(64)); + StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(32)); + StructType* StructTy_llvm_dbg_basictype_type = StructType::get(StructTy_llvm_dbg_basictype_type_fields, /*isPacked=*/false); + mod->addTypeName("llvm.dbg.basictype.type", StructTy_llvm_dbg_basictype_type); + + std::vector<const Type*>StructTy_llvm_dbg_compile_unit_type_fields; + StructTy_llvm_dbg_compile_unit_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_compile_unit_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_compile_unit_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_compile_unit_type_fields.push_back(PointerTy_2); + StructTy_llvm_dbg_compile_unit_type_fields.push_back(PointerTy_2); + StructTy_llvm_dbg_compile_unit_type_fields.push_back(PointerTy_2); + StructType* StructTy_llvm_dbg_compile_unit_type = StructType::get(StructTy_llvm_dbg_compile_unit_type_fields, /*isPacked=*/false); + mod->addTypeName("llvm.dbg.compile_unit.type", StructTy_llvm_dbg_compile_unit_type); + + std::vector<const Type*>StructTy_llvm_dbg_compositetype_type_fields; + StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_2); + StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(64)); + StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(64)); + StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(64)); + StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_0); + StructType* StructTy_llvm_dbg_compositetype_type = StructType::get(StructTy_llvm_dbg_compositetype_type_fields, /*isPacked=*/false); + mod->addTypeName("llvm.dbg.compositetype.type", StructTy_llvm_dbg_compositetype_type); + + std::vector<const Type*>StructTy_llvm_dbg_derivedtype_type_fields; + StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_derivedtype_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_derivedtype_type_fields.push_back(PointerTy_2); + StructTy_llvm_dbg_derivedtype_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(64)); + StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(64)); + StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(64)); + StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_derivedtype_type_fields.push_back(PointerTy_0); + StructType* StructTy_llvm_dbg_derivedtype_type = StructType::get(StructTy_llvm_dbg_derivedtype_type_fields, /*isPacked=*/false); + mod->addTypeName("llvm.dbg.derivedtype.type", StructTy_llvm_dbg_derivedtype_type); + + std::vector<const Type*>StructTy_llvm_dbg_global_variable_type_fields; + StructTy_llvm_dbg_global_variable_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_2); + StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_2); + StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_2); + StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_global_variable_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_global_variable_type_fields.push_back(IntegerType::get(1)); + StructTy_llvm_dbg_global_variable_type_fields.push_back(IntegerType::get(1)); + StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0); + StructType* StructTy_llvm_dbg_global_variable_type = StructType::get(StructTy_llvm_dbg_global_variable_type_fields, /*isPacked=*/false); + mod->addTypeName("llvm.dbg.global_variable.type", StructTy_llvm_dbg_global_variable_type); + + std::vector<const Type*>StructTy_llvm_dbg_subprogram_type_fields; + StructTy_llvm_dbg_subprogram_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_2); + StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_2); + StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_2); + StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_subprogram_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_subprogram_type_fields.push_back(IntegerType::get(1)); + StructTy_llvm_dbg_subprogram_type_fields.push_back(IntegerType::get(1)); + StructType* StructTy_llvm_dbg_subprogram_type = StructType::get(StructTy_llvm_dbg_subprogram_type_fields, /*isPacked=*/false); + mod->addTypeName("llvm.dbg.subprogram.type", StructTy_llvm_dbg_subprogram_type); + + std::vector<const Type*>StructTy_llvm_dbg_variable_type_fields; + StructTy_llvm_dbg_variable_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_variable_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_variable_type_fields.push_back(PointerTy_2); + StructTy_llvm_dbg_variable_type_fields.push_back(PointerTy_0); + StructTy_llvm_dbg_variable_type_fields.push_back(IntegerType::get(32)); + StructTy_llvm_dbg_variable_type_fields.push_back(PointerTy_0); + StructType* StructTy_llvm_dbg_variable_type = StructType::get(StructTy_llvm_dbg_variable_type_fields, /*isPacked=*/false); + mod->addTypeName("llvm.dbg.variable.type", StructTy_llvm_dbg_variable_type); + + std::vector<const Type*>FuncTy_3_args; + FuncTy_3_args.push_back(PointerTy_0); + ParamAttrsList *FuncTy_3_PAL = 0; + FunctionType* FuncTy_3 = FunctionType::get( + /*Result=*/Type::VoidTy, + /*Params=*/FuncTy_3_args, + /*isVarArg=*/false, + /*ParamAttrs=*/FuncTy_3_PAL); + + std::vector<const Type*>FuncTy_4_args; + FuncTy_4_args.push_back(IntegerType::get(32)); + FuncTy_4_args.push_back(IntegerType::get(32)); + FuncTy_4_args.push_back(PointerTy_0); + ParamAttrsList *FuncTy_4_PAL = 0; + FunctionType* FuncTy_4 = FunctionType::get( + /*Result=*/Type::VoidTy, + /*Params=*/FuncTy_4_args, + /*isVarArg=*/false, + /*ParamAttrs=*/FuncTy_4_PAL); + + std::vector<const Type*>FuncTy_5_args; + FuncTy_5_args.push_back(PointerTy_0); + FuncTy_5_args.push_back(PointerTy_0); + ParamAttrsList *FuncTy_5_PAL = 0; + FunctionType* FuncTy_5 = FunctionType::get( + /*Result=*/Type::VoidTy, + /*Params=*/FuncTy_5_args, + /*isVarArg=*/false, + /*ParamAttrs=*/FuncTy_5_PAL); + + + // Function Declarations + + Function* func_llvm_dbg_func_start = new Function( + /*Type=*/FuncTy_3, + /*Linkage=*/GlobalValue::ExternalLinkage, + /*Name=*/"llvm.dbg.func.start", mod); // (external, no body) + func_llvm_dbg_func_start->setCallingConv(CallingConv::C); + + Function* func_llvm_dbg_stoppoint = new Function( + /*Type=*/FuncTy_4, + /*Linkage=*/GlobalValue::ExternalLinkage, + /*Name=*/"llvm.dbg.stoppoint", mod); // (external, no body) + func_llvm_dbg_stoppoint->setCallingConv(CallingConv::C); + + Function* func_llvm_dbg_declare = new Function( + /*Type=*/FuncTy_5, + /*Linkage=*/GlobalValue::ExternalLinkage, + /*Name=*/"llvm.dbg.declare", mod); // (external, no body) + func_llvm_dbg_declare->setCallingConv(CallingConv::C); + + Function* func_llvm_dbg_region_end = new Function( + /*Type=*/FuncTy_3, + /*Linkage=*/GlobalValue::ExternalLinkage, + /*Name=*/"llvm.dbg.region.end", mod); // (external, no body) + func_llvm_dbg_region_end->setCallingConv(CallingConv::C); +}
--- a/gen/irstate.c Thu Nov 01 17:27:18 2007 +0100 +++ b/gen/irstate.c Fri Nov 02 01:17:26 2007 +0100 @@ -38,6 +38,7 @@ emitMain = false; mainFunc = 0; ir.state = this; + dwarfCompileUnit = 0; } IRFunction& IRState::func()
--- a/gen/irstate.h Thu Nov 01 17:27:18 2007 +0100 +++ b/gen/irstate.h Fri Nov 02 01:17:26 2007 +0100 @@ -162,6 +162,9 @@ // builder helper IRBuilderHelper ir; + + // Dwarf debugging info + llvm::GlobalVariable* dwarfCompileUnit; }; #endif // LLVMDC_GEN_IRSTATE_H
--- a/gen/statements.c Thu Nov 01 17:27:18 2007 +0100 +++ b/gen/statements.c Fri Nov 02 01:17:26 2007 +0100 @@ -22,6 +22,7 @@ #include "gen/tollvm.h" #include "gen/runtime.h" #include "gen/arrays.h" +#include "gen/todebug.h" ////////////////////////////////////////////////////////////////////////////// @@ -63,6 +64,8 @@ TypeFunction* f = p->topfunctype(); assert(f->llvmRetInPtr && f->llvmRetArg); + if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum); + p->exps.push_back(IRExp(NULL,exp,f->llvmRetArg)); elem* e = exp->toElem(p); p->exps.pop_back(); @@ -93,14 +96,17 @@ assert(0); IRFunction::FinallyVec& fin = p->func().finallys; - if (fin.empty()) + if (fin.empty()) { + if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl); new llvm::ReturnInst(p->scopebb()); + } else { new llvm::BranchInst(fin.back().retbb, p->scopebb()); } delete e; } else { + if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum); elem* e = exp->toElem(p); llvm::Value* v = e->getValue(); delete e; @@ -108,6 +114,7 @@ IRFunction::FinallyVec& fin = p->func().finallys; if (fin.empty()) { + if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl); new llvm::ReturnInst(v, p->scopebb()); } else { @@ -124,6 +131,7 @@ if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) { IRFunction::FinallyVec& fin = p->func().finallys; if (fin.empty()) { + if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl); new llvm::ReturnInst(p->scopebb()); } else { @@ -145,6 +153,9 @@ Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars()); LOG_SCOPE; + if (global.params.symdebug) + DtoDwarfStopPoint(loc.linnum); + if (exp != 0) { elem* e = exp->toElem(p); delete e; @@ -473,6 +484,7 @@ // no outer else { + if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl); llvm::Value* retval = p->func().finallyretval; if (retval) { retval = p->ir->CreateLoad(retval,"tmp");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/todebug.c Fri Nov 02 01:17:26 2007 +0100 @@ -0,0 +1,183 @@ +#include "gen/llvm.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/CodeGen/MachineModuleInfo.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" + +using namespace llvm::dwarf; + +static const llvm::PointerType* ptrTy(const llvm::Type* t) +{ + return llvm::PointerType::get(t); +} + +static const llvm::PointerType* dbgArrTy() +{ + std::vector<const llvm::Type*> t; + return ptrTy(llvm::StructType::get(t)); +} + +static llvm::Constant* dbgToArrTy(llvm::Constant* c) +{ + Logger::cout() << "casting: " << *c << '\n'; + return llvm::ConstantExpr::getBitCast(c, dbgArrTy()); +} + +#define Ty(X) llvm::Type::X + +////////////////////////////////////////////////////////////////////////////////////////////////// + +static llvm::GlobalVariable* dbg_compile_units = 0; +static llvm::GlobalVariable* dbg_global_variables = 0; +static llvm::GlobalVariable* dbg_subprograms = 0; + +const llvm::StructType* GetDwarfAnchorType() +{ + /* + %llvm.dbg.anchor.type = type { + uint, ;; Tag = 0 + LLVMDebugVersion + uint ;; Tag of descriptors grouped by the anchor + } + */ + std::vector<const llvm::Type*> elems(2, Ty(Int32Ty)); + const llvm::StructType* t = llvm::cast<llvm::StructType>(gIR->module->getTypeByName("llvm.dbg.anchor.type")); + + /* + %llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { uint 0, uint 17 } ;; DW_TAG_compile_unit + %llvm.dbg.global_variables = linkonce constant %llvm.dbg.anchor.type { uint 0, uint 52 } ;; DW_TAG_variable + %llvm.dbg.subprograms = linkonce constant %llvm.dbg.anchor.type { uint 0, uint 46 } ;; DW_TAG_subprogram + */ + if (!gIR->module->getNamedGlobal("llvm.dbg.compile_units")) { + std::vector<llvm::Constant*> vals; + vals.push_back(DtoConstUint(0)); + vals.push_back(DtoConstUint(DW_TAG_compile_unit)); + llvm::Constant* i = llvm::ConstantStruct::get(t, vals); + dbg_compile_units = new llvm::GlobalVariable(t,true,llvm::GlobalValue::LinkOnceLinkage,i,"llvm.dbg.compile_units",gIR->module); + dbg_compile_units->setSection("llvm.metadata"); + } + if (!gIR->module->getNamedGlobal("llvm.dbg.global_variables")) { + std::vector<llvm::Constant*> vals; + vals.push_back(DtoConstUint(0)); + vals.push_back(DtoConstUint(DW_TAG_variable)); + llvm::Constant* i = llvm::ConstantStruct::get(t, vals); + dbg_global_variables = new llvm::GlobalVariable(t,true,llvm::GlobalValue::LinkOnceLinkage,i,"llvm.dbg.global_variables",gIR->module); + dbg_global_variables->setSection("llvm.metadata"); + } + if (!gIR->module->getNamedGlobal("llvm.dbg.subprograms")) { + std::vector<llvm::Constant*> vals; + vals.push_back(DtoConstUint(0)); + vals.push_back(DtoConstUint(DW_TAG_subprogram)); + llvm::Constant* i = llvm::ConstantStruct::get(t, vals); + dbg_subprograms = new llvm::GlobalVariable(t,true,llvm::GlobalValue::LinkOnceLinkage,i,"llvm.dbg.subprograms",gIR->module); + dbg_subprograms->setSection("llvm.metadata"); + } + + return t; +} + +llvm::Constant* GetDwarfAnchor(llvm::dwarf::dwarf_constants c) +{ + GetDwarfAnchorType(); + switch (c) + { + case DW_TAG_compile_unit: + return dbg_compile_units; + case DW_TAG_variable: + return dbg_global_variables; + case DW_TAG_subprogram: + return dbg_subprograms; + } + assert(0); + return 0; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +const llvm::StructType* GetDwarfCompileUnitType() { + return llvm::cast<llvm::StructType>(gIR->module->getTypeByName("llvm.dbg.compile_unit.type")); +} + +const llvm::StructType* GetDwarfSubProgramType() { + return llvm::cast<llvm::StructType>(gIR->module->getTypeByName("llvm.dbg.subprogram.type")); +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +llvm::GlobalVariable* DtoDwarfCompileUnit(Module* m) +{ + std::vector<llvm::Constant*> vals; + vals.push_back(llvm::ConstantExpr::getAdd( + DtoConstUint(DW_TAG_compile_unit), + DtoConstUint(llvm::LLVMDebugVersion))); + vals.push_back(dbgToArrTy(GetDwarfAnchor(DW_TAG_compile_unit))); + + vals.push_back(DtoConstUint(DW_LANG_D)); + vals.push_back(DtoConstStringPtr(m->srcfile->name->toChars(), "llvm.metadata")); + std::string srcpath(FileName::path(m->srcfile->name->toChars())); + srcpath.append("/"); + vals.push_back(DtoConstStringPtr(srcpath.c_str(), "llvm.metadata")); + vals.push_back(DtoConstStringPtr("LLVMDC (http://www.dsource.org/projects/llvmdc)", "llvm.metadata")); + + llvm::Constant* c = llvm::ConstantStruct::get(GetDwarfCompileUnitType(), vals); + llvm::GlobalVariable* gv = new llvm::GlobalVariable(c->getType(), true, llvm::GlobalValue::InternalLinkage, c, "llvm.dbg.compile_unit", gIR->module); + gv->setSection("llvm.metadata"); + return gv; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +llvm::GlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd) +{ + std::vector<llvm::Constant*> vals; + vals.push_back(llvm::ConstantExpr::getAdd( + DtoConstUint(DW_TAG_subprogram), + DtoConstUint(llvm::LLVMDebugVersion))); + vals.push_back(dbgToArrTy(GetDwarfAnchor(DW_TAG_subprogram))); + + vals.push_back(dbgToArrTy(gIR->dwarfCompileUnit)); + vals.push_back(DtoConstStringPtr(fd->toPrettyChars(), "llvm.metadata")); + vals.push_back(DtoConstStringPtr(fd->mangle(), "llvm.metadata")); + vals.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); + vals.push_back(dbgToArrTy(gIR->dwarfCompileUnit)); + vals.push_back(DtoConstUint(fd->loc.linnum)); + vals.push_back(llvm::ConstantPointerNull::get(dbgArrTy())); + vals.push_back(DtoConstBool(fd->protection == PROTprivate)); + vals.push_back(DtoConstBool(fd->getModule() == gIR->dmodule)); + + llvm::Constant* c = llvm::ConstantStruct::get(GetDwarfSubProgramType(), vals); + llvm::GlobalVariable* gv = new llvm::GlobalVariable(c->getType(), true, llvm::GlobalValue::InternalLinkage, c, "llvm.dbg.subprogram", gIR->module); + gv->setSection("llvm.metadata"); + return gv; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +void DtoDwarfFuncStart(FuncDeclaration* fd) +{ + assert(fd->llvmDwarfSubProgram); + gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), dbgToArrTy(fd->llvmDwarfSubProgram)); +} + +void DtoDwarfFuncEnd(FuncDeclaration* fd) +{ + assert(fd->llvmDwarfSubProgram); + gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), dbgToArrTy(fd->llvmDwarfSubProgram)); +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +void DtoDwarfStopPoint(unsigned ln) +{ + std::vector<llvm::Value*> args; + args.push_back(DtoConstUint(ln)); + args.push_back(DtoConstUint(0)); + args.push_back(dbgToArrTy(gIR->dwarfCompileUnit)); + gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.stoppoint"), args.begin(), args.end()); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/todebug.h Fri Nov 02 01:17:26 2007 +0100 @@ -0,0 +1,20 @@ +#ifndef LLVMDC_GEN_TODEBUG_H +#define LLVMDC_GEN_TODEBUG_H + +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); + +void DtoDwarfFuncStart(FuncDeclaration* fd); +void DtoDwarfFuncEnd(FuncDeclaration* fd); + +void DtoDwarfStopPoint(unsigned ln); + +#endif // LLVMDC_GEN_TODEBUG_H + +
--- a/gen/toir.c Thu Nov 01 17:27:18 2007 +0100 +++ b/gen/toir.c Fri Nov 02 01:17:26 2007 +0100 @@ -168,29 +168,17 @@ // this happens when the DMD frontend generates by pointer wrappers for struct opEquals(S) and opCmp(S) vd->llvmValue = &p->func().func->getArgumentList().back(); } - if (vd->isRef() || vd->isOut()) { + if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa<llvm::AllocaInst>(vd->llvmValue)) { e->mem = vd->llvmValue; e->type = elem::VAR; + e->vardecl = vd; } - else { - if (DtoIsPassedByRef(vd->type)) { - e->mem = vd->llvmValue; - e->type = elem::VAR; - } - else { - if (llvm::isa<llvm::Argument>(vd->llvmValue)) { - e->val = vd->llvmValue; - e->type = elem::VAL; - e->vardecl = vd; - } - else if (llvm::isa<llvm::AllocaInst>(vd->llvmValue)) { - e->mem = vd->llvmValue; - e->type = elem::VAR; - } - else - assert(0); - } + else if (llvm::isa<llvm::Argument>(vd->llvmValue)) { + e->val = vd->llvmValue; + e->type = elem::VAL; + e->vardecl = vd; } + else assert(0); } else { // take care of forward references of global variables @@ -463,18 +451,6 @@ return 0; } - // handle function argument - allocate temp storage for it :/ annoying - if (l->mem == 0) { - assert(l->val); - if (llvm::isa<llvm::Argument>(l->val)) - DtoGiveArgumentStorage(l); - else { - Logger::cout() << "here it comes... " << *l->val << '\n'; - assert(0); - } - } - //e->val = l->store(r->getValue()); - Type* e1type = DtoDType(e1->type); Type* e2type = DtoDType(e2->type); TY e1ty = e1type->ty; @@ -689,8 +665,7 @@ tmp = DtoPointedType(storeVal, tmp); }*/ - if (l->mem == 0) - DtoGiveArgumentStorage(l); + assert(l->mem); new llvm::StoreInst(val,l->mem,p->scopebb()); e->type = elem::VAR; @@ -762,8 +737,7 @@ tmp = DtoPointedType(storeVal, tmp); }*/ - if (l->mem == 0) - DtoGiveArgumentStorage(l); + assert(l->mem); new llvm::StoreInst(tmp, l->mem, p->scopebb()); delete l; @@ -814,8 +788,7 @@ tmp = DtoPointedType(storeVal, tmp); }*/ - if (l->mem == 0) - DtoGiveArgumentStorage(l); + assert(l->mem); new llvm::StoreInst(tmp,l->mem,p->scopebb()); delete l; @@ -881,8 +854,7 @@ tmp = DtoPointedType(storeVal, tmp); }*/ - if (l->mem == 0) - DtoGiveArgumentStorage(l); + assert(l->mem); new llvm::StoreInst(tmp,l->mem,p->scopebb()); delete l; @@ -948,8 +920,7 @@ tmp = DtoPointedType(storeVal, tmp); }*/ - if (l->mem == 0) - DtoGiveArgumentStorage(l); + assert(l->mem); new llvm::StoreInst(tmp,l->mem,p->scopebb()); delete l; @@ -1020,7 +991,7 @@ va_magic = true; } else if (fn->funcdecl->llvmInternal == LLVMva_arg) { - Argument* fnarg = Argument::getNth(tf->parameters, 0); + //Argument* fnarg = Argument::getNth(tf->parameters, 0); Expression* exp = (Expression*)arguments->data[0]; elem* expelem = exp->toElem(p); assert(expelem->mem); @@ -2158,8 +2129,7 @@ else assert(post); - if (l->mem == 0) - DtoGiveArgumentStorage(l); + assert(l->mem); new llvm::StoreInst(post,l->mem,p->scopebb()); delete l; @@ -2503,8 +2473,7 @@ llvm::Value* vval = v->getValue(); \ assert(vval); \ llvm::Value* tmp = llvm::BinaryOperator::create(llvm::Instruction::Y, uval, vval, "tmp", p->scopebb()); \ - if (u->mem == 0) \ - DtoGiveArgumentStorage(u); \ + assert(u->mem); \ Logger::cout() << *tmp << '|' << *u->mem << '\n'; \ new llvm::StoreInst(DtoPointedType(u->mem, tmp), u->mem, p->scopebb()); \ delete u; \
--- a/gen/tollvm.c Thu Nov 01 17:27:18 2007 +0100 +++ b/gen/tollvm.c Fri Nov 02 01:17:26 2007 +0100 @@ -482,6 +482,7 @@ llvm::Value* DtoStructCopy(llvm::Value* dst, llvm::Value* src) { + Logger::cout() << "dst = " << *dst << " src = " << *src << '\n'; assert(dst->getType() == src->getType()); assert(gIR); @@ -1093,20 +1094,6 @@ ////////////////////////////////////////////////////////////////////////////////////////// -void DtoGiveArgumentStorage(elem* l) -{ - assert(l->mem == 0); - assert(l->val); - assert(llvm::isa<llvm::Argument>(l->val)); - assert(l->vardecl != 0); - - llvm::AllocaInst* allocainst = new llvm::AllocaInst(l->val->getType(), l->val->getName()+"_storage", gIR->topallocapoint()); - l->mem = allocainst; - l->vardecl->llvmValue = l->mem; -} - -////////////////////////////////////////////////////////////////////////////////////////// - llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty) { /*size_t sz = gTargetData->getTypeSize(ty); @@ -1235,7 +1222,6 @@ if (paramtype && retval->getType() != paramtype) { assert(retval->getType() == paramtype->getContainedType(0)); - DtoGiveArgumentStorage(arg); new llvm::StoreInst(retval, arg->mem, gIR->scopebb()); retval = arg->mem; } @@ -1373,6 +1359,16 @@ llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2) ); } +llvm::Constant* DtoConstStringPtr(const char* str, const char* section) +{ + std::string s(str); + llvm::Constant* init = llvm::ConstantArray::get(s, true); + llvm::GlobalVariable* gvar = new llvm::GlobalVariable( + init->getType(), true,llvm::GlobalValue::InternalLinkage, init, "stringliteral", gIR->module); + if (section) gvar->setSection(section); + llvm::Constant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) }; + return llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2); +} //////////////////////////////////////////////////////////////////////////////////////////
--- a/gen/tollvm.h Thu Nov 01 17:27:18 2007 +0100 +++ b/gen/tollvm.h Fri Nov 02 01:17:26 2007 +0100 @@ -46,8 +46,6 @@ llvm::Value* DtoGEPi(llvm::Value* ptr, unsigned i0, const std::string& var, llvm::BasicBlock* bb=NULL); llvm::Value* DtoGEPi(llvm::Value* ptr, unsigned i0, unsigned i1, const std::string& var, llvm::BasicBlock* bb=NULL); -void DtoGiveArgumentStorage(elem* e); - llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty); llvm::Value* DtoRealloc(llvm::Value* ptr, llvm::Value* len); @@ -63,6 +61,7 @@ llvm::ConstantInt* DtoConstUint(unsigned i); llvm::ConstantInt* DtoConstInt(int i); llvm::Constant* DtoConstString(const char*); +llvm::Constant* DtoConstStringPtr(const char* str, const char* section = 0); llvm::Constant* DtoConstBool(bool); void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes);
--- a/gen/toobj.c Thu Nov 01 17:27:18 2007 +0100 +++ b/gen/toobj.c Fri Nov 02 01:17:26 2007 +0100 @@ -36,6 +36,7 @@ #include "gen/logger.h" #include "gen/tollvm.h" #include "gen/arrays.h" +#include "gen/todebug.h" ////////////////////////////////////////////////////////////////////////////////////////// @@ -75,6 +76,12 @@ llvm::TargetMachine &targetMachine = *targetPtr.get(); gTargetData = targetMachine.getTargetData(); + // debug info + if (global.params.symdebug) { + RegisterDwarfSymbols(ir.module); + ir.dwarfCompileUnit = DtoDwarfCompileUnit(this); + } + // process module members for (int k=0; k < members->dim; k++) { Dsymbol* dsym = (Dsymbol*)(members->data[k]); @@ -750,6 +757,11 @@ return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete } + // debug info + if (global.params.symdebug) { + llvmDwarfSubProgram = DtoDwarfSubProgram(this); + } + assert(f->llvmType); const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0)); @@ -809,6 +821,29 @@ f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb()); gIR->func().allocapoint = f->llvmAllocaPoint; + // give arguments storage + size_t n = Argument::dim(f->parameters); + for (int i=0; i < n; ++i) { + Argument* arg = Argument::getNth(f->parameters, i); + if (arg && arg->vardecl) { + VarDeclaration* vd = arg->vardecl; + if (!vd->llvmNeedsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)) + continue; + llvm::Value* a = vd->llvmValue; + assert(a); + std::string s(a->getName()); + Logger::println("giving argument '%s' storage", s.c_str()); + s.append("_storage"); + llvm::Value* v = new llvm::AllocaInst(a->getType(),s,f->llvmAllocaPoint); + gIR->ir->CreateStore(a,v); + vd->llvmValue = v; + } + else assert(0); + } + + // debug info + if (global.params.symdebug) DtoDwarfFuncStart(this); + llvm::Value* parentNested = NULL; if (FuncDeclaration* fd = toParent()->isFuncDeclaration()) { parentNested = fd->llvmNested; @@ -866,7 +901,7 @@ if (!isMain()) { if (!gIR->scopereturned()) { // pass the previous block into this block - //new llvm::BranchInst(irs.end, irs.begin); + if (global.params.symdebug) DtoDwarfFuncEnd(this); if (func->getReturnType() == llvm::Type::VoidTy) { new llvm::ReturnInst(gIR->scopebb()); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bug47.d Fri Nov 02 01:17:26 2007 +0100 @@ -0,0 +1,15 @@ +module bug47; + +bool func(bool a, bool b) +{ + if (a) b = false; + return b; +} + +void main() +{ + assert(func(0,0) == 0); + assert(func(0,1) == 1); + assert(func(1,0) == 0); + assert(func(1,1) == 0); +}