changeset 40:8b0e809563df trunk

[svn r44] Lots of bug fixes. New array literal support New array ~= operator support (for single element) New with statement support More...
author lindquist
date Fri, 19 Oct 2007 07:43:21 +0200
parents fd5e8bbfcb25
children 835320b88ad6
files dmd/declaration.c dmd/declaration.h dmd/expression.h dmd/mars.c gen/arrays.c gen/arrays.h gen/elem.c gen/elem.h gen/irstate.c gen/irstate.h gen/llvm.h gen/runtime.c gen/statements.c gen/toir.c gen/tollvm.c gen/tollvm.h gen/toobj.c lphobos/internal/arrays.d test/arrays4.d test/arrays6.d test/arrays7.d test/bug10.d test/bug11.d test/bug12.d test/bug13.d test/bug14.d test/bug15.d test/bug3.d test/bug8.d test/bug9.d test/cond1.d test/scope2.d test/scope3.d test/scope4.d test/virtcall.d test/with1.d tester.sh
diffstat 37 files changed, 1328 insertions(+), 532 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/declaration.c	Wed Oct 10 06:21:31 2007 +0200
+++ b/dmd/declaration.c	Fri Oct 19 07:43:21 2007 +0200
@@ -31,7 +31,8 @@
     type = NULL;
     storage_class = STCundefined;
     protection = PROTundefined;
-    linkage = LINKdefault;
+    linkage = LINKdefault;
+    llvmTouched = false;
 }
 
 void Declaration::semantic(Scope *sc)
--- a/dmd/declaration.h	Wed Oct 10 06:21:31 2007 +0200
+++ b/dmd/declaration.h	Fri Oct 19 07:43:21 2007 +0200
@@ -125,7 +125,9 @@
 
     Declaration *isDeclaration() { return this; }
 
-    virtual void toObjFile();           // compile to .obj file
+    virtual void toObjFile();           // compile to .obj file
+    
+    bool llvmTouched;
 };
 
 /**************************************************************/
--- a/dmd/expression.h	Wed Oct 10 06:21:31 2007 +0200
+++ b/dmd/expression.h	Fri Oct 19 07:43:21 2007 +0200
@@ -46,6 +46,7 @@
 
 namespace llvm
 {
+    class Constant;
     class ConstantInt;
 }
 
@@ -147,6 +148,8 @@
     // Back end
     virtual elem *toElem(IRState *irs);
     virtual dt_t **toDt(dt_t **pdt);
+    // LLVMDC
+    virtual llvm::Constant *toConstElem(IRState *irs);
 };
 
 struct IntegerExp : Expression
@@ -172,6 +175,8 @@
     Expression *toLvalue(Scope *sc, Expression *e);
     elem *toElem(IRState *irs);
     dt_t **toDt(dt_t **pdt);
+    // LLVMDC
+    virtual llvm::Constant *toConstElem(IRState *irs);
 };
 
 struct RealExp : Expression
@@ -195,6 +200,8 @@
     void toMangleBuffer(OutBuffer *buf);
     elem *toElem(IRState *irs);
     dt_t **toDt(dt_t **pdt);
+    // LLVMDC
+    virtual llvm::Constant *toConstElem(IRState *irs);
 };
 
 struct ComplexExp : Expression
@@ -298,6 +305,8 @@
     Expression *interpret(InterState *istate);
     elem *toElem(IRState *irs);
     dt_t **toDt(dt_t **pdt);
+    // LLVMDC
+    virtual llvm::Constant *toConstElem(IRState *irs);
 };
 
 struct StringExp : Expression
@@ -326,6 +335,8 @@
     void toMangleBuffer(OutBuffer *buf);
     elem *toElem(IRState *irs);
     dt_t **toDt(dt_t **pdt);
+    // LLVMDC
+    virtual llvm::Constant *toConstElem(IRState *irs);
 };
 
 // Tuple
@@ -376,6 +387,8 @@
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
     Expression *inlineScan(InlineScanState *iss);
+    // LLVMDC
+    virtual llvm::Constant *toConstElem(IRState *irs);
 };
 
 struct AssocArrayLiteralExp : Expression
@@ -401,6 +414,8 @@
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
     Expression *inlineScan(InlineScanState *iss);
+    // LLVMDC
+    virtual llvm::Constant *toConstElem(IRState *irs);
 };
 
 struct StructLiteralExp : Expression
@@ -432,6 +447,8 @@
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
     Expression *inlineScan(InlineScanState *iss);
+    // LLVMDC
+    virtual llvm::Constant *toConstElem(IRState *irs);
 };
 
 struct TypeDotIdExp : Expression
@@ -564,6 +581,8 @@
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
     //Expression *inlineScan(InlineScanState *iss);
+    // LLVMDC
+    virtual llvm::Constant *toConstElem(IRState *irs);
 };
 
 // Function/Delegate literal
--- a/dmd/mars.c	Wed Oct 10 06:21:31 2007 +0200
+++ b/dmd/mars.c	Fri Oct 19 07:43:21 2007 +0200
@@ -192,16 +192,16 @@
                  x86 x86-64 ppc32 ppc64\n\
   -nofloat       do not emit reference to floating point\n\
   -noruntime     do not allow code that generates implicit runtime calls\n\
-  -novalidate    do not run the validation pass before writing bitcode\n\
+  -noverify      do not run the validation pass before writing bitcode\n\
   -O             optimize, same as -O2\n\
   -O<n>          optimize at level <n> (0-5)\n\
   -o-            do not write object file\n\
   -od<objdir>    write object files to directory <objdir>\n\
   -of<filename>	 name output file to <filename>\n\
   -op            do not strip paths from source file\n\
-  -profile	     profile runtime performance of generated code\n\
+  -profile       profile runtime performance of generated code\n\
   -quiet         suppress unnecessary messages\n\
-  -release	     compile release version\n\
+  -release       compile release version\n\
   -run srcfile args...   run resulting program, passing args\n\
   -unittest      compile in unit tests\n\
   -v             verbose\n\
@@ -382,7 +382,7 @@
 		global.params.forceBE = 1;
         else if (strcmp(p + 1, "noruntime") == 0)
 		global.params.noruntime = 1;
-        else if (strcmp(p + 1, "novalidate") == 0)
+        else if (strcmp(p + 1, "noverify") == 0)
         global.params.novalidate = 1;
 	    else if (p[1] == 'o')
 	    {
--- a/gen/arrays.c	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/arrays.c	Fri Oct 19 07:43:21 2007 +0200
@@ -1,8 +1,4 @@
-#include "llvm/Constants.h"
-#include "llvm/Type.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Instructions.h"
-#include "llvm/CallingConv.h"
+#include "gen/llvm.h"
 
 #include "mtype.h"
 #include "dsymbol.h"
@@ -218,16 +214,17 @@
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* arrinit)
+llvm::Constant* LLVM_DtoConstArrayInitializer(ArrayInitializer* arrinit)
 {
     Logger::println("arr init begin");
-    assert(arrinit->type->ty == Tsarray);
-    TypeSArray* t = (TypeSArray*)arrinit->type;
+    Type* arrinittype = LLVM_DtoDType(arrinit->type);
+    assert(arrinittype->ty == Tsarray);
+    TypeSArray* t = (TypeSArray*)arrinittype;
     integer_t tdim = t->dim->toInteger();
 
     std::vector<llvm::Constant*> inits(tdim, 0);
 
-    const llvm::Type* elemty = LLVM_DtoType(arrinit->type->next);
+    const llvm::Type* elemty = LLVM_DtoType(arrinittype->next);
 
     assert(arrinit->index.dim == arrinit->value.dim);
     for (int i=0,j=0; i < tdim; ++i)
@@ -255,23 +252,19 @@
 
         if (!init)
         {
-            elem* e = t->next->defaultInit()->toElem(gIR);
-            v = llvm::cast<llvm::Constant>(e->val);
-            delete e;
+            v = t->next->defaultInit()->toConstElem(gIR);
         }
         else if (ExpInitializer* ex = init->isExpInitializer())
         {
-            elem* e = ex->exp->toElem(gIR);
-            v = llvm::cast<llvm::Constant>(e->val);
-            delete e;
+            v = ex->exp->toConstElem(gIR);
         }
         else if (StructInitializer* si = init->isStructInitializer())
         {
-            v = LLVM_DtoStructInitializer(si);
+            v = LLVM_DtoConstStructInitializer(si);
         }
         else if (ArrayInitializer* ai = init->isArrayInitializer())
         {
-            v = LLVM_DtoArrayInitializer(ai);
+            v = LLVM_DtoConstArrayInitializer(ai);
         }
         else if (init->isVoidInitializer())
         {
@@ -415,3 +408,61 @@
     new llvm::StoreInst(sz,len,gIR->scopebb());
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLVM_DtoCatArrayElement(llvm::Value* arr, Expression* exp)
+{
+    llvm::Value* ptr = LLVM_DtoGEPi(arr, 0, 0, "tmp", gIR->scopebb());
+    llvm::Value* idx = new llvm::LoadInst(ptr, "tmp", gIR->scopebb());
+    llvm::Value* one = llvm::ConstantInt::get(idx->getType(),1,false);
+    llvm::Value* len = llvm::BinaryOperator::createAdd(idx, one, "tmp", gIR->scopebb());
+    LLVM_DtoResizeDynArray(arr,len);
+
+    ptr = LLVM_DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb());
+    ptr = new llvm::LoadInst(ptr, "tmp", gIR->scopebb());
+    ptr = new llvm::GetElementPtrInst(ptr, idx, "tmp", gIR->scopebb());
+
+    elem* e = exp->toElem(gIR);
+    Type* et = LLVM_DtoDType(exp->type);
+
+    if (et->ty == Tstruct) {
+        TypeStruct* ts = (TypeStruct*)et;
+        LLVM_DtoStructCopy(ts,ptr,e->getValue());
+    }
+    else {
+        llvm::Value* val = e->getValue();
+        Logger::cout() << "ptr = '" << *ptr << "' element = '" << *val << "'\n";
+        new llvm::StoreInst(val, ptr, gIR->scopebb());
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Value* LLVM_DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r)
+{
+    const char* fname;
+    if (op == TOKequal)
+        fname = "_d_static_array_eq";
+    else if (op == TOKnotequal)
+        fname = "_d_static_array_neq";
+    else
+        assert(0);
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
+    assert(fn);
+
+    assert(l->getType() == r->getType());
+    assert(llvm::isa<llvm::PointerType>(l->getType()));
+    const llvm::Type* arrty = l->getType()->getContainedType(0);
+    assert(llvm::isa<llvm::ArrayType>(arrty));
+    
+    llvm::Value* ll = new llvm::BitCastInst(l, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
+    llvm::Value* rr = new llvm::BitCastInst(r, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
+    llvm::Value* n = llvm::ConstantInt::get(LLVM_DtoSize_t(),gTargetData->getTypeSize(arrty),false);
+
+    std::vector<llvm::Value*> args;
+    args.push_back(ll);
+    args.push_back(rr);
+    args.push_back(n);
+    return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
--- a/gen/arrays.h	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/arrays.h	Fri Oct 19 07:43:21 2007 +0200
@@ -4,7 +4,7 @@
 const llvm::StructType* LLVM_DtoArrayType(Type* t);
 const llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t);
 
-llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* si);
+llvm::Constant* LLVM_DtoConstArrayInitializer(ArrayInitializer* si);
 llvm::Constant* LLVM_DtoConstantSlice(llvm::Constant* dim, llvm::Constant* ptr);
 
 void LLVM_DtoArrayCopy(elem* dst, elem* src);
@@ -17,4 +17,8 @@
 void LLVM_DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool doinit=true);
 void LLVM_DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz);
 
+void LLVM_DtoCatArrayElement(llvm::Value* arr, Expression* exp);
+
+llvm::Value* LLVM_DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r);
+
 #endif // LLVMC_GEN_ARRAYS_H
--- a/gen/elem.c	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/elem.c	Fri Oct 19 07:43:21 2007 +0200
@@ -1,6 +1,6 @@
 #include <iostream>
 
-#include "llvm/Instructions.h"
+#include "gen/llvm.h"
 
 #include "gen/elem.h"
 #include "gen/irstate.h"
@@ -50,7 +50,7 @@
                 return mem;
             }
             else {
-                return new llvm::LoadInst(mem, "tmp", gIR->scopebb());
+                return gIR->ir->CreateLoad(mem, "tmp");
             }
         }
 
--- a/gen/elem.h	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/elem.h	Fri Oct 19 07:43:21 2007 +0200
@@ -1,8 +1,6 @@
 #ifndef LLVMDC_GEN_ELEM_H
 #define LLVMDC_GEN_ELEM_H
 
-#include "llvm/Value.h"
-
 #include "root.h"
 #include "declaration.h"
 #include "aggregate.h"
--- a/gen/irstate.c	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/irstate.c	Fri Oct 19 07:43:21 2007 +0200
@@ -4,8 +4,15 @@
  * has been parsed. Substitute your own behaviors for these routimes.
  */
 
+#include <cstdarg>
+
+#include "gen/llvm.h"
+
 #include "mtype.h"
+#include "declaration.h"
+
 #include "gen/irstate.h"
+#include "tollvm.h"
 
 IRState* gIR = 0;
 llvm::TargetData* gTargetData = 0;
@@ -13,15 +20,14 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 IRScope::IRScope()
 {
-    begin = end = 0;
-    returned = false;
+    begin = end = NULL;
 }
 
 IRScope::IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e)
 {
     begin = b;
     end = e;
-    returned = false;
+    builder.SetInsertPoint(b);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -32,24 +38,31 @@
     inLvalue = false;
     emitMain = false;
     mainFunc = 0;
+    ir.state = this;
+}
+
+IRFunction& IRState::func()
+{
+    assert(!functions.empty() && "Function stack is empty!");
+    return functions.back();
 }
 
 llvm::Function* IRState::topfunc()
 {
-    assert(!funcs.empty() && "Function stack is empty!");
-    return funcs.top();
+    assert(!functions.empty() && "Function stack is empty!");
+    return functions.back().func;
 }
 
 TypeFunction* IRState::topfunctype()
 {
-    assert(!functypes.empty() && "TypeFunction stack is empty!");
-    return functypes.top();
+    assert(!functions.empty() && "Function stack is empty!");
+    return functions.back().type;
 }
 
 llvm::Instruction* IRState::topallocapoint()
 {
-    assert(!functypes.empty() && "AllocaPoint stack is empty!");
-    return functypes.top()->llvmAllocaPoint;
+    assert(!functions.empty() && "AllocaPoint stack is empty!");
+    return functions.back().allocapoint;
 }
 
 IRStruct& IRState::topstruct()
