D2: pass static arrays into functions by value

This commit is contained in:
Alexey Prokhin 2011-04-30 15:30:57 +04:00
parent 069f0a6262
commit 805fb5cfc1
5 changed files with 22 additions and 27 deletions

View file

@ -1193,10 +1193,9 @@ LLValue* DtoArrayLen(DValue* v)
else if (t->ty == Tsarray) { else if (t->ty == Tsarray) {
assert(!v->isSlice()); assert(!v->isSlice());
assert(!v->isNull()); assert(!v->isNull());
LLValue* rv = v->getRVal(); assert(v->type->toBasetype()->ty == Tsarray);
const LLArrayType* t = isaArray(rv->getType()->getContainedType(0)); TypeSArray *sarray = (TypeSArray*)v->type->toBasetype();
assert(t); return DtoConstSize_t(sarray->dim->toUInteger());
return DtoConstSize_t(t->getNumElements());
} }
assert(0 && "unsupported array for len"); assert(0 && "unsupported array for len");
return 0; return 0;
@ -1278,7 +1277,8 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to)
fatal(); 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()) if (fromtype->nextOf()->size() != totype->nextOf()->size())
rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0)); rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
rval = DtoBitCast(uval, ptrty); rval = DtoBitCast(uval, ptrty);

View file

@ -144,8 +144,11 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
// get argument // get argument
Parameter* arg = Parameter::getNth(f->parameters, i); Parameter* arg = Parameter::getNth(f->parameters, i);
// reference semantics? ref, out and static arrays are // reference semantics? ref, out and d1 static arrays are
bool byref = (arg->storageClass & (STCref|STCout)) || (arg->type->toBasetype()->ty == Tsarray); bool byref = arg->storageClass & (STCref|STCout);
#if !SARRAYVALUE
byref = byref || (arg->type->toBasetype()->ty == Tsarray);
#endif
Type* argtype = arg->type; Type* argtype = arg->type;
unsigned a = 0; 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); TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
TypeDelegate *ltd = new TypeDelegate(ltf); TypeDelegate *ltd = new TypeDelegate(ltf);
argtype = ltd; argtype = ltd;
#if DMDV2
byref = byref && arg->type->toBasetype()->ty != Tsarray;
#endif
} }
// byval // byval
else if (abi->passByVal(byref ? argtype->pointerTo() : argtype)) else if (abi->passByVal(byref ? argtype->pointerTo() : argtype))
@ -745,12 +745,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
bool refout = vd->storage_class & (STCref | STCout); bool refout = vd->storage_class & (STCref | STCout);
bool lazy = vd->storage_class & STClazy; 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)) if (!refout && (!f->fty.args[i]->byref || lazy))
#endif
{ {
// alloca a stack slot for this first class value arg // alloca a stack slot for this first class value arg
const LLType* argt; const LLType* argt;
@ -760,12 +755,6 @@ void DtoDefineFunction(FuncDeclaration* fd)
argt = DtoType(vd->type); argt = DtoType(vd->type);
LLValue* mem = DtoRawAlloca(argt, 0, vd->ident->toChars()); 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 // let the abi transform the argument back first
DImValue arg_dval(vd->type, irloc->value); DImValue arg_dval(vd->type, irloc->value);
f->fty.getParam(vd->type, i, &arg_dval, mem); f->fty.getParam(vd->type, i, &arg_dval, mem);

View file

@ -144,7 +144,7 @@ void ReturnStatement::toIR(IRState* p)
// If the function returns a struct or a static array, and the return // 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 // value is a pointer to a struct or a static array, load from it
// before returning. // before returning.
int ty = f->type->next->ty; int ty = f->type->next->toBasetype()->ty;
if (v->getType() != p->topfunc()->getReturnType() && if (v->getType() != p->topfunc()->getReturnType() &&
(ty == Tstruct (ty == Tstruct
#if DMDV2 #if DMDV2

View file

@ -139,11 +139,17 @@ static LLValue *fixArgument(DValue *argval, TypeFunction* tf, const LLType *call
} }
#endif #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 // If the function wants a struct, and the argument value is a
// pointer to a struct, load from it before passing it in. // pointer to a struct, load from it before passing it in.
if (argval->getType()->ty == Tstruct int ty = argval->getType()->toBasetype()->ty;
&& isaPointer(arg) && !isaPointer(callableArgType)) { if (isaPointer(arg) && !isaPointer(callableArgType) &&
#if DMDV2
(ty == Tstruct || ty == Tsarray))
#else
ty == Tstruct)
#endif
{
Logger::println("Loading struct type for function argument"); Logger::println("Loading struct type for function argument");
arg = DtoLoad(arg); 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 // 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 // value is not a pointer to a struct or a static array, store it to
// a stack slot before continuing. // a stack slot before continuing.
int ty = tf->next->ty; int ty = tf->next->toBasetype()->ty;
if ((ty == Tstruct && !isaPointer(retllval)) if ((ty == Tstruct && !isaPointer(retllval))
#if DMDV2 #if DMDV2
|| (ty == Tsarray && isaArray(retllval)) || (ty == Tsarray && isaArray(retllval))

View file

@ -176,7 +176,7 @@ const llvm::Type * IrTypeSArray::sarray2llvm(Type * t)
const llvm::Type* elemType = DtoType(t->nextOf()); const llvm::Type* elemType = DtoType(t->nextOf());
if (elemType == llvm::Type::getVoidTy(llvm::getGlobalContext())) if (elemType == llvm::Type::getVoidTy(llvm::getGlobalContext()))
elemType = llvm::Type::getInt8Ty(llvm::getGlobalContext()); elemType = llvm::Type::getInt8Ty(llvm::getGlobalContext());
return llvm::ArrayType::get(elemType, dim); return llvm::ArrayType::get(elemType, dim == 0 ? 1 : dim);
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////