1 //===-- Flang.cpp - Flang+LLVM ToolChain Implementations --------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
11 #include "CommonArgs.h"
13 #include "clang/Driver/Options.h"
17 using namespace clang::driver
;
18 using namespace clang::driver::tools
;
19 using namespace clang
;
20 using namespace llvm::opt
;
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()));
30 void Flang::AddFortranDialectOptions(const ArgList
&Args
,
31 ArgStringList
&CmdArgs
) const {
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
});
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
});
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
});
61 void Flang::AddPicOptions(const ArgList
&Args
, ArgStringList
&CmdArgs
) const {
62 // ParsePICArgs parses -fPIC/-fPIE and their variants and returns a tuple of
63 // (RelocationModel, PICLevel, IsPIE).
64 llvm::Reloc::Model RelocationModel
;
67 std::tie(RelocationModel
, PICLevel
, IsPIE
) =
68 ParsePICArgs(getToolChain(), Args
);
70 if (auto *RMName
= RelocationModelName(RelocationModel
)) {
71 CmdArgs
.push_back("-mrelocation-model");
72 CmdArgs
.push_back(RMName
);
75 CmdArgs
.push_back("-pic-level");
76 CmdArgs
.push_back(PICLevel
== 1 ? "1" : "2");
78 CmdArgs
.push_back("-pic-is-pie");
82 void Flang::ConstructJob(Compilation
&C
, const JobAction
&JA
,
83 const InputInfo
&Output
, const InputInfoList
&Inputs
,
84 const ArgList
&Args
, const char *LinkingOutput
) const {
85 const auto &TC
= getToolChain();
86 const llvm::Triple
&Triple
= TC
.getEffectiveTriple();
87 const std::string
&TripleStr
= Triple
.getTriple();
89 const Driver
&D
= TC
.getDriver();
90 ArgStringList CmdArgs
;
92 // Invoke ourselves in -fc1 mode.
93 CmdArgs
.push_back("-fc1");
95 // Add the "effective" target triple.
96 CmdArgs
.push_back("-triple");
97 CmdArgs
.push_back(Args
.MakeArgString(TripleStr
));
99 if (isa
<PreprocessJobAction
>(JA
)) {
100 CmdArgs
.push_back("-E");
101 } else if (isa
<CompileJobAction
>(JA
) || isa
<BackendJobAction
>(JA
)) {
102 if (JA
.getType() == types::TY_Nothing
) {
103 CmdArgs
.push_back("-fsyntax-only");
104 } else if (JA
.getType() == types::TY_AST
) {
105 CmdArgs
.push_back("-emit-ast");
106 } else if (JA
.getType() == types::TY_LLVM_IR
||
107 JA
.getType() == types::TY_LTO_IR
) {
108 CmdArgs
.push_back("-emit-llvm");
109 } else if (JA
.getType() == types::TY_LLVM_BC
||
110 JA
.getType() == types::TY_LTO_BC
) {
111 CmdArgs
.push_back("-emit-llvm-bc");
112 } else if (JA
.getType() == types::TY_PP_Asm
) {
113 CmdArgs
.push_back("-S");
115 assert(false && "Unexpected output type!");
117 } else if (isa
<AssembleJobAction
>(JA
)) {
118 CmdArgs
.push_back("-emit-obj");
120 assert(false && "Unexpected action class for Flang tool.");
123 const InputInfo
&Input
= Inputs
[0];
124 types::ID InputType
= Input
.getType();
126 // Add preprocessing options like -I, -D, etc. if we are using the
127 // preprocessor (i.e. skip when dealing with e.g. binary files).
128 if (types::getPreprocessedType(InputType
) != types::TY_INVALID
)
129 AddPreprocessingOptions(Args
, CmdArgs
);
131 AddFortranDialectOptions(Args
, CmdArgs
);
133 // Color diagnostics are parsed by the driver directly from argv and later
134 // re-parsed to construct this job; claim any possible color diagnostic here
135 // to avoid warn_drv_unused_argument.
136 Args
.getLastArg(options::OPT_fcolor_diagnostics
,
137 options::OPT_fno_color_diagnostics
);
138 if (D
.getDiags().getDiagnosticOptions().ShowColors
)
139 CmdArgs
.push_back("-fcolor-diagnostics");
141 // -fPIC and related options.
142 AddPicOptions(Args
, CmdArgs
);
144 // Add other compile options
145 AddOtherOptions(Args
, CmdArgs
);
147 // Forward -Xflang arguments to -fc1
148 Args
.AddAllArgValues(CmdArgs
, options::OPT_Xflang
);
150 // Forward -mllvm options to the LLVM option parser. In practice, this means
151 // forwarding to `-fc1` as that's where the LLVM parser is run.
152 for (const Arg
*A
: Args
.filtered(options::OPT_mllvm
)) {
154 A
->render(Args
, CmdArgs
);
157 for (const Arg
*A
: Args
.filtered(options::OPT_mmlir
)) {
159 A
->render(Args
, CmdArgs
);
162 // Optimization level for CodeGen.
163 if (const Arg
*A
= Args
.getLastArg(options::OPT_O_Group
)) {
164 if (A
->getOption().matches(options::OPT_O4
)) {
165 CmdArgs
.push_back("-O3");
166 D
.Diag(diag::warn_O4_is_O3
);
168 A
->render(Args
, CmdArgs
);
172 if (Output
.isFilename()) {
173 CmdArgs
.push_back("-o");
174 CmdArgs
.push_back(Output
.getFilename());
176 assert(Output
.isNothing() && "Invalid output.");
179 assert(Input
.isFilename() && "Invalid input.");
181 addDashXForInput(Args
, Input
, CmdArgs
);
183 CmdArgs
.push_back(Input
.getFilename());
185 // TODO: Replace flang-new with flang once the new driver replaces the
187 const char *Exec
= Args
.MakeArgString(D
.GetProgramPath("flang-new", TC
));
188 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
189 ResponseFileSupport::AtFileUTF8(),
190 Exec
, CmdArgs
, Inputs
, Output
));
193 Flang::Flang(const ToolChain
&TC
) : Tool("flang-new", "flang frontend", TC
) {}