changeset 797:340acf1535d0

Removed KDevelop3 project files, CMake can generate them just fine! Fixed function literals in static initializers. Changed alignment of delegates from 2*PTRSIZE to just PTRSIZE. Changed errors to go to stderr instead of stdout. Fairly major rewriting of struct/union/class handling, STILL A BIT BUGGY !!!
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sat, 29 Nov 2008 21:25:43 +0100
parents 6e7a4c3b64d2
children 92ea3015ace6 d14e4594c7d7
files dmd/aggregate.h dmd/attrib.c dmd/attrib.h dmd/declaration.c dmd/declaration.h dmd/expression.h dmd/mars.c dmd/mars.h dmd/mtype.c dmd/mtype.h dmd2/aggregate.h dmd2/attrib.c dmd2/attrib.h dmd2/declaration.c dmd2/declaration.h dmd2/expression.h dmd2/mars.c dmd2/mars.h dmd2/mtype.c dmd2/mtype.h gen/arrays.cpp gen/arrays.h gen/classes.cpp gen/functions.cpp gen/irstate.h gen/llvmhelpers.cpp gen/llvmhelpers.h gen/runtime.cpp gen/statements.cpp gen/structs.cpp gen/structs.h gen/tocall.cpp gen/todebug.cpp gen/toir.cpp gen/tollvm.cpp gen/tollvm.h gen/toobj.cpp gen/typinf.cpp ir/irstruct.cpp ir/irstruct.h ir/irtype.cpp ir/irtype.h ir/irvar.cpp ir/irvar.h llvmdc.kdevelop llvmdc.kdevelop.filelist tests/mini/interface3.d
diffstat 47 files changed, 2100 insertions(+), 2395 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/aggregate.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd/aggregate.h	Sat Nov 29 21:25:43 2008 +0100
@@ -45,7 +45,6 @@
     class ConstantStruct;
     class GlobalVariable;
 }
-struct DUnion;
 
 struct AggregateDeclaration : ScopeDsymbol
 {
@@ -258,9 +257,6 @@
 
     Symbol *vtblsym;
 
-    // llvm
-    void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result);
-
     ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
 };
 
--- a/dmd/attrib.c	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd/attrib.c	Sat Nov 29 21:25:43 2008 +0100
@@ -616,7 +616,6 @@
 	sc->flags = 0;
 	aad.structalign = sc->structalign;
 	aad.parent = ad;
-
 	for (unsigned i = 0; i < decl->dim; i++)
 	{
 	    Dsymbol *s = (Dsymbol *)decl->data[i];
@@ -672,6 +671,9 @@
 	{
 	    VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
 
+        // LDC
+        v->offset2 = sc->offset;
+
 	    v->offset += sc->offset;
 
         // LDC
--- a/dmd/attrib.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd/attrib.h	Sat Nov 29 21:25:43 2008 +0100
@@ -50,7 +50,7 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     AttribDeclaration *isAttribDeclaration() { return this; }
 
-    void toObjFile(int multiobj);			// compile to .obj file
+    virtual void toObjFile(int multiobj);			// compile to .obj file
     int cvMember(unsigned char *p);
 };
 
@@ -107,6 +107,9 @@
     void semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     const char *kind();
+
+    // LDC
+    void toObjFile(int multiobj);           // compile to .obj file
 };
 
 struct PragmaDeclaration : AttribDeclaration
--- a/dmd/declaration.c	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd/declaration.c	Sat Nov 29 21:25:43 2008 +0100
@@ -624,6 +624,7 @@
 
     // LDC
     anonDecl = NULL;
+    offset2 = 0;
 }
 
 Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
--- a/dmd/declaration.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd/declaration.h	Sat Nov 29 21:25:43 2008 +0100
@@ -273,6 +273,7 @@
 
     // LDC
     AnonDeclaration* anonDecl;
+    unsigned offset2;
 };
 
 /**************************************************************/
--- a/dmd/expression.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd/expression.h	Sat Nov 29 21:25:43 2008 +0100
@@ -628,6 +628,9 @@
     int inlineCost(InlineCostState *ics);
     //Expression *doInline(InlineDoState *ids);
     //Expression *inlineScan(InlineScanState *iss);
+
+    // LDC
+    virtual llvm::Constant *toConstElem(IRState *irs);
 };
 
 // Declaration of a symbol
--- a/dmd/mars.c	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd/mars.c	Sat Nov 29 21:25:43 2008 +0100
@@ -1196,9 +1196,9 @@
 	    m->inlineScan();
 	}
     }
+#endif
     if (global.errors)
 	fatal();
-#endif
 
     // Generate output files
     for (i = 0; i < modules.dim; i++)
--- a/dmd/mars.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd/mars.h	Sat Nov 29 21:25:43 2008 +0100
@@ -345,7 +345,7 @@
 void halt();
 
 /*** Where to send error messages ***/
-#if IN_GCC
+#if IN_GCC || IN_LLVM
 #define stdmsg stderr
 #else
 #define stdmsg stdout
--- a/dmd/mtype.c	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd/mtype.c	Sat Nov 29 21:25:43 2008 +0100
@@ -3186,6 +3186,14 @@
     return PTRSIZE * 2;
 }
 
+// LDC added, no reason to align to 2*PTRSIZE
+unsigned TypeDelegate::alignsize()
+{
+    // A Delegate consists of two ptr values, so align it on pointer size
+    // boundary
+    return PTRSIZE;
+}
+
 void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
     if (mod != this->mod)
--- a/dmd/mtype.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd/mtype.h	Sat Nov 29 21:25:43 2008 +0100
@@ -451,6 +451,7 @@
     Type *syntaxCopy();
     Type *semantic(Loc loc, Scope *sc);
     d_uns64 size(Loc loc);
+    unsigned alignsize(); // added in LDC
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *defaultInit(Loc loc);
     int isZeroInit();
--- a/dmd2/aggregate.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd2/aggregate.h	Sat Nov 29 21:25:43 2008 +0100
@@ -45,7 +45,6 @@
     class ConstantStruct;
     class GlobalVariable;
 }
-struct DUnion;
 
 struct AggregateDeclaration : ScopeDsymbol
 {
@@ -264,9 +263,6 @@
 
     Symbol *vtblsym;
 
-    // llvm
-    void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result);
-
     ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
 };
 
--- a/dmd2/attrib.c	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd2/attrib.c	Sat Nov 29 21:25:43 2008 +0100
@@ -629,7 +629,6 @@
 	sc->flags = 0;
 	aad.structalign = sc->structalign;
 	aad.parent = ad;
-
 	for (unsigned i = 0; i < decl->dim; i++)
 	{
 	    Dsymbol *s = (Dsymbol *)decl->data[i];
@@ -685,6 +684,9 @@
 	{
 	    VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
 
+        // LDC
+        v->offset2 = sc->offset;
+
 	    v->offset += sc->offset;
 
         // LDC
--- a/dmd2/attrib.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd2/attrib.h	Sat Nov 29 21:25:43 2008 +0100
@@ -50,7 +50,7 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     AttribDeclaration *isAttribDeclaration() { return this; }
 
-    void toObjFile(int multiobj);			// compile to .obj file
+    virtual void toObjFile(int multiobj);			// compile to .obj file
     int cvMember(unsigned char *p);
 };
 
--- a/dmd2/declaration.c	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd2/declaration.c	Sat Nov 29 21:25:43 2008 +0100
@@ -618,6 +618,7 @@
 
     // LDC
     anonDecl = NULL;
+    offset2 = 0;
 }
 
 Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
--- a/dmd2/declaration.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd2/declaration.h	Sat Nov 29 21:25:43 2008 +0100
@@ -279,6 +279,7 @@
 
     // LDC
     AnonDeclaration* anonDecl;
+    unsigned offset2;
 };
 
 /**************************************************************/
--- a/dmd2/expression.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd2/expression.h	Sat Nov 29 21:25:43 2008 +0100
@@ -653,6 +653,9 @@
     int inlineCost(InlineCostState *ics);
     //Expression *doInline(InlineDoState *ids);
     //Expression *inlineScan(InlineScanState *iss);
+
+    // LDC
+    virtual llvm::Constant *toConstElem(IRState *irs);
 };
 
 // Declaration of a symbol
--- a/dmd2/mars.c	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd2/mars.c	Sat Nov 29 21:25:43 2008 +0100
@@ -1220,9 +1220,9 @@
 	    m->inlineScan();
 	}
     }
+#endif
     if (global.errors)
 	fatal();
-#endif
 
     // Generate output files
     for (i = 0; i < modules.dim; i++)
--- a/dmd2/mars.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd2/mars.h	Sat Nov 29 21:25:43 2008 +0100
@@ -350,7 +350,7 @@
 void halt();
 
 /*** Where to send error messages ***/
-#if IN_GCC
+#if IN_GCC || IN_LLVM
 #define stdmsg stderr
 #else
 #define stdmsg stdout
--- a/dmd2/mtype.c	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd2/mtype.c	Sat Nov 29 21:25:43 2008 +0100
@@ -3694,6 +3694,14 @@
     return PTRSIZE * 2;
 }
 
+// LDC added, no reason to align to 2*PTRSIZE
+unsigned TypeDelegate::alignsize()
+{
+    // A Delegate consists of two ptr values, so align it on pointer size
+    // boundary
+    return PTRSIZE;
+}
+
 void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
     if (mod != this->mod)
--- a/dmd2/mtype.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/dmd2/mtype.h	Sat Nov 29 21:25:43 2008 +0100
@@ -516,6 +516,7 @@
     Type *syntaxCopy();
     Type *semantic(Loc loc, Scope *sc);
     d_uns64 size(Loc loc);
+    unsigned alignsize(); // added in LDC
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *defaultInit(Loc loc);
     int isZeroInit();
--- a/gen/arrays.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/arrays.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -208,6 +208,9 @@
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
+
+// FIXME: this looks like it could use a cleanup
+
 LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
 {
     Logger::println("DtoConstArrayInitializer: %s | %s", arrinit->toChars(), arrinit->type->toChars());
@@ -241,6 +244,9 @@
     Type* arrnext = arrinittype->nextOf();
     const LLType* elemty = DtoType(arrinittype->nextOf());
 
+    // true if there is a mismatch with one of the initializers
+    bool mismatch = false;
+
     assert(arrinit->index.dim == arrinit->value.dim);
     for (unsigned i=0,j=0; i < tdim; ++i)
     {
@@ -292,23 +298,51 @@
             v = DtoConstInitializer(arrinit->loc, t->nextOf(), init);
         assert(v);
 
+        // global arrays of unions might have type mismatch for each element
+        // if there is any mismatch at all, we need to use a struct instead :/
+        if (v->getType() != elemty)
+            mismatch = true;
+
         inits[i] = v;
         if (Logger::enabled())
             Logger::cout() << "llval: " << *v << '\n';
     }
 
     Logger::println("building constant array");
+
+    LLConstant* constarr;
     const LLArrayType* arrty = LLArrayType::get(elemty,tdim);
-    LLConstant* constarr = LLConstantArray::get(arrty, inits);
+
+    if (mismatch)
+    {
+        constarr = LLConstantStruct::get(inits);
+    }
+    else
+    {
+        constarr = LLConstantArray::get(arrty, inits);
+    }
+
+#if 0
+    if (Logger::enabled())
+    {
+        Logger::cout() << "array type: " << *arrty << '\n';
+        size_t n = inits.size();
+        for (size_t i=0; i<n; i++)
+            Logger::cout() << "  init " << i << " = " << *inits[i] << '\n';
+    }
+#endif
 
     if (arrinittype->ty == Tsarray)
         return constarr;
     else
         assert(arrinittype->ty == Tarray);
 
-    LLGlobalVariable* gvar = new LLGlobalVariable(arrty,true,LLGlobalValue::InternalLinkage,constarr,".constarray",gIR->module);
+    LLGlobalVariable* gvar = new LLGlobalVariable(constarr->getType(),true,LLGlobalValue::InternalLinkage,constarr,".constarray",gIR->module);
     LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
+
     LLConstant* gep = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
+    gep = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(elemty));
+
     return DtoConstSlice(DtoConstSize_t(tdim),gep);
 }
 
@@ -795,24 +829,6 @@
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-LLConstant* DtoConstStaticArray(const LLType* t, LLConstant* c)
-{
-    const LLArrayType* at = isaArray(t);
-    assert(at);
-
-    if (isaArray(at->getElementType()))
-    {
-        c = DtoConstStaticArray(at->getElementType(), c);
-    }
-    else {
-        assert(at->getElementType() == c->getType());
-    }
-    std::vector<LLConstant*> initvals;
-    initvals.resize(at->getNumElements(), c);
-    return llvm::ConstantArray::get(at, initvals);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
 LLValue* DtoArrayLen(DValue* v)
 {
     Logger::println("DtoArrayLen");
--- a/gen/arrays.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/arrays.h	Sat Nov 29 21:25:43 2008 +0100
@@ -9,7 +9,6 @@
 
 LLConstant* DtoConstArrayInitializer(ArrayInitializer* si);
 LLConstant* DtoConstSlice(LLConstant* dim, LLConstant* ptr);
-LLConstant* DtoConstStaticArray(const LLType* t, LLConstant* c);
 
 void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src);
 void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src);
--- a/gen/classes.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/classes.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -21,76 +21,163 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-static void LLVM_AddBaseClassInterfaces(ClassDeclaration* target, BaseClasses* bcs)
+// adds interface b to target, if newinstance != 0, then target must provide all
+// functions required to implement b (it reimplements b)
+static void add_interface(ClassDeclaration* target, BaseClass* b, int newinstance)
 {
-    // add base class data members first
-    for (int j=0; j<bcs->dim; j++)
-    {
-        BaseClass* bc = (BaseClass*)(bcs->data[j]);
+    Logger::println("adding interface: %s", b->base->toChars());
+    LOG_SCOPE;
+
+    InterfaceDeclaration* inter = b->base->isInterfaceDeclaration();
+    DtoResolveClass(inter);
+
+    assert(inter);
+    IrStruct* irstruct = target->ir.irStruct;
+    assert(irstruct);
 
-        // base *classes* might add more interfaces?
-        DtoResolveClass(bc->base);
-        LLVM_AddBaseClassInterfaces(target, &bc->base->baseclasses);
+    // add interface to map/list
+    // if it's already inserted in the map, it's because another interface has it as baseclass
+    // but if it appears here, it's because we're reimplementing it, so we overwrite the IrInterface entry
+    IrInterface* iri;
+    bool overwrite = false;
+    if (irstruct->interfaceMap.find(inter) != irstruct->interfaceMap.end())
+    {
+        overwrite = true;
+    }
 
-        // resolve interfaces while we're at it
-        if (bc->base->isInterfaceDeclaration())
+    iri = new IrInterface(b);
+    // add to map
+    if (overwrite)
+        irstruct->interfaceMap[b->base] = iri;
+    else
+        irstruct->interfaceMap.insert(std::make_pair(b->base, iri));
+    // add to ordered list
+    irstruct->interfaceVec.push_back(iri);
+
+    // assign this iri to all base interfaces of this one
+    for (unsigned j = 0; j < b->baseInterfaces_dim; j++)
+    {
+        BaseClass *bc = &b->baseInterfaces[j];
+        // add to map
+        if (irstruct->interfaceMap.find(bc->base) == irstruct->interfaceMap.end())
         {
-            // don't add twice
-            if (target->ir.irStruct->interfaceMap.find(bc->base) == target->ir.irStruct->interfaceMap.end())
-            {
-                Logger::println("adding interface '%s'", bc->base->toPrettyChars());
-                IrInterface* iri = new IrInterface(bc);
+            irstruct->interfaceMap.insert(std::make_pair(bc->base, iri));
+        }
+    }
+
+    // build the interface vtable
+    b->fillVtbl(target, &b->vtbl, newinstance);
+
+    // add the vtable type
+    assert(inter->type->ir.type);
+    irstruct->types.push_back( inter->type->ir.type->get() );
+    // set and increment index
+    iri->index = irstruct->index++;
+}
+
+static void add_class_data(ClassDeclaration* target, ClassDeclaration* cd)
+{
+    Logger::println("Adding data from class: %s", cd->toChars());
+    LOG_SCOPE;
 
-                // add to map
-                target->ir.irStruct->interfaceMap.insert(std::make_pair(bc->base, iri));
-                // add to ordered list
-                target->ir.irStruct->interfaceVec.push_back(iri);
+    // recurse into baseClasses
+    if (cd->baseClass)
+    {
+        add_class_data(target, cd->baseClass);
+        //offset = baseClass->structsize;
+    }
 
-                // Fill in vtbl[]
-                if (!target->isAbstract()) {
-                    bc->fillVtbl(target, &bc->vtbl, 0);
-                }
-            }
+    // add members
+    Array* arr = cd->members;
+    for (int k=0; k < arr->dim; k++) {
+        Dsymbol* s = (Dsymbol*)arr->data[k];
+        s->toObjFile(0);
+    }
+
+    // add interfaces
+    if (cd->vtblInterfaces)
+    {
+        Logger::println("num vtbl interfaces: %u", cd->vtblInterfaces->dim);
+        for (int i = 0; i < cd->vtblInterfaces->dim; i++)
+        {
+            BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i];
+            assert(b);
+            // create new instances only for explicitly derived interfaces
+            add_interface(target, b, (cd == target));
         }
     }
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-static void LLVM_AddBaseClassData(IrStruct* irstruct, BaseClasses* bcs)
+static void DtoResolveInterface(InterfaceDeclaration* cd)
 {
-    // add base class data members first
-    for (int j=0; j<bcs->dim; j++)
-    {
-        BaseClass* bc = (BaseClass*)(bcs->data[j]);
+    if (cd->ir.resolved) return;
+    cd->ir.resolved = true;
+
+    Logger::println("DtoResolveInterface(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
+    LOG_SCOPE;
 
-        // interfaces never add data fields
-        if (bc->base->isInterfaceDeclaration())
-            continue;
+    // get the TypeClass
+    assert(cd->type->ty == Tclass);
+    TypeClass* ts = (TypeClass*)cd->type;
 
-        // recursively add baseclass data
-        LLVM_AddBaseClassData(irstruct, &bc->base->baseclasses);
+    // create the IrStruct, we need somewhere to store the classInfo
+    assert(!cd->ir.irStruct);
+    IrStruct* irstruct = new IrStruct(cd);
+    cd->ir.irStruct = irstruct;
 
-        Array* arr = &bc->base->fields;
-        if (arr->dim == 0)
-            continue;
-
-        Logger::println("Adding base class members of %s", bc->base->toChars());
+    // handle base interfaces
+    if (cd->baseclasses.dim)
+    {
+        Logger::println("num baseclasses: %u", cd->baseclasses.dim);
         LOG_SCOPE;
 
-        for (int k=0; k < arr->dim; k++) {
-            VarDeclaration* v = (VarDeclaration*)(arr->data[k]);
-            Logger::println("Adding field: %s %s", v->type->toChars(), v->toChars());
-            // init fields, used to happen in VarDeclaration::toObjFile
-            irstruct->addField(v);
+        for (int i=0; i<cd->baseclasses.dim; i++)
+        {
+            BaseClass* bc = (BaseClass*)cd->baseclasses.data[i];
+            Logger::println("baseclass %d: %s", i, bc->base->toChars());
+
+            InterfaceDeclaration* id = bc->base->isInterfaceDeclaration();
+            assert(id);
+
+            DtoResolveInterface(id);
+    
+            // add to interfaceInfos
+            IrInterface* iri = new IrInterface(bc);
+            irstruct->interfaceVec.push_back(iri);
         }
     }
+
+    // create the type
+    const LLType* t = LLArrayType::get(getVoidPtrType(), cd->vtbl.dim);
+    assert(!ts->ir.type);
+    ts->ir.type = new LLPATypeHolder(getPtrToType(t));
+
+    // request declaration
+    gIR->declareList.push_back(cd);
+
+    // handle members
+    // like "nested" interfaces
+    Array* arr = cd->members;
+    for (int k=0; k < arr->dim; k++) {
+        Dsymbol* s = (Dsymbol*)arr->data[k];
+        s->toObjFile(0);
+    }
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+// FIXME: this needs to be cleaned up
+
 void DtoResolveClass(ClassDeclaration* cd)
 {
+    if (InterfaceDeclaration* id = cd->isInterfaceDeclaration())
+    {
+        DtoResolveInterface(id);
+        return;
+    }
+
     if (cd->ir.resolved) return;
     cd->ir.resolved = true;
 
@@ -103,11 +190,20 @@
     assert(cd->type->ty == Tclass);
     TypeClass* ts = (TypeClass*)cd->type;
 
-    // make sure the IrStruct is created
-    IrStruct* irstruct = cd->ir.irStruct;
-    if (!irstruct) {
-        irstruct = new IrStruct(ts);
-        cd->ir.irStruct = irstruct;
+    // create the IrStruct
+    assert(!cd->ir.irStruct);
+    IrStruct* irstruct = new IrStruct(cd);
+    cd->ir.irStruct = irstruct;
+
+    // create the type
+    ts->ir.type = new LLPATypeHolder(llvm::OpaqueType::get());
+
+    // if it just a forward declaration?
+    if (cd->sizeok != 1)
+    {
+        // just name the type
+        gIR->module->addTypeName(cd->mangle(), ts->ir.type->get());
+        return;
     }
 
     // resolve the base class
@@ -115,247 +211,45 @@
         DtoResolveClass(cd->baseClass);
     }
 
-    // resolve interface vtables
-    /*if (cd->vtblInterfaces) {
-        Logger::println("Vtbl interfaces for '%s'", cd->toPrettyChars());
-        LOG_SCOPE;
-        for (int i=0; i < cd->vtblInterfaces->dim; i++) {
-            BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i];
-            ClassDeclaration *id = b->base;
-            Logger::println("Vtbl interface: '%s'", id->toPrettyChars());
-            DtoResolveClass(id);
-            // Fill in vtbl[]
-            b->fillVtbl(cd, &b->vtbl, 1);
-        }
-    }*/
-
     // push state
     gIR->structs.push_back(irstruct);
-    gIR->classes.push_back(cd);
-
-    // vector holding the field types
-    std::vector<const LLType*> fieldtypes;
 
     // add vtable
-    ts->ir.vtblType = new llvm::PATypeHolder(llvm::OpaqueType::get());
-    const LLType* vtabty = getPtrToType(ts->ir.vtblType->get());
-    fieldtypes.push_back(vtabty);
+    irstruct->types.push_back(getPtrToType(irstruct->vtblTy.get()));
+    irstruct->index++;
 
     // add monitor
-    fieldtypes.push_back(getVoidPtrType());
-
-    // add base class data fields first
-    LLVM_AddBaseClassData(irstruct, &cd->baseclasses);
-
-    // add own fields
-    Array* fields = &cd->fields;
-    for (int k=0; k < fields->dim; k++)
-    {
-        VarDeclaration* v = (VarDeclaration*)fields->data[k];
-        Logger::println("Adding field: %s %s", v->type->toChars(), v->toChars());
-        // init fields, used to happen in VarDeclaration::toObjFile
-        irstruct->addField(v);
-    }
-
-    // then add other members of us, if any
-    if(cd->members) {
-        for (int k=0; k < cd->members->dim; k++) {
-            Dsymbol* dsym = (Dsymbol*)(cd->members->data[k]);
-            dsym->toObjFile(0); // TODO: multiobj
-        }
-    }
-
-    // resolve class data fields (possibly unions)
-    Logger::println("doing class fields");
+    irstruct->types.push_back(getVoidPtrType());
+    irstruct->index++;
 
-    if (irstruct->offsets.empty())
-    {
-        Logger::println("has no fields");
-    }
-    else
-    {
-        Logger::println("has fields");
-        unsigned prevsize = (unsigned)-1;
-        unsigned lastoffset = (unsigned)-1;
-        const LLType* fieldtype = NULL;
-        VarDeclaration* fieldinit = NULL;
-        size_t fieldpad = 0;
-        int idx = 0;
-        for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
-            // first iteration
-            if (lastoffset == (unsigned)-1) {
-                lastoffset = i->first;
-                fieldtype = i->second.type;
-                fieldinit = i->second.var;
-                prevsize = getABITypeSize(fieldtype);
-                i->second.var->ir.irField->index = idx;
-            }
-            // colliding offset?
-            else if (lastoffset == i->first) {
-                size_t s = getABITypeSize(i->second.type);
-                if (s > prevsize) {
-                    fieldpad += s - prevsize;
-                    prevsize = s;
-                }
-                cd->ir.irStruct->hasUnions = true;
-                i->second.var->ir.irField->index = idx;
-            }
-            // intersecting offset?
-            else if (i->first < (lastoffset + prevsize)) {
-                size_t s = getABITypeSize(i->second.type);
-                assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
-                cd->ir.irStruct->hasUnions = true;
-                i->second.var->ir.irField->index = idx;
-                i->second.var->ir.irField->indexOffset = (i->first - lastoffset) / s;
-            }
-            // fresh offset
-            else {
-                // commit the field
-                fieldtypes.push_back(fieldtype);
-                irstruct->defaultFields.push_back(fieldinit);
-                if (fieldpad) {
-                    fieldtypes.push_back(llvm::ArrayType::get(LLType::Int8Ty, fieldpad));
-                    irstruct->defaultFields.push_back(NULL);
-                    idx++;
-                }
+    // add class data fields and interface vtables recursively
+    add_class_data(cd, cd);
 
-                idx++;
-
-                // start new
-                lastoffset = i->first;
-                fieldtype = i->second.type;
-                fieldinit = i->second.var;
-                prevsize = getABITypeSize(fieldtype);
-                i->second.var->ir.irField->index = idx;
-                fieldpad = 0;
-            }
-        }
-        fieldtypes.push_back(fieldtype);
-        irstruct->defaultFields.push_back(fieldinit);
-        if (fieldpad) {
-            fieldtypes.push_back(llvm::ArrayType::get(LLType::Int8Ty, fieldpad));
-            irstruct->defaultFields.push_back(NULL);
-        }
-    }
-
-    // populate interface map
-    {
-        Logger::println("Adding interfaces to '%s'", cd->toPrettyChars());
-        LOG_SCOPE;
-        LLVM_AddBaseClassInterfaces(cd, &cd->baseclasses);
-        Logger::println("%d interfaces added", cd->ir.irStruct->interfaceVec.size());
-        assert(cd->ir.irStruct->interfaceVec.size() == cd->ir.irStruct->interfaceMap.size());
-    }
-
-    // add interface vtables at the end
-    int interIdx = (int)fieldtypes.size();
-    for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i)
-    {
-        IrInterface* iri = *i;
-        ClassDeclaration* id = iri->decl;
-
-        // set vtbl type
-        TypeClass* itc = (TypeClass*)id->type;
-        const LLType* ivtblTy = itc->ir.vtblType->get();
-        assert(ivtblTy);
-        if (Logger::enabled())
-            Logger::cout() << "interface vtbl type: " << *ivtblTy << '\n';
-        fieldtypes.push_back(getPtrToType(ivtblTy));
-
-        // fix the interface vtable type
-        assert(iri->vtblTy == NULL);
-        iri->vtblTy = new llvm::PATypeHolder(ivtblTy);
-
-        // set index
-        iri->index = interIdx++;
-    }
-    Logger::println("%d interface vtables added", cd->ir.irStruct->interfaceVec.size());
-    assert(cd->ir.irStruct->interfaceVec.size() == cd->ir.irStruct->interfaceMap.size());
+    // check if errors occured while building interface vtables
+    if (global.errors)
+        fatal();
 
     // create type
-    const llvm::StructType* structtype = llvm::StructType::get(fieldtypes);
+    assert(irstruct->index == irstruct->types.size());
+    const LLType* structtype = irstruct->build();
 
     // refine abstract types for stuff like: class C {C next;}
-    assert(irstruct->recty != 0);
-    llvm::PATypeHolder& spa = irstruct->recty;
-    llvm::cast<llvm::OpaqueType>(spa.get())->refineAbstractTypeTo(structtype);
-    structtype = isaStruct(spa.get());
-
-    // make it official
-    if (!ts->ir.type)
-        ts->ir.type = new llvm::PATypeHolder(structtype);
-    else
-        *ts->ir.type = structtype;
-    spa = *ts->ir.type;
+    llvm::PATypeHolder* spa = ts->ir.type;
+    llvm::cast<llvm::OpaqueType>(spa->get())->refineAbstractTypeTo(structtype);
+    structtype = isaStruct(spa->get());
 
     // name the type
     gIR->module->addTypeName(cd->mangle(), ts->ir.type->get());
 
-    // create vtable type
-    llvm::GlobalVariable* svtblVar = 0;
-#if OPAQUE_VTBLS
-    // void*[vtbl.dim]
-    const llvm::ArrayType* svtbl_ty
-        = llvm::ArrayType::get(getVoidPtrType(), cd->vtbl.dim);
-
-#else
-    std::vector<const LLType*> sinits_ty;
-
-    for (int k=0; k < cd->vtbl.dim; k++)
-    {
-        Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k];
-        assert(dsym);
-        //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
+    // refine vtable type
 
-        if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
-            DtoResolveFunction(fd);
-            //assert(fd->type->ty == Tfunction);
-            //TypeFunction* tf = (TypeFunction*)fd->type;
-            //const LLType* fpty = getPtrToType(tf->ir.type->get());
-            const llvm::FunctionType* vfty = DtoBaseFunctionType(fd);
-            const LLType* vfpty = getPtrToType(vfty);
-            sinits_ty.push_back(vfpty);
-        }
-        else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) {
-            Logger::println("*** ClassDeclaration in vtable: %s", cd2->toChars());
-            const LLType* cinfoty;
-            if (cd->isInterfaceDeclaration()) {
-                cinfoty = DtoInterfaceInfoType();
-            }
-            else if (cd != ClassDeclaration::classinfo) {
-                cinfoty = ClassDeclaration::classinfo->type->ir.type->get();
-            }
-            else {
-                // this is the ClassInfo class, the type is this type
-                cinfoty = ts->ir.type->get();
-            }
-            const LLType* cty = getPtrToType(cinfoty);
-            sinits_ty.push_back(cty);
-        }
-        else
-        assert(0);
-    }
-
-    // get type
-    assert(!sinits_ty.empty());
-    const llvm::StructType* svtbl_ty = llvm::StructType::get(sinits_ty);
-#endif
-
-    // refine for final vtable type
-    llvm::cast<llvm::OpaqueType>(ts->ir.vtblType->get())->refineAbstractTypeTo(svtbl_ty);
-
-#if !OPAQUE_VTBLS
-    // name vtbl type
-    std::string styname(cd->mangle());
-    styname.append("__vtblType");
-    gIR->module->addTypeName(styname, svtbl_ty);
-#endif
+    // void*[vtbl.dim]
+    llvm::cast<llvm::OpaqueType>(irstruct->vtblTy.get())->refineAbstractTypeTo(LLArrayType::get(getVoidPtrType(), cd->vtbl.dim));
 
     // log
-    //Logger::cout() << "final class type: " << *ts->ir.type->get() << '\n';
+    Logger::cout() << "final class type: " << *ts->ir.type->get() << '\n';
 
     // pop state
-    gIR->classes.pop_back();
     gIR->structs.pop_back();
 
     // queue declare
@@ -364,12 +258,79 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoDeclareClass(ClassDeclaration* cd)
+static void DtoDeclareInterface(InterfaceDeclaration* cd)
 {
     if (cd->ir.declared) return;
     cd->ir.declared = true;
 
-    Logger::println("DtoDeclareClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
+    Logger::println("DtoDeclareInterface(%s): %s", cd->toPrettyChars(), cd->locToChars());
+    LOG_SCOPE;
+
+    assert(cd->ir.irStruct);
+    IrStruct* irstruct = cd->ir.irStruct;
+
+    // get interface info type
+    const llvm::StructType* infoTy = DtoInterfaceInfoType();
+
+    // interface info array
+    if (!irstruct->interfaceVec.empty()) {
+        // symbol name
+        std::string nam = "_D";
+        nam.append(cd->mangle());
+        nam.append("16__interfaceInfosZ");
+
+        llvm::GlobalValue::LinkageTypes linkage = DtoLinkage(cd);
+
+        // resolve array type
+        const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, irstruct->interfaceVec.size());
+        // declare global
+        irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, linkage, NULL, nam, gIR->module);
+
+        // do each interface info
+        unsigned idx = 0;
+        size_t n = irstruct->interfaceVec.size();
+        for (size_t i=0; i < n; i++)
+        {
+            IrInterface* iri = irstruct->interfaceVec[i];
+            ClassDeclaration* id = iri->decl;
+
+            // always create interfaceinfos
+            LLConstant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)};
+            iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2);
+            idx++;
+        }
+    }
+
+    // declare the classinfo
+    DtoDeclareClassInfo(cd);
+
+    // request const init
+    gIR->constInitList.push_back(cd);
+
+    // emit typeinfo and request definition
+    if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd))
+    {
+        gIR->defineList.push_back(cd);
+        DtoTypeInfoOf(cd->type, false);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// FIXME: this needs to be cleaned up
+
+void DtoDeclareClass(ClassDeclaration* cd)
+{
+    if (InterfaceDeclaration* id = cd->isInterfaceDeclaration())
+    {
+        DtoDeclareInterface(id);
+        return;
+    }
+
+    if (cd->ir.declared) return;
+    cd->ir.declared = true;
+
+    Logger::println("DtoDeclareClass(%s): %s", cd->toPrettyChars(), cd->locToChars());
     LOG_SCOPE;
 
     //printf("declare class: %s\n", cd->toPrettyChars());
@@ -381,7 +342,6 @@
     IrStruct* irstruct = cd->ir.irStruct;
 
     gIR->structs.push_back(irstruct);
-    gIR->classes.push_back(cd);
 
     bool needs_definition = false;
     if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)) {
@@ -390,82 +350,344 @@
 
     llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(cd);
 
-    // interfaces have no static initializer
-    // same goes for abstract classes
-    if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) {
-        // vtable
-        std::string varname("_D");
-        varname.append(cd->mangle());
-        varname.append("6__vtblZ");
-        cd->ir.irStruct->vtbl = new llvm::GlobalVariable(ts->ir.vtblType->get(), true, _linkage, 0, varname, gIR->module);
-    }
+    // create vtbl symbol
+    std::string varname("_D");
+    varname.append(cd->mangle());
+    varname.append("6__vtblZ");
+    irstruct->vtbl = new llvm::GlobalVariable(irstruct->vtblInitTy.get(), true, _linkage, 0, varname, gIR->module);
 
     // get interface info type
     const llvm::StructType* infoTy = DtoInterfaceInfoType();
 
     // interface info array
