changeset 486:a34078905d01

Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in. Reimplemented support for nested functions/class using a new approach. Added error on taking address of intrinsic. Fixed problems with the ->syntaxCopy of TypeFunction delegate exp. Removed DtoDType and replaced all uses with ->toBasetype() instead. Removed unused inplace stuff. Fixed a bunch of issues in the runtime unittests, not complete yet. Added mini tests.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sun, 10 Aug 2008 08:37:38 +0200
parents 50f6e2337a6b
children d7b2e8777e2b
files dmd/attrib.c dmd/expression.c dmd/id.c dmd/id.h dmd/idgen.c dmd/mars.c dmd/module.c dmd/module.h dmd/mtype.c dmd/mtype.h gen/arrays.cpp gen/classes.cpp gen/classes.h gen/complex.cpp gen/dvalue.h gen/enums.h gen/functions.cpp gen/functions.h gen/llvmhelpers.cpp gen/llvmhelpers.h gen/statements.cpp gen/structs.cpp gen/tocall.cpp gen/todebug.cpp gen/toir.cpp gen/tollvm.cpp gen/tollvm.h gen/toobj.cpp ir/irfunction.cpp ir/irfunction.h runtime/internal/aApplyR.d runtime/internal/aaA.d runtime/internal/adi.d tests/mini/aa7.d tests/mini/nested13.d tests/mini/nested16.d tests/mini/nested17.d tests/mini/nested19.d tests/mini/nested6.d
diffstat 39 files changed, 703 insertions(+), 465 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/attrib.c	Sat Aug 09 09:03:52 2008 +0200
+++ b/dmd/attrib.c	Sun Aug 10 08:37:38 2008 +0200
@@ -831,7 +831,7 @@
 // LLVMDC
 #if IN_LLVM
 
-    // pragma(intrinsic, string) { funcdecl(s) }
+    // pragma(intrinsic, "string") { funcdecl(s) }
     else if (ident == Id::intrinsic)
     {
         Expression* expr = (Expression *)args->data[0];
@@ -920,6 +920,27 @@
         }
         llvm_internal = LLVMva_arg;
     }
+    
+    // pragma(llvmdc, "string") { templdecl(s) }
+    else if (ident == Id::llvmdc)
+    {
+        Expression* expr = (Expression *)args->data[0];
+        expr = expr->semantic(sc);
+        if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
+        {
+             error("pragma llvmdc requires exactly 1 string literal parameter");
+             fatal();
+        }
+        else if (arg1str == "verbose")
+        {
+            sc->module->llvmForceLogging = true;
+        }
+        else
+        {
+            error("pragma llvmdc command '%s' invalid");
+            fatal();
+        }
+    }
 
 #endif // LLVMDC
 
--- a/dmd/expression.c	Sat Aug 09 09:03:52 2008 +0200
+++ b/dmd/expression.c	Sun Aug 10 08:37:38 2008 +0200
@@ -260,6 +260,10 @@
 		    {
 			//printf("rewriting e1 to %s's this\n", f->toChars());
 			n++;
+
+            // LLVMDC seems dmd misses it sometimes here :/
+            f->vthis->nestedref = 1;
+
 			e1 = new VarExp(loc, f->vthis);
 		    }
 		}
@@ -5983,6 +5987,13 @@
 	    FuncDeclaration *f = dve->var->isFuncDeclaration();
         VarDeclaration *v = dve->var->isVarDeclaration();
 
+        // LLVMDC
+        if (f && f->isIntrinsic())
+        {
+            error("cannot take the address of intrinsic function %s", e1->toChars());
+            return this;
+        }
+
 	    if (f && f->isNested())
 	    {	Expression *e;
 
--- a/dmd/id.c	Sat Aug 09 09:03:52 2008 +0200
+++ b/dmd/id.c	Sun Aug 10 08:37:38 2008 +0200
@@ -176,6 +176,7 @@
 Identifier *Id::vacopy;
 Identifier *Id::vaend;
 Identifier *Id::vaarg;
+Identifier *Id::llvmdc;
 Identifier *Id::tohash;
 Identifier *Id::tostring;
 Identifier *Id::main;
@@ -357,6 +358,7 @@
     vacopy = Lexer::idPool("va_copy");
     vaend = Lexer::idPool("va_end");
     vaarg = Lexer::idPool("va_arg");
+    llvmdc = Lexer::idPool("llvmdc");
     tohash = Lexer::idPool("toHash");
     tostring = Lexer::idPool("toString");
     main = Lexer::idPool("main");
--- a/dmd/id.h	Sat Aug 09 09:03:52 2008 +0200
+++ b/dmd/id.h	Sun Aug 10 08:37:38 2008 +0200
@@ -178,6 +178,7 @@
     static Identifier *vacopy;
     static Identifier *vaend;
     static Identifier *vaarg;
+    static Identifier *llvmdc;
     static Identifier *tohash;
     static Identifier *tostring;
     static Identifier *main;
--- a/dmd/idgen.c	Sat Aug 09 09:03:52 2008 +0200
+++ b/dmd/idgen.c	Sun Aug 10 08:37:38 2008 +0200
@@ -223,6 +223,7 @@
     { "vacopy", "va_copy" },
     { "vaend", "va_end" },
     { "vaarg", "va_arg" },
+    { "llvmdc" },
 
     // For toHash/toString
     { "tohash", "toHash" },
--- a/dmd/mars.c	Sat Aug 09 09:03:52 2008 +0200
+++ b/dmd/mars.c	Sun Aug 10 08:37:38 2008 +0200
@@ -311,6 +311,7 @@
     VersionCondition::addPredefinedGlobalIdent("LLVM");
     VersionCondition::addPredefinedGlobalIdent("LLVMDC");
 #endif
+
 #if _WIN32
     VersionCondition::addPredefinedGlobalIdent("Windows");
     VersionCondition::addPredefinedGlobalIdent("Win32");
--- a/dmd/module.c	Sat Aug 09 09:03:52 2008 +0200
+++ b/dmd/module.c	Sun Aug 10 08:37:38 2008 +0200
@@ -162,6 +162,9 @@
     bcfile = new File(bcfilename);
     llfile = new File(llfilename);
     symfile = new File(symfilename);
+    
+    // LLVMDC
+    llvmForceLogging = false;
 }
 
 void Module::setDocfile()
--- a/dmd/module.h	Sat Aug 09 09:03:52 2008 +0200
+++ b/dmd/module.h	Sun Aug 10 08:37:38 2008 +0200
@@ -66,8 +66,11 @@
     ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
     File *srcfile;	// input source file
     File *objfile;	// output .obj file
+    
+    // LLVMDC
     File *bcfile;  // output .bc file
     File *llfile;  // output .ll file
+
     File *hdrfile;	// 'header' file
     File *symfile;	// output symbol file
     File *docfile;	// output documentation file
@@ -171,6 +174,8 @@
 
     // LLVMDC
     Module *isModule() { return this; }
+    
+    bool llvmForceLogging;
 };
 
 
--- a/dmd/mtype.c	Sat Aug 09 09:03:52 2008 +0200
+++ b/dmd/mtype.c	Sun Aug 10 08:37:38 2008 +0200
@@ -2651,9 +2651,10 @@
     this->varargs = varargs;
     this->linkage = linkage;
     this->inuse = 0;
-    this->llvmRetInPtr = false;
-    this->llvmUsesThis = false;
-    this->llvmRetAttrs = 0;
+    this->retInPtr = false;
+    this->usesThis = false;
+    this->usesNest = false;
+    this->retAttrs = 0;
 }
 
 Type *TypeFunction::syntaxCopy()
@@ -2661,9 +2662,10 @@
     Type *treturn = next ? next->syntaxCopy() : NULL;
     Arguments *params = Argument::arraySyntaxCopy(parameters);
     TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage);
-    t->llvmRetInPtr = llvmRetInPtr;
-    t->llvmUsesThis = llvmUsesThis;
-    t->llvmRetAttrs = llvmRetAttrs;
+    t->retInPtr = retInPtr;
+    t->usesThis = usesThis;
+    t->usesNest = usesNest;
+    t->retAttrs = retAttrs;
     return t;
 }
 
@@ -3813,6 +3815,11 @@
     return sym->toChars();
 }
 
+Type *TypeEnum::syntaxCopy()
+{
+    return this;
+}
+
 Type *TypeEnum::semantic(Loc loc, Scope *sc)
 {
     sym->semantic(sc);
--- a/dmd/mtype.h	Sat Aug 09 09:03:52 2008 +0200
+++ b/dmd/mtype.h	Sun Aug 10 08:37:38 2008 +0200
@@ -441,9 +441,11 @@
 
     unsigned totym();
 
-    bool llvmRetInPtr;
-    bool llvmUsesThis;
-    unsigned llvmRetAttrs;
+    // LLVMDC
+    bool retInPtr;
+    bool usesThis;
+    bool usesNest;
+    unsigned retAttrs;
 };
 
 struct TypeDelegate : Type
@@ -556,6 +558,7 @@
     d_uns64 size(Loc loc);
     unsigned alignsize();
     char *toChars();
+    Type *syntaxCopy();
     Type *semantic(Loc loc, Scope *sc);
     Dsymbol *toDsymbol(Scope *sc);
     void toDecoBuffer(OutBuffer *buf);
--- a/gen/arrays.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/arrays.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -89,7 +89,7 @@
         const LLArrayType* arrty = isaArray(src->getType()->getContainedType(0));
         if (!arrty)
         {
-            Logger::cout() << "invalid: " << *src << '\n';
+            std::cout << "invalid: " << *src << '\n';
             assert(0);
         }
         const LLType* dstty = getPtrToType(arrty->getElementType());
@@ -244,7 +244,7 @@
     Logger::println("DtoConstArrayInitializer: %s | %s", arrinit->toChars(), arrinit->type->toChars());
     LOG_SCOPE;
 
-    Type* arrinittype = DtoDType(arrinit->type);
+    Type* arrinittype = arrinit->type->toBasetype();
 
     Type* t;
     integer_t tdim;
@@ -530,8 +530,7 @@
 
     DValue* e = exp->toElem(gIR);
 
-    if (!e->inPlace())
-        DtoAssign(exp->loc, dptr, e);
+    DtoAssign(exp->loc, dptr, e);
 
     return slice;
 }
@@ -573,8 +572,8 @@
     Logger::println("DtoCatArrays");
     LOG_SCOPE;
 
-    Type* t1 = DtoDType(exp1->type);
-    Type* t2 = DtoDType(exp2->type);
+    Type* t1 = exp1->type->toBasetype();
+    Type* t2 = exp2->type->toBasetype();
 
     assert(t1->ty == Tarray || t1->ty == Tsarray);
     assert(t2->ty == Tarray || t2->ty == Tsarray);
@@ -614,8 +613,8 @@
     Logger::println("DtoCatArrayElement");
     LOG_SCOPE;
 
-    Type* t1 = DtoDType(exp1->type);
-    Type* t2 = DtoDType(exp2->type);
+    Type* t1 = exp1->type->toBasetype();
+    Type* t2 = exp2->type->toBasetype();
 
     DValue* e1 = exp1->toElem(gIR);
     DValue* e2 = exp2->toElem(gIR);
