mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge remote-tracking branch 'origin/master' into master-next
This commit is contained in:
@@ -150,6 +150,9 @@ ERROR(error_implicit_output_file_is_directory,none,
|
|||||||
"the implicit output file '%0' is a directory; explicitly specify a filename "
|
"the implicit output file '%0' is a directory; explicitly specify a filename "
|
||||||
"using -o", (StringRef))
|
"using -o", (StringRef))
|
||||||
|
|
||||||
|
ERROR(error_if_any_output_files_are_specified_they_all_must_be,none,
|
||||||
|
"if any output files are specified, they all must be", ())
|
||||||
|
|
||||||
ERROR(error_primary_file_not_found,none,
|
ERROR(error_primary_file_not_found,none,
|
||||||
"primary file '%0' was not found in file list '%1'",
|
"primary file '%0' was not found in file list '%1'",
|
||||||
(StringRef, StringRef))
|
(StringRef, StringRef))
|
||||||
|
|||||||
@@ -190,6 +190,11 @@ public:
|
|||||||
|
|
||||||
/// 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.
|
||||||
|
/// This function is used by (at least)
|
||||||
|
/// lldb/source/Symbol/SwiftASTContext.cpp:4603
|
||||||
|
/// FIXME: This function should go away in favor of
|
||||||
|
/// Instance.getFrontendOptions().InputsAndOutputs.getSingleOutputFilename
|
||||||
|
/// when batch mode handles all contingencies.
|
||||||
StringRef getSingleOutputFilename() const {
|
StringRef getSingleOutputFilename() const {
|
||||||
if (OutputFilenames.size() >= 1)
|
if (OutputFilenames.size() >= 1)
|
||||||
return OutputFilenames.back();
|
return OutputFilenames.back();
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace swift {
|
|||||||
class ArgsToFrontendInputsConverter {
|
class ArgsToFrontendInputsConverter {
|
||||||
DiagnosticEngine &Diags;
|
DiagnosticEngine &Diags;
|
||||||
const llvm::opt::ArgList &Args;
|
const llvm::opt::ArgList &Args;
|
||||||
FrontendInputs &Inputs;
|
FrontendInputsAndOutputs &InputsAndOutputs;
|
||||||
|
|
||||||
llvm::opt::Arg const *const FilelistPathArg;
|
llvm::opt::Arg const *const FilelistPathArg;
|
||||||
llvm::opt::Arg const *const PrimaryFilelistPathArg;
|
llvm::opt::Arg const *const PrimaryFilelistPathArg;
|
||||||
@@ -54,7 +54,7 @@ class ArgsToFrontendInputsConverter {
|
|||||||
public:
|
public:
|
||||||
ArgsToFrontendInputsConverter(DiagnosticEngine &diags,
|
ArgsToFrontendInputsConverter(DiagnosticEngine &diags,
|
||||||
const llvm::opt::ArgList &args,
|
const llvm::opt::ArgList &args,
|
||||||
FrontendInputs &inputs);
|
FrontendInputsAndOutputs &inputsAndOutputs);
|
||||||
|
|
||||||
bool convert();
|
bool convert();
|
||||||
|
|
||||||
@@ -69,6 +69,8 @@ private:
|
|||||||
std::set<StringRef>
|
std::set<StringRef>
|
||||||
createInputFilesConsumingPrimaries(std::set<StringRef> primaryFiles);
|
createInputFilesConsumingPrimaries(std::set<StringRef> primaryFiles);
|
||||||
bool checkForMissingPrimaryFiles(std::set<StringRef> primaryFiles);
|
bool checkForMissingPrimaryFiles(std::set<StringRef> primaryFiles);
|
||||||
|
|
||||||
|
bool isSingleThreadedWMO() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace swift
|
} // namespace swift
|
||||||
|
|||||||
@@ -50,34 +50,13 @@ private:
|
|||||||
void setUnsignedIntegerArgument(options::ID optionID, unsigned max,
|
void setUnsignedIntegerArgument(options::ID optionID, unsigned max,
|
||||||
unsigned &valueToSet);
|
unsigned &valueToSet);
|
||||||
|
|
||||||
FrontendOptions::ActionType determineRequestedAction() const;
|
|
||||||
|
|
||||||
bool setUpForSILOrLLVM();
|
bool setUpForSILOrLLVM();
|
||||||
|
|
||||||
/// Determine the correct output filename when none was specified.
|
|
||||||
///
|
|
||||||
/// Such an absence should only occur when invoking the frontend
|
|
||||||
/// without the driver,
|
|
||||||
/// because the driver will always pass -o with an appropriate filename
|
|
||||||
/// if output is required for the requested action.
|
|
||||||
bool deriveOutputFilenameFromInputFile();
|
|
||||||
|
|
||||||
/// Determine the correct output filename when a directory was specified.
|
|
||||||
///
|
|
||||||
/// Such a specification should only occur when invoking the frontend
|
|
||||||
/// directly, because the driver will always pass -o with an appropriate
|
|
||||||
/// filename if output is required for the requested action.
|
|
||||||
bool deriveOutputFilenameForDirectory(StringRef outputDir);
|
|
||||||
|
|
||||||
std::string determineBaseNameOfOutput() const;
|
|
||||||
|
|
||||||
void deriveOutputFilenameFromParts(StringRef dir, StringRef base);
|
|
||||||
|
|
||||||
void determineSupplementaryOutputFilenames();
|
void determineSupplementaryOutputFilenames();
|
||||||
|
|
||||||
/// Returns the output filenames on the command line or in the output
|
/// \returns the output filenames on the command line or in the output
|
||||||
/// filelist. If there
|
/// filelist, or an empty vector if there were neither -o's nor an output
|
||||||
/// were neither -o's nor an output filelist, returns an empty vector.
|
/// filelist.
|
||||||
ArrayRef<std::string> getOutputFilenamesFromCommandLineOrFilelist();
|
ArrayRef<std::string> getOutputFilenamesFromCommandLineOrFilelist();
|
||||||
|
|
||||||
bool checkForUnusedOutputPaths() const;
|
bool checkForUnusedOutputPaths() const;
|
||||||
@@ -91,6 +70,9 @@ public:
|
|||||||
: Diags(Diags), Args(Args), Opts(Opts) {}
|
: Diags(Diags), Args(Args), Opts(Opts) {}
|
||||||
|
|
||||||
bool convert();
|
bool convert();
|
||||||
|
|
||||||
|
static FrontendOptions::ActionType
|
||||||
|
determineRequestedAction(const llvm::opt::ArgList &);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace swift
|
} // namespace swift
|
||||||
|
|||||||
113
include/swift/Frontend/ArgsToFrontendOutputsConverter.h
Normal file
113
include/swift/Frontend/ArgsToFrontendOutputsConverter.h
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
//===--- ArgsToFrontendOutputsConverter.h -----------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See https://swift.org/LICENSE.txt for license information
|
||||||
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef SWIFT_FRONTEND_ARGSTOFRONTENDOUTPUTSCONVERTER_H
|
||||||
|
#define SWIFT_FRONTEND_ARGSTOFRONTENDOUTPUTSCONVERTER_H
|
||||||
|
|
||||||
|
#include "swift/AST/DiagnosticConsumer.h"
|
||||||
|
#include "swift/AST/DiagnosticEngine.h"
|
||||||
|
#include "swift/Basic/LLVM.h"
|
||||||
|
#include "swift/Frontend/FrontendOptions.h"
|
||||||
|
#include "swift/Option/Options.h"
|
||||||
|
#include "llvm/Option/ArgList.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace swift {
|
||||||
|
|
||||||
|
/// Given the command line arguments and information about the inputs,
|
||||||
|
/// Fill in all the information in FrontendInputsAndOutputs.
|
||||||
|
|
||||||
|
class ArgsToFrontendOutputsConverter {
|
||||||
|
const llvm::opt::ArgList &Args;
|
||||||
|
StringRef ModuleName;
|
||||||
|
FrontendInputsAndOutputs &InputsAndOutputs;
|
||||||
|
DiagnosticEngine &Diags;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ArgsToFrontendOutputsConverter(const llvm::opt::ArgList &args,
|
||||||
|
StringRef moduleName,
|
||||||
|
FrontendInputsAndOutputs &inputsAndOutputs,
|
||||||
|
DiagnosticEngine &diags)
|
||||||
|
: Args(args), ModuleName(moduleName), InputsAndOutputs(inputsAndOutputs),
|
||||||
|
Diags(diags) {}
|
||||||
|
|
||||||
|
Optional<std::vector<std::string>> convert();
|
||||||
|
|
||||||
|
/// Try to read an output file list file.
|
||||||
|
/// \returns `None` if it could not open the filelist.
|
||||||
|
static Optional<std::vector<std::string>>
|
||||||
|
readOutputFileList(StringRef filelistPath, DiagnosticEngine &diags);
|
||||||
|
};
|
||||||
|
|
||||||
|
class OutputFilesComputer {
|
||||||
|
const llvm::opt::ArgList &Args;
|
||||||
|
DiagnosticEngine &Diags;
|
||||||
|
const FrontendInputsAndOutputs &InputsAndOutputs;
|
||||||
|
const std::vector<std::string> OutputFileArguments;
|
||||||
|
const std::string OutputDirectoryArgument;
|
||||||
|
const StringRef FirstInput;
|
||||||
|
const FrontendOptions::ActionType RequestedAction;
|
||||||
|
const llvm::opt::Arg *const ModuleNameArg;
|
||||||
|
const StringRef Suffix;
|
||||||
|
const bool HasTextualOutput;
|
||||||
|
|
||||||
|
OutputFilesComputer(const llvm::opt::ArgList &args, DiagnosticEngine &diags,
|
||||||
|
const FrontendInputsAndOutputs &inputsAndOutputs,
|
||||||
|
std::vector<std::string> outputFileArguments,
|
||||||
|
StringRef outputDirectoryArgument, StringRef firstInput,
|
||||||
|
FrontendOptions::ActionType requestedAction,
|
||||||
|
const llvm::opt::Arg *moduleNameArg, StringRef suffix,
|
||||||
|
bool hasTextualOutput);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static Optional<OutputFilesComputer>
|
||||||
|
create(const llvm::opt::ArgList &args, DiagnosticEngine &diags,
|
||||||
|
const FrontendInputsAndOutputs &inputsAndOutputs);
|
||||||
|
|
||||||
|
/// \return the output filenames on the command line or in the output
|
||||||
|
/// filelist. If there
|
||||||
|
/// were neither -o's nor an output filelist, returns an empty vector.
|
||||||
|
static Optional<std::vector<std::string>>
|
||||||
|
getOutputFilenamesFromCommandLineOrFilelist(const llvm::opt::ArgList &args,
|
||||||
|
DiagnosticEngine &diags);
|
||||||
|
|
||||||
|
Optional<std::vector<std::string>> computeOutputFiles() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Optional<std::string> computeOutputFile(StringRef outputArg,
|
||||||
|
const InputFile &input) const;
|
||||||
|
|
||||||
|
/// \return the correct output filename when none was specified.
|
||||||
|
///
|
||||||
|
/// Such an absence should only occur when invoking the frontend
|
||||||
|
/// without the driver,
|
||||||
|
/// because the driver will always pass -o with an appropriate filename
|
||||||
|
/// if output is required for the requested action.
|
||||||
|
Optional<std::string> deriveOutputFileFromInput(const InputFile &input) const;
|
||||||
|
|
||||||
|
/// \return the correct output filename when a directory was specified.
|
||||||
|
///
|
||||||
|
/// Such a specification should only occur when invoking the frontend
|
||||||
|
/// directly, because the driver will always pass -o with an appropriate
|
||||||
|
/// filename if output is required for the requested action.
|
||||||
|
Optional<std::string>
|
||||||
|
deriveOutputFileForDirectory(const InputFile &input) const;
|
||||||
|
|
||||||
|
std::string determineBaseNameOfOutput(const InputFile &input) const;
|
||||||
|
|
||||||
|
std::string deriveOutputFileFromParts(StringRef dir, StringRef base) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace swift
|
||||||
|
|
||||||
|
#endif /* SWIFT_FRONTEND_ARGSTOFRONTENDOUTPUTSCONVERTER_H */
|
||||||
@@ -54,7 +54,7 @@ class SerializedModuleLoader;
|
|||||||
/// - options for all stages of translation,
|
/// - options for all stages of translation,
|
||||||
/// - information about the build environment,
|
/// - information about the build environment,
|
||||||
/// - information about the job being performed, and
|
/// - information about the job being performed, and
|
||||||
/// - lists of inputs.
|
/// - lists of inputs and outputs.
|
||||||
///
|
///
|
||||||
/// A CompilerInvocation can be built from a frontend command line
|
/// A CompilerInvocation can be built from a frontend command line
|
||||||
/// using parseArgs. It can then be used to build a CompilerInstance,
|
/// using parseArgs. It can then be used to build a CompilerInstance,
|
||||||
@@ -245,7 +245,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
StringRef getOutputFilename() const {
|
StringRef getOutputFilename() const {
|
||||||
return FrontendOpts.getSingleOutputFilename();
|
return FrontendOpts.InputsAndOutputs.getSingleOutputFilename();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCodeCompletionPoint(llvm::MemoryBuffer *Buf, unsigned Offset) {
|
void setCodeCompletionPoint(llvm::MemoryBuffer *Buf, unsigned Offset) {
|
||||||
|
|||||||
@@ -1,127 +0,0 @@
|
|||||||
//===--- FrontendInputs.h ---------------------------------------*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// This source file is part of the Swift.org open source project
|
|
||||||
//
|
|
||||||
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
|
|
||||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
||||||
//
|
|
||||||
// See https://swift.org/LICENSE.txt for license information
|
|
||||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef SWIFT_FRONTEND_FRONTENDINPUTS_H
|
|
||||||
#define SWIFT_FRONTEND_FRONTENDINPUTS_H
|
|
||||||
|
|
||||||
#include "swift/AST/Module.h"
|
|
||||||
#include "swift/Frontend/FrontendInputs.h"
|
|
||||||
#include "swift/Frontend/InputFile.h"
|
|
||||||
#include "llvm/ADT/Hashing.h"
|
|
||||||
#include "llvm/ADT/MapVector.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
class MemoryBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace swift {
|
|
||||||
|
|
||||||
/// Information about all the inputs to the frontend.
|
|
||||||
class FrontendInputs {
|
|
||||||
friend class ArgsToFrontendInputsConverter;
|
|
||||||
|
|
||||||
std::vector<InputFile> AllInputs;
|
|
||||||
typedef llvm::StringMap<unsigned> InputFileMap;
|
|
||||||
InputFileMap PrimaryInputs;
|
|
||||||
|
|
||||||
public:
|
|
||||||
FrontendInputs() = default;
|
|
||||||
|
|
||||||
FrontendInputs(const FrontendInputs &other);
|
|
||||||
|
|
||||||
FrontendInputs &operator=(const FrontendInputs &other);
|
|
||||||
|
|
||||||
// Readers:
|
|
||||||
|
|
||||||
ArrayRef<InputFile> getAllInputs() const { return AllInputs; }
|
|
||||||
|
|
||||||
std::vector<std::string> getInputFilenames() const;
|
|
||||||
|
|
||||||
unsigned inputCount() const { return AllInputs.size(); }
|
|
||||||
|
|
||||||
bool hasInputs() const { return !AllInputs.empty(); }
|
|
||||||
|
|
||||||
bool hasSingleInput() const { return inputCount() == 1; }
|
|
||||||
|
|
||||||
StringRef getFilenameOfFirstInput() const;
|
|
||||||
|
|
||||||
bool isReadingFromStdin() const;
|
|
||||||
|
|
||||||
// If we have exactly one input filename, and its extension is "bc" or "ll",
|
|
||||||
// treat the input as LLVM_IR.
|
|
||||||
bool shouldTreatAsLLVM() const;
|
|
||||||
|
|
||||||
// Primary input readers
|
|
||||||
|
|
||||||
private:
|
|
||||||
void assertMustNotBeMoreThanOnePrimaryInput() const;
|
|
||||||
|
|
||||||
bool areAllNonPrimariesSIB() const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
unsigned primaryInputCount() const { return PrimaryInputs.size(); }
|
|
||||||
|
|
||||||
// Primary count readers:
|
|
||||||
|
|
||||||
bool hasUniquePrimaryInput() const { return primaryInputCount() == 1; }
|
|
||||||
|
|
||||||
bool hasPrimaryInputs() const { return primaryInputCount() > 0; }
|
|
||||||
|
|
||||||
bool isWholeModule() const { return !hasPrimaryInputs(); }
|
|
||||||
|
|
||||||
// Count-dependend readers:
|
|
||||||
|
|
||||||
/// \return the unique primary input, if one exists.
|
|
||||||
const InputFile *getUniquePrimaryInput() const;
|
|
||||||
|
|
||||||
const InputFile &getRequiredUniquePrimaryInput() const;
|
|
||||||
|
|
||||||
/// \return the name of the unique primary input, or an empty StrinRef if
|
|
||||||
/// there isn't one.
|
|
||||||
StringRef getNameOfUniquePrimaryInputFile() const;
|
|
||||||
|
|
||||||
bool isInputPrimary(StringRef file) const;
|
|
||||||
|
|
||||||
unsigned numberOfPrimaryInputsEndingWith(const char *extension) const;
|
|
||||||
|
|
||||||
// Multi-facet readers
|
|
||||||
|
|
||||||
bool shouldTreatAsSIL() const;
|
|
||||||
|
|
||||||
/// \return true for error
|
|
||||||
bool verifyInputs(DiagnosticEngine &diags, bool treatAsSIL,
|
|
||||||
bool isREPLRequested, bool isNoneRequested) const;
|
|
||||||
|
|
||||||
// Writers
|
|
||||||
|
|
||||||
void addInputFile(StringRef file, llvm::MemoryBuffer *buffer = nullptr) {
|
|
||||||
addInput(InputFile(file, false, buffer));
|
|
||||||
}
|
|
||||||
void addPrimaryInputFile(StringRef file,
|
|
||||||
llvm::MemoryBuffer *buffer = nullptr) {
|
|
||||||
addInput(InputFile(file, true, buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
void addInput(const InputFile &input);
|
|
||||||
|
|
||||||
void clearInputs() {
|
|
||||||
AllInputs.clear();
|
|
||||||
PrimaryInputs.clear();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace swift
|
|
||||||
|
|
||||||
#endif /* SWIFT_FRONTEND_FRONTENDINPUTS_H */
|
|
||||||
200
include/swift/Frontend/FrontendInputsAndOutputs.h
Normal file
200
include/swift/Frontend/FrontendInputsAndOutputs.h
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
//===--- FrontendInputs.h ---------------------------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See https://swift.org/LICENSE.txt for license information
|
||||||
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef SWIFT_FRONTEND_FRONTENDINPUTS_H
|
||||||
|
#define SWIFT_FRONTEND_FRONTENDINPUTS_H
|
||||||
|
|
||||||
|
#include "swift/AST/Module.h"
|
||||||
|
#include "swift/Frontend/InputFile.h"
|
||||||
|
#include "llvm/ADT/Hashing.h"
|
||||||
|
#include "llvm/ADT/MapVector.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class MemoryBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace swift {
|
||||||
|
|
||||||
|
/// Information about all the inputs and outputs to the frontend.
|
||||||
|
|
||||||
|
class FrontendInputsAndOutputs {
|
||||||
|
friend class ArgsToFrontendInputsConverter;
|
||||||
|
|
||||||
|
std::vector<InputFile> AllInputs;
|
||||||
|
|
||||||
|
llvm::StringMap<unsigned> PrimaryInputs;
|
||||||
|
|
||||||
|
/// In Single-threaded WMO mode, all inputs are used
|
||||||
|
/// both for importing and compiling.
|
||||||
|
bool IsSingleThreadedWMO = false;
|
||||||
|
|
||||||
|
/// Punt where needed to enable batch mode experiments.
|
||||||
|
bool AreBatchModeChecksBypassed = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool areBatchModeChecksBypassed() const { return AreBatchModeChecksBypassed; }
|
||||||
|
void setBypassBatchModeChecks(bool bbc) { AreBatchModeChecksBypassed = bbc; }
|
||||||
|
|
||||||
|
FrontendInputsAndOutputs() = default;
|
||||||
|
FrontendInputsAndOutputs(const FrontendInputsAndOutputs &other);
|
||||||
|
FrontendInputsAndOutputs &operator=(const FrontendInputsAndOutputs &other);
|
||||||
|
|
||||||
|
// Whole-module-optimization (WMO) routines:
|
||||||
|
|
||||||
|
// SingleThreadedWMO produces only main output file. In contrast,
|
||||||
|
// multi-threaded WMO produces one main output per input, as single-file and
|
||||||
|
// batch-mode do for each primary. Both WMO modes produce only one set of
|
||||||
|
// supplementary outputs.
|
||||||
|
|
||||||
|
bool isSingleThreadedWMO() const { return IsSingleThreadedWMO; }
|
||||||
|
void setIsSingleThreadedWMO(bool istw) { IsSingleThreadedWMO = istw; }
|
||||||
|
|
||||||
|
bool isWholeModule() const { return !hasPrimaryInputs(); }
|
||||||
|
|
||||||
|
// Readers:
|
||||||
|
|
||||||
|
// All inputs:
|
||||||
|
|
||||||
|
ArrayRef<InputFile> getAllInputs() const { return AllInputs; }
|
||||||
|
|
||||||
|
std::vector<std::string> getInputFilenames() const;
|
||||||
|
|
||||||
|
unsigned inputCount() const { return AllInputs.size(); }
|
||||||
|
|
||||||
|
bool hasInputs() const { return !AllInputs.empty(); }
|
||||||
|
|
||||||
|
bool hasSingleInput() const { return inputCount() == 1; }
|
||||||
|
|
||||||
|
const InputFile &firstInput() const { return AllInputs[0]; }
|
||||||
|
InputFile &firstInput() { return AllInputs[0]; }
|
||||||
|
|
||||||
|
const InputFile &lastInput() const { return AllInputs.back(); }
|
||||||
|
|
||||||
|
StringRef getFilenameOfFirstInput() const;
|
||||||
|
|
||||||
|
bool isReadingFromStdin() const;
|
||||||
|
|
||||||
|
void forEachInput(llvm::function_ref<void(const InputFile &)> fn) const;
|
||||||
|
|
||||||
|
// Primaries:
|
||||||
|
|
||||||
|
const InputFile &firstPrimaryInput() const;
|
||||||
|
const InputFile &lastPrimaryInput() const;
|
||||||
|
|
||||||
|
void
|
||||||
|
forEachPrimaryInput(llvm::function_ref<void(const InputFile &)> fn) const;
|
||||||
|
|
||||||
|
unsigned primaryInputCount() const { return PrimaryInputs.size(); }
|
||||||
|
|
||||||
|
// Primary count readers:
|
||||||
|
|
||||||
|
bool hasUniquePrimaryInput() const { return primaryInputCount() == 1; }
|
||||||
|
|
||||||
|
bool hasPrimaryInputs() const { return primaryInputCount() > 0; }
|
||||||
|
|
||||||
|
/// Fails an assertion if there is more than one primary input.
|
||||||
|
/// Used in situations where only one primary input can be handled
|
||||||
|
/// and where batch mode has not been implemented yet.
|
||||||
|
void assertMustNotBeMoreThanOnePrimaryInput() const;
|
||||||
|
|
||||||
|
/// Fails an assertion when there is more than one primary input unless
|
||||||
|
/// the experimental -bypass-batch-mode-checks argument was passed to
|
||||||
|
/// the front end.
|
||||||
|
/// FIXME: When batch mode is complete, this function should be obsolete.
|
||||||
|
void
|
||||||
|
assertMustNotBeMoreThanOnePrimaryInputUnlessBatchModeChecksHaveBeenBypassed()
|
||||||
|
const;
|
||||||
|
|
||||||
|
// Count-dependend readers:
|
||||||
|
|
||||||
|
/// \return the unique primary input, if one exists.
|
||||||
|
const InputFile *getUniquePrimaryInput() const;
|
||||||
|
|
||||||
|
const InputFile &getRequiredUniquePrimaryInput() const;
|
||||||
|
|
||||||
|
/// \return the name of the unique primary input, or an empty StrinRef if
|
||||||
|
/// there isn't one.
|
||||||
|
StringRef getNameOfUniquePrimaryInputFile() const;
|
||||||
|
|
||||||
|
/// Combines all primaries for stats reporter
|
||||||
|
std::string getStatsFileMangledInputName() const;
|
||||||
|
|
||||||
|
bool isInputPrimary(StringRef file) const;
|
||||||
|
|
||||||
|
unsigned numberOfPrimaryInputsEndingWith(const char *extension) const;
|
||||||
|
|
||||||
|
// Multi-facet readers
|
||||||
|
|
||||||
|
// If we have exactly one input filename, and its extension is "bc" or "ll",
|
||||||
|
// treat the input as LLVM_IR.
|
||||||
|
bool shouldTreatAsLLVM() const;
|
||||||
|
bool shouldTreatAsSIL() const;
|
||||||
|
|
||||||
|
bool areAllNonPrimariesSIB() const;
|
||||||
|
|
||||||
|
/// \return true for error
|
||||||
|
bool verifyInputs(DiagnosticEngine &diags, bool treatAsSIL,
|
||||||
|
bool isREPLRequested, bool isNoneRequested) const;
|
||||||
|
|
||||||
|
// Changing inputs
|
||||||
|
|
||||||
|
public:
|
||||||
|
void clearInputs();
|
||||||
|
void addInput(const InputFile &input);
|
||||||
|
void addInputFile(StringRef file, llvm::MemoryBuffer *buffer = nullptr);
|
||||||
|
void addPrimaryInputFile(StringRef file,
|
||||||
|
llvm::MemoryBuffer *buffer = nullptr);
|
||||||
|
|
||||||
|
// Outputs
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ArgsToFrontendOptionsConverter;
|
||||||
|
|
||||||
|
void setMainOutputs(ArrayRef<std::string> outputFiles);
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsigned countOfInputsProducingMainOutputs() const;
|
||||||
|
|
||||||
|
const InputFile &firstInputProducingOutput() const;
|
||||||
|
const InputFile &lastInputProducingOutput() const;
|
||||||
|
|
||||||
|
/// Under single-threaded WMO, we pretend that the first input
|
||||||
|
/// generates the main output, even though it will include code
|
||||||
|
/// generated from all of them.
|
||||||
|
void forEachInputProducingAMainOutputFile(
|
||||||
|
llvm::function_ref<void(const InputFile &)> fn) const;
|
||||||
|
|
||||||
|
std::vector<std::string> copyOutputFilenames() const;
|
||||||
|
|
||||||
|
void
|
||||||
|
forEachOutputFilename(llvm::function_ref<void(const std::string &)> fn) const;
|
||||||
|
|
||||||
|
/// Gets the name of the specified output filename.
|
||||||
|
/// If multiple files are specified, the last one is returned.
|
||||||
|
StringRef getSingleOutputFilename() const;
|
||||||
|
|
||||||
|
bool isOutputFilenameStdout() const;
|
||||||
|
bool isOutputFileDirectory() const;
|
||||||
|
bool hasNamedOutputFile() const;
|
||||||
|
|
||||||
|
// Supplementary outputs
|
||||||
|
|
||||||
|
void forEachInputProducingSupplementaryOutput(
|
||||||
|
llvm::function_ref<void(const InputFile &)> fn) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace swift
|
||||||
|
|
||||||
|
#endif /* SWIFT_FRONTEND_FRONTENDINPUTS_H */
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
#define SWIFT_FRONTEND_FRONTENDOPTIONS_H
|
#define SWIFT_FRONTEND_FRONTENDOPTIONS_H
|
||||||
|
|
||||||
#include "swift/AST/Module.h"
|
#include "swift/AST/Module.h"
|
||||||
#include "swift/Frontend/FrontendInputs.h"
|
#include "swift/Frontend/FrontendInputsAndOutputs.h"
|
||||||
#include "swift/Frontend/InputFile.h"
|
#include "swift/Frontend/InputFile.h"
|
||||||
#include "llvm/ADT/Hashing.h"
|
#include "llvm/ADT/Hashing.h"
|
||||||
|
|
||||||
@@ -33,37 +33,15 @@ class FrontendOptions {
|
|||||||
friend class ArgsToFrontendOptionsConverter;
|
friend class ArgsToFrontendOptionsConverter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FrontendInputs Inputs;
|
FrontendInputsAndOutputs InputsAndOutputs;
|
||||||
|
|
||||||
/// The kind of input on which the frontend should operate.
|
/// The kind of input on which the frontend should operate.
|
||||||
InputFileKind InputKind = InputFileKind::IFK_Swift;
|
InputFileKind InputKind = InputFileKind::IFK_Swift;
|
||||||
|
|
||||||
/// The specified output files. If only a single outputfile is generated,
|
void forAllOutputPaths(const InputFile &input,
|
||||||
/// the name of the last specified file is taken.
|
std::function<void(const std::string &)> fn) const;
|
||||||
std::vector<std::string> OutputFilenames;
|
|
||||||
|
|
||||||
void forAllOutputPaths(std::function<void(const std::string &)> fn) const;
|
|
||||||
|
|
||||||
/// Gets the name of the specified output filename.
|
|
||||||
/// If multiple files are specified, the last one is returned.
|
|
||||||
StringRef getSingleOutputFilename() const {
|
|
||||||
if (OutputFilenames.size() >= 1)
|
|
||||||
return OutputFilenames.back();
|
|
||||||
return StringRef();
|
|
||||||
}
|
|
||||||
/// Sets a single filename as output filename.
|
|
||||||
void setSingleOutputFilename(const std::string &FileName) {
|
|
||||||
OutputFilenames.clear();
|
|
||||||
OutputFilenames.push_back(FileName);
|
|
||||||
}
|
|
||||||
void setOutputFilenameToStdout() { setSingleOutputFilename("-"); }
|
|
||||||
bool isOutputFilenameStdout() const {
|
|
||||||
return getSingleOutputFilename() == "-";
|
|
||||||
}
|
|
||||||
bool isOutputFileDirectory() const;
|
bool isOutputFileDirectory() const;
|
||||||
bool hasNamedOutputFile() const {
|
|
||||||
return !OutputFilenames.empty() && !isOutputFilenameStdout();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A list of arbitrary modules to import and make implicitly visible.
|
/// A list of arbitrary modules to import and make implicitly visible.
|
||||||
std::vector<std::string> ImplicitImportModuleNames;
|
std::vector<std::string> ImplicitImportModuleNames;
|
||||||
@@ -315,7 +293,8 @@ public:
|
|||||||
StringRef determineFallbackModuleName() const;
|
StringRef determineFallbackModuleName() const;
|
||||||
|
|
||||||
bool isCompilingExactlyOneSwiftFile() const {
|
bool isCompilingExactlyOneSwiftFile() const {
|
||||||
return InputKind == InputFileKind::IFK_Swift && Inputs.hasSingleInput();
|
return InputKind == InputFileKind::IFK_Swift &&
|
||||||
|
InputsAndOutputs.hasSingleInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -33,15 +33,24 @@ enum class InputFileKind {
|
|||||||
class InputFile {
|
class InputFile {
|
||||||
std::string Filename;
|
std::string Filename;
|
||||||
bool IsPrimary;
|
bool IsPrimary;
|
||||||
/// Null if the contents are not overridden.
|
/// Points to a buffer overriding the file's contents, or nullptr if there is
|
||||||
|
/// none.
|
||||||
llvm::MemoryBuffer *Buffer;
|
llvm::MemoryBuffer *Buffer;
|
||||||
|
|
||||||
|
/// Contains the name of the main output file, that is, the .o file for this
|
||||||
|
/// input. If there is no such file, contains an empty string. If the output
|
||||||
|
/// is to be written to stdout, contains "-".
|
||||||
|
std::string OutputFilename;
|
||||||
|
|
||||||
public:
|
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
|
||||||
/// string.
|
/// string.
|
||||||
InputFile(StringRef name, bool isPrimary,
|
InputFile(StringRef name, bool isPrimary,
|
||||||
llvm::MemoryBuffer *buffer = nullptr)
|
llvm::MemoryBuffer *buffer = nullptr,
|
||||||
: Filename(name), IsPrimary(isPrimary), Buffer(buffer) {
|
StringRef outputFilename = StringRef())
|
||||||
|
: Filename(
|
||||||
|
convertBufferNameFromLLVM_getFileOrSTDIN_toSwiftConventions(name)),
|
||||||
|
IsPrimary(isPrimary), Buffer(buffer), OutputFilename(outputFilename) {
|
||||||
assert(!name.empty());
|
assert(!name.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +67,12 @@ public:
|
|||||||
StringRef filename) {
|
StringRef filename) {
|
||||||
return filename.equals("<stdin>") ? "-" : filename;
|
return filename.equals("<stdin>") ? "-" : filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string &outputFilename() const { return OutputFilename; }
|
||||||
|
|
||||||
|
void setOutputFilename(StringRef outputFilename) {
|
||||||
|
OutputFilename = outputFilename;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace swift
|
} // namespace swift
|
||||||
|
|||||||
@@ -456,5 +456,8 @@ def validate_tbd_against_ir_EQ: Joined<["-"], "validate-tbd-against-ir=">,
|
|||||||
// This is used to guard preemptive testing for the fix-it.
|
// This is used to guard preemptive testing for the fix-it.
|
||||||
def fix_string_substring_conversion: Flag<["-"], "fix-string-substring-conversion">,
|
def fix_string_substring_conversion: Flag<["-"], "fix-string-substring-conversion">,
|
||||||
HelpText<"Emit a fix-it to append '[]' to String expressions when converting to Substring.">;
|
HelpText<"Emit a fix-it to append '[]' to String expressions when converting to Substring.">;
|
||||||
|
|
||||||
|
def bypass_batch_mode_checks: Flag<["-"], "bypass-batch-mode-checks">,
|
||||||
|
HelpText<"Bypass checks for batch-mode errors.">;
|
||||||
|
|
||||||
} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]
|
} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//===--- ArgsToFrontendInputsConverter.cpp ----------------------*- C++ -*-===//
|
//===--- ArgsToFrontendInputsConverter.cpp --------------------------------===//
|
||||||
//
|
//
|
||||||
// This source file is part of the Swift.org open source project
|
// This source file is part of the Swift.org open source project
|
||||||
//
|
//
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "swift/Frontend/ArgsToFrontendInputsConverter.h"
|
#include "swift/Frontend/ArgsToFrontendInputsConverter.h"
|
||||||
|
|
||||||
#include "swift/AST/DiagnosticsFrontend.h"
|
#include "swift/AST/DiagnosticsFrontend.h"
|
||||||
|
#include "swift/Frontend/ArgsToFrontendOutputsConverter.h"
|
||||||
#include "swift/Frontend/FrontendOptions.h"
|
#include "swift/Frontend/FrontendOptions.h"
|
||||||
#include "swift/Option/Options.h"
|
#include "swift/Option/Options.h"
|
||||||
#include "swift/Parse/Lexer.h"
|
#include "swift/Parse/Lexer.h"
|
||||||
@@ -29,8 +30,9 @@ using namespace swift;
|
|||||||
using namespace llvm::opt;
|
using namespace llvm::opt;
|
||||||
|
|
||||||
ArgsToFrontendInputsConverter::ArgsToFrontendInputsConverter(
|
ArgsToFrontendInputsConverter::ArgsToFrontendInputsConverter(
|
||||||
DiagnosticEngine &diags, const ArgList &args, FrontendInputs &inputs)
|
DiagnosticEngine &diags, const ArgList &args,
|
||||||
: Diags(diags), Args(args), Inputs(inputs),
|
FrontendInputsAndOutputs &inputsAndOutputs)
|
||||||
|
: Diags(diags), Args(args), InputsAndOutputs(inputsAndOutputs),
|
||||||
FilelistPathArg(args.getLastArg(options::OPT_filelist)),
|
FilelistPathArg(args.getLastArg(options::OPT_filelist)),
|
||||||
PrimaryFilelistPathArg(args.getLastArg(options::OPT_primary_filelist)) {}
|
PrimaryFilelistPathArg(args.getLastArg(options::OPT_primary_filelist)) {}
|
||||||
|
|
||||||
@@ -45,7 +47,16 @@ bool ArgsToFrontendInputsConverter::convert() {
|
|||||||
return true;
|
return true;
|
||||||
std::set<StringRef> unusedPrimaryFiles =
|
std::set<StringRef> unusedPrimaryFiles =
|
||||||
createInputFilesConsumingPrimaries(*primaryFiles);
|
createInputFilesConsumingPrimaries(*primaryFiles);
|
||||||
return checkForMissingPrimaryFiles(unusedPrimaryFiles);
|
|
||||||
|
if (checkForMissingPrimaryFiles(unusedPrimaryFiles))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Must be set before iterating over inputs needing outputs.
|
||||||
|
InputsAndOutputs.setIsSingleThreadedWMO(isSingleThreadedWMO());
|
||||||
|
|
||||||
|
InputsAndOutputs.setBypassBatchModeChecks(
|
||||||
|
Args.hasArg(options::OPT_bypass_batch_mode_checks));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArgsToFrontendInputsConverter::enforceFilelistExclusion() {
|
bool ArgsToFrontendInputsConverter::enforceFilelistExclusion() {
|
||||||
@@ -131,7 +142,7 @@ ArgsToFrontendInputsConverter::createInputFilesConsumingPrimaries(
|
|||||||
std::set<StringRef> primaryFiles) {
|
std::set<StringRef> primaryFiles) {
|
||||||
for (auto &file : Files) {
|
for (auto &file : Files) {
|
||||||
bool isPrimary = primaryFiles.count(file) > 0;
|
bool isPrimary = primaryFiles.count(file) > 0;
|
||||||
Inputs.addInput(InputFile(file, isPrimary));
|
InputsAndOutputs.addInput(InputFile(file, isPrimary));
|
||||||
if (isPrimary)
|
if (isPrimary)
|
||||||
primaryFiles.erase(file);
|
primaryFiles.erase(file);
|
||||||
}
|
}
|
||||||
@@ -149,3 +160,11 @@ bool ArgsToFrontendInputsConverter::checkForMissingPrimaryFiles(
|
|||||||
}
|
}
|
||||||
return !primaryFiles.empty();
|
return !primaryFiles.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ArgsToFrontendInputsConverter::isSingleThreadedWMO() const {
|
||||||
|
Optional<std::vector<std::string>> userSuppliedNamesOrErr =
|
||||||
|
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(Args,
|
||||||
|
Diags);
|
||||||
|
return InputsAndOutputs.hasInputs() && !InputsAndOutputs.hasPrimaryInputs() &&
|
||||||
|
userSuppliedNamesOrErr && userSuppliedNamesOrErr->size() == 1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//===--- ArgsToFrontendOptionsConverter -------------------------*- C++ -*-===//
|
//===--- ArgsToFrontendOptionsConverter -----------------------------------===//
|
||||||
//
|
//
|
||||||
// This source file is part of the Swift.org open source project
|
// This source file is part of the Swift.org open source project
|
||||||
//
|
//
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "swift/AST/DiagnosticsFrontend.h"
|
#include "swift/AST/DiagnosticsFrontend.h"
|
||||||
#include "swift/Basic/Platform.h"
|
#include "swift/Basic/Platform.h"
|
||||||
#include "swift/Frontend/ArgsToFrontendInputsConverter.h"
|
#include "swift/Frontend/ArgsToFrontendInputsConverter.h"
|
||||||
|
#include "swift/Frontend/ArgsToFrontendOutputsConverter.h"
|
||||||
#include "swift/Frontend/Frontend.h"
|
#include "swift/Frontend/Frontend.h"
|
||||||
#include "swift/Option/Options.h"
|
#include "swift/Option/Options.h"
|
||||||
#include "swift/Option/SanitizerOptions.h"
|
#include "swift/Option/SanitizerOptions.h"
|
||||||
@@ -82,21 +83,24 @@ bool ArgsToFrontendOptionsConverter::convert() {
|
|||||||
// This can be enabled independently of the playground transform.
|
// This can be enabled independently of the playground transform.
|
||||||
Opts.PCMacro |= Args.hasArg(OPT_pc_macro);
|
Opts.PCMacro |= Args.hasArg(OPT_pc_macro);
|
||||||
|
|
||||||
computeHelpOptions();
|
|
||||||
if (ArgsToFrontendInputsConverter(Diags, Args, Opts.Inputs).convert())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
Opts.ParseStdlib |= Args.hasArg(OPT_parse_stdlib);
|
Opts.ParseStdlib |= Args.hasArg(OPT_parse_stdlib);
|
||||||
|
|
||||||
|
computeHelpOptions();
|
||||||
|
|
||||||
if (const Arg *A = Args.getLastArg(OPT_verify_generic_signatures)) {
|
if (const Arg *A = Args.getLastArg(OPT_verify_generic_signatures)) {
|
||||||
Opts.VerifyGenericSignaturesInModule = A->getValue();
|
Opts.VerifyGenericSignaturesInModule = A->getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
computeDumpScopeMapLocations();
|
computeDumpScopeMapLocations();
|
||||||
Opts.RequestedAction = determineRequestedAction();
|
|
||||||
|
if (ArgsToFrontendInputsConverter(Diags, Args, Opts.InputsAndOutputs)
|
||||||
|
.convert())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Opts.RequestedAction = determineRequestedAction(Args);
|
||||||
|
|
||||||
if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate &&
|
if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate &&
|
||||||
Opts.Inputs.hasPrimaryInputs()) {
|
Opts.InputsAndOutputs.hasPrimaryInputs()) {
|
||||||
Diags.diagnose(SourceLoc(), diag::error_immediate_mode_primary_file);
|
Diags.diagnose(SourceLoc(), diag::error_immediate_mode_primary_file);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -267,12 +271,12 @@ void ArgsToFrontendOptionsConverter::computeDumpScopeMapLocations() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FrontendOptions::ActionType
|
FrontendOptions::ActionType
|
||||||
ArgsToFrontendOptionsConverter::determineRequestedAction() const {
|
ArgsToFrontendOptionsConverter::determineRequestedAction(const ArgList &args) {
|
||||||
using namespace options;
|
using namespace options;
|
||||||
const Arg *A = Args.getLastArg(OPT_modes_Group);
|
const Arg *A = args.getLastArg(OPT_modes_Group);
|
||||||
if (!A) {
|
if (!A) {
|
||||||
// We don't have a mode, so determine a default.
|
// We don't have a mode, so determine a default.
|
||||||
if (Args.hasArg(OPT_emit_module, OPT_emit_module_path)) {
|
if (args.hasArg(OPT_emit_module, OPT_emit_module_path)) {
|
||||||
// We've been told to emit a module, but have no other mode indicators.
|
// We've been told to emit a module, but have no other mode indicators.
|
||||||
// As a result, put the frontend into EmitModuleOnly mode.
|
// As a result, put the frontend into EmitModuleOnly mode.
|
||||||
// (Setting up module output will be handled below.)
|
// (Setting up module output will be handled below.)
|
||||||
@@ -333,10 +337,10 @@ ArgsToFrontendOptionsConverter::determineRequestedAction() const {
|
|||||||
bool ArgsToFrontendOptionsConverter::setUpForSILOrLLVM() {
|
bool ArgsToFrontendOptionsConverter::setUpForSILOrLLVM() {
|
||||||
using namespace options;
|
using namespace options;
|
||||||
bool treatAsSIL =
|
bool treatAsSIL =
|
||||||
Args.hasArg(OPT_parse_sil) || Opts.Inputs.shouldTreatAsSIL();
|
Args.hasArg(OPT_parse_sil) || Opts.InputsAndOutputs.shouldTreatAsSIL();
|
||||||
bool treatAsLLVM = Opts.Inputs.shouldTreatAsLLVM();
|
bool treatAsLLVM = Opts.InputsAndOutputs.shouldTreatAsLLVM();
|
||||||
|
|
||||||
if (Opts.Inputs.verifyInputs(
|
if (Opts.InputsAndOutputs.verifyInputs(
|
||||||
Diags, treatAsSIL,
|
Diags, treatAsSIL,
|
||||||
Opts.RequestedAction == FrontendOptions::ActionType::REPL,
|
Opts.RequestedAction == FrontendOptions::ActionType::REPL,
|
||||||
Opts.RequestedAction == FrontendOptions::ActionType::NoneAction)) {
|
Opts.RequestedAction == FrontendOptions::ActionType::NoneAction)) {
|
||||||
@@ -344,7 +348,7 @@ bool ArgsToFrontendOptionsConverter::setUpForSILOrLLVM() {
|
|||||||
}
|
}
|
||||||
if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate) {
|
if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate) {
|
||||||
Opts.ImmediateArgv.push_back(
|
Opts.ImmediateArgv.push_back(
|
||||||
Opts.Inputs.getFilenameOfFirstInput()); // argv[0]
|
Opts.InputsAndOutputs.getFilenameOfFirstInput()); // argv[0]
|
||||||
if (const Arg *A = Args.getLastArg(OPT__DASH_DASH)) {
|
if (const Arg *A = Args.getLastArg(OPT__DASH_DASH)) {
|
||||||
for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
|
for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
|
||||||
Opts.ImmediateArgv.push_back(A->getValue(i));
|
Opts.ImmediateArgv.push_back(A->getValue(i));
|
||||||
@@ -405,151 +409,43 @@ bool ArgsToFrontendOptionsConverter::computeFallbackModuleName() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// In order to pass some tests, must leave ModuleName empty.
|
// In order to pass some tests, must leave ModuleName empty.
|
||||||
if (!Opts.Inputs.hasInputs()) {
|
if (!Opts.InputsAndOutputs.hasInputs()) {
|
||||||
Opts.ModuleName = StringRef();
|
Opts.ModuleName = StringRef();
|
||||||
// FIXME: This is a bug that should not happen, but does in tests.
|
// FIXME: This is a bug that should not happen, but does in tests.
|
||||||
// The compiler should bail out earlier, where "no frontend action was
|
// The compiler should bail out earlier, where "no frontend action was
|
||||||
// selected".
|
// selected".
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ArrayRef<std::string> outputFilenames =
|
Optional<std::vector<std::string>> outputFilenames =
|
||||||
getOutputFilenamesFromCommandLineOrFilelist();
|
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(Args,
|
||||||
|
Diags);
|
||||||
|
|
||||||
|
auto nameToStem =
|
||||||
|
outputFilenames && outputFilenames->size() == 1 &&
|
||||||
|
outputFilenames->front() != "-" &&
|
||||||
|
!llvm::sys::fs::is_directory(outputFilenames->front())
|
||||||
|
? outputFilenames->front()
|
||||||
|
: Opts.InputsAndOutputs.getFilenameOfFirstInput().str();
|
||||||
|
|
||||||
bool isOutputAUniqueOrdinaryFile =
|
|
||||||
outputFilenames.size() == 1 && outputFilenames[0] != "-" &&
|
|
||||||
!llvm::sys::fs::is_directory(outputFilenames[0]);
|
|
||||||
std::string nameToStem = isOutputAUniqueOrdinaryFile
|
|
||||||
? outputFilenames[0]
|
|
||||||
: Opts.Inputs.getFilenameOfFirstInput().str();
|
|
||||||
Opts.ModuleName = llvm::sys::path::stem(nameToStem);
|
Opts.ModuleName = llvm::sys::path::stem(nameToStem);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArgsToFrontendOptionsConverter::computeOutputFilenames() {
|
bool ArgsToFrontendOptionsConverter::computeOutputFilenames() {
|
||||||
assert(Opts.OutputFilenames.empty() &&
|
Optional<std::vector<std::string>> outs =
|
||||||
"Output filename should not be set at this point");
|
ArgsToFrontendOutputsConverter(Args, Opts.ModuleName,
|
||||||
if (!FrontendOptions::doesActionProduceOutput(Opts.RequestedAction)) {
|
Opts.InputsAndOutputs, Diags)
|
||||||
return false;
|
.convert();
|
||||||
}
|
if (!outs)
|
||||||
ArrayRef<std::string> outputFilenamesFromCommandLineOrFilelist =
|
|
||||||
getOutputFilenamesFromCommandLineOrFilelist();
|
|
||||||
|
|
||||||
if (outputFilenamesFromCommandLineOrFilelist.size() > 1) {
|
|
||||||
// WMO, threaded with N files (also someday batch mode).
|
|
||||||
Opts.OutputFilenames = outputFilenamesFromCommandLineOrFilelist;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outputFilenamesFromCommandLineOrFilelist.empty()) {
|
|
||||||
// When the Frontend is invoked without going through the driver
|
|
||||||
// (e.g. for testing), it is convenient to derive output filenames from
|
|
||||||
// input.
|
|
||||||
return deriveOutputFilenameFromInputFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
StringRef outputFilename = outputFilenamesFromCommandLineOrFilelist[0];
|
|
||||||
if (!llvm::sys::fs::is_directory(outputFilename)) {
|
|
||||||
// Could be -primary-file (1), or -wmo (non-threaded w/ N (input) files)
|
|
||||||
Opts.OutputFilenames = outputFilenamesFromCommandLineOrFilelist;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Only used for testing & when invoking frontend directly.
|
|
||||||
return deriveOutputFilenameForDirectory(outputFilename);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ArgsToFrontendOptionsConverter::deriveOutputFilenameFromInputFile() {
|
|
||||||
if (Opts.Inputs.isReadingFromStdin() ||
|
|
||||||
FrontendOptions::doesActionProduceTextualOutput(Opts.RequestedAction)) {
|
|
||||||
Opts.setOutputFilenameToStdout();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::string baseName = determineBaseNameOfOutput();
|
|
||||||
if (baseName.empty()) {
|
|
||||||
if (Opts.RequestedAction != FrontendOptions::ActionType::REPL &&
|
|
||||||
Opts.RequestedAction != FrontendOptions::ActionType::Immediate &&
|
|
||||||
Opts.RequestedAction != FrontendOptions::ActionType::NoneAction) {
|
|
||||||
Diags.diagnose(SourceLoc(), diag::error_no_output_filename_specified);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
deriveOutputFilenameFromParts("", baseName);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ArgsToFrontendOptionsConverter::deriveOutputFilenameForDirectory(
|
|
||||||
StringRef outputDir) {
|
|
||||||
|
|
||||||
std::string baseName = determineBaseNameOfOutput();
|
|
||||||
if (baseName.empty()) {
|
|
||||||
Diags.diagnose(SourceLoc(), diag::error_implicit_output_file_is_directory,
|
|
||||||
outputDir);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
if (FrontendOptions::doesActionProduceOutput(Opts.RequestedAction))
|
||||||
deriveOutputFilenameFromParts(outputDir, baseName);
|
Opts.InputsAndOutputs.setMainOutputs(*outs);
|
||||||
|
else
|
||||||
|
assert(outs->empty() &&
|
||||||
|
"cannot have main outputs for actions that don't produce outputs");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArgsToFrontendOptionsConverter::deriveOutputFilenameFromParts(
|
|
||||||
StringRef dir, StringRef base) {
|
|
||||||
assert(!base.empty());
|
|
||||||
llvm::SmallString<128> path(dir);
|
|
||||||
llvm::sys::path::append(path, base);
|
|
||||||
StringRef suffix = FrontendOptions::suffixForPrincipalOutputFileForAction(
|
|
||||||
Opts.RequestedAction);
|
|
||||||
llvm::sys::path::replace_extension(path, suffix);
|
|
||||||
Opts.OutputFilenames.push_back(path.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ArgsToFrontendOptionsConverter::determineBaseNameOfOutput() const {
|
|
||||||
std::string nameToStem;
|
|
||||||
if (Opts.Inputs.hasPrimaryInputs()) {
|
|
||||||
nameToStem = Opts.Inputs.getRequiredUniquePrimaryInput().file();
|
|
||||||
} else if (auto UserSpecifiedModuleName =
|
|
||||||
Args.getLastArg(options::OPT_module_name)) {
|
|
||||||
nameToStem = UserSpecifiedModuleName->getValue();
|
|
||||||
} else if (Opts.Inputs.hasSingleInput()) {
|
|
||||||
nameToStem = Opts.Inputs.getFilenameOfFirstInput();
|
|
||||||
} else
|
|
||||||
nameToStem = "";
|
|
||||||
|
|
||||||
return llvm::sys::path::stem(nameToStem).str();
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayRef<std::string>
|
|
||||||
ArgsToFrontendOptionsConverter::getOutputFilenamesFromCommandLineOrFilelist() {
|
|
||||||
if (cachedOutputFilenamesFromCommandLineOrFilelist) {
|
|
||||||
return *cachedOutputFilenamesFromCommandLineOrFilelist;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const Arg *A = Args.getLastArg(options::OPT_output_filelist)) {
|
|
||||||
assert(!Args.hasArg(options::OPT_o) &&
|
|
||||||
"don't use -o with -output-filelist");
|
|
||||||
cachedOutputFilenamesFromCommandLineOrFilelist.emplace(
|
|
||||||
readOutputFileList(A->getValue()));
|
|
||||||
} else {
|
|
||||||
cachedOutputFilenamesFromCommandLineOrFilelist.emplace(
|
|
||||||
Args.getAllArgValues(options::OPT_o));
|
|
||||||
}
|
|
||||||
return *cachedOutputFilenamesFromCommandLineOrFilelist;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Try to read an output file list file.
|
|
||||||
std::vector<std::string> ArgsToFrontendOptionsConverter::readOutputFileList(
|
|
||||||
const StringRef filelistPath) const {
|
|
||||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
|
|
||||||
llvm::MemoryBuffer::getFile(filelistPath);
|
|
||||||
if (!buffer) {
|
|
||||||
Diags.diagnose(SourceLoc(), diag::cannot_open_file, filelistPath,
|
|
||||||
buffer.getError().message());
|
|
||||||
}
|
|
||||||
std::vector<std::string> outputFiles;
|
|
||||||
for (StringRef line : make_range(llvm::line_iterator(*buffer.get()), {})) {
|
|
||||||
outputFiles.push_back(line.str());
|
|
||||||
}
|
|
||||||
return outputFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArgsToFrontendOptionsConverter::determineSupplementaryOutputFilenames() {
|
void ArgsToFrontendOptionsConverter::determineSupplementaryOutputFilenames() {
|
||||||
using namespace options;
|
using namespace options;
|
||||||
auto determineOutputFilename =
|
auto determineOutputFilename =
|
||||||
@@ -564,8 +460,9 @@ void ArgsToFrontendOptionsConverter::determineSupplementaryOutputFilenames() {
|
|||||||
if (!Args.hasArg(optWithoutPath))
|
if (!Args.hasArg(optWithoutPath))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (useMainOutput && !Opts.OutputFilenames.empty()) {
|
if (useMainOutput &&
|
||||||
output = Opts.getSingleOutputFilename();
|
!Opts.InputsAndOutputs.getSingleOutputFilename().empty()) {
|
||||||
|
output = Opts.InputsAndOutputs.getSingleOutputFilename();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,8 +543,8 @@ 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.Inputs.hasPrimaryInputs() && !Opts.ModuleOutputPath.empty();
|
!Opts.ModuleOutputPath.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void ArgsToFrontendOptionsConverter::computeImplicitImportModuleNames() {
|
void ArgsToFrontendOptionsConverter::computeImplicitImportModuleNames() {
|
||||||
|
|||||||
204
lib/Frontend/ArgsToFrontendOutputsConverter.cpp
Normal file
204
lib/Frontend/ArgsToFrontendOutputsConverter.cpp
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
//===--- ArgsToFrontendOutputsConverter.cpp -------------------------------===//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See https://swift.org/LICENSE.txt for license information
|
||||||
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "swift/Frontend/ArgsToFrontendOutputsConverter.h"
|
||||||
|
|
||||||
|
#include "swift/AST/DiagnosticsFrontend.h"
|
||||||
|
#include "swift/Basic/Platform.h"
|
||||||
|
#include "swift/Frontend/ArgsToFrontendInputsConverter.h"
|
||||||
|
#include "swift/Frontend/ArgsToFrontendOptionsConverter.h"
|
||||||
|
#include "swift/Frontend/Frontend.h"
|
||||||
|
#include "swift/Option/Options.h"
|
||||||
|
#include "swift/Option/SanitizerOptions.h"
|
||||||
|
#include "swift/Strings.h"
|
||||||
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
#include "llvm/ADT/Triple.h"
|
||||||
|
#include "llvm/Option/Arg.h"
|
||||||
|
#include "llvm/Option/ArgList.h"
|
||||||
|
#include "llvm/Option/Option.h"
|
||||||
|
#include "llvm/Support/FileSystem.h"
|
||||||
|
#include "llvm/Support/LineIterator.h"
|
||||||
|
#include "llvm/Support/Path.h"
|
||||||
|
|
||||||
|
using namespace swift;
|
||||||
|
using namespace llvm::opt;
|
||||||
|
|
||||||
|
Optional<std::vector<std::string>> ArgsToFrontendOutputsConverter::convert() {
|
||||||
|
const auto requestedAction =
|
||||||
|
ArgsToFrontendOptionsConverter::determineRequestedAction(Args);
|
||||||
|
|
||||||
|
if (!FrontendOptions::doesActionProduceOutput(requestedAction))
|
||||||
|
return std::vector<std::string>();
|
||||||
|
|
||||||
|
if (auto ofc = OutputFilesComputer::create(Args, Diags, InputsAndOutputs))
|
||||||
|
return ofc->computeOutputFiles();
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<std::vector<std::string>>
|
||||||
|
ArgsToFrontendOutputsConverter::readOutputFileList(const StringRef filelistPath,
|
||||||
|
DiagnosticEngine &diags) {
|
||||||
|
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
|
||||||
|
llvm::MemoryBuffer::getFile(filelistPath);
|
||||||
|
if (!buffer) {
|
||||||
|
diags.diagnose(SourceLoc(), diag::cannot_open_file, filelistPath,
|
||||||
|
buffer.getError().message());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
std::vector<std::string> outputFiles;
|
||||||
|
for (StringRef line : make_range(llvm::line_iterator(*buffer.get()), {})) {
|
||||||
|
outputFiles.push_back(line.str());
|
||||||
|
}
|
||||||
|
return outputFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<std::vector<std::string>>
|
||||||
|
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(
|
||||||
|
const ArgList &args, DiagnosticEngine &diags) {
|
||||||
|
if (const Arg *A = args.getLastArg(options::OPT_output_filelist)) {
|
||||||
|
assert(!args.hasArg(options::OPT_o) &&
|
||||||
|
"don't use -o with -output-filelist");
|
||||||
|
return ArgsToFrontendOutputsConverter::readOutputFileList(A->getValue(),
|
||||||
|
diags);
|
||||||
|
}
|
||||||
|
return args.getAllArgValues(options::OPT_o);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<OutputFilesComputer>
|
||||||
|
OutputFilesComputer::create(const llvm::opt::ArgList &args,
|
||||||
|
DiagnosticEngine &diags,
|
||||||
|
const FrontendInputsAndOutputs &inputsAndOutputs) {
|
||||||
|
Optional<std::vector<std::string>> outputArguments =
|
||||||
|
getOutputFilenamesFromCommandLineOrFilelist(args, diags);
|
||||||
|
if (!outputArguments)
|
||||||
|
return None;
|
||||||
|
const StringRef outputDirectoryArgument =
|
||||||
|
outputArguments->size() == 1 &&
|
||||||
|
llvm::sys::fs::is_directory(outputArguments->front())
|
||||||
|
? StringRef(outputArguments->front())
|
||||||
|
: StringRef();
|
||||||
|
ArrayRef<std::string> outputFileArguments =
|
||||||
|
outputDirectoryArgument.empty() ? ArrayRef<std::string>(*outputArguments)
|
||||||
|
: ArrayRef<std::string>();
|
||||||
|
const StringRef firstInput = inputsAndOutputs.hasSingleInput()
|
||||||
|
? inputsAndOutputs.getFilenameOfFirstInput()
|
||||||
|
: StringRef();
|
||||||
|
const FrontendOptions::ActionType requestedAction =
|
||||||
|
ArgsToFrontendOptionsConverter::determineRequestedAction(args);
|
||||||
|
|
||||||
|
if (!outputFileArguments.empty() &&
|
||||||
|
outputFileArguments.size() !=
|
||||||
|
inputsAndOutputs.countOfInputsProducingMainOutputs()) {
|
||||||
|
diags.diagnose(
|
||||||
|
SourceLoc(),
|
||||||
|
diag::error_if_any_output_files_are_specified_they_all_must_be);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OutputFilesComputer(
|
||||||
|
args, diags, inputsAndOutputs, std::move(outputFileArguments),
|
||||||
|
outputDirectoryArgument, firstInput, requestedAction,
|
||||||
|
args.getLastArg(options::OPT_module_name),
|
||||||
|
FrontendOptions::suffixForPrincipalOutputFileForAction(requestedAction),
|
||||||
|
FrontendOptions::doesActionProduceTextualOutput(requestedAction));
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputFilesComputer::OutputFilesComputer(
|
||||||
|
const llvm::opt::ArgList &args, DiagnosticEngine &diags,
|
||||||
|
const FrontendInputsAndOutputs &inputsAndOutputs,
|
||||||
|
std::vector<std::string> outputFileArguments,
|
||||||
|
const StringRef outputDirectoryArgument, const StringRef firstInput,
|
||||||
|
const FrontendOptions::ActionType requestedAction,
|
||||||
|
const llvm::opt::Arg *moduleNameArg, const StringRef suffix,
|
||||||
|
const bool hasTextualOutput)
|
||||||
|
: Args(args), Diags(diags), InputsAndOutputs(inputsAndOutputs),
|
||||||
|
OutputFileArguments(outputFileArguments),
|
||||||
|
OutputDirectoryArgument(outputDirectoryArgument), FirstInput(firstInput),
|
||||||
|
RequestedAction(requestedAction), ModuleNameArg(moduleNameArg),
|
||||||
|
Suffix(suffix), HasTextualOutput(hasTextualOutput) {}
|
||||||
|
|
||||||
|
Optional<std::vector<std::string>>
|
||||||
|
OutputFilesComputer::computeOutputFiles() const {
|
||||||
|
std::vector<std::string> outputFiles;
|
||||||
|
bool hadError = false;
|
||||||
|
unsigned i = 0;
|
||||||
|
InputsAndOutputs.forEachInputProducingAMainOutputFile(
|
||||||
|
[&](const InputFile &input) -> void {
|
||||||
|
|
||||||
|
StringRef outputArg = OutputFileArguments.empty()
|
||||||
|
? StringRef()
|
||||||
|
: StringRef(OutputFileArguments[i++]);
|
||||||
|
|
||||||
|
Optional<std::string> outputFile = computeOutputFile(outputArg, input);
|
||||||
|
if (!outputFile) {
|
||||||
|
hadError = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
outputFiles.push_back(*outputFile);
|
||||||
|
});
|
||||||
|
return hadError ? None : Optional<std::vector<std::string>>(outputFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<std::string>
|
||||||
|
OutputFilesComputer::computeOutputFile(StringRef outputArg,
|
||||||
|
const InputFile &input) const {
|
||||||
|
if (!OutputDirectoryArgument.empty())
|
||||||
|
return deriveOutputFileForDirectory(input);
|
||||||
|
|
||||||
|
if (!outputArg.empty())
|
||||||
|
return outputArg.str();
|
||||||
|
|
||||||
|
return deriveOutputFileFromInput(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<std::string>
|
||||||
|
OutputFilesComputer::deriveOutputFileFromInput(const InputFile &input) const {
|
||||||
|
if (input.file() == "-" || HasTextualOutput)
|
||||||
|
return std::string("-");
|
||||||
|
|
||||||
|
std::string baseName = determineBaseNameOfOutput(input);
|
||||||
|
if (baseName.empty()) {
|
||||||
|
// Assuming FrontendOptions::doesActionProduceOutput(RequestedAction)
|
||||||
|
Diags.diagnose(SourceLoc(), diag::error_no_output_filename_specified);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
return deriveOutputFileFromParts("", baseName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<std::string> OutputFilesComputer::deriveOutputFileForDirectory(
|
||||||
|
const InputFile &input) const {
|
||||||
|
std::string baseName = determineBaseNameOfOutput(input);
|
||||||
|
if (baseName.empty()) {
|
||||||
|
Diags.diagnose(SourceLoc(), diag::error_implicit_output_file_is_directory,
|
||||||
|
OutputDirectoryArgument);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
return deriveOutputFileFromParts(OutputDirectoryArgument, baseName);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
OutputFilesComputer::determineBaseNameOfOutput(const InputFile &input) const {
|
||||||
|
StringRef nameToStem =
|
||||||
|
input.isPrimary()
|
||||||
|
? input.file()
|
||||||
|
: ModuleNameArg ? ModuleNameArg->getValue() : FirstInput;
|
||||||
|
return llvm::sys::path::stem(nameToStem).str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
OutputFilesComputer::deriveOutputFileFromParts(StringRef dir,
|
||||||
|
StringRef base) const {
|
||||||
|
assert(!base.empty());
|
||||||
|
llvm::SmallString<128> path(dir);
|
||||||
|
llvm::sys::path::append(path, base);
|
||||||
|
llvm::sys::path::replace_extension(path, Suffix);
|
||||||
|
return path.str();
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
add_swift_library(swiftFrontend STATIC
|
add_swift_library(swiftFrontend STATIC
|
||||||
ArgsToFrontendInputsConverter.cpp
|
ArgsToFrontendInputsConverter.cpp
|
||||||
ArgsToFrontendOptionsConverter.cpp
|
ArgsToFrontendOptionsConverter.cpp
|
||||||
|
ArgsToFrontendOutputsConverter.cpp
|
||||||
CompilerInvocation.cpp
|
CompilerInvocation.cpp
|
||||||
DiagnosticVerifier.cpp
|
DiagnosticVerifier.cpp
|
||||||
Frontend.cpp
|
Frontend.cpp
|
||||||
FrontendInputs.cpp
|
FrontendInputsAndOutputs.cpp
|
||||||
FrontendOptions.cpp
|
FrontendOptions.cpp
|
||||||
PrintingDiagnosticConsumer.cpp
|
PrintingDiagnosticConsumer.cpp
|
||||||
SerializedDiagnosticConsumer.cpp
|
SerializedDiagnosticConsumer.cpp
|
||||||
|
|||||||
@@ -672,7 +672,7 @@ 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.getSingleOutputFilename();
|
StringRef 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())
|
||||||
@@ -818,12 +818,13 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
|
|||||||
if (!SILOpts.SILOutputFileNameForDebugging.empty()) {
|
if (!SILOpts.SILOutputFileNameForDebugging.empty()) {
|
||||||
Opts.MainInputFilename = SILOpts.SILOutputFileNameForDebugging;
|
Opts.MainInputFilename = SILOpts.SILOutputFileNameForDebugging;
|
||||||
} else if (const InputFile *input =
|
} else if (const InputFile *input =
|
||||||
FrontendOpts.Inputs.getUniquePrimaryInput()) {
|
FrontendOpts.InputsAndOutputs.getUniquePrimaryInput()) {
|
||||||
Opts.MainInputFilename = input->file();
|
Opts.MainInputFilename = input->file();
|
||||||
} else if (FrontendOpts.Inputs.hasSingleInput()) {
|
} else if (FrontendOpts.InputsAndOutputs.hasSingleInput()) {
|
||||||
Opts.MainInputFilename = FrontendOpts.Inputs.getFilenameOfFirstInput();
|
Opts.MainInputFilename =
|
||||||
|
FrontendOpts.InputsAndOutputs.getFilenameOfFirstInput();
|
||||||
}
|
}
|
||||||
Opts.OutputFilenames = FrontendOpts.OutputFilenames;
|
Opts.OutputFilenames = FrontendOpts.InputsAndOutputs.copyOutputFilenames();
|
||||||
Opts.ModuleName = FrontendOpts.ModuleName;
|
Opts.ModuleName = FrontendOpts.ModuleName;
|
||||||
|
|
||||||
if (Args.hasArg(OPT_use_jit))
|
if (Args.hasArg(OPT_use_jit))
|
||||||
@@ -1064,7 +1065,7 @@ CompilerInvocation::setUpInputForSILTool(
|
|||||||
|
|
||||||
// If it looks like we have an AST, set the source file kind to SIL and the
|
// If it looks like we have an AST, set the source file kind to SIL and the
|
||||||
// name of the module to the file's name.
|
// name of the module to the file's name.
|
||||||
getFrontendOptions().Inputs.addInput(
|
getFrontendOptions().InputsAndOutputs.addInput(
|
||||||
InputFile(inputFilename, bePrimary, fileBufOrErr.get().get()));
|
InputFile(inputFilename, bePrimary, fileBufOrErr.get().get()));
|
||||||
|
|
||||||
auto result = serialization::validateSerializedAST(
|
auto result = serialization::validateSerializedAST(
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ void CompilerInstance::createSILModule() {
|
|||||||
// Assume WMO if a -primary-file option was not provided.
|
// Assume WMO if a -primary-file option was not provided.
|
||||||
TheSILModule = SILModule::createEmptyModule(
|
TheSILModule = SILModule::createEmptyModule(
|
||||||
getMainModule(), Invocation.getSILOptions(),
|
getMainModule(), Invocation.getSILOptions(),
|
||||||
Invocation.getFrontendOptions().Inputs.isWholeModule());
|
Invocation.getFrontendOptions().InputsAndOutputs.isWholeModule());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompilerInstance::recordPrimaryInputBuffer(unsigned BufID) {
|
void CompilerInstance::recordPrimaryInputBuffer(unsigned BufID) {
|
||||||
@@ -182,7 +182,7 @@ bool CompilerInstance::setUpInputs() {
|
|||||||
const Optional<unsigned> codeCompletionBufferID = setUpCodeCompletionBuffer();
|
const Optional<unsigned> codeCompletionBufferID = setUpCodeCompletionBuffer();
|
||||||
|
|
||||||
for (const InputFile &input :
|
for (const InputFile &input :
|
||||||
Invocation.getFrontendOptions().Inputs.getAllInputs())
|
Invocation.getFrontendOptions().InputsAndOutputs.getAllInputs())
|
||||||
if (setUpForInput(input))
|
if (setUpForInput(input))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|||||||
@@ -1,176 +0,0 @@
|
|||||||
//===--- FrontendInputs.cpp -------------------------------------*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// This source file is part of the Swift.org open source project
|
|
||||||
//
|
|
||||||
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
|
|
||||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
||||||
//
|
|
||||||
// See https://swift.org/LICENSE.txt for license information
|
|
||||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "swift/Frontend/FrontendInputs.h"
|
|
||||||
|
|
||||||
#include "swift/AST/DiagnosticsFrontend.h"
|
|
||||||
#include "swift/Frontend/FrontendOptions.h"
|
|
||||||
#include "swift/AST/DiagnosticsFrontend.h"
|
|
||||||
#include "swift/Option/Options.h"
|
|
||||||
#include "swift/Parse/Lexer.h"
|
|
||||||
#include "swift/Strings.h"
|
|
||||||
#include "llvm/Option/Arg.h"
|
|
||||||
#include "llvm/Option/ArgList.h"
|
|
||||||
#include "llvm/Option/Option.h"
|
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
|
||||||
#include "llvm/Support/FileSystem.h"
|
|
||||||
#include "llvm/Support/LineIterator.h"
|
|
||||||
#include "llvm/Support/Path.h"
|
|
||||||
|
|
||||||
using namespace swift;
|
|
||||||
using namespace llvm::opt;
|
|
||||||
|
|
||||||
FrontendInputs::FrontendInputs(const FrontendInputs &other) {
|
|
||||||
for (InputFile input : other.AllInputs)
|
|
||||||
addInput(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
FrontendInputs &FrontendInputs::operator=(const FrontendInputs &other) {
|
|
||||||
clearInputs();
|
|
||||||
for (InputFile input : other.AllInputs)
|
|
||||||
addInput(input);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> FrontendInputs::getInputFilenames() const {
|
|
||||||
std::vector<std::string> filenames;
|
|
||||||
for (auto &input : AllInputs) {
|
|
||||||
filenames.push_back(input.file());
|
|
||||||
}
|
|
||||||
return filenames;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FrontendInputs::isReadingFromStdin() const {
|
|
||||||
return hasSingleInput() && getFilenameOfFirstInput() == "-";
|
|
||||||
}
|
|
||||||
|
|
||||||
void FrontendInputs::assertMustNotBeMoreThanOnePrimaryInput() const {
|
|
||||||
assert(primaryInputCount() < 2 &&
|
|
||||||
"have not implemented >1 primary input yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
const InputFile *FrontendInputs::getUniquePrimaryInput() const {
|
|
||||||
assertMustNotBeMoreThanOnePrimaryInput();
|
|
||||||
const auto b = PrimaryInputs.begin();
|
|
||||||
return b == PrimaryInputs.end() ? nullptr : &AllInputs[b->second];
|
|
||||||
}
|
|
||||||
|
|
||||||
const InputFile &FrontendInputs::getRequiredUniquePrimaryInput() const {
|
|
||||||
if (const auto *input = getUniquePrimaryInput())
|
|
||||||
return *input;
|
|
||||||
llvm_unreachable("No primary when one is required");
|
|
||||||
}
|
|
||||||
|
|
||||||
StringRef FrontendInputs::getNameOfUniquePrimaryInputFile() const {
|
|
||||||
const auto *input = getUniquePrimaryInput();
|
|
||||||
return input == nullptr ? StringRef() : input->file();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FrontendInputs::isInputPrimary(StringRef file) const {
|
|
||||||
auto iterator = PrimaryInputs.find(file);
|
|
||||||
return iterator != PrimaryInputs.end() &&
|
|
||||||
AllInputs[iterator->second].isPrimary();
|
|
||||||
}
|
|
||||||
|
|
||||||
StringRef FrontendInputs::getFilenameOfFirstInput() const {
|
|
||||||
assert(hasInputs());
|
|
||||||
const InputFile &inp = AllInputs[0];
|
|
||||||
StringRef f = inp.file();
|
|
||||||
assert(!f.empty());
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FrontendInputs::shouldTreatAsLLVM() const {
|
|
||||||
if (hasSingleInput()) {
|
|
||||||
StringRef Input(getFilenameOfFirstInput());
|
|
||||||
return llvm::sys::path::extension(Input).endswith(LLVM_BC_EXTENSION) ||
|
|
||||||
llvm::sys::path::extension(Input).endswith(LLVM_IR_EXTENSION);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FrontendInputs::shouldTreatAsSIL() const {
|
|
||||||
if (hasSingleInput()) {
|
|
||||||
// If we have exactly one input filename, and its extension is "sil",
|
|
||||||
// treat the input as SIL.
|
|
||||||
StringRef Input(getFilenameOfFirstInput());
|
|
||||||
return llvm::sys::path::extension(Input).endswith(SIL_EXTENSION);
|
|
||||||
}
|
|
||||||
// If we have one primary input and it's a filename with extension "sil",
|
|
||||||
// treat the input as SIL.
|
|
||||||
unsigned silPrimaryCount = numberOfPrimaryInputsEndingWith(SIL_EXTENSION);
|
|
||||||
if (silPrimaryCount == 0)
|
|
||||||
return false;
|
|
||||||
if (silPrimaryCount == primaryInputCount()) {
|
|
||||||
// Not clear what to do someday with multiple primaries
|
|
||||||
assertMustNotBeMoreThanOnePrimaryInput();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
llvm_unreachable("Either all primaries or none must end with .sil");
|
|
||||||
}
|
|
||||||
|
|
||||||
void FrontendInputs::addInput(const InputFile &input) {
|
|
||||||
if (!input.file().empty() && input.isPrimary())
|
|
||||||
PrimaryInputs.insert(std::make_pair(input.file(), AllInputs.size()));
|
|
||||||
AllInputs.push_back(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned
|
|
||||||
FrontendInputs::numberOfPrimaryInputsEndingWith(const char *extension) const {
|
|
||||||
return count_if(
|
|
||||||
PrimaryInputs, [&](const llvm::StringMapEntry<unsigned> &elem) -> bool {
|
|
||||||
StringRef filename = AllInputs[elem.second].file();
|
|
||||||
return llvm::sys::path::extension(filename).endswith(extension);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FrontendInputs::verifyInputs(DiagnosticEngine &diags, bool treatAsSIL,
|
|
||||||
bool isREPLRequested,
|
|
||||||
bool isNoneRequested) const {
|
|
||||||
if (isREPLRequested) {
|
|
||||||
if (hasInputs()) {
|
|
||||||
diags.diagnose(SourceLoc(), diag::error_repl_requires_no_input_files);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (treatAsSIL) {
|
|
||||||
if (isWholeModule()) {
|
|
||||||
if (inputCount() != 1) {
|
|
||||||
diags.diagnose(SourceLoc(), diag::error_mode_requires_one_input_file);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
assertMustNotBeMoreThanOnePrimaryInput();
|
|
||||||
// If we have the SIL as our primary input, we can waive the one file
|
|
||||||
// requirement as long as all the other inputs are SIBs.
|
|
||||||
if (!areAllNonPrimariesSIB()) {
|
|
||||||
diags.diagnose(SourceLoc(),
|
|
||||||
diag::error_mode_requires_one_sil_multi_sib);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!isNoneRequested && !hasInputs()) {
|
|
||||||
diags.diagnose(SourceLoc(), diag::error_mode_requires_an_input_file);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FrontendInputs::areAllNonPrimariesSIB() const {
|
|
||||||
for (const InputFile &input : AllInputs) {
|
|
||||||
if (input.isPrimary())
|
|
||||||
continue;
|
|
||||||
if (!llvm::sys::path::extension(input.file()).endswith(SIB_EXTENSION)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
346
lib/Frontend/FrontendInputsAndOutputs.cpp
Normal file
346
lib/Frontend/FrontendInputsAndOutputs.cpp
Normal file
@@ -0,0 +1,346 @@
|
|||||||
|
//===--- FrontendInputsAndOutputs.cpp -------------------------------------===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See https://swift.org/LICENSE.txt for license information
|
||||||
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "swift/Frontend/FrontendInputsAndOutputs.h"
|
||||||
|
|
||||||
|
#include "swift/AST/DiagnosticsFrontend.h"
|
||||||
|
#include "swift/Frontend/FrontendOptions.h"
|
||||||
|
#include "swift/Option/Options.h"
|
||||||
|
#include "swift/Parse/Lexer.h"
|
||||||
|
#include "swift/Strings.h"
|
||||||
|
#include "llvm/Option/Arg.h"
|
||||||
|
#include "llvm/Option/ArgList.h"
|
||||||
|
#include "llvm/Option/Option.h"
|
||||||
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
|
#include "llvm/Support/FileSystem.h"
|
||||||
|
#include "llvm/Support/LineIterator.h"
|
||||||
|
#include "llvm/Support/Path.h"
|
||||||
|
|
||||||
|
using namespace swift;
|
||||||
|
using namespace llvm::opt;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
FrontendInputsAndOutputs::FrontendInputsAndOutputs(
|
||||||
|
const FrontendInputsAndOutputs &other) {
|
||||||
|
for (InputFile input : other.AllInputs)
|
||||||
|
addInput(input);
|
||||||
|
IsSingleThreadedWMO = other.IsSingleThreadedWMO;
|
||||||
|
}
|
||||||
|
|
||||||
|
FrontendInputsAndOutputs &FrontendInputsAndOutputs::
|
||||||
|
operator=(const FrontendInputsAndOutputs &other) {
|
||||||
|
clearInputs();
|
||||||
|
for (InputFile input : other.AllInputs)
|
||||||
|
addInput(input);
|
||||||
|
IsSingleThreadedWMO = other.IsSingleThreadedWMO;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All inputs:
|
||||||
|
|
||||||
|
std::vector<std::string> FrontendInputsAndOutputs::getInputFilenames() const {
|
||||||
|
std::vector<std::string> filenames;
|
||||||
|
for (auto &input : AllInputs) {
|
||||||
|
filenames.push_back(input.file());
|
||||||
|
}
|
||||||
|
return filenames;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FrontendInputsAndOutputs::isReadingFromStdin() const {
|
||||||
|
return hasSingleInput() && getFilenameOfFirstInput() == "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef FrontendInputsAndOutputs::getFilenameOfFirstInput() const {
|
||||||
|
assert(hasInputs());
|
||||||
|
const InputFile &inp = AllInputs[0];
|
||||||
|
StringRef f = inp.file();
|
||||||
|
assert(!f.empty());
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendInputsAndOutputs::forEachInput(
|
||||||
|
llvm::function_ref<void(const InputFile &)> fn) const {
|
||||||
|
for (const InputFile &input : AllInputs)
|
||||||
|
fn(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Primaries:
|
||||||
|
|
||||||
|
const InputFile &FrontendInputsAndOutputs::firstPrimaryInput() const {
|
||||||
|
assert(!PrimaryInputs.empty());
|
||||||
|
for (const auto &f : AllInputs)
|
||||||
|
if (f.isPrimary())
|
||||||
|
return f;
|
||||||
|
llvm_unreachable("no first primary?!");
|
||||||
|
}
|
||||||
|
|
||||||
|
const InputFile &FrontendInputsAndOutputs::lastPrimaryInput() const {
|
||||||
|
assert(!PrimaryInputs.empty());
|
||||||
|
for (const auto &f : reversed(AllInputs))
|
||||||
|
if (f.isPrimary())
|
||||||
|
return f;
|
||||||
|
llvm_unreachable("no last primary?!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendInputsAndOutputs::forEachPrimaryInput(
|
||||||
|
llvm::function_ref<void(const InputFile &)> fn) const {
|
||||||
|
for (auto &f : AllInputs)
|
||||||
|
if (f.isPrimary())
|
||||||
|
fn(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendInputsAndOutputs::assertMustNotBeMoreThanOnePrimaryInput() const {
|
||||||
|
assert(primaryInputCount() < 2 &&
|
||||||
|
"have not implemented >1 primary input yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendInputsAndOutputs::
|
||||||
|
assertMustNotBeMoreThanOnePrimaryInputUnlessBatchModeChecksHaveBeenBypassed()
|
||||||
|
const {
|
||||||
|
if (!areBatchModeChecksBypassed())
|
||||||
|
assertMustNotBeMoreThanOnePrimaryInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
const InputFile *FrontendInputsAndOutputs::getUniquePrimaryInput() const {
|
||||||
|
assertMustNotBeMoreThanOnePrimaryInput();
|
||||||
|
const auto b = PrimaryInputs.begin();
|
||||||
|
return b == PrimaryInputs.end() ? nullptr : &AllInputs[b->second];
|
||||||
|
}
|
||||||
|
|
||||||
|
const InputFile &
|
||||||
|
FrontendInputsAndOutputs::getRequiredUniquePrimaryInput() const {
|
||||||
|
if (const auto *input = getUniquePrimaryInput())
|
||||||
|
return *input;
|
||||||
|
llvm_unreachable("No primary when one is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef FrontendInputsAndOutputs::getNameOfUniquePrimaryInputFile() const {
|
||||||
|
const auto *input = getUniquePrimaryInput();
|
||||||
|
return input == nullptr ? StringRef() : input->file();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FrontendInputsAndOutputs::getStatsFileMangledInputName() const {
|
||||||
|
// FIXME: "batch" should probably be some concatenation of all the primary
|
||||||
|
// input names, in order to keep the stats file names unique. (Or perhaps just
|
||||||
|
// the first primary?)
|
||||||
|
return isWholeModule()
|
||||||
|
? "all"
|
||||||
|
: primaryInputCount() == 1 ? firstPrimaryInput().file() : "batch";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FrontendInputsAndOutputs::isInputPrimary(StringRef file) const {
|
||||||
|
StringRef correctedFile =
|
||||||
|
InputFile::convertBufferNameFromLLVM_getFileOrSTDIN_toSwiftConventions(
|
||||||
|
file);
|
||||||
|
auto iterator = PrimaryInputs.find(correctedFile);
|
||||||
|
if (iterator == PrimaryInputs.end())
|
||||||
|
return false;
|
||||||
|
assert(AllInputs[iterator->second].isPrimary() &&
|
||||||
|
"PrimaryInputs should only hold primaries");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned FrontendInputsAndOutputs::numberOfPrimaryInputsEndingWith(
|
||||||
|
const char *extension) const {
|
||||||
|
return count_if(
|
||||||
|
PrimaryInputs, [&](const llvm::StringMapEntry<unsigned> &elem) -> bool {
|
||||||
|
StringRef filename = AllInputs[elem.second].file();
|
||||||
|
|
||||||
|
return llvm::sys::path::extension(filename).endswith(extension);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input queries
|
||||||
|
|
||||||
|
bool FrontendInputsAndOutputs::shouldTreatAsLLVM() const {
|
||||||
|
if (hasSingleInput()) {
|
||||||
|
StringRef Input(getFilenameOfFirstInput());
|
||||||
|
return llvm::sys::path::extension(Input).endswith(LLVM_BC_EXTENSION) ||
|
||||||
|
llvm::sys::path::extension(Input).endswith(LLVM_IR_EXTENSION);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FrontendInputsAndOutputs::shouldTreatAsSIL() const {
|
||||||
|
if (hasSingleInput()) {
|
||||||
|
// If we have exactly one input filename, and its extension is "sil",
|
||||||
|
// treat the input as SIL.
|
||||||
|
StringRef Input(getFilenameOfFirstInput());
|
||||||
|
return llvm::sys::path::extension(Input).endswith(SIL_EXTENSION);
|
||||||
|
}
|
||||||
|
// If we have one primary input and it's a filename with extension "sil",
|
||||||
|
// treat the input as SIL.
|
||||||
|
unsigned silPrimaryCount = numberOfPrimaryInputsEndingWith(SIL_EXTENSION);
|
||||||
|
if (silPrimaryCount == 0)
|
||||||
|
return false;
|
||||||
|
if (silPrimaryCount == primaryInputCount()) {
|
||||||
|
// Not clear what to do someday with multiple primaries
|
||||||
|
assertMustNotBeMoreThanOnePrimaryInput();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
llvm_unreachable("Either all primaries or none must end with .sil");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FrontendInputsAndOutputs::areAllNonPrimariesSIB() const {
|
||||||
|
for (const InputFile &input : AllInputs) {
|
||||||
|
if (input.isPrimary())
|
||||||
|
continue;
|
||||||
|
if (!llvm::sys::path::extension(input.file()).endswith(SIB_EXTENSION)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FrontendInputsAndOutputs::verifyInputs(DiagnosticEngine &diags,
|
||||||
|
bool treatAsSIL,
|
||||||
|
bool isREPLRequested,
|
||||||
|
bool isNoneRequested) const {
|
||||||
|
if (isREPLRequested) {
|
||||||
|
if (hasInputs()) {
|
||||||
|
diags.diagnose(SourceLoc(), diag::error_repl_requires_no_input_files);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (treatAsSIL) {
|
||||||
|
if (isWholeModule()) {
|
||||||
|
if (inputCount() != 1) {
|
||||||
|
diags.diagnose(SourceLoc(), diag::error_mode_requires_one_input_file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assertMustNotBeMoreThanOnePrimaryInput();
|
||||||
|
// If we have the SIL as our primary input, we can waive the one file
|
||||||
|
// requirement as long as all the other inputs are SIBs.
|
||||||
|
if (!areAllNonPrimariesSIB()) {
|
||||||
|
diags.diagnose(SourceLoc(),
|
||||||
|
diag::error_mode_requires_one_sil_multi_sib);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!isNoneRequested && !hasInputs()) {
|
||||||
|
diags.diagnose(SourceLoc(), diag::error_mode_requires_an_input_file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Changing inputs
|
||||||
|
|
||||||
|
void FrontendInputsAndOutputs::clearInputs() {
|
||||||
|
AllInputs.clear();
|
||||||
|
PrimaryInputs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendInputsAndOutputs::addInput(const InputFile &input) {
|
||||||
|
if (!input.file().empty() && input.isPrimary())
|
||||||
|
PrimaryInputs.insert(std::make_pair(input.file(), AllInputs.size()));
|
||||||
|
AllInputs.push_back(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendInputsAndOutputs::addInputFile(StringRef file,
|
||||||
|
llvm::MemoryBuffer *buffer) {
|
||||||
|
addInput(InputFile(file, false, buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendInputsAndOutputs::addPrimaryInputFile(StringRef file,
|
||||||
|
llvm::MemoryBuffer *buffer) {
|
||||||
|
addInput(InputFile(file, true, buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outputs
|
||||||
|
|
||||||
|
unsigned FrontendInputsAndOutputs::countOfInputsProducingMainOutputs() const {
|
||||||
|
return isSingleThreadedWMO()
|
||||||
|
? 1
|
||||||
|
: hasPrimaryInputs() ? primaryInputCount() : inputCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
const InputFile &FrontendInputsAndOutputs::firstInputProducingOutput() const {
|
||||||
|
return isSingleThreadedWMO()
|
||||||
|
? firstInput()
|
||||||
|
: hasPrimaryInputs() ? firstPrimaryInput() : firstInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
const InputFile &FrontendInputsAndOutputs::lastInputProducingOutput() const {
|
||||||
|
return isSingleThreadedWMO()
|
||||||
|
? firstInput()
|
||||||
|
: hasPrimaryInputs() ? lastPrimaryInput() : lastInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendInputsAndOutputs::forEachInputProducingAMainOutputFile(
|
||||||
|
llvm::function_ref<void(const InputFile &)> fn) const {
|
||||||
|
isSingleThreadedWMO()
|
||||||
|
? fn(firstInput())
|
||||||
|
: hasPrimaryInputs() ? forEachPrimaryInput(fn) : forEachInput(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendInputsAndOutputs::setMainOutputs(
|
||||||
|
ArrayRef<std::string> outputFiles) {
|
||||||
|
assert(countOfInputsProducingMainOutputs() == outputFiles.size());
|
||||||
|
if (hasPrimaryInputs()) {
|
||||||
|
unsigned i = 0;
|
||||||
|
for (auto index : indices(AllInputs)) {
|
||||||
|
InputFile &f = AllInputs[index];
|
||||||
|
if (f.isPrimary())
|
||||||
|
f.setOutputFilename(outputFiles[i++]);
|
||||||
|
}
|
||||||
|
} else if (isSingleThreadedWMO()) {
|
||||||
|
AllInputs[0].setOutputFilename(outputFiles[0]);
|
||||||
|
} else {
|
||||||
|
for (auto i : indices(AllInputs))
|
||||||
|
AllInputs[i].setOutputFilename(outputFiles[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> FrontendInputsAndOutputs::copyOutputFilenames() const {
|
||||||
|
std::vector<std::string> outputs;
|
||||||
|
forEachInputProducingAMainOutputFile([&](const InputFile &input) -> void {
|
||||||
|
outputs.push_back(input.outputFilename());
|
||||||
|
});
|
||||||
|
return outputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendInputsAndOutputs::forEachOutputFilename(
|
||||||
|
llvm::function_ref<void(const std::string &)> fn) const {
|
||||||
|
forEachInputProducingAMainOutputFile(
|
||||||
|
[&](const InputFile &input) -> void { fn(input.outputFilename()); });
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef FrontendInputsAndOutputs::getSingleOutputFilename() const {
|
||||||
|
assertMustNotBeMoreThanOnePrimaryInputUnlessBatchModeChecksHaveBeenBypassed();
|
||||||
|
return hasInputs() ? StringRef(lastInputProducingOutput().outputFilename())
|
||||||
|
: StringRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FrontendInputsAndOutputs::isOutputFilenameStdout() const {
|
||||||
|
return getSingleOutputFilename() == "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FrontendInputsAndOutputs::isOutputFileDirectory() const {
|
||||||
|
return hasNamedOutputFile() &&
|
||||||
|
llvm::sys::fs::is_directory(getSingleOutputFilename());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FrontendInputsAndOutputs::hasNamedOutputFile() const {
|
||||||
|
return hasInputs() && !isOutputFilenameStdout();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supplementary outputs
|
||||||
|
|
||||||
|
void FrontendInputsAndOutputs::forEachInputProducingSupplementaryOutput(
|
||||||
|
llvm::function_ref<void(const InputFile &)> fn) const {
|
||||||
|
if (hasPrimaryInputs())
|
||||||
|
forEachPrimaryInput(fn);
|
||||||
|
else
|
||||||
|
fn(firstInput());
|
||||||
|
}
|
||||||
@@ -95,12 +95,13 @@ bool FrontendOptions::isActionImmediate(ActionType action) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FrontendOptions::forAllOutputPaths(
|
void FrontendOptions::forAllOutputPaths(
|
||||||
std::function<void(const std::string &)> fn) const {
|
const InputFile &input, std::function<void(const std::string &)> fn) const {
|
||||||
if (RequestedAction != FrontendOptions::ActionType::EmitModuleOnly &&
|
if (RequestedAction != FrontendOptions::ActionType::EmitModuleOnly &&
|
||||||
RequestedAction != FrontendOptions::ActionType::MergeModules) {
|
RequestedAction != FrontendOptions::ActionType::MergeModules) {
|
||||||
for (const std::string &OutputFileName : OutputFilenames) {
|
if (InputsAndOutputs.isWholeModule())
|
||||||
fn(OutputFileName);
|
InputsAndOutputs.forEachOutputFilename(fn);
|
||||||
}
|
else
|
||||||
|
fn(input.outputFilename());
|
||||||
}
|
}
|
||||||
const std::string *outputs[] = {
|
const std::string *outputs[] = {
|
||||||
&ModuleOutputPath,
|
&ModuleOutputPath,
|
||||||
@@ -115,23 +116,18 @@ void FrontendOptions::forAllOutputPaths(
|
|||||||
|
|
||||||
|
|
||||||
StringRef FrontendOptions::originalPath() const {
|
StringRef FrontendOptions::originalPath() const {
|
||||||
if (hasNamedOutputFile())
|
if (InputsAndOutputs.hasNamedOutputFile())
|
||||||
// Put the serialized diagnostics file next to the output file.
|
// Put the serialized diagnostics file next to the output file.
|
||||||
return getSingleOutputFilename();
|
return InputsAndOutputs.getSingleOutputFilename();
|
||||||
|
|
||||||
// If we have a primary input, so use that as the basis for the name of the
|
// 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
|
// serialized diagnostics file, otherwise fall back on the
|
||||||
// module name.
|
// module name.
|
||||||
const auto input = Inputs.getUniquePrimaryInput();
|
const auto input = InputsAndOutputs.getUniquePrimaryInput();
|
||||||
return input ? llvm::sys::path::filename(input->file())
|
return input ? llvm::sys::path::filename(input->file())
|
||||||
: StringRef(ModuleName);
|
: StringRef(ModuleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FrontendOptions::isOutputFileDirectory() const {
|
|
||||||
return hasNamedOutputFile() &&
|
|
||||||
llvm::sys::fs::is_directory(getSingleOutputFilename());
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
FrontendOptions::suffixForPrincipalOutputFileForAction(ActionType action) {
|
FrontendOptions::suffixForPrincipalOutputFileForAction(ActionType action) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
|||||||
@@ -101,7 +101,8 @@ 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 emitMakeDependencies(DiagnosticEngine &diags,
|
||||||
DependencyTracker &depTracker,
|
DependencyTracker &depTracker,
|
||||||
const FrontendOptions &opts) {
|
const FrontendOptions &opts,
|
||||||
|
const InputFile &input) {
|
||||||
std::error_code EC;
|
std::error_code EC;
|
||||||
llvm::raw_fd_ostream out(opts.DependenciesFilePath, EC,
|
llvm::raw_fd_ostream out(opts.DependenciesFilePath, EC,
|
||||||
llvm::sys::fs::F_None);
|
llvm::sys::fs::F_None);
|
||||||
@@ -135,12 +136,12 @@ static bool emitMakeDependencies(DiagnosticEngine &diags,
|
|||||||
|
|
||||||
// FIXME: Xcode can't currently handle multiple targets in a single
|
// FIXME: Xcode can't currently handle multiple targets in a single
|
||||||
// dependency line.
|
// dependency line.
|
||||||
opts.forAllOutputPaths([&](StringRef targetName) {
|
opts.forAllOutputPaths(input, [&](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!
|
||||||
for (auto const &path :
|
for (auto const &path :
|
||||||
reversePathSortedFilenames(opts.Inputs.getInputFilenames()))
|
reversePathSortedFilenames(opts.InputsAndOutputs.getInputFilenames()))
|
||||||
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 :
|
||||||
@@ -152,6 +153,17 @@ static bool emitMakeDependencies(DiagnosticEngine &diags,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool emitMakeDependencies(DiagnosticEngine &diags,
|
||||||
|
DependencyTracker &depTracker,
|
||||||
|
const FrontendOptions &opts) {
|
||||||
|
bool hadError = false;
|
||||||
|
opts.InputsAndOutputs.forEachInputProducingSupplementaryOutput(
|
||||||
|
[&](const InputFile &f) -> void {
|
||||||
|
hadError = emitMakeDependencies(diags, depTracker, opts, f) || hadError;
|
||||||
|
});
|
||||||
|
return hadError;
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct LoadedModuleTraceFormat {
|
struct LoadedModuleTraceFormat {
|
||||||
std::string Name;
|
std::string Name;
|
||||||
@@ -548,15 +560,17 @@ static bool performCompile(CompilerInstance &Instance,
|
|||||||
auto &PCHOutDir = ImporterOpts.PrecompiledHeaderOutputDir;
|
auto &PCHOutDir = ImporterOpts.PrecompiledHeaderOutputDir;
|
||||||
if (!PCHOutDir.empty()) {
|
if (!PCHOutDir.empty()) {
|
||||||
ImporterOpts.BridgingHeader =
|
ImporterOpts.BridgingHeader =
|
||||||
Invocation.getFrontendOptions().Inputs.getFilenameOfFirstInput();
|
Invocation.getFrontendOptions()
|
||||||
|
.InputsAndOutputs.getFilenameOfFirstInput();
|
||||||
// Create or validate a persistent PCH.
|
// Create or validate a persistent PCH.
|
||||||
auto SwiftPCHHash = Invocation.getPCHHash();
|
auto SwiftPCHHash = Invocation.getPCHHash();
|
||||||
auto PCH = clangImporter->getOrCreatePCH(ImporterOpts, SwiftPCHHash);
|
auto PCH = clangImporter->getOrCreatePCH(ImporterOpts, SwiftPCHHash);
|
||||||
return !PCH.hasValue();
|
return !PCH.hasValue();
|
||||||
}
|
}
|
||||||
return clangImporter->emitBridgingPCH(
|
return clangImporter->emitBridgingPCH(
|
||||||
Invocation.getFrontendOptions().Inputs.getFilenameOfFirstInput(),
|
Invocation.getFrontendOptions()
|
||||||
opts.getSingleOutputFilename());
|
.InputsAndOutputs.getFilenameOfFirstInput(),
|
||||||
|
opts.InputsAndOutputs.getSingleOutputFilename());
|
||||||
}
|
}
|
||||||
|
|
||||||
IRGenOptions &IRGenOpts = Invocation.getIRGenOptions();
|
IRGenOptions &IRGenOpts = Invocation.getIRGenOptions();
|
||||||
@@ -566,15 +580,17 @@ static bool performCompile(CompilerInstance &Instance,
|
|||||||
auto &LLVMContext = getGlobalLLVMContext();
|
auto &LLVMContext = getGlobalLLVMContext();
|
||||||
|
|
||||||
// Load in bitcode file.
|
// Load in bitcode file.
|
||||||
assert(Invocation.getFrontendOptions().Inputs.hasSingleInput() &&
|
assert(Invocation.getFrontendOptions().InputsAndOutputs.hasSingleInput() &&
|
||||||
"We expect a single input for bitcode input!");
|
"We expect a single input for bitcode input!");
|
||||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
|
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
|
||||||
llvm::MemoryBuffer::getFileOrSTDIN(
|
llvm::MemoryBuffer::getFileOrSTDIN(
|
||||||
Invocation.getFrontendOptions().Inputs.getFilenameOfFirstInput());
|
Invocation.getFrontendOptions()
|
||||||
|
.InputsAndOutputs.getFilenameOfFirstInput());
|
||||||
if (!FileBufOrErr) {
|
if (!FileBufOrErr) {
|
||||||
Instance.getASTContext().Diags.diagnose(
|
Instance.getASTContext().Diags.diagnose(
|
||||||
SourceLoc(), diag::error_open_input_file,
|
SourceLoc(), diag::error_open_input_file,
|
||||||
Invocation.getFrontendOptions().Inputs.getFilenameOfFirstInput(),
|
Invocation.getFrontendOptions()
|
||||||
|
.InputsAndOutputs.getFilenameOfFirstInput(),
|
||||||
FileBufOrErr.getError().message());
|
FileBufOrErr.getError().message());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -589,7 +605,8 @@ static bool performCompile(CompilerInstance &Instance,
|
|||||||
// if available.
|
// if available.
|
||||||
Instance.getASTContext().Diags.diagnose(
|
Instance.getASTContext().Diags.diagnose(
|
||||||
SourceLoc(), diag::error_parse_input_file,
|
SourceLoc(), diag::error_parse_input_file,
|
||||||
Invocation.getFrontendOptions().Inputs.getFilenameOfFirstInput(),
|
Invocation.getFrontendOptions()
|
||||||
|
.InputsAndOutputs.getFilenameOfFirstInput(),
|
||||||
Err.getMessage());
|
Err.getMessage());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -719,7 +736,7 @@ static bool performCompile(CompilerInstance &Instance,
|
|||||||
SF->dumpInterfaceHash(llvm::errs());
|
SF->dumpInterfaceHash(llvm::errs());
|
||||||
else if (Action == FrontendOptions::ActionType::EmitSyntax) {
|
else if (Action == FrontendOptions::ActionType::EmitSyntax) {
|
||||||
emitSyntax(SF, Invocation.getLangOptions(), Instance.getSourceMgr(),
|
emitSyntax(SF, Invocation.getLangOptions(), Instance.getSourceMgr(),
|
||||||
opts.getSingleOutputFilename());
|
opts.InputsAndOutputs.getSingleOutputFilename());
|
||||||
} else
|
} else
|
||||||
SF->dump();
|
SF->dump();
|
||||||
return Context.hadError();
|
return Context.hadError();
|
||||||
@@ -806,16 +823,14 @@ static bool performCompile(CompilerInstance &Instance,
|
|||||||
auto SASTF = dyn_cast<SerializedASTFile>(File);
|
auto SASTF = dyn_cast<SerializedASTFile>(File);
|
||||||
return SASTF && SASTF->isSIB();
|
return SASTF && SASTF->isSIB();
|
||||||
};
|
};
|
||||||
if (opts.Inputs.hasPrimaryInputs()) {
|
if (opts.InputsAndOutputs.hasPrimaryInputs()) {
|
||||||
if (Instance.getPrimarySourceFiles().empty()) {
|
if (Instance.getPrimarySourceFiles().empty()) {
|
||||||
// If we have primary inputs but no primary _source files_, we might
|
// If we have primary inputs but no primary _source files_, we might
|
||||||
// have a primary serialized input.
|
// have a primary serialized input.
|
||||||
for (FileUnit *fileUnit : mod->getFiles()) {
|
for (FileUnit *fileUnit : mod->getFiles()) {
|
||||||
if (auto SASTF = dyn_cast<SerializedASTFile>(fileUnit)) {
|
if (auto SASTF = dyn_cast<SerializedASTFile>(fileUnit)) {
|
||||||
if (Invocation.getFrontendOptions().Inputs.isInputPrimary(
|
if (Invocation.getFrontendOptions().InputsAndOutputs.isInputPrimary(
|
||||||
InputFile::
|
SASTF->getFilename())) {
|
||||||
convertBufferNameFromLLVM_getFileOrSTDIN_toSwiftConventions(
|
|
||||||
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);
|
||||||
PSGIs.push_back(
|
PSGIs.push_back(
|
||||||
@@ -887,7 +902,8 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
|
|||||||
if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll)
|
if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll)
|
||||||
performSILLinking(SM.get(), true);
|
performSILLinking(SM.get(), true);
|
||||||
return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL,
|
return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL,
|
||||||
opts.getSingleOutputFilename(), opts.EmitSortedSIL);
|
opts.InputsAndOutputs.getSingleOutputFilename(),
|
||||||
|
opts.EmitSortedSIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Action == FrontendOptions::ActionType::EmitSIBGen) {
|
if (Action == FrontendOptions::ActionType::EmitSIBGen) {
|
||||||
@@ -1065,7 +1081,8 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
|
|||||||
// We've been told to write canonical SIL, so write it now.
|
// We've been told to write canonical SIL, so write it now.
|
||||||
if (Action == FrontendOptions::ActionType::EmitSIL) {
|
if (Action == FrontendOptions::ActionType::EmitSIL) {
|
||||||
return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL,
|
return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL,
|
||||||
opts.getSingleOutputFilename(), opts.EmitSortedSIL);
|
opts.InputsAndOutputs.getSingleOutputFilename(),
|
||||||
|
opts.EmitSortedSIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(Action >= FrontendOptions::ActionType::Immediate &&
|
assert(Action >= FrontendOptions::ActionType::Immediate &&
|
||||||
@@ -1109,12 +1126,12 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
|
|||||||
IRModule = performIRGeneration(IRGenOpts,
|
IRModule = performIRGeneration(IRGenOpts,
|
||||||
*MSF.get<SourceFile*>(),
|
*MSF.get<SourceFile*>(),
|
||||||
std::move(SM),
|
std::move(SM),
|
||||||
opts.getSingleOutputFilename(), LLVMContext,
|
opts.InputsAndOutputs.getSingleOutputFilename(), LLVMContext,
|
||||||
0, &HashGlobal);
|
0, &HashGlobal);
|
||||||
} else {
|
} else {
|
||||||
IRModule = performIRGeneration(IRGenOpts, MSF.get<ModuleDecl*>(),
|
IRModule = performIRGeneration(IRGenOpts, MSF.get<ModuleDecl*>(),
|
||||||
std::move(SM),
|
std::move(SM),
|
||||||
opts.getSingleOutputFilename(), LLVMContext,
|
opts.InputsAndOutputs.getSingleOutputFilename(), LLVMContext,
|
||||||
&HashGlobal);
|
&HashGlobal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1178,8 +1195,10 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
|
|||||||
|
|
||||||
// Now that we have a single IR Module, hand it over to performLLVM.
|
// Now that we have a single IR Module, hand it over to performLLVM.
|
||||||
return performLLVM(IRGenOpts, &Instance.getDiags(), nullptr, HashGlobal,
|
return performLLVM(IRGenOpts, &Instance.getDiags(), nullptr, HashGlobal,
|
||||||
IRModule.get(), TargetMachine.get(), EffectiveLanguageVersion,
|
IRModule.get(), TargetMachine.get(),
|
||||||
opts.getSingleOutputFilename(), Stats) || HadError;
|
EffectiveLanguageVersion,
|
||||||
|
opts.InputsAndOutputs.getSingleOutputFilename(), Stats) ||
|
||||||
|
HadError;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool emitIndexData(SourceFile *PrimarySourceFile,
|
static bool emitIndexData(SourceFile *PrimarySourceFile,
|
||||||
@@ -1204,18 +1223,17 @@ static bool emitIndexData(SourceFile *PrimarySourceFile,
|
|||||||
|
|
||||||
if (PrimarySourceFile) {
|
if (PrimarySourceFile) {
|
||||||
if (index::indexAndRecord(
|
if (index::indexAndRecord(
|
||||||
PrimarySourceFile, opts.getSingleOutputFilename(),
|
PrimarySourceFile, opts.InputsAndOutputs.getSingleOutputFilename(),
|
||||||
opts.IndexStorePath, opts.IndexSystemModules,
|
opts.IndexStorePath, opts.IndexSystemModules, isDebugCompilation,
|
||||||
isDebugCompilation, Invocation.getTargetTriple(),
|
Invocation.getTargetTriple(), *Instance.getDependencyTracker())) {
|
||||||
*Instance.getDependencyTracker())) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
StringRef moduleToken = opts.ModuleOutputPath;
|
StringRef moduleToken = opts.ModuleOutputPath;
|
||||||
if (moduleToken.empty())
|
if (moduleToken.empty())
|
||||||
moduleToken = opts.getSingleOutputFilename();
|
moduleToken = opts.InputsAndOutputs.getSingleOutputFilename();
|
||||||
|
|
||||||
if (index::indexAndRecord(Instance.getMainModule(), opts.OutputFilenames,
|
if (index::indexAndRecord(Instance.getMainModule(), opts.InputsAndOutputs.copyOutputFilenames(),
|
||||||
moduleToken, opts.IndexStorePath,
|
moduleToken, opts.IndexStorePath,
|
||||||
opts.IndexSystemModules,
|
opts.IndexSystemModules,
|
||||||
isDebugCompilation, Invocation.getTargetTriple(),
|
isDebugCompilation, Invocation.getTargetTriple(),
|
||||||
@@ -1301,6 +1319,36 @@ silOptModeArgStr(OptimizationMode mode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<UnifiedStatsReporter>
|
||||||
|
computeStatsReporter(const CompilerInvocation &Invocation, CompilerInstance *Instance) {
|
||||||
|
const std::string &StatsOutputDir =
|
||||||
|
Invocation.getFrontendOptions().StatsOutputDir;
|
||||||
|
std::unique_ptr<UnifiedStatsReporter> StatsReporter;
|
||||||
|
if (StatsOutputDir.empty())
|
||||||
|
return std::unique_ptr<UnifiedStatsReporter>();
|
||||||
|
|
||||||
|
auto &FEOpts = Invocation.getFrontendOptions();
|
||||||
|
auto &LangOpts = Invocation.getLangOptions();
|
||||||
|
auto &SILOpts = Invocation.getSILOptions();
|
||||||
|
std::string InputName =
|
||||||
|
FEOpts.InputsAndOutputs.getStatsFileMangledInputName();
|
||||||
|
StringRef OptType = silOptModeArgStr(SILOpts.OptMode);
|
||||||
|
StringRef OutFile =
|
||||||
|
FEOpts.InputsAndOutputs.lastInputProducingOutput().outputFilename();
|
||||||
|
StringRef OutputType = llvm::sys::path::extension(OutFile);
|
||||||
|
std::string TripleName = LangOpts.Target.normalize();
|
||||||
|
auto Trace = Invocation.getFrontendOptions().TraceStats;
|
||||||
|
SourceManager *SM = &Instance->getSourceMgr();
|
||||||
|
clang::SourceManager *CSM = nullptr;
|
||||||
|
if (auto *clangImporter = static_cast<ClangImporter *>(
|
||||||
|
Instance->getASTContext().getClangModuleLoader())) {
|
||||||
|
CSM = &clangImporter->getClangASTContext().getSourceManager();
|
||||||
|
}
|
||||||
|
return llvm::make_unique<UnifiedStatsReporter>(
|
||||||
|
"swift-frontend", FEOpts.ModuleName, InputName, TripleName, OutputType,
|
||||||
|
OptType, StatsOutputDir, SM, CSM, Trace);
|
||||||
|
}
|
||||||
|
|
||||||
int swift::performFrontend(ArrayRef<const char *> Args,
|
int swift::performFrontend(ArrayRef<const char *> Args,
|
||||||
const char *Argv0, void *MainAddr,
|
const char *Argv0, void *MainAddr,
|
||||||
FrontendObserver *observer) {
|
FrontendObserver *observer) {
|
||||||
@@ -1465,35 +1513,9 @@ int swift::performFrontend(ArrayRef<const char *> Args,
|
|||||||
return finishDiagProcessing(1);
|
return finishDiagProcessing(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &StatsOutputDir =
|
std::unique_ptr<UnifiedStatsReporter> StatsReporter =
|
||||||
Invocation.getFrontendOptions().StatsOutputDir;
|
computeStatsReporter(Invocation, Instance.get());
|
||||||
std::unique_ptr<UnifiedStatsReporter> StatsReporter;
|
if (StatsReporter) {
|
||||||
if (!StatsOutputDir.empty()) {
|
|
||||||
auto &FEOpts = Invocation.getFrontendOptions();
|
|
||||||
auto &LangOpts = Invocation.getLangOptions();
|
|
||||||
auto &SILOpts = Invocation.getSILOptions();
|
|
||||||
StringRef InputName = FEOpts.Inputs.getNameOfUniquePrimaryInputFile();
|
|
||||||
StringRef OptType = silOptModeArgStr(SILOpts.OptMode);
|
|
||||||
StringRef OutFile = FEOpts.getSingleOutputFilename();
|
|
||||||
StringRef OutputType = llvm::sys::path::extension(OutFile);
|
|
||||||
std::string TripleName = LangOpts.Target.normalize();
|
|
||||||
SourceManager *SM = &Instance->getSourceMgr();
|
|
||||||
clang::SourceManager *CSM = nullptr;
|
|
||||||
if (auto *clangImporter = static_cast<ClangImporter *>(
|
|
||||||
Instance->getASTContext().getClangModuleLoader())) {
|
|
||||||
CSM = &clangImporter->getClangASTContext().getSourceManager();
|
|
||||||
}
|
|
||||||
auto Trace = Invocation.getFrontendOptions().TraceStats;
|
|
||||||
StatsReporter = llvm::make_unique<UnifiedStatsReporter>("swift-frontend",
|
|
||||||
FEOpts.ModuleName,
|
|
||||||
InputName,
|
|
||||||
TripleName,
|
|
||||||
OutputType,
|
|
||||||
OptType,
|
|
||||||
StatsOutputDir,
|
|
||||||
SM, CSM,
|
|
||||||
Trace);
|
|
||||||
|
|
||||||
// Install stats-reporter somewhere visible for subsystems that
|
// Install stats-reporter somewhere visible for subsystems that
|
||||||
// need to bump counters as they work, rather than measure
|
// need to bump counters as they work, rather than measure
|
||||||
// accumulated work on completion (mostly: TypeChecker).
|
// accumulated work on completion (mostly: TypeChecker).
|
||||||
|
|||||||
@@ -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.getSingleOutputFilename();
|
auto 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);
|
||||||
|
|
||||||
|
|||||||
@@ -1050,7 +1050,7 @@ getNotableRegions(StringRef SourceText, unsigned NameOffset, StringRef Name,
|
|||||||
|
|
||||||
CompilerInvocation Invocation{};
|
CompilerInvocation Invocation{};
|
||||||
|
|
||||||
Invocation.getFrontendOptions().Inputs.addInput(
|
Invocation.getFrontendOptions().InputsAndOutputs.addInput(
|
||||||
InputFile("<extract>", true, InputBuffer.get()));
|
InputFile("<extract>", true, InputBuffer.get()));
|
||||||
Invocation.getFrontendOptions().ModuleName = "extract";
|
Invocation.getFrontendOptions().ModuleName = "extract";
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ Migrator::performAFixItMigration(version::Version SwiftLanguageVersion) {
|
|||||||
llvm::MemoryBuffer::getMemBufferCopy(InputText, getInputFilename());
|
llvm::MemoryBuffer::getMemBufferCopy(InputText, getInputFilename());
|
||||||
|
|
||||||
CompilerInvocation Invocation { StartInvocation };
|
CompilerInvocation Invocation { StartInvocation };
|
||||||
Invocation.getFrontendOptions().Inputs.clearInputs();
|
Invocation.getFrontendOptions().InputsAndOutputs.clearInputs();
|
||||||
Invocation.getLangOptions().EffectiveLanguageVersion = SwiftLanguageVersion;
|
Invocation.getLangOptions().EffectiveLanguageVersion = SwiftLanguageVersion;
|
||||||
auto &LLVMArgs = Invocation.getFrontendOptions().LLVMArgs;
|
auto &LLVMArgs = Invocation.getFrontendOptions().LLVMArgs;
|
||||||
auto aarch64_use_tbi = std::find(LLVMArgs.begin(), LLVMArgs.end(),
|
auto aarch64_use_tbi = std::find(LLVMArgs.begin(), LLVMArgs.end(),
|
||||||
@@ -144,10 +144,10 @@ Migrator::performAFixItMigration(version::Version SwiftLanguageVersion) {
|
|||||||
|
|
||||||
const auto &OrigFrontendOpts = StartInvocation.getFrontendOptions();
|
const auto &OrigFrontendOpts = StartInvocation.getFrontendOptions();
|
||||||
|
|
||||||
assert(OrigFrontendOpts.Inputs.hasPrimaryInputs() &&
|
assert(OrigFrontendOpts.InputsAndOutputs.hasPrimaryInputs() &&
|
||||||
"Migration must have a primary");
|
"Migration must have a primary");
|
||||||
for (const auto &input : OrigFrontendOpts.Inputs.getAllInputs()) {
|
for (const auto &input : OrigFrontendOpts.InputsAndOutputs.getAllInputs()) {
|
||||||
Invocation.getFrontendOptions().Inputs.addInput(
|
Invocation.getFrontendOptions().InputsAndOutputs.addInput(
|
||||||
InputFile(input.file(), input.isPrimary(),
|
InputFile(input.file(), input.isPrimary(),
|
||||||
input.isPrimary() ? InputBuffer.get() : input.buffer()));
|
input.isPrimary() ? InputBuffer.get() : input.buffer()));
|
||||||
}
|
}
|
||||||
@@ -438,6 +438,6 @@ const MigratorOptions &Migrator::getMigratorOptions() const {
|
|||||||
|
|
||||||
const StringRef Migrator::getInputFilename() const {
|
const StringRef Migrator::getInputFilename() const {
|
||||||
auto &PrimaryInput = StartInvocation.getFrontendOptions()
|
auto &PrimaryInput = StartInvocation.getFrontendOptions()
|
||||||
.Inputs.getRequiredUniquePrimaryInput();
|
.InputsAndOutputs.getRequiredUniquePrimaryInput();
|
||||||
return PrimaryInput.file();
|
return PrimaryInput.file();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Check that we don't crash when we verify after every pass.
|
// Check that we don't crash when we verify after every pass.
|
||||||
// RUN: %empty-directory(%t)
|
// RUN: %empty-directory(%t)
|
||||||
//
|
//
|
||||||
// RUN: %target-swift-frontend %s -I %S/../stdlib/Inputs/Mirror/ -o %t/Mirror \
|
// RUN: %target-swift-frontend %s -I %S/../stdlib/Inputs/Mirror/ \
|
||||||
// RUN: -emit-ir -sil-verify-all -o /dev/null
|
// RUN: -emit-ir -sil-verify-all -o /dev/null
|
||||||
|
|
||||||
class A : CustomReflectable {
|
class A : CustomReflectable {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// REQUIRES: objc_interop
|
// REQUIRES: objc_interop
|
||||||
// REQUIRES: OS=macosx
|
// REQUIRES: OS=macosx
|
||||||
// RUN: %target-swift-frontend -typecheck -swift-version 3 %s
|
// RUN: %target-swift-frontend -typecheck -swift-version 3 %s
|
||||||
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -emit-migrated-file-path %t/nsopengl_openglversion.swift.result -o %t/nsopengl_openglversion.swift.remap -o /dev/null
|
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -emit-migrated-file-path %t/nsopengl_openglversion.swift.result -o /dev/null
|
||||||
// RUN: diff -u %S/nsopengl_openglversion.swift.expected %t/nsopengl_openglversion.swift.result
|
// RUN: diff -u %S/nsopengl_openglversion.swift.expected %t/nsopengl_openglversion.swift.result
|
||||||
// RUN: %target-swift-frontend -typecheck -swift-version 4 %t/nsopengl_openglversion.swift.result
|
// RUN: %target-swift-frontend -typecheck -swift-version 4 %t/nsopengl_openglversion.swift.result
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// REQUIRES: objc_interop
|
// REQUIRES: objc_interop
|
||||||
// REQUIRES: OS=macosx
|
// REQUIRES: OS=macosx
|
||||||
// RUN: %target-swift-frontend -typecheck -swift-version 3 %s
|
// RUN: %target-swift-frontend -typecheck -swift-version 3 %s
|
||||||
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -emit-migrated-file-path %t/nsopengl_openglversion.swift.result -o %t/nsopengl_openglversion.swift.remap -o /dev/null
|
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -emit-migrated-file-path %t/nsopengl_openglversion.swift.result -o /dev/null
|
||||||
// RUN: diff -u %S/nsopengl_openglversion.swift.expected %t/nsopengl_openglversion.swift.result
|
// RUN: diff -u %S/nsopengl_openglversion.swift.expected %t/nsopengl_openglversion.swift.result
|
||||||
// RUN: %target-swift-frontend -typecheck -swift-version 4 %t/nsopengl_openglversion.swift.result
|
// RUN: %target-swift-frontend -typecheck -swift-version 4 %t/nsopengl_openglversion.swift.result
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// REQUIRES: objc_interop
|
// REQUIRES: objc_interop
|
||||||
// RUN: %empty-directory(%t.mod)
|
// RUN: %empty-directory(%t.mod)
|
||||||
// RUN: %target-swift-frontend -emit-module -o %t.mod/Cities.swiftmodule %S/Inputs/Cities.swift -module-name Cities -parse-as-library
|
// RUN: %target-swift-frontend -emit-module -o %t.mod/Cities.swiftmodule %S/Inputs/Cities.swift -module-name Cities -parse-as-library
|
||||||
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/rename-func-decl.swift.result -o %t/rename-func-decl.swift.remap -o /dev/null
|
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/rename-func-decl.swift.result -o %t/rename-func-decl.swift.remap
|
||||||
// RUN: diff -u %S/rename-func-decl.swift.expected %t/rename-func-decl.swift.result
|
// RUN: diff -u %S/rename-func-decl.swift.expected %t/rename-func-decl.swift.result
|
||||||
|
|
||||||
import Cities
|
import Cities
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// REQUIRES: objc_interop
|
// REQUIRES: objc_interop
|
||||||
// RUN: %empty-directory(%t.mod)
|
// RUN: %empty-directory(%t.mod)
|
||||||
// RUN: %target-swift-frontend -emit-module -o %t.mod/Cities.swiftmodule %S/Inputs/Cities.swift -module-name Cities -parse-as-library
|
// RUN: %target-swift-frontend -emit-module -o %t.mod/Cities.swiftmodule %S/Inputs/Cities.swift -module-name Cities -parse-as-library
|
||||||
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/rename-func-decl.swift.result -o %t/rename-func-decl.swift.remap -o /dev/null
|
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/rename-func-decl.swift.result -o %t/rename-func-decl.swift.remap
|
||||||
// RUN: diff -u %S/rename-func-decl.swift.expected %t/rename-func-decl.swift.result
|
// RUN: diff -u %S/rename-func-decl.swift.expected %t/rename-func-decl.swift.result
|
||||||
|
|
||||||
import Cities
|
import Cities
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// REQUIRES: objc_interop
|
// REQUIRES: objc_interop
|
||||||
// RUN: %empty-directory(%t.mod)
|
// RUN: %empty-directory(%t.mod)
|
||||||
// RUN: %target-swift-frontend -emit-module -o %t.mod/Cities.swiftmodule %S/Inputs/Cities.swift -module-name Cities -parse-as-library
|
// RUN: %target-swift-frontend -emit-module -o %t.mod/Cities.swiftmodule %S/Inputs/Cities.swift -module-name Cities -parse-as-library
|
||||||
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/wrap_optional.swift.result -o %t/wrap_optional.swift.remap -o /dev/null
|
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/wrap_optional.swift.result -o /dev/null
|
||||||
// RUN: diff -u %S/wrap_optional.swift.expected %t/wrap_optional.swift.result
|
// RUN: diff -u %S/wrap_optional.swift.expected %t/wrap_optional.swift.result
|
||||||
|
|
||||||
import Cities
|
import Cities
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// REQUIRES: objc_interop
|
// REQUIRES: objc_interop
|
||||||
// RUN: %empty-directory(%t.mod)
|
// RUN: %empty-directory(%t.mod)
|
||||||
// RUN: %target-swift-frontend -emit-module -o %t.mod/Cities.swiftmodule %S/Inputs/Cities.swift -module-name Cities -parse-as-library
|
// RUN: %target-swift-frontend -emit-module -o %t.mod/Cities.swiftmodule %S/Inputs/Cities.swift -module-name Cities -parse-as-library
|
||||||
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/wrap_optional.swift.result -o %t/wrap_optional.swift.remap -o /dev/null
|
// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -disable-migrator-fixits -primary-file %s -I %t.mod -api-diff-data-file %S/Inputs/API.json -emit-migrated-file-path %t/wrap_optional.swift.result -o /dev/null
|
||||||
// RUN: diff -u %S/wrap_optional.swift.expected %t/wrap_optional.swift.result
|
// RUN: diff -u %S/wrap_optional.swift.expected %t/wrap_optional.swift.result
|
||||||
|
|
||||||
import Cities
|
import Cities
|
||||||
|
|||||||
@@ -83,13 +83,15 @@ struct InvocationOptions {
|
|||||||
// Assert invocation with a primary file. We want to avoid full typechecking
|
// Assert invocation with a primary file. We want to avoid full typechecking
|
||||||
// for all files.
|
// for all files.
|
||||||
assert(!this->PrimaryFile.empty());
|
assert(!this->PrimaryFile.empty());
|
||||||
assert(this->Invok.getFrontendOptions().Inputs.hasUniquePrimaryInput() &&
|
assert(this->Invok.getFrontendOptions()
|
||||||
|
.InputsAndOutputs.hasUniquePrimaryInput() &&
|
||||||
"Must have exactly one primary input for code completion, etc.");
|
"Must have exactly one primary input for code completion, etc.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyTo(CompilerInvocation &CompInvok) const;
|
void applyTo(CompilerInvocation &CompInvok) const;
|
||||||
void applyToSubstitutingInputs(CompilerInvocation &CompInvok,
|
void
|
||||||
FrontendInputs &&Inputs) const;
|
applyToSubstitutingInputs(CompilerInvocation &CompInvok,
|
||||||
|
FrontendInputsAndOutputs &&InputsAndOutputs) const;
|
||||||
void profile(llvm::FoldingSetNodeID &ID) const;
|
void profile(llvm::FoldingSetNodeID &ID) const;
|
||||||
void raw(std::vector<std::string> &Args, std::string &PrimaryFile) const;
|
void raw(std::vector<std::string> &Args, std::string &PrimaryFile) const;
|
||||||
|
|
||||||
@@ -135,9 +137,10 @@ void InvocationOptions::applyTo(CompilerInvocation &CompInvok) const {
|
|||||||
CompInvok = this->Invok;
|
CompInvok = this->Invok;
|
||||||
}
|
}
|
||||||
void InvocationOptions::applyToSubstitutingInputs(
|
void InvocationOptions::applyToSubstitutingInputs(
|
||||||
CompilerInvocation &CompInvok, FrontendInputs &&inputs) const {
|
CompilerInvocation &CompInvok,
|
||||||
|
FrontendInputsAndOutputs &&inputsAndOutputs) const {
|
||||||
CompInvok = this->Invok;
|
CompInvok = this->Invok;
|
||||||
CompInvok.getFrontendOptions().Inputs = inputs;
|
CompInvok.getFrontendOptions().InputsAndOutputs = inputsAndOutputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InvocationOptions::raw(std::vector<std::string> &Args,
|
void InvocationOptions::raw(std::vector<std::string> &Args,
|
||||||
@@ -373,11 +376,12 @@ static void setModuleName(CompilerInvocation &Invocation) {
|
|||||||
|
|
||||||
StringRef Filename = Invocation.getOutputFilename();
|
StringRef Filename = Invocation.getOutputFilename();
|
||||||
if (Filename.empty()) {
|
if (Filename.empty()) {
|
||||||
if (!Invocation.getFrontendOptions().Inputs.hasInputs()) {
|
if (!Invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) {
|
||||||
Invocation.setModuleName("__main__");
|
Invocation.setModuleName("__main__");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Filename = Invocation.getFrontendOptions().Inputs.getFilenameOfFirstInput();
|
Filename = Invocation.getFrontendOptions()
|
||||||
|
.InputsAndOutputs.getFilenameOfFirstInput();
|
||||||
}
|
}
|
||||||
Filename = llvm::sys::path::filename(Filename);
|
Filename = llvm::sys::path::filename(Filename);
|
||||||
StringRef ModuleName = llvm::sys::path::stem(Filename);
|
StringRef ModuleName = llvm::sys::path::stem(Filename);
|
||||||
@@ -409,16 +413,16 @@ static void sanitizeCompilerArgs(ArrayRef<const char *> Args,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static FrontendInputs
|
static FrontendInputsAndOutputs
|
||||||
convertFileContentsToInputs(const SmallVectorImpl<FileContent> &contents) {
|
convertFileContentsToInputs(const SmallVectorImpl<FileContent> &contents) {
|
||||||
FrontendInputs inputs;
|
FrontendInputsAndOutputs inputsAndOutputs;
|
||||||
for (const FileContent &content : contents)
|
for (const FileContent &content : contents)
|
||||||
inputs.addInput(InputFile(content));
|
inputsAndOutputs.addInput(InputFile(content));
|
||||||
return inputs;
|
return inputsAndOutputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FrontendInputs
|
static FrontendInputsAndOutputs
|
||||||
resolveSymbolicLinksInInputs(FrontendInputs &inputs,
|
resolveSymbolicLinksInInputs(FrontendInputsAndOutputs &inputsAndOutputs,
|
||||||
StringRef UnresolvedPrimaryFile,
|
StringRef UnresolvedPrimaryFile,
|
||||||
std::string &Error) {
|
std::string &Error) {
|
||||||
unsigned primaryCount = 0;
|
unsigned primaryCount = 0;
|
||||||
@@ -426,8 +430,8 @@ resolveSymbolicLinksInInputs(FrontendInputs &inputs,
|
|||||||
SwiftLangSupport::resolvePathSymlinks(UnresolvedPrimaryFile);
|
SwiftLangSupport::resolvePathSymlinks(UnresolvedPrimaryFile);
|
||||||
// FIXME: The frontend should be dealing with symlinks, maybe similar to
|
// FIXME: The frontend should be dealing with symlinks, maybe similar to
|
||||||
// clang's FileManager ?
|
// clang's FileManager ?
|
||||||
FrontendInputs replacementInputs;
|
FrontendInputsAndOutputs replacementInputsAndOutputs;
|
||||||
for (const InputFile &input : inputs.getAllInputs()) {
|
for (const InputFile &input : inputsAndOutputs.getAllInputs()) {
|
||||||
std::string newFilename =
|
std::string newFilename =
|
||||||
SwiftLangSupport::resolvePathSymlinks(input.file());
|
SwiftLangSupport::resolvePathSymlinks(input.file());
|
||||||
bool newIsPrimary = input.isPrimary() ||
|
bool newIsPrimary = input.isPrimary() ||
|
||||||
@@ -436,19 +440,19 @@ resolveSymbolicLinksInInputs(FrontendInputs &inputs,
|
|||||||
++primaryCount;
|
++primaryCount;
|
||||||
}
|
}
|
||||||
assert(primaryCount < 2 && "cannot handle multiple primaries");
|
assert(primaryCount < 2 && "cannot handle multiple primaries");
|
||||||
replacementInputs.addInput(
|
replacementInputsAndOutputs.addInput(
|
||||||
InputFile(newFilename, newIsPrimary, input.buffer()));
|
InputFile(newFilename, newIsPrimary, input.buffer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PrimaryFile.empty() || primaryCount == 1) {
|
if (PrimaryFile.empty() || primaryCount == 1) {
|
||||||
return replacementInputs;
|
return replacementInputsAndOutputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::SmallString<64> Err;
|
llvm::SmallString<64> Err;
|
||||||
llvm::raw_svector_ostream OS(Err);
|
llvm::raw_svector_ostream OS(Err);
|
||||||
OS << "'" << PrimaryFile << "' is not part of the input files";
|
OS << "'" << PrimaryFile << "' is not part of the input files";
|
||||||
Error = OS.str();
|
Error = OS.str();
|
||||||
return replacementInputs;
|
return replacementInputsAndOutputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation,
|
bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation,
|
||||||
@@ -465,8 +469,10 @@ bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation,
|
|||||||
Error = "error when parsing the compiler arguments";
|
Error = "error when parsing the compiler arguments";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Invocation.getFrontendOptions().Inputs = resolveSymbolicLinksInInputs(
|
Invocation.getFrontendOptions().InputsAndOutputs =
|
||||||
Invocation.getFrontendOptions().Inputs, UnresolvedPrimaryFile, Error);
|
resolveSymbolicLinksInInputs(
|
||||||
|
Invocation.getFrontendOptions().InputsAndOutputs,
|
||||||
|
UnresolvedPrimaryFile, Error);
|
||||||
if (!Error.empty())
|
if (!Error.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -707,9 +713,9 @@ bool ASTProducer::shouldRebuild(SwiftASTManager::Implementation &MgrImpl,
|
|||||||
// Check if the inputs changed.
|
// Check if the inputs changed.
|
||||||
SmallVector<BufferStamp, 8> InputStamps;
|
SmallVector<BufferStamp, 8> InputStamps;
|
||||||
InputStamps.reserve(
|
InputStamps.reserve(
|
||||||
Invok.Opts.Invok.getFrontendOptions().Inputs.inputCount());
|
Invok.Opts.Invok.getFrontendOptions().InputsAndOutputs.inputCount());
|
||||||
for (const auto &input :
|
for (const auto &input :
|
||||||
Invok.Opts.Invok.getFrontendOptions().Inputs.getAllInputs()) {
|
Invok.Opts.Invok.getFrontendOptions().InputsAndOutputs.getAllInputs()) {
|
||||||
StringRef File = input.file();
|
StringRef File = input.file();
|
||||||
bool FoundSnapshot = false;
|
bool FoundSnapshot = false;
|
||||||
for (auto &Snap : Snapshots) {
|
for (auto &Snap : Snapshots) {
|
||||||
@@ -723,7 +729,7 @@ bool ASTProducer::shouldRebuild(SwiftASTManager::Implementation &MgrImpl,
|
|||||||
InputStamps.push_back(MgrImpl.getBufferStamp(File));
|
InputStamps.push_back(MgrImpl.getBufferStamp(File));
|
||||||
}
|
}
|
||||||
assert(InputStamps.size() ==
|
assert(InputStamps.size() ==
|
||||||
Invok.Opts.Invok.getFrontendOptions().Inputs.inputCount());
|
Invok.Opts.Invok.getFrontendOptions().InputsAndOutputs.inputCount());
|
||||||
if (Stamps != InputStamps)
|
if (Stamps != InputStamps)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -896,7 +902,7 @@ void ASTProducer::findSnapshotAndOpenFiles(
|
|||||||
SmallVectorImpl<FileContent> &Contents, std::string &Error) const {
|
SmallVectorImpl<FileContent> &Contents, std::string &Error) const {
|
||||||
const InvocationOptions &Opts = InvokRef->Impl.Opts;
|
const InvocationOptions &Opts = InvokRef->Impl.Opts;
|
||||||
for (const auto &input :
|
for (const auto &input :
|
||||||
Opts.Invok.getFrontendOptions().Inputs.getAllInputs()) {
|
Opts.Invok.getFrontendOptions().InputsAndOutputs.getAllInputs()) {
|
||||||
StringRef File = input.file();
|
StringRef File = input.file();
|
||||||
bool IsPrimary = input.isPrimary();
|
bool IsPrimary = input.isPrimary();
|
||||||
bool FoundSnapshot = false;
|
bool FoundSnapshot = false;
|
||||||
@@ -920,5 +926,5 @@ void ASTProducer::findSnapshotAndOpenFiles(
|
|||||||
Contents.push_back(std::move(Content));
|
Contents.push_back(std::move(Content));
|
||||||
}
|
}
|
||||||
assert(Contents.size() ==
|
assert(Contents.size() ==
|
||||||
Opts.Invok.getFrontendOptions().Inputs.inputCount());
|
Opts.Invok.getFrontendOptions().InputsAndOutputs.inputCount());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ static bool swiftCodeCompleteImpl(SwiftLangSupport &Lang,
|
|||||||
if (Failed) {
|
if (Failed) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!Invocation.getFrontendOptions().Inputs.hasInputs()) {
|
if (!Invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) {
|
||||||
Error = "no input filenames specified";
|
Error = "no input filenames specified";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -773,13 +773,13 @@ private:
|
|||||||
|
|
||||||
static bool makeParserAST(CompilerInstance &CI, StringRef Text,
|
static bool makeParserAST(CompilerInstance &CI, StringRef Text,
|
||||||
CompilerInvocation Invocation) {
|
CompilerInvocation Invocation) {
|
||||||
Invocation.getFrontendOptions().Inputs.clearInputs();
|
Invocation.getFrontendOptions().InputsAndOutputs.clearInputs();
|
||||||
Invocation.setModuleName("main");
|
Invocation.setModuleName("main");
|
||||||
Invocation.setInputKind(InputFileKind::IFK_Swift);
|
Invocation.setInputKind(InputFileKind::IFK_Swift);
|
||||||
|
|
||||||
std::unique_ptr<llvm::MemoryBuffer> Buf;
|
std::unique_ptr<llvm::MemoryBuffer> Buf;
|
||||||
Buf = llvm::MemoryBuffer::getMemBuffer(Text, "<module-interface>");
|
Buf = llvm::MemoryBuffer::getMemBuffer(Text, "<module-interface>");
|
||||||
Invocation.getFrontendOptions().Inputs.addInput(
|
Invocation.getFrontendOptions().InputsAndOutputs.addInput(
|
||||||
InputFile(Buf.get()->getBufferIdentifier(), false, Buf.get()));
|
InputFile(Buf.get()->getBufferIdentifier(), false, Buf.get()));
|
||||||
if (CI.setup(Invocation))
|
if (CI.setup(Invocation))
|
||||||
return true;
|
return true;
|
||||||
@@ -1094,7 +1094,7 @@ static bool reportSourceDocInfo(CompilerInvocation Invocation,
|
|||||||
|
|
||||||
EditorDiagConsumer DiagConsumer;
|
EditorDiagConsumer DiagConsumer;
|
||||||
CI.addDiagnosticConsumer(&DiagConsumer);
|
CI.addDiagnosticConsumer(&DiagConsumer);
|
||||||
Invocation.getFrontendOptions().Inputs.addInput(
|
Invocation.getFrontendOptions().InputsAndOutputs.addInput(
|
||||||
InputFile(InputBuf->getBufferIdentifier(), false, InputBuf));
|
InputFile(InputBuf->getBufferIdentifier(), false, InputBuf));
|
||||||
if (CI.setup(Invocation))
|
if (CI.setup(Invocation))
|
||||||
return true;
|
return true;
|
||||||
@@ -1367,7 +1367,7 @@ SourceFile *SwiftLangSupport::getSyntacticSourceFile(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
Invocation.setInputKind(InputFileKind::IFK_Swift);
|
Invocation.setInputKind(InputFileKind::IFK_Swift);
|
||||||
Invocation.getFrontendOptions().Inputs.addInput(
|
Invocation.getFrontendOptions().InputsAndOutputs.addInput(
|
||||||
InputFile(InputBuf->getBufferIdentifier(), false, InputBuf));
|
InputFile(InputBuf->getBufferIdentifier(), false, InputBuf));
|
||||||
|
|
||||||
if (ParseCI.setup(Invocation)) {
|
if (ParseCI.setup(Invocation)) {
|
||||||
@@ -1443,7 +1443,7 @@ findModuleGroups(StringRef ModuleName, ArrayRef<const char *> Args,
|
|||||||
StringRef Error)> Receiver) {
|
StringRef Error)> Receiver) {
|
||||||
CompilerInvocation Invocation;
|
CompilerInvocation Invocation;
|
||||||
Invocation.getClangImporterOptions().ImportForwardDeclarations = true;
|
Invocation.getClangImporterOptions().ImportForwardDeclarations = true;
|
||||||
Invocation.getFrontendOptions().Inputs.clearInputs();
|
Invocation.getFrontendOptions().InputsAndOutputs.clearInputs();
|
||||||
|
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
// Display diagnostics to stderr.
|
// Display diagnostics to stderr.
|
||||||
|
|||||||
@@ -228,13 +228,13 @@ public:
|
|||||||
|
|
||||||
static bool makeParserAST(CompilerInstance &CI, StringRef Text,
|
static bool makeParserAST(CompilerInstance &CI, StringRef Text,
|
||||||
CompilerInvocation Invocation) {
|
CompilerInvocation Invocation) {
|
||||||
Invocation.getFrontendOptions().Inputs.clearInputs();
|
Invocation.getFrontendOptions().InputsAndOutputs.clearInputs();
|
||||||
Invocation.setModuleName("main");
|
Invocation.setModuleName("main");
|
||||||
Invocation.setInputKind(InputFileKind::IFK_Swift);
|
Invocation.setInputKind(InputFileKind::IFK_Swift);
|
||||||
|
|
||||||
std::unique_ptr<llvm::MemoryBuffer> Buf;
|
std::unique_ptr<llvm::MemoryBuffer> Buf;
|
||||||
Buf = llvm::MemoryBuffer::getMemBuffer(Text, "<module-interface>");
|
Buf = llvm::MemoryBuffer::getMemBuffer(Text, "<module-interface>");
|
||||||
Invocation.getFrontendOptions().Inputs.addInput(
|
Invocation.getFrontendOptions().InputsAndOutputs.addInput(
|
||||||
InputFile(Buf.get()->getBufferIdentifier(), false, Buf.get()));
|
InputFile(Buf.get()->getBufferIdentifier(), false, Buf.get()));
|
||||||
if (CI.setup(Invocation))
|
if (CI.setup(Invocation))
|
||||||
return true;
|
return true;
|
||||||
@@ -402,7 +402,7 @@ SwiftInterfaceGenContext::create(StringRef DocumentName,
|
|||||||
// Display diagnostics to stderr.
|
// Display diagnostics to stderr.
|
||||||
CI.addDiagnosticConsumer(&IFaceGenCtx->Impl.DiagConsumer);
|
CI.addDiagnosticConsumer(&IFaceGenCtx->Impl.DiagConsumer);
|
||||||
|
|
||||||
Invocation.getFrontendOptions().Inputs.clearInputs();
|
Invocation.getFrontendOptions().InputsAndOutputs.clearInputs();
|
||||||
if (CI.setup(Invocation)) {
|
if (CI.setup(Invocation)) {
|
||||||
ErrMsg = "Error during invocation setup";
|
ErrMsg = "Error during invocation setup";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ void SwiftLangSupport::indexSource(StringRef InputFile,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Invocation.getFrontendOptions().Inputs.hasInputs()) {
|
if (!Invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) {
|
||||||
IdxConsumer.failed("no input filenames specified");
|
IdxConsumer.failed("no input filenames specified");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -729,7 +729,8 @@ static int doCodeCompletion(const CompilerInvocation &InitInvok,
|
|||||||
|
|
||||||
Invocation.setCodeCompletionFactory(CompletionCallbacksFactory.get());
|
Invocation.setCodeCompletionFactory(CompletionCallbacksFactory.get());
|
||||||
if (!SecondSourceFileName.empty()) {
|
if (!SecondSourceFileName.empty()) {
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(SecondSourceFileName);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(
|
||||||
|
SecondSourceFileName);
|
||||||
}
|
}
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
|
|
||||||
@@ -955,7 +956,7 @@ static int doSyntaxColoring(const CompilerInvocation &InitInvok,
|
|||||||
bool RunTypeChecker,
|
bool RunTypeChecker,
|
||||||
bool Playground) {
|
bool Playground) {
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
|
||||||
Invocation.getLangOptions().DisableAvailabilityChecking = false;
|
Invocation.getLangOptions().DisableAvailabilityChecking = false;
|
||||||
|
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
@@ -998,7 +999,7 @@ static int doDumpImporterLookupTables(const CompilerInvocation &InitInvok,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
|
||||||
|
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
|
|
||||||
@@ -1178,7 +1179,7 @@ static int doStructureAnnotation(const CompilerInvocation &InitInvok,
|
|||||||
StringRef SourceFilename) {
|
StringRef SourceFilename) {
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
|
Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
|
||||||
|
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
|
|
||||||
@@ -1434,7 +1435,7 @@ static int doSemanticAnnotation(const CompilerInvocation &InitInvok,
|
|||||||
StringRef SourceFilename,
|
StringRef SourceFilename,
|
||||||
bool TerminalOutput) {
|
bool TerminalOutput) {
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
|
||||||
|
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
|
|
||||||
@@ -1499,7 +1500,7 @@ static int doPrintAST(const CompilerInvocation &InitInvok,
|
|||||||
StringRef MangledNameToFind,
|
StringRef MangledNameToFind,
|
||||||
StringRef DebugClientDiscriminator) {
|
StringRef DebugClientDiscriminator) {
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
|
||||||
|
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
|
|
||||||
@@ -1930,7 +1931,8 @@ static int doPrintSwiftFileInterface(const CompilerInvocation &InitInvok,
|
|||||||
StringRef SourceFilename,
|
StringRef SourceFilename,
|
||||||
bool AnnotatePrint) {
|
bool AnnotatePrint) {
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addPrimaryInputFile(SourceFilename);
|
Invocation.getFrontendOptions().InputsAndOutputs.addPrimaryInputFile(
|
||||||
|
SourceFilename);
|
||||||
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
// Display diagnostics to stderr.
|
// Display diagnostics to stderr.
|
||||||
@@ -1960,7 +1962,8 @@ static int doPrintDecls(const CompilerInvocation &InitInvok,
|
|||||||
const PrintOptions &Options,
|
const PrintOptions &Options,
|
||||||
bool AnnotatePrint) {
|
bool AnnotatePrint) {
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addPrimaryInputFile(SourceFilename);
|
Invocation.getFrontendOptions().InputsAndOutputs.addPrimaryInputFile(
|
||||||
|
SourceFilename);
|
||||||
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
// Display diagnostics to stderr.
|
// Display diagnostics to stderr.
|
||||||
@@ -2071,7 +2074,7 @@ static int doPrintTypes(const CompilerInvocation &InitInvok,
|
|||||||
StringRef SourceFilename,
|
StringRef SourceFilename,
|
||||||
bool FullyQualifiedTypes) {
|
bool FullyQualifiedTypes) {
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
|
||||||
|
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
// Display diagnostics to stderr.
|
// Display diagnostics to stderr.
|
||||||
@@ -2297,7 +2300,7 @@ public:
|
|||||||
static int doDumpComments(const CompilerInvocation &InitInvok,
|
static int doDumpComments(const CompilerInvocation &InitInvok,
|
||||||
StringRef SourceFilename) {
|
StringRef SourceFilename) {
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
|
||||||
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
// Display diagnostics to stderr.
|
// Display diagnostics to stderr.
|
||||||
@@ -2319,7 +2322,7 @@ static int doPrintComments(const CompilerInvocation &InitInvok,
|
|||||||
StringRef SourceFilename,
|
StringRef SourceFilename,
|
||||||
StringRef CommentsXMLSchema) {
|
StringRef CommentsXMLSchema) {
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
|
||||||
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
||||||
Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
|
Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
|
||||||
|
|
||||||
@@ -2449,7 +2452,7 @@ static int doPrintTypeInterface(const CompilerInvocation &InitInvok,
|
|||||||
if (!Pair.hasValue())
|
if (!Pair.hasValue())
|
||||||
return 1;
|
return 1;
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(FileName);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(FileName);
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
if (CI.setup(Invocation))
|
if (CI.setup(Invocation))
|
||||||
return 1;
|
return 1;
|
||||||
@@ -2495,7 +2498,7 @@ static int doPrintTypeInterfaceForTypeUsr(const CompilerInvocation &InitInvok,
|
|||||||
const StringRef FileName,
|
const StringRef FileName,
|
||||||
const StringRef Usr) {
|
const StringRef Usr) {
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(FileName);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(FileName);
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
if (CI.setup(Invocation))
|
if (CI.setup(Invocation))
|
||||||
return 1;
|
return 1;
|
||||||
@@ -2656,7 +2659,7 @@ private:
|
|||||||
static int doReconstructType(const CompilerInvocation &InitInvok,
|
static int doReconstructType(const CompilerInvocation &InitInvok,
|
||||||
StringRef SourceFilename) {
|
StringRef SourceFilename) {
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
|
||||||
Invocation.getLangOptions().DisableAvailabilityChecking = false;
|
Invocation.getLangOptions().DisableAvailabilityChecking = false;
|
||||||
|
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
@@ -2690,7 +2693,7 @@ static int doPrintRangeInfo(const CompilerInvocation &InitInvok,
|
|||||||
auto StartLineCol = StartOp.getValue();
|
auto StartLineCol = StartOp.getValue();
|
||||||
auto EndLineCol = EndOp.getValue();
|
auto EndLineCol = EndOp.getValue();
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFileName);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFileName);
|
||||||
Invocation.getLangOptions().DisableAvailabilityChecking = false;
|
Invocation.getLangOptions().DisableAvailabilityChecking = false;
|
||||||
Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
|
Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
|
||||||
|
|
||||||
@@ -2792,7 +2795,7 @@ static int doPrintIndexedSymbols(const CompilerInvocation &InitInvok,
|
|||||||
StringRef SourceFileName, bool indexLocals) {
|
StringRef SourceFileName, bool indexLocals) {
|
||||||
|
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFileName);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFileName);
|
||||||
Invocation.getLangOptions().DisableAvailabilityChecking = false;
|
Invocation.getLangOptions().DisableAvailabilityChecking = false;
|
||||||
Invocation.getLangOptions().TypoCorrectionLimit = 0;
|
Invocation.getLangOptions().TypoCorrectionLimit = 0;
|
||||||
|
|
||||||
@@ -2857,7 +2860,7 @@ static int doPrintIndexedSymbolsFromModule(const CompilerInvocation &InitInvok,
|
|||||||
static int doPrintUSRs(const CompilerInvocation &InitInvok,
|
static int doPrintUSRs(const CompilerInvocation &InitInvok,
|
||||||
StringRef SourceFilename) {
|
StringRef SourceFilename) {
|
||||||
CompilerInvocation Invocation(InitInvok);
|
CompilerInvocation Invocation(InitInvok);
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(SourceFilename);
|
||||||
|
|
||||||
ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions();
|
ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions();
|
||||||
ImporterOpts.DetailedPreprocessingRecord = true;
|
ImporterOpts.DetailedPreprocessingRecord = true;
|
||||||
@@ -3004,7 +3007,7 @@ int main(int argc, char *argv[]) {
|
|||||||
CompilerInvocation InitInvok;
|
CompilerInvocation InitInvok;
|
||||||
|
|
||||||
for (auto &File : options::InputFilenames)
|
for (auto &File : options::InputFilenames)
|
||||||
InitInvok.getFrontendOptions().Inputs.addInputFile(File);
|
InitInvok.getFrontendOptions().InputsAndOutputs.addInputFile(File);
|
||||||
if (!options::InputFilenames.empty())
|
if (!options::InputFilenames.empty())
|
||||||
InitInvok.setInputKind(InputFileKind::IFK_Swift_Library);
|
InitInvok.setInputKind(InputFileKind::IFK_Swift_Library);
|
||||||
|
|
||||||
|
|||||||
@@ -233,12 +233,13 @@ int main(int argc, char *argv[]) {
|
|||||||
Invocation.setMainExecutablePath(
|
Invocation.setMainExecutablePath(
|
||||||
llvm::sys::fs::getMainExecutable(argv[0],
|
llvm::sys::fs::getMainExecutable(argv[0],
|
||||||
reinterpret_cast<void *>(&anchorForGetMainExecutable)));
|
reinterpret_cast<void *>(&anchorForGetMainExecutable)));
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(options::SourceFilename);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(
|
||||||
|
options::SourceFilename);
|
||||||
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
||||||
Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
|
Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
|
||||||
|
|
||||||
for (auto FileName : options::InputFilenames)
|
for (auto FileName : options::InputFilenames)
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(FileName);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(FileName);
|
||||||
Invocation.setModuleName(options::ModuleName);
|
Invocation.setModuleName(options::ModuleName);
|
||||||
CompilerInstance CI;
|
CompilerInstance CI;
|
||||||
// Display diagnostics to stderr.
|
// Display diagnostics to stderr.
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ SourceFile *getSourceFile(CompilerInstance &Instance,
|
|||||||
CompilerInvocation Invocation;
|
CompilerInvocation Invocation;
|
||||||
Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
|
Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
|
||||||
Invocation.getLangOptions().VerifySyntaxTree = true;
|
Invocation.getLangOptions().VerifySyntaxTree = true;
|
||||||
Invocation.getFrontendOptions().Inputs.addInputFile(InputFileName);
|
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(InputFileName);
|
||||||
Invocation.setMainExecutablePath(
|
Invocation.setMainExecutablePath(
|
||||||
llvm::sys::fs::getMainExecutable(MainExecutablePath,
|
llvm::sys::fs::getMainExecutable(MainExecutablePath,
|
||||||
reinterpret_cast<void *>(&anchorForGetMainExecutable)));
|
reinterpret_cast<void *>(&anchorForGetMainExecutable)));
|
||||||
|
|||||||
Reference in New Issue
Block a user