changeset 86:fd32135dca3e trunk

[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!! Lots of bugfixes. Added support for special foreach on strings. Added std.array, std.utf, std.ctype and std.uni to phobos. Changed all the .c files in the gen dir to .cpp (it *is* C++ after all)
author lindquist
date Sat, 03 Nov 2007 14:44:58 +0100
parents f869c636a113
children 25d4fcce53f4
files dmd/declaration.h dmd/expression.h dmd/func.c dmd/module.h dmd/statement.c dmd/statement.h gen/arrays.c gen/arrays.cpp gen/arrays.h gen/binops.cpp gen/dwarftypes.c gen/dwarftypes.cpp gen/elem.c gen/elem.cpp gen/elem.h gen/irstate.c gen/irstate.cpp gen/irstate.h gen/logger.c gen/logger.cpp gen/runtime.c gen/runtime.cpp gen/statements.c gen/statements.cpp gen/tocsym.c gen/tocsym.cpp gen/todebug.c gen/todebug.cpp gen/todt.c gen/todt.cpp gen/toir.c gen/toir.cpp gen/tollvm.c gen/tollvm.cpp gen/tollvm.h gen/toobj.c gen/toobj.cpp gen/typinf.c gen/typinf.cpp lphobos/build.sh lphobos/internal/aApply.d lphobos/internal/aApplyR.d lphobos/internal/objectimpl.d lphobos/phobos.d lphobos/std/array.d lphobos/std/ctype.d lphobos/std/uni.d lphobos/std/utf.d premake.lua test/arrays10.d test/arrays7.d test/arrays9.d test/b.d test/bitops.d test/bug48.d test/bug49.d test/bug50.d
diffstat 57 files changed, 12630 insertions(+), 9130 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/declaration.h	Fri Nov 02 06:32:32 2007 +0100
+++ b/dmd/declaration.h	Sat Nov 03 14:44:58 2007 +0100
@@ -527,6 +527,7 @@
     llvm::Value* llvmArguments;
     llvm::Value* llvmArgPtr;
     llvm::Constant* llvmDwarfSubProgram;
+    bool llvmRunTimeHack;
 };
 
 struct FuncAliasDeclaration : FuncDeclaration
--- a/dmd/expression.h	Fri Nov 02 06:32:32 2007 +0100
+++ b/dmd/expression.h	Sat Nov 03 14:44:58 2007 +0100
@@ -56,11 +56,16 @@
 struct IRState;
 struct dt_t;
 
+#if IN_LLVM
+struct DValue;
+typedef DValue elem;
+#else
 #ifdef IN_GCC
 union tree_node; typedef union tree_node elem;
 #else
 struct elem;
 #endif
+#endif
 
 void initPrecedence();
 
--- a/dmd/func.c	Fri Nov 02 06:32:32 2007 +0100
+++ b/dmd/func.c	Sat Nov 03 14:44:58 2007 +0100
@@ -79,6 +79,7 @@
     llvmArguments = NULL;
     llvmArgPtr = NULL;
     llvmDwarfSubProgram = NULL;
+    llvmRunTimeHack = false;
 }
 
 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
--- a/dmd/module.h	Fri Nov 02 06:32:32 2007 +0100
+++ b/dmd/module.h	Sat Nov 03 14:44:58 2007 +0100
@@ -26,11 +26,16 @@
 struct VarDeclaration;
 
 // Back end
-#if IN_GCC
+#if IN_LLVM
+struct DValue;
+typedef DValue elem;
+#else
+#ifdef IN_GCC
 union tree_node; typedef union tree_node elem;
 #else
 struct elem;
 #endif
+#endif
 
 struct Package : ScopeDsymbol
 {
--- a/dmd/statement.c	Fri Nov 02 06:32:32 2007 +0100
+++ b/dmd/statement.c	Sat Nov 03 14:44:58 2007 +0100
@@ -1438,6 +1438,7 @@
 		    fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply2");
 		else
 		    fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply");
+        fdapply->llvmRunTimeHack = true;
 		ec = new VarExp(0, fdapply);
 		Expressions *exps = new Expressions();
 		exps->push(aggr);
@@ -1479,6 +1480,7 @@
 		int j = sprintf(fdname, "_aApply%s%.*s%d", r, 2, fntab[flag], dim);
 		assert(j < sizeof(fdname));
 		fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname);
+        fdapply->llvmRunTimeHack = true;
 
 		ec = new VarExp(0, fdapply);
 		Expressions *exps = new Expressions();
@@ -3464,7 +3466,7 @@
     this->statement = statement;
     this->tf = NULL;
     this->lblock = NULL;
-    this->isReturnLabel = 0;
+    this->isReturnLabel = 0;
     this->llvmBB = NULL;
 }
 
--- a/dmd/statement.h	Fri Nov 02 06:32:32 2007 +0100
+++ b/dmd/statement.h	Sat Nov 03 14:44:58 2007 +0100
@@ -51,19 +51,24 @@
 
 namespace llvm
 {
-    class Value;
+    class Value;
     class BasicBlock;
 }
 
 // Back end
 struct IRState;
 struct Blockx;
+#if IN_LLVM
+struct DValue;
+typedef DValue elem;
+#endif
+
 #if IN_GCC
 union tree_node; typedef union tree_node block;
-union tree_node; typedef union tree_node elem;
+//union tree_node; typedef union tree_node elem;
 #else
 struct block;
-struct elem;
+//struct elem;
 #endif
 struct code;
 
@@ -715,8 +720,8 @@
 
     Statement *inlineScan(InlineScanState *iss);
 
-    void toIR(IRState *irs);
-    
+    void toIR(IRState *irs);
+    
     llvm::BasicBlock* llvmBB;
 };
 
--- a/gen/arrays.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,672 +0,0 @@
-#include "gen/llvm.h"
-
-#include "mtype.h"
-#include "dsymbol.h"
-#include "aggregate.h"
-#include "declaration.h"
-#include "init.h"
-
-#include "gen/irstate.h"
-#include "gen/tollvm.h"
-#include "gen/arrays.h"
-#include "gen/runtime.h"
-#include "gen/logger.h"
-#include "gen/elem.h"
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-const llvm::StructType* DtoArrayType(Type* t)
-{
-    assert(t->next);
-    const llvm::Type* at = DtoType(t->next);
-    const llvm::Type* arrty;
-
-    /*if (t->ty == Tsarray) {
-        TypeSArray* tsa = (TypeSArray*)t;
-        assert(tsa->dim->type->isintegral());
-        arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger());
-    }
-    else {
-        arrty = llvm::ArrayType::get(at,0);
-    }*/
-    if (at == llvm::Type::VoidTy) {
-        at = llvm::Type::Int8Ty;
-    }
-    arrty = llvm::PointerType::get(at);
-
-    std::vector<const llvm::Type*> members;
-    if (global.params.is64bit)
-        members.push_back(llvm::Type::Int64Ty);
-    else
-        members.push_back(llvm::Type::Int32Ty);
-
-    members.push_back(arrty);
-
-    return llvm::StructType::get(members);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-const llvm::ArrayType* DtoStaticArrayType(Type* t)
-{
-    if (t->llvmType)
-        return llvm::cast<llvm::ArrayType>(t->llvmType);
-
-    assert(t->ty == Tsarray);
-    assert(t->next);
-
-    const llvm::Type* at = DtoType(t->next);
-
-    TypeSArray* tsa = (TypeSArray*)t;
-    assert(tsa->dim->type->isintegral());
-    const llvm::ArrayType* arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger());
-
-    tsa->llvmType = arrty;
-    return arrty;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoNullArray(llvm::Value* v)
-{
-    assert(gIR);
-
-    llvm::Value* len = DtoGEPi(v,0,0,"tmp",gIR->scopebb());
-    llvm::Value* zerolen = llvm::ConstantInt::get(len->getType()->getContainedType(0), 0, false);
-    new llvm::StoreInst(zerolen, len, gIR->scopebb());
-
-    llvm::Value* ptr = DtoGEPi(v,0,1,"tmp",gIR->scopebb());
-    const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(ptr->getType()->getContainedType(0));
-    llvm::Value* nullptr = llvm::ConstantPointerNull::get(pty);
-    new llvm::StoreInst(nullptr, ptr, gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
-{
-    assert(gIR);
-    if (dst->getType() == src->getType())
-    {
-        llvm::Value* ptr = DtoGEPi(src,0,0,"tmp",gIR->scopebb());
-        llvm::Value* val = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
-        ptr = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
-        new llvm::StoreInst(val, ptr, gIR->scopebb());
-
-        ptr = DtoGEPi(src,0,1,"tmp",gIR->scopebb());
-        val = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
-        ptr = DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
-        new llvm::StoreInst(val, ptr, gIR->scopebb());
-    }
-    else
-    {
-        Logger::cout() << "array assignment type dont match: " << *dst->getType() << '\n' << *src->getType() << '\n';
-        if (!llvm::isa<llvm::ArrayType>(src->getType()->getContainedType(0)))
-        {
-            Logger::cout() << "invalid: " << *src << '\n';
-            assert(0);
-        }
-        const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(src->getType()->getContainedType(0));
-        llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType());
-
-        llvm::Value* dstlen = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
-        llvm::Value* srclen = DtoConstSize_t(arrty->getNumElements());
-        new llvm::StoreInst(srclen, dstlen, gIR->scopebb());
-
-        llvm::Value* dstptr = DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
-        llvm::Value* srcptr = new llvm::BitCastInst(src,dstty,"tmp",gIR->scopebb());
-        new llvm::StoreInst(srcptr, dstptr, gIR->scopebb());
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoArrayInit(llvm::Value* l, llvm::Value* r)
-{
-    const llvm::PointerType* ptrty = llvm::cast<llvm::PointerType>(l->getType());
-    const llvm::Type* t = ptrty->getContainedType(0);
-    const llvm::ArrayType* arrty = llvm::cast_or_null<llvm::ArrayType>(t);
-    if (arrty)
-    {
-        llvm::Value* ptr = DtoGEPi(l,0,0,"tmp",gIR->scopebb());
-        llvm::Value* dim = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
-        llvm::Value* val = r;
-        DtoArrayInit(ptr, dim, val);
-    }
-    else if (llvm::isa<llvm::StructType>(t))
-    {
-        assert(0 && "Only static arrays support initialisers atm");
-    }
-    else
-    assert(0);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-typedef const llvm::Type* constLLVMTypeP;
-
-static size_t checkRectArrayInit(const llvm::Type* pt, constLLVMTypeP& finalty)
-{
-    if (llvm::isa<llvm::ArrayType>(pt)) {
-        size_t n = checkRectArrayInit(pt->getContainedType(0), finalty);
-        size_t ne = llvm::cast<llvm::ArrayType>(pt)->getNumElements();
-        if (n) return n * ne;
-        return ne;
-    }
-    finalty = pt;
-    return 0;
-}
-
-void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
-{
-    const llvm::Type* pt = ptr->getType()->getContainedType(0);
-    const llvm::Type* t = val->getType();
-    const llvm::Type* finalTy;
-    if (size_t arrsz = checkRectArrayInit(pt, finalTy)) {
-        assert(finalTy == t);
-        llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(dim);
-        assert(c);
-        dim = llvm::ConstantExpr::getMul(c, DtoConstSize_t(arrsz));
-        ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(finalTy), "tmp");
-    }
-    else if (llvm::isa<llvm::StructType>(t)) {
-        assert(0);
-    }
-    else {
-        assert(t == pt);
-    }
-
-    std::vector<llvm::Value*> args;
-    args.push_back(ptr);
-    args.push_back(dim);
-    args.push_back(val);
-
-    const char* funcname = NULL;
-
-    if (llvm::isa<llvm::PointerType>(t)) {
-        funcname = "_d_array_init_pointer";
-
-        const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
-        if (args[0]->getType() != dstty)
-            args[0] = new llvm::BitCastInst(args[0],dstty,"tmp",gIR->scopebb());
-
-        const llvm::Type* valty = llvm::PointerType::get(llvm::Type::Int8Ty);
-        if (args[2]->getType() != valty)
-            args[2] = new llvm::BitCastInst(args[2],valty,"tmp",gIR->scopebb());
-    }
-    else if (t == llvm::Type::Int1Ty) {
-        funcname = "_d_array_init_i1";
-    }
-    else if (t == llvm::Type::Int8Ty) {
-        funcname = "_d_array_init_i8";
-    }
-    else if (t == llvm::Type::Int16Ty) {
-        funcname = "_d_array_init_i16";
-    }
-    else if (t == llvm::Type::Int32Ty) {
-        funcname = "_d_array_init_i32";
-    }
-    else if (t == llvm::Type::Int64Ty) {
-        funcname = "_d_array_init_i64";
-    }
-    else if (t == llvm::Type::FloatTy) {
-        funcname = "_d_array_init_float";
-    }
-    else if (t == llvm::Type::DoubleTy) {
-        funcname = "_d_array_init_double";
-    }
-    else {
-        Logger::cout() << *ptr->getType() << " = " << *val->getType() << '\n';
-        assert(0);
-    }
-
-    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, funcname);
-    assert(fn);
-    Logger::cout() << "calling array init function: " << *fn <<'\n';
-    llvm::CallInst* call = new llvm::CallInst(fn, args.begin(), args.end(), "", gIR->scopebb());
-    call->setCallingConv(llvm::CallingConv::C);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr)
-{
-    Logger::cout() << "DtoSetArray(" << *arr << ", " << *dim << ", " << *ptr << ")\n";
-    const llvm::StructType* st = llvm::cast<llvm::StructType>(arr->getType()->getContainedType(0));
-    //const llvm::PointerType* pt = llvm::cast<llvm::PointerType>(r->getType());
-    
-    llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-    llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
-
-    llvm::Value* arrdim = DtoGEP(arr,zero,zero,"tmp",gIR->scopebb());
-    new llvm::StoreInst(dim, arrdim, gIR->scopebb());
-    
-    llvm::Value* arrptr = DtoGEP(arr,zero,one,"tmp",gIR->scopebb());
-    new llvm::StoreInst(ptr, arrptr, gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-llvm::Constant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
-{
-    Logger::println("arr init begin");
-    Type* arrinittype = DtoDType(arrinit->type);
-    assert(arrinittype->ty == Tsarray);
-    TypeSArray* t = (TypeSArray*)arrinittype;
-    integer_t tdim = t->dim->toInteger();
-
-    std::vector<llvm::Constant*> inits(tdim, 0);
-
-    const llvm::Type* elemty = DtoType(arrinittype->next);
-
-    assert(arrinit->index.dim == arrinit->value.dim);
-    for (int i=0,j=0; i < tdim; ++i)
-    {
-        Initializer* init = 0;
-        Expression* idx = (Expression*)arrinit->index.data[j];
-
-        if (idx)
-        {
-            integer_t k = idx->toInteger();
-            if (i == k)
-            {
-                init = (Initializer*)arrinit->value.data[j];
-                assert(init);
-                ++j;
-            }
-        }
-        else
-        {
-            init = (Initializer*)arrinit->value.data[j];
-            ++j;
-        }
-
-        llvm::Constant* v = 0;
-
-        if (!init)
-        {
-            v = t->next->defaultInit()->toConstElem(gIR);
-        }
-        else if (ExpInitializer* ex = init->isExpInitializer())
-        {
-            v = ex->exp->toConstElem(gIR);
-        }
-        else if (StructInitializer* si = init->isStructInitializer())
-        {
-            v = DtoConstStructInitializer(si);
-        }
-        else if (ArrayInitializer* ai = init->isArrayInitializer())
-        {
-            v = DtoConstArrayInitializer(ai);
-        }
-        else if (init->isVoidInitializer())
-        {
-            v = llvm::UndefValue::get(elemty);
-        }
-        else
-        assert(v);
-
-        inits[i] = v;
-    }
-
-    const llvm::ArrayType* arrty = DtoStaticArrayType(t);
-    return llvm::ConstantArray::get(arrty, inits);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-static llvm::Value* get_slice_ptr(elem* e, llvm::Value*& sz)
-{
-    assert(e->mem);
-    const llvm::Type* t = e->mem->getType()->getContainedType(0);
-    llvm::Value* ret = 0;
-    if (e->arg != 0) {
-        // this means it's a real slice
-        ret = e->mem;
-
-        size_t elembsz = gTargetData->getTypeSize(ret->getType());
-        llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
-
-        if (llvm::isa<llvm::ConstantInt>(e->arg)) {
-            sz = llvm::ConstantExpr::getMul(elemsz, llvm::cast<llvm::Constant>(e->arg));
-        }
-        else {
-            sz = llvm::BinaryOperator::createMul(elemsz,e->arg,"tmp",gIR->scopebb());
-        }
-    }
-    else if (llvm::isa<llvm::ArrayType>(t)) {
-        ret = DtoGEPi(e->mem, 0, 0, "tmp", gIR->scopebb());
-
-        size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0));
-        llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
-
-        size_t numelements = llvm::cast<llvm::ArrayType>(t)->getNumElements();
-        llvm::ConstantInt* nelems = llvm::ConstantInt::get(DtoSize_t(), numelements, false);
-
-        sz = llvm::ConstantExpr::getMul(elemsz, nelems);
-    }
-    else if (llvm::isa<llvm::StructType>(t)) {
-        ret = DtoGEPi(e->mem, 0, 1, "tmp", gIR->scopebb());
-        ret = new llvm::LoadInst(ret, "tmp", gIR->scopebb());
-
-        size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0));
-        llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
-
-        llvm::Value* len = DtoGEPi(e->mem, 0, 0, "tmp", gIR->scopebb());
-        len = new llvm::LoadInst(len, "tmp", gIR->scopebb());
-        sz = llvm::BinaryOperator::createMul(len,elemsz,"tmp",gIR->scopebb());
-    }
-    else {
-        assert(0);
-    }
-    return ret;
-}
-
-void DtoArrayCopy(elem* dst, elem* src)
-{
-    Logger::cout() << "Array copy ((((" << *src->mem << ")))) into ((((" << *dst->mem << "))))\n";
-
-    assert(dst->type == elem::SLICE);
-    assert(src->type == elem::SLICE);
-
-    llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
-
-    llvm::Value* sz1;
-    llvm::Value* dstarr = new llvm::BitCastInst(get_slice_ptr(dst,sz1),arrty,"tmp",gIR->scopebb());
-
-    llvm::Value* sz2;
-    llvm::Value* srcarr = new llvm::BitCastInst(get_slice_ptr(src,sz2),arrty,"tmp",gIR->scopebb());
-
-    llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
-    std::vector<llvm::Value*> llargs;
-    llargs.resize(4);
-    llargs[0] = dstarr;
-    llargs[1] = srcarr;
-    llargs[2] = sz1;
-    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-    new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src)
-{
-    assert(dst->getType() == src->getType());
-    size_t arrsz = gTargetData->getTypeSize(dst->getType()->getContainedType(0));
-    llvm::Value* n = llvm::ConstantInt::get(DtoSize_t(), arrsz, false);
-
-    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 = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
-    std::vector<llvm::Value*> llargs;
-    llargs.resize(4);
-    llargs[0] = dstarr;
-    llargs[1] = srcarr;
-    llargs[2] = n;
-    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-    new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-llvm::Constant* DtoConstSlice(llvm::Constant* dim, llvm::Constant* ptr)
-{
-    std::vector<const llvm::Type*> types;
-    types.push_back(dim->getType());
-    types.push_back(ptr->getType());
-    const llvm::StructType* type = llvm::StructType::get(types);
-    std::vector<llvm::Constant*> values;
-    values.push_back(dim);
-    values.push_back(ptr);
-    return llvm::ConstantStruct::get(type,values);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-llvm::Value* DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool doinit)
-{
-    const llvm::Type* ty = DtoType(dty);
-    assert(ty != llvm::Type::VoidTy);
-    size_t sz = gTargetData->getTypeSize(ty);
-    llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), sz, false);
-    llvm::Value* bytesize = (sz == 1) ? dim : llvm::BinaryOperator::createMul(n,dim,"tmp",gIR->scopebb());
-
-    llvm::Value* nullptr = llvm::ConstantPointerNull::get(llvm::PointerType::get(ty));
-
-    llvm::Value* newptr = DtoRealloc(nullptr, bytesize);
-
-    if (doinit) {
-        elem* e = dty->defaultInit()->toElem(gIR);
-        DtoArrayInit(newptr,dim,e->getValue());
-        delete e;
-    }
-
-    llvm::Value* lenptr = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
-    new llvm::StoreInst(dim,lenptr,gIR->scopebb());
-    llvm::Value* ptrptr = DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
-    new llvm::StoreInst(newptr,ptrptr,gIR->scopebb());
-
-    return newptr;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz)
-{
-    llvm::Value* ptr = DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb());
-    llvm::Value* ptrld = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
-
-    size_t isz = gTargetData->getTypeSize(ptrld->getType()->getContainedType(0));
-    llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), isz, false);
-    llvm::Value* bytesz = (isz == 1) ? sz : llvm::BinaryOperator::createMul(n,sz,"tmp",gIR->scopebb());
-
-    llvm::Value* newptr = DtoRealloc(ptrld, bytesz);
-    new llvm::StoreInst(newptr,ptr,gIR->scopebb());
-
-    llvm::Value* len = DtoGEPi(arr, 0, 0, "tmp", gIR->scopebb());
-    new llvm::StoreInst(sz,len,gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void DtoCatAssignElement(llvm::Value* arr, Expression* exp)
-{
-    llvm::Value* ptr = DtoGEPi(arr, 0, 0, "tmp", gIR->scopebb());
-    llvm::Value* idx = new llvm::LoadInst(ptr, "tmp", gIR->scopebb());
-    llvm::Value* one = llvm::ConstantInt::get(idx->getType(),1,false);
-    llvm::Value* len = llvm::BinaryOperator::createAdd(idx, one, "tmp", gIR->scopebb());
-    DtoResizeDynArray(arr,len);
-
-    ptr = DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb());
-    ptr = new llvm::LoadInst(ptr, "tmp", gIR->scopebb());
-    ptr = new llvm::GetElementPtrInst(ptr, idx, "tmp", gIR->scopebb());
-
-    elem* e = exp->toElem(gIR);
-    Type* et = DtoDType(exp->type);
-    DtoAssign(et, ptr, e->getValue());
-    delete e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void DtoCatArrays(llvm::Value* arr, Expression* exp1, Expression* exp2)
-{
-    Type* t1 = DtoDType(exp1->type);
-    Type* t2 = DtoDType(exp2->type);
-
-    assert(t1->ty == Tarray);
-    assert(t1->ty == t2->ty);
-
-    elem* e1 = exp1->toElem(gIR);
-    llvm::Value* a = e1->getValue();
-    delete e1;
-
-    elem* e2 = exp2->toElem(gIR);
-    llvm::Value* b = e2->getValue();
-    delete e2;
-
-    llvm::Value *len1, *len2, *src1, *src2, *res;
-    len1 = gIR->ir->CreateLoad(DtoGEPi(a,0,0,"tmp"),"tmp");
-    len2 = gIR->ir->CreateLoad(DtoGEPi(b,0,0,"tmp"),"tmp");
-    res = gIR->ir->CreateAdd(len1,len2,"tmp");
-
-    llvm::Value* mem = DtoNewDynArray(arr, res, DtoDType(t1->next), false);
-
-    src1 = gIR->ir->CreateLoad(DtoGEPi(a,0,1,"tmp"),"tmp");
-    src2 = gIR->ir->CreateLoad(DtoGEPi(b,0,1,"tmp"),"tmp");
-
-    DtoMemCpy(mem,src1,len1);
-    mem = gIR->ir->CreateGEP(mem,len1,"tmp");
-    DtoMemCpy(mem,src2,len2);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-llvm::Value* DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r)
-{
-    const char* fname;
-    if (op == TOKequal)
-        fname = "_d_static_array_eq";
-    else if (op == TOKnotequal)
-        fname = "_d_static_array_neq";
-    else
-        assert(0);
-    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
-    assert(fn);
-
-    assert(l->getType() == r->getType());
-    assert(llvm::isa<llvm::PointerType>(l->getType()));
-    const llvm::Type* arrty = l->getType()->getContainedType(0);
-    assert(llvm::isa<llvm::ArrayType>(arrty));
-    
-    llvm::Value* ll = new llvm::BitCastInst(l, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
-    llvm::Value* rr = new llvm::BitCastInst(r, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
-    llvm::Value* n = llvm::ConstantInt::get(DtoSize_t(),gTargetData->getTypeSize(arrty),false);
-
-    std::vector<llvm::Value*> args;
-    args.push_back(ll);
-    args.push_back(rr);
-    args.push_back(n);
-    return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoDynArrayCompare(TOK op, llvm::Value* l, llvm::Value* r)
-{
-    const char* fname;
-    if (op == TOKequal)
-        fname = "_d_dyn_array_eq";
-    else if (op == TOKnotequal)
-        fname = "_d_dyn_array_neq";
-    else
-        assert(0);
-    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
-    assert(fn);
-
-    Logger::cout() << "lhsType:" << *l->getType() << "\nrhsType:" << *r->getType() << '\n';
-    assert(l->getType() == r->getType());
-    assert(llvm::isa<llvm::PointerType>(l->getType()));
-    const llvm::Type* arrty = l->getType()->getContainedType(0);
-    assert(llvm::isa<llvm::StructType>(arrty));
-    const llvm::StructType* structType = llvm::cast<llvm::StructType>(arrty);
-    const llvm::Type* elemType = structType->getElementType(1)->getContainedType(0);
-
-    std::vector<const llvm::Type*> arrTypes;
-    arrTypes.push_back(DtoSize_t());
-    arrTypes.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
-    const llvm::StructType* arrType = llvm::StructType::get(arrTypes);
-
-    llvm::Value* llmem = l;
-    llvm::Value* rrmem = r;
-
-    if (arrty != arrType) {
-        llmem= new llvm::AllocaInst(arrType,"tmparr",gIR->topallocapoint());
-
-        llvm::Value* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0, "tmp"),"tmp");
-        ll = DtoArrayCastLength(ll, elemType, llvm::Type::Int8Ty);
-        llvm::Value* lllen = DtoGEPi(llmem, 0,0, "tmp");
-        gIR->ir->CreateStore(ll,lllen);
-
-        ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,1, "tmp"),"tmp");
-        ll = new llvm::BitCastInst(ll, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
-        llvm::Value* llptr = DtoGEPi(llmem, 0,1, "tmp");
-        gIR->ir->CreateStore(ll,llptr);
-
-        rrmem = new llvm::AllocaInst(arrType,"tmparr",gIR->topallocapoint());
-
-        llvm::Value* rr = gIR->ir->CreateLoad(DtoGEPi(r, 0,0, "tmp"),"tmp");
-        rr = DtoArrayCastLength(rr, elemType, llvm::Type::Int8Ty);
-        llvm::Value* rrlen = DtoGEPi(rrmem, 0,0, "tmp");
-        gIR->ir->CreateStore(rr,rrlen);
-
-        rr = gIR->ir->CreateLoad(DtoGEPi(r, 0,1, "tmp"),"tmp");
-        rr = new llvm::BitCastInst(rr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
-        llvm::Value* rrptr = DtoGEPi(rrmem, 0,1, "tmp");
-        gIR->ir->CreateStore(rr,rrptr);
-    }
-
-    std::vector<llvm::Value*> args;
-    args.push_back(llmem);
-    args.push_back(rrmem);
-    return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-llvm::Value* DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty)
-{
-    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_cast_len");
-    assert(fn);
-    std::vector<llvm::Value*> args;
-    args.push_back(len);
-    args.push_back(llvm::ConstantInt::get(DtoSize_t(), gTargetData->getTypeSize(elemty), false));
-    args.push_back(llvm::ConstantInt::get(DtoSize_t(), gTargetData->getTypeSize(newelemty), false));
-    return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-llvm::Value* DtoDynArrayIs(TOK op, llvm::Value* l, llvm::Value* r)
-{
-    llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
-
-    if (r == NULL) {
-        llvm::Value* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0, "tmp"),"tmp");
-        llvm::Value* rl = DtoConstSize_t(0);
-        llvm::Value* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
-
-        llvm::Value* lp = gIR->ir->CreateLoad(DtoGEPi(l, 0,1, "tmp"),"tmp");
-        const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(lp->getType());
-        llvm::Value* rp = llvm::ConstantPointerNull::get(pty);
-        llvm::Value* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
-
-        llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
-        return b;
-    }
-    else {
-        assert(l->getType() == r->getType());
-
-        llvm::Value* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0, "tmp"),"tmp");
-        llvm::Value* rl = gIR->ir->CreateLoad(DtoGEPi(r, 0,0, "tmp"),"tmp");
-        llvm::Value* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
-
-        llvm::Value* lp = gIR->ir->CreateLoad(DtoGEPi(l, 0,1, "tmp"),"tmp");
-        llvm::Value* rp = gIR->ir->CreateLoad(DtoGEPi(r, 0,1, "tmp"),"tmp");
-        llvm::Value* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
-
-        llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
-        return b;
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-llvm::Constant* DtoConstStaticArray(const llvm::Type* t, llvm::Constant* c)
-{
-    assert(llvm::isa<llvm::ArrayType>(t));
-    const llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(t);
-
-    if (llvm::isa<llvm::ArrayType>(at->getElementType()))
-    {
-        c = DtoConstStaticArray(at->getElementType(), c);
-    }
-    else {
-        assert(at->getElementType() == c->getType());
-    }
-    std::vector<llvm::Constant*> initvals;
-    initvals.resize(at->getNumElements(), c);
-    return llvm::ConstantArray::get(at, initvals);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/arrays.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,754 @@
+#include "gen/llvm.h"
+
+#include "mtype.h"
+#include "dsymbol.h"
+#include "aggregate.h"
+#include "declaration.h"
+#include "init.h"
+
+#include "gen/irstate.h"
+#include "gen/tollvm.h"
+#include "gen/arrays.h"
+#include "gen/runtime.h"
+#include "gen/logger.h"
+#include "gen/dvalue.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+const llvm::StructType* DtoArrayType(Type* t)
+{
+    assert(t->next);
+    const llvm::Type* at = DtoType(t->next);
+    const llvm::Type* arrty;
+
+    /*if (t->ty == Tsarray) {
+        TypeSArray* tsa = (TypeSArray*)t;
+        assert(tsa->dim->type->isintegral());
+        arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger());
+    }
+    else {
+        arrty = llvm::ArrayType::get(at,0);
+    }*/
+    if (at == llvm::Type::VoidTy) {
+        at = llvm::Type::Int8Ty;
+    }
+    arrty = llvm::PointerType::get(at);
+
+    std::vector<const llvm::Type*> members;
+    if (global.params.is64bit)
+        members.push_back(llvm::Type::Int64Ty);
+    else
+        members.push_back(llvm::Type::Int32Ty);
+
+    members.push_back(arrty);
+
+    return llvm::StructType::get(members);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+const llvm::ArrayType* DtoStaticArrayType(Type* t)
+{
+    if (t->llvmType)
+        return llvm::cast<llvm::ArrayType>(t->llvmType);
+
+    assert(t->ty == Tsarray);
+    assert(t->next);
+
+    const llvm::Type* at = DtoType(t->next);
+
+    TypeSArray* tsa = (TypeSArray*)t;
+    assert(tsa->dim->type->isintegral());
+    const llvm::ArrayType* arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger());
+
+    tsa->llvmType = arrty;
+    return arrty;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoNullArray(llvm::Value* v)
+{
+    assert(gIR);
+
+    llvm::Value* len = DtoGEPi(v,0,0,"tmp",gIR->scopebb());
+    llvm::Value* zerolen = llvm::ConstantInt::get(len->getType()->getContainedType(0), 0, false);
+    new llvm::StoreInst(zerolen, len, gIR->scopebb());
+
+    llvm::Value* ptr = DtoGEPi(v,0,1,"tmp",gIR->scopebb());
+    const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(ptr->getType()->getContainedType(0));
+    llvm::Value* nullptr = llvm::ConstantPointerNull::get(pty);
+    new llvm::StoreInst(nullptr, ptr, gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
+{
+    assert(gIR);
+    if (dst->getType() == src->getType())
+    {
+        llvm::Value* ptr = DtoGEPi(src,0,0,"tmp",gIR->scopebb());
+        llvm::Value* val = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
+        ptr = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
+        new llvm::StoreInst(val, ptr, gIR->scopebb());
+
+        ptr = DtoGEPi(src,0,1,"tmp",gIR->scopebb());
+        val = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
+        ptr = DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
+        new llvm::StoreInst(val, ptr, gIR->scopebb());
+    }
+    else
+    {
+        Logger::cout() << "array assignment type dont match: " << *dst->getType() << '\n' << *src->getType() << '\n';
+        if (!llvm::isa<llvm::ArrayType>(src->getType()->getContainedType(0)))
+        {
+            Logger::cout() << "invalid: " << *src << '\n';
+            assert(0);
+        }
+        const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(src->getType()->getContainedType(0));
+        llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType());
+
+        llvm::Value* dstlen = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
+        llvm::Value* srclen = DtoConstSize_t(arrty->getNumElements());
+        new llvm::StoreInst(srclen, dstlen, gIR->scopebb());
+
+        llvm::Value* dstptr = DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
+        llvm::Value* srcptr = new llvm::BitCastInst(src,dstty,"tmp",gIR->scopebb());
+        new llvm::StoreInst(srcptr, dstptr, gIR->scopebb());
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoArrayInit(llvm::Value* l, llvm::Value* r)
+{
+    const llvm::PointerType* ptrty = llvm::cast<llvm::PointerType>(l->getType());
+    const llvm::Type* t = ptrty->getContainedType(0);
+    const llvm::ArrayType* arrty = llvm::dyn_cast<llvm::ArrayType>(t);
+    if (arrty)
+    {
+        llvm::Value* ptr = DtoGEPi(l,0,0,"tmp",gIR->scopebb());
+        llvm::Value* dim = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
+        DtoArrayInit(ptr, dim, r);
+    }
+    else if (llvm::isa<llvm::StructType>(t))
+    {
+        llvm::Value* dim = DtoLoad(DtoGEPi(l, 0,0, "tmp"));
+        llvm::Value* ptr = DtoLoad(DtoGEPi(l, 0,1, "tmp"));
+        DtoArrayInit(ptr, dim, r);
+    }
+    else
+    assert(0);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+typedef const llvm::Type* constLLVMTypeP;
+
+static size_t checkRectArrayInit(const llvm::Type* pt, constLLVMTypeP& finalty)
+{
+    if (llvm::isa<llvm::ArrayType>(pt)) {
+        size_t n = checkRectArrayInit(pt->getContainedType(0), finalty);
+        size_t ne = llvm::cast<llvm::ArrayType>(pt)->getNumElements();
+        if (n) return n * ne;
+        return ne;
+    }
+    finalty = pt;
+    return 0;
+}
+
+void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
+{
+    Logger::println("HELLO");
+    Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n';
+    const llvm::Type* pt = ptr->getType()->getContainedType(0);
+    const llvm::Type* t = val->getType();
+    const llvm::Type* finalTy;
+    if (size_t arrsz = checkRectArrayInit(pt, finalTy)) {
+        assert(finalTy == t);
+        llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(dim);
+        assert(c);
+        dim = llvm::ConstantExpr::getMul(c, DtoConstSize_t(arrsz));
+        ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(finalTy), "tmp");
+    }
+    else if (llvm::isa<llvm::StructType>(t)) {
+        assert(0);
+    }
+    else {
+        assert(t == pt);
+    }
+
+    std::vector<llvm::Value*> args;
+    args.push_back(ptr);
+    args.push_back(dim);
+    args.push_back(val);
+
+    const char* funcname = NULL;
+
+    if (llvm::isa<llvm::PointerType>(t)) {
+        funcname = "_d_array_init_pointer";
+
+        const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
+        if (args[0]->getType() != dstty)
+            args[0] = new llvm::BitCastInst(args[0],dstty,"tmp",gIR->scopebb());
+
+        const llvm::Type* valty = llvm::PointerType::get(llvm::Type::Int8Ty);
+        if (args[2]->getType() != valty)
+            args[2] = new llvm::BitCastInst(args[2],valty,"tmp",gIR->scopebb());
+    }
+    else if (t == llvm::Type::Int1Ty) {
+        funcname = "_d_array_init_i1";
+    }
+    else if (t == llvm::Type::Int8Ty) {
+        funcname = "_d_array_init_i8";
+    }
+    else if (t == llvm::Type::Int16Ty) {
+        funcname = "_d_array_init_i16";
+    }
+    else if (t == llvm::Type::Int32Ty) {
+        funcname = "_d_array_init_i32";
+    }
+    else if (t == llvm::Type::Int64Ty) {
+        funcname = "_d_array_init_i64";
+    }
+    else if (t == llvm::Type::FloatTy) {
+        funcname = "_d_array_init_float";
+    }
+    else if (t == llvm::Type::DoubleTy) {
+        funcname = "_d_array_init_double";
+    }
+    else {
+        Logger::cout() << *ptr->getType() << " = " << *val->getType() << '\n';
+        assert(0);
+    }
+
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, funcname);
+    assert(fn);
+    Logger::cout() << "calling array init function: " << *fn <<'\n';
+    llvm::CallInst* call = new llvm::CallInst(fn, args.begin(), args.end(), "", gIR->scopebb());
+    call->setCallingConv(llvm::CallingConv::C);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr)
+{
+    Logger::cout() << "DtoSetArray(" << *arr << ", " << *dim << ", " << *ptr << ")\n";
+    const llvm::StructType* st = llvm::cast<llvm::StructType>(arr->getType()->getContainedType(0));
+    //const llvm::PointerType* pt = llvm::cast<llvm::PointerType>(r->getType());
+    
+    llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+    llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
+
+    llvm::Value* arrdim = DtoGEP(arr,zero,zero,"tmp",gIR->scopebb());
+    new llvm::StoreInst(dim, arrdim, gIR->scopebb());
+    
+    llvm::Value* arrptr = DtoGEP(arr,zero,one,"tmp",gIR->scopebb());
+    new llvm::StoreInst(ptr, arrptr, gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Constant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
+{
+    Logger::println("arr init begin");
+    Type* arrinittype = DtoDType(arrinit->type);
+
+    Type* t;
+    integer_t tdim;
+    if (arrinittype->ty == Tsarray) {
+        TypeSArray* tsa = (TypeSArray*)arrinittype;
+        tdim = tsa->dim->toInteger();
+        t = tsa;
+    }
+    else if (arrinittype->ty == Tarray) {
+        t = arrinittype;
+        tdim = arrinit->dim;
+    }
+    else
+    assert(0);
+
+    std::vector<llvm::Constant*> inits(tdim, 0);
+
+    const llvm::Type* elemty = DtoType(arrinittype->next);
+
+    assert(arrinit->index.dim == arrinit->value.dim);
+    for (int i=0,j=0; i < tdim; ++i)
+    {
+        Initializer* init = 0;
+        Expression* idx = (Expression*)arrinit->index.data[j];
+
+        if (idx)
+        {
+            integer_t k = idx->toInteger();
+            if (i == k)
+            {
+                init = (Initializer*)arrinit->value.data[j];
+                assert(init);
+                ++j;
+            }
+        }
+        else
+        {
+            init = (Initializer*)arrinit->value.data[j];
+            ++j;
+        }
+
+        llvm::Constant* v = 0;
+
+        if (!init)
+        {
+            v = t->next->defaultInit()->toConstElem(gIR);
+        }
+        else if (ExpInitializer* ex = init->isExpInitializer())
+        {
+            v = ex->exp->toConstElem(gIR);
+        }
+        else if (StructInitializer* si = init->isStructInitializer())
+        {
+            v = DtoConstStructInitializer(si);
+        }
+        else if (ArrayInitializer* ai = init->isArrayInitializer())
+        {
+            v = DtoConstArrayInitializer(ai);
+        }
+        else if (init->isVoidInitializer())
+        {
+            v = llvm::UndefValue::get(elemty);
+        }
+        else
+        assert(v);
+
+        inits[i] = v;
+    }
+
+    const llvm::ArrayType* arrty = llvm::ArrayType::get(elemty,tdim);
+    llvm::Constant* constarr = llvm::ConstantArray::get(arrty, inits);
+
+    if (arrinittype->ty == Tsarray)
+        return constarr;
+    else
+        assert(arrinittype->ty == Tarray);
+
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrty,true,llvm::GlobalValue::InternalLinkage,constarr,"constarray",gIR->module);
+    llvm::Constant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
+    llvm::Constant* gep = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
+    return DtoConstSlice(DtoConstSize_t(tdim),gep);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+static llvm::Value* get_slice_ptr(DSliceValue* e, llvm::Value*& sz)
+{
+    const llvm::Type* t = e->ptr->getType()->getContainedType(0);
+    llvm::Value* ret = 0;
+    if (e->len != 0) {
+        // this means it's a real slice
+        ret = e->ptr;
+
+        size_t elembsz = gTargetData->getTypeSize(ret->getType());
+        llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
+
+        if (llvm::isa<llvm::ConstantInt>(e->len)) {
+            sz = llvm::ConstantExpr::getMul(elemsz, llvm::cast<llvm::Constant>(e->len));
+        }
+        else {
+            sz = llvm::BinaryOperator::createMul(elemsz,e->len,"tmp",gIR->scopebb());
+        }
+    }
+    else if (llvm::isa<llvm::ArrayType>(t)) {
+        ret = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb());
+
+        size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0));
+        llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
+
+        size_t numelements = llvm::cast<llvm::ArrayType>(t)->getNumElements();
+        llvm::ConstantInt* nelems = llvm::ConstantInt::get(DtoSize_t(), numelements, false);
+
+        sz = llvm::ConstantExpr::getMul(elemsz, nelems);
+    }
+    else if (llvm::isa<llvm::StructType>(t)) {
+        ret = DtoGEPi(e->ptr, 0, 1, "tmp", gIR->scopebb());
+        ret = new llvm::LoadInst(ret, "tmp", gIR->scopebb());
+
+        size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0));
+        llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
+
+        llvm::Value* len = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb());
+        len = new llvm::LoadInst(len, "tmp", gIR->scopebb());
+        sz = llvm::BinaryOperator::createMul(len,elemsz,"tmp",gIR->scopebb());
+    }
+    else {
+        assert(0);
+    }
+    return ret;
+}
+
+void DtoArrayCopy(DSliceValue* dst, DSliceValue* src)
+{
+    llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
+
+    llvm::Value* sz1;
+    llvm::Value* dstarr = new llvm::BitCastInst(get_slice_ptr(dst,sz1),arrty,"tmp",gIR->scopebb());
+
+    llvm::Value* sz2;
+    llvm::Value* srcarr = new llvm::BitCastInst(get_slice_ptr(src,sz2),arrty,"tmp",gIR->scopebb());
+
+    llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
+    std::vector<llvm::Value*> llargs;
+    llargs.resize(4);
+    llargs[0] = dstarr;
+    llargs[1] = srcarr;
+    llargs[2] = sz1;
+    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+
+    new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src)
+{
+    assert(dst->getType() == src->getType());
+    size_t arrsz = gTargetData->getTypeSize(dst->getType()->getContainedType(0));
+    llvm::Value* n = llvm::ConstantInt::get(DtoSize_t(), arrsz, false);
+
+    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 = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
+    std::vector<llvm::Value*> llargs;
+    llargs.resize(4);
+    llargs[0] = dstarr;
+    llargs[1] = srcarr;
+    llargs[2] = n;
+    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+
+    new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Constant* DtoConstSlice(llvm::Constant* dim, llvm::Constant* ptr)
+{
+    std::vector<const llvm::Type*> types;
+    types.push_back(dim->getType());
+    types.push_back(ptr->getType());
+    const llvm::StructType* type = llvm::StructType::get(types);
+    std::vector<llvm::Constant*> values;
+    values.push_back(dim);
+    values.push_back(ptr);
+    return llvm::ConstantStruct::get(type,values);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Value* DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool doinit)
+{
+    const llvm::Type* ty = DtoType(dty);
+    assert(ty != llvm::Type::VoidTy);
+    size_t sz = gTargetData->getTypeSize(ty);
+    llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), sz, false);
+    llvm::Value* bytesize = (sz == 1) ? dim : llvm::BinaryOperator::createMul(n,dim,"tmp",gIR->scopebb());
+
+    llvm::Value* nullptr = llvm::ConstantPointerNull::get(llvm::PointerType::get(ty));
+
+    llvm::Value* newptr = DtoRealloc(nullptr, bytesize);
+
+    if (doinit) {
+        DValue* e = dty->defaultInit()->toElem(gIR);
+        DtoArrayInit(newptr,dim,e->getRVal());
+    }
+
+    llvm::Value* lenptr = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
+    new llvm::StoreInst(dim,lenptr,gIR->scopebb());
+    llvm::Value* ptrptr = DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
+    new llvm::StoreInst(newptr,ptrptr,gIR->scopebb());
+
+    return newptr;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Value* DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz)
+{
+    llvm::Value* ptr = DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb());
+    llvm::Value* ptrld = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
+
+    size_t isz = gTargetData->getTypeSize(ptrld->getType()->getContainedType(0));
+    llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), isz, false);
+    llvm::Value* bytesz = (isz == 1) ? sz : llvm::BinaryOperator::createMul(n,sz,"tmp",gIR->scopebb());
+
+    llvm::Value* newptr = DtoRealloc(ptrld, bytesz);
+    new llvm::StoreInst(newptr,ptr,gIR->scopebb());
+
+    llvm::Value* len = DtoGEPi(arr, 0, 0, "tmp", gIR->scopebb());
+    new llvm::StoreInst(sz,len,gIR->scopebb());
+
+    return newptr;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void DtoCatAssignElement(llvm::Value* arr, Expression* exp)
+{
+    llvm::Value* ptr = DtoGEPi(arr, 0, 0, "tmp");
+    llvm::Value* idx = DtoLoad(ptr);
+    llvm::Value* one = llvm::ConstantInt::get(idx->getType(),1,false);
+    llvm::Value* len = llvm::BinaryOperator::createAdd(idx, one, "tmp", gIR->scopebb());
+    DtoResizeDynArray(arr,len);
+
+    ptr = DtoLoad(DtoGEPi(arr, 0, 1, "tmp"));
+    ptr = new llvm::GetElementPtrInst(ptr, idx, "tmp", gIR->scopebb());
+
+    DValue* dptr = new DVarValue(exp->type, ptr, true);
+
+    gIR->exps.push_back(IRExp(0,exp,dptr));
+    DValue* e = exp->toElem(gIR);
+    gIR->exps.pop_back();
+
+    if (!e->inPlace())
+        DtoAssign(dptr, e);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void DtoCatAssignArray(llvm::Value* arr, Expression* exp)
+{
+    DValue* e = exp->toElem(gIR);
+
+    llvm::Value *len1, *len2, *src1, *src2, *res;
+
+    DValue* darr = new DVarValue(exp->type, arr, true);
+
+    len1 = DtoArrayLen(darr);
+    len2 = DtoArrayLen(e);
+    res = gIR->ir->CreateAdd(len1,len2,"tmp");
+
+    llvm::Value* mem = DtoResizeDynArray(arr,res);
+
+    src1 = DtoArrayPtr(darr);
+    src2 = DtoArrayPtr(e);
+
+    mem = gIR->ir->CreateGEP(mem,len1,"tmp");
+    DtoMemCpy(mem,src2,len2);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void DtoCatArrays(llvm::Value* arr, Expression* exp1, Expression* exp2)
+{
+    Type* t1 = DtoDType(exp1->type);
+    Type* t2 = DtoDType(exp2->type);
+
+    assert(t1->ty == Tarray);
+    assert(t1->ty == t2->ty);
+
+    DValue* e1 = exp1->toElem(gIR);
+    llvm::Value* a = e1->getRVal();
+
+    DValue* e2 = exp2->toElem(gIR);
+    llvm::Value* b = e2->getRVal();
+
+    llvm::Value *len1, *len2, *src1, *src2, *res;
+    len1 = gIR->ir->CreateLoad(DtoGEPi(a,0,0,"tmp"),"tmp");
+    len2 = gIR->ir->CreateLoad(DtoGEPi(b,0,0,"tmp"),"tmp");
+    res = gIR->ir->CreateAdd(len1,len2,"tmp");
+
+    llvm::Value* mem = DtoNewDynArray(arr, res, DtoDType(t1->next), false);
+
+    src1 = gIR->ir->CreateLoad(DtoGEPi(a,0,1,"tmp"),"tmp");
+    src2 = gIR->ir->CreateLoad(DtoGEPi(b,0,1,"tmp"),"tmp");
+
+    DtoMemCpy(mem,src1,len1);
+    mem = gIR->ir->CreateGEP(mem,len1,"tmp");
+    DtoMemCpy(mem,src2,len2);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Value* DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r)
+{
+    const char* fname;
+    if (op == TOKequal)
+        fname = "_d_static_array_eq";
+    else if (op == TOKnotequal)
+        fname = "_d_static_array_neq";
+    else
+        assert(0);
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
+    assert(fn);
+
+    assert(l->getType() == r->getType());
+    assert(llvm::isa<llvm::PointerType>(l->getType()));
+    const llvm::Type* arrty = l->getType()->getContainedType(0);
+    assert(llvm::isa<llvm::ArrayType>(arrty));
+    
+    llvm::Value* ll = new llvm::BitCastInst(l, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
+    llvm::Value* rr = new llvm::BitCastInst(r, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
+    llvm::Value* n = llvm::ConstantInt::get(DtoSize_t(),gTargetData->getTypeSize(arrty),false);
+
+    std::vector<llvm::Value*> args;
+    args.push_back(ll);
+    args.push_back(rr);
+    args.push_back(n);
+    return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoDynArrayCompare(TOK op, llvm::Value* l, llvm::Value* r)
+{
+    const char* fname;
+    if (op == TOKequal)
+        fname = "_d_dyn_array_eq";
+    else if (op == TOKnotequal)
+        fname = "_d_dyn_array_neq";
+    else
+        assert(0);
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
+    assert(fn);
+
+    Logger::cout() << "lhsType:" << *l->getType() << "\nrhsType:" << *r->getType() << '\n';
+    assert(l->getType() == r->getType());
+    assert(llvm::isa<llvm::PointerType>(l->getType()));
+    const llvm::Type* arrty = l->getType()->getContainedType(0);
+    assert(llvm::isa<llvm::StructType>(arrty));
+    const llvm::StructType* structType = llvm::cast<llvm::StructType>(arrty);
+    const llvm::Type* elemType = structType->getElementType(1)->getContainedType(0);
+
+    std::vector<const llvm::Type*> arrTypes;
+    arrTypes.push_back(DtoSize_t());
+    arrTypes.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
+    const llvm::StructType* arrType = llvm::StructType::get(arrTypes);
+
+    llvm::Value* llmem = l;
+    llvm::Value* rrmem = r;
+
+    if (arrty != arrType) {
+        llmem= new llvm::AllocaInst(arrType,"tmparr",gIR->topallocapoint());
+
+        llvm::Value* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0, "tmp"),"tmp");
+        ll = DtoArrayCastLength(ll, elemType, llvm::Type::Int8Ty);
+        llvm::Value* lllen = DtoGEPi(llmem, 0,0, "tmp");
+        gIR->ir->CreateStore(ll,lllen);
+
+        ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,1, "tmp"),"tmp");
+        ll = new llvm::BitCastInst(ll, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
+        llvm::Value* llptr = DtoGEPi(llmem, 0,1, "tmp");
+        gIR->ir->CreateStore(ll,llptr);
+
+        rrmem = new llvm::AllocaInst(arrType,"tmparr",gIR->topallocapoint());
+
+        llvm::Value* rr = gIR->ir->CreateLoad(DtoGEPi(r, 0,0, "tmp"),"tmp");
+        rr = DtoArrayCastLength(rr, elemType, llvm::Type::Int8Ty);
+        llvm::Value* rrlen = DtoGEPi(rrmem, 0,0, "tmp");
+        gIR->ir->CreateStore(rr,rrlen);
+
+        rr = gIR->ir->CreateLoad(DtoGEPi(r, 0,1, "tmp"),"tmp");
+        rr = new llvm::BitCastInst(rr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
+        llvm::Value* rrptr = DtoGEPi(rrmem, 0,1, "tmp");
+        gIR->ir->CreateStore(rr,rrptr);
+    }
+
+    std::vector<llvm::Value*> args;
+    args.push_back(llmem);
+    args.push_back(rrmem);
+    return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Value* DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty)
+{
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_cast_len");
+    assert(fn);
+    std::vector<llvm::Value*> args;
+    args.push_back(len);
+    args.push_back(llvm::ConstantInt::get(DtoSize_t(), gTargetData->getTypeSize(elemty), false));
+    args.push_back(llvm::ConstantInt::get(DtoSize_t(), gTargetData->getTypeSize(newelemty), false));
+    return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Value* DtoDynArrayIs(TOK op, llvm::Value* l, llvm::Value* r)
+{
+    llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
+
+    if (r == NULL) {
+        llvm::Value* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0, "tmp"),"tmp");
+        llvm::Value* rl = DtoConstSize_t(0);
+        llvm::Value* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
+
+        llvm::Value* lp = gIR->ir->CreateLoad(DtoGEPi(l, 0,1, "tmp"),"tmp");
+        const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(lp->getType());
+        llvm::Value* rp = llvm::ConstantPointerNull::get(pty);
+        llvm::Value* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
+
+        llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
+        return b;
+    }
+    else {
+        assert(l->getType() == r->getType());
+
+        llvm::Value* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0, "tmp"),"tmp");
+        llvm::Value* rl = gIR->ir->CreateLoad(DtoGEPi(r, 0,0, "tmp"),"tmp");
+        llvm::Value* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
+
+        llvm::Value* lp = gIR->ir->CreateLoad(DtoGEPi(l, 0,1, "tmp"),"tmp");
+        llvm::Value* rp = gIR->ir->CreateLoad(DtoGEPi(r, 0,1, "tmp"),"tmp");
+        llvm::Value* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
+
+        llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
+        return b;
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Constant* DtoConstStaticArray(const llvm::Type* t, llvm::Constant* c)
+{
+    assert(llvm::isa<llvm::ArrayType>(t));
+    const llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(t);
+
+    if (llvm::isa<llvm::ArrayType>(at->getElementType()))
+    {
+        c = DtoConstStaticArray(at->getElementType(), c);
+    }
+    else {
+        assert(at->getElementType() == c->getType());
+    }
+    std::vector<llvm::Constant*> initvals;
+    initvals.resize(at->getNumElements(), c);
+    return llvm::ConstantArray::get(at, initvals);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Value* DtoArrayLen(DValue* v)
+{
+    Type* t = DtoDType(v->getType());
+    if (t->ty == Tarray) {
+        if (DSliceValue* s = v->isSlice()) {
+            if (s->len) return s->len;
+            DValue* next = new DVarValue(t,s->ptr,true);
+            return DtoArrayLen(next);
+        }
+        return DtoLoad(DtoGEPi(v->getRVal(), 0,0, "tmp"));
+    }
+    else if (t->ty == Tsarray) {
+        const llvm::ArrayType* t = llvm::cast<llvm::ArrayType>(v->getLVal()->getType());
+        return DtoConstSize_t(t->getNumElements());
+    }
+    assert(0);
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Value* DtoArrayPtr(DValue* v)
+{
+    Type* t = DtoDType(v->getType());
+    if (t->ty == Tarray) {
+        if (DSliceValue* s = v->isSlice()) {
+            if (s->len) return s->ptr;
+            DValue* next = new DVarValue(t,s->ptr,true);
+            return DtoArrayPtr(next);
+        }
+        return DtoLoad(DtoGEPi(v->getRVal(), 0,1, "tmp"));
+    }
+    else if (t->ty == Tsarray) {
+        return DtoGEPi(v->getRVal(), 0,0, "tmp");
+    }
+    assert(0);
+    return 0;
+}
+
--- a/gen/arrays.h	Fri Nov 02 06:32:32 2007 +0100
+++ b/gen/arrays.h	Sat Nov 03 14:44:58 2007 +0100
@@ -1,6 +1,8 @@
 #ifndef LLVMC_GEN_ARRAYS_H
 #define LLVMC_GEN_ARRAYS_H
 
+struct DSliceValue;
+
 const llvm::StructType* DtoArrayType(Type* t);
 const llvm::ArrayType* DtoStaticArrayType(Type* t);
 
@@ -8,7 +10,8 @@
 llvm::Constant* DtoConstSlice(llvm::Constant* dim, llvm::Constant* ptr);
 llvm::Constant* DtoConstStaticArray(const llvm::Type* t, llvm::Constant* c);
 
-void DtoArrayCopy(elem* dst, elem* src);
+void DtoArrayCopy(DSliceValue* dst, DSliceValue* src);
+
 void DtoArrayInit(llvm::Value* l, llvm::Value* r);
 void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val);
 void DtoArrayAssign(llvm::Value* l, llvm::Value* r);
@@ -16,9 +19,10 @@
 void DtoNullArray(llvm::Value* v);
 
 llvm::Value* DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool doinit=true);
-void DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz);
+llvm::Value* DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz);
 
 void DtoCatAssignElement(llvm::Value* arr, Expression* exp);
