Skip to content

Commit 213ddd7

Browse files
committed
[silgen] Compute the ResultPlan outside of SILGenApply so that we can untangle indirect result/normal argument lifetime scopes.
rdar://30955427
1 parent b052263 commit 213ddd7

14 files changed

+132
-90
lines changed

lib/SILGen/ResultPlan.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "ResultPlan.h"
14+
#include "Callee.h"
1415
#include "Initialization.h"
1516
#include "RValue.h"
1617
#include "SILGenFunction.h"
@@ -374,3 +375,46 @@ ResultPlanPtr ResultPlanBuilder::buildForTuple(Initialization *init,
374375
return ResultPlanPtr(
375376
new InitValueFromRValueResultPlan(init, std::move(subplan)));
376377
}
378+
379+
ResultPlanPtr
380+
ResultPlanBuilder::computeResultPlan(SILGenFunction &SGF,
381+
CalleeTypeInfo &calleeTypeInfo,
382+
SILLocation loc, SGFContext evalContext) {
383+
auto origResultTypeForPlan = calleeTypeInfo.origResultType;
384+
auto substResultTypeForPlan = calleeTypeInfo.substResultType;
385+
ArrayRef<SILResultInfo> allResults = calleeTypeInfo.substFnType->getResults();
386+
SILResultInfo optResult;
387+
388+
// The plan needs to be built using the formal result type
389+
// after foreign-error adjustment.
390+
if (auto foreignError = calleeTypeInfo.foreignError) {
391+
switch (foreignError->getKind()) {
392+
// These conventions make the formal result type ().
393+
case ForeignErrorConvention::ZeroResult:
394+
case ForeignErrorConvention::NonZeroResult:
395+
assert(calleeTypeInfo.substResultType->isVoid());
396+
allResults = {};
397+
break;
398+
399+
// These conventions leave the formal result alone.
400+
case ForeignErrorConvention::ZeroPreservedResult:
401+
case ForeignErrorConvention::NonNilError:
402+
break;
403+
404+
// This convention changes the formal result to the optional object
405+
// type; we need to make our own make SILResultInfo array.
406+
case ForeignErrorConvention::NilResult: {
407+
assert(allResults.size() == 1);
408+
CanType objectType = allResults[0].getType().getAnyOptionalObjectType();
409+
optResult = allResults[0].getWithType(objectType);
410+
allResults = optResult;
411+
break;
412+
}
413+
}
414+
}
415+
416+
ResultPlanBuilder builder(SGF, loc, allResults,
417+
calleeTypeInfo.getOverrideRep());
418+
return builder.build(evalContext.getEmitInto(), origResultTypeForPlan,
419+
substResultTypeForPlan);
420+
}

lib/SILGen/ResultPlan.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class Initialization;
3030
class ManagedValue;
3131
class RValue;
3232
class SILGenFunction;
33+
class SGFContext;
34+
class CalleeTypeInfo;
3335

