Skip to content

Commit 49f1deb

Browse files
committed
[MandatoryInliner] Stack nest at OSSA lowering.
Now that in OSSA `partial_apply [on_stack]`s are represented as owned values rather than stack locations, it is possible for their destroys to violate stack discipline. A direct lowering of the instructions to non-OSSA would violate stack nesting. Previously, when inlining, it was assumed that non-coroutine callees maintained stack discipline. And, when inlining an OSSA function into a non-OSSA function, OSSA instructions were lowered directly. The result was that stack discipline could be violated. Here, when inlining a function in OSSA form into a function lowered out of OSSA form, stack nesting is fixed up.
1 parent a8c5d4e commit 49f1deb

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

lib/SILOptimizer/Mandatory/MandatoryInlining.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,14 @@ runOnFunctionRecursively(SILOptFunctionBuilder &FuncBuilder, SILFunction *F,
956956
// nextBB will point to the last inlined block
957957
SILBasicBlock *lastBB =
958958
Inliner.inlineFunction(CalleeFunction, InnerAI, FullArgs);
959+
960+
// When inlining an OSSA function into a non-OSSA function, ownership of
961+
// nonescaping closures is lowered. At that point, they are recognized
962+
// as stack users. Since they weren't recognized as such before, they
963+
// may not satisfy stack discipline. Fix that up now.
964+
invalidatedStackNesting |=
965+
(CalleeFunction->hasOwnership() && !F->hasOwnership());
966+
959967
if (SILPrintInliningCallerAfter) {
960968
printInliningDetailsCallerAfter("MandatoryInlining", F, CalleeFunction);
961969
}

test/SILOptimizer/mandatory_inlining_ossa_to_non_ossa.sil

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,3 +456,36 @@ bb0(%0 : $Builtin.NativeObject):
456456
%9999 = tuple()
457457
return %9999 : $()
458458
}
459+
460+
sil @paable : $@convention(thin) (Builtin.Int64) -> ()
461+
462+
sil [transparent] [ossa] @partial_apply_on_stack_nesting_violator : $@convention(thin) () -> () {
463+
%paable = function_ref @paable : $@convention(thin) (Builtin.Int64) -> ()
464+
%one = integer_literal $Builtin.Int64, 1
465+
%first = partial_apply [callee_guaranteed] [on_stack] %paable(%one) : $@convention(thin) (Builtin.Int64) -> ()
466+
%two = integer_literal $Builtin.Int64, 2
467+
%second = partial_apply [callee_guaranteed] [on_stack] %paable(%two) : $@convention(thin) (Builtin.Int64) -> ()
468+
// Note that the destroy_values do not occur in an order which coincides
469+
// with stack disciplined dealloc_stacks.
470+
destroy_value %first : $@noescape @callee_guaranteed () -> ()
471+
destroy_value %second : $@noescape @callee_guaranteed () -> ()
472+
%retval = tuple ()
473+
return %retval : $()
474+
}
475+
476+
// Verify that when inlining partial_apply_on_stack_nesting_violator, the stack
477+
// nesting of the on_stack closures is fixed.
478+
// CHECK-LABEL: sil @test_inline_stack_violating_ossa_func : {{.*}} {
479+
// CHECK: [[PAABLE:%[^,]+]] = function_ref @paable
480+
// CHECK: [[FIRST:%[^,]+]] = partial_apply [callee_guaranteed] [on_stack] [[PAABLE]]
481+
// CHECK: [[SECOND:%[^,]+]] = partial_apply [callee_guaranteed] [on_stack] [[PAABLE]]
482+
// CHECK: dealloc_stack [[SECOND]]
483+
// CHECK: dealloc_stack [[FIRST]]
484+
// CHECK-LABEL: } // end sil function 'test_inline_stack_violating_ossa_func'
485+
sil @test_inline_stack_violating_ossa_func : $@convention(thin) () -> () {
486+
%callee = function_ref @partial_apply_on_stack_nesting_violator : $@convention(thin) () -> ()
487+
apply %callee() : $@convention(thin) () -> ()
488+
%retval = tuple ()
489+
return %retval : $()
490+
}
491+

0 commit comments

Comments
 (0)