mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #15013 from davidungar/PR-18-11-fileMap
[Batch mode] Write supplementary output file map. rdar://problem/38157859
This commit is contained in:
@@ -5,12 +5,10 @@ set(swiftDriver_sources
|
||||
Driver.cpp
|
||||
FrontendUtil.cpp
|
||||
Job.cpp
|
||||
OutputFileMap.cpp
|
||||
ParseableOutput.cpp
|
||||
PrettyStackTrace.cpp
|
||||
ToolChain.cpp
|
||||
ToolChains.cpp
|
||||
Types.cpp
|
||||
)
|
||||
|
||||
set(swiftDriver_targetDefines)
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "swift/Driver/Job.h"
|
||||
#include "swift/Driver/ParseableOutput.h"
|
||||
#include "swift/Driver/ToolChain.h"
|
||||
#include "swift/Frontend/OutputFileMap.h"
|
||||
#include "swift/Option/Options.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
@@ -37,12 +39,14 @@
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
#include "llvm/Support/YAMLParser.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include "CompilationRecord.h"
|
||||
|
||||
#define DEBUG_TYPE "batch-mode"
|
||||
|
||||
// Batch-mode has a sub-mode for testing that randomizes batch partitions,
|
||||
// by user-provided seed. That is the only thing randomized here.
|
||||
#include <random>
|
||||
@@ -103,6 +107,7 @@ Compilation::Compilation(DiagnosticEngine &Diags,
|
||||
bool EnableIncrementalBuild,
|
||||
bool EnableBatchMode,
|
||||
unsigned BatchSeed,
|
||||
bool ForceOneBatchRepartition,
|
||||
bool SkipTaskExecution,
|
||||
bool SaveTemps,
|
||||
bool ShowDriverTimeCompilation,
|
||||
@@ -119,12 +124,14 @@ Compilation::Compilation(DiagnosticEngine &Diags,
|
||||
EnableIncrementalBuild(EnableIncrementalBuild),
|
||||
EnableBatchMode(EnableBatchMode),
|
||||
BatchSeed(BatchSeed),
|
||||
ForceOneBatchRepartition(ForceOneBatchRepartition),
|
||||
SaveTemps(SaveTemps),
|
||||
ShowDriverTimeCompilation(ShowDriverTimeCompilation),
|
||||
Stats(std::move(StatsReporter)) {
|
||||
};
|
||||
|
||||
static bool writeFilelistIfNecessary(const Job *job, DiagnosticEngine &diags);
|
||||
static bool writeFilelistIfNecessary(const Job *job, const ArgList &args,
|
||||
DiagnosticEngine &diags);
|
||||
|
||||
using CommandSet = llvm::SmallPtrSet<const Job *, 16>;
|
||||
using CommandSetVector = llvm::SetVector<const Job*>;
|
||||
@@ -254,7 +261,8 @@ namespace driver {
|
||||
|
||||
void addPendingJobToTaskQueue(const Job *Cmd) {
|
||||
// FIXME: Failing here should not take down the whole process.
|
||||
bool success = writeFilelistIfNecessary(Cmd, Comp.Diags);
|
||||
bool success =
|
||||
writeFilelistIfNecessary(Cmd, *Comp.TranslatedArgs.get(), Comp.Diags);
|
||||
assert(success && "failed to write filelist");
|
||||
(void)success;
|
||||
|
||||
@@ -787,12 +795,20 @@ namespace driver {
|
||||
});
|
||||
}
|
||||
|
||||
// FIXME: at the moment we're not passing OutputFileMaps to frontends, so
|
||||
// due to the multiplication of the number of additional files and the
|
||||
// Due to the multiplication of the number of additional files and the
|
||||
// number of files in a batch, it's pretty easy to construct too-long
|
||||
// command lines here, which will then fail to exec. We address this crudely
|
||||
// by re-forming batches with a finer partition when we overflow.
|
||||
//
|
||||
// Now that we're passing OutputFileMaps to frontends, this should never
|
||||
// happen, but keep this as insurance, because the decision to pass output
|
||||
// file maps cannot know the exact length of the command line, so may
|
||||
// possibly fail to use the OutputFileMap.
|
||||
//
|
||||
// In order to be able to exercise as much of the code paths as possible,
|
||||
// take a flag to force a retry, but only once.
|
||||
bool shouldRetryWithMorePartitions(std::vector<const Job *> const &Batches,
|
||||
bool &PretendTheCommandLineIsTooLongOnce,
|
||||
size_t &NumPartitions) {
|
||||
|
||||
// Stop rebatching if we can't subdivide batches any further.
|
||||
@@ -801,10 +817,14 @@ namespace driver {
|
||||
|
||||
for (auto const *B : Batches) {
|
||||
if (!llvm::sys::commandLineFitsWithinSystemLimits(B->getExecutable(),
|
||||
B->getArguments())) {
|
||||
B->getArguments()) ||
|
||||
PretendTheCommandLineIsTooLongOnce) {
|
||||
PretendTheCommandLineIsTooLongOnce = false;
|
||||
// To avoid redoing the batch loop too many times, repartition pretty
|
||||
// aggressively by doubling partition count / halving size.
|
||||
NumPartitions *= 2;
|
||||
DEBUG(llvm::dbgs()
|
||||
<< "Should have used a supplementary output file map.\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -827,6 +847,8 @@ namespace driver {
|
||||
size_t NumPartitions = Comp.NumberOfParallelCommands;
|
||||
CommandSetVector Batchable, NonBatchable;
|
||||
std::vector<const Job *> Batches;
|
||||
bool PretendTheCommandLineIsTooLongOnce =
|
||||
Comp.getForceOneBatchRepartition();
|
||||
do {
|
||||
// We might be restarting loop; clear these before proceeding.
|
||||
Batchable.clear();
|
||||
@@ -845,7 +867,8 @@ namespace driver {
|
||||
formBatchJobFromPartitionBatch(Batches, Batch);
|
||||
}
|
||||
|
||||
} while (shouldRetryWithMorePartitions(Batches, NumPartitions));
|
||||
} while (shouldRetryWithMorePartitions(
|
||||
Batches, PretendTheCommandLineIsTooLongOnce, NumPartitions));
|
||||
PendingExecution.clear();
|
||||
|
||||
// Save batches so we can locate and decompose them on task-exit.
|
||||
@@ -1089,7 +1112,8 @@ static void writeCompilationRecord(StringRef path, StringRef argsHash,
|
||||
}
|
||||
}
|
||||
|
||||
static bool writeFilelistIfNecessary(const Job *job, DiagnosticEngine &diags) {
|
||||
static bool writeFilelistIfNecessary(const Job *job, const ArgList &args,
|
||||
DiagnosticEngine &diags) {
|
||||
bool ok = true;
|
||||
for (const FilelistInfo &filelistInfo : job->getFilelistInfos()) {
|
||||
if (filelistInfo.path.empty())
|
||||
@@ -1121,18 +1145,29 @@ static bool writeFilelistIfNecessary(const Job *job, DiagnosticEngine &diags) {
|
||||
}
|
||||
break;
|
||||
case FilelistInfo::WhichFiles::PrimaryInputs:
|
||||
for (const Action *A : job->getSource().getInputs()) {
|
||||
const auto *IA = cast<InputAction>(A);
|
||||
out << IA->getInputArg().getValue() << "\n";
|
||||
// Ensure that -index-file-path works in conjunction with
|
||||
// -driver-use-filelists. It needs to be the only primary.
|
||||
if (Arg *A = args.getLastArg(options::OPT_index_file_path))
|
||||
out << A->getValue() << "\n";
|
||||
else {
|
||||
// The normal case for non-single-compile jobs.
|
||||
for (const Action *A : job->getSource().getInputs()) {
|
||||
const auto *IA = cast<InputAction>(A);
|
||||
out << IA->getInputArg().getValue() << "\n";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FilelistInfo::WhichFiles::Output:
|
||||
case FilelistInfo::WhichFiles::Output: {
|
||||
const CommandOutput &outputInfo = job->getOutput();
|
||||
assert(outputInfo.getPrimaryOutputType() == filelistInfo.type);
|
||||
for (auto &output : outputInfo.getPrimaryOutputFilenames())
|
||||
out << output << "\n";
|
||||
break;
|
||||
}
|
||||
case FilelistInfo::WhichFiles::SupplementaryOutput:
|
||||
job->getOutput().writeOutputFileMap(out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
@@ -1171,7 +1206,7 @@ int Compilation::performSingleCommand(const Job *Cmd) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!writeFilelistIfNecessary(Cmd, Diags))
|
||||
if (!writeFilelistIfNecessary(Cmd, *TranslatedArgs.get(), Diags))
|
||||
return 1;
|
||||
|
||||
switch (Level) {
|
||||
|
||||
@@ -17,25 +17,25 @@
|
||||
#include "swift/Driver/Driver.h"
|
||||
|
||||
#include "ToolChains.h"
|
||||
#include "swift/Strings.h"
|
||||
#include "swift/AST/DiagnosticEngine.h"
|
||||
#include "swift/AST/DiagnosticsDriver.h"
|
||||
#include "swift/AST/DiagnosticsFrontend.h"
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "swift/Basic/TaskQueue.h"
|
||||
#include "swift/Basic/Version.h"
|
||||
#include "swift/Basic/Range.h"
|
||||
#include "swift/Basic/Statistic.h"
|
||||
#include "swift/Basic/TaskQueue.h"
|
||||
#include "swift/Basic/Version.h"
|
||||
#include "swift/Config.h"
|
||||
#include "swift/Driver/Action.h"
|
||||
#include "swift/Driver/Compilation.h"
|
||||
#include "swift/Driver/Job.h"
|
||||
#include "swift/Driver/OutputFileMap.h"
|
||||
#include "swift/Driver/PrettyStackTrace.h"
|
||||
#include "swift/Driver/ToolChain.h"
|
||||
#include "swift/Frontend/OutputFileMap.h"
|
||||
#include "swift/Option/Options.h"
|
||||
#include "swift/Option/SanitizerOptions.h"
|
||||
#include "swift/Parse/Lexer.h"
|
||||
#include "swift/Config.h"
|
||||
#include "swift/Strings.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
@@ -531,6 +531,8 @@ Driver::buildCompilation(const ToolChain &TC,
|
||||
A->getAsString(*ArgList), A->getValue());
|
||||
}
|
||||
}
|
||||
DriverForceOneBatchRepartition =
|
||||
ArgList->hasArg(options::OPT_driver_force_one_batch_repartition);
|
||||
|
||||
bool Incremental = ArgList->hasArg(options::OPT_incremental);
|
||||
if (ArgList->hasArg(options::OPT_whole_module_optimization)) {
|
||||
@@ -621,7 +623,7 @@ Driver::buildCompilation(const ToolChain &TC,
|
||||
// REPL mode expects no input files, so suppress the error.
|
||||
SuppressNoInputFilesError = true;
|
||||
|
||||
std::unique_ptr<OutputFileMap> OFM =
|
||||
Optional<OutputFileMap> OFM =
|
||||
buildOutputFileMap(*TranslatedArgList, workingDirectory);
|
||||
|
||||
if (Diags.hadAnyError())
|
||||
@@ -704,13 +706,14 @@ Driver::buildCompilation(const ToolChain &TC,
|
||||
Incremental,
|
||||
BatchMode,
|
||||
DriverBatchSeed,
|
||||
DriverForceOneBatchRepartition,
|
||||
DriverSkipExecution,
|
||||
SaveTemps,
|
||||
ShowDriverTimeCompilation,
|
||||
std::move(StatsReporter)));
|
||||
// Construct the graph of Actions.
|
||||
SmallVector<const Action *, 8> TopLevelActions;
|
||||
buildActions(TopLevelActions, TC, OI, OFM.get(),
|
||||
buildActions(TopLevelActions, TC, OI, OFM ? OFM.getPointer() : nullptr,
|
||||
rebuildEverything ? nullptr : &outOfDateMap, *C);
|
||||
|
||||
if (Diags.hadAnyError())
|
||||
@@ -721,7 +724,8 @@ Driver::buildCompilation(const ToolChain &TC,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
buildJobs(TopLevelActions, OI, OFM.get(), workingDirectory, TC, *C);
|
||||
buildJobs(TopLevelActions, OI, OFM ? OFM.getPointer() : nullptr,
|
||||
workingDirectory, TC, *C);
|
||||
|
||||
if (DriverPrintDerivedOutputFileMap) {
|
||||
C->getDerivedOutputFileMap().dump(llvm::outs(), true);
|
||||
@@ -1102,7 +1106,8 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
|
||||
|
||||
} else { // DriverKind::Batch
|
||||
OI.CompilerMode = OutputInfo::Mode::StandardCompile;
|
||||
if (Args.hasArg(options::OPT_whole_module_optimization))
|
||||
if (Args.hasArg(options::OPT_whole_module_optimization,
|
||||
options::OPT_index_file))
|
||||
OI.CompilerMode = OutputInfo::Mode::SingleCompile;
|
||||
OI.CompilerOutputType = types::TY_Object;
|
||||
}
|
||||
@@ -1697,20 +1702,21 @@ bool Driver::handleImmediateArgs(const ArgList &Args, const ToolChain &TC) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<OutputFileMap>
|
||||
Optional<OutputFileMap>
|
||||
Driver::buildOutputFileMap(const llvm::opt::DerivedArgList &Args,
|
||||
StringRef workingDirectory) const {
|
||||
const Arg *A = Args.getLastArg(options::OPT_output_file_map);
|
||||
if (!A)
|
||||
return nullptr;
|
||||
return None;
|
||||
|
||||
// TODO: perform some preflight checks to ensure the file exists.
|
||||
auto OFM = OutputFileMap::loadFromPath(A->getValue(), workingDirectory);
|
||||
if (!OFM) {
|
||||
// TODO: emit diagnostic with error string
|
||||
Diags.diagnose(SourceLoc(), diag::error_unable_to_load_output_file_map);
|
||||
llvm::Expected<OutputFileMap> OFM =
|
||||
OutputFileMap::loadFromPath(A->getValue(), workingDirectory);
|
||||
if (auto Err = OFM.takeError()) {
|
||||
Diags.diagnose(SourceLoc(), diag::error_unable_to_load_output_file_map,
|
||||
llvm::toString(std::move(Err)));
|
||||
}
|
||||
return OFM;
|
||||
return *OFM;
|
||||
}
|
||||
|
||||
void Driver::buildJobs(ArrayRef<const Action *> TopLevelActions,
|
||||
@@ -2650,3 +2656,17 @@ void Driver::printHelp(bool ShowHidden) const {
|
||||
getOpts().PrintHelp(llvm::outs(), Name.c_str(), "Swift compiler",
|
||||
IncludedFlagsBitmask, ExcludedFlagsBitmask);
|
||||
}
|
||||
|
||||
bool OutputInfo::mightHaveExplicitPrimaryInputs(
|
||||
const CommandOutput &Output) const {
|
||||
switch (CompilerMode) {
|
||||
case Mode::StandardCompile:
|
||||
case Mode::BatchModeCompile:
|
||||
return true;
|
||||
case Mode::SingleCompile:
|
||||
return false;
|
||||
case Mode::Immediate:
|
||||
case Mode::REPL:
|
||||
llvm_unreachable("REPL and immediate modes handled elsewhere");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +240,10 @@ StringRef CommandOutput::getAnyOutputForType(types::ID Type) const {
|
||||
return getAdditionalOutputForType(Type);
|
||||
}
|
||||
|
||||
const OutputFileMap &CommandOutput::getDerivedOutputMap() const {
|
||||
return DerivedOutputMap;
|
||||
}
|
||||
|
||||
StringRef CommandOutput::getBaseInput(size_t Index) const {
|
||||
assert(Index < Inputs.size());
|
||||
return Inputs[Index].Base;
|
||||
@@ -310,6 +314,16 @@ CommandOutput::dump() const {
|
||||
llvm::errs() << '\n';
|
||||
}
|
||||
|
||||
void CommandOutput::writeOutputFileMap(llvm::raw_ostream &out) const {
|
||||
SmallVector<StringRef, 4> inputs;
|
||||
for (const CommandInputPair IP : Inputs) {
|
||||
assert(IP.Base == IP.Primary && !IP.Base.empty() &&
|
||||
"output file maps won't work if these differ");
|
||||
inputs.push_back(IP.Primary);
|
||||
}
|
||||
getDerivedOutputMap().write(out, inputs);
|
||||
}
|
||||
|
||||
Job::~Job() = default;
|
||||
|
||||
void Job::printArguments(raw_ostream &os,
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
//===--- OutputFileMap.cpp - Driver output file map -----------------------===//
|
||||
//
|
||||
// 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/Driver/OutputFileMap.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <system_error>
|
||||
|
||||
using namespace swift;
|
||||
using namespace swift::driver;
|
||||
|
||||
std::unique_ptr<OutputFileMap>
|
||||
OutputFileMap::loadFromPath(StringRef Path, StringRef workingDirectory) {
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
|
||||
llvm::MemoryBuffer::getFile(Path);
|
||||
if (!FileBufOrErr)
|
||||
return nullptr;
|
||||
return loadFromBuffer(std::move(FileBufOrErr.get()), workingDirectory);
|
||||
}
|
||||
|
||||
std::unique_ptr<OutputFileMap>
|
||||
OutputFileMap::loadFromBuffer(StringRef Data, StringRef workingDirectory) {
|
||||
std::unique_ptr<llvm::MemoryBuffer> Buffer{
|
||||
llvm::MemoryBuffer::getMemBuffer(Data)
|
||||
};
|
||||
return loadFromBuffer(std::move(Buffer), workingDirectory);
|
||||
}
|
||||
|
||||
std::unique_ptr<OutputFileMap>
|
||||
OutputFileMap::loadFromBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer,
|
||||
StringRef workingDirectory) {
|
||||
std::unique_ptr<OutputFileMap> OFM(new OutputFileMap());
|
||||
|
||||
if (OFM->parse(std::move(Buffer), workingDirectory))
|
||||
return nullptr;
|
||||
|
||||
return OFM;
|
||||
}
|
||||
|
||||
const TypeToPathMap *OutputFileMap::getOutputMapForInput(StringRef Input) const{
|
||||
auto iter = InputToOutputsMap.find(Input);
|
||||
if (iter == InputToOutputsMap.end())
|
||||
return nullptr;
|
||||
else
|
||||
return &iter->second;
|
||||
}
|
||||
|
||||
TypeToPathMap &
|
||||
OutputFileMap::getOrCreateOutputMapForInput(StringRef Input) {
|
||||
return InputToOutputsMap[Input];
|
||||
}
|
||||
|
||||
const TypeToPathMap *OutputFileMap::getOutputMapForSingleOutput() const {
|
||||
return getOutputMapForInput(StringRef());
|
||||
}
|
||||
|
||||
TypeToPathMap &
|
||||
OutputFileMap::getOrCreateOutputMapForSingleOutput() {
|
||||
return InputToOutputsMap[StringRef()];
|
||||
}
|
||||
|
||||
void OutputFileMap::dump(llvm::raw_ostream &os, bool Sort) const {
|
||||
typedef std::pair<types::ID, std::string> TypePathPair;
|
||||
|
||||
auto printOutputPair = [&os] (StringRef InputPath,
|
||||
const TypePathPair &OutputPair) -> void {
|
||||
os << InputPath << " -> " << types::getTypeName(OutputPair.first) << ": \""
|
||||
<< OutputPair.second << "\"\n";
|
||||
};
|
||||
|
||||
if (Sort) {
|
||||
typedef std::pair<StringRef, TypeToPathMap> PathMapPair;
|
||||
std::vector<PathMapPair> Maps;
|
||||
for (auto &InputPair : InputToOutputsMap) {
|
||||
Maps.emplace_back(InputPair.first(), InputPair.second);
|
||||
}
|
||||
std::sort(Maps.begin(), Maps.end(), [] (const PathMapPair &LHS,
|
||||
const PathMapPair &RHS) -> bool {
|
||||
return LHS.first < RHS.first;
|
||||
});
|
||||
for (auto &InputPair : Maps) {
|
||||
const TypeToPathMap &Map = InputPair.second;
|
||||
std::vector<TypePathPair> Pairs;
|
||||
Pairs.insert(Pairs.end(), Map.begin(), Map.end());
|
||||
std::sort(Pairs.begin(), Pairs.end());
|
||||
for (auto &OutputPair : Pairs) {
|
||||
printOutputPair(InputPair.first, OutputPair);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto &InputPair : InputToOutputsMap) {
|
||||
const TypeToPathMap &Map = InputPair.second;
|
||||
for (const TypePathPair &OutputPair : Map) {
|
||||
printOutputPair(InputPair.first(), OutputPair);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool OutputFileMap::parse(std::unique_ptr<llvm::MemoryBuffer> Buffer,
|
||||
StringRef workingDirectory) {
|
||||
llvm::SourceMgr SM;
|
||||
llvm::yaml::Stream YAMLStream(Buffer->getMemBufferRef(), SM);
|
||||
auto I = YAMLStream.begin();
|
||||
if (I == YAMLStream.end())
|
||||
return true;
|
||||
|
||||
auto Root = I->getRoot();
|
||||
if (!Root)
|
||||
return true;
|
||||
|
||||
auto *Map = dyn_cast<llvm::yaml::MappingNode>(Root);
|
||||
if (!Map)
|
||||
return true;
|
||||
|
||||
auto resolvePath =
|
||||
[workingDirectory](
|
||||
llvm::yaml::ScalarNode *Path,
|
||||
llvm::SmallVectorImpl<char> &PathStorage) -> StringRef {
|
||||
StringRef PathStr = Path->getValue(PathStorage);
|
||||
if (workingDirectory.empty() || PathStr.empty() || PathStr == "-" ||
|
||||
llvm::sys::path::is_absolute(PathStr)) {
|
||||
return PathStr;
|
||||
}
|
||||
// Copy the path to avoid making assumptions about how getValue deals with
|
||||
// Storage.
|
||||
SmallString<128> PathStrCopy(PathStr);
|
||||
PathStorage.clear();
|
||||
PathStorage.reserve(PathStrCopy.size() + workingDirectory.size() + 1);
|
||||
PathStorage.insert(PathStorage.begin(), workingDirectory.begin(),
|
||||
workingDirectory.end());
|
||||
llvm::sys::path::append(PathStorage, PathStrCopy);
|
||||
return StringRef(PathStorage.data(), PathStorage.size());
|
||||
};
|
||||
|
||||
for (auto &Pair : *Map) {
|
||||
llvm::yaml::Node *Key = Pair.getKey();
|
||||
llvm::yaml::Node *Value = Pair.getValue();
|
||||
|
||||
if (!Key)
|
||||
return true;
|
||||
|
||||
if (!Value)
|
||||
return true;
|
||||
|
||||
auto *InputPath = dyn_cast<llvm::yaml::ScalarNode>(Key);
|
||||
if (!InputPath)
|
||||
return true;
|
||||
|
||||
llvm::yaml::MappingNode *OutputMapNode =
|
||||
dyn_cast<llvm::yaml::MappingNode>(Value);
|
||||
if (!OutputMapNode)
|
||||
return true;
|
||||
|
||||
TypeToPathMap OutputMap;
|
||||
|
||||
for (auto &OutputPair : *OutputMapNode) {
|
||||
llvm::yaml::Node *Key = OutputPair.getKey();
|
||||
llvm::yaml::Node *Value = OutputPair.getValue();
|
||||
|
||||
auto *KindNode = dyn_cast<llvm::yaml::ScalarNode>(Key);
|
||||
if (!KindNode)
|
||||
return true;
|
||||
|
||||
auto *Path = dyn_cast<llvm::yaml::ScalarNode>(Value);
|
||||
if (!Path)
|
||||
return true;
|
||||
|
||||
llvm::SmallString<16> KindStorage;
|
||||
types::ID Kind =
|
||||
types::lookupTypeForName(KindNode->getValue(KindStorage));
|
||||
|
||||
// Ignore unknown types, so that an older swiftc can be used with a newer
|
||||
// build system.
|
||||
if (Kind == types::TY_INVALID)
|
||||
continue;
|
||||
|
||||
llvm::SmallString<128> PathStorage;
|
||||
OutputMap.insert(std::pair<types::ID, std::string>(
|
||||
Kind, resolvePath(Path, PathStorage)));
|
||||
}
|
||||
|
||||
llvm::SmallString<128> InputStorage;
|
||||
InputToOutputsMap[resolvePath(InputPath, InputStorage)] =
|
||||
std::move(OutputMap);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "swift/Basic/JSONSerialization.h"
|
||||
#include "swift/Driver/Action.h"
|
||||
#include "swift/Driver/Job.h"
|
||||
#include "swift/Driver/Types.h"
|
||||
#include "swift/Frontend/Types.h"
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "swift/Driver/PrettyStackTrace.h"
|
||||
#include "swift/Driver/Action.h"
|
||||
#include "swift/Driver/Job.h"
|
||||
#include "swift/Driver/Types.h"
|
||||
#include "swift/Frontend/Types.h"
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
|
||||
@@ -21,24 +21,23 @@
|
||||
#include "swift/Driver/Compilation.h"
|
||||
#include "swift/Driver/Driver.h"
|
||||
#include "swift/Driver/Job.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/Program.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace swift::driver;
|
||||
using namespace llvm::opt;
|
||||
|
||||
ToolChain::JobContext::JobContext(Compilation &C,
|
||||
ArrayRef<const Job *> Inputs,
|
||||
ToolChain::JobContext::JobContext(Compilation &C, ArrayRef<const Job *> Inputs,
|
||||
ArrayRef<const Action *> InputActions,
|
||||
const CommandOutput &Output,
|
||||
const OutputInfo &OI)
|
||||
: C(C), Inputs(Inputs), InputActions(InputActions), Output(Output),
|
||||
OI(OI), Args(C.getArgs()) {}
|
||||
: C(C), Inputs(Inputs), InputActions(InputActions), Output(Output), OI(OI),
|
||||
Args(C.getArgs()) {}
|
||||
|
||||
ArrayRef<InputPair> ToolChain::JobContext::getTopLevelInputFiles() const {
|
||||
return C.getInputFiles();
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "swift/Basic/Platform.h"
|
||||
#include "swift/Basic/Range.h"
|
||||
#include "swift/Basic/TaskQueue.h"
|
||||
#include "swift/Driver/Compilation.h"
|
||||
#include "swift/Driver/Driver.h"
|
||||
#include "swift/Driver/Job.h"
|
||||
#include "swift/Frontend/Frontend.h"
|
||||
@@ -37,8 +38,41 @@ using namespace swift;
|
||||
using namespace swift::driver;
|
||||
using namespace llvm::opt;
|
||||
|
||||
/// The limit for passing a list of files on the command line.
|
||||
static const size_t TOO_MANY_FILES = 128;
|
||||
bool ToolChain::JobContext::shouldUseInputFileList() const {
|
||||
if (Args.hasArg(options::OPT_driver_use_filelists))
|
||||
return true;
|
||||
return getTopLevelInputFiles().size() > TOO_MANY_FILES;
|
||||
}
|
||||
|
||||
bool ToolChain::JobContext::shouldUsePrimaryInputFileListInFrontendInvocation()
|
||||
const {
|
||||
if (Args.hasArg(options::OPT_driver_use_filelists))
|
||||
return true;
|
||||
return InputActions.size() > TOO_MANY_FILES;
|
||||
}
|
||||
|
||||
bool ToolChain::JobContext::shouldUseMainOutputFileListInFrontendInvocation()
|
||||
const {
|
||||
if (Args.hasArg(options::OPT_driver_use_filelists))
|
||||
return true;
|
||||
return Output.getPrimaryOutputFilenames().size() > TOO_MANY_FILES;
|
||||
}
|
||||
|
||||
bool ToolChain::JobContext::
|
||||
shouldUseSupplementaryOutputFileMapInFrontendInvocation() const {
|
||||
if (Args.hasArg(options::OPT_driver_use_filelists))
|
||||
return true;
|
||||
static const unsigned UpperBoundOnSupplementaryOutputFileTypes =
|
||||
types::TY_INVALID;
|
||||
return InputActions.size() * UpperBoundOnSupplementaryOutputFileTypes >
|
||||
TOO_MANY_FILES;
|
||||
}
|
||||
|
||||
bool ToolChain::JobContext::shouldFilterFrontendInputsByType() const {
|
||||
// FIXME: SingleCompile has not filtered its inputs in the past and now people
|
||||
// rely upon that. But we would like the compilation modes to be consistent.
|
||||
return OI.CompilerMode != OutputInfo::Mode::SingleCompile;
|
||||
}
|
||||
|
||||
static void addInputsOfType(ArgStringList &Arguments,
|
||||
ArrayRef<const Action *> Inputs,
|
||||
@@ -214,19 +248,10 @@ static void addCommonFrontendArgs(const ToolChain &TC,
|
||||
inputArgs.AddAllArgs(arguments, options::OPT_Xllvm);
|
||||
inputArgs.AddAllArgs(arguments, options::OPT_Xcc);
|
||||
|
||||
addOutputsOfType(arguments, output, inputArgs,
|
||||
types::TY_SwiftModuleDocFile,
|
||||
"-emit-module-doc-path");
|
||||
|
||||
if (llvm::sys::Process::StandardErrHasColors())
|
||||
arguments.push_back("-color-diagnostics");
|
||||
|
||||
addOutputsOfType(arguments, output, inputArgs,
|
||||
types::TY_SerializedDiagnostics,
|
||||
"-serialize-diagnostics-path");
|
||||
}
|
||||
|
||||
|
||||
ToolChain::InvocationInfo
|
||||
ToolChain::constructInvocation(const CompileJobAction &job,
|
||||
const JobContext &context) const {
|
||||
@@ -235,164 +260,15 @@ ToolChain::constructInvocation(const CompileJobAction &job,
|
||||
|
||||
Arguments.push_back("-frontend");
|
||||
|
||||
// Determine the frontend mode option.
|
||||
const char *FrontendModeOption = nullptr;
|
||||
switch (context.OI.CompilerMode) {
|
||||
case OutputInfo::Mode::StandardCompile:
|
||||
case OutputInfo::Mode::SingleCompile:
|
||||
case OutputInfo::Mode::BatchModeCompile: {
|
||||
switch (context.Output.getPrimaryOutputType()) {
|
||||
case types::TY_Object:
|
||||
FrontendModeOption = "-c";
|
||||
break;
|
||||
case types::TY_PCH:
|
||||
FrontendModeOption = "-emit-pch";
|
||||
break;
|
||||
case types::TY_RawSIL:
|
||||
FrontendModeOption = "-emit-silgen";
|
||||
break;
|
||||
case types::TY_SIL:
|
||||
FrontendModeOption = "-emit-sil";
|
||||
break;
|
||||
case types::TY_RawSIB:
|
||||
FrontendModeOption = "-emit-sibgen";
|
||||
break;
|
||||
case types::TY_SIB:
|
||||
FrontendModeOption = "-emit-sib";
|
||||
break;
|
||||
case types::TY_LLVM_IR:
|
||||
FrontendModeOption = "-emit-ir";
|
||||
break;
|
||||
case types::TY_LLVM_BC:
|
||||
FrontendModeOption = "-emit-bc";
|
||||
break;
|
||||
case types::TY_Assembly:
|
||||
FrontendModeOption = "-S";
|
||||
break;
|
||||
case types::TY_SwiftModuleFile:
|
||||
// Since this is our primary output, we need to specify the option here.
|
||||
FrontendModeOption = "-emit-module";
|
||||
break;
|
||||
case types::TY_ImportedModules:
|
||||
FrontendModeOption = "-emit-imported-modules";
|
||||
break;
|
||||
case types::TY_IndexData:
|
||||
FrontendModeOption = "-typecheck";
|
||||
break;
|
||||
case types::TY_Remapping:
|
||||
FrontendModeOption = "-update-code";
|
||||
break;
|
||||
case types::TY_Nothing:
|
||||
// We were told to output nothing, so get the last mode option and use that.
|
||||
if (const Arg *A = context.Args.getLastArg(options::OPT_modes_Group))
|
||||
FrontendModeOption = A->getSpelling().data();
|
||||
else
|
||||
llvm_unreachable("We were told to perform a standard compile, "
|
||||
"but no mode option was passed to the driver.");
|
||||
break;
|
||||
case types::TY_Swift:
|
||||
case types::TY_dSYM:
|
||||
case types::TY_AutolinkFile:
|
||||
case types::TY_Dependencies:
|
||||
case types::TY_SwiftModuleDocFile:
|
||||
case types::TY_ClangModuleFile:
|
||||
case types::TY_SerializedDiagnostics:
|
||||
case types::TY_ObjCHeader:
|
||||
case types::TY_Image:
|
||||
case types::TY_SwiftDeps:
|
||||
case types::TY_ModuleTrace:
|
||||
case types::TY_TBD:
|
||||
case types::TY_OptRecord:
|
||||
llvm_unreachable("Output type can never be primary output.");
|
||||
case types::TY_INVALID:
|
||||
llvm_unreachable("Invalid type ID");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OutputInfo::Mode::Immediate:
|
||||
case OutputInfo::Mode::REPL:
|
||||
llvm_unreachable("REPL and immediate modes handled elsewhere");
|
||||
{
|
||||
// Determine the frontend mode option.
|
||||
const char *FrontendModeOption = context.computeFrontendModeForCompile();
|
||||
assert(FrontendModeOption != nullptr &&
|
||||
"No frontend mode option specified!");
|
||||
Arguments.push_back(FrontendModeOption);
|
||||
}
|
||||
|
||||
assert(FrontendModeOption != nullptr && "No frontend mode option specified!");
|
||||
|
||||
Arguments.push_back(FrontendModeOption);
|
||||
|
||||
// Add input arguments.
|
||||
switch (context.OI.CompilerMode) {
|
||||
case OutputInfo::Mode::StandardCompile:
|
||||
assert(context.InputActions.size() == 1 &&
|
||||
"Standard-compile mode takes exactly one input (the primary file)");
|
||||
LLVM_FALLTHROUGH;
|
||||
case OutputInfo::Mode::BatchModeCompile: {
|
||||
bool UseFileList =
|
||||
(context.Args.hasArg(options::OPT_driver_use_filelists) ||
|
||||
context.getTopLevelInputFiles().size() > TOO_MANY_FILES);
|
||||
bool UsePrimaryFileList =
|
||||
((context.OI.CompilerMode == OutputInfo::Mode::BatchModeCompile) &&
|
||||
(context.Args.hasArg(options::OPT_driver_use_filelists) ||
|
||||
context.InputActions.size() > TOO_MANY_FILES));
|
||||
if (UseFileList) {
|
||||
Arguments.push_back("-filelist");
|
||||
Arguments.push_back(context.getAllSourcesPath());
|
||||
}
|
||||
if (UsePrimaryFileList) {
|
||||
Arguments.push_back("-primary-filelist");
|
||||
Arguments.push_back(context.getTemporaryFilePath("primaryInputs", ""));
|
||||
II.FilelistInfos.push_back({Arguments.back(), types::TY_Swift,
|
||||
FilelistInfo::WhichFiles::PrimaryInputs});
|
||||
}
|
||||
if (!UseFileList || !UsePrimaryFileList) {
|
||||
llvm::StringSet<> primaries;
|
||||
for (const Action *A : context.InputActions) {
|
||||
const auto *IA = cast<InputAction>(A);
|
||||
primaries.insert(IA->getInputArg().getValue());
|
||||
}
|
||||
for (auto inputPair : context.getTopLevelInputFiles()) {
|
||||
if (!types::isPartOfSwiftCompilation(inputPair.first))
|
||||
continue;
|
||||
const char *inputName = inputPair.second->getValue();
|
||||
if (primaries.count(inputName)) {
|
||||
if (!UsePrimaryFileList) {
|
||||
Arguments.push_back("-primary-file");
|
||||
Arguments.push_back(inputName);
|
||||
}
|
||||
} else {
|
||||
if (!UseFileList) {
|
||||
Arguments.push_back(inputName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OutputInfo::Mode::SingleCompile: {
|
||||
StringRef PrimaryFileWrittenToCommandLine;
|
||||
if (context.Output.getPrimaryOutputType() == types::TY_IndexData) {
|
||||
if (Arg *A = context.Args.getLastArg(options::OPT_index_file_path)) {
|
||||
Arguments.push_back("-primary-file");
|
||||
Arguments.push_back(A->getValue());
|
||||
PrimaryFileWrittenToCommandLine = A->getValue();
|
||||
}
|
||||
}
|
||||
if (context.Args.hasArg(options::OPT_driver_use_filelists) ||
|
||||
context.InputActions.size() > TOO_MANY_FILES) {
|
||||
Arguments.push_back("-filelist");
|
||||
Arguments.push_back(context.getAllSourcesPath());
|
||||
} else {
|
||||
for (const Action *A : context.InputActions) {
|
||||
const Arg &InputArg = cast<InputAction>(A)->getInputArg();
|
||||
// Frontend no longer tolerates redundant input files on command line.
|
||||
if (InputArg.getValue() != PrimaryFileWrittenToCommandLine)
|
||||
InputArg.render(context.Args, Arguments);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OutputInfo::Mode::Immediate:
|
||||
case OutputInfo::Mode::REPL:
|
||||
llvm_unreachable("REPL and immediate modes handled elsewhere");
|
||||
}
|
||||
context.addFrontendInputAndOutputArguments(Arguments, II.FilelistInfos);
|
||||
|
||||
// Forward migrator flags.
|
||||
if (auto DataPath = context.Args.getLastArg(options::
|
||||
@@ -453,33 +329,6 @@ ToolChain::constructInvocation(const CompileJobAction &job,
|
||||
Arguments.push_back("-module-name");
|
||||
Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName));
|
||||
|
||||
addOutputsOfType(Arguments, context.Output, context.Args,
|
||||
types::ID::TY_SwiftModuleFile,
|
||||
"-emit-module-path");
|
||||
|
||||
if (addOutputsOfType(Arguments, context.Output, context.Args,
|
||||
types::ID::TY_ObjCHeader, "-emit-objc-header-path")) {
|
||||
assert(context.OI.CompilerMode == OutputInfo::Mode::SingleCompile &&
|
||||
"The Swift tool should only emit an Obj-C header in single compile"
|
||||
"mode!");
|
||||
}
|
||||
|
||||
addOutputsOfType(Arguments, context.Output, context.Args,
|
||||
types::TY_Dependencies,
|
||||
"-emit-dependencies-path");
|
||||
|
||||
addOutputsOfType(Arguments, context.Output, context.Args,
|
||||
types::TY_SwiftDeps,
|
||||
"-emit-reference-dependencies-path");
|
||||
|
||||
addOutputsOfType(Arguments, context.Output, context.Args,
|
||||
types::TY_ModuleTrace,
|
||||
"-emit-loaded-module-trace-path");
|
||||
|
||||
addOutputsOfType(Arguments, context.Output, context.Args,
|
||||
types::TY_TBD,
|
||||
"-emit-tbd-path");
|
||||
|
||||
addOutputsOfType(Arguments, context.Output, context.Args,
|
||||
types::TY_OptRecord,
|
||||
"-save-optimization-record-path");
|
||||
@@ -500,8 +349,7 @@ ToolChain::constructInvocation(const CompileJobAction &job,
|
||||
|
||||
// Add the output file argument if necessary.
|
||||
if (context.Output.getPrimaryOutputType() != types::TY_Nothing) {
|
||||
if (context.Args.hasArg(options::OPT_driver_use_filelists) ||
|
||||
context.Output.getPrimaryOutputFilenames().size() > TOO_MANY_FILES) {
|
||||
if (context.shouldUseMainOutputFileListInFrontendInvocation()) {
|
||||
Arguments.push_back("-output-filelist");
|
||||
Arguments.push_back(context.getTemporaryFilePath("outputs", ""));
|
||||
II.FilelistInfos.push_back({Arguments.back(),
|
||||
@@ -526,6 +374,185 @@ ToolChain::constructInvocation(const CompileJobAction &job,
|
||||
return II;
|
||||
}
|
||||
|
||||
const char *ToolChain::JobContext::computeFrontendModeForCompile() const {
|
||||
switch (OI.CompilerMode) {
|
||||
case OutputInfo::Mode::StandardCompile:
|
||||
case OutputInfo::Mode::SingleCompile:
|
||||
case OutputInfo::Mode::BatchModeCompile:
|
||||
break;
|
||||
case OutputInfo::Mode::Immediate:
|
||||
case OutputInfo::Mode::REPL:
|
||||
llvm_unreachable("REPL and immediate modes handled elsewhere");
|
||||
}
|
||||
switch (Output.getPrimaryOutputType()) {
|
||||
case types::TY_Object:
|
||||
return "-c";
|
||||
case types::TY_PCH:
|
||||
return "-emit-pch";
|
||||
case types::TY_RawSIL:
|
||||
return "-emit-silgen";
|
||||
case types::TY_SIL:
|
||||
return "-emit-sil";
|
||||
case types::TY_RawSIB:
|
||||
return "-emit-sibgen";
|
||||
case types::TY_SIB:
|
||||
return "-emit-sib";
|
||||
case types::TY_LLVM_IR:
|
||||
return "-emit-ir";
|
||||
case types::TY_LLVM_BC:
|
||||
return "-emit-bc";
|
||||
case types::TY_Assembly:
|
||||
return "-S";
|
||||
case types::TY_SwiftModuleFile:
|
||||
// Since this is our primary output, we need to specify the option here.
|
||||
return "-emit-module";
|
||||
case types::TY_ImportedModules:
|
||||
return "-emit-imported-modules";
|
||||
case types::TY_IndexData:
|
||||
return "-typecheck";
|
||||
case types::TY_Remapping:
|
||||
return "-update-code";
|
||||
case types::TY_Nothing:
|
||||
// We were told to output nothing, so get the last mode option and use that.
|
||||
if (const Arg *A = Args.getLastArg(options::OPT_modes_Group))
|
||||
return A->getSpelling().data();
|
||||
else
|
||||
llvm_unreachable("We were told to perform a standard compile, "
|
||||
"but no mode option was passed to the driver.");
|
||||
case types::TY_Swift:
|
||||
case types::TY_dSYM:
|
||||
case types::TY_AutolinkFile:
|
||||
case types::TY_Dependencies:
|
||||
case types::TY_SwiftModuleDocFile:
|
||||
case types::TY_ClangModuleFile:
|
||||
case types::TY_SerializedDiagnostics:
|
||||
case types::TY_ObjCHeader:
|
||||
case types::TY_Image:
|
||||
case types::TY_SwiftDeps:
|
||||
case types::TY_ModuleTrace:
|
||||
case types::TY_TBD:
|
||||
case types::TY_OptRecord:
|
||||
llvm_unreachable("Output type can never be primary output.");
|
||||
case types::TY_INVALID:
|
||||
llvm_unreachable("Invalid type ID");
|
||||
}
|
||||
}
|
||||
|
||||
void ToolChain::JobContext::addFrontendInputAndOutputArguments(
|
||||
ArgStringList &Arguments, std::vector<FilelistInfo> &FilelistInfos) const {
|
||||
|
||||
switch (OI.CompilerMode) {
|
||||
case OutputInfo::Mode::StandardCompile:
|
||||
assert(InputActions.size() == 1 &&
|
||||
"Standard-compile mode takes exactly one input (the primary file)");
|
||||
break;
|
||||
case OutputInfo::Mode::BatchModeCompile:
|
||||
case OutputInfo::Mode::SingleCompile:
|
||||
break;
|
||||
case OutputInfo::Mode::Immediate:
|
||||
case OutputInfo::Mode::REPL:
|
||||
llvm_unreachable("REPL and immediate modes handled elsewhere");
|
||||
}
|
||||
|
||||
const bool UseFileList = shouldUseInputFileList();
|
||||
const bool MayHavePrimaryInputs = OI.mightHaveExplicitPrimaryInputs(Output);
|
||||
const bool UsePrimaryFileList =
|
||||
MayHavePrimaryInputs &&
|
||||
shouldUsePrimaryInputFileListInFrontendInvocation();
|
||||
const bool FilterInputsByType = shouldFilterFrontendInputsByType();
|
||||
const bool UseSupplementaryOutputFileList =
|
||||
shouldUseSupplementaryOutputFileMapInFrontendInvocation();
|
||||
|
||||
if (UseFileList) {
|
||||
Arguments.push_back("-filelist");
|
||||
Arguments.push_back(getAllSourcesPath());
|
||||
}
|
||||
if (UsePrimaryFileList) {
|
||||
Arguments.push_back("-primary-filelist");
|
||||
Arguments.push_back(getTemporaryFilePath("primaryInputs", ""));
|
||||
FilelistInfos.push_back({Arguments.back(), types::TY_Swift,
|
||||
FilelistInfo::WhichFiles::PrimaryInputs});
|
||||
}
|
||||
if (!UseFileList || !UsePrimaryFileList) {
|
||||
addFrontendCommandLineInputArguments(MayHavePrimaryInputs, UseFileList,
|
||||
UsePrimaryFileList, FilterInputsByType,
|
||||
Arguments);
|
||||
}
|
||||
|
||||
if (UseSupplementaryOutputFileList) {
|
||||
Arguments.push_back("-supplementary-output-file-map");
|
||||
Arguments.push_back(getTemporaryFilePath("supplementaryOutputs", ""));
|
||||
FilelistInfos.push_back({Arguments.back(), types::TY_INVALID,
|
||||
FilelistInfo::WhichFiles::SupplementaryOutput});
|
||||
} else {
|
||||
addFrontendSupplementaryOutputArguments(Arguments);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolChain::JobContext::addFrontendCommandLineInputArguments(
|
||||
const bool mayHavePrimaryInputs, const bool useFileList,
|
||||
const bool usePrimaryFileList, const bool filterByType,
|
||||
ArgStringList &arguments) const {
|
||||
llvm::StringSet<> primaries;
|
||||
|
||||
if (mayHavePrimaryInputs) {
|
||||
for (const Action *A : InputActions) {
|
||||
const auto *IA = cast<InputAction>(A);
|
||||
const llvm::opt::Arg &InArg = IA->getInputArg();
|
||||
primaries.insert(InArg.getValue());
|
||||
}
|
||||
}
|
||||
// -index-file compilations are weird. They are processed as SingleCompiles
|
||||
// (WMO), but must indicate that there is one primary file, designated by
|
||||
// -index-file-path.
|
||||
if (Arg *A = Args.getLastArg(options::OPT_index_file_path)) {
|
||||
assert(primaries.empty() &&
|
||||
"index file jobs should be treated as single (WMO) compiles");
|
||||
primaries.insert(A->getValue());
|
||||
}
|
||||
for (auto inputPair : getTopLevelInputFiles()) {
|
||||
if (filterByType && !types::isPartOfSwiftCompilation(inputPair.first))
|
||||
continue;
|
||||
const char *inputName = inputPair.second->getValue();
|
||||
const bool isPrimary = primaries.count(inputName);
|
||||
if (isPrimary && !usePrimaryFileList) {
|
||||
arguments.push_back("-primary-file");
|
||||
arguments.push_back(inputName);
|
||||
}
|
||||
if ((!isPrimary || usePrimaryFileList) && !useFileList)
|
||||
arguments.push_back(inputName);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolChain::JobContext::addFrontendSupplementaryOutputArguments(
|
||||
ArgStringList &arguments) const {
|
||||
// FIXME: Get these and other argument strings from the same place for both
|
||||
// driver and frontend.
|
||||
addOutputsOfType(arguments, Output, Args, types::ID::TY_SwiftModuleFile,
|
||||
"-emit-module-path");
|
||||
|
||||
addOutputsOfType(arguments, Output, Args, types::TY_SwiftModuleDocFile,
|
||||
"-emit-module-doc-path");
|
||||
|
||||
addOutputsOfType(arguments, Output, Args, types::TY_SerializedDiagnostics,
|
||||
"-serialize-diagnostics-path");
|
||||
|
||||
if (addOutputsOfType(arguments, Output, Args, types::ID::TY_ObjCHeader,
|
||||
"-emit-objc-header-path")) {
|
||||
assert(OI.CompilerMode == OutputInfo::Mode::SingleCompile &&
|
||||
"The Swift tool should only emit an Obj-C header in single compile"
|
||||
"mode!");
|
||||
}
|
||||
|
||||
addOutputsOfType(arguments, Output, Args, types::TY_Dependencies,
|
||||
"-emit-dependencies-path");
|
||||
addOutputsOfType(arguments, Output, Args, types::TY_SwiftDeps,
|
||||
"-emit-reference-dependencies-path");
|
||||
addOutputsOfType(arguments, Output, Args, types::TY_ModuleTrace,
|
||||
"-emit-loaded-module-trace-path");
|
||||
addOutputsOfType(arguments, Output, Args, types::TY_TBD, "-emit-tbd-path");
|
||||
}
|
||||
|
||||
ToolChain::InvocationInfo
|
||||
ToolChain::constructInvocation(const InterpretJobAction &job,
|
||||
const JobContext &context) const {
|
||||
@@ -711,8 +738,7 @@ ToolChain::constructInvocation(const MergeModuleJobAction &job,
|
||||
Arguments.push_back("-merge-modules");
|
||||
Arguments.push_back("-emit-module");
|
||||
|
||||
if (context.Args.hasArg(options::OPT_driver_use_filelists) ||
|
||||
context.Inputs.size() > TOO_MANY_FILES) {
|
||||
if (context.shouldUseInputFileList()) {
|
||||
Arguments.push_back("-filelist");
|
||||
Arguments.push_back(context.getTemporaryFilePath("inputs", ""));
|
||||
II.FilelistInfos.push_back({Arguments.back(), types::TY_SwiftModuleFile,
|
||||
@@ -747,6 +773,14 @@ ToolChain::constructInvocation(const MergeModuleJobAction &job,
|
||||
|
||||
addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
|
||||
Arguments);
|
||||
addOutputsOfType(Arguments, context.Output, context.Args,
|
||||
types::TY_SwiftModuleDocFile, "-emit-module-doc-path");
|
||||
addOutputsOfType(Arguments, context.Output, context.Args,
|
||||
types::TY_SerializedDiagnostics,
|
||||
"-serialize-diagnostics-path");
|
||||
addOutputsOfType(Arguments, context.Output, context.Args,
|
||||
types::TY_ObjCHeader, "-emit-objc-header-path");
|
||||
|
||||
context.Args.AddLastArg(Arguments, options::OPT_import_objc_header);
|
||||
|
||||
Arguments.push_back("-module-name");
|
||||
@@ -755,13 +789,6 @@ ToolChain::constructInvocation(const MergeModuleJobAction &job,
|
||||
assert(context.Output.getPrimaryOutputType() == types::TY_SwiftModuleFile &&
|
||||
"The MergeModule tool only produces swiftmodule files!");
|
||||
|
||||
auto ObjCHeaderOutputPath =
|
||||
context.Output.getAdditionalOutputForType(types::TY_ObjCHeader);
|
||||
if (!ObjCHeaderOutputPath.empty()) {
|
||||
Arguments.push_back("-emit-objc-header-path");
|
||||
Arguments.push_back(
|
||||
context.Args.MakeArgString(ObjCHeaderOutputPath));
|
||||
}
|
||||
|
||||
Arguments.push_back("-o");
|
||||
Arguments.push_back(context.Args.MakeArgString(
|
||||
@@ -899,6 +926,9 @@ ToolChain::constructInvocation(const GeneratePCHJobAction &job,
|
||||
|
||||
addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
|
||||
Arguments);
|
||||
addOutputsOfType(Arguments, context.Output, context.Args,
|
||||
types::TY_SerializedDiagnostics,
|
||||
"-serialize-diagnostics-path");
|
||||
|
||||
addInputsOfType(Arguments, context.InputActions, types::TY_ObjCHeader);
|
||||
context.Args.AddLastArg(Arguments, options::OPT_index_store_path);
|
||||
@@ -1267,8 +1297,7 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job,
|
||||
InvocationInfo II = {LD};
|
||||
ArgStringList &Arguments = II.Arguments;
|
||||
|
||||
if (context.Args.hasArg(options::OPT_driver_use_filelists) ||
|
||||
context.Inputs.size() > TOO_MANY_FILES) {
|
||||
if (context.shouldUseInputFileList()) {
|
||||
Arguments.push_back("-filelist");
|
||||
Arguments.push_back(context.getTemporaryFilePath("inputs", "LinkFileList"));
|
||||
II.FilelistInfos.push_back(
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
//===--- Types.cpp - Driver input & temporary type information ------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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/Driver/Types.h"
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace swift::driver;
|
||||
using namespace swift::driver::types;
|
||||
|
||||
struct TypeInfo {
|
||||
const char *Name;
|
||||
const char *Flags;
|
||||
const char *TempSuffix;
|
||||
};
|
||||
|
||||
static const TypeInfo TypeInfos[] = {
|
||||
#define TYPE(NAME, ID, TEMP_SUFFIX, FLAGS) \
|
||||
{ NAME, FLAGS, TEMP_SUFFIX },
|
||||
#include "swift/Driver/Types.def"
|
||||
};
|
||||
|
||||
static const TypeInfo &getInfo(unsigned Id) {
|
||||
assert(Id >= 0 && Id < TY_INVALID && "Invalid Type ID.");
|
||||
return TypeInfos[Id];
|
||||
}
|
||||
|
||||
StringRef types::getTypeName(ID Id) {
|
||||
return getInfo(Id).Name;
|
||||
}
|
||||
|
||||
StringRef types::getTypeTempSuffix(ID Id) {
|
||||
return getInfo(Id).TempSuffix;
|
||||
}
|
||||
|
||||
ID types::lookupTypeForExtension(StringRef Ext) {
|
||||
if (Ext.empty())
|
||||
return TY_INVALID;
|
||||
assert(Ext.front() == '.' && "not a file extension");
|
||||
return llvm::StringSwitch<types::ID>(Ext.drop_front())
|
||||
#define TYPE(NAME, ID, SUFFIX, FLAGS) \
|
||||
.Case(SUFFIX, TY_##ID)
|
||||
#include "swift/Driver/Types.def"
|
||||
.Default(TY_INVALID);
|
||||
}
|
||||
|
||||
ID types::lookupTypeForName(StringRef Name) {
|
||||
return llvm::StringSwitch<types::ID>(Name)
|
||||
#define TYPE(NAME, ID, SUFFIX, FLAGS) \
|
||||
.Case(NAME, TY_##ID)
|
||||
#include "swift/Driver/Types.def"
|
||||
.Default(TY_INVALID);
|
||||
}
|
||||
|
||||
bool types::isTextual(ID Id) {
|
||||
switch (Id) {
|
||||
case types::TY_Swift:
|
||||
case types::TY_SIL:
|
||||
case types::TY_Dependencies:
|
||||
case types::TY_Assembly:
|
||||
case types::TY_RawSIL:
|
||||
case types::TY_LLVM_IR:
|
||||
case types::TY_ObjCHeader:
|
||||
case types::TY_AutolinkFile:
|
||||
case types::TY_ImportedModules:
|
||||
case types::TY_TBD:
|
||||
case types::TY_ModuleTrace:
|
||||
case types::TY_OptRecord:
|
||||
return true;
|
||||
case types::TY_Image:
|
||||
case types::TY_Object:
|
||||
case types::TY_dSYM:
|
||||
case types::TY_PCH:
|
||||
case types::TY_SIB:
|
||||
case types::TY_RawSIB:
|
||||
case types::TY_SwiftModuleFile:
|
||||
case types::TY_SwiftModuleDocFile:
|
||||
case types::TY_LLVM_BC:
|
||||
case types::TY_SerializedDiagnostics:
|
||||
case types::TY_ClangModuleFile:
|
||||
case types::TY_SwiftDeps:
|
||||
case types::TY_Nothing:
|
||||
case types::TY_Remapping:
|
||||
case types::TY_IndexData:
|
||||
return false;
|
||||
case types::TY_INVALID:
|
||||
llvm_unreachable("Invalid type ID.");
|
||||
}
|
||||
|
||||
// Work around MSVC warning: not all control paths return a value
|
||||
llvm_unreachable("All switch cases are covered");
|
||||
}
|
||||
|
||||
bool types::isAfterLLVM(ID Id) {
|
||||
switch (Id) {
|
||||
case types::TY_Assembly:
|
||||
case types::TY_LLVM_IR:
|
||||
case types::TY_LLVM_BC:
|
||||
case types::TY_Object:
|
||||
return true;
|
||||
case types::TY_Swift:
|
||||
case types::TY_PCH:
|
||||
case types::TY_ImportedModules:
|
||||
case types::TY_TBD:
|
||||
case types::TY_SIL:
|
||||
case types::TY_Dependencies:
|
||||
case types::TY_RawSIL:
|
||||
case types::TY_ObjCHeader:
|
||||
case types::TY_AutolinkFile:
|
||||
case types::TY_Image:
|
||||
case types::TY_dSYM:
|
||||
case types::TY_SIB:
|
||||
case types::TY_RawSIB:
|
||||
case types::TY_SwiftModuleFile:
|
||||
case types::TY_SwiftModuleDocFile:
|
||||
case types::TY_SerializedDiagnostics:
|
||||
case types::TY_ClangModuleFile:
|
||||
case types::TY_SwiftDeps:
|
||||
case types::TY_Nothing:
|
||||
case types::TY_Remapping:
|
||||
case types::TY_IndexData:
|
||||
case types::TY_ModuleTrace:
|
||||
case types::TY_OptRecord:
|
||||
return false;
|
||||
case types::TY_INVALID:
|
||||
llvm_unreachable("Invalid type ID.");
|
||||
}
|
||||
|
||||
// Work around MSVC warning: not all control paths return a value
|
||||
llvm_unreachable("All switch cases are covered");
|
||||
}
|
||||
|
||||
bool types::isPartOfSwiftCompilation(ID Id) {
|
||||
switch (Id) {
|
||||
case types::TY_Swift:
|
||||
case types::TY_SIL:
|
||||
case types::TY_RawSIL:
|
||||
case types::TY_SIB:
|
||||
case types::TY_RawSIB:
|
||||
return true;
|
||||
case types::TY_Assembly:
|
||||
case types::TY_LLVM_IR:
|
||||
case types::TY_LLVM_BC:
|
||||
case types::TY_Object:
|
||||
case types::TY_Dependencies:
|
||||
case types::TY_ObjCHeader:
|
||||
case types::TY_AutolinkFile:
|
||||
case types::TY_PCH:
|
||||
case types::TY_ImportedModules:
|
||||
case types::TY_TBD:
|
||||
case types::TY_Image:
|
||||
case types::TY_dSYM:
|
||||
case types::TY_SwiftModuleFile:
|
||||
case types::TY_SwiftModuleDocFile:
|
||||
case types::TY_SerializedDiagnostics:
|
||||
case types::TY_ClangModuleFile:
|
||||
case types::TY_SwiftDeps:
|
||||
case types::TY_Nothing:
|
||||
case types::TY_Remapping:
|
||||
case types::TY_IndexData:
|
||||
case types::TY_ModuleTrace:
|
||||
case types::TY_OptRecord:
|
||||
return false;
|
||||
case types::TY_INVALID:
|
||||
llvm_unreachable("Invalid type ID.");
|
||||
}
|
||||
|
||||
// Work around MSVC warning: not all control paths return a value
|
||||
llvm_unreachable("All switch cases are covered");
|
||||
}
|
||||
Reference in New Issue
Block a user