changeset 121:9c79b61fb638 trunk

[svn r125] Renamed/moved a few backend member inside DMD structures for consistency. Unit tests are now implemented.
author lindquist
date Tue, 27 Nov 2007 03:09:36 +0100
parents 5ce8ab11e75a
children 36ab367572df
files dmd/aggregate.h dmd/declaration.h dmd/func.c dmd/mtype.c dmd/mtype.h dmd/struct.c gen/classes.cpp gen/functions.cpp gen/statements.cpp gen/structs.cpp gen/toir.cpp gen/tollvm.cpp gen/toobj.cpp gen/typinf.cpp llvmdc.kdevelop test/bug77.d test/unittest1.d
diffstat 17 files changed, 144 insertions(+), 111 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/aggregate.h	Mon Nov 26 07:26:21 2007 +0100
+++ b/dmd/aggregate.h	Tue Nov 27 03:09:36 2007 +0100
@@ -104,9 +104,10 @@
     bool llvmInProgress;
     llvm::GlobalVariable* llvmVtbl;
     llvm::ConstantStruct* llvmConstVtbl;
-    llvm::Constant* llvmInitZ;
+    llvm::GlobalVariable* llvmInit;
+    llvm::Constant* llvmConstInit;
     llvm::GlobalVariable* llvmClass;
-    llvm::Constant* llvmClassZ;
+    llvm::Constant* llvmConstClass;
     bool llvmHasUnions;
     DUnion* llvmUnion;
     IRStruct* llvmIRStruct;
--- a/dmd/declaration.h	Mon Nov 26 07:26:21 2007 +0100
+++ b/dmd/declaration.h	Tue Nov 27 03:09:36 2007 +0100
@@ -615,6 +615,7 @@
     llvm::Constant* llvmDwarfSubProgram;
     bool llvmRunTimeHack;
     IRFunction* llvmIRFunc;
+    llvm::Value* llvmRetArg;
 };
 
 struct FuncAliasDeclaration : FuncDeclaration
--- a/dmd/func.c	Mon Nov 26 07:26:21 2007 +0100
+++ b/dmd/func.c	Tue Nov 27 03:09:36 2007 +0100
@@ -81,6 +81,7 @@
     llvmDwarfSubProgram = NULL;
     llvmRunTimeHack = false;
     llvmIRFunc = NULL;
+    llvmRetArg = NULL;
 }
 
 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
--- a/dmd/mtype.c	Mon Nov 26 07:26:21 2007 +0100
+++ b/dmd/mtype.c	Tue Nov 27 03:09:36 2007 +0100
@@ -2560,8 +2560,6 @@
     this->inuse = 0;
     this->llvmRetInPtr = false;
     this->llvmUsesThis = false;
-    this->llvmRetArg = 0;
-    this->llvmAllocaPoint = 0;
 }
 
 Type *TypeFunction::syntaxCopy()
@@ -4094,7 +4092,6 @@
 	: Type(Tstruct, NULL)
 {
     this->sym = sym;
-    llvmInit = 0;
 }
 
 char *TypeStruct::toChars()
@@ -4383,7 +4380,6 @@
 	: Type(Tclass, NULL)
 {
     this->sym = sym;
-    llvmInit = 0;
     llvmVtblType = 0;
 }
 
--- a/dmd/mtype.h	Mon Nov 26 07:26:21 2007 +0100
+++ b/dmd/mtype.h	Tue Nov 27 03:09:36 2007 +0100
@@ -437,8 +437,6 @@
 
     bool llvmRetInPtr;
     bool llvmUsesThis;
-    llvm::Value* llvmRetArg;
-    llvm::Instruction* llvmAllocaPoint;
 };
 
 struct TypeDelegate : Type
@@ -542,8 +540,6 @@
     int hasPointers();
 
     type *toCtype();
-
-    llvm::GlobalVariable* llvmInit;
 };
 
 struct TypeEnum : Type
@@ -641,7 +637,6 @@
 
     Symbol *toSymbol();
 
-    llvm::GlobalVariable* llvmInit;
     llvm::PATypeHolder* llvmVtblType;
 };
 
