changeset 585:fbb1a366cfbc

Complex number should now follow the D ABI on x86. They're also treated as first class values now. Big change.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 09 Sep 2008 16:49:47 -0700
parents c7d7e2282ba3
children 192b82878b78
files dmd/expression.c dmd/expression.h dmd/mtype.c gen/aa.cpp gen/arrays.cpp gen/complex.cpp gen/complex.h gen/dvalue.cpp gen/dvalue.h gen/functions.cpp gen/llvmhelpers.cpp gen/statements.cpp gen/structs.cpp gen/tocall.cpp gen/toir.cpp gen/tollvm.cpp gen/tollvm.h tests/mini/complex1.d tests/mini/complex2.d tests/mini/complex3.d tests/mini/complex4.d
diffstat 21 files changed, 180 insertions(+), 230 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/expression.c	Mon Sep 08 20:38:55 2008 +0200
+++ b/dmd/expression.c	Tue Sep 09 16:49:47 2008 -0700
@@ -7929,7 +7929,6 @@
 AddExp::AddExp(Loc loc, Expression *e1, Expression *e2)
 	: BinExp(loc, TOKadd, sizeof(AddExp), e1, e2)
 {
-    llvmFieldIndex = false;
 }
 
 Expression *AddExp::semantic(Scope *sc)
--- a/dmd/expression.h	Mon Sep 08 20:38:55 2008 +0200
+++ b/dmd/expression.h	Tue Sep 09 16:49:47 2008 -0700
@@ -1173,9 +1173,6 @@
     Identifier *opId_r();
 
     elem *toElem(IRState *irs);
-
-    // LLVMDC
-    bool llvmFieldIndex;
 };
 
 struct MinExp : BinExp
--- a/dmd/mtype.c	Mon Sep 08 20:38:55 2008 +0200
+++ b/dmd/mtype.c	Tue Sep 09 16:49:47 2008 -0700
@@ -4456,18 +4456,17 @@
 
 	// *(&e + offset)
 	accessCheck(e->loc, sc, e, d);
+
+// LLVMDC we don't want dot exprs turned into pointer arithmetic. it complicates things for no apparent gain
+#ifndef IN_LLVM
 	b = new AddrExp(e->loc, e);
 	b->type = e->type->pointerTo();
 	b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tint32));
-#if IN_LLVM
-    // LLVMDC modification
-    // this is *essential*
-    ((AddExp*)b)->llvmFieldIndex = true;
-#endif
 	b->type = v->type->pointerTo();
 	e = new PtrExp(e->loc, b);
 	e->type = v->type;
 	return e;
+#endif
     }
 
     de = new DotVarExp(e->loc, e, d);
--- a/gen/aa.cpp	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/aa.cpp	Tue Sep 09 16:49:47 2008 -0700
@@ -23,13 +23,8 @@
         pkey = key->getRVal();
     }
     else if (DVarValue* var = key->isVar()) {
-        if (var->lval) {
-            pkey = key->getLVal();
-            needmem = false;
-        }
-        else {
-            pkey = key->getRVal();
-        }
+        pkey = key->getLVal();
+        needmem = false;
     }
     else if (key->isConst()) {
         needmem = true;
@@ -37,8 +32,8 @@
     }
     else {
         LLValue* tmp = DtoAlloca(DtoType(keytype), "aatmpkeystorage");
-        DVarValue* var = new DVarValue(keytype, tmp, true);
-        DtoAssign(loc, var, key);
+        DVarValue var(keytype, tmp);
+        DtoAssign(loc, &var, key);
         return tmp;
     }
 
@@ -96,7 +91,7 @@
     if (ret->getType() != targettype)
         ret = DtoBitCast(ret, targettype);
 
-    return new DVarValue(type, ret, true);
+    return new DVarValue(type, ret);
 }
 
 /////////////////////////////////////////////////////////////////////////////////////
--- a/gen/arrays.cpp	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/arrays.cpp	Tue Sep 09 16:49:47 2008 -0700
@@ -116,10 +116,10 @@
     LLValue* val;
 
     // give slices and complex values storage (and thus an address to pass)
-    if (value->isSlice() || value->isComplex())
+    if (value->isSlice())
     {
         val = DtoAlloca(DtoType(value->getType()), ".tmpparam");
-        DVarValue lval(value->getType(), val, true);
+        DVarValue lval(value->getType(), val);
         DtoAssign(loc, &lval, value);
     }
     else
@@ -526,7 +526,7 @@
     LLValue* ptr = slice->ptr;
     ptr = llvm::GetElementPtrInst::Create(ptr, idx, "tmp", gIR->scopebb());
 
-    DValue* dptr = new DVarValue(exp->type, ptr, true);
+    DValue* dptr = new DVarValue(exp->type, ptr);
 
     DValue* e = exp->toElem(gIR);
 
@@ -631,7 +631,7 @@
         DSliceValue* slice = DtoNewDynArray(type, lenval, false);
         LLValue* mem = slice->ptr;
 
-        DVarValue* memval = new DVarValue(e1->getType(), mem, true);
+        DVarValue* memval = new DVarValue(e1->getType(), mem);
         DtoAssign(exp1->loc, memval, e1);
 
         src1 = DtoArrayPtr(e2);
@@ -662,7 +662,7 @@
         DtoMemCpy(mem,src1,bytelen);
 
         mem = gIR->ir->CreateGEP(mem,len1,"tmp");
