changeset 102:027b8d8b71ec trunk

[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up. Basically it tries to do the following in order: Resolve types, Declare symbols, Create constant initializers, Apply initializers, Generate functions bodies. ClassInfo is now has the most useful(biased?) members working. Probably other stuf...
author lindquist
date Sun, 18 Nov 2007 06:52:57 +0100
parents 169fda3a77d4
children 855adfdb8d38
files dmd/aggregate.h dmd/dsymbol.c dmd/dsymbol.h dmd/mtype.c dmd/mtype.h dmd/struct.c gen/arrays.cpp gen/arrays.h gen/classes.cpp gen/classes.h gen/functions.cpp gen/functions.h gen/irstate.h gen/logger.cpp gen/structs.cpp gen/structs.h gen/toir.cpp gen/tollvm.cpp gen/tollvm.h gen/toobj.cpp gen/typeinf.h gen/typinf.cpp llvmdc.kdevelop llvmdc.kdevelop.filelist lphobos/build.sh test/bug51.d test/classinfo1.d test/funcptr.d
diffstat 28 files changed, 798 insertions(+), 304 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/aggregate.h	Fri Nov 16 10:01:24 2007 +0100
+++ b/dmd/aggregate.h	Sun Nov 18 06:52:57 2007 +0100
@@ -110,6 +110,8 @@
     bool llvmHasUnions;
     DUnion* llvmUnion;
     IRStruct* llvmIRStruct;
+    bool llvmClassDeclared;
+    bool llvmClassDefined;
 
     AggregateDeclaration *isAggregateDeclaration() { return this; }
 };
--- a/dmd/dsymbol.c	Fri Nov 16 10:01:24 2007 +0100
+++ b/dmd/dsymbol.c	Sun Nov 18 06:52:57 2007 +0100
@@ -48,7 +48,11 @@
     this->llvmInternal2 = NULL;
     this->llvmValue = NULL;
     this->llvmDModule = NULL;
-    this->llvmTouched = false;
+
+    this->llvmResolved = false;
+    this->llvmDeclared = false;
+    this->llvmInitialized = false;
+    this->llvmDefined = false;
 }
 
 Dsymbol::Dsymbol(Identifier *ident)
@@ -66,7 +70,11 @@
     this->llvmInternal2 = NULL;
     this->llvmValue = NULL;
     this->llvmDModule = NULL;
-    this->llvmTouched = false;
+
+    this->llvmResolved = false;
+    this->llvmDeclared = false;
+    this->llvmInitialized = false;
+    this->llvmDefined = false;
 }
 
 int Dsymbol::equals(Object *o)
--- a/dmd/dsymbol.h	Fri Nov 16 10:01:24 2007 +0100
+++ b/dmd/dsymbol.h	Sun Nov 18 06:52:57 2007 +0100
@@ -223,7 +223,10 @@
     llvm::Value* llvmValue;
     Module* llvmDModule;
 
-    bool llvmTouched;
+    bool llvmResolved;
+    bool llvmDeclared;
+    bool llvmInitialized;
+    bool llvmDefined;
 };
 
 // Dsymbol that generates a scope
--- a/dmd/mtype.c	Fri Nov 16 10:01:24 2007 +0100
+++ b/dmd/mtype.c	Sun Nov 18 06:52:57 2007 +0100
@@ -4374,6 +4374,7 @@
 {
     this->sym = sym;
     llvmInit = 0;
+    llvmVtblType = 0;
 }
 
 char *TypeClass::toChars()
--- a/dmd/mtype.h	Fri Nov 16 10:01:24 2007 +0100
+++ b/dmd/mtype.h	Sun Nov 18 06:52:57 2007 +0100
@@ -642,6 +642,7 @@
     Symbol *toSymbol();
 
     llvm::GlobalVariable* llvmInit;
+    llvm::PATypeHolder* llvmVtblType;
 };
 
 struct TypeTuple : Type
--- a/dmd/struct.c	Fri Nov 16 10:01:24 2007 +0100
+++ b/dmd/struct.c	Sun Nov 18 06:52:57 2007 +0100
@@ -54,6 +54,8 @@
     llvmHasUnions = false;
     llvmUnion = NULL;
     llvmIRStruct = NULL;
+    llvmClassDeclared = false;
+    llvmClassDefined = false;
 }
 
 enum PROT AggregateDeclaration::prot()
--- a/gen/arrays.cpp	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/arrays.cpp	Sun Nov 18 06:52:57 2007 +0100
@@ -60,10 +60,8 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoNullArray(llvm::Value* v)
+void DtoSetArrayToNull(llvm::Value* v)
 {
-    assert(gIR);
-
     llvm::Value* len = DtoGEPi(v,0,0,"tmp",gIR->scopebb());
     llvm::Value* zerolen = llvm::ConstantInt::get(len->getType()->getContainedType(0), 0, false);
     new llvm::StoreInst(zerolen, len, gIR->scopebb());
@@ -593,7 +591,7 @@
     if (useti) {
         TypeInfoDeclaration* ti = DtoDType(l->getType())->next->getTypeInfoDeclaration();
         if (!ti->llvmValue) {
-            ti->toObjFile();
+            DtoForceConstInitDsymbol(ti);
         }
         Logger::cout() << "typeinfo decl: " << *ti->llvmValue << '\n';
 
@@ -786,3 +784,85 @@
     return 0;
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
+DValue* DtoCastArray(DValue* u, Type* to)
+{
+    const llvm::Type* tolltype = DtoType(to);
+
+    Type* totype = DtoDType(to);
+    Type* fromtype = DtoDType(u->getType());
+    assert(fromtype->ty == Tarray || fromtype->ty == Tsarray);
+
+    llvm::Value* rval;
+    llvm::Value* rval2;
+    bool isslice = false;
+
+    Logger::cout() << "from array or sarray" << '\n';
+    if (totype->ty == Tpointer) {
+        Logger::cout() << "to pointer" << '\n';
+        assert(fromtype->next == totype->next || totype->next->ty == Tvoid);
+        llvm::Value* ptr = DtoGEPi(u->getRVal(),0,1,"tmp",gIR->scopebb());
+        rval = new llvm::LoadInst(ptr, "tmp", gIR->scopebb());
+        if (fromtype->next != totype->next)
+            rval = gIR->ir->CreateBitCast(rval, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
+    }
+    else if (totype->ty == Tarray) {
+        Logger::cout() << "to array" << '\n';
+        const llvm::Type* ptrty = DtoType(totype->next);
+        if (ptrty == llvm::Type::VoidTy)
+            ptrty = llvm::Type::Int8Ty;
+        ptrty = llvm::PointerType::get(ptrty);
+
+        const llvm::Type* ety = DtoType(fromtype->next);
+        if (ety == llvm::Type::VoidTy)
+            ety = llvm::Type::Int8Ty;
+
+        if (DSliceValue* usl = u->isSlice()) {
+            Logger::println("from slice");
+            Logger::cout() << "from: " << *usl->ptr << " to: " << *ptrty << '\n';
+            rval = new llvm::BitCastInst(usl->ptr, ptrty, "tmp", gIR->scopebb());
+            if (fromtype->next->size() == totype->next->size())
+                rval2 = usl->len;
+            else
+                rval2 = DtoArrayCastLength(usl->len, ety, ptrty->getContainedType(0));
+        }
+        else {
+            llvm::Value* uval = u->getRVal();
+            if (fromtype->ty == Tsarray) {
+                Logger::cout() << "uvalTy = " << *uval->getType() << '\n';
+                assert(isaPointer(uval->getType()));
+                const llvm::ArrayType* arrty = isaArray(uval->getType()->getContainedType(0));
+                rval2 = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
+                rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
+                rval = new llvm::BitCastInst(uval, ptrty, "tmp", gIR->scopebb());
+            }
+            else {
+                llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+                llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
+                rval2 = DtoGEP(uval,zero,zero,"tmp",gIR->scopebb());
+                rval2 = new llvm::LoadInst(rval2, "tmp", gIR->scopebb());
+                rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
+
+                rval = DtoGEP(uval,zero,one,"tmp",gIR->scopebb());
+                rval = new llvm::LoadInst(rval, "tmp", gIR->scopebb());
+                //Logger::cout() << *e->mem->getType() << '|' << *ptrty << '\n';
+                rval = new llvm::BitCastInst(rval, ptrty, "tmp", gIR->scopebb());
+            }
+        }
+        isslice = true;
+    }
+    else if (totype->ty == Tsarray) {
+        Logger::cout() << "to sarray" << '\n';
+        assert(0);
+    }
+    else {
+        assert(0);
+    }
+
+    if (isslice) {
+        Logger::println("isslice");
+        return new DSliceValue(to, rval2, rval);
+    }
+
+    return new DImValue(to, rval);
+}
--- a/gen/arrays.h	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/arrays.h	Sun Nov 18 06:52:57 2007 +0100
@@ -16,7 +16,7 @@
 void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val);
 void DtoArrayAssign(llvm::Value* l, llvm::Value* r);
 void DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr);
-void DtoNullArray(llvm::Value* v);
+void DtoSetArrayToNull(llvm::Value* v);
 
 llvm::Value* DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool doinit=true);
 llvm::Value* DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz);