--- a/dmd/struct.c	Mon Nov 26 07:26:21 2007 +0100
+++ b/dmd/struct.c	Tue Nov 27 03:09:36 2007 +0100
@@ -47,9 +47,10 @@
 
     llvmVtbl = NULL;
     llvmConstVtbl = NULL;
-    llvmInitZ = NULL;
+    llvmInit = NULL;
+    llvmConstInit = NULL;
     llvmClass = NULL;
-    llvmClassZ = NULL;
+    llvmConstClass = NULL;
     llvmInProgress = false;
     llvmHasUnions = false;
     llvmUnion = NULL;
--- a/gen/classes.cpp	Mon Nov 26 07:26:21 2007 +0100
+++ b/gen/classes.cpp	Tue Nov 27 03:09:36 2007 +0100
@@ -305,7 +305,7 @@
         initname.append("6__initZ");
 
         llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module);
-        ts->llvmInit = initvar;
+        cd->llvmInit = initvar;
     }
 
     gIR->classes.pop_back();
@@ -394,7 +394,7 @@
 
     llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits);
     assert(_init);
-    cd->llvmInitZ = _init;
+    cd->llvmConstInit = _init;
 
     // generate vtable initializer
     std::vector<llvm::Constant*> sinits;
@@ -524,7 +524,7 @@
     if (cd->parent->isModule() && cd->getModule() == gIR->dmodule) {
         // interfaces don't have initializers
         if (!cd->isInterfaceDeclaration()) {
-            ts->llvmInit->setInitializer(cd->llvmInitZ);
+            cd->llvmInit->setInitializer(cd->llvmConstInit);
             cd->llvmVtbl->setInitializer(cd->llvmConstVtbl);
 
             // initialize interface vtables
@@ -579,15 +579,15 @@
 
     // copy the static initializer
     if (n > 0) {
-        assert(tc->llvmInit);
-        assert(dst->getType() == tc->llvmInit->getType());
+        assert(tc->sym->llvmInit);
+        assert(dst->getType() == tc->sym->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());
+        llvm::Value* srcarr = new llvm::BitCastInst(tc->sym->llvmInit,arrty,"tmp",gIR->scopebb());
         srcarr = DtoGEPi(srcarr,size_t_size,"tmp",gIR->scopebb());
 
         llvm::Function* fn = LLVM_DeclareMemCpy32();
@@ -912,10 +912,10 @@
 
     TypeClass* cdty = (TypeClass*)cd->type;
     if (!cd->isInterfaceDeclaration()) {
-        assert(cd->llvmInitZ);
+        assert(cd->llvmInit);
+        assert(cd->llvmConstInit);
         assert(cd->llvmVtbl);
         assert(cd->llvmConstVtbl);
-        assert(cdty->llvmInit);
     }
 
     // holds the list of initializers for llvm
@@ -923,28 +923,28 @@
 
     ClassDeclaration* cinfo = ClassDeclaration::classinfo;
     DtoForceConstInitDsymbol(cinfo);
-    assert(cinfo->llvmInitZ);
+    assert(cinfo->llvmConstInit);
 
     llvm::Constant* c;
 
     // own vtable
-    c = cinfo->llvmInitZ->getOperand(0);
+    c = cinfo->llvmConstInit->getOperand(0);
     assert(c);
     inits.push_back(c);
 
     // monitor
-    c = cinfo->llvmInitZ->getOperand(1);
+    c = cinfo->llvmConstInit->getOperand(1);
     inits.push_back(c);
 
     // byte[] init
     const llvm::Type* byteptrty = llvm::PointerType::get(llvm::Type::Int8Ty);
     if (cd->isInterfaceDeclaration()) {
-        c = cinfo->llvmInitZ->getOperand(2);
+        c = cinfo->llvmConstInit->getOperand(2);
     }
     else {
-        c = llvm::ConstantExpr::getBitCast(cdty->llvmInit, byteptrty);
-        assert(!cd->llvmInitZ->getType()->isAbstract());
-        size_t initsz = gTargetData->getTypeSize(cd->llvmInitZ->getType());
+        c = llvm::ConstantExpr::getBitCast(cd->llvmInit, byteptrty);
+        assert(!cd->llvmConstInit->getType()->isAbstract());
+        size_t initsz = gTargetData->getTypeSize(cd->llvmConstInit->getType());
         c = DtoConstSlice(DtoConstSize_t(initsz), c);
     }
     inits.push_back(c);
@@ -963,7 +963,7 @@
 
     // vtbl array
     if (cd->isInterfaceDeclaration()) {
-        c = cinfo->llvmInitZ->getOperand(4);
+        c = cinfo->llvmConstInit->getOperand(4);
     }
     else {
         const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty);
@@ -978,10 +978,10 @@
     // interfaces array
     IRStruct* irstruct = cd->llvmIRStruct;
     if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos) {
-        c = cinfo->llvmInitZ->getOperand(5);
+        c = cinfo->llvmConstInit->getOperand(5);
     }
     else {
-        const llvm::Type* t = cinfo->llvmInitZ->getOperand(5)->getType()->getContainedType(1);
+        const llvm::Type* t = cinfo->llvmConstInit->getOperand(5)->getType()->getContainedType(1);
         c = llvm::ConstantExpr::getBitCast(irstruct->interfaceInfos, t);
         size_t iisz = irstruct->interfaceInfosTy->getNumElements();
         c = DtoConstSlice(DtoConstSize_t(iisz), c);
@@ -997,13 +997,13 @@
     }
     else {
         // null
-        c = cinfo->llvmInitZ->getOperand(6);
+        c = cinfo->llvmConstInit->getOperand(6);
         inits.push_back(c);
     }
 
     // destructor
     if (cd->isInterfaceDeclaration()) {
-        c = cinfo->llvmInitZ->getOperand(7);
+        c = cinfo->llvmConstInit->getOperand(7);
     }
     else {
         c = build_class_dtor(cd);
@@ -1012,12 +1012,12 @@
 
     // invariant
     // TODO
-    c = cinfo->llvmInitZ->getOperand(8);
+    c = cinfo->llvmConstInit->getOperand(8);
     inits.push_back(c);
 
     // uint flags
     if (cd->isInterfaceDeclaration()) {
-        c = cinfo->llvmInitZ->getOperand(9);
+        c = cinfo->llvmConstInit->getOperand(9);
     }
     else {
         uint flags = build_classinfo_flags(cd);
@@ -1027,15 +1027,15 @@
 
     // allocator
     // TODO
-    c = cinfo->llvmInitZ->getOperand(10);
+    c = cinfo->llvmConstInit->getOperand(10);
     inits.push_back(c);
 
     // offset typeinfo
     if (cd->isInterfaceDeclaration()) {
-        c = cinfo->llvmInitZ->getOperand(11);
+        c = cinfo->llvmConstInit->getOperand(11);
     }
     else {
-        c = build_offti_array(cd, cinfo->llvmInitZ->getOperand(11));
+        c = build_offti_array(cd, cinfo->llvmConstInit->getOperand(11));
     }
     inits.push_back(c);
 
@@ -1043,11 +1043,11 @@
     if (cd->defaultCtor && !cd->isInterfaceDeclaration()) {
         DtoForceDeclareDsymbol(cd->defaultCtor);
         c = isaConstant(cd->defaultCtor->llvmValue);
-        const llvm::Type* toTy = cinfo->llvmInitZ->getOperand(12)->getType();
+        const llvm::Type* toTy = cinfo->llvmConstInit->getOperand(12)->getType();
         c = llvm::ConstantExpr::getBitCast(c, toTy);
     }
     else {
-        c = cinfo->llvmInitZ->getOperand(12);
+        c = cinfo->llvmConstInit->getOperand(12);
     }
     inits.push_back(c);
 
@@ -1058,10 +1058,10 @@
     }*/
 
     // build the initializer
-    const llvm::StructType* st = isaStruct(cinfo->llvmInitZ->getType());
+    const llvm::StructType* st = isaStruct(cinfo->llvmConstInit->getType());
     llvm::Constant* finalinit = llvm::ConstantStruct::get(st, inits);
     //Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
 
-    cd->llvmClassZ = finalinit;
+    cd->llvmConstClass = finalinit;
     cd->llvmClass->setInitializer(finalinit);
 }
--- a/gen/functions.cpp	Mon Nov 26 07:26:21 2007 +0100
+++ b/gen/functions.cpp	Tue Nov 27 03:09:36 2007 +0100
@@ -73,10 +73,10 @@
         ClassDeclaration* ti = Type::typeinfo;
         ti->toObjFile();
         DtoForceConstInitDsymbol(ti);
-        assert(ti->llvmInitZ);
+        assert(ti->llvmConstInit);
         std::vector<const llvm::Type*> types;
         types.push_back(DtoSize_t());
-        types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmInitZ->getType())));
+        types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmConstInit->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));
@@ -182,6 +182,12 @@
         return DtoVaFunctionType(fdecl);
     }
 
