changeset 100:5071469303d4 trunk

[svn r104] TONS OF FIXES. Split up declaration, constant initializer gen and definition for globals, structs, classes and functions. Improved ClassInfo support (not complete), not in vtable yet. Fixed a bunch of forward reference problems. Much more. Major commit! :)
author lindquist
date Fri, 16 Nov 2007 08:21:47 +0100
parents a676a7743642
children 169fda3a77d4
files demos/ray.d dmd/aggregate.h dmd/declaration.c dmd/declaration.h dmd/dsymbol.c dmd/dsymbol.h dmd/func.c dmd/mtype.h dmd/struct.c gen/arrays.cpp gen/classes.cpp gen/classes.h gen/functions.cpp gen/functions.h gen/irstate.cpp gen/irstate.h gen/statements.cpp gen/structs.cpp gen/structs.h gen/toir.cpp gen/tollvm.cpp gen/tollvm.h gen/toobj.cpp gen/typinf.cpp llvmdc.kdevelop.filelist lphobos/internal/arrays.d runalltests.d test/arrays13.d test/bug58.d test/bug63.d test/bug66.d test/classinfo1.d test/structs7.d test/throw1.d test/typeinfo3.d
diffstat 35 files changed, 1824 insertions(+), 1452 deletions(-) [+]
line wrap: on
line diff
--- a/demos/ray.d	Thu Nov 15 00:24:44 2007 +0100
+++ b/demos/ray.d	Fri Nov 16 08:21:47 2007 +0100
@@ -1,5 +1,4 @@
-//import std.stdio, std.math, std.string;
-//import tools.base;
+import std.stdio;
 
 int atoi(char[] s) {
     int i, fac=1;
@@ -105,7 +104,7 @@
     n = (args.length==3 ? args[2].atoi() : 512), ss = 4;
   auto light = Vec(-1, -3, 2).unitise();
   auto s=create(level, Vec(0, -1, 0), 1);
-  printf("P5\n%d %d\n255", n, n);
+  writefln("P5\n", n, " ", n, "\n255");
   for (int y=n-1; y>=0; --y)
     for (int x=0; x<n; ++x) {
       double g=0;
--- a/dmd/aggregate.h	Thu Nov 15 00:24:44 2007 +0100
+++ b/dmd/aggregate.h	Fri Nov 16 08:21:47 2007 +0100
@@ -43,8 +43,9 @@
     class Value;
     class Constant;
     class ConstantStruct;
+    class GlobalVariable;
 }
-
+struct IRStruct;
 struct DUnion;
 
 struct AggregateDeclaration : ScopeDsymbol
@@ -101,12 +102,14 @@
     Symbol *toInitializer();
 
     bool llvmInProgress;
-    const llvm::Type* llvmType;
-    llvm::Constant* llvmVtbl;
+    llvm::GlobalVariable* llvmVtbl;
     llvm::ConstantStruct* llvmConstVtbl;
     llvm::Constant* llvmInitZ;
+    llvm::GlobalVariable* llvmClass;
+    llvm::Constant* llvmClassZ;
     bool llvmHasUnions;
     DUnion* llvmUnion;
+    IRStruct* llvmIRStruct;
 
     AggregateDeclaration *isAggregateDeclaration() { return this; }
 };
--- a/dmd/declaration.c	Thu Nov 15 00:24:44 2007 +0100
+++ b/dmd/declaration.c	Fri Nov 16 08:21:47 2007 +0100
@@ -32,7 +32,6 @@
     storage_class = STCundefined;
     protection = PROTundefined;
     linkage = LINKdefault;
-    llvmTouched = false;
 }
 
 void Declaration::semantic(Scope *sc)
@@ -553,6 +552,8 @@
     llvmFieldIndex = -1;
     llvmFieldIndexOffset = 0;
     llvmNeedsStorage = false;
+    llvmConstInit = NULL;
+    llvmIRGlobal = NULL;
 }
 
 Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
--- a/dmd/declaration.h	Thu Nov 15 00:24:44 2007 +0100
+++ b/dmd/declaration.h	Fri Nov 16 08:21:47 2007 +0100
@@ -24,6 +24,8 @@
 namespace llvm {
     class Value;
 }
+struct IRFunction;
+struct IRGlobal;
 
 struct Expression;
 struct Statement;
@@ -128,8 +130,6 @@
     Declaration *isDeclaration() { return this; }
 
     virtual void toObjFile();           // compile to .obj file
-    
-    bool llvmTouched;
 };
 
 /**************************************************************/
@@ -263,6 +263,8 @@
     int llvmFieldIndex;
     size_t llvmFieldIndexOffset;
     bool llvmNeedsStorage;
+    llvm::Constant* llvmConstInit;
+    IRGlobal* llvmIRGlobal;
 };
 
 /**************************************************************/
@@ -293,6 +295,8 @@
     void emitComment(Scope *sc);
 
     Symbol *toSymbol();
+
+    ClassInfoDeclaration* isClassInfoDeclaration() { return this; }
 };
 
 struct ModuleInfoDeclaration : VarDeclaration
@@ -558,6 +562,7 @@
     llvm::Value* llvmArgPtr;
     llvm::Constant* llvmDwarfSubProgram;
     bool llvmRunTimeHack;
+    IRFunction* llvmIRFunc;
 };
 
 struct FuncAliasDeclaration : FuncDeclaration
--- a/dmd/dsymbol.c	Thu Nov 15 00:24:44 2007 +0100
+++ b/dmd/dsymbol.c	Fri Nov 16 08:21:47 2007 +0100
@@ -48,6 +48,7 @@
     this->llvmInternal2 = NULL;
     this->llvmValue = NULL;
     this->llvmDModule = NULL;
+    this->llvmTouched = false;
 }
 
 Dsymbol::Dsymbol(Identifier *ident)
@@ -65,6 +66,7 @@
     this->llvmInternal2 = NULL;
     this->llvmValue = NULL;
     this->llvmDModule = NULL;
+    this->llvmTouched = false;
 }
 
 int Dsymbol::equals(Object *o)
--- a/dmd/dsymbol.h	Thu Nov 15 00:24:44 2007 +0100
+++ b/dmd/dsymbol.h	Fri Nov 16 08:21:47 2007 +0100
@@ -67,6 +67,7 @@
 struct DeleteDeclaration;
 struct HdrGenState;
 struct TypeInfoDeclaration;
+struct ClassInfoDeclaration;
 
 #if IN_GCC
 union tree_node;
@@ -212,6 +213,7 @@
     virtual SymbolDeclaration *isSymbolDeclaration() { return NULL; }
     virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
     virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
+    virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
     
     // llvm stuff
     int llvmInternal;
@@ -220,6 +222,8 @@
 
     llvm::Value* llvmValue;
     Module* llvmDModule;
+
+    bool llvmTouched;
 };
 
 // Dsymbol that generates a scope
--- a/dmd/func.c	Thu Nov 15 00:24:44 2007 +0100
+++ b/dmd/func.c	Fri Nov 16 08:21:47 2007 +0100
@@ -80,6 +80,7 @@
     llvmArgPtr = NULL;
     llvmDwarfSubProgram = NULL;
     llvmRunTimeHack = false;
+    llvmIRFunc = NULL;
 }
 
 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
--- a/dmd/mtype.h	Thu Nov 15 00:24:44 2007 +0100
+++ b/dmd/mtype.h	Fri Nov 16 08:21:47 2007 +0100
@@ -21,11 +21,14 @@
 #include "arraytypes.h"
 #include "expression.h"
 
+// LLVMDC
 namespace llvm
 {
     class Value;
+    class Instruction;
     class Type;
-    class Instruction;
+    class PATypeHolder;
+    class GlobalVariable;
 }
 
 struct Scope;
@@ -250,7 +253,7 @@
     virtual type *toCParamtype();
     virtual Symbol *toSymbol();
 
-    const llvm::Type* llvmType;
+    llvm::PATypeHolder* llvmType;
 
     // For eliminating dynamic_cast
     virtual TypeBasic *isTypeBasic();
@@ -540,7 +543,7 @@
 
     type *toCtype();
 
-    llvm::Constant* llvmInit;
+    llvm::GlobalVariable* llvmInit;
 };
 
 struct TypeEnum : Type
@@ -638,7 +641,7 @@
 
     Symbol *toSymbol();
 
-    llvm::Constant* llvmInit;
+    llvm::GlobalVariable* llvmInit;
 };
 
 struct TypeTuple : Type
--- a/dmd/struct.c	Thu Nov 15 00:24:44 2007 +0100
+++ b/dmd/struct.c	Fri Nov 16 08:21:47 2007 +0100
@@ -45,13 +45,15 @@
     sinit = NULL;
     scope = NULL;
 
-    llvmType = NULL;
     llvmVtbl = NULL;
     llvmConstVtbl = NULL;
     llvmInitZ = NULL;
+    llvmClass = NULL;
+    llvmClassZ = NULL;
     llvmInProgress = false;
     llvmHasUnions = false;
     llvmUnion = NULL;
+    llvmIRStruct = NULL;
 }
 
 enum PROT AggregateDeclaration::prot()
--- a/gen/arrays.cpp	Thu Nov 15 00:24:44 2007 +0100
+++ b/gen/arrays.cpp	Fri Nov 16 08:21:47 2007 +0100
@@ -42,7 +42,7 @@
 const llvm::ArrayType* DtoStaticArrayType(Type* t)
 {
     if (t->llvmType)
-        return isaArray(t->llvmType);
+        return isaArray(t->llvmType->get());
 
     assert(t->ty == Tsarray);
     assert(t->next);
@@ -53,7 +53,8 @@
     assert(tsa->dim->type->isintegral());
     const llvm::ArrayType* arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger());
 
-    tsa->llvmType = arrty;
+    assert(!tsa->llvmType);
+    tsa->llvmType = new llvm::PATypeHolder(arrty);
     return arrty;
 }
 
@@ -547,7 +548,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 // helper for eq and cmp
-static llvm::Value* DtoArrayEqCmp_impl(const char* func, DValue* l, DValue* r)
+static llvm::Value* DtoArrayEqCmp_impl(const char* func, DValue* l, DValue* r, bool useti)
 {
     llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, func);
     assert(fn);
@@ -588,14 +589,17 @@
     args.push_back(DtoBitCast(lmem,pt));
     args.push_back(DtoBitCast(rmem,pt));
 
-    TypeInfoDeclaration* ti = DtoDType(l->getType())->next->getTypeInfoDeclaration();
-    if (!ti->llvmValue) {
-        ti->toObjFile();
+    // pass element typeinfo ?
+    if (useti) {
+        TypeInfoDeclaration* ti = DtoDType(l->getType())->next->getTypeInfoDeclaration();
+        if (!ti->llvmValue) {
+            ti->toObjFile();
+        }
+        Logger::cout() << "typeinfo decl: " << *ti->llvmValue << '\n';
+
+        pt = fn->getFunctionType()->getParamType(2);
+        args.push_back(DtoBitCast(ti->llvmValue, pt));
     }
-    Logger::cout() << "typeinfo decl: " << *ti->llvmValue << '\n';
-
-    pt = fn->getFunctionType()->getParamType(2);
-    args.push_back(DtoBitCast(ti->llvmValue, pt));
 
     return gIR->ir->CreateCall(fn, args.begin(), args.end(), "tmp");
 }
@@ -606,7 +610,7 @@
     llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_adEq");
     assert(fn);
 
-    llvm::Value* res = DtoArrayEqCmp_impl("_adEq", l, r);
+    llvm::Value* res = DtoArrayEqCmp_impl("_adEq", l, r, true);
     if (op == TOKnotequal)
         res = gIR->ir->CreateNot(res, "tmp");
 
