# HG changeset patch # User lindquist # Date 1212640716 -7200 # Node ID 0806379a5eca1e9e083420c14b45ff9b27778b47 # Parent 3d022aa016ae6aeeb66980936eca8bca6eb23249 [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. diff -r 3d022aa016ae -r 0806379a5eca dmd/mars.c --- 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 write object files to directory \n\ -of name output file to \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); diff -r 3d022aa016ae -r 0806379a5eca dmd/mars.h --- 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 diff -r 3d022aa016ae -r 0806379a5eca dmd/mtype.c --- 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; } diff -r 3d022aa016ae -r 0806379a5eca dmd/mtype.h --- 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; diff -r 3d022aa016ae -r 0806379a5eca gen/aa.cpp --- 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 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 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); diff -r 3d022aa016ae -r 0806379a5eca gen/arrays.cpp --- 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 args; + LLSmallVector 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 llargs; - llargs.resize(4); + LLSmallVector 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 llargs; - llargs.resize(4); + LLSmallVector 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 llargs; - llargs.resize(4); + LLSmallVector 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 types; - types.push_back(dim->getType()); - types.push_back(ptr->getType()); - const llvm::StructType* type = llvm::StructType::get(types); - std::vector 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 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 args; + LLSmallVector 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 args; + LLSmallVector 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)); diff -r 3d022aa016ae -r 0806379a5eca gen/classes.cpp --- 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 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 ctorargs; ctorargs.push_back(mem); for (size_t i=0; idim; ++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 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 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& 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 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 tmp; + DStructIndexVector tmp; return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); } else { diff -r 3d022aa016ae -r 0806379a5eca gen/classes.h --- 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& idxs); +LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os, DStructIndexVector& idxs); LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl); diff -r 3d022aa016ae -r 0806379a5eca gen/complex.cpp --- 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 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 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()); diff -r 3d022aa016ae -r 0806379a5eca gen/complex.h --- 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); diff -r 3d022aa016ae -r 0806379a5eca gen/functions.cpp --- 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(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(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 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; } diff -r 3d022aa016ae -r 0806379a5eca gen/statements.cpp --- 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 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) diff -r 3d022aa016ae -r 0806379a5eca gen/structs.cpp --- 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& 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 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 tmp; + DStructIndexVector tmp; return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); } else { diff -r 3d022aa016ae -r 0806379a5eca gen/structs.h --- 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& idxs); +typedef LLSmallVector DStructIndexVector; +LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, DStructIndexVector& idxs); struct DUnionField { diff -r 3d022aa016ae -r 0806379a5eca gen/todebug.cpp --- 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 args; + LLSmallVector args; args.push_back(DtoConstUint(ln)); args.push_back(DtoConstUint(0)); FuncDeclaration* fd = gIR->func()->decl; diff -r 3d022aa016ae -r 0806379a5eca gen/toir.cpp --- 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(r->isConst()->c); TypeStruct* ts = (TypeStruct*)e1next; - std::vector 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 dst; + DStructIndexVector dst; varmem = DtoIndexStruct(llvalue,vdt->sym, tnext, offset, dst); } } @@ -1429,7 +1445,7 @@ LLValue* src = l->getRVal(); - std::vector 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 vdoffsets; + DStructIndexVector vdoffsets; arrptr = DtoIndexClass(src, tc->sym, vd->type, vd->offset, vdoffsets); /*std::vector 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; diff -r 3d022aa016ae -r 0806379a5eca gen/tollvm.cpp --- 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 v(2); + LLSmallVector 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& 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 dst(n, NULL); - //std::ostream& ostr = Logger::cout(); - //ostr << "indices for '" << *ptr << "':"; - for (size_t i=0; i 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 v(2); - v[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i0, false); - v[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i1, false); + LLSmallVector 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 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); } ////////////////////////////////////////////////////////////////////////////////////////// diff -r 3d022aa016ae -r 0806379a5eca gen/tollvm.h --- 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& 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); diff -r 3d022aa016ae -r 0806379a5eca gen/toobj.cpp --- 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); } diff -r 3d022aa016ae -r 0806379a5eca llvmdc.kdevelop.filelist --- 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 diff -r 3d022aa016ae -r 0806379a5eca tango/lib/compiler/llvmdc/memory.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 diff -r 3d022aa016ae -r 0806379a5eca tangotests/vararg4.d --- /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"); +} diff -r 3d022aa016ae -r 0806379a5eca tests/runtest --- 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