3436
/// An abstract class for working with results.of applies.
3537
class ResultPlan {
@@ -62,6 +64,11 @@ struct ResultPlanBuilder {
6264
AbstractionPattern origType,
6365
CanTupleType substType);
6466

67+
static ResultPlanPtr computeResultPlan(SILGenFunction &SGF,
68+
CalleeTypeInfo &calleeTypeInfo,
69+
SILLocation loc,
70+
SGFContext evalContext);
71+
6572
~ResultPlanBuilder() {
6673
assert(allResults.empty() && "didn't consume all results!");
6774
}

lib/SILGen/SILGenApply.cpp

Lines changed: 23 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,64 +1740,19 @@ static bool hasUnownedInnerPointerResult(CanSILFunctionType fnType) {
17401740
return false;
17411741
}
17421742

1743-
static ResultPlanPtr computeResultPlan(SILGenFunction *SGF,
1744-
CalleeTypeInfo &calleeTypeInfo,
1745-
SILLocation loc,
1746-
SGFContext evalContext) {
1747-
auto origResultTypeForPlan = calleeTypeInfo.origResultType;
1748-
auto substResultTypeForPlan = calleeTypeInfo.substResultType;
1749-
ArrayRef<SILResultInfo> allResults = calleeTypeInfo.substFnType->getResults();
1750-
SILResultInfo optResult;
1751-
1752-
// The plan needs to be built using the formal result type
1753-
// after foreign-error adjustment.
1754-
if (auto foreignError = calleeTypeInfo.foreignError) {
1755-
switch (foreignError->getKind()) {
1756-
// These conventions make the formal result type ().
1757-
case ForeignErrorConvention::ZeroResult:
1758-
case ForeignErrorConvention::NonZeroResult:
1759-
assert(calleeTypeInfo.substResultType->isVoid());
1760-
allResults = {};
1761-
break;
1762-
1763-
// These conventions leave the formal result alone.
1764-
case ForeignErrorConvention::ZeroPreservedResult:
1765-
case ForeignErrorConvention::NonNilError:
1766-
break;
1767-
1768-
// This convention changes the formal result to the optional object
1769-
// type; we need to make our own make SILResultInfo array.
1770-
case ForeignErrorConvention::NilResult: {
1771-
assert(allResults.size() == 1);
1772-
CanType objectType = allResults[0].getType().getAnyOptionalObjectType();
1773-
optResult = allResults[0].getWithType(objectType);
1774-
allResults = optResult;
1775-
break;
1776-
}
1777-
}
1778-
}
1779-
1780-
ResultPlanBuilder builder(*SGF, loc, allResults,
1781-
calleeTypeInfo.getOverrideRep());
1782-
return builder.build(evalContext.getEmitInto(), origResultTypeForPlan,
1783-
substResultTypeForPlan);
1784-
}
1785-
17861743
/// Emit a function application, assuming that the arguments have been
17871744
/// lowered appropriately for the abstraction level but that the
17881745
/// result does need to be turned back into something matching a
17891746
/// formal type.
1790-
RValue SILGenFunction::emitApply(SILLocation loc, ManagedValue fn,
1791-
SubstitutionList subs,
1747+
RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan, SILLocation loc,
1748+
ManagedValue fn, SubstitutionList subs,
17921749
ArrayRef<ManagedValue> args,
17931750
CalleeTypeInfo &calleeTypeInfo,
17941751
ApplyOptions options, SGFContext evalContext) {
17951752
auto substFnType = calleeTypeInfo.substFnType;
17961753
auto substResultType = calleeTypeInfo.substResultType;
17971754

17981755
// Create the result plan.
1799-
ResultPlanPtr resultPlan =
1800-
computeResultPlan(this, calleeTypeInfo, loc, evalContext);
18011756
SmallVector<SILValue, 4> indirectResultAddrs;
18021757
resultPlan->gatherIndirectResultAddrs(indirectResultAddrs);
18031758

@@ -1966,9 +1921,13 @@ RValue SILGenFunction::emitMonomorphicApply(SILLocation loc,
19661921
const Optional<ForeignErrorConvention> &foreignError){
19671922
auto fnType = fn.getType().castTo<SILFunctionType>();
19681923
assert(!fnType->isPolymorphic());
1924+
SGFContext evalContext;
19691925
CalleeTypeInfo calleeTypeInfo(fnType, AbstractionPattern(resultType),
19701926
resultType, foreignError, overrideRep);
1971-
return emitApply(loc, fn, {}, args, calleeTypeInfo, options, SGFContext());
1927+
ResultPlanPtr resultPlan = ResultPlanBuilder::computeResultPlan(
1928+
*this, calleeTypeInfo, loc, evalContext);
1929+
return emitApply(std::move(resultPlan), loc, fn, {}, args, calleeTypeInfo,
1930+
options, evalContext);
19721931
}
19731932

19741933
/// Count the number of SILParameterInfos that are needed in order to
@@ -3870,6 +3829,8 @@ RValue CallEmission::applyNormalCall(
38703829
CalleeTypeInfo calleeTypeInfo(
38713830
substFnType, getUncurriedOrigFormalType(*origFormalType),
38723831
uncurriedSites.back().getSubstResultType(), foreignError);
3832+
ResultPlanPtr resultPlan = ResultPlanBuilder::computeResultPlan(
3833+
SGF, calleeTypeInfo, uncurriedSites.back().Loc, uncurriedContext);
38733834

38743835
// Now that we know the substFnType, check if we assumed that we were
38753836
// passing self at +0. If we did and self is not actually passed at +0,
@@ -3894,9 +3855,9 @@ RValue CallEmission::applyNormalCall(
38943855
initialOptions, uncurriedArgs, uncurriedLoc,
38953856
formalApplyType);
38963857
// Emit the uncurried call.
3897-
return SGF.emitApply(uncurriedLoc.getValue(), mv, callee.getSubstitutions(),
3898-
uncurriedArgs, calleeTypeInfo, initialOptions,
3899-
uncurriedContext);
3858+
return SGF.emitApply(std::move(resultPlan), uncurriedLoc.getValue(), mv,
3859+
callee.getSubstitutions(), uncurriedArgs, calleeTypeInfo,
3860+
initialOptions, uncurriedContext);
39003861
}
39013862

39023863
RValue CallEmission::applyEnumElementConstructor(
@@ -4239,10 +4200,14 @@ RValue CallEmission::applyRemainingCallSites(
42394200
AbstractionPattern origResultType(formalType.getResult());
42404201
AbstractionPattern origParamType(claimNextParamClause(formalType));
42414202

4242-
// Create the callee type info.
4203+
SGFContext context = i == size - 1 ? C : SGFContext();
4204+
4205+
// Create the callee type info and initialize our indirect results.
42434206
CalleeTypeInfo calleeTypeInfo(substFnType, origResultType,
42444207
extraSites[i].getSubstResultType(),
42454208
foreignError);
4209+
ResultPlanPtr resultPtr =
4210+
ResultPlanBuilder::computeResultPlan(SGF, calleeTypeInfo, loc, context);
42464211

42474212
std::move(extraSites[i])
42484213
.emit(SGF, origParamType, paramLowering, siteArgs, inoutArgs,
@@ -4251,11 +4216,10 @@ RValue CallEmission::applyRemainingCallSites(
42514216
beginInOutFormalAccesses(SGF, inoutArgs, siteArgs);
42524217
}
42534218

4254-
SGFContext context = i == size - 1 ? C : SGFContext();
42554219
ApplyOptions options = ApplyOptions::None;
42564220

4257-
result = SGF.emitApply(loc, functionMV, {}, siteArgs, calleeTypeInfo,
4258-
options, context);
4221+
result = SGF.emitApply(std::move(resultPtr), loc, functionMV, {}, siteArgs,
4222+
calleeTypeInfo, options, context);
42594223
}
42604224

42614225
return std::move(result);
@@ -4332,7 +4296,10 @@ SILGenFunction::emitApplyOfLibraryIntrinsic(SILLocation loc,
43324296
CalleeTypeInfo calleeTypeInfo(
43334297
substFnType, AbstractionPattern(origFormalType).getFunctionResultType(),
43344298
substFormalType.getResult());
4335-
return emitApply(loc, mv, subs, args, calleeTypeInfo, options, ctx);
4299+
ResultPlanPtr resultPlan =
4300+
ResultPlanBuilder::computeResultPlan(*this, calleeTypeInfo, loc, ctx);
4301+
return emitApply(std::move(resultPlan), loc, mv, subs, args, calleeTypeInfo,
4302+
options, ctx);
43364303
}
43374304

43384305
static StringRef

lib/SILGen/SILGenBridging.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "Callee.h"
1414
#include "RValue.h"
15+
#include "ResultPlan.h"
1516
#include "SILGenFunction.h"
1617
#include "Scope.h"
1718
#include "swift/AST/DiagnosticsSIL.h"
@@ -168,11 +169,14 @@ emitBridgeObjectiveCToNative(SILGenFunction &SGF,
168169
CalleeTypeInfo calleeTypeInfo(
169170
witnessFnTy, AbstractionPattern(canGenericSig, formalResultTy),
170171
swiftValueType->getCanonicalType());
171-
return SGF
172-
.emitApply(loc, ManagedValue::forUnmanaged(witnessRef), subs,
173-
{objcValue, ManagedValue::forUnmanaged(metatypeValue)},
174-
calleeTypeInfo, ApplyOptions::None, SGFContext())
175-
.getAsSingleValue(SGF, loc);
172+
SGFContext context;
173+
ResultPlanPtr resultPlan =
174+
ResultPlanBuilder::computeResultPlan(SGF, calleeTypeInfo, loc, context);
175+
RValue result = SGF.emitApply(
176+
std::move(resultPlan), loc, ManagedValue::forUnmanaged(witnessRef), subs,
177+
{objcValue, ManagedValue::forUnmanaged(metatypeValue)}, calleeTypeInfo,
178+
ApplyOptions::None, context);
179+
return std::move(result).getAsSingleValue(SGF, loc);
176180
}
177181

178182
static ManagedValue emitBridgeBoolToObjCBool(SILGenFunction &SGF,
@@ -1338,9 +1342,13 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) {
13381342
fnType, AbstractionPattern(nativeFnTy->getGenericSignature(),
13391343
nativeFormalResultTy),
13401344
substResultTy, foreignError);
1341-
auto resultMV = emitApply(fd, ManagedValue::forUnmanaged(fn), subs, args,
1342-
calleeTypeInfo, ApplyOptions::None, SGFContext())
1343-
.getAsSingleValue(*this, fd);
1345+
SGFContext context;
1346+
ResultPlanPtr resultPlan = ResultPlanBuilder::computeResultPlan(
1347+
*this, calleeTypeInfo, fd, context);
1348+
auto resultMV =
1349+
emitApply(std::move(resultPlan), fd, ManagedValue::forUnmanaged(fn),
1350+
subs, args, calleeTypeInfo, ApplyOptions::None, context)
1351+
.getAsSingleValue(*this, fd);
13441352
// TODO: Emit directly into the indirect result.
13451353
if (indirectResult) {
13461354
resultMV.forwardInto(*this, fd, indirectResult);

lib/SILGen/SILGenExpr.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "Initialization.h"
1919
#include "LValue.h"
2020
#include "RValue.h"
21+
#include "ResultPlan.h"
2122
#include "SILGenDynamicCast.h"
2223
#include "Scope.h"
2324
#include "Varargs.h"
@@ -2085,8 +2086,11 @@ SILGenFunction::emitApplyOfDefaultArgGenerator(SILLocation loc,
20852086
auto substFnType = fnType->substGenericArgs(SGM.M,
20862087
defaultArgsOwner.getSubstitutions());
20872088
CalleeTypeInfo calleeTypeInfo(substFnType, origResultType, resultType);
2088-
return emitApply(loc, fnRef, defaultArgsOwner.getSubstitutions(), {},
2089-
calleeTypeInfo, ApplyOptions::None, C);
2089+
ResultPlanPtr resultPtr =
2090+
ResultPlanBuilder::computeResultPlan(*this, calleeTypeInfo, loc, C);
2091+
return emitApply(std::move(resultPtr), loc, fnRef,
2092+
defaultArgsOwner.getSubstitutions(), {}, calleeTypeInfo,
2093+
ApplyOptions::None, C);
20902094
}
20912095

20922096
RValue SILGenFunction::emitApplyOfStoredPropertyInitializer(
@@ -2105,7 +2109,10 @@ RValue SILGenFunction::emitApplyOfStoredPropertyInitializer(
21052109
auto substFnType = fnType->substGenericArgs(SGM.M, subs);
21062110

21072111
CalleeTypeInfo calleeTypeInfo(substFnType, origResultType, resultType);
2108-
return emitApply(loc, fnRef, subs, {}, calleeTypeInfo, ApplyOptions::None, C);
2112+
ResultPlanPtr resultPlan =
2113+
ResultPlanBuilder::computeResultPlan(*this, calleeTypeInfo, loc, C);
2114+
return emitApply(std::move(resultPlan), loc, fnRef, subs, {}, calleeTypeInfo,
2115+
ApplyOptions::None, C);
21092116
}
21102117

21112118
static void emitTupleShuffleExprInto(RValueEmitter &emitter,

lib/SILGen/SILGenFunction.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class ManagedValue;
3939
class RValue;
4040
class TemporaryInitialization;
4141
class CalleeTypeInfo;
42+
class ResultPlan;
43+
using ResultPlanPtr = std::unique_ptr<ResultPlan>;
4244

4345
/// Internal context information for the SILGenFunction visitor.
4446
///
@@ -1271,9 +1273,10 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
12711273
/// lowered appropriately for the abstraction level but that the
12721274
/// result does need to be turned back into something matching a
12731275
/// formal type.
1274-
RValue emitApply(SILLocation loc, ManagedValue fn, SubstitutionList subs,
1275-
ArrayRef<ManagedValue> args, CalleeTypeInfo &calleeTypeInfo,
1276-
ApplyOptions options, SGFContext evalContext);
1276+
RValue emitApply(ResultPlanPtr &&resultPlan, SILLocation loc, ManagedValue fn,
1277+
SubstitutionList subs, ArrayRef<ManagedValue> args,
1278+
CalleeTypeInfo &calleeTypeInfo, ApplyOptions options,
1279+
SGFContext evalContext);
12771280

12781281
RValue emitApplyOfDefaultArgGenerator(SILLocation loc,
12791282
ConcreteDeclRef defaultArgsOwner,

test/SILGen/errors.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ func dont_return<T>(_ argument: T) throws -> T {
5050
// CHECK: sil hidden @_TF6errors16all_together_nowFSbCS_3Cat : $@convention(thin) (Bool) -> @owned Cat {
5151
// CHECK: bb0(%0 : $Bool):
5252
// CHECK: [[DR_FN:%.*]] = function_ref @_TF6errors11dont_returnur{{.*}} :
53+
// CHECK-NEXT: [[RET_TEMP:%.*]] = alloc_stack $Cat
5354

5455
// Branch on the flag.
5556
// CHECK: cond_br {{%.*}}, [[FLAG_TRUE:bb[0-9]+]], [[FLAG_FALSE:bb[0-9]+]]
@@ -72,12 +73,11 @@ func dont_return<T>(_ argument: T) throws -> T {
7273
// CHECK: [[TERNARY_CONT]]([[T0:%.*]] : $Cat):
7374
// CHECK-NEXT: [[ARG_TEMP:%.*]] = alloc_stack $Cat
7475
// CHECK-NEXT: store [[T0]] to [init] [[ARG_TEMP]]
75-
// CHECK-NEXT: [[RET_TEMP:%.*]] = alloc_stack $Cat
7676
// CHECK-NEXT: try_apply [[DR_FN]]<Cat>([[RET_TEMP]], [[ARG_TEMP]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error Error), normal [[DR_NORMAL:bb[0-9]+]], error [[DR_ERROR:bb[0-9]+]]
7777
// CHECK: [[DR_NORMAL]]({{%.*}} : $()):
7878
// CHECK-NEXT: [[T0:%.*]] = load [take] [[RET_TEMP]] : $*Cat
79-
// CHECK-NEXT: dealloc_stack [[RET_TEMP]]
8079
// CHECK-NEXT: dealloc_stack [[ARG_TEMP]]
80+
// CHECK-NEXT: dealloc_stack [[RET_TEMP]]
8181
// CHECK-NEXT: br [[RETURN:bb[0-9]+]]([[T0]] : $Cat)
8282

8383
// Return block.
@@ -130,8 +130,10 @@ func dont_return<T>(_ argument: T) throws -> T {
130130

131131
// Landing pad.
132132
// CHECK: [[MAC_ERROR]]([[T0:%.*]] : $Error):
133+
// CHECK-NEXT: dealloc_stack [[RET_TEMP]]
133134
// CHECK-NEXT: br [[CATCH]]([[T0]] : $Error)
134135
// CHECK: [[DMAC_ERROR]]([[T0:%.*]] : $Error):
136+
// CHECK-NEXT: dealloc_stack [[RET_TEMP]]
135137
// CHECK-NEXT: br [[CATCH]]([[T0]] : $Error)
136138
// CHECK: [[DR_ERROR]]([[T0:%.*]] : $Error):
137139
// CHECK-NEXT: dealloc_stack

test/SILGen/functions.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,24 +247,24 @@ func calls(_ i:Int, j:Int, k:Int) {
247247

248248
// CHECK: [[G:%[0-9]+]] = load [copy] [[GADDR]]
249249
// CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[G]] : {{.*}}, #SomeGeneric.method!1
250-
// CHECK: [[TMPI:%.*]] = alloc_stack $Builtin.Int64
251250
// CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
251+
// CHECK: [[TMPI:%.*]] = alloc_stack $Builtin.Int64
252252
// CHECK: apply [[METHOD_GEN]]<{{.*}}>([[TMPR]], [[TMPI]], [[G]])
253253
// CHECK: destroy_value [[G]]
254254
g.method(i)
255255

256256
// CHECK: [[G:%[0-9]+]] = load [copy] [[GADDR]]
257257
// CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[G]] : {{.*}}, #SomeGeneric.generic!1
258-
// CHECK: [[TMPJ:%.*]] = alloc_stack $Builtin.Int64
259258
// CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
259+
// CHECK: [[TMPJ:%.*]] = alloc_stack $Builtin.Int64
260260
// CHECK: apply [[METHOD_GEN]]<{{.*}}>([[TMPR]], [[TMPJ]], [[G]])
261261
// CHECK: destroy_value [[G]]
262262
g.generic(j)
263263

264264
// CHECK: [[C:%[0-9]+]] = load [copy] [[CADDR]]
265265
// CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[C]] : {{.*}}, #SomeClass.generic!1
266-
// CHECK: [[TMPK:%.*]] = alloc_stack $Builtin.Int64
267266
// CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
267+
// CHECK: [[TMPK:%.*]] = alloc_stack $Builtin.Int64
268268
// CHECK: apply [[METHOD_GEN]]<{{.*}}>([[TMPR]], [[TMPK]], [[C]])
269269
// CHECK: destroy_value [[C]]
270270
c.generic(k)

0 commit comments

Comments
 (0)