+    // unittest has null type, just build it manually
+    /*if (fdecl->isUnitTestDeclaration()) {
+        std::vector<const llvm::Type*> args;
+        return llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
+    }*/
+
     // type has already been resolved
     if (fdecl->type->llvmType != 0) {
         return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType->get());
@@ -238,6 +244,10 @@
 
 void DtoResolveFunction(FuncDeclaration* fdecl)
 {
+    if (!global.params.useUnitTests && fdecl->isUnitTestDeclaration()) {
+        return; // ignore declaration completely
+    }
+
     if (fdecl->llvmResolved) return;
     fdecl->llvmResolved = true;
 
@@ -249,11 +259,6 @@
         return;
     }
 
-    if (fdecl->isUnitTestDeclaration()) {
-        Logger::attention("ignoring unittest declaration: %s", fdecl->toChars());
-        return;
-    }
-
     if (fdecl->parent)
     if (TemplateInstance* tinst = fdecl->parent->isTemplateInstance())
     {
@@ -293,6 +298,12 @@
 
     assert(!fdecl->isAbstract());
 
+    // intrinsic sanity check
+    if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) {
+        error(fdecl->loc, "intrinsics cannot have function bodies");
+        fatal();
+    }
+
     if (fdecl->llvmRunTimeHack) {
         Logger::println("runtime hack func chars: %s", fdecl->toChars());
         if (!fdecl->llvmValue)
@@ -318,26 +329,6 @@
     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);
