changeset 217:0806379a5eca trunk

[svn r233] Added: -oq command line option for writing fully qualified object names. Added: started support for x86 80bit floating point. Changed: aggregates passed by value now use the llvm 'byval' parameter attribute, also lays ground work for using other attributes. Changed: eliminated a lot more std::vectorS, these showed up pretty much at the top when profiling! Changed: performed other misc. cleanups. Changed: halt expression now call the new llvm trap intrinsic instead of an assert(0). Changed: dstress suite now passes -O0 by default, this only eliminates unreferenced globals, which speeds up linking quite a bit.
author lindquist
date Thu, 05 Jun 2008 06:38:36 +0200
parents 3d022aa016ae
children df641a27e9fd
files dmd/mars.c dmd/mars.h dmd/mtype.c dmd/mtype.h gen/aa.cpp gen/arrays.cpp gen/classes.cpp gen/classes.h gen/complex.cpp gen/complex.h gen/functions.cpp gen/statements.cpp gen/structs.cpp gen/structs.h gen/todebug.cpp gen/toir.cpp gen/tollvm.cpp gen/tollvm.h gen/toobj.cpp llvmdc.kdevelop.filelist tango/lib/compiler/llvmdc/memory.d tangotests/vararg4.d tests/runtest
diffstat 23 files changed, 299 insertions(+), 187 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/mars.c	Tue Jun 03 22:32:59 2008 +0200
+++ b/dmd/mars.c	Thu Jun 05 06:38:36 2008 +0200
@@ -202,6 +202,7 @@
   -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\
+  -oq            write object files with fully qualified names\n\
   -profile	 profile runtime performance of generated code\n\
   -quiet         suppress unnecessary messages\n\
   -release	 compile release version\n\
@@ -214,6 +215,7 @@
   -version=level compile in version code >= level\n\
   -version=ident compile in version code identified by ident\n\
   -w             enable warnings\n\
+  -fp80          enable 80bit reals on x86 32bit (EXPERIMENTAL)\n\
 ",
 #if WIN32
 "  @cmdfile       read arguments from cmdfile\n"
@@ -397,6 +399,8 @@
             global.params.disassemble = 1;
         else if (strcmp(p + 1, "annotate") == 0)
             global.params.llvmAnnotate = 1;
+        else if (strcmp(p + 1, "fp80") == 0)
+            global.params.useFP80 = 1;
 	    else if (p[1] == 'o')
 	    {
 		switch (p[2])
@@ -423,6 +427,12 @@
 			global.params.preservePaths = 1;
 			break;
 
+            case 'q':
+            if (p[3])
+                goto Lerror;
+            global.params.fqnPaths = 1;
+            break;
+
 		    case 0:
 			error("-o no longer supported, use -of or -od");
 			break;
@@ -691,6 +701,7 @@
         }
     }
 
+    bool is_x86 = false;
     if (strcmp(global.params.llvmArch,"x86")==0) {
         VersionCondition::addPredefinedGlobalIdent("X86");
         //VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86");
@@ -698,6 +709,7 @@
         global.params.is64bit = false;
         tt_arch = "i686";
         data_layout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:8";
+        is_x86 = true;
     }
     else if (strcmp(global.params.llvmArch,"x86-64")==0) {
         VersionCondition::addPredefinedGlobalIdent("X86_64");
@@ -740,6 +752,14 @@
         VersionCondition::addPredefinedGlobalIdent("LLVM64");
     }
 
+    if (global.params.useFP80) {
+        if (!is_x86) {
+            error("the -fp80 option is only valid for the x86 32bit architecture");
+            fatal();
+        }
+        VersionCondition::addPredefinedGlobalIdent("LLVM_X86_FP80");
+    }
+
     assert(tt_arch != 0);
     assert(tt_os != 0);
     assert(data_layout != 0);
--- a/dmd/mars.h	Tue Jun 03 22:32:59 2008 +0200
+++ b/dmd/mars.h	Thu Jun 05 06:38:36 2008 +0200
@@ -133,6 +133,8 @@
     char llvmInline;
     char llvmAnnotate;
     char *runtimePath;
+    char useFP80;
+    char fqnPaths; // use fully qualified object names
 };
 
 struct Global
--- a/dmd/mtype.c	Tue Jun 03 22:32:59 2008 +0200
+++ b/dmd/mtype.c	Thu Jun 05 06:38:36 2008 +0200
@@ -2538,7 +2538,9 @@
 {
     Type *treturn = next ? next->syntaxCopy() : NULL;
     Arguments *params = Argument::arraySyntaxCopy(parameters);
-    Type *t = new TypeFunction(params, treturn, varargs, linkage);
+    TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage);
+    t->llvmRetInPtr = llvmRetInPtr;
+    t->llvmUsesThis = llvmUsesThis;
     return t;
 }
 
@@ -5062,6 +5064,7 @@
     this->ident = ident;
     this->storageClass = storageClass;
     this->defaultArg = defaultArg;
+    this->llvmByVal = false;
 }
 
 Argument *Argument::syntaxCopy()
@@ -5070,6 +5073,7 @@
 		type ? type->syntaxCopy() : NULL,
 		ident,
 		defaultArg ? defaultArg->syntaxCopy() : NULL);
+    a->llvmByVal = llvmByVal;
     return a;
 }
 
--- a/dmd/mtype.h	Tue Jun 03 22:32:59 2008 +0200
+++ b/dmd/mtype.h	Thu Jun 05 06:38:36 2008 +0200
@@ -681,6 +681,9 @@
     static void argsToDecoBuffer(OutBuffer *buf, Arguments *arguments);
     static size_t dim(Arguments *arguments);
     static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL);
+
+    // LLVMDC
+    bool llvmByVal;
 };
 
 extern int PTRSIZE;