-    if (!cd->ir.irStruct->interfaceVec.empty()) {
+    if (!irstruct->interfaceVec.empty()) {
         // symbol name
         std::string nam = "_D";
         nam.append(cd->mangle());
         nam.append("16__interfaceInfosZ");
         // resolve array type
-        const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->ir.irStruct->interfaceVec.size());
+        const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, irstruct->interfaceVec.size());
         // declare global
-        irstruct->interfaceInfosTy = arrTy;
         irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module);
     }
 
-    // interfaces have no static initializer
-    // same goes for abstract classes
-    if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) {
-        // interface vtables
-        unsigned idx = 0;
-        for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i)
-        {
-            IrInterface* iri = *i;
-            ClassDeclaration* id = iri->decl;
+    // DMD gives abstract classes a full ClassInfo, so we do it as well
+
+    // interface vtables
+    unsigned idx = 0;
+
+    for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i)
+    {
+        IrInterface* iri = *i;
+        ClassDeclaration* id = iri->decl;
 
-            std::string nam("_D");
-            nam.append(cd->mangle());
-            nam.append("11__interface");
-            nam.append(id->mangle());
-            nam.append("6__vtblZ");
+        std::string nam("_D");
+        nam.append(cd->mangle());
+        nam.append("11__interface");
+        nam.append(id->mangle());
+        nam.append("6__vtblZ");
 
-            assert(iri->vtblTy);
-            iri->vtbl = new llvm::GlobalVariable(iri->vtblTy->get(), true, _linkage, 0, nam, gIR->module);
-            LLConstant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)};
-            iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2);
-            idx++;
-        }
+        iri->vtbl = new llvm::GlobalVariable(iri->vtblInitTy.get(), true, _linkage, 0, nam, gIR->module);
 
-        // init
-        std::string initname("_D");
-        initname.append(cd->mangle());
-        initname.append("6__initZ");
-
-        llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->ir.type->get(), true, _linkage, NULL, initname, gIR->module);
-        cd->ir.irStruct->init = initvar;
+        // always create interfaceinfos
+        LLConstant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)};
+        iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2);
+        idx++;
     }
 
-    gIR->classes.pop_back();
+    // initZ init
+    std::string initname("_D");
+    initname.append(cd->mangle());
+    initname.append("6__initZ");
+
+    // initZ global
+    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(irstruct->initOpaque.get(), true, _linkage, NULL, initname, gIR->module);
+    irstruct->init = initvar;
+
     gIR->structs.pop_back();
 
+    // request const init
     gIR->constInitList.push_back(cd);
+
+    // define ? (set initializers)
     if (needs_definition)
         gIR->defineList.push_back(cd);
 
     // classinfo
     DtoDeclareClassInfo(cd);
 
-    // typeinfo
+    // do typeinfo ?
     if (needs_definition)
         DtoTypeInfoOf(cd->type, false);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoConstInitClass(ClassDeclaration* cd)
+void addZeros(std::vector<llvm::Constant*>& inits, size_t pos, size_t offset); // irstruct.cpp
+
+//////////////////////////////////////////////////////////////////////////////
+
+// assigns constant initializers to fields introduced by cd
+static void init_field_inits(ClassDeclaration* cd)
+{
+    size_t n = cd->fields.dim;
+    for (size_t i=0; i<n; i++)
+    {
+        VarDeclaration* v = (VarDeclaration*)cd->fields.data[i];
+        IrField* f = v->ir.irField;
+        assert(!f->constInit);
+        f->constInit = DtoConstFieldInitializer(v->loc, v->type, v->init);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// adds data fields and interface vtables to the constant initializer of class cd
+static size_t init_class_initializer(std::vector<LLConstant*>& inits, ClassDeclaration* target, ClassDeclaration* cd, size_t offsetbegin)
+{
+    // first do baseclasses
+    if (cd->baseClass)
+    {
+        offsetbegin = init_class_initializer(inits, target, cd->baseClass, offsetbegin);
+    }
+
+    Logger::println("adding data of %s to %s", cd->toChars(), target->toChars());
+    LOG_SCOPE;
+
+    // add default fields
+    VarDeclaration** fields = (VarDeclaration**)cd->fields.data;
+    size_t nfields = cd->fields.dim;
+
+    std::vector<VarDeclaration*> defVars;
+    defVars.reserve(nfields);
+
+    size_t lastoffset = offsetbegin; // vtbl,monitor
+    size_t lastsize = 0;
+
+    // find fields that contribute to default
+    for (size_t i=0; i<nfields; i++)
+    {
+        VarDeclaration* var = fields[i];
+        // only add vars that don't overlap
+        size_t offset = var->offset;
+        size_t size = var->type->size();
+        if (offset >= lastoffset+lastsize)
+        {
+            Logger::println("  added");
+            lastoffset = offset;
+            lastsize = size;
+            defVars.push_back(var);
+        }
+    }
+
+    // go through the default vars and build the default constant initializer
+    // adding zeros along the way to live up to alignment expectations
+    size_t nvars = defVars.size();
+    for (size_t i=0; i<nvars; i++)
+    {
+        VarDeclaration* var = defVars[i];
+
+        Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset);
+
+        // get offset and size
+        size_t offset = var->offset;
+        size_t size = var->type->size();
+
+        // is there space in between last last offset and this one?
+        // if so, fill it with zeros
+        if (offset > lastoffset+lastsize)
+        {
+            size_t pos = lastoffset + lastsize;
+            addZeros(inits, pos, offset);
+        }
+
+        // add the field
+        assert(var->ir.irField->constInit);
+        inits.push_back(var->ir.irField->constInit);
+
+        lastoffset = offset;
+        lastsize = var->type->size();
+    }
+
+    // if it's a class, and it implements interfaces, add the vtables
+    IrStruct* irstruct = cd->ir.irStruct;
+
+    size_t nvtbls = cd->vtblInterfaces->dim;
+    for(size_t i=0; i<nvtbls; i++)
+    {
+        BaseClass* bc = (BaseClass*)cd->vtblInterfaces->data[i];
+        IrStruct::InterfaceMap::iterator iter = irstruct->interfaceMap.find(bc->base);
+        assert(iter != irstruct->interfaceMap.end());
+
+        IrInterface* iri = iter->second;
+        if (iri->vtbl)
+            inits.push_back(iri->vtbl);
+        else // abstract impl
+            inits.push_back(getNullPtr(getVoidPtrType()));
+
+        lastoffset += PTRSIZE;
+        lastsize = PTRSIZE;
+    }
+
+    // return next offset
+    return lastoffset + lastsize;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// build the vtable initializer for class cd
+static void init_class_vtbl_initializer(ClassDeclaration* cd)
+{
+    // generate vtable initializer
+    std::vector<LLConstant*> sinits(cd->vtbl.dim, NULL);
+
+    IrStruct* irstruct = cd->ir.irStruct;
+
+    assert(cd->vtbl.dim > 1);
+
+    // first entry always classinfo
+    assert(irstruct->classInfo);
+    sinits[0] = DtoBitCast(irstruct->classInfo, DtoType(ClassDeclaration::classinfo->type));
+
+    // add virtual functions
+    for (int k=1; k < cd->vtbl.dim; k++)
+    {
+        Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k];
+        assert(dsym);
+
+//         Logger::println("vtbl[%d] = %s", k, dsym->toChars());
+
+        FuncDeclaration* fd = dsym->isFuncDeclaration();
+        assert(fd);
+
+        if (fd->isAbstract())
+        {
+            sinits[k] = getNullPtr(getVoidPtrType());
+        }
+        else
+        {
+            DtoForceDeclareDsymbol(fd);
+            assert(fd->ir.irFunc->func);
+            sinits[k] = fd->ir.irFunc->func;
+        }
+
+//         if (Logger::enabled())
+//             Logger::cout() << "vtbl[" << k << "] = " << *sinits[k] << std::endl;
+    }
+
+    irstruct->constVtbl = LLConstantStruct::get(sinits);
+
+    // refine type
+    llvm::cast<llvm::OpaqueType>(irstruct->vtblInitTy.get())->refineAbstractTypeTo(irstruct->constVtbl->getType());
+
+    if (Logger::enabled())
+        Logger::cout() << "vtbl initializer: " << *irstruct->constVtbl << std::endl;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+static void init_class_interface_vtbl_initializers(ClassDeclaration* cd)
+{
+    IrStruct* irstruct = cd->ir.irStruct;
+
+    // don't do anything if list is empty
+    if (irstruct->interfaceVec.empty())
+        return;
+
+    std::vector<LLConstant*> inits;
+    std::vector<LLConstant*> infoInits(3);
+
+    // go through each interface
+    size_t ninter = irstruct->interfaceVec.size();
+    for (size_t i=0; i<ninter; i++)
+    {
+        IrInterface* iri = irstruct->interfaceVec[i];
+        Logger::println("interface %s", iri->decl->toChars());
+
+        // build vtable intializer for this interface implementation
+        Array& arr = iri->base->vtbl;
+        size_t narr = arr.dim;
+
+        if (narr > 0)
+        {
+            inits.resize(narr, NULL);
+
+            // first is always the interface info
+            assert(iri->info);
+            inits[0] = iri->info;
+
+            // build vtable
+            for (size_t j=1; j < narr; j++)
+            {
+                Dsymbol* dsym = (Dsymbol*)arr.data[j];
+                if (!dsym)
+                {
+                    inits[j] = getNullPtr(getVoidPtrType());
+                    continue;
+                }
+
+                //Logger::println("ivtbl[%d] = %s", j, dsym->toChars());
+
+                // must all be functions
+                FuncDeclaration* fd = dsym->isFuncDeclaration();
+                assert(fd);
+
+                if (fd->isAbstract())
+                    inits[j] = getNullPtr(getVoidPtrType());
+                else
+                {
+                    DtoForceDeclareDsymbol(fd);
+
+                    assert(fd->ir.irFunc->func);
+                    inits[j] = fd->ir.irFunc->func;
+                }
+
+                //if (Logger::enabled())
+                //    Logger::cout() << "ivtbl[" << j << "] = " << *inits[j] << std::endl;
+            }
+
+            // build the constant
+            iri->vtblInit = LLConstantStruct::get(inits);
+        }
+
+        // build the interface info for ClassInfo
+        // generate interface info initializer
+
+        DtoForceDeclareDsymbol(iri->decl);
+
+        // classinfo
+        IrStruct* iris = iri->decl->ir.irStruct;
+        assert(iris);
+        assert(iris->classInfo);
+        infoInits[0] = DtoBitCast(iris->classInfo, DtoType(ClassDeclaration::classinfo->type));
+
+        // vtbl
+        LLConstant* c;
+        if (iri->vtbl)
+            c = llvm::ConstantExpr::getBitCast(iri->vtbl, getPtrToType(getVoidPtrType()));
+        else
+            c = getNullPtr(getPtrToType(getVoidPtrType()));
+        infoInits[1] = DtoConstSlice(DtoConstSize_t(narr), c);
+
+        // offset
+        size_t ioff;
+        if (iri->index == 0)
+            ioff = 0;
+        else
+            ioff = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(iri->index);
+
+        Logger::println("DMD interface offset: %d, LLVM interface offset: %lu", iri->base->offset, ioff);
+        assert(iri->base->offset == ioff);
+        infoInits[2] = DtoConstUint(ioff);
+
+        // create interface info initializer constant
+        iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(infoInits));
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+static void DtoConstInitInterface(InterfaceDeclaration* cd)
 {
     if (cd->ir.initialized) return;
     cd->ir.initialized = true;
@@ -473,281 +695,141 @@
     Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
     LOG_SCOPE;
 
-    IrStruct* irstruct = cd->ir.irStruct;
-    gIR->structs.push_back(irstruct);
-    gIR->classes.push_back(cd);
-
-    // get the struct (class) type
-    assert(cd->type->ty == Tclass);
-    TypeClass* ts = (TypeClass*)cd->type;
-    const llvm::StructType* structtype = isaStruct(ts->ir.type->get());
-#if OPAQUE_VTBLS
-    const llvm::ArrayType* vtbltype = isaArray(ts->ir.vtblType->get());
-#else
-    const llvm::StructType* vtbltype = isaStruct(ts->ir.vtblType->get());
-#endif
+    init_class_interface_vtbl_initializers(cd);
+}
 
-    // make sure each offset knows its default initializer
-    for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i)
-    {
-        IrStruct::Offset* so = &i->second;
-        LLConstant* finit = DtoConstFieldInitializer(so->var->loc, so->var->type, so->var->init);
-        so->init = finit;
-        so->var->ir.irField->constInit = finit;
-    }
+//////////////////////////////////////////////////////////////////////////////
 
-    // fill out fieldtypes/inits
-    std::vector<LLConstant*> fieldinits;
-
-    // first field is always the vtable
-    if (cd->isAbstract() || cd->isInterfaceDeclaration())
-    {
-        const LLType* ptrTy = getPtrToType(ts->ir.vtblType->get());
-        fieldinits.push_back(llvm::Constant::getNullValue(ptrTy));
-    }
-    else
+void DtoConstInitClass(ClassDeclaration* cd)
+{
+    if (InterfaceDeclaration* it = cd->isInterfaceDeclaration())
     {
-        assert(cd->ir.irStruct->vtbl != 0);
-        fieldinits.push_back(cd->ir.irStruct->vtbl);
-    }
-
-    // then comes monitor
-    fieldinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
-
-    // go through the field inits and build the default initializer
-    size_t nfi = irstruct->defaultFields.size();
-    for (size_t i=0; i<nfi; ++i) {
-        LLConstant* c;
-        if (irstruct->defaultFields[i]) {
-            c = irstruct->defaultFields[i]->ir.irField->constInit;
-            assert(c);
-        }
-        else {
-            const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i+2));
-            assert(arrty);
-            std::vector<LLConstant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(LLType::Int8Ty, 0, false));
-            c = llvm::ConstantArray::get(arrty, vals);
-        }
-        fieldinits.push_back(c);
-    }
-
-    // last comes interface vtables
-    const llvm::StructType* infoTy = DtoInterfaceInfoType();
-    for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i)
-    {
-        IrInterface* iri = *i;
-        iri->infoTy = infoTy;
-
-        if (cd->isAbstract() || cd->isInterfaceDeclaration())
-        {
-            fieldinits.push_back(llvm::Constant::getNullValue(structtype->getElementType(iri->index)));
-        }
-        else
-        {
-            assert(iri->vtbl);
-            fieldinits.push_back(iri->vtbl);
-        }
+        DtoConstInitInterface(it);
+        return;
     }
 
-    // generate initializer
-#if 0
-    //Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n';
-    assert(fieldinits.size() == structtype->getNumElements());
-    for(size_t i=0; i<structtype->getNumElements(); ++i) {
-        Logger::cout() << "s#" << i << " = " << *structtype->getElementType(i) << '\n';
-        Logger::cout() << "i#" << i << " = " << *fieldinits[i] << '\n';
-        assert(fieldinits[i]->getType() == structtype->getElementType(i));
-    }
-#endif
+    if (cd->ir.initialized) return;
+    cd->ir.initialized = true;
 
-#if 0
-    for(size_t i=0; i<fieldinits.size(); ++i) {
-        Logger::cout() << "i#" << i << " = " << *fieldinits[i]->getType() << '\n';
-    }
-#endif
+    Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
+    LOG_SCOPE;
 
-    LLConstant* _init = llvm::ConstantStruct::get(structtype, fieldinits);
-    assert(_init);
-    cd->ir.irStruct->constInit = _init;
-
-    // abstract classes have no static vtable
-    // neither do interfaces (on their own, the implementing class supplies the vtable)
-    if (!cd->isInterfaceDeclaration() && !cd->isAbstract())
-    {
-        // generate vtable initializer
-        std::vector<LLConstant*> sinits;
+    assert(!cd->isInterfaceDeclaration());
 
-        for (int k=0; k < cd->vtbl.dim; k++)
-        {
-            Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k];
-            assert(dsym);
-            //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
-
-        #if OPAQUE_VTBLS
-            const LLType* targetTy = getVoidPtrType();
-        #else
-            const LLType* targetTy = vtbltype->getElementType(k);
-        #endif
+    // make sure the baseclass is const initialized
+    if (cd->baseClass)
+        DtoForceConstInitDsymbol(cd->baseClass);
 
-            LLConstant* c = NULL;
-            // virtual method
-            if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
-                DtoForceDeclareDsymbol(fd);
-                assert(fd->ir.irFunc->func);
-                c = llvm::cast<llvm::Constant>(fd->ir.irFunc->func);
-            }
-            // classinfo
-            else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) {
-                assert(cd->ir.irStruct->classInfo);
-                c = cd->ir.irStruct->classInfo;
-            }
-            assert(c != NULL);
+    // get IrStruct
+    IrStruct* irstruct = cd->ir.irStruct;
+    gIR->structs.push_back(irstruct);
 
-            // cast if necessary (overridden method)
-            if (c->getType() != targetTy)
-                c = llvm::ConstantExpr::getBitCast(c, targetTy);
-            sinits.push_back(c);
-        }
-    #if OPAQUE_VTBLS
-        const llvm::ArrayType* svtbl_ty = isaArray(ts->ir.vtblType->get());
-        cd->ir.irStruct->constVtbl = llvm::ConstantArray::get(svtbl_ty, sinits);
-    #else
-        const llvm::StructType* svtbl_ty = isaStruct(ts->ir.vtblType->get());
-        LLConstant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits);
-        cd->ir.irStruct->constVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit);
-    #endif
+    // get types
+    TypeClass* tc = (TypeClass*)cd->type;
+    const llvm::StructType* structtype = isaStruct(tc->ir.type->get());
+    assert(structtype);
+    const llvm::ArrayType* vtbltype = isaArray(irstruct->vtblTy.get());
+    assert(vtbltype);
 
