Skip to content

Commit 7de0722

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 1600ae0 commit 7de0722

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
@@ -4067,8 +4067,10 @@ IRGenModule::getAddrOfGlobalUTF16ConstantString(StringRef utf8) {
40674067
/// - For classes, the superclass might change the size or number
40684068
/// of stored properties
40694069
bool IRGenModule::isResilient(NominalTypeDecl *D, ResilienceExpansion expansion) {
4070-
if (Types.isCompletelyFragile())
4070+
if (expansion == ResilienceExpansion::Maximal &&
4071+
Types.isCompletelyFragile()) {
40714072
return false;
4073+
}
40724074
return D->isResilient(getSwiftModule(), expansion);
40734075
}
40744076

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)