diff --git a/Sources/SwiftDriver/Driver/Driver.swift b/Sources/SwiftDriver/Driver/Driver.swift index db11ab3cc..9e856531c 100644 --- a/Sources/SwiftDriver/Driver/Driver.swift +++ b/Sources/SwiftDriver/Driver/Driver.swift @@ -2751,7 +2751,7 @@ extension Driver { } // Check that we're one of the known supported targets for sanitizers. - if !(targetTriple.isWindows || targetTriple.isDarwin || targetTriple.os == .linux) { + if !(targetTriple.isWindows || targetTriple.isDarwin || targetTriple.os == .linux || targetTriple.os == .wasi) { diagnosticEngine.emit( .error_unsupported_opt_for_target( arg: "-sanitize=", diff --git a/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift index ab4cfe0f4..f2fad3ad0 100644 --- a/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift @@ -26,12 +26,7 @@ extension Toolchain { for targetInfo: FrontendTargetInfo, parsedOptions: inout ParsedOptions ) throws -> VirtualPath { - var platform = targetInfo.target.triple.platformName(conflatingDarwin: true)! - // compiler-rt moved these Android sanitizers into `lib/linux/` a couple - // years ago, llvm/llvm-project@a68ccba, so look for them there instead. - if platform == "android" { - platform = "linux" - } + let platform = targetInfo.target.triple.clangOSLibName // NOTE(compnerd) Windows uses the per-target runtime directory for the // Windows runtimes. This should also be done for the other platforms, but diff --git a/Sources/SwiftDriver/Jobs/WebAssemblyToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/WebAssemblyToolchain+LinkerSupport.swift index 3ea3a2709..aee547b52 100644 --- a/Sources/SwiftDriver/Jobs/WebAssemblyToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/WebAssemblyToolchain+LinkerSupport.swift @@ -165,8 +165,12 @@ extension WebAssemblyToolchain { // Delegate to Clang for sanitizers. It will figure out the correct linker // options. - guard sanitizers.isEmpty else { - throw Error.sanitizersUnsupportedForTarget(targetTriple.triple) + if linkerOutputType == .executable && !sanitizers.isEmpty { + let sanitizerNames = sanitizers + .map { $0.rawValue } + .sorted() // Sort so we get a stable, testable order + .joined(separator: ",") + commandLine.appendFlag("-fsanitize=\(sanitizerNames)") } if parsedOptions.hasArgument(.profileGenerate) { diff --git a/Sources/SwiftDriver/Toolchains/WebAssemblyToolchain.swift b/Sources/SwiftDriver/Toolchains/WebAssemblyToolchain.swift index 25cdb90c0..8db1558dc 100644 --- a/Sources/SwiftDriver/Toolchains/WebAssemblyToolchain.swift +++ b/Sources/SwiftDriver/Toolchains/WebAssemblyToolchain.swift @@ -140,7 +140,12 @@ public final class WebAssemblyToolchain: Toolchain { targetTriple: Triple, isShared: Bool ) throws -> String { - throw Error.sanitizersUnsupportedForTarget(targetTriple.triple) + switch sanitizer { + case .address: + return "libclang_rt.\(sanitizer.libraryName)-\(targetTriple.archName).a" + default: + throw Error.sanitizersUnsupportedForTarget(targetTriple.triple) + } } public func platformSpecificInterpreterEnvironmentVariables(env: [String : String], diff --git a/Sources/SwiftDriver/Utilities/Triple+Platforms.swift b/Sources/SwiftDriver/Utilities/Triple+Platforms.swift index 0841046ae..d66c17314 100644 --- a/Sources/SwiftDriver/Utilities/Triple+Platforms.swift +++ b/Sources/SwiftDriver/Utilities/Triple+Platforms.swift @@ -303,7 +303,28 @@ extension Triple { } } - /// The platform name, i.e. the name clang uses to identify this target in its + + /// The "os" component of the Clang compiler resource library directory (`/lib/`). + /// Must be kept in sync with Clang driver: + /// https://github.com/llvm/llvm-project/blob/llvmorg-20.1.4/clang/lib/Driver/ToolChain.cpp#L690 + @_spi(Testing) public var clangOSLibName: String { + guard let os else { + return osName + } + if os.isDarwin { + return "darwin" + } + + switch os { + case .freeBSD: return "freebsd" + case .netbsd: return "netbsd" + case .openbsd: return "openbsd" + case .aix: return "aix" + default: return osName + } + } + + /// The platform name, i.e. the name Swift uses to identify this target in its /// resource directory. /// /// - Parameter conflatingDarwin: If true, all Darwin platforms will be diff --git a/Tests/SwiftDriverTests/SwiftDriverTests.swift b/Tests/SwiftDriverTests/SwiftDriverTests.swift index e3779ee48..fccc3d969 100644 --- a/Tests/SwiftDriverTests/SwiftDriverTests.swift +++ b/Tests/SwiftDriverTests/SwiftDriverTests.swift @@ -2877,6 +2877,47 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=address"))) } #endif + + func checkWASITarget(target: String, clangOSDir: String) throws { + try withTemporaryDirectory { resourceDir in + var env = ProcessEnv.vars + env["SWIFT_DRIVER_SWIFT_AUTOLINK_EXTRACT_EXEC"] = "/garbage/swift-autolink-extract" + + let asanRuntimeLibPath = resourceDir.appending(components: [ + "clang", "lib", clangOSDir, "libclang_rt.asan-wasm32.a" + ]) + try localFileSystem.writeFileContents(asanRuntimeLibPath) { + $0.send("garbage") + } + try localFileSystem.writeFileContents(resourceDir.appending(components: "wasi", "static-executable-args.lnk")) { + $0.send("garbage") + } + + var driver = try Driver( + args: commonArgs + [ + "-target", target, "-sanitize=address", + "-resource-dir", resourceDir.pathString + ], + env: env + ) + let plannedJobs = try driver.planBuild() + + XCTAssertEqual(plannedJobs.count, 4) + + let compileJob = plannedJobs[0] + let compileCmd = compileJob.commandLine + XCTAssertTrue(compileCmd.contains(.flag("-sanitize=address"))) + + let linkJob = plannedJobs[3] + let linkCmd = linkJob.commandLine + XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=address"))) + } + } + do { + try checkWASITarget(target: "wasm32-unknown-wasi", clangOSDir: "wasi") + try checkWASITarget(target: "wasm32-unknown-wasip1", clangOSDir: "wasip1") + try checkWASITarget(target: "wasm32-unknown-wasip1-threads", clangOSDir: "wasip1") + } } func testSanitizerCoverageArgs() throws { diff --git a/Tests/SwiftDriverTests/TripleTests.swift b/Tests/SwiftDriverTests/TripleTests.swift index 311e77fc4..ff037d26e 100644 --- a/Tests/SwiftDriverTests/TripleTests.swift +++ b/Tests/SwiftDriverTests/TripleTests.swift @@ -1317,6 +1317,15 @@ final class TripleTests: XCTestCase { shouldHaveJetPacks: true) } + func testClangOSLibName() { + XCTAssertEqual("darwin", Triple("x86_64-apple-macosx").clangOSLibName) + XCTAssertEqual("darwin", Triple("arm64-apple-ios13.0").clangOSLibName) + XCTAssertEqual("linux", Triple("aarch64-unknown-linux-android24").clangOSLibName) + XCTAssertEqual("wasi", Triple("wasm32-unknown-wasi").clangOSLibName) + XCTAssertEqual("wasip1", Triple("wasm32-unknown-wasip1-threads").clangOSLibName) + XCTAssertEqual("none", Triple("arm64-unknown-none").clangOSLibName) + } + func testToolchainSelection() { let diagnostics = DiagnosticsEngine() struct None { }