@@ -660,7 +664,11 @@
 
     if (!skip)
     {
-        res = DtoArrayEqCmp_impl("_adCmp", l, r);
+        Type* t = DtoDType(DtoDType(l->getType())->next);
+        if (t->ty == Tchar)
+            res = DtoArrayEqCmp_impl("_adCmpChar", l, r, false);
+        else
+            res = DtoArrayEqCmp_impl("_adCmp", l, r, true);
         res = new llvm::ICmpInst(cmpop, res, DtoConstInt(0), "tmp", gIR->scopebb());
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/classes.cpp	Fri Nov 16 08:21:47 2007 +0100
@@ -0,0 +1,431 @@
+#include "gen/llvm.h"
+
+#include "mtype.h"
+#include "aggregate.h"
+#include "init.h"
+#include "declaration.h"
+
+#include "gen/irstate.h"
+#include "gen/tollvm.h"
+#include "gen/arrays.h"
+#include "gen/logger.h"
+#include "gen/classes.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+static void LLVM_AddBaseClassData(BaseClasses* bcs)
+{
+    // add base class data members first
+    for (int j=0; j<bcs->dim; j++)
+    {
+        BaseClass* bc = (BaseClass*)(bcs->data[j]);
+        assert(bc);
+        Logger::println("Adding base class members of %s", bc->base->toChars());
+        LOG_SCOPE;
+
+        bc->base->toObjFile();
+
+        LLVM_AddBaseClassData(&bc->base->baseclasses);
+        for (int k=0; k < bc->base->members->dim; k++) {
+            Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]);
+            if (dsym->isVarDeclaration())
+            {
+                dsym->toObjFile();
+            }
+        }
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoDeclareClass(ClassDeclaration* cd)
+{
+    if (cd->llvmTouched) return;
+    cd->llvmTouched = true;
+
+    Logger::println("DtoDeclareClass(%s)\n", cd->toPrettyChars());
+    LOG_SCOPE;
+
+    assert(cd->type->ty == Tclass);
+    TypeClass* ts = (TypeClass*)cd->type;
+
+    assert(!cd->llvmIRStruct);
+    IRStruct* irstruct = new IRStruct(ts);
+    cd->llvmIRStruct = irstruct;
+
+    gIR->structs.push_back(irstruct);
+    gIR->classes.push_back(cd);
+
+    // add vtable
+    llvm::PATypeHolder pa = llvm::OpaqueType::get();
+    const llvm::Type* vtabty = llvm::PointerType::get(pa);
+
+    std::vector<const llvm::Type*> fieldtypes;
+    fieldtypes.push_back(vtabty);
+
+    // base classes first
+    LLVM_AddBaseClassData(&cd->baseclasses);
+
+    // then add own members
+    for (int k=0; k < cd->members->dim; k++) {
+        Dsymbol* dsym = (Dsymbol*)(cd->members->data[k]);
+        dsym->toObjFile();
+    }
+
+    // add field types
+    for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
+        fieldtypes.push_back(i->second.type);
+    }
+
+    const llvm::StructType* structtype = llvm::StructType::get(fieldtypes);
+    // 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());
+    }
+
+    // create the type
+    ts->llvmType = new llvm::PATypeHolder(structtype);
+
+    bool needs_definition = false;
+    if (cd->parent->isModule()) {
+        gIR->module->addTypeName(cd->mangle(), ts->llvmType->get());
+        needs_definition = (cd->getModule() == gIR->dmodule);
+    }
+    else {
+        assert(0 && "class parent is not a module");
+    }
+
+    // generate vtable
+    llvm::GlobalVariable* svtblVar = 0;
+    std::vector<llvm::Constant*> sinits;
+    std::vector<const llvm::Type*> sinits_ty;
+    sinits.reserve(cd->vtbl.dim);
+    sinits_ty.reserve(cd->vtbl.dim);
+
+    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 (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
+            fd->toObjFile();
+            assert(fd->llvmValue);
+            llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
+            sinits.push_back(c);
+            sinits_ty.push_back(c->getType());
+        }
+        else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
+            const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty);
+            llvm::Constant* c = llvm::Constant::getNullValue(cty);
+            sinits.push_back(c);
+            sinits_ty.push_back(cty);
+        }
+        else
+        assert(0);
+    }
+
+    const llvm::StructType* svtbl_ty = 0;
+    if (!sinits.empty())
+    {
+        llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
+
+        std::string varname("_D");
+        varname.append(cd->mangle());
+        varname.append("6__vtblZ");
+
+        std::string styname(cd->mangle());
+        styname.append("__vtblTy");
+
+        svtbl_ty = llvm::StructType::get(sinits_ty);
+        gIR->module->addTypeName(styname, svtbl_ty);
+        svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
+
+        cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits));
+        if (needs_definition)
+            svtblVar->setInitializer(cd->llvmConstVtbl);
+        cd->llvmVtbl = svtblVar;
+    }
+
+    // refine for final vtable type
+    llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty);
+
+    std::string initname("_D");
+    initname.append(cd->mangle());
+    initname.append("6__initZ");
+    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
+    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module);
+    ts->llvmInit = initvar;
+
+    gIR->classes.pop_back();
+    gIR->structs.pop_back();
+
+    gIR->constInitQueue.push_back(cd);
+    if (needs_definition)
+    gIR->defineQueue.push_back(cd);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoConstInitClass(ClassDeclaration* cd)
+{
+    IRStruct* irstruct = cd->llvmIRStruct;
+    if (irstruct->constinited) return;
+    irstruct->constinited = true;
+
+    Logger::println("DtoConstInitClass(%s)\n", cd->toPrettyChars());
+    LOG_SCOPE;
+
+    gIR->structs.push_back(irstruct);
+    gIR->classes.push_back(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;
+        llvm::Constant* finit = DtoConstFieldInitializer(so->var->type, so->var->init);
+        so->init = finit;
+        so->var->llvmConstInit = finit;
+    }
+
+    // fill out fieldtypes/inits
+    std::vector<llvm::Constant*> fieldinits;
+
+    // first field is always the vtable
+    assert(cd->llvmVtbl != 0);
+    fieldinits.push_back(cd->llvmVtbl);
+
+    // rest
+    for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
+        fieldinits.push_back(i->second.init);
+    }
+
+    // get the struct (class) type
+    assert(cd->type->ty == Tclass);
+    TypeClass* ts = (TypeClass*)cd->type;
+    const llvm::StructType* structtype = isaStruct(ts->llvmType->get());
+
+    // generate initializer
+    Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n';
+    Logger::println("%u %u fields", structtype->getNumElements(), fieldinits.size());
+    llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits);
+    assert(_init);
+    cd->llvmInitZ = _init;
+
+    gIR->classes.pop_back();
+    gIR->structs.pop_back();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoDefineClass(ClassDeclaration* cd)
+{
+    IRStruct* irstruct = cd->llvmIRStruct;
+    if (irstruct->defined) return;
+    irstruct->defined = true;
+
+    Logger::println("DtoDefineClass(%s)\n", cd->toPrettyChars());
+    LOG_SCOPE;
+
+    // get the struct (class) type
+    assert(cd->type->ty == Tclass);
+    TypeClass* ts = (TypeClass*)cd->type;
+
+    bool def = false;
+    if (cd->parent->isModule() && cd->getModule() == gIR->dmodule) {
+        ts->llvmInit->setInitializer(cd->llvmInitZ);
+        def = true;
+    }
+
+    // generate classinfo
+    DtoDeclareClassInfo(cd);
+    if (def) DtoDefineClassInfo(cd);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance)
+{
+    Array* arr = &tc->sym->dtors;
+    for (size_t i=0; i<arr->dim; i++)
+    {
+        FuncDeclaration* fd = (FuncDeclaration*)arr->data[i];
+        assert(fd->llvmValue);
+        new llvm::CallInst(fd->llvmValue, instance, "", gIR->scopebb());
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoInitClass(TypeClass* tc, llvm::Value* dst)
+{
+    assert(gIR);
+
+    assert(tc->llvmType);
+    uint64_t size_t_size = gTargetData->getTypeSize(DtoSize_t());
+    uint64_t n = gTargetData->getTypeSize(tc->llvmType->get()) - size_t_size;
+
+    // set vtable field
+    llvm::Value* vtblvar = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
+    assert(tc->sym->llvmVtbl);
+    new llvm::StoreInst(tc->sym->llvmVtbl, vtblvar, gIR->scopebb());
+
+    // copy the static initializer
+    if (n > 0) {
+        assert(tc->llvmInit);
+        assert(dst->getType() == tc->llvmInit->getType());
+
+        llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
+
+        llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
+        dstarr = DtoGEPi(dstarr,size_t_size,"tmp",gIR->scopebb());
+
+        llvm::Value* srcarr = new llvm::BitCastInst(tc->llvmInit,arrty,"tmp",gIR->scopebb());
+        srcarr = DtoGEPi(srcarr,size_t_size,"tmp",gIR->scopebb());
+
+        llvm::Function* fn = LLVM_DeclareMemCpy32();
+        std::vector<llvm::Value*> llargs;
+        llargs.resize(4);
+        llargs[0] = dstarr;
+        llargs[1] = srcarr;
+        llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
+        llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+
+        new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoDeclareClassInfo(ClassDeclaration* cd)
+{
+    if (cd->llvmClass)
+        return;
+
+    Logger::println("CLASS INFO DECLARATION: %s", cd->toChars());
+    LOG_SCOPE;
+
+    ClassDeclaration* cinfo = ClassDeclaration::classinfo;
+    cinfo->toObjFile();
+
+    const llvm::Type* st = cinfo->type->llvmType->get();
+
+    std::string gname("_D");
+    gname.append(cd->mangle());
+    gname.append("7__ClassZ");
+
+    cd->llvmClass = new llvm::GlobalVariable(st, true, llvm::GlobalValue::ExternalLinkage, NULL, gname, gIR->module);
+}
+
+void DtoDefineClassInfo(ClassDeclaration* cd)
+{
+//     The layout is:
+//        {
+//         void **vptr;
+//         monitor_t monitor;
+//         byte[] initializer;     // static initialization data
+//         char[] name;        // class name
+//         void *[] vtbl;
+//         Interface[] interfaces;
+//         ClassInfo *base;        // base class
+//         void *destructor;
+//         void *invariant;        // class invariant
+//         uint flags;
+//         void *deallocator;
+//         OffsetTypeInfo[] offTi;
+//         void *defaultConstructor;
+//        }
+
+    if (cd->llvmClassZ)
+        return;
+
+    Logger::println("CLASS INFO DEFINITION: %s", cd->toChars());
+    LOG_SCOPE;
+    assert(cd->llvmClass);
+
+    // holds the list of initializers for llvm
+    std::vector<llvm::Constant*> inits;
+
+    ClassDeclaration* cinfo = ClassDeclaration::classinfo;
+    DtoConstInitClass(cinfo);
+    assert(cinfo->llvmInitZ);
+
+    llvm::Constant* c;
+
+    // own vtable
+    c = cinfo->llvmInitZ->getOperand(0);
+    assert(c);
+    inits.push_back(c);
+
+    // monitor
+    // TODO no monitors yet
+
+    // initializer
+    c = cinfo->llvmInitZ->getOperand(1);
+    inits.push_back(c);
+
+    // class name
+    // from dmd
+    char *name = cd->ident->toChars();
+    size_t namelen = strlen(name);
+    if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
+    {
+        name = cd->toPrettyChars();
+        namelen = strlen(name);
+    }
+    c = DtoConstString(name);
+    inits.push_back(c);
+
+    // vtbl array
+    c = cinfo->llvmInitZ->getOperand(3);
+    inits.push_back(c);
+
+    // interfaces array
+    c = cinfo->llvmInitZ->getOperand(4);
+    inits.push_back(c);
+
+    // base classinfo
+    c = cinfo->llvmInitZ->getOperand(5);
+    inits.push_back(c);
+
+    // destructor
+    c = cinfo->llvmInitZ->getOperand(6);
+    inits.push_back(c);
+
+    // invariant
+    c = cinfo->llvmInitZ->getOperand(7);
+    inits.push_back(c);
+
+    // flags
+    c = cinfo->llvmInitZ->getOperand(8);
+    inits.push_back(c);
+
+    // allocator
+    c = cinfo->llvmInitZ->getOperand(9);
+    inits.push_back(c);
+
+    // offset typeinfo
+    c = cinfo->llvmInitZ->getOperand(10);
+    inits.push_back(c);
+
+    // default constructor
+    c = cinfo->llvmInitZ->getOperand(11);
+    inits.push_back(c);
+
+    /*size_t n = inits.size();
+    for (size_t i=0; i<n; ++i)
+    {
+        Logger::cout() << "inits[" << i << "]: " << *inits[i] << '\n';
+    }*/
+
+    // build the initializer
+    const llvm::StructType* st = isaStruct(cinfo->llvmInitZ->getType());
+    llvm::Constant* finalinit = llvm::ConstantStruct::get(st, inits);
+    //Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
+
+    cd->llvmClassZ = finalinit;
+    cd->llvmClass->setInitializer(finalinit);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/classes.h	Fri Nov 16 08:21:47 2007 +0100
@@ -0,0 +1,25 @@
+#ifndef LLVMDC_GEN_CLASSES_H
+#define LLVMDC_GEN_CLASSES_H
+
+/**
+ * Provides the llvm declaration for a class declaration
+ */
+void DtoDeclareClass(ClassDeclaration* cd);
+
+/**
+ * Constructs the constant initializer for a class declaration
+ */
+void DtoConstInitClass(ClassDeclaration* cd);
+
+/**
+ * Provides the llvm definition for a class declaration
+ */
+void DtoDefineClass(ClassDeclaration* cd);
+
+void DtoDeclareClassInfo(ClassDeclaration* cd);
+void DtoDefineClassInfo(ClassDeclaration* cd);
+
+void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance);
+void DtoInitClass(TypeClass* tc, llvm::Value* dst);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/functions.cpp	Fri Nov 16 08:21:47 2007 +0100
@@ -0,0 +1,662 @@
+#include "gen/llvm.h"
+
+#include "mtype.h"
+#include "aggregate.h"
+#include "init.h"
+#include "declaration.h"
+#include "template.h"
+#include "module.h"
+#include "statement.h"
+
+#include "gen/irstate.h"
+#include "gen/tollvm.h"
+#include "gen/runtime.h"
+#include "gen/arrays.h"
+#include "gen/logger.h"
+#include "gen/functions.h"
+#include "gen/todebug.h"
+#include "gen/classes.h"
+
+const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype, bool ismain)
+{
+    TypeFunction* f = (TypeFunction*)type;
+    assert(f != 0);
+
+    if (type->llvmType != NULL) {
+        return llvm::cast<llvm::FunctionType>(type->llvmType->get());
+    }
+
+    bool typesafeVararg = false;
+    if (f->linkage == LINKd && f->varargs == 1) {
+        typesafeVararg = true;
+    }
+
+    // return value type
+    const llvm::Type* rettype;
+    const llvm::Type* actualRettype;
+    Type* rt = f->next;
+    bool retinptr = false;
+    bool usesthis = false;
+
+    if (ismain) {
+        rettype = llvm::Type::Int32Ty;
+        actualRettype = rettype;
+    }
+    else {
+        assert(rt);
+        if (DtoIsPassedByRef(rt)) {
+            rettype = llvm::PointerType::get(DtoType(rt));
+            actualRettype = llvm::Type::VoidTy;
+            f->llvmRetInPtr = retinptr = true;
+        }
+        else {
+            rettype = DtoType(rt);
+            actualRettype = rettype;
+        }
+    }
+
+    // parameter types
+    std::vector<const llvm::Type*> paramvec;
+
+    if (retinptr) {
+        Logger::cout() << "returning through pointer parameter: " << *rettype << '\n';
+        paramvec.push_back(rettype);
+    }
+
+    if (thistype) {
+        paramvec.push_back(thistype);
+        usesthis = true;
+    }
+
+    if (typesafeVararg) {
+        ClassDeclaration* ti = Type::typeinfo;
+        ti->toObjFile();
+        DtoConstInitClass(ti);
+        assert(ti->llvmInitZ);
+        std::vector<const llvm::Type*> types;
+        types.push_back(DtoSize_t());
+        types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmInitZ->getType())));
+        const llvm::Type* t1 = llvm::StructType::get(types);
+        paramvec.push_back(llvm::PointerType::get(t1));
+        paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
+    }
+
+    size_t n = Argument::dim(f->parameters);
+
+    for (int i=0; i < n; ++i) {
+        Argument* arg = Argument::getNth(f->parameters, i);
+        // ensure scalar
+        Type* argT = DtoDType(arg->type);
+        assert(argT);
+
+        if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
+            //assert(arg->vardecl);
+            //arg->vardecl->refparam = true;
+        }
+        else
+            arg->llvmCopy = true;
+
+        const llvm::Type* at = DtoType(argT);
+        if (isaStruct(at)) {
+            Logger::println("struct param");
+            paramvec.push_back(llvm::PointerType::get(at));
+        }
+        else if (isaArray(at)) {
+            Logger::println("sarray param");
+            assert(argT->ty == Tsarray);
+            //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0)));
+            paramvec.push_back(llvm::PointerType::get(at));
+        }
+        else if (llvm::isa<llvm::OpaqueType>(at)) {
+            Logger::println("opaque param");
+            assert(argT->ty == Tstruct || argT->ty == Tclass);
+            paramvec.push_back(llvm::PointerType::get(at));
+        }
+        else {
+            if (!arg->llvmCopy) {
+                Logger::println("ref param");
+                at = llvm::PointerType::get(at);
+            }
+            else {
+                Logger::println("in param");
+            }
+            paramvec.push_back(at);
+        }
+    }
+
+    // construct function type
+    bool isvararg = !typesafeVararg && f->varargs;
+    llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
+
+    f->llvmRetInPtr = retinptr;
+    f->llvmUsesThis = usesthis;
+
+    if (!f->llvmType)
+        f->llvmType = new llvm::PATypeHolder(functype);
+    else
+        assert(functype == f->llvmType->get());
+
+    return functype;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
+{
+    TypeFunction* f = (TypeFunction*)fdecl->type;
+    assert(f != 0);
+
+    const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    std::vector<const llvm::Type*> args;
+
+    if (fdecl->llvmInternal == LLVMva_start) {
+        args.push_back(i8pty);
+    }
+    else if (fdecl->llvmInternal == LLVMva_intrinsic) {
+        size_t n = Argument::dim(f->parameters);
+        for (size_t i=0; i<n; ++i) {
+            args.push_back(i8pty);
+        }
+    }
+    else
+    assert(0);
+
+    const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
+
+    if (!f->llvmType)
+        f->llvmType = new llvm::PATypeHolder(fty);
+    else
+        assert(fty == f->llvmType->get());
+
+    return fty;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
+{
+    if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
+        return DtoVaFunctionType(fdecl);
+    }
+
+    // type has already been resolved
+    if (fdecl->type->llvmType != 0) {
+        return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType->get());
+    }
+
+    const llvm::Type* thisty = NULL;
+    if (fdecl->needThis()) {
+        if (AggregateDeclaration* ad = fdecl->isMember()) {
+            Logger::print("isMember = this is: %s\n", ad->type->toChars());
+            thisty = DtoType(ad->type);
+            Logger::cout() << "this llvm type: " << *thisty << '\n';
+            if (isaStruct(thisty) || thisty == gIR->topstruct()->recty.get())
+                thisty = llvm::PointerType::get(thisty);
+        }
+        else
+        assert(0);
+    }
+    else if (fdecl->isNested()) {
+        thisty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    }
+
+    const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain());
+
+    return functype;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl)
+{
+    TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
+    const llvm::FunctionType* fty = DtoVaFunctionType(fdecl);
+    llvm::Constant* fn = 0;
+
+    if (fdecl->llvmInternal == LLVMva_start) {
+        fn = gIR->module->getOrInsertFunction("llvm.va_start", fty);
+        assert(fn);
+    }
+    else if (fdecl->llvmInternal == LLVMva_intrinsic) {
+        fn = gIR->module->getOrInsertFunction(fdecl->llvmInternal1, fty);
+        assert(fn);
+    }
+    else
+    assert(0);
+
+    llvm::Function* func = llvm::dyn_cast<llvm::Function>(fn);
+    assert(func);
+    assert(func->isIntrinsic());
+    fdecl->llvmValue = func;
+    return func;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoDeclareFunction(FuncDeclaration* fdecl)
+{
+    Logger::println("DtoDeclareFunction(%s)", fdecl->toPrettyChars());
+    LOG_SCOPE;
+
+    if (fdecl->llvmRunTimeHack) {
+        Logger::println("runtime hack func chars: %s", fdecl->toChars());
+        if (!fdecl->llvmValue)
+            fdecl->llvmValue = LLVM_D_GetRuntimeFunction(gIR->module, fdecl->toChars());
+        return;
+    }
+
+    if (fdecl->isUnitTestDeclaration()) {
+        Logger::attention("ignoring unittest declaration: %s", fdecl->toChars());
+        return;
+    }
+
+    bool declareOnly = false;
+    if (fdecl->parent)
+    {
+    if (TemplateInstance* tinst = fdecl->parent->isTemplateInstance())
+    {
+        TemplateDeclaration* tempdecl = tinst->tempdecl;
+        if (tempdecl->llvmInternal == LLVMva_start)
+        {
+            Logger::println("magic va_start found");
+            fdecl->llvmInternal = LLVMva_start;
+            declareOnly = true;
+        }
+        else if (tempdecl->llvmInternal == LLVMva_arg)
+        {
+            Logger::println("magic va_arg found");
+            fdecl->llvmInternal = LLVMva_arg;
+            return;
+        }
+    }
+    }
+
+    if (fdecl->llvmTouched) return;
+    fdecl->llvmTouched = true;
+
+    if (!fdecl->llvmIRFunc) {
+        fdecl->llvmIRFunc = new IRFunction(fdecl);
+    }
+
+    // mangled name
+    char* mangled_name;
+    if (fdecl->llvmInternal == LLVMintrinsic)
+        mangled_name = fdecl->llvmInternal1;
+    else
+        mangled_name = fdecl->mangle();
+
+    // unit test special handling
+    if (fdecl->isUnitTestDeclaration())
+    {
+        assert(0 && "no unittests yet");
+        /*const llvm::FunctionType* fnty = llvm::FunctionType::get(llvm::Type::VoidTy, std::vector<const llvm::Type*>(), false);
+        // make the function
+        llvm::Function* func = gIR->module->getFunction(mangled_name);
+        if (func == 0)
+            func = new llvm::Function(fnty,llvm::GlobalValue::InternalLinkage,mangled_name,gIR->module);
+        func->setCallingConv(llvm::CallingConv::Fast);
+        fdecl->llvmValue = func;
+        return func;
+        */
+    }
+
+    if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) {
+        error("intrinsics cannot have function bodies");
+        fatal();
+    }
+
+    llvm::Function* vafunc = 0;
+    if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
+        vafunc = DtoDeclareVaFunction(fdecl);
+    }
+
+    Type* t = DtoDType(fdecl->type);
+    TypeFunction* f = (TypeFunction*)t;
+
+    // construct function
+    const llvm::FunctionType* functype = DtoFunctionType(fdecl);
+    llvm::Function* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name);
+    if (!func)
+        func = new llvm::Function(functype, DtoLinkage(fdecl->protection, fdecl->storage_class), mangled_name, gIR->module);
+    else
+        assert(func->getFunctionType() == functype);
+
+    // add func to IRFunc
+    fdecl->llvmIRFunc->func = func;
+
+    // calling convention
+    if (!vafunc && fdecl->llvmInternal != LLVMintrinsic)
+        func->setCallingConv(DtoCallingConv(f->linkage));
+
+    // template instances should have weak linkage
+    if (!vafunc && fdecl->llvmInternal != LLVMintrinsic && fdecl->parent && DtoIsTemplateInstance(fdecl->parent))
+        func->setLinkage(llvm::GlobalValue::WeakLinkage);
+
+    fdecl->llvmValue = func;
+    assert(llvm::isa<llvm::FunctionType>(f->llvmType->get()));
+
+    if (fdecl->isMain()) {
+        gIR->mainFunc = func;
+    }
+
+    // name parameters
+    llvm::Function::arg_iterator iarg = func->arg_begin();
+    int k = 0;
+    if (f->llvmRetInPtr) {
+        iarg->setName("retval");
+        f->llvmRetArg = iarg;
+        ++iarg;
+    }
+    if (f->llvmUsesThis) {
+        iarg->setName("this");
+        ++iarg;
+    }
+    int varargs = -1;
+    if (f->linkage == LINKd && f->varargs == 1)
+        varargs = 0;
+    for (; iarg != func->arg_end(); ++iarg)
+    {
+        Argument* arg = Argument::getNth(f->parameters, k++);
+        //arg->llvmValue = iarg;
+        //Logger::println("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident);
+        if (arg && arg->ident != 0) {
+            if (arg->vardecl) {
+                arg->vardecl->llvmValue = iarg;
+            }
+            iarg->setName(arg->ident->toChars());
+        }
+        else if (!arg && varargs >= 0) {
+            if (varargs == 0) {
+                iarg->setName("_arguments");
+                fdecl->llvmArguments = iarg;
+            }
+            else if (varargs == 1) {
+                iarg->setName("_argptr");
+                fdecl->llvmArgPtr = iarg;
+            }
+            else
+            assert(0);
+            varargs++;
+        }
+        else {
+            iarg->setName("unnamed");
+        }
+    }
+
+    if (!declareOnly)
+        gIR->defineQueue.push_back(fdecl);
+
+    Logger::cout() << "func decl: " << *func << '\n';
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// TODO split this monster up
+void DtoDefineFunc(FuncDeclaration* fd)
+{
+    // debug info
+    if (global.params.symdebug) {
+        Module* mo = fd->getModule();
+        if (!mo->llvmCompileUnit) {
+            mo->llvmCompileUnit = DtoDwarfCompileUnit(mo,false);
+        }
+        fd->llvmDwarfSubProgram = DtoDwarfSubProgram(fd, mo->llvmCompileUnit);
+    }
+
+    Type* t = DtoDType(fd->type);
+    TypeFunction* f = (TypeFunction*)t;
+
+    assert(f->llvmType);
+    llvm::Function* func = fd->llvmIRFunc->func;
+    const llvm::FunctionType* functype = func->getFunctionType();
+
+    // only members of the current module or template instances maybe be defined
+    if (fd->getModule() == gIR->dmodule || DtoIsTemplateInstance(fd->parent))
+    {
+        fd->llvmDModule = gIR->dmodule;
+
+        // handle static constructor / destructor
+        if (fd->isStaticCtorDeclaration() || fd->isStaticDtorDeclaration()) {
+            const llvm::ArrayType* sctor_type = llvm::ArrayType::get(llvm::PointerType::get(functype),1);
+            //Logger::cout() << "static ctor type: " << *sctor_type << '\n';
+
+            llvm::Constant* sctor_func = llvm::cast<llvm::Constant>(fd->llvmValue);
+            //Logger::cout() << "static ctor func: " << *sctor_func << '\n';
+
+            llvm::Constant* sctor_init = llvm::ConstantArray::get(sctor_type,&sctor_func,1);
+
+            //Logger::cout() << "static ctor init: " << *sctor_init << '\n';
+
+            // output the llvm.global_ctors array
+            const char* varname = fd->isStaticCtorDeclaration() ? "_d_module_ctor_array" : "_d_module_dtor_array";
+            llvm::GlobalVariable* sctor_arr = new llvm::GlobalVariable(sctor_type, false, llvm::GlobalValue::AppendingLinkage, sctor_init, varname, gIR->module);
+        }
+
+        // function definition
+        if (fd->fbody != 0)
+        {
+            Logger::println("Doing function body for: %s", fd->toChars());
+            assert(fd->llvmIRFunc);
+            gIR->functions.push_back(fd->llvmIRFunc);
+
+            // this handling
+            if (f->llvmUsesThis) {
+                Logger::println("uses this");
+                if (f->llvmRetInPtr)
+                    fd->llvmThisVar = ++func->arg_begin();
+                else
+                    fd->llvmThisVar = func->arg_begin();
+                assert(fd->llvmThisVar != 0);
+            }
+
+            if (fd->isMain())
+                gIR->emitMain = true;
+
+            llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func);
+            llvm::BasicBlock* endbb = new llvm::BasicBlock("endentry",func);
+
+            //assert(gIR->scopes.empty());
+            gIR->scopes.push_back(IRScope(beginbb, endbb));
+
+                // create alloca point
+                f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb());
+                gIR->func()->allocapoint = f->llvmAllocaPoint;
+
+                // give arguments storage
+                size_t n = Argument::dim(f->parameters);
+                for (int i=0; i < n; ++i) {
+                    Argument* arg = Argument::getNth(f->parameters, i);
+                    if (arg && arg->vardecl) {
+                        VarDeclaration* vd = arg->vardecl;
+                        if (!vd->llvmNeedsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))
+                            continue;
+                        llvm::Value* a = vd->llvmValue;
+                        assert(a);
+                        std::string s(a->getName());
+                        Logger::println("giving argument '%s' storage", s.c_str());
+                        s.append("_storage");
+                        llvm::Value* v = new llvm::AllocaInst(a->getType(),s,f->llvmAllocaPoint);
+                        gIR->ir->CreateStore(a,v);
+                        vd->llvmValue = v;
+                    }
+                    else {
+                        Logger::attention("some unknown argument: %s", arg ? arg->toChars() : 0);
+                    }
+                }
+
+                // debug info
+                if (global.params.symdebug) DtoDwarfFuncStart(fd);
+
+                llvm::Value* parentNested = NULL;
+                if (FuncDeclaration* fd2 = fd->toParent()->isFuncDeclaration()) {
+                    parentNested = fd2->llvmNested;
+                }
+
+                // construct nested variables struct
+                if (!fd->llvmNestedVars.empty() || parentNested) {
+                    std::vector<const llvm::Type*> nestTypes;
+                    int j = 0;
+                    if (parentNested) {
+                        nestTypes.push_back(parentNested->getType());
+                        j++;
+                    }
+                    for (std::set<VarDeclaration*>::iterator i=fd->llvmNestedVars.begin(); i!=fd->llvmNestedVars.end(); ++i) {
+                        VarDeclaration* vd = *i;
+                        vd->llvmNestedIndex = j++;
+                        if (vd->isParameter()) {
+                            assert(vd->llvmValue);
+                            nestTypes.push_back(vd->llvmValue->getType());
+                        }
+                        else {
+                            nestTypes.push_back(DtoType(vd->type));
+                        }
+                    }
+                    const llvm::StructType* nestSType = llvm::StructType::get(nestTypes);
+                    Logger::cout() << "nested var struct has type:" << '\n' << *nestSType;
+                    fd->llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",f->llvmAllocaPoint);
+                    if (parentNested) {
+                        assert(fd->llvmThisVar);
+                        llvm::Value* ptr = gIR->ir->CreateBitCast(fd->llvmThisVar, parentNested->getType(), "tmp");
+                        gIR->ir->CreateStore(ptr, DtoGEPi(fd->llvmNested, 0,0, "tmp"));
+                    }
+                    for (std::set<VarDeclaration*>::iterator i=fd->llvmNestedVars.begin(); i!=fd->llvmNestedVars.end(); ++i) {
+                        VarDeclaration* vd = *i;
+                        if (vd->isParameter()) {
+                            gIR->ir->CreateStore(vd->llvmValue, DtoGEPi(fd->llvmNested, 0, vd->llvmNestedIndex, "tmp"));
+                            vd->llvmValue = fd->llvmNested;
+                        }
+                    }
+                }
+
+                // copy _argptr to a memory location
+                if (f->linkage == LINKd && f->varargs == 1)
+                {
+                    llvm::Value* argptrmem = new llvm::AllocaInst(fd->llvmArgPtr->getType(), "_argptrmem", gIR->topallocapoint());
+                    new llvm::StoreInst(fd->llvmArgPtr, argptrmem, gIR->scopebb());
+                    fd->llvmArgPtr = argptrmem;
+                }
+
+                // output function body
+                fd->fbody->toIR(gIR);
+
+                // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement
+                // in automatically, so we do it here.
+                if (!fd->isMain()) {
+                    if (!gIR->scopereturned()) {
+                        // pass the previous block into this block
+                        if (global.params.symdebug) DtoDwarfFuncEnd(fd);
+                        if (func->getReturnType() == llvm::Type::VoidTy) {
+                            new llvm::ReturnInst(gIR->scopebb());
+                        }
+                        else {
+                            new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), gIR->scopebb());
+                        }
+                    }
+                }
+
+                // erase alloca point
+                f->llvmAllocaPoint->eraseFromParent();
+                f->llvmAllocaPoint = 0;
+                gIR->func()->allocapoint = 0;
+
+            gIR->scopes.pop_back();
+
+            // get rid of the endentry block, it's never used
+            assert(!func->getBasicBlockList().empty());
+            func->getBasicBlockList().pop_back();
+
+            // if the last block is empty now, it must be unreachable or it's a bug somewhere else
+            // would be nice to figure out how to assert that this is correct
+            llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
+            if (lastbb->empty()) {
+                if (lastbb->getNumUses() == 0)
+                    lastbb->eraseFromParent();
+                else {
+                    new llvm::UnreachableInst(lastbb);
+                    /*if (func->getReturnType() == llvm::Type::VoidTy) {
+                        new llvm::ReturnInst(lastbb);
+                    }
+                    else {
+                        new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), lastbb);
+                    }*/
+                }
+            }
+
+            gIR->functions.pop_back();
+        }
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoMain()
+{
+    // emit main function llvm style
+    // int main(int argc, char**argv, char**env);
+
+    assert(gIR != 0);
+    IRState& ir = *gIR;
+
+    assert(ir.emitMain && ir.mainFunc);
+
+    // parameter types
+    std::vector<const llvm::Type*> pvec;
+    pvec.push_back((const llvm::Type*)llvm::Type::Int32Ty);
+    const llvm::Type* chPtrType = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty);
+    pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType));
+    pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType));
+    const llvm::Type* rettype = (const llvm::Type*)llvm::Type::Int32Ty;
+
+    llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false);
+    llvm::Function* func = new llvm::Function(functype,llvm::GlobalValue::ExternalLinkage,"main",ir.module);
+
+    llvm::BasicBlock* bb = new llvm::BasicBlock("entry",func);
+
+    // call static ctors
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_ctors");
+    llvm::Instruction* apt = new llvm::CallInst(fn,"",bb);
+
+    // call user main function
+    const llvm::FunctionType* mainty = ir.mainFunc->getFunctionType();
+    llvm::CallInst* call;
+    if (mainty->getNumParams() > 0)
+    {
+        // main with arguments
+        assert(mainty->getNumParams() == 1);
+        std::vector<llvm::Value*> args;
+        llvm::Function* mfn = LLVM_D_GetRuntimeFunction(ir.module,"_d_main_args");
+
+        llvm::Function::arg_iterator argi = func->arg_begin();
+        args.push_back(argi++);
+        args.push_back(argi++);
+
+        const llvm::Type* at = mainty->getParamType(0)->getContainedType(0);
+        llvm::Value* arr = new llvm::AllocaInst(at->getContainedType(1)->getContainedType(0), func->arg_begin(), "argstorage", apt);
+        llvm::Value* a = new llvm::AllocaInst(at, "argarray", apt);
+        llvm::Value* ptr = DtoGEPi(a,0,0,"tmp",bb);
+        llvm::Value* v = args[0];
+        if (v->getType() != DtoSize_t())
+            v = new llvm::ZExtInst(v, DtoSize_t(), "tmp", bb);
+        new llvm::StoreInst(v,ptr,bb);
+        ptr = DtoGEPi(a,0,1,"tmp",bb);
+        new llvm::StoreInst(arr,ptr,bb);
+        args.push_back(a);
+        new llvm::CallInst(mfn, args.begin(), args.end(), "", bb);
+        call = new llvm::CallInst(ir.mainFunc,a,"ret",bb);
+    }
+    else
+    {
+        // main with no arguments
+        call = new llvm::CallInst(ir.mainFunc,"ret",bb);
+    }
+    call->setCallingConv(ir.mainFunc->getCallingConv());
+
+    // call static dtors
+    fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_dtors");
+    new llvm::CallInst(fn,"",bb);
+
+    // return
+    new llvm::ReturnInst(call,bb);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/functions.h	Fri Nov 16 08:21:47 2007 +0100
@@ -0,0 +1,12 @@
+#ifndef LLVMDC_GEN_FUNCTIONS_H
+#define LLVMDC_GEN_FUNCTIONS_H
+
+const llvm::FunctionType* DtoFunctionType(Type* t, const llvm::Type* thistype, bool ismain = false);
+const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl);
+
+void DtoDeclareFunction(FuncDeclaration* fdecl);
+void DtoDefineFunc(FuncDeclaration* fd);
+
+void DtoMain();
+
+#endif
--- a/gen/irstate.cpp	Thu Nov 15 00:24:44 2007 +0100
+++ b/gen/irstate.cpp	Fri Nov 16 08:21:47 2007 +0100
@@ -40,7 +40,7 @@
     ir.state = this;
 }
 
