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;
+            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]);
+                // this hack is necessary :/
+                if (dfn && dfn->func && dfn->func->llvmRunTimeHack) {
+                    if (llargs[j]->getType() != llfnty->getParamType(j))
+                        llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
+                }
+            }
+            Logger::println("%d params passed", n);
+            for (int i=0; i<n; ++i) {
+                assert(llargs[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());
+    llvm::Value* retllval = (retinptr) ? llargs[0] : call;
+
+    // set calling convention
+    if (dfn && dfn->func) {
+        int li = dfn->func->llvmInternal;
+        if (li != LLVMintrinsic && li != LLVMva_start && li != LLVMva_intrinsic) {
+            call->setCallingConv(DtoCallingConv(dlink));
+        }
+    }
+    else if (delegateCall) {
+        call->setCallingConv(DtoCallingConv(dlink));
+    }
+    else if (dfn && dfn->cc != (unsigned)-1) {
+        call->setCallingConv(dfn->cc);
+    }
+
+    return new DImValue(type, retllval, isInPlace);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* CastExp::toElem(IRState* p)
+{
+    Logger::print("CastExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* 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
+    llvm::Value* rval = 0;
+    llvm::Value* rval2 = 0;
+    bool isslice = false;
+
+    if (fromtype->isintegral()) {
+        if (totype->isintegral()) {
+            if (lsz < rsz) {
+                Logger::cout() << "cast to: " << *tolltype << '\n';
+                if (fromtype->isunsigned() || fromtype->ty == Tbool) {
+                    rval = new llvm::ZExtInst(u->getRVal(), tolltype, "tmp", p->scopebb());
+                } else {
+                    rval = new llvm::SExtInst(u->getRVal(), tolltype, "tmp", p->scopebb());
+                }
+            }
+            else if (lsz > rsz) {
+                rval = new llvm::TruncInst(u->getRVal(), tolltype, "tmp", p->scopebb());
+            }
+            else {
+                rval = new llvm::BitCastInst(u->getRVal(), tolltype, "tmp", p->scopebb());
+            }
+        }
+        else if (totype->isfloating()) {
+            if (fromtype->isunsigned()) {
+                rval = new llvm::UIToFPInst(u->getRVal(), tolltype, "tmp", p->scopebb());
+            }
+            else {
+                rval = new llvm::SIToFPInst(u->getRVal(), tolltype, "tmp", p->scopebb());
+            }
+        }
+        else if (totype->ty == Tpointer) {
+            rval = p->ir->CreateIntToPtr(u->getRVal(), tolltype, "tmp");
+        }
+        else {
+            assert(0);
+        }
+    }
+    else if (fromtype->isfloating()) {
+        if (totype->isfloating()) {
+            if ((fromtype->ty == Tfloat80 || fromtype->ty == Tfloat64) && (totype->ty == Tfloat80 || totype->ty == Tfloat64)) {
+                rval = u->getRVal();
+            }
+            else if (lsz < rsz) {
+                rval = new llvm::FPExtInst(u->getRVal(), tolltype, "tmp", p->scopebb());
+            }
+            else if (lsz > rsz) {
+                rval = new llvm::FPTruncInst(u->getRVal(), tolltype, "tmp", p->scopebb());
+            }
+            else {
+                assert(0);
+            }
+        }
+        else if (totype->isintegral()) {
+            if (totype->isunsigned()) {
+                rval = new llvm::FPToUIInst(u->getRVal(), tolltype, "tmp", p->scopebb());
+            }
+            else {
+                rval = new llvm::FPToSIInst(u->getRVal(), tolltype, "tmp", p->scopebb());
+            }
+        }
+        else {
+            assert(0);
+        }
+    }
+    else if (fromtype->ty == Tclass) {
+        //assert(to->ty == Tclass);
+        rval = new llvm::BitCastInst(u->getRVal(), tolltype, "tmp", p->scopebb());
+    }
+    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->getRVal(),zero,one,"tmp",p->scopebb());
+            rval = new llvm::LoadInst(ptr, "tmp", p->scopebb());
+            if (fromtype->next != totype->next)
+                rval = p->ir->CreateBitCast(rval, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
+        }
+        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 (DSliceValue* usl = u->isSlice()) {
+                rval = new llvm::BitCastInst(usl->ptr, ptrty, "tmp", p->scopebb());
+                if (fromtype->next->size() == totype->next->size())
+                    rval2 = usl->len;
+                else
+                    rval2 = DtoArrayCastLength(usl->len, ety, ptrty->getContainedType(0));
+            }
+            else {
+                llvm::Value* uval = u->getRVal();
+                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));
+                    rval2 = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
+                    rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
+                    rval = 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);
+                    rval2 = DtoGEP(uval,zero,zero,"tmp",p->scopebb());
+                    rval2 = new llvm::LoadInst(rval2, "tmp", p->scopebb());
+                    rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
+
+                    rval = DtoGEP(uval,zero,one,"tmp",p->scopebb());
+                    rval = new llvm::LoadInst(rval, "tmp", p->scopebb());
+                    //Logger::cout() << *e->mem->getType() << '|' << *ptrty << '\n';
+                    rval = new llvm::BitCastInst(rval, ptrty, "tmp", p->scopebb());
+                }
+            }
+            isslice = true;
+        }
+        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->getRVal();
+            Logger::cout() << "src: " << *src << "to type: " << *tolltype << '\n';
+            rval = new llvm::BitCastInst(src, tolltype, "tmp", p->scopebb());
+        }
+        else if (totype->isintegral()) {
+            rval = new llvm::PtrToIntInst(u->getRVal(), tolltype, "tmp", p->scopebb());
+        }
+        else
+        assert(0);
+    }
+    else {
+        assert(0);
+    }
+
+    if (isslice) {
+        return new DSliceValue(type, rval2, rval);
+    }
+    else if (u->isLValueCast() || u->isVar()) {
+        return new DLValueCast(type, u->getLVal(), rval);
+    }
+    else if (p->topexp() && p->topexp()->e1 == this) {
+        llvm::Value* lval = u->getLVal();
+        Logger::cout() << "lval: " << *lval << "rval: " << *rval << '\n';
+        return new DLValueCast(type, lval, rval);
+    }
+    else {
+        Logger::cout() << "im rval: " << *rval << '\n';
+        return new DImValue(type, rval);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* SymOffExp::toElem(IRState* p)
+{
+    Logger::print("SymOffExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    if (VarDeclaration* vd = var->isVarDeclaration())
+    {
+        Logger::println("VarDeclaration");
+        if (!vd->llvmTouched && vd->isDataseg())
+            vd->toObjFile();
+
+        // TODO
+        /*
+        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;
+        llvm::Value* varmem = 0;
+
+        if (vdtype->ty == Tstruct && !(t->ty == Tpointer && t->next == vdtype)) {
+            Logger::println("struct");
+            TypeStruct* vdt = (TypeStruct*)vdtype;
+            assert(vdt->sym);
+
+            const llvm::Type* llt = DtoType(t);
+            if (offset == 0) {
+                varmem = p->ir->CreateBitCast(llvalue, llt, "tmp");
+            }
+            else {
+                std::vector<unsigned> dst;
+                varmem = DtoIndexStruct(llvalue,vdt->sym, tnext, offset, dst);
+            }
+        }
+        else if (vdtype->ty == Tsarray) {
+            Logger::println("sarray");
+
+            assert(llvalue);
+            //e->arg = llvalue; // TODO
+
+            const llvm::Type* llt = DtoType(t);
+            llvm::Value* off = 0;
+            if (offset != 0) {
+                Logger::println("offset = %d\n", offset);
+            }
+            if (llvalue->getType() != llt) {
+                varmem = p->ir->CreateBitCast(llvalue, llt, "tmp");
+                if (offset != 0)
+                    varmem = DtoGEPi(varmem, offset, "tmp");
+            }
+            else {
+                assert(offset == 0);
+                varmem = DtoGEPi(llvalue,0,0,"tmp");
+            }
+        }
+        else if (offset == 0) {
+            Logger::println("normal symoff");
+
+            assert(llvalue);
+            varmem = llvalue;
+
+            const llvm::Type* llt = DtoType(t);
+            if (llvalue->getType() != llt) {
+                varmem = p->ir->CreateBitCast(varmem, llt, "tmp");
+            }
+        }
+        else {
+            assert(0);
+        }
+        return new DFieldValue(type, varmem, true);
+    }
+    else if (FuncDeclaration* fd = var->isFuncDeclaration())
+    {
+        Logger::println("FuncDeclaration");
+
+        if (fd->llvmValue == 0)
+            fd->toObjFile();
+        return new DFuncValue(fd, fd->llvmValue);
+    }
+
+    assert(0);
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* PtrExp::toElem(IRState* p)
+{
+    Logger::print("PtrExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* a = e1->toElem(p);
+
+    if (p->topexp() && p->topexp()->e1 == this) {
+        Logger::println("lval PtrExp");
+        //if (a->isField()) return a;
+        return new DVarValue(type, a->getRVal(), true);
+    }
+
+    llvm::Value* lv = a->getRVal();
+    llvm::Value* v = lv;
+    if (DtoCanLoad(v))
+        v = DtoLoad(v);
+    return new DLValueCast(type, lv, v);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DotVarExp::toElem(IRState* p)
+{
+    Logger::print("DotVarExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* 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->getRVal();
+            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->getRVal();
+            Logger::cout() << "src: " << *src << '\n';
+            arrptr = DtoGEP(src,vdoffsets,"tmp",p->scopebb());
+        }
+        else
+            assert(0);
+
+        Logger::cout() << "mem: " << *arrptr << '\n';
+        return new DVarValue(vd, arrptr, true);
+    }
+    else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
+    {
+        if (fdecl->llvmValue == 0)
+        {
+            fdecl->toObjFile();
+        }
+
+        llvm::Value* funcval = fdecl->llvmValue;
+        llvm::Value* vthis = l->getRVal();
+        unsigned cc = (unsigned)-1;
+
+        // 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(vthis, 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());
+            cc = DtoCallingConv(fdecl->linkage);
+        }
+        return new DFuncValue(fdecl, funcval, vthis);
+    }
+    else {
+        printf("unknown: %s\n", var->toChars());
+    }
+
+    assert(0);
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* ThisExp::toElem(IRState* p)
+{
+    Logger::print("ThisExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    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());
+        return new DThisValue(vd, v);
+    }
+
+    assert(0);
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* AddrExp::toElem(IRState* p)
+{
+    Logger::print("AddrExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+    DValue* v = e1->toElem(p);
+    if (v->isField())
+        return v;
+    return new DFieldValue(type, v->getLVal(), false);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* IndexExp::toElem(IRState* p)
+{
+    Logger::print("IndexExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+
+    Type* e1type = DtoDType(e1->type);
+
+    p->arrays.push_back(l); // if $ is used it must be an array so this is fine.
+    DValue* 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->getRVal(),r->getRVal(),"tmp",p->scopebb());
+    }
+    else if (e1type->ty == Tsarray) {
+        arrptr = DtoGEP(l->getRVal(), zero, r->getRVal(),"tmp",p->scopebb());
+    }
+    else if (e1type->ty == Tarray) {
+        arrptr = DtoGEP(l->getLVal(),zero,one,"tmp",p->scopebb());
+        arrptr = new llvm::LoadInst(arrptr,"tmp",p->scopebb());
+        arrptr = new llvm::GetElementPtrInst(arrptr,r->getRVal(),"tmp",p->scopebb());
+    }
+    assert(arrptr);
+    return new DVarValue(type, arrptr, true);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* SliceExp::toElem(IRState* p)
+{
+    Logger::print("SliceExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    Type* t = DtoDType(type);
+    Type* e1type = DtoDType(e1->type);
+
+    DValue* v = e1->toElem(p);
+    llvm::Value* vmem = v->getLVal();
+    assert(vmem);
+
+    llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+    llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
+
+    llvm::Value* emem = 0;
+    llvm::Value* earg = 0;
+
+    // partial slice
+    if (lwr)
+    {
+        assert(upr);
+        p->arrays.push_back(v);
+        DValue* lo = lwr->toElem(p);
+
+        bool lwr_is_zero = false;
+        if (DConstValue* cv = lo->isConst())
+        {
+            assert(llvm::isa<llvm::ConstantInt>(cv->c));
+
+            if (e1type->ty == Tpointer) {
+                emem = v->getRVal();
+            }
+            else if (e1type->ty == Tarray) {
+                llvm::Value* tmp = DtoGEP(vmem,zero,one,"tmp",p->scopebb());
+                emem = new llvm::LoadInst(tmp,"tmp",p->scopebb());
+            }
+            else if (e1type->ty == Tsarray) {
+                emem = DtoGEP(vmem,zero,zero,"tmp",p->scopebb());
+            }
+            else
+            assert(emem);
+
+            llvm::ConstantInt* c = llvm::cast<llvm::ConstantInt>(cv->c);
+            if (!(lwr_is_zero = c->isZero())) {
+                emem = new llvm::GetElementPtrInst(emem,cv->c,"tmp",p->scopebb());
+            }
+        }
+        else
+        {
+            if (e1type->ty == Tarray) {
+                llvm::Value* tmp = DtoGEP(vmem,zero,one,"tmp",p->scopebb());
+                tmp = new llvm::LoadInst(tmp,"tmp",p->scopebb());
+                emem = new llvm::GetElementPtrInst(tmp,lo->getRVal(),"tmp",p->scopebb());
+            }
+            else if (e1type->ty == Tsarray) {
+                emem = DtoGEP(vmem,zero,lo->getRVal(),"tmp",p->scopebb());
+            }
+            else if (e1type->ty == Tpointer) {
+                emem = new llvm::GetElementPtrInst(v->getRVal(),lo->getRVal(),"tmp",p->scopebb());
+            }
+            else {
+                Logger::println("type = %s", e1type->toChars());
+                assert(0);
+            }
+        }
+
+        DValue* up = upr->toElem(p);
+        p->arrays.pop_back();
+
+        if (DConstValue* cv = up->isConst())
+        {
+            assert(llvm::isa<llvm::ConstantInt>(cv->c));
+            if (lwr_is_zero) {
+                earg = cv->c;
+            }
+            else {
+                if (lo->isConst()) {
+                    llvm::Constant* clo = llvm::cast<llvm::Constant>(lo->getRVal());
+                    llvm::Constant* cup = llvm::cast<llvm::Constant>(cv->c);
+                    earg = llvm::ConstantExpr::getSub(cup, clo);
+                }
+                else {
+                    earg = llvm::BinaryOperator::createSub(cv->c, lo->getRVal(), "tmp", p->scopebb());
+                }
+            }
+        }
+        else
+        {
+            if (lwr_is_zero) {
+                earg = up->getRVal();
+            }
+            else {
+                earg = llvm::BinaryOperator::createSub(up->getRVal(), lo->getRVal(), "tmp", p->scopebb());
+            }
+        }
+    }
+    // full slice
+    else
+    {
+        emem = vmem;
+    }
+
+    return new DSliceValue(type,earg,emem);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* CmpExp::toElem(IRState* p)
+{
+    Logger::print("CmpExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+    DValue* r = e2->toElem(p);
+
+    Type* t = DtoDType(e1->type);
+    Type* e2t = DtoDType(e2->type);
+    assert(t == e2t);
+
+    llvm::Value* eval = 0;
+
+    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;
+            eval = llvm::ConstantInt::getTrue();
+            break;
+        case TOKunord:
+            skip = true;
+            eval = llvm::ConstantInt::getFalse();
+            break;
+
+        default:
+            assert(0);
+        }
+        if (!skip)
+        {
+            eval = new llvm::ICmpInst(cmpop, l->getRVal(), r->getRVal(), "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);
+        }
+        eval = new llvm::FCmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb());
+    }
+    else
+    {
+        assert(0 && "Unsupported CmpExp type");
+    }
+
+    return new DImValue(type, eval);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* EqualExp::toElem(IRState* p)
+{
+    Logger::print("EqualExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+    DValue* r = e2->toElem(p);
+
+    Type* t = DtoDType(e1->type);
+    Type* e2t = DtoDType(e2->type);
+    assert(t == e2t);
+
+    llvm::Value* eval = 0;
+
+    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);
+        }
+        eval = new llvm::ICmpInst(cmpop, l->getRVal(), r->getRVal(), "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);
+        }
+        eval = new llvm::FCmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb());
+    }
+    else if (t->ty == Tsarray)
+    {
+        Logger::println("static array");
+        eval = DtoStaticArrayCompare(op,l->getRVal(),r->getRVal());
+    }
+    else if (t->ty == Tarray)
+    {
+        Logger::println("dynamic array");
+        eval = DtoDynArrayCompare(op,l->getRVal(),r->getRVal());
+    }
+    else if (t->ty == Tdelegate)
+    {
+        Logger::println("delegate");
+        eval = DtoCompareDelegate(op,l->getRVal(),r->getRVal());
+    }
+    else
+    {
+        assert(0 && "Unsupported EqualExp type");
+    }
+
+    return new DImValue(type, eval);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* PostExp::toElem(IRState* p)
+{
+    Logger::print("PostExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+    DValue* r = e2->toElem(p);
+
+    llvm::Value* val = l->getRVal();
+    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);
+
+    DtoStore(post,l->getLVal());
+
+    return new DImValue(type,val,true);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* NewExp::toElem(IRState* p)
+{
+    Logger::print("NewExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    assert(!thisexp);
+    assert(!newargs);
+    assert(newtype);
+    assert(!allocator);
+
+    Type* ntype = DtoDType(newtype);
+
+    const llvm::Type* t = DtoType(ntype);
+
+    llvm::Value* emem = 0;
+    bool inplace = true;
+
+    if (onstack) {
+        assert(ntype->ty == Tclass);
+        emem = new llvm::AllocaInst(t->getContainedType(0),"tmp",p->topallocapoint());
+    }
+    else {
+        if (ntype->ty == Tclass) {
+            emem = new llvm::MallocInst(t->getContainedType(0),"tmp",p->scopebb());
+        }
+        else if (ntype->ty == Tarray) {
+            assert(arguments);
+            if (arguments->dim == 1) {
+                DValue* sz = ((Expression*)arguments->data[0])->toElem(p);
+                llvm::Value* dimval = sz->getRVal();
+                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';
+                    emem = new llvm::AllocaInst(restype,"tmp",p->topallocapoint());
+                    DtoNewDynArray(emem, dimval, nnt);
+                    inplace = false;
+                }
+                else if (p->topexp() || p->topexp()->e2 != this) {
+                    assert(p->topexp()->v);
+                    emem = p->topexp()->v->getLVal();
+                    DtoNewDynArray(emem, dimval, nnt);
+                }
+                else
+                assert(0);
+            }
+            else {
+                assert(0);
+            }
+        }
+        else {
+            emem = new llvm::MallocInst(t,"tmp",p->scopebb());
+        }
+    }
+
+    if (ntype->ty == Tclass) {
+        // first apply the static initializer
+        DtoInitClass((TypeClass*)ntype, emem);
+
+        // 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(emem);
+            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);
+            }
+            emem = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb());
+        }
+    }
+    else if (ntype->ty == Tstruct) {
+        TypeStruct* ts = (TypeStruct*)ntype;
+        if (ts->isZeroInit()) {
+            DtoStructZeroInit(emem);
+        }
+        else {
+            DtoStructCopy(emem,ts->llvmInit);
+        }
+    }
+
+    if (inplace)
+        return new DImValue(type, emem, true);
+
+    return new DVarValue(type, emem, true);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DeleteExp::toElem(IRState* p)
+{
+    Logger::print("DeleteExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    //assert(e1->type->ty != Tclass);
+
+    DValue* v = e1->toElem(p);
+    llvm::Value* val = v->getRVal();
+    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) {
+        Logger::cout() << *z << '\n';
+        Logger::cout() << *val << '\n';
+        new llvm::FreeInst(val, p->scopebb());
+        new llvm::StoreInst(z, v->getLVal(), p->scopebb());
+    }
+    else if (e1type->ty == Tclass) {
+        TypeClass* tc = (TypeClass*)e1type;
+        DtoCallClassDtors(tc, val);
+
+        if (DVarValue* vv = v->isVar()) {
+            if (vv->var && !vv->var->onstack)
+                new llvm::FreeInst(val, p->scopebb());
+        }
+        new llvm::StoreInst(z, v->getLVal(), p->scopebb());
+    }
+    else if (e1type->ty == Tarray) {
+        // must be on the heap (correct?)
+        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(val,zero,one,"tmp",p->scopebb());
+        ptr = new llvm::LoadInst(ptr,"tmp",p->scopebb());
+        new llvm::FreeInst(ptr, p->scopebb());
+        DtoNullArray(val);
+    }
+    else {
+        assert(0);
+    }
+
+    // this expression produces no useful data
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* ArrayLengthExp::toElem(IRState* p)
+{
+    Logger::print("ArrayLengthExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* u = e1->toElem(p);
+
+    if (p->topexp() && p->topexp()->e1 == this)
+    {
+        return new DArrayLenValue(type, u->getLVal());
+    }
+    else
+    {
+        llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+        llvm::Value* ptr = DtoGEP(u->getRVal(),zero,zero,"tmp",p->scopebb());
+        ptr = new llvm::LoadInst(ptr, "tmp", p->scopebb());
+        return new DImValue(type, ptr);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* AssertExp::toElem(IRState* p)
+{
+    Logger::print("AssertExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* u = e1->toElem(p);
+    DValue* m = msg ? msg->toElem(p) : NULL;
+
+    llvm::Value* loca = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
+    DtoAssert(u->getRVal(), loca, m ? m->getRVal() : NULL);
+
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* NotExp::toElem(IRState* p)
+{
+    Logger::print("NotExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* u = e1->toElem(p);
+
+    llvm::Value* b = DtoBoolean(u->getRVal());
+
+    llvm::Constant* zero = llvm::ConstantInt::get(llvm::Type::Int1Ty, 0, true);
+    b = p->ir->CreateICmpEQ(b,zero);
+
+    return new DImValue(type, b);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* 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());
+
+    DValue* 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->getRVal());
+    new llvm::StoreInst(ubool,resval,p->scopebb());
+    new llvm::BranchInst(andand,andandend,ubool,p->scopebb());
+
+    p->scope() = IRScope(andand, andandend);
+    DValue* v = e2->toElem(p);
+
+    llvm::Value* vbool = DtoBoolean(v->getRVal());
+    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());
+
+    p->scope() = IRScope(andandend, oldend);
+
+    resval = new llvm::LoadInst(resval,"tmp",p->scopebb());
+    return new DImValue(type, resval);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* 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());
+
+    DValue* 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->getRVal());
+    new llvm::StoreInst(ubool,resval,p->scopebb());
+    new llvm::BranchInst(ororend,oror,ubool,p->scopebb());
+
+    p->scope() = IRScope(oror, ororend);
+    DValue* v = e2->toElem(p);
+
+    llvm::Value* vbool = DtoBoolean(v->getRVal());
+    new llvm::StoreInst(vbool,resval,p->scopebb());
+    new llvm::BranchInst(ororend,p->scopebb());
+
+    p->scope() = IRScope(ororend, oldend);
+
+    resval = new llvm::LoadInst(resval,"tmp",p->scopebb());
+    return new DImValue(type, resval);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#define BinBitExp(X,Y) \
+DValue* X##Exp::toElem(IRState* p) \
+{ \
+    Logger::print("%sExp::toElem: %s | %s\n", #X, toChars(), type->toChars()); \
+    LOG_SCOPE; \
+    DValue* u = e1->toElem(p); \
+    DValue* v = e2->toElem(p); \
+    llvm::Value* x = llvm::BinaryOperator::create(llvm::Instruction::Y, u->getRVal(), v->getRVal(), "tmp", p->scopebb()); \
+    return new DImValue(type, x); \
+} \
+\
+DValue* X##AssignExp::toElem(IRState* p) \
+{ \
+    Logger::print("%sAssignExp::toElem: %s | %s\n", #X, toChars(), type->toChars()); \
+    LOG_SCOPE; \
+    p->exps.push_back(IRExp(e1,e2,NULL)); \
+    DValue* u = e1->toElem(p); \
+    p->topexp()->v = u; \
+    DValue* v = e2->toElem(p); \
+    p->exps.pop_back(); \
+    llvm::Value* uval = u->getRVal(); \
+    llvm::Value* vval = v->getRVal(); \
+    llvm::Value* tmp = llvm::BinaryOperator::create(llvm::Instruction::Y, uval, vval, "tmp", p->scopebb()); \
+    new llvm::StoreInst(DtoPointedType(u->getLVal(), tmp), u->getLVal(), p->scopebb()); \
+    return u; \
+}
+
+BinBitExp(And,And);
+BinBitExp(Or,Or);
+BinBitExp(Xor,Xor);
+BinBitExp(Shl,Shl);
+BinBitExp(Shr,AShr);
+BinBitExp(Ushr,LShr);
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* 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;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DelegateExp::toElem(IRState* p)
+{
+    Logger::print("DelegateExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* 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->getLVal();
+
+    llvm::Value* context = DtoGEP(lval,zero,zero,"tmp",p->scopebb());
+    llvm::Value* castcontext = new llvm::BitCastInst(u->getRVal(),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());
+
+    return new DImValue(type, u->getRVal(), true);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* IdentityExp::toElem(IRState* p)
+{
+    Logger::print("IdentityExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* u = e1->toElem(p);
+    DValue* v = e2->toElem(p);
+
+    llvm::Value* l = u->getRVal();
+    llvm::Value* r = v->getRVal();
+
+    Type* t1 = DtoDType(e1->type);
+
+    llvm::Value* eval = 0;
+
+    if (t1->ty == Tarray) {
+        if (v->isNull()) {
+            r = NULL;
+        }
+        else {
+            assert(l->getType() == r->getType());
+        }
+        eval = DtoDynArrayIs(op,l,r);
+    }
+    else {
+        llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
+        if (t1->ty == Tpointer && v->isNull() && l->getType() != r->getType()) {
+            r = llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(l->getType()));
+        }
+        Logger::cout() << "l = " << *l << " r = " << *r << '\n';
+        eval = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
+    }
+    return new DImValue(type, eval);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* CommaExp::toElem(IRState* p)
+{
+    Logger::print("CommaExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* u = e1->toElem(p);
+    DValue* v = e2->toElem(p);
+    return v;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* 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());
+    DVarValue* dvv = new DVarValue(type, resval, true);
+
+    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);
+
+    DValue* c = econd->toElem(p);
+    llvm::Value* cond_val = DtoBoolean(c->getRVal());
+    new llvm::BranchInst(condtrue,condfalse,cond_val,p->scopebb());
+
+    p->scope() = IRScope(condtrue, condfalse);
+    DValue* u = e1->toElem(p);
+    DtoAssign(dvv, u);
+    new llvm::BranchInst(condend,p->scopebb());
+
+    p->scope() = IRScope(condfalse, condend);
+    DValue* v = e2->toElem(p);
+    DtoAssign(dvv, v);
+    new llvm::BranchInst(condend,p->scopebb());
+
+    p->scope() = IRScope(condend, oldend);
+    return dvv;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* ComExp::toElem(IRState* p)
+{
+    Logger::print("ComExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* u = e1->toElem(p);
+
+    llvm::Value* value = u->getRVal();
+    llvm::Value* minusone = llvm::ConstantInt::get(value->getType(), -1, true);
+    value = llvm::BinaryOperator::create(llvm::Instruction::Xor, value, minusone, "tmp", p->scopebb());
+
+    return new DImValue(type, value);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* NegExp::toElem(IRState* p)
+{
+    Logger::print("NegExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+    llvm::Value* val = l->getRVal();
+
+    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);
+
+    val = llvm::BinaryOperator::createSub(zero,val,"tmp",p->scopebb());
+    return new DImValue(type, val);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* CatExp::toElem(IRState* p)
+{
+    Logger::print("CatExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    Type* t = DtoDType(type);
+
+    IRExp* ex = p->topexp();
+    if (ex && ex->e2 == this) {
+        assert(ex->v);
+        DtoCatArrays(ex->v->getLVal(),e1,e2);
+        return new DImValue(type, ex->v->getLVal(), true);
+    }
+    else {
+        assert(t->ty == Tarray);
+        const llvm::Type* arrty = DtoType(t);
+        llvm::Value* dst = new llvm::AllocaInst(arrty, "tmpmem", p->topallocapoint());
+        DtoCatArrays(dst,e1,e2);
+        return new DVarValue(type, dst, true);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* CatAssignExp::toElem(IRState* p)
+{
+    Logger::print("CatAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    DValue* l = e1->toElem(p);
+
+    Type* e1type = DtoDType(e1->type);
+    Type* elemtype = DtoDType(e1type->next);
+    Type* e2type = DtoDType(e2->type);
+
+    if (e2type == elemtype) {
+        DtoCatAssignElement(l->getLVal(),e2);
+    }
+    else if (e1type == e2type) {
+        DtoCatAssignArray(l->getLVal(),e2);
+    }
+    else
+        assert(0 && "only one element at a time right now");
+
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* 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) {
+        assert(p->topexp()->v);
+        lval = p->topexp()->v->getLVal();;
+    }
+    else
+    assert(0);
+
+    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());
+
+    return new DImValue(type, lval, true);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* 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) {
+        DValue* tlv = p->topexp()->v;
+        if (DSliceValue* sv = tlv->isSlice()) {
+            assert(sv->len == 0);
+            mem = sv->ptr;
+        }
+        else {
+            mem = p->topexp()->v->getLVal();
+        }
+        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());
+        DValue* e = expr->toElem(p);
+        new llvm::StoreInst(e->getRVal(), elemAddr, p->scopebb());
+    }
+
+    return new DImValue(type, mem, true);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+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);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* StructLiteralExp::toElem(IRState* p)
+{
+    Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    llvm::Value* sptr;
+    const llvm::Type* llt = DtoType(type);
+
+    llvm::Value* mem = 0;
+
+    // temporary struct literal
+    if (!p->topexp() || p->topexp()->e2 != this)
+    {
+        sptr = new llvm::AllocaInst(llt,"tmpstructliteral",p->topallocapoint());
+    }
+    // already has memory
+    else
+    {
+        assert(p->topexp()->e2 == this);
+        sptr = p->topexp()->v->getLVal();
+    }
+
+    // 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());
+        DValue* darrptr = new DVarValue(vx->type, arrptr, true);
+
+        p->exps.push_back(IRExp(NULL,vx,darrptr));
+        DValue* ve = vx->toElem(p);
+        p->exps.pop_back();
+
+        if (!ve->inPlace())
+            DtoAssign(darrptr, ve);
+
+        j++;
+    }
+
+    return new DImValue(type, sptr, true);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+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);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#define STUB(x) DValue *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();
+}
--- a/gen/tollvm.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1479 +0,0 @@
-#include <iostream>
-
-#include "gen/llvm.h"
-
-#include "mtype.h"
-#include "dsymbol.h"
-#include "aggregate.h"
-#include "declaration.h"
-#include "init.h"
-
-#include "gen/tollvm.h"
-#include "gen/irstate.h"
-#include "gen/logger.h"
-#include "gen/runtime.h"
-#include "gen/elem.h"
-#include "gen/arrays.h"
-
-bool DtoIsPassedByRef(Type* type)
-{
-    TY t = DtoDType(type)->ty;
-    return (t == Tstruct || t == Tarray || t == Tdelegate);
-}
-
-Type* DtoDType(Type* t)
-{
-    if (t->ty == Ttypedef) {
-        Type* bt = t->toBasetype();
-        assert(bt);
-        return DtoDType(bt);
-    }
-    return t;
-}
-
-const llvm::Type* DtoType(Type* t)
-{
-    assert(t);
-    switch (t->ty)
-    {
-    // integers
-    case Tint8:
-    case Tuns8:
-    case Tchar:
-        return (const llvm::Type*)llvm::Type::Int8Ty;
-    case Tint16:
-    case Tuns16:
-    case Twchar:
-        return (const llvm::Type*)llvm::Type::Int16Ty;
-    case Tint32:
-    case Tuns32:
-    case Tdchar:
-        return (const llvm::Type*)llvm::Type::Int32Ty;
-    case Tint64:
-    case Tuns64:
-        return (const llvm::Type*)llvm::Type::Int64Ty;
-
-    case Tbool:
-        return (const llvm::Type*)llvm::ConstantInt::getTrue()->getType();
-
-    // floats
-    case Tfloat32:
-    case Timaginary32:
-        return llvm::Type::FloatTy;
-    case Tfloat64:
-    case Timaginary64:
-    case Tfloat80:
-    case Timaginary80:
-        return llvm::Type::DoubleTy;
-
-    // complex
-    case Tcomplex32:
-    case Tcomplex64:
-    case Tcomplex80:
-        assert(0 && "complex number types not yet implemented");
-
-    // pointers
-    case Tpointer: {
-        assert(t->next);
-        if (t->next->ty == Tvoid)
-            return (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty);
-        else
-            return (const llvm::Type*)llvm::PointerType::get(DtoType(t->next));
-    }
-
-    // arrays
-    case Tarray:
-        return DtoArrayType(t);
-    case Tsarray:
-        return DtoStaticArrayType(t);
-
-    // void
-    case Tvoid:
-        return llvm::Type::VoidTy;
-
-    // aggregates
-    case Tstruct:    {
-        if (t->llvmType == 0)
-        {
-            // recursive or cyclic declaration
-            if (!gIR->structs.empty())
-            {
-                IRStruct* found = 0;
-                for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i)
-                {
-                    if (t == i->type)
-                    {
-                        return i->recty.get();
-                    }
-                }
-            }
-
-            // forward declaration
-            TypeStruct* ts = (TypeStruct*)t;
-            assert(ts->sym);
-            ts->sym->toObjFile();
-        }
-        return t->llvmType;
-    }
-
-    case Tclass:    {
-        if (t->llvmType == 0)
-        {
-            // recursive or cyclic declaration
-            if (!gIR->structs.empty())
-            {
-                IRStruct* found = 0;
-                for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i)
-                {
-                    if (t == i->type)
-                    {
-                        return llvm::PointerType::get(i->recty.get());
-                    }
-                }
-            }
-
-            // forward declaration
-            TypeClass* tc = (TypeClass*)t;
-            assert(tc->sym);
-            tc->sym->toObjFile();
-        }
-        return llvm::PointerType::get(t->llvmType);
-    }
-
-    // functions
-    case Tfunction:
-    {
-        if (t->llvmType == 0) {
-            return DtoFunctionType(t,NULL);
-        }
-        else {
-            return t->llvmType;
-        }
-    }
-
-    // delegates
-    case Tdelegate:
-    {
-        if (t->llvmType == 0) {
-            return DtoDelegateType(t);
-        }
-        else {
-            return t->llvmType;
-        }
-    }
-
-    // typedefs
-    // enum
-    case Ttypedef:
-    case Tenum:
-    {
-        Type* bt = t->toBasetype();
-        assert(bt);
-        return DtoType(bt);
-    }
-
-    default:
-        printf("trying to convert unknown type with value %d\n", t->ty);
-        assert(0);
-    }
-    return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype, bool ismain)
-{
-    TypeFunction* f = (TypeFunction*)type;
-    assert(f != 0);
-
-    bool typesafeVararg = false;
-    if (f->linkage == LINKd && f->varargs == 1) {
-        typesafeVararg = true;
-    }
-
-    // return value type
-    const llvm::Type* rettype;
-    const llvm::Type* actualRettype;
-    Type* rt = f->next;
-    bool retinptr = false;
-    bool usesthis = false;
-
-    if (ismain) {
-        rettype = llvm::Type::Int32Ty;
-        actualRettype = rettype;
-    }
-    else {
-        assert(rt);
-        if (DtoIsPassedByRef(rt)) {
-            rettype = llvm::PointerType::get(DtoType(rt));
-            actualRettype = llvm::Type::VoidTy;
-            f->llvmRetInPtr = retinptr = true;
-        }
-        else {
-            rettype = DtoType(rt);
-            actualRettype = rettype;
-        }
-    }
-
-    // parameter types
-    std::vector<const llvm::Type*> paramvec;
-
-    if (retinptr) {
-        Logger::cout() << "returning through pointer parameter: " << *rettype << '\n';
-        paramvec.push_back(rettype);
-    }
-
-    if (thistype) {
-        paramvec.push_back(thistype);
-        usesthis = true;
-    }
-
-    if (typesafeVararg) {
-        ClassDeclaration* ti = Type::typeinfo;
-        if (!ti->llvmInitZ)
-            ti->toObjFile();
-        assert(ti->llvmInitZ);
-        std::vector<const llvm::Type*> types;
-        types.push_back(DtoSize_t());
-        types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmInitZ->getType())));
-        const llvm::Type* t1 = llvm::StructType::get(types);
-        paramvec.push_back(llvm::PointerType::get(t1));
-        paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
-    }
-
-    size_t n = Argument::dim(f->parameters);
-
-    for (int i=0; i < n; ++i) {
-        Argument* arg = Argument::getNth(f->parameters, i);
-        // ensure scalar
-        Type* argT = DtoDType(arg->type);
-        assert(argT);
-
-        if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
-            //assert(arg->vardecl);
-            //arg->vardecl->refparam = true;
-        }
-        else
-            arg->llvmCopy = true;
-
-        const llvm::Type* at = DtoType(argT);
-        if (llvm::isa<llvm::StructType>(at)) {
-            Logger::println("struct param");
-            paramvec.push_back(llvm::PointerType::get(at));
-        }
-        else if (llvm::isa<llvm::ArrayType>(at)) {
-            Logger::println("sarray param");
-            assert(argT->ty == Tsarray);
-            //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0)));
-            paramvec.push_back(llvm::PointerType::get(at));
-        }
-        else if (llvm::isa<llvm::OpaqueType>(at)) {
-            Logger::println("opaque param");
-            if (argT->ty == Tstruct || argT->ty == Tclass)
-                paramvec.push_back(llvm::PointerType::get(at));
-            else
-            assert(0);
-        }
-        /*if (llvm::isa<llvm::StructType>(at) || argT->ty == Tstruct || argT->ty == Tsarray) {
-            paramvec.push_back(llvm::PointerType::get(at));
-        }*/
-        else {
-            if (!arg->llvmCopy) {
-                Logger::println("ref param");
-                at = llvm::PointerType::get(at);
-            }
-            else {
-                Logger::println("in param");
-            }
-            paramvec.push_back(at);
-        }
-    }
-
-    // construct function type
-    bool isvararg = !typesafeVararg && f->varargs;
-    llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
-
-    f->llvmRetInPtr = retinptr;
-    f->llvmUsesThis = usesthis;
-    return functype;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
-{
-    TypeFunction* f = (TypeFunction*)fdecl->type;
-    assert(f != 0);
-
-    const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
-    std::vector<const llvm::Type*> args;
-
-    if (fdecl->llvmInternal == LLVMva_start) {
-        args.push_back(i8pty);
-    }
-    else if (fdecl->llvmInternal == LLVMva_intrinsic) {
-        size_t n = Argument::dim(f->parameters);
-        for (size_t i=0; i<n; ++i) {
-            args.push_back(i8pty);
-        }
-    }
-    else
-    assert(0);
-
-    const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
-    f->llvmType = fty;
-    return fty;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
-{
-    if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
-        return DtoVaFunctionType(fdecl);
-    }
-
-    // type has already been resolved
-    if (fdecl->type->llvmType != 0) {
-        return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType);
-    }
-
-    const llvm::Type* thisty = NULL;
-    if (fdecl->needThis()) {
-        if (AggregateDeclaration* ad = fdecl->isMember()) {
-            Logger::print("isMember = this is: %s\n", ad->type->toChars());
-            thisty = DtoType(ad->type);
-            Logger::cout() << "this llvm type: " << *thisty << '\n';
-            if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get())
-                thisty = llvm::PointerType::get(thisty);
-        }
-        else
-        assert(0);
-    }
-    else if (fdecl->isNested()) {
-        thisty = llvm::PointerType::get(llvm::Type::Int8Ty);
-    }
-
-    const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain());
-    fdecl->type->llvmType = functype;
-    return functype;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-const llvm::StructType* DtoDelegateType(Type* t)
-{
-    const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty);
-    const llvm::Type* func = DtoFunctionType(t->next, i8ptr);
-    const llvm::Type* funcptr = llvm::PointerType::get(func);
-
-    std::vector<const llvm::Type*> types;
-    types.push_back(i8ptr);
-    types.push_back(funcptr);
-    return llvm::StructType::get(types);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-const llvm::Type* DtoStructType(Type* t)
-{
-    assert(0);
-    std::vector<const llvm::Type*> types;
-    return llvm::StructType::get(types);
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static llvm::Function* LLVM_DeclareMemIntrinsic(const char* name, int bits, bool set=false)
-{
-    assert(bits == 32 || bits == 64);
-    const llvm::Type* int8ty =    (const llvm::Type*)llvm::Type::Int8Ty;
-    const llvm::Type* int32ty =   (const llvm::Type*)llvm::Type::Int32Ty;
-    const llvm::Type* int64ty =   (const llvm::Type*)llvm::Type::Int64Ty;
-    const llvm::Type* int8ptrty = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty);
-    const llvm::Type* voidty =    (const llvm::Type*)llvm::Type::VoidTy;
-
-    assert(gIR);
-    assert(gIR->module);
-
-    // parameter types
-    std::vector<const llvm::Type*> pvec;
-    pvec.push_back(int8ptrty);
-    pvec.push_back(set?int8ty:int8ptrty);
-    pvec.push_back(bits==32?int32ty:int64ty);
-    pvec.push_back(int32ty);
-    llvm::FunctionType* functype = llvm::FunctionType::get(voidty, pvec, false);
-    return new llvm::Function(functype, llvm::GlobalValue::ExternalLinkage, name, gIR->module);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-// llvm.memset.i32
-llvm::Function* LLVM_DeclareMemSet32()
-{
-    static llvm::Function* _func = 0;
-    if (_func == 0) {
-        _func = LLVM_DeclareMemIntrinsic("llvm.memset.i32", 32, true);
-    }
-    return _func;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Function* LLVM_DeclareMemSet64()
-{
-    static llvm::Function* _func = 0;
-    if (_func == 0) {
-        _func = LLVM_DeclareMemIntrinsic("llvm.memset.i64", 64, true);
-    }
-    return _func;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-// llvm.memcpy.i32
-llvm::Function* LLVM_DeclareMemCpy32()
-{
-    static llvm::Function* _func = 0;
-    if (_func == 0) {
-        _func = LLVM_DeclareMemIntrinsic("llvm.memcpy.i32", 32);
-    }
-    return _func;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-// llvm.memcpy.i64
-llvm::Function* LLVM_DeclareMemCpy64()
-{
-    static llvm::Function* _func = 0;
-    if (_func == 0) {
-        _func = LLVM_DeclareMemIntrinsic("llvm.memcpy.i64", 64);
-    }
-    return _func;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoStructZeroInit(llvm::Value* v)
-{
-    assert(gIR);
-    uint64_t n = gTargetData->getTypeSize(v->getType()->getContainedType(0));
-    //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n));
-    llvm::Type* sarrty = llvm::PointerType::get(llvm::Type::Int8Ty);
-
-    llvm::Value* sarr = new llvm::BitCastInst(v,sarrty,"tmp",gIR->scopebb());
-
-    llvm::Function* fn = LLVM_DeclareMemSet32();
-    std::vector<llvm::Value*> llargs;
-    llargs.resize(4);
-    llargs[0] = sarr;
-    llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false);
-    llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
-    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-    llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-
-    return ret;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoStructCopy(llvm::Value* dst, llvm::Value* src)
-{
-    Logger::cout() << "dst = " << *dst << " src = " << *src << '\n';
-    assert(dst->getType() == src->getType());
-    assert(gIR);
-
-    uint64_t n = gTargetData->getTypeSize(dst->getType()->getContainedType(0));
-    //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n));
-    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 = LLVM_DeclareMemCpy32();
-    std::vector<llvm::Value*> llargs;
-    llargs.resize(4);
-    llargs[0] = dstarr;
-    llargs[1] = srcarr;
-    llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
-    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-    return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-llvm::Constant* DtoConstStructInitializer(StructInitializer* si)
-{
-    llvm::StructType* structtype = llvm::cast<llvm::StructType>(si->ad->llvmType);
-    size_t n = structtype->getNumElements();
-
-    assert(si->value.dim == si->vars.dim);
-
-    std::vector<llvm::Constant*> inits;
-    inits.resize(n, NULL);
-    for (int i = 0; i < si->value.dim; ++i)
-    {
-        Initializer* ini = (Initializer*)si->value.data[i];
-        assert(ini);
-
-        VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
-        Type* vdtype = DtoDType(vd->type);
-        assert(vd);
-        Logger::println("vars[%d] = %s", i, vd->toChars());
-
-        llvm::Constant* v = 0;
-
-        assert(vd->llvmFieldIndex >= 0);
-        unsigned idx = vd->llvmFieldIndex;
-
-        if (ExpInitializer* ex = ini->isExpInitializer())
-        {
-            v = ex->exp->toConstElem(gIR);
-        }
-        else if (StructInitializer* si = ini->isStructInitializer())
-        {
-            v = DtoConstStructInitializer(si);
-        }
-        else if (ArrayInitializer* ai = ini->isArrayInitializer())
-        {
-            v = DtoConstArrayInitializer(ai);
-        }
-        else if (ini->isVoidInitializer())
-        {
-            v = llvm::UndefValue::get(structtype->getElementType(idx));
-        }
-        else
-        assert(v);
-
-        inits[idx] = v;
-        Logger::cout() << "init[" << idx << "] = " << *v << '\n';
-    }
-
-    // fill out nulls
-    assert(si->ad->llvmInitZ);
-    if (si->ad->llvmInitZ->isNullValue())
-    {
-        for (int i = 0; i < n; ++i)
-        {
-            if (inits[i] == 0)
-            {
-                inits[i] = llvm::Constant::getNullValue(structtype->getElementType(i));
-            }
-        }
-    }
-    else
-    {
-        for (int i = 0; i < n; ++i)
-        {
-            if (inits[i] == 0)
-            {
-                inits[i] = si->ad->llvmInitZ->getOperand(i);
-            }
-        }
-    }
-
-    return llvm::ConstantStruct::get(structtype, inits);
-}
-
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoNullDelegate(llvm::Value* v)
-{
-    assert(gIR);
-    d_uns64 n = (global.params.is64bit) ? 16 : 8;
-
-    llvm::Type* i8p_ty = llvm::PointerType::get(llvm::Type::Int8Ty);
-
-    llvm::Value* arr = new llvm::BitCastInst(v,i8p_ty,"tmp",gIR->scopebb());
-
-    llvm::Function* fn = LLVM_DeclareMemSet32();
-    std::vector<llvm::Value*> llargs;
-    llargs.resize(4);
-    llargs[0] = arr;
-    llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false);
-    llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
-    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-    llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-
-    return ret;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoDelegateCopy(llvm::Value* dst, llvm::Value* src)
-{
-    assert(dst->getType() == src->getType());
-    assert(gIR);
-
-    d_uns64 n = (global.params.is64bit) ? 16 : 8;
-
-    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 = LLVM_DeclareMemCpy32();
-    std::vector<llvm::Value*> llargs;
-    llargs.resize(4);
-    llargs[0] = dstarr;
-    llargs[1] = srcarr;
-    llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
-    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-    return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoCompareDelegate(TOK op, llvm::Value* lhs, llvm::Value* rhs)
-{
-    llvm::ICmpInst::Predicate pred = (op == TOKequal) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
-    llvm::Value* l = gIR->ir->CreateLoad(DtoGEPi(lhs,0,0,"tmp"),"tmp");
-    llvm::Value* r = gIR->ir->CreateLoad(DtoGEPi(rhs,0,0,"tmp"),"tmp");
-    llvm::Value* b1 = gIR->ir->CreateICmp(pred,l,r,"tmp");
-    l = gIR->ir->CreateLoad(DtoGEPi(lhs,0,1,"tmp"),"tmp");
-    r = gIR->ir->CreateLoad(DtoGEPi(rhs,0,1,"tmp"),"tmp");
-    llvm::Value* b2 = gIR->ir->CreateICmp(pred,l,r,"tmp");
-    llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
-    if (op == TOKnotequal)
-        return gIR->ir->CreateNot(b,"tmp");
-    return b;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::GlobalValue::LinkageTypes DtoLinkage(PROT prot, uint stc)
-{
-    switch(prot)
-    {
-    case PROTprivate:
-        return llvm::GlobalValue::InternalLinkage;
-
-    case PROTpublic:
-    case PROTpackage:
-    case PROTprotected:
-    case PROTexport:
-        return llvm::GlobalValue::ExternalLinkage;
-
-    case PROTundefined:
-    case PROTnone:
-        assert(0 && "Unsupported linkage type");
-    }
-    return llvm::GlobalValue::ExternalLinkage;
-
-/*      ExternalLinkage = 0, LinkOnceLinkage, WeakLinkage, AppendingLinkage,
-  InternalLinkage, DLLImportLinkage, DLLExportLinkage, ExternalWeakLinkage,
-  GhostLinkage */
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-unsigned DtoCallingConv(LINK l)
-{
-    if (l == LINKc)
-        return llvm::CallingConv::C;
-    else if (l == LINKd || l == LINKdefault)
-        return llvm::CallingConv::Fast;
-    else if (l == LINKwindows)
-        return llvm::CallingConv::X86_StdCall;
-    else
-        assert(0 && "Unsupported calling convention");
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoPointedType(llvm::Value* ptr, llvm::Value* val)
-{
-    const llvm::Type* ptrTy = ptr->getType()->getContainedType(0);
-    const llvm::Type* valTy = val->getType();
-    // ptr points to val's type
-    if (ptrTy == valTy)
-    {
-        return val;
-    }
-    // ptr is integer pointer
-    else if (ptrTy->isInteger())
-    {
-        // val is integer
-        assert(valTy->isInteger());
-        const llvm::IntegerType* pt = llvm::cast<const llvm::IntegerType>(ptrTy);
-        const llvm::IntegerType* vt = llvm::cast<const llvm::IntegerType>(valTy);
-        if (pt->getBitWidth() < vt->getBitWidth()) {
-            return new llvm::TruncInst(val, pt, "tmp", gIR->scopebb());
-        }
-        else
-        assert(0);
-    }
-    // something else unsupported
-    else
-    {
-        Logger::cout() << *ptrTy << '|' << *valTy << '\n';
-        assert(0);
-    }
-    return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoBoolean(llvm::Value* val)
-{
-    const llvm::Type* t = val->getType();
-    if (t->isInteger())
-    {
-        if (t == llvm::Type::Int1Ty)
-            return val;
-        else {
-            llvm::Value* zero = llvm::ConstantInt::get(t, 0, false);
-            return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, val, zero, "tmp", gIR->scopebb());
-        }
-    }
-    else if (llvm::isa<llvm::PointerType>(t)) {
-        const llvm::Type* st = DtoSize_t();
-        llvm::Value* ptrasint = new llvm::PtrToIntInst(val,st,"tmp",gIR->scopebb());
-        llvm::Value* zero = llvm::ConstantInt::get(st, 0, false);
-        return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, ptrasint, zero, "tmp", gIR->scopebb());
-    }
-    else
-    {
-        Logger::cout() << *t << '\n';
-    }
-    assert(0);
-    return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-const llvm::Type* DtoSize_t()
-{
-    if (global.params.is64bit)
-    return llvm::Type::Int64Ty;
-    else
-    return llvm::Type::Int32Ty;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoMain()
-{
-    // emit main function llvm style
-    // int main(int argc, char**argv, char**env);
-
-    assert(gIR != 0);
-    IRState& ir = *gIR;
-
-    assert(ir.emitMain && ir.mainFunc);
-
-    // parameter types
-    std::vector<const llvm::Type*> pvec;
-    pvec.push_back((const llvm::Type*)llvm::Type::Int32Ty);
-    const llvm::Type* chPtrType = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty);
-    pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType));
-    pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType));
-    const llvm::Type* rettype = (const llvm::Type*)llvm::Type::Int32Ty;
-
-    llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false);
-    llvm::Function* func = new llvm::Function(functype,llvm::GlobalValue::ExternalLinkage,"main",ir.module);
-
-    llvm::BasicBlock* bb = new llvm::BasicBlock("entry",func);
-
-    // call static ctors
-    llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_ctors");
-    new llvm::CallInst(fn,"",bb);
-
-    // call user main function
-    llvm::CallInst* call = new llvm::CallInst(ir.mainFunc,"ret",bb);
-    call->setCallingConv(ir.mainFunc->getCallingConv());
-
-    // call static dtors
-    fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_dtors");
-    new llvm::CallInst(fn,"",bb);
-
-    // return
-    new llvm::ReturnInst(call,bb);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance)
-{
-    Array* arr = &tc->sym->dtors;
-    for (size_t i=0; i<arr->dim; i++)
-    {
-        FuncDeclaration* fd = (FuncDeclaration*)arr->data[i];
-        assert(fd->llvmValue);
-        new llvm::CallInst(fd->llvmValue, instance, "", gIR->scopebb());
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoInitClass(TypeClass* tc, llvm::Value* dst)
-{
-    assert(gIR);
-
-    assert(tc->llvmType);
-    uint64_t size_t_size = gTargetData->getTypeSize(DtoSize_t());
-    uint64_t n = gTargetData->getTypeSize(tc->llvmType) - size_t_size;
-
-    // set vtable field
-    llvm::Value* vtblvar = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
-    assert(tc->sym->llvmVtbl);
-    new llvm::StoreInst(tc->sym->llvmVtbl, vtblvar, gIR->scopebb());
-
-    // copy the static initializer
-    if (n > 0) {
-        assert(tc->llvmInit);
-        assert(dst->getType() == tc->llvmInit->getType());
-
-        llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
-
-        llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
-        dstarr = DtoGEPi(dstarr,size_t_size,"tmp",gIR->scopebb());
-
-        llvm::Value* srcarr = new llvm::BitCastInst(tc->llvmInit,arrty,"tmp",gIR->scopebb());
-        srcarr = DtoGEPi(srcarr,size_t_size,"tmp",gIR->scopebb());
-
-        llvm::Function* fn = LLVM_DeclareMemCpy32();
-        std::vector<llvm::Value*> llargs;
-        llargs.resize(4);
-        llargs[0] = dstarr;
-        llargs[1] = srcarr;
-        llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
-        llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-        new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Constant* DtoConstInitializer(Type* type, Initializer* init)
-{
-    llvm::Constant* _init = 0; // may return zero
-    if (!init)
-    {
-        Logger::println("const default initializer for %s", type->toChars());
-        _init = type->defaultInit()->toConstElem(gIR);
-    }
-    else if (ExpInitializer* ex = init->isExpInitializer())
-    {
-        Logger::println("const expression initializer");
-        _init = ex->exp->toConstElem(gIR);
-    }
-    else if (StructInitializer* si = init->isStructInitializer())
-    {
-        Logger::println("const struct initializer");
-        _init = DtoConstStructInitializer(si);
-    }
-    else if (ArrayInitializer* ai = init->isArrayInitializer())
-    {
-        Logger::println("const array initializer");
-        _init = DtoConstArrayInitializer(ai);
-    }
-    else if (init->isVoidInitializer())
-    {
-        Logger::println("const void initializer");
-        const llvm::Type* ty = DtoType(type);
-        _init = llvm::Constant::getNullValue(ty);
-    }
-    else {
-        Logger::println("unsupported const initializer: %s", init->toChars());
-    }
-    return _init;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-elem* DtoInitializer(Initializer* init)
-{
-    if (ExpInitializer* ex = init->isExpInitializer())
-    {
-        Logger::println("expression initializer");
-        return ex->exp->toElem(gIR);
-    }
-    else if (init->isVoidInitializer())
-    {
-        // do nothing
-    }
-    else {
-        Logger::println("unsupported initializer: %s", init->toChars());
-        assert(0);
-    }
-    return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb)
-{
-    std::vector<llvm::Value*> v(2);
-    v[0] = i0;
-    v[1] = i1;
-    Logger::cout() << "DtoGEP: " << *ptr << '\n';
-    return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoGEP(llvm::Value* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb)
-{
-    size_t n = src.size();
-    std::vector<llvm::Value*> dst(n);
-    std::ostream& ostr = Logger::cout();
-    ostr << "indices for '" << *ptr << "':";
-    for (size_t i=0; i<n; ++i)
-    {
-        ostr << ' ' << i;
-        dst[i] = llvm::ConstantInt::get(llvm::Type::Int32Ty, src[i], false);
-    }
-    ostr << '\n';
-    return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb?bb:gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoGEPi(llvm::Value* ptr, unsigned i, const std::string& var, llvm::BasicBlock* bb)
-{
-    return new llvm::GetElementPtrInst(ptr, llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false), var, bb?bb:gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoGEPi(llvm::Value* ptr, unsigned i0, unsigned i1, const std::string& var, llvm::BasicBlock* bb)
-{
-    std::vector<llvm::Value*> v(2);
-    v[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i0, false);
-    v[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i1, false);
-    return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl)
-{
-    TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
-    const llvm::FunctionType* fty = DtoVaFunctionType(fdecl);
-    llvm::Constant* fn = 0;
-
-    if (fdecl->llvmInternal == LLVMva_start) {
-        fn = gIR->module->getOrInsertFunction("llvm.va_start", fty);
-        assert(fn);
-    }
-    else if (fdecl->llvmInternal == LLVMva_intrinsic) {
-        fn = gIR->module->getOrInsertFunction(fdecl->llvmInternal1, fty);
-        assert(fn);
-    }
-    else
-    assert(0);
-
-    llvm::Function* func = llvm::cast_or_null<llvm::Function>(fn);
-    assert(func);
-    assert(func->isIntrinsic());
-    fdecl->llvmValue = func;
-    return func;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Function* DtoDeclareFunction(FuncDeclaration* fdecl)
-{
-    if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
-        return DtoDeclareVaFunction(fdecl);
-    }
-
-    // mangled name
-    char* mangled_name;
-    if (fdecl->llvmInternal == LLVMintrinsic)
-        mangled_name = fdecl->llvmInternal1;
-    else
-        mangled_name = fdecl->mangle();
-
-    // unit test special handling
-    if (fdecl->isUnitTestDeclaration())
-    {
-        assert(0 && "no unittests yet");
-        /*const llvm::FunctionType* fnty = llvm::FunctionType::get(llvm::Type::VoidTy, std::vector<const llvm::Type*>(), false);
-        // make the function
-        llvm::Function* func = gIR->module->getFunction(mangled_name);
-        if (func == 0)
-            func = new llvm::Function(fnty,llvm::GlobalValue::InternalLinkage,mangled_name,gIR->module);
-        func->setCallingConv(llvm::CallingConv::Fast);
-        fdecl->llvmValue = func;
-        return func;
-        */
-    }
-
-    // regular function
-    TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
-    assert(f != 0);
-
-    if (fdecl->llvmValue != 0) {
-        if (!llvm::isa<llvm::Function>(fdecl->llvmValue))
-        {
-            Logger::cout() << *fdecl->llvmValue << '\n';
-            assert(0);
-        }
-        return llvm::cast<llvm::Function>(fdecl->llvmValue);
-    }
-
-    Logger::print("FuncDeclaration::toObjFile(%s): %s\n", fdecl->needThis()?"this":"static",fdecl->toChars());
-    LOG_SCOPE;
-
-    if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) {
-        error("intrinsics cannot have function bodies");
-        fatal();
-    }
-
-    // construct function
-    const llvm::FunctionType* functype = (f->llvmType == 0) ? DtoFunctionType(fdecl) : llvm::cast<llvm::FunctionType>(f->llvmType);
-
-    // make the function
-    llvm::Function* func = gIR->module->getFunction(mangled_name);
-    if (func == 0) {
-        func = new llvm::Function(functype,DtoLinkage(fdecl->protection, fdecl->storage_class),mangled_name,gIR->module);
-    }
-
-    if (fdecl->llvmInternal != LLVMintrinsic)
-        func->setCallingConv(DtoCallingConv(f->linkage));
-
-    fdecl->llvmValue = func;
-    f->llvmType = functype;
-    assert(llvm::isa<llvm::FunctionType>(f->llvmType));
-
-    if (fdecl->isMain()) {
-        gIR->mainFunc = func;
-    }
-
-    // name parameters
-    llvm::Function::arg_iterator iarg = func->arg_begin();
-    int k = 0;
-    if (f->llvmRetInPtr) {
-        iarg->setName("retval");
-        f->llvmRetArg = iarg;
-        ++iarg;
-    }
-    if (f->llvmUsesThis) {
-        iarg->setName("this");
-        ++iarg;
-    }
-    int varargs = -1;
-    if (f->linkage == LINKd && f->varargs == 1)
-        varargs = 0;
-    for (; iarg != func->arg_end(); ++iarg)
-    {
-        Argument* arg = Argument::getNth(f->parameters, k++);
-        //arg->llvmValue = iarg;
-        //printf("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident);
-        if (arg && arg->ident != 0) {
-            if (arg->vardecl) {
-                arg->vardecl->llvmValue = iarg;
-            }
-            iarg->setName(arg->ident->toChars());
-        }
-        else if (!arg && varargs >= 0) {
-            if (varargs == 0) {
-                iarg->setName("_arguments");
-                fdecl->llvmArguments = iarg;
-            }
-            else if (varargs == 1) {
-                iarg->setName("_argptr");
-                fdecl->llvmArgPtr = iarg;
-            }
-            else
-            assert(0);
-            varargs++;
-        }
-        else {
-            iarg->setName("unnamed");
-        }
-    }
-
-    return func;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty)
-{
-    /*size_t sz = gTargetData->getTypeSize(ty);
-    llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), sz, false);
-    if (ptr == 0) {
-        llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
-        ptr = llvm::ConstantPointerNull::get(i8pty);
-    }
-    return DtoRealloc(ptr, n);*/
-    return NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoRealloc(llvm::Value* ptr, llvm::Value* n)
-{
-    assert(ptr);
-    assert(n);
-
-    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_realloc");
-    assert(fn);
-
-    llvm::Value* newptr = ptr;
-
-    llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
-    if (ptr->getType() != i8pty) {
-        newptr = new llvm::BitCastInst(ptr,i8pty,"tmp",gIR->scopebb());
-    }
-
-    std::vector<llvm::Value*> args;
-    args.push_back(newptr);
-    args.push_back(n);
-    llvm::Value* ret = new llvm::CallInst(fn, args.begin(), args.end(), "tmprealloc", gIR->scopebb());
-
-    return ret->getType() == ptr->getType() ? ret : new llvm::BitCastInst(ret,ptr->getType(),"tmp",gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoAssert(llvm::Value* cond, llvm::Value* loc, llvm::Value* msg)
-{
-    assert(loc);
-    std::vector<llvm::Value*> llargs;
-    llargs.resize(3);
-    llargs[0] = cond ? DtoBoolean(cond) : llvm::ConstantInt::getFalse();
-    llargs[1] = loc;
-    llargs[2] = msg ? msg : llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
-
-    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_assert");
-    assert(fn);
-    llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-    call->setCallingConv(llvm::CallingConv::C);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp)
-{
-    llvm::Value* retval = 0;
-
-    bool haslvals = !gIR->exps.empty();
-    if (haslvals)
-        gIR->exps.push_back(IRExp(NULL,NULL,NULL));
-
-    elem* arg = argexp->toElem(gIR);
-
-    if (haslvals)
-        gIR->exps.pop_back();
-
-    if (arg->inplace) {
-        assert(arg->mem != 0);
-        retval = arg->mem;
-        delete arg;
-        return retval;
-    }
-
-    Type* realtype = DtoDType(argexp->type);
-    TY argty = realtype->ty;
-    if (DtoIsPassedByRef(realtype)) {
-        if (!fnarg || !fnarg->llvmCopy) {
-            retval = arg->getValue();
-            assert(retval != 0);
-        }
-        else {
-            llvm::Value* allocaInst = 0;
-            llvm::BasicBlock* entryblock = &gIR->topfunc()->front();
-            //const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(arg->mem->getType());
-            const llvm::Type* realtypell = DtoType(realtype);
-            const llvm::PointerType* pty = llvm::PointerType::get(realtypell);
-            if (argty == Tstruct) {
-                allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
-                DtoStructCopy(allocaInst,arg->mem);
-            }
-            else if (argty == Tdelegate) {
-                allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
-                DtoDelegateCopy(allocaInst,arg->mem);
-            }
-            else if (argty == Tarray) {
-                if (arg->type == elem::SLICE) {
-                    allocaInst = new llvm::AllocaInst(realtypell, "tmpparam", gIR->topallocapoint());
-                    DtoSetArray(allocaInst, arg->arg, arg->mem);
-                }
-                else if (arg->temp) {
-                    allocaInst = arg->mem;
-                }
-                else {
-                    allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
-                    DtoArrayAssign(allocaInst,arg->mem);
-                }
-            }
-            else
-            assert(0);
-
-            retval = allocaInst;
-        }
-    }
-    else if (!fnarg || fnarg->llvmCopy) {
-        Logger::println("regular arg");
-        assert(arg->type != elem::SLICE);
-        if (arg->mem) Logger::cout() << "mem = " << *arg->mem << '\n';
-        if (arg->val) Logger::cout() << "val = " << *arg->val << '\n';
-        if (arg->arg) Logger::cout() << "arg = " << *arg->arg << '\n';
-        retval = arg->arg ? arg->arg : arg->field ? arg->mem : arg->getValue();
-    }
-    else {
-        Logger::println("as ptr arg");
-        retval = arg->mem ? arg->mem : arg->val;
-        if (paramtype && retval->getType() != paramtype)
-        {
-            assert(retval->getType() == paramtype->getContainedType(0));
-            new llvm::StoreInst(retval, arg->mem, gIR->scopebb());
-            retval = arg->mem;
-        }
-    }
-
-    if (fnarg && paramtype && retval->getType() != paramtype) {
-        // this is unfortunately needed with the way SymOffExp is overused
-        // and static arrays can end up being a pointer to their element type
-        if (arg->field) {
-            retval = gIR->ir->CreateBitCast(retval, paramtype, "tmp");
-        }
-        else {
-            Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n";
-            assert(0 && "parameter type that was actually passed is invalid");
-        }
-    }
-
-    delete arg;
-
-    return retval;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoNestedVariable(VarDeclaration* vd)
-{
-    FuncDeclaration* fd = vd->toParent()->isFuncDeclaration();
-    assert(fd != NULL);
-
-    IRFunction* fcur = &gIR->func();
-    FuncDeclaration* f = fcur->decl;
-
-    // on this stack
-    if (fd == f) {
-        llvm::Value* v = DtoGEPi(vd->llvmValue,0,unsigned(vd->llvmNestedIndex),"tmp");
-        if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) {
-            Logger::cout() << "1267 loading: " << *v << '\n';
-            v = gIR->ir->CreateLoad(v,"tmp");
-        }
-        return v;
-    }
-
-    // on a caller stack
-    llvm::Value* ptr = f->llvmThisVar;
-    assert(ptr);
-
-    f = f->toParent()->isFuncDeclaration();
-    assert(f);
-    assert(f->llvmNested);
-    const llvm::Type* nesttype = f->llvmNested->getType();
-    assert(nesttype);
-
-    ptr = gIR->ir->CreateBitCast(ptr, nesttype, "tmp");
-
-    Logger::cout() << "nested var reference:" << '\n' << *ptr << *nesttype << '\n';
-
-    while (f) {
-        if (fd == f) {
-            llvm::Value* v = DtoGEPi(ptr,0,vd->llvmNestedIndex,"tmp");
-            if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) {
-                Logger::cout() << "1291 loading: " << *v << '\n';
-                v = gIR->ir->CreateLoad(v,"tmp");
-            }
-            return v;
-        }
-        else {
-            ptr = DtoGEPi(ptr,0,0,"tmp");
-            ptr = gIR->ir->CreateLoad(ptr,"tmp");
-        }
-        f = f->toParent()->isFuncDeclaration();
-    }
-
-    assert(0 && "nested var not found");
-    return NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoAssign(Type* t, llvm::Value* lhs, llvm::Value* rhs)
-{
-    Logger::cout() << "assignment:" << '\n' << *lhs << *rhs << '\n';
-
-    if (t->ty == Tstruct) {
-        assert(lhs->getType() == rhs->getType());
-        DtoStructCopy(lhs,rhs);
-    }
-    else if (t->ty == Tarray) {
-        assert(lhs->getType() == rhs->getType());
-        DtoArrayAssign(lhs,rhs);
-    }
-    else if (t->ty == Tsarray) {
-        assert(lhs->getType() == rhs->getType());
-        DtoStaticArrayCopy(lhs,rhs);
-    }
-    else if (t->ty == Tdelegate) {
-        assert(lhs->getType() == rhs->getType());
-        DtoDelegateCopy(lhs,rhs);
-    }
-    else {
-        assert(lhs->getType()->getContainedType(0) == rhs->getType());
-        gIR->ir->CreateStore(rhs, lhs);
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::ConstantInt* DtoConstSize_t(size_t i)
-{
-    return llvm::ConstantInt::get(DtoSize_t(), i, false);
-}
-llvm::ConstantInt* DtoConstUint(unsigned i)
-{
-    return llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false);
-}
-llvm::ConstantInt* DtoConstInt(int i)
-{
-    return llvm::ConstantInt::get(llvm::Type::Int32Ty, i, true);
-}
-llvm::Constant* DtoConstBool(bool b)
-{
-    return llvm::ConstantInt::get(llvm::Type::Int1Ty, b, false);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Constant* DtoConstString(const char* str)
-{
-    std::string s(str);
-    llvm::Constant* init = llvm::ConstantArray::get(s, true);
-    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(
-        init->getType(), true,llvm::GlobalValue::InternalLinkage, init, "stringliteral", gIR->module);
-    llvm::Constant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
-    return DtoConstSlice(
-        DtoConstSize_t(s.length()),
-        llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2)
-    );
-}
-llvm::Constant* DtoConstStringPtr(const char* str, const char* section)
-{
-    std::string s(str);
-    llvm::Constant* init = llvm::ConstantArray::get(s, true);
-    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(
-        init->getType(), true,llvm::GlobalValue::InternalLinkage, init, "stringliteral", gIR->module);
-    if (section) gvar->setSection(section);
-    llvm::Constant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
-    return llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes)
-{
-    assert(dst->getType() == src->getType());
-
-    llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
-    llvm::Value *dstarr, *srcarr;
-    if (dst->getType() == arrty)
-    {
-        dstarr = dst;
-        srcarr = src;
-    }
-    else
-    {
-        dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
-        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] = nbytes;
-    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-    new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs)
-{
-    Logger::println("checking for offset %u type %s:", os, t->toChars());
-    LOG_SCOPE;
-
-    if (idxs.empty())
-        idxs.push_back(0);
-
-    const llvm::Type* llt = llvm::PointerType::get(DtoType(t));
-
-    for (unsigned i=0; i<sd->fields.dim; ++i) {
-        VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i];
-        Type* vdtype = DtoDType(vd->type);
-        Logger::println("found %u type %s", vd->offset, vdtype->toChars());
-        assert(vd->llvmFieldIndex >= 0);
-        if (os == vd->offset && vdtype == t) {
-            idxs.push_back(vd->llvmFieldIndex);
-            ptr = DtoGEP(ptr, idxs, "tmp");
-            if (ptr->getType() != llt)
-                ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
-            if (vd->llvmFieldIndexOffset)
-                ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
-            return ptr;
-        }
-        else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
-            TypeStruct* ts = (TypeStruct*)vdtype;
-            StructDeclaration* ssd = ts->sym;
-            idxs.push_back(vd->llvmFieldIndex);
-            if (vd->llvmFieldIndexOffset) {
-                Logger::println("has union field offset");
-                ptr = DtoGEP(ptr, idxs, "tmp");
-                if (ptr->getType() != llt)
-                    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
-                ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
-                std::vector<unsigned> tmp;
-                return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
-            }
-            else {
-                const llvm::Type* sty = llvm::PointerType::get(DtoType(vd->type));
-                if (ptr->getType() != sty) {
-                    ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
-                    std::vector<unsigned> tmp;
-                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
-                }
-                else {
-                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs);
-                }
-            }
-        }
-    }
-
-    size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
-    assert(os % llt_sz == 0);
-    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
-    return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-bool DtoIsTemplateInstance(Dsymbol* s)
-{
-    assert(s);
-    if (s->isTemplateInstance() && !s->isTemplateMixin())
-        return true;
-    else if (s->parent)
-        return DtoIsTemplateInstance(s->parent);
-    return false;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/tollvm.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,1565 @@
+#include <iostream>
+
+#include "gen/llvm.h"
+
+#include "mtype.h"
+#include "dsymbol.h"
+#include "aggregate.h"
+#include "declaration.h"
+#include "init.h"
+
+#include "gen/tollvm.h"
+#include "gen/irstate.h"
+#include "gen/logger.h"
+#include "gen/runtime.h"
+#include "gen/arrays.h"
+#include "gen/dvalue.h"
+
+bool DtoIsPassedByRef(Type* type)
+{
+    TY t = DtoDType(type)->ty;
+    return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray);
+}
+
+Type* DtoDType(Type* t)
+{
+    if (t->ty == Ttypedef) {
+        Type* bt = t->toBasetype();
+        assert(bt);
+        return DtoDType(bt);
+    }
+    return t;
+}
+
+const llvm::Type* DtoType(Type* t)
+{
+    assert(t);
+    switch (t->ty)
+    {
+    // integers
+    case Tint8:
+    case Tuns8:
+    case Tchar:
+        return (const llvm::Type*)llvm::Type::Int8Ty;
+    case Tint16:
+    case Tuns16:
+    case Twchar:
+        return (const llvm::Type*)llvm::Type::Int16Ty;
+    case Tint32:
+    case Tuns32:
+    case Tdchar:
+        return (const llvm::Type*)llvm::Type::Int32Ty;
+    case Tint64:
+    case Tuns64:
+        return (const llvm::Type*)llvm::Type::Int64Ty;
+
+    case Tbool:
+        return (const llvm::Type*)llvm::ConstantInt::getTrue()->getType();
+
+    // floats
+    case Tfloat32:
+    case Timaginary32:
+        return llvm::Type::FloatTy;
+    case Tfloat64:
+    case Timaginary64:
+    case Tfloat80:
+    case Timaginary80:
+        return llvm::Type::DoubleTy;
+
+    // complex
+    case Tcomplex32:
+    case Tcomplex64:
+    case Tcomplex80:
+        assert(0 && "complex number types not yet implemented");
+
+    // pointers
+    case Tpointer: {
+        assert(t->next);
+        if (t->next->ty == Tvoid)
+            return (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty);
+        else
+            return (const llvm::Type*)llvm::PointerType::get(DtoType(t->next));
+    }
+
+    // arrays
+    case Tarray:
+        return DtoArrayType(t);
+    case Tsarray:
+        return DtoStaticArrayType(t);
+
+    // void
+    case Tvoid:
+        return llvm::Type::VoidTy;
+
+    // aggregates
+    case Tstruct:    {
+        if (t->llvmType == 0)
+        {
+            // recursive or cyclic declaration
+            if (!gIR->structs.empty())
+            {
+                IRStruct* found = 0;
+                for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i)
+                {
+                    if (t == i->type)
+                    {
+                        return i->recty.get();
+                    }
+                }
+            }
+
+            // forward declaration
+            TypeStruct* ts = (TypeStruct*)t;
+            assert(ts->sym);
+            ts->sym->toObjFile();
+        }
+        return t->llvmType;
+    }
+
+    case Tclass:    {
+        if (t->llvmType == 0)
+        {
+            // recursive or cyclic declaration
+            if (!gIR->structs.empty())
+            {
+                IRStruct* found = 0;
+                for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i)
+                {
+                    if (t == i->type)
+                    {
+                        return llvm::PointerType::get(i->recty.get());
+                    }
+                }
+            }
+
+            // forward declaration
+            TypeClass* tc = (TypeClass*)t;
+            assert(tc->sym);
+            tc->sym->toObjFile();
+        }
+        return llvm::PointerType::get(t->llvmType);
+    }
+
+    // functions
+    case Tfunction:
+    {
+        if (t->llvmType == 0) {
+            return DtoFunctionType(t,NULL);
+        }
+        else {
+            return t->llvmType;
+        }
+    }
+
+    // delegates
+    case Tdelegate:
+    {
+        if (t->llvmType == 0) {
+            return DtoDelegateType(t);
+        }
+        else {
+            return t->llvmType;
+        }
+    }
+
+    // typedefs
+    // enum
+    case Ttypedef:
+    case Tenum:
+    {
+        Type* bt = t->toBasetype();
+        assert(bt);
+        return DtoType(bt);
+    }
+
+    default:
+        printf("trying to convert unknown type with value %d\n", t->ty);
+        assert(0);
+    }
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype, bool ismain)
+{
+    TypeFunction* f = (TypeFunction*)type;
+    assert(f != 0);
+
+    bool typesafeVararg = false;
+    if (f->linkage == LINKd && f->varargs == 1) {
+        typesafeVararg = true;
+    }
+
+    // return value type
+    const llvm::Type* rettype;
+    const llvm::Type* actualRettype;
+    Type* rt = f->next;
+    bool retinptr = false;
+    bool usesthis = false;
+
+    if (ismain) {
+        rettype = llvm::Type::Int32Ty;
+        actualRettype = rettype;
+    }
+    else {
+        assert(rt);
+        if (DtoIsPassedByRef(rt)) {
+            rettype = llvm::PointerType::get(DtoType(rt));
+            actualRettype = llvm::Type::VoidTy;
+            f->llvmRetInPtr = retinptr = true;
+        }
+        else {
+            rettype = DtoType(rt);
+            actualRettype = rettype;
+        }
+    }
+
+    // parameter types
+    std::vector<const llvm::Type*> paramvec;
+
+    if (retinptr) {
+        Logger::cout() << "returning through pointer parameter: " << *rettype << '\n';
+        paramvec.push_back(rettype);
+    }
+
+    if (thistype) {
+        paramvec.push_back(thistype);
+        usesthis = true;
+    }
+
+    if (typesafeVararg) {
+        ClassDeclaration* ti = Type::typeinfo;
+        if (!ti->llvmInitZ)
+            ti->toObjFile();
+        assert(ti->llvmInitZ);
+        std::vector<const llvm::Type*> types;
+        types.push_back(DtoSize_t());
+        types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmInitZ->getType())));
+        const llvm::Type* t1 = llvm::StructType::get(types);
+        paramvec.push_back(llvm::PointerType::get(t1));
+        paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
+    }
+
+    size_t n = Argument::dim(f->parameters);
+
+    for (int i=0; i < n; ++i) {
+        Argument* arg = Argument::getNth(f->parameters, i);
+        // ensure scalar
+        Type* argT = DtoDType(arg->type);
+        assert(argT);
+
+        if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
+            //assert(arg->vardecl);
+            //arg->vardecl->refparam = true;
+        }
+        else
+            arg->llvmCopy = true;
+
+        const llvm::Type* at = DtoType(argT);
+        if (llvm::isa<llvm::StructType>(at)) {
+            Logger::println("struct param");
+            paramvec.push_back(llvm::PointerType::get(at));
+        }
+        else if (llvm::isa<llvm::ArrayType>(at)) {
+            Logger::println("sarray param");
+            assert(argT->ty == Tsarray);
+            //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0)));
+            paramvec.push_back(llvm::PointerType::get(at));
+        }
+        else if (llvm::isa<llvm::OpaqueType>(at)) {
+            Logger::println("opaque param");
+            if (argT->ty == Tstruct || argT->ty == Tclass)
+                paramvec.push_back(llvm::PointerType::get(at));
+            else
+            assert(0);
+        }
+        /*if (llvm::isa<llvm::StructType>(at) || argT->ty == Tstruct || argT->ty == Tsarray) {
+            paramvec.push_back(llvm::PointerType::get(at));
+        }*/
+        else {
+            if (!arg->llvmCopy) {
+                Logger::println("ref param");
+                at = llvm::PointerType::get(at);
+            }
+            else {
+                Logger::println("in param");
+            }
+            paramvec.push_back(at);
+        }
+    }
+
+    // construct function type
+    bool isvararg = !typesafeVararg && f->varargs;
+    llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
+
+    f->llvmRetInPtr = retinptr;
+    f->llvmUsesThis = usesthis;
+    return functype;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
+{
+    TypeFunction* f = (TypeFunction*)fdecl->type;
+    assert(f != 0);
+
+    const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    std::vector<const llvm::Type*> args;
+
+    if (fdecl->llvmInternal == LLVMva_start) {
+        args.push_back(i8pty);
+    }
+    else if (fdecl->llvmInternal == LLVMva_intrinsic) {
+        size_t n = Argument::dim(f->parameters);
+        for (size_t i=0; i<n; ++i) {
+            args.push_back(i8pty);
+        }
+    }
+    else
+    assert(0);
+
+    const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
+    f->llvmType = fty;
+    return fty;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
+{
+    if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
+        return DtoVaFunctionType(fdecl);
+    }
+
+    // type has already been resolved
+    if (fdecl->type->llvmType != 0) {
+        return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType);
+    }
+
+    const llvm::Type* thisty = NULL;
+    if (fdecl->needThis()) {
+        if (AggregateDeclaration* ad = fdecl->isMember()) {
+            Logger::print("isMember = this is: %s\n", ad->type->toChars());
+            thisty = DtoType(ad->type);
+            Logger::cout() << "this llvm type: " << *thisty << '\n';
+            if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get())
+                thisty = llvm::PointerType::get(thisty);
+        }
+        else
+        assert(0);
+    }
+    else if (fdecl->isNested()) {
+        thisty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    }
+
+    const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain());
+    fdecl->type->llvmType = functype;
+    return functype;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+const llvm::StructType* DtoDelegateType(Type* t)
+{
+    const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::Type* func = DtoFunctionType(t->next, i8ptr);
+    const llvm::Type* funcptr = llvm::PointerType::get(func);
+
+    std::vector<const llvm::Type*> types;
+    types.push_back(i8ptr);
+    types.push_back(funcptr);
+    return llvm::StructType::get(types);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+const llvm::Type* DtoStructType(Type* t)
+{
+    assert(0);
+    std::vector<const llvm::Type*> types;
+    return llvm::StructType::get(types);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+static llvm::Function* LLVM_DeclareMemIntrinsic(const char* name, int bits, bool set=false)
+{
+    assert(bits == 32 || bits == 64);
+    const llvm::Type* int8ty =    (const llvm::Type*)llvm::Type::Int8Ty;
+    const llvm::Type* int32ty =   (const llvm::Type*)llvm::Type::Int32Ty;
+    const llvm::Type* int64ty =   (const llvm::Type*)llvm::Type::Int64Ty;
+    const llvm::Type* int8ptrty = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::Type* voidty =    (const llvm::Type*)llvm::Type::VoidTy;
+
+    assert(gIR);
+    assert(gIR->module);
+
+    // parameter types
+    std::vector<const llvm::Type*> pvec;
+    pvec.push_back(int8ptrty);
+    pvec.push_back(set?int8ty:int8ptrty);
+    pvec.push_back(bits==32?int32ty:int64ty);
+    pvec.push_back(int32ty);
+    llvm::FunctionType* functype = llvm::FunctionType::get(voidty, pvec, false);
+    return new llvm::Function(functype, llvm::GlobalValue::ExternalLinkage, name, gIR->module);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// llvm.memset.i32
+llvm::Function* LLVM_DeclareMemSet32()
+{
+    static llvm::Function* _func = 0;
+    if (_func == 0) {
+        _func = LLVM_DeclareMemIntrinsic("llvm.memset.i32", 32, true);
+    }
+    return _func;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Function* LLVM_DeclareMemSet64()
+{
+    static llvm::Function* _func = 0;
+    if (_func == 0) {
+        _func = LLVM_DeclareMemIntrinsic("llvm.memset.i64", 64, true);
+    }
+    return _func;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// llvm.memcpy.i32
+llvm::Function* LLVM_DeclareMemCpy32()
+{
+    static llvm::Function* _func = 0;
+    if (_func == 0) {
+        _func = LLVM_DeclareMemIntrinsic("llvm.memcpy.i32", 32);
+    }
+    return _func;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// llvm.memcpy.i64
+llvm::Function* LLVM_DeclareMemCpy64()
+{
+    static llvm::Function* _func = 0;
+    if (_func == 0) {
+        _func = LLVM_DeclareMemIntrinsic("llvm.memcpy.i64", 64);
+    }
+    return _func;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoStructZeroInit(llvm::Value* v)
+{
+    assert(gIR);
+    uint64_t n = gTargetData->getTypeSize(v->getType()->getContainedType(0));
+    //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n));
+    llvm::Type* sarrty = llvm::PointerType::get(llvm::Type::Int8Ty);
+
+    llvm::Value* sarr = new llvm::BitCastInst(v,sarrty,"tmp",gIR->scopebb());
+
+    llvm::Function* fn = LLVM_DeclareMemSet32();
+    std::vector<llvm::Value*> llargs;
+    llargs.resize(4);
+    llargs[0] = sarr;
+    llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false);
+    llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
+    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+
+    llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+
+    return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoStructCopy(llvm::Value* dst, llvm::Value* src)
+{
+    Logger::cout() << "dst = " << *dst << " src = " << *src << '\n';
+    assert(dst->getType() == src->getType());
+    assert(gIR);
+
+    uint64_t n = gTargetData->getTypeSize(dst->getType()->getContainedType(0));
+    //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n));
+    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 = LLVM_DeclareMemCpy32();
+    std::vector<llvm::Value*> llargs;
+    llargs.resize(4);
+    llargs[0] = dstarr;
+    llargs[1] = srcarr;
+    llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
+    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+
+    return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Constant* DtoConstStructInitializer(StructInitializer* si)
+{
+    llvm::StructType* structtype = llvm::cast<llvm::StructType>(si->ad->llvmType);
+    size_t n = structtype->getNumElements();
+
+    assert(si->value.dim == si->vars.dim);
+
+    std::vector<llvm::Constant*> inits;
+    inits.resize(n, NULL);
+    for (int i = 0; i < si->value.dim; ++i)
+    {
+        Initializer* ini = (Initializer*)si->value.data[i];
+        assert(ini);
+
+        VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
+        Type* vdtype = DtoDType(vd->type);
+        assert(vd);
+        Logger::println("vars[%d] = %s", i, vd->toChars());
+
+        llvm::Constant* v = 0;
+
+        assert(vd->llvmFieldIndex >= 0);
+        unsigned idx = vd->llvmFieldIndex;
+
+        if (ExpInitializer* ex = ini->isExpInitializer())
+        {
+            v = ex->exp->toConstElem(gIR);
+        }
+        else if (StructInitializer* si = ini->isStructInitializer())
+        {
+            v = DtoConstStructInitializer(si);
+        }
+        else if (ArrayInitializer* ai = ini->isArrayInitializer())
+        {
+            v = DtoConstArrayInitializer(ai);
+        }
+        else if (ini->isVoidInitializer())
+        {
+            v = llvm::UndefValue::get(structtype->getElementType(idx));
+        }
+        else
+        assert(v);
+
+        inits[idx] = v;
+        Logger::cout() << "init[" << idx << "] = " << *v << '\n';
+    }
+
+    // fill out nulls
+    assert(si->ad->llvmInitZ);
+    if (si->ad->llvmInitZ->isNullValue())
+    {
+        for (int i = 0; i < n; ++i)
+        {
+            if (inits[i] == 0)
+            {
+                inits[i] = llvm::Constant::getNullValue(structtype->getElementType(i));
+            }
+        }
+    }
+    else
+    {
+        for (int i = 0; i < n; ++i)
+        {
+            if (inits[i] == 0)
+            {
+                inits[i] = si->ad->llvmInitZ->getOperand(i);
+            }
+        }
+    }
+
+    return llvm::ConstantStruct::get(structtype, inits);
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoNullDelegate(llvm::Value* v)
+{
+    assert(gIR);
+    d_uns64 n = (global.params.is64bit) ? 16 : 8;
+
+    llvm::Type* i8p_ty = llvm::PointerType::get(llvm::Type::Int8Ty);
+
+    llvm::Value* arr = new llvm::BitCastInst(v,i8p_ty,"tmp",gIR->scopebb());
+
+    llvm::Function* fn = LLVM_DeclareMemSet32();
+    std::vector<llvm::Value*> llargs;
+    llargs.resize(4);
+    llargs[0] = arr;
+    llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false);
+    llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
+    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+
+    llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+
+    return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoDelegateCopy(llvm::Value* dst, llvm::Value* src)
+{
+    assert(dst->getType() == src->getType());
+    assert(gIR);
+
+    d_uns64 n = (global.params.is64bit) ? 16 : 8;
+
+    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 = LLVM_DeclareMemCpy32();
+    std::vector<llvm::Value*> llargs;
+    llargs.resize(4);
+    llargs[0] = dstarr;
+    llargs[1] = srcarr;
+    llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
+    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+
+    return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoCompareDelegate(TOK op, llvm::Value* lhs, llvm::Value* rhs)
+{
+    llvm::ICmpInst::Predicate pred = (op == TOKequal) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
+    llvm::Value* l = gIR->ir->CreateLoad(DtoGEPi(lhs,0,0,"tmp"),"tmp");
+    llvm::Value* r = gIR->ir->CreateLoad(DtoGEPi(rhs,0,0,"tmp"),"tmp");
+    llvm::Value* b1 = gIR->ir->CreateICmp(pred,l,r,"tmp");
+    l = gIR->ir->CreateLoad(DtoGEPi(lhs,0,1,"tmp"),"tmp");
+    r = gIR->ir->CreateLoad(DtoGEPi(rhs,0,1,"tmp"),"tmp");
+    llvm::Value* b2 = gIR->ir->CreateICmp(pred,l,r,"tmp");
+    llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
+    if (op == TOKnotequal)
+        return gIR->ir->CreateNot(b,"tmp");
+    return b;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::GlobalValue::LinkageTypes DtoLinkage(PROT prot, uint stc)
+{
+    switch(prot)
+    {
+    case PROTprivate:
+        return llvm::GlobalValue::InternalLinkage;
+
+    case PROTpublic:
+    case PROTpackage:
+    case PROTprotected:
+    case PROTexport:
+        return llvm::GlobalValue::ExternalLinkage;
+
+    case PROTundefined:
+    case PROTnone:
+        assert(0 && "Unsupported linkage type");
+    }
+    return llvm::GlobalValue::ExternalLinkage;
+
+/*      ExternalLinkage = 0, LinkOnceLinkage, WeakLinkage, AppendingLinkage,
+  InternalLinkage, DLLImportLinkage, DLLExportLinkage, ExternalWeakLinkage,
+  GhostLinkage */
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+unsigned DtoCallingConv(LINK l)
+{
+    if (l == LINKc)
+        return llvm::CallingConv::C;
+    else if (l == LINKd || l == LINKdefault)
+        return llvm::CallingConv::Fast;
+    else if (l == LINKwindows)
+        return llvm::CallingConv::X86_StdCall;
+    else
+        assert(0 && "Unsupported calling convention");
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoPointedType(llvm::Value* ptr, llvm::Value* val)
+{
+    const llvm::Type* ptrTy = ptr->getType()->getContainedType(0);
+    const llvm::Type* valTy = val->getType();
+    // ptr points to val's type
+    if (ptrTy == valTy)
+    {
+        return val;
+    }
+    // ptr is integer pointer
+    else if (ptrTy->isInteger())
+    {
+        // val is integer
+        assert(valTy->isInteger());
+        const llvm::IntegerType* pt = llvm::cast<const llvm::IntegerType>(ptrTy);
+        const llvm::IntegerType* vt = llvm::cast<const llvm::IntegerType>(valTy);
+        if (pt->getBitWidth() < vt->getBitWidth()) {
+            return new llvm::TruncInst(val, pt, "tmp", gIR->scopebb());
+        }
+        else
+        assert(0);
+    }
+    // something else unsupported
+    else
+    {
+        Logger::cout() << *ptrTy << '|' << *valTy << '\n';
+        assert(0);
+    }
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoBoolean(llvm::Value* val)
+{
+    const llvm::Type* t = val->getType();
+    if (t->isInteger())
+    {
+        if (t == llvm::Type::Int1Ty)
+            return val;
+        else {
+            llvm::Value* zero = llvm::ConstantInt::get(t, 0, false);
+            return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, val, zero, "tmp", gIR->scopebb());
+        }
+    }
+    else if (llvm::isa<llvm::PointerType>(t)) {
+        const llvm::Type* st = DtoSize_t();
+        llvm::Value* ptrasint = new llvm::PtrToIntInst(val,st,"tmp",gIR->scopebb());
+        llvm::Value* zero = llvm::ConstantInt::get(st, 0, false);
+        return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, ptrasint, zero, "tmp", gIR->scopebb());
+    }
+    else
+    {
+        Logger::cout() << *t << '\n';
+    }
+    assert(0);
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+const llvm::Type* DtoSize_t()
+{
+    if (global.params.is64bit)
+    return llvm::Type::Int64Ty;
+    else
+    return llvm::Type::Int32Ty;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoMain()
+{
+    // emit main function llvm style
+    // int main(int argc, char**argv, char**env);
+
+    assert(gIR != 0);
+    IRState& ir = *gIR;
+
+    assert(ir.emitMain && ir.mainFunc);
+
+    // parameter types
+    std::vector<const llvm::Type*> pvec;
+    pvec.push_back((const llvm::Type*)llvm::Type::Int32Ty);
+    const llvm::Type* chPtrType = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty);
+    pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType));
+    pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType));
+    const llvm::Type* rettype = (const llvm::Type*)llvm::Type::Int32Ty;
+
+    llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false);
+    llvm::Function* func = new llvm::Function(functype,llvm::GlobalValue::ExternalLinkage,"main",ir.module);
+
+    llvm::BasicBlock* bb = new llvm::BasicBlock("entry",func);
+
+    // call static ctors
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_ctors");
+    new llvm::CallInst(fn,"",bb);
+
+    // call user main function
+    llvm::CallInst* call = new llvm::CallInst(ir.mainFunc,"ret",bb);
+    call->setCallingConv(ir.mainFunc->getCallingConv());
+
+    // call static dtors
+    fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_dtors");
+    new llvm::CallInst(fn,"",bb);
+
+    // return
+    new llvm::ReturnInst(call,bb);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance)
+{
+    Array* arr = &tc->sym->dtors;
+    for (size_t i=0; i<arr->dim; i++)
+    {
+        FuncDeclaration* fd = (FuncDeclaration*)arr->data[i];
+        assert(fd->llvmValue);
+        new llvm::CallInst(fd->llvmValue, instance, "", gIR->scopebb());
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoInitClass(TypeClass* tc, llvm::Value* dst)
+{
+    assert(gIR);
+
+    assert(tc->llvmType);
+    uint64_t size_t_size = gTargetData->getTypeSize(DtoSize_t());
+    uint64_t n = gTargetData->getTypeSize(tc->llvmType) - size_t_size;
+
+    // set vtable field
+    llvm::Value* vtblvar = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
+    assert(tc->sym->llvmVtbl);
+    new llvm::StoreInst(tc->sym->llvmVtbl, vtblvar, gIR->scopebb());
+
+    // copy the static initializer
+    if (n > 0) {
+        assert(tc->llvmInit);
+        assert(dst->getType() == tc->llvmInit->getType());
+
+        llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
+
+        llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
+        dstarr = DtoGEPi(dstarr,size_t_size,"tmp",gIR->scopebb());
+
+        llvm::Value* srcarr = new llvm::BitCastInst(tc->llvmInit,arrty,"tmp",gIR->scopebb());
+        srcarr = DtoGEPi(srcarr,size_t_size,"tmp",gIR->scopebb());
+
+        llvm::Function* fn = LLVM_DeclareMemCpy32();
+        std::vector<llvm::Value*> llargs;
+        llargs.resize(4);
+        llargs[0] = dstarr;
+        llargs[1] = srcarr;
+        llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
+        llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+
+        new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* DtoConstInitializer(Type* type, Initializer* init)
+{
+    llvm::Constant* _init = 0; // may return zero
+    if (!init)
+    {
+        Logger::println("const default initializer for %s", type->toChars());
+        _init = type->defaultInit()->toConstElem(gIR);
+    }
+    else if (ExpInitializer* ex = init->isExpInitializer())
+    {
+        Logger::println("const expression initializer");
+        _init = ex->exp->toConstElem(gIR);
+    }
+    else if (StructInitializer* si = init->isStructInitializer())
+    {
+        Logger::println("const struct initializer");
+        _init = DtoConstStructInitializer(si);
+    }
+    else if (ArrayInitializer* ai = init->isArrayInitializer())
+    {
+        Logger::println("const array initializer");
+        _init = DtoConstArrayInitializer(ai);
+    }
+    else if (init->isVoidInitializer())
+    {
+        Logger::println("const void initializer");
+        const llvm::Type* ty = DtoType(type);
+        _init = llvm::Constant::getNullValue(ty);
+    }
+    else {
+        Logger::println("unsupported const initializer: %s", init->toChars());
+    }
+    return _init;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DtoInitializer(Initializer* init)
+{
+    if (ExpInitializer* ex = init->isExpInitializer())
+    {
+        Logger::println("expression initializer");
+        return ex->exp->toElem(gIR);
+    }
+    else if (init->isVoidInitializer())
+    {
+        // do nothing
+    }
+    else {
+        Logger::println("unsupported initializer: %s", init->toChars());
+        assert(0);
+    }
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb)
+{
+    std::vector<llvm::Value*> v(2);
+    v[0] = i0;
+    v[1] = i1;
+    Logger::cout() << "DtoGEP: " << *ptr << '\n';
+    return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoGEP(llvm::Value* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb)
+{
+    size_t n = src.size();
+    std::vector<llvm::Value*> dst(n);
+    std::ostream& ostr = Logger::cout();
+    ostr << "indices for '" << *ptr << "':";
+    for (size_t i=0; i<n; ++i)
+    {
+        ostr << ' ' << i;
+        dst[i] = llvm::ConstantInt::get(llvm::Type::Int32Ty, src[i], false);
+    }
+    ostr << '\n';
+    return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb?bb:gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoGEPi(llvm::Value* ptr, unsigned i, const std::string& var, llvm::BasicBlock* bb)
+{
+    return new llvm::GetElementPtrInst(ptr, llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false), var, bb?bb:gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoGEPi(llvm::Value* ptr, unsigned i0, unsigned i1, const std::string& var, llvm::BasicBlock* bb)
+{
+    std::vector<llvm::Value*> v(2);
+    v[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i0, false);
+    v[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i1, false);
+    return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl)
+{
+    TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
+    const llvm::FunctionType* fty = DtoVaFunctionType(fdecl);
+    llvm::Constant* fn = 0;
+
+    if (fdecl->llvmInternal == LLVMva_start) {
+        fn = gIR->module->getOrInsertFunction("llvm.va_start", fty);
+        assert(fn);
+    }
+    else if (fdecl->llvmInternal == LLVMva_intrinsic) {
+        fn = gIR->module->getOrInsertFunction(fdecl->llvmInternal1, fty);
+        assert(fn);
+    }
+    else
+    assert(0);
+
+    llvm::Function* func = llvm::cast_or_null<llvm::Function>(fn);
+    assert(func);
+    assert(func->isIntrinsic());
+    fdecl->llvmValue = func;
+    return func;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Function* DtoDeclareFunction(FuncDeclaration* fdecl)
+{
+    if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
+        return DtoDeclareVaFunction(fdecl);
+    }
+
+    // mangled name
+    char* mangled_name;
+    if (fdecl->llvmInternal == LLVMintrinsic)
+        mangled_name = fdecl->llvmInternal1;
+    else
+        mangled_name = fdecl->mangle();
+
+    // unit test special handling
+    if (fdecl->isUnitTestDeclaration())
+    {
+        assert(0 && "no unittests yet");
+        /*const llvm::FunctionType* fnty = llvm::FunctionType::get(llvm::Type::VoidTy, std::vector<const llvm::Type*>(), false);
+        // make the function
+        llvm::Function* func = gIR->module->getFunction(mangled_name);
+        if (func == 0)
+            func = new llvm::Function(fnty,llvm::GlobalValue::InternalLinkage,mangled_name,gIR->module);
+        func->setCallingConv(llvm::CallingConv::Fast);
+        fdecl->llvmValue = func;
+        return func;
+        */
+    }
+
+    // regular function
+    TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
+    assert(f != 0);
+
+    if (fdecl->llvmValue != 0) {
+        if (!llvm::isa<llvm::Function>(fdecl->llvmValue))
+        {
+            Logger::cout() << *fdecl->llvmValue << '\n';
+            assert(0);
+        }
+        return llvm::cast<llvm::Function>(fdecl->llvmValue);
+    }
+
+    Logger::print("FuncDeclaration::toObjFile(%s): %s\n", fdecl->needThis()?"this":"static",fdecl->toChars());
+    LOG_SCOPE;
+
+    if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) {
+        error("intrinsics cannot have function bodies");
+        fatal();
+    }
+
+    // construct function
+    const llvm::FunctionType* functype = (f->llvmType == 0) ? DtoFunctionType(fdecl) : llvm::cast<llvm::FunctionType>(f->llvmType);
+
+    // make the function
+    llvm::Function* func = gIR->module->getFunction(mangled_name);
+    if (func == 0) {
+        func = new llvm::Function(functype,DtoLinkage(fdecl->protection, fdecl->storage_class),mangled_name,gIR->module);
+    }
+
+    if (fdecl->llvmInternal != LLVMintrinsic)
+        func->setCallingConv(DtoCallingConv(f->linkage));
+
+    fdecl->llvmValue = func;
+    f->llvmType = functype;
+    assert(llvm::isa<llvm::FunctionType>(f->llvmType));
+
+    if (fdecl->isMain()) {
+        gIR->mainFunc = func;
+    }
+
+    // name parameters
+    llvm::Function::arg_iterator iarg = func->arg_begin();
+    int k = 0;
+    if (f->llvmRetInPtr) {
+        iarg->setName("retval");
+        f->llvmRetArg = iarg;
+        ++iarg;
+    }
+    if (f->llvmUsesThis) {
+        iarg->setName("this");
+        ++iarg;
+    }
+    int varargs = -1;
+    if (f->linkage == LINKd && f->varargs == 1)
+        varargs = 0;
+    for (; iarg != func->arg_end(); ++iarg)
+    {
+        Argument* arg = Argument::getNth(f->parameters, k++);
+        //arg->llvmValue = iarg;
+        //Logger::println("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident);
+        if (arg && arg->ident != 0) {
+            if (arg->vardecl) {
+                arg->vardecl->llvmValue = iarg;
+            }
+            iarg->setName(arg->ident->toChars());
+        }
+        else if (!arg && varargs >= 0) {
+            if (varargs == 0) {
+                iarg->setName("_arguments");
+                fdecl->llvmArguments = iarg;
+            }
+            else if (varargs == 1) {
+                iarg->setName("_argptr");
+                fdecl->llvmArgPtr = iarg;
+            }
+            else
+            assert(0);
+            varargs++;
+        }
+        else {
+            iarg->setName("unnamed");
+        }
+    }
+
+    Logger::cout() << "func decl: " << *func << '\n';
+
+    return func;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty)
+{
+    /*size_t sz = gTargetData->getTypeSize(ty);
+    llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), sz, false);
+    if (ptr == 0) {
+        llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
+        ptr = llvm::ConstantPointerNull::get(i8pty);
+    }
+    return DtoRealloc(ptr, n);*/
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoRealloc(llvm::Value* ptr, llvm::Value* n)
+{
+    assert(ptr);
+    assert(n);
+
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_realloc");
+    assert(fn);
+
+    llvm::Value* newptr = ptr;
+
+    llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    if (ptr->getType() != i8pty) {
+        newptr = new llvm::BitCastInst(ptr,i8pty,"tmp",gIR->scopebb());
+    }
+
+    std::vector<llvm::Value*> args;
+    args.push_back(newptr);
+    args.push_back(n);
+    llvm::Value* ret = new llvm::CallInst(fn, args.begin(), args.end(), "tmprealloc", gIR->scopebb());
+
+    return ret->getType() == ptr->getType() ? ret : new llvm::BitCastInst(ret,ptr->getType(),"tmp",gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoAssert(llvm::Value* cond, llvm::Value* loc, llvm::Value* msg)
+{
+    assert(loc);
+    std::vector<llvm::Value*> llargs;
+    llargs.resize(3);
+    llargs[0] = cond ? DtoBoolean(cond) : llvm::ConstantInt::getFalse();
+    llargs[1] = loc;
+    llargs[2] = msg ? msg : llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
+
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_assert");
+    assert(fn);
+    llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+    call->setCallingConv(llvm::CallingConv::C);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp)
+{
+    llvm::Value* retval = 0;
+
+    bool haslvals = !gIR->exps.empty();
+    if (haslvals)
+        gIR->exps.push_back(IRExp(NULL,NULL,NULL));
+
+    DValue* arg = argexp->toElem(gIR);
+
+    if (haslvals)
+        gIR->exps.pop_back();
+
+    if (arg->inPlace()) {
+        retval = arg->getRVal();
+        return retval;
+    }
+
+    Type* realtype = DtoDType(argexp->type);
+    TY argty = realtype->ty;
+    if (DtoIsPassedByRef(realtype)) {
+        if (!fnarg || !fnarg->llvmCopy) {
+            if (DSliceValue* sv = arg->isSlice()) {
+                retval = new llvm::AllocaInst(DtoType(realtype), "tmpparam", gIR->topallocapoint());
+                DtoSetArray(retval, DtoArrayLen(sv), DtoArrayPtr(sv));
+            }
+            else {
+                retval = arg->getRVal();
+            }
+        }
+        else {
+            llvm::Value* allocaInst = 0;
+            llvm::BasicBlock* entryblock = &gIR->topfunc()->front();
+            //const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(arg->mem->getType());
+            const llvm::Type* realtypell = DtoType(realtype);
+            const llvm::PointerType* pty = llvm::PointerType::get(realtypell);
+            if (argty == Tstruct) {
+                allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
+                DValue* dst = new DVarValue(realtype, allocaInst, true);
+                DtoAssign(dst,arg);
+                delete dst;
+            }
+            else if (argty == Tdelegate) {
+                allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
+                DValue* dst = new DVarValue(realtype, allocaInst, true);
+                DtoAssign(dst,arg);
+                delete dst;
+            }
+            else if (argty == Tarray) {
+                if (arg->isSlice()) {
+                    allocaInst = new llvm::AllocaInst(realtypell, "tmpparam", gIR->topallocapoint());
+                }
+                else {
+                    allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
+                }
+            }
+            else
+            assert(0);
+
+            DValue* dst = new DVarValue(realtype, allocaInst, true);
+            DtoAssign(dst,arg);
+            delete dst;
+
+            retval = allocaInst;
+        }
+    }
+    else if (!fnarg || fnarg->llvmCopy) {
+        Logger::println("regular arg");
+        if (DSliceValue* sl = arg->isSlice()) {
+            if (sl->ptr) Logger::cout() << "ptr = " << *sl->ptr << '\n';
+            if (sl->len) Logger::cout() << "len = " << *sl->len << '\n';
+            assert(0);
+        }
+        else {
+            retval = arg->getRVal();
+        }
+    }
+    else {
+        Logger::println("as ptr arg");
+        retval = arg->getLVal();
+        if (paramtype && retval->getType() != paramtype)
+        {
+            assert(0);
+            /*assert(retval->getType() == paramtype->getContainedType(0));
+            new llvm::StoreInst(retval, arg->getLVal(), gIR->scopebb());
+            retval = arg->getLVal();*/
+        }
+    }
+
+    if (fnarg && paramtype && retval->getType() != paramtype) {
+        // this is unfortunately needed with the way SymOffExp is overused
+        // and static arrays can end up being a pointer to their element type
+        if (arg->isField()) {
+            retval = gIR->ir->CreateBitCast(retval, paramtype, "tmp");
+        }
+        else {
+            Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n";
+            assert(0 && "parameter type that was actually passed is invalid");
+        }
+    }
+
+    delete arg;
+
+    return retval;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoNestedVariable(VarDeclaration* vd)
+{
+    FuncDeclaration* fd = vd->toParent()->isFuncDeclaration();
+    assert(fd != NULL);
+
+    IRFunction* fcur = &gIR->func();
+    FuncDeclaration* f = fcur->decl;
+
+    // on this stack
+    if (fd == f) {
+        llvm::Value* v = DtoGEPi(vd->llvmValue,0,unsigned(vd->llvmNestedIndex),"tmp");
+        if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) {
+            Logger::cout() << "1267 loading: " << *v << '\n';
+            v = gIR->ir->CreateLoad(v,"tmp");
+        }
+        return v;
+    }
+
+    // on a caller stack
+    llvm::Value* ptr = f->llvmThisVar;
+    assert(ptr);
+
+    f = f->toParent()->isFuncDeclaration();
+    assert(f);
+    assert(f->llvmNested);
+    const llvm::Type* nesttype = f->llvmNested->getType();
+    assert(nesttype);
+
+    ptr = gIR->ir->CreateBitCast(ptr, nesttype, "tmp");
+
+    Logger::cout() << "nested var reference:" << '\n' << *ptr << *nesttype << '\n';
+
+    while (f) {
+        if (fd == f) {
+            llvm::Value* v = DtoGEPi(ptr,0,vd->llvmNestedIndex,"tmp");
+            if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) {
+                Logger::cout() << "1291 loading: " << *v << '\n';
+                v = gIR->ir->CreateLoad(v,"tmp");
+            }
+            return v;
+        }
+        else {
+            ptr = DtoGEPi(ptr,0,0,"tmp");
+            ptr = gIR->ir->CreateLoad(ptr,"tmp");
+        }
+        f = f->toParent()->isFuncDeclaration();
+    }
+
+    assert(0 && "nested var not found");
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoAssign(DValue* lhs, DValue* rhs)
+{
+    Type* t = DtoDType(lhs->getType());
+    Type* t2 = DtoDType(rhs->getType());
+
+    if (t->ty == Tstruct) {
+        if (t2 != t) {
+            // TODO: fix this, use 'rhs' for something
+            DtoStructZeroInit(lhs->getLVal());
+        }
+        else if (!rhs->inPlace()) {
+            DtoStructCopy(lhs->getLVal(),rhs->getRVal());
+        }
+    }
+    else if (t->ty == Tarray) {
+        // lhs is slice
+        if (DSliceValue* s = lhs->isSlice()) {
+            if (DSliceValue* s2 = rhs->isSlice()) {
+                DtoArrayCopy(s, s2);
+            }
+            else if (t->next == t2) {
+                if (s->len)
+                    DtoArrayInit(s->ptr, s->len, rhs->getRVal());
+                else
+                    DtoArrayInit(s->ptr, rhs->getRVal());
+            }
+            else
+            assert(rhs->inPlace());
+        }
+        // rhs is slice
+        else if (DSliceValue* s = rhs->isSlice()) {
+            DtoSetArray(lhs->getLVal(),s->len,s->ptr);
+        }
+        // null
+        else if (rhs->isNull()) {
+            DtoNullArray(lhs->getLVal());
+        }
+        // reference assignment
+        else {
+            DtoArrayAssign(lhs->getLVal(), rhs->getRVal());
+        }
+    }
+    else if (t->ty == Tsarray) {
+        DtoStaticArrayCopy(lhs->getLVal(), rhs->getRVal());
+    }
+    else if (t->ty == Tdelegate) {
+        if (rhs->isNull())
+            DtoNullDelegate(lhs->getLVal());
+        else if (!rhs->inPlace())
+            DtoDelegateCopy(lhs->getLVal(), rhs->getRVal());
+    }
+    else if (t->ty == Tclass) {
+        assert(t2->ty == Tclass);
+        // assignment to this in constructor special case
+        if (lhs->isThis()) {
+            llvm::Value* tmp = rhs->getRVal();
+            FuncDeclaration* fdecl = gIR->func().decl;
+            // respecify the this param
+            if (!llvm::isa<llvm::AllocaInst>(fdecl->llvmThisVar))
+                fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", gIR->topallocapoint());
+            DtoStore(tmp, fdecl->llvmThisVar);
+        }
+        // regular class ref -> class ref assignment
+        else {
+            DtoStore(rhs->getRVal(), lhs->getLVal());
+        }
+    }
+    else {
+        llvm::Value* r = rhs->getRVal();
+        llvm::Value* l = lhs->getLVal();
+        Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n';
+        gIR->ir->CreateStore(r, l);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::ConstantInt* DtoConstSize_t(size_t i)
+{
+    return llvm::ConstantInt::get(DtoSize_t(), i, false);
+}
+llvm::ConstantInt* DtoConstUint(unsigned i)
+{
+    return llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false);
+}
+llvm::ConstantInt* DtoConstInt(int i)
+{
+    return llvm::ConstantInt::get(llvm::Type::Int32Ty, i, true);
+}
+llvm::Constant* DtoConstBool(bool b)
+{
+    return llvm::ConstantInt::get(llvm::Type::Int1Ty, b, false);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* DtoConstString(const char* str)
+{
+    std::string s(str);
+    llvm::Constant* init = llvm::ConstantArray::get(s, true);
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(
+        init->getType(), true,llvm::GlobalValue::InternalLinkage, init, "stringliteral", gIR->module);
+    llvm::Constant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
+    return DtoConstSlice(
+        DtoConstSize_t(s.length()),
+        llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2)
+    );
+}
+llvm::Constant* DtoConstStringPtr(const char* str, const char* section)
+{
+    std::string s(str);
+    llvm::Constant* init = llvm::ConstantArray::get(s, true);
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(
+        init->getType(), true,llvm::GlobalValue::InternalLinkage, init, "stringliteral", gIR->module);
+    if (section) gvar->setSection(section);
+    llvm::Constant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
+    return llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes)
+{
+    assert(dst->getType() == src->getType());
+
+    llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    llvm::Value *dstarr, *srcarr;
+    if (dst->getType() == arrty)
+    {
+        dstarr = dst;
+        srcarr = src;
+    }
+    else
+    {
+        dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
+        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] = nbytes;
+    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+
+    new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoLoad(llvm::Value* src)
+{
+    return gIR->ir->CreateLoad(src,"tmp");
+}
+
+void DtoStore(llvm::Value* src, llvm::Value* dst)
+{
+    gIR->ir->CreateStore(src,dst);
+}
+
+bool DtoCanLoad(llvm::Value* ptr)
+{
+    if (llvm::isa<llvm::PointerType>(ptr->getType())) {
+        return ptr->getType()->getContainedType(0)->isFirstClassType();
+    }
+    return false;
+}
+
+llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t)
+{
+    return gIR->ir->CreateBitCast(v, t, "tmp");
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs)
+{
+    Logger::println("checking for offset %u type %s:", os, t->toChars());
+    LOG_SCOPE;
+
+    if (idxs.empty())
+        idxs.push_back(0);
+
+    const llvm::Type* llt = llvm::PointerType::get(DtoType(t));
+
+    for (unsigned i=0; i<sd->fields.dim; ++i) {
+        VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i];
+        Type* vdtype = DtoDType(vd->type);
+        Logger::println("found %u type %s", vd->offset, vdtype->toChars());
+        assert(vd->llvmFieldIndex >= 0);
+        if (os == vd->offset && vdtype == t) {
+            idxs.push_back(vd->llvmFieldIndex);
+            ptr = DtoGEP(ptr, idxs, "tmp");
+            if (ptr->getType() != llt)
+                ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
+            if (vd->llvmFieldIndexOffset)
+                ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
+            return ptr;
+        }
+        else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
+            TypeStruct* ts = (TypeStruct*)vdtype;
+            StructDeclaration* ssd = ts->sym;
+            idxs.push_back(vd->llvmFieldIndex);
+            if (vd->llvmFieldIndexOffset) {
+                Logger::println("has union field offset");
+                ptr = DtoGEP(ptr, idxs, "tmp");
+                if (ptr->getType() != llt)
+                    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
+                ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
+                std::vector<unsigned> tmp;
+                return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
+            }
+            else {
+                const llvm::Type* sty = llvm::PointerType::get(DtoType(vd->type));
+                if (ptr->getType() != sty) {
+                    ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
+                    std::vector<unsigned> tmp;
+                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
+                }
+                else {
+                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs);
+                }
+            }
+        }
+    }
+
+    size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
+    assert(os % llt_sz == 0);
+    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
+    return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+bool DtoIsTemplateInstance(Dsymbol* s)
+{
+    if (!s) return false;
+    if (s->isTemplateInstance() && !s->isTemplateMixin())
+        return true;
+    else if (s->parent)
+        return DtoIsTemplateInstance(s->parent);
+    return false;
+}
--- a/gen/tollvm.h	Fri Nov 02 06:32:32 2007 +0100
+++ b/gen/tollvm.h	Sat Nov 03 14:44:58 2007 +0100
@@ -1,6 +1,10 @@
+#ifndef LLVMDC_GEN_TOLLVM_H
+#define LLVMDC_GEN_TOLLVM_H
+
 // D -> LLVM helpers
 
 struct StructInitializer;
+struct DValue;
 
 const llvm::Type* DtoType(Type* t);
 bool DtoIsPassedByRef(Type* type);
@@ -55,8 +59,6 @@
 
 llvm::Value* DtoNestedVariable(VarDeclaration* vd);
 
-void DtoAssign(Type* lhsType, llvm::Value* lhs, llvm::Value* rhs);
-
 llvm::ConstantInt* DtoConstSize_t(size_t);
 llvm::ConstantInt* DtoConstUint(unsigned i);
 llvm::ConstantInt* DtoConstInt(int i);
@@ -64,10 +66,27 @@
 llvm::Constant* DtoConstStringPtr(const char* str, const char* section = 0);
 llvm::Constant* DtoConstBool(bool);
 
-void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes);
-
 llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs);
 
 bool DtoIsTemplateInstance(Dsymbol* s);
 
+// llvm wrappers
+void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes);
+bool DtoCanLoad(llvm::Value* ptr);
+llvm::Value* DtoLoad(llvm::Value* src);
+void DtoStore(llvm::Value* src, llvm::Value* dst);
+llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t);
+
+// basic operations
+void DtoAssign(DValue* lhs, DValue* rhs);
+
+// binary operations
+DValue* DtoBinAdd(DValue* lhs, DValue* rhs);
+DValue* DtoBinSub(DValue* lhs, DValue* rhs);
+DValue* DtoBinMul(DValue* lhs, DValue* rhs);
+DValue* DtoBinDiv(DValue* lhs, DValue* rhs);
+DValue* DtoBinRem(DValue* lhs, DValue* rhs);
+
 #include "enums.h"
+
+#endif // LLVMDC_GEN_TOLLVM_H
--- a/gen/toobj.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,989 +0,0 @@
-
-// Copyright (c) 1999-2004 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.
-
-#include <cstddef>
-#include <iostream>
-#include <fstream>
-
-#include "gen/llvm.h"
-#include "llvm/Analysis/Verifier.h"
-#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetMachineRegistry.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 "id.h"
-#include "import.h"
-#include "template.h"
-#include "scope.h"
-
-#include "gen/irstate.h"
-#include "gen/elem.h"
-#include "gen/logger.h"
-#include "gen/tollvm.h"
-#include "gen/arrays.h"
-#include "gen/todebug.h"
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void
-Module::genobjfile()
-{
-    Logger::cout() << "Generating module: " << (md ? md->toChars() : toChars()) << '\n';
-    LOG_SCOPE;
-
-    // start by deleting the old object file
-    deleteObjFile();
-
-    // create a new ir state
-    IRState ir;
-    gIR = &ir;
-    ir.dmodule = this;
-
-    // name the module
-    std::string mname(toChars());
-    if (md != 0)
-        mname = md->toChars();
-    ir.module = new llvm::Module(mname);
-
-    // set target stuff
-    std::string target_triple(global.params.tt_arch);
-    target_triple.append(global.params.tt_os);
-    ir.module->setTargetTriple(target_triple);
-    ir.module->setDataLayout(global.params.data_layout);
-
-    // heavily inspired by tools/llc/llc.cpp:200-230
-    const llvm::TargetMachineRegistry::Entry* targetEntry;
-    std::string targetError;
-    targetEntry = llvm::TargetMachineRegistry::getClosestStaticTargetForModule(*ir.module, targetError);
-    assert(targetEntry && "Failed to find a static target for module");
-    std::auto_ptr<llvm::TargetMachine> targetPtr(targetEntry->CtorFn(*ir.module, "")); // TODO: replace "" with features
-    assert(targetPtr.get() && "Could not allocate target machine!");
-    llvm::TargetMachine &targetMachine = *targetPtr.get();
-    gTargetData = targetMachine.getTargetData();
-
-    // debug info
-    if (global.params.symdebug) {
-        RegisterDwarfSymbols(ir.module);
-        ir.dwarfCompileUnit = DtoDwarfCompileUnit(this);
-    }
-
-    // process module members
-    for (int k=0; k < members->dim; k++) {
-        Dsymbol* dsym = (Dsymbol*)(members->data[k]);
-        assert(dsym);
-        dsym->toObjFile();
-    }
-
-    gTargetData = 0;
-
-    // emit the llvm main function if necessary
-    if (ir.emitMain) {
-        DtoMain();
-    }
-
-    // verify the llvm
-    if (!global.params.novalidate) {
-        std::string verifyErr;
-        Logger::println("Verifying module...");
-        if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr))
-        {
-            error("%s", verifyErr.c_str());
-            fatal();
-        }
-        else {
-            Logger::println("Verification passed!");
-        }
-    }
-
-    // run passes
-    // TODO
-
-    // write bytecode
-    {
-        Logger::println("Writing LLVM bitcode\n");
-        std::ofstream bos(bcfile->name->toChars(), std::ios::binary);
-        llvm::WriteBitcodeToFile(ir.module, bos);
-    }
-
-    // disassemble ?
-    if (global.params.disassemble) {
-        Logger::println("Writing LLVM asm to: %s\n", llfile->name->toChars());
-        std::ofstream aos(llfile->name->toChars());
-        ir.module->print(aos);
-    }
-
-    delete ir.module;
-    gIR = NULL;
-}
-
-/* ================================================================== */
-
-// Put out instance of ModuleInfo for this Module
-
-void Module::genmoduleinfo()
-{
-}
-
-/* ================================================================== */
-
-void Dsymbol::toObjFile()
-{
-    Logger::println("Ignoring Dsymbol::toObjFile for %s", toChars());
-}
-
-/* ================================================================== */
-
-void Declaration::toObjFile()
-{
-    Logger::println("Ignoring Declaration::toObjFile for %s", toChars());
-}
-
-/* ================================================================== */
-
-void InterfaceDeclaration::toObjFile()
-{
-    Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars());
-}
-
-/* ================================================================== */
-
-void StructDeclaration::toObjFile()
-{
-    TypeStruct* ts = (TypeStruct*)DtoDType(type);
-    if (llvmType != 0)
-        return;
-
-    static int sdi = 0;
-    Logger::print("StructDeclaration::toObjFile(%d): %s\n", sdi++, toChars());
-    LOG_SCOPE;
-
-    gIR->structs.push_back(IRStruct(ts));
-
-    for (int k=0; k < members->dim; k++) {
-        Dsymbol* dsym = (Dsymbol*)(members->data[k]);
-        dsym->toObjFile();
-    }
-
-    Logger::println("doing struct fields");
-
-    llvm::StructType* structtype = 0;
-    std::vector<llvm::Constant*> fieldinits;
-
-    if (gIR->topstruct().offsets.empty())
-    {
-        std::vector<const llvm::Type*> fieldtypes;
-        Logger::println("has no fields");
-        fieldtypes.push_back(llvm::Type::Int8Ty);
-        fieldinits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
-        structtype = llvm::StructType::get(fieldtypes);
-    }
-    else
-    {
-        Logger::println("has fields");
-        std::vector<const llvm::Type*> fieldtypes;
-        unsigned prevsize = (unsigned)-1;
-        unsigned lastoffset = (unsigned)-1;
-        const llvm::Type* fieldtype = NULL;
-        llvm::Constant* fieldinit = NULL;
-        size_t fieldpad = 0;
-        int idx = 0;
-        for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
-            // first iteration
-            if (lastoffset == (unsigned)-1) {
-                lastoffset = i->first;
-                assert(lastoffset == 0);
-                fieldtype = DtoType(i->second.var->type);
-                fieldinit = i->second.init;
-                prevsize = gTargetData->getTypeSize(fieldtype);
-                i->second.var->llvmFieldIndex = idx;
-            }
-            // colliding offset?
-            else if (lastoffset == i->first) {
-                const llvm::Type* t = DtoType(i->second.var->type);
-                size_t s = gTargetData->getTypeSize(t);
-                if (s > prevsize) {
-                    fieldpad += s - prevsize;
-                    prevsize = s;
-                }
-                llvmHasUnions = true;
-                i->second.var->llvmFieldIndex = idx;
-            }
-            // intersecting offset?
-            else if (i->first < (lastoffset + prevsize)) {
-                const llvm::Type* t = DtoType(i->second.var->type);
-                size_t s = gTargetData->getTypeSize(t);
-                assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
-                llvmHasUnions = true;
-                i->second.var->llvmFieldIndex = idx;
-                i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s;
-            }
-            // fresh offset
-            else {
-                // commit the field
-                fieldtypes.push_back(fieldtype);
-                fieldinits.push_back(fieldinit);
-                if (fieldpad) {
-                    // match up with below
-                    std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
-                    llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
-                    fieldtypes.push_back(c->getType());
-                    fieldinits.push_back(c);
-                    idx++;
-                }
-
-                idx++;
-
-                // start new
-                lastoffset = i->first;
-                fieldtype = DtoType(i->second.var->type);
-                fieldinit = i->second.init;
-                prevsize = gTargetData->getTypeSize(fieldtype);
-                i->second.var->llvmFieldIndex = idx;
-                fieldpad = 0;
-            }
-        }
-        fieldtypes.push_back(fieldtype);
-        fieldinits.push_back(fieldinit);
-        if (fieldpad) {
-            // match up with above
-            std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
-            llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
-            fieldtypes.push_back(c->getType());
-            fieldinits.push_back(c);
-        }
-
-        Logger::println("creating struct type");
-        structtype = llvm::StructType::get(fieldtypes);
-    }
-
-    // refine abstract types for stuff like: struct S{S* next;}
-    if (gIR->topstruct().recty != 0)
-    {
-        llvm::PATypeHolder& pa = gIR->topstruct().recty;
-        llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
-        structtype = llvm::cast<llvm::StructType>(pa.get());
-    }
-
-    ts->llvmType = structtype;
-    llvmType = structtype;
-
-    if (parent->isModule()) {
-        gIR->module->addTypeName(mangle(),ts->llvmType);
-    }
-
-    // generate static data
-    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
-    llvm::Constant* _init = 0;
-
-    // always generate the constant initalizer
-    if (!zeroInit) {
-        Logger::println("Not zero initialized");
-        //assert(tk == gIR->gIR->topstruct()().size());
-        #ifndef LLVMD_NO_LOGGER
-        Logger::cout() << "struct type: " << *structtype << '\n';
-        for (size_t k=0; k<fieldinits.size(); ++k) {
-            Logger::cout() << "Type:" << '\n';
-            Logger::cout() << *fieldinits[k]->getType() << '\n';
-            Logger::cout() << "Value:" << '\n';
-            Logger::cout() << *fieldinits[k] << '\n';
-        }
-        Logger::cout() << "Initializer printed" << '\n';
-        #endif
-        llvmInitZ = llvm::ConstantStruct::get(structtype,fieldinits);
-    }
-    else {
-        Logger::println("Zero initialized");
-        llvmInitZ = llvm::ConstantAggregateZero::get(structtype);
-    }
-
-    // only provide the constant initializer for the defining module
-    if (getModule() == gIR->dmodule)
-    {
-        _init = llvmInitZ;
-    }
-
-    std::string initname("_D");
-    initname.append(mangle());
-    initname.append("6__initZ");
-    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module);
-    ts->llvmInit = initvar;
-
-    // generate member function definitions
-    gIR->topstruct().queueFuncs = false;
-    IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
-    size_t n = mfs.size();
-    for (size_t i=0; i<n; ++i) {
-        mfs[i]->toObjFile();
-    }
-
-    llvmDModule = gIR->dmodule;
-
-    gIR->structs.pop_back();
-
-    // generate typeinfo
-    if (getModule() == gIR->dmodule && llvmInternal != LLVMnotypeinfo)
-        type->getTypeInfo(NULL);
-}
-
-/* ================================================================== */
-
-static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx)
-{
-    // start at the bottom of the inheritance chain
-    if (cd->baseClass != 0) {
-        unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx);
-        if (o != (unsigned)-1)
-            return o;
-    }
-
-    // check this class
-    unsigned i;
-    for (i=0; i<cd->fields.dim; ++i) {
-        VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i];
-        if (os == vd->offset)
-            return i+idx;
-    }
-    idx += i;
-
-    return (unsigned)-1;
-}
-
-void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
-{
-    unsigned idx = 0;
-    unsigned r = LLVM_ClassOffsetToIndex(this, os, idx);
-    assert(r != (unsigned)-1 && "Offset not found in any aggregate field");
-    result.push_back(r+1); // vtable is 0
-}
-
-/* ================================================================== */
-
-static void LLVM_AddBaseClassData(BaseClasses* bcs)
-{
-    // add base class data members first
-    for (int j=0; j<bcs->dim; j++)
-    {
-        BaseClass* bc = (BaseClass*)(bcs->data[j]);
-        assert(bc);
-        Logger::println("Adding base class members of %s", bc->base->toChars());
-        LOG_SCOPE;
-
-        LLVM_AddBaseClassData(&bc->base->baseclasses);
-        for (int k=0; k < bc->base->members->dim; k++) {
-            Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]);
-            if (dsym->isVarDeclaration())
-            {
-                dsym->toObjFile();
-            }
-        }
-    }
-}
-
-void ClassDeclaration::toObjFile()
-{
-    TypeClass* ts = (TypeClass*)DtoDType(type);
-    if (ts->llvmType != 0 || llvmInProgress)
-        return;
-
-    llvmInProgress = true;
-
-    static int fdi = 0;
-    Logger::print("ClassDeclaration::toObjFile(%d): %s\n", fdi++, toChars());
-    LOG_SCOPE;
-
-    gIR->structs.push_back(IRStruct(ts));
-    gIR->classes.push_back(this);
-
-    // add vtable
-    llvm::PATypeHolder pa = llvm::OpaqueType::get();
-    const llvm::Type* vtabty = llvm::PointerType::get(pa);
-
-    std::vector<const llvm::Type*> fieldtypes;
-    fieldtypes.push_back(vtabty);
-
-    std::vector<llvm::Constant*> fieldinits;
-    fieldinits.push_back(0);
-
-    // base classes first
-    LLVM_AddBaseClassData(&baseclasses);
-
-    // then add own members
-    for (int k=0; k < members->dim; k++) {
-        Dsymbol* dsym = (Dsymbol*)(members->data[k]);
-        dsym->toObjFile();
-    }
-
-    // fill out fieldtypes/inits
-    for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
-        fieldtypes.push_back(DtoType(i->second.var->type));
-        fieldinits.push_back(i->second.init);
-    }
-
-    llvm::StructType* structtype = llvm::StructType::get(fieldtypes);
-    // refine abstract types for stuff like: class C {C next;}
-    if (gIR->topstruct().recty != 0)
-    {
-        llvm::PATypeHolder& pa = gIR->topstruct().recty;
-        llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
-        structtype = llvm::cast<llvm::StructType>(pa.get());
-    }
-
-    ts->llvmType = structtype;
-    llvmType = structtype;
-
-    bool needs_definition = false;
-    if (parent->isModule()) {
-        gIR->module->addTypeName(mangle(),ts->llvmType);
-        needs_definition = (getModule() == gIR->dmodule);
-    }
-    else {
-        assert(0 && "class parent is not a module");
-    }
-
-    // generate vtable
-    llvm::GlobalVariable* svtblVar = 0;
-    std::vector<llvm::Constant*> sinits;
-    std::vector<const llvm::Type*> sinits_ty;
-    sinits.reserve(vtbl.dim);
-    sinits_ty.reserve(vtbl.dim);
-
-    for (int k=0; k < vtbl.dim; k++)
-    {
-        Dsymbol* dsym = (Dsymbol*)vtbl.data[k];
-        assert(dsym);
-        //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
-
-        if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
-            fd->toObjFile();
-            assert(fd->llvmValue);
-            llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
-            sinits.push_back(c);
-            sinits_ty.push_back(c->getType());
-        }
-        else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
-            const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty);
-            llvm::Constant* c = llvm::Constant::getNullValue(cty);
-            sinits.push_back(c);
-            sinits_ty.push_back(cty);
-        }
-        else
-        assert(0);
-    }
-
-    const llvm::StructType* svtbl_ty = 0;
-    if (!sinits.empty())
-    {
-        llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
-
-        std::string varname("_D");
-        varname.append(mangle());
-        varname.append("6__vtblZ");
-
-        std::string styname(mangle());
-        styname.append("__vtblTy");
-
-        svtbl_ty = llvm::StructType::get(sinits_ty);
-        gIR->module->addTypeName(styname, svtbl_ty);
-        svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
-
-        llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits));
-        if (needs_definition)
-            svtblVar->setInitializer(llvmConstVtbl);
-        llvmVtbl = svtblVar;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////////
-
-    // refine for final vtable type
-    llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty);
-    svtbl_ty = llvm::cast<llvm::StructType>(pa.get());
-    structtype = llvm::cast<llvm::StructType>(gIR->topstruct().recty.get());
-    ts->llvmType = structtype;
-    llvmType = structtype;
-
-    // generate initializer
-    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
-    llvm::Constant* _init = 0;
-
-    // first field is always the vtable
-    assert(svtblVar != 0);
-    fieldinits[0] = svtblVar;
-
-    llvmInitZ = _init = llvm::ConstantStruct::get(structtype,fieldinits);
-    assert(_init);
-
-    std::string initname("_D");
-    initname.append(mangle());
-    initname.append("6__initZ");
-    //Logger::cout() << *_init << '\n';
-    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, NULL, initname, gIR->module);
-    ts->llvmInit = initvar;
-
-    if (needs_definition) {
-        initvar->setInitializer(_init);
-        // generate member functions
-        gIR->topstruct().queueFuncs = false;
-        IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
-        size_t n = mfs.size();
-        for (size_t i=0; i<n; ++i) {
-            mfs[i]->toObjFile();
-        }
-    }
-
-    gIR->classes.pop_back();
-    gIR->structs.pop_back();
-
-    llvmInProgress = false;
-}
-
-/******************************************
- * Get offset of base class's vtbl[] initializer from start of csym.
- * Returns ~0 if not this csym.
- */
-
-unsigned ClassDeclaration::baseVtblOffset(BaseClass *bc)
-{
-  return ~0;
-}
-
-/* ================================================================== */
-
-void VarDeclaration::toObjFile()
-{
-    Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-    llvm::Module* M = gIR->module;
-
-    if (aliassym)
-    {
-        toAlias()->toObjFile();
-        return;
-    }
-
-    // global variable or magic
-    if (isDataseg())
-    {
-        if (llvmTouched) return;
-        else llvmTouched = true;
-
-        bool _isconst = false;
-        if (isConst() && (init && !init->isExpInitializer()))
-            _isconst = true;
-
-        llvm::GlobalValue::LinkageTypes _linkage;
-        bool istempl = false;
-        if ((storage_class & STCcomdat) || (parent && DtoIsTemplateInstance(parent))) {
-            _linkage = llvm::GlobalValue::WeakLinkage;
-            istempl = true;
-        }
-        else if (parent && parent->isFuncDeclaration())
-            _linkage = llvm::GlobalValue::InternalLinkage;
-        else
-            _linkage = DtoLinkage(protection, storage_class);
-
-        Type* t = DtoDType(type);
-
-        const llvm::Type* _type = DtoType(t);
-        assert(_type);
-
-        llvm::Constant* _init = 0;
-        bool _signed = !type->isunsigned();
-
-        Logger::println("Creating global variable");
-        std::string _name(mangle());
-
-        llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M);
-        llvmValue = gvar;
-
-        if (!(storage_class & STCextern) && (getModule() == gIR->dmodule || istempl))
-        {
-            if (parent && parent->isFuncDeclaration() && init && init->isExpInitializer()) {
-                _init = DtoConstInitializer(t, NULL);
-                // create a flag to make sure initialization only happens once
-                llvm::GlobalValue::LinkageTypes gflaglink = istempl ? llvm::GlobalValue::WeakLinkage : llvm::GlobalValue::InternalLinkage;
-                std::string gflagname(_name);
-                gflagname.append("__initflag");
-                llvm::GlobalVariable* gflag = new llvm::GlobalVariable(llvm::Type::Int1Ty,false,gflaglink,DtoConstBool(false),gflagname,M);
-
-                // check flag and do init if not already done
-                llvm::BasicBlock* oldend = gIR->scopeend();
-                llvm::BasicBlock* initbb = new llvm::BasicBlock("ifnotinit",gIR->topfunc(),oldend);
-                llvm::BasicBlock* endinitbb = new llvm::BasicBlock("ifnotinitend",gIR->topfunc(),oldend);
-                llvm::Value* cond = gIR->ir->CreateICmpEQ(gIR->ir->CreateLoad(gflag,"tmp"),DtoConstBool(false));
-                gIR->ir->CreateCondBr(cond, initbb, endinitbb);
-                gIR->scope() = IRScope(initbb,endinitbb);
-                elem* ie = DtoInitializer(init);
-                if (!ie->inplace)
-                    DtoAssign(t, gvar, ie->getValue());
-                gIR->ir->CreateStore(DtoConstBool(true), gflag);
-                gIR->ir->CreateBr(endinitbb);
-                gIR->scope() = IRScope(endinitbb,oldend);
-            }
-            else {
-                _init = DtoConstInitializer(t, init);
-            }
-
-            //Logger::cout() << "initializer: " << *_init << '\n';
-            if (_type != _init->getType()) {
-                Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n";
-                // zero initalizer
-                if (_init->isNullValue())
-                    _init = llvm::Constant::getNullValue(_type);
-                // pointer to global constant (struct.init)
-                else if (llvm::isa<llvm::GlobalVariable>(_init))
-                {
-                    assert(_init->getType()->getContainedType(0) == _type);
-                    llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init);
-                    assert(t->ty == Tstruct);
-                    TypeStruct* ts = (TypeStruct*)t;
-                    assert(ts->sym->llvmInitZ);
-                    _init = ts->sym->llvmInitZ;
-                }
-                // array single value init
-                else if (llvm::isa<llvm::ArrayType>(_type))
-                {
-                    _init = DtoConstStaticArray(_type, _init);
-                }
-                else {
-                    Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
-                    //assert(0);
-                }
-            }
-
-            Logger::cout() << "final init = " << *_init << '\n';
-            gvar->setInitializer(_init);
-        }
-
-        llvmDModule = gIR->dmodule;
-
-        //if (storage_class & STCprivate)
-        //    gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility);
-    }
-
-    // inside aggregate declaration. declare a field.
-    else
-    {
-        Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset);
-
-        Type* t = DtoDType(type);
-        const llvm::Type* _type = DtoType(t);
-
-        llvm::Constant*_init = DtoConstInitializer(t, init);
-        assert(_init);
-        Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n';
-        if (_type != _init->getType())
-        {
-            if (t->ty == Tsarray)
-            {
-                const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(_type);
-                uint64_t n = arrty->getNumElements();
-                std::vector<llvm::Constant*> vals(n,_init);
-                _init = llvm::ConstantArray::get(arrty, vals);
-            }
-            else if (t->ty == Tarray)
-            {
-                assert(llvm::isa<llvm::StructType>(_type));
-                _init = llvm::ConstantAggregateZero::get(_type);
-            }
-            else if (t->ty == Tstruct)
-            {
-                const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type);
-                TypeStruct* ts = (TypeStruct*)t;
-                assert(ts);
-                assert(ts->sym);
-                assert(ts->sym->llvmInitZ);
-                _init = ts->sym->llvmInitZ;
-            }
-            else if (t->ty == Tclass)
-            {
-                _init = llvm::Constant::getNullValue(_type);
-            }
-            else {
-                Logger::println("failed for type %s", type->toChars());
-                assert(0);
-            }
-        }
-
-        // add the field in the IRStruct
-        gIR->topstruct().offsets.insert(std::make_pair(offset, IRStruct::Offset(this,_init)));
-    }
-
-    Logger::println("VarDeclaration::toObjFile is done");
-}
-
-/* ================================================================== */
-
-void TypedefDeclaration::toObjFile()
-{
-    static int tdi = 0;
-    Logger::print("TypedefDeclaration::toObjFile(%d): %s\n", tdi++, toChars());
-    LOG_SCOPE;
-
-    // generate typeinfo
-    type->getTypeInfo(NULL);
-}
-
-/* ================================================================== */
-
-void EnumDeclaration::toObjFile()
-{
-    Logger::println("Ignoring EnumDeclaration::toObjFile for %s", toChars());
-}
-
-/* ================================================================== */
-
-void FuncDeclaration::toObjFile()
-{
-    if (llvmDModule) {
-        assert(llvmValue != 0);
-        return;
-    }
-
-    if (isUnitTestDeclaration()) {
-        Logger::println("*** ATTENTION: ignoring unittest declaration: %s", toChars());
-        return;
-    }
-
-    Type* t = DtoDType(type);
-    TypeFunction* f = (TypeFunction*)t;
-
-    bool declareOnly = false;
-    if (TemplateInstance* tinst = parent->isTemplateInstance()) {
-        TemplateDeclaration* tempdecl = tinst->tempdecl;
-        if (tempdecl->llvmInternal == LLVMva_start)
-        {
-            Logger::println("magic va_start found");
-            llvmInternal = LLVMva_start;
-            declareOnly = true;
-        }
-        else if (tempdecl->llvmInternal == LLVMva_arg)
-        {
-            Logger::println("magic va_arg found");
-            llvmInternal = LLVMva_arg;
-            return;
-        }
-    }
-
-    llvm::Function* func = DtoDeclareFunction(this);
-
-    if (declareOnly)
-        return;
-
-    if (!gIR->structs.empty() && gIR->topstruct().queueFuncs) {
-        if (!llvmQueued) {
-            Logger::println("queueing %s", toChars());
-            gIR->topstruct().funcs.push_back(this);
-            llvmQueued = true;
-        }
-        return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete
-    }
-
-    // debug info
-    if (global.params.symdebug) {
-        llvmDwarfSubProgram = DtoDwarfSubProgram(this);
-    }
-
-    assert(f->llvmType);
-    const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0));
-
-    // template instances should have weak linkage
-    assert(parent);
-    if (DtoIsTemplateInstance(parent)) {
-        func->setLinkage(llvm::GlobalValue::WeakLinkage);
-    }
-
-    // only members of the current module maybe be defined
-    if (getModule() == gIR->dmodule || DtoIsTemplateInstance(parent))
-    {
-        llvmDModule = gIR->dmodule;
-
-        // handle static constructor / destructor
-        if (isStaticCtorDeclaration() || isStaticDtorDeclaration()) {
-            const llvm::ArrayType* sctor_type = llvm::ArrayType::get(llvm::PointerType::get(functype),1);
-            //Logger::cout() << "static ctor type: " << *sctor_type << '\n';
-
-            llvm::Constant* sctor_func = llvm::cast<llvm::Constant>(llvmValue);
-            //Logger::cout() << "static ctor func: " << *sctor_func << '\n';
-
-            llvm::Constant* sctor_init = llvm::ConstantArray::get(sctor_type,&sctor_func,1);
-
-            //Logger::cout() << "static ctor init: " << *sctor_init << '\n';
-
-            // output the llvm.global_ctors array
-            const char* varname = isStaticCtorDeclaration() ? "_d_module_ctor_array" : "_d_module_dtor_array";
-            llvm::GlobalVariable* sctor_arr = new llvm::GlobalVariable(sctor_type, false, llvm::GlobalValue::AppendingLinkage, sctor_init, varname, gIR->module);
-        }
-
-        // function definition
-        if (fbody != 0)
-        {
-            gIR->functions.push_back(IRFunction(this));
-            gIR->func().func = func;
-
-            // first make absolutely sure the type is up to date
-            f->llvmType = llvmValue->getType()->getContainedType(0);
-
-            //Logger::cout() << "func type: " << *f->llvmType << '\n';
-
-            // this handling
-            if (f->llvmUsesThis) {
-                Logger::println("uses this");
-                if (f->llvmRetInPtr)
-                    llvmThisVar = ++func->arg_begin();
-                else
-                    llvmThisVar = func->arg_begin();
-                assert(llvmThisVar != 0);
-            }
-
-            if (isMain())
-                gIR->emitMain = true;
-
-            llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func);
-            llvm::BasicBlock* endbb = new llvm::BasicBlock("endentry",func);
-
-            //assert(gIR->scopes.empty());
-            gIR->scopes.push_back(IRScope(beginbb, endbb));
-
-                // create alloca point
-                f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb());
-                gIR->func().allocapoint = f->llvmAllocaPoint;
-
-                // give arguments storage
-                size_t n = Argument::dim(f->parameters);
-                for (int i=0; i < n; ++i) {
-                    Argument* arg = Argument::getNth(f->parameters, i);
-                    if (arg && arg->vardecl) {
-                        VarDeclaration* vd = arg->vardecl;
-                        if (!vd->llvmNeedsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))
-                            continue;
-                        llvm::Value* a = vd->llvmValue;
-                        assert(a);
-                        std::string s(a->getName());
-                        Logger::println("giving argument '%s' storage", s.c_str());
-                        s.append("_storage");
-                        llvm::Value* v = new llvm::AllocaInst(a->getType(),s,f->llvmAllocaPoint);
-                        gIR->ir->CreateStore(a,v);
-                        vd->llvmValue = v;
-                    }
-                    else {
-                        Logger::println("*** ATTENTION: some unknown argument: %s", arg ? arg->toChars() : 0);
-                    }
-                }
-
-                // debug info
-                if (global.params.symdebug) DtoDwarfFuncStart(this);
-
-                llvm::Value* parentNested = NULL;
-                if (FuncDeclaration* fd = toParent()->isFuncDeclaration()) {
-                    parentNested = fd->llvmNested;
-                }
-
-                // construct nested variables struct
-                if (!llvmNestedVars.empty() || parentNested) {
-                    std::vector<const llvm::Type*> nestTypes;
-                    int j = 0;
-                    if (parentNested) {
-                        nestTypes.push_back(parentNested->getType());
-                        j++;
-                    }
-                    for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) {
-                        VarDeclaration* vd = *i;
-                        vd->llvmNestedIndex = j++;
-                        if (vd->isParameter()) {
-                            assert(vd->llvmValue);
-                            nestTypes.push_back(vd->llvmValue->getType());
-                        }
-                        else {
-                            nestTypes.push_back(DtoType(vd->type));
-                        }
-                    }
-                    const llvm::StructType* nestSType = llvm::StructType::get(nestTypes);
-                    Logger::cout() << "nested var struct has type:" << '\n' << *nestSType;
-                    llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",f->llvmAllocaPoint);
-                    if (parentNested) {
-                        assert(llvmThisVar);
-                        llvm::Value* ptr = gIR->ir->CreateBitCast(llvmThisVar, parentNested->getType(), "tmp");
-                        gIR->ir->CreateStore(ptr, DtoGEPi(llvmNested, 0,0, "tmp"));
-                    }
-                    for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) {
-                        VarDeclaration* vd = *i;
-                        if (vd->isParameter()) {
-                            gIR->ir->CreateStore(vd->llvmValue, DtoGEPi(llvmNested, 0, vd->llvmNestedIndex, "tmp"));
-                            vd->llvmValue = llvmNested;
-                        }
-                    }
-                }
-
-                // copy _argptr to a memory location
-                if (f->linkage == LINKd && f->varargs == 1)
-                {
-                    llvm::Value* argptrmem = new llvm::AllocaInst(llvmArgPtr->getType(), "_argptrmem", gIR->topallocapoint());
-                    new llvm::StoreInst(llvmArgPtr, argptrmem, gIR->scopebb());
-                    llvmArgPtr = argptrmem;
-                }
-
-                // output function body
-                fbody->toIR(gIR);
-
-                // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement
-                // in automatically, so we do it here.
-                if (!isMain()) {
-                    if (!gIR->scopereturned()) {
-                        // pass the previous block into this block
-                        if (global.params.symdebug) DtoDwarfFuncEnd(this);
-                        if (func->getReturnType() == llvm::Type::VoidTy) {
-                            new llvm::ReturnInst(gIR->scopebb());
-                        }
-                        else {
-                            new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), gIR->scopebb());
-                        }
-                    }
-                }
-
-                // erase alloca point
-                f->llvmAllocaPoint->eraseFromParent();
-                f->llvmAllocaPoint = 0;
-                gIR->func().allocapoint = 0;
-
-            gIR->scopes.pop_back();
-
-            // get rid of the endentry block, it's never used
-            assert(!func->getBasicBlockList().empty());
-            func->getBasicBlockList().pop_back();
-
-            // if the last block is empty now, it must be unreachable or it's a bug somewhere else
-            // would be nice to figure out how to assert that this is correct
-            llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
-            if (lastbb->empty()) {
-                if (lastbb->getNumUses() == 0)
-                    lastbb->eraseFromParent();
-                else {
-                    new llvm::UnreachableInst(lastbb);
-                    /*if (func->getReturnType() == llvm::Type::VoidTy) {
-                        new llvm::ReturnInst(lastbb);
-                    }
-                    else {
-                        new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), lastbb);
-                    }*/
-                }
-            }
-
-            gIR->functions.pop_back();
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/toobj.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,1002 @@
+
+// Copyright (c) 1999-2004 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.
+
+#include <cstddef>
+#include <iostream>
+#include <fstream>
+
+#include "gen/llvm.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetMachineRegistry.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 "id.h"
+#include "import.h"
+#include "template.h"
+#include "scope.h"
+
+#include "gen/irstate.h"
+#include "gen/elem.h"
+#include "gen/logger.h"
+#include "gen/tollvm.h"
+#include "gen/arrays.h"
+#include "gen/todebug.h"
+#include "gen/runtime.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void
+Module::genobjfile()
+{
+    Logger::cout() << "Generating module: " << (md ? md->toChars() : toChars()) << '\n';
+    LOG_SCOPE;
+
+    // start by deleting the old object file
+    deleteObjFile();
+
+    // create a new ir state
+    IRState ir;
+    gIR = &ir;
+    ir.dmodule = this;
+
+    // name the module
+    std::string mname(toChars());
+    if (md != 0)
+        mname = md->toChars();
+    ir.module = new llvm::Module(mname);
+
+    // set target stuff
+    std::string target_triple(global.params.tt_arch);
+    target_triple.append(global.params.tt_os);
+    ir.module->setTargetTriple(target_triple);
+    ir.module->setDataLayout(global.params.data_layout);
+
+    // heavily inspired by tools/llc/llc.cpp:200-230
+    const llvm::TargetMachineRegistry::Entry* targetEntry;
+    std::string targetError;
+    targetEntry = llvm::TargetMachineRegistry::getClosestStaticTargetForModule(*ir.module, targetError);
+    assert(targetEntry && "Failed to find a static target for module");
+    std::auto_ptr<llvm::TargetMachine> targetPtr(targetEntry->CtorFn(*ir.module, "")); // TODO: replace "" with features
+    assert(targetPtr.get() && "Could not allocate target machine!");
+    llvm::TargetMachine &targetMachine = *targetPtr.get();
+    gTargetData = targetMachine.getTargetData();
+
+    // debug info
+    if (global.params.symdebug) {
+        RegisterDwarfSymbols(ir.module);
+        ir.dwarfCompileUnit = DtoDwarfCompileUnit(this);
+    }
+
+    // process module members
+    for (int k=0; k < members->dim; k++) {
+        Dsymbol* dsym = (Dsymbol*)(members->data[k]);
+        assert(dsym);
+        dsym->toObjFile();
+    }
+
+    gTargetData = 0;
+
+    // emit the llvm main function if necessary
+    if (ir.emitMain) {
+        DtoMain();
+    }
+
+    // verify the llvm
+    if (!global.params.novalidate) {
+        std::string verifyErr;
+        Logger::println("Verifying module...");
+        if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr))
+        {
+            error("%s", verifyErr.c_str());
+            fatal();
+        }
+        else {
+            Logger::println("Verification passed!");
+        }
+    }
+
+    // run passes
+    // TODO
+
+    // write bytecode
+    {
+        Logger::println("Writing LLVM bitcode\n");
+        std::ofstream bos(bcfile->name->toChars(), std::ios::binary);
+        llvm::WriteBitcodeToFile(ir.module, bos);
+    }
+
+    // disassemble ?
+    if (global.params.disassemble) {
+        Logger::println("Writing LLVM asm to: %s\n", llfile->name->toChars());
+        std::ofstream aos(llfile->name->toChars());
+        ir.module->print(aos);
+    }
+
+    delete ir.module;
+    gIR = NULL;
+}
+
+/* ================================================================== */
+
+// Put out instance of ModuleInfo for this Module
+
+void Module::genmoduleinfo()
+{
+}
+
+/* ================================================================== */
+
+void Dsymbol::toObjFile()
+{
+    Logger::println("Ignoring Dsymbol::toObjFile for %s", toChars());
+}
+
+/* ================================================================== */
+
+void Declaration::toObjFile()
+{
+    Logger::println("Ignoring Declaration::toObjFile for %s", toChars());
+}
+
+/* ================================================================== */
+
+void InterfaceDeclaration::toObjFile()
+{
+    Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars());
+}
+
+/* ================================================================== */
+
+void StructDeclaration::toObjFile()
+{
+    TypeStruct* ts = (TypeStruct*)DtoDType(type);
+    if (llvmType != 0)
+        return;
+
+    static int sdi = 0;
+    Logger::print("StructDeclaration::toObjFile(%d): %s\n", sdi++, toChars());
+    LOG_SCOPE;
+
+    gIR->structs.push_back(IRStruct(ts));
+
+    for (int k=0; k < members->dim; k++) {
+        Dsymbol* dsym = (Dsymbol*)(members->data[k]);
+        dsym->toObjFile();
+    }
+
+    Logger::println("doing struct fields");
+
+    llvm::StructType* structtype = 0;
+    std::vector<llvm::Constant*> fieldinits;
+
+    if (gIR->topstruct().offsets.empty())
+    {
+        std::vector<const llvm::Type*> fieldtypes;
+        Logger::println("has no fields");
+        fieldtypes.push_back(llvm::Type::Int8Ty);
+        fieldinits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
+        structtype = llvm::StructType::get(fieldtypes);
+    }
+    else
+    {
+        Logger::println("has fields");
+        std::vector<const llvm::Type*> fieldtypes;
+        unsigned prevsize = (unsigned)-1;
+        unsigned lastoffset = (unsigned)-1;
+        const llvm::Type* fieldtype = NULL;
+        llvm::Constant* fieldinit = NULL;
+        size_t fieldpad = 0;
+        int idx = 0;
+        for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
+            // first iteration
+            if (lastoffset == (unsigned)-1) {
+                lastoffset = i->first;
+                assert(lastoffset == 0);
+                fieldtype = DtoType(i->second.var->type);
+                fieldinit = i->second.init;
+                prevsize = gTargetData->getTypeSize(fieldtype);
+                i->second.var->llvmFieldIndex = idx;
+            }
+            // colliding offset?
+            else if (lastoffset == i->first) {
+                const llvm::Type* t = DtoType(i->second.var->type);
+                size_t s = gTargetData->getTypeSize(t);
+                if (s > prevsize) {
+                    fieldpad += s - prevsize;
+                    prevsize = s;
+                }
+                llvmHasUnions = true;
+                i->second.var->llvmFieldIndex = idx;
+            }
+            // intersecting offset?
+            else if (i->first < (lastoffset + prevsize)) {
+                const llvm::Type* t = DtoType(i->second.var->type);
+                size_t s = gTargetData->getTypeSize(t);
+                assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
+                llvmHasUnions = true;
+                i->second.var->llvmFieldIndex = idx;
+                i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s;
+            }
+            // fresh offset
+            else {
+                // commit the field
+                fieldtypes.push_back(fieldtype);
+                fieldinits.push_back(fieldinit);
+                if (fieldpad) {
+                    // match up with below
+                    std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
+                    llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
+                    fieldtypes.push_back(c->getType());
+                    fieldinits.push_back(c);
+                    idx++;
+                }
+
+                idx++;
+
+                // start new
+                lastoffset = i->first;
+                fieldtype = DtoType(i->second.var->type);
+                fieldinit = i->second.init;
+                prevsize = gTargetData->getTypeSize(fieldtype);
+                i->second.var->llvmFieldIndex = idx;
+                fieldpad = 0;
+            }
+        }
+        fieldtypes.push_back(fieldtype);
+        fieldinits.push_back(fieldinit);
+        if (fieldpad) {
+            // match up with above
+            std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
+            llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
+            fieldtypes.push_back(c->getType());
+            fieldinits.push_back(c);
+        }
+
+        Logger::println("creating struct type");
+        structtype = llvm::StructType::get(fieldtypes);
+    }
+
+    // refine abstract types for stuff like: struct S{S* next;}
+    if (gIR->topstruct().recty != 0)
+    {
+        llvm::PATypeHolder& pa = gIR->topstruct().recty;
+        llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
+        structtype = llvm::cast<llvm::StructType>(pa.get());
+    }
+
+    ts->llvmType = structtype;
+    llvmType = structtype;
+
+    if (parent->isModule()) {
+        gIR->module->addTypeName(mangle(),ts->llvmType);
+    }
+
+    // generate static data
+    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
+    llvm::Constant* _init = 0;
+
+    // always generate the constant initalizer
+    if (!zeroInit) {
+        Logger::println("Not zero initialized");
+        //assert(tk == gIR->gIR->topstruct()().size());
+        #ifndef LLVMD_NO_LOGGER
+        Logger::cout() << "struct type: " << *structtype << '\n';
+        for (size_t k=0; k<fieldinits.size(); ++k) {
+            Logger::cout() << "Type:" << '\n';
+            Logger::cout() << *fieldinits[k]->getType() << '\n';
+            Logger::cout() << "Value:" << '\n';
+            Logger::cout() << *fieldinits[k] << '\n';
+        }
+        Logger::cout() << "Initializer printed" << '\n';
+        #endif
+        llvmInitZ = llvm::ConstantStruct::get(structtype,fieldinits);
+    }
+    else {
+        Logger::println("Zero initialized");
+        llvmInitZ = llvm::ConstantAggregateZero::get(structtype);
+    }
+
+    // only provide the constant initializer for the defining module
+    if (getModule() == gIR->dmodule)
+    {
+        _init = llvmInitZ;
+    }
+
+    std::string initname("_D");
+    initname.append(mangle());
+    initname.append("6__initZ");
+    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module);
+    ts->llvmInit = initvar;
+
+    // generate member function definitions
+    gIR->topstruct().queueFuncs = false;
+    IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
+    size_t n = mfs.size();
+    for (size_t i=0; i<n; ++i) {
+        mfs[i]->toObjFile();
+    }
+
+    llvmDModule = gIR->dmodule;
+
+    gIR->structs.pop_back();
+
+    // generate typeinfo
+    if (getModule() == gIR->dmodule && llvmInternal != LLVMnotypeinfo)
+        type->getTypeInfo(NULL);
+}
+
+/* ================================================================== */
+
+static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx)
+{
+    // start at the bottom of the inheritance chain
+    if (cd->baseClass != 0) {
+        unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx);
+        if (o != (unsigned)-1)
+            return o;
+    }
+
+    // check this class
+    unsigned i;
+    for (i=0; i<cd->fields.dim; ++i) {
+        VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i];
+        if (os == vd->offset)
+            return i+idx;
+    }
+    idx += i;
+
+    return (unsigned)-1;
+}
+
+void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
+{
+    unsigned idx = 0;
+    unsigned r = LLVM_ClassOffsetToIndex(this, os, idx);
+    assert(r != (unsigned)-1 && "Offset not found in any aggregate field");
+    result.push_back(r+1); // vtable is 0
+}
+
+/* ================================================================== */
+
+static void LLVM_AddBaseClassData(BaseClasses* bcs)
+{
+    // add base class data members first
+    for (int j=0; j<bcs->dim; j++)
+    {
+        BaseClass* bc = (BaseClass*)(bcs->data[j]);
+        assert(bc);
+        Logger::println("Adding base class members of %s", bc->base->toChars());
+        LOG_SCOPE;
+
+        LLVM_AddBaseClassData(&bc->base->baseclasses);
+        for (int k=0; k < bc->base->members->dim; k++) {
+            Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]);
+            if (dsym->isVarDeclaration())
+            {
+                dsym->toObjFile();
+            }
+        }
+    }
+}
+
+void ClassDeclaration::toObjFile()
+{
+    TypeClass* ts = (TypeClass*)DtoDType(type);
+    if (ts->llvmType != 0 || llvmInProgress)
+        return;
+
+    llvmInProgress = true;
+
+    static int fdi = 0;
+    Logger::print("ClassDeclaration::toObjFile(%d): %s\n", fdi++, toChars());
+    LOG_SCOPE;
+
+    gIR->structs.push_back(IRStruct(ts));
+    gIR->classes.push_back(this);
+
+    // add vtable
+    llvm::PATypeHolder pa = llvm::OpaqueType::get();
+    const llvm::Type* vtabty = llvm::PointerType::get(pa);
+
+    std::vector<const llvm::Type*> fieldtypes;
+    fieldtypes.push_back(vtabty);
+
+    std::vector<llvm::Constant*> fieldinits;
+    fieldinits.push_back(0);
+
+    // base classes first
+    LLVM_AddBaseClassData(&baseclasses);
+
+    // then add own members
+    for (int k=0; k < members->dim; k++) {
+        Dsymbol* dsym = (Dsymbol*)(members->data[k]);
+        dsym->toObjFile();
+    }
+
+    // fill out fieldtypes/inits
+    for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
+        fieldtypes.push_back(DtoType(i->second.var->type));
+        fieldinits.push_back(i->second.init);
+    }
+
+    llvm::StructType* structtype = llvm::StructType::get(fieldtypes);
+    // refine abstract types for stuff like: class C {C next;}
+    if (gIR->topstruct().recty != 0)
+    {
+        llvm::PATypeHolder& pa = gIR->topstruct().recty;
+        llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
+        structtype = llvm::cast<llvm::StructType>(pa.get());
+    }
+
+    ts->llvmType = structtype;
+    llvmType = structtype;
+
+    bool needs_definition = false;
+    if (parent->isModule()) {
+        gIR->module->addTypeName(mangle(),ts->llvmType);
+        needs_definition = (getModule() == gIR->dmodule);
+    }
+    else {
+        assert(0 && "class parent is not a module");
+    }
+
+    // generate vtable
+    llvm::GlobalVariable* svtblVar = 0;
+    std::vector<llvm::Constant*> sinits;
+    std::vector<const llvm::Type*> sinits_ty;
+    sinits.reserve(vtbl.dim);
+    sinits_ty.reserve(vtbl.dim);
+
+    for (int k=0; k < vtbl.dim; k++)
+    {
+        Dsymbol* dsym = (Dsymbol*)vtbl.data[k];
+        assert(dsym);
+        //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
+
+        if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
+            fd->toObjFile();
+            assert(fd->llvmValue);
+            llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
+            sinits.push_back(c);
+            sinits_ty.push_back(c->getType());
+        }
+        else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
+            const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty);
+            llvm::Constant* c = llvm::Constant::getNullValue(cty);
+            sinits.push_back(c);
+            sinits_ty.push_back(cty);
+        }
+        else
+        assert(0);
+    }
+
+    const llvm::StructType* svtbl_ty = 0;
+    if (!sinits.empty())
+    {
+        llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
+
+        std::string varname("_D");
+        varname.append(mangle());
+        varname.append("6__vtblZ");
+
+        std::string styname(mangle());
+        styname.append("__vtblTy");
+
+        svtbl_ty = llvm::StructType::get(sinits_ty);
+        gIR->module->addTypeName(styname, svtbl_ty);
+        svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
+
+        llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits));
+        if (needs_definition)
+            svtblVar->setInitializer(llvmConstVtbl);
+        llvmVtbl = svtblVar;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////
+
+    // refine for final vtable type
+    llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty);
+    svtbl_ty = llvm::cast<llvm::StructType>(pa.get());
+    structtype = llvm::cast<llvm::StructType>(gIR->topstruct().recty.get());
+    ts->llvmType = structtype;
+    llvmType = structtype;
+
+    // generate initializer
+    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
+    llvm::Constant* _init = 0;
+
+    // first field is always the vtable
+    assert(svtblVar != 0);
+    fieldinits[0] = svtblVar;
+
+    llvmInitZ = _init = llvm::ConstantStruct::get(structtype,fieldinits);
+    assert(_init);
+
+    std::string initname("_D");
+    initname.append(mangle());
+    initname.append("6__initZ");
+    //Logger::cout() << *_init << '\n';
+    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, NULL, initname, gIR->module);
+    ts->llvmInit = initvar;
+
+    if (needs_definition) {
+        initvar->setInitializer(_init);
+        // generate member functions
+        gIR->topstruct().queueFuncs = false;
+        IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
+        size_t n = mfs.size();
+        for (size_t i=0; i<n; ++i) {
+            mfs[i]->toObjFile();
+        }
+    }
+
+    gIR->classes.pop_back();
+    gIR->structs.pop_back();
+
+    llvmInProgress = false;
+}
+
+/******************************************
+ * Get offset of base class's vtbl[] initializer from start of csym.
+ * Returns ~0 if not this csym.
+ */
+
+unsigned ClassDeclaration::baseVtblOffset(BaseClass *bc)
+{
+  return ~0;
+}
+
+/* ================================================================== */
+
+void VarDeclaration::toObjFile()
+{
+    Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+    llvm::Module* M = gIR->module;
+
+    if (aliassym)
+    {
+        toAlias()->toObjFile();
+        return;
+    }
+
+    // global variable or magic
+    if (isDataseg())
+    {
+        if (llvmTouched) return;
+        else llvmTouched = true;
+
+        bool _isconst = false;
+        if (isConst() && (init && !init->isExpInitializer()))
+            _isconst = true;
+
+        llvm::GlobalValue::LinkageTypes _linkage;
+        bool istempl = false;
+        if ((storage_class & STCcomdat) || (parent && DtoIsTemplateInstance(parent))) {
+            _linkage = llvm::GlobalValue::WeakLinkage;
+            istempl = true;
+        }
+        else if (parent && parent->isFuncDeclaration())
+            _linkage = llvm::GlobalValue::InternalLinkage;
+        else
+            _linkage = DtoLinkage(protection, storage_class);
+
+        Type* t = DtoDType(type);
+
+        const llvm::Type* _type = DtoType(t);
+        assert(_type);
+
+        llvm::Constant* _init = 0;
+        bool _signed = !type->isunsigned();
+
+        Logger::println("Creating global variable");
+        std::string _name(mangle());
+
+        llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M);
+        llvmValue = gvar;
+
+        if (!(storage_class & STCextern) && (getModule() == gIR->dmodule || istempl))
+        {
+            if (parent && parent->isFuncDeclaration() && init && init->isExpInitializer()) {
+                _init = DtoConstInitializer(t, NULL);
+                // create a flag to make sure initialization only happens once
+                llvm::GlobalValue::LinkageTypes gflaglink = istempl ? llvm::GlobalValue::WeakLinkage : llvm::GlobalValue::InternalLinkage;
+                std::string gflagname(_name);
+                gflagname.append("__initflag");
+                llvm::GlobalVariable* gflag = new llvm::GlobalVariable(llvm::Type::Int1Ty,false,gflaglink,DtoConstBool(false),gflagname,M);
+
+                // check flag and do init if not already done
+                llvm::BasicBlock* oldend = gIR->scopeend();
+                llvm::BasicBlock* initbb = new llvm::BasicBlock("ifnotinit",gIR->topfunc(),oldend);
+                llvm::BasicBlock* endinitbb = new llvm::BasicBlock("ifnotinitend",gIR->topfunc(),oldend);
+                llvm::Value* cond = gIR->ir->CreateICmpEQ(gIR->ir->CreateLoad(gflag,"tmp"),DtoConstBool(false));
+                gIR->ir->CreateCondBr(cond, initbb, endinitbb);
+                gIR->scope() = IRScope(initbb,endinitbb);
+                elem* ie = DtoInitializer(init);
+                if (!ie->inPlace()) {
+                    DValue* dst = new DVarValue(t, gvar, true);
+                    DtoAssign(dst, ie);
+                    delete dst;
+                }
+                gIR->ir->CreateStore(DtoConstBool(true), gflag);
+                gIR->ir->CreateBr(endinitbb);
+                gIR->scope() = IRScope(endinitbb,oldend);
+            }
+            else {
+                _init = DtoConstInitializer(t, init);
+            }
+
+            //Logger::cout() << "initializer: " << *_init << '\n';
+            if (_type != _init->getType()) {
+                Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n";
+                // zero initalizer
+                if (_init->isNullValue())
+                    _init = llvm::Constant::getNullValue(_type);
+                // pointer to global constant (struct.init)
+                else if (llvm::isa<llvm::GlobalVariable>(_init))
+                {
+                    assert(_init->getType()->getContainedType(0) == _type);
+                    llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init);
+                    assert(t->ty == Tstruct);
+                    TypeStruct* ts = (TypeStruct*)t;
+                    assert(ts->sym->llvmInitZ);
+                    _init = ts->sym->llvmInitZ;
+                }
+                // array single value init
+                else if (llvm::isa<llvm::ArrayType>(_type))
+                {
+                    _init = DtoConstStaticArray(_type, _init);
+                }
+                else {
+                    Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
+                    //assert(0);
+                }
+            }
+
+            Logger::cout() << "final init = " << *_init << '\n';
+            gvar->setInitializer(_init);
+        }
+
+        llvmDModule = gIR->dmodule;
+
+        //if (storage_class & STCprivate)
+        //    gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility);
+    }
+
+    // inside aggregate declaration. declare a field.
+    else
+    {
+        Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset);
+
+        Type* t = DtoDType(type);
+        const llvm::Type* _type = DtoType(t);
+
+        llvm::Constant*_init = DtoConstInitializer(t, init);
+        assert(_init);
+        Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n';
+        if (_type != _init->getType())
+        {
+            if (t->ty == Tsarray)
+            {
+                const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(_type);
+                uint64_t n = arrty->getNumElements();
+                std::vector<llvm::Constant*> vals(n,_init);
+                _init = llvm::ConstantArray::get(arrty, vals);
+            }
+            else if (t->ty == Tarray)
+            {
+                assert(llvm::isa<llvm::StructType>(_type));
+                _init = llvm::ConstantAggregateZero::get(_type);
+            }
+            else if (t->ty == Tstruct)
+            {
+                const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type);
+                TypeStruct* ts = (TypeStruct*)t;
+                assert(ts);
+                assert(ts->sym);
+                assert(ts->sym->llvmInitZ);
+                _init = ts->sym->llvmInitZ;
+            }
+            else if (t->ty == Tclass)
+            {
+                _init = llvm::Constant::getNullValue(_type);
+            }
+            else {
+                Logger::println("failed for type %s", type->toChars());
+                assert(0);
+            }
+        }
+
+        // add the field in the IRStruct
+        gIR->topstruct().offsets.insert(std::make_pair(offset, IRStruct::Offset(this,_init)));
+    }
+
+    Logger::println("VarDeclaration::toObjFile is done");
+}
+
+/* ================================================================== */
+
+void TypedefDeclaration::toObjFile()
+{
+    static int tdi = 0;
+    Logger::print("TypedefDeclaration::toObjFile(%d): %s\n", tdi++, toChars());
+    LOG_SCOPE;
+
+    // generate typeinfo
+    type->getTypeInfo(NULL);
+}
+
+/* ================================================================== */
+
+void EnumDeclaration::toObjFile()
+{
+    Logger::println("Ignoring EnumDeclaration::toObjFile for %s", toChars());
+}
+
+/* ================================================================== */
+
+void FuncDeclaration::toObjFile()
+{
+    if (llvmDModule) {
+        assert(llvmValue != 0);
+        return;
+    }
+
+    if (llvmRunTimeHack) {
+        Logger::println("runtime hack func chars: %s", toChars());
+        if (!llvmValue)
+            llvmValue = LLVM_D_GetRuntimeFunction(gIR->module, toChars());
+        return;
+    }
+
+    if (isUnitTestDeclaration()) {
+        Logger::println("*** ATTENTION: ignoring unittest declaration: %s", toChars());
+        return;
+    }
+
+    Type* t = DtoDType(type);
+    TypeFunction* f = (TypeFunction*)t;
+
+    bool declareOnly = false;
+    if (parent)
+    {
+    if (TemplateInstance* tinst = parent->isTemplateInstance()) {
+        TemplateDeclaration* tempdecl = tinst->tempdecl;
+        if (tempdecl->llvmInternal == LLVMva_start)
+        {
+            Logger::println("magic va_start found");
+            llvmInternal = LLVMva_start;
+            declareOnly = true;
+        }
+        else if (tempdecl->llvmInternal == LLVMva_arg)
+        {
+            Logger::println("magic va_arg found");
+            llvmInternal = LLVMva_arg;
+            return;
+        }
+    }
+    }
+
+    llvm::Function* func = DtoDeclareFunction(this);
+
+    if (declareOnly)
+        return;
+
+    if (!gIR->structs.empty() && gIR->topstruct().queueFuncs) {
+        if (!llvmQueued) {
+            Logger::println("queueing %s", toChars());
+            gIR->topstruct().funcs.push_back(this);
+            llvmQueued = true;
+        }
+        return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete
+    }
+
+    // debug info
+    if (global.params.symdebug) {
+        llvmDwarfSubProgram = DtoDwarfSubProgram(this);
+    }
+
+    assert(f->llvmType);
+    const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0));
+
+    // template instances should have weak linkage
+    if (parent && DtoIsTemplateInstance(parent)) {
+        func->setLinkage(llvm::GlobalValue::WeakLinkage);
+    }
+
+    // only members of the current module maybe be defined
+    if (getModule() == gIR->dmodule || DtoIsTemplateInstance(parent))
+    {
+        llvmDModule = gIR->dmodule;
+
+        // handle static constructor / destructor
+        if (isStaticCtorDeclaration() || isStaticDtorDeclaration()) {
+            const llvm::ArrayType* sctor_type = llvm::ArrayType::get(llvm::PointerType::get(functype),1);
+            //Logger::cout() << "static ctor type: " << *sctor_type << '\n';
+
+            llvm::Constant* sctor_func = llvm::cast<llvm::Constant>(llvmValue);
+            //Logger::cout() << "static ctor func: " << *sctor_func << '\n';
+
+            llvm::Constant* sctor_init = llvm::ConstantArray::get(sctor_type,&sctor_func,1);
+
+            //Logger::cout() << "static ctor init: " << *sctor_init << '\n';
+
+            // output the llvm.global_ctors array
+            const char* varname = isStaticCtorDeclaration() ? "_d_module_ctor_array" : "_d_module_dtor_array";
+            llvm::GlobalVariable* sctor_arr = new llvm::GlobalVariable(sctor_type, false, llvm::GlobalValue::AppendingLinkage, sctor_init, varname, gIR->module);
+        }
+
+        // function definition
+        if (fbody != 0)
+        {
+            gIR->functions.push_back(IRFunction(this));
+            gIR->func().func = func;
+
+            // first make absolutely sure the type is up to date
+            f->llvmType = llvmValue->getType()->getContainedType(0);
+
+            //Logger::cout() << "func type: " << *f->llvmType << '\n';
+
+            // this handling
+            if (f->llvmUsesThis) {
+                Logger::println("uses this");
+                if (f->llvmRetInPtr)
+                    llvmThisVar = ++func->arg_begin();
+                else
+                    llvmThisVar = func->arg_begin();
+                assert(llvmThisVar != 0);
+            }
+
+            if (isMain())
+                gIR->emitMain = true;
+
+            llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func);
+            llvm::BasicBlock* endbb = new llvm::BasicBlock("endentry",func);
+
+            //assert(gIR->scopes.empty());
+            gIR->scopes.push_back(IRScope(beginbb, endbb));
+
+                // create alloca point
+                f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb());
+                gIR->func().allocapoint = f->llvmAllocaPoint;
+
+                // give arguments storage
+                size_t n = Argument::dim(f->parameters);
+                for (int i=0; i < n; ++i) {
+                    Argument* arg = Argument::getNth(f->parameters, i);
+                    if (arg && arg->vardecl) {
+                        VarDeclaration* vd = arg->vardecl;
+                        if (!vd->llvmNeedsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))
+                            continue;
+                        llvm::Value* a = vd->llvmValue;
+                        assert(a);
+                        std::string s(a->getName());
+                        Logger::println("giving argument '%s' storage", s.c_str());
+                        s.append("_storage");
+                        llvm::Value* v = new llvm::AllocaInst(a->getType(),s,f->llvmAllocaPoint);
+                        gIR->ir->CreateStore(a,v);
+                        vd->llvmValue = v;
+                    }
+                    else {
+                        Logger::println("*** ATTENTION: some unknown argument: %s", arg ? arg->toChars() : 0);
+                    }
+                }
+
+                // debug info
+                if (global.params.symdebug) DtoDwarfFuncStart(this);
+
+                llvm::Value* parentNested = NULL;
+                if (FuncDeclaration* fd = toParent()->isFuncDeclaration()) {
+                    parentNested = fd->llvmNested;
+                }
+
+                // construct nested variables struct
+                if (!llvmNestedVars.empty() || parentNested) {
+                    std::vector<const llvm::Type*> nestTypes;
+                    int j = 0;
+                    if (parentNested) {
+                        nestTypes.push_back(parentNested->getType());
+                        j++;
+                    }
+                    for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) {
+                        VarDeclaration* vd = *i;
+                        vd->llvmNestedIndex = j++;
+                        if (vd->isParameter()) {
+                            assert(vd->llvmValue);
+                            nestTypes.push_back(vd->llvmValue->getType());
+                        }
+                        else {
+                            nestTypes.push_back(DtoType(vd->type));
+                        }
+                    }
+                    const llvm::StructType* nestSType = llvm::StructType::get(nestTypes);
+                    Logger::cout() << "nested var struct has type:" << '\n' << *nestSType;
+                    llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",f->llvmAllocaPoint);
+                    if (parentNested) {
+                        assert(llvmThisVar);
+                        llvm::Value* ptr = gIR->ir->CreateBitCast(llvmThisVar, parentNested->getType(), "tmp");
+                        gIR->ir->CreateStore(ptr, DtoGEPi(llvmNested, 0,0, "tmp"));
+                    }
+                    for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) {
+                        VarDeclaration* vd = *i;
+                        if (vd->isParameter()) {
+                            gIR->ir->CreateStore(vd->llvmValue, DtoGEPi(llvmNested, 0, vd->llvmNestedIndex, "tmp"));
+                            vd->llvmValue = llvmNested;
+                        }
+                    }
+                }
+
+                // copy _argptr to a memory location
+                if (f->linkage == LINKd && f->varargs == 1)
+                {
+                    llvm::Value* argptrmem = new llvm::AllocaInst(llvmArgPtr->getType(), "_argptrmem", gIR->topallocapoint());
+                    new llvm::StoreInst(llvmArgPtr, argptrmem, gIR->scopebb());
+                    llvmArgPtr = argptrmem;
+                }
+
+                // output function body
+                fbody->toIR(gIR);
+
+                // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement
+                // in automatically, so we do it here.
+                if (!isMain()) {
+                    if (!gIR->scopereturned()) {
+                        // pass the previous block into this block
+                        if (global.params.symdebug) DtoDwarfFuncEnd(this);
+                        if (func->getReturnType() == llvm::Type::VoidTy) {
+                            new llvm::ReturnInst(gIR->scopebb());
+                        }
+                        else {
+                            new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), gIR->scopebb());
+                        }
+                    }
+                }
+
+                // erase alloca point
+                f->llvmAllocaPoint->eraseFromParent();
+                f->llvmAllocaPoint = 0;
+                gIR->func().allocapoint = 0;
+
+            gIR->scopes.pop_back();
+
+            // get rid of the endentry block, it's never used
+            assert(!func->getBasicBlockList().empty());
+            func->getBasicBlockList().pop_back();
+
+            // if the last block is empty now, it must be unreachable or it's a bug somewhere else
+            // would be nice to figure out how to assert that this is correct
+            llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
+            if (lastbb->empty()) {
+                if (lastbb->getNumUses() == 0)
+                    lastbb->eraseFromParent();
+                else {
+                    new llvm::UnreachableInst(lastbb);
+                    /*if (func->getReturnType() == llvm::Type::VoidTy) {
+                        new llvm::ReturnInst(lastbb);
+                    }
+                    else {
+                        new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), lastbb);
+                    }*/
+                }
+            }
+
+            gIR->functions.pop_back();
+        }
+    }
+}
--- a/gen/typinf.c	Fri Nov 02 06:32:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,775 +0,0 @@
-
-
-// Copyright (c) 1999-2004 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.
-
-#include <cstdio>
-#include <cassert>
-
-#include "gen/llvm.h"
-
-#include "mars.h"
-#include "module.h"
-#include "mtype.h"
-#include "scope.h"
-#include "init.h"
-#include "expression.h"
-#include "attrib.h"
-#include "declaration.h"
-#include "template.h"
-#include "id.h"
-#include "enum.h"
-#include "import.h"
-#include "aggregate.h"
-
-#include "gen/irstate.h"
-#include "gen/logger.h"
-#include "gen/runtime.h"
-#include "gen/tollvm.h"
-#include "gen/arrays.h"
-
-/*******************************************
- * Get a canonicalized form of the TypeInfo for use with the internal
- * runtime library routines. Canonicalized in that static arrays are
- * represented as dynamic arrays, enums are represented by their
- * underlying type, etc. This reduces the number of TypeInfo's needed,
- * so we can use the custom internal ones more.
- */
-
-Expression *Type::getInternalTypeInfo(Scope *sc)
-{   TypeInfoDeclaration *tid;
-    Expression *e;
-    Type *t;
-    static TypeInfoDeclaration *internalTI[TMAX];
-
-    //printf("Type::getInternalTypeInfo() %s\n", toChars());
-    t = toBasetype();
-    switch (t->ty)
-    {
-    case Tsarray:
-        t = t->next->arrayOf(); // convert to corresponding dynamic array type
-        break;
-
-    case Tclass:
-        if (((TypeClass *)t)->sym->isInterfaceDeclaration())
-        break;
-        goto Linternal;
-
-    case Tarray:
-        if (t->next->ty != Tclass)
-        break;
-        goto Linternal;
-
-    case Tfunction:
-    case Tdelegate:
-    case Tpointer:
-    Linternal:
-        tid = internalTI[t->ty];
-        if (!tid)
-        {   tid = new TypeInfoDeclaration(t, 1);
-        internalTI[t->ty] = tid;
-        }
-        e = new VarExp(0, tid);
-        //e = e->addressOf(sc);
-        e->type = tid->type;    // do this so we don't get redundant dereference
-        return e;
-
-    default:
-        break;
-    }
-    //printf("\tcalling getTypeInfo() %s\n", t->toChars());
-    return t->getTypeInfo(sc);
-}
-
-
-/****************************************************
- * Get the exact TypeInfo.
- */
-
-Expression *Type::getTypeInfo(Scope *sc)
-{
-    Expression *e;
-    Type *t;
-
-    //printf("Type::getTypeInfo() %p, %s\n", this, toChars());
-    t = merge();    // do this since not all Type's are merge'd
-    if (!t->vtinfo)
-    {   t->vtinfo = t->getTypeInfoDeclaration();
-    assert(t->vtinfo);
-
-    /* If this has a custom implementation in std/typeinfo, then
-     * do not generate a COMDAT for it.
-     */
-    if (!t->builtinTypeInfo())
-    {   // Generate COMDAT
-        if (sc)         // if in semantic() pass
-        {   // Find module that will go all the way to an object file
-        Module *m = sc->module->importedFrom;
-        m->members->push(t->vtinfo);
-        }
-        else            // if in obj generation pass
-        {
-        t->vtinfo->toObjFile();
-        }
-    }
-    }
-    e = new VarExp(0, t->vtinfo);
-    //e = e->addressOf(sc);
-    e->type = t->vtinfo->type;      // do this so we don't get redundant dereference
-    return e;
-}
-
-enum RET TypeFunction::retStyle()
-{
-    return RETstack;
-}
-
-TypeInfoDeclaration *Type::getTypeInfoDeclaration()
-{
-    //printf("Type::getTypeInfoDeclaration() %s\n", toChars());
-    return new TypeInfoDeclaration(this, 0);
-}
-
-TypeInfoDeclaration *TypeTypedef::getTypeInfoDeclaration()
-{
-    return new TypeInfoTypedefDeclaration(this);
-}
-
-TypeInfoDeclaration *TypePointer::getTypeInfoDeclaration()
-{
-    return new TypeInfoPointerDeclaration(this);
-}
-
-TypeInfoDeclaration *TypeDArray::getTypeInfoDeclaration()
-{
-    return new TypeInfoArrayDeclaration(this);
-}
-
-TypeInfoDeclaration *TypeSArray::getTypeInfoDeclaration()
-{
-    return new TypeInfoStaticArrayDeclaration(this);
-}
-
-TypeInfoDeclaration *TypeAArray::getTypeInfoDeclaration()
-{
-    return new TypeInfoAssociativeArrayDeclaration(this);
-}
-
-TypeInfoDeclaration *TypeStruct::getTypeInfoDeclaration()
-{
-    return new TypeInfoStructDeclaration(this);
-}
-
-TypeInfoDeclaration *TypeClass::getTypeInfoDeclaration()
-{
-    if (sym->isInterfaceDeclaration())
-    return new TypeInfoInterfaceDeclaration(this);
-    else
-    return new TypeInfoClassDeclaration(this);
-}
-
-TypeInfoDeclaration *TypeEnum::getTypeInfoDeclaration()
-{
-    return new TypeInfoEnumDeclaration(this);
-}
-
-TypeInfoDeclaration *TypeFunction::getTypeInfoDeclaration()
-{
-    return new TypeInfoFunctionDeclaration(this);
-}
-
-TypeInfoDeclaration *TypeDelegate::getTypeInfoDeclaration()
-{
-    return new TypeInfoDelegateDeclaration(this);
-}
-
-TypeInfoDeclaration *TypeTuple::getTypeInfoDeclaration()
-{
-    return new TypeInfoTupleDeclaration(this);
-}
-
-
-/* ========================================================================= */
-
-/* These decide if there's an instance for them already in std.typeinfo,
- * because then the compiler doesn't need to build one.
- */
-
-int Type::builtinTypeInfo()
-{
-    return 0;
-}
-
-int TypeBasic::builtinTypeInfo()
-{
-    return 1;
-}
-
-int TypeDArray::builtinTypeInfo()
-{
-    return next->isTypeBasic() != NULL;
-}
-
-/* ========================================================================= */
-
-/***************************************
- * Create a static array of TypeInfo references
- * corresponding to an array of Expression's.
- * Used to supply hidden _arguments[] value for variadic D functions.
- */
-
-Expression *createTypeInfoArray(Scope *sc, Expression *exps[], int dim)
-{
-    assert(0);
-    return NULL;
-}
-
-/* ========================================================================= */
-
-//////////////////////////////////////////////////////////////////////////////
-//                             MAGIC   PLACE
-//////////////////////////////////////////////////////////////////////////////
-
-void TypeInfoDeclaration::toObjFile()
-{
-    if (llvmTouched) return;
-    else llvmTouched = true;
-
-    Logger::println("TypeInfoDeclaration::toObjFile()");
-    LOG_SCOPE;
-
-    Logger::println("type = '%s'", tinfo->toChars());
-    Logger::println("typeinfo mangle: %s", mangle());
-
-    // this is a declaration of a builtin __initZ var
-    if (tinfo->builtinTypeInfo()) {
-        llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangle());
-        assert(llvmValue);
-        Logger::cout() << "Got typeinfo var:" << '\n' << *llvmValue << '\n';
-    }
-    // custom typedef
-    else {
-        toDt(NULL);
-    }
-}
-
-/* ========================================================================= */
-
-void TypeInfoDeclaration::toDt(dt_t **pdt)
-{
-    assert(0 && "TypeInfoDeclaration");
-}
-
-/* ========================================================================= */
-
-void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
-{
-    Logger::println("TypeInfoTypedefDeclaration::toDt() %s", toChars());
-    LOG_SCOPE;
-
-    ClassDeclaration* base = Type::typeinfotypedef;
-    base->toObjFile();
-
-    llvm::Constant* initZ = base->llvmInitZ;
-    assert(initZ);
-    const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType());
-
-    std::vector<llvm::Constant*> sinits;
-    sinits.push_back(initZ->getOperand(0));
-
-    assert(tinfo->ty == Ttypedef);
-    TypeTypedef *tc = (TypeTypedef *)tinfo;
-    TypedefDeclaration *sd = tc->sym;
-
-    // TypeInfo base
-    //const llvm::PointerType* basept = llvm::cast<llvm::PointerType>(initZ->getOperand(1)->getType());
-    //sinits.push_back(llvm::ConstantPointerNull::get(basept));
-    Logger::println("generating base typeinfo");
-    //sd->basetype = sd->basetype->merge();
-    sd->basetype->getTypeInfo(NULL);        // generate vtinfo
-    assert(sd->basetype->vtinfo);
-    if (!sd->basetype->vtinfo->llvmValue)
-        sd->basetype->vtinfo->toObjFile();
-    assert(llvm::isa<llvm::Constant>(sd->basetype->vtinfo->llvmValue));
-    llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->basetype->vtinfo->llvmValue);
-    castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType());
-    sinits.push_back(castbase);
-
-    // char[] name
-    char *name = sd->toPrettyChars();
-    sinits.push_back(DtoConstString(name));
-    assert(sinits.back()->getType() == initZ->getOperand(2)->getType());
-
-    // void[] init
-    const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
-    if (tinfo->isZeroInit() || !sd->init) // 0 initializer, or the same as the base type
-    {
-        sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
-    }
-    else
-    {
-        llvm::Constant* ci = DtoConstInitializer(sd->basetype, sd->init);
-        std::string ciname(sd->mangle());
-        ciname.append("__init");
-        llvm::GlobalVariable* civar = new llvm::GlobalVariable(DtoType(sd->basetype),true,llvm::GlobalValue::InternalLinkage,ci,ciname,gIR->module);
-        llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(civar, initpt);
-        size_t cisize = gTargetData->getTypeSize(DtoType(sd->basetype));
-        sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
-    }
-
-    // create the symbol
-    llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
-    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module);
-
-    llvmValue = gvar;
-}
-
-/* ========================================================================= */
-
-void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
-{
-    Logger::println("TypeInfoTypedefDeclaration::toDt() %s", toChars());
-    LOG_SCOPE;
-
-    ClassDeclaration* base = Type::typeinfoenum;
-    base->toObjFile();
-
-    llvm::Constant* initZ = base->llvmInitZ;
-    assert(initZ);
-    const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType());
-
-    std::vector<llvm::Constant*> sinits;
-    sinits.push_back(initZ->getOperand(0));
-
-    assert(tinfo->ty == Tenum);
-    TypeEnum *tc = (TypeEnum *)tinfo;
-    EnumDeclaration *sd = tc->sym;
-
-    // TypeInfo base
-    //const llvm::PointerType* basept = llvm::cast<llvm::PointerType>(initZ->getOperand(1)->getType());
-    //sinits.push_back(llvm::ConstantPointerNull::get(basept));
-    Logger::println("generating base typeinfo");
-    //sd->basetype = sd->basetype->merge();
-    sd->memtype->getTypeInfo(NULL);        // generate vtinfo
-    assert(sd->memtype->vtinfo);
-    if (!sd->memtype->vtinfo->llvmValue)
-        sd->memtype->vtinfo->toObjFile();
-    assert(llvm::isa<llvm::Constant>(sd->memtype->vtinfo->llvmValue));
-    llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->memtype->vtinfo->llvmValue);
-    castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType());
-    sinits.push_back(castbase);
-
-    // char[] name
-    char *name = sd->toPrettyChars();
-    sinits.push_back(DtoConstString(name));
-    assert(sinits.back()->getType() == initZ->getOperand(2)->getType());
-
-    // void[] init
-    const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
-    if (tinfo->isZeroInit() || !sd->defaultval) // 0 initializer, or the same as the base type
-    {
-        sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
-    }
-    else
-    {
-        const llvm::Type* memty = DtoType(sd->memtype);
-        llvm::Constant* ci = llvm::ConstantInt::get(memty, sd->defaultval, !sd->memtype->isunsigned());
-        std::string ciname(sd->mangle());
-        ciname.append("__init");
-        llvm::GlobalVariable* civar = new llvm::GlobalVariable(memty,true,llvm::GlobalValue::InternalLinkage,ci,ciname,gIR->module);
-        llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(civar, initpt);
-        size_t cisize = gTargetData->getTypeSize(memty);
-        sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
-    }
-
-    // create the symbol
-    llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
-    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module);
-
-    llvmValue = gvar;
-}
-
-/* ========================================================================= */
-
-static llvm::Constant* LLVM_D_Create_TypeInfoBase(Type* basetype, TypeInfoDeclaration* tid, ClassDeclaration* cd)
-{
-    ClassDeclaration* base = cd;
-    base->toObjFile();
-
-    llvm::Constant* initZ = base->llvmInitZ;
-    assert(initZ);
-    const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType());
-
-    std::vector<llvm::Constant*> sinits;
-    sinits.push_back(initZ->getOperand(0));
-
-    // TypeInfo base
-    Logger::println("generating base typeinfo");
-    basetype->getTypeInfo(NULL);
-    assert(basetype->vtinfo);
-    if (!basetype->vtinfo->llvmValue)
-        basetype->vtinfo->toObjFile();
-    assert(llvm::isa<llvm::Constant>(basetype->vtinfo->llvmValue));
-    llvm::Constant* castbase = llvm::cast<llvm::Constant>(basetype->vtinfo->llvmValue);
-    castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType());
-    sinits.push_back(castbase);
-
-    // create the symbol
-    llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
-    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,tid->toChars(),gIR->module);
-
-    tid->llvmValue = gvar;
-}
-
-/* ========================================================================= */
-
-void TypeInfoPointerDeclaration::toDt(dt_t **pdt)
-{
-    Logger::println("TypeInfoPointerDeclaration::toDt() %s", toChars());
-    LOG_SCOPE;
-
-    assert(tinfo->ty == Tpointer);
-    TypePointer *tc = (TypePointer *)tinfo;
-
-    LLVM_D_Create_TypeInfoBase(tc->next, this, Type::typeinfopointer);
-}
-
-/* ========================================================================= */
-
-void TypeInfoArrayDeclaration::toDt(dt_t **pdt)
-{
-    Logger::println("TypeInfoArrayDeclaration::toDt() %s", toChars());
-    LOG_SCOPE;
-
-    assert(tinfo->ty == Tarray);
-    TypeDArray *tc = (TypeDArray *)tinfo;
-
-    LLVM_D_Create_TypeInfoBase(tc->next, this, Type::typeinfoarray);
-}
-
-/* ========================================================================= */
-
-void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt)
-{
-    assert(0 && "TypeInfoStaticArrayDeclaration");
-
-    /*
-    //printf("TypeInfoStaticArrayDeclaration::toDt()\n");
-    dtxoff(pdt, Type::typeinfostaticarray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_StaticArray
-    dtdword(pdt, 0);                // monitor
-
-    assert(tinfo->ty == Tsarray);
-
-    TypeSArray *tc = (TypeSArray *)tinfo;
-
-    tc->next->getTypeInfo(NULL);
-    dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type
-
-    dtdword(pdt, tc->dim->toInteger());     // length
-    */
-}
-
-/* ========================================================================= */
-
-void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt)
-{
-    assert(0 && "TypeInfoAssociativeArrayDeclaration");
-
-    /*
-    //printf("TypeInfoAssociativeArrayDeclaration::toDt()\n");
-    dtxoff(pdt, Type::typeinfoassociativearray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_AssociativeArray
-    dtdword(pdt, 0);                // monitor
-
-    assert(tinfo->ty == Taarray);
-
-    TypeAArray *tc = (TypeAArray *)tinfo;
-
-    tc->next->getTypeInfo(NULL);
-    dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type
-
-    tc->index->getTypeInfo(NULL);
-    dtxoff(pdt, tc->index->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type
-    */
-}
-
-/* ========================================================================= */
-
-void TypeInfoFunctionDeclaration::toDt(dt_t **pdt)
-{
-    Logger::println("TypeInfoFunctionDeclaration::toDt() %s", toChars());
-    LOG_SCOPE;
-
-    assert(tinfo->ty == Tfunction);
-    TypeFunction *tc = (TypeFunction *)tinfo;
-
-    LLVM_D_Create_TypeInfoBase(tc->next, this, Type::typeinfofunction);
-}
-
-/* ========================================================================= */
-
-void TypeInfoDelegateDeclaration::toDt(dt_t **pdt)
-{
-    Logger::println("TypeInfoDelegateDeclaration::toDt() %s", toChars());
-    LOG_SCOPE;
-
-    assert(tinfo->ty == Tdelegate);
-    TypeDelegate *tc = (TypeDelegate *)tinfo;
-
-    LLVM_D_Create_TypeInfoBase(tc->next->next, this, Type::typeinfodelegate);
-}
-
-/* ========================================================================= */
-
-void TypeInfoStructDeclaration::toDt(dt_t **pdt)
-{
-    Logger::println("TypeInfoStructDeclaration::toDt() %s", toChars());
-    LOG_SCOPE;
-
-    assert(tinfo->ty == Tstruct);
-    TypeStruct *tc = (TypeStruct *)tinfo;
-    StructDeclaration *sd = tc->sym;
-
-    ClassDeclaration* base = Type::typeinfostruct;
-    base->toObjFile();
-
-    const llvm::StructType* stype = llvm::cast<llvm::StructType>(base->llvmType);
-
-    std::vector<llvm::Constant*> sinits;
-    sinits.push_back(base->llvmVtbl);
-
-    // char[] name
-    char *name = sd->toPrettyChars();
-    sinits.push_back(DtoConstString(name));
-    Logger::println("************** A");
-    assert(sinits.back()->getType() == stype->getElementType(1));
-
-    // void[] init
-    const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
-    if (sd->zeroInit) // 0 initializer, or the same as the base type
-    {
-        sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
-    }
-    else
-    {
-        assert(sd->llvmInitZ);
-        size_t cisize = gTargetData->getTypeSize(tc->llvmType);
-        llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(tc->llvmInit, initpt);
-        sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
-    }
-
-    // toX functions ground work
-    FuncDeclaration *fd;
-    FuncDeclaration *fdx;
-    TypeFunction *tf;
-    Type *ta;
-    Dsymbol *s;
-
-    static TypeFunction *tftohash;
-    static TypeFunction *tftostring;
-
-    if (!tftohash)
-    {
-    Scope sc;
-
-    tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd);
-    tftohash = (TypeFunction *)tftohash->semantic(0, &sc);
-
-    tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd);
-    tftostring = (TypeFunction *)tftostring->semantic(0, &sc);
-    }
-
-    TypeFunction *tfeqptr;
-    {
-    Scope sc;
-    Arguments *arguments = new Arguments;
-    Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL);
-
-    arguments->push(arg);
-    tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
-    tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc);
-    }
-
-#if 0
-    TypeFunction *tfeq;
-    {
-    Scope sc;
-    Array *arguments = new Array;
-    Argument *arg = new Argument(In, tc, NULL, NULL);
-
-    arguments->push(arg);
-    tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
-    tfeq = (TypeFunction *)tfeq->semantic(0, &sc);
-    }
-#endif
-
-    Logger::println("************** B");
-    const llvm::PointerType* ptty = llvm::cast<llvm::PointerType>(stype->getElementType(3));
-
-    s = search_function(sd, Id::tohash);
-    fdx = s ? s->isFuncDeclaration() : NULL;
-    if (fdx)
-    {
-        fd = fdx->overloadExactMatch(tftohash);
-        if (fd) {
-            assert(fd->llvmValue != 0);
-            llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
-            assert(c);
-            c = llvm::ConstantExpr::getBitCast(c, ptty);
-            sinits.push_back(c);
-        }
-        else {
-            //fdx->error("must be declared as extern (D) uint toHash()");
-            sinits.push_back(llvm::ConstantPointerNull::get(ptty));
-        }
-    }
-    else {
-        sinits.push_back(llvm::ConstantPointerNull::get(ptty));
-    }
-
-    s = search_function(sd, Id::eq);
-    fdx = s ? s->isFuncDeclaration() : NULL;
-    for (int i = 0; i < 2; i++)
-    {
-        Logger::println("************** C %d", i);
-        ptty = llvm::cast<llvm::PointerType>(stype->getElementType(4+i));
-        if (fdx)
-        {
-            fd = fdx->overloadExactMatch(tfeqptr);
-            if (fd) {
-                assert(fd->llvmValue != 0);
-                llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
-                assert(c);
-                c = llvm::ConstantExpr::getBitCast(c, ptty);
-                sinits.push_back(c);
-            }
-            else {
-                //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars());
-                sinits.push_back(llvm::ConstantPointerNull::get(ptty));
-            }
-        }
-        else {
-            sinits.push_back(llvm::ConstantPointerNull::get(ptty));
-        }
-
-        s = search_function(sd, Id::cmp);
-        fdx = s ? s->isFuncDeclaration() : NULL;
-    }
-
-    Logger::println("************** D");
-    ptty = llvm::cast<llvm::PointerType>(stype->getElementType(6));
-    s = search_function(sd, Id::tostring);
-    fdx = s ? s->isFuncDeclaration() : NULL;
-    if (fdx)
-    {
-        fd = fdx->overloadExactMatch(tftostring);
-        if (fd) {
-            assert(fd->llvmValue != 0);
-            llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
-            assert(c);
-            c = llvm::ConstantExpr::getBitCast(c, ptty);
-            sinits.push_back(c);
-        }
-        else {
-            //fdx->error("must be declared as extern (D) char[] toString()");
-            sinits.push_back(llvm::ConstantPointerNull::get(ptty));
-        }
-    }
-    else {
-        sinits.push_back(llvm::ConstantPointerNull::get(ptty));
-    }
-
-    // uint m_flags;
-    sinits.push_back(DtoConstUint(tc->hasPointers()));
-
-    // create the symbol
-    llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
-    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module);
-
-    llvmValue = gvar;
-}
-
-/* ========================================================================= */
-
-void TypeInfoClassDeclaration::toDt(dt_t **pdt)
-{
-    assert(0 && "TypeInfoClassDeclaration");
-
-    /*
-    //printf("TypeInfoClassDeclaration::toDt() %s\n", tinfo->toChars());
-    dtxoff(pdt, Type::typeinfoclass->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoClass
-    dtdword(pdt, 0);                // monitor
-
-    assert(tinfo->ty == Tclass);
-
-    TypeClass *tc = (TypeClass *)tinfo;
-    Symbol *s;
-
-    if (!tc->sym->vclassinfo)
-    tc->sym->vclassinfo = new ClassInfoDeclaration(tc->sym);
-    s = tc->sym->vclassinfo->toSymbol();
-    dtxoff(pdt, s, 0, TYnptr);      // ClassInfo for tinfo
-    */
-}
-
-/* ========================================================================= */
-
-void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt)
-{
-    assert(0 && "TypeInfoInterfaceDeclaration");
-
-    /*
-    //printf("TypeInfoInterfaceDeclaration::toDt() %s\n", tinfo->toChars());
-    dtxoff(pdt, Type::typeinfointerface->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface
-    dtdword(pdt, 0);                // monitor
-
-    assert(tinfo->ty == Tclass);
-
-    TypeClass *tc = (TypeClass *)tinfo;
-    Symbol *s;
-
-    if (!tc->sym->vclassinfo)
-    tc->sym->vclassinfo = new ClassInfoDeclaration(tc->sym);
-    s = tc->sym->vclassinfo->toSymbol();
-    dtxoff(pdt, s, 0, TYnptr);      // ClassInfo for tinfo
-    */
-}
-
-/* ========================================================================= */
-
-void TypeInfoTupleDeclaration::toDt(dt_t **pdt)
-{
-    assert(0 && "TypeInfoTupleDeclaration");
-
-    /*
-    //printf("TypeInfoTupleDeclaration::toDt() %s\n", tinfo->toChars());
-    dtxoff(pdt, Type::typeinfotypelist->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface
-    dtdword(pdt, 0);                // monitor
-
-    assert(tinfo->ty == Ttuple);
-
-    TypeTuple *tu = (TypeTuple *)tinfo;
-
-    size_t dim = tu->arguments->dim;
-    dtdword(pdt, dim);              // elements.length
-
-    dt_t *d = NULL;
-    for (size_t i = 0; i < dim; i++)
-    {   Argument *arg = (Argument *)tu->arguments->data[i];
-    Expression *e = arg->type->getTypeInfo(NULL);
-    e = e->optimize(WANTvalue);
-    e->toDt(&d);
-    }
-
-    Symbol *s;
-    s = static_sym();
-    s->Sdt = d;
-    outdata(s);
-
-    dtxoff(pdt, s, 0, TYnptr);          // elements.ptr
-    */
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/typinf.cpp	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,775 @@
+
+
+// Copyright (c) 1999-2004 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.
+
+#include <cstdio>
+#include <cassert>
+
+#include "gen/llvm.h"
+
+#include "mars.h"
+#include "module.h"
+#include "mtype.h"
+#include "scope.h"
+#include "init.h"
+#include "expression.h"
+#include "attrib.h"
+#include "declaration.h"
+#include "template.h"
+#include "id.h"
+#include "enum.h"
+#include "import.h"
+#include "aggregate.h"
+
+#include "gen/irstate.h"
+#include "gen/logger.h"
+#include "gen/runtime.h"
+#include "gen/tollvm.h"
+#include "gen/arrays.h"
+
+/*******************************************
+ * Get a canonicalized form of the TypeInfo for use with the internal
+ * runtime library routines. Canonicalized in that static arrays are
+ * represented as dynamic arrays, enums are represented by their
+ * underlying type, etc. This reduces the number of TypeInfo's needed,
+ * so we can use the custom internal ones more.
+ */
+
+Expression *Type::getInternalTypeInfo(Scope *sc)
+{   TypeInfoDeclaration *tid;
+    Expression *e;
+    Type *t;
+    static TypeInfoDeclaration *internalTI[TMAX];
+
+    //printf("Type::getInternalTypeInfo() %s\n", toChars());
+    t = toBasetype();
+    switch (t->ty)
+    {
+    case Tsarray:
+        t = t->next->arrayOf(); // convert to corresponding dynamic array type
+        break;
+
+    case Tclass:
+        if (((TypeClass *)t)->sym->isInterfaceDeclaration())
+        break;
+        goto Linternal;
+
+    case Tarray:
+        if (t->next->ty != Tclass)
+        break;
+        goto Linternal;
+
+    case Tfunction:
+    case Tdelegate:
+    case Tpointer:
+    Linternal:
+        tid = internalTI[t->ty];
+        if (!tid)
+        {   tid = new TypeInfoDeclaration(t, 1);
+        internalTI[t->ty] = tid;
+        }
+        e = new VarExp(0, tid);
+        //e = e->addressOf(sc);
+        e->type = tid->type;    // do this so we don't get redundant dereference
+        return e;
+
+    default:
+        break;
+    }
+    //printf("\tcalling getTypeInfo() %s\n", t->toChars());
+    return t->getTypeInfo(sc);
+}
+
+
+/****************************************************
+ * Get the exact TypeInfo.
+ */
+
+Expression *Type::getTypeInfo(Scope *sc)
+{
+    Expression *e;
+    Type *t;
+
+    //printf("Type::getTypeInfo() %p, %s\n", this, toChars());
+    t = merge();    // do this since not all Type's are merge'd
+    if (!t->vtinfo)
+    {   t->vtinfo = t->getTypeInfoDeclaration();
+    assert(t->vtinfo);
+
+    /* If this has a custom implementation in std/typeinfo, then
+     * do not generate a COMDAT for it.
+     */
+    if (!t->builtinTypeInfo())
+    {   // Generate COMDAT
+        if (sc)         // if in semantic() pass
+        {   // Find module that will go all the way to an object file
+        Module *m = sc->module->importedFrom;
+        m->members->push(t->vtinfo);
+        }
+        else            // if in obj generation pass
+        {
+        t->vtinfo->toObjFile();
+        }
+    }
+    }
+    e = new VarExp(0, t->vtinfo);
+    //e = e->addressOf(sc);
+    e->type = t->vtinfo->type;      // do this so we don't get redundant dereference
+    return e;
+}
+
+enum RET TypeFunction::retStyle()
+{
+    return RETstack;
+}
+
+TypeInfoDeclaration *Type::getTypeInfoDeclaration()
+{
+    //printf("Type::getTypeInfoDeclaration() %s\n", toChars());
+    return new TypeInfoDeclaration(this, 0);
+}
+
+TypeInfoDeclaration *TypeTypedef::getTypeInfoDeclaration()
+{
+    return new TypeInfoTypedefDeclaration(this);
+}
+
+TypeInfoDeclaration *TypePointer::getTypeInfoDeclaration()
+{
+    return new TypeInfoPointerDeclaration(this);
+}
+
+TypeInfoDeclaration *TypeDArray::getTypeInfoDeclaration()
+{
+    return new TypeInfoArrayDeclaration(this);
+}
+
+TypeInfoDeclaration *TypeSArray::getTypeInfoDeclaration()
+{
+    return new TypeInfoStaticArrayDeclaration(this);
+}
+
+TypeInfoDeclaration *TypeAArray::getTypeInfoDeclaration()
+{
+    return new TypeInfoAssociativeArrayDeclaration(this);
+}
+
+TypeInfoDeclaration *TypeStruct::getTypeInfoDeclaration()
+{
+    return new TypeInfoStructDeclaration(this);
+}
+
+TypeInfoDeclaration *TypeClass::getTypeInfoDeclaration()
+{
+    if (sym->isInterfaceDeclaration())
+    return new TypeInfoInterfaceDeclaration(this);
+    else
+    return new TypeInfoClassDeclaration(this);
+}
+
+TypeInfoDeclaration *TypeEnum::getTypeInfoDeclaration()
+{
+    return new TypeInfoEnumDeclaration(this);
+}
+
+TypeInfoDeclaration *TypeFunction::getTypeInfoDeclaration()
+{
+    return new TypeInfoFunctionDeclaration(this);
+}
+
+TypeInfoDeclaration *TypeDelegate::getTypeInfoDeclaration()
+{
+    return new TypeInfoDelegateDeclaration(this);
+}
+
+TypeInfoDeclaration *TypeTuple::getTypeInfoDeclaration()
+{
+    return new TypeInfoTupleDeclaration(this);
+}
+
+
+/* ========================================================================= */
+
+/* These decide if there's an instance for them already in std.typeinfo,
+ * because then the compiler doesn't need to build one.
+ */
+
+int Type::builtinTypeInfo()
+{
+    return 0;
+}
+
+int TypeBasic::builtinTypeInfo()
+{
+    return 1;
+}
+
+int TypeDArray::builtinTypeInfo()
+{
+    return next->isTypeBasic() != NULL;
+}
+
+/* ========================================================================= */
+
+/***************************************
+ * Create a static array of TypeInfo references
+ * corresponding to an array of Expression's.
+ * Used to supply hidden _arguments[] value for variadic D functions.
+ */
+
+Expression *createTypeInfoArray(Scope *sc, Expression *exps[], int dim)
+{
+    assert(0);
+    return NULL;
+}
+
+/* ========================================================================= */
+
+//////////////////////////////////////////////////////////////////////////////
+//                             MAGIC   PLACE
+//////////////////////////////////////////////////////////////////////////////
+
+void TypeInfoDeclaration::toObjFile()
+{
+    if (llvmTouched) return;
+    else llvmTouched = true;
+
+    Logger::println("TypeInfoDeclaration::toObjFile()");
+    LOG_SCOPE;
+
+    Logger::println("type = '%s'", tinfo->toChars());
+    Logger::println("typeinfo mangle: %s", mangle());
+
+    // this is a declaration of a builtin __initZ var
+    if (tinfo->builtinTypeInfo()) {
+        llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangle());
+        assert(llvmValue);
+        Logger::cout() << "Got typeinfo var:" << '\n' << *llvmValue << '\n';
+    }
+    // custom typedef
+    else {
+        toDt(NULL);
+    }
+}
+
+/* ========================================================================= */
+
+void TypeInfoDeclaration::toDt(dt_t **pdt)
+{
+    assert(0 && "TypeInfoDeclaration");
+}
+
+/* ========================================================================= */
+
+void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
+{
+    Logger::println("TypeInfoTypedefDeclaration::toDt() %s", toChars());
+    LOG_SCOPE;
+
+    ClassDeclaration* base = Type::typeinfotypedef;
+    base->toObjFile();
+
+    llvm::Constant* initZ = base->llvmInitZ;
+    assert(initZ);
+    const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType());
+
+    std::vector<llvm::Constant*> sinits;
+    sinits.push_back(initZ->getOperand(0));
+
+    assert(tinfo->ty == Ttypedef);
+    TypeTypedef *tc = (TypeTypedef *)tinfo;
+    TypedefDeclaration *sd = tc->sym;
+
+    // TypeInfo base
+    //const llvm::PointerType* basept = llvm::cast<llvm::PointerType>(initZ->getOperand(1)->getType());
+    //sinits.push_back(llvm::ConstantPointerNull::get(basept));
+    Logger::println("generating base typeinfo");
+    //sd->basetype = sd->basetype->merge();
+    sd->basetype->getTypeInfo(NULL);        // generate vtinfo
+    assert(sd->basetype->vtinfo);
+    if (!sd->basetype->vtinfo->llvmValue)
+        sd->basetype->vtinfo->toObjFile();
+    assert(llvm::isa<llvm::Constant>(sd->basetype->vtinfo->llvmValue));
+    llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->basetype->vtinfo->llvmValue);
+    castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType());
+    sinits.push_back(castbase);
+
+    // char[] name
+    char *name = sd->toPrettyChars();
+    sinits.push_back(DtoConstString(name));
+    assert(sinits.back()->getType() == initZ->getOperand(2)->getType());
+
+    // void[] init
+    const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
+    if (tinfo->isZeroInit() || !sd->init) // 0 initializer, or the same as the base type
+    {
+        sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
+    }
+    else
+    {
+        llvm::Constant* ci = DtoConstInitializer(sd->basetype, sd->init);
+        std::string ciname(sd->mangle());
+        ciname.append("__init");
+        llvm::GlobalVariable* civar = new llvm::GlobalVariable(DtoType(sd->basetype),true,llvm::GlobalValue::InternalLinkage,ci,ciname,gIR->module);
+        llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(civar, initpt);
+        size_t cisize = gTargetData->getTypeSize(DtoType(sd->basetype));
+        sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
+    }
+
+    // create the symbol
+    llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module);
+
+    llvmValue = gvar;
+}
+
+/* ========================================================================= */
+
+void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
+{
+    Logger::println("TypeInfoTypedefDeclaration::toDt() %s", toChars());
+    LOG_SCOPE;
+
+    ClassDeclaration* base = Type::typeinfoenum;
+    base->toObjFile();
+
+    llvm::Constant* initZ = base->llvmInitZ;
+    assert(initZ);
+    const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType());
+
+    std::vector<llvm::Constant*> sinits;
+    sinits.push_back(initZ->getOperand(0));
+
+    assert(tinfo->ty == Tenum);
+    TypeEnum *tc = (TypeEnum *)tinfo;
+    EnumDeclaration *sd = tc->sym;
+
+    // TypeInfo base
+    //const llvm::PointerType* basept = llvm::cast<llvm::PointerType>(initZ->getOperand(1)->getType());
+    //sinits.push_back(llvm::ConstantPointerNull::get(basept));
+    Logger::println("generating base typeinfo");
+    //sd->basetype = sd->basetype->merge();
+    sd->memtype->getTypeInfo(NULL);        // generate vtinfo
+    assert(sd->memtype->vtinfo);
+    if (!sd->memtype->vtinfo->llvmValue)
+        sd->memtype->vtinfo->toObjFile();
+    assert(llvm::isa<llvm::Constant>(sd->memtype->vtinfo->llvmValue));
+    llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->memtype->vtinfo->llvmValue);
+    castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType());
+    sinits.push_back(castbase);
+
+    // char[] name
+    char *name = sd->toPrettyChars();
+    sinits.push_back(DtoConstString(name));
+    assert(sinits.back()->getType() == initZ->getOperand(2)->getType());
+
+    // void[] init
+    const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
+    if (tinfo->isZeroInit() || !sd->defaultval) // 0 initializer, or the same as the base type
+    {
+        sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
+    }
+    else
+    {
+        const llvm::Type* memty = DtoType(sd->memtype);
+        llvm::Constant* ci = llvm::ConstantInt::get(memty, sd->defaultval, !sd->memtype->isunsigned());
+        std::string ciname(sd->mangle());
+        ciname.append("__init");
+        llvm::GlobalVariable* civar = new llvm::GlobalVariable(memty,true,llvm::GlobalValue::InternalLinkage,ci,ciname,gIR->module);
+        llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(civar, initpt);
+        size_t cisize = gTargetData->getTypeSize(memty);
+        sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
+    }
+
+    // create the symbol
+    llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module);
+
+    llvmValue = gvar;
+}
+
+/* ========================================================================= */
+
+static llvm::Constant* LLVM_D_Create_TypeInfoBase(Type* basetype, TypeInfoDeclaration* tid, ClassDeclaration* cd)
+{
+    ClassDeclaration* base = cd;
+    base->toObjFile();
+
+    llvm::Constant* initZ = base->llvmInitZ;
+    assert(initZ);
+    const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType());
+
+    std::vector<llvm::Constant*> sinits;
+    sinits.push_back(initZ->getOperand(0));
+
+    // TypeInfo base
+    Logger::println("generating base typeinfo");
+    basetype->getTypeInfo(NULL);
+    assert(basetype->vtinfo);
+    if (!basetype->vtinfo->llvmValue)
+        basetype->vtinfo->toObjFile();
+    assert(llvm::isa<llvm::Constant>(basetype->vtinfo->llvmValue));
+    llvm::Constant* castbase = llvm::cast<llvm::Constant>(basetype->vtinfo->llvmValue);
+    castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType());
+    sinits.push_back(castbase);
+
+    // create the symbol
+    llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,tid->toChars(),gIR->module);
+
+    tid->llvmValue = gvar;
+}
+
+/* ========================================================================= */
+
+void TypeInfoPointerDeclaration::toDt(dt_t **pdt)
+{
+    Logger::println("TypeInfoPointerDeclaration::toDt() %s", toChars());
+    LOG_SCOPE;
+
+    assert(tinfo->ty == Tpointer);
+    TypePointer *tc = (TypePointer *)tinfo;
+
+    LLVM_D_Create_TypeInfoBase(tc->next, this, Type::typeinfopointer);
+}
+
+/* ========================================================================= */
+
+void TypeInfoArrayDeclaration::toDt(dt_t **pdt)
+{
+    Logger::println("TypeInfoArrayDeclaration::toDt() %s", toChars());
+    LOG_SCOPE;
+
+    assert(tinfo->ty == Tarray);
+    TypeDArray *tc = (TypeDArray *)tinfo;
+
+    LLVM_D_Create_TypeInfoBase(tc->next, this, Type::typeinfoarray);
+}
+
+/* ========================================================================= */
+
+void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt)
+{
+    assert(0 && "TypeInfoStaticArrayDeclaration");
+
+    /*
+    //printf("TypeInfoStaticArrayDeclaration::toDt()\n");
+    dtxoff(pdt, Type::typeinfostaticarray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_StaticArray
+    dtdword(pdt, 0);                // monitor
+
+    assert(tinfo->ty == Tsarray);
+
+    TypeSArray *tc = (TypeSArray *)tinfo;
+
+    tc->next->getTypeInfo(NULL);
+    dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type
+
+    dtdword(pdt, tc->dim->toInteger());     // length
+    */
+}
+
+/* ========================================================================= */
+
+void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt)
+{
+    assert(0 && "TypeInfoAssociativeArrayDeclaration");
+
+    /*
+    //printf("TypeInfoAssociativeArrayDeclaration::toDt()\n");
+    dtxoff(pdt, Type::typeinfoassociativearray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_AssociativeArray
+    dtdword(pdt, 0);                // monitor
+
+    assert(tinfo->ty == Taarray);
+
+    TypeAArray *tc = (TypeAArray *)tinfo;
+
+    tc->next->getTypeInfo(NULL);
+    dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type
+
+    tc->index->getTypeInfo(NULL);
+    dtxoff(pdt, tc->index->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type
+    */
+}
+
+/* ========================================================================= */
+
+void TypeInfoFunctionDeclaration::toDt(dt_t **pdt)
+{
+    Logger::println("TypeInfoFunctionDeclaration::toDt() %s", toChars());
+    LOG_SCOPE;
+
+    assert(tinfo->ty == Tfunction);
+    TypeFunction *tc = (TypeFunction *)tinfo;
+
+    LLVM_D_Create_TypeInfoBase(tc->next, this, Type::typeinfofunction);
+}
+
+/* ========================================================================= */
+
+void TypeInfoDelegateDeclaration::toDt(dt_t **pdt)
+{
+    Logger::println("TypeInfoDelegateDeclaration::toDt() %s", toChars());
+    LOG_SCOPE;
+
+    assert(tinfo->ty == Tdelegate);
+    TypeDelegate *tc = (TypeDelegate *)tinfo;
+
+    LLVM_D_Create_TypeInfoBase(tc->next->next, this, Type::typeinfodelegate);
+}
+
+/* ========================================================================= */
+
+void TypeInfoStructDeclaration::toDt(dt_t **pdt)
+{
+    Logger::println("TypeInfoStructDeclaration::toDt() %s", toChars());
+    LOG_SCOPE;
+
+    assert(tinfo->ty == Tstruct);
+    TypeStruct *tc = (TypeStruct *)tinfo;
+    StructDeclaration *sd = tc->sym;
+
+    ClassDeclaration* base = Type::typeinfostruct;
+    base->toObjFile();
+
+    const llvm::StructType* stype = llvm::cast<llvm::StructType>(base->llvmType);
+
+    std::vector<llvm::Constant*> sinits;
+    sinits.push_back(base->llvmVtbl);
+
+    // char[] name
+    char *name = sd->toPrettyChars();
+    sinits.push_back(DtoConstString(name));
+    Logger::println("************** A");
+    assert(sinits.back()->getType() == stype->getElementType(1));
+
+    // void[] init
+    const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
+    if (sd->zeroInit) // 0 initializer, or the same as the base type
+    {
+        sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
+    }
+    else
+    {
+        assert(sd->llvmInitZ);
+        size_t cisize = gTargetData->getTypeSize(tc->llvmType);
+        llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(tc->llvmInit, initpt);
+        sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
+    }
+
+    // toX functions ground work
+    FuncDeclaration *fd;
+    FuncDeclaration *fdx;
+    TypeFunction *tf;
+    Type *ta;
+    Dsymbol *s;
+
+    static TypeFunction *tftohash;
+    static TypeFunction *tftostring;
+
+    if (!tftohash)
+    {
+    Scope sc;
+
+    tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd);
+    tftohash = (TypeFunction *)tftohash->semantic(0, &sc);
+
+    tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd);
+    tftostring = (TypeFunction *)tftostring->semantic(0, &sc);
+    }
+
+    TypeFunction *tfeqptr;
+    {
+    Scope sc;
+    Arguments *arguments = new Arguments;
+    Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL);
+
+    arguments->push(arg);
+    tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
+    tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc);
+    }
+
+#if 0
+    TypeFunction *tfeq;
+    {
+    Scope sc;
+    Array *arguments = new Array;
+    Argument *arg = new Argument(In, tc, NULL, NULL);
+
+    arguments->push(arg);
+    tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
+    tfeq = (TypeFunction *)tfeq->semantic(0, &sc);
+    }
+#endif
+
+    Logger::println("************** B");
+    const llvm::PointerType* ptty = llvm::cast<llvm::PointerType>(stype->getElementType(3));
+
+    s = search_function(sd, Id::tohash);
+    fdx = s ? s->isFuncDeclaration() : NULL;
+    if (fdx)
+    {
+        fd = fdx->overloadExactMatch(tftohash);
+        if (fd) {
+            assert(fd->llvmValue != 0);
+            llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
+            assert(c);
+            c = llvm::ConstantExpr::getBitCast(c, ptty);
+            sinits.push_back(c);
+        }
+        else {
+            //fdx->error("must be declared as extern (D) uint toHash()");
+            sinits.push_back(llvm::ConstantPointerNull::get(ptty));
+        }
+    }
+    else {
+        sinits.push_back(llvm::ConstantPointerNull::get(ptty));
+    }
+
+    s = search_function(sd, Id::eq);
+    fdx = s ? s->isFuncDeclaration() : NULL;
+    for (int i = 0; i < 2; i++)
+    {
+        Logger::println("************** C %d", i);
+        ptty = llvm::cast<llvm::PointerType>(stype->getElementType(4+i));
+        if (fdx)
+        {
+            fd = fdx->overloadExactMatch(tfeqptr);
+            if (fd) {
+                assert(fd->llvmValue != 0);
+                llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
+                assert(c);
+                c = llvm::ConstantExpr::getBitCast(c, ptty);
+                sinits.push_back(c);
+            }
+            else {
+                //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars());
+                sinits.push_back(llvm::ConstantPointerNull::get(ptty));
+            }
+        }
+        else {
+            sinits.push_back(llvm::ConstantPointerNull::get(ptty));
+        }
+
+        s = search_function(sd, Id::cmp);
+        fdx = s ? s->isFuncDeclaration() : NULL;
+    }
+
+    Logger::println("************** D");
+    ptty = llvm::cast<llvm::PointerType>(stype->getElementType(6));
+    s = search_function(sd, Id::tostring);
+    fdx = s ? s->isFuncDeclaration() : NULL;
+    if (fdx)
+    {
+        fd = fdx->overloadExactMatch(tftostring);
+        if (fd) {
+            assert(fd->llvmValue != 0);
+            llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
+            assert(c);
+            c = llvm::ConstantExpr::getBitCast(c, ptty);
+            sinits.push_back(c);
+        }
+        else {
+            //fdx->error("must be declared as extern (D) char[] toString()");
+            sinits.push_back(llvm::ConstantPointerNull::get(ptty));
+        }
+    }
+    else {
+        sinits.push_back(llvm::ConstantPointerNull::get(ptty));
+    }
+
+    // uint m_flags;
+    sinits.push_back(DtoConstUint(tc->hasPointers()));
+
+    // create the symbol
+    llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module);
+
+    llvmValue = gvar;
+}
+
+/* ========================================================================= */
+
+void TypeInfoClassDeclaration::toDt(dt_t **pdt)
+{
+    assert(0 && "TypeInfoClassDeclaration");
+
+    /*
+    //printf("TypeInfoClassDeclaration::toDt() %s\n", tinfo->toChars());
+    dtxoff(pdt, Type::typeinfoclass->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoClass
+    dtdword(pdt, 0);                // monitor
+
+    assert(tinfo->ty == Tclass);
+
+    TypeClass *tc = (TypeClass *)tinfo;
+    Symbol *s;
+
+    if (!tc->sym->vclassinfo)
+    tc->sym->vclassinfo = new ClassInfoDeclaration(tc->sym);
+    s = tc->sym->vclassinfo->toSymbol();
+    dtxoff(pdt, s, 0, TYnptr);      // ClassInfo for tinfo
+    */
+}
+
+/* ========================================================================= */
+
+void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt)
+{
+    assert(0 && "TypeInfoInterfaceDeclaration");
+
+    /*
+    //printf("TypeInfoInterfaceDeclaration::toDt() %s\n", tinfo->toChars());
+    dtxoff(pdt, Type::typeinfointerface->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface
+    dtdword(pdt, 0);                // monitor
+
+    assert(tinfo->ty == Tclass);
+
+    TypeClass *tc = (TypeClass *)tinfo;
+    Symbol *s;
+
+    if (!tc->sym->vclassinfo)
+    tc->sym->vclassinfo = new ClassInfoDeclaration(tc->sym);
+    s = tc->sym->vclassinfo->toSymbol();
+    dtxoff(pdt, s, 0, TYnptr);      // ClassInfo for tinfo
+    */
+}
+
+/* ========================================================================= */
+
+void TypeInfoTupleDeclaration::toDt(dt_t **pdt)
+{
+    assert(0 && "TypeInfoTupleDeclaration");
+
+    /*
+    //printf("TypeInfoTupleDeclaration::toDt() %s\n", tinfo->toChars());
+    dtxoff(pdt, Type::typeinfotypelist->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface
+    dtdword(pdt, 0);                // monitor
+
+    assert(tinfo->ty == Ttuple);
+
+    TypeTuple *tu = (TypeTuple *)tinfo;
+
+    size_t dim = tu->arguments->dim;
+    dtdword(pdt, dim);              // elements.length
+
+    dt_t *d = NULL;
+    for (size_t i = 0; i < dim; i++)
+    {   Argument *arg = (Argument *)tu->arguments->data[i];
+    Expression *e = arg->type->getTypeInfo(NULL);
+    e = e->optimize(WANTvalue);
+    e->toDt(&d);
+    }
+
+    Symbol *s;
+    s = static_sym();
+    s->Sdt = d;
+    outdata(s);
+
+    dtxoff(pdt, s, 0, TYnptr);          // elements.ptr
+    */
+}
--- a/lphobos/build.sh	Fri Nov 02 06:32:32 2007 +0100
+++ b/lphobos/build.sh	Sat Nov 03 14:44:58 2007 +0100
@@ -12,7 +12,7 @@
 rebuild internal/arrays.d \
         internal/mem.d \
         internal/moduleinit.d \