@@ -37,4 +37,6 @@
 llvm::Value* DtoArrayLen(DValue* v);
 llvm::Value* DtoArrayPtr(DValue* v);
 
+DValue* DtoCastArray(DValue* val, Type* to);
+
 #endif // LLVMC_GEN_ARRAYS_H
--- a/gen/classes.cpp	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/classes.cpp	Sun Nov 18 06:52:57 2007 +0100
@@ -10,6 +10,7 @@
 #include "gen/arrays.h"
 #include "gen/logger.h"
 #include "gen/classes.h"
+#include "gen/functions.h"
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
@@ -23,8 +24,6 @@
         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]);
@@ -38,12 +37,17 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoDeclareClass(ClassDeclaration* cd)
+void DtoResolveClass(ClassDeclaration* cd)
 {
-    if (cd->llvmTouched) return;
-    cd->llvmTouched = true;
+    if (cd->llvmResolved) return;
+    cd->llvmResolved = true;
 
-    Logger::println("DtoDeclareClass(%s)\n", cd->toPrettyChars());
+    // first resolve the base class
+    if (cd->baseClass) {
+        DtoResolveClass(cd->baseClass);
+    }
+
+    Logger::println("DtoResolveClass(%s)", cd->toPrettyChars());
     LOG_SCOPE;
 
     assert(cd->type->ty == Tclass);
@@ -57,8 +61,8 @@
     gIR->classes.push_back(cd);
 
     // add vtable
-    llvm::PATypeHolder pa = llvm::OpaqueType::get();
-    const llvm::Type* vtabty = llvm::PointerType::get(pa);
+    ts->llvmVtblType = new llvm::PATypeHolder(llvm::OpaqueType::get());
+    const llvm::Type* vtabty = llvm::PointerType::get(ts->llvmVtblType->get());
 
     std::vector<const llvm::Type*> fieldtypes;
     fieldtypes.push_back(vtabty);
@@ -80,13 +84,11 @@
     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;
@@ -100,10 +102,7 @@
 
     // 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++)
     {
@@ -112,73 +111,100 @@
         //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());
+            DtoResolveFunction(fd);
+            assert(fd->type->ty == Tfunction);
+            TypeFunction* tf = (TypeFunction*)fd->type;
+            const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get());
+            sinits_ty.push_back(fpty);
         }
         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;
+    assert(!sinits_ty.empty());
+    const llvm::StructType* svtbl_ty = llvm::StructType::get(sinits_ty);
+
+    std::string styname(cd->mangle());
+    styname.append("__vtblType");
+    gIR->module->addTypeName(styname, svtbl_ty);
 
-        std::string varname("_D");
-        varname.append(cd->mangle());
-        varname.append("6__vtblZ");
+    // refine for final vtable type
+    llvm::cast<llvm::OpaqueType>(ts->llvmVtblType->get())->refineAbstractTypeTo(svtbl_ty);
+
+    gIR->classes.pop_back();
+    gIR->structs.pop_back();
+
+    gIR->declareList.push_back(cd);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
 
-        std::string styname(cd->mangle());
-        styname.append("__vtblTy");
+void DtoDeclareClass(ClassDeclaration* cd)
+{
+    if (cd->llvmDeclared) return;
+    cd->llvmDeclared = true;
+
+    Logger::println("DtoDeclareClass(%s)", cd->toPrettyChars());
+    LOG_SCOPE;
 
-        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);
+    assert(cd->type->ty == Tclass);
+    TypeClass* ts = (TypeClass*)cd->type;
+
+    assert(cd->llvmIRStruct);
+    IRStruct* irstruct = cd->llvmIRStruct;
 
-        cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits));
-        if (needs_definition)
-            svtblVar->setInitializer(cd->llvmConstVtbl);
-        cd->llvmVtbl = svtblVar;
+    gIR->structs.push_back(irstruct);
+    gIR->classes.push_back(cd);
+
+    bool needs_definition = false;
+    if (cd->parent->isModule()) {
+        needs_definition = (cd->getModule() == gIR->dmodule);
     }
 
-    // refine for final vtable type
-    llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty);
+    // vtable
+    std::string varname("_D");
+    varname.append(cd->mangle());
+    varname.append("6__vtblZ");
 
+    std::string styname(cd->mangle());
+    styname.append("__vtblTy");
+
+    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
+
+    const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
+    cd->llvmVtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
+
+    // init
     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);
+    gIR->constInitList.push_back(cd);
     if (needs_definition)
-    gIR->defineQueue.push_back(cd);
+        gIR->defineList.push_back(cd);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
 void DtoConstInitClass(ClassDeclaration* cd)
 {
-    IRStruct* irstruct = cd->llvmIRStruct;
-    if (irstruct->constinited) return;
-    irstruct->constinited = true;
+    if (cd->llvmInitialized) return;
+    cd->llvmInitialized = true;
 
-    Logger::println("DtoConstInitClass(%s)\n", cd->toPrettyChars());
+    Logger::println("DtoConstInitClass(%s)", cd->toPrettyChars());
     LOG_SCOPE;
 
+    IRStruct* irstruct = cd->llvmIRStruct;
     gIR->structs.push_back(irstruct);
     gIR->classes.push_back(cd);
 
@@ -200,6 +226,7 @@
 
     // rest
     for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
+        Logger::println("adding fieldinit for: %s", i->second.var->toChars());
         fieldinits.push_back(i->second.init);
     }
 
@@ -210,24 +237,69 @@
 
     // generate initializer
     Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n';
-    Logger::println("%u %u fields", structtype->getNumElements(), fieldinits.size());
+
+    for(size_t i=0; i<structtype->getNumElements(); ++i) {
+        Logger::cout() << "s#" << i << " = " << *structtype->getElementType(i) << '\n';
+    }
+
+    for(size_t i=0; i<fieldinits.size(); ++i) {
+        Logger::cout() << "i#" << i << " = " << *fieldinits[i]->getType() << '\n';
+    }
+
     llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits);
     assert(_init);
     cd->llvmInitZ = _init;
 
+    // generate vtable initializer
+    std::vector<llvm::Constant*> sinits;
+
+    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()) {
+            DtoForceDeclareDsymbol(fd);
+            assert(fd->llvmValue);
+            llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
+            sinits.push_back(c);
+        }
+        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);
+        }
+        else
+        assert(0);
+    }
+
+    const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
+
+    /*for (size_t i=0; i< sinits.size(); ++i)
+    {
+        Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n';
+        Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n';
+        assert(svtbl_ty->getElementType(i) == sinits[i]->getType());
+    }*/
+
+    llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits);
+    cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit);
+
     gIR->classes.pop_back();
     gIR->structs.pop_back();
+
+    DtoDeclareClassInfo(cd);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
 void DtoDefineClass(ClassDeclaration* cd)
 {
-    IRStruct* irstruct = cd->llvmIRStruct;
-    if (irstruct->defined) return;
-    irstruct->defined = true;
+    if (cd->llvmDefined) return;
+    cd->llvmDefined = true;
 
-    Logger::println("DtoDefineClass(%s)\n", cd->toPrettyChars());
+    Logger::println("DtoDefineClass(%s)", cd->toPrettyChars());
     LOG_SCOPE;
 
     // get the struct (class) type
@@ -237,11 +309,11 @@
     bool def = false;
     if (cd->parent->isModule() && cd->getModule() == gIR->dmodule) {
         ts->llvmInit->setInitializer(cd->llvmInitZ);
+        cd->llvmVtbl->setInitializer(cd->llvmConstVtbl);
         def = true;
     }
 
     // generate classinfo
-    DtoDeclareClassInfo(cd);
     if (def) DtoDefineClassInfo(cd);
 }
 