-        DVarValue* memval = new DVarValue(e2->getType(), mem, true);
+        DVarValue* memval = new DVarValue(e2->getType(), mem);
         DtoAssign(exp1->loc, memval, e2);
 
         return slice;
--- a/gen/complex.cpp	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/complex.cpp	Tue Sep 09 16:49:47 2008 -0700
@@ -8,20 +8,15 @@
 #include "gen/llvmhelpers.h"
 #include "gen/irstate.h"
 #include "gen/dvalue.h"
+#include "gen/logger.h"
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
 const llvm::StructType* DtoComplexType(Type* type)
 {
     Type* t = type->toBasetype();
-
     const LLType* base = DtoComplexBaseType(t);
-
-    std::vector<const LLType*> types;
-    types.push_back(base);
-    types.push_back(base);
-
-    return llvm::StructType::get(types);
+    return llvm::StructType::get(base, base, NULL);
 }
 
 const LLType* DtoComplexBaseType(Type* t)
@@ -47,19 +42,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-LLConstant* DtoConstComplex(Type* ty, LLConstant* re, LLConstant* im)
-{
-    assert(0);
-    const LLType* base = DtoComplexBaseType(ty);
-
-    std::vector<LLConstant*> inits;
-    inits.push_back(re);
-    inits.push_back(im);
-
-    const llvm::VectorType* vt = llvm::VectorType::get(base, 2);
-    return llvm::ConstantVector::get(vt, inits);
-}
-
 LLConstant* DtoConstComplex(Type* _ty, long double re, long double im)
 {
     TY ty = _ty->toBasetype()->ty;
@@ -108,7 +90,7 @@
 {
     Type* t = val->getType()->toBasetype();
 
-    if (val->isComplex() || t->iscomplex()) {
+    if (t->iscomplex()) {
         return DtoCastComplex(loc, val, to);
     }
 
@@ -127,27 +109,27 @@
         baserety = Type::tfloat80;
         baseimty = Type::timaginary80;
     }
+    else {
+        assert(0);
+    }
+
+    const LLType* complexTy = DtoType(to);
+    LLValue* res;
 
     if (t->isimaginary()) {
-        return new DComplexValue(to, LLConstant::getNullValue(DtoType(baserety)), DtoCastFloat(loc, val, baseimty)->getRVal());
+        res = DtoAggrPair(complexTy, LLConstant::getNullValue(DtoType(baserety)), DtoCastFloat(loc, val, baseimty)->getRVal());
     }
-    else if (t->isfloating()) {
-        return new DComplexValue(to, DtoCastFloat(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty)));
+    else if (t->isfloating() || t->isintegral()) {
+        res = DtoAggrPair(complexTy, DtoCastFloat(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty)));
     }
-    else if (t->isintegral()) {
-        return new DComplexValue(to, DtoCastInt(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty)));
+    else {
+        assert(0);
     }
-    assert(0);
+    return new DImValue(to, res);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoComplexAssign(LLValue* l, LLValue* r)
-{
-    DtoStore(DtoLoad(DtoGEPi(r, 0,0, "tmp")), DtoGEPi(l,0,0,"tmp"));
-    DtoStore(DtoLoad(DtoGEPi(r, 0,1, "tmp")), DtoGEPi(l,0,1,"tmp"));
-}
-
 void DtoComplexSet(LLValue* c, LLValue* re, LLValue* im)
 {
     DtoStore(re, DtoGEPi(c,0,0,"tmp"));
@@ -158,15 +140,10 @@
 
 void DtoGetComplexParts(DValue* c, LLValue*& re, LLValue*& im)
 {
-    // get LLValues
-    if (DComplexValue* cx = c->isComplex()) {
-        re = cx->re;
-        im = cx->im;
-    }
-    else {
-        re = DtoLoad(DtoGEPi(c->getRVal(),0,0,"tmp"));
-        im = DtoLoad(DtoGEPi(c->getRVal(),0,1,"tmp"));
-    }
+    LLValue* v = c->getRVal();
+    Logger::cout() << "extracting real and imaginary parts from: " << *v << '\n';
+    re = gIR->ir->CreateExtractValue(v, 0, ".re_part");
+    im = gIR->ir->CreateExtractValue(v, 1, ".im_part");
 }
 
 DValue* resolveLR(DValue* val, bool getlval)
@@ -232,7 +209,8 @@
     else // either hasIm(rhstype) or no im at all (then use any)
         res_im = rhs_im;
 
-    return new DComplexValue(type, res_re, res_im);
+    LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
+    return new DImValue(type, res);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -262,7 +240,8 @@
     else
         res_im = lhs_im;
 
-    return new DComplexValue(type, res_re, res_im);
+    LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
+    return new DImValue(type, res);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -314,7 +293,8 @@
     else
         res_im = hasRe(lhstype) ? rhs_im : lhs_re; // null!
 
-    return new DComplexValue(type, res_re, res_im);
+    LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
+    return new DImValue(type, res);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -390,7 +370,8 @@
         res_im = gIR->ir->CreateFDiv(res_im, denom, "res_im");
     }
 
-    return new DComplexValue(type, res_re, res_im);
+    LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
+    return new DImValue(type, res);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -408,7 +389,8 @@
     re = gIR->ir->CreateNeg(a, "tmp");
     im = gIR->ir->CreateNeg(b, "tmp");
 
-    return new DComplexValue(type, re, im);
+    LLValue* res = DtoAggrPair(DtoType(type), re, im);
+    return new DImValue(type, res);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -462,35 +444,35 @@
             re = gIR->ir->CreateFPTrunc(re, toty, "tmp");
             im = gIR->ir->CreateFPTrunc(im, toty, "tmp");
         }
