changeset 133:44a95ac7368a trunk

[svn r137] Many fixes towards tango.io.Console working, but not quite there yet... In particular, assertions has been fixed to include file/line info, and much more!
author lindquist
date Mon, 14 Jan 2008 05:11:54 +0100
parents 1700239cab2e
children 0dec7b3727ea
files bin/llvmdc.conf bin/llvmdc.phobos dmd/link.c dmd/mars.c dmd/mars.h gen/aa.cpp gen/arrays.cpp gen/classes.cpp gen/classes.h gen/complex.cpp gen/dwarftypes.cpp gen/functions.cpp gen/runtime.cpp gen/statements.cpp gen/structs.cpp gen/todebug.cpp gen/toir.cpp gen/tollvm.cpp gen/tollvm.h gen/toobj.cpp gen/typinf.cpp llvmdc-posix-internal llvmdc.kdevelop.filelist tango/lib/common/tango/core/Exception.d tango/lib/common/tango/llvmdc.mak tango/lib/common/tango/stdc/wrap.ll tango/lib/compiler/llvmdc/cast.d tango/lib/compiler/llvmdc/contract.d tango/lib/compiler/llvmdc/critical.c tango/lib/compiler/llvmdc/dmain2.d tango/lib/compiler/llvmdc/eh.d tango/lib/compiler/llvmdc/genobj.d tango/lib/compiler/llvmdc/lifetime.d tango/lib/compiler/llvmdc/llvmdc.mak tango/lib/compiler/llvmdc/mars.h tango/lib/compiler/llvmdc/monitor.c tango/lib/compiler/llvmdc/util/console.d tango/lib/llvmdc-posix.mak tango/tango/io/Console.d tangotests/f.d tangotests/h.d tangotests/i.d tangotests/j.d tangotests/k.d tangotests/l.d tangotests/m.d tangotests/n.d tangotests/o.d test/interface1.d test/interface2.d test/interface3.d test/interface4.d test/interface5.d test/interface6.d test/interface7.d test/intrinsics.d test/mainargs1.d test/memory1.d
diffstat 58 files changed, 1990 insertions(+), 758 deletions(-) [+]
line wrap: on
line diff
--- a/bin/llvmdc.conf	Fri Jan 11 17:57:40 2008 +0100
+++ b/bin/llvmdc.conf	Mon Jan 14 05:11:54 2008 +0100
@@ -1,4 +1,4 @@
 
 [Environment]
 
-DFLAGS=-I%@P%/../tango -E%@P%/../lib -L-L=%@P%/../lib
+DFLAGS=-I%@P%/../tango -L-L%@P%/../lib -R%@P%/../lib
--- a/bin/llvmdc.phobos	Fri Jan 11 17:57:40 2008 +0100
+++ b/bin/llvmdc.phobos	Mon Jan 14 05:11:54 2008 +0100
@@ -1,4 +1,4 @@
 
 [Environment]
 
-DFLAGS=-I%@P%/../lphobos -E%@P%/../lib -L-L=%@P%/../lib
+DFLAGS=-I%@P%/../lphobos -L-L%@P%/../lib -R%@P%/../lib
--- a/dmd/link.c	Fri Jan 11 17:57:40 2008 +0100
+++ b/dmd/link.c	Mon Jan 14 05:11:54 2008 +0100
@@ -283,14 +283,18 @@
      * passed with -l.
      */
 
-    //argv.push((void *)"-lphobos");    // turns into /usr/lib/libphobos.a
-    argv.push((void *)"-lpthread");
-    argv.push((void *)"-lm");
+    argv.push((void*)"-ltango-base-c-llvmdc");
+    argv.push((void*)"-lpthread");
+    argv.push((void*)"-ldl");
+    argv.push((void*)"-lm");
 
-    std::string corelibpath = global.params.runtimeImppath;
-    corelibpath.append("/libtango-base-llvmdc.a");
     argv.append(global.params.objfiles);
-    argv.push((void *)corelibpath.c_str());
+
+    std::string runtime_path(global.params.runtimePath);
+    if (*runtime_path.rbegin() != '/')
+        runtime_path.append("/");
+    runtime_path.append("libtango-base-llvmdc.a");
+    argv.push((void*)runtime_path.c_str());
 
     if (!global.params.quiet)
     {
--- a/dmd/mars.c	Fri Jan 11 17:57:40 2008 +0100
+++ b/dmd/mars.c	Mon Jan 14 05:11:54 2008 +0100
@@ -158,7 +158,7 @@
 
 void usage()
 {
-    printf("LLVM D Compiler %s (based on DMD %s)\n%s\n%s\n",
+    printf("LLVM D Compiler %s (based on DMD %s and LLVM 2.2)\n%s\n%s\n",
     global.llvmdc_version, global.version, global.copyright, global.written);
     printf("\
 D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n\
@@ -187,7 +187,6 @@
   -Hf<filename>  write 'header' file to <filename>\n\
   --help         print help\n\
   -I<path>       where to look for imports\n\
-  -E<path>       where to look for the core runtime\n\
   -J<path>       where to look for string imports\n\
   -inline        do function inlining\n\
   -Llinkerflag   pass linkerflag to link\n\
@@ -206,6 +205,7 @@
   -quiet         suppress unnecessary messages\n\
   -release       compile release version\n\
   -run srcfile args...   run resulting program, passing args\n\
+  -R<path>       provide path to the directory containing the runtime library\n\
   -unittest      compile in unit tests\n\
   -v             verbose\n\
   -vv            very verbose (does not include -v)\n\
@@ -386,15 +386,15 @@
             }
         }
         else if (strcmp(p + 1, "forcebe") == 0)
-		global.params.forceBE = 1;
+            global.params.forceBE = 1;
         else if (strcmp(p + 1, "noruntime") == 0)
-		global.params.noruntime = 1;
+            global.params.noruntime = 1;
         else if (strcmp(p + 1, "noverify") == 0)
-        global.params.novalidate = 1;
+            global.params.novalidate = 1;
         else if (strcmp(p + 1, "dis") == 0)
-        global.params.disassemble = 1;
+            global.params.disassemble = 1;
         else if (strcmp(p + 1, "annotate") == 0)
-        global.params.llvmAnnotate = 1;
+            global.params.llvmAnnotate = 1;
 	    else if (p[1] == 'o')
 	    {
 		switch (p[2])
@@ -503,9 +503,9 @@
 		    global.params.fileImppath = new Array();
 		global.params.fileImppath->push(p + 2);
 	    }
-        else if (p[1] == 'E')
+        else if (p[1] == 'R')
         {
-        global.params.runtimeImppath = p+2;
+        global.params.runtimePath = p+2;
         }
 	    else if (memcmp(p + 1, "debug", 5) == 0 && p[6] != 'l')
 	    {
@@ -671,7 +671,7 @@
 
     if (global.params.llvmArch == 0) {
         std::string err_str;
-        const llvm::TargetMachineRegistry::Entry* e = llvm::TargetMachineRegistry::getClosestTargetForJIT(err_str);
+        const llvm::TargetMachineRegistry::entry* e = llvm::TargetMachineRegistry::getClosestTargetForJIT(err_str);
         if (e == 0) {
             error("Failed to find a default target machine: %s", err_str.c_str());
             fatal();
--- a/dmd/mars.h	Fri Jan 11 17:57:40 2008 +0100
+++ b/dmd/mars.h	Mon Jan 14 05:11:54 2008 +0100
@@ -131,6 +131,7 @@
     char disassemble;
     char llvmInline;
     char llvmAnnotate;
+    char *runtimePath;
 };
 
 struct Global
--- a/gen/aa.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/aa.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -86,7 +86,7 @@
     pkey = DtoBitCast(pkey, funcTy->getParamType(2));
 
     // valuesize param
-    llvm::Value* valsize = DtoConstSize_t(gTargetData->getTypeSize(DtoType(type)));
+    llvm::Value* valsize = DtoConstSize_t(getABITypeSize(DtoType(type)));
 
     // build arg vector
     std::vector<llvm::Value*> args;
@@ -99,7 +99,7 @@
     llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "aa.index");
 
     // cast return value
-    const llvm::Type* targettype = llvm::PointerType::get(DtoType(type));
+    const llvm::Type* targettype = getPtrToType(DtoType(type));
     if (ret->getType() != targettype)
         ret = DtoBitCast(ret, targettype);
 
--- a/gen/arrays.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/arrays.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -24,7 +24,7 @@
     if (at == llvm::Type::VoidTy) {
         at = llvm::Type::Int8Ty;
     }
-    arrty = llvm::PointerType::get(at);
+    arrty = getPtrToType(at);
 
     std::vector<const llvm::Type*> members;
     if (global.params.is64bit)
@@ -98,7 +98,7 @@
             Logger::cout() << "invalid: " << *src << '\n';
             assert(0);
         }
-        llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType());
+        const llvm::Type* dstty = getPtrToType(arrty->getElementType());
 
         llvm::Value* dstlen = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
         llvm::Value* srclen = DtoConstSize_t(arrty->getNumElements());
@@ -161,10 +161,10 @@
         llvm::Constant* c = isaConstant(dim);
         assert(c);
         dim = llvm::ConstantExpr::getMul(c, DtoConstSize_t(arrsz));
-        ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(finalTy), "tmp");
+        ptr = gIR->ir->CreateBitCast(ptr, getPtrToType(finalTy), "tmp");
     }
     else if (isaStruct(t)) {
-        aggrsz = gTargetData->getTypeSize(t);
+        aggrsz = getABITypeSize(t);
         llvm::Constant* c = isaConstant(val);
         if (c && c->isNullValue()) {
             llvm::Value* nbytes;
@@ -176,7 +176,7 @@
             return;
         }
         else {
-            ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
+            ptr = gIR->ir->CreateBitCast(ptr, getPtrToType(llvm::Type::Int8Ty), "tmp");
         }
     }
     else {
@@ -199,11 +199,11 @@
     else if (isaPointer(t)) {
         funcname = "_d_array_init_pointer";
 
-        const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
+        const llvm::Type* dstty = getPtrToType(getPtrToType(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);
+        const llvm::Type* valty = getPtrToType(llvm::Type::Int8Ty);
         if (args[2]->getType() != valty)
             args[2] = new llvm::BitCastInst(args[2],valty,"tmp",gIR->scopebb());
     }
@@ -365,7 +365,7 @@
         // this means it's a real slice
         ret = e->ptr;
 
-        size_t elembsz = gTargetData->getTypeSize(ret->getType());
+        size_t elembsz = getABITypeSize(ret->getType());
         llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
 
         if (isaConstantInt(e->len)) {
@@ -378,7 +378,7 @@
     else if (isaArray(t)) {
         ret = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb());
 
-        size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0));
+        size_t elembsz = getABITypeSize(ret->getType()->getContainedType(0));
         llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
 
         size_t numelements = isaArray(t)->getNumElements();
@@ -390,7 +390,7 @@
         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));
+        size_t elembsz = getABITypeSize(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());
@@ -405,7 +405,7 @@
 
 void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src)
 {
-    llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
 
     llvm::Value* sz1;
     llvm::Value* dstarr = new llvm::BitCastInst(get_slice_ptr(dst,sz1),arrty,"tmp",gIR->scopebb());
@@ -426,7 +426,7 @@
 
 void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src)
 {
-    llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
 
     llvm::Value* sz1;
     llvm::Value* dstarr = new llvm::BitCastInst(get_slice_ptr(dst,sz1),arrty,"tmp",gIR->scopebb());
@@ -447,10 +447,10 @@
 void DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src)
 {
     assert(dst->getType() == src->getType());
-    size_t arrsz = gTargetData->getTypeSize(dst->getType()->getContainedType(0));
+    size_t arrsz = getABITypeSize(dst->getType()->getContainedType(0));
     llvm::Value* n = llvm::ConstantInt::get(DtoSize_t(), arrsz, false);
 
-    llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::Type* arrty = getPtrToType(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());
 
@@ -483,11 +483,11 @@
 {
     const llvm::Type* ty = DtoType(dty);
     assert(ty != llvm::Type::VoidTy);
-    size_t sz = gTargetData->getTypeSize(ty);
+    size_t sz = getABITypeSize(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* nullptr = llvm::ConstantPointerNull::get(getPtrToType(ty));
 
     llvm::Value* newptr = DtoRealloc(nullptr, bytesize);
 
@@ -510,7 +510,7 @@
     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));
+    size_t isz = getABITypeSize(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());
 
@@ -758,8 +758,8 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 llvm::Value* DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty)
 {
-    size_t esz = gTargetData->getTypeSize(elemty);
-    size_t nsz = gTargetData->getTypeSize(newelemty);
+    size_t esz = getABITypeSize(elemty);
+    size_t nsz = getABITypeSize(newelemty);
     if (esz == nsz)
         return len;
 
@@ -898,14 +898,14 @@
         llvm::Value* ptr = DtoGEPi(u->getRVal(),0,1,"tmp",gIR->scopebb());
         rval = new llvm::LoadInst(ptr, "tmp", gIR->scopebb());
         if (fromtype->next != totype->next)
-            rval = gIR->ir->CreateBitCast(rval, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
+            rval = gIR->ir->CreateBitCast(rval, getPtrToType(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);
+        ptrty = getPtrToType(ptrty);
 
         const llvm::Type* ety = DtoType(fromtype->next);
         if (ety == llvm::Type::VoidTy)
--- a/gen/classes.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/classes.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -56,7 +56,21 @@
     if (cd->llvmResolved) return;
     cd->llvmResolved = true;
 
-    // first resolve the base class
+    Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
+    LOG_SCOPE;
+
+    // get the TypeClass
+    assert(cd->type->ty == Tclass);
+    TypeClass* ts = (TypeClass*)cd->type;
+
+    // make sure the IRStruct is created
+    IRStruct* irstruct = cd->llvmIRStruct;
+    if (!irstruct) {
+        irstruct = new IRStruct(ts);
+        cd->llvmIRStruct = irstruct;
+    }
+
+    // resolve the base class
     if (cd->baseClass) {
         DtoResolveClass(cd->baseClass);
     }
@@ -72,28 +86,18 @@
         }
     }
 
-    Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
-    LOG_SCOPE;
-
-    assert(cd->type->ty == Tclass);
-    TypeClass* ts = (TypeClass*)cd->type;
-
-    assert(!cd->llvmIRStruct);
-    IRStruct* irstruct = new IRStruct(ts);
-    cd->llvmIRStruct = irstruct;
-
     gIR->structs.push_back(irstruct);
     gIR->classes.push_back(cd);
 
     // add vtable
     ts->llvmVtblType = new llvm::PATypeHolder(llvm::OpaqueType::get());
-    const llvm::Type* vtabty = llvm::PointerType::get(ts->llvmVtblType->get());
+    const llvm::Type* vtabty = getPtrToType(ts->llvmVtblType->get());
 
     std::vector<const llvm::Type*> fieldtypes;
     fieldtypes.push_back(vtabty);
 
     // add monitor
-    fieldtypes.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
+    fieldtypes.push_back(getPtrToType(llvm::Type::Int8Ty));
 
     // add interface vtables
     if (cd->vtblInterfaces)
@@ -103,7 +107,7 @@
         ClassDeclaration *id = b->base;
         assert(id->type->ty == Tclass);
         TypeClass* itc = (TypeClass*)id->type;
-        const llvm::Type* ivtblTy = llvm::PointerType::get(itc->llvmVtblType->get());
+        const llvm::Type* ivtblTy = getPtrToType(itc->llvmVtblType->get());
         fieldtypes.push_back(ivtblTy);
 
         // add this interface to the map
@@ -142,12 +146,12 @@
                 lastoffset = i->first;
                 fieldtype = i->second.type;
                 fieldinit = i->second.var;
-                prevsize = gTargetData->getTypeSize(fieldtype);
+                prevsize = getABITypeSize(fieldtype);
                 i->second.var->llvmFieldIndex = idx;
             }
             // colliding offset?
             else if (lastoffset == i->first) {
-                size_t s = gTargetData->getTypeSize(i->second.type);
+                size_t s = getABITypeSize(i->second.type);
                 if (s > prevsize) {
                     fieldpad += s - prevsize;
                     prevsize = s;
@@ -157,7 +161,7 @@
             }
             // intersecting offset?
             else if (i->first < (lastoffset + prevsize)) {
-                size_t s = gTargetData->getTypeSize(i->second.type);
+                size_t s = getABITypeSize(i->second.type);
                 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
                 cd->llvmHasUnions = true;
                 i->second.var->llvmFieldIndex = idx;
@@ -180,7 +184,7 @@
                 lastoffset = i->first;
                 fieldtype = i->second.type;
                 fieldinit = i->second.var;
-                prevsize = gTargetData->getTypeSize(fieldtype);
+                prevsize = getABITypeSize(fieldtype);
                 i->second.var->llvmFieldIndex = idx;
                 fieldpad = 0;
             }
@@ -212,6 +216,7 @@
         ts->llvmType = new llvm::PATypeHolder(structtype);
     else
         *ts->llvmType = structtype;
+    spa = *ts->llvmType;
 
     // name the type
     gIR->module->addTypeName(cd->mangle(), ts->llvmType->get());
@@ -221,11 +226,11 @@
     // ClassInfo classinfo
     ClassDeclaration* cinfod = ClassDeclaration::classinfo;
     DtoResolveClass(cinfod);
-    infoTypes.push_back(llvm::PointerType::get(cinfod->type->llvmType->get()));
+    infoTypes.push_back(getPtrToType(cinfod->type->llvmType->get()));
     // void*[] vtbl
     std::vector<const llvm::Type*> infoVtbltypes;
     infoVtbltypes.push_back(DtoSize_t());
-    const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
+    const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty));
     infoVtbltypes.push_back(byteptrptrty);
     infoTypes.push_back(llvm::StructType::get(infoVtbltypes));
     // int offset
@@ -247,9 +252,9 @@
             DtoResolveFunction(fd);
             //assert(fd->type->ty == Tfunction);
             //TypeFunction* tf = (TypeFunction*)fd->type;
-            //const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get());
+            //const llvm::Type* fpty = getPtrToType(tf->llvmType->get());
             const llvm::FunctionType* vfty = DtoBaseFunctionType(fd);
-            const llvm::Type* vfpty = llvm::PointerType::get(vfty);
+            const llvm::Type* vfpty = getPtrToType(vfty);
             sinits_ty.push_back(vfpty);
         }
         else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) {
@@ -266,7 +271,7 @@
                 // this is the ClassInfo class, the type is this type
                 cinfoty = ts->llvmType->get();
             }
-            const llvm::Type* cty = llvm::PointerType::get(cinfoty);
+            const llvm::Type* cty = getPtrToType(cinfoty);
             sinits_ty.push_back(cty);
         }
         else
@@ -314,8 +319,9 @@
     }
 
     // interface vtables are emitted by the class implementing them
-    // also interfaces have no static initializer
-    if (!cd->isInterfaceDeclaration()) {
+    // also, interfaces have no static initializer
+    // also, abstract classes have no vtable
+    if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) {
         // vtable
         std::string varname("_D");
         varname.append(cd->mangle());
@@ -331,11 +337,11 @@
         // ClassInfo classinfo
         ClassDeclaration* cd2 = ClassDeclaration::classinfo;
         DtoResolveClass(cd2);
-        types.push_back(llvm::PointerType::get(cd2->type->llvmType->get()));
+        types.push_back(getPtrToType(cd2->type->llvmType->get()));
         // void*[] vtbl
         std::vector<const llvm::Type*> vtbltypes;
         vtbltypes.push_back(DtoSize_t());
-        const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
+        const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty));
         vtbltypes.push_back(byteptrptrty);
         types.push_back(llvm::StructType::get(vtbltypes));
         // int offset