-        // create interface vtable const initalizers
-        for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i)
-        {
-            IrInterface* iri = *i;
-            BaseClass* b = iri->base;
-
-            ClassDeclaration* id = iri->decl;
-            assert(id->type->ty == Tclass);
-            TypeClass* its = (TypeClass*)id->type;
-
-        #if OPAQUE_VTBLS
-            const llvm::ArrayType* ivtbl_ty = isaArray(its->ir.vtblType->get());
-        #else
-            const llvm::StructType* ivtbl_ty = isaStruct(its->ir.vtblType->get());
-        #endif
-
-            // generate interface info initializer
-            std::vector<LLConstant*> infoInits;
-
-            // classinfo
-            assert(id->ir.irStruct->classInfo);
-            LLConstant* c = id->ir.irStruct->classInfo;
-            infoInits.push_back(c);
+    // make sure each field knows its default initializer
+    init_field_inits(cd);
 
-            // vtbl
-            const LLType* byteptrptrty = getPtrToType(getPtrToType(LLType::Int8Ty));
-            c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty);
-            c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c);
-            infoInits.push_back(c);
-
-            // offset
-            assert(iri->index >= 0);
-            size_t ioff = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(iri->index);
-            infoInits.push_back(DtoConstUint(ioff));
-
-            // create interface info initializer constant
-            iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits));
-
-            // generate vtable initializer
-            std::vector<LLConstant*> iinits;
+    // build initializer list
+    std::vector<LLConstant*> inits;
+    inits.reserve(irstruct->varDecls.size());
 
-            // add interface info
-        #if OPAQUE_VTBLS
-            const LLType* targetTy = getVoidPtrType();
-            iinits.push_back(llvm::ConstantExpr::getBitCast(iri->info, targetTy));
-        #else
-            iinits.push_back(iri->info);
-        #endif
-
-            for (int k=1; k < b->vtbl.dim; k++)
-            {
-//                 Logger::println("interface vtbl const init nr. %d", k);
-                Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k];
+    // vtable is always first
+    assert(irstruct->vtbl != 0);
+    inits.push_back(irstruct->vtbl);
 
-                // error on unimplemented functions, error was already generated earlier
-                if(!dsym)
-                    fatal();
+    // then comes monitor
+    inits.push_back(LLConstant::getNullValue(getVoidPtrType()));
 
-                FuncDeclaration* fd = dsym->isFuncDeclaration();
-                assert(fd);
-                DtoForceDeclareDsymbol(fd);
-                assert(fd->ir.irFunc->func);
-                LLConstant* c = llvm::cast<llvm::Constant>(fd->ir.irFunc->func);
-
-            #if !OPAQUE_VTBLS
-                const LLType* targetTy = iri->vtblTy->getContainedType(k);
-            #endif
+    // recursively do data and interface vtables
+    init_class_initializer(inits, cd, cd, 2 * PTRSIZE);
 
-                // we have to bitcast, as the type created in ResolveClass expects a different this type
-                c = llvm::ConstantExpr::getBitCast(c, targetTy);
-                iinits.push_back(c);
-//                 if (Logger::enabled())
-//                     Logger::cout() << "c: " << *c << '\n';
-            }
+    // build vtable initializer
+    init_class_vtbl_initializer(cd);
+
+    // build interface vtables
+    init_class_interface_vtbl_initializers(cd);
 
-        #if OPAQUE_VTBLS
-//             if (Logger::enabled())
-//                 Logger::cout() << "n: " << iinits.size() << " ivtbl_ty: " << *ivtbl_ty << '\n';
-            LLConstant* civtblInit = llvm::ConstantArray::get(ivtbl_ty, iinits);
-            iri->vtblInit = llvm::cast<llvm::ConstantArray>(civtblInit);
-        #else
-            LLConstant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits);
-            iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit);
-        #endif
-        }
-    }
-    // we always generate interfaceinfos as best we can
-    else
+    // build constant from inits
+    irstruct->constInit = LLConstantStruct::get(inits); // classes are never packed
+
+    // refine __initZ global type to the one of the initializer
+    llvm::cast<llvm::OpaqueType>(irstruct->initOpaque.get())->refineAbstractTypeTo(irstruct->constInit->getType());
+
+    if (Logger::enabled())
     {
-        // TODO: this is duplicated code from right above... I'm just too lazy to generalise it right now :/
-        // create interface vtable const initalizers
-        for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i)
-        {
-            IrInterface* iri = *i;
-            BaseClass* b = iri->base;
-
-            ClassDeclaration* id = iri->decl;
-            assert(id->type->ty == Tclass);
-            TypeClass* its = (TypeClass*)id->type;
-
-            // generate interface info initializer
-            std::vector<LLConstant*> infoInits;
-
-            // classinfo
-            assert(id->ir.irStruct->classInfo);
-            LLConstant* c = id->ir.irStruct->classInfo;
-            infoInits.push_back(c);
-
-            // vtbl
-            const LLType* byteptrptrty = getPtrToType(getPtrToType(LLType::Int8Ty));
-            c = DtoConstSlice(DtoConstSize_t(0), getNullPtr(byteptrptrty));
-            infoInits.push_back(c);
-
-            // offset
-            assert(iri->index >= 0);
-            size_t ioff = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(iri->index);
-            infoInits.push_back(DtoConstUint(ioff));
-
-            // create interface info initializer constant
-            iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits));
-        }
+        Logger::cout() << "class " << cd->toChars() << std::endl;
+        Logger::cout() << "type " << *cd->type->ir.type->get() << std::endl;
+        Logger::cout() << "initializer " << *irstruct->constInit << std::endl;
     }
 
-    gIR->classes.pop_back();
     gIR->structs.pop_back();
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+static void DefineInterfaceInfos(IrStruct* irstruct)
+{
+    // always do interface info array when possible
+    std::vector<LLConstant*> infoInits;
+    infoInits.reserve(irstruct->interfaceVec.size());
+
+    for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i)
+    {
+        IrInterface* iri = *i;
+        assert(iri->infoInit);
+        infoInits.push_back(iri->infoInit);
+    }
+
+    // set initializer
+    if (!infoInits.empty())
+    {
+        const LLArrayType* arrty = LLArrayType::get(infoInits[0]->getType(), infoInits.size());
+        LLConstant* arrInit = llvm::ConstantArray::get(arrty, infoInits);
+        irstruct->interfaceInfos->setInitializer(arrInit);
+    }
+    else
+    {
+        assert(irstruct->interfaceInfos == NULL);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+static void DtoDefineInterface(InterfaceDeclaration* cd)
+{
+    if (cd->ir.defined) return;
+    cd->ir.defined = true;
+
+    Logger::println("DtoDefineClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
+    LOG_SCOPE;
+
+    // defined interface infos
+    DefineInterfaceInfos(cd->ir.irStruct);
+
+    // define the classinfo
+    if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd))
+    {
+        DtoDefineClassInfo(cd);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// FIXME: clean this up
+
 void DtoDefineClass(ClassDeclaration* cd)
 {
+    if (InterfaceDeclaration* id = cd->isInterfaceDeclaration())
+    {
+        DtoDefineInterface(id);
+        return;
+    }
+
     if (cd->ir.defined) return;
     cd->ir.defined = true;
 
@@ -758,46 +840,48 @@
     assert(cd->type->ty == Tclass);
     TypeClass* ts = (TypeClass*)cd->type;
 
-    if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)) {
+    IrStruct* irstruct = cd->ir.irStruct;
 
-        // interfaces don't have static initializer/vtable
-        // neither do abstract classes
-        if (!cd->isInterfaceDeclaration() && !cd->isAbstract())
-        {
-            cd->ir.irStruct->init->setInitializer(cd->ir.irStruct->constInit);
-            cd->ir.irStruct->vtbl->setInitializer(cd->ir.irStruct->constVtbl);
+    assert(cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd));
 
-            // initialize interface vtables
-            IrStruct* irstruct = cd->ir.irStruct;
-            for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i)
-            {
-                IrInterface* iri = *i;
-                iri->vtbl->setInitializer(iri->vtblInit);
-            }
-        }
+    // sanity check
+    assert(irstruct->init);
+    assert(irstruct->constInit);
+    assert(irstruct->vtbl);
+    assert(irstruct->constVtbl);
+
+    if (Logger::enabled())
+    {
+        Logger::cout() << "initZ: " << *irstruct->init << std::endl;
+        Logger::cout() << "cinitZ: " << *irstruct->constInit << std::endl;
+        Logger::cout() << "vtblZ: " << *irstruct->vtbl << std::endl;
+        Logger::cout() << "cvtblZ: " << *irstruct->constVtbl << std::endl;
+    }
 
-        // always do interface info array when possible
-        IrStruct* irstruct = cd->ir.irStruct;
-        std::vector<LLConstant*> infoInits;
-        for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i)
-        {
-            IrInterface* iri = *i;
-            infoInits.push_back(iri->infoInit);
-        }
-        // set initializer
-        if (!infoInits.empty())
-        {
-            LLConstant* arrInit = llvm::ConstantArray::get(irstruct->interfaceInfosTy, infoInits);
-            irstruct->interfaceInfos->setInitializer(arrInit);
-        }
-        else
-        {
-            assert(irstruct->interfaceInfos == NULL);
-        }
+    // set initializers
+    irstruct->init->setInitializer(irstruct->constInit);
+    irstruct->vtbl->setInitializer(irstruct->constVtbl);
+
+    // initialize interface vtables
+    size_t n = irstruct->interfaceVec.size();
+    for (size_t i=0; i<n; i++)
+    {
+        IrInterface* iri = irstruct->interfaceVec[i];
+        Logger::println("interface %s", iri->base->base->toChars());
+        assert(iri->vtblInit);
 
-        // generate classinfo
-        DtoDefineClassInfo(cd);
+        // refine the init type
+        llvm::cast<llvm::OpaqueType>(iri->vtblInitTy.get())->refineAbstractTypeTo(iri->vtblInit->getType());
+
+        // apply initializer
+        assert(iri->vtbl);
+        iri->vtbl->setInitializer(iri->vtblInit);
     }
+
+    DefineInterfaceInfos(irstruct);
+
+    // generate classinfo
+    DtoDefineClassInfo(cd);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -825,7 +909,8 @@
     else
     {
         llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_allocclass");
-        mem = gIR->CreateCallOrInvoke(fn, tc->sym->ir.irStruct->classInfo, ".newclass_gc_alloc")->get();
+        LLConstant* ci = DtoBitCast(tc->sym->ir.irStruct->classInfo, DtoType(ClassDeclaration::classinfo->type));
+        mem = gIR->CreateCallOrInvoke(fn, ci, ".newclass_gc_alloc")->get();
         mem = DtoBitCast(mem, DtoType(tc), ".newclass_gc");
     }
 
@@ -838,7 +923,7 @@
         Logger::println("Resolving outer class");
         LOG_SCOPE;
         DValue* thisval = newexp->thisexp->toElem(gIR);
-        size_t idx = 2 + tc->sym->vthis->ir.irField->index;
+        size_t idx = tc->sym->vthis->ir.irField->index;
         LLValue* src = thisval->getRVal();
         LLValue* dst = DtoGEPi(mem,0,idx,"tmp");
         if (Logger::enabled())
@@ -855,7 +940,7 @@
         LLValue* nest = DtoNestedContext(loc, tc->sym);
 
         // store into right location
-        size_t idx = 2 + tc->sym->vthis->ir.irField->index;
+        size_t idx = tc->sym->vthis->ir.irField->index;
         LLValue* gep = DtoGEPi(mem,0,idx,"tmp");
         DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep);
     }
@@ -877,16 +962,21 @@
 
 void DtoInitClass(TypeClass* tc, LLValue* dst)
 {
+    DtoForceConstInitDsymbol(tc->sym);
+
     size_t presz = 2*getABITypeSize(DtoSize_t());
     uint64_t n = getABITypeSize(tc->ir.type->get()) - presz;
 
     // set vtable field seperately, this might give better optimization
     assert(tc->sym->ir.irStruct->vtbl);
-    DtoStore(tc->sym->ir.irStruct->vtbl, DtoGEPi(dst,0,0,"vtbl"));
+    LLValue* tmp = DtoGEPi(dst,0,0,"vtbl");
+    LLValue* val = DtoBitCast(tc->sym->ir.irStruct->vtbl, tmp->getType()->getContainedType(0));
+    DtoStore(val, tmp);
 
     // monitor always defaults to zero
-    LLValue* tmp = DtoGEPi(dst,0,1,"monitor");
-    DtoStore(llvm::Constant::getNullValue(tmp->getType()->getContainedType(0)), tmp);
+    tmp = DtoGEPi(dst,0,1,"monitor");
+    val = llvm::Constant::getNullValue(tmp->getType()->getContainedType(0));
+    DtoStore(val, tmp);
 
     // done?
     if (n == 0)
@@ -894,7 +984,6 @@
 
     // copy the rest from the static initializer
     assert(tc->sym->ir.irStruct->init);
-    assert(dst->getType() == tc->sym->ir.irStruct->init->getType());
 
     LLValue* dstarr = DtoGEPi(dst,0,2,"tmp");
     LLValue* srcarr = DtoGEPi(tc->sym->ir.irStruct->init,0,2,"tmp");
@@ -923,12 +1012,15 @@
     LOG_SCOPE;
 
     Type* to = _to->toBasetype();
+
+    // class -> pointer
     if (to->ty == Tpointer) {
         Logger::println("to pointer");
         const LLType* tolltype = DtoType(_to);
         LLValue* rval = DtoBitCast(val->getRVal(), tolltype);
         return new DImValue(_to, rval);
     }
+    // class -> bool
     else if (to->ty == Tbool) {
         Logger::println("to bool");
         LLValue* llval = val->getRVal();
@@ -936,36 +1028,67 @@
         return new DImValue(_to, gIR->ir->CreateICmpNE(llval, zero, "tmp"));
     }
 
+    // must be class/interface
     assert(to->ty == Tclass);
     TypeClass* tc = (TypeClass*)to;
 
+    // from type
     Type* from = val->getType()->toBasetype();
     TypeClass* fc = (TypeClass*)from;
 
-    if (tc->sym->isInterfaceDeclaration()) {
+    // x -> interface
+    if (InterfaceDeclaration* it = tc->sym->isInterfaceDeclaration()) {
         Logger::println("to interface");
+        // interface -> interface
         if (fc->sym->isInterfaceDeclaration()) {
             Logger::println("from interface");
             return DtoDynamicCastInterface(val, _to);
         }
+        // class -> interface - static cast
+        else if (it->isBaseOf(fc->sym,NULL)) {
+            Logger::println("static down cast)");
+            // get the from class
+            ClassDeclaration* cd = fc->sym->isClassDeclaration();
+            IrStruct* irstruct = cd->ir.irStruct;
+            // find interface impl
+            IrStruct::InterfaceMapIter iriter = irstruct->interfaceMap.find(it);
+            assert(iriter != irstruct->interfaceMap.end());
+            IrInterface* iri = iriter->second;
+            // offset pointer
+            LLValue* v = val->getRVal();
+            v = DtoGEPi(v, 0, iri->index);
+            if (Logger::enabled())
+            {
+                Logger::cout() << "V = " << *v << std::endl;
+                Logger::cout() << "T = " << *DtoType(_to) << std::endl;
+            }
+            v = DtoBitCast(v, DtoType(_to));
+            // return r-value
+            return new DImValue(_to, v);
+        }
+        // class -> interface
         else {
             Logger::println("from object");
             return DtoDynamicCastObject(val, _to);
         }
     }
+    // x -> class
     else {
         Logger::println("to class");
         int poffset;
+        // interface -> class
         if (fc->sym->isInterfaceDeclaration()) {
             Logger::println("interface cast");
             return DtoCastInterfaceToObject(val, _to);
         }
-        else if (!tc->sym->isInterfaceDeclaration() && tc->sym->isBaseOf(fc->sym,NULL)) {
+        // class -> class - static down cast
+        else if (tc->sym->isBaseOf(fc->sym,NULL)) {
             Logger::println("static down cast)");
             const LLType* tolltype = DtoType(_to);
             LLValue* rval = DtoBitCast(val->getRVal(), tolltype);
             return new DImValue(_to, rval);
         }
+        // class -> class - dynamic up cast
         else {
             Logger::println("dynamic up cast");
             return DtoDynamicCastObject(val, _to);
@@ -1100,19 +1223,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
-{
-    unsigned idx = 0;
-    unsigned r = LLVM_ClassOffsetToIndex(this, os, idx);
-    assert(r != (unsigned)-1 && "Offset not found in any aggregate field");
-    // vtable is 0, monitor is 1
-    r += 2;
-    // the final index was not pushed
-    result.push_back(r); 
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* cd, VarDeclaration* vd)
 {
     Logger::println("indexing class field %s:", vd->toPrettyChars());
@@ -1125,17 +1235,31 @@
     IrField* field = vd->ir.irField;
     assert(field);
 
-    unsigned idx = field->index + 2; // vtbl & monitor
-    unsigned off = field->indexOffset;
-
+    // get the start pointer
     const LLType* st = DtoType(cd->type);
+    // cast to the struct type
     src = DtoBitCast(src, st);
 
-    LLValue* val = DtoGEPi(src, 0,idx);
-    val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
+    // gep to the index
+    if (Logger::enabled())
+    {
+        Logger::cout() << "src2: " << *src << '\n';
+        Logger::cout() << "index: " << field->index << '\n';
+        Logger::cout() << "srctype: " << *src->getType() << '\n';
+    }
+    LLValue* val = DtoGEPi(src, 0, field->index);
 
-    if (off)
-        val = DtoGEPi1(val, off);
+    // do we need to offset further? (union area)
+    if (field->unionOffset)
+    {
+        // cast to void*
+        val = DtoBitCast(val, getVoidPtrType());
+        // offset
+        val = DtoGEPi1(val, field->unionOffset);
+    }
+
+    // cast it to the right type
+    val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
 
     if (Logger::enabled())
         Logger::cout() << "value: " << *val << '\n';
@@ -1155,8 +1279,9 @@
     if (Logger::enabled())
         Logger::cout() << "vthis: " << *vthis << '\n';
 
-    LLValue* funcval;
-    funcval = DtoGEPi(vthis, 0, 0, "tmp");
+    LLValue* funcval = vthis;
+    if (!fdecl->isMember2()->isInterfaceDeclaration())
+        funcval = DtoGEPi(funcval, 0, 0, "tmp");
     funcval = DtoLoad(funcval);
     funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toPrettyChars());
     funcval = DtoLoad(funcval);
@@ -1164,11 +1289,9 @@
     if (Logger::enabled())
         Logger::cout() << "funcval: " << *funcval << '\n';
 
-#if OPAQUE_VTBLS
     funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type)));
     if (Logger::enabled())
         Logger::cout() << "funcval casted: " << *funcval << '\n';
-#endif
 
     return funcval;
 }
@@ -1177,8 +1300,10 @@
 
 void DtoDeclareClassInfo(ClassDeclaration* cd)
 {
-    if (cd->ir.irStruct->classDeclared) return;
-    cd->ir.irStruct->classDeclared = true;
+    IrStruct* irstruct = cd->ir.irStruct;
+
+    if (irstruct->classInfoDeclared) return;
+    irstruct->classInfoDeclared = true;
 
     Logger::println("DtoDeclareClassInfo(%s)", cd->toChars());
     LOG_SCOPE;
@@ -1193,9 +1318,7 @@
     else
         gname.append("11__InterfaceZ");
 
-    const LLType* st = cinfo->type->ir.type->get();
-
-    cd->ir.irStruct->classInfo = new llvm::GlobalVariable(st, false, DtoLinkage(cd), NULL, gname, gIR->module);
+    irstruct->classInfo = new llvm::GlobalVariable(irstruct->classInfoOpaque.get(), false, DtoLinkage(cd), NULL, gname, gIR->module);
 }
 
 static LLConstant* build_offti_entry(ClassDeclaration* cd, VarDeclaration* vd)
@@ -1206,8 +1329,8 @@
     types.push_back(DtoSize_t());
 
     assert(vd->ir.irField);
-    assert(vd->ir.irField->index >= 0);
-    size_t offset = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(vd->ir.irField->index+2);
+    size_t offset = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(vd->ir.irField->index);
+    offset += vd->ir.irField->unionOffset;
     inits.push_back(DtoConstSize_t(offset));
 
     LLConstant* c = DtoTypeInfoOf(vd->type, true);
@@ -1227,24 +1350,15 @@
     assert(initTy);
 
     std::vector<LLConstant*> arrayInits;
-    for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass)
-    {
-    if (cd2->members)
+
+    VarDeclaration** fields = &cd->ir.irStruct->varDecls[0];
+    size_t nvars = cd->ir.irStruct->varDecls.size();
+
+    for (size_t i=0; i<nvars; i++)
     {
-        for (size_t i = 0; i < cd2->members->dim; i++)
-        {
-        Dsymbol *sm = (Dsymbol *)cd2->members->data[i];
-        if (VarDeclaration* vd = sm->isVarDeclaration()) // is this enough?
-        {
-            if (!vd->isDataseg()) // static members dont have an offset!
-            {
-                LLConstant* c = build_offti_entry(cd, vd);
-                assert(c);
-                arrayInits.push_back(c);
-            }
-        }
-        }
-    }
+        LLConstant* c = build_offti_entry(cd, fields[i]);
+        assert(c);
+        arrayInits.push_back(c);
     }
 
     size_t ninits = arrayInits.size();
@@ -1336,21 +1450,23 @@
 //         void *defaultConstructor;
 //        }
 
-    if (cd->ir.irStruct->classDefined) return;
-    cd->ir.irStruct->classDefined = true;
+    IrStruct* ir = cd->ir.irStruct;
+
+    if (ir->classInfoDefined) return;
+    ir->classInfoDefined = true;
 
     Logger::println("DtoDefineClassInfo(%s)", cd->toChars());
     LOG_SCOPE;
 
     assert(cd->type->ty == Tclass);
-    assert(cd->ir.irStruct->classInfo);
+    assert(ir->classInfo);
 
     TypeClass* cdty = (TypeClass*)cd->type;
     if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) {
-        assert(cd->ir.irStruct->init);
-        assert(cd->ir.irStruct->constInit);
-        assert(cd->ir.irStruct->vtbl);
-        assert(cd->ir.irStruct->constVtbl);
+        assert(ir->init);
+        assert(ir->constInit);
+        assert(ir->vtbl);
+        assert(ir->constVtbl);
     }
 
     // holds the list of initializers for llvm
@@ -1381,8 +1497,9 @@
         c = defc->getOperand(2);
     }
     else {
-        c = llvm::ConstantExpr::getBitCast(cd->ir.irStruct->init, byteptrty);
-        size_t initsz = getABITypeSize(cd->ir.irStruct->constInit->getType());
+        c = llvm::ConstantExpr::getBitCast(ir->init, byteptrty);
+        //Logger::cout() << *ir->constInit->getType() << std::endl;
+        size_t initsz = getABITypeSize(ir->constInit->getType());
         c = DtoConstSlice(DtoConstSize_t(initsz), c);
     }
     inits.push_back(c);
@@ -1405,27 +1522,23 @@
     }
     else {
         const LLType* byteptrptrty = getPtrToType(byteptrty);
-        assert(!cd->ir.irStruct->vtbl->getType()->isAbstract());
         c = llvm::ConstantExpr::getBitCast(cd->ir.irStruct->vtbl, byteptrptrty);
-        assert(!cd->ir.irStruct->constVtbl->getType()->isAbstract());
-        size_t vtblsz = 0;
-        llvm::ConstantArray* constVtblArray = llvm::dyn_cast<llvm::ConstantArray>(cd->ir.irStruct->constVtbl);
-        if(constVtblArray) {
-            vtblsz = constVtblArray->getType()->getNumElements();
-        }
+
+        assert(ir->constVtbl);
+        size_t vtblsz = ir->constVtbl->getNumOperands();
         c = DtoConstSlice(DtoConstSize_t(vtblsz), c);
     }
     inits.push_back(c);
 
     // interfaces array
     IrStruct* irstruct = cd->ir.irStruct;
-    if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos || cd->isAbstract()) {
+    if (!irstruct->interfaceInfos) {
         c = defc->getOperand(5);
     }
     else {
         const LLType* t = defc->getOperand(5)->getType()->getContainedType(1);
         c = llvm::ConstantExpr::getBitCast(irstruct->interfaceInfos, t);
-        size_t iisz = irstruct->interfaceInfosTy->getNumElements();
+        size_t iisz = irstruct->interfaceVec.size();
         c = DtoConstSlice(DtoConstSize_t(iisz), c);
     }
     inits.push_back(c);
@@ -1521,10 +1634,13 @@
     }*/
 
     // build the initializer
-    const llvm::StructType* st = isaStruct(defc->getType());
-    LLConstant* finalinit = llvm::ConstantStruct::get(st, inits);
+    LLConstant* finalinit = llvm::ConstantStruct::get(inits);
     //Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
+    ir->constClassInfo = finalinit;
 
-    cd->ir.irStruct->constClassInfo = finalinit;
-    cd->ir.irStruct->classInfo->setInitializer(finalinit);
+    // refine the type
+    llvm::cast<llvm::OpaqueType>(ir->classInfoOpaque.get())->refineAbstractTypeTo(finalinit->getType());
+
+    // apply initializer
+    ir->classInfo->setInitializer(finalinit);
 }
--- a/gen/functions.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/functions.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -97,16 +97,8 @@
     }
 
     if (dVararg) {
-        ClassDeclaration* ti = Type::typeinfo;
-        ti->toObjFile(0); // TODO: multiobj
-        DtoForceConstInitDsymbol(ti);
-        assert(ti->ir.irStruct->constInit);
-        std::vector<const LLType*> types;
-        types.push_back(DtoSize_t());
-        types.push_back(getPtrToType(getPtrToType(ti->ir.irStruct->constInit->getType())));
-        const LLType* t1 = llvm::StructType::get(types);
-        paramvec.push_back(t1);
-        paramvec.push_back(getPtrToType(LLType::Int8Ty));
+        paramvec.push_back(DtoType(Type::typeinfo->type->arrayOf())); // _arguments
+        paramvec.push_back(getVoidPtrType()); // _argptr
     }
 
     // number of formal params
@@ -286,7 +278,7 @@
             Logger::println("isMember = this is: %s", ad->type->toChars());
             thisty = DtoType(ad->type);
             //Logger::cout() << "this llvm type: " << *thisty << '\n';