@@ -387,7 +378,7 @@
     int k = 0;
     if (f->llvmRetInPtr) {
         iarg->setName("retval");
-        f->llvmRetArg = iarg;
+        fdecl->llvmRetArg = iarg;
         ++iarg;
     }
     if (f->llvmUsesThis) {
@@ -422,6 +413,9 @@
         }
     }
 
+    if (fdecl->isUnitTestDeclaration())
+        gIR->unitTests.push_back(fdecl);
+
     if (!declareOnly)
         gIR->defineList.push_back(fdecl);
 
@@ -430,7 +424,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-// TODO split this monster up
 void DtoDefineFunc(FuncDeclaration* fd)
 {
     if (fd->llvmDefined) return;
@@ -452,8 +445,8 @@
 
     Type* t = DtoDType(fd->type);
     TypeFunction* f = (TypeFunction*)t;
+    assert(f->llvmType);
 
-    assert(f->llvmType);
     llvm::Function* func = fd->llvmIRFunc->func;
     const llvm::FunctionType* functype = func->getFunctionType();
 
@@ -479,13 +472,13 @@
             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;
+                llvm::Instruction* allocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb());
+                gIR->func()->allocapoint = allocaPoint;
 
                 // need result variable? (not nested)
                 if (fd->vresult && !fd->vresult->nestedref) {
                     Logger::println("non-nested vresult value");
-                    fd->vresult->llvmValue = new llvm::AllocaInst(DtoType(fd->vresult->type),"function_vresult",f->llvmAllocaPoint);
+                    fd->vresult->llvmValue = new llvm::AllocaInst(DtoType(fd->vresult->type),"function_vresult",allocaPoint);
                 }
 
                 // give arguments storage
@@ -501,7 +494,7 @@
                         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);
