Skip to content

Commit 40a184e

Browse files
committed
[SILGen] avoid hop before autoreleased foreign error is retained
For an isolated ObjC function that is not async, we emit a hops around the call. But if that function returns an autoreleased pointer, we need to ensure we're retaining that pointer before hopping back after the call. We weren't doing that in the case of an autoreleased NSError: ``` %10 = alloc_stack $@sil_unmanaged Optional<NSError> %19 = ... a bunch of steps to wrap up %10 ... %20 = enum $Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, #Optional.some!enumelt, %19 : $AutoreleasingUnsafeMutablePointer<Optional<NSError>> hop_to_executor $MainActor %26 = apply X(Y, %20) : $@convention(objc_method) (NSObject, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>) -> @autoreleased Optional<NSString> hop_to_executor $Optional<Builtin.Executor> // retain the autoreleased pointer written-out. %28 = load [trivial] %10 : $*@sil_unmanaged Optional<NSError> %29 = unmanaged_to_ref %28 : $@sil_unmanaged Optional<NSError> to $Optional<NSError> %30 = copy_value %29 : $Optional<NSError> assign %31 to %7 : $*Optional<NSError> ``` This patch sinks the hop emission after the call so it happens after doing that copy. rdar://114049646
1 parent 235a22c commit 40a184e

File tree

7 files changed

+43
-15
lines changed

7 files changed

+43
-15
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5553,10 +5553,6 @@ RValue SILGenFunction::emitApply(
55535553
// plan's finish method is called, because it must happen in the
55545554
// successors of the `await_async_continuation` terminator.
55555555
resultPlan->deferExecutorBreadcrumb(std::move(breadcrumb));
5556-
5557-
} else {
5558-
// In the ordinary case, we hop back to the current executor
5559-
breadcrumb.emit(*this, loc);
55605556
}
55615557

55625558
// Pop the argument scope.
@@ -5629,6 +5625,12 @@ RValue SILGenFunction::emitApply(
56295625
});
56305626
}
56315627

5628+
if (!calleeTypeInfo.foreign.async) {
5629+
// For a non-foreign-async callee, we hop back to the current executor
5630+
// _after_ popping the argument scope and collecting the results.
5631+
breadcrumb.emit(*this, loc);
5632+
}
5633+
56325634
SILValue bridgedForeignError;
56335635
// If there was a foreign error convention, consider it.
56345636
// TODO: maybe this should happen after managing the result if it's

test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,4 +327,11 @@ UI_ACTOR
327327
- (void)icedMochaService:(NSObject *)mochaService generateMochaWithCompletion:(void (^)(NSObject *_Nullable ingredient1, NSObject *ingredient2, NSObject *ingredient3))completionHandler;
328328
@end
329329

330+
// rdar://114049646
331+
MAIN_ACTOR
332+
@protocol HotdogCompetitor
333+
- (nullable NSString *)pileOfHotdogsToEatWithLimit:(NSObject *)limit
334+
error:(NSError * __autoreleasing *)error;
335+
@end
336+
330337
#pragma clang assume_nonnull end

