@@ -83,19 +83,30 @@ class DeleteInstructionsHandler : public DeleteNotificationHandler {
83
83
// / applications: namely, that an apply of a thick function consumes the callee
84
84
// / and that the function implementing the closure consumes its capture
85
85
// / arguments.
86
- static void fixupReferenceCounts (SILBasicBlock::iterator I,
87
- SILValue CalleeValue,
88
- SmallVectorImpl<SILValue> &CaptureArgs) {
86
+ static void fixupReferenceCounts (
87
+ SILBasicBlock::iterator I, SILValue CalleeValue,
88
+ SmallVectorImpl<std::pair<SILValue, ParameterConvention>> &CaptureArgs,
89
+ bool isCalleeGuaranteed) {
89
90
// Add a copy of each non-address type capture argument to lifetime extend the
90
91
// captured argument over the inlined function. This deals with the
91
92
// possibility of the closure being destroyed by an earlier application and
92
93
// thus cause the captured argument to be destroyed.
93
- for (auto &CaptureArg : CaptureArgs)
94
- if (!CaptureArg->getType ().isAddress ())
95
- createIncrementBefore (CaptureArg, &*I);
94
+ for (auto &CaptureArg : CaptureArgs) {
95
+ if (!CaptureArg.first ->getType ().isAddress () &&
96
+ CaptureArg.second != ParameterConvention::Direct_Guaranteed &&
97
+ CaptureArg.second != ParameterConvention::Direct_Unowned) {
98
+ createIncrementBefore (CaptureArg.first , &*I);
99
+ } else {
100
+ // FIXME: What about indirectly owned parameters? The invocation of the
101
+ // closure would perform an indirect copy which we should mimick here.
102
+ assert (CaptureArg.second != ParameterConvention::Indirect_In &&
103
+ " Missing indirect copy" );
104
+ }
105
+ }
96
106
97
107
// Destroy the callee as the apply would have done.
98
- createDecrementBefore (CalleeValue, &*I);
108
+ if (!isCalleeGuaranteed)
109
+ createDecrementBefore (CalleeValue, &*I);
99
110
}
100
111
101
112
static SILValue cleanupLoadedCalleeValue (SILValue CalleeValue, LoadInst *LI) {
@@ -159,9 +170,9 @@ static SILValue cleanupLoadedCalleeValue(SILValue CalleeValue, LoadInst *LI) {
159
170
160
171
// / \brief Removes instructions that create the callee value if they are no
161
172
// / longer necessary after inlining.
162
- static void
163
- cleanupCalleeValue (SILValue CalleeValue, ArrayRef< SILValue> CaptureArgs ,
164
- ArrayRef<SILValue> FullArgs) {
173
+ static void cleanupCalleeValue (
174
+ SILValue CalleeValue ,
175
+ ArrayRef<SILValue> FullArgs) {
165
176
SmallVector<SILInstruction*, 16 > InstsToDelete;
166
177
for (SILValue V : FullArgs) {
167
178
if (V != CalleeValue)
@@ -217,6 +228,22 @@ cleanupCalleeValue(SILValue CalleeValue, ArrayRef<SILValue> CaptureArgs,
217
228
}
218
229
}
219
230
231
+ static void collectPartiallyAppliedArguments (
232
+ PartialApplyInst *PAI,
233
+ SmallVectorImpl<std::pair<SILValue, ParameterConvention>> &CapturedArgs,
234
+ SmallVectorImpl<SILValue> &FullArgs) {
235
+ ApplySite Site (PAI);
236
+ SILFunctionConventions CalleeConv (Site.getSubstCalleeType (),
237
+ PAI->getModule ());
238
+ for (auto &Arg : PAI->getArgumentOperands ()) {
239
+ unsigned CalleeArgumentIndex = Site.getCalleeArgIndex (Arg);
240
+ assert (CalleeArgumentIndex >= CalleeConv.getSILArgIndexOfFirstParam ());
241
+ auto ParamInfo = CalleeConv.getParamInfoForSILArg (CalleeArgumentIndex);
242
+ CapturedArgs.push_back (std::make_pair (Arg.get (), ParamInfo.getConvention ()));
243
+ FullArgs.push_back (Arg.get ());
244
+ }
245
+ }
246
+
220
247
// / \brief Returns the callee SILFunction called at a call site, in the case
221
248
// / that the call is transparent (as in, both that the call is marked
222
249
// / with the transparent flag and that callee function is actually transparently
@@ -225,12 +252,11 @@ cleanupCalleeValue(SILValue CalleeValue, ArrayRef<SILValue> CaptureArgs,
225
252
// /
226
253
// / In the case that a non-null value is returned, FullArgs contains effective
227
254
// / argument operands for the callee function.
228
- static SILFunction *getCalleeFunction (SILFunction *F, FullApplySite AI,
229
- bool &IsThick,
230
- SmallVectorImpl<SILValue> &CaptureArgs,
231
- SmallVectorImpl<SILValue> &FullArgs,
232
- PartialApplyInst *&PartialApply,
233
- SILModule::LinkingMode Mode) {
255
+ static SILFunction *getCalleeFunction (
256
+ SILFunction *F, FullApplySite AI, bool &IsThick,
257
+ SmallVectorImpl<std::pair<SILValue, ParameterConvention>> &CaptureArgs,
258
+ SmallVectorImpl<SILValue> &FullArgs, PartialApplyInst *&PartialApply,
259
+ SILModule::LinkingMode Mode) {
234
260
IsThick = false ;
235
261
PartialApply = nullptr ;
236
262
CaptureArgs.clear ();
@@ -319,10 +345,9 @@ static SILFunction *getCalleeFunction(SILFunction *F, FullApplySite AI,
319
345
// one "thin to thick function" instructions, since those are the patterns
320
346
// generated when using auto closures.
321
347
if (auto *PAI = dyn_cast<PartialApplyInst>(CalleeValue)) {
322
- for (const auto &Arg : PAI->getArguments ()) {
323
- CaptureArgs.push_back (Arg);
324
- FullArgs.push_back (Arg);
325
- }
348
+
349
+ // Collect the applied arguments and their convention.
350
+ collectPartiallyAppliedArguments (PAI, CaptureArgs, FullArgs);
326
351
327
352
CalleeValue = PAI->getCallee ();
328
353
IsThick = true ;
@@ -440,7 +465,7 @@ runOnFunctionRecursively(SILFunction *F, FullApplySite AI,
440
465
// during this call and recursive subcalls).
441
466
CurrentInliningSet = SetFactory.add (CurrentInliningSet, F);
442
467
443
- SmallVector<SILValue, 16 > CaptureArgs;
468
+ SmallVector<std::pair< SILValue, ParameterConvention> , 16 > CaptureArgs;
444
469
SmallVector<SILValue, 32 > FullArgs;
445
470
446
471
for (auto BI = F->begin (), BE = F->end (); BI != BE; ++BI) {
@@ -465,6 +490,7 @@ runOnFunctionRecursively(SILFunction *F, FullApplySite AI,
465
490
PartialApplyInst *PAI;
466
491
SILFunction *CalleeFunction = getCalleeFunction (
467
492
F, InnerAI, IsThick, CaptureArgs, FullArgs, PAI, Mode);
493
+
468
494
if (!CalleeFunction)
469
495
continue ;
470
496
@@ -529,8 +555,12 @@ runOnFunctionRecursively(SILFunction *F, FullApplySite AI,
529
555
530
556
// If we intend to inline a thick function, then we need to balance the
531
557
// reference counts for correctness.
532
- if (IsThick)
533
- fixupReferenceCounts (II, CalleeValue, CaptureArgs);
558
+ if (IsThick) {
559
+ bool IsCalleeGuaranteed =
560
+ PAI &&
561
+ PAI->getType ().castTo <SILFunctionType>()->isCalleeGuaranteed ();
562
+ fixupReferenceCounts (II, CalleeValue, CaptureArgs, IsCalleeGuaranteed);
563
+ }
534
564
535
565
// Decrement our iterator (carefully, to avoid going off the front) so it
536
566
// is valid after inlining is done. Inlining deletes the apply, and can
@@ -551,7 +581,7 @@ runOnFunctionRecursively(SILFunction *F, FullApplySite AI,
551
581
552
582
// Now that the IR is correct, see if we can remove dead callee
553
583
// computations (e.g. dead partial_apply closures).
554
- cleanupCalleeValue (CalleeValue, CaptureArgs, FullArgs);
584
+ cleanupCalleeValue (CalleeValue, FullArgs);
555
585
556
586
// Reposition iterators possibly invalidated by mutation.
557
587
BI = SILFunction::iterator (ApplyBlock);
0 commit comments