Simplify generation of a call's return value

This commit is contained in:
Martin 2016-05-29 13:47:39 +02:00
parent 0f41c0c681
commit 7778db00a8
3 changed files with 8 additions and 36 deletions

View file

@ -1600,7 +1600,6 @@ DValue *DtoSymbolAddress(Loc &loc, Type *type, Declaration *decl) {
if (vd->storage_class & STClazy) { if (vd->storage_class & STClazy) {
Logger::println("lazy parameter"); Logger::println("lazy parameter");
assert(type->ty == Tdelegate); assert(type->ty == Tdelegate);
return new DVarValue(type, getIrValue(vd));
} }
assert(!isSpecialRefVar(vd) && "Code not expected to handle special " assert(!isSpecialRefVar(vd) && "Code not expected to handle special "
"ref vars, although it can easily be " "ref vars, although it can easily be "

View file

@ -168,7 +168,7 @@ void DtoPaddedStruct(Type *dty, LLValue *v, LLValue *lval) {
// Nested structs are the only members that can contain padding // Nested structs are the only members that can contain padding
DtoPaddedStruct(fields[i]->type, fieldval, fieldptr); DtoPaddedStruct(fields[i]->type, fieldval, fieldptr);
} else { } else {
DtoStore(fieldval, fieldptr); DtoStoreZextI8(fieldval, fieldptr);
} }
} }
} }

View file

@ -882,45 +882,21 @@ DValue *DtoCallFunction(Loc &loc, Type *resulttype, DValue *fnval,
: 0); : 0);
LLValue *retllval = LLValue *retllval =
(irFty.arg_sret ? args[sretArgIndex] : call.getInstruction()); (irFty.arg_sret ? args[sretArgIndex] : call.getInstruction());
bool retValIsLVal = (tf->isref && returnTy != Tvoid) || (irFty.arg_sret != nullptr);
// Hack around LDC assuming structs and static arrays are in memory: if (!retValIsLVal) {
// If the function returns a struct or a static array, and the return // let the ABI transform the return value back
// value is not a pointer to a struct or a static array, store it to if (DtoIsInMemoryOnly(returntype)) {
// a stack slot before continuing.
bool storeReturnValueOnStack =
(returnTy == Tstruct && !isaPointer(retllval)) ||
(returnTy == Tsarray && isaArray(retllval));
bool retValIsAlloca = false;
// ignore ABI for intrinsics
const bool intrinsic =
(dfnval && dfnval->func && DtoIsIntrinsic(dfnval->func));
if (!intrinsic && !irFty.arg_sret) {
// do ABI specific return value fixups
if (storeReturnValueOnStack) {
Logger::println("Storing return value to stack slot");
retllval = irFty.getRetLVal(returntype, retllval); retllval = irFty.getRetLVal(returntype, retllval);
retValIsAlloca = true; retValIsLVal = true;
storeReturnValueOnStack = false;
} else { } else {
retllval = irFty.getRetRVal(returntype, retllval); retllval = irFty.getRetRVal(returntype, retllval);
storeReturnValueOnStack =
(returnTy == Tstruct && !isaPointer(retllval)) ||
(returnTy == Tsarray && isaArray(retllval));
} }
} }
if (storeReturnValueOnStack) {
Logger::println("Storing return value to stack slot");
retllval = DtoAllocaDump(retllval, returntype);
retValIsAlloca = true;
}
// repaint the type if necessary // repaint the type if necessary
Type *rbase = stripModifiers(resulttype->toBasetype(), true); Type *rbase = stripModifiers(resulttype->toBasetype(), true);
Type *nextbase = stripModifiers(returntype->toBasetype(), true); Type *nextbase = stripModifiers(returntype->toBasetype(), true);
bool retinptr = irFty.arg_sret;
if (!rbase->equals(nextbase)) { if (!rbase->equals(nextbase)) {
IF_LOG Logger::println("repainting return value from '%s' to '%s'", IF_LOG Logger::println("repainting return value from '%s' to '%s'",
returntype->toChars(), rbase->toChars()); returntype->toChars(), rbase->toChars());
@ -958,7 +934,7 @@ DValue *DtoCallFunction(Loc &loc, Type *resulttype, DValue *fnval,
LLValue *val = LLValue *val =
DtoInsertValue(llvm::UndefValue::get(DtoType(rbase)), retllval, 0); DtoInsertValue(llvm::UndefValue::get(DtoType(rbase)), retllval, 0);
retllval = DtoAllocaDump(val, rbase, ".aalvaluetmp"); retllval = DtoAllocaDump(val, rbase, ".aalvaluetmp");
retinptr = true; retValIsLVal = true;
break; break;
} }
// Fall through. // Fall through.
@ -1033,10 +1009,7 @@ DValue *DtoCallFunction(Loc &loc, Type *resulttype, DValue *fnval,
return new DVarValue(resulttype, dfnval->vthis); return new DVarValue(resulttype, dfnval->vthis);
} }
// if we are returning through a pointer arg if (retValIsLVal) {
// or if we are returning a reference
// make sure we provide a lvalue back!
if (retinptr || (tf->isref && returnTy != Tvoid) || retValIsAlloca) {
return new DVarValue(resulttype, retllval); return new DVarValue(resulttype, retllval);
} }