-IRFunction& IRState::func()
+IRFunction* IRState::func()
 {
     assert(!functions.empty() && "Function stack is empty!");
     return functions.back();
@@ -49,22 +49,22 @@
 llvm::Function* IRState::topfunc()
 {
     assert(!functions.empty() && "Function stack is empty!");
-    return functions.back().func;
+    return functions.back()->func;
 }
 
 TypeFunction* IRState::topfunctype()
 {
     assert(!functions.empty() && "Function stack is empty!");
-    return functions.back().type;
+    return functions.back()->type;
 }
 
 llvm::Instruction* IRState::topallocapoint()
 {
     assert(!functions.empty() && "AllocaPoint stack is empty!");
-    return functions.back().allocapoint;
+    return functions.back()->allocapoint;
 }
 
-IRStruct& IRState::topstruct()
+IRStruct* IRState::topstruct()
 {
     assert(!structs.empty() && "Struct vector is empty!");
     return structs.back();
@@ -109,14 +109,16 @@
  : recty(llvm::OpaqueType::get())
 {
     type = 0;
-    queueFuncs = true;
+    defined = false;
+    constinited = false;
 }
 
 IRStruct::IRStruct(Type* t)
  : recty(llvm::OpaqueType::get())
 {
     type = t;
-    queueFuncs = true;
+    defined = false;
+    constinited = false;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -153,6 +155,7 @@
     func = NULL;
     allocapoint = NULL;
     finallyretval = NULL;
+    defined = false;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -169,3 +172,11 @@
     e2 = r;
     v = val;
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+IRGlobal::IRGlobal(VarDeclaration* v) :
+    type(llvm::OpaqueType::get())
+{
+    var = v;
+}
--- a/gen/irstate.h	Thu Nov 15 00:24:44 2007 +0100
+++ b/gen/irstate.h	Fri Nov 16 08:21:47 2007 +0100
@@ -39,19 +39,20 @@
 };
 
 // represents a struct or class
-struct IRStruct
+struct IRStruct : Object
 {
     struct Offset
     {
         VarDeclaration* var;
+        const llvm::Type* type;
         llvm::Constant* init;
 
-        Offset(VarDeclaration* v, llvm::Constant* i)
-        : var(v), init(i) {}
+        Offset(VarDeclaration* v, const llvm::Type* ty)
+        : var(v), type(ty), init(NULL) {}
     };
 
-    typedef std::vector<FuncDeclaration*> FuncDeclVector;
     typedef std::multimap<unsigned, Offset> OffsetMap;
+    typedef std::vector<VarDeclaration*> VarDeclVector;
 
 public:
     IRStruct();
@@ -59,10 +60,11 @@
 
     Type* type;
     llvm::PATypeHolder recty;
-    FuncDeclVector funcs;
-    bool queueFuncs;
+    OffsetMap offsets;
+    VarDeclVector defaultFields;
 
-    OffsetMap offsets;
+    bool defined;
+    bool constinited;
 };
 
 // represents a finally block
@@ -76,7 +78,7 @@
 };
 
 // represents a function
-struct IRFunction
+struct IRFunction : Object
 {
     llvm::Function* func;
     llvm::Instruction* allocapoint;
@@ -88,6 +90,8 @@
     FinallyVec finallys;
     llvm::Value* finallyretval;
 
+    bool defined;
+
     IRFunction(FuncDeclaration*);
 };
 
@@ -106,6 +110,15 @@
     IRExp(Expression* l, Expression* r, DValue* val);
 };
 