--- a/gen/aa.cpp	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/aa.cpp	Thu Jun 05 06:38:36 2008 +0200
@@ -86,15 +86,8 @@
     LLValue* pkey = to_pkey(key);
     pkey = DtoBitCast(pkey, funcTy->getParamType(3));
 
-    // build arg vector
-    LLSmallVector<LLValue*, 4> args;
-    args.push_back(aaval);
-    args.push_back(keyti);
-    args.push_back(valsize);
-    args.push_back(pkey);
-
     // call runtime
-    LLValue* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "aa.index");
+    LLValue* ret = gIR->ir->CreateCall4(func, aaval, keyti, valsize, pkey, "aa.index");
 
     // cast return value
     const LLType* targettype = getPtrToType(DtoType(type));
@@ -131,14 +124,8 @@
     LLValue* pkey = to_pkey(key);
     pkey = DtoBitCast(pkey, funcTy->getParamType(2));
 
-    // build arg vector
-    LLSmallVector<LLValue*, 3> args;
-    args.push_back(aaval);
-    args.push_back(keyti);
-    args.push_back(pkey);
-
     // call runtime
-    LLValue* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "aa.in");
+    LLValue* ret = gIR->ir->CreateCall3(func, aaval, keyti, pkey, "aa.in");
 
     // cast return value
     const LLType* targettype = DtoType(type);
--- a/gen/arrays.cpp	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/arrays.cpp	Thu Jun 05 06:38:36 2008 +0200
@@ -184,7 +184,7 @@
 
     Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n';
 
-    std::vector<LLValue*> args;
+    LLSmallVector<LLValue*, 4> args;
     args.push_back(ptr);
     args.push_back(dim);
     args.push_back(val);
@@ -424,12 +424,11 @@
     LLValue* srcarr = DtoBitCast(get_slice_ptr(src,sz2),arrty);
 
     llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
-    std::vector<LLValue*> llargs;
-    llargs.resize(4);
+    LLSmallVector<LLValue*, 4> llargs(4);
     llargs[0] = dstarr;
     llargs[1] = srcarr;
     llargs[2] = sz1;
-    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+    llargs[3] = DtoConstInt(0);
 
     llvm::CallInst::Create(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
 }
@@ -444,12 +443,11 @@
     LLValue* srcarr = DtoBitCast(DtoArrayPtr(src),arrty);
 
     llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
-    std::vector<LLValue*> llargs;
-    llargs.resize(4);
+    LLSmallVector<LLValue*, 4> llargs(4);
     llargs[0] = dstarr;
     llargs[1] = srcarr;
     llargs[2] = sz1;
-    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+    llargs[3] = DtoConstInt(0);
 
     llvm::CallInst::Create(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
 }
@@ -467,12 +465,11 @@
     LLValue* srcarr = DtoBitCast(src,arrty);
 
     llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
-    std::vector<LLValue*> llargs;
-    llargs.resize(4);
+    LLSmallVector<LLValue*,4> llargs(4);
     llargs[0] = dstarr;
     llargs[1] = srcarr;
     llargs[2] = n;
-    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+    llargs[3] = DtoConstInt(0);
 
     llvm::CallInst::Create(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
 }
@@ -480,14 +477,8 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 LLConstant* DtoConstSlice(LLConstant* dim, LLConstant* ptr)
 {
-    std::vector<const LLType*> types;
-    types.push_back(dim->getType());
-    types.push_back(ptr->getType());
-    const llvm::StructType* type = llvm::StructType::get(types);
-    std::vector<LLConstant*> values;
-    values.push_back(dim);
-    values.push_back(ptr);
-    return llvm::ConstantStruct::get(type,values);
+    LLConstant* values[2] = { dim, ptr };
+    return llvm::ConstantStruct::get(values, 2);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -496,15 +487,21 @@
     Logger::println("DtoNewDynArray : %s", arrayType->toChars());
     LOG_SCOPE;
 
+    // typeinfo arg
+    LLValue* arrayTypeInfo = DtoTypeInfoOf(arrayType);
+
+    // dim arg
+    assert(DtoType(dim->getType()) == DtoSize_t());
+    LLValue* arrayLen = dim->getRVal();
+
+    // get runtime function
     bool zeroInit = arrayType->toBasetype()->nextOf()->isZeroInit();
     llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, zeroInit ? "_d_newarrayT" : "_d_newarrayiT" );
 
-    LLSmallVector<LLValue*,2> args;
-    args.push_back(DtoTypeInfoOf(arrayType));
-    assert(DtoType(dim->getType()) == DtoSize_t());
-    args.push_back(dim->getRVal());
+    // call allocator
+    LLValue* newptr = gIR->ir->CreateCall2(fn, arrayTypeInfo, arrayLen, ".gc_mem");
 
-    LLValue* newptr = gIR->ir->CreateCall(fn, args.begin(), args.end(), ".gc_mem");
+    // cast to wanted type
     const LLType* dstType = DtoType(arrayType)->getContainedType(1);
     if (newptr->getType() != dstType)
         newptr = DtoBitCast(newptr, dstType, ".gc_mem");
@@ -518,7 +515,7 @@
     }
 #endif
 
-    return new DSliceValue(arrayType, args[1], newptr);
+    return new DSliceValue(arrayType, arrayLen, newptr);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -542,6 +539,7 @@
     args.push_back(DtoTypeInfoOf(arrayType));
     args.push_back(newdim->getRVal());
     args.push_back(DtoArrayLen(array));
+
     LLValue* arrPtr = DtoArrayPtr(array);
     Logger::cout() << "arrPtr = " << *arrPtr << '\n';
     args.push_back(DtoBitCast(arrPtr, fn->getFunctionType()->getParamType(3), "tmp"));