+void DtoCatAssignArray(llvm::Value* arr, Expression* exp);
 void DtoCatArrays(llvm::Value* arr, Expression* e1, Expression* e2);
 
 void DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src);
@@ -30,4 +34,7 @@
 
 llvm::Value* DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty);
 
+llvm::Value* DtoArrayLen(DValue* v);
+llvm::Value* DtoArrayPtr(DValue* v);
+
 #endif // LLVMC_GEN_ARRAYS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/binops.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,56 @@
+#include "gen/llvm.h"
+
+#include "declaration.h"
+
+#include "gen/irstate.h"
+#include "gen/dvalue.h"
+
+DValue* DtoBinAdd(DValue* lhs, DValue* rhs)
+{
+    llvm::Value* v = gIR->ir->CreateAdd(lhs->getRVal(), rhs->getRVal(), "tmp");
+    return new DImValue( lhs->getType(), v );
+}
+
+DValue* DtoBinSub(DValue* lhs, DValue* rhs)
+{
+    llvm::Value* v = gIR->ir->CreateSub(lhs->getRVal(), rhs->getRVal(), "tmp");
+    return new DImValue( lhs->getType(), v );
+}
+
+DValue* DtoBinMul(DValue* lhs, DValue* rhs)
+{
+    llvm::Value* v = gIR->ir->CreateMul(lhs->getRVal(), rhs->getRVal(), "tmp");
+    return new DImValue( lhs->getType(), v );
+}
+
+DValue* DtoBinDiv(DValue* lhs, DValue* rhs)
+{
+    Type* t = lhs->getType();
+    llvm::Value *l, *r;
+    l = lhs->getRVal();
+    r = rhs->getRVal();
+    llvm::Value* res;
+    if (t->isfloating())
+        res = gIR->ir->CreateFDiv(l, r, "tmp");
+    else if (!t->isunsigned())
+        res = gIR->ir->CreateSDiv(l, r, "tmp");
+    else
+        res = gIR->ir->CreateUDiv(l, r, "tmp");
+    return new DImValue( lhs->getType(), res );
+}
+
+DValue* DtoBinRem(DValue* lhs, DValue* rhs)
+{
+    Type* t = lhs->getType();
+    llvm::Value *l, *r;
+    l = lhs->getRVal();
+    r = rhs->getRVal();
+    llvm::Value* res;
+    if (t->isfloating())
+        res = gIR->ir->CreateFRem(l, r, "tmp");
+    else if (!t->isunsigned())
+        res = gIR->ir->CreateSRem(l, r, "tmp");
+    else
+        res = gIR->ir->CreateURem(l, r, "tmp");
+    return new DImValue( lhs->getType(), res );
+}
--- a/gen/dwarftypes.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,187 +0,0 @@
-// Generated by llvm2cpp - DO NOT MODIFY!
-
-#include <llvm/Module.h>
-#include <llvm/DerivedTypes.h>
-#include <llvm/Constants.h>
-#include <llvm/GlobalVariable.h>
-#include <llvm/Function.h>
-#include <llvm/CallingConv.h>
-#include <llvm/BasicBlock.h>
-#include <llvm/Instructions.h>
-#include <llvm/InlineAsm.h>
-#include <llvm/ParameterAttributes.h>
-#include <llvm/Support/MathExtras.h>
-#include <llvm/Pass.h>
-#include <llvm/PassManager.h>
-#include <llvm/Analysis/Verifier.h>
-#include <llvm/Assembly/PrintModulePass.h>
-#include <algorithm>
-#include <iostream>
-
-void RegisterDwarfSymbols(llvm::Module* mod) {
-  using namespace llvm;
-  // Type Definitions
-  std::vector<const Type*>StructTy_llvm_dbg_anchor_type_fields;
-  StructTy_llvm_dbg_anchor_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_anchor_type_fields.push_back(IntegerType::get(32));
-  StructType* StructTy_llvm_dbg_anchor_type = StructType::get(StructTy_llvm_dbg_anchor_type_fields, /*isPacked=*/false);
-  mod->addTypeName("llvm.dbg.anchor.type", StructTy_llvm_dbg_anchor_type);
-  
-  std::vector<const Type*>StructTy_llvm_dbg_basictype_type_fields;
-  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(32));
-  std::vector<const Type*>StructTy_1_fields;
-  StructType* StructTy_1 = StructType::get(StructTy_1_fields, /*isPacked=*/false);
-  
-  PointerType* PointerTy_0 = PointerType::get(StructTy_1);
-  
-  StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_0);
-  PointerType* PointerTy_2 = PointerType::get(IntegerType::get(8));
-  
-  StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_2);
-  StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(64));
-  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(64));
-  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(64));
-  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(32));
-  StructType* StructTy_llvm_dbg_basictype_type = StructType::get(StructTy_llvm_dbg_basictype_type_fields, /*isPacked=*/false);
-  mod->addTypeName("llvm.dbg.basictype.type", StructTy_llvm_dbg_basictype_type);
-  
-  std::vector<const Type*>StructTy_llvm_dbg_compile_unit_type_fields;
-  StructTy_llvm_dbg_compile_unit_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_compile_unit_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_compile_unit_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_compile_unit_type_fields.push_back(PointerTy_2);
-  StructTy_llvm_dbg_compile_unit_type_fields.push_back(PointerTy_2);
-  StructTy_llvm_dbg_compile_unit_type_fields.push_back(PointerTy_2);
-  StructType* StructTy_llvm_dbg_compile_unit_type = StructType::get(StructTy_llvm_dbg_compile_unit_type_fields, /*isPacked=*/false);
-  mod->addTypeName("llvm.dbg.compile_unit.type", StructTy_llvm_dbg_compile_unit_type);
-  
-  std::vector<const Type*>StructTy_llvm_dbg_compositetype_type_fields;
-  StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_2);
-  StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(64));
-  StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(64));
-  StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(64));
-  StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_0);
-  StructType* StructTy_llvm_dbg_compositetype_type = StructType::get(StructTy_llvm_dbg_compositetype_type_fields, /*isPacked=*/false);
-  mod->addTypeName("llvm.dbg.compositetype.type", StructTy_llvm_dbg_compositetype_type);
-  
-  std::vector<const Type*>StructTy_llvm_dbg_derivedtype_type_fields;
-  StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_derivedtype_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_derivedtype_type_fields.push_back(PointerTy_2);
-  StructTy_llvm_dbg_derivedtype_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(64));
-  StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(64));
-  StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(64));
-  StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_derivedtype_type_fields.push_back(PointerTy_0);
-  StructType* StructTy_llvm_dbg_derivedtype_type = StructType::get(StructTy_llvm_dbg_derivedtype_type_fields, /*isPacked=*/false);
-  mod->addTypeName("llvm.dbg.derivedtype.type", StructTy_llvm_dbg_derivedtype_type);
-  
-  std::vector<const Type*>StructTy_llvm_dbg_global_variable_type_fields;
-  StructTy_llvm_dbg_global_variable_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_2);
-  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_2);
-  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_2);
-  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_global_variable_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_global_variable_type_fields.push_back(IntegerType::get(1));
-  StructTy_llvm_dbg_global_variable_type_fields.push_back(IntegerType::get(1));
-  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0);
-  StructType* StructTy_llvm_dbg_global_variable_type = StructType::get(StructTy_llvm_dbg_global_variable_type_fields, /*isPacked=*/false);
-  mod->addTypeName("llvm.dbg.global_variable.type", StructTy_llvm_dbg_global_variable_type);
-  
-  std::vector<const Type*>StructTy_llvm_dbg_subprogram_type_fields;
-  StructTy_llvm_dbg_subprogram_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_2);
-  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_2);
-  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_2);
-  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_subprogram_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_subprogram_type_fields.push_back(IntegerType::get(1));
-  StructTy_llvm_dbg_subprogram_type_fields.push_back(IntegerType::get(1));
-  StructType* StructTy_llvm_dbg_subprogram_type = StructType::get(StructTy_llvm_dbg_subprogram_type_fields, /*isPacked=*/false);
-  mod->addTypeName("llvm.dbg.subprogram.type", StructTy_llvm_dbg_subprogram_type);
-  
-  std::vector<const Type*>StructTy_llvm_dbg_variable_type_fields;
-  StructTy_llvm_dbg_variable_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_variable_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_variable_type_fields.push_back(PointerTy_2);
-  StructTy_llvm_dbg_variable_type_fields.push_back(PointerTy_0);
-  StructTy_llvm_dbg_variable_type_fields.push_back(IntegerType::get(32));
-  StructTy_llvm_dbg_variable_type_fields.push_back(PointerTy_0);
-  StructType* StructTy_llvm_dbg_variable_type = StructType::get(StructTy_llvm_dbg_variable_type_fields, /*isPacked=*/false);
-  mod->addTypeName("llvm.dbg.variable.type", StructTy_llvm_dbg_variable_type);
-
-  std::vector<const Type*>FuncTy_3_args;
-  FuncTy_3_args.push_back(PointerTy_0);
-  ParamAttrsList *FuncTy_3_PAL = 0;
-  FunctionType* FuncTy_3 = FunctionType::get(
-    /*Result=*/Type::VoidTy,
-    /*Params=*/FuncTy_3_args,
-    /*isVarArg=*/false,
-    /*ParamAttrs=*/FuncTy_3_PAL);
-  
-  std::vector<const Type*>FuncTy_4_args;
-  FuncTy_4_args.push_back(IntegerType::get(32));
-  FuncTy_4_args.push_back(IntegerType::get(32));
-  FuncTy_4_args.push_back(PointerTy_0);
-  ParamAttrsList *FuncTy_4_PAL = 0;
-  FunctionType* FuncTy_4 = FunctionType::get(
-    /*Result=*/Type::VoidTy,
-    /*Params=*/FuncTy_4_args,
-    /*isVarArg=*/false,
-    /*ParamAttrs=*/FuncTy_4_PAL);
-  
-  std::vector<const Type*>FuncTy_5_args;
-  FuncTy_5_args.push_back(PointerTy_0);
-  FuncTy_5_args.push_back(PointerTy_0);
-  ParamAttrsList *FuncTy_5_PAL = 0;
-  FunctionType* FuncTy_5 = FunctionType::get(
-    /*Result=*/Type::VoidTy,
-    /*Params=*/FuncTy_5_args,
-    /*isVarArg=*/false,
-    /*ParamAttrs=*/FuncTy_5_PAL);
-  
-  
-  // Function Declarations
-  
-  Function* func_llvm_dbg_func_start = new Function(
-    /*Type=*/FuncTy_3,
-    /*Linkage=*/GlobalValue::ExternalLinkage,
-    /*Name=*/"llvm.dbg.func.start", mod); // (external, no body)
-  func_llvm_dbg_func_start->setCallingConv(CallingConv::C);
-  
-  Function* func_llvm_dbg_stoppoint = new Function(
-    /*Type=*/FuncTy_4,
-    /*Linkage=*/GlobalValue::ExternalLinkage,
-    /*Name=*/"llvm.dbg.stoppoint", mod); // (external, no body)
-  func_llvm_dbg_stoppoint->setCallingConv(CallingConv::C);
-  
-  Function* func_llvm_dbg_declare = new Function(
-    /*Type=*/FuncTy_5,
-    /*Linkage=*/GlobalValue::ExternalLinkage,
-    /*Name=*/"llvm.dbg.declare", mod); // (external, no body)
-  func_llvm_dbg_declare->setCallingConv(CallingConv::C);
-  
-  Function* func_llvm_dbg_region_end = new Function(
-    /*Type=*/FuncTy_3,
-    /*Linkage=*/GlobalValue::ExternalLinkage,
-    /*Name=*/"llvm.dbg.region.end", mod); // (external, no body)
-  func_llvm_dbg_region_end->setCallingConv(CallingConv::C);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/dwarftypes.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,187 @@
+// Generated by llvm2cpp - DO NOT MODIFY!
+
+#include <llvm/Module.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/Constants.h>
+#include <llvm/GlobalVariable.h>
+#include <llvm/Function.h>
+#include <llvm/CallingConv.h>
+#include <llvm/BasicBlock.h>
+#include <llvm/Instructions.h>
+#include <llvm/InlineAsm.h>
+#include <llvm/ParameterAttributes.h>
+#include <llvm/Support/MathExtras.h>
+#include <llvm/Pass.h>
+#include <llvm/PassManager.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Assembly/PrintModulePass.h>
+#include <algorithm>
+#include <iostream>
+
+void RegisterDwarfSymbols(llvm::Module* mod) {
+  using namespace llvm;
+  // Type Definitions
+  std::vector<const Type*>StructTy_llvm_dbg_anchor_type_fields;
+  StructTy_llvm_dbg_anchor_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_anchor_type_fields.push_back(IntegerType::get(32));
+  StructType* StructTy_llvm_dbg_anchor_type = StructType::get(StructTy_llvm_dbg_anchor_type_fields, /*isPacked=*/false);
+  mod->addTypeName("llvm.dbg.anchor.type", StructTy_llvm_dbg_anchor_type);
+  
+  std::vector<const Type*>StructTy_llvm_dbg_basictype_type_fields;
+  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(32));
+  std::vector<const Type*>StructTy_1_fields;
+  StructType* StructTy_1 = StructType::get(StructTy_1_fields, /*isPacked=*/false);
+  
+  PointerType* PointerTy_0 = PointerType::get(StructTy_1);
+  
+  StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_0);
+  PointerType* PointerTy_2 = PointerType::get(IntegerType::get(8));
+  
+  StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_2);
+  StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(64));
+  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(64));
+  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(64));
+  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_basictype_type_fields.push_back(IntegerType::get(32));
+  StructType* StructTy_llvm_dbg_basictype_type = StructType::get(StructTy_llvm_dbg_basictype_type_fields, /*isPacked=*/false);
+  mod->addTypeName("llvm.dbg.basictype.type", StructTy_llvm_dbg_basictype_type);
+  
+  std::vector<const Type*>StructTy_llvm_dbg_compile_unit_type_fields;
+  StructTy_llvm_dbg_compile_unit_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_compile_unit_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_compile_unit_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_compile_unit_type_fields.push_back(PointerTy_2);
+  StructTy_llvm_dbg_compile_unit_type_fields.push_back(PointerTy_2);
+  StructTy_llvm_dbg_compile_unit_type_fields.push_back(PointerTy_2);
+  StructType* StructTy_llvm_dbg_compile_unit_type = StructType::get(StructTy_llvm_dbg_compile_unit_type_fields, /*isPacked=*/false);
+  mod->addTypeName("llvm.dbg.compile_unit.type", StructTy_llvm_dbg_compile_unit_type);
+  
+  std::vector<const Type*>StructTy_llvm_dbg_compositetype_type_fields;
+  StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_2);
+  StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(64));
+  StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(64));
+  StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(64));
+  StructTy_llvm_dbg_compositetype_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_compositetype_type_fields.push_back(PointerTy_0);
+  StructType* StructTy_llvm_dbg_compositetype_type = StructType::get(StructTy_llvm_dbg_compositetype_type_fields, /*isPacked=*/false);
+  mod->addTypeName("llvm.dbg.compositetype.type", StructTy_llvm_dbg_compositetype_type);
+  
+  std::vector<const Type*>StructTy_llvm_dbg_derivedtype_type_fields;
+  StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_derivedtype_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_derivedtype_type_fields.push_back(PointerTy_2);
+  StructTy_llvm_dbg_derivedtype_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(64));
+  StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(64));
+  StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(64));
+  StructTy_llvm_dbg_derivedtype_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_derivedtype_type_fields.push_back(PointerTy_0);
+  StructType* StructTy_llvm_dbg_derivedtype_type = StructType::get(StructTy_llvm_dbg_derivedtype_type_fields, /*isPacked=*/false);
+  mod->addTypeName("llvm.dbg.derivedtype.type", StructTy_llvm_dbg_derivedtype_type);
+  
+  std::vector<const Type*>StructTy_llvm_dbg_global_variable_type_fields;
+  StructTy_llvm_dbg_global_variable_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_2);
+  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_2);
+  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_2);
+  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_global_variable_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_global_variable_type_fields.push_back(IntegerType::get(1));
+  StructTy_llvm_dbg_global_variable_type_fields.push_back(IntegerType::get(1));
+  StructTy_llvm_dbg_global_variable_type_fields.push_back(PointerTy_0);
+  StructType* StructTy_llvm_dbg_global_variable_type = StructType::get(StructTy_llvm_dbg_global_variable_type_fields, /*isPacked=*/false);
+  mod->addTypeName("llvm.dbg.global_variable.type", StructTy_llvm_dbg_global_variable_type);
+  
+  std::vector<const Type*>StructTy_llvm_dbg_subprogram_type_fields;
+  StructTy_llvm_dbg_subprogram_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_2);
+  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_2);
+  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_2);
+  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_subprogram_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_subprogram_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_subprogram_type_fields.push_back(IntegerType::get(1));
+  StructTy_llvm_dbg_subprogram_type_fields.push_back(IntegerType::get(1));
+  StructType* StructTy_llvm_dbg_subprogram_type = StructType::get(StructTy_llvm_dbg_subprogram_type_fields, /*isPacked=*/false);
+  mod->addTypeName("llvm.dbg.subprogram.type", StructTy_llvm_dbg_subprogram_type);
+  
+  std::vector<const Type*>StructTy_llvm_dbg_variable_type_fields;
+  StructTy_llvm_dbg_variable_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_variable_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_variable_type_fields.push_back(PointerTy_2);
+  StructTy_llvm_dbg_variable_type_fields.push_back(PointerTy_0);
+  StructTy_llvm_dbg_variable_type_fields.push_back(IntegerType::get(32));
+  StructTy_llvm_dbg_variable_type_fields.push_back(PointerTy_0);
+  StructType* StructTy_llvm_dbg_variable_type = StructType::get(StructTy_llvm_dbg_variable_type_fields, /*isPacked=*/false);
+  mod->addTypeName("llvm.dbg.variable.type", StructTy_llvm_dbg_variable_type);
+
+  std::vector<const Type*>FuncTy_3_args;
+  FuncTy_3_args.push_back(PointerTy_0);
+  ParamAttrsList *FuncTy_3_PAL = 0;
+  FunctionType* FuncTy_3 = FunctionType::get(
+    /*Result=*/Type::VoidTy,
+    /*Params=*/FuncTy_3_args,
+    /*isVarArg=*/false,
+    /*ParamAttrs=*/FuncTy_3_PAL);
+  
+  std::vector<const Type*>FuncTy_4_args;
+  FuncTy_4_args.push_back(IntegerType::get(32));
+  FuncTy_4_args.push_back(IntegerType::get(32));
+  FuncTy_4_args.push_back(PointerTy_0);
+  ParamAttrsList *FuncTy_4_PAL = 0;
+  FunctionType* FuncTy_4 = FunctionType::get(
+    /*Result=*/Type::VoidTy,
+    /*Params=*/FuncTy_4_args,
+    /*isVarArg=*/false,
+    /*ParamAttrs=*/FuncTy_4_PAL);
+  
+  std::vector<const Type*>FuncTy_5_args;
+  FuncTy_5_args.push_back(PointerTy_0);
+  FuncTy_5_args.push_back(PointerTy_0);
+  ParamAttrsList *FuncTy_5_PAL = 0;
+  FunctionType* FuncTy_5 = FunctionType::get(
+    /*Result=*/Type::VoidTy,
+    /*Params=*/FuncTy_5_args,
+    /*isVarArg=*/false,
+    /*ParamAttrs=*/FuncTy_5_PAL);
+  
+  
+  // Function Declarations
+  
+  Function* func_llvm_dbg_func_start = new Function(
+    /*Type=*/FuncTy_3,
+    /*Linkage=*/GlobalValue::ExternalLinkage,
+    /*Name=*/"llvm.dbg.func.start", mod); // (external, no body)
+  func_llvm_dbg_func_start->setCallingConv(CallingConv::C);
+  
+  Function* func_llvm_dbg_stoppoint = new Function(
+    /*Type=*/FuncTy_4,
+    /*Linkage=*/GlobalValue::ExternalLinkage,
+    /*Name=*/"llvm.dbg.stoppoint", mod); // (external, no body)
+  func_llvm_dbg_stoppoint->setCallingConv(CallingConv::C);
+  
+  Function* func_llvm_dbg_declare = new Function(
+    /*Type=*/FuncTy_5,
+    /*Linkage=*/GlobalValue::ExternalLinkage,
+    /*Name=*/"llvm.dbg.declare", mod); // (external, no body)
+  func_llvm_dbg_declare->setCallingConv(CallingConv::C);
+  
+  Function* func_llvm_dbg_region_end = new Function(
+    /*Type=*/FuncTy_3,
+    /*Linkage=*/GlobalValue::ExternalLinkage,
+    /*Name=*/"llvm.dbg.region.end", mod); // (external, no body)
+  func_llvm_dbg_region_end->setCallingConv(CallingConv::C);
+}
--- a/gen/elem.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-#include <iostream>
-
-#include "gen/llvm.h"
-
-#include "gen/elem.h"
-#include "gen/irstate.h"
-#include "gen/logger.h"
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem::elem()
-{
-    mem = 0;
-    val = 0;
-    arg = 0;
-
-    type = NONE;
-    inplace = false;
-    field = false;
-    callconv = (unsigned)-1;
-    isthis = false;
-    istypeinfo = false;
-    temp = false;
-
-    vardecl = 0;
-    funcdecl = 0;
-}
-
-llvm::Value* elem::getValue()
-{
-    assert(val || mem);
-    switch(type)
-    {
-    case NONE:
-        assert(0 && "type == NONE");
-        break;
-
-    case VAR:
-    case REF:
-    case ARRAYLEN:
-        if (val) {
-            return val;
-        }
-        else {
-            if (!llvm::isa<llvm::PointerType>(mem->getType()))
-            {
-                Logger::cout() << "unexpected type: " << *mem->getType() << '\n';
-                assert(0);
-            }
-            const llvm::PointerType* pt = llvm::cast<llvm::PointerType>(mem->getType());
-            if (!pt->getElementType()->isFirstClassType()) {
-                return mem;
-            }
-            else {
-                return gIR->ir->CreateLoad(mem, "tmp");
-            }
-        }
-
-    case VAL:
-    case NUL:
-    case FUNC:
-    case CONST:
-    case SLICE:
-        return val ? val : mem;
-    }
-    assert(0 && "type == invalid value");
-    return 0;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/elem.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,85 @@
+/*
+#include <iostream>
+
+#include "gen/llvm.h"
+
+#include "gen/elem.h"
+#include "gen/irstate.h"
+#include "gen/logger.h"
+#include "gen/dvalue.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+elem::elem(Expression* e)
+{
+    exp = e;
+
+    mem = 0;
+    val = 0;
+    arg = 0;
+
+    type = NONE;
+    inplace = false;
+    field = false;
+    callconv = (unsigned)-1;
+    isthis = false;
+    istypeinfo = false;
+    temp = false;
+
+    vardecl = 0;
+    funcdecl = 0;
+
+    dvalue = 0;
+}
+
+elem::~elem()
+{
+    delete dvalue;
+}
+
+llvm::Value* elem::getValue()
+{
+    if (dvalue && !dvalue->isSlice()) {
+        Logger::println("HAS DVALUE");
+        return dvalue->getRVal();
+    }
+
+    assert(val || mem);
+    switch(type)
+    {
+    case NONE:
+        assert(0 && "type == NONE");
+        break;
+
+    case VAR:
+    case REF:
+    case ARRAYLEN:
+        if (val) {
+            return val;
+        }
+        else {
+            if (!llvm::isa<llvm::PointerType>(mem->getType()))
+            {
+                Logger::cout() << "unexpected type: " << *mem->getType() << '\n';
+                assert(0);
+            }
+            const llvm::PointerType* pt = llvm::cast<llvm::PointerType>(mem->getType());
+            if (!pt->getElementType()->isFirstClassType()) {
+                return mem;
+            }
+            else {
+                return gIR->ir->CreateLoad(mem, "tmp");
+            }
+        }
+
+    case VAL:
+    case NUL:
+    case FUNC:
+    case CONST:
+    case SLICE:
+        return val ? val : mem;
+    }
+    assert(0 && "type == invalid value");
+    return 0;
+}
+*/
--- a/gen/elem.h	Fri Nov 02 06:32:32 2007 +0100
+++ b/gen/elem.h	Sat Nov 03 14:44:58 2007 +0100
@@ -1,10 +1,17 @@
 #ifndef LLVMDC_GEN_ELEM_H
 #define LLVMDC_GEN_ELEM_H
 
+#include "dvalue.h"
+typedef DValue elem;
+
+/*
+
 #include "root.h"
 #include "declaration.h"
 #include "aggregate.h"
 
+struct DValue;
+
 // represents a value. be it a constant literal, a variable etc.
 // maintains all the information for doing load/store appropriately
 struct elem : Object
@@ -22,7 +29,10 @@
     };
 
 public:
-    elem();
+    elem(Expression* e);
+    virtual ~elem();
+
+    Expression* exp;
 
     llvm::Value* mem;
     llvm::Value* val;
@@ -41,7 +51,11 @@
     llvm::Value* getValue();
     //llvm::Value* getMemory();
 
+    DValue* dvalue;
+
     bool isNull()   {return !(mem || val);}
 };
 
+*/
+
 #endif // LLVMDC_GEN_ELEM_H
--- a/gen/irstate.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,172 +0,0 @@
-/* DMDFE backend stubs
- * This file contains the implementations of the backend routines.
- * For dmdfe these do nothing but print a message saying the module
- * has been parsed. Substitute your own behaviors for these routimes.
- */
-
-#include <cstdarg>
-
-#include "gen/llvm.h"
-
-#include "mtype.h"
-#include "declaration.h"
-
-#include "gen/irstate.h"
-#include "tollvm.h"
-
-IRState* gIR = 0;
-const llvm::TargetData* gTargetData = 0;
-
-//////////////////////////////////////////////////////////////////////////////////////////
-IRScope::IRScope()
-{
-    begin = end = NULL;
-}
-
-IRScope::IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e)
-{
-    begin = b;
-    end = e;
-    builder.SetInsertPoint(b);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-IRState::IRState()
-{
-    dmodule = 0;
-    module = 0;
-    emitMain = false;
-    mainFunc = 0;
-    ir.state = this;
-    dwarfCompileUnit = 0;
-}
-
-IRFunction& IRState::func()
-{
-    assert(!functions.empty() && "Function stack is empty!");
-    return functions.back();
-}
-
-llvm::Function* IRState::topfunc()
-{
-    assert(!functions.empty() && "Function stack is empty!");
-    return functions.back().func;
-}
-
-TypeFunction* IRState::topfunctype()
-{
-    assert(!functions.empty() && "Function stack is empty!");
-    return functions.back().type;
-}
-
-llvm::Instruction* IRState::topallocapoint()
-{
-    assert(!functions.empty() && "AllocaPoint stack is empty!");
-    return functions.back().allocapoint;
-}
-
-IRStruct& IRState::topstruct()
-{
-    assert(!structs.empty() && "Struct vector is empty!");
-    return structs.back();
-}
-
-IRExp* IRState::topexp()
-{
-    return exps.empty() ? NULL : &exps.back();
-}
-
-IRScope& IRState::scope()
-{
-    assert(!scopes.empty());
-    return scopes.back();
-}
-
-llvm::BasicBlock* IRState::scopebb()
-{
-    return scopebegin();
-}
-llvm::BasicBlock* IRState::scopebegin()
-{
-    IRScope& s = scope();
-    assert(s.begin);
-    return s.begin;
-}
-llvm::BasicBlock* IRState::scopeend()
-{
-    IRScope& s = scope();
-    assert(s.end);
-    return s.end;
-}
-bool IRState::scopereturned()
-{
-    //return scope().returned;
-    return !scopebb()->empty() && scopebb()->back().isTerminator();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-IRStruct::IRStruct()
- : recty(llvm::OpaqueType::get())
-{
-    type = 0;
-    queueFuncs = true;
-}
-
-IRStruct::IRStruct(Type* t)
- : recty(llvm::OpaqueType::get())
-{
-    type = t;
-    queueFuncs = true;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-IRFinally::IRFinally()
-{
-    bb = 0;
-    retbb = 0;
-}
-
-IRFinally::IRFinally(llvm::BasicBlock* b, llvm::BasicBlock* rb)
-{
-    bb = b;
-    retbb = rb;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-LLVMBuilder* IRBuilderHelper::operator->()
-{
-    LLVMBuilder& b = state->scope().builder;
-    assert(b.GetInsertBlock() != NULL);
-    return &b;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-IRFunction::IRFunction(FuncDeclaration* fd)
-{
-    decl = fd;
-    Type* t = DtoDType(fd->type);
-    assert(t->ty == Tfunction);
-    type = (TypeFunction*)t;
-    func = NULL;
-    allocapoint = NULL;
-    finallyretval = NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-IRExp::IRExp()
-{
-    e1 = e2 = NULL;
-    v = NULL;
-}
-
-IRExp::IRExp(Expression* l, Expression* r, llvm::Value* val)
-{
-    e1 = l;
-    e2 = r;
-    v = val;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/irstate.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,172 @@
+/* DMDFE backend stubs
+ * This file contains the implementations of the backend routines.
+ * For dmdfe these do nothing but print a message saying the module
+ * has been parsed. Substitute your own behaviors for these routimes.
+ */
+
+#include <cstdarg>
+
+#include "gen/llvm.h"
+
+#include "mtype.h"
+#include "declaration.h"
+
+#include "gen/irstate.h"
+#include "tollvm.h"
+
+IRState* gIR = 0;
+const llvm::TargetData* gTargetData = 0;
+
+//////////////////////////////////////////////////////////////////////////////////////////
+IRScope::IRScope()
+{
+    begin = end = NULL;
+}
+
+IRScope::IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e)
+{
+    begin = b;
+    end = e;
+    builder.SetInsertPoint(b);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+IRState::IRState()
+{
+    dmodule = 0;
+    module = 0;
+    emitMain = false;
+    mainFunc = 0;
+    ir.state = this;
+    dwarfCompileUnit = 0;
+}
+
+IRFunction& IRState::func()
+{
+    assert(!functions.empty() && "Function stack is empty!");
+    return functions.back();
+}
+
+llvm::Function* IRState::topfunc()
+{
+    assert(!functions.empty() && "Function stack is empty!");
+    return functions.back().func;
+}
+
+TypeFunction* IRState::topfunctype()
+{
+    assert(!functions.empty() && "Function stack is empty!");
+    return functions.back().type;
+}
+
+llvm::Instruction* IRState::topallocapoint()
+{
+    assert(!functions.empty() && "AllocaPoint stack is empty!");
+    return functions.back().allocapoint;
+}
+
+IRStruct& IRState::topstruct()
+{
+    assert(!structs.empty() && "Struct vector is empty!");
+    return structs.back();
+}
+
+IRExp* IRState::topexp()
+{
+    return exps.empty() ? NULL : &exps.back();
+}
+
+IRScope& IRState::scope()
+{
+    assert(!scopes.empty());
+    return scopes.back();
+}
+
+llvm::BasicBlock* IRState::scopebb()
+{
+    return scopebegin();
+}
+llvm::BasicBlock* IRState::scopebegin()
+{
+    IRScope& s = scope();
+    assert(s.begin);
+    return s.begin;
+}
+llvm::BasicBlock* IRState::scopeend()
+{
+    IRScope& s = scope();
+    assert(s.end);
+    return s.end;
+}
+bool IRState::scopereturned()
+{
+    //return scope().returned;
+    return !scopebb()->empty() && scopebb()->back().isTerminator();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+IRStruct::IRStruct()
+ : recty(llvm::OpaqueType::get())
+{
+    type = 0;
+    queueFuncs = true;
+}
+
+IRStruct::IRStruct(Type* t)
+ : recty(llvm::OpaqueType::get())
+{
+    type = t;
+    queueFuncs = true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+IRFinally::IRFinally()
+{
+    bb = 0;
+    retbb = 0;
+}
+
+IRFinally::IRFinally(llvm::BasicBlock* b, llvm::BasicBlock* rb)
+{
+    bb = b;
+    retbb = rb;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+LLVMBuilder* IRBuilderHelper::operator->()
+{
+    LLVMBuilder& b = state->scope().builder;
+    assert(b.GetInsertBlock() != NULL);
+    return &b;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+IRFunction::IRFunction(FuncDeclaration* fd)
+{
+    decl = fd;
+    Type* t = DtoDType(fd->type);
+    assert(t->ty == Tfunction);
+    type = (TypeFunction*)t;
+    func = NULL;
+    allocapoint = NULL;
+    finallyretval = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+IRExp::IRExp()
+{
+    e1 = e2 = NULL;
+    v = NULL;
+}
+
+IRExp::IRExp(Expression* l, Expression* r, DValue* val)
+{
+    e1 = l;
+    e2 = r;
+    v = val;
+}
--- a/gen/irstate.h	Fri Nov 02 06:32:32 2007 +0100
+++ b/gen/irstate.h	Sat Nov 03 14:44:58 2007 +0100
@@ -101,9 +101,9 @@
 {
     Expression* e1;
     Expression* e2;
-    llvm::Value* v;
+    DValue* v;
     IRExp();
-    IRExp(Expression* l, Expression* r, llvm::Value* val);
+    IRExp(Expression* l, Expression* r, DValue* val);
 };
 
 // represents the module
@@ -158,7 +158,7 @@
     // might be a better way but it works. problem is I only get a
     // VarDeclaration for __dollar, but I can't see how to get the
     // array pointer from this :(
-    std::vector<llvm::Value*> arrays;
+    std::vector<DValue*> arrays;
 
     // builder helper
     IRBuilderHelper ir;
--- a/gen/logger.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-#include <cassert>
-#include <cstdarg>
-#include <cstdio>
-#include <cstdlib>
-#include <iostream>
-#include <fstream>
-#include <string>
-
-#include "gen/logger.h"
-
-namespace Logger
-{
-    static std::string indent_str;
-    static std::ofstream null_out("/dev/null");
-
-    static bool enabled = false;
-    void indent()
-    {
-        if (enabled)
-        indent_str += "  ";
-    }
-    void undent()
-    {
-        if (enabled) {
-            assert(!indent_str.empty());
-            indent_str.resize(indent_str.size()-2);
-        }
-    }
-    std::ostream& cout()
-    {
-        if (enabled)
-            return std::cout << indent_str;
-        else
-            return null_out;
-    }
-    void println(const char* fmt,...)
-    {
-        if (enabled) {
-            printf(indent_str.c_str());
-            va_list va;
-            va_start(va,fmt);
-            vprintf(fmt,va);
-            va_end(va);
-            printf("\n");
-        }
-    }
-    void print(const char* fmt,...)
-    {
-        if (enabled) {
-            printf(indent_str.c_str());
-            va_list va;
-            va_start(va,fmt);
-            vprintf(fmt,va);
-            va_end(va);
-        }
-    }
-    void enable()
-    {
-        enabled = true;
-    }
-    void disable()
-    {
-        enabled = false;
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/logger.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,66 @@
+#include <cassert>
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "gen/logger.h"
+
+namespace Logger
+{
+    static std::string indent_str;
+    static std::ofstream null_out("/dev/null");
+
+    static bool enabled = false;
+    void indent()
+    {
+        if (enabled)
+        indent_str += "  ";
+    }
+    void undent()
+    {
+        if (enabled) {
+            assert(!indent_str.empty());
+            indent_str.resize(indent_str.size()-2);
+        }
+    }
+    std::ostream& cout()
+    {
+        if (enabled)
+            return std::cout << indent_str;
+        else
+            return null_out;
+    }
+    void println(const char* fmt,...)
+    {
+        if (enabled) {
+            printf(indent_str.c_str());
+            va_list va;
+            va_start(va,fmt);
+            vprintf(fmt,va);
+            va_end(va);
+            printf("\n");
+        }
+    }
+    void print(const char* fmt,...)
+    {
+        if (enabled) {
+            printf(indent_str.c_str());
+            va_list va;
+            va_start(va,fmt);
+            vprintf(fmt,va);
+            va_end(va);
+        }
+    }
+    void enable()
+    {
+        enabled = true;
+    }
+    void disable()
+    {
+        enabled = false;
+    }
+}
+
--- a/gen/runtime.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-#include <cassert>
-
-#include "gen/llvm.h"
-#include "llvm/Module.h"
-#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/Support/MemoryBuffer.h"
-
-#include "root.h"
-#include "mars.h"
-
-#include "gen/runtime.h"
-#include "gen/logger.h"
-
-static llvm::Module* M = NULL;
-static bool runtime_failed = false;
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-bool LLVM_D_InitRuntime()
-{
-    Logger::println("*** Loading D runtime ***");
-    LOG_SCOPE;
-
-    if (!global.params.runtimeImppath) {
-        error("You must set the runtime import path with -E");
-        fatal();
-    }
-    std::string filename(global.params.runtimeImppath);
-    filename.append("/llvmdcore.bc");
-    llvm::MemoryBuffer* buffer = llvm::MemoryBuffer::getFile(filename.c_str(), filename.length());
-    if (!buffer) {
-        Logger::println("Failed to load runtime library from disk");
-        runtime_failed = true;
-        return false;
-    }
-
-    std::string errstr;
-    bool retval = false;
-    M = llvm::ParseBitcodeFile(buffer, &errstr);
-    if (M) {
-        retval = true;
-    }
-    else {
-        Logger::println("Failed to load runtime: %s", errstr.c_str());
-        runtime_failed = true;
-    }
-
-    delete buffer;
-    return retval;
-}
-
-void LLVM_D_FreeRuntime()
-{
-    if (M) {
-        Logger::println("*** Freeing D runtime ***");
-        delete M;
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name)
-{
-    // TODO maybe check the target module first, to allow overriding the runtime on a pre module basis?
-    // could be done and seems like it could be neat too :)
-
-    if (global.params.noruntime) {
-        error("No implicit runtime calls allowed with -noruntime option enabled");
-        fatal();
-    }
-
-    if (!M) {
-        assert(!runtime_failed);
-        LLVM_D_InitRuntime();
-    }
-
-    llvm::Function* fn = M->getFunction(name);
-    if (!fn) {
-        error("Runtime function '%s' was not found", name);
-        fatal();
-        //return NULL;
-    }
-
-    const llvm::FunctionType* fnty = fn->getFunctionType();
-    return llvm::cast<llvm::Function>(target->getOrInsertFunction(name, fnty));
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char* name)
-{
-    // TODO maybe check the target module first, to allow overriding the runtime on a pre module basis?
-    // could be done and seems like it could be neat too :)
-
-    llvm::GlobalVariable* gv = target->getNamedGlobal(name);
-    if (gv) {
-        return gv;
-    }
-
-    if (global.params.noruntime) {
-        error("No implicit runtime calls allowed with -noruntime option enabled");
-        fatal();
-    }
-
-    if (!M) {
-        assert(!runtime_failed);
-        LLVM_D_InitRuntime();
-    }
-
-    llvm::GlobalVariable* g = M->getNamedGlobal(name);
-    if (!g) {
-        error("Runtime global '%s' was not found", name);
-        fatal();
-        //return NULL;
-    }
-
-    const llvm::PointerType* t = g->getType();
-    return new llvm::GlobalVariable(t->getElementType(),g->isConstant(),g->getLinkage(),NULL,g->getName(),target);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/runtime.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,119 @@
+#include <cassert>
+
+#include "gen/llvm.h"
+#include "llvm/Module.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include "root.h"
+#include "mars.h"
+
+#include "gen/runtime.h"
+#include "gen/logger.h"
+
+static llvm::Module* M = NULL;
+static bool runtime_failed = false;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool LLVM_D_InitRuntime()
+{
+    Logger::println("*** Loading D runtime ***");
+    LOG_SCOPE;
+
+    if (!global.params.runtimeImppath) {
+        error("You must set the runtime import path with -E");
+        fatal();
+    }
+    std::string filename(global.params.runtimeImppath);
+    filename.append("/llvmdcore.bc");
+    llvm::MemoryBuffer* buffer = llvm::MemoryBuffer::getFile(filename.c_str(), filename.length());
+    if (!buffer) {
+        Logger::println("Failed to load runtime library from disk");
+        runtime_failed = true;
+        return false;
+    }
+
+    std::string errstr;
+    bool retval = false;
+    M = llvm::ParseBitcodeFile(buffer, &errstr);
+    if (M) {
+        retval = true;
+    }
+    else {
+        Logger::println("Failed to load runtime: %s", errstr.c_str());
+        runtime_failed = true;
+    }
+
+    delete buffer;
+    return retval;
+}
+
+void LLVM_D_FreeRuntime()
+{
+    if (M) {
+        Logger::println("*** Freeing D runtime ***");
+        delete M;
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name)
+{
+    // TODO maybe check the target module first, to allow overriding the runtime on a pre module basis?
+    // could be done and seems like it could be neat too :)
+
+    if (global.params.noruntime) {
+        error("No implicit runtime calls allowed with -noruntime option enabled");
+        fatal();
+    }
+
+    if (!M) {
+        assert(!runtime_failed);
+        LLVM_D_InitRuntime();
+    }
+
+    llvm::Function* fn = M->getFunction(name);
+    if (!fn) {
+        error("Runtime function '%s' was not found", name);
+        fatal();
+        //return NULL;
+    }
+
+    const llvm::FunctionType* fnty = fn->getFunctionType();
+    return llvm::cast<llvm::Function>(target->getOrInsertFunction(name, fnty));
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char* name)
+{
+    // TODO maybe check the target module first, to allow overriding the runtime on a pre module basis?
+    // could be done and seems like it could be neat too :)
+
+    llvm::GlobalVariable* gv = target->getNamedGlobal(name);
+    if (gv) {
+        return gv;
+    }
+
+    if (global.params.noruntime) {
+        error("No implicit runtime calls allowed with -noruntime option enabled");
+        fatal();
+    }
+
+    if (!M) {
+        assert(!runtime_failed);
+        LLVM_D_InitRuntime();
+    }
+
+    llvm::GlobalVariable* g = M->getNamedGlobal(name);
+    if (!g) {
+        error("Runtime global '%s' was not found", name);
+        fatal();
+        //return NULL;
+    }
+
+    const llvm::PointerType* t = g->getType();
+    return new llvm::GlobalVariable(t->getElementType(),g->isConstant(),g->getLinkage(),NULL,g->getName(),target);
+}
--- a/gen/statements.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,874 +0,0 @@
-// Statements: D -> LLVM glue
-
-#include <stdio.h>
-#include <math.h>
-#include <sstream>
-#include <fstream>
-#include <iostream>
-
-#include "gen/llvm.h"
-#include "llvm/Transforms/Utils/Cloning.h"
-
-#include "total.h"
-#include "init.h"
-#include "symbol.h"
-#include "mtype.h"
-#include "hdrgen.h"
-#include "port.h"
-
-#include "gen/irstate.h"
-#include "gen/elem.h"
-#include "gen/logger.h"
-#include "gen/tollvm.h"
-#include "gen/runtime.h"
-#include "gen/arrays.h"
-#include "gen/todebug.h"
-
-//////////////////////////////////////////////////////////////////////////////
-
-void CompoundStatement::toIR(IRState* p)
-{
-    static int csi = 0;
-    Logger::println("CompoundStatement::toIR(%d):\n<<<\n%s>>>", csi++, toChars());
-    LOG_SCOPE;
-
-    for (int i=0; i<statements->dim; i++)
-    {
-        Statement* s = (Statement*)statements->data[i];
-        if (s)
-            s->toIR(p);
-        else {
-            Logger::println("*** ATTENTION: null statement found in CompoundStatement");
-            //assert(0);
-        }
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void ReturnStatement::toIR(IRState* p)
-{
-    static int rsi = 0;
-    Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars());
-    LOG_SCOPE;
-
-    if (exp)
-    {
-        Logger::println("return type is: %s", exp->type->toChars());
-
-        Type* exptype = DtoDType(exp->type);
-        TY expty = exptype->ty;
-        if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
-            assert(DtoIsPassedByRef(exptype));
-
-            TypeFunction* f = p->topfunctype();
-            assert(f->llvmRetInPtr && f->llvmRetArg);
-
-            if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
-
-            p->exps.push_back(IRExp(NULL,exp,f->llvmRetArg));
-            elem* e = exp->toElem(p);
-            p->exps.pop_back();
-
-            if (expty == Tstruct) {
-                if (!e->inplace)
-                    DtoStructCopy(f->llvmRetArg,e->getValue());
-            }
-            else if (expty == Tdelegate) {
-                if (!e->inplace)
-                    DtoDelegateCopy(f->llvmRetArg,e->getValue());
-            }
-            else if (expty == Tarray) {
-                if (e->type == elem::SLICE) {
-                    assert(e->mem);
-                    DtoSetArray(f->llvmRetArg,e->arg,e->mem);
-                }
-                else if (!e->inplace) {
-                    if (e->type == elem::NUL) {
-                        DtoNullArray(f->llvmRetArg);
-                    }
-                    else {
-                        DtoArrayAssign(f->llvmRetArg, e->getValue());
-                    }
-                }
-            }
-            else
-            assert(0);
-
-            IRFunction::FinallyVec& fin = p->func().finallys;
-            if (fin.empty()) {
-                if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
-                new llvm::ReturnInst(p->scopebb());
-            }
-            else {
-                new llvm::BranchInst(fin.back().retbb, p->scopebb());
-            }
-            delete e;
-        }
-        else {
-            if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
-            elem* e = exp->toElem(p);
-            llvm::Value* v = e->getValue();
-            delete e;
-            Logger::cout() << "return value is '" <<*v << "'\n";
-
-            IRFunction::FinallyVec& fin = p->func().finallys;
-            if (fin.empty()) {
-                if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
-                new llvm::ReturnInst(v, p->scopebb());
-            }
-            else {
-                if (!p->func().finallyretval)
-                    p->func().finallyretval = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint());
-                llvm::Value* rettmp = p->func().finallyretval;
-                new llvm::StoreInst(v,rettmp,p->scopebb());
-                new llvm::BranchInst(fin.back().retbb, p->scopebb());
-            }
-        }
-    }
-    else
-    {
-        if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
-            IRFunction::FinallyVec& fin = p->func().finallys;
-            if (fin.empty()) {
-                if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
-                new llvm::ReturnInst(p->scopebb());
-            }
-            else {
-                new llvm::BranchInst(fin.back().retbb, p->scopebb());
-            }
-        }
-        else {
-            assert(0); // why should this ever happen?
-            new llvm::UnreachableInst(p->scopebb());
-        }
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void ExpStatement::toIR(IRState* p)
-{
-    static int esi = 0;
-    Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars());
-    LOG_SCOPE;
-
-    if (global.params.symdebug)
-        DtoDwarfStopPoint(loc.linnum);
-
-    if (exp != 0) {
-        elem* e = exp->toElem(p);
-        delete e;
-    }
-    /*elem* e = exp->toElem(p);
-    p->buf.printf("%s", e->toChars());
-    delete e;
-    p->buf.writenl();*/
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void IfStatement::toIR(IRState* p)
-{
-    static int wsi = 0;
-    Logger::println("IfStatement::toIR(%d): %s", wsi++, toChars());
-    LOG_SCOPE;
-
-    elem* cond_e = condition->toElem(p);
-    llvm::Value* cond_val = cond_e->getValue();
-    delete cond_e;
-
-    llvm::BasicBlock* oldend = gIR->scopeend();
-
-    llvm::BasicBlock* ifbb = new llvm::BasicBlock("if", gIR->topfunc(), oldend);
-    llvm::BasicBlock* endbb = new llvm::BasicBlock("endif", gIR->topfunc(), oldend);
-    llvm::BasicBlock* elsebb = elsebody ? new llvm::BasicBlock("else", gIR->topfunc(), endbb) : endbb;
-
-    if (cond_val->getType() != llvm::Type::Int1Ty) {
-        Logger::cout() << "if conditional: " << *cond_val << '\n';
-        cond_val = DtoBoolean(cond_val);
-    }
-    llvm::Value* ifgoback = new llvm::BranchInst(ifbb, elsebb, cond_val, gIR->scopebegin());
-
-    // replace current scope
-    gIR->scope() = IRScope(ifbb,elsebb);
-
-    // do scoped statements
-    ifbody->toIR(p);
-    if (!gIR->scopereturned()) {
-        new llvm::BranchInst(endbb,gIR->scopebegin());
-    }
-
-    if (elsebody) {
-        //assert(0);
-        gIR->scope() = IRScope(elsebb,endbb);
-        elsebody->toIR(p);
-        if (!gIR->scopereturned()) {
-            new llvm::BranchInst(endbb,gIR->scopebegin());
-        }
-    }
-
-    // rewrite the scope
-    gIR->scope() = IRScope(endbb,oldend);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void ScopeStatement::toIR(IRState* p)
-{
-    Logger::println("ScopeStatement::toIR(): %s", toChars());
-    LOG_SCOPE;
-
-    llvm::BasicBlock* oldend = p->scopeend();
-
-    llvm::BasicBlock* beginbb = 0;
-
-    // remove useless branches by clearing and reusing the current basicblock
-    llvm::BasicBlock* bb = p->scopebegin();
-    if (bb->empty()) {
-        beginbb = bb;
-    }
-    else {
-        assert(!p->scopereturned());
-        beginbb = new llvm::BasicBlock("scope", p->topfunc(), oldend);
-        new llvm::BranchInst(beginbb, p->scopebegin());
-    }
-    llvm::BasicBlock* endbb = new llvm::BasicBlock("endscope", p->topfunc(), oldend);
-
-    gIR->scope() = IRScope(beginbb, endbb);
-
-    statement->toIR(p);
-
-    p->scope() = IRScope(p->scopebb(),oldend);
-    endbb->eraseFromParent();
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void WhileStatement::toIR(IRState* p)
-{
-    static int wsi = 0;
-    Logger::println("WhileStatement::toIR(%d): %s", wsi++, toChars());
-    LOG_SCOPE;
-
-    // create while blocks
-    llvm::BasicBlock* oldend = gIR->scopeend();
-    llvm::BasicBlock* whilebb = new llvm::BasicBlock("whilecond", gIR->topfunc(), oldend);
-    llvm::BasicBlock* whilebodybb = new llvm::BasicBlock("whilebody", gIR->topfunc(), oldend);
-    llvm::BasicBlock* endbb = new llvm::BasicBlock("endwhile", gIR->topfunc(), oldend);
-
-    // move into the while block
-    p->ir->CreateBr(whilebb);
-    //new llvm::BranchInst(whilebb, gIR->scopebegin());
-
-    // replace current scope
-    gIR->scope() = IRScope(whilebb,endbb);
-
-    // create the condition
-    elem* cond_e = condition->toElem(p);
-    llvm::Value* cond_val = DtoBoolean(cond_e->getValue());
-    delete cond_e;
-
-    // conditional branch
-    llvm::Value* ifbreak = new llvm::BranchInst(whilebodybb, endbb, cond_val, p->scopebb());
-
-    // rewrite scope
-    gIR->scope() = IRScope(whilebodybb,endbb);
-
-    // do while body code
-    body->toIR(p);
-
-    // loop
-    new llvm::BranchInst(whilebb, gIR->scopebegin());
-
-    // rewrite the scope
-    gIR->scope() = IRScope(endbb,oldend);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void DoStatement::toIR(IRState* p)
-{
-    static int wsi = 0;
-    Logger::println("DoStatement::toIR(%d): %s", wsi++, toChars());
-    LOG_SCOPE;
-
-    // create while blocks
-    llvm::BasicBlock* oldend = gIR->scopeend();
-    llvm::BasicBlock* dowhilebb = new llvm::BasicBlock("dowhile", gIR->topfunc(), oldend);
-    llvm::BasicBlock* endbb = new llvm::BasicBlock("enddowhile", gIR->topfunc(), oldend);
-
-    // move into the while block
-    new llvm::BranchInst(dowhilebb, gIR->scopebegin());
-
-    // replace current scope
-    gIR->scope() = IRScope(dowhilebb,endbb);
-
-    // do do-while body code
-    body->toIR(p);
-
-    // create the condition
-    elem* cond_e = condition->toElem(p);
-    llvm::Value* cond_val = DtoBoolean(cond_e->getValue());
-    delete cond_e;
-
-    // conditional branch
-    llvm::Value* ifbreak = new llvm::BranchInst(dowhilebb, endbb, cond_val, gIR->scopebegin());
-
-    // rewrite the scope
-    gIR->scope() = IRScope(endbb,oldend);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void ForStatement::toIR(IRState* p)
-{
-    static int wsi = 0;
-    Logger::println("ForStatement::toIR(%d): %s", wsi++, toChars());
-    LOG_SCOPE;
-
-    // create for blocks
-    llvm::BasicBlock* oldend = gIR->scopeend();
-    llvm::BasicBlock* forbb = new llvm::BasicBlock("forcond", gIR->topfunc(), oldend);
-    llvm::BasicBlock* forbodybb = new llvm::BasicBlock("forbody", gIR->topfunc(), oldend);
-    llvm::BasicBlock* forincbb = new llvm::BasicBlock("forinc", gIR->topfunc(), oldend);
-    llvm::BasicBlock* endbb = new llvm::BasicBlock("endfor", gIR->topfunc(), oldend);
-
-    // init
-    if (init != 0)
-    init->toIR(p);
-
-    // move into the for condition block, ie. start the loop
-    new llvm::BranchInst(forbb, gIR->scopebegin());
-
-    p->loopbbs.push_back(IRScope(forincbb,endbb));
-
-    // replace current scope
-    gIR->scope() = IRScope(forbb,forbodybb);
-
-    // create the condition
-    elem* cond_e = condition->toElem(p);
-    llvm::Value* cond_val = DtoBoolean(cond_e->getValue());
-    delete cond_e;
-
-    // conditional branch
-    llvm::Value* ifbreak = new llvm::BranchInst(forbodybb, endbb, cond_val, forbb);
-
-    // rewrite scope
-    gIR->scope() = IRScope(forbodybb,forincbb);
-
-    // do for body code
-    body->toIR(p);
-
-    // move into the for increment block
-    new llvm::BranchInst(forincbb, gIR->scopebegin());
-    gIR->scope() = IRScope(forincbb, endbb);
-
-    // increment
-    if (increment) {
-        elem* inc = increment->toElem(p);
-        delete inc;
-    }
-
-    // loop
-    new llvm::BranchInst(forbb, gIR->scopebegin());
-
-    p->loopbbs.pop_back();
-
-    // rewrite the scope
-    gIR->scope() = IRScope(endbb,oldend);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void BreakStatement::toIR(IRState* p)
-{
-    static int wsi = 0;
-    Logger::println("BreakStatement::toIR(%d): %s", wsi++, toChars());
-    LOG_SCOPE;
-
-    if (ident != 0) {
-        Logger::println("ident = %s", ident->toChars());
-        assert(0);
-    }
-    else {
-        new llvm::BranchInst(gIR->loopbbs.back().end, gIR->scopebegin());
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void ContinueStatement::toIR(IRState* p)
-{
-    static int wsi = 0;
-    Logger::println("ContinueStatement::toIR(%d): %s", wsi++, toChars());
-    LOG_SCOPE;
-
-    if (ident != 0) {
-        Logger::println("ident = %s", ident->toChars());
-        assert(0);
-    }
-    else {
-        new llvm::BranchInst(gIR->loopbbs.back().begin, gIR->scopebegin());
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void OnScopeStatement::toIR(IRState* p)
-{
-    static int wsi = 0;
-    Logger::println("OnScopeStatement::toIR(%d): %s", wsi++, toChars());
-    LOG_SCOPE;
-
-    assert(statement);
-    //statement->toIR(p); // this seems to be redundant
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-static void replaceFinallyBBs(std::vector<llvm::BasicBlock*>& a, std::vector<llvm::BasicBlock*>& b)
-{
-}
-
-void TryFinallyStatement::toIR(IRState* p)
-{
-    Logger::println("TryFinallyStatement::toIR(): %s", toChars());
-    LOG_SCOPE;
-
-    // create basic blocks
-    llvm::BasicBlock* oldend = p->scopeend();
-
-    llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend);
-    llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", p->topfunc(), oldend);
-    llvm::BasicBlock* finallyretbb = new llvm::BasicBlock("finallyreturn", p->topfunc(), oldend);
-    llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", p->topfunc(), oldend);
-
-    // pass the previous BB into this
-    assert(!gIR->scopereturned());
-    new llvm::BranchInst(trybb, p->scopebb());
-
-    // do the try block
-    p->scope() = IRScope(trybb,finallybb);
-    gIR->func().finallys.push_back(IRFinally(finallybb,finallyretbb));
-    IRFinally& fin = p->func().finallys.back();
-
-    assert(body);
-    body->toIR(p);
-
-    // terminate try BB
-    if (!p->scopereturned())
-        new llvm::BranchInst(finallybb, p->scopebb());
-
-    // do finally block
-    p->scope() = IRScope(finallybb,finallyretbb);
-    assert(finalbody);
-    finalbody->toIR(p);
-
-    // terminate finally
-    if (!gIR->scopereturned()) {
-        new llvm::BranchInst(endbb, p->scopebb());
-    }
-
-    // do finally block (return path)
-    p->scope() = IRScope(finallyretbb,endbb);
-    assert(finalbody);
-    finalbody->toIR(p); // hope this will work, otherwise it's time it gets fixed
-
-    // terminate finally (return path)
-    size_t nfin = p->func().finallys.size();
-    if (nfin > 1) {
-        IRFinally& ofin = p->func().finallys[nfin-2];
-        p->ir->CreateBr(ofin.retbb);
-    }
-    // no outer
-    else
-    {
-        if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
-        llvm::Value* retval = p->func().finallyretval;
-        if (retval) {
-            retval = p->ir->CreateLoad(retval,"tmp");
-            p->ir->CreateRet(retval);
-        }
-        else {
-            FuncDeclaration* fd = p->func().decl;
-            if (fd->isMain()) {
-                assert(fd->type->next->ty == Tvoid);
-                p->ir->CreateRet(DtoConstInt(0));
-            }
-            else {
-                p->ir->CreateRetVoid();
-            }
-        }
-    }
-
-    // rewrite the scope
-    p->func().finallys.pop_back();
-    p->scope() = IRScope(endbb,oldend);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void TryCatchStatement::toIR(IRState* p)
-{
-    static int wsi = 0;
-    Logger::println("TryCatchStatement::toIR(%d): %s", wsi++, toChars());
-    LOG_SCOPE;
-
-    Logger::println("*** ATTENTION: try-catch is not yet fully implemented, only the try block will be emitted.");
-
-    assert(body);
-    body->toIR(p);
-
-    /*assert(catches);
-    for(size_t i=0; i<catches->dim; ++i)
-    {
-        Catch* c = (Catch*)catches->data[i];
-        c->handler->toIR(p);
-    }*/
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void ThrowStatement::toIR(IRState* p)
-{
-    static int wsi = 0;
-    Logger::println("ThrowStatement::toIR(%d): %s", wsi++, toChars());
-    LOG_SCOPE;
-
-    Logger::println("*** ATTENTION: throw is not yet implemented, replacing expression with assert(0);");
-
-    llvm::Value* line = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
-    DtoAssert(NULL, line, NULL);
-
-    /*
-    assert(exp);
-    elem* e = exp->toElem(p);
-    delete e;
-    */
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void SwitchStatement::toIR(IRState* p)
-{
-    Logger::println("SwitchStatement::toIR(): %s", toChars());
-    LOG_SCOPE;
-
-    llvm::BasicBlock* oldend = gIR->scopeend();
-
-    // collect the needed cases
-    typedef std::pair<llvm::BasicBlock*, llvm::ConstantInt*> CasePair;
-    std::vector<CasePair> vcases;
-    for (int i=0; i<cases->dim; ++i)
-    {
-        CaseStatement* cs = (CaseStatement*)cases->data[i];
-
-        // get the case value
-        elem* e = cs->exp->toElem(p);
-        assert(e->val && llvm::isa<llvm::ConstantInt>(e->val));
-        llvm::ConstantInt* ec = llvm::cast<llvm::ConstantInt>(e->val);
-        delete e;
-
-        // create the case bb with a nice label
-        std::string lblname("case"+std::string(cs->exp->toChars()));
-        llvm::BasicBlock* bb = new llvm::BasicBlock(lblname, p->topfunc(), oldend);
-
-        vcases.push_back(CasePair(bb,ec));
-    }
-
-    // default
-    llvm::BasicBlock* defbb = 0;
-    if (!hasNoDefault) {
-        defbb = new llvm::BasicBlock("default", p->topfunc(), oldend);
-    }
-
-    // end (break point)
-    llvm::BasicBlock* endbb = new llvm::BasicBlock("switchend", p->topfunc(), oldend);
-
-    // condition var
-    elem* cond = condition->toElem(p);
-    llvm::SwitchInst* si = new llvm::SwitchInst(cond->getValue(), defbb ? defbb : endbb, cases->dim, p->scopebb());
-    delete cond;
-
-    // add the cases
-    size_t n = vcases.size();
-    for (size_t i=0; i<n; ++i)
-    {
-        si->addCase(vcases[i].second, vcases[i].first);
-    }
-
-    // insert case statements
-    for (size_t i=0; i<n; ++i)
-    {
-        llvm::BasicBlock* nextbb = (i == n-1) ? (defbb ? defbb : endbb) : vcases[i+1].first;
-        p->scope() = IRScope(vcases[i].first,nextbb);
-
-        p->loopbbs.push_back(IRScope(p->scopebb(),endbb));
-        static_cast<CaseStatement*>(cases->data[i])->statement->toIR(p);
-        p->loopbbs.pop_back();
-
-        llvm::BasicBlock* curbb = p->scopebb();
-        if (curbb->empty() || !curbb->back().isTerminator())
-        {
-            new llvm::BranchInst(nextbb, curbb);
-        }
-    }
-
-    // default statement
-    if (defbb)
-    {
-        p->scope() = IRScope(defbb,endbb);
-        p->loopbbs.push_back(IRScope(defbb,endbb));
-        Logger::println("doing default statement");
-        sdefault->statement->toIR(p);
-        p->loopbbs.pop_back();
-
-        llvm::BasicBlock* curbb = p->scopebb();
-        if (curbb->empty() || !curbb->back().isTerminator())
-        {
-            new llvm::BranchInst(endbb, curbb);
-        }
-    }
-
-    gIR->scope() = IRScope(endbb,oldend);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void UnrolledLoopStatement::toIR(IRState* p)
-{
-    Logger::println("UnrolledLoopStatement::toIR(): %s", toChars());
-    LOG_SCOPE;
-
-    llvm::BasicBlock* oldend = gIR->scopeend();
-    llvm::BasicBlock* endbb = new llvm::BasicBlock("unrolledend", p->topfunc(), oldend);
-
-    p->scope() = IRScope(p->scopebb(),endbb);
-    p->loopbbs.push_back(IRScope(p->scopebb(),endbb));
-
-    for (int i=0; i<statements->dim; ++i)
-    {
-        Statement* s = (Statement*)statements->data[i];
-        s->toIR(p);
-    }
-
-    p->loopbbs.pop_back();
-
-    new llvm::BranchInst(endbb, p->scopebb());
-    p->scope() = IRScope(endbb,oldend);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void ForeachStatement::toIR(IRState* p)
-{
-    Logger::println("ForeachStatement::toIR(): %s", toChars());
-    LOG_SCOPE;
-
-    //assert(arguments->dim == 1);
-    assert(value != 0);
-    assert(body != 0);
-    assert(aggr != 0);
-    assert(func != 0);
-
-    //Argument* arg = (Argument*)arguments->data[0];
-    //Logger::println("Argument is %s", arg->toChars());
-
-    Logger::println("aggr = %s", aggr->toChars());
-    Logger::println("func = %s", func->toChars());
-
-    elem* arr = aggr->toElem(p);
-    llvm::Value* val = arr->getValue();
-    Logger::cout() << "aggr2llvm = " << *val << '\n';
-
-    llvm::Value* numiters = 0;
-
-    const llvm::Type* keytype = key ? DtoType(key->type) : DtoSize_t();
-    llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint());
-    if (key) key->llvmValue = keyvar;
-
-    const llvm::Type* valtype = DtoType(value->type);
-    llvm::Value* valvar = !value->isRef() ? new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()) : NULL;
-
-    Type* aggrtype = DtoDType(aggr->type);
-    if (aggrtype->ty == Tsarray)
-    {
-        assert(llvm::isa<llvm::PointerType>(val->getType()));
-        assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0)));
-        size_t n = llvm::cast<llvm::ArrayType>(val->getType()->getContainedType(0))->getNumElements();
-        assert(n > 0);
-        numiters = llvm::ConstantInt::get(keytype,n,false); 
-    }
-    else if (aggrtype->ty == Tarray)
-    {
-        if (arr->type == elem::SLICE) {
-            numiters = arr->arg;
-            val = arr->mem;
-        }
-        else {
-            numiters = p->ir->CreateLoad(DtoGEPi(val,0,0,"tmp",p->scopebb()));
-            val = p->ir->CreateLoad(DtoGEPi(val,0,1,"tmp",p->scopebb()));
-        }
-    }
-    else
-    {
-        assert(0 && "aggregate type is not Tarray or Tsarray");
-    }
-
-    if (op == TOKforeach) {
-        new llvm::StoreInst(llvm::ConstantInt::get(keytype,0,false), keyvar, p->scopebb());
-    }
-    else if (op == TOKforeach_reverse) {
-        llvm::Value* v = llvm::BinaryOperator::createSub(numiters, llvm::ConstantInt::get(keytype,1,false),"tmp",p->scopebb());
-        new llvm::StoreInst(v, keyvar, p->scopebb());
-    }
-
-    delete arr;
-
-    llvm::BasicBlock* oldend = gIR->scopeend();
-    llvm::BasicBlock* nexbb = new llvm::BasicBlock("foreachnext", p->topfunc(), oldend);
-    llvm::BasicBlock* begbb = new llvm::BasicBlock("foreachbegin", p->topfunc(), oldend);
-    llvm::BasicBlock* endbb = new llvm::BasicBlock("foreachend", p->topfunc(), oldend);
-
-    new llvm::BranchInst(begbb, p->scopebb());
-
-    // next
-    p->scope() = IRScope(nexbb,begbb);
-    llvm::Value* done = 0;
-    llvm::Value* load = new llvm::LoadInst(keyvar, "tmp", p->scopebb());
-    if (op == TOKforeach) {
-        load = llvm::BinaryOperator::createAdd(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb());
-        new llvm::StoreInst(load, keyvar, p->scopebb());
-        done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_ULT, load, numiters, "tmp", p->scopebb());
-    }
-    else if (op == TOKforeach_reverse) {
-        done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_UGT, load, llvm::ConstantInt::get(keytype, 0, false), "tmp", p->scopebb());
-        load = llvm::BinaryOperator::createSub(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb());
-        new llvm::StoreInst(load, keyvar, p->scopebb());
-    }
-    new llvm::BranchInst(begbb, endbb, done, p->scopebb());
-
-    // begin
-    p->scope() = IRScope(begbb,nexbb);
-
-    // get value for this iteration
-    llvm::Constant* zero = llvm::ConstantInt::get(keytype,0,false);
-    llvm::Value* loadedKey = p->ir->CreateLoad(keyvar,"tmp");
-    if (aggrtype->ty == Tsarray)
-        value->llvmValue = DtoGEP(val,zero,loadedKey,"tmp");
-    else if (aggrtype->ty == Tarray)
-        value->llvmValue = new llvm::GetElementPtrInst(val,loadedKey,"tmp",p->scopebb());
-
-    if (!value->isRef()) {
-        elem* e = new elem;
-        e->mem = value->llvmValue;
-        e->type = elem::VAR;
-        DtoAssign(DtoDType(value->type), valvar, e->getValue());
-        delete e;
-        value->llvmValue = valvar;
-    }
-
-    // body
-    p->scope() = IRScope(p->scopebb(),endbb);
-    p->loopbbs.push_back(IRScope(nexbb,endbb));
-    body->toIR(p);
-    p->loopbbs.pop_back();
-
-    if (!p->scopereturned())
-        new llvm::BranchInst(nexbb, p->scopebb());
-
-    // end
-    p->scope() = IRScope(endbb,oldend);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void LabelStatement::toIR(IRState* p)
-{
-    Logger::println("LabelStatement::toIR(): %s", toChars());
-    LOG_SCOPE;
-
-    assert(tf == NULL);
-    assert(!isReturnLabel);
-
-    llvm::BasicBlock* oldend = gIR->scopeend();
-    if (llvmBB)
-        llvmBB->moveBefore(oldend);
-    else
-        llvmBB = new llvm::BasicBlock("label", p->topfunc(), oldend);
-
-    new llvm::BranchInst(llvmBB, p->scopebb());
-    p->scope() = IRScope(llvmBB,oldend);
-    statement->toIR(p);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void GotoStatement::toIR(IRState* p)
-{
-    Logger::println("GotoStatement::toIR(): %s", toChars());
-    LOG_SCOPE;
-
-    assert(tf == NULL);
-
-    llvm::BasicBlock* oldend = gIR->scopeend();
-    llvm::BasicBlock* bb = new llvm::BasicBlock("aftergoto", p->topfunc(), oldend);
-
-    if (label->statement->llvmBB == NULL)
-        label->statement->llvmBB = new llvm::BasicBlock("label", p->topfunc());
-    new llvm::BranchInst(label->statement->llvmBB, p->scopebb());
-    p->scope() = IRScope(bb,oldend);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void WithStatement::toIR(IRState* p)
-{
-    Logger::println("WithStatement::toIR(): %s", toChars());
-    LOG_SCOPE;
-
-    assert(exp);
-    assert(body);
-
-    elem* e = exp->toElem(p);
-    wthis->llvmValue = e->getValue();
-    delete e;
-
-    body->toIR(p);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-//////////////////////////////////////////////////////////////////////////////
-
-#define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();}
-//STUBST(BreakStatement);
-//STUBST(ForStatement);
-//STUBST(WithStatement);
-STUBST(SynchronizedStatement);
-//STUBST(ReturnStatement);
-//STUBST(ContinueStatement);
-STUBST(DefaultStatement);
-STUBST(CaseStatement);
-//STUBST(SwitchStatement);
-STUBST(SwitchErrorStatement);
-STUBST(Statement);
-//STUBST(IfStatement);
-//STUBST(ForeachStatement);
-//STUBST(DoStatement);
-//STUBST(WhileStatement);
-//STUBST(ExpStatement);
-//STUBST(CompoundStatement);
-//STUBST(ScopeStatement);
-STUBST(AsmStatement);
-//STUBST(TryCatchStatement);
-//STUBST(TryFinallyStatement);
-STUBST(VolatileStatement);
-//STUBST(LabelStatement);
-//STUBST(ThrowStatement);
-STUBST(GotoCaseStatement);
-STUBST(GotoDefaultStatement);
-//STUBST(GotoStatement);
-//STUBST(UnrolledLoopStatement);
-//STUBST(OnScopeStatement);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/statements.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,862 @@
+// Statements: D -> LLVM glue
+
+#include <stdio.h>
+#include <math.h>
+#include <sstream>
+#include <fstream>
+#include <iostream>
+
+#include "gen/llvm.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+
+#include "total.h"
+#include "init.h"
+#include "symbol.h"
+#include "mtype.h"
+#include "hdrgen.h"
+#include "port.h"
+
+#include "gen/irstate.h"
+#include "gen/elem.h"
+#include "gen/logger.h"
+#include "gen/tollvm.h"
+#include "gen/runtime.h"
+#include "gen/arrays.h"
+#include "gen/todebug.h"
+#include "gen/dvalue.h"
+
+//////////////////////////////////////////////////////////////////////////////
+
+void CompoundStatement::toIR(IRState* p)
+{
+    static int csi = 0;
+    Logger::println("CompoundStatement::toIR(%d):\n<<<\n%s>>>", csi++, toChars());
+    LOG_SCOPE;
+
+    for (int i=0; i<statements->dim; i++)
+    {
+        Statement* s = (Statement*)statements->data[i];
+        if (s)
+            s->toIR(p);
+        else {
+            Logger::println("*** ATTENTION: null statement found in CompoundStatement");
+            //assert(0);
+        }
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void ReturnStatement::toIR(IRState* p)
+{
+    static int rsi = 0;
+    Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars());
+    LOG_SCOPE;
+
+    if (exp)
+    {
+        Logger::println("return type is: %s", exp->type->toChars());
+
+        Type* exptype = DtoDType(exp->type);
+        TY expty = exptype->ty;
+        if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
+            assert(DtoIsPassedByRef(exptype));
+
+            TypeFunction* f = p->topfunctype();
+            assert(f->llvmRetInPtr && f->llvmRetArg);
+
+            if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
+
+            DValue* rvar = new DVarValue(f->next, f->llvmRetArg, true);
+
+            p->exps.push_back(IRExp(NULL,exp,rvar));
+            DValue* e = exp->toElem(p);
+            p->exps.pop_back();
+
+            if (!e->inPlace())
+                DtoAssign(rvar, e);
+
+            IRFunction::FinallyVec& fin = p->func().finallys;
+            if (fin.empty()) {
+                if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
+                new llvm::ReturnInst(p->scopebb());
+            }
+            else {
+                new llvm::BranchInst(fin.back().retbb, p->scopebb());
+            }
+        }
+        else {
+            if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
+            DValue* e = exp->toElem(p);
+            llvm::Value* v = e->getRVal();
+            delete e;
+            Logger::cout() << "return value is '" <<*v << "'\n";
+
+            IRFunction::FinallyVec& fin = p->func().finallys;
+            if (fin.empty()) {
+                if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
+                new llvm::ReturnInst(v, p->scopebb());
+            }
+            else {
+                if (!p->func().finallyretval)
+                    p->func().finallyretval = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint());
+                llvm::Value* rettmp = p->func().finallyretval;
+                new llvm::StoreInst(v,rettmp,p->scopebb());
+                new llvm::BranchInst(fin.back().retbb, p->scopebb());
+            }
+        }
+    }
+    else
+    {
+        if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
+            IRFunction::FinallyVec& fin = p->func().finallys;
+            if (fin.empty()) {
+                if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
+                new llvm::ReturnInst(p->scopebb());
+            }
+            else {
+                new llvm::BranchInst(fin.back().retbb, p->scopebb());
+            }
+        }
+        else {
+            assert(0); // why should this ever happen?
+            new llvm::UnreachableInst(p->scopebb());
+        }
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void ExpStatement::toIR(IRState* p)
+{
+    static int esi = 0;
+    Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars());
+    LOG_SCOPE;
+
+    if (global.params.symdebug)
+        DtoDwarfStopPoint(loc.linnum);
+
+    if (exp != 0) {
+        elem* e = exp->toElem(p);
+        delete e;
+    }
+    /*elem* e = exp->toElem(p);
+    p->buf.printf("%s", e->toChars());
+    delete e;
+    p->buf.writenl();*/
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void IfStatement::toIR(IRState* p)
+{
+    static int wsi = 0;
+    Logger::println("IfStatement::toIR(%d): %s", wsi++, toChars());
+    LOG_SCOPE;
+
+    DValue* cond_e = condition->toElem(p);
+    llvm::Value* cond_val = cond_e->getRVal();
+    delete cond_e;
+
+    llvm::BasicBlock* oldend = gIR->scopeend();
+
+    llvm::BasicBlock* ifbb = new llvm::BasicBlock("if", gIR->topfunc(), oldend);
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("endif", gIR->topfunc(), oldend);
+    llvm::BasicBlock* elsebb = elsebody ? new llvm::BasicBlock("else", gIR->topfunc(), endbb) : endbb;
+
+    if (cond_val->getType() != llvm::Type::Int1Ty) {
+        Logger::cout() << "if conditional: " << *cond_val << '\n';
+        cond_val = DtoBoolean(cond_val);
+    }
+    llvm::Value* ifgoback = new llvm::BranchInst(ifbb, elsebb, cond_val, gIR->scopebegin());
+
+    // replace current scope
+    gIR->scope() = IRScope(ifbb,elsebb);
+
+    // do scoped statements
+    ifbody->toIR(p);
+    if (!gIR->scopereturned()) {
+        new llvm::BranchInst(endbb,gIR->scopebegin());
+    }
+
+    if (elsebody) {
+        //assert(0);
+        gIR->scope() = IRScope(elsebb,endbb);
+        elsebody->toIR(p);
+        if (!gIR->scopereturned()) {
+            new llvm::BranchInst(endbb,gIR->scopebegin());
+        }
+    }
+
+    // rewrite the scope
+    gIR->scope() = IRScope(endbb,oldend);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void ScopeStatement::toIR(IRState* p)
+{
+    Logger::println("ScopeStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    llvm::BasicBlock* oldend = p->scopeend();
+
+    llvm::BasicBlock* beginbb = 0;
+
+    // remove useless branches by clearing and reusing the current basicblock
+    llvm::BasicBlock* bb = p->scopebegin();
+    if (bb->empty()) {
+        beginbb = bb;
+    }
+    else {
+        assert(!p->scopereturned());
+        beginbb = new llvm::BasicBlock("scope", p->topfunc(), oldend);
+        new llvm::BranchInst(beginbb, p->scopebegin());
+    }
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("endscope", p->topfunc(), oldend);
+
+    gIR->scope() = IRScope(beginbb, endbb);
+
+    statement->toIR(p);
+
+    p->scope() = IRScope(p->scopebb(),oldend);
+    endbb->eraseFromParent();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void WhileStatement::toIR(IRState* p)
+{
+    static int wsi = 0;
+    Logger::println("WhileStatement::toIR(%d): %s", wsi++, toChars());
+    LOG_SCOPE;
+
+    // create while blocks
+    llvm::BasicBlock* oldend = gIR->scopeend();
+    llvm::BasicBlock* whilebb = new llvm::BasicBlock("whilecond", gIR->topfunc(), oldend);
+    llvm::BasicBlock* whilebodybb = new llvm::BasicBlock("whilebody", gIR->topfunc(), oldend);
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("endwhile", gIR->topfunc(), oldend);
+
+    // move into the while block
+    p->ir->CreateBr(whilebb);
+    //new llvm::BranchInst(whilebb, gIR->scopebegin());
+
+    // replace current scope
+    gIR->scope() = IRScope(whilebb,endbb);
+
+    // create the condition
+    DValue* cond_e = condition->toElem(p);
+    llvm::Value* cond_val = DtoBoolean(cond_e->getRVal());
+    delete cond_e;
+
+    // conditional branch
+    llvm::Value* ifbreak = new llvm::BranchInst(whilebodybb, endbb, cond_val, p->scopebb());
+
+    // rewrite scope
+    gIR->scope() = IRScope(whilebodybb,endbb);
+
+    // do while body code
+    body->toIR(p);
+
+    // loop
+    new llvm::BranchInst(whilebb, gIR->scopebegin());
+
+    // rewrite the scope
+    gIR->scope() = IRScope(endbb,oldend);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void DoStatement::toIR(IRState* p)
+{
+    static int wsi = 0;
+    Logger::println("DoStatement::toIR(%d): %s", wsi++, toChars());
+    LOG_SCOPE;
+
+    // create while blocks
+    llvm::BasicBlock* oldend = gIR->scopeend();
+    llvm::BasicBlock* dowhilebb = new llvm::BasicBlock("dowhile", gIR->topfunc(), oldend);
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("enddowhile", gIR->topfunc(), oldend);
+
+    // move into the while block
+    new llvm::BranchInst(dowhilebb, gIR->scopebegin());
+
+    // replace current scope
+    gIR->scope() = IRScope(dowhilebb,endbb);
+
+    // do do-while body code
+    body->toIR(p);
+
+    // create the condition
+    DValue* cond_e = condition->toElem(p);
+    llvm::Value* cond_val = DtoBoolean(cond_e->getRVal());
+    delete cond_e;
+
+    // conditional branch
+    llvm::Value* ifbreak = new llvm::BranchInst(dowhilebb, endbb, cond_val, gIR->scopebegin());
+
+    // rewrite the scope
+    gIR->scope() = IRScope(endbb,oldend);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void ForStatement::toIR(IRState* p)
+{
+    static int wsi = 0;
+    Logger::println("ForStatement::toIR(%d): %s", wsi++, toChars());
+    LOG_SCOPE;
+
+    // create for blocks
+    llvm::BasicBlock* oldend = gIR->scopeend();
+    llvm::BasicBlock* forbb = new llvm::BasicBlock("forcond", gIR->topfunc(), oldend);
+    llvm::BasicBlock* forbodybb = new llvm::BasicBlock("forbody", gIR->topfunc(), oldend);
+    llvm::BasicBlock* forincbb = new llvm::BasicBlock("forinc", gIR->topfunc(), oldend);
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("endfor", gIR->topfunc(), oldend);
+
+    // init
+    if (init != 0)
+    init->toIR(p);
+
+    // move into the for condition block, ie. start the loop
+    new llvm::BranchInst(forbb, gIR->scopebegin());
+
+    p->loopbbs.push_back(IRScope(forincbb,endbb));
+
+    // replace current scope
+    gIR->scope() = IRScope(forbb,forbodybb);
+
+    // create the condition
+    DValue* cond_e = condition->toElem(p);
+    llvm::Value* cond_val = DtoBoolean(cond_e->getRVal());
+    delete cond_e;
+
+    // conditional branch
+    llvm::Value* ifbreak = new llvm::BranchInst(forbodybb, endbb, cond_val, forbb);
+
+    // rewrite scope
+    gIR->scope() = IRScope(forbodybb,forincbb);
+
+    // do for body code
+    body->toIR(p);
+
+    // move into the for increment block
+    new llvm::BranchInst(forincbb, gIR->scopebegin());
+    gIR->scope() = IRScope(forincbb, endbb);
+
+    // increment
+    if (increment) {
+        DValue* inc = increment->toElem(p);
+        delete inc;
+    }
+
+    // loop
+    new llvm::BranchInst(forbb, gIR->scopebegin());
+
+    p->loopbbs.pop_back();
+
+    // rewrite the scope
+    gIR->scope() = IRScope(endbb,oldend);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void BreakStatement::toIR(IRState* p)
+{
+    static int wsi = 0;
+    Logger::println("BreakStatement::toIR(%d): %s", wsi++, toChars());
+    LOG_SCOPE;
+
+    if (ident != 0) {
+        Logger::println("ident = %s", ident->toChars());
+        assert(0);
+    }
+    else {
+        new llvm::BranchInst(gIR->loopbbs.back().end, gIR->scopebegin());
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void ContinueStatement::toIR(IRState* p)
+{
+    static int wsi = 0;
+    Logger::println("ContinueStatement::toIR(%d): %s", wsi++, toChars());
+    LOG_SCOPE;
+
+    if (ident != 0) {
+        Logger::println("ident = %s", ident->toChars());
+        assert(0);
+    }
+    else {
+        new llvm::BranchInst(gIR->loopbbs.back().begin, gIR->scopebegin());
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void OnScopeStatement::toIR(IRState* p)
+{
+    static int wsi = 0;
+    Logger::println("OnScopeStatement::toIR(%d): %s", wsi++, toChars());
+    LOG_SCOPE;
+
+    assert(statement);
+    //statement->toIR(p); // this seems to be redundant
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+static void replaceFinallyBBs(std::vector<llvm::BasicBlock*>& a, std::vector<llvm::BasicBlock*>& b)
+{
+}
+
+void TryFinallyStatement::toIR(IRState* p)
+{
+    Logger::println("TryFinallyStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    // create basic blocks
+    llvm::BasicBlock* oldend = p->scopeend();
+
+    llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend);
+    llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", p->topfunc(), oldend);
+    llvm::BasicBlock* finallyretbb = new llvm::BasicBlock("finallyreturn", p->topfunc(), oldend);
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", p->topfunc(), oldend);
+
+    // pass the previous BB into this
+    assert(!gIR->scopereturned());
+    new llvm::BranchInst(trybb, p->scopebb());
+
+    // do the try block
+    p->scope() = IRScope(trybb,finallybb);
+    gIR->func().finallys.push_back(IRFinally(finallybb,finallyretbb));
+    IRFinally& fin = p->func().finallys.back();
+
+    assert(body);
+    body->toIR(p);
+
+    // terminate try BB
+    if (!p->scopereturned())
+        new llvm::BranchInst(finallybb, p->scopebb());
+
+    // do finally block
+    p->scope() = IRScope(finallybb,finallyretbb);
+    assert(finalbody);
+    finalbody->toIR(p);
+
+    // terminate finally
+    if (!gIR->scopereturned()) {
+        new llvm::BranchInst(endbb, p->scopebb());
+    }
+
+    // do finally block (return path)
+    p->scope() = IRScope(finallyretbb,endbb);
+    assert(finalbody);
+    finalbody->toIR(p); // hope this will work, otherwise it's time it gets fixed
+
+    // terminate finally (return path)
+    size_t nfin = p->func().finallys.size();
+    if (nfin > 1) {
+        IRFinally& ofin = p->func().finallys[nfin-2];
+        p->ir->CreateBr(ofin.retbb);
+    }
+    // no outer
+    else
+    {
+        if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl);
+        llvm::Value* retval = p->func().finallyretval;
+        if (retval) {
+            retval = p->ir->CreateLoad(retval,"tmp");
+            p->ir->CreateRet(retval);
+        }
+        else {
+            FuncDeclaration* fd = p->func().decl;
+            if (fd->isMain()) {
+                assert(fd->type->next->ty == Tvoid);
+                p->ir->CreateRet(DtoConstInt(0));
+            }
+            else {
+                p->ir->CreateRetVoid();
+            }
+        }
+    }
+
+    // rewrite the scope
+    p->func().finallys.pop_back();
+    p->scope() = IRScope(endbb,oldend);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void TryCatchStatement::toIR(IRState* p)
+{
+    static int wsi = 0;
+    Logger::println("TryCatchStatement::toIR(%d): %s", wsi++, toChars());
+    LOG_SCOPE;
+
+    Logger::println("*** ATTENTION: try-catch is not yet fully implemented, only the try block will be emitted.");
+
+    assert(body);
+    body->toIR(p);
+
+    /*assert(catches);
+    for(size_t i=0; i<catches->dim; ++i)
+    {
+        Catch* c = (Catch*)catches->data[i];
+        c->handler->toIR(p);
+    }*/
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void ThrowStatement::toIR(IRState* p)
+{
+    static int wsi = 0;
+    Logger::println("ThrowStatement::toIR(%d): %s", wsi++, toChars());
+    LOG_SCOPE;
+
+    Logger::println("*** ATTENTION: throw is not yet implemented, replacing expression with assert(0);");
+
+    llvm::Value* line = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
+    DtoAssert(NULL, line, NULL);
+
+    /*
+    assert(exp);
+    DValue* e = exp->toElem(p);
+    delete e;
+    */
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void SwitchStatement::toIR(IRState* p)
+{
+    Logger::println("SwitchStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    llvm::BasicBlock* oldend = gIR->scopeend();
+
+    // collect the needed cases
+    typedef std::pair<llvm::BasicBlock*, llvm::ConstantInt*> CasePair;
+    std::vector<CasePair> vcases;
+    for (int i=0; i<cases->dim; ++i)
+    {
+        CaseStatement* cs = (CaseStatement*)cases->data[i];
+
+        // get the case value
+        DValue* e = cs->exp->toElem(p);
+        DConstValue* ce = e->isConst();
+        assert(ce && llvm::isa<llvm::ConstantInt>(ce->c));
+        llvm::ConstantInt* ec = llvm::cast<llvm::ConstantInt>(ce->c);
+        delete e;
+
+        // create the case bb with a nice label
+        std::string lblname("case"+std::string(cs->exp->toChars()));
+        llvm::BasicBlock* bb = new llvm::BasicBlock(lblname, p->topfunc(), oldend);
+
+        vcases.push_back(CasePair(bb,ec));
+    }
+
+    // default
+    llvm::BasicBlock* defbb = 0;
+    if (!hasNoDefault) {
+        defbb = new llvm::BasicBlock("default", p->topfunc(), oldend);
+    }
+
+    // end (break point)
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("switchend", p->topfunc(), oldend);
+
+    // condition var
+    DValue* cond = condition->toElem(p);
+    llvm::SwitchInst* si = new llvm::SwitchInst(cond->getRVal(), defbb ? defbb : endbb, cases->dim, p->scopebb());
+    delete cond;
+
+    // add the cases
+    size_t n = vcases.size();
+    for (size_t i=0; i<n; ++i)
+    {
+        si->addCase(vcases[i].second, vcases[i].first);
+    }
+
+    // insert case statements
+    for (size_t i=0; i<n; ++i)
+    {
+        llvm::BasicBlock* nextbb = (i == n-1) ? (defbb ? defbb : endbb) : vcases[i+1].first;
+        p->scope() = IRScope(vcases[i].first,nextbb);
+
+        p->loopbbs.push_back(IRScope(p->scopebb(),endbb));
+        static_cast<CaseStatement*>(cases->data[i])->statement->toIR(p);
+        p->loopbbs.pop_back();
+
+        llvm::BasicBlock* curbb = p->scopebb();
+        if (curbb->empty() || !curbb->back().isTerminator())
+        {
+            new llvm::BranchInst(nextbb, curbb);
+        }
+    }
+
+    // default statement
+    if (defbb)
+    {
+        p->scope() = IRScope(defbb,endbb);
+        p->loopbbs.push_back(IRScope(defbb,endbb));
+        Logger::println("doing default statement");
+        sdefault->statement->toIR(p);
+        p->loopbbs.pop_back();
+
+        llvm::BasicBlock* curbb = p->scopebb();
+        if (curbb->empty() || !curbb->back().isTerminator())
+        {
+            new llvm::BranchInst(endbb, curbb);
+        }
+    }
+
+    gIR->scope() = IRScope(endbb,oldend);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void UnrolledLoopStatement::toIR(IRState* p)
+{
+    Logger::println("UnrolledLoopStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    llvm::BasicBlock* oldend = gIR->scopeend();
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("unrolledend", p->topfunc(), oldend);
+
+    p->scope() = IRScope(p->scopebb(),endbb);
+    p->loopbbs.push_back(IRScope(p->scopebb(),endbb));
+
+    for (int i=0; i<statements->dim; ++i)
+    {
+        Statement* s = (Statement*)statements->data[i];
+        s->toIR(p);
+    }
+
+    p->loopbbs.pop_back();
+
+    new llvm::BranchInst(endbb, p->scopebb());
+    p->scope() = IRScope(endbb,oldend);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void ForeachStatement::toIR(IRState* p)
+{
+    Logger::println("ForeachStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    //assert(arguments->dim == 1);
+    assert(value != 0);
+    assert(body != 0);
+    assert(aggr != 0);
+    assert(func != 0);
+
+    //Argument* arg = (Argument*)arguments->data[0];
+    //Logger::println("Argument is %s", arg->toChars());
+
+    Logger::println("aggr = %s", aggr->toChars());
+    Logger::println("func = %s", func->toChars());
+
+    DValue* arr = aggr->toElem(p);
+    llvm::Value* val = 0;
+    if (!arr->isSlice()) {
+        val = arr->getRVal();
+        Logger::cout() << "aggr2llvm = " << *val << '\n';
+    }
+
+    llvm::Value* numiters = 0;
+
+    const llvm::Type* keytype = key ? DtoType(key->type) : DtoSize_t();
+    llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint());
+    if (key) key->llvmValue = keyvar;
+
+    const llvm::Type* valtype = DtoType(value->type);
+    llvm::Value* valvar = !(value->isRef() || value->isOut()) ? new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()) : NULL;
+
+    Type* aggrtype = DtoDType(aggr->type);
+    if (aggrtype->ty == Tsarray)
+    {
+        assert(llvm::isa<llvm::PointerType>(val->getType()));
+        assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0)));
+        size_t n = llvm::cast<llvm::ArrayType>(val->getType()->getContainedType(0))->getNumElements();
+        assert(n > 0);
+        numiters = llvm::ConstantInt::get(keytype,n,false); 
+    }
+    else if (aggrtype->ty == Tarray)
+    {
+        if (DSliceValue* slice = arr->isSlice()) {
+            numiters = slice->len;
+            val = slice->ptr;
+        }
+        else {
+            numiters = p->ir->CreateLoad(DtoGEPi(val,0,0,"tmp",p->scopebb()));
+            val = p->ir->CreateLoad(DtoGEPi(val,0,1,"tmp",p->scopebb()));
+        }
+    }
+    else
+    {
+        assert(0 && "aggregate type is not Tarray or Tsarray");
+    }
+
+    if (op == TOKforeach) {
+        new llvm::StoreInst(llvm::ConstantInt::get(keytype,0,false), keyvar, p->scopebb());
+    }
+    else if (op == TOKforeach_reverse) {
+        llvm::Value* v = llvm::BinaryOperator::createSub(numiters, llvm::ConstantInt::get(keytype,1,false),"tmp",p->scopebb());
+        new llvm::StoreInst(v, keyvar, p->scopebb());
+    }
+
+    delete arr;
+
+    llvm::BasicBlock* oldend = gIR->scopeend();
+    llvm::BasicBlock* nexbb = new llvm::BasicBlock("foreachnext", p->topfunc(), oldend);
+    llvm::BasicBlock* begbb = new llvm::BasicBlock("foreachbegin", p->topfunc(), oldend);
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("foreachend", p->topfunc(), oldend);
+
+    new llvm::BranchInst(begbb, p->scopebb());
+
+    // next
+    p->scope() = IRScope(nexbb,begbb);
+    llvm::Value* done = 0;
+    llvm::Value* load = new llvm::LoadInst(keyvar, "tmp", p->scopebb());
+    if (op == TOKforeach) {
+        load = llvm::BinaryOperator::createAdd(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb());
+        new llvm::StoreInst(load, keyvar, p->scopebb());
+        done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_ULT, load, numiters, "tmp", p->scopebb());
+    }
+    else if (op == TOKforeach_reverse) {
+        done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_UGT, load, llvm::ConstantInt::get(keytype, 0, false), "tmp", p->scopebb());
+        load = llvm::BinaryOperator::createSub(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb());
+        new llvm::StoreInst(load, keyvar, p->scopebb());
+    }
+    new llvm::BranchInst(begbb, endbb, done, p->scopebb());
+
+    // begin
+    p->scope() = IRScope(begbb,nexbb);
+
+    // get value for this iteration
+    llvm::Constant* zero = llvm::ConstantInt::get(keytype,0,false);
+    llvm::Value* loadedKey = p->ir->CreateLoad(keyvar,"tmp");
+    if (aggrtype->ty == Tsarray)
+        value->llvmValue = DtoGEP(val,zero,loadedKey,"tmp");
+    else if (aggrtype->ty == Tarray)
+        value->llvmValue = new llvm::GetElementPtrInst(val,loadedKey,"tmp",p->scopebb());
+
+    if (!value->isRef() && !value->isOut()) {
+        DValue* dst = new DVarValue(value->type, valvar, true);
+        DValue* src = new DVarValue(value->type, value->llvmValue, true);
+        DtoAssign(dst, src);
+        delete dst;
+        delete src;
+        value->llvmValue = valvar;
+    }
+
+    // body
+    p->scope() = IRScope(p->scopebb(),endbb);
+    p->loopbbs.push_back(IRScope(nexbb,endbb));
+    body->toIR(p);
+    p->loopbbs.pop_back();
+
+    if (!p->scopereturned())
+        new llvm::BranchInst(nexbb, p->scopebb());
+
+    // end
+    p->scope() = IRScope(endbb,oldend);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void LabelStatement::toIR(IRState* p)
+{
+    Logger::println("LabelStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    assert(tf == NULL);
+    assert(!isReturnLabel);
+
+    llvm::BasicBlock* oldend = gIR->scopeend();
+    if (llvmBB)
+        llvmBB->moveBefore(oldend);
+    else
+        llvmBB = new llvm::BasicBlock("label", p->topfunc(), oldend);
+
+    if (!p->scopereturned())
+        new llvm::BranchInst(llvmBB, p->scopebb());
+
+    p->scope() = IRScope(llvmBB,oldend);
+    if (statement)
+        statement->toIR(p);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void GotoStatement::toIR(IRState* p)
+{
+    Logger::println("GotoStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    assert(tf == NULL);
+
+    llvm::BasicBlock* oldend = gIR->scopeend();
+    llvm::BasicBlock* bb = new llvm::BasicBlock("aftergoto", p->topfunc(), oldend);
+
+    if (label->statement->llvmBB == NULL)
+        label->statement->llvmBB = new llvm::BasicBlock("label", p->topfunc());
+    assert(!p->scopereturned());
+    new llvm::BranchInst(label->statement->llvmBB, p->scopebb());
+    p->scope() = IRScope(bb,oldend);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void WithStatement::toIR(IRState* p)
+{
+    Logger::println("WithStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    assert(exp);
+    assert(body);
+
+    DValue* e = exp->toElem(p);
+    wthis->llvmValue = e->getRVal();
+    delete e;
+
+    body->toIR(p);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();}
+//STUBST(BreakStatement);
+//STUBST(ForStatement);
+//STUBST(WithStatement);
+STUBST(SynchronizedStatement);
+//STUBST(ReturnStatement);
+//STUBST(ContinueStatement);
+STUBST(DefaultStatement);
+STUBST(CaseStatement);
+//STUBST(SwitchStatement);
+STUBST(SwitchErrorStatement);
+STUBST(Statement);
+//STUBST(IfStatement);
+//STUBST(ForeachStatement);
+//STUBST(DoStatement);
+//STUBST(WhileStatement);
+//STUBST(ExpStatement);
+//STUBST(CompoundStatement);
+//STUBST(ScopeStatement);
+STUBST(AsmStatement);
+//STUBST(TryCatchStatement);
+//STUBST(TryFinallyStatement);
+STUBST(VolatileStatement);
+//STUBST(LabelStatement);
+//STUBST(ThrowStatement);
+STUBST(GotoCaseStatement);
+STUBST(GotoDefaultStatement);
+//STUBST(GotoStatement);
+//STUBST(UnrolledLoopStatement);
+//STUBST(OnScopeStatement);
--- a/gen/tocsym.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,215 +0,0 @@
-
-// Copyright (c) 1999-2005 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-// stubbed out for dmdfe. Original is in dmd/tocsym.c
-
-#include <stddef.h>
-
-#include "mars.h"
-#include "module.h"
-#include "mtype.h"
-#include "declaration.h"
-#include "statement.h"
-#include "enum.h"
-#include "aggregate.h"
-#include "init.h"
-#include "attrib.h"
-#include "lexer.h"
-#include "symbol.h"
-
-/********************************* SymbolDeclaration ****************************/
-
-SymbolDeclaration::SymbolDeclaration(Loc loc, Symbol *s, StructDeclaration *dsym)
-    : Declaration(new Identifier("", TOKidentifier))
-{
-}
-
-Symbol *SymbolDeclaration::toSymbol()
-{
-    return sym;
-}
-
-/*************************************
- * Helper
- */
-
-Symbol *Dsymbol::toSymbolX(const char *prefix, int sclass, TYPE *t, const char *suffix)
-{
-  return 0;
-}
-
-/*************************************
- */
-
-Symbol *Dsymbol::toSymbol()
-{
-  return 0;
-}
-
-/*********************************
- * Generate import symbol from symbol.
- */
-
-Symbol *Dsymbol::toImport()
-{
-  return 0;
-}
-
-/*************************************
- */
-
-Symbol *Dsymbol::toImport(Symbol *sym)
-{
-  return 0;
-}
-
-/*************************************
- */
-
-Symbol *VarDeclaration::toSymbol()
-{
-  return 0;
-}
-
-/*************************************
- */
-
-Symbol *ClassInfoDeclaration::toSymbol()
-{
-  return 0;
-}
-
-/*************************************
- */
-
-Symbol *ModuleInfoDeclaration::toSymbol()
-{
-  return 0;
-}
-
-/*************************************
- */
-
-Symbol *TypeInfoDeclaration::toSymbol()
-{
-  return 0;
-}
-
-/*************************************
- */
-
-Symbol *FuncDeclaration::toSymbol()
-{
-
-    return 0;
-}
-
-/*************************************
- */
-
-Symbol *FuncDeclaration::toThunkSymbol(int offset)
-{
-  return 0;
-}
-
-/*************************************
- */
-
-Symbol *FuncAliasDeclaration::toSymbol()
-{
-
-    return 0;
-}
-
-
-/****************************************
- * Create a static symbol we can hang DT initializers onto.
- */
-
-Symbol *static_sym()
-{
-  return 0;
-}
-
-/*************************************
- * Create the "ClassInfo" symbol
- */
-
-Symbol *ClassDeclaration::toSymbol()
-{
-  return 0;
-}
-
-/*************************************
- * Create the "InterfaceInfo" symbol
- */
-
-Symbol *InterfaceDeclaration::toSymbol()
-{
-  return 0;
-}
-
-/*************************************
- * Create the "ModuleInfo" symbol
- */
-
-Symbol *Module::toSymbol()
-{
-  return 0;
-}
-
-/*************************************
- * This is accessible via the ClassData, but since it is frequently
- * needed directly (like for rtti comparisons), make it directly accessible.
- */
-
-Symbol *ClassDeclaration::toVtblSymbol()
-{
-  return 0;
-}
-
-/**********************************
- * Create the static initializer for the struct/class.
- */
-
-Symbol *AggregateDeclaration::toInitializer()
-{
-  return 0;
-}
-
-
-/******************************************
- */
-
-Symbol *Module::toModuleAssert()
-{
-  return 0;
-}
-
-/******************************************
- */
-
-Symbol *Module::toModuleArray()
-{
-  return 0;
-}
-
-/********************************************
- * Determine the right symbol to look up
- * an associative array element.
- * Input:
- *	flags	0	don't add value signature
- *		1	add value signature
- */
-
-Symbol *TypeAArray::aaGetSymbol(char *func, int flags)
-{
-  return 0;
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/tocsym.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,215 @@
+
+// Copyright (c) 1999-2005 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+// stubbed out for dmdfe. Original is in dmd/tocsym.c
+
+#include <stddef.h>
+
+#include "mars.h"
+#include "module.h"
+#include "mtype.h"
+#include "declaration.h"
+#include "statement.h"
+#include "enum.h"
+#include "aggregate.h"
+#include "init.h"
+#include "attrib.h"
+#include "lexer.h"
+#include "symbol.h"
+
+/********************************* SymbolDeclaration ****************************/
+
+SymbolDeclaration::SymbolDeclaration(Loc loc, Symbol *s, StructDeclaration *dsym)
+    : Declaration(new Identifier("", TOKidentifier))
+{
+}
+
+Symbol *SymbolDeclaration::toSymbol()
+{
+    return sym;
+}
+
+/*************************************
+ * Helper
+ */
+
+Symbol *Dsymbol::toSymbolX(const char *prefix, int sclass, TYPE *t, const char *suffix)
+{
+  return 0;
+}
+
+/*************************************
+ */
+
+Symbol *Dsymbol::toSymbol()
+{
+  return 0;
+}
+
+/*********************************
+ * Generate import symbol from symbol.
+ */
+
+Symbol *Dsymbol::toImport()
+{
+  return 0;
+}
+
+/*************************************
+ */
+
+Symbol *Dsymbol::toImport(Symbol *sym)
+{
+  return 0;
+}
+
+/*************************************
+ */
+
+Symbol *VarDeclaration::toSymbol()
+{
+  return 0;
+}
+
+/*************************************
+ */
+
+Symbol *ClassInfoDeclaration::toSymbol()
+{
+  return 0;
+}
+
+/*************************************
+ */
+
+Symbol *ModuleInfoDeclaration::toSymbol()
+{
+  return 0;
+}
+
+/*************************************
+ */
+
+Symbol *TypeInfoDeclaration::toSymbol()
+{
+  return 0;
+}
+
+/*************************************
+ */
+
+Symbol *FuncDeclaration::toSymbol()
+{
+
+    return 0;
+}
+
+/*************************************
+ */
+
+Symbol *FuncDeclaration::toThunkSymbol(int offset)
+{
+  return 0;
+}
+
+/*************************************
+ */
+
+Symbol *FuncAliasDeclaration::toSymbol()
+{
+
+    return 0;
+}
+
+
+/****************************************
+ * Create a static symbol we can hang DT initializers onto.
+ */
+
+Symbol *static_sym()
+{
+  return 0;
+}
+
+/*************************************
+ * Create the "ClassInfo" symbol
+ */
+
+Symbol *ClassDeclaration::toSymbol()
+{
+  return 0;
+}
+
+/*************************************
+ * Create the "InterfaceInfo" symbol
+ */
+
+Symbol *InterfaceDeclaration::toSymbol()
+{
+  return 0;
+}
+
+/*************************************
+ * Create the "ModuleInfo" symbol
+ */
+
+Symbol *Module::toSymbol()
+{
+  return 0;
+}
+
+/*************************************
+ * This is accessible via the ClassData, but since it is frequently
+ * needed directly (like for rtti comparisons), make it directly accessible.
+ */
+
+Symbol *ClassDeclaration::toVtblSymbol()
+{
+  return 0;
+}
+
+/**********************************
+ * Create the static initializer for the struct/class.
+ */
+
+Symbol *AggregateDeclaration::toInitializer()
+{
+  return 0;
+}
+
+
+/******************************************
+ */
+
+Symbol *Module::toModuleAssert()
+{
+  return 0;
+}
+
+/******************************************
+ */
+
+Symbol *Module::toModuleArray()
+{
+  return 0;
+}
+
+/********************************************
+ * Determine the right symbol to look up
+ * an associative array element.
+ * Input:
+ *	flags	0	don't add value signature
+ *		1	add value signature
+ */
+
+Symbol *TypeAArray::aaGetSymbol(char *func, int flags)
+{
+  return 0;
+}
+
--- a/gen/todebug.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,183 +0,0 @@
-#include "gen/llvm.h"
-#include "llvm/Support/Dwarf.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
-
-#include "declaration.h"
-#include "module.h"
-#include "mars.h"
-
-#include "gen/todebug.h"
-#include "gen/irstate.h"
-#include "gen/tollvm.h"
-#include "gen/logger.h"
-
-using namespace llvm::dwarf;
-
-static const llvm::PointerType* ptrTy(const llvm::Type* t)
-{
-    return llvm::PointerType::get(t);
-}
-
-static const llvm::PointerType* dbgArrTy()
-{
-    std::vector<const llvm::Type*> t;
-    return ptrTy(llvm::StructType::get(t));
-}
-
-static llvm::Constant* dbgToArrTy(llvm::Constant* c)
-{
-    Logger::cout() << "casting: " << *c << '\n';
-    return llvm::ConstantExpr::getBitCast(c, dbgArrTy());
-}
-
-#define Ty(X) llvm::Type::X
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-static llvm::GlobalVariable* dbg_compile_units = 0;
-static llvm::GlobalVariable* dbg_global_variables = 0;
-static llvm::GlobalVariable* dbg_subprograms = 0;
-
-const llvm::StructType* GetDwarfAnchorType()
-{
-    /*
-    %llvm.dbg.anchor.type = type {
-        uint,   ;; Tag = 0 + LLVMDebugVersion
-        uint    ;; Tag of descriptors grouped by the anchor
-    }
-    */
-    std::vector<const llvm::Type*> elems(2, Ty(Int32Ty));
-    const llvm::StructType* t = llvm::cast<llvm::StructType>(gIR->module->getTypeByName("llvm.dbg.anchor.type"));
-
-    /*
-    %llvm.dbg.compile_units       = linkonce constant %llvm.dbg.anchor.type  { uint 0, uint 17 } ;; DW_TAG_compile_unit
-    %llvm.dbg.global_variables    = linkonce constant %llvm.dbg.anchor.type  { uint 0, uint 52 } ;; DW_TAG_variable
-    %llvm.dbg.subprograms         = linkonce constant %llvm.dbg.anchor.type  { uint 0, uint 46 } ;; DW_TAG_subprogram
-    */
-    if (!gIR->module->getNamedGlobal("llvm.dbg.compile_units")) {
-        std::vector<llvm::Constant*> vals;
-        vals.push_back(DtoConstUint(0));
-        vals.push_back(DtoConstUint(DW_TAG_compile_unit));
-        llvm::Constant* i = llvm::ConstantStruct::get(t, vals);
-        dbg_compile_units = new llvm::GlobalVariable(t,true,llvm::GlobalValue::LinkOnceLinkage,i,"llvm.dbg.compile_units",gIR->module);
-        dbg_compile_units->setSection("llvm.metadata");
-    }
-    if (!gIR->module->getNamedGlobal("llvm.dbg.global_variables")) {
-        std::vector<llvm::Constant*> vals;
-        vals.push_back(DtoConstUint(0));
-        vals.push_back(DtoConstUint(DW_TAG_variable));
-        llvm::Constant* i = llvm::ConstantStruct::get(t, vals);
-        dbg_global_variables = new llvm::GlobalVariable(t,true,llvm::GlobalValue::LinkOnceLinkage,i,"llvm.dbg.global_variables",gIR->module);
-        dbg_global_variables->setSection("llvm.metadata");
-    }
-    if (!gIR->module->getNamedGlobal("llvm.dbg.subprograms")) {
-        std::vector<llvm::Constant*> vals;
-        vals.push_back(DtoConstUint(0));
-        vals.push_back(DtoConstUint(DW_TAG_subprogram));
-        llvm::Constant* i = llvm::ConstantStruct::get(t, vals);
-        dbg_subprograms = new llvm::GlobalVariable(t,true,llvm::GlobalValue::LinkOnceLinkage,i,"llvm.dbg.subprograms",gIR->module);
-        dbg_subprograms->setSection("llvm.metadata");
-    }
-
-    return t;
-}
-
-llvm::Constant* GetDwarfAnchor(llvm::dwarf::dwarf_constants c)
-{
-    GetDwarfAnchorType();
-    switch (c)
-    {
-    case DW_TAG_compile_unit:
-        return dbg_compile_units;
-    case DW_TAG_variable:
-        return dbg_global_variables;
-    case DW_TAG_subprogram:
-        return dbg_subprograms;
-    }
-    assert(0);
-    return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-const llvm::StructType* GetDwarfCompileUnitType() {
-    return llvm::cast<llvm::StructType>(gIR->module->getTypeByName("llvm.dbg.compile_unit.type"));
-}
-
-const llvm::StructType* GetDwarfSubProgramType() {
-    return llvm::cast<llvm::StructType>(gIR->module->getTypeByName("llvm.dbg.subprogram.type"));
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::GlobalVariable* DtoDwarfCompileUnit(Module* m)
-{
-    std::vector<llvm::Constant*> vals;
-    vals.push_back(llvm::ConstantExpr::getAdd(
-        DtoConstUint(DW_TAG_compile_unit),
-        DtoConstUint(llvm::LLVMDebugVersion)));
-    vals.push_back(dbgToArrTy(GetDwarfAnchor(DW_TAG_compile_unit)));
-
-    vals.push_back(DtoConstUint(DW_LANG_D));
-    vals.push_back(DtoConstStringPtr(m->srcfile->name->toChars(), "llvm.metadata"));
-    std::string srcpath(FileName::path(m->srcfile->name->toChars()));
-    srcpath.append("/");
-    vals.push_back(DtoConstStringPtr(srcpath.c_str(), "llvm.metadata"));
-    vals.push_back(DtoConstStringPtr("LLVMDC (http://www.dsource.org/projects/llvmdc)", "llvm.metadata"));
-
-    llvm::Constant* c = llvm::ConstantStruct::get(GetDwarfCompileUnitType(), vals);
-    llvm::GlobalVariable* gv = new llvm::GlobalVariable(c->getType(), true, llvm::GlobalValue::InternalLinkage, c, "llvm.dbg.compile_unit", gIR->module);
-    gv->setSection("llvm.metadata");
-    return gv;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::GlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd)
-{
-    std::vector<llvm::Constant*> vals;
-    vals.push_back(llvm::ConstantExpr::getAdd(
-        DtoConstUint(DW_TAG_subprogram),
-        DtoConstUint(llvm::LLVMDebugVersion)));
-    vals.push_back(dbgToArrTy(GetDwarfAnchor(DW_TAG_subprogram)));
-
-    vals.push_back(dbgToArrTy(gIR->dwarfCompileUnit));
-    vals.push_back(DtoConstStringPtr(fd->toPrettyChars(), "llvm.metadata"));
-    vals.push_back(DtoConstStringPtr(fd->mangle(), "llvm.metadata"));
-    vals.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
-    vals.push_back(dbgToArrTy(gIR->dwarfCompileUnit));
-    vals.push_back(DtoConstUint(fd->loc.linnum));
-    vals.push_back(llvm::ConstantPointerNull::get(dbgArrTy()));
-    vals.push_back(DtoConstBool(fd->protection == PROTprivate));
-    vals.push_back(DtoConstBool(fd->getModule() == gIR->dmodule));
-
-    llvm::Constant* c = llvm::ConstantStruct::get(GetDwarfSubProgramType(), vals);
-    llvm::GlobalVariable* gv = new llvm::GlobalVariable(c->getType(), true, llvm::GlobalValue::InternalLinkage, c, "llvm.dbg.subprogram", gIR->module);
-    gv->setSection("llvm.metadata");
-    return gv;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoDwarfFuncStart(FuncDeclaration* fd)
-{
-    assert(fd->llvmDwarfSubProgram);
-    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), dbgToArrTy(fd->llvmDwarfSubProgram));
-}
-
-void DtoDwarfFuncEnd(FuncDeclaration* fd)
-{
-    assert(fd->llvmDwarfSubProgram);
-    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), dbgToArrTy(fd->llvmDwarfSubProgram));
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoDwarfStopPoint(unsigned ln)
-{
-    std::vector<llvm::Value*> args;
-    args.push_back(DtoConstUint(ln));
-    args.push_back(DtoConstUint(0));
-    args.push_back(dbgToArrTy(gIR->dwarfCompileUnit));
-    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.stoppoint"), args.begin(), args.end());
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/todebug.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,183 @@
+#include "gen/llvm.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+
+#include "declaration.h"
+#include "module.h"
+#include "mars.h"
+
+#include "gen/todebug.h"
+#include "gen/irstate.h"
+#include "gen/tollvm.h"
+#include "gen/logger.h"
+
+using namespace llvm::dwarf;
+
+static const llvm::PointerType* ptrTy(const llvm::Type* t)
+{
+    return llvm::PointerType::get(t);
+}
+
+static const llvm::PointerType* dbgArrTy()
+{
+    std::vector<const llvm::Type*> t;
+    return ptrTy(llvm::StructType::get(t));
+}
+
+static llvm::Constant* dbgToArrTy(llvm::Constant* c)
+{
+    Logger::cout() << "casting: " << *c << '\n';
+    return llvm::ConstantExpr::getBitCast(c, dbgArrTy());
+}
+
+#define Ty(X) llvm::Type::X
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+static llvm::GlobalVariable* dbg_compile_units = 0;
+static llvm::GlobalVariable* dbg_global_variables = 0;
+static llvm::GlobalVariable* dbg_subprograms = 0;
+
+const llvm::StructType* GetDwarfAnchorType()
+{
+    /*
+    %llvm.dbg.anchor.type = type {
+        uint,   ;; Tag = 0 + LLVMDebugVersion
+        uint    ;; Tag of descriptors grouped by the anchor
+    }
+    */
+    std::vector<const llvm::Type*> elems(2, Ty(Int32Ty));
+    const llvm::StructType* t = llvm::cast<llvm::StructType>(gIR->module->getTypeByName("llvm.dbg.anchor.type"));
+
+    /*
+    %llvm.dbg.compile_units       = linkonce constant %llvm.dbg.anchor.type  { uint 0, uint 17 } ;; DW_TAG_compile_unit
+    %llvm.dbg.global_variables    = linkonce constant %llvm.dbg.anchor.type  { uint 0, uint 52 } ;; DW_TAG_variable
+    %llvm.dbg.subprograms         = linkonce constant %llvm.dbg.anchor.type  { uint 0, uint 46 } ;; DW_TAG_subprogram
+    */
+    if (!gIR->module->getNamedGlobal("llvm.dbg.compile_units")) {
+        std::vector<llvm::Constant*> vals;
+        vals.push_back(DtoConstUint(0));
+        vals.push_back(DtoConstUint(DW_TAG_compile_unit));
+        llvm::Constant* i = llvm::ConstantStruct::get(t, vals);
+        dbg_compile_units = new llvm::GlobalVariable(t,true,llvm::GlobalValue::LinkOnceLinkage,i,"llvm.dbg.compile_units",gIR->module);
+        dbg_compile_units->setSection("llvm.metadata");
+    }
+    if (!gIR->module->getNamedGlobal("llvm.dbg.global_variables")) {
+        std::vector<llvm::Constant*> vals;
+        vals.push_back(DtoConstUint(0));
+        vals.push_back(DtoConstUint(DW_TAG_variable));
+        llvm::Constant* i = llvm::ConstantStruct::get(t, vals);
+        dbg_global_variables = new llvm::GlobalVariable(t,true,llvm::GlobalValue::LinkOnceLinkage,i,"llvm.dbg.global_variables",gIR->module);
+        dbg_global_variables->setSection("llvm.metadata");
+    }
+    if (!gIR->module->getNamedGlobal("llvm.dbg.subprograms")) {
+        std::vector<llvm::Constant*> vals;
+        vals.push_back(DtoConstUint(0));
+        vals.push_back(DtoConstUint(DW_TAG_subprogram));
+        llvm::Constant* i = llvm::ConstantStruct::get(t, vals);
+        dbg_subprograms = new llvm::GlobalVariable(t,true,llvm::GlobalValue::LinkOnceLinkage,i,"llvm.dbg.subprograms",gIR->module);
+        dbg_subprograms->setSection("llvm.metadata");
+    }
+
+    return t;
+}
+
+llvm::Constant* GetDwarfAnchor(llvm::dwarf::dwarf_constants c)
+{
+    GetDwarfAnchorType();
+    switch (c)
+    {
+    case DW_TAG_compile_unit:
+        return dbg_compile_units;
+    case DW_TAG_variable:
+        return dbg_global_variables;
+    case DW_TAG_subprogram:
+        return dbg_subprograms;
+    }
+    assert(0);
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+const llvm::StructType* GetDwarfCompileUnitType() {
+    return llvm::cast<llvm::StructType>(gIR->module->getTypeByName("llvm.dbg.compile_unit.type"));
+}
+
+const llvm::StructType* GetDwarfSubProgramType() {
+    return llvm::cast<llvm::StructType>(gIR->module->getTypeByName("llvm.dbg.subprogram.type"));
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::GlobalVariable* DtoDwarfCompileUnit(Module* m)
+{
+    std::vector<llvm::Constant*> vals;
+    vals.push_back(llvm::ConstantExpr::getAdd(
+        DtoConstUint(DW_TAG_compile_unit),
+        DtoConstUint(llvm::LLVMDebugVersion)));
+    vals.push_back(dbgToArrTy(GetDwarfAnchor(DW_TAG_compile_unit)));
+
+    vals.push_back(DtoConstUint(DW_LANG_D));
+    vals.push_back(DtoConstStringPtr(m->srcfile->name->toChars(), "llvm.metadata"));
+    std::string srcpath(FileName::path(m->srcfile->name->toChars()));
+    srcpath.append("/");
+    vals.push_back(DtoConstStringPtr(srcpath.c_str(), "llvm.metadata"));
+    vals.push_back(DtoConstStringPtr("LLVMDC (http://www.dsource.org/projects/llvmdc)", "llvm.metadata"));
+
+    llvm::Constant* c = llvm::ConstantStruct::get(GetDwarfCompileUnitType(), vals);
+    llvm::GlobalVariable* gv = new llvm::GlobalVariable(c->getType(), true, llvm::GlobalValue::InternalLinkage, c, "llvm.dbg.compile_unit", gIR->module);
+    gv->setSection("llvm.metadata");
+    return gv;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::GlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd)
+{
+    std::vector<llvm::Constant*> vals;
+    vals.push_back(llvm::ConstantExpr::getAdd(
+        DtoConstUint(DW_TAG_subprogram),
+        DtoConstUint(llvm::LLVMDebugVersion)));
+    vals.push_back(dbgToArrTy(GetDwarfAnchor(DW_TAG_subprogram)));
+
+    vals.push_back(dbgToArrTy(gIR->dwarfCompileUnit));
+    vals.push_back(DtoConstStringPtr(fd->toPrettyChars(), "llvm.metadata"));
+    vals.push_back(DtoConstStringPtr(fd->mangle(), "llvm.metadata"));
+    vals.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
+    vals.push_back(dbgToArrTy(gIR->dwarfCompileUnit));
+    vals.push_back(DtoConstUint(fd->loc.linnum));
+    vals.push_back(llvm::ConstantPointerNull::get(dbgArrTy()));
+    vals.push_back(DtoConstBool(fd->protection == PROTprivate));
+    vals.push_back(DtoConstBool(fd->getModule() == gIR->dmodule));
+
+    llvm::Constant* c = llvm::ConstantStruct::get(GetDwarfSubProgramType(), vals);
+    llvm::GlobalVariable* gv = new llvm::GlobalVariable(c->getType(), true, llvm::GlobalValue::InternalLinkage, c, "llvm.dbg.subprogram", gIR->module);
+    gv->setSection("llvm.metadata");
+    return gv;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoDwarfFuncStart(FuncDeclaration* fd)
+{
+    assert(fd->llvmDwarfSubProgram);
+    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), dbgToArrTy(fd->llvmDwarfSubProgram));
+}
+
+void DtoDwarfFuncEnd(FuncDeclaration* fd)
+{
+    assert(fd->llvmDwarfSubProgram);
+    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), dbgToArrTy(fd->llvmDwarfSubProgram));
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoDwarfStopPoint(unsigned ln)
+{
+    std::vector<llvm::Value*> args;
+    args.push_back(DtoConstUint(ln));
+    args.push_back(DtoConstUint(0));
+    args.push_back(dbgToArrTy(gIR->dwarfCompileUnit));
+    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.stoppoint"), args.begin(), args.end());
+}
--- a/gen/todt.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-
-// Copyright (c) 1999-2005 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-// stubbed out for dmdfe. Original is in dmd/todt.c
-
-#include	"lexer.h"
-#include	"mtype.h"
-#include	"expression.h"
-#include	"init.h"
-#include	"enum.h"
-#include	"aggregate.h"
-#include	"declaration.h"
-
-struct dt_t {};
-
-dt_t *Initializer::toDt()
-{
-    return 0;
-}
-
-
-dt_t *StructInitializer::toDt()
-{
-    return 0;
-}
-
-
-dt_t *ArrayInitializer::toDt()
-{
-    return 0;
-}
-
-
-dt_t *ArrayInitializer::toDtBit()
-{
-    return 0;
-}
-
-
-dt_t *ExpInitializer::toDt()
-{
-    return 0;
-}
-
-dt_t *VoidInitializer::toDt()
-{
-    return 0;
-}
-
-/* ================================================================ */
-
-dt_t **Expression::toDt(dt_t **pdt)
-{
-    return 0;
-}
-
-dt_t **IntegerExp::toDt(dt_t **pdt)
-{
-    return 0;
-}
-
-dt_t **RealExp::toDt(dt_t **pdt)
-{
-    return 0;
-}
-
-dt_t **ComplexExp::toDt(dt_t **pdt)
-{
-    return 0;
-}
-
-dt_t **NullExp::toDt(dt_t **pdt)
-{
-    return 0;
-}
-
-dt_t **StringExp::toDt(dt_t **pdt)
-{
-    return 0;
-}
-
-dt_t **SymOffExp::toDt(dt_t **pdt)
-{
-    return 0;
-}
-
-dt_t **VarExp::toDt(dt_t **pdt)
-{
-    return 0;
-}
-
-dt_t **ArrayLiteralExp::toDt(dt_t **pdt)
-{
-    return 0;
-}
-dt_t **StructLiteralExp::toDt(dt_t **pdt)
-{
-    return 0;
-}
-
-void ClassDeclaration::toDt(dt_t **pdt)
-{
-}
-
-void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd)
-{
-}
-
-void StructDeclaration::toDt(dt_t **pdt)
-{
-}
-
-dt_t **Type::toDt(dt_t **pdt)
-{
-    return 0;
-}
-
-dt_t **TypeSArray::toDt(dt_t **pdt)
-{
-    return 0;
-}
-
-dt_t **TypeStruct::toDt(dt_t **pdt)
-{
-    return 0;
-}
-
-dt_t **TypeTypedef::toDt(dt_t **pdt)
-{
-    return 0;
-}
-
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/todt.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,140 @@
+
+// Copyright (c) 1999-2005 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+// stubbed out for dmdfe. Original is in dmd/todt.c
+
+#include	"lexer.h"
+#include	"mtype.h"
+#include	"expression.h"
+#include	"init.h"
+#include	"enum.h"
+#include	"aggregate.h"
+#include	"declaration.h"
+
+struct dt_t {};
+
+dt_t *Initializer::toDt()
+{
+    return 0;
+}
+
+
+dt_t *StructInitializer::toDt()
+{
+    return 0;
+}
+
+
+dt_t *ArrayInitializer::toDt()
+{
+    return 0;
+}
+
+
+dt_t *ArrayInitializer::toDtBit()
+{
+    return 0;
+}
+
+
+dt_t *ExpInitializer::toDt()
+{
+    return 0;
+}
+
+dt_t *VoidInitializer::toDt()
+{
+    return 0;
+}
+
+/* ================================================================ */
+
+dt_t **Expression::toDt(dt_t **pdt)
+{
+    return 0;
+}
+
+dt_t **IntegerExp::toDt(dt_t **pdt)
+{
+    return 0;
+}
+
+dt_t **RealExp::toDt(dt_t **pdt)
+{
+    return 0;
+}
+
+dt_t **ComplexExp::toDt(dt_t **pdt)
+{
+    return 0;
+}
+
+dt_t **NullExp::toDt(dt_t **pdt)
+{
+    return 0;
+}
+
+dt_t **StringExp::toDt(dt_t **pdt)
+{
+    return 0;
+}
+
+dt_t **SymOffExp::toDt(dt_t **pdt)
+{
+    return 0;
+}
+
+dt_t **VarExp::toDt(dt_t **pdt)
+{
+    return 0;
+}
+
+dt_t **ArrayLiteralExp::toDt(dt_t **pdt)
+{
+    return 0;
+}
+dt_t **StructLiteralExp::toDt(dt_t **pdt)
+{
+    return 0;
+}
+
+void ClassDeclaration::toDt(dt_t **pdt)
+{
+}
+
+void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd)
+{
+}
+
+void StructDeclaration::toDt(dt_t **pdt)
+{
+}
+
+dt_t **Type::toDt(dt_t **pdt)
+{
+    return 0;
+}
+
+dt_t **TypeSArray::toDt(dt_t **pdt)
+{
+    return 0;
+}
+
+dt_t **TypeStruct::toDt(dt_t **pdt)
+{
+    return 0;
+}
+
+dt_t **TypeTypedef::toDt(dt_t **pdt)
+{
+    return 0;
+}
+
+
+
--- a/gen/toir.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3161 +0,0 @@
-// Backend stubs
-
-/* DMDFE backend stubs
- * This file contains the implementations of the backend routines.
- * For dmdfe these do nothing but print a message saying the module
- * has been parsed. Substitute your own behaviors for these routimes.
- */
-
-#include <stdio.h>
-#include <math.h>
-#include <sstream>
-#include <fstream>
-#include <iostream>
-
-#include "gen/llvm.h"
-
-#include "total.h"
-#include "init.h"
-#include "symbol.h"
-#include "mtype.h"
-#include "hdrgen.h"
-#include "port.h"
-
-#include "gen/irstate.h"
-#include "gen/elem.h"
-#include "gen/logger.h"
-#include "gen/tollvm.h"
-#include "gen/runtime.h"
-#include "gen/arrays.h"
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* DeclarationExp::toElem(IRState* p)
-{
-    Logger::print("DeclarationExp::toElem: %s | T=%s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-    elem* e = new elem;
-
-    // variable declaration
-    if (VarDeclaration* vd = declaration->isVarDeclaration())
-    {
-        Logger::println("VarDeclaration");
-
-        // static
-        if (vd->isDataseg())
-        {
-            vd->toObjFile();
-        }
-        else
-        {
-            Logger::println("vdtype = %s", vd->type->toChars());
-            // referenced by nested delegate?
-            if (vd->nestedref) {
-                Logger::println("has nestedref set");
-                vd->llvmValue = p->func().decl->llvmNested;
-                assert(vd->llvmValue);
-                assert(vd->llvmNestedIndex >= 0);
-            }
-            // normal stack variable
-            else {
-                // allocate storage on the stack
-                const llvm::Type* lltype = DtoType(vd->type);
-                llvm::AllocaInst* allocainst = new llvm::AllocaInst(lltype, vd->toChars(), p->topallocapoint());
-                //allocainst->setAlignment(vd->type->alignsize()); // TODO
-                vd->llvmValue = allocainst;
-            }
-            elem* ie = DtoInitializer(vd->init);
-            delete ie;
-        }
-    }
-    // struct declaration
-    else if (StructDeclaration* s = declaration->isStructDeclaration())
-    {
-        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 - no work");
-        // do nothing
-    }
-    else if (EnumDeclaration* e = declaration->isEnumDeclaration())
-    {
-        Logger::println("EnumDeclaration - no work");
-        // do nothing
-    }
-    // unsupported declaration
-    else
-    {
-        error("Only Var/Struct-Declaration is supported for DeclarationExp");
-        assert(0);
-    }
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* VarExp::toElem(IRState* p)
-{
-    Logger::print("VarExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    elem* e = new elem;
-
-    assert(var);
-    if (VarDeclaration* vd = var->isVarDeclaration())
-    {
-        Logger::println("VarDeclaration %s", vd->toChars());
-
-        // _arguments
-        if (vd->ident == Id::_arguments)
-        {
-            Logger::println("Id::_arguments");
-            vd->llvmValue = p->func().decl->llvmArguments;
-            assert(vd->llvmValue);
-            e->mem = vd->llvmValue;
-            e->type = elem::VAR;
-        }
-        // _argptr
-        else if (vd->ident == Id::_argptr)
-        {
-            Logger::println("Id::_argptr");
-            vd->llvmValue = p->func().decl->llvmArgPtr;
-            assert(vd->llvmValue);
-            e->mem = vd->llvmValue;
-            e->type = elem::VAR;
-        }
-        // _dollar
-        else if (vd->ident == Id::dollar)
-        {
-            Logger::println("Id::dollar");
-            assert(!p->arrays.empty());
-            llvm::Value* tmp = DtoGEPi(p->arrays.back(),0,0,"tmp",p->scopebb());
-            e->val = new llvm::LoadInst(tmp,"tmp",p->scopebb());
-            e->type = elem::VAL;
-        }
-        // typeinfo
-        else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
-        {
-            Logger::println("TypeInfoDeclaration");
-            tid->toObjFile();
-            assert(tid->llvmValue);
-            const llvm::Type* vartype = DtoType(type);
-            if (tid->llvmValue->getType() != llvm::PointerType::get(vartype))
-                e->mem = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp");
-            else
-                e->mem = tid->llvmValue;
-            e->type = elem::VAR;
-        }
-        // nested variable
-        else if (vd->nestedref) {
-            Logger::println("nested variable");
-            e->mem = DtoNestedVariable(vd);
-            e->type = elem::VAR;
-            e->vardecl = vd;
-        }
-        // function parameter
-        else if (vd->isParameter()) {
-            Logger::println("function param");
-            if (!vd->llvmValue) {
-                // TODO: determine this properly
-                // this happens when the DMD frontend generates by pointer wrappers for struct opEquals(S) and opCmp(S)
-                vd->llvmValue = &p->func().func->getArgumentList().back();
-            }
-            if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa<llvm::AllocaInst>(vd->llvmValue)) {
-                e->mem = vd->llvmValue;
-                e->type = elem::VAR;
-                e->vardecl = vd;
-            }
-            else if (llvm::isa<llvm::Argument>(vd->llvmValue)) {
-                e->val = vd->llvmValue;
-                e->type = elem::VAL;
-                e->vardecl = vd;
-            }
-            else assert(0);
-        }
-        else {
-            // take care of forward references of global variables
-            if (!vd->llvmTouched && vd->isDataseg())
-                vd->toObjFile();
-            assert(vd->llvmValue);
-            e->mem = vd->llvmValue;
-            e->vardecl = vd;
-            e->type = elem::VAR;
-        }
-
-        assert(e->mem || e->val);
-    }
-    else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
-    {
-        Logger::println("FuncDeclaration");
-        if (fdecl->llvmInternal != LLVMva_arg && fdecl->llvmValue == 0)
-            fdecl->toObjFile();
-        e->val = fdecl->llvmValue;
-        e->type = elem::FUNC;
-        e->funcdecl = fdecl;
-    }
-    else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
-    {
-        // this seems to be the static initialiser for structs
-        Type* sdecltype = 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;
-    }
-    else
-    {
-        assert(0 && "Unimplemented VarExp type");
-    }
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-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 = 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 = DtoType(type);
-    if (llvm::isa<llvm::PointerType>(t)) {
-        llvm::Constant* i = llvm::ConstantInt::get(DtoSize_t(),(uint64_t)value,false);
-        return llvm::ConstantExpr::getIntToPtr(i, t);
-    }
-    else if (llvm::isa<llvm::IntegerType>(t)) {
-        return llvm::ConstantInt::get(t,(uint64_t)value,!type->isunsigned());
-    }
-    assert(0);
-    return NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* RealExp::toElem(IRState* p)
-{
-    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;
-    Type* t = DtoDType(type);
-    const llvm::Type* fty = DtoType(t);
-    if (t->ty == Tfloat32 || t->ty == Timaginary32)
-        return llvm::ConstantFP::get(fty,float(value));
-    else if (t->ty == Tfloat64 || t->ty == Timaginary64 || t->ty == Tfloat80 || t->ty == Timaginary80)
-        return llvm::ConstantFP::get(fty,double(value));
-    assert(0);
-    return NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* NullExp::toElem(IRState* p)
-{
-    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 = DtoType(type);
-    if (type->ty == Tarray) {
-        assert(llvm::isa<llvm::StructType>(t));
-        return llvm::ConstantAggregateZero::get(t);
-    }
-    else {
-        return llvm::Constant::getNullValue(t);
-    }
-    assert(0);
-    return NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* StringExp::toElem(IRState* p)
-{
-    Logger::print("StringExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    Type* dtype = DtoDType(type);
-
-    assert(dtype->next->ty == Tchar && "Only char is supported");
-    assert(sz == 1);
-
-    const llvm::Type* ct = DtoType(dtype->next);
-    //printf("ct = %s\n", type->next->toChars());
-    const llvm::ArrayType* at = llvm::ArrayType::get(ct,len+1);
-
-    uint8_t* str = (uint8_t*)string;
-    std::string cont((char*)str, len);
-
-    llvm::Constant* _init = llvm::ConstantArray::get(cont,true);
-
-    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
-    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::Constant* idxs[2] = { zero, zero };
-    llvm::Constant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
-
-    elem* e = new elem;
-
-    if (dtype->ty == Tarray) {
-        llvm::Constant* clen = llvm::ConstantInt::get(DtoSize_t(),len,false);
-        if (!p->topexp() || p->topexp()->e2 != this) {
-            llvm::Value* tmpmem = new llvm::AllocaInst(DtoType(dtype),"tempstring",p->topallocapoint());
-            DtoSetArray(tmpmem, clen, arrptr);
-            e->mem = tmpmem;
-            e->temp = true;
-        }
-        else if (p->topexp()->e2 == this) {
-            llvm::Value* arr = p->topexp()->v;
-            assert(arr);
-            DtoSetArray(arr, clen, arrptr);
-            e->inplace = true;
-        }
-        else
-        assert(0);
-    }
-    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 (dtype->ty == Tpointer) {
-        e->mem = arrptr;
-    }
-    else {
-        assert(0);
-    }
-
-    e->type = elem::VAL;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-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 = DtoDType(type);
-
-    if (t->ty == Tsarray) {
-        return llvm::ConstantArray::get(cont,false);
-    }
-    llvm::Constant* _init = llvm::ConstantArray::get(cont,true);
-
-    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(DtoSize_t(),len,false);
-        return DtoConstSlice(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 ? e2->type->toChars() : 0);
-    LOG_SCOPE;
-
-    p->exps.push_back(IRExp(e1,e2,NULL));
-
-    elem* l = e1->toElem(p);
-    p->topexp()->v = l->mem;
-    elem* r = e2->toElem(p);
-
-    p->exps.pop_back();
-
-    if (l->type == elem::ARRAYLEN)
-    {
-        DtoResizeDynArray(l->mem, r->getValue());
-        delete r;
-        delete l;
-        return 0;
-    }
-
-    Type* e1type = DtoDType(e1->type);
-    Type* e2type = 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) {
-                DtoStructCopy(l->mem,r->getValue());
-            }
-            else {
-                e->inplace = true;
-            }
-        }
-        // struct + const int
-        else if (e2type->isintegral()){
-            IntegerExp* iexp = (IntegerExp*)e2;
-            assert(iexp->value == 0 && "Only integral struct initializer allowed is zero");
-            DtoStructZeroInit(l->mem);
-        }
-        // :x
-        else
-        assert(0 && "struct = unknown");
-    }
-    else if (e1ty == Tsarray) {
-        assert(0 && "static array not supported");
-    }
-    else if (e1ty == Tarray) {
-        if (e2type->isscalar() || e2type->ty == Tclass){
-            DtoArrayInit(l->mem, r->getValue());
-        }
-        else if (e2ty == Tarray) {
-            //new llvm::StoreInst(r->val,l->val,p->scopebb());
-            if (r->type == elem::NUL) {
-                llvm::Constant* c = llvm::cast<llvm::Constant>(r->val);
-                assert(c->isNullValue());
-                DtoNullArray(l->mem);
-                e->mem = l->mem;
-            }
-            else if (r->type == elem::SLICE) {
-                if (l->type == elem::SLICE) {
-                    DtoArrayCopy(l,r);
-                    e->type = elem::SLICE;
-                    e->mem = l->mem;
-                    e->arg = l->arg;
-                }
-                else {
-                    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);
-                    DtoArrayAssign(l->mem, r->mem);
-                }
-                else {
-                    e->inplace = true;
-                }
-            }
-        }
-        else
-        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';
-            new llvm::StoreInst(v, l->mem, p->scopebb());
-        }
-        else
-        assert(0);
-    }
-    else if (e1ty == Tclass) {
-        if (e2ty == Tclass) {
-            llvm::Value* tmp = r->getValue();
-            Logger::cout() << "tmp: " << *tmp << " ||| " << *l->mem << '\n';
-            // assignment to this in constructor special case
-            if (l->isthis) {
-                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
-        assert(0);
-    }
-    else if (e1ty == Tdelegate) {
-        Logger::println("Assigning to delegate");
-        if (e2ty == Tdelegate) {
-            if (r->type == elem::NUL) {
-                llvm::Constant* c = llvm::cast<llvm::Constant>(r->val);
-                if (c->isNullValue()) {
-                    DtoNullDelegate(l->mem);
-                    e->mem = l->mem;
-                }
-                else
-                assert(0);
-            }
-            else if (r->inplace) {
-                // do nothing
-                e->inplace = true;
-                e->mem = l->mem;
-            }
-            else {
-                DtoDelegateCopy(l->mem, r->getValue());
-                e->mem = l->mem;
-            }
-        }
-        else
-        assert(0);
-    }
-    // !struct && !array && !pointer && !class
-    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;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* AddExp::toElem(IRState* p)
-{
-    Logger::print("AddExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-    elem* e = new elem;
-    elem* l = e1->toElem(p);
-    elem* r = e2->toElem(p);
-
-    Type* t = DtoDType(type);
-    Type* e1type = DtoDType(e1->type);
-    Type* e2type = 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*)e1type->next;
-            std::vector<unsigned> offsets;
-            e->mem = DtoIndexStruct(l->getValue(), ts->sym, t->next, cofs->getZExtValue(), offsets);
-            e->type = elem::VAR;
-            e->field = true;
-        }
-        else if (e1->type->ty == Tpointer) {
-            e->val = new llvm::GetElementPtrInst(l->getValue(), r->getValue(), "tmp", p->scopebb());
-            e->type = elem::VAR;
-        }
-        else {
-            assert(0);
-        }
-    }
-    else {
-        e->val = llvm::BinaryOperator::createAdd(l->getValue(), r->getValue(), "tmp", p->scopebb());
-        e->type = elem::VAL;
-    }
-    delete l;
-    delete r;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* AddAssignExp::toElem(IRState* p)
-{
-    Logger::print("AddAssignExp::toElem: %s\n", toChars());
-    LOG_SCOPE;
-
-    elem* l = e1->toElem(p);
-    elem* r = e2->toElem(p);
-
-    Type* e1type = DtoDType(e1->type);
-
-    elem* e = new elem;
-    llvm::Value* val = 0;
-    if (e1type->ty == Tpointer) {
-        val = e->mem = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    }
-    else {
-        val = e->val = llvm::BinaryOperator::createAdd(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    }
-
-    /*llvm::Value* storeVal = l->storeVal ? l->storeVal : l->val;
-    if (llvm::isa<llvm::PointerType>(storeVal->getType()) && storeVal->getType()->getContainedType(0) != tmp->getType())
-    {
-        tmp = DtoPointedType(storeVal, tmp);
-    }*/
-
-    assert(l->mem);
-    new llvm::StoreInst(val,l->mem,p->scopebb());
-    e->type = elem::VAR;
-
-    delete l;
-    delete r;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* MinExp::toElem(IRState* p)
-{
-    Logger::print("MinExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-    elem* e = new elem;
-    elem* l = e1->toElem(p);
-    elem* r = e2->toElem(p);
-
-    llvm::Value* left = l->getValue();
-    if (llvm::isa<llvm::PointerType>(left->getType()))
-        left = new llvm::PtrToIntInst(left,DtoSize_t(),"tmp",p->scopebb());
-
-    llvm::Value* right = r->getValue();
-    if (llvm::isa<llvm::PointerType>(right->getType()))
-        right = new llvm::PtrToIntInst(right,DtoSize_t(),"tmp",p->scopebb());
-
-    e->val = llvm::BinaryOperator::createSub(left,right,"tmp",p->scopebb());
-    e->type = elem::VAL;
-
-    const llvm::Type* totype = DtoType(type);
-    if (e->val->getType() != totype) {
-        assert(0);
-        assert(llvm::isa<llvm::PointerType>(e->val->getType()));
-        assert(llvm::isa<llvm::IntegerType>(totype));
-        e->val = new llvm::IntToPtrInst(e->val,totype,"tmp",p->scopebb());
-    }
-
-    delete l;
-    delete r;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* MinAssignExp::toElem(IRState* p)
-{
-    Logger::print("MinAssignExp::toElem: %s\n", toChars());
-    LOG_SCOPE;
-
-    elem* l = e1->toElem(p);
-    elem* r = e2->toElem(p);
-
-    Type* e1type = DtoDType(e1->type);
-
-    llvm::Value* tmp = 0;
-    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());
-        tmp = new llvm::GetElementPtrInst(l->getValue(),tmp,"tmp",p->scopebb());
-    }
-    else {
-        tmp = llvm::BinaryOperator::createSub(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    }
-
-    /*llvm::Value* storeVal = l->storeVal ? l->storeVal : l->val;
-    if (storeVal->getType()->getContainedType(0) != tmp->getType())
-    {
-        tmp = DtoPointedType(storeVal, tmp);
-    }*/
-
-    assert(l->mem);
-    new llvm::StoreInst(tmp, l->mem, p->scopebb());
-
-    delete l;
-    delete r;
-
-    elem* e = new elem;
-    e->val = tmp;
-    e->type = elem::VAR;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* MulExp::toElem(IRState* p)
-{
-    Logger::print("MulExp::toElem: %s\n", toChars());
-    LOG_SCOPE;
-    elem* e = new elem;
-    elem* l = e1->toElem(p);
-    elem* r = e2->toElem(p);
-    llvm::Value* vl = l->getValue();
-    llvm::Value* vr = r->getValue();
-    Logger::cout() << "mul: " << *vl << ", " << *vr << '\n';
-    e->val = llvm::BinaryOperator::createMul(vl,vr,"tmp",p->scopebb());
-    e->type = elem::VAL;
-    delete l;
-    delete r;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* MulAssignExp::toElem(IRState* p)
-{
-    Logger::print("MulAssignExp::toElem: %s\n", toChars());
-    LOG_SCOPE;
-
-    elem* l = e1->toElem(p);
-    elem* r = e2->toElem(p);
-    llvm::Value* vl = l->getValue();
-    llvm::Value* vr = r->getValue();
-    Logger::cout() << "mulassign: " << *vl << ", " << *vr << '\n';
-    llvm::Value* tmp = llvm::BinaryOperator::createMul(vl,vr,"tmp",p->scopebb());
-
-    /*llvm::Value* storeVal = l->storeVal ? l->storeVal : l->val;
-    if (storeVal->getType()->getContainedType(0) != tmp->getType())
-    {
-        tmp = DtoPointedType(storeVal, tmp);
-    }*/
-
-    assert(l->mem);
-    new llvm::StoreInst(tmp,l->mem,p->scopebb());
-
-    delete l;
-    delete r;
-
-    elem* e = new elem;
-    e->val = tmp;
-    e->type = elem::VAR;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* DivExp::toElem(IRState* p)
-{
-    Logger::print("DivExp::toElem: %s\n", toChars());
-    LOG_SCOPE;
-    elem* e = new elem;
-    elem* l = e1->toElem(p);
-    elem* r = e2->toElem(p);
-
-    Type* t = DtoDType(type);
-
-    if (t->isunsigned())
-        e->val = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (t->isintegral())
-        e->val = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (t->isfloating())
-        e->val = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else
-        assert(0);
-    e->type = elem::VAL;
-    delete l;
-    delete r;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* DivAssignExp::toElem(IRState* p)
-{
-    Logger::print("DivAssignExp::toElem: %s\n", toChars());
-    LOG_SCOPE;
-
-    elem* l = e1->toElem(p);
-    elem* r = e2->toElem(p);
-
-    Type* t = DtoDType(type);
-
-    llvm::Value* tmp;
-    if (t->isunsigned())
-        tmp = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (t->isintegral())
-        tmp = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (t->isfloating())
-        tmp = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else
-        assert(0);
-
-    /*llvm::Value* storeVal = l->storeVal ? l->storeVal : l->val;
-    if (storeVal->getType()->getContainedType(0) != tmp->getType())
-    {
-        tmp = DtoPointedType(storeVal, tmp);
-    }*/
-
-    assert(l->mem);
-    new llvm::StoreInst(tmp,l->mem,p->scopebb());
-
-    delete l;
-    delete r;
-
-    elem* e = new elem;
-    e->val = tmp;
-    e->type = elem::VAR;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* ModExp::toElem(IRState* p)
-{
-    Logger::print("ModExp::toElem: %s\n", toChars());
-    LOG_SCOPE;
-    elem* e = new elem;
-    elem* l = e1->toElem(p);
-    elem* r = e2->toElem(p);
-
-    Type* t = DtoDType(type);
-
-    if (t->isunsigned())
-        e->val = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (t->isintegral())
-        e->val = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (t->isfloating())
-        e->val = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else
-        assert(0);
-    e->type = elem::VAL;
-    delete l;
-    delete r;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* ModAssignExp::toElem(IRState* p)
-{
-    Logger::print("ModAssignExp::toElem: %s\n", toChars());
-    LOG_SCOPE;
-
-    elem* l = e1->toElem(p);
-    elem* r = e2->toElem(p);
-
-    Type* t = DtoDType(type);
-
-    llvm::Value* tmp;
-    if (t->isunsigned())
-        tmp = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (t->isintegral())
-        tmp = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (t->isfloating())
-        tmp = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else
-        assert(0);
-
-    /*llvm::Value* storeVal = l->storeVal ? l->storeVal : l->val;
-    if (storeVal->getType()->getContainedType(0) != tmp->getType())
-    {
-        tmp = DtoPointedType(storeVal, tmp);
-    }*/
-
-    assert(l->mem);
-    new llvm::StoreInst(tmp,l->mem,p->scopebb());
-
-    delete l;
-    delete r;
-
-    elem* e = new elem;
-    e->val = tmp;
-    e->type = elem::VAR;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* CallExp::toElem(IRState* p)
-{
-    Logger::print("CallExp::toElem: %s\n", toChars());
-    LOG_SCOPE;
-
-    elem* e = new elem;
-    elem* fn = e1->toElem(p);
-
-    TypeFunction* tf = 0;
-    Type* e1type = DtoDType(e1->type);
-
-    bool delegateCall = false;
-    llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false);
-    llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty,1,false);
-    LINK dlink = LINKdefault;
-
-    // hidden struct return parameter handling
-    bool retinptr = false;
-
-    // regular functions
-    if (e1type->ty == Tfunction) {
-        tf = (TypeFunction*)e1type;
-        if (tf->llvmRetInPtr) {
-            retinptr = true;
-        }
-        dlink = tf->linkage;
-    }
-
-    // delegates
-    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;
-        }
-        dlink = tf->linkage;
-        delegateCall = true;
-    }
-
-    // invalid
-    else {
-        assert(tf);
-    }
-
-    // va args
-    bool va_magic = false;
-    bool va_intrinsic = false;
-    if (fn->funcdecl) {
-        if (fn->funcdecl->llvmInternal == LLVMva_intrinsic) {
-            va_magic = true;
-            va_intrinsic = true;
-        }
-        else if (fn->funcdecl->llvmInternal == LLVMva_start) {
-            va_magic = true;
-        }
-        else if (fn->funcdecl->llvmInternal == LLVMva_arg) {
-            //Argument* fnarg = Argument::getNth(tf->parameters, 0);
-            Expression* exp = (Expression*)arguments->data[0];
-            elem* expelem = exp->toElem(p);
-            assert(expelem->mem);
-            elem* e = new elem;
-            Type* t = DtoDType(type);
-            const llvm::Type* llt = DtoType(type);
-            if (DtoIsPassedByRef(t))
-                llt = llvm::PointerType::get(llt);
-            e->type = elem::VAL;
-            e->val = p->ir->CreateVAArg(expelem->mem,llt,"tmp");
-            delete expelem;
-            return e;
-        }
-    }
-
-    // args
-    size_t n = arguments->dim;
-    if (fn->funcdecl && fn->funcdecl->llvmInternal == LLVMva_start)
-        n = 1;
-    if (fn->arg || delegateCall) n++;
-    if (retinptr) n++;
-    if (tf->linkage == LINKd && tf->varargs == 1) n+=2;
-    if (fn->funcdecl && fn->funcdecl->isNested()) n++;
-
-    llvm::Value* funcval = fn->getValue();
-    assert(funcval != 0);
-    std::vector<llvm::Value*> llargs(n, 0);
-
-    const llvm::FunctionType* llfnty = 0;
-
-    // normal function call
-    if (llvm::isa<llvm::FunctionType>(funcval->getType())) {
-        llfnty = llvm::cast<llvm::FunctionType>(funcval->getType());
-    }
-    // pointer to something
-    else if (llvm::isa<llvm::PointerType>(funcval->getType())) {
-        // pointer to function pointer - I think this not really supposed to happen, but does :/
-        // seems like sometimes we get a func* other times a func**
-        if (llvm::isa<llvm::PointerType>(funcval->getType()->getContainedType(0))) {
-            funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
-        }
-        // function pointer
-        if (llvm::isa<llvm::FunctionType>(funcval->getType()->getContainedType(0))) {
-            //Logger::cout() << "function pointer type:\n" << *funcval << '\n';
-            llfnty = llvm::cast<llvm::FunctionType>(funcval->getType()->getContainedType(0));
-        }
-        // struct pointer - delegate
-        else if (llvm::isa<llvm::StructType>(funcval->getType()->getContainedType(0))) {
-            funcval = DtoGEP(funcval,zero,one,"tmp",p->scopebb());
-            funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
-            const llvm::Type* ty = funcval->getType()->getContainedType(0);
-            llfnty = llvm::cast<llvm::FunctionType>(ty);
-        }
-        // unknown
-        else {
-            Logger::cout() << "what kind of pointer are we calling? : " << *funcval->getType() << '\n';
-        }
-    }
-    else {
-        Logger::cout() << "what are we calling? : " << *funcval << '\n';
-    }
-    assert(llfnty);
-    //Logger::cout() << "Function LLVM type: " << *llfnty << '\n';
-
-    // argument handling
-    llvm::FunctionType::param_iterator argiter = llfnty->param_begin();
-    int j = 0;
-
-    IRExp* topexp = p->topexp();
-
-    // hidden struct return arguments
-    if (retinptr) {
-        if (topexp && topexp->e2 == this) {
-            assert(topexp->v);
-            assert(llvm::isa<llvm::StructType>(topexp->v->getType()->getContainedType(0)));
-            llargs[j] = topexp->v;
-            if (DtoIsPassedByRef(tf->next)) {
-                e->inplace = true;
-            }
-            else
-            assert(0);
-        }
-        else {
-            llargs[j] = new llvm::AllocaInst(argiter->get()->getContainedType(0),"rettmp",p->topallocapoint());
-        }
-        ++j;
-        ++argiter;
-        e->type = elem::VAR;
-    }
-    else {
-        e->type = elem::VAL;
-    }
-
-    // this arguments
-    if (fn->arg) {
-        Logger::println("This Call");
-        if (fn->arg->getType() != argiter->get()) {
-            //Logger::cout() << *fn->thisparam << '|' << *argiter->get() << '\n';
-            llargs[j] = new llvm::BitCastInst(fn->arg, argiter->get(), "tmp", p->scopebb());
-        }
-        else {
-            llargs[j] = fn->arg;
-        }
-        ++j;
-        ++argiter;
-    }
-    // delegate context arguments
-    else if (delegateCall) {
-        Logger::println("Delegate Call");
-        llvm::Value* contextptr = DtoGEP(fn->mem,zero,zero,"tmp",p->scopebb());
-        llargs[j] = new llvm::LoadInst(contextptr,"tmp",p->scopebb());
-        ++j;
-        ++argiter;
-    }
-    // nested call
-    else if (fn->funcdecl && fn->funcdecl->isNested()) {
-        Logger::println("Nested Call");
-        llvm::Value* contextptr = p->func().decl->llvmNested;
-        assert(contextptr);
-        llargs[j] = p->ir->CreateBitCast(contextptr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
-        ++j;
-        ++argiter;
-    }
-
-    // va arg function special argument passing
-    if (va_magic) {
-        size_t n = va_intrinsic ? arguments->dim : 1;
-        for (int i=0; i<n; i++,j++)
-        {
-            Argument* fnarg = Argument::getNth(tf->parameters, i);
-            Expression* exp = (Expression*)arguments->data[i];
-            elem* expelem = exp->toElem(p);
-            assert(expelem->mem);
-            llargs[j] = p->ir->CreateBitCast(expelem->mem, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
-            delete expelem;
-        }
-    }
-    // regular arguments
-    else {
-        if (tf->linkage == LINKd && tf->varargs == 1)
-        {
-            Logger::println("doing d-style variadic arguments");
-
-            std::vector<const llvm::Type*> vtypes;
-            std::vector<llvm::Value*> vvalues;
-            std::vector<llvm::Value*> vtypeinfos;
-
-            for (int i=0; i<arguments->dim; i++) {
-                Argument* fnarg = Argument::getNth(tf->parameters, i);
-                Expression* argexp = (Expression*)arguments->data[i];
-                vvalues.push_back(DtoArgument(NULL, fnarg, argexp));
-                vtypes.push_back(vvalues.back()->getType());
-
-                TypeInfoDeclaration* tidecl = argexp->type->getTypeInfoDeclaration();
-                tidecl->toObjFile();
-                assert(tidecl->llvmValue);
-                vtypeinfos.push_back(tidecl->llvmValue);
-            }
-
-            const llvm::StructType* vtype = llvm::StructType::get(vtypes);
-            llvm::Value* mem = new llvm::AllocaInst(vtype,"_argptr_storage",p->topallocapoint());
-            for (unsigned i=0; i<vtype->getNumElements(); ++i)
-                p->ir->CreateStore(vvalues[i], DtoGEPi(mem,0,i,"tmp"));
-
-            //llvm::Constant* typeinfoparam = llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(llfnty->getParamType(j)));
-            assert(Type::typeinfo->llvmInitZ);
-            const llvm::Type* typeinfotype = llvm::PointerType::get(Type::typeinfo->llvmInitZ->getType());
-            Logger::cout() << "typeinfo ptr type: " << *typeinfotype << '\n';
-            const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements());
-            llvm::Value* typeinfomem = new llvm::AllocaInst(typeinfoarraytype,"_arguments_storage",p->topallocapoint());
-            for (unsigned i=0; i<vtype->getNumElements(); ++i) {
-                llvm::Value* v = p->ir->CreateBitCast(vtypeinfos[i], typeinfotype, "tmp");
-                p->ir->CreateStore(v, DtoGEPi(typeinfomem,0,i,"tmp"));
-            }
-
-            llvm::Value* typeinfoarrayparam = new llvm::AllocaInst(llfnty->getParamType(j)->getContainedType(0),"_arguments_array",p->topallocapoint());
-            p->ir->CreateStore(DtoConstSize_t(vtype->getNumElements()), DtoGEPi(typeinfoarrayparam,0,0,"tmp"));
-            llvm::Value* casttypeinfomem = p->ir->CreateBitCast(typeinfomem, llvm::PointerType::get(typeinfotype), "tmp");
-            p->ir->CreateStore(casttypeinfomem, DtoGEPi(typeinfoarrayparam,0,1,"tmp"));
-
-            llargs[j] = typeinfoarrayparam;;
-            j++;
-            llargs[j] = p->ir->CreateBitCast(mem, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
-            j++;
-            llargs.resize(2);
-        }
-        else {
-            Logger::println("doing normal arguments");
-            for (int i=0; i<arguments->dim; i++,j++) {
-                Argument* fnarg = Argument::getNth(tf->parameters, i);
-                llargs[j] = DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]);
-            }
-            Logger::println("%d params passed", n);
-            for (int i=0; i<n; ++i) {
-                Logger::cout() << *llargs[i] << '\n';
-            }
-        }
-    }
-
-    // void returns cannot not be named
-    const char* varname = "";
-    if (llfnty->getReturnType() != llvm::Type::VoidTy)
-        varname = "tmp";
-
-    Logger::cout() << "Calling: " << *funcval->getType() << '\n';
-
-    // call the function
-    llvm::CallInst* call = new llvm::CallInst(funcval, llargs.begin(), llargs.end(), varname, p->scopebb());
-    if (retinptr)
-        e->mem = llargs[0];
-    else
-        e->val = call;
-
-    // set calling convention
-    if (fn->funcdecl) {
-        int li = fn->funcdecl->llvmInternal;
-        if (li != LLVMintrinsic && li != LLVMva_start && li != LLVMva_intrinsic) {
-            call->setCallingConv(DtoCallingConv(dlink));
-        }
-    }
-    else if (delegateCall) {
-        call->setCallingConv(DtoCallingConv(dlink));
-    }
-    else if (fn->callconv != (unsigned)-1) {
-        call->setCallingConv(fn->callconv);
-    }
-
-    delete fn;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* CastExp::toElem(IRState* p)
-{
-    Logger::print("CastExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-    elem* e = new elem;
-    elem* u = e1->toElem(p);
-    const llvm::Type* tolltype = DtoType(to);
-    Type* fromtype = DtoDType(e1->type);
-    Type* totype = 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 (fromtype->isintegral()) {
-        if (totype->isintegral()) {
-            if (lsz < rsz) {
-                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(), tolltype, "tmp", p->scopebb());
-                }
-            }
-            else if (lsz > rsz) {
-                e->val = new llvm::TruncInst(u->getValue(), tolltype, "tmp", p->scopebb());
-            }
-            else {
-                e->val = new llvm::BitCastInst(u->getValue(), tolltype, "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(), tolltype, "tmp", p->scopebb());
-            }
-        }
-        else if (totype->ty == Tpointer) {
-            e->val = p->ir->CreateIntToPtr(u->getValue(), tolltype, "tmp");
-        }
-        else {
-            assert(0);
-        }
-        //e->storeVal = u->storeVal ? u->storeVal : u->val;
-        e->type = elem::VAL;
-    }
-    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(), tolltype, "tmp", p->scopebb());
-            }
-            else if (lsz > rsz) {
-                e->val = new llvm::FPTruncInst(u->getValue(), tolltype, "tmp", p->scopebb());
-            }
-            else {
-                assert(0);
-            }
-        }
-        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(), tolltype, "tmp", p->scopebb());
-            }
-        }
-        else {
-            assert(0);
-        }
-        e->type = elem::VAL;
-    }
-    else if (fromtype->ty == Tclass) {
-        //assert(to->ty == Tclass);
-        e->val = new llvm::BitCastInst(u->getValue(), tolltype, "tmp", p->scopebb());
-        e->type = elem::VAL;
-    }
-    else if (fromtype->ty == Tarray || fromtype->ty == Tsarray) {
-        Logger::cout() << "from array or sarray" << '\n';
-        if (totype->ty == Tpointer) {
-            Logger::cout() << "to pointer" << '\n';
-            assert(fromtype->next == totype->next || totype->next->ty == Tvoid);
-            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 = DtoGEP(u->getValue(),zero,one,"tmp",p->scopebb());
-            e->val = new llvm::LoadInst(ptr, "tmp", p->scopebb());
-            if (fromtype->next != totype->next)
-                e->val = p->ir->CreateBitCast(e->val, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
-            e->type = elem::VAL;
-        }
-        else if (totype->ty == Tarray) {
-            Logger::cout() << "to array" << '\n';
-            const llvm::Type* ptrty = DtoType(totype->next);
-            if (ptrty == llvm::Type::VoidTy)
-                ptrty = llvm::Type::Int8Ty;
-            ptrty = llvm::PointerType::get(ptrty);
-
-            const llvm::Type* ety = DtoType(fromtype->next);
-            if (ety == llvm::Type::VoidTy)
-                ety = llvm::Type::Int8Ty;
-
-            if (u->type == elem::SLICE) {
-                e->mem = new llvm::BitCastInst(u->mem, ptrty, "tmp", p->scopebb());
-                if (fromtype->next->size() == totype->next->size())
-                    e->arg = u->arg;
-                else
-                    e->arg = DtoArrayCastLength(u->arg, ety, ptrty->getContainedType(0));
-            }
-            else {
-                llvm::Value* uval = u->getValue();
-                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));
-                    e->arg = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
-                    e->arg = DtoArrayCastLength(e->arg, ety, ptrty->getContainedType(0));
-                    e->mem = new llvm::BitCastInst(uval, ptrty, "tmp", p->scopebb());
-                }
-                else {
-                    llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-                    llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
-                    e->arg = DtoGEP(uval,zero,zero,"tmp",p->scopebb());
-                    e->arg = new llvm::LoadInst(e->arg, "tmp", p->scopebb());
-                    e->arg = DtoArrayCastLength(e->arg, ety, ptrty->getContainedType(0));
-
-                    e->mem = DtoGEP(uval,zero,one,"tmp",p->scopebb());
-                    e->mem = new llvm::LoadInst(e->mem, "tmp", p->scopebb());
-                    //Logger::cout() << *e->mem->getType() << '|' << *ptrty << '\n';
-                    e->mem = new llvm::BitCastInst(e->mem, ptrty, "tmp", p->scopebb());
-                }
-            }
-            e->type = elem::SLICE;
-        }
-        else if (totype->ty == Tsarray) {
-            Logger::cout() << "to sarray" << '\n';
-            assert(0);
-        }
-        else {
-            assert(0);
-        }
-    }
-    else if (fromtype->ty == Tpointer) {
-        if (totype->ty == Tpointer || totype->ty == Tclass) {
-            llvm::Value* src = u->getValue();
-            Logger::cout() << *src << '|' << *tolltype << '\n';
-            e->val = new llvm::BitCastInst(src, tolltype, "tmp", p->scopebb());
-        }
-        else if (totype->isintegral()) {
-            e->val = new llvm::PtrToIntInst(u->getValue(), tolltype, "tmp", p->scopebb());
-        }
-        else
-        assert(0);
-        e->type = elem::VAL;
-    }
-    else {
-        assert(0);
-    }
-    delete u;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* SymOffExp::toElem(IRState* p)
-{
-    Logger::print("SymOffExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-    elem* e = 0;
-    if (VarDeclaration* vd = var->isVarDeclaration())
-    {
-        Logger::println("VarDeclaration");
-        if (!vd->llvmTouched && vd->isDataseg())
-            vd->toObjFile();
-
-        if (vd->isTypedefDeclaration()) {
-            e->istypeinfo = true;
-        }
-
-        assert(vd->llvmValue);
-        Type* t = DtoDType(type);
-        Type* tnext = DtoDType(t->next);
-        Type* vdtype = DtoDType(vd->type);
-
-        llvm::Value* llvalue = vd->nestedref ? DtoNestedVariable(vd) : vd->llvmValue;
-
-        if (vdtype->ty == Tstruct && !(t->ty == Tpointer && t->next == vdtype)) {
-            Logger::println("struct");
-            TypeStruct* vdt = (TypeStruct*)vdtype;
-            assert(vdt->sym);
-            e = new elem;
-            const llvm::Type* llt = DtoType(t);
-            if (offset == 0) {
-                e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp");
-            }
-            else {
-                std::vector<unsigned> dst;
-                e->mem = DtoIndexStruct(llvalue,vdt->sym, tnext, offset, dst);
-            }
-            e->type = elem::VAL;
-            e->field = true;
-        }
-        else if (vdtype->ty == Tsarray) {
-            Logger::println("sarray");
-            e = new elem;
-            assert(llvalue);
-            e->arg = llvalue;
-            e->type = elem::VAL;
-
-            const llvm::Type* llt = DtoType(t);
-            llvm::Value* off = 0;
-            if (offset != 0) {
-                Logger::println("offset = %d\n", offset);
-            }
-            if (llvalue->getType() != llt) {
-                e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp");
-                if (offset != 0)
-                    e->mem = DtoGEPi(e->mem, offset, "tmp");
-            }
-            else {
-                assert(offset == 0);
-                e->mem = DtoGEPi(llvalue,0,0,"tmp");
-            }
-        }
-        else if (offset == 0) {
-            Logger::println("normal symoff");
-            e = new elem;
-            e->type = elem::VAL;
-            assert(llvalue);
-            e->mem = llvalue;
-
-            const llvm::Type* llt = DtoType(t);
-            if (llvalue->getType() != llt) {
-                e->mem = p->ir->CreateBitCast(e->mem, llt, "tmp");
-            }
-        }
-        else {
-            assert(0);
-        }
-    }
-    else if (FuncDeclaration* fd = var->isFuncDeclaration())
-    {
-        Logger::println("FuncDeclaration");
-        e = new elem;
-        if (fd->llvmValue == 0)
-            fd->toObjFile();
-        e->val = fd->llvmValue;
-        e->type = elem::FUNC;
-    }
-    assert(e != 0);
-    assert(e->type != elem::NONE);
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* PtrExp::toElem(IRState* p)
-{
-    Logger::print("PtrExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-    elem* e = new elem;
-    elem* a = e1->toElem(p);
-
-    if (a->mem)
-        Logger::cout() << "mem: " << *a->mem << '\n';
-    if (a->val)
-        Logger::cout() << "val: " << *a->val << '\n';
-
-    if (a->field)
-        e->mem = a->mem;
-    else
-        e->mem = a->getValue();
-    e->type = elem::VAR;
-
-    delete a;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* DotVarExp::toElem(IRState* p)
-{
-    Logger::print("DotVarExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-    elem* e = new elem;
-
-    elem* l = e1->toElem(p);
-
-    Type* t = DtoDType(type);
-    Type* e1type = DtoDType(e1->type);
-
-    Logger::print("e1->type=%s\n", e1type->toChars());
-
-    if (VarDeclaration* vd = var->isVarDeclaration()) {
-        llvm::Value* arrptr;
-        if (e1type->ty == Tpointer) {
-            assert(e1type->next->ty == Tstruct);
-            TypeStruct* ts = (TypeStruct*)e1type->next;
-            Logger::println("Struct member offset:%d", vd->offset);
-            llvm::Value* src = l->val ? l->val : l->mem;
-            std::vector<unsigned> vdoffsets;
-            arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
-        }
-        else if (e1->type->ty == Tclass) {
-            TypeClass* tc = (TypeClass*)e1type;
-            Logger::println("Class member offset: %d", vd->offset);
-            std::vector<unsigned> vdoffsets(1,0);
-            tc->sym->offsetToIndex(vd->type, vd->offset, vdoffsets);
-            llvm::Value* src = l->getValue();
-            Logger::cout() << "src: " << *src << '\n';
-            arrptr = DtoGEP(src,vdoffsets,"tmp",p->scopebb());
-        }
-        else
-            assert(0);
-        e->mem = arrptr;
-        Logger::cout() << "mem: " << *e->mem << '\n';
-        e->type = elem::VAR;
-    }
-    else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
-    {
-        if (fdecl->llvmValue == 0)
-        {
-            fdecl->toObjFile();
-        }
-
-        llvm::Value* funcval = fdecl->llvmValue;
-        e->arg = l->getValue();
-
-        // virtual call
-        if (fdecl->isVirtual()) {
-            assert(fdecl->vtblIndex > 0);
-            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);
-            funcval = DtoGEP(e->arg, zero, zero, "tmp", p->scopebb());
-            funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
-            funcval = DtoGEP(funcval, zero, vtblidx, toChars(), p->scopebb());
-            funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
-            assert(funcval->getType() == fdecl->llvmValue->getType());
-            e->callconv = DtoCallingConv(fdecl->linkage);
-        }
-        e->val = funcval;
-        e->type = elem::FUNC;
-        e->funcdecl = fdecl;
-    }
-    else {
-        printf("unknown: %s\n", var->toChars());
-        assert(0);
-    }
-
-    delete l;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* ThisExp::toElem(IRState* p)
-{
-    Logger::print("ThisExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-    elem* e = new elem;
-
-    if (VarDeclaration* vd = var->isVarDeclaration()) {
-        llvm::Value* v = p->func().decl->llvmThisVar;
-        if (llvm::isa<llvm::AllocaInst>(v))
-            v = new llvm::LoadInst(v, "tmp", p->scopebb());
-        e->mem = v;
-        e->type = elem::VAL;
-        e->isthis = true;
-    }
-    else {
-        assert(0);
-    }
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* AddrExp::toElem(IRState* p)
-{
-    Logger::print("AddrExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-    elem* e = e1->toElem(p);
-    e->field = true;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* StructLiteralExp::toElem(IRState* p)
-{
-    Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-    elem* e = new elem;
-
-    llvm::Value* sptr;
-    const llvm::Type* llt = DtoType(type);
-
-    // temporary struct literal
-    if (!p->topexp() || p->topexp()->e2 != this)
-    {
-        sptr = new llvm::AllocaInst(llt,"tmpstructliteral",p->topallocapoint());
-        e->mem = sptr;
-        e->type = elem::VAR;
-    }
-    // already has memory
-    else
-    {
-        assert(p->topexp()->e2 == this);
-        sptr = p->topexp()->v;
-    }
-
-    // num elements in literal
-    unsigned n = elements->dim;
-
-    // unions might have different types for each literal
-    if (sd->llvmHasUnions) {
-        // build the type of the literal
-        std::vector<const llvm::Type*> tys;
-        for (unsigned i=0; i<n; ++i) {
-            Expression* vx = (Expression*)elements->data[i];
-            if (!vx) continue;
-            tys.push_back(DtoType(vx->type));
-        }
-        const llvm::StructType* t = llvm::StructType::get(tys);
-        if (t != llt) {
-            if (gTargetData->getTypeSize(t) != gTargetData->getTypeSize(llt)) { 
-                Logger::cout() << "got size " << gTargetData->getTypeSize(t) << ", expected " << gTargetData->getTypeSize(llt) << '\n';
-                assert(0 && "type size mismatch");
-            }
-            sptr = p->ir->CreateBitCast(sptr, llvm::PointerType::get(t), "tmp");
-            Logger::cout() << "sptr type is now: " << *t << '\n';
-        }
-    }
-
-    // build
-    unsigned j = 0;
-    for (unsigned i=0; i<n; ++i)
-    {
-        Expression* vx = (Expression*)elements->data[i];
-        if (!vx) continue;
-
-        Logger::cout() << "getting index " << j << " of " << *sptr << '\n';
-        llvm::Value* arrptr = DtoGEPi(sptr,0,j,"tmp",p->scopebb());
-
-        p->exps.push_back(IRExp(NULL,vx,arrptr));
-        elem* ve = vx->toElem(p);
-        p->exps.pop_back();
-
-        if (!ve->inplace) {
-            llvm::Value* val = ve->getValue();
-            Logger::cout() << *val << " | " << *arrptr << '\n';
-
-            Type* vxtype = DtoDType(vx->type);
-            DtoAssign(vxtype, arrptr, val);
-        }
-        delete ve;
-
-        j++;
-    }
-
-    e->inplace = true;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-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(DtoDType(type)->ty == Tstruct);
-    const llvm::Type* t = 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());
-    LOG_SCOPE;
-
-    elem* e = new elem;
-
-    elem* l = e1->toElem(p);
-
-    Type* e1type = 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();
-
-    llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-    llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
-
-    llvm::Value* arrptr = 0;
-    if (e1type->ty == Tpointer) {
-        arrptr = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    }
-    else if (e1type->ty == Tsarray) {
-        arrptr = DtoGEP(l->getValue(), zero, r->getValue(),"tmp",p->scopebb());
-    }
-    else if (e1type->ty == Tarray) {
-        arrptr = 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());
-    }
-    assert(arrptr);
-
-    e->mem = arrptr;
-    e->type = elem::VAR;
-
-    delete l;
-    delete r;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* SliceExp::toElem(IRState* p)
-{
-    Logger::print("SliceExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    Type* t = DtoDType(type);
-    assert(t->ty == Tarray);
-
-    elem* v = e1->toElem(p);
-    Type* e1type = DtoDType(e1->type);
-
-    elem* e = new elem;
-    assert(v->mem);
-    e->type = elem::SLICE;
-
-    llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-    llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
-
-    // partial slice
-    if (lwr)
-    {
-        assert(upr);
-        p->arrays.push_back(v->mem);
-        elem* lo = lwr->toElem(p);
-
-        bool lwr_is_zero = false;
-        if (lo->type == elem::CONST)
-        {
-            assert(lo->val);
-            assert(llvm::isa<llvm::ConstantInt>(lo->val));
-
-            if (e1type->ty == Tpointer) {
-                e->mem = v->getValue();
-            }
-            else if (e1type->ty == Tarray) {
-                llvm::Value* tmp = DtoGEP(v->mem,zero,one,"tmp",p->scopebb());
-                e->mem = new llvm::LoadInst(tmp,"tmp",p->scopebb());
-            }
-            else if (e1type->ty == Tsarray) {
-                e->mem = DtoGEP(v->mem,zero,zero,"tmp",p->scopebb());
-            }
-            else
-            assert(e->mem);
-
-            llvm::ConstantInt* c = llvm::cast<llvm::ConstantInt>(lo->val);
-            if (!(lwr_is_zero = c->isZero())) {
-                e->mem = new llvm::GetElementPtrInst(e->mem,lo->val,"tmp",p->scopebb());
-            }
-        }
-        else
-        {
-            if (e1type->ty == Tarray) {
-                llvm::Value* tmp = 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 = DtoGEP(v->mem,zero,lo->getValue(),"tmp",p->scopebb());
-            }
-            else if (e1type->ty == Tpointer) {
-                e->mem = new llvm::GetElementPtrInst(v->getValue(),lo->getValue(),"tmp",p->scopebb());
-            }
-            else {
-                Logger::println("type = %s", e1type->toChars());
-                assert(0);
-            }
-        }
-
-        elem* up = upr->toElem(p);
-        p->arrays.pop_back();
-
-        if (up->type == elem::CONST)
-        {
-            assert(up->val);
-            assert(llvm::isa<llvm::ConstantInt>(up->val));
-            if (lwr_is_zero) {
-                e->arg = up->val;
-            }
-            else {
-                if (lo->type == elem::CONST) {
-                    llvm::Constant* clo = llvm::cast<llvm::Constant>(lo->val);
-                    llvm::Constant* cup = llvm::cast<llvm::Constant>(up->val);
-                    e->arg = llvm::ConstantExpr::getSub(cup, clo);
-                }
-                else {
-                    e->arg = llvm::BinaryOperator::createSub(up->val, lo->getValue(), "tmp", p->scopebb());
-                }
-            }
-        }
-        else
-        {
-            if (lwr_is_zero) {
-                e->arg = up->getValue();
-            }
-            else {
-                e->arg = llvm::BinaryOperator::createSub(up->getValue(), lo->getValue(), "tmp", p->scopebb());
-            }
-        }
-
-        delete lo;
-        delete up;
-
-        /*
-        llvm::Value* tmpmem = new llvm::AllocaInst(DtoType(t),"tmp",p->topallocapoint());
-        llvm::Value* ptr = DtoGEPi(tmpmem,0,0,"tmp");
-        p->ir->CreateStore(e->arg, ptr);
-        ptr = DtoGEPi(tmpmem,0,1,"tmp");
-        p->ir->CreateStore(e->mem, ptr);
-        e->arg = NULL;
-        e->mem = tmpmem;
-        */
-    }
-    // full slice
-    else
-    {
-        e->mem = v->mem;
-    }
-
-    delete v;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* CmpExp::toElem(IRState* p)
-{
-    Logger::print("CmpExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    elem* e = new elem;
-
-    elem* l = e1->toElem(p);
-    elem* r = e2->toElem(p);
-
-    Type* t = DtoDType(e1->type);
-    Type* e2t = DtoDType(e2->type);
-    assert(t == e2t);
-
-    if (t->isintegral() || t->ty == Tpointer)
-    {
-        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);
-        }
-        if (!skip)
-        {
-            e->val = new llvm::ICmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb());
-        }
-    }
-    else if (t->isfloating())
-    {
-        llvm::FCmpInst::Predicate cmpop;
-        switch(op)
-        {
-        case TOKlt:
-            cmpop = llvm::FCmpInst::FCMP_OLT;break;
-        case TOKle:
-            cmpop = llvm::FCmpInst::FCMP_OLE;break;
-        case TOKgt:
-            cmpop = llvm::FCmpInst::FCMP_OGT;break;
-        case TOKge:
-            cmpop = llvm::FCmpInst::FCMP_OGE;break;
-        case TOKunord:
-            cmpop = llvm::FCmpInst::FCMP_UNO;break;
-        case TOKule:
-            cmpop = llvm::FCmpInst::FCMP_ULE;break;
-        case TOKul:
-            cmpop = llvm::FCmpInst::FCMP_ULT;break;
-        case TOKuge:
-            cmpop = llvm::FCmpInst::FCMP_UGE;break;
-        case TOKug:
-            cmpop = llvm::FCmpInst::FCMP_UGT;break;
-        case TOKue:
-            cmpop = llvm::FCmpInst::FCMP_UEQ;break;
-        case TOKlg:
-            cmpop = llvm::FCmpInst::FCMP_ONE;break;
-        case TOKleg:
-            cmpop = llvm::FCmpInst::FCMP_ORD;break;
-
-        default:
-            assert(0);
-        }
-        e->val = new llvm::FCmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb());
-    }
-    else
-    {
-        assert(0 && "Unsupported CmpExp type");
-    }
-
-    delete l;
-    delete r;
-
-    e->type = elem::VAL;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* EqualExp::toElem(IRState* p)
-{
-    Logger::print("EqualExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    elem* e = new elem;
-
-    elem* l = e1->toElem(p);
-    elem* r = e2->toElem(p);
-
-    Type* t = DtoDType(e1->type);
-    Type* e2t = DtoDType(e2->type);
-    assert(t == e2t);
-
-    if (t->isintegral() || t->ty == Tpointer)
-    {
-        Logger::println("integral or pointer");
-        llvm::ICmpInst::Predicate cmpop;
-        switch(op)
-        {
-        case TOKequal:
-            cmpop = llvm::ICmpInst::ICMP_EQ;
-            break;
-        case TOKnotequal:
-            cmpop = llvm::ICmpInst::ICMP_NE;
-            break;
-        default:
-            assert(0);
-        }
-        e->val = new llvm::ICmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb());
-    }
-    else if (t->isfloating())
-    {
-        Logger::println("floating");
-        llvm::FCmpInst::Predicate cmpop;
-        switch(op)
-        {
-        case TOKequal:
-            cmpop = llvm::FCmpInst::FCMP_OEQ;
-            break;
-        case TOKnotequal:
-            cmpop = llvm::FCmpInst::FCMP_UNE;
-            break;
-        default:
-            assert(0);
-        }
-        e->val = new llvm::FCmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb());
-    }
-    else if (t->ty == Tsarray)
-    {
-        Logger::println("static array");
-        e->val = DtoStaticArrayCompare(op,l->mem,r->mem);
-    }
-    else if (t->ty == Tarray)
-    {
-        Logger::println("dynamic array");
-        e->val = DtoDynArrayCompare(op,l->mem,r->mem);
-    }
-    else if (t->ty == Tdelegate)
-    {
-        Logger::println("delegate");
-        e->val = DtoCompareDelegate(op,l->mem,r->mem);
-    }
-    else
-    {
-        assert(0 && "Unsupported EqualExp type");
-    }
-
-    delete l;
-    delete r;
-
-    e->type = elem::VAL;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* PostExp::toElem(IRState* p)
-{
-    Logger::print("PostExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    elem* l = e1->toElem(p);
-    elem* r = e2->toElem(p);
-
-    elem* e = new elem;
-    e->mem = l->mem;
-    e->val = l->getValue();
-    e->type = elem::VAL;
-
-    llvm::Value* val = e->val;
-    llvm::Value* post = 0;
-
-    Type* e1type = DtoDType(e1->type);
-    Type* e2type = DtoDType(e2->type);
-
-    if (e1type->isintegral())
-    {
-        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());
-        }
-        else if (op == TOKminusminus) {
-            post = llvm::BinaryOperator::createSub(val,one,"tmp",p->scopebb());
-        }
-    }
-    else if (e1type->ty == Tpointer)
-    {
-        assert(e2type->isintegral());
-        llvm::Constant* minusone = llvm::ConstantInt::get(DtoSize_t(),(uint64_t)-1,true);
-        llvm::Constant* plusone = llvm::ConstantInt::get(DtoSize_t(),(uint64_t)1,false);
-        llvm::Constant* whichone = (op == TOKplusplus) ? plusone : minusone;
-        post = new llvm::GetElementPtrInst(val, whichone, "tmp", p->scopebb());
-    }
-    else if (e1type->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());
-        }
-        else if (op == TOKminusminus) {
-            post = llvm::BinaryOperator::createSub(val,one,"tmp",p->scopebb());
-        }
-    }
-    else
-    assert(post);
-
-    assert(l->mem);
-    new llvm::StoreInst(post,l->mem,p->scopebb());
-
-    delete l;
-    delete r;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* NewExp::toElem(IRState* p)
-{
-    Logger::print("NewExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    assert(!thisexp);
-    assert(!newargs);
-    assert(newtype);
-    assert(!allocator);
-
-    elem* e = new elem;
-    e->inplace = true;
-
-    Type* ntype = DtoDType(newtype);
-
-    const llvm::Type* t = DtoType(ntype);
-
-    if (onstack) {
-        assert(ntype->ty == Tclass);
-        e->mem = new llvm::AllocaInst(t->getContainedType(0),"tmp",p->topallocapoint());
-    }
-    else {
-        if (ntype->ty == Tclass) {
-            e->mem = new llvm::MallocInst(t->getContainedType(0),"tmp",p->scopebb());
-        }
-        else if (ntype->ty == Tarray) {
-            assert(arguments);
-            if (arguments->dim == 1) {
-                elem* sz = ((Expression*)arguments->data[0])->toElem(p);
-                llvm::Value* dimval = sz->getValue();
-                Type* nnt = DtoDType(ntype->next);
-                if (nnt->ty == Tvoid)
-                    nnt = Type::tint8;
-                if (!p->topexp() || p->topexp()->e2 != this) {
-                    const llvm::Type* restype = DtoType(type);
-                    Logger::cout() << "restype = " << *restype << '\n';
-                    e->mem = new llvm::AllocaInst(restype,"tmp",p->topallocapoint());
-                    DtoNewDynArray(e->mem, dimval, nnt);
-                    e->inplace = false;
-                }
-                else if (p->topexp() || p->topexp()->e2 != this) {
-                    assert(p->topexp()->v);
-                    e->mem = p->topexp()->v;
-                    DtoNewDynArray(e->mem, dimval, nnt);
-                }
-                else
-                assert(0);
-                delete sz;
-            }
-            else {
-                assert(0);
-            }
-        }
-        else {
-            e->mem = new llvm::MallocInst(t,"tmp",p->scopebb());
-        }
-    }
-
-    if (ntype->ty == Tclass) {
-        // first apply the static initializer
-        assert(e->mem);
-        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*)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];
-                Argument* fnarg = Argument::getNth(tf->parameters, i);
-                llvm::Value* a = DtoArgument(fn->getFunctionType()->getParamType(i+1), fnarg, ex);
-                ctorargs.push_back(a);
-            }
-            e->mem = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb());
-        }
-    }
-    else if (ntype->ty == Tstruct) {
-        TypeStruct* ts = (TypeStruct*)ntype;
-        if (ts->isZeroInit()) {
-            DtoStructZeroInit(e->mem);
-        }
-        else {
-            DtoStructCopy(e->mem,ts->llvmInit);
-        }
-    }
-
-    e->type = elem::VAR;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* DeleteExp::toElem(IRState* p)
-{
-    Logger::print("DeleteExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    //assert(e1->type->ty != Tclass);
-
-    elem* v = e1->toElem(p);
-    llvm::Value* val = v->getValue();
-    llvm::Value* ldval = 0;
-
-    const llvm::Type* t = val->getType();
-    llvm::Constant* z = llvm::Constant::getNullValue(t);
-
-    Type* e1type = DtoDType(e1->type);
-
-    if (e1type->ty == Tpointer) {
-        ldval = v->getValue();
-        new llvm::FreeInst(ldval, p->scopebb());
-
-        Logger::cout() << *z << '\n';
-        Logger::cout() << *val << '\n';
-        new llvm::StoreInst(z, v->mem, p->scopebb());
-    }
-    else if (e1type->ty == Tclass) {
-        TypeClass* tc = (TypeClass*)e1type;
-        DtoCallClassDtors(tc, val);
-
-        if (v->vardecl && !v->vardecl->onstack) {
-            new llvm::FreeInst(val, p->scopebb());
-        }
-        new llvm::StoreInst(z, v->mem, p->scopebb());
-    }
-    else if (e1type->ty == Tarray) {
-        // must be on the heap (correct?)
-        ldval = v->getValue();
-        
-        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 = DtoGEP(ldval,zero,one,"tmp",p->scopebb());
-        ptr = new llvm::LoadInst(ptr,"tmp",p->scopebb());
-        new llvm::FreeInst(ptr, p->scopebb());
-        DtoNullArray(val);
-    }
-    else {
-        assert(0);
-    }
-
-    delete v;
-
-    // this expression produces no useful data
-    return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* ArrayLengthExp::toElem(IRState* p)
-{
-    Logger::print("ArrayLengthExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    elem* e = new elem;
-    elem* u = e1->toElem(p);
-
-    if (p->topexp() && p->topexp()->e1 == this)
-    {
-        e->mem = u->mem;
-        e->type = elem::ARRAYLEN;
-    }
-    else
-    {
-        llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-        llvm::Value* ptr = DtoGEP(u->mem,zero,zero,"tmp",p->scopebb());
-        e->val = new llvm::LoadInst(ptr, "tmp", p->scopebb());
-        e->type = elem::VAL;
-    }
-    delete u;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* AssertExp::toElem(IRState* p)
-{
-    Logger::print("AssertExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    elem* u = e1->toElem(p);
-    elem* m = msg ? msg->toElem(p) : NULL;
-
-    llvm::Value* loca = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
-    DtoAssert(u->getValue(), loca, m ? m->val : NULL);
-
-    delete m;
-    delete u;
-
-    return new elem;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* NotExp::toElem(IRState* p)
-{
-    Logger::print("NotExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    elem* e = new elem;
-    elem* u = e1->toElem(p);
-
-    llvm::Value* b = DtoBoolean(u->getValue());
-
-    llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int1Ty, 0, true);
-    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;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* AndAndExp::toElem(IRState* p)
-{
-    Logger::print("AndAndExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    // allocate a temporary for the final result. failed to come up with a better way :/
-    llvm::Value* resval = 0;
-    llvm::BasicBlock* entryblock = &p->topfunc()->front();
-    resval = new llvm::AllocaInst(llvm::Type::Int1Ty,"andandtmp",p->topallocapoint());
-    
-    elem* e = new elem;
-    elem* u = e1->toElem(p);
-
-    llvm::BasicBlock* oldend = p->scopeend();
-    llvm::BasicBlock* andand = new llvm::BasicBlock("andand", gIR->topfunc(), oldend);
-    llvm::BasicBlock* andandend = new llvm::BasicBlock("andandend", gIR->topfunc(), oldend);
-    
-    llvm::Value* ubool = DtoBoolean(u->getValue());
-    new llvm::StoreInst(ubool,resval,p->scopebb());
-    new llvm::BranchInst(andand,andandend,ubool,p->scopebb());
-    
-    p->scope() = IRScope(andand, andandend);
-    elem* v = e2->toElem(p);
-
-    llvm::Value* vbool = DtoBoolean(v->getValue());
-    llvm::Value* uandvbool = llvm::BinaryOperator::create(llvm::BinaryOperator::And, ubool, vbool,"tmp",p->scopebb());
-    new llvm::StoreInst(uandvbool,resval,p->scopebb());
-    new llvm::BranchInst(andandend,p->scopebb());
-
-    delete u;
-    delete v;
-
-    p->scope() = IRScope(andandend, oldend);
-    
-    e->val = new llvm::LoadInst(resval,"tmp",p->scopebb());
-    e->type = elem::VAL;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* OrOrExp::toElem(IRState* p)
-{
-    Logger::print("OrOrExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    // allocate a temporary for the final result. failed to come up with a better way :/
-    llvm::Value* resval = 0;
-    llvm::BasicBlock* entryblock = &p->topfunc()->front();
-    resval = new llvm::AllocaInst(llvm::Type::Int1Ty,"orortmp",p->topallocapoint());
-    
-    elem* e = new elem;
-    elem* u = e1->toElem(p);
-
-    llvm::BasicBlock* oldend = p->scopeend();
-    llvm::BasicBlock* oror = new llvm::BasicBlock("oror", gIR->topfunc(), oldend);
-    llvm::BasicBlock* ororend = new llvm::BasicBlock("ororend", gIR->topfunc(), oldend);
-    
-    llvm::Value* ubool = DtoBoolean(u->getValue());
-    new llvm::StoreInst(ubool,resval,p->scopebb());
-    new llvm::BranchInst(ororend,oror,ubool,p->scopebb());
-    
-    p->scope() = IRScope(oror, ororend);
-    elem* v = e2->toElem(p);
-
-    llvm::Value* vbool = DtoBoolean(v->getValue());
-    new llvm::StoreInst(vbool,resval,p->scopebb());
-    new llvm::BranchInst(ororend,p->scopebb());
-
-    delete u;
-    delete v;
-
-    p->scope() = IRScope(ororend, oldend);
-    
-    e->val = new llvm::LoadInst(resval,"tmp",p->scopebb());
-    e->type = elem::VAL;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-#define BinBitExp(X,Y) \
-elem* X##Exp::toElem(IRState* p) \
-{ \
-    Logger::print("%sExp::toElem: %s | %s\n", #X, toChars(), type->toChars()); \
-    LOG_SCOPE; \
-    elem* e = new elem; \
-    elem* u = e1->toElem(p); \
-    elem* v = e2->toElem(p); \
-    e->val = llvm::BinaryOperator::create(llvm::Instruction::Y, u->getValue(), v->getValue(), "tmp", p->scopebb()); \
-    e->type = elem::VAL; \
-    delete u; \
-    delete v; \
-    return e; \
-} \
-\
-elem* X##AssignExp::toElem(IRState* p) \
-{ \
-    Logger::print("%sAssignExp::toElem: %s | %s\n", #X, toChars(), type->toChars()); \
-    LOG_SCOPE; \
-    elem* u = e1->toElem(p); \
-    elem* v = e2->toElem(p); \
-    llvm::Value* uval = u->getValue(); \
-    assert(uval); \
-    llvm::Value* vval = v->getValue(); \
-    assert(vval); \
-    llvm::Value* tmp = llvm::BinaryOperator::create(llvm::Instruction::Y, uval, vval, "tmp", p->scopebb()); \
-    assert(u->mem); \
-    Logger::cout() << *tmp << '|' << *u->mem << '\n'; \
-    new llvm::StoreInst(DtoPointedType(u->mem, tmp), u->mem, p->scopebb()); \
-    delete u; \
-    delete v; \
-    elem* e = new elem; \
-    e->mem = u->mem; \
-    e->type = elem::VAR; \
-    return e; \
-}
-
-BinBitExp(And,And);
-BinBitExp(Or,Or);
-BinBitExp(Xor,Xor);
-BinBitExp(Shl,Shl);
-BinBitExp(Shr,AShr);
-BinBitExp(Ushr,LShr);
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* HaltExp::toElem(IRState* p)
-{
-    Logger::print("HaltExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    llvm::Value* loca = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
-    DtoAssert(llvm::ConstantInt::getFalse(), loca, NULL);
-
-    new llvm::UnreachableInst(p->scopebb());
-    return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* DelegateExp::toElem(IRState* p)
-{
-    Logger::print("DelegateExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    elem* e = new elem;
-    elem* u = e1->toElem(p);
-
-    llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-    llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
-
-    const llvm::Type* int8ptrty = llvm::PointerType::get(llvm::Type::Int8Ty);
-
-    assert(p->topexp() && p->topexp()->e2 == this && p->topexp()->v);
-    llvm::Value* lval = p->topexp()->v;
-
-    llvm::Value* context = DtoGEP(lval,zero,zero,"tmp",p->scopebb());
-    llvm::Value* castcontext = new llvm::BitCastInst(u->getValue(),int8ptrty,"tmp",p->scopebb());
-    new llvm::StoreInst(castcontext, context, p->scopebb());
-
-    llvm::Value* fptr = DtoGEP(lval,zero,one,"tmp",p->scopebb());
-
-    assert(func->llvmValue);
-    llvm::Value* castfptr = new llvm::BitCastInst(func->llvmValue,fptr->getType()->getContainedType(0),"tmp",p->scopebb());
-    new llvm::StoreInst(castfptr, fptr, p->scopebb());
-
-    e->inplace = true;
-
-    delete u;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* IdentityExp::toElem(IRState* p)
-{
-    Logger::print("IdentityExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    elem* u = e1->toElem(p);
-    elem* v = e2->toElem(p);
-
-    elem* e = new elem;
-
-    llvm::Value* l = u->field ? u->mem : u->getValue();
-    llvm::Value* r = v->field ? v->mem : v->getValue();
-
-    Type* t1 = DtoDType(e1->type);
-
-    if (t1->ty == Tarray) {
-        if (v->type == elem::NUL) {
-            r = NULL;
-        }
-        else {
-            assert(l->getType() == r->getType());
-        }
-        e->val = DtoDynArrayIs(op,l,r);
-    }
-    else {
-        llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
-        if (t1->ty == Tpointer && v->type == elem::NUL && l->getType() != r->getType()) {
-            r = llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(l->getType()));
-        }
-        Logger::cout() << "l = " << *l << " r = " << *r << '\n';
-        e->val = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
-    }
-    e->type = elem::VAL;
-
-    delete u;
-    delete v;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* CommaExp::toElem(IRState* p)
-{
-    Logger::print("CommaExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    elem* u = e1->toElem(p);
-    elem* v = e2->toElem(p);
-    delete u;
-    return v;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* CondExp::toElem(IRState* p)
-{
-    Logger::print("CondExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    Type* dtype = DtoDType(type);
-    const llvm::Type* resty = DtoType(dtype);
-
-    // allocate a temporary for the final result. failed to come up with a better way :/
-    llvm::BasicBlock* entryblock = &p->topfunc()->front();
-    llvm::Value* resval = new llvm::AllocaInst(resty,"condtmp",p->topallocapoint());
-
-    llvm::BasicBlock* oldend = p->scopeend();
-    llvm::BasicBlock* condtrue = new llvm::BasicBlock("condtrue", gIR->topfunc(), oldend);
-    llvm::BasicBlock* condfalse = new llvm::BasicBlock("condfalse", gIR->topfunc(), oldend);
-    llvm::BasicBlock* condend = new llvm::BasicBlock("condend", gIR->topfunc(), oldend);
-
-    elem* c = econd->toElem(p);
-    llvm::Value* cond_val = DtoBoolean(c->getValue());
-    delete c;
-    new llvm::BranchInst(condtrue,condfalse,cond_val,p->scopebb());
-
-    p->scope() = IRScope(condtrue, condfalse);
-    elem* u = e1->toElem(p);
-    DtoAssign(dtype, resval, u->getValue());
-    new llvm::BranchInst(condend,p->scopebb());
-    delete u;
-
-    p->scope() = IRScope(condfalse, condend);
-    elem* v = e2->toElem(p);
-    DtoAssign(dtype, resval, v->getValue());
-    new llvm::BranchInst(condend,p->scopebb());
-    delete v;
-
-    p->scope() = IRScope(condend, oldend);
-
-    elem* e = new elem;
-    e->mem = resval;
-    e->type = elem::VAR;
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* ComExp::toElem(IRState* p)
-{
-    Logger::print("ComExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    elem* e = new elem;
-    elem* u = e1->toElem(p);
-
-    llvm::Value* value = u->getValue();
-    llvm::Value* minusone = llvm::ConstantInt::get(value->getType(), -1, true);
-    e->val = llvm::BinaryOperator::create(llvm::Instruction::Xor, value, minusone, "tmp", p->scopebb());
-
-    delete u;
-
-    e->type = elem::VAL;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* NegExp::toElem(IRState* p)
-{
-    Logger::print("NegExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-    elem* e = new elem;
-    elem* l = e1->toElem(p);
-    llvm::Value* val = l->getValue();
-    delete l;
-
-    Type* t = DtoDType(type);
-
-    llvm::Value* zero = 0;
-    if (t->isintegral())
-        zero = llvm::ConstantInt::get(val->getType(), 0, true);
-    else if (t->isfloating()) {
-        if (t->ty == Tfloat32)
-            zero = llvm::ConstantFP::get(val->getType(), float(0));
-        else if (t->ty == Tfloat64 || t->ty == Tfloat80)
-            zero = llvm::ConstantFP::get(val->getType(), double(0));
-        else
-        assert(0);
-    }
-    else
-        assert(0);
-
-    e->val = llvm::BinaryOperator::createSub(zero,val,"tmp",p->scopebb());
-    e->type = elem::VAL;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* CatExp::toElem(IRState* p)
-{
-    Logger::print("CatExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    Type* t = DtoDType(type);
-
-    bool inplace = false;
-    llvm::Value* dst = 0;
-    IRExp* ex = p->topexp();
-    if (ex && ex->e2 == this) {
-        assert(ex->v);
-        dst = ex->v;
-        inplace = true;
-    }
-    else {
-        assert(t->ty == Tarray);
-        const llvm::Type* arrty = DtoType(t);
-        dst = new llvm::AllocaInst(arrty, "tmpmem", p->topallocapoint());
-    }
-
-    DtoCatArrays(dst,e1,e2);
-
-    elem* e = new elem;
-    e->mem = dst;
-    e->type = elem::VAR;
-    e->inplace = inplace;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-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 = DtoDType(e1->type);
-    Type* elemtype = DtoDType(e1type->next);
-    Type* e2type = DtoDType(e2->type);
-
-    if (e2type == elemtype) {
-        DtoCatAssignElement(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 = DtoType(type);
-    Logger::cout() << "array literal has llvm type: " << *t << '\n';
-
-    llvm::Value* mem = 0;
-    if (!p->topexp() || p->topexp()->e2 != this) {
-        assert(DtoDType(type)->ty == Tsarray);
-        mem = new llvm::AllocaInst(t,"tmparrayliteral",p->topallocapoint());
-    }
-    else if (p->topexp()->e2 == this) {
-        mem = p->topexp()->v;
-        assert(mem);
-        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();
-        }
-    }
-    else
-    assert(0);
-
-    for (unsigned i=0; i<elements->dim; ++i)
-    {
-        Expression* expr = (Expression*)elements->data[i];
-        llvm::Value* elemAddr = 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 = 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);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* FuncExp::toElem(IRState* p)
-{
-    Logger::print("FuncExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    assert(fd);
-
-    if (fd->isNested()) Logger::println("nested");
-    Logger::println("kind = %s\n", fd->kind());
-
-    fd->toObjFile();
-
-    llvm::Value* lval = NULL;
-    if (!p->topexp() || p->topexp()->e2 != this) {
-        const llvm::Type* dgty = DtoType(type);
-        Logger::cout() << "delegate without explicit storage:" << '\n' << *dgty << '\n';
-        lval = new llvm::AllocaInst(dgty,"dgstorage",p->topallocapoint());
-    }
-    else if (p->topexp()->e2 == this) {
-        lval = p->topexp()->v;
-        assert(lval);
-    }
-    else
-    assert(0);
-
-    elem* e = new elem;
-
-    llvm::Value* context = DtoGEPi(lval,0,0,"tmp",p->scopebb());
-    const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(context->getType()->getContainedType(0));
-    llvm::Value* llvmNested = p->func().decl->llvmNested;
-    if (llvmNested == NULL) {
-        llvm::Value* nullcontext = llvm::ConstantPointerNull::get(pty);
-        p->ir->CreateStore(nullcontext, context);
-    }
-    else {
-        llvm::Value* nestedcontext = p->ir->CreateBitCast(llvmNested, pty, "tmp");
-        p->ir->CreateStore(nestedcontext, context);
-    }
-
-    llvm::Value* fptr = DtoGEPi(lval,0,1,"tmp",p->scopebb());
-
-    assert(fd->llvmValue);
-    llvm::Value* castfptr = new llvm::BitCastInst(fd->llvmValue,fptr->getType()->getContainedType(0),"tmp",p->scopebb());
-    new llvm::StoreInst(castfptr, fptr, p->scopebb());
-
-    e->inplace = true;
-    e->mem = lval;
-    e->type = elem::VAR;
-
-    return e;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-#define STUB(x) elem *x::toElem(IRState * p) {error("Exp type "#x" not implemented: %s", toChars()); fatal(); return 0; }
-//STUB(IdentityExp);
-//STUB(CondExp);
-//STUB(EqualExp);
-STUB(InExp);
-//STUB(CmpExp);
-//STUB(AndAndExp);
-//STUB(OrOrExp);
-//STUB(AndExp);
-//STUB(AndAssignExp);
-//STUB(OrExp);
-//STUB(OrAssignExp);
-//STUB(XorExp);
-//STUB(XorAssignExp);
-//STUB(ShrExp);
-//STUB(ShrAssignExp);
-//STUB(ShlExp);
-//STUB(ShlAssignExp);
-//STUB(UshrExp);
-//STUB(UshrAssignExp);
-//STUB(DivExp);
-//STUB(DivAssignExp);
-//STUB(MulExp);
-//STUB(MulAssignExp);
-//STUB(ModExp);
-//STUB(ModAssignExp);
-//STUB(CatExp);
-//STUB(CatAssignExp);
-//STUB(AddExp);
-//STUB(AddAssignExp);
-STUB(Expression);
-//STUB(MinExp);
-//STUB(MinAssignExp);
-//STUB(PostExp);
-//STUB(NullExp);
-//STUB(ThisExp);
-//STUB(CallExp);
-STUB(DotTypeExp);
-STUB(TypeDotIdExp);
-//STUB(DotVarExp);
-//STUB(AssertExp);
-//STUB(FuncExp);
-//STUB(DelegateExp);
-//STUB(VarExp);
-//STUB(DeclarationExp);
-//STUB(NewExp);
-//STUB(SymOffExp);
-STUB(ScopeExp);
-//STUB(AssignExp);
-
-STUB(TypeExp);
-//STUB(RealExp);
-STUB(ComplexExp);
-//STUB(StringExp);
-//STUB(IntegerExp);
-STUB(BoolExp);
-
-//STUB(NotExp);
-//STUB(ComExp);
-//STUB(NegExp);
-//STUB(PtrExp);
-//STUB(AddrExp);
-//STUB(SliceExp);
-//STUB(CastExp);
-//STUB(DeleteExp);
-//STUB(IndexExp);
-//STUB(CommaExp);
-//STUB(ArrayLengthExp);
-//STUB(HaltExp);
-STUB(RemoveExp);
-//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()
-{
-    assert(0);
-    return 0;
-}
-
-type * Type::toCParamtype()
-{
-    assert(0);
-    return 0;
-}
-Symbol * Type::toSymbol()
-{
-    assert(0);
-    return 0;
-}
-
-type *
-TypeTypedef::toCtype()
-{
-    assert(0);
-    return 0;
-}
-
-type *
-TypeTypedef::toCParamtype()
-{
-    assert(0);
-    return 0;
-}
-
-void
-TypedefDeclaration::toDebug()
-{
-    assert(0);
-}
-
-
-type *
-TypeEnum::toCtype()
-{
-    assert(0);
-    return 0;
-}
-
-type *
-TypeStruct::toCtype()
-{
-    assert(0);
-    return 0;
-}
-
-void
-StructDeclaration::toDebug()
-{
-    assert(0);
-}
-
-Symbol * TypeClass::toSymbol()
-{
-    assert(0);
-    return 0;
-}
-
-unsigned TypeFunction::totym()
-{
-    assert(0);
-    return 0;
-}
-
-type * TypeFunction::toCtype()
-{
-    assert(0);
-    return 0;
-}
-
-type * TypeSArray::toCtype()
-{
-    assert(0);
-    return 0;
-}
-
-type *TypeSArray::toCParamtype()
-{
-    assert(0);
-    return 0;
-}
-
-type * TypeDArray::toCtype()
-{
-    assert(0);
-    return 0;
-}
-
-type * TypeAArray::toCtype()
-{
-    assert(0);
-    return 0;
-}
-
-type * TypePointer::toCtype()
-{
-    assert(0);
-    return 0;
-}
-
-type * TypeDelegate::toCtype()
-{
-    assert(0);
-    return 0;
-}
-
-type * TypeClass::toCtype()
-{
-    assert(0);
-    return 0;
-}
-
-void ClassDeclaration::toDebug()
-{
-    assert(0);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void
-EnumDeclaration::toDebug()
-{
-    assert(0);
-}
-
-int Dsymbol::cvMember(unsigned char*)
-{
-    assert(0);
-    return 0;
-}
-int EnumDeclaration::cvMember(unsigned char*)
-{
-    assert(0);
-    return 0;
-}
-int FuncDeclaration::cvMember(unsigned char*)
-{
-    assert(0);
-    return 0;
-}
-int VarDeclaration::cvMember(unsigned char*)
-{
-    assert(0);
-    return 0;
-}
-int TypedefDeclaration::cvMember(unsigned char*)
-{
-    assert(0);
-    return 0;
-}
-
-void obj_includelib(char*){}
-
-AsmStatement::AsmStatement(Loc loc, Token *tokens) :
-    Statement(loc)
-{
-    assert(0);
-}
-Statement *AsmStatement::syntaxCopy()
-{
-    assert(0);
-    return 0;
-}
-
-Statement *AsmStatement::semantic(Scope *sc)
-{
-    return Statement::semantic(sc);
-}
-
-
-void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    Statement::toCBuffer(buf, hgs);
-}
-
-int AsmStatement::comeFrom()
-{
-    assert(0);
-    return FALSE;
-}
-
-void
-backend_init()
-{
-    // now lazily loaded
-    //LLVM_D_InitRuntime();
-}
-
-void
-backend_term()
-{
-    LLVM_D_FreeRuntime();
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/toir.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,3089 @@
+// Backend stubs
+
+/* DMDFE backend stubs
+ * This file contains the implementations of the backend routines.
+ * For dmdfe these do nothing but print a message saying the module
+ * has been parsed. Substitute your own behaviors for these routimes.
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <sstream>
+#include <fstream>
+#include <iostream>
+
+#include "gen/llvm.h"
+
+#include "total.h"
+#include "init.h"
+#include "symbol.h"
+#include "mtype.h"
+#include "hdrgen.h"
+#include "port.h"
+
+#include "gen/irstate.h"
+#include "gen/elem.h"
+#include "gen/logger.h"
+#include "gen/tollvm.h"
+#include "gen/runtime.h"
+#include "gen/arrays.h"
+
+#include "gen/dvalue.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DeclarationExp::toElem(IRState* p)
+{
+    Logger::print("DeclarationExp::toElem: %s | T=%s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    // variable declaration
+    if (VarDeclaration* vd = declaration->isVarDeclaration())
+    {
+        Logger::println("VarDeclaration");
+
+        // static
+        if (vd->isDataseg())
+        {
+            vd->toObjFile();
+        }
+        else
+        {
+            Logger::println("vdtype = %s", vd->type->toChars());
+            // referenced by nested delegate?
+            if (vd->nestedref) {
+                Logger::println("has nestedref set");
+                vd->llvmValue = p->func().decl->llvmNested;
+                assert(vd->llvmValue);
+                assert(vd->llvmNestedIndex >= 0);
+            }
+            // normal stack variable
+            else {
+                // allocate storage on the stack
+                const llvm::Type* lltype = DtoType(vd->type);
+                llvm::AllocaInst* allocainst = new llvm::AllocaInst(lltype, vd->toChars(), p->topallocapoint());
+                //allocainst->setAlignment(vd->type->alignsize()); // TODO
+                vd->llvmValue = allocainst;
+            }
+            DValue* ie = DtoInitializer(vd->init);
+            delete ie;
+        }
+
+        return new DVarValue(vd, vd->llvmValue, true);
+    }
+    // struct declaration
+    else if (StructDeclaration* s = declaration->isStructDeclaration())
+    {
+        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 - no work");
+        // do nothing
+    }
+    else if (EnumDeclaration* e = declaration->isEnumDeclaration())
+    {
+        Logger::println("EnumDeclaration - no work");
+        // do nothing
+    }
+    // unsupported declaration
+    else
+    {
+        error("Only Var/Struct-Declaration is supported for DeclarationExp");
+        assert(0);
+    }
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* VarExp::toElem(IRState* p)
+{
+    Logger::print("VarExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    assert(var);
+    if (VarDeclaration* vd = var->isVarDeclaration())
+    {
+        Logger::println("VarDeclaration %s", vd->toChars());
+
+        // _arguments
+        if (vd->ident == Id::_arguments)
+        {
+            Logger::println("Id::_arguments");
+            if (!vd->llvmValue)
+                vd->llvmValue = p->func().decl->llvmArguments;
+            assert(vd->llvmValue);
+            return new DVarValue(vd, vd->llvmValue, true);
+        }
+        // _argptr
+        else if (vd->ident == Id::_argptr)
+        {
+            Logger::println("Id::_argptr");
+            if (!vd->llvmValue)
+                vd->llvmValue = p->func().decl->llvmArgPtr;
+            assert(vd->llvmValue);
+            return new DVarValue(vd, vd->llvmValue, true);
+        }
+        // _dollar
+        else if (vd->ident == Id::dollar)
+        {
+            Logger::println("Id::dollar");
+            assert(!p->arrays.empty());
+            llvm::Value* tmp = DtoArrayLen(p->arrays.back());
+            return new DVarValue(vd, tmp, false);
+        }
+        // typeinfo
+        else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
+        {
+            Logger::println("TypeInfoDeclaration");
+            tid->toObjFile();
+            assert(tid->llvmValue);
+            const llvm::Type* vartype = DtoType(type);
+            llvm::Value* m;
+            if (tid->llvmValue->getType() != llvm::PointerType::get(vartype))
+                m = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp");
+            else
+                m = tid->llvmValue;
+            return new DVarValue(vd, m, true);
+        }
+        // nested variable
+        else if (vd->nestedref) {
+            Logger::println("nested variable");
+            return new DVarValue(vd, DtoNestedVariable(vd), true);
+        }
+        // function parameter
+        else if (vd->isParameter()) {
+            Logger::println("function param");
+            if (!vd->llvmValue) {
+                // TODO: determine this properly
+                // this happens when the DMD frontend generates by pointer wrappers for struct opEquals(S) and opCmp(S)
+                vd->llvmValue = &p->func().func->getArgumentList().back();
+            }
+            if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa<llvm::AllocaInst>(vd->llvmValue)) {
+                return new DVarValue(vd, vd->llvmValue, true);
+            }
+            else if (llvm::isa<llvm::Argument>(vd->llvmValue)) {
+                return new DImValue(type, vd->llvmValue);
+            }
+            else assert(0);
+        }
+        else {
+            // take care of forward references of global variables
+            if (!vd->llvmTouched && vd->isDataseg())
+                vd->toObjFile();
+            assert(vd->llvmValue);
+            return new DVarValue(vd, vd->llvmValue, true);
+        }
+    }
+    else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
+    {
+        Logger::println("FuncDeclaration");
+        if (fdecl->llvmInternal != LLVMva_arg)// && fdecl->llvmValue == 0)
+            fdecl->toObjFile();
+        return new DFuncValue(fdecl, fdecl->llvmValue);
+    }
+    else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
+    {
+        // this seems to be the static initialiser for structs
+        Type* sdecltype = DtoDType(sdecl->type);
+        Logger::print("Sym: type=%s\n", sdecltype->toChars());
+        assert(sdecltype->ty == Tstruct);
+        TypeStruct* ts = (TypeStruct*)sdecltype;
+        assert(ts->llvmInit);
+        return new DVarValue(type, ts->llvmInit, true);
+    }
+    else
+    {
+        assert(0 && "Unimplemented VarExp type");
+    }
+
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+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 = 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;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* IntegerExp::toElem(IRState* p)
+{
+    Logger::print("IntegerExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+    llvm::Constant* c = toConstElem(p);
+    return new DConstValue(type, c);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* IntegerExp::toConstElem(IRState* p)
+{
+    Logger::print("IntegerExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+    const llvm::Type* t = DtoType(type);
+    if (llvm::isa<llvm::PointerType>(t)) {
+        llvm::Constant* i = llvm::ConstantInt::get(DtoSize_t(),(uint64_t)value,false);
+        return llvm::ConstantExpr::getIntToPtr(i, t);
+    }
+    else if (llvm::isa<llvm::IntegerType>(t)) {
+        return llvm::ConstantInt::get(t,(uint64_t)value,!type->isunsigned());
+    }
+    assert(0);
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* RealExp::toElem(IRState* p)
+{
+    Logger::print("RealExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+    llvm::Constant* c = toConstElem(p);
+    return new DConstValue(type, c);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* RealExp::toConstElem(IRState* p)
+{
+    Logger::print("RealExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+    Type* t = DtoDType(type);
+    const llvm::Type* fty = DtoType(t);
+    if (t->ty == Tfloat32 || t->ty == Timaginary32)
+        return llvm::ConstantFP::get(fty,float(value));
+    else if (t->ty == Tfloat64 || t->ty == Timaginary64 || t->ty == Tfloat80 || t->ty == Timaginary80)
+        return llvm::ConstantFP::get(fty,double(value));
+    assert(0);
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* NullExp::toElem(IRState* p)
+{
+    Logger::print("NullExp::toElem(type=%s): %s\n", type->toChars(),toChars());
+    LOG_SCOPE;
+    llvm::Constant* c = toConstElem(p);
+    return new DNullValue(type, c);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* NullExp::toConstElem(IRState* p)
+{
+    Logger::print("NullExp::toConstElem(type=%s): %s\n", type->toChars(),toChars());
+    LOG_SCOPE;
+    const llvm::Type* t = DtoType(type);
+    if (type->ty == Tarray) {
+        assert(llvm::isa<llvm::StructType>(t));
+        return llvm::ConstantAggregateZero::get(t);
+    }
+    else {
+        return llvm::Constant::getNullValue(t);
+    }
+    assert(0);
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* StringExp::toElem(IRState* p)
+{
+    Logger::print("StringExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    Type* dtype = DtoDType(type);
+    Type* cty = DtoDType(dtype->next);
+
+    const llvm::Type* ct = DtoType(dtype->next);
+    //printf("ct = %s\n", type->next->toChars());
+    const llvm::ArrayType* at = llvm::ArrayType::get(ct,len+1);
+
+    llvm::Constant* _init;
+    if (cty->ty == Tchar) {
+        uint8_t* str = (uint8_t*)string;
+        std::string cont((char*)str, len);
+        _init = llvm::ConstantArray::get(cont,true);
+    }
+    else if (cty->ty == Twchar) {
+        uint16_t* str = (uint16_t*)string;
+        std::vector<llvm::Constant*> vals;
+        for(size_t i=0; i<len; ++i) {
+            vals.push_back(llvm::ConstantInt::get(ct, str[i], false));;
+        }
+        vals.push_back(llvm::ConstantInt::get(ct, 0, false));
+        _init = llvm::ConstantArray::get(at,vals);
+    }
+    else if (cty->ty == Tdchar) {
+        uint32_t* str = (uint32_t*)string;
+        std::vector<llvm::Constant*> vals;
+        for(size_t i=0; i<len; ++i) {
+            vals.push_back(llvm::ConstantInt::get(ct, str[i], false));;
+        }
+        vals.push_back(llvm::ConstantInt::get(ct, 0, false));
+        _init = llvm::ConstantArray::get(at,vals);
+    }
+    else
+    assert(0);
+
+    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
+    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::Constant* idxs[2] = { zero, zero };
+    llvm::Constant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
+
+    if (dtype->ty == Tarray) {
+        llvm::Constant* clen = llvm::ConstantInt::get(DtoSize_t(),len,false);
+        if (!p->topexp() || p->topexp()->e2 != this) {
+            llvm::Value* tmpmem = new llvm::AllocaInst(DtoType(dtype),"tempstring",p->topallocapoint());
+            DtoSetArray(tmpmem, clen, arrptr);
+            return new DVarValue(type, tmpmem, true);
+        }
+        else if (p->topexp()->e2 == this) {
+            DValue* arr = p->topexp()->v;
+            assert(arr);
+            DtoSetArray(arr->getLVal(), clen, arrptr);
+            return new DImValue(type, arr->getLVal(), true);
+        }
+        assert(0);
+    }
+    else if (dtype->ty == Tsarray) {
+        const llvm::Type* dstType = llvm::PointerType::get(llvm::ArrayType::get(ct, len));
+        llvm::Value* emem = (gvar->getType() == dstType) ? gvar : DtoBitCast(gvar, dstType);
+        return new DVarValue(type, emem, true);
+    }
+    else if (dtype->ty == Tpointer) {
+        return new DImValue(type, arrptr);
+    }
+
+    assert(0);
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+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 = DtoDType(type);
+
+    if (t->ty == Tsarray) {
+        return llvm::ConstantArray::get(cont,false);
+    }
+    llvm::Constant* _init = llvm::ConstantArray::get(cont,true);
+
+    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(DtoSize_t(),len,false);
+        return DtoConstSlice(clen, arrptr);
+    }
+
+    assert(0);
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* AssignExp::toElem(IRState* p)
+{
+    Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type ? e2->type->toChars() : 0);
+    LOG_SCOPE;
+
+    p->exps.push_back(IRExp(e1,e2,NULL));
+
+    DValue* l = e1->toElem(p);
+    p->topexp()->v = l;
+    DValue* r = e2->toElem(p);
+
+    p->exps.pop_back();
+
+    if (l->isArrayLen())
+        DtoResizeDynArray(l->getLVal(), r->getRVal());
+    else
+        DtoAssign(l, r);
+    return l;
+
+    /*
+    if (l->type == DValue::ARRAYLEN)
+    {
+        DtoResizeDynArray(l->mem, r->getValue());
+        delete r;
+        delete l;
+        return 0;
+    }
+
+    Type* e1type = DtoDType(e1->type);
+    Type* e2type = DtoDType(e2->type);
+    TY e1ty = e1type->ty;
+    TY e2ty = e2type->ty;
+
+    DValue* e = new DValue(this);
+    e->type = DValue::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) {
+                DtoStructCopy(l->mem,r->getValue());
+            }
+            else {
+                e->inplace = true;
+            }
+        }
+        // struct + const int
+        else if (e2type->isintegral()){
+            IntegerExp* iexp = (IntegerExp*)e2;
+            assert(iexp->value == 0 && "Only integral struct initializer allowed is zero");
+            DtoStructZeroInit(l->mem);
+        }
+        // :x
+        else
+        assert(0 && "struct = unknown");
+    }
+    else if (e1ty == Tsarray) {
+        assert(0 && "static array not supported");
+    }
+    else if (e1ty == Tarray) {
+        if (e2type->isscalar() || e2type->ty == Tclass){
+            if (l->type == DValue::SLICE) {
+                DtoArrayInit(l->mem, l->arg, r->getValue());
+            }
+            else {
+                DtoArrayInit(l->mem, r->getValue());
+            }
+        }
+        else if (e2ty == Tarray) {
+            //new llvm::StoreInst(r->val,l->val,p->scopebb());
+            if (r->type == DValue::NUL) {
+                llvm::Constant* c = llvm::cast<llvm::Constant>(r->val);
+                assert(c->isNullValue());
+                DtoNullArray(l->mem);
+                e->mem = l->mem;
+            }
+            else if (r->type == DValue::SLICE) {
+                if (l->type == DValue::SLICE) {
+                    DtoArrayCopy(l,r);
+                    e->type = DValue::SLICE;
+                    e->mem = l->mem;
+                    e->arg = l->arg;
+                }
+                else {
+                    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);
+                    DtoArrayAssign(l->mem, r->mem);
+                }
+                else {
+                    e->inplace = true;
+                }
+            }
+        }
+        else
+        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';
+            new llvm::StoreInst(v, l->mem, p->scopebb());
+        }
+        else
+        assert(0);
+    }
+    else if (e1ty == Tclass) {
+        if (e2ty == Tclass) {
+            llvm::Value* tmp = r->getValue();
+            Logger::cout() << "tmp: " << *tmp << " ||| " << *l->mem << '\n';
+            // assignment to this in constructor special case
+            if (l->isthis) {
+                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
+        assert(0);
+    }
+    else if (e1ty == Tdelegate) {
+        Logger::println("Assigning to delegate");
+        if (e2ty == Tdelegate) {
+            if (r->type == DValue::NUL) {
+                llvm::Constant* c = llvm::cast<llvm::Constant>(r->val);
+                if (c->isNullValue()) {
+                    DtoNullDelegate(l->mem);
+                    e->mem = l->mem;
+                }
+                else
+                assert(0);
+            }
+            else if (r->inplace) {
+                // do nothing
+                e->inplace = true;
+                e->mem = l->mem;
+            }
+            else {
+                DtoDelegateCopy(l->mem, r->getValue());
+                e->mem = l->mem;
+            }
+        }
+        else
+        assert(0);
+    }
+    // !struct && !array && !pointer && !class
+    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;
+    */
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* AddExp::toElem(IRState* p)
+{
+    Logger::print("AddExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+    DValue* r = e2->toElem(p);
+
+    Type* t = DtoDType(type);
+    Type* e1type = DtoDType(e1->type);
+    Type* e2type = DtoDType(e2->type);
+
+    if (e1type != e2type) {
+        if (e1type->ty == Tpointer && e1type->next->ty == Tstruct) {
+            assert(r->isConst());
+            llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->isConst()->c);
+
+            TypeStruct* ts = (TypeStruct*)e1type->next;
+            std::vector<unsigned> offsets;
+            llvm::Value* v = DtoIndexStruct(l->getRVal(), ts->sym, t->next, cofs->getZExtValue(), offsets);
+            return new DFieldValue(type, v, true);
+        }
+        else if (e1->type->ty == Tpointer) {
+            llvm::Value* v = new llvm::GetElementPtrInst(l->getRVal(), r->getRVal(), "tmp", p->scopebb());
+            return new DImValue(type, v);
+        }
+        assert(0);
+    }
+    else {
+        return DtoBinAdd(l,r);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* AddAssignExp::toElem(IRState* p)
+{
+    Logger::print("AddAssignExp::toElem: %s\n", toChars());
+    LOG_SCOPE;
+
+    p->exps.push_back(IRExp(e1,e2,NULL));
+    DValue* l = e1->toElem(p);
+    DValue* r = e2->toElem(p);
+    p->exps.pop_back();
+
+    DValue* res;
+    if (DtoDType(e1->type)->ty == Tpointer) {
+        llvm::Value* gep = new llvm::GetElementPtrInst(l->getRVal(),r->getRVal(),"tmp",p->scopebb());
+        res = new DImValue(type, gep);
+    }
+    else {
+        res = DtoBinAdd(l,r);
+    }
+    DtoAssign(l, res);
+
+    return l;
+
+    /*
+
+    Type* e1type = DtoDType(e1->type);
+
+    DValue* e = new DValue(this);
+    llvm::Value* val = 0;
+    if (e1type->ty == Tpointer) {
+        val = e->mem = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    }
+    else {
+        val = e->val = llvm::BinaryOperator::createAdd(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    }
+
+    assert(l->mem);
+    new llvm::StoreInst(val,l->mem,p->scopebb());
+    e->type = DValue::VAR;
+
+    delete l;
+    delete r;
+    return e;
+    */
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* MinExp::toElem(IRState* p)
+{
+    Logger::print("MinExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+    DValue* r = e2->toElem(p);
+
+    if (DtoDType(e1->type)->ty == Tpointer) {
+        llvm::Value* left = p->ir->CreatePtrToInt(l->getRVal(), DtoSize_t(), "tmp");
+        llvm::Value* right = p->ir->CreatePtrToInt(r->getRVal(), DtoSize_t(), "tmp");
+        llvm::Value* diff = p->ir->CreateSub(left,right,"tmp");
+        if (diff->getType() != DtoType(type))
+            diff = p->ir->CreateIntToPtr(diff, DtoType(type));
+        return new DImValue(type, diff);
+    }
+    else {
+        return DtoBinSub(l,r);
+    }
+
+    /*
+    llvm::Value* left = l->getValue();
+    if (llvm::isa<llvm::PointerType>(left->getType()))
+        left = new llvm::PtrToIntInst(left,DtoSize_t(),"tmp",p->scopebb());
+
+    llvm::Value* right = r->getValue();
+    if (llvm::isa<llvm::PointerType>(right->getType()))
+        right = new llvm::PtrToIntInst(right,DtoSize_t(),"tmp",p->scopebb());
+
+    e->val = llvm::BinaryOperator::createSub(left,right,"tmp",p->scopebb());
+    e->type = DValue::VAL;
+
+    const llvm::Type* totype = DtoType(type);
+    if (e->val->getType() != totype) {
+        assert(0);
+        assert(llvm::isa<llvm::PointerType>(e->val->getType()));
+        assert(llvm::isa<llvm::IntegerType>(totype));
+        e->val = new llvm::IntToPtrInst(e->val,totype,"tmp",p->scopebb());
+    }
+
+    delete l;
+    delete r;
+    return e;
+    */
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* MinAssignExp::toElem(IRState* p)
+{
+    Logger::print("MinAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+    DValue* r = e2->toElem(p);
+
+    DValue* res;
+    if (DtoDType(e1->type)->ty == Tpointer) {
+        llvm::Value* tmp = r->getRVal();
+        llvm::Value* zero = llvm::ConstantInt::get(tmp->getType(),0,false);
+        tmp = llvm::BinaryOperator::createSub(zero,tmp,"tmp",p->scopebb());
+        tmp = new llvm::GetElementPtrInst(l->getRVal(),tmp,"tmp",p->scopebb());
+        res = new DImValue(type, tmp);
+    }
+    else {
+        res = DtoBinSub(l,r);
+    }
+    DtoAssign(l, res);
+
+    return l;
+
+    /*
+
+    Type* e1type = DtoDType(e1->type);
+
+    llvm::Value* tmp = 0;
+    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());
+        tmp = new llvm::GetElementPtrInst(l->getValue(),tmp,"tmp",p->scopebb());
+    }
+    else {
+        tmp = llvm::BinaryOperator::createSub(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    }
+
+    assert(l->mem);
+    new llvm::StoreInst(tmp, l->mem, p->scopebb());
+
+    delete l;
+    delete r;
+
+    DValue* e = new DValue(this);
+    e->val = tmp;
+    e->type = DValue::VAR;
+    return e;
+    */
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* MulExp::toElem(IRState* p)
+{
+    Logger::print("MulExp::toElem: %s\n", toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+    DValue* r = e2->toElem(p);
+
+    return DtoBinMul(l,r);
+    /*
+    if (l->dvalue && r->dvalue) {
+        Logger::println("DVALUE PATH");
+        e->dvalue = DtoBinMul(l->dvalue, r->dvalue);
+        e->val = e->dvalue->getRVal();
+    }
+    else {
+        llvm::Value* vl = l->getValue();
+        llvm::Value* vr = r->getValue();
+        Logger::cout() << "mul: " << *vl << ", " << *vr << '\n';
+        e->val = llvm::BinaryOperator::createMul(vl,vr,"tmp",p->scopebb());
+        e->dvalue = new DImValue(type, e->val);
+    }
+    e->type = DValue::VAL;
+    delete l;
+    delete r;
+    return e;
+    */
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* MulAssignExp::toElem(IRState* p)
+{
+    Logger::print("MulAssignExp::toElem: %s\n", toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+    DValue* r = e2->toElem(p);
+
+    DValue* res = DtoBinMul(l,r);
+    DtoAssign(l, res);
+
+    return l;
+
+    /*
+    llvm::Value* vl = l->getValue();
+    llvm::Value* vr = r->getValue();
+    Logger::cout() << "mulassign: " << *vl << ", " << *vr << '\n';
+    llvm::Value* tmp = llvm::BinaryOperator::createMul(vl,vr,"tmp",p->scopebb());
+
+    assert(l->mem);
+    new llvm::StoreInst(tmp,l->mem,p->scopebb());
+
+    delete l;
+    delete r;
+
+    DValue* e = new DValue(this);
+    e->val = tmp;
+    e->type = DValue::VAR;
+    return e;
+    */
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DivExp::toElem(IRState* p)
+{
+    Logger::print("DivExp::toElem: %s\n", toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+    DValue* r = e2->toElem(p);
+
+    return DtoBinDiv(l, r);
+    /*
+
+    Type* t = DtoDType(type);
+
+    if (t->isunsigned())
+        e->val = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    else if (t->isintegral())
+        e->val = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    else if (t->isfloating())
+        e->val = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    else
+        assert(0);
+    e->type = DValue::VAL;
+    delete l;
+    delete r;
+    return e;
+    */
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DivAssignExp::toElem(IRState* p)
+{
+    Logger::print("DivAssignExp::toElem: %s\n", toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+    DValue* r = e2->toElem(p);
+
+    DValue* res = DtoBinDiv(l,r);
+    DtoAssign(l, res);
+
+    return l;
+
+    /*
+
+    Type* t = DtoDType(type);
+
+    llvm::Value* tmp;
+    if (t->isunsigned())
+        tmp = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    else if (t->isintegral())
+        tmp = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    else if (t->isfloating())
+        tmp = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    else
+        assert(0);
+
+    assert(l->mem);
+    new llvm::StoreInst(tmp,l->mem,p->scopebb());
+
+    delete l;
+    delete r;
+
+    DValue* e = new DValue(this);
+    e->val = tmp;
+    e->type = DValue::VAR;
+    return e;
+    */
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* ModExp::toElem(IRState* p)
+{
+    Logger::print("ModExp::toElem: %s\n", toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+    DValue* r = e2->toElem(p);
+
+    return DtoBinRem(l, r);
+    /*
+    Type* t = DtoDType(type);
+
+    if (t->isunsigned())
+        e->val = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    else if (t->isintegral())
+        e->val = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    else if (t->isfloating())
+        e->val = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    else
+        assert(0);
+    e->type = DValue::VAL;
+    delete l;
+    delete r;
+    return e;
+    */
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* ModAssignExp::toElem(IRState* p)
+{
+    Logger::print("ModAssignExp::toElem: %s\n", toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+    DValue* r = e2->toElem(p);
+
+    DValue* res = DtoBinRem(l, r);
+    DtoAssign(l, res);
+
+    return l;
+
+    /*
+
+    Type* t = DtoDType(type);
+
+    llvm::Value* tmp;
+    if (t->isunsigned())
+        tmp = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    else if (t->isintegral())
+        tmp = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    else if (t->isfloating())
+        tmp = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
+    else
+        assert(0);
+
+    assert(l->mem);
+    new llvm::StoreInst(tmp,l->mem,p->scopebb());
+
+    delete l;
+    delete r;
+
+    DValue* e = new DValue(this);
+    e->val = tmp;
+    e->type = DValue::VAR;
+    return e;
+    */
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* CallExp::toElem(IRState* p)
+{
+    Logger::print("CallExp::toElem: %s\n", toChars());
+    LOG_SCOPE;
+
+    DValue* fn = e1->toElem(p);
+
+    TypeFunction* tf = 0;
+    Type* e1type = DtoDType(e1->type);
+
+    bool delegateCall = false;
+    llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false);
+    llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty,1,false);
+    LINK dlink = LINKdefault;
+
+    // hidden struct return parameter handling
+    bool retinptr = false;
+
+    // regular functions
+    if (e1type->ty == Tfunction) {
+        tf = (TypeFunction*)e1type;
+        if (tf->llvmRetInPtr) {
+            retinptr = true;
+        }
+        dlink = tf->linkage;
+    }
+
+    // delegates
+    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;
+        }
+        dlink = tf->linkage;
+        delegateCall = true;
+    }
+
+    // invalid
+    else {
+        assert(tf);
+    }
+
+    // va args
+    bool va_magic = false;
+    bool va_intrinsic = false;
+    DFuncValue* dfv = fn->isFunc();
+    if (dfv && dfv->func) {
+        FuncDeclaration* fndecl = dfv->func;
+        if (fndecl->llvmInternal == LLVMva_intrinsic) {
+            va_magic = true;
+            va_intrinsic = true;
+        }
+        else if (fndecl->llvmInternal == LLVMva_start) {
+            va_magic = true;
+        }
+        else if (fndecl->llvmInternal == LLVMva_arg) {
+            //Argument* fnarg = Argument::getNth(tf->parameters, 0);
+            Expression* exp = (Expression*)arguments->data[0];
+            DValue* expelem = exp->toElem(p);
+            Type* t = DtoDType(type);
+            const llvm::Type* llt = DtoType(type);
+            if (DtoIsPassedByRef(t))
+                llt = llvm::PointerType::get(llt);
+            return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp"));
+        }
+    }
+
+    // args
+    size_t n = arguments->dim;
+    DFuncValue* dfn = fn->isFunc();
+    if (dfn && dfn->func && dfn->func->llvmInternal == LLVMva_start)
+        n = 1;
+    if (delegateCall || (dfn && dfn->vthis)) n++;
+    if (retinptr) n++;
+    if (tf->linkage == LINKd && tf->varargs == 1) n+=2;
+    if (dfn && dfn->func && dfn->func->isNested()) n++;
+
+    llvm::Value* funcval = fn->getRVal();
+    assert(funcval != 0);
+    std::vector<llvm::Value*> llargs(n, 0);
+
+    const llvm::FunctionType* llfnty = 0;
+
+    // normal function call
+    if (llvm::isa<llvm::FunctionType>(funcval->getType())) {
+        llfnty = llvm::cast<llvm::FunctionType>(funcval->getType());
+    }
+    // pointer to something
+    else if (llvm::isa<llvm::PointerType>(funcval->getType())) {
+        // pointer to function pointer - I think this not really supposed to happen, but does :/
+        // seems like sometimes we get a func* other times a func**
+        if (llvm::isa<llvm::PointerType>(funcval->getType()->getContainedType(0))) {
+            funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
+        }
+        // function pointer
+        if (llvm::isa<llvm::FunctionType>(funcval->getType()->getContainedType(0))) {
+            //Logger::cout() << "function pointer type:\n" << *funcval << '\n';
+            llfnty = llvm::cast<llvm::FunctionType>(funcval->getType()->getContainedType(0));
+        }
+        // struct pointer - delegate
+        else if (llvm::isa<llvm::StructType>(funcval->getType()->getContainedType(0))) {
+            funcval = DtoGEP(funcval,zero,one,"tmp",p->scopebb());
+            funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
+            const llvm::Type* ty = funcval->getType()->getContainedType(0);
+            llfnty = llvm::cast<llvm::FunctionType>(ty);
+        }
+        // unknown
+        else {
+            Logger::cout() << "what kind of pointer are we calling? : " << *funcval->getType() << '\n';
+        }
+    }
+    else {
+        Logger::cout() << "what are we calling? : " << *funcval << '\n';
+    }
+    assert(llfnty);
+    //Logger::cout() << "Function LLVM type: " << *llfnty << '\n';
+
+    // argument handling
+    llvm::FunctionType::param_iterator argiter = llfnty->param_begin();
+    int j = 0;
+
+    IRExp* topexp = p->topexp();
+
+    bool isInPlace = false;
+
+    // hidden struct return arguments
+    if (retinptr) {
+        if (topexp && topexp->e2 == this) {
+            assert(topexp->v);
+            llvm::Value* tlv = topexp->v->getLVal();
+            assert(llvm::isa<llvm::StructType>(tlv->getType()->getContainedType(0)));
+            llargs[j] = tlv;
+            if (DtoIsPassedByRef(tf->next)) {
+                isInPlace = true;
+            }
+            else
+            assert(0);
+        }
+        else {
+            llargs[j] = new llvm::AllocaInst(argiter->get()->getContainedType(0),"rettmp",p->topallocapoint());
+        }
+        ++j;
+        ++argiter;
+    }
+
+    // this arguments
+    if (dfn && dfn->vthis) {
+        Logger::println("This Call");
+        if (dfn->vthis->getType() != argiter->get()) {
+            //Logger::cout() << *fn->thisparam << '|' << *argiter->get() << '\n';
+            llargs[j] = new llvm::BitCastInst(dfn->vthis, argiter->get(), "tmp", p->scopebb());
+        }
+        else {
+            llargs[j] = dfn->vthis;
+        }
+        ++j;
+        ++argiter;
+    }
+    // delegate context arguments
+    else if (delegateCall) {
+        Logger::println("Delegate Call");
+        llvm::Value* contextptr = DtoGEP(fn->getRVal(),zero,zero,"tmp",p->scopebb());
+        llargs[j] = new llvm::LoadInst(contextptr,"tmp",p->scopebb());
+        ++j;
+        ++argiter;
+    }
+    // nested call
+    else if (dfn && dfn->func && dfn->func->isNested()) {
+        Logger::println("Nested Call");
+        llvm::Value* contextptr = p->func().decl->llvmNested;
+        assert(contextptr);
+        llargs[j] = p->ir->CreateBitCast(contextptr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
+        ++j;
+        ++argiter;
+    }
+
+    // va arg function special argument passing
+    if (va_magic) {
+        size_t n = va_intrinsic ? arguments->dim : 1;
+        for (int i=0; i<n; i++,j++)
+        {
+            Argument* fnarg = Argument::getNth(tf->parameters, i);
+            Expression* exp = (Expression*)arguments->data[i];
+            DValue* expelem = exp->toElem(p);
+            llargs[j] = p->ir->CreateBitCast(expelem->getLVal(), llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
+        }
+    }
+    // regular arguments
+    else {
+        if (tf->linkage == LINKd && tf->varargs == 1)
+        {
+            Logger::println("doing d-style variadic arguments");
+
+            std::vector<const llvm::Type*> vtypes;
+            std::vector<llvm::Value*> vvalues;
+