changeset 946:1714836f2c0b

Mostly rewrite debug info generation in terms of llvm/Analysis/DebugInfo.h. Add getCompilationModule to Dsymbol and fix template compile unit decision code. Runtime compiles with -g again.
author Christian Kamm <kamm incasoftware de>
date Sun, 08 Feb 2009 16:50:22 +0100
parents 03d7c4aac654
children 9a10fa839dc5
files dmd/dsymbol.c dmd/dsymbol.h dmd/template.c gen/functions.cpp gen/irstate.cpp gen/irstate.h gen/llvm.h gen/llvmhelpers.cpp gen/todebug.cpp gen/todebug.h gen/toobj.cpp ir/irfunction.cpp ir/irfunction.h ir/irmodule.cpp ir/irmodule.h ir/irstruct.cpp ir/irstruct.h
diffstat 17 files changed, 251 insertions(+), 390 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/dsymbol.c	Sun Feb 08 05:26:54 2009 +0100
+++ b/dmd/dsymbol.c	Sun Feb 08 16:50:22 2009 +0100
@@ -554,6 +554,34 @@
     return NULL;
 }
 
+
+/**********************************
+ * Determine which Module a Dsymbol will be compiled in.
+ * This may be different from getModule for templates.
+ */
+
+Module *Dsymbol::getCompilationModule()
+{
+    Module *m;
+    TemplateInstance *ti;
+    Dsymbol *s;
+
+    //printf("Dsymbol::getModule()\n");
+    s = this;
+    while (s)
+    {
+	//printf("\ts = '%s'\n", s->toChars());
+	m = s->isModule();
+	if (m)
+	    return m;
+	ti = s->isTemplateInstance();
+	if (ti && ti->tmodule)
+	    return ti->tmodule;
+	s = s->parent;
+    }
+    return NULL;
+}
+
 /*************************************
  */
 
--- a/dmd/dsymbol.h	Sun Feb 08 05:26:54 2009 +0100
+++ b/dmd/dsymbol.h	Sun Feb 08 16:50:22 2009 +0100
@@ -119,7 +119,8 @@
     void error(Loc loc, const char *format, ...);
     void error(const char *format, ...);
     void checkDeprecated(Loc loc, Scope *sc);
-    Module *getModule();
+    Module *getModule();        // module where declared
+    Module *getCompilationModule(); // possibly different for templates
     Dsymbol *pastMixin();
     Dsymbol *toParent();
     Dsymbol *toParent2();
--- a/dmd/template.c	Sun Feb 08 05:26:54 2009 +0100
+++ b/dmd/template.c	Sun Feb 08 16:50:22 2009 +0100
@@ -2982,7 +2982,12 @@
 
     // get the enclosing template instance from the scope tinst
     tinst = sc->tinst;
-    tmodule = sc->module;
+
+    // get the module of the outermost enclosing instantiation
+    if (tinst)
+	tmodule = tinst->tmodule;
+    else
+	tmodule = sc->module;
 
 #if LOG
     printf("\tdo semantic\n");
--- a/gen/functions.cpp	Sun Feb 08 05:26:54 2009 +0100
+++ b/gen/functions.cpp	Sun Feb 08 16:50:22 2009 +0100
@@ -647,7 +647,7 @@
     // debug info
     if (global.params.symdebug) {
         Module* mo = fd->getModule();
-        fd->ir.irFunc->dwarfSubProg = DtoDwarfSubProgram(fd);
+        fd->ir.irFunc->diSubprogram = DtoDwarfSubProgram(fd);
     }
 
     Type* t = fd->type->toBasetype();
