Skip to content

Commit 56a0727

Browse files
authored
Merge pull request #1078 from banach-space/andrzej/cherry_pick_for_generate_fir
Cherry picks from llvm-project/main for #1008
2 parents 27f9b66 + d7ab981 commit 56a0727

File tree

111 files changed

+1560
-585
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+1560
-585
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ def ObjC : Flag<["-"], "ObjC">, Flags<[NoXarchOption]>,
701701
def O : Joined<["-"], "O">, Group<O_Group>, Flags<[CC1Option]>;
702702
def O_flag : Flag<["-"], "O">, Flags<[CC1Option]>, Alias<O>, AliasArgs<["1"]>;
703703
def Ofast : Joined<["-"], "Ofast">, Group<O_Group>, Flags<[CC1Option]>;
704-
def P : Flag<["-"], "P">, Flags<[CC1Option]>, Group<Preprocessor_Group>,
704+
def P : Flag<["-"], "P">, Flags<[CC1Option,FlangOption,FC1Option]>, Group<Preprocessor_Group>,
705705
HelpText<"Disable linemarker output in -E mode">,
706706
MarshallingInfoNegativeFlag<PreprocessorOutputOpts<"ShowLineMarkers">>;
707707
def Qy : Flag<["-"], "Qy">, Flags<[CC1Option]>,
@@ -4504,6 +4504,8 @@ def fdebug_dump_parse_tree_no_sema : Flag<["-"], "fdebug-dump-parse-tree-no-sema
45044504
HelpText<"Dump the parse tree (skips the semantic checks)">,
45054505
DocBrief<[{Run the Parser and then output the parse tree. Semantic
45064506
checks are disabled.}]>;
4507+
def fdebug_dump_all : Flag<["-"], "fdebug-dump-all">, Group<Action_Group>,
4508+
HelpText<"Dump symbols and the parse tree after the semantic checks">;
45074509
def fdebug_dump_provenance : Flag<["-"], "fdebug-dump-provenance">, Group<Action_Group>,
45084510
HelpText<"Dump provenance">;
45094511
def fdebug_dump_parsing_log : Flag<["-"], "fdebug-dump-parsing-log">, Group<Action_Group>,
@@ -4512,11 +4514,20 @@ def fdebug_measure_parse_tree : Flag<["-"], "fdebug-measure-parse-tree">, Group<
45124514
HelpText<"Measure the parse tree">;
45134515
def fdebug_pre_fir_tree : Flag<["-"], "fdebug-pre-fir-tree">, Group<Action_Group>,
45144516
HelpText<"Dump the pre-FIR tree">;
4515-
def fdebug_module_writer : Flag<["-"],"fdebug-module-writer">,
4517+
def fdebug_module_writer : Flag<["-"],"fdebug-module-writer">,
45164518
HelpText<"Enable debug messages while writing module files">;
45174519
def fget_symbols_sources : Flag<["-"], "fget-symbols-sources">, Group<Action_Group>,
45184520
HelpText<"Dump symbols and their source code locations">;
45194521

4522+
def module_suffix : Separate<["-"], "module-suffix">, Group<f_Group>, MetaVarName<"<suffix>">,
4523+
HelpText<"Use <suffix> as the suffix for module files (the default value is `.mod`)">;
4524+
def fanalyzed_objects_for_unparse : Flag<["-"],
4525+
"fanalyzed-objects-for-unparse">, Group<f_Group>;
4526+
def fno_analyzed_objects_for_unparse : Flag<["-"],
4527+
"fno-analyzed-objects-for-unparse">, Group<f_Group>,
4528+
HelpText<"Do not use the analyzed objects when unparsing">;
4529+
def fno_reformat : Flag<["-"], "fno-reformat">, Group<Preprocessor_Group>,
4530+
HelpText<"Dump the cooked character stream in -E mode">;
45204531
}
45214532

45224533
//===----------------------------------------------------------------------===//
@@ -5265,8 +5276,6 @@ def analyze : Flag<["-"], "analyze">,
52655276
HelpText<"Run static analysis engine">;
52665277
def dump_tokens : Flag<["-"], "dump-tokens">,
52675278
HelpText<"Run preprocessor, dump internal rep of tokens">;
5268-
def init_only : Flag<["-"], "init-only">,
5269-
HelpText<"Only execute frontend initialization">;
52705279
def fixit : Flag<["-"], "fixit">,
52715280
HelpText<"Apply fix-it advice to the input source">;
52725281
def fixit_EQ : Joined<["-"], "fixit=">,
@@ -5732,6 +5741,8 @@ let Group = Action_Group in {
57325741

57335742
def emit_obj : Flag<["-"], "emit-obj">,
57345743
HelpText<"Emit native object files">;
5744+
def init_only : Flag<["-"], "init-only">,
5745+
HelpText<"Only execute frontend initialization">;
57355746

57365747
} // let Group = Action_Group
57375748
} // let Flags = [CC1Option, FC1Option, NoDriverOption]