@@ -302,21 +374,21 @@
 
 void DtoDeclareClassInfo(ClassDeclaration* cd)
 {
-    if (cd->llvmClass)
-        return;
+    if (cd->llvmClassDeclared) return;
+    cd->llvmClassDeclared = true;
 
-    Logger::println("CLASS INFO DECLARATION: %s", cd->toChars());
+    Logger::println("DtoDeclareClassInfo(%s)", cd->toChars());
     LOG_SCOPE;
 
     ClassDeclaration* cinfo = ClassDeclaration::classinfo;
-    cinfo->toObjFile();
-
-    const llvm::Type* st = cinfo->type->llvmType->get();
+    DtoResolveClass(cinfo);
 
     std::string gname("_D");
     gname.append(cd->mangle());
     gname.append("7__ClassZ");
 
+    const llvm::Type* st = cinfo->type->llvmType->get();
+
     cd->llvmClass = new llvm::GlobalVariable(st, true, llvm::GlobalValue::ExternalLinkage, NULL, gname, gIR->module);
 }
 
@@ -339,18 +411,26 @@
 //         void *defaultConstructor;
 //        }
 
-    if (cd->llvmClassZ)
-        return;
+    if (cd->llvmClassDefined) return;
+    cd->llvmClassDefined = true;
+
+    Logger::println("DtoDefineClassInfo(%s)", cd->toChars());
+    LOG_SCOPE;
 
-    Logger::println("CLASS INFO DEFINITION: %s", cd->toChars());
-    LOG_SCOPE;
+    assert(cd->type->ty == Tclass);
     assert(cd->llvmClass);
+    assert(cd->llvmInitZ);
+    assert(cd->llvmVtbl);
+    assert(cd->llvmConstVtbl);
+
+    TypeClass* cdty = (TypeClass*)cd->type;
+    assert(cdty->llvmInit);
 
     // holds the list of initializers for llvm
     std::vector<llvm::Constant*> inits;
 
     ClassDeclaration* cinfo = ClassDeclaration::classinfo;
-    DtoConstInitClass(cinfo);
+    DtoForceConstInitDsymbol(cinfo);
     assert(cinfo->llvmInitZ);
 
     llvm::Constant* c;
@@ -363,8 +443,12 @@
     // monitor
     // TODO no monitors yet
 
-    // initializer
-    c = cinfo->llvmInitZ->getOperand(1);
+    // byte[] init
+    const llvm::Type* byteptrty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    c = llvm::ConstantExpr::getBitCast(cdty->llvmInit, byteptrty);
+    assert(!cd->llvmInitZ->getType()->isAbstract());
+    size_t initsz = gTargetData->getTypeSize(cd->llvmInitZ->getType());
+    c = DtoConstSlice(DtoConstSize_t(initsz), c);
     inits.push_back(c);
 
     // class name
@@ -380,38 +464,77 @@
     inits.push_back(c);
 
     // vtbl array
-    c = cinfo->llvmInitZ->getOperand(3);
+    const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty);
+    assert(!cd->llvmVtbl->getType()->isAbstract());
+    c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty);
+    assert(!cd->llvmConstVtbl->getType()->isAbstract());
+    size_t vtblsz = gTargetData->getTypeSize(cd->llvmConstVtbl->getType());
+    c = DtoConstSlice(DtoConstSize_t(vtblsz), c);
     inits.push_back(c);
 
     // interfaces array
+    // TODO
     c = cinfo->llvmInitZ->getOperand(4);
     inits.push_back(c);
 
     // base classinfo
-    c = cinfo->llvmInitZ->getOperand(5);
-    inits.push_back(c);
+    if (cd->baseClass) {
+        DtoDeclareClassInfo(cd->baseClass);
+        c = cd->baseClass->llvmClass;
+        assert(c);
+        inits.push_back(c);
+    }
+    else {
+        // null
+        c = cinfo->llvmInitZ->getOperand(5);
+        inits.push_back(c);
+    }
 
     // destructor
+    // TODO
     c = cinfo->llvmInitZ->getOperand(6);
     inits.push_back(c);
 
     // invariant
+    // TODO
     c = cinfo->llvmInitZ->getOperand(7);
     inits.push_back(c);
 
-    // flags
-    c = cinfo->llvmInitZ->getOperand(8);
+    // uint flags, adapted from original dmd code
+    uint flags = 0;
+    //flags |= 4; // has offTi
+    //flags |= isCOMclass(); // IUnknown
+    if (cd->ctor) flags |= 8;
+    for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass)
+    {
+    if (cd2->members)
+    {
+        for (size_t i = 0; i < cd2->members->dim; i++)
+        {
+        Dsymbol *sm = (Dsymbol *)cd2->members->data[i];
+        //printf("sm = %s %s\n", sm->kind(), sm->toChars());
+        if (sm->hasPointers())
+            goto L2;
+        }
+    }
+    }
+    flags |= 2;         // no pointers
+L2:
+    c = DtoConstUint(flags);
     inits.push_back(c);
 
     // allocator
+    // TODO
     c = cinfo->llvmInitZ->getOperand(9);
     inits.push_back(c);
 
     // offset typeinfo
+    // TODO
     c = cinfo->llvmInitZ->getOperand(10);
     inits.push_back(c);
 
     // default constructor
+    // TODO
     c = cinfo->llvmInitZ->getOperand(11);
     inits.push_back(c);
 
--- a/gen/classes.h	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/classes.h	Sun Nov 18 06:52:57 2007 +0100
@@ -2,6 +2,11 @@
 #define LLVMDC_GEN_CLASSES_H
 
 /**
+ * Resolves the llvm type for a class declaration
+ */
+void DtoResolveClass(ClassDeclaration* cd);
+
+/**
  * Provides the llvm declaration for a class declaration
  */
 void DtoDeclareClass(ClassDeclaration* cd);
--- a/gen/functions.cpp	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/functions.cpp	Sun Nov 18 06:52:57 2007 +0100
@@ -71,7 +71,7 @@
     if (typesafeVararg) {
         ClassDeclaration* ti = Type::typeinfo;
         ti->toObjFile();
-        DtoConstInitClass(ti);
+        DtoForceConstInitDsymbol(ti);
         assert(ti->llvmInitZ);
         std::vector<const llvm::Type*> types;
         types.push_back(DtoSize_t());
@@ -131,10 +131,10 @@
     f->llvmRetInPtr = retinptr;
     f->llvmUsesThis = usesthis;
 
-    if (!f->llvmType)
+    //if (!f->llvmType)
         f->llvmType = new llvm::PATypeHolder(functype);
-    else
-        assert(functype == f->llvmType->get());
+    //else
+        //assert(functype == f->llvmType->get());
 
     return functype;
 }
@@ -143,6 +143,11 @@
 
 static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
 {
+    // type has already been resolved
+    if (fdecl->type->llvmType != 0) {
+        return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType->get());
+    }
+
     TypeFunction* f = (TypeFunction*)fdecl->type;
     assert(f != 0);
 
@@ -163,10 +168,7 @@
 
     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());
+    f->llvmType = new llvm::PATypeHolder(fty);
 
     return fty;
 }
@@ -190,7 +192,7 @@
             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())
+            if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->recty.get()))
                 thisty = llvm::PointerType::get(thisty);
         }
         else
