Merge pull request #8180 from gottesmm/small_result_plan_refactor
[silgen] Move foreignErrorPreparation code in ResultPlanBuilder into a new buildTopLevelResult method.
diff --git a/lib/SILGen/FormalEvaluation.cpp b/lib/SILGen/FormalEvaluation.cpp
index 8e0922c..b14d0df 100644
--- a/lib/SILGen/FormalEvaluation.cpp
+++ b/lib/SILGen/FormalEvaluation.cpp
@@ -50,8 +50,9 @@
FormalEvaluationScope::FormalEvaluationScope(SILGenFunction &SGF)
: SGF(SGF), savedDepth(SGF.FormalEvalContext.stable_begin()),
- wasInWritebackScope(SGF.InWritebackScope) {
- if (SGF.InInOutConversionScope) {
+ wasInWritebackScope(SGF.InWritebackScope),
+ wasInInOutConversionScope(SGF.InInOutConversionScope) {
+ if (wasInInOutConversionScope) {
savedDepth.reset();
return;
}
@@ -60,7 +61,8 @@
FormalEvaluationScope::FormalEvaluationScope(FormalEvaluationScope &&o)
: SGF(o.SGF), savedDepth(o.savedDepth),
- wasInWritebackScope(o.wasInWritebackScope) {
+ wasInWritebackScope(o.wasInWritebackScope),
+ wasInInOutConversionScope(o.wasInInOutConversionScope) {
o.savedDepth.reset();
}
diff --git a/lib/SILGen/FormalEvaluation.h b/lib/SILGen/FormalEvaluation.h
index 929bbd9..66a0a51 100644
--- a/lib/SILGen/FormalEvaluation.h
+++ b/lib/SILGen/FormalEvaluation.h
@@ -175,6 +175,7 @@
SILGenFunction &SGF;
llvm::Optional<FormalEvaluationContext::stable_iterator> savedDepth;
bool wasInWritebackScope;
+ bool wasInInOutConversionScope;
public:
FormalEvaluationScope(SILGenFunction &SGF);
@@ -187,6 +188,9 @@
bool isPopped() const { return !savedDepth.hasValue(); }
void pop() {
+ if (wasInInOutConversionScope)
+ return;
+
assert(!isPopped() && "popping an already-popped writeback scope!");
popImpl();
savedDepth.reset();
diff --git a/lib/SILGen/ResultPlan.cpp b/lib/SILGen/ResultPlan.cpp
index a11442d..d47355c 100644
--- a/lib/SILGen/ResultPlan.cpp
+++ b/lib/SILGen/ResultPlan.cpp
@@ -290,6 +290,50 @@
/// Build a result plan for the results of an apply.
///
/// If the initialization is non-null, the result plan will emit into it.
+ResultPlanPtr ResultPlanBuilder::buildTopLevelResult(Initialization *init) {
+ // First check if we do not have a foreign error. If we don't, just call
+ // build.
+ auto foreignError = calleeTypeInfo.foreignError;
+ if (!foreignError) {
+ return build(init, calleeTypeInfo.origResultType,
+ calleeTypeInfo.substResultType);
+ }
+
+ // Otherwise, handle the foreign error first.
+ //
+ // The plan needs to be built using the formal result type after foreign-error
+ // adjustment.
+ switch (foreignError->getKind()) {
+ // These conventions make the formal result type ().
+ case ForeignErrorConvention::ZeroResult:
+ case ForeignErrorConvention::NonZeroResult:
+ assert(calleeTypeInfo.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);
+ CanType objectType = allResults[0].getType().getAnyOptionalObjectType();
+ SILResultInfo optResult = allResults[0].getWithType(objectType);
+ allResults = optResult;
+ break;
+ }
+ }
+
+ return build(init, calleeTypeInfo.origResultType,
+ calleeTypeInfo.substResultType);
+}
+
+/// Build a result plan for the results of an apply.
+///
+/// If the initialization is non-null, the result plan will emit into it.
ResultPlanPtr ResultPlanBuilder::build(Initialization *init,
AbstractionPattern origType,
CanType substType) {
@@ -310,7 +354,7 @@
// there are no abstraction differences, then just do it.
if (initAddr && SGF.silConv.isSILIndirect(result) &&
!initAddr->getType().hasAbstractionDifference(
- rep, result.getSILStorageType())) {
+ calleeTypeInfo.getOverrideRep(), result.getSILStorageType())) {
return ResultPlanPtr(new InPlaceInitializationResultPlan(init));
}
}
@@ -329,8 +373,8 @@
temporary = SGF.emitTemporary(loc, resultTL);
}
- return ResultPlanPtr(
- new ScalarResultPlan(std::move(temporary), origType, init, rep));
+ return ResultPlanPtr(new ScalarResultPlan(
+ std::move(temporary), origType, init, calleeTypeInfo.getOverrideRep()));
}
ResultPlanPtr ResultPlanBuilder::buildForTuple(Initialization *init,
@@ -380,41 +424,6 @@
ResultPlanBuilder::computeResultPlan(SILGenFunction &SGF,
CalleeTypeInfo &calleeTypeInfo,
SILLocation loc, SGFContext evalContext) {
- auto origResultTypeForPlan = calleeTypeInfo.origResultType;
- auto substResultTypeForPlan = calleeTypeInfo.substResultType;
- ArrayRef<SILResultInfo> allResults = calleeTypeInfo.substFnType->getResults();
- SILResultInfo optResult;
-
- // The plan needs to be built using the formal result type
- // after foreign-error adjustment.
- if (auto foreignError = calleeTypeInfo.foreignError) {
- switch (foreignError->getKind()) {
- // These conventions make the formal result type ().
- case ForeignErrorConvention::ZeroResult:
- case ForeignErrorConvention::NonZeroResult:
- assert(calleeTypeInfo.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);
- CanType objectType = allResults[0].getType().getAnyOptionalObjectType();
- optResult = allResults[0].getWithType(objectType);
- allResults = optResult;
- break;
- }
- }
- }
-
- ResultPlanBuilder builder(SGF, loc, allResults,
- calleeTypeInfo.getOverrideRep());
- return builder.build(evalContext.getEmitInto(), origResultTypeForPlan,
- substResultTypeForPlan);
+ ResultPlanBuilder builder(SGF, loc, calleeTypeInfo);
+ return builder.buildTopLevelResult(evalContext.getEmitInto());
}
diff --git a/lib/SILGen/ResultPlan.h b/lib/SILGen/ResultPlan.h
index 288a7ca..256830b 100644
--- a/lib/SILGen/ResultPlan.h
+++ b/lib/SILGen/ResultPlan.h
@@ -13,6 +13,7 @@
#ifndef SWIFT_SILGEN_RESULTPLAN_H
#define SWIFT_SILGEN_RESULTPLAN_H
+#include "Callee.h"
#include "swift/AST/Types.h"
#include "swift/Basic/LLVM.h"
#include "swift/SIL/SILLocation.h"
@@ -50,13 +51,13 @@
struct ResultPlanBuilder {
SILGenFunction &SGF;
SILLocation loc;
+ CalleeTypeInfo &calleeTypeInfo;
ArrayRef<SILResultInfo> allResults;
- SILFunctionTypeRepresentation rep;
ResultPlanBuilder(SILGenFunction &SGF, SILLocation loc,
- ArrayRef<SILResultInfo> allResults,
- SILFunctionTypeRepresentation rep)
- : SGF(SGF), loc(loc), allResults(allResults), rep(rep) {}
+ CalleeTypeInfo &calleeTypeInfo)
+ : SGF(SGF), loc(loc), calleeTypeInfo(calleeTypeInfo),
+ allResults(calleeTypeInfo.substFnType->getResults()) {}
ResultPlanPtr build(Initialization *emitInto, AbstractionPattern origType,
CanType substType);
@@ -72,6 +73,9 @@
~ResultPlanBuilder() {
assert(allResults.empty() && "didn't consume all results!");
}
+
+private:
+ ResultPlanPtr buildTopLevelResult(Initialization *init);
};
} // end namespace Lowering