Merge remote-tracking branch 'origin/master' into master-next

This commit is contained in:
swift-ci
2018-02-01 16:49:08 -08:00
39 changed files with 1156 additions and 661 deletions

View File

@@ -150,6 +150,9 @@ ERROR(error_implicit_output_file_is_directory,none,
"the implicit output file '%0' is a directory; explicitly specify a filename "
"using -o", (StringRef))
ERROR(error_if_any_output_files_are_specified_they_all_must_be,none,
"if any output files are specified, they all must be", ())
ERROR(error_primary_file_not_found,none,
"primary file '%0' was not found in file list '%1'",
(StringRef, StringRef))

View File

@@ -190,6 +190,11 @@ public:
/// Gets the name of the specified output filename.
/// If multiple files are specified, the last one is returned.
/// This function is used by (at least)
/// lldb/source/Symbol/SwiftASTContext.cpp:4603
/// FIXME: This function should go away in favor of
/// Instance.getFrontendOptions().InputsAndOutputs.getSingleOutputFilename
/// when batch mode handles all contingencies.
StringRef getSingleOutputFilename() const {
if (OutputFilenames.size() >= 1)
return OutputFilenames.back();

View File

@@ -42,7 +42,7 @@ namespace swift {
class ArgsToFrontendInputsConverter {
DiagnosticEngine &Diags;
const llvm::opt::ArgList &Args;
FrontendInputs &Inputs;
FrontendInputsAndOutputs &InputsAndOutputs;
llvm::opt::Arg const *const FilelistPathArg;
llvm::opt::Arg const *const PrimaryFilelistPathArg;
@@ -54,7 +54,7 @@ class ArgsToFrontendInputsConverter {
public:
ArgsToFrontendInputsConverter(DiagnosticEngine &diags,
const llvm::opt::ArgList &args,
FrontendInputs &inputs);
FrontendInputsAndOutputs &inputsAndOutputs);
bool convert();
@@ -69,6 +69,8 @@ private:
std::set<StringRef>
createInputFilesConsumingPrimaries(std::set<StringRef> primaryFiles);
bool checkForMissingPrimaryFiles(std::set<StringRef> primaryFiles);
bool isSingleThreadedWMO() const;
};
} // namespace swift

View File

@@ -50,34 +50,13 @@ private:
void setUnsignedIntegerArgument(options::ID optionID, unsigned max,
unsigned &valueToSet);
FrontendOptions::ActionType determineRequestedAction() const;
bool setUpForSILOrLLVM();
/// Determine the correct output filename when none was specified.
///
/// Such an absence should only occur when invoking the frontend
/// without the driver,
/// because the driver will always pass -o with an appropriate filename
/// if output is required for the requested action.
bool deriveOutputFilenameFromInputFile();
/// Determine the correct output filename when a directory was specified.
///
/// Such a specification should only occur when invoking the frontend
/// directly, because the driver will always pass -o with an appropriate
/// filename if output is required for the requested action.
bool deriveOutputFilenameForDirectory(StringRef outputDir);
std::string determineBaseNameOfOutput() const;
void deriveOutputFilenameFromParts(StringRef dir, StringRef base);
void determineSupplementaryOutputFilenames();
/// Returns the output filenames on the command line or in the output
/// filelist. If there
/// were neither -o's nor an output filelist, returns an empty vector.
/// \returns the output filenames on the command line or in the output
/// filelist, or an empty vector if there were neither -o's nor an output
/// filelist.
ArrayRef<std::string> getOutputFilenamesFromCommandLineOrFilelist();
bool checkForUnusedOutputPaths() const;
@@ -91,6 +70,9 @@ public:
: Diags(Diags), Args(Args), Opts(Opts) {}
bool convert();
static FrontendOptions::ActionType
determineRequestedAction(const llvm::opt::ArgList &);
};
} // namespace swift

View File

@@ -0,0 +1,113 @@
//===--- ArgsToFrontendOutputsConverter.h -----------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_FRONTEND_ARGSTOFRONTENDOUTPUTSCONVERTER_H
#define SWIFT_FRONTEND_ARGSTOFRONTENDOUTPUTSCONVERTER_H
#include "swift/AST/DiagnosticConsumer.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/Basic/LLVM.h"
#include "swift/Frontend/FrontendOptions.h"
#include "swift/Option/Options.h"
#include "llvm/Option/ArgList.h"
#include <vector>
namespace swift {
/// Given the command line arguments and information about the inputs,
/// Fill in all the information in FrontendInputsAndOutputs.
class ArgsToFrontendOutputsConverter {
const llvm::opt::ArgList &Args;
StringRef ModuleName;
FrontendInputsAndOutputs &InputsAndOutputs;
DiagnosticEngine &Diags;
public:
ArgsToFrontendOutputsConverter(const llvm::opt::ArgList &args,
StringRef moduleName,
FrontendInputsAndOutputs &inputsAndOutputs,
DiagnosticEngine &diags)
: Args(args), ModuleName(moduleName), InputsAndOutputs(inputsAndOutputs),
Diags(diags) {}
Optional<std::vector<std::string>> convert();
/// Try to read an output file list file.
/// \returns `None` if it could not open the filelist.
static Optional<std::vector<std::string>>
readOutputFileList(StringRef filelistPath, DiagnosticEngine &diags);
};
class OutputFilesComputer {
const llvm::opt::ArgList &Args;
DiagnosticEngine &Diags;
const FrontendInputsAndOutputs &InputsAndOutputs;
const std::vector<std::string> OutputFileArguments;
const std::string OutputDirectoryArgument;
const StringRef FirstInput;
const FrontendOptions::ActionType RequestedAction;
const llvm::opt::Arg *const ModuleNameArg;
const StringRef Suffix;
const bool HasTextualOutput;
OutputFilesComputer(const llvm::opt::ArgList &args, DiagnosticEngine &diags,
const FrontendInputsAndOutputs &inputsAndOutputs,
std::vector<std::string> outputFileArguments,
StringRef outputDirectoryArgument, StringRef firstInput,
FrontendOptions::ActionType requestedAction,
const llvm::opt::Arg *moduleNameArg, StringRef suffix,
bool hasTextualOutput);
public:
static Optional<OutputFilesComputer>
create(const llvm::opt::ArgList &args, DiagnosticEngine &diags,
const FrontendInputsAndOutputs &inputsAndOutputs);
/// \return the output filenames on the command line or in the output
/// filelist. If there
/// were neither -o's nor an output filelist, returns an empty vector.
static Optional<std::vector<std::string>>
getOutputFilenamesFromCommandLineOrFilelist(const llvm::opt::ArgList &args,
DiagnosticEngine &diags);
Optional<std::vector<std::string>> computeOutputFiles() const;
private:
Optional<std::string> computeOutputFile(StringRef outputArg,
const InputFile &input) const;
/// \return the correct output filename when none was specified.
///
/// Such an absence should only occur when invoking the frontend
/// without the driver,
/// because the driver will always pass -o with an appropriate filename
/// if output is required for the requested action.
Optional<std::string> deriveOutputFileFromInput(const InputFile &input) const;
/// \return the correct output filename when a directory was specified.
///
/// Such a specification should only occur when invoking the frontend
/// directly, because the driver will always pass -o with an appropriate
/// filename if output is required for the requested action.
Optional<std::string>
deriveOutputFileForDirectory(const InputFile &input) const;
std::string determineBaseNameOfOutput(const InputFile &input) const;
std::string deriveOutputFileFromParts(StringRef dir, StringRef base) const;
};
} // namespace swift
#endif /* SWIFT_FRONTEND_ARGSTOFRONTENDOUTPUTSCONVERTER_H */

View File