@@ -233,8 +235,57 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+void DtoResolveFunction(FuncDeclaration* fdecl)
+{
+    if (fdecl->llvmResolved) return;
+    fdecl->llvmResolved = true;
+
+    Logger::println("DtoResolveFunction(%s)", fdecl->toPrettyChars());
+    LOG_SCOPE;
+
+    if (fdecl->llvmRunTimeHack) {
+        gIR->declareList.push_back(fdecl);
+        return;
+    }
+
+    if (fdecl->isUnitTestDeclaration()) {
+        Logger::attention("ignoring unittest declaration: %s", fdecl->toChars());
+        return;
+    }
+
+    if (fdecl->parent)
+    if (TemplateInstance* tinst = fdecl->parent->isTemplateInstance())
+    {
+        TemplateDeclaration* tempdecl = tinst->tempdecl;
+        if (tempdecl->llvmInternal == LLVMva_arg)
+        {
+            Logger::println("magic va_arg found");
+            fdecl->llvmInternal = LLVMva_arg;
+            fdecl->llvmDeclared = true;
+            fdecl->llvmInitialized = true;
+            fdecl->llvmDefined = true;
+            return; // this gets mapped to an instruction so a declaration makes no sence
+        }
+        else if (tempdecl->llvmInternal == LLVMva_start)
+        {
+            Logger::println("magic va_start found");
+            fdecl->llvmInternal = LLVMva_start;
+        }
+    }
+
+    DtoFunctionType(fdecl);
+
+    // queue declaration
+    gIR->declareList.push_back(fdecl);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 void DtoDeclareFunction(FuncDeclaration* fdecl)
 {
+    if (fdecl->llvmDeclared) return;
+    fdecl->llvmDeclared = true;
+
     Logger::println("DtoDeclareFunction(%s)", fdecl->toPrettyChars());
     LOG_SCOPE;
 
@@ -245,34 +296,12 @@
         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;
+    bool templInst = fdecl->parent && DtoIsTemplateInstance(fdecl->parent);
+    if (!templInst && fdecl->getModule() != gIR->dmodule)
+        declareOnly = true;
+    else if (fdecl->llvmInternal == LLVMva_start)
+        declareOnly = true;
 
     if (!fdecl->llvmIRFunc) {
         fdecl->llvmIRFunc = new IRFunction(fdecl);
@@ -384,7 +413,7 @@
     }
 
     if (!declareOnly)
-        gIR->defineQueue.push_back(fdecl);
+        gIR->defineList.push_back(fdecl);
 
     Logger::cout() << "func decl: " << *func << '\n';
 }
@@ -394,6 +423,12 @@
 // TODO split this monster up
 void DtoDefineFunc(FuncDeclaration* fd)
 {
+    if (fd->llvmDefined) return;
+    fd->llvmDefined = true;
+
+    Logger::println("DtoDefineFunc(%s)", fd->toPrettyChars());
+    LOG_SCOPE;
+
     // debug info
     if (global.params.symdebug) {
         Module* mo = fd->getModule();
--- a/gen/functions.h	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/functions.h	Sun Nov 18 06:52:57 2007 +0100
@@ -4,6 +4,7 @@
 const llvm::FunctionType* DtoFunctionType(Type* t, const llvm::Type* thistype, bool ismain = false);
 const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl);
 
+void DtoResolveFunction(FuncDeclaration* fdecl);
 void DtoDeclareFunction(FuncDeclaration* fdecl);
 void DtoDefineFunc(FuncDeclaration* fd);
 
--- a/gen/irstate.h	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/irstate.h	Sun Nov 18 06:52:57 2007 +0100
@@ -5,6 +5,7 @@
 #include <vector>
 #include <deque>
 #include <map>
+#include <list>
 
 #include "root.h"
 
@@ -176,11 +177,15 @@
     // builder helper
     IRBuilderHelper ir;
 
-    typedef std::vector<Dsymbol*> DsymbolVector;
+    typedef std::list<Dsymbol*> DsymbolList;
+    // dsymbols that need to be resolved
+    DsymbolList resolveList;
+    // dsymbols that need to be declared
+    DsymbolList declareList;
     // dsymbols that need constant initializers constructed
-    DsymbolVector constInitQueue;
-    // dsymbols that need definitions (symbols in current module)
-    DsymbolVector defineQueue;
+    DsymbolList constInitList;
+    // dsymbols that need definitions
+    DsymbolList defineList;
 };
 
 #endif // LLVMDC_GEN_IRSTATE_H
--- a/gen/logger.cpp	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/logger.cpp	Sun Nov 18 06:52:57 2007 +0100
@@ -16,8 +16,9 @@
     static bool enabled = false;
     void indent()
     {
-        if (enabled)
-        indent_str += "  ";
+        if (enabled) {
+            indent_str += "* ";
+        }
     }
     void undent()
     {
--- a/gen/structs.cpp	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/structs.cpp	Sun Nov 18 06:52:57 2007 +0100
@@ -96,6 +96,7 @@
         inits.push_back(DUnionIdx(vd->llvmFieldIndex, vd->llvmFieldIndexOffset, v));
     }
 
+    DtoConstInitStruct((StructDeclaration*)si->ad);
     return si->ad->llvmUnion->getConst(inits);
 }
 
@@ -165,12 +166,12 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoDeclareStruct(StructDeclaration* sd)
+void DtoResolveStruct(StructDeclaration* sd)
 {
-    if (sd->llvmTouched) return;
-    sd->llvmTouched = true;
+    if (sd->llvmResolved) return;
+    sd->llvmResolved = true;
 
-    Logger::println("DtoDeclareStruct(%s)", sd->toChars());
+    Logger::println("DtoResolveStruct(%s)", sd->toChars());
     LOG_SCOPE;
 
     TypeStruct* ts = (TypeStruct*)DtoDType(sd->type);
@@ -280,6 +281,23 @@
         gIR->module->addTypeName(sd->mangle(),structtype);
     }
 
+    gIR->structs.pop_back();
+
+    gIR->declareList.push_back(sd);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoDeclareStruct(StructDeclaration* sd)
+{
+    if (sd->llvmDeclared) return;
+    sd->llvmDeclared = true;
+
+    Logger::println("DtoDeclareStruct(%s)", sd->toChars());
+    LOG_SCOPE;
+
+    TypeStruct* ts = (TypeStruct*)DtoDType(sd->type);
+
     std::string initname("_D");
     initname.append(sd->mangle());
     initname.append("6__initZ");
@@ -288,28 +306,22 @@
     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);
+    gIR->constInitList.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);
+        gIR->defineList.push_back(sd);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
 void DtoConstInitStruct(StructDeclaration* sd)
 {
-    IRStruct* irstruct = sd->llvmIRStruct;
-    if (irstruct->constinited) return;
-    irstruct->constinited = true;
+    if (sd->llvmInitialized) return;
+    sd->llvmInitialized = true;
 
     Logger::println("DtoConstInitStruct(%s)", sd->toChars());
     LOG_SCOPE;
 
+    IRStruct* irstruct = sd->llvmIRStruct;
     gIR->structs.push_back(irstruct);
 
     // make sure each offset knows its default initializer
@@ -365,17 +377,18 @@
     }
 
     gIR->structs.pop_back();
+
+    // emit typeinfo
+    if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMnotypeinfo)
+        sd->type->getTypeInfo(NULL);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
 void DtoDefineStruct(StructDeclaration* sd)
 {
-    IRStruct* irstruct = sd->llvmIRStruct;
-    if (irstruct->defined) return;
-    irstruct->defined = true;
-
-    DtoConstInitStruct(sd);
+    if (sd->llvmDefined) return;
+    sd->llvmDefined = true;
 
     Logger::println("DtoDefineStruct(%s)", sd->toChars());
     LOG_SCOPE;
--- a/gen/structs.h	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/structs.h	Sun Nov 18 06:52:57 2007 +0100
@@ -11,6 +11,11 @@
 llvm::Constant* DtoConstStructInitializer(StructInitializer* si);
 
 /**
+ * Resolves the llvm type for a struct
+ */
+void DtoResolveStruct(StructDeclaration* sd);
+
+/**
  * Provides the llvm declaration for a struct
  */
 void DtoDeclareStruct(StructDeclaration* sd);
--- a/gen/toir.cpp	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/toir.cpp	Sun Nov 18 06:52:57 2007 +0100
@@ -27,6 +27,7 @@
 #include "gen/arrays.h"
 #include "gen/structs.h"
 #include "gen/classes.h"
+#include "gen/typeinf.h"
 
 #include "gen/dvalue.h"
 
@@ -45,7 +46,7 @@
         // static
         if (vd->isDataseg())
         {
-            vd->toObjFile();
+            vd->toObjFile(); // TODO
         }
         else
         {
@@ -75,13 +76,13 @@
     else if (StructDeclaration* s = declaration->isStructDeclaration())
     {
         Logger::println("StructDeclaration");
-        s->toObjFile();
+        DtoForceConstInitDsymbol(s);
     }
     // function declaration
     else if (FuncDeclaration* f = declaration->isFuncDeclaration())
     {
         Logger::println("FuncDeclaration");
-        f->toObjFile();
+        DtoForceDeclareDsymbol(f);
     }
     // alias declaration
     else if (AliasDeclaration* a = declaration->isAliasDeclaration())
@@ -145,7 +146,7 @@
         else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
         {
             Logger::println("TypeInfoDeclaration");
-            tid->toObjFile();
+            DtoForceDeclareDsymbol(tid);
             assert(tid->llvmValue);
             const llvm::Type* vartype = DtoType(type);
             llvm::Value* m;
@@ -159,6 +160,7 @@
         else if (ClassInfoDeclaration* cid = vd->isClassInfoDeclaration())
         {
             Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars());
+            DtoDeclareClassInfo(cid->cd);
             assert(cid->cd->llvmClass);
             return new DVarValue(vd, cid->cd->llvmClass, true);
         }
@@ -199,8 +201,9 @@
     else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
     {
         Logger::println("FuncDeclaration");
-        if (fdecl->llvmInternal != LLVMva_arg)// && fdecl->llvmValue == 0)
-            fdecl->toObjFile();
+        if (fdecl->llvmInternal != LLVMva_arg) {// && fdecl->llvmValue == 0)
+            DtoForceDeclareDsymbol(fdecl);
+        }
         return new DFuncValue(fdecl, fdecl->llvmValue);
     }
     else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
@@ -234,8 +237,7 @@
         Logger::print("Sym: type=%s\n", sdecltype->toChars());
         assert(sdecltype->ty == Tstruct);
         TypeStruct* ts = (TypeStruct*)sdecltype;
-        ts->sym->toObjFile();
-        DtoConstInitStruct(ts->sym);
+        DtoForceConstInitDsymbol(ts->sym);
         assert(ts->sym->llvmInitZ);
         return ts->sym->llvmInitZ;
     }
@@ -1063,7 +1065,7 @@
     bool delegateCall = false;
     llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false);
     llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty,1,false);