-        -c -oqobj -dc=llvmdc-posix || exit 1
+        -c -oqobj -dc=llvmdc-posix -explicit || exit 1
 
 echo "compiling module init backend"
 llvm-as -f -o=obj/moduleinit_backend.bc internal/moduleinit_backend.ll || exit 1
@@ -30,18 +30,21 @@
 rebuild typeinfos2.d -c -oqobj -dc=llvmdc-posix || exit 1
 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo2.*.bc` ../lib/llvmdcore.bc || exit 1
 
+echo "compiling string foreach runtime support"
+llvmdc internal/aApply.d -c -odobj || exit 1
+llvmdc internal/aApplyR.d -c -odobj || exit 1
+llvm-link -f -o=../lib/llvmdcore.bc obj/aApply.bc obj/aApplyR.bc ../lib/llvmdcore.bc || exit 1
 
 echo "compiling llvm runtime support"
 rebuild llvmsupport.d -c -oqobj -dc=llvmdc-posix || exit
 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/llvm.*.bc` ../lib/llvmdcore.bc || exit 1
 
+echo "compiling phobos"
+rebuild phobos.d -c -oqobj -dc=llvmdc-posix || exit 1
+llvm-link -f -o=../lib/llvmdcore.bc `ls obj/std.*.bc` ../lib/llvmdcore.bc || exit 1
+
 echo "optimizing"
 opt -f -std-compile-opts -o=../lib/llvmdcore.bc ../lib/llvmdcore.bc || exit 1
 
