Skip to content

Commit 74f18ef

Browse files
committed
[4.1] IRGen: Fix witness-table accessors for conditional conformances
Explanation: After adding conditional conformances witness table accessors are no longer readnone because the witnesses are passed as an in memory argument. In optimized mode LLVM will optimize away the store of the witnesses because it believes the accessor function is readnone leading to crashes Scope: Introduced with conditional conformances, potentially affects any project that emit witness-table accessors on based types with conditional conformances Risk: Very low since the fix is to not emit LLVM's readnone attribute (which should do no harm) Testing: The project on which this was reported was tested and a CI test added SR-7228 rdar://38624842
1 parent 705a0bd commit 74f18ef

File tree

2 files changed

+7
-3
lines changed

2 files changed

+7
-3
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,7 @@ static llvm::Value *emitWitnessTableAccessorCall(
10641064
// If the conformance is generic, the accessor takes the metatype plus
10651065
// possible conditional conformances arguments.
10661066
llvm::CallInst *call;
1067+
bool requiresMemoryArguments = false;
10671068
if (conformance->witnessTableAccessorRequiresArguments()) {
10681069
// Emit the source metadata if we haven't yet.
10691070
if (!*srcMetadataCache) {
@@ -1076,13 +1077,14 @@ static llvm::Value *emitWitnessTableAccessorCall(
10761077

10771078
call = IGF.Builder.CreateCall(
10781079
accessor, {*srcMetadataCache, conditionalTables, numConditionalTables});
1079-
1080+
requiresMemoryArguments = true;
10801081
} else {
10811082
call = IGF.Builder.CreateCall(accessor, {});
10821083
}
10831084

10841085
call->setCallingConv(IGF.IGM.DefaultCC);
1085-
call->setDoesNotAccessMemory();
1086+
if (!requiresMemoryArguments)
1087+
call->setDoesNotAccessMemory();
10861088
call->setDoesNotThrow();
10871089

10881090
return call;

test/Inputs/conditional_conformance_basic_conformances.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public func single_concrete() {
102102
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
103103
// CHECK-NEXT: store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T042conditional_conformance_basic_conformances4IsP2VAA0F0AAWP, i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
104104

105-
// CHECK-NEXT: [[Single_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlWa(%swift.type* [[Single_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1)
105+
// CHECK-NEXT: [[Single_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlWa(%swift.type* [[Single_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1) [[ATTRS:#[0-9]+]]
106106
// CHECK-NEXT: store atomic i8** [[Single_P1]], i8*** @_T042conditional_conformance_basic_conformances6SingleVyAA4IsP2VGACyxGAA2P1A2A0G0RzlWL release, align 8
107107
// CHECK-NEXT: br label %cont
108108

@@ -323,3 +323,5 @@ public func double_concrete_concrete() {
323323
func dynamicCastToP1(_ value: Any) -> P1? {
324324
return value as? P1
325325
}
326+
327+
// CHECK: attributes [[ATTRS]] = { nounwind }

0 commit comments

Comments
 (0)