diff gen/tollvm.cpp @ 88:058d3925950e trunk

[svn r92] Fixed support for statically initialized unions. lots of bugfixes as cleanups too.
author lindquist
date Tue, 06 Nov 2007 10:03:14 +0100
parents fd32135dca3e
children 16e88334bba7
line wrap: on
line diff
--- a/gen/tollvm.cpp	Sat Nov 03 14:48:33 2007 +0100
+++ b/gen/tollvm.cpp	Tue Nov 06 10:03:14 2007 +0100
@@ -14,6 +14,7 @@
 #include "gen/runtime.h"
 #include "gen/arrays.h"
 #include "gen/dvalue.h"
+#include "gen/structs.h"
 
 bool DtoIsPassedByRef(Type* type)
 {
@@ -375,16 +376,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-const llvm::Type* DtoStructType(Type* t)
-{
-    assert(0);
-    std::vector<const llvm::Type*> types;
-    return llvm::StructType::get(types);
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 static llvm::Function* LLVM_DeclareMemIntrinsic(const char* name, int bits, bool set=false)
 {
     assert(bits == 32 || bits == 64);
@@ -456,132 +447,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::Value* DtoStructZeroInit(llvm::Value* v)
-{
-    assert(gIR);
-    uint64_t n = gTargetData->getTypeSize(v->getType()->getContainedType(0));
-    //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n));
-    llvm::Type* sarrty = llvm::PointerType::get(llvm::Type::Int8Ty);
-
-    llvm::Value* sarr = new llvm::BitCastInst(v,sarrty,"tmp",gIR->scopebb());
-
-    llvm::Function* fn = LLVM_DeclareMemSet32();
-    std::vector<llvm::Value*> llargs;
-    llargs.resize(4);
-    llargs[0] = sarr;
-    llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false);
-    llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
-    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-    llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-
-    return ret;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoStructCopy(llvm::Value* dst, llvm::Value* src)
-{
-    Logger::cout() << "dst = " << *dst << " src = " << *src << '\n';
-    assert(dst->getType() == src->getType());
-    assert(gIR);
-
-    uint64_t n = gTargetData->getTypeSize(dst->getType()->getContainedType(0));
-    //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n));
-    llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
-
-    llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
-    llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"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);
-
-    return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-llvm::Constant* DtoConstStructInitializer(StructInitializer* si)
-{
-    llvm::StructType* structtype = llvm::cast<llvm::StructType>(si->ad->llvmType);
-    size_t n = structtype->getNumElements();
-
-    assert(si->value.dim == si->vars.dim);
-
-    std::vector<llvm::Constant*> inits;
-    inits.resize(n, NULL);
-    for (int i = 0; i < si->value.dim; ++i)
-    {
-        Initializer* ini = (Initializer*)si->value.data[i];
-        assert(ini);
-
-        VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
-        Type* vdtype = DtoDType(vd->type);
-        assert(vd);
-        Logger::println("vars[%d] = %s", i, vd->toChars());
-
-        llvm::Constant* v = 0;
-
-        assert(vd->llvmFieldIndex >= 0);
-        unsigned idx = vd->llvmFieldIndex;
-
-        if (ExpInitializer* ex = ini->isExpInitializer())
-        {
-            v = ex->exp->toConstElem(gIR);
-        }
-        else if (StructInitializer* si = ini->isStructInitializer())
-        {
-            v = DtoConstStructInitializer(si);
-        }
-        else if (ArrayInitializer* ai = ini->isArrayInitializer())
-        {
-            v = DtoConstArrayInitializer(ai);
-        }
-        else if (ini->isVoidInitializer())
-        {
-            v = llvm::UndefValue::get(structtype->getElementType(idx));
-        }
-        else
-        assert(v);
-
-        inits[idx] = v;
-        Logger::cout() << "init[" << idx << "] = " << *v << '\n';
-    }
-
-    // fill out nulls
-    assert(si->ad->llvmInitZ);
-    if (si->ad->llvmInitZ->isNullValue())
-    {
-        for (int i = 0; i < n; ++i)
-        {
-            if (inits[i] == 0)
-            {
-                inits[i] = llvm::Constant::getNullValue(structtype->getElementType(i));
-            }
-        }
-    }
-    else
-    {
-        for (int i = 0; i < n; ++i)
-        {
-            if (inits[i] == 0)
-            {
-                inits[i] = si->ad->llvmInitZ->getOperand(i);
-            }
-        }
-    }
-
-    return llvm::ConstantStruct::get(structtype, inits);
-}
-
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 llvm::Value* DtoNullDelegate(llvm::Value* v)
 {
     assert(gIR);
@@ -1495,65 +1360,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs)
-{
-    Logger::println("checking for offset %u type %s:", os, t->toChars());
-    LOG_SCOPE;
-
-    if (idxs.empty())
-        idxs.push_back(0);
-
-    const llvm::Type* llt = llvm::PointerType::get(DtoType(t));
-
-    for (unsigned i=0; i<sd->fields.dim; ++i) {
-        VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i];
-        Type* vdtype = DtoDType(vd->type);
-        Logger::println("found %u type %s", vd->offset, vdtype->toChars());
-        assert(vd->llvmFieldIndex >= 0);
-        if (os == vd->offset && vdtype == t) {
-            idxs.push_back(vd->llvmFieldIndex);
-            ptr = DtoGEP(ptr, idxs, "tmp");
-            if (ptr->getType() != llt)
-                ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
-            if (vd->llvmFieldIndexOffset)
-                ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
-            return ptr;
-        }
-        else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
-            TypeStruct* ts = (TypeStruct*)vdtype;
-            StructDeclaration* ssd = ts->sym;
-            idxs.push_back(vd->llvmFieldIndex);
-            if (vd->llvmFieldIndexOffset) {
-                Logger::println("has union field offset");
-                ptr = DtoGEP(ptr, idxs, "tmp");
-                if (ptr->getType() != llt)
-                    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
-                ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
-                std::vector<unsigned> tmp;
-                return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
-            }
-            else {
-                const llvm::Type* sty = llvm::PointerType::get(DtoType(vd->type));
-                if (ptr->getType() != sty) {
-                    ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
-                    std::vector<unsigned> tmp;
-                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
-                }
-                else {
-                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs);
-                }
-            }
-        }
-    }
-
-    size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
-    assert(os % llt_sz == 0);
-    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
-    return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 bool DtoIsTemplateInstance(Dsymbol* s)
 {
     if (!s) return false;
@@ -1563,3 +1369,28 @@
         return DtoIsTemplateInstance(s->parent);
     return false;
 }
+
+void DtoLazyStaticInit(bool istempl, llvm::Value* gvar, Initializer* init, Type* t)
+{
+    // create a flag to make sure initialization only happens once
+    llvm::GlobalValue::LinkageTypes gflaglink = istempl ? llvm::GlobalValue::WeakLinkage : llvm::GlobalValue::InternalLinkage;
+    std::string gflagname(gvar->getName());
+    gflagname.append("__initflag");
+    llvm::GlobalVariable* gflag = new llvm::GlobalVariable(llvm::Type::Int1Ty,false,gflaglink,DtoConstBool(false),gflagname,gIR->module);
+
+    // check flag and do init if not already done
+    llvm::BasicBlock* oldend = gIR->scopeend();
+    llvm::BasicBlock* initbb = new llvm::BasicBlock("ifnotinit",gIR->topfunc(),oldend);
+    llvm::BasicBlock* endinitbb = new llvm::BasicBlock("ifnotinitend",gIR->topfunc(),oldend);
+    llvm::Value* cond = gIR->ir->CreateICmpEQ(gIR->ir->CreateLoad(gflag,"tmp"),DtoConstBool(false));
+    gIR->ir->CreateCondBr(cond, initbb, endinitbb);
+    gIR->scope() = IRScope(initbb,endinitbb);
+    DValue* ie = DtoInitializer(init);
+    if (!ie->inPlace()) {
+        DValue* dst = new DVarValue(t, gvar, true);
+        DtoAssign(dst, ie);
+    }
+    gIR->ir->CreateStore(DtoConstBool(true), gflag);
+    gIR->ir->CreateBr(endinitbb);
+    gIR->scope() = IRScope(endinitbb,oldend);
+}