Skip to content

Commit 821345c

Browse files
author
Nathan Hawes
committed
[Frontend] Add a new -index-unit-ouput-path and filelist equivalent to the frontend
These new options mirror -o and -output-filelist and are used instead of those options to supply the output file path(s) to record in the index store. This is intended to allow sharing index data across builds in separate directories that are otherwise equivalent as far as the index data is concered (e.g. an ASAN build and a non-ASAN build) by supplying the same -index-unit-output-path for both. Resolves rdar://problem/74816412
1 parent 6e0267f commit 821345c

14 files changed

+397
-36
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,15 @@ ERROR(error_mode_requires_one_sil_multi_sib,none,
165165
())
166166

167167
ERROR(error_no_output_filename_specified,none,
168-
"an output filename was not specified for a mode which requires an "
169-
"output filename", ())
168+
"an %0 filename was not specified for a mode which requires an "
169+
"%0 filename", (StringRef))
170170

171171
ERROR(error_implicit_output_file_is_directory,none,
172172
"the implicit output file '%0' is a directory; explicitly specify a "
173-
"filename using -o", (StringRef))
173+
"filename using %1", (StringRef, StringRef))
174174

175175
ERROR(error_if_any_output_files_are_specified_they_all_must_be,none,
176-
"if any output files are specified, they all must be", ())
176+
"if any %0 files are specified, they all must be", (StringRef))
177177

