Skip to content

Commit 2b5add9

Browse files
authored
Merge pull request #1657 from hamishknight/windows-coverage-6.0
[6.0] Pass `-lld-allow-duplicate-weak` for coverage on Windows
2 parents 5fa2596 + 73160aa commit 2b5add9

File tree

2 files changed

+101
-11
lines changed

2 files changed

+101
-11
lines changed

Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,41 @@ extension WindowsToolchain {
3939
sanitizers: Set<Sanitizer>,
4040
targetInfo: FrontendTargetInfo)
4141
throws -> ResolvedTool {
42+
// Check to see whether we need to use lld as the linker.
43+
let requiresLLD = {
44+
if let ld = parsedOptions.getLastArgument(.useLd)?.asSingle {
45+
switch ld {
46+
case "lld", "lld.exe", "lld-link", "lld-link.exe":
47+
return true
48+
default:
49+
return false
50+
}
51+
}
52+
if lto != nil {
53+
return true
54+
}
55+
// Profiling currently relies on the ability to emit duplicate weak
56+
// symbols across translation units and having the linker coalesce them.
57+
// Unfortunately link.exe does not support this, so require lld-link
58+
// for now, which supports the behavior via a flag.
59+
// TODO: Once we've changed coverage to no longer rely on emitting
60+
// duplicate weak symbols (rdar://131295678), we can remove this.
61+
if parsedOptions.hasArgument(.profileGenerate) {
62+
return true
63+
}
64+
return false
65+
}()
66+
4267
// Special case static linking as clang cannot drive the operation.
4368
if linkerOutputType == .staticLibrary {
4469
let librarian: String
45-
switch parsedOptions.getLastArgument(.useLd)?.asSingle {
46-
case .none:
47-
librarian = lto == nil ? "link" : "lld-link"
48-
case .some("lld"), .some("lld.exe"), .some("lld-link"), .some("lld-link.exe"):
70+
if requiresLLD {
4971
librarian = "lld-link"
50-
case let .some(linker):
51-
librarian = linker
72+
} else if let ld = parsedOptions.getLastArgument(.useLd)?.asSingle {
73+
librarian = ld
74+
} else {
75+
librarian = "link"
5276
}
53-
5477
commandLine.appendFlag("/LIB")
5578
commandLine.appendFlag("/NOLOGO")
5679
commandLine.appendFlag("/OUT:\(outputFile.name.spm_shellEscaped())")
@@ -99,9 +122,9 @@ extension WindowsToolchain {
99122
}
100123

101124
// Select the linker to use.
102-
if let arg = parsedOptions.getLastArgument(.useLd) {
103-
commandLine.appendFlag("-fuse-ld=\(arg.asSingle)")
104-
} else if lto != nil {
125+
if let arg = parsedOptions.getLastArgument(.useLd)?.asSingle {
126+
commandLine.appendFlag("-fuse-ld=\(arg)")
127+
} else if requiresLLD {
105128
commandLine.appendFlag("-fuse-ld=lld")
106129
}
107130

@@ -195,6 +218,13 @@ extension WindowsToolchain {
195218
// FIXME(compnerd) wrap llvm::getInstrProfRuntimeHookVarName()
196219
commandLine.appendFlag("-include:__llvm_profile_runtime")
197220
commandLine.appendFlag("-lclang_rt.profile")
221+
222+
// FIXME(rdar://131295678): Currently profiling requires the ability to
223+
// emit duplicate weak symbols. Assuming we're using lld, pass
224+
// -lld-allow-duplicate-weak to enable this behavior.
225+
if requiresLLD {
226+
commandLine.appendFlags("-Xlinker", "-lld-allow-duplicate-weak")
227+
}
198228
}
199229

200230
try addExtraClangLinkerArgs(to: &commandLine, parsedOptions: &parsedOptions)

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4373,7 +4373,67 @@ final class SwiftDriverTests: XCTestCase {
43734373
}
43744374
#endif
43754375

4376-
// TODO: Windows
4376+
for explicitUseLd in [true, false] {
4377+
var args = ["swiftc", "-profile-generate", "-target", "x86_64-unknown-windows-msvc", "test.swift"]
4378+
if explicitUseLd {
4379+
// Explicitly passing '-use-ld=lld' should still result in '-lld-allow-duplicate-weak'.
4380+
args.append("-use-ld=lld")
4381+
}
4382+
var driver = try Driver(args: args)
4383+
let plannedJobs = try driver.planBuild()
4384+
print(plannedJobs[1].commandLine)
4385+
4386+
XCTAssertEqual(plannedJobs.count, 2)
4387+
XCTAssertEqual(plannedJobs[0].kind, .compile)
4388+
4389+
XCTAssertEqual(plannedJobs[1].kind, .link)
4390+
4391+
let linkCmds = plannedJobs[1].commandLine
4392+
XCTAssert(linkCmds.contains(.flag("-include:__llvm_profile_runtime")))
4393+
XCTAssert(linkCmds.contains(.flag("-lclang_rt.profile")))
4394+
4395+
// rdar://131295678 - Make sure we force the use of lld and pass
4396+
// '-lld-allow-duplicate-weak'.
4397+
XCTAssert(linkCmds.contains(.flag("-fuse-ld=lld")))
4398+
XCTAssert(linkCmds.contains([.flag("-Xlinker"), .flag("-lld-allow-duplicate-weak")]))
4399+
}
4400+
4401+
do {
4402+
// If the user passes -use-ld for a non-lld linker, respect that and
4403+
// don't use '-lld-allow-duplicate-weak'
4404+
var driver = try Driver(args: ["swiftc", "-profile-generate", "-use-ld=link", "-target", "x86_64-unknown-windows-msvc", "test.swift"])
4405+
let plannedJobs = try driver.planBuild()
4406+
print(plannedJobs[1].commandLine)
4407+
4408+
XCTAssertEqual(plannedJobs.count, 2)
4409+
XCTAssertEqual(plannedJobs[0].kind, .compile)
4410+
4411+
XCTAssertEqual(plannedJobs[1].kind, .link)
4412+
4413+
let linkCmds = plannedJobs[1].commandLine
4414+
XCTAssert(linkCmds.contains(.flag("-include:__llvm_profile_runtime")))
4415+
XCTAssert(linkCmds.contains(.flag("-lclang_rt.profile")))
4416+
4417+
XCTAssertTrue(linkCmds.contains(.flag("-fuse-ld=link")))
4418+
XCTAssertFalse(linkCmds.contains(.flag("-fuse-ld=lld")))
4419+
XCTAssertFalse(linkCmds.contains(.flag("-lld-allow-duplicate-weak")))
4420+
}
4421+
4422+
do {
4423+
// If we're not building for profiling, don't add '-lld-allow-duplicate-weak'.
4424+
var driver = try Driver(args: ["swiftc", "-use-ld=lld", "-target", "x86_64-unknown-windows-msvc", "test.swift"])
4425+
let plannedJobs = try driver.planBuild()
4426+
print(plannedJobs[1].commandLine)
4427+
4428+
XCTAssertEqual(plannedJobs.count, 2)
4429+
XCTAssertEqual(plannedJobs[0].kind, .compile)
4430+
4431+
XCTAssertEqual(plannedJobs[1].kind, .link)
4432+
4433+
let linkCmds = plannedJobs[1].commandLine
4434+
XCTAssertTrue(linkCmds.contains(.flag("-fuse-ld=lld")))
4435+
XCTAssertFalse(linkCmds.contains(.flag("-lld-allow-duplicate-weak")))
4436+
}
43774437
}
43784438

43794439
func testConditionalCompilationArgValidation() throws {

0 commit comments

Comments
 (0)