diff gen/tollvm.c @ 40:8b0e809563df trunk

[svn r44] Lots of bug fixes. New array literal support New array ~= operator support (for single element) New with statement support More...
author lindquist
date Fri, 19 Oct 2007 07:43:21 +0200
parents 4648206ca213
children e5c4bece7fa1
line wrap: on
line diff
--- a/gen/tollvm.c	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/tollvm.c	Fri Oct 19 07:43:21 2007 +0200
@@ -1,11 +1,6 @@
 #include <iostream>
 
-#include "llvm/Constants.h"
-#include "llvm/Type.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/GlobalValue.h"
-#include "llvm/Instructions.h"
-#include "llvm/CallingConv.h"
+#include "gen/llvm.h"
 
 #include "mtype.h"
 #include "dsymbol.h"
@@ -20,6 +15,29 @@
 #include "gen/elem.h"
 #include "gen/arrays.h"
 
+bool LLVM_DtoIsPassedByRef(Type* type)
+{
+    TY t = type->ty;
+    if (t == Tstruct || t == Tarray || t == Tdelegate)
+        return true;
+    else if (t == Ttypedef) {
+        Type* bt = type->toBasetype();
+        assert(bt);
+        return LLVM_DtoIsPassedByRef(bt);
+    }
+    return false;
+}
+
+Type* LLVM_DtoDType(Type* t)
+{
+    if (t->ty == Ttypedef) {
+        Type* bt = t->toBasetype();
+        assert(bt);
+        return LLVM_DtoDType(bt);
+    }
+    return t;
+}
+
 const llvm::Type* LLVM_DtoType(Type* t)
 {
     assert(t);
@@ -167,9 +185,7 @@
     const llvm::Type* rettype;
     std::vector<const llvm::Type*> paramvec;
 
-    TY retty = f->next->ty;
-
-    if (retty == Tstruct || retty == Tdelegate || retty == Tarray) {
+    if (LLVM_DtoIsPassedByRef(f->next)) {
         rettype = llvm::PointerType::get(LLVM_DtoType(f->next));
         paramvec.push_back(rettype);
         rettype = llvm::Type::VoidTy;
@@ -225,7 +241,7 @@
         actualRettype = rettype;
     }
     else if (rt) {
-        if (rt->ty == Tstruct || rt->ty == Tdelegate || rt->ty == Tarray) {
+        if (LLVM_DtoIsPassedByRef(rt)) {
             rettype = llvm::PointerType::get(LLVM_DtoType(rt));
             actualRettype = llvm::Type::VoidTy;
             f->llvmRetInPtr = retinptr = true;
@@ -265,7 +281,7 @@
     for (int i=0; i < n; ++i) {
         Argument* arg = Argument::getNth(f->parameters, i);
         // ensure scalar
-        Type* argT = arg->type;
+        Type* argT = LLVM_DtoDType(arg->type);
         assert(argT);
 
         if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
@@ -286,6 +302,16 @@
             //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");
+            if (argT->ty == Tstruct || argT->ty == Tclass)
+                paramvec.push_back(llvm::PointerType::get(at));
+            else
+            assert(0);
+        }
+        /*if (llvm::isa<llvm::StructType>(at) || argT->ty == Tstruct || argT->ty == Tsarray) {
+            paramvec.push_back(llvm::PointerType::get(at));
+        }*/
         else {
             if (!arg->llvmCopy) {
                 Logger::println("ref param");
@@ -453,7 +479,7 @@
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-llvm::Constant* LLVM_DtoStructInitializer(StructInitializer* si)
+llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si)
 {
     llvm::StructType* structtype = llvm::cast<llvm::StructType>(si->ad->llvmType);
     size_t n = structtype->getNumElements();
@@ -468,11 +494,12 @@
         assert(ini);
 
         VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
+        Type* vdtype = LLVM_DtoDType(vd->type);
         assert(vd);
         Logger::println("vars[%d] = %s", i, vd->toChars());
 
         std::vector<unsigned> idxs;
-        si->ad->offsetToIndex(vd->type, vd->offset, idxs);
+        si->ad->offsetToIndex(vdtype, vd->offset, idxs);
         assert(idxs.size() == 1);
         unsigned idx = idxs[0];
 
@@ -480,17 +507,15 @@
 
         if (ExpInitializer* ex = ini->isExpInitializer())
         {
-            elem* e = ex->exp->toElem(gIR);
-            v = llvm::cast<llvm::Constant>(e->val);
-            delete e;
+            v = ex->exp->toConstElem(gIR);
         }
         else if (StructInitializer* si = ini->isStructInitializer())
         {
-            v = LLVM_DtoStructInitializer(si);
+            v = LLVM_DtoConstStructInitializer(si);
         }
         else if (ArrayInitializer* ai = ini->isArrayInitializer())
         {
-            v = LLVM_DtoArrayInitializer(ai);
+            v = LLVM_DtoConstArrayInitializer(ai);
         }
         else if (ini->isVoidInitializer())
         {
@@ -731,20 +756,6 @@
 
     // return
     new llvm::ReturnInst(call,bb);
-
-    /*
-    // return value type
-    const llvm::Type* rettype;
-    Type* rt = f->next;
-    if (rt) {
-        rettype = LLVM_DtoType(rt);
-    }
-    else {
-        assert(0);
-    }
-
-    llvm::FunctionType* functype = llvm::FunctionType::get(rettype, paramvec, false);
-    */
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -802,47 +813,54 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::Constant* LLVM_DtoInitializer(Type* type, Initializer* init)
+llvm::Constant* LLVM_DtoConstInitializer(Type* type, Initializer* init)
 {
     llvm::Constant* _init = 0; // may return zero
     if (!init)
     {
-        Logger::println("default initializer");
-        elem* e = type->defaultInit()->toElem(gIR);
-        if (!e->inplace && !e->isNull()) {
-            _init = llvm::cast<llvm::Constant>(e->getValue());
-        }
-        delete e;
+        Logger::println("const default initializer for %s", type->toChars());
+        _init = type->defaultInit()->toConstElem(gIR);
     }
     else if (ExpInitializer* ex = init->isExpInitializer())
     {
-        Logger::println("expression initializer");
-        elem* e = ex->exp->toElem(gIR);
-        if (!e->inplace && !e->isNull()) {
-            _init = llvm::cast<llvm::Constant>(e->getValue());
-        }
-        delete e;
+        Logger::println("const expression initializer");
+        _init = ex->exp->toConstElem(gIR);
     }
     else if (StructInitializer* si = init->isStructInitializer())
     {
-        Logger::println("struct initializer");
-        _init = LLVM_DtoStructInitializer(si);
+        Logger::println("const struct initializer");
+        _init = LLVM_DtoConstStructInitializer(si);
     }
     else if (ArrayInitializer* ai = init->isArrayInitializer())
     {
-        Logger::println("array initializer");
-        _init = LLVM_DtoArrayInitializer(ai);
+        Logger::println("const array initializer");
+        _init = LLVM_DtoConstArrayInitializer(ai);
     }
     else if (init->isVoidInitializer())
     {
-        Logger::println("void initializer");
+        Logger::println("const void initializer");
         const llvm::Type* ty = LLVM_DtoType(type);
         _init = llvm::Constant::getNullValue(ty);
     }
     else {
+        Logger::println("unsupported const initializer: %s", init->toChars());
+    }
+    return _init;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void LLVM_DtoInitializer(Initializer* init)
+{
+    if (ExpInitializer* ex = init->isExpInitializer())
+    {
+        Logger::println("expression initializer");
+        elem* e = ex->exp->toElem(gIR);
+        delete e;
+    }
+    else {
         Logger::println("unsupported initializer: %s", init->toChars());
     }
-    return _init;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -862,13 +880,14 @@
 {
     size_t n = src.size();
     std::vector<llvm::Value*> dst(n);
-    Logger::cout() << "indices:";
+    std::ostream& ostr = Logger::cout();
+    ostr << "indices for '" << *ptr << "':";
     for (size_t i=0; i<n; ++i)
     {
-        Logger::cout() << ' ' << i;
+        ostr << ' ' << i;
         dst[i] = llvm::ConstantInt::get(llvm::Type::Int32Ty, src[i], false);
     }
-    Logger::cout() << '\n';
+    ostr << '\n';
     return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb);
 }
 
@@ -912,7 +931,7 @@
     }
 
     // regular function
-    TypeFunction* f = (TypeFunction*)fdecl->type;
+    TypeFunction* f = (TypeFunction*)LLVM_DtoDType(fdecl->type);
     assert(f != 0);
 
     if (fdecl->llvmValue != 0) {
@@ -1054,9 +1073,93 @@
     call->setCallingConv(llvm::CallingConv::C);
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
 
+llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp)
+{
+    llvm::Value* retval = 0;
+
+    bool haslvals = !gIR->lvals.empty();
+    if (haslvals)
+        gIR->lvals.push_back(NULL);
+
+    elem* arg = argexp->toElem(gIR);
+
+    if (haslvals)
+        gIR->lvals.pop_back();
+
+    if (arg->inplace) {
+        assert(arg->mem != 0);
+        retval = arg->mem;
+        delete arg;
+        return retval;
+    }
+
+    Type* realtype = LLVM_DtoDType(argexp->type);
+    TY argty = realtype->ty;
+    if (LLVM_DtoIsPassedByRef(realtype)) {
+        if (!fnarg || !fnarg->llvmCopy) {
+            retval = arg->getValue();
+            assert(retval != 0);
+        }
+        else {
+            llvm::Value* allocaInst = 0;
+            llvm::BasicBlock* entryblock = &gIR->topfunc()->front();
+            //const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(arg->mem->getType());
+            const llvm::PointerType* pty = llvm::PointerType::get(LLVM_DtoType(argexp->type));
+            if (argty == Tstruct) {
+                allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
+                TypeStruct* ts = (TypeStruct*)LLVM_DtoDType(argexp->type);
+                LLVM_DtoStructCopy(ts,allocaInst,arg->mem);
+            }
+            else if (argty == Tdelegate) {
+                allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
+                LLVM_DtoDelegateCopy(allocaInst,arg->mem);
+            }
+            else if (argty == Tarray) {
+                if (arg->type == elem::SLICE) {
+                    allocaInst = new llvm::AllocaInst(LLVM_DtoType(argexp->type), "tmpparam", gIR->topallocapoint());
+                    LLVM_DtoSetArray(allocaInst, arg->arg, arg->mem);
+                }
+                else {
+                    allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
+                    LLVM_DtoArrayAssign(allocaInst,arg->mem);
+                }
+            }
+            else
+            assert(0);
+
+            assert(allocaInst != 0);
+            retval = allocaInst;
+        }
+    }
+    else if (!fnarg || fnarg->llvmCopy) {
+        Logger::println("regular arg");
+        assert(arg->type != elem::SLICE);
+        if (arg->mem) Logger::cout() << "mem = " << *arg->mem << '\n';
+        if (arg->val) Logger::cout() << "val = " << *arg->val << '\n';
+        if (arg->arg) Logger::cout() << "arg = " << *arg->arg << '\n';
+        retval = arg->arg ? arg->arg : arg->field ? arg->mem : arg->getValue();
+    }
+    else {
+        Logger::println("as ptr arg");
+        retval = arg->mem ? arg->mem : arg->val;
+        if (retval->getType() != paramtype)
+        {
+            assert(retval->getType() == paramtype->getContainedType(0));
+            LLVM_DtoGiveArgumentStorage(arg);
+            new llvm::StoreInst(retval, arg->mem, gIR->scopebb());
+            retval = arg->mem;
+        }
+    }
+
+    delete arg;
+
+    if (fnarg && retval->getType() != paramtype) {
+        Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n";
+        assert(0 && "parameter type that was actually passed is invalid");
+    }
+    return retval;
+}
 
 
-
-
-