-        else if (to->size() > vty->size()) {
+        else {
             re = gIR->ir->CreateFPExt(re, toty, "tmp");
             im = gIR->ir->CreateFPExt(im, toty, "tmp");
         }
-        else {
-            return val;
+
+        LLValue* pair = DtoAggrPair(DtoType(_to), re, im);
+        DValue* rval = new DImValue(_to, pair);
+
+        // if the value we're casting is not a lvalue, the cast value can't be either
+        if (!val->isLVal()) {
+            return rval;
         }
 
-        if (val->isComplex())
-            return new DComplexValue(_to, re, im);
-
         // unfortunately at this point, the cast value can show up as the lvalue for += and similar expressions.
-        // so we need to give it storage, or fix the system that handles this stuff (DLRValue)
-        LLValue* mem = DtoAlloca(DtoType(_to), "castcomplextmp");
-        DtoComplexSet(mem, re, im);
-        return new DLRValue(val, new DImValue(_to, mem));
+        // so we need to maintain the storage
+        return new DLRValue(val, rval);
     }
     else if (to->isimaginary()) {
-        if (val->isComplex())
-            return new DImValue(to, val->isComplex()->im);
+        // FIXME: this loads both values, even when we only need one
         LLValue* v = val->getRVal();
-        DImValue* im = new DImValue(to, DtoLoad(DtoGEPi(v,0,1,"tmp")));
+        LLValue* impart = gIR->ir->CreateExtractValue(v, 1, ".im_part");
+        DImValue* im = new DImValue(to, impart);
         return DtoCastFloat(loc, im, to);
     }
     else if (to->isfloating()) {
-        if (val->isComplex())
-            return new DImValue(to, val->isComplex()->re);
+        // FIXME: this loads both values, even when we only need one
         LLValue* v = val->getRVal();
-        DImValue* re = new DImValue(to, DtoLoad(DtoGEPi(v,0,0,"tmp")));
+        LLValue* repart = gIR->ir->CreateExtractValue(v, 0, ".re_part");
+        DImValue* re = new DImValue(to, repart);
         return DtoCastFloat(loc, re, to);
     }
     else
--- a/gen/complex.h	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/complex.h	Tue Sep 09 16:49:47 2008 -0700
@@ -4,7 +4,6 @@
 const llvm::StructType* DtoComplexType(Type* t);
 const LLType* DtoComplexBaseType(Type* t);
 
-LLConstant* DtoConstComplex(Type* t, LLConstant* re, LLConstant* im);
 LLConstant* DtoConstComplex(Type* t, long double re, long double im);
 
 LLConstant* DtoComplexShuffleMask(unsigned a, unsigned b);
@@ -13,7 +12,6 @@
 LLValue* DtoImagPart(DValue* val);
 DValue* DtoComplex(Loc& loc, Type* to, DValue* val);
 
-void DtoComplexAssign(LLValue* l, LLValue* r);
 void DtoComplexSet(LLValue* c, LLValue* re, LLValue* im);
 
 void DtoGetComplexParts(DValue* c, LLValue*& re, LLValue*& im);
--- a/gen/dvalue.cpp	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/dvalue.cpp	Tue Sep 09 16:49:47 2008 -0700
@@ -4,60 +4,40 @@
 #include "gen/irstate.h"
 #include "gen/logger.h"
 #include "gen/dvalue.h"
+#include "gen/llvmhelpers.h"
 
 #include "declaration.h"
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////////////////
 
-DVarValue::DVarValue(Type* t, VarDeclaration* vd, LLValue* llvmValue, bool lvalue)
+DVarValue::DVarValue(Type* t, VarDeclaration* vd, LLValue* llvmValue)
 {
     var = vd;
     val = llvmValue;
-    rval = 0;
-    lval = lvalue;
     type = t;
 }
 
-DVarValue::DVarValue(Type* t, LLValue* lv, LLValue* rv)
-{
-    var = 0;
-    val = lv;
-    rval = rv;
-    lval = true;
-    type = t;
-}
-
-DVarValue::DVarValue(Type* t, LLValue* llvmValue, bool lvalue)
+DVarValue::DVarValue(Type* t, LLValue* llvmValue)
 {
     var = 0;
     val = llvmValue;
-    rval = 0;
-    lval = lvalue;
     type = t;
 }
 
 LLValue* DVarValue::getLVal()
 {
-    assert(val && lval);
+    assert(val);
     return val;
 }
 
 LLValue* DVarValue::getRVal()
 {
-    assert(rval || val);
-    if (DtoIsPassedByRef(type)) {
-        if (rval) return rval;
+    assert(val);
+    Type* bt = type->toBasetype();
+    if (DtoIsPassedByRef(bt))
         return val;
-    }
-    else {
-        if (rval) return rval;
-        //Logger::cout() << "val: " << *val << '\n';
-        if (!isField() && DtoCanLoad(val)) {
-            return DtoLoad(val);
-        }
-        return val;
-    }
+    return DtoLoad(val);
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
--- a/gen/dvalue.h	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/dvalue.h	Tue Sep 09 16:49:47 2008 -0700
@@ -31,7 +31,6 @@
 struct DSliceValue;
 struct DArrayLenValue;
 struct DLRValue;
-struct DComplexValue;
 
 // base class for d-values
 struct DValue : Object
@@ -51,7 +50,6 @@
     virtual DSliceValue* isSlice() { return NULL; }
     virtual DFuncValue* isFunc() { return NULL; }
     virtual DArrayLenValue* isArrayLen() { return NULL; }
-    virtual DComplexValue* isComplex() { return NULL; }
     virtual DLRValue* isLRValue() { return NULL; }
 
 protected:
@@ -101,14 +99,11 @@
     Type* type;
     VarDeclaration* var;
     LLValue* val;
-    LLValue* rval;
-    bool lval;
 
-    DVarValue(Type* t, VarDeclaration* vd, LLValue* llvmValue, bool lvalue);
-    DVarValue(Type* t, LLValue* lv, LLValue* rv);
-    DVarValue(Type* t, LLValue* llvmValue, bool lvalue);
+    DVarValue(Type* t, VarDeclaration* vd, LLValue* llvmValue);
+    DVarValue(Type* t, LLValue* llvmValue);
 
-    virtual bool isLVal() { return val && lval; }
+    virtual bool isLVal() { return true; }
     virtual LLValue* getLVal();
     virtual LLValue* getRVal();
 
@@ -119,7 +114,7 @@
 // field d-value
 struct DFieldValue : DVarValue
 {
-    DFieldValue(Type* t, LLValue* llvmValue, bool l) : DVarValue(t, llvmValue, l) {}
+    DFieldValue(Type* t, LLValue* llvmValue) : DVarValue(t, llvmValue) {}
     virtual DFieldValue* isField() { return this; }
 };
 
@@ -173,21 +168,4 @@
     virtual DLRValue* isLRValue() { return this; }
 };
 
-// complex number immediate d-value (much like slice)
-struct DComplexValue : DValue
-{
-    Type* type;
-    LLValue* re;
-    LLValue* im;
-
-    DComplexValue(Type* t, LLValue* r, LLValue* i) {
-        type = t;
-        re = r;
-        im = i;
-    }
-
-    virtual Type*& getType() { assert(type); return type; }
-    virtual DComplexValue* isComplex() { return this; }
-};
-
 #endif // LLVMDC_GEN_DVALUE_H
--- a/gen/functions.cpp	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/functions.cpp	Tue Sep 09 16:49:47 2008 -0700
@@ -122,7 +122,13 @@
         bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout));
 
         const LLType* at = DtoType(argT);