@@ -734,7 +732,7 @@
     Type* r_ty = DtoDType(r->getType());
     assert(l_ty->next == r_ty->next);
     if ((l_ty->ty == Tsarray) || (r_ty->ty == Tsarray)) {
-        Type* a_ty = new Type(Tarray, l_ty->next);
+        Type* a_ty = l_ty->next->arrayOf();
         if (l_ty->ty == Tsarray)
             l = DtoCastArray(l, a_ty);
         if (r_ty->ty == Tsarray)
@@ -774,7 +772,7 @@
 
     const LLType* pt = fn->getFunctionType()->getParamType(0);
 
-    std::vector<LLValue*> args;
+    LLSmallVector<LLValue*, 3> args;
     Logger::cout() << "bitcasting to " << *pt << '\n';
     Logger::cout() << *lmem << '\n';
     Logger::cout() << *rmem << '\n';
@@ -799,9 +797,6 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 LLValue* DtoArrayEquals(TOK op, DValue* l, DValue* r)
 {
-    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_adEq");
-    assert(fn);
-
     LLValue* res = DtoArrayEqCmp_impl("_adEq", l, r, true);
     if (op == TOKnotequal)
         res = gIR->ir->CreateNot(res, "tmp");
@@ -883,7 +878,7 @@
     if (esz == nsz)
         return len;
 
-    std::vector<LLValue*> args;
+    LLSmallVector<LLValue*, 3> args;
     args.push_back(len);
     args.push_back(llvm::ConstantInt::get(DtoSize_t(), esz, false));
     args.push_back(llvm::ConstantInt::get(DtoSize_t(), nsz, false));
--- a/gen/classes.cpp	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/classes.cpp	Thu Jun 05 06:38:36 2008 +0200
@@ -796,9 +796,7 @@
     else
     {
         llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_newclass");
-        std::vector<LLValue*> args;
-        args.push_back(tc->sym->ir.irStruct->classInfo);
-        mem = gIR->ir->CreateCall(fn, args.begin(), args.end(), "newclass_gc_alloc");
+        mem = gIR->ir->CreateCall(fn, tc->sym->ir.irStruct->classInfo, "newclass_gc_alloc");
         mem = DtoBitCast(mem, DtoType(tc), "newclass_gc");
     }
 
@@ -898,6 +896,8 @@
     llvm::Function* fn = ctor->ir.irFunc->func;
     TypeFunction* tf = (TypeFunction*)DtoDType(ctor->type);
 
+    llvm::PAListPtr palist;
+
     std::vector<LLValue*> ctorargs;
     ctorargs.push_back(mem);
     for (size_t i=0; i<arguments->dim; ++i)
@@ -910,9 +910,12 @@
         if (a->getType() != aty)
             a = DtoBitCast(a, aty);
         ctorargs.push_back(a);
+        if (fnarg && fnarg->llvmByVal)
+            palist = palist.addAttr(i+2, llvm::ParamAttr::ByVal); // return,this is 2
     }
     llvm::CallInst* call = llvm::CallInst::Create(fn, ctorargs.begin(), ctorargs.end(), "tmp", gIR->scopebb());
     call->setCallingConv(DtoCallingConv(LINKd));
+    call->setParamAttrs(palist);
 
     return new DImValue(type, call, false);
 }
@@ -997,24 +1000,22 @@
     std::vector<LLValue*> args;
 
     // Object o
-    LLValue* tmp = val->getRVal();
-    tmp = DtoBitCast(tmp, funcTy->getParamType(0));
-    args.push_back(tmp);
-    assert(funcTy->getParamType(0) == tmp->getType());
+    LLValue* obj = val->getRVal();
+    obj = DtoBitCast(obj, funcTy->getParamType(0));
+    assert(funcTy->getParamType(0) == obj->getType());
 
     // ClassInfo c
     TypeClass* to = (TypeClass*)DtoDType(_to);
     DtoForceDeclareDsymbol(to->sym);
     assert(to->sym->ir.irStruct->classInfo);
-    tmp = to->sym->ir.irStruct->classInfo;
+    LLValue* cinfo = to->sym->ir.irStruct->classInfo;
     // unfortunately this is needed as the implementation of object differs somehow from the declaration
     // this could happen in user code as well :/
-    tmp = DtoBitCast(tmp, funcTy->getParamType(1));
-    args.push_back(tmp);
-    assert(funcTy->getParamType(1) == tmp->getType());
+    cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
+    assert(funcTy->getParamType(1) == cinfo->getType());
 
     // call it
-    LLValue* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp");
+    LLValue* ret = gIR->ir->CreateCall2(func, obj, cinfo, "tmp");
 
     // cast return value
     ret = DtoBitCast(ret, DtoType(_to));
@@ -1064,22 +1065,20 @@
     std::vector<LLValue*> args;
 
     // void* p
-    LLValue* tmp = val->getRVal();
-    tmp = DtoBitCast(tmp, funcTy->getParamType(0));
-    args.push_back(tmp);
+    LLValue* ptr = val->getRVal();
+    ptr = DtoBitCast(ptr, funcTy->getParamType(0));
 
     // ClassInfo c
     TypeClass* to = (TypeClass*)DtoDType(_to);
     DtoForceDeclareDsymbol(to->sym);
     assert(to->sym->ir.irStruct->classInfo);
-    tmp = to->sym->ir.irStruct->classInfo;
+    LLValue* cinfo = to->sym->ir.irStruct->classInfo;
     // unfortunately this is needed as the implementation of object differs somehow from the declaration
     // this could happen in user code as well :/
-    tmp = DtoBitCast(tmp, funcTy->getParamType(1));
-    args.push_back(tmp);
+    cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
 
     // call it
-    LLValue* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp");
+    LLValue* ret = gIR->ir->CreateCall2(func, ptr, cinfo, "tmp");
 
     // cast return value
     ret = DtoBitCast(ret, DtoType(_to));
