Skip to content

Commit 51ece23

Browse files
committed
IRGen: Fix enum lowering with -enable-resilience-bypass
The layout of an enum type will only use spare bits if the payload types have a fixed size in all resilience domains where they are visible. In practice, this means that: - If the enum is internal or resilient, we can use spare bits if the payload types are fixed size from inside the current module. - If the enum is public and not resilient, we can use spare bits if the payload types are fixed size from all resilience domains. The bug was that the 'fixed size in all resilience domains' check was returning true for resilient types when the -enable-resilience-bypass flag was on. This is wrong, because this meant that building a module with and without -enable-resilience-bypass could produce different lowerings for enum types. Fixes <rdar://problem/40034143>.
1 parent 99bf4dd commit 51ece23

File tree

4 files changed

+34
-1
lines changed

4 files changed

+34
-1
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4062,8 +4062,10 @@ IRGenModule::getAddrOfGlobalUTF16ConstantString(StringRef utf8) {
40624062
/// - For classes, the superclass might change the size or number
40634063
/// of stored properties
40644064
bool IRGenModule::isResilient(NominalTypeDecl *D, ResilienceExpansion expansion) {
4065-
if (Types.isCompletelyFragile())
4065+
if (expansion == ResilienceExpansion::Maximal &&
4066+
Types.isCompletelyFragile()) {
40664067
return false;
4068+
}
40674069
return D->isResilient(getSwiftModule(), expansion);
40684070
}
40694071

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
public class C {}
2+
3+
public struct S {
4+
public let c: C
5+
6+
public init() {
7+
self.c = C()
8+
}
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import first
2+
3+
public enum E {
4+
case a(S)
5+
case b(S)
6+
}

test/IRGen/resilience_bypass.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/first.swiftmodule -module-name=first %S/Inputs/resilience_bypass/first.swift
4+
// RUN: %target-swift-frontend -emit-module -emit-module-path=%t/second.swiftmodule -module-name=second %S/Inputs/resilience_bypass/second.swift -I %t
5+
// RUN: %target-swift-frontend -emit-ir -enable-resilience-bypass %s -I %t | %FileCheck %s -DINT=i%target-ptrsize
6+
7+
import second
8+
9+
// CHECK: define{{( protected)?}} swiftcc [[INT]] @"$S17resilience_bypass7getSizeSiyF"() {{.*}} {
10+
// CHECK-NEXT: entry:
11+
// CHECK-NEXT: ret [[INT]] {{5|9}}
12+
// CHECK-NEXT: }
13+
14+
public func getSize() -> Int {
15+
return MemoryLayout<E>.size
16+
}

0 commit comments

Comments
 (0)