-        if (isaStruct(at)) {
+
+        // FIXME: using the llvm type for these is a bad idea... aggregates are first class now and we're starting to use it ...
+
+        if (argT->iscomplex()) {
+            goto Lbadstuff;
+        }
+        else if (isaStruct(at)) {
             Logger::println("struct param");
             paramvec.push_back(getPtrToType(at));
             if (!refOrOut)
@@ -140,6 +146,7 @@
             paramvec.push_back(getPtrToType(at));
         }
         else {
+Lbadstuff:
             if (refOrOut) {
                 Logger::println("by ref param");
                 at = getPtrToType(at);
@@ -866,10 +873,10 @@
             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()))
+    else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isNull()))
     {
         LLValue* alloc = DtoAlloca(DtoType(argexp->type), ".tmp_arg");
-        DVarValue* vv = new DVarValue(argexp->type, alloc, true);
+        DVarValue* vv = new DVarValue(argexp->type, alloc);
         DtoAssign(argexp->loc, vv, arg);
         arg = vv;
     }
@@ -883,7 +890,7 @@
 {
     Logger::println("DtoVariadicArgument");
     LOG_SCOPE;
-    DVarValue vv(argexp->type, dst, true);
+    DVarValue vv(argexp->type, dst);
     DtoAssign(argexp->loc, &vv, argexp->toElem(gIR));
 }
 
--- a/gen/llvmhelpers.cpp	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/llvmhelpers.cpp	Tue Sep 09 16:49:47 2008 -0700
@@ -360,7 +360,7 @@
     if (vdparent == irfunc->decl)
     {
         LLValue* val = vd->ir.getIrValue();
-        return new DVarValue(astype, vd, val, true);
+        return new DVarValue(astype, vd, val);
     }
     
     // get it from the nested context
@@ -381,7 +381,7 @@
     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);
+    return new DVarValue(astype, vd, val);
 }
 
 LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