+                        llvm::Value* v = new llvm::AllocaInst(a->getType(),s,allocaPoint);
                         gIR->ir->CreateStore(a,v);
                         vd->llvmValue = v;
                     }
@@ -546,7 +539,7 @@
                     }
                     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);
+                    fd->llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",allocaPoint);
                     if (parentNested) {
                         assert(fd->llvmThisVar);
                         llvm::Value* ptr = gIR->ir->CreateBitCast(fd->llvmThisVar, parentNested->getType(), "tmp");
@@ -588,8 +581,8 @@
                 }
 
                 // erase alloca point
-                f->llvmAllocaPoint->eraseFromParent();
-                f->llvmAllocaPoint = 0;
+                allocaPoint->eraseFromParent();
+                allocaPoint = 0;
                 gIR->func()->allocapoint = 0;
 
             gIR->scopes.pop_back();
@@ -649,6 +642,12 @@
     llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_moduleCtor");
     llvm::Instruction* apt = new llvm::CallInst(fn,"",bb);
 
+    // run unit tests if -unittest is provided
+    if (global.params.useUnitTests) {
+        fn = LLVM_D_GetRuntimeFunction(ir.module,"_moduleUnitTests");
+        llvm::Instruction* apt = new llvm::CallInst(fn,"",bb);
+    }
+
     // call user main function
     const llvm::FunctionType* mainty = ir.mainFunc->getFunctionType();
     llvm::CallInst* call;
--- a/gen/statements.cpp	Mon Nov 26 07:26:21 2007 +0100
+++ b/gen/statements.cpp	Tue Nov 27 03:09:36 2007 +0100
@@ -57,12 +57,13 @@
         if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
             assert(DtoIsPassedByRef(exptype));
 
-            TypeFunction* f = p->topfunctype();
-            assert(f->llvmRetInPtr && f->llvmRetArg);
+            IRFunction* f = p->func();
+            assert(f->type->llvmRetInPtr);
+            assert(f->decl->llvmRetArg);
 
             if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
 
-            DValue* rvar = new DVarValue(f->next, f->llvmRetArg, true);
+            DValue* rvar = new DVarValue(f->type->next, f->decl->llvmRetArg, true);
 
             p->exps.push_back(IRExp(NULL,exp,rvar));
             DValue* e = exp->toElem(p);
@@ -71,9 +72,9 @@
             if (!e->inPlace())
                 DtoAssign(rvar, e);
 
-            IRFunction::FinallyVec& fin = p->func()->finallys;
+            IRFunction::FinallyVec& fin = f->finallys;
             if (fin.empty()) {
-                if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
+                if (global.params.symdebug) DtoDwarfFuncEnd(f->decl);
                 new llvm::ReturnInst(p->scopebb());
             }
             else {
--- a/gen/structs.cpp	Mon Nov 26 07:26:21 2007 +0100
+++ b/gen/structs.cpp	Tue Nov 27 03:09:36 2007 +0100
@@ -304,7 +304,7 @@
 
     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;
+    sd->llvmInit = initvar;
 
     gIR->constInitList.push_back(sd);
     if (sd->getModule() == gIR->dmodule)
@@ -369,11 +369,11 @@
         }
         Logger::cout() << "Initializer printed" << '\n';
         #endif
-        sd->llvmInitZ = llvm::ConstantStruct::get(structtype,fieldinits_ll);
+        sd->llvmConstInit = llvm::ConstantStruct::get(structtype,fieldinits_ll);
     }
     else {
         Logger::println("Zero initialized");
-        sd->llvmInitZ = llvm::ConstantAggregateZero::get(structtype);
+        sd->llvmConstInit = llvm::ConstantAggregateZero::get(structtype);
     }
 
     gIR->structs.pop_back();
@@ -395,7 +395,7 @@
 
     assert(sd->type->ty == Tstruct);
     TypeStruct* ts = (TypeStruct*)sd->type;
-    ts->llvmInit->setInitializer(sd->llvmInitZ);
+    sd->llvmInit->setInitializer(sd->llvmConstInit);
 
     sd->llvmDModule = gIR->dmodule;
 }