@@ -418,6 +424,12 @@
     gIR->structs.push_back(irstruct);
     gIR->classes.push_back(cd);
 
+    // get the struct (class) type
+    assert(cd->type->ty == Tclass);
+    TypeClass* ts = (TypeClass*)cd->type;
+    const llvm::StructType* structtype = isaStruct(ts->llvmType->get());
+    const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get());
+
     // make sure each offset knows its default initializer
     for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i)
     {
@@ -431,11 +443,24 @@
     std::vector<llvm::Constant*> fieldinits;
 
     // first field is always the vtable
-    assert(cd->llvmVtbl != 0);
-    fieldinits.push_back(cd->llvmVtbl);
+    if (cd->isAbstract())
+    {
+        fieldinits.push_back(
+            llvm::ConstantPointerNull::get(
+                getPtrToType(
+                    ts->llvmVtblType->get()
+                )
+            )
+        );
+    }
+    else
+    {
+        assert(cd->llvmVtbl != 0);
+        fieldinits.push_back(cd->llvmVtbl);
+    }
 
     // then comes monitor
-    fieldinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
+    fieldinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
 
     size_t dataoffset = 2;
 
@@ -443,9 +468,16 @@
     for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
     {
         IRInterface* iri = i->second;
-        assert(iri->vtbl);
-        fieldinits.push_back(iri->vtbl);
-        ++dataoffset;
+        if (cd->isAbstract())
+        {
+            fieldinits.push_back(llvm::Constant::getNullValue(iri->vtblTy));
+        }
+        else
+        {
+            assert(iri->vtbl);
+            fieldinits.push_back(iri->vtbl);
+            ++dataoffset;
+        }
     }
 
     /*
@@ -456,12 +488,6 @@
     }
     */
 
-    // get the struct (class) type
-    assert(cd->type->ty == Tclass);
-    TypeClass* ts = (TypeClass*)cd->type;
-    const llvm::StructType* structtype = isaStruct(ts->llvmType->get());
-    const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get());
-
     // go through the field inits and build the default initializer
     size_t nfi = irstruct->defaultFields.size();
     for (size_t i=0; i<nfi; ++i) {
@@ -495,111 +521,115 @@
     assert(_init);
     cd->llvmConstInit = _init;
 
-    // generate vtable initializer
-    std::vector<llvm::Constant*> sinits;
+    // abstract classes have no static vtable
+    if (!cd->isAbstract())
+    {
+        // generate vtable initializer
+        std::vector<llvm::Constant*> sinits;
 
-    for (int k=0; k < cd->vtbl.dim; k++)
-    {
-        Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k];
-        assert(dsym);
-        //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
+        for (int k=0; k < cd->vtbl.dim; k++)
+        {
+            Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k];
+            assert(dsym);
+            //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
 
-        if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
-            DtoForceDeclareDsymbol(fd);
-            assert(fd->llvmValue);
-            llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
-            // cast if necessary (overridden method)
-            if (c->getType() != vtbltype->getElementType(k))
-                c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k));
-            sinits.push_back(c);
+            if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
+                DtoForceDeclareDsymbol(fd);
+                assert(fd->llvmValue);
+                llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
+                // cast if necessary (overridden method)
+                if (c->getType() != vtbltype->getElementType(k))
+                    c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k));
+                sinits.push_back(c);
+            }
+            else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) {
+                assert(cd->llvmClass);
+                llvm::Constant* c = cd->llvmClass;
+                sinits.push_back(c);
+            }
+            else
+            assert(0);
         }
-        else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) {
-            assert(cd->llvmClass);
-            llvm::Constant* c = cd->llvmClass;
-            sinits.push_back(c);
-        }
-        else
-        assert(0);
-    }
 
-    const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
+        const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
 
 #if 0
-    for (size_t i=0; i< sinits.size(); ++i)
-    {
-        Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n';
-        Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n';
-        assert(svtbl_ty->getElementType(i) == sinits[i]->getType());
-    }
-#endif
-
-    llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits);
-    cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit);
-
-    // create interface vtable const initalizers
-    int idx = 2;
-    int idxScale = PTRSIZE;
-    for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
-    {
-        ClassDeclaration* id = i->first;
-        assert(id->type->ty == Tclass);
-        TypeClass* its = (TypeClass*)id->type;
-
-        IRInterface* iri = i->second;
-        BaseClass* b = iri->base;
-
-        const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get());
-
-        // generate interface info initializer
-        std::vector<llvm::Constant*> infoInits;
-        // classinfo
-        assert(id->llvmClass);
-        llvm::Constant* c = id->llvmClass;
-        infoInits.push_back(c);
-        // vtbl
-        const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
-        c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty);
-        c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c);
-        infoInits.push_back(c);
-        // offset
-        infoInits.push_back(DtoConstInt(idx*idxScale));
-        // create interface info initializer constant
-        iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits));
-
-        // generate vtable initializer
-        std::vector<llvm::Constant*> iinits;
-
-        // add interface info
-        iinits.push_back(iri->info);
-
-        for (int k=1; k < b->vtbl.dim; k++)
+        for (size_t i=0; i< sinits.size(); ++i)
         {
-            Logger::println("interface vtbl const init nr. %d", k);
-            Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k];
-            FuncDeclaration* fd = dsym->isFuncDeclaration();
-            assert(fd);
-            DtoForceDeclareDsymbol(fd);
-            assert(fd->llvmValue);
-            llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
-            // we have to bitcast, as the type created in ResolveClass expects a different this type
-            c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k));
-            iinits.push_back(c);
-        }
-
-#if 1
-        for (size_t x=0; x< iinits.size(); ++x)
-        {
-            Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n";
-            Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n";
-            assert(ivtbl_ty->getElementType(x) == iinits[x]->getType());
+            Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n';
+            Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n';
+            assert(svtbl_ty->getElementType(i) == sinits[i]->getType());
         }
 #endif
 
-        llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits);
-        iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit);
+        llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits);
+        cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit);
+
+        // create interface vtable const initalizers
+        int idx = 2;
+        int idxScale = PTRSIZE;
+        for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
+        {
+            ClassDeclaration* id = i->first;
+            assert(id->type->ty == Tclass);
+            TypeClass* its = (TypeClass*)id->type;
+
+            IRInterface* iri = i->second;
+            BaseClass* b = iri->base;
+
+            const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get());
+
+            // generate interface info initializer
+            std::vector<llvm::Constant*> infoInits;
+            // classinfo
+            assert(id->llvmClass);
+            llvm::Constant* c = id->llvmClass;
+            infoInits.push_back(c);
+            // vtbl
+            const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty));
+            c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty);
+            c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c);
+            infoInits.push_back(c);
+            // offset
+            infoInits.push_back(DtoConstInt(idx*idxScale));
+            // create interface info initializer constant
+            iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits));
 
-        idx++;
-    }
+            // generate vtable initializer
+            std::vector<llvm::Constant*> iinits;
+
+            // add interface info
+            iinits.push_back(iri->info);
+
+            for (int k=1; k < b->vtbl.dim; k++)
+            {
+                Logger::println("interface vtbl const init nr. %d", k);
+                Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k];
+                FuncDeclaration* fd = dsym->isFuncDeclaration();
+                assert(fd);
+                DtoForceDeclareDsymbol(fd);
+                assert(fd->llvmValue);
+                llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
+                // we have to bitcast, as the type created in ResolveClass expects a different this type
+                c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k));
+                iinits.push_back(c);
+            }
+
+    #if 1
+            for (size_t x=0; x< iinits.size(); ++x)
+            {
+                Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n";
+                Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n";
+                assert(ivtbl_ty->getElementType(x) == iinits[x]->getType());
+            }
+    #endif
+
+            llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits);
+            iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit);
+
+            idx++;
+        }
+    } // !abstract
 
     gIR->classes.pop_back();
     gIR->structs.pop_back();
@@ -621,7 +651,9 @@
 
     if (cd->getModule() == gIR->dmodule) {
         // interfaces don't have initializers
-        if (!cd->isInterfaceDeclaration()) {
+        // neither do abstract classes
+        if (!cd->isInterfaceDeclaration() && !cd->isAbstract())
+        {
             cd->llvmInit->setInitializer(cd->llvmConstInit);
             cd->llvmVtbl->setInitializer(cd->llvmConstVtbl);
 
@@ -635,7 +667,8 @@
                 infoInits.push_back(iri->infoInit);
             }
             // initialize interface info array
-            if (!infoInits.empty()) {
+            if (!infoInits.empty())
+            {
                 llvm::Constant* arrInit = llvm::ConstantArray::get(irstruct->interfaceInfosTy, infoInits);
                 irstruct->interfaceInfos->setInitializer(arrInit);
             }
@@ -648,6 +681,141 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+DValue* DtoNewClass(TypeClass* tc, NewExp* newexp)
+{
+    // resolve type
+    DtoForceDeclareDsymbol(tc->sym);
+
+    // allocate
+    llvm::Value* mem;
+    if (newexp->onstack)
+    {
+        mem = new llvm::AllocaInst(DtoType(tc)->getContainedType(0), "newclass_alloca", gIR->topallocapoint());
+    }
+    else
+    {
+        llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_newclass");
+        std::vector<llvm::Value*> args;
+        args.push_back(tc->sym->llvmClass);
+        mem = gIR->ir->CreateCall(fn, args.begin(), args.end(), "newclass_gc_alloc");
+        mem = DtoBitCast(mem, DtoType(tc), "newclass_gc");
+    }
+
+    // init
+    DtoInitClass(tc, mem);
+
+    // init inner-class outer reference
+    if (newexp->thisexp)
+    {
+        Logger::println("Resolving outer class");
+        LOG_SCOPE;
+        DValue* thisval = newexp->thisexp->toElem(gIR);
+        size_t idx = 2;
+        idx += tc->sym->llvmIRStruct->interfaces.size();
+        llvm::Value* dst = thisval->getRVal();
+        llvm::Value* src = DtoGEPi(mem,0,idx,"tmp");
+        Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n';
+        DtoStore(dst, src);
+    }
+    // set the context for nested classes
+    else if (tc->sym->isNested())
+    {
+        Logger::println("Resolving nested context");
+        LOG_SCOPE;
+        size_t idx = 2;
+        idx += tc->sym->llvmIRStruct->interfaces.size();
+        llvm::Value* nest = gIR->func()->decl->llvmNested;
+        if (!nest)
+            nest = gIR->func()->decl->llvmThisVar;
+        assert(nest);
+        llvm::Value* gep = DtoGEPi(mem,0,idx,"tmp");
+        nest = DtoBitCast(nest, gep->getType()->getContainedType(0));
+        DtoStore(nest, gep);
+    }
+
+    // call constructor
+    if (newexp->arguments)
+        return DtoCallClassCtor(tc, newexp->member, newexp->arguments, mem);
+
+    // return default constructed class
+    return new DImValue(tc, mem, false);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoInitClass(TypeClass* tc, llvm::Value* dst)
+{
+    size_t presz = 2*getABITypeSize(DtoSize_t());
+    uint64_t n = getABITypeSize(tc->llvmType->get()) - presz;
+
+    // set vtable field seperately, this might give better optimization
+    assert(tc->sym->llvmVtbl);
+    DtoStore(tc->sym->llvmVtbl, DtoGEPi(dst,0,0,"vtbl"));
+
+    // monitor always defaults to zero
+    llvm::Value* tmp = DtoGEPi(dst,0,1,"monitor");
+    DtoStore(llvm::Constant::getNullValue(tmp->getType()->getContainedType(0)), tmp);
+
+    // done?
+    if (n == 0)
+        return;
+
+    // copy the rest from the static initializer
+    assert(tc->sym->llvmInit);
+    assert(dst->getType() == tc->sym->llvmInit->getType());
+
+    const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
+
+    llvm::Value* dstarr = DtoGEPi(dst,0,2,"tmp");
+    dstarr = DtoBitCast(dstarr, arrty);
+
+    llvm::Value* srcarr = DtoGEPi(tc->sym->llvmInit,0,2,"tmp");
+    srcarr = DtoBitCast(srcarr, arrty);
+
+    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());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DtoCallClassCtor(TypeClass* type, CtorDeclaration* ctor, Array* arguments, llvm::Value* mem)
+{
+    Logger::println("Calling constructor");
+    LOG_SCOPE;
+
+    assert(ctor);
+    DtoForceDeclareDsymbol(ctor);
+    llvm::Function* fn = llvm::cast<llvm::Function>(ctor->llvmValue);
+    TypeFunction* tf = (TypeFunction*)DtoDType(ctor->type);
+
+    std::vector<llvm::Value*> ctorargs;
+    ctorargs.push_back(mem);
+    for (size_t i=0; i<arguments->dim; ++i)
+    {
+        Expression* ex = (Expression*)arguments->data[i];
+        Argument* fnarg = Argument::getNth(tf->parameters, i);
+        DValue* argval = DtoArgument(fnarg, ex);
+        llvm::Value* a = argval->getRVal();
+        const llvm::Type* aty = fn->getFunctionType()->getParamType(i+1);
+        if (a->getType() != aty)
+            a = DtoBitCast(a, aty);
+        ctorargs.push_back(a);
+    }
+    llvm::CallInst* call = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", gIR->scopebb());
+    call->setCallingConv(DtoCallingConv(LINKd));
+
+    return new DImValue(type, call, false);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance)
 {
     Array* arr = &tc->sym->dtors;
@@ -661,46 +829,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-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->get()) - 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->sym->llvmInit);
-        assert(dst->getType() == tc->sym->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->sym->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());
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 DValue* DtoCastClass(DValue* val, Type* _to)
 {
     Type* to = DtoDType(_to);
@@ -717,8 +845,12 @@
     TypeClass* fc = (TypeClass*)from;
 
     if (tc->sym->isInterfaceDeclaration()) {
-        assert(!fc->sym->isInterfaceDeclaration());
-        return DtoDynamicCastObject(val, _to);
+        if (fc->sym->isInterfaceDeclaration()) {
+            return DtoDynamicCastInterface(val, _to);
+        }
+        else {
+            return DtoDynamicCastObject(val, _to);
+        }
     }
     else {
         int poffset;
@@ -805,6 +937,45 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+DValue* DtoDynamicCastInterface(DValue* val, Type* _to)
+{
+    // call:
+    // Object _d_interface_cast(void* p, ClassInfo c)
+
+    DtoForceDeclareDsymbol(ClassDeclaration::object);
+    DtoForceDeclareDsymbol(ClassDeclaration::classinfo);
+
+    llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_interface_cast");
+    const llvm::FunctionType* funcTy = func->getFunctionType();
+
+    std::vector<llvm::Value*> args;
+
+    // void* p
+    llvm::Value* tmp = val->getRVal();
+    tmp = DtoBitCast(tmp, funcTy->getParamType(0));
+    args.push_back(tmp);
+
+    // ClassInfo c
+    TypeClass* to = (TypeClass*)DtoDType(_to);
+    DtoForceDeclareDsymbol(to->sym);
+    assert(to->sym->llvmClass);
+    tmp = to->sym->llvmClass;
+    // unfortunately this is needed as the implementation of object differs somehow from the declaration
+    // this could happen in user code as well :/
+    tmp = DtoBitCast(tmp, funcTy->getParamType(1));
+    args.push_back(tmp);
+
+    // call it
+    llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp");
+
+    // cast return value
+    ret = DtoBitCast(ret, DtoType(_to));
+
+    return new DImValue(_to, ret);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx)
 {
     // start at the bottom of the inheritance chain
@@ -851,7 +1022,7 @@
     if (idxs.empty())
         idxs.push_back(0);
 
-    const llvm::Type* llt = llvm::PointerType::get(DtoType(t));
+    const llvm::Type* llt = getPtrToType(DtoType(t));
     const llvm::Type* st = DtoType(cd->type);
     if (ptr->getType() != st) {
         assert(cd->llvmHasUnions);
@@ -895,7 +1066,7 @@
                 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
             }
             else {
-                const llvm::Type* sty = llvm::PointerType::get(DtoType(vd->type));
+                const llvm::Type* sty = getPtrToType(DtoType(vd->type));
                 if (ptr->getType() != sty) {
                     ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
                     std::vector<unsigned> tmp;
@@ -910,7 +1081,7 @@
 
     assert(0);
 
-    size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
+    size_t llt_sz = getABITypeSize(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());
@@ -918,6 +1089,29 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+llvm::Value* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl)
+{
+    assert(fdecl->isVirtual());//fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual()));
+    assert(fdecl->vtblIndex > 0);
+    assert(DtoDType(inst->getType())->ty == Tclass);
+
+    llvm::Value* vthis = inst->getRVal();
+    //Logger::cout() << "vthis: " << *vthis << '\n';
+
+    llvm::Value* funcval;
+    funcval = DtoGEPi(vthis, 0, 0, "tmp");
+    funcval = DtoLoad(funcval);
+    funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toPrettyChars());
+    funcval = DtoLoad(funcval);
+
+    //assert(funcval->getType() == DtoType(fdecl->type));
+    //cc = DtoCallingConv(fdecl->linkage);
+
+    return funcval;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 void DtoDeclareClassInfo(ClassDeclaration* cd)
 {
     if (cd->llvmClassDeclared) return;
@@ -961,7 +1155,7 @@
     DtoForceDeclareDsymbol(vd->type->vtinfo);
     llvm::Constant* c = isaConstant(vd->type->vtinfo->llvmValue);
 
-    const llvm::Type* tiTy = llvm::PointerType::get(Type::typeinfo->type->llvmType->get());
+    const llvm::Type* tiTy = getPtrToType(Type::typeinfo->type->llvmType->get());
     //Logger::cout() << "tiTy = " << *tiTy << '\n';
 
     types.push_back(tiTy);
@@ -1002,7 +1196,7 @@
         // OffsetTypeInfo type
         std::vector<const llvm::Type*> elemtypes;
         elemtypes.push_back(DtoSize_t());
-        const llvm::Type* tiTy = llvm::PointerType::get(Type::typeinfo->type->llvmType->get());
+        const llvm::Type* tiTy = getPtrToType(Type::typeinfo->type->llvmType->get());
         elemtypes.push_back(tiTy);
         const llvm::StructType* sTy = llvm::StructType::get(elemtypes);
 
@@ -1013,7 +1207,7 @@
         std::string name(cd->type->vtinfo->toChars());
         name.append("__OffsetTypeInfos");
         llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,llvm::GlobalValue::InternalLinkage,arrInit,name,gIR->module);
-        ptr = llvm::ConstantExpr::getBitCast(gvar, llvm::PointerType::get(sTy));
+        ptr = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(sTy));
     }
     else {
         ptr = llvm::ConstantPointerNull::get(isaPointer(initTy->getElementType(1)));
@@ -1026,18 +1220,18 @@
 {
     // construct the function
     std::vector<const llvm::Type*> paramTypes;
-    paramTypes.push_back(llvm::PointerType::get(cd->type->llvmType->get()));
+    paramTypes.push_back(getPtrToType(cd->type->llvmType->get()));
 
     const llvm::FunctionType* fnTy = llvm::FunctionType::get(llvm::Type::VoidTy, paramTypes, false);
 
     if (cd->dtors.dim == 0) {
-        return llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
+        return llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty));
     }
     else if (cd->dtors.dim == 1) {
         DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[0];
         DtoForceDeclareDsymbol(d);
         assert(d->llvmValue);
-        return llvm::ConstantExpr::getBitCast(isaConstant(d->llvmValue), llvm::PointerType::get(llvm::Type::Int8Ty));
+        return llvm::ConstantExpr::getBitCast(isaConstant(d->llvmValue), getPtrToType(llvm::Type::Int8Ty));
     }
 
     std::string gname("_D");
@@ -1060,7 +1254,7 @@
     }
     builder.CreateRetVoid();
 
-    return llvm::ConstantExpr::getBitCast(func, llvm::PointerType::get(llvm::Type::Int8Ty));
+    return llvm::ConstantExpr::getBitCast(func, getPtrToType(llvm::Type::Int8Ty));
 }
 
 static uint build_classinfo_flags(ClassDeclaration* cd)
@@ -1121,7 +1315,7 @@
     assert(cd->llvmClass);
 
     TypeClass* cdty = (TypeClass*)cd->type;
-    if (!cd->isInterfaceDeclaration()) {
+    if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) {
         assert(cd->llvmInit);
         assert(cd->llvmConstInit);
         assert(cd->llvmVtbl);
@@ -1147,14 +1341,14 @@
     inits.push_back(c);
 
     // byte[] init
-    const llvm::Type* byteptrty = llvm::PointerType::get(llvm::Type::Int8Ty);
-    if (cd->isInterfaceDeclaration()) {
+    const llvm::Type* byteptrty = getPtrToType(llvm::Type::Int8Ty);
+    if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
         c = cinfo->llvmConstInit->getOperand(2);
     }
     else {
         c = llvm::ConstantExpr::getBitCast(cd->llvmInit, byteptrty);
         assert(!cd->llvmConstInit->getType()->isAbstract());
-        size_t initsz = gTargetData->getTypeSize(cd->llvmConstInit->getType());
+        size_t initsz = getABITypeSize(cd->llvmConstInit->getType());
         c = DtoConstSlice(DtoConstSize_t(initsz), c);
     }
     inits.push_back(c);
@@ -1172,11 +1366,11 @@
     inits.push_back(c);
 
     // vtbl array
-    if (cd->isInterfaceDeclaration()) {
+    if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
         c = cinfo->llvmConstInit->getOperand(4);
     }
     else {
-        const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty);
+        const llvm::Type* byteptrptrty = getPtrToType(byteptrty);
         assert(!cd->llvmVtbl->getType()->isAbstract());
         c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty);
         assert(!cd->llvmConstVtbl->getType()->isAbstract());
@@ -1187,7 +1381,7 @@
 
     // interfaces array
     IRStruct* irstruct = cd->llvmIRStruct;
-    if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos) {
+    if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos || cd->isAbstract()) {
         c = cinfo->llvmConstInit->getOperand(5);
     }
     else {
@@ -1199,7 +1393,7 @@
     inits.push_back(c);
 
     // base classinfo
-    if (cd->baseClass && !cd->isInterfaceDeclaration()) {
+    if (cd->baseClass && !cd->isInterfaceDeclaration() && !cd->isAbstract()) {
         DtoDeclareClassInfo(cd->baseClass);
         c = cd->baseClass->llvmClass;
         assert(c);
@@ -1212,7 +1406,7 @@
     }
 
     // destructor
-    if (cd->isInterfaceDeclaration()) {
+    if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
         c = cinfo->llvmConstInit->getOperand(7);
     }
     else {
@@ -1226,7 +1420,7 @@
     inits.push_back(c);
 
     // uint flags
-    if (cd->isInterfaceDeclaration()) {
+    if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
         c = cinfo->llvmConstInit->getOperand(9);
     }
     else {
@@ -1241,7 +1435,7 @@
     inits.push_back(c);
 
     // offset typeinfo
-    if (cd->isInterfaceDeclaration()) {
+    if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
         c = cinfo->llvmConstInit->getOperand(11);
     }
     else {
@@ -1250,7 +1444,7 @@
     inits.push_back(c);
 
     // default constructor
-    if (cd->defaultCtor && !cd->isInterfaceDeclaration()) {
+    if (cd->defaultCtor && !cd->isInterfaceDeclaration() && !cd->isAbstract()) {
         DtoForceDeclareDsymbol(cd->defaultCtor);
         c = isaConstant(cd->defaultCtor->llvmValue);
         const llvm::Type* toTy = cinfo->llvmConstInit->getOperand(12)->getType();
--- a/gen/classes.h	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/classes.h	Mon Jan 14 05:11:54 2008 +0100
@@ -24,13 +24,19 @@
 void DtoDeclareClassInfo(ClassDeclaration* cd);
 void DtoDefineClassInfo(ClassDeclaration* cd);
 
+DValue* DtoNewClass(TypeClass* type, NewExp* newexp);
+void DtoInitClass(TypeClass* tc, llvm::Value* dst);
+DValue* DtoCallClassCtor(TypeClass* type, CtorDeclaration* ctor, Array* arguments, llvm::Value* mem);
 void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance);
-void DtoInitClass(TypeClass* tc, llvm::Value* dst);
 
 DValue* DtoCastClass(DValue* val, Type* to);
 DValue* DtoDynamicCastObject(DValue* val, Type* to);
+
 DValue* DtoCastInterfaceToObject(DValue* val, Type* to);
+DValue* DtoDynamicCastInterface(DValue* val, Type* to);
 
 llvm::Value* DtoIndexClass(llvm::Value* ptr, ClassDeclaration* cd, Type* t, unsigned os, std::vector<unsigned>& idxs);
 
+llvm::Value* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl);
+
 #endif
--- a/gen/complex.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/complex.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -135,9 +135,9 @@
     llvm::Constant* undef = llvm::UndefValue::get(base);
     llvm::Constant* zero;
     if (ty == Tfloat32 || ty == Timaginary32 || ty == Tcomplex32)
-        zero = llvm::ConstantFP::get(llvm::Type::FloatTy, float(0));
+        zero = llvm::ConstantFP::get(llvm::Type::FloatTy, llvm::APFloat(0.0f));
     else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tcomplex64 || ty == Tfloat80 || ty == Timaginary80 || ty == Tcomplex80)
-        zero = llvm::ConstantFP::get(llvm::Type::DoubleTy, double(0));
+        zero = llvm::ConstantFP::get(llvm::Type::DoubleTy, llvm::APFloat(0.0));
 
     if (t->isimaginary()) {
         return new DComplexValue(to, zero, val->getRVal());
--- a/gen/dwarftypes.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/dwarftypes.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -32,10 +32,10 @@
   std::vector<const Type*>StructTy_1_fields;
   StructType* StructTy_1 = StructType::get(StructTy_1_fields, /*isPacked=*/false);
   
-  PointerType* PointerTy_0 = PointerType::get(StructTy_1);
+  PointerType* PointerTy_0 = PointerType::get(StructTy_1,0);
   
   StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_0);
-  PointerType* PointerTy_2 = PointerType::get(IntegerType::get(8));
+  PointerType* PointerTy_2 = PointerType::get(IntegerType::get(8),0);
   
   StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_2);
   StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_0);
@@ -130,33 +130,27 @@
 
   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);
+    /*isVarArg=*/false);
   
   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);
+    /*isVarArg=*/false);
   
   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);
