mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-14 15:16:07 +03:00
Simplify generation of a call's return value
This commit is contained in:
parent
0f41c0c681
commit
7778db00a8
3 changed files with 8 additions and 36 deletions
|
@ -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 "
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue