Files
swift-mirror/test/Concurrency/isolation_macro_sil.swift
Michael Gottesman 390afe3e7d [concurrency] Implement bit masking for TBI when available or in tagged pointer bits otherwise.
Specifically, when TBI is available we use the bottom two bits of the top nibble
(bits 60,61). On platforms without TBI, we use the bottom two tagged pointer
bits (bits 0, 1).

rdar://156525771
2025-10-16 10:52:05 -07:00

148 lines
6.4 KiB
Swift

// RUN: %target-swift-frontend -parse-as-library -emit-sil %s -module-name test | %FileCheck %s
// REQUIRES: concurrency
nonisolated(nonsending) func nonisolatedNonsending() async {
let iso = #isolation
take(iso: iso)
}
func take(iso: (any Actor)?) {}
func takeDefaulted(iso: isolated (any Actor)? = #isolation) {}
// CHECK-LABEL: // nonisolatedNonsending()
// CHECK-NEXT: // Isolation: caller_isolation_inheriting
// CHECK-NEXT: sil hidden @$s4test21nonisolatedNonsendingyyYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> () {
// CHECK: bb0([[IMPLICIT_ACTOR:%.*]] : $Builtin.ImplicitActor):
// CHECK: [[ACTOR:%.*]] = implicitactor_to_opaqueisolation_cast [[IMPLICIT_ACTOR]]
// CHECK: retain_value [[ACTOR]]
// CHECK: debug_value [[ACTOR]], let, name "iso"
// CHECK: [[FUNC:%.*]] = function_ref @$s4test4take3isoyScA_pSg_tF : $@convention(thin) (@guaranteed Optional<any Actor>) -> ()
// CHECK: apply [[FUNC]]([[ACTOR]]) : $@convention(thin) (@guaranteed Optional<any Actor>) -> ()
// CHECK: release_value [[ACTOR]]
// CHECK: } // end sil function '$s4test21nonisolatedNonsendingyyYaF'
// Check that we emit #isolation correctly in closures.
// CHECK-LABEL: // closure #1 in containsClosure()
// CHECK-NEXT: // Isolation: caller_isolation_inheriting
// CHECK-LABEL: sil private @$s4test15containsClosureyyFyyYaYCcfU_ : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> () {
// CHECK: bb0(%0 : $Builtin.ImplicitActor):
// CHECK: [[ACTOR:%.*]] = implicitactor_to_opaqueisolation_cast %0
// CHECK-NEXT: // function_ref take(iso:)
// CHECK-NEXT: [[FN:%.*]] = function_ref @
// CHECK-NEXT: apply [[FN]]([[ACTOR]])
// CHECK: } // end sil function '$s4test15containsClosureyyFyyYaYCcfU_'
func containsClosure() {
let closure: nonisolated(nonsending) () async -> Void = {
take(iso: #isolation)
}
}
// Check that we capture variables as necessary to emit #isolation
// correctly in defer bodies.
func deferWithIsolatedParam(_ iso: isolated (any Actor)) {
defer {
take(iso: #isolation)
}
do {}
}
// CHECK-LABEL: sil hidden @$s4test22deferWithIsolatedParamyyScA_pYiF :
// CHECK: bb0(%0 : $any Actor)
// CHECK: [[DEFER:%.*]] = function_ref @$s4test22deferWithIsolatedParamyyScA_pYiF6$deferL_yyF :
// CHECK-NEXT: apply [[DEFER]](%0)
// CHECK: } // end sil function '$s4test22deferWithIsolatedParamyyScA_pYiF'
// CHECK-LABEL: sil private @$s4test22deferWithIsolatedParamyyScA_pYiF6$deferL_yyF :
// CHECK: bb0(%0 : @closureCapture $any Actor):
// CHECK: [[T0:%.*]] = enum $Optional<any Actor>, #Optional.some!enumelt, %0
// CHECK: [[FN:%.*]] = function_ref @$s4test4take3isoyScA_pSg_tF :
// CHECK-NEXT: apply [[FN]]([[T0]])
// CHECK: } // end sil function '$s4test22deferWithIsolatedParamyyScA_pYiF6$deferL_yyF'
// Check that that happens even with uses in caller-side default
// arguments, which capture analysis was not previously walking into.
func deferWithIsolatedParam_defaultedUse(_ iso: isolated (any Actor)) {
defer {
takeDefaulted()
}
do {}
}
// CHECK-LABEL: sil hidden @$s4test35deferWithIsolatedParam_defaultedUseyyScA_pYiF :
// CHECK: bb0(%0 : $any Actor):
// CHECK: [[DEFER:%.*]] = function_ref @$s4test35deferWithIsolatedParam_defaultedUseyyScA_pYiF6$deferL_yyF :
// CHECK-NEXT: apply [[DEFER]](%0)
// CHECK: } // end sil function '$s4test35deferWithIsolatedParam_defaultedUseyyScA_pYiF'
// CHECK-LABEL: sil private @$s4test35deferWithIsolatedParam_defaultedUseyyScA_pYiF6$deferL_yyF :
// CHECK: bb0(%0 : @closureCapture $any Actor):
// CHECK: [[T0:%.*]] = enum $Optional<any Actor>, #Optional.some!enumelt, %0
// CHECK: [[FN:%.*]] = function_ref @$s4test13takeDefaulted3isoyScA_pSgYi_tF :
// CHECK-NEXT: apply [[FN]]([[T0]])
// CHECK: } // end sil function '$s4test35deferWithIsolatedParam_defaultedUseyyScA_pYiF6$deferL_yyF'
// TODO: we can't currently call nonisolated(nonsending) functions in
// defer bodies because they have to be async, but that should be
// tested here as well.
// Check that we emit #isolation correctly in defer bodies.
nonisolated(nonsending)
func hasDefer() async {
defer {
take(iso: #isolation)
}
do {}
}
// CHECK-LABEL: sil hidden @$s4test8hasDeferyyYaF :
// CHECK: bb0(%0 : $Builtin.ImplicitActor):
// CHECK: // function_ref $defer
// CHECK-NEXT: [[DEFER:%.*]] = function_ref
// CHECK-NEXT: apply [[DEFER]](%0)
// CHECK: } // end sil function '$s4test8hasDeferyyYaF'
// CHECK-LABEL: // $defer #1 () in hasDefer()
// CHECK-NEXT: // Isolation: caller_isolation_inheriting
// CHECK: bb0(%0 : $Builtin.ImplicitActor):
// CHECK-NEXT: [[ACTOR:%.*]] = implicitactor_to_opaqueisolation_cast %0
// CHECK-NEXT: // function_ref take(iso:)
// CHECK-NEXT: [[FN:%.*]] = function_ref @
// CHECK-NEXT: apply [[FN]]([[ACTOR]])
// Check that we emit #isolation correctly in nested defer bodies.
nonisolated(nonsending)
func hasNestedDefer() async {
defer {
defer {
take(iso: #isolation)
}
do {}
}
do {}
}
// CHECK-LABEL: sil hidden @$s4test14hasNestedDeferyyYaF :
// CHECK: bb0(%0 : $Builtin.ImplicitActor):
// CHECK: // function_ref $defer #1 () in hasNestedDefer()
// CHECK-NEXT: [[DEFER:%.*]] = function_ref
// CHECK-NEXT: apply [[DEFER]](%0)
// CHECK: } // end sil function '$s4test14hasNestedDeferyyYaF'
// CHECK-LABEL: // $defer #1 () in hasNestedDefer()
// CHECK-NEXT: // Isolation: caller_isolation_inheriting
// CHECK: bb0(%0 : $Builtin.ImplicitActor):
// CHECK: // function_ref $defer #1 () in $defer #1 () in hasNestedDefer()
// CHECK-NEXT: [[DEFER:%.*]] = function_ref
// CHECK-NEXT: apply [[DEFER]](%0)
// CHECK: } // end sil function '$s4test14hasNestedDeferyyYaF6$deferL_yyF'
// CHECK-LABEL: // $defer #1 () in $defer #1 () in hasNestedDefer()
// CHECK-NEXT: // Isolation: caller_isolation_inheriting
// CHECK-NEXT: sil private @$s4test14hasNestedDeferyyYaF6$deferL_yyFACL_yyF : $@convention(thin) (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> () {
// CHECK: bb0(%0 : $Builtin.ImplicitActor):
// CHECK-NEXT: [[ACTOR:%.*]] = implicitactor_to_opaqueisolation_cast %0
// CHECK-NEXT: // function_ref take(iso:)
// CHECK-NEXT: [[FN:%.*]] = function_ref @
// CHECK-NEXT: apply [[FN]]([[ACTOR]])
// CHECK: } // end sil function '$s4test14hasNestedDeferyyYaF6$deferL_yyFACL_yyF'