+    /*isVarArg=*/false);
   
   
   // Function Declarations
--- a/gen/functions.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/functions.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -47,7 +47,7 @@
         assert(rt);
         Type* rtfin = DtoDType(rt);
         if (DtoIsPassedByRef(rt)) {
-            rettype = llvm::PointerType::get(DtoType(rt));
+            rettype = getPtrToType(DtoType(rt));
             actualRettype = llvm::Type::VoidTy;
             f->llvmRetInPtr = retinptr = true;
         }
@@ -77,10 +77,10 @@
         assert(ti->llvmConstInit);
         std::vector<const llvm::Type*> types;
         types.push_back(DtoSize_t());
-        types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmConstInit->getType())));
+        types.push_back(getPtrToType(getPtrToType(ti->llvmConstInit->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));
+        paramvec.push_back(getPtrToType(t1));
+        paramvec.push_back(getPtrToType(llvm::Type::Int8Ty));
     }
 
     size_t n = Argument::dim(f->parameters);
@@ -94,23 +94,23 @@
         const llvm::Type* at = DtoType(argT);
         if (isaStruct(at)) {
             Logger::println("struct param");
-            paramvec.push_back(llvm::PointerType::get(at));
+            paramvec.push_back(getPtrToType(at));
         }
         else if (isaArray(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));
+            //paramvec.push_back(getPtrToType(at->getContainedType(0)));
+            paramvec.push_back(getPtrToType(at));
         }
         else if (llvm::isa<llvm::OpaqueType>(at)) {
             Logger::println("opaque param");
             assert(argT->ty == Tstruct || argT->ty == Tclass);
-            paramvec.push_back(llvm::PointerType::get(at));
+            paramvec.push_back(getPtrToType(at));
         }
         else {
             if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
                 Logger::println("by ref param");
-                at = llvm::PointerType::get(at);
+                at = getPtrToType(at);
             }
             else {
                 Logger::println("in param");
@@ -146,7 +146,7 @@
     TypeFunction* f = (TypeFunction*)fdecl->type;
     assert(f != 0);
 
-    const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::PointerType* i8pty = getPtrToType(llvm::Type::Int8Ty);
     std::vector<const llvm::Type*> args;
 
     if (fdecl->llvmInternal == LLVMva_start) {
@@ -194,7 +194,7 @@
             thisty = DtoType(ad->type);
             //Logger::cout() << "this llvm type: " << *thisty << '\n';
             if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->recty.get()))
-                thisty = llvm::PointerType::get(thisty);
+                thisty = getPtrToType(thisty);
         }
         else {
             Logger::println("chars: %s type: %s kind: %s", fdecl->toChars(), fdecl->type->toChars(), fdecl->kind());
@@ -202,7 +202,7 @@
         }
     }
     else if (fdecl->isNested()) {
-        thisty = llvm::PointerType::get(llvm::Type::Int8Ty);
+        thisty = getPtrToType(llvm::Type::Int8Ty);
     }
 
     const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain());
@@ -244,6 +244,13 @@
         return; // ignore declaration completely
     }
 
+    // is imported and we don't have access?
+    if (fdecl->getModule() != gIR->dmodule)
+    {
+        if (fdecl->prot() == PROTprivate)
+            return;
+    }
+
     if (fdecl->llvmResolved) return;
     fdecl->llvmResolved = true;
 
@@ -427,6 +434,8 @@
 
     if (!declareOnly)
         gIR->defineList.push_back(fdecl);
+    else
+        assert(func->getLinkage() != llvm::GlobalValue::InternalLinkage);
 
     Logger::cout() << "func decl: " << *func << '\n';
 }
@@ -637,9 +646,9 @@
     // 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* chPtrType = (const llvm::Type*)getPtrToType(llvm::Type::Int8Ty);
+    pvec.push_back((const llvm::Type*)getPtrToType(chPtrType));
+    pvec.push_back((const llvm::Type*)getPtrToType(chPtrType));
     const llvm::Type* rettype = (const llvm::Type*)llvm::Type::Int32Ty;
 
     llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false);
--- a/gen/runtime.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/runtime.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -133,7 +133,7 @@
 
 static const llvm::Type* rt_ptr(const llvm::Type* t)
 {
-    return llvm::PointerType::get(t);
+    return getPtrToType(t);
 }
 
 static const llvm::Type* rt_array(const llvm::Type* elemty)
@@ -197,15 +197,30 @@
     /////////////////////////////////////////////////////////////////////////////////////
     /////////////////////////////////////////////////////////////////////////////////////
 
-    // assert
-    // void _d_assert(bool cond, uint line, char[] msg)
+    // void _d_assert( char[] file, uint line )
+    // void _d_array_bounds( char[] file, uint line )
+    // void _d_switch_error( char[] file, uint line )
     {
         std::string fname("_d_assert");
+        std::string fname2("_d_array_bounds");
+        std::string fname3("_d_switch_error");
         std::vector<const llvm::Type*> types;
-        types.push_back(boolTy);
+        types.push_back(stringTy);
         types.push_back(intTy);
+        const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
+        new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
+        new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
+        new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname3, M);
+    }
+
+    // void _d_assert_msg( char[] msg, char[] file, uint line )
+    {
+        std::string fname("_d_assert_msg");
+        std::vector<const llvm::Type*> types;
         types.push_back(stringTy);
-        const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
+        types.push_back(stringTy);
+        types.push_back(intTy);
+        const llvm::FunctionType* fty = llvm::FunctionType::get(voidPtrTy, types, false);
         new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
     }
 
@@ -234,6 +249,15 @@
         new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
     }
 
+    // Object _d_newclass(ClassInfo ci)
+    {
+        std::string fname("_d_newclass");
+        std::vector<const llvm::Type*> types;
+        types.push_back(classInfoTy);
+        const llvm::FunctionType* fty = llvm::FunctionType::get(objectTy, types, false);
+        new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
+    }
+
     /////////////////////////////////////////////////////////////////////////////////////
     /////////////////////////////////////////////////////////////////////////////////////
     /////////////////////////////////////////////////////////////////////////////////////
@@ -626,6 +650,51 @@
         new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
     }
 
+    /////////////////////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    // Object _d_toObject(void* p)
+    {
+        std::string fname("_d_toObject");
+        std::vector<const llvm::Type*> types;
+        types.push_back(voidPtrTy);
+        const llvm::FunctionType* fty = llvm::FunctionType::get(objectTy, types, false);
+        new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
+    }
+
+    // Object _d_dynamic_cast(Object o, ClassInfo c)
+    {
+        std::string fname("_d_dynamic_cast");
+        std::vector<const llvm::Type*> types;
+        types.push_back(objectTy);
+        types.push_back(classInfoTy);
+        const llvm::FunctionType* fty = llvm::FunctionType::get(objectTy, types, false);
+        new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
+    }
+
+    // Object _d_interface_cast(void* p, ClassInfo c)
+    {
+        std::string fname("_d_interface_cast");
+        std::vector<const llvm::Type*> types;
+        types.push_back(voidPtrTy);
+        types.push_back(classInfoTy);
+        const llvm::FunctionType* fty = llvm::FunctionType::get(objectTy, types, false);
+        new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
+    }
+
+    /////////////////////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    // void _d_throw_exception(Object e)
+    {
+        std::string fname("_d_throw_exception");
+        std::vector<const llvm::Type*> types;
+        types.push_back(objectTy);
+        const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
+        new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
+    }
 }
 
 
--- a/gen/statements.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/statements.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -8,6 +8,7 @@
 
 #include "gen/llvm.h"
 #include "llvm/InlineAsm.h"
+#include "llvm/Support/CFG.h"
 
 #include "mars.h"
 #include "total.h"
@@ -488,17 +489,39 @@
     Logger::println("TryCatchStatement::toIR(): %s", loc.toChars());
     LOG_SCOPE;
 
-    Logger::attention(loc, "try-catch is not yet fully implemented, only the try block will be emitted.");
+    Logger::attention(loc, "try-catch is not yet fully implemented");
+
+    // create basic blocks
+    llvm::BasicBlock* oldend = p->scopeend();
 
+    llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend);
+    llvm::BasicBlock* catchbb = new llvm::BasicBlock("catch", p->topfunc(), oldend);
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("endtrycatch", 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,catchbb);
     assert(body);
     body->toIR(p);
 
+    if (!gIR->scopereturned())
+        new llvm::BranchInst(endbb, p->scopebb());
+
+    // do catch
+    p->scope() = IRScope(catchbb,oldend);
+    new llvm::BranchInst(endbb, p->scopebb());
     /*assert(catches);
     for(size_t i=0; i<catches->dim; ++i)
     {
         Catch* c = (Catch*)catches->data[i];
         c->handler->toIR(p);
     }*/
+
+    // rewrite the scope
+    p->scope() = IRScope(endbb,oldend);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -508,15 +531,16 @@
     Logger::println("ThrowStatement::toIR(): %s", loc.toChars());
     LOG_SCOPE;
 
-    Logger::attention(loc, "throw is not yet implemented, replacing expression with assert(0);");
+    Logger::attention(loc, "throw is not yet fully implemented");
 
-    DtoAssert(NULL, &loc, NULL);
-
-    /*
     assert(exp);
     DValue* e = exp->toElem(p);
-    delete e;
-    */
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_throw_exception");
+    //Logger::cout() << "calling: " << *fn << '\n';
+    llvm::Value* arg = DtoBitCast(e->getRVal(), fn->getFunctionType()->getParamType(0));
+    //Logger::cout() << "arg: " << *arg << '\n';
+    gIR->ir->CreateCall(fn, arg, "");
+    gIR->ir->CreateUnreachable();
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -629,7 +653,7 @@
         llvm::Constant* arrInit = llvm::ConstantArray::get(arrTy, inits);
         llvm::GlobalVariable* arr = new llvm::GlobalVariable(arrTy, true, llvm::GlobalValue::InternalLinkage, arrInit, "string_switch_table_data", gIR->module);
 
-        const llvm::Type* elemPtrTy = llvm::PointerType::get(elemTy);
+        const llvm::Type* elemPtrTy = getPtrToType(elemTy);
         llvm::Constant* arrPtr = llvm::ConstantExpr::getBitCast(arr, elemPtrTy);
 
         // build the static table
@@ -824,8 +848,8 @@
 
     if (niters->getType() != keytype)
     {
-        size_t sz1 = gTargetData->getTypeSize(niters->getType());
-        size_t sz2 = gTargetData->getTypeSize(keytype);
+        size_t sz1 = getTypeBitSize(niters->getType());
+        size_t sz2 = getTypeBitSize(keytype);
         if (sz1 < sz2)
             niters = gIR->ir->CreateZExt(niters, keytype, "foreachtrunckey");
         else if (sz1 > sz2)
--- a/gen/structs.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/structs.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -27,11 +27,11 @@
 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);
+    uint64_t n = getTypeStoreSize(v->getType()->getContainedType(0));
+    //llvm::Type* sarrty = getPtrToType(llvm::ArrayType::get(llvm::Type::Int8Ty, n));
+    const llvm::Type* sarrty = getPtrToType(llvm::Type::Int8Ty);
 
-    llvm::Value* sarr = new llvm::BitCastInst(v,sarrty,"tmp",gIR->scopebb());
+    llvm::Value* sarr = DtoBitCast(v, sarrty);
 
     llvm::Function* fn = LLVM_DeclareMemSet32();
     std::vector<llvm::Value*> llargs;
@@ -54,9 +54,9 @@
     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);
+    uint64_t n = getTypeStoreSize(dst->getType()->getContainedType(0));
+    //llvm::Type* sarrty = getPtrToType(llvm::ArrayType::get(llvm::Type::Int8Ty, n));
+    const llvm::Type* arrty = getPtrToType(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());
@@ -110,8 +110,8 @@
     if (idxs.empty())
         idxs.push_back(0);
 
-    const llvm::Type* llt = llvm::PointerType::get(DtoType(t));
-    const llvm::Type* st = llvm::PointerType::get(DtoType(sd->type));
+    const llvm::Type* llt = getPtrToType(DtoType(t));
+    const llvm::Type* st = getPtrToType(DtoType(sd->type));
     if (ptr->getType() != st) {
         assert(sd->llvmHasUnions);
         ptr = gIR->ir->CreateBitCast(ptr, st, "tmp");
@@ -139,15 +139,15 @@
                 Logger::println("has union field offset");
                 ptr = DtoGEP(ptr, idxs, "tmp");
                 if (ptr->getType() != llt)
-                    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
+                    ptr = DtoBitCast(ptr, llt);
                 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));