--- a/gen/irstate.cpp	Sun Feb 08 05:26:54 2009 +0100
+++ b/gen/irstate.cpp	Sun Feb 08 16:50:22 2009 +0100
@@ -47,14 +47,14 @@
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-IRState::IRState()
+IRState::IRState(llvm::Module* m)
+    : module(m), difactory(*m)
 {
     interfaceInfoType = NULL;
     mutexType = NULL;
     moduleRefType = NULL;
 
     dmodule = 0;
-    module = 0;
     emitMain = false;
     mainFunc = 0;
     ir.state = this;
--- a/gen/irstate.h	Sun Feb 08 05:26:54 2009 +0100
+++ b/gen/irstate.h	Sun Feb 08 16:50:22 2009 +0100
@@ -131,7 +131,7 @@
 // represents the module
 struct IRState
 {
-    IRState();
+    IRState(llvm::Module* m);
 
     // module
     Module* dmodule;
@@ -190,6 +190,9 @@
     // builder helper
     IRBuilderHelper ir;
 
+    // debug info helper
+    llvm::DIFactory difactory;
+
     typedef std::list<Dsymbol*> DsymbolList;
     // dsymbols that need to be resolved
     DsymbolList resolveList;
--- a/gen/llvm.h	Sun Feb 08 05:26:54 2009 +0100
+++ b/gen/llvm.h	Sun Feb 08 16:50:22 2009 +0100
@@ -14,6 +14,8 @@
 
 #include "llvm/Target/TargetData.h"
 
+#include "llvm/Analysis/DebugInfo.h"
+
 #include "llvm/Support/IRBuilder.h"
 using llvm::IRBuilder;
 
--- a/gen/llvmhelpers.cpp	Sun Feb 08 05:26:54 2009 +0100
+++ b/gen/llvmhelpers.cpp	Sun Feb 08 16:50:22 2009 +0100
@@ -974,7 +974,7 @@
         // do debug info
         if (global.params.symdebug)
         {
-            LLGlobalVariable* gv = DtoDwarfGlobalVariable(gvar, vd);
+            LLGlobalVariable* gv = DtoDwarfGlobalVariable(gvar, vd).getGV();
             // keep a reference so GDCE doesn't delete it !
             gIR->usedArray.push_back(llvm::ConstantExpr::getBitCast(gv, getVoidPtrType()));
         }
@@ -1557,7 +1557,7 @@
 
 bool mustDefineSymbol(Dsymbol* s)
 {
-#if 1
+#if 0
     return s->getModule() == gIR->dmodule || DtoIsTemplateInstance(s) != NULL;
 #else
     Module* M = DtoIsTemplateInstance(s);
@@ -1573,7 +1573,7 @@
 
 bool needsTemplateLinkage(Dsymbol* s)
 {
-#if 1
+#if 0
     return DtoIsTemplateInstance(s) != NULL;
 #else
     Module* M = DtoIsTemplateInstance(s);
--- a/gen/todebug.cpp	Sun Feb 08 05:26:54 2009 +0100
+++ b/gen/todebug.cpp	Sun Feb 08 16:50:22 2009 +0100
@@ -25,22 +25,6 @@
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
 /**
- * Emits a global variable, LLVM Dwarf style.
- * @param type Type of variable.
- * @param values Initializers.
- * @param name Name.
- * @return The global variable.
- */
-static LLGlobalVariable* emitDwarfGlobal(const LLStructType* type, const std::vector<LLConstant*> values, const char* name, bool linkonce=false)
-{
-    LLConstant* c = llvm::ConstantStruct::get(type, values);
-    LLGlobalValue::LinkageTypes linkage = linkonce ? LLGlobalValue::LinkOnceLinkage : LLGlobalValue::InternalLinkage;
-    LLGlobalVariable* gv = new LLGlobalVariable(type, true, linkage, c, name, gIR->module);
-    gv->setSection("llvm.metadata");
-    return gv;
-}
-
-/**
  * Emits a global variable, LLVM Dwarf style, only declares.
  * @param type Type of variable.
  * @param name Name.
@@ -56,41 +40,16 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-/**
- * Emits the Dwarf anchors that are used repeatedly by LLVM debug info.
- */
-static void emitDwarfAnchors()
+static llvm::DIAnchor getDwarfAnchor(dwarf_constants c)
 {
-    const llvm::StructType* anchorTy = isaStruct(gIR->module->getTypeByName("llvm.dbg.anchor.type"));
-    std::vector<LLConstant*> vals(2);
-
-    vals[0] = DtoConstUint(llvm::LLVMDebugVersion);
-    vals[1] = DtoConstUint(DW_TAG_compile_unit);
-    gIR->dwarfCUs = emitDwarfGlobal(anchorTy, vals, "llvm.dbg.compile_units", true);
-
-    vals[0] = DtoConstUint(llvm::LLVMDebugVersion);
-    vals[1] = DtoConstUint(DW_TAG_variable);
-    gIR->dwarfGVs = emitDwarfGlobal(anchorTy, vals, "llvm.dbg.global_variables", true);
-
-    vals[0] = DtoConstUint(llvm::LLVMDebugVersion);
-    vals[1] = DtoConstUint(DW_TAG_subprogram);
-    gIR->dwarfSPs = emitDwarfGlobal(anchorTy, vals, "llvm.dbg.subprograms", true);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-static LLConstant* getDwarfAnchor(dwarf_constants c)
-{
-    if (!gIR->dwarfCUs)
-        emitDwarfAnchors();
     switch (c)
     {
     case DW_TAG_compile_unit:
-        return gIR->dwarfCUs;
+        return gIR->difactory.GetOrCreateCompileUnitAnchor();
     case DW_TAG_variable:
-        return gIR->dwarfGVs;
+        return gIR->difactory.GetOrCreateGlobalVariableAnchor();
     case DW_TAG_subprogram:
-        return gIR->dwarfSPs;
+        return gIR->difactory.GetOrCreateSubprogramAnchor();
     default:
         assert(0);
     }
@@ -126,123 +85,20 @@
     return isaStruct(gIR->module->getTypeByName("llvm.dbg.global_variable.type"));
 }
 
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-static LLGlobalVariable* dwarfCompileUnit(Module* m)
-{
-    std::vector<LLConstant*> vals(6);
-    vals[0] = DBG_TAG(DW_TAG_compile_unit);
-    vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_compile_unit));
-
-    if (global.params.symdebug == 2)
-        vals[2] = DtoConstUint(DW_LANG_C);
-    else
-        vals[2] = DtoConstUint(DW_LANG_D);
-    vals[3] = DtoConstStringPtr(FileName::name(m->srcfile->name->toChars()), "llvm.metadata");
-    std::string srcpath(FileName::path(m->srcfile->name->toChars()));
-    if (!FileName::absolute(srcpath.c_str())) {
-        llvm::sys::Path tmp = llvm::sys::Path::GetCurrentDirectory();
-        tmp.appendComponent(srcpath);
-        srcpath = tmp.toString();
-        if (!srcpath.empty() && *srcpath.rbegin() != '/' && *srcpath.rbegin() != '\\')
-            srcpath = srcpath + '/';
-    }
-    vals[4] = DtoConstStringPtr(srcpath.c_str(), "llvm.metadata");
-    vals[5] = DtoConstStringPtr("LDC (http://www.dsource.org/projects/ldc)", "llvm.metadata");
-
-    LLGlobalVariable* gv = emitDwarfGlobal(getDwarfCompileUnitType(), vals, "llvm.dbg.compile_unit");
-    m->ir.irModule->dwarfCompileUnit = gv;
-    return gv;
-}
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-static LLGlobalVariable* dwarfSubProgram(llvm::GlobalVariable* emitUnit, llvm::GlobalVariable* defineUnit, const char* prettyname, const char* mangledname, unsigned int linenum, bool isprivate)
-{
-    std::vector<LLConstant*> vals(11);
-    vals[0] = DBG_TAG(DW_TAG_subprogram);
-    vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_subprogram));
-
-    vals[2] = DBG_CAST(emitUnit);
-    vals[3] = DtoConstStringPtr(prettyname, "llvm.metadata");
-    vals[4] = vals[3];
-    vals[5] = DtoConstStringPtr(mangledname, "llvm.metadata");
-    vals[6] = DBG_CAST(defineUnit);
-    vals[7] = DtoConstUint(linenum);
-    vals[8] = DBG_NULL;
-    vals[9] = DtoConstBool(isprivate);
-    vals[10] = DtoConstBool(emitUnit == defineUnit);
-
-    Logger::println("emitting subprogram global");
-
-    return emitDwarfGlobal(getDwarfSubProgramType(), vals, "llvm.dbg.subprogram");
-}
-
-/*
-static LLGlobalVariable* dwarfSubProgram(FuncDeclaration* fd, llvm::GlobalVariable* compileUnit)
-{
-    std::vector<LLConstant*> vals(11);
-    vals[0] = DBG_TAG(DW_TAG_subprogram);
-    vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_subprogram));
-
-    vals[2] = DBG_CAST(compileUnit);
-    vals[3] = DtoConstStringPtr(fd->toPrettyChars(), "llvm.metadata");
-    vals[4] = vals[3];
-    vals[5] = DtoConstStringPtr(fd->mangle(), "llvm.metadata");
-    vals[6] = DBG_CAST( DtoDwarfCompileUnit(fd->getModule()) );
-    vals[7] = DtoConstUint(fd->loc.linnum);
-    vals[8] = DBG_NULL;
-    vals[9] = DtoConstBool(fd->protection == PROTprivate);
-    vals[10] = DtoConstBool(fd->getModule() == gIR->dmodule);
-
-    Logger::println("emitting subprogram global");
-
-    return emitDwarfGlobal(getDwarfSubProgramType(), vals, "llvm.dbg.subprogram");
-}*/
+static llvm::DIType dwarfTypeDescription_impl(Type* type, llvm::DICompileUnit cu, const char* c_name);
+static llvm::DIType dwarfTypeDescription(Type* type, llvm::DICompileUnit cu, const char* c_name);
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-static LLGlobalVariable* dwarfTypeDescription_impl(Type* type, LLGlobalVariable* cu, const char* c_name);
-static LLGlobalVariable* dwarfTypeDescription(Type* type, LLGlobalVariable* cu, const char* c_name);
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-static LLGlobalVariable* dwarfBasicType(Type* type, llvm::GlobalVariable* compileUnit)
+static llvm::DIBasicType dwarfBasicType(Type* type, llvm::DICompileUnit compileUnit)
 {
     Type* t = type->toBasetype();
-
     const LLType* T = DtoType(type);
 
-    std::vector<LLConstant*> vals(10);
-
-    // tag
-    vals[0] = DBG_TAG(DW_TAG_base_type);
-
-    // context
-    vals[1] = DBG_CAST(compileUnit);
-
-    // name
-    vals[2] = DtoConstStringPtr(type->toChars(), "llvm.metadata");
-
-    // compile unit where defined
-    vals[3] = DBG_NULL;
-
-    // line number where defined
-    vals[4] = DtoConstInt(0);
-
-    // size in bits
-    vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false);
-
-    // alignment in bits
-    vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false);
-
-    // offset in bits
-    vals[7] = LLConstantInt::get(LLType::Int64Ty, 0, false);
-
-    // FIXME: dont know what this is
-    vals[8] = DtoConstUint(0);
-
-    // dwarf type
+    // find encoding
     unsigned id;
     if (t->isintegral())
     {
@@ -259,131 +115,85 @@
     {
         assert(0 && "unsupported basictype for debug info");
     }
-    vals[9] = DtoConstUint(id);
 
-    return emitDwarfGlobal(getDwarfBasicTypeType(), vals, "llvm.dbg.basictype");
+    return gIR->difactory.CreateBasicType(
+        compileUnit, // context
+        type->toChars(), // name
+        llvm::DICompileUnit(NULL), // compile unit
+        0, // line number
+        getTypeBitSize(T), // size (bits)
+        getABITypeAlign(T)*8, // align (bits)
+        0, // offset (bits)
+//FIXME: need flags?
+        0, // flags
+        id // encoding
+    );
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-static LLGlobalVariable* dwarfDerivedType(Type* type, llvm::GlobalVariable* compileUnit)
+static llvm::DIDerivedType dwarfDerivedType(Type* type, llvm::DICompileUnit compileUnit)
 {
     const LLType* T = DtoType(type);
     Type* t = type->toBasetype();
 
-    // defaults
-    LLConstant* name = getNullPtr(getVoidPtrType());
+    assert(t->ty == Tpointer && "unsupported derivedtype for debug info, only pointers allowed");
 
-    // find tag
-    unsigned tag;
-    if (t->ty == Tpointer)
-    {
-        tag = DW_TAG_pointer_type;
-    }
-    else
-    {
-        assert(0 && "unsupported derivedtype for debug info");
-    }
-
-    std::vector<LLConstant*> vals(10);
-
-    // tag
-    vals[0] = DBG_TAG(tag);
-
-    // context
-    vals[1] = DBG_CAST(compileUnit);
-
-    // name
-    vals[2] = name;
+    // find base type
+    llvm::DIType basetype;
+    Type* nt = t->nextOf();
+    basetype = dwarfTypeDescription_impl(nt, compileUnit, NULL);
+    if (nt->ty == Tvoid)
+        basetype = llvm::DIType(NULL);
 
-    // compile unit where defined
-    vals[3] = DBG_NULL;
-
-    // line number where defined
-    vals[4] = DtoConstInt(0);
-
-    // size in bits
-    vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false);
-
-    // alignment in bits
-    vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false);
-
-    // offset in bits
-    vals[7] = LLConstantInt::get(LLType::Int64Ty, 0, false);
-
-    // FIXME: dont know what this is
-    vals[8] = DtoConstUint(0);
-
-    // base type
-    Type* nt = t->nextOf();
-    LLGlobalVariable* nTD = dwarfTypeDescription_impl(nt, compileUnit, NULL);
-    if (nt->ty == Tvoid || !nTD)
-        vals[9] = DBG_NULL;
-    else
-        vals[9] = DBG_CAST(nTD);
-
-    return emitDwarfGlobal(getDwarfDerivedTypeType(), vals, "llvm.dbg.derivedtype");
+    return gIR->difactory.CreateDerivedType(
+        DW_TAG_pointer_type, // tag
+        compileUnit, // context
+        "", // name
+        llvm::DICompileUnit(NULL), // compile unit
+        0, // line number
+        getTypeBitSize(T), // size (bits)
+        getABITypeAlign(T)*8, // align (bits)
+        0, // offset (bits)
+//FIXME: need flags?
+        0, // flags
+        basetype // derived from
+    );
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-static LLGlobalVariable* dwarfMemberType(unsigned linnum, Type* type, LLGlobalVariable* compileUnit, LLGlobalVariable* definedCU, const char* c_name, unsigned offset)
+static llvm::DIDerivedType dwarfMemberType(unsigned linnum, Type* type, llvm::DICompileUnit compileUnit, llvm::DICompileUnit definedCU, const char* c_name, unsigned offset)
 {
     const LLType* T = DtoType(type);
     Type* t = type->toBasetype();
 
-    // defaults
-    LLConstant* name;
-    if (c_name)
-        name = DtoConstStringPtr(c_name, "llvm.metadata");
-    else
-        name = getNullPtr(getVoidPtrType());
-
-    std::vector<LLConstant*> vals(10);
-
-    // tag
-    vals[0] = DBG_TAG(DW_TAG_member);
-
-    // context
-    vals[1] = DBG_CAST(compileUnit);
-
-    // name
-    vals[2] = name;
-
-    // compile unit where defined
-    if (definedCU)
-        vals[3] = DBG_CAST(definedCU);
-    else
-        vals[3] = DBG_NULL;
+    // find base type
+    llvm::DIType basetype;
+    basetype = dwarfTypeDescription(t, compileUnit, NULL);
+    if (t->ty == Tvoid)
+        basetype = llvm::DIType(NULL);
 
-    // line number where defined
-    vals[4] = DtoConstInt(linnum);
-
-    // size in bits
-    vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false);
-
-    // alignment in bits
-    vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false);
-
-    // offset in bits
-    vals[7] = LLConstantInt::get(LLType::Int64Ty, offset*8, false);
-
-    // FIXME: dont know what this is
-    vals[8] = DtoConstUint(0);
-
-    // base type
-    LLGlobalVariable* nTD = dwarfTypeDescription(t, compileUnit, NULL);
-    if (t->ty == Tvoid || !nTD)
-        vals[9] = DBG_NULL;
-    else
-        vals[9] = DBG_CAST(nTD);
-
-    return emitDwarfGlobal(getDwarfDerivedTypeType(), vals, "llvm.dbg.derivedtype");
+    return gIR->difactory.CreateDerivedType(
+        DW_TAG_member, // tag
+        compileUnit, // context
+        c_name, // name
+        definedCU, // compile unit
+        linnum, // line number
+        getTypeBitSize(T), // size (bits)
+        getABITypeAlign(T)*8, // align (bits)
+        offset*8, // offset (bits)
+//FIXME: need flags?
+        0, // flags
+        basetype // derived from
+    );
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-static LLGlobalVariable* dwarfCompositeType(Type* type, llvm::GlobalVariable* compileUnit)
+//FIXME: This does not use llvm's DIFactory as it can't 
+//   handle recursive types properly.
+static llvm::DICompositeType dwarfCompositeType(Type* type, llvm::DICompileUnit compileUnit)
 {
     const LLType* T = DtoType(type);
     Type* t = type->toBasetype();
@@ -392,7 +202,7 @@
     LLConstant* name = getNullPtr(getVoidPtrType());
     LLGlobalVariable* members = NULL;
     unsigned linnum = 0;
-    LLGlobalVariable* definedCU = NULL;
+    llvm::DICompileUnit definedCU;
 
     // prepare tag and members
     unsigned tag;
@@ -405,9 +215,9 @@
     {
         tag = DW_TAG_structure_type;
 
-        LLGlobalVariable* len = dwarfMemberType(0, Type::tsize_t, compileUnit, NULL, "length", 0);
+        LLGlobalVariable* len = dwarfMemberType(0, Type::tsize_t, compileUnit, llvm::DICompileUnit(NULL), "length", 0).getGV();
         assert(len);
-        LLGlobalVariable* ptr = dwarfMemberType(0, t->nextOf()->pointerTo(), compileUnit, NULL, "ptr", global.params.is64bit?8:4);
+        LLGlobalVariable* ptr = dwarfMemberType(0, t->nextOf()->pointerTo(), compileUnit, llvm::DICompileUnit(NULL), "ptr", global.params.is64bit?8:4).getGV();
         assert(ptr);
 
         const LLArrayType* at = LLArrayType::get(DBG_TYPE, 2);
@@ -442,22 +252,24 @@
         // if we don't know the aggregate's size, we don't know enough about it
         // to provide debug info. probably a forward-declared struct?
         if (sd->sizeok == 0)
-            return NULL;
+            return llvm::DICompositeType(NULL);
 
         IrStruct* ir = sd->ir.irStruct;
         assert(ir);
-        if (ir->dwarfComposite)
-            return ir->dwarfComposite;
+        if (!ir->diCompositeType.isNull())
+            return ir->diCompositeType;
 
         // set to handle recursive types properly
         gv = emitDwarfGlobalDecl(getDwarfCompositeTypeType(), "llvm.dbg.compositetype");
-        ir->dwarfComposite = gv;
+        // set bogus initializer to satisfy asserts in DICompositeType constructor
+        gv->setInitializer(LLConstant::getNullValue(getDwarfCompositeTypeType()));
+        ir->diCompositeType = llvm::DICompositeType(gv);
 
         tag = DW_TAG_structure_type;
 
         name = DtoConstStringPtr(sd->toChars(), "llvm.metadata");
         linnum = sd->loc.linnum;
-        definedCU = DtoDwarfCompileUnit(sd->getModule());
+        definedCU = DtoDwarfCompileUnit(sd->getCompilationModule());
 
         std::vector<LLConstant*> elems;
         if (!ir->aggrdecl->isInterfaceDeclaration()) // plain interfaces don't have one
@@ -470,7 +282,7 @@
                 VarDeclaration* vd = arr[k];
                 assert(vd);
 
-                LLGlobalVariable* ptr = dwarfMemberType(vd->loc.linnum, vd->type, compileUnit, definedCU, vd->toChars(), vd->offset);
+                LLGlobalVariable* ptr = dwarfMemberType(vd->loc.linnum, vd->type, compileUnit, definedCU, vd->toChars(), vd->offset).getGV();
                 elems.push_back(DBG_CAST(ptr));
             }
         }