clang/lib/Driver/ToolChains/Flang.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ void Flang::AddFortranDialectOptions(const ArgList &Args,
3737

3838
void Flang::AddPreprocessingOptions(const ArgList &Args,
3939
ArgStringList &CmdArgs) const {
40-
Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I,
41-
options::OPT_cpp, options::OPT_nocpp});
40+
Args.AddAllArgs(CmdArgs,
41+
{options::OPT_P, options::OPT_D, options::OPT_U,
42+
options::OPT_I, options::OPT_cpp, options::OPT_nocpp});
4243
}
4344

4445
void Flang::AddOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {

flang/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
7272
include(AddLLVM)
7373
include(HandleLLVMOptions)
7474
include(VersionFromVCS)
75+
include(GetErrcMessages)
7576

7677
if(FLANG_BUILD_NEW_DRIVER)
7778
include(AddClang)
@@ -136,6 +137,8 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
136137
"Generate build targets for the Flang unit tests."
137138
ON)
138139

140+
get_errc_messages(LLVM_LIT_ERRC_MESSAGES)
141+
139142
#Handle unittests when out-of-tree
140143
#LLVM_BUILD_MAIN_SRC_DIR - Path to llvm source when out-of-tree.
141144
set(FLANG_GTEST_AVAIL 0)