+// represents a global variable
+struct IRGlobal : Object
+{
+    VarDeclaration* var;
+    llvm::PATypeHolder type;
+
+    IRGlobal(VarDeclaration* v);
+};
+
 // represents the module
 struct IRState
 {
@@ -116,18 +129,18 @@
     llvm::Module* module;
 
     // functions
-    typedef std::vector<IRFunction> FunctionVector;
+    typedef std::vector<IRFunction*> FunctionVector;
     FunctionVector functions;
-    IRFunction& func();
+    IRFunction* func();
 
     llvm::Function* topfunc();
     TypeFunction* topfunctype();
     llvm::Instruction* topallocapoint();
 
     // structs
-    typedef std::vector<IRStruct> StructVector;
+    typedef std::vector<IRStruct*> StructVector;
     StructVector structs;
-    IRStruct& topstruct();
+    IRStruct* topstruct();
 
     // classes TODO move into IRClass
     typedef std::vector<ClassDeclaration*> ClassDeclVec;
@@ -163,9 +176,11 @@
     // builder helper
     IRBuilderHelper ir;
 
-    // functions queued for lazy definition
-    typedef std::vector<FuncDeclaration*> FuncDeclVector;
-    FuncDeclVector funcQueue;
+    typedef std::vector<Dsymbol*> DsymbolVector;
+    // dsymbols that need constant initializers constructed
+    DsymbolVector constInitQueue;
+    // dsymbols that need definitions (symbols in current module)
+    DsymbolVector defineQueue;
 };
 
 #endif // LLVMDC_GEN_IRSTATE_H
--- a/gen/statements.cpp	Thu Nov 15 00:24:44 2007 +0100
+++ b/gen/statements.cpp	Fri Nov 16 08:21:47 2007 +0100
@@ -71,9 +71,9 @@
             if (!e->inPlace())
                 DtoAssign(rvar, e);
 
-            IRFunction::FinallyVec& fin = p->func().finallys;
+            IRFunction::FinallyVec& fin = p->func()->finallys;
             if (fin.empty()) {
-                if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
+                if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
                 new llvm::ReturnInst(p->scopebb());
             }
             else {
@@ -87,15 +87,15 @@
             delete e;
             Logger::cout() << "return value is '" <<*v << "'\n";
 
-            IRFunction::FinallyVec& fin = p->func().finallys;
+            IRFunction::FinallyVec& fin = p->func()->finallys;
             if (fin.empty()) {
-                if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
+                if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
                 new llvm::ReturnInst(v, p->scopebb());
             }
             else {
-                if (!p->func().finallyretval)
-                    p->func().finallyretval = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint());
-                llvm::Value* rettmp = p->func().finallyretval;
+                if (!p->func()->finallyretval)
+                    p->func()->finallyretval = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint());
+                llvm::Value* rettmp = p->func()->finallyretval;
                 new llvm::StoreInst(v,rettmp,p->scopebb());
                 new llvm::BranchInst(fin.back().retbb, p->scopebb());
             }
