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);
+}
--- /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();
+}