@@ -108,6 +121,35 @@
     queueFuncs = true;
 }
 
-IRStruct::~IRStruct()
+//////////////////////////////////////////////////////////////////////////////////////////
+
+IRFinally::IRFinally()
+ : bb(NULL), ret(false), retval(NULL)
+{
+}
+
+IRFinally::IRFinally(llvm::BasicBlock* b)
+ : bb(b), ret(false), retval(NULL)
 {
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+LLVMBuilder* IRBuilderHelper::operator->()
+{
+    LLVMBuilder& b = state->scope().builder;
+    assert(b.GetInsertBlock() != NULL);
+    return &b;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+IRFunction::IRFunction(FuncDeclaration* fd)
+{
+    decl = fd;
+    Type* t = LLVM_DtoDType(fd->type);
+    assert(t->ty == Tfunction);
+    type = (TypeFunction*)t;
+    func = NULL;
+    allocapoint = NULL;
+}
--- a/gen/irstate.h	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/irstate.h	Fri Oct 19 07:43:21 2007 +0200
@@ -5,12 +5,6 @@
 #include <vector>
 #include <deque>
 
-#include "llvm/DerivedTypes.h"
-#include "llvm/Module.h"
-#include "llvm/Function.h"
-#include "llvm/BasicBlock.h"
-#include "llvm/Target/TargetData.h"
-
 #include "root.h"
 
 // global ir state for current module
@@ -25,19 +19,26 @@
 struct Module;
 struct TypeStruct;
 
+/*
+struct LLVMValue
+{
+    std::vector<llvm::Value*> vals;
+};
+*/
+
 // represents a scope
 struct IRScope
 {
     llvm::BasicBlock* begin;
     llvm::BasicBlock* end;
-    bool returned;
+    LLVMBuilder builder;
 
     IRScope();
     IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e);
 };
 
 // represents a struct or class
-struct IRStruct : Object
+struct IRStruct
 {
     typedef std::vector<const llvm::Type*> TypeVector;
     typedef std::vector<llvm::Constant*> ConstantVector;
@@ -46,7 +47,6 @@
 public:
     IRStruct();
     IRStruct(Type*);
-    virtual ~IRStruct();
 
     Type* type;
     TypeVector fields;
@@ -56,8 +56,40 @@
     bool queueFuncs;
 };
 
+// represents a finally block
+struct IRFinally
+{
+    llvm::BasicBlock* bb;
+    bool ret;
+    llvm::Value* retval;
+
+    IRFinally();
+    IRFinally(llvm::BasicBlock* b);
+};
+
+// represents a function
+struct IRFunction
+{
+    llvm::Function* func;
+    llvm::Instruction* allocapoint;
+    FuncDeclaration* decl;
+    TypeFunction* type;
+
+    // finally blocks
+    typedef std::vector<IRFinally> FinallyVec;
+    FinallyVec finallys;
+
+    IRFunction(FuncDeclaration*);
+};
+
+struct IRBuilderHelper
+{
+    IRState* state;
+    LLVMBuilder* operator->();
+};
+
 // represents the module
-struct IRState : Object
+struct IRState
 {
     IRState();
 
@@ -66,9 +98,11 @@
     llvm::Module* module;
 
     // functions
-    std::stack<llvm::Function*> funcs;
+    typedef std::vector<IRFunction> FunctionVector;
+    FunctionVector functions;
+    IRFunction& func();
+
     llvm::Function* topfunc();
-    std::stack<TypeFunction*> functypes;
     TypeFunction* topfunctype();
     llvm::Instruction* topallocapoint();
 
@@ -109,9 +143,8 @@
     // array pointer from this :(
     LvalVec arrays;
 
-    // keeping track of the declaration for the current function body
-    typedef std::vector<FuncDeclaration*> FuncDeclVec;
-    FuncDeclVec funcdecls;
+    // builder helper
+    IRBuilderHelper ir;
 };
 
 #endif // LLVMDC_GEN_IRSTATE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/llvm.h	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,18 @@
+#ifndef GEN_LLVM_H
+#define GEN_LLVM_H
+
+#include "llvm/Type.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Constants.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/CallingConv.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Function.h"
+#include "llvm/Module.h"
+
+#include "llvm/Target/TargetData.h"
+
+#include "llvm/Support/LLVMBuilder.h"
+using llvm::LLVMBuilder;
+
+#endif // GEN_LLVM_H
--- a/gen/runtime.c	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/runtime.c	Fri Oct 19 07:43:21 2007 +0200
@@ -70,9 +70,13 @@
     }
     
     llvm::Function* fn = M->getFunction(name);
-    if (!fn)
-        return NULL;
+    if (!fn) {
+        error("Runtime function '%s' was not found", name);
+        fatal();
+        //return NULL;
+    }
     
     const llvm::FunctionType* fnty = fn->getFunctionType();
     return llvm::cast<llvm::Function>(target->getOrInsertFunction(name, fnty));
 }
+
--- a/gen/statements.c	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/statements.c	Fri Oct 19 07:43:21 2007 +0200
@@ -6,12 +6,7 @@
 #include <fstream>
 #include <iostream>
 
-#include "llvm/Type.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Constants.h"
-#include "llvm/Instructions.h"
-#include "llvm/IntrinsicInst.h"
-#include "llvm/CallingConv.h"
+#include "gen/llvm.h"
 
 #include "total.h"
 #include "init.h"
@@ -41,8 +36,8 @@
         if (s)
             s->toIR(p);
         else {
-            Logger::println("NULL statement found in CompoundStatement !! :S");
-            assert(0);
+            Logger::println("*** ATTENTION: null statement found in CompoundStatement");
+            //assert(0);
         }
     }
 
@@ -56,11 +51,14 @@
     Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars());
     LOG_SCOPE;
 
+    IRFunction::FinallyVec& fin = p->func().finallys;
+
     if (exp)
     {
-        TY expty = exp->type->ty;
+        Type* exptype = LLVM_DtoDType(exp->type);
+        TY expty = exptype->ty;
         if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
-            assert(expty == Tstruct || expty == Tdelegate || expty == Tarray);
+            assert(LLVM_DtoIsPassedByRef(exptype));
 
             TypeFunction* f = p->topfunctype();
             assert(f->llvmRetInPtr && f->llvmRetArg);
@@ -69,17 +67,14 @@
             elem* e = exp->toElem(p);
             p->lvals.pop_back();
 
-            // structliterals do this themselves
-            // also they dont produce any value
             if (expty == Tstruct) {
                 if (!e->inplace) {
-                    TypeStruct* ts = (TypeStruct*)exp->type;
+                    TypeStruct* ts = (TypeStruct*)exptype;
                     assert(e->mem);
                     LLVM_DtoStructCopy(ts,f->llvmRetArg,e->mem);
                 }
             }
             else if (expty == Tdelegate) {
-                // do nothing, handled by the DelegateExp
                 LLVM_DtoDelegateCopy(f->llvmRetArg,e->mem);
             }
             else if (expty == Tarray) {
@@ -91,26 +86,47 @@
             else
             assert(0);
 
-            new llvm::ReturnInst(p->scopebb());
+            if (fin.empty())
+                new llvm::ReturnInst(p->scopebb());
+            else {
+                new llvm::BranchInst(fin.back().bb);
+                fin.back().ret = true;
+            }
             delete e;
         }
         else {
             elem* e = exp->toElem(p);
             llvm::Value* v = e->getValue();
-            Logger::cout() << *v << '\n';
-            new llvm::ReturnInst(v, p->scopebb());
             delete e;
+            Logger::cout() << "return value is '" <<*v << "'\n";
+            if (fin.empty()) {
+                new llvm::ReturnInst(v, p->scopebb());
+            }
+            else {
+                llvm::Value* rettmp = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint());
+                new llvm::StoreInst(v,rettmp,p->scopebb());
+                new llvm::BranchInst(fin.back().bb, p->scopebb());
+                fin.back().ret = true;
+                fin.back().retval = rettmp;
+            }
         }
     }
     else
     {
-        if (p->topfunc()->getReturnType() == llvm::Type::VoidTy)
-            new llvm::ReturnInst(p->scopebb());
-        else
+        if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
+            if (fin.empty()) {
+                new llvm::ReturnInst(p->scopebb());
+            }
+            else {
+                new llvm::BranchInst(fin.back().bb);
+                fin.back().ret = true;
+            }
+        }
+        else {
+            assert(0); // why should this ever happen?
             new llvm::UnreachableInst(p->scopebb());
+        }
     }
-
-    p->scope().returned = true;
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -196,33 +212,26 @@
 
     llvm::BasicBlock* oldend = p->scopeend();
 
-    IRScope irs;
+    llvm::BasicBlock* beginbb = 0;
+    
     // remove useless branches by clearing and reusing the current basicblock
     llvm::BasicBlock* bb = p->scopebegin();
     if (bb->empty()) {
-        irs.begin = bb;
+        beginbb = bb;
     }
     else {
-        irs.begin = new llvm::BasicBlock("scope", p->topfunc(), oldend);
-        new llvm::BranchInst(irs.begin, p->scopebegin());
+        assert(!p->scopereturned());
+        beginbb = new llvm::BasicBlock("scope", p->topfunc(), oldend);
+        new llvm::BranchInst(beginbb, p->scopebegin());
     }
-    irs.end = new llvm::BasicBlock("endscope", p->topfunc(), oldend);
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("endscope", p->topfunc(), oldend);
 
-    gIR->scope() = irs;
+    gIR->scope() = IRScope(beginbb, endbb);
 
     statement->toIR(p);
 
     p->scope() = IRScope(p->scopebb(),oldend);
-    irs.end->eraseFromParent();
-
-    /*
-    if (!gIR->scopereturned()) {
-        new llvm::BranchInst(irs.end, gIR->scopebegin());
-    }
-
-    // rewrite the scope
-    gIR->scope() = IRScope(irs.end,oldend);
-    */
+    endbb->eraseFromParent();
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -239,7 +248,8 @@
     llvm::BasicBlock* endbb = new llvm::BasicBlock("endwhile", gIR->topfunc(), oldend);
 
     // move into the while block
-    new llvm::BranchInst(whilebb, gIR->scopebegin());
+    p->ir->CreateBr(whilebb);
+    //new llvm::BranchInst(whilebb, gIR->scopebegin());
 
     // replace current scope
     gIR->scope() = IRScope(whilebb,endbb);
@@ -324,10 +334,7 @@
     // move into the for condition block, ie. start the loop
     new llvm::BranchInst(forbb, gIR->scopebegin());
 
-    IRScope loop;
-    loop.begin = forincbb;
-    loop.end = endbb;
-    p->loopbbs.push_back(loop);
+    p->loopbbs.push_back(IRScope(forincbb,endbb));
 
     // replace current scope
     gIR->scope() = IRScope(forbb,forbodybb);
@@ -419,30 +426,46 @@
     Logger::println("TryFinallyStatement::toIR(%d): %s", wsi++, toChars());
     LOG_SCOPE;
 
-    llvm::BasicBlock* oldend = gIR->scopeend();
+    llvm::BasicBlock* oldend = p->scopeend();
 
-    llvm::BasicBlock* trybb = new llvm::BasicBlock("try", gIR->topfunc(), oldend);
-    llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", gIR->topfunc(), oldend);
-    llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", gIR->topfunc(), oldend);
+    llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend);
+    llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", p->topfunc(), oldend);
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", p->topfunc(), oldend);
 
     // pass the previous BB into this
-    new llvm::BranchInst(trybb, gIR->scopebegin());
+    new llvm::BranchInst(trybb, p->scopebb());
 
-    gIR->scope() = IRScope(trybb,finallybb);
+    p->scope() = IRScope(trybb,finallybb);
 
     assert(body);
+    gIR->func().finallys.push_back(IRFinally(finallybb));
     body->toIR(p);
-    new llvm::BranchInst(finallybb, gIR->scopebegin());
+    if (!gIR->scopereturned())
+        new llvm::BranchInst(finallybb, p->scopebb());
 
     // rewrite the scope
-    gIR->scope() = IRScope(finallybb,endbb);
+    p->scope() = IRScope(finallybb,endbb);
 
     assert(finalbody);
     finalbody->toIR(p);
-    new llvm::BranchInst(endbb, gIR->scopebegin());
+    if (gIR->func().finallys.back().ret) {
+        llvm::Value* retval = p->func().finallys.back().retval;
+        if (retval) {
+            retval = new llvm::LoadInst(retval,"tmp",p->scopebb());
+            new llvm::ReturnInst(retval, p->scopebb());
+        }
+        else {
+            new llvm::ReturnInst(p->scopebb());
+        }
+    }
+    else if (!gIR->scopereturned()) {
+        new llvm::BranchInst(endbb, p->scopebb());
+    }
+
+    p->func().finallys.pop_back();
 
     // rewrite the scope
-    gIR->scope() = IRScope(endbb,oldend);
+    p->scope() = IRScope(endbb,oldend);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -628,7 +651,7 @@
     const llvm::Type* valtype = LLVM_DtoType(value->type);
     llvm::Value* valvar = new llvm::AllocaInst(keytype, "foreachval", p->topallocapoint());
 
-    if (aggr->type->ty == Tsarray)
+    if (LLVM_DtoDType(aggr->type)->ty == Tsarray)
     {
         assert(llvm::isa<llvm::PointerType>(val->getType()));
         assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0)));
@@ -686,7 +709,7 @@
     body->toIR(p);
     p->loopbbs.pop_back();
 
-    if (!p->scope().returned)
+    if (!p->scopereturned())
         new llvm::BranchInst(nexbb, p->scopebb());
 
     // end
@@ -734,12 +757,29 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
+void WithStatement::toIR(IRState* p)
+{
+    Logger::println("WithStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    assert(exp);
+    assert(body);
+
+    elem* e = exp->toElem(p);
+    wthis->llvmValue = e->getValue();
+    delete e;
+
+    body->toIR(p);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
 //////////////////////////////////////////////////////////////////////////////
 
 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();}
 //STUBST(BreakStatement);
 //STUBST(ForStatement);
-STUBST(WithStatement);
+//STUBST(WithStatement);
 STUBST(SynchronizedStatement);
 //STUBST(ReturnStatement);
 //STUBST(ContinueStatement);
--- a/gen/toir.c	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/toir.c	Fri Oct 19 07:43:21 2007 +0200
@@ -12,12 +12,7 @@
 #include <fstream>
 #include <iostream>
 
-#include "llvm/Type.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Constants.h"
-#include "llvm/Instructions.h"
-#include "llvm/IntrinsicInst.h"
-#include "llvm/CallingConv.h"
+#include "gen/llvm.h"
 
 #include "total.h"
 #include "init.h"
@@ -60,7 +55,7 @@
             vd->llvmValue = allocainst;
             // e->val = really needed??
 
-            LLVM_DtoInitializer(vd->type, vd->init);
+            LLVM_DtoInitializer(vd->init);
         }
     }
     // struct declaration