@@ -623,7 +622,7 @@
     llvm::Value *len1, *src1, *res;
 
     // handle prefix case, eg. int~int[]
-    if (t2->next && t1 == DtoDType(t2->next))
+    if (t2->next && t1 == t2->next->toBasetype())
     {
         len1 = DtoArrayLen(e2);
         res = gIR->ir->CreateAdd(len1,DtoConstSize_t(1),"tmp");
@@ -683,8 +682,8 @@
 
     // cast static arrays to dynamic ones, this turns them into DSliceValues
     Logger::println("casting to dynamic arrays");
-    Type* l_ty = DtoDType(l->getType());
-    Type* r_ty = DtoDType(r->getType());
+    Type* l_ty = l->getType()->toBasetype();
+    Type* r_ty = r->getType()->toBasetype();
     assert(l_ty->next == r_ty->next);
     if ((l_ty->ty == Tsarray) || (r_ty->ty == Tsarray)) {
         Type* a_ty = l_ty->next->arrayOf();
@@ -815,7 +814,7 @@
 
     if (!skip)
     {
-        Type* t = DtoDType(DtoDType(l->getType())->next);
+        Type* t = l->getType()->toBasetype()->next->toBasetype();
         if (t->ty == Tchar)
             res = DtoArrayEqCmp_impl(loc, "_adCmpChar", l, r, false);
         else
@@ -900,7 +899,7 @@
     Logger::println("DtoArrayLen");
     LOG_SCOPE;
 
-    Type* t = DtoDType(v->getType());
+    Type* t = v->getType()->toBasetype();
     if (t->ty == Tarray) {
         if (DSliceValue* s = v->isSlice())
             return s->len;
@@ -926,7 +925,7 @@
     Logger::println("DtoArrayPtr");
     LOG_SCOPE;
 
-    Type* t = DtoDType(v->getType());
+    Type* t = v->getType()->toBasetype();
     if (t->ty == Tarray) {
         if (DSliceValue* s = v->isSlice())
             return s->ptr;
@@ -951,8 +950,8 @@
 
     const LLType* tolltype = DtoType(to);
 
-    Type* totype = DtoDType(to);
-    Type* fromtype = DtoDType(u->getType());
+    Type* totype = to->toBasetype();
+    Type* fromtype = u->getType()->toBasetype();
     assert(fromtype->ty == Tarray || fromtype->ty == Tsarray);
 
     LLValue* rval;
--- a/gen/classes.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/classes.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -786,7 +786,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-DValue* DtoNewClass(TypeClass* tc, NewExp* newexp)
+DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
 {
     // resolve type
     DtoForceDeclareDsymbol(tc->sym);
@@ -829,25 +829,18 @@
         DtoStore(src, dst);
     }
     // set the context for nested classes
-    else if (tc->sym->isNested())
+    else if (tc->sym->isNested() && tc->sym->vthis)
     {
         Logger::println("Resolving nested context");
         LOG_SCOPE;
 
+        // get context
+        LLValue* nest = DtoNestedContext(loc, tc->sym);
+
+        // store into right location
         size_t idx = 2 + tc->sym->vthis->ir.irField->index;
         LLValue* gep = DtoGEPi(mem,0,idx,"tmp");
-
-        // this value might be zero if it was not necessary to generate it ...
-        LLValue* nest = gIR->func()->nestedVar;
-        // ... then revert to the this ptr if there is one
-        if (!nest)
-            nest = gIR->func()->thisVar;
-        // ... or just use zero, since it must be unused.
-        if (!nest)
-            nest = llvm::Constant::getNullValue(gep->getType()->getContainedType(0));
-        else
-            nest = DtoBitCast(nest, gep->getType()->getContainedType(0));
-        DtoStore(nest, gep);
+        DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep);
     }
 
     // call constructor
@@ -860,7 +853,7 @@
     }
 
     // return default constructed class
-    return new DImValue(tc, mem, false);
+    return new DImValue(tc, mem);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -912,7 +905,7 @@
     Logger::println("DtoCastClass(%s, %s)", val->getType()->toChars(), _to->toChars());
     LOG_SCOPE;
 
-    Type* to = DtoDType(_to);
+    Type* to = _to->toBasetype();
     if (to->ty == Tpointer) {
         const LLType* tolltype = DtoType(_to);
         LLValue* rval = DtoBitCast(val->getRVal(), tolltype);
@@ -922,7 +915,7 @@
     assert(to->ty == Tclass);
     TypeClass* tc = (TypeClass*)to;
 
-    Type* from = DtoDType(val->getType());
+    Type* from = val->getType()->toBasetype();
     TypeClass* fc = (TypeClass*)from;
 
     if (tc->sym->isInterfaceDeclaration()) {
@@ -977,7 +970,7 @@
     assert(funcTy->getParamType(0) == obj->getType());
 
     // ClassInfo c
-    TypeClass* to = (TypeClass*)DtoDType(_to);
+    TypeClass* to = (TypeClass*)_to->toBasetype();
     DtoForceDeclareDsymbol(to->sym);
     assert(to->sym->ir.irStruct->classInfo);
     LLValue* cinfo = to->sym->ir.irStruct->classInfo;
@@ -1041,7 +1034,7 @@
     ptr = DtoBitCast(ptr, funcTy->getParamType(0));
 
     // ClassInfo c
-    TypeClass* to = (TypeClass*)DtoDType(_to);
+    TypeClass* to = (TypeClass*)_to->toBasetype();
     DtoForceDeclareDsymbol(to->sym);
     assert(to->sym->ir.irStruct->classInfo);
     LLValue* cinfo = to->sym->ir.irStruct->classInfo;
@@ -1116,7 +1109,7 @@
     for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
         VarDeclaration* vd = i->second.var;
         assert(vd);
-        Type* vdtype = DtoDType(vd->type);
+        Type* vdtype = vd->type->toBasetype();
         //Logger::println("found %u type %s", vd->offset, vdtype->toChars());
         assert(vd->ir.irField->index >= 0);
         if (os == vd->offset && vdtype->toBasetype() == t->toBasetype()) {
@@ -1173,7 +1166,7 @@
 {
     assert(fdecl->isVirtual());//fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual()));
     assert(fdecl->vtblIndex > 0);
-    assert(DtoDType(inst->getType())->ty == Tclass);
+    assert(inst->getType()->toBasetype()->ty == Tclass);
 
     LLValue* vthis = inst->getRVal();
     Logger::cout() << "vthis: " << *vthis << '\n';
--- a/gen/classes.h	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/classes.h	Sun Aug 10 08:37:38 2008 +0200
@@ -26,7 +26,7 @@
 void DtoDeclareClassInfo(ClassDeclaration* cd);
 void DtoDefineClassInfo(ClassDeclaration* cd);
 
-DValue* DtoNewClass(TypeClass* type, NewExp* newexp);
+DValue* DtoNewClass(Loc loc, TypeClass* type, NewExp* newexp);
 void DtoInitClass(TypeClass* tc, LLValue* dst);
 DValue* DtoCallClassCtor(TypeClass* type, CtorDeclaration* ctor, Array* arguments, LLValue* mem);
 void DtoFinalizeClass(LLValue* inst);
--- a/gen/complex.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/complex.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -13,7 +13,7 @@
 
 const llvm::StructType* DtoComplexType(Type* type)
 {
-    Type* t = DtoDType(type);
+    Type* t = type->toBasetype();
 
     const LLType* base = DtoComplexBaseType(t);
 
@@ -26,7 +26,7 @@
 
 const LLType* DtoComplexBaseType(Type* t)
 {
-    TY ty = DtoDType(t)->ty;
+    TY ty = t->toBasetype()->ty;
     const LLType* base;
     if (ty == Tcomplex32) {
         return LLType::FloatTy;
@@ -62,7 +62,7 @@
 
 LLConstant* DtoConstComplex(Type* _ty, long double re, long double im)
 {
-    TY ty = DtoDType(_ty)->ty;
+    TY ty = _ty->toBasetype()->ty;
 
     llvm::ConstantFP* fre;
     llvm::ConstantFP* fim;
@@ -106,7 +106,7 @@
 
 DValue* DtoComplex(Loc& loc, Type* to, DValue* val)
 {
-    Type* t = DtoDType(val->getType());
+    Type* t = val->getType()->toBasetype();
 
     if (val->isComplex() || t->iscomplex()) {
         return DtoCastComplex(loc, val, to);
@@ -448,7 +448,7 @@
 
 DValue* DtoCastComplex(Loc& loc, DValue* val, Type* _to)
 {
-    Type* to = DtoDType(_to);
+    Type* to = _to->toBasetype();
     Type* vty = val->getType();
     if (to->iscomplex()) {
         if (vty->size() == to->size())
--- a/gen/dvalue.h	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/dvalue.h	Sun Aug 10 08:37:38 2008 +0200
@@ -54,8 +54,6 @@
     virtual DComplexValue* isComplex() { return NULL; }
     virtual DLRValue* isLRValue() { return NULL; }
 
-    virtual bool inPlace() { return false; }
-
 protected:
     DValue() {}
     DValue(const DValue&) { }
@@ -67,16 +65,13 @@
 {
     Type* type;
     LLValue* val;
-    bool inplace;
 
-    DImValue(Type* t, LLValue* v, bool in_place = false) { type = t; val = v; inplace = in_place; }
+    DImValue(Type* t, LLValue* v) : type(t), val(v) { }
 
     virtual LLValue* getRVal() { assert(val); return val; }
 
     virtual Type*& getType() { assert(type); return type; }
     virtual DImValue* isIm() { return this; }
-
-    virtual bool inPlace() { return inplace; }
 };
 
 // constant d-value
--- a/gen/enums.h	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/enums.h	Sun Aug 10 08:37:38 2008 +0200
@@ -8,5 +8,6 @@
     LLVMva_start,
     LLVMva_copy,
     LLVMva_end,
-    LLVMva_arg
+    LLVMva_arg,
+    LLVMllvmdc
 };
--- a/gen/functions.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/functions.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -21,7 +21,7 @@
 #include "gen/classes.h"
 #include "gen/dvalue.h"
 
-const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bool ismain)
+const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, const LLType* nesttype, bool ismain)
 {
     assert(type->ty == Tfunction);
     TypeFunction* f = (TypeFunction*)type;
@@ -46,6 +46,7 @@
     Type* rt = f->next;
     bool retinptr = false;
     bool usesthis = false;
+    bool usesnest = false;
 
     // parameter types
     std::vector<const LLType*> paramvec;
@@ -66,7 +67,7 @@
         if (DtoIsReturnedInArg(rt)) {
             rettype = getPtrToType(DtoType(rt));
             actualRettype = LLType::VoidTy;
-            f->llvmRetInPtr = retinptr = true;
+            f->retInPtr = retinptr = true;
         }
         else {
             rettype = DtoType(rt);
@@ -75,7 +76,7 @@
 
         if (unsigned ea = DtoShouldExtend(rt))
         {
-            f->llvmRetAttrs |= ea;
+            f->retAttrs |= ea;
         }
     }
 
@@ -88,6 +89,10 @@
         paramvec.push_back(thistype);
         usesthis = true;
     }
+    else if (nesttype) {
+        paramvec.push_back(nesttype);
+        usesnest = true;
+    }
 
     if (typesafeVararg) {
         ClassDeclaration* ti = Type::typeinfo;
@@ -111,7 +116,7 @@
     for (int i=0; i < n; ++i) {
         Argument* arg = Argument::getNth(f->parameters, i);
         // ensure scalar
-        Type* argT = DtoDType(arg->type);
+        Type* argT = arg->type->toBasetype();
         assert(argT);
 
         bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout));
@@ -166,8 +171,9 @@
     bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs;
     llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
 
-    f->llvmRetInPtr = retinptr;
-    f->llvmUsesThis = usesthis;
+    f->retInPtr = retinptr;
+    f->usesThis = usesthis;
+    f->usesNest = usesnest;
 
     f->ir.type = new llvm::PATypeHolder(functype);
 
@@ -210,7 +216,9 @@
     if (fdecl->type->ir.type != 0)
         return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get());
 
-    const LLType* thisty = NULL;
+    const LLType* thisty = 0;
+    const LLType* nestty = 0;
+
     if (fdecl->needThis()) {
         if (AggregateDeclaration* ad = fdecl->isMember2()) {
             Logger::println("isMember = this is: %s", ad->type->toChars());
@@ -225,10 +233,10 @@
         }
     }
     else if (fdecl->isNested()) {
-        thisty = getPtrToType(LLType::Int8Ty);
+        nestty = getPtrToType(LLType::Int8Ty);
     }
 
-    const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain());
+    const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, nestty, fdecl->isMain());
 
     return functype;
 }
@@ -237,7 +245,7 @@
 
 static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl)
 {
-    TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
+    TypeFunction* f = (TypeFunction*)fdecl->type->toBasetype();
     const llvm::FunctionType* fty = DtoVaFunctionType(fdecl);
     llvm::Function* func = 0;
 
@@ -306,8 +314,9 @@
 static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclaration* fdecl)
 {
     int llidx = 1;
-    if (f->llvmRetInPtr) ++llidx;
-    if (f->llvmUsesThis) ++llidx;
+    if (f->retInPtr) ++llidx;
+    if (f->usesThis) ++llidx;
+    else if (f->usesNest) ++llidx;
     if (f->linkage == LINKd && f->varargs == 1)
         llidx += 2;
 
@@ -318,15 +327,15 @@
     llvm::ParamAttrsWithIndex PAWI;
 
     // set return value attrs if any
-    if (f->llvmRetAttrs)
+    if (f->retAttrs)
     {
         PAWI.Index = 0;
-        PAWI.Attrs = f->llvmRetAttrs;
+        PAWI.Attrs = f->retAttrs;
         attrs.push_back(PAWI);
     }
 
     // set sret param
-    if (f->llvmRetInPtr)
+    if (f->retInPtr)
     {
         PAWI.Index = 1;
         PAWI.Attrs = llvm::ParamAttr::StructRet;
@@ -378,7 +387,7 @@
     }
 
     // get TypeFunction*
-    Type* t = DtoDType(fdecl->type);
+    Type* t = fdecl->type->toBasetype();
     TypeFunction* f = (TypeFunction*)t;
 
     bool declareOnly = false;
@@ -417,8 +426,6 @@
     llvm::Function* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name);
     if (!func)
         func = llvm::Function::Create(functype, DtoLinkage(fdecl), mangled_name, gIR->module);
-    else
-        assert(func->getFunctionType() == functype);
 
     // add func to IRFunc
     fdecl->ir.irFunc->func = func;
@@ -457,15 +464,22 @@
         // name parameters
         llvm::Function::arg_iterator iarg = func->arg_begin();
         int k = 0;
-        if (f->llvmRetInPtr) {
-            iarg->setName("retval");
+        if (f->retInPtr) {
+            iarg->setName(".sretarg");
             fdecl->ir.irFunc->retArg = iarg;
             ++iarg;
         }
-        if (f->llvmUsesThis) {
-            iarg->setName(fdecl->isNested()?".context":"this");
-            fdecl->ir.irFunc->thisVar = iarg;
-            assert(fdecl->ir.irFunc->thisVar);
+        
+        if (f->usesThis) {
+            iarg->setName("this");
+            fdecl->ir.irFunc->thisArg = iarg;
+            assert(fdecl->ir.irFunc->thisArg);
+            ++iarg;
+        }
+        else if (f->usesNest) {
+            iarg->setName(".nest");
+            fdecl->ir.irFunc->nestArg = iarg;
+            assert(fdecl->ir.irFunc->nestArg);
             ++iarg;
         }
 
@@ -520,13 +534,19 @@
     Logger::println("DtoDefineFunc(%s): %s", fd->toPrettyChars(), fd->loc.toChars());
     LOG_SCOPE;
 
+    // warn about naked
+    if (fd->naked)
+    {
+        warning("%s: naked is currently ignored", fd->locToChars());
+    }
+
     // debug info
     if (global.params.symdebug) {
         Module* mo = fd->getModule();
         fd->ir.irFunc->dwarfSubProg = DtoDwarfSubProgram(fd);
     }
 
-    Type* t = DtoDType(fd->type);
+    Type* t = fd->type->toBasetype();
     TypeFunction* f = (TypeFunction*)t;
     assert(f->ir.type);
 
@@ -568,26 +588,32 @@
     // debug info - after all allocas, but before any llvm.dbg.declare etc
     if (global.params.symdebug) DtoDwarfFuncStart(fd);
 
-    // need result variable? (not nested)
-    if (fd->vresult && !fd->vresult->nestedref) {
-        Logger::println("non-nested vresult value");
+    // need result variable?
+    if (fd->vresult) {
+        Logger::println("vresult value");
         fd->vresult->ir.irLocal = new IrLocal(fd->vresult);
-        fd->vresult->ir.irLocal->value = DtoAlloca(DtoType(fd->vresult->type),"function_vresult");
+        fd->vresult->ir.irLocal->value = DtoAlloca(DtoType(fd->vresult->type), "function_vresult");
     }
 
     // give the 'this' argument storage and debug info
-    // only if not referenced by nested functions
-    if (fd->needThis() && !fd->vthis->nestedref)
+    if (f->usesThis)
     {
-        LLValue* thisvar = irfunction->thisVar;
+        LLValue* thisvar = irfunction->thisArg;
         assert(thisvar);
 
-        LLValue* thismem = DtoAlloca(thisvar->getType(), ".newthis");
+        LLValue* thismem = DtoAlloca(thisvar->getType(), ".this");
         DtoStore(thisvar, thismem);
-        irfunction->thisVar = thismem;
+        irfunction->thisArg = thismem;
+        
+        assert(!fd->vthis->ir.irLocal);
+        fd->vthis->ir.irLocal = new IrLocal(fd->vthis);
+        fd->vthis->ir.irLocal->value = thismem;
 
         if (global.params.symdebug)
             DtoDwarfLocalVariable(thismem, fd->vthis);
+        
+        if (fd->vthis->nestedref)
+            fd->nestedVars.insert(fd->vthis);
     }
 
     // give arguments storage
@@ -600,13 +626,16 @@
             Dsymbol* argsym = (Dsymbol*)fd->parameters->data[i];
             VarDeclaration* vd = argsym->isVarDeclaration();
             assert(vd);
+            
+            if (vd->nestedref)
+                fd->nestedVars.insert(vd);
 
             IrLocal* irloc = vd->ir.irLocal;
             assert(irloc);
 
             bool refoutlazy = vd->storage_class & (STCref | STCout | STClazy);
 
-            if (vd->nestedref || refoutlazy)
+            if (refoutlazy)
             {
                 continue;
             }
@@ -625,66 +654,99 @@
         }
     }
 
-    LLValue* parentNested = NULL;
-    if (FuncDeclaration* fd2 = fd->toParent2()->isFuncDeclaration()) {
-        if (!fd->isStatic()) // huh?
-            parentNested = fd2->ir.irFunc->nestedVar;
-    }
-
     // need result variable? (nested)
     if (fd->vresult && fd->vresult->nestedref) {
         Logger::println("nested vresult value: %s", fd->vresult->toChars());
         fd->nestedVars.insert(fd->vresult);
     }
 
-    // construct nested variables struct
-    if (!fd->nestedVars.empty() || parentNested) {
-        std::vector<const LLType*> nestTypes;
-        int j = 0;
-        if (parentNested) {
-            nestTypes.push_back(parentNested->getType());
-            j++;
+    // construct nested variables array
+    if (!fd->nestedVars.empty())
+    {
+        Logger::println("has nested frame");
+        // start with add all enclosing parent frames
+        int nparelems = 0;
+        Dsymbol* par = fd->toParent2();
+        while (par)
+        {
+            if (FuncDeclaration* parfd = par->isFuncDeclaration())
+            {
+                nparelems += parfd->nestedVars.size();
+            }
+            else if (ClassDeclaration* parcd = par->isClassDeclaration())
+            {
+                // nothing needed
+            }
+            else
+            {
+                break;
+            }
+            par = par->toParent2();
         }
-        for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) {
+        int nelems = fd->nestedVars.size() + nparelems;
+        
+        // make array type for nested vars
+        const LLType* nestedVarsTy = LLArrayType::get(getVoidPtrType(), nelems);
+    
+        // alloca it
+        LLValue* nestedVars = DtoAlloca(nestedVarsTy, ".nested_vars");
+        
+        // copy parent frame into beginning
+        if (nparelems)
+        {
+            LLValue* src = irfunction->nestArg;
+            if (!src)
+            {
+                assert(irfunction->thisArg);
+                assert(fd->isMember2());
+                LLValue* thisval = DtoLoad(irfunction->thisArg);
+                ClassDeclaration* cd = fd->isMember2()->isClassDeclaration();
+                assert(cd);
+                assert(cd->vthis);
+                src = DtoLoad(DtoGEPi(thisval, 0,2+cd->vthis->ir.irField->index, ".vthis"));
+            }
+            DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE));
+        }
+        
+        // store in IrFunction
+        irfunction->nestedVar = nestedVars;
+        
+        // go through all nested vars and assign indices
+        int idx = nparelems;
+        for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i)
+        {
             VarDeclaration* vd = *i;
-            Logger::println("referenced nested variable %s", vd->toChars());
             if (!vd->ir.irLocal)
                 vd->ir.irLocal = new IrLocal(vd);
-            vd->ir.irLocal->nestedIndex = j++;
-            if (vd->isParameter()) {
-                if (!vd->ir.irLocal->value) {
-                    assert(vd == fd->vthis);
-                    vd->ir.irLocal->value = fd->ir.irFunc->thisVar;
-                }
-                assert(vd->ir.irLocal->value);
-                nestTypes.push_back(vd->ir.irLocal->value->getType());
+
+            if (vd->isParameter())
+            {
+                Logger::println("nested param: %s", vd->toChars());
+                LLValue* gep = DtoGEPi(nestedVars, 0, idx);
+                LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
+                DtoStore(val, gep);
             }
-            else {
-                nestTypes.push_back(DtoType(vd->type));
+            else
+            {
+                Logger::println("nested var:   %s", vd->toChars());
             }
+
+            vd->ir.irLocal->nestedIndex = idx++;
         }
-        const llvm::StructType* nestSType = llvm::StructType::get(nestTypes);
-        Logger::cout() << "nested var struct has type:" << *nestSType << '\n';
-        fd->ir.irFunc->nestedVar = DtoAlloca(nestSType,"nestedvars");
-        if (parentNested) {
-            assert(fd->ir.irFunc->thisVar);
-            LLValue* ptr = gIR->ir->CreateBitCast(fd->ir.irFunc->thisVar, parentNested->getType(), "tmp");
-            gIR->ir->CreateStore(ptr, DtoGEPi(fd->ir.irFunc->nestedVar, 0,0, "tmp"));
-        }
-        for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) {
-            VarDeclaration* vd = *i;
-            if (vd->isParameter()) {
-                assert(vd->ir.irLocal);
-                gIR->ir->CreateStore(vd->ir.irLocal->value, DtoGEPi(fd->ir.irFunc->nestedVar, 0, vd->ir.irLocal->nestedIndex, "tmp"));
-                vd->ir.irLocal->value = fd->ir.irFunc->nestedVar;
-            }
+        
+        // fixup nested result variable
+        if (fd->vresult && fd->vresult->nestedref) {
+            Logger::println("nested vresult value: %s", fd->vresult->toChars());
+            LLValue* gep = DtoGEPi(nestedVars, 0, fd->vresult->ir.irLocal->nestedIndex);
+            LLValue* val = DtoBitCast(fd->vresult->ir.irLocal->value, getVoidPtrType());
+            DtoStore(val, gep);
         }
     }
 
     // copy _argptr to a memory location
     if (f->linkage == LINKd && f->varargs == 1)
     {
-        LLValue* argptrmem = DtoAlloca(fd->ir.irFunc->_argptr->getType(), "_argptrmem");
+        LLValue* argptrmem = DtoAlloca(fd->ir.irFunc->_argptr->getType(), "_argptr_mem");
         new llvm::StoreInst(fd->ir.irFunc->_argptr, argptrmem, gIR->scopebb());
         fd->ir.irFunc->_argptr = argptrmem;
     }
@@ -784,14 +846,14 @@
     if (fnarg && ((fnarg->storageClass & STCref) || (fnarg->storageClass & STCout)))
     {
         if (arg->isVar() || arg->isLRValue())
-            arg = new DImValue(argexp->type, arg->getLVal(), false);
+            arg = new DImValue(argexp->type, arg->getLVal());
         else
-            arg = new DImValue(argexp->type, arg->getRVal(), false);
+            arg = new DImValue(argexp->type, arg->getRVal());
     }
     // byval arg, but expr has no storage yet
     else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isComplex() || arg->isNull()))
     {
-        LLValue* alloc = DtoAlloca(DtoType(argexp->type), "tmpparam");
+        LLValue* alloc = DtoAlloca(DtoType(argexp->type), ".tmp_arg");
         DVarValue* vv = new DVarValue(argexp->type, alloc, true);
         DtoAssign(argexp->loc, vv, arg);
         arg = vv;
--- a/gen/functions.h	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/functions.h	Sun Aug 10 08:37:38 2008 +0200
@@ -1,7 +1,7 @@
 #ifndef LLVMDC_GEN_FUNCTIONS_H
 #define LLVMDC_GEN_FUNCTIONS_H
 
-const llvm::FunctionType* DtoFunctionType(Type* t, const LLType* thistype, bool ismain = false);
+const llvm::FunctionType* DtoFunctionType(Type* t, const LLType* thistype, const LLType* nesttype, bool ismain = false);
 const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl);
 
 const llvm::FunctionType* DtoBaseFunctionType(FuncDeclaration* fdecl);
--- a/gen/llvmhelpers.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/llvmhelpers.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -349,156 +349,72 @@
 // NESTED VARIABLE HELPERS
 ////////////////////////////////////////////////////////////////////////////////////////*/
 
-/*
+DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
+{
+    Dsymbol* vdparent = vd->toParent2();
+    assert(vdparent);
+    
+    IrFunction* irfunc = gIR->func();
+    
+    // is the nested variable in this scope?
+    if (vdparent == irfunc->decl)
+    {
+        LLValue* val = vd->ir.getIrValue();
+        return new DVarValue(astype, vd, val, true);
+    }
+    
+    // get it from the nested context
+    LLValue* ctx = 0;
+    if (irfunc->decl->isMember2())
+    {
+        ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();
+        LLValue* val = DtoLoad(irfunc->thisArg);
+        ctx = DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis"));
+    }
+    else
+        ctx = irfunc->nestArg;
+    assert(ctx);
+    
+    assert(vd->ir.irLocal);
+    LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType()));
+    val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex);
+    val = DtoLoad(val);
+    assert(vd->ir.irLocal->value);
+    val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars());
+    return new DVarValue(astype, vd, val, true);
+}
 
-got:
+LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
+{
+    Logger::println("DtoNestedContext for %s", sym->toPrettyChars());
+    LOG_SCOPE;
 
-    context pointer of 'this' function
-
-    declaration for target context's function
-
-want:
-
-    context pointer of target function in call chain
-
-*/
-
-static LLValue* dive_into_nested(Dsymbol* from, LLValue* val)
-{
-    from = from->toParent2();
-
-    // parent is a function
-    if (FuncDeclaration* f = from->isFuncDeclaration())
+    IrFunction* irfunc = gIR->func();
+    
+    if (irfunc->nestedVar)
+        return irfunc->nestedVar;
+    else if (irfunc->nestArg)
+        return irfunc->nestArg;
+    else if (irfunc->thisArg)
     {
-        IrFunction* irfunc = f->ir.irFunc;
-        // parent has nested var struct
-        if (irfunc->nestedVar)
-        {
-            return DtoBitCast(val, irfunc->nestedVar->getType());
-        }
-        // parent has this argument
-        else if (irfunc->thisVar)
-        {
-            return DtoBitCast(val, irfunc->thisVar->getType()->getContainedType(0));
-        }
-        // none of the above, means no context is required, dummy.
-        else
-        {
+        ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();
+        assert(cd);
+        if (!cd->vthis)
             return getNullPtr(getVoidPtrType());
-        }
+        LLValue* val = DtoLoad(irfunc->thisArg);
+        return DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis"));
     }
-    // parent is a class
-    else if (ClassDeclaration* c = from->isClassDeclaration())
-    {
-        return DtoBitCast(DtoLoad(val), DtoType(c->type));
-    }
-    // parent is not valid
     else
     {
-        assert(0 && "!(class|function)");
+        if (irfunc->decl->isStatic())
+        {
+            irfunc->decl->error("is static and cannot access nested %s %s", sym->kind(), sym->toChars());
+            fatal();
+        }
+        return getNullPtr(getVoidPtrType());
     }
 }
 
-LLValue* DtoNestedContext(FuncDeclaration* func)
-{
-    Logger::println("listing context frame list for funcdecl '%s'", func->toPrettyChars());
-    LOG_SCOPE;
-
-    int level = 0;
-
-    IrFunction* irfunc = gIR->func();
-    Dsymbol* current = irfunc->decl;
-
-    // this context ?
-    if (current == func)
-    {
-        return irfunc->nestedVar;
-    }
-
-    // otherwise use the context argument
-    LLValue* val = dive_into_nested(current, irfunc->thisVar);
-    current = current->toParent2();
-    assert(val);
-
-    for (;;)
-    {
-        Logger::cout() << "context: " << *val << '\n';
-        Logger::println("(%d) looking in: %s (%s)", level, current->toPrettyChars(), current->kind());
-        if (FuncDeclaration* f = current->isFuncDeclaration())
-        {
-            if (f == func)
-            {
-                Logger::println("-> found <-");
-                Logger::cout() << "-> val: " << *val << '\n';
-                return val;
-            }
-            else
-            {
-                val = DtoLoad(DtoGEPi(val,0,0));
-            }
-        }
-        else if (ClassDeclaration* c = current->isClassDeclaration())
-        {
-            val = DtoLoad(DtoGEPi(val, 0, 2+c->vthis->ir.irField->index));
-            val = dive_into_nested(current, val);
-        }
-        else
-        {
-            Logger::cout() << "val: " << *val << '\n';
-            assert(0 && "!(class|function)");
-        }
-        current = current->toParent2();
-        ++level;
-    }
-
-    assert(0);
-    return val;
-}
-
-DValue* DtoNestedVariable(Type* astype, VarDeclaration* vd)
-{
-    IrFunction* irfunc = gIR->func();
-
-    // var parent (the scope we're looking for)
-    Dsymbol* varParent = vd->toParent2();
-
-    // on level 0
-    if (varParent == irfunc->decl)
-    {
-        LLValue* nest = irfunc->nestedVar;
-        LLValue* v = DtoGEPi(nest, 0, vd->ir.irLocal->nestedIndex, "tmp");
-        // references must be loaded to get the variable address
-        if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)))
-            v = DtoLoad(v);
-        return new DVarValue(astype, vd, v, true);
-    }
-
-    // on level n != 0
-    FuncDeclaration* varFunc = varParent->isFuncDeclaration();
-    assert(varFunc);
-
-    // get context of variable
-    LLValue* ctx = DtoNestedContext(varFunc);
-
-    // if no local var, it's the context itself (class this)
-    if (!vd->ir.irLocal)
-        return new DImValue(astype, ctx);
-
-    // extract variable
-    IrLocal* local = vd->ir.irLocal;
-    assert(local);
-    assert(local->nestedIndex >= 0);
-    LLValue* val = DtoGEPi(ctx, 0, local->nestedIndex);
-
-    // references must be loaded to get the variable address
-    if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)))
-        val = DtoLoad(val);
-
-    Logger::cout() << "value: " << *val << '\n';
-
-    return new DVarValue(astype, vd, val, true);
-}
-
 /****************************************************************************************/
 /*////////////////////////////////////////////////////////////////////////////////////////
 // ASSIGNMENT HELPER (store this in that)
@@ -509,15 +425,15 @@
     Logger::cout() << "DtoAssign(...);\n";
     LOG_SCOPE;
 
-    Type* t = DtoDType(lhs->getType());
-    Type* t2 = DtoDType(rhs->getType());
+    Type* t = lhs->getType()->toBasetype();
+    Type* t2 = rhs->getType()->toBasetype();
 
     if (t->ty == Tstruct) {
         if (!t->equals(t2)) {
             // TODO: fix this, use 'rhs' for something
             DtoAggrZeroInit(lhs->getLVal());
         }
-        else if (!rhs->inPlace()) {
+        else {
             DtoAggrCopy(lhs->getLVal(), rhs->getRVal());
         }
     }
@@ -559,7 +475,7 @@
     else if (t->ty == Tdelegate) {
         if (rhs->isNull())
             DtoAggrZeroInit(lhs->getLVal());
-        else if (!rhs->inPlace()) {
+        else {
             LLValue* l = lhs->getLVal();
             LLValue* r = rhs->getRVal();
             Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n';
@@ -665,8 +581,8 @@
 {
     const LLType* tolltype = DtoType(_to);
 
-    Type* to = DtoDType(_to);
-    Type* from = DtoDType(val->getType());
+    Type* to = _to->toBasetype();
+    Type* from = val->getType()->toBasetype();
     assert(from->isintegral());
 
     size_t fromsz = from->size();
@@ -720,8 +636,8 @@
 {
     const LLType* tolltype = DtoType(to);
 
-    Type* totype = DtoDType(to);
-    Type* fromtype = DtoDType(val->getType());
+    Type* totype = to->toBasetype();
+    Type* fromtype = val->getType()->toBasetype();
     assert(fromtype->ty == Tpointer || fromtype->ty == Tfunction);
 
     LLValue* rval;
@@ -749,8 +665,8 @@
 
     const LLType* tolltype = DtoType(to);
 
-    Type* totype = DtoDType(to);
-    Type* fromtype = DtoDType(val->getType());
+    Type* totype = to->toBasetype();
+    Type* fromtype = val->getType()->toBasetype();
     assert(fromtype->isfloating());
 
     size_t fromsz = fromtype->size();
@@ -814,7 +730,7 @@
 
 DValue* DtoCast(Loc& loc, DValue* val, Type* to)
 {
-    Type* fromtype = DtoDType(val->getType());
+    Type* fromtype = val->getType()->toBasetype();
     Logger::println("Casting from '%s' to '%s'", fromtype->toChars(), to->toChars());
     if (fromtype->isintegral()) {
         return DtoCastInt(loc, val, to);
@@ -879,10 +795,10 @@
     gIR->ir->CreateCondBr(cond, initbb, endinitbb);
     gIR->scope() = IRScope(initbb,endinitbb);
     DValue* ie = DtoInitializer(gvar, init);
-    if (!ie->inPlace()) {
-        DValue* dst = new DVarValue(t, gvar, true);
-        DtoAssign(init->loc, dst, ie);
-    }
+    
+    DVarValue dst(t, gvar, true);
+    DtoAssign(init->loc, &dst, ie);
+    
     gIR->ir->CreateStore(DtoConstBool(true), gflag);
     gIR->ir->CreateBr(endinitbb);
     gIR->scope() = IRScope(endinitbb,oldend);
@@ -1001,7 +917,7 @@
     }
 
     const LLType* _type = DtoType(vd->type);
-    Type* t = DtoDType(vd->type);
+    Type* t = vd->type->toBasetype();
 
     //Logger::cout() << "initializer: " << *_init << '\n';
     if (_type != _init->getType()) {
@@ -1218,9 +1134,23 @@
             if (vd->nestedref) {
                 Logger::println("has nestedref set");
                 assert(vd->ir.irLocal);
-                vd->ir.irLocal->value = gIR->func()->decl->ir.irFunc->nestedVar;
-                assert(vd->ir.irLocal->value);
+                
+                // alloca as usual is no value already
+                if (!vd->ir.irLocal->value)
+                {
+                    vd->ir.irLocal->value = DtoAlloca(DtoType(vd->type), vd->toChars());
+                }
+                
+                // store the address into the nested vars array
+                
                 assert(vd->ir.irLocal->nestedIndex >= 0);
+                LLValue* gep = DtoGEPi(gIR->func()->decl->ir.irFunc->nestedVar, 0, vd->ir.irLocal->nestedIndex);
+                
+                assert(isaPointer(vd->ir.irLocal->value));
+                LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
+                
+                DtoStore(val, gep);
+                
             }
             // normal stack variable, allocate storage on the stack if it has not already been done
             else if(!vd->ir.irLocal) {
@@ -1241,6 +1171,10 @@
                     DtoDwarfLocalVariable(allocainst, vd);
                 }
             }
+            else
+            {
+                assert(vd->ir.irLocal->value);
+            }
 
             Logger::cout() << "llvm value for decl: " << *vd->ir.irLocal->value << '\n';
             DValue* ie = DtoInitializer(vd->ir.irLocal->value, vd->init);
--- a/gen/llvmhelpers.h	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/llvmhelpers.h	Sun Aug 10 08:37:38 2008 +0200
@@ -38,9 +38,18 @@
 // leaves a monitor lock
 void DtoLeaveMonitor(LLValue* v);
 
-// nested variable/class helpers
-LLValue* DtoNestedContext(FuncDeclaration* func);
-DValue* DtoNestedVariable(Type* astype, VarDeclaration* vd);
+// nested variable and context helpers
+
+// gets the context value for a call to a nested function or newing a class, with arbitrary nesting
+LLValue* DtoNestedContext(Loc loc, Dsymbol* sym);
+
+// gets the dvalue of a nested variable with arbitrary nesting
+DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd);
+
+// old nested stuff
+// LLValue* DtoNestedContext(Loc loc, FuncDeclaration* func);
+// LLValue* DtoNestedContext(Loc loc, ClassDeclaration* cd);
+// DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd);
 
 // basic operations
 void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs);
--- a/gen/statements.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/statements.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -57,7 +57,7 @@
     {
         if (p->topfunc()->getReturnType() == LLType::VoidTy) {
             IrFunction* f = p->func();
-            assert(f->type->llvmRetInPtr);
+            assert(f->type->retInPtr);
             assert(f->decl->ir.irFunc->retArg);
 
             if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
@@ -66,8 +66,7 @@
 
             DValue* e = exp->toElem(p);
 
-            if (!e->inPlace())
-                DtoAssign(loc, rvar, e);
+            DtoAssign(loc, rvar, e);
 
             DtoEnclosingHandlers(enclosinghandler, NULL);
 
@@ -647,8 +646,8 @@
 
 static LLValue* call_string_switch_runtime(llvm::GlobalVariable* table, Expression* e)
 {
-    Type* dt = DtoDType(e->type);
-    Type* dtnext = DtoDType(dt->next);
+    Type* dt = e->type->toBasetype();
+    Type* dtnext = dt->next->toBasetype();
     TY ty = dtnext->ty;
     const char* fname;
     if (ty == Tchar) {
@@ -934,7 +933,7 @@
 
     // what to iterate
     DValue* aggrval = aggr->toElem(p);
-    Type* aggrtype = DtoDType(aggr->type);
+    Type* aggrtype = aggr->type->toBasetype();
 
     // get length and pointer
     LLValue* niters = DtoArrayLen(aggrval);
--- a/gen/structs.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/structs.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -67,7 +67,7 @@
 
     for (unsigned i=0; i<sd->fields.dim; ++i) {
         VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i];
-        Type* vdtype = DtoDType(vd->type);
+        Type* vdtype = vd->type->toBasetype();
         //Logger::println("found %u type %s", vd->offset, vdtype->toChars());
         assert(vd->ir.irField->index >= 0);
         if (os == vd->offset && vdtype == t) {
@@ -125,7 +125,7 @@
     if (sd->prot() == PROTprivate && sd->getModule() != gIR->dmodule)
         Logger::println("using a private struct from outside its module");
 
-    TypeStruct* ts = (TypeStruct*)DtoDType(sd->type);
+    TypeStruct* ts = (TypeStruct*)sd->type->toBasetype();
 
     bool ispacked = (ts->alignsize() == 1);
 
@@ -279,7 +279,7 @@
     Logger::println("DtoDeclareStruct(%s): %s", sd->toChars(), sd->loc.toChars());
     LOG_SCOPE;
 
-    TypeStruct* ts = (TypeStruct*)DtoDType(sd->type);
+    TypeStruct* ts = (TypeStruct*)sd->type->toBasetype();
 
     std::string initname("_D");
     initname.append(sd->mangle());
--- a/gen/tocall.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/tocall.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -71,6 +71,7 @@
     else if (type->ty == Tdelegate)
     {
         LLValue* dg = fn->getRVal();
+        Logger::cout() << "delegate: " << *dg << '\n';
         LLValue* funcptr = DtoGEPi(dg, 0, 1);
         return DtoLoad(funcptr);
     }
@@ -200,10 +201,10 @@
     TypeFunction* tf = DtoTypeFunction(fnval);
 
     // misc
-    bool retinptr = tf->llvmRetInPtr;
-    bool usesthis = tf->llvmUsesThis;
+    bool retinptr = tf->retInPtr;
+    bool thiscall = tf->usesThis;
     bool delegatecall = (calleeType->toBasetype()->ty == Tdelegate);
-    bool nestedcall = (dfnval && dfnval->func && dfnval->func->isNested());
+    bool nestedcall = tf->usesNest;
     bool dvarargs = (tf->linkage == LINKd && tf->varargs == 1);
 
     unsigned callconv = DtoCallingConv(tf->linkage);
@@ -221,8 +222,8 @@
     llvm::PAListPtr palist;
 
     // return attrs
-    if (tf->llvmRetAttrs)
-        palist = palist.addAttr(0, tf->llvmRetAttrs);
+    if (tf->retAttrs)
+        palist = palist.addAttr(0, tf->retAttrs);
 
     // handle implicit arguments
     std::vector<LLValue*> args;
@@ -237,11 +238,12 @@
     }
 
     // then comes a context argument...
-    if(usesthis || delegatecall || nestedcall)
+    if(thiscall || delegatecall || nestedcall)
     {
         // ... which can be a 'this' argument
-        if (dfnval && dfnval->vthis)
+        if (thiscall)
         {
+            assert(dfnval && dfnval->vthis);
             LLValue* thisarg = DtoBitCast(dfnval->vthis, argiter->get());
             ++argiter;
             args.push_back(thisarg);
@@ -257,11 +259,8 @@
         // ... or a nested function context arg
         else if (nestedcall)
         {
-            LLValue* contextptr = DtoNestedContext(dfnval->func->toParent2()->isFuncDeclaration());
-            if (!contextptr)
-                contextptr = getNullPtr(getVoidPtrType());
-            else
-                contextptr = DtoBitCast(contextptr, getVoidPtrType());
+            LLValue* contextptr = DtoNestedContext(loc, dfnval->func);
+            contextptr = DtoBitCast(contextptr, getVoidPtrType());
             ++argiter;
             args.push_back(contextptr);
         }
@@ -354,7 +353,7 @@
         call->setCallingConv(callconv);
     call->setParamAttrs(palist);
 
-    return new DImValue(resulttype, retllval, false);
+    return new DImValue(resulttype, retllval);
 }
 
 
--- a/gen/todebug.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/todebug.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -239,7 +239,7 @@
 static LLGlobalVariable* dwarfDerivedType(Type* type, llvm::GlobalVariable* compileUnit)
 {
     const LLType* T = DtoType(type);
-    Type* t = DtoDType(type);
+    Type* t = type->toBasetype();
 
     // defaults
     LLConstant* name = getNullPtr(getVoidPtrType());
@@ -300,7 +300,7 @@
 static LLGlobalVariable* dwarfMemberType(unsigned linnum, Type* type, LLGlobalVariable* compileUnit, LLGlobalVariable* definedCU, const char* c_name, unsigned offset)
 {
     const LLType* T = DtoType(type);
-    Type* t = DtoDType(type);
+    Type* t = type->toBasetype();
 
     // defaults
     LLConstant* name;
@@ -356,7 +356,7 @@
 static LLGlobalVariable* dwarfCompositeType(Type* type, llvm::GlobalVariable* compileUnit)
 {
     const LLType* T = DtoType(type);
-    Type* t = DtoDType(type);
+    Type* t = type->toBasetype();
 
     // defaults
     LLConstant* name = getNullPtr(getVoidPtrType());
--- a/gen/toir.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/toir.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -106,7 +106,7 @@
         // nested variable
         else if (vd->nestedref) {
             Logger::println("nested variable");
-            return DtoNestedVariable(type, vd);
+            return DtoNestedVariable(loc, type, vd);
         }
         // function parameter
         else if (vd->isParameter()) {
@@ -114,7 +114,7 @@
             FuncDeclaration* fd = vd->toParent2()->isFuncDeclaration();
             if (fd && fd != p->func()->decl) {
                 Logger::println("nested parameter");
-                return DtoNestedVariable(type, vd);
+                return DtoNestedVariable(loc, type, vd);
             }
             else if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa<llvm::AllocaInst>(vd->ir.getIrValue())) {
                 return new DVarValue(type, vd, vd->ir.getIrValue(), true);
@@ -151,7 +151,7 @@
     else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
     {
         // this seems to be the static initialiser for structs
-        Type* sdecltype = DtoDType(sdecl->type);
+        Type* sdecltype = sdecl->type->toBasetype();
         Logger::print("Sym: type=%s\n", sdecltype->toChars());
         assert(sdecltype->ty == Tstruct);
         TypeStruct* ts = (TypeStruct*)sdecltype;
@@ -177,7 +177,7 @@
     if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
     {
         // this seems to be the static initialiser for structs
-        Type* sdecltype = DtoDType(sdecl->type);
+        Type* sdecltype = sdecl->type->toBasetype();
         Logger::print("Sym: type=%s\n", sdecltype->toChars());
         assert(sdecltype->ty == Tstruct);
         TypeStruct* ts = (TypeStruct*)sdecltype;
@@ -242,7 +242,7 @@
 {
     Logger::print("RealExp::toConstElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
-    Type* t = DtoDType(type);
+    Type* t = type->toBasetype();
     return DtoConstFP(t, value);
 }
 
@@ -283,7 +283,7 @@
     LLConstant* c = toConstElem(p);
 
     if (c->isNullValue()) {
-        Type* t = DtoDType(type);
+        Type* t = type->toBasetype();
         if (t->ty == Tcomplex32)
             c = DtoConstFP(Type::tfloat32, 0);
         else if (t->ty == Tcomplex64)
@@ -314,8 +314,8 @@
     Logger::print("StringExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    Type* dtype = DtoDType(type);
-    Type* cty = DtoDType(dtype->next);
+    Type* dtype = type->toBasetype();
+    Type* cty = dtype->next->toBasetype();
 
     const LLType* ct = DtoTypeNotVoid(cty);
     //printf("ct = %s\n", type->next->toChars());
@@ -382,8 +382,8 @@
     Logger::print("StringExp::toConstElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    Type* t = DtoDType(type);
-    Type* cty = DtoDType(t->next);
+    Type* t = type->toBasetype();
+    Type* cty = t->next->toBasetype();
 
     bool nullterm = (t->ty != Tsarray);
     size_t endlen = nullterm ? len+1 : len;
@@ -472,7 +472,19 @@
     if (l->isSlice() || l->isComplex())
         return l;
 
+#if 0
+    if (type->toBasetype()->ty == Tstruct && e2->type->isintegral())
+    { 
+        // handle struct = 0; 
+        return l; 
+    } 
+    else 
+    { 
+        return r;
+    }
+#else
     return r;
+#endif
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -485,10 +497,10 @@
     DValue* l = e1->toElem(p);
     DValue* r = e2->toElem(p);
 
-    Type* t = DtoDType(type);
-    Type* e1type = DtoDType(e1->type);
-    Type* e1next = e1type->next ? DtoDType(e1type->next) : NULL;
-    Type* e2type = DtoDType(e2->type);
+    Type* t = type->toBasetype();
+    Type* e1type = e1->type->toBasetype();
+    Type* e1next = e1type->next ? e1type->next->toBasetype() : NULL;
+    Type* e2type = e2->type->toBasetype();
 
     if (e1type != e2type) {
         if (llvmFieldIndex) {
@@ -537,10 +549,10 @@
     DValue* l = e1->toElem(p);
     DValue* r = e2->toElem(p);
 
-    Type* t = DtoDType(type);
+    Type* t = type->toBasetype();
 
     DValue* res;
-    if (DtoDType(e1->type)->ty == Tpointer) {
+    if (e1->type->toBasetype()->ty == Tpointer) {
         LLValue* gep = llvm::GetElementPtrInst::Create(l->getRVal(),r->getRVal(),"tmp",p->scopebb());
         res = new DImValue(type, gep);
     }
@@ -565,9 +577,9 @@
     DValue* l = e1->toElem(p);
     DValue* r = e2->toElem(p);
 
-    Type* t = DtoDType(type);
-    Type* t1 = DtoDType(e1->type);
-    Type* t2 = DtoDType(e2->type);
+    Type* t = type->toBasetype();
+    Type* t1 = e1->type->toBasetype();
+    Type* t2 = e2->type->toBasetype();
 
     if (t1->ty == Tpointer && t2->ty == Tpointer) {
         LLValue* lv = l->getRVal();
@@ -603,10 +615,10 @@
     DValue* l = e1->toElem(p);
     DValue* r = e2->toElem(p);
 
-    Type* t = DtoDType(type);
+    Type* t = type->toBasetype();
 
     DValue* res;
-    if (DtoDType(e1->type)->ty == Tpointer) {
+    if (e1->type->toBasetype()->ty == Tpointer) {
         Logger::println("ptr");
         LLValue* tmp = r->getRVal();
         LLValue* zero = llvm::ConstantInt::get(tmp->getType(),0,false);
@@ -770,7 +782,7 @@
             DValue* expv = exp->toElem(p);
             if (expv->getType()->toBasetype()->ty != Tint32)
                 expv = DtoCast(loc, expv, Type::tint32);
-            return new DImValue(type, DtoAlloca(LLType::Int8Ty, expv->getRVal(), ".alloca"));
+            return new DImValue(type, p->ir->CreateAlloca(LLType::Int8Ty, expv->getRVal(), ".alloca"));
         }
     }
 
@@ -844,6 +856,12 @@
     assert(e1->op == TOKvar);
     VarExp* vexp = (VarExp*)e1;
 
+    if (vexp->var->needThis())
+    {
+        error("need 'this' to access %s", vexp->var->toChars());
+        fatal();
+    }
+
     // global variable
     if (VarDeclaration* vd = vexp->var->isVarDeclaration())
     {
@@ -892,8 +910,8 @@
 
     DValue* l = e1->toElem(p);
 
-    Type* t = DtoDType(type);
-    Type* e1type = DtoDType(e1->type);
+    Type* t = type->toBasetype();
+    Type* e1type = e1->type->toBasetype();
 
     //Logger::println("e1type=%s", e1type->toChars());
     //Logger::cout() << *DtoType(e1type) << '\n';
@@ -910,6 +928,16 @@
             DStructIndexVector vdoffsets;
             arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
         }
+        // happens for tuples
+        else if (e1type->ty == Tstruct) {
+            TypeStruct* ts = (TypeStruct*)e1type;
+            Logger::println("Struct member offset:%d", vd->offset);
+
+            LLValue* src = l->getRVal();
+
+            DStructIndexVector vdoffsets;
+            arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
+        }
         else if (e1type->ty == Tclass) {
             TypeClass* tc = (TypeClass*)e1type;
             Logger::println("Class member offset: %d", vd->offset);
@@ -953,7 +981,7 @@
 
             LLValue* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false);
             LLValue* vtblidx = llvm::ConstantInt::get(LLType::Int32Ty, (size_t)fdecl->vtblIndex, false);
-            //Logger::cout() << "vthis: " << *vthis << '\n';
+            Logger::cout() << "vthis: " << *vthis << '\n';
             funcval = DtoGEP(vthis, zero, zero);
             funcval = DtoLoad(funcval);
             funcval = DtoGEP(funcval, zero, vtblidx, toChars());
@@ -991,7 +1019,7 @@
     // FIXME: check for TOKthis in AssertExp instead
     if (!var)
     {
-        LLValue* v = p->func()->thisVar;
+        LLValue* v = p->func()->thisArg;
         assert(v);
         return new DVarValue(type, v, true);
     }
@@ -1000,11 +1028,11 @@
         LLValue* v;
         if (vd->toParent2() != p->func()->decl) {
             Logger::println("nested this exp");
-            return DtoNestedVariable(type, vd);
+            return DtoNestedVariable(loc, type, vd);
         }
         else {
             Logger::println("normal this exp");
-            v = p->func()->decl->ir.irFunc->thisVar;
+            v = p->func()->thisArg;
         }
         return new DVarValue(type, vd, v, true);
     }
@@ -1023,7 +1051,7 @@
 
     DValue* l = e1->toElem(p);
 
-    Type* e1type = DtoDType(e1->type);
+    Type* e1type = e1->type->toBasetype();
 
     p->arrays.push_back(l); // if $ is used it must be an array so this is fine.
     DValue* r = e2->toElem(p);
@@ -1141,8 +1169,8 @@
     DValue* l = e1->toElem(p);
     DValue* r = e2->toElem(p);
 
-    Type* t = DtoDType(e1->type);
-    Type* e2t = DtoDType(e2->type);
+    Type* t = e1->type->toBasetype();
+    Type* e2t = e2->type->toBasetype();
     assert(DtoType(t) == DtoType(e2t));
 
     LLValue* eval = 0;
@@ -1254,8 +1282,8 @@
     DValue* l = e1->toElem(p);
     DValue* r = e2->toElem(p);
 
-    Type* t = DtoDType(e1->type);
-    Type* e2t = DtoDType(e2->type);
+    Type* t = e1->type->toBasetype();
+    Type* e2t = e2->type->toBasetype();
     //assert(t == e2t);
 
     LLValue* eval = 0;
@@ -1341,8 +1369,8 @@
     LLValue* val = l->getRVal();
     LLValue* post = 0;
 
-    Type* e1type = DtoDType(e1->type);
-    Type* e2type = DtoDType(e2->type);
+    Type* e1type = e1->type->toBasetype();
+    Type* e2type = e2->type->toBasetype();
 
     if (e1type->isintegral())
     {
@@ -1379,7 +1407,7 @@
 
     DtoStore(post,l->getLVal());
 
-    return new DImValue(type,val,true);
+    return new DImValue(type,val);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -1390,12 +1418,12 @@
     LOG_SCOPE;
 
     assert(newtype);
-    Type* ntype = DtoDType(newtype);
+    Type* ntype = newtype->toBasetype();
 
     // new class
     if (ntype->ty == Tclass) {
         Logger::println("new class");
-        return DtoNewClass((TypeClass*)ntype, this);
+        return DtoNewClass(loc, (TypeClass*)ntype, this);
     }
     // new dynamic array
     else if (ntype->ty == Tarray)
@@ -1439,7 +1467,7 @@
             assert(ts->sym);
             DtoAggrCopy(mem,ts->sym->ir.irStruct->init);
         }
-        return new DImValue(type, mem, false);
+        return new DImValue(type, mem);
     }
     // new basic type
     else
@@ -1454,7 +1482,7 @@
         DtoAssign(loc, &tmpvar, iv);
 
         // return as pointer-to
-        return new DImValue(type, mem, false);
+        return new DImValue(type, mem);
     }
 
     assert(0);
@@ -1468,7 +1496,7 @@
     LOG_SCOPE;
 
     DValue* dval = e1->toElem(p);
-    Type* et = DtoDType(e1->type);
+    Type* et = e1->type->toBasetype();
 
     // simple pointer
     if (et->ty == Tpointer)
@@ -1763,12 +1791,13 @@
     DValue* u = e1->toElem(p);
     LLValue* uval;
     if (DFuncValue* f = u->isFunc()) {
-        assert(f->func);
-        LLValue* contextptr = DtoNestedContext(f->func->toParent2()->isFuncDeclaration());
-        if (!contextptr)
-            uval = LLConstant::getNullValue(getVoidPtrType());
+        assert(f->func);        
+        LLValue* contextptr;
+        if (p->func()->decl == f->func)
+            contextptr = p->func()->thisArg;
         else
-            uval = DtoBitCast(contextptr, getVoidPtrType());
+            contextptr = DtoNestedContext(loc, f->func);
+        uval = DtoBitCast(contextptr, getVoidPtrType());
     }
     else {
         DValue* src = u;
@@ -1892,7 +1921,7 @@
     Logger::print("CondExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    Type* dtype = DtoDType(type);
+    Type* dtype = type->toBasetype();
     const LLType* resty = DtoType(dtype);
 
     // allocate a temporary for the final result. failed to come up with a better way :/
@@ -1953,7 +1982,7 @@
     }
 
     LLValue* val = l->getRVal();
-    Type* t = DtoDType(type);
+    Type* t = type->toBasetype();
 
     LLValue* zero = 0;
     if (t->isintegral())
@@ -1975,9 +2004,9 @@
     Logger::print("CatExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    Type* t = DtoDType(type);
-
-    bool arrNarr = DtoDType(e1->type) == DtoDType(e2->type);
+    Type* t = type->toBasetype();
+
+    bool arrNarr = e1->type->toBasetype() == e2->type->toBasetype();
 
     // array ~ array
     if (arrNarr)
@@ -2001,9 +2030,9 @@
 
     DValue* l = e1->toElem(p);
 
-    Type* e1type = DtoDType(e1->type);
-    Type* elemtype = DtoDType(e1type->next);
-    Type* e2type = DtoDType(e2->type);
+    Type* e1type = e1->type->toBasetype();
+    Type* elemtype = e1type->next->toBasetype();
+    Type* e2type = e2->type->toBasetype();
 
     if (e2type == elemtype) {
         DSliceValue* slice = DtoCatAssignElement(l,e2);
@@ -2037,17 +2066,17 @@
     LLValue* lval = DtoAlloca(dgty,"dgstorage");
 
     LLValue* context = DtoGEPi(lval,0,0);
-    const LLPointerType* pty = isaPointer(context->getType()->getContainedType(0));
-    LLValue* llvmNested = p->func()->decl->ir.irFunc->nestedVar;
-    if (llvmNested == NULL) {
-        LLValue* nullcontext = llvm::ConstantPointerNull::get(pty);
-        DtoStore(nullcontext, context);
-    }
-    else {
-        LLValue* nestedcontext = DtoBitCast(llvmNested, pty);
-        DtoStore(nestedcontext, context);
-    }
-
+    LLValue* cval;
+    IrFunction* irfn = p->func();
+    if (irfn->nestedVar)
+        cval = irfn->nestedVar;
+    else if (irfn->nestArg)
+        cval = irfn->nestArg;
+    else
+        cval = getNullPtr(getVoidPtrType());
+    cval = DtoBitCast(cval, context->getType()->getContainedType(0));
+    DtoStore(cval, context);
+    
     LLValue* fptr = DtoGEPi(lval,0,1,"tmp",p->scopebb());
 
     assert(fd->ir.irFunc->func);
@@ -2072,8 +2101,6 @@
     bool dyn = (arrayType->ty == Tarray);
     // length
     size_t len = elements->dim;
-    // store into slice?
-    bool sliceInPlace = false;
 
     // llvm target type
     const LLType* llType = DtoType(arrayType);
@@ -2096,15 +2123,13 @@
         // emulate assignment
         DVarValue* vv = new DVarValue(expr->type, elemAddr, true);
         DValue* e = expr->toElem(p);
-        DImValue* im = e->isIm();
-        if (!im || !im->inPlace()) {
-            DtoAssign(loc, vv, e);
-        }
+        DtoAssign(loc, vv, e);
     }
 
     // return storage directly ?
-    if (!dyn || (dyn && sliceInPlace))
-        return new DImValue(type, dstMem, false);
+    if (!dyn)
+        return new DImValue(type, dstMem);
+
     // wrap in a slice
     return new DSliceValue(type, DtoConstSize_t(len), DtoGEPi(dstMem,0,0,"tmp"));
 }
@@ -2188,9 +2213,7 @@
         DValue* darrptr = new DVarValue(vx->type, arrptr, true);
 
         DValue* ve = vx->toElem(p);
-
-        if (!ve->inPlace())
-            DtoAssign(loc, darrptr, ve);
+        DtoAssign(loc, darrptr, ve);
 
         j++;
     }
@@ -2214,7 +2237,7 @@
         vals[i] = vx->toConstElem(p);
     }
 
-    assert(DtoDType(type)->ty == Tstruct);
+    assert(type->toBasetype()->ty == Tstruct);
     const LLType* t = DtoType(type);
     const LLStructType* st = isaStruct(t);
     return llvm::ConstantStruct::get(st,vals);
@@ -2257,7 +2280,7 @@
     assert(values);
     assert(keys->dim == values->dim);
 
-    Type* aatype = DtoDType(type);
+    Type* aatype = type->toBasetype();
     Type* vtype = aatype->next;
     const LLType* aalltype = DtoType(type);
 
--- a/gen/tollvm.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/tollvm.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -23,14 +23,14 @@
 
 bool DtoIsPassedByRef(Type* type)
 {
-    Type* typ = DtoDType(type);
+    Type* typ = type->toBasetype();
     TY t = typ->ty;
     return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
 }
 
 bool DtoIsReturnedInArg(Type* type)
 {
-    Type* typ = DtoDType(type);
+    Type* typ = type->toBasetype();
     TY t = typ->ty;
     return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
 }
@@ -54,16 +54,6 @@
     return llvm::ParamAttr::None;
 }
 
-Type* DtoDType(Type* t)
-{
-    if (t->ty == Ttypedef) {
-        Type* bt = t->toBasetype();
-        assert(bt);
-        return DtoDType(bt);
-    }
-    return t;
-}
-
 const LLType* DtoType(Type* t)
 {
     assert(t);
@@ -143,7 +133,7 @@
     case Tfunction:
     {
         if (!t->ir.type || *t->ir.type == NULL) {
-            return DtoFunctionType(t,NULL);
+            return DtoFunctionType(t,NULL,NULL);
         }
         else {
             return t->ir.type->get();
@@ -205,7 +195,7 @@
 const LLStructType* DtoDelegateType(Type* t)
 {
     const LLType* i8ptr = getVoidPtrType();
-    const LLType* func = DtoFunctionType(t->next, i8ptr);
+    const LLType* func = DtoFunctionType(t->next, NULL, i8ptr);
     const LLType* funcptr = getPtrToType(func);
     return LLStructType::get(i8ptr, funcptr, 0);
 }
@@ -666,8 +656,9 @@
 
 size_t getABITypeSize(const LLType* t)
 {
-    Logger::cout() << "getting abi type of: " << *t << '\n';
-    return gTargetData->getABITypeSize(t);
+    size_t sz = gTargetData->getABITypeSize(t);
+    Logger::cout() << "abi type size of: " << *t << " == " << sz << '\n';
+    return sz;
 }
 
 unsigned char getABITypeAlign(const LLType* t)
--- a/gen/tollvm.h	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/tollvm.h	Sun Aug 10 08:37:38 2008 +0200
@@ -23,10 +23,6 @@
 
 unsigned DtoShouldExtend(Type* type);
 
-// resolve typedefs to their real type.
-// TODO should probably be removed in favor of DMD's Type::toBasetype
-Type* DtoDType(Type* t);
-
 // delegate helpers
 const LLStructType* DtoDelegateType(Type* t);
 LLValue* DtoDelegateEquals(TOK op, LLValue* lhs, LLValue* rhs);
@@ -92,6 +88,7 @@
 size_t getTypeBitSize(const LLType* t);
 size_t getTypeStoreSize(const LLType* t);
 size_t getABITypeSize(const LLType* t);
+
 // type alignments
 unsigned char getABITypeAlign(const LLType* t);
 unsigned char getPrefTypeAlign(const LLType* t);
--- a/gen/toobj.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/toobj.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -55,9 +55,17 @@
 
 void Module::genobjfile(int multiobj)
 {
+    bool logenabled = Logger::enabled();
+    if (llvmForceLogging && !logenabled)
+    {
+        Logger::enable();
+    }
+
     Logger::cout() << "Generating module: " << (md ? md->toChars() : toChars()) << '\n';
     LOG_SCOPE;
 
+    //printf("codegen: %s\n", srcfile->toChars());
+
     // start by deleting the old object file
     deleteObjFile();
 
@@ -161,10 +169,10 @@
 
     if (global.params.fqnPaths)
     {
-        bcpath = LLPath(md->toChars());
+        bcpath = LLPath(mname);
         bcpath.appendSuffix("bc");
 
-        llpath = LLPath(md->toChars());
+        llpath = LLPath(mname);
         llpath.appendSuffix("ll");
     }
     else
@@ -190,6 +198,11 @@
     delete ir.module;
     gTargetData = 0;
     gIR = NULL;
+    
+    if (llvmForceLogging && !logenabled)
+    {
+        Logger::disable();
+    }
 }
 
 /* ================================================================== */
--- a/ir/irfunction.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/ir/irfunction.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -13,7 +13,7 @@
 {
     decl = fd;
 
-    Type* t = DtoDType(fd->type);
+    Type* t = fd->type->toBasetype();
     assert(t->ty == Tfunction);
     type = (TypeFunction*)t;
     func = NULL;
@@ -23,10 +23,14 @@
     defined = false;
 
     retArg = NULL;
-    thisVar = NULL;
+    thisArg = NULL;
+    nestArg = NULL;
+
     nestedVar = NULL;
+    
     _arguments = NULL;
     _argptr = NULL;
+    
     dwarfSubProg = NULL;
 
     srcfileArg = NULL;
--- a/ir/irfunction.h	Sat Aug 09 09:03:52 2008 +0200
+++ b/ir/irfunction.h	Sun Aug 10 08:37:38 2008 +0200
@@ -18,11 +18,16 @@
 
     bool queued;
     bool defined;
-    llvm::Value* retArg;
-    llvm::Value* thisVar;
-    llvm::Value* nestedVar;
+    
+    llvm::Value* retArg; // return in ptr arg
+    llvm::Value* thisArg; // class/struct 'this' arg
+    llvm::Value* nestArg; // nested function 'this' arg
+    
+    llvm::Value* nestedVar; // nested var alloca
+    
     llvm::Value* _arguments;
     llvm::Value* _argptr;
+    
     llvm::Constant* dwarfSubProg;
 
     llvm::AllocaInst* srcfileArg;
--- a/runtime/internal/aApplyR.d	Sat Aug 09 09:03:52 2008 +0200
+++ b/runtime/internal/aApplyR.d	Sun Aug 10 08:37:38 2008 +0200
@@ -79,7 +79,7 @@
 {
     debug(apply) printf("_aApplyRcd1.unittest\n");
 
-    auto s = "hello"c;
+    char[] s = "hello"c;
     int i;
 
     foreach_reverse(dchar d; s)
@@ -143,7 +143,7 @@
 {
     debug(apply) printf("_aApplyRwd1.unittest\n");
 
-    auto s = "hello"w;
+    wchar[] s = "hello"w;
     int i;
 
     foreach_reverse(dchar d; s)
@@ -229,7 +229,7 @@
 {
     debug(apply) printf("_aApplyRcw1.unittest\n");
 
-    auto s = "hello"c;
+    char[] s = "hello"c;
     int i;
 
     foreach_reverse(wchar d; s)
@@ -310,7 +310,7 @@
 {
     debug(apply) printf("_aApplyRwc1.unittest\n");
 
-    auto s = "hello"w;
+    wchar[] s = "hello"w;
     int i;
 
     foreach_reverse(char d; s)
@@ -389,7 +389,7 @@
 {
     debug(apply) printf("_aApplyRdc1.unittest\n");
 
-    auto s = "hello"d;
+    dchar[] s = "hello"d;
     int i;
 
     foreach_reverse(char d; s)
@@ -461,7 +461,7 @@
 {
     debug(apply) printf("_aApplyRdw1.unittest\n");
 
-    auto s = "hello"d;
+    dchar[] s = "hello"d;
     int i;
 
     foreach_reverse(wchar d; s)
@@ -543,7 +543,7 @@
 {
     debug(apply) printf("_aApplyRcd2.unittest\n");
 
-    auto s = "hello"c;
+    char[] s = "hello"c;
     int i;
 
     foreach_reverse(k, dchar d; s)
@@ -608,7 +608,7 @@
 {
     debug(apply) printf("_aApplyRwd2.unittest\n");
 
-    auto s = "hello"w;
+    wchar[] s = "hello"w;
     int i;
 
     foreach_reverse(k, dchar d; s)
@@ -696,7 +696,7 @@
 {
     debug(apply) printf("_aApplyRcw2.unittest\n");
 
-    auto s = "hello"c;
+    char[] s = "hello"c;
     int i;
 
     foreach_reverse(k, wchar d; s)
@@ -779,7 +779,7 @@
 {
     debug(apply) printf("_aApplyRwc2.unittest\n");
 
-    auto s = "hello"w;
+    wchar[] s = "hello"w;
     int i;
 
     foreach_reverse(k, char d; s)
@@ -859,7 +859,7 @@
 {
     debug(apply) printf("_aApplyRdc2.unittest\n");
 
-    auto s = "hello"d;
+    dchar[] s = "hello"d;
     int i;
 
     foreach_reverse(k, char d; s)
@@ -933,7 +933,7 @@
 {
     debug(apply) printf("_aApplyRdw2.unittest\n");
 
-    auto s = "hello"d;
+    dchar[] s = "hello"d;
     int i;
 
     foreach_reverse(k, wchar d; s)
--- a/runtime/internal/aaA.d	Sat Aug 09 09:03:52 2008 +0200
+++ b/runtime/internal/aaA.d	Sun Aug 10 08:37:38 2008 +0200
@@ -101,7 +101,6 @@
 
 size_t aligntsize(size_t tsize)
 {
-    // Is pointer alignment on the x64 4 bytes or 8?
     return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
 }
 
--- a/runtime/internal/adi.d	Sat Aug 09 09:03:52 2008 +0200
+++ b/runtime/internal/adi.d	Sun Aug 10 08:37:38 2008 +0200
@@ -67,7 +67,7 @@
  * reversed.
  */
 
-extern (C) Array _adReverseChar(char[] a)
+extern (C) char[] _adReverseChar(char[] a)
 {
     if (a.length > 1)
     {
@@ -127,14 +127,14 @@
             hi = hi - 1 + (stridehi - stridelo);
         }
     }
-    return Array(a.length, a.ptr);
+    return a;
 }
 
 unittest
 {
-    auto a = "abcd"c;
+    char[] a = "abcd"c;
 
-    auto r = a.dup.reverse;
+    char[] r = a.dup.reverse;
     //writefln(r);
     assert(r == "dcba");
 
@@ -162,7 +162,7 @@
  * reversed.
  */
 
-extern (C) Array _adReverseWchar(wchar[] a)
+extern (C) wchar[] _adReverseWchar(wchar[] a)
 {
     if (a.length > 1)
     {
@@ -220,13 +220,13 @@
             hi = hi - 1 + (stridehi - stridelo);
         }
     }
-    return Array(a.length, a.ptr);
+    return a;
 }
 
 unittest
 {
-    wstring a = "abcd";
-    wstring r;
+    wchar[] a = "abcd";
+    wchar[] r;
 
     r = a.dup.reverse;
     assert(r == "dcba");
@@ -331,7 +331,7 @@
  * Sort array of chars.
  */
 
-extern (C) Array _adSortChar(char[] a)
+extern (C) char[] _adSortChar(char[] a)
 {
     if (a.length > 1)
     {
@@ -346,14 +346,14 @@
         }
         delete da;
     }
-    return Array(a.length, a.ptr);
+    return a;
 }
 
 /**********************************************
  * Sort array of wchars.
  */
 
-extern (C) Array _adSortWchar(wchar[] a)
+extern (C) wchar[] _adSortWchar(wchar[] a)
 {
     if (a.length > 1)
     {
@@ -368,7 +368,7 @@
         }
         delete da;
     }
-    return Array(a.length, a.ptr);
+    return a;
 }
 
 /***************************************
@@ -392,7 +392,7 @@
 {
     debug(adi) printf("array.Eq unittest\n");
 
-    auto a = "hello"c;
+    char[] a = "hello"c;
 
     assert(a != "hel");
     assert(a != "helloo");
@@ -425,7 +425,7 @@
 {
     debug(adi) printf("array.Cmp unittest\n");
 
-    auto a = "hello"c;
+    char[] a = "hello"c;
 
     assert(a >  "hel");
     assert(a >= "hel");
@@ -575,7 +575,7 @@
 {
     debug(adi) printf("array.CmpChar unittest\n");
 
-    auto a = "hello"c;
+    char[] a = "hello"c;
 
     assert(a >  "hel");
     assert(a >= "hel");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/aa7.d	Sun Aug 10 08:37:38 2008 +0200
@@ -0,0 +1,57 @@
+// adapted from dstress.run.a.associative_array_19_A to catch regressions early
+
+module mini.aa7;
+
+extern (C) int printf(char*, ...);
+
+extern (C) void gc_collect();
+
+union Key{
+    char x;
+}
+
+class Payload {
+    this(Key value) {
+        value.x += 1;
+        _value = value;
+    }
+
+    Key value() {
+        return _value;
+    }
+
+    Key _value;
+}
+
+int main(){
+    Payload[Key] aa;
+
+    Key[] allKeys;
+    static Key a = { 'a' };
+    static Key b = { 'b' };
+    static Key c = { 'c' };
+    allKeys ~= a;
+    allKeys ~= b;
+    allKeys ~= c;
+
+    foreach(Key key; allKeys) {
+        aa[key] = new Payload(key);
+    }
+
+    int i = 0;
+    foreach(Key key; allKeys) {
+        printf("1st #%d\n", i++);
+        assert(key in aa);
+    }
+
+    gc_collect();
+
+    i = 0;
+    foreach(Key key; allKeys) {
+        printf("2nd #%d\n", i++);
+        assert(key in aa);
+    }
+
+    return 0;
+}
+
--- a/tests/mini/nested13.d	Sat Aug 09 09:03:52 2008 +0200
+++ b/tests/mini/nested13.d	Sun Aug 10 08:37:38 2008 +0200
@@ -1,4 +1,4 @@
-module tangotests.nested2;
+module mini.nested13;
 
 extern(C) int printf(char*, ...);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/nested16.d	Sun Aug 10 08:37:38 2008 +0200
@@ -0,0 +1,31 @@
+module mini.nested16;
+
+void main()
+{
+    int idx = 123;
+    int func(int* idp)
+    {
+        void foo()
+        {
+            void bar(int* idp)
+            {
+                auto c = new class
+                {
+                    void mem()
+                    {
+                        scope(exit) ++*idp;
+                    }
+                };
+                auto dg = () {
+                    c.mem();
+                };
+                dg();
+            }
+            bar(idp);
+            ++*idp;
+        }
+        foo();
+        return ++*idp;
+    }
+    assert(func(&idx) == 126);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/nested17.d	Sun Aug 10 08:37:38 2008 +0200
@@ -0,0 +1,45 @@
+// $HeadURL: svn://svn.berlios.de/dstress/trunk/run/n/nested_class_03_A.d $
+// $Date: 2005-06-18 09:15:32 +0200 (Sat, 18 Jun 2005) $
+// $Author: thomask $
+
+// @author@ John C <johnch_atms@hotmail.com>
+// @date@   2005-06-09
+// @uri@    news:d88vta$vak$1@digitaldaemon.com
+
+//module dstress.run.n.nested_class_03_A;
+module mini.nested17;
+
+interface Inner{
+    int value();        
+}
+
+class Outer{
+    int x;
+
+    Inner test(){
+        printf("val = %d\n", x);
+        return new class Inner {
+            int y;
+
+            this(){
+                printf("val = %d\n", x);
+                y=x;
+            }
+
+            int value(){
+                return y;
+            }
+        };
+    }
+}
+
+int main(){
+    Outer o = new Outer();
+    o.x=2;  
+    int val = o.test().value();
+    printf("val = %d\n", val);
+    assert(val == o.x);
+    return 0;
+}
+
+extern(C) int printf(char*, ...);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/nested19.d	Sun Aug 10 08:37:38 2008 +0200
@@ -0,0 +1,27 @@
+module mini.nested19;
+
+void main()
+{
+    int i = 1;
+    
+    class C
+    {
+        int j = 2;
+        void func()
+        {
+            int k = 3;
+            
+            void foo()
+            {
+                i = i+j+k;
+            }
+            
+            foo();
+        }
+    }
+    
+    auto c = new C;
+    c.func();
+    
+    assert(i == 6);
+}
--- a/tests/mini/nested6.d	Sat Aug 09 09:03:52 2008 +0200
+++ b/tests/mini/nested6.d	Sun Aug 10 08:37:38 2008 +0200
@@ -21,13 +21,13 @@
                 }
             }
 
-            {
-                scope c2 = new C2;
-                c2.func2();
-            }
+            auto c2 = new C2;
+            c2.func2();
         }
     }
 
-    scope c = new C;
+    auto c = new C;
     c.func();
+    
+    assert(i == 45);
 }