@@ -130,6 +130,39 @@ struct LoweredParamGenerator {
130
130
}
131
131
};
132
132
133
+ struct WritebackReabstractedInoutCleanup final : Cleanup {
134
+ SILValue OrigAddress, SubstAddress;
135
+ AbstractionPattern OrigTy;
136
+ CanType SubstTy;
137
+ WritebackReabstractedInoutCleanup (SILValue origAddress, SILValue substAddress,
138
+ AbstractionPattern origTy,
139
+ CanType substTy)
140
+ : OrigAddress(origAddress), SubstAddress(substAddress),
141
+ OrigTy (origTy), SubstTy(substTy)
142
+ {}
143
+
144
+ void emit (SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind)
145
+ override {
146
+ Scope s (SGF.Cleanups , l);
147
+ // Load the final local value coming in.
148
+ auto mv = SGF.emitLoad (l, SubstAddress,
149
+ SGF.getTypeLowering (SubstAddress->getType ()),
150
+ SGFContext (), IsTake);
151
+ // Reabstract the value back to the original representation.
152
+ mv = SGF.emitSubstToOrigValue (l, mv.ensurePlusOne (SGF, l),
153
+ OrigTy, SubstTy);
154
+ // Write it back to the original inout parameter.
155
+ SGF.B .createStore (l, mv.forward (SGF), OrigAddress,
156
+ StoreOwnershipQualifier::Init);
157
+ }
158
+
159
+ void dump (SILGenFunction&) const override {
160
+ llvm::errs () << " WritebackReabstractedInoutCleanup\n " ;
161
+ OrigAddress->print (llvm::errs ());
162
+ SubstAddress->print (llvm::errs ());
163
+ }
164
+ };
165
+
133
166
class EmitBBArguments : public CanTypeVisitor <EmitBBArguments,
134
167
/* RetTy*/ ManagedValue,
135
168
/* ArgTys...*/ AbstractionPattern,
@@ -255,6 +288,23 @@ class EmitBBArguments : public CanTypeVisitor<EmitBBArguments,
255
288
if (mv.getType ().isMoveOnly () && !mv.getType ().isMoveOnlyWrapped ())
256
289
mv = SGF.B .createMarkMustCheckInst (
257
290
loc, mv, MarkMustCheckInst::CheckKind::ConsumableAndAssignable);
291
+
292
+ // If the value needs to be reabstracted, set up a shadow copy with
293
+ // writeback here.
294
+ if (argType.getASTType () != mv.getType ().getASTType ()) {
295
+ // Load the value coming in.
296
+ auto origBuf = mv.getValue ();
297
+ mv = SGF.emitLoad (loc, origBuf, SGF.getTypeLowering (mv.getType ()), SGFContext (), IsTake);
298
+ // Reabstract the value if necessary.
299
+ mv = SGF.emitOrigToSubstValue (loc, mv.ensurePlusOne (SGF, loc), orig, t);
300
+ // Store the value to a local buffer.
301
+ auto substBuf = SGF.emitTemporaryAllocation (loc, argType);
302
+ SGF.B .createStore (loc, mv.forward (SGF), substBuf, StoreOwnershipQualifier::Init);
303
+ // Introduce a writeback to put the final value back in the inout.
304
+ SGF.Cleanups .pushCleanup <WritebackReabstractedInoutCleanup>(origBuf, substBuf, orig, t);
305
+ mv = ManagedValue::forLValue (substBuf);
306
+ }
307
+
258
308
return mv;
259
309
}
260
310
0 commit comments