Skip to content

Commit ad92fee

Browse files
committed
Update Options.swift
1 parent acbb3b0 commit ad92fee

File tree

5 files changed

+257
-22
lines changed

5 files changed

+257
-22
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3341,21 +3341,25 @@ extension Driver {
33413341
let genFlags: [Option] = [
33423342
.profileGenerate,
33433343
.irProfileGenerate,
3344+
.irProfileGenerateEQ,
33443345
.csProfileGenerate,
3345-
.csProfileGenerateEq,
3346+
.csProfileGenerateEQ,
33463347
]
3348+
func resolveDualFormConflict(_ plain: Option, _ equalsForm: Option) {
3349+
if parsedOptions.hasArgument(plain),
3350+
parsedOptions.hasArgument(equalsForm)
3351+
{
3352+
diagnosticEngine.emit(
3353+
.error(Error.conflictingOptions(plain, equalsForm)),
3354+
location: nil
3355+
)
3356+
providedGen.removeAll { $0 == equalsForm }
3357+
}
3358+
}
33473359

33483360
var providedGen = genFlags.filter { parsedOptions.hasArgument($0) }
3349-
if parsedOptions.hasArgument(.csProfileGenerate),
3350-
parsedOptions.hasArgument(.csProfileGenerateEq)
3351-
{
3352-
// If both forms were specified, report a clear conflict.
3353-
diagnosticEngine.emit(
3354-
.error(Error.conflictingOptions(.csProfileGenerate, .csProfileGenerateEq)),
3355-
location: nil
3356-
)
3357-
providedGen.removeAll { $0 == .csProfileGenerateEq }
3358-
}
3361+
resolveDualFormConflict(.irProfileGenerate, .irProfileGenerateEQ)
3362+
resolveDualFormConflict(.csProfileGenerate, .csProfileGenerateEQ)
33593363

33603364
guard providedGen.count >= 2 else { return }
33613365
for i in 1..<providedGen.count {
@@ -3371,10 +3375,12 @@ extension Driver {
33713375
let conflictingGenFlags: [Option] = [
33723376
.profileGenerate,
33733377
.irProfileGenerate,
3378+
.irProfileGenerateEQ,
33743379
]
33753380
let useProfArgs: [Option] = [
33763381
.profileUse,
33773382
.profileSampleUse,
3383+
.irProfileUse
33783384
]
33793385
let providedUse = useProfArgs.filter { parsedOptions.hasArgument($0) }
33803386
guard !providedUse.isEmpty else { return }
@@ -3439,6 +3445,10 @@ extension Driver {
34393445
if let profileSampleUseArg = parsedOptions.getLastArgument(.profileSampleUse)?.asSingle {
34403446
checkForMissingProfilingData([profileSampleUseArg])
34413447
}
3448+
3449+
if let irProfileUseArgs = parsedOptions.getLastArgument(.irProfileUse)?.asMultiple {
3450+
checkForMissingProfilingData(irProfileUseArgs)
3451+
}
34423452
}
34433453

34443454
static func validateParseableOutputArgs(_ parsedOptions: inout ParsedOptions,

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,10 @@ extension Driver {
244244
try commandLine.appendLast(.suppressWarnings, from: &parsedOptions)
245245
try commandLine.appendLast(.profileGenerate, from: &parsedOptions)
246246
try commandLine.appendLast(.irProfileGenerate, from: &parsedOptions)
247+
try commandLine.appendLast(.irProfileGenerateEQ, from: &parsedOptions)
248+
try commandLine.appendLast(.irProfileUse, from: &parsedOptions)
247249
try commandLine.appendLast(.csProfileGenerate, from: &parsedOptions)
248-
try commandLine.appendLast(.csProfileGenerateEq, from: &parsedOptions)
250+
try commandLine.appendLast(.csProfileGenerateEQ, from: &parsedOptions)
249251
try commandLine.appendLast(.profileUse, from: &parsedOptions)
250252
try commandLine.appendLast(.profileCoverageMapping, from: &parsedOptions)
251253
try commandLine.appendLast(.debugInfoForProfiling, from: &parsedOptions)

Sources/SwiftDriver/Toolchains/Toolchain.swift

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,23 +384,34 @@ extension Toolchain {
384384
args.append("-fprofile-generate")
385385
}
386386

387+
if options.contains(.irProfileGenerateEQ),
388+
let path = options.getLastArgument(.irProfileGenerateEQ)?.asSingle {
389+
args.append("-fprofile-generate=\(path)")
390+
}
391+
387392
if options.contains(.csProfileGenerate) {
388393
args.append("-fcs-profile-generate")
389394
}
390395

391-
if options.contains(.csProfileGenerateEq),
392-
let path = options.getLastArgument(.csProfileGenerateEq)?.asSingle {
396+
if options.contains(.csProfileGenerateEQ),
397+
let path = options.getLastArgument(.csProfileGenerateEQ)?.asSingle {
393398
args.append("-fcs-profile-generate=\(path)")
394399
}
395400

401+
if options.contains(.irProfileUse),
402+
let path = options.getLastArgument(.irProfileUse)?.asMultiple.last {
403+
args.append("-fprofile-use=\(path)")
404+
}
405+
396406
return args
397407
}
398408

399409
internal func needsInstrumentedProfile(from parsedOptions: inout ParsedOptions) -> Bool {
400410
parsedOptions.contains(.profileGenerate) ||
401411
parsedOptions.contains(.irProfileGenerate) ||
412+
parsedOptions.contains(.irProfileGenerateEQ) ||
402413
parsedOptions.contains(.csProfileGenerate) ||
403-
parsedOptions.contains(.csProfileGenerateEq)
414+
parsedOptions.contains(.csProfileGenerateEQ)
404415
}
405416
}
406417

Sources/SwiftOptions/Options.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -804,9 +804,6 @@ extension Option {
804804
public static let printZeroStats: Option = Option("-print-zero-stats", .flag, attributes: [.helpHidden, .frontend], helpText: "Prints all stats even if they are zero")
805805
public static let profileCoverageMapping: Option = Option("-profile-coverage-mapping", .flag, attributes: [.frontend, .noInteractive], helpText: "Generate coverage data for use with profiled execution counts")
806806
public static let profileGenerate: Option = Option("-profile-generate", .flag, attributes: [.frontend, .noInteractive], helpText: "Generate instrumented code to collect execution counts")
807-
public static let irProfileGenerate: Option = Option("-ir-profile-generate", .flag, attributes: [.frontend, .noInteractive], helpText: "Generate instrumented code to collect execution counts into default.profraw (overridden by LLVM_PROFILE_FILE env var)")
808-
public static let csProfileGenerate: Option = Option("-cs-profile-generate", .flag, attributes: [.frontend, .noInteractive], helpText: "Generate instrumented code to collect context sensitive execution counts into default.profraw (overridden by LLVM_PROFILE_FILE env var)")
809-
public static let csProfileGenerateEq: Option = Option("-cs-profile-generate=", .joined, attributes: [.frontend, .noInteractive, .argumentIsPath], metaVar: "<dir>", helpText: "Generate instrumented code to collect context sensitive execution counts into <directory>/default.profraw (overridden by LLVM_PROFILE_FILE env var)")
810807
public static let profileSampleUse: Option = Option("-profile-sample-use=", .joined, attributes: [.frontend, .noInteractive, .argumentIsPath], metaVar: "<profile data>", helpText: "Supply sampling-based profiling data from llvm-profdata to enable profile-guided optimization")
811808
public static let profileStatsEntities: Option = Option("-profile-stats-entities", .flag, attributes: [.helpHidden, .frontend], helpText: "Profile changes to stats in -stats-output-dir, subdivided by source entity")
812809
public static let profileStatsEvents: Option = Option("-profile-stats-events", .flag, attributes: [.helpHidden, .frontend], helpText: "Profile changes to stats in -stats-output-dir")
@@ -1818,9 +1815,6 @@ extension Option {
18181815
Option.printZeroStats,
18191816
Option.profileCoverageMapping,
18201817
Option.profileGenerate,
1821-
Option.irProfileGenerate,
1822-
Option.csProfileGenerate,
1823-
Option.csProfileGenerateEq,
18241818
Option.profileSampleUse,
18251819
Option.profileStatsEntities,
18261820
Option.profileStatsEvents,

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 219 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4911,6 +4911,10 @@ final class SwiftDriverTests: XCTestCase {
49114911
$1.expect(.error(Driver.Error.missingProfilingData(try toPath("profile.profdata").name)))
49124912
}
49134913

4914+
try assertDriverDiagnostics(args: ["swiftc", "foo.swift", "-ir-profile-use=profile.profdata"]) {
4915+
$1.expect(.error(Driver.Error.missingProfilingData(try toPath("profile.profdata").name)))
4916+
}
4917+
49144918
try withTemporaryDirectory { path in
49154919
try localFileSystem.writeFileContents(path.appending(component: "profile.profdata"), bytes: .init())
49164920
try assertNoDriverDiagnostics(args: "swiftc", "-working-directory", path.pathString, "foo.swift", "-profile-use=profile.profdata")
@@ -4934,15 +4938,40 @@ final class SwiftDriverTests: XCTestCase {
49344938
$1.expect(.error(Driver.Error.conflictingOptions(.profileGenerate, .irProfileGenerate)))
49354939
}
49364940

4941+
try withTemporaryDirectory { directoryPath in
4942+
try assertDriverDiagnostics(args: ["swiftc", "foo.swift", "-profile-generate", "-ir-profile-generate=\(directoryPath)"]) {
4943+
$1.expect(.error(Driver.Error.conflictingOptions(.profileGenerate, .irProfileGenerateEQ)))
4944+
}
4945+
}
4946+
49374947
try assertDriverDiagnostics(args: ["swiftc", "foo.swift", "-ir-profile-generate", "-cs-profile-generate"]) {
49384948
$1.expect(.error(Driver.Error.conflictingOptions(.irProfileGenerate, .csProfileGenerate)))
49394949
}
49404950

49414951
try withTemporaryDirectory { directoryPath in
49424952
try assertDriverDiagnostics(args: ["swiftc", "foo.swift", "-ir-profile-generate", "-cs-profile-generate=\(directoryPath)"]) {
4943-
$1.expect(.error(Driver.Error.conflictingOptions(.irProfileGenerate, .csProfileGenerateEq)))
4953+
$1.expect(.error(Driver.Error.conflictingOptions(.irProfileGenerate, .csProfileGenerateEQ)))
4954+
}
4955+
}
4956+
4957+
try withTemporaryDirectory { directoryPath in
4958+
try assertDriverDiagnostics(args: ["swiftc", "foo.swift", "-ir-profile-generate=\(directoryPath)", "-cs-profile-generate=\(directoryPath)"]) {
4959+
$1.expect(.error(Driver.Error.conflictingOptions(.irProfileGenerateEQ, .csProfileGenerateEQ)))
4960+
}
4961+
}
4962+
4963+
try withTemporaryDirectory { directoryPath in
4964+
try assertDriverDiagnostics(args: ["swiftc", "foo.swift", "-cs-profile-generate", "-cs-profile-generate=\(directoryPath)"]) {
4965+
$1.expect(.error(Driver.Error.conflictingOptions(.csProfileGenerate, .csProfileGenerateEQ)))
4966+
}
4967+
}
4968+
4969+
try withTemporaryDirectory { directoryPath in
4970+
try assertDriverDiagnostics(args: ["swiftc", "foo.swift", "-ir-profile-generate", "-ir-profile-generate=\(directoryPath)"]) {
4971+
$1.expect(.error(Driver.Error.conflictingOptions(.irProfileGenerate, .irProfileGenerateEQ)))
49444972
}
49454973
}
4974+
49464975
}
49474976

49484977
func testProfileSampleUseFrontendFlags() throws {
@@ -5356,6 +5385,195 @@ final class SwiftDriverTests: XCTestCase {
53565385
}
53575386
}
53585387

5388+
func testIRProfileEqLinkerArgs() throws {
5389+
var envVars = ProcessEnv.block
5390+
envVars["SWIFT_DRIVER_LD_EXEC"] = ld.nativePathString(escaped: false)
5391+
try withTemporaryDirectory { directoryPath in
5392+
do {
5393+
var driver = try Driver(args: ["swiftc", "-ir-profile-generate=\(directoryPath)", "-target", "x86_64-apple-macosx10.9", "test.swift"],
5394+
env: envVars)
5395+
let plannedJobs = try driver.planBuild()
5396+
5397+
XCTAssertEqual(plannedJobs.count, 2)
5398+
XCTAssertEqual(plannedJobs[0].kind, .compile)
5399+
5400+
XCTAssertEqual(plannedJobs[1].kind, .link)
5401+
XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate=\(directoryPath)")))
5402+
}
5403+
5404+
do {
5405+
var driver = try Driver(args: ["swiftc", "-ir-profile-generate=\(directoryPath)", "-target", "x86_64-apple-ios7.1-simulator", "test.swift"],
5406+
env: envVars)
5407+
let plannedJobs = try driver.planBuild()
5408+
5409+
XCTAssertEqual(plannedJobs.count, 2)
5410+
XCTAssertEqual(plannedJobs[0].kind, .compile)
5411+
5412+
XCTAssertEqual(plannedJobs[1].kind, .link)
5413+
XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate=\(directoryPath)")))
5414+
}
5415+
5416+
do {
5417+
var driver = try Driver(args: ["swiftc", "-ir-profile-generate=\(directoryPath)", "-target", "arm64-apple-ios7.1", "test.swift"],
5418+
env: envVars)
5419+
let plannedJobs = try driver.planBuild()
5420+
5421+
XCTAssertEqual(plannedJobs.count, 2)
5422+
XCTAssertEqual(plannedJobs[0].kind, .compile)
5423+
5424+
XCTAssertEqual(plannedJobs[1].kind, .link)
5425+
XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate=\(directoryPath)")))
5426+
}
5427+
5428+
do {
5429+
var driver = try Driver(args: ["swiftc", "-ir-profile-generate=\(directoryPath)", "-target", "x86_64-apple-tvos9.0-simulator", "test.swift"],
5430+
env: envVars)
5431+
let plannedJobs = try driver.planBuild()
5432+
5433+
XCTAssertEqual(plannedJobs.count, 2)
5434+
XCTAssertEqual(plannedJobs[0].kind, .compile)
5435+
5436+
XCTAssertEqual(plannedJobs[1].kind, .link)
5437+
XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate=\(directoryPath)")))
5438+
}
5439+
5440+
do {
5441+
var driver = try Driver(args: ["swiftc", "-ir-profile-generate=\(directoryPath)", "-target", "arm64-apple-tvos9.0", "test.swift"],
5442+
env: envVars)
5443+
let plannedJobs = try driver.planBuild()
5444+
5445+
XCTAssertEqual(plannedJobs.count, 2)
5446+
XCTAssertEqual(plannedJobs[0].kind, .compile)
5447+
5448+
XCTAssertEqual(plannedJobs[1].kind, .link)
5449+
XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate=\(directoryPath)")))
5450+
}
5451+
5452+
do {
5453+
var driver = try Driver(args: ["swiftc", "-ir-profile-generate=\(directoryPath)", "-target", "i386-apple-watchos2.0-simulator", "test.swift"],
5454+
env: envVars)
5455+
let plannedJobs = try driver.planBuild()
5456+
5457+
XCTAssertEqual(plannedJobs.count, 2)
5458+
XCTAssertEqual(plannedJobs[0].kind, .compile)
5459+
5460+
XCTAssertEqual(plannedJobs[1].kind, .link)
5461+
XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate=\(directoryPath)")))
5462+
}
5463+
5464+
do {
5465+
var driver = try Driver(args: ["swiftc", "-ir-profile-generate=\(directoryPath)", "-target", "armv7k-apple-watchos2.0", "test.swift"],
5466+
env: envVars)
5467+
let plannedJobs = try driver.planBuild()
5468+
5469+
XCTAssertEqual(plannedJobs.count, 2)
5470+
XCTAssertEqual(plannedJobs[0].kind, .compile)
5471+
5472+
XCTAssertEqual(plannedJobs[1].kind, .link)
5473+
XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate=\(directoryPath)")))
5474+
}
5475+
5476+
// FIXME: This will fail when run on macOS, because
5477+
// swift-autolink-extract is not present
5478+
#if os(Linux) || os(Android) || os(Windows)
5479+
for triple in ["aarch64-unknown-linux-android", "x86_64-unknown-linux-gnu"] {
5480+
var driver = try Driver(args: ["swiftc", "-ir-profile-generate=\(directoryPath)", "-target", triple, "test.swift"])
5481+
let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs()
5482+
5483+
XCTAssertEqual(plannedJobs.count, 2)
5484+
XCTAssertEqual(plannedJobs[0].kind, .compile)
5485+
5486+
XCTAssertEqual(plannedJobs[1].kind, .link)
5487+
if triple == "aarch64-unknown-linux-android" {
5488+
XCTAssert(plannedJobs[1].commandLine.containsPathWithBasename("libclang_rt.profile-aarch64-android.a"))
5489+
} else {
5490+
XCTAssert(plannedJobs[1].commandLine.containsPathWithBasename("libclang_rt.profile-x86_64.a"))
5491+
}
5492+
XCTAssert(plannedJobs[1].commandLine.contains { $0 == .flag("-u__llvm_profile_runtime") })
5493+
}
5494+
#endif
5495+
5496+
// -ir-profile-generate should add libclang_rt.profile for WebAssembly targets
5497+
try withTemporaryDirectory { resourceDir in
5498+
try localFileSystem.writeFileContents(resourceDir.appending(components: "wasi", "static-executable-args.lnk")) {
5499+
$0.send("garbage")
5500+
}
5501+
5502+
var env = ProcessEnv.block
5503+
env["SWIFT_DRIVER_SWIFT_AUTOLINK_EXTRACT_EXEC"] = "//bin/swift-autolink-extract"
5504+
5505+
for triple in ["wasm32-unknown-wasi", "wasm32-unknown-wasip1-threads"] {
5506+
var driver = try Driver(args: [
5507+
"swiftc", "-ir-profile-generate=\(directoryPath)", "-target", triple, "test.swift",
5508+
"-resource-dir", resourceDir.pathString
5509+
], env: env)
5510+
let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs()
5511+
5512+
XCTAssertEqual(plannedJobs.count, 2)
5513+
XCTAssertEqual(plannedJobs[0].kind, .compile)
5514+
5515+
XCTAssertEqual(plannedJobs[1].kind, .link)
5516+
XCTAssert(plannedJobs[1].commandLine.containsPathWithBasename("libclang_rt.profile-wasm32.a"))
5517+
}
5518+
}
5519+
5520+
for explicitUseLd in [true, false] {
5521+
var args = ["swiftc", "-ir-profile-generate=\(directoryPath)", "-target", "x86_64-unknown-windows-msvc", "test.swift"]
5522+
if explicitUseLd {
5523+
// Explicitly passing '-use-ld=lld' should still result in '-lld-allow-duplicate-weak'.
5524+
args.append("-use-ld=lld")
5525+
}
5526+
var driver = try Driver(args: args)
5527+
let plannedJobs = try driver.planBuild()
5528+
5529+
XCTAssertEqual(plannedJobs.count, 2)
5530+
XCTAssertEqual(plannedJobs[0].kind, .compile)
5531+
5532+
XCTAssertEqual(plannedJobs[1].kind, .link)
5533+
5534+
let linkCmds = plannedJobs[1].commandLine
5535+
5536+
// rdar://131295678 - Make sure we force the use of lld and pass
5537+
// '-lld-allow-duplicate-weak'.
5538+
XCTAssert(linkCmds.contains(.flag("-fuse-ld=lld")))
5539+
XCTAssert(linkCmds.contains([.flag("-Xlinker"), .flag("-lld-allow-duplicate-weak")]))
5540+
}
5541+
5542+
// rdar://131295678 - Make sure we force the use of lld and pass
5543+
// '-lld-allow-duplicate-weak' even if the user requests something else.
5544+
do {
5545+
var driver = try Driver(args: ["swiftc", "-ir-profile-generate=\(directoryPath)", "-use-ld=link", "-target", "x86_64-unknown-windows-msvc", "test.swift"])
5546+
let plannedJobs = try driver.planBuild()
5547+
5548+
XCTAssertEqual(plannedJobs.count, 2)
5549+
XCTAssertEqual(plannedJobs[0].kind, .compile)
5550+
5551+
XCTAssertEqual(plannedJobs[1].kind, .link)
5552+
5553+
let linkCmds = plannedJobs[1].commandLine
5554+
5555+
XCTAssertFalse(linkCmds.contains(.flag("-fuse-ld=link")))
5556+
XCTAssertTrue(linkCmds.contains(.flag("-fuse-ld=lld")))
5557+
XCTAssertTrue(linkCmds.contains(.flag("-lld-allow-duplicate-weak")))
5558+
}
5559+
5560+
do {
5561+
// If we're not building for profiling, don't add '-lld-allow-duplicate-weak'.
5562+
var driver = try Driver(args: ["swiftc", "-use-ld=lld", "-target", "x86_64-unknown-windows-msvc", "test.swift"])
5563+
let plannedJobs = try driver.planBuild()
5564+
5565+
XCTAssertEqual(plannedJobs.count, 2)
5566+
XCTAssertEqual(plannedJobs[0].kind, .compile)
5567+
5568+
XCTAssertEqual(plannedJobs[1].kind, .link)
5569+
5570+
let linkCmds = plannedJobs[1].commandLine
5571+
XCTAssertTrue(linkCmds.contains(.flag("-fuse-ld=lld")))
5572+
XCTAssertFalse(linkCmds.contains(.flag("-lld-allow-duplicate-weak")))
5573+
}
5574+
}
5575+
}
5576+
53595577
func testCSProfileLinkerArgs() throws {
53605578
var envVars = ProcessEnv.block
53615579
envVars["SWIFT_DRIVER_LD_EXEC"] = ld.nativePathString(escaped: false)

0 commit comments

Comments
 (0)