diff gen/llvmhelpers.cpp @ 797:340acf1535d0

Removed KDevelop3 project files, CMake can generate them just fine! Fixed function literals in static initializers. Changed alignment of delegates from 2*PTRSIZE to just PTRSIZE. Changed errors to go to stderr instead of stdout. Fairly major rewriting of struct/union/class handling, STILL A BIT BUGGY !!!
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sat, 29 Nov 2008 21:25:43 +0100
parents 6e7a4c3b64d2
children 92ea3015ace6
line wrap: on
line diff
--- a/gen/llvmhelpers.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/llvmhelpers.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -338,7 +338,7 @@
     {
         ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();
         LLValue* val = DtoLoad(irfunc->thisArg);
-        ctx = DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis"));
+        ctx = DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis"));
     }
     else
         ctx = irfunc->nestArg;
@@ -374,7 +374,7 @@
         if (!cd || !cd->vthis)
             return getNullPtr(getVoidPtrType());
         LLValue* val = DtoLoad(irfunc->thisArg);
-        return DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis"));
+        return DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis"));
     }
     else
     {
@@ -964,73 +964,68 @@
     if (vd->ir.initialized) return;
     vd->ir.initialized = gIR->dmodule;
 
-    Logger::println("* DtoConstInitGlobal(%s)", vd->toChars());
+    Logger::println("DtoConstInitGlobal(%s) @ %s", vd->toChars(), vd->locToChars());
     LOG_SCOPE;
 
-    bool emitRTstaticInit = false;
+    // if the variable is a function local static variable with a runtime initializer
+    // we must do lazy initialization, which involves a boolean flag to make sure it happens only once
+    // FIXME: I don't think it's thread safe ...
+
+    bool doLazyInit = false;
+    Dsymbol* par = vd->toParent2();
 
-    LLConstant* _init = 0;
-    if (vd->parent && vd->parent->isFuncDeclaration() && vd->init && vd->init->isExpInitializer()) {
-        _init = DtoConstInitializer(vd->loc, vd->type, NULL);
-        emitRTstaticInit = true;
-    }
-    else {
-        _init = DtoConstInitializer(vd->loc, vd->type, vd->init);
+    if (par && par->isFuncDeclaration() && vd->init)
+    {
+        if (ExpInitializer* einit = vd->init->isExpInitializer())
+        {
+            if (!einit->exp->isConst())
+            {
+                // mark as needing lazy now
+                doLazyInit = true;
+            }
+        }
     }
 
-    const LLType* _type = DtoType(vd->type);
-    Type* t = vd->type->toBasetype();
-
-    //Logger::cout() << "initializer: " << *_init << '\n';
-    if (_type != _init->getType()) {
-        if (Logger::enabled())
-            Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n";
+    // if we do lazy init, we start out with an undefined initializer
+    LLConstant* initVal;
+    if (doLazyInit)
+    {
+        initVal = llvm::UndefValue::get(DtoType(vd->type));
+    }
+    // otherwise we build it
+    else
+    {
+        initVal = DtoConstInitializer(vd->loc, vd->type, vd->init);
+    }
 
-        // 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->ir.irStruct->constInit);
-            _init = ts->sym->ir.irStruct->constInit;
-        }
-        // array single value init
-        else if (isaArray(_type))
-        {
-            _init = DtoConstStaticArray(_type, _init);
-        }
-        else {
-            if (Logger::enabled())
-                Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
-            //assert(0);
-        }
-    }
+    // set the initializer if appropriate
+    IrGlobal* glob = vd->ir.irGlobal;
+    llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(glob->value);
+
+    // refine the global's opaque type to the type of the initializer
+    llvm::cast<LLOpaqueType>(glob->type.get())->refineAbstractTypeTo(initVal->getType());
+
+    glob->constInit = initVal;
 
     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<LLOpaqueType>(vd->ir.irGlobal->type.get())->refineAbstractTypeTo(_type);
-    _type = vd->ir.irGlobal->type.get();
+    // assign the initializer
+    llvm::GlobalVariable* globalvar = llvm::cast<llvm::GlobalVariable>(glob->value);
 
-    llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(vd->ir.irGlobal->value);
     if (!(vd->storage_class & STCextern) && (vd->getModule() == gIR->dmodule || istempl))
     {
         if (Logger::enabled())
         {
             Logger::println("setting initializer");
             Logger::cout() << "global: " << *gvar << '\n';
-            Logger::cout() << "init:   " << *_init << '\n';
+            Logger::cout() << "init:   " << *initVal << '\n';
         }
-        gvar->setInitializer(_init);
+
+        gvar->setInitializer(initVal);
+
         // do debug info
         if (global.params.symdebug)
         {
@@ -1040,8 +1035,8 @@
         }
     }
 
-    if (emitRTstaticInit)
-        DtoLazyStaticInit(istempl, gvar, vd->init, t);
+    if (doLazyInit)
+        DtoLazyStaticInit(istempl, gvar, vd->init, vd->type);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -1396,18 +1391,18 @@
 //      INITIALIZER HELPERS
 ////////////////////////////////////////////////////////////////////////////////////////*/
 
-LLConstant* DtoConstInitializer(Loc& loc, Type* type, Initializer* init)
+LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
 {
     LLConstant* _init = 0; // may return zero
     if (!init)
     {
         Logger::println("const default initializer for %s", type->toChars());
-        _init = DtoDefaultInit(loc, type);
+        _init = DtoConstExpInit(loc, type, type->defaultInit());
     }
     else if (ExpInitializer* ex = init->isExpInitializer())
     {
         Logger::println("const expression initializer");
-        _init = ex->exp->toConstElem(gIR);
+        _init = DtoConstExpInit(loc, type, ex->exp);;
     }
     else if (StructInitializer* si = init->isStructInitializer())
     {
@@ -1433,7 +1428,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-LLConstant* DtoConstFieldInitializer(Loc& loc, Type* t, Initializer* init)
+LLConstant* DtoConstFieldInitializer(Loc loc, Type* t, Initializer* init)
 {
     Logger::println("DtoConstFieldInitializer");
     LOG_SCOPE;
@@ -1530,20 +1525,33 @@
 
 static LLConstant* expand_to_sarray(Type *base, Expression* exp)
 {
-    Logger::println("building type %s to expression (%s) of type %s", base->toChars(), exp->toChars(), exp->type->toChars());
+    Logger::println("building type %s from expression (%s) of type %s", base->toChars(), exp->toChars(), exp->type->toChars());
     const LLType* dstTy = DtoType(base);
     if (Logger::enabled())
         Logger::cout() << "final llvm type requested: " << *dstTy << '\n';
-    
+
     LLConstant* val = exp->toConstElem(gIR);
-    
+
     Type* expbase = exp->type->toBasetype();
-    Type* t = base;
-    
+    Logger::println("expbase: %s", expbase->toChars());
+    Type* t = base->toBasetype();
+
     LLSmallVector<size_t, 4> dims;
 
+    // handle zero initializers
+    if (expbase->isintegral() && exp->isConst())
+    {
+        if (!exp->toInteger())
+            return LLConstant::getNullValue(dstTy);
+    }
+    else if (exp->op == TOKnull)
+    {
+        return LLConstant::getNullValue(dstTy);
+    }
+
     while(1)
     {
+        Logger::println("t: %s", t->toChars());
         if (t->equals(expbase))
             break;
         assert(t->ty == Tsarray);
@@ -1552,7 +1560,7 @@
         assert(t->nextOf());
         t = t->nextOf()->toBasetype();
     }
-    
+
     size_t i = dims.size();
     assert(i);
 
@@ -1564,17 +1572,15 @@
         inits.insert(inits.end(), dims[i], val);
         val = LLConstantArray::get(arrty, inits);
     }
-    
+
     return val;
 }
 
-LLConstant* DtoDefaultInit(Loc& loc, Type* type)
+LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp)
 {
-    Expression* exp = type->defaultInit();
-    
     Type* expbase = exp->type->toBasetype();
     Type* base = type->toBasetype();
-    
+
     // if not the same basetypes, we won't get the same llvm types either
     if (!expbase->equals(base))
     {
@@ -1584,7 +1590,6 @@
                 error(loc, "static arrays of voids have no default initializer");
                 fatal();
             }
-            
             Logger::println("type is a static array, building constant array initializer to single value");
             return expand_to_sarray(base, exp);
         }
@@ -1594,9 +1599,8 @@
             fatal();
         }
         assert(0);
-        
     }
-    
+
     return exp->toConstElem(gIR);
 }
 
@@ -1615,6 +1619,7 @@
         ++p;
     }
     // create a noop with the code as the result name!
+    // FIXME: this is const folded and eliminated immediately ... :/
     gIR->ir->CreateAnd(DtoConstSize_t(0),DtoConstSize_t(0),s.c_str());
 }