changeset 1151:3cf0066e6faf

- Versioned Expresssion::toElem with #if IN_DMD/IN_LLVM. - Eliminated the DLRValue DValue. - Implemented proactive handling of l-value CastExpS. - Minor tweak in runtime memory.d .
author Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
date Sat, 28 Mar 2009 05:00:43 +0100
parents 2a687353c84d
children 521dd1626d76
files dmd/expression.c dmd/expression.h gen/complex.cpp gen/dvalue.cpp gen/dvalue.h gen/functions.cpp gen/llvmhelpers.cpp gen/llvmhelpers.h gen/structs.cpp gen/structs.h gen/toir.cpp runtime/internal/memory.d
diffstat 12 files changed, 595 insertions(+), 483 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/expression.c	Fri Mar 27 23:24:47 2009 +0100
+++ b/dmd/expression.c	Sat Mar 28 05:00:43 2009 +0100
@@ -887,6 +887,10 @@
     this->op = op;
     this->size = size;
     type = NULL;
+
+#if IN_LLVM
+    cachedLvalue = NULL;
+#endif
 }
 
 Expression *Expression::syntaxCopy()
--- a/dmd/expression.h	Fri Mar 27 23:24:47 2009 +0100
+++ b/dmd/expression.h	Sat Mar 28 05:00:43 2009 +0100
@@ -46,10 +46,10 @@
 
 enum TOK;
 
+#if IN_DMD
 // Back end
 struct IRState;
 
-#if IN_DMD
 struct dt_t;
 struct elem;
 struct Symbol;		// back end symbol
@@ -60,11 +60,9 @@
 #endif
 
 #if IN_LLVM
+struct IRState;
 struct DValue;
-typedef DValue elem;
-
-namespace llvm
-{
+namespace llvm {
     class Constant;
     class ConstantInt;
 }
@@ -160,13 +158,18 @@
     virtual void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
     virtual Expression *buildArrayLoop(Arguments *fparams);
 
+#if IN_DMD
     // Back end
     virtual elem *toElem(IRState *irs);
-#if IN_DMD
     virtual dt_t **toDt(dt_t **pdt);
-#elif IN_LLVM
-    // LDC
+#endif
+
+#if IN_LLVM
+    virtual DValue* toElem(IRState* irs);
     virtual llvm::Constant *toConstElem(IRState *irs);
+    virtual void cacheLvalue(IRState* irs);
+
+    llvm::Value* cachedLvalue;
 #endif
 };
 
@@ -191,12 +194,12 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     void toMangleBuffer(OutBuffer *buf);
     Expression *toLvalue(Scope *sc, Expression *e);
+#if IN_DMD
     elem *toElem(IRState *irs);
-#if IN_DMD
     dt_t **toDt(dt_t **pdt);
 #elif IN_LLVM
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
 #endif
 };
 
@@ -219,12 +222,12 @@
     int isBool(int result);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     void toMangleBuffer(OutBuffer *buf);
+#if IN_DMD
     elem *toElem(IRState *irs);
-#if IN_DMD
     dt_t **toDt(dt_t **pdt);
 #elif IN_LLVM
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
 #endif
 };
 
@@ -250,12 +253,12 @@
 #ifdef _DH
     OutBuffer hexp;
 #endif
+#if IN_DMD
     elem *toElem(IRState *irs);
-#if IN_DMD
     dt_t **toDt(dt_t **pdt);
 #elif IN_LLVM
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
 #endif
 };
 
@@ -305,7 +308,13 @@
     Expression *doInline(InlineDoState *ids);
     //Expression *inlineScan(InlineScanState *iss);
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct SuperExp : ThisExp
@@ -332,12 +341,12 @@
     MATCH implicitConvTo(Type *t);
     Expression *castTo(Scope *sc, Type *t);
     Expression *interpret(InterState *istate);
+#if IN_DMD
     elem *toElem(IRState *irs);
-#if IN_DMD
     dt_t **toDt(dt_t **pdt);
 #elif IN_LLVM
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
 #endif
 };
 
@@ -365,12 +374,12 @@
     unsigned charAt(size_t i);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     void toMangleBuffer(OutBuffer *buf);
+#if IN_DMD
     elem *toElem(IRState *irs);
-#if IN_DMD
     dt_t **toDt(dt_t **pdt);
 #elif IN_LLVM
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
 #endif
 };
 
@@ -392,11 +401,17 @@
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
     Expression *castTo(Scope *sc, Type *t);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
     Expression *inlineScan(InlineScanState *iss);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct ArrayLiteralExp : Expression
@@ -409,7 +424,6 @@
     Expression *syntaxCopy();
     Expression *semantic(Scope *sc);
     int isBool(int result);
-    elem *toElem(IRState *irs);
     int checkSideEffect(int flag);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     void toMangleBuffer(OutBuffer *buf);
@@ -418,16 +432,18 @@
     Expression *interpret(InterState *istate);
     MATCH implicitConvTo(Type *t);
     Expression *castTo(Scope *sc, Type *t);
-#if IN_DMD
-    dt_t **toDt(dt_t **pdt);
-#elif IN_LLVM
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-#endif
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
     Expression *inlineScan(InlineScanState *iss);
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+    dt_t **toDt(dt_t **pdt);
+#elif IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
 };
 
 struct AssocArrayLiteralExp : Expression
@@ -440,7 +456,9 @@
     Expression *syntaxCopy();
     Expression *semantic(Scope *sc);
     int isBool(int result);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
     int checkSideEffect(int flag);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     void toMangleBuffer(OutBuffer *buf);
@@ -453,9 +471,10 @@
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
     Expression *inlineScan(InlineScanState *iss);
+
 #if IN_LLVM
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
 #endif
 };
 
@@ -477,25 +496,25 @@
     Expression *semantic(Scope *sc);
     Expression *getField(Type *type, unsigned offset);
     int getFieldIndex(Type *type, unsigned offset);
-    elem *toElem(IRState *irs);
     int checkSideEffect(int flag);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     void toMangleBuffer(OutBuffer *buf);
     void scanForNestedRef(Scope *sc);
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
-#if IN_DMD
-    dt_t **toDt(dt_t **pdt);
-#elif IN_LLVM
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-#endif
     Expression *toLvalue(Scope *sc, Expression *e);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
     Expression *inlineScan(InlineScanState *iss);
-    
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+    dt_t **toDt(dt_t **pdt);
+#elif IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
 };
 
 struct TypeDotIdExp : Expression
@@ -506,7 +525,13 @@
     Expression *syntaxCopy();
     Expression *semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct TypeExp : Expression