+                const llvm::Type* sty = getPtrToType(DtoType(vd->type));
                 if (ptr->getType() != sty) {
-                    ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
+                    ptr = DtoBitCast(ptr, sty);
                     std::vector<unsigned> tmp;
                     return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
                 }
@@ -158,9 +158,9 @@
         }
     }
 
-    size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
+    size_t llt_sz = getTypeStoreSize(llt->getContainedType(0));
     assert(os % llt_sz == 0);
-    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
+    ptr = DtoBitCast(ptr, llt);
     return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
 }
 
@@ -180,12 +180,34 @@
     sd->llvmIRStruct = irstruct;
     gIR->structs.push_back(irstruct);
 
+    // fields
     Array* arr = &sd->fields;
     for (int k=0; k < arr->dim; k++) {
-        VarDeclaration* v = (VarDeclaration*)(arr->data[k]);
+        VarDeclaration* v = (VarDeclaration*)arr->data[k];
         v->toObjFile();
     }
 
+    bool thisModule = false;
+    if (sd->getModule() == gIR->dmodule)
+        thisModule = true;
+
+    // methods
+    arr = sd->members;
+    for (int k=0; k < arr->dim; k++) {
+        Dsymbol* s = (Dsymbol*)arr->data[k];
+        if (FuncDeclaration* fd = s->isFuncDeclaration()) {
+            if (thisModule || (fd->prot() != PROTprivate)) {
+                fd->toObjFile();
+            }
+        }
+        else if (s->isAttribDeclaration()) {
+            s->toObjFile();
+        }
+        else {
+            Logger::println("Ignoring dsymbol '%s' in this->members of kind '%s'", s->toPrettyChars(), s->kind());
+        }
+    }
+
     /*for (int k=0; k < sd->members->dim; k++) {
         Dsymbol* dsym = (Dsymbol*)(sd->members->data[k]);
         dsym->toObjFile();
@@ -218,12 +240,12 @@
                 assert(lastoffset == 0);
                 fieldtype = i->second.type;
                 fieldinit = i->second.var;
-                prevsize = gTargetData->getTypeSize(fieldtype);
+                prevsize = getABITypeSize(fieldtype);
                 i->second.var->llvmFieldIndex = idx;
             }
             // colliding offset?
             else if (lastoffset == i->first) {
-                size_t s = gTargetData->getTypeSize(i->second.type);
+                size_t s = getABITypeSize(i->second.type);
                 if (s > prevsize) {
                     fieldpad += s - prevsize;
                     prevsize = s;
@@ -233,7 +255,7 @@
             }
             // intersecting offset?
             else if (i->first < (lastoffset + prevsize)) {
-                size_t s = gTargetData->getTypeSize(i->second.type);
+                size_t s = getABITypeSize(i->second.type);
                 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
                 sd->llvmHasUnions = true;
                 i->second.var->llvmFieldIndex = idx;
@@ -256,7 +278,7 @@
                 lastoffset = i->first;
                 fieldtype = i->second.type;
                 fieldinit = i->second.var;
-                prevsize = gTargetData->getTypeSize(fieldtype);
+                prevsize = getABITypeSize(fieldtype);
                 i->second.var->llvmFieldIndex = idx;
                 fieldpad = 0;
             }
@@ -420,7 +442,7 @@
         unsigned o = i->first;
         IRStruct::Offset* so = &i->second;
         const llvm::Type* ft = so->init->getType();
-        size_t sz = gTargetData->getTypeSize(ft);
+        size_t sz = getABITypeSize(ft);
         if (f == NULL) { // new field
             fields.push_back(DUnionField());
             f = &fields.back();
@@ -495,7 +517,7 @@
 
         if (ii < nin && fi == in[ii].idx)
         {
-            size_t s = gTargetData->getTypeSize(in[ii].c->getType());
+            size_t s = getABITypeSize(in[ii].c->getType());
             if (in[ii].idx == last)
             {
                 size_t nos = in[ii].idxos * s;
--- a/gen/todebug.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/todebug.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -15,7 +15,7 @@
 
 static const llvm::PointerType* ptrTy(const llvm::Type* t)
 {
-    return llvm::PointerType::get(t);
+    return llvm::PointerType::get(t, 0);
 }
 
 static const llvm::PointerType* dbgArrTy()
--- a/gen/toir.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/toir.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -179,7 +179,7 @@
             assert(tid->llvmValue);
             const llvm::Type* vartype = DtoType(type);
             llvm::Value* m;
-            if (tid->llvmValue->getType() != llvm::PointerType::get(vartype))
+            if (tid->llvmValue->getType() != getPtrToType(vartype))
                 m = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp");
             else
                 m = tid->llvmValue;
@@ -278,7 +278,7 @@
         const llvm::Type* vartype = DtoType(type);
         llvm::Constant* m = isaConstant(ti->llvmValue);
         assert(m);
-        if (ti->llvmValue->getType() != llvm::PointerType::get(vartype))
+        if (ti->llvmValue->getType() != getPtrToType(vartype))
             m = llvm::ConstantExpr::getBitCast(m, vartype);
         return m;
     }
@@ -403,11 +403,13 @@
     Type* cty = DtoDType(dtype->next);
 
     const llvm::Type* ct = DtoType(cty);
+    if (ct == llvm::Type::VoidTy)
+        ct = llvm::Type::Int8Ty;
     //printf("ct = %s\n", type->next->toChars());
     const llvm::ArrayType* at = llvm::ArrayType::get(ct,len+1);
 
     llvm::Constant* _init;
-    if (cty->ty == Tchar) {
+    if (cty->ty == Tchar || cty->ty == Tvoid) {
         uint8_t* str = (uint8_t*)string;
         std::string cont((char*)str, len);
         _init = llvm::ConstantArray::get(cont,true);
@@ -434,6 +436,7 @@
     assert(0);
 
     llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
+    Logger::cout() << "type: " << *at << "\ninit: " << *_init << '\n';
     llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,"stringliteral",gIR->module);
 
     llvm::ConstantInt* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
@@ -461,7 +464,7 @@
         assert(0);
     }
     else if (dtype->ty == Tsarray) {
-        const llvm::Type* dstType = llvm::PointerType::get(llvm::ArrayType::get(ct, len));
+        const llvm::Type* dstType = getPtrToType(llvm::ArrayType::get(ct, len));
         llvm::Value* emem = (gvar->getType() == dstType) ? gvar : DtoBitCast(gvar, dstType);
         return new DVarValue(type, emem, true);
     }
@@ -877,7 +880,7 @@
             Type* t = DtoDType(type);
             const llvm::Type* llt = DtoType(type);
             if (DtoIsPassedByRef(t))
-                llt = llvm::PointerType::get(llt);
+                llt = getPtrToType(llt);
             // TODO
             if (strcmp(global.params.llvmArch, "x86") != 0) {
                 warning("%s: va_arg for C variadic functions is broken for anything but x86", loc.toChars());
@@ -972,7 +975,7 @@
         }
 
         if (dfn && dfn->func && dfn->func->llvmRunTimeHack) {
-            const llvm::Type* rettype = llvm::PointerType::get(DtoType(type));
+            const llvm::Type* rettype = getPtrToType(DtoType(type));
             if (llargs[j]->getType() != llfnty->getParamType(j)) {
                 Logger::println("llvmRunTimeHack==true - force casting return value param");
                 Logger::cout() << "casting: " << *llargs[j] << " to type: " << *llfnty->getParamType(j) << '\n';
@@ -986,9 +989,9 @@
 
     // this arguments
     if (dfn && dfn->vthis) {
-        Logger::println("This Call");
+        Logger::cout() << "This Call func val:" << *funcval << '\n';
         if (dfn->vthis->getType() != argiter->get()) {
-            //Logger::cout() << *fn->thisparam << '|' << *argiter->get() << '\n';
+            //Logger::cout() << "value: " << *dfn->vthis << " totype: " << *argiter->get() << '\n';
             llargs[j] = DtoBitCast(dfn->vthis, argiter->get());
         }
         else {
@@ -1010,8 +1013,8 @@
         Logger::println("Nested Call");
         llvm::Value* contextptr = DtoNestedContext(dfn->func->toParent2()->isFuncDeclaration());
         if (!contextptr)
-            contextptr = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
-        llargs[j] = DtoBitCast(contextptr, llvm::PointerType::get(llvm::Type::Int8Ty));
+            contextptr = llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty));
+        llargs[j] = DtoBitCast(contextptr, getPtrToType(llvm::Type::Int8Ty));
         ++j;
         ++argiter;
     }
@@ -1025,7 +1028,7 @@
             Argument* fnarg = Argument::getNth(tf->parameters, i);
             Expression* exp = (Expression*)arguments->data[i];
             DValue* expelem = exp->toElem(p);
-            llargs[j] = DtoBitCast(expelem->getLVal(), llvm::PointerType::get(llvm::Type::Int8Ty));
+            llargs[j] = DtoBitCast(expelem->getLVal(), getPtrToType(llvm::Type::Int8Ty));
         }
     }
     // regular arguments
@@ -1062,7 +1065,7 @@
 
             // build type info array
             assert(Type::typeinfo->llvmConstInit);
-            const llvm::Type* typeinfotype = llvm::PointerType::get(Type::typeinfo->llvmConstInit->getType());
+            const llvm::Type* typeinfotype = getPtrToType(Type::typeinfo->llvmConstInit->getType());
             Logger::cout() << "typeinfo ptr type: " << *typeinfotype << '\n';
             const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements());
 
@@ -1081,13 +1084,13 @@
             // put data in d-array
             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");
+            llvm::Value* casttypeinfomem = p->ir->CreateBitCast(typeinfomem, getPtrToType(typeinfotype), "tmp");
             p->ir->CreateStore(casttypeinfomem, DtoGEPi(typeinfoarrayparam,0,1,"tmp"));
 
             // specify arguments
             llargs[j] = typeinfoarrayparam;;
             j++;
-            llargs[j] = p->ir->CreateBitCast(mem, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
+            llargs[j] = p->ir->CreateBitCast(mem, getPtrToType(llvm::Type::Int8Ty), "tmp");
             j++;
             llargs.resize(nimplicit+2);
         }
@@ -1128,14 +1131,14 @@
     if (llfnty->getReturnType() != llvm::Type::VoidTy)
         varname = "tmp";
 
-    Logger::cout() << "Calling: " << *funcval << '\n';
+    //Logger::cout() << "Calling: " << *funcval << '\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;
 
     if (retinptr && dfn && dfn->func && dfn->func->llvmRunTimeHack) {
-        const llvm::Type* rettype = llvm::PointerType::get(DtoType(type));
+        const llvm::Type* rettype = getPtrToType(DtoType(type));
         if (retllval->getType() != rettype) {
             Logger::println("llvmRunTimeHack==true - force casting return value");
             Logger::cout() << "from: " << *retllval->getType() << " to: " << *rettype << '\n';
@@ -1243,7 +1246,7 @@
             }
             else {
                 const llvm::Type* elemtype = llvalue->getType()->getContainedType(0)->getContainedType(0);
-                size_t elemsz = gTargetData->getTypeSize(elemtype);
+                size_t elemsz = getABITypeSize(elemtype);
                 varmem = DtoGEPi(llvalue, 0, offset / elemsz, "tmp");
             }
         }
@@ -1388,8 +1391,14 @@
         if (!vthis2) vthis2 = vthis;
         //unsigned cc = (unsigned)-1;
 
-        // virtual call
-        if (!fdecl->isFinal() && fdecl->isVirtual()) {
+        // super call
+        if (e1->op == TOKsuper) {
+            DtoForceDeclareDsymbol(fdecl);
+            funcval = fdecl->llvmValue;
+            assert(funcval);
+        }
+        // normal virtual call
+        else if (fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual())) {
             assert(fdecl->vtblIndex > 0);
             assert(e1type->ty == Tclass);
 
@@ -1428,7 +1437,8 @@
     LOG_SCOPE;
 
     if (VarDeclaration* vd = var->isVarDeclaration()) {
-        llvm::Value* v = p->func()->decl->llvmThisVar;
+        llvm::Value* v;
+        v = p->func()->decl->llvmThisVar;
         if (llvm::isa<llvm::AllocaInst>(v))
             v = new llvm::LoadInst(v, "tmp", p->scopebb());
         return new DThisValue(vd, v);
@@ -1818,7 +1828,7 @@
     else if (e1type->isfloating())
     {
         assert(e2type->isfloating());
-        llvm::Value* one = llvm::ConstantFP::get(val->getType(), 1.0f);
+        llvm::Value* one = llvm::ConstantFP::get(val->getType(), llvm::APFloat(1.0f));
         if (op == TOKplusplus) {
             post = llvm::BinaryOperator::createAdd(val,one,"tmp",p->scopebb());
         }
@@ -1847,113 +1857,47 @@
 
     Type* ntype = DtoDType(newtype);
 
+    if (ntype->ty == Tclass) {
+        return DtoNewClass((TypeClass*)ntype, this);
+    }
+
     const llvm::Type* t = DtoType(ntype);
 
     llvm::Value* emem = 0;
     bool inplace = false;
 
-    {
-        Logger::println("Allocating memory");
-        LOG_SCOPE;
-        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) {
-                    assert(p->topexp()->v);
-                    emem = p->topexp()->v->getLVal();
-                    DtoNewDynArray(emem, dimval, nnt);
-                    inplace = true;
-                }
-                else {
-                    const llvm::Type* restype = DtoType(type);
-                    Logger::cout() << "restype = " << *restype << '\n';
-                    emem = new llvm::AllocaInst(restype,"newstorage",p->topallocapoint());
-                    DtoNewDynArray(emem, dimval, nnt);
-                    return new DVarValue(newtype, emem, true);
-                }
+    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) {
+                assert(p->topexp()->v);
+                emem = p->topexp()->v->getLVal();
+                DtoNewDynArray(emem, dimval, nnt);
+                inplace = true;
             }
             else {
-                assert(0 && "num args to 'new' != 1");
+                const llvm::Type* restype = DtoType(type);
+                Logger::cout() << "restype = " << *restype << '\n';
+                emem = new llvm::AllocaInst(restype,"newstorage",p->topallocapoint());
+                DtoNewDynArray(emem, dimval, nnt);
+                return new DVarValue(newtype, emem, true);
             }
         }
         else {
-            emem = new llvm::MallocInst(t,"tmp",p->scopebb());
+            assert(0 && "num args to 'new' != 1");
         }
     }
-
-    if (ntype->ty == Tclass) {
-        // first apply the static initializer
-        TypeClass* tc = (TypeClass*)ntype;
-        DtoInitClass(tc, emem);
-
-        // set the this var for nested classes
-        if (thisexp) {
-            Logger::println("Resolving 'this' expression");
-            LOG_SCOPE;
-            DValue* thisval = thisexp->toElem(p);
-            size_t idx = 2;
-            idx += tc->sym->llvmIRStruct->interfaces.size();
-            llvm::Value* dst = thisval->getRVal();
-            llvm::Value* src = DtoGEPi(emem,0,idx,"tmp");
-            Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n';
-            DtoStore(dst, src);
-        }
-        else if (tc->sym->isNested())
-        {
-            Logger::println("Resolving nested context");
-            LOG_SCOPE;
-            size_t idx = 2;
-            idx += tc->sym->llvmIRStruct->interfaces.size();
-            llvm::Value* nest = p->func()->decl->llvmNested;
-            if (!nest)
-                nest = p->func()->decl->llvmThisVar;
-            assert(nest);
-            llvm::Value* gep = DtoGEPi(emem,0,idx,"tmp");
-            nest = DtoBitCast(nest, gep->getType()->getContainedType(0));
-            DtoStore(nest, gep);
-        }
-
-        // then call constructor
-        if (arguments) {
-            Logger::println("Calling constructor");
-            LOG_SCOPE;
-            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);
-                DValue* argval = DtoArgument(fnarg, ex);
-                llvm::Value* a = argval->getRVal();
-                const llvm::Type* aty = fn->getFunctionType()->getParamType(i+1);
-                if (a->getType() != aty) // this param might have type mismatch
-                    a = DtoBitCast(a, aty);
-                ctorargs.push_back(a);
-            }
-            llvm::CallInst* call = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb());
-            call->setCallingConv(DtoCallingConv(LINKd));
-            emem = call;
-        }
+    else {
+        emem = new llvm::MallocInst(t,"tmp",p->scopebb());
     }
-    else if (ntype->ty == Tstruct) {
+
+    if (ntype->ty == Tstruct) {
         TypeStruct* ts = (TypeStruct*)ntype;
         if (ts->isZeroInit()) {
             DtoStructZeroInit(emem);
@@ -2053,12 +1997,33 @@
     Logger::print("AssertExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    DValue* u = e1->toElem(p);
-    DValue* m = msg ? msg->toElem(p) : NULL;
-
-    DtoAssert(u->getRVal(), &loc, m);
-
-    return 0;
+    // condition
+    DValue* cond = e1->toElem(p);
+
+    // create basic blocks
+    llvm::BasicBlock* oldend = p->scopeend();
+    llvm::BasicBlock* assertbb = new llvm::BasicBlock("assert", p->topfunc(), oldend);
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("endassert", p->topfunc(), oldend);
+
+    // test condition
+    llvm::Value* condval = cond->getRVal();
+    condval = DtoBoolean(condval);
+
+    // branch
+    new llvm::BranchInst(endbb, assertbb, condval, p->scopebb());
+
+    // call assert runtime functions
+    p->scope() = IRScope(assertbb,endbb);
+    DtoAssert(&loc, msg ? msg->toElem(p) : NULL);
+
+    if (!gIR->scopereturned())
+        new llvm::BranchInst(endbb, p->scopebb());
+
+    // rewrite the scope
+    p->scope() = IRScope(endbb,oldend);
+
+    // no meaningful return value
+    return NULL;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -2192,7 +2157,7 @@
     Logger::print("HaltExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    DtoAssert(DtoConstBool(false), &loc, NULL);
+    DtoAssert(&loc, NULL);
 
     new llvm::UnreachableInst(p->scopebb());
     return 0;
@@ -2207,10 +2172,7 @@
 
     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);
+    const llvm::PointerType* int8ptrty = getPtrToType(llvm::Type::Int8Ty);
 
     llvm::Value* lval;
     if (p->topexp() && p->topexp()->e2 == this) {
@@ -2229,21 +2191,32 @@
         if (nestvar)
             uval = nestvar;
         else
-            uval = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
+            uval = llvm::ConstantPointerNull::get(int8ptrty);
     }
     else {
         uval = u->getRVal();
     }
 
-    llvm::Value* context = DtoGEP(lval,zero,zero,"tmp",p->scopebb());
-    llvm::Value* castcontext = DtoBitCast(uval,int8ptrty);
-    new llvm::StoreInst(castcontext, context, p->scopebb());
-
-    llvm::Value* fptr = DtoGEP(lval,zero,one,"tmp",p->scopebb());
-
-    assert(func->llvmValue);
-    llvm::Value* castfptr = DtoBitCast(func->llvmValue,fptr->getType()->getContainedType(0));
-    new llvm::StoreInst(castfptr, fptr, p->scopebb());
+    llvm::Value* context = DtoGEPi(lval,0,0,"tmp");
+    llvm::Value* castcontext = DtoBitCast(uval, int8ptrty);
+    DtoStore(castcontext, context);
+
+    llvm::Value* fptr = DtoGEPi(lval,0,1,"tmp");
+
+    Logger::println("func: '%s'", func->toPrettyChars());
+
+    llvm::Value* castfptr;
+    if (func->isVirtual())
+        castfptr = DtoVirtualFunctionPointer(u, func);
+    else if (func->isAbstract())
+        assert(0 && "TODO delegate to abstract method");
+    else if (func->toParent()->isInterfaceDeclaration())
+        assert(0 && "TODO delegate to interface method");
+    else
+        castfptr = func->llvmValue;
+
+    castfptr = DtoBitCast(castfptr, fptr->getType()->getContainedType(0));
+    DtoStore(castfptr, fptr);
 
     return new DVarValue(type, lval, true);
 }
@@ -2279,7 +2252,7 @@
         if (t1->ty == Tpointer && v->isNull() && l->getType() != r->getType()) {
             r = llvm::ConstantPointerNull::get(isaPointer(l->getType()));
         }
-        Logger::cout() << "l = " << *l << " r = " << *r << '\n';
+        //Logger::cout() << "l = " << *l << " r = " << *r << '\n';
         eval = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
     }
     return new DImValue(type, eval);
@@ -2368,9 +2341,9 @@
         zero = llvm::ConstantInt::get(val->getType(), 0, true);
     else if (t->isfloating()) {
         if (t->ty == Tfloat32 || t->ty == Timaginary32)
-            zero = llvm::ConstantFP::get(val->getType(), float(0));
+            zero = llvm::ConstantFP::get(val->getType(), llvm::APFloat(0.0f));
         else if (t->ty == Tfloat64 || t->ty == Tfloat80 || t->ty == Timaginary64 || t->ty == Timaginary80)
-            zero = llvm::ConstantFP::get(val->getType(), double(0));
+            zero = llvm::ConstantFP::get(val->getType(), llvm::APFloat(0.0));
         else
         assert(0);
     }
@@ -2619,11 +2592,11 @@
         }
         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';
+            if (getABITypeSize(t) != getABITypeSize(llt)) {
+                Logger::cout() << "got size " << getABITypeSize(t) << ", expected " << getABITypeSize(llt) << '\n';
                 assert(0 && "type size mismatch");
             }
-            sptr = p->ir->CreateBitCast(sptr, llvm::PointerType::get(t), "tmp");
+            sptr = DtoBitCast(sptr, getPtrToType(t));
             Logger::cout() << "sptr type is now: " << *t << '\n';
         }
     }
--- a/gen/tollvm.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/tollvm.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -82,9 +82,9 @@
     case Tpointer: {
         assert(t->next);
         if (t->next->ty == Tvoid)
-            return (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty);
+            return (const llvm::Type*)getPtrToType(llvm::Type::Int8Ty);
         else
-            return (const llvm::Type*)llvm::PointerType::get(DtoType(t->next));
+            return (const llvm::Type*)getPtrToType(DtoType(t->next));
     }
 
     // arrays
@@ -117,11 +117,11 @@
         TypeStruct* ts = (TypeStruct*)t;
         assert(ts->sym);
         DtoResolveDsymbol(ts->sym);
-        return t->llvmType->get();
+        return ts->sym->llvmIRStruct->recty.get();//t->llvmType->get();
     }
 
     case Tclass:    {
-        if (!t->llvmType || *t->llvmType == NULL) {
+        /*if (!t->llvmType || *t->llvmType == NULL) {
             // recursive or cyclic declaration
             if (!gIR->structs.empty())
             {
@@ -130,17 +130,17 @@
                 {
                     if (t == (*i)->type)
                     {
-                        return llvm::PointerType::get((*i)->recty.get());
+                        return getPtrToType((*i)->recty.get());
                     }
                 }
             }
             Logger::println("no type found");
-        }
+        }*/
 
         TypeClass* tc = (TypeClass*)t;
         assert(tc->sym);
         DtoResolveDsymbol(tc->sym);