--- a/gen/toir.cpp	Mon Nov 26 07:26:21 2007 +0100
+++ b/gen/toir.cpp	Tue Nov 27 03:09:36 2007 +0100
@@ -215,8 +215,9 @@
         Logger::print("Sym: type=%s\n", sdecltype->toChars());
         assert(sdecltype->ty == Tstruct);
         TypeStruct* ts = (TypeStruct*)sdecltype;
-        assert(ts->llvmInit);
-        return new DVarValue(type, ts->llvmInit, true);
+        assert(ts->sym);
+        assert(ts->sym->llvmInit);
+        return new DVarValue(type, ts->sym->llvmInit, true);
     }
     else
     {
@@ -240,8 +241,8 @@
         assert(sdecltype->ty == Tstruct);
         TypeStruct* ts = (TypeStruct*)sdecltype;
         DtoForceConstInitDsymbol(ts->sym);
-        assert(ts->sym->llvmInitZ);
-        return ts->sym->llvmInitZ;
+        assert(ts->sym->llvmConstInit);
+        return ts->sym->llvmConstInit;
     }
     assert(0 && "Only supported const VarExp is of a SymbolDeclaration");
     return NULL;
@@ -1004,8 +1005,8 @@
                 p->ir->CreateStore(vvalues[i], DtoGEPi(mem,0,i,"tmp"));
 
             //llvm::Constant* typeinfoparam = llvm::ConstantPointerNull::get(isaPointer(llfnty->getParamType(j)));
-            assert(Type::typeinfo->llvmInitZ);
-            const llvm::Type* typeinfotype = llvm::PointerType::get(Type::typeinfo->llvmInitZ->getType());
+            assert(Type::typeinfo->llvmConstInit);
+            const llvm::Type* typeinfotype = llvm::PointerType::get(Type::typeinfo->llvmConstInit->getType());
             Logger::cout() << "typeinfo ptr type: " << *typeinfotype << '\n';
             const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements());
             llvm::Value* typeinfomem = new llvm::AllocaInst(typeinfoarraytype,"_arguments_storage",p->topallocapoint());
@@ -1830,7 +1831,8 @@
             DtoStructZeroInit(emem);
         }
         else {
-            DtoStructCopy(emem,ts->llvmInit);
+            assert(ts->sym);
+            DtoStructCopy(emem,ts->sym->llvmInit);
         }
     }
 
--- a/gen/tollvm.cpp	Mon Nov 26 07:26:21 2007 +0100
+++ b/gen/tollvm.cpp	Tue Nov 27 03:09:36 2007 +0100
@@ -522,8 +522,8 @@
             TypeStruct* ts = (TypeStruct*)t;
             assert(ts);
             assert(ts->sym);
-            assert(ts->sym->llvmInitZ);
-            _init = ts->sym->llvmInitZ;
+            assert(ts->sym->llvmConstInit);
+            _init = ts->sym->llvmConstInit;
         }
         else if (t->ty == Tclass)
         {
@@ -1529,8 +1529,8 @@
             llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init);
             assert(t->ty == Tstruct);
             TypeStruct* ts = (TypeStruct*)t;
-            assert(ts->sym->llvmInitZ);
-            _init = ts->sym->llvmInitZ;
+            assert(ts->sym->llvmConstInit);
+            _init = ts->sym->llvmConstInit;
         }
         // array single value init
         else if (isaArray(_type))
--- a/gen/toobj.cpp	Mon Nov 26 07:26:21 2007 +0100
+++ b/gen/toobj.cpp	Tue Nov 27 03:09:36 2007 +0100
@@ -223,6 +223,39 @@
     return fn;
 }
 