@@ -486,21 +486,15 @@
         DtoStore(r, l);
     }
     else if (t->iscomplex()) {
-        assert(!lhs->isComplex());
-
         LLValue* dst;
         if (DLRValue* lr = lhs->isLRValue()) {
             dst = lr->getLVal();
             rhs = DtoCastComplex(loc, rhs, lr->getLType());
         }
         else {
-            dst = lhs->getRVal();
+            dst = lhs->getLVal();
         }
-
-        if (DComplexValue* cx = rhs->isComplex())
-            DtoComplexSet(dst, cx->re, cx->im);
-        else
-            DtoComplexAssign(dst, rhs->getRVal());
+        DtoStore(rhs->getRVal(), dst);
     }
     else {
         LLValue* l = lhs->getLVal();
@@ -538,7 +532,8 @@
     if (basetype->iscomplex())
     {
         const LLType* basefp = DtoComplexBaseType(basetype);
-        return new DComplexValue(type, LLConstant::getNullValue(basefp), LLConstant::getNullValue(basefp));
+        LLValue* res = DtoAggrPair(DtoType(type), LLConstant::getNullValue(basefp), LLConstant::getNullValue(basefp));
+        return new DImValue(type, res);
     }
     // integer, floating, pointer and class have no special representation
     else if (basetype->isintegral() || basetype->isfloating() || basety == Tpointer || basety == Tclass)
@@ -790,7 +785,7 @@
     gIR->scope() = IRScope(initbb,endinitbb);
     DValue* ie = DtoInitializer(gvar, init);
     
-    DVarValue dst(t, gvar, true);
+    DVarValue dst(t, gvar);
     DtoAssign(init->loc, &dst, ie);
     
     gIR->ir->CreateStore(DtoConstBool(true), gflag);
@@ -1177,7 +1172,7 @@
             DValue* ie = DtoInitializer(vd->ir.irLocal->value, vd->init);
         }
 
-        return new DVarValue(vd->type, vd, vd->ir.getIrValue(), true);
+        return new DVarValue(vd->type, vd, vd->ir.getIrValue());
     }
     // struct declaration
     else if (StructDeclaration* s = declaration->isStructDeclaration())
--- a/gen/statements.cpp	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/statements.cpp	Tue Sep 09 16:49:47 2008 -0700
@@ -62,7 +62,7 @@
 
             if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
 
-            DValue* rvar = new DVarValue(f->type->next, f->decl->ir.irFunc->retArg, true);
+            DValue* rvar = new DVarValue(f->type->next, f->decl->ir.irFunc->retArg);
 
             DValue* e = exp->toElem(p);
 
@@ -687,7 +687,7 @@
     {
         // give storage
         llval = DtoAlloca(DtoType(e->type), "tmp");
-        DVarValue* vv = new DVarValue(e->type, llval, true);
+        DVarValue* vv = new DVarValue(e->type, llval);
         DtoAssign(e->loc, vv, val);
     }
     else
@@ -1002,9 +1002,9 @@
     value->ir.irLocal->value = DtoGEP1(val,loadedKey);
 
     if (!value->isRef() && !value->isOut()) {
-        DValue* dst = new DVarValue(value->type, valvar, true);
-        DValue* src = new DVarValue(value->type, value->ir.irLocal->value, true);
-        DtoAssign(loc, dst, src);
+        DVarValue dst(value->type, valvar);
+        DVarValue src(value->type, value->ir.irLocal->value);
+        DtoAssign(loc, &dst, &src);
         value->ir.irLocal->value = valvar;
     }
 
@@ -1151,7 +1151,8 @@
     DValue* e = exp->toElem(p);
     assert(!wthis->ir.isSet());
     wthis->ir.irLocal = new IrLocal(wthis);
-    wthis->ir.irLocal->value = e->getRVal();
+    wthis->ir.irLocal->value = DtoAlloca(DtoType(wthis->type), wthis->toChars());
+    DtoStore(e->getRVal(), wthis->ir.irLocal->value);
 
     body->toIR(p);
 }
--- a/gen/structs.cpp	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/structs.cpp	Tue Sep 09 16:49:47 2008 -0700
@@ -60,6 +60,10 @@
 
     const LLType* llt = getPtrToType(DtoType(t));
     const LLType* st = getPtrToType(DtoType(sd->type));
+
+    Logger::cout() << "ptr = " << *ptr << '\n';
+    Logger::cout() << "st  = " << *st << '\n';
+
     if (ptr->getType() != st) {
         assert(sd->ir.irStruct->hasUnions);
         ptr = gIR->ir->CreateBitCast(ptr, st, "tmp");
--- a/gen/tocall.cpp	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/tocall.cpp	Tue Sep 09 16:49:47 2008 -0700
@@ -314,6 +314,8 @@
             LLValue* arg = argval->getRVal();
             if (fnarg) // can fnarg ever be null in this block?
             {
+                Logger::cout() << "arg:     " << *arg << '\n';
+                Logger::cout() << "expects: " << *callableTy->getParamType(j) << '\n';
                 if (arg->getType() != callableTy->getParamType(j))
                     arg = DtoBitCast(arg, callableTy->getParamType(j));
                 if (fnarg->llvmAttrs)
--- a/gen/toir.cpp	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/toir.cpp	Tue Sep 09 16:49:47 2008 -0700
@@ -64,14 +64,14 @@
         {
             Logger::println("Id::_arguments");
             LLValue* v = p->func()->_arguments;
-            return new DVarValue(type, vd, v, true);
+            return new DVarValue(type, vd, v);
         }
         // _argptr
         else if (vd->ident == Id::_argptr && p->func()->_argptr)
         {
             Logger::println("Id::_argptr");
             LLValue* v = p->func()->_argptr;
-            return new DVarValue(type, vd, v, true);
+            return new DVarValue(type, vd, v);
         }
         // _dollar
         else if (vd->ident == Id::dollar)
@@ -79,7 +79,7 @@
             Logger::println("Id::dollar");
             assert(!p->arrays.empty());
             LLValue* tmp = DtoArrayLen(p->arrays.back());
-            return new DVarValue(type, vd, tmp, false);
+            return new DImValue(type, tmp);
         }
         // typeinfo
         else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
@@ -88,12 +88,10 @@
             DtoForceDeclareDsymbol(tid);
             assert(tid->ir.getIrValue());
             const LLType* vartype = DtoType(type);
-            LLValue* m;
-            if (tid->ir.getIrValue()->getType() != getPtrToType(vartype))
-                m = p->ir->CreateBitCast(tid->ir.getIrValue(), vartype, "tmp");
-            else
-                m = tid->ir.getIrValue();
-            return new DVarValue(type, vd, m, true);
+            LLValue* m = tid->ir.getIrValue();
+            if (m->getType() != getPtrToType(vartype))
+                m = p->ir->CreateBitCast(m, vartype, "tmp");
+            return new DImValue(type, m);
         }
         // classinfo
         else if (ClassInfoDeclaration* cid = vd->isClassInfoDeclaration())