-            if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->recty.get()))
+            if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->type->ir.type->get()))
                 thisty = getPtrToType(thisty);
         }
         else {
@@ -547,35 +539,36 @@
     }
 
     // we never reference parameters of function prototypes
+    std::string str;
     if (!declareOnly)
     {
         // name parameters
         llvm::Function::arg_iterator iarg = func->arg_begin();
 
         if (f->retInPtr) {
-            iarg->setName(".sretarg");
+            iarg->setName(".sret_arg");
             fdecl->ir.irFunc->retArg = iarg;
             ++iarg;
         }
 
         if (f->usesThis) {
-            iarg->setName("this");
+            iarg->setName(".this_arg");
             fdecl->ir.irFunc->thisArg = iarg;
             assert(fdecl->ir.irFunc->thisArg);
             ++iarg;
         }
         else if (f->usesNest) {
-            iarg->setName(".nest");
+            iarg->setName(".nest_arg");
             fdecl->ir.irFunc->nestArg = iarg;
             assert(fdecl->ir.irFunc->nestArg);
             ++iarg;
         }
 
         if (f->linkage == LINKd && f->varargs == 1) {
-            iarg->setName("_arguments");
+            iarg->setName("._arguments");
             fdecl->ir.irFunc->_arguments = iarg;
             ++iarg;
-            iarg->setName("_argptr");
+            iarg->setName("._argptr");
             fdecl->ir.irFunc->_argptr = iarg;
             ++iarg;
         }
@@ -597,7 +590,10 @@
                 assert(!argvd->ir.irLocal);
                 argvd->ir.irLocal = new IrLocal(argvd);
                 argvd->ir.irLocal->value = iarg;
-                iarg->setName(argvd->ident->toChars());
+
+                str = argvd->ident->toChars();
+                str.append("_arg");
+                iarg->setName(str);
 
                 k++;
             }
@@ -671,8 +667,7 @@
     if (fd->isMain())
         gIR->emitMain = true;
 
-    std::string entryname("entry_");
-    entryname.append(fd->toPrettyChars());
+    std::string entryname("entry");
 
     llvm::BasicBlock* beginbb = llvm::BasicBlock::Create(entryname,func);
     llvm::BasicBlock* endbb = llvm::BasicBlock::Create("endentry",func);
@@ -710,7 +705,7 @@
         LLValue* thisvar = irfunction->thisArg;
         assert(thisvar);
 
-        LLValue* thismem = DtoAlloca(thisvar->getType(), ".this");
+        LLValue* thismem = DtoAlloca(thisvar->getType(), "this");
         DtoStore(thisvar, thismem);
         irfunction->thisArg = thismem;
         
@@ -760,7 +755,7 @@
             if (!refout && (!DtoIsPassedByRef(vd->type) || lazy))
             {
                 LLValue* a = irloc->value;
-                LLValue* v = DtoAlloca(a->getType(), "."+a->getName());
+                LLValue* v = DtoAlloca(a->getType(), vd->ident->toChars());
                 DtoStore(a,v);
                 irloc->value = v;
             }
@@ -822,7 +817,7 @@
                 ClassDeclaration* cd = fd->isMember2()->isClassDeclaration();
                 assert(cd);
                 assert(cd->vthis);
-                src = DtoLoad(DtoGEPi(thisval, 0,2+cd->vthis->ir.irField->index, ".vthis"));
+                src = DtoLoad(DtoGEPi(thisval, 0,cd->vthis->ir.irField->index, ".vthis"));
             }
             DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE));
         }
--- a/gen/irstate.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/irstate.h	Sat Nov 29 21:25:43 2008 +0100
@@ -23,6 +23,7 @@
 struct Module;
 struct TypeStruct;
 struct BaseClass;
+struct AnonDeclaration;
 struct EnclosingHandler;
 
 struct IrModule;
@@ -147,10 +148,6 @@
     StructVector structs;
     IrStruct* topstruct();
 
-    // classes TODO move into IRClass
-    typedef std::vector<ClassDeclaration*> ClassDeclVec;
-    ClassDeclVec classes;
-
     // D main function
     bool emitMain;
     llvm::Function* mainFunc;
--- a/gen/llvmhelpers.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/llvmhelpers.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -338,7 +338,7 @@
     {
         ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();
         LLValue* val = DtoLoad(irfunc->thisArg);
-        ctx = DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis"));
+        ctx = DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis"));
     }
     else
         ctx = irfunc->nestArg;
@@ -374,7 +374,7 @@
         if (!cd || !cd->vthis)
             return getNullPtr(getVoidPtrType());
         LLValue* val = DtoLoad(irfunc->thisArg);
-        return DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis"));
+        return DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis"));
     }
     else
     {
@@ -964,73 +964,68 @@
     if (vd->ir.initialized) return;
     vd->ir.initialized = gIR->dmodule;
 
-    Logger::println("* DtoConstInitGlobal(%s)", vd->toChars());
+    Logger::println("DtoConstInitGlobal(%s) @ %s", vd->toChars(), vd->locToChars());
     LOG_SCOPE;
 
-    bool emitRTstaticInit = false;
+    // if the variable is a function local static variable with a runtime initializer
+    // we must do lazy initialization, which involves a boolean flag to make sure it happens only once
+    // FIXME: I don't think it's thread safe ...
+
+    bool doLazyInit = false;
+    Dsymbol* par = vd->toParent2();
 
-    LLConstant* _init = 0;
-    if (vd->parent && vd->parent->isFuncDeclaration() && vd->init && vd->init->isExpInitializer()) {
-        _init = DtoConstInitializer(vd->loc, vd->type, NULL);
-        emitRTstaticInit = true;
-    }
-    else {
-        _init = DtoConstInitializer(vd->loc, vd->type, vd->init);
+    if (par && par->isFuncDeclaration() && vd->init)
+    {
+        if (ExpInitializer* einit = vd->init->isExpInitializer())
+        {
+            if (!einit->exp->isConst())
+            {
+                // mark as needing lazy now
+                doLazyInit = true;
+            }
+        }
     }
 
-    const LLType* _type = DtoType(vd->type);
-    Type* t = vd->type->toBasetype();
-
-    //Logger::cout() << "initializer: " << *_init << '\n';
-    if (_type != _init->getType()) {
-        if (Logger::enabled())
-            Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n";
+    // if we do lazy init, we start out with an undefined initializer
+    LLConstant* initVal;
+    if (doLazyInit)
+    {
+        initVal = llvm::UndefValue::get(DtoType(vd->type));
+    }
+    // otherwise we build it
+    else
+    {
+        initVal = DtoConstInitializer(vd->loc, vd->type, vd->init);
+    }
 
-        // zero initalizer
-        if (_init->isNullValue())
-            _init = llvm::Constant::getNullValue(_type);
-        // pointer to global constant (struct.init)
-        else if (llvm::isa<llvm::GlobalVariable>(_init))
-        {
-            assert(_init->getType()->getContainedType(0) == _type);
-            llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init);
-            assert(t->ty == Tstruct);
-            TypeStruct* ts = (TypeStruct*)t;
-            assert(ts->sym->ir.irStruct->constInit);
-            _init = ts->sym->ir.irStruct->constInit;
-        }
-        // array single value init
-        else if (isaArray(_type))
-        {
-            _init = DtoConstStaticArray(_type, _init);
-        }
-        else {
-            if (Logger::enabled())
-                Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
-            //assert(0);
-        }
-    }
+    // set the initializer if appropriate
+    IrGlobal* glob = vd->ir.irGlobal;
+    llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(glob->value);
+
+    // refine the global's opaque type to the type of the initializer
+    llvm::cast<LLOpaqueType>(glob->type.get())->refineAbstractTypeTo(initVal->getType());
+
+    glob->constInit = initVal;
 
     bool istempl = false;
     if ((vd->storage_class & STCcomdat) || (vd->parent && DtoIsTemplateInstance(vd->parent))) {
         istempl = true;
     }
 
-    if (_init && _init->getType() != _type)
-        _type = _init->getType();
-    llvm::cast<LLOpaqueType>(vd->ir.irGlobal->type.get())->refineAbstractTypeTo(_type);
-    _type = vd->ir.irGlobal->type.get();
+    // assign the initializer
+    llvm::GlobalVariable* globalvar = llvm::cast<llvm::GlobalVariable>(glob->value);
 
-    llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(vd->ir.irGlobal->value);
     if (!(vd->storage_class & STCextern) && (vd->getModule() == gIR->dmodule || istempl))
     {
         if (Logger::enabled())
         {
             Logger::println("setting initializer");
             Logger::cout() << "global: " << *gvar << '\n';
-            Logger::cout() << "init:   " << *_init << '\n';
+            Logger::cout() << "init:   " << *initVal << '\n';
         }
-        gvar->setInitializer(_init);
+
+        gvar->setInitializer(initVal);
+
         // do debug info
         if (global.params.symdebug)
         {
@@ -1040,8 +1035,8 @@
         }
     }
 
-    if (emitRTstaticInit)
-        DtoLazyStaticInit(istempl, gvar, vd->init, t);
+    if (doLazyInit)
+        DtoLazyStaticInit(istempl, gvar, vd->init, vd->type);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -1396,18 +1391,18 @@
 //      INITIALIZER HELPERS
 ////////////////////////////////////////////////////////////////////////////////////////*/
 
-LLConstant* DtoConstInitializer(Loc& loc, Type* type, Initializer* init)
+LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
 {
     LLConstant* _init = 0; // may return zero
     if (!init)
     {
         Logger::println("const default initializer for %s", type->toChars());
-        _init = DtoDefaultInit(loc, type);
+        _init = DtoConstExpInit(loc, type, type->defaultInit());
     }
     else if (ExpInitializer* ex = init->isExpInitializer())
     {
         Logger::println("const expression initializer");
-        _init = ex->exp->toConstElem(gIR);
+        _init = DtoConstExpInit(loc, type, ex->exp);;
     }
     else if (StructInitializer* si = init->isStructInitializer())
     {
@@ -1433,7 +1428,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-LLConstant* DtoConstFieldInitializer(Loc& loc, Type* t, Initializer* init)
+LLConstant* DtoConstFieldInitializer(Loc loc, Type* t, Initializer* init)
 {
     Logger::println("DtoConstFieldInitializer");
     LOG_SCOPE;
@@ -1530,20 +1525,33 @@
 
 static LLConstant* expand_to_sarray(Type *base, Expression* exp)
 {
-    Logger::println("building type %s to expression (%s) of type %s", base->toChars(), exp->toChars(), exp->type->toChars());
+    Logger::println("building type %s from expression (%s) of type %s", base->toChars(), exp->toChars(), exp->type->toChars());
     const LLType* dstTy = DtoType(base);
     if (Logger::enabled())
         Logger::cout() << "final llvm type requested: " << *dstTy << '\n';
-    
+
     LLConstant* val = exp->toConstElem(gIR);
-    
+
     Type* expbase = exp->type->toBasetype();
-    Type* t = base;
-    
+    Logger::println("expbase: %s", expbase->toChars());
+    Type* t = base->toBasetype();
+
     LLSmallVector<size_t, 4> dims;
 
+    // handle zero initializers
+    if (expbase->isintegral() && exp->isConst())
+    {
+        if (!exp->toInteger())
+            return LLConstant::getNullValue(dstTy);
+    }
+    else if (exp->op == TOKnull)
+    {
+        return LLConstant::getNullValue(dstTy);
+    }
+
     while(1)
     {
+        Logger::println("t: %s", t->toChars());
         if (t->equals(expbase))
             break;
         assert(t->ty == Tsarray);
@@ -1552,7 +1560,7 @@
         assert(t->nextOf());
         t = t->nextOf()->toBasetype();
     }
-    
+
     size_t i = dims.size();
     assert(i);
 
@@ -1564,17 +1572,15 @@
         inits.insert(inits.end(), dims[i], val);
         val = LLConstantArray::get(arrty, inits);
     }
-    
+
     return val;
 }
 
-LLConstant* DtoDefaultInit(Loc& loc, Type* type)
+LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp)
 {
-    Expression* exp = type->defaultInit();
-    
     Type* expbase = exp->type->toBasetype();
     Type* base = type->toBasetype();
-    
+
     // if not the same basetypes, we won't get the same llvm types either
     if (!expbase->equals(base))
     {
@@ -1584,7 +1590,6 @@
                 error(loc, "static arrays of voids have no default initializer");
                 fatal();
             }
-            
             Logger::println("type is a static array, building constant array initializer to single value");
             return expand_to_sarray(base, exp);
         }
@@ -1594,9 +1599,8 @@
             fatal();
         }
         assert(0);
-        
     }
-    
+
     return exp->toConstElem(gIR);
 }
 
@@ -1615,6 +1619,7 @@
         ++p;
     }
     // create a noop with the code as the result name!
+    // FIXME: this is const folded and eliminated immediately ... :/
     gIR->ir->CreateAnd(DtoConstSize_t(0),DtoConstSize_t(0),s.c_str());
 }
 
--- a/gen/llvmhelpers.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/llvmhelpers.h	Sat Nov 29 21:25:43 2008 +0100
@@ -86,8 +86,9 @@
 LLValue* DtoRawVarDeclaration(VarDeclaration* var);
 
 // initializer helpers
-LLConstant* DtoConstInitializer(Loc& loc, Type* type, Initializer* init);
-LLConstant* DtoConstFieldInitializer(Loc& loc, Type* type, Initializer* init);
+LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init);
+LLConstant* DtoConstFieldInitializer(Loc loc, Type* type, Initializer* init);
+LLConstant* DtoConstExpInit(Loc loc, Type* t, Expression* exp);
 DValue* DtoInitializer(LLValue* target, Initializer* init);
 
 // annotation generator
@@ -108,9 +109,6 @@
 // target stuff
 void findDefaultTarget();
 
-/// get the default initializer of the type
-LLConstant* DtoDefaultInit(Loc& loc, Type* t);
-
 // fixup an overloaded intrinsic name string
 void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, std::string& name);
 
