Skip to content

Commit 22b3177

Browse files
authored
Merge pull request #1144 from artemcm/AddConstValueExtractionPathHandling
Add supplementary output path handling for extracted compile-time-known values
2 parents 07e627a + 3b745ee commit 22b3177

File tree

6 files changed

+178
-5
lines changed

6 files changed

+178
-5
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,9 @@ public struct Driver {
287287
/// Path to the discovered dependencies file of the emit-module task.
288288
let emitModuleDependenciesFilePath: VirtualPath.Handle?
289289

290+
/// Path to emitted compile-time-known values.
291+
let constValuesFilePath: VirtualPath.Handle?
292+
290293
/// Path to the Objective-C generated header.
291294
let objcGeneratedHeaderPath: VirtualPath.Handle?
292295

@@ -733,6 +736,14 @@ public struct Driver {
733736
emitModuleSeparately: emitModuleSeparately,
734737
outputFileMap: self.outputFileMap,
735738
moduleName: moduleOutputInfo.name)
739+
self.constValuesFilePath = try Self.computeSupplementaryOutputPath(
740+
&parsedOptions, type: .swiftConstValues, isOutputOptions: [.emitConstValues],
741+
outputPath: .emitConstValuesPath,
742+
compilerOutputType: compilerOutputType,
743+
compilerMode: compilerMode,
744+
emitModuleSeparately: emitModuleSeparately,
745+
outputFileMap: self.outputFileMap,
746+
moduleName: moduleOutputInfo.name)
736747
// FIXME: -fixits-output-path
737748
self.objcGeneratedHeaderPath = try Self.computeSupplementaryOutputPath(
738749
&parsedOptions, type: .objcHeader, isOutputOptions: [.emitObjcHeader],

Sources/SwiftDriver/Jobs/CompileJob.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ extension Driver {
9494
.diagnostics, .emitModuleDiagnostics, .objcHeader, .swiftDeps, .remap, .tbd,
9595
.moduleTrace, .yamlOptimizationRecord, .bitstreamOptimizationRecord, .pcm, .pch,
9696
.clangModuleMap, .jsonCompilerFeatures, .jsonTargetInfo, .jsonSwiftArtifacts,
97-
.indexUnitOutputPath, .modDepCache, .jsonAPIBaseline, .jsonABIBaseline, nil:
97+
.indexUnitOutputPath, .modDepCache, .jsonAPIBaseline, .jsonABIBaseline,
98+
.swiftConstValues, nil:
9899
return false
99100
}
100101
}
@@ -459,7 +460,8 @@ extension FileType {
459460
.objcHeader, .image, .swiftDeps, .moduleTrace, .tbd, .yamlOptimizationRecord,
460461
.bitstreamOptimizationRecord, .swiftInterface, .privateSwiftInterface,
461462
.swiftSourceInfoFile, .clangModuleMap, .jsonSwiftArtifacts,
462-
.indexUnitOutputPath, .modDepCache, .jsonAPIBaseline, .jsonABIBaseline:
463+
.indexUnitOutputPath, .modDepCache, .jsonAPIBaseline, .jsonABIBaseline,
464+
.swiftConstValues:
463465
fatalError("Output type can never be a primary output")
464466
}
465467
}

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,12 @@ extension Driver {
394394
input: input,
395395
flag: "-emit-dependencies-path")
396396