-    LINK dlink = LINKdefault;
+    LINK dlink = LINKd;
 
     // hidden struct return parameter handling
     bool retinptr = false;
@@ -1117,7 +1119,7 @@
                 llt = llvm::PointerType::get(llt);
             // TODO
             if (strcmp(global.params.llvmArch, "x86") != 0) {
-                warning("va_arg for C variadic functions is broken for anything but x86");
+                warning("%s: va_arg for C variadic functions is broken for anything but x86", loc.toChars());
             }
             return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp"));
         }
@@ -1267,7 +1269,7 @@
                 vtypes.push_back(vvalues.back()->getType());
 
                 TypeInfoDeclaration* tidecl = argexp->type->getTypeInfoDeclaration();
-                tidecl->toObjFile();
+                DtoForceDeclareDsymbol(tidecl);
                 assert(tidecl->llvmValue);
                 vtypeinfos.push_back(tidecl->llvmValue);
             }
@@ -1306,8 +1308,10 @@
                 llargs[j] = DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]);
                 // this hack is necessary :/
                 if (dfn && dfn->func && dfn->func->llvmRunTimeHack) {
-                    if (llargs[j]->getType() != llfnty->getParamType(j))
+                    Logger::println("llvmRunTimeHack==true");
+                    if (llargs[j]->getType() != llfnty->getParamType(j)) {
                         llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
+                    }
                 }
             }
             Logger::println("%d params passed", n);
@@ -1336,13 +1340,13 @@
             call->setCallingConv(DtoCallingConv(dlink));
         }
     }
-    else if (delegateCall) {
+    /*else if (delegateCall) {
         call->setCallingConv(DtoCallingConv(dlink));
-    }
+    }*/
     else if (dfn && dfn->cc != (unsigned)-1) {
         call->setCallingConv(dfn->cc);
     }
-    else if (llvm::isa<llvm::LoadInst>(funcval)) {
+    else {
         call->setCallingConv(DtoCallingConv(dlink));
     }
 
@@ -1385,8 +1389,11 @@
     if (VarDeclaration* vd = var->isVarDeclaration())
     {
         Logger::println("VarDeclaration");
-        if (!vd->llvmTouched && vd->isDataseg())
-            vd->toObjFile();
+
+        // handle forward reference
+        if (!vd->llvmDeclared && vd->isDataseg()) {
+            vd->toObjFile(); // TODO
+        }
 
         assert(vd->llvmValue);
         Type* t = DtoDType(type);
@@ -1465,7 +1472,7 @@
         FuncDeclaration* fd = fv->func;
         assert(fd);
         if (fd->llvmValue == 0)
-            fd->toObjFile();
+            DtoForceDeclareDsymbol(fd);
         return new DFuncValue(fd, fd->llvmValue);
     }
     else if (DImValue* im = v->isIm()) {
@@ -1539,7 +1546,7 @@
     {
         if (fdecl->llvmValue == 0)
         {
-            fdecl->toObjFile();
+            DtoForceDeclareDsymbol(fdecl);
         }
 
         llvm::Value* funcval = fdecl->llvmValue;
@@ -2099,7 +2106,7 @@
         llvm::Value* ptr = DtoGEP(val,zero,one,"tmp",p->scopebb());
         ptr = new llvm::LoadInst(ptr,"tmp",p->scopebb());
         new llvm::FreeInst(ptr, p->scopebb());
-        DtoNullArray(val);
+        DtoSetArrayToNull(val);
     }
     else {
         assert(0);
@@ -2507,7 +2514,7 @@
     if (fd->isNested()) Logger::println("nested");
     Logger::println("kind = %s\n", fd->kind());
 
-    fd->toObjFile();
+    DtoForceDeclareDsymbol(fd);
 
     bool temp = false;
     llvm::Value* lval = NULL;
--- a/gen/tollvm.cpp	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/tollvm.cpp	Sun Nov 18 06:52:57 2007 +0100
@@ -17,6 +17,7 @@
 #include "gen/functions.h"
 #include "gen/structs.h"
 #include "gen/classes.h"
+#include "gen/typeinf.h"
 
 bool DtoIsPassedByRef(Type* type)
 {
@@ -114,7 +115,7 @@
             // forward declaration
             TypeStruct* ts = (TypeStruct*)t;
             assert(ts->sym);
-            ts->sym->toObjFile();
+            DtoResolveDsymbol(ts->sym);
         }
         return t->llvmType->get();
     }
@@ -137,7 +138,7 @@
             // forward declaration
             TypeClass* tc = (TypeClass*)t;
             assert(tc->sym);
-            tc->sym->toObjFile();
+            DtoResolveDsymbol(tc->sym);
         }
         return llvm::PointerType::get(t->llvmType->get());
     }
@@ -654,7 +655,17 @@
     llargs.resize(3);
     llargs[0] = cond ? DtoBoolean(cond) : llvm::ConstantInt::getFalse();
     llargs[1] = DtoConstUint(loc->linnum);
-    llargs[2] = msg ? msg->getRVal() : llvm::Constant::getNullValue(fnt->getParamType(2));
+    if (msg)
+        llargs[2] = msg->getRVal();
+    else {
+        llvm::Constant* c = DtoConstSlice(DtoConstSize_t(0), DtoConstNullPtr(llvm::Type::Int8Ty));
+        static llvm::AllocaInst* alloc = 0;
+        if (!alloc || alloc->getParent()->getParent() != gIR->func()->func) {
+            alloc = new llvm::AllocaInst(c->getType(), "assertnullparam", gIR->topallocapoint());
+            DtoSetArrayToNull(alloc);
+        }
+        llargs[2] = alloc;
+    }
 
     assert(fn);
     llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
@@ -861,7 +872,7 @@
         }
         // null
         else if (rhs->isNull()) {
-            DtoNullArray(lhs->getLVal());
+            DtoSetArrayToNull(lhs->getLVal());
         }
         // reference assignment
         else {
@@ -1030,87 +1041,6 @@
     return new DImValue(_to, rval);
 }
 