--- a/gen/runtime.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/runtime.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -134,8 +134,10 @@
 
 static void LLVM_D_BuildRuntimeModule()
 {
+    Logger::println("building module");
     M = new llvm::Module("ldc internal runtime");
 
+    Logger::println("building basic types");
     const LLType* voidTy = LLType::VoidTy;
     const LLType* boolTy = LLType::Int1Ty;
     const LLType* byteTy = LLType::Int8Ty;
@@ -144,6 +146,7 @@
     const LLType* longTy = LLType::Int64Ty;
     const LLType* sizeTy = DtoSize_t();
 
+    Logger::println("building float types");
     const LLType* floatTy = LLType::FloatTy;
     const LLType* doubleTy = LLType::DoubleTy;
     const LLType* realTy;
@@ -156,15 +159,22 @@
     const LLType* cdoubleTy = llvm::StructType::get(doubleTy, doubleTy, NULL);
     const LLType* crealTy = llvm::StructType::get(realTy, realTy, NULL);
 
+    Logger::println("building aggr types");
     const LLType* voidPtrTy = rt_ptr(byteTy);
     const LLType* stringTy = rt_array(byteTy);
     const LLType* wstringTy = rt_array(shortTy);
     const LLType* dstringTy = rt_array(intTy);
-    const LLType* objectTy = rt_ptr(ClassDeclaration::object->type->ir.type->get());
-    const LLType* classInfoTy = rt_ptr(ClassDeclaration::classinfo->type->ir.type->get());
-    const LLType* typeInfoTy = rt_ptr(Type::typeinfo->type->ir.type->get());
+
+    Logger::println("building class types");
+    const LLType* objectTy = DtoType(ClassDeclaration::object->type);
+    const LLType* classInfoTy = DtoType(ClassDeclaration::classinfo->type);
+    const LLType* typeInfoTy = DtoType(Type::typeinfo->type);
+
+    Logger::println("building aa type");
     const LLType* aaTy = rt_ptr(llvm::OpaqueType::get());
 
+    Logger::println("building functions");
+
     /////////////////////////////////////////////////////////////////////////////////////
     /////////////////////////////////////////////////////////////////////////////////////
     /////////////////////////////////////////////////////////////////////////////////////
--- a/gen/statements.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/statements.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -897,7 +897,7 @@
         DtoDwarfStopPoint(loc.linnum);
 
     // DMD doesn't fold stuff like continue/break, and since this isn't really a loop
-    // we have to keep track of each statement and jump to next the next/end on continue/break
+    // we have to keep track of each statement and jump to the next/end on continue/break
 
     llvm::BasicBlock* oldend = gIR->scopeend();
 
--- a/gen/structs.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/structs.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -18,36 +18,279 @@
 #include "ir/irstruct.h"
 
 //////////////////////////////////////////////////////////////////////////////////////////
+void addZeros(std::vector<llvm::Constant*>& inits, unsigned pos, unsigned offset); // defined in irstruct.cpp
+
+// pair of var and its init
+typedef std::pair<VarDeclaration*,Initializer*> VarInitPair;
+
+// comparison func for qsort
+static int varinit_offset_cmp_func(const void* p1, const void* p2)
+{
+    VarDeclaration* v1 = ((VarInitPair*)p1)->first;
+    VarDeclaration* v2 = ((VarInitPair*)p2)->first;
+    if (v1->offset < v2->offset)
+        return -1;
+    else if (v1->offset > v2->offset)
+        return 1;
+    else
+        return 0;
+}
+
+/*
+this uses a simple algorithm to build the correct constant
+
+(1) first sort the explicit initializers by offset... well, DMD doesn't :)
+
+(2) if there is NO space before the next explicit initializeer, goto (9)
+(3) find the next default initializer that fits before it, if NOT found goto (7)
+(4) insert zero padding up to the next default initializer
+(5) insert the next default initializer
+(6) goto (2)
+
+(7) insert zero padding up to the next explicit initializer
+
+(9) insert the next explicit initializer
+(10) goto (2)
+
+(11) done
+
+(next can be the end too)
+
+*/
+
+// return the next default initializer to use or null
+static VarDeclaration* nextDefault(IrStruct* irstruct, size_t& idx, size_t pos, size_t offset)
+{
+    IrStruct::VarDeclVector& defaults = irstruct->defVars;
+    size_t ndefaults = defaults.size();
+
+    // for each valid index
+    while(idx < ndefaults)
+    {
+        VarDeclaration* v = defaults[idx];
+
+        // skip defaults before pos
+        if (v->offset < pos)
+        {
+            idx++;
+            continue;
+        }
+
+        // this var default fits
+        if (v->offset >= pos && v->offset + v->type->size() <= offset)
+            return v;
+
+        // not usable
+        break;
+    }
+
+    // not usable
+    return NULL;
+}
+
 LLConstant* DtoConstStructInitializer(StructInitializer* si)
 {
     Logger::println("DtoConstStructInitializer: %s", si->toChars());
     LOG_SCOPE;
 
+    // get TypeStruct
     assert(si->ad);
     TypeStruct* ts = (TypeStruct*)si->ad->type;
 
-    DtoResolveDsymbol(si->ad);
+    // force constant initialization of the symbol
+    DtoForceConstInitDsymbol(si->ad);
 
+    // get formal type
     const llvm::StructType* structtype = isaStruct(ts->ir.type->get());
 
+    // log it
     if (Logger::enabled())
         Logger::cout() << "llvm struct type: " << *structtype << '\n';
 
+    // sanity check
+    assert(si->value.dim > 0);
     assert(si->value.dim == si->vars.dim);
 
-    std::vector<DUnionIdx> inits;
-    for (int i = 0; i < si->value.dim; ++i)
+    // vector of final initializer constants
+    std::vector<LLConstant*> inits;
+
+    // get the ir struct
+    IrStruct* irstruct = si->ad->ir.irStruct;
+
+    // get default fields
+    IrStruct::VarDeclVector& defaults = irstruct->defVars;
+    size_t ndefaults = defaults.size();
+
+    // make sure si->vars is sorted by offset
+    std::vector<VarInitPair> vars;
+    size_t nvars = si->vars.dim;
+    vars.resize(nvars);
+
+    // fill pair vector
+    for (size_t i = 0; i < nvars; i++)
     {
+        VarDeclaration* var = (VarDeclaration*)si->vars.data[i];
         Initializer* ini = (Initializer*)si->value.data[i];
+        assert(var);
         assert(ini);
-        VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
-        assert(vd);
-        LLConstant* v = DtoConstInitializer(vd->loc, vd->type, ini);
-        inits.push_back(DUnionIdx(vd->ir.irField->index, vd->ir.irField->indexOffset, v));
+        vars[i] = std::make_pair(var, ini);
+    }
+    // sort it
+    qsort(&vars[0], nvars, sizeof(VarInitPair), &varinit_offset_cmp_func);
+
+    // check integrity
+    // and do error checking, since the frontend does verify static struct initializers
+    size_t lastoffset = 0;
+    size_t lastsize = 0;
+    bool overlap = false;
+    for (size_t i=0; i < nvars; i++)
+    {
+        // next explicit init var
+        VarDeclaration* var = vars[i].first;
+        Logger::println("var = %s : +%u", var->toChars(), var->offset);
+
+        // I would have thought this to be a frontend check
+        for (size_t j=i+1; j<nvars; j++)
+        {
+            if (j == i)
+                continue;
+            VarDeclaration* var2 = vars[j].first;
+            if (var2->offset >= var->offset && var2->offset < var->offset + var->type->size())
+            {
+                fprintf(stdmsg, "Error: %s: initializer '%s' overlaps with '%s'\n", si->loc.toChars(), var->toChars(), var2->toChars());
+                overlap = true;
+            }
+        }
+
+        // update offsets
+        lastoffset = var->offset;
+        lastsize = var->type->size();
+    }
+
+    // error handling, report all overlaps before aborting
+    if (overlap)
+    {
+        error("%s: overlapping union initializers", si->loc.toChars());
     }
 
-    DtoConstInitStruct((StructDeclaration*)si->ad);
-    return si->ad->ir.irStruct->dunion->getConst(inits);
+    // go through each explicit initalizer, falling back to defaults or zeros when necessary
+    lastoffset = 0;
+    lastsize = 0;
+
+    size_t j=0; // defaults
+
+    for (size_t i=0; i < nvars; i++)
+    {
+        // get var and init
+        VarDeclaration* var = vars[i].first;
+        Initializer* ini = vars[i].second;
+
+        size_t offset = var->offset;
+        size_t size = var->type->size();
+
+        // if there is space before the next explicit initializer
+Lpadding:
+        size_t pos = lastoffset+lastsize;
+        if (offset > pos)
+        {
+            // find the the next default initializer that fits in this space
+            VarDeclaration* nextdef = nextDefault(irstruct, j, lastoffset+lastsize, offset);
+
+            // found
+            if (nextdef)
+            {
+                // need zeros before the default
+                if (nextdef->offset > pos)
+                {
+                    Logger::println("inserting %lu byte padding at %lu", nextdef->offset - pos, pos);
+                    addZeros(inits, pos, nextdef->offset);
+                }
+
+                // do the default
+                Logger::println("adding default field: %s : +%u", nextdef->toChars(), nextdef->offset);
+                LLConstant* c = nextdef->ir.irField->constInit;
+                inits.push_back(c);
+
+                // update offsets
+                lastoffset = nextdef->offset;
+                lastsize = nextdef->type->size();
+
+                // check if more defaults would fit
+                goto Lpadding;
+            }
+            // not found, pad with zeros
+            else
+            {
+                Logger::println("inserting %lu byte padding at %lu", offset - pos, pos);
+                addZeros(inits, pos, offset);
+                // offsets are updated by the explicit initializer
+            }
+        }
+
+        // insert next explicit
+        Logger::println("adding explicit field: %s : +%lu", var->toChars(), offset);
+        LOG_SCOPE;
+        LLConstant* c = DtoConstInitializer(var->loc, var->type, ini);
+        inits.push_back(c);
+
+        lastoffset = offset;
+        lastsize = size;
+    }
+
+    // there might still be padding after the last one, make sure that is defaulted/zeroed as well
+    size_t structsize = getABITypeSize(structtype);
+
+    // if there is space before the next explicit initializer
+    // FIXME: this should be handled in the loop above as well
+Lpadding2:
+    size_t pos = lastoffset+lastsize;
+    if (structsize > pos)
+    {
+        // find the the next default initializer that fits in this space
+        VarDeclaration* nextdef = nextDefault(irstruct, j, lastoffset+lastsize, structsize);
+
+        // found
+        if (nextdef)
+        {
+            // need zeros before the default
+            if (nextdef->offset > pos)
+            {
+                Logger::println("inserting %lu byte padding at %lu", nextdef->offset - pos, pos);
+                addZeros(inits, pos, nextdef->offset);
+            }
+
+            // do the default
+            Logger::println("adding default field: %s : +%u", nextdef->toChars(), nextdef->offset);
+            LLConstant* c = nextdef->ir.irField->constInit;
+            inits.push_back(c);
+
+            // update offsets
+            lastoffset = nextdef->offset;
+            lastsize = nextdef->type->size();
+
+            // check if more defaults would fit
+            goto Lpadding2;
+        }
+        // not found, pad with zeros
+        else
+        {
+            Logger::println("inserting %lu byte padding at %lu", structsize - pos, pos);
+            addZeros(inits, pos, structsize);
+            lastoffset = pos;
+            lastsize = structsize - pos;
+        }
+    }
+
+    assert(lastoffset+lastsize == structsize);
+
+    // make the constant struct
+    LLConstant* c = LLConstantStruct::get(inits, si->ad->ir.irStruct->packed);
+    if (Logger::enabled())
+    {
+        Logger::cout() << "constant struct initializer: " << *c << '\n';
+    }
+    assert(getABITypeSize(c->getType()) == structsize);
+    return c;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -61,17 +304,26 @@
     IrField* field = vd->ir.irField;
     assert(field);
 
-    unsigned idx = field->index;
-    unsigned off = field->indexOffset;
+    // get the start pointer
+    const LLType* st = getPtrToType(DtoType(sd->type));
 
-    const LLType* st = getPtrToType(DtoType(sd->type));
+    // cast to the formal struct type
     src = DtoBitCast(src, st);
 
-    LLValue* val = DtoGEPi(src, 0,idx);
-    val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
+    // gep to the index
+    LLValue* val = DtoGEPi(src, 0, field->index);
 
-    if (off)
-        val = DtoGEPi1(val, off);
+    // do we need to offset further? (union area)
+    if (field->unionOffset)
+    {
+        // cast to void*
+        val = DtoBitCast(val, getVoidPtrType());
+        // offset
+        val = DtoGEPi1(val, field->unionOffset);
+    }
+
+    // cast it to the right type
+    val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
 
     if (Logger::enabled())
         Logger::cout() << "value: " << *val << '\n';
@@ -79,46 +331,46 @@
     return val;
 }
 
-//////////////////////////////////////////////////////////////////////////////////////////
-
 void DtoResolveStruct(StructDeclaration* sd)
 {
+    // don't do anything if already been here
     if (sd->ir.resolved) return;
+    // make sure above works :P
     sd->ir.resolved = true;
 
-    Logger::println("DtoResolveStruct(%s): %s", sd->toChars(), sd->loc.toChars());
+    // log what we're doing
+    Logger::println("Resolving struct type: %s (%s)", sd->toChars(), sd->locToChars());
     LOG_SCOPE;
 
-    TypeStruct* ts = (TypeStruct*)sd->type->toBasetype();
+    // get the DMD TypeStruct
+    TypeStruct* ts = (TypeStruct*)sd->type;
 
-    // this struct is a forward declaration
+    // create the IrStruct
+    IrStruct* irstruct = new IrStruct(sd);
+    sd->ir.irStruct = irstruct;
+
+    // create the type
+    ts->ir.type = new LLPATypeHolder(llvm::OpaqueType::get());
+
+    // handle forward declaration structs (opaques)
     // didn't even know D had those ...
     if (sd->sizeok != 1)
     {
-        sd->ir.irStruct = new IrStruct(ts);
-        ts->ir.type = new llvm::PATypeHolder(llvm::OpaqueType::get());
+        // nothing more to do
         return;
     }
 
-    bool ispacked = (ts->alignsize() == 1);
-
-    // create the IrStruct
-    IrStruct* irstruct = new IrStruct(ts);
-    sd->ir.irStruct = irstruct;
+    // make this struct current
     gIR->structs.push_back(irstruct);
 
-    // add fields
-    Array* fields = &sd->fields;
-    for (int k=0; k < fields->dim; k++)
-    {
-        VarDeclaration* v = (VarDeclaration*)fields->data[k];
-        Logger::println("Adding field: %s %s", v->type->toChars(), v->toChars());
-        // init fields, used to happen in VarDeclaration::toObjFile
-        irstruct->addField(v);
-    }
+    // get some info
+    bool ispacked = (ts->alignsize() == 1);
+    bool isunion = sd->isUnionDeclaration();
 
+    // set irstruct info
     irstruct->packed = ispacked;
 
+    // defined in this module?
     bool thisModule = false;
     if (sd->getModule() == gIR->dmodule)
         thisModule = true;
@@ -127,21 +379,29 @@
     Array* arr = sd->members;
     for (int k=0; k < arr->dim; k++) {
         Dsymbol* s = (Dsymbol*)arr->data[k];
-        if (FuncDeclaration* fd = s->isFuncDeclaration()) {
-            if (thisModule || (fd->prot() != PROTprivate)) {
-                fd->toObjFile(0); // TODO: multiobj
-            }
-        }
-        else if (s->isAttribDeclaration() ||
-                 s->isVarDeclaration() ||
-                 s->isTemplateMixin()) {
-            s->toObjFile(0); // TODO: multiobj
-        }
-        else {
-            Logger::println("Ignoring dsymbol '%s' in this->members of kind '%s'", s->toPrettyChars(), s->kind());
-        }
+        s->toObjFile(0);
     }
 
+    const LLType* ST = irstruct->build();
+
+#if 0
+    std::cout << sd->kind() << ' ' << sd->toPrettyChars() << " type: " << *ST << '\n';
+
+    // add fields
+    for (int k=0; k < fields->dim; k++)
+    {
+        VarDeclaration* v = (VarDeclaration*)fields->data[k];
+        printf("  field: %s %s\n", v->type->toChars(), v->toChars());
+        printf("    index: %u offset: %u\n", v->ir.irField->index, v->ir.irField->unionOffset);
+    }
+
+    unsigned llvmSize = (unsigned)getABITypeSize(ST);
+    unsigned dmdSize = (unsigned)sd->type->size();
+    printf("  llvm size: %u     dmd size: %u\n", llvmSize, dmdSize);
+    assert(llvmSize == dmdSize);
+
+#endif
+
     /*for (int k=0; k < sd->members->dim; k++) {
         Dsymbol* dsym = (Dsymbol*)(sd->members->data[k]);
         dsym->toObjFile();
@@ -149,98 +409,13 @@
 
     Logger::println("doing struct fields");
 
-    const llvm::StructType* structtype = 0;
-    std::vector<const LLType*> fieldtypes;
+    // refine abstract types for stuff like: struct S{S* next;}
+    llvm::cast<llvm::OpaqueType>(ts->ir.type->get())->refineAbstractTypeTo(ST);
+    ST = ts->ir.type->get();
 
-    if (irstruct->offsets.empty())
-    {
-        Logger::println("has no fields");
-        fieldtypes.push_back(LLType::Int8Ty);
-        structtype = llvm::StructType::get(fieldtypes, ispacked);
-    }
-    else
-    {
-        Logger::println("has fields");
-        unsigned prevsize = (unsigned)-1;
-        unsigned lastoffset = (unsigned)-1;
-        const LLType* fieldtype = NULL;
-        VarDeclaration* fieldinit = NULL;
-        size_t fieldpad = 0;
-        int idx = 0;
-        for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
-            // first iteration
-            if (lastoffset == (unsigned)-1) {
-                lastoffset = i->first;
-                assert(lastoffset == 0);
-                fieldtype = i->second.type;
-                fieldinit = i->second.var;
-                prevsize = fieldinit->type->size();
-                i->second.var->ir.irField->index = idx;
-            }
-            // colliding offset?
-            else if (lastoffset == i->first) {
-                size_t s = i->second.var->type->size();
-                if (s > prevsize) {
-                    fieldpad += s - prevsize;
-                    prevsize = s;
-                }
-                sd->ir.irStruct->hasUnions = true;
-                i->second.var->ir.irField->index = idx;
-            }
-            // intersecting offset?
-            else if (i->first < (lastoffset + prevsize)) {
-                size_t s = i->second.var->type->size();
-                assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
-                sd->ir.irStruct->hasUnions = true;
-                i->second.var->ir.irField->index = idx;
-                i->second.var->ir.irField->indexOffset = (i->first - lastoffset) / s;
-            }
-            // fresh offset
-            else {
-                // commit the field
-                fieldtypes.push_back(fieldtype);
-                irstruct->defaultFields.push_back(fieldinit);
-                if (fieldpad) {
-                    fieldtypes.push_back(llvm::ArrayType::get(LLType::Int8Ty, fieldpad));
-                    irstruct->defaultFields.push_back(NULL);
-                    idx++;
-                }
-
-                idx++;
-
-                // start new
-                lastoffset = i->first;
-                fieldtype = i->second.type;
-                fieldinit = i->second.var;
-                prevsize = fieldinit->type->size();
-                i->second.var->ir.irField->index = idx;
-                fieldpad = 0;
-            }
-        }
-        fieldtypes.push_back(fieldtype);
-        irstruct->defaultFields.push_back(fieldinit);
-        if (fieldpad) {
-            fieldtypes.push_back(llvm::ArrayType::get(LLType::Int8Ty, fieldpad));
-            irstruct->defaultFields.push_back(NULL);
-        }
-
-        Logger::println("creating struct type");
-        structtype = llvm::StructType::get(fieldtypes, ispacked);
-    }
-
-    // refine abstract types for stuff like: struct S{S* next;}
-    if (irstruct->recty != 0)
-    {
-        llvm::PATypeHolder& pa = irstruct->recty;
-        llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
-        structtype = isaStruct(pa.get());
-    }
-
-    assert(ts->ir.type == 0);
-    ts->ir.type = new llvm::PATypeHolder(structtype);
-
+    // name type
     if (sd->parent->isModule()) {
-        gIR->module->addTypeName(sd->mangle(),structtype);
+        gIR->module->addTypeName(sd->mangle(),ST);
     }
 
     gIR->structs.pop_back();
@@ -265,7 +440,7 @@
     initname.append("6__initZ");
 
     llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(sd);
-    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->ir.type->get(), true, _linkage, NULL, initname, gIR->module);
+    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(sd->ir.irStruct->initOpaque.get(), true, _linkage, NULL, initname, gIR->module);
     sd->ir.irStruct->init = initvar;
 
     gIR->constInitList.push_back(sd);
@@ -286,59 +461,33 @@
     IrStruct* irstruct = sd->ir.irStruct;
     gIR->structs.push_back(irstruct);
 
-    // make sure each offset knows its default initializer
-    for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i)
-    {
-        IrStruct::Offset* so = &i->second;
-        LLConstant* finit = DtoConstFieldInitializer(so->var->loc, so->var->type, so->var->init);
-        so->init = finit;
-        so->var->ir.irField->constInit = finit;
-    }
-
     const llvm::StructType* structtype = isaStruct(sd->type->ir.type->get());
 
-    // go through the field inits and build the default initializer
-    std::vector<LLConstant*> fieldinits_ll;
-    size_t nfi = irstruct->defaultFields.size();
-    for (size_t i=0; i<nfi; ++i) {
-        LLConstant* c;
-        if (irstruct->defaultFields[i] != NULL) {
-            c = irstruct->defaultFields[i]->ir.irField->constInit;
-            assert(c);
-        }
-        else {
-            const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i));
-            std::vector<LLConstant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(LLType::Int8Ty, 0, false));
-            c = llvm::ConstantArray::get(arrty, vals);
-        }
-        fieldinits_ll.push_back(c);
+    // make sure each offset knows its default initializer
+    Array* fields = &sd->fields;
+    for (int k=0; k < fields->dim; k++)
+    {
+        VarDeclaration* v = (VarDeclaration*)fields->data[k];
+        LLConstant* finit = DtoConstFieldInitializer(v->loc, v->type, v->init);
+        v->ir.irField->constInit = finit;
     }
 
-    // generate the union mapper
-    sd->ir.irStruct->dunion = new DUnion(); // uses gIR->topstruct()
-
     // always generate the constant initalizer
-    if (!sd->zeroInit) {
+    if (sd->zeroInit)
+    {
+        Logger::println("Zero initialized");
+        irstruct->constInit = llvm::ConstantAggregateZero::get(structtype);
+    }
+    else
+    {
         Logger::println("Not zero initialized");
-    #if 0
-        //assert(tk == gIR->gIR->topstruct()().size());
-        #ifndef LLVMD_NO_LOGGER
-        Logger::cout() << "struct type: " << *structtype << '\n';
-        for (size_t k=0; k<fieldinits_ll.size(); ++k) {
-            Logger::cout() << "Type:" << '\n';
-            Logger::cout() << *fieldinits_ll[k]->getType() << '\n';
-            Logger::cout() << "Value:" << '\n';
-            Logger::cout() << *fieldinits_ll[k] << '\n';
-        }
-        Logger::cout() << "Initializer printed" << '\n';
-        #endif
-    #endif
-        sd->ir.irStruct->constInit = llvm::ConstantStruct::get(structtype,fieldinits_ll);
+
+        LLConstant* c = irstruct->buildDefaultConstInit();
+        irstruct->constInit = c;
     }
-    else {
-        Logger::println("Zero initialized");
-        sd->ir.irStruct->constInit = llvm::ConstantAggregateZero::get(structtype);
-    }
+
+    // refine __initZ global type to the one of the initializer
+    llvm::cast<llvm::OpaqueType>(irstruct->initOpaque.get())->refineAbstractTypeTo(irstruct->constInit->getType());
 
     gIR->structs.pop_back();
 
@@ -385,163 +534,3 @@
     LLValue* val = DtoMemCmp(lhs->getRVal(), rhs->getRVal(), DtoConstSize_t(sz));
     return gIR->ir->CreateICmp(cmpop, val, LLConstantInt::get(val->getType(), 0, false), "tmp");
 }
-
-//////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////   D UNION HELPER CLASS   ////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////////////////
-
-DUnion::DUnion()
-{
-    DUnionField* f = NULL;
-    IrStruct* topstruct = gIR->topstruct();
-    bool unions = false;
-    for (IrStruct::OffsetMap::iterator i=topstruct->offsets.begin(); i!=topstruct->offsets.end(); ++i)
-    {
-        unsigned o = i->first;
-        IrStruct::Offset* so = &i->second;
-        const LLType* ft = so->init->getType();
-        size_t sz = getABITypeSize(ft);
-        if (f == NULL) { // new field
-            fields.push_back(DUnionField());
-            f = &fields.back();
-            f->size = sz;
-            f->offset = o;
-            f->init = so->init;
-            f->initsize = sz; 
-            f->types.push_back(ft);
-        }
-        else if (o == f->offset) { // same offset
-            if (sz > f->size)
-                f->size = sz;
-            f->types.push_back(ft);
-            unions = true;
-        }
-        else if (o < f->offset+f->size) {
-            assert((o+sz) <= (f->offset+f->size));
-            unions = true;
-        }
-        else {
-            fields.push_back(DUnionField());
-            f = &fields.back();
-            f->size = sz;
-            f->offset = o;
-            f->init = so->init;
-            f->initsize = sz;
-            f->types.push_back(ft);
-        }
-    }
-
-    ispacked = topstruct->packed;
-
-    /*{
-        LOG_SCOPE;
-        Logger::println("******** DUnion BEGIN");
-        size_t n = fields.size();
-        for (size_t i=0; i<n; ++i) {
-            Logger::cout()<<"field #"<<i<<" offset: "<<fields[i].offset<<" size: "<<fields[i].size<<'('<<fields[i].initsize<<")\n";
-            LOG_SCOPE;
-            size_t nt = fields[i].types.size();
-            for (size_t j=0; j<nt; ++j) {
-                Logger::cout()<<*fields[i].types[j]<<'\n';
-            }
-        }
-        Logger::println("******** DUnion END");
-    }*/
-}
-
-static void push_nulls(size_t nbytes, std::vector<LLConstant*>& out)
-{
-    assert(nbytes > 0);
-    std::vector<LLConstant*> i(nbytes, llvm::ConstantInt::get(LLType::Int8Ty, 0, false));
-    out.push_back(llvm::ConstantArray::get(llvm::ArrayType::get(LLType::Int8Ty, nbytes), i));
-}
-
-LLConstant* DUnion::getConst(std::vector<DUnionIdx>& in)
-{
-    std::sort(in.begin(), in.end());
-    std::vector<LLConstant*> out;
-
-    size_t nin = in.size();
-    size_t nfields = fields.size();
-
-    size_t fi = 0;
-    size_t last = 0;
-    size_t ii = 0;
-    size_t os = 0;
-
-    for(;;)
-    {
-        if (fi == nfields) break;
-
-        bool nextSame = (ii+1 < nin) && (in[ii+1].idx == fi);
-
-        if (ii < nin && fi == in[ii].idx)
-        {
-            size_t s = getABITypeSize(in[ii].c->getType());
-            if (in[ii].idx == last)
-            {
-                size_t nos = in[ii].idxos * s;
-                if (nos && nos-os) {
-                    assert(nos >= os);
-                    push_nulls(nos-os, out);
-                }
-                os = nos + s;
-            }
-            else
-            {
-                os = s;
-            }
-            out.push_back(in[ii].c);
-            ii++;
-            if (!nextSame)
-            {
-                if (os < fields[fi].size)
-                    push_nulls(fields[fi].size - os, out);
-                os = 0;
-                last = fi++;
-            }
-            continue;
-        }
-
-        // default initialize if necessary
-        if (ii == nin || fi < in[ii].idx)
-        {
-            DUnionField& f = fields[fi];
-            out.push_back(f.init);
-            if (f.initsize < f.size)
-                push_nulls(f.size - f.initsize, out);
-            last = fi++;
-            os = 0;
-            continue;
-        }
-    }
-
-    std::vector<const LLType*> tys;
-    size_t nout = out.size();
-    for (size_t i=0; i<nout; ++i)
-        tys.push_back(out[i]->getType());
-
-    const llvm::StructType* st = llvm::StructType::get(tys, ispacked);
-    return llvm::ConstantStruct::get(st, out);
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
--- a/gen/structs.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/structs.h	Sat Nov 29 21:25:43 2008 +0100
@@ -33,43 +33,4 @@
 // index a struct one level
 LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd);
 
-struct DUnionField
-{
-    unsigned offset;
-    size_t size;
-    std::vector<const LLType*> types;
-    LLConstant* init;
-    size_t initsize;
-
-    DUnionField() {
-        offset = 0;
-        size = 0;
-        init = NULL;
-        initsize = 0;
-    }
-};
-
-struct DUnionIdx
-{
-    unsigned idx,idxos;
-    LLConstant* c;
-
-    DUnionIdx()
-    : idx(0), c(0) {}
-    DUnionIdx(unsigned _idx, unsigned _idxos, LLConstant* _c)
-    : idx(_idx), idxos(_idxos), c(_c) {}
-    bool operator<(const DUnionIdx& i) const {
-        return (idx < i.idx) || (idx == i.idx && idxos < i.idxos);
-    }
-};
-
-class DUnion
-{
-    std::vector<DUnionField> fields;
-    bool ispacked;
-public:
-    DUnion();
-    LLConstant* getConst(std::vector<DUnionIdx>& in);
-};
-
 #endif
--- a/gen/tocall.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/tocall.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -41,11 +41,12 @@
     {
         //TODO: StdCall is not a good base on Windows due to extra name mangling
         // applied there
-        if (global.params.cpu == ARCHx86 && global.params.os != OSWindows)
-            return llvm::CallingConv::X86_StdCall;
+        if (global.params.cpu == ARCHx86)
+            return (global.params.os != OSWindows) ? llvm::CallingConv::X86_StdCall : llvm::CallingConv::C;
         else
             return llvm::CallingConv::Fast;
     }
+    // on the other hand, here, it's exactly what we want!!! TODO: right?
     else if (l == LINKwindows)
         return llvm::CallingConv::X86_StdCall;
     else
@@ -155,7 +156,6 @@
     }
 
     // build type info array
-    assert(Type::typeinfo->ir.irStruct->constInit);
     const LLType* typeinfotype = DtoType(Type::typeinfo->type);
     const LLArrayType* typeinfoarraytype = LLArrayType::get(typeinfotype,vtype->getNumElements());
 
--- a/gen/todebug.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/todebug.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -452,14 +452,19 @@
         definedCU = DtoDwarfCompileUnit(sd->getModule());
 
         std::vector<LLConstant*> elems;
-        elems.reserve(ir->offsets.size());
-        for (IrStruct::OffsetMap::iterator i=ir->offsets.begin(); i!=ir->offsets.end(); ++i)
+        if (!ir->aggrdecl->isInterfaceDeclaration()) // plain interfaces don't have one
         {
-            unsigned offset = i->first;
-            IrStruct::Offset& o = i->second;
+            std::vector<VarDeclaration*>& arr = ir->varDecls;
+            size_t narr = arr.size();
+            elems.reserve(narr);
+            for (int k=0; k<narr; k++)
+            {
+                VarDeclaration* vd = arr[k];
+                assert(vd);
 
-            LLGlobalVariable* ptr = dwarfMemberType(o.var->loc.linnum, o.var->type, compileUnit, definedCU, o.var->toChars(), offset);
-            elems.push_back(DBG_CAST(ptr));
+                LLGlobalVariable* ptr = dwarfMemberType(vd->loc.linnum, vd->type, compileUnit, definedCU, vd->toChars(), vd->offset);
+                elems.push_back(DBG_CAST(ptr));
+            }
         }
 
         const LLArrayType* at = LLArrayType::get(DBG_TYPE, elems.size());
--- a/gen/toir.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/toir.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -135,20 +135,27 @@
         }
         else {
             Logger::println("a normal variable");
+
             // take care of forward references of global variables
             if (vd->isDataseg() || (vd->storage_class & STCextern)) {
                 vd->toObjFile(0); // TODO: multiobj
             }
-            if (!vd->ir.isSet() || !vd->ir.getIrValue()) {
+
+            LLValue* val;
+
+            if (!vd->ir.isSet() || !(val = vd->ir.getIrValue())) {
                 error("variable %s not resolved", vd->toChars());
                 if (Logger::enabled())
                     Logger::cout() << "unresolved variable had type: " << *DtoType(vd->type) << '\n';
                 fatal();
             }
+
             if (vd->isDataseg() || (vd->storage_class & STCextern)) {
                 DtoConstInitGlobal(vd);
+                val = DtoBitCast(val, DtoType(type->pointerTo()));
             }
-            return new DVarValue(type, vd, vd->ir.getIrValue());
+
+            return new DVarValue(type, vd, val);
         }
     }
     else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
@@ -369,7 +376,7 @@
     llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
     if (Logger::enabled())
         Logger::cout() << "type: " << *at << "\ninit: " << *_init << '\n';
-    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,".stringliteral",gIR->module);
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,".str",gIR->module);
 
     llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false);
     LLConstant* idxs[2] = { zero, zero };
@@ -443,7 +450,7 @@
     }
 
     llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
-    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,".stringliteral",gIR->module);
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,".str",gIR->module);
 
     llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false);
     LLConstant* idxs[2] = { zero, zero };
@@ -1008,19 +1015,21 @@
             assert(fdecl->vtblIndex > 0);
             assert(e1type->ty == Tclass);
 
-            LLValue* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false);
-            LLValue* vtblidx = llvm::ConstantInt::get(LLType::Int32Ty, (size_t)fdecl->vtblIndex, false);
+            LLValue* zero = DtoConstUint(0);
+            size_t vtblidx = fdecl->vtblIndex;
             if (Logger::enabled())
                 Logger::cout() << "vthis: " << *vthis << '\n';
-            funcval = DtoGEP(vthis, zero, zero);
+            funcval = vthis;
+            if (!fdecl->isMember2()->isInterfaceDeclaration())
+                funcval = DtoGEP(funcval, zero, zero);
             funcval = DtoLoad(funcval);
-            funcval = DtoGEP(funcval, zero, vtblidx, toChars());
+            Logger::println("vtblidx = %lu", vtblidx);
+            funcval = DtoGEP(funcval, zero, DtoConstUint(vtblidx), toChars());
             funcval = DtoLoad(funcval);
-        #if OPAQUE_VTBLS
+
             funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type)));
             if (Logger::enabled())
                 Logger::cout() << "funcval casted: " << *funcval << '\n';
