Skip to content

Commit c67b72b

Browse files
authored
Merge pull request #41344 from atrick/fix-open-existential
Fix a miscompile in existential specialization during SILCombine.
2 parents 92d014c + 07e6cfc commit c67b72b

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6814,6 +6814,11 @@ class OpenExistentialAddrInst
68146814
SILType SelfTy, OpenedExistentialAccess AccessKind);
68156815

68166816
public:
6817+
static bool isRead(SILInstruction *inst) {
6818+
auto *open = dyn_cast<OpenExistentialAddrInst>(inst);
6819+
return open && open->getAccessKind() == OpenedExistentialAccess::Immutable;
6820+
}
6821+
68176822
OpenedExistentialAccess getAccessKind() const { return ForAccess; }
68186823
};
68196824

lib/SILOptimizer/Utils/Existential.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ static SILInstruction *getStackInitInst(SILValue allocStackAddr,
9090
DebugValueInst::hasAddrVal(User) ||
9191
isa<DestroyAddrInst>(User) || isa<WitnessMethodInst>(User) ||
9292
isa<DeinitExistentialAddrInst>(User) ||
93-
isa<OpenExistentialAddrInst>(User) || User == ASIUser) {
93+
OpenExistentialAddrInst::isRead(User) || User == ASIUser) {
9494
continue;
9595
}
9696
if (auto *CAI = dyn_cast<CopyAddrInst>(User)) {

test/SILOptimizer/sil_combine_concrete_existential.sil

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,67 @@ bb3(%20 : $Error):
721721
throw %20 : $Error
722722
}
723723

724+
// -----------------------------------------------------------------------------
725+
// rdar://88664423 (SR-15791: Miscompile under -O with mutating protocol method)
726+
//
727+
// Basic outline (test case has more copies):
728+
// %1 = alloc_stack $PPP
729+
// %2 = init_existential %1
730+
// %3 = open_existential_addr mutable_access %1
731+
// apply mutatingFunc(%3)
732+
// %5 = open_existential_addr %1
733+
// %6 = alloc_stack $@opened P
734+
// copy_addr %5 to [initialization] %6 : $*@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D") PPP
735+
// apply callee3(%5)
736+
//
737+
// When ConcreteExistentialInfo identified the initialization of:
738+
// %4 = alloc_stack [lexical] $PPP, var, name "mergedCommand"
739+
//
740+
// It checks for any mutation other than the initialization itself.
741+
// In this case, `open_existential_addr mutable_access` must be
742+
// considered a possible mutation of the on-stack value.
743+
744+
sil @mutatingFunc : $@convention(method) (@inout S) -> ()
745+
746+
sil @callee3 : $@convention(thin) <τ_0_0 where τ_0_0 : PPP> (@in τ_0_0) -> ()
747+
748+
// CHECK-LABEL: sil @testMutatingCopiedOpenExistential : $@convention(thin) (S) -> () {
749+
// CHECK: bb0(%0 : $S):
750+
// CHECK: [[EXISCP:%.*]] = alloc_stack [lexical] $PPP, var, name "mergedCommand"
751+
// CHECK: apply %{{.*}} : $@convention(method) (@inout S) -> ()
752+
// CHECK: [[OPENED:%.*]] = open_existential_addr mutable_access [[EXISCP]] : $*PPP to $*@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D") PPP
753+
// CHECK: [[OPENEDCP:%.*]] = alloc_stack $@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D") PPP
754+
// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENEDCP]] : $*@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D") PPP
755+
// CHECK: [[CALLEE3:%.*]] = function_ref @callee3 : $@convention(thin) <τ_0_0 where τ_0_0 : PPP> (@in τ_0_0) -> ()
756+
// CHECK: apply [[CALLEE3]]<@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D") PPP>([[OPENEDCP]]) : $@convention(thin) <τ_0_0 where τ_0_0 : PPP> (@in τ_0_0) -> ()
757+
// CHECK-LABEL: } // end sil function 'testMutatingCopiedOpenExistential'
758+
sil @testMutatingCopiedOpenExistential : $@convention(thin) (S) -> () {
759+
bb0(%0 : $S):
760+
%1 = alloc_stack $PPP
761+
%2 = init_existential_addr %1 : $*PPP, $S
762+
store %0 to %2 : $*S
763+
%4 = alloc_stack [lexical] $PPP, var, name "mergedCommand"
764+
copy_addr %1 to [initialization] %4 : $*PPP
765+
%6 = open_existential_addr mutable_access %4 : $*PPP to $*@opened("3818BC52-89A1-11EC-999A-D0817AD9985D") PPP
766+
%7 = unchecked_addr_cast %6 : $*@opened("3818BC52-89A1-11EC-999A-D0817AD9985D") PPP to $*S
767+
768+
%8 = function_ref @mutatingFunc : $@convention(method) (@inout S) -> ()
769+
%9 = apply %8(%7) : $@convention(method) (@inout S) -> ()
770+
%10 = open_existential_addr mutable_access %4 : $*PPP to $*@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D") PPP
771+
%11 = alloc_stack $@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D") PPP
772+
copy_addr %10 to [initialization] %11 : $*@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D") PPP
773+
774+
%13 = function_ref @callee3 : $@convention(thin) <τ_0_0 where τ_0_0 : PPP> (@in τ_0_0) -> ()
775+
%14 = apply %13<@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D") PPP>(%11) : $@convention(thin) <τ_0_0 where τ_0_0 : PPP> (@in τ_0_0) -> ()
776+
dealloc_stack %11 : $*@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D") PPP
777+
destroy_addr %4 : $*PPP
778+
dealloc_stack %4 : $*PPP
779+
destroy_addr %1 : $*PPP
780+
dealloc_stack %1 : $*PPP
781+
%20 = tuple ()
782+
return %20 : $()
783+
}
784+
724785
sil_vtable SubscriptionViewControllerBuilder {}
725786
sil_vtable SubscriptionViewController {}
726787
sil_vtable ViewController {}

0 commit comments

Comments
 (0)