From c77ecbf49941d6c50c4bd039d59a9af9c1fcdb44 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 10 May 2018 00:46:55 -0400 Subject: [PATCH] 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 . --- lib/IRGen/GenDecl.cpp | 4 +++- test/IRGen/Inputs/resilience_bypass/first.swift | 9 +++++++++ test/IRGen/Inputs/resilience_bypass/second.swift | 6 ++++++ test/IRGen/resilience_bypass.swift | 16 ++++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 test/IRGen/Inputs/resilience_bypass/first.swift create mode 100644 test/IRGen/Inputs/resilience_bypass/second.swift create mode 100644 test/IRGen/resilience_bypass.swift diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 13da1237d3867..81c674f79f44b 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -4067,8 +4067,10 @@ IRGenModule::getAddrOfGlobalUTF16ConstantString(StringRef utf8) { /// - For classes, the superclass might change the size or number /// of stored properties bool IRGenModule::isResilient(NominalTypeDecl *D, ResilienceExpansion expansion) { - if (Types.isCompletelyFragile()) + if (expansion == ResilienceExpansion::Maximal && + Types.isCompletelyFragile()) { return false; + } return D->isResilient(getSwiftModule(), expansion); } diff --git a/test/IRGen/Inputs/resilience_bypass/first.swift b/test/IRGen/Inputs/resilience_bypass/first.swift new file mode 100644 index 0000000000000..8f9771e50def1 --- /dev/null +++ b/test/IRGen/Inputs/resilience_bypass/first.swift @@ -0,0 +1,9 @@ +public class C {} + +public struct S { + public let c: C + + public init() { + self.c = C() + } +} diff --git a/test/IRGen/Inputs/resilience_bypass/second.swift b/test/IRGen/Inputs/resilience_bypass/second.swift new file mode 100644 index 0000000000000..019596bfafe5d --- /dev/null +++ b/test/IRGen/Inputs/resilience_bypass/second.swift @@ -0,0 +1,6 @@ +import first + +public enum E { + case a(S) + case b(S) +} diff --git a/test/IRGen/resilience_bypass.swift b/test/IRGen/resilience_bypass.swift new file mode 100644 index 0000000000000..95b59e292e800 --- /dev/null +++ b/test/IRGen/resilience_bypass.swift @@ -0,0 +1,16 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/first.swiftmodule -module-name=first %S/Inputs/resilience_bypass/first.swift +// RUN: %target-swift-frontend -emit-module -emit-module-path=%t/second.swiftmodule -module-name=second %S/Inputs/resilience_bypass/second.swift -I %t +// RUN: %target-swift-frontend -emit-ir -enable-resilience-bypass %s -I %t | %FileCheck %s -DINT=i%target-ptrsize + +import second + +// CHECK: define{{( protected)?}} swiftcc [[INT]] @"$S17resilience_bypass7getSizeSiyF"() {{.*}} { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret [[INT]] {{5|9}} +// CHECK-NEXT: } + +public func getSize() -> Int { + return MemoryLayout.size +}