Skip to content

Commit 5680bfd

Browse files
committed
IRGen: Always use YAML files for completely fragile class layout
The layouts of resilient value types shipped in the Swift 5 standard library x and overlays will forever be frozen in time for backward deployment to old Objective-C runtimes. This PR ensures that even if the layouts of these types evolve in the future, binaries built to run on the old runtime will continue to lay out class instances in a manner compatible with Swift 5. Fixes <rdar://problem/45646886>.
1 parent 32954fc commit 5680bfd

34 files changed

+153
-93
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ class IRGenOptions {
178178
/// Used on Windows to avoid cross-module references.
179179
unsigned LazyInitializeClassMetadata : 1;
180180

181+
/// Normally if the -read-legacy-type-info flag is not specified, we look for
182+
/// a file named "legacy-<arch>.yaml" in SearchPathOpts.RuntimeLibraryPath.
183+
/// Passing this flag completely disables this behavior.
184+
unsigned DisableLegacyTypeInfo : 1;
185+
181186
/// The path to load legacy type layouts from.
182187
StringRef ReadLegacyTypeInfoPath;
183188

@@ -233,6 +238,7 @@ class IRGenOptions {
233238
EnableReflectionNames(true), EnableAnonymousContextMangledNames(false),
234239
EnableClassResilience(false),
235240
EnableResilienceBypass(false), LazyInitializeClassMetadata(false),
241+
DisableLegacyTypeInfo(false),
236242
UseIncrementalLLVMCodeGen(true), UseSwiftCall(false),
237243
GenerateProfile(false), EnableDynamicReplacementChaining(false),
238244
DisableRoundTripDebugTypes(false),

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ def enable_resilience : Flag<["-"], "enable-resilience">,
177177
def enable_class_resilience : Flag<["-"], "enable-class-resilience">,
178178
HelpText<"Enable resilient layout for classes containing resilient value types">;
179179

180+
def disable_legacy_type_info : Flag<["-"], "disable-legacy-type-info">,
181+
HelpText<"Completely disable legacy type layout">;
182+
180183
def read_legacy_type_info_path_EQ : Joined<["-"], "read-legacy-type-info-path=">,
181184
HelpText<"Read legacy type layout from the given path instead of default path">;
182185
}

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,10 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
10791079
// (e.g. NativeObject). Force the lazy initialization of the VWT always.
10801080
Opts.LazyInitializeClassMetadata = Triple.isOSBinFormatCOFF();
10811081

1082+
if (Args.hasArg(OPT_disable_legacy_type_info)) {
1083+
Opts.DisableLegacyTypeInfo = true;
1084+
}
1085+
10821086
if (const Arg *A = Args.getLastArg(OPT_read_legacy_type_info_path_EQ)) {
10831087
Opts.ReadLegacyTypeInfoPath = A->getValue();
10841088
}

lib/IRGen/GenClass.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,9 @@ namespace {
376376
// Lower the field type.
377377
auto *eltType = &IGM.getTypeInfo(type);
378378
if (CompletelyFragileLayout && !eltType->isFixedSize()) {
379-
// For staging purposes, only do the new thing if the path flag
380-
// is provided.
381-
auto mode = (IGM.IRGen.Opts.ReadLegacyTypeInfoPath.empty()
379+
// For staging purposes, only do the new thing if we're going
380+
// to load a YAML file describing legacy type layouts.
381+
auto mode = (IGM.IRGen.Opts.DisableLegacyTypeInfo
382382
? TypeConverter::Mode::CompletelyFragile
383383
: TypeConverter::Mode::Legacy);
384384
LoweringModeScope scope(IGM, mode);

lib/IRGen/GenType.cpp

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@
2121
#include "swift/AST/IRGenOptions.h"
2222
#include "swift/AST/PrettyStackTrace.h"
2323
#include "swift/AST/Types.h"
24+
#include "swift/Basic/Platform.h"
2425
#include "swift/IRGen/Linking.h"
2526
#include "swift/SIL/SILModule.h"
2627
#include "llvm/IR/DerivedTypes.h"
2728
#include "llvm/ADT/SmallString.h"
2829
#include "llvm/Support/ErrorHandling.h"
30+
#include "llvm/Support/Path.h"
2931
#include "clang/CodeGen/SwiftCallingConv.h"
3032

3133
#include "EnumPayload.h"
@@ -1114,6 +1116,30 @@ TypeConverter::getLegacyTypeInfo(NominalTypeDecl *decl) const {
11141116
return found->second;
11151117
}
11161118

1119+
static llvm::StringLiteral platformsWithLegacyLayouts[][2] = {
1120+
{"appletvos", "arm64"},
1121+
{"appletvsimulator", "x86_64"},
1122+
{"iphoneos", "armv7"},
1123+
{"iphoneos", "armv7s"},
1124+
{"iphoneos", "arm64"},
1125+
{"iphonesimulator", "i386"},
1126+
{"iphonesimulator", "x86_64"},
1127+
{"macosx", "x86_64"},
1128+
{"watchos", "armv7k"},
1129+
{"watchsimulator", "i386"}
1130+
};
1131+
1132+
static bool doesPlatformUseLegacyLayouts(StringRef platformName,
1133+
StringRef archName) {
1134+
for (auto platformArchPair : platformsWithLegacyLayouts) {
1135+
if (platformName == platformArchPair[0] &&
1136+
archName == platformArchPair[1]) {
1137+
return true;
1138+
}
1139+
}
1140+
1141+
return false;
1142+
}
11171143
TypeConverter::TypeConverter(IRGenModule &IGM)
11181144
: IGM(IGM),
11191145
FirstType(invalidTypeInfo()) {
@@ -1125,13 +1151,34 @@ TypeConverter::TypeConverter(IRGenModule &IGM)
11251151
if (IGM.IRGen.Opts.EnableResilienceBypass)
11261152
LoweringMode = Mode::CompletelyFragile;
11271153

1154+
// We have a bunch of -parse-stdlib tests that pass a -target in the test
1155+
// suite. To prevent these from failing when the user hasn't build the
1156+
// standard library for that target, we pass -disable-legacy-type-info to
1157+
// disable trying to load the legacy type info.
1158+
if (IGM.IRGen.Opts.DisableLegacyTypeInfo)
1159+
return;
1160+
1161+
auto platformName = getPlatformNameForTriple(IGM.Triple);
1162+
auto archName = getMajorArchitectureName(IGM.Triple);
1163+
1164+
if (!doesPlatformUseLegacyLayouts(platformName, archName))
1165+
return;
1166+
1167+
llvm::SmallString<128> defaultPath;
1168+
11281169
StringRef path = IGM.IRGen.Opts.ReadLegacyTypeInfoPath;
1129-
if (!path.empty()) {
1130-
bool error = readLegacyTypeInfo(path);
1131-
if (error) {
1132-
llvm::report_fatal_error("Cannot read '" + path + "'");
1133-
}
1170+
if (path.empty()) {
1171+
defaultPath.append(IGM.Context.SearchPathOpts.RuntimeLibraryPath);
1172+
llvm::sys::path::append(defaultPath, "layouts-");
1173+
defaultPath.append(archName);
1174+
defaultPath.append(".yaml");
1175+
1176+
path = defaultPath;
11341177
}
1178+
1179+
bool error = readLegacyTypeInfo(path);
1180+
if (error)
1181+
llvm::report_fatal_error("Cannot read '" + path + "'");
11351182
}
11361183

11371184
TypeConverter::~TypeConverter() {

test/DebugInfo/compiler-flags-macosx.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// a Darwin target and set the RC_DEBUG_OPTIONS environment variable. This
33
// matches the behavior found in Clang.
44

5-
// RUN: %swiftc_driver %s -emit-ir -g -target x86_64-apple-macosx10.10 -parse-stdlib -module-name scratch -o - | %FileCheck %s
6-
// RUN: env RC_DEBUG_OPTIONS=1 %swiftc_driver %s -emit-ir -g -target x86_64-apple-macosx10.10 -parse-stdlib -module-name scratch -o - | %FileCheck --check-prefix CHECK-VAR-SET %s
5+
// RUN: %swiftc_driver %s -emit-ir -g -Xfrontend -disable-legacy-type-info -target x86_64-apple-macosx10.10 -parse-stdlib -module-name scratch -o - | %FileCheck %s
6+
// RUN: env RC_DEBUG_OPTIONS=1 %swiftc_driver %s -emit-ir -g -Xfrontend -disable-legacy-type-info -target x86_64-apple-macosx10.10 -parse-stdlib -module-name scratch -o - | %FileCheck --check-prefix CHECK-VAR-SET %s
77
// CHECK: !DICompileUnit({{.*}} producer: "{{(Apple )?Swift version [^"]+}}"
88
// CHECK-NOT: flags: "
99
// CHECK-VAR-SET: !DICompileUnit({{.*}}producer: "{{(Apple )?Swift version [^"]+}}"

test/IRGen/alloc.sil

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
// RUN: %swift -target x86_64-apple-macosx10.9 -module-name main %s -emit-ir -o - | %FileCheck %s
2-
// RUN: %swift -target i386-apple-ios7.0 %s -module-name main -emit-ir -o - | %FileCheck %s
3-
// RUN: %swift -target x86_64-apple-ios7.0 %s -module-name main -emit-ir -o - | %FileCheck %s
4-
// RUN: %swift -target armv7-apple-ios7.0 %s -module-name main -emit-ir -o - | %FileCheck %s
5-
// RUN: %swift -target arm64-apple-ios7.0 %s -module-name main -emit-ir -o - | %FileCheck %s
6-
// RUN: %swift -target x86_64-unknown-linux-gnu %s -disable-objc-interop -module-name main -emit-ir -o - | %FileCheck %s
1+
// RUN: %swift -disable-legacy-type-info -target x86_64-apple-macosx10.9 -module-name main %s -emit-ir -o - | %FileCheck %s
2+
// RUN: %swift -disable-legacy-type-info -target i386-apple-ios7.0 %s -module-name main -emit-ir -o - | %FileCheck %s
3+
// RUN: %swift -disable-legacy-type-info -target x86_64-apple-ios7.0 %s -module-name main -emit-ir -o - | %FileCheck %s
4+
// RUN: %swift -disable-legacy-type-info -target armv7-apple-ios7.0 %s -module-name main -emit-ir -o - | %FileCheck %s
5+
// RUN: %swift -disable-legacy-type-info -target arm64-apple-ios7.0 %s -module-name main -emit-ir -o - | %FileCheck %s
6+
// RUN: %swift -disable-legacy-type-info -target x86_64-unknown-linux-gnu %s -disable-objc-interop -module-name main -emit-ir -o - | %FileCheck %s
77

88
// REQUIRES: CODEGENERATOR=X86
99
// REQUIRES: CODEGENERATOR=ARM

test/IRGen/autolink-coff-x86.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %swift -target x86_64--windows-gnu -parse-as-library -parse-stdlib -emit-module-path %t/module.swiftmodule -module-name module -module-link-name module %s
4-
// RUN: %swift -target x86_64--windows-gnu -parse-as-library -parse-stdlib -module-name autolink -I %t -D MAIN_MODULE -emit-ir -o - %s | %FileCheck %s -check-prefix CHECK-GNU-IR
5-
// RUN: %swift -target x86_64--windows-gnu -parse-as-library -parse-stdlib -module-name autolink -I %t -D MAIN_MODULE -S -o - %s | %FileCheck %s -check-prefix CHECK-GNU-ASM
3+
// RUN: %swift -target x86_64--windows-gnu -parse-as-library -disable-legacy-type-info -parse-stdlib -emit-module-path %t/module.swiftmodule -module-name module -module-link-name module %s
4+
// RUN: %swift -target x86_64--windows-gnu -parse-as-library -disable-legacy-type-info -parse-stdlib -module-name autolink -I %t -D MAIN_MODULE -emit-ir -o - %s | %FileCheck %s -check-prefix CHECK-GNU-IR
5+
// RUN: %swift -target x86_64--windows-gnu -parse-as-library -disable-legacy-type-info -parse-stdlib -module-name autolink -I %t -D MAIN_MODULE -S -o - %s | %FileCheck %s -check-prefix CHECK-GNU-ASM
66

77
// REQUIRES: CODEGENERATOR=X86
88

test/IRGen/autolink-coff.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %swift -target thumbv7--windows-itanium -parse-as-library -parse-stdlib -emit-module-path %t/module.swiftmodule -module-name module -module-link-name module %s
4-
// RUN: %swift -target thumbv7--windows-itanium -parse-as-library -parse-stdlib -module-name autolink -I %t -D MAIN_MODULE -emit-ir -o - %s | %FileCheck %s -check-prefix CHECK-MSVC-IR
5-
// RUN: %swift -target thumbv7--windows-itanium -parse-as-library -parse-stdlib -module-name autolink -I %t -D MAIN_MODULE -S -o - %s | %FileCheck %s -check-prefix CHECK-MSVC-ASM
3+
// RUN: %swift -target thumbv7--windows-itanium -parse-as-library -disable-legacy-type-info -parse-stdlib -emit-module-path %t/module.swiftmodule -module-name module -module-link-name module %s
4+
// RUN: %swift -target thumbv7--windows-itanium -parse-as-library -disable-legacy-type-info -parse-stdlib -module-name autolink -I %t -D MAIN_MODULE -emit-ir -o - %s | %FileCheck %s -check-prefix CHECK-MSVC-IR
5+
// RUN: %swift -target thumbv7--windows-itanium -parse-as-library -disable-legacy-type-info -parse-stdlib -module-name autolink -I %t -D MAIN_MODULE -S -o - %s | %FileCheck %s -check-prefix CHECK-MSVC-ASM
66

7-
// RUN: %swift -target thumbv7--windows-msvc -parse-as-library -parse-stdlib -emit-module-path %t/module.swiftmodule -module-name module -module-link-name module %s
8-
// RUN: %swift -target thumbv7--windows-msvc -parse-as-library -parse-stdlib -module-name autolink -I %t -D MAIN_MODULE -emit-ir -o - %s | %FileCheck %s -check-prefix CHECK-MSVC-IR
9-
// RUN: %swift -target thumbv7--windows-msvc -parse-as-library -parse-stdlib -module-name autolink -I %t -D MAIN_MODULE -S -o - %s | %FileCheck %s -check-prefix CHECK-MSVC-ASM
7+
// RUN: %swift -target thumbv7--windows-msvc -parse-as-library -disable-legacy-type-info -parse-stdlib -emit-module-path %t/module.swiftmodule -module-name module -module-link-name module %s
8+
// RUN: %swift -target thumbv7--windows-msvc -parse-as-library -disable-legacy-type-info -parse-stdlib -module-name autolink -I %t -D MAIN_MODULE -emit-ir -o - %s | %FileCheck %s -check-prefix CHECK-MSVC-IR
9+
// RUN: %swift -target thumbv7--windows-msvc -parse-as-library -disable-legacy-type-info -parse-stdlib -module-name autolink -I %t -D MAIN_MODULE -S -o - %s | %FileCheck %s -check-prefix CHECK-MSVC-ASM
1010

1111
// REQUIRES: CODEGENERATOR=ARM
1212

test/IRGen/autolink-force-link.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %swift -target x86_64-apple-macosx10.9 -parse-stdlib -autolink-force-load -module-name TEST -module-link-name TEST -emit-ir %s %S/../Inputs/empty.swift | %FileCheck -check-prefix=CHECK-WMO %s
3+
// RUN: %swift -disable-legacy-type-info -target x86_64-apple-macosx10.9 -parse-stdlib -autolink-force-load -module-name TEST -module-link-name TEST -emit-ir %s %S/../Inputs/empty.swift | %FileCheck -check-prefix=CHECK-WMO %s
44

55
// CHECK-WMO: source_filename = "-"
66
// CHECK-WMO: define void @"_swift_FORCE_LOAD_$_TEST"()
77
// CHECK-WMO-NOT: source_filename
88

99

10-
// RUN: %swift -target x86_64-apple-macosx10.9 -parse-stdlib -autolink-force-load -module-name TEST -module-link-name TEST -emit-ir -num-threads 1 %s %S/../Inputs/empty.swift | %FileCheck -check-prefix=CHECK-WMO-THREADED %s
10+
// RUN: %swift -disable-legacy-type-info -target x86_64-apple-macosx10.9 -parse-stdlib -autolink-force-load -module-name TEST -module-link-name TEST -emit-ir -num-threads 1 %s %S/../Inputs/empty.swift | %FileCheck -check-prefix=CHECK-WMO-THREADED %s
1111

1212
// CHECK-WMO-THREADED: source_filename = "-"
1313
// CHECK-WMO-THREADED: define void @"_swift_FORCE_LOAD_$_TEST"()
@@ -16,8 +16,8 @@
1616
// CHECK-WMO-THREADED-NOT: source_filename
1717

1818

19-
// RUN: %swift -target x86_64-apple-macosx10.9 -parse-stdlib -autolink-force-load -module-name TEST -module-link-name TEST -emit-ir -primary-file %s %S/../Inputs/empty.swift | %FileCheck -check-prefix=CHECK-SINGLE-FILE-FIRST %s
20-
// RUN: %swift -target x86_64-apple-macosx10.9 -parse-stdlib -autolink-force-load -module-name TEST -module-link-name TEST -emit-ir %S/../Inputs/empty.swift -primary-file %s | %FileCheck -check-prefix=CHECK-SINGLE-FILE-SECOND %s
19+
// RUN: %swift -disable-legacy-type-info -target x86_64-apple-macosx10.9 -parse-stdlib -autolink-force-load -module-name TEST -module-link-name TEST -emit-ir -primary-file %s %S/../Inputs/empty.swift | %FileCheck -check-prefix=CHECK-SINGLE-FILE-FIRST %s
20+
// RUN: %swift -disable-legacy-type-info -target x86_64-apple-macosx10.9 -parse-stdlib -autolink-force-load -module-name TEST -module-link-name TEST -emit-ir %S/../Inputs/empty.swift -primary-file %s | %FileCheck -check-prefix=CHECK-SINGLE-FILE-SECOND %s
2121

2222
// CHECK-SINGLE-FILE-FIRST: source_filename = "-"
2323
// CHECK-SINGLE-FILE-FIRST: define void @"_swift_FORCE_LOAD_$_TEST"()

0 commit comments

Comments
 (0)