Skip to content

Commit 5839e6c

Browse files
committed
Add ir and cs instrumentation options
Update Options.swift Update as per suggestions
1 parent 83f8460 commit 5839e6c

File tree

8 files changed

+935
-21
lines changed

8 files changed

+935
-21
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 84 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3334,24 +3334,91 @@ extension Driver {
33343334
}
33353335
}
33363336

3337+
static private func validateProfilingGenerateArgs(
3338+
_ parsedOptions: inout ParsedOptions,
3339+
diagnosticEngine: DiagnosticsEngine
3340+
) {
3341+
let genFlags: [Option] = [
3342+
.profileGenerate,
3343+
.irProfileGenerate,
3344+
.irProfileGenerateEQ,
3345+
.csProfileGenerate,
3346+
.csProfileGenerateEQ,
3347+
]
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+
}
3359+
3360+
var providedGen = genFlags.filter { parsedOptions.hasArgument($0) }
3361+
resolveDualFormConflict(.irProfileGenerate, .irProfileGenerateEQ)
3362+
resolveDualFormConflict(.csProfileGenerate, .csProfileGenerateEQ)
3363+
3364+
guard providedGen.count >= 2 else { return }
3365+
for i in 1..<providedGen.count {
3366+
let error = Error.conflictingOptions(providedGen[i - 1], providedGen[i])
3367+
diagnosticEngine.emit(.error(error), location: nil)
3368+
}
3369+
}
3370+
3371+
static private func validateProfilingUseArgs(
3372+
_ parsedOptions: inout ParsedOptions,
3373+
diagnosticEngine: DiagnosticsEngine
3374+
) {
3375+
let conflictingGenFlags: [Option] = [
3376+
.profileGenerate,
3377+
.irProfileGenerate,
3378+
.irProfileGenerateEQ,
3379+
]
3380+
let useProfArgs: [Option] = [
3381+
.profileUse,
3382+
.profileSampleUse,
3383+
.irProfileUse
3384+
]
3385+
let providedUse = useProfArgs.filter { parsedOptions.hasArgument($0) }
3386+
guard !providedUse.isEmpty else { return }
3387+
3388+
// At most one *use* option allowed
3389+
if providedUse.count > 1 {
3390+
for (i, left) in providedUse.enumerated() {
3391+
for (j, right) in providedUse.enumerated() {
3392+
guard i < j else { continue }
3393+
diagnosticEngine.emit(.error(Error.conflictingOptions(left, right)), location: nil)
3394+
}
3395+
}
3396+
}
3397+
3398+
// If no generate flags, we're good.
3399+
let providedGen = conflictingGenFlags.filter { parsedOptions.hasArgument($0) }
3400+
guard !providedGen.isEmpty else { return }
3401+
3402+
// We already diagnosed if the user passed more than one "use" option
3403+
// (e.g. both `-profile-use` and `-profile-sample-use`). To avoid
3404+
// spamming diagnostics, we now treat the first provided "use" flag
3405+
// as the canonical representative.
3406+
let canonicalUse = providedUse[0]
3407+
3408+
// Generate vs Use are mutually exclusive
3409+
for g in providedGen {
3410+
diagnosticEngine.emit(.error(Error.conflictingOptions(g, canonicalUse)), location: nil)
3411+
}
3412+
}
3413+
3414+
33373415
static func validateProfilingArgs(_ parsedOptions: inout ParsedOptions,
33383416
fileSystem: FileSystem,
33393417
workingDirectory: AbsolutePath?,
33403418
diagnosticEngine: DiagnosticsEngine) {
3341-
let conflictingProfArgs: [Option] = [.profileGenerate,
3342-
.profileUse,
3343-
.profileSampleUse]
3344-
33453419
// Find out which of the mutually exclusive profiling arguments were provided.
3346-
let provided = conflictingProfArgs.filter { parsedOptions.hasArgument($0) }
3347-
3348-
// If there's at least two of them, there's a conflict.
3349-
if provided.count >= 2 {
3350-
for i in 1..<provided.count {
3351-
let error = Error.conflictingOptions(provided[i-1], provided[i])
3352-
diagnosticEngine.emit(.error(error), location: nil)
3353-
}
3354-
}
3420+
validateProfilingGenerateArgs(&parsedOptions, diagnosticEngine: diagnosticEngine)
3421+
validateProfilingUseArgs(&parsedOptions, diagnosticEngine: diagnosticEngine)
33553422

33563423
// Ensure files exist for the given paths.
33573424
func checkForMissingProfilingData(_ profileDataArgs: [String]) {
@@ -3376,6 +3443,10 @@ extension Driver {
33763443
if let profileSampleUseArg = parsedOptions.getLastArgument(.profileSampleUse)?.asSingle {
33773444
checkForMissingProfilingData([profileSampleUseArg])
33783445
}
3446+
3447+
if let irProfileUseArgs = parsedOptions.getLastArgument(.irProfileUse)?.asMultiple {
3448+
checkForMissingProfilingData(irProfileUseArgs)
3449+
}
33793450
}
33803451

33813452
static func validateParseableOutputArgs(_ parsedOptions: inout ParsedOptions,

Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,7 @@ extension DarwinToolchain {
258258
fileSystem: fileSystem
259259
)
260260

261-
if parsedOptions.hasArgument(.profileGenerate) {
262-
commandLine.appendFlag("-fprofile-generate")
263-
}
261+
commandLine.appendFlags(mapInstrumentationTypeToClangArgs(from: &parsedOptions))
264262

265263
// These custom arguments should be right before the object file at the
266264
// end.

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,11 @@ extension Driver {
243243
try commandLine.appendLast(.RpassMissedEQ, from: &parsedOptions)
244244
try commandLine.appendLast(.suppressWarnings, from: &parsedOptions)
245245
try commandLine.appendLast(.profileGenerate, from: &parsedOptions)
246+
try commandLine.appendLast(.irProfileGenerate, from: &parsedOptions)
247+
try commandLine.appendLast(.irProfileGenerateEQ, from: &parsedOptions)
248+
try commandLine.appendLast(.irProfileUse, from: &parsedOptions)
249+
try commandLine.appendLast(.csProfileGenerate, from: &parsedOptions)
250+
try commandLine.appendLast(.csProfileGenerateEQ, from: &parsedOptions)
246251
try commandLine.appendLast(.profileUse, from: &parsedOptions)
247252
try commandLine.appendLast(.profileCoverageMapping, from: &parsedOptions)
248253
try commandLine.appendLast(.debugInfoForProfiling, from: &parsedOptions)

Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ extension GenericUnixToolchain {
303303
}
304304
}
305305

306-
if parsedOptions.hasArgument(.profileGenerate) {
306+
if needsInstrumentedProfile(from: &parsedOptions) {
307307
let environment = (targetTriple.environment == .android) ? "-android" : ""
308308
let libProfile = VirtualPath.lookup(targetInfo.runtimeResourcePath.path)
309309
.appending(components: "clang", "lib", targetTriple.osNameUnversioned,

Sources/SwiftDriver/Jobs/WebAssemblyToolchain+LinkerSupport.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ extension WebAssemblyToolchain {
176176
commandLine.appendFlag("-fsanitize=\(sanitizerNames)")
177177
}
178178

179-
if parsedOptions.hasArgument(.profileGenerate) {
179+
if needsInstrumentedProfile(from: &parsedOptions) {
180180
let libProfile = VirtualPath.lookup(targetInfo.runtimeResourcePath.path)
181181
.appending(components: "clang", "lib", targetTriple.osName,
182182
"libclang_rt.profile-\(targetTriple.archName).a")

Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ extension WindowsToolchain {
5050
// for now, which supports the behavior via a flag.
5151
// TODO: Once we've changed coverage to no longer rely on emitting
5252
// duplicate weak symbols (rdar://131295678), we can remove this.
53-
if parsedOptions.hasArgument(.profileGenerate) { return true }
53+
if needsInstrumentedProfile(from: &parsedOptions) { return true }
5454

5555
return false
5656
}()
@@ -228,11 +228,12 @@ extension WindowsToolchain {
228228
commandLine.appendFlag("-fsanitize=\(sanitize)")
229229
}
230230

231-
if parsedOptions.contains(.profileGenerate) {
231+
if needsInstrumentedProfile(from: &parsedOptions) {
232232
assert(bForceLLD,
233233
"LLD is currently required for profiling (rdar://131295678)")
234234

235-
commandLine.appendFlag("-fprofile-generate")
235+
commandLine.appendFlags(mapInstrumentationTypeToClangArgs(from: &parsedOptions))
236+
236237
// FIXME(rdar://131295678): Currently profiling requires the ability to
237238
// emit duplicate weak symbols. Assume we're using lld and pass
238239
// `-lld-allow-duplicate-weak` to enable this behavior.

Sources/SwiftDriver/Toolchains/Toolchain.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,43 @@ extension Toolchain {
376376
}
377377
return clangArg
378378
}
379+
380+
internal func mapInstrumentationTypeToClangArgs(from options: inout ParsedOptions) -> [String] {
381+
var args: [String] = []
382+
383+
if options.contains(.profileGenerate) || options.contains(.irProfileGenerate) {
384+
args.append("-fprofile-generate")
385+
}
386+
387+
if options.contains(.irProfileGenerateEQ),
388+
let path = options.getLastArgument(.irProfileGenerateEQ)?.asSingle {
389+
args.append("-fprofile-generate=\(path)")
390+
}
391+
392+
if options.contains(.csProfileGenerate) {
393+
args.append("-fcs-profile-generate")
394+
}
395+
396+
if options.contains(.csProfileGenerateEQ),
397+
let path = options.getLastArgument(.csProfileGenerateEQ)?.asSingle {
398+
args.append("-fcs-profile-generate=\(path)")
399+
}
400+
401+
if options.contains(.irProfileUse),
402+
let path = options.getLastArgument(.irProfileUse)?.asMultiple.last {
403+
args.append("-fprofile-use=\(path)")
404+
}
405+
406+
return args
407+
}
408+
409+
internal func needsInstrumentedProfile(from parsedOptions: inout ParsedOptions) -> Bool {
410+
parsedOptions.contains(.profileGenerate) ||
411+
parsedOptions.contains(.irProfileGenerate) ||
412+
parsedOptions.contains(.irProfileGenerateEQ) ||
413+
parsedOptions.contains(.csProfileGenerate) ||
414+
parsedOptions.contains(.csProfileGenerateEQ)
415+
}
379416
}
380417

381418
@_spi(Testing) public enum ToolchainError: Swift.Error {

0 commit comments

Comments
 (0)