@@ -516,7 +541,13 @@
     Expression *semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     Expression *optimize(int result);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct ScopeExp : Expression
@@ -526,8 +557,14 @@
     ScopeExp(Loc loc, ScopeDsymbol *sds);
     Expression *syntaxCopy();
     Expression *semantic(Scope *sc);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct TemplateExp : Expression
@@ -556,7 +593,9 @@
 	Type *newtype, Expressions *arguments);
     Expression *syntaxCopy();
     Expression *semantic(Scope *sc);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
     int checkSideEffect(int flag);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     void scanForNestedRef(Scope *sc);
@@ -564,6 +603,10 @@
     //int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
     //Expression *inlineScan(InlineScanState *iss);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct NewAnonClassExp : Expression
@@ -601,10 +644,14 @@
     Expression *castTo(Scope *sc, Type *t);
     void scanForNestedRef(Scope *sc);
 
+#if IN_DMD
     elem *toElem(IRState *irs);
-#if IN_DMD
     dt_t **toDt(dt_t **pdt);
 #endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 // Variable
@@ -624,18 +671,21 @@
     void checkEscape();
     Expression *toLvalue(Scope *sc, Expression *e);
     Expression *modifiableLvalue(Scope *sc, Expression *e);
+#if IN_DMD
     elem *toElem(IRState *irs);
-#if IN_DMD
     dt_t **toDt(dt_t **pdt);
-#elif IN_LLVM
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
 #endif
     void scanForNestedRef(Scope *sc);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
     //Expression *inlineScan(InlineScanState *iss);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+    void cacheLvalue(IRState* irs);
+#endif
 };
 
 #if DMDV2
@@ -663,14 +713,18 @@
     void scanForNestedRef(Scope *sc);
     char *toChars();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
 
     int inlineCost(InlineCostState *ics);
     //Expression *doInline(InlineDoState *ids);
     //Expression *inlineScan(InlineScanState *iss);
 
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
 };
 
 // Declaration of a symbol
@@ -685,12 +739,18 @@
     Expression *interpret(InterState *istate);
     int checkSideEffect(int flag);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
     void scanForNestedRef(Scope *sc);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
     Expression *inlineScan(InlineScanState *iss);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct TypeidExp : Expression
@@ -723,7 +783,13 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     int checkSideEffect(int flag);
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct IsExp : Expression
@@ -796,7 +862,9 @@
 
     Expression *op_overload(Scope *sc);
 
+#if IN_DMD
     elem *toElemBin(IRState *irs, int op);
+#endif
 };
 
 struct BinAssignExp : BinExp
@@ -836,7 +904,13 @@
     Expression *doInline(InlineDoState *ids);
     Expression *inlineScan(InlineScanState *iss);
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct DotIdExp : UnaExp
@@ -869,7 +943,14 @@
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     void dump(int indent);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    void cacheLvalue(IRState* irs);
+#endif
 };
 
 struct DotTemplateInstanceExp : UnaExp
@@ -895,7 +976,13 @@
     void dump(int indent);
 
     int inlineCost(InlineCostState *ics);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct DotTypeExp : UnaExp
@@ -905,7 +992,13 @@
     DotTypeExp(Loc loc, Expression *e, Dsymbol *sym);
     Expression *semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct CallExp : UnaExp
@@ -924,25 +1017,36 @@
     int checkSideEffect(int flag);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     void dump(int indent);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
     void scanForNestedRef(Scope *sc);
     Expression *toLvalue(Scope *sc, Expression *e);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
     Expression *inlineScan(InlineScanState *iss);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct AddrExp : UnaExp
 {
     AddrExp(Loc loc, Expression *e);
     Expression *semantic(Scope *sc);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
     MATCH implicitConvTo(Type *t);
     Expression *castTo(Scope *sc, Type *t);
     Expression *optimize(int result);
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
 };
 
 struct PtrExp : UnaExp
@@ -952,9 +1056,16 @@
     Expression *semantic(Scope *sc);
     Expression *toLvalue(Scope *sc, Expression *e);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    void cacheLvalue(IRState* irs);
+#endif
 };
 
 struct NegExp : UnaExp
@@ -969,7 +1080,13 @@
     // For operator overloading
     Identifier *opId();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct UAddExp : UnaExp
@@ -993,7 +1110,13 @@
     // For operator overloading
     Identifier *opId();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct NotExp : UnaExp
@@ -1003,7 +1126,13 @@
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
     int isBit();
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct BoolExp : UnaExp
@@ -1013,7 +1142,13 @@
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
     int isBit();
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct DeleteExp : UnaExp
@@ -1023,7 +1158,13 @@
     Expression *checkToBoolean();
     int checkSideEffect(int flag);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct CastExp : UnaExp
@@ -1039,13 +1180,17 @@
     int checkSideEffect(int flag);
     void checkEscape();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
 
     // For operator overloading
     Identifier *opId();
 
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
 };
 
 
@@ -1065,7 +1210,9 @@
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
     void dump(int indent);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
     void scanForNestedRef(Scope *sc);
     void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
     Expression *buildArrayLoop(Arguments *fparams);
@@ -1074,8 +1221,10 @@
     Expression *doInline(InlineDoState *ids);
     Expression *inlineScan(InlineScanState *iss);
 
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
 };
 
 struct ArrayLengthExp : UnaExp
@@ -1085,7 +1234,13 @@
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 // e1[a0,a1,a2,a3,...]
@@ -1128,7 +1283,13 @@
     int checkSideEffect(int flag);
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct IndexExp : BinExp
@@ -1146,9 +1307,13 @@
     Expression *doInline(InlineDoState *ids);
     void scanForNestedRef(Scope *sc);
 
+#if IN_DMD
     elem *toElem(IRState *irs);
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
+#elif IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+    void cacheLvalue(IRState* irs);
+#endif
 };
 
 /* For both i++ and i--
@@ -1160,7 +1325,13 @@
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     Identifier *opId();    // For operator overloading
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct AssignExp : BinExp
@@ -1173,9 +1344,23 @@
     Identifier *opId();    // For operator overloading
     void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
     Expression *buildArrayLoop(Arguments *fparams);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
+#if IN_DMD
+#define ASSIGNEXP_TOELEM    elem *toElem(IRState *irs);
+#elif IN_LLVM
+#define ASSIGNEXP_TOELEM    DValue* toElem(IRState *irs);
+#else
+#define ASSIGNEXP_TOELEM
+#endif
+
 #define ASSIGNEXP(op)	\
 struct op##AssignExp : BinExp					\
 {								\
@@ -1187,7 +1372,7 @@
 								\
     Identifier *opId();    /* For operator overloading */	\
 								\