-        return llvm::PointerType::get(t->llvmType->get());
+        return getPtrToType(tc->sym->llvmIRStruct->recty.get());//t->llvmType->get());
     }
 
     // functions
@@ -182,7 +182,7 @@
         std::vector<const llvm::Type*> types;
         types.push_back(DtoType(taa->key));
         types.push_back(DtoType(taa->next));
-        return llvm::PointerType::get(llvm::StructType::get(types));
+        return getPtrToType(llvm::StructType::get(types));
     }
 
     default:
@@ -196,9 +196,9 @@
 
 const llvm::StructType* DtoDelegateType(Type* t)
 {
-    const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::Type* i8ptr = getPtrToType(llvm::Type::Int8Ty);
     const llvm::Type* func = DtoFunctionType(t->next, i8ptr);
-    const llvm::Type* funcptr = llvm::PointerType::get(func);
+    const llvm::Type* funcptr = getPtrToType(func);
 
     std::vector<const llvm::Type*> types;
     types.push_back(i8ptr);
@@ -214,7 +214,7 @@
     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* int8ptrty = (const llvm::Type*)getPtrToType(llvm::Type::Int8Ty);
     const llvm::Type* voidty =    (const llvm::Type*)llvm::Type::VoidTy;
 
     assert(gIR);
@@ -284,7 +284,7 @@
     assert(gIR);
     d_uns64 n = (global.params.is64bit) ? 16 : 8;
 
-    llvm::Type* i8p_ty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::Type* i8p_ty = getPtrToType(llvm::Type::Int8Ty);
 
     llvm::Value* arr = new llvm::BitCastInst(v,i8p_ty,"tmp",gIR->scopebb());
 
@@ -310,7 +310,7 @@
 
     d_uns64 n = (global.params.is64bit) ? 16 : 8;
 
-    llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::Type* arrty = getPtrToType(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());
@@ -434,10 +434,8 @@
         }
     }
     else if (isaPointer(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());
+        llvm::Value* zero = llvm::Constant::getNullValue(t);
+        return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, val, zero, "tmp", gIR->scopebb());
     }
     else
     {
@@ -615,7 +613,7 @@
     /*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);
+        llvm::PointerType* i8pty = getPtrToType(llvm::Type::Int8Ty);
         ptr = llvm::ConstantPointerNull::get(i8pty);
     }
     return DtoRealloc(ptr, n);*/
@@ -634,7 +632,7 @@
 
     llvm::Value* newptr = ptr;
 
-    llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::PointerType* i8pty = getPtrToType(llvm::Type::Int8Ty);
     if (ptr->getType() != i8pty) {
         newptr = new llvm::BitCastInst(ptr,i8pty,"tmp",gIR->scopebb());
     }
@@ -649,30 +647,33 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoAssert(llvm::Value* cond, Loc* loc, DValue* msg)
+void DtoAssert(Loc* loc, DValue* msg)
 {
-    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_assert");
-    const llvm::FunctionType* fnt = fn->getFunctionType();
+    std::vector<llvm::Value*> args;
+    llvm::Constant* c;
+
+    // func
+    const char* fname = msg ? "_d_assert_msg" : "_d_assert";
+
+    // msg param
+    if (msg) args.push_back(msg->getRVal());
 
-    std::vector<llvm::Value*> llargs;
-    llargs.resize(3);
-    llargs[0] = cond ? DtoBoolean(cond) : llvm::ConstantInt::getFalse();
-    llargs[1] = DtoConstUint(loc->linnum);
-    if (msg)
-        llargs[2] = msg->getRVal();
-    else {
-        llvm::Constant* c = DtoConstSlice(DtoConstSize_t(0), DtoConstNullPtr(llvm::Type::Int8Ty));
-        static llvm::AllocaInst* alloc = 0;
-        if (!alloc || alloc->getParent()->getParent() != gIR->func()->func) {
-            alloc = new llvm::AllocaInst(c->getType(), "assertnullparam", gIR->topallocapoint());
-            DtoSetArrayToNull(alloc);
-        }
-        llargs[2] = alloc;
-    }
+    // file param
+    c = DtoConstString(loc->filename);
+    llvm::AllocaInst* alloc = new llvm::AllocaInst(c->getType(), "srcfile", gIR->topallocapoint());
+    llvm::Value* ptr = DtoGEPi(alloc, 0,0, "tmp");
+    DtoStore(c->getOperand(0), ptr);
+    ptr = DtoGEPi(alloc, 0,1, "tmp");
+    DtoStore(c->getOperand(1), ptr);
+    args.push_back(alloc);
 
-    assert(fn);
-    llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-    call->setCallingConv(llvm::CallingConv::C);
+    // line param
+    c = DtoConstUint(loc->linnum);
+    args.push_back(c);
+
+    // call
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
+    llvm::CallInst* call = new llvm::CallInst(fn, args.begin(), args.end(), "", gIR->scopebb());
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -1191,9 +1192,9 @@
 {
     TY ty = DtoDType(t)->ty;
     if (ty == Tfloat32 || ty == Timaginary32)
-        return llvm::ConstantFP::get(llvm::Type::FloatTy, float(value));
+        return llvm::ConstantFP::get(llvm::Type::FloatTy, llvm::APFloat(float(value)));
     else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tfloat80 || ty == Timaginary80)
-        return llvm::ConstantFP::get(llvm::Type::DoubleTy, double(value));
+        return llvm::ConstantFP::get(llvm::Type::DoubleTy, llvm::APFloat(double(value)));
 }
 
 
@@ -1227,7 +1228,7 @@
 llvm::Constant* DtoConstNullPtr(const llvm::Type* t)
 {
     return llvm::ConstantPointerNull::get(
-        llvm::PointerType::get(t)
+        getPtrToType(t)
     );
 }
 
@@ -1235,7 +1236,7 @@
 
 void DtoMemSetZero(llvm::Value* dst, llvm::Value* nbytes)
 {
-    llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
     llvm::Value *dstarr;
     if (dst->getType() == arrty)
     {
@@ -1263,7 +1264,7 @@
 {
     assert(dst->getType() == src->getType());
 
-    llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
     llvm::Value *dstarr, *srcarr;
     if (dst->getType() == arrty)
     {
@@ -1309,11 +1310,11 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t)
+llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t, const char* name)
 {
     if (v->getType() == t)
         return v;
-    return gIR->ir->CreateBitCast(v, t, "tmp");
+    return gIR->ir->CreateBitCast(v, t, name ? name : "tmp");
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -1370,6 +1371,36 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+const llvm::PointerType* getPtrToType(const llvm::Type* t)
+{
+    return llvm::PointerType::get(t, 0);
+}
+
+llvm::ConstantPointerNull* getNullPtr(const llvm::Type* t)
+{
+    const llvm::PointerType* pt = llvm::cast<llvm::PointerType>(t);
+    return llvm::ConstantPointerNull::get(pt);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+size_t getTypeBitSize(const llvm::Type* t)
+{
+    return gTargetData->getTypeSizeInBits(t);
+}
+
+size_t getTypeStoreSize(const llvm::Type* t)
+{
+    return gTargetData->getTypeStoreSize(t);
+}
+
+size_t getABITypeSize(const llvm::Type* t)
+{
+    return gTargetData->getABITypeSize(t);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 bool DtoIsTemplateInstance(Dsymbol* s)
 {
     if (!s) return false;
@@ -1656,7 +1687,7 @@
 void DtoForceDeclareDsymbol(Dsymbol* dsym)
 {
     if (dsym->llvmDeclared) return;
-    Logger::println("DtoForceDeclareDsymbol(%s)", dsym->toChars());
+    Logger::println("DtoForceDeclareDsymbol(%s)", dsym->toPrettyChars());
     LOG_SCOPE;
     DtoResolveDsymbol(dsym);
 
@@ -1670,7 +1701,7 @@
 void DtoForceConstInitDsymbol(Dsymbol* dsym)
 {
     if (dsym->llvmInitialized) return;
-    Logger::println("DtoForceConstInitDsymbol(%s)", dsym->toChars());
+    Logger::println("DtoForceConstInitDsymbol(%s)", dsym->toPrettyChars());
     LOG_SCOPE;
     DtoResolveDsymbol(dsym);
 
@@ -1685,7 +1716,7 @@
 void DtoForceDefineDsymbol(Dsymbol* dsym)
 {
     if (dsym->llvmDefined) return;
-    Logger::println("DtoForceDefineDsymbol(%s)", dsym->toChars());
+    Logger::println("DtoForceDefineDsymbol(%s)", dsym->toPrettyChars());
     LOG_SCOPE;
     DtoResolveDsymbol(dsym);
 
--- a/gen/tollvm.h	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/tollvm.h	Mon Jan 14 05:11:54 2008 +0100
@@ -39,7 +39,7 @@
 llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty);
 llvm::Value* DtoRealloc(llvm::Value* ptr, llvm::Value* len);
 
-void DtoAssert(llvm::Value* cond, Loc* loc, DValue* msg);
+void DtoAssert(Loc* loc, DValue* msg);
 
 llvm::Value* DtoNestedContext(FuncDeclaration* func);
 llvm::Value* DtoNestedVariable(VarDeclaration* vd);
@@ -81,7 +81,7 @@
 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);
+llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t, const char* name=0);
 
 // llvm::dyn_cast wrappers
 const llvm::PointerType* isaPointer(llvm::Value* v);
@@ -95,6 +95,15 @@
 llvm::Argument* isaArgument(llvm::Value* v);
 llvm::GlobalVariable* isaGlobalVar(llvm::Value* v);
 
+// llvm::T::get(...) wrappers
+const llvm::PointerType* getPtrToType(const llvm::Type* t);
+llvm::ConstantPointerNull* getNullPtr(const llvm::Type* t);
+
+// type sizes
+size_t getTypeBitSize(const llvm::Type* t);
+size_t getTypeStoreSize(const llvm::Type* t);
+size_t getABITypeSize(const llvm::Type* t);
+
 // basic operations
 void DtoAssign(DValue* lhs, DValue* rhs);
 
--- a/gen/toobj.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/toobj.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -74,7 +74,7 @@
     ir.module->setDataLayout(global.params.data_layout);
 
     // heavily inspired by tools/llc/llc.cpp:200-230
-    const llvm::TargetMachineRegistry::Entry* targetEntry;
+    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");
@@ -118,7 +118,7 @@
 
     // emit the llvm main function if necessary
     if (ir.emitMain) {
-        DtoMain();
+        //DtoMain();
     }
 
     // verify the llvm
@@ -295,7 +295,7 @@
     initVec.push_back(c);
 
     // monitor
-    c = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
+    c = getNullPtr(getPtrToType(llvm::Type::Int8Ty));
     initVec.push_back(c);
 
     // name
@@ -321,14 +321,15 @@
         }
     }
     // has import array?
-    if (!importInits.empty()) {
-        const llvm::ArrayType* importArrTy = llvm::ArrayType::get(llvm::PointerType::get(moduleinfoTy), importInits.size());
+    if (!importInits.empty())
+    {
+        const llvm::ArrayType* importArrTy = llvm::ArrayType::get(getPtrToType(moduleinfoTy), importInits.size());
         c = llvm::ConstantArray::get(importArrTy, importInits);
         std::string m_name("_D");
         m_name.append(mangle());
         m_name.append("9__importsZ");
         llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(importArrTy, true, llvm::GlobalValue::InternalLinkage, c, m_name, gIR->module);
-        c = llvm::ConstantExpr::getBitCast(m_gvar, llvm::PointerType::get(importArrTy->getElementType()));
+        c = llvm::ConstantExpr::getBitCast(m_gvar, getPtrToType(importArrTy->getElementType()));
         c = DtoConstSlice(DtoConstSize_t(importInits.size()), c);
     }
     else
@@ -351,19 +352,25 @@
     for (size_t i = 0; i < aclasses.dim; i++)
     {
         ClassDeclaration* cd = (ClassDeclaration*)aclasses.data[i];
+        if (cd->isInterfaceDeclaration())
+        {
+            Logger::println("skipping interface '%s'", cd->toPrettyChars());
+            continue;
+        }
         Logger::println("class: %s", cd->toPrettyChars());
         assert(cd->llvmClass);
         classInits.push_back(cd->llvmClass);
     }
     // has class array?
-    if (!classInits.empty()) {
-        const llvm::ArrayType* classArrTy = llvm::ArrayType::get(llvm::PointerType::get(classinfoTy), classInits.size());
+    if (!classInits.empty())
+    {
+        const llvm::ArrayType* classArrTy = llvm::ArrayType::get(getPtrToType(classinfoTy), classInits.size());
         c = llvm::ConstantArray::get(classArrTy, classInits);
         std::string m_name("_D");
         m_name.append(mangle());
         m_name.append("9__classesZ");
         llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(classArrTy, true, llvm::GlobalValue::InternalLinkage, c, m_name, gIR->module);
-        c = llvm::ConstantExpr::getBitCast(m_gvar, llvm::PointerType::get(classArrTy->getElementType()));
+        c = llvm::ConstantExpr::getBitCast(m_gvar, getPtrToType(classArrTy->getElementType()));
         c = DtoConstSlice(DtoConstSize_t(classInits.size()), c);
     }
     else
@@ -420,9 +427,9 @@
     llvm::GlobalVariable* gvar = new llvm::GlobalVariable(moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, constMI, MIname, gIR->module);
 
     // declare the appending array
-    const llvm::ArrayType* appendArrTy = llvm::ArrayType::get(llvm::PointerType::get(llvm::Type::Int8Ty), 1);
+    const llvm::ArrayType* appendArrTy = llvm::ArrayType::get(getPtrToType(llvm::Type::Int8Ty), 1);
     std::vector<llvm::Constant*> appendInits;
-    appendInits.push_back(llvm::ConstantExpr::getBitCast(gvar, llvm::PointerType::get(llvm::Type::Int8Ty)));
+    appendInits.push_back(llvm::ConstantExpr::getBitCast(gvar, getPtrToType(llvm::Type::Int8Ty)));
     llvm::Constant* appendInit = llvm::ConstantArray::get(appendArrTy, appendInits);
     std::string appendName("_d_moduleinfo_array");
     llvm::GlobalVariable* appendVar = new llvm::GlobalVariable(appendArrTy, true, llvm::GlobalValue::AppendingLinkage, appendInit, appendName, gIR->module);
@@ -446,7 +453,8 @@
 
 void InterfaceDeclaration::toObjFile()
 {
-    Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars());
+    //Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars());
+    gIR->resolveList.push_back(this);
 }
 
 /* ================================================================== */
@@ -491,7 +499,7 @@
     if (isDataseg())
     {
         // we don't want to touch private static members at all !!!
-        if ((prot() & PROTprivate) && getModule() != gIR->dmodule)
+        if ((prot() == PROTprivate) && getModule() != gIR->dmodule)
             return;
 
         // don't duplicate work
--- a/gen/typinf.cpp	Fri Jan 11 17:57:40 2008 +0100
+++ b/gen/typinf.cpp	Mon Jan 14 05:11:54 2008 +0100
@@ -371,7 +371,7 @@
     sinits.push_back(base->llvmVtbl);
 
     // monitor
-    sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
+    sinits.push_back(getNullPtr(getPtrToType(llvm::Type::Int8Ty)));
 
     assert(tinfo->ty == Ttypedef);
     TypeTypedef *tc = (TypeTypedef *)tinfo;
@@ -400,10 +400,10 @@
     assert(sinits.back()->getType() == stype->getElementType(3));
 
     // void[] init
-    const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::PointerType* initpt = getPtrToType(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)));
+        sinits.push_back(DtoConstSlice(DtoConstSize_t(0), getNullPtr(initpt)));
     }
     else
     {
@@ -412,7 +412,7 @@
         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));
+        size_t cisize = getTypeStoreSize(DtoType(sd->basetype));
         sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
     }
 
@@ -457,7 +457,7 @@
     sinits.push_back(base->llvmVtbl);
 
     // monitor
-    sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
+    sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
 
     assert(tinfo->ty == Tenum);
     TypeEnum *tc = (TypeEnum *)tinfo;
@@ -485,7 +485,7 @@
     assert(sinits.back()->getType() == stype->getElementType(3));
 
     // void[] init
-    const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::PointerType* initpt = getPtrToType(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)));
@@ -498,7 +498,7 @@
         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);