@@ -493,14 +305,14 @@
     vals[0] = DBG_TAG(tag);
 
     // context
-    vals[1] = DBG_CAST(compileUnit);
+    vals[1] = DBG_CAST(compileUnit.getGV());
 
     // name
     vals[2] = name;
 
     // compile unit where defined
-    if (definedCU)
-        vals[3] = DBG_CAST(definedCU);
+    if (definedCU.getGV())
+        vals[3] = DBG_CAST(definedCU.getGV());
     else
         vals[3] = DBG_NULL;
 
@@ -534,42 +346,33 @@
     LLConstant* initia = LLConstantStruct::get(getDwarfCompositeTypeType(), vals);
     gv->setInitializer(initia);
 
-    return gv;
+    return llvm::DICompositeType(gv);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-static LLGlobalVariable* dwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd)
+static llvm::DIGlobalVariable dwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd)
 {
     assert(vd->isDataseg());
-    LLGlobalVariable* compileUnit = DtoDwarfCompileUnit(gIR->dmodule);
-
-    std::vector<LLConstant*> vals(12);
-    vals[0] = DBG_TAG(DW_TAG_variable);
-    vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_variable));
-
-    vals[2] = DBG_CAST(compileUnit);
-
-    vals[3] = DtoConstStringPtr(vd->mangle(), "llvm.metadata");
-    vals[4] = DtoConstStringPtr(vd->toPrettyChars(), "llvm.metadata");
-    vals[5] = DtoConstStringPtr(vd->toChars(), "llvm.metadata");
+    llvm::DICompileUnit compileUnit = DtoDwarfCompileUnit(gIR->dmodule);
 