-DValue* DtoCastArray(DValue* u, Type* to)
-{
-    const llvm::Type* tolltype = DtoType(to);
-
-    Type* totype = DtoDType(to);
-    Type* fromtype = DtoDType(u->getType());
-    assert(fromtype->ty == Tarray || fromtype->ty == Tsarray);
-
-    llvm::Value* rval;
-    llvm::Value* rval2;
-    bool isslice = false;
-
-    Logger::cout() << "from array or sarray" << '\n';
-    if (totype->ty == Tpointer) {
-        Logger::cout() << "to pointer" << '\n';
-        assert(fromtype->next == totype->next || totype->next->ty == Tvoid);
-        llvm::Value* ptr = DtoGEPi(u->getRVal(),0,1,"tmp",gIR->scopebb());
-        rval = new llvm::LoadInst(ptr, "tmp", gIR->scopebb());
-        if (fromtype->next != totype->next)
-            rval = gIR->ir->CreateBitCast(rval, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
-    }
-    else if (totype->ty == Tarray) {
-        Logger::cout() << "to array" << '\n';
-        const llvm::Type* ptrty = DtoType(totype->next);
-        if (ptrty == llvm::Type::VoidTy)
-            ptrty = llvm::Type::Int8Ty;
-        ptrty = llvm::PointerType::get(ptrty);
-
-        const llvm::Type* ety = DtoType(fromtype->next);
-        if (ety == llvm::Type::VoidTy)
-            ety = llvm::Type::Int8Ty;
-
-        if (DSliceValue* usl = u->isSlice()) {
-            Logger::println("from slice");
-            rval = new llvm::BitCastInst(usl->ptr, ptrty, "tmp", gIR->scopebb());
-            if (fromtype->next->size() == totype->next->size())
-                rval2 = usl->len;
-            else
-                rval2 = DtoArrayCastLength(usl->len, ety, ptrty->getContainedType(0));
-        }
-        else {
-            llvm::Value* uval = u->getRVal();
-            if (fromtype->ty == Tsarray) {
-                Logger::cout() << "uvalTy = " << *uval->getType() << '\n';
-                assert(isaPointer(uval->getType()));
-                const llvm::ArrayType* arrty = isaArray(uval->getType()->getContainedType(0));
-                rval2 = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
-                rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
-                rval = new llvm::BitCastInst(uval, ptrty, "tmp", gIR->scopebb());
-            }
-            else {
-                llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-                llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
-                rval2 = DtoGEP(uval,zero,zero,"tmp",gIR->scopebb());
-                rval2 = new llvm::LoadInst(rval2, "tmp", gIR->scopebb());
-                rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
-
-                rval = DtoGEP(uval,zero,one,"tmp",gIR->scopebb());
-                rval = new llvm::LoadInst(rval, "tmp", gIR->scopebb());
-                //Logger::cout() << *e->mem->getType() << '|' << *ptrty << '\n';
-                rval = new llvm::BitCastInst(rval, ptrty, "tmp", gIR->scopebb());
-            }
-        }
-        isslice = true;
-    }
-    else if (totype->ty == Tsarray) {
-        Logger::cout() << "to sarray" << '\n';
-        assert(0);
-    }
-    else {
-        assert(0);
-    }
-
-    if (isslice) {
-        Logger::println("isslice");
-        return new DSliceValue(to, rval2, rval);
-    }
-
-    return new DImValue(to, rval);
-}
-
 DValue* DtoCast(DValue* val, Type* to)
 {
     Type* fromtype = DtoDType(val->getType());
@@ -1180,6 +1110,15 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+llvm::Constant* DtoConstNullPtr(const llvm::Type* t)
+{
+    return llvm::ConstantPointerNull::get(
+        llvm::PointerType::get(t)
+    );
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes)
 {
     assert(dst->getType() == src->getType());
@@ -1321,20 +1260,45 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoDefineDsymbol(Dsymbol* dsym)
+void DtoResolveDsymbol(Dsymbol* dsym)
 {
     if (StructDeclaration* sd = dsym->isStructDeclaration()) {
-        DtoDefineStruct(sd);
+        DtoResolveStruct(sd);
     }
     else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
-        DtoDefineClass(cd);
+        DtoResolveClass(cd);
     }
     else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
-        DtoDefineFunc(fd);
+        DtoResolveFunction(fd);
+    }
+    else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
+        DtoResolveTypeInfo(fd);
     }
     else {
     error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
-    assert(0 && "unsupported dsymbol for DtoDefineDsymbol");
+    assert(0 && "unsupported dsymbol for DtoResolveDsymbol");
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoDeclareDsymbol(Dsymbol* dsym)
+{
+    if (StructDeclaration* sd = dsym->isStructDeclaration()) {
+        DtoDeclareStruct(sd);
+    }
+    else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
+        DtoDeclareClass(cd);
+    }
+    else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
+        DtoDeclareFunction(fd);
+    }
+    else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
+        DtoDeclareTypeInfo(fd);
+    }
+    else {
+    error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
+    assert(0 && "unsupported dsymbol for DtoDeclareDsymbol");
     }
 }
 
@@ -1348,12 +1312,37 @@
     else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
         DtoConstInitClass(cd);
     }
+    else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
+        DtoConstInitTypeInfo(fd);
+    }
     else if (VarDeclaration* vd = dsym->isVarDeclaration()) {
         DtoConstInitGlobal(vd);
     }
     else {
     error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
-    assert(0 && "unsupported dsymbol for DtoInitDsymbol");
+    assert(0 && "unsupported dsymbol for DtoConstInitDsymbol");
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+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 if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
+        DtoDefineTypeInfo(fd);
+    }
+    else {
+    error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
+    assert(0 && "unsupported dsymbol for DtoDefineDsymbol");
     }
 }
 
