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:
@@ -15,26 +15,39 @@
|
|||||||
|
|
||||||
#include "swift/Basic/LLVM.h"
|
#include "swift/Basic/LLVM.h"
|
||||||
#include "swift/Basic/SupplementaryOutputPaths.h"
|
#include "swift/Basic/SupplementaryOutputPaths.h"
|
||||||
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
|
|
||||||
|
/// Holds all of the output paths, and debugging-info path that are
|
||||||
|
/// specific to which primary file is being compiled at the moment.
|
||||||
|
|
||||||
class PrimarySpecificPaths {
|
class PrimarySpecificPaths {
|
||||||
public:
|
public:
|
||||||
|
/// 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;
|
std::string OutputFilename;
|
||||||
|
|
||||||
SupplementaryOutputPaths SupplementaryOutputs;
|
SupplementaryOutputPaths SupplementaryOutputs;
|
||||||
|
|
||||||
/// The name of the "main" input file, used by the debug info.
|
/// The name of the "main" input file, used by the debug info.
|
||||||
std::string MainInputFilenameForDebugInfo;
|
std::string MainInputFilenameForDebugInfo;
|
||||||
|
|
||||||
PrimarySpecificPaths(
|
PrimarySpecificPaths(StringRef OutputFilename = StringRef(),
|
||||||
std::string OutputFilename = std::string(),
|
StringRef MainInputFilenameForDebugInfo = StringRef(),
|
||||||
std::string MainInputFilenameForDebugInfo = std::string(),
|
SupplementaryOutputPaths SupplementaryOutputs =
|
||||||
SupplementaryOutputPaths SupplementaryOutputs =
|
SupplementaryOutputPaths())
|
||||||
SupplementaryOutputPaths())
|
|
||||||
: OutputFilename(OutputFilename),
|
: OutputFilename(OutputFilename),
|
||||||
SupplementaryOutputs(SupplementaryOutputs),
|
SupplementaryOutputs(SupplementaryOutputs),
|
||||||
MainInputFilenameForDebugInfo(MainInputFilenameForDebugInfo) {}
|
MainInputFilenameForDebugInfo(MainInputFilenameForDebugInfo) {}
|
||||||
|
|
||||||
|
bool haveModuleOrModuleDocOutputPaths() const {
|
||||||
|
return !SupplementaryOutputs.ModuleOutputPath.empty() ||
|
||||||
|
!SupplementaryOutputs.ModuleDocOutputPath.empty();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace swift
|
} // namespace swift
|
||||||
|
|
||||||
|
|||||||
@@ -21,18 +21,28 @@
|
|||||||
namespace swift {
|
namespace swift {
|
||||||
struct SupplementaryOutputPaths {
|
struct SupplementaryOutputPaths {
|
||||||
/// The path to which we should emit an Objective-C header for the module.
|
/// The path to which we should emit an Objective-C header for the module.
|
||||||
|
/// Currently only makes sense when the compiler has whole module knowledge.
|
||||||
|
/// The modes for which it makes sense incuide both WMO and the "merge
|
||||||
|
/// modules" job that happens after the normal compilation jobs. That's where
|
||||||
|
/// the header is emitted in single-file mode, since it needs whole-module
|
||||||
|
/// information.
|
||||||
|
|
||||||
std::string ObjCHeaderOutputPath;
|
std::string ObjCHeaderOutputPath;
|
||||||
|
|
||||||
/// The path to which we should emit a serialized module.
|
/// The path to which we should emit a serialized module.
|
||||||
|
/// It is valid whenever there are any inputs.
|
||||||
std::string ModuleOutputPath;
|
std::string ModuleOutputPath;
|
||||||
|
|
||||||
/// The path to which we should emit a module documentation file.
|
/// The path to which we should emit a module documentation file.
|
||||||
|
/// It is valid whenever there are any inputs.
|
||||||
std::string ModuleDocOutputPath;
|
std::string ModuleDocOutputPath;
|
||||||
|
|
||||||
/// The path to which we should output a Make-style dependencies file.
|
/// The path to which we should output a Make-style dependencies file.
|
||||||
|
/// It is valid whenever there are any inputs.
|
||||||
std::string DependenciesFilePath;
|
std::string DependenciesFilePath;
|
||||||
|
|
||||||
/// The path to which we should output a Swift reference dependencies file.
|
/// The path to which we should output a Swift reference dependencies file.
|
||||||
|
/// It is valid whenever there are any inputs.
|
||||||
std::string ReferenceDependenciesFilePath;
|
std::string ReferenceDependenciesFilePath;
|
||||||
|
|
||||||
/// Path to a file which should contain serialized diagnostics for this
|
/// Path to a file which should contain serialized diagnostics for this
|
||||||
@@ -40,9 +50,11 @@ struct SupplementaryOutputPaths {
|
|||||||
std::string SerializedDiagnosticsPath;
|
std::string SerializedDiagnosticsPath;
|
||||||
|
|
||||||
/// The path to which we should output a loaded module trace file.
|
/// The path to which we should output a loaded module trace file.
|
||||||
|
/// It is currently only used with WMO, but could be generalized.
|
||||||
std::string LoadedModuleTracePath;
|
std::string LoadedModuleTracePath;
|
||||||
|
|
||||||
/// The path to which we should output a TBD file.
|
/// The path to which we should output a TBD file.
|
||||||
|
/// It is currently only used with WMO, but could be generalized.
|
||||||
std::string TBDPath;
|
std::string TBDPath;
|
||||||
|
|
||||||
SupplementaryOutputPaths() = default;
|
SupplementaryOutputPaths() = default;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public:
|
|||||||
Diags(diags) {}
|
Diags(diags) {}
|
||||||
|
|
||||||
bool convert(std::vector<std::string> &mainOutputs,
|
bool convert(std::vector<std::string> &mainOutputs,
|
||||||
SupplementaryOutputPaths &supplementaryOutputs);
|
std::vector<SupplementaryOutputPaths> &supplementaryOutputs);
|
||||||
|
|
||||||
/// Try to read an output file list file.
|
/// Try to read an output file list file.
|
||||||
/// \returns `None` if it could not open the filelist.
|
/// \returns `None` if it could not open the filelist.
|
||||||
@@ -57,7 +57,7 @@ class OutputFilesComputer {
|
|||||||
const FrontendInputsAndOutputs &InputsAndOutputs;
|
const FrontendInputsAndOutputs &InputsAndOutputs;
|
||||||
const std::vector<std::string> OutputFileArguments;
|
const std::vector<std::string> OutputFileArguments;
|
||||||
const std::string OutputDirectoryArgument;
|
const std::string OutputDirectoryArgument;
|
||||||
const StringRef FirstInput;
|
const std::string FirstInput;
|
||||||
const FrontendOptions::ActionType RequestedAction;
|
const FrontendOptions::ActionType RequestedAction;
|
||||||
const llvm::opt::Arg *const ModuleNameArg;
|
const llvm::opt::Arg *const ModuleNameArg;
|
||||||
const StringRef Suffix;
|
const StringRef Suffix;
|
||||||
|
|||||||
@@ -174,15 +174,6 @@ public:
|
|||||||
return SearchPathOpts.SDKPath;
|
return SearchPathOpts.SDKPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSerializedDiagnosticsPath(StringRef Path) {
|
|
||||||
FrontendOpts.InputsAndOutputs.supplementaryOutputs()
|
|
||||||
.SerializedDiagnosticsPath = Path;
|
|
||||||
}
|
|
||||||
StringRef getSerializedDiagnosticsPath() const {
|
|
||||||
return FrontendOpts.InputsAndOutputs.supplementaryOutputs()
|
|
||||||
.SerializedDiagnosticsPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
LangOptions &getLangOptions() {
|
LangOptions &getLangOptions() {
|
||||||
return LangOpts;
|
return LangOpts;
|
||||||
}
|
}
|
||||||
@@ -245,8 +236,7 @@ public:
|
|||||||
return FrontendOpts.ModuleName;
|
return FrontendOpts.ModuleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string getOutputFilename() const {
|
||||||
StringRef getOutputFilename() const {
|
|
||||||
return FrontendOpts.InputsAndOutputs.getSingleOutputFilename();
|
return FrontendOpts.InputsAndOutputs.getSingleOutputFilename();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,11 +292,25 @@ public:
|
|||||||
return FrontendOpts.InputKind == InputFileKind::IFK_Swift_Library;
|
return FrontendOpts.InputKind == InputFileKind::IFK_Swift_Library;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimarySpecificPaths getPrimarySpecificPathsForAtMostOnePrimary() const;
|
const PrimarySpecificPaths &
|
||||||
PrimarySpecificPaths
|
getPrimarySpecificPathsForAtMostOnePrimary() const;
|
||||||
|
const PrimarySpecificPaths &
|
||||||
getPrimarySpecificPathsForPrimary(StringRef filename) const;
|
getPrimarySpecificPathsForPrimary(StringRef filename) const;
|
||||||
PrimarySpecificPaths
|
const PrimarySpecificPaths &
|
||||||
getPrimarySpecificPathsForSourceFile(const SourceFile &SF) const;
|
getPrimarySpecificPathsForSourceFile(const SourceFile &SF) const;
|
||||||
|
|
||||||
|
std::string getOutputFilenameForAtMostOnePrimary() const;
|
||||||
|
std::string getMainInputFilenameForDebugInfoForAtMostOnePrimary() const;
|
||||||
|
std::string getObjCHeaderOutputPathForAtMostOnePrimary() const;
|
||||||
|
std::string getModuleOutputPathForAtMostOnePrimary() const;
|
||||||
|
std::string
|
||||||
|
getReferenceDependenciesFilePathForPrimary(StringRef filename) const;
|
||||||
|
std::string getSerializedDiagnosticsPathForAtMostOnePrimary() const;
|
||||||
|
|
||||||
|
/// TBDPath only makes sense in whole module compilation mode,
|
||||||
|
/// so return the TBDPath when in that mode and fail an assert
|
||||||
|
/// if not in that mode.
|
||||||
|
std::string getTBDPathForWholeModule() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A class which manages the state and execution of the compiler.
|
/// A class which manages the state and execution of the compiler.
|
||||||
@@ -584,12 +588,13 @@ private:
|
|||||||
void finishTypeChecking(OptionSet<TypeCheckingFlags> TypeCheckOptions);
|
void finishTypeChecking(OptionSet<TypeCheckingFlags> TypeCheckOptions);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PrimarySpecificPaths
|
const PrimarySpecificPaths &
|
||||||
getPrimarySpecificPathsForWholeModuleOptimizationMode() const;
|
getPrimarySpecificPathsForWholeModuleOptimizationMode() const;
|
||||||
PrimarySpecificPaths
|
const PrimarySpecificPaths &
|
||||||
getPrimarySpecificPathsForPrimary(StringRef filename) const;
|
getPrimarySpecificPathsForPrimary(StringRef filename) const;
|
||||||
PrimarySpecificPaths getPrimarySpecificPathsForAtMostOnePrimary() const;
|
const PrimarySpecificPaths &
|
||||||
PrimarySpecificPaths
|
getPrimarySpecificPathsForAtMostOnePrimary() const;
|
||||||
|
const PrimarySpecificPaths &
|
||||||
getPrimarySpecificPathsForSourceFile(const SourceFile &SF) const;
|
getPrimarySpecificPathsForSourceFile(const SourceFile &SF) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ class FrontendInputsAndOutputs {
|
|||||||
friend class ArgsToFrontendInputsConverter;
|
friend class ArgsToFrontendInputsConverter;
|
||||||
|
|
||||||
std::vector<InputFile> AllInputs;
|
std::vector<InputFile> AllInputs;
|
||||||
|
llvm::StringMap<unsigned> PrimaryInputsByName;
|
||||||
llvm::StringMap<unsigned> PrimaryInputs;
|
std::vector<unsigned> PrimaryInputsInOrder;
|
||||||
|
|
||||||
/// In Single-threaded WMO mode, all inputs are used
|
/// In Single-threaded WMO mode, all inputs are used
|
||||||
/// both for importing and compiling.
|
/// both for importing and compiling.
|
||||||
@@ -45,25 +45,10 @@ class FrontendInputsAndOutputs {
|
|||||||
/// Punt where needed to enable batch mode experiments.
|
/// Punt where needed to enable batch mode experiments.
|
||||||
bool AreBatchModeChecksBypassed = false;
|
bool AreBatchModeChecksBypassed = false;
|
||||||
|
|
||||||
SupplementaryOutputPaths SupplementaryOutputs;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool areBatchModeChecksBypassed() const { return AreBatchModeChecksBypassed; }
|
bool areBatchModeChecksBypassed() const { return AreBatchModeChecksBypassed; }
|
||||||
void setBypassBatchModeChecks(bool bbc) { AreBatchModeChecksBypassed = bbc; }
|
void setBypassBatchModeChecks(bool bbc) { AreBatchModeChecksBypassed = bbc; }
|
||||||
|
|
||||||
const SupplementaryOutputPaths &supplementaryOutputs() const {
|
|
||||||
return SupplementaryOutputs;
|
|
||||||
}
|
|
||||||
SupplementaryOutputPaths &supplementaryOutputs() {
|
|
||||||
return SupplementaryOutputs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// When performing a compilation for zero or one primary input file,
|
|
||||||
/// this will hold the PrimarySpecificPaths.
|
|
||||||
/// In a future PR, each InputFile will hold its own PrimarySpecificPaths and
|
|
||||||
/// this will go away.
|
|
||||||
PrimarySpecificPaths PrimarySpecificPathsForAtMostOnePrimary;
|
|
||||||
|
|
||||||
FrontendInputsAndOutputs() = default;
|
FrontendInputsAndOutputs() = default;
|
||||||
FrontendInputsAndOutputs(const FrontendInputsAndOutputs &other);
|
FrontendInputsAndOutputs(const FrontendInputsAndOutputs &other);
|
||||||
FrontendInputsAndOutputs &operator=(const FrontendInputsAndOutputs &other);
|
FrontendInputsAndOutputs &operator=(const FrontendInputsAndOutputs &other);
|
||||||
@@ -88,6 +73,9 @@ public:
|
|||||||
|
|
||||||
std::vector<std::string> getInputFilenames() const;
|
std::vector<std::string> getInputFilenames() const;
|
||||||
|
|
||||||
|
/// \return nullptr if not a primary input file.
|
||||||
|
const InputFile *primaryInputNamed(StringRef name) const;
|
||||||
|
|
||||||
unsigned inputCount() const { return AllInputs.size(); }
|
unsigned inputCount() const { return AllInputs.size(); }
|
||||||
|
|
||||||
bool hasInputs() const { return !AllInputs.empty(); }
|
bool hasInputs() const { return !AllInputs.empty(); }
|
||||||
@@ -99,21 +87,23 @@ public:
|
|||||||
|
|
||||||
const InputFile &lastInput() const { return AllInputs.back(); }
|
const InputFile &lastInput() const { return AllInputs.back(); }
|
||||||
|
|
||||||
StringRef getFilenameOfFirstInput() const;
|
const std::string &getFilenameOfFirstInput() const;
|
||||||
|
|
||||||
bool isReadingFromStdin() const;
|
bool isReadingFromStdin() const;
|
||||||
|
|
||||||
void forEachInput(llvm::function_ref<void(const InputFile &)> fn) const;
|
/// If \p fn returns true, exits early and returns true.
|
||||||
|
bool forEachInput(llvm::function_ref<bool(const InputFile &)> fn) const;
|
||||||
|
|
||||||
// Primaries:
|
// Primaries:
|
||||||
|
|
||||||
const InputFile &firstPrimaryInput() const;
|
const InputFile &firstPrimaryInput() const;
|
||||||
const InputFile &lastPrimaryInput() const;
|
const InputFile &lastPrimaryInput() const;
|
||||||
|
|
||||||
void
|
/// If \p fn returns true, exit early and return true.
|
||||||
forEachPrimaryInput(llvm::function_ref<void(const InputFile &)> fn) const;
|
bool
|
||||||
|
forEachPrimaryInput(llvm::function_ref<bool(const InputFile &)> fn) const;
|
||||||
|
|
||||||
unsigned primaryInputCount() const { return PrimaryInputs.size(); }
|
unsigned primaryInputCount() const { return PrimaryInputsInOrder.size(); }
|
||||||
|
|
||||||
// Primary count readers:
|
// Primary count readers:
|
||||||
|
|
||||||
@@ -143,11 +133,8 @@ public:
|
|||||||
|
|
||||||
const InputFile &getRequiredUniquePrimaryInput() const;
|
const InputFile &getRequiredUniquePrimaryInput() const;
|
||||||
|
|
||||||
/// \return the name of the unique primary input, or an empty StrinRef if
|
/// FIXME: Should combine all primaries for the result
|
||||||
/// there isn't one.
|
/// instead of just answering "batch" if there is more than one primary.
|
||||||
StringRef getNameOfUniquePrimaryInputFile() const;
|
|
||||||
|
|
||||||
/// Combines all primaries for stats reporter
|
|
||||||
std::string getStatsFileMangledInputName() const;
|
std::string getStatsFileMangledInputName() const;
|
||||||
|
|
||||||
bool isInputPrimary(StringRef file) const;
|
bool isInputPrimary(StringRef file) const;
|
||||||
@@ -181,9 +168,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
friend class ArgsToFrontendOptionsConverter;
|
friend class ArgsToFrontendOptionsConverter;
|
||||||
|
|
||||||
void
|
void setMainAndSupplementaryOutputs(
|
||||||
setMainAndSupplementaryOutputs(ArrayRef<std::string> outputFiles,
|
ArrayRef<std::string> outputFiles,
|
||||||
SupplementaryOutputPaths supplementaryOutputs);
|
ArrayRef<SupplementaryOutputPaths> supplementaryOutputs);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
unsigned countOfInputsProducingMainOutputs() const;
|
unsigned countOfInputsProducingMainOutputs() const;
|
||||||
@@ -198,17 +185,18 @@ public:
|
|||||||
/// Under single-threaded WMO, we pretend that the first input
|
/// Under single-threaded WMO, we pretend that the first input
|
||||||
/// generates the main output, even though it will include code
|
/// generates the main output, even though it will include code
|
||||||
/// generated from all of them.
|
/// generated from all of them.
|
||||||
void forEachInputProducingAMainOutputFile(
|
///
|
||||||
llvm::function_ref<void(const InputFile &)> fn) const;
|
/// If \p fn returns true, return early and return true.
|
||||||
|
bool forEachInputProducingAMainOutputFile(
|
||||||
|
llvm::function_ref<bool(const InputFile &)> fn) const;
|
||||||
|
|
||||||
std::vector<std::string> copyOutputFilenames() const;
|
std::vector<std::string> copyOutputFilenames() const;
|
||||||
|
|
||||||
void
|
void forEachOutputFilename(llvm::function_ref<void(StringRef)> fn) const;
|
||||||
forEachOutputFilename(llvm::function_ref<void(const std::string &)> fn) const;
|
|
||||||
|
|
||||||
/// Gets the name of the specified output filename.
|
/// Gets the name of the specified output filename.
|
||||||
/// If multiple files are specified, the last one is returned.
|
/// If multiple files are specified, the last one is returned.
|
||||||
StringRef getSingleOutputFilename() const;
|
std::string getSingleOutputFilename() const;
|
||||||
|
|
||||||
bool isOutputFilenameStdout() const;
|
bool isOutputFilenameStdout() const;
|
||||||
bool isOutputFileDirectory() const;
|
bool isOutputFileDirectory() const;
|
||||||
@@ -218,17 +206,22 @@ public:
|
|||||||
|
|
||||||
unsigned countOfFilesProducingSupplementaryOutput() const;
|
unsigned countOfFilesProducingSupplementaryOutput() const;
|
||||||
|
|
||||||
void forEachInputProducingSupplementaryOutput(
|
/// If \p fn returns true, exit early and return true.
|
||||||
llvm::function_ref<void(const InputFile &)> fn) const;
|
bool forEachInputProducingSupplementaryOutput(
|
||||||
|
llvm::function_ref<bool(const InputFile &)> fn) const;
|
||||||
|
|
||||||
/// Assumes there is not more than one primary input file, if any.
|
/// Assumes there is not more than one primary input file, if any.
|
||||||
/// Otherwise, you would need to call getPrimarySpecificPathsForPrimary
|
/// Otherwise, you would need to call getPrimarySpecificPathsForPrimary
|
||||||
/// to tell it which primary input you wanted the outputs for.
|
/// to tell it which primary input you wanted the outputs for.
|
||||||
|
const PrimarySpecificPaths &
|
||||||
|
getPrimarySpecificPathsForAtMostOnePrimary() const;
|
||||||
|
|
||||||
PrimarySpecificPaths getPrimarySpecificPathsForAtMostOnePrimary() const;
|
const PrimarySpecificPaths &
|
||||||
|
getPrimarySpecificPathsForPrimary(StringRef) const;
|
||||||
|
|
||||||
PrimarySpecificPaths
|
bool hasSupplementaryOutputPath(
|
||||||
getPrimarySpecificPathsForPrimary(StringRef filename) const;
|
llvm::function_ref<const std::string &(const SupplementaryOutputPaths &)>
|
||||||
|
extractorFn) const;
|
||||||
|
|
||||||
bool hasDependenciesPath() const;
|
bool hasDependenciesPath() const;
|
||||||
bool hasReferenceDependenciesPath() const;
|
bool hasReferenceDependenciesPath() const;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public:
|
|||||||
InputFileKind InputKind = InputFileKind::IFK_Swift;
|
InputFileKind InputKind = InputFileKind::IFK_Swift;
|
||||||
|
|
||||||
void forAllOutputPaths(const InputFile &input,
|
void forAllOutputPaths(const InputFile &input,
|
||||||
std::function<void(const std::string &)> fn) const;
|
std::function<void(StringRef)> fn) const;
|
||||||
|
|
||||||
bool isOutputFileDirectory() const;
|
bool isOutputFileDirectory() const;
|
||||||
|
|
||||||
@@ -273,8 +273,6 @@ public:
|
|||||||
return llvm::hash_value(0);
|
return llvm::hash_value(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef originalPath() const;
|
|
||||||
|
|
||||||
StringRef determineFallbackModuleName() const;
|
StringRef determineFallbackModuleName() const;
|
||||||
|
|
||||||
bool isCompilingExactlyOneSwiftFile() const {
|
bool isCompilingExactlyOneSwiftFile() const {
|
||||||
@@ -282,8 +280,10 @@ public:
|
|||||||
InputsAndOutputs.hasSingleInput();
|
InputsAndOutputs.hasSingleInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimarySpecificPaths getPrimarySpecificPathsForAtMostOnePrimary() const;
|
const PrimarySpecificPaths &
|
||||||
PrimarySpecificPaths getPrimarySpecificPathsForPrimary(StringRef) const;
|
getPrimarySpecificPathsForAtMostOnePrimary() const;
|
||||||
|
const PrimarySpecificPaths &
|
||||||
|
getPrimarySpecificPathsForPrimary(StringRef) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool canActionEmitDependencies(ActionType);
|
static bool canActionEmitDependencies(ActionType);
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
#ifndef SWIFT_FRONTEND_INPUTFILE_H
|
#ifndef SWIFT_FRONTEND_INPUTFILE_H
|
||||||
#define SWIFT_FRONTEND_INPUTFILE_H
|
#define SWIFT_FRONTEND_INPUTFILE_H
|
||||||
|
|
||||||
|
#include "swift/Basic/PrimarySpecificPaths.h"
|
||||||
|
#include "swift/Basic/SupplementaryOutputPaths.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -37,10 +39,12 @@ class InputFile {
|
|||||||
/// none.
|
/// none.
|
||||||
llvm::MemoryBuffer *Buffer;
|
llvm::MemoryBuffer *Buffer;
|
||||||
|
|
||||||
/// Contains the name of the main output file, that is, the .o file for this
|
/// If there are explicit primary inputs (i.e. designated with -primary-input
|
||||||
/// input. If there is no such file, contains an empty string. If the output
|
/// or -primary-filelist), the paths specific to those inputs (other than the
|
||||||
/// is to be written to stdout, contains "-".
|
/// input file path itself) are kept here. If there are no explicit primary
|
||||||
std::string OutputFilename;
|
/// inputs (for instance for whole module optimization), the corresponding
|
||||||
|
/// paths are kept in the first input file.
|
||||||
|
PrimarySpecificPaths PSPs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Does not take ownership of \p buffer. Does take ownership of (copy) a
|
/// Does not take ownership of \p buffer. Does take ownership of (copy) a
|
||||||
@@ -50,13 +54,13 @@ public:
|
|||||||
StringRef outputFilename = StringRef())
|
StringRef outputFilename = StringRef())
|
||||||
: Filename(
|
: Filename(
|
||||||
convertBufferNameFromLLVM_getFileOrSTDIN_toSwiftConventions(name)),
|
convertBufferNameFromLLVM_getFileOrSTDIN_toSwiftConventions(name)),
|
||||||
IsPrimary(isPrimary), Buffer(buffer), OutputFilename(outputFilename) {
|
IsPrimary(isPrimary), Buffer(buffer), PSPs(PrimarySpecificPaths()) {
|
||||||
assert(!name.empty());
|
assert(!name.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isPrimary() const { return IsPrimary; }
|
bool isPrimary() const { return IsPrimary; }
|
||||||
llvm::MemoryBuffer *buffer() const { return Buffer; }
|
llvm::MemoryBuffer *buffer() const { return Buffer; }
|
||||||
StringRef file() const {
|
const std::string &file() const {
|
||||||
assert(!Filename.empty());
|
assert(!Filename.empty());
|
||||||
return Filename;
|
return Filename;
|
||||||
}
|
}
|
||||||
@@ -68,13 +72,26 @@ public:
|
|||||||
return filename.equals("<stdin>") ? "-" : filename;
|
return filename.equals("<stdin>") ? "-" : filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &outputFilename() const { return OutputFilename; }
|
std::string outputFilename() const { return PSPs.OutputFilename; }
|
||||||
|
|
||||||
void setOutputFilename(StringRef outputFilename) {
|
const PrimarySpecificPaths &getPrimarySpecificPaths() const { return PSPs; }
|
||||||
OutputFilename = outputFilename;
|
|
||||||
|
void setPrimarySpecificPaths(const PrimarySpecificPaths &PSPs) {
|
||||||
|
this->PSPs = PSPs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The next set of functions provides access to those primary-specific paths
|
||||||
|
// accessed directly from an InputFile, as opposed to via
|
||||||
|
// FrontendInputsAndOutputs. They merely make the call sites
|
||||||
|
// a bit shorter. Add more forwarding methods as needed.
|
||||||
|
|
||||||
|
std::string dependenciesFilePath() const {
|
||||||
|
return getPrimarySpecificPaths().SupplementaryOutputs.DependenciesFilePath;
|
||||||
|
}
|
||||||
|
std::string loadedModuleTracePath() const {
|
||||||
|
return getPrimarySpecificPaths().SupplementaryOutputs.LoadedModuleTracePath;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace swift
|
} // namespace swift
|
||||||
|
|
||||||
#endif /* SWIFT_FRONTEND_INPUTFILE_H */
|
#endif /* SWIFT_FRONTEND_INPUTFILE_H */
|
||||||
|
|||||||
@@ -427,12 +427,12 @@ bool ArgsToFrontendOptionsConverter::computeFallbackModuleName() {
|
|||||||
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(Args,
|
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(Args,
|
||||||
Diags);
|
Diags);
|
||||||
|
|
||||||
auto nameToStem =
|
std::string nameToStem =
|
||||||
outputFilenames && outputFilenames->size() == 1 &&
|
outputFilenames && outputFilenames->size() == 1 &&
|
||||||
outputFilenames->front() != "-" &&
|
outputFilenames->front() != "-" &&
|
||||||
!llvm::sys::fs::is_directory(outputFilenames->front())
|
!llvm::sys::fs::is_directory(outputFilenames->front())
|
||||||
? outputFilenames->front()
|
? outputFilenames->front()
|
||||||
: Opts.InputsAndOutputs.getFilenameOfFirstInput().str();
|
: Opts.InputsAndOutputs.getFilenameOfFirstInput();
|
||||||
|
|
||||||
Opts.ModuleName = llvm::sys::path::stem(nameToStem);
|
Opts.ModuleName = llvm::sys::path::stem(nameToStem);
|
||||||
return false;
|
return false;
|
||||||
@@ -441,7 +441,7 @@ bool ArgsToFrontendOptionsConverter::computeFallbackModuleName() {
|
|||||||
bool ArgsToFrontendOptionsConverter::
|
bool ArgsToFrontendOptionsConverter::
|
||||||
computeMainAndSupplementaryOutputFilenames() {
|
computeMainAndSupplementaryOutputFilenames() {
|
||||||
std::vector<std::string> mainOutputs;
|
std::vector<std::string> mainOutputs;
|
||||||
SupplementaryOutputPaths supplementaryOutputs;
|
std::vector<SupplementaryOutputPaths> supplementaryOutputs;
|
||||||
const bool hadError = ArgsToFrontendOutputsConverter(
|
const bool hadError = ArgsToFrontendOutputsConverter(
|
||||||
Args, Opts.ModuleName, Opts.InputsAndOutputs, Diags)
|
Args, Opts.ModuleName, Opts.InputsAndOutputs, Diags)
|
||||||
.convert(mainOutputs, supplementaryOutputs);
|
.convert(mainOutputs, supplementaryOutputs);
|
||||||
@@ -487,9 +487,7 @@ void ArgsToFrontendOptionsConverter::computeImportObjCHeaderOptions() {
|
|||||||
using namespace options;
|
using namespace options;
|
||||||
if (const Arg *A = Args.getLastArgNoClaim(OPT_import_objc_header)) {
|
if (const Arg *A = Args.getLastArgNoClaim(OPT_import_objc_header)) {
|
||||||
Opts.ImplicitObjCHeaderPath = A->getValue();
|
Opts.ImplicitObjCHeaderPath = A->getValue();
|
||||||
Opts.SerializeBridgingHeader |=
|
Opts.SerializeBridgingHeader |= !Opts.InputsAndOutputs.hasPrimaryInputs();
|
||||||
!Opts.InputsAndOutputs.hasPrimaryInputs() &&
|
|
||||||
!Opts.InputsAndOutputs.supplementaryOutputs().ModuleOutputPath.empty();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void ArgsToFrontendOptionsConverter::computeImplicitImportModuleNames() {
|
void ArgsToFrontendOptionsConverter::computeImplicitImportModuleNames() {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ using namespace llvm::opt;
|
|||||||
|
|
||||||
bool ArgsToFrontendOutputsConverter::convert(
|
bool ArgsToFrontendOutputsConverter::convert(
|
||||||
std::vector<std::string> &mainOutputs,
|
std::vector<std::string> &mainOutputs,
|
||||||
SupplementaryOutputPaths &supplementaryOutputs) {
|
std::vector<SupplementaryOutputPaths> &supplementaryOutputs) {
|
||||||
|
|
||||||
Optional<OutputFilesComputer> ofc =
|
Optional<OutputFilesComputer> ofc =
|
||||||
OutputFilesComputer::create(Args, Diags, InputsAndOutputs);
|
OutputFilesComputer::create(Args, Diags, InputsAndOutputs);
|
||||||
@@ -51,10 +51,7 @@ bool ArgsToFrontendOutputsConverter::convert(
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
mainOutputs = std::move(*mains);
|
mainOutputs = std::move(*mains);
|
||||||
assert(supplementaries->size() <= 1 &&
|
supplementaryOutputs = std::move(*supplementaries);
|
||||||
"Have not implemented multiple primaries yet");
|
|
||||||
if (!supplementaries->empty())
|
|
||||||
supplementaryOutputs = std::move(supplementaries->front());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,9 +100,10 @@ OutputFilesComputer::create(const llvm::opt::ArgList &args,
|
|||||||
ArrayRef<std::string> outputFileArguments =
|
ArrayRef<std::string> outputFileArguments =
|
||||||
outputDirectoryArgument.empty() ? ArrayRef<std::string>(*outputArguments)
|
outputDirectoryArgument.empty() ? ArrayRef<std::string>(*outputArguments)
|
||||||
: ArrayRef<std::string>();
|
: ArrayRef<std::string>();
|
||||||
const StringRef firstInput = inputsAndOutputs.hasSingleInput()
|
const StringRef firstInput =
|
||||||
? inputsAndOutputs.getFilenameOfFirstInput()
|
inputsAndOutputs.hasSingleInput()
|
||||||
: StringRef();
|
? StringRef(inputsAndOutputs.getFilenameOfFirstInput())
|
||||||
|
: StringRef();
|
||||||
const FrontendOptions::ActionType requestedAction =
|
const FrontendOptions::ActionType requestedAction =
|
||||||
ArgsToFrontendOptionsConverter::determineRequestedAction(args);
|
ArgsToFrontendOptionsConverter::determineRequestedAction(args);
|
||||||
|
|
||||||
@@ -143,21 +141,19 @@ OutputFilesComputer::OutputFilesComputer(
|
|||||||
Optional<std::vector<std::string>>
|
Optional<std::vector<std::string>>
|
||||||
OutputFilesComputer::computeOutputFiles() const {
|
OutputFilesComputer::computeOutputFiles() const {
|
||||||
std::vector<std::string> outputFiles;
|
std::vector<std::string> outputFiles;
|
||||||
bool hadError = false;
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
InputsAndOutputs.forEachInputProducingAMainOutputFile(
|
bool hadError = InputsAndOutputs.forEachInputProducingAMainOutputFile(
|
||||||
[&](const InputFile &input) -> void {
|
[&](const InputFile &input) -> bool {
|
||||||
|
|
||||||
StringRef outputArg = OutputFileArguments.empty()
|
StringRef outputArg = OutputFileArguments.empty()
|
||||||
? StringRef()
|
? StringRef()
|
||||||
: StringRef(OutputFileArguments[i++]);
|
: StringRef(OutputFileArguments[i++]);
|
||||||
|
|
||||||
Optional<std::string> outputFile = computeOutputFile(outputArg, input);
|
Optional<std::string> outputFile = computeOutputFile(outputArg, input);
|
||||||
if (!outputFile) {
|
if (!outputFile)
|
||||||
hadError = true;
|
return true;
|
||||||
return;
|
|
||||||
}
|
|
||||||
outputFiles.push_back(*outputFile);
|
outputFiles.push_back(*outputFile);
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
return hadError ? None : Optional<std::vector<std::string>>(outputFiles);
|
return hadError ? None : Optional<std::vector<std::string>>(outputFiles);
|
||||||
}
|
}
|
||||||
@@ -208,7 +204,7 @@ Optional<std::string> OutputFilesComputer::deriveOutputFileForDirectory(
|
|||||||
|
|
||||||
std::string
|
std::string
|
||||||
OutputFilesComputer::determineBaseNameOfOutput(const InputFile &input) const {
|
OutputFilesComputer::determineBaseNameOfOutput(const InputFile &input) const {
|
||||||
StringRef nameToStem =
|
std::string nameToStem =
|
||||||
input.isPrimary()
|
input.isPrimary()
|
||||||
? input.file()
|
? input.file()
|
||||||
: ModuleNameArg ? ModuleNameArg->getValue() : FirstInput;
|
: ModuleNameArg ? ModuleNameArg->getValue() : FirstInput;
|
||||||
@@ -256,15 +252,15 @@ SupplementaryOutputPathsComputer::computeOutputPaths() const {
|
|||||||
|
|
||||||
std::vector<SupplementaryOutputPaths> outputPaths;
|
std::vector<SupplementaryOutputPaths> outputPaths;
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
bool hadError = false;
|
bool hadError = InputsAndOutputs.forEachInputProducingSupplementaryOutput(
|
||||||
InputsAndOutputs.forEachInputProducingSupplementaryOutput(
|
[&](const InputFile &input) -> bool {
|
||||||
[&](const InputFile &input) -> void {
|
|
||||||
if (auto suppPaths = computeOutputPathsForOneInput(
|
if (auto suppPaths = computeOutputPathsForOneInput(
|
||||||
OutputFiles[i], (*pathsFromUser)[i], input))
|
OutputFiles[i], (*pathsFromUser)[i], input)) {
|
||||||
|
++i;
|
||||||
outputPaths.push_back(*suppPaths);
|
outputPaths.push_back(*suppPaths);
|
||||||
else
|
return false;
|
||||||
hadError = true;
|
}
|
||||||
++i;
|
return true;
|
||||||
});
|
});
|
||||||
if (hadError)
|
if (hadError)
|
||||||
return None;
|
return None;
|
||||||
|
|||||||
@@ -675,12 +675,12 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
|
|||||||
if (Args.hasArg(OPT_debug_on_sil)) {
|
if (Args.hasArg(OPT_debug_on_sil)) {
|
||||||
// Derive the name of the SIL file for debugging from
|
// Derive the name of the SIL file for debugging from
|
||||||
// the regular outputfile.
|
// the regular outputfile.
|
||||||
StringRef BaseName = FEOpts.InputsAndOutputs.getSingleOutputFilename();
|
std::string BaseName = FEOpts.InputsAndOutputs.getSingleOutputFilename();
|
||||||
// If there are no or multiple outputfiles, derive the name
|
// If there are no or multiple outputfiles, derive the name
|
||||||
// from the module name.
|
// from the module name.
|
||||||
if (BaseName.empty())
|
if (BaseName.empty())
|
||||||
BaseName = FEOpts.ModuleName;
|
BaseName = FEOpts.ModuleName;
|
||||||
Opts.SILOutputFileNameForDebugging = BaseName.str();
|
Opts.SILOutputFileNameForDebugging = BaseName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const Arg *A = Args.getLastArg(options::OPT_sanitize_EQ)) {
|
if (const Arg *A = Args.getLastArg(options::OPT_sanitize_EQ)) {
|
||||||
|
|||||||
@@ -56,21 +56,58 @@ std::string CompilerInvocation::getPCHHash() const {
|
|||||||
return llvm::APInt(64, Code).toString(36, /*Signed=*/false);
|
return llvm::APInt(64, Code).toString(36, /*Signed=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimarySpecificPaths
|
const PrimarySpecificPaths &
|
||||||
CompilerInvocation::getPrimarySpecificPathsForAtMostOnePrimary() const {
|
CompilerInvocation::getPrimarySpecificPathsForAtMostOnePrimary() const {
|
||||||
return getFrontendOptions().getPrimarySpecificPathsForAtMostOnePrimary();
|
return getFrontendOptions().getPrimarySpecificPathsForAtMostOnePrimary();
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimarySpecificPaths CompilerInvocation::getPrimarySpecificPathsForPrimary(
|
const PrimarySpecificPaths &
|
||||||
|
CompilerInvocation::getPrimarySpecificPathsForPrimary(
|
||||||
StringRef filename) const {
|
StringRef filename) const {
|
||||||
return getFrontendOptions().getPrimarySpecificPathsForPrimary(filename);
|
return getFrontendOptions().getPrimarySpecificPathsForPrimary(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimarySpecificPaths CompilerInvocation::getPrimarySpecificPathsForSourceFile(
|
const PrimarySpecificPaths &
|
||||||
|
CompilerInvocation::getPrimarySpecificPathsForSourceFile(
|
||||||
const SourceFile &SF) const {
|
const SourceFile &SF) const {
|
||||||
return getPrimarySpecificPathsForPrimary(SF.getFilename());
|
return getPrimarySpecificPathsForPrimary(SF.getFilename());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CompilerInvocation::getOutputFilenameForAtMostOnePrimary() const {
|
||||||
|
return getPrimarySpecificPathsForAtMostOnePrimary().OutputFilename;
|
||||||
|
}
|
||||||
|
std::string
|
||||||
|
CompilerInvocation::getMainInputFilenameForDebugInfoForAtMostOnePrimary()
|
||||||
|
const {
|
||||||
|
return getPrimarySpecificPathsForAtMostOnePrimary()
|
||||||
|
.MainInputFilenameForDebugInfo;
|
||||||
|
}
|
||||||
|
std::string
|
||||||
|
CompilerInvocation::getObjCHeaderOutputPathForAtMostOnePrimary() const {
|
||||||
|
return getPrimarySpecificPathsForAtMostOnePrimary()
|
||||||
|
.SupplementaryOutputs.ObjCHeaderOutputPath;
|
||||||
|
}
|
||||||
|
std::string CompilerInvocation::getModuleOutputPathForAtMostOnePrimary() const {
|
||||||
|
return getPrimarySpecificPathsForAtMostOnePrimary()
|
||||||
|
.SupplementaryOutputs.ModuleOutputPath;
|
||||||
|
}
|
||||||
|
std::string CompilerInvocation::getReferenceDependenciesFilePathForPrimary(
|
||||||
|
StringRef filename) const {
|
||||||
|
return getPrimarySpecificPathsForPrimary(filename)
|
||||||
|
.SupplementaryOutputs.ReferenceDependenciesFilePath;
|
||||||
|
}
|
||||||
|
std::string
|
||||||
|
CompilerInvocation::getSerializedDiagnosticsPathForAtMostOnePrimary() const {
|
||||||
|
return getPrimarySpecificPathsForAtMostOnePrimary()
|
||||||
|
.SupplementaryOutputs.SerializedDiagnosticsPath;
|
||||||
|
}
|
||||||
|
std::string CompilerInvocation::getTBDPathForWholeModule() const {
|
||||||
|
assert(getFrontendOptions().InputsAndOutputs.isWholeModule() &&
|
||||||
|
"TBDPath only makes sense in WMO mode");
|
||||||
|
return getPrimarySpecificPathsForAtMostOnePrimary()
|
||||||
|
.SupplementaryOutputs.TBDPath;
|
||||||
|
}
|
||||||
|
|
||||||
void CompilerInstance::createSILModule() {
|
void CompilerInstance::createSILModule() {
|
||||||
assert(MainModule && "main module not created yet");
|
assert(MainModule && "main module not created yet");
|
||||||
// Assume WMO if a -primary-file option was not provided.
|
// Assume WMO if a -primary-file option was not provided.
|
||||||
@@ -103,9 +140,7 @@ bool CompilerInstance::setup(const CompilerInvocation &Invok) {
|
|||||||
|
|
||||||
// If we are asked to emit a module documentation file, configure lexing and
|
// If we are asked to emit a module documentation file, configure lexing and
|
||||||
// parsing to remember comments.
|
// parsing to remember comments.
|
||||||
if (!Invocation.getFrontendOptions()
|
if (Invocation.getFrontendOptions().InputsAndOutputs.hasModuleDocOutputPath())
|
||||||
.InputsAndOutputs.supplementaryOutputs()
|
|
||||||
.ModuleDocOutputPath.empty())
|
|
||||||
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
||||||
|
|
||||||
// If we are doing index-while-building, configure lexing and parsing to
|
// If we are doing index-while-building, configure lexing and parsing to
|
||||||
@@ -240,7 +275,6 @@ bool CompilerInstance::setUpForInput(const InputFile &input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (input.isPrimary()) {
|
if (input.isPrimary()) {
|
||||||
assert(PrimaryBufferIDs.empty() && "re-setting PrimaryBufferID");
|
|
||||||
recordPrimaryInputBuffer(*bufferID);
|
recordPrimaryInputBuffer(*bufferID);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -849,20 +883,21 @@ void CompilerInstance::freeASTContext() {
|
|||||||
|
|
||||||
void CompilerInstance::freeSILModule() { TheSILModule.reset(); }
|
void CompilerInstance::freeSILModule() { TheSILModule.reset(); }
|
||||||
|
|
||||||
PrimarySpecificPaths
|
const PrimarySpecificPaths &
|
||||||
CompilerInstance::getPrimarySpecificPathsForWholeModuleOptimizationMode()
|
CompilerInstance::getPrimarySpecificPathsForWholeModuleOptimizationMode()
|
||||||
const {
|
const {
|
||||||
return getPrimarySpecificPathsForAtMostOnePrimary();
|
return getPrimarySpecificPathsForAtMostOnePrimary();
|
||||||
}
|
}
|
||||||
PrimarySpecificPaths
|
const PrimarySpecificPaths &
|
||||||
CompilerInstance::getPrimarySpecificPathsForAtMostOnePrimary() const {
|
CompilerInstance::getPrimarySpecificPathsForAtMostOnePrimary() const {
|
||||||
return Invocation.getPrimarySpecificPathsForAtMostOnePrimary();
|
return Invocation.getPrimarySpecificPathsForAtMostOnePrimary();
|
||||||
}
|
}
|
||||||
PrimarySpecificPaths
|
const PrimarySpecificPaths &
|
||||||
CompilerInstance::getPrimarySpecificPathsForPrimary(StringRef filename) const {
|
CompilerInstance::getPrimarySpecificPathsForPrimary(StringRef filename) const {
|
||||||
return Invocation.getPrimarySpecificPathsForPrimary(filename);
|
return Invocation.getPrimarySpecificPathsForPrimary(filename);
|
||||||
}
|
}
|
||||||
PrimarySpecificPaths CompilerInstance::getPrimarySpecificPathsForSourceFile(
|
const PrimarySpecificPaths &
|
||||||
|
CompilerInstance::getPrimarySpecificPathsForSourceFile(
|
||||||
const SourceFile &SF) const {
|
const SourceFile &SF) const {
|
||||||
return Invocation.getPrimarySpecificPathsForSourceFile(SF);
|
return Invocation.getPrimarySpecificPathsForSourceFile(SF);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,9 +36,6 @@ FrontendInputsAndOutputs::FrontendInputsAndOutputs(
|
|||||||
for (InputFile input : other.AllInputs)
|
for (InputFile input : other.AllInputs)
|
||||||
addInput(input);
|
addInput(input);
|
||||||
IsSingleThreadedWMO = other.IsSingleThreadedWMO;
|
IsSingleThreadedWMO = other.IsSingleThreadedWMO;
|
||||||
SupplementaryOutputs = other.SupplementaryOutputs;
|
|
||||||
PrimarySpecificPathsForAtMostOnePrimary =
|
|
||||||
other.PrimarySpecificPathsForAtMostOnePrimary;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FrontendInputsAndOutputs &FrontendInputsAndOutputs::
|
FrontendInputsAndOutputs &FrontendInputsAndOutputs::
|
||||||
@@ -47,9 +44,6 @@ operator=(const FrontendInputsAndOutputs &other) {
|
|||||||
for (InputFile input : other.AllInputs)
|
for (InputFile input : other.AllInputs)
|
||||||
addInput(input);
|
addInput(input);
|
||||||
IsSingleThreadedWMO = other.IsSingleThreadedWMO;
|
IsSingleThreadedWMO = other.IsSingleThreadedWMO;
|
||||||
SupplementaryOutputs = other.SupplementaryOutputs;
|
|
||||||
PrimarySpecificPathsForAtMostOnePrimary =
|
|
||||||
other.PrimarySpecificPathsForAtMostOnePrimary;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,43 +61,40 @@ bool FrontendInputsAndOutputs::isReadingFromStdin() const {
|
|||||||
return hasSingleInput() && getFilenameOfFirstInput() == "-";
|
return hasSingleInput() && getFilenameOfFirstInput() == "-";
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef FrontendInputsAndOutputs::getFilenameOfFirstInput() const {
|
const std::string &FrontendInputsAndOutputs::getFilenameOfFirstInput() const {
|
||||||
assert(hasInputs());
|
assert(hasInputs());
|
||||||
const InputFile &inp = AllInputs[0];
|
const InputFile &inp = AllInputs[0];
|
||||||
StringRef f = inp.file();
|
const std::string &f = inp.file();
|
||||||
assert(!f.empty());
|
assert(!f.empty());
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrontendInputsAndOutputs::forEachInput(
|
bool FrontendInputsAndOutputs::forEachInput(
|
||||||
llvm::function_ref<void(const InputFile &)> fn) const {
|
llvm::function_ref<bool(const InputFile &)> fn) const {
|
||||||
for (const InputFile &input : AllInputs)
|
for (const InputFile &input : AllInputs)
|
||||||
fn(input);
|
if (fn(input))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Primaries:
|
// Primaries:
|
||||||
|
|
||||||
const InputFile &FrontendInputsAndOutputs::firstPrimaryInput() const {
|
const InputFile &FrontendInputsAndOutputs::firstPrimaryInput() const {
|
||||||
assert(!PrimaryInputs.empty());
|
assert(!PrimaryInputsInOrder.empty());
|
||||||
for (const auto &f : AllInputs)
|
return AllInputs[PrimaryInputsInOrder.front()];
|
||||||
if (f.isPrimary())
|
|
||||||
return f;
|
|
||||||
llvm_unreachable("no first primary?!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputFile &FrontendInputsAndOutputs::lastPrimaryInput() const {
|
const InputFile &FrontendInputsAndOutputs::lastPrimaryInput() const {
|
||||||
assert(!PrimaryInputs.empty());
|
assert(!PrimaryInputsInOrder.empty());
|
||||||
for (const auto &f : reversed(AllInputs))
|
return AllInputs[PrimaryInputsInOrder.back()];
|
||||||
if (f.isPrimary())
|
|
||||||
return f;
|
|
||||||
llvm_unreachable("no last primary?!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrontendInputsAndOutputs::forEachPrimaryInput(
|
bool FrontendInputsAndOutputs::forEachPrimaryInput(
|
||||||
llvm::function_ref<void(const InputFile &)> fn) const {
|
llvm::function_ref<bool(const InputFile &)> fn) const {
|
||||||
for (auto &f : AllInputs)
|
for (unsigned i : PrimaryInputsInOrder)
|
||||||
if (f.isPrimary())
|
if (fn(AllInputs[i]))
|
||||||
fn(f);
|
return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrontendInputsAndOutputs::assertMustNotBeMoreThanOnePrimaryInput() const {
|
void FrontendInputsAndOutputs::assertMustNotBeMoreThanOnePrimaryInput() const {
|
||||||
@@ -120,8 +111,9 @@ void FrontendInputsAndOutputs::
|
|||||||
|
|
||||||
const InputFile *FrontendInputsAndOutputs::getUniquePrimaryInput() const {
|
const InputFile *FrontendInputsAndOutputs::getUniquePrimaryInput() const {
|
||||||
assertMustNotBeMoreThanOnePrimaryInput();
|
assertMustNotBeMoreThanOnePrimaryInput();
|
||||||
const auto b = PrimaryInputs.begin();
|
return PrimaryInputsInOrder.empty()
|
||||||
return b == PrimaryInputs.end() ? nullptr : &AllInputs[b->second];
|
? nullptr
|
||||||
|
: &AllInputs[PrimaryInputsInOrder.front()];
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputFile &
|
const InputFile &
|
||||||
@@ -131,11 +123,6 @@ FrontendInputsAndOutputs::getRequiredUniquePrimaryInput() const {
|
|||||||
llvm_unreachable("No primary when one is required");
|
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 {
|
std::string FrontendInputsAndOutputs::getStatsFileMangledInputName() const {
|
||||||
// FIXME: "batch" should probably be some concatenation of all the primary
|
// 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
|
// input names, in order to keep the stats file names unique. (Or perhaps just
|
||||||
@@ -146,25 +133,18 @@ std::string FrontendInputsAndOutputs::getStatsFileMangledInputName() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool FrontendInputsAndOutputs::isInputPrimary(StringRef file) const {
|
bool FrontendInputsAndOutputs::isInputPrimary(StringRef file) const {
|
||||||
StringRef correctedFile =
|
return primaryInputNamed(file) != nullptr;
|
||||||
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(
|
unsigned FrontendInputsAndOutputs::numberOfPrimaryInputsEndingWith(
|
||||||
const char *extension) const {
|
const char *extension) const {
|
||||||
return count_if(
|
unsigned n = 0;
|
||||||
PrimaryInputs, [&](const llvm::StringMapEntry<unsigned> &elem) -> bool {
|
(void)forEachPrimaryInput([&](const InputFile &input) -> bool {
|
||||||
StringRef filename = AllInputs[elem.second].file();
|
if (llvm::sys::path::extension(input.file()).endswith(extension))
|
||||||
|
++n;
|
||||||
return llvm::sys::path::extension(filename).endswith(extension);
|
return false;
|
||||||
});
|
});
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Input queries
|
// Input queries
|
||||||
@@ -182,7 +162,7 @@ bool FrontendInputsAndOutputs::shouldTreatAsSIL() const {
|
|||||||
if (hasSingleInput()) {
|
if (hasSingleInput()) {
|
||||||
// If we have exactly one input filename, and its extension is "sil",
|
// If we have exactly one input filename, and its extension is "sil",
|
||||||
// treat the input as SIL.
|
// treat the input as SIL.
|
||||||
StringRef Input(getFilenameOfFirstInput());
|
const std::string &Input(getFilenameOfFirstInput());
|
||||||
return llvm::sys::path::extension(Input).endswith(SIL_EXTENSION);
|
return llvm::sys::path::extension(Input).endswith(SIL_EXTENSION);
|
||||||
}
|
}
|
||||||
// If we have one primary input and it's a filename with extension "sil",
|
// If we have one primary input and it's a filename with extension "sil",
|
||||||
@@ -245,13 +225,17 @@ bool FrontendInputsAndOutputs::verifyInputs(DiagnosticEngine &diags,
|
|||||||
|
|
||||||
void FrontendInputsAndOutputs::clearInputs() {
|
void FrontendInputsAndOutputs::clearInputs() {
|
||||||
AllInputs.clear();
|
AllInputs.clear();
|
||||||
PrimaryInputs.clear();
|
PrimaryInputsByName.clear();
|
||||||
|
PrimaryInputsInOrder.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrontendInputsAndOutputs::addInput(const InputFile &input) {
|
void FrontendInputsAndOutputs::addInput(const InputFile &input) {
|
||||||
if (!input.file().empty() && input.isPrimary())
|
const unsigned index = AllInputs.size();
|
||||||
PrimaryInputs.insert(std::make_pair(input.file(), AllInputs.size()));
|
|
||||||
AllInputs.push_back(input);
|
AllInputs.push_back(input);
|
||||||
|
if (input.isPrimary()) {
|
||||||
|
PrimaryInputsInOrder.push_back(index);
|
||||||
|
PrimaryInputsByName.insert(std::make_pair(AllInputs.back().file(), index));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrontendInputsAndOutputs::addInputFile(StringRef file,
|
void FrontendInputsAndOutputs::addInputFile(StringRef file,
|
||||||
@@ -284,62 +268,77 @@ const InputFile &FrontendInputsAndOutputs::lastInputProducingOutput() const {
|
|||||||
: hasPrimaryInputs() ? lastPrimaryInput() : lastInput();
|
: hasPrimaryInputs() ? lastPrimaryInput() : lastInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrontendInputsAndOutputs::forEachInputProducingAMainOutputFile(
|
bool FrontendInputsAndOutputs::forEachInputProducingAMainOutputFile(
|
||||||
llvm::function_ref<void(const InputFile &)> fn) const {
|
llvm::function_ref<bool(const InputFile &)> fn) const {
|
||||||
isSingleThreadedWMO()
|
return isSingleThreadedWMO()
|
||||||
? fn(firstInput())
|
? fn(firstInput())
|
||||||
: hasPrimaryInputs() ? forEachPrimaryInput(fn) : forEachInput(fn);
|
: hasPrimaryInputs() ? forEachPrimaryInput(fn) : forEachInput(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrontendInputsAndOutputs::setMainAndSupplementaryOutputs(
|
void FrontendInputsAndOutputs::setMainAndSupplementaryOutputs(
|
||||||
ArrayRef<std::string> outputFiles,
|
ArrayRef<std::string> outputFiles,
|
||||||
SupplementaryOutputPaths supplementaryOutputs) {
|
ArrayRef<SupplementaryOutputPaths> supplementaryOutputs) {
|
||||||
|
if (AllInputs.empty()) {
|
||||||
|
assert(outputFiles.empty() && "Cannot have outputs without inputs");
|
||||||
|
assert(supplementaryOutputs.empty() &&
|
||||||
|
"Cannot have supplementary outputs without inputs");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (hasPrimaryInputs()) {
|
if (hasPrimaryInputs()) {
|
||||||
unsigned i = 0;
|
const auto N = primaryInputCount();
|
||||||
for (auto index : indices(AllInputs)) {
|
assert(outputFiles.size() == N && "Must have one main output per primary");
|
||||||
InputFile &f = AllInputs[index];
|
assert(supplementaryOutputs.size() == N &&
|
||||||
if (f.isPrimary())
|
"Must have one set of supplementary outputs per primary");
|
||||||
f.setOutputFilename(outputFiles[i++]);
|
|
||||||
}
|
|
||||||
} else if (isSingleThreadedWMO()) {
|
|
||||||
AllInputs[0].setOutputFilename(outputFiles[0]);
|
|
||||||
} else {
|
|
||||||
for (auto i : indices(AllInputs))
|
|
||||||
AllInputs[i].setOutputFilename(outputFiles[i]);
|
|
||||||
}
|
|
||||||
SupplementaryOutputs = supplementaryOutputs;
|
|
||||||
|
|
||||||
if (hasUniquePrimaryInput() || (hasInputs() && isWholeModule())) {
|
unsigned i = 0;
|
||||||
// When batch mode is fully implemented, each InputFile will own
|
for (auto &input : AllInputs) {
|
||||||
// a PrimarySpecificPaths.
|
if (input.isPrimary()) {
|
||||||
PrimarySpecificPathsForAtMostOnePrimary.OutputFilename =
|
input.setPrimarySpecificPaths(PrimarySpecificPaths(
|
||||||
getSingleOutputFilename();
|
outputFiles[i], input.file(), supplementaryOutputs[i]));
|
||||||
PrimarySpecificPathsForAtMostOnePrimary.MainInputFilenameForDebugInfo =
|
++i;
|
||||||
hasInputsProducingMainOutputs() ? firstInputProducingOutput().file()
|
}
|
||||||
: StringRef();
|
}
|
||||||
PrimarySpecificPathsForAtMostOnePrimary.SupplementaryOutputs =
|
return;
|
||||||
supplementaryOutputs;
|
|
||||||
}
|
}
|
||||||
|
assert(supplementaryOutputs.size() == 1 &&
|
||||||
|
"WMO only ever produces one set of supplementary outputs");
|
||||||
|
if (outputFiles.size() == 1) {
|
||||||
|
AllInputs.front().setPrimarySpecificPaths(PrimarySpecificPaths(
|
||||||
|
outputFiles.front(), firstInputProducingOutput().file(),
|
||||||
|
supplementaryOutputs.front()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(outputFiles.size() == AllInputs.size() &&
|
||||||
|
"Multi-threaded WMO requires one main output per input");
|
||||||
|
for (auto i : indices(AllInputs))
|
||||||
|
AllInputs[i].setPrimarySpecificPaths(PrimarySpecificPaths(
|
||||||
|
outputFiles[i], outputFiles[i],
|
||||||
|
i == 0 ? supplementaryOutputs.front() : SupplementaryOutputPaths()));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> FrontendInputsAndOutputs::copyOutputFilenames() const {
|
std::vector<std::string> FrontendInputsAndOutputs::copyOutputFilenames() const {
|
||||||
std::vector<std::string> outputs;
|
std::vector<std::string> outputs;
|
||||||
forEachInputProducingAMainOutputFile([&](const InputFile &input) -> void {
|
(void)forEachInputProducingAMainOutputFile(
|
||||||
outputs.push_back(input.outputFilename());
|
[&](const InputFile &input) -> bool {
|
||||||
});
|
outputs.push_back(input.outputFilename());
|
||||||
|
return false;
|
||||||
|
});
|
||||||
return outputs;
|
return outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrontendInputsAndOutputs::forEachOutputFilename(
|
void FrontendInputsAndOutputs::forEachOutputFilename(
|
||||||
llvm::function_ref<void(const std::string &)> fn) const {
|
llvm::function_ref<void(StringRef)> fn) const {
|
||||||
forEachInputProducingAMainOutputFile(
|
(void)forEachInputProducingAMainOutputFile(
|
||||||
[&](const InputFile &input) -> void { fn(input.outputFilename()); });
|
[&](const InputFile &input) -> bool {
|
||||||
|
fn(input.outputFilename());
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef FrontendInputsAndOutputs::getSingleOutputFilename() const {
|
std::string FrontendInputsAndOutputs::getSingleOutputFilename() const {
|
||||||
assertMustNotBeMoreThanOnePrimaryInputUnlessBatchModeChecksHaveBeenBypassed();
|
assertMustNotBeMoreThanOnePrimaryInputUnlessBatchModeChecksHaveBeenBypassed();
|
||||||
return hasInputs() ? StringRef(lastInputProducingOutput().outputFilename())
|
return hasInputs() ? lastInputProducingOutput().outputFilename()
|
||||||
: StringRef();
|
: std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FrontendInputsAndOutputs::isOutputFilenameStdout() const {
|
bool FrontendInputsAndOutputs::isOutputFilenameStdout() const {
|
||||||
@@ -362,34 +361,63 @@ FrontendInputsAndOutputs::countOfFilesProducingSupplementaryOutput() const {
|
|||||||
return hasPrimaryInputs() ? primaryInputCount() : hasInputs() ? 1 : 0;
|
return hasPrimaryInputs() ? primaryInputCount() : hasInputs() ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrontendInputsAndOutputs::forEachInputProducingSupplementaryOutput(
|
bool FrontendInputsAndOutputs::forEachInputProducingSupplementaryOutput(
|
||||||
llvm::function_ref<void(const InputFile &)> fn) const {
|
llvm::function_ref<bool(const InputFile &)> fn) const {
|
||||||
if (hasPrimaryInputs())
|
return hasPrimaryInputs() ? forEachPrimaryInput(fn)
|
||||||
forEachPrimaryInput(fn);
|
: hasInputs() ? fn(firstInput()) : false;
|
||||||
else if (hasInputs())
|
}
|
||||||
fn(firstInput());
|
|
||||||
|
bool FrontendInputsAndOutputs::hasSupplementaryOutputPath(
|
||||||
|
llvm::function_ref<const std::string &(const SupplementaryOutputPaths &)>
|
||||||
|
extractorFn) const {
|
||||||
|
return forEachInputProducingSupplementaryOutput([&](const InputFile &input)
|
||||||
|
-> bool {
|
||||||
|
return !extractorFn(input.getPrimarySpecificPaths().SupplementaryOutputs)
|
||||||
|
.empty();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FrontendInputsAndOutputs::hasDependenciesPath() const {
|
bool FrontendInputsAndOutputs::hasDependenciesPath() const {
|
||||||
return !supplementaryOutputs().DependenciesFilePath.empty();
|
return hasSupplementaryOutputPath(
|
||||||
|
[](const SupplementaryOutputPaths &outs) -> const std::string & {
|
||||||
|
return outs.DependenciesFilePath;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
bool FrontendInputsAndOutputs::hasReferenceDependenciesPath() const {
|
bool FrontendInputsAndOutputs::hasReferenceDependenciesPath() const {
|
||||||
return !supplementaryOutputs().ReferenceDependenciesFilePath.empty();
|
return hasSupplementaryOutputPath(
|
||||||
|
[](const SupplementaryOutputPaths &outs) -> const std::string & {
|
||||||
|
return outs.ReferenceDependenciesFilePath;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
bool FrontendInputsAndOutputs::hasObjCHeaderOutputPath() const {
|
bool FrontendInputsAndOutputs::hasObjCHeaderOutputPath() const {
|
||||||
return !supplementaryOutputs().ObjCHeaderOutputPath.empty();
|
return hasSupplementaryOutputPath(
|
||||||
|
[](const SupplementaryOutputPaths &outs) -> const std::string & {
|
||||||
|
return outs.ObjCHeaderOutputPath;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
bool FrontendInputsAndOutputs::hasLoadedModuleTracePath() const {
|
bool FrontendInputsAndOutputs::hasLoadedModuleTracePath() const {
|
||||||
return !supplementaryOutputs().LoadedModuleTracePath.empty();
|
return hasSupplementaryOutputPath(
|
||||||
|
[](const SupplementaryOutputPaths &outs) -> const std::string & {
|
||||||
|
return outs.LoadedModuleTracePath;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
bool FrontendInputsAndOutputs::hasModuleOutputPath() const {
|
bool FrontendInputsAndOutputs::hasModuleOutputPath() const {
|
||||||
return !supplementaryOutputs().ModuleOutputPath.empty();
|
return hasSupplementaryOutputPath(
|
||||||
|
[](const SupplementaryOutputPaths &outs) -> const std::string & {
|
||||||
|
return outs.ModuleOutputPath;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
bool FrontendInputsAndOutputs::hasModuleDocOutputPath() const {
|
bool FrontendInputsAndOutputs::hasModuleDocOutputPath() const {
|
||||||
return !supplementaryOutputs().ModuleDocOutputPath.empty();
|
return hasSupplementaryOutputPath(
|
||||||
|
[](const SupplementaryOutputPaths &outs) -> const std::string & {
|
||||||
|
return outs.ModuleDocOutputPath;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
bool FrontendInputsAndOutputs::hasTBDPath() const {
|
bool FrontendInputsAndOutputs::hasTBDPath() const {
|
||||||
return !supplementaryOutputs().TBDPath.empty();
|
return hasSupplementaryOutputPath(
|
||||||
|
[](const SupplementaryOutputPaths &outs) -> const std::string & {
|
||||||
|
return outs.TBDPath;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FrontendInputsAndOutputs::hasDependencyTrackerPath() const {
|
bool FrontendInputsAndOutputs::hasDependencyTrackerPath() const {
|
||||||
@@ -397,13 +425,31 @@ bool FrontendInputsAndOutputs::hasDependencyTrackerPath() const {
|
|||||||
hasLoadedModuleTracePath();
|
hasLoadedModuleTracePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimarySpecificPaths
|
const PrimarySpecificPaths &
|
||||||
FrontendInputsAndOutputs::getPrimarySpecificPathsForAtMostOnePrimary() const {
|
FrontendInputsAndOutputs::getPrimarySpecificPathsForAtMostOnePrimary() const {
|
||||||
return PrimarySpecificPathsForAtMostOnePrimary;
|
assertMustNotBeMoreThanOnePrimaryInputUnlessBatchModeChecksHaveBeenBypassed();
|
||||||
|
static auto emptyPaths = PrimarySpecificPaths();
|
||||||
|
return hasInputs() ? firstInputProducingOutput().getPrimarySpecificPaths()
|
||||||
|
: emptyPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimarySpecificPaths
|
const PrimarySpecificPaths &
|
||||||
FrontendInputsAndOutputs::getPrimarySpecificPathsForPrimary(
|
FrontendInputsAndOutputs::getPrimarySpecificPathsForPrimary(
|
||||||
StringRef filename) const {
|
StringRef filename) const {
|
||||||
return getPrimarySpecificPathsForAtMostOnePrimary(); // just a stub for now
|
const InputFile *f = primaryInputNamed(filename);
|
||||||
|
return f->getPrimarySpecificPaths();
|
||||||
|
}
|
||||||
|
|
||||||
|
const InputFile *
|
||||||
|
FrontendInputsAndOutputs::primaryInputNamed(StringRef name) const {
|
||||||
|
assert(!name.empty() && "input files have names");
|
||||||
|
StringRef correctedFile =
|
||||||
|
InputFile::convertBufferNameFromLLVM_getFileOrSTDIN_toSwiftConventions(
|
||||||
|
name);
|
||||||
|
auto iterator = PrimaryInputsByName.find(correctedFile);
|
||||||
|
if (iterator == PrimaryInputsByName.end())
|
||||||
|
return nullptr;
|
||||||
|
const InputFile *f = &AllInputs[iterator->second];
|
||||||
|
assert(f->isPrimary() && "PrimaryInputsByName should only include primries");
|
||||||
|
return f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ bool FrontendOptions::shouldActionOnlyParse(ActionType action) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FrontendOptions::forAllOutputPaths(
|
void FrontendOptions::forAllOutputPaths(
|
||||||
const InputFile &input, std::function<void(const std::string &)> fn) const {
|
const InputFile &input, std::function<void(StringRef)> fn) const {
|
||||||
if (RequestedAction != FrontendOptions::ActionType::EmitModuleOnly &&
|
if (RequestedAction != FrontendOptions::ActionType::EmitModuleOnly &&
|
||||||
RequestedAction != FrontendOptions::ActionType::MergeModules) {
|
RequestedAction != FrontendOptions::ActionType::MergeModules) {
|
||||||
if (InputsAndOutputs.isWholeModule())
|
if (InputsAndOutputs.isWholeModule())
|
||||||
@@ -116,28 +116,19 @@ void FrontendOptions::forAllOutputPaths(
|
|||||||
else
|
else
|
||||||
fn(input.outputFilename());
|
fn(input.outputFilename());
|
||||||
}
|
}
|
||||||
const std::string *outputs[] = {
|
(void)InputsAndOutputs.forEachInputProducingSupplementaryOutput(
|
||||||
&InputsAndOutputs.supplementaryOutputs().ModuleOutputPath,
|
[&](const InputFile &inp) -> bool {
|
||||||
&InputsAndOutputs.supplementaryOutputs().ModuleDocOutputPath,
|
const SupplementaryOutputPaths &outs =
|
||||||
&InputsAndOutputs.supplementaryOutputs().ObjCHeaderOutputPath};
|
inp.getPrimarySpecificPaths().SupplementaryOutputs;
|
||||||
for (const std::string *next : outputs) {
|
const std::string *outputs[] = {&outs.ModuleOutputPath,
|
||||||
if (!next->empty())
|
&outs.ModuleDocOutputPath,
|
||||||
fn(*next);
|
&outs.ObjCHeaderOutputPath};
|
||||||
}
|
for (const std::string *next : outputs) {
|
||||||
}
|
if (!next->empty())
|
||||||
|
fn(*next);
|
||||||
|
}
|
||||||
StringRef FrontendOptions::originalPath() const {
|
return false;
|
||||||
if (InputsAndOutputs.hasNamedOutputFile())
|
});
|
||||||
// Put the serialized diagnostics file next to the output file.
|
|
||||||
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 = InputsAndOutputs.getUniquePrimaryInput();
|
|
||||||
return input ? llvm::sys::path::filename(input->file())
|
|
||||||
: StringRef(ModuleName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
@@ -387,12 +378,12 @@ bool FrontendOptions::doesActionProduceTextualOutput(ActionType action) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimarySpecificPaths
|
const PrimarySpecificPaths &
|
||||||
FrontendOptions::getPrimarySpecificPathsForAtMostOnePrimary() const {
|
FrontendOptions::getPrimarySpecificPathsForAtMostOnePrimary() const {
|
||||||
return InputsAndOutputs.getPrimarySpecificPathsForAtMostOnePrimary();
|
return InputsAndOutputs.getPrimarySpecificPathsForAtMostOnePrimary();
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimarySpecificPaths
|
const PrimarySpecificPaths &
|
||||||
FrontendOptions::getPrimarySpecificPathsForPrimary(StringRef filename) const {
|
FrontendOptions::getPrimarySpecificPathsForPrimary(StringRef filename) const {
|
||||||
return InputsAndOutputs.getPrimarySpecificPathsForPrimary(filename);
|
return InputsAndOutputs.getPrimarySpecificPathsForPrimary(filename);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,20 +99,20 @@ static std::string displayName(StringRef MainExecutablePath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Emits a Make-style dependencies file.
|
/// Emits a Make-style dependencies file.
|
||||||
static bool emitMakeDependencies(DiagnosticEngine &diags,
|
static bool emitMakeDependenciesIfNeeded(DiagnosticEngine &diags,
|
||||||
DependencyTracker &depTracker,
|
DependencyTracker *depTracker,
|
||||||
const FrontendOptions &opts,
|
const FrontendOptions &opts,
|
||||||
const InputFile &input) {
|
const InputFile &input) {
|
||||||
|
const std::string &dependenciesFilePath = input.dependenciesFilePath();
|
||||||
|
if (dependenciesFilePath.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
std::error_code EC;
|
std::error_code EC;
|
||||||
llvm::raw_fd_ostream out(
|
llvm::raw_fd_ostream out(dependenciesFilePath, EC, llvm::sys::fs::F_None);
|
||||||
opts.InputsAndOutputs.supplementaryOutputs().DependenciesFilePath, EC,
|
|
||||||
llvm::sys::fs::F_None);
|
|
||||||
|
|
||||||
if (out.has_error() || EC) {
|
if (out.has_error() || EC) {
|
||||||
diags.diagnose(
|
diags.diagnose(SourceLoc(), diag::error_opening_output,
|
||||||
SourceLoc(), diag::error_opening_output,
|
dependenciesFilePath, EC.message());
|
||||||
opts.InputsAndOutputs.supplementaryOutputs().DependenciesFilePath,
|
|
||||||
EC.message());
|
|
||||||
out.clear_error();
|
out.clear_error();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ static bool emitMakeDependencies(DiagnosticEngine &diags,
|
|||||||
|
|
||||||
// FIXME: Xcode can't currently handle multiple targets in a single
|
// FIXME: Xcode can't currently handle multiple targets in a single
|
||||||
// dependency line.
|
// dependency line.
|
||||||
opts.forAllOutputPaths(input, [&](StringRef targetName) {
|
opts.forAllOutputPaths(input, [&](const StringRef targetName) {
|
||||||
out << escape(targetName) << " :";
|
out << escape(targetName) << " :";
|
||||||
// First include all other files in the module. Make-style dependencies
|
// First include all other files in the module. Make-style dependencies
|
||||||
// need to be conservative!
|
// need to be conservative!
|
||||||
@@ -148,7 +148,7 @@ static bool emitMakeDependencies(DiagnosticEngine &diags,
|
|||||||
out << ' ' << escape(path);
|
out << ' ' << escape(path);
|
||||||
// Then print dependencies we've picked up during compilation.
|
// Then print dependencies we've picked up during compilation.
|
||||||
for (auto const &path :
|
for (auto const &path :
|
||||||
reversePathSortedFilenames(depTracker.getDependencies()))
|
reversePathSortedFilenames(depTracker->getDependencies()))
|
||||||
out << ' ' << escape(path);
|
out << ' ' << escape(path);
|
||||||
out << '\n';
|
out << '\n';
|
||||||
});
|
});
|
||||||
@@ -156,15 +156,13 @@ static bool emitMakeDependencies(DiagnosticEngine &diags,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool emitMakeDependencies(DiagnosticEngine &diags,
|
static bool emitMakeDependenciesIfNeeded(DiagnosticEngine &diags,
|
||||||
DependencyTracker &depTracker,
|
DependencyTracker *depTracker,
|
||||||
const FrontendOptions &opts) {
|
const FrontendOptions &opts) {
|
||||||
bool hadError = false;
|
return opts.InputsAndOutputs.forEachInputProducingSupplementaryOutput(
|
||||||
opts.InputsAndOutputs.forEachInputProducingSupplementaryOutput(
|
[&](const InputFile &f) -> bool {
|
||||||
[&](const InputFile &f) -> void {
|
return emitMakeDependenciesIfNeeded(diags, depTracker, opts, f);
|
||||||
hadError = emitMakeDependencies(diags, depTracker, opts, f) || hadError;
|
|
||||||
});
|
});
|
||||||
return hadError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -189,20 +187,16 @@ template <> struct ObjectTraits<LoadedModuleTraceFormat> {
|
|||||||
|
|
||||||
static bool emitLoadedModuleTraceIfNeeded(ASTContext &ctxt,
|
static bool emitLoadedModuleTraceIfNeeded(ASTContext &ctxt,
|
||||||
DependencyTracker *depTracker,
|
DependencyTracker *depTracker,
|
||||||
const FrontendOptions &opts) {
|
StringRef loadedModuleTracePath,
|
||||||
if (opts.InputsAndOutputs.supplementaryOutputs()
|
StringRef moduleName) {
|
||||||
.LoadedModuleTracePath.empty())
|
if (loadedModuleTracePath.empty())
|
||||||
return false;
|
return false;
|
||||||
std::error_code EC;
|
std::error_code EC;
|
||||||
llvm::raw_fd_ostream out(
|
llvm::raw_fd_ostream out(loadedModuleTracePath, EC, llvm::sys::fs::F_Append);
|
||||||
opts.InputsAndOutputs.supplementaryOutputs().LoadedModuleTracePath, EC,
|
|
||||||
llvm::sys::fs::F_Append);
|
|
||||||
|
|
||||||
if (out.has_error() || EC) {
|
if (out.has_error() || EC) {
|
||||||
ctxt.Diags.diagnose(
|
ctxt.Diags.diagnose(SourceLoc(), diag::error_opening_output,
|
||||||
SourceLoc(), diag::error_opening_output,
|
loadedModuleTracePath, EC.message());
|
||||||
opts.InputsAndOutputs.supplementaryOutputs().LoadedModuleTracePath,
|
|
||||||
EC.message());
|
|
||||||
out.clear_error();
|
out.clear_error();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -235,7 +229,7 @@ static bool emitLoadedModuleTraceIfNeeded(ASTContext &ctxt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
LoadedModuleTraceFormat trace = {
|
LoadedModuleTraceFormat trace = {
|
||||||
/*name=*/opts.ModuleName,
|
/*name=*/moduleName,
|
||||||
/*arch=*/ctxt.LangOpts.Target.getArchName(),
|
/*arch=*/ctxt.LangOpts.Target.getArchName(),
|
||||||
/*swiftmodules=*/reversePathSortedFilenames(swiftModules)};
|
/*swiftmodules=*/reversePathSortedFilenames(swiftModules)};
|
||||||
|
|
||||||
@@ -255,6 +249,16 @@ static bool emitLoadedModuleTraceIfNeeded(ASTContext &ctxt,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
emitLoadedModuleTraceForAllPrimariesIfNeeded(ASTContext &ctxt,
|
||||||
|
DependencyTracker *depTracker,
|
||||||
|
const FrontendOptions &opts) {
|
||||||
|
return opts.InputsAndOutputs.forEachInputProducingSupplementaryOutput(
|
||||||
|
[&](const InputFile &input) -> bool {
|
||||||
|
return emitLoadedModuleTraceIfNeeded(
|
||||||
|
ctxt, depTracker, input.loadedModuleTracePath(), opts.ModuleName);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets an output stream for the provided output filename, or diagnoses to the
|
/// Gets an output stream for the provided output filename, or diagnoses to the
|
||||||
/// provided AST Context and returns null if there was an error getting the
|
/// provided AST Context and returns null if there was an error getting the
|
||||||
@@ -306,7 +310,7 @@ static bool writeSIL(SILModule &SM, const PrimarySpecificPaths &PSPs,
|
|||||||
PSPs.OutputFilename, opts.EmitSortedSIL);
|
PSPs.OutputFilename, opts.EmitSortedSIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool printAsObjCIfNeeded(const std::string &outputPath, ModuleDecl *M,
|
static bool printAsObjCIfNeeded(StringRef outputPath, ModuleDecl *M,
|
||||||
StringRef bridgingHeader, bool moduleIsPublic) {
|
StringRef bridgingHeader, bool moduleIsPublic) {
|
||||||
using namespace llvm::sys;
|
using namespace llvm::sys;
|
||||||
|
|
||||||
@@ -739,19 +743,18 @@ static Optional<bool> dumpASTIfNeeded(CompilerInvocation &Invocation,
|
|||||||
static void emitReferenceDependenciesForAllPrimaryInputsIfNeeded(
|
static void emitReferenceDependenciesForAllPrimaryInputsIfNeeded(
|
||||||
CompilerInvocation &Invocation, CompilerInstance &Instance) {
|
CompilerInvocation &Invocation, CompilerInstance &Instance) {
|
||||||
if (Invocation.getFrontendOptions()
|
if (Invocation.getFrontendOptions()
|
||||||
.InputsAndOutputs.supplementaryOutputs()
|
.InputsAndOutputs.hasReferenceDependenciesPath() &&
|
||||||
.ReferenceDependenciesFilePath.empty())
|
Instance.getPrimarySourceFiles().empty()) {
|
||||||
return;
|
|
||||||
if (Instance.getPrimarySourceFiles().empty()) {
|
|
||||||
Instance.getASTContext().Diags.diagnose(
|
Instance.getASTContext().Diags.diagnose(
|
||||||
SourceLoc(), diag::emit_reference_dependencies_without_primary_file);
|
SourceLoc(), diag::emit_reference_dependencies_without_primary_file);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (auto *SF : Instance.getPrimarySourceFiles()) {
|
for (auto *SF : Instance.getPrimarySourceFiles()) {
|
||||||
std::string referenceDependenciesFilePath =
|
const std::string &referenceDependenciesFilePath =
|
||||||
Invocation.getPrimarySpecificPathsForSourceFile(*SF)
|
Invocation.getReferenceDependenciesFilePathForPrimary(
|
||||||
.SupplementaryOutputs.ReferenceDependenciesFilePath;
|
SF->getFilename());
|
||||||
emitReferenceDependenciesIfNeeded(Instance.getASTContext().Diags, SF,
|
if (!referenceDependenciesFilePath.empty())
|
||||||
|
(void)emitReferenceDependencies(Instance.getASTContext().Diags, SF,
|
||||||
*Instance.getDependencyTracker(),
|
*Instance.getDependencyTracker(),
|
||||||
referenceDependenciesFilePath);
|
referenceDependenciesFilePath);
|
||||||
}
|
}
|
||||||
@@ -759,11 +762,13 @@ static void emitReferenceDependenciesForAllPrimaryInputsIfNeeded(
|
|||||||
|
|
||||||
static bool writeTBDIfNeeded(CompilerInvocation &Invocation,
|
static bool writeTBDIfNeeded(CompilerInvocation &Invocation,
|
||||||
CompilerInstance &Instance) {
|
CompilerInstance &Instance) {
|
||||||
StringRef TBDPath = Invocation.getFrontendOptions()
|
if (!Invocation.getFrontendOptions().InputsAndOutputs.hasTBDPath())
|
||||||
.InputsAndOutputs.supplementaryOutputs()
|
|
||||||
.TBDPath;
|
|
||||||
if (TBDPath.empty())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
const std::string &TBDPath = Invocation.getTBDPathForWholeModule();
|
||||||
|
assert(!TBDPath.empty() &&
|
||||||
|
"If not WMO, getTBDPathForWholeModule should have failed");
|
||||||
|
|
||||||
auto installName = Invocation.getFrontendOptions().TBDInstallName.empty()
|
auto installName = Invocation.getFrontendOptions().TBDInstallName.empty()
|
||||||
? "lib" + Invocation.getModuleName().str() + ".dylib"
|
? "lib" + Invocation.getModuleName().str() + ".dylib"
|
||||||
: Invocation.getFrontendOptions().TBDInstallName;
|
: Invocation.getFrontendOptions().TBDInstallName;
|
||||||
@@ -822,7 +827,7 @@ generateSILModules(CompilerInvocation &Invocation, CompilerInstance &Instance) {
|
|||||||
SASTF->getFilename())) {
|
SASTF->getFilename())) {
|
||||||
assert(PSGIs.empty() && "Can only handle one primary AST input");
|
assert(PSGIs.empty() && "Can only handle one primary AST input");
|
||||||
auto SM = performSILGeneration(*SASTF, SILOpts, None);
|
auto SM = performSILGeneration(*SASTF, SILOpts, None);
|
||||||
const PrimarySpecificPaths PSPs =
|
const PrimarySpecificPaths &PSPs =
|
||||||
Instance.getPrimarySpecificPathsForPrimary(SASTF->getFilename());
|
Instance.getPrimarySpecificPathsForPrimary(SASTF->getFilename());
|
||||||
PSGIs.push_back(
|
PSGIs.push_back(
|
||||||
PostSILGenInputs{std::move(SM), !fileIsSIB(SASTF), mod, PSPs});
|
PostSILGenInputs{std::move(SM), !fileIsSIB(SASTF), mod, PSPs});
|
||||||
@@ -831,6 +836,18 @@ generateSILModules(CompilerInvocation &Invocation, CompilerInstance &Instance) {
|
|||||||
return PSGIs;
|
return PSGIs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Emits index data for all primary inputs, or the main module.
|
||||||
|
static bool
|
||||||
|
emitIndexData(CompilerInvocation &Invocation, CompilerInstance &Instance) {
|
||||||
|
bool hadEmitIndexDataError = false;
|
||||||
|
if (Instance.getPrimarySourceFiles().empty())
|
||||||
|
return emitIndexDataIfNeeded(nullptr, Invocation, Instance);
|
||||||
|
for (SourceFile *SF : Instance.getPrimarySourceFiles())
|
||||||
|
hadEmitIndexDataError = emitIndexDataIfNeeded(SF, Invocation, Instance) ||
|
||||||
|
hadEmitIndexDataError;
|
||||||
|
return hadEmitIndexDataError;
|
||||||
|
}
|
||||||
|
|
||||||
static bool performCompileStepsPostSILGen(
|
static bool performCompileStepsPostSILGen(
|
||||||
CompilerInstance &Instance, CompilerInvocation &Invocation,
|
CompilerInstance &Instance, CompilerInvocation &Invocation,
|
||||||
std::unique_ptr<SILModule> SM, bool astGuaranteedToCorrespondToSIL,
|
std::unique_ptr<SILModule> SM, bool astGuaranteedToCorrespondToSIL,
|
||||||
@@ -905,20 +922,17 @@ static bool performCompile(CompilerInstance &Instance,
|
|||||||
if (opts.PrintClangStats && Context.getClangModuleLoader())
|
if (opts.PrintClangStats && Context.getClangModuleLoader())
|
||||||
Context.getClangModuleLoader()->printStatistics();
|
Context.getClangModuleLoader()->printStatistics();
|
||||||
|
|
||||||
if (!opts.InputsAndOutputs.supplementaryOutputs()
|
(void)emitMakeDependenciesIfNeeded(Context.Diags,
|
||||||
.DependenciesFilePath.empty())
|
Instance.getDependencyTracker(), opts);
|
||||||
(void)emitMakeDependencies(Context.Diags, *Instance.getDependencyTracker(),
|
|
||||||
opts);
|
|
||||||
|
|
||||||
emitReferenceDependenciesForAllPrimaryInputsIfNeeded(Invocation, Instance);
|
emitReferenceDependenciesForAllPrimaryInputsIfNeeded(Invocation, Instance);
|
||||||
|
|
||||||
(void)emitLoadedModuleTraceIfNeeded(Context, Instance.getDependencyTracker(),
|
(void)emitLoadedModuleTraceForAllPrimariesIfNeeded(
|
||||||
opts);
|
Context, Instance.getDependencyTracker(), opts);
|
||||||
|
|
||||||
if (Context.hadError()) {
|
if (Context.hadError()) {
|
||||||
// Emit the index store data even if there were compiler errors.
|
// Emit the index store data even if there were compiler errors.
|
||||||
(void)emitIndexDataIfNeeded(Instance.getPrimarySourceFile(), Invocation,
|
(void)emitIndexData(Invocation, Instance);
|
||||||
Instance);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -932,11 +946,11 @@ static bool performCompile(CompilerInstance &Instance,
|
|||||||
// We've just been told to perform a typecheck, so we can return now.
|
// We've just been told to perform a typecheck, so we can return now.
|
||||||
if (Action == FrontendOptions::ActionType::Typecheck) {
|
if (Action == FrontendOptions::ActionType::Typecheck) {
|
||||||
const bool hadPrintAsObjCError = printAsObjCIfNeeded(
|
const bool hadPrintAsObjCError = printAsObjCIfNeeded(
|
||||||
opts.InputsAndOutputs.supplementaryOutputs().ObjCHeaderOutputPath,
|
Invocation.getObjCHeaderOutputPathForAtMostOnePrimary(),
|
||||||
Instance.getMainModule(), opts.ImplicitObjCHeaderPath, moduleIsPublic);
|
Instance.getMainModule(), opts.ImplicitObjCHeaderPath, moduleIsPublic);
|
||||||
|
|
||||||
const bool hadEmitIndexDataError = emitIndexDataIfNeeded(
|
const bool hadEmitIndexDataError = emitIndexData(Invocation, Instance);
|
||||||
Instance.getPrimarySourceFile(), Invocation, Instance);
|
|
||||||
return hadPrintAsObjCError || hadEmitIndexDataError || Context.hadError();
|
return hadPrintAsObjCError || hadEmitIndexDataError || Context.hadError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1008,7 +1022,7 @@ computeSerializationOptions(const CompilerInvocation &Invocation,
|
|||||||
serializationOpts.OutputPath = outs.ModuleOutputPath.c_str();
|
serializationOpts.OutputPath = outs.ModuleOutputPath.c_str();
|
||||||
serializationOpts.DocOutputPath = outs.ModuleDocOutputPath.c_str();
|
serializationOpts.DocOutputPath = outs.ModuleDocOutputPath.c_str();
|
||||||
serializationOpts.GroupInfoPath = opts.GroupInfoPath.c_str();
|
serializationOpts.GroupInfoPath = opts.GroupInfoPath.c_str();
|
||||||
if (opts.SerializeBridgingHeader)
|
if (opts.SerializeBridgingHeader && !outs.ModuleOutputPath.empty())
|
||||||
serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath;
|
serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath;
|
||||||
serializationOpts.ModuleLinkName = opts.ModuleLinkName;
|
serializationOpts.ModuleLinkName = opts.ModuleLinkName;
|
||||||
serializationOpts.ExtraClangOptions =
|
serializationOpts.ExtraClangOptions =
|
||||||
@@ -1144,7 +1158,7 @@ static bool validateTBDIfNeeded(CompilerInvocation &Invocation,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool generateCode(CompilerInvocation &Invocation,
|
static bool generateCode(CompilerInvocation &Invocation,
|
||||||
CompilerInstance &Instance, std::string OutputFilename,
|
CompilerInstance &Instance, StringRef OutputFilename,
|
||||||
llvm::Module *IRModule,
|
llvm::Module *IRModule,
|
||||||
llvm::GlobalVariable *HashGlobal,
|
llvm::GlobalVariable *HashGlobal,
|
||||||
UnifiedStatsReporter *Stats) {
|
UnifiedStatsReporter *Stats) {
|
||||||
@@ -1263,21 +1277,21 @@ static bool performCompileStepsPostSILGen(
|
|||||||
if (Action == FrontendOptions::ActionType::EmitSIB)
|
if (Action == FrontendOptions::ActionType::EmitSIB)
|
||||||
return serializeSIB(SM.get(), PSPs, Instance.getASTContext(), MSF);
|
return serializeSIB(SM.get(), PSPs, Instance.getASTContext(), MSF);
|
||||||
|
|
||||||
const bool haveModulePath =
|
{
|
||||||
!PSPs.SupplementaryOutputs.ModuleOutputPath.empty() ||
|
const bool haveModulePath = PSPs.haveModuleOrModuleDocOutputPaths();
|
||||||
!PSPs.SupplementaryOutputs.ModuleDocOutputPath.empty();
|
if (haveModulePath && !SM->isSerialized())
|
||||||
if (haveModulePath && !SM->isSerialized())
|
SM->serialize();
|
||||||
SM->serialize();
|
|
||||||
|
|
||||||
if (haveModulePath) {
|
if (haveModulePath) {
|
||||||
if (Action == FrontendOptions::ActionType::MergeModules ||
|
if (Action == FrontendOptions::ActionType::MergeModules ||
|
||||||
Action == FrontendOptions::ActionType::EmitModuleOnly) {
|
Action == FrontendOptions::ActionType::EmitModuleOnly) {
|
||||||
// What if MSF is a module?
|
// What if MSF is a module?
|
||||||
// emitIndexDataIfNeeded already handles that case;
|
// emitIndexDataIfNeeded already handles that case;
|
||||||
// it'll index everything.
|
// it'll index everything.
|
||||||
return emitIndexDataIfNeeded(MSF.dyn_cast<SourceFile *>(), Invocation,
|
return emitIndexDataIfNeeded(MSF.dyn_cast<SourceFile *>(), Invocation,
|
||||||
Instance) ||
|
Instance) ||
|
||||||
Context.hadError();
|
Context.hadError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1360,15 +1374,18 @@ static bool emitIndexDataIfNeeded(SourceFile *PrimarySourceFile,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (PrimarySourceFile) {
|
if (PrimarySourceFile) {
|
||||||
if (index::indexAndRecord(
|
const PrimarySpecificPaths &PSPs =
|
||||||
PrimarySourceFile, opts.InputsAndOutputs.getSingleOutputFilename(),
|
opts.InputsAndOutputs.getPrimarySpecificPathsForPrimary(
|
||||||
opts.IndexStorePath, opts.IndexSystemModules, isDebugCompilation,
|
PrimarySourceFile->getFilename());
|
||||||
Invocation.getTargetTriple(), *Instance.getDependencyTracker())) {
|
if (index::indexAndRecord(PrimarySourceFile, PSPs.OutputFilename,
|
||||||
|
opts.IndexStorePath, opts.IndexSystemModules,
|
||||||
|
isDebugCompilation, Invocation.getTargetTriple(),
|
||||||
|
*Instance.getDependencyTracker())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
StringRef moduleToken =
|
std::string moduleToken =
|
||||||
opts.InputsAndOutputs.supplementaryOutputs().ModuleOutputPath;
|
Invocation.getModuleOutputPathForAtMostOnePrimary();
|
||||||
if (moduleToken.empty())
|
if (moduleToken.empty())
|
||||||
moduleToken = opts.InputsAndOutputs.getSingleOutputFilename();
|
moduleToken = opts.InputsAndOutputs.getSingleOutputFilename();
|
||||||
|
|
||||||
@@ -1472,7 +1489,7 @@ computeStatsReporter(const CompilerInvocation &Invocation, CompilerInstance *Ins
|
|||||||
std::string InputName =
|
std::string InputName =
|
||||||
FEOpts.InputsAndOutputs.getStatsFileMangledInputName();
|
FEOpts.InputsAndOutputs.getStatsFileMangledInputName();
|
||||||
StringRef OptType = silOptModeArgStr(SILOpts.OptMode);
|
StringRef OptType = silOptModeArgStr(SILOpts.OptMode);
|
||||||
StringRef OutFile =
|
const std::string &OutFile =
|
||||||
FEOpts.InputsAndOutputs.lastInputProducingOutput().outputFilename();
|
FEOpts.InputsAndOutputs.lastInputProducingOutput().outputFilename();
|
||||||
StringRef OutputType = llvm::sys::path::extension(OutFile);
|
StringRef OutputType = llvm::sys::path::extension(OutFile);
|
||||||
std::string TripleName = LangOpts.Target.normalize();
|
std::string TripleName = LangOpts.Target.normalize();
|
||||||
@@ -1606,12 +1623,13 @@ int swift::performFrontend(ArrayRef<const char *> Args,
|
|||||||
// arguments are generated by the driver, not directly by a user. The driver
|
// arguments are generated by the driver, not directly by a user. The driver
|
||||||
// is responsible for emitting diagnostics for its own errors. See SR-2683
|
// is responsible for emitting diagnostics for its own errors. See SR-2683
|
||||||
// for details.
|
// for details.
|
||||||
|
//
|
||||||
|
// FIXME: Do we need one SerializedConsumer per primary? Owned by the
|
||||||
|
// SourceFile?
|
||||||
std::unique_ptr<DiagnosticConsumer> SerializedConsumer;
|
std::unique_ptr<DiagnosticConsumer> SerializedConsumer;
|
||||||
{
|
{
|
||||||
const std::string &SerializedDiagnosticsPath =
|
const std::string &SerializedDiagnosticsPath =
|
||||||
Invocation.getFrontendOptions()
|
Invocation.getSerializedDiagnosticsPathForAtMostOnePrimary();
|
||||||
.InputsAndOutputs.supplementaryOutputs()
|
|
||||||
.SerializedDiagnosticsPath;
|
|
||||||
if (!SerializedDiagnosticsPath.empty()) {
|
if (!SerializedDiagnosticsPath.empty()) {
|
||||||
SerializedConsumer.reset(
|
SerializedConsumer.reset(
|
||||||
serialized_diagnostics::createConsumer(SerializedDiagnosticsPath));
|
serialized_diagnostics::createConsumer(SerializedDiagnosticsPath));
|
||||||
@@ -1646,17 +1664,13 @@ int swift::performFrontend(ArrayRef<const char *> Args,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DependencyTracker depTracker;
|
DependencyTracker depTracker;
|
||||||
if (!Invocation.getFrontendOptions()
|
{
|
||||||
.InputsAndOutputs.supplementaryOutputs()
|
const FrontendInputsAndOutputs &io =
|
||||||
.DependenciesFilePath.empty() ||
|
Invocation.getFrontendOptions().InputsAndOutputs;
|
||||||
!Invocation.getFrontendOptions()
|
if (io.hasDependencyTrackerPath() ||
|
||||||
.InputsAndOutputs.supplementaryOutputs()
|
!Invocation.getFrontendOptions().IndexStorePath.empty()) {
|
||||||
.ReferenceDependenciesFilePath.empty() ||
|
Instance->setDependencyTracker(&depTracker);
|
||||||
!Invocation.getFrontendOptions().IndexStorePath.empty() ||
|
}
|
||||||
!Invocation.getFrontendOptions()
|
|
||||||
.InputsAndOutputs.supplementaryOutputs()
|
|
||||||
.LoadedModuleTracePath.empty()) {
|
|
||||||
Instance->setDependencyTracker(&depTracker);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Instance->setup(Invocation)) {
|
if (Instance->setup(Invocation)) {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ static void findAllClangImports(const clang::Module *module,
|
|||||||
bool swift::emitImportedModules(ASTContext &Context, ModuleDecl *mainModule,
|
bool swift::emitImportedModules(ASTContext &Context, ModuleDecl *mainModule,
|
||||||
const FrontendOptions &opts) {
|
const FrontendOptions &opts) {
|
||||||
|
|
||||||
auto path = opts.InputsAndOutputs.getSingleOutputFilename();
|
std::string path = opts.InputsAndOutputs.getSingleOutputFilename();
|
||||||
std::error_code EC;
|
std::error_code EC;
|
||||||
llvm::raw_fd_ostream out(path, EC, llvm::sys::fs::F_None);
|
llvm::raw_fd_ostream out(path, EC, llvm::sys::fs::F_None);
|
||||||
|
|
||||||
|
|||||||
@@ -123,20 +123,11 @@ swift::reversePathSortedFilenames(const ArrayRef<std::string> elts) {
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool swift::emitReferenceDependenciesIfNeeded(DiagnosticEngine &diags,
|
bool swift::emitReferenceDependencies(DiagnosticEngine &diags, SourceFile *SF,
|
||||||
SourceFile *SF,
|
DependencyTracker &depTracker,
|
||||||
DependencyTracker &depTracker,
|
StringRef outputPath) {
|
||||||
StringRef outputPath) {
|
|
||||||
assert(SF && "Cannot emit reference dependencies without a SourceFile");
|
assert(SF && "Cannot emit reference dependencies without a SourceFile");
|
||||||
|
|
||||||
const ReferencedNameTracker *const tracker = SF->getReferencedNameTracker();
|
|
||||||
if (!tracker) {
|
|
||||||
assert(outputPath.empty());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!outputPath.empty());
|
|
||||||
|
|
||||||
// Before writing to the dependencies file path, preserve any previous file
|
// Before writing to the dependencies file path, preserve any previous file
|
||||||
// that may have been there. No error handling -- this is just a nicety, it
|
// that may have been there. No error handling -- this is just a nicety, it
|
||||||
// doesn't matter if it fails.
|
// doesn't matter if it fails.
|
||||||
@@ -342,6 +333,9 @@ bool swift::emitReferenceDependenciesIfNeeded(DiagnosticEngine &diags,
|
|||||||
return pairs;
|
return pairs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ReferencedNameTracker *const tracker = SF->getReferencedNameTracker();
|
||||||
|
assert(tracker && "Cannot emit reference dependencies without a tracker");
|
||||||
|
|
||||||
out << "depends-top-level:\n";
|
out << "depends-top-level:\n";
|
||||||
for (auto &entry : sortedByName(tracker->getTopLevelNames())) {
|
for (auto &entry : sortedByName(tracker->getTopLevelNames())) {
|
||||||
assert(!entry.first.empty());
|
assert(!entry.first.empty());
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ std::vector<std::string>
|
|||||||
reversePathSortedFilenames(const llvm::ArrayRef<std::string> paths);
|
reversePathSortedFilenames(const llvm::ArrayRef<std::string> paths);
|
||||||
|
|
||||||
/// Emit a Swift-style dependencies file for \p SF.
|
/// Emit a Swift-style dependencies file for \p SF.
|
||||||
bool emitReferenceDependenciesIfNeeded(DiagnosticEngine &diags, SourceFile *SF,
|
bool emitReferenceDependencies(DiagnosticEngine &diags, SourceFile *SF,
|
||||||
DependencyTracker &depTracker,
|
DependencyTracker &depTracker,
|
||||||
StringRef outputPath);
|
StringRef outputPath);
|
||||||
} // end namespace swift
|
} // end namespace swift
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ class ModuleDecl;
|
|||||||
class FileUnit;
|
class FileUnit;
|
||||||
class FrontendOptions;
|
class FrontendOptions;
|
||||||
|
|
||||||
bool writeTBD(ModuleDecl *M, bool hasMultipleIGMs,
|
bool writeTBD(ModuleDecl *M, bool hasMultipleIGMs, StringRef OutputFilename,
|
||||||
llvm::StringRef OutputFilename, llvm::StringRef installName);
|
llvm::StringRef installName);
|
||||||
bool inputFileKindCanHaveTBDValidated(InputFileKind kind);
|
bool inputFileKindCanHaveTBDValidated(InputFileKind kind);
|
||||||
bool validateTBD(ModuleDecl *M, llvm::Module &IRModule, bool hasMultipleIGMs,
|
bool validateTBD(ModuleDecl *M, llvm::Module &IRModule, bool hasMultipleIGMs,
|
||||||
bool diagnoseExtraSymbolsInTBD);
|
bool diagnoseExtraSymbolsInTBD);
|
||||||
|
|||||||
@@ -665,8 +665,7 @@ static void initLLVMModule(const IRGenModule &IGM) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::pair<IRGenerator *, IRGenModule *>
|
std::pair<IRGenerator *, IRGenModule *>
|
||||||
swift::irgen::createIRGenModule(SILModule *SILMod,
|
swift::irgen::createIRGenModule(SILModule *SILMod, StringRef OutputFilename,
|
||||||
StringRef OutputFilename,
|
|
||||||
StringRef MainInputFilenameForDebugInfo,
|
StringRef MainInputFilenameForDebugInfo,
|
||||||
llvm::LLVMContext &LLVMContext) {
|
llvm::LLVMContext &LLVMContext) {
|
||||||
|
|
||||||
|
|||||||
@@ -1049,11 +1049,9 @@ public:
|
|||||||
///
|
///
|
||||||
/// The \p SF is the source file for which the llvm module is generated when
|
/// The \p SF is the source file for which the llvm module is generated when
|
||||||
/// doing multi-threaded whole-module compilation. Otherwise it is null.
|
/// doing multi-threaded whole-module compilation. Otherwise it is null.
|
||||||
IRGenModule(IRGenerator &irgen,
|
IRGenModule(IRGenerator &irgen, std::unique_ptr<llvm::TargetMachine> &&target,
|
||||||
std::unique_ptr<llvm::TargetMachine> &&target,
|
|
||||||
SourceFile *SF, llvm::LLVMContext &LLVMContext,
|
SourceFile *SF, llvm::LLVMContext &LLVMContext,
|
||||||
StringRef ModuleName,
|
StringRef ModuleName, StringRef OutputFilename,
|
||||||
StringRef OutputFilename,
|
|
||||||
StringRef MainInputFilenameForDebugInfo);
|
StringRef MainInputFilenameForDebugInfo);
|
||||||
~IRGenModule();
|
~IRGenModule();
|
||||||
|
|
||||||
|
|||||||
@@ -897,10 +897,11 @@ private:
|
|||||||
if (!ShouldRun)
|
if (!ShouldRun)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
const PrimarySpecificPaths PSPs =
|
||||||
|
CI.getPrimarySpecificPathsForAtMostOnePrimary();
|
||||||
// IRGen the current line(s).
|
// IRGen the current line(s).
|
||||||
// FIXME: We shouldn't need to use the global context here, but
|
// FIXME: We shouldn't need to use the global context here, but
|
||||||
// something is persisting across calls to performIRGeneration.
|
// something is persisting across calls to performIRGeneration.
|
||||||
const auto PSPs = CI.getPrimarySpecificPathsForAtMostOnePrimary();
|
|
||||||
auto LineModule = performIRGeneration(
|
auto LineModule = performIRGeneration(
|
||||||
IRGenOpts, REPLInputFile, std::move(sil), "REPLLine", PSPs,
|
IRGenOpts, REPLInputFile, std::move(sil), "REPLLine", PSPs,
|
||||||
getGlobalLLVMContext(), RC.CurIRGenElem);
|
getGlobalLLVMContext(), RC.CurIRGenElem);
|
||||||
|
|||||||
@@ -439,7 +439,6 @@ bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation,
|
|||||||
ImporterOpts.DetailedPreprocessingRecord = true;
|
ImporterOpts.DetailedPreprocessingRecord = true;
|
||||||
|
|
||||||
assert(!Invocation.getModuleName().empty());
|
assert(!Invocation.getModuleName().empty());
|
||||||
Invocation.setSerializedDiagnosticsPath(StringRef());
|
|
||||||
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
||||||
Invocation.getLangOptions().DiagnosticsEditorMode = true;
|
Invocation.getLangOptions().DiagnosticsEditorMode = true;
|
||||||
Invocation.getLangOptions().CollectParsedToken = true;
|
Invocation.getLangOptions().CollectParsedToken = true;
|
||||||
@@ -700,7 +699,7 @@ bool ASTProducer::shouldRebuild(SwiftASTManager::Implementation &MgrImpl,
|
|||||||
Invok.Opts.Invok.getFrontendOptions().InputsAndOutputs.inputCount());
|
Invok.Opts.Invok.getFrontendOptions().InputsAndOutputs.inputCount());
|
||||||
for (const auto &input :
|
for (const auto &input :
|
||||||
Invok.Opts.Invok.getFrontendOptions().InputsAndOutputs.getAllInputs()) {
|
Invok.Opts.Invok.getFrontendOptions().InputsAndOutputs.getAllInputs()) {
|
||||||
StringRef File = input.file();
|
const std::string &File = input.file();
|
||||||
bool FoundSnapshot = false;
|
bool FoundSnapshot = false;
|
||||||
for (auto &Snap : Snapshots) {
|
for (auto &Snap : Snapshots) {
|
||||||
if (Snap->getFilename() == File) {
|
if (Snap->getFilename() == File) {
|
||||||
@@ -887,7 +886,7 @@ void ASTProducer::findSnapshotAndOpenFiles(
|
|||||||
const InvocationOptions &Opts = InvokRef->Impl.Opts;
|
const InvocationOptions &Opts = InvokRef->Impl.Opts;
|
||||||
for (const auto &input :
|
for (const auto &input :
|
||||||
Opts.Invok.getFrontendOptions().InputsAndOutputs.getAllInputs()) {
|
Opts.Invok.getFrontendOptions().InputsAndOutputs.getAllInputs()) {
|
||||||
StringRef File = input.file();
|
const std::string &File = input.file();
|
||||||
bool IsPrimary = input.isPrimary();
|
bool IsPrimary = input.isPrimary();
|
||||||
bool FoundSnapshot = false;
|
bool FoundSnapshot = false;
|
||||||
for (auto &Snap : Snapshots) {
|
for (auto &Snap : Snapshots) {
|
||||||
|
|||||||
@@ -427,9 +427,9 @@ int main(int argc, char **argv) {
|
|||||||
} else {
|
} else {
|
||||||
auto *SILMod = CI.getSILModule();
|
auto *SILMod = CI.getSILModule();
|
||||||
{
|
{
|
||||||
const auto PSPs = CI.getPrimarySpecificPathsForAtMostOnePrimary();
|
|
||||||
auto T = irgen::createIRGenModule(
|
auto T = irgen::createIRGenModule(
|
||||||
SILMod, PSPs.OutputFilename, PSPs.MainInputFilenameForDebugInfo,
|
SILMod, Invocation.getOutputFilenameForAtMostOnePrimary(),
|
||||||
|
Invocation.getMainInputFilenameForDebugInfoForAtMostOnePrimary(),
|
||||||
getGlobalLLVMContext());
|
getGlobalLLVMContext());
|
||||||
runCommandLineSelectedPasses(SILMod, T.second);
|
runCommandLineSelectedPasses(SILMod, T.second);
|
||||||
irgen::deleteIRGenModule(T);
|
irgen::deleteIRGenModule(T);
|
||||||
|
|||||||
Reference in New Issue
Block a user