Skip to content

[gardening] Refactor out construction of the ResultPlan into a helper… #5770

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 49 additions & 39 deletions lib/SILGen/SILGenApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2272,6 +2272,52 @@ static bool hasUnownedInnerPointerResult(CanSILFunctionType fnType) {
return false;
}

static ResultPlanPtr
computeResultPlan(SILGenFunction *SGF, CanSILFunctionType substFnType,
AbstractionPattern origResultType, CanType substResultType,
const Optional<ForeignErrorConvention> &foreignError,
SILFunctionTypeRepresentation rep, SILLocation loc,
SGFContext evalContext,
SmallVectorImpl<SILValue> &indirectResultAddrs) {
auto origResultTypeForPlan = origResultType;
auto substResultTypeForPlan = substResultType;
ArrayRef<SILResultInfo> allResults = substFnType->getAllResults();
SILResultInfo optResult;

// The plan needs to be built using the formal result type
// after foreign-error adjustment.
if (foreignError) {
switch (foreignError->getKind()) {
// These conventions make the formal result type ().
case ForeignErrorConvention::ZeroResult:
case ForeignErrorConvention::NonZeroResult:
assert(substResultType->isVoid());
allResults = {};
break;

// These conventions leave the formal result alone.
case ForeignErrorConvention::ZeroPreservedResult:
case ForeignErrorConvention::NonNilError:
break;

// This convention changes the formal result to the optional object
// type; we need to make our own make SILResultInfo array.
case ForeignErrorConvention::NilResult: {
assert(allResults.size() == 1);
SILType objectType =
allResults[0].getSILType().getAnyOptionalObjectType();
optResult = allResults[0].getWithType(objectType.getSwiftRValueType());
allResults = optResult;
break;
}
}
}

ResultPlanBuilder builder(*SGF, loc, allResults, rep, indirectResultAddrs);
return builder.build(evalContext.getEmitInto(), origResultTypeForPlan,
substResultTypeForPlan);
}

/// Emit a function application, assuming that the arguments have been
/// lowered appropriately for the abstraction level but that the
/// result does need to be turned back into something matching a
Expand All @@ -2292,45 +2338,9 @@ RValue SILGenFunction::emitApply(

// Create the result plan.
SmallVector<SILValue, 4> indirectResultAddrs;
ResultPlanPtr resultPlan = [&]() -> ResultPlanPtr {
auto origResultTypeForPlan = origResultType;
auto substResultTypeForPlan = substResultType;
ArrayRef<SILResultInfo> allResults = substFnType->getAllResults();
SILResultInfo optResult;

// The plan needs to be built using the formal result type
// after foreign-error adjustment.
if (foreignError) {
switch (foreignError->getKind()) {
// These conventions make the formal result type ().
case ForeignErrorConvention::ZeroResult:
case ForeignErrorConvention::NonZeroResult:
assert(substResultType->isVoid());
allResults = {};
break;

// These conventions leave the formal result alone.
case ForeignErrorConvention::ZeroPreservedResult:
case ForeignErrorConvention::NonNilError:
break;

// This convention changes the formal result to the optional object
// type; we need to make our own make SILResultInfo array.
case ForeignErrorConvention::NilResult: {
assert(allResults.size() == 1);
SILType objectType =
allResults[0].getSILType().getAnyOptionalObjectType();
optResult = allResults[0].getWithType(objectType.getSwiftRValueType());
allResults = optResult;
break;
}
}
}

ResultPlanBuilder builder(*this, loc, allResults, rep, indirectResultAddrs);
return builder.build(evalContext.getEmitInto(),
origResultTypeForPlan, substResultTypeForPlan);
}();
ResultPlanPtr resultPlan = computeResultPlan(
this, substFnType, origResultType, substResultType, foreignError, rep,
loc, evalContext, indirectResultAddrs);

// If the function returns an inner pointer, we'll need to lifetime-extend
// the 'self' parameter.
Expand Down