+        size_t cisize = getTypeStoreSize(memty);
         sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
     }
 
@@ -537,7 +537,7 @@
     sinits.push_back(base->llvmVtbl);
 
     // monitor
-    sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
+    sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
 
     // TypeInfo base
     Logger::println("generating base typeinfo");
@@ -649,7 +649,7 @@
     sinits.push_back(base->llvmVtbl);
 
     // monitor
-    sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
+    sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
 
     // value typeinfo
     assert(tinfo->ty == Tsarray);
@@ -712,7 +712,7 @@
     sinits.push_back(base->llvmVtbl);
 
     // monitor
-    sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
+    sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
 
     // get type
     assert(tinfo->ty == Taarray);
@@ -847,7 +847,7 @@
     sinits.push_back(base->llvmVtbl);
 
     // monitor
-    sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
+    sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
 
     // char[] name
     char *name = sd->toPrettyChars();
@@ -856,14 +856,14 @@
     assert(sinits.back()->getType() == stype->getElementType(2));
 
     // void[] init
-    const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
+    const llvm::PointerType* initpt = getPtrToType(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
     {
-        size_t cisize = gTargetData->getTypeSize(tc->llvmType->get());
+        size_t cisize = getTypeStoreSize(tc->llvmType->get());
         llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(sd->llvmInit, initpt);
         sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
     }
@@ -1046,7 +1046,7 @@
     sinits.push_back(base->llvmVtbl);
 
     // monitor
-    sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
+    sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
 
     // get classinfo
     assert(tinfo->ty == Tclass);
@@ -1102,7 +1102,7 @@
     sinits.push_back(base->llvmVtbl);
 
     // monitor
-    sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
+    sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
 
     // get classinfo
     assert(tinfo->ty == Tclass);
@@ -1158,7 +1158,7 @@
     sinits.push_back(base->llvmVtbl);
 
     // monitor
-    sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
+    sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
 
     // create elements array
     assert(tinfo->ty == Ttuple);
@@ -1168,7 +1168,7 @@
     std::vector<llvm::Constant*> arrInits;
 
     const llvm::Type* tiTy = Type::typeinfo->type->llvmType->get();
-    tiTy = llvm::PointerType::get(tiTy);
+    tiTy = getPtrToType(tiTy);
 
     for (size_t i = 0; i < dim; i++)
     {
--- a/llvmdc-posix-internal	Fri Jan 11 17:57:40 2008 +0100
+++ b/llvmdc-posix-internal	Mon Jan 14 05:11:54 2008 +0100
@@ -8,7 +8,7 @@
 objext=bc
 
 
-version=LLVM
+version=LLVMDC
 noversion=DigitalMars
 noversion=GNU
 testversion=linux
--- a/llvmdc.kdevelop.filelist	Fri Jan 11 17:57:40 2008 +0100
+++ b/llvmdc.kdevelop.filelist	Mon Jan 14 05:11:54 2008 +0100
@@ -120,6 +120,7 @@
 gen/irstate.cpp
 gen/irstate.h
 gen/llvm.h
+gen/llvmd.h
 gen/logger.cpp
 gen/logger.h
 gen/optimizer.cpp
@@ -255,187 +256,24 @@
 tango/lib/common/tango/stdc/posix/pthread_darwin.d
 tango/lib/common/tango/stdc/wrap.c
 tango/lib/compiler
-tango/lib/compiler/dmd
-tango/lib/compiler/dmd/aApply.d
-tango/lib/compiler/dmd/aApplyR.d
-tango/lib/compiler/dmd/aaA.d
-tango/lib/compiler/dmd/adi.d
-tango/lib/compiler/dmd/alloca.d
-tango/lib/compiler/dmd/arraycast.d
-tango/lib/compiler/dmd/arraycat.d
-tango/lib/compiler/dmd/cast.d
-tango/lib/compiler/dmd/cmath2.d
-tango/lib/compiler/dmd/compiler.d
-tango/lib/compiler/dmd/complex.c
-tango/lib/compiler/dmd/cover.d
-tango/lib/compiler/dmd/critical.c
-tango/lib/compiler/dmd/deh.c
-tango/lib/compiler/dmd/deh2.d
-tango/lib/compiler/dmd/dmain2.d
-tango/lib/compiler/dmd/genobj.d
-tango/lib/compiler/dmd/invariant.d
-tango/lib/compiler/dmd/lifetime.d
-tango/lib/compiler/dmd/llmath.d
-tango/lib/compiler/dmd/mars.h
-tango/lib/compiler/dmd/memory.d
-tango/lib/compiler/dmd/memset.d
-tango/lib/compiler/dmd/monitor.c
-tango/lib/compiler/dmd/obj.d
-tango/lib/compiler/dmd/qsort.d
-tango/lib/compiler/dmd/qsort2.d
-tango/lib/compiler/dmd/switch.d
-tango/lib/compiler/dmd/trace.d
-tango/lib/compiler/dmd/typeinfo
-tango/lib/compiler/dmd/typeinfo/ti_AC.d
-tango/lib/compiler/dmd/typeinfo/ti_Acdouble.d
-tango/lib/compiler/dmd/typeinfo/ti_Acfloat.d
-tango/lib/compiler/dmd/typeinfo/ti_Acreal.d
-tango/lib/compiler/dmd/typeinfo/ti_Adouble.d
-tango/lib/compiler/dmd/typeinfo/ti_Afloat.d
-tango/lib/compiler/dmd/typeinfo/ti_Ag.d
-tango/lib/compiler/dmd/typeinfo/ti_Aint.d
-tango/lib/compiler/dmd/typeinfo/ti_Along.d
-tango/lib/compiler/dmd/typeinfo/ti_Areal.d
-tango/lib/compiler/dmd/typeinfo/ti_Ashort.d
-tango/lib/compiler/dmd/typeinfo/ti_C.d
-tango/lib/compiler/dmd/typeinfo/ti_byte.d
-tango/lib/compiler/dmd/typeinfo/ti_cdouble.d
-tango/lib/compiler/dmd/typeinfo/ti_cfloat.d
-tango/lib/compiler/dmd/typeinfo/ti_char.d
-tango/lib/compiler/dmd/typeinfo/ti_creal.d
-tango/lib/compiler/dmd/typeinfo/ti_dchar.d
-tango/lib/compiler/dmd/typeinfo/ti_delegate.d
-tango/lib/compiler/dmd/typeinfo/ti_double.d
-tango/lib/compiler/dmd/typeinfo/ti_float.d
-tango/lib/compiler/dmd/typeinfo/ti_idouble.d
-tango/lib/compiler/dmd/typeinfo/ti_ifloat.d
-tango/lib/compiler/dmd/typeinfo/ti_int.d
-tango/lib/compiler/dmd/typeinfo/ti_ireal.d
-tango/lib/compiler/dmd/typeinfo/ti_long.d
-tango/lib/compiler/dmd/typeinfo/ti_ptr.d
-tango/lib/compiler/dmd/typeinfo/ti_real.d
-tango/lib/compiler/dmd/typeinfo/ti_short.d
-tango/lib/compiler/dmd/typeinfo/ti_ubyte.d
-tango/lib/compiler/dmd/typeinfo/ti_uint.d
-tango/lib/compiler/dmd/typeinfo/ti_ulong.d
-tango/lib/compiler/dmd/typeinfo/ti_ushort.d
-tango/lib/compiler/dmd/typeinfo/ti_void.d
-tango/lib/compiler/dmd/typeinfo/ti_wchar.d
-tango/lib/compiler/dmd/util
-tango/lib/compiler/dmd/util/console.d
-tango/lib/compiler/dmd/util/ctype.d
-tango/lib/compiler/dmd/util/string.d
-tango/lib/compiler/dmd/util/utf.d
-tango/lib/compiler/gdc
-tango/lib/compiler/gdc/aApply.d
-tango/lib/compiler/gdc/aApplyR.d
-tango/lib/compiler/gdc/aaA.d
-tango/lib/compiler/gdc/actest.d
-tango/lib/compiler/gdc/adi.d
-tango/lib/compiler/gdc/arraycast.d
-tango/lib/compiler/gdc/arraycat.d
-tango/lib/compiler/gdc/cast.d
-tango/lib/compiler/gdc/cmain.d
-tango/lib/compiler/gdc/cmath2.d
-tango/lib/compiler/gdc/compiler.d
-tango/lib/compiler/gdc/config
-tango/lib/compiler/gdc/config.h
-tango/lib/compiler/gdc/config/darwin8
-tango/lib/compiler/gdc/config/gen_config1.c
-tango/lib/compiler/gdc/config/gen_math.c
-tango/lib/compiler/gdc/config/gen_unix.c
-tango/lib/compiler/gdc/config/makestruct.h
-tango/lib/compiler/gdc/config/mingw
-tango/lib/compiler/gdc/config/skyos
-tango/lib/compiler/gdc/critical.c
-tango/lib/compiler/gdc/deh.c
-tango/lib/compiler/gdc/dgccmain2.d
-tango/lib/compiler/gdc/fpmath.d
-tango/lib/compiler/gdc/gcc
-tango/lib/compiler/gdc/gcc/aix_float.h
-tango/lib/compiler/gdc/gcc/builtins.d
-tango/lib/compiler/gdc/gcc/cbridge_fdset.c
-tango/lib/compiler/gdc/gcc/cbridge_math.c
-tango/lib/compiler/gdc/gcc/cbridge_stdio.c
-tango/lib/compiler/gdc/gcc/cbridge_time.c
-tango/lib/compiler/gdc/gcc/configext.d
-tango/lib/compiler/gdc/gcc/configunix.d
-tango/lib/compiler/gdc/gcc/deh.d
-tango/lib/compiler/gdc/gcc/fpmath.d
-tango/lib/compiler/gdc/gcc/support.d
-tango/lib/compiler/gdc/gcc/threadsem.d
-tango/lib/compiler/gdc/gcc/unwind.d
-tango/lib/compiler/gdc/genobj.d
-tango/lib/compiler/gdc/invariant.d
-tango/lib/compiler/gdc/lifetime.d
-tango/lib/compiler/gdc/mars.h
-tango/lib/compiler/gdc/memory.d
-tango/lib/compiler/gdc/memory_dyld.c
-tango/lib/compiler/gdc/memory_freebsd.c
-tango/lib/compiler/gdc/memset.d
-tango/lib/compiler/gdc/minimal.c
-tango/lib/compiler/gdc/monitor.c
-tango/lib/compiler/gdc/obj.d
-tango/lib/compiler/gdc/qsort2.d
-tango/lib/compiler/gdc/qsortg.d
-tango/lib/compiler/gdc/rundmain.d
-tango/lib/compiler/gdc/std
-tango/lib/compiler/gdc/std/intrinsic.d
-tango/lib/compiler/gdc/switch.d
-tango/lib/compiler/gdc/typeinfo
-tango/lib/compiler/gdc/typeinfo/ti_AC.d
-tango/lib/compiler/gdc/typeinfo/ti_Acdouble.d
-tango/lib/compiler/gdc/typeinfo/ti_Acfloat.d
-tango/lib/compiler/gdc/typeinfo/ti_Acreal.d
-tango/lib/compiler/gdc/typeinfo/ti_Adouble.d
-tango/lib/compiler/gdc/typeinfo/ti_Afloat.d
-tango/lib/compiler/gdc/typeinfo/ti_Ag.d
-tango/lib/compiler/gdc/typeinfo/ti_Aint.d
-tango/lib/compiler/gdc/typeinfo/ti_Along.d
-tango/lib/compiler/gdc/typeinfo/ti_Areal.d
-tango/lib/compiler/gdc/typeinfo/ti_Ashort.d
-tango/lib/compiler/gdc/typeinfo/ti_C.d
-tango/lib/compiler/gdc/typeinfo/ti_byte.d
-tango/lib/compiler/gdc/typeinfo/ti_cdouble.d
-tango/lib/compiler/gdc/typeinfo/ti_cfloat.d
-tango/lib/compiler/gdc/typeinfo/ti_char.d
-tango/lib/compiler/gdc/typeinfo/ti_creal.d
-tango/lib/compiler/gdc/typeinfo/ti_dchar.d
-tango/lib/compiler/gdc/typeinfo/ti_delegate.d
-tango/lib/compiler/gdc/typeinfo/ti_double.d
-tango/lib/compiler/gdc/typeinfo/ti_float.d
-tango/lib/compiler/gdc/typeinfo/ti_idouble.d
-tango/lib/compiler/gdc/typeinfo/ti_ifloat.d
-tango/lib/compiler/gdc/typeinfo/ti_int.d
-tango/lib/compiler/gdc/typeinfo/ti_ireal.d
-tango/lib/compiler/gdc/typeinfo/ti_long.d
-tango/lib/compiler/gdc/typeinfo/ti_ptr.d
-tango/lib/compiler/gdc/typeinfo/ti_real.d
-tango/lib/compiler/gdc/typeinfo/ti_short.d
-tango/lib/compiler/gdc/typeinfo/ti_ubyte.d
-tango/lib/compiler/gdc/typeinfo/ti_uint.d
-tango/lib/compiler/gdc/typeinfo/ti_ulong.d
-tango/lib/compiler/gdc/typeinfo/ti_ushort.d
-tango/lib/compiler/gdc/typeinfo/ti_void.d
-tango/lib/compiler/gdc/typeinfo/ti_wchar.d
-tango/lib/compiler/gdc/util
-tango/lib/compiler/gdc/util/console.d
-tango/lib/compiler/gdc/util/ctype.d
-tango/lib/compiler/gdc/util/string.d
-tango/lib/compiler/gdc/util/utf.d
 tango/lib/compiler/llvmdc
 tango/lib/compiler/llvmdc/aApply.d
 tango/lib/compiler/llvmdc/aApplyR.d
 tango/lib/compiler/llvmdc/aaA.d
 tango/lib/compiler/llvmdc/adi.d
 tango/lib/compiler/llvmdc/arrays.d
-tango/lib/compiler/llvmdc/build.sh
 tango/lib/compiler/llvmdc/cast.d
 tango/lib/compiler/llvmdc/contract.d
+tango/lib/compiler/llvmdc/critical.c
+tango/lib/compiler/llvmdc/dmain2.d
+tango/lib/compiler/llvmdc/eh.d
 tango/lib/compiler/llvmdc/genobj.d
+tango/lib/compiler/llvmdc/lifetime.d
 tango/lib/compiler/llvmdc/llvm
-tango/lib/compiler/llvmdc/llvm/intrinsic.di
-tango/lib/compiler/llvmdc/obj
+tango/lib/compiler/llvmdc/mars.h
+tango/lib/compiler/llvmdc/mem.d
+tango/lib/compiler/llvmdc/memory.d
+tango/lib/compiler/llvmdc/monitor.c
 tango/lib/compiler/llvmdc/qsort2.d
 tango/lib/compiler/llvmdc/std
 tango/lib/compiler/llvmdc/std/intrinsic.d
@@ -900,6 +738,17 @@
 tangotests/e.d
 tangotests/f.d
 tangotests/g.d
+tangotests/h.d
+tangotests/i.d
+tangotests/j.d
+tangotests/k.d
+tangotests/l.d
+tangotests/m.d
+tangotests/n.d
+tangotests/o.d
+tangotests/p.d
+tangotests/q.d
+tangotests/r.d
 test
 test/a.d
 test/aa1.d
--- a/tango/lib/common/tango/core/Exception.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/tango/lib/common/tango/core/Exception.d	Mon Jan 14 05:11:54 2008 +0100
@@ -481,6 +481,7 @@
 // Overridable Callbacks
 ////////////////////////////////////////////////////////////////////////////////
 
+private extern(C) int printf(char*,...);
 
 /**
  * A callback for assert errors in D.  The user-supplied assert handler will
@@ -493,8 +494,11 @@
  */
 extern (C) void onAssertError( char[] file, size_t line )
 {
-    if( assertHandler is null )
+    printf("Assertion failed:\n");
+    printf("%.*s(%lu)\n", file.length, file.ptr, line);
+    if( assertHandler is null ) {
         throw new AssertException( file, line );
+    }
     assertHandler( file, line );
 }
 
@@ -511,6 +515,9 @@
  */
 extern (C) void onAssertErrorMsg( char[] file, size_t line, char[] msg )
 {
+    printf("Assertion failed:\n");
+    printf("%.*s(%lu):\n", file.length, file.ptr, line);
+    printf("%.*s\n", msg.length, msg.ptr);
     if( assertHandler is null )
         throw new AssertException( msg, file, line );
     assertHandler( file, line, msg );
--- a/tango/lib/common/tango/llvmdc.mak	Fri Jan 11 17:57:40 2008 +0100
+++ b/tango/lib/common/tango/llvmdc.mak	Mon Jan 14 05:11:54 2008 +0100
@@ -12,6 +12,8 @@
 
 LIB_TARGET=libtango-cc-tango.a
 LIB_MASK=libtango-cc-tango*.a
+LIB_TARGET_C=libtango-cc-c-tango.a
+LIB_MASK_C=libtango-cc-c-tango*.a
 
 CP=cp -f
 RM=rm -f
@@ -33,6 +35,7 @@
 
 CC=gcc
 LC=llvm-ar rsv
+CLC=ar rsv
 DC=llvmdc
 LLC=llvm-as
 
@@ -68,7 +71,7 @@
 targets : lib doc
 all     : lib doc
 tango   : lib
-lib     : tango.lib
+lib     : tango.lib tango.clib
 doc     : tango.doc
 
 ######################################################
@@ -82,14 +85,15 @@
 #    core/ThreadASM.o
 
 OBJ_STDC= \
-    stdc/wrap.bc
+    stdc/wrap.o
+#    stdc/wrap.bc
 
 OBJ_STDC_POSIX= \
     stdc/posix/pthread_darwin.o
 
 ALL_OBJS= \
-    $(OBJ_CORE) \
-    $(OBJ_STDC)
+    $(OBJ_CORE)
+#    $(OBJ_STDC)
 #    $(OBJ_STDC_POSIX)
 
 ######################################################
@@ -112,6 +116,14 @@
 	$(RM) $@
 	$(LC) $@ $(ALL_OBJS)
 
+
+tango.clib : $(LIB_TARGET_C)
+
+$(LIB_TARGET_C) : $(OBJ_STDC)
+	$(RM) $@
+	$(CLC) $@ $(OBJ_STDC)
+
+
 tango.doc : $(ALL_DOCS)
 	echo Documentation generated.
 
@@ -127,8 +139,10 @@
 clean :
 	find . -name "*.di" | xargs $(RM)
 	$(RM) $(ALL_OBJS)
+	$(RM) $(OBJ_STDC)
 	$(RM) $(ALL_DOCS)
 	find . -name "$(LIB_MASK)" | xargs $(RM)
+	find . -name "$(LIB_MASK_C)" | xargs $(RM)
 
 install :
 	$(MD) $(INC_DEST)
@@ -137,3 +151,4 @@
 	find . -name "*.html" -exec cp -f {} $(DOC_DEST)/{} \;
 	$(MD) $(LIB_DEST)
 	find . -name "$(LIB_MASK)" -exec cp -f {} $(LIB_DEST)/{} \;
+	find . -name "$(LIB_MASK_C)" -exec cp -f {} $(LIB_DEST)/{} \;
--- a/tango/lib/common/tango/stdc/wrap.ll	Fri Jan 11 17:57:40 2008 +0100
+++ b/tango/lib/common/tango/stdc/wrap.ll	Mon Jan 14 05:11:54 2008 +0100
@@ -1,5 +1,5 @@
 ; ModuleID = 'wrap.bc'
-@errno = external global i32		; <i32*> [#uses=2]
+@errno = external thread_local global i32	; <i32*> [#uses=2]
 
 define i32 @getErrno() {
 entry:
--- a/tango/lib/compiler/llvmdc/cast.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/tango/lib/compiler/llvmdc/cast.d	Mon Jan 14 05:11:54 2008 +0100
@@ -99,7 +99,7 @@
     return o;
 }
 
-int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout size_t offset)
+int _d_isbaseof2(ClassInfo oc, ClassInfo c, ref size_t offset)
 {   int i;
 
     if (oc is c)
--- a/tango/lib/compiler/llvmdc/contract.d	Fri Jan 11 17:57:40 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-extern(C):
-
-void exit(int);
-int printf(char*,...);
-
-void _d_assert(bool cond, uint line, char[] msg)
-{
-    if (!cond) {
-        printf("Aborted(%u): %.*s\n", line, msg.length, msg.ptr);
-        exit(1);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tango/lib/compiler/llvmdc/critical.c	Mon Jan 14 05:11:54 2008 +0100
@@ -0,0 +1,160 @@
+/*
+ * Placed into the Public Domain
+ * written by Walter Bright, Digital Mars
+ * www.digitalmars.com
+ */
+
+/* ================================= Win32 ============================ */
+
+#if _WIN32
+
+#include	<windows.h>
+
+/******************************************
+ * Enter/exit critical section.
+ */
+
+/* We don't initialize critical sections unless we actually need them.
+ * So keep a linked list of the ones we do use, and in the static destructor
+ * code, walk the list and release them.
+ */
+
+typedef struct D_CRITICAL_SECTION
+{
+    struct D_CRITICAL_SECTION *next;
+    CRITICAL_SECTION cs;
+} D_CRITICAL_SECTION;
+
+static D_CRITICAL_SECTION *dcs_list;
+static D_CRITICAL_SECTION critical_section;
+static volatile int inited;
+
+void _d_criticalenter(D_CRITICAL_SECTION *dcs)
+{
+    if (!dcs->next)
+    {
+	EnterCriticalSection(&critical_section.cs);
+	if (!dcs->next)	// if, in the meantime, another thread didn't set it
+	{
+	    dcs->next = dcs_list;
+	    dcs_list = dcs;
+	    InitializeCriticalSection(&dcs->cs);
+	}
+	LeaveCriticalSection(&critical_section.cs);
+    }
+    EnterCriticalSection(&dcs->cs);
+}
+
+void _d_criticalexit(D_CRITICAL_SECTION *dcs)
+{
+    LeaveCriticalSection(&dcs->cs);
+}
+
+void _STI_critical_init()
+{
+    if (!inited)
+    {	InitializeCriticalSection(&critical_section.cs);
+	dcs_list = &critical_section;
+	inited = 1;
+    }
+}
+
+void _STD_critical_term()
+{
+    if (inited)
+    {	inited = 0;
+	while (dcs_list)
+	{
+	    DeleteCriticalSection(&dcs_list->cs);
+	    dcs_list = dcs_list->next;
+	}
+    }
+}
+
+#endif
+
+/* ================================= linux ============================ */
+
+#if linux
+
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	<pthread.h>
+
+/******************************************
+ * Enter/exit critical section.
+ */
+
+/* We don't initialize critical sections unless we actually need them.
+ * So keep a linked list of the ones we do use, and in the static destructor
+ * code, walk the list and release them.
+ */
+
+typedef struct D_CRITICAL_SECTION
+{
+    struct D_CRITICAL_SECTION *next;
+    pthread_mutex_t cs;
+} D_CRITICAL_SECTION;
+
+static D_CRITICAL_SECTION *dcs_list;
+static D_CRITICAL_SECTION critical_section;
+static pthread_mutexattr_t _criticals_attr;
+
+void _STI_critical_init(void);
+void _STD_critical_term(void);
+
+void _d_criticalenter(D_CRITICAL_SECTION *dcs)
+{
+    if (!dcs_list)
+    {	_STI_critical_init();
+	atexit(_STD_critical_term);
+    }
+    //printf("_d_criticalenter(dcs = x%x)\n", dcs);
+    if (!dcs->next)
+    {
+	pthread_mutex_lock(&critical_section.cs);
+	if (!dcs->next)	// if, in the meantime, another thread didn't set it
+	{
+	    dcs->next = dcs_list;
+	    dcs_list = dcs;
+	    pthread_mutex_init(&dcs->cs, &_criticals_attr);
+	}
+	pthread_mutex_unlock(&critical_section.cs);
+    }
+    pthread_mutex_lock(&dcs->cs);
+}
+
+void _d_criticalexit(D_CRITICAL_SECTION *dcs)
+{
+    //printf("_d_criticalexit(dcs = x%x)\n", dcs);
+    pthread_mutex_unlock(&dcs->cs);
+}
+
+void _STI_critical_init()
+{
+    if (!dcs_list)
+    {	//printf("_STI_critical_init()\n");
+	pthread_mutexattr_init(&_criticals_attr);
+	pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE_NP);
+
+	// The global critical section doesn't need to be recursive
+	pthread_mutex_init(&critical_section.cs, 0);
+	dcs_list = &critical_section;
+    }
+}
+
+void _STD_critical_term()
+{
+    if (dcs_list)
+    {	//printf("_STI_critical_term()\n");
+	while (dcs_list)
+	{
+	    //printf("\tlooping... %x\n", dcs_list);
+	    pthread_mutex_destroy(&dcs_list->cs);
+	    dcs_list = dcs_list->next;
+	}
+    }
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tango/lib/compiler/llvmdc/dmain2.d	Mon Jan 14 05:11:54 2008 +0100
@@ -0,0 +1,303 @@
+/*
+ * Placed into the Public Domain.
+ * written by Walter Bright
+ * www.digitalmars.com
+ */
+
+/*
+ *  Modified by Sean Kelly <sean@f4.ca> for use with Tango.
+ */
+
+private
+{
+    import util.console;
+
+    import tango.stdc.stddef;
+    import tango.stdc.stdlib;
+    import tango.stdc.string;
+}
+
+version( Win32 )
+{
+    extern (Windows) void*      LocalFree(void*);
+    extern (Windows) wchar_t*   GetCommandLineW();
+    extern (Windows) wchar_t**  CommandLineToArgvW(wchar_t*, int*);
+    extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int);
+    pragma(lib, "shell32.lib");   // needed for CommandLineToArgvW
+    pragma(lib, "tango-win32-dmd.lib"); // links Tango's Win32 library to reduce EXE size
+}
+
+extern (C) void _STI_monitor_staticctor();
+extern (C) void _STD_monitor_staticdtor();
+extern (C) void _STI_critical_init();
+extern (C) void _STD_critical_term();
+extern (C) void gc_init();
+extern (C) void gc_term();
+extern (C) void _minit();
+extern (C) void _moduleCtor();
+extern (C) void _moduleDtor();
+extern (C) void thread_joinAll();
+
+//debug=PRINTF;
+debug(PRINTF) extern (C) int printf(char*, ...);
+
+/***********************************
+ * These functions must be defined for any D program linked
+ * against this library.
+ */
+extern (C) void onAssertError( char[] file, size_t line );
+extern (C) void onAssertErrorMsg( char[] file, size_t line, char[] msg );
+extern (C) void onArrayBoundsError( char[] file, size_t line );
+extern (C) void onSwitchError( char[] file, size_t line );
+extern (C) bool runModuleUnitTests();
+
+// this function is called from the utf module
+//extern (C) void onUnicodeError( char[] msg, size_t idx );
+
+/***********************************
+ * These are internal callbacks for various language errors.
+ */
+extern (C) void _d_assert( char[] file, uint line )
+{
+    onAssertError( file, line );
+}
+
+extern (C) void _d_assert_msg( char[] msg, char[] file, uint line )
+{
+    onAssertErrorMsg( file, line, msg );
+}
+
+extern (C) void _d_array_bounds( char[] file, uint line )
+{
+    onArrayBoundsError( file, line );
+}
+
+extern (C) void _d_switch_error( char[] file, uint line )
+{
+    onSwitchError( file, line );
+}
+
+bool _d_isHalting = false;
+
+extern (C) bool rt_isHalting()
+{
+    return _d_isHalting;
+}
+
+extern (C) bool rt_trapExceptions = true;
+
+void _d_criticalInit()
+{
+    version (linux)
+    {
+        _STI_monitor_staticctor();
+        _STI_critical_init();
+    }
+}
+
+extern (C) bool rt_init( void delegate( Exception ) dg = null )
+{
+    _d_criticalInit();
+
+    try
+    {
+        gc_init();
+        version (Win32)
+            _minit();
+        _moduleCtor();
+        return true;
+    }
+    catch( Exception e )
+    {
+        if( dg )
+            dg( e );
+    }
+    catch
+    {
+
+    }
+    _d_criticalTerm();
+    return false;
+}
+
+void _d_criticalTerm()
+{
+    version (linux)
+    {
+        _STD_critical_term();
+        _STD_monitor_staticdtor();
+    }
+}
+
+extern (C) bool rt_term( void delegate( Exception ) dg = null )
+{
+    try
+    {
+        thread_joinAll();
+        _d_isHalting = true;
+        _moduleDtor();
+        gc_term();
+        return true;
+    }
+    catch( Exception e )
+    {
+        if( dg )
+            dg( e );
+    }
+    catch
+    {
+
+    }
+    finally
+    {
+        _d_criticalTerm();
+    }
+    return false;
+}
+
+/***********************************
+ * The D main() function supplied by the user's program
+ */
+int main(char[][] args);
+
+/***********************************
+ * Substitutes for the C main() function.
+ * It's purpose is to wrap the call to the D main()
+ * function and catch any unhandled exceptions.
+ */
+
+extern (C) int main(int argc, char **argv, char** env)
+{
+    char[][] args;
+    int result;
+
+    version (linux)
+    {
+        debug(PRINTF) printf("main ctors\n");
+        _STI_monitor_staticctor();
+        _STI_critical_init();
+    }
+
+    debug(PRINTF) printf("main args\n");
+    version (Win32)
+    {
+        wchar_t*  wcbuf = GetCommandLineW();
+        size_t    wclen = wcslen(wcbuf);
+        int       wargc = 0;
+        wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
+        assert(wargc == argc);
+
+        char*     cargp = null;
+        size_t    cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
+
+        cargp = cast(char*) alloca(cargl);
+        args  = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
+
+        for (size_t i = 0, p = 0; i < wargc; i++)
+        {
+            int wlen = wcslen( wargs[i] );
+            int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
+            args[i]  = cargp[p .. p+clen];
+            p += clen; assert(p <= cargl);
+            WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
+        }
+        LocalFree(wargs);
+        wargs = null;
+        wargc = 0;
+    }
+    else version (linux)
+    {
+        char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
+        scope(exit) free(am);
+
+        for (size_t i = 0; i < argc; i++)
+        {
+            auto len = strlen(argv[i]);
+            am[i] = argv[i][0 .. len];
+        }
+        args = am[0 .. argc];
+    }
+
+    debug(PRINTF) printf("main trap exceptions\n");
+    bool trapExceptions = rt_trapExceptions;
+
+    void tryExec(void delegate() dg)
+    {
+        debug(PRINTF) printf("main try exec\n");
+        if (trapExceptions)
+        {
+            try
+            {
+                dg();
+            }
+            catch (Exception e)
+            {
+                while (e)
+                {
+                    if (e.file)
+                    {
+                       debug(PRINTF) printf("%.*s(%u): %.*s\n", e.file.length, e.file.ptr, e.line, e.msg.length, e.msg.ptr);
+                       console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n");
+                    }
+                    else
+                    {
+                       // debug(PRINTF) printf("%.*s\n", e.toString());
+                       console (e.classinfo.name)(": ")(e.toString)("\n");
+                    }
+                    e = e.next;
+                }
+                result = EXIT_FAILURE;
+            }
+            catch (Object o)
+            {
+                // fprintf(stderr, "%.*s\n", o.toString());
+                console (o.toString)("\n");
+                result = EXIT_FAILURE;
+            }
+        }
+        else
+        {
+            dg();
+        }
+    }
+
+    // NOTE: The lifetime of a process is much like the lifetime of an object:
+    //       it is initialized, then used, then destroyed.  If initialization
+    //       fails, the successive two steps are never reached.  However, if
+    //       initialization succeeds, then cleanup will occur even if the use
+    //       step fails in some way.  Here, the use phase consists of running
+    //       the user's main function.  If main terminates with an exception,
+    //       the exception is handled and then cleanup begins.  An exception
+    //       thrown during cleanup, however, will abort the cleanup process.
+
+    void runMain()
+    {
+        debug(PRINTF) printf("main runMain\n");
+        result = main(args);
+    }
+
+    void runAll()
+    {
+        debug(PRINTF) printf("main runAll\n");
+        gc_init();
+        version (Win32)
+            _minit();
+        _moduleCtor();
+        if (runModuleUnitTests())
+            tryExec(&runMain);
+        thread_joinAll();
+        _d_isHalting = true;
+        _moduleDtor();
+        gc_term();
+    }
+
+    tryExec(&runAll);
+
+    version (linux)
+    {
+        debug(PRINTF) printf("main dtor\n");
+        _STD_critical_term();
+        _STD_monitor_staticdtor();
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tango/lib/compiler/llvmdc/eh.d	Mon Jan 14 05:11:54 2008 +0100
@@ -0,0 +1,17 @@
+/*
+ * Temporary exception handling stubs
+ */
+
+import util.console;
+
+private extern(C) void abort();
+
+extern(C) void _d_throw_exception(Object e)
+{
+    console("Exception: ");
+    if (e !is null)
+    {
+        console(e.toString())("\n");
+    }
+    abort();
+}
--- a/tango/lib/compiler/llvmdc/genobj.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/tango/lib/compiler/llvmdc/genobj.d	Mon Jan 14 05:11:54 2008 +0100
@@ -37,6 +37,8 @@
 
 module object;
 
+//debug=PRINTF;
+
 private
 {
     import tango.stdc.string; // : memcmp, memcpy;
@@ -962,19 +964,8 @@
 // linux: this gets initialized in _moduleCtor()
 extern (C) ModuleInfo[] _moduleinfo_array;
 
-
-version (linux)
-{
-    // This linked list is created by a compiler generated function inserted
-    // into the .ctor list by the compiler.
-    struct ModuleReference
-    {
-        ModuleReference* next;
-        ModuleInfo       mod;
-    }
-
-    extern (C) ModuleReference* _Dmodule_ref;   // start of linked list
-}
+// llvmdc method
+extern (C) void** _d_get_moduleinfo_array();
 
 ModuleInfo[] _moduleinfo_dtors;
 uint         _moduleinfo_dtors_i;
@@ -989,19 +980,20 @@
 extern (C) void _moduleCtor()
 {
     debug(PRINTF) printf("_moduleCtor()\n");
-    version (linux)
-    {
-        int len = 0;
-        ModuleReference *mr;
+
+    ModuleInfo* mrbegin = cast(ModuleInfo*)_d_get_moduleinfo_array();
+    assert(mrbegin !is null);
 
-        for (mr = _Dmodule_ref; mr; mr = mr.next)
-            len++;
-        _moduleinfo_array = new ModuleInfo[len];
-        len = 0;
-        for (mr = _Dmodule_ref; mr; mr = mr.next)
-        {   _moduleinfo_array[len] = mr.mod;
-            len++;
-        }
+    int len = 0;
+    ModuleInfo* mr;
+    for (mr = mrbegin; *mr !is null; ++mr)
+        len++;
+    _moduleinfo_array = new ModuleInfo[len];
+
+    len = 0;
+    for (mr = mrbegin; *mr !is null; ++mr)
+    {   _moduleinfo_array[len] = *mr;
+        len++;
     }
 
     version (Win32)
@@ -1014,6 +1006,7 @@
     debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors);
     _moduleIndependentCtors();
     _moduleCtor2(_moduleinfo_array, 0);
+    debug(PRINTF) printf("_moduleCtor() DONE\n");
 }
 
 extern (C) void _moduleIndependentCtors()
@@ -1026,6 +1019,7 @@
             (*m.ictor)();
         }
     }
+    debug(PRINTF) printf("_moduleIndependentCtors() DONE\n");
 }
 
 void _moduleCtor2(ModuleInfo[] mi, int skip)
@@ -1038,10 +1032,10 @@
         debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
         if (!m)
             continue;
-        debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name.length, m.name.ptr);
         if (m.flags & MIctordone)
             continue;
-        debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name.length, m.name.ptr, m);
 
         if (m.ctor || m.dtor)
         {
@@ -1069,6 +1063,7 @@
             _moduleCtor2(m.importedModules, 1);
         }
     }
+    debug(PRINTF) printf("_moduleCtor2() DONE\n");
 }
 
 /**
--- a/tango/lib/compiler/llvmdc/lifetime.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/tango/lib/compiler/llvmdc/lifetime.d	Mon Jan 14 05:11:54 2008 +0100
@@ -26,6 +26,8 @@
  */
 module lifetime;
 
+//debug=PRINTF;
+debug=PRINTF2;
 
 private
 {
@@ -33,6 +35,7 @@
     import tango.stdc.string;
     import tango.stdc.stdarg;
     debug(PRINTF) import tango.stdc.stdio;
+    else debug(PRINTF2) import tango.stdc.stdio;
 }
 
 
@@ -86,7 +89,8 @@
 {
     void* p;
 
-    debug(PRINTF) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char *)ci.name);
+    debug(PRINTF) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char *)ci.name.ptr);
+    /+
     if (ci.flags & 1) // if COM object
     {   /* COM objects are not garbage collected, they are reference counted
          * using AddRef() and Release().  They get free'd by C's free()
@@ -98,10 +102,11 @@
             onOutOfMemoryError();
     }
     else
+    +/
     {
         p = gc_malloc(ci.init.length,
                       BlkAttr.FINALIZE | (ci.flags & 2 ? BlkAttr.NO_SCAN : 0));
-        debug(PRINTF) printf(" p = %p\n", p);
+        debug(PRINTF2) printf(" p = %p\n", p);
     }
 
     debug(PRINTF)
@@ -119,7 +124,8 @@
     }
 
     // initialize it
-    (cast(byte*) p)[0 .. ci.init.length] = ci.init[];
+    // llvmdc does this inline
+    //(cast(byte*) p)[0 .. ci.init.length] = ci.init[];
 
     debug(PRINTF) printf("initialization done\n");
     return cast(Object) p;
--- a/tango/lib/compiler/llvmdc/llvmdc.mak	Fri Jan 11 17:57:40 2008 +0100
+++ b/tango/lib/compiler/llvmdc/llvmdc.mak	Mon Jan 14 05:11:54 2008 +0100
@@ -13,6 +13,9 @@
 LIB_TARGET=libtango-rt-llvmdc.a
 LIB_MASK=libtango-rt-llvmdc*.a
 
+LIB_TARGET_C=libtango-rt-c-llvmdc.a
+LIB_MASK_C=libtango-rt-c-llvmdc*.a
+
 CP=cp -f
 RM=rm -f
 MD=mkdir -p
@@ -30,6 +33,7 @@
 
 CC=gcc
 LC=llvm-ar rsv
+CLC=ar rsv
 DC=llvmdc
 LLC=llvm-as
 
@@ -60,10 +64,13 @@
 
 targets : lib doc
 all     : lib doc
-lib     : llvmdc.lib
+lib     : llvmdc.lib llvmdc.clib
 doc     : llvmdc.doc
 
 ######################################################
+OBJ_C= \
+    monitor.o \
+    critical.o
 
 OBJ_BASE= \
     aaA.bc \
@@ -72,7 +79,8 @@
     adi.bc \
     arrays.bc \
     cast.bc \
-    contract.bc \
+    dmain2.bc \
+    eh.bc \
     genobj.bc \
     lifetime.bc \
     mem.bc \
@@ -147,6 +155,12 @@
 	$(RM) $@
 	$(LC) $@ $(ALL_OBJS)
 
+llvmdc.clib : $(LIB_TARGET_C)
+
+$(LIB_TARGET_C) : $(OBJ_C)
+	$(RM) $@
+	$(CLC) $@ $(OBJ_C)
+
 llvmdc.doc : $(ALL_DOCS)
 	echo No documentation available.
 
@@ -155,9 +169,12 @@
 clean :
 	find . -name "*.di" | xargs $(RM)
 	$(RM) $(ALL_OBJS)
+	$(RM) $(OBJ_C)
 	$(RM) $(ALL_DOCS)
 	$(RM) $(LIB_MASK)
+	$(RM) $(LIB_MASK_C)
 
 install :
 	$(MD) $(LIB_DEST)
 	$(CP) $(LIB_MASK) $(LIB_DEST)/.
+	$(CP) $(LIB_MASK_C) $(LIB_DEST)/.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tango/lib/compiler/llvmdc/mars.h	Mon Jan 14 05:11:54 2008 +0100
@@ -0,0 +1,104 @@
+
+/*
+ * Placed into the Public Domain
+ * written by Walter Bright, Digital Mars
+ * www.digitalmars.com
+ */
+
+/*
+ *  Modified by Sean Kelly <sean@f4.ca> for use with Tango.
+ */
+
+#include <stddef.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+struct ClassInfo;
+struct Vtbl;
+
+typedef struct Vtbl
+{
+    size_t len;
+    void **vptr;
+} Vtbl;
+
+typedef struct Interface
+{
+    struct ClassInfo *classinfo;
+    struct Vtbl vtbl;
+    int offset;
+} Interface;
+
+typedef struct Object
+{
+    void **vptr;
+    void *monitor;
+} Object;
+
+typedef struct ClassInfo
+{
+    Object object;
+
+    size_t initlen;
+    void *init;
+
+    size_t namelen;
+    char *name;
+
+    Vtbl vtbl;
+
+    size_t interfacelen;
+    Interface *interfaces;
+
+    struct ClassInfo *baseClass;
+
+    void *destructor;
+    void *invariant;
+
+    int flags;
+} ClassInfo;
+
+typedef struct Exception
+{
+    Object object;
+
+    size_t msglen;
+    char*  msg;
+
+    size_t filelen;
+    char*  file;
+
+    size_t line;
+
+    struct Exception *next;
+} Exception;
+
+typedef struct Array
+{
+    size_t length;
+    void *ptr;
+} Array;
+
+typedef struct Delegate
+{
+    void *thisptr;
+    void (*funcptr)();
+} Delegate;
+
+void _d_monitorenter(Object *h);
+void _d_monitorexit(Object *h);
+
+int _d_isbaseof(ClassInfo *b, ClassInfo *c);
+Object *_d_dynamic_cast(Object *o, ClassInfo *ci);
+
+Object * _d_newclass(ClassInfo *ci);
+void _d_delclass(Object **p);
+
+void _d_OutOfMemory();
+
+#if __cplusplus
+}
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tango/lib/compiler/llvmdc/monitor.c	Mon Jan 14 05:11:54 2008 +0100
@@ -0,0 +1,207 @@
+// D programming language runtime library
+// Public Domain
+// written by Walter Bright, Digital Mars
+// www.digitalmars.com
+
+// This is written in C because nobody has written a pthreads interface
+// to D yet.
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#if _WIN32
+#elif linux
+#define USE_PTHREADS	1
+#else
+#endif
+
+#if _WIN32
+#include <windows.h>
+#endif
+
+#if USE_PTHREADS
+#include <pthread.h>
+#endif
+
+#include "mars.h"
+
+// This is what the monitor reference in Object points to
+typedef struct Monitor
+{
+    void* impl; // for user-level monitors
+
+#if _WIN32
+    CRITICAL_SECTION mon;
+#endif
+
+#if USE_PTHREADS
+    pthread_mutex_t mon;
+#endif
+} Monitor;
+
+#define MONPTR(h)	(&((Monitor *)(h)->monitor)->mon)
+
+static volatile int inited;
+
+/* =============================== Win32 ============================ */
+
+#if _WIN32
+
+static CRITICAL_SECTION _monitor_critsec;
+
+void _STI_monitor_staticctor()
+{
+    if (!inited)
+    {	InitializeCriticalSection(&_monitor_critsec);
+	inited = 1;
+    }
+}
+
+void _STD_monitor_staticdtor()
+{
+    if (inited)
+    {	inited = 0;
+	DeleteCriticalSection(&_monitor_critsec);
+    }
+}
+
+void _d_monitor_create(Object *h)
+{
+    /*
+     * NOTE: Assume this is only called when h->monitor is null prior to the
+     * call.  However, please note that another thread may call this function
+     * at the same time, so we can not assert this here.  Instead, try and
+     * create a lock, and if one already exists then forget about it.
+     */
+
+    //printf("+_d_monitor_create(%p)\n", h);
+    assert(h);
+    Monitor *cs = NULL;
+    EnterCriticalSection(&_monitor_critsec);
+    if (!h->monitor)
+    {
+        cs = (Monitor *)calloc(sizeof(Monitor), 1);
+        assert(cs);
+        InitializeCriticalSection(&cs->mon);
+        h->monitor = (void *)cs;
+        cs = NULL;
+    }
+    LeaveCriticalSection(&_monitor_critsec);
+    if (cs)
+        free(cs);
+    //printf("-_d_monitor_create(%p)\n", h);
+}
+
+void _d_monitor_destroy(Object *h)
+{
+    //printf("+_d_monitor_destroy(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    DeleteCriticalSection(MONPTR(h));
+    free((void *)h->monitor);
+    h->monitor = NULL;
+    //printf("-_d_monitor_destroy(%p)\n", h);
+}
+
+int _d_monitor_lock(Object *h)
+{
+    //printf("+_d_monitor_acquire(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    EnterCriticalSection(MONPTR(h));
+    //printf("-_d_monitor_acquire(%p)\n", h);
+}
+
+void _d_monitor_unlock(Object *h)
+{
+    //printf("+_d_monitor_release(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    LeaveCriticalSection(MONPTR(h));
+    //printf("-_d_monitor_release(%p)\n", h);
+}
+
+#endif
+
+/* =============================== linux ============================ */
+
+#if USE_PTHREADS
+
+// Includes attribute fixes from David Friedman's GDC port
+
+static pthread_mutex_t _monitor_critsec;
+static pthread_mutexattr_t _monitors_attr;
+
+void _STI_monitor_staticctor()
+{
+    if (!inited)
+    {
+	pthread_mutexattr_init(&_monitors_attr);
+	pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE_NP);
+	pthread_mutex_init(&_monitor_critsec, 0);
+	inited = 1;
+    }
+}
+
+void _STD_monitor_staticdtor()
+{
+    if (inited)
+    {	inited = 0;
+	pthread_mutex_destroy(&_monitor_critsec);
+	pthread_mutexattr_destroy(&_monitors_attr);
+    }
+}
+
+void _d_monitor_create(Object *h)
+{
+    /*
+     * NOTE: Assume this is only called when h->monitor is null prior to the
+     * call.  However, please note that another thread may call this function
+     * at the same time, so we can not assert this here.  Instead, try and
+     * create a lock, and if one already exists then forget about it.
+     */
+
+    //printf("+_d_monitor_create(%p)\n", h);
+    assert(h);
+    Monitor *cs = NULL;
+    pthread_mutex_lock(&_monitor_critsec);
+    if (!h->monitor)
+    {
+        cs = (Monitor *)calloc(sizeof(Monitor), 1);
+        assert(cs);
+        pthread_mutex_init(&cs->mon, & _monitors_attr);
+        h->monitor = (void *)cs;
+        cs = NULL;
+    }
+    pthread_mutex_unlock(&_monitor_critsec);
+    if (cs)
+        free(cs);
+    //printf("-_d_monitor_create(%p)\n", h);
+}
+
+void _d_monitor_destroy(Object *h)
+{
+    //printf("+_d_monitor_destroy(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    pthread_mutex_destroy(MONPTR(h));
+    free((void *)h->monitor);
+    h->monitor = NULL;
+    //printf("-_d_monitor_destroy(%p)\n", h);
+}
+
+int _d_monitor_lock(Object *h)
+{
+    //printf("+_d_monitor_acquire(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    pthread_mutex_lock(MONPTR(h));
+    //printf("-_d_monitor_acquire(%p)\n", h);
+}
+
+void _d_monitor_unlock(Object *h)
+{
+    //printf("+_d_monitor_release(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    pthread_mutex_unlock(MONPTR(h));
+    //printf("-_d_monitor_release(%p)\n", h);
+}
+
+#endif
--- a/tango/lib/compiler/llvmdc/util/console.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/tango/lib/compiler/llvmdc/util/console.d	Mon Jan 14 05:11:54 2008 +0100
@@ -75,9 +75,9 @@
     }
 
     // emit an integer to the console
