//===- FrontendOptions.h ----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//
#ifndef FORTRAN_FRONTEND_FRONTENDOPTIONS_H
#define FORTRAN_FRONTEND_FRONTENDOPTIONS_H
#include "flang/Common/Fortran-features.h"
#include "flang/Lower/EnvironmentDefault.h"
#include "flang/Parser/characters.h"
#include "flang/Parser/unparse.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cstdint>
#include <string>
namespace Fortran::frontend {
enum ActionKind {
/// -test-io mode
InputOutputTest,
/// -E mode
PrintPreprocessedInput,
/// -fsyntax-only
ParseSyntaxOnly,
/// Emit FIR mlir file
EmitFIR,
/// Emit HLFIR mlir file
EmitHLFIR,
/// Emit an .ll file
EmitLLVM,
/// Emit a .bc file
EmitLLVMBitcode,
/// Emit a .o file.
EmitObj,
/// Emit a .s file.
EmitAssembly,
/// Parse, unparse the parse-tree and output a Fortran source file
DebugUnparse,
/// Parse, unparse the parse-tree and output a Fortran source file, skip the
/// semantic checks
DebugUnparseNoSema,
/// Parse, resolve the sybmols, unparse the parse-tree and then output a
/// Fortran source file
DebugUnparseWithSymbols,
/// Parse, run semantics, and output a Fortran source file preceded
/// by all the necessary modules (transitively)
DebugUnparseWithModules,
/// Parse, run semantics and then output symbols from semantics
DebugDumpSymbols,
/// Parse, run semantics and then output the parse tree
DebugDumpParseTree,
/// Parse, run semantics and then output the pre-fir parse tree
DebugDumpPFT,
/// Parse, run semantics and then output the parse tree and symbols
DebugDumpAll,
/// Parse and then output the parse tree, skip the semantic checks
DebugDumpParseTreeNoSema,
/// Dump provenance
DebugDumpProvenance,
/// Parse then output the parsing log
DebugDumpParsingLog,
/// Parse then output the number of objects in the parse tree and the overall
/// size
DebugMeasureParseTree,
/// Parse, run semantics and then output the pre-FIR tree
DebugPreFIRTree,
/// `-fget-definition`
GetDefinition,
/// Parse, run semantics and then dump symbol sources map
GetSymbolsSources,
/// Only execute frontend initialization
InitOnly,
/// Run a plugin action
PluginAction
};
/// \param suffix The file extension
/// \return True if the file extension should be processed as fixed form
bool isFixedFormSuffix(llvm::StringRef suffix);
/// \param suffix The file extension
/// \return True if the file extension should be processed as free form
bool isFreeFormSuffix(llvm::StringRef suffix);
/// \param suffix The file extension
/// \return True if the file should be preprocessed
bool isToBePreprocessed(llvm::StringRef suffix);
/// \param suffix The file extension
/// \return True if the file contains CUDA Fortran
bool isCUDAFortranSuffix(llvm::StringRef suffix);
enum class Language : uint8_t {
Unknown,
/// MLIR: we accept this so that we can run the optimizer on it, and compile
/// it to LLVM IR, assembly or object code.
MLIR,
/// LLVM IR: we accept this so that we can run the optimizer on it,
/// and compile it to assembly or object code.
LLVM_IR,
/// @{ Languages that the frontend can parse and compile.
Fortran,
/// @}
};
// Source file layout
enum class FortranForm {
/// The user has not specified a form. Base the form off the file extension.
Unknown,
/// -ffree-form
FixedForm,
/// -ffixed-form
FreeForm
};
/// The kind of a file that we've been handed as an input.
class InputKind {
private:
Language lang;
public:
/// The input file format.
enum Format { Source, ModuleMap, Precompiled };
constexpr InputKind(Language l = Language::Unknown) : lang(l) {}
Language getLanguage() const { return static_cast<Language>(lang); }
/// Is the input kind fully-unknown?
bool isUnknown() const { return lang == Language::Unknown; }
};
/// An input file for the front end.
class FrontendInputFile {
/// The file name, or "-" to read from standard input.
std::string file;
/// The input, if it comes from a buffer rather than a file. This object
/// does not own the buffer, and the caller is responsible for ensuring
/// that it outlives any users.
const llvm::MemoryBuffer *buffer = nullptr;
/// The kind of input, atm it contains language
InputKind kind;
/// Is this input file in fixed-form format? This is simply derived from the
/// file extension and should not be altered by consumers. For input from
/// stdin this is never modified.
bool isFixedForm = false;
/// Must this file be preprocessed? Note that in Flang the preprocessor is
/// always run. This flag is used to control whether predefined and command
/// line preprocessor macros are enabled or not. In practice, this is
/// sufficient to implement gfortran`s logic controlled with `-cpp/-nocpp`.
unsigned mustBePreprocessed : 1;
/// Whether to enable CUDA Fortran language extensions
bool isCUDAFortran{false};
public:
FrontendInputFile() = default;
FrontendInputFile(llvm::StringRef file, InputKind inKind)
: file(file.str()), kind(inKind) {
// Based on the extension, decide whether this is a fixed or free form
// file.
auto pathDotIndex{file.rfind(".")};
std::string pathSuffix{file.substr(pathDotIndex + 1)};
isFixedForm = isFixedFormSuffix(pathSuffix);
mustBePreprocessed = isToBePreprocessed(pathSuffix);
isCUDAFortran = isCUDAFortranSuffix(pathSuffix);
}
FrontendInputFile(const llvm::MemoryBuffer *memBuf, InputKind inKind)
: buffer(memBuf), kind(inKind) {}
InputKind getKind() const { return kind; }
bool isEmpty() const { return file.empty() && buffer == nullptr; }
bool isFile() const { return (buffer == nullptr); }
bool getIsFixedForm() const { return isFixedForm; }
bool getMustBePreprocessed() const { return mustBePreprocessed; }
bool getIsCUDAFortran() const { return isCUDAFortran; }
llvm::StringRef getFile() const {
assert(isFile());
return file;
}
const llvm::MemoryBuffer *getBuffer() const {
assert(buffer && "Requested buffer, but it is empty!");
return buffer;
}
};
/// FrontendOptions - Options for controlling the behavior of the frontend.
struct FrontendOptions {
FrontendOptions()
: showHelp(false), showVersion(false), instrumentedParse(false),
showColors(false), needProvenanceRangeToCharBlockMappings(false) {}
/// Show the -help text.
unsigned showHelp : 1;
/// Show the -version text.
unsigned showVersion : 1;
/// Instrument the parse to get a more verbose log
unsigned instrumentedParse : 1;
/// Enable color diagnostics.
unsigned showColors : 1;
/// Enable Provenance to character-stream mapping. Allows e.g. IDEs to find
/// symbols based on source-code location. This is not needed in regular
/// compilation.
unsigned needProvenanceRangeToCharBlockMappings : 1;
/// Input values from `-fget-definition`
struct GetDefinitionVals {
unsigned line;
unsigned startColumn;
unsigned endColumn;
};
GetDefinitionVals getDefVals;
/// The input files and their types.
std::vector<FrontendInputFile> inputs;
/// The output file, if any.
std::string outputFile;
/// The frontend action to perform.
frontend::ActionKind programAction = ParseSyntaxOnly;
// The form to process files in, if specified.
FortranForm fortranForm = FortranForm::Unknown;
// Default values for environment variables to be set by the runtime.
std::vector<Fortran::lower::EnvironmentDefault> envDefaults;
// The column after which characters are ignored in fixed form lines in the
// source file.
int fixedFormColumns = 72;
/// The input kind, either specified via -x argument or deduced from the input
/// file name.
InputKind dashX;
// Language features
common::LanguageFeatureControl features;
// Source file encoding
Fortran::parser::Encoding encoding{Fortran::parser::Encoding::UTF_8};
/// The list of plugins to load.
std::vector<std::string> plugins;
/// The name of the action to run when using a plugin action.
std::string actionName;
/// A list of arguments to forward to LLVM's option processing; this
/// should only be used for debugging and experimental features.
std::vector<std::string> llvmArgs;
/// A list of arguments to forward to MLIR's option processing; this
/// should only be used for debugging and experimental features.
std::vector<std::string> mlirArgs;
// Return the appropriate input kind for a file extension. For example,
/// "*.f" would return Language::Fortran.
///
/// \return The input kind for the extension, or Language::Unknown if the
/// extension is not recognized.
static InputKind getInputKindForExtension(llvm::StringRef extension);
};
} // namespace Fortran::frontend
#endif // FORTRAN_FRONTEND_FRONTENDOPTIONS_H