-    vals[6] = DBG_CAST(DtoDwarfCompileUnit(vd->getModule()));
-    vals[7] = DtoConstUint(vd->loc.linnum);
-
-    LLGlobalVariable* TY = dwarfTypeDescription_impl(vd->type, compileUnit, NULL);
-    vals[8] = TY ? DBG_CAST(TY) : DBG_NULL;
-    vals[9] = DtoConstBool(vd->protection == PROTprivate);
-    vals[10] = DtoConstBool(vd->getModule() == gIR->dmodule);
-
-    vals[11] = DBG_CAST(ll);
-
-    return emitDwarfGlobal(getDwarfGlobalVariableType(), vals, "llvm.dbg.global_variable");
+    return gIR->difactory.CreateGlobalVariable(
+        compileUnit, // context
+        vd->mangle(), // name
+        vd->toPrettyChars(), // displayname
+        vd->toChars(), // linkage name
+        DtoDwarfCompileUnit(vd->getCompilationModule()), // compile unit
+        vd->loc.linnum, // line num
+        dwarfTypeDescription_impl(vd->type, compileUnit, NULL), // type
+        vd->protection == PROTprivate, // is local to unit
+        vd->getCompilationModule() == gIR->dmodule, // is definition
+        ll // value
+    );
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-static LLGlobalVariable* dwarfVariable(VarDeclaration* vd, LLGlobalVariable* typeDescr)
+static llvm::DIVariable dwarfVariable(VarDeclaration* vd, llvm::DIType type)
 {
     assert(!vd->isDataseg() && "static variable");
 
@@ -579,40 +382,30 @@
     else
         tag = DW_TAG_auto_variable;
 
-    std::vector<LLConstant*> vals(6);
-    // tag
-    vals[0] = DBG_TAG(tag);
-    // context
-    vals[1] = DBG_CAST(gIR->func()->dwarfSubProg);
-    // name
-    vals[2] = DtoConstStringPtr(vd->toChars(), "llvm.metadata");
-    // compile unit where defined
-    vals[3] = DBG_CAST(DtoDwarfCompileUnit(vd->getModule()));
-    // line number where defined
-    vals[4] = DtoConstUint(vd->loc.linnum);
-    // type descriptor
-    vals[5] = DBG_CAST(typeDescr);
-
-    return emitDwarfGlobal(getDwarfVariableType(), vals, "llvm.dbg.variable");
+    return gIR->difactory.CreateVariable(
+        tag, // tag
+        gIR->func()->diSubprogram, // context
+        vd->toChars(), // name
+        DtoDwarfCompileUnit(vd->getCompilationModule()), // compile unit
+        vd->loc.linnum, // line num
+        type // type
+    );
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-static void dwarfDeclare(LLValue* var, LLGlobalVariable* varDescr)
+static void dwarfDeclare(LLValue* var, llvm::DIVariable divar)
 {
-    LLSmallVector<LLValue*,2> args(2);
-    args[0] = DtoBitCast(var, DBG_TYPE);
-    args[1] = DBG_CAST(varDescr);
-    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.declare"), args.begin(), args.end());
+    gIR->difactory.InsertDeclare(var, divar, gIR->scopebb());
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-static LLGlobalVariable* dwarfTypeDescription_impl(Type* type, LLGlobalVariable* cu, const char* c_name)
+static llvm::DIType dwarfTypeDescription_impl(Type* type, llvm::DICompileUnit cu, const char* c_name)
 {
     Type* t = type->toBasetype();
     if (t->ty == Tvoid)
-        return NULL;
+        return llvm::DIType(NULL);
     else if (t->isintegral() || t->isfloating())
         return dwarfBasicType(type, cu);
     else if (t->ty == Tpointer)
@@ -620,10 +413,10 @@
     else if (t->ty == Tarray || t->ty == Tstruct || t->ty == Tclass)
         return dwarfCompositeType(type, cu);
 
-    return NULL;
+    return llvm::DIType(NULL);
 }
 
-static LLGlobalVariable* dwarfTypeDescription(Type* type, LLGlobalVariable* cu, const char* c_name)
+static llvm::DIType dwarfTypeDescription(Type* type, llvm::DICompileUnit cu, const char* c_name)
 {
     Type* t = type->toBasetype();
     if (t->ty == Tclass)
@@ -640,20 +433,18 @@
     LOG_SCOPE;
 
     // get compile units
-    LLGlobalVariable* thisCU = DtoDwarfCompileUnit(gIR->dmodule);
-    LLGlobalVariable* varCU = thisCU;
-    if (vd->getModule() != gIR->dmodule)
-        varCU = DtoDwarfCompileUnit(vd->getModule());
+    llvm::DICompileUnit thisCU = DtoDwarfCompileUnit(gIR->dmodule);
+    llvm::DICompileUnit varCU = thisCU;
+    if (vd->getCompilationModule() != gIR->dmodule)
+        varCU = DtoDwarfCompileUnit(vd->getCompilationModule());
 
     // get type description
-    Type* t = vd->type->toBasetype();
-    LLGlobalVariable* TD = dwarfTypeDescription(vd->type, thisCU, NULL);
-    if (TD == NULL)
+    llvm::DIType TD = dwarfTypeDescription(vd->type, thisCU, NULL);
+    if (TD.isNull())
         return; // unsupported
 
     // get variable description
-    LLGlobalVariable* VD;
-    VD = dwarfVariable(vd, TD);
+    llvm::DIVariable VD = dwarfVariable(vd, TD);
 
     // declare
     dwarfDeclare(ll, VD);
@@ -661,7 +452,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-LLGlobalVariable* DtoDwarfCompileUnit(Module* m)
+llvm::DICompileUnit DtoDwarfCompileUnit(Module* m)
 {
     Logger::println("D to dwarf compile_unit");
     LOG_SCOPE;
@@ -669,52 +460,89 @@
     // we might be generating for an import
     if (!m->ir.irModule)
         m->ir.irModule = new IrModule(m, m->srcfile->toChars());
-    else if (m->ir.irModule->dwarfCompileUnit)
+    else if (!m->ir.irModule->diCompileUnit.isNull())
     {
-        if (m->ir.irModule->dwarfCompileUnit->getParent() == gIR->module)
-            return m->ir.irModule->dwarfCompileUnit;
+        assert (m->ir.irModule->diCompileUnit.getGV()->getParent() == gIR->module
+            && "debug info compile unit belongs to incorrect llvm module!");
+        return m->ir.irModule->diCompileUnit;
     }
 
-    LLGlobalVariable* gv = dwarfCompileUnit(m);
-    m->ir.irModule->dwarfCompileUnit = gv;
-    return gv;
+    // prepare srcpath
+    std::string srcpath(FileName::path(m->srcfile->name->toChars()));
+    if (!FileName::absolute(srcpath.c_str())) {
+        llvm::sys::Path tmp = llvm::sys::Path::GetCurrentDirectory();
+        tmp.appendComponent(srcpath);
+        srcpath = tmp.toString();
+        if (!srcpath.empty() && *srcpath.rbegin() != '/' && *srcpath.rbegin() != '\\')
+            srcpath = srcpath + '/';
+    }
+
+    // make compile unit
+    m->ir.irModule->diCompileUnit = gIR->difactory.CreateCompileUnit(
+        global.params.symdebug == 2 ? DW_LANG_C : DW_LANG_D,
+        m->srcfile->name->toChars(),
+        srcpath,
+        "LDC (http://www.dsource.org/projects/ldc)",
+//FIXME: What do these two mean?
+        false, // isMain,
+        false // isOptimized
+    );
+
+    return m->ir.irModule->diCompileUnit;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-LLGlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd)
+llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd)
 {
     Logger::println("D to dwarf subprogram");
     LOG_SCOPE;
 
+    llvm::DICompileUnit context = DtoDwarfCompileUnit(gIR->dmodule);
+    llvm::DICompileUnit definition = DtoDwarfCompileUnit(fd->getCompilationModule());
+
     // FIXME: duplicates ?
-    return dwarfSubProgram(
-        DtoDwarfCompileUnit(gIR->dmodule),
-        DtoDwarfCompileUnit(fd->getModule()),
-        fd->toPrettyChars(), fd->mangle(),
-        fd->loc.linnum,
-        fd->protection == PROTprivate);
+    return gIR->difactory.CreateSubprogram(
+        context, // context
+        fd->toPrettyChars(), // name
+        fd->toPrettyChars(), // display name
+        fd->mangle(), // linkage name
+        definition, // compile unit
+        fd->loc.linnum, // line no
+//FIXME: what's this type for?
+        llvm::DIType(NULL), // type
+        fd->protection == PROTprivate, // is local to unit
+        context.getGV() == definition.getGV() // isdefinition
+    );
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-LLGlobalVariable* DtoDwarfSubProgramInternal(const char* prettyname, const char* mangledname)
+llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char* mangledname)
 {
     Logger::println("D to dwarf subprogram");
     LOG_SCOPE;
 
+    llvm::DICompileUnit context = DtoDwarfCompileUnit(gIR->dmodule);
+
     // FIXME: duplicates ?
-    return dwarfSubProgram(
-        DtoDwarfCompileUnit(gIR->dmodule),
-        DtoDwarfCompileUnit(gIR->dmodule),
-        prettyname, mangledname,
-        0,
-        true);
+    return gIR->difactory.CreateSubprogram(
+        context, // context
+        prettyname, // name
+        prettyname, // display name
+        mangledname, // linkage name
+        context, // compile unit
+        0, // line no
+//FIXME: what's this type for?
+        llvm::DIType(NULL), // type
+        true, // is local to unit
+        true // isdefinition
+    );
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-LLGlobalVariable* DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd)
+llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd)
 {
     Logger::println("D to dwarf global_variable");
     LOG_SCOPE;
@@ -730,8 +558,8 @@
     Logger::println("D to dwarf funcstart");
     LOG_SCOPE;
 
-    assert(fd->ir.irFunc->dwarfSubProg);
-    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(fd->ir.irFunc->dwarfSubProg));
+    assert(!fd->ir.irFunc->diSubprogram.isNull());
+    gIR->difactory.InsertSubprogramStart(fd->ir.irFunc->diSubprogram, gIR->scopebb());
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
@@ -741,8 +569,8 @@
     Logger::println("D to dwarf funcend");
     LOG_SCOPE;
 
-    assert(fd->ir.irFunc->dwarfSubProg);
-    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(fd->ir.irFunc->dwarfSubProg));
+    assert(!fd->ir.irFunc->diSubprogram.isNull());
+    gIR->difactory.InsertRegionEnd(fd->ir.irFunc->diSubprogram, gIR->scopebb());
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
@@ -752,10 +580,10 @@
     Logger::println("D to dwarf stoppoint at line %u", ln);
     LOG_SCOPE;
 
