From 7cda054974094f1e3eed318009d29245324f7334 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Mon, 13 Feb 2023 16:30:30 -0800 Subject: [PATCH] Pass down an optimization level to the Clang linker invocation Resolves rdar://105261863 --- .../Jobs/DarwinToolchain+LinkerSupport.swift | 5 ++++ .../GenericUnixToolchain+LinkerSupport.swift | 5 ++++ .../WebAssemblyToolchain+LinkerSupport.swift | 5 ++++ .../Jobs/WindowsToolchain+LinkerSupport.swift | 5 ++++ .../SwiftDriver/Toolchains/Toolchain.swift | 24 +++++++++++++++++++ Tests/SwiftDriverTests/SwiftDriverTests.swift | 15 ++++++++---- 6 files changed, 54 insertions(+), 5 deletions(-) diff --git a/Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift index 4985d71a5..c718852a6 100644 --- a/Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift @@ -191,6 +191,11 @@ extension DarwinToolchain { commandLine.appendFlag("-fapplication-extension") } + // Pass down an optimization level + if let optArg = mapOptimizationLevelToClangArg(from: &parsedOptions) { + commandLine.appendFlag(optArg) + } + // Linking sanitizers will add rpaths, which might negatively interact when // other rpaths are involved, so we should make sure we add the rpaths after // all user-specified rpaths. diff --git a/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift index a4a735f49..cba8b9ff2 100644 --- a/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift @@ -253,6 +253,11 @@ extension GenericUnixToolchain { commandLine.append(.responseFilePath(linkFile)) } + // Pass down an optimization level + if let optArg = mapOptimizationLevelToClangArg(from: &parsedOptions) { + commandLine.appendFlag(optArg) + } + // Explicitly pass the target to the linker commandLine.appendFlag("--target=\(targetTriple.triple)") diff --git a/Sources/SwiftDriver/Jobs/WebAssemblyToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/WebAssemblyToolchain+LinkerSupport.swift index 70327bb60..255096fb9 100644 --- a/Sources/SwiftDriver/Jobs/WebAssemblyToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/WebAssemblyToolchain+LinkerSupport.swift @@ -125,6 +125,11 @@ extension WebAssemblyToolchain { } commandLine.append(.responseFilePath(linkFilePath)) + // Pass down an optimization level + if let optArg = mapOptimizationLevelToClangArg(from: &parsedOptions) { + commandLine.appendFlag(optArg) + } + // Explicitly pass the target to the linker commandLine.appendFlag("--target=\(targetTriple.triple)") diff --git a/Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift index 8feb7cefe..4f2a9ab67 100644 --- a/Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift @@ -172,6 +172,11 @@ extension WindowsToolchain { commandLine.appendFlag("-stdlib=\(stdlib.asSingle)") } + // Pass down an optimization level + if let optArg = mapOptimizationLevelToClangArg(from: &parsedOptions) { + commandLine.appendFlag(optArg) + } + // FIXME(compnerd) render asan/ubsan runtime link for executables if parsedOptions.contains(.profileGenerate) { diff --git a/Sources/SwiftDriver/Toolchains/Toolchain.swift b/Sources/SwiftDriver/Toolchains/Toolchain.swift index 83fa18f94..a2d97d2b4 100644 --- a/Sources/SwiftDriver/Toolchains/Toolchain.swift +++ b/Sources/SwiftDriver/Toolchains/Toolchain.swift @@ -325,6 +325,30 @@ extension Toolchain { supportsResponseFiles: tool.supportsResponseFiles(in: self) ) } + + /// Maps an optimization level swiftc arg to a corresponding flag for the Clang linker driver invocation + internal func mapOptimizationLevelToClangArg(from parsedOptions: inout ParsedOptions) -> String? { + guard let opt = parsedOptions.getLast(in: .O) else { + return nil + } + let clangArg: String? + switch opt.option { + case .Oplayground: + fallthrough + case .Onone: + clangArg = "-O0" + case .O: + fallthrough + case .Ounchecked: + clangArg = "-O3" + case .Osize: + clangArg = "-Os" + default: + clangArg = nil + assert(false, "Unhandled Optimization Mode: \(opt.description)") + } + return clangArg + } } @_spi(Testing) public enum ToolchainError: Swift.Error { diff --git a/Tests/SwiftDriverTests/SwiftDriverTests.swift b/Tests/SwiftDriverTests/SwiftDriverTests.swift index b94699fa9..6b1628732 100644 --- a/Tests/SwiftDriverTests/SwiftDriverTests.swift +++ b/Tests/SwiftDriverTests/SwiftDriverTests.swift @@ -1666,7 +1666,7 @@ final class SwiftDriverTests: XCTestCase { do { // macOS target - var driver = try Driver(args: commonArgs + ["-emit-library", "-target", "x86_64-apple-macosx10.15", "-use-ld=foo"], env: env) + var driver = try Driver(args: commonArgs + ["-emit-library", "-target", "x86_64-apple-macosx10.15", "-Onone", "-use-ld=foo"], env: env) let plannedJobs = try driver.planBuild() XCTAssertEqual(3, plannedJobs.count) @@ -1685,6 +1685,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertFalse(cmd.contains(.flag("-shared"))) // Handling of '-lobjc' is now in the Clang linker driver. XCTAssertFalse(cmd.contains(.flag("-lobjc"))) + XCTAssertTrue(cmd.contains(.flag("-O0"))) } do { @@ -1952,12 +1953,13 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(linkJob1?.commandLine.contains(.flag("-flto=thin"))) #endif - var driver2 = try Driver(args: commonArgs + ["-emit-executable", "-target", "x86_64-unknown-linux", "-lto=llvm-thin"], env: env) + var driver2 = try Driver(args: commonArgs + ["-emit-executable", "-O", "-target", "x86_64-unknown-linux", "-lto=llvm-thin"], env: env) let plannedJobs2 = try driver2.planBuild() XCTAssertFalse(plannedJobs2.contains(where: { $0.kind == .autolinkExtract })) let linkJob2 = plannedJobs2.first(where: { $0.kind == .link }) XCTAssertTrue(linkJob2?.tool.name.contains("clang")) XCTAssertTrue(linkJob2?.commandLine.contains(.flag("-flto=thin"))) + XCTAssertTrue(linkJob2?.commandLine.contains(.flag("-O3"))) var driver3 = try Driver(args: commonArgs + ["-emit-executable", "-target", "x86_64-unknown-linux", "-lto=llvm-full"], env: env) let plannedJobs3 = try driver3.planBuild() @@ -1972,7 +1974,7 @@ final class SwiftDriverTests: XCTestCase { } do { - var driver = try Driver(args: commonArgs + ["-emit-executable", "-emit-module", "-g", "-target", "x86_64-apple-macosx10.15"], env: env) + var driver = try Driver(args: commonArgs + ["-emit-executable", "-Onone", "-emit-module", "-g", "-target", "x86_64-apple-macosx10.15"], env: env) let plannedJobs = try driver.planBuild() XCTAssertEqual(5, plannedJobs.count) XCTAssertEqual(plannedJobs.map(\.kind), [.emitModule, .compile, .compile, .link, .generateDSYM]) @@ -1985,6 +1987,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(commandContainsTemporaryPath(cmd, "foo.o")) XCTAssertTrue(commandContainsTemporaryPath(cmd, "bar.o")) XCTAssertTrue(cmd.contains(.joinedOptionAndPath("-Wl,-add_ast_path,", .relative(.init("Test.swiftmodule"))))) + XCTAssertTrue(cmd.contains(.flag("-O0"))) XCTAssertEqual(linkJob.outputs[0].file, try VirtualPath(path: "Test")) XCTAssertFalse(cmd.contains(.flag("-static"))) @@ -2057,7 +2060,7 @@ final class SwiftDriverTests: XCTestCase { #if os(Linux) do { // executable linking linux static stdlib - var driver = try Driver(args: commonArgs + ["-emit-executable", "-static-stdlib", "-target", "x86_64-unknown-linux"], env: env) + var driver = try Driver(args: commonArgs + ["-emit-executable", "-Osize", "-static-stdlib", "-target", "x86_64-unknown-linux"], env: env) let plannedJobs = try driver.planBuild() XCTAssertEqual(plannedJobs.count, 4) @@ -2077,6 +2080,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(commandContainsTemporaryPath(cmd, "bar.o")) XCTAssertTrue(cmd.contains(.flag("--start-group"))) XCTAssertTrue(cmd.contains(.flag("--end-group"))) + XCTAssertTrue(cmd.contains(.flag("-Os"))) XCTAssertEqual(linkJob.outputs[0].file, try VirtualPath(path: "Test")) XCTAssertFalse(cmd.contains(.flag("-static"))) @@ -2119,7 +2123,7 @@ final class SwiftDriverTests: XCTestCase { try localFileSystem.writeFileContents( path.appending(components: "wasi", "static-executable-args.lnk")) { $0 <<< "garbage" } // WASM executable linking - var driver = try Driver(args: commonArgs + ["-emit-executable", + var driver = try Driver(args: commonArgs + ["-emit-executable", "-Ounchecked", "-target", "wasm32-unknown-wasi", "-resource-dir", path.pathString, "-sdk", "/sdk/path"], env: env) @@ -2144,6 +2148,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(commandContainsTemporaryPath(cmd, "bar.o")) XCTAssertTrue(commandContainsTemporaryResponsePath(cmd, "Test.autolink")) XCTAssertTrue(cmd.contains(.responseFilePath(.absolute(path.appending(components: "wasi", "static-executable-args.lnk"))))) + XCTAssertTrue(cmd.contains(.flag("-O3"))) XCTAssertEqual(linkJob.outputs[0].file, try VirtualPath(path: "Test")) XCTAssertFalse(cmd.contains(.flag("-dylib")))