@@ -101,7 +99,7 @@
             Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars());
             DtoForceDeclareDsymbol(cid->cd);
             assert(cid->cd->ir.irStruct->classInfo);
-            return new DVarValue(type, vd, cid->cd->ir.irStruct->classInfo, true);
+            return new DVarValue(type, vd, cid->cd->ir.irStruct->classInfo);
         }
         // nested variable
         else if (vd->nestedref) {
@@ -117,7 +115,7 @@
                 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);
+                return new DVarValue(type, vd, vd->ir.getIrValue());
             }
             else if (llvm::isa<llvm::Argument>(vd->ir.getIrValue())) {
                 return new DImValue(type, vd->ir.getIrValue());
@@ -125,6 +123,7 @@
             else assert(0);
         }
         else {
+            Logger::println("a normal variable");
             // take care of forward references of global variables
             if (vd->isDataseg() || (vd->storage_class & STCextern)) {
                 vd->toObjFile(0); // TODO: multiobj
@@ -135,7 +134,7 @@
                 Logger::cout() << "unresolved global had type: " << *DtoType(vd->type) << '\n';
                 fatal();
             }
-            return new DVarValue(type, vd, vd->ir.getIrValue(), true);
+            return new DVarValue(type, vd, vd->ir.getIrValue());
         }
     }
     else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
@@ -158,7 +157,7 @@
         assert(ts->sym);
         DtoForceConstInitDsymbol(ts->sym);
         assert(ts->sym->ir.irStruct->init);