-    Console opCall (uint i)
+    Console opCall (size_t i)
     {
-            char[10] tmp = void;
+            char[20] tmp = void;
 
             return console (intToUtf8 (tmp, i));
     }
--- a/tango/lib/llvmdc-posix.mak	Fri Jan 11 17:57:40 2008 +0100
+++ b/tango/lib/llvmdc-posix.mak	Mon Jan 14 05:11:54 2008 +0100
@@ -12,6 +12,8 @@
 
 LIB_TARGET=libtango-base-llvmdc.a
 LIB_MASK=libtango-base-llvmdc*.a
+LIB_TARGET_C=libtango-base-c-llvmdc.a
+LIB_MASK_C=libtango-base-c-llvmdc*.a
 
 DIR_CC=./common/tango
 DIR_RT=./compiler/llvmdc
@@ -23,13 +25,14 @@
 
 CC=gcc
 LC=llvm-ar rsv
+CLC=ar rsv
 DC=llvmdc
 
 ADD_CFLAGS=
 ADD_DFLAGS=
 
-targets : lib doc
-all     : lib doc
+targets : lib clib doc
+all     : lib clib doc
 
 ######################################################
 
@@ -49,6 +52,8 @@
 	$(LC) $(LIB_TARGET) `find $(DIR_CC) -name "*.bc" | xargs echo`
 	$(LC) $(LIB_TARGET) `find $(DIR_RT) -name "*.bc" | xargs echo`
 	$(LC) $(LIB_TARGET) `find $(DIR_GC) -name "*.bc" | xargs echo`