@@ -54,7 +54,7 @@ class SerializedModuleLoader;
/// - options for all stages of translation,
/// - information about the build environment,
/// - information about the job being performed, and
/// - lists of inputs.
/// - lists of inputs and outputs.
///
/// A CompilerInvocation can be built from a frontend command line
/// using parseArgs. It can then be used to build a CompilerInstance,
@@ -245,7 +245,7 @@ public:
StringRef getOutputFilename() const {
return FrontendOpts.getSingleOutputFilename();
return FrontendOpts.InputsAndOutputs.getSingleOutputFilename();
}
void setCodeCompletionPoint(llvm::MemoryBuffer *Buf, unsigned Offset) {

View File

@@ -1,127 +0,0 @@
//===--- FrontendInputs.h ---------------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_FRONTEND_FRONTENDINPUTS_H
#define SWIFT_FRONTEND_FRONTENDINPUTS_H
#include "swift/AST/Module.h"
#include "swift/Frontend/FrontendInputs.h"
#include "swift/Frontend/InputFile.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/MapVector.h"
#include <string>
#include <vector>
namespace llvm {
class MemoryBuffer;
}
namespace swift {
/// Information about all the inputs to the frontend.
class FrontendInputs {
friend class ArgsToFrontendInputsConverter;
std::vector<InputFile> AllInputs;
typedef llvm::StringMap<unsigned> InputFileMap;
InputFileMap PrimaryInputs;
public:
FrontendInputs() = default;
FrontendInputs(const FrontendInputs &other);
FrontendInputs &operator=(const FrontendInputs &other);
// Readers:
ArrayRef<InputFile> getAllInputs() const { return AllInputs; }
std::vector<std::string> getInputFilenames() const;
unsigned inputCount() const { return AllInputs.size(); }
bool hasInputs() const { return !AllInputs.empty(); }
bool hasSingleInput() const { return inputCount() == 1; }
StringRef getFilenameOfFirstInput() const;
bool isReadingFromStdin() const;
// If we have exactly one input filename, and its extension is "bc" or "ll",
// treat the input as LLVM_IR.
bool shouldTreatAsLLVM() const;
// Primary input readers
private:
void assertMustNotBeMoreThanOnePrimaryInput() const;
bool areAllNonPrimariesSIB() const;
public:
unsigned primaryInputCount() const { return PrimaryInputs.size(); }
// Primary count readers:
bool hasUniquePrimaryInput() const { return primaryInputCount() == 1; }
bool hasPrimaryInputs() const { return primaryInputCount() > 0; }
bool isWholeModule() const { return !hasPrimaryInputs(); }
// Count-dependend readers:
/// \return the unique primary input, if one exists.
const InputFile *getUniquePrimaryInput() const;
const InputFile &getRequiredUniquePrimaryInput() const;
/// \return the name of the unique primary input, or an empty StrinRef if
/// there isn't one.
StringRef getNameOfUniquePrimaryInputFile() const;
bool isInputPrimary(StringRef file) const;
unsigned numberOfPrimaryInputsEndingWith(const char *extension) const;
// Multi-facet readers
bool shouldTreatAsSIL() const;
/// \return true for error
bool verifyInputs(DiagnosticEngine &diags, bool treatAsSIL,
bool isREPLRequested, bool isNoneRequested) const;
// Writers
void addInputFile(StringRef file, llvm::MemoryBuffer *buffer = nullptr) {
addInput(InputFile(file, false, buffer));
}
void addPrimaryInputFile(StringRef file,
llvm::MemoryBuffer *buffer = nullptr) {
addInput(InputFile(file, true, buffer));
}
void addInput(const InputFile &input);
void clearInputs() {
AllInputs.clear();
PrimaryInputs.clear();
}
};
} // namespace swift
#endif /* SWIFT_FRONTEND_FRONTENDINPUTS_H */

View File

@@ -0,0 +1,200 @@
//===--- FrontendInputs.h ---------------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_FRONTEND_FRONTENDINPUTS_H
#define SWIFT_FRONTEND_FRONTENDINPUTS_H
#include "swift/AST/Module.h"
#include "swift/Frontend/InputFile.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/MapVector.h"
#include <string>
#include <vector>
namespace llvm {
class MemoryBuffer;
}
namespace swift {
/// Information about all the inputs and outputs to the frontend.
class FrontendInputsAndOutputs {
friend class ArgsToFrontendInputsConverter;
std::vector<InputFile> AllInputs;
llvm::StringMap<unsigned> PrimaryInputs;
/// In Single-threaded WMO mode, all inputs are used
/// both for importing and compiling.
bool IsSingleThreadedWMO = false;
/// Punt where needed to enable batch mode experiments.
bool AreBatchModeChecksBypassed = false;
public:
bool areBatchModeChecksBypassed() const { return AreBatchModeChecksBypassed; }
void setBypassBatchModeChecks(bool bbc) { AreBatchModeChecksBypassed = bbc; }
FrontendInputsAndOutputs() = default;
FrontendInputsAndOutputs(const FrontendInputsAndOutputs &other);
FrontendInputsAndOutputs &operator=(const FrontendInputsAndOutputs &other);
// Whole-module-optimization (WMO) routines:
// SingleThreadedWMO produces only main output file. In contrast,
// multi-threaded WMO produces one main output per input, as single-file and
// batch-mode do for each primary. Both WMO modes produce only one set of
// supplementary outputs.
bool isSingleThreadedWMO() const { return IsSingleThreadedWMO; }
void setIsSingleThreadedWMO(bool istw) { IsSingleThreadedWMO = istw; }
bool isWholeModule() const { return !hasPrimaryInputs(); }
// Readers:
// All inputs:
ArrayRef<InputFile> getAllInputs() const { return AllInputs; }
std::vector<std::string> getInputFilenames() const;
unsigned inputCount() const { return AllInputs.size(); }
bool hasInputs() const { return !AllInputs.empty(); }
bool hasSingleInput() const { return inputCount() == 1; }
const InputFile &firstInput() const { return AllInputs[0]; }
InputFile &firstInput() { return AllInputs[0]; }
const InputFile &lastInput() const { return AllInputs.back(); }
StringRef getFilenameOfFirstInput() const;
bool isReadingFromStdin() const;
void forEachInput(llvm::function_ref<void(const InputFile &)> fn) const;
// Primaries:
const InputFile &firstPrimaryInput() const;
const InputFile &lastPrimaryInput() const;
void
forEachPrimaryInput(llvm::function_ref<void(const InputFile &)> fn) const;
unsigned primaryInputCount() const { return PrimaryInputs.size(); }
// Primary count readers:
bool hasUniquePrimaryInput() const { return primaryInputCount() == 1; }
bool hasPrimaryInputs() const { return primaryInputCount() > 0; }
/// Fails an assertion if there is more than one primary input.
/// Used in situations where only one primary input can be handled
/// and where batch mode has not been implemented yet.
void assertMustNotBeMoreThanOnePrimaryInput() const;
/// Fails an assertion when there is more than one primary input unless
/// the experimental -bypass-batch-mode-checks argument was passed to
/// the front end.
/// FIXME: When batch mode is complete, this function should be obsolete.
void
assertMustNotBeMoreThanOnePrimaryInputUnlessBatchModeChecksHaveBeenBypassed()
const;
// Count-dependend readers:
/// \return the unique primary input, if one exists.
const InputFile *getUniquePrimaryInput() const;
const InputFile &getRequiredUniquePrimaryInput() const;
/// \return the name of the unique primary input, or an empty StrinRef if
/// there isn't one.
StringRef getNameOfUniquePrimaryInputFile() const;
/// Combines all primaries for stats reporter
std::string getStatsFileMangledInputName() const;
bool isInputPrimary(StringRef file) const;
unsigned numberOfPrimaryInputsEndingWith(const char *extension) const;
// Multi-facet readers
// If we have exactly one input filename, and its extension is "bc" or "ll",
// treat the input as LLVM_IR.
bool shouldTreatAsLLVM() const;
bool shouldTreatAsSIL() const;
bool areAllNonPrimariesSIB() const;
/// \return true for error
bool verifyInputs(DiagnosticEngine &diags, bool treatAsSIL,
bool isREPLRequested, bool isNoneRequested) const;
// Changing inputs
public:
void clearInputs();
void addInput(const InputFile &input);
void addInputFile(StringRef file, llvm::MemoryBuffer *buffer = nullptr);
void addPrimaryInputFile(StringRef file,
llvm::MemoryBuffer *buffer = nullptr);
// Outputs
private:
friend class ArgsToFrontendOptionsConverter;
void setMainOutputs(ArrayRef<std::string> outputFiles);
public:
unsigned countOfInputsProducingMainOutputs() const;
const InputFile &firstInputProducingOutput() const;
const InputFile &lastInputProducingOutput() const;
/// Under single-threaded WMO, we pretend that the first input
/// generates the main output, even though it will include code
/// generated from all of them.
void forEachInputProducingAMainOutputFile(
llvm::function_ref<void(const InputFile &)> fn) const;
std::vector<std::string> copyOutputFilenames() const;
void
forEachOutputFilename(llvm::function_ref<void(const std::string &)> fn) const;
/// Gets the name of the specified output filename.
/// If multiple files are specified, the last one is returned.
StringRef getSingleOutputFilename() const;
bool isOutputFilenameStdout() const;
bool isOutputFileDirectory() const;
bool hasNamedOutputFile() const;
// Supplementary outputs
void forEachInputProducingSupplementaryOutput(
llvm::function_ref<void(const InputFile &)> fn) const;
};
} // namespace swift
#endif /* SWIFT_FRONTEND_FRONTENDINPUTS_H */

View File

@@ -14,7 +14,7 @@
#define SWIFT_FRONTEND_FRONTENDOPTIONS_H
#include "swift/AST/Module.h"
#include "swift/Frontend/FrontendInputs.h"
#include "swift/Frontend/FrontendInputsAndOutputs.h"
#include "swift/Frontend/InputFile.h"
#include "llvm/ADT/Hashing.h"
@@ -33,37 +33,15 @@ class FrontendOptions {
friend class ArgsToFrontendOptionsConverter;
public:
FrontendInputs Inputs;
FrontendInputsAndOutputs InputsAndOutputs;
/// The kind of input on which the frontend should operate.
InputFileKind InputKind = InputFileKind::IFK_Swift;
/// The specified output files. If only a single outputfile is generated,
/// the name of the last specified file is taken.
std::vector<std::string> OutputFilenames;
void forAllOutputPaths(const InputFile &input,
std::function<void(const std::string &)> fn) const;
void forAllOutputPaths(std::function<void(const std::string &)> fn) const;
/// Gets the name of the specified output filename.
/// If multiple files are specified, the last one is returned.
StringRef getSingleOutputFilename() const {
if (OutputFilenames.size() >= 1)
return OutputFilenames.back();
return StringRef();
}
/// Sets a single filename as output filename.
void setSingleOutputFilename(const std::string &FileName) {
OutputFilenames.clear();
OutputFilenames.push_back(FileName);
}
void setOutputFilenameToStdout() { setSingleOutputFilename("-"); }
bool isOutputFilenameStdout() const {
return getSingleOutputFilename() == "-";
}
bool isOutputFileDirectory() const;
bool hasNamedOutputFile() const {
return !OutputFilenames.empty() && !isOutputFilenameStdout();
}
/// A list of arbitrary modules to import and make implicitly visible.
std::vector<std::string> ImplicitImportModuleNames;
@@ -315,7 +293,8 @@ public:
StringRef determineFallbackModuleName() const;
bool isCompilingExactlyOneSwiftFile() const {
return InputKind == InputFileKind::IFK_Swift && Inputs.hasSingleInput();
return InputKind == InputFileKind::IFK_Swift &&
InputsAndOutputs.hasSingleInput();
}
private:

View File

@@ -33,15 +33,24 @@ enum class InputFileKind {
class InputFile {
std::string Filename;
bool IsPrimary;
/// Null if the contents are not overridden.
/// Points to a buffer overriding the file's contents, or nullptr if there is
/// none.
llvm::MemoryBuffer *Buffer;
/// Contains the name of the main output file, that is, the .o file for this
/// input. If there is no such file, contains an empty string. If the output
/// is to be written to stdout, contains "-".
std::string OutputFilename;
public:
/// Does not take ownership of \p buffer. Does take ownership of (copy) a
/// string.
InputFile(StringRef name, bool isPrimary,
llvm::MemoryBuffer *buffer = nullptr)
: Filename(name), IsPrimary(isPrimary), Buffer(buffer) {
llvm::MemoryBuffer *buffer = nullptr,
StringRef outputFilename = StringRef())
: Filename(
convertBufferNameFromLLVM_getFileOrSTDIN_toSwiftConventions(name)),
IsPrimary(isPrimary), Buffer(buffer), OutputFilename(outputFilename) {
assert(!name.empty());
}
@@ -58,6 +67,12 @@ public:
StringRef filename) {
return filename.equals("<stdin>") ? "-" : filename;
}
const std::string &outputFilename() const { return OutputFilename; }
void setOutputFilename(StringRef outputFilename) {
OutputFilename = outputFilename;
}
};
} // namespace swift

View File

@@ -456,5 +456,8 @@ def validate_tbd_against_ir_EQ: Joined<["-"], "validate-tbd-against-ir=">,
// This is used to guard preemptive testing for the fix-it.
def fix_string_substring_conversion: Flag<["-"], "fix-string-substring-conversion">,
HelpText<"Emit a fix-it to append '[]' to String expressions when converting to Substring.">;
def bypass_batch_mode_checks: Flag<["-"], "bypass-batch-mode-checks">,
HelpText<"Bypass checks for batch-mode errors.">;
} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]

View File