-        return new DVarValue(type, ts->sym->ir.irStruct->init, true);
+        return new DVarValue(type, ts->sym->ir.irStruct->init);
     }
     else
     {
@@ -281,6 +280,7 @@
     Logger::print("ComplexExp::toElem(): %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     LLConstant* c = toConstElem(p);
+    LLValue* res;
 
     if (c->isNullValue()) {
         Type* t = type->toBasetype();
@@ -292,10 +292,13 @@
             c = DtoConstFP(Type::tfloat80, 0);
         else
             assert(0);
-        return new DComplexValue(type, c, c);
+        res = DtoAggrPair(DtoType(type), c, c);
     }
-
-    return new DComplexValue(type, c->getOperand(0), c->getOperand(1));
+    else {
+        res = DtoAggrPair(DtoType(type), c->getOperand(0), c->getOperand(1));
+    }
+
+    return new DImValue(type, res);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -360,12 +363,12 @@
         LLConstant* clen = llvm::ConstantInt::get(DtoSize_t(),len,false);
         LLValue* tmpmem = DtoAlloca(DtoType(dtype),"tempstring");
         DtoSetArray(tmpmem, clen, arrptr);
-        return new DVarValue(type, tmpmem, true);
+        return new DVarValue(type, tmpmem);
     }
     else if (dtype->ty == Tsarray) {
         const LLType* dstType = getPtrToType(LLArrayType::get(ct, len));
         LLValue* emem = (gvar->getType() == dstType) ? gvar : DtoBitCast(gvar, dstType);
-        return new DVarValue(type, emem, true);
+        return new DVarValue(type, emem);
     }
     else if (dtype->ty == Tpointer) {
         return new DImValue(type, arrptr);
@@ -456,7 +459,7 @@
         Logger::println("performing array.length assignment");
         ArrayLengthExp *ale = (ArrayLengthExp *)e1;
         DValue* arr = ale->e1->toElem(p);
-        DVarValue arrval(ale->e1->type, arr->getLVal(), true);
+        DVarValue arrval(ale->e1->type, arr->getLVal());
         DValue* newlen = e2->toElem(p);
         DSliceValue* slice = DtoResizeDynArray(arrval.getType(), &arrval, newlen);
         DtoAssign(loc, &arrval, slice);
@@ -469,7 +472,7 @@
     DValue* r = e2->toElem(p);
     DtoAssign(loc, l, r);
 
-    if (l->isSlice() || l->isComplex())
+    if (l->isSlice())
         return l;
 
 #if 0
@@ -503,7 +506,7 @@
     Type* e2type = e2->type->toBasetype();
 
     if (e1type != e2type) {
-        if (llvmFieldIndex) {
+        /*if (llvmFieldIndex) {
             assert(e1type->ty == Tpointer && e1next && e1next->ty == Tstruct);
             Logger::println("add to AddrExp of struct");
             assert(r->isConst());
@@ -512,9 +515,9 @@
             TypeStruct* ts = (TypeStruct*)e1next;
             DStructIndexVector offsets;
             LLValue* v = DtoIndexStruct(l->getRVal(), ts->sym, t->next, cofs->getZExtValue(), offsets);
-            return new DFieldValue(type, v, true);
+            return new DFieldValue(type, v);
         }
-        else if (e1type->ty == Tpointer) {
+        else*/ if (e1type->ty == Tpointer) {
             Logger::println("add to pointer");
             if (r->isConst()) {
                 llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->isConst()->c);
@@ -848,7 +851,9 @@
         return v;
     }
     Logger::println("is nothing special");
-    return new DFieldValue(type, v->getLVal(), false);
+    LLValue* lval = v->getLVal();
+    Logger::cout() << "lval: " << *lval << '\n';
+    return new DImValue(type, v->getLVal());
 }
 
 LLConstant* AddrExp::toConstElem(IRState* p)
@@ -893,12 +898,18 @@
 
     DValue* a = e1->toElem(p);
 
-    // this should be deterministic but right now lvalue casts don't propagate lvalueness !?!
+    // this is *so* ugly.. I'd really like to figure out some way to avoid this badness...
     LLValue* lv = a->getRVal();
     LLValue* v = lv;
-    if (DtoCanLoad(v))
+
+    Type* bt = type->toBasetype();
+
+    // we can't load function pointers, but they aren't passed by reference either
+    // FIXME: maybe a MayLoad function isn't a bad idea after all ...
+    if (!DtoIsPassedByRef(bt) && bt->ty != Tfunction)
         v = DtoLoad(v);
-    return new DLRValue(new DVarValue(type, lv, true), new DImValue(type, v));
+
+    return new DLRValue(new DVarValue(type, lv), new DImValue(type, v));
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -951,7 +962,7 @@
             assert(0);
 
         //Logger::cout() << "mem: " << *arrptr << '\n';
-        return new DVarValue(type, vd, arrptr, true);
+        return new DVarValue(type, vd, arrptr);
     }
     else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
     {
@@ -1021,7 +1032,7 @@
     {
         LLValue* v = p->func()->thisArg;
         assert(v);
-        return new DVarValue(type, v, true);
+        return new DVarValue(type, v);
     }
     // regular this expr
     else if (VarDeclaration* vd = var->isVarDeclaration()) {
@@ -1034,7 +1045,7 @@
             Logger::println("normal this exp");
             v = p->func()->thisArg;
         }
-        return new DVarValue(type, vd, v, true);
+        return new DVarValue(type, vd, v);
     }
 
     // anything we're not yet handling ?
@@ -1082,7 +1093,7 @@
         Logger::println("invalid index exp! e1type: %s", e1type->toChars());
         assert(0);
     }
-    return new DVarValue(type, arrptr, true);
+    return new DVarValue(type, arrptr);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -1479,7 +1490,7 @@
     {
         // allocate
         LLValue* mem = DtoNew(newtype);
-        DVarValue tmpvar(newtype, mem, true);
+        DVarValue tmpvar(newtype, mem);
 
         // default initialize
         Expression* exp = newtype->defaultInit(loc);
@@ -1508,7 +1519,7 @@
     {
         LLValue* rval = dval->getRVal();
         DtoDeleteMemory(rval);
-        if (dval->isVar() && dval->isVar()->lval)
+        if (dval->isVar())
             DtoStore(llvm::Constant::getNullValue(rval->getType()), dval->getLVal());
     }
     // class
@@ -1531,7 +1542,7 @@
             LLValue* rval = dval->getRVal();
             DtoDeleteClass(rval);
         }
-        if (dval->isVar() && dval->isVar()->lval) {
+        if (dval->isVar()) {
             LLValue* lval = dval->getLVal();
             DtoStore(llvm::Constant::getNullValue(lval->getType()->getContainedType(0)), lval);
         }
@@ -1957,7 +1968,7 @@
     // allocate a temporary for the final result. failed to come up with a better way :/
     llvm::BasicBlock* entryblock = &p->topfunc()->front();
     LLValue* resval = DtoAlloca(resty,"condtmp");
-    DVarValue* dvv = new DVarValue(type, resval, true);
+    DVarValue* dvv = new DVarValue(type, resval);
 
     llvm::BasicBlock* oldend = p->scopeend();
     llvm::BasicBlock* condtrue = llvm::BasicBlock::Create("condtrue", gIR->topfunc(), oldend);
@@ -2115,10 +2126,10 @@
         LLValue* castfptr = DtoBitCast(fd->ir.irFunc->func, fptr->getType()->getContainedType(0));
         DtoStore(castfptr, fptr);
 
-        return new DVarValue(type, lval, true);
+        return new DVarValue(type, lval);
 
     } else if(fd->tok == TOKfunction) {
-        return new DVarValue(type, fd->ir.irFunc->func, false);
+        return new DImValue(type, fd->ir.irFunc->func);
     }
 
     assert(0 && "fd->tok must be TOKfunction or TOKdelegate");
@@ -2159,7 +2170,7 @@
         LLValue* elemAddr = DtoGEPi(dstMem,0,i,"tmp",p->scopebb());
 
         // emulate assignment
-        DVarValue* vv = new DVarValue(expr->type, elemAddr, true);
+        DVarValue* vv = new DVarValue(expr->type, elemAddr);
         DValue* e = expr->toElem(p);
         DtoAssign(loc, vv, e);
     }
