diff gen/tollvm.cpp @ 100:5071469303d4 trunk

[svn r104] TONS OF FIXES. Split up declaration, constant initializer gen and definition for globals, structs, classes and functions. Improved ClassInfo support (not complete), not in vtable yet. Fixed a bunch of forward reference problems. Much more. Major commit! :)
author lindquist
date Fri, 16 Nov 2007 08:21:47 +0100
parents a676a7743642
children 027b8d8b71ec
line wrap: on
line diff
--- a/gen/tollvm.cpp	Thu Nov 15 00:24:44 2007 +0100
+++ b/gen/tollvm.cpp	Fri Nov 16 08:21:47 2007 +0100
@@ -14,7 +14,9 @@
 #include "gen/runtime.h"
 #include "gen/arrays.h"
 #include "gen/dvalue.h"
+#include "gen/functions.h"
 #include "gen/structs.h"
+#include "gen/classes.h"
 
 bool DtoIsPassedByRef(Type* type)
 {
@@ -95,17 +97,16 @@
 
     // aggregates
     case Tstruct:    {
-        if (t->llvmType == 0)
-        {
+        if (!t->llvmType || *t->llvmType == NULL) {
             // recursive or cyclic declaration
             if (!gIR->structs.empty())
             {
                 IRStruct* found = 0;
                 for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i)
                 {
-                    if (t == i->type)
+                    if (t == (*i)->type)
                     {
-                        return i->recty.get();
+                        return (*i)->recty.get();
                     }
                 }
             }
@@ -115,21 +116,20 @@
             assert(ts->sym);
             ts->sym->toObjFile();
         }
-        return t->llvmType;
+        return t->llvmType->get();
     }
 
     case Tclass:    {
-        if (t->llvmType == 0)
-        {
+        if (!t->llvmType || *t->llvmType == NULL) {
             // recursive or cyclic declaration
             if (!gIR->structs.empty())
             {
                 IRStruct* found = 0;
                 for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i)
                 {
-                    if (t == i->type)
+                    if (t == (*i)->type)
                     {
-                        return llvm::PointerType::get(i->recty.get());
+                        return llvm::PointerType::get((*i)->recty.get());
                     }
                 }
             }
@@ -139,28 +139,28 @@
             assert(tc->sym);
             tc->sym->toObjFile();
         }
-        return llvm::PointerType::get(t->llvmType);
+        return llvm::PointerType::get(t->llvmType->get());
     }
 
     // functions
     case Tfunction:
     {
-        if (t->llvmType == 0) {
+        if (!t->llvmType || *t->llvmType == NULL) {
             return DtoFunctionType(t,NULL);
         }
         else {
-            return t->llvmType;
+            return t->llvmType->get();
         }
     }
 
     // delegates
     case Tdelegate:
     {
-        if (t->llvmType == 0) {
+        if (!t->llvmType || *t->llvmType == NULL) {
             return DtoDelegateType(t);
         }
         else {
-            return t->llvmType;
+            return t->llvmType->get();
         }
     }
 
@@ -183,181 +183,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype, bool ismain)
-{
-    TypeFunction* f = (TypeFunction*)type;
-    assert(f != 0);
-
-    bool typesafeVararg = false;
-    if (f->linkage == LINKd && f->varargs == 1) {
-        typesafeVararg = true;
-    }
-
-    // return value type
-    const llvm::Type* rettype;
-    const llvm::Type* actualRettype;
-    Type* rt = f->next;
-    bool retinptr = false;
-    bool usesthis = false;
-
-    if (ismain) {
-        rettype = llvm::Type::Int32Ty;
-        actualRettype = rettype;
-    }
-    else {
-        assert(rt);
-        if (DtoIsPassedByRef(rt)) {
-            rettype = llvm::PointerType::get(DtoType(rt));
-            actualRettype = llvm::Type::VoidTy;
-            f->llvmRetInPtr = retinptr = true;
-        }
-        else {
-            rettype = DtoType(rt);
-            actualRettype = rettype;
-        }
-    }
-
-    // parameter types
-    std::vector<const llvm::Type*> paramvec;
-
-    if (retinptr) {
-        Logger::cout() << "returning through pointer parameter: " << *rettype << '\n';
-        paramvec.push_back(rettype);
-    }
-
-    if (thistype) {
-        paramvec.push_back(thistype);
-        usesthis = true;
-    }
-
-    if (typesafeVararg) {
-        ClassDeclaration* ti = Type::typeinfo;
-        if (!ti->llvmInitZ)
-            ti->toObjFile();
-        assert(ti->llvmInitZ);
-        std::vector<const llvm::Type*> types;
-        types.push_back(DtoSize_t());
-        types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmInitZ->getType())));
-        const llvm::Type* t1 = llvm::StructType::get(types);
-        paramvec.push_back(llvm::PointerType::get(t1));
-        paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
-    }
-
-    size_t n = Argument::dim(f->parameters);
-
-    for (int i=0; i < n; ++i) {
-        Argument* arg = Argument::getNth(f->parameters, i);
-        // ensure scalar
-        Type* argT = DtoDType(arg->type);
-        assert(argT);
-
-        if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
-            //assert(arg->vardecl);
-            //arg->vardecl->refparam = true;
-        }
-        else
-            arg->llvmCopy = true;
-
-        const llvm::Type* at = DtoType(argT);
-        if (isaStruct(at)) {
-            Logger::println("struct param");
-            paramvec.push_back(llvm::PointerType::get(at));
-        }
-        else if (isaArray(at)) {
-            Logger::println("sarray param");
-            assert(argT->ty == Tsarray);
-            //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0)));
-            paramvec.push_back(llvm::PointerType::get(at));
-        }
-        else if (llvm::isa<llvm::OpaqueType>(at)) {
-            Logger::println("opaque param");
-            assert(argT->ty == Tstruct || argT->ty == Tclass);
-            paramvec.push_back(llvm::PointerType::get(at));
-        }
-        else {
-            if (!arg->llvmCopy) {
-                Logger::println("ref param");
-                at = llvm::PointerType::get(at);
-            }
-            else {
-                Logger::println("in param");
-            }
-            paramvec.push_back(at);
-        }
-    }
-
-    // construct function type
-    bool isvararg = !typesafeVararg && f->varargs;
-    llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
-
-    f->llvmRetInPtr = retinptr;
-    f->llvmUsesThis = usesthis;
-    return functype;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
-{
-    TypeFunction* f = (TypeFunction*)fdecl->type;
-    assert(f != 0);
-
-    const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
-    std::vector<const llvm::Type*> args;
-
-    if (fdecl->llvmInternal == LLVMva_start) {
-        args.push_back(i8pty);
-    }
-    else if (fdecl->llvmInternal == LLVMva_intrinsic) {
-        size_t n = Argument::dim(f->parameters);
-        for (size_t i=0; i<n; ++i) {
-            args.push_back(i8pty);
-        }
-    }
-    else
-    assert(0);
-
-    const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
-    f->llvmType = fty;
-    return fty;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
-{
-    if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
-        return DtoVaFunctionType(fdecl);
-    }
-
-    // type has already been resolved
-    if (fdecl->type->llvmType != 0) {
-        return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType);
-    }
-
-    const llvm::Type* thisty = NULL;
-    if (fdecl->needThis()) {
-        if (AggregateDeclaration* ad = fdecl->isMember()) {
-            Logger::print("isMember = this is: %s\n", ad->type->toChars());
-            thisty = DtoType(ad->type);
-            Logger::cout() << "this llvm type: " << *thisty << '\n';
-            if (isaStruct(thisty) || thisty == gIR->topstruct().recty.get())
-                thisty = llvm::PointerType::get(thisty);
-        }
-        else
-        assert(0);
-    }
-    else if (fdecl->isNested()) {
-        thisty = llvm::PointerType::get(llvm::Type::Int8Ty);
-    }
-
-    const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain());
-    fdecl->type->llvmType = functype;
-    return functype;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 const llvm::StructType* DtoDelegateType(Type* t)
 {
     const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty);