-    LLSmallVector<LLValue*,3> args(3);
-    args[0] = DtoConstUint(ln);
-    args[1] = DtoConstUint(0);
-    FuncDeclaration* fd = gIR->func()->decl;
-    args[2] = DBG_CAST(DtoDwarfCompileUnit(fd->getModule()));
-    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.stoppoint"), args.begin(), args.end());
+    gIR->difactory.InsertStopPoint(
+        DtoDwarfCompileUnit(gIR->func()->decl->getCompilationModule()), // compile unit
+        ln, // line no
+        0, // col no
+        gIR->scopebb()
+    );
 }
--- a/gen/todebug.h	Sun Feb 08 05:26:54 2009 +0100
+++ b/gen/todebug.h	Sun Feb 08 16:50:22 2009 +0100
@@ -8,14 +8,14 @@
  * @param m
  * @return the Dwarf compile_unit.
  */
-llvm::GlobalVariable* DtoDwarfCompileUnit(Module* m);
+llvm::DICompileUnit DtoDwarfCompileUnit(Module* m);
 
 /**
  * Emit the Dwarf subprogram global for a function declaration fd.
  * @param fd
  * @return the Dwarf subprogram global.
  */
-llvm::GlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd);
+llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd);
 
 /**
  * Emit the Dwarf subprogram global for a internal function.
@@ -23,7 +23,7 @@
  * module ctors/dtors and unittests.
  * @return the Dwarf subprogram global.
  */
