# HG changeset patch # User lindquist # Date 1193962646 -3600 # Node ID d8dd47ef397365fd2d7e3e5f6fbe039edc166027 # Parent 3587401b6eeb2ab0b47ce3d0d638263ac86b5f23 [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 :) diff -r 3587401b6eeb -r d8dd47ef3973 demos/readme.txt --- /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 diff -r 3587401b6eeb -r d8dd47ef3973 dmd/declaration.c --- 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) diff -r 3587401b6eeb -r d8dd47ef3973 dmd/declaration.h --- 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 diff -r 3587401b6eeb -r d8dd47ef3973 dmd/expression.c --- 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 diff -r 3587401b6eeb -r d8dd47ef3973 dmd/func.c --- 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) diff -r 3587401b6eeb -r d8dd47ef3973 gen/dwarftypes.c --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void RegisterDwarfSymbols(llvm::Module* mod) { + using namespace llvm; + // Type Definitions + std::vectorStructTy_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::vectorStructTy_llvm_dbg_basictype_type_fields; + StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(32)); + std::vectorStructTy_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::vectorStructTy_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::vectorStructTy_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::vectorStructTy_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::vectorStructTy_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::vectorStructTy_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::vectorStructTy_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::vectorFuncTy_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::vectorFuncTy_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::vectorFuncTy_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); +} diff -r 3587401b6eeb -r d8dd47ef3973 gen/irstate.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() diff -r 3587401b6eeb -r d8dd47ef3973 gen/irstate.h --- 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 diff -r 3587401b6eeb -r d8dd47ef3973 gen/statements.c --- 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"); diff -r 3587401b6eeb -r d8dd47ef3973 gen/todebug.c --- /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 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 elems(2, Ty(Int32Ty)); + const llvm::StructType* t = llvm::cast(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 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 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 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(gIR->module->getTypeByName("llvm.dbg.compile_unit.type")); +} + +const llvm::StructType* GetDwarfSubProgramType() { + return llvm::cast(gIR->module->getTypeByName("llvm.dbg.subprogram.type")); +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +llvm::GlobalVariable* DtoDwarfCompileUnit(Module* m) +{ + std::vector 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 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 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()); +} diff -r 3587401b6eeb -r d8dd47ef3973 gen/todebug.h --- /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 + + diff -r 3587401b6eeb -r d8dd47ef3973 gen/toir.c --- 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(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(vd->llvmValue)) { - e->val = vd->llvmValue; - e->type = elem::VAL; - e->vardecl = vd; - } - else if (llvm::isa(vd->llvmValue)) { - e->mem = vd->llvmValue; - e->type = elem::VAR; - } - else - assert(0); - } + else if (llvm::isa(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(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; \ diff -r 3587401b6eeb -r d8dd47ef3973 gen/tollvm.c --- 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(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); +} ////////////////////////////////////////////////////////////////////////////////////////// diff -r 3587401b6eeb -r d8dd47ef3973 gen/tollvm.h --- 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); diff -r 3587401b6eeb -r d8dd47ef3973 gen/toobj.c --- 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(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()); } diff -r 3587401b6eeb -r d8dd47ef3973 test/bug47.d --- /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); +} diff -r 3587401b6eeb -r d8dd47ef3973 test/fail1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/fail1.d Fri Nov 02 01:17:26 2007 +0100 @@ -0,0 +1,12 @@ +module fail1; + +void func() +{ + float* fp; + float f = *fp; +} + +void main() +{ + func(); +}