This patch adds support for most common optimisation compiler flags:
`-O{0|1|2|3}`. This is implemented in both the compiler and frontend
drivers. At this point, these options are only used to configure the
LLVM optimisation pipelines (aka middle-end). LLVM backend or MLIR/FIR
optimisations are not supported yet.
Previously, the middle-end pass manager was only required when
generating LLVM bitcode (i.e. for `flang-new -c -emit-llvm <file>` or
`flang-new -fc1 -emit-llvm-bc <file>`). With this change, it becomes
required for all frontend actions that are represented as
`CodeGenAction` and `CodeGenAction::executeAction` is refactored
accordingly (in the spirit of better code re-use).
Additionally, the `-fdebug-pass-manager` option is enabled to facilitate
testing. This flag can be used to configure the pass manager to print
the middle-end passes that are being run. Similar option exists in Clang
and the semantics in Flang are identical. This option translates to
extra configuration when setting up the pass manager. This is
implemented in `CodeGenAction::runOptimizationPipeline`.
This patch also adds some bolier plate code to manage code-gen options
("code-gen" refers to generating machine code in LLVM in this context).
This was extracted from Clang. In Clang, it simplifies defining code-gen
options and enables option marshalling. In Flang, option marshalling is
not yet supported (we might do at some point), but being able to
auto-generate some code with macros is beneficial. This will become
particularly apparent when we start adding more options (at least in
Clang, the list of code-gen options is rather long).
Differential Revision: https://reviews.llvm.org/D128043
172 lines
6.2 KiB
C++
172 lines
6.2 KiB
C++
//===-- Flang.cpp - Flang+LLVM ToolChain Implementations --------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
#include "Flang.h"
|
|
#include "CommonArgs.h"
|
|
|
|
#include "clang/Driver/Options.h"
|
|
|
|
#include <cassert>
|
|
|
|
using namespace clang::driver;
|
|
using namespace clang::driver::tools;
|
|
using namespace clang;
|
|
using namespace llvm::opt;
|
|
|
|
/// Add -x lang to \p CmdArgs for \p Input.
|
|
static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
|
|
ArgStringList &CmdArgs) {
|
|
CmdArgs.push_back("-x");
|
|
// Map the driver type to the frontend type.
|
|
CmdArgs.push_back(types::getTypeName(Input.getType()));
|
|
}
|
|
|
|
void Flang::AddFortranDialectOptions(const ArgList &Args,
|
|
ArgStringList &CmdArgs) const {
|
|
Args.AddAllArgs(
|
|
CmdArgs, {options::OPT_ffixed_form, options::OPT_ffree_form,
|
|
options::OPT_ffixed_line_length_EQ, options::OPT_fopenmp,
|
|
options::OPT_fopenacc, options::OPT_finput_charset_EQ,
|
|
options::OPT_fimplicit_none, options::OPT_fno_implicit_none,
|
|
options::OPT_fbackslash, options::OPT_fno_backslash,
|
|
options::OPT_flogical_abbreviations,
|
|
options::OPT_fno_logical_abbreviations,
|
|
options::OPT_fxor_operator, options::OPT_fno_xor_operator,
|
|
options::OPT_falternative_parameter_statement,
|
|
options::OPT_fdefault_real_8, options::OPT_fdefault_integer_8,
|
|
options::OPT_fdefault_double_8, options::OPT_flarge_sizes,
|
|
options::OPT_fno_automatic});
|
|
}
|
|
|
|
void Flang::AddPreprocessingOptions(const ArgList &Args,
|
|
ArgStringList &CmdArgs) const {
|
|
Args.AddAllArgs(CmdArgs,
|
|
{options::OPT_P, options::OPT_D, options::OPT_U,
|
|
options::OPT_I, options::OPT_cpp, options::OPT_nocpp});
|
|
}
|
|
|
|
void Flang::AddOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
|
|
Args.AddAllArgs(CmdArgs,
|
|
{options::OPT_module_dir, options::OPT_fdebug_module_writer,
|
|
options::OPT_fintrinsic_modules_path, options::OPT_pedantic,
|
|
options::OPT_std_EQ, options::OPT_W_Joined});
|
|
}
|
|
|
|
void Flang::ConstructJob(Compilation &C, const JobAction &JA,
|
|
const InputInfo &Output, const InputInfoList &Inputs,
|
|
const ArgList &Args, const char *LinkingOutput) const {
|
|
const auto &TC = getToolChain();
|
|
const llvm::Triple &Triple = TC.getEffectiveTriple();
|
|
const std::string &TripleStr = Triple.getTriple();
|
|
|
|
const Driver &D = TC.getDriver();
|
|
ArgStringList CmdArgs;
|
|
|
|
// Invoke ourselves in -fc1 mode.
|
|
CmdArgs.push_back("-fc1");
|
|
|
|
// Add the "effective" target triple.
|
|
CmdArgs.push_back("-triple");
|
|
CmdArgs.push_back(Args.MakeArgString(TripleStr));
|
|
|
|
if (isa<PreprocessJobAction>(JA)) {
|
|
CmdArgs.push_back("-E");
|
|
} else if (isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) {
|
|
if (JA.getType() == types::TY_Nothing) {
|
|
CmdArgs.push_back("-fsyntax-only");
|
|
} else if (JA.getType() == types::TY_AST) {
|
|
CmdArgs.push_back("-emit-ast");
|
|
} else if (JA.getType() == types::TY_LLVM_IR ||
|
|
JA.getType() == types::TY_LTO_IR) {
|
|
CmdArgs.push_back("-emit-llvm");
|
|
} else if (JA.getType() == types::TY_LLVM_BC ||
|
|
JA.getType() == types::TY_LTO_BC) {
|
|
CmdArgs.push_back("-emit-llvm-bc");
|
|
} else if (JA.getType() == types::TY_PP_Asm) {
|
|
CmdArgs.push_back("-S");
|
|
} else {
|
|
assert(false && "Unexpected output type!");
|
|
}
|
|
} else if (isa<AssembleJobAction>(JA)) {
|
|
CmdArgs.push_back("-emit-obj");
|
|
} else {
|
|
assert(false && "Unexpected action class for Flang tool.");
|
|
}
|
|
|
|
const InputInfo &Input = Inputs[0];
|
|
types::ID InputType = Input.getType();
|
|
|
|
// Add preprocessing options like -I, -D, etc. if we are using the
|
|
// preprocessor (i.e. skip when dealing with e.g. binary files).
|
|
if (types::getPreprocessedType(InputType) != types::TY_INVALID)
|
|
AddPreprocessingOptions(Args, CmdArgs);
|
|
|
|
AddFortranDialectOptions(Args, CmdArgs);
|
|
|
|
// Color diagnostics are parsed by the driver directly from argv and later
|
|
// re-parsed to construct this job; claim any possible color diagnostic here
|
|
// to avoid warn_drv_unused_argument.
|
|
Args.getLastArg(options::OPT_fcolor_diagnostics,
|
|
options::OPT_fno_color_diagnostics);
|
|
if (D.getDiags().getDiagnosticOptions().ShowColors)
|
|
CmdArgs.push_back("-fcolor-diagnostics");
|
|
|
|
// Add other compile options
|
|
AddOtherOptions(Args, CmdArgs);
|
|
|
|
// Forward -Xflang arguments to -fc1
|
|
Args.AddAllArgValues(CmdArgs, options::OPT_Xflang);
|
|
|
|
// Forward -mllvm options to the LLVM option parser. In practice, this means
|
|
// forwarding to `-fc1` as that's where the LLVM parser is run.
|
|
for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
|
|
A->claim();
|
|
A->render(Args, CmdArgs);
|
|
}
|
|
|
|
for (const Arg *A : Args.filtered(options::OPT_mmlir)) {
|
|
A->claim();
|
|
A->render(Args, CmdArgs);
|
|
}
|
|
|
|
// Optimization level for CodeGen.
|
|
if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) {
|
|
if (A->getOption().matches(options::OPT_O4)) {
|
|
CmdArgs.push_back("-O3");
|
|
D.Diag(diag::warn_O4_is_O3);
|
|
} else {
|
|
A->render(Args, CmdArgs);
|
|
}
|
|
}
|
|
|
|
if (Output.isFilename()) {
|
|
CmdArgs.push_back("-o");
|
|
CmdArgs.push_back(Output.getFilename());
|
|
} else {
|
|
assert(Output.isNothing() && "Invalid output.");
|
|
}
|
|
|
|
assert(Input.isFilename() && "Invalid input.");
|
|
|
|
addDashXForInput(Args, Input, CmdArgs);
|
|
|
|
CmdArgs.push_back(Input.getFilename());
|
|
|
|
// TODO: Replace flang-new with flang once the new driver replaces the
|
|
// throwaway driver
|
|
const char *Exec = Args.MakeArgString(D.GetProgramPath("flang-new", TC));
|
|
C.addCommand(std::make_unique<Command>(JA, *this,
|
|
ResponseFileSupport::AtFileUTF8(),
|
|
Exec, CmdArgs, Inputs, Output));
|
|
}
|
|
|
|
Flang::Flang(const ToolChain &TC) : Tool("flang-new", "flang frontend", TC) {}
|
|
|
|
Flang::~Flang() {}
|