-    elem *toElem(IRState *irs);					\
+    ASSIGNEXP_TOELEM					        \
 };
 
 #define X(a) a
@@ -1210,6 +1395,7 @@
 
 #undef X
 #undef ASSIGNEXP
+#undef ASSIGNEXP_TOELEM
 
 struct AddExp : BinExp
 {
@@ -1225,7 +1411,13 @@
     Identifier *opId();
     Identifier *opId_r();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct MinExp : BinExp
@@ -1241,7 +1433,13 @@
     Identifier *opId();
     Identifier *opId_r();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct CatExp : BinExp
@@ -1255,7 +1453,13 @@
     Identifier *opId();
     Identifier *opId_r();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct MulExp : BinExp
@@ -1272,7 +1476,13 @@
     Identifier *opId();
     Identifier *opId_r();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct DivExp : BinExp
@@ -1288,7 +1498,13 @@
     Identifier *opId();
     Identifier *opId_r();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct ModExp : BinExp
@@ -1304,7 +1520,13 @@
     Identifier *opId();
     Identifier *opId_r();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct ShlExp : BinExp
@@ -1318,7 +1540,13 @@
     Identifier *opId();
     Identifier *opId_r();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct ShrExp : BinExp
@@ -1332,7 +1560,13 @@
     Identifier *opId();
     Identifier *opId_r();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct UshrExp : BinExp
@@ -1346,7 +1580,13 @@
     Identifier *opId();
     Identifier *opId_r();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct AndExp : BinExp
@@ -1363,7 +1603,13 @@
     Identifier *opId();
     Identifier *opId_r();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct OrExp : BinExp
@@ -1380,7 +1626,13 @@
     Identifier *opId();
     Identifier *opId_r();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct XorExp : BinExp
@@ -1397,7 +1649,13 @@
     Identifier *opId();
     Identifier *opId_r();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct OrOrExp : BinExp
@@ -1409,7 +1667,13 @@
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
     int checkSideEffect(int flag);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct AndAndExp : BinExp
@@ -1421,7 +1685,13 @@
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
     int checkSideEffect(int flag);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct CmpExp : BinExp
@@ -1436,7 +1706,13 @@
     int isCommutative();
     Identifier *opId();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct InExp : BinExp
@@ -1449,13 +1725,25 @@
     Identifier *opId();
     Identifier *opId_r();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 struct RemoveExp : BinExp
 {
     RemoveExp(Loc loc, Expression *e1, Expression *e2);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 // == and !=
@@ -1472,7 +1760,13 @@
     int isCommutative();
     Identifier *opId();
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 // === and !===
@@ -1484,7 +1778,13 @@
     int isBit();
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 /****************************************************************/
@@ -1512,7 +1812,13 @@
     Expression *doInline(InlineDoState *ids);
     Expression *inlineScan(InlineScanState *iss);
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
 };
 
 #if DMDV2
@@ -1557,8 +1863,12 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     Expression *toLvalue(Scope *sc, Expression *e);
 
+#if IN_DMD
     elem *toElem(IRState *irs);
+#elif IN_LLVM
+    DValue* toElem(IRState* irs);
     llvm::Constant *toConstElem(IRState *irs);
+#endif
 };
 
 #endif
--- a/gen/complex.cpp	Fri Mar 27 23:24:47 2009 +0100
+++ b/gen/complex.cpp	Sat Mar 28 05:00:43 2009 +0100
@@ -429,16 +429,7 @@
         }
 
         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;
-        }
-
-        // unfortunately at this point, the cast value can show up as the lvalue for += and similar expressions.
-        // so we need to maintain the storage
-        return new DLRValue(val, rval);
+        return new DImValue(_to, pair);
     }
     else if (to->isimaginary()) {
         // FIXME: this loads both values, even when we only need one
--- a/gen/dvalue.cpp	Fri Mar 27 23:24:47 2009 +0100
+++ b/gen/dvalue.cpp	Sat Mar 28 05:00:43 2009 +0100
@@ -78,15 +78,3 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////////////////
-
-Type*& DLRValue::getLType()
-{
-    if (DLRValue* lr = lvalue->isLRValue())
-    {
-        return lr->getLType();
-    }
-    else
-    {
-        return lvalue->getType();
-    }
-}
--- a/gen/dvalue.h	Fri Mar 27 23:24:47 2009 +0100
+++ b/gen/dvalue.h	Sat Mar 28 05:00:43 2009 +0100
@@ -29,7 +29,6 @@
 struct DFieldValue;
 struct DFuncValue;
 struct DSliceValue;
-struct DLRValue;
 
 // base class for d-values
 struct DValue : Object
@@ -48,7 +47,6 @@
     virtual DFieldValue* isField() { return NULL; }
     virtual DSliceValue* isSlice() { return NULL; }
     virtual DFuncValue* isFunc() { return NULL; }
-    virtual DLRValue* isLRValue() { return NULL; }
 
 protected:
     DValue() {}
@@ -147,25 +145,4 @@
     virtual DFuncValue* isFunc() { return this; }
 };
 
-// l-value and r-value pair d-value
-struct DLRValue : DValue
-{
-    DValue* lvalue;
-    DValue* rvalue;
-
-    DLRValue(DValue* lval, DValue* rval) {
-        lvalue = lval;
-        rvalue = rval;
-    }
-
-    virtual bool isLVal() { return true; }
-    virtual LLValue* getLVal() { return lvalue->isLVal() ? lvalue->getLVal() : lvalue->getRVal(); }
-    virtual LLValue* getRVal() { return rvalue->getRVal(); }
-
-    Type*& getLType();
-    Type*& getRType() { return rvalue->getType(); }
-    virtual Type*& getType() { return getRType(); }
-    virtual DLRValue* isLRValue() { return this; }
-};
-
 #endif // LDC_GEN_DVALUE_H