@@ -2248,7 +2259,7 @@
 
         Logger::cout() << "getting index " << j << " of " << *sptr << '\n';
         LLValue* arrptr = DtoGEPi(sptr,0,j);
-        DValue* darrptr = new DVarValue(vx->type, arrptr, true);
+        DValue* darrptr = new DVarValue(vx->type, arrptr);
 
         DValue* ve = vx->toElem(p);
         DtoAssign(loc, darrptr, ve);
@@ -2324,7 +2335,7 @@
 
     // it should be possible to avoid the temporary in some cases
     LLValue* tmp = DtoAlloca(aalltype,"aaliteral");
-    DValue* aa = new DVarValue(type, tmp, true);
+    DValue* aa = new DVarValue(type, tmp);
     DtoStore(LLConstant::getNullValue(aalltype), tmp);
 
     const size_t n = keys->dim;
--- a/gen/tollvm.cpp	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/tollvm.cpp	Tue Sep 09 16:49:47 2008 -0700
@@ -25,14 +25,14 @@
 {
     Type* typ = type->toBasetype();
     TY t = typ->ty;
-    return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
+    return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray);
 }
 
 bool DtoIsReturnedInArg(Type* type)
 {
     Type* typ = type->toBasetype();
     TY t = typ->ty;
-    return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
+    return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray);
 }
 
 unsigned DtoShouldExtend(Type* type)
@@ -541,15 +541,6 @@
     //st->setVolatile(gIR->func()->inVolatile);
 }
 
-bool DtoCanLoad(LLValue* ptr)
-{
-    if (isaPointer(ptr->getType())) {
-        const LLType* data = ptr->getType()->getContainedType(0);
-        return data->isFirstClassType() && !(isaStruct(data) || isaArray(data));
-    }
-    return false;
-}
-
 //////////////////////////////////////////////////////////////////////////////////////////
 
 LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name)
@@ -770,3 +761,12 @@
     gIR->module->addTypeName("ModuleReference", st);
     return st;
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+LLValue* DtoAggrPair(const LLType* type, LLValue* V1, LLValue* V2, const char* name)
+{
+    LLValue* res = llvm::UndefValue::get(type);
+    res = gIR->ir->CreateInsertValue(res, V1, 0, "tmp");
+    return gIR->ir->CreateInsertValue(res, V2, 1, name?name:"tmp");
+}
--- a/gen/tollvm.h	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/tollvm.h	Tue Sep 09 16:49:47 2008 -0700
@@ -60,7 +60,6 @@
 LLConstant* DtoConstBool(bool);
 
 // llvm wrappers
-bool DtoCanLoad(LLValue* ptr);
 LLValue* DtoLoad(LLValue* src, const char* name=0);
 void DtoStore(LLValue* src, LLValue* dst);
 LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name=0);
@@ -93,6 +92,9 @@
 unsigned char getABITypeAlign(const LLType* t);
 unsigned char getPrefTypeAlign(const LLType* t);
 
+// pair type helpers
+LLValue* DtoAggrPair(const LLType* type, LLValue* V1, LLValue* V2, const char* name = 0);
+
 /**
  * Generates a call to llvm.memset.i32 (or i64 depending on architecture).
  * @param dst Destination memory.
--- a/tests/mini/complex1.d	Mon Sep 08 20:38:55 2008 +0200
+++ b/tests/mini/complex1.d	Tue Sep 09 16:49:47 2008 -0700
@@ -7,12 +7,8 @@
     cfloat cf3 = func();
     auto c1 = cf1 + cf2;
     auto c2 = cf2 - cf3;
-    {
     auto c3 = cf1 * cf3;
-    {
     auto c4 = cf2 / cf3;
-    }
-    }
 }
 
 cfloat func()
--- a/tests/mini/complex2.d	Mon Sep 08 20:38:55 2008 +0200
+++ b/tests/mini/complex2.d	Tue Sep 09 16:49:47 2008 -0700
@@ -4,11 +4,7 @@
 {
     cdouble c = 3.0 + 0i;
     cdouble d = 2.0 + 0i;
-    {
-        cdouble c1 = c + 3.0;
-        cdouble c2 = c - 3.0i;
-    }
-    {
-        cdouble c1 = c / 2.0;
-    }
+    cdouble c1 = c + 3.0;
+    cdouble c2 = c - 3.0i;
+    cdouble c3 = c / 2.0;
 }
--- a/tests/mini/complex3.d	Mon Sep 08 20:38:55 2008 +0200
+++ b/tests/mini/complex3.d	Tue Sep 09 16:49:47 2008 -0700
@@ -5,5 +5,5 @@
     cfloat c1 = 1f + 0i;
     cfloat c2 = 0f + 0i;
     c2 += 1f + 0i;
-    //assert(c1 == c2);
+    assert(c1 == c2);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/complex4.d	Tue Sep 09 16:49:47 2008 -0700
@@ -0,0 +1,8 @@
+module complex4;
+
+void main()
+{
+    cfloat c = 2f + 3fi;
+    float r = cast(float)c;
+    ifloat i = cast(ifloat)c;
+}
\ No newline at end of file