@@ -104,9 +104,9 @@
     else
     {
         if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
-            IRFunction::FinallyVec& fin = p->func().finallys;
+            IRFunction::FinallyVec& fin = p->func()->finallys;
             if (fin.empty()) {
-                if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
+                if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
                 new llvm::ReturnInst(p->scopebb());
             }
             else {
@@ -420,8 +420,8 @@
 
     // do the try block
     p->scope() = IRScope(trybb,finallybb);
-    gIR->func().finallys.push_back(IRFinally(finallybb,finallyretbb));
-    IRFinally& fin = p->func().finallys.back();
+    gIR->func()->finallys.push_back(IRFinally(finallybb,finallyretbb));
+    IRFinally& fin = p->func()->finallys.back();
 
     assert(body);
     body->toIR(p);
@@ -446,22 +446,22 @@
     finalbody->toIR(p); // hope this will work, otherwise it's time it gets fixed
 
     // terminate finally (return path)
-    size_t nfin = p->func().finallys.size();
+    size_t nfin = p->func()->finallys.size();
     if (nfin > 1) {
-        IRFinally& ofin = p->func().finallys[nfin-2];
+        IRFinally& ofin = p->func()->finallys[nfin-2];
         p->ir->CreateBr(ofin.retbb);
     }
     // no outer
     else
     {
-        if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
-        llvm::Value* retval = p->func().finallyretval;
+        if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
+        llvm::Value* retval = p->func()->finallyretval;
         if (retval) {
             retval = p->ir->CreateLoad(retval,"tmp");
             p->ir->CreateRet(retval);
         }
         else {
-            FuncDeclaration* fd = p->func().decl;
+            FuncDeclaration* fd = p->func()->decl;
             if (fd->isMain()) {
                 assert(fd->type->next->ty == Tvoid);
                 p->ir->CreateRet(DtoConstInt(0));
@@ -473,7 +473,7 @@
     }
 
     // rewrite the scope
-    p->func().finallys.pop_back();
+    p->func()->finallys.pop_back();
     p->scope() = IRScope(endbb,oldend);
 }
 
--- a/gen/structs.cpp	Thu Nov 15 00:24:44 2007 +0100
+++ b/gen/structs.cpp	Fri Nov 16 08:21:47 2007 +0100
@@ -78,7 +78,9 @@
     Logger::println("DtoConstStructInitializer: %s", si->toChars());
     LOG_SCOPE;
 
-    const llvm::StructType* structtype = isaStruct(si->ad->llvmType);
+    TypeStruct* ts = (TypeStruct*)si->ad->type;
+
+    const llvm::StructType* structtype = isaStruct(ts->llvmType->get());
     Logger::cout() << "llvm struct type: " << *structtype << '\n';
 
     assert(si->value.dim == si->vars.dim);
@@ -160,6 +162,231 @@
     ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
     return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoDeclareStruct(StructDeclaration* sd)
+{
+    if (sd->llvmTouched) return;
+    sd->llvmTouched = true;
+
+    Logger::println("DtoDeclareStruct(%s)", sd->toChars());
+    LOG_SCOPE;
+
+    TypeStruct* ts = (TypeStruct*)DtoDType(sd->type);
+
+    IRStruct* irstruct = new IRStruct(ts);
+    sd->llvmIRStruct = irstruct;
+    gIR->structs.push_back(irstruct);
+
+    for (int k=0; k < sd->members->dim; k++) {
+        Dsymbol* dsym = (Dsymbol*)(sd->members->data[k]);
+        dsym->toObjFile();
+    }
+
+    Logger::println("doing struct fields");
+
+    const llvm::StructType* structtype = 0;
+    std::vector<const llvm::Type*> fieldtypes;
+
+    if (irstruct->offsets.empty())
+    {
+        Logger::println("has no fields");
+        fieldtypes.push_back(llvm::Type::Int8Ty);
+        structtype = llvm::StructType::get(fieldtypes);
+    }
+    else
+    {
+        Logger::println("has fields");
+        unsigned prevsize = (unsigned)-1;
+        unsigned lastoffset = (unsigned)-1;
+        const llvm::Type* 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 = gTargetData->getTypeSize(fieldtype);
+                i->second.var->llvmFieldIndex = idx;
+            }
+            // colliding offset?
+            else if (lastoffset == i->first) {
+                size_t s = gTargetData->getTypeSize(i->second.type);
+                if (s > prevsize) {
+                    fieldpad += s - prevsize;
+                    prevsize = s;
+                }
+                sd->llvmHasUnions = true;
+                i->second.var->llvmFieldIndex = idx;
+            }
+            // intersecting offset?
+            else if (i->first < (lastoffset + prevsize)) {
+                size_t s = gTargetData->getTypeSize(i->second.type);
+                assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
+                sd->llvmHasUnions = true;
+                i->second.var->llvmFieldIndex = idx;
+                i->second.var->llvmFieldIndexOffset = (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(llvm::Type::Int8Ty, fieldpad));
+                    irstruct->defaultFields.push_back(NULL);
+                    idx++;
+                }
+
+                idx++;
+
+                // start new
+                lastoffset = i->first;
+                fieldtype = i->second.type;
+                fieldinit = i->second.var;
+                prevsize = gTargetData->getTypeSize(fieldtype);
+                i->second.var->llvmFieldIndex = idx;
+                fieldpad = 0;
+            }
+        }
+        fieldtypes.push_back(fieldtype);
+        irstruct->defaultFields.push_back(fieldinit);
+        if (fieldpad) {
+            fieldtypes.push_back(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad));
+            irstruct->defaultFields.push_back(NULL);
+        }
+
+        Logger::println("creating struct type");
+        structtype = llvm::StructType::get(fieldtypes);
+    }
+
+    // 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->llvmType == 0);
+    ts->llvmType = new llvm::PATypeHolder(structtype);
+
+    if (sd->parent->isModule()) {
+        gIR->module->addTypeName(sd->mangle(),structtype);
+    }
+
+    std::string initname("_D");
+    initname.append(sd->mangle());
+    initname.append("6__initZ");
+
+    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
+    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module);
+    ts->llvmInit = initvar;
+
+    gIR->structs.pop_back();
+
+    gIR->constInitQueue.push_back(sd);
+    if (sd->getModule() == gIR->dmodule)
+        gIR->defineQueue.push_back(sd);
+
+    // declare typeinfo
+    if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMnotypeinfo)
+        sd->type->getTypeInfo(NULL);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoConstInitStruct(StructDeclaration* sd)
+{
+    IRStruct* irstruct = sd->llvmIRStruct;
+    if (irstruct->constinited) return;
+    irstruct->constinited = true;
+
+    Logger::println("DtoConstInitStruct(%s)", sd->toChars());
+    LOG_SCOPE;
+
+    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;
+        llvm::Constant* finit = DtoConstFieldInitializer(so->var->type, so->var->init);
+        so->init = finit;
+        so->var->llvmConstInit = finit;
+    }
+
+    const llvm::StructType* structtype = isaStruct(sd->type->llvmType->get());
+
+    // go through the field inits and build the default initializer
+    std::vector<llvm::Constant*> fieldinits_ll;
+    size_t nfi = irstruct->defaultFields.size();
+    for (size_t i=0; i<nfi; ++i) {
+        llvm::Constant* c;
+        if (irstruct->defaultFields[i] != NULL) {
+            c = irstruct->defaultFields[i]->llvmConstInit;
+            assert(c);
+        }
+        else {
+            const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i));
+            std::vector<llvm::Constant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
+            c = llvm::ConstantArray::get(arrty, vals);
+        }
+        fieldinits_ll.push_back(c);
+    }
+
+    // generate the union mapper
+    sd->llvmUnion = new DUnion; // uses gIR->topstruct()
+
+    // always generate the constant initalizer
+    if (!sd->zeroInit) {
+        Logger::println("Not zero initialized");
+        //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
+        sd->llvmInitZ = llvm::ConstantStruct::get(structtype,fieldinits_ll);
+    }
+    else {
+        Logger::println("Zero initialized");
+        sd->llvmInitZ = llvm::ConstantAggregateZero::get(structtype);
+    }
+
+    gIR->structs.pop_back();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoDefineStruct(StructDeclaration* sd)
+{
+    IRStruct* irstruct = sd->llvmIRStruct;
+    if (irstruct->defined) return;
+    irstruct->defined = true;
+
+    DtoConstInitStruct(sd);
+
+    Logger::println("DtoDefineStruct(%s)", sd->toChars());
+    LOG_SCOPE;
+
+    assert(sd->type->ty == Tstruct);
+    TypeStruct* ts = (TypeStruct*)sd->type;
+    ts->llvmInit->setInitializer(sd->llvmInitZ);
+
+    sd->llvmDModule = gIR->dmodule;
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////   D UNION HELPER CLASS   ////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -167,9 +394,9 @@
 DUnion::DUnion()
 {
     DUnionField* f = NULL;
-    IRStruct& topstruct = gIR->topstruct();
+    IRStruct* topstruct = gIR->topstruct();
     bool unions = false;
-    for (IRStruct::OffsetMap::iterator i=topstruct.offsets.begin(); i!=topstruct.offsets.end(); ++i)
+    for (IRStruct::OffsetMap::iterator i=topstruct->offsets.begin(); i!=topstruct->offsets.end(); ++i)
     {
         unsigned o = i->first;
         IRStruct::Offset* so = &i->second;
--- a/gen/structs.h	Thu Nov 15 00:24:44 2007 +0100
+++ b/gen/structs.h	Fri Nov 16 08:21:47 2007 +0100
@@ -2,10 +2,29 @@
 #define LLVMD_GEN_STRUCTS_H
 
 struct StructInitializer;
+
 const llvm::Type* DtoStructType(Type* t);
+
 llvm::Value* DtoStructZeroInit(llvm::Value* v);
 llvm::Value* DtoStructCopy(llvm::Value* dst, llvm::Value* src);
+
 llvm::Constant* DtoConstStructInitializer(StructInitializer* si);
+
+/**
+ * Provides the llvm declaration for a struct
+ */
+void DtoDeclareStruct(StructDeclaration* sd);
+
+/**
+ * Constructs the constant default initializer a struct
+ */
+void DtoConstInitStruct(StructDeclaration* sd);
+
+/**
+ * Provides the llvm definition for a struct
+ */
+void DtoDefineStruct(StructDeclaration* sd);
+
 llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs);
 
 struct DUnionField
--- a/gen/toir.cpp	Thu Nov 15 00:24:44 2007 +0100
+++ b/gen/toir.cpp	Fri Nov 16 08:21:47 2007 +0100
@@ -26,6 +26,7 @@
 #include "gen/runtime.h"
 #include "gen/arrays.h"
 #include "gen/structs.h"
+#include "gen/classes.h"
 
 #include "gen/dvalue.h"
 
@@ -52,7 +53,7 @@
             // referenced by nested delegate?
             if (vd->nestedref) {
                 Logger::println("has nestedref set");
-                vd->llvmValue = p->func().decl->llvmNested;
+                vd->llvmValue = p->func()->decl->llvmNested;
                 assert(vd->llvmValue);
                 assert(vd->llvmNestedIndex >= 0);
             }
@@ -119,7 +120,7 @@
         {
             Logger::println("Id::_arguments");
             if (!vd->llvmValue)
-                vd->llvmValue = p->func().decl->llvmArguments;
+                vd->llvmValue = p->func()->decl->llvmArguments;
             assert(vd->llvmValue);
             return new DVarValue(vd, vd->llvmValue, true);
         }
@@ -128,7 +129,7 @@
         {
             Logger::println("Id::_argptr");
             if (!vd->llvmValue)
-                vd->llvmValue = p->func().decl->llvmArgPtr;
+                vd->llvmValue = p->func()->decl->llvmArgPtr;
             assert(vd->llvmValue);
             return new DVarValue(vd, vd->llvmValue, true);
         }
@@ -154,6 +155,13 @@
                 m = tid->llvmValue;
             return new DVarValue(vd, m, true);
         }
+        // classinfo
+        else if (ClassInfoDeclaration* cid = vd->isClassInfoDeclaration())
+        {
+            Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars());
+            assert(cid->cd->llvmClass);
+            return new DVarValue(vd, cid->cd->llvmClass, true);
+        }
         // nested variable
         else if (vd->nestedref) {
             Logger::println("nested variable");
@@ -165,7 +173,7 @@
             if (!vd->llvmValue) {
                 // TODO: determine this properly
                 // this happens when the DMD frontend generates by pointer wrappers for struct opEquals(S) and opCmp(S)
-                vd->llvmValue = &p->func().func->getArgumentList().back();
+                vd->llvmValue = &p->func()->func->getArgumentList().back();
             }
             if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa<llvm::AllocaInst>(vd->llvmValue)) {
                 return new DVarValue(vd, vd->llvmValue, true);
@@ -177,9 +185,11 @@
         }
         else {
             // take care of forward references of global variables
-            if (!vd->llvmTouched && (vd->isDataseg() || (vd->storage_class & STCextern))) // !vd->onstack)
+            if (vd->isDataseg() || (vd->storage_class & STCextern)) {
                 vd->toObjFile();
-            if (!vd->llvmValue) {
+                DtoConstInitGlobal(vd);
+            }
+            if (!vd->llvmValue || vd->llvmValue->getType()->isAbstract()) {
                 Logger::println("global variable not resolved :/ %s", vd->toChars());
                 assert(0);
             }
@@ -224,6 +234,8 @@
         Logger::print("Sym: type=%s\n", sdecltype->toChars());
         assert(sdecltype->ty == Tstruct);
         TypeStruct* ts = (TypeStruct*)sdecltype;
+        ts->sym->toObjFile();
+        DtoConstInitStruct(ts->sym);
         assert(ts->sym->llvmInitZ);
         return ts->sym->llvmInitZ;
     }
@@ -1220,7 +1232,7 @@
     // nested call
     else if (dfn && dfn->func && dfn->func->isNested()) {
         Logger::println("Nested Call");
-        llvm::Value* contextptr = p->func().decl->llvmNested;
+        llvm::Value* contextptr = p->func()->decl->llvmNested;
         assert(contextptr);
         llargs[j] = p->ir->CreateBitCast(contextptr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
         ++j;
@@ -1330,6 +1342,9 @@
     else if (dfn && dfn->cc != (unsigned)-1) {
         call->setCallingConv(dfn->cc);
     }
+    else if (llvm::isa<llvm::LoadInst>(funcval)) {
+        call->setCallingConv(DtoCallingConv(dlink));
+    }
 
     return new DImValue(type, retllval, isInPlace);
 }
@@ -1445,9 +1460,8 @@
     DValue* v = e1->toElem(p);
     if (v->isField())
         return v;
-    if (DFuncValue* fv = v->isFunc())
-    {
-        Logger::println("FuncDeclaration");
+    else if (DFuncValue* fv = v->isFunc()) {
+        //Logger::println("FuncDeclaration");
         FuncDeclaration* fd = fv->func;
         assert(fd);
         if (fd->llvmValue == 0)
@@ -1562,7 +1576,7 @@
     LOG_SCOPE;
 
     if (VarDeclaration* vd = var->isVarDeclaration()) {
-        llvm::Value* v = p->func().decl->llvmThisVar;
+        llvm::Value* v = p->func()->decl->llvmThisVar;
         if (llvm::isa<llvm::AllocaInst>(v))
             v = new llvm::LoadInst(v, "tmp", p->scopebb());
         return new DThisValue(vd, v);
@@ -2023,7 +2037,9 @@
                 llvm::Value* a = DtoArgument(fn->getFunctionType()->getParamType(i+1), fnarg, ex);
                 ctorargs.push_back(a);
             }
-            emem = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb());
+            llvm::CallInst* call = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb());
+            call->setCallingConv(DtoCallingConv(LINKd));
+            emem = call;
         }
     }
     else if (ntype->ty == Tstruct) {
@@ -2505,7 +2521,7 @@
 
     llvm::Value* context = DtoGEPi(lval,0,0,"tmp",p->scopebb());
     const llvm::PointerType* pty = isaPointer(context->getType()->getContainedType(0));
-    llvm::Value* llvmNested = p->func().decl->llvmNested;
+    llvm::Value* llvmNested = p->func()->decl->llvmNested;
     if (llvmNested == NULL) {
         llvm::Value* nullcontext = llvm::ConstantPointerNull::get(pty);
         p->ir->CreateStore(nullcontext, context);
@@ -2539,6 +2555,8 @@
     Logger::cout() << "array literal has llvm type: " << *t << '\n';
 
     llvm::Value* mem = 0;
+    bool inplace_slice = false;
+
     if (!p->topexp() || p->topexp()->e2 != this) {
         assert(DtoDType(type)->ty == Tsarray);
         mem = new llvm::AllocaInst(t,"arrayliteral",p->topallocapoint());
@@ -2548,6 +2566,7 @@
         if (DSliceValue* sv = tlv->isSlice()) {
             assert(sv->len == 0);
             mem = sv->ptr;
+            inplace_slice = true;
         }
         else {
             mem = p->topexp()->v->getLVal();
@@ -2556,6 +2575,7 @@
         if (!isaPointer(mem->getType()) ||
             !isaArray(mem->getType()->getContainedType(0)))
         {
+            assert(!inplace_slice);
             assert(ty->ty == Tarray);
             // we need to give this array literal storage
             const llvm::ArrayType* arrty = llvm::ArrayType::get(DtoType(ty->next), elements->dim);
@@ -2582,7 +2602,7 @@
         }
     }
 
-    if (ty->ty == Tsarray)
+    if (ty->ty == Tsarray || (ty->ty == Tarray && inplace_slice))
         return new DImValue(type, mem, true);
     else if (ty->ty == Tarray)
         return new DSliceValue(type, DtoConstSize_t(elements->dim), DtoGEPi(mem,0,0,"tmp"));
--- a/gen/tollvm.cpp	Thu Nov 15 00:24:44 2007 +0100
+++ b/gen/tollvm.cpp	Fri Nov 16 08:21:47 2007 +0100
@@ -14,7 +14,9 @@
 #include "gen/runtime.h"
 #include "gen/arrays.h"
 #include "gen/dvalue.h"
+#include "gen/functions.h"
 #include "gen/structs.h"
+#include "gen/classes.h"
 
 bool DtoIsPassedByRef(Type* type)
 {
@@ -95,17 +97,16 @@
 
     // aggregates
     case Tstruct:    {
-        if (t->llvmType == 0)
-        {
+        if (!t->llvmType || *t->llvmType == NULL) {
             // recursive or cyclic declaration
             if (!gIR->structs.empty())
             {
                 IRStruct* found = 0;
                 for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i)
                 {
-                    if (t == i->type)
+                    if (t == (*i)->type)
                     {
-                        return i->recty.get();
+                        return (*i)->recty.get();
                     }
                 }
             }
@@ -115,21 +116,20 @@
             assert(ts->sym);
             ts->sym->toObjFile();
         }
-        return t->llvmType;
+        return t->llvmType->get();
     }
 
     case Tclass:    {
-        if (t->llvmType == 0)
-        {
+        if (!t->llvmType || *t->llvmType == NULL) {
             // recursive or cyclic declaration
             if (!gIR->structs.empty())
             {
                 IRStruct* found = 0;
                 for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i)
                 {
-                    if (t == i->type)
+                    if (t == (*i)->type)
                     {
-                        return llvm::PointerType::get(i->recty.get());
+                        return llvm::PointerType::get((*i)->recty.get());
                     }
                 }
             }
@@ -139,28 +139,28 @@
             assert(tc->sym);
             tc->sym->toObjFile();
         }
-        return llvm::PointerType::get(t->llvmType);
+        return llvm::PointerType::get(t->llvmType->get());
     }
 
     // functions
     case Tfunction:
     {
-        if (t->llvmType == 0) {
+        if (!t->llvmType || *t->llvmType == NULL) {
             return DtoFunctionType(t,NULL);
         }
         else {
-            return t->llvmType;
+            return t->llvmType->get();
         }
     }
 
     // delegates
     case Tdelegate:
     {
-        if (t->llvmType == 0) {
+        if (!t->llvmType || *t->llvmType == NULL) {
             return DtoDelegateType(t);
         }
         else {
-            return t->llvmType;
+            return t->llvmType->get();
         }
     }
 
@@ -183,181 +183,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype, bool ismain)
-{
-    TypeFunction* f = (TypeFunction*)type;
-    assert(f != 0);
-
-    bool typesafeVararg = false;
-    if (f->linkage == LINKd && f->varargs == 1) {
-        typesafeVararg = true;
-    }
-
-    // return value type
-    const llvm::Type* rettype;
-    const llvm::Type* actualRettype;
-    Type* rt = f->next;
-    bool retinptr = false;
-    bool usesthis = false;
-
-    if (ismain) {
-        rettype = llvm::Type::Int32Ty;
-        actualRettype = rettype;
-    }
-    else {
-        assert(rt);
-        if (DtoIsPassedByRef(rt)) {
-            rettype = llvm::PointerType::get(DtoType(rt));
-            actualRettype = llvm::Type::VoidTy;
-            f->llvmRetInPtr = retinptr = true;
-        }
-        else {
-            rettype = DtoType(rt);
-            actualRettype = rettype;
-        }
-    }
-
-    // parameter types
-    std::vector<const llvm::Type*> paramvec;
-
-    if (retinptr) {
-        Logger::cout() << "returning through pointer parameter: " << *rettype << '\n';
-        paramvec.push_back(rettype);
-    }
-
-    if (thistype) {
-        paramvec.push_back(thistype);
-        usesthis = true;
-    }
-
-    if (typesafeVararg) {
-        ClassDeclaration* ti = Type::typeinfo;
-        if (!ti->llvmInitZ)
-            ti->toObjFile();
-        assert(ti->llvmInitZ);
-        std::vector<const llvm::Type*> types;
-        types.push_back(DtoSize_t());
-        types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmInitZ->getType())));
-        const llvm::Type* t1 = llvm::StructType::get(types);
-        paramvec.push_back(llvm::PointerType::get(t1));
-        paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
-    }
-
-    size_t n = Argument::dim(f->parameters);
-
-    for (int i=0; i < n; ++i) {
-        Argument* arg = Argument::getNth(f->parameters, i);
-        // ensure scalar
-        Type* argT = DtoDType(arg->type);
-        assert(argT);
-
-        if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
-            //assert(arg->vardecl);
-            //arg->vardecl->refparam = true;
-        }
-        else
-            arg->llvmCopy = true;
-
-        const llvm::Type* at = DtoType(argT);
-        if (isaStruct(at)) {
-            Logger::println("struct param");
-            paramvec.push_back(llvm::PointerType::get(at));
-        }
-        else if (isaArray(at)) {
-            Logger::println("sarray param");
-            assert(argT->ty == Tsarray);
-            //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0)));
-            paramvec.push_back(llvm::PointerType::get(at));
-        }
-        else if (llvm::isa<llvm::OpaqueType>(at)) {
-            Logger::println("opaque param");
-            assert(argT->ty == Tstruct || argT->ty == Tclass);
-            paramvec.push_back(llvm::PointerType::get(at));
-        }
-        else {
-            if (!arg->llvmCopy) {
-                Logger::println("ref param");
-                at = llvm::PointerType::get(at);
-            }
-            else {
-                Logger::println("in param");
-            }
-            paramvec.push_back(at);
-        }
-    }
-
-    // construct function type
-    bool isvararg = !typesafeVararg && f->varargs;
-    llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
-
-    f->llvmRetInPtr = retinptr;
-    f->llvmUsesThis = usesthis;
-    return functype;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
-{
-    TypeFunction* f = (TypeFunction*)fdecl->type;
-    assert(f != 0);
-
-    const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
-    std::vector<const llvm::Type*> args;
-
-    if (fdecl->llvmInternal == LLVMva_start) {
-        args.push_back(i8pty);
-    }
-    else if (fdecl->llvmInternal == LLVMva_intrinsic) {
-        size_t n = Argument::dim(f->parameters);
-        for (size_t i=0; i<n; ++i) {
-            args.push_back(i8pty);
-        }
-    }
-    else
-    assert(0);
-
-    const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
-    f->llvmType = fty;
-    return fty;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
-{
-    if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
-        return DtoVaFunctionType(fdecl);
-    }
-
-    // type has already been resolved
-    if (fdecl->type->llvmType != 0) {
-        return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType);
-    }
-
-    const llvm::Type* thisty = NULL;
-    if (fdecl->needThis()) {
-        if (AggregateDeclaration* ad = fdecl->isMember()) {
-            Logger::print("isMember = this is: %s\n", ad->type->toChars());
-            thisty = DtoType(ad->type);
-            Logger::cout() << "this llvm type: " << *thisty << '\n';
-            if (isaStruct(thisty) || thisty == gIR->topstruct().recty.get())
-                thisty = llvm::PointerType::get(thisty);
-        }
-        else
-        assert(0);
-    }
-    else if (fdecl->isNested()) {
-        thisty = llvm::PointerType::get(llvm::Type::Int8Ty);
-    }
-
-    const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain());
-    fdecl->type->llvmType = functype;
-    return functype;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 const llvm::StructType* DtoDelegateType(Type* t)
 {
     const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty);
@@ -630,131 +455,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoMain()
-{
-    // emit main function llvm style
-    // int main(int argc, char**argv, char**env);
-
-    assert(gIR != 0);
-    IRState& ir = *gIR;
-
-    assert(ir.emitMain && ir.mainFunc);
-
-    // parameter types
-    std::vector<const llvm::Type*> pvec;
-    pvec.push_back((const llvm::Type*)llvm::Type::Int32Ty);
-    const llvm::Type* chPtrType = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty);
-    pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType));
-    pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType));
-    const llvm::Type* rettype = (const llvm::Type*)llvm::Type::Int32Ty;
-
-    llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false);
-    llvm::Function* func = new llvm::Function(functype,llvm::GlobalValue::ExternalLinkage,"main",ir.module);
-
-    llvm::BasicBlock* bb = new llvm::BasicBlock("entry",func);
-
-    // call static ctors
-    llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_ctors");
-    llvm::Instruction* apt = new llvm::CallInst(fn,"",bb);
-
-    // call user main function
-    const llvm::FunctionType* mainty = ir.mainFunc->getFunctionType();
-    llvm::CallInst* call;
-    if (mainty->getNumParams() > 0)
-    {
-        // main with arguments
-        assert(mainty->getNumParams() == 1);
-        std::vector<llvm::Value*> args;
-        llvm::Function* mfn = LLVM_D_GetRuntimeFunction(ir.module,"_d_main_args");
-
-        llvm::Function::arg_iterator argi = func->arg_begin();
-        args.push_back(argi++);
-        args.push_back(argi++);
-
-        const llvm::Type* at = mainty->getParamType(0)->getContainedType(0);
-        llvm::Value* arr = new llvm::AllocaInst(at->getContainedType(1)->getContainedType(0), func->arg_begin(), "argstorage", apt);
-        llvm::Value* a = new llvm::AllocaInst(at, "argarray", apt);
-        llvm::Value* ptr = DtoGEPi(a,0,0,"tmp",bb);
-        llvm::Value* v = args[0];
-        if (v->getType() != DtoSize_t())
-            v = new llvm::ZExtInst(v, DtoSize_t(), "tmp", bb);
-        new llvm::StoreInst(v,ptr,bb);
-        ptr = DtoGEPi(a,0,1,"tmp",bb);
-        new llvm::StoreInst(arr,ptr,bb);
-        args.push_back(a);
-        new llvm::CallInst(mfn, args.begin(), args.end(), "", bb);
-        call = new llvm::CallInst(ir.mainFunc,a,"ret",bb);
-    }
-    else
-    {
-        // main with no arguments
-        call = new llvm::CallInst(ir.mainFunc,"ret",bb);
-    }
-    call->setCallingConv(ir.mainFunc->getCallingConv());
-
-    // call static dtors
-    fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_dtors");
-    new llvm::CallInst(fn,"",bb);
-
-    // return
-    new llvm::ReturnInst(call,bb);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance)
-{
-    Array* arr = &tc->sym->dtors;
-    for (size_t i=0; i<arr->dim; i++)
-    {
-        FuncDeclaration* fd = (FuncDeclaration*)arr->data[i];
-        assert(fd->llvmValue);
-        new llvm::CallInst(fd->llvmValue, instance, "", gIR->scopebb());
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoInitClass(TypeClass* tc, llvm::Value* dst)
-{
-    assert(gIR);
-
-    assert(tc->llvmType);
-    uint64_t size_t_size = gTargetData->getTypeSize(DtoSize_t());
-    uint64_t n = gTargetData->getTypeSize(tc->llvmType) - size_t_size;
-
-    // set vtable field
-    llvm::Value* vtblvar = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
-    assert(tc->sym->llvmVtbl);
-    new llvm::StoreInst(tc->sym->llvmVtbl, vtblvar, gIR->scopebb());
-
-    // copy the static initializer
-    if (n > 0) {
-        assert(tc->llvmInit);
-        assert(dst->getType() == tc->llvmInit->getType());
-
-        llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
-
-        llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
-        dstarr = DtoGEPi(dstarr,size_t_size,"tmp",gIR->scopebb());
-
-        llvm::Value* srcarr = new llvm::BitCastInst(tc->llvmInit,arrty,"tmp",gIR->scopebb());
-        srcarr = DtoGEPi(srcarr,size_t_size,"tmp",gIR->scopebb());
-
-        llvm::Function* fn = LLVM_DeclareMemCpy32();
-        std::vector<llvm::Value*> llargs;
-        llargs.resize(4);
-        llargs[0] = dstarr;
-        llargs[1] = srcarr;
-        llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
-        llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-        new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 llvm::Constant* DtoConstInitializer(Type* type, Initializer* init)
 {
     llvm::Constant* _init = 0; // may return zero
@@ -792,6 +492,54 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+llvm::Constant* DtoConstFieldInitializer(Type* t, Initializer* init)
+{
+    Logger::println("DtoConstFieldInitializer");
+    LOG_SCOPE;
+
+    const llvm::Type* _type = DtoType(t);
+
+    llvm::Constant* _init = DtoConstInitializer(t, init);
+    assert(_init);
+    if (_type != _init->getType())
+    {
+        Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n';
+        if (t->ty == Tsarray)
+        {
+            const llvm::ArrayType* arrty = isaArray(_type);
+            uint64_t n = arrty->getNumElements();
+            std::vector<llvm::Constant*> vals(n,_init);
+            _init = llvm::ConstantArray::get(arrty, vals);
+        }
+        else if (t->ty == Tarray)
+        {
+            assert(isaStruct(_type));
+            _init = llvm::ConstantAggregateZero::get(_type);
+        }
+        else if (t->ty == Tstruct)
+        {
+            const llvm::StructType* structty = isaStruct(_type);
+            TypeStruct* ts = (TypeStruct*)t;
+            assert(ts);
+            assert(ts->sym);
+            assert(ts->sym->llvmInitZ);
+            _init = ts->sym->llvmInitZ;
+        }
+        else if (t->ty == Tclass)
+        {
+            _init = llvm::Constant::getNullValue(_type);
+        }
+        else {
+            Logger::println("failed for type %s", t->toChars());
+            assert(0);
+        }
+    }
+
+    return _init;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 DValue* DtoInitializer(Initializer* init)
 {
     if (ExpInitializer* ex = init->isExpInitializer())
@@ -858,152 +606,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl)
-{
-    TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
-    const llvm::FunctionType* fty = DtoVaFunctionType(fdecl);
-    llvm::Constant* fn = 0;
-
-    if (fdecl->llvmInternal == LLVMva_start) {
-        fn = gIR->module->getOrInsertFunction("llvm.va_start", fty);
-        assert(fn);
-    }
-    else if (fdecl->llvmInternal == LLVMva_intrinsic) {
-        fn = gIR->module->getOrInsertFunction(fdecl->llvmInternal1, fty);
-        assert(fn);
-    }
-    else
-    assert(0);
-
-    llvm::Function* func = llvm::dyn_cast<llvm::Function>(fn);
-    assert(func);
-    assert(func->isIntrinsic());
-    fdecl->llvmValue = func;
-    return func;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Function* DtoDeclareFunction(FuncDeclaration* fdecl)
-{
-    if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
-        return DtoDeclareVaFunction(fdecl);
-    }
-
-    // mangled name
-    char* mangled_name;
-    if (fdecl->llvmInternal == LLVMintrinsic)
-        mangled_name = fdecl->llvmInternal1;
-    else
-        mangled_name = fdecl->mangle();
-
-    // unit test special handling
-    if (fdecl->isUnitTestDeclaration())
-    {
-        assert(0 && "no unittests yet");
-        /*const llvm::FunctionType* fnty = llvm::FunctionType::get(llvm::Type::VoidTy, std::vector<const llvm::Type*>(), false);
-        // make the function
-        llvm::Function* func = gIR->module->getFunction(mangled_name);
-        if (func == 0)
-            func = new llvm::Function(fnty,llvm::GlobalValue::InternalLinkage,mangled_name,gIR->module);
-        func->setCallingConv(llvm::CallingConv::Fast);
-        fdecl->llvmValue = func;
-        return func;
-        */
-    }
-
-    // regular function
-    TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
-    assert(f != 0);
-
-    if (fdecl->llvmValue != 0) {
-        if (!llvm::isa<llvm::Function>(fdecl->llvmValue))
-        {
-            Logger::cout() << *fdecl->llvmValue << '\n';
-            assert(0);
-        }
-        return llvm::cast<llvm::Function>(fdecl->llvmValue);
-    }
-
-    Logger::print("FuncDeclaration::toObjFile(%s): %s\n", fdecl->needThis()?"this":"static",fdecl->toChars());
-    LOG_SCOPE;
-
-    if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) {
-        error("intrinsics cannot have function bodies");
-        fatal();
-    }
-
-    // construct function
-    const llvm::FunctionType* functype = (f->llvmType == 0) ? DtoFunctionType(fdecl) : llvm::cast<llvm::FunctionType>(f->llvmType);
-
-    // make the function
-    llvm::Function* func = gIR->module->getFunction(mangled_name);
-    if (func == 0) {
-        func = new llvm::Function(functype,DtoLinkage(fdecl->protection, fdecl->storage_class),mangled_name,gIR->module);
-    }
-
-    if (fdecl->llvmInternal != LLVMintrinsic)
-        func->setCallingConv(DtoCallingConv(f->linkage));
-
-    fdecl->llvmValue = func;
-    f->llvmType = functype;
-    assert(llvm::isa<llvm::FunctionType>(f->llvmType));
-
-    if (fdecl->isMain()) {
-        gIR->mainFunc = func;
-    }
-
-    // name parameters
-    llvm::Function::arg_iterator iarg = func->arg_begin();
-    int k = 0;
-    if (f->llvmRetInPtr) {
-        iarg->setName("retval");
-        f->llvmRetArg = iarg;
-        ++iarg;
-    }
-    if (f->llvmUsesThis) {
-        iarg->setName("this");
-        ++iarg;
-    }
-    int varargs = -1;
-    if (f->linkage == LINKd && f->varargs == 1)
-        varargs = 0;
-    for (; iarg != func->arg_end(); ++iarg)
-    {
-        Argument* arg = Argument::getNth(f->parameters, k++);
-        //arg->llvmValue = iarg;
-        //Logger::println("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident);
-        if (arg && arg->ident != 0) {
-            if (arg->vardecl) {
-                arg->vardecl->llvmValue = iarg;
-            }
-            iarg->setName(arg->ident->toChars());
-        }
-        else if (!arg && varargs >= 0) {
-            if (varargs == 0) {
-                iarg->setName("_arguments");
-                fdecl->llvmArguments = iarg;
-            }
-            else if (varargs == 1) {
-                iarg->setName("_argptr");
-                fdecl->llvmArgPtr = iarg;
-            }
-            else
-            assert(0);
-            varargs++;
-        }
-        else {
-            iarg->setName("unnamed");
-        }
-    }
-
-    Logger::cout() << "func decl: " << *func << '\n';
-
-    return func;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty)
 {
     /*size_t sz = gTargetData->getTypeSize(ty);
@@ -1174,7 +776,7 @@
     FuncDeclaration* fd = vd->toParent()->isFuncDeclaration();
     assert(fd != NULL);
 
-    IRFunction* fcur = &gIR->func();
+    IRFunction* fcur = gIR->func();
     FuncDeclaration* f = fcur->decl;
 
     // on this stack
@@ -1280,7 +882,7 @@
         // assignment to this in constructor special case
         if (lhs->isThis()) {
             llvm::Value* tmp = rhs->getRVal();
-            FuncDeclaration* fdecl = gIR->func().decl;
+            FuncDeclaration* fdecl = gIR->func()->decl;
             // respecify the this param
             if (!llvm::isa<llvm::AllocaInst>(fdecl->llvmThisVar))
                 fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", gIR->topallocapoint());
@@ -1716,3 +1318,113 @@
     gIR->ir->CreateBr(endinitbb);
     gIR->scope() = IRScope(endinitbb,oldend);
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoDefineDsymbol(Dsymbol* dsym)
+{
+    if (StructDeclaration* sd = dsym->isStructDeclaration()) {
+        DtoDefineStruct(sd);
+    }
+    else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
+        DtoDefineClass(cd);
+    }
+    else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
+        DtoDefineFunc(fd);
+    }
+    else {
+    error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
+    assert(0 && "unsupported dsymbol for DtoDefineDsymbol");
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoConstInitDsymbol(Dsymbol* dsym)
+{
+    if (StructDeclaration* sd = dsym->isStructDeclaration()) {
+        DtoConstInitStruct(sd);
+    }
+    else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
+        DtoConstInitClass(cd);
+    }
+    else if (VarDeclaration* vd = dsym->isVarDeclaration()) {
+        DtoConstInitGlobal(vd);
+    }
+    else {
+    error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
+    assert(0 && "unsupported dsymbol for DtoInitDsymbol");
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoConstInitGlobal(VarDeclaration* vd)
+{
+    Logger::println("DtoConstInitGlobal(%s)", vd->toChars());
+    LOG_SCOPE;
+
+    if (vd->llvmDModule) return;
+    vd->llvmDModule = gIR->dmodule;
+
+    bool emitRTstaticInit = false;
+
+    llvm::Constant* _init = 0;
+    if (vd->parent && vd->parent->isFuncDeclaration() && vd->init && vd->init->isExpInitializer()) {
+        _init = DtoConstInitializer(vd->type, NULL);
+        emitRTstaticInit = true;
+    }
+    else {
+        _init = DtoConstInitializer(vd->type, vd->init);
+    }
+
+    const llvm::Type* _type = DtoType(vd->type);
+    Type* t = DtoDType(vd->type);
+
+    //Logger::cout() << "initializer: " << *_init << '\n';
+    if (_type != _init->getType()) {
+        Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n";
+        // 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->llvmInitZ);
+            _init = ts->sym->llvmInitZ;
+        }
+        // array single value init
+        else if (isaArray(_type))
+        {
+            _init = DtoConstStaticArray(_type, _init);
+        }
+        else {
+            Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
+            //assert(0);
+        }
+    }
+
+    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<llvm::OpaqueType>(vd->llvmIRGlobal->type.get())->refineAbstractTypeTo(_type);
+    _type = vd->llvmIRGlobal->type.get();
+    assert(!_type->isAbstract());
+
+    llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(vd->llvmValue);
+    if (!(vd->storage_class & STCextern) && (vd->getModule() == gIR->dmodule || istempl))
+    {
+        gvar->setInitializer(_init);
+    }
+
+    if (emitRTstaticInit)
+        DtoLazyStaticInit(istempl, gvar, vd->init, t);
+}
--- a/gen/tollvm.h	Thu Nov 15 00:24:44 2007 +0100
+++ b/gen/tollvm.h	Fri Nov 16 08:21:47 2007 +0100
@@ -9,10 +9,6 @@
 bool DtoIsPassedByRef(Type* type);
 Type* DtoDType(Type* t);
 
-const llvm::FunctionType* DtoFunctionType(Type* t, const llvm::Type* thistype, bool ismain = false);
-const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl);
-llvm::Function* DtoDeclareFunction(FuncDeclaration* fdecl);
-
 const llvm::StructType* DtoDelegateType(Type* t);
 llvm::Value* DtoNullDelegate(llvm::Value* v);
 llvm::Value* DtoDelegateCopy(llvm::Value* dst, llvm::Value* src);
@@ -28,12 +24,8 @@
 
 const llvm::StructType* DtoComplexType(const llvm::Type* base);
 
-void DtoMain();
-
-void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance);
-void DtoInitClass(TypeClass* tc, llvm::Value* dst);
-
 llvm::Constant* DtoConstInitializer(Type* type, Initializer* init);
+llvm::Constant* DtoConstFieldInitializer(Type* type, Initializer* init);
 DValue* DtoInitializer(Initializer* init);
 
 llvm::Function* LLVM_DeclareMemSet32();
@@ -66,7 +58,9 @@
 
 void DtoLazyStaticInit(bool istempl, llvm::Value* gvar, Initializer* init, Type* t);
 
-void DtoClassInfo(ClassDeclaration* cd);
+void DtoDefineDsymbol(Dsymbol* dsym);
+void DtoConstInitDsymbol(Dsymbol* dsym);
+void DtoConstInitGlobal(VarDeclaration* vd);
 
 // llvm wrappers
 void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes);
--- a/gen/toobj.cpp	Thu Nov 15 00:24:44 2007 +0100
+++ b/gen/toobj.cpp	Fri Nov 16 08:21:47 2007 +0100
@@ -36,6 +36,8 @@
 #include "gen/tollvm.h"
 #include "gen/arrays.h"
 #include "gen/structs.h"
+#include "gen/classes.h"
+#include "gen/functions.h"
 #include "gen/todebug.h"
 #include "gen/runtime.h"
 
@@ -90,12 +92,14 @@
         dsym->toObjFile();
     }
 
-    // check if there are queued function definitions, if so process their bodies now
-    if (!ir.funcQueue.empty()) {
-        size_t n = ir.funcQueue.size();
-        for (size_t i=0; i<n; ++i) {
-            ir.funcQueue[i]->toObjFile();
-        }
+    // process deferred const initializers
+    for (size_t i=0; i<ir.constInitQueue.size(); ++i) {
+        DtoConstInitDsymbol(ir.constInitQueue[i]);
+    }
+
+    // process deferred definitions
+    for (size_t i=0; i<ir.defineQueue.size(); ++i) {
+        DtoDefineDsymbol(ir.defineQueue[i]);
     }
 
     // generate ModuleInfo
@@ -322,183 +326,7 @@
 
 void StructDeclaration::toObjFile()
 {
-    TypeStruct* ts = (TypeStruct*)DtoDType(type);
-    if (llvmType != 0)
-        return;
-
-    static int sdi = 0;
-    Logger::print("StructDeclaration::toObjFile(%d): %s\n", sdi++, toChars());
-    LOG_SCOPE;
-
-    gIR->structs.push_back(IRStruct(ts));
-
-    for (int k=0; k < members->dim; k++) {
-        Dsymbol* dsym = (Dsymbol*)(members->data[k]);
-        dsym->toObjFile();
-    }
-
-    Logger::println("doing struct fields");
-
-    const llvm::StructType* structtype = 0;
-    std::vector<llvm::Constant*> fieldinits;
-
-    if (gIR->topstruct().offsets.empty())
-    {
-        std::vector<const llvm::Type*> fieldtypes;
-        Logger::println("has no fields");
-        fieldtypes.push_back(llvm::Type::Int8Ty);
-        fieldinits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
-        structtype = llvm::StructType::get(fieldtypes);
-    }
-    else
-    {
-        Logger::println("has fields");
-        std::vector<const llvm::Type*> fieldtypes;
-        unsigned prevsize = (unsigned)-1;
-        unsigned lastoffset = (unsigned)-1;
-        const llvm::Type* fieldtype = NULL;
-        llvm::Constant* fieldinit = NULL;
-        size_t fieldpad = 0;
-        int idx = 0;
-        for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
-            // first iteration
-            if (lastoffset == (unsigned)-1) {
-                lastoffset = i->first;
-                assert(lastoffset == 0);
-                fieldtype = DtoType(i->second.var->type);
-                fieldinit = i->second.init;
-                prevsize = gTargetData->getTypeSize(fieldtype);
-                i->second.var->llvmFieldIndex = idx;
-            }
-            // colliding offset?
-            else if (lastoffset == i->first) {
-                const llvm::Type* t = DtoType(i->second.var->type);
-                size_t s = gTargetData->getTypeSize(t);
-                if (s > prevsize) {
-                    fieldpad += s - prevsize;
-                    prevsize = s;
-                }
-                llvmHasUnions = true;
-                i->second.var->llvmFieldIndex = idx;
-            }
-            // intersecting offset?
-            else if (i->first < (lastoffset + prevsize)) {
-                const llvm::Type* t = DtoType(i->second.var->type);
-                size_t s = gTargetData->getTypeSize(t);
-                assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
-                llvmHasUnions = true;
-                i->second.var->llvmFieldIndex = idx;
-                i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s;
-            }
-            // fresh offset
-            else {
-                // commit the field
-                fieldtypes.push_back(fieldtype);
-                fieldinits.push_back(fieldinit);
-                if (fieldpad) {
-                    // match up with below
-                    std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
-                    llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
-                    fieldtypes.push_back(c->getType());
-                    fieldinits.push_back(c);
-                    idx++;
-                }
-
-                idx++;
-
-                // start new
-                lastoffset = i->first;
-                fieldtype = DtoType(i->second.var->type);
-                fieldinit = i->second.init;
-                prevsize = gTargetData->getTypeSize(fieldtype);
-                i->second.var->llvmFieldIndex = idx;
-                fieldpad = 0;
-            }
-        }
-        fieldtypes.push_back(fieldtype);
-        fieldinits.push_back(fieldinit);
-        if (fieldpad) {
-            // match up with above
-            std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
-            llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
-            fieldtypes.push_back(c->getType());
-            fieldinits.push_back(c);
-        }
-
-        Logger::println("creating struct type");
-        structtype = llvm::StructType::get(fieldtypes);
-    }
-
-    // refine abstract types for stuff like: struct S{S* next;}
-    if (gIR->topstruct().recty != 0)
-    {
-        llvm::PATypeHolder& pa = gIR->topstruct().recty;
-        llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
-        structtype = isaStruct(pa.get());
-    }
-
-    ts->llvmType = structtype;
-    llvmType = structtype;
-
-    if (parent->isModule()) {
-        gIR->module->addTypeName(mangle(),ts->llvmType);
-    }
-
-    llvmUnion = new DUnion; // uses gIR->topstruct()
-
-    // generate static data
-    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
-    llvm::Constant* _init = 0;
-
-    // always generate the constant initalizer
-    if (!zeroInit) {
-        Logger::println("Not zero initialized");
-        //assert(tk == gIR->gIR->topstruct()().size());
-        #ifndef LLVMD_NO_LOGGER
-        Logger::cout() << "struct type: " << *structtype << '\n';
-        for (size_t k=0; k<fieldinits.size(); ++k) {
-            Logger::cout() << "Type:" << '\n';
-            Logger::cout() << *fieldinits[k]->getType() << '\n';
-            Logger::cout() << "Value:" << '\n';
-            Logger::cout() << *fieldinits[k] << '\n';
-        }
-        Logger::cout() << "Initializer printed" << '\n';
-        #endif
-        llvmInitZ = llvm::ConstantStruct::get(structtype,fieldinits);
-    }
-    else {
-        Logger::println("Zero initialized");
-        llvmInitZ = llvm::ConstantAggregateZero::get(structtype);
-    }
-
-    // only provide the constant initializer for the defining module
-    if (getModule() == gIR->dmodule)
-    {
-        _init = llvmInitZ;
-    }
-
-    std::string initname("_D");
-    initname.append(mangle());
-    initname.append("6__initZ");
-    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module);
-    ts->llvmInit = initvar;
-
-    // generate member function definitions
-    gIR->topstruct().queueFuncs = false;
-    IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
-    size_t n = mfs.size();
-    for (size_t i=0; i<n; ++i) {
-        //mfs[i]->toObjFile();
-        gIR->funcQueue.push_back(mfs[i]);
-    }
-
-    llvmDModule = gIR->dmodule;
-
-    gIR->structs.pop_back();
-
-    // generate typeinfo
-    if (getModule() == gIR->dmodule && llvmInternal != LLVMnotypeinfo)
-        type->getTypeInfo(NULL);
+    DtoDeclareStruct(this);
 }
 
 /* ================================================================== */
@@ -534,186 +362,9 @@
 
 /* ================================================================== */
 
-static void LLVM_AddBaseClassData(BaseClasses* bcs)
-{
-    // add base class data members first
-    for (int j=0; j<bcs->dim; j++)
-    {
-        BaseClass* bc = (BaseClass*)(bcs->data[j]);
-        assert(bc);
-        Logger::println("Adding base class members of %s", bc->base->toChars());
-        LOG_SCOPE;
-
-        LLVM_AddBaseClassData(&bc->base->baseclasses);
-        for (int k=0; k < bc->base->members->dim; k++) {
-            Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]);
-            if (dsym->isVarDeclaration())
-            {
-                dsym->toObjFile();
-            }
-        }
-    }
-}
-
 void ClassDeclaration::toObjFile()
 {
-    TypeClass* ts = (TypeClass*)DtoDType(type);
-    if (ts->llvmType != 0 || llvmInProgress)
-        return;
-
-    llvmInProgress = true;
-
-    static int fdi = 0;
-    Logger::print("ClassDeclaration::toObjFile(%d): %s\n", fdi++, toChars());
-    LOG_SCOPE;
-
-    gIR->structs.push_back(IRStruct(ts));
-    gIR->classes.push_back(this);
-
-    // add vtable
-    llvm::PATypeHolder pa = llvm::OpaqueType::get();
-    const llvm::Type* vtabty = llvm::PointerType::get(pa);
-
-    std::vector<const llvm::Type*> fieldtypes;
-    fieldtypes.push_back(vtabty);
-
-    std::vector<llvm::Constant*> fieldinits;
-    fieldinits.push_back(0);
-
-    // base classes first
-    LLVM_AddBaseClassData(&baseclasses);
-
-    // then add own members
-    for (int k=0; k < members->dim; k++) {
-        Dsymbol* dsym = (Dsymbol*)(members->data[k]);
-        dsym->toObjFile();
-    }
-
-    // fill out fieldtypes/inits
-    for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
-        fieldtypes.push_back(DtoType(i->second.var->type));
-        fieldinits.push_back(i->second.init);
-    }
-
-    const llvm::StructType* structtype = llvm::StructType::get(fieldtypes);
-    // refine abstract types for stuff like: class C {C next;}
-    if (gIR->topstruct().recty != 0)
-    {
-        llvm::PATypeHolder& pa = gIR->topstruct().recty;
-        llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
-        structtype = isaStruct(pa.get());
-    }
-
-    ts->llvmType = structtype;
-    llvmType = structtype;
-
-    bool needs_definition = false;
-    if (parent->isModule()) {
-        gIR->module->addTypeName(mangle(),ts->llvmType);
-        needs_definition = (getModule() == gIR->dmodule);
-    }
-    else {
-        assert(0 && "class parent is not a module");
-    }
-
-    // generate vtable
-    llvm::GlobalVariable* svtblVar = 0;
-    std::vector<llvm::Constant*> sinits;
-    std::vector<const llvm::Type*> sinits_ty;
-    sinits.reserve(vtbl.dim);
-    sinits_ty.reserve(vtbl.dim);
-
-    for (int k=0; k < vtbl.dim; k++)
-    {
-        Dsymbol* dsym = (Dsymbol*)vtbl.data[k];
-        assert(dsym);
-        //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
-
-        if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
-            fd->toObjFile();
-            assert(fd->llvmValue);
-            llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
-            sinits.push_back(c);
-            sinits_ty.push_back(c->getType());
-        }
-        else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
-            const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty);
-            llvm::Constant* c = llvm::Constant::getNullValue(cty);
-            sinits.push_back(c);
-            sinits_ty.push_back(cty);
-        }
-        else
-        assert(0);
-    }
-
-    const llvm::StructType* svtbl_ty = 0;
-    if (!sinits.empty())
-    {
-        llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
-
-        std::string varname("_D");
-        varname.append(mangle());
-        varname.append("6__vtblZ");
-
-        std::string styname(mangle());
-        styname.append("__vtblTy");
-
-        svtbl_ty = llvm::StructType::get(sinits_ty);
-        gIR->module->addTypeName(styname, svtbl_ty);
-        svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
-
-        llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits));
-        if (needs_definition)
-            svtblVar->setInitializer(llvmConstVtbl);
-        llvmVtbl = svtblVar;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////////
-
-    // refine for final vtable type
-    llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty);
-    svtbl_ty = isaStruct(pa.get());
-    structtype = isaStruct(gIR->topstruct().recty.get());
-    ts->llvmType = structtype;
-    llvmType = structtype;
-
-    // generate initializer
-    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
-    llvm::Constant* _init = 0;
-
-    // first field is always the vtable
-    assert(svtblVar != 0);
-    fieldinits[0] = svtblVar;
-
-    llvmInitZ = _init = llvm::ConstantStruct::get(structtype,fieldinits);
-    assert(_init);
-
-    std::string initname("_D");
-    initname.append(mangle());
-    initname.append("6__initZ");
-    //Logger::cout() << *_init << '\n';
-    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, NULL, initname, gIR->module);
-    ts->llvmInit = initvar;
-
-    if (needs_definition) {
-        initvar->setInitializer(_init);
-        // generate member functions
-        gIR->topstruct().queueFuncs = false;
-        IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
-        size_t n = mfs.size();
-        for (size_t i=0; i<n; ++i) {
-            //mfs[i]->toObjFile();
-            gIR->funcQueue.push_back(mfs[i]);
-        }
-    }
-
-    gIR->classes.pop_back();
-    gIR->structs.pop_back();
-
-    llvmInProgress = false;
-
-    //     if (ClassDeclaration::classinfo != this)
-    //         DtoClassInfo(this);
+    DtoDeclareClass(this);
 }
 
 /******************************************
@@ -732,7 +383,6 @@
 {
     Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
-    llvm::Module* M = gIR->module;
 
     if (aliassym)
     {
@@ -747,81 +397,40 @@
         if (llvmTouched) return;
         else llvmTouched = true;
 
-        bool _isconst = false;
-        if (isConst() && (init && !init->isExpInitializer()))
-            _isconst = true;
+        llvmIRGlobal = new IRGlobal(this);
+
+        Logger::println("parent: %s (%s)", parent->toChars(), parent->kind());
+
+        bool _isconst = isConst();
+        if (parent && parent->isFuncDeclaration() && init && init->isExpInitializer())
+            _isconst = false;
 
         llvm::GlobalValue::LinkageTypes _linkage;
         bool istempl = false;
+        bool static_local = false;
         if ((storage_class & STCcomdat) || (parent && DtoIsTemplateInstance(parent))) {
             _linkage = llvm::GlobalValue::WeakLinkage;
             istempl = true;
         }
-        else if (parent && parent->isFuncDeclaration())
+        else if (parent && parent->isFuncDeclaration()) {
             _linkage = llvm::GlobalValue::InternalLinkage;
+            static_local = true;
+        }
         else
             _linkage = DtoLinkage(protection, storage_class);
 
-        Type* t = DtoDType(type);
-
-        const llvm::Type* _type = DtoType(t);
-        assert(_type);
-
-        llvm::Constant* _init = 0;
-        bool _signed = !type->isunsigned();
+        const llvm::Type* _type = llvmIRGlobal->type.get();
 
         Logger::println("Creating global variable");
         std::string _name(mangle());
 
-        bool emitRTstaticInit = false;
-
-        if (!(storage_class & STCextern) && (getModule() == gIR->dmodule || istempl))
-        {
-            if (parent && parent->isFuncDeclaration() && init && init->isExpInitializer()) {
-                _init = DtoConstInitializer(t, NULL);
-                emitRTstaticInit = true;
-            }
-            else {
-                _init = DtoConstInitializer(t, init);
-            }
-
-            //Logger::cout() << "initializer: " << *_init << '\n';
-            if (_type != _init->getType()) {
-                Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n";
-                // 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->llvmInitZ);
-                    _init = ts->sym->llvmInitZ;
-                }
-                // array single value init
-                else if (isaArray(_type))
-                {
-                    _init = DtoConstStaticArray(_type, _init);
-                }
-                else {
-                    Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
-                    //assert(0);
-                }
-            }
-        }
-
-        if (_init && _init->getType() != _type)
-            _type = _init->getType();
-        llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,_init,_name,M);
+        llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,NULL,_name,gIR->module);
         llvmValue = gvar;
 
-        if (emitRTstaticInit)
-            DtoLazyStaticInit(istempl, gvar, init, t);
-
-        llvmDModule = gIR->dmodule;
+        if (static_local)
+            DtoConstInitGlobal(this);
+        else
+            gIR->constInitQueue.push_back(this);
 
         //if (storage_class & STCprivate)
         //    gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility);
@@ -832,47 +441,10 @@
     {
         Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset);
 
-        Type* t = DtoDType(type);
-        const llvm::Type* _type = DtoType(t);
-
-        llvm::Constant*_init = DtoConstInitializer(t, init);
-        assert(_init);
-        Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n';
-        if (_type != _init->getType())
-        {
-            if (t->ty == Tsarray)
-            {
-                const llvm::ArrayType* arrty = isaArray(_type);
-                uint64_t n = arrty->getNumElements();
-                std::vector<llvm::Constant*> vals(n,_init);
-                _init = llvm::ConstantArray::get(arrty, vals);
-            }
-            else if (t->ty == Tarray)
-            {
-                assert(isaStruct(_type));
-                _init = llvm::ConstantAggregateZero::get(_type);
-            }
-            else if (t->ty == Tstruct)
-            {
-                const llvm::StructType* structty = isaStruct(_type);
-                TypeStruct* ts = (TypeStruct*)t;
-                assert(ts);
-                assert(ts->sym);
-                assert(ts->sym->llvmInitZ);
-                _init = ts->sym->llvmInitZ;
-            }
-            else if (t->ty == Tclass)
-            {
-                _init = llvm::Constant::getNullValue(_type);
-            }
-            else {
-                Logger::println("failed for type %s", type->toChars());
-                assert(0);
-            }
-        }
+        const llvm::Type* _type = DtoType(type);
 
         // add the field in the IRStruct
-        gIR->topstruct().offsets.insert(std::make_pair(offset, IRStruct::Offset(this,_init)));
+        gIR->topstruct()->offsets.insert(std::make_pair(offset, IRStruct::Offset(this, _type)));
     }
 
     Logger::println("VarDeclaration::toObjFile is done");
@@ -901,254 +473,5 @@
 
 void FuncDeclaration::toObjFile()
 {
-    if (llvmDModule) {
-        assert(llvmValue != 0);
-        return;
-    }
-
-    if (llvmRunTimeHack) {
-        Logger::println("runtime hack func chars: %s", toChars());
-        if (!llvmValue)
-            llvmValue = LLVM_D_GetRuntimeFunction(gIR->module, toChars());
-        return;
-    }
-
-    if (isUnitTestDeclaration()) {
-        Logger::attention("ignoring unittest declaration: %s", toChars());
-        return;
-    }
-
-    Type* t = DtoDType(type);
-    TypeFunction* f = (TypeFunction*)t;
-
-    bool declareOnly = false;
-    if (parent)
-    {
-    if (TemplateInstance* tinst = parent->isTemplateInstance()) {
-        TemplateDeclaration* tempdecl = tinst->tempdecl;
-        if (tempdecl->llvmInternal == LLVMva_start)
-        {
-            Logger::println("magic va_start found");
-            llvmInternal = LLVMva_start;
-            declareOnly = true;
-        }
-        else if (tempdecl->llvmInternal == LLVMva_arg)
-        {
-            Logger::println("magic va_arg found");
-            llvmInternal = LLVMva_arg;
-            return;
-        }
-    }
-    }
-
-    llvm::Function* func = DtoDeclareFunction(this);
-
-    if (declareOnly)
-        return;
-
-    if (!gIR->structs.empty() && gIR->topstruct().queueFuncs) {
-        if (!llvmQueued) {
-            Logger::println("queueing %s", toChars());
-            gIR->topstruct().funcs.push_back(this);
-            llvmQueued = true;
-        }
-        return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete
-    }
-
-    // debug info
-    if (global.params.symdebug) {
-        Module* mo = getModule();
-        if (!mo->llvmCompileUnit) {
-            mo->llvmCompileUnit = DtoDwarfCompileUnit(mo,false);
-        }
-        llvmDwarfSubProgram = DtoDwarfSubProgram(this, mo->llvmCompileUnit);
-    }
-
-    assert(f->llvmType);
-    const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0));
-
-    // template instances should have weak linkage
-    if (parent && DtoIsTemplateInstance(parent)) {
-        func->setLinkage(llvm::GlobalValue::WeakLinkage);
-    }
-
-    // only members of the current module maybe be defined
-    if (getModule() == gIR->dmodule || DtoIsTemplateInstance(parent))
-    {
-        llvmDModule = gIR->dmodule;
-
-        // handle static constructor / destructor
-        if (isStaticCtorDeclaration() || isStaticDtorDeclaration()) {
-            const llvm::ArrayType* sctor_type = llvm::ArrayType::get(llvm::PointerType::get(functype),1);
-            //Logger::cout() << "static ctor type: " << *sctor_type << '\n';
-
-            llvm::Constant* sctor_func = llvm::cast<llvm::Constant>(llvmValue);
-            //Logger::cout() << "static ctor func: " << *sctor_func << '\n';
-
-            llvm::Constant* sctor_init = llvm::ConstantArray::get(sctor_type,&sctor_func,1);
-
-            //Logger::cout() << "static ctor init: " << *sctor_init << '\n';
-
-            // output the llvm.global_ctors array
-            const char* varname = isStaticCtorDeclaration() ? "_d_module_ctor_array" : "_d_module_dtor_array";
-            llvm::GlobalVariable* sctor_arr = new llvm::GlobalVariable(sctor_type, false, llvm::GlobalValue::AppendingLinkage, sctor_init, varname, gIR->module);
-        }
-
-        // function definition
-        if (fbody != 0)
-        {
-            gIR->functions.push_back(IRFunction(this));
-            gIR->func().func = func;
-
-            // first make absolutely sure the type is up to date
-            f->llvmType = llvmValue->getType()->getContainedType(0);
-
-            //Logger::cout() << "func type: " << *f->llvmType << '\n';
-
-            // this handling
-            if (f->llvmUsesThis) {
-                Logger::println("uses this");
-                if (f->llvmRetInPtr)
-                    llvmThisVar = ++func->arg_begin();
-                else
-                    llvmThisVar = func->arg_begin();
-                assert(llvmThisVar != 0);
-            }
-
-            if (isMain())
-                gIR->emitMain = true;
-
-            llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func);
-            llvm::BasicBlock* endbb = new llvm::BasicBlock("endentry",func);
-
-            //assert(gIR->scopes.empty());
-            gIR->scopes.push_back(IRScope(beginbb, endbb));
-
-                // create alloca point
-                f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb());
-                gIR->func().allocapoint = f->llvmAllocaPoint;
-
-                // give arguments storage
-                size_t n = Argument::dim(f->parameters);
-                for (int i=0; i < n; ++i) {
-                    Argument* arg = Argument::getNth(f->parameters, i);
-                    if (arg && arg->vardecl) {
-                        VarDeclaration* vd = arg->vardecl;
-                        if (!vd->llvmNeedsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))
-                            continue;
-                        llvm::Value* a = vd->llvmValue;
-                        assert(a);
-                        std::string s(a->getName());
-                        Logger::println("giving argument '%s' storage", s.c_str());
-                        s.append("_storage");
-                        llvm::Value* v = new llvm::AllocaInst(a->getType(),s,f->llvmAllocaPoint);
-                        gIR->ir->CreateStore(a,v);
-                        vd->llvmValue = v;
-                    }
-                    else {
-                        Logger::attention("some unknown argument: %s", arg ? arg->toChars() : 0);
-                    }
-                }
-
-                // debug info
-                if (global.params.symdebug) DtoDwarfFuncStart(this);
-
-                llvm::Value* parentNested = NULL;
-                if (FuncDeclaration* fd = toParent()->isFuncDeclaration()) {
-                    parentNested = fd->llvmNested;
-                }
-
-                // construct nested variables struct
-                if (!llvmNestedVars.empty() || parentNested) {
-                    std::vector<const llvm::Type*> nestTypes;
-                    int j = 0;
-                    if (parentNested) {
-                        nestTypes.push_back(parentNested->getType());
-                        j++;
-                    }
-                    for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) {
-                        VarDeclaration* vd = *i;
-                        vd->llvmNestedIndex = j++;
-                        if (vd->isParameter()) {
-                            assert(vd->llvmValue);
-                            nestTypes.push_back(vd->llvmValue->getType());
-                        }
-                        else {
-                            nestTypes.push_back(DtoType(vd->type));
-                        }
-                    }
-                    const llvm::StructType* nestSType = llvm::StructType::get(nestTypes);
-                    Logger::cout() << "nested var struct has type:" << '\n' << *nestSType;
-                    llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",f->llvmAllocaPoint);
-                    if (parentNested) {
-                        assert(llvmThisVar);
-                        llvm::Value* ptr = gIR->ir->CreateBitCast(llvmThisVar, parentNested->getType(), "tmp");
-                        gIR->ir->CreateStore(ptr, DtoGEPi(llvmNested, 0,0, "tmp"));
-                    }
-                    for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) {
-                        VarDeclaration* vd = *i;
-                        if (vd->isParameter()) {
-                            gIR->ir->CreateStore(vd->llvmValue, DtoGEPi(llvmNested, 0, vd->llvmNestedIndex, "tmp"));
-                            vd->llvmValue = llvmNested;
-                        }
-                    }
-                }
-
-                // copy _argptr to a memory location
-                if (f->linkage == LINKd && f->varargs == 1)
-                {
-                    llvm::Value* argptrmem = new llvm::AllocaInst(llvmArgPtr->getType(), "_argptrmem", gIR->topallocapoint());
-                    new llvm::StoreInst(llvmArgPtr, argptrmem, gIR->scopebb());
-                    llvmArgPtr = argptrmem;
-                }
-
-                // output function body
-                fbody->toIR(gIR);
-
-                // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement
-                // in automatically, so we do it here.
-                if (!isMain()) {
-                    if (!gIR->scopereturned()) {
-                        // pass the previous block into this block
-                        if (global.params.symdebug) DtoDwarfFuncEnd(this);
-                        if (func->getReturnType() == llvm::Type::VoidTy) {
-                            new llvm::ReturnInst(gIR->scopebb());
-                        }
-                        else {
-                            new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), gIR->scopebb());
-                        }
-                    }
-                }
-
-                // erase alloca point
-                f->llvmAllocaPoint->eraseFromParent();
-                f->llvmAllocaPoint = 0;
-                gIR->func().allocapoint = 0;
-
-            gIR->scopes.pop_back();
-
-            // get rid of the endentry block, it's never used
-            assert(!func->getBasicBlockList().empty());
-            func->getBasicBlockList().pop_back();
-
-            // if the last block is empty now, it must be unreachable or it's a bug somewhere else
-            // would be nice to figure out how to assert that this is correct
-            llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
-            if (lastbb->empty()) {
-                if (lastbb->getNumUses() == 0)
-                    lastbb->eraseFromParent();
-                else {
-                    new llvm::UnreachableInst(lastbb);
-                    /*if (func->getReturnType() == llvm::Type::VoidTy) {
-                        new llvm::ReturnInst(lastbb);
-                    }
-                    else {
-                        new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), lastbb);
-                    }*/
-                }
-            }
-
-            gIR->functions.pop_back();
-        }
-    }
+    DtoDeclareFunction(this);
 }