--- a/gen/functions.cpp	Fri Mar 27 23:24:47 2009 +0100
+++ b/gen/functions.cpp	Sat Mar 28 05:00:43 2009 +0100
@@ -940,7 +940,7 @@
     // ref/out arg
     if (fnarg && (fnarg->storageClass & (STCref | STCout)))
     {
-        if (arg->isVar() || arg->isLRValue())
+        if (arg->isVar())
             arg = new DImValue(argexp->type, arg->getLVal());
         else
             arg = new DImValue(argexp->type, arg->getRVal());
--- a/gen/llvmhelpers.cpp	Fri Mar 27 23:24:47 2009 +0100
+++ b/gen/llvmhelpers.cpp	Sat Mar 28 05:00:43 2009 +0100
@@ -472,15 +472,9 @@
         DtoStore(r, l);
     }
     else if (t->iscomplex()) {
-        LLValue* dst;
-        if (DLRValue* lr = lhs->isLRValue()) {
-            dst = lr->getLVal();
-            rhs = DtoCastComplex(loc, rhs, lr->getLType());
-        }
-        else {
-            dst = lhs->getLVal();
-        }
-        DtoStore(rhs->getRVal(), dst);
+        LLValue* dst = lhs->getLVal();
+        LLValue* src = DtoCast(loc, rhs, lhs->getType())->getRVal();
+        DtoStore(src, dst);
     }
     else {
         LLValue* l = lhs->getLVal();
@@ -489,14 +483,7 @@
             Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n';
         const LLType* lit = l->getType()->getContainedType(0);
         if (r->getType() != lit) {
-            // handle lvalue cast assignments
-            if (DLRValue* lr = lhs->isLRValue()) {
-                Logger::println("lvalue cast!");
-                r = DtoCast(loc, rhs, lr->getLType())->getRVal();
-            }
-            else {
-                r = DtoCast(loc, rhs, lhs->getType())->getRVal();
-            }
+            r = DtoCast(loc, rhs, lhs->getType())->getRVal();
             if (Logger::enabled())
                 Logger::cout() << "really assign\nlhs: " << *l << "rhs: " << *r << '\n';
             assert(r->getType() == l->getType()->getContainedType(0));
@@ -723,7 +710,13 @@
 DValue* DtoCast(Loc& loc, DValue* val, Type* to)
 {
     Type* fromtype = val->getType()->toBasetype();
+    Type* totype = to->toBasetype();
+    if (fromtype->equals(totype))
+        return val;
+
     Logger::println("Casting from '%s' to '%s'", fromtype->toChars(), to->toChars());
+    LOG_SCOPE;
+
     if (fromtype->isintegral()) {
         return DtoCastInt(loc, val, to);
     }
@@ -864,78 +857,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoDeclareDsymbol(Dsymbol* dsym)
-{
-    DtoResolveDsymbol(dsym);
-
-    if (StructDeclaration* sd = dsym->isStructDeclaration()) {
-        DtoDeclareStruct(sd);
-    }
-    else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
-        DtoDeclareClass(cd);
-    }
-    else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
-        DtoDeclareFunction(fd);
-    }
-    else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
-        DtoDeclareTypeInfo(fd);
-    }
-    else {
-    error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
-    assert(0 && "unsupported dsymbol for DtoDeclareDsymbol");
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoConstInitDsymbol(Dsymbol* dsym)
-{
-    DtoDeclareDsymbol(dsym);
-
-    if (StructDeclaration* sd = dsym->isStructDeclaration()) {
-        DtoConstInitStruct(sd);
-    }
-    else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
-        DtoConstInitClass(cd);
-    }
-    else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
-        DtoConstInitTypeInfo(fd);
-    }
-    else if (VarDeclaration* vd = dsym->isVarDeclaration()) {
-        DtoConstInitGlobal(vd);
-    }
-    else {
-    error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
-    assert(0 && "unsupported dsymbol for DtoConstInitDsymbol");
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoDefineDsymbol(Dsymbol* dsym)
-{
-    DtoConstInitDsymbol(dsym);
-
-    if (StructDeclaration* sd = dsym->isStructDeclaration()) {
-        DtoDefineStruct(sd);
-    }
-    else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
-        DtoDefineClass(cd);
-    }
-    else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
-        Type::sir->addFunctionBody(fd->ir.irFunc);
-    }
-    else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
-        DtoDefineTypeInfo(fd);
-    }
-    else {
-    error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
-    assert(0 && "unsupported dsymbol for DtoDefineDsymbol");
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 void DtoConstInitGlobal(VarDeclaration* vd)
 {
     vd->codegen(Type::sir);
--- a/gen/llvmhelpers.h	Fri Mar 27 23:24:47 2009 +0100
+++ b/gen/llvmhelpers.h	Sat Mar 28 05:00:43 2009 +0100
@@ -52,27 +52,29 @@
 // the scope created by the 'target' statement.
 void DtoEnclosingHandlers(Loc loc, Statement* target);
 
-// enters a critical section
+/// Enters a critical section.
 void DtoEnterCritical(LLValue* g);
-// leaves a critical section
+/// leaves a critical section.
 void DtoLeaveCritical(LLValue* g);
 
-// enters a monitor lock
+/// Enters a monitor lock.
 void DtoEnterMonitor(LLValue* v);
-// leaves a monitor lock
+/// Leaves a monitor lock.
 void DtoLeaveMonitor(LLValue* v);
 
 // nested variable and context helpers
 
-// gets the context value for a call to a nested function or newing a class, with arbitrary nesting
+/// Gets the context value for a call to a nested function or newing a nested
+/// class with arbitrary nesting.
 LLValue* DtoNestedContext(Loc loc, Dsymbol* sym);
-// gets the dvalue of a nested variable with arbitrary nesting
+
+/// Gets the DValue of a nested variable with arbitrary nesting.
 DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd);
 
 // basic operations
 void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs);
 
-// create a null dvalue
+/// Create a null DValue.
 DValue* DtoNullValue(Type* t);
 
 // casts
@@ -88,11 +90,11 @@
 // is template instance check, returns module where instantiated
 TemplateInstance* DtoIsTemplateInstance(Dsymbol* s);
 
-// these are all basically drivers for the codegeneration called by the main loop
+/// Generate code for the symbol.
+/// Dispatches as appropriate.
 void DtoResolveDsymbol(Dsymbol* dsym);
-void DtoDeclareDsymbol(Dsymbol* dsym);
-void DtoDefineDsymbol(Dsymbol* dsym);
-void DtoConstInitDsymbol(Dsymbol* dsym);
+
+/// Generates the constant initializer for a global variable.
 void DtoConstInitGlobal(VarDeclaration* vd);
 
 // declaration inside a declarationexp
@@ -122,16 +124,16 @@
 // target stuff
 void findDefaultTarget();
 
-// fixup an overloaded intrinsic name string
+/// Fixup an overloaded intrinsic name string.
 void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, std::string& name);
 
-// return true if the symbol should be defined in the current module, not just declared
+/// Returns true if the symbol should be defined in the current module, not just declared.
 bool mustDefineSymbol(Dsymbol* s);
 