-llvm::GlobalVariable* DtoDwarfSubProgramInternal(const char* prettyname, const char* mangledname);
+llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char* mangledname);
 
 void DtoDwarfFuncStart(FuncDeclaration* fd);
 void DtoDwarfFuncEnd(FuncDeclaration* fd);
@@ -43,7 +43,7 @@
  * @param vd 
  * @return 
  */
-LLGlobalVariable* DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd);
+llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd);
 
 #endif // LDC_GEN_TODEBUG_H
 
--- a/gen/toobj.cpp	Sun Feb 08 05:26:54 2009 +0100
+++ b/gen/toobj.cpp	Sun Feb 08 16:50:22 2009 +0100
@@ -82,9 +82,14 @@
     // start by deleting the old object file
     deleteObjFile();
 
+    // name the module
+    std::string mname(toChars());
+    if (md != 0)
+        mname = md->toChars();
+
     // create a new ir state
     // TODO look at making the instance static and moving most functionality into IrModule where it belongs
-    IRState ir;
+    IRState ir(new llvm::Module(mname));
     gIR = &ir;
     ir.dmodule = this;
 
@@ -92,12 +97,6 @@
     IrDsymbol::resetAll();
     IrType::resetAll();
 
-    // name the module
-    std::string mname(toChars());
-    if (md != 0)
-        mname = md->toChars();
-    ir.module = new llvm::Module(mname);
-
     // module ir state
     // might already exist via import, just overwrite since
     // the global created for the filename must belong to the right llvm module
