diff gen/toir.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 77cdca8c210f
children 0b9b286b67b6
line wrap: on
line diff
--- a/gen/toir.c	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/toir.c	Fri Oct 19 07:43:21 2007 +0200
@@ -12,12 +12,7 @@
 #include <fstream>
 #include <iostream>
 
-#include "llvm/Type.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Constants.h"
-#include "llvm/Instructions.h"
-#include "llvm/IntrinsicInst.h"
-#include "llvm/CallingConv.h"
+#include "gen/llvm.h"
 
 #include "total.h"
 #include "init.h"
@@ -60,7 +55,7 @@
             vd->llvmValue = allocainst;
             // e->val = really needed??
 
-            LLVM_DtoInitializer(vd->type, vd->init);
+            LLVM_DtoInitializer(vd->init);
         }
     }
     // struct declaration
@@ -69,6 +64,17 @@
         Logger::println("StructDeclaration");
         s->toObjFile();
     }
+    // function declaration
+    else if (FuncDeclaration* f = declaration->isFuncDeclaration())
+    {
+        Logger::println("FuncDeclaration");
+        f->toObjFile();
+    }
+    // alias declaration
+    else if (AliasDeclaration* a = declaration->isAliasDeclaration())
+    {
+        Logger::println("AliasDeclaration");
+    }
     // unsupported declaration
     else
     {
@@ -91,6 +97,10 @@
     if (VarDeclaration* vd = var->isVarDeclaration())
     {
         Logger::println("VarDeclaration");
+        
+        // needed to take care of forward references of global variables
+        if (!vd->llvmTouched && vd->isDataseg())
+            vd->toObjFile();
 
         if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
         {
@@ -98,6 +108,7 @@
         }
 
         // this must be a dollar expression or some other magic value
+        // or it could be a forward declaration of a global variable
         if (!vd->llvmValue)
         {
             // dollar
@@ -109,19 +120,17 @@
                 e->val = new llvm::LoadInst(tmp,"tmp",p->scopebb());
                 e->type = elem::VAL;
             }
-            // magic
-            else
+            // typeinfo
+            else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
             {
-                if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
-                {
-                    tid->toObjFile();
-                    e->mem = tid->llvmValue;
-                    e->type = elem::VAR;
-                }
-                else {
-                    Logger::println("unsupported: %s\n", vd->toChars());
-                    assert(0 && "only magic supported is typeinfo");
-                }
+                tid->toObjFile();
+                e->mem = tid->llvmValue;
+                e->type = elem::VAR;
+            }
+            // global forward ref
+            else {
+                Logger::println("unsupported: %s\n", vd->toChars());
+                assert(0 && "only magic supported is typeinfo");
             }
             return e;
         }
@@ -134,7 +143,7 @@
                 e->type = elem::VAR;
             }
             else {
-                if (vd->type->ty == Tstruct || vd->type->ty == Tdelegate || vd->type->ty == Tarray) {
+                if (LLVM_DtoIsPassedByRef(vd->type)) {
                     e->mem = vd->llvmValue;
                     e->type = elem::VAR;
                 }
@@ -173,11 +182,10 @@
     else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
     {
         // this seems to be the static initialiser for structs
-        Logger::print("Sym: type=%s\n", sdecl->type->toChars());
-        assert(sdecl->type->ty == Tstruct);
-        //assert(sdecl->llvmInitZ);
-        //e->val = sdecl->llvmInitZ;
-        TypeStruct* ts = (TypeStruct*)sdecl->type;
+        Type* sdecltype = LLVM_DtoDType(sdecl->type);
+        Logger::print("Sym: type=%s\n", sdecltype->toChars());
+        assert(sdecltype->ty == Tstruct);
+        TypeStruct* ts = (TypeStruct*)sdecltype;
         e->mem = ts->llvmInit;
         assert(e->mem);
         e->type = elem::VAR;
@@ -193,24 +201,52 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+llvm::Constant* VarExp::toConstElem(IRState* p)
+{
+    Logger::print("VarExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+    if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
+    {
+        // this seems to be the static initialiser for structs
+        Type* sdecltype = LLVM_DtoDType(sdecl->type);
+        Logger::print("Sym: type=%s\n", sdecltype->toChars());
+        assert(sdecltype->ty == Tstruct);
+        TypeStruct* ts = (TypeStruct*)sdecltype;
+        assert(ts->sym->llvmInitZ);
+        return ts->sym->llvmInitZ;
+    }
+    assert(0 && "Only support const var exp is SymbolDeclaration");
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 elem* IntegerExp::toElem(IRState* p)
 {
     Logger::print("IntegerExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     elem* e = new elem;
+    e->val = toConstElem(p);
+    e->type = elem::CONST;
+    return e;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* IntegerExp::toConstElem(IRState* p)
+{
+    Logger::print("IntegerExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
     const llvm::Type* t = LLVM_DtoType(type);
     if (llvm::isa<llvm::PointerType>(t)) {
         llvm::Constant* i = llvm::ConstantInt::get(LLVM_DtoSize_t(),(uint64_t)value,false);
-        e->val = llvm::ConstantExpr::getIntToPtr(i, t);
+        return llvm::ConstantExpr::getIntToPtr(i, t);
     }
     else if (llvm::isa<llvm::IntegerType>(t)) {
-        e->val = llvm::ConstantInt::get(t,(uint64_t)value,!type->isunsigned());
+        return llvm::ConstantInt::get(t,(uint64_t)value,!type->isunsigned());
     }
-    else {
-        assert(0);
-    }
-    e->type = elem::CONST;
-    return e;
+    assert(0);
+    return NULL;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -220,15 +256,24 @@
     Logger::print("RealExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     elem* e = new elem;
+    e->val = toConstElem(p);
+    e->type = elem::CONST;
+    return e;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* RealExp::toConstElem(IRState* p)
+{
+    Logger::print("RealExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
     const llvm::Type* fty = LLVM_DtoType(type);
     if (type->ty == Tfloat32)
-        e->val = llvm::ConstantFP::get(fty,float(value));
+        return llvm::ConstantFP::get(fty,float(value));
     else if (type->ty == Tfloat64 || type->ty == Tfloat80)
-        e->val = llvm::ConstantFP::get(fty,double(value));
-    else
+        return llvm::ConstantFP::get(fty,double(value));
     assert(0);
-    e->type = elem::CONST;
-    return e;
+    return NULL;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -238,19 +283,28 @@
     Logger::print("NullExp::toElem(type=%s): %s\n", type->toChars(),toChars());
     LOG_SCOPE;
     elem* e = new elem;
+    e->val = toConstElem(p);
+    e->type = elem::NUL;
+    //Logger::cout() << "null value is now " << *e->val << '\n';
+    return e;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* NullExp::toConstElem(IRState* p)
+{
+    Logger::print("NullExp::toConstElem(type=%s): %s\n", type->toChars(),toChars());
+    LOG_SCOPE;
     const llvm::Type* t = LLVM_DtoType(type);
-
     if (type->ty == Tarray) {
         assert(llvm::isa<llvm::StructType>(t));
-        e->val = llvm::ConstantAggregateZero::get(t);
+        return llvm::ConstantAggregateZero::get(t);
     }
-    else
-        e->val = llvm::Constant::getNullValue(t);
-    assert(e->val);
-
-    Logger::cout() << "null value is now " << *e->val << '\n';
-    e->type = elem::NUL;
-    return e;
+    else {
+        return llvm::Constant::getNullValue(t);
+    }
+    assert(0);
+    return NULL;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -260,10 +314,12 @@
     Logger::print("StringExp::toElem: %s | \n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    assert(type->next->ty == Tchar && "Only char is supported");
+    Type* dtype = LLVM_DtoDType(type);
+
+    assert(dtype->next->ty == Tchar && "Only char is supported");
     assert(sz == 1);
 
-    const llvm::Type* ct = LLVM_DtoType(type->next);
+    const llvm::Type* ct = LLVM_DtoType(dtype->next);
     //printf("ct = %s\n", type->next->toChars());
     const llvm::ArrayType* at = llvm::ArrayType::get(ct,len+1);
 
@@ -276,22 +332,20 @@
     llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,"stringliteral",gIR->module);
 
     llvm::ConstantInt* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-    //llvm::Value* arrptr = LLVM_DtoGEP(gvar,zero,zero,"tmp",p->scopebb());
     llvm::Constant* idxs[2] = { zero, zero };
     llvm::Constant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
 
     elem* e = new elem;
 
-    if (type->ty == Tarray) {
+    if (dtype->ty == Tarray) {
         llvm::Constant* clen = llvm::ConstantInt::get(LLVM_DtoSize_t(),len,false);
-        if (p->lvals.empty()) {
+        if (p->lvals.empty() || !p->toplval()) {
             e->type = elem::SLICE;
             e->arg = clen;
             e->mem = arrptr;
             return e;
         }
-        else {
-            llvm::Value* arr = p->toplval();
+        else if (llvm::Value* arr = p->toplval()) {
             if (llvm::isa<llvm::GlobalVariable>(arr)) {
                 e->val = LLVM_DtoConstantSlice(clen, arrptr);
             }
@@ -300,12 +354,14 @@
                 e->inplace = true;
             }
         }
+        else
+        assert(0);
     }
-    else if (type->ty == Tsarray) {
+    else if (dtype->ty == Tsarray) {
         const llvm::Type* dstType = llvm::PointerType::get(llvm::ArrayType::get(ct, len));
         e->mem = new llvm::BitCastInst(gvar, dstType, "tmp", gIR->scopebb());
     }
-    else if (type->ty == Tpointer) {
+    else if (dtype->ty == Tpointer) {
         e->mem = arrptr;
     }
     else {
@@ -319,6 +375,42 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+llvm::Constant* StringExp::toConstElem(IRState* p)
+{
+    Logger::print("StringExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    uint8_t* str = (uint8_t*)string;
+    std::string cont((char*)str, len);
+
+    Type* t = LLVM_DtoDType(type);
+
+    llvm::Constant* _init = llvm::ConstantArray::get(cont,true);
+    if (t->ty == Tsarray) {
+        return _init;
+    }
+    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,"stringliteral",gIR->module);
+
+    llvm::ConstantInt* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+    llvm::Constant* idxs[2] = { zero, zero };
+    llvm::Constant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
+
+    if (t->ty == Tpointer) {
+        return arrptr;
+    }
+
+    if (t->ty == Tarray) {
+        llvm::Constant* clen = llvm::ConstantInt::get(LLVM_DtoSize_t(),len,false);
+        return LLVM_DtoConstantSlice(clen, arrptr);
+    }
+
+    assert(0);
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 elem* AssignExp::toElem(IRState* p)
 {
     Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type->toChars());
@@ -353,30 +445,33 @@
     }
     //e->val = l->store(r->getValue());
 
-    TY e1ty = e1->type->ty;
-    TY e2ty = e2->type->ty;
+    Type* e1type = LLVM_DtoDType(e1->type);
+    Type* e2type = LLVM_DtoDType(e2->type);
+    TY e1ty = e1type->ty;
+    TY e2ty = e2type->ty;
 
     elem* e = new elem;
+    e->type = elem::VAR;
 
     // struct
     if (e1ty == Tstruct) {
+        e->mem = l->mem;
         // struct + struct
         if (e2ty == Tstruct) {
             // struct literals do the assignment themselvs (in place)
             if (!r->inplace) {
-                TypeStruct* ts = (TypeStruct*)e2->type;
-                assert(r->mem);
-                LLVM_DtoStructCopy(ts,l->mem,r->mem);
+                TypeStruct* ts = (TypeStruct*)e2type;
+                LLVM_DtoStructCopy(ts,l->mem,r->getValue());
             }
             else {
                 e->inplace = true;
             }
         }
         // struct + const int
-        else if (e2->type->isintegral()){
+        else if (e2type->isintegral()){
             IntegerExp* iexp = (IntegerExp*)e2;
             assert(iexp->value == 0 && "Only integral struct initializer allowed is zero");
-            TypeStruct* st = (TypeStruct*)e1->type;
+            TypeStruct* st = (TypeStruct*)e1type;
             LLVM_DtoStructZeroInit(st, l->mem);
         }
         // :x
@@ -384,10 +479,10 @@
         assert(0 && "struct = unknown");
     }
     else if (e1ty == Tsarray) {
-        assert(0 && "static array = not supported");
+        assert(0 && "static array not supported");
     }
     else if (e1ty == Tarray) {
-        if (e2->type->isscalar() || e2->type->ty == Tclass){
+        if (e2type->isscalar() || e2type->ty == Tclass){
             LLVM_DtoArrayInit(l->mem, r->getValue());
         }
         else if (e2ty == Tarray) {
@@ -396,16 +491,24 @@
                 llvm::Constant* c = llvm::cast<llvm::Constant>(r->val);
                 assert(c->isNullValue());
                 LLVM_DtoNullArray(l->mem);
+                e->mem = l->mem;
             }
             else if (r->type == elem::SLICE) {
-                if (l->type == elem::SLICE)
-                LLVM_DtoArrayCopy(l,r);
-                else
-                LLVM_DtoSetArray(l->mem,r->arg,r->mem);
+                if (l->type == elem::SLICE) {
+                    LLVM_DtoArrayCopy(l,r);
+                    e->type = elem::SLICE;
+                    e->mem = l->mem;
+                    e->arg = l->arg;
+                }
+                else {
+                    LLVM_DtoSetArray(l->mem,r->arg,r->mem);
+                    e->mem = l->mem;
+                }
             }
             else {
                 // new expressions write directly to the array reference
                 // so do string literals
+                e->mem = l->mem;
                 if (!r->inplace) {
                     assert(r->mem);
                     LLVM_DtoArrayAssign(l->mem, r->mem);
@@ -419,6 +522,7 @@
         assert(0);
     }
     else if (e1ty == Tpointer) {
+        e->mem = l->mem;
         if (e2ty == Tpointer) {
             llvm::Value* v = r->field ? r->mem : r->getValue();
             Logger::cout() << "*=*: " << *v << ", " << *l->mem << '\n';
@@ -433,15 +537,17 @@
             Logger::cout() << "tmp: " << *tmp << " ||| " << *l->mem << '\n';
             // assignment to this in constructor special case
             if (l->isthis) {
-                FuncDeclaration* fdecl = p->funcdecls.back();
+                FuncDeclaration* fdecl = p->func().decl;
                 // respecify the this param
                 if (!llvm::isa<llvm::AllocaInst>(fdecl->llvmThisVar))
                     fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", p->topallocapoint());
                 new llvm::StoreInst(tmp, fdecl->llvmThisVar, p->scopebb());
+                e->mem = fdecl->llvmThisVar;
             }
             // regular class ref -> class ref assignment
             else {
                 new llvm::StoreInst(tmp, l->mem, p->scopebb());
+                e->mem = l->mem;
             }
         }
         else
@@ -454,6 +560,7 @@
                 llvm::Constant* c = llvm::cast<llvm::Constant>(r->val);
                 if (c->isNullValue()) {
                     LLVM_DtoNullDelegate(l->mem);
+                    e->mem = l->mem;
                 }
                 else
                 assert(0);
@@ -461,6 +568,7 @@
             else if (r->inplace) {
                 // do nothing
                 e->inplace = true;
+                e->mem = l->mem;
             }
             else
             assert(0);
@@ -472,10 +580,12 @@
     else {
         Logger::cout() << *l->mem << '\n';
         new llvm::StoreInst(r->getValue(),l->mem,p->scopebb());
+        e->mem = l->mem;
     }
 
     delete r;
     delete l;
+
     return e;
 }
 
@@ -489,15 +599,19 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
-    if (e1->type != e2->type) {
-        if (e1->type->ty == Tpointer && e1->type->next->ty == Tstruct) {
+    Type* t = LLVM_DtoDType(type);
+    Type* e1type = LLVM_DtoDType(e1->type);
+    Type* e2type = LLVM_DtoDType(e2->type);
+
+    if (e1type != e2type) {
+        if (e1type->ty == Tpointer && e1type->next->ty == Tstruct) {
             //assert(l->field);
             assert(r->type == elem::CONST);
             llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->val);
 
-            TypeStruct* ts = (TypeStruct*)e1->type->next;
+            TypeStruct* ts = (TypeStruct*)e1type->next;
             std::vector<unsigned> offsets(1,0);
-            ts->sym->offsetToIndex(type->next, cofs->getZExtValue(), offsets);
+            ts->sym->offsetToIndex(t->next, cofs->getZExtValue(), offsets);
             e->mem = LLVM_DtoGEP(l->getValue(), offsets, "tmp", p->scopebb());
             e->type = elem::VAR;
             e->field = true;
@@ -529,9 +643,11 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
+    Type* e1type = LLVM_DtoDType(e1->type);
+
     elem* e = new elem;
     llvm::Value* val = 0;
-    if (e1->type->ty == Tpointer) {
+    if (e1type->ty == Tpointer) {
         val = e->mem = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb());
     }
     else {
@@ -598,8 +714,10 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
+    Type* e1type = LLVM_DtoDType(e1->type);
+
     llvm::Value* tmp = 0;
-    if (e1->type->ty == Tpointer) {
+    if (e1type->ty == Tpointer) {
         tmp = r->getValue();
         llvm::Value* zero = llvm::ConstantInt::get(tmp->getType(),0,false);
         tmp = llvm::BinaryOperator::createSub(zero,tmp,"tmp",p->scopebb());
@@ -690,11 +808,13 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
-    if (type->isunsigned())
+    Type* t = LLVM_DtoDType(type);
+
+    if (t->isunsigned())
         e->val = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isintegral())
+    else if (t->isintegral())
         e->val = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isfloating())
+    else if (t->isfloating())
         e->val = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
     else
         assert(0);
@@ -714,12 +834,14 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
+    Type* t = LLVM_DtoDType(type);
+
     llvm::Value* tmp;
-    if (type->isunsigned())
+    if (t->isunsigned())
         tmp = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isintegral())
+    else if (t->isintegral())
         tmp = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isfloating())
+    else if (t->isfloating())
         tmp = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
     else
         assert(0);
@@ -753,11 +875,13 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
-    if (type->isunsigned())
+    Type* t = LLVM_DtoDType(type);
+
+    if (t->isunsigned())
         e->val = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isintegral())
+    else if (t->isintegral())
         e->val = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isfloating())
+    else if (t->isfloating())
         e->val = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
     else
         assert(0);
@@ -777,12 +901,14 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
+    Type* t = LLVM_DtoDType(type);
+
     llvm::Value* tmp;
-    if (type->isunsigned())
+    if (t->isunsigned())
         tmp = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isintegral())
+    else if (t->isintegral())
         tmp = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isfloating())
+    else if (t->isfloating())
         tmp = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
     else
         assert(0);
@@ -825,9 +951,11 @@
 
     TypeFunction* tf = 0;
 
+    Type* e1type = LLVM_DtoDType(e1->type);
+
     // regular functions
-    if (e1->type->ty == Tfunction) {
-        tf = (TypeFunction*)e1->type;
+    if (e1type->ty == Tfunction) {
+        tf = (TypeFunction*)e1type;
         if (tf->llvmRetInPtr) {
             retinptr = true;
         }
@@ -835,10 +963,10 @@
     }
 
     // delegates
-    else if (e1->type->ty == Tdelegate) {
-        Logger::println("delegateTy = %s\n", e1->type->toChars());
-        assert(e1->type->next->ty == Tfunction);
-        tf = (TypeFunction*)e1->type->next;
+    else if (e1type->ty == Tdelegate) {
+        Logger::println("delegateTy = %s\n", e1type->toChars());
+        assert(e1type->next->ty == Tfunction);
+        tf = (TypeFunction*)e1type->next;
         if (tf->llvmRetInPtr) {
             retinptr = true;
         }
@@ -899,13 +1027,12 @@
     llvm::FunctionType::param_iterator argiter = llfnty->param_begin();
     int j = 0;
 
-    // hidden struct return parameter
+    // hidden struct return arguments
     if (retinptr) {
         if (!p->lvals.empty()) {
             assert(llvm::isa<llvm::StructType>(p->toplval()->getType()->getContainedType(0)));
             llargs[j] = p->toplval();
-            TY Dty = tf->next->ty;
-            if (Dty == Tstruct || Dty == Tdelegate || Dty == Tarray) {
+            if (LLVM_DtoIsPassedByRef(tf->next)) {
                 e->inplace = true;
             }
             else
@@ -922,7 +1049,7 @@
         e->type = elem::VAL;
     }
 
-    // this parameter
+    // this arguments
     if (fn->arg) {
         Logger::println("This Call");
         if (fn->arg->getType() != argiter->get()) {
@@ -935,7 +1062,7 @@
         ++j;
         ++argiter;
     }
-    // delegate context parameter
+    // delegate context arguments
     else if (delegateCall) {
         Logger::println("Delegate Call");
         llvm::Value* contextptr = LLVM_DtoGEP(fn->mem,zero,zero,"tmp",p->scopebb());
@@ -944,75 +1071,11 @@
         ++argiter;
     }
 
-    // regular parameters
+    // regular arguments
     for (int i=0; i<arguments->dim; i++,j++)
     {
-        Expression* argexp = (Expression*)arguments->data[i];
-        elem* arg = argexp->toElem(p);
-        if (arg->inplace) {
-            assert(arg->mem);
-            llargs[j] = arg->mem;
-            continue;
-        }
-
         Argument* fnarg = Argument::getNth(tf->parameters, i);
-
-        TY argty = argexp->type->ty;
-        if (argty == Tstruct || argty == Tdelegate || argty == Tarray) {
-            if (!fnarg || !fnarg->llvmCopy) {
-                llargs[j] = arg->getValue();
-                assert(llargs[j] != 0);
-            }
-            else {
-                llvm::Value* allocaInst = 0;
-                llvm::BasicBlock* entryblock = &p->topfunc()->front();
-                const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(arg->mem->getType());
-                if (argty == Tstruct) {
-                    allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", p->topallocapoint());
-                    TypeStruct* ts = (TypeStruct*)argexp->type;
-                    LLVM_DtoStructCopy(ts,allocaInst,arg->mem);
-                }
-                else if (argty == Tdelegate) {
-                    allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", p->topallocapoint());
-                    LLVM_DtoDelegateCopy(allocaInst,arg->mem);
-                }
-                else if (argty == Tarray) {
-                    if (arg->type == elem::SLICE) {
-                        allocaInst = new llvm::AllocaInst(LLVM_DtoType(argexp->type), "tmpparam", p->topallocapoint());
-                        LLVM_DtoSetArray(allocaInst, arg->arg, arg->mem);
-                    }
-                    else {
-                        allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", p->topallocapoint());
-                        LLVM_DtoArrayAssign(allocaInst,arg->mem);
-                    }
-                }
-                else
-                assert(0);
-
-                llargs[j] = allocaInst;
-                assert(llargs[j] != 0);
-            }
-        }
-        else if (!fnarg || fnarg->llvmCopy) {
-            Logger::println("regular arg");
-            assert(arg->type != elem::SLICE);
-            llargs[j] = arg->arg ? arg->arg : arg->getValue();
-            assert(llargs[j] != 0);
-        }
-        else {
-            Logger::println("as ptr arg");
-            llargs[j] = arg->mem ? arg->mem : arg->val;
-            if (llargs[j]->getType() != llfnty->getParamType(j))
-            {
-                assert(llargs[j]->getType() == llfnty->getParamType(j)->getContainedType(0));
-                LLVM_DtoGiveArgumentStorage(arg);
-                new llvm::StoreInst(llargs[j], arg->mem, p->scopebb());
-                llargs[j] = arg->mem;
-            }
-            assert(llargs[j] != 0);
-        }
-
-        delete arg;
+        llargs[j] = LLVM_DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]);
     }
 
     // void returns cannot not be named
@@ -1053,37 +1116,38 @@
     LOG_SCOPE;
     elem* e = new elem;
     elem* u = e1->toElem(p);
-    const llvm::Type* totype = LLVM_DtoType(to);
-    Type* from = e1->type;
-    int lsz = from->size();
-    int rsz = to->size();
+    const llvm::Type* tolltype = LLVM_DtoType(to);
+    Type* fromtype = LLVM_DtoDType(e1->type);
+    Type* totype = LLVM_DtoDType(to);
+    int lsz = fromtype->size();
+    int rsz = totype->size();
 
     // this makes sure the strange lvalue casts don't screw things up
     e->mem = u->mem;
 
-    if (from->isintegral()) {
-        if (to->isintegral()) {
+    if (fromtype->isintegral()) {
+        if (totype->isintegral()) {
             if (lsz < rsz) {
-                Logger::cout() << *totype << '\n';
-                if (from->isunsigned() || from->ty == Tbool) {
-                    e->val = new llvm::ZExtInst(u->getValue(), totype, "tmp", p->scopebb());
+                Logger::cout() << *tolltype << '\n';
+                if (fromtype->isunsigned() || fromtype->ty == Tbool) {
+                    e->val = new llvm::ZExtInst(u->getValue(), tolltype, "tmp", p->scopebb());
                 } else {
-                    e->val = new llvm::SExtInst(u->getValue(), totype, "tmp", p->scopebb());
+                    e->val = new llvm::SExtInst(u->getValue(), tolltype, "tmp", p->scopebb());
                 }
             }
             else if (lsz > rsz) {
-                e->val = new llvm::TruncInst(u->getValue(), totype, "tmp", p->scopebb());
+                e->val = new llvm::TruncInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
             else {
-                e->val = new llvm::BitCastInst(u->getValue(), totype, "tmp", p->scopebb());
+                e->val = new llvm::BitCastInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
         }
-        else if (to->isfloating()) {
-            if (from->isunsigned()) {
-                e->val = new llvm::UIToFPInst(u->getValue(), totype, "tmp", p->scopebb());
+        else if (totype->isfloating()) {
+            if (fromtype->isunsigned()) {
+                e->val = new llvm::UIToFPInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
             else {
-                e->val = new llvm::SIToFPInst(u->getValue(), totype, "tmp", p->scopebb());
+                e->val = new llvm::SIToFPInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
         }
         else {
@@ -1092,27 +1156,27 @@
         //e->storeVal = u->storeVal ? u->storeVal : u->val;
         e->type = elem::VAL;
     }
-    else if (from->isfloating()) {
-        if (to->isfloating()) {
-            if ((from->ty == Tfloat80 || from->ty == Tfloat64) && (to->ty == Tfloat80 || to->ty == Tfloat64)) {
+    else if (fromtype->isfloating()) {
+        if (totype->isfloating()) {
+            if ((fromtype->ty == Tfloat80 || fromtype->ty == Tfloat64) && (totype->ty == Tfloat80 || totype->ty == Tfloat64)) {
                 e->val = u->getValue();
             }
             else if (lsz < rsz) {
-                e->val = new llvm::FPExtInst(u->getValue(), totype, "tmp", p->scopebb());
+                e->val = new llvm::FPExtInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
             else if (lsz > rsz) {
-                e->val = new llvm::FPTruncInst(u->getValue(), totype, "tmp", p->scopebb());
+                e->val = new llvm::FPTruncInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
             else {
                 assert(0);
             }
         }
-        else if (to->isintegral()) {
-            if (to->isunsigned()) {
-                e->val = new llvm::FPToUIInst(u->getValue(), totype, "tmp", p->scopebb());
+        else if (totype->isintegral()) {
+            if (totype->isunsigned()) {
+                e->val = new llvm::FPToUIInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
             else {
-                e->val = new llvm::FPToSIInst(u->getValue(), totype, "tmp", p->scopebb());
+                e->val = new llvm::FPToSIInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
         }
         else {
@@ -1120,26 +1184,26 @@
         }
         e->type = elem::VAL;
     }
-    else if (from->ty == Tclass) {
+    else if (fromtype->ty == Tclass) {
         //assert(to->ty == Tclass);
-        e->val = new llvm::BitCastInst(u->getValue(), totype, "tmp", p->scopebb());
+        e->val = new llvm::BitCastInst(u->getValue(), tolltype, "tmp", p->scopebb());
         e->type = elem::VAL;
     }
-    else if (from->ty == Tarray || from->ty == Tsarray) {
+    else if (fromtype->ty == Tarray || fromtype->ty == Tsarray) {
         Logger::cout() << "from array or sarray" << '\n';
-        if (to->ty == Tpointer) {
+        if (totype->ty == Tpointer) {
             Logger::cout() << "to pointer" << '\n';
-            assert(from->next == to->next);
+            assert(fromtype->next == totype->next);
             llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
             llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
             llvm::Value* ptr = LLVM_DtoGEP(u->getValue(),zero,one,"tmp",p->scopebb());
             e->val = new llvm::LoadInst(ptr, "tmp", p->scopebb());
             e->type = elem::VAL;
         }
-        else if (to->ty == Tarray) {
+        else if (totype->ty == Tarray) {
             Logger::cout() << "to array" << '\n';
-            assert(from->next->size() == to->next->size());
-            const llvm::Type* ptrty = LLVM_DtoType(to->next);
+            assert(fromtype->next->size() == totype->next->size());
+            const llvm::Type* ptrty = LLVM_DtoType(totype->next);
             if (ptrty == llvm::Type::VoidTy)
                 ptrty = llvm::Type::Int8Ty;
             ptrty = llvm::PointerType::get(ptrty);
@@ -1150,7 +1214,7 @@
             }
             else {
                 llvm::Value* uval = u->getValue();
-                if (from->ty == Tsarray) {
+                if (fromtype->ty == Tsarray) {
                     Logger::cout() << "uvalTy = " << *uval->getType() << '\n';
                     assert(llvm::isa<llvm::PointerType>(uval->getType()));
                     const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(uval->getType()->getContainedType(0));
@@ -1171,7 +1235,7 @@
             }
             e->type = elem::SLICE;
         }
-        else if (to->ty == Tsarray) {
+        else if (totype->ty == Tsarray) {
             Logger::cout() << "to sarray" << '\n';
             assert(0);
         }
@@ -1179,14 +1243,14 @@
             assert(0);
         }
     }
-    else if (from->ty == Tpointer) {
-        if (to->ty == Tpointer || to->ty == Tclass) {
+    else if (fromtype->ty == Tpointer) {
+        if (totype->ty == Tpointer || totype->ty == Tclass) {
             llvm::Value* src = u->getValue();
             //Logger::cout() << *src << '|' << *totype << '\n';
-            e->val = new llvm::BitCastInst(src, totype, "tmp", p->scopebb());
+            e->val = new llvm::BitCastInst(src, tolltype, "tmp", p->scopebb());
         }
-        else if (to->isintegral()) {
-            e->val = new llvm::PtrToIntInst(u->getValue(), totype, "tmp", p->scopebb());
+        else if (totype->isintegral()) {
+            e->val = new llvm::PtrToIntInst(u->getValue(), tolltype, "tmp", p->scopebb());
         }
         else
         assert(0);
@@ -1210,18 +1274,20 @@
     {
         Logger::println("VarDeclaration");
         assert(vd->llvmValue);
-        if (vd->type->ty == Tstruct && !(type->ty == Tpointer && type->next == vd->type)) {
-            TypeStruct* vdt = (TypeStruct*)vd->type;
+        Type* t = LLVM_DtoDType(type);
+        Type* vdtype = LLVM_DtoDType(vd->type);
+        if (vdtype->ty == Tstruct && !(t->ty == Tpointer && t->next == vdtype)) {
+            TypeStruct* vdt = (TypeStruct*)vdtype;
             e = new elem;
             std::vector<unsigned> dst(1,0);
-            vdt->sym->offsetToIndex(type->next, offset, dst);
+            vdt->sym->offsetToIndex(t->next, offset, dst);
             llvm::Value* ptr = vd->llvmValue;
             assert(ptr);
             e->mem = LLVM_DtoGEP(ptr,dst,"tmp",p->scopebb());
             e->type = elem::VAL;
             e->field = true;
         }
-        else if (vd->type->ty == Tsarray) {
+        else if (vdtype->ty == Tsarray) {
             /*e = new elem;
             llvm::Value* idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
             e->val = new llvm::GetElementPtrInst(vd->llvmValue,idx0,idx0,"tmp",p->scopebb());*/
@@ -1294,26 +1360,30 @@
 
     elem* l = e1->toElem(p);
 
-    Logger::print("e1->type=%s\n", e1->type->toChars());
+    Type* t = LLVM_DtoDType(type);
+    Type* e1type = LLVM_DtoDType(e1->type);
+
+    Logger::print("e1->type=%s\n", e1type->toChars());
 
     if (VarDeclaration* vd = var->isVarDeclaration()) {
         std::vector<unsigned> vdoffsets(1,0);
         llvm::Value* src = 0;
-        if (e1->type->ty == Tpointer) {
-            assert(e1->type->next->ty == Tstruct);
-            TypeStruct* ts = (TypeStruct*)e1->type->next;
+        if (e1type->ty == Tpointer) {
+            assert(e1type->next->ty == Tstruct);
+            TypeStruct* ts = (TypeStruct*)e1type->next;
             ts->sym->offsetToIndex(vd->type, vd->offset, vdoffsets);
             Logger::println("Struct member offset:%d", vd->offset);
             src = l->val ? l->val : l->mem;
         }
         else if (e1->type->ty == Tclass) {
-            TypeClass* tc = (TypeClass*)e1->type;
+            TypeClass* tc = (TypeClass*)e1type;
             Logger::println("Class member offset: %d", vd->offset);
             tc->sym->offsetToIndex(vd->type, vd->offset, vdoffsets);
             src = l->getValue();
         }
         assert(vdoffsets.size() != 1);
         assert(src != 0);
+        Logger::cout() << "src: " << *src << '\n';
         llvm::Value* arrptr = LLVM_DtoGEP(src,vdoffsets,"tmp",p->scopebb());
         e->mem = arrptr;
         Logger::cout() << "mem: " << *e->mem << '\n';
@@ -1332,7 +1402,7 @@
         // virtual call
         if (fdecl->isVirtual()) {
             assert(fdecl->vtblIndex > 0);
-            assert(e1->type->ty == Tclass);
+            assert(e1type->ty == Tclass);
 
             llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
             llvm::Value* vtblidx = llvm::ConstantInt::get(llvm::Type::Int32Ty, (size_t)fdecl->vtblIndex, false);
@@ -1365,22 +1435,7 @@
     elem* e = new elem;
 
     if (VarDeclaration* vd = var->isVarDeclaration()) {
-        /*assert(vd->llvmValue == 0);
-
-        llvm::Function* fn = p->topfunc();
-        assert(fn);
-
-        TypeFunction* tf = p->topfunctype();
-        assert(tf);
-
-        llvm::Value* v = 0;
-        if (tf->llvmRetInPtr)
-        v = ++fn->arg_begin();
-        else
-        v = fn->arg_begin();
-        assert(v);*/
-
-        llvm::Value* v = p->funcdecls.back()->llvmThisVar;
+        llvm::Value* v = p->func().decl->llvmThisVar;
         if (llvm::isa<llvm::AllocaInst>(v))
             v = new llvm::LoadInst(v, "tmp", p->scopebb());
         e->mem = v;
@@ -1440,15 +1495,22 @@
 
         Expression* vx = (Expression*)elements->data[i];
         if (vx != 0) {
+            p->lvals.push_back(arrptr);
             elem* ve = vx->toElem(p);
-            llvm::Value* val = ve->getValue();
-            Logger::cout() << *val << " | " << *arrptr << '\n';
-            if (vx->type->ty == Tstruct) {
-                TypeStruct* ts = (TypeStruct*)vx->type;
-                LLVM_DtoStructCopy(ts,arrptr,val);
+            p->lvals.pop_back();
+
+            if (!ve->inplace) {
+                llvm::Value* val = ve->getValue();
+                Logger::cout() << *val << " | " << *arrptr << '\n';
+
+                Type* vxtype = LLVM_DtoDType(vx->type);
+                if (vxtype->ty == Tstruct) {
+                    TypeStruct* ts = (TypeStruct*)vxtype;
+                    LLVM_DtoStructCopy(ts,arrptr,val);
+                }
+                else
+                    new llvm::StoreInst(val, arrptr, p->scopebb());
             }
-            else
-                new llvm::StoreInst(val, arrptr, p->scopebb());
             delete ve;
         }
         else {
@@ -1463,6 +1525,28 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+llvm::Constant* StructLiteralExp::toConstElem(IRState* p)
+{
+    Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    unsigned n = elements->dim;
+    std::vector<llvm::Constant*> vals(n, NULL);
+
+    for (unsigned i=0; i<n; ++i)
+    {
+        Expression* vx = (Expression*)elements->data[i];
+        vals[i] = vx->toConstElem(p);
+    }
+
+    assert(LLVM_DtoDType(type)->ty == Tstruct);
+    const llvm::Type* t = LLVM_DtoType(type);
+    const llvm::StructType* st = llvm::cast<llvm::StructType>(t);
+    return llvm::ConstantStruct::get(st,vals);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 elem* IndexExp::toElem(IRState* p)
 {
     Logger::print("IndexExp::toElem: %s | %s\n", toChars(), type->toChars());
@@ -1472,6 +1556,8 @@
 
     elem* l = e1->toElem(p);
 
+    Type* e1type = LLVM_DtoDType(e1->type);
+
     p->arrays.push_back(l->mem); // if $ is used it must be an array so this is fine.
     elem* r = e2->toElem(p);
     p->arrays.pop_back();
@@ -1480,13 +1566,13 @@
     llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
 
     llvm::Value* arrptr = 0;
-    if (e1->type->ty == Tpointer) {
+    if (e1type->ty == Tpointer) {
         arrptr = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb());
     }
-    else if (e1->type->ty == Tsarray) {
-        arrptr = LLVM_DtoGEP(l->mem, zero, r->getValue(),"tmp",p->scopebb());
+    else if (e1type->ty == Tsarray) {
+        arrptr = LLVM_DtoGEP(l->getValue(), zero, r->getValue(),"tmp",p->scopebb());
     }
-    else if (e1->type->ty == Tarray) {
+    else if (e1type->ty == Tarray) {
         arrptr = LLVM_DtoGEP(l->mem,zero,one,"tmp",p->scopebb());
         arrptr = new llvm::LoadInst(arrptr,"tmp",p->scopebb());
         arrptr = new llvm::GetElementPtrInst(arrptr,r->getValue(),"tmp",p->scopebb());
@@ -1510,6 +1596,7 @@
     LOG_SCOPE;
 
     elem* v = e1->toElem(p);
+    Type* e1type = LLVM_DtoDType(e1->type);
 
     elem* e = new elem;
     assert(v->mem);
@@ -1531,13 +1618,16 @@
             assert(lo->val);
             assert(llvm::isa<llvm::ConstantInt>(lo->val));
 
-            if (e1->type->ty == Tpointer) {
+            if (e1type->ty == Tpointer) {
                 e->mem = v->getValue();
             }
-            else if (e1->type->ty == Tarray) {
+            else if (e1type->ty == Tarray) {
                 llvm::Value* tmp = LLVM_DtoGEP(v->mem,zero,one,"tmp",p->scopebb());
                 e->mem = new llvm::LoadInst(tmp,"tmp",p->scopebb());
             }
+            else if (e1type->ty == Tsarray) {
+                e->mem = LLVM_DtoGEP(v->mem,zero,zero,"tmp",p->scopebb());
+            }
             else
             assert(e->mem);
 
@@ -1548,9 +1638,16 @@
         }
         else
         {
-            llvm::Value* tmp = LLVM_DtoGEP(v->mem,zero,one,"tmp",p->scopebb());
-            tmp = new llvm::LoadInst(tmp,"tmp",p->scopebb());
-            e->mem = new llvm::GetElementPtrInst(tmp,lo->getValue(),"tmp",p->scopebb());
+            if (e1type->ty == Tarray) {
+                llvm::Value* tmp = LLVM_DtoGEP(v->mem,zero,one,"tmp",p->scopebb());
+                tmp = new llvm::LoadInst(tmp,"tmp",p->scopebb());
+                e->mem = new llvm::GetElementPtrInst(tmp,lo->getValue(),"tmp",p->scopebb());
+            }
+            else if (e1type->ty == Tsarray) {
+                e->mem = LLVM_DtoGEP(v->mem,zero,lo->getValue(),"tmp",p->scopebb());
+            }
+            else
+            assert(0);
         }
 
         elem* up = upr->toElem(p);
@@ -1610,31 +1707,54 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
-    assert(e1->type == e2->type);
-
-    Type* t = e1->type;
+    Type* t = LLVM_DtoDType(e1->type);
+    Type* e2t = LLVM_DtoDType(e2->type);
+    assert(t == e2t);
 
     if (t->isintegral())
     {
         llvm::ICmpInst::Predicate cmpop;
+        bool skip = false;
         switch(op)
         {
         case TOKlt:
+        case TOKul:
             cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_ULT : llvm::ICmpInst::ICMP_SLT;
             break;
         case TOKle:
+        case TOKule:
             cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_ULE : llvm::ICmpInst::ICMP_SLE;
             break;
         case TOKgt:
+        case TOKug:
             cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_UGT : llvm::ICmpInst::ICMP_SGT;
             break;
         case TOKge:
+        case TOKuge:
             cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_UGE : llvm::ICmpInst::ICMP_SGE;
             break;
+        case TOKue:
+            cmpop = llvm::ICmpInst::ICMP_EQ;
+            break;
+        case TOKlg:
+            cmpop = llvm::ICmpInst::ICMP_NE;
+            break;
+        case TOKleg:
+            skip = true;
+            e->val = llvm::ConstantInt::getTrue();
+            break;
+        case TOKunord:
+            skip = true;
+            e->val = llvm::ConstantInt::getFalse();
+            break;
+
         default:
             assert(0);
         }
-        e->val = new llvm::ICmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb());
+        if (!skip)
+        {
+            e->val = new llvm::ICmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb());
+        }
     }
     else if (t->isfloating())
     {
@@ -1696,9 +1816,9 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
-    assert(e1->type == e2->type);
-
-    Type* t = e1->type;
+    Type* t = LLVM_DtoDType(e1->type);
+    Type* e2t = LLVM_DtoDType(e2->type);
+    assert(t == e2t);
 
     if (t->isintegral() || t->ty == Tpointer)
     {
@@ -1732,10 +1852,13 @@
         }
         e->val = new llvm::FCmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb());
     }
+    else if (t->ty == Tsarray)
+    {
+        e->val = LLVM_DtoStaticArrayCompare(op,l->mem,r->mem);
+    }
     else if (t->ty == Tarray)
     {
-        // array comparison invokes the typeinfo runtime
-        assert(0);
+        assert(0 && "array comparison invokes the typeinfo runtime");
     }
     else
     {
@@ -1768,10 +1891,13 @@
     llvm::Value* val = e->val;
     llvm::Value* post = 0;
 
-    if (e1->type->isintegral())
+    Type* e1type = LLVM_DtoDType(e1->type);
+    Type* e2type = LLVM_DtoDType(e2->type);
+
+    if (e1type->isintegral())
     {
-        assert(e2->type->isintegral());
-        llvm::Value* one = llvm::ConstantInt::get(val->getType(), 1, !e2->type->isunsigned());
+        assert(e2type->isintegral());
+        llvm::Value* one = llvm::ConstantInt::get(val->getType(), 1, !e2type->isunsigned());
         if (op == TOKplusplus) {
             post = llvm::BinaryOperator::createAdd(val,one,"tmp",p->scopebb());
         }
@@ -1779,17 +1905,17 @@
             post = llvm::BinaryOperator::createSub(val,one,"tmp",p->scopebb());
         }
     }
-    else if (e1->type->ty == Tpointer)
+    else if (e1type->ty == Tpointer)
     {
-        assert(e2->type->isintegral());
+        assert(e2type->isintegral());
         llvm::Constant* minusone = llvm::ConstantInt::get(LLVM_DtoSize_t(),(uint64_t)-1,true);
         llvm::Constant* plusone = llvm::ConstantInt::get(LLVM_DtoSize_t(),(uint64_t)1,false);
         llvm::Constant* whichone = (op == TOKplusplus) ? plusone : minusone;
         post = new llvm::GetElementPtrInst(val, whichone, "tmp", p->scopebb());
     }
-    else if (e1->type->isfloating())
+    else if (e1type->isfloating())
     {
-        assert(e2->type->isfloating());
+        assert(e2type->isfloating());
         llvm::Value* one = llvm::ConstantFP::get(val->getType(), 1.0f);
         if (op == TOKplusplus) {
             post = llvm::BinaryOperator::createAdd(val,one,"tmp",p->scopebb());
@@ -1820,28 +1946,28 @@
     assert(!thisexp);
     assert(!newargs);
     assert(newtype);
-    //assert(!arguments);
-    //assert(!member);
     assert(!allocator);
 
     elem* e = new elem;
 
-    const llvm::Type* t = LLVM_DtoType(newtype);
+    Type* ntype = LLVM_DtoDType(newtype);
+
+    const llvm::Type* t = LLVM_DtoType(ntype);
 
     if (onstack) {
-        assert(newtype->ty == Tclass);
+        assert(ntype->ty == Tclass);
         e->mem = new llvm::AllocaInst(t->getContainedType(0),"tmp",p->topallocapoint());
     }
     else {
-        if (newtype->ty == Tclass) {
+        if (ntype->ty == Tclass) {
             e->mem = new llvm::MallocInst(t->getContainedType(0),"tmp",p->scopebb());
         }
-        else if (newtype->ty == Tarray) {
+        else if (ntype->ty == Tarray) {
             assert(arguments);
             if (arguments->dim == 1) {
                 elem* sz = ((Expression*)arguments->data[0])->toElem(p);
                 llvm::Value* dimval = sz->getValue();
-                LLVM_DtoNewDynArray(p->toplval(), dimval, newtype->next);
+                LLVM_DtoNewDynArray(p->toplval(), dimval, ntype->next);
                 delete sz;
             }
             else {
@@ -1853,32 +1979,32 @@
         }
     }
 
-    if (newtype->ty == Tclass) {
+    if (ntype->ty == Tclass) {
         // first apply the static initializer
         assert(e->mem);
-        LLVM_DtoInitClass((TypeClass*)newtype, e->mem);
+        LLVM_DtoInitClass((TypeClass*)ntype, e->mem);
 
         // then call constructor
         if (arguments) {
+            assert(member);
+            assert(member->llvmValue);
+            llvm::Function* fn = llvm::cast<llvm::Function>(member->llvmValue);
+            TypeFunction* tf = (TypeFunction*)LLVM_DtoDType(member->type);
+
             std::vector<llvm::Value*> ctorargs;
             ctorargs.push_back(e->mem);
             for (size_t i=0; i<arguments->dim; ++i)
             {
                 Expression* ex = (Expression*)arguments->data[i];
-                Logger::println("arg=%s", ex->toChars());
-                elem* exe = ex->toElem(p);
-                llvm::Value* v = exe->getValue();
-                assert(v);
-                ctorargs.push_back(v);
-                delete exe;
+                Argument* fnarg = Argument::getNth(tf->parameters, i);
+                llvm::Value* a = LLVM_DtoArgument(fn->getFunctionType()->getParamType(i+1), fnarg, ex);
+                ctorargs.push_back(a);
             }
-            assert(member);
-            assert(member->llvmValue);
-            e->mem = new llvm::CallInst(member->llvmValue, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb());
+            e->mem = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb());
         }
     }
-    else if (newtype->ty == Tstruct) {
-        TypeStruct* ts = (TypeStruct*)newtype;
+    else if (ntype->ty == Tstruct) {
+        TypeStruct* ts = (TypeStruct*)ntype;
         if (ts->isZeroInit()) {
             LLVM_DtoStructZeroInit(ts,e->mem);
         }
@@ -1909,7 +2035,9 @@
     const llvm::Type* t = val->getType();
     llvm::Constant* z = llvm::Constant::getNullValue(t);
 
-    if (e1->type->ty == Tpointer) {
+    Type* e1type = LLVM_DtoDType(e1->type);
+
+    if (e1type->ty == Tpointer) {
         ldval = v->getValue();
         new llvm::FreeInst(ldval, p->scopebb());
 
@@ -1917,8 +2045,8 @@
         Logger::cout() << *val << '\n';
         new llvm::StoreInst(z, v->mem, p->scopebb());
     }
-    else if (e1->type->ty == Tclass) {
-        TypeClass* tc = (TypeClass*)e1->type;
+    else if (e1type->ty == Tclass) {
+        TypeClass* tc = (TypeClass*)e1type;
         LLVM_DtoCallClassDtors(tc, val);
 
         if (v->vardecl && !v->vardecl->onstack) {
@@ -1926,7 +2054,7 @@
         }
         new llvm::StoreInst(z, v->mem, p->scopebb());
     }
-    else if (e1->type->ty == Tarray) {
+    else if (e1type->ty == Tarray) {
         // must be on the heap (correct?)
         ldval = v->getValue();
         
@@ -2007,7 +2135,8 @@
     llvm::Value* b = LLVM_DtoBoolean(u->getValue());
 
     llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int1Ty, 0, true);
-    e->val = new llvm::ICmpInst(llvm::ICmpInst::ICMP_EQ,b,zero,"tmp",p->scopebb());
+    e->val = p->ir->CreateICmpEQ(b,zero);
+    //e->val = new llvm::ICmpInst(llvm::ICmpInst::ICMP_EQ,b,zero,"tmp",p->scopebb());
     e->type = elem::VAL;
 
     delete u;
@@ -2151,7 +2280,7 @@
     llvm::Value* loca = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
     LLVM_DtoAssert(llvm::ConstantInt::getFalse(), loca, NULL);
 
-    //new llvm::UnreachableInst(p->scopebb());
+    new llvm::UnreachableInst(p->scopebb());
     return 0;
 }
 
@@ -2305,13 +2434,15 @@
     llvm::Value* val = l->getValue();
     delete l;
 
+    Type* t = LLVM_DtoDType(type);
+
     llvm::Value* zero = 0;
-    if (type->isintegral())
+    if (t->isintegral())
         zero = llvm::ConstantInt::get(val->getType(), 0, true);
-    else if (type->isfloating()) {
-        if (type->ty == Tfloat32)
+    else if (t->isfloating()) {
+        if (t->ty == Tfloat32)
             zero = llvm::ConstantFP::get(val->getType(), float(0));
-        else if (type->ty == Tfloat64 || type->ty == Tfloat80)
+        else if (t->ty == Tfloat64 || t->ty == Tfloat80)
             zero = llvm::ConstantFP::get(val->getType(), double(0));
         else
         assert(0);
@@ -2332,7 +2463,7 @@
     Logger::print("CatExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    assert(0 && "array concatenation is not yet implemented");
+    assert(0 && "array cat is not yet implemented");
 
     elem* lhs = e1->toElem(p);
     elem* rhs = e2->toElem(p);
@@ -2347,6 +2478,93 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+elem* CatAssignExp::toElem(IRState* p)
+{
+    Logger::print("CatAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    elem* l = e1->toElem(p);
+    assert(l->mem);
+
+    Type* e1type = LLVM_DtoDType(e1->type);
+    Type* elemtype = LLVM_DtoDType(e1type->next);
+    Type* e2type = LLVM_DtoDType(e2->type);
+
+    if (e2type == elemtype) {
+        LLVM_DtoCatArrayElement(l->mem,e2);
+    }
+    else
+        assert(0 && "only one element at a time right now");
+
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+elem* ArrayLiteralExp::toElem(IRState* p)
+{
+    Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    const llvm::Type* t = LLVM_DtoType(type);
+    Logger::cout() << "array literal has llvm type: " << *t << '\n';
+
+    llvm::Value* mem = 0;
+    if (p->lvals.empty()) {
+        assert(LLVM_DtoDType(type)->ty == Tsarray);
+        mem = new llvm::AllocaInst(t,"tmparrayliteral",p->topallocapoint());
+    }
+    else {
+        mem = p->toplval();
+        if (!llvm::isa<llvm::PointerType>(mem->getType()) ||
+            !llvm::isa<llvm::ArrayType>(mem->getType()->getContainedType(0)))
+        {
+            error("TODO array literals can currently only be used to initialise static arrays");
+            fatal();
+        }
+    }
+
+    for (unsigned i=0; i<elements->dim; ++i)
+    {
+        Expression* expr = (Expression*)elements->data[i];
+        llvm::Value* elemAddr = LLVM_DtoGEPi(mem,0,i,"tmp",p->scopebb());
+        elem* e = expr->toElem(p);
+        new llvm::StoreInst(e->getValue(), elemAddr, p->scopebb());
+    }
+
+    elem* e = new elem;
+    e->mem = mem;
+    e->type = elem::VAL;
+    e->inplace = true;
+
+    return e;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* ArrayLiteralExp::toConstElem(IRState* p)
+{
+    Logger::print("ArrayLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    const llvm::Type* t = LLVM_DtoType(type);
+    Logger::cout() << "array literal has llvm type: " << *t << '\n';
+    assert(llvm::isa<llvm::ArrayType>(t));
+    const llvm::ArrayType* arrtype = llvm::cast<llvm::ArrayType>(t);
+
+    assert(arrtype->getNumElements() == elements->dim);
+    std::vector<llvm::Constant*> vals(elements->dim, NULL);
+    for (unsigned i=0; i<elements->dim; ++i)
+    {
+        Expression* expr = (Expression*)elements->data[i];
+        vals[i] = expr->toConstElem(p);
+    }
+
+    return llvm::ConstantArray::get(arrtype, vals);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 #define STUB(x) elem *x::toElem(IRState * p) {error("Exp type "#x" not implemented: %s", toChars()); fatal(); return 0; }
 //STUB(IdentityExp);
 //STUB(CondExp);
@@ -2374,7 +2592,7 @@
 //STUB(ModExp);
 //STUB(ModAssignExp);
 //STUB(CatExp);
-STUB(CatAssignExp);
+//STUB(CatAssignExp);
 //STUB(AddExp);
 //STUB(AddAssignExp);
 STUB(Expression);
@@ -2417,10 +2635,21 @@
 //STUB(ArrayLengthExp);
 //STUB(HaltExp);
 STUB(RemoveExp);
-STUB(ArrayLiteralExp);
+//STUB(ArrayLiteralExp);
 STUB(AssocArrayLiteralExp);
 //STUB(StructLiteralExp);
 
+#define CONSTSTUB(x) llvm::Constant* x::toConstElem(IRState * p) {error("const Exp type "#x" not implemented: '%s' type: '%s'", toChars(), type->toChars()); assert(0); fatal(); return NULL; }
+CONSTSTUB(Expression);
+//CONSTSTUB(IntegerExp);
+//CONSTSTUB(RealExp);
+//CONSTSTUB(NullExp);
+//CONSTSTUB(StringExp);
+//CONSTSTUB(VarExp);
+//CONSTSTUB(ArrayLiteralExp);
+CONSTSTUB(AssocArrayLiteralExp);
+//CONSTSTUB(StructLiteralExp);
+
 unsigned Type::totym() { return 0; }
 
 type * Type::toCtype()