-// returns true if the symbol needs template linkage, or just external
+/// Returns true if the symbol needs template linkage, or just external.
 bool needsTemplateLinkage(Dsymbol* s);
 
-// returns true if there is any unaligned type inside the aggregate
+/// Returns true if there is any unaligned type inside the aggregate.
 bool hasUnalignedFields(Type* t);
 
 ////////////////////////////////////////////
--- a/gen/structs.cpp	Fri Mar 27 23:24:47 2009 +0100
+++ b/gen/structs.cpp	Sat Mar 28 05:00:43 2009 +0100
@@ -487,6 +487,12 @@
     return val;
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
+
+static void DtoDeclareStruct(StructDeclaration* sd);
+static void DtoConstInitStruct(StructDeclaration* sd);
+static void DtoDefineStruct(StructDeclaration* sd);
+
 void DtoResolveStruct(StructDeclaration* sd)
 {
     // don't do anything if already been here
@@ -584,7 +590,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoDeclareStruct(StructDeclaration* sd)
+static void DtoDeclareStruct(StructDeclaration* sd)
 {
     DtoResolveStruct(sd);
 
@@ -603,7 +609,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoConstInitStruct(StructDeclaration* sd)
+static void DtoConstInitStruct(StructDeclaration* sd)
 {
     DtoDeclareStruct(sd);
 
@@ -654,7 +660,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoDefineStruct(StructDeclaration* sd)
+static void DtoDefineStruct(StructDeclaration* sd)
 {
     DtoConstInitStruct(sd);
 
--- a/gen/structs.h	Fri Mar 27 23:24:47 2009 +0100
+++ b/gen/structs.h	Sat Mar 28 05:00:43 2009 +0100
@@ -3,35 +3,19 @@
 
 struct StructInitializer;
 
-LLConstant* DtoConstStructInitializer(StructInitializer* si);
-std::vector<llvm::Value*> DtoStructLiteralValues(const StructDeclaration* sd, const std::vector<llvm::Value*>& inits);
-
-/**
- * Resolves the llvm type for a struct
- */
+/// Generate code for the struct.
 void DtoResolveStruct(StructDeclaration* sd);
 
-/**
- * Provides the llvm declaration for a struct
- */
-void DtoDeclareStruct(StructDeclaration* sd);
+/// Build constant struct initializer.
+LLConstant* DtoConstStructInitializer(StructInitializer* si);
 
-/**
- * Constructs the constant default initializer a struct
- */
-void DtoConstInitStruct(StructDeclaration* sd);
+/// Build values for a struct literal.
+std::vector<llvm::Value*> DtoStructLiteralValues(const StructDeclaration* sd, const std::vector<llvm::Value*>& inits);
 
-/**
- * Provides the llvm definition for a struct
- */
-void DtoDefineStruct(StructDeclaration* sd);
-
-/**
- * Returns a boolean=true if the two structs are equal
- */
+/// Returns a boolean=true if the two structs are equal.
 LLValue* DtoStructEquals(TOK op, DValue* lhs, DValue* rhs);
 
-// index a struct one level
+/// index a struct one level
 LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd);
 
 #endif
--- a/gen/toir.cpp	Fri Mar 27 23:24:47 2009 +0100
+++ b/gen/toir.cpp	Sat Mar 28 05:00:43 2009 +0100
@@ -41,6 +41,14 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+void Expression::cacheLvalue(IRState* irs)
+{
+    error("expression %s does not mask any l-value", toChars());
+    fatal();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 DValue* DeclarationExp::toElem(IRState* p)
 {
     Logger::print("DeclarationExp::toElem: %s | T=%s\n", toChars(), type->toChars());
@@ -51,13 +59,27 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+void VarExp::cacheLvalue(IRState* p)
+{
+    Logger::println("Caching l-value of %s", toChars());
+    LOG_SCOPE;
+    cachedLvalue = toElem(p)->getLVal();
+}
+
 DValue* VarExp::toElem(IRState* p)
 {
-    Logger::print("VarExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("VarExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     assert(var);
 
+    if (cachedLvalue)
+    {
+        LLValue* V = cachedLvalue;
+        cachedLvalue = NULL;
+        return new DVarValue(type, V);
+    }
+
     if (VarDeclaration* vd = var->isVarDeclaration())
     {
         Logger::println("VarDeclaration ' %s ' of type ' %s '", vd->toChars(), vd->type->toChars());
@@ -204,7 +226,7 @@
 
 LLConstant* VarExp::toConstElem(IRState* p)
 {
-    Logger::print("VarExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("VarExp::toConstElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     if (StaticStructInitDeclaration* sdecl = var->isStaticStructInitDeclaration())
@@ -244,7 +266,7 @@
 
 DValue* IntegerExp::toElem(IRState* p)
 {
-    Logger::print("IntegerExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("IntegerExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     LLConstant* c = toConstElem(p);
     return new DConstValue(type, c);
@@ -254,7 +276,7 @@
 
 LLConstant* IntegerExp::toConstElem(IRState* p)
 {
-    Logger::print("IntegerExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("IntegerExp::toConstElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     const LLType* t = DtoType(type);
     if (isaPointer(t)) {
@@ -274,7 +296,7 @@
 
 DValue* RealExp::toElem(IRState* p)
 {
-    Logger::print("RealExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("RealExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     LLConstant* c = toConstElem(p);
     return new DConstValue(type, c);
@@ -284,7 +306,7 @@
 
 LLConstant* RealExp::toConstElem(IRState* p)
 {
-    Logger::print("RealExp::toConstElem: %s | %s | %LX\n", toChars(), type->toChars(), value);
+    Logger::print("RealExp::toConstElem: %s @ %s | %LX\n", toChars(), type->toChars(), value);
     LOG_SCOPE;
     Type* t = type->toBasetype();
     return DtoConstFP(t, value);
@@ -322,7 +344,7 @@
 
 DValue* ComplexExp::toElem(IRState* p)
 {
-    Logger::print("ComplexExp::toElem(): %s | %s\n", toChars(), type->toChars());
+    Logger::print("ComplexExp::toElem(): %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     LLConstant* c = toConstElem(p);
     LLValue* res;
@@ -350,7 +372,7 @@
 
 LLConstant* ComplexExp::toConstElem(IRState* p)
 {
-    Logger::print("ComplexExp::toConstElem(): %s | %s\n", toChars(), type->toChars());
+    Logger::print("ComplexExp::toConstElem(): %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     return DtoConstComplex(type, value.re, value.im);
 }
@@ -359,7 +381,7 @@
 
 DValue* StringExp::toElem(IRState* p)
 {
-    Logger::print("StringExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("StringExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     Type* dtype = type->toBasetype();
@@ -426,7 +448,7 @@
 
 LLConstant* StringExp::toConstElem(IRState* p)
 {
-    Logger::print("StringExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("StringExp::toConstElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     Type* t = type->toBasetype();
@@ -524,9 +546,54 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+/// Finds the proper lvalue for a binassign expressions.
+/// Makes sure the given LHS expression is only evaluated once.
+static Expression* findLvalue(IRState* irs, Expression* exp)
+{
+    Expression* e = exp;
+
+    // skip past any casts
+    while(e->op == TOKcast)
+        e = ((CastExp*)e)->e1;
+
+    // cache lvalue and return
+    e->cacheLvalue(irs);
+    return e;
+}
+
+#define BIN_ASSIGN(X) \
+DValue* X##AssignExp::toElem(IRState* p) \
+{ \
+    Logger::print(#X"AssignExp::toElem: %s @ %s\n", toChars(), type->toChars()); \
+    LOG_SCOPE; \
+    X##Exp e3(loc, e1, e2); \
+    e3.type = e1->type; \
+    DValue* dst = findLvalue(p, e1)->toElem(p); \
+    DValue* res = e3.toElem(p); \
+    DValue* stval = DtoCast(loc, res, dst->getType()); \
+    DtoAssign(loc, dst, stval); \
+    return DtoCast(loc, res, type); \
+}
+
+BIN_ASSIGN(Add)
+BIN_ASSIGN(Min)
+BIN_ASSIGN(Mul)
+BIN_ASSIGN(Div)
+BIN_ASSIGN(Mod)
+BIN_ASSIGN(And)
+BIN_ASSIGN(Or)
+BIN_ASSIGN(Xor)
+BIN_ASSIGN(Shl)
+BIN_ASSIGN(Shr)
+BIN_ASSIGN(Ushr)
+
+#undef BIN_ASSIGN
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 DValue* AddExp::toElem(IRState* p)
 {
-    Logger::print("AddExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("AddExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* l = e1->toElem(p);
@@ -565,40 +632,9 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-DValue* AddAssignExp::toElem(IRState* p)
-{
-    Logger::print("AddAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    DValue* l = e1->toElem(p);
-    DValue* r = e2->toElem(p);
-
-    Type* t = type->toBasetype();
-
-    DValue* res;
-    if (e1->type->toBasetype()->ty == Tpointer) {
-        LLValue* gep = llvm::GetElementPtrInst::Create(l->getRVal(),r->getRVal(),"tmp",p->scopebb());
-        res = new DImValue(type, gep);
-    }
-    else if (t->iscomplex()) {
-        res = DtoComplexAdd(loc, e1->type, l, r);
-    }
-    else {
-        res = DtoBinAdd(l,r);
-    }
-    DtoAssign(loc, l, res);
-
-    if (res->getType() != type)
-        res = DtoCast(loc, res, type);
-
-    return res;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 DValue* MinExp::toElem(IRState* p)
 {
-    Logger::print("MinExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("MinExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* l = e1->toElem(p);
@@ -635,46 +671,9 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-DValue* MinAssignExp::toElem(IRState* p)
-{
-    Logger::print("MinAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    DValue* l = e1->toElem(p);
-    DValue* r = e2->toElem(p);
-
-    Type* t = type->toBasetype();
-
-    DValue* res;
-    if (e1->type->toBasetype()->ty == Tpointer) {
-        Logger::println("ptr");
-        LLValue* tmp = r->getRVal();
-        LLValue* zero = llvm::ConstantInt::get(tmp->getType(),0,false);
-        tmp = llvm::BinaryOperator::CreateSub(zero,tmp,"tmp",p->scopebb());
-        tmp = llvm::GetElementPtrInst::Create(l->getRVal(),tmp,"tmp",p->scopebb());
-        res = new DImValue(type, tmp);
-    }
-    else if (t->iscomplex()) {
-        Logger::println("complex");
-        res = DtoComplexSub(loc, type, l, r);
-    }
-    else {
-        Logger::println("basic");
-        res = DtoBinSub(l,r);
-    }
-    DtoAssign(loc, l, res);
-
-    if (res->getType() != type)
-        res = DtoCast(loc, res, type);
-
-    return res;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 DValue* MulExp::toElem(IRState* p)
 {
-    Logger::print("MulExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("MulExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* l = e1->toElem(p);
@@ -689,34 +688,9 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-DValue* MulAssignExp::toElem(IRState* p)
-{
-    Logger::print("MulAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    DValue* l = e1->toElem(p);
-    DValue* r = e2->toElem(p);
-
-    DValue* res;
-    if (type->iscomplex()) {
-        res = DtoComplexMul(loc, type, l, r);
-    }
-    else {
-        res = DtoBinMul(l->getType(), l, r);
-    }
-    DtoAssign(loc, l, res);
-
-    if (res->getType() != type)
-        res = DtoCast(loc, res, type);
-
-    return res;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 DValue* DivExp::toElem(IRState* p)
 {
-    Logger::print("DivExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("DivExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* l = e1->toElem(p);
@@ -731,34 +705,9 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-DValue* DivAssignExp::toElem(IRState* p)
-{
-    Logger::print("DivAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    DValue* l = e1->toElem(p);
-    DValue* r = e2->toElem(p);
-
-    DValue* res;
-    if (type->iscomplex()) {
-        res = DtoComplexDiv(loc, type, l, r);
-    }
-    else {
-        res = DtoBinDiv(l->getType(), l, r);
-    }
-    DtoAssign(loc, l, res);
-
-    if (res->getType() != type)
-        res = DtoCast(loc, res, type);
-
-    return res;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 DValue* ModExp::toElem(IRState* p)
 {
-    Logger::print("ModExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("ModExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* l = e1->toElem(p);
@@ -769,28 +718,9 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-DValue* ModAssignExp::toElem(IRState* p)
-{
-    Logger::print("ModAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    DValue* l = e1->toElem(p);
-    DValue* r = e2->toElem(p);
-
-    DValue* res = DtoBinRem(l->getType(), l, r);
-    DtoAssign(loc, l, res);
-
-    if (res->getType() != type)
-        res = DtoCast(loc, res, type);
-
-    return res;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 DValue* CallExp::toElem(IRState* p)
 {
-    Logger::print("CallExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("CallExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     // get the callee value
@@ -833,7 +763,7 @@
 
 DValue* CastExp::toElem(IRState* p)
 {
-    Logger::print("CastExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("CastExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     // get the value to cast
@@ -848,13 +778,7 @@
     if (!type->equals(to))
         v = DtoPaintType(loc, v, type);
 
-    // slices are not valid lvalues
-    if (v->isSlice())
-        return v;
-    // if we're casting a lvalue, keep it around, we might be in a lvalue cast.
-    else if(u->isLVal())
-        return new DLRValue(u, v);
-    // otherwise just return the new value
+    // return the new rvalue
     return v;
 }
 
@@ -862,7 +786,7 @@
 
 LLConstant* CastExp::toConstElem(IRState* p)
 {
-    Logger::print("CastExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("CastExp::toConstElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     LLConstant* res;
@@ -899,7 +823,7 @@
 
 DValue* SymOffExp::toElem(IRState* p)
 {
-    Logger::print("SymOffExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("SymOffExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     assert(0 && "SymOffExp::toElem should no longer be called :/");
@@ -910,7 +834,7 @@
 
 DValue* AddrExp::toElem(IRState* p)
 {
-    Logger::println("AddrExp::toElem: %s | %s", toChars(), type->toChars());
+    Logger::println("AddrExp::toElem: %s @ %s", toChars(), type->toChars());
     LOG_SCOPE;
     DValue* v = e1->toElem(p);
     if (v->isField()) {
@@ -1030,34 +954,62 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+void PtrExp::cacheLvalue(IRState* p)
+{
+    Logger::println("Caching l-value of %s", toChars());
+    LOG_SCOPE;
+    cachedLvalue = e1->toElem(p)->getRVal();
+}
+
 DValue* PtrExp::toElem(IRState* p)
 {
-    Logger::println("PtrExp::toElem: %s | %s", toChars(), type->toChars());
+    Logger::println("PtrExp::toElem: %s @ %s", toChars(), type->toChars());
     LOG_SCOPE;
 
-    DValue* a = e1->toElem(p);
-
-    // this is *so* ugly.. I'd really like to figure out some way to avoid this badness...
-    LLValue* lv = a->getRVal();
-    LLValue* v = lv;
-
-    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), new DImValue(type, v));
+    // function pointers are special
+    if (type->toBasetype()->ty == Tfunction)
+    {
+        assert(!cachedLvalue);
+        return new DImValue(type, e1->toElem(p)->getRVal());
+    }
+
+    // get the rvalue and return it as an lvalue
+    LLValue* V;
+    if (cachedLvalue)
+    {
+        V = cachedLvalue;
+        cachedLvalue = NULL;
+    }
+    else
+    {
+        V = e1->toElem(p)->getRVal();
+    }
+    return new DVarValue(type, V);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+void DotVarExp::cacheLvalue(IRState* p)
+{
+    Logger::println("Caching l-value of %s", toChars());
+    LOG_SCOPE;
+    cachedLvalue = toElem(p)->getLVal();
+}
+
 DValue* DotVarExp::toElem(IRState* p)
 {
-    Logger::print("DotVarExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("DotVarExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
+    if (cachedLvalue)
+    {
+        LLValue *V = cachedLvalue;
+        cachedLvalue = NULL;
+        VarDeclaration* vd = var->isVarDeclaration();
+        assert(vd);
+        return new DVarValue(type, vd, V);
+    }
+
     DValue* l = e1->toElem(p);
 
     Type* t = type->toBasetype();
@@ -1165,7 +1117,7 @@
 
 DValue* ThisExp::toElem(IRState* p)
 {
-    Logger::print("ThisExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("ThisExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     // this seems to happen for dmd generated assert statements like:
@@ -1198,11 +1150,25 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+void IndexExp::cacheLvalue(IRState* p)
+{
+    Logger::println("Caching l-value of %s", toChars());
+    LOG_SCOPE;
+    cachedLvalue = toElem(p)->getLVal();
+}
+
 DValue* IndexExp::toElem(IRState* p)
 {
-    Logger::print("IndexExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("IndexExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
+    if (cachedLvalue)
+    {
+        LLValue* V = cachedLvalue;
+        cachedLvalue = NULL;
+        return new DVarValue(type, V);
+    }
+
     DValue* l = e1->toElem(p);
 
     Type* e1type = e1->type->toBasetype();
@@ -1243,7 +1209,7 @@
 
 DValue* SliceExp::toElem(IRState* p)
 {
-    Logger::print("SliceExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("SliceExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     // this is the new slicing code, it's different in that a full slice will no longer retain the original pointer.
@@ -1320,7 +1286,7 @@
 
 DValue* CmpExp::toElem(IRState* p)
 {
-    Logger::print("CmpExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("CmpExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* l = e1->toElem(p);
@@ -1439,7 +1405,7 @@
 
 DValue* EqualExp::toElem(IRState* p)
 {
-    Logger::print("EqualExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("EqualExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* l = e1->toElem(p);
@@ -1530,7 +1496,7 @@
 
 DValue* PostExp::toElem(IRState* p)
 {
-    Logger::print("PostExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("PostExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* l = e1->toElem(p);
@@ -1584,7 +1550,7 @@
 
 DValue* NewExp::toElem(IRState* p)
 {
-    Logger::print("NewExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("NewExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     assert(newtype);
@@ -1665,7 +1631,7 @@
 
 DValue* DeleteExp::toElem(IRState* p)
 {
-    Logger::print("DeleteExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("DeleteExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* dval = e1->toElem(p);
@@ -1725,7 +1691,7 @@
 
 DValue* ArrayLengthExp::toElem(IRState* p)
 {
-    Logger::print("ArrayLengthExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("ArrayLengthExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* u = e1->toElem(p);
@@ -1798,7 +1764,7 @@
 
 DValue* NotExp::toElem(IRState* p)
 {
-    Logger::print("NotExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("NotExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* u = e1->toElem(p);
@@ -1815,7 +1781,7 @@
 
 DValue* AndAndExp::toElem(IRState* p)
 {
-    Logger::print("AndAndExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("AndAndExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     // allocate a temporary for the final result. failed to come up with a better way :/
@@ -1853,7 +1819,7 @@
 
 DValue* OrOrExp::toElem(IRState* p)
 {
-    Logger::print("OrOrExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("OrOrExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     // allocate a temporary for the final result. failed to come up with a better way :/
@@ -1891,25 +1857,12 @@
 #define BinBitExp(X,Y) \
 DValue* X##Exp::toElem(IRState* p) \
 { \
-    Logger::print("%sExp::toElem: %s | %s\n", #X, toChars(), type->toChars()); \
+    Logger::print("%sExp::toElem: %s @ %s\n", #X, toChars(), type->toChars()); \
     LOG_SCOPE; \
     DValue* u = e1->toElem(p); \
     DValue* v = e2->toElem(p); \
     LLValue* x = llvm::BinaryOperator::Create(llvm::Instruction::Y, u->getRVal(), v->getRVal(), "tmp", p->scopebb()); \
     return new DImValue(type, x); \
-} \
-\
-DValue* X##AssignExp::toElem(IRState* p) \
-{ \
-    Logger::print("%sAssignExp::toElem: %s | %s\n", #X, toChars(), type->toChars()); \
-    LOG_SCOPE; \
-    DValue* u = e1->toElem(p); \
-    DValue* v = e2->toElem(p); \
-    LLValue* uval = u->getRVal(); \
-    LLValue* vval = v->getRVal(); \
-    LLValue* tmp = llvm::BinaryOperator::Create(llvm::Instruction::Y, uval, vval, "tmp", p->scopebb()); \
-    DtoStore(DtoPointedType(u->getLVal(), tmp), u->getLVal()); \
-    return u; \
 }
 
 BinBitExp(And,And);
@@ -1920,7 +1873,7 @@
 
 DValue* ShrExp::toElem(IRState* p)
 {
-    Logger::print("ShrExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("ShrExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     DValue* u = e1->toElem(p);
     DValue* v = e2->toElem(p);
@@ -1932,23 +1885,6 @@
     return new DImValue(type, x);
 }
 
-DValue* ShrAssignExp::toElem(IRState* p)
-{
-    Logger::print("ShrAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-    DValue* u = e1->toElem(p);
-    DValue* v = e2->toElem(p);
-    LLValue* uval = u->getRVal();
-    LLValue* vval = v->getRVal();
-    LLValue* tmp;
-    if (e1->type->isunsigned())
-        tmp = p->ir->CreateLShr(uval, vval, "tmp");
-    else
-        tmp = p->ir->CreateAShr(uval, vval, "tmp");
-    DtoStore(DtoPointedType(u->getLVal(), tmp), u->getLVal());
-    return u;
-}
-
 //////////////////////////////////////////////////////////////////////////////////////////
 
 DValue* HaltExp::toElem(IRState* p)
@@ -1980,7 +1916,7 @@
 
 DValue* DelegateExp::toElem(IRState* p)
 {
-    Logger::print("DelegateExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("DelegateExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     if(func->isStatic())
@@ -2041,7 +1977,7 @@
 
 DValue* IdentityExp::toElem(IRState* p)
 {
-    Logger::print("IdentityExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("IdentityExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* u = e1->toElem(p);
@@ -2101,7 +2037,7 @@
 
 DValue* CommaExp::toElem(IRState* p)
 {
-    Logger::print("CommaExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("CommaExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* u = e1->toElem(p);
@@ -2114,7 +2050,7 @@
 
 DValue* CondExp::toElem(IRState* p)
 {
-    Logger::print("CondExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("CondExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     Type* dtype = type->toBasetype();
@@ -2159,7 +2095,7 @@
 
 DValue* ComExp::toElem(IRState* p)
 {
-    Logger::print("ComExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("ComExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* u = e1->toElem(p);
@@ -2175,7 +2111,7 @@
 
 DValue* NegExp::toElem(IRState* p)
 {
-    Logger::print("NegExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("NegExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* l = e1->toElem(p);
@@ -2194,7 +2130,7 @@
 
 DValue* CatExp::toElem(IRState* p)
 {
-    Logger::print("CatExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("CatExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     Type* t = type->toBasetype();
@@ -2218,7 +2154,7 @@
 
 DValue* CatAssignExp::toElem(IRState* p)
 {
-    Logger::print("CatAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("CatAssignExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* l = e1->toElem(p);
@@ -2245,7 +2181,7 @@
 
 DValue* FuncExp::toElem(IRState* p)
 {
-    Logger::print("FuncExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("FuncExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     assert(fd);
@@ -2284,7 +2220,7 @@
 
 LLConstant* FuncExp::toConstElem(IRState* p)
 {
-    Logger::print("FuncExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("FuncExp::toConstElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     assert(fd);
@@ -2300,7 +2236,7 @@
 
 DValue* ArrayLiteralExp::toElem(IRState* p)
 {
-    Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("ArrayLiteralExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     // D types
@@ -2369,7 +2305,7 @@
 
 LLConstant* ArrayLiteralExp::toConstElem(IRState* p)
 {
-    Logger::print("ArrayLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("ArrayLiteralExp::toConstElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     // extract D types
@@ -2409,7 +2345,7 @@
 
 DValue* StructLiteralExp::toElem(IRState* p)
 {
-    Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("StructLiteralExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     // get inits
@@ -2467,7 +2403,7 @@
 
 LLConstant* StructLiteralExp::toConstElem(IRState* p)
 {
-    Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("StructLiteralExp::toConstElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     // get inits
@@ -2496,7 +2432,7 @@
 
 DValue* InExp::toElem(IRState* p)
 {
-    Logger::print("InExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("InExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     DValue* key = e1->toElem(p);
@@ -2522,7 +2458,7 @@
 
 DValue* AssocArrayLiteralExp::toElem(IRState* p)
 {
-    Logger::print("AssocArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
+    Logger::print("AssocArrayLiteralExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
     assert(keys);
--- a/runtime/internal/memory.d	Fri Mar 27 23:24:47 2009 +0100
+++ b/runtime/internal/memory.d	Sat Mar 28 05:00:43 2009 +0100
@@ -68,12 +68,9 @@
             import tango.stdc.posix.dlfcn;
         }
     }
-    version(LDC)
+    pragma(intrinsic, "llvm.frameaddress")
     {
-        pragma(intrinsic, "llvm.frameaddress")
-        {
-                void* llvm_frameaddress(uint level=0);
-        }
+            void* llvm_frameaddress(uint level=0);
     }
 }
 
@@ -147,11 +144,7 @@
  */
 extern (C) void* rt_stackTop()
 {
-    version(LDC)
-    {
-        return llvm_frameaddress();
-    }
-    else version( D_InlineAsm_X86 )
+    version( D_InlineAsm_X86 )
     {
         asm
         {
@@ -162,7 +155,7 @@
     }
     else
     {
-            static assert( false, "Architecture not supported." );
+        return llvm_frameaddress();
     }
 }