test/SILGen/async_initializer.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ enum Birb {
131131
// CHECK-NEXT: hop_to_executor [[GENERIC_EXEC]] : $Optional<Builtin.Executor>
132132
// CHECK: hop_to_executor {{%[0-9]+}} : $MainActor
133133
// CHECK-NEXT: {{%[0-9]+}} = apply {{%[0-9]+}}({{%[0-9]+}}, {{%[0-9]+}}) : $@convention(method) (@owned String, @thick Cat.Type) -> @owned Cat
134-
// CHECK-NEXT: hop_to_executor [[GENERIC_EXEC]] : $Optional<Builtin.Executor>
134+
// CHECK: hop_to_executor [[GENERIC_EXEC]] : $Optional<Builtin.Executor>
135135
// CHECK: } // end sil function '$s12initializers7makeCatyyYaF'
136136
func makeCat() async {
137137
_ = await Cat(name: "Socks")
@@ -142,7 +142,7 @@ func makeCat() async {
142142
// CHECK-NEXT: hop_to_executor [[GENERIC_EXEC]] : $Optional<Builtin.Executor>
143143
// CHECK: hop_to_executor {{%[0-9]+}} : $MainActor
144144
// CHECK-NEXT: {{%[0-9]+}} = apply {{%[0-9]+}}({{%[0-9]+}}, {{%[0-9]+}}) : $@convention(method) (@owned String, @thin Dog.Type) -> Dog
145-
// CHECK-NEXT: hop_to_executor [[GENERIC_EXEC]] : $Optional<Builtin.Executor>
145+
// CHECK: hop_to_executor [[GENERIC_EXEC]] : $Optional<Builtin.Executor>
146146
// CHECK: } // end sil function '$s12initializers7makeDogyyYaF'
147147
func makeDog() async {
148148
_ = await Dog(name: "Lassie")
@@ -153,7 +153,7 @@ func makeDog() async {
153153
// CHECK-NEXT: hop_to_executor [[GENERIC_EXEC]] : $Optional<Builtin.Executor>
154154
// CHECK: hop_to_executor {{%[0-9]+}} : $MainActor
155155
// CHECK-NEXT: {{%[0-9]+}} = apply {{%[0-9]+}}({{%[0-9]+}}, {{%[0-9]+}}) : $@convention(method) (@owned String, @thin Birb.Type) -> Birb
156-
// CHECK-NEXT: hop_to_executor [[GENERIC_EXEC]] : $Optional<Builtin.Executor>
156+
// CHECK: hop_to_executor [[GENERIC_EXEC]] : $Optional<Builtin.Executor>
157157
// CHECK: } // end sil function '$s12initializers8makeBirbyyYaF'
158158
func makeBirb() async {
159159
_ = await Birb(name: "Chirpy")

test/SILGen/hop_to_executor.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ actor MyActor {
4747
// CHECK: [[BORROWED_SELF:%[0-9]+]] = begin_borrow %0 : $MyActor
4848
// CHECK: hop_to_executor [[BORROWED_SELF]] : $MyActor
4949
// CHECK: = apply {{.*}} : $@convention(method) @async (Int, @guaranteed MyActor) -> ()
50-
// CHECK-NEXT: hop_to_executor [[BORROWED_SELF]] : $MyActor
50+
// CHECK: hop_to_executor [[BORROWED_SELF]] : $MyActor
5151
// CHECK: } // end sil function '$s4test7MyActorC0A22ConsumingAsyncFunctionyyYaF'
5252
__consuming func testConsumingAsyncFunction() async {
5353
await callee(p)
@@ -271,9 +271,9 @@ struct BlueActor {
271271
// CHECK: hop_to_executor [[REDEXE]] : $RedActorImpl
272272
// ---- now invoke redFn, hop back to Blue, and clean-up ----
273273
// CHECK-NEXT: {{%[0-9]+}} = apply [[CALLEE]]([[ARG]]) : $@convention(thin) (Int) -> ()
274+
// CHECK-NEXT: end_borrow [[REDEXE]] : $RedActorImpl
275+
// CHECK-NEXT: destroy_value [[R]] : $RedActorImpl
274276
// CHECK-NEXT: hop_to_executor [[BLUEEXE]] : $BlueActorImpl
275-
// CHECK: end_borrow [[REDEXE]] : $RedActorImpl
276-
// CHECK: destroy_value [[R]] : $RedActorImpl
277277
// CHECK: end_borrow [[BLUEEXE]] : $BlueActorImpl
278278
// CHECK: destroy_value [[B]] : $BlueActorImpl
279279
// CHECK: } // end sil function '$s4test6blueFnyyYaF'
@@ -287,8 +287,9 @@ struct BlueActor {
287287
// CHECK: [[BORROW:%[0-9]+]] = begin_borrow {{%[0-9]+}} : $RedActorImpl
288288
// CHECK-NEXT: hop_to_executor [[BORROW]] : $RedActorImpl
289289
// CHECK-NEXT: {{%[0-9]+}} = apply {{%[0-9]+}}({{%[0-9]+}}) : $@convention(thin) (Int) -> ()
290-
// CHECK-NEXT: hop_to_executor [[GENERIC_EXEC]]
291290
// CHECK-NEXT: end_borrow [[BORROW]] : $RedActorImpl
291+
// CHECK-NEXT: destroy_value
292+
// CHECK-NEXT: hop_to_executor [[GENERIC_EXEC]]
292293
// CHECK: } // end sil function '$s4test20unspecifiedAsyncFuncyyYaF'
293294
func unspecifiedAsyncFunc() async {
294295
await redFn(200)
@@ -315,7 +316,7 @@ func anotherUnspecifiedAsyncFunc(_ red : RedActorImpl) async {
315316
// CHECK: hop_to_executor [[RED:%[0-9]+]] : $RedActorImpl
316317
// CHECK-NEXT: begin_borrow
317318
// CHECK-NEXT: apply
318-
// CHECK-NEXT: hop_to_executor [[GENERIC_EXEC:%[0-9]+]] : $Optional<Builtin.Executor>
319+
// CHECK: hop_to_executor [[GENERIC_EXEC:%[0-9]+]] : $Optional<Builtin.Executor>
319320
func testGlobalActorFuncValue(_ fn: @RedActor () -> Void) async {
320321
await fn()
321322
}

test/SILGen/hop_to_executor_async_prop.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ func accessSweaterOfSweater(cat : Cat) async -> Sweater {
123123

124124
// CHECK: hop_to_executor [[GLOBAL_CAT]] : $Cat
125125
// CHECK: [[THE_STRING:%[0-9]+]] = apply [[GETTER]]([[CAT]]) : $@convention(method) (@guaranteed Cat) -> @owned String
126-
// CHECK: hop_to_executor [[GENERIC_EXEC]]
127126
// CHECK: end_borrow [[GLOBAL_CAT]] : $Cat
128127
// CHECK: destroy_value [[GLOBAL_CAT_REF]] : $Cat
128+
// CHECK: hop_to_executor [[GENERIC_EXEC]]
129129
// CHECK: return [[THE_STRING]] : $String
130130
// CHECK: } // end sil function '$s4test26accessGlobalIsolatedMember3catSSAA3CatC_tYaF'
131131
func accessGlobalIsolatedMember(cat : Cat) async -> String {

test/SILGen/objc_async.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,21 @@ func testThrowingMethodFromMain(slowServer: SlowServer) async -> String {
276276
func checkCostcoMembership() async -> Bool {
277277
return await CostcoManager.shared().isCustomerEnrolled(inExecutiveProgram: Person.asCustomer())
278278
}
279+
280+
281+
// CHECK-LABEL: sil {{.*}} @$s10objc_async12checkHotdogsySSSgx_So8NSObjectCtYaKSo16HotdogCompetitorRzlF
282+
// CHECK: hop_to_executor {{.*}} : $MainActor
283+
// CHECK: [[AUTO_REL_STR:%.*]] = apply {{.*}}<some HotdogCompetitor>({{.*}}) : $@convention(objc_method)
284+
// CHECK: [[UNMANAGED_OPTIONAL:%.*]] = load [trivial] {{.*}} : $*@sil_unmanaged Optional<NSError>
285+
// CHECK: [[MANAGED_OPTIONAL:%.*]] = unmanaged_to_ref [[UNMANAGED_OPTIONAL]] : $@sil_unmanaged Optional<NSError> to $Optional<NSError>
286+
// CHECK: [[RETAINED_OPTIONAL:%.*]] = copy_value [[MANAGED_OPTIONAL]] : $Optional<NSError>
287+
// CHECK: [[MARKED:%.*]] = mark_dependence [[RETAINED_OPTIONAL]] : $Optional<NSError> on {{.*}} : $*Optional<NSError> // user: %32
288+
// CHECK: assign [[MARKED]] to {{.*}} : $*Optional<NSError>
289+
// CHECK: destroy_value {{.*}} : $MainActor
290+
// CHECK: dealloc_stack {{.*}} : $*AutoreleasingUnsafeMutablePointer<Optional<NSError>>
291+
// CHECK: dealloc_stack {{.*}} : $*@sil_unmanaged Optional<NSError>
292+
// CHECK: hop_to_executor {{.*}} : $Optional<Builtin.Executor>
293+
// CHECK: switch_enum
294+
func checkHotdogs(_ v: some HotdogCompetitor, _ timeLimit: NSObject) async throws -> String? {
295+
return try await v.pileOfHotdogsToEat(withLimit: timeLimit)
296+
}

test/SILGen/toplevel_globalactorvars.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ await printFromMyActor(value: a)
6868
// CHECK: [[ACTORREF:%[0-9]+]] = begin_borrow {{%[0-9]+}} : $MyActorImpl
6969
// CHECK: hop_to_executor [[ACTORREF]] : $MyActorImpl
7070
// CHECK: {{%[0-9]+}} = apply [[PRINTFROMMYACTOR_FUNC]]([[AGLOBAL]])
71-
// CHECK: hop_to_executor [[MAIN_OPTIONAL]]
7271
// CHECK: end_borrow [[ACTORREF]]
72+
// CHECK: hop_to_executor [[MAIN_OPTIONAL]]
7373

7474
if a < 10 {
7575
// CHECK: [[AACCESS:%[0-9]+]] = begin_access [read] [dynamic] [[AREF]] : $*Int
@@ -122,6 +122,6 @@ if a < 10 {
122122
// CHECK: [[ACTORREF:%[0-9]+]] = begin_borrow {{%[0-9]+}} : $MyActorImpl
123123
// CHECK: hop_to_executor [[ACTORREF]] : $MyActorImpl
124124
// CHECK: {{%[0-9]+}} = apply [[PRINTFROMMYACTOR_FUNC]]([[AGLOBAL]])
125-
// CHECK: hop_to_executor [[MAIN_OPTIONAL]]
126125
// CHECK: end_borrow [[ACTORREF]]
126+
// CHECK: hop_to_executor [[MAIN_OPTIONAL]]
127127
}

0 commit comments

Comments
 (0)