@@ -69,6 +64,17 @@
         Logger::println("StructDeclaration");
         s->toObjFile();
     }
+    // function declaration
+    else if (FuncDeclaration* f = declaration->isFuncDeclaration())
+    {
+        Logger::println("FuncDeclaration");
+        f->toObjFile();
+    }
+    // alias declaration
+    else if (AliasDeclaration* a = declaration->isAliasDeclaration())
+    {
+        Logger::println("AliasDeclaration");
+    }
     // unsupported declaration
     else
     {
@@ -91,6 +97,10 @@
     if (VarDeclaration* vd = var->isVarDeclaration())
     {
         Logger::println("VarDeclaration");
+        
+        // needed to take care of forward references of global variables
+        if (!vd->llvmTouched && vd->isDataseg())
+            vd->toObjFile();
 
         if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
         {
@@ -98,6 +108,7 @@
         }
 
         // this must be a dollar expression or some other magic value
+        // or it could be a forward declaration of a global variable
         if (!vd->llvmValue)
         {
             // dollar
@@ -109,19 +120,17 @@
                 e->val = new llvm::LoadInst(tmp,"tmp",p->scopebb());
                 e->type = elem::VAL;
             }
-            // magic
-            else
+            // typeinfo
+            else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
             {
-                if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
-                {
-                    tid->toObjFile();
-                    e->mem = tid->llvmValue;
-                    e->type = elem::VAR;
-                }
-                else {
-                    Logger::println("unsupported: %s\n", vd->toChars());
-                    assert(0 && "only magic supported is typeinfo");
-                }
+                tid->toObjFile();
+                e->mem = tid->llvmValue;
+                e->type = elem::VAR;
+            }
+            // global forward ref
+            else {
+                Logger::println("unsupported: %s\n", vd->toChars());
+                assert(0 && "only magic supported is typeinfo");
             }
             return e;
         }
@@ -134,7 +143,7 @@
                 e->type = elem::VAR;
             }
             else {
-                if (vd->type->ty == Tstruct || vd->type->ty == Tdelegate || vd->type->ty == Tarray) {
+                if (LLVM_DtoIsPassedByRef(vd->type)) {
                     e->mem = vd->llvmValue;
                     e->type = elem::VAR;
                 }
@@ -173,11 +182,10 @@
     else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
     {
         // this seems to be the static initialiser for structs
-        Logger::print("Sym: type=%s\n", sdecl->type->toChars());
-        assert(sdecl->type->ty == Tstruct);
-        //assert(sdecl->llvmInitZ);
-        //e->val = sdecl->llvmInitZ;
-        TypeStruct* ts = (TypeStruct*)sdecl->type;
+        Type* sdecltype = LLVM_DtoDType(sdecl->type);
+        Logger::print("Sym: type=%s\n", sdecltype->toChars());
+        assert(sdecltype->ty == Tstruct);
+        TypeStruct* ts = (TypeStruct*)sdecltype;
         e->mem = ts->llvmInit;
         assert(e->mem);
         e->type = elem::VAR;
@@ -193,24 +201,52 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+llvm::Constant* VarExp::toConstElem(IRState* p)
+{
+    Logger::print("VarExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+    if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
+    {
+        // this seems to be the static initialiser for structs
+        Type* sdecltype = LLVM_DtoDType(sdecl->type);
+        Logger::print("Sym: type=%s\n", sdecltype->toChars());
+        assert(sdecltype->ty == Tstruct);
+        TypeStruct* ts = (TypeStruct*)sdecltype;
+        assert(ts->sym->llvmInitZ);
+        return ts->sym->llvmInitZ;
+    }
+    assert(0 && "Only support const var exp is SymbolDeclaration");
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 elem* IntegerExp::toElem(IRState* p)
 {
     Logger::print("IntegerExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     elem* e = new elem;
+    e->val = toConstElem(p);
+    e->type = elem::CONST;
+    return e;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* IntegerExp::toConstElem(IRState* p)
+{
+    Logger::print("IntegerExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
     const llvm::Type* t = LLVM_DtoType(type);
     if (llvm::isa<llvm::PointerType>(t)) {
         llvm::Constant* i = llvm::ConstantInt::get(LLVM_DtoSize_t(),(uint64_t)value,false);
-        e->val = llvm::ConstantExpr::getIntToPtr(i, t);
+        return llvm::ConstantExpr::getIntToPtr(i, t);
     }
     else if (llvm::isa<llvm::IntegerType>(t)) {
-        e->val = llvm::ConstantInt::get(t,(uint64_t)value,!type->isunsigned());
+        return llvm::ConstantInt::get(t,(uint64_t)value,!type->isunsigned());
     }
-    else {
-        assert(0);
-    }
-    e->type = elem::CONST;
-    return e;
+    assert(0);
+    return NULL;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -220,15 +256,24 @@
     Logger::print("RealExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     elem* e = new elem;
+    e->val = toConstElem(p);
+    e->type = elem::CONST;
+    return e;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* RealExp::toConstElem(IRState* p)
+{
+    Logger::print("RealExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
     const llvm::Type* fty = LLVM_DtoType(type);
     if (type->ty == Tfloat32)
-        e->val = llvm::ConstantFP::get(fty,float(value));
+        return llvm::ConstantFP::get(fty,float(value));
     else if (type->ty == Tfloat64 || type->ty == Tfloat80)
-        e->val = llvm::ConstantFP::get(fty,double(value));
-    else
+        return llvm::ConstantFP::get(fty,double(value));
     assert(0);
-    e->type = elem::CONST;
-    return e;
+    return NULL;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -238,19 +283,28 @@
     Logger::print("NullExp::toElem(type=%s): %s\n", type->toChars(),toChars());
     LOG_SCOPE;
     elem* e = new elem;
+    e->val = toConstElem(p);
+    e->type = elem::NUL;
+    //Logger::cout() << "null value is now " << *e->val << '\n';
+    return e;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* NullExp::toConstElem(IRState* p)
+{
+    Logger::print("NullExp::toConstElem(type=%s): %s\n", type->toChars(),toChars());
+    LOG_SCOPE;
     const llvm::Type* t = LLVM_DtoType(type);
-
     if (type->ty == Tarray) {
         assert(llvm::isa<llvm::StructType>(t));
-        e->val = llvm::ConstantAggregateZero::get(t);
+        return llvm::ConstantAggregateZero::get(t);
     }
-    else
-        e->val = llvm::Constant::getNullValue(t);
-    assert(e->val);
-
-    Logger::cout() << "null value is now " << *e->val << '\n';
-    e->type = elem::NUL;
-    return e;
+    else {
+        return llvm::Constant::getNullValue(t);
+    }
+    assert(0);
+    return NULL;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -260,10 +314,12 @@
     Logger::print("StringExp::toElem: %s | \n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    assert(type->next->ty == Tchar && "Only char is supported");
+    Type* dtype = LLVM_DtoDType(type);
+
+    assert(dtype->next->ty == Tchar && "Only char is supported");
     assert(sz == 1);
 
-    const llvm::Type* ct = LLVM_DtoType(type->next);
+    const llvm::Type* ct = LLVM_DtoType(dtype->next);
     //printf("ct = %s\n", type->next->toChars());
     const llvm::ArrayType* at = llvm::ArrayType::get(ct,len+1);
 
@@ -276,22 +332,20 @@
     llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,"stringliteral",gIR->module);
 
     llvm::ConstantInt* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-    //llvm::Value* arrptr = LLVM_DtoGEP(gvar,zero,zero,"tmp",p->scopebb());
     llvm::Constant* idxs[2] = { zero, zero };
     llvm::Constant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
 
     elem* e = new elem;
 
-    if (type->ty == Tarray) {
+    if (dtype->ty == Tarray) {
         llvm::Constant* clen = llvm::ConstantInt::get(LLVM_DtoSize_t(),len,false);
-        if (p->lvals.empty()) {
+        if (p->lvals.empty() || !p->toplval()) {
             e->type = elem::SLICE;
             e->arg = clen;
             e->mem = arrptr;
             return e;
         }
-        else {
-            llvm::Value* arr = p->toplval();
+        else if (llvm::Value* arr = p->toplval()) {
             if (llvm::isa<llvm::GlobalVariable>(arr)) {
                 e->val = LLVM_DtoConstantSlice(clen, arrptr);
             }
@@ -300,12 +354,14 @@
                 e->inplace = true;
             }
         }
+        else
+        assert(0);
     }
-    else if (type->ty == Tsarray) {
+    else if (dtype->ty == Tsarray) {
         const llvm::Type* dstType = llvm::PointerType::get(llvm::ArrayType::get(ct, len));
         e->mem = new llvm::BitCastInst(gvar, dstType, "tmp", gIR->scopebb());
     }
-    else if (type->ty == Tpointer) {
+    else if (dtype->ty == Tpointer) {
         e->mem = arrptr;
     }
     else {
@@ -319,6 +375,42 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+llvm::Constant* StringExp::toConstElem(IRState* p)
+{
+    Logger::print("StringExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    uint8_t* str = (uint8_t*)string;
+    std::string cont((char*)str, len);
+
+    Type* t = LLVM_DtoDType(type);
+
+    llvm::Constant* _init = llvm::ConstantArray::get(cont,true);
+    if (t->ty == Tsarray) {
+        return _init;
+    }
+    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,"stringliteral",gIR->module);
+
+    llvm::ConstantInt* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+    llvm::Constant* idxs[2] = { zero, zero };
+    llvm::Constant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
+
+    if (t->ty == Tpointer) {
+        return arrptr;
+    }
+
+    if (t->ty == Tarray) {
+        llvm::Constant* clen = llvm::ConstantInt::get(LLVM_DtoSize_t(),len,false);
+        return LLVM_DtoConstantSlice(clen, arrptr);
+    }
+
+    assert(0);
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 elem* AssignExp::toElem(IRState* p)
 {
     Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type->toChars());
@@ -353,30 +445,33 @@
     }
     //e->val = l->store(r->getValue());
 
-    TY e1ty = e1->type->ty;
-    TY e2ty = e2->type->ty;
+    Type* e1type = LLVM_DtoDType(e1->type);
+    Type* e2type = LLVM_DtoDType(e2->type);
+    TY e1ty = e1type->ty;
+    TY e2ty = e2type->ty;
 
     elem* e = new elem;
+    e->type = elem::VAR;
 
     // struct
     if (e1ty == Tstruct) {
+        e->mem = l->mem;
         // struct + struct
         if (e2ty == Tstruct) {
             // struct literals do the assignment themselvs (in place)
             if (!r->inplace) {
-                TypeStruct* ts = (TypeStruct*)e2->type;
-                assert(r->mem);
-                LLVM_DtoStructCopy(ts,l->mem,r->mem);
+                TypeStruct* ts = (TypeStruct*)e2type;
+                LLVM_DtoStructCopy(ts,l->mem,r->getValue());
             }
             else {
                 e->inplace = true;
             }
         }
         // struct + const int
-        else if (e2->type->isintegral()){
+        else if (e2type->isintegral()){
             IntegerExp* iexp = (IntegerExp*)e2;
             assert(iexp->value == 0 && "Only integral struct initializer allowed is zero");
-            TypeStruct* st = (TypeStruct*)e1->type;
+            TypeStruct* st = (TypeStruct*)e1type;
             LLVM_DtoStructZeroInit(st, l->mem);
         }
         // :x
@@ -384,10 +479,10 @@
         assert(0 && "struct = unknown");
     }
     else if (e1ty == Tsarray) {
-        assert(0 && "static array = not supported");
+        assert(0 && "static array not supported");
     }
     else if (e1ty == Tarray) {
-        if (e2->type->isscalar() || e2->type->ty == Tclass){
+        if (e2type->isscalar() || e2type->ty == Tclass){
             LLVM_DtoArrayInit(l->mem, r->getValue());
         }
         else if (e2ty == Tarray) {
@@ -396,16 +491,24 @@
                 llvm::Constant* c = llvm::cast<llvm::Constant>(r->val);
                 assert(c->isNullValue());
                 LLVM_DtoNullArray(l->mem);
+                e->mem = l->mem;
             }
             else if (r->type == elem::SLICE) {
-                if (l->type == elem::SLICE)
-                LLVM_DtoArrayCopy(l,r);
-                else
-                LLVM_DtoSetArray(l->mem,r->arg,r->mem);
+                if (l->type == elem::SLICE) {
+                    LLVM_DtoArrayCopy(l,r);
+                    e->type = elem::SLICE;
+                    e->mem = l->mem;
+                    e->arg = l->arg;
+                }
+                else {
+                    LLVM_DtoSetArray(l->mem,r->arg,r->mem);
+                    e->mem = l->mem;
+                }
             }
             else {
                 // new expressions write directly to the array reference
                 // so do string literals
+                e->mem = l->mem;
                 if (!r->inplace) {
                     assert(r->mem);
                     LLVM_DtoArrayAssign(l->mem, r->mem);
@@ -419,6 +522,7 @@
         assert(0);
     }
     else if (e1ty == Tpointer) {
+        e->mem = l->mem;
         if (e2ty == Tpointer) {
             llvm::Value* v = r->field ? r->mem : r->getValue();
             Logger::cout() << "*=*: " << *v << ", " << *l->mem << '\n';
@@ -433,15 +537,17 @@
             Logger::cout() << "tmp: " << *tmp << " ||| " << *l->mem << '\n';
             // assignment to this in constructor special case
             if (l->isthis) {
-                FuncDeclaration* fdecl = p->funcdecls.back();
+                FuncDeclaration* fdecl = p->func().decl;
                 // respecify the this param
                 if (!llvm::isa<llvm::AllocaInst>(fdecl->llvmThisVar))
                     fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", p->topallocapoint());
                 new llvm::StoreInst(tmp, fdecl->llvmThisVar, p->scopebb());
+                e->mem = fdecl->llvmThisVar;
             }
             // regular class ref -> class ref assignment
             else {
                 new llvm::StoreInst(tmp, l->mem, p->scopebb());
+                e->mem = l->mem;
             }
         }
         else
@@ -454,6 +560,7 @@
                 llvm::Constant* c = llvm::cast<llvm::Constant>(r->val);
                 if (c->isNullValue()) {
                     LLVM_DtoNullDelegate(l->mem);
+                    e->mem = l->mem;
                 }
                 else
                 assert(0);
@@ -461,6 +568,7 @@
             else if (r->inplace) {
                 // do nothing
                 e->inplace = true;
+                e->mem = l->mem;
             }
             else
             assert(0);
@@ -472,10 +580,12 @@
     else {
         Logger::cout() << *l->mem << '\n';
         new llvm::StoreInst(r->getValue(),l->mem,p->scopebb());
+        e->mem = l->mem;
     }
 
     delete r;
     delete l;
+
     return e;
 }
 
@@ -489,15 +599,19 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
-    if (e1->type != e2->type) {
-        if (e1->type->ty == Tpointer && e1->type->next->ty == Tstruct) {
+    Type* t = LLVM_DtoDType(type);
+    Type* e1type = LLVM_DtoDType(e1->type);
+    Type* e2type = LLVM_DtoDType(e2->type);
+
+    if (e1type != e2type) {
+        if (e1type->ty == Tpointer && e1type->next->ty == Tstruct) {
             //assert(l->field);
             assert(r->type == elem::CONST);
             llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->val);
 
-            TypeStruct* ts = (TypeStruct*)e1->type->next;
+            TypeStruct* ts = (TypeStruct*)e1type->next;
             std::vector<unsigned> offsets(1,0);
-            ts->sym->offsetToIndex(type->next, cofs->getZExtValue(), offsets);
+            ts->sym->offsetToIndex(t->next, cofs->getZExtValue(), offsets);
             e->mem = LLVM_DtoGEP(l->getValue(), offsets, "tmp", p->scopebb());
             e->type = elem::VAR;
             e->field = true;
@@ -529,9 +643,11 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
+    Type* e1type = LLVM_DtoDType(e1->type);
+
     elem* e = new elem;
     llvm::Value* val = 0;
-    if (e1->type->ty == Tpointer) {
+    if (e1type->ty == Tpointer) {
         val = e->mem = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb());
     }
     else {
@@ -598,8 +714,10 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
+    Type* e1type = LLVM_DtoDType(e1->type);
+
     llvm::Value* tmp = 0;
-    if (e1->type->ty == Tpointer) {
+    if (e1type->ty == Tpointer) {
         tmp = r->getValue();
         llvm::Value* zero = llvm::ConstantInt::get(tmp->getType(),0,false);
         tmp = llvm::BinaryOperator::createSub(zero,tmp,"tmp",p->scopebb());
@@ -690,11 +808,13 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
-    if (type->isunsigned())
+    Type* t = LLVM_DtoDType(type);
+
+    if (t->isunsigned())
         e->val = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isintegral())
+    else if (t->isintegral())
         e->val = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isfloating())
+    else if (t->isfloating())
         e->val = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
     else
         assert(0);
@@ -714,12 +834,14 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
+    Type* t = LLVM_DtoDType(type);
+
     llvm::Value* tmp;
-    if (type->isunsigned())
+    if (t->isunsigned())
         tmp = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isintegral())
+    else if (t->isintegral())
         tmp = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isfloating())
+    else if (t->isfloating())
         tmp = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
     else
         assert(0);
@@ -753,11 +875,13 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
-    if (type->isunsigned())
+    Type* t = LLVM_DtoDType(type);
+
+    if (t->isunsigned())
         e->val = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isintegral())
+    else if (t->isintegral())
         e->val = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isfloating())
+    else if (t->isfloating())
         e->val = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
     else
         assert(0);
@@ -777,12 +901,14 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
+    Type* t = LLVM_DtoDType(type);
+
     llvm::Value* tmp;
-    if (type->isunsigned())
+    if (t->isunsigned())
         tmp = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isintegral())
+    else if (t->isintegral())
         tmp = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
-    else if (type->isfloating())
+    else if (t->isfloating())
         tmp = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
     else
         assert(0);
@@ -825,9 +951,11 @@
 
     TypeFunction* tf = 0;
 
+    Type* e1type = LLVM_DtoDType(e1->type);
+
     // regular functions
-    if (e1->type->ty == Tfunction) {
-        tf = (TypeFunction*)e1->type;
+    if (e1type->ty == Tfunction) {
+        tf = (TypeFunction*)e1type;
         if (tf->llvmRetInPtr) {
             retinptr = true;
         }
@@ -835,10 +963,10 @@
     }
 
     // delegates
-    else if (e1->type->ty == Tdelegate) {
-        Logger::println("delegateTy = %s\n", e1->type->toChars());
-        assert(e1->type->next->ty == Tfunction);
-        tf = (TypeFunction*)e1->type->next;
+    else if (e1type->ty == Tdelegate) {
+        Logger::println("delegateTy = %s\n", e1type->toChars());
+        assert(e1type->next->ty == Tfunction);
+        tf = (TypeFunction*)e1type->next;
         if (tf->llvmRetInPtr) {
             retinptr = true;
         }
@@ -899,13 +1027,12 @@
     llvm::FunctionType::param_iterator argiter = llfnty->param_begin();
     int j = 0;
 
-    // hidden struct return parameter
+    // hidden struct return arguments
     if (retinptr) {
         if (!p->lvals.empty()) {
             assert(llvm::isa<llvm::StructType>(p->toplval()->getType()->getContainedType(0)));
             llargs[j] = p->toplval();
-            TY Dty = tf->next->ty;
-            if (Dty == Tstruct || Dty == Tdelegate || Dty == Tarray) {
+            if (LLVM_DtoIsPassedByRef(tf->next)) {
                 e->inplace = true;
             }
             else
@@ -922,7 +1049,7 @@
         e->type = elem::VAL;
     }
 
-    // this parameter
+    // this arguments
     if (fn->arg) {
         Logger::println("This Call");
         if (fn->arg->getType() != argiter->get()) {
@@ -935,7 +1062,7 @@
         ++j;
         ++argiter;
     }
-    // delegate context parameter
+    // delegate context arguments
     else if (delegateCall) {
         Logger::println("Delegate Call");
         llvm::Value* contextptr = LLVM_DtoGEP(fn->mem,zero,zero,"tmp",p->scopebb());
@@ -944,75 +1071,11 @@
         ++argiter;
     }
 
-    // regular parameters
+    // regular arguments
     for (int i=0; i<arguments->dim; i++,j++)
     {
-        Expression* argexp = (Expression*)arguments->data[i];
-        elem* arg = argexp->toElem(p);
-        if (arg->inplace) {
-            assert(arg->mem);
-            llargs[j] = arg->mem;
-            continue;
-        }
-
         Argument* fnarg = Argument::getNth(tf->parameters, i);
-
-        TY argty = argexp->type->ty;
-        if (argty == Tstruct || argty == Tdelegate || argty == Tarray) {
-            if (!fnarg || !fnarg->llvmCopy) {
-                llargs[j] = arg->getValue();
-                assert(llargs[j] != 0);
-            }
-            else {
-                llvm::Value* allocaInst = 0;
-                llvm::BasicBlock* entryblock = &p->topfunc()->front();
-                const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(arg->mem->getType());
-                if (argty == Tstruct) {
-                    allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", p->topallocapoint());
-                    TypeStruct* ts = (TypeStruct*)argexp->type;
-                    LLVM_DtoStructCopy(ts,allocaInst,arg->mem);
-                }
-                else if (argty == Tdelegate) {
-                    allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", p->topallocapoint());
-                    LLVM_DtoDelegateCopy(allocaInst,arg->mem);
-                }
-                else if (argty == Tarray) {
-                    if (arg->type == elem::SLICE) {
-                        allocaInst = new llvm::AllocaInst(LLVM_DtoType(argexp->type), "tmpparam", p->topallocapoint());
-                        LLVM_DtoSetArray(allocaInst, arg->arg, arg->mem);
-                    }
-                    else {
-                        allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", p->topallocapoint());
-                        LLVM_DtoArrayAssign(allocaInst,arg->mem);
-                    }
-                }
-                else
-                assert(0);
-
-                llargs[j] = allocaInst;
-                assert(llargs[j] != 0);
-            }
-        }
-        else if (!fnarg || fnarg->llvmCopy) {
-            Logger::println("regular arg");
-            assert(arg->type != elem::SLICE);
-            llargs[j] = arg->arg ? arg->arg : arg->getValue();
-            assert(llargs[j] != 0);
-        }
-        else {
-            Logger::println("as ptr arg");
-            llargs[j] = arg->mem ? arg->mem : arg->val;
-            if (llargs[j]->getType() != llfnty->getParamType(j))
-            {
-                assert(llargs[j]->getType() == llfnty->getParamType(j)->getContainedType(0));
-                LLVM_DtoGiveArgumentStorage(arg);
-                new llvm::StoreInst(llargs[j], arg->mem, p->scopebb());
-                llargs[j] = arg->mem;
-            }
-            assert(llargs[j] != 0);
-        }
-
-        delete arg;
+        llargs[j] = LLVM_DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]);
     }
 
     // void returns cannot not be named
@@ -1053,37 +1116,38 @@
     LOG_SCOPE;
     elem* e = new elem;
     elem* u = e1->toElem(p);
-    const llvm::Type* totype = LLVM_DtoType(to);
-    Type* from = e1->type;
-    int lsz = from->size();
-    int rsz = to->size();
+    const llvm::Type* tolltype = LLVM_DtoType(to);
+    Type* fromtype = LLVM_DtoDType(e1->type);
+    Type* totype = LLVM_DtoDType(to);
+    int lsz = fromtype->size();
+    int rsz = totype->size();
 
     // this makes sure the strange lvalue casts don't screw things up
     e->mem = u->mem;
 
-    if (from->isintegral()) {
-        if (to->isintegral()) {
+    if (fromtype->isintegral()) {
+        if (totype->isintegral()) {
             if (lsz < rsz) {
-                Logger::cout() << *totype << '\n';
-                if (from->isunsigned() || from->ty == Tbool) {
-                    e->val = new llvm::ZExtInst(u->getValue(), totype, "tmp", p->scopebb());
+                Logger::cout() << *tolltype << '\n';
+                if (fromtype->isunsigned() || fromtype->ty == Tbool) {
+                    e->val = new llvm::ZExtInst(u->getValue(), tolltype, "tmp", p->scopebb());
                 } else {
-                    e->val = new llvm::SExtInst(u->getValue(), totype, "tmp", p->scopebb());
+                    e->val = new llvm::SExtInst(u->getValue(), tolltype, "tmp", p->scopebb());
                 }
             }
             else if (lsz > rsz) {
-                e->val = new llvm::TruncInst(u->getValue(), totype, "tmp", p->scopebb());
+                e->val = new llvm::TruncInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
             else {
-                e->val = new llvm::BitCastInst(u->getValue(), totype, "tmp", p->scopebb());
+                e->val = new llvm::BitCastInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
         }
-        else if (to->isfloating()) {
-            if (from->isunsigned()) {
-                e->val = new llvm::UIToFPInst(u->getValue(), totype, "tmp", p->scopebb());
+        else if (totype->isfloating()) {
+            if (fromtype->isunsigned()) {
+                e->val = new llvm::UIToFPInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
             else {
-                e->val = new llvm::SIToFPInst(u->getValue(), totype, "tmp", p->scopebb());
+                e->val = new llvm::SIToFPInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
         }
         else {
@@ -1092,27 +1156,27 @@
         //e->storeVal = u->storeVal ? u->storeVal : u->val;
         e->type = elem::VAL;
     }
-    else if (from->isfloating()) {
-        if (to->isfloating()) {
-            if ((from->ty == Tfloat80 || from->ty == Tfloat64) && (to->ty == Tfloat80 || to->ty == Tfloat64)) {
+    else if (fromtype->isfloating()) {
+        if (totype->isfloating()) {
+            if ((fromtype->ty == Tfloat80 || fromtype->ty == Tfloat64) && (totype->ty == Tfloat80 || totype->ty == Tfloat64)) {
                 e->val = u->getValue();
             }
             else if (lsz < rsz) {
-                e->val = new llvm::FPExtInst(u->getValue(), totype, "tmp", p->scopebb());
+                e->val = new llvm::FPExtInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
             else if (lsz > rsz) {
-                e->val = new llvm::FPTruncInst(u->getValue(), totype, "tmp", p->scopebb());
+                e->val = new llvm::FPTruncInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
             else {
                 assert(0);
             }
         }
-        else if (to->isintegral()) {
-            if (to->isunsigned()) {
-                e->val = new llvm::FPToUIInst(u->getValue(), totype, "tmp", p->scopebb());
+        else if (totype->isintegral()) {
+            if (totype->isunsigned()) {
+                e->val = new llvm::FPToUIInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
             else {
-                e->val = new llvm::FPToSIInst(u->getValue(), totype, "tmp", p->scopebb());
+                e->val = new llvm::FPToSIInst(u->getValue(), tolltype, "tmp", p->scopebb());
             }
         }
         else {
@@ -1120,26 +1184,26 @@
         }
         e->type = elem::VAL;
     }
-    else if (from->ty == Tclass) {
+    else if (fromtype->ty == Tclass) {
         //assert(to->ty == Tclass);
-        e->val = new llvm::BitCastInst(u->getValue(), totype, "tmp", p->scopebb());
+        e->val = new llvm::BitCastInst(u->getValue(), tolltype, "tmp", p->scopebb());
         e->type = elem::VAL;
     }
-    else if (from->ty == Tarray || from->ty == Tsarray) {
+    else if (fromtype->ty == Tarray || fromtype->ty == Tsarray) {
         Logger::cout() << "from array or sarray" << '\n';
-        if (to->ty == Tpointer) {
+        if (totype->ty == Tpointer) {
             Logger::cout() << "to pointer" << '\n';
-            assert(from->next == to->next);
+            assert(fromtype->next == totype->next);
             llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
             llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
             llvm::Value* ptr = LLVM_DtoGEP(u->getValue(),zero,one,"tmp",p->scopebb());
             e->val = new llvm::LoadInst(ptr, "tmp", p->scopebb());
             e->type = elem::VAL;
         }
-        else if (to->ty == Tarray) {
+        else if (totype->ty == Tarray) {
             Logger::cout() << "to array" << '\n';
-            assert(from->next->size() == to->next->size());
-            const llvm::Type* ptrty = LLVM_DtoType(to->next);
+            assert(fromtype->next->size() == totype->next->size());
+            const llvm::Type* ptrty = LLVM_DtoType(totype->next);
             if (ptrty == llvm::Type::VoidTy)
                 ptrty = llvm::Type::Int8Ty;
             ptrty = llvm::PointerType::get(ptrty);
@@ -1150,7 +1214,7 @@
             }
             else {
                 llvm::Value* uval = u->getValue();
-                if (from->ty == Tsarray) {
+                if (fromtype->ty == Tsarray) {
                     Logger::cout() << "uvalTy = " << *uval->getType() << '\n';
                     assert(llvm::isa<llvm::PointerType>(uval->getType()));
                     const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(uval->getType()->getContainedType(0));
@@ -1171,7 +1235,7 @@
             }
             e->type = elem::SLICE;
         }
-        else if (to->ty == Tsarray) {
+        else if (totype->ty == Tsarray) {
             Logger::cout() << "to sarray" << '\n';
             assert(0);
         }
@@ -1179,14 +1243,14 @@
             assert(0);
         }
     }
-    else if (from->ty == Tpointer) {
-        if (to->ty == Tpointer || to->ty == Tclass) {
+    else if (fromtype->ty == Tpointer) {
+        if (totype->ty == Tpointer || totype->ty == Tclass) {
             llvm::Value* src = u->getValue();
             //Logger::cout() << *src << '|' << *totype << '\n';
-            e->val = new llvm::BitCastInst(src, totype, "tmp", p->scopebb());
+            e->val = new llvm::BitCastInst(src, tolltype, "tmp", p->scopebb());
         }
-        else if (to->isintegral()) {
-            e->val = new llvm::PtrToIntInst(u->getValue(), totype, "tmp", p->scopebb());
+        else if (totype->isintegral()) {
+            e->val = new llvm::PtrToIntInst(u->getValue(), tolltype, "tmp", p->scopebb());
         }
         else
         assert(0);
@@ -1210,18 +1274,20 @@
     {
         Logger::println("VarDeclaration");
         assert(vd->llvmValue);
-        if (vd->type->ty == Tstruct && !(type->ty == Tpointer && type->next == vd->type)) {
-            TypeStruct* vdt = (TypeStruct*)vd->type;
+        Type* t = LLVM_DtoDType(type);
+        Type* vdtype = LLVM_DtoDType(vd->type);
+        if (vdtype->ty == Tstruct && !(t->ty == Tpointer && t->next == vdtype)) {
+            TypeStruct* vdt = (TypeStruct*)vdtype;
             e = new elem;
             std::vector<unsigned> dst(1,0);
-            vdt->sym->offsetToIndex(type->next, offset, dst);
+            vdt->sym->offsetToIndex(t->next, offset, dst);
             llvm::Value* ptr = vd->llvmValue;
             assert(ptr);
             e->mem = LLVM_DtoGEP(ptr,dst,"tmp",p->scopebb());
             e->type = elem::VAL;
             e->field = true;
         }
-        else if (vd->type->ty == Tsarray) {
+        else if (vdtype->ty == Tsarray) {
             /*e = new elem;
             llvm::Value* idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
             e->val = new llvm::GetElementPtrInst(vd->llvmValue,idx0,idx0,"tmp",p->scopebb());*/
@@ -1294,26 +1360,30 @@
 
     elem* l = e1->toElem(p);
 
-    Logger::print("e1->type=%s\n", e1->type->toChars());
+    Type* t = LLVM_DtoDType(type);
+    Type* e1type = LLVM_DtoDType(e1->type);
+
+    Logger::print("e1->type=%s\n", e1type->toChars());
 
     if (VarDeclaration* vd = var->isVarDeclaration()) {
         std::vector<unsigned> vdoffsets(1,0);
         llvm::Value* src = 0;
-        if (e1->type->ty == Tpointer) {
-            assert(e1->type->next->ty == Tstruct);
-            TypeStruct* ts = (TypeStruct*)e1->type->next;
+        if (e1type->ty == Tpointer) {
+            assert(e1type->next->ty == Tstruct);
+            TypeStruct* ts = (TypeStruct*)e1type->next;
             ts->sym->offsetToIndex(vd->type, vd->offset, vdoffsets);
             Logger::println("Struct member offset:%d", vd->offset);
             src = l->val ? l->val : l->mem;
         }
         else if (e1->type->ty == Tclass) {
-            TypeClass* tc = (TypeClass*)e1->type;
+            TypeClass* tc = (TypeClass*)e1type;
             Logger::println("Class member offset: %d", vd->offset);
             tc->sym->offsetToIndex(vd->type, vd->offset, vdoffsets);
             src = l->getValue();
         }
         assert(vdoffsets.size() != 1);
         assert(src != 0);
+        Logger::cout() << "src: " << *src << '\n';
         llvm::Value* arrptr = LLVM_DtoGEP(src,vdoffsets,"tmp",p->scopebb());
         e->mem = arrptr;
         Logger::cout() << "mem: " << *e->mem << '\n';
@@ -1332,7 +1402,7 @@
         // virtual call
         if (fdecl->isVirtual()) {
             assert(fdecl->vtblIndex > 0);
-            assert(e1->type->ty == Tclass);
+            assert(e1type->ty == Tclass);
 
             llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
             llvm::Value* vtblidx = llvm::ConstantInt::get(llvm::Type::Int32Ty, (size_t)fdecl->vtblIndex, false);
@@ -1365,22 +1435,7 @@
     elem* e = new elem;
 
     if (VarDeclaration* vd = var->isVarDeclaration()) {
-        /*assert(vd->llvmValue == 0);
-
-        llvm::Function* fn = p->topfunc();
-        assert(fn);
-
-        TypeFunction* tf = p->topfunctype();
-        assert(tf);
-
-        llvm::Value* v = 0;
-        if (tf->llvmRetInPtr)
-        v = ++fn->arg_begin();
-        else
-        v = fn->arg_begin();
-        assert(v);*/
-
-        llvm::Value* v = p->funcdecls.back()->llvmThisVar;
+        llvm::Value* v = p->func().decl->llvmThisVar;
         if (llvm::isa<llvm::AllocaInst>(v))
             v = new llvm::LoadInst(v, "tmp", p->scopebb());
         e->mem = v;
@@ -1440,15 +1495,22 @@
 
         Expression* vx = (Expression*)elements->data[i];
         if (vx != 0) {
+            p->lvals.push_back(arrptr);
             elem* ve = vx->toElem(p);
-            llvm::Value* val = ve->getValue();
-            Logger::cout() << *val << " | " << *arrptr << '\n';
-            if (vx->type->ty == Tstruct) {
-                TypeStruct* ts = (TypeStruct*)vx->type;
-                LLVM_DtoStructCopy(ts,arrptr,val);
+            p->lvals.pop_back();
+
+            if (!ve->inplace) {
+                llvm::Value* val = ve->getValue();
+                Logger::cout() << *val << " | " << *arrptr << '\n';
+
+                Type* vxtype = LLVM_DtoDType(vx->type);
+                if (vxtype->ty == Tstruct) {
+                    TypeStruct* ts = (TypeStruct*)vxtype;
+                    LLVM_DtoStructCopy(ts,arrptr,val);
+                }
+                else
+                    new llvm::StoreInst(val, arrptr, p->scopebb());
             }
-            else
-                new llvm::StoreInst(val, arrptr, p->scopebb());
             delete ve;
         }
         else {
@@ -1463,6 +1525,28 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+llvm::Constant* StructLiteralExp::toConstElem(IRState* p)
+{
+    Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    unsigned n = elements->dim;
+    std::vector<llvm::Constant*> vals(n, NULL);
+
+    for (unsigned i=0; i<n; ++i)
+    {
+        Expression* vx = (Expression*)elements->data[i];
+        vals[i] = vx->toConstElem(p);
+    }
+
+    assert(LLVM_DtoDType(type)->ty == Tstruct);
+    const llvm::Type* t = LLVM_DtoType(type);
+    const llvm::StructType* st = llvm::cast<llvm::StructType>(t);
+    return llvm::ConstantStruct::get(st,vals);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 elem* IndexExp::toElem(IRState* p)
 {
     Logger::print("IndexExp::toElem: %s | %s\n", toChars(), type->toChars());
@@ -1472,6 +1556,8 @@
 
     elem* l = e1->toElem(p);
 
+    Type* e1type = LLVM_DtoDType(e1->type);
+
     p->arrays.push_back(l->mem); // if $ is used it must be an array so this is fine.
     elem* r = e2->toElem(p);
     p->arrays.pop_back();
@@ -1480,13 +1566,13 @@
     llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
 
     llvm::Value* arrptr = 0;
-    if (e1->type->ty == Tpointer) {
+    if (e1type->ty == Tpointer) {
         arrptr = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb());
     }
-    else if (e1->type->ty == Tsarray) {
-        arrptr = LLVM_DtoGEP(l->mem, zero, r->getValue(),"tmp",p->scopebb());
+    else if (e1type->ty == Tsarray) {
+        arrptr = LLVM_DtoGEP(l->getValue(), zero, r->getValue(),"tmp",p->scopebb());
     }
-    else if (e1->type->ty == Tarray) {
+    else if (e1type->ty == Tarray) {
         arrptr = LLVM_DtoGEP(l->mem,zero,one,"tmp",p->scopebb());
         arrptr = new llvm::LoadInst(arrptr,"tmp",p->scopebb());
         arrptr = new llvm::GetElementPtrInst(arrptr,r->getValue(),"tmp",p->scopebb());
@@ -1510,6 +1596,7 @@
     LOG_SCOPE;
 
     elem* v = e1->toElem(p);
+    Type* e1type = LLVM_DtoDType(e1->type);
 
     elem* e = new elem;
     assert(v->mem);
@@ -1531,13 +1618,16 @@
             assert(lo->val);
             assert(llvm::isa<llvm::ConstantInt>(lo->val));
 
-            if (e1->type->ty == Tpointer) {
+            if (e1type->ty == Tpointer) {
                 e->mem = v->getValue();
             }
-            else if (e1->type->ty == Tarray) {
+            else if (e1type->ty == Tarray) {
                 llvm::Value* tmp = LLVM_DtoGEP(v->mem,zero,one,"tmp",p->scopebb());
                 e->mem = new llvm::LoadInst(tmp,"tmp",p->scopebb());
             }
+            else if (e1type->ty == Tsarray) {
+                e->mem = LLVM_DtoGEP(v->mem,zero,zero,"tmp",p->scopebb());
+            }
             else
             assert(e->mem);
 
@@ -1548,9 +1638,16 @@
         }
         else
         {
-            llvm::Value* tmp = LLVM_DtoGEP(v->mem,zero,one,"tmp",p->scopebb());
-            tmp = new llvm::LoadInst(tmp,"tmp",p->scopebb());
-            e->mem = new llvm::GetElementPtrInst(tmp,lo->getValue(),"tmp",p->scopebb());
+            if (e1type->ty == Tarray) {
+                llvm::Value* tmp = LLVM_DtoGEP(v->mem,zero,one,"tmp",p->scopebb());
+                tmp = new llvm::LoadInst(tmp,"tmp",p->scopebb());
+                e->mem = new llvm::GetElementPtrInst(tmp,lo->getValue(),"tmp",p->scopebb());
+            }
+            else if (e1type->ty == Tsarray) {
+                e->mem = LLVM_DtoGEP(v->mem,zero,lo->getValue(),"tmp",p->scopebb());
+            }
+            else
+            assert(0);
         }
 
         elem* up = upr->toElem(p);
@@ -1610,31 +1707,54 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
-    assert(e1->type == e2->type);
-
-    Type* t = e1->type;
+    Type* t = LLVM_DtoDType(e1->type);
+    Type* e2t = LLVM_DtoDType(e2->type);
+    assert(t == e2t);
 
     if (t->isintegral())
     {
         llvm::ICmpInst::Predicate cmpop;
+        bool skip = false;
         switch(op)
         {
         case TOKlt:
+        case TOKul:
             cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_ULT : llvm::ICmpInst::ICMP_SLT;
             break;
         case TOKle:
+        case TOKule:
             cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_ULE : llvm::ICmpInst::ICMP_SLE;
             break;
         case TOKgt:
+        case TOKug:
             cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_UGT : llvm::ICmpInst::ICMP_SGT;
             break;
         case TOKge:
+        case TOKuge:
             cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_UGE : llvm::ICmpInst::ICMP_SGE;
             break;
+        case TOKue:
+            cmpop = llvm::ICmpInst::ICMP_EQ;
+            break;
+        case TOKlg:
+            cmpop = llvm::ICmpInst::ICMP_NE;
+            break;
+        case TOKleg:
+            skip = true;
+            e->val = llvm::ConstantInt::getTrue();
+            break;
+        case TOKunord:
+            skip = true;
+            e->val = llvm::ConstantInt::getFalse();
+            break;
+
         default:
             assert(0);
         }
-        e->val = new llvm::ICmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb());
+        if (!skip)
+        {
+            e->val = new llvm::ICmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb());
+        }
     }
     else if (t->isfloating())
     {
@@ -1696,9 +1816,9 @@
     elem* l = e1->toElem(p);
     elem* r = e2->toElem(p);
 
-    assert(e1->type == e2->type);
-
-    Type* t = e1->type;
+    Type* t = LLVM_DtoDType(e1->type);
+    Type* e2t = LLVM_DtoDType(e2->type);
+    assert(t == e2t);
 
     if (t->isintegral() || t->ty == Tpointer)
     {
@@ -1732,10 +1852,13 @@
         }
         e->val = new llvm::FCmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb());
     }
+    else if (t->ty == Tsarray)
+    {
+        e->val = LLVM_DtoStaticArrayCompare(op,l->mem,r->mem);
+    }
     else if (t->ty == Tarray)
     {
-        // array comparison invokes the typeinfo runtime
-        assert(0);
+        assert(0 && "array comparison invokes the typeinfo runtime");
     }
     else
     {
@@ -1768,10 +1891,13 @@
     llvm::Value* val = e->val;
     llvm::Value* post = 0;
 
-    if (e1->type->isintegral())
+    Type* e1type = LLVM_DtoDType(e1->type);
+    Type* e2type = LLVM_DtoDType(e2->type);
+
+    if (e1type->isintegral())
     {
-        assert(e2->type->isintegral());
-        llvm::Value* one = llvm::ConstantInt::get(val->getType(), 1, !e2->type->isunsigned());
+        assert(e2type->isintegral());
+        llvm::Value* one = llvm::ConstantInt::get(val->getType(), 1, !e2type->isunsigned());
         if (op == TOKplusplus) {
             post = llvm::BinaryOperator::createAdd(val,one,"tmp",p->scopebb());
         }
@@ -1779,17 +1905,17 @@
             post = llvm::BinaryOperator::createSub(val,one,"tmp",p->scopebb());
         }
     }
-    else if (e1->type->ty == Tpointer)
+    else if (e1type->ty == Tpointer)
     {
-        assert(e2->type->isintegral());
+        assert(e2type->isintegral());
         llvm::Constant* minusone = llvm::ConstantInt::get(LLVM_DtoSize_t(),(uint64_t)-1,true);
         llvm::Constant* plusone = llvm::ConstantInt::get(LLVM_DtoSize_t(),(uint64_t)1,false);
         llvm::Constant* whichone = (op == TOKplusplus) ? plusone : minusone;
         post = new llvm::GetElementPtrInst(val, whichone, "tmp", p->scopebb());
     }
-    else if (e1->type->isfloating())
+    else if (e1type->isfloating())
     {
-        assert(e2->type->isfloating());
+        assert(e2type->isfloating());
         llvm::Value* one = llvm::ConstantFP::get(val->getType(), 1.0f);
         if (op == TOKplusplus) {
             post = llvm::BinaryOperator::createAdd(val,one,"tmp",p->scopebb());
@@ -1820,28 +1946,28 @@
     assert(!thisexp);
     assert(!newargs);
     assert(newtype);
-    //assert(!arguments);
-    //assert(!member);
     assert(!allocator);
 
     elem* e = new elem;
 
-    const llvm::Type* t = LLVM_DtoType(newtype);
+    Type* ntype = LLVM_DtoDType(newtype);
+
+    const llvm::Type* t = LLVM_DtoType(ntype);
 
     if (onstack) {
-        assert(newtype->ty == Tclass);
+        assert(ntype->ty == Tclass);
         e->mem = new llvm::AllocaInst(t->getContainedType(0),"tmp",p->topallocapoint());
     }
     else {
-        if (newtype->ty == Tclass) {
+        if (ntype->ty == Tclass) {
             e->mem = new llvm::MallocInst(t->getContainedType(0),"tmp",p->scopebb());
         }
-        else if (newtype->ty == Tarray) {
+        else if (ntype->ty == Tarray) {
             assert(arguments);
             if (arguments->dim == 1) {
                 elem* sz = ((Expression*)arguments->data[0])->toElem(p);
                 llvm::Value* dimval = sz->getValue();
-                LLVM_DtoNewDynArray(p->toplval(), dimval, newtype->next);
+                LLVM_DtoNewDynArray(p->toplval(), dimval, ntype->next);
                 delete sz;
             }
             else {
@@ -1853,32 +1979,32 @@
         }
     }
 
-    if (newtype->ty == Tclass) {
+    if (ntype->ty == Tclass) {
         // first apply the static initializer
         assert(e->mem);
-        LLVM_DtoInitClass((TypeClass*)newtype, e->mem);
+        LLVM_DtoInitClass((TypeClass*)ntype, e->mem);
 
         // then call constructor
         if (arguments) {
+            assert(member);
+            assert(member->llvmValue);
+            llvm::Function* fn = llvm::cast<llvm::Function>(member->llvmValue);
+            TypeFunction* tf = (TypeFunction*)LLVM_DtoDType(member->type);
+
             std::vector<llvm::Value*> ctorargs;
             ctorargs.push_back(e->mem);
             for (size_t i=0; i<arguments->dim; ++i)
             {
                 Expression* ex = (Expression*)arguments->data[i];
-                Logger::println("arg=%s", ex->toChars());
-                elem* exe = ex->toElem(p);
-                llvm::Value* v = exe->getValue();
-                assert(v);
-                ctorargs.push_back(v);
-                delete exe;
+                Argument* fnarg = Argument::getNth(tf->parameters, i);
+                llvm::Value* a = LLVM_DtoArgument(fn->getFunctionType()->getParamType(i+1), fnarg, ex);
+                ctorargs.push_back(a);
             }
-            assert(member);
-            assert(member->llvmValue);
-            e->mem = new llvm::CallInst(member->llvmValue, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb());
+            e->mem = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb());
         }
     }
-    else if (newtype->ty == Tstruct) {
-        TypeStruct* ts = (TypeStruct*)newtype;
+    else if (ntype->ty == Tstruct) {
+        TypeStruct* ts = (TypeStruct*)ntype;
         if (ts->isZeroInit()) {
             LLVM_DtoStructZeroInit(ts,e->mem);
         }
@@ -1909,7 +2035,9 @@
     const llvm::Type* t = val->getType();
     llvm::Constant* z = llvm::Constant::getNullValue(t);
 
-    if (e1->type->ty == Tpointer) {
+    Type* e1type = LLVM_DtoDType(e1->type);
+
+    if (e1type->ty == Tpointer) {
         ldval = v->getValue();
         new llvm::FreeInst(ldval, p->scopebb());
 
@@ -1917,8 +2045,8 @@
         Logger::cout() << *val << '\n';
         new llvm::StoreInst(z, v->mem, p->scopebb());
     }
-    else if (e1->type->ty == Tclass) {
-        TypeClass* tc = (TypeClass*)e1->type;
+    else if (e1type->ty == Tclass) {
+        TypeClass* tc = (TypeClass*)e1type;
         LLVM_DtoCallClassDtors(tc, val);
 
         if (v->vardecl && !v->vardecl->onstack) {
@@ -1926,7 +2054,7 @@
         }
         new llvm::StoreInst(z, v->mem, p->scopebb());
     }
-    else if (e1->type->ty == Tarray) {
+    else if (e1type->ty == Tarray) {
         // must be on the heap (correct?)
         ldval = v->getValue();
         
@@ -2007,7 +2135,8 @@
     llvm::Value* b = LLVM_DtoBoolean(u->getValue());
 
     llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int1Ty, 0, true);
-    e->val = new llvm::ICmpInst(llvm::ICmpInst::ICMP_EQ,b,zero,"tmp",p->scopebb());
+    e->val = p->ir->CreateICmpEQ(b,zero);
+    //e->val = new llvm::ICmpInst(llvm::ICmpInst::ICMP_EQ,b,zero,"tmp",p->scopebb());
     e->type = elem::VAL;
 
     delete u;
@@ -2151,7 +2280,7 @@
     llvm::Value* loca = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
     LLVM_DtoAssert(llvm::ConstantInt::getFalse(), loca, NULL);
 
-    //new llvm::UnreachableInst(p->scopebb());
+    new llvm::UnreachableInst(p->scopebb());
     return 0;
 }
 
@@ -2305,13 +2434,15 @@
     llvm::Value* val = l->getValue();
     delete l;
 
+    Type* t = LLVM_DtoDType(type);
+
     llvm::Value* zero = 0;
-    if (type->isintegral())
+    if (t->isintegral())
         zero = llvm::ConstantInt::get(val->getType(), 0, true);
-    else if (type->isfloating()) {
-        if (type->ty == Tfloat32)
+    else if (t->isfloating()) {
+        if (t->ty == Tfloat32)
             zero = llvm::ConstantFP::get(val->getType(), float(0));
-        else if (type->ty == Tfloat64 || type->ty == Tfloat80)
+        else if (t->ty == Tfloat64 || t->ty == Tfloat80)
             zero = llvm::ConstantFP::get(val->getType(), double(0));
         else
         assert(0);
@@ -2332,7 +2463,7 @@
     Logger::print("CatExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    assert(0 && "array concatenation is not yet implemented");
+    assert(0 && "array cat is not yet implemented");
 
     elem* lhs = e1->toElem(p);
     elem* rhs = e2->toElem(p);
@@ -2347,6 +2478,93 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+elem* CatAssignExp::toElem(IRState* p)
+{
+    Logger::print("CatAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    elem* l = e1->toElem(p);
+    assert(l->mem);
+
+    Type* e1type = LLVM_DtoDType(e1->type);
+    Type* elemtype = LLVM_DtoDType(e1type->next);
+    Type* e2type = LLVM_DtoDType(e2->type);
+
+    if (e2type == elemtype) {
+        LLVM_DtoCatArrayElement(l->mem,e2);
+    }
+    else
+        assert(0 && "only one element at a time right now");
+
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+elem* ArrayLiteralExp::toElem(IRState* p)
+{
+    Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    const llvm::Type* t = LLVM_DtoType(type);
+    Logger::cout() << "array literal has llvm type: " << *t << '\n';
+
+    llvm::Value* mem = 0;
+    if (p->lvals.empty()) {
+        assert(LLVM_DtoDType(type)->ty == Tsarray);
+        mem = new llvm::AllocaInst(t,"tmparrayliteral",p->topallocapoint());
+    }
+    else {
+        mem = p->toplval();
+        if (!llvm::isa<llvm::PointerType>(mem->getType()) ||
+            !llvm::isa<llvm::ArrayType>(mem->getType()->getContainedType(0)))
+        {
+            error("TODO array literals can currently only be used to initialise static arrays");
+            fatal();
+        }
+    }
+
+    for (unsigned i=0; i<elements->dim; ++i)
+    {
+        Expression* expr = (Expression*)elements->data[i];
+        llvm::Value* elemAddr = LLVM_DtoGEPi(mem,0,i,"tmp",p->scopebb());
+        elem* e = expr->toElem(p);
+        new llvm::StoreInst(e->getValue(), elemAddr, p->scopebb());
+    }
+
+    elem* e = new elem;
+    e->mem = mem;
+    e->type = elem::VAL;
+    e->inplace = true;
+
+    return e;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* ArrayLiteralExp::toConstElem(IRState* p)
+{
+    Logger::print("ArrayLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    const llvm::Type* t = LLVM_DtoType(type);
+    Logger::cout() << "array literal has llvm type: " << *t << '\n';
+    assert(llvm::isa<llvm::ArrayType>(t));
+    const llvm::ArrayType* arrtype = llvm::cast<llvm::ArrayType>(t);
+
+    assert(arrtype->getNumElements() == elements->dim);
+    std::vector<llvm::Constant*> vals(elements->dim, NULL);
+    for (unsigned i=0; i<elements->dim; ++i)
+    {
+        Expression* expr = (Expression*)elements->data[i];
+        vals[i] = expr->toConstElem(p);
+    }
+
+    return llvm::ConstantArray::get(arrtype, vals);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 #define STUB(x) elem *x::toElem(IRState * p) {error("Exp type "#x" not implemented: %s", toChars()); fatal(); return 0; }
 //STUB(IdentityExp);
 //STUB(CondExp);
@@ -2374,7 +2592,7 @@
 //STUB(ModExp);
 //STUB(ModAssignExp);
 //STUB(CatExp);
-STUB(CatAssignExp);
+//STUB(CatAssignExp);
 //STUB(AddExp);
 //STUB(AddAssignExp);
 STUB(Expression);
@@ -2417,10 +2635,21 @@
 //STUB(ArrayLengthExp);
 //STUB(HaltExp);
 STUB(RemoveExp);
-STUB(ArrayLiteralExp);
+//STUB(ArrayLiteralExp);
 STUB(AssocArrayLiteralExp);
 //STUB(StructLiteralExp);
 
+#define CONSTSTUB(x) llvm::Constant* x::toConstElem(IRState * p) {error("const Exp type "#x" not implemented: '%s' type: '%s'", toChars(), type->toChars()); assert(0); fatal(); return NULL; }
+CONSTSTUB(Expression);
+//CONSTSTUB(IntegerExp);
+//CONSTSTUB(RealExp);
+//CONSTSTUB(NullExp);
+//CONSTSTUB(StringExp);
+//CONSTSTUB(VarExp);
+//CONSTSTUB(ArrayLiteralExp);
+CONSTSTUB(AssocArrayLiteralExp);
+//CONSTSTUB(StructLiteralExp);
+
 unsigned Type::totym() { return 0; }
 
 type * Type::toCtype()
--- a/gen/tollvm.c	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/tollvm.c	Fri Oct 19 07:43:21 2007 +0200
@@ -1,11 +1,6 @@
 #include <iostream>
 
-#include "llvm/Constants.h"
-#include "llvm/Type.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/GlobalValue.h"
-#include "llvm/Instructions.h"
-#include "llvm/CallingConv.h"
+#include "gen/llvm.h"
 
 #include "mtype.h"
 #include "dsymbol.h"
@@ -20,6 +15,29 @@
 #include "gen/elem.h"
 #include "gen/arrays.h"
 
+bool LLVM_DtoIsPassedByRef(Type* type)
+{
+    TY t = type->ty;
+    if (t == Tstruct || t == Tarray || t == Tdelegate)
+        return true;
+    else if (t == Ttypedef) {
+        Type* bt = type->toBasetype();
+        assert(bt);
+        return LLVM_DtoIsPassedByRef(bt);
+    }
+    return false;
+}
+
+Type* LLVM_DtoDType(Type* t)
+{
+    if (t->ty == Ttypedef) {
+        Type* bt = t->toBasetype();
+        assert(bt);
+        return LLVM_DtoDType(bt);
+    }
+    return t;
+}
+
 const llvm::Type* LLVM_DtoType(Type* t)
 {
     assert(t);
@@ -167,9 +185,7 @@
     const llvm::Type* rettype;
     std::vector<const llvm::Type*> paramvec;
 
-    TY retty = f->next->ty;
-
-    if (retty == Tstruct || retty == Tdelegate || retty == Tarray) {
+    if (LLVM_DtoIsPassedByRef(f->next)) {
         rettype = llvm::PointerType::get(LLVM_DtoType(f->next));
         paramvec.push_back(rettype);
         rettype = llvm::Type::VoidTy;
@@ -225,7 +241,7 @@
         actualRettype = rettype;
     }
     else if (rt) {
-        if (rt->ty == Tstruct || rt->ty == Tdelegate || rt->ty == Tarray) {
+        if (LLVM_DtoIsPassedByRef(rt)) {
             rettype = llvm::PointerType::get(LLVM_DtoType(rt));
             actualRettype = llvm::Type::VoidTy;
             f->llvmRetInPtr = retinptr = true;
@@ -265,7 +281,7 @@
     for (int i=0; i < n; ++i) {
         Argument* arg = Argument::getNth(f->parameters, i);
         // ensure scalar
-        Type* argT = arg->type;
+        Type* argT = LLVM_DtoDType(arg->type);
         assert(argT);
 
         if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
@@ -286,6 +302,16 @@
             //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0)));
             paramvec.push_back(llvm::PointerType::get(at));
         }
+        else if (llvm::isa<llvm::OpaqueType>(at)) {
+            Logger::println("opaque param");
+            if (argT->ty == Tstruct || argT->ty == Tclass)
+                paramvec.push_back(llvm::PointerType::get(at));
+            else
+            assert(0);
+        }
+        /*if (llvm::isa<llvm::StructType>(at) || argT->ty == Tstruct || argT->ty == Tsarray) {
+            paramvec.push_back(llvm::PointerType::get(at));
+        }*/
         else {
             if (!arg->llvmCopy) {
                 Logger::println("ref param");
@@ -453,7 +479,7 @@
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-llvm::Constant* LLVM_DtoStructInitializer(StructInitializer* si)
+llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si)
 {
     llvm::StructType* structtype = llvm::cast<llvm::StructType>(si->ad->llvmType);
     size_t n = structtype->getNumElements();
@@ -468,11 +494,12 @@
         assert(ini);
 
         VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
+        Type* vdtype = LLVM_DtoDType(vd->type);
         assert(vd);
         Logger::println("vars[%d] = %s", i, vd->toChars());
 
         std::vector<unsigned> idxs;
-        si->ad->offsetToIndex(vd->type, vd->offset, idxs);
+        si->ad->offsetToIndex(vdtype, vd->offset, idxs);
         assert(idxs.size() == 1);
         unsigned idx = idxs[0];
 
@@ -480,17 +507,15 @@
 
         if (ExpInitializer* ex = ini->isExpInitializer())
         {
-            elem* e = ex->exp->toElem(gIR);
-            v = llvm::cast<llvm::Constant>(e->val);
-            delete e;
+            v = ex->exp->toConstElem(gIR);
         }
         else if (StructInitializer* si = ini->isStructInitializer())
         {
-            v = LLVM_DtoStructInitializer(si);
+            v = LLVM_DtoConstStructInitializer(si);
         }
         else if (ArrayInitializer* ai = ini->isArrayInitializer())
         {
-            v = LLVM_DtoArrayInitializer(ai);
+            v = LLVM_DtoConstArrayInitializer(ai);
         }
         else if (ini->isVoidInitializer())
         {
@@ -731,20 +756,6 @@
 
     // return
     new llvm::ReturnInst(call,bb);
-
-    /*
-    // return value type
-    const llvm::Type* rettype;
-    Type* rt = f->next;
-    if (rt) {
-        rettype = LLVM_DtoType(rt);
-    }
-    else {
-        assert(0);
-    }
-
-    llvm::FunctionType* functype = llvm::FunctionType::get(rettype, paramvec, false);
-    */
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -802,47 +813,54 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::Constant* LLVM_DtoInitializer(Type* type, Initializer* init)
+llvm::Constant* LLVM_DtoConstInitializer(Type* type, Initializer* init)
 {
     llvm::Constant* _init = 0; // may return zero
     if (!init)
     {
-        Logger::println("default initializer");
-        elem* e = type->defaultInit()->toElem(gIR);
-        if (!e->inplace && !e->isNull()) {
-            _init = llvm::cast<llvm::Constant>(e->getValue());
-        }
-        delete e;
+        Logger::println("const default initializer for %s", type->toChars());
+        _init = type->defaultInit()->toConstElem(gIR);
     }
     else if (ExpInitializer* ex = init->isExpInitializer())
     {
-        Logger::println("expression initializer");
-        elem* e = ex->exp->toElem(gIR);
-        if (!e->inplace && !e->isNull()) {
-            _init = llvm::cast<llvm::Constant>(e->getValue());
-        }
-        delete e;
+        Logger::println("const expression initializer");
+        _init = ex->exp->toConstElem(gIR);
     }
     else if (StructInitializer* si = init->isStructInitializer())
     {
-        Logger::println("struct initializer");
-        _init = LLVM_DtoStructInitializer(si);
+        Logger::println("const struct initializer");
+        _init = LLVM_DtoConstStructInitializer(si);
     }
     else if (ArrayInitializer* ai = init->isArrayInitializer())
     {
-        Logger::println("array initializer");
-        _init = LLVM_DtoArrayInitializer(ai);
+        Logger::println("const array initializer");
+        _init = LLVM_DtoConstArrayInitializer(ai);
     }
     else if (init->isVoidInitializer())
     {
-        Logger::println("void initializer");
+        Logger::println("const void initializer");
         const llvm::Type* ty = LLVM_DtoType(type);
         _init = llvm::Constant::getNullValue(ty);
     }
     else {
+        Logger::println("unsupported const initializer: %s", init->toChars());
+    }
+    return _init;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void LLVM_DtoInitializer(Initializer* init)
+{
+    if (ExpInitializer* ex = init->isExpInitializer())
+    {
+        Logger::println("expression initializer");
+        elem* e = ex->exp->toElem(gIR);
+        delete e;
+    }
+    else {
         Logger::println("unsupported initializer: %s", init->toChars());
     }
-    return _init;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -862,13 +880,14 @@
 {
     size_t n = src.size();
     std::vector<llvm::Value*> dst(n);
-    Logger::cout() << "indices:";
+    std::ostream& ostr = Logger::cout();
+    ostr << "indices for '" << *ptr << "':";
     for (size_t i=0; i<n; ++i)
     {
-        Logger::cout() << ' ' << i;
+        ostr << ' ' << i;
         dst[i] = llvm::ConstantInt::get(llvm::Type::Int32Ty, src[i], false);
     }
-    Logger::cout() << '\n';
+    ostr << '\n';
     return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb);
 }
 
@@ -912,7 +931,7 @@
     }
 
     // regular function
-    TypeFunction* f = (TypeFunction*)fdecl->type;
+    TypeFunction* f = (TypeFunction*)LLVM_DtoDType(fdecl->type);
     assert(f != 0);
 
     if (fdecl->llvmValue != 0) {
@@ -1054,9 +1073,93 @@
     call->setCallingConv(llvm::CallingConv::C);
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
 
+llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp)
+{
+    llvm::Value* retval = 0;
+
+    bool haslvals = !gIR->lvals.empty();
+    if (haslvals)
+        gIR->lvals.push_back(NULL);
+
+    elem* arg = argexp->toElem(gIR);
+
+    if (haslvals)
+        gIR->lvals.pop_back();
+
+    if (arg->inplace) {
+        assert(arg->mem != 0);
+        retval = arg->mem;
+        delete arg;
+        return retval;
+    }
+
+    Type* realtype = LLVM_DtoDType(argexp->type);
+    TY argty = realtype->ty;
+    if (LLVM_DtoIsPassedByRef(realtype)) {
+        if (!fnarg || !fnarg->llvmCopy) {
+            retval = arg->getValue();
+            assert(retval != 0);
+        }
+        else {
+            llvm::Value* allocaInst = 0;
+            llvm::BasicBlock* entryblock = &gIR->topfunc()->front();
+            //const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(arg->mem->getType());
+            const llvm::PointerType* pty = llvm::PointerType::get(LLVM_DtoType(argexp->type));
+            if (argty == Tstruct) {
+                allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
+                TypeStruct* ts = (TypeStruct*)LLVM_DtoDType(argexp->type);
+                LLVM_DtoStructCopy(ts,allocaInst,arg->mem);
+            }
+            else if (argty == Tdelegate) {
+                allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
+                LLVM_DtoDelegateCopy(allocaInst,arg->mem);
+            }
+            else if (argty == Tarray) {
+                if (arg->type == elem::SLICE) {
+                    allocaInst = new llvm::AllocaInst(LLVM_DtoType(argexp->type), "tmpparam", gIR->topallocapoint());
+                    LLVM_DtoSetArray(allocaInst, arg->arg, arg->mem);
+                }
+                else {
+                    allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
+                    LLVM_DtoArrayAssign(allocaInst,arg->mem);
+                }
+            }
+            else
+            assert(0);
+
+            assert(allocaInst != 0);
+            retval = allocaInst;
+        }
+    }
+    else if (!fnarg || fnarg->llvmCopy) {
+        Logger::println("regular arg");
+        assert(arg->type != elem::SLICE);
+        if (arg->mem) Logger::cout() << "mem = " << *arg->mem << '\n';
+        if (arg->val) Logger::cout() << "val = " << *arg->val << '\n';
+        if (arg->arg) Logger::cout() << "arg = " << *arg->arg << '\n';
+        retval = arg->arg ? arg->arg : arg->field ? arg->mem : arg->getValue();
+    }
+    else {
+        Logger::println("as ptr arg");
+        retval = arg->mem ? arg->mem : arg->val;
+        if (retval->getType() != paramtype)
+        {
+            assert(retval->getType() == paramtype->getContainedType(0));
+            LLVM_DtoGiveArgumentStorage(arg);
+            new llvm::StoreInst(retval, arg->mem, gIR->scopebb());
+            retval = arg->mem;
+        }
+    }
+
+    delete arg;
+
+    if (fnarg && retval->getType() != paramtype) {
+        Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n";
+        assert(0 && "parameter type that was actually passed is invalid");
+    }
+    return retval;
+}
 
 
-
-
-
--- a/gen/tollvm.h	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/tollvm.h	Fri Oct 19 07:43:21 2007 +0200
@@ -3,11 +3,13 @@
 struct StructInitializer;
 
 const llvm::Type* LLVM_DtoType(Type* t);
+bool LLVM_DtoIsPassedByRef(Type* type);
+Type* LLVM_DtoDType(Type* t);
 
 const llvm::Type* LLVM_DtoStructType(Type* t);
 llvm::Value* LLVM_DtoStructZeroInit(TypeStruct* t, llvm::Value* v);
 llvm::Value* LLVM_DtoStructCopy(TypeStruct* t, llvm::Value* dst, llvm::Value* src);
-llvm::Constant* LLVM_DtoStructInitializer(StructInitializer* si);
+llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si);
 
 const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam = 0);
 const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl);
@@ -30,7 +32,8 @@
 void LLVM_DtoCallClassDtors(TypeClass* tc, llvm::Value* instance);
 void LLVM_DtoInitClass(TypeClass* tc, llvm::Value* dst);
 
-llvm::Constant* LLVM_DtoInitializer(Type* type, Initializer* init);
+llvm::Constant* LLVM_DtoConstInitializer(Type* type, Initializer* init);
+void LLVM_DtoInitializer(Initializer* init);
 
 llvm::Function* LLVM_DeclareMemSet32();
 llvm::Function* LLVM_DeclareMemSet64();
@@ -49,4 +52,6 @@
 
 void LLVM_DtoAssert(llvm::Value* cond, llvm::Value* loc, llvm::Value* msg);
 
+llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp);
+
 #include "enums.h"
--- a/gen/toobj.c	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/toobj.c	Fri Oct 19 07:43:21 2007 +0200
@@ -11,14 +11,9 @@
 #include <iostream>
 #include <fstream>
 
-#include "llvm/Type.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Instructions.h"
+#include "gen/llvm.h"
 #include "llvm/Analysis/Verifier.h"
 #include "llvm/Bitcode/ReaderWriter.h"
-
-#include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetMachineRegistry.h"
 
@@ -152,13 +147,14 @@
     LOG_SCOPE;
     for (unsigned i=0; i<fields.dim; ++i) {
         VarDeclaration* vd = (VarDeclaration*)fields.data[i];
-        Logger::println("found %u type %s", vd->offset, vd->type->toChars());
-        if (os == vd->offset && vd->type == t) {
+        Type* vdtype = LLVM_DtoDType(vd->type);
+        Logger::println("found %u type %s", vd->offset, vdtype->toChars());
+        if (os == vd->offset && vdtype == t) {
             result.push_back(i);
             return;
         }
-        else if (vd->type->ty == Tstruct && (vd->offset + vd->type->size()) > os) {
-            TypeStruct* ts = (TypeStruct*)vd->type;
+        else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
+            TypeStruct* ts = (TypeStruct*)vdtype;
             StructDeclaration* sd = ts->sym;
             result.push_back(i);
             sd->offsetToIndex(t, os - vd->offset, result);
@@ -212,7 +208,7 @@
 
 void StructDeclaration::toObjFile()
 {
-    TypeStruct* ts = (TypeStruct*)type;
+    TypeStruct* ts = (TypeStruct*)LLVM_DtoDType(type);
     if (llvmType != 0)
         return;
 
@@ -288,7 +284,7 @@
 
     // generate member function definitions
     gIR->topstruct().queueFuncs = false;
-    IRState::FuncDeclVec& mfs = gIR->topstruct().funcs;
+    IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs;
     size_t n = mfs.size();
     for (size_t i=0; i<n; ++i) {
         mfs[i]->toObjFile();
@@ -311,6 +307,9 @@
     {
         BaseClass* bc = (BaseClass*)(bcs->data[j]);
         assert(bc);
+        Logger::println("Adding base class members of %s", bc->base->toChars());
+        LOG_SCOPE;
+
         LLVM_AddBaseClassData(&bc->base->baseclasses);
         for (int k=0; k < bc->base->members->dim; k++) {
             Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]);
@@ -324,7 +323,7 @@
 
 void ClassDeclaration::toObjFile()
 {
-    TypeClass* ts = (TypeClass*)type;
+    TypeClass* ts = (TypeClass*)LLVM_DtoDType(type);
     if (ts->llvmType != 0 || llvmInProgress)
         return;
 
@@ -453,7 +452,7 @@
 
     // generate member function definitions
     gIR->topstruct().queueFuncs = false;
-    IRState::FuncDeclVec& mfs = gIR->topstruct().funcs;
+    IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs;
     size_t n = mfs.size();
     for (size_t i=0; i<n; ++i) {
         mfs[i]->toObjFile();
@@ -479,8 +478,7 @@
 
 void VarDeclaration::toObjFile()
 {
-    static int vdi = 0;
-    Logger::print("VarDeclaration::toObjFile(%d): %s | %s\n", vdi++, toChars(), type->toChars());
+    Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     llvm::Module* M = gIR->module;
 
@@ -493,8 +491,11 @@
     }
 
     // global variable or magic
-    if (isDataseg())
+    if (isDataseg() || parent->isModule())
     {
+        if (llvmTouched) return;
+        else llvmTouched = true;
+
         bool _isconst = isConst();
 
         llvm::GlobalValue::LinkageTypes _linkage;
@@ -503,7 +504,9 @@
         else
             _linkage = LLVM_DtoLinkage(protection, storage_class);
 
-        const llvm::Type* _type = LLVM_DtoType(type);
+        Type* t = LLVM_DtoDType(type);
+
+        const llvm::Type* _type = LLVM_DtoType(t);
         assert(_type);
 
         llvm::Constant* _init = 0;
@@ -513,10 +516,10 @@
         std::string _name(mangle());
         llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M);
         llvmValue = gvar;
+
         gIR->lvals.push_back(gvar);
-
-        _init = LLVM_DtoInitializer(type, init);
-        assert(_init);
+        _init = LLVM_DtoConstInitializer(t, init);
+        gIR->lvals.pop_back();
 
         //Logger::cout() << "initializer: " << *_init << '\n';
         if (_type != _init->getType()) {
@@ -529,8 +532,8 @@
             {
                 assert(_init->getType()->getContainedType(0) == _type);
                 llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init);
-                assert(type->ty == Tstruct);
-                TypeStruct* ts = (TypeStruct*)type;
+                assert(t->ty == Tstruct);
+                TypeStruct* ts = (TypeStruct*)t;
                 assert(ts->sym->llvmInitZ);
                 _init = ts->sym->llvmInitZ;
             }
@@ -549,9 +552,9 @@
             }
         }
 
-        gIR->lvals.pop_back();
-
         gvar->setInitializer(_init);
+        
+        llvmDModule = gIR->dmodule;
 
         //if (storage_class & STCprivate)
         //    gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility);
@@ -562,36 +565,37 @@
     {
         Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset);
 
-        const llvm::Type* _type = LLVM_DtoType(type);
+        Type* t = LLVM_DtoDType(type);
+        const llvm::Type* _type = LLVM_DtoType(t);
         gIR->topstruct().fields.push_back(_type);
 
-        llvm::Constant*_init = LLVM_DtoInitializer(type, init);
+        llvm::Constant*_init = LLVM_DtoConstInitializer(t, init);
         assert(_init);
         Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n';
-        if (!_init || _type != _init->getType())
+        if (_type != _init->getType())
         {
-            if (type->ty == Tsarray)
+            if (t->ty == Tsarray)
             {
                 const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(_type);
                 uint64_t n = arrty->getNumElements();
                 std::vector<llvm::Constant*> vals(n,_init);
                 _init = llvm::ConstantArray::get(arrty, vals);
             }
-            else if (type->ty == Tarray)
+            else if (t->ty == Tarray)
             {
                 assert(llvm::isa<llvm::StructType>(_type));
                 _init = llvm::ConstantAggregateZero::get(_type);
             }
-            else if (type->ty == Tstruct)
+            else if (t->ty == Tstruct)
             {
                 const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type);
-                TypeStruct* ts = (TypeStruct*)type;
+                TypeStruct* ts = (TypeStruct*)t;
                 assert(ts);
                 assert(ts->sym);
                 assert(ts->sym->llvmInitZ);
                 _init = ts->sym->llvmInitZ;
             }
-            else if (type->ty == Tclass)
+            else if (t->ty == Tclass)
             {
                 _init = llvm::Constant::getNullValue(_type);
             }
@@ -644,7 +648,8 @@
         return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete
     }
 
-    TypeFunction* f = (TypeFunction*)type;
+    Type* t = LLVM_DtoDType(type);
+    TypeFunction* f = (TypeFunction*)t;
     assert(f->llvmType);
     const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0));
 
@@ -684,7 +689,8 @@
         // function definition
         if (allow_fbody && fbody != 0)
         {
-            gIR->funcdecls.push_back(this);
+            gIR->functions.push_back(IRFunction(this));
+            gIR->func().func = func;
 
             // first make absolutely sure the type is up to date
             f->llvmType = llvmValue->getType()->getContainedType(0);
@@ -703,39 +709,38 @@
             if (isMain())
                 gIR->emitMain = true;
 
-            gIR->funcs.push(func);
-            gIR->functypes.push(f);
-
-            IRScope irs;
-            irs.begin = new llvm::BasicBlock("entry",func);
-            irs.end = new llvm::BasicBlock("endentry",func);
+            llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func);
+            llvm::BasicBlock* endbb = new llvm::BasicBlock("endentry",func);
 
             //assert(gIR->scopes.empty());
-            gIR->scopes.push_back(irs);
+            gIR->scopes.push_back(IRScope(beginbb, endbb));
 
                 // create alloca point
                 f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb());
+                gIR->func().allocapoint = f->llvmAllocaPoint;
 
                 // output function body
                 fbody->toIR(gIR);
 
                 // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement
                 // in automatically, so we do it here.
-                if (!isMain() && (gIR->scopebb()->empty() || !llvm::isa<llvm::TerminatorInst>(gIR->scopebb()->back()))) {
-                    // pass the previous block into this block
-                    //new llvm::BranchInst(irs.end, irs.begin);
-                    new llvm::ReturnInst(gIR->scopebb());
+                if (!isMain()) {
+                    if (gIR->scopebb()->empty() || !llvm::isa<llvm::TerminatorInst>(gIR->scopebb()->back())) {
+                        // pass the previous block into this block
+                        //new llvm::BranchInst(irs.end, irs.begin);
+                        if (func->getReturnType() == llvm::Type::VoidTy) {
+                            new llvm::ReturnInst(gIR->scopebb());
+                        }
+                        
+                    }
                 }
 
                 // erase alloca point
                 f->llvmAllocaPoint->eraseFromParent();
                 f->llvmAllocaPoint = 0;
+                gIR->func().allocapoint = 0;
 
             gIR->scopes.pop_back();
-            //assert(gIR->scopes.empty());
-
-            gIR->functypes.pop();
-            gIR->funcs.pop();
 
             // get rid of the endentry block, it's never used
             assert(!func->getBasicBlockList().empty());
@@ -745,11 +750,10 @@
             // would be nice to figure out how to assert that this is correct
             llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
             if (lastbb->empty()) {
-                // possibly assert(lastbb->getNumPredecessors() == 0); ??? try it out sometime ...
-                new llvm::UnreachableInst(lastbb);
+                lastbb->eraseFromParent();
             }
 
-            gIR->funcdecls.pop_back();
+            gIR->functions.pop_back();
         }
 
         // template instances should have weak linkage
--- a/lphobos/internal/arrays.d	Wed Oct 10 06:21:31 2007 +0200
+++ b/lphobos/internal/arrays.d	Fri Oct 19 07:43:21 2007 +0200
@@ -2,6 +2,8 @@
 
 extern(C):
 
+// per-element array init routines
+
 void _d_array_init_i1(bool* a, size_t n, bool v)
 {
     auto p = a;
@@ -65,3 +67,21 @@
     while (p !is end)
         *p++ = v;
 }
+
+// array comparison routines
+int memcmp(void*,void*,size_t);
+
+bool _d_static_array_eq(void* lhs, void* rhs, size_t bytesize)
+{
+    if (lhs is rhs)
+        return true;
+    return memcmp(lhs,rhs,bytesize) == 0;
+}
+
+bool _d_static_array_neq(void* lhs, void* rhs, size_t bytesize)
+{
+    if (lhs is rhs)
+        return false;
+    return memcmp(lhs,rhs,bytesize) != 0;
+}
+
--- a/test/arrays4.d	Wed Oct 10 06:21:31 2007 +0200
+++ b/test/arrays4.d	Fri Oct 19 07:43:21 2007 +0200
@@ -1,9 +1,14 @@
 module arrays4;
-
+import std.stdio;
 void main()
 {
-    auto arr = new int[4];
-    auto arrcat = arr ~ arr;
-    assert(arrcat.length == arr.length * 2);
+    int[] arr;
+    arr ~= 3;
+    assert(arr.length == 1);
+    assert(arr[0] == 3);
+    arr ~= 5;
+    assert(arr.length == 2);
+    assert(arr[0] == 3);
+    assert(arr[1] == 5);
+    writefln(arr);
 }
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/arrays6.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,6 @@
+module arrays6;
+
+void main()
+{
+    int[4] a = [1,2,3,4];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/arrays7.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,19 @@
+module arrays7;
+
+struct S
+{
+    int i;
+    float f;
+    long l;
+}
+
+void main()
+{
+    S[] arr;
+    S s;
+    arr ~= s;
+    arr ~= S(1,2.64,0xFFFF_FFFF_FFFF);
+    assert(arr[1].i == 1);
+    assert(arr[1].f > 2.63 && arr[1].f < 2.65);
+    assert(arr[1].l == 0xFFFF_FFFF_FFFF);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug10.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,23 @@
+module bug10;
+import std.stdio;
+class C
+{
+    char[] msg;
+
+    this()
+    {
+    }
+    this(char[] msg)
+    {
+        this.msg = msg;
+    }
+}
+
+void main()
+{
+    auto c = new C();
+    c.msg = "world";
+    auto b = new C("hello");
+    printf("%.*s\n", b.msg.length, b.msg.ptr);
+    printf("%.*s\n", c.msg.length, c.msg.ptr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug11.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,12 @@
+module bug11;
+
+struct S
+{
+    int[4] arr;
+}
+
+S s=S([1,2,3,4]);
+
+void main()
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug12.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,6 @@
+module bug12;
+
+void main()
+{
+    const string name="y";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug13.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,18 @@
+module bug13;
+
+void func1(ubyte[4]* arr)
+{
+    ubyte* b = &(*arr)[0];
+    func2(&(*arr)[1]);
+}
+
+void func2(ubyte* ptr)
+{
+    assert(*ptr == 2);
+}
+
+void main()
+{
+    ubyte[4] arr = [cast(ubyte)1,2,3,4];
+    func1(&arr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug14.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,7 @@
+module bug14;
+
+void main()
+{
+    int[] arr = new int[12];
+    int i = arr[0];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug15.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,17 @@
+module bug15;
+
+bool bool1(bool b) {
+    if (b) return true;
+    else return false;
+}
+
+bool bool2(bool b) {
+    if (b) {return true;}
+    else {return false;}
+}
+
+void main()
+{
+    assert(bool1(true));
+    assert(!bool2(false));
+}
--- a/test/bug3.d	Wed Oct 10 06:21:31 2007 +0200
+++ b/test/bug3.d	Fri Oct 19 07:43:21 2007 +0200
@@ -17,6 +17,8 @@
     S s;
     s.arr = new int[5];
     s.arr[1] = 32;
-    assert(s.arr[0] == 0);
-    assert(s.arr[1] == 32);
+    int i;
+    i = s.arr[0];
+    //assert(s.arr[0] == 0);
+    //assert(s.arr[1] == 32);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug8.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,21 @@
+module bug8;
+
+void main()
+{
+    s = newS();
+}
+
+S* s;
+
+struct S
+{
+    int i;
+}
+
+S* newS()
+{
+    auto tmp = new S;
+    tmp.i = 4;
+    return tmp;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug9.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,32 @@
+module bug9;
+struct rgb
+{
+  ubyte[3] values;
+  rgb average(rgb other)
+  {
+    rgb res;
+    foreach (id, ref v; res.values) v=(values[id]+other.values[id])/2;
+    return res;
+  }
+  void print()
+  {
+    printf("[%d,%d,%d]\n", values[0], values[1], values[2]);
+  }
+}
+
+void main()
+{
+    rgb a,b;
+    a.values[0] = 10;
+    a.values[1] = 20;
+    a.values[2] = 30;
+    b.values[0] = 30;
+    b.values[1] = 20;
+    b.values[2] = 10;
+    rgb avg = a.average(b);
+    avg.print();
+    assert(avg.values[0] == 20);
+    assert(avg.values[1] == 20);
+    assert(avg.values[2] == 20);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/cond1.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,8 @@
+module cond1;
+
+void main()
+{
+    double a = 2;
+    double b = 4;
+    double c = (a > 0) ? a : b;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/scope2.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,8 @@
+module scope2;
+
+void main()
+{
+    scope(exit) printf("exit\n");
+    scope(failure) printf("failure\n");
+    scope(success) printf("success\n");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/scope3.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,10 @@
+module scope3;
+
+void main()
+{
+    int i;
+    while (i < 10) {
+        scope(success) i++;
+    }
+    printf("%d\n", i);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/scope4.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,13 @@
+module scope4;
+int main()
+{
+    int i;
+    try
+    {
+        return i;
+    }
+    finally
+    {
+        //i = 1;
+    }
+}
--- a/test/virtcall.d	Wed Oct 10 06:21:31 2007 +0200
+++ b/test/virtcall.d	Fri Oct 19 07:43:21 2007 +0200
@@ -12,4 +12,5 @@
 {
     C c = new C;
     auto s = c.toString();
+    printf("%.*s\n", s.length, s.ptr);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/with1.d	Fri Oct 19 07:43:21 2007 +0200
@@ -0,0 +1,15 @@
+module with1;
+struct S
+{
+    int i;
+    float f;
+}
+void main()
+{
+    S s;
+    with(s)
+    {
+        i = 0;
+        f = 3.4;
+    }
+}
--- a/tester.sh	Wed Oct 10 06:21:31 2007 +0200
+++ b/tester.sh	Fri Oct 19 07:43:21 2007 +0200
@@ -6,28 +6,28 @@
 fi
 
 if [ "$2" = "ll" ]; then
-    llvmdc $1 -Itest -odtest -c &&
+    llvmdc $1 -Itest -odtest -c -vv &&
     llvm-dis -f $1.bc &&
     cat $1.ll
     exit $?
 elif [ "$2" = "llopt" ]; then
-    llvmdc $1 -Itest -odtest -c &&
+    llvmdc $1 -Itest -odtest -c -vv &&
     opt -f -o=$1.bc -std-compile-opts $1.bc &&
     llvm-dis -f $1.bc &&
     cat $1.ll
     exit $?
 elif [ "$2" = "run" ]; then
-    llvmdc $1 lib/lphobos.bc -Itest -odtest -of$1 &&
+    llvmdc $1 lib/lphobos.bc -Itest -odtest -of$1 -vv &&
     $1
     exit $?
 elif [ "$2" = "c" ]; then
-    llvmdc $1 -Itest -odtest -c
+    llvmdc $1 -Itest -odtest -c -vv
     exit $?
 elif [ "$2" = "gdb" ]; then
-    gdb --args llvmdc $1 -Itest -odtest -c
+    gdb --args llvmdc $1 -Itest -odtest -c -vv
     exit $?
 elif [ "$2" = "gdbrun" ]; then
-    llvmdc $1 -Itest -odtest -c &&
+    llvmdc $1 -Itest -odtest -c -vv &&
     gdb $1
     exit $?
 else