@@ -426,7 +425,7 @@
     // debug info
     LLGlobalVariable* subprog;
     if(global.params.symdebug) {
-        subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str());
+        subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()).getGV();
         builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog));
     }
 
@@ -471,7 +470,7 @@
     // debug info
     LLGlobalVariable* subprog;
     if(global.params.symdebug) {
-        subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str());
+        subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()).getGV();
         builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog));
     }
 
@@ -516,7 +515,7 @@
     // debug info
     LLGlobalVariable* subprog;
     if(global.params.symdebug) {
-        subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str());
+        subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()).getGV();
         builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog));
     }
 
@@ -573,7 +572,7 @@
     // debug info
     LLGlobalVariable* subprog;
     if(global.params.symdebug) {
-        subprog = DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str());
+        subprog = DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str()).getGV();
         builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog));
     }
 
--- a/ir/irfunction.cpp	Sun Feb 08 05:26:54 2009 +0100
+++ b/ir/irfunction.cpp	Sun Feb 08 16:50:22 2009 +0100
@@ -31,8 +31,6 @@
     _arguments = NULL;
     _argptr = NULL;
     
-    dwarfSubProg = NULL;
-
     nextUnique.push(0);
 }
 
--- a/ir/irfunction.h	Sun Feb 08 05:26:54 2009 +0100
+++ b/ir/irfunction.h	Sun Feb 08 16:50:22 2009 +0100
@@ -28,7 +28,7 @@
     llvm::Value* _arguments;
     llvm::Value* _argptr;
     
