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