From 805fb5cfc13a182c8aa46f02f12f427666806afb Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Sat, 30 Apr 2011 15:30:57 +0400 Subject: [PATCH] D2: pass static arrays into functions by value --- gen/arrays.cpp | 10 +++++----- gen/functions.cpp | 21 +++++---------------- gen/statements.cpp | 2 +- gen/tocall.cpp | 14 ++++++++++---- ir/irtype.cpp | 2 +- 5 files changed, 22 insertions(+), 27 deletions(-) diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 4af85bec..c27f09bb 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -1193,10 +1193,9 @@ LLValue* DtoArrayLen(DValue* v) else if (t->ty == Tsarray) { assert(!v->isSlice()); assert(!v->isNull()); - LLValue* rv = v->getRVal(); - const LLArrayType* t = isaArray(rv->getType()->getContainedType(0)); - assert(t); - return DtoConstSize_t(t->getNumElements()); + assert(v->type->toBasetype()->ty == Tsarray); + TypeSArray *sarray = (TypeSArray*)v->type->toBasetype(); + return DtoConstSize_t(sarray->dim->toUInteger()); } assert(0 && "unsupported array for len"); return 0; @@ -1278,7 +1277,8 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to) fatal(); } - rval2 = LLConstantInt::get(DtoSize_t(), arrty->getNumElements(), false); + uinteger_t len = ((TypeSArray*)fromtype)->dim->toUInteger(); + rval2 = LLConstantInt::get(DtoSize_t(), len, false); if (fromtype->nextOf()->size() != totype->nextOf()->size()) rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0)); rval = DtoBitCast(uval, ptrty); diff --git a/gen/functions.cpp b/gen/functions.cpp index dc1d0fb3..94d63e22 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -144,8 +144,11 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest // get argument Parameter* arg = Parameter::getNth(f->parameters, i); - // reference semantics? ref, out and static arrays are - bool byref = (arg->storageClass & (STCref|STCout)) || (arg->type->toBasetype()->ty == Tsarray); + // reference semantics? ref, out and d1 static arrays are + bool byref = arg->storageClass & (STCref|STCout); +#if !SARRAYVALUE + byref = byref || (arg->type->toBasetype()->ty == Tsarray); +#endif Type* argtype = arg->type; unsigned a = 0; @@ -157,9 +160,6 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd); TypeDelegate *ltd = new TypeDelegate(ltf); argtype = ltd; -#if DMDV2 - byref = byref && arg->type->toBasetype()->ty != Tsarray; -#endif } // byval else if (abi->passByVal(byref ? argtype->pointerTo() : argtype)) @@ -745,12 +745,7 @@ void DtoDefineFunction(FuncDeclaration* fd) bool refout = vd->storage_class & (STCref | STCout); bool lazy = vd->storage_class & STClazy; -#if DMDV2 - bool isStaticArray = vd->type->toBasetype()->ty == Tsarray; - if (!refout && (!f->fty.args[i]->byref || lazy || isStaticArray)) -#else if (!refout && (!f->fty.args[i]->byref || lazy)) -#endif { // alloca a stack slot for this first class value arg const LLType* argt; @@ -760,12 +755,6 @@ void DtoDefineFunction(FuncDeclaration* fd) argt = DtoType(vd->type); LLValue* mem = DtoRawAlloca(argt, 0, vd->ident->toChars()); -#if DMDV2 - // if it is a static array, load from it, because static arrays - // are always passed by reference - if (isStaticArray && !lazy) - irloc->value = DtoLoad(irloc->value); -#endif // let the abi transform the argument back first DImValue arg_dval(vd->type, irloc->value); f->fty.getParam(vd->type, i, &arg_dval, mem); diff --git a/gen/statements.cpp b/gen/statements.cpp index 0b929781..76226af9 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -144,7 +144,7 @@ void ReturnStatement::toIR(IRState* p) // If the function returns a struct or a static array, and the return // value is a pointer to a struct or a static array, load from it // before returning. - int ty = f->type->next->ty; + int ty = f->type->next->toBasetype()->ty; if (v->getType() != p->topfunc()->getReturnType() && (ty == Tstruct #if DMDV2 diff --git a/gen/tocall.cpp b/gen/tocall.cpp index 93c2bce7..29c71049 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -139,11 +139,17 @@ static LLValue *fixArgument(DValue *argval, TypeFunction* tf, const LLType *call } #endif - // Hack around LDC assuming structs are in memory: + // Hack around LDC assuming structs and static arrays are in memory: // If the function wants a struct, and the argument value is a // pointer to a struct, load from it before passing it in. - if (argval->getType()->ty == Tstruct - && isaPointer(arg) && !isaPointer(callableArgType)) { + int ty = argval->getType()->toBasetype()->ty; + if (isaPointer(arg) && !isaPointer(callableArgType) && +#if DMDV2 + (ty == Tstruct || ty == Tsarray)) +#else + ty == Tstruct) +#endif + { Logger::println("Loading struct type for function argument"); arg = DtoLoad(arg); } @@ -586,7 +592,7 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* // If the function returns a struct or a static array, and the return // value is not a pointer to a struct or a static array, store it to // a stack slot before continuing. - int ty = tf->next->ty; + int ty = tf->next->toBasetype()->ty; if ((ty == Tstruct && !isaPointer(retllval)) #if DMDV2 || (ty == Tsarray && isaArray(retllval)) diff --git a/ir/irtype.cpp b/ir/irtype.cpp index 44d29f3a..92a0499b 100644 --- a/ir/irtype.cpp +++ b/ir/irtype.cpp @@ -176,7 +176,7 @@ const llvm::Type * IrTypeSArray::sarray2llvm(Type * t) const llvm::Type* elemType = DtoType(t->nextOf()); if (elemType == llvm::Type::getVoidTy(llvm::getGlobalContext())) elemType = llvm::Type::getInt8Ty(llvm::getGlobalContext()); - return llvm::ArrayType::get(elemType, dim); + return llvm::ArrayType::get(elemType, dim == 0 ? 1 : dim); } //////////////////////////////////////////////////////////////////////////////