-    llvm::Constant* dwarfSubProg;
+    llvm::DISubprogram diSubprogram;
 
     // pushes a unique label scope of the given name
     void pushUniqueLabelScope(const char* name);
--- a/ir/irmodule.cpp	Sun Feb 08 05:26:54 2009 +0100
+++ b/ir/irmodule.cpp	Sun Feb 08 16:50:22 2009 +0100
@@ -10,8 +10,6 @@
     LLConstant* slice = DtoConstString(srcfilename);
     fileName = new llvm::GlobalVariable(
         slice->getType(), true, LLGlobalValue::InternalLinkage, slice, ".modulefilename", gIR->module);
-
-    dwarfCompileUnit = NULL;
 }
 
 IrModule::~IrModule()
--- a/ir/irmodule.h	Sun Feb 08 05:26:54 2009 +0100
+++ b/ir/irmodule.h	Sun Feb 08 16:50:22 2009 +0100
@@ -12,8 +12,8 @@
 
     Module* M;
 
-    LLGlobalVariable* dwarfCompileUnit;
     LLGlobalVariable* fileName;
+    llvm::DICompileUnit diCompileUnit;
 };
 
 #endif
--- a/ir/irstruct.cpp	Sun Feb 08 05:26:54 2009 +0100
+++ b/ir/irstruct.cpp	Sun Feb 08 16:50:22 2009 +0100
@@ -33,7 +33,8 @@
 :   initOpaque(llvm::OpaqueType::get()),
     classInfoOpaque(llvm::OpaqueType::get()),
     vtblTy(llvm::OpaqueType::get()),
-    vtblInitTy(llvm::OpaqueType::get())
+    vtblInitTy(llvm::OpaqueType::get()),
+    diCompositeType(NULL)
 {
     aggrdecl = aggr;
     defaultFound = false;
@@ -57,8 +58,6 @@
     classInfoDefined = false;
 
     packed = false;
-
-    dwarfComposite = NULL;
 }
 
 IrStruct::~IrStruct()
--- a/ir/irstruct.h	Sun Feb 08 05:26:54 2009 +0100
+++ b/ir/irstruct.h	Sun Feb 08 16:50:22 2009 +0100
@@ -148,8 +148,8 @@
     // align(1) struct S { ... }
     bool packed;
 
-    // dwarf composite global
-    LLGlobalVariable* dwarfComposite;
+    // composite type debug description
+    llvm::DICompositeType diCompositeType;
 };
 
 //////////////////////////////////////////////////////////////////////////////