mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge remote-tracking branch 'origin/master' into master-next
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
113
include/swift/Frontend/ArgsToFrontendOutputsConverter.h
Normal file
113
include/swift/Frontend/ArgsToFrontendOutputsConverter.h
Normal 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 */
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 */
|
||||
200
include/swift/Frontend/FrontendInputsAndOutputs.h
Normal file
200
include/swift/Frontend/FrontendInputsAndOutputs.h
Normal 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 */
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
204
lib/Frontend/ArgsToFrontendOutputsConverter.cpp
Normal file
204
lib/Frontend/ArgsToFrontendOutputsConverter.cpp
Normal 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();
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
346
lib/Frontend/FrontendInputsAndOutputs.cpp
Normal file
346
lib/Frontend/FrontendInputsAndOutputs.cpp
Normal 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());
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)));
|
||||
|
||||
Reference in New Issue
Block a user