mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Unify actionHasOutput w/ doesActionProduceOutput & correct both. Do not set an output filename if there is no output. Add test to ensure no output is created in immediate mode. Restore NFC module name computation.
471 lines
14 KiB
C++
471 lines
14 KiB
C++
//===--- FrontendOptions.cpp ----------------------------------------------===//
|
|
//
|
|
// 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/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;
|
|
|
|
bool FrontendInputs::shouldTreatAsLLVM() const {
|
|
if (hasUniqueInputFilename()) {
|
|
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 (hasUniqueInputFilename()) {
|
|
// 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.
|
|
if (const Optional<StringRef> filename =
|
|
getOptionalUniquePrimaryInputFilename()) {
|
|
return llvm::sys::path::extension(filename.getValue())
|
|
.endswith(SIL_EXTENSION);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool FrontendInputs::verifyInputs(DiagnosticEngine &diags, bool treatAsSIL,
|
|
bool isREPLRequested,
|
|
bool isNoneRequested) const {
|
|
if (isREPLRequested) {
|
|
if (hasInputFilenames()) {
|
|
diags.diagnose(SourceLoc(), diag::error_repl_requires_no_input_files);
|
|
return true;
|
|
}
|
|
} else if (treatAsSIL && hasPrimaryInputs()) {
|
|
// 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.
|
|
for (unsigned i = 0, e = inputFilenameCount(); i != e; ++i) {
|
|
if (i == getOptionalUniquePrimaryInput()->Index)
|
|
continue;
|
|
|
|
StringRef file(getInputFilenames()[i]);
|
|
if (!llvm::sys::path::extension(file).endswith(SIB_EXTENSION)) {
|
|
diags.diagnose(SourceLoc(),
|
|
diag::error_mode_requires_one_sil_multi_sib);
|
|
return true;
|
|
}
|
|
}
|
|
} else if (treatAsSIL) {
|
|
if (!hasUniqueInputFilename()) {
|
|
diags.diagnose(SourceLoc(), diag::error_mode_requires_one_input_file);
|
|
return true;
|
|
}
|
|
} else if (!isNoneRequested) {
|
|
if (!hasInputFilenames()) {
|
|
diags.diagnose(SourceLoc(), diag::error_mode_requires_an_input_file);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void FrontendInputs::transformInputFilenames(
|
|
const llvm::function_ref<std::string(std::string)> &fn) {
|
|
for (auto &InputFile : InputFilenames) {
|
|
InputFile = fn(InputFile);
|
|
}
|
|
}
|
|
|
|
bool FrontendOptions::doesActionImplyMainModule(ActionType action) {
|
|
switch (action) {
|
|
case ActionType::NoneAction:
|
|
case ActionType::Parse:
|
|
case ActionType::Typecheck:
|
|
case ActionType::DumpParse:
|
|
case ActionType::DumpAST:
|
|
case ActionType::EmitSyntax:
|
|
case ActionType::DumpInterfaceHash:
|
|
case ActionType::PrintAST:
|
|
case ActionType::DumpScopeMaps:
|
|
case ActionType::DumpTypeRefinementContexts:
|
|
return true;
|
|
case ActionType::EmitPCH:
|
|
case ActionType::EmitSILGen:
|
|
case ActionType::EmitSIL:
|
|
case ActionType::EmitSIBGen:
|
|
case ActionType::EmitSIB:
|
|
case ActionType::EmitModuleOnly:
|
|
case ActionType::MergeModules:
|
|
return false;
|
|
case ActionType::Immediate:
|
|
case ActionType::REPL:
|
|
return true;
|
|
case ActionType::EmitAssembly:
|
|
case ActionType::EmitIR:
|
|
case ActionType::EmitBC:
|
|
case ActionType::EmitObject:
|
|
case ActionType::EmitImportedModules:
|
|
return false;
|
|
}
|
|
llvm_unreachable("Unknown ActionType");
|
|
}
|
|
|
|
bool FrontendOptions::actionIsImmediate() const {
|
|
switch (RequestedAction) {
|
|
case ActionType::NoneAction:
|
|
case ActionType::Parse:
|
|
case ActionType::Typecheck:
|
|
case ActionType::DumpParse:
|
|
case ActionType::DumpAST:
|
|
case ActionType::EmitSyntax:
|
|
case ActionType::DumpInterfaceHash:
|
|
case ActionType::PrintAST:
|
|
case ActionType::DumpScopeMaps:
|
|
case ActionType::DumpTypeRefinementContexts:
|
|
case ActionType::EmitPCH:
|
|
case ActionType::EmitSILGen:
|
|
case ActionType::EmitSIL:
|
|
case ActionType::EmitSIBGen:
|
|
case ActionType::EmitSIB:
|
|
case ActionType::EmitModuleOnly:
|
|
case ActionType::MergeModules:
|
|
return false;
|
|
case ActionType::Immediate:
|
|
case ActionType::REPL:
|
|
return true;
|
|
case ActionType::EmitAssembly:
|
|
case ActionType::EmitIR:
|
|
case ActionType::EmitBC:
|
|
case ActionType::EmitObject:
|
|
case ActionType::EmitImportedModules:
|
|
return false;
|
|
}
|
|
llvm_unreachable("Unknown ActionType");
|
|
}
|
|
|
|
void FrontendOptions::forAllOutputPaths(
|
|
std::function<void(const std::string &)> fn) const {
|
|
if (RequestedAction != FrontendOptions::ActionType::EmitModuleOnly &&
|
|
RequestedAction != FrontendOptions::ActionType::MergeModules) {
|
|
for (const std::string &OutputFileName : OutputFilenames) {
|
|
fn(OutputFileName);
|
|
}
|
|
}
|
|
const std::string *outputs[] = {
|
|
&ModuleOutputPath,
|
|
&ModuleDocOutputPath,
|
|
&ObjCHeaderOutputPath
|
|
};
|
|
for (const std::string *next : outputs) {
|
|
if (!next->empty())
|
|
fn(*next);
|
|
}
|
|
}
|
|
|
|
|
|
StringRef FrontendOptions::originalPath() const {
|
|
if (hasNamedOutputFile())
|
|
// Put the serialized diagnostics file next to the output file.
|
|
return getSingleOutputFilename();
|
|
|
|
StringRef fn = Inputs.primaryInputFilenameIfAny();
|
|
// If we have a primary input, so use that as the basis for the name of the
|
|
// serialized diagnostics file, otherwise fall back on the
|
|
// module name.
|
|
return !fn.empty() ? llvm::sys::path::filename(fn) : StringRef(ModuleName);
|
|
}
|
|
|
|
bool FrontendOptions::isOutputFileDirectory() const {
|
|
return hasNamedOutputFile() &&
|
|
llvm::sys::fs::is_directory(getSingleOutputFilename());
|
|
}
|
|
|
|
const char *
|
|
FrontendOptions::suffixForPrincipalOutputFileForAction(ActionType action) {
|
|
switch (action) {
|
|
case ActionType::NoneAction:
|
|
return nullptr;
|
|
|
|
case ActionType::Parse:
|
|
case ActionType::Typecheck:
|
|
case ActionType::DumpParse:
|
|
case ActionType::DumpInterfaceHash:
|
|
case ActionType::DumpAST:
|
|
case ActionType::EmitSyntax:
|
|
case ActionType::PrintAST:
|
|
case ActionType::DumpScopeMaps:
|
|
case ActionType::DumpTypeRefinementContexts:
|
|
return nullptr;
|
|
|
|
case ActionType::EmitPCH:
|
|
return PCH_EXTENSION;
|
|
|
|
case ActionType::EmitSILGen:
|
|
case ActionType::EmitSIL:
|
|
return SIL_EXTENSION;
|
|
|
|
case ActionType::EmitSIBGen:
|
|
case ActionType::EmitSIB:
|
|
return SIB_EXTENSION;
|
|
|
|
case ActionType::MergeModules:
|
|
case ActionType::EmitModuleOnly:
|
|
return SERIALIZED_MODULE_EXTENSION;
|
|
|
|
case ActionType::Immediate:
|
|
case ActionType::REPL:
|
|
// These modes have no frontend-generated output.
|
|
return nullptr;
|
|
|
|
case ActionType::EmitAssembly:
|
|
return "s";
|
|
|
|
case ActionType::EmitIR:
|
|
return "ll";
|
|
|
|
case ActionType::EmitBC:
|
|
return "bc";
|
|
|
|
case ActionType::EmitObject:
|
|
return "o";
|
|
|
|
case ActionType::EmitImportedModules:
|
|
return "importedmodules";
|
|
}
|
|
}
|
|
|
|
bool FrontendOptions::hasUnusedDependenciesFilePath() const {
|
|
return !DependenciesFilePath.empty() &&
|
|
!canActionEmitDependencies(RequestedAction);
|
|
}
|
|
|
|
bool FrontendOptions::canActionEmitDependencies(ActionType action) {
|
|
switch (action) {
|
|
case ActionType::NoneAction:
|
|
case ActionType::DumpParse:
|
|
case ActionType::DumpInterfaceHash:
|
|
case ActionType::DumpAST:
|
|
case ActionType::EmitSyntax:
|
|
case ActionType::PrintAST:
|
|
case ActionType::DumpScopeMaps:
|
|
case ActionType::DumpTypeRefinementContexts:
|
|
case ActionType::Immediate:
|
|
case ActionType::REPL:
|
|
return false;
|
|
case ActionType::Parse:
|
|
case ActionType::Typecheck:
|
|
case ActionType::MergeModules:
|
|
case ActionType::EmitModuleOnly:
|
|
case ActionType::EmitPCH:
|
|
case ActionType::EmitSILGen:
|
|
case ActionType::EmitSIL:
|
|
case ActionType::EmitSIBGen:
|
|
case ActionType::EmitSIB:
|
|
case ActionType::EmitIR:
|
|
case ActionType::EmitBC:
|
|
case ActionType::EmitAssembly:
|
|
case ActionType::EmitObject:
|
|
case ActionType::EmitImportedModules:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool FrontendOptions::hasUnusedObjCHeaderOutputPath() const {
|
|
return !ObjCHeaderOutputPath.empty() && !canActionEmitHeader(RequestedAction);
|
|
}
|
|
|
|
bool FrontendOptions::canActionEmitHeader(ActionType action) {
|
|
switch (action) {
|
|
case ActionType::NoneAction:
|
|
case ActionType::DumpParse:
|
|
case ActionType::DumpInterfaceHash:
|
|
case ActionType::DumpAST:
|
|
case ActionType::EmitSyntax:
|
|
case ActionType::PrintAST:
|
|
case ActionType::EmitPCH:
|
|
case ActionType::DumpScopeMaps:
|
|
case ActionType::DumpTypeRefinementContexts:
|
|
case ActionType::Immediate:
|
|
case ActionType::REPL:
|
|
return false;
|
|
case ActionType::Parse:
|
|
case ActionType::Typecheck:
|
|
case ActionType::MergeModules:
|
|
case ActionType::EmitModuleOnly:
|
|
case ActionType::EmitSILGen:
|
|
case ActionType::EmitSIL:
|
|
case ActionType::EmitSIBGen:
|
|
case ActionType::EmitSIB:
|
|
case ActionType::EmitIR:
|
|
case ActionType::EmitBC:
|
|
case ActionType::EmitAssembly:
|
|
case ActionType::EmitObject:
|
|
case ActionType::EmitImportedModules:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool FrontendOptions::hasUnusedLoadedModuleTracePath() const {
|
|
return !LoadedModuleTracePath.empty() &&
|
|
!canActionEmitLoadedModuleTrace(RequestedAction);
|
|
}
|
|
|
|
bool FrontendOptions::canActionEmitLoadedModuleTrace(ActionType action) {
|
|
switch (action) {
|
|
case ActionType::NoneAction:
|
|
case ActionType::Parse:
|
|
case ActionType::DumpParse:
|
|
case ActionType::DumpInterfaceHash:
|
|
case ActionType::DumpAST:
|
|
case ActionType::EmitSyntax:
|
|
case ActionType::PrintAST:
|
|
case ActionType::DumpScopeMaps:
|
|
case ActionType::DumpTypeRefinementContexts:
|
|
case ActionType::Immediate:
|
|
case ActionType::REPL:
|
|
return false;
|
|
case ActionType::Typecheck:
|
|
case ActionType::MergeModules:
|
|
case ActionType::EmitModuleOnly:
|
|
case ActionType::EmitPCH:
|
|
case ActionType::EmitSILGen:
|
|
case ActionType::EmitSIL:
|
|
case ActionType::EmitSIBGen:
|
|
case ActionType::EmitSIB:
|
|
case ActionType::EmitIR:
|
|
case ActionType::EmitBC:
|
|
case ActionType::EmitAssembly:
|
|
case ActionType::EmitObject:
|
|
case ActionType::EmitImportedModules:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool FrontendOptions::hasUnusedModuleOutputPath() const {
|
|
return !ModuleOutputPath.empty() && !canActionEmitModule(RequestedAction);
|
|
}
|
|
|
|
bool FrontendOptions::hasUnusedModuleDocOutputPath() const {
|
|
return !ModuleDocOutputPath.empty() && !canActionEmitModule(RequestedAction);
|
|
}
|
|
|
|
bool FrontendOptions::canActionEmitModule(ActionType action) {
|
|
switch (action) {
|
|
case ActionType::NoneAction:
|
|
case ActionType::Parse:
|
|
case ActionType::Typecheck:
|
|
case ActionType::DumpParse:
|
|
case ActionType::DumpInterfaceHash:
|
|
case ActionType::DumpAST:
|
|
case ActionType::EmitSyntax:
|
|
case ActionType::PrintAST:
|
|
case ActionType::EmitPCH:
|
|
case ActionType::DumpScopeMaps:
|
|
case ActionType::DumpTypeRefinementContexts:
|
|
case ActionType::EmitSILGen:
|
|
case ActionType::Immediate:
|
|
case ActionType::REPL:
|
|
return false;
|
|
case ActionType::MergeModules:
|
|
case ActionType::EmitModuleOnly:
|
|
case ActionType::EmitSIL:
|
|
case ActionType::EmitSIBGen:
|
|
case ActionType::EmitSIB:
|
|
case ActionType::EmitIR:
|
|
case ActionType::EmitBC:
|
|
case ActionType::EmitAssembly:
|
|
case ActionType::EmitObject:
|
|
case ActionType::EmitImportedModules:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool FrontendOptions::canActionEmitModuleDoc(ActionType action) {
|
|
return canActionEmitModule(action);
|
|
}
|
|
|
|
bool FrontendOptions::doesActionProduceOutput(ActionType action) {
|
|
switch (action) {
|
|
case ActionType::Parse:
|
|
case ActionType::Typecheck:
|
|
case ActionType::DumpParse:
|
|
case ActionType::DumpAST:
|
|
case ActionType::EmitSyntax:
|
|
case ActionType::DumpInterfaceHash:
|
|
case ActionType::PrintAST:
|
|
case ActionType::DumpScopeMaps:
|
|
case ActionType::DumpTypeRefinementContexts:
|
|
case ActionType::EmitPCH:
|
|
case ActionType::EmitSILGen:
|
|
case ActionType::EmitSIL:
|
|
case ActionType::EmitSIBGen:
|
|
case ActionType::EmitSIB:
|
|
case ActionType::EmitModuleOnly:
|
|
case ActionType::EmitAssembly:
|
|
case ActionType::EmitIR:
|
|
case ActionType::EmitBC:
|
|
case ActionType::EmitObject:
|
|
case ActionType::EmitImportedModules:
|
|
case ActionType::MergeModules:
|
|
return true;
|
|
|
|
case ActionType::NoneAction:
|
|
case ActionType::Immediate:
|
|
case ActionType::REPL:
|
|
return false;
|
|
}
|
|
llvm_unreachable("Unknown ActionType");
|
|
}
|
|
|
|
bool FrontendOptions::doesActionProduceTextualOutput(ActionType action) {
|
|
switch (action) {
|
|
case ActionType::NoneAction:
|
|
case ActionType::EmitPCH:
|
|
case ActionType::EmitSIBGen:
|
|
case ActionType::EmitSIB:
|
|
case ActionType::MergeModules:
|
|
case ActionType::EmitModuleOnly:
|
|
case ActionType::EmitBC:
|
|
case ActionType::EmitObject:
|
|
case ActionType::Immediate:
|
|
case ActionType::REPL:
|
|
return false;
|
|
|
|
case ActionType::Parse:
|
|
case ActionType::Typecheck:
|
|
case ActionType::DumpParse:
|
|
case ActionType::DumpInterfaceHash:
|
|
case ActionType::DumpAST:
|
|
case ActionType::EmitSyntax:
|
|
case ActionType::PrintAST:
|
|
case ActionType::DumpScopeMaps:
|
|
case ActionType::DumpTypeRefinementContexts:
|
|
case ActionType::EmitImportedModules:
|
|
case ActionType::EmitSILGen:
|
|
case ActionType::EmitSIL:
|
|
case ActionType::EmitAssembly:
|
|
case ActionType::EmitIR:
|
|
return true;
|
|
}
|
|
}
|