-        #endif
         }
         // static call
         else {
@@ -2143,6 +2152,22 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+LLConstant* FuncExp::toConstElem(IRState* p)
+{
+    Logger::print("FuncExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    assert(fd);
+    assert(fd->tok == TOKfunction);
+
+    DtoForceDefineDsymbol(fd);
+    assert(fd->ir.irFunc->func);
+
+    return fd->ir.irFunc->func;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 DValue* ArrayLiteralExp::toElem(IRState* p)
 {
     Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
@@ -2252,91 +2277,147 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+void addZeros(std::vector<llvm::Value*>& inits, unsigned pos, unsigned offset);
+
 DValue* StructLiteralExp::toElem(IRState* p)
 {
     Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    const LLType* llt = DtoType(type);
-
-    LLValue* mem = 0;
-
-    LLValue* sptr = DtoAlloca(llt,"tmpstructliteral");
-
-    // default init the struct to take care of padding
-    // and unspecified members
-    TypeStruct* ts = (TypeStruct*)type->toBasetype();
-    assert(ts->sym);
-    DtoForceConstInitDsymbol(ts->sym);
-    assert(ts->sym->ir.irStruct->init);
-    DtoAggrCopy(sptr, ts->sym->ir.irStruct->init);
-
-    // num elements in literal
-    unsigned n = elements->dim;
-
-    // unions might have different types for each literal
-    if (sd->ir.irStruct->hasUnions) {
-        // build the type of the literal
-        std::vector<const LLType*> tys;
-        for (unsigned i=0; i<n; ++i) {
-            Expression* vx = (Expression*)elements->data[i];
-            if (!vx) continue;
-            tys.push_back(DtoType(vx->type));
+    // get arrays 
+    size_t n = elements->dim;
+    Expression** exprs = (Expression**)elements->data;
+
+    assert(sd->fields.dim == n);
+    VarDeclaration** vars = (VarDeclaration**)sd->fields.data;
+
+    // vector of values to build aggregate from
+    std::vector<llvm::Value*> values;
+
+    // trackers
+    size_t lastoffset = 0;
+    size_t lastsize = 0;
+
+    // for through each field and build up the struct, padding with zeros
+    for (size_t i=0; i<n; i++)
+    {
+        Expression* e = exprs[i];
+        VarDeclaration* var = vars[i];
+
+        // field is skipped
+        if (!e)
+            continue;
+
+        // add any 0 padding needed before this field
+        if (var->offset > lastoffset + lastsize)
+        {
+            addZeros(values, lastoffset + lastsize, var->offset);
         }
-        const LLStructType* t = LLStructType::get(tys, sd->ir.irStruct->packed);
-        if (t != llt) {
-            if (getABITypeSize(t) != getABITypeSize(llt)) {
-                if (Logger::enabled())
-                    Logger::cout() << "got size " << getABITypeSize(t) << ", expected " << getABITypeSize(llt) << '\n';
-                assert(0 && "type size mismatch");
-            }
-            sptr = DtoBitCast(sptr, getPtrToType(t));
-            if (Logger::enabled())
-                Logger::cout() << "sptr type is now: " << *t << '\n';
-        }
+
+        // add the expression value
+        DValue* v = e->toElem(p);
+        values.push_back(v->getRVal());
+
+        // update offsets
+        lastoffset = var->offset;
+        lastsize = var->type->size();
+    }
+
+    // add any 0 padding needed at the end of the literal
+    const LLType* structtype = DtoType(sd->type);
+    size_t structsize = getABITypeSize(structtype);
+
+    if (structsize > lastoffset+lastsize)
+    {
+        addZeros(values, lastoffset + lastsize, structsize);
     }
 
-    // build
-    unsigned j = 0;
-    for (unsigned i=0; i<n; ++i)
+    // get the struct type from the values
+    n = values.size();
+    std::vector<const LLType*> types(n, NULL);
+
+    for (size_t i=0; i<n; i++)
     {
-        Expression* vx = (Expression*)elements->data[i];
-        if (!vx) continue;
-
-        if (Logger::enabled())
-            Logger::cout() << "getting index " << j << " of " << *sptr << '\n';
-        LLValue* arrptr = DtoGEPi(sptr,0,j);
-        DValue* darrptr = new DVarValue(vx->type, arrptr);
-
-        DValue* ve = vx->toElem(p);
-        DtoAssign(loc, darrptr, ve);
-
-        j++;
+        types[i] = values[i]->getType();
     }
 
-    return new DImValue(type, sptr);
+    const LLStructType* sty = LLStructType::get(types, sd->ir.irStruct->packed);
+
+    // allocate storage for the struct literal on the stack
+    LLValue* mem = DtoAlloca(sty, "tmpstructliteral");
+
+    // put all the values into the storage
+    for (size_t i=0; i<n; i++)
+    {
+        LLValue* ptr = DtoGEPi(mem, 0, i);
+        DtoStore(values[i], ptr);
+    }
+
+    // cast the alloca pointer to the "formal" struct type
+    mem = DtoBitCast(mem, getPtrToType(structtype));
+
+    // return as a var
+    return new DVarValue(type, mem);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+void addZeros(std::vector<llvm::Constant*>& inits, unsigned pos, unsigned offset);
+
 LLConstant* StructLiteralExp::toConstElem(IRState* p)
 {
     Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    unsigned n = elements->dim;
-    std::vector<LLConstant*> vals(n, NULL);
-
-    for (unsigned i=0; i<n; ++i)
+    // get arrays 
+    size_t n = elements->dim;
+    Expression** exprs = (Expression**)elements->data;
+
+    assert(sd->fields.dim == n);
+    VarDeclaration** vars = (VarDeclaration**)sd->fields.data;
+
+    // vector of values to build aggregate from
+    std::vector<llvm::Constant*> values;
+
+    // trackers
+    size_t lastoffset = 0;
+    size_t lastsize = 0;
+
+    // for through each field and build up the struct, padding with zeros
+    for (size_t i=0; i<n; i++)
     {
-        Expression* vx = (Expression*)elements->data[i];
-        vals[i] = vx->toConstElem(p);
+        Expression* e = exprs[i];
+        VarDeclaration* var = vars[i];
+
+        // field is skipped
+        if (!e)
+            continue;
+
+        // add any 0 padding needed before this field
+        if (var->offset > lastoffset + lastsize)
+        {
+            addZeros(values, lastoffset + lastsize, var->offset);
+        }
+
+        // add the expression value
+        values.push_back(e->toConstElem(p));
+
+        // update offsets
+        lastoffset = var->offset;
+        lastsize = var->type->size();
     }
 
-    assert(type->toBasetype()->ty == Tstruct);
-    const LLType* t = DtoType(type);
-    const LLStructType* st = isaStruct(t);
-    return llvm::ConstantStruct::get(st,vals);
+    // add any 0 padding needed at the end of the literal
+    const LLType* structtype = DtoType(sd->type);
+    size_t structsize = getABITypeSize(structtype);
+
+    if (structsize > lastoffset+lastsize)
+    {
+        addZeros(values, lastoffset + lastsize, structsize);
+    }
+
+    // return constant struct
+    return LLConstantStruct::get(values, sd->ir.irStruct->packed);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
--- a/gen/tollvm.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/tollvm.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -119,14 +119,14 @@
         TypeStruct* ts = (TypeStruct*)t;
         assert(ts->sym);
         DtoResolveDsymbol(ts->sym);
-        return ts->sym->ir.irStruct->recty.get(); // t->ir.type->get();
+        return ts->ir.type->get();
     }
 
     case Tclass:    {
         TypeClass* tc = (TypeClass*)t;
         assert(tc->sym);
         DtoResolveDsymbol(tc->sym);
-        return getPtrToType(tc->sym->ir.irStruct->recty.get()); // t->ir.type->get());
+        return getPtrToType(tc->ir.type->get());
     }
 
     // functions
@@ -584,6 +584,13 @@
     return gIR->ir->CreateBitCast(v, t, name ? name : "tmp");
 }
 
+LLConstant* DtoBitCast(LLConstant* v, const LLType* t)
+{
+    if (v->getType() == t)
+        return v;
+    return llvm::ConstantExpr::getBitCast(v, t);
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
 
 const LLPointerType* isaPointer(LLValue* v)
@@ -695,6 +702,33 @@
     return gTargetData->getPrefTypeAlignment(t);
 }
 
+const LLType* getBiggestType(const LLType** begin, size_t n)
+{
+    const LLType* bigTy = 0;
+    size_t bigSize = 0;
+    size_t bigAlign = 0;
+
+    const LLType** end = begin+n;
+    while (begin != end)
+    {
+        const LLType* T = *begin;
+
+        size_t sz = getABITypeSize(T);
+        size_t ali = getABITypeAlign(T);
+        if (sz > bigSize || (sz == bigSize && ali > bigAlign))
+        {
+            bigTy = T;
+            bigSize = sz;
+            bigAlign = ali;
+        }
+
+        ++begin;
+    }
+
+    // will be null for n==0
+    return bigTy;
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
 
 const LLStructType* DtoInterfaceInfoType()
--- a/gen/tollvm.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/tollvm.h	Sat Nov 29 21:25:43 2008 +0100
@@ -67,6 +67,7 @@
 LLValue* DtoLoad(LLValue* src, const char* name=0);
 void DtoStore(LLValue* src, LLValue* dst);
 LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name=0);
+LLConstant* DtoBitCast(LLConstant* v, const LLType* t);
 
 // llvm::dyn_cast wrappers
 const LLPointerType* isaPointer(LLValue* v);
@@ -96,6 +97,9 @@
 unsigned char getABITypeAlign(const LLType* t);
 unsigned char getPrefTypeAlign(const LLType* t);
 
+// get biggest type, for unions ...
+const LLType* getBiggestType(const LLType** begin, size_t n);
+
 // pair type helpers
 LLValue* DtoAggrPair(const LLType* type, LLValue* V1, LLValue* V2, const char* name = 0);
 LLValue* DtoAggrPair(LLValue* V1, LLValue* V2, const char* name = 0);
--- a/gen/toobj.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/toobj.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -77,6 +77,8 @@
 
     //printf("codegen: %s\n", srcfile->toChars());
 
+    assert(!global.errors);
+
     // start by deleting the old object file
     deleteObjFile();
 
@@ -156,16 +158,6 @@
         fatal();
     }
 
-    // start out by providing opaque for the built-in class types
-    if (!ClassDeclaration::object->type->ir.type)
-        ClassDeclaration::object->type->ir.type = new llvm::PATypeHolder(llvm::OpaqueType::get());
-
-    if (!Type::typeinfo->type->ir.type)
-        Type::typeinfo->type->ir.type = new llvm::PATypeHolder(llvm::OpaqueType::get());
-
-    if (!ClassDeclaration::classinfo->type->ir.type)
-        ClassDeclaration::classinfo->type->ir.type = new llvm::PATypeHolder(llvm::OpaqueType::get());
-
     // process module members
     for (int k=0; k < members->dim; k++) {
         Dsymbol* dsym = (Dsymbol*)(members->data[k]);
@@ -638,7 +630,7 @@
     const LLStructType* modulerefTy = DtoModuleReferenceType();
     std::vector<LLConstant*> mrefvalues;
     mrefvalues.push_back(LLConstant::getNullValue(modulerefTy->getContainedType(0)));
-    mrefvalues.push_back(moduleinfo);
+    mrefvalues.push_back(llvm::ConstantExpr::getBitCast(moduleinfo, modulerefTy->getContainedType(1)));
     LLConstant* thismrefinit = LLConstantStruct::get(modulerefTy, mrefvalues);
 
     // create the ModuleReference node for this module
@@ -704,6 +696,13 @@
     assert(moduleinfo);
     DtoForceConstInitDsymbol(moduleinfo);
 
+    // check for patch
+    if (moduleinfo->ir.irStruct->constInit->getNumOperands() != 11)
+    {
+        error("unpatched object.d detected, ModuleInfo incorrect");
+        fatal();
+    }
+
     // moduleinfo llvm struct type
     const llvm::StructType* moduleinfoTy = isaStruct(moduleinfo->type->ir.type->get());
 
@@ -783,9 +782,15 @@
             Logger::println("skipping interface '%s' in moduleinfo", cd->toPrettyChars());
             continue;
         }
+        else if (cd->sizeok != 1)
+        {
+            Logger::println("skipping opaque class declaration '%s' in moduleinfo", cd->toPrettyChars());
+            continue;
+        }
         Logger::println("class: %s", cd->toPrettyChars());
         assert(cd->ir.irStruct->classInfo);
-        classInits.push_back(cd->ir.irStruct->classInfo);
+        c = llvm::ConstantExpr::getBitCast(cd->ir.irStruct->classInfo, getPtrToType(classinfoTy));
+        classInits.push_back(c);
     }
     // has class array?
     if (!classInits.empty())
@@ -842,7 +847,7 @@
     }*/
 
     // create initializer
-    LLConstant* constMI = llvm::ConstantStruct::get(moduleinfoTy, initVec);
+    LLConstant* constMI = llvm::ConstantStruct::get(initVec);
 
     // create name
     std::string MIname("_D");
@@ -853,7 +858,8 @@
     // flags will be modified at runtime so can't make it constant
 
     llvm::GlobalVariable* gvar = gIR->module->getGlobalVariable(MIname);
-    if (!gvar) gvar = new llvm::GlobalVariable(moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname, gIR->module);
+    if (!gvar) gvar = new llvm::GlobalVariable(constMI->getType(), false, llvm::GlobalValue::ExternalLinkage, NULL, MIname, gIR->module);
+    else assert(gvar->getType()->getContainedType(0) == constMI->getType());
     gvar->setInitializer(constMI);
 
     // build the modulereference and ctor for registering it
@@ -988,7 +994,8 @@
     #else
         bool _isconst = isConst();
     #endif
-        if (parent && parent->isFuncDeclaration())
+        Dsymbol* par = toParent2();
+        if (par && par->isFuncDeclaration())
         {
             static_local = true;
             if (init && init->isExpInitializer()) {
@@ -1015,20 +1022,17 @@
     }
     else
     {
-#if DMDV2
-    #if 0
+        // might already have its irField, as classes derive each other without getting copies of the VarDeclaration
         if (!ir.irField)
         {
-            printf("dataseg: %d\n", isDataseg());
-            printf("parent: %s %s\n", parent->kind(), parent->toPrettyChars());
-            printf("this: %s %s\n", this->kind(), this->toPrettyChars());
+            assert(!ir.isSet());
+            ir.irField = new IrField(this);
         }
-    #endif
-#else
-        assert(ir.irField != 0);
-#endif
+        IrStruct* irstruct = gIR->topstruct();
+        irstruct->addVar(this);
+
+        Logger::println("added offset %u", offset);
     }
-    Logger::println("VarDeclaration::toObjFile is done");
 }
 
 /* ================================================================== */
@@ -1056,3 +1060,28 @@
 {
     gIR->resolveList.push_back(this);
 }
+
+/* ================================================================== */
+
+void AnonDeclaration::toObjFile(int multiobj)
+{
+    Array *d = include(NULL, NULL);
+
+    if (d)
+    {
+        // get real aggregate parent
+        IrStruct* irstruct = gIR->topstruct();
+
+        // push a block on the stack
+        irstruct->pushAnon(isunion);
+
+        // go over children
+        for (unsigned i = 0; i < d->dim; i++)
+        {   Dsymbol *s = (Dsymbol *)d->data[i];
+            s->toObjFile(multiobj);
+        }
+
+        // finish
+        irstruct->popAnon();
+    }
+}
--- a/gen/typinf.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/typinf.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -379,7 +379,7 @@
     const LLStructType* stype = isaStruct(base->type->ir.type->get());
 
     // create the symbol
-    this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
+    ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
 }
 
 void TypeInfoTypedefDeclaration::llvmDefine()
@@ -390,10 +390,6 @@
     ClassDeclaration* base = Type::typeinfotypedef;
     DtoForceConstInitDsymbol(base);
 
-    const LLStructType* stype = isaStruct(base->type->ir.type->get());
-    if (Logger::enabled())
-        Logger::cout() << "got stype: " << *stype << '\n';
-
     // vtbl
     std::vector<LLConstant*> sinits;
     sinits.push_back(base->ir.irStruct->vtbl);
@@ -408,13 +404,11 @@
     // TypeInfo base
     sd->basetype = sd->basetype->merge(); // DMD does this!
     LLConstant* castbase = DtoTypeInfoOf(sd->basetype, true);
-    assert(castbase->getType() == stype->getElementType(2));
     sinits.push_back(castbase);
 
     // char[] name
     char *name = sd->toPrettyChars();
     sinits.push_back(DtoConstString(name));
-    assert(sinits.back()->getType() == stype->getElementType(3));
 
     // void[] init
     const LLPointerType* initpt = getPtrToType(LLType::Int8Ty);
@@ -433,9 +427,14 @@
         sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
     }
 
-    // create the symbol
-    LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
-    isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
+    // create the inititalizer
+    LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
+
+    // refine global type
+    llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
+
+    // set the initializer
+    isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
 }
 
 void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
@@ -453,10 +452,8 @@
     ClassDeclaration* base = Type::typeinfoenum;
     DtoResolveClass(base);
 
-    const LLStructType* stype = isaStruct(base->type->ir.type->get());
-
     // create the symbol
-    this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
+    ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
 }
 
 void TypeInfoEnumDeclaration::llvmDefine()
@@ -467,8 +464,6 @@
     ClassDeclaration* base = Type::typeinfoenum;
     DtoForceConstInitDsymbol(base);
 
-    const LLStructType* stype = isaStruct(base->type->ir.type->get());
-
     // vtbl
     std::vector<LLConstant*> sinits;
     sinits.push_back(base->ir.irStruct->vtbl);
@@ -482,13 +477,11 @@
 
     // TypeInfo base
     LLConstant* castbase = DtoTypeInfoOf(sd->memtype, true);
-    assert(castbase->getType() == stype->getElementType(2));
     sinits.push_back(castbase);
 
     // char[] name
     char *name = sd->toPrettyChars();
     sinits.push_back(DtoConstString(name));
-    assert(sinits.back()->getType() == stype->getElementType(3));
 
     // void[] init
     const LLPointerType* initpt = getPtrToType(LLType::Int8Ty);
@@ -512,9 +505,14 @@
     #endif
     }
 
-    // create the symbol
-    LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
-    isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
+    // create the inititalizer
+    LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
+
+    // refine global type
+    llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
+
+    // set the initializer
+    isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
 }
 
 void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
@@ -529,10 +527,8 @@
     ClassDeclaration* base = cd;
     DtoResolveClass(base);
 
-    const LLStructType* stype = isaStruct(base->type->ir.type->get());
-
     // create the symbol
-    tid->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,tid->toChars(),gIR->module);
+    tid->ir.irGlobal->value = new llvm::GlobalVariable(tid->ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,tid->toChars(),gIR->module);
 }
 
 static LLConstant* LLVM_D_Define_TypeInfoBase(Type* basetype, TypeInfoDeclaration* tid, ClassDeclaration* cd)
@@ -540,8 +536,6 @@
     ClassDeclaration* base = cd;
     DtoForceConstInitDsymbol(base);
 
-    const LLStructType* stype = isaStruct(base->type->ir.type->get());
-
     // vtbl
     std::vector<LLConstant*> sinits;
     sinits.push_back(base->ir.irStruct->vtbl);
@@ -551,11 +545,15 @@
 
     // TypeInfo base
     LLConstant* castbase = DtoTypeInfoOf(basetype, true);
-    assert(castbase->getType() == stype->getElementType(2));
     sinits.push_back(castbase);
 
-    // create the symbol
-    LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
+    // create the inititalizer
+    LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
+
+    // refine global type
+    llvm::cast<llvm::OpaqueType>(tid->ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
+
+    // set the initializer
     isaGlobalVar(tid->ir.irGlobal->value)->setInitializer(tiInit);
 }
 
@@ -628,11 +626,8 @@
     ClassDeclaration* base = Type::typeinfostaticarray;
     DtoResolveClass(base);
 
-    // get type of typeinfo class
-    const LLStructType* stype = isaStruct(base->type->ir.type->get());
-
     // create the symbol
-    this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
+    ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
 }
 
 void TypeInfoStaticArrayDeclaration::llvmDefine()
@@ -665,9 +660,14 @@
     // length
     sinits.push_back(DtoConstSize_t(tc->dim->toInteger()));
 
-    // create the symbol
-    LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
-    isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
+    // create the inititalizer
+    LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
+
+    // refine global type
+    llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
+
+    // set the initializer
+    isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
 }
 
 void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt)
@@ -686,11 +686,8 @@
     ClassDeclaration* base = Type::typeinfoassociativearray;
     DtoResolveClass(base);
 
-    // get type of typeinfo class
-    const LLStructType* stype = isaStruct(base->type->ir.type->get());
-
     // create the symbol
-    this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
+    ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
 }
 
 void TypeInfoAssociativeArrayDeclaration::llvmDefine()
@@ -702,9 +699,6 @@
     ClassDeclaration* base = Type::typeinfoassociativearray;
     DtoForceConstInitDsymbol(base);
 
-    // get type of typeinfo class
-    const LLStructType* stype = isaStruct(base->type->ir.type->get());
-
     // initializer vector
     std::vector<LLConstant*> sinits;
     // first is always the vtable
@@ -719,17 +713,20 @@
 
     // value typeinfo
     LLConstant* castbase = DtoTypeInfoOf(tc->next, true);
-    assert(castbase->getType() == stype->getElementType(2));
     sinits.push_back(castbase);
 
     // key typeinfo
     castbase = DtoTypeInfoOf(tc->index, true);
-    assert(castbase->getType() == stype->getElementType(3));
     sinits.push_back(castbase);
 
-    // create the symbol
-    LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
-    isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
+    // create the inititalizer
+    LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
+
+    // refine global type
+    llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
+
+    // set the initializer
+    isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
 }
 
 void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt)
@@ -810,10 +807,8 @@
     ClassDeclaration* base = Type::typeinfostruct;
     DtoResolveClass(base);
 
-    const LLStructType* stype = isaStruct(base->type->ir.type->get());
-
     // create the symbol
-    this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
+    ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
 }
 
 void TypeInfoStructDeclaration::llvmDefine()
@@ -1001,9 +996,14 @@
 
 #endif
 
-    // create the symbol
-    LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
-    isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
+    // create the inititalizer
+    LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
+
+    // refine global type
+    llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
+
+    // set the initializer
+    isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
 }
 
 void TypeInfoStructDeclaration::toDt(dt_t **pdt)
@@ -1023,11 +1023,8 @@
     assert(base);
     DtoResolveClass(base);
 
-    // get type of typeinfo class
-    const LLStructType* stype = isaStruct(base->type->ir.type->get());
-
     // create the symbol
-    this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
+    ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true, llvm::GlobalValue::WeakLinkage, NULL, toChars(), gIR->module);
 }
 
 void TypeInfoClassDeclaration::llvmDefine()
@@ -1040,9 +1037,6 @@
     assert(base);
     DtoForceConstInitDsymbol(base);
 
-    // get type of typeinfo class
-    const LLStructType* stype = isaStruct(base->type->ir.type->get());
-
     // initializer vector
     std::vector<LLConstant*> sinits;
     // first is always the vtable
@@ -1058,9 +1052,14 @@
     assert(tc->sym->ir.irStruct->classInfo);
     sinits.push_back(tc->sym->ir.irStruct->classInfo);
 
-    // create the symbol
-    LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
-    isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
+    // create the inititalizer
+    LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
+
+    // refine global type
+    llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
+
+    // set the initializer
+    isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
 }
 
 void TypeInfoClassDeclaration::toDt(dt_t **pdt)
@@ -1080,11 +1079,8 @@
     assert(base);
     DtoResolveClass(base);
 
-    // get type of typeinfo class
-    const LLStructType* stype = isaStruct(base->type->ir.type->get());
-
     // create the symbol
-    this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
+    ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
 }
 
 void TypeInfoInterfaceDeclaration::llvmDefine()
@@ -1114,9 +1110,14 @@
     assert(tc->sym->ir.irStruct->classInfo);
     sinits.push_back(tc->sym->ir.irStruct->classInfo);
 
-    // create the symbol
-    LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
-    isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
+    // create the inititalizer
+    LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
+
+    // refine global type
+    llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
+
+    // set the initializer
+    isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
 }
 
 void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt)
@@ -1136,11 +1137,8 @@
     assert(base);
     DtoResolveClass(base);
 
-    // get type of typeinfo class
-    const LLStructType* stype = isaStruct(base->type->ir.type->get());
-
     // create the symbol
-    this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
+    ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
 }
 
 void TypeInfoTupleDeclaration::llvmDefine()
@@ -1199,9 +1197,14 @@
     LLConstant* slice = DtoConstSlice(DtoConstSize_t(dim), arrptr);
     sinits.push_back(slice);
 
-    // create the symbol
-    LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
-    isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
+    // create the inititalizer
+    LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
+
+    // refine global type
+    llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
+
+    // set the initializer
+    isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
 }
 
 void TypeInfoTupleDeclaration::toDt(dt_t **pdt)
--- a/ir/irstruct.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/ir/irstruct.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -3,54 +3,57 @@
 #include "mtype.h"
 #include "aggregate.h"
 #include "declaration.h"
+#include "init.h"
 
 #include "ir/irstruct.h"
 #include "gen/irstate.h"
 #include "gen/tollvm.h"
+#include "gen/logger.h"
 
 IrInterface::IrInterface(BaseClass* b)
