mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Add a -experimental-hermetic-seal-at-link flag that triggers aggressive LTO-based dead-stripping (VFE, WME, conditional runtime records, internalization) (#39793)
This commit is contained in:
committed by
GitHub
parent
1ab88ed090
commit
94f23942db
@@ -166,6 +166,14 @@ ERROR(error_darwin_only_supports_libcxx, none,
|
||||
"The only C++ standard library supported on Apple platforms is libc++",
|
||||
())
|
||||
|
||||
ERROR(error_hermetic_seal_cannot_have_library_evolution, none,
|
||||
"Cannot use -experimental-hermetic-seal-at-link with -enable-library-evolution",
|
||||
())
|
||||
|
||||
ERROR(error_hermetic_seal_requires_lto, none,
|
||||
"-experimental-hermetic-seal-at-link requires -lto=llvm-full or -lto=llvm-thin",
|
||||
())
|
||||
|
||||
WARNING(warn_drv_darwin_sdk_invalid_settings, none,
|
||||
"SDK settings were ignored because 'SDKSettings.json' could not be parsed",
|
||||
())
|
||||
|
||||
@@ -620,6 +620,11 @@ def requirement_machine_protocol_signatures_EQ : Joined<["-"], "requirement-mach
|
||||
Flags<[FrontendOption]>,
|
||||
HelpText<"Control usage of experimental protocol requirement signature minimization: 'on', 'off', or 'verify'">;
|
||||
|
||||
def experimental_hermetic_seal_at_link:
|
||||
Flag<["-"], "experimental-hermetic-seal-at-link">,
|
||||
Flags<[FrontendOption, HelpHidden]>,
|
||||
HelpText<"Library code can assume that all clients are visible at linktime, and aggressively strip unused code">;
|
||||
|
||||
// Diagnostic control options
|
||||
def suppress_warnings : Flag<["-"], "suppress-warnings">,
|
||||
Flags<[FrontendOption]>,
|
||||
|
||||
@@ -283,6 +283,28 @@ static void validateSearchPathArgs(DiagnosticEngine &diags,
|
||||
}
|
||||
}
|
||||
|
||||
static void validateLinkArgs(DiagnosticEngine &diags, const ArgList &args) {
|
||||
if (args.hasArg(options::OPT_experimental_hermetic_seal_at_link)) {
|
||||
if (args.hasArg(options::OPT_enable_library_evolution)) {
|
||||
diags.diagnose(SourceLoc(),
|
||||
diag::error_hermetic_seal_cannot_have_library_evolution);
|
||||
}
|
||||
|
||||
bool ltoOk = false;
|
||||
if (const Arg *A = args.getLastArg(options::OPT_lto)) {
|
||||
StringRef name = A->getValue();
|
||||
if (name == "llvm-thin" || name == "llvm-full") {
|
||||
ltoOk = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ltoOk) {
|
||||
diags.diagnose(SourceLoc(),
|
||||
diag::error_hermetic_seal_requires_lto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform miscellaneous early validation of arguments.
|
||||
static void validateArgs(DiagnosticEngine &diags, const ArgList &args,
|
||||
const llvm::Triple &T) {
|
||||
@@ -294,6 +316,7 @@ static void validateArgs(DiagnosticEngine &diags, const ArgList &args,
|
||||
validateCompilationConditionArgs(diags, args);
|
||||
validateSearchPathArgs(diags, args);
|
||||
validateVerifyIncrementalDependencyArgs(diags, args);
|
||||
validateLinkArgs(diags, args);
|
||||
}
|
||||
|
||||
std::unique_ptr<ToolChain>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "ToolChains.h"
|
||||
|
||||
#include "swift/AST/DiagnosticsDriver.h"
|
||||
#include "swift/Basic/Dwarf.h"
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "swift/Basic/Platform.h"
|
||||
@@ -198,6 +199,13 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
|
||||
inputArgs.MakeArgString(Twine("-stdlib=") + arg->getValue()));
|
||||
}
|
||||
|
||||
if (inputArgs.hasArg(options::OPT_experimental_hermetic_seal_at_link)) {
|
||||
arguments.push_back("-enable-llvm-vfe");
|
||||
arguments.push_back("-enable-llvm-wme");
|
||||
arguments.push_back("-conditional-runtime-records");
|
||||
arguments.push_back("-internalize-at-link");
|
||||
}
|
||||
|
||||
// Handle the CPU and its preferences.
|
||||
inputArgs.AddLastArg(arguments, options::OPT_target_cpu);
|
||||
|
||||
|
||||
19
test/Driver/hermetic-seal.swift
Normal file
19
test/Driver/hermetic-seal.swift
Normal file
@@ -0,0 +1,19 @@
|
||||
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 %s \
|
||||
// RUN: -experimental-hermetic-seal-at-link -lto=llvm-full 2>&1 | %FileCheck %s
|
||||
|
||||
// CHECK: swift
|
||||
// CHECK: -enable-llvm-vfe
|
||||
// CHECK: -enable-llvm-wme
|
||||
// CHECK: -conditional-runtime-records
|
||||
// CHECK: -internalize-at-link
|
||||
// CHECK: -lto=llvm-full
|
||||
|
||||
// RUN: not %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 %s \
|
||||
// RUN: -experimental-hermetic-seal-at-link -enable-library-evolution 2>&1 | %FileCheck %s --check-prefix CHECK-LE
|
||||
|
||||
// CHECK-LE: error: Cannot use -experimental-hermetic-seal-at-link with -enable-library-evolution
|
||||
|
||||
// RUN: not %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 %s \
|
||||
// RUN: -experimental-hermetic-seal-at-link 2>&1 | %FileCheck %s --check-prefix CHECK-NOLTO
|
||||
|
||||
// CHECK-NOLTO: error: -experimental-hermetic-seal-at-link requires -lto=llvm-full or -lto=llvm-thin
|
||||
72
test/IRGen/hermetic-seal-exec.swift
Normal file
72
test/IRGen/hermetic-seal-exec.swift
Normal file
@@ -0,0 +1,72 @@
|
||||
// End-to-end test of -experimental-hermetic-seal-at-link flag.
|
||||
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// (1) Build library swiftmodule
|
||||
// RUN: %target-build-swift %s -DLIBRARY -module-name Library -experimental-hermetic-seal-at-link -lto=llvm-full %lto_flags \
|
||||
// RUN: -Xfrontend -disable-reflection-metadata -Xfrontend -disable-reflection-names -Xfrontend -disable-objc-interop \
|
||||
// RUN: -emit-library -static -o %t/libLibrary.a \
|
||||
// RUN: -emit-module -emit-module-path %t/Library.swiftmodule
|
||||
|
||||
// (2) Check that libLibrary.a does actually provide all its public interfaces
|
||||
// RUN: %llvm-nm %t/libLibrary.a | %FileCheck %s --check-prefix CHECK-NM-LIB
|
||||
|
||||
// (3) Build client
|
||||
// RUN: %target-build-swift %s -DCLIENT -parse-as-library -module-name Main -experimental-hermetic-seal-at-link -lto=llvm-full %lto_flags \
|
||||
// RUN: -Xfrontend -disable-reflection-metadata -Xfrontend -disable-reflection-names -Xfrontend -disable-objc-interop \
|
||||
// RUN: -I%t -L%t -lLibrary -o %t/main
|
||||
|
||||
// (4) Check that unused symbols are not present in final executable
|
||||
// RUN: %llvm-nm %t/main | %FileCheck %s --check-prefix CHECK-NM-EXEC
|
||||
|
||||
// (5) Execute
|
||||
// RUN: %target-run %t/main | %FileCheck %s
|
||||
|
||||
// REQUIRES: executable_test
|
||||
|
||||
// Test disabled until LLVM GlobalDCE supports conditional references.
|
||||
// REQUIRES: rdar81868900
|
||||
|
||||
#if LIBRARY
|
||||
|
||||
// The only symbol that's actually used by client code
|
||||
public func used_func() {
|
||||
print("used_func")
|
||||
}
|
||||
|
||||
public class MyUnusedClass {}
|
||||
public class MyUnusedSubClass: MyUnusedClass {}
|
||||
public protocol MyUnusedProtocol {}
|
||||
public struct MyUnusedStruct {}
|
||||
public struct MyUnusedStruct2: MyUnusedProtocol {}
|
||||
public enum MyUnusedEnum {}
|
||||
public func MyUnusedFunc() {}
|
||||
|
||||
// (2) In libLibrary.a, all exported symbols are present...
|
||||
// CHECK-NM-LIB-DAG: MyUnusedClass
|
||||
// CHECK-NM-LIB-DAG: MyUnusedSubClass
|
||||
// CHECK-NM-LIB-DAG: MyUnusedProtocol
|
||||
// CHECK-NM-LIB-DAG: MyUnusedStruct
|
||||
// CHECK-NM-LIB-DAG: MyUnusedStruct2
|
||||
// CHECK-NM-LIB-DAG: MyUnusedEnum
|
||||
// CHECK-NM-LIB-DAG: MyUnusedFunc
|
||||
|
||||
// (4) ... but after linking the main executable, they are removed.
|
||||
// CHECK-NM-EXEC-NOT: MyUnused
|
||||
|
||||
#endif // LIBRARY
|
||||
|
||||
#if CLIENT
|
||||
|
||||
import Library
|
||||
|
||||
@_cdecl("main")
|
||||
func main() -> Int32 {
|
||||
used_func()
|
||||
print("Done")
|
||||
// CHECK: used_func
|
||||
// CHECK-NEXT: Done
|
||||
return 0
|
||||
}
|
||||
|
||||
#endif // CLIENT
|
||||
Reference in New Issue
Block a user