flang/docs/FlangDriver.md

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
<!--===- docs/FlangDriver.md
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+
# Flang drivers
10+
11+
```eval_rst
12+
.. contents::
13+
:local:
14+
```
15+
16+
There are two main drivers in Flang:
17+
* the compiler driver, `flang-new`
18+
* the frontend driver, `flang-new -fc1`
19+
20+
The compiler driver will allow you to control all compilation phases (i.e.
21+
preprocessing, frontend code-generation, middlend/backend code-optimisation and
22+
lowering, linking). For frontend specific tasks, the compiler driver creates a
23+
Fortran compilation job and delegates it to `flang-new -fc1`, the frontend driver.
24+
25+
The frontend driver glues all of the frontend libraries together and provides
26+
an easy-to-use and intuitive interface to the frontend. It accepts many
27+
frontend-specific options not available in `flang-new` and as such it provides a
28+
finer control over the frontend. Similarly to `-Xclang` in `clang`, you can use
29+
`-Xflang` to forward the frontend specific flags from the compiler directly to
30+
the frontend driver.
31+
32+
## Compiler Driver
33+
34+
The main entry point for Flang's compiler driver is implemented in
35+
`flang/tools/flang-driver/driver.cpp`. Flang's compiler driver is implemented
36+
in terms of Clang's driver library, `clangDriver`. This approach allows us to:
37+
* benefit from Clang's support for various targets, platforms and operating systems
38+
* leverage Clang's ability to drive various backends available in LLVM, as well
39+
as linkers and assemblers.
40+
One implication of this dependency on Clang is that all of Flang's compiler
41+
options are defined alongside Clang's options in
42+
`clang/include/clang/Driver/Options.td`. For options that are common for both
43+
Flang and Clang, the corresponding definitions are shared.
44+
45+
Internally, a `clangDriver` based compiler driver works by creating actions
46+
that correspond to various compilation phases, e.g. `PreprocessJobClass`,
47+
`CompileJobClass`, `BackendJobClass` or `LinkJobClass` from the
48+
`clang::driver::Action::ActionClass` enum. There are also other, more
49+
specialised actions, e.g. `MigrateJobClass` or `InputClass`, that do not map
50+
directly to common compilation steps. The actions to run are determined from
51+
the supplied compiler flags, e.g.
52+
53+
* `-E` for `PreprocessJobClass`,
54+
* `-c` for `CompileJobClass`.
55+
56+
In most cases, the driver creates a chain of actions/jobs/phases where the
57+
output from one action is the input for the subsequent one. You can use the
58+
`-ccc-print-phases` flag to see the sequence of actions that the driver will
59+
create for your compiler invocation:
60+
```bash
61+
flang-new -ccc-print-phases -E file.f
62+
+- 0: input, "file.f", f95-cpp-input
63+
1: preprocessor, {0}, f95
64+
```
65+
As you can see, for `-E` the driver creates only two jobs and stops immediately
66+
after preprocessing. The first job simply prepares the input. For `-c`, the
67+
pipeline of the created jobs is more complex:
68+
```bash
69+
flang-new -ccc-print-phases -c file.f
70+
+- 0: input, "file.f", f95-cpp-input
71+
+- 1: preprocessor, {0}, f95
72+
+- 2: compiler, {1}, ir
73+
+- 3: backend, {2}, assembler
74+
4: assembler, {3}, object
75+
```
76+
Note that currently Flang does not support code-generation and `flang-new` will
77+
fail during the second step above with the following error:
78+
```bash
79+
error: code-generation is not available yet
80+
```
81+
The other phases are printed nonetheless when using `-ccc-print-phases`, as
82+
that reflects what `clangDriver`, the library, will try to create and run.
83+
84+
For actions specific to the frontend (e.g. preprocessing or code generation), a
85+
command to call the frontend driver is generated (more specifically, an
86+
instance of `clang::driver::Command`). Every command is bound to an instance of
87+
`clang::driver::Tool`. For Flang we introduced a specialisation of this class:
88+
`clang::driver::Flang`. This class implements the logic to either translate or
89+
forward compiler options to the frontend driver, `flang-new -fc1`.
90+
91+
You can read more on the design of `clangDriver` in Clang's [Driver Design &
92+
Internals](https://clang.llvm.org/docs/DriverInternals.html).
93+
94+
## Frontend Driver
95+
Flang's frontend driver is the main interface between end-users and the Flang
96+
frontend. The high-level design is similar to Clang's frontend driver, `clang
97+
-cc1` and consists of the following classes:
98+
* `CompilerInstance`, which is a helper class that encapsulates and manages
99+
various objects that are always required by the frontend (e.g. `AllSources`,
100+
`AllCookedSources, `Parsing`, `CompilerInvocation`, etc.). In most cases
101+
`CompilerInstance` owns these objects, but it also can share them with its
102+
clients when required. It also implements utility methods to construct and
103+
manipulate them.
104+
* `CompilerInvocation` encapsulates the configuration of the current
105+
invocation of the compiler as derived from the command-line options and the
106+
input files (in particular, file extensions). Among other things, it holds an
107+
instance of `FrontendOptions`. Like `CompilerInstance`, it owns the objects
108+
that it manages. It can share them with its clients that want to access them
109+
even after the corresponding `CompilerInvocation` has been destructed.
110+
* `FrontendOptions` holds options that control the behaviour of the frontend,
111+
as well as e.g. the list of the input files. These options come either
112+
directly from the users (through command-line flags) or are derived from
113+
e.g. the host system configuration.
114+
* `FrontendAction` and `FrontendActions` (the former being the base class for
115+
the latter) implement the actual actions to perform by the frontend. Usually
116+
there is one specialisation of `FrontendActions` for every compiler action flag
117+
(e.g. `-E`, `-fdebug-unparse`). These classes also contain various hooks that
118+
allow you to e.g. fine-tune the configuration of the frontend based on the
119+
input.
120+
121+
This list is not exhaustive and only covers the main classes that implement the
122+
driver. The main entry point for the frontend driver, `fc1_main`, is
123+
implemented in `flang/tools/flang-driver/driver.cpp`. It can be accessed by
124+
invoking the compiler driver, `flang-new`, with the `-fc1` flag.
125+
126+
The frontend driver will only run one action at a time. If you specify multiple
127+
action flags, only the last one will be taken into account. The default action
128+
is `ParseSyntaxOnlyAction`, which corresponds to `-fsyntax-only`. In other
129+
words, `flang-new -fc1 <input-file>` is equivalent to `flang-new -fc1 -fsyntax-only
130+
<input-file>`.
131+
132+
## Adding new Compiler Options
133+
Adding a new compiler option in Flang consists of two steps:
134+
* define the new option in a dedicated TableGen file,
135+
* parse and implement the option in the relevant drivers that support it.
136+
137+
### Option Definition
138+
All of Flang's compiler and frontend driver options are defined in
139+
`clang/include/clang/Driver/Options.td` in Clang. When adding a new option to
140+
Flang, you will either:
141+
* extend the existing definition for an option that is already available
142+
in one of Clang's drivers (e.g. `clang`), but not yet available in Flang, or
143+
* add a completely new definition if the option that you are adding has not
144+
been defined yet.
145+
146+
There are many predefined TableGen classes and records that you can use to fine
147+
tune your new option. The list of available configurations can be overwhelming
148+
at times. Sometimes the easiest approach is to find an existing option that has
149+
similar semantics to your new option and start by copying that.
150+
151+
For every new option, you will also have to define the visibility of the new
152+
option. This is controlled through the `Flags` field. You can use the following
153+
Flang specific option flags to control this:
154+
* `FlangOption` - this option will be available in the `flang-new` compiler driver,
155+
* `FC1Option` - this option will be available in the `flang-new -fc1` frontend driver,
156+
* `FlangOnlyOption` - this option will not be visible in Clang drivers.
157+
158+
Please make sure that options that you add are only visible in drivers that can
159+
support it. For example, options that only make sense for Fortran input files
160+
(e.g. `-ffree-form`) should not be visible in Clang and be marked as
161+
`FlangOnlyOption`.
162+
163+
When deciding what `OptionGroup` to use when defining a new option in the
164+
`Options.td` file, many new options fall into one of the following two
165+
categories:
166+
* `Action_Group` - options that define an action to run (e.g.
167+
`-fsyntax-only`, `-E`)
168+
* `f_Group` - target independent compiler flags (e.g. `-ffixed-form`,
169+
`-fopenmp`)
170+
There are also other groups and occasionally you will use them instead of the
171+
groups listed above.
172+
173+
### Option Implementation
174+
First, every option needs to be parsed. Flang compiler options are parsed in
175+
two different places, depending on which driver they belong to:
176+
177+
* frontend driver: `flang/lib/Frontend/CompilerInvocation.cpp`,
178+
* compiler driver: `clang/lib/Driver/ToolChains/Flang.cpp`.
179+
180+
The parsing will depend on the semantics encoded in the TableGen definition.
181+
182+
When adding a compiler driver option (i.e. an option that contains
183+
`FlangOption` among its `Flags`) that you also intend to be understood by the
184+
frontend, make sure that it is either forwarded to `flang-new -fc1` or translated
185+
into some other option that is accepted by the frontend driver. In the case of
186+
options that contain both `FlangOption` and `FC1Option` among its flags, we
187+
usually just forward from `flang-new` to `flang-new -fc1`. This is then tested in
188+
`flang/test/Driver/frontend-forward.F90`.
189+
190+
What follows is usually very dependant on the meaning of the corresponding
191+
option. In general, regular compiler flags (e.g. `-ffree-form`) are mapped to
192+
some state within the driver. A lot of this state is stored within an instance
193+
of `FrontendOptions`, but there are other more specialised classes too. Action
194+
flags (e.g. `-fsyntax-only`) are usually more complex overall, but also more
195+
structured in terms of the implementation.
196+
197+
### Action Options
198+
For options that correspond to an action (i.e. marked as `Action_Group`), you
199+
will have to define a dedicated instance of `FrontendActions` in
200+
`flang/include/flang/Frontend/FrontendOptions.h`. For example, for
201+
`-fsyntax-only` we defined:
202+
```cpp
203+
class ParseSyntaxOnlyAction : public PrescanAndSemaAction {
204+
void ExecuteAction() override;
205+
};
206+
```
207+
Command line options are mapped to frontend actions through the
208+
`Fortran::frontend::ActionKind` enum. For every new action option that you
209+
add, you will have to add a dedicated entry in that enum (e.g.
210+
`ParseSyntaxOnly` for `-fsyntax-only`) and a corresponding `case` in
211+
`ParseFrontendArgs` function in the `CompilerInvocation.cpp` file, e.g.:
212+
```cpp
213+
case clang::driver::options::OPT_fsyntax_only:
214+
opts.programAction = ParseSyntaxOnly;
215+
break;
216+
```
217+
Note that this simply sets the program/frontend action within the frontend
218+
driver. You still have make sure that the corresponding frontend action class
219+
is instantiated when your new action option is used. The relevant `switch`
220+
statement is implemented in `Fortran::frontend::CreatedFrontendBaseAction` in
221+
the `ExecuteCompilerInvocation.cpp` file. Here's an example for
222+
`-fsyntax-only`:
223+
```cpp
224+
case ParseSyntaxOnly:
225+
return std::make_unique<ParseSyntaxOnlyAction>();
226+
```
227+
At this point you should be able to trigger that frontend action that you have
228+
just added using your new frontend option.
229+
230+
# Testing
231+
In LIT, we define two variables that you can use to invoke Flang's drivers:
232+
* `%flang` is expanded as `flang-new` (i.e. the compiler driver)
233+
* `%flang_fc1` is expanded as `flang-new -fc1` (i.e. the frontend driver)
234+
235+
For most regression tests for the frontend, you will want to use `%flang_fc1`.
236+
In some cases, the observable behaviour will be identical regardless of whether
237+
`%flang` or `%flang_fc1` is used. However, when you are using `%flang` instead
238+
of `%flang_fc1`, the compiler driver will add extra flags to the frontend
239+
driver invocation (i.e. `flang-new -fc1 -<extra-flags>`). In some cases that might
240+
be exactly what you want to test. In fact, you can check these additional
241+
flags by using the `-###` compiler driver command line option.
242+
243+
Lastly, you can use `! REQUIRES: <feature>` for tests that will only work when
244+
`<feature>` is available. For example, you can use`! REQUIRES: shell` to mark a
245+
test as only available on Unix-like systems (i.e. systems that contain a Unix
246+
shell). In practice this means that the corresponding test is skipped on
247+
Windows.

0 commit comments

Comments
 (0)