@@ -630,131 +455,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoMain()
-{
-    // emit main function llvm style
-    // int main(int argc, char**argv, char**env);
-
-    assert(gIR != 0);
-    IRState& ir = *gIR;
-
-    assert(ir.emitMain && ir.mainFunc);
-
-    // parameter types
-    std::vector<const llvm::Type*> pvec;
-    pvec.push_back((const llvm::Type*)llvm::Type::Int32Ty);
-    const llvm::Type* chPtrType = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty);
-    pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType));
-    pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType));
-    const llvm::Type* rettype = (const llvm::Type*)llvm::Type::Int32Ty;
-
-    llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false);
-    llvm::Function* func = new llvm::Function(functype,llvm::GlobalValue::ExternalLinkage,"main",ir.module);
-
-    llvm::BasicBlock* bb = new llvm::BasicBlock("entry",func);
-
-    // call static ctors
-    llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_ctors");
-    llvm::Instruction* apt = new llvm::CallInst(fn,"",bb);
-
-    // call user main function
-    const llvm::FunctionType* mainty = ir.mainFunc->getFunctionType();
-    llvm::CallInst* call;
-    if (mainty->getNumParams() > 0)
-    {
-        // main with arguments
-        assert(mainty->getNumParams() == 1);
-        std::vector<llvm::Value*> args;
-        llvm::Function* mfn = LLVM_D_GetRuntimeFunction(ir.module,"_d_main_args");
-
-        llvm::Function::arg_iterator argi = func->arg_begin();
-        args.push_back(argi++);
-        args.push_back(argi++);
-
-        const llvm::Type* at = mainty->getParamType(0)->getContainedType(0);
-        llvm::Value* arr = new llvm::AllocaInst(at->getContainedType(1)->getContainedType(0), func->arg_begin(), "argstorage", apt);
-        llvm::Value* a = new llvm::AllocaInst(at, "argarray", apt);
-        llvm::Value* ptr = DtoGEPi(a,0,0,"tmp",bb);
-        llvm::Value* v = args[0];
-        if (v->getType() != DtoSize_t())
-            v = new llvm::ZExtInst(v, DtoSize_t(), "tmp", bb);
-        new llvm::StoreInst(v,ptr,bb);
-        ptr = DtoGEPi(a,0,1,"tmp",bb);
-        new llvm::StoreInst(arr,ptr,bb);
-        args.push_back(a);
-        new llvm::CallInst(mfn, args.begin(), args.end(), "", bb);
-        call = new llvm::CallInst(ir.mainFunc,a,"ret",bb);
-    }
-    else
-    {
-        // main with no arguments
-        call = new llvm::CallInst(ir.mainFunc,"ret",bb);
-    }
-    call->setCallingConv(ir.mainFunc->getCallingConv());
-
-    // call static dtors
-    fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_dtors");
-    new llvm::CallInst(fn,"",bb);
-
-    // return
-    new llvm::ReturnInst(call,bb);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance)
-{
-    Array* arr = &tc->sym->dtors;
-    for (size_t i=0; i<arr->dim; i++)
-    {
-        FuncDeclaration* fd = (FuncDeclaration*)arr->data[i];
-        assert(fd->llvmValue);
-        new llvm::CallInst(fd->llvmValue, instance, "", gIR->scopebb());
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoInitClass(TypeClass* tc, llvm::Value* dst)
-{
-    assert(gIR);
-
-    assert(tc->llvmType);
-    uint64_t size_t_size = gTargetData->getTypeSize(DtoSize_t());
-    uint64_t n = gTargetData->getTypeSize(tc->llvmType) - size_t_size;
-
-    // set vtable field
-    llvm::Value* vtblvar = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
-    assert(tc->sym->llvmVtbl);
-    new llvm::StoreInst(tc->sym->llvmVtbl, vtblvar, gIR->scopebb());
-
-    // copy the static initializer
-    if (n > 0) {
-        assert(tc->llvmInit);
-        assert(dst->getType() == tc->llvmInit->getType());
-
-        llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
-
-        llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
-        dstarr = DtoGEPi(dstarr,size_t_size,"tmp",gIR->scopebb());
-
-        llvm::Value* srcarr = new llvm::BitCastInst(tc->llvmInit,arrty,"tmp",gIR->scopebb());
-        srcarr = DtoGEPi(srcarr,size_t_size,"tmp",gIR->scopebb());
-
-        llvm::Function* fn = LLVM_DeclareMemCpy32();
-        std::vector<llvm::Value*> llargs;
-        llargs.resize(4);
-        llargs[0] = dstarr;
-        llargs[1] = srcarr;
-        llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
-        llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-        new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 llvm::Constant* DtoConstInitializer(Type* type, Initializer* init)
 {
     llvm::Constant* _init = 0; // may return zero
@@ -792,6 +492,54 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+llvm::Constant* DtoConstFieldInitializer(Type* t, Initializer* init)
+{
+    Logger::println("DtoConstFieldInitializer");
+    LOG_SCOPE;
+
+    const llvm::Type* _type = DtoType(t);
+
+    llvm::Constant* _init = DtoConstInitializer(t, init);
+    assert(_init);
+    if (_type != _init->getType())
+    {
+        Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n';
+        if (t->ty == Tsarray)
+        {
+            const llvm::ArrayType* arrty = isaArray(_type);
+            uint64_t n = arrty->getNumElements();
+            std::vector<llvm::Constant*> vals(n,_init);
+            _init = llvm::ConstantArray::get(arrty, vals);
+        }
+        else if (t->ty == Tarray)
+        {
+            assert(isaStruct(_type));
+            _init = llvm::ConstantAggregateZero::get(_type);
+        }
+        else if (t->ty == Tstruct)
+        {
+            const llvm::StructType* structty = isaStruct(_type);
+            TypeStruct* ts = (TypeStruct*)t;
+            assert(ts);
+            assert(ts->sym);
+            assert(ts->sym->llvmInitZ);
+            _init = ts->sym->llvmInitZ;
+        }
+        else if (t->ty == Tclass)
+        {
+            _init = llvm::Constant::getNullValue(_type);
+        }
+        else {
+            Logger::println("failed for type %s", t->toChars());
+            assert(0);
+        }
+    }
+
+    return _init;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 DValue* DtoInitializer(Initializer* init)
 {
     if (ExpInitializer* ex = init->isExpInitializer())
@@ -858,152 +606,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl)
-{
-    TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
-    const llvm::FunctionType* fty = DtoVaFunctionType(fdecl);
-    llvm::Constant* fn = 0;
-
-    if (fdecl->llvmInternal == LLVMva_start) {
-        fn = gIR->module->getOrInsertFunction("llvm.va_start", fty);
-        assert(fn);
-    }
-    else if (fdecl->llvmInternal == LLVMva_intrinsic) {
-        fn = gIR->module->getOrInsertFunction(fdecl->llvmInternal1, fty);
-        assert(fn);
-    }
-    else
-    assert(0);
-
-    llvm::Function* func = llvm::dyn_cast<llvm::Function>(fn);
-    assert(func);
-    assert(func->isIntrinsic());
-    fdecl->llvmValue = func;
-    return func;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Function* DtoDeclareFunction(FuncDeclaration* fdecl)
-{
-    if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
-        return DtoDeclareVaFunction(fdecl);
-    }
-
-    // mangled name
-    char* mangled_name;
-    if (fdecl->llvmInternal == LLVMintrinsic)
-        mangled_name = fdecl->llvmInternal1;
-    else
-        mangled_name = fdecl->mangle();
-
-    // unit test special handling
-    if (fdecl->isUnitTestDeclaration())
-    {
-        assert(0 && "no unittests yet");
-        /*const llvm::FunctionType* fnty = llvm::FunctionType::get(llvm::Type::VoidTy, std::vector<const llvm::Type*>(), false);
-        // make the function
-        llvm::Function* func = gIR->module->getFunction(mangled_name);
-        if (func == 0)
-            func = new llvm::Function(fnty,llvm::GlobalValue::InternalLinkage,mangled_name,gIR->module);
-        func->setCallingConv(llvm::CallingConv::Fast);
-        fdecl->llvmValue = func;
-        return func;
-        */
-    }
-
-    // regular function
-    TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
-    assert(f != 0);
-
-    if (fdecl->llvmValue != 0) {
-        if (!llvm::isa<llvm::Function>(fdecl->llvmValue))
-        {
-            Logger::cout() << *fdecl->llvmValue << '\n';
-            assert(0);
-        }
-        return llvm::cast<llvm::Function>(fdecl->llvmValue);
-    }
-
-    Logger::print("FuncDeclaration::toObjFile(%s): %s\n", fdecl->needThis()?"this":"static",fdecl->toChars());
-    LOG_SCOPE;
-
-    if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) {
-        error("intrinsics cannot have function bodies");
-        fatal();
-    }
-
-    // construct function
-    const llvm::FunctionType* functype = (f->llvmType == 0) ? DtoFunctionType(fdecl) : llvm::cast<llvm::FunctionType>(f->llvmType);
-
-    // make the function
-    llvm::Function* func = gIR->module->getFunction(mangled_name);
-    if (func == 0) {
-        func = new llvm::Function(functype,DtoLinkage(fdecl->protection, fdecl->storage_class),mangled_name,gIR->module);
-    }
-
-    if (fdecl->llvmInternal != LLVMintrinsic)
-        func->setCallingConv(DtoCallingConv(f->linkage));
-
-    fdecl->llvmValue = func;
-    f->llvmType = functype;
-    assert(llvm::isa<llvm::FunctionType>(f->llvmType));
-
-    if (fdecl->isMain()) {
-        gIR->mainFunc = func;
-    }
-
-    // name parameters
-    llvm::Function::arg_iterator iarg = func->arg_begin();
-    int k = 0;
-    if (f->llvmRetInPtr) {
-        iarg->setName("retval");
-        f->llvmRetArg = iarg;
-        ++iarg;
-    }
-    if (f->llvmUsesThis) {
-        iarg->setName("this");
-        ++iarg;
-    }
-    int varargs = -1;
-    if (f->linkage == LINKd && f->varargs == 1)
-        varargs = 0;
-    for (; iarg != func->arg_end(); ++iarg)
-    {
-        Argument* arg = Argument::getNth(f->parameters, k++);
-        //arg->llvmValue = iarg;
-        //Logger::println("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident);
-        if (arg && arg->ident != 0) {
-            if (arg->vardecl) {
-                arg->vardecl->llvmValue = iarg;
-            }
-            iarg->setName(arg->ident->toChars());
-        }
-        else if (!arg && varargs >= 0) {
-            if (varargs == 0) {
-                iarg->setName("_arguments");
-                fdecl->llvmArguments = iarg;
-            }
-            else if (varargs == 1) {
-                iarg->setName("_argptr");
-                fdecl->llvmArgPtr = iarg;
-            }
-            else
-            assert(0);
-            varargs++;
-        }
-        else {
-            iarg->setName("unnamed");
-        }
-    }
-
-    Logger::cout() << "func decl: " << *func << '\n';
-
-    return func;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty)
 {
     /*size_t sz = gTargetData->getTypeSize(ty);
@@ -1174,7 +776,7 @@
     FuncDeclaration* fd = vd->toParent()->isFuncDeclaration();
     assert(fd != NULL);
 
-    IRFunction* fcur = &gIR->func();
+    IRFunction* fcur = gIR->func();
     FuncDeclaration* f = fcur->decl;
 
     // on this stack
@@ -1280,7 +882,7 @@
         // assignment to this in constructor special case
         if (lhs->isThis()) {
             llvm::Value* tmp = rhs->getRVal();
-            FuncDeclaration* fdecl = gIR->func().decl;
+            FuncDeclaration* fdecl = gIR->func()->decl;
             // respecify the this param
             if (!llvm::isa<llvm::AllocaInst>(fdecl->llvmThisVar))
                 fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", gIR->topallocapoint());
@@ -1716,3 +1318,113 @@
     gIR->ir->CreateBr(endinitbb);
     gIR->scope() = IRScope(endinitbb,oldend);
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoDefineDsymbol(Dsymbol* dsym)
+{
+    if (StructDeclaration* sd = dsym->isStructDeclaration()) {
+        DtoDefineStruct(sd);
+    }
+    else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
+        DtoDefineClass(cd);
+    }
+    else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
+        DtoDefineFunc(fd);
+    }
+    else {
+    error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
+    assert(0 && "unsupported dsymbol for DtoDefineDsymbol");
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoConstInitDsymbol(Dsymbol* dsym)
+{
+    if (StructDeclaration* sd = dsym->isStructDeclaration()) {
+        DtoConstInitStruct(sd);
+    }
+    else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
+        DtoConstInitClass(cd);
+    }
+    else if (VarDeclaration* vd = dsym->isVarDeclaration()) {
+        DtoConstInitGlobal(vd);
+    }
+    else {
+    error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
+    assert(0 && "unsupported dsymbol for DtoInitDsymbol");
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoConstInitGlobal(VarDeclaration* vd)
+{
+    Logger::println("DtoConstInitGlobal(%s)", vd->toChars());
+    LOG_SCOPE;
+
+    if (vd->llvmDModule) return;
+    vd->llvmDModule = gIR->dmodule;
+
+    bool emitRTstaticInit = false;
+
+    llvm::Constant* _init = 0;
+    if (vd->parent && vd->parent->isFuncDeclaration() && vd->init && vd->init->isExpInitializer()) {
+        _init = DtoConstInitializer(vd->type, NULL);
+        emitRTstaticInit = true;
+    }
+    else {
+        _init = DtoConstInitializer(vd->type, vd->init);
+    }
+
+    const llvm::Type* _type = DtoType(vd->type);
+    Type* t = DtoDType(vd->type);
+
+    //Logger::cout() << "initializer: " << *_init << '\n';
+    if (_type != _init->getType()) {
+        Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n";
+        // zero initalizer
+        if (_init->isNullValue())
+            _init = llvm::Constant::getNullValue(_type);
+        // pointer to global constant (struct.init)
+        else if (llvm::isa<llvm::GlobalVariable>(_init))
+        {
+            assert(_init->getType()->getContainedType(0) == _type);
+            llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init);
+            assert(t->ty == Tstruct);
+            TypeStruct* ts = (TypeStruct*)t;
+            assert(ts->sym->llvmInitZ);
+            _init = ts->sym->llvmInitZ;
+        }
+        // array single value init
+        else if (isaArray(_type))
+        {
+            _init = DtoConstStaticArray(_type, _init);
+        }
+        else {
+            Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
+            //assert(0);
+        }
+    }
+
+    bool istempl = false;
+    if ((vd->storage_class & STCcomdat) || (vd->parent && DtoIsTemplateInstance(vd->parent))) {
+        istempl = true;
+    }
+
+    if (_init && _init->getType() != _type)
+        _type = _init->getType();
+    llvm::cast<llvm::OpaqueType>(vd->llvmIRGlobal->type.get())->refineAbstractTypeTo(_type);
+    _type = vd->llvmIRGlobal->type.get();
+    assert(!_type->isAbstract());
+
+    llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(vd->llvmValue);
+    if (!(vd->storage_class & STCextern) && (vd->getModule() == gIR->dmodule || istempl))
+    {
+        gvar->setInitializer(_init);
+    }
+
+    if (emitRTstaticInit)
+        DtoLazyStaticInit(istempl, gvar, vd->init, t);
+}