This legacy option (available in other Fortran compilers with various spellings) implies the SAVE attribute for local variables on subprograms that are not explicitly RECURSIVE. The SAVE attribute essentially implies static rather than stack storage. This was the default setting in Fortran until surprisingly recently, so explicit SAVE statements & attributes could be and often were omitted from older codes. Note that initialized objects already have an implied SAVE attribute, and objects in COMMON effectively do too, as data overlays are extinct; and since objects that are expected to survive from one invocation of a procedure to the next in static storage should probably be explicit initialized in the first place, so the use cases for this option are somewhat rare, and all of them could be handled with explicit SAVE statements or attributes. This implicit SAVE attribute must not apply to automatic (in the Fortran sense) local objects, whose sizes cannot be known at compilation time. To get the semantics of IsSaved() right, the IsAutomatic() predicate was moved into Evaluate/tools.cpp to allow for dynamic linking of the compiler. The redundant predicate IsAutomatic() was noticed, removed, and its uses replaced. GNU Fortran's spelling of the option (-fno-automatic) was added to the clang-based driver and used for basic sanity testing. Differential Revision: https://reviews.llvm.org/D114209
135 lines
5.0 KiB
C++
135 lines
5.0 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;
|
|
|
|
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();
|
|
// TODO: Once code-generation is available, this will need to be commented
|
|
// out.
|
|
// const llvm::Triple &Triple = TC.getEffectiveTriple();
|
|
// const std::string &TripleStr = Triple.getTriple();
|
|
|
|
ArgStringList CmdArgs;
|
|
|
|
// Invoke ourselves in -fc1 mode.
|
|
CmdArgs.push_back("-fc1");
|
|
|
|
// TODO: Once code-generation is available, this will need to be commented
|
|
// out.
|
|
// 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);
|
|
|
|
// Add other compile options
|
|
AddOtherOptions(Args, CmdArgs);
|
|
|
|
// Forward -Xflang arguments to -fc1
|
|
Args.AddAllArgValues(CmdArgs, options::OPT_Xflang);
|
|
|
|
if (Output.isFilename()) {
|
|
CmdArgs.push_back("-o");
|
|
CmdArgs.push_back(Output.getFilename());
|
|
} else {
|
|
assert(Output.isNothing() && "Invalid output.");
|
|
}
|
|
|
|
assert(Input.isFilename() && "Invalid input.");
|
|
CmdArgs.push_back(Input.getFilename());
|
|
|
|
const auto& D = C.getDriver();
|
|
// 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() {}
|