--- a/gen/typinf.cpp	Thu Nov 15 00:24:44 2007 +0100
+++ b/gen/typinf.cpp	Fri Nov 16 08:21:47 2007 +0100
@@ -32,6 +32,7 @@
 #include "gen/runtime.h"
 #include "gen/tollvm.h"
 #include "gen/arrays.h"
+#include "gen/structs.h"
 
 /*******************************************
  * Get a canonicalized form of the TypeInfo for use with the internal
@@ -258,6 +259,7 @@
     }
     // custom typedef
     else {
+        // emit globals
         toDt(NULL);
     }
 }
@@ -279,12 +281,10 @@
     ClassDeclaration* base = Type::typeinfotypedef;
     base->toObjFile();
 
-    llvm::Constant* initZ = base->llvmInitZ;
-    assert(initZ);
-    const llvm::StructType* stype = isaStruct(initZ->getType());
+    const llvm::StructType* stype = isaStruct(base->type->llvmType->get());
 
     std::vector<llvm::Constant*> sinits;
-    sinits.push_back(initZ->getOperand(0));
+    sinits.push_back(base->llvmVtbl);
 
     assert(tinfo->ty == Ttypedef);
     TypeTypedef *tc = (TypeTypedef *)tinfo;
@@ -301,13 +301,13 @@
         sd->basetype->vtinfo->toObjFile();
     assert(llvm::isa<llvm::Constant>(sd->basetype->vtinfo->llvmValue));
     llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->basetype->vtinfo->llvmValue);
-    castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType());
+    castbase = llvm::ConstantExpr::getBitCast(castbase, stype->getElementType(1));
     sinits.push_back(castbase);
 
     // char[] name
     char *name = sd->toPrettyChars();
     sinits.push_back(DtoConstString(name));
-    assert(sinits.back()->getType() == initZ->getOperand(2)->getType());
+    assert(sinits.back()->getType() == stype->getElementType(2));
 
     // void[] init
     const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
@@ -343,12 +343,10 @@
     ClassDeclaration* base = Type::typeinfoenum;
     base->toObjFile();
 
-    llvm::Constant* initZ = base->llvmInitZ;
-    assert(initZ);
-    const llvm::StructType* stype = isaStruct(initZ->getType());
+    const llvm::StructType* stype = isaStruct(base->type->llvmType->get());
 
     std::vector<llvm::Constant*> sinits;
-    sinits.push_back(initZ->getOperand(0));
+    sinits.push_back(base->llvmVtbl);
 
     assert(tinfo->ty == Tenum);
     TypeEnum *tc = (TypeEnum *)tinfo;
@@ -365,13 +363,13 @@
         sd->memtype->vtinfo->toObjFile();
     assert(llvm::isa<llvm::Constant>(sd->memtype->vtinfo->llvmValue));
     llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->memtype->vtinfo->llvmValue);
-    castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType());
+    castbase = llvm::ConstantExpr::getBitCast(castbase, stype->getElementType(1));
     sinits.push_back(castbase);
 
     // char[] name
     char *name = sd->toPrettyChars();
     sinits.push_back(DtoConstString(name));
-    assert(sinits.back()->getType() == initZ->getOperand(2)->getType());
+    assert(sinits.back()->getType() == stype->getElementType(2));
 
     // void[] init
     const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
@@ -405,12 +403,10 @@
     ClassDeclaration* base = cd;
     base->toObjFile();
 
-    llvm::Constant* initZ = base->llvmInitZ;
-    assert(initZ);
-    const llvm::StructType* stype = isaStruct(initZ->getType());
+    const llvm::StructType* stype = isaStruct(base->type->llvmType->get());
 
     std::vector<llvm::Constant*> sinits;
-    sinits.push_back(initZ->getOperand(0));
+    sinits.push_back(base->llvmVtbl);
 
     // TypeInfo base
     Logger::println("generating base typeinfo");
@@ -420,7 +416,7 @@
         basetype->vtinfo->toObjFile();
     assert(llvm::isa<llvm::Constant>(basetype->vtinfo->llvmValue));
     llvm::Constant* castbase = llvm::cast<llvm::Constant>(basetype->vtinfo->llvmValue);
-    castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType());
+    castbase = llvm::ConstantExpr::getBitCast(castbase, stype->getElementType(1));
     sinits.push_back(castbase);
 
     // create the symbol
@@ -538,11 +534,12 @@
     TypeStruct *tc = (TypeStruct *)tinfo;
     StructDeclaration *sd = tc->sym;
     sd->toObjFile();
+    DtoConstInitStruct(sd);
 
     ClassDeclaration* base = Type::typeinfostruct;
     base->toObjFile();
 
-    const llvm::StructType* stype = isaStruct(base->llvmType);
+    const llvm::StructType* stype = isaStruct(((TypeClass*)base->type)->llvmType->get());
 
     std::vector<llvm::Constant*> sinits;
     sinits.push_back(base->llvmVtbl);
@@ -562,7 +559,7 @@
     else
     {
         assert(sd->llvmInitZ);
-        size_t cisize = gTargetData->getTypeSize(tc->llvmType);
+        size_t cisize = gTargetData->getTypeSize(tc->llvmType->get());
         llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(tc->llvmInit, initpt);
         sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
     }
@@ -778,131 +775,3 @@
     dtxoff(pdt, s, 0, TYnptr);          // elements.ptr
     */
 }