@@ -1127,7 +1126,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os, std::vector<unsigned>& idxs)
+LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os, DStructIndexVector& idxs)
 {
     Logger::println("checking for offset %u type %s:", os, t->toChars());
     LOG_SCOPE;
@@ -1157,7 +1156,7 @@
             Logger::println("found %s %s", vdtype->toChars(), vd->toChars());
             idxs.push_back(vd->ir.irField->index + dataoffset);
             //Logger::cout() << "indexing: " << *ptr << '\n';
-            ptr = DtoGEP(ptr, idxs, "tmp");
+            ptr = DtoGEPi(ptr, idxs, "tmp");
             if (ptr->getType() != llt)
                 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
             //Logger::cout() << "indexing: " << *ptr << '\n';
@@ -1172,18 +1171,18 @@
             idxs.push_back(vd->ir.irField->index + dataoffset);
             if (vd->ir.irField->indexOffset) {
                 Logger::println("has union field offset");
-                ptr = DtoGEP(ptr, idxs, "tmp");
+                ptr = DtoGEPi(ptr, idxs, "tmp");
                 if (ptr->getType() != llt)
                     ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
                 ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "tmp", gIR->scopebb());
-                std::vector<unsigned> tmp;
+                DStructIndexVector tmp;
                 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
             }
             else {
                 const LLType* sty = getPtrToType(DtoType(vd->type));
                 if (ptr->getType() != sty) {
                     ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
-                    std::vector<unsigned> tmp;
+                    DStructIndexVector tmp;
                     return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
                 }
                 else {
--- a/gen/classes.h	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/classes.h	Thu Jun 05 06:38:36 2008 +0200
@@ -1,6 +1,8 @@
 #ifndef LLVMDC_GEN_CLASSES_H
 #define LLVMDC_GEN_CLASSES_H
 
+#include "gen/structs.h"
+
 /**
  * Resolves the llvm type for a class declaration
  */
@@ -35,7 +37,7 @@
 DValue* DtoCastInterfaceToObject(DValue* val, Type* to);
 DValue* DtoDynamicCastInterface(DValue* val, Type* to);
 
-LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os, std::vector<unsigned>& idxs);
+LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os, DStructIndexVector& idxs);
 
 LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl);
 
--- a/gen/complex.cpp	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/complex.cpp	Thu Jun 05 06:38:36 2008 +0200
@@ -28,10 +28,13 @@
     TY ty = DtoDType(t)->ty;
     const LLType* base;
     if (ty == Tcomplex32) {
-        return llvm::Type::FloatTy;
+        return LLType::FloatTy;
     }
