17
17
#include " LValue.h"
18
18
#include " RValue.h"
19
19
#include " SILGenFunction.h"
20
+ #include " swift/AST/GenericEnvironment.h"
20
21
21
22
using namespace swift ;
22
23
using namespace Lowering ;
@@ -29,7 +30,7 @@ namespace {
29
30
30
31
// / A result plan for evaluating an indirect result into the address
31
32
// / associated with an initialization.
32
- class InPlaceInitializationResultPlan : public ResultPlan {
33
+ class InPlaceInitializationResultPlan final : public ResultPlan {
33
34
Initialization *init;
34
35
35
36
public:
@@ -47,10 +48,150 @@ class InPlaceInitializationResultPlan : public ResultPlan {
47
48
}
48
49
};
49
50
51
+ // / A cleanup that handles the delayed emission of an indirect buffer for opened
52
+ // / Self arguments.
53
+ class IndirectOpenedSelfCleanup final : public Cleanup {
54
+ SILValue box;
55
+ public:
56
+ IndirectOpenedSelfCleanup ()
57
+ : box()
58
+ {}
59
+
60
+ void setBox (SILValue b) {
61
+ assert (!box && " buffer already set?!" );
62
+ box = b;
63
+ }
64
+
65
+ void emit (SILGenFunction &SGF, CleanupLocation loc) override {
66
+ assert (box && " buffer never emitted before activating cleanup?!" );
67
+ SGF.B .createDeallocBox (loc, box);
68
+ }
69
+
70
+ void dump (SILGenFunction &SGF) const override {
71
+ llvm::errs () << " IndirectOpenedSelfCleanup\n " ;
72
+ if (box)
73
+ box->dump ();
74
+ }
75
+ };
76
+
77
+ // / Map a type expressed in terms of opened archetypes into a context-free
78
+ // / dependent type, returning the type, a generic signature with parameters
79
+ // / corresponding to each opened type,
80
+ static std::pair<CanType, CanGenericSignature>
81
+ mapTypeOutOfOpenedExistentialContext (CanType t,
82
+ SmallVectorImpl<Substitution> &mappedSubs) {
83
+ SmallVector<ArchetypeType *, 4 > openedTypes;
84
+ t->getOpenedExistentials (openedTypes);
85
+
86
+ SmallVector<GenericTypeParamType *, 4 > params;
87
+ for (unsigned i : indices (openedTypes)) {
88
+ params.push_back (GenericTypeParamType::get (0 , i, t->getASTContext ()));
89
+ mappedSubs.push_back (Substitution (openedTypes[i], {}));
90
+ }
91
+
92
+ auto mappedSig = GenericSignature::get (params, {});
93
+
94
+ auto mappedTy = t.subst (
95
+ [&](SubstitutableType *t) -> Type {
96
+ auto index = std::find (openedTypes.begin (), openedTypes.end (), t)
97
+ - openedTypes.begin ();
98
+ assert (index != openedTypes.end () - openedTypes.begin ());
99
+ return params[index];
100
+ },
101
+ MakeAbstractConformanceForGenericType ());
102
+
103
+ return std::make_pair (mappedTy->getCanonicalType (mappedSig),
104
+ mappedSig->getCanonicalSignature ());
105
+ }
106
+
107
+ // / A result plan for an indirectly-returned opened existential value.
108
+ // /
109
+ // / This defers allocating the temporary for the result to a later point so that
110
+ // / it happens after the arguments are evaluated.
111
+ class IndirectOpenedSelfResultPlan final : public ResultPlan {
112
+ AbstractionPattern origType;
113
+ CanType substType;
114
+ CleanupHandle handle = CleanupHandle::invalid();
115
+ mutable SILValue resultBox, resultBuf;
116
+
117
+ public:
118
+ IndirectOpenedSelfResultPlan (SILGenFunction &SGF,
119
+ AbstractionPattern origType,
120
+ CanType substType)
121
+ : origType(origType), substType(substType)
122
+ {
123
+ // Create a cleanup to deallocate the stack buffer at the proper scope.
124
+ // We won't emit the buffer till later, after arguments have been opened,
125
+ // though.
126
+ SGF.Cleanups .pushCleanupInState <IndirectOpenedSelfCleanup>(
127
+ CleanupState::Dormant);
128
+ handle = SGF.Cleanups .getCleanupsDepth ();
129
+ }
130
+
131
+ void
132
+ gatherIndirectResultAddrs (SILGenFunction &SGF, SILLocation loc,
133
+ SmallVectorImpl<SILValue> &outList) const override {
134
+ assert (!resultBox && " already created temporary?!" );
135
+
136
+ // We allocate the buffer as a box because the scope nesting won't clean
137
+ // this up with good stack discipline relative to any stack allocations that
138
+ // occur during argument emission. Escape analysis during mandatory passes
139
+ // ought to clean this up.
140
+
141
+ auto resultTy = SGF.getLoweredType (origType, substType).getSwiftRValueType ();
142
+ CanType layoutTy;
143
+ CanGenericSignature layoutSig;
144
+ SmallVector<Substitution, 4 > layoutSubs;
145
+ std::tie (layoutTy, layoutSig)
146
+ = mapTypeOutOfOpenedExistentialContext (resultTy, layoutSubs);
147
+
148
+ auto boxLayout = SILLayout::get (SGF.getASTContext (),
149
+ layoutSig->getCanonicalSignature (),
150
+ SILField (layoutTy->getCanonicalType (layoutSig), true ));
151
+
152
+ resultBox = SGF.B .createAllocBox (loc,
153
+ SILBoxType::get (SGF.getASTContext (),
154
+ boxLayout,
155
+ layoutSubs));
156
+
157
+ // Complete the cleanup to deallocate this buffer later, after we're
158
+ // finished with the argument.
159
+ static_cast <IndirectOpenedSelfCleanup&>(SGF.Cleanups .getCleanup (handle))
160
+ .setBox (resultBox);
161
+ SGF.Cleanups .setCleanupState (handle, CleanupState::Active);
162
+
163
+ resultBuf = SGF.B .createProjectBox (loc, resultBox, 0 );
164
+ outList.emplace_back (resultBuf);
165
+ }
166
+
167
+ RValue finish (SILGenFunction &SGF, SILLocation loc, CanType substType,
168
+ ArrayRef<ManagedValue> &directResults) override {
169
+ assert (resultBox && " never emitted temporary?!" );
170
+
171
+ // Lower the unabstracted result type.
172
+ auto &substTL = SGF.getTypeLowering (substType);
173
+
174
+ ManagedValue value;
175
+ // If the value isn't address-only, go ahead and load.
176
+ if (!substTL.isAddressOnly ()) {
177
+ auto load = substTL.emitLoad (SGF.B , loc, resultBuf,
178
+ LoadOwnershipQualifier::Take);
179
+ value = SGF.emitManagedRValueWithCleanup (load);
180
+ } else {
181
+ value = SGF.emitManagedRValueWithCleanup (resultBuf);
182
+ }
183
+
184
+ // A Self return should never be further abstracted. It's also never emitted
185
+ // into context; we disable that optimization because Self may not even
186
+ // be available to pre-allocate a stack buffer before we prepare a call.
187
+ return RValue (SGF, loc, substType, value);
188
+ }
189
+ };
190
+
50
191
// / A result plan for working with a single value and potentially
51
192
// / reabstracting it. The value can actually be a tuple if the
52
193
// / abstraction is opaque.
53
- class ScalarResultPlan : public ResultPlan {
194
+ class ScalarResultPlan final : public ResultPlan {
54
195
std::unique_ptr<TemporaryInitialization> temporary;
55
196
AbstractionPattern origType;
56
197
Initialization *init;
@@ -150,7 +291,7 @@ class ScalarResultPlan : public ResultPlan {
150
291
151
292
// / A result plan which calls copyOrInitValueInto on an Initialization
152
293
// / using a temporary buffer initialized by a sub-plan.
153
- class InitValueFromTemporaryResultPlan : public ResultPlan {
294
+ class InitValueFromTemporaryResultPlan final : public ResultPlan {
154
295
Initialization *init;
155
296
ResultPlanPtr subPlan;
156
297
std::unique_ptr<TemporaryInitialization> temporary;
@@ -184,7 +325,7 @@ class InitValueFromTemporaryResultPlan : public ResultPlan {
184
325
185
326
// / A result plan which calls copyOrInitValueInto using the result of
186
327
// / a sub-plan.
187
- class InitValueFromRValueResultPlan : public ResultPlan {
328
+ class InitValueFromRValueResultPlan final : public ResultPlan {
188
329
Initialization *init;
189
330
ResultPlanPtr subPlan;
190
331
@@ -212,7 +353,7 @@ class InitValueFromRValueResultPlan : public ResultPlan {
212
353
213
354
// / A result plan which produces a larger RValue from a bunch of
214
355
// / components.
215
- class TupleRValueResultPlan : public ResultPlan {
356
+ class TupleRValueResultPlan final : public ResultPlan {
216
357
SmallVector<ResultPlanPtr, 4 > eltPlans;
217
358
218
359
public:
@@ -254,7 +395,7 @@ class TupleRValueResultPlan : public ResultPlan {
254
395
255
396
// / A result plan which evaluates into the sub-components
256
397
// / of a splittable tuple initialization.
257
- class TupleInitializationResultPlan : public ResultPlan {
398
+ class TupleInitializationResultPlan final : public ResultPlan {
258
399
Initialization *tupleInit;
259
400
SmallVector<InitializationPtr, 4 > eltInitsBuffer;
260
401
MutableArrayRef<InitializationPtr> eltInits;
@@ -305,7 +446,7 @@ class TupleInitializationResultPlan : public ResultPlan {
305
446
}
306
447
};
307
448
308
- class ForeignErrorInitializationPlan : public ResultPlan {
449
+ class ForeignErrorInitializationPlan final : public ResultPlan {
309
450
SILLocation loc;
310
451
LValue lvalue;
311
452
ResultPlanPtr subPlan;
@@ -466,6 +607,16 @@ ResultPlanPtr ResultPlanBuilder::build(Initialization *init,
466
607
// - store it to the destination
467
608
// We could break this down into different ResultPlan implementations,
468
609
// but it's easier not to.
610
+
611
+ // If the result type involves an indirectly-returned opened existential,
612
+ // then we need to evaluate the arguments first in order to have access to
613
+ // the opened Self type. A special result plan defers allocating the stack
614
+ // slot to the point the call is emitted.
615
+ if (result.getType ()->hasOpenedExistential ()
616
+ && SGF.silConv .isSILIndirect (result)) {
617
+ return ResultPlanPtr (
618
+ new IndirectOpenedSelfResultPlan (SGF, origType, substType));
619
+ }
469
620
470
621
// Create a temporary if the result is indirect.
471
622
std::unique_ptr<TemporaryInitialization> temporary;
0 commit comments