diff gen/toir.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 4adf0f742896
children 28ce72c60a21
line wrap: on
line diff
--- a/gen/toir.cpp	Sat Nov 29 12:28:10 2008 +0100
+++ b/gen/toir.cpp	Sat Nov 29 21:25:43 2008 +0100
@@ -135,20 +135,27 @@
         }
         else {
             Logger::println("a normal variable");
+
             // take care of forward references of global variables
             if (vd->isDataseg() || (vd->storage_class & STCextern)) {
                 vd->toObjFile(0); // TODO: multiobj
             }
-            if (!vd->ir.isSet() || !vd->ir.getIrValue()) {
+
+            LLValue* val;
+
+            if (!vd->ir.isSet() || !(val = vd->ir.getIrValue())) {
                 error("variable %s not resolved", vd->toChars());
                 if (Logger::enabled())
                     Logger::cout() << "unresolved variable had type: " << *DtoType(vd->type) << '\n';
                 fatal();
             }
+
             if (vd->isDataseg() || (vd->storage_class & STCextern)) {
                 DtoConstInitGlobal(vd);
+                val = DtoBitCast(val, DtoType(type->pointerTo()));
             }
-            return new DVarValue(type, vd, vd->ir.getIrValue());
+
+            return new DVarValue(type, vd, val);
         }
     }
     else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
@@ -369,7 +376,7 @@
     llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
     if (Logger::enabled())
         Logger::cout() << "type: " << *at << "\ninit: " << *_init << '\n';
-    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,".stringliteral",gIR->module);
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,".str",gIR->module);
 
     llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false);
     LLConstant* idxs[2] = { zero, zero };
@@ -443,7 +450,7 @@
     }
 
     llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
-    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,".stringliteral",gIR->module);
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,".str",gIR->module);
 
     llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false);
     LLConstant* idxs[2] = { zero, zero };
@@ -1008,19 +1015,21 @@
             assert(fdecl->vtblIndex > 0);
             assert(e1type->ty == Tclass);
 
-            LLValue* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false);
-            LLValue* vtblidx = llvm::ConstantInt::get(LLType::Int32Ty, (size_t)fdecl->vtblIndex, false);
+            LLValue* zero = DtoConstUint(0);
+            size_t vtblidx = fdecl->vtblIndex;
             if (Logger::enabled())
                 Logger::cout() << "vthis: " << *vthis << '\n';
-            funcval = DtoGEP(vthis, zero, zero);
+            funcval = vthis;
+            if (!fdecl->isMember2()->isInterfaceDeclaration())
+                funcval = DtoGEP(funcval, zero, zero);
             funcval = DtoLoad(funcval);
-            funcval = DtoGEP(funcval, zero, vtblidx, toChars());
+            Logger::println("vtblidx = %lu", vtblidx);
+            funcval = DtoGEP(funcval, zero, DtoConstUint(vtblidx), toChars());
             funcval = DtoLoad(funcval);
-        #if OPAQUE_VTBLS
+
             funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type)));
             if (Logger::enabled())
                 Logger::cout() << "funcval casted: " << *funcval << '\n';