+// build module unittest
+
+static llvm::Function* build_module_unittest()
+{
+    if (gIR->unitTests.empty())
+        return NULL;
+
+    size_t n = gIR->unitTests.size();
+    if (n == 1)
+        return llvm::cast<llvm::Function>(gIR->unitTests[0]->llvmValue);
+
+    std::string name("_D");
+    name.append(gIR->dmodule->mangle());
+    name.append("10__unittestZ");
+
+    std::vector<const llvm::Type*> argsTy;
+    const llvm::FunctionType* fnTy = llvm::FunctionType::get(llvm::Type::VoidTy,argsTy,false);
+    llvm::Function* fn = new llvm::Function(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module);
+    fn->setCallingConv(llvm::CallingConv::Fast);
+
+    llvm::BasicBlock* bb = new llvm::BasicBlock("entry", fn);
+    LLVMBuilder builder(bb);
+
+    for (size_t i=0; i<n; i++) {
+        llvm::Function* f = llvm::cast<llvm::Function>(gIR->unitTests[i]->llvmValue);
+        llvm::CallInst* call = builder.CreateCall(f,"");
+        call->setCallingConv(llvm::CallingConv::Fast);
+    }
+
+    builder.CreateRetVoid();
+    return fn;
+}
+
 // Put out instance of ModuleInfo for this Module
 
 void Module::genmoduleinfo()
@@ -296,7 +329,7 @@
         c = DtoConstSlice(DtoConstSize_t(importInits.size()), c);
     }
     else
-        c = moduleinfo->llvmInitZ->getOperand(3);
+        c = moduleinfo->llvmConstInit->getOperand(3);
     initVec.push_back(c);
 
     // localClasses[]
@@ -330,7 +363,7 @@
         c = DtoConstSlice(DtoConstSize_t(classInits.size()), c);
     }
     else
-        c = moduleinfo->llvmInitZ->getOperand(4);
+        c = moduleinfo->llvmConstInit->getOperand(4);
     initVec.push_back(c);
 
     // flags
@@ -342,16 +375,17 @@
 
     // ctor
     llvm::Function* fctor = build_module_ctor();
-    c = fctor ? fctor : moduleinfo->llvmInitZ->getOperand(6);
+    c = fctor ? fctor : moduleinfo->llvmConstInit->getOperand(6);
     initVec.push_back(c);
 
     // dtor
     llvm::Function* fdtor = build_module_dtor();
-    c = fdtor ? fdtor : moduleinfo->llvmInitZ->getOperand(7);
+    c = fdtor ? fdtor : moduleinfo->llvmConstInit->getOperand(7);
     initVec.push_back(c);
 
     // unitTest
-    c = moduleinfo->llvmInitZ->getOperand(8);
+    llvm::Function* unittest = build_module_unittest();
+    c = unittest ? unittest : moduleinfo->llvmConstInit->getOperand(8);
     initVec.push_back(c);
 
     // create initializer
--- a/gen/typinf.cpp	Mon Nov 26 07:26:21 2007 +0100
+++ b/gen/typinf.cpp	Tue Nov 27 03:09:36 2007 +0100
@@ -852,9 +852,8 @@
     }
     else
     {
-        assert(sd->llvmInitZ);
         size_t cisize = gTargetData->getTypeSize(tc->llvmType->get());
-        llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(tc->llvmInit, initpt);
+        llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(sd->llvmInit, initpt);
         sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
     }
 
--- a/llvmdc.kdevelop	Mon Nov 26 07:26:21 2007 +0100
+++ b/llvmdc.kdevelop	Tue Nov 27 03:09:36 2007 +0100
@@ -98,7 +98,7 @@
       <hidenonlocation>false</hidenonlocation>
     </groups>
     <tree>
-      <hidepatterns>*.bc,*.ll</hidepatterns>
+      <hidepatterns>*.bc</hidepatterns>
       <hidenonprojectfiles>false</hidenonprojectfiles>
     </tree>
   </kdevfileview>
--- a/test/bug77.d	Mon Nov 26 07:26:21 2007 +0100
+++ b/test/bug77.d	Tue Nov 27 03:09:36 2007 +0100
@@ -12,6 +12,8 @@
         len = strlen(prefix);
         assert(len == 0);
         }
+
+        func();
     }
     func2();
 }
--- a/test/unittest1.d	Mon Nov 26 07:26:21 2007 +0100
+++ b/test/unittest1.d	Tue Nov 27 03:09:36 2007 +0100
@@ -1,9 +1,10 @@
 module unittest1;
 
-unittest
-{
-}
-
 void main()
 {
 }
+
+unittest
+{
+    printf("hello\n");
+}