397+
addOutputOfType(
398+
outputType: .swiftConstValues,
399+
finalOutputPath: constValuesFilePath,
400+
input: input,
401+
flag: "-emit-const-values-path")
402+
397403
addOutputOfType(
398404
outputType: .swiftDeps,
399405
finalOutputPath: referenceDependenciesPath,

Sources/SwiftDriver/Utilities/FileType.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public enum FileType: String, Hashable, CaseIterable, Codable {
5757
/// Serialized source information.
5858
case swiftSourceInfoFile = "swiftsourceinfo"
5959

60+
/// Extracted compile-time-known values
61+
case swiftConstValues = "swiftconstvalues"
62+
6063
/// Assembler source.
6164
case assembly = "s"
6265

@@ -229,6 +232,9 @@ extension FileType: CustomStringConvertible {
229232

230233
case .jsonABIBaseline:
231234
return "abi-baseline-json"
235+
236+
case .swiftConstValues:
237+
return "const-values"
232238
}
233239
}
234240
}
@@ -248,7 +254,7 @@ extension FileType {
248254
.swiftInterface, .privateSwiftInterface, .swiftSourceInfoFile,
249255
.jsonDependencies, .clangModuleMap, .jsonTargetInfo, .jsonCompilerFeatures,
250256
.jsonSwiftArtifacts, .indexUnitOutputPath, .modDepCache, .jsonAPIBaseline,
251-
.jsonABIBaseline:
257+
.jsonABIBaseline, .swiftConstValues:
252258
return false
253259
}
254260
}
@@ -351,6 +357,8 @@ extension FileType {
351357
return "api-baseline-json"
352358
case .jsonABIBaseline:
353359
return "abi-baseline-json"
360+
case .swiftConstValues:
361+
return "const-values"
354362
}
355363
}
356364
}
@@ -362,7 +370,7 @@ extension FileType {
362370
.raw_sil, .llvmIR,.objcHeader, .autolink, .importedModules, .tbd,
363371
.moduleTrace, .yamlOptimizationRecord, .swiftInterface, .privateSwiftInterface,
364372
.jsonDependencies, .clangModuleMap, .jsonCompilerFeatures, .jsonTargetInfo,
365-
.jsonSwiftArtifacts, .jsonAPIBaseline, .jsonABIBaseline:
373+
.jsonSwiftArtifacts, .jsonAPIBaseline, .jsonABIBaseline, .swiftConstValues:
366374
return true
367375
case .image, .object, .dSYM, .pch, .sib, .raw_sib, .swiftModule,
368376
.swiftDocumentation, .swiftSourceInfoFile, .llvmBitcode, .diagnostics,
@@ -385,7 +393,7 @@ extension FileType {
385393
.importedModules, .tbd, .moduleTrace, .indexData, .yamlOptimizationRecord,
386394
.modDepCache, .bitstreamOptimizationRecord, .pcm, .pch, .jsonDependencies,
387395
.clangModuleMap, .jsonCompilerFeatures, .jsonTargetInfo, .jsonSwiftArtifacts,
388-
.indexUnitOutputPath, .jsonAPIBaseline, .jsonABIBaseline:
396+
.indexUnitOutputPath, .jsonAPIBaseline, .jsonABIBaseline, .swiftConstValues:
389397
return false
390398
}
391399
}