-        #endif
         }
         // static call
         else {
@@ -2143,6 +2152,22 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+LLConstant* FuncExp::toConstElem(IRState* p)
+{
+    Logger::print("FuncExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    assert(fd);
+    assert(fd->tok == TOKfunction);
+
+    DtoForceDefineDsymbol(fd);
+    assert(fd->ir.irFunc->func);
+
+    return fd->ir.irFunc->func;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 DValue* ArrayLiteralExp::toElem(IRState* p)
 {
     Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
@@ -2252,91 +2277,147 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+void addZeros(std::vector<llvm::Value*>& inits, unsigned pos, unsigned offset);
+
 DValue* StructLiteralExp::toElem(IRState* p)
 {
     Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    const LLType* llt = DtoType(type);
-
-    LLValue* mem = 0;
-
-    LLValue* sptr = DtoAlloca(llt,"tmpstructliteral");
-
-    // default init the struct to take care of padding
-    // and unspecified members
-    TypeStruct* ts = (TypeStruct*)type->toBasetype();
-    assert(ts->sym);
-    DtoForceConstInitDsymbol(ts->sym);
-    assert(ts->sym->ir.irStruct->init);
-    DtoAggrCopy(sptr, ts->sym->ir.irStruct->init);
-
-    // num elements in literal
-    unsigned n = elements->dim;
-
-    // unions might have different types for each literal
-    if (sd->ir.irStruct->hasUnions) {
-        // build the type of the literal
-        std::vector<const LLType*> tys;
-        for (unsigned i=0; i<n; ++i) {
-            Expression* vx = (Expression*)elements->data[i];
-            if (!vx) continue;
-            tys.push_back(DtoType(vx->type));
+    // get arrays 
+    size_t n = elements->dim;
+    Expression** exprs = (Expression**)elements->data;
+
+    assert(sd->fields.dim == n);
+    VarDeclaration** vars = (VarDeclaration**)sd->fields.data;
+
+    // vector of values to build aggregate from
+    std::vector<llvm::Value*> values;
+
+    // trackers
+    size_t lastoffset = 0;
+    size_t lastsize = 0;
+
+    // for through each field and build up the struct, padding with zeros
+    for (size_t i=0; i<n; i++)
+    {
+        Expression* e = exprs[i];
+        VarDeclaration* var = vars[i];
+
+        // field is skipped
+        if (!e)
+            continue;
+
+        // add any 0 padding needed before this field
+        if (var->offset > lastoffset + lastsize)
+        {
+            addZeros(values, lastoffset + lastsize, var->offset);
         }
-        const LLStructType* t = LLStructType::get(tys, sd->ir.irStruct->packed);
-        if (t != llt) {
-            if (getABITypeSize(t) != getABITypeSize(llt)) {
-                if (Logger::enabled())
-                    Logger::cout() << "got size " << getABITypeSize(t) << ", expected " << getABITypeSize(llt) << '\n';
-                assert(0 && "type size mismatch");
-            }
-            sptr = DtoBitCast(sptr, getPtrToType(t));
-            if (Logger::enabled())
-                Logger::cout() << "sptr type is now: " << *t << '\n';
-        }
+
+        // add the expression value
+        DValue* v = e->toElem(p);
+        values.push_back(v->getRVal());
+
+        // update offsets
+        lastoffset = var->offset;
+        lastsize = var->type->size();
+    }
+
+    // add any 0 padding needed at the end of the literal
+    const LLType* structtype = DtoType(sd->type);
+    size_t structsize = getABITypeSize(structtype);
+
+    if (structsize > lastoffset+lastsize)
+    {
+        addZeros(values, lastoffset + lastsize, structsize);
     }
 
-    // build
-    unsigned j = 0;
-    for (unsigned i=0; i<n; ++i)
+    // get the struct type from the values
+    n = values.size();
+    std::vector<const LLType*> types(n, NULL);
+
+    for (size_t i=0; i<n; i++)
     {
-        Expression* vx = (Expression*)elements->data[i];
-        if (!vx) continue;
-
-        if (Logger::enabled())
-            Logger::cout() << "getting index " << j << " of " << *sptr << '\n';
-        LLValue* arrptr = DtoGEPi(sptr,0,j);
-        DValue* darrptr = new DVarValue(vx->type, arrptr);
-
-        DValue* ve = vx->toElem(p);
-        DtoAssign(loc, darrptr, ve);
-
-        j++;
+        types[i] = values[i]->getType();
     }
 
-    return new DImValue(type, sptr);
+    const LLStructType* sty = LLStructType::get(types, sd->ir.irStruct->packed);
+
+    // allocate storage for the struct literal on the stack
+    LLValue* mem = DtoAlloca(sty, "tmpstructliteral");
+
+    // put all the values into the storage
+    for (size_t i=0; i<n; i++)
+    {
+        LLValue* ptr = DtoGEPi(mem, 0, i);
+        DtoStore(values[i], ptr);
+    }
+
+    // cast the alloca pointer to the "formal" struct type
+    mem = DtoBitCast(mem, getPtrToType(structtype));
+
+    // return as a var
+    return new DVarValue(type, mem);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+void addZeros(std::vector<llvm::Constant*>& inits, unsigned pos, unsigned offset);
+
 LLConstant* StructLiteralExp::toConstElem(IRState* p)
 {
     Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    unsigned n = elements->dim;
-    std::vector<LLConstant*> vals(n, NULL);
-
-    for (unsigned i=0; i<n; ++i)
+    // get arrays 
+    size_t n = elements->dim;
+    Expression** exprs = (Expression**)elements->data;
+
+    assert(sd->fields.dim == n);
+    VarDeclaration** vars = (VarDeclaration**)sd->fields.data;
+
+    // vector of values to build aggregate from
+    std::vector<llvm::Constant*> values;
+
+    // trackers
+    size_t lastoffset = 0;
+    size_t lastsize = 0;
+
+    // for through each field and build up the struct, padding with zeros
+    for (size_t i=0; i<n; i++)
     {
-        Expression* vx = (Expression*)elements->data[i];
-        vals[i] = vx->toConstElem(p);
+        Expression* e = exprs[i];
+        VarDeclaration* var = vars[i];
+
+        // field is skipped
+        if (!e)
+            continue;
+
+        // add any 0 padding needed before this field
+        if (var->offset > lastoffset + lastsize)
+        {
+            addZeros(values, lastoffset + lastsize, var->offset);
+        }
+
+        // add the expression value
+        values.push_back(e->toConstElem(p));
+
+        // update offsets
+        lastoffset = var->offset;
+        lastsize = var->type->size();
     }
 
-    assert(type->toBasetype()->ty == Tstruct);
-    const LLType* t = DtoType(type);
-    const LLStructType* st = isaStruct(t);
-    return llvm::ConstantStruct::get(st,vals);
+    // add any 0 padding needed at the end of the literal
+    const LLType* structtype = DtoType(sd->type);
+    size_t structsize = getABITypeSize(structtype);
+
+    if (structsize > lastoffset+lastsize)
+    {
+        addZeros(values, lastoffset + lastsize, structsize);
+    }
+
+    // return constant struct
+    return LLConstantStruct::get(values, sd->ir.irStruct->packed);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////