+	$(CLC) $(LIB_TARGET_C) `find $(DIR_CC) -name "*.o" | xargs echo`
+	$(CLC) $(LIB_TARGET_C) `find $(DIR_RT) -name "*.o" | xargs echo`
 
 doc : $(ALL_DOCS)
 	make -C $(DIR_CC) -fllvmdc.mak doc
@@ -65,9 +70,11 @@
 	make -C $(DIR_RT) -fllvmdc.mak clean
 	make -C $(DIR_GC) -fllvmdc.mak clean
 	$(RM) $(LIB_MASK)
+	$(RM) $(LIB_MASK_C)
 
 install :
 	make -C $(DIR_CC) -fllvmdc.mak install
 	make -C $(DIR_RT) -fllvmdc.mak install
 	make -C $(DIR_GC) -fllvmdc.mak install
-#	$(CP) $(LIB_MASK) $(LIB_DEST)/.
+	$(CP) $(LIB_MASK) $(LIB_DEST)/.
+	$(CP) $(LIB_MASK_C) $(LIB_DEST)/.
--- a/tango/tango/io/Console.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/tango/tango/io/Console.d	Mon Jan 14 05:11:54 2008 +0100
@@ -621,14 +621,21 @@
 
 ******************************************************************************/
 
+extern(C) int printf(char*, ...);
+
 static this ()
 {
+        printf("STATIC INIT FOR CONSOLE\n");
+        printf("Cin\n");
         auto conduit = new Console.Conduit (0);
+        assert(conduit);
         Cin  = new Console.Input (conduit, conduit.redirected);
 
+        printf("Cout\n");
         conduit = new Console.Conduit (1);
         Cout = new Console.Output (conduit, conduit.redirected);
 
+        printf("Cerr\n");
         conduit = new Console.Conduit (2);
         Cerr = new Console.Output (conduit, conduit.redirected);
 }
--- a/tangotests/f.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/tangotests/f.d	Mon Jan 14 05:11:54 2008 +0100
@@ -1,5 +1,7 @@
 extern(C) int printf(char*,...);
 
+
+
 void main()
 {
     printf("Hello World!\n");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tangotests/h.d	Mon Jan 14 05:11:54 2008 +0100
@@ -0,0 +1,27 @@
+interface Iin
+{
+    void[] read(size_t n);
+}
+
+interface Iout
+{
+    size_t write(void[] d);
+}
+
+class C : Iin
+{
+    void[] read(size_t n)
+    {
+        return null;
+    }
+
+    size_t write(void[] d)
+    {
+        return 0;
+    }
+}
+
+void func()
+{
+    scope c = new C;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tangotests/i.d	Mon Jan 14 05:11:54 2008 +0100
@@ -0,0 +1,20 @@
+interface IN
+{
+    void func();
+}
+abstract class AC
+{
+    abstract void func();
+    long ll;
+}
+class C : AC
+{
+    void func()
+    {
+    }
+}
+
+void func()
+{
+    scope c = new C;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tangotests/j.d	Mon Jan 14 05:11:54 2008 +0100
@@ -0,0 +1,44 @@
+module j;
+
+interface Inter1
+{
+    int func1();
+}
+
+interface Inter2
+{
+    int func2();
+}
+
+class C12 : Inter1, Inter2
+{
+    int func1()
+    {
+        return 1;
+    }
+    int func2()
+    {
+        return 2;
+    }
+}
+
+void func(Object c)
+{
+    auto i1 = cast(Inter1)c;
+    assert(i1.func1() == 1);
+    auto i2 = cast(Inter2)c;
+    assert(i2.func2() == 2);
+    auto j1 = cast(Inter1)i2;
+    assert(j1.func1() == 1);
+    auto j2 = cast(Inter2)i1;
+    assert(j2.func2() == 2);
+}
+
+void main()
+{
+    scope c = new C12;
+    func(c);
+    printf("OK\n");
+}
+
+extern(C) int printf(char*,...);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tangotests/k.d	Mon Jan 14 05:11:54 2008 +0100
@@ -0,0 +1,31 @@
+interface Inter
+{
+    int func();
+}
+
+extern(C) int printf(char*, ...);
+
+class InterClass : Inter
+{
+    int func()
+    {
+        return printf("InterClass.func()\n");
+    }
+}
+
+alias int delegate() dg_t;
+
+void main()
+{
+    scope c = new InterClass;
+
+    {
+    Inter i = cast(Inter)c;
+        {
+        dg_t dg = &i.func;
+            {
+            int j = dg();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tangotests/l.d	Mon Jan 14 05:11:54 2008 +0100
@@ -0,0 +1,11 @@
+import tango.io.Console;
+
+void main()
+{
+    printf("enter\n");
+    assert(Cout !is null);
+    Cout("Hi, says LLVMDC + Tango").newline;
+    printf("exit\n");
+}
+
+extern(C) int printf(char*,...);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tangotests/m.d	Mon Jan 14 05:11:54 2008 +0100
@@ -0,0 +1,10 @@
+void main()
+{
+    int* e = __errno_location();
+    printf("&errno = %p\n", e);
+    printf("errno = %d\n", *e);
+}
+
+extern(C):
+int* __errno_location();
+int printf(char*,...);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tangotests/n.d	Mon Jan 14 05:11:54 2008 +0100
@@ -0,0 +1,18 @@
+struct Structure
+{
+    static void static_method()
+    {
+    }
+
+    void method()
+    {
+    }
+}
+
+void main()
+{
+    //Structure.static_method();
+
+    Structure s;
+    s.method();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tangotests/o.d	Mon Jan 14 05:11:54 2008 +0100
@@ -0,0 +1,24 @@
+extern(C) int printf(char*, ...);
+
+void func()
+{
+    try
+    {
+        printf("try\n");
+        return 0;
+    }
+    catch
+    {
+        printf("catch\n");
+    }
+    finally
+    {
+        printf("finally\n");
+    }
+    return 0;
+}
+
+void main()
+{
+    func();
+}
--- a/test/interface1.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/test/interface1.d	Mon Jan 14 05:11:54 2008 +0100
@@ -1,5 +1,7 @@
 module interface1;
 
+extern(C) int printf(char*,...);
+
 interface Inter
 {
     void func();
--- a/test/interface2.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/test/interface2.d	Mon Jan 14 05:11:54 2008 +0100
@@ -1,5 +1,7 @@
 module interface2;
 
+extern(C) int printf(char*,...);
+
 interface A
 {
     void a();
--- a/test/interface3.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/test/interface3.d	Mon Jan 14 05:11:54 2008 +0100
@@ -1,5 +1,7 @@
 module interface3;
 
+extern(C) int printf(char*,...);
+
 interface I
 {
     void func();
--- a/test/interface4.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/test/interface4.d	Mon Jan 14 05:11:54 2008 +0100
@@ -1,5 +1,7 @@
 module interface4;
 
+extern(C) int printf(char*,...);
+
 interface I
 {
     void func();
--- a/test/interface5.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/test/interface5.d	Mon Jan 14 05:11:54 2008 +0100
@@ -1,5 +1,7 @@
 module interface5;
 
+extern(C) int printf(char*,...);
+
 interface I
 {
     void func();
--- a/test/interface6.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/test/interface6.d	Mon Jan 14 05:11:54 2008 +0100
@@ -1,5 +1,7 @@
 module interface6;
 
+extern(C) int printf(char*,...);
+
 interface I
 {
     void Ifunc();
--- a/test/interface7.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/test/interface7.d	Mon Jan 14 05:11:54 2008 +0100
@@ -1,5 +1,7 @@
 module interface7;
 
+extern(C) int printf(char*,...);
+
 interface I
 {
 }
--- a/test/intrinsics.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/test/intrinsics.d	Mon Jan 14 05:11:54 2008 +0100
@@ -1,5 +1,6 @@
 import llvm.intrinsic;
 
+extern(C) int printf(char*,...);
 extern(C) int scanf(char*,...);
 
 void main()
--- a/test/mainargs1.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/test/mainargs1.d	Mon Jan 14 05:11:54 2008 +0100
@@ -1,5 +1,7 @@
 module mainargs1;
 
+extern(C) int printf(char*,...);
+
 void main(string[] args)
 {
     foreach(v; args)
--- a/test/memory1.d	Fri Jan 11 17:57:40 2008 +0100
+++ b/test/memory1.d	Mon Jan 14 05:11:54 2008 +0100
@@ -1,5 +1,7 @@
 module memory1;
 
+extern(C) int printf(char*,...);
+
 void main()
 {
     auto a = new int[16];