Sources/SwiftOptions/Options.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ extension Option {
6060
public static let compilerStyleDiags: Option = Option("-compiler-style-diags", .flag, attributes: [.noDriver], helpText: "Print compiler style diagnostics to stderr.")
6161
public static let compilerStyleDiags_: Option = Option("--compiler-style-diags", .flag, alias: Option.compilerStyleDiags, attributes: [.noDriver], helpText: "Print compiler style diagnostics to stderr.")
6262
public static let conditionalRuntimeRecords: Option = Option("-conditional-runtime-records", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Allow removal of runtime metadata records (public types, protocol conformances) based on whether they're used or unused")
63+
public static let constGatherProtocolsFile: Option = Option("-const-gather-protocols-file", .separate, attributes: [.frontend, .noDriver], metaVar: "<path>", helpText: "Specify a list of protocols for extraction of conformances' const values'")
6364
public static let continueBuildingAfterErrors: Option = Option("-continue-building-after-errors", .flag, attributes: [.frontend, .doesNotAffectIncrementalBuild], helpText: "Continue building, even after errors are encountered")
6465
public static let coveragePrefixMap: Option = Option("-coverage-prefix-map", .separate, attributes: [.frontend], metaVar: "<prefix=replacement>", helpText: "Remap source paths in coverage info")
6566
public static let CrossModuleOptimization: Option = Option("-cross-module-optimization", .flag, attributes: [.helpHidden, .frontend], helpText: "Perform cross-module optimization")
@@ -222,6 +223,8 @@ extension Option {
222223
public static let emitAssembly: Option = Option("-emit-assembly", .flag, attributes: [.frontend, .noInteractive, .doesNotAffectIncrementalBuild], helpText: "Emit assembly file(s) (-S)", group: .modes)
223224
public static let emitBc: Option = Option("-emit-bc", .flag, attributes: [.frontend, .noInteractive, .doesNotAffectIncrementalBuild], helpText: "Emit LLVM BC file(s)", group: .modes)
224225
public static let emitClangHeaderPath: Option = Option("-emit-clang-header-path", .separate, alias: Option.emitObjcHeaderPath, attributes: [.frontend, .noDriver, .noInteractive, .argumentIsPath, .supplementaryOutput], helpText: "Emit an Objective-C and C++ header file to <path>")
226+
public static let emitConstValuesPath: Option = Option("-emit-const-values-path", .separate, attributes: [.frontend, .noInteractive, .argumentIsPath, .supplementaryOutput], metaVar: "<path>", helpText: "Emit the extracted compile-time known values to <path>")
227+
public static let emitConstValues: Option = Option("-emit-const-values", .flag, attributes: [.noInteractive, .supplementaryOutput])
225228
public static let emitDependenciesPath: Option = Option("-emit-dependencies-path", .separate, attributes: [.frontend, .noDriver], metaVar: "<path>", helpText: "Output basic Make-compatible dependencies file to <path>")
226229
public static let emitDependencies: Option = Option("-emit-dependencies", .flag, attributes: [.frontend, .noInteractive, .supplementaryOutput], helpText: "Emit basic Make-compatible dependencies files")
227230
public static let emitExecutable: Option = Option("-emit-executable", .flag, attributes: [.noInteractive, .doesNotAffectIncrementalBuild], helpText: "Emit a linked executable", group: .modes)
@@ -395,6 +398,8 @@ extension Option {
395398
public static let iframework: Option = Option("-iframework", .joinedOrSeparate, attributes: [.noDriver, .argumentIsPath], helpText: "add a directory to the clang importer system framework search path")
396399
public static let ignoreAlwaysInline: Option = Option("-ignore-always-inline", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Ignore @inline(__always) attributes.")
397400
public static let ignoreModuleSourceInfo: Option = Option("-ignore-module-source-info", .flag, attributes: [.frontend, .noDriver], helpText: "Avoid getting source location from .swiftsourceinfo files")
401+
public static let ignoreSpiGroups: Option = Option("-ignore-spi-group", .separate, attributes: [.noDriver], helpText: "SPI group name to not diagnose about")
402+
public static let ignoreSpiGroups_: Option = Option("--ignore-spi-group", .separate, alias: Option.ignoreSpiGroups, attributes: [.noDriver], helpText: "SPI group name to not diagnose about")
398403
public static let ignoredUsrs: Option = Option("-ignored-usrs", .separate, attributes: [.noDriver, .argumentIsPath], metaVar: "<path>", helpText: "the file containing USRs of removed decls that the digester should ignore")
399404
public static let ignoredUsrs_: Option = Option("--ignored-usrs", .separate, alias: Option.ignoredUsrs, attributes: [.noDriver, .argumentIsPath], metaVar: "<path>", helpText: "the file containing USRs of removed decls that the digester should ignore")
400405
public static let importCfTypes: Option = Option("-import-cf-types", .flag, attributes: [.helpHidden, .frontend], helpText: "Recognize and import CF types as class types")
@@ -732,6 +737,7 @@ extension Option {
732737
Option.compilerStyleDiags,
733738
Option.compilerStyleDiags_,
734739
Option.conditionalRuntimeRecords,
740+
Option.constGatherProtocolsFile,
735741
Option.continueBuildingAfterErrors,
736742
Option.coveragePrefixMap,
737743
Option.CrossModuleOptimization,
@@ -894,6 +900,8 @@ extension Option {
894900
Option.emitAssembly,
895901
Option.emitBc,
896902
Option.emitClangHeaderPath,
903+
Option.emitConstValuesPath,
904+
Option.emitConstValues,
897905
Option.emitDependenciesPath,
898906
Option.emitDependencies,
899907
Option.emitExecutable,

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,144 @@ final class SwiftDriverTests: XCTestCase {
10471047
XCTAssertTrue(plannedJobs[0].commandLine.contains(.flag("-serialize-diagnostics-path")))
10481048
}
10491049

1050+
func testEmitConstValues() throws {
1051+
do { // Just single files
1052+
var driver = try Driver(args: ["swiftc", "foo.swift", "bar.swift", "baz.swift",
1053+
"-module-name", "Foo", "-emit-const-values"])
1054+
let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs()
1055+
XCTAssertEqual(plannedJobs.count, 4)
1056+
XCTAssertEqual(plannedJobs[0].kind, .compile)
1057+
XCTAssertTrue(plannedJobs[0].commandLine.contains("-emit-const-values-path"))
1058+
XCTAssertTrue(plannedJobs[0].outputs.contains(where: { $0.type == .swiftConstValues }))
1059+
XCTAssertEqual(plannedJobs[1].kind, .compile)
1060+
XCTAssertTrue(plannedJobs[1].commandLine.contains("-emit-const-values-path"))
1061+
XCTAssertTrue(plannedJobs[1].outputs.contains(where: { $0.type == .swiftConstValues }))
1062+
XCTAssertEqual(plannedJobs[2].kind, .compile)
1063+
XCTAssertTrue(plannedJobs[2].commandLine.contains("-emit-const-values-path"))
1064+
XCTAssertTrue(plannedJobs[2].outputs.contains(where: { $0.type == .swiftConstValues }))
1065+
XCTAssertEqual(plannedJobs[3].kind, .link)
1066+
}
1067+
1068+
do { // Just single files with emit-module
1069+
var driver = try Driver(args: ["swiftc", "foo.swift", "bar.swift", "baz.swift", "-emit-module",
1070+
"-module-name", "Foo", "-emit-const-values"])
1071+
let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs()
1072+
XCTAssertEqual(plannedJobs.count, 4)
1073+
XCTAssertEqual(plannedJobs[0].kind, .emitModule)
1074+
// Ensure the emit-module job does *not* contain this flag
1075+
XCTAssertFalse(plannedJobs[0].commandLine.contains("-emit-const-values-path"))
1076+
XCTAssertEqual(plannedJobs[1].kind, .compile)
1077+
XCTAssertTrue(plannedJobs[1].commandLine.contains("-emit-const-values-path"))
1078+
XCTAssertTrue(plannedJobs[1].outputs.contains(where: { $0.type == .swiftConstValues }))
1079+
XCTAssertEqual(plannedJobs[2].kind, .compile)
1080+
XCTAssertTrue(plannedJobs[2].commandLine.contains("-emit-const-values-path"))
1081+
XCTAssertTrue(plannedJobs[2].outputs.contains(where: { $0.type == .swiftConstValues }))
1082+
XCTAssertEqual(plannedJobs[3].kind, .compile)
1083+
XCTAssertTrue(plannedJobs[3].commandLine.contains("-emit-const-values-path"))
1084+
XCTAssertTrue(plannedJobs[3].outputs.contains(where: { $0.type == .swiftConstValues }))
1085+
}
1086+
1087+
do { // Batch
1088+
var driver = try Driver(args: ["swiftc", "foo.swift", "bar.swift", "baz.swift",
1089+
"-enable-batch-mode","-driver-batch-size-limit", "2",
1090+
"-module-name", "Foo", "-emit-const-values"])
1091+
let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs()
1092+
XCTAssertEqual(plannedJobs.count, 3)
1093+
XCTAssertEqual(plannedJobs[0].kind, .compile)
1094+
XCTAssertTrue(plannedJobs[0].primaryInputs.map{ $0.file.description }.elementsEqual(["foo.swift",
1095+
"bar.swift"]))
1096+
XCTAssertTrue(plannedJobs[0].commandLine.contains("-emit-const-values-path"))
1097+
XCTAssertEqual(plannedJobs[0].outputs.filter({ $0.type == .swiftConstValues }).count, 2)
1098+
XCTAssertEqual(plannedJobs[1].kind, .compile)
1099+
XCTAssertTrue(plannedJobs[1].primaryInputs.map{ $0.file.description }.elementsEqual(["baz.swift"]))
1100+
XCTAssertTrue(plannedJobs[1].commandLine.contains("-emit-const-values-path"))
1101+
XCTAssertEqual(plannedJobs[1].outputs.filter({ $0.type == .swiftConstValues }).count, 1)
1102+
XCTAssertEqual(plannedJobs[2].kind, .link)
1103+
}
1104+
1105+
try withTemporaryFile { fileMapFile in // Batch with output-file-map
1106+
let outputMapContents = """
1107+
{
1108+
"foo.swift": {
1109+
"object": "/tmp/foo.build/foo.swift.o",
1110+
"const-values": "/tmp/foo.build/foo.swiftconstvalues"
1111+
},
1112+
"bar.swift": {
1113+
"object": "/tmp/foo.build/bar.swift.o",
1114+
"const-values": "/tmp/foo.build/bar.swiftconstvalues"
1115+
},
1116+
"baz.swift": {
1117+
"object": "/tmp/foo.build/baz.swift.o",
1118+
"const-values": "/tmp/foo.build/baz.swiftconstvalues"
1119+
}
1120+
}
1121+
"""
1122+
try localFileSystem.writeFileContents(fileMapFile.path) { $0 <<< outputMapContents }
1123+
var driver = try Driver(args: ["swiftc", "foo.swift", "bar.swift", "baz.swift",
1124+
"-enable-batch-mode","-driver-batch-size-limit", "2",
1125+
"-module-name", "Foo", "-emit-const-values",
1126+
"-output-file-map", fileMapFile.path.description])
1127+
let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs()
1128+
XCTAssertEqual(plannedJobs.count, 3)
1129+
XCTAssertEqual(plannedJobs[0].kind, .compile)
1130+
XCTAssertTrue(plannedJobs[0].primaryInputs.map{ $0.file.description }.elementsEqual(["foo.swift",
1131+
"bar.swift"]))
1132+
XCTAssertTrue(plannedJobs[0].commandLine.contains(subsequence: [.flag("-emit-const-values-path"), .path(.absolute(.init("/tmp/foo.build/foo.swiftconstvalues")))]))
1133+
XCTAssertTrue(plannedJobs[0].commandLine.contains(subsequence: [.flag("-emit-const-values-path"), .path(.absolute(.init("/tmp/foo.build/bar.swiftconstvalues")))]))
1134+
XCTAssertEqual(plannedJobs[0].outputs.filter({ $0.type == .swiftConstValues }).count, 2)
1135+
XCTAssertEqual(plannedJobs[1].kind, .compile)
1136+
XCTAssertTrue(plannedJobs[1].primaryInputs.map{ $0.file.description }.elementsEqual(["baz.swift"]))
1137+
XCTAssertTrue(plannedJobs[1].commandLine.contains("-emit-const-values-path"))
1138+
XCTAssertEqual(plannedJobs[1].outputs.filter({ $0.type == .swiftConstValues }).count, 1)
1139+
XCTAssertTrue(plannedJobs[1].commandLine.contains(subsequence: [.flag("-emit-const-values-path"), .path(.absolute(.init("/tmp/foo.build/baz.swiftconstvalues")))]))
1140+
XCTAssertEqual(plannedJobs[2].kind, .link)
1141+
}
1142+
1143+
do { // WMO
1144+
var driver = try Driver(args: ["swiftc", "foo.swift", "bar.swift", "baz.swift",
1145+
"-whole-module-optimization",
1146+
"-module-name", "Foo", "-emit-const-values"])
1147+
let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs()
1148+
XCTAssertEqual(plannedJobs.count, 2)
1149+
XCTAssertEqual(plannedJobs[0].kind, .compile)
1150+
XCTAssertEqual(plannedJobs[0].outputs.filter({ $0.type == .swiftConstValues }).count, 1)
1151+
XCTAssertEqual(plannedJobs[1].kind, .link)
1152+
}
1153+
1154+
try withTemporaryFile { fileMapFile in // WMO with output-file-map
1155+
let outputMapContents = """
1156+
{
1157+
"": {
1158+
"const-values": "/tmp/foo.build/foo.master.swiftconstvalues"
1159+
},
1160+
"foo.swift": {
1161+
"object": "/tmp/foo.build/foo.swift.o",
1162+
"const-values": "/tmp/foo.build/foo.swiftconstvalues"
1163+
},
1164+
"bar.swift": {
1165+
"object": "/tmp/foo.build/bar.swift.o",
1166+
"const-values": "/tmp/foo.build/bar.swiftconstvalues"
1167+
},
1168+
"baz.swift": {
1169+
"object": "/tmp/foo.build/baz.swift.o",
1170+
"const-values": "/tmp/foo.build/baz.swiftconstvalues"
1171+
}
1172+
}
1173+
"""
1174+
try localFileSystem.writeFileContents(fileMapFile.path) { $0 <<< outputMapContents }
1175+
var driver = try Driver(args: ["swiftc", "foo.swift", "bar.swift", "baz.swift",
1176+
"-whole-module-optimization",
1177+
"-module-name", "Foo", "-emit-const-values",
1178+
"-output-file-map", fileMapFile.path.description])
1179+
let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs()
1180+
XCTAssertEqual(plannedJobs.count, 2)
1181+
XCTAssertEqual(plannedJobs[0].kind, .compile)
1182+
XCTAssertEqual(plannedJobs[0].outputs.first(where: { $0.type == .swiftConstValues })?.file,
1183+
.absolute(.init("/tmp/foo.build/foo.master.swiftconstvalues")))
1184+
XCTAssertEqual(plannedJobs[1].kind, .link)
1185+
}
1186+
}
1187+
10501188
func testEmitModuleSepratelyEmittingDiagnosticsWithOutputFileMap() throws {
10511189
try withTemporaryDirectory { path in
10521190
let outputFileMap = path.appending(component: "outputFileMap.json")

0 commit comments

Comments
 (0)