-    else if (ty == Tcomplex64 || ty == Tcomplex80) {
-        return llvm::Type::DoubleTy;
+    else if (ty == Tcomplex64) {
+        return LLType::DoubleTy;
+    }
+    else if (ty == Tcomplex80) {
+        return (global.params.useFP80) ? LLType::X86_FP80Ty : LLType::DoubleTy;
     }
     else {
         assert(0);
@@ -60,47 +63,23 @@
     llvm::ConstantFP* fre;
     llvm::ConstantFP* fim;
 
-    const LLType* base;
+    Type* base = 0;
 
     if (ty == Tcomplex32) {
-        fre = DtoConstFP(Type::tfloat32, re);
-        fim = DtoConstFP(Type::tfloat32, im);
-        base = llvm::Type::FloatTy;
+        base = Type::tfloat32;
     }
-    else if (ty == Tcomplex64 || ty == Tcomplex80) {
-        fre = DtoConstFP(Type::tfloat64, re);
-        fim = DtoConstFP(Type::tfloat64, im);
-        base = llvm::Type::DoubleTy;
+    else if (ty == Tcomplex64) {
+        base = Type::tfloat64;
     }
-    else
-    assert(0);
+    else if (ty == Tcomplex80) {
+        base = (global.params.useFP80) ? Type::tfloat80 : Type::tfloat64;
+    }
 
     std::vector<LLConstant*> inits;
-    inits.push_back(fre);
-    inits.push_back(fim);
-    return llvm::ConstantStruct::get(DtoComplexType(_ty), inits);
-}
+    inits.push_back(DtoConstFP(base, re));
+    inits.push_back(DtoConstFP(base, im));
 
-LLConstant* DtoUndefComplex(Type* _ty)
-{
-    assert(0);
-    TY ty = DtoDType(_ty)->ty;
-    const LLType* base;
-    if (ty == Tcomplex32) {
-        base = llvm::Type::FloatTy;
-    }
-    else if (ty == Tcomplex64 || ty == Tcomplex80) {
-        base = llvm::Type::DoubleTy;
-    }
-    else
-    assert(0);
-
-    std::vector<LLConstant*> inits;
-    inits.push_back(llvm::UndefValue::get(base));
-    inits.push_back(llvm::UndefValue::get(base));
-
-    const llvm::VectorType* vt = llvm::VectorType::get(base, 2);
-    return llvm::ConstantVector::get(vt, inits);
+    return llvm::ConstantStruct::get(DtoComplexType(_ty), inits);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -135,9 +114,11 @@
     LLConstant* undef = llvm::UndefValue::get(base);
     LLConstant* zero;
     if (ty == Tfloat32 || ty == Timaginary32 || ty == Tcomplex32)
-        zero = llvm::ConstantFP::get(llvm::APFloat(0.0f));
-    else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tcomplex64 || ty == Tfloat80 || ty == Timaginary80 || ty == Tcomplex80)
-        zero = llvm::ConstantFP::get(llvm::APFloat(0.0));
+        zero = LLConstant::getNullValue(DtoType(Type::tfloat32)); // llvm::ConstantFP::get(llvm::APFloat(0.0f));
+    else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tcomplex64)
+        zero = LLConstant::getNullValue(DtoType(Type::tfloat64));
+    else if (ty == Tfloat80 || ty == Timaginary80 || ty == Tcomplex80)
+        zero = LLConstant::getNullValue(DtoType((global.params.useFP80)?Type::tfloat80:Type::tfloat64));
 
     if (t->isimaginary()) {
         return new DComplexValue(to, zero, val->getRVal());
--- a/gen/complex.h	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/complex.h	Thu Jun 05 06:38:36 2008 +0200
@@ -2,11 +2,10 @@
 #define LLVMDC_GEN_COMPLEX_H
 
 const llvm::StructType* DtoComplexType(Type* t);
-const llvm::Type* DtoComplexBaseType(Type* t);
+const LLType* DtoComplexBaseType(Type* t);
 
 LLConstant* DtoConstComplex(Type* t, LLConstant* re, LLConstant* im);
 LLConstant* DtoConstComplex(Type* t, long double re, long double im);
-LLConstant* DtoUndefComplex(Type* _ty);
 
 LLConstant* DtoComplexShuffleMask(unsigned a, unsigned b);
 
--- a/gen/functions.cpp	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/functions.cpp	Thu Jun 05 06:38:36 2008 +0200
@@ -51,7 +51,7 @@
     else {
         assert(rt);
         Type* rtfin = DtoDType(rt);
-        if (DtoIsPassedByRef(rt)) {
+        if (DtoIsReturnedInArg(rt)) {
             rettype = getPtrToType(DtoType(rt));
             actualRettype = llvm::Type::VoidTy;
             f->llvmRetInPtr = retinptr = true;
@@ -94,22 +94,30 @@
 
     size_t n = Argument::dim(f->parameters);
 
+    int nbyval = 0;
+
+    llvm::PAListPtr palist;
+
     for (int i=0; i < n; ++i) {
         Argument* arg = Argument::getNth(f->parameters, i);
         // ensure scalar
         Type* argT = DtoDType(arg->type);
         assert(argT);
 
+        bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout));
+
         const LLType* at = DtoType(argT);
         if (isaStruct(at)) {
             Logger::println("struct param");
             paramvec.push_back(getPtrToType(at));
+            arg->llvmByVal = !refOrOut;
         }
         else if (isaArray(at)) {
             Logger::println("sarray param");
             assert(argT->ty == Tsarray);
             //paramvec.push_back(getPtrToType(at->getContainedType(0)));
             paramvec.push_back(getPtrToType(at));
+            arg->llvmByVal = !refOrOut;
         }
         else if (llvm::isa<llvm::OpaqueType>(at)) {
             Logger::println("opaque param");
@@ -117,7 +125,7 @@
             paramvec.push_back(getPtrToType(at));
         }
         else {
-            if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
+            if (refOrOut) {
                 Logger::println("by ref param");
                 at = getPtrToType(at);
             }
@@ -126,8 +134,13 @@
             }
             paramvec.push_back(at);
         }
+
+        if (arg->llvmByVal)
+            nbyval++;
     }
 
+    //warning("set %d byval args for type: %s", nbyval, f->toChars());
+
     // construct function type
     bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs;
     llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
@@ -135,10 +148,7 @@
     f->llvmRetInPtr = retinptr;
     f->llvmUsesThis = usesthis;
 
-    //if (!f->ir.type)
-        f->ir.type = new llvm::PATypeHolder(functype);
-    //else
-        //assert(functype == f->ir.type->get());
+    f->ir.type = new llvm::PATypeHolder(functype);
 
     return functype;
 }
@@ -378,6 +388,43 @@
     fdecl->ir.irFunc->func = func;
     assert(llvm::isa<llvm::FunctionType>(f->ir.type->get()));
 
+    // parameter attributes
+    if (f->parameters)
+    {
+        int llidx = 1;
+        if (f->llvmRetInPtr) ++llidx;
+        if (f->llvmUsesThis) ++llidx;
+        if (f->linkage == LINKd && f->varargs == 1)
+            llidx += 2;
+
+        int funcNumArgs = func->getArgumentList().size();
+        std::vector<llvm::ParamAttrsWithIndex> attrs;
+        int k = 0;
+
+        int nbyval = 0;
+
+        for (; llidx <= funcNumArgs && f->parameters->dim > k; ++llidx,++k)
+        {
+            Argument* fnarg = (Argument*)f->parameters->data[k];
+            assert(fnarg);
+            if (fnarg->llvmByVal)
+            {
+                llvm::ParamAttrsWithIndex PAWI;
+                PAWI.Index = llidx;
+                PAWI.Attrs = llvm::ParamAttr::ByVal;
+                attrs.push_back(PAWI);
+                nbyval++;
+            }
+        }
+
+        //warning("set %d byval args for function: %s", nbyval, func->getName().c_str());
+
+        if (nbyval) {
+            llvm::PAListPtr palist = llvm::PAListPtr::get(attrs.begin(), attrs.end());
+            func->setParamAttrs(palist);
+        }
+    }
+
     // main
     if (fdecl->isMain()) {
         gIR->mainFunc = func;
@@ -775,19 +822,14 @@
         else
             arg = new DImValue(argexp->type, arg->getRVal(), false);
     }
-    // aggregate arg
-    else if (DtoIsPassedByRef(argexp->type))
+    // byval arg, but expr has no storage yet
+    else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isComplex() || arg->isNull()))
     {
         LLValue* alloc = new llvm::AllocaInst(DtoType(argexp->type), "tmpparam", gIR->topallocapoint());
         DVarValue* vv = new DVarValue(argexp->type, alloc, true);
         DtoAssign(vv, arg);
         arg = vv;
     }
-    // normal arg (basic/value type)
-    else
-    {
-        // nothing to do
-    }
 
     return arg;
 }
--- a/gen/statements.cpp	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/statements.cpp	Thu Jun 05 06:38:36 2008 +0200
@@ -92,7 +92,7 @@
 
             emit_finallyblocks(p, enclosingtryfinally, NULL);
 
