@@ -4126,6 +4126,91 @@ pipeline.
4126
4126
4127
4127
The operand is a guaranteed operand, i.e. not consumed.
4128
4128
4129
+ merge_isolation_region
4130
+ ``````````````````````
4131
+
4132
+ ::
4133
+
4134
+ sil-instruction :: 'merge_isolation_region' (sil-operand ',')+ sil-operand
4135
+
4136
+ %2 = merge_isolation_region %first : $*T, %second : $U
4137
+ %2 = merge_isolation_region %first : $*T, %second : $U, %third : $H
4138
+
4139
+ Instruction that is only valid in Ownership SSA.
4140
+
4141
+ This instruction informs region isolation that all of the operands should be
4142
+ considered to be artificially apart of the same region. It is intended to be
4143
+ used to express region dependency when due to unsafe codegen we have to traffic
4144
+ a non-Sendable value through computations with Sendable values (causing us to
4145
+ not track the non-Sendable value) but have to later express that a non-Sendable
4146
+ result of using the Sendable value needs to be in the same region as the
4147
+ original non-Sendable value. As an example of where this comes up, consider the
4148
+ following code::
4149
+
4150
+ // objc code
4151
+ @interface CallbackData : NSObject
4152
+ @end
4153
+
4154
+ @interface Klass : NSObject
4155
+
4156
+ - (void)loadDataWithCompletionHandler:(void (^)(CallbackData * _Nullable, NSError * _Nullable))completionHandler;
4157
+
4158
+ @end
4159
+
4160
+ // swift code
4161
+ extension Klass {
4162
+ func loadCallbackData() async throws -> sending CallbackData {
4163
+ try await loadData()
4164
+ }
4165
+ }
4166
+
4167
+ This lowers to::
4168
+
4169
+ %5 = alloc_stack $CallbackData // users: %26, %25, %31, %16, %7
4170
+ %6 = objc_method %0 : $Klass, #Klass.loadData!foreign : (Klass) -> () async throws -> CallbackData, $@convention(objc_method) (Optional<@convention(block) (Optional<CallbackData>, Optional<NSError>) -> ()>, Klass) -> () // user: %20
4171
+ %7 = get_async_continuation_addr [throws] CallbackData, %5 : $*CallbackData // users: %23, %8
4172
+ %8 = struct $UnsafeContinuation<CallbackData, any Error> (%7 : $Builtin.RawUnsafeContinuation) // user: %14
4173
+ %9 = alloc_stack $@block_storage Any // users: %22, %16, %10
4174
+ %10 = project_block_storage %9 : $*@block_storage Any // user: %11
4175
+ %11 = init_existential_addr %10 : $*Any, $CheckedContinuation<CallbackData, any Error> // user: %15
4176
+ // function_ref _createCheckedThrowingContinuation<A>(_:)
4177
+ %12 = function_ref @$ss34_createCheckedThrowingContinuationyScCyxs5Error_pGSccyxsAB_pGnlF : $@convention(thin) <τ_0_0> (UnsafeContinuation<τ_0_0, any Error>) -> @out CheckedContinuation<τ_0_0, any Error> // user: %14
4178
+ %13 = alloc_stack $CheckedContinuation<CallbackData, any Error> // users: %21, %15, %14
4179
+ %14 = apply %12<CallbackData>(%13, %8) : $@convention(thin) <τ_0_0> (UnsafeContinuation<τ_0_0, any Error>) -> @out CheckedContinuation<τ_0_0, any Error>
4180
+ copy_addr [take] %13 to [init] %11 : $*CheckedContinuation<CallbackData, any Error> // id: %15
4181
+ merge_isolation_region %9 : $*@block_storage Any, %5 : $*CallbackData // id: %16
4182
+ // function_ref @objc completion handler block implementation for @escaping @callee_unowned @convention(block) (@unowned CallbackData?, @unowned NSError?) -> () with result type CallbackData
4183
+ %17 = function_ref @$sSo12CallbackDataCSgSo7NSErrorCSgIeyByy_ABTz_ : $@convention(c) (@inout_aliasable @block_storage Any, Optional<CallbackData>, Optional<NSError>) -> () // user: %18
4184
+ %18 = init_block_storage_header %9 : $*@block_storage Any, invoke %17 : $@convention(c) (@inout_aliasable @block_storage Any, Optional<CallbackData>, Optional<NSError>) -> (), type $@convention(block) (Optional<CallbackData>, Optional<NSError>) -> () // user: %19
4185
+ %19 = enum $Optional<@convention(block) (Optional<CallbackData>, Optional<NSError>) -> ()>, #Optional.some!enumelt, %18 : $@convention(block) (Optional<CallbackData>, Optional<NSError>) -> () // user: %20
4186
+ %20 = apply %6(%19, %0) : $@convention(objc_method) (Optional<@convention(block) (Optional<CallbackData>, Optional<NSError>) -> ()>, Klass) -> ()
4187
+
4188
+ Notice how without the `merge_isolation_region `_ instruction (%16) there is no
4189
+ non-Sendable def-use chain from %5, the indirect return value of the block, to
4190
+ the actual non-Sendable block storage %9. This can result in region isolation
4191
+ not propagating restrictions on usage from %9 onto %5 risking the creation of
4192
+ races.
4193
+
4194
+ Applying the previous discussion to this specific example, self (%0) is
4195
+ non-Sendable and is bound to the current task. If we did not have the
4196
+ `merge_isolation_region `_ instruction here, we would not tie the return value %5
4197
+ to %0 via %9. This would cause %5 to be treated as a disconnected value and thus
4198
+ be a valid sending return value potentially allowing for %5 in the caller of the
4199
+ function to be sent to another isolation domain and introduce a race.
4200
+
4201
+ .. note ::
4202
+ This is effectively the same purpose that `mark_dependence `_ plays for memory
4203
+ dependence (expressing memory dependence that the compiler cannot infer)
4204
+ except in the world of region isolation. We purposely use a different
4205
+ instruction since `mark_dependence `_ is often times used to create a
4206
+ temporary dependence in between two values via the return value of
4207
+ `mark_dependence `_. If `mark_dependence `_ had the semantics of acting like a
4208
+ region merge we would in contrast have from that point on a region dependence
4209
+ in between the base and value of the `mark_dependence `_ causing the
4210
+ `mark_dependence `_ to have a less "local" effect since all paths through that
4211
+ program point would have to maintain that region dependence until the end of
4212
+ the function.
4213
+
4129
4214
dealloc_stack
4130
4215
`````````````
4131
4216
::
@@ -9049,7 +9134,6 @@ NOTE: From the perspective of the address checker, a trivial `load`_ with a
9049
9134
`moveonlywrapper_to_copyable_addr `_ operand is considered to be a use of a
9050
9135
noncopyable type.
9051
9136
9052
-
9053
9137
Assertion configuration
9054
9138
~~~~~~~~~~~~~~~~~~~~~~~
9055
9139
0 commit comments