clang  16.0.0git
Flang.cpp
Go to the documentation of this file.
1 //===-- Flang.cpp - Flang+LLVM ToolChain Implementations --------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 
10 #include "Flang.h"
11 #include "CommonArgs.h"
12 
13 #include "clang/Driver/Options.h"
14 
15 #include <cassert>
16 
17 using namespace clang::driver;
18 using namespace clang::driver::tools;
19 using namespace clang;
20 using namespace llvm::opt;
21 
22 /// Add -x lang to \p CmdArgs for \p Input.
23 static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
24  ArgStringList &CmdArgs) {
25  CmdArgs.push_back("-x");
26  // Map the driver type to the frontend type.
27  CmdArgs.push_back(types::getTypeName(Input.getType()));
28 }
29 
30 void Flang::addFortranDialectOptions(const ArgList &Args,
31  ArgStringList &CmdArgs) const {
32  Args.AddAllArgs(
33  CmdArgs, {options::OPT_ffixed_form, options::OPT_ffree_form,
34  options::OPT_ffixed_line_length_EQ, options::OPT_fopenmp,
35  options::OPT_fopenacc, options::OPT_finput_charset_EQ,
36  options::OPT_fimplicit_none, options::OPT_fno_implicit_none,
37  options::OPT_fbackslash, options::OPT_fno_backslash,
38  options::OPT_flogical_abbreviations,
39  options::OPT_fno_logical_abbreviations,
40  options::OPT_fxor_operator, options::OPT_fno_xor_operator,
41  options::OPT_falternative_parameter_statement,
42  options::OPT_fdefault_real_8, options::OPT_fdefault_integer_8,
43  options::OPT_fdefault_double_8, options::OPT_flarge_sizes,
44  options::OPT_fno_automatic});
45 }
46 
47 void Flang::addPreprocessingOptions(const ArgList &Args,
48  ArgStringList &CmdArgs) const {
49  Args.AddAllArgs(CmdArgs,
50  {options::OPT_P, options::OPT_D, options::OPT_U,
51  options::OPT_I, options::OPT_cpp, options::OPT_nocpp});
52 }
53 
54 void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
55  Args.AddAllArgs(CmdArgs,
56  {options::OPT_module_dir, options::OPT_fdebug_module_writer,
57  options::OPT_fintrinsic_modules_path, options::OPT_pedantic,
58  options::OPT_std_EQ, options::OPT_W_Joined,
59  options::OPT_fconvert_EQ, options::OPT_fpass_plugin_EQ});
60 }
61 
62 void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
63  // ParsePICArgs parses -fPIC/-fPIE and their variants and returns a tuple of
64  // (RelocationModel, PICLevel, IsPIE).
65  llvm::Reloc::Model RelocationModel;
66  unsigned PICLevel;
67  bool IsPIE;
68  std::tie(RelocationModel, PICLevel, IsPIE) =
69  ParsePICArgs(getToolChain(), Args);
70 
71  if (auto *RMName = RelocationModelName(RelocationModel)) {
72  CmdArgs.push_back("-mrelocation-model");
73  CmdArgs.push_back(RMName);
74  }
75  if (PICLevel > 0) {
76  CmdArgs.push_back("-pic-level");
77  CmdArgs.push_back(PICLevel == 1 ? "1" : "2");
78  if (IsPIE)
79  CmdArgs.push_back("-pic-is-pie");
80  }
81 }
82 
83 static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
84  ArgStringList &CmdArgs) {
85  StringRef FPContract;
86  bool HonorINFs = true;
87  bool HonorNaNs = true;
88  bool ApproxFunc = false;
89  bool SignedZeros = true;
90  bool AssociativeMath = false;
91  bool ReciprocalMath = false;
92 
93  if (const Arg *A = Args.getLastArg(options::OPT_ffp_contract)) {
94  const StringRef Val = A->getValue();
95  if (Val == "fast" || Val == "off") {
96  FPContract = Val;
97  } else if (Val == "on") {
98  // Warn instead of error because users might have makefiles written for
99  // gfortran (which accepts -ffp-contract=on)
100  D.Diag(diag::warn_drv_unsupported_option_for_flang)
101  << Val << A->getOption().getName() << "off";
102  FPContract = "off";
103  } else
104  // Clang's "fast-honor-pragmas" option is not supported because it is
105  // non-standard
106  D.Diag(diag::err_drv_unsupported_option_argument)
107  << A->getSpelling() << Val;
108  }
109 
110  for (const Arg *A : Args) {
111  auto optId = A->getOption().getID();
112  switch (optId) {
113  // if this isn't an FP option, skip the claim below
114  default:
115  continue;
116 
117  case options::OPT_fhonor_infinities:
118  HonorINFs = true;
119  break;
120  case options::OPT_fno_honor_infinities:
121  HonorINFs = false;
122  break;
123  case options::OPT_fhonor_nans:
124  HonorNaNs = true;
125  break;
126  case options::OPT_fno_honor_nans:
127  HonorNaNs = false;
128  break;
129  case options::OPT_fapprox_func:
130  ApproxFunc = true;
131  break;
132  case options::OPT_fno_approx_func:
133  ApproxFunc = false;
134  break;
135  case options::OPT_fsigned_zeros:
136  SignedZeros = true;
137  break;
138  case options::OPT_fno_signed_zeros:
139  SignedZeros = false;
140  break;
141  case options::OPT_fassociative_math:
142  AssociativeMath = true;
143  break;
144  case options::OPT_fno_associative_math:
145  AssociativeMath = false;
146  break;
147  case options::OPT_freciprocal_math:
148  ReciprocalMath = true;
149  break;
150  case options::OPT_fno_reciprocal_math:
151  ReciprocalMath = false;
152  break;
153  }
154 
155  // If we handled this option claim it
156  A->claim();
157  }
158 
159  if (!FPContract.empty())
160  CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract));
161 
162  if (!HonorINFs)
163  CmdArgs.push_back("-menable-no-infs");
164 
165  if (!HonorNaNs)
166  CmdArgs.push_back("-menable-no-nans");
167 
168  if (ApproxFunc)
169  CmdArgs.push_back("-fapprox-func");
170 
171  if (!SignedZeros)
172  CmdArgs.push_back("-fno-signed-zeros");
173 
174  if (AssociativeMath && !SignedZeros)
175  CmdArgs.push_back("-mreassociate");
176 
177  if (ReciprocalMath)
178  CmdArgs.push_back("-freciprocal-math");
179 }
180 
182  const InputInfo &Output, const InputInfoList &Inputs,
183  const ArgList &Args, const char *LinkingOutput) const {
184  const auto &TC = getToolChain();
185  const llvm::Triple &Triple = TC.getEffectiveTriple();
186  const std::string &TripleStr = Triple.getTriple();
187 
188  const Driver &D = TC.getDriver();
189  ArgStringList CmdArgs;
190 
191  // Invoke ourselves in -fc1 mode.
192  CmdArgs.push_back("-fc1");
193 
194  // Add the "effective" target triple.
195  CmdArgs.push_back("-triple");
196  CmdArgs.push_back(Args.MakeArgString(TripleStr));
197 
198  if (isa<PreprocessJobAction>(JA)) {
199  CmdArgs.push_back("-E");
200  } else if (isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) {
201  if (JA.getType() == types::TY_Nothing) {
202  CmdArgs.push_back("-fsyntax-only");
203  } else if (JA.getType() == types::TY_AST) {
204  CmdArgs.push_back("-emit-ast");
205  } else if (JA.getType() == types::TY_LLVM_IR ||
206  JA.getType() == types::TY_LTO_IR) {
207  CmdArgs.push_back("-emit-llvm");
208  } else if (JA.getType() == types::TY_LLVM_BC ||
209  JA.getType() == types::TY_LTO_BC) {
210  CmdArgs.push_back("-emit-llvm-bc");
211  } else if (JA.getType() == types::TY_PP_Asm) {
212  CmdArgs.push_back("-S");
213  } else {
214  assert(false && "Unexpected output type!");
215  }
216  } else if (isa<AssembleJobAction>(JA)) {
217  CmdArgs.push_back("-emit-obj");
218  } else {
219  assert(false && "Unexpected action class for Flang tool.");
220  }
221 
222  const InputInfo &Input = Inputs[0];
223  types::ID InputType = Input.getType();
224 
225  // Add preprocessing options like -I, -D, etc. if we are using the
226  // preprocessor (i.e. skip when dealing with e.g. binary files).
228  addPreprocessingOptions(Args, CmdArgs);
229 
230  addFortranDialectOptions(Args, CmdArgs);
231 
232  // Color diagnostics are parsed by the driver directly from argv and later
233  // re-parsed to construct this job; claim any possible color diagnostic here
234  // to avoid warn_drv_unused_argument.
235  Args.getLastArg(options::OPT_fcolor_diagnostics,
236  options::OPT_fno_color_diagnostics);
237  if (D.getDiags().getDiagnosticOptions().ShowColors)
238  CmdArgs.push_back("-fcolor-diagnostics");
239 
240  // -fPIC and related options.
241  addPicOptions(Args, CmdArgs);
242 
243  // Floating point related options
244  addFloatingPointOptions(D, Args, CmdArgs);
245 
246  // Add other compile options
247  addOtherOptions(Args, CmdArgs);
248 
249  // Forward -Xflang arguments to -fc1
250  Args.AddAllArgValues(CmdArgs, options::OPT_Xflang);
251 
252  // Forward -mllvm options to the LLVM option parser. In practice, this means
253  // forwarding to `-fc1` as that's where the LLVM parser is run.
254  for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
255  A->claim();
256  A->render(Args, CmdArgs);
257  }
258 
259  for (const Arg *A : Args.filtered(options::OPT_mmlir)) {
260  A->claim();
261  A->render(Args, CmdArgs);
262  }
263 
264  // Optimization level for CodeGen.
265  if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) {
266  if (A->getOption().matches(options::OPT_O4)) {
267  CmdArgs.push_back("-O3");
268  D.Diag(diag::warn_O4_is_O3);
269  } else {
270  A->render(Args, CmdArgs);
271  }
272  }
273 
274  if (Output.isFilename()) {
275  CmdArgs.push_back("-o");
276  CmdArgs.push_back(Output.getFilename());
277  } else {
278  assert(Output.isNothing() && "Invalid output.");
279  }
280 
281  assert(Input.isFilename() && "Invalid input.");
282 
283  addDashXForInput(Args, Input, CmdArgs);
284 
285  CmdArgs.push_back(Input.getFilename());
286 
287  // TODO: Replace flang-new with flang once the new driver replaces the
288  // throwaway driver
289  const char *Exec = Args.MakeArgString(D.GetProgramPath("flang-new", TC));
290  C.addCommand(std::make_unique<Command>(JA, *this,
292  Exec, CmdArgs, Inputs, Output));
293 }
294 
295 Flang::Flang(const ToolChain &TC) : Tool("flang-new", "flang frontend", TC) {}
296 
clang::driver::Driver::GetProgramPath
std::string GetProgramPath(StringRef Name, const ToolChain &TC) const
GetProgramPath - Lookup Name in the list of program search paths.
Definition: Driver.cpp:5773
clang::driver::tools::Flang::ConstructJob
void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override
ConstructJob - Construct jobs to perform the action JA, writing to Output and with Inputs,...
Definition: Flang.cpp:181
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::driver::tools::ParsePICArgs
std::tuple< llvm::Reloc::Model, unsigned, bool > ParsePICArgs(const ToolChain &ToolChain, const llvm::opt::ArgList &Args)
clang::driver::ResponseFileSupport::AtFileUTF8
static constexpr ResponseFileSupport AtFileUTF8()
Definition: Job.h:85
llvm::SmallVector
Definition: LLVM.h:38
clang::DiagnosticsEngine::getDiagnosticOptions
DiagnosticOptions & getDiagnosticOptions() const
Retrieve the diagnostic options.
Definition: Diagnostic.h:557
addFloatingPointOptions
static void addFloatingPointOptions(const Driver &D, const ArgList &Args, ArgStringList &CmdArgs)
Definition: Flang.cpp:83
clang::driver::tools
Definition: AIX.h:17
clang::driver::InputInfo
InputInfo - Wrapper for information about an input source.
Definition: InputInfo.h:22
clang::driver::Driver::getDiags
DiagnosticsEngine & getDiags() const
Definition: Driver.h:367
clang::driver::Driver::Diag
DiagnosticBuilder Diag(unsigned DiagID) const
Definition: Driver.h:142
clang::driver::Tool
Tool - Information on a specific compilation tool.
Definition: Tool.h:32
Options.h
clang::driver::InputInfo::isFilename
bool isFilename() const
Definition: InputInfo.h:75
clang::driver::tools::Flang::Flang
Flang(const ToolChain &TC)
Definition: Flang.cpp:295
clang::driver::Action::getType
types::ID getType() const
Definition: Action.h:147
llvm::opt
Definition: DiagnosticOptions.h:19
clang::driver::types::TY_INVALID
@ TY_INVALID
Definition: Types.h:24
clang::driver::InputInfo::isNothing
bool isNothing() const
Definition: InputInfo.h:74
clang::driver::ToolChain
ToolChain - Access to tools for a single platform.
Definition: ToolChain.h:91
clang::driver::types::ID
ID
Definition: Types.h:23
clang::driver::Compilation
Compilation - A set of tasks to perform for a single driver invocation.
Definition: Compilation.h:45
clang::driver::InputInfo::getFilename
const char * getFilename() const
Definition: InputInfo.h:83
clang::driver::tools::RelocationModelName
const char * RelocationModelName(llvm::Reloc::Model Model)
Definition: CommonArgs.cpp:1263
CommonArgs.h
clang
Definition: CalledOnceCheck.h:17
clang::driver::Driver
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:75
clang::driver::InputInfo::getType
types::ID getType() const
Definition: InputInfo.h:77
clang::driver::tools::Flang::~Flang
~Flang() override
Definition: Flang.cpp:297
clang::driver::types::getPreprocessedType
ID getPreprocessedType(ID Id)
getPreprocessedType - Get the ID of the type for this input when it has been preprocessed,...
Definition: Types.cpp:56
Flang.h
clang::driver
Definition: Action.h:31
clang::driver::JobAction
Definition: Action.h:398
addDashXForInput
static void addDashXForInput(const ArgList &Args, const InputInfo &Input, ArgStringList &CmdArgs)
Add -x lang to CmdArgs for Input.
Definition: Flang.cpp:23
clang::driver::types::getTypeName
const char * getTypeName(ID Id)
getTypeName - Return the name of the type for Id.
Definition: Types.cpp:52