-
-/* ========================================================================= */
-/* ========================================================================= */
-/*                           CLASS INFO STUFF                                */
-/* ========================================================================= */
-/* ========================================================================= */
-
-void DtoClassInfo(ClassDeclaration* cd)
-{
-//     The layout is:
-//        {
-//         void **vptr;
-//         monitor_t monitor;
-//         byte[] initializer;     // static initialization data
-//         char[] name;        // class name
-//         void *[] vtbl;
-//         Interface[] interfaces;
-//         ClassInfo *base;        // base class
-//         void *destructor;
-//         void *invariant;        // class invariant
-//         uint flags;
-//         void *deallocator;
-//         OffsetTypeInfo[] offTi;
-//         void *defaultConstructor;
-//        }
-
-    // holds the list of initializers for llvm
-    std::vector<llvm::Constant*> inits;
-
-    ClassDeclaration* cinfo = ClassDeclaration::classinfo;
-    assert(cinfo);
-    Logger::println("cinfo toObj");
-    cinfo->toObjFile();
-    
-    Logger::println("cinfo toObj done");
-    assert(cinfo->type->ty == Tclass);
-    TypeClass* tc = (TypeClass*)cinfo->type;
-    //assert(tc->llvmInit);
-    //assert(cinfo->llvmInitZ);
-
-    cinfo = ClassDeclaration::classinfo;
-    assert(cinfo->llvmInitZ);
-
-    /*
-    llvm::Constant* c;
-
-    // own vtable
-    c = cinfo->llvmInitZ->getOperand(0);
-    assert(c);
-    inits.push_back(c);
-
-    // monitor
-    // TODO no monitors yet
-
-    // initializer
-    c = cinfo->llvmInitZ->getOperand(1);
-    inits.push_back(c);
-
-    // class name
-    // from dmd
-    char *name = cd->ident->toChars();
-    size_t namelen = strlen(name);
-    if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
-    {
-        name = cd->toPrettyChars();
-        namelen = strlen(name);
-    }
-    c = DtoConstString(name);
-    inits.push_back(c);
-
-    // vtbl array
-    c = cinfo->llvmInitZ->getOperand(3);
-    inits.push_back(c);
-
-    // interfaces array
-    c = cinfo->llvmInitZ->getOperand(4);
-    inits.push_back(c);
-
-    // base classinfo
-    c = cinfo->llvmInitZ->getOperand(5);
-    inits.push_back(c);
-
-    // destructor
-    c = cinfo->llvmInitZ->getOperand(5);
-    inits.push_back(c);
-
-    // invariant
-    c = cinfo->llvmInitZ->getOperand(6);
-    inits.push_back(c);
-
-    // flags
-    c = cinfo->llvmInitZ->getOperand(7);
-    inits.push_back(c);
-
-    // allocator
-    c = cinfo->llvmInitZ->getOperand(8);
-    inits.push_back(c);
-
-    // offset typeinfo
-    c = cinfo->llvmInitZ->getOperand(9);
-    inits.push_back(c);
-
-    // default constructor
-    c = cinfo->llvmInitZ->getOperand(10);
-    inits.push_back(c);
-
-    // build the initializer
-    const llvm::StructType* st = isaStruct(cinfo->llvmInitZ->getType());
-    llvm::Constant* finalinit = llvm::ConstantStruct::get(st, inits);
-    Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
-
-    assert(0);
-    */
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
--- a/llvmdc.kdevelop.filelist	Thu Nov 15 00:24:44 2007 +0100
+++ b/llvmdc.kdevelop.filelist	Fri Nov 16 08:21:47 2007 +0100
@@ -103,10 +103,14 @@
 gen/arrays.cpp
 gen/arrays.h
 gen/binops.cpp
+gen/classes.cpp
+gen/classes.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/llvm.h
@@ -223,6 +227,7 @@
 test/arrays10.d
 test/arrays11.d
 test/arrays12.d
+test/arrays13.d
 test/arrays2.d
 test/arrays3.d
 test/arrays4.d
@@ -291,7 +296,9 @@
 test/bug60.d
 test/bug61.d
 test/bug62.d
+test/bug63.d
 test/bug64.d
+test/bug66.d
 test/bug7.d
 test/bug8.d
 test/bug9.d
--- a/lphobos/internal/arrays.d	Thu Nov 15 00:24:44 2007 +0100
+++ b/lphobos/internal/arrays.d	Fri Nov 16 08:21:47 2007 +0100
@@ -88,40 +88,6 @@
     }
 }
 