-            if (gIR->func()->inVolatile) {
+            if (f->inVolatile) {
                 // store-load barrier
                 DtoMemoryBarrier(false, false, true, false);
             }
@@ -128,21 +128,16 @@
     }
     else
     {
-        if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
-            emit_finallyblocks(p, enclosingtryfinally, NULL);
-
-            if (gIR->func()->inVolatile) {
-                // store-load barrier
-                DtoMemoryBarrier(false, false, true, false);
-            }
+        assert(p->topfunc()->getReturnType() == llvm::Type::VoidTy);
+        emit_finallyblocks(p, enclosingtryfinally, NULL);
 
-            if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
-            llvm::ReturnInst::Create(p->scopebb());
+        if (gIR->func()->inVolatile) {
+            // store-load barrier
+            DtoMemoryBarrier(false, false, true, false);
         }
-        else {
-            assert(0); // why should this ever happen?
-            new llvm::UnreachableInst(p->scopebb());
-        }
+
+        if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
+        llvm::ReturnInst::Create(p->scopebb());
     }
 }
 
@@ -616,11 +611,10 @@
     }
 
     llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
-    std::vector<LLValue*> args;
+
     Logger::cout() << *table->getType() << '\n';
     Logger::cout() << *fn->getFunctionType()->getParamType(0) << '\n';
     assert(table->getType() == fn->getFunctionType()->getParamType(0));
-    args.push_back(table);
 
     DValue* val = e->toElem(gIR);
     LLValue* llval;
@@ -636,9 +630,8 @@
         llval = val->getRVal();
     }
     assert(llval->getType() == fn->getFunctionType()->getParamType(1));
-    args.push_back(llval);
 
-    return gIR->ir->CreateCall(fn, args.begin(), args.end(), "tmp");
+    return gIR->ir->CreateCall2(fn, table, llval, "tmp");
 }
 
 void SwitchStatement::toIR(IRState* p)
--- a/gen/structs.cpp	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/structs.cpp	Thu Jun 05 06:38:36 2008 +0200
@@ -105,7 +105,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs)
+LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, DStructIndexVector& idxs)
 {
     Logger::println("checking for offset %u type %s:", os, t->toChars());
     LOG_SCOPE;
@@ -127,7 +127,7 @@
         assert(vd->ir.irField->index >= 0);
         if (os == vd->offset && vdtype == t) {
             idxs.push_back(vd->ir.irField->index);
-            ptr = DtoGEP(ptr, idxs, "tmp");
+            ptr = DtoGEPi(ptr, idxs, "tmp");
             if (ptr->getType() != llt)
                 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
             if (vd->ir.irField->indexOffset)
@@ -140,18 +140,18 @@
             idxs.push_back(vd->ir.irField->index);
             if (vd->ir.irField->indexOffset) {
                 Logger::println("has union field offset");
-                ptr = DtoGEP(ptr, idxs, "tmp");
+                ptr = DtoGEPi(ptr, idxs, "tmp");
                 if (ptr->getType() != llt)
                     ptr = DtoBitCast(ptr, llt);
                 ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "tmp", gIR->scopebb());
-                std::vector<unsigned> tmp;
+                DStructIndexVector tmp;
                 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
             }
             else {
                 const LLType* sty = getPtrToType(DtoType(vd->type));
                 if (ptr->getType() != sty) {
                     ptr = DtoBitCast(ptr, sty);
-                    std::vector<unsigned> tmp;
+                    DStructIndexVector tmp;
                     return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
                 }
                 else {
--- a/gen/structs.h	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/structs.h	Thu Jun 05 06:38:36 2008 +0200
@@ -30,7 +30,8 @@
  */
 void DtoDefineStruct(StructDeclaration* sd);
 
-LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs);
+typedef LLSmallVector<unsigned, 3> DStructIndexVector;
+LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, DStructIndexVector& idxs);
 
 struct DUnionField
 {
--- a/gen/todebug.cpp	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/todebug.cpp	Thu Jun 05 06:38:36 2008 +0200
@@ -196,7 +196,7 @@
 
 void DtoDwarfStopPoint(unsigned ln)
 {
-    std::vector<LLValue*> args;
+    LLSmallVector<LLValue*,3> args;
     args.push_back(DtoConstUint(ln));
     args.push_back(DtoConstUint(0));
     FuncDeclaration* fd = gIR->func()->decl;
--- a/gen/toir.cpp	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/toir.cpp	Thu Jun 05 06:38:36 2008 +0200
@@ -618,7 +618,7 @@
             llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->isConst()->c);
 
             TypeStruct* ts = (TypeStruct*)e1next;
-            std::vector<unsigned> offsets;
+            DStructIndexVector offsets;
             LLValue* v = DtoIndexStruct(l->getRVal(), ts->sym, t->next, cofs->getZExtValue(), offsets);
             return new DFieldValue(type, v, true);
         }
@@ -1018,7 +1018,11 @@
 
     bool isInPlace = false;
 
+    // attrs
+    llvm::PAListPtr palist;
+
     // hidden struct return arguments
+    // TODO: use sret param attr
     if (retinptr) {
         if (topexp && topexp->e2 == this) {
             assert(topexp->v);
@@ -1167,6 +1171,10 @@
             Argument* fnarg = Argument::getNth(tf->parameters, i);
             DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
             llargs[j] = argval->getRVal();
+        #if USE_BYVAL
+            if (fnarg->llvmByVal)
+                palist = palist.addAttr(j, llvm::ParamAttr::ByVal);
+        #endif
             j++;
         }
 
@@ -1187,6 +1195,11 @@
                 llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
             }
 
+        #if USE_BYVAL
+            if (fnarg && fnarg->llvmByVal)
+                palist = palist.addAttr(j+1, llvm::ParamAttr::ByVal);
+        #endif
+
             // this hack is necessary :/
             if (dfn && dfn->func && dfn->func->runTimeHack) {
                 if (llfnty->getParamType(j) != NULL) {
@@ -1245,6 +1258,9 @@
         call->setCallingConv(DtoCallingConv(dlink));
     }
 
+    // param attrs
+    call->setParamAttrs(palist);
+
     return new DImValue(type, retllval, isInPlace);
 }
 
@@ -1311,7 +1327,7 @@
                 varmem = p->ir->CreateBitCast(llvalue, llt, "tmp");
             }
             else {
-                std::vector<unsigned> dst;
+                DStructIndexVector dst;
                 varmem = DtoIndexStruct(llvalue,vdt->sym, tnext, offset, dst);
             }
         }