178178
ERROR(error_primary_file_not_found,none,
179179
"primary file '%0' was not found in file list '%1'",
@@ -211,6 +211,8 @@ ERROR(error_index_failed_status_check,none,
211211
"failed file status check: %0", (StringRef))
212212
ERROR(error_index_inputs_more_than_outputs,none,
213213
"index output filenames do not match input source files", ())
214+
WARNING(warn_index_unit_output_path_without_index_store,none,
215+
"-index-unit-output-path is ignored without -index-store-path", ())
214216

215217
ERROR(error_wrong_number_of_arguments,none,
216218
"wrong number of '%0' arguments (expected %1, got %2)",

include/swift/Basic/PrimarySpecificPaths.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,23 @@ class PrimarySpecificPaths {
3232
/// is to be written to stdout, contains "-".
3333
std::string OutputFilename;
3434

35+
/// The name to report the main output file as being in the index store.
36+
/// This is equivalent to OutputFilename, unless -index-store-output-path
37+
/// was specified.
38+
std::string IndexUnitOutputFilename;
39+
3540
SupplementaryOutputPaths SupplementaryOutputs;
3641

3742
/// The name of the "main" input file, used by the debug info.
3843
std::string MainInputFilenameForDebugInfo;
3944

4045
PrimarySpecificPaths(StringRef OutputFilename = StringRef(),
46+
StringRef IndexUnitOutputFilename = StringRef(),
4147
StringRef MainInputFilenameForDebugInfo = StringRef(),
4248
SupplementaryOutputPaths SupplementaryOutputs =
4349
SupplementaryOutputPaths())
4450
: OutputFilename(OutputFilename),
51+
IndexUnitOutputFilename(IndexUnitOutputFilename),
4552
SupplementaryOutputs(SupplementaryOutputs),
4653
MainInputFilenameForDebugInfo(MainInputFilenameForDebugInfo) {}
4754

include/swift/Basic/SupplementaryOutputPaths.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ struct SupplementaryOutputPaths {
185185
if (!LdAddCFilePath.empty())
186186
fn(LdAddCFilePath);
187187
if (!ModuleSummaryOutputPath.empty())
188-
fn(ModuleSummaryOutputPath);
188+
fn(ModuleSummaryOutputPath);
189189
}
190190

191191
bool empty() const {

include/swift/Frontend/FrontendInputsAndOutputs.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ class FrontendInputsAndOutputs {
188188
friend struct InterfaceSubContextDelegateImpl;
189189
void setMainAndSupplementaryOutputs(
190190
ArrayRef<std::string> outputFiles,
191-
ArrayRef<SupplementaryOutputPaths> supplementaryOutputs);
191+
ArrayRef<SupplementaryOutputPaths> supplementaryOutputs,
192+
ArrayRef<std::string> outputFilesForIndexUnits = None);
192193

193194
public:
194195
unsigned countOfInputsProducingMainOutputs() const;
@@ -209,13 +210,18 @@ class FrontendInputsAndOutputs {
209210
llvm::function_ref<bool(const InputFile &)> fn) const;
210211

211212
std::vector<std::string> copyOutputFilenames() const;
213+
std::vector<std::string> copyIndexUnitOutputFilenames() const;
212214

213215
void forEachOutputFilename(llvm::function_ref<void(StringRef)> fn) const;
214216

215217
/// Gets the name of the specified output filename.
216218
/// If multiple files are specified, the last one is returned.
217219
std::string getSingleOutputFilename() const;
218220

221+
/// Gets the name of the specified output filename to record in the index unit
222+
/// output files. If multiple are specified, the last one is returned.
223+
std::string getSingleIndexUnitOutputFilename() const;
224+
219225
bool isOutputFilenameStdout() const;
220226
bool isOutputFileDirectory() const;
221227
bool hasNamedOutputFile() const;

include/swift/Frontend/InputFile.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ class InputFile final {
105105
/// stream, the result is "-".
106106
std::string outputFilename() const { return PSPs.OutputFilename; }
107107

108+
std::string indexUnitOutputFilename() const {
109+
if (!PSPs.IndexUnitOutputFilename.empty())
110+
return PSPs.IndexUnitOutputFilename;
111+
return outputFilename();
112+
}
113+
108114
/// If there are explicit primary inputs (i.e. designated with -primary-input
109115
/// or -primary-filelist), the paths specific to those inputs (other than the
110116
/// input file path itself) are kept here. If there are no explicit primary

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,9 @@ def index_ignore_stdlib :
626626
Flag<["-"], "index-ignore-stdlib">,
627627
HelpText<"Avoid emitting index data for the standard library.">;
628628

629+
def index_unit_output_path_filelist : Separate<["-"], "index-unit-output-path-filelist">,
630+
HelpText<"Specify index unit output paths in a file rather than on the command line">;
631+
629632
def dump_interface_hash : Flag<["-"], "dump-interface-hash">,
630633
HelpText<"Parse input file(s) and dump interface token hash(es)">,
631634
ModeOpt;

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,10 @@ def index_store_path : Separate<["-"], "index-store-path">,
11231123
Flags<[FrontendOption, ArgumentIsPath]>, MetaVarName<"<path>">,
11241124
HelpText<"Store indexing data to <path>">;
11251125

1126+
def index_unit_output_path : Separate<["-"], "index-unit-output-path">,
1127+
Flags<[FrontendOption, ArgumentIsPath]>, MetaVarName<"<path>">,
1128+
HelpText<"Use <path> as the output path in the produced index data.">;
1129+
11261130
def index_ignore_system_modules : Flag<["-"], "index-ignore-system-modules">,
11271131
Flags<[NoInteractiveOption]>,
11281132
HelpText<"Avoid indexing system modules">;

lib/Frontend/ArgsToFrontendInputsConverter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,8 @@ ArgsToFrontendInputsConverter::createInputFilesConsumingPrimaries(
187187

188188
if (!Files.empty() && !hasAnyPrimaryFiles) {
189189
Optional<std::vector<std::string>> userSuppliedNamesOrErr =
190-
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(Args,
191-
Diags);
190+
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(
191+
Args, Diags, options::OPT_o, options::OPT_output_filelist);
192192
if (userSuppliedNamesOrErr && userSuppliedNamesOrErr->size() == 1)
193193
result.setIsSingleThreadedWMO(true);
194194
}

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,8 @@ bool ArgsToFrontendOptionsConverter::computeFallbackModuleName() {
514514
return false;
515515
}
516516
Optional<std::vector<std::string>> outputFilenames =
517-
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(Args,
518-
Diags);
517+
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(
518+
Args, Diags, options::OPT_o, options::OPT_output_filelist);
519519

520520
std::string nameToStem =
521521
outputFilenames && outputFilenames->size() == 1 &&
@@ -531,14 +531,17 @@ bool ArgsToFrontendOptionsConverter::computeFallbackModuleName() {
531531
bool ArgsToFrontendOptionsConverter::
532532
computeMainAndSupplementaryOutputFilenames() {
533533
std::vector<std::string> mainOutputs;
534+
std::vector<std::string> mainOutputForIndexUnits;
534535
std::vector<SupplementaryOutputPaths> supplementaryOutputs;
535536
const bool hadError = ArgsToFrontendOutputsConverter(
536537
Args, Opts.ModuleName, Opts.InputsAndOutputs, Diags)
537-
.convert(mainOutputs, supplementaryOutputs);
538+
.convert(mainOutputs, mainOutputForIndexUnits,
539+
supplementaryOutputs);
538540
if (hadError)
539541
return true;
540542
Opts.InputsAndOutputs.setMainAndSupplementaryOutputs(mainOutputs,
541-
supplementaryOutputs);
543+
supplementaryOutputs,
544+
mainOutputForIndexUnits);
542545
return false;
543546
}
544547

lib/Frontend/ArgsToFrontendOutputsConverter.cpp

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,43 @@ using namespace llvm::opt;
3434

3535
bool ArgsToFrontendOutputsConverter::convert(
3636
std::vector<std::string> &mainOutputs,
37+
std::vector<std::string> &mainOutputsForIndexUnits,
3738
std::vector<SupplementaryOutputPaths> &supplementaryOutputs) {
3839

3940
Optional<OutputFilesComputer> ofc =
40-
OutputFilesComputer::create(Args, Diags, InputsAndOutputs);
41+
OutputFilesComputer::create(Args, Diags, InputsAndOutputs, {
42+
"output", options::OPT_o, options::OPT_output_filelist, "-o"
43+
});
4144
if (!ofc)
4245
return true;
4346
Optional<std::vector<std::string>> mains = ofc->computeOutputFiles();
4447
if (!mains)
4548
return true;
4649

50+
Optional<std::vector<std::string>> indexMains;
51+
if (Args.hasArg(options::OPT_index_unit_output_path,
52+
options::OPT_index_unit_output_path_filelist)) {
53+
54+
if (!Args.hasArg(options::OPT_index_store_path)) {
55+
Diags.diagnose(SourceLoc(),
56+
diag::warn_index_unit_output_path_without_index_store);
57+
}
58+
59+
Optional<OutputFilesComputer> iuofc =
60+
OutputFilesComputer::create(Args, Diags, InputsAndOutputs, {
61+
"index unit output path", options::OPT_index_unit_output_path,
62+
options::OPT_index_unit_output_path_filelist,
63+
"-index-unit-output-path"
64+
});
65+
if (!iuofc)
66+
return true;
67+
indexMains = iuofc->computeOutputFiles();
68+
if (!indexMains)
69+
return true;
70+
71+
assert(mains->size() == indexMains->size() && "checks not equivalent?");
72+
}
73+
4774
Optional<std::vector<SupplementaryOutputPaths>> supplementaries =
4875
SupplementaryOutputPathsComputer(Args, Diags, InputsAndOutputs, *mains,
4976
ModuleName)
@@ -52,6 +79,8 @@ bool ArgsToFrontendOutputsConverter::convert(
5279
return true;
5380

5481
mainOutputs = std::move(*mains);
82+
if (indexMains)
83+
mainOutputsForIndexUnits = std::move(*indexMains);
5584
supplementaryOutputs = std::move(*supplementaries);
5685
return false;
5786
}
@@ -75,22 +104,26 @@ ArgsToFrontendOutputsConverter::readOutputFileList(const StringRef filelistPath,
75104

76105
Optional<std::vector<std::string>>
77106
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(
78-
const ArgList &args, DiagnosticEngine &diags) {
79-
if (const Arg *A = args.getLastArg(options::OPT_output_filelist)) {
80-
assert(!args.hasArg(options::OPT_o) &&
81-
"don't use -o with -output-filelist");
107+
const ArgList &args, DiagnosticEngine &diags, options::ID singleOpt,
108+
options::ID filelistOpt) {
109+
if (const Arg *A = args.getLastArg(filelistOpt)) {
110+
assert(!args.hasArg(singleOpt) &&
111+
"don't use -o with -output-filelist or -index-unit-output-path with "
112+
" -index-unit-output-filelist");
82113
return ArgsToFrontendOutputsConverter::readOutputFileList(A->getValue(),
83114
diags);
84115
}
85-
return args.getAllArgValues(options::OPT_o);
116+
return args.getAllArgValues(singleOpt);
86117
}
87118

88119
Optional<OutputFilesComputer>
89120
OutputFilesComputer::create(const llvm::opt::ArgList &args,
90121
DiagnosticEngine &diags,
91-
const FrontendInputsAndOutputs &inputsAndOutputs) {
122+
const FrontendInputsAndOutputs &inputsAndOutputs,
123+
OutputOptInfo optInfo) {
92124
Optional<std::vector<std::string>> outputArguments =
93-
getOutputFilenamesFromCommandLineOrFilelist(args, diags);
125+
getOutputFilenamesFromCommandLineOrFilelist(args, diags, optInfo.SingleID,
126+
optInfo.FilelistID);
94127
if (!outputArguments)
95128
return None;
96129
const StringRef outputDirectoryArgument =
@@ -113,7 +146,8 @@ OutputFilesComputer::create(const llvm::opt::ArgList &args,
113146
inputsAndOutputs.countOfInputsProducingMainOutputs()) {
114147
diags.diagnose(
115148
SourceLoc(),
116-
diag::error_if_any_output_files_are_specified_they_all_must_be);
149+
diag::error_if_any_output_files_are_specified_they_all_must_be,
150+
optInfo.PrettyName);
117151
return None;
118152
}
119153

@@ -125,7 +159,8 @@ OutputFilesComputer::create(const llvm::opt::ArgList &args,
125159
outputDirectoryArgument, firstInput, requestedAction,
126160
args.getLastArg(options::OPT_module_name),
127161
file_types::getExtension(outputType),
128-
FrontendOptions::doesActionProduceTextualOutput(requestedAction));
162+
FrontendOptions::doesActionProduceTextualOutput(requestedAction),
163+
optInfo);
129164
}
130165

131166
OutputFilesComputer::OutputFilesComputer(
@@ -135,12 +170,13 @@ OutputFilesComputer::OutputFilesComputer(
135170
const StringRef outputDirectoryArgument, const StringRef firstInput,
136171
const FrontendOptions::ActionType requestedAction,
137172
const llvm::opt::Arg *moduleNameArg, const StringRef suffix,
138-
const bool hasTextualOutput)
173+
const bool hasTextualOutput, OutputOptInfo optInfo)
139174
: Diags(diags), InputsAndOutputs(inputsAndOutputs),
140175
OutputFileArguments(outputFileArguments),
141176
OutputDirectoryArgument(outputDirectoryArgument), FirstInput(firstInput),
142177
RequestedAction(requestedAction), ModuleNameArg(moduleNameArg),
143-
Suffix(suffix), HasTextualOutput(hasTextualOutput) {}
178+
Suffix(suffix), HasTextualOutput(hasTextualOutput),
179+
OutputInfo(optInfo) {}
144180

145181
Optional<std::vector<std::string>>
146182
OutputFilesComputer::computeOutputFiles() const {
@@ -189,7 +225,8 @@ OutputFilesComputer::deriveOutputFileFromInput(const InputFile &input) const {
189225
std::string baseName = determineBaseNameOfOutput(input);
190226
if (baseName.empty()) {
191227
// Assuming FrontendOptions::doesActionProduceOutput(RequestedAction)
192-
Diags.diagnose(SourceLoc(), diag::error_no_output_filename_specified);
228+
Diags.diagnose(SourceLoc(), diag::error_no_output_filename_specified,
229+
OutputInfo.PrettyName);
193230
return None;
194231
}
195232
return deriveOutputFileFromParts("", baseName);
@@ -200,7 +237,7 @@ Optional<std::string> OutputFilesComputer::deriveOutputFileForDirectory(
200237
std::string baseName = determineBaseNameOfOutput(input);
201238
if (baseName.empty()) {
202239
Diags.diagnose(SourceLoc(), diag::error_implicit_output_file_is_directory,
203-
OutputDirectoryArgument);
240+
OutputDirectoryArgument, OutputInfo.SingleOptSpelling);
204241
return None;
205242
}
206243
return deriveOutputFileFromParts(OutputDirectoryArgument, baseName);

lib/Frontend/ArgsToFrontendOutputsConverter.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class ArgsToFrontendOutputsConverter {
4444
Diags(diags) {}
4545

4646
bool convert(std::vector<std::string> &mainOutputs,
47+
std::vector<std::string> &mainOutputsForIndexUnits,
4748
std::vector<SupplementaryOutputPaths> &supplementaryOutputs);
4849

4950
/// Try to read an output file list file.
@@ -52,6 +53,13 @@ class ArgsToFrontendOutputsConverter {
5253
readOutputFileList(StringRef filelistPath, DiagnosticEngine &diags);
5354
};
5455

56+
struct OutputOptInfo {
57+
StringRef PrettyName;
58+
options::ID SingleID;
59+
options::ID FilelistID;
60+
StringRef SingleOptSpelling;
61+
};
62+
5563
class OutputFilesComputer {
5664
DiagnosticEngine &Diags;
5765
const FrontendInputsAndOutputs &InputsAndOutputs;
@@ -62,26 +70,31 @@ class OutputFilesComputer {
6270
const llvm::opt::Arg *const ModuleNameArg;
6371
const StringRef Suffix;
6472
const bool HasTextualOutput;
73+
const OutputOptInfo OutputInfo;
6574

6675
OutputFilesComputer(DiagnosticEngine &diags,
6776
const FrontendInputsAndOutputs &inputsAndOutputs,
6877
std::vector<std::string> outputFileArguments,
6978
StringRef outputDirectoryArgument, StringRef firstInput,
7079
FrontendOptions::ActionType requestedAction,
7180
const llvm::opt::Arg *moduleNameArg, StringRef suffix,
72-
bool hasTextualOutput);
81+
bool hasTextualOutput,
82+
OutputOptInfo optInfo);
7383

7484
public:
7585
static Optional<OutputFilesComputer>
7686
create(const llvm::opt::ArgList &args, DiagnosticEngine &diags,
77-
const FrontendInputsAndOutputs &inputsAndOutputs);
87+
const FrontendInputsAndOutputs &inputsAndOutputs,
88+
OutputOptInfo optInfo);
7889

7990
/// \return the output filenames on the command line or in the output
8091
/// filelist. If there
8192
/// were neither -o's nor an output filelist, returns an empty vector.
8293
static Optional<std::vector<std::string>>
8394
getOutputFilenamesFromCommandLineOrFilelist(const llvm::opt::ArgList &args,
84-
DiagnosticEngine &diags);
95+
DiagnosticEngine &diags,
96+
options::ID singleOpt,
97+
options::ID filelistOpt);
8598

8699
Optional<std::vector<std::string>> computeOutputFiles() const;
87100

0 commit comments

Comments
 (0)