Files
swift-mirror/lib/Frontend/FrontendOptions.cpp
David Ungar 04c16cdebd Incorperate advice from review.
Change “have” routines to “has”.
Use more consistent casing.
Remove spurious “DelayedFunctionParsing” option.
Move debugFail routines to top lexical level.
Rename and reorder declaration of functions in FrontendArgsToOptionsConverter.
Move, reword, and doxygenate comments for some of those functions.
Fix casing on some more setUp* functions.
Return NoneAction instead of existing RequestedAction in FrontendArgsToOptionsConverter::determineRequestedAction.
Remove test names and put in FIXME’s.
Remove “Jordan” from comments & reword.
Reorder if-then arms of FrontendArgsToOptionsConverter::computeOutputFilenames for readability.
Test for empty string instead of equality with “”.
Use hasUnusedModuleDocOutputPath.
Remove optionality from return type of getOutputFilenamesFromCommandLineOrFilelist.
Rename isPrimaryInputAFileAt to isThereAPrimaryInputWithAFilenameAt.
Added a FIXME in doesActionProduceOutput to reflect that some actions actually do not produce output.
2017-11-30 17:28:15 -08:00

473 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::actionHasOutput() 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:
return false;
case ActionType::EmitPCH:
case ActionType::EmitSILGen:
case ActionType::EmitSIL:
case ActionType::EmitSIBGen:
case ActionType::EmitSIB:
case ActionType::EmitModuleOnly:
case ActionType::MergeModules:
return true;
case ActionType::Immediate:
case ActionType::REPL:
return false;
case ActionType::EmitAssembly:
case ActionType::EmitIR:
case ActionType::EmitBC:
case ActionType::EmitObject:
case ActionType::EmitImportedModules:
return true;
}
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) {
// FIXME: Some of these don't actually produce output
// but for now stay consistent with the status quo.
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::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;
case ActionType::Immediate:
case ActionType::REPL:
// These modes have no frontend-generated output.
return false;
}
}
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;
}
}