-// array comparison routines
-
-bool _d_static_array_eq(void* lhs, void* rhs, size_t bytesize)
-{
-    if (lhs is rhs)
-        return true;
-    return memcmp(lhs,rhs,bytesize) == 0;
-}
-
-bool _d_static_array_neq(void* lhs, void* rhs, size_t bytesize)
-{
-    if (lhs is rhs)
-        return false;
-    return memcmp(lhs,rhs,bytesize) != 0;
-}
-
-bool _d_dyn_array_eq(void[] lhs, void[] rhs)
-{
-    if (lhs.length != rhs.length)
-        return false;
-    else if (lhs is rhs)
-        return true;
-    return memcmp(lhs.ptr,rhs.ptr,lhs.length) == 0;
-}
-
-bool _d_dyn_array_neq(void[] lhs, void[] rhs)
-{
-    if (lhs.length != rhs.length)
-        return true;
-    else if (lhs is rhs)
-        return false;
-    return memcmp(lhs.ptr,rhs.ptr,lhs.length) != 0;
-}
-
 // for array cast
 size_t _d_array_cast_len(size_t len, size_t elemsz, size_t newelemsz)
 {
--- a/runalltests.d	Thu Nov 15 00:24:44 2007 +0100
+++ b/runalltests.d	Fri Nov 16 08:21:47 2007 +0100
@@ -13,7 +13,11 @@
 
     auto contents = listdir(".", "*.d");
     foreach(c; contents) {
-        auto cmd = "llvmdc -quiet "~c;
+        string cmd = "llvmdc -quiet "~c;
+        foreach(v; args[1..$]) {
+            cmd ~= ' ';
+            cmd ~= v;
+        }
         writefln(cmd);
         if (system(cmd) != 0) {
             bad ~= c;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/arrays13.d	Fri Nov 16 08:21:47 2007 +0100
@@ -0,0 +1,16 @@
+module arrays13;
+
+void main()
+{
+    string a = "hello";
+
+    assert(a >  "hel");
+    assert(a >= "hel");
+    assert(a <  "helloo");
+    assert(a <= "helloo");
+    assert(a >  "betty");
+    assert(a >= "betty");
+    assert(a == "hello");
+    assert(a <= "hello");
+    assert(a >= "hello");
+}
--- a/test/bug58.d	Thu Nov 15 00:24:44 2007 +0100
+++ b/test/bug58.d	Fri Nov 16 08:21:47 2007 +0100
@@ -7,4 +7,4 @@
     arr.sort;
     writefln("arr.sort = ",arr);
     assert(arr == [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]);
-}
\ No newline at end of file
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug63.d	Fri Nov 16 08:21:47 2007 +0100
@@ -0,0 +1,10 @@
+module bug63;
+
+void main()
+{
+    static void notnested()
+    {
+        printf("hello world\n");
+    }
+    notnested();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug66.d	Fri Nov 16 08:21:47 2007 +0100
@@ -0,0 +1,5 @@
+module bug66;
+import std.stdio;
+class Scene { string name() { return "Scene"; } }
+class Group : Scene { this () { } }
+void main() { writefln((new Group).name); }
--- a/test/classinfo1.d	Thu Nov 15 00:24:44 2007 +0100
+++ b/test/classinfo1.d	Fri Nov 16 08:21:47 2007 +0100
@@ -6,5 +6,5 @@
 
 void main()
 {
-    auto ci = C.classinfo;
+    ClassInfo ci = C.classinfo;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/structs7.d	Fri Nov 16 08:21:47 2007 +0100
@@ -0,0 +1,15 @@
+module structs7;
+
+pragma(LLVM_internal, "notypeinfo")
+struct S
+{
+    int i;
+    long l;
+}
+
+void main()
+{
+    S s = void;
+    int i = s.i;
+    long l = s.l;
+}
--- a/test/throw1.d	Thu Nov 15 00:24:44 2007 +0100
+++ b/test/throw1.d	Fri Nov 16 08:21:47 2007 +0100
@@ -6,17 +6,18 @@
 {
 }
 
-void func()
+void func(bool b)
 {
-    if (rand() & 1)
+    if (b)
         throw new C;
 }
 
 int main()
 {
+    bool b = true;
     try
     {
-        func();
+        func(b);
     }
     catch(Object)
     {
--- a/test/typeinfo3.d	Thu Nov 15 00:24:44 2007 +0100
+++ b/test/typeinfo3.d	Fri Nov 16 08:21:47 2007 +0100
@@ -4,11 +4,11 @@
 
 void main()
 {
-    int_t i;
+    /*int_t i;
     auto ti = typeid(typeof(i));
     printf("%s\n",ti.toString.ptr);
     assert(ti.toString() == "typeinfo3.int_t");
     assert(ti.next !is null);
     assert(ti.next.toString() == "int");
-    assert(ti.init is null);
+    assert(ti.init is null);*/
 }