@@ -1361,11 +1350,11 @@
 
 void DtoConstInitGlobal(VarDeclaration* vd)
 {
-    Logger::println("DtoConstInitGlobal(%s)", vd->toChars());
-    LOG_SCOPE;
+    if (vd->llvmInitialized) return;
+    vd->llvmInitialized = gIR->dmodule;
 
-    if (vd->llvmDModule) return;
-    vd->llvmDModule = gIR->dmodule;
+    Logger::println("* DtoConstInitGlobal(%s)", vd->toChars());
+    LOG_SCOPE;
 
     bool emitRTstaticInit = false;
 
@@ -1428,3 +1417,100 @@
     if (emitRTstaticInit)
         DtoLazyStaticInit(istempl, gvar, vd->init, t);
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoEmptyResolveList()
+{
+    //Logger::println("DtoEmptyResolveList()");
+    Dsymbol* dsym;
+    while (!gIR->resolveList.empty()) {
+        dsym = gIR->resolveList.front();
+        gIR->resolveList.pop_front();
+        DtoResolveDsymbol(dsym);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoEmptyDeclareList()
+{
+    //Logger::println("DtoEmptyDeclareList()");
+    Dsymbol* dsym;
+    while (!gIR->declareList.empty()) {
+        dsym = gIR->declareList.front();
+        gIR->declareList.pop_front();
+        DtoDeclareDsymbol(dsym);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoEmptyConstInitList()
+{
+    //Logger::println("DtoEmptyConstInitList()");
+    Dsymbol* dsym;
+    while (!gIR->constInitList.empty()) {
+        dsym = gIR->constInitList.front();
+        gIR->constInitList.pop_front();
+        DtoConstInitDsymbol(dsym);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoEmptyDefineList()
+{
+    //Logger::println("DtoEmptyDefineList()");
+    Dsymbol* dsym;
+    while (!gIR->defineList.empty()) {
+        dsym = gIR->defineList.front();
+        gIR->defineList.pop_front();
+        DtoDefineDsymbol(dsym);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoForceDeclareDsymbol(Dsymbol* dsym)
+{
+    if (dsym->llvmDeclared) return;
+    Logger::println("DtoForceDeclareDsymbol(%s)", dsym->toChars());
+    LOG_SCOPE;
+    DtoResolveDsymbol(dsym);
+
+    DtoEmptyResolveList();
+
+    DtoDeclareDsymbol(dsym);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoForceConstInitDsymbol(Dsymbol* dsym)
+{
+    if (dsym->llvmInitialized) return;
+    Logger::println("DtoForceConstInitDsymbol(%s)", dsym->toChars());
+    LOG_SCOPE;
+    DtoResolveDsymbol(dsym);
+
+    DtoEmptyResolveList();
+    DtoEmptyDeclareList();
+
+    DtoConstInitDsymbol(dsym);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoForceDefineDsymbol(Dsymbol* dsym)
+{
+    if (dsym->llvmDefined) return;
+    Logger::println("DtoForceDefineDsymbol(%s)", dsym->toChars());
+    LOG_SCOPE;
+    DtoResolveDsymbol(dsym);
+
+    DtoEmptyResolveList();
+    DtoEmptyDeclareList();
+    DtoEmptyConstInitList();
+
+    DtoDefineDsymbol(dsym);
+}
--- a/gen/tollvm.h	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/tollvm.h	Sun Nov 18 06:52:57 2007 +0100
@@ -53,15 +53,26 @@
 llvm::Constant* DtoConstString(const char*);
 llvm::Constant* DtoConstStringPtr(const char* str, const char* section = 0);
 llvm::Constant* DtoConstBool(bool);
+llvm::Constant* DtoConstNullPtr(const llvm::Type* t);
 
 bool DtoIsTemplateInstance(Dsymbol* s);
 
 void DtoLazyStaticInit(bool istempl, llvm::Value* gvar, Initializer* init, Type* t);
 
+void DtoResolveDsymbol(Dsymbol* dsym);
+void DtoDeclareDsymbol(Dsymbol* dsym);
 void DtoDefineDsymbol(Dsymbol* dsym);
 void DtoConstInitDsymbol(Dsymbol* dsym);
+
 void DtoConstInitGlobal(VarDeclaration* vd);
 
+void DtoEmptyResolveList();
+void DtoEmptyDeclareList();
+void DtoEmptyConstInitList();
+void DtoForceDeclareDsymbol(Dsymbol* dsym);
+void DtoForceConstInitDsymbol(Dsymbol* dsym);
+void DtoForceDefineDsymbol(Dsymbol* dsym);
+
 // llvm wrappers
 void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes);
 bool DtoCanLoad(llvm::Value* ptr);
@@ -87,7 +98,6 @@
 DValue* DtoCastInt(DValue* val, Type* to);
 DValue* DtoCastPtr(DValue* val, Type* to);
 DValue* DtoCastFloat(DValue* val, Type* to);
-DValue* DtoCastArray(DValue* val, Type* to);
 DValue* DtoCastClass(DValue* val, Type* to);
 DValue* DtoCast(DValue* val, Type* to);
 
--- a/gen/toobj.cpp	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/toobj.cpp	Sun Nov 18 06:52:57 2007 +0100
@@ -92,14 +92,33 @@
         dsym->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]);
+    // main driver loop
+    for(;;)
+    {
+        Dsymbol* dsym;
+        if (!ir.resolveList.empty()) {
+            dsym = ir.resolveList.front();
+            ir.resolveList.pop_front();
+            DtoResolveDsymbol(dsym);
+        }
+        else if (!ir.declareList.empty()) {
+            dsym = ir.declareList.front();
+            ir.declareList.pop_front();
+            DtoDeclareDsymbol(dsym);
+        }
+        else if (!ir.constInitList.empty()) {
+            dsym = ir.constInitList.front();
+            ir.constInitList.pop_front();
+            DtoConstInitDsymbol(dsym);
+        }
+        else if (!ir.defineList.empty()) {
+            dsym = ir.defineList.front();
+            ir.defineList.pop_front();
+            DtoDefineDsymbol(dsym);
+        }
+        else {
+            break;
+        }
     }
 
     // generate ModuleInfo
@@ -326,7 +345,7 @@
 
 void StructDeclaration::toObjFile()
 {
-    DtoDeclareStruct(this);
+    gIR->resolveList.push_back(this);
 }
 
 /* ================================================================== */
@@ -364,7 +383,7 @@
 
 void ClassDeclaration::toObjFile()
 {
-    DtoDeclareClass(this);
+    gIR->resolveList.push_back(this);
 }
 
 /******************************************
@@ -394,8 +413,9 @@
     // global variable or magic
     if (isDataseg())
     {
-        if (llvmTouched) return;
-        else llvmTouched = true;
+        if (llvmResolved) return;
+        llvmResolved = true;
+        llvmDeclared = true;
 
         llvmIRGlobal = new IRGlobal(this);
 
@@ -430,7 +450,7 @@
         if (static_local)
             DtoConstInitGlobal(this);
         else
-            gIR->constInitQueue.push_back(this);
+            gIR->constInitList.push_back(this);
 
         //if (storage_class & STCprivate)
         //    gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility);
@@ -473,5 +493,5 @@
 
 void FuncDeclaration::toObjFile()
 {
-    DtoDeclareFunction(this);
+    gIR->resolveList.push_back(this);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/typeinf.h	Sun Nov 18 06:52:57 2007 +0100
@@ -0,0 +1,9 @@
+#ifndef LLVMDC_GEN_TYPEINF_H
+#define LLVMDC_GEN_TYPEINF_H
+
+void DtoResolveTypeInfo(TypeInfoDeclaration* tid);
+void DtoDeclareTypeInfo(TypeInfoDeclaration* tid);
+void DtoConstInitTypeInfo(TypeInfoDeclaration* tid);
+void DtoDefineTypeInfo(TypeInfoDeclaration* tid);
+
+#endif
--- a/gen/typinf.cpp	Fri Nov 16 10:01:24 2007 +0100
+++ b/gen/typinf.cpp	Sun Nov 18 06:52:57 2007 +0100
@@ -8,6 +8,10 @@
 // in artistic.txt, or the GNU General Public License in gnu.txt.
 // See the included readme.txt for details.
 
+// Modifications for LLVMDC:
+// Copyright (c) 2007 by Tomas Lindquist Olsen
+// tomas at famolsen dk
+
 #include <cstdio>
 #include <cassert>
 
@@ -238,32 +242,76 @@
 
 void TypeInfoDeclaration::toObjFile()
 {
-    if (llvmTouched) return;
-    else llvmTouched = true;
+    gIR->resolveList.push_back(this);
+}
 
-    Logger::println("TypeInfoDeclaration::toObjFile()");
+void DtoResolveTypeInfo(TypeInfoDeclaration* tid)
+{
+    if (tid->llvmResolved) return;
+    tid->llvmResolved = true;
+
+    Logger::println("* DtoResolveTypeInfo(%s)", tid->toChars());
     LOG_SCOPE;
 
-    std::string mangled(mangle());
+    tid->llvmIRGlobal = new IRGlobal(tid);
+
+    gIR->declareList.push_back(tid);
+}
 
-    Logger::println("type = '%s'", tinfo->toChars());
+void DtoDeclareTypeInfo(TypeInfoDeclaration* tid)
+{
+    if (tid->llvmDeclared) return;
+    tid->llvmDeclared = true;
+
+    Logger::println("* DtoDeclareTypeInfo(%s)", tid->toChars());
+    LOG_SCOPE;
+
+    std::string mangled(tid->mangle());
+
+    Logger::println("type = '%s'", tid->tinfo->toChars());
     Logger::println("typeinfo mangle: %s", mangled.c_str());
 
     // this is a declaration of a builtin __initZ var
-    if (tinfo->builtinTypeInfo()) {
-        llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangled.c_str());
-        assert(llvmValue);
+    if (tid->tinfo->builtinTypeInfo()) {
+        tid->llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangled.c_str());
+        assert(tid->llvmValue);
         mangled.append("__TYPE");
-        gIR->module->addTypeName(mangled, llvmValue->getType()->getContainedType(0));
-        Logger::println("Got typeinfo var: %s", llvmValue->getName().c_str());
+        gIR->module->addTypeName(mangled, tid->llvmValue->getType()->getContainedType(0));
+        Logger::println("Got typeinfo var: %s", tid->llvmValue->getName().c_str());
+        tid->llvmInitialized = true;
+        tid->llvmDefined = true;
     }
     // custom typedef
     else {
-        // emit globals
-        toDt(NULL);
+        gIR->constInitList.push_back(tid);
     }
 }
 
+void DtoConstInitTypeInfo(TypeInfoDeclaration* tid)
+{
+    if (tid->llvmInitialized) return;
+    tid->llvmInitialized = true;
+
+    Logger::println("* DtoConstInitTypeInfo(%s)", tid->toChars());
+    LOG_SCOPE;
+
+    tid->toDt(NULL);
+
+    tid->llvmDefined = true;
+    //gIR->defineList.push_back(tid);
+}
+
+void DtoDefineTypeInfo(TypeInfoDeclaration* tid)
+{
+    if (tid->llvmDefined) return;
+    tid->llvmDefined = true;
+
+    Logger::println("* DtoDefineTypeInfo(%s)", tid->toChars());
+    LOG_SCOPE;
+
+    assert(0);
+}
+
 /* ========================================================================= */
 
 void TypeInfoDeclaration::toDt(dt_t **pdt)
@@ -279,9 +327,10 @@
     LOG_SCOPE;
 
     ClassDeclaration* base = Type::typeinfotypedef;
-    base->toObjFile();
+    DtoForceConstInitDsymbol(base);
 
     const llvm::StructType* stype = isaStruct(base->type->llvmType->get());
+    Logger::cout() << "got stype: " << *stype << '\n';
 
     std::vector<llvm::Constant*> sinits;
     sinits.push_back(base->llvmVtbl);
@@ -295,10 +344,13 @@
     //sinits.push_back(llvm::ConstantPointerNull::get(basept));
     Logger::println("generating base typeinfo");
     //sd->basetype = sd->basetype->merge();
+
     sd->basetype->getTypeInfo(NULL);        // generate vtinfo
     assert(sd->basetype->vtinfo);
     if (!sd->basetype->vtinfo->llvmValue)
-        sd->basetype->vtinfo->toObjFile();
+        DtoForceConstInitDsymbol(sd->basetype->vtinfo);
+
+    assert(sd->basetype->vtinfo->llvmValue);
     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, stype->getElementType(1));
@@ -341,7 +393,7 @@
     LOG_SCOPE;
 
     ClassDeclaration* base = Type::typeinfoenum;
-    base->toObjFile();
+    DtoForceConstInitDsymbol(base);
 
     const llvm::StructType* stype = isaStruct(base->type->llvmType->get());
 
@@ -357,10 +409,12 @@
     //sinits.push_back(llvm::ConstantPointerNull::get(basept));
     Logger::println("generating base typeinfo");
     //sd->basetype = sd->basetype->merge();
+
     sd->memtype->getTypeInfo(NULL);        // generate vtinfo
     assert(sd->memtype->vtinfo);
     if (!sd->memtype->vtinfo->llvmValue)
-        sd->memtype->vtinfo->toObjFile();
+        DtoForceConstInitDsymbol(sd->memtype->vtinfo);
+
     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, stype->getElementType(1));
@@ -401,7 +455,7 @@
 static llvm::Constant* LLVM_D_Create_TypeInfoBase(Type* basetype, TypeInfoDeclaration* tid, ClassDeclaration* cd)
 {
     ClassDeclaration* base = cd;
-    base->toObjFile();
+    DtoForceConstInitDsymbol(base);
 
     const llvm::StructType* stype = isaStruct(base->type->llvmType->get());
 
@@ -413,7 +467,7 @@
     basetype->getTypeInfo(NULL);
     assert(basetype->vtinfo);
     if (!basetype->vtinfo->llvmValue)
-        basetype->vtinfo->toObjFile();
+        DtoForceConstInitDsymbol(basetype->vtinfo);
     assert(llvm::isa<llvm::Constant>(basetype->vtinfo->llvmValue));
     llvm::Constant* castbase = llvm::cast<llvm::Constant>(basetype->vtinfo->llvmValue);
     castbase = llvm::ConstantExpr::getBitCast(castbase, stype->getElementType(1));
@@ -533,11 +587,10 @@
     assert(tinfo->ty == Tstruct);
     TypeStruct *tc = (TypeStruct *)tinfo;
     StructDeclaration *sd = tc->sym;
-    sd->toObjFile();
-    DtoConstInitStruct(sd);
+    DtoForceConstInitDsymbol(sd);
 
     ClassDeclaration* base = Type::typeinfostruct;
-    base->toObjFile();
+    DtoForceConstInitDsymbol(base);
 
     const llvm::StructType* stype = isaStruct(((TypeClass*)base->type)->llvmType->get());
 
--- a/llvmdc.kdevelop	Fri Nov 16 10:01:24 2007 +0100
+++ b/llvmdc.kdevelop	Sun Nov 18 06:52:57 2007 +0100
@@ -98,7 +98,7 @@
       <hidenonlocation>false</hidenonlocation>
     </groups>
     <tree>
-      <hidepatterns>*.o,*.lo,CVS</hidepatterns>
+      <hidepatterns>*.bc</hidepatterns>
       <hidenonprojectfiles>false</hidenonprojectfiles>
     </tree>
   </kdevfileview>
@@ -394,6 +394,7 @@
       <path>obj/Debug/unialpha.d</path>
       <path>obj/Debug/utf.d</path>
       <path>obj/Debug/version.d</path>
+      <path>obj</path>
     </blacklist>
     <build>
       <buildtool>make</buildtool>
--- a/llvmdc.kdevelop.filelist	Fri Nov 16 10:01:24 2007 +0100
+++ b/llvmdc.kdevelop.filelist	Sun Nov 18 06:52:57 2007 +0100
@@ -129,6 +129,7 @@
 gen/tollvm.cpp
 gen/tollvm.h
 gen/toobj.cpp
+gen/typeinf.h
 gen/typinf.cpp
 lphobos
 lphobos/crc32.d
@@ -299,7 +300,7 @@
 test/bug63.d
 test/bug64.d
 test/bug66.d
-test/bug67.d
+test/bug69.d
 test/bug7.d
 test/bug8.d
 test/bug9.d
--- a/lphobos/build.sh	Fri Nov 16 10:01:24 2007 +0100
+++ b/lphobos/build.sh	Sun Nov 18 06:52:57 2007 +0100
@@ -20,7 +20,7 @@
 
 
 echo "compiling typeinfo 1"
-rebuild typeinfos1.d -c -oqobj -dc=llvmdc-posix || exit 1
+rebuild typeinfos1.d -c -oqobj -dc=llvmdc-posix -v || exit 1
 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo1.*.bc` ../lib/llvmdcore.bc || exit 1
 
 echo "compiling typeinfo 2"
@@ -52,7 +52,7 @@
 llvm-link -f -o=../lib/llvmdcore.bc obj/gclinux.bc obj/gcstub.bc ../lib/llvmdcore.bc || exit 1
 
 echo "compiling phobos"
-rebuild phobos.d -c -oqobj -dc=llvmdc-posix || exit 1
+rebuild phobos.d -c -oqobj -dc=llvmdc-posix -v || exit 1
 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/std.*.bc` ../lib/llvmdcore.bc || exit 1
 
 echo "optimizing"
--- a/test/bug51.d	Fri Nov 16 10:01:24 2007 +0100
+++ b/test/bug51.d	Sun Nov 18 06:52:57 2007 +0100
@@ -1,5 +1,7 @@
 module bug51;
 const ubyte[3] arr1 = 0;
 const ubyte[3] arr2 = [0];
-const ubyte[3] arr3 = [0:1];
-void main() {}
+const ubyte[3] arr3 = [1:1];
+void main()
+{
+}
--- a/test/classinfo1.d	Fri Nov 16 10:01:24 2007 +0100
+++ b/test/classinfo1.d	Sun Nov 18 06:52:57 2007 +0100
@@ -1,10 +1,28 @@
 module classinfo1;
 
-class C
+class NoPtrs
 {
 }
 
+class HasPtrs
+{
+    void* p;
+}
+
 void main()
 {
-    ClassInfo ci = C.classinfo;
+    {
+    ClassInfo ci = NoPtrs.classinfo;
+    char[] name = ci.name;
+    printf("%.*s\n", name.length, name.ptr);
+    assert(ci.name == "classinfo1.NoPtrs");
+    assert(ci.flags == 2);
+    }
+    {
+    ClassInfo ci = HasPtrs.classinfo;
+    char[] name = ci.name;
+    printf("%.*s\n", name.length, name.ptr);
+    assert(ci.name == "classinfo1.HasPtrs");
+    assert(ci.flags == 0);
+    }
 }
--- a/test/funcptr.d	Fri Nov 16 10:01:24 2007 +0100
+++ b/test/funcptr.d	Sun Nov 18 06:52:57 2007 +0100
@@ -42,14 +42,14 @@
 
     binfn_t binfn = &add_int;
     assert(binfn(4,1045) == 1049);
-    
+
     assert(binop_int(binfn, 10,656) == 666);
-    
+
     binfn = get_binop_int('+');
     assert(binop_int(binfn, 10,100) == 110);
     binfn = get_binop_int('-');
     assert(binop_int(binfn, 10,100) == -90);
-    
+
     {
     auto ffn = &mul_float;
     float ftmp = mul_float(2.5,5);