+:   vtblInitTy(llvm::OpaqueType::get())
 {
     base = b;
     decl = b->base;
-    vtblTy = NULL;
     vtblInit = NULL;
     vtbl = NULL;
     infoTy = NULL;
     infoInit = NULL;
     info = NULL;
 
-    index = -1;
-}
-
-IrInterface::~IrInterface()
-{
-    delete vtblTy;
+    index = 0;
 }
 
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
-IrStruct::IrStruct(Type* t)
- : recty((t->ir.type) ? *t->ir.type : llvm::OpaqueType::get())
+IrStruct::IrStruct(AggregateDeclaration* aggr)
+:   initOpaque(llvm::OpaqueType::get()),
+    classInfoOpaque(llvm::OpaqueType::get()),
+    vtblTy(llvm::OpaqueType::get()),
+    vtblInitTy(llvm::OpaqueType::get())
 {
-    type = t;
+    aggrdecl = aggr;
+    defaultFound = false;
+    anon = NULL;
+    index = 0;
+
+    type = aggr->type;
     defined = false;
     constinited = false;
-    interfaceInfosTy = NULL;
+
     interfaceInfos = NULL;
-
     vtbl = NULL;
     constVtbl = NULL;
+
     init = NULL;
     constInit = NULL;
+
     classInfo = NULL;
     constClassInfo = NULL;
-    hasUnions = false;
-    dunion = NULL;
-
-    classDeclared = false;
-    classDefined = false;
+    classInfoDeclared = false;
+    classInfoDefined = false;
 
     packed = false;
 
@@ -61,14 +64,294 @@
 {
 }
 
-void IrStruct::addField(VarDeclaration* v)
+//////////////////////////////////////////
+
+void IrStruct::pushAnon(bool isunion)
+{
+    anon = new Anon(isunion, anon);
+}
+
+//////////////////////////////////////////
+
+void IrStruct::popAnon()
+{
+    assert(anon);
+
+    const LLType* BT;
+
+    // get the anon type
+    if (anon->isunion)
+    {
+        // get biggest type in block
+        const LLType* biggest = getBiggestType(&anon->types[0], anon->types.size());
+        std::vector<const LLType*> vec(1, biggest);
+        BT = LLStructType::get(vec, aggrdecl->ir.irStruct->packed);
+    }
+    else
+    {
+        // build a struct from the types
+        BT = LLStructType::get(anon->types, aggrdecl->ir.irStruct->packed);
+    }
+
+    // pop anon
+    Anon* tmp = anon;
+    anon = anon->parent;
+    delete tmp;
+
+    // is there a parent anon?
+    if (anon)
+    {
+        // make sure type gets pushed in the anon, not the main
+        anon->types.push_back(BT);
+        // index is only manipulated at the top level, anons use raw offsets
+    }
+    // no parent anon, finally add to aggrdecl
+    else
+    {
+        types.push_back(BT);
+        // only advance to next position if main is not a union
+        if (!aggrdecl->isUnionDeclaration())
+        {
+            index++;
+        }
+    }
+}
+
+//////////////////////////////////////////
+
+void addZeros(std::vector<const llvm::Type*>& inits, size_t pos, size_t offset);
+
+void IrStruct::addVar(VarDeclaration * var)
 {
-    // might already have its irField, as classes derive each other without getting copies of the VarDeclaration
-    if (!v->ir.irField)
+    TypeVector* tvec = &types;
+    if (anon)
+    {
+        // make sure type gets pushed in the anon, not the main
+        tvec = &anon->types;
+
+        // set but don't advance index
+        var->ir.irField->index = index;
+
+        // set offset in bytes from start of anon block
+        var->ir.irField->unionOffset = var->offset - var->offset2;
+    }
+    else if (aggrdecl->isUnionDeclaration())
+    {
+        // set but don't advance index
+        var->ir.irField->index = index;
+    }
+    else
+    {
+        // set and advance index
+        var->ir.irField->index = index++;
+    }
+
+    // add type
+    tvec->push_back(DtoType(var->type));
+
+    // add var
+    varDecls.push_back(var);
+}
+
+//////////////////////////////////////////
+
+const LLType* IrStruct::build()
+{
+    // if types is empty, add a byte
+    if (types.empty())
+    {
+        types.push_back(LLType::Int8Ty);
+    }
+
+    // union type
+    if (aggrdecl->isUnionDeclaration())
+    {
+        const LLType* biggest = getBiggestType(&types[0], types.size());
+        std::vector<const LLType*> vec(1, biggest);
+        return LLStructType::get(vec, aggrdecl->ir.irStruct->packed);
+    }
+    // struct/class type
+    else
+    {
+        return LLStructType::get(types, aggrdecl->ir.irStruct->packed);
+    }
+}
+
+void addZeros(std::vector<const llvm::Type*>& inits, size_t pos, size_t offset)
+{
+    assert(offset > pos);
+    size_t diff = offset - pos;
+
+    size_t sz;
+
+    do
     {
-        assert(!v->ir.isSet());
-        v->ir.irField = new IrField(v);
+        if (pos%8 == 0 && diff >= 8)
+            sz = 8;
+        else if (pos%4 == 0 && diff >= 4)
+            sz = 4;
+        else if (pos%2 == 0 && diff >= 2)
+            sz = 2;
+        else // if (pos % 1 == 0)
+            sz = 1;
+        inits.push_back(LLIntegerType::get(sz*8));
+        pos += sz;
+        diff -= sz;
+    } while (pos < offset);
+
+    assert(pos == offset);
+}
+
+void addZeros(std::vector<llvm::Constant*>& inits, size_t pos, size_t offset)
+{
+    assert(offset > pos);
+    size_t diff = offset - pos;
+
+    size_t sz;
+
+    do
+    {
+        if (pos%8 == 0 && diff >= 8)
+            sz = 8;
+        else if (pos%4 == 0 && diff >= 4)
+            sz = 4;
+        else if (pos%2 == 0 && diff >= 2)
+            sz = 2;
+        else // if (pos % 1 == 0)
+            sz = 1;
+        inits.push_back(LLConstant::getNullValue(LLIntegerType::get(sz*8)));
+        pos += sz;
+        diff -= sz;
+    } while (pos < offset);
+
+    assert(pos == offset);
+}
+
+// FIXME: body is exact copy of above
+void addZeros(std::vector<llvm::Value*>& inits, size_t pos, size_t offset)
+{
+    assert(offset > pos);
+    size_t diff = offset - pos;
+
+    size_t sz;
+
+    do
+    {
+        if (pos%8 == 0 && diff >= 8)
+            sz = 8;
+        else if (pos%4 == 0 && diff >= 4)
+            sz = 4;
+        else if (pos%2 == 0 && diff >= 2)
+            sz = 2;
+        else // if (pos % 1 == 0)
+            sz = 1;
+        inits.push_back(LLConstant::getNullValue(LLIntegerType::get(sz*8)));
+        pos += sz;
+        diff -= sz;
+    } while (pos < offset);
+
+    assert(pos == offset);
+}
+
+void IrStruct::buildDefaultConstInit(std::vector<llvm::Constant*>& inits)
+{
+    assert(!defaultFound);
+    defaultFound = true;
+
+    const llvm::StructType* structtype = isaStruct(aggrdecl->type->ir.type->get());
+    Logger::cout() << "struct type: " << *structtype << '\n';
+
+    size_t lastoffset = 0;
+    size_t lastsize = 0;
+
+    {
+        Logger::println("Find the default fields");
+        LOG_SCOPE;
+
+        // go through all vars and find the ones that contribute to the default
+        size_t nvars = varDecls.size();
+        for (size_t i=0; i<nvars; i++)
+        {
+            VarDeclaration* var = varDecls[i];
+
+            Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset);
+
+            // only add vars that don't overlap
+            size_t offset = var->offset;
+            size_t size = var->type->size();
+            if (offset >= lastoffset+lastsize)
+            {
+                Logger::println("  added");
+                lastoffset = offset;
+                lastsize = size;
+                defVars.push_back(var);
+            }
+        }
     }
-    const LLType* _type = DtoType(v->type);
-    offsets.insert(std::make_pair(v->offset, IrStruct::Offset(v, _type)));
+
+    {
+        Logger::println("Build the default initializer");
+        LOG_SCOPE;
+
+        lastoffset = 0;
+        lastsize = 0;
+
+        // go through the default vars and build the default constant initializer
+        // adding zeros along the way to live up to alignment expectations
+        size_t nvars = defVars.size();
+        for (size_t i=0; i<nvars; i++)
+        {
+            VarDeclaration* var = defVars[i];
+
+            Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset);
+
+            // get offset and size
+            size_t offset = var->offset;
+            size_t size = var->type->size();
+
+            // is there space in between last last offset and this one?
+            // if so, fill it with zeros
+            if (offset > lastoffset+lastsize)
+            {
+                size_t pos = lastoffset + lastsize;
+                addZeros(inits, pos, offset);
+            }
+
+            // add the field
+            assert(var->ir.irField->constInit);
+            inits.push_back(var->ir.irField->constInit);
+
+            lastoffset = offset;
+            lastsize = var->type->size();
+        }
+
+        // there might still be padding after the last one, make sure that is zeroed as well
+        // is there space in between last last offset and this one?
+        size_t structsize = getABITypeSize(structtype);
+
+        if (structsize > lastoffset+lastsize)
+        {
+            size_t pos = lastoffset + lastsize;
+            addZeros(inits, pos, structsize);
+        }
+    }
 }
+
+LLConstant* IrStruct::buildDefaultConstInit()
+{
+    // doesn't work for classes, they add stuff before and maybe after data fields
+    assert(!aggrdecl->isClassDeclaration());
+
+    // initializer llvm constant list
+    std::vector<LLConstant*> inits;
+
+    // just start with an empty list
+    buildDefaultConstInit(inits);
+
+    // build the constant
+    // note that the type matches the initializer, not the aggregate in cases with unions
+    LLConstant* c = LLConstantStruct::get(inits, aggrdecl->ir.irStruct->packed);
+    Logger::cout() << "llvm constant: " << *c << '\n';
+//     assert(0);
+    return c;
+}
--- a/ir/irstruct.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/ir/irstruct.h	Sat Nov 29 21:25:43 2008 +0100
@@ -6,86 +6,168 @@
 #include <vector>
 #include <map>
 
-struct IrInterface : IrBase
-{
-    BaseClass* base;
-    ClassDeclaration* decl;
-
-    llvm::PATypeHolder* vtblTy;
-    LLConstant* vtblInit;
-    LLGlobalVariable* vtbl;
-
-    const LLStructType* infoTy;
-    LLConstantStruct* infoInit;
-    LLConstant* info;
-
-    int index;
-
-    IrInterface(BaseClass* b);
-    ~IrInterface();
-};
+struct IrInterface;
 
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
 // represents a struct or class
+// it is used during codegen to hold all the vital info we need
 struct IrStruct : IrBase
 {
-    struct Offset
-    {
-        VarDeclaration* var;
-        const LLType* type;
-        LLConstant* init;
+    /////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////
 
-        Offset(VarDeclaration* v, const LLType* ty)
-        : var(v), type(ty), init(NULL) {}
-    };
+    typedef std::vector<VarDeclaration*> VarDeclVector;
 
-    typedef std::multimap<unsigned, Offset> OffsetMap;
-    typedef std::vector<VarDeclaration*> VarDeclVector;
-    typedef std::map<ClassDeclaration*, IrInterface*> InterfaceMap;
-    typedef InterfaceMap::iterator InterfaceMapIter;
+    typedef std::map<ClassDeclaration*, IrInterface*>   InterfaceMap;
+    typedef InterfaceMap::iterator                      InterfaceMapIter;
+
     typedef std::vector<IrInterface*> InterfaceVector;
     typedef InterfaceVector::iterator InterfaceVectorIter;
 
-public:
-    IrStruct(Type*);
+    // vector of LLVM types
+    typedef std::vector<const llvm::Type*> TypeVector;
+
+    /////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////
+
+    // Anon represents an anonymous struct union block inside an aggregate
+    // during LLVM type construction.
+    struct Anon
+    {
+        bool isunion;
+        Anon* parent;
+
+        TypeVector types;
+
+        Anon(bool IsUnion, Anon* par) : isunion(IsUnion), parent(par) {}
+    };
+
+    /////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////
+
+    /// ctor
+    IrStruct(AggregateDeclaration* agg);
+
+    /// dtor
     virtual ~IrStruct();
 
-    void addField(VarDeclaration* v);
+    /////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////
+
+    /// push an anonymous struct/union
+    void pushAnon(bool isunion);
+
+    /// pops an anonymous struct/union
+    void popAnon();
+
+    /// adds field
+    void addVar(VarDeclaration* var);
+
+    /////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////
+
+    /// build the aggr type
+    const LLType* build();
+
+    /// put the aggr initializers in a vector
+    void buildDefaultConstInit(std::vector<llvm::Constant*>& inits);
+
+    /// ditto - but also builds the constant struct, for convenience
+    LLConstant* buildDefaultConstInit();
 
+    /////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////
+
+    // the D aggregate
+    AggregateDeclaration* aggrdecl;
+
+    // vector of VarDeclarations in this aggregate
+    VarDeclVector varDecls;
+
+    // vector of VarDeclarations that contribute to the default initializer
+    VarDeclVector defVars;
+
+    // true if the default initializer has been built
+    bool defaultFound;
+
+    // top element
+    Anon* anon;
+
+    // toplevel types in this aggr
+    TypeVector types;
+
+    // current index
+    // always the same as types.size()
+    size_t index; 
+
+    // aggregate D type
     Type* type;
-    llvm::PATypeHolder recty;
-    OffsetMap offsets;
-    VarDeclVector defaultFields;
+
+    // class vtable type
+    llvm::PATypeHolder vtblTy;
+    llvm::PATypeHolder vtblInitTy;
 
+    // initializer type opaque (type of global matches initializer, not formal type)
+    llvm::PATypeHolder initOpaque;
+    llvm::PATypeHolder classInfoOpaque;
+
+    // map/vector of interfaces implemented
     InterfaceMap interfaceMap;
     InterfaceVector interfaceVec;
-    const llvm::ArrayType* interfaceInfosTy;
+
+    // interface info array global
     LLGlobalVariable* interfaceInfos;
 
+    // ...
     bool defined;
     bool constinited;
 
+    // vtbl global and initializer
     LLGlobalVariable* vtbl;
-#if OPAQUE_VTBLS
     LLConstant* constVtbl;
-#else
-    LLConstantStruct* constVtbl;
-#endif
+
+    // static initializers global and constant
     LLGlobalVariable* init;
     LLConstant* constInit;
+
+    // classinfo global and initializer constant
     LLGlobalVariable* classInfo;
     LLConstant* constClassInfo;
-    bool hasUnions;
-    DUnion* dunion;
-    bool classDeclared;
-    bool classDefined;
+    bool classInfoDeclared;
+    bool classInfoDefined;
 
-    bool packed; // true for: align(1) struct S { ... }
+    // align(1) struct S { ... }
+    bool packed;
 
+    // dwarf composite global
     LLGlobalVariable* dwarfComposite;
 };
 
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+// represents interface implemented by a class
+struct IrInterface : IrBase
+{
+    BaseClass* base;
+    ClassDeclaration* decl;
+
+    llvm::PATypeHolder vtblInitTy;
+
+    LLConstant* vtblInit;
+    LLGlobalVariable* vtbl;
+
+    const LLStructType* infoTy;
+    LLConstant* infoInit;
+    LLConstant* info;
+
+    size_t index;
+
+    IrInterface(BaseClass* b);
+};
+
 #endif
--- a/ir/irtype.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/ir/irtype.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -21,9 +21,6 @@
 {
     assert(list.insert(this).second);
     type = s.type;
-#if OPAQUE_VTBLS
-    vtblType = s.type;
-#endif
 }
 
 IrType::~IrType()
@@ -34,7 +31,4 @@
 void IrType::reset()
 {
     type = NULL;
-#if OPAQUE_VTBLS
-    vtblType = NULL;
-#endif
 }
--- a/ir/irtype.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/ir/irtype.h	Sat Nov 29 21:25:43 2008 +0100
@@ -21,7 +21,6 @@
     void reset();
 
     llvm::PATypeHolder* type;
-    llvm::PATypeHolder* vtblType;
 };
 
 #endif
--- a/ir/irvar.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/ir/irvar.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -1,4 +1,4 @@
-#include "llvm/DerivedTypes.h"
+#include "gen/llvm.h"
 #include "declaration.h"
 #include "ir/irvar.h"
 
@@ -38,8 +38,8 @@
 
 IrField::IrField(VarDeclaration* v) : IrVar(v)
 {
-    index = -1;
-    indexOffset = 0;
+    index = 0;
+    unionOffset = 0;
     constInit = NULL;
 }
 
--- a/ir/irvar.h	Sat Nov 29 12:28:10 2008 +0100
+++ b/ir/irvar.h	Sat Nov 29 21:25:43 2008 +0100
@@ -34,8 +34,9 @@
 {
     IrField(VarDeclaration* v);
 
-    int index;
-    size_t indexOffset;
+    unsigned index;
+    unsigned unionOffset;
+
     llvm::Constant* constInit;
 };
 