@@ -1429,7 +1445,7 @@
 
             LLValue* src = l->getRVal();
 
-            std::vector<unsigned> vdoffsets;
+            DStructIndexVector vdoffsets;
             arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
         }
         else if (e1type->ty == Tclass) {
@@ -1438,7 +1454,7 @@
 
             LLValue* src = l->getRVal();
 
-            std::vector<unsigned> vdoffsets;
+            DStructIndexVector vdoffsets;
             arrptr = DtoIndexClass(src, tc->sym, vd->type, vd->offset, vdoffsets);
 
             /*std::vector<unsigned> vdoffsets(1,0);
@@ -2255,7 +2271,8 @@
     Logger::print("HaltExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    DtoAssert(&loc, NULL);
+    // call the new (?) trap intrinsic
+    p->ir->CreateCall(GET_INTRINSIC_DECL(trap),"");
 
     new llvm::UnreachableInst(p->scopebb());
     return 0;
--- a/gen/tollvm.cpp	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/tollvm.cpp	Thu Jun 05 06:38:36 2008 +0200
@@ -26,6 +26,13 @@
     return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
 }
 
+bool DtoIsReturnedInArg(Type* type)
+{
+    Type* typ = DtoDType(type);
+    TY t = typ->ty;
+    return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
+}
+
 Type* DtoDType(Type* t)
 {
     if (t->ty == Ttypedef) {
@@ -67,9 +74,10 @@
         return llvm::Type::FloatTy;
     case Tfloat64:
     case Timaginary64:
+        return llvm::Type::DoubleTy;
     case Tfloat80:
     case Timaginary80:
-        return llvm::Type::DoubleTy;
+        return (global.params.useFP80) ? llvm::Type::X86_FP80Ty : llvm::Type::DoubleTy;
 
     // complex
     case Tcomplex32:
@@ -590,46 +598,42 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const std::string& var, llvm::BasicBlock* bb)
+LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const char* var, llvm::BasicBlock* bb)
 {
-    std::vector<LLValue*> v(2);
+    LLSmallVector<LLValue*,2> v(2);
     v[0] = i0;
     v[1] = i1;
-    Logger::cout() << "DtoGEP: " << *ptr << ", " << *i0 << ", " << *i1 << '\n';
     return llvm::GetElementPtrInst::Create(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb());
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-LLValue* DtoGEP(LLValue* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb)
+LLValue* DtoGEPi(LLValue* ptr, const DStructIndexVector& src, const char* var, llvm::BasicBlock* bb)
 {
     size_t n = src.size();
-    std::vector<LLValue*> dst(n, NULL);
-    //std::ostream& ostr = Logger::cout();
-    //ostr << "indices for '" << *ptr << "':";
-    for (size_t i=0; i<n; ++i)
-    {
-        //ostr << ' ' << i;
-        dst[i] = llvm::ConstantInt::get(llvm::Type::Int32Ty, src[i], false);
-    }
-    //ostr << '\n';*/
+    LLSmallVector<LLValue*, 3> dst(n);
+
+    size_t j=0;
+    for (DStructIndexVector::const_iterator i=src.begin(); i!=src.end(); ++i)
+        dst[j++] = DtoConstUint(*i);
+
     return llvm::GetElementPtrInst::Create(ptr, dst.begin(), dst.end(), var, bb?bb:gIR->scopebb());
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-LLValue* DtoGEPi(LLValue* ptr, unsigned i, const std::string& var, llvm::BasicBlock* bb)
+LLValue* DtoGEPi(LLValue* ptr, unsigned i, const char* var, llvm::BasicBlock* bb)
 {
     return llvm::GetElementPtrInst::Create(ptr, llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false), var, bb?bb:gIR->scopebb());
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const std::string& var, llvm::BasicBlock* bb)
+LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const char* var, llvm::BasicBlock* bb)
 {
-    std::vector<LLValue*> v(2);
-    v[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i0, false);
-    v[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i1, false);
+    LLSmallVector<LLValue*,2> v(2);
+    v[0] = DtoConstUint(i0);
+    v[1] = DtoConstUint(i1);
     return llvm::GetElementPtrInst::Create(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb());
 }
 
@@ -642,11 +646,8 @@
     // get type info
     LLConstant* ti = DtoTypeInfoOf(newtype);
     assert(isaPointer(ti));
-    // call runtime
-    LLSmallVector<LLValue*,1> arg;
-    arg.push_back(ti);
-    // allocate
-    LLValue* mem = gIR->ir->CreateCall(fn, arg.begin(), arg.end(), ".gc_mem");
+    // call runtime allocator
+    LLValue* mem = gIR->ir->CreateCall(fn, ti, ".gc_mem");
     // cast
     return DtoBitCast(mem, getPtrToType(DtoType(newtype)), ".gc_mem");
 }
@@ -707,6 +708,10 @@
     const char* fname = msg ? "_d_assert_msg" : "_d_assert";
     llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
 
+    // param attrs
+    llvm::PAListPtr palist;
+    int idx = 1;
+
     c = DtoConstString(loc->filename);
 
     // msg param
@@ -727,6 +732,7 @@
         {
             args.push_back(msg->getRVal());
         }
+        palist = palist.addAttr(idx++, llvm::ParamAttr::ByVal);
     }
 
     // file param
@@ -740,7 +746,10 @@
     DtoStore(c->getOperand(0), ptr);
     ptr = DtoGEPi(alloc, 0,1, "tmp");
     DtoStore(c->getOperand(1), ptr);