-# build phobos
-echo "compiling phobos"
-rebuild phobos.d -c -oqobj -dc=llvmdc-posix || exit 1
-llvm-link -f -o=../lib/lphobos.bc `ls obj/std.*.bc` || exit 1
-opt -f -std-compile-opts -o=../lib/lphobos.bc ../lib/lphobos.bc || exit 1
 
 echo "SUCCESS"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/internal/aApply.d	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,410 @@
+
+/**
+ * Part of the D programming language runtime library.
+ */
+
+/*
+ *  Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
+ *  Written by Walter Bright
+ *
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, in both source and binary form, subject to the following
+ *  restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ */
+
+/* This code handles decoding UTF strings for foreach loops.
+ * There are 6 combinations of conversions between char, wchar,
+ * and dchar, and 2 of each of those.
+ */
+
+import std.utf;
+
+//debug=apply;
+
+/**********************************************
+ */
+
+// dg is D, but _aApplycd() is C
+extern (D) typedef int delegate(void *) dg_t;
+
+extern (C) int _aApplycd1(char[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycd1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {	dchar d;
+
+	d = aa[i];
+	if (d & 0x80)
+	    d = std.utf.decode(aa, i);
+	else
+	    i++;
+	result = dg(cast(void *)&d);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywd1(wchar[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywd1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {	dchar d;
+
+	d = aa[i];
+	if (d & ~0x7F)
+	    d = std.utf.decode(aa, i);
+	else
+	    i++;
+	result = dg(cast(void *)&d);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+extern (C) int _aApplycw1(char[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycw1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {	dchar d;
+	wchar w;
+
+	w = aa[i];
+	if (w & 0x80)
+	{   d = std.utf.decode(aa, i);
+	    if (d <= 0xFFFF)
+		w = cast(wchar) d;
+	    else
+	    {
+		w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+		result = dg(cast(void *)&w);
+		if (result)
+		    break;
+		w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
+	    }
+	}
+	else
+	    i++;
+	result = dg(cast(void *)&w);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywc1(wchar[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywc1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {	dchar d;
+	wchar w;
+	char c;
+
+	w = aa[i];
+	if (w & ~0x7F)
+	{
+	    char[4] buf;
+	    char[] b;
+
+	    d = std.utf.decode(aa, i);
+	    b = std.utf.toUTF8(buf, d);
+	    foreach (char c2; b)
+	    {
+		result = dg(cast(void *)&c2);
+		if (result)
+		    return result;
+	    }
+	    continue;
+	}
+	else
+	{   c = cast(char)w;
+	    i++;
+	}
+	result = dg(cast(void *)&c);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydc1(dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplydc1(), len = %d\n", aa.length);
+    foreach (dchar d; aa)
+    {
+	char c;
+
+	if (d & ~0x7F)
+	{
+	    char[4] buf;
+	    char[] b;
+
+	    b = std.utf.toUTF8(buf, d);
+	    foreach (char c2; b)
+	    {
+		result = dg(cast(void *)&c2);
+		if (result)
+		    return result;
+	    }
+	    continue;
+	}
+	else
+	{
+	    c = cast(char)d;
+	}
+	result = dg(cast(void *)&c);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydw1(dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplydw1(), len = %d\n", aa.length);
+    foreach (dchar d; aa)
+    {
+	wchar w;
+
+	if (d <= 0xFFFF)
+	    w = cast(wchar) d;
+	else
+	{
+	    w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+	    result = dg(cast(void *)&w);
+	    if (result)
+		break;
+	    w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
+	}
+	result = dg(cast(void *)&w);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+
+/****************************************************************************/
+
+// dg is D, but _aApplycd2() is C
+extern (D) typedef int delegate(void *, void *) dg2_t;
+
+extern (C) int _aApplycd2(char[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycd2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {	dchar d;
+
+	d = aa[i];
+	if (d & 0x80)
+	{
+	    n = i;
+	    d = std.utf.decode(aa, n);
+	    n -= i;
+	}
+	else
+	    n = 1;
+	result = dg(&i, cast(void *)&d);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywd2(wchar[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywd2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {	dchar d;
+
+	d = aa[i];
+	if (d & ~0x7F)
+	{
+	    n = i;
+	    d = std.utf.decode(aa, n);
+	    n -= i;
+	}
+	else
+	    n = 1;
+	result = dg(&i, cast(void *)&d);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+extern (C) int _aApplycw2(char[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycw2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {	dchar d;
+	wchar w;
+
+	w = aa[i];
+	if (w & 0x80)
+	{   n = i;
+	    d = std.utf.decode(aa, n);
+	    n -= i;
+	    if (d <= 0xFFFF)
+		w = cast(wchar) d;
+	    else
+	    {
+		w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+		result = dg(&i, cast(void *)&w);
+		if (result)
+		    break;
+		w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+	    }
+	}
+	else
+	    n = 1;
+	result = dg(&i, cast(void *)&w);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywc2(wchar[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywc2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {	dchar d;
+	wchar w;
+	char c;
+
+	w = aa[i];
+	if (w & ~0x7F)
+	{
+	    char[4] buf;
+	    char[] b;
+
+	    n = i;
+	    d = std.utf.decode(aa, n);
+	    n -= i;
+	    b = std.utf.toUTF8(buf, d);
+	    foreach (char c2; b)
+	    {
+		result = dg(&i, cast(void *)&c2);
+		if (result)
+		    return result;
+	    }
+	    continue;
+	}
+	else
+	{   c = cast(char)w;
+	    n = 1;
+	}
+	result = dg(&i, cast(void *)&c);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydc2(dchar[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplydc2(), len = %d\n", len);
+    for (i = 0; i < len; i++)
+    {	dchar d;
+	char c;
+
+	d = aa[i];
+	if (d & ~0x7F)
+	{
+	    char[4] buf;
+	    char[] b;
+
+	    b = std.utf.toUTF8(buf, d);
+	    foreach (char c2; b)
+	    {
+		result = dg(&i, cast(void *)&c2);
+		if (result)
+		    return result;
+	    }
+	    continue;
+	}
+	else
+	{   c = cast(char)d;
+	}
+	result = dg(&i, cast(void *)&c);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydw2(dchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplydw2(), len = %d\n", aa.length);
+    foreach (size_t i, dchar d; aa)
+    {
+	wchar w;
+
+	if (d <= 0xFFFF)
+	    w = cast(wchar) d;
+	else
+	{
+	    w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+	    result = dg(&i, cast(void *)&w);
+	    if (result)
+		break;
+	    w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+	}
+	result = dg(&i, cast(void *)&w);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/internal/aApplyR.d	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,977 @@
+
+/**
+ * Part of the D programming language runtime library.
+ */
+
+/*
+ *  Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
+ *  Written by Walter Bright
+ *
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, in both source and binary form, subject to the following
+ *  restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ */
+
+/* This code handles decoding UTF strings for foreach_reverse loops.
+ * There are 6 combinations of conversions between char, wchar,
+ * and dchar, and 2 of each of those.
+ */
+
+import std.utf;
+
+//debug=apply;
+
+/**********************************************/
+/* 1 argument versions */
+
+// dg is D, but _aApplyRcd() is C
+extern (D) typedef int delegate(void *) dg_t;
+
+extern (C) int _aApplyRcd1(char[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {	dchar d;
+
+	i--;
+	d = aa[i];
+	if (d & 0x80)
+	{   char c = cast(char)d;
+	    uint j;
+	    uint m = 0x3F;
+	    d = 0;
+	    while ((c & 0xC0) != 0xC0)
+	    {	if (i == 0)
+		    throw new std.utf.UtfException("Invalid UTF-8 sequence", 0);
+		i--;
+		d |= (c & 0x3F) << j;
+		j += 6;
+		m >>= 1;
+		c = aa[i];
+	    }
+	    d |= (c & m) << j;
+	}
+	result = dg(cast(void *)&d);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcd1.unittest\n");
+
+    char[] s = "hello";
+    int i;
+
+    foreach_reverse(dchar d; s)
+    {
+	switch (i)
+	{
+	    case 0:	assert(d == 'o'); break;
+	    case 1:	assert(d == 'l'); break;
+	    case 2:	assert(d == 'l'); break;
+	    case 3:	assert(d == 'e'); break;
+	    case 4:	assert(d == 'h'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(dchar d; s)
+    {
+	//printf("i = %d, d = %x\n", i, d);
+	switch (i)
+	{
+	    case 0:	assert(d == 'b'); break;
+	    case 1:	assert(d == '\U00100456'); break;
+	    case 2:	assert(d == '\u1234'); break;
+	    case 3:	assert(d == 'a'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwd1(wchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {	dchar d;
+
+	i--;
+	d = aa[i];
+	if (d >= 0xDC00 && d <= 0xDFFF)
+	{   if (i == 0)
+		throw new std.utf.UtfException("Invalid UTF-16 sequence", 0);
+	    i--;
+	    d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+	}
+	result = dg(cast(void *)&d);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwd1.unittest\n");
+
+    wchar[] s = "hello";
+    int i;
+
+    foreach_reverse(dchar d; s)
+    {
+	switch (i)
+	{
+	    case 0:	assert(d == 'o'); break;
+	    case 1:	assert(d == 'l'); break;
+	    case 2:	assert(d == 'l'); break;
+	    case 3:	assert(d == 'e'); break;
+	    case 4:	assert(d == 'h'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(dchar d; s)
+    {
+	//printf("i = %d, d = %x\n", i, d);
+	switch (i)
+	{
+	    case 0:	assert(d == 'b'); break;
+	    case 1:	assert(d == '\U00100456'); break;
+	    case 2:	assert(d == '\u1234'); break;
+	    case 3:	assert(d == 'a'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRcw1(char[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {	dchar d;
+	wchar w;
+
+	i--;
+	w = aa[i];
+	if (w & 0x80)
+	{   char c = cast(char)w;
+	    uint j;
+	    uint m = 0x3F;
+	    d = 0;
+	    while ((c & 0xC0) != 0xC0)
+	    {	if (i == 0)
+		    throw new std.utf.UtfException("Invalid UTF-8 sequence", 0);
+		i--;
+		d |= (c & 0x3F) << j;
+		j += 6;
+		m >>= 1;
+		c = aa[i];
+	    }
+	    d |= (c & m) << j;
+
+	    if (d <= 0xFFFF)
+		w = cast(wchar) d;
+	    else
+	    {
+		w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+		result = dg(cast(void *)&w);
+		if (result)
+		    break;
+		w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+	    }
+	}
+	result = dg(cast(void *)&w);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcw1.unittest\n");
+
+    char[] s = "hello";
+    int i;
+
+    foreach_reverse(wchar d; s)
+    {
+	switch (i)
+	{
+	    case 0:	assert(d == 'o'); break;
+	    case 1:	assert(d == 'l'); break;
+	    case 2:	assert(d == 'l'); break;
+	    case 3:	assert(d == 'e'); break;
+	    case 4:	assert(d == 'h'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(wchar d; s)
+    {
+	//printf("i = %d, d = %x\n", i, d);
+	switch (i)
+	{
+	    case 0:	assert(d == 'b'); break;
+	    case 1:	assert(d == 0xDBC1); break;
+	    case 2:	assert(d == 0xDC56); break;
+	    case 3:	assert(d == 0x1234); break;
+	    case 4:	assert(d == 'a'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwc1(wchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {	dchar d;
+	char c;
+
+	i--;
+	d = aa[i];
+	if (d >= 0xDC00 && d <= 0xDFFF)
+	{   if (i == 0)
+		throw new std.utf.UtfException("Invalid UTF-16 sequence", 0);
+	    i--;
+	    d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+	}
+
+	if (d & ~0x7F)
+	{
+	    char[4] buf;
+	    char[] b;
+
+	    b = std.utf.toUTF8(buf, d);
+	    foreach (char c2; b)
+	    {
+		result = dg(cast(void *)&c2);
+		if (result)
+		    return result;
+	    }
+	    continue;
+	}
+	c = cast(char)d;
+	result = dg(cast(void *)&c);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwc1.unittest\n");
+
+    wchar[] s = "hello";
+    int i;
+
+    foreach_reverse(char d; s)
+    {
+	switch (i)
+	{
+	    case 0:	assert(d == 'o'); break;
+	    case 1:	assert(d == 'l'); break;
+	    case 2:	assert(d == 'l'); break;
+	    case 3:	assert(d == 'e'); break;
+	    case 4:	assert(d == 'h'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(char d; s)
+    {
+	//printf("i = %d, d = %x\n", i, d);
+	switch (i)
+	{
+	    case 0:	assert(d == 'b'); break;
+	    case 1:	assert(d == 0xF4); break;
+	    case 2:	assert(d == 0x80); break;
+	    case 3:	assert(d == 0x91); break;
+	    case 4:	assert(d == 0x96); break;
+	    case 5:	assert(d == 0xE1); break;
+	    case 6:	assert(d == 0x88); break;
+	    case 7:	assert(d == 0xB4); break;
+	    case 8:	assert(d == 'a'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdc1(dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0;)
+    {	dchar d = aa[--i];
+	char c;
+
+	if (d & ~0x7F)
+	{
+	    char[4] buf;
+	    char[] b;
+
+	    b = std.utf.toUTF8(buf, d);
+	    foreach (char c2; b)
+	    {
+		result = dg(cast(void *)&c2);
+		if (result)
+		    return result;
+	    }
+	    continue;
+	}
+	else
+	{
+	    c = cast(char)d;
+	}
+	result = dg(cast(void *)&c);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdc1.unittest\n");
+
+    dchar[] s = "hello";
+    int i;
+
+    foreach_reverse(char d; s)
+    {
+	switch (i)
+	{
+	    case 0:	assert(d == 'o'); break;
+	    case 1:	assert(d == 'l'); break;
+	    case 2:	assert(d == 'l'); break;
+	    case 3:	assert(d == 'e'); break;
+	    case 4:	assert(d == 'h'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(char d; s)
+    {
+	//printf("i = %d, d = %x\n", i, d);
+	switch (i)
+	{
+	    case 0:	assert(d == 'b'); break;
+	    case 1:	assert(d == 0xF4); break;
+	    case 2:	assert(d == 0x80); break;
+	    case 3:	assert(d == 0x91); break;
+	    case 4:	assert(d == 0x96); break;
+	    case 5:	assert(d == 0xE1); break;
+	    case 6:	assert(d == 0x88); break;
+	    case 7:	assert(d == 0xB4); break;
+	    case 8:	assert(d == 'a'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdw1(dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {	dchar d = aa[--i];
+	wchar w;
+
+	if (d <= 0xFFFF)
+	    w = cast(wchar) d;
+	else
+	{
+	    w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+	    result = dg(cast(void *)&w);
+	    if (result)
+		break;
+	    w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+	}
+	result = dg(cast(void *)&w);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdw1.unittest\n");
+
+    dchar[] s = "hello";
+    int i;
+
+    foreach_reverse(wchar d; s)
+    {
+	switch (i)
+	{
+	    case 0:	assert(d == 'o'); break;
+	    case 1:	assert(d == 'l'); break;
+	    case 2:	assert(d == 'l'); break;
+	    case 3:	assert(d == 'e'); break;
+	    case 4:	assert(d == 'h'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(wchar d; s)
+    {
+	//printf("i = %d, d = %x\n", i, d);
+	switch (i)
+	{
+	    case 0:	assert(d == 'b'); break;
+	    case 1:	assert(d == 0xDBC1); break;
+	    case 2:	assert(d == 0xDC56); break;
+	    case 3:	assert(d == 0x1234); break;
+	    case 4:	assert(d == 'a'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+}
+
+
+/****************************************************************************/
+/* 2 argument versions */
+
+// dg is D, but _aApplyRcd2() is C
+extern (D) typedef int delegate(void *, void *) dg2_t;
+
+extern (C) int _aApplyRcd2(char[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplyRcd2(), len = %d\n", len);
+    for (i = len; i != 0; )
+    {	dchar d;
+
+	i--;
+	d = aa[i];
+	if (d & 0x80)
+	{   char c = cast(char)d;
+	    uint j;
+	    uint m = 0x3F;
+	    d = 0;
+	    while ((c & 0xC0) != 0xC0)
+	    {	if (i == 0)
+		    throw new std.utf.UtfException("Invalid UTF-8 sequence", 0);
+		i--;
+		d |= (c & 0x3F) << j;
+		j += 6;
+		m >>= 1;
+		c = aa[i];
+	    }
+	    d |= (c & m) << j;
+	}
+	result = dg(&i, cast(void *)&d);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcd2.unittest\n");
+
+    char[] s = "hello";
+    int i;
+
+    foreach_reverse(k, dchar d; s)
+    {
+	assert(k == 4 - i);
+	switch (i)
+	{
+	    case 0:	assert(d == 'o'); break;
+	    case 1:	assert(d == 'l'); break;
+	    case 2:	assert(d == 'l'); break;
+	    case 3:	assert(d == 'e'); break;
+	    case 4:	assert(d == 'h'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, dchar d; s)
+    {
+	//printf("i = %d, k = %d, d = %x\n", i, k, d);
+	switch (i)
+	{
+	    case 0:	assert(d == 'b'); assert(k == 8); break;
+	    case 1:	assert(d == '\U00100456'); assert(k == 4); break;
+	    case 2:	assert(d == '\u1234'); assert(k == 1); break;
+	    case 3:	assert(d == 'a'); assert(k == 0); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwd2(wchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {	dchar d;
+
+	i--;
+	d = aa[i];
+	if (d >= 0xDC00 && d <= 0xDFFF)
+	{   if (i == 0)
+		throw new std.utf.UtfException("Invalid UTF-16 sequence", 0);
+	    i--;
+	    d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+	}
+	result = dg(&i, cast(void *)&d);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwd2.unittest\n");
+
+    wchar[] s = "hello";
+    int i;
+
+    foreach_reverse(k, dchar d; s)
+    {
+	//printf("i = %d, k = %d, d = %x\n", i, k, d);
+	assert(k == 4 - i);
+	switch (i)
+	{
+	    case 0:	assert(d == 'o'); break;
+	    case 1:	assert(d == 'l'); break;
+	    case 2:	assert(d == 'l'); break;
+	    case 3:	assert(d == 'e'); break;
+	    case 4:	assert(d == 'h'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, dchar d; s)
+    {
+	//printf("i = %d, k = %d, d = %x\n", i, k, d);
+	switch (i)
+	{
+	    case 0:	assert(k == 4); assert(d == 'b'); break;
+	    case 1:	assert(k == 2); assert(d == '\U00100456'); break;
+	    case 2:	assert(k == 1); assert(d == '\u1234'); break;
+	    case 3:	assert(k == 0); assert(d == 'a'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRcw2(char[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {	dchar d;
+	wchar w;
+
+	i--;
+	w = aa[i];
+	if (w & 0x80)
+	{   char c = cast(char)w;
+	    uint j;
+	    uint m = 0x3F;
+	    d = 0;
+	    while ((c & 0xC0) != 0xC0)
+	    {	if (i == 0)
+		    throw new std.utf.UtfException("Invalid UTF-8 sequence", 0);
+		i--;
+		d |= (c & 0x3F) << j;
+		j += 6;
+		m >>= 1;
+		c = aa[i];
+	    }
+	    d |= (c & m) << j;
+
+	    if (d <= 0xFFFF)
+		w = cast(wchar) d;
+	    else
+	    {
+		w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+		result = dg(&i, cast(void *)&w);
+		if (result)
+		    break;
+		w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+	    }
+	}
+	result = dg(&i, cast(void *)&w);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcw2.unittest\n");
+
+    char[] s = "hello";
+    int i;
+
+    foreach_reverse(k, wchar d; s)
+    {
+	//printf("i = %d, k = %d, d = %x\n", i, k, d);
+	assert(k == 4 - i);
+	switch (i)
+	{
+	    case 0:	assert(d == 'o'); break;
+	    case 1:	assert(d == 'l'); break;
+	    case 2:	assert(d == 'l'); break;
+	    case 3:	assert(d == 'e'); break;
+	    case 4:	assert(d == 'h'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, wchar d; s)
+    {
+	//printf("i = %d, k = %d, d = %x\n", i, k, d);
+	switch (i)
+	{
+	    case 0:	assert(k == 8); assert(d == 'b'); break;
+	    case 1:	assert(k == 4); assert(d == 0xDBC1); break;
+	    case 2:	assert(k == 4); assert(d == 0xDC56); break;
+	    case 3:	assert(k == 1); assert(d == 0x1234); break;
+	    case 4:	assert(k == 0); assert(d == 'a'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwc2(wchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {	dchar d;
+	char c;
+
+	i--;
+	d = aa[i];
+	if (d >= 0xDC00 && d <= 0xDFFF)
+	{   if (i == 0)
+		throw new std.utf.UtfException("Invalid UTF-16 sequence", 0);
+	    i--;
+	    d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+	}
+
+	if (d & ~0x7F)
+	{
+	    char[4] buf;
+	    char[] b;
+
+	    b = std.utf.toUTF8(buf, d);
+	    foreach (char c2; b)
+	    {
+		result = dg(&i, cast(void *)&c2);
+		if (result)
+		    return result;
+	    }
+	    continue;
+	}
+	c = cast(char)d;
+	result = dg(&i, cast(void *)&c);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwc2.unittest\n");
+
+    wchar[] s = "hello";
+    int i;
+
+    foreach_reverse(k, char d; s)
+    {
+	//printf("i = %d, k = %d, d = %x\n", i, k, d);
+	assert(k == 4 - i);
+	switch (i)
+	{
+	    case 0:	assert(d == 'o'); break;
+	    case 1:	assert(d == 'l'); break;
+	    case 2:	assert(d == 'l'); break;
+	    case 3:	assert(d == 'e'); break;
+	    case 4:	assert(d == 'h'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, char d; s)
+    {
+	//printf("i = %d, k = %d, d = %x\n", i, k, d);
+	switch (i)
+	{
+	    case 0:	assert(k == 4); assert(d == 'b'); break;
+	    case 1:	assert(k == 2); assert(d == 0xF4); break;
+	    case 2:	assert(k == 2); assert(d == 0x80); break;
+	    case 3:	assert(k == 2); assert(d == 0x91); break;
+	    case 4:	assert(k == 2); assert(d == 0x96); break;
+	    case 5:	assert(k == 1); assert(d == 0xE1); break;
+	    case 6:	assert(k == 1); assert(d == 0x88); break;
+	    case 7:	assert(k == 1); assert(d == 0xB4); break;
+	    case 8:	assert(k == 0); assert(d == 'a'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdc2(dchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {	dchar d = aa[--i];
+	char c;
+
+	if (d & ~0x7F)
+	{
+	    char[4] buf;
+	    char[] b;
+
+	    b = std.utf.toUTF8(buf, d);
+	    foreach (char c2; b)
+	    {
+		result = dg(&i, cast(void *)&c2);
+		if (result)
+		    return result;
+	    }
+	    continue;
+	}
+	else
+	{   c = cast(char)d;
+	}
+	result = dg(&i, cast(void *)&c);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdc2.unittest\n");
+
+    dchar[] s = "hello";
+    int i;
+
+    foreach_reverse(k, char d; s)
+    {
+	//printf("i = %d, k = %d, d = %x\n", i, k, d);
+	assert(k == 4 - i);
+	switch (i)
+	{
+	    case 0:	assert(d == 'o'); break;
+	    case 1:	assert(d == 'l'); break;
+	    case 2:	assert(d == 'l'); break;
+	    case 3:	assert(d == 'e'); break;
+	    case 4:	assert(d == 'h'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, char d; s)
+    {
+	//printf("i = %d, k = %d, d = %x\n", i, k, d);
+	switch (i)
+	{
+	    case 0:	assert(k == 3); assert(d == 'b'); break;
+	    case 1:	assert(k == 2); assert(d == 0xF4); break;
+	    case 2:	assert(k == 2); assert(d == 0x80); break;
+	    case 3:	assert(k == 2); assert(d == 0x91); break;
+	    case 4:	assert(k == 2); assert(d == 0x96); break;
+	    case 5:	assert(k == 1); assert(d == 0xE1); break;
+	    case 6:	assert(k == 1); assert(d == 0x88); break;
+	    case 7:	assert(k == 1); assert(d == 0xB4); break;
+	    case 8:	assert(k == 0); assert(d == 'a'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdw2(dchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {	dchar d = aa[--i];
+	wchar w;
+
+	if (d <= 0xFFFF)
+	    w = cast(wchar) d;
+	else
+	{
+	    w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+	    result = dg(&i, cast(void *)&w);
+	    if (result)
+		break;
+	    w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+	}
+	result = dg(&i, cast(void *)&w);
+	if (result)
+	    break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdw2.unittest\n");
+
+    dchar[] s = "hello";
+    int i;
+
+    foreach_reverse(k, wchar d; s)
+    {
+	//printf("i = %d, k = %d, d = %x\n", i, k, d);
+	assert(k == 4 - i);
+	switch (i)
+	{
+	    case 0:	assert(d == 'o'); break;
+	    case 1:	assert(d == 'l'); break;
+	    case 2:	assert(d == 'l'); break;
+	    case 3:	assert(d == 'e'); break;
+	    case 4:	assert(d == 'h'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, wchar d; s)
+    {
+	//printf("i = %d, k = %d, d = %x\n", i, k, d);
+	switch (i)
+	{
+	    case 0:	assert(k == 3); assert(d == 'b'); break;
+	    case 1:	assert(k == 2); assert(d == 0xDBC1); break;
+	    case 2:	assert(k == 2); assert(d == 0xDC56); break;
+	    case 3:	assert(k == 1); assert(d == 0x1234); break;
+	    case 4:	assert(k == 0); assert(d == 'a'); break;
+	    default:	assert(0);
+	}
+	i++;
+    }
+    assert(i == 5);
+}
+
+
--- a/lphobos/internal/objectimpl.d	Fri Nov 02 06:32:32 2007 +0100
+++ b/lphobos/internal/objectimpl.d	Sat Nov 03 14:44:58 2007 +0100
@@ -1135,6 +1135,12 @@
     this.msg = msg;
     }
 
+    void print()
+    {
+    char[] s = toString();
+    printf("%.*s\n", s.length, s.ptr);
+    }
+
     char[] toString() { return msg; }
 }
 
--- a/lphobos/phobos.d	Fri Nov 02 06:32:32 2007 +0100
+++ b/lphobos/phobos.d	Sat Nov 03 14:44:58 2007 +0100
@@ -1,5 +1,9 @@
 module phobos;
 
 import
+std.array,
+std.ctype,
 std.stdio,
-std.stdarg;
+std.stdarg,
+std.uni,
+std.utf;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/std/array.d	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,38 @@
+
+module std.array;
+
+private import std.c.stdio;
+
+class ArrayBoundsError : Error
+{
+  private:
+
+    uint linnum;
+    char[] filename;
+
+  public:
+    this(char[] filename, uint linnum)
+    {
+	this.linnum = linnum;
+	this.filename = filename;
+
+	char[] buffer = new char[19 + filename.length + linnum.sizeof * 3 + 1];
+	int len;
+	len = sprintf(buffer.ptr, "ArrayBoundsError %.*s(%u)", filename, linnum);
+	super(buffer[0..len]);
+    }
+}
+
+
+/********************************************
+ * Called by the compiler generated module assert function.
+ * Builds an ArrayBoundsError exception and throws it.
+ */
+
+extern (C) static void _d_array_bounds(char[] filename, uint line)
+{
+    //printf("_d_assert(%s, %d)\n", (char *)filename, line);
+    ArrayBoundsError a = new ArrayBoundsError(filename, line);
+    //printf("assertion %p created\n", a);
+    throw a;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/std/ctype.d	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,154 @@
+/*
+ * Placed into the Public Domain.
+ * Digital Mars, www.digitalmars.com
+ * Written by Walter Bright
+ */
+
+/**
+ * Simple ASCII character classification functions.
+ * For Unicode classification, see $(LINK2 std_uni.html, std.uni).
+ * References:
+ *	$(LINK2 http://www.digitalmars.com/d/ascii-table.html, ASCII Table),
+ *	$(LINK2 http://en.wikipedia.org/wiki/Ascii, Wikipedia)
+ * Macros:
+ *	WIKI=Phobos/StdCtype
+ */
+
+module std.ctype;
+
+/**
+ * Returns !=0 if c is a letter in the range (0..9, a..z, A..Z).
+ */
+int isalnum(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG) : 0; }
+
+/**
+ * Returns !=0 if c is an ascii upper or lower case letter.
+ */
+int isalpha(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_ALP)      : 0; }
+
+/**
+ * Returns !=0 if c is a control character.
+ */
+int iscntrl(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_CTL)      : 0; }
+
+/**
+ * Returns !=0 if c is a digit.
+ */
+int isdigit(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_DIG)      : 0; }
+
+/**
+ * Returns !=0 if c is lower case ascii letter.
+ */
+int islower(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_LC)       : 0; }
+
+/**
+ * Returns !=0 if c is a punctuation character.
+ */
+int ispunct(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_PNC)      : 0; }
+
+/**
+ * Returns !=0 if c is a space, tab, vertical tab, form feed,
+ * carriage return, or linefeed.
+ */
+int isspace(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_SPC)      : 0; }
+
+/**
+ * Returns !=0 if c is an upper case ascii character.
+ */
+int isupper(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_UC)       : 0; }
+
+/**
+ * Returns !=0 if c is a hex digit (0..9, a..f, A..F).
+ */
+int isxdigit(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_HEX)      : 0; }
+
+/**
+ * Returns !=0 if c is a printing character except for the space character.
+ */
+int isgraph(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC) : 0; }
+
+/**
+ * Returns !=0 if c is a printing character including the space character.
+ */
+int isprint(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC|_BLK) : 0; }
+
+/**
+ * Returns !=0 if c is in the ascii character set, i.e. in the range 0..0x7F.
+ */
+int isascii(dchar c)  { return c <= 0x7F; }
+
+
+/**
+ * If c is an upper case ascii character,
+ * return the lower case equivalent, otherwise return c.
+ */
+dchar tolower(dchar c)
+    out (result)
+    {
+	assert(!isupper(result));
+    }
+    body
+    {
+	return isupper(c) ? c + (cast(dchar)'a' - 'A') : c;
+    }
+
+
+/**
+ * If c is a lower case ascii character,
+ * return the upper case equivalent, otherwise return c.
+ */
+dchar toupper(dchar c)
+    out (result)
+    {
+	assert(!islower(result));
+    }
+    body
+    {
+	return islower(c) ? c - (cast(dchar)'a' - 'A') : c;
+    }
+
+private:
+
+enum
+{
+    _SPC =	8,
+    _CTL =	0x20,
+    _BLK =	0x40,
+    _HEX =	0x80,
+    _UC  =	1,
+    _LC  =	2,
+    _PNC =	0x10,
+    _DIG =	4,
+    _ALP =	_UC|_LC,
+}
+
+ubyte _ctype[128] =
+[
+	_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
+	_CTL,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL,_CTL,
+	_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
+	_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
+	_SPC|_BLK,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
+	_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
+	_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
+	_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
+	_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
+	_PNC,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC,
+	_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
+	_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
+	_UC,_UC,_UC,_PNC,_PNC,_PNC,_PNC,_PNC,
+	_PNC,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC,
+	_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
+	_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
+	_LC,_LC,_LC,_PNC,_PNC,_PNC,_PNC,_CTL
+];
+
+
+unittest
+{
+    assert(isspace(' '));
+    assert(!isspace('z'));
+    assert(toupper('a') == 'A');
+    assert(tolower('Q') == 'q');
+    assert(!isxdigit('G'));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/std/uni.d	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,630 @@
+
+// Written in the D programming language.
+
+/*
+ * Placed into the Public Domain.
+ * Digital Mars, www.digitalmars.com
+ * Written by Walter Bright
+ */
+
+/**
+ * Simple Unicode character classification functions.
+ * For ASCII classification, see $(LINK2 std_ctype.html, std.ctype).
+ * Macros:
+ *	WIKI=Phobos/StdUni
+ * References:
+ *	$(LINK2 http://www.digitalmars.com/d/ascii-table.html, ASCII Table),
+ *	$(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia),
+ *	$(LINK2 http://www.unicode.org, The Unicode Consortium)
+ * Trademarks:
+ *	Unicode(tm) is a trademark of Unicode, Inc.
+ */
+
+
+module std.uni;
+
+/**
+ * Returns !=0 if c is a Unicode lower case character.
+ */
+int isUniLower(dchar c)
+{
+    if (c <= 0x7F)
+	return (c >= 'a' && c <= 'z');
+
+    return isUniAlpha(c) && c == toUniLower(c);
+}
+
+/**
+ * Returns !=0 if c is a Unicode upper case character.
+ */
+int isUniUpper(dchar c)
+{
+    if (c <= 0x7F)
+	return (c >= 'A' && c <= 'Z');
+
+    return isUniAlpha(c) && c == toUniUpper(c);
+}
+
+/**
+ * If c is a Unicode upper case character, return the lower case
+ * equivalent, otherwise return c.
+ */
+dchar toUniLower(dchar c)
+{
+    if (c >= 'A' && c <= 'Z')
+    {
+        c += 32;
+    }
+    else if (c >= 0x00C0)
+    {
+	if ((c >= 0x00C0 && c <= 0x00D6) || (c >= 0x00D8 && c<=0x00DE))
+	{
+	    c += 32;
+	}
+	else if ((c >= 0x0100 && c < 0x0138) || (c > 0x0149 && c < 0x0178))
+	{
+	    if (c == 0x0130)
+		c = 0x0069;
+	    else if ((c & 1) == 0)
+		c += 1;
+	}
+	else if (c == 0x0178)
+	{
+	    c = 0x00FF;
+	}
+	else if ((c >= 0x0139 && c < 0x0149) || (c > 0x0178 && c < 0x017F))
+	{
+	    if (c & 1)
+		c += 1;
+	}
+	else if (c >= 0x0200 && c <= 0x0217)
+	{
+	    if ((c & 1) == 0)
+		c += 1;
+	}
+	else if ((c >= 0x0401 && c <= 0x040C) || (c>= 0x040E && c <= 0x040F))
+	{
+	    c += 80;
+	}
+	else if (c >= 0x0410  && c <= 0x042F)
+	{
+	    c += 32;
+	}
+	else if (c >= 0x0460 && c <= 0x047F)
+	{
+	    if ((c & 1) == 0)
+		c += 1;
+	}
+	else if (c >= 0x0531 && c <= 0x0556)
+	{
+	    c += 48;
+	}
+	else if (c >= 0x10A0 && c <= 0x10C5)
+	{
+	    c += 48;
+	}
+	else if (c >= 0xFF21 && c <= 0xFF3A)
+	{
+	    c += 32;
+	}
+    }
+    return c;
+}
+
+/**
+ * If c is a Unicode lower case character, return the upper case
+ * equivalent, otherwise return c.
+ */
+dchar toUniUpper(dchar c)
+{
+    if (c >= 'a' && c <= 'z')
+    {
+	c -= 32;
+    }
+    else if (c >= 0x00E0)
+    {
+	if ((c >= 0x00E0 && c <= 0x00F6) || (c >= 0x00F8 && c <= 0x00FE))
+	{
+	    c -= 32;
+	}
+	else if (c == 0x00FF)
+	{
+	    c = 0x0178;
+	}
+	else if ((c >= 0x0100 && c < 0x0138) || (c > 0x0149 && c < 0x0178))
+	{
+	    if (c == 0x0131)
+		c = 0x0049;
+	    else if (c & 1)
+		c -= 1;
+	}
+	else if ((c >= 0x0139 && c < 0x0149) || (c > 0x0178 && c < 0x017F))
+	{
+	    if ((c & 1) == 0)
+		c = c-1;
+	}
+	else if (c == 0x017F)
+	{
+	    c = 0x0053;
+	}
+	else if (c >= 0x0200 && c <= 0x0217)
+	{
+	    if (c & 1)
+		c = c-1;
+	}
+	else if (c >= 0x0430 && c<= 0x044F)
+	{
+	    c -= 32;
+	}
+	else if ((c >= 0x0451 && c <= 0x045C) || (c >=0x045E && c<= 0x045F))
+	{
+	    c -= 80;
+	}
+	else if (c >= 0x0460 && c <= 0x047F)
+	{
+	    if (c & 1)
+		c -= 1;
+	}
+	else if (c >= 0x0561 && c < 0x0587)
+	{
+	    c -= 48;
+	}
+	else if (c >= 0xFF41 && c <= 0xFF5A)
+	{
+	    c -= 32;
+	}
+    }
+    return c;
+}
+
+
+/*******************************
+ * Return !=0 if u is a Unicode alpha character.
+ * (general Unicode category: Lu, Ll, Lt, Lm and Lo)
+ *
+ * Standards: Unicode 5.0.0
+ */
+
+int isUniAlpha(dchar u)
+{
+    static dchar table[][2] =
+    [
+	[ 'A', 'Z' ],
+	[ 'a', 'z' ],
+	[ 0x00AA, 0x00AA ],
+	[ 0x00B5, 0x00B5 ],
+	[ 0x00BA, 0x00BA ],
+	[ 0x00C0, 0x00D6 ],
+	[ 0x00D8, 0x00F6 ],
+	[ 0x00F8, 0x02C1 ],
+	[ 0x02C6, 0x02D1 ],
+	[ 0x02E0, 0x02E4 ],
+	[ 0x02EE, 0x02EE ],
+	[ 0x037A, 0x037D ],
+	[ 0x0386, 0x0386 ],
+	[ 0x0388, 0x038A ],
+	[ 0x038C, 0x038C ],
+	[ 0x038E, 0x03A1 ],
+	[ 0x03A3, 0x03CE ],
+	[ 0x03D0, 0x03F5 ],
+	[ 0x03F7, 0x0481 ],
+	[ 0x048A, 0x0513 ],
+	[ 0x0531, 0x0556 ],
+	[ 0x0559, 0x0559 ],
+	[ 0x0561, 0x0587 ],
+	[ 0x05D0, 0x05EA ],
+	[ 0x05F0, 0x05F2 ],
+	[ 0x0621, 0x063A ],
+	[ 0x0640, 0x064A ],
+	[ 0x066E, 0x066F ],
+	[ 0x0671, 0x06D3 ],
+	[ 0x06D5, 0x06D5 ],
+	[ 0x06E5, 0x06E6 ],
+	[ 0x06EE, 0x06EF ],
+	[ 0x06FA, 0x06FC ],
+	[ 0x06FF, 0x06FF ],
+	[ 0x0710, 0x0710 ],
+	[ 0x0712, 0x072F ],
+	[ 0x074D, 0x076D ],
+	[ 0x0780, 0x07A5 ],
+	[ 0x07B1, 0x07B1 ],
+	[ 0x07CA, 0x07EA ],
+	[ 0x07F4, 0x07F5 ],
+	[ 0x07FA, 0x07FA ],
+	[ 0x0904, 0x0939 ],
+	[ 0x093D, 0x093D ],
+	[ 0x0950, 0x0950 ],
+	[ 0x0958, 0x0961 ],
+	[ 0x097B, 0x097F ],
+	[ 0x0985, 0x098C ],
+	[ 0x098F, 0x0990 ],
+	[ 0x0993, 0x09A8 ],
+	[ 0x09AA, 0x09B0 ],
+	[ 0x09B2, 0x09B2 ],
+	[ 0x09B6, 0x09B9 ],
+	[ 0x09BD, 0x09BD ],
+	[ 0x09CE, 0x09CE ],
+	[ 0x09DC, 0x09DD ],
+	[ 0x09DF, 0x09E1 ],
+	[ 0x09F0, 0x09F1 ],
+	[ 0x0A05, 0x0A0A ],
+	[ 0x0A0F, 0x0A10 ],
+	[ 0x0A13, 0x0A28 ],
+	[ 0x0A2A, 0x0A30 ],
+	[ 0x0A32, 0x0A33 ],
+	[ 0x0A35, 0x0A36 ],
+	[ 0x0A38, 0x0A39 ],
+	[ 0x0A59, 0x0A5C ],
+	[ 0x0A5E, 0x0A5E ],
+	[ 0x0A72, 0x0A74 ],
+	[ 0x0A85, 0x0A8D ],
+	[ 0x0A8F, 0x0A91 ],
+	[ 0x0A93, 0x0AA8 ],
+	[ 0x0AAA, 0x0AB0 ],
+	[ 0x0AB2, 0x0AB3 ],
+	[ 0x0AB5, 0x0AB9 ],
+	[ 0x0ABD, 0x0ABD ],
+	[ 0x0AD0, 0x0AD0 ],
+	[ 0x0AE0, 0x0AE1 ],
+	[ 0x0B05, 0x0B0C ],
+	[ 0x0B0F, 0x0B10 ],
+	[ 0x0B13, 0x0B28 ],
+	[ 0x0B2A, 0x0B30 ],
+	[ 0x0B32, 0x0B33 ],
+	[ 0x0B35, 0x0B39 ],
+	[ 0x0B3D, 0x0B3D ],
+	[ 0x0B5C, 0x0B5D ],
+	[ 0x0B5F, 0x0B61 ],
+	[ 0x0B71, 0x0B71 ],
+	[ 0x0B83, 0x0B83 ],
+	[ 0x0B85, 0x0B8A ],
+	[ 0x0B8E, 0x0B90 ],
+	[ 0x0B92, 0x0B95 ],
+	[ 0x0B99, 0x0B9A ],
+	[ 0x0B9C, 0x0B9C ],
+	[ 0x0B9E, 0x0B9F ],
+	[ 0x0BA3, 0x0BA4 ],
+	[ 0x0BA8, 0x0BAA ],
+	[ 0x0BAE, 0x0BB9 ],
+	[ 0x0C05, 0x0C0C ],
+	[ 0x0C0E, 0x0C10 ],
+	[ 0x0C12, 0x0C28 ],
+	[ 0x0C2A, 0x0C33 ],
+	[ 0x0C35, 0x0C39 ],
+	[ 0x0C60, 0x0C61 ],
+	[ 0x0C85, 0x0C8C ],
+	[ 0x0C8E, 0x0C90 ],
+	[ 0x0C92, 0x0CA8 ],
+	[ 0x0CAA, 0x0CB3 ],
+	[ 0x0CB5, 0x0CB9 ],
+	[ 0x0CBD, 0x0CBD ],
+	[ 0x0CDE, 0x0CDE ],
+	[ 0x0CE0, 0x0CE1 ],
+	[ 0x0D05, 0x0D0C ],
+	[ 0x0D0E, 0x0D10 ],
+	[ 0x0D12, 0x0D28 ],
+	[ 0x0D2A, 0x0D39 ],
+	[ 0x0D60, 0x0D61 ],
+	[ 0x0D85, 0x0D96 ],
+	[ 0x0D9A, 0x0DB1 ],
+	[ 0x0DB3, 0x0DBB ],
+	[ 0x0DBD, 0x0DBD ],
+	[ 0x0DC0, 0x0DC6 ],
+	[ 0x0E01, 0x0E30 ],
+	[ 0x0E32, 0x0E33 ],
+	[ 0x0E40, 0x0E46 ],
+	[ 0x0E81, 0x0E82 ],
+	[ 0x0E84, 0x0E84 ],
+	[ 0x0E87, 0x0E88 ],
+	[ 0x0E8A, 0x0E8A ],
+	[ 0x0E8D, 0x0E8D ],
+	[ 0x0E94, 0x0E97 ],
+	[ 0x0E99, 0x0E9F ],
+	[ 0x0EA1, 0x0EA3 ],
+	[ 0x0EA5, 0x0EA5 ],
+	[ 0x0EA7, 0x0EA7 ],
+	[ 0x0EAA, 0x0EAB ],
+	[ 0x0EAD, 0x0EB0 ],
+	[ 0x0EB2, 0x0EB3 ],
+	[ 0x0EBD, 0x0EBD ],
+	[ 0x0EC0, 0x0EC4 ],
+	[ 0x0EC6, 0x0EC6 ],
+	[ 0x0EDC, 0x0EDD ],
+	[ 0x0F00, 0x0F00 ],
+	[ 0x0F40, 0x0F47 ],
+	[ 0x0F49, 0x0F6A ],
+	[ 0x0F88, 0x0F8B ],
+	[ 0x1000, 0x1021 ],
+	[ 0x1023, 0x1027 ],
+	[ 0x1029, 0x102A ],
+	[ 0x1050, 0x1055 ],
+	[ 0x10A0, 0x10C5 ],
+	[ 0x10D0, 0x10FA ],
+	[ 0x10FC, 0x10FC ],
+	[ 0x1100, 0x1159 ],
+	[ 0x115F, 0x11A2 ],
+	[ 0x11A8, 0x11F9 ],
+	[ 0x1200, 0x1248 ],
+	[ 0x124A, 0x124D ],
+	[ 0x1250, 0x1256 ],
+	[ 0x1258, 0x1258 ],
+	[ 0x125A, 0x125D ],
+	[ 0x1260, 0x1288 ],
+	[ 0x128A, 0x128D ],
+	[ 0x1290, 0x12B0 ],
+	[ 0x12B2, 0x12B5 ],
+	[ 0x12B8, 0x12BE ],
+	[ 0x12C0, 0x12C0 ],
+	[ 0x12C2, 0x12C5 ],
+	[ 0x12C8, 0x12D6 ],
+	[ 0x12D8, 0x1310 ],
+	[ 0x1312, 0x1315 ],
+	[ 0x1318, 0x135A ],
+	[ 0x1380, 0x138F ],
+	[ 0x13A0, 0x13F4 ],
+	[ 0x1401, 0x166C ],
+	[ 0x166F, 0x1676 ],
+	[ 0x1681, 0x169A ],
+	[ 0x16A0, 0x16EA ],
+	[ 0x1700, 0x170C ],
+	[ 0x170E, 0x1711 ],
+	[ 0x1720, 0x1731 ],
+	[ 0x1740, 0x1751 ],
+	[ 0x1760, 0x176C ],
+	[ 0x176E, 0x1770 ],
+	[ 0x1780, 0x17B3 ],
+	[ 0x17D7, 0x17D7 ],
+	[ 0x17DC, 0x17DC ],
+	[ 0x1820, 0x1877 ],
+	[ 0x1880, 0x18A8 ],
+	[ 0x1900, 0x191C ],
+	[ 0x1950, 0x196D ],
+	[ 0x1970, 0x1974 ],
+	[ 0x1980, 0x19A9 ],
+	[ 0x19C1, 0x19C7 ],
+	[ 0x1A00, 0x1A16 ],
+	[ 0x1B05, 0x1B33 ],
+	[ 0x1B45, 0x1B4B ],
+	[ 0x1D00, 0x1DBF ],
+	[ 0x1E00, 0x1E9B ],
+	[ 0x1EA0, 0x1EF9 ],
+	[ 0x1F00, 0x1F15 ],
+	[ 0x1F18, 0x1F1D ],
+	[ 0x1F20, 0x1F45 ],
+	[ 0x1F48, 0x1F4D ],
+	[ 0x1F50, 0x1F57 ],
+	[ 0x1F59, 0x1F59 ],
+	[ 0x1F5B, 0x1F5B ],
+	[ 0x1F5D, 0x1F5D ],
+	[ 0x1F5F, 0x1F7D ],
+	[ 0x1F80, 0x1FB4 ],
+	[ 0x1FB6, 0x1FBC ],
+	[ 0x1FBE, 0x1FBE ],
+	[ 0x1FC2, 0x1FC4 ],
+	[ 0x1FC6, 0x1FCC ],
+	[ 0x1FD0, 0x1FD3 ],
+	[ 0x1FD6, 0x1FDB ],
+	[ 0x1FE0, 0x1FEC ],
+	[ 0x1FF2, 0x1FF4 ],
+	[ 0x1FF6, 0x1FFC ],
+	[ 0x2071, 0x2071 ],
+	[ 0x207F, 0x207F ],
+	[ 0x2090, 0x2094 ],
+	[ 0x2102, 0x2102 ],
+	[ 0x2107, 0x2107 ],
+	[ 0x210A, 0x2113 ],
+	[ 0x2115, 0x2115 ],
+	[ 0x2119, 0x211D ],
+	[ 0x2124, 0x2124 ],
+	[ 0x2126, 0x2126 ],
+	[ 0x2128, 0x2128 ],
+	[ 0x212A, 0x212D ],
+	[ 0x212F, 0x2139 ],
+	[ 0x213C, 0x213F ],
+	[ 0x2145, 0x2149 ],
+	[ 0x214E, 0x214E ],
+	[ 0x2183, 0x2184 ],
+	[ 0x2C00, 0x2C2E ],
+	[ 0x2C30, 0x2C5E ],
+	[ 0x2C60, 0x2C6C ],
+	[ 0x2C74, 0x2C77 ],
+	[ 0x2C80, 0x2CE4 ],
+	[ 0x2D00, 0x2D25 ],
+	[ 0x2D30, 0x2D65 ],
+	[ 0x2D6F, 0x2D6F ],
+	[ 0x2D80, 0x2D96 ],
+	[ 0x2DA0, 0x2DA6 ],
+	[ 0x2DA8, 0x2DAE ],
+	[ 0x2DB0, 0x2DB6 ],
+	[ 0x2DB8, 0x2DBE ],
+	[ 0x2DC0, 0x2DC6 ],
+	[ 0x2DC8, 0x2DCE ],
+	[ 0x2DD0, 0x2DD6 ],
+	[ 0x2DD8, 0x2DDE ],
+	[ 0x3005, 0x3006 ],
+	[ 0x3031, 0x3035 ],
+	[ 0x303B, 0x303C ],
+	[ 0x3041, 0x3096 ],
+	[ 0x309D, 0x309F ],
+	[ 0x30A1, 0x30FA ],
+	[ 0x30FC, 0x30FF ],
+	[ 0x3105, 0x312C ],
+	[ 0x3131, 0x318E ],
+	[ 0x31A0, 0x31B7 ],
+	[ 0x31F0, 0x31FF ],
+	[ 0x3400, 0x4DB5 ],
+	[ 0x4E00, 0x9FBB ],
+	[ 0xA000, 0xA48C ],
+	[ 0xA717, 0xA71A ],
+	[ 0xA800, 0xA801 ],
+	[ 0xA803, 0xA805 ],
+	[ 0xA807, 0xA80A ],
+	[ 0xA80C, 0xA822 ],
+	[ 0xA840, 0xA873 ],
+	[ 0xAC00, 0xD7A3 ],
+	[ 0xF900, 0xFA2D ],
+	[ 0xFA30, 0xFA6A ],
+	[ 0xFA70, 0xFAD9 ],
+	[ 0xFB00, 0xFB06 ],
+	[ 0xFB13, 0xFB17 ],
+	[ 0xFB1D, 0xFB1D ],
+	[ 0xFB1F, 0xFB28 ],
+	[ 0xFB2A, 0xFB36 ],
+	[ 0xFB38, 0xFB3C ],
+	[ 0xFB3E, 0xFB3E ],
+	[ 0xFB40, 0xFB41 ],
+	[ 0xFB43, 0xFB44 ],
+	[ 0xFB46, 0xFBB1 ],
+	[ 0xFBD3, 0xFD3D ],
+	[ 0xFD50, 0xFD8F ],
+	[ 0xFD92, 0xFDC7 ],
+	[ 0xFDF0, 0xFDFB ],
+	[ 0xFE70, 0xFE74 ],
+	[ 0xFE76, 0xFEFC ],
+	[ 0xFF21, 0xFF3A ],
+	[ 0xFF41, 0xFF5A ],
+	[ 0xFF66, 0xFFBE ],
+	[ 0xFFC2, 0xFFC7 ],
+	[ 0xFFCA, 0xFFCF ],
+	[ 0xFFD2, 0xFFD7 ],
+	[ 0xFFDA, 0xFFDC ],
+	[ 0x10000, 0x1000B ],
+	[ 0x1000D, 0x10026 ],
+	[ 0x10028, 0x1003A ],
+	[ 0x1003C, 0x1003D ],
+	[ 0x1003F, 0x1004D ],
+	[ 0x10050, 0x1005D ],
+	[ 0x10080, 0x100FA ],
+	[ 0x10300, 0x1031E ],
+	[ 0x10330, 0x10340 ],
+	[ 0x10342, 0x10349 ],
+	[ 0x10380, 0x1039D ],
+	[ 0x103A0, 0x103C3 ],
+	[ 0x103C8, 0x103CF ],
+	[ 0x10400, 0x1049D ],
+	[ 0x10800, 0x10805 ],
+	[ 0x10808, 0x10808 ],
+	[ 0x1080A, 0x10835 ],
+	[ 0x10837, 0x10838 ],
+	[ 0x1083C, 0x1083C ],
+	[ 0x1083F, 0x1083F ],
+	[ 0x10900, 0x10915 ],
+	[ 0x10A00, 0x10A00 ],
+	[ 0x10A10, 0x10A13 ],
+	[ 0x10A15, 0x10A17 ],
+	[ 0x10A19, 0x10A33 ],
+	[ 0x12000, 0x1236E ],
+	[ 0x1D400, 0x1D454 ],
+	[ 0x1D456, 0x1D49C ],
+	[ 0x1D49E, 0x1D49F ],
+	[ 0x1D4A2, 0x1D4A2 ],
+	[ 0x1D4A5, 0x1D4A6 ],
+	[ 0x1D4A9, 0x1D4AC ],
+	[ 0x1D4AE, 0x1D4B9 ],
+	[ 0x1D4BB, 0x1D4BB ],
+	[ 0x1D4BD, 0x1D4C3 ],
+	[ 0x1D4C5, 0x1D505 ],
+	[ 0x1D507, 0x1D50A ],
+	[ 0x1D50D, 0x1D514 ],
+	[ 0x1D516, 0x1D51C ],
+	[ 0x1D51E, 0x1D539 ],
+	[ 0x1D53B, 0x1D53E ],
+	[ 0x1D540, 0x1D544 ],
+	[ 0x1D546, 0x1D546 ],
+	[ 0x1D54A, 0x1D550 ],
+	[ 0x1D552, 0x1D6A5 ],
+	[ 0x1D6A8, 0x1D6C0 ],
+	[ 0x1D6C2, 0x1D6DA ],
+	[ 0x1D6DC, 0x1D6FA ],
+	[ 0x1D6FC, 0x1D714 ],
+	[ 0x1D716, 0x1D734 ],
+	[ 0x1D736, 0x1D74E ],
+	[ 0x1D750, 0x1D76E ],
+	[ 0x1D770, 0x1D788 ],
+	[ 0x1D78A, 0x1D7A8 ],
+	[ 0x1D7AA, 0x1D7C2 ],
+	[ 0x1D7C4, 0x1D7CB ],
+	[ 0x20000, 0x2A6D6 ],
+	[ 0x2F800, 0x2FA1D ],
+    ];
+
+    debug
+    {
+	for (int i = 0; i < table.length; i++)
+	{
+	    assert(table[i][0] <= table[i][1]);
+	    if (i < table.length - 1)
+	    {
+		if (table[i][1] >= table[i + 1][0])
+		    printf("table[%d][1] = x%x, table[%d][0] = x%x\n", i, table[i][1], i + 1, table[i + 1][0]);
+		assert(table[i][1] < table[i + 1][0]);
+	    }
+	}
+    }
+
+    if (u < 0xAA)
+    {
+	if (u < 'A')
+	    goto Lisnot;
+	if (u <= 'Z')
+	    goto Lis;
+	if (u < 'a')
+	    goto Lisnot;
+	if (u <= 'z')
+	    goto Lis;
+	goto Lisnot;
+    }
+
+    // Binary search
+    uint mid;
+    uint low;
+    uint high;
+
+    low = 0;
+    high = table.length - 1;
+    while (cast(int)low <= cast(int)high)
+    {
+	mid = (low + high) >> 1;
+	if (u < table[mid][0])
+	    high = mid - 1;
+	else if (u > table[mid][1])
+	    low = mid + 1;
+	else
+	    goto Lis;
+    }
+
+Lisnot:
+    debug
+    {
+	for (int i = 0; i < table.length; i++)
+	{
+	    assert(u < table[i][0] || u > table[i][1]);
+	}
+    }
+    return 0;
+
+Lis:
+    debug
+    {
+	for (int i = 0; i < table.length; i++)
+	{
+	    if (u >= table[i][0] && u <= table[i][1])
+		return 1;
+	}
+	assert(0);		// should have been in table
+    }
+    return 1;
+}
+
+unittest
+{
+    for (uint i = 0; i < 0x80; i++)
+    {
+	if (i >= 'A' && i <= 'Z')
+	    assert(isUniAlpha(i));
+	else if (i >= 'a' && i <= 'z')
+	    assert(isUniAlpha(i));
+	else
+	    assert(!isUniAlpha(i));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/std/utf.d	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,969 @@
+// utf.d
+
+/*
+ *  Copyright (C) 2003-2004 by Digital Mars, www.digitalmars.com
+ *  Written by Walter Bright
+ *
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, subject to the following restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ */
+
+/********************************************
+ * Encode and decode UTF-8, UTF-16 and UTF-32 strings.
+ *
+ * For Win32 systems, the C wchar_t type is UTF-16 and corresponds to the D
+ * wchar type.
+ * For linux systems, the C wchar_t type is UTF-32 and corresponds to
+ * the D utf.dchar type. 
+ *
+ * UTF character support is restricted to (\u0000 &lt;= character &lt;= \U0010FFFF).
+ *
+ * See_Also:
+ *	$(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia)<br>
+ *	$(LINK http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)<br>
+ *	$(LINK http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335)
+ * Macros:
+ *	WIKI = Phobos/StdUtf
+ */
+ 
+module std.utf;
+
+private import std.stdio;
+
+//debug=utf;		// uncomment to turn on debugging printf's
+
+deprecated class UtfError : Error
+{
+    size_t idx;	// index in string of where error occurred
+
+    this(char[] s, size_t i)
+    {
+	idx = i;
+	super(s);
+    }
+}
+
+/**********************************
+ * Exception class that is thrown upon any errors.
+ */
+
+class UtfException : Exception
+{
+    size_t idx;	/// index in string of where error occurred
+
+    this(char[] s, size_t i)
+    {
+	idx = i;
+	super(s);
+    }
+}
+
+/*******************************
+ * Test if c is a valid UTF-32 character.
+ *
+ * \uFFFE and \uFFFF are considered valid by this function,
+ * as they are permitted for internal use by an application,
+ * but they are not allowed for interchange by the Unicode standard.
+ *
+ * Returns: true if it is, false if not.
+ */
+
+bool isValidDchar(dchar c)
+{
+    /* Note: FFFE and FFFF are specifically permitted by the
+     * Unicode standard for application internal use, but are not
+     * allowed for interchange.
+     * (thanks to Arcane Jill)
+     */
+
+    return c < 0xD800 ||
+	(c > 0xDFFF && c <= 0x10FFFF /*&& c != 0xFFFE && c != 0xFFFF*/);
+}
+
+unittest
+{
+    debug(utf) printf("utf.isValidDchar.unittest\n");
+    assert(isValidDchar(cast(dchar)'a') == true);
+    assert(isValidDchar(cast(dchar)0x1FFFFF) == false);
+}
+
+
+ubyte[256] UTF8stride =
+[
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+    4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF,
+];
+
+/**
+ * stride() returns the length of a UTF-8 sequence starting at index i
+ * in string s.
+ * Returns:
+ *	The number of bytes in the UTF-8 sequence or
+ *	0xFF meaning s[i] is not the start of of UTF-8 sequence.
+ */
+
+uint stride(char[] s, size_t i)
+{
+    return UTF8stride[s[i]];
+}
+
+/**
+ * stride() returns the length of a UTF-16 sequence starting at index i
+ * in string s.
+ */
+
+uint stride(wchar[] s, size_t i)
+{   uint u = s[i];
+    return 1 + (u >= 0xD800 && u <= 0xDBFF);
+}
+
+/**
+ * stride() returns the length of a UTF-32 sequence starting at index i
+ * in string s.
+ * Returns: The return value will always be 1.
+ */
+
+uint stride(dchar[] s, size_t i)
+{
+    return 1;
+}
+
+/*******************************************
+ * Given an index i into an array of characters s[],
+ * and assuming that index i is at the start of a UTF character,
+ * determine the number of UCS characters up to that index i.
+ */
+
+size_t toUCSindex(char[] s, size_t i)
+{
+    size_t n;
+    size_t j;
+    size_t stride;
+
+    for (j = 0; j < i; j += stride)
+    {
+	stride = UTF8stride[s[j]];
+	if (stride == 0xFF)
+	    goto Lerr;
+	n++;
+    }
+    if (j > i)
+    {
+      Lerr:
+	throw new UtfException("1invalid UTF-8 sequence", j);
+    }
+    return n;
+}
+
+/** ditto */
+
+size_t toUCSindex(wchar[] s, size_t i)
+{
+    size_t n;
+    size_t j;
+
+    for (j = 0; j < i; )
+    {	uint u = s[j];
+
+	j += 1 + (u >= 0xD800 && u <= 0xDBFF);
+	n++;
+    }
+    if (j > i)
+    {
+      Lerr:
+	throw new UtfException("2invalid UTF-16 sequence", j);
+    }
+    return n;
+}
+
+/** ditto */
+
+size_t toUCSindex(dchar[] s, size_t i)
+{
+    return i;
+}
+
+/******************************************
+ * Given a UCS index n into an array of characters s[], return the UTF index.
+ */
+
+size_t toUTFindex(char[] s, size_t n)
+{
+    size_t i;
+
+    while (n--)
+    {
+	uint j = UTF8stride[s[i]];
+	if (j == 0xFF)
+	    throw new UtfException("3invalid UTF-8 sequence", i);
+	i += j;
+    }
+    return i;
+}
+
+/** ditto */
+
+size_t toUTFindex(wchar[] s, size_t n)
+{
+    size_t i;
+
+    while (n--)
+    {	wchar u = s[i];
+
+	i += 1 + (u >= 0xD800 && u <= 0xDBFF);
+    }
+    return i;
+}
+
+/** ditto */
+
+size_t toUTFindex(dchar[] s, size_t n)
+{
+    return n;
+}
+
+/* =================== Decode ======================= */
+
+/***************
+ * Decodes and returns character starting at s[idx]. idx is advanced past the
+ * decoded character. If the character is not well formed, a UtfException is
+ * thrown and idx remains unchanged.
+ */
+
+dchar decode(char[] s, inout size_t idx)
+    in
+    {
+	assert(idx >= 0 && idx < s.length);
+    }
+    out (result)
+    {
+	assert(isValidDchar(result));
+    }
+    body
+    {
+	size_t len = s.length;
+	dchar V;
+	size_t i = idx;
+	char u = s[i];
+
+	if (u & 0x80)
+	{   uint n;
+	    char u2;
+
+	    /* The following encodings are valid, except for the 5 and 6 byte
+	     * combinations:
+	     *	0xxxxxxx
+	     *	110xxxxx 10xxxxxx
+	     *	1110xxxx 10xxxxxx 10xxxxxx
+	     *	11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+	     *	111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+	     *	1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+	     */
+	    for (n = 1; ; n++)
+	    {
+		if (n > 4)
+		    goto Lerr;		// only do the first 4 of 6 encodings
+		if (((u << n) & 0x80) == 0)
+		{
+		    if (n == 1)
+			goto Lerr;
+		    break;
+		}
+	    }
+
+	    // Pick off (7 - n) significant bits of B from first byte of octet
+	    V = cast(dchar)(u & ((1 << (7 - n)) - 1));
+
+	    if (i + (n - 1) >= len)
+		goto Lerr;			// off end of string
+
+	    /* The following combinations are overlong, and illegal:
+	     *	1100000x (10xxxxxx)
+	     *	11100000 100xxxxx (10xxxxxx)
+	     *	11110000 1000xxxx (10xxxxxx 10xxxxxx)
+	     *	11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx)
+	     *	11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
+	     */
+	    u2 = s[i + 1];
+	    if ((u & 0xFE) == 0xC0 ||
+		(u == 0xE0 && (u2 & 0xE0) == 0x80) ||
+		(u == 0xF0 && (u2 & 0xF0) == 0x80) ||
+		(u == 0xF8 && (u2 & 0xF8) == 0x80) ||
+		(u == 0xFC && (u2 & 0xFC) == 0x80))
+		goto Lerr;			// overlong combination
+
+	    for (uint j = 1; j != n; j++)
+	    {
+		u = s[i + j];
+		if ((u & 0xC0) != 0x80)
+		    goto Lerr;			// trailing bytes are 10xxxxxx
+		V = (V << 6) | (u & 0x3F);
+	    }
+	    if (!isValidDchar(V))
+		goto Lerr;
+	    i += n;
+	}
+	else
+	{
+	    V = cast(dchar) u;
+	    i++;
+	}
+
+	idx = i;
+	return V;
+
+      Lerr:
+	//printf("\ndecode: idx = %d, i = %d, length = %d s = \n'%.*s'\n%x\n'%.*s'\n", idx, i, s.length, s, s[i], s[i .. length]);
+	throw new UtfException("4invalid UTF-8 sequence", i);
+    }
+
+unittest
+{   size_t i;
+    dchar c;
+
+    debug(utf) printf("utf.decode.unittest\n");
+
+    static char[] s1 = "abcd";
+    i = 0;
+    c = decode(s1, i);
+    assert(c == cast(dchar)'a');
+    assert(i == 1);
+    c = decode(s1, i);
+    assert(c == cast(dchar)'b');
+    assert(i == 2);
+
+    static char[] s2 = "\xC2\xA9";
+    i = 0;
+    c = decode(s2, i);
+    assert(c == cast(dchar)'\u00A9');
+    assert(i == 2);
+
+    static char[] s3 = "\xE2\x89\xA0";
+    i = 0;
+    c = decode(s3, i);
+    assert(c == cast(dchar)'\u2260');
+    assert(i == 3);
+
+    static char[][] s4 =
+    [	"\xE2\x89",		// too short
+	"\xC0\x8A",
+	"\xE0\x80\x8A",
+	"\xF0\x80\x80\x8A",
+	"\xF8\x80\x80\x80\x8A",
+	"\xFC\x80\x80\x80\x80\x8A",
+    ];
+
+    for (int j = 0; j < s4.length; j++)
+    {
+	try
+	{
+	    i = 0;
+	    c = decode(s4[j], i);
+	    assert(0);
+	}
+	catch (UtfException u)
+	{
+	    i = 23;
+	    delete u;
+	}
+	assert(i == 23);
+    }
+}
+
+/** ditto */
+
+dchar decode(wchar[] s, inout size_t idx)
+    in
+    {
+	assert(idx >= 0 && idx < s.length);
+    }
+    out (result)
+    {
+	assert(isValidDchar(result));
+    }
+    body
+    {
+	char[] msg;
+	dchar V;
+	size_t i = idx;
+	uint u = s[i];
+
+	if (u & ~0x7F)
+	{   if (u >= 0xD800 && u <= 0xDBFF)
+	    {   uint u2;
+
+		if (i + 1 == s.length)
+		{   msg = "surrogate UTF-16 high value past end of string";
+		    goto Lerr;
+		}
+		u2 = s[i + 1];
+		if (u2 < 0xDC00 || u2 > 0xDFFF)
+		{   msg = "surrogate UTF-16 low value out of range";
+		    goto Lerr;
+		}
+		u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00);
+		i += 2;
+	    }
+	    else if (u >= 0xDC00 && u <= 0xDFFF)
+	    {   msg = "unpaired surrogate UTF-16 value";
+		goto Lerr;
+	    }
+	    else if (u == 0xFFFE || u == 0xFFFF)
+	    {   msg = "illegal UTF-16 value";
+		goto Lerr;
+	    }
+	    else
+		i++;
+	}
+	else
+	{
+	    i++;
+	}
+
+	idx = i;
+	return cast(dchar)u;
+
+      Lerr:
+	throw new UtfException(msg, i);
+    }
+
+/** ditto */
+
+dchar decode(dchar[] s, inout size_t idx)
+    in
+    {
+	assert(idx >= 0 && idx < s.length);
+    }
+    body
+    {
+	size_t i = idx;
+	dchar c = s[i];
+
+	if (!isValidDchar(c))
+	    goto Lerr;
+	idx = i + 1;
+	return c;
+
+      Lerr:
+	throw new UtfException("5invalid UTF-32 value", i);
+    }
+
+
+/* =================== Encode ======================= */
+
+/*******************************
+ * Encodes character c and appends it to array s[].
+ */
+
+void encode(inout char[] s, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	char[] r = s;
+
+	if (c <= 0x7F)
+	{
+	    r ~= cast(char) c;
+	}
+	else
+	{
+	    char[4] buf;
+	    uint L;
+
+	    if (c <= 0x7FF)
+	    {
+		buf[0] = cast(char)(0xC0 | (c >> 6));
+		buf[1] = cast(char)(0x80 | (c & 0x3F));
+		L = 2;
+	    }
+	    else if (c <= 0xFFFF)
+	    {
+		buf[0] = cast(char)(0xE0 | (c >> 12));
+		buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F));
+		buf[2] = cast(char)(0x80 | (c & 0x3F));
+		L = 3;
+	    }
+	    else if (c <= 0x10FFFF)
+	    {
+		buf[0] = cast(char)(0xF0 | (c >> 18));
+		buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F));
+		buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F));
+		buf[3] = cast(char)(0x80 | (c & 0x3F));
+		L = 4;
+	    }
+	    else
+	    {
+		assert(0);
+	    }
+	    r ~= buf[0 .. L];
+	}
+	s = r;
+    }
+
+unittest
+{
+    debug(utf) printf("utf.encode.unittest\n");
+
+    char[] s = "abcd";
+    encode(s, cast(dchar)'a');
+    assert(s.length == 5);
+    assert(s == "abcda");
+
+    encode(s, cast(dchar)'\u00A9');
+    assert(s.length == 7);
+    assert(s == "abcda\xC2\xA9");
+    //assert(s == "abcda\u00A9");	// BUG: fix compiler
+
+    encode(s, cast(dchar)'\u2260');
+    assert(s.length == 10);
+    assert(s == "abcda\xC2\xA9\xE2\x89\xA0");
+}
+
+/** ditto */
+
+void encode(inout wchar[] s, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	wchar[] r = s;
+
+	if (c <= 0xFFFF)
+	{
+	    r ~= cast(wchar) c;
+	}
+	else
+	{
+	    wchar[2] buf;
+
+	    buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
+	    buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
+	    r ~= buf;
+	}
+	s = r;
+    }
+
+/** ditto */
+
+void encode(inout dchar[] s, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	s ~= c;
+    }
+
+/* =================== Validation ======================= */
+
+/***********************************
+ * Checks to see if string is well formed or not. Throws a UtfException if it is
+ * not. Use to check all untrusted input for correctness.
+ */
+
+void validate(char[] s)
+{
+    size_t len = s.length;
+    size_t i;
+
+    for (i = 0; i < len; )
+    {
+	decode(s, i);
+    }
+}
+
+/** ditto */
+
+void validate(wchar[] s)
+{
+    size_t len = s.length;
+    size_t i;
+
+    for (i = 0; i < len; )
+    {
+	decode(s, i);
+    }
+}
+
+/** ditto */
+
+void validate(dchar[] s)
+{
+    size_t len = s.length;
+    size_t i;
+
+    for (i = 0; i < len; )
+    {
+	decode(s, i);
+    }
+}
+
+/* =================== Conversion to UTF8 ======================= */
+
+char[] toUTF8(char[4] buf, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	if (c <= 0x7F)
+	{
+	    buf[0] = cast(char) c;
+	    return buf[0 .. 1];
+	}
+	else if (c <= 0x7FF)
+	{
+	    buf[0] = cast(char)(0xC0 | (c >> 6));
+	    buf[1] = cast(char)(0x80 | (c & 0x3F));
+	    return buf[0 .. 2];
+	}
+	else if (c <= 0xFFFF)
+	{
+	    buf[0] = cast(char)(0xE0 | (c >> 12));
+	    buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F));
+	    buf[2] = cast(char)(0x80 | (c & 0x3F));
+	    return buf[0 .. 3];
+	}
+	else if (c <= 0x10FFFF)
+	{
+	    buf[0] = cast(char)(0xF0 | (c >> 18));
+	    buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F));
+	    buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F));
+	    buf[3] = cast(char)(0x80 | (c & 0x3F));
+	    return buf[0 .. 4];
+	}
+	assert(0);
+    }
+
+/*******************
+ * Encodes string s into UTF-8 and returns the encoded string.
+ */
+
+char[] toUTF8(char[] s)
+    in
+    {
+	validate(s);
+    }
+    body
+    {
+	return s;
+    }
+
+/** ditto */
+
+char[] toUTF8(wchar[] s)
+{
+    char[] r;
+    size_t i;
+    size_t slen = s.length;
+
+    r.length = slen;
+
+    for (i = 0; i < slen; i++)
+    {	wchar c = s[i];
+
+	if (c <= 0x7F)
+	    r[i] = cast(char)c;		// fast path for ascii
+	else
+	{
+	    r.length = i;
+	    foreach (dchar c; s[i .. slen])
+	    {
+		encode(r, c);
+	    }
+	    break;
+	}
+    }
+    return r;
+}
+
+/** ditto */
+
+char[] toUTF8(dchar[] s)
+{
+    char[] r;
+    size_t i;
+    size_t slen = s.length;
+
+    r.length = slen;
+
+    for (i = 0; i < slen; i++)
+    {	dchar c = s[i];
+
+	if (c <= 0x7F)
+	    r[i] = cast(char)c;		// fast path for ascii
+	else
+	{
+	    r.length = i;
+	    foreach (dchar d; s[i .. slen])
+	    {
+		encode(r, d);
+	    }
+	    break;
+	}
+    }
+    return r;
+}
+
+/* =================== Conversion to UTF16 ======================= */
+
+wchar[] toUTF16(wchar[2] buf, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	if (c <= 0xFFFF)
+	{
+	    buf[0] = cast(wchar) c;
+	    return buf[0 .. 1];
+	}
+	else
+	{
+	    buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
+	    buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
+	    return buf[0 .. 2];
+	}
+    }
+
+/****************
+ * Encodes string s into UTF-16 and returns the encoded string.
+ * toUTF16z() is suitable for calling the 'W' functions in the Win32 API that take
+ * an LPWSTR or LPCWSTR argument.
+ */
+
+wchar[] toUTF16(char[] s)
+{
+    wchar[] r;
+    size_t slen = s.length;
+
+    r.length = slen;
+    r.length = 0;
+    for (size_t i = 0; i < slen; )
+    {
+	dchar c = s[i];
+	if (c <= 0x7F)
+	{
+	    i++;
+	    r ~= cast(wchar)c;
+	}
+	else
+	{
+	    c = decode(s, i);
+	    encode(r, c);
+	}
+    }
+    return r;
+}
+
+/** ditto */
+
+wchar* toUTF16z(char[] s)
+{
+    wchar[] r;
+    size_t slen = s.length;
+
+    r.length = slen + 1;
+    r.length = 0;
+    for (size_t i = 0; i < slen; )
+    {
+	dchar c = s[i];
+	if (c <= 0x7F)
+	{
+	    i++;
+	    r ~= cast(wchar)c;
+	}
+	else
+	{
+	    c = decode(s, i);
+	    encode(r, c);
+	}
+    }
+    r ~= "\000";
+    return r.ptr;
+}
+
+/** ditto */
+
+wchar[] toUTF16(wchar[] s)
+    in
+    {
+	validate(s);
+    }
+    body
+    {
+	return s;
+    }
+
+/** ditto */
+
+wchar[] toUTF16(dchar[] s)
+{
+    wchar[] r;
+    size_t slen = s.length;
+
+    r.length = slen;
+    r.length = 0;
+    for (size_t i = 0; i < slen; i++)
+    {
+	encode(r, s[i]);
+    }
+    return r;
+}
+
+/* =================== Conversion to UTF32 ======================= */
+
+/*****
+ * Encodes string s into UTF-32 and returns the encoded string.
+ */
+
+dchar[] toUTF32(char[] s)
+{
+    dchar[] r;
+    size_t slen = s.length;
+    size_t j = 0;
+
+    r.length = slen;		// r[] will never be longer than s[]
+    for (size_t i = 0; i < slen; )
+    {
+	dchar c = s[i];
+	if (c >= 0x80)
+	    c = decode(s, i);
+	else
+	    i++;		// c is ascii, no need for decode
+	r[j++] = c;
+    }
+    return r[0 .. j];
+}
+
+/** ditto */
+
+dchar[] toUTF32(wchar[] s)
+{
+    dchar[] r;
+    size_t slen = s.length;
+    size_t j = 0;
+
+    r.length = slen;		// r[] will never be longer than s[]
+    for (size_t i = 0; i < slen; )
+    {
+	dchar c = s[i];
+	if (c >= 0x80)
+	    c = decode(s, i);
+	else
+	    i++;		// c is ascii, no need for decode
+	r[j++] = c;
+    }
+    return r[0 .. j];
+}
+
+/** ditto */
+
+dchar[] toUTF32(dchar[] s)
+    in
+    {
+	validate(s);
+    }
+    body
+    {
+	return s;
+    }
+
+/* ================================ tests ================================== */
+
+unittest
+{
+    debug(utf) printf("utf.toUTF.unittest\n");
+
+    char[] c;
+    wchar[] w;
+    dchar[] d;
+
+    c = "hello";
+    w = toUTF16(c);
+    assert(w == "hello");
+    d = toUTF32(c);
+    assert(d == "hello");
+
+    c = toUTF8(w);
+    assert(c == "hello");
+    d = toUTF32(w);
+    assert(d == "hello");
+
+    c = toUTF8(d);
+    assert(c == "hello");
+    w = toUTF16(d);
+    assert(w == "hello");
+
+
+    c = "hel\u1234o";
+    w = toUTF16(c);
+    assert(w == "hel\u1234o");
+    d = toUTF32(c);
+    assert(d == "hel\u1234o");
+
+    c = toUTF8(w);
+    assert(c == "hel\u1234o");
+    d = toUTF32(w);
+    assert(d == "hel\u1234o");
+
+    c = toUTF8(d);
+    assert(c == "hel\u1234o");
+    w = toUTF16(d);
+    assert(w == "hel\u1234o");
+
+
+    c = "he\U0010AAAAllo";
+    w = toUTF16(c);
+    //foreach (wchar c; w) printf("c = x%x\n", c);
+    //foreach (wchar c; cast(wchar[])"he\U0010AAAAllo") printf("c = x%x\n", c);
+    assert(w == "he\U0010AAAAllo");
+    d = toUTF32(c);
+    assert(d == "he\U0010AAAAllo");
+
+    c = toUTF8(w);
+    assert(c == "he\U0010AAAAllo");
+    d = toUTF32(w);
+    assert(d == "he\U0010AAAAllo");
+
+    c = toUTF8(d);
+    assert(c == "he\U0010AAAAllo");
+    w = toUTF16(d);
+    assert(w == "he\U0010AAAAllo");
+}
--- a/premake.lua	Fri Nov 02 06:32:32 2007 +0100
+++ b/premake.lua	Sat Nov 03 14:44:58 2007 +0100
@@ -21,13 +21,13 @@
 package.name = "llvmdc"
 package.kind = "exe"
 package.language = "c++"
-package.files = { matchfiles("dmd/*.c"), matchfiles("gen/*.c") }
+package.files = { matchfiles("dmd/*.c"), matchfiles("gen/*.cpp") }
 package.excludes = { "dmd/idgen.c", "dmd/impcnvgen.c" }
 package.buildoptions = { "-x c++", "`llvm-config --cxxflags`" }
 package.linkoptions = { "`llvm-config --libs native bitwriter bitreader`", "`llvm-config --ldflags`" }
 package.defines = { "IN_LLVM", "_DH" }
 package.config.Release.defines = { "LLVMD_NO_LOGGER" }
-package.config.Debug.buildoptions = { "-g" }
+package.config.Debug.buildoptions = { "-g -O0" }
 --package.targetprefix = "llvm"
 package.includepaths = { ".", "dmd" }
 --package.postbuildcommands = { "cd runtime; ./build.sh; cd .." }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/arrays10.d	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,7 @@
+module arrays10;
+
+void main()
+{
+    int[] a = new int[10];
+    a[] = 3;
+}
\ No newline at end of file
--- a/test/arrays7.d	Fri Nov 02 06:32:32 2007 +0100
+++ b/test/arrays7.d	Sat Nov 03 14:44:58 2007 +0100
@@ -1,18 +1,29 @@
 module arrays7;
 
+pragma(LLVM_internal, "notypeinfo")
 struct S
 {
     int i;
     float f;
     long l;
+
+    void print()
+    {
+        printf("%d %f %lx\n", i, f, l);
+    }
 }
 
 void main()
 {
     S[] arr;
     S s;
+    assert(arr.length == 0);
     arr ~= s;
+    assert(arr.length == 1);
     arr ~= S(1,2.64,0xFFFF_FFFF_FFFF);
+    assert(arr.length == 2);
+    arr[0].print();
+    arr[1].print();
     assert(arr[1].i == 1);
     assert(arr[1].f > 2.63 && arr[1].f < 2.65);
     assert(arr[1].l == 0xFFFF_FFFF_FFFF);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/arrays9.d	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,8 @@
+module arrays9;
+
+const int[] g = [1,2,3,4];
+
+void main()
+{
+
+}
--- a/test/b.d	Fri Nov 02 06:32:32 2007 +0100
+++ b/test/b.d	Sat Nov 03 14:44:58 2007 +0100
@@ -10,7 +10,7 @@
 {
     S s;
     int i = s.i;
-    int* p = &s.i;
+    /*int* p = &s.i;
     *p = 42;
     printf("%d == %d\n", *p, s.i);
 
@@ -19,5 +19,5 @@
     *f = 3.1415;
     printf("%f == %f\n", *f, s.f[0]);
     s.f[0] = 123.456;
-    printf("%f == %f\n", *f, s.f[0]);
+    printf("%f == %f\n", *f, s.f[0]);*/
 }
--- a/test/bitops.d	Fri Nov 02 06:32:32 2007 +0100
+++ b/test/bitops.d	Sat Nov 03 14:44:58 2007 +0100
@@ -19,7 +19,7 @@
         assert((s>>1) == -5);
         assert((s>>>1) != -5);
     }
-    
+
     {   ushort a = 0xFFF0;
         ushort b = 0x0FFF;
         auto t = a;
@@ -70,6 +70,6 @@
         s.i &= s.l;
         assert(s.i == 0x00FF_FF00);
     }
-        
+
     printf("  SUCCESS\n");
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug48.d	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,10 @@
+module bug48;
+
+size_t func(void *p)
+{
+    return cast(size_t)*cast(void* *)p;
+}
+
+void main()
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug49.d	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,16 @@
+module bug49;
+
+pragma(LLVM_internal, "notypeinfo")
+struct S
+{
+    int i;
+    long l;
+}
+
+void main()
+{
+    S s;
+    s.i = 0x__FFFF_FF00;
+    s.l = 0xFF00FF_FF00;
+    s.i &= s.l;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug50.d	Sat Nov 03 14:44:58 2007 +0100
@@ -0,0 +1,28 @@
+module bug50;
+
+pragma(LLVM_internal, "notypeinfo")
+struct S
+{
+    int i;
+    float f;
+    long l;
+
+    void print()
+    {
+        printf("%d %f %lx\n", i, f, l);
+    }
+}
+
+void main()
+{
+    S s;
+    s.print();
+    s = S(1,2,3);
+    s.print();
+
+    S[] arr;
+    {arr ~= s;}
+    {arr[0].print();}
+    {arr ~= S(1,2,3);}
+    {arr[1].print();}
+}