--- a/llvmdc.kdevelop	Sat Nov 29 12:28:10 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,684 +0,0 @@
-<?xml version = '1.0'?>
-<kdevelop>
-  <general>
-    <author>Tomas Lindquist Olsen</author>
-    <email>tomas.l.olsen@gmail.com</email>
-    <version>0.1</version>
-    <projectmanagement>KDevCustomProject</projectmanagement>
-    <primarylanguage>C++</primarylanguage>
-    <keywords>
-      <keyword>C++</keyword>
-      <keyword>Code</keyword>
-    </keywords>
-    <ignoreparts/>
-    <projectname>llvmdc</projectname>
-    <projectdirectory>.</projectdirectory>
-    <absoluteprojectpath>false</absoluteprojectpath>
-    <description/>
-    <defaultencoding/>
-    <versioncontrol>kdevsubversion</versioncontrol>
-  </general>
-  <kdevautoproject>
-    <general/>
-    <run/>
-    <configurations>
-      <optimized>
-        <builddir>optimized</builddir>
-        <ccompiler>kdevgccoptions</ccompiler>
-        <cxxcompiler>kdevgppoptions</cxxcompiler>
-        <f77compiler>kdevg77options</f77compiler>
-        <cxxflags>-O2 -g0</cxxflags>
-      </optimized>
-      <debug>
-        <configargs>--enable-debug=full</configargs>
-        <builddir>debug</builddir>
-        <ccompiler>kdevgccoptions</ccompiler>
-        <cxxcompiler>kdevgppoptions</cxxcompiler>
-        <f77compiler>kdevg77options</f77compiler>
-        <cxxflags>-O0 -g3</cxxflags>
-      </debug>
-    </configurations>
-  </kdevautoproject>
-  <kdevdoctreeview>
-    <ignoretocs>
-      <toc>ada</toc>
-      <toc>ada_bugs_gcc</toc>
-      <toc>bash</toc>
-      <toc>bash_bugs</toc>
-      <toc>clanlib</toc>
-      <toc>w3c-dom-level2-html</toc>
-      <toc>fortran_bugs_gcc</toc>
-      <toc>gnome1</toc>
-      <toc>gnustep</toc>
-      <toc>gtk</toc>
-      <toc>gtk_bugs</toc>
-      <toc>haskell</toc>
-      <toc>haskell_bugs_ghc</toc>
-      <toc>java_bugs_gcc</toc>
-      <toc>java_bugs_sun</toc>
-      <toc>kde2book</toc>
-      <toc>opengl</toc>
-      <toc>pascal_bugs_fp</toc>
-      <toc>php</toc>
-      <toc>php_bugs</toc>
-      <toc>perl</toc>
-      <toc>perl_bugs</toc>
-      <toc>python</toc>
-      <toc>python_bugs</toc>
-      <toc>qt-kdev3</toc>
-      <toc>ruby</toc>
-      <toc>ruby_bugs</toc>
-      <toc>sdl</toc>
-      <toc>w3c-svg</toc>
-      <toc>sw</toc>
-      <toc>w3c-uaag10</toc>
-      <toc>wxwidgets_bugs</toc>
-    </ignoretocs>
-    <ignoreqt_xml>
-      <toc>Guide to the Qt Translation Tools</toc>
-      <toc>Qt Assistant Manual</toc>
-      <toc>Qt Designer Manual</toc>
-      <toc>Qt Reference Documentation</toc>
-      <toc>qmake User Guide</toc>
-    </ignoreqt_xml>
-    <ignoredoxygen>
-      <toc>KDE Libraries (Doxygen)</toc>
-    </ignoredoxygen>
-  </kdevdoctreeview>
-  <kdevfilecreate>
-    <filetypes/>
-    <useglobaltypes>
-      <type ext="cpp" />
-      <type ext="h" />
-    </useglobaltypes>
-  </kdevfilecreate>
-  <kdevfileview>
-    <groups>
-      <group pattern="*.h" name="Header files" />
-      <group pattern="*.cpp" name="Source files" />
-      <hidenonprojectfiles>true</hidenonprojectfiles>
-      <hidenonlocation>false</hidenonlocation>
-    </groups>
-    <tree>
-      <hidepatterns>*.bc</hidepatterns>
-      <hidenonprojectfiles>false</hidenonprojectfiles>
-      <showvcsfields>false</showvcsfields>
-    </tree>
-  </kdevfileview>
-  <kdevdocumentation>
-    <projectdoc>
-      <docsystem>Doxygen Documentation Collection</docsystem>
-      <docurl>llvmdc.tag</docurl>
-    </projectdoc>
-  </kdevdocumentation>
-  <substmap>
-    <APPNAME>llvmdc</APPNAME>
-    <APPNAMELC>llvmdc</APPNAMELC>
-    <APPNAMESC>Llvmdc</APPNAMESC>
-    <APPNAMEUC>LLVMDC</APPNAMEUC>
-    <AUTHOR>Tomas Lindquist Olsen</AUTHOR>
-    <EMAIL>tomas.l.olsen@gmail.com</EMAIL>
-    <LICENSE>GPL</LICENSE>
-    <LICENSEFILE>COPYING</LICENSEFILE>
-    <VERSION>0.1</VERSION>
-    <YEAR>2007</YEAR>
-    <dest>/home/tomas/projects/llvmdc</dest>
-  </substmap>
-  <kdevcppsupport>
-    <qt>
-      <used>false</used>
-      <version>3</version>
-      <includestyle>3</includestyle>
-      <root>/opt/qt</root>
-      <designerintegration>EmbeddedKDevDesigner</designerintegration>
-      <qmake>/opt/qt/bin/qmake</qmake>
-      <designer>/opt/qt/bin/designer</designer>
-      <designerpluginpaths/>
-    </qt>
-    <codecompletion>
-      <automaticCodeCompletion>false</automaticCodeCompletion>
-      <automaticArgumentsHint>true</automaticArgumentsHint>
-      <automaticHeaderCompletion>true</automaticHeaderCompletion>
-      <codeCompletionDelay>250</codeCompletionDelay>
-      <argumentsHintDelay>400</argumentsHintDelay>
-      <headerCompletionDelay>250</headerCompletionDelay>
-      <showOnlyAccessibleItems>false</showOnlyAccessibleItems>
-      <completionBoxItemOrder>0</completionBoxItemOrder>
-      <howEvaluationContextMenu>true</howEvaluationContextMenu>
-      <showCommentWithArgumentHint>true</showCommentWithArgumentHint>
-      <statusBarTypeEvaluation>false</statusBarTypeEvaluation>
-      <namespaceAliases>std=_GLIBCXX_STD;__gnu_cxx=std</namespaceAliases>
-      <processPrimaryTypes>true</processPrimaryTypes>
-      <processFunctionArguments>false</processFunctionArguments>
-      <preProcessAllHeaders>true</preProcessAllHeaders>
-      <parseMissingHeadersExperimental>false</parseMissingHeadersExperimental>
-      <resolveIncludePathsUsingMakeExperimental>false</resolveIncludePathsUsingMakeExperimental>
-      <alwaysParseInBackground>true</alwaysParseInBackground>
-      <usePermanentCaching>true</usePermanentCaching>
-      <alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
-      <includePaths>.;</includePaths>
-    </codecompletion>
-    <creategettersetter>
-      <prefixGet/>
-      <prefixSet>set</prefixSet>
-      <prefixVariable>m_,_</prefixVariable>
-      <parameterName>theValue</parameterName>
-      <inlineGet>true</inlineGet>
-      <inlineSet>true</inlineSet>
-    </creategettersetter>
-    <splitheadersource>
-      <enabled>false</enabled>
-      <synchronize>true</synchronize>
-      <orientation>Vertical</orientation>
-    </splitheadersource>
-    <references/>
-  </kdevcppsupport>
-  <kdevcustomproject>
-    <run>
-      <directoryradio>executable</directoryradio>
-      <mainprogram>/home/tomas/kdevprojects/llvmdc</mainprogram>
-      <programargs/>
-      <globaldebugarguments/>
-      <globalcwd>/home/tomas/kdevprojects/llvmdc</globalcwd>
-      <useglobalprogram>false</useglobalprogram>
-      <terminal>false</terminal>
-      <autocompile>false</autocompile>
-      <autoinstall>false</autoinstall>
-      <autokdesu>false</autokdesu>
-      <envvars/>
-    </run>
-    <filetypes>
-      <filetype>*.h</filetype>
-      <filetype>*.c</filetype>
-      <filetype>*.cpp</filetype>
-      <filetype>build.sh</filetype>
-    </filetypes>
-    <blacklist>
-      <path>demos</path>
-      <path>demos/ray.cpp</path>
-      <path>dmdorig</path>
-      <path>dmdorig/dmd</path>
-      <path>dmdorig/dmd/access.c</path>
-      <path>dmdorig/dmd/aggregate.h</path>
-      <path>dmdorig/dmd/array.c</path>
-      <path>dmdorig/dmd/arraytypes.h</path>
-      <path>dmdorig/dmd/attrib.c</path>
-      <path>dmdorig/dmd/attrib.h</path>
-      <path>dmdorig/dmd/bit.c</path>
-      <path>dmdorig/dmd/cast.c</path>
-      <path>dmdorig/dmd/class.c</path>
-      <path>dmdorig/dmd/complex_t.h</path>
-      <path>dmdorig/dmd/cond.c</path>
-      <path>dmdorig/dmd/cond.h</path>
-      <path>dmdorig/dmd/constfold.c</path>
-      <path>dmdorig/dmd/dchar.c</path>
-      <path>dmdorig/dmd/dchar.h</path>
-      <path>dmdorig/dmd/declaration.c</path>
-      <path>dmdorig/dmd/declaration.h</path>
-      <path>dmdorig/dmd/delegatize.c</path>
-      <path>dmdorig/dmd/doc.c</path>
-      <path>dmdorig/dmd/doc.h</path>
-      <path>dmdorig/dmd/dsymbol.c</path>
-      <path>dmdorig/dmd/dsymbol.h</path>
-      <path>dmdorig/dmd/dump.c</path>
-      <path>dmdorig/dmd/entity.c</path>
-      <path>dmdorig/dmd/enum.c</path>
-      <path>dmdorig/dmd/enum.h</path>
-      <path>dmdorig/dmd/expression.c</path>
-      <path>dmdorig/dmd/expression.h</path>
-      <path>dmdorig/dmd/func.c</path>
-      <path>dmdorig/dmd/gnuc.c</path>
-      <path>dmdorig/dmd/gnuc.h</path>
-      <path>dmdorig/dmd/hdrgen.c</path>
-      <path>dmdorig/dmd/hdrgen.h</path>
-      <path>dmdorig/dmd/html.c</path>
-      <path>dmdorig/dmd/html.h</path>
-      <path>dmdorig/dmd/identifier.c</path>
-      <path>dmdorig/dmd/identifier.h</path>
-      <path>dmdorig/dmd/idgen.c</path>
-      <path>dmdorig/dmd/impcnvgen.c</path>
-      <path>dmdorig/dmd/import.c</path>
-      <path>dmdorig/dmd/import.h</path>
-      <path>dmdorig/dmd/inifile.c</path>
-      <path>dmdorig/dmd/init.c</path>
-      <path>dmdorig/dmd/init.h</path>
-      <path>dmdorig/dmd/inline.c</path>
-      <path>dmdorig/dmd/interpret.c</path>
-      <path>dmdorig/dmd/lexer.c</path>
-      <path>dmdorig/dmd/lexer.h</path>
-      <path>dmdorig/dmd/link.c</path>
-      <path>dmdorig/dmd/lstring.c</path>
-      <path>dmdorig/dmd/lstring.h</path>
-      <path>dmdorig/dmd/macro.c</path>
-      <path>dmdorig/dmd/macro.h</path>
-      <path>dmdorig/dmd/mangle.c</path>
-      <path>dmdorig/dmd/mars.c</path>
-      <path>dmdorig/dmd/mars.h</path>
-      <path>dmdorig/dmd/mem.c</path>
-      <path>dmdorig/dmd/mem.h</path>
-      <path>dmdorig/dmd/module.c</path>
-      <path>dmdorig/dmd/module.h</path>
-      <path>dmdorig/dmd/mtype.c</path>
-      <path>dmdorig/dmd/mtype.h</path>
-      <path>dmdorig/dmd/opover.c</path>
-      <path>dmdorig/dmd/optimize.c</path>
-      <path>dmdorig/dmd/parse.c</path>
-      <path>dmdorig/dmd/parse.h</path>
-      <path>dmdorig/dmd/port.h</path>
-      <path>dmdorig/dmd/root.c</path>
-      <path>dmdorig/dmd/root.h</path>
-      <path>dmdorig/dmd/scope.c</path>
-      <path>dmdorig/dmd/scope.h</path>
-      <path>dmdorig/dmd/statement.c</path>
-      <path>dmdorig/dmd/statement.h</path>
-      <path>dmdorig/dmd/staticassert.c</path>
-      <path>dmdorig/dmd/staticassert.h</path>
-      <path>dmdorig/dmd/stringtable.c</path>
-      <path>dmdorig/dmd/stringtable.h</path>
-      <path>dmdorig/dmd/struct.c</path>
-      <path>dmdorig/dmd/template.c</path>
-      <path>dmdorig/dmd/template.h</path>
-      <path>dmdorig/dmd/tocsym.c</path>
-      <path>dmdorig/dmd/todt.c</path>
-      <path>dmdorig/dmd/toir.c</path>
-      <path>dmdorig/dmd/toir.h</path>
-      <path>dmdorig/dmd/toobj.c</path>
-      <path>dmdorig/dmd/total.h</path>
-      <path>dmdorig/dmd/typinf.c</path>
-      <path>dmdorig/dmd/unialpha.c</path>
-      <path>dmdorig/dmd/utf.c</path>
-      <path>dmdorig/dmd/utf.h</path>
-      <path>dmdorig/dmd/version.c</path>
-      <path>dmdorig/dmd/version.h</path>
-      <path>dmdorig/phobos</path>
-      <path>dmdorig/phobos/errno.c</path>
-      <path>dmdorig/phobos/etc</path>
-      <path>dmdorig/phobos/etc/c</path>
-      <path>dmdorig/phobos/etc/c/zlib</path>
-      <path>dmdorig/phobos/etc/c/zlib/adler32.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/compress.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/crc32.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/crc32.h</path>
-      <path>dmdorig/phobos/etc/c/zlib/deflate.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/deflate.h</path>
-      <path>dmdorig/phobos/etc/c/zlib/example.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/gzio.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/infback.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/inffast.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/inffast.h</path>
-      <path>dmdorig/phobos/etc/c/zlib/inffixed.h</path>
-      <path>dmdorig/phobos/etc/c/zlib/inflate.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/inflate.h</path>
-      <path>dmdorig/phobos/etc/c/zlib/inftrees.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/inftrees.h</path>
-      <path>dmdorig/phobos/etc/c/zlib/minigzip.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/trees.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/trees.h</path>
-      <path>dmdorig/phobos/etc/c/zlib/uncompr.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/zconf.h</path>
-      <path>dmdorig/phobos/etc/c/zlib/zconf.in.h</path>
-      <path>dmdorig/phobos/etc/c/zlib/zlib.h</path>
-      <path>dmdorig/phobos/etc/c/zlib/zutil.c</path>
-      <path>dmdorig/phobos/etc/c/zlib/zutil.h</path>
-      <path>dmdorig/phobos/internal</path>
-      <path>dmdorig/phobos/internal/complex.c</path>
-      <path>dmdorig/phobos/internal/critical.c</path>
-      <path>dmdorig/phobos/internal/deh.c</path>
-      <path>dmdorig/phobos/internal/mars.h</path>
-      <path>dmdorig/phobos/internal/monitor.c</path>
-      <path>lphobos</path>
-      <path>lphobos/build.sh</path>
-      <path>suite</path>
-      <path>suite/dwarfdebug</path>
-      <path>suite/dwarfdebug/dwarf1</path>
-      <path>suite/dwarfdebug/dwarf1/build.sh</path>
-      <path>suite/dwarfdebug/dwarf2</path>
-      <path>suite/dwarfdebug/dwarf2/build.sh</path>
-      <path>tango</path>
-      <path>tango/lib</path>
-      <path>tango/lib/common</path>
-      <path>tango/lib/common/tango</path>
-      <path>tango/lib/common/tango/stdc</path>
-      <path>tango/lib/common/tango/stdc/wrap.c</path>
-      <path>tango/lib/compiler</path>
-      <path>tango/lib/compiler/llvmdc</path>
-      <path>tango/lib/compiler/llvmdc/critical.c</path>
-      <path>tango/lib/compiler/llvmdc/mars.h</path>
-      <path>tango/lib/compiler/llvmdc/monitor.c</path>
-      <path>tests</path>
-      <path>tests/dstress</path>
-      <path>tests/dstress/benchmark</path>
-      <path>tests/dstress/benchmark/ackermann</path>
-      <path>tests/dstress/benchmark/ackermann/ackermann_c.c</path>
-      <path>tests/dstress/benchmark/cowell-shah</path>
-      <path>tests/dstress/benchmark/cowell-shah/benchmark.c</path>
-      <path>tests/dstress/benchmark/known_gcc_problems</path>
-      <path>tests/dstress/benchmark/known_gcc_problems/common_subexpressions_01_c.c</path>
-      <path>tests/dstress/benchmark/oopack</path>
-      <path>tests/dstress/benchmark/oopack/oopack_v1p8_cpp.cpp</path>
-      <path>tests/dstress/crashRun.c</path>
-      <path>tests/dstress/dstress.c</path>
-      <path>tests/dstress/extract__.c</path>
-      <path>tests/dstress/ifeq__.c</path>
-      <path>tests/dstress/return__.c</path>
-      <path>e2ir.c</path>
-      <path>tango-llvmdc</path>
-      <path>tango-llvmdc/lib</path>
-      <path>tango-llvmdc/lib/common</path>
-      <path>tango-llvmdc/lib/common/tango</path>
-      <path>tango-llvmdc/lib/common/tango/stdc</path>
-      <path>tango-llvmdc/lib/common/tango/stdc/wrap.c</path>
-      <path>tango-llvmdc/lib/compiler</path>
-      <path>tango-llvmdc/lib/compiler/dmd</path>
-      <path>tango-llvmdc/lib/compiler/dmd/complex.c</path>
-      <path>tango-llvmdc/lib/compiler/dmd/critical.c</path>
-      <path>tango-llvmdc/lib/compiler/dmd/deh.c</path>
-      <path>tango-llvmdc/lib/compiler/dmd/mars.h</path>
-      <path>tango-llvmdc/lib/compiler/dmd/monitor.c</path>
-      <path>tango-llvmdc/lib/compiler/gdc</path>
-      <path>tango-llvmdc/lib/compiler/gdc/config</path>
-      <path>tango-llvmdc/lib/compiler/gdc/config/gen_config1.c</path>
-      <path>tango-llvmdc/lib/compiler/gdc/config/gen_math.c</path>
-      <path>tango-llvmdc/lib/compiler/gdc/config/gen_unix.c</path>
-      <path>tango-llvmdc/lib/compiler/gdc/config/makestruct.h</path>
-      <path>tango-llvmdc/lib/compiler/gdc/critical.c</path>
-      <path>tango-llvmdc/lib/compiler/gdc/deh.c</path>
-      <path>tango-llvmdc/lib/compiler/gdc/gcc</path>
-      <path>tango-llvmdc/lib/compiler/gdc/gcc/aix_float.h</path>
-      <path>tango-llvmdc/lib/compiler/gdc/gcc/cbridge_fdset.c</path>
-      <path>tango-llvmdc/lib/compiler/gdc/gcc/cbridge_math.c</path>
-      <path>tango-llvmdc/lib/compiler/gdc/gcc/cbridge_stdio.c</path>
-      <path>tango-llvmdc/lib/compiler/gdc/gcc/cbridge_time.c</path>
-      <path>tango-llvmdc/lib/compiler/gdc/mars.h</path>
-      <path>tango-llvmdc/lib/compiler/gdc/memory_dyld.c</path>
-      <path>tango-llvmdc/lib/compiler/gdc/memory_freebsd.c</path>
-      <path>tango-llvmdc/lib/compiler/gdc/monitor.c</path>
-      <path>tango-llvmdc/lib/compiler/llvmdc</path>
-      <path>tango-llvmdc/lib/compiler/llvmdc/critical.c</path>
-      <path>tango-llvmdc/lib/compiler/llvmdc/mars.h</path>
-      <path>tango-llvmdc/lib/compiler/llvmdc/monitor.c</path>
-      <path>tango-llvmdc/patches</path>
-      <path>tango-llvmdc/patches/proposals</path>
-      <path>tango-llvmdc/patches/proposals/integrated_locks</path>
-      <path>tango-llvmdc/patches/proposals/integrated_locks/lib</path>
-      <path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler</path>
-      <path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/dmd</path>
-      <path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/dmd/monitor.c</path>
-      <path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/gdc</path>
-      <path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/gdc/monitor.c</path>
-      <path>runtime/build.sh</path>
-      <path>runtime/internal</path>
-      <path>runtime/internal/critical.c</path>
-      <path>runtime/internal/mars.h</path>
-      <path>runtime/internal/monitor.c</path>
-      <path>build</path>
-      <path>build/CMakeFiles</path>
-      <path>build/CMakeFiles/CompilerIdC</path>
-      <path>build/CMakeFiles/CompilerIdC/CMakeCCompilerId.c</path>
-      <path>build/CMakeFiles/CompilerIdCXX</path>
-      <path>build/CMakeFiles/CompilerIdCXX/CMakeCXXCompilerId.cpp</path>
-      <path>build/dmd</path>
-      <path>build/dmd/id.c</path>
-      <path>build/dmd/id.h</path>
-      <path>build/dmd/impcnvtab.c</path>
-      <path>dmd2.020</path>
-      <path>dmd2.020/access.c</path>
-      <path>dmd2.020/aggregate.h</path>
-      <path>dmd2.020/array.c</path>
-      <path>dmd2.020/arrayop.c</path>
-      <path>dmd2.020/arraytypes.h</path>
-      <path>dmd2.020/attrib.c</path>
-      <path>dmd2.020/attrib.h</path>
-      <path>dmd2.020/bit.c</path>
-      <path>dmd2.020/builtin.c</path>
-      <path>dmd2.020/cast.c</path>
-      <path>dmd2.020/class.c</path>
-      <path>dmd2.020/clone.c</path>
-      <path>dmd2.020/complex_t.h</path>
-      <path>dmd2.020/cond.c</path>
-      <path>dmd2.020/cond.h</path>
-      <path>dmd2.020/constfold.c</path>
-      <path>dmd2.020/dchar.c</path>
-      <path>dmd2.020/dchar.h</path>
-      <path>dmd2.020/declaration.c</path>
-      <path>dmd2.020/declaration.h</path>
-      <path>dmd2.020/delegatize.c</path>
-      <path>dmd2.020/doc.c</path>
-      <path>dmd2.020/doc.h</path>
-      <path>dmd2.020/dsymbol.c</path>
-      <path>dmd2.020/dsymbol.h</path>
-      <path>dmd2.020/dump.c</path>
-      <path>dmd2.020/e2ir.c</path>
-      <path>dmd2.020/entity.c</path>
-      <path>dmd2.020/enum.c</path>
-      <path>dmd2.020/enum.h</path>
-      <path>dmd2.020/expression.c</path>
-      <path>dmd2.020/expression.h</path>
-      <path>dmd2.020/func.c</path>
-      <path>dmd2.020/gnuc.c</path>
-      <path>dmd2.020/gnuc.h</path>
-      <path>dmd2.020/hdrgen.c</path>
-      <path>dmd2.020/hdrgen.h</path>
-      <path>dmd2.020/html.c</path>
-      <path>dmd2.020/html.h</path>
-      <path>dmd2.020/identifier.c</path>
-      <path>dmd2.020/identifier.h</path>
-      <path>dmd2.020/idgen.c</path>
-      <path>dmd2.020/impcnvgen.c</path>
-      <path>dmd2.020/import.c</path>
-      <path>dmd2.020/import.h</path>
-      <path>dmd2.020/inifile.c</path>
-      <path>dmd2.020/init.c</path>
-      <path>dmd2.020/init.h</path>
-      <path>dmd2.020/inline.c</path>
-      <path>dmd2.020/interpret.c</path>
-      <path>dmd2.020/lexer.c</path>
-      <path>dmd2.020/lexer.h</path>
-      <path>dmd2.020/lib.h</path>
-      <path>dmd2.020/libelf.c</path>
-      <path>dmd2.020/link.c</path>
-      <path>dmd2.020/lstring.c</path>
-      <path>dmd2.020/lstring.h</path>
-      <path>dmd2.020/macro.c</path>
-      <path>dmd2.020/macro.h</path>
-      <path>dmd2.020/man.c</path>
-      <path>dmd2.020/mangle.c</path>
-      <path>dmd2.020/mars.c</path>
-      <path>dmd2.020/mars.h</path>
-      <path>dmd2.020/md5.c</path>
-      <path>dmd2.020/md5.h</path>
-      <path>dmd2.020/mem.c</path>
-      <path>dmd2.020/mem.h</path>
-      <path>dmd2.020/module.c</path>
-      <path>dmd2.020/module.h</path>
-      <path>dmd2.020/mtype.c</path>
-      <path>dmd2.020/mtype.h</path>
-      <path>dmd2.020/opover.c</path>
-      <path>dmd2.020/optimize.c</path>
-      <path>dmd2.020/parse.c</path>
-      <path>dmd2.020/parse.h</path>
-      <path>dmd2.020/port.h</path>
-      <path>dmd2.020/root.c</path>
-      <path>dmd2.020/root.h</path>
-      <path>dmd2.020/scope.c</path>
-      <path>dmd2.020/scope.h</path>
-      <path>dmd2.020/statement.c</path>
-      <path>dmd2.020/statement.h</path>
-      <path>dmd2.020/staticassert.c</path>
-      <path>dmd2.020/staticassert.h</path>
-      <path>dmd2.020/stringtable.c</path>
-      <path>dmd2.020/stringtable.h</path>
-      <path>dmd2.020/struct.c</path>
-      <path>dmd2.020/template.c</path>
-      <path>dmd2.020/template.h</path>
-      <path>dmd2.020/tocsym.c</path>
-      <path>dmd2.020/todt.c</path>
-      <path>dmd2.020/toir.c</path>
-      <path>dmd2.020/toir.h</path>
-      <path>dmd2.020/toobj.c</path>
-      <path>dmd2.020/total.h</path>
-      <path>dmd2.020/traits.c</path>
-      <path>dmd2.020/typinf.c</path>
-      <path>dmd2.020/unialpha.c</path>
-      <path>dmd2.020/utf.c</path>
-      <path>dmd2.020/utf.h</path>
-      <path>dmd2.020/version.c</path>
-      <path>dmd2.020/version.h</path>
-      <path>dmd36</path>
-      <path>dmd36/access.c</path>
-      <path>dmd36/aggregate.h</path>
-      <path>dmd36/array.c</path>
-      <path>dmd36/arrayop.c</path>
-      <path>dmd36/arraytypes.h</path>
-      <path>dmd36/attrib.c</path>
-      <path>dmd36/attrib.h</path>
-      <path>dmd36/bit.c</path>
-      <path>dmd36/cast.c</path>
-      <path>dmd36/class.c</path>
-      <path>dmd36/clone.c</path>
-      <path>dmd36/complex_t.h</path>
-      <path>dmd36/cond.c</path>
-      <path>dmd36/cond.h</path>
-      <path>dmd36/constfold.c</path>
-      <path>dmd36/dchar.c</path>
-      <path>dmd36/dchar.h</path>
-      <path>dmd36/declaration.c</path>
-      <path>dmd36/declaration.h</path>
-      <path>dmd36/delegatize.c</path>
-      <path>dmd36/doc.c</path>
-      <path>dmd36/doc.h</path>
-      <path>dmd36/dsymbol.c</path>
-      <path>dmd36/dsymbol.h</path>
-      <path>dmd36/dump.c</path>
-      <path>dmd36/e2ir.c</path>
-      <path>dmd36/entity.c</path>
-      <path>dmd36/enum.c</path>
-      <path>dmd36/enum.h</path>
-      <path>dmd36/expression.c</path>
-      <path>dmd36/expression.h</path>
-      <path>dmd36/func.c</path>
-      <path>dmd36/gnuc.c</path>
-      <path>dmd36/gnuc.h</path>
-      <path>dmd36/hdrgen.c</path>
-      <path>dmd36/hdrgen.h</path>
-      <path>dmd36/html.c</path>
-      <path>dmd36/html.h</path>
-      <path>dmd36/identifier.c</path>
-      <path>dmd36/identifier.h</path>
-      <path>dmd36/idgen.c</path>
-      <path>dmd36/impcnvgen.c</path>
-      <path>dmd36/import.c</path>
-      <path>dmd36/import.h</path>
-      <path>dmd36/inifile.c</path>
-      <path>dmd36/init.c</path>
-      <path>dmd36/init.h</path>
-      <path>dmd36/inline.c</path>
-      <path>dmd36/interpret.c</path>
-      <path>dmd36/lexer.c</path>
-      <path>dmd36/lexer.h</path>
-      <path>dmd36/lib.h</path>
-      <path>dmd36/libelf.c</path>
-      <path>dmd36/link.c</path>
-      <path>dmd36/lstring.c</path>
-      <path>dmd36/lstring.h</path>
-      <path>dmd36/macro.c</path>
-      <path>dmd36/macro.h</path>
-      <path>dmd36/man.c</path>
-      <path>dmd36/mangle.c</path>
-      <path>dmd36/mars.c</path>
-      <path>dmd36/mars.h</path>
-      <path>dmd36/md5.c</path>
-      <path>dmd36/md5.h</path>
-      <path>dmd36/mem.c</path>
-      <path>dmd36/mem.h</path>
-      <path>dmd36/module.c</path>
-      <path>dmd36/module.h</path>
-      <path>dmd36/mtype.c</path>
-      <path>dmd36/mtype.h</path>
-      <path>dmd36/opover.c</path>
-      <path>dmd36/optimize.c</path>
-      <path>dmd36/parse.c</path>
-      <path>dmd36/parse.h</path>
-      <path>dmd36/port.h</path>
-      <path>dmd36/root.c</path>
-      <path>dmd36/root.h</path>
-      <path>dmd36/scope.c</path>
-      <path>dmd36/scope.h</path>
-      <path>dmd36/statement.c</path>
-      <path>dmd36/statement.h</path>
-      <path>dmd36/staticassert.c</path>
-      <path>dmd36/staticassert.h</path>
-      <path>dmd36/stringtable.c</path>
-      <path>dmd36/stringtable.h</path>
-      <path>dmd36/struct.c</path>
-      <path>dmd36/template.c</path>
-      <path>dmd36/template.h</path>
-      <path>dmd36/tocsym.c</path>
-      <path>dmd36/todt.c</path>
-      <path>dmd36/toir.c</path>
-      <path>dmd36/toir.h</path>
-      <path>dmd36/toobj.c</path>
-      <path>dmd36/total.h</path>
-      <path>dmd36/typinf.c</path>
-      <path>dmd36/unialpha.c</path>
-      <path>dmd36/utf.c</path>
-      <path>dmd36/utf.h</path>
-      <path>dmd36/version.c</path>
-      <path>dmd36/version.h</path>
-    </blacklist>
-    <build>
-      <buildtool>make</buildtool>
-      <builddir/>
-    </build>
-    <other>
-      <prio>0</prio>
-      <otherbin/>
-      <defaulttarget/>
-      <otheroptions/>
-      <selectedenvironment>default</selectedenvironment>
-      <environments>
-        <default/>
-      </environments>
-    </other>
-    <make>
-      <abortonerror>false</abortonerror>
-      <numberofjobs>0</numberofjobs>
-      <prio>0</prio>
-      <dontact>false</dontact>
-      <makebin/>
-      <defaulttarget/>
-      <makeoptions/>
-      <selectedenvironment>default</selectedenvironment>
-      <environments>
-        <default/>
-      </environments>
-    </make>
-    <general>
-      <activedir>tangotests</activedir>
-    </general>
-  </kdevcustomproject>
-  <cppsupportpart>
-    <filetemplates>
-      <interfacesuffix>.h</interfacesuffix>
-      <implementationsuffix>.cpp</implementationsuffix>
-    </filetemplates>
-  </cppsupportpart>
-  <kdevdebugger>
-    <general>
-      <gdbpath/>
-      <dbgshell/>
-      <configGdbScript/>
-      <runShellScript/>
-      <runGdbScript/>
-      <breakonloadinglibs>true</breakonloadinglibs>
-      <separatetty>false</separatetty>
-      <floatingtoolbar>false</floatingtoolbar>
-      <raiseGDBOnStart>false</raiseGDBOnStart>
-    </general>
-    <display>
-      <staticmembers>false</staticmembers>
-      <demanglenames>true</demanglenames>
-      <outputradix>10</outputradix>
-    </display>
-  </kdevdebugger>
-</kdevelop>
--- a/llvmdc.kdevelop.filelist	Sat Nov 29 12:28:10 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,239 +0,0 @@
-# KDevelop Custom Project File List
-dmd
-dmd/access.c
-dmd/aggregate.h
-dmd/array.c
-dmd/arrayop.c
-dmd/arraytypes.h
-dmd/attrib.c
-dmd/attrib.h
-dmd/cast.c
-dmd/class.c
-dmd/clone.c
-dmd/complex_t.h
-dmd/cond.c
-dmd/cond.h
-dmd/constfold.c
-dmd/dchar.c
-dmd/dchar.h
-dmd/declaration.c
-dmd/declaration.h
-dmd/delegatize.c
-dmd/doc.c
-dmd/doc.h
-dmd/dsymbol.c
-dmd/dsymbol.h
-dmd/dump.c
-dmd/entity.c
-dmd/enum.c
-dmd/enum.h
-dmd/expression.c
-dmd/expression.h
-dmd/func.c
-dmd/gnuc.c
-dmd/gnuc.h
-dmd/hdrgen.c
-dmd/hdrgen.h
-dmd/html.c
-dmd/html.h
-dmd/identifier.c
-dmd/identifier.h
-dmd/idgen.c
-dmd/impcnvgen.c
-dmd/import.c
-dmd/import.h
-dmd/inifile.c
-dmd/init.c
-dmd/init.h
-dmd/inline.c
-dmd/interpret.c
-dmd/lexer.c
-dmd/lexer.h
-dmd/lstring.c
-dmd/lstring.h
-dmd/macro.c
-dmd/macro.h
-dmd/mangle.c
-dmd/mars.c
-dmd/mars.h
-dmd/mem.c
-dmd/mem.h
-dmd/module.c
-dmd/module.h
-dmd/mtype.c
-dmd/mtype.h
-dmd/opover.c
-dmd/optimize.c
-dmd/parse.c
-dmd/parse.h
-dmd/port.h
-dmd/root.c
-dmd/root.h
-dmd/scope.c
-dmd/scope.h
-dmd/statement.c
-dmd/statement.h
-dmd/staticassert.c
-dmd/staticassert.h
-dmd/stringtable.c
-dmd/stringtable.h
-dmd/struct.c
-dmd/template.c
-dmd/template.h
-dmd/total.h
-dmd/unialpha.c
-dmd/utf.c
-dmd/utf.h
-dmd/version.c
-dmd/version.h
-dmd2
-dmd2/access.c
-dmd2/aggregate.h
-dmd2/array.c
-dmd2/arrayop.c
-dmd2/arraytypes.h
-dmd2/attrib.c
-dmd2/attrib.h
-dmd2/builtin.c
-dmd2/cast.c
-dmd2/class.c
-dmd2/clone.c
-dmd2/complex_t.h
-dmd2/cond.c
-dmd2/cond.h
-dmd2/constfold.c
-dmd2/dchar.c
-dmd2/dchar.h
-dmd2/declaration.c
-dmd2/declaration.h
-dmd2/delegatize.c
-dmd2/doc.c
-dmd2/doc.h
-dmd2/dsymbol.c
-dmd2/dsymbol.h
-dmd2/dump.c
-dmd2/entity.c
-dmd2/enum.c
-dmd2/enum.h
-dmd2/expression.c
-dmd2/expression.h
-dmd2/func.c
-dmd2/gnuc.c
-dmd2/gnuc.h
-dmd2/hdrgen.c
-dmd2/hdrgen.h
-dmd2/html.c
-dmd2/html.h
-dmd2/id.c
-dmd2/id.h
-dmd2/identifier.c
-dmd2/identifier.h
-dmd2/idgen.c
-dmd2/impcnvgen.c
-dmd2/impcnvtab.c
-dmd2/import.c
-dmd2/import.h
-dmd2/inifile.c
-dmd2/init.c
-dmd2/init.h
-dmd2/inline.c
-dmd2/interpret.c
-dmd2/lexer.c
-dmd2/lexer.h
-dmd2/lstring.c
-dmd2/lstring.h
-dmd2/macro.c
-dmd2/macro.h
-dmd2/man.c
-dmd2/mangle.c
-dmd2/mars.c
-dmd2/mars.h
-dmd2/mem.c
-dmd2/mem.h
-dmd2/module.c
-dmd2/module.h
-dmd2/mtype.c
-dmd2/mtype.h
-dmd2/opover.c
-dmd2/optimize.c
-dmd2/parse.c
-dmd2/parse.h
-dmd2/port.h
-dmd2/root.c
-dmd2/root.h
-dmd2/scope.c
-dmd2/scope.h
-dmd2/statement.c
-dmd2/statement.h
-dmd2/staticassert.c
-dmd2/staticassert.h
-dmd2/stringtable.c
-dmd2/stringtable.h
-dmd2/struct.c
-dmd2/template.c
-dmd2/template.h
-dmd2/total.h
-dmd2/traits.c
-dmd2/unialpha.c
-dmd2/utf.c
-dmd2/utf.h
-dmd2/version.c
-dmd2/version.h
-gen
-gen/aa.cpp
-gen/aa.h
-gen/arrays.cpp
-gen/arrays.h
-gen/asmstmt.cpp
-gen/binops.cpp
-gen/classes.cpp
-gen/classes.h
-gen/complex.cpp
-gen/complex.h
-gen/dvalue.cpp
-gen/dvalue.h
-gen/dwarftypes.cpp
-gen/enums.h
-gen/functions.cpp
-gen/functions.h
-gen/irstate.cpp
-gen/irstate.h
-gen/linker.cpp
-gen/linker.h
-gen/llvm.h
-gen/llvmhelpers.cpp
-gen/llvmhelpers.h
-gen/logger.cpp
-gen/logger.h
-gen/optimizer.cpp
-gen/runtime.cpp
-gen/runtime.h
-gen/statements.cpp
-gen/structs.cpp
-gen/structs.h
-gen/tocall.cpp
-gen/tocsym.cpp
-gen/todebug.cpp
-gen/todebug.h
-gen/todt.cpp
-gen/toir.cpp
-gen/tollvm.cpp
-gen/tollvm.h
-gen/toobj.cpp
-gen/typeinf.h
-gen/typinf.cpp
-ir
-ir/ir.h
-ir/irforw.h
-ir/irfunction.cpp
-ir/irfunction.h
-ir/irmodule.cpp
-ir/irmodule.h
-ir/irstruct.cpp
-ir/irstruct.h
-ir/irsymbol.cpp
-ir/irsymbol.h
-ir/irtype.cpp
-ir/irtype.h
-ir/irvar.cpp
-ir/irvar.h
--- a/tests/mini/interface3.d	Sat Nov 29 12:28:10 2008 +0100
+++ b/tests/mini/interface3.d	Sat Nov 29 21:25:43 2008 +0100
@@ -12,14 +12,14 @@
     int i = 42;
     override void func()
     {
-        printf("hello %d\n", i);
+        printf("hello %d from %p\n", i, this);
         i++;
     }
 }
 
 void main()
 {
-    scope c = new C;
+    auto c = new C;
     {c.func();}
     {
         I i = c;