+
     args.push_back(alloc);
+    palist = palist.addAttr(idx++, llvm::ParamAttr::ByVal);
+
 
     // line param
     c = DtoConstUint(loc->linnum);
@@ -748,6 +757,7 @@
 
     // call
     llvm::CallInst* call = llvm::CallInst::Create(fn, args.begin(), args.end(), "", gIR->scopebb());
+    call->setParamAttrs(palist);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
--- a/gen/tollvm.h	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/tollvm.h	Thu Jun 05 06:38:36 2008 +0200
@@ -7,9 +7,12 @@
 #include "attrib.h"
 #include "declaration.h"
 
+#include "gen/structs.h"
+
 // D->LLVM type handling stuff
 const LLType* DtoType(Type* t);
 bool DtoIsPassedByRef(Type* type);
+bool DtoIsReturnedInArg(Type* type);
 
 // resolve typedefs to their real type.
 // TODO should probably be removed in favor of DMD's Type::toBasetype
@@ -54,10 +57,10 @@
 llvm::Function* LLVM_DeclareMemCpy64();
 
 // getelementptr helpers
-LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const std::string& var, llvm::BasicBlock* bb=NULL);
-LLValue* DtoGEP(LLValue* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb=NULL);
-LLValue* DtoGEPi(LLValue* ptr, unsigned i0, const std::string& var, llvm::BasicBlock* bb=NULL);
-LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const std::string& var, llvm::BasicBlock* bb=NULL);
+LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const char* var, llvm::BasicBlock* bb=NULL);
+LLValue* DtoGEPi(LLValue* ptr, const DStructIndexVector& src, const char* var, llvm::BasicBlock* bb=NULL);
+LLValue* DtoGEPi(LLValue* ptr, unsigned i0, const char* var, llvm::BasicBlock* bb=NULL);
+LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const char* var, llvm::BasicBlock* bb=NULL);
 
 // dynamic memory helpers
 LLValue* DtoNew(Type* newtype);
--- a/gen/toobj.cpp	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/toobj.cpp	Thu Jun 05 06:38:36 2008 +0200
@@ -16,6 +16,7 @@
 #include "llvm/Bitcode/ReaderWriter.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/System/Path.h"
 
 #include "mars.h"
 #include "module.h"
@@ -151,17 +152,36 @@
     // run optimizer
     llvmdc_optimize_module(ir.module, global.params.optimizeLevel, global.params.llvmInline);
 
+    // eventually do our own path stuff, dmd's is a bit strange.
+    typedef llvm::sys::Path LLPath;
+    LLPath bcpath;
+    LLPath llpath;
+
+    if (global.params.fqnPaths)
+    {
+        bcpath = LLPath(md->toChars());
+        bcpath.appendSuffix("bc");
+
+        llpath = LLPath(md->toChars());
+        llpath.appendSuffix("ll");
+    }
+    else
+    {
+        bcpath = LLPath(bcfile->name->toChars());
+        llpath = LLPath(llfile->name->toChars());
+    }
+
     // write bytecode
     {
         Logger::println("Writing LLVM bitcode\n");
-        std::ofstream bos(bcfile->name->toChars(), std::ios::binary);
+        std::ofstream bos(bcpath.c_str(), std::ios::binary);
         llvm::WriteBitcodeToFile(ir.module, bos);
     }
 
     // disassemble ?
     if (global.params.disassemble) {
         Logger::println("Writing LLVM asm to: %s\n", llfile->name->toChars());
-        std::ofstream aos(llfile->name->toChars());
+        std::ofstream aos(llpath.c_str());
         ir.module->print(aos);
     }
 
--- a/llvmdc.kdevelop.filelist	Tue Jun 03 22:32:59 2008 +0200
+++ b/llvmdc.kdevelop.filelist	Thu Jun 05 06:38:36 2008 +0200
@@ -749,7 +749,9 @@
 tangotests/aa1.d
 tangotests/aa2.d
 tangotests/align1.d
+tangotests/arrays1.d
 tangotests/b.d
+tangotests/byval1.d
 tangotests/c.d
 tangotests/classes1.d
 tangotests/constructors.d
--- a/tango/lib/compiler/llvmdc/memory.d	Tue Jun 03 22:32:59 2008 +0200
+++ b/tango/lib/compiler/llvmdc/memory.d	Thu Jun 05 06:38:36 2008 +0200
@@ -47,6 +47,7 @@
         {
                 void* llvm_frameaddress(uint level=0);
         }
+        extern(C) int printf(char*, ...);
     }
 }
 
@@ -161,6 +162,7 @@
     }
     else version( linux )
     {
+        //printf("scanning static data from %p to %p\n", &__data_start, &_end);
         scan( &__data_start, &_end );
     }
     else
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tangotests/vararg4.d	Thu Jun 05 06:38:36 2008 +0200
@@ -0,0 +1,30 @@
+module tangotests.vararg4;
+
+extern(C) int printf(char*, ...);
+
+struct S
+{
+    int i;
+}
+
+void func(...)
+{
+    S* sp = cast(S*)_argptr;
+    assert(sp.i == 42);
+}
+
+void main()
+{
+    printf("1st:\n");
+    {
+    S s = S(42);
+    func(s);
+    }
+    printf("ok\n");
+
+    printf("2nd:\n");
+    {
+    func(S(42));
+    }
+    printf("ok\n");
+}
--- a/tests/runtest	Tue Jun 03 22:32:59 2008 +0200
+++ b/tests/runtest	Thu Jun 05 06:38:36 2008 +0200
@@ -35,7 +35,7 @@
 
 if [ -z $DMD ] ; then
 	echo "Testing with llvmdc. Set DMD environment variable to select compiler."
-	DMD="llvmdc"
+	DMD="llvmdc -O0"
 else
 	echo "Using compiler given by DMD environment variable: $DMD"
 fi