@@ -1,4 +1,4 @@
//===--- ArgsToFrontendInputsConverter.cpp ----------------------*- C++ -*-===//
//===--- ArgsToFrontendInputsConverter.cpp --------------------------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -13,6 +13,7 @@
#include "swift/Frontend/ArgsToFrontendInputsConverter.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Frontend/ArgsToFrontendOutputsConverter.h"
#include "swift/Frontend/FrontendOptions.h"
#include "swift/Option/Options.h"
#include "swift/Parse/Lexer.h"
@@ -29,8 +30,9 @@ using namespace swift;
using namespace llvm::opt;
ArgsToFrontendInputsConverter::ArgsToFrontendInputsConverter(
DiagnosticEngine &diags, const ArgList &args, FrontendInputs &inputs)
: Diags(diags), Args(args), Inputs(inputs),
DiagnosticEngine &diags, const ArgList &args,
FrontendInputsAndOutputs &inputsAndOutputs)
: Diags(diags), Args(args), InputsAndOutputs(inputsAndOutputs),
FilelistPathArg(args.getLastArg(options::OPT_filelist)),
PrimaryFilelistPathArg(args.getLastArg(options::OPT_primary_filelist)) {}
@@ -45,7 +47,16 @@ bool ArgsToFrontendInputsConverter::convert() {
return true;
std::set<StringRef> unusedPrimaryFiles =
createInputFilesConsumingPrimaries(*primaryFiles);
return checkForMissingPrimaryFiles(unusedPrimaryFiles);
if (checkForMissingPrimaryFiles(unusedPrimaryFiles))
return true;
// Must be set before iterating over inputs needing outputs.
InputsAndOutputs.setIsSingleThreadedWMO(isSingleThreadedWMO());
InputsAndOutputs.setBypassBatchModeChecks(
Args.hasArg(options::OPT_bypass_batch_mode_checks));
return false;
}
bool ArgsToFrontendInputsConverter::enforceFilelistExclusion() {
@@ -131,7 +142,7 @@ ArgsToFrontendInputsConverter::createInputFilesConsumingPrimaries(
std::set<StringRef> primaryFiles) {
for (auto &file : Files) {
bool isPrimary = primaryFiles.count(file) > 0;
Inputs.addInput(InputFile(file, isPrimary));
InputsAndOutputs.addInput(InputFile(file, isPrimary));
if (isPrimary)
primaryFiles.erase(file);
}
@@ -149,3 +160,11 @@ bool ArgsToFrontendInputsConverter::checkForMissingPrimaryFiles(
}
return !primaryFiles.empty();
}
bool ArgsToFrontendInputsConverter::isSingleThreadedWMO() const {
Optional<std::vector<std::string>> userSuppliedNamesOrErr =
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(Args,
Diags);
return InputsAndOutputs.hasInputs() && !InputsAndOutputs.hasPrimaryInputs() &&
userSuppliedNamesOrErr && userSuppliedNamesOrErr->size() == 1;
}

View File

@@ -1,4 +1,4 @@
//===--- ArgsToFrontendOptionsConverter -------------------------*- C++ -*-===//
//===--- ArgsToFrontendOptionsConverter -----------------------------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -15,6 +15,7 @@
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Basic/Platform.h"
#include "swift/Frontend/ArgsToFrontendInputsConverter.h"
#include "swift/Frontend/ArgsToFrontendOutputsConverter.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Option/Options.h"
#include "swift/Option/SanitizerOptions.h"
@@ -82,21 +83,24 @@ bool ArgsToFrontendOptionsConverter::convert() {
// This can be enabled independently of the playground transform.
Opts.PCMacro |= Args.hasArg(OPT_pc_macro);
computeHelpOptions();
if (ArgsToFrontendInputsConverter(Diags, Args, Opts.Inputs).convert())
return true;
Opts.ParseStdlib |= Args.hasArg(OPT_parse_stdlib);
computeHelpOptions();
if (const Arg *A = Args.getLastArg(OPT_verify_generic_signatures)) {
Opts.VerifyGenericSignaturesInModule = A->getValue();
}
computeDumpScopeMapLocations();
Opts.RequestedAction = determineRequestedAction();
if (ArgsToFrontendInputsConverter(Diags, Args, Opts.InputsAndOutputs)
.convert())
return true;
Opts.RequestedAction = determineRequestedAction(Args);
if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate &&
Opts.Inputs.hasPrimaryInputs()) {
Opts.InputsAndOutputs.hasPrimaryInputs()) {
Diags.diagnose(SourceLoc(), diag::error_immediate_mode_primary_file);
return true;
}
@@ -267,12 +271,12 @@ void ArgsToFrontendOptionsConverter::computeDumpScopeMapLocations() {
}
FrontendOptions::ActionType
ArgsToFrontendOptionsConverter::determineRequestedAction() const {
ArgsToFrontendOptionsConverter::determineRequestedAction(const ArgList &args) {
using namespace options;
const Arg *A = Args.getLastArg(OPT_modes_Group);
const Arg *A = args.getLastArg(OPT_modes_Group);
if (!A) {
// We don't have a mode, so determine a default.
if (Args.hasArg(OPT_emit_module, OPT_emit_module_path)) {
if (args.hasArg(OPT_emit_module, OPT_emit_module_path)) {
// We've been told to emit a module, but have no other mode indicators.
// As a result, put the frontend into EmitModuleOnly mode.
// (Setting up module output will be handled below.)
@@ -333,10 +337,10 @@ ArgsToFrontendOptionsConverter::determineRequestedAction() const {
bool ArgsToFrontendOptionsConverter::setUpForSILOrLLVM() {
using namespace options;
bool treatAsSIL =
Args.hasArg(OPT_parse_sil) || Opts.Inputs.shouldTreatAsSIL();
bool treatAsLLVM = Opts.Inputs.shouldTreatAsLLVM();
Args.hasArg(OPT_parse_sil) || Opts.InputsAndOutputs.shouldTreatAsSIL();
bool treatAsLLVM = Opts.InputsAndOutputs.shouldTreatAsLLVM();
if (Opts.Inputs.verifyInputs(
if (Opts.InputsAndOutputs.verifyInputs(
Diags, treatAsSIL,
Opts.RequestedAction == FrontendOptions::ActionType::REPL,
Opts.RequestedAction == FrontendOptions::ActionType::NoneAction)) {
@@ -344,7 +348,7 @@ bool ArgsToFrontendOptionsConverter::setUpForSILOrLLVM() {
}
if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate) {
Opts.ImmediateArgv.push_back(
Opts.Inputs.getFilenameOfFirstInput()); // argv[0]
Opts.InputsAndOutputs.getFilenameOfFirstInput()); // argv[0]
if (const Arg *A = Args.getLastArg(OPT__DASH_DASH)) {
for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
Opts.ImmediateArgv.push_back(A->getValue(i));
@@ -405,151 +409,43 @@ bool ArgsToFrontendOptionsConverter::computeFallbackModuleName() {
return false;
}
// In order to pass some tests, must leave ModuleName empty.
if (!Opts.Inputs.hasInputs()) {
if (!Opts.InputsAndOutputs.hasInputs()) {
Opts.ModuleName = StringRef();
// FIXME: This is a bug that should not happen, but does in tests.
// The compiler should bail out earlier, where "no frontend action was
// selected".
return false;
}
ArrayRef<std::string> outputFilenames =
getOutputFilenamesFromCommandLineOrFilelist();
Optional<std::vector<std::string>> outputFilenames =
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(Args,
Diags);
auto nameToStem =
outputFilenames && outputFilenames->size() == 1 &&
outputFilenames->front() != "-" &&
!llvm::sys::fs::is_directory(outputFilenames->front())
? outputFilenames->front()
: Opts.InputsAndOutputs.getFilenameOfFirstInput().str();
bool isOutputAUniqueOrdinaryFile =
outputFilenames.size() == 1 && outputFilenames[0] != "-" &&
!llvm::sys::fs::is_directory(outputFilenames[0]);
std::string nameToStem = isOutputAUniqueOrdinaryFile
? outputFilenames[0]
: Opts.Inputs.getFilenameOfFirstInput().str();
Opts.ModuleName = llvm::sys::path::stem(nameToStem);
return false;
}
bool ArgsToFrontendOptionsConverter::computeOutputFilenames() {
assert(Opts.OutputFilenames.empty() &&
"Output filename should not be set at this point");
if (!FrontendOptions::doesActionProduceOutput(Opts.RequestedAction)) {
return false;
}
ArrayRef<std::string> outputFilenamesFromCommandLineOrFilelist =
getOutputFilenamesFromCommandLineOrFilelist();
if (outputFilenamesFromCommandLineOrFilelist.size() > 1) {
// WMO, threaded with N files (also someday batch mode).
Opts.OutputFilenames = outputFilenamesFromCommandLineOrFilelist;
return false;
}
if (outputFilenamesFromCommandLineOrFilelist.empty()) {
// When the Frontend is invoked without going through the driver
// (e.g. for testing), it is convenient to derive output filenames from
// input.
return deriveOutputFilenameFromInputFile();
}
StringRef outputFilename = outputFilenamesFromCommandLineOrFilelist[0];
if (!llvm::sys::fs::is_directory(outputFilename)) {
// Could be -primary-file (1), or -wmo (non-threaded w/ N (input) files)
Opts.OutputFilenames = outputFilenamesFromCommandLineOrFilelist;
return false;
}
// Only used for testing & when invoking frontend directly.
return deriveOutputFilenameForDirectory(outputFilename);
}
bool ArgsToFrontendOptionsConverter::deriveOutputFilenameFromInputFile() {
if (Opts.Inputs.isReadingFromStdin() ||
FrontendOptions::doesActionProduceTextualOutput(Opts.RequestedAction)) {
Opts.setOutputFilenameToStdout();
return false;
}
std::string baseName = determineBaseNameOfOutput();
if (baseName.empty()) {
if (Opts.RequestedAction != FrontendOptions::ActionType::REPL &&
Opts.RequestedAction != FrontendOptions::ActionType::Immediate &&
Opts.RequestedAction != FrontendOptions::ActionType::NoneAction) {
Diags.diagnose(SourceLoc(), diag::error_no_output_filename_specified);
return true;
}
return false;
}
deriveOutputFilenameFromParts("", baseName);
return false;
}
bool ArgsToFrontendOptionsConverter::deriveOutputFilenameForDirectory(
StringRef outputDir) {
std::string baseName = determineBaseNameOfOutput();
if (baseName.empty()) {
Diags.diagnose(SourceLoc(), diag::error_implicit_output_file_is_directory,
outputDir);
Optional<std::vector<std::string>> outs =
ArgsToFrontendOutputsConverter(Args, Opts.ModuleName,
Opts.InputsAndOutputs, Diags)
.convert();
if (!outs)
return true;
}
deriveOutputFilenameFromParts(outputDir, baseName);
if (FrontendOptions::doesActionProduceOutput(Opts.RequestedAction))
Opts.InputsAndOutputs.setMainOutputs(*outs);
else
assert(outs->empty() &&
"cannot have main outputs for actions that don't produce outputs");
return false;
}
void ArgsToFrontendOptionsConverter::deriveOutputFilenameFromParts(
StringRef dir, StringRef base) {
assert(!base.empty());
llvm::SmallString<128> path(dir);
llvm::sys::path::append(path, base);
StringRef suffix = FrontendOptions::suffixForPrincipalOutputFileForAction(
Opts.RequestedAction);
llvm::sys::path::replace_extension(path, suffix);
Opts.OutputFilenames.push_back(path.str());
}
std::string ArgsToFrontendOptionsConverter::determineBaseNameOfOutput() const {
std::string nameToStem;
if (Opts.Inputs.hasPrimaryInputs()) {
nameToStem = Opts.Inputs.getRequiredUniquePrimaryInput().file();
} else if (auto UserSpecifiedModuleName =
Args.getLastArg(options::OPT_module_name)) {
nameToStem = UserSpecifiedModuleName->getValue();
} else if (Opts.Inputs.hasSingleInput()) {
nameToStem = Opts.Inputs.getFilenameOfFirstInput();
} else
nameToStem = "";
return llvm::sys::path::stem(nameToStem).str();
}
ArrayRef<std::string>
ArgsToFrontendOptionsConverter::getOutputFilenamesFromCommandLineOrFilelist() {
if (cachedOutputFilenamesFromCommandLineOrFilelist) {
return *cachedOutputFilenamesFromCommandLineOrFilelist;
}
if (const Arg *A = Args.getLastArg(options::OPT_output_filelist)) {
assert(!Args.hasArg(options::OPT_o) &&
"don't use -o with -output-filelist");
cachedOutputFilenamesFromCommandLineOrFilelist.emplace(
readOutputFileList(A->getValue()));
} else {
cachedOutputFilenamesFromCommandLineOrFilelist.emplace(
Args.getAllArgValues(options::OPT_o));
}
return *cachedOutputFilenamesFromCommandLineOrFilelist;
}
/// Try to read an output file list file.
std::vector<std::string> ArgsToFrontendOptionsConverter::readOutputFileList(
const StringRef filelistPath) const {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
llvm::MemoryBuffer::getFile(filelistPath);
if (!buffer) {
Diags.diagnose(SourceLoc(), diag::cannot_open_file, filelistPath,
buffer.getError().message());
}
std::vector<std::string> outputFiles;
for (StringRef line : make_range(llvm::line_iterator(*buffer.get()), {})) {
outputFiles.push_back(line.str());
}
return outputFiles;
}
void ArgsToFrontendOptionsConverter::determineSupplementaryOutputFilenames() {
using namespace options;
auto determineOutputFilename =
@@ -564,8 +460,9 @@ void ArgsToFrontendOptionsConverter::determineSupplementaryOutputFilenames() {
if (!Args.hasArg(optWithoutPath))
return;
if (useMainOutput && !Opts.OutputFilenames.empty()) {
output = Opts.getSingleOutputFilename();
if (useMainOutput &&
!Opts.InputsAndOutputs.getSingleOutputFilename().empty()) {
output = Opts.InputsAndOutputs.getSingleOutputFilename();
return;
}
@@ -646,8 +543,8 @@ void ArgsToFrontendOptionsConverter::computeImportObjCHeaderOptions() {
using namespace options;
if (const Arg *A = Args.getLastArgNoClaim(OPT_import_objc_header)) {
Opts.ImplicitObjCHeaderPath = A->getValue();
Opts.SerializeBridgingHeader |=
!Opts.Inputs.hasPrimaryInputs() && !Opts.ModuleOutputPath.empty();
Opts.SerializeBridgingHeader |= !Opts.InputsAndOutputs.hasPrimaryInputs() &&
!Opts.ModuleOutputPath.empty();
}
}
void ArgsToFrontendOptionsConverter::computeImplicitImportModuleNames() {

View File

@@ -0,0 +1,204 @@
//===--- ArgsToFrontendOutputsConverter.cpp -------------------------------===//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Frontend/ArgsToFrontendOutputsConverter.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Basic/Platform.h"
#include "swift/Frontend/ArgsToFrontendInputsConverter.h"
#include "swift/Frontend/ArgsToFrontendOptionsConverter.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Option/Options.h"
#include "swift/Option/SanitizerOptions.h"
#include "swift/Strings.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/Path.h"
using namespace swift;
using namespace llvm::opt;
Optional<std::vector<std::string>> ArgsToFrontendOutputsConverter::convert() {
const auto requestedAction =
ArgsToFrontendOptionsConverter::determineRequestedAction(Args);
if (!FrontendOptions::doesActionProduceOutput(requestedAction))
return std::vector<std::string>();
if (auto ofc = OutputFilesComputer::create(Args, Diags, InputsAndOutputs))
return ofc->computeOutputFiles();
return None;
}
Optional<std::vector<std::string>>
ArgsToFrontendOutputsConverter::readOutputFileList(const StringRef filelistPath,
DiagnosticEngine &diags) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
llvm::MemoryBuffer::getFile(filelistPath);
if (!buffer) {
diags.diagnose(SourceLoc(), diag::cannot_open_file, filelistPath,
buffer.getError().message());
return None;
}
std::vector<std::string> outputFiles;
for (StringRef line : make_range(llvm::line_iterator(*buffer.get()), {})) {
outputFiles.push_back(line.str());
}
return outputFiles;
}
Optional<std::vector<std::string>>
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(
const ArgList &args, DiagnosticEngine &diags) {
if (const Arg *A = args.getLastArg(options::OPT_output_filelist)) {
assert(!args.hasArg(options::OPT_o) &&
"don't use -o with -output-filelist");
return ArgsToFrontendOutputsConverter::readOutputFileList(A->getValue(),
diags);
}
return args.getAllArgValues(options::OPT_o);
}
Optional<OutputFilesComputer>
OutputFilesComputer::create(const llvm::opt::ArgList &args,
DiagnosticEngine &diags,
const FrontendInputsAndOutputs &inputsAndOutputs) {
Optional<std::vector<std::string>> outputArguments =
getOutputFilenamesFromCommandLineOrFilelist(args, diags);
if (!outputArguments)
return None;
const StringRef outputDirectoryArgument =
outputArguments->size() == 1 &&
llvm::sys::fs::is_directory(outputArguments->front())
? StringRef(outputArguments->front())
: StringRef();
ArrayRef<std::string> outputFileArguments =
outputDirectoryArgument.empty() ? ArrayRef<std::string>(*outputArguments)
: ArrayRef<std::string>();
const StringRef firstInput = inputsAndOutputs.hasSingleInput()
? inputsAndOutputs.getFilenameOfFirstInput()
: StringRef();
const FrontendOptions::ActionType requestedAction =
ArgsToFrontendOptionsConverter::determineRequestedAction(args);
if (!outputFileArguments.empty() &&
outputFileArguments.size() !=
inputsAndOutputs.countOfInputsProducingMainOutputs()) {
diags.diagnose(
SourceLoc(),
diag::error_if_any_output_files_are_specified_they_all_must_be);
return None;
}
return OutputFilesComputer(
args, diags, inputsAndOutputs, std::move(outputFileArguments),
outputDirectoryArgument, firstInput, requestedAction,
args.getLastArg(options::OPT_module_name),
FrontendOptions::suffixForPrincipalOutputFileForAction(requestedAction),
FrontendOptions::doesActionProduceTextualOutput(requestedAction));
}
OutputFilesComputer::OutputFilesComputer(
const llvm::opt::ArgList &args, DiagnosticEngine &diags,
const FrontendInputsAndOutputs &inputsAndOutputs,
std::vector<std::string> outputFileArguments,
const StringRef outputDirectoryArgument, const StringRef firstInput,
const FrontendOptions::ActionType requestedAction,
const llvm::opt::Arg *moduleNameArg, const StringRef suffix,
const bool hasTextualOutput)
: Args(args), Diags(diags), InputsAndOutputs(inputsAndOutputs),
OutputFileArguments(outputFileArguments),
OutputDirectoryArgument(outputDirectoryArgument), FirstInput(firstInput),
RequestedAction(requestedAction), ModuleNameArg(moduleNameArg),
Suffix(suffix), HasTextualOutput(hasTextualOutput) {}
Optional<std::vector<std::string>>
OutputFilesComputer::computeOutputFiles() const {
std::vector<std::string> outputFiles;
bool hadError = false;
unsigned i = 0;
InputsAndOutputs.forEachInputProducingAMainOutputFile(
[&](const InputFile &input) -> void {
StringRef outputArg = OutputFileArguments.empty()
? StringRef()
: StringRef(OutputFileArguments[i++]);
Optional<std::string> outputFile = computeOutputFile(outputArg, input);
if (!outputFile) {
hadError = true;
return;
}
outputFiles.push_back(*outputFile);
});
return hadError ? None : Optional<std::vector<std::string>>(outputFiles);
}
Optional<std::string>
OutputFilesComputer::computeOutputFile(StringRef outputArg,
const InputFile &input) const {
if (!OutputDirectoryArgument.empty())
return deriveOutputFileForDirectory(input);
if (!outputArg.empty())
return outputArg.str();
return deriveOutputFileFromInput(input);
}
Optional<std::string>
OutputFilesComputer::deriveOutputFileFromInput(const InputFile &input) const {
if (input.file() == "-" || HasTextualOutput)
return std::string("-");
std::string baseName = determineBaseNameOfOutput(input);
if (baseName.empty()) {
// Assuming FrontendOptions::doesActionProduceOutput(RequestedAction)
Diags.diagnose(SourceLoc(), diag::error_no_output_filename_specified);
return None;
}
return deriveOutputFileFromParts("", baseName);
}
Optional<std::string> OutputFilesComputer::deriveOutputFileForDirectory(
const InputFile &input) const {
std::string baseName = determineBaseNameOfOutput(input);
if (baseName.empty()) {
Diags.diagnose(SourceLoc(), diag::error_implicit_output_file_is_directory,
OutputDirectoryArgument);
return None;
}
return deriveOutputFileFromParts(OutputDirectoryArgument, baseName);
}
std::string
OutputFilesComputer::determineBaseNameOfOutput(const InputFile &input) const {
StringRef nameToStem =
input.isPrimary()
? input.file()
: ModuleNameArg ? ModuleNameArg->getValue() : FirstInput;
return llvm::sys::path::stem(nameToStem).str();
}
std::string
OutputFilesComputer::deriveOutputFileFromParts(StringRef dir,
StringRef base) const {
assert(!base.empty());
llvm::SmallString<128> path(dir);
llvm::sys::path::append(path, base);
llvm::sys::path::replace_extension(path, Suffix);
return path.str();
}

View File

@@ -1,10 +1,11 @@
add_swift_library(swiftFrontend STATIC
ArgsToFrontendInputsConverter.cpp
ArgsToFrontendOptionsConverter.cpp
ArgsToFrontendOutputsConverter.cpp
CompilerInvocation.cpp
DiagnosticVerifier.cpp
Frontend.cpp
FrontendInputs.cpp
FrontendInputsAndOutputs.cpp
FrontendOptions.cpp
PrintingDiagnosticConsumer.cpp
SerializedDiagnosticConsumer.cpp

View File

@@ -672,7 +672,7 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
if (Args.hasArg(OPT_debug_on_sil)) {
// Derive the name of the SIL file for debugging from
// the regular outputfile.
StringRef BaseName = FEOpts.getSingleOutputFilename();
StringRef BaseName = FEOpts.InputsAndOutputs.getSingleOutputFilename();
// If there are no or multiple outputfiles, derive the name
// from the module name.
if (BaseName.empty())
@@ -818,12 +818,13 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
if (!SILOpts.SILOutputFileNameForDebugging.empty()) {
Opts.MainInputFilename = SILOpts.SILOutputFileNameForDebugging;
} else if (const InputFile *input =
FrontendOpts.Inputs.getUniquePrimaryInput()) {
FrontendOpts.InputsAndOutputs.getUniquePrimaryInput()) {
Opts.MainInputFilename = input->file();
} else if (FrontendOpts.Inputs.hasSingleInput()) {
Opts.MainInputFilename = FrontendOpts.Inputs.getFilenameOfFirstInput();
} else if (FrontendOpts.InputsAndOutputs.hasSingleInput()) {
Opts.MainInputFilename =
FrontendOpts.InputsAndOutputs.getFilenameOfFirstInput();
}
Opts.OutputFilenames = FrontendOpts.OutputFilenames;
Opts.OutputFilenames = FrontendOpts.InputsAndOutputs.copyOutputFilenames();
Opts.ModuleName = FrontendOpts.ModuleName;
if (Args.hasArg(OPT_use_jit))
@@ -1064,7 +1065,7 @@ CompilerInvocation::setUpInputForSILTool(
// If it looks like we have an AST, set the source file kind to SIL and the
// name of the module to the file's name.
getFrontendOptions().Inputs.addInput(
getFrontendOptions().InputsAndOutputs.addInput(
InputFile(inputFilename, bePrimary, fileBufOrErr.get().get()));
auto result = serialization::validateSerializedAST(

View File

@@ -58,7 +58,7 @@ void CompilerInstance::createSILModule() {
// Assume WMO if a -primary-file option was not provided.
TheSILModule = SILModule::createEmptyModule(
getMainModule(), Invocation.getSILOptions(),
Invocation.getFrontendOptions().Inputs.isWholeModule());
Invocation.getFrontendOptions().InputsAndOutputs.isWholeModule());
}
void CompilerInstance::recordPrimaryInputBuffer(unsigned BufID) {
@@ -182,7 +182,7 @@ bool CompilerInstance::setUpInputs() {
const Optional<unsigned> codeCompletionBufferID = setUpCodeCompletionBuffer();
for (const InputFile &input :
Invocation.getFrontendOptions().Inputs.getAllInputs())
Invocation.getFrontendOptions().InputsAndOutputs.getAllInputs())
if (setUpForInput(input))
return true;

View File

@@ -1,176 +0,0 @@
//===--- FrontendInputs.cpp -------------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Frontend/FrontendInputs.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Frontend/FrontendOptions.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Option/Options.h"
#include "swift/Parse/Lexer.h"
#include "swift/Strings.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/Path.h"
using namespace swift;
using namespace llvm::opt;
FrontendInputs::FrontendInputs(const FrontendInputs &other) {
for (InputFile input : other.AllInputs)
addInput(input);
}
FrontendInputs &FrontendInputs::operator=(const FrontendInputs &other) {
clearInputs();
for (InputFile input : other.AllInputs)
addInput(input);
return *this;
}
std::vector<std::string> FrontendInputs::getInputFilenames() const {
std::vector<std::string> filenames;
for (auto &input : AllInputs) {
filenames.push_back(input.file());
}
return filenames;
}
bool FrontendInputs::isReadingFromStdin() const {
return hasSingleInput() && getFilenameOfFirstInput() == "-";
}
void FrontendInputs::assertMustNotBeMoreThanOnePrimaryInput() const {
assert(primaryInputCount() < 2 &&
"have not implemented >1 primary input yet");
}
const InputFile *FrontendInputs::getUniquePrimaryInput() const {
assertMustNotBeMoreThanOnePrimaryInput();
const auto b = PrimaryInputs.begin();
return b == PrimaryInputs.end() ? nullptr : &AllInputs[b->second];
}
const InputFile &FrontendInputs::getRequiredUniquePrimaryInput() const {
if (const auto *input = getUniquePrimaryInput())
return *input;
llvm_unreachable("No primary when one is required");
}
StringRef FrontendInputs::getNameOfUniquePrimaryInputFile() const {
const auto *input = getUniquePrimaryInput();
return input == nullptr ? StringRef() : input->file();
}
bool FrontendInputs::isInputPrimary(StringRef file) const {
auto iterator = PrimaryInputs.find(file);
return iterator != PrimaryInputs.end() &&
AllInputs[iterator->second].isPrimary();
}
StringRef FrontendInputs::getFilenameOfFirstInput() const {
assert(hasInputs());
const InputFile &inp = AllInputs[0];
StringRef f = inp.file();
assert(!f.empty());
return f;
}
bool FrontendInputs::shouldTreatAsLLVM() const {
if (hasSingleInput()) {
StringRef Input(getFilenameOfFirstInput());
return llvm::sys::path::extension(Input).endswith(LLVM_BC_EXTENSION) ||
llvm::sys::path::extension(Input).endswith(LLVM_IR_EXTENSION);
}
return false;
}
bool FrontendInputs::shouldTreatAsSIL() const {
if (hasSingleInput()) {
// If we have exactly one input filename, and its extension is "sil",
// treat the input as SIL.
StringRef Input(getFilenameOfFirstInput());
return llvm::sys::path::extension(Input).endswith(SIL_EXTENSION);
}
// If we have one primary input and it's a filename with extension "sil",
// treat the input as SIL.
unsigned silPrimaryCount = numberOfPrimaryInputsEndingWith(SIL_EXTENSION);
if (silPrimaryCount == 0)
return false;
if (silPrimaryCount == primaryInputCount()) {
// Not clear what to do someday with multiple primaries
assertMustNotBeMoreThanOnePrimaryInput();
return true;
}
llvm_unreachable("Either all primaries or none must end with .sil");
}
void FrontendInputs::addInput(const InputFile &input) {
if (!input.file().empty() && input.isPrimary())
PrimaryInputs.insert(std::make_pair(input.file(), AllInputs.size()));
AllInputs.push_back(input);
}
unsigned
FrontendInputs::numberOfPrimaryInputsEndingWith(const char *extension) const {
return count_if(
PrimaryInputs, [&](const llvm::StringMapEntry<unsigned> &elem) -> bool {
StringRef filename = AllInputs[elem.second].file();
return llvm::sys::path::extension(filename).endswith(extension);
});
}
bool FrontendInputs::verifyInputs(DiagnosticEngine &diags, bool treatAsSIL,
bool isREPLRequested,
bool isNoneRequested) const {
if (isREPLRequested) {
if (hasInputs()) {
diags.diagnose(SourceLoc(), diag::error_repl_requires_no_input_files);
return true;
}
} else if (treatAsSIL) {
if (isWholeModule()) {
if (inputCount() != 1) {
diags.diagnose(SourceLoc(), diag::error_mode_requires_one_input_file);
return true;
}
} else {
assertMustNotBeMoreThanOnePrimaryInput();
// If we have the SIL as our primary input, we can waive the one file
// requirement as long as all the other inputs are SIBs.
if (!areAllNonPrimariesSIB()) {
diags.diagnose(SourceLoc(),
diag::error_mode_requires_one_sil_multi_sib);
return true;
}
}
} else if (!isNoneRequested && !hasInputs()) {
diags.diagnose(SourceLoc(), diag::error_mode_requires_an_input_file);
return true;
}
return false;
}
bool FrontendInputs::areAllNonPrimariesSIB() const {
for (const InputFile &input : AllInputs) {
if (input.isPrimary())
continue;
if (!llvm::sys::path::extension(input.file()).endswith(SIB_EXTENSION)) {
return false;
}
}
return true;
}

View File

@@ -0,0 +1,346 @@
//===--- FrontendInputsAndOutputs.cpp -------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Frontend/FrontendInputsAndOutputs.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Frontend/FrontendOptions.h"
#include "swift/Option/Options.h"
#include "swift/Parse/Lexer.h"
#include "swift/Strings.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/Path.h"
using namespace swift;
using namespace llvm::opt;
// Constructors
FrontendInputsAndOutputs::FrontendInputsAndOutputs(
const FrontendInputsAndOutputs &other) {
for (InputFile input : other.AllInputs)
addInput(input);
IsSingleThreadedWMO = other.IsSingleThreadedWMO;
}
FrontendInputsAndOutputs &FrontendInputsAndOutputs::
operator=(const FrontendInputsAndOutputs &other) {
clearInputs();
for (InputFile input : other.AllInputs)
addInput(input);
IsSingleThreadedWMO = other.IsSingleThreadedWMO;
return *this;
}
// All inputs:
std::vector<std::string> FrontendInputsAndOutputs::getInputFilenames() const {
std::vector<std::string> filenames;
for (auto &input : AllInputs) {
filenames.push_back(input.file());
}
return filenames;
}
bool FrontendInputsAndOutputs::isReadingFromStdin() const {
return hasSingleInput() && getFilenameOfFirstInput() == "-";
}
StringRef FrontendInputsAndOutputs::getFilenameOfFirstInput() const {
assert(hasInputs());
const InputFile &inp = AllInputs[0];
StringRef f = inp.file();
assert(!f.empty());
return f;
}
void FrontendInputsAndOutputs::forEachInput(
llvm::function_ref<void(const InputFile &)> fn) const {
for (const InputFile &input : AllInputs)
fn(input);
}
// Primaries:
const InputFile &FrontendInputsAndOutputs::firstPrimaryInput() const {
assert(!PrimaryInputs.empty());
for (const auto &f : AllInputs)
if (f.isPrimary())
return f;
llvm_unreachable("no first primary?!");
}
const InputFile &FrontendInputsAndOutputs::lastPrimaryInput() const {
assert(!PrimaryInputs.empty());
for (const auto &f : reversed(AllInputs))
if (f.isPrimary())
return f;
llvm_unreachable("no last primary?!");
}
void FrontendInputsAndOutputs::forEachPrimaryInput(
llvm::function_ref<void(const InputFile &)> fn) const {
for (auto &f : AllInputs)
if (f.isPrimary())
fn(f);
}
void FrontendInputsAndOutputs::assertMustNotBeMoreThanOnePrimaryInput() const {
assert(primaryInputCount() < 2 &&
"have not implemented >1 primary input yet");
}
void FrontendInputsAndOutputs::
assertMustNotBeMoreThanOnePrimaryInputUnlessBatchModeChecksHaveBeenBypassed()
const {
if (!areBatchModeChecksBypassed())
assertMustNotBeMoreThanOnePrimaryInput();
}
const InputFile *FrontendInputsAndOutputs::getUniquePrimaryInput() const {
assertMustNotBeMoreThanOnePrimaryInput();
const auto b = PrimaryInputs.begin();
return b == PrimaryInputs.end() ? nullptr : &AllInputs[b->second];
}
const InputFile &
FrontendInputsAndOutputs::getRequiredUniquePrimaryInput() const {
if (const auto *input = getUniquePrimaryInput())
return *input;
llvm_unreachable("No primary when one is required");
}
StringRef FrontendInputsAndOutputs::getNameOfUniquePrimaryInputFile() const {
const auto *input = getUniquePrimaryInput();
return input == nullptr ? StringRef() : input->file();
}
std::string FrontendInputsAndOutputs::getStatsFileMangledInputName() const {
// FIXME: "batch" should probably be some concatenation of all the primary
// input names, in order to keep the stats file names unique. (Or perhaps just
// the first primary?)
return isWholeModule()
? "all"
: primaryInputCount() == 1 ? firstPrimaryInput().file() : "batch";
}
bool FrontendInputsAndOutputs::isInputPrimary(StringRef file) const {
StringRef correctedFile =
InputFile::convertBufferNameFromLLVM_getFileOrSTDIN_toSwiftConventions(
file);
auto iterator = PrimaryInputs.find(correctedFile);
if (iterator == PrimaryInputs.end())
return false;
assert(AllInputs[iterator->second].isPrimary() &&
"PrimaryInputs should only hold primaries");
return true;
}
unsigned FrontendInputsAndOutputs::numberOfPrimaryInputsEndingWith(
const char *extension) const {
return count_if(
PrimaryInputs, [&](const llvm::StringMapEntry<unsigned> &elem) -> bool {
StringRef filename = AllInputs[elem.second].file();
return llvm::sys::path::extension(filename).endswith(extension);
});
}
// Input queries
bool FrontendInputsAndOutputs::shouldTreatAsLLVM() const {
if (hasSingleInput()) {
StringRef Input(getFilenameOfFirstInput());
return llvm::sys::path::extension(Input).endswith(LLVM_BC_EXTENSION) ||
llvm::sys::path::extension(Input).endswith(LLVM_IR_EXTENSION);
}
return false;
}
bool FrontendInputsAndOutputs::shouldTreatAsSIL() const {
if (hasSingleInput()) {
// If we have exactly one input filename, and its extension is "sil",
// treat the input as SIL.
StringRef Input(getFilenameOfFirstInput());
return llvm::sys::path::extension(Input).endswith(SIL_EXTENSION);
}
// If we have one primary input and it's a filename with extension "sil",
// treat the input as SIL.
unsigned silPrimaryCount = numberOfPrimaryInputsEndingWith(SIL_EXTENSION);
if (silPrimaryCount == 0)
return false;
if (silPrimaryCount == primaryInputCount()) {
// Not clear what to do someday with multiple primaries
assertMustNotBeMoreThanOnePrimaryInput();
return true;
}
llvm_unreachable("Either all primaries or none must end with .sil");
}
bool FrontendInputsAndOutputs::areAllNonPrimariesSIB() const {
for (const InputFile &input : AllInputs) {
if (input.isPrimary())
continue;
if (!llvm::sys::path::extension(input.file()).endswith(SIB_EXTENSION)) {
return false;
}
}
return true;
}
bool FrontendInputsAndOutputs::verifyInputs(DiagnosticEngine &diags,
bool treatAsSIL,
bool isREPLRequested,
bool isNoneRequested) const {
if (isREPLRequested) {
if (hasInputs()) {
diags.diagnose(SourceLoc(), diag::error_repl_requires_no_input_files);
return true;
}
} else if (treatAsSIL) {
if (isWholeModule()) {
if (inputCount() != 1) {
diags.diagnose(SourceLoc(), diag::error_mode_requires_one_input_file);
return true;
}
} else {
assertMustNotBeMoreThanOnePrimaryInput();
// If we have the SIL as our primary input, we can waive the one file
// requirement as long as all the other inputs are SIBs.
if (!areAllNonPrimariesSIB()) {
diags.diagnose(SourceLoc(),
diag::error_mode_requires_one_sil_multi_sib);
return true;
}
}
} else if (!isNoneRequested && !hasInputs()) {
diags.diagnose(SourceLoc(), diag::error_mode_requires_an_input_file);
return true;
}
return false;
}
// Changing inputs
void FrontendInputsAndOutputs::clearInputs() {
AllInputs.clear();
PrimaryInputs.clear();
}
void FrontendInputsAndOutputs::addInput(const InputFile &input) {
if (!input.file().empty() && input.isPrimary())
PrimaryInputs.insert(std::make_pair(input.file(), AllInputs.size()));
AllInputs.push_back(input);
}
void FrontendInputsAndOutputs::addInputFile(StringRef file,
llvm::MemoryBuffer *buffer) {
addInput(InputFile(file, false, buffer));
}
void FrontendInputsAndOutputs::addPrimaryInputFile(StringRef file,
llvm::MemoryBuffer *buffer) {
addInput(InputFile(file, true, buffer));
}
// Outputs
unsigned FrontendInputsAndOutputs::countOfInputsProducingMainOutputs() const {
return isSingleThreadedWMO()
? 1
: hasPrimaryInputs() ? primaryInputCount() : inputCount();
}
const InputFile &FrontendInputsAndOutputs::firstInputProducingOutput() const {
return isSingleThreadedWMO()
? firstInput()
: hasPrimaryInputs() ? firstPrimaryInput() : firstInput();
}
const InputFile &FrontendInputsAndOutputs::lastInputProducingOutput() const {
return isSingleThreadedWMO()
? firstInput()
: hasPrimaryInputs() ? lastPrimaryInput() : lastInput();
}
void FrontendInputsAndOutputs::forEachInputProducingAMainOutputFile(
llvm::function_ref<void(const InputFile &)> fn) const {
isSingleThreadedWMO()
? fn(firstInput())
: hasPrimaryInputs() ? forEachPrimaryInput(fn) : forEachInput(fn);
}
void FrontendInputsAndOutputs::setMainOutputs(
ArrayRef<std::string> outputFiles) {
assert(countOfInputsProducingMainOutputs() == outputFiles.size());
if (hasPrimaryInputs()) {
unsigned i = 0;
for (auto index : indices(AllInputs)) {
InputFile &f = AllInputs[index];
if (f.isPrimary())
f.setOutputFilename(outputFiles[i++]);
}
} else if (isSingleThreadedWMO()) {
AllInputs[0].setOutputFilename(outputFiles[0]);
} else {
for (auto i : indices(AllInputs))
AllInputs[i].setOutputFilename(outputFiles[i]);
}
}
std::vector<std::string> FrontendInputsAndOutputs::copyOutputFilenames() const {
std::vector<std::string> outputs;
forEachInputProducingAMainOutputFile([&](const InputFile &input) -> void {
outputs.push_back(input.outputFilename());
});
return outputs;
}
void FrontendInputsAndOutputs::forEachOutputFilename(
llvm::function_ref<void(const std::string &)> fn) const {
forEachInputProducingAMainOutputFile(
[&](const InputFile &input) -> void { fn(input.outputFilename()); });
}
StringRef FrontendInputsAndOutputs::getSingleOutputFilename() const {
assertMustNotBeMoreThanOnePrimaryInputUnlessBatchModeChecksHaveBeenBypassed();
return hasInputs() ? StringRef(lastInputProducingOutput().outputFilename())
: StringRef();
}
bool FrontendInputsAndOutputs::isOutputFilenameStdout() const {
return getSingleOutputFilename() == "-";
}
bool FrontendInputsAndOutputs::isOutputFileDirectory() const {
return hasNamedOutputFile() &&
llvm::sys::fs::is_directory(getSingleOutputFilename());
}
bool FrontendInputsAndOutputs::hasNamedOutputFile() const {
return hasInputs() && !isOutputFilenameStdout();
}
// Supplementary outputs
void FrontendInputsAndOutputs::forEachInputProducingSupplementaryOutput(
llvm::function_ref<void(const InputFile &)> fn) const {
if (hasPrimaryInputs())
forEachPrimaryInput(fn);
else
fn(firstInput());
}

View File

@@ -95,12 +95,13 @@ bool FrontendOptions::isActionImmediate(ActionType action) {
}
void FrontendOptions::forAllOutputPaths(
std::function<void(const std::string &)> fn) const {
const InputFile &input, std::function<void(const std::string &)> fn) const {
if (RequestedAction != FrontendOptions::ActionType::EmitModuleOnly &&
RequestedAction != FrontendOptions::ActionType::MergeModules) {
for (const std::string &OutputFileName : OutputFilenames) {
fn(OutputFileName);
}
if (InputsAndOutputs.isWholeModule())
InputsAndOutputs.forEachOutputFilename(fn);
else
fn(input.outputFilename());
}
const std::string *outputs[] = {
&ModuleOutputPath,
@@ -115,23 +116,18 @@ void FrontendOptions::forAllOutputPaths(
StringRef FrontendOptions::originalPath() const {
if (hasNamedOutputFile())
if (InputsAndOutputs.hasNamedOutputFile())
// Put the serialized diagnostics file next to the output file.
return getSingleOutputFilename();
return InputsAndOutputs.getSingleOutputFilename();
// If we have a primary input, so use that as the basis for the name of the
// serialized diagnostics file, otherwise fall back on the
// module name.
const auto input = Inputs.getUniquePrimaryInput();
const auto input = InputsAndOutputs.getUniquePrimaryInput();
return input ? llvm::sys::path::filename(input->file())
: StringRef(ModuleName);
}
bool FrontendOptions::isOutputFileDirectory() const {
return hasNamedOutputFile() &&
llvm::sys::fs::is_directory(getSingleOutputFilename());
}
const char *
FrontendOptions::suffixForPrincipalOutputFileForAction(ActionType action) {
switch (action) {

View File

@@ -101,7 +101,8 @@ static std::string displayName(StringRef MainExecutablePath) {
/// Emits a Make-style dependencies file.
static bool emitMakeDependencies(DiagnosticEngine &diags,
DependencyTracker &depTracker,
const FrontendOptions &opts) {
const FrontendOptions &opts,
const InputFile &input) {
std::error_code EC;
llvm::raw_fd_ostream out(opts.DependenciesFilePath, EC,
llvm::sys::fs::F_None);
@@ -135,12 +136,12 @@ static bool emitMakeDependencies(DiagnosticEngine &diags,
// FIXME: Xcode can't currently handle multiple targets in a single
// dependency line.
opts.forAllOutputPaths([&](StringRef targetName) {
opts.forAllOutputPaths(input, [&](StringRef targetName) {
out << escape(targetName) << " :";
// First include all other files in the module. Make-style dependencies
// need to be conservative!
for (auto const &path :
reversePathSortedFilenames(opts.Inputs.getInputFilenames()))
reversePathSortedFilenames(opts.InputsAndOutputs.getInputFilenames()))
out << ' ' << escape(path);
// Then print dependencies we've picked up during compilation.
for (auto const &path :
@@ -152,6 +153,17 @@ static bool emitMakeDependencies(DiagnosticEngine &diags,
return false;
}
static bool emitMakeDependencies(DiagnosticEngine &diags,
DependencyTracker &depTracker,
const FrontendOptions &opts) {
bool hadError = false;
opts.InputsAndOutputs.forEachInputProducingSupplementaryOutput(
[&](const InputFile &f) -> void {
hadError = emitMakeDependencies(diags, depTracker, opts, f) || hadError;
});
return hadError;
}
namespace {
struct LoadedModuleTraceFormat {
std::string Name;
@@ -548,15 +560,17 @@ static bool performCompile(CompilerInstance &Instance,
auto &PCHOutDir = ImporterOpts.PrecompiledHeaderOutputDir;
if (!PCHOutDir.empty()) {
ImporterOpts.BridgingHeader =
Invocation.getFrontendOptions().Inputs.getFilenameOfFirstInput();
Invocation.getFrontendOptions()
.InputsAndOutputs.getFilenameOfFirstInput();
// Create or validate a persistent PCH.
auto SwiftPCHHash = Invocation.getPCHHash();
auto PCH = clangImporter->getOrCreatePCH(ImporterOpts, SwiftPCHHash);
return !PCH.hasValue();
}
return clangImporter->emitBridgingPCH(
Invocation.getFrontendOptions().Inputs.getFilenameOfFirstInput(),
opts.getSingleOutputFilename());
Invocation.getFrontendOptions()
.InputsAndOutputs.getFilenameOfFirstInput(),
opts.InputsAndOutputs.getSingleOutputFilename());
}
IRGenOptions &IRGenOpts = Invocation.getIRGenOptions();
@@ -566,15 +580,17 @@ static bool performCompile(CompilerInstance &Instance,
auto &LLVMContext = getGlobalLLVMContext();
// Load in bitcode file.
assert(Invocation.getFrontendOptions().Inputs.hasSingleInput() &&
assert(Invocation.getFrontendOptions().InputsAndOutputs.hasSingleInput() &&
"We expect a single input for bitcode input!");
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
llvm::MemoryBuffer::getFileOrSTDIN(
Invocation.getFrontendOptions().Inputs.getFilenameOfFirstInput());
Invocation.getFrontendOptions()
.InputsAndOutputs.getFilenameOfFirstInput());
if (!FileBufOrErr) {
Instance.getASTContext().Diags.diagnose(
SourceLoc(), diag::error_open_input_file,
Invocation.getFrontendOptions().Inputs.getFilenameOfFirstInput(),
Invocation.getFrontendOptions()
.InputsAndOutputs.getFilenameOfFirstInput(),
FileBufOrErr.getError().message());
return true;
}
@@ -589,7 +605,8 @@ static bool performCompile(CompilerInstance &Instance,
// if available.
Instance.getASTContext().Diags.diagnose(
SourceLoc(), diag::error_parse_input_file,
Invocation.getFrontendOptions().Inputs.getFilenameOfFirstInput(),
Invocation.getFrontendOptions()
.InputsAndOutputs.getFilenameOfFirstInput(),
Err.getMessage());
return true;
}
@@ -719,7 +736,7 @@ static bool performCompile(CompilerInstance &Instance,
SF->dumpInterfaceHash(llvm::errs());
else if (Action == FrontendOptions::ActionType::EmitSyntax) {
emitSyntax(SF, Invocation.getLangOptions(), Instance.getSourceMgr(),
opts.getSingleOutputFilename());
opts.InputsAndOutputs.getSingleOutputFilename());
} else
SF->dump();
return Context.hadError();
@@ -806,16 +823,14 @@ static bool performCompile(CompilerInstance &Instance,
auto SASTF = dyn_cast<SerializedASTFile>(File);
return SASTF && SASTF->isSIB();
};
if (opts.Inputs.hasPrimaryInputs()) {
if (opts.InputsAndOutputs.hasPrimaryInputs()) {
if (Instance.getPrimarySourceFiles().empty()) {
// If we have primary inputs but no primary _source files_, we might
// have a primary serialized input.
for (FileUnit *fileUnit : mod->getFiles()) {
if (auto SASTF = dyn_cast<SerializedASTFile>(fileUnit)) {
if (Invocation.getFrontendOptions().Inputs.isInputPrimary(
InputFile::
convertBufferNameFromLLVM_getFileOrSTDIN_toSwiftConventions(
SASTF->getFilename()))) {
if (Invocation.getFrontendOptions().InputsAndOutputs.isInputPrimary(
SASTF->getFilename())) {
assert(PSGIs.empty() && "Can only handle one primary AST input");
auto SM = performSILGeneration(*SASTF, SILOpts, None);
PSGIs.push_back(
@@ -887,7 +902,8 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll)
performSILLinking(SM.get(), true);
return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL,
opts.getSingleOutputFilename(), opts.EmitSortedSIL);
opts.InputsAndOutputs.getSingleOutputFilename(),
opts.EmitSortedSIL);
}
if (Action == FrontendOptions::ActionType::EmitSIBGen) {
@@ -1065,7 +1081,8 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
// We've been told to write canonical SIL, so write it now.
if (Action == FrontendOptions::ActionType::EmitSIL) {
return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL,
opts.getSingleOutputFilename(), opts.EmitSortedSIL);
opts.InputsAndOutputs.getSingleOutputFilename(),
opts.EmitSortedSIL);
}
assert(Action >= FrontendOptions::ActionType::Immediate &&
@@ -1109,12 +1126,12 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
IRModule = performIRGeneration(IRGenOpts,
*MSF.get<SourceFile*>(),
std::move(SM),
opts.getSingleOutputFilename(), LLVMContext,
opts.InputsAndOutputs.getSingleOutputFilename(), LLVMContext,
0, &HashGlobal);
} else {
IRModule = performIRGeneration(IRGenOpts, MSF.get<ModuleDecl*>(),
std::move(SM),
opts.getSingleOutputFilename(), LLVMContext,
opts.InputsAndOutputs.getSingleOutputFilename(), LLVMContext,
&HashGlobal);
}
@@ -1178,8 +1195,10 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
// Now that we have a single IR Module, hand it over to performLLVM.
return performLLVM(IRGenOpts, &Instance.getDiags(), nullptr, HashGlobal,
IRModule.get(), TargetMachine.get(), EffectiveLanguageVersion,
opts.getSingleOutputFilename(), Stats) || HadError;
IRModule.get(), TargetMachine.get(),
EffectiveLanguageVersion,
opts.InputsAndOutputs.getSingleOutputFilename(), Stats) ||
HadError;
}
static bool emitIndexData(SourceFile *PrimarySourceFile,
@@ -1204,18 +1223,17 @@ static bool emitIndexData(SourceFile *PrimarySourceFile,
if (PrimarySourceFile) {
if (index::indexAndRecord(
PrimarySourceFile, opts.getSingleOutputFilename(),
opts.IndexStorePath, opts.IndexSystemModules,
isDebugCompilation, Invocation.getTargetTriple(),
*Instance.getDependencyTracker())) {
PrimarySourceFile, opts.InputsAndOutputs.getSingleOutputFilename(),
opts.IndexStorePath, opts.IndexSystemModules, isDebugCompilation,
Invocation.getTargetTriple(), *Instance.getDependencyTracker())) {
return true;
}
} else {
StringRef moduleToken = opts.ModuleOutputPath;
if (moduleToken.empty())
moduleToken = opts.getSingleOutputFilename();
moduleToken = opts.InputsAndOutputs.getSingleOutputFilename();
if (index::indexAndRecord(Instance.getMainModule(), opts.OutputFilenames,
if (index::indexAndRecord(Instance.getMainModule(), opts.InputsAndOutputs.copyOutputFilenames(),
moduleToken, opts.IndexStorePath,
opts.IndexSystemModules,
isDebugCompilation, Invocation.getTargetTriple(),
@@ -1301,6 +1319,36 @@ silOptModeArgStr(OptimizationMode mode) {
}
}
static std::unique_ptr<UnifiedStatsReporter>
computeStatsReporter(const CompilerInvocation &Invocation, CompilerInstance *Instance) {
const std::string &StatsOutputDir =
Invocation.getFrontendOptions().StatsOutputDir;
std::unique_ptr<UnifiedStatsReporter> StatsReporter;
if (StatsOutputDir.empty())
return std::unique_ptr<UnifiedStatsReporter>();
auto &FEOpts = Invocation.getFrontendOptions();
auto &LangOpts = Invocation.getLangOptions();
auto &SILOpts = Invocation.getSILOptions();
std::string InputName =
FEOpts.InputsAndOutputs.getStatsFileMangledInputName();
StringRef OptType = silOptModeArgStr(SILOpts.OptMode);
StringRef OutFile =
FEOpts.InputsAndOutputs.lastInputProducingOutput().outputFilename();
StringRef OutputType = llvm::sys::path::extension(OutFile);
std::string TripleName = LangOpts.Target.normalize();
auto Trace = Invocation.getFrontendOptions().TraceStats;
SourceManager *SM = &Instance->getSourceMgr();
clang::SourceManager *CSM = nullptr;
if (auto *clangImporter = static_cast<ClangImporter *>(
Instance->getASTContext().getClangModuleLoader())) {
CSM = &clangImporter->getClangASTContext().getSourceManager();
}
return llvm::make_unique<UnifiedStatsReporter>(
"swift-frontend", FEOpts.ModuleName, InputName, TripleName, OutputType,
OptType, StatsOutputDir, SM, CSM, Trace);
}
int swift::performFrontend(ArrayRef<const char *> Args,
const char *Argv0, void *MainAddr,
FrontendObserver *observer) {
@@ -1465,35 +1513,9 @@ int swift::performFrontend(ArrayRef<const char *> Args,
return finishDiagProcessing(1);
}
const std::string &StatsOutputDir =
Invocation.getFrontendOptions().StatsOutputDir;
std::unique_ptr<UnifiedStatsReporter> StatsReporter;
if (!StatsOutputDir.empty()) {
auto &FEOpts = Invocation.getFrontendOptions();
auto &LangOpts = Invocation.getLangOptions();
auto &SILOpts = Invocation.getSILOptions();
StringRef InputName = FEOpts.Inputs.getNameOfUniquePrimaryInputFile();
StringRef OptType = silOptModeArgStr(SILOpts.OptMode);
StringRef OutFile = FEOpts.getSingleOutputFilename();
StringRef OutputType = llvm::sys::path::extension(OutFile);
std::string TripleName = LangOpts.Target.normalize();
SourceManager *SM = &Instance->getSourceMgr();
clang::SourceManager *CSM = nullptr;
if (auto *clangImporter = static_cast<ClangImporter *>(
Instance->getASTContext().getClangModuleLoader())) {
CSM = &clangImporter->getClangASTContext().getSourceManager();
}
auto Trace = Invocation.getFrontendOptions().TraceStats;
StatsReporter = llvm::make_unique<UnifiedStatsReporter>("swift-frontend",
FEOpts.ModuleName,
InputName,
TripleName,
OutputType,
OptType,
StatsOutputDir,
SM, CSM,
Trace);
std::unique_ptr<UnifiedStatsReporter> StatsReporter =
computeStatsReporter(Invocation, Instance.get());
if (StatsReporter) {
// Install stats-reporter somewhere visible for subsystems that
// need to bump counters as they work, rather than measure
// accumulated work on completion (mostly: TypeChecker).

View File

@@ -46,7 +46,7 @@ static void findAllClangImports(const clang::Module *module,
bool swift::emitImportedModules(ASTContext &Context, ModuleDecl *mainModule,
const FrontendOptions &opts) {
auto path = opts.getSingleOutputFilename();
auto path = opts.InputsAndOutputs.getSingleOutputFilename();
std::error_code EC;
llvm::raw_fd_ostream out(path, EC, llvm::sys::fs::F_None);

View File

@@ -1050,7 +1050,7 @@ getNotableRegions(StringRef SourceText, unsigned NameOffset, StringRef Name,
CompilerInvocation Invocation{};
Invocation.getFrontendOptions().Inputs.addInput(
Invocation.getFrontendOptions().InputsAndOutputs.addInput(
InputFile("<extract>", true, InputBuffer.get()));
Invocation.getFrontendOptions().ModuleName = "extract";

View File

@@ -118,7 +118,7 @@ Migrator::performAFixItMigration(version::Version SwiftLanguageVersion) {
llvm::MemoryBuffer::getMemBufferCopy(InputText, getInputFilename());
CompilerInvocation Invocation { StartInvocation };
Invocation.getFrontendOptions().Inputs.clearInputs();
Invocation.getFrontendOptions().InputsAndOutputs.clearInputs();
Invocation.getLangOptions().EffectiveLanguageVersion = SwiftLanguageVersion;
auto &LLVMArgs = Invocation.getFrontendOptions().LLVMArgs;
auto aarch64_use_tbi = std::find(LLVMArgs.begin(), LLVMArgs.end(),
@@ -144,10 +144,10 @@ Migrator::performAFixItMigration(version::Version SwiftLanguageVersion) {
const auto &OrigFrontendOpts = StartInvocation.getFrontendOptions();
assert(OrigFrontendOpts.Inputs.hasPrimaryInputs() &&
assert(OrigFrontendOpts.InputsAndOutputs.hasPrimaryInputs() &&
"Migration must have a primary");
for (const auto &input : OrigFrontendOpts.Inputs.getAllInputs()) {
Invocation.getFrontendOptions().Inputs.addInput(
for (const auto &input : OrigFrontendOpts.InputsAndOutputs.getAllInputs()) {
Invocation.getFrontendOptions().InputsAndOutputs.addInput(
InputFile(input.file(), input.isPrimary(),
input.isPrimary() ? InputBuffer.get() : input.buffer()));
}
@@ -438,6 +438,6 @@ const MigratorOptions &Migrator::getMigratorOptions() const {
const StringRef Migrator::getInputFilename() const {
auto &PrimaryInput = StartInvocation.getFrontendOptions()
.Inputs.getRequiredUniquePrimaryInput();
.InputsAndOutputs.getRequiredUniquePrimaryInput();
return PrimaryInput.file();
}

View File

@@ -1,7 +1,7 @@
// Check that we don't crash when we verify after every pass.
// RUN: %empty-directory(%t)
//
// RUN: %target-swift-frontend %s -I %S/../stdlib/Inputs/Mirror/ -o %t/Mirror \
// RUN: %target-swift-frontend %s -I %S/../stdlib/Inputs/Mirror/ \
// RUN: -emit-ir -sil-verify-all -o /dev/null
class A : CustomReflectable {

View File

@@ -1,7 +1,7 @@
// REQUIRES: objc_interop
// REQUIRES: OS=macosx
// RUN: %target-swift-frontend -typecheck -swift-version 3 %s
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -emit-migrated-file-path %t/nsopengl_openglversion.swift.result -o %t/nsopengl_openglversion.swift.remap -o /dev/null
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -emit-migrated-file-path %t/nsopengl_openglversion.swift.result -o /dev/null
// RUN: diff -u %S/nsopengl_openglversion.swift.expected %t/nsopengl_openglversion.swift.result
// RUN: %target-swift-frontend -typecheck -swift-version 4 %t/nsopengl_openglversion.swift.result

View File

@@ -1,7 +1,7 @@
// REQUIRES: objc_interop
// REQUIRES: OS=macosx
// RUN: %target-swift-frontend -typecheck -swift-version 3 %s
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -emit-migrated-file-path %t/nsopengl_openglversion.swift.result -o %t/nsopengl_openglversion.swift.remap -o /dev/null
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -emit-migrated-file-path %t/nsopengl_openglversion.swift.result -o /dev/null
// RUN: diff -u %S/nsopengl_openglversion.swift.expected %t/nsopengl_openglversion.swift.result
// RUN: %target-swift-frontend -typecheck -swift-version 4 %t/nsopengl_openglversion.swift.result

View File

@@ -1,7 +1,7 @@
// REQUIRES: objc_interop
// RUN: %empty-directory(%t.mod)
// RUN: %target-swift-frontend -emit-module -o %t.mod/Cities.swiftmodule %S/Inputs/Cities.swift -module-name Cities -parse-as-library
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/rename-func-decl.swift.result -o %t/rename-func-decl.swift.remap -o /dev/null
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/rename-func-decl.swift.result -o %t/rename-func-decl.swift.remap
// RUN: diff -u %S/rename-func-decl.swift.expected %t/rename-func-decl.swift.result
import Cities

View File

@@ -1,7 +1,7 @@
// REQUIRES: objc_interop
// RUN: %empty-directory(%t.mod)
// RUN: %target-swift-frontend -emit-module -o %t.mod/Cities.swiftmodule %S/Inputs/Cities.swift -module-name Cities -parse-as-library
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/rename-func-decl.swift.result -o %t/rename-func-decl.swift.remap -o /dev/null
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/rename-func-decl.swift.result -o %t/rename-func-decl.swift.remap
// RUN: diff -u %S/rename-func-decl.swift.expected %t/rename-func-decl.swift.result
import Cities

View File

@@ -1,7 +1,7 @@
// REQUIRES: objc_interop
// RUN: %empty-directory(%t.mod)
// RUN: %target-swift-frontend -emit-module -o %t.mod/Cities.swiftmodule %S/Inputs/Cities.swift -module-name Cities -parse-as-library
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/wrap_optional.swift.result -o %t/wrap_optional.swift.remap -o /dev/null
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/wrap_optional.swift.result -o /dev/null
// RUN: diff -u %S/wrap_optional.swift.expected %t/wrap_optional.swift.result
import Cities

View File

@@ -1,7 +1,7 @@
// REQUIRES: objc_interop
// RUN: %empty-directory(%t.mod)
// RUN: %target-swift-frontend -emit-module -o %t.mod/Cities.swiftmodule %S/Inputs/Cities.swift -module-name Cities -parse-as-library
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/wrap_optional.swift.result -o %t/wrap_optional.swift.remap -o /dev/null
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/wrap_optional.swift.result -o /dev/null
// RUN: diff -u %S/wrap_optional.swift.expected %t/wrap_optional.swift.result
import Cities

View File

@@ -83,13 +83,15 @@ struct InvocationOptions {
// Assert invocation with a primary file. We want to avoid full typechecking
// for all files.
assert(!this->PrimaryFile.empty());
assert(this->Invok.getFrontendOptions().Inputs.hasUniquePrimaryInput() &&
assert(this->Invok.getFrontendOptions()
.InputsAndOutputs.hasUniquePrimaryInput() &&
"Must have exactly one primary input for code completion, etc.");
}
void applyTo(CompilerInvocation &CompInvok) const;
void applyToSubstitutingInputs(CompilerInvocation &CompInvok,
FrontendInputs &&Inputs) const;
void
applyToSubstitutingInputs(CompilerInvocation &CompInvok,
FrontendInputsAndOutputs &&InputsAndOutputs) const;
void profile(llvm::FoldingSetNodeID &ID) const;
void raw(std::vector<std::string> &Args, std::string &PrimaryFile) const;
@@ -135,9 +137,10 @@ void InvocationOptions::applyTo(CompilerInvocation &CompInvok) const {
CompInvok = this->Invok;
}
void InvocationOptions::applyToSubstitutingInputs(
CompilerInvocation &CompInvok, FrontendInputs &&inputs) const {
CompilerInvocation &CompInvok,
FrontendInputsAndOutputs &&inputsAndOutputs) const {
CompInvok = this->Invok;
CompInvok.getFrontendOptions().Inputs = inputs;
CompInvok.getFrontendOptions().InputsAndOutputs = inputsAndOutputs;
}
void InvocationOptions::raw(std::vector<std::string> &Args,
@@ -373,11 +376,12 @@ static void setModuleName(CompilerInvocation &Invocation) {
StringRef Filename = Invocation.getOutputFilename();
if (Filename.empty()) {
if (!Invocation.getFrontendOptions().Inputs.hasInputs()) {
if (!Invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) {
Invocation.setModuleName("__main__");
return;
}
Filename = Invocation.getFrontendOptions().Inputs.getFilenameOfFirstInput();
Filename = Invocation.getFrontendOptions()
.InputsAndOutputs.getFilenameOfFirstInput();
}
Filename = llvm::sys::path::filename(Filename);
StringRef ModuleName = llvm::sys::path::stem(Filename);
@@ -409,16 +413,16 @@ static void sanitizeCompilerArgs(ArrayRef<const char *> Args,
}
}
static FrontendInputs
static FrontendInputsAndOutputs
convertFileContentsToInputs(const SmallVectorImpl<FileContent> &contents) {
FrontendInputs inputs;
FrontendInputsAndOutputs inputsAndOutputs;
for (const FileContent &content : contents)
inputs.addInput(InputFile(content));
return inputs;
inputsAndOutputs.addInput(InputFile(content));
return inputsAndOutputs;
}
static FrontendInputs
resolveSymbolicLinksInInputs(FrontendInputs &inputs,
static FrontendInputsAndOutputs
resolveSymbolicLinksInInputs(FrontendInputsAndOutputs &inputsAndOutputs,
StringRef UnresolvedPrimaryFile,
std::string &Error) {
unsigned primaryCount = 0;
@@ -426,8 +430,8 @@ resolveSymbolicLinksInInputs(FrontendInputs &inputs,
SwiftLangSupport::resolvePathSymlinks(UnresolvedPrimaryFile);
// FIXME: The frontend should be dealing with symlinks, maybe similar to
// clang's FileManager ?
FrontendInputs replacementInputs;
for (const InputFile &input : inputs.getAllInputs()) {
FrontendInputsAndOutputs replacementInputsAndOutputs;
for (const InputFile &input : inputsAndOutputs.getAllInputs()) {
std::string newFilename =
SwiftLangSupport::resolvePathSymlinks(input.file());
bool newIsPrimary = input.isPrimary() ||
@@ -436,19 +440,19 @@ resolveSymbolicLinksInInputs(FrontendInputs &inputs,
++primaryCount;
}
assert(primaryCount < 2 && "cannot handle multiple primaries");
replacementInputs.addInput(
replacementInputsAndOutputs.addInput(
InputFile(newFilename, newIsPrimary, input.buffer()));
}
if (PrimaryFile.empty() || primaryCount == 1) {
return replacementInputs;
return replacementInputsAndOutputs;
}
llvm::SmallString<64> Err;
llvm::raw_svector_ostream OS(Err);
OS << "'" << PrimaryFile << "' is not part of the input files";
Error = OS.str();
return replacementInputs;
return replacementInputsAndOutputs;
}
bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation,
@@ -465,8 +469,10 @@ bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation,
Error = "error when parsing the compiler arguments";
return true;
}
Invocation.getFrontendOptions().Inputs = resolveSymbolicLinksInInputs(
Invocation.getFrontendOptions().Inputs, UnresolvedPrimaryFile, Error);
Invocation.getFrontendOptions().InputsAndOutputs =
resolveSymbolicLinksInInputs(
Invocation.getFrontendOptions().InputsAndOutputs,
UnresolvedPrimaryFile, Error);
if (!Error.empty())
return true;
@@ -707,9 +713,9 @@ bool ASTProducer::shouldRebuild(SwiftASTManager::Implementation &MgrImpl,
// Check if the inputs changed.
SmallVector<BufferStamp, 8> InputStamps;
InputStamps.reserve(
Invok.Opts.Invok.getFrontendOptions().Inputs.inputCount());
Invok.Opts.Invok.getFrontendOptions().InputsAndOutputs.inputCount());
for (const auto &input :
Invok.Opts.Invok.getFrontendOptions().Inputs.getAllInputs()) {
Invok.Opts.Invok.getFrontendOptions().InputsAndOutputs.getAllInputs()) {
StringRef File = input.file();
bool FoundSnapshot = false;
for (auto &Snap : Snapshots) {
@@ -723,7 +729,7 @@ bool ASTProducer::shouldRebuild(SwiftASTManager::Implementation &MgrImpl,
InputStamps.push_back(MgrImpl.getBufferStamp(File));
}
assert(InputStamps.size() ==
Invok.Opts.Invok.getFrontendOptions().Inputs.inputCount());
Invok.Opts.Invok.getFrontendOptions().InputsAndOutputs.inputCount());
if (Stamps != InputStamps)
return true;
@@ -896,7 +902,7 @@ void ASTProducer::findSnapshotAndOpenFiles(
SmallVectorImpl<FileContent> &Contents, std::string &Error) const {
const InvocationOptions &Opts = InvokRef->Impl.Opts;
for (const auto &input :
Opts.Invok.getFrontendOptions().Inputs.getAllInputs()) {
Opts.Invok.getFrontendOptions().InputsAndOutputs.getAllInputs()) {
StringRef File = input.file();
bool IsPrimary = input.isPrimary();
bool FoundSnapshot = false;
@@ -920,5 +926,5 @@ void ASTProducer::findSnapshotAndOpenFiles(
Contents.push_back(std::move(Content));
}
assert(Contents.size() ==
Opts.Invok.getFrontendOptions().Inputs.inputCount());
Opts.Invok.getFrontendOptions().InputsAndOutputs.inputCount());
}

View File

@@ -144,7 +144,7 @@ static bool swiftCodeCompleteImpl(SwiftLangSupport &Lang,
if (Failed) {
return false;
}
if (!Invocation.getFrontendOptions().Inputs.hasInputs()) {
if (!Invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) {
Error = "no input filenames specified";
return false;
}

View File

@@ -773,13 +773,13 @@ private:
static bool makeParserAST(CompilerInstance &CI, StringRef Text,
CompilerInvocation Invocation) {
Invocation.getFrontendOptions().Inputs.clearInputs();
Invocation.getFrontendOptions().InputsAndOutputs.clearInputs();
Invocation.setModuleName("main");
Invocation.setInputKind(InputFileKind::IFK_Swift);
std::unique_ptr<llvm::MemoryBuffer> Buf;
Buf = llvm::MemoryBuffer::getMemBuffer(Text, "<module-interface>");
Invocation.getFrontendOptions().Inputs.addInput(
Invocation.getFrontendOptions().InputsAndOutputs.addInput(
InputFile(Buf.get()->getBufferIdentifier(), false, Buf.get()));
if (CI.setup(Invocation))
return true;
@@ -1094,7 +1094,7 @@ static bool reportSourceDocInfo(CompilerInvocation Invocation,
EditorDiagConsumer DiagConsumer;
CI.addDiagnosticConsumer(&DiagConsumer);
Invocation.getFrontendOptions().Inputs.addInput(
Invocation.getFrontendOptions().InputsAndOutputs.addInput(
InputFile(InputBuf->getBufferIdentifier(), false, InputBuf));
if (CI.setup(Invocation))
return true;
@@ -1367,7 +1367,7 @@ SourceFile *SwiftLangSupport::getSyntacticSourceFile(
return nullptr;
}
Invocation.setInputKind(InputFileKind::IFK_Swift);
Invocation.getFrontendOptions().Inputs.addInput(
Invocation.getFrontendOptions().InputsAndOutputs.addInput(
InputFile(InputBuf->getBufferIdentifier(), false, InputBuf));
if (ParseCI.setup(Invocation)) {
@@ -1443,7 +1443,7 @@ findModuleGroups(StringRef ModuleName, ArrayRef<const char *> Args,
StringRef Error)> Receiver) {
CompilerInvocation Invocation;
Invocation.getClangImporterOptions().ImportForwardDeclarations = true;
Invocation.getFrontendOptions().Inputs.clearInputs();
Invocation.getFrontendOptions().InputsAndOutputs.clearInputs();
CompilerInstance CI;
// Display diagnostics to stderr.

View File

@@ -228,13 +228,13 @@ public:
static bool makeParserAST(CompilerInstance &CI, StringRef Text,
CompilerInvocation Invocation) {
Invocation.getFrontendOptions().Inputs.clearInputs();
Invocation.getFrontendOptions().InputsAndOutputs.clearInputs();
Invocation.setModuleName("main");
Invocation.setInputKind(InputFileKind::IFK_Swift);
std::unique_ptr<llvm::MemoryBuffer> Buf;
Buf = llvm::MemoryBuffer::getMemBuffer(Text, "<module-interface>");
Invocation.getFrontendOptions().Inputs.addInput(
Invocation.getFrontendOptions().InputsAndOutputs.addInput(
InputFile(Buf.get()->getBufferIdentifier(), false, Buf.get()));
if (CI.setup(Invocation))
return true;
@@ -402,7 +402,7 @@ SwiftInterfaceGenContext::create(StringRef DocumentName,
// Display diagnostics to stderr.
CI.addDiagnosticConsumer(&IFaceGenCtx->Impl.DiagConsumer);
Invocation.getFrontendOptions().Inputs.clearInputs();
Invocation.getFrontendOptions().InputsAndOutputs.clearInputs();
if (CI.setup(Invocation)) {
ErrMsg = "Error during invocation setup";
return nullptr;

View File

@@ -279,7 +279,7 @@ void SwiftLangSupport::indexSource(StringRef InputFile,
return;
}
if (!Invocation.getFrontendOptions().Inputs.hasInputs()) {
if (!Invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) {
IdxConsumer.failed("no input filenames specified");
return;
}

View File

@@ -729,7 +729,8 @@ static int doCodeCompletion(const CompilerInvocation &InitInvok,
Invocation.setCodeCompletionFactory(CompletionCallbacksFactory.get());
if (!SecondSourceFileName.empty()) {
Invocation.getFrontendOptions().Inputs.addInputFile(SecondSourceFileName);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(
SecondSourceFileName);
}
CompilerInstance CI;
@@ -955,7 +956,7 @@ static int doSyntaxColoring(const CompilerInvocation &InitInvok,
bool RunTypeChecker,
bool Playground) {
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
Invocation.getLangOptions().DisableAvailabilityChecking = false;
CompilerInstance CI;
@@ -998,7 +999,7 @@ static int doDumpImporterLookupTables(const CompilerInvocation &InitInvok,
}
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
CompilerInstance CI;
@@ -1178,7 +1179,7 @@ static int doStructureAnnotation(const CompilerInvocation &InitInvok,
StringRef SourceFilename) {
CompilerInvocation Invocation(InitInvok);
Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
CompilerInstance CI;
@@ -1434,7 +1435,7 @@ static int doSemanticAnnotation(const CompilerInvocation &InitInvok,
StringRef SourceFilename,
bool TerminalOutput) {
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
CompilerInstance CI;
@@ -1499,7 +1500,7 @@ static int doPrintAST(const CompilerInvocation &InitInvok,
StringRef MangledNameToFind,
StringRef DebugClientDiscriminator) {
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
CompilerInstance CI;
@@ -1930,7 +1931,8 @@ static int doPrintSwiftFileInterface(const CompilerInvocation &InitInvok,
StringRef SourceFilename,
bool AnnotatePrint) {
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addPrimaryInputFile(SourceFilename);
Invocation.getFrontendOptions().InputsAndOutputs.addPrimaryInputFile(
SourceFilename);
Invocation.getLangOptions().AttachCommentsToDecls = true;
CompilerInstance CI;
// Display diagnostics to stderr.
@@ -1960,7 +1962,8 @@ static int doPrintDecls(const CompilerInvocation &InitInvok,
const PrintOptions &Options,
bool AnnotatePrint) {
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addPrimaryInputFile(SourceFilename);
Invocation.getFrontendOptions().InputsAndOutputs.addPrimaryInputFile(
SourceFilename);
Invocation.getLangOptions().AttachCommentsToDecls = true;
CompilerInstance CI;
// Display diagnostics to stderr.
@@ -2071,7 +2074,7 @@ static int doPrintTypes(const CompilerInvocation &InitInvok,
StringRef SourceFilename,
bool FullyQualifiedTypes) {
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
CompilerInstance CI;
// Display diagnostics to stderr.
@@ -2297,7 +2300,7 @@ public:
static int doDumpComments(const CompilerInvocation &InitInvok,
StringRef SourceFilename) {
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
Invocation.getLangOptions().AttachCommentsToDecls = true;
CompilerInstance CI;
// Display diagnostics to stderr.
@@ -2319,7 +2322,7 @@ static int doPrintComments(const CompilerInvocation &InitInvok,
StringRef SourceFilename,
StringRef CommentsXMLSchema) {
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
Invocation.getLangOptions().AttachCommentsToDecls = true;
Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
@@ -2449,7 +2452,7 @@ static int doPrintTypeInterface(const CompilerInvocation &InitInvok,
if (!Pair.hasValue())
return 1;
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addInputFile(FileName);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(FileName);
CompilerInstance CI;
if (CI.setup(Invocation))
return 1;
@@ -2495,7 +2498,7 @@ static int doPrintTypeInterfaceForTypeUsr(const CompilerInvocation &InitInvok,
const StringRef FileName,
const StringRef Usr) {
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addInputFile(FileName);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(FileName);
CompilerInstance CI;
if (CI.setup(Invocation))
return 1;
@@ -2656,7 +2659,7 @@ private:
static int doReconstructType(const CompilerInvocation &InitInvok,
StringRef SourceFilename) {
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
Invocation.getLangOptions().DisableAvailabilityChecking = false;
CompilerInstance CI;
@@ -2690,7 +2693,7 @@ static int doPrintRangeInfo(const CompilerInvocation &InitInvok,
auto StartLineCol = StartOp.getValue();
auto EndLineCol = EndOp.getValue();
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFileName);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFileName);
Invocation.getLangOptions().DisableAvailabilityChecking = false;
Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
@@ -2792,7 +2795,7 @@ static int doPrintIndexedSymbols(const CompilerInvocation &InitInvok,
StringRef SourceFileName, bool indexLocals) {
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFileName);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFileName);
Invocation.getLangOptions().DisableAvailabilityChecking = false;
Invocation.getLangOptions().TypoCorrectionLimit = 0;
@@ -2857,7 +2860,7 @@ static int doPrintIndexedSymbolsFromModule(const CompilerInvocation &InitInvok,
static int doPrintUSRs(const CompilerInvocation &InitInvok,
StringRef SourceFilename) {
CompilerInvocation Invocation(InitInvok);
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions();
ImporterOpts.DetailedPreprocessingRecord = true;
@@ -3004,7 +3007,7 @@ int main(int argc, char *argv[]) {
CompilerInvocation InitInvok;
for (auto &File : options::InputFilenames)
InitInvok.getFrontendOptions().Inputs.addInputFile(File);
InitInvok.getFrontendOptions().InputsAndOutputs.addInputFile(File);
if (!options::InputFilenames.empty())
InitInvok.setInputKind(InputFileKind::IFK_Swift_Library);

View File

@@ -233,12 +233,13 @@ int main(int argc, char *argv[]) {
Invocation.setMainExecutablePath(
llvm::sys::fs::getMainExecutable(argv[0],
reinterpret_cast<void *>(&anchorForGetMainExecutable)));
Invocation.getFrontendOptions().Inputs.addInputFile(options::SourceFilename);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(
options::SourceFilename);
Invocation.getLangOptions().AttachCommentsToDecls = true;
Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
for (auto FileName : options::InputFilenames)
Invocation.getFrontendOptions().Inputs.addInputFile(FileName);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(FileName);
Invocation.setModuleName(options::ModuleName);
CompilerInstance CI;
// Display diagnostics to stderr.

View File

@@ -146,7 +146,7 @@ SourceFile *getSourceFile(CompilerInstance &Instance,
CompilerInvocation Invocation;
Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
Invocation.getLangOptions().VerifySyntaxTree = true;
Invocation.getFrontendOptions().Inputs.addInputFile(InputFileName);
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(InputFileName);
Invocation.setMainExecutablePath(
llvm::sys::fs::getMainExecutable(MainExecutablePath,
reinterpret_cast<void *>(&anchorForGetMainExecutable)));