2020-09-11 10:17:31 +01:00
|
|
|
//===- CompilerInvocation.cpp ---------------------------------------------===//
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2022-04-29 17:36:26 +00:00
|
|
|
//
|
|
|
|
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2020-09-11 10:17:31 +01:00
|
|
|
|
|
|
|
#include "flang/Frontend/CompilerInvocation.h"
|
2021-02-10 09:24:45 +00:00
|
|
|
#include "flang/Common/Fortran-features.h"
|
2022-06-06 09:44:21 +00:00
|
|
|
#include "flang/Frontend/CodeGenOptions.h"
|
2021-01-06 15:42:24 +00:00
|
|
|
#include "flang/Frontend/PreprocessorOptions.h"
|
[flang][driver] Add support for `--target`/`--triple`
This patch adds support for:
* `--target` in the compiler driver (`flang-new`)
* `--triple` in the frontend driver (`flang-new -fc1`)
The semantics of these flags are inherited from `clangDriver`, i.e.
consistent with `clang --target` and `clang -cc1 --triple`,
respectively.
A new structure is defined, `TargetOptions`, that will hold various
Frontend options related to the target. Currently, this is mostly a
placeholder that contains the target triple. In the future, it will be
used for storing e.g. the CPU to tune for or the target features to
enable.
Additionally, the following target/triple related options are enabled
[*]: `-print-effective-triple`, `-print-target-triple`. Definitions in
Options.td are updated accordingly and, to facilated testing,
`-emit-llvm` is added to the list of options available in `flang-new`
(previously it was only enabled in `flang-new -fc1`).
[*] These options were actually available before (like all other options
defined in `clangDriver`), but not included in `flang-new --help`.
Before this change, `flang-new` would just use `native` for defining the
target, so these options were of little value.
Differential Revision: https://reviews.llvm.org/D120246
2022-02-21 11:51:32 +00:00
|
|
|
#include "flang/Frontend/TargetOptions.h"
|
2021-02-10 09:24:45 +00:00
|
|
|
#include "flang/Semantics/semantics.h"
|
2021-01-19 13:15:53 +00:00
|
|
|
#include "flang/Version.inc"
|
2020-09-11 10:17:31 +01:00
|
|
|
#include "clang/Basic/AllDiagnostics.h"
|
|
|
|
#include "clang/Basic/DiagnosticDriver.h"
|
|
|
|
#include "clang/Basic/DiagnosticOptions.h"
|
|
|
|
#include "clang/Driver/DriverDiagnostic.h"
|
2022-06-06 09:44:21 +00:00
|
|
|
#include "clang/Driver/OptionUtils.h"
|
2020-09-11 10:17:31 +01:00
|
|
|
#include "clang/Driver/Options.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
[flang][driver] Define the default frontend driver triple
*SUMMARY*
Currently, the frontend driver assumes that a target triple is either:
* provided by the frontend itself (e.g. when lowering and generating
code),
* specified through the `-triple/-target` command line flags.
If `-triple/-target` is not used, the frontend will simply use the host
triple.
This is going to be insufficient when e.g. consuming an LLVM IR file
that has no triple specified (reading LLVM files is WIP, see D124667).
We shouldn't require the triple to be specified via the command line in
such situation. Instead, the frontend driver should contain a good
default, e.g. the host triple.
This patch updates Flang's `CompilerInvocation` to do just that, i.e.
defines its default target triple. Similarly to Clang:
* the default `CompilerInvocation` triple is set as the host triple,
* the value specified with `-triple` takes precedence over the frontend
driver default and the current module triple,
* the frontend driver default takes precedence over the module triple.
*TESTS*
This change requires 2 unit tests to be updated. That's because relevant
frontend actions are updated to assume that there's always a valid
triple available in the current `CompilerInvocation`. This update is
required because the unit tests bypass the regular `CompilerInvocation`
set-up (in particular, they don't call
`CompilerInvocation::CreateFromArgs`). I've also taken the liberty to
disable the pre-precossor formatting in the affected unit tests as well
(it is not required).
No new tests are added. As `flang-new -fc1` does not support consuming
LLVM IR files just yet, it is not possible to compile an LLVM IR file
without a triple. More specifically, atm all LLVM IR files are generated
and stored internally and the driver makes sure that these contain a
valid target triple. This is about to change in D124667 (which adds
support for reading LLVM IR/BC files) and that's where tests for
exercising the default frontend driver triple will be added.
*WHAT DOES CLANG DO?*
For reference, the default target triple for Clang's
`CompilerInvocation` is set through option marshalling infra [1] in
Options.td. Please check the definition of the `-triple` flag:
```
def triple : Separate<["-"], "triple">,
HelpText<"Specify target triple (e.g. i686-apple-darwin9)">,
MarshallingInfoString<TargetOpts<"Triple">, "llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple())">,
AlwaysEmit, Normalizer<"normalizeTriple">;
```
Ideally, we should re-use the marshalling infra in Flang.
[1] https://clang.llvm.org/docs/InternalsManual.html#option-marshalling-infrastructure
Differential Revision: https://reviews.llvm.org/D124664
2022-04-28 14:12:32 +00:00
|
|
|
#include "llvm/ADT/Triple.h"
|
2020-09-11 10:17:31 +01:00
|
|
|
#include "llvm/Option/Arg.h"
|
|
|
|
#include "llvm/Option/ArgList.h"
|
|
|
|
#include "llvm/Option/OptTable.h"
|
2021-03-23 12:24:57 -04:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
|
|
|
#include "llvm/Support/FileUtilities.h"
|
[flang][driver] Define the default frontend driver triple
*SUMMARY*
Currently, the frontend driver assumes that a target triple is either:
* provided by the frontend itself (e.g. when lowering and generating
code),
* specified through the `-triple/-target` command line flags.
If `-triple/-target` is not used, the frontend will simply use the host
triple.
This is going to be insufficient when e.g. consuming an LLVM IR file
that has no triple specified (reading LLVM files is WIP, see D124667).
We shouldn't require the triple to be specified via the command line in
such situation. Instead, the frontend driver should contain a good
default, e.g. the host triple.
This patch updates Flang's `CompilerInvocation` to do just that, i.e.
defines its default target triple. Similarly to Clang:
* the default `CompilerInvocation` triple is set as the host triple,
* the value specified with `-triple` takes precedence over the frontend
driver default and the current module triple,
* the frontend driver default takes precedence over the module triple.
*TESTS*
This change requires 2 unit tests to be updated. That's because relevant
frontend actions are updated to assume that there's always a valid
triple available in the current `CompilerInvocation`. This update is
required because the unit tests bypass the regular `CompilerInvocation`
set-up (in particular, they don't call
`CompilerInvocation::CreateFromArgs`). I've also taken the liberty to
disable the pre-precossor formatting in the affected unit tests as well
(it is not required).
No new tests are added. As `flang-new -fc1` does not support consuming
LLVM IR files just yet, it is not possible to compile an LLVM IR file
without a triple. More specifically, atm all LLVM IR files are generated
and stored internally and the driver makes sure that these contain a
valid target triple. This is about to change in D124667 (which adds
support for reading LLVM IR/BC files) and that's where tests for
exercising the default frontend driver triple will be added.
*WHAT DOES CLANG DO?*
For reference, the default target triple for Clang's
`CompilerInvocation` is set through option marshalling infra [1] in
Options.td. Please check the definition of the `-triple` flag:
```
def triple : Separate<["-"], "triple">,
HelpText<"Specify target triple (e.g. i686-apple-darwin9)">,
MarshallingInfoString<TargetOpts<"Triple">, "llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple())">,
AlwaysEmit, Normalizer<"normalizeTriple">;
```
Ideally, we should re-use the marshalling infra in Flang.
[1] https://clang.llvm.org/docs/InternalsManual.html#option-marshalling-infrastructure
Differential Revision: https://reviews.llvm.org/D124664
2022-04-28 14:12:32 +00:00
|
|
|
#include "llvm/Support/Host.h"
|
2022-01-21 17:05:36 +01:00
|
|
|
#include "llvm/Support/Path.h"
|
2020-10-05 17:42:00 +01:00
|
|
|
#include "llvm/Support/Process.h"
|
2020-09-11 10:17:31 +01:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2021-02-10 09:24:45 +00:00
|
|
|
#include <memory>
|
2020-09-11 10:17:31 +01:00
|
|
|
|
|
|
|
using namespace Fortran::frontend;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Initialization.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
CompilerInvocationBase::CompilerInvocationBase()
|
2022-04-29 17:36:26 +00:00
|
|
|
: diagnosticOpts(new clang::DiagnosticOptions()),
|
|
|
|
preprocessorOpts(new PreprocessorOptions()) {}
|
2020-09-11 10:17:31 +01:00
|
|
|
|
|
|
|
CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &x)
|
2022-04-29 17:36:26 +00:00
|
|
|
: diagnosticOpts(new clang::DiagnosticOptions(x.getDiagnosticOpts())),
|
|
|
|
preprocessorOpts(new PreprocessorOptions(x.getPreprocessorOpts())) {}
|
2020-09-11 10:17:31 +01:00
|
|
|
|
|
|
|
CompilerInvocationBase::~CompilerInvocationBase() = default;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Deserialization (from args)
|
|
|
|
//===----------------------------------------------------------------------===//
|
[flang][Driver] Refine _when_ driver diagnostics are formatted
This patch refines //when// driver diagnostics are formatted so that
`flang-new` and `flang-new -fc1` behave consistently with `clang` and
`clang -cc1`, respectively. This change only applies to driver diagnostics.
Scanning, parsing and semantic diagnostics are separate and not covered here.
**NEW BEHAVIOUR**
To illustrate the new behaviour, consider the following input file:
```! file.f90
program m
integer :: i = k
end
```
In the following invocations, "error: Semantic errors in file.f90" _will be_
formatted:
```
$ flang-new file.f90
error: Semantic errors in file.f90
./file.f90:2:18: error: Must be a constant value
integer :: i = k
$ flang-new -fc1 -fcolor-diagnostics file.f90
error: Semantic errors in file.f90
./file.f90:2:18: error: Must be a constant value
integer :: i = k
```
However, in the following invocations, "error: Semantic errors in file.f90"
_will not be_ formatted:
```
$ flang-new -fno-color-diagnostics file.f90
error: Semantic errors in file.f90
./file.f90:2:18: error: Must be a constant value
integer :: i = k
$ flang-new -fc1 file.f90
error: Semantic errors in file.f90
./file.f90:2:18: error: Must be a constant value
integer :: i = k
```
Before this change, none of the above would be formatted. Note also that the
default behaviour in `flang-new` is different to `flang-new -fc1` (this is
consistent with Clang).
**NOTES ON IMPLEMENTATION**
Note that the diagnostic options are parsed in `createAndPopulateDiagOpt`s in
driver.cpp. That's where the driver's `DiagnosticEngine` options are set. Like
most command-line compiler driver options, these flags are "claimed" in
Flang.cpp (i.e. when creating a frontend driver invocation) by calling
`getLastArg` rather than in driver.cpp.
In Clang's Options.td, `defm color_diagnostics` is replaced with two separate
definitions: `def fcolor_diagnostics` and def fno_color_diagnostics`. That's
because originally `color_diagnostics` derived from `OptInCC1FFlag`, which is a
multiclass for opt-in options in CC1. In order to preserve the current
behaviour in `clang -cc1` (i.e. to keep `-fno-color-diagnostics` unavailable in
`clang -cc1`) and to implement similar behaviour in `flang-new -fc1`, we can't
re-use `OptInCC1FFlag`.
Formatting is only available in consoles that support it and will normally mean that
the message is printed in bold + color.
Co-authored-by: Andrzej Warzynski <andrzej.warzynski@arm.com>
Reviewed By: rovka
Differential Revision: https://reviews.llvm.org/D126164
2022-06-22 23:56:34 +08:00
|
|
|
static bool parseShowColorsArgs(const llvm::opt::ArgList &args,
|
|
|
|
bool defaultColor = true) {
|
|
|
|
// Color diagnostics default to auto ("on" if terminal supports) in the
|
|
|
|
// compiler driver `flang-new` but default to off in the frontend driver
|
|
|
|
// `flang-new -fc1`, needing an explicit OPT_fdiagnostics_color.
|
2020-10-05 17:42:00 +01:00
|
|
|
// Support both clang's -f[no-]color-diagnostics and gcc's
|
|
|
|
// -f[no-]diagnostics-colors[=never|always|auto].
|
|
|
|
enum {
|
|
|
|
Colors_On,
|
|
|
|
Colors_Off,
|
|
|
|
Colors_Auto
|
2022-04-29 17:36:26 +00:00
|
|
|
} showColors = defaultColor ? Colors_Auto : Colors_Off;
|
2020-10-05 17:42:00 +01:00
|
|
|
|
|
|
|
for (auto *a : args) {
|
2022-04-29 17:36:26 +00:00
|
|
|
const llvm::opt::Option &opt = a->getOption();
|
|
|
|
if (opt.matches(clang::driver::options::OPT_fcolor_diagnostics)) {
|
|
|
|
showColors = Colors_On;
|
|
|
|
} else if (opt.matches(clang::driver::options::OPT_fno_color_diagnostics)) {
|
|
|
|
showColors = Colors_Off;
|
|
|
|
} else if (opt.matches(clang::driver::options::OPT_fdiagnostics_color_EQ)) {
|
2020-10-05 17:42:00 +01:00
|
|
|
llvm::StringRef value(a->getValue());
|
|
|
|
if (value == "always")
|
2022-04-29 17:36:26 +00:00
|
|
|
showColors = Colors_On;
|
2020-10-05 17:42:00 +01:00
|
|
|
else if (value == "never")
|
2022-04-29 17:36:26 +00:00
|
|
|
showColors = Colors_Off;
|
2020-10-05 17:42:00 +01:00
|
|
|
else if (value == "auto")
|
2022-04-29 17:36:26 +00:00
|
|
|
showColors = Colors_Auto;
|
2020-10-05 17:42:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
return showColors == Colors_On ||
|
|
|
|
(showColors == Colors_Auto &&
|
|
|
|
llvm::sys::Process::StandardErrHasColors());
|
2020-10-05 17:42:00 +01:00
|
|
|
}
|
|
|
|
|
2022-07-19 17:48:31 +00:00
|
|
|
/// Extracts the optimisation level from \a args.
|
|
|
|
static unsigned getOptimizationLevel(llvm::opt::ArgList &args,
|
|
|
|
clang::DiagnosticsEngine &diags) {
|
|
|
|
unsigned defaultOpt = llvm::CodeGenOpt::None;
|
|
|
|
|
|
|
|
if (llvm::opt::Arg *a =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_O_Group)) {
|
|
|
|
if (a->getOption().matches(clang::driver::options::OPT_O0))
|
|
|
|
return llvm::CodeGenOpt::None;
|
|
|
|
|
|
|
|
assert(a->getOption().matches(clang::driver::options::OPT_O));
|
|
|
|
|
|
|
|
return getLastArgIntValue(args, clang::driver::options::OPT_O, defaultOpt,
|
|
|
|
diags);
|
|
|
|
}
|
|
|
|
|
|
|
|
return defaultOpt;
|
|
|
|
}
|
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
bool Fortran::frontend::parseDiagnosticArgs(clang::DiagnosticOptions &opts,
|
[flang][Driver] Refine _when_ driver diagnostics are formatted
This patch refines //when// driver diagnostics are formatted so that
`flang-new` and `flang-new -fc1` behave consistently with `clang` and
`clang -cc1`, respectively. This change only applies to driver diagnostics.
Scanning, parsing and semantic diagnostics are separate and not covered here.
**NEW BEHAVIOUR**
To illustrate the new behaviour, consider the following input file:
```! file.f90
program m
integer :: i = k
end
```
In the following invocations, "error: Semantic errors in file.f90" _will be_
formatted:
```
$ flang-new file.f90
error: Semantic errors in file.f90
./file.f90:2:18: error: Must be a constant value
integer :: i = k
$ flang-new -fc1 -fcolor-diagnostics file.f90
error: Semantic errors in file.f90
./file.f90:2:18: error: Must be a constant value
integer :: i = k
```
However, in the following invocations, "error: Semantic errors in file.f90"
_will not be_ formatted:
```
$ flang-new -fno-color-diagnostics file.f90
error: Semantic errors in file.f90
./file.f90:2:18: error: Must be a constant value
integer :: i = k
$ flang-new -fc1 file.f90
error: Semantic errors in file.f90
./file.f90:2:18: error: Must be a constant value
integer :: i = k
```
Before this change, none of the above would be formatted. Note also that the
default behaviour in `flang-new` is different to `flang-new -fc1` (this is
consistent with Clang).
**NOTES ON IMPLEMENTATION**
Note that the diagnostic options are parsed in `createAndPopulateDiagOpt`s in
driver.cpp. That's where the driver's `DiagnosticEngine` options are set. Like
most command-line compiler driver options, these flags are "claimed" in
Flang.cpp (i.e. when creating a frontend driver invocation) by calling
`getLastArg` rather than in driver.cpp.
In Clang's Options.td, `defm color_diagnostics` is replaced with two separate
definitions: `def fcolor_diagnostics` and def fno_color_diagnostics`. That's
because originally `color_diagnostics` derived from `OptInCC1FFlag`, which is a
multiclass for opt-in options in CC1. In order to preserve the current
behaviour in `clang -cc1` (i.e. to keep `-fno-color-diagnostics` unavailable in
`clang -cc1`) and to implement similar behaviour in `flang-new -fc1`, we can't
re-use `OptInCC1FFlag`.
Formatting is only available in consoles that support it and will normally mean that
the message is printed in bold + color.
Co-authored-by: Andrzej Warzynski <andrzej.warzynski@arm.com>
Reviewed By: rovka
Differential Revision: https://reviews.llvm.org/D126164
2022-06-22 23:56:34 +08:00
|
|
|
llvm::opt::ArgList &args) {
|
|
|
|
opts.ShowColors = parseShowColorsArgs(args);
|
2020-10-05 17:42:00 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-06-06 09:44:21 +00:00
|
|
|
static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
|
|
|
|
llvm::opt::ArgList &args,
|
|
|
|
clang::DiagnosticsEngine &diags) {
|
2022-07-19 17:48:31 +00:00
|
|
|
opts.OptimizationLevel = getOptimizationLevel(args, diags);
|
2022-06-06 09:44:21 +00:00
|
|
|
|
|
|
|
if (args.hasFlag(clang::driver::options::OPT_fdebug_pass_manager,
|
|
|
|
clang::driver::options::OPT_fno_debug_pass_manager, false))
|
|
|
|
opts.DebugPassManager = 1;
|
2022-08-22 10:24:49 -07:00
|
|
|
|
|
|
|
// -mrelocation-model option.
|
|
|
|
if (const llvm::opt::Arg *A =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_mrelocation_model)) {
|
|
|
|
llvm::StringRef ModelName = A->getValue();
|
|
|
|
auto RM = llvm::StringSwitch<llvm::Optional<llvm::Reloc::Model>>(ModelName)
|
|
|
|
.Case("static", llvm::Reloc::Static)
|
|
|
|
.Case("pic", llvm::Reloc::PIC_)
|
|
|
|
.Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC)
|
|
|
|
.Case("ropi", llvm::Reloc::ROPI)
|
|
|
|
.Case("rwpi", llvm::Reloc::RWPI)
|
|
|
|
.Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI)
|
|
|
|
.Default(llvm::None);
|
|
|
|
if (RM.has_value())
|
|
|
|
opts.setRelocationModel(*RM);
|
|
|
|
else
|
|
|
|
diags.Report(clang::diag::err_drv_invalid_value)
|
|
|
|
<< A->getAsString(args) << ModelName;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -pic-level and -pic-is-pie option.
|
|
|
|
if (int PICLevel = getLastArgIntValue(
|
|
|
|
args, clang::driver::options::OPT_pic_level, 0, diags)) {
|
|
|
|
if (PICLevel > 2)
|
|
|
|
diags.Report(clang::diag::err_drv_invalid_value)
|
|
|
|
<< args.getLastArg(clang::driver::options::OPT_pic_level)
|
|
|
|
->getAsString(args)
|
|
|
|
<< PICLevel;
|
|
|
|
|
|
|
|
opts.PICLevel = PICLevel;
|
|
|
|
if (args.hasArg(clang::driver::options::OPT_pic_is_pie))
|
|
|
|
opts.IsPIE = 1;
|
|
|
|
}
|
2022-06-06 09:44:21 +00:00
|
|
|
}
|
|
|
|
|
[flang][driver] Add support for `--target`/`--triple`
This patch adds support for:
* `--target` in the compiler driver (`flang-new`)
* `--triple` in the frontend driver (`flang-new -fc1`)
The semantics of these flags are inherited from `clangDriver`, i.e.
consistent with `clang --target` and `clang -cc1 --triple`,
respectively.
A new structure is defined, `TargetOptions`, that will hold various
Frontend options related to the target. Currently, this is mostly a
placeholder that contains the target triple. In the future, it will be
used for storing e.g. the CPU to tune for or the target features to
enable.
Additionally, the following target/triple related options are enabled
[*]: `-print-effective-triple`, `-print-target-triple`. Definitions in
Options.td are updated accordingly and, to facilated testing,
`-emit-llvm` is added to the list of options available in `flang-new`
(previously it was only enabled in `flang-new -fc1`).
[*] These options were actually available before (like all other options
defined in `clangDriver`), but not included in `flang-new --help`.
Before this change, `flang-new` would just use `native` for defining the
target, so these options were of little value.
Differential Revision: https://reviews.llvm.org/D120246
2022-02-21 11:51:32 +00:00
|
|
|
/// Parses all target input arguments and populates the target
|
|
|
|
/// options accordingly.
|
|
|
|
///
|
|
|
|
/// \param [in] opts The target options instance to update
|
|
|
|
/// \param [in] args The list of input arguments (from the compiler invocation)
|
2022-04-29 17:36:26 +00:00
|
|
|
static void parseTargetArgs(TargetOptions &opts, llvm::opt::ArgList &args) {
|
[flang][driver] Define the default frontend driver triple
*SUMMARY*
Currently, the frontend driver assumes that a target triple is either:
* provided by the frontend itself (e.g. when lowering and generating
code),
* specified through the `-triple/-target` command line flags.
If `-triple/-target` is not used, the frontend will simply use the host
triple.
This is going to be insufficient when e.g. consuming an LLVM IR file
that has no triple specified (reading LLVM files is WIP, see D124667).
We shouldn't require the triple to be specified via the command line in
such situation. Instead, the frontend driver should contain a good
default, e.g. the host triple.
This patch updates Flang's `CompilerInvocation` to do just that, i.e.
defines its default target triple. Similarly to Clang:
* the default `CompilerInvocation` triple is set as the host triple,
* the value specified with `-triple` takes precedence over the frontend
driver default and the current module triple,
* the frontend driver default takes precedence over the module triple.
*TESTS*
This change requires 2 unit tests to be updated. That's because relevant
frontend actions are updated to assume that there's always a valid
triple available in the current `CompilerInvocation`. This update is
required because the unit tests bypass the regular `CompilerInvocation`
set-up (in particular, they don't call
`CompilerInvocation::CreateFromArgs`). I've also taken the liberty to
disable the pre-precossor formatting in the affected unit tests as well
(it is not required).
No new tests are added. As `flang-new -fc1` does not support consuming
LLVM IR files just yet, it is not possible to compile an LLVM IR file
without a triple. More specifically, atm all LLVM IR files are generated
and stored internally and the driver makes sure that these contain a
valid target triple. This is about to change in D124667 (which adds
support for reading LLVM IR/BC files) and that's where tests for
exercising the default frontend driver triple will be added.
*WHAT DOES CLANG DO?*
For reference, the default target triple for Clang's
`CompilerInvocation` is set through option marshalling infra [1] in
Options.td. Please check the definition of the `-triple` flag:
```
def triple : Separate<["-"], "triple">,
HelpText<"Specify target triple (e.g. i686-apple-darwin9)">,
MarshallingInfoString<TargetOpts<"Triple">, "llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple())">,
AlwaysEmit, Normalizer<"normalizeTriple">;
```
Ideally, we should re-use the marshalling infra in Flang.
[1] https://clang.llvm.org/docs/InternalsManual.html#option-marshalling-infrastructure
Differential Revision: https://reviews.llvm.org/D124664
2022-04-28 14:12:32 +00:00
|
|
|
if (const llvm::opt::Arg *a =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_triple))
|
|
|
|
opts.triple = a->getValue();
|
[flang][driver] Add support for `--target`/`--triple`
This patch adds support for:
* `--target` in the compiler driver (`flang-new`)
* `--triple` in the frontend driver (`flang-new -fc1`)
The semantics of these flags are inherited from `clangDriver`, i.e.
consistent with `clang --target` and `clang -cc1 --triple`,
respectively.
A new structure is defined, `TargetOptions`, that will hold various
Frontend options related to the target. Currently, this is mostly a
placeholder that contains the target triple. In the future, it will be
used for storing e.g. the CPU to tune for or the target features to
enable.
Additionally, the following target/triple related options are enabled
[*]: `-print-effective-triple`, `-print-target-triple`. Definitions in
Options.td are updated accordingly and, to facilated testing,
`-emit-llvm` is added to the list of options available in `flang-new`
(previously it was only enabled in `flang-new -fc1`).
[*] These options were actually available before (like all other options
defined in `clangDriver`), but not included in `flang-new --help`.
Before this change, `flang-new` would just use `native` for defining the
target, so these options were of little value.
Differential Revision: https://reviews.llvm.org/D120246
2022-02-21 11:51:32 +00:00
|
|
|
}
|
|
|
|
|
2021-02-23 17:59:17 +00:00
|
|
|
// Tweak the frontend configuration based on the frontend action
|
|
|
|
static void setUpFrontendBasedOnAction(FrontendOptions &opts) {
|
2021-07-29 12:39:10 +00:00
|
|
|
if (opts.programAction == DebugDumpParsingLog)
|
|
|
|
opts.instrumentedParse = true;
|
2021-04-07 13:10:35 +00:00
|
|
|
|
2021-07-29 12:39:10 +00:00
|
|
|
if (opts.programAction == DebugDumpProvenance ||
|
|
|
|
opts.programAction == Fortran::frontend::GetDefinition)
|
|
|
|
opts.needProvenanceRangeToCharBlockMappings = true;
|
2021-02-23 17:59:17 +00:00
|
|
|
}
|
|
|
|
|
2022-07-19 11:47:25 -07:00
|
|
|
/// Parse the argument specified for the -fconvert=<value> option
|
|
|
|
static std::optional<const char *> parseConvertArg(const char *s) {
|
|
|
|
return llvm::StringSwitch<std::optional<const char *>>(s)
|
|
|
|
.Case("unknown", "UNKNOWN")
|
|
|
|
.Case("native", "NATIVE")
|
|
|
|
.Case("little-endian", "LITTLE_ENDIAN")
|
|
|
|
.Case("big-endian", "BIG_ENDIAN")
|
|
|
|
.Case("swap", "SWAP")
|
|
|
|
.Default(std::nullopt);
|
|
|
|
}
|
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
|
|
|
|
clang::DiagnosticsEngine &diags) {
|
2021-04-14 10:43:14 +00:00
|
|
|
unsigned numErrorsBefore = diags.getNumErrors();
|
2021-02-02 09:07:33 +00:00
|
|
|
|
|
|
|
// By default the frontend driver creates a ParseSyntaxOnly action.
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = ParseSyntaxOnly;
|
2021-02-02 09:07:33 +00:00
|
|
|
|
2021-10-14 08:07:30 +00:00
|
|
|
// Treat multiple action options as an invocation error. Note that `clang
|
|
|
|
// -cc1` does accept multiple action options, but will only consider the
|
|
|
|
// rightmost one.
|
|
|
|
if (args.hasMultipleArgs(clang::driver::options::OPT_Action_Group)) {
|
|
|
|
const unsigned diagID = diags.getCustomDiagID(
|
|
|
|
clang::DiagnosticsEngine::Error, "Only one action option is allowed");
|
|
|
|
diags.Report(diagID);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-09-11 10:17:31 +01:00
|
|
|
// Identify the action (i.e. opts.ProgramAction)
|
|
|
|
if (const llvm::opt::Arg *a =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_Action_Group)) {
|
|
|
|
switch (a->getOption().getID()) {
|
|
|
|
default: {
|
|
|
|
llvm_unreachable("Invalid option in group!");
|
|
|
|
}
|
2020-10-24 12:33:19 +01:00
|
|
|
case clang::driver::options::OPT_test_io:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = InputOutputTest;
|
2020-10-24 12:33:19 +01:00
|
|
|
break;
|
2020-10-27 12:26:47 +00:00
|
|
|
case clang::driver::options::OPT_E:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = PrintPreprocessedInput;
|
2020-10-27 12:26:47 +00:00
|
|
|
break;
|
2020-12-08 16:27:46 +00:00
|
|
|
case clang::driver::options::OPT_fsyntax_only:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = ParseSyntaxOnly;
|
2020-12-08 16:27:46 +00:00
|
|
|
break;
|
2022-02-03 17:00:27 +00:00
|
|
|
case clang::driver::options::OPT_emit_mlir:
|
|
|
|
opts.programAction = EmitMLIR;
|
|
|
|
break;
|
2022-02-04 17:15:12 +00:00
|
|
|
case clang::driver::options::OPT_emit_llvm:
|
|
|
|
opts.programAction = EmitLLVM;
|
|
|
|
break;
|
2022-04-06 11:59:28 +00:00
|
|
|
case clang::driver::options::OPT_emit_llvm_bc:
|
|
|
|
opts.programAction = EmitLLVMBitcode;
|
|
|
|
break;
|
[flang][driver] Add support for `-c` and `-emit-obj`
This patch adds a frontend action for emitting object files. While Flang
does not support code-generation, this action remains a placeholder.
This patch simply provides glue-code to connect the compiler driver
with the appropriate frontend action.
The new action is triggered with the `-c` compiler driver flag, i.e.
`flang-new -c`. This is then translated to `flang-new -fc1 -emit-obj`,
so `-emit-obj` has to be marked as supported as well.
As code-generation is not available yet, `flang-new -c` results in a
driver error:
```
error: code-generation is not available yet
```
Hopefully this will help communicating the level of available
functionality within Flang.
The definition of `emit-obj` is updated so that it can be shared between
Clang and Flang. As the original definition was enclosed within a
Clang-specific TableGen `let` statement, it is extracted into a new `let`
statement. That felt like the cleanest option.
I also commented out `-triple` in Flang::ConstructJob and updated some
comments there. This is similar to https://reviews.llvm.org/D93027. I
wanted to make sure that it's clear that we can't support `-triple`
until we have code-generation. However, once code-generation is
available we _will need_ `-triple`.
As this patch adds `-emit-obj`, the emit-obj.f90 becomes irrelevant and
is deleted. Instead, phases.f90 is added to demonstrate that users can
control compilation phases (indeed, `-c` is a phase control flag).
Reviewed By: SouraVX, clementval
Differential Revision: https://reviews.llvm.org/D93301
2021-01-07 09:08:54 +00:00
|
|
|
case clang::driver::options::OPT_emit_obj:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = EmitObj;
|
[flang][driver] Add support for `-c` and `-emit-obj`
This patch adds a frontend action for emitting object files. While Flang
does not support code-generation, this action remains a placeholder.
This patch simply provides glue-code to connect the compiler driver
with the appropriate frontend action.
The new action is triggered with the `-c` compiler driver flag, i.e.
`flang-new -c`. This is then translated to `flang-new -fc1 -emit-obj`,
so `-emit-obj` has to be marked as supported as well.
As code-generation is not available yet, `flang-new -c` results in a
driver error:
```
error: code-generation is not available yet
```
Hopefully this will help communicating the level of available
functionality within Flang.
The definition of `emit-obj` is updated so that it can be shared between
Clang and Flang. As the original definition was enclosed within a
Clang-specific TableGen `let` statement, it is extracted into a new `let`
statement. That felt like the cleanest option.
I also commented out `-triple` in Flang::ConstructJob and updated some
comments there. This is similar to https://reviews.llvm.org/D93027. I
wanted to make sure that it's clear that we can't support `-triple`
until we have code-generation. However, once code-generation is
available we _will need_ `-triple`.
As this patch adds `-emit-obj`, the emit-obj.f90 becomes irrelevant and
is deleted. Instead, phases.f90 is added to demonstrate that users can
control compilation phases (indeed, `-c` is a phase control flag).
Reviewed By: SouraVX, clementval
Differential Revision: https://reviews.llvm.org/D93301
2021-01-07 09:08:54 +00:00
|
|
|
break;
|
2022-02-24 17:34:27 +00:00
|
|
|
case clang::driver::options::OPT_S:
|
|
|
|
opts.programAction = EmitAssembly;
|
|
|
|
break;
|
2021-02-04 11:14:57 +00:00
|
|
|
case clang::driver::options::OPT_fdebug_unparse:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = DebugUnparse;
|
2021-02-04 11:14:57 +00:00
|
|
|
break;
|
2021-03-30 10:35:42 +00:00
|
|
|
case clang::driver::options::OPT_fdebug_unparse_no_sema:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = DebugUnparseNoSema;
|
2021-03-30 10:35:42 +00:00
|
|
|
break;
|
2021-02-04 11:14:57 +00:00
|
|
|
case clang::driver::options::OPT_fdebug_unparse_with_symbols:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = DebugUnparseWithSymbols;
|
2021-02-04 11:14:57 +00:00
|
|
|
break;
|
2021-02-17 15:55:56 +00:00
|
|
|
case clang::driver::options::OPT_fdebug_dump_symbols:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = DebugDumpSymbols;
|
2021-02-17 15:55:56 +00:00
|
|
|
break;
|
|
|
|
case clang::driver::options::OPT_fdebug_dump_parse_tree:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = DebugDumpParseTree;
|
2021-02-17 15:55:56 +00:00
|
|
|
break;
|
2022-03-08 10:01:55 +00:00
|
|
|
case clang::driver::options::OPT_fdebug_dump_pft:
|
|
|
|
opts.programAction = DebugDumpPFT;
|
|
|
|
break;
|
2021-06-15 15:30:23 +00:00
|
|
|
case clang::driver::options::OPT_fdebug_dump_all:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = DebugDumpAll;
|
2021-06-15 15:30:23 +00:00
|
|
|
break;
|
2021-03-30 10:35:42 +00:00
|
|
|
case clang::driver::options::OPT_fdebug_dump_parse_tree_no_sema:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = DebugDumpParseTreeNoSema;
|
2021-03-30 10:35:42 +00:00
|
|
|
break;
|
2021-02-17 15:55:56 +00:00
|
|
|
case clang::driver::options::OPT_fdebug_dump_provenance:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = DebugDumpProvenance;
|
2021-02-17 15:55:56 +00:00
|
|
|
break;
|
2021-02-23 17:59:17 +00:00
|
|
|
case clang::driver::options::OPT_fdebug_dump_parsing_log:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = DebugDumpParsingLog;
|
2021-02-23 17:59:17 +00:00
|
|
|
break;
|
2021-02-17 18:53:05 +00:00
|
|
|
case clang::driver::options::OPT_fdebug_measure_parse_tree:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = DebugMeasureParseTree;
|
2021-02-17 18:53:05 +00:00
|
|
|
break;
|
|
|
|
case clang::driver::options::OPT_fdebug_pre_fir_tree:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = DebugPreFIRTree;
|
2021-02-17 18:53:05 +00:00
|
|
|
break;
|
2021-03-08 16:54:11 +00:00
|
|
|
case clang::driver::options::OPT_fget_symbols_sources:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = GetSymbolsSources;
|
2021-03-08 16:54:11 +00:00
|
|
|
break;
|
2021-04-14 10:43:14 +00:00
|
|
|
case clang::driver::options::OPT_fget_definition:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = GetDefinition;
|
2021-04-14 10:43:14 +00:00
|
|
|
break;
|
2021-06-07 15:40:26 +01:00
|
|
|
case clang::driver::options::OPT_init_only:
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.programAction = InitOnly;
|
2021-06-07 15:40:26 +01:00
|
|
|
break;
|
2020-10-27 12:26:47 +00:00
|
|
|
|
2020-09-11 10:17:31 +01:00
|
|
|
// TODO:
|
2021-06-07 15:40:26 +01:00
|
|
|
// case clang::driver::options::OPT_emit_llvm:
|
2020-09-11 10:17:31 +01:00
|
|
|
// case clang::driver::options::OPT_emit_llvm_only:
|
|
|
|
// case clang::driver::options::OPT_emit_codegen_only:
|
|
|
|
// case clang::driver::options::OPT_emit_module:
|
|
|
|
// (...)
|
|
|
|
}
|
2021-04-14 10:43:14 +00:00
|
|
|
|
|
|
|
// Parse the values provided with `-fget-definition` (there should be 3
|
|
|
|
// integers)
|
|
|
|
if (llvm::opt::OptSpecifier(a->getOption().getID()) ==
|
|
|
|
clang::driver::options::OPT_fget_definition) {
|
|
|
|
unsigned optVals[3] = {0, 0, 0};
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < 3; i++) {
|
|
|
|
llvm::StringRef val = a->getValue(i);
|
|
|
|
|
|
|
|
if (val.getAsInteger(10, optVals[i])) {
|
|
|
|
// A non-integer was encountered - that's an error.
|
|
|
|
diags.Report(clang::diag::err_drv_invalid_value)
|
|
|
|
<< a->getOption().getName() << val;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.getDefVals.line = optVals[0];
|
|
|
|
opts.getDefVals.startColumn = optVals[1];
|
|
|
|
opts.getDefVals.endColumn = optVals[2];
|
2021-04-14 10:43:14 +00:00
|
|
|
}
|
2020-09-11 10:17:31 +01:00
|
|
|
}
|
|
|
|
|
2021-08-12 11:42:08 +01:00
|
|
|
// Parsing -load <dsopath> option and storing shared object path
|
|
|
|
if (llvm::opt::Arg *a = args.getLastArg(clang::driver::options::OPT_load)) {
|
|
|
|
opts.plugins.push_back(a->getValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parsing -plugin <name> option and storing plugin name and setting action
|
|
|
|
if (const llvm::opt::Arg *a =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_plugin)) {
|
|
|
|
opts.programAction = PluginAction;
|
2022-04-29 17:36:26 +00:00
|
|
|
opts.actionName = a->getValue();
|
2021-08-12 11:42:08 +01:00
|
|
|
}
|
|
|
|
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.outputFile = args.getLastArgValue(clang::driver::options::OPT_o);
|
|
|
|
opts.showHelp = args.hasArg(clang::driver::options::OPT_help);
|
|
|
|
opts.showVersion = args.hasArg(clang::driver::options::OPT_version);
|
2020-09-11 10:17:31 +01:00
|
|
|
|
|
|
|
// Get the input kind (from the value passed via `-x`)
|
|
|
|
InputKind dashX(Language::Unknown);
|
|
|
|
if (const llvm::opt::Arg *a =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_x)) {
|
2022-04-29 17:36:26 +00:00
|
|
|
llvm::StringRef xValue = a->getValue();
|
2020-09-11 10:17:31 +01:00
|
|
|
// Principal languages.
|
2022-04-29 17:36:26 +00:00
|
|
|
dashX = llvm::StringSwitch<InputKind>(xValue)
|
2022-06-06 17:57:33 +00:00
|
|
|
// Flang does not differentiate between pre-processed and not
|
|
|
|
// pre-processed inputs.
|
|
|
|
.Case("f95", Language::Fortran)
|
|
|
|
.Case("f95-cpp-input", Language::Fortran)
|
2020-09-11 10:17:31 +01:00
|
|
|
.Default(Language::Unknown);
|
|
|
|
|
2022-06-01 16:00:31 +00:00
|
|
|
// Flang's intermediate representations.
|
2022-04-29 17:36:26 +00:00
|
|
|
if (dashX.isUnknown())
|
|
|
|
dashX = llvm::StringSwitch<InputKind>(xValue)
|
2020-09-11 10:17:31 +01:00
|
|
|
.Case("ir", Language::LLVM_IR)
|
2022-06-01 16:00:31 +00:00
|
|
|
.Case("fir", Language::MLIR)
|
|
|
|
.Case("mlir", Language::MLIR)
|
2020-09-11 10:17:31 +01:00
|
|
|
.Default(Language::Unknown);
|
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
if (dashX.isUnknown())
|
2020-09-11 10:17:31 +01:00
|
|
|
diags.Report(clang::diag::err_drv_invalid_value)
|
|
|
|
<< a->getAsString(args) << a->getValue();
|
|
|
|
}
|
|
|
|
|
2020-10-24 12:33:19 +01:00
|
|
|
// Collect the input files and save them in our instance of FrontendOptions.
|
|
|
|
std::vector<std::string> inputs =
|
|
|
|
args.getAllArgValues(clang::driver::options::OPT_INPUT);
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.inputs.clear();
|
2020-10-24 12:33:19 +01:00
|
|
|
if (inputs.empty())
|
|
|
|
// '-' is the default input if none is given.
|
|
|
|
inputs.push_back("-");
|
|
|
|
for (unsigned i = 0, e = inputs.size(); i != e; ++i) {
|
|
|
|
InputKind ik = dashX;
|
2022-04-29 17:36:26 +00:00
|
|
|
if (ik.isUnknown()) {
|
|
|
|
ik = FrontendOptions::getInputKindForExtension(
|
2020-10-24 12:33:19 +01:00
|
|
|
llvm::StringRef(inputs[i]).rsplit('.').second);
|
2022-04-29 17:36:26 +00:00
|
|
|
if (ik.isUnknown())
|
2020-10-24 12:33:19 +01:00
|
|
|
ik = Language::Unknown;
|
|
|
|
if (i == 0)
|
|
|
|
dashX = ik;
|
|
|
|
}
|
|
|
|
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.inputs.emplace_back(std::move(inputs[i]), ik);
|
2020-10-24 12:33:19 +01:00
|
|
|
}
|
2021-01-26 16:27:30 +00:00
|
|
|
|
2021-07-29 12:39:10 +00:00
|
|
|
// Set fortranForm based on options -ffree-form and -ffixed-form.
|
2022-11-02 14:31:14 -07:00
|
|
|
if (const auto *arg =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_ffixed_form,
|
|
|
|
clang::driver::options::OPT_ffree_form)) {
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.fortranForm =
|
2021-01-26 16:27:30 +00:00
|
|
|
arg->getOption().matches(clang::driver::options::OPT_ffixed_form)
|
2022-11-02 14:31:14 -07:00
|
|
|
? FortranForm::FixedForm
|
|
|
|
: FortranForm::FreeForm;
|
2021-01-26 16:27:30 +00:00
|
|
|
}
|
|
|
|
|
2021-07-29 12:39:10 +00:00
|
|
|
// Set fixedFormColumns based on -ffixed-line-length=<value>
|
2021-01-26 16:27:30 +00:00
|
|
|
if (const auto *arg =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_ffixed_line_length_EQ)) {
|
|
|
|
llvm::StringRef argValue = llvm::StringRef(arg->getValue());
|
|
|
|
std::int64_t columns = -1;
|
|
|
|
if (argValue == "none") {
|
|
|
|
columns = 0;
|
|
|
|
} else if (argValue.getAsInteger(/*Radix=*/10, columns)) {
|
|
|
|
columns = -1;
|
|
|
|
}
|
|
|
|
if (columns < 0) {
|
2021-05-05 11:01:33 -07:00
|
|
|
diags.Report(clang::diag::err_drv_negative_columns)
|
|
|
|
<< arg->getOption().getName() << arg->getValue();
|
2021-01-26 16:27:30 +00:00
|
|
|
} else if (columns == 0) {
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.fixedFormColumns = 1000000;
|
2021-01-26 16:27:30 +00:00
|
|
|
} else if (columns < 7) {
|
2021-05-05 11:01:33 -07:00
|
|
|
diags.Report(clang::diag::err_drv_small_columns)
|
|
|
|
<< arg->getOption().getName() << arg->getValue() << "7";
|
2021-01-26 16:27:30 +00:00
|
|
|
} else {
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.fixedFormColumns = columns;
|
2021-01-26 16:27:30 +00:00
|
|
|
}
|
|
|
|
}
|
2021-02-10 09:24:45 +00:00
|
|
|
|
2022-07-19 11:47:25 -07:00
|
|
|
// Set conversion based on -fconvert=<value>
|
|
|
|
if (const auto *arg =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_fconvert_EQ)) {
|
|
|
|
const char *argValue = arg->getValue();
|
|
|
|
if (auto convert = parseConvertArg(argValue))
|
|
|
|
opts.envDefaults.push_back({"FORT_CONVERT", *convert});
|
|
|
|
else
|
|
|
|
diags.Report(clang::diag::err_drv_invalid_value)
|
|
|
|
<< arg->getAsString(args) << argValue;
|
|
|
|
}
|
|
|
|
|
[flang][driver] Refactor boolean options
For boolean options, e.g. `-fxor-operator`/`-fno-xor-operator`, we ought
to be using TableGen multi-classes. This way, we only have to write one
definition to have both forms auto-generated. This patch refactors all
of Flang's boolean options to use two new multi-classes:
`OptInFC1FFOption` and `OptOutFC1FFOption`. These multi-classes are
based on `OptInFFOption`/`OptOutFFOption`, respectively. I've also
simplified the processing of the updated options in
CompilerInvocation.cpp.
With the new approach, "empty" help text (i.e. no `HelpText`) is now
replaced with an empty string (i.e. HelpText<"">). When running
flang-new --help, that's considered as non-empty help messages, which is
then printed (that's controlled by `printHelp` from
llvm/lib/Option/OptTable.cpp). This means that with this patch,
flang-new --help will start printing e.g. -fno-backslash, even though
there is no actual help text to print for this option (apart from the
empty string ""). Tests are updated accordingly.
Note that with this patch, both `-fxor-operator` and `-fno-xor-operator`
(and other boolean options refactored here) remain available in
`flang-new` and `flang-new -fc1`. In this respect, nothing changes. In a
forthcoming patch, I will refine this so that `flang-new -fc1` only
accepts `-ffoo` (`OptInFC1FFOption`) or `-fno-foo` (`OptOutCC1FFOption`).
For clarity, `OptInFFOption`/`OptOutFFOption` are renamed as
`OptInCC1FFOption`/`OptOutCC1FFOption`, respectively. Otherwise, this is
an NFC from Clang's perspective.
Differential Revision: https://reviews.llvm.org/D105881
2021-06-30 10:57:48 +00:00
|
|
|
// -f{no-}implicit-none
|
|
|
|
opts.features.Enable(
|
|
|
|
Fortran::common::LanguageFeature::ImplicitNoneTypeAlways,
|
|
|
|
args.hasFlag(clang::driver::options::OPT_fimplicit_none,
|
2022-11-02 14:31:14 -07:00
|
|
|
clang::driver::options::OPT_fno_implicit_none, false));
|
[flang][driver] Refactor boolean options
For boolean options, e.g. `-fxor-operator`/`-fno-xor-operator`, we ought
to be using TableGen multi-classes. This way, we only have to write one
definition to have both forms auto-generated. This patch refactors all
of Flang's boolean options to use two new multi-classes:
`OptInFC1FFOption` and `OptOutFC1FFOption`. These multi-classes are
based on `OptInFFOption`/`OptOutFFOption`, respectively. I've also
simplified the processing of the updated options in
CompilerInvocation.cpp.
With the new approach, "empty" help text (i.e. no `HelpText`) is now
replaced with an empty string (i.e. HelpText<"">). When running
flang-new --help, that's considered as non-empty help messages, which is
then printed (that's controlled by `printHelp` from
llvm/lib/Option/OptTable.cpp). This means that with this patch,
flang-new --help will start printing e.g. -fno-backslash, even though
there is no actual help text to print for this option (apart from the
empty string ""). Tests are updated accordingly.
Note that with this patch, both `-fxor-operator` and `-fno-xor-operator`
(and other boolean options refactored here) remain available in
`flang-new` and `flang-new -fc1`. In this respect, nothing changes. In a
forthcoming patch, I will refine this so that `flang-new -fc1` only
accepts `-ffoo` (`OptInFC1FFOption`) or `-fno-foo` (`OptOutCC1FFOption`).
For clarity, `OptInFFOption`/`OptOutFFOption` are renamed as
`OptInCC1FFOption`/`OptOutCC1FFOption`, respectively. Otherwise, this is
an NFC from Clang's perspective.
Differential Revision: https://reviews.llvm.org/D105881
2021-06-30 10:57:48 +00:00
|
|
|
|
|
|
|
// -f{no-}backslash
|
|
|
|
opts.features.Enable(Fortran::common::LanguageFeature::BackslashEscapes,
|
2022-11-02 14:31:14 -07:00
|
|
|
args.hasFlag(clang::driver::options::OPT_fbackslash,
|
|
|
|
clang::driver::options::OPT_fno_backslash,
|
|
|
|
false));
|
[flang][driver] Refactor boolean options
For boolean options, e.g. `-fxor-operator`/`-fno-xor-operator`, we ought
to be using TableGen multi-classes. This way, we only have to write one
definition to have both forms auto-generated. This patch refactors all
of Flang's boolean options to use two new multi-classes:
`OptInFC1FFOption` and `OptOutFC1FFOption`. These multi-classes are
based on `OptInFFOption`/`OptOutFFOption`, respectively. I've also
simplified the processing of the updated options in
CompilerInvocation.cpp.
With the new approach, "empty" help text (i.e. no `HelpText`) is now
replaced with an empty string (i.e. HelpText<"">). When running
flang-new --help, that's considered as non-empty help messages, which is
then printed (that's controlled by `printHelp` from
llvm/lib/Option/OptTable.cpp). This means that with this patch,
flang-new --help will start printing e.g. -fno-backslash, even though
there is no actual help text to print for this option (apart from the
empty string ""). Tests are updated accordingly.
Note that with this patch, both `-fxor-operator` and `-fno-xor-operator`
(and other boolean options refactored here) remain available in
`flang-new` and `flang-new -fc1`. In this respect, nothing changes. In a
forthcoming patch, I will refine this so that `flang-new -fc1` only
accepts `-ffoo` (`OptInFC1FFOption`) or `-fno-foo` (`OptOutCC1FFOption`).
For clarity, `OptInFFOption`/`OptOutFFOption` are renamed as
`OptInCC1FFOption`/`OptOutCC1FFOption`, respectively. Otherwise, this is
an NFC from Clang's perspective.
Differential Revision: https://reviews.llvm.org/D105881
2021-06-30 10:57:48 +00:00
|
|
|
|
|
|
|
// -f{no-}logical-abbreviations
|
2022-11-02 14:31:14 -07:00
|
|
|
opts.features.Enable(
|
|
|
|
Fortran::common::LanguageFeature::LogicalAbbreviations,
|
[flang][driver] Refactor boolean options
For boolean options, e.g. `-fxor-operator`/`-fno-xor-operator`, we ought
to be using TableGen multi-classes. This way, we only have to write one
definition to have both forms auto-generated. This patch refactors all
of Flang's boolean options to use two new multi-classes:
`OptInFC1FFOption` and `OptOutFC1FFOption`. These multi-classes are
based on `OptInFFOption`/`OptOutFFOption`, respectively. I've also
simplified the processing of the updated options in
CompilerInvocation.cpp.
With the new approach, "empty" help text (i.e. no `HelpText`) is now
replaced with an empty string (i.e. HelpText<"">). When running
flang-new --help, that's considered as non-empty help messages, which is
then printed (that's controlled by `printHelp` from
llvm/lib/Option/OptTable.cpp). This means that with this patch,
flang-new --help will start printing e.g. -fno-backslash, even though
there is no actual help text to print for this option (apart from the
empty string ""). Tests are updated accordingly.
Note that with this patch, both `-fxor-operator` and `-fno-xor-operator`
(and other boolean options refactored here) remain available in
`flang-new` and `flang-new -fc1`. In this respect, nothing changes. In a
forthcoming patch, I will refine this so that `flang-new -fc1` only
accepts `-ffoo` (`OptInFC1FFOption`) or `-fno-foo` (`OptOutCC1FFOption`).
For clarity, `OptInFFOption`/`OptOutFFOption` are renamed as
`OptInCC1FFOption`/`OptOutCC1FFOption`, respectively. Otherwise, this is
an NFC from Clang's perspective.
Differential Revision: https://reviews.llvm.org/D105881
2021-06-30 10:57:48 +00:00
|
|
|
args.hasFlag(clang::driver::options::OPT_flogical_abbreviations,
|
2022-11-02 14:31:14 -07:00
|
|
|
clang::driver::options::OPT_fno_logical_abbreviations,
|
|
|
|
false));
|
[flang][driver] Refactor boolean options
For boolean options, e.g. `-fxor-operator`/`-fno-xor-operator`, we ought
to be using TableGen multi-classes. This way, we only have to write one
definition to have both forms auto-generated. This patch refactors all
of Flang's boolean options to use two new multi-classes:
`OptInFC1FFOption` and `OptOutFC1FFOption`. These multi-classes are
based on `OptInFFOption`/`OptOutFFOption`, respectively. I've also
simplified the processing of the updated options in
CompilerInvocation.cpp.
With the new approach, "empty" help text (i.e. no `HelpText`) is now
replaced with an empty string (i.e. HelpText<"">). When running
flang-new --help, that's considered as non-empty help messages, which is
then printed (that's controlled by `printHelp` from
llvm/lib/Option/OptTable.cpp). This means that with this patch,
flang-new --help will start printing e.g. -fno-backslash, even though
there is no actual help text to print for this option (apart from the
empty string ""). Tests are updated accordingly.
Note that with this patch, both `-fxor-operator` and `-fno-xor-operator`
(and other boolean options refactored here) remain available in
`flang-new` and `flang-new -fc1`. In this respect, nothing changes. In a
forthcoming patch, I will refine this so that `flang-new -fc1` only
accepts `-ffoo` (`OptInFC1FFOption`) or `-fno-foo` (`OptOutCC1FFOption`).
For clarity, `OptInFFOption`/`OptOutFFOption` are renamed as
`OptInCC1FFOption`/`OptOutCC1FFOption`, respectively. Otherwise, this is
an NFC from Clang's perspective.
Differential Revision: https://reviews.llvm.org/D105881
2021-06-30 10:57:48 +00:00
|
|
|
|
|
|
|
// -f{no-}xor-operator
|
2022-11-02 14:31:14 -07:00
|
|
|
opts.features.Enable(
|
|
|
|
Fortran::common::LanguageFeature::XOROperator,
|
[flang][driver] Refactor boolean options
For boolean options, e.g. `-fxor-operator`/`-fno-xor-operator`, we ought
to be using TableGen multi-classes. This way, we only have to write one
definition to have both forms auto-generated. This patch refactors all
of Flang's boolean options to use two new multi-classes:
`OptInFC1FFOption` and `OptOutFC1FFOption`. These multi-classes are
based on `OptInFFOption`/`OptOutFFOption`, respectively. I've also
simplified the processing of the updated options in
CompilerInvocation.cpp.
With the new approach, "empty" help text (i.e. no `HelpText`) is now
replaced with an empty string (i.e. HelpText<"">). When running
flang-new --help, that's considered as non-empty help messages, which is
then printed (that's controlled by `printHelp` from
llvm/lib/Option/OptTable.cpp). This means that with this patch,
flang-new --help will start printing e.g. -fno-backslash, even though
there is no actual help text to print for this option (apart from the
empty string ""). Tests are updated accordingly.
Note that with this patch, both `-fxor-operator` and `-fno-xor-operator`
(and other boolean options refactored here) remain available in
`flang-new` and `flang-new -fc1`. In this respect, nothing changes. In a
forthcoming patch, I will refine this so that `flang-new -fc1` only
accepts `-ffoo` (`OptInFC1FFOption`) or `-fno-foo` (`OptOutCC1FFOption`).
For clarity, `OptInFFOption`/`OptOutFFOption` are renamed as
`OptInCC1FFOption`/`OptOutCC1FFOption`, respectively. Otherwise, this is
an NFC from Clang's perspective.
Differential Revision: https://reviews.llvm.org/D105881
2021-06-30 10:57:48 +00:00
|
|
|
args.hasFlag(clang::driver::options::OPT_fxor_operator,
|
2022-11-02 14:31:14 -07:00
|
|
|
clang::driver::options::OPT_fno_xor_operator, false));
|
[flang][driver] Refactor boolean options
For boolean options, e.g. `-fxor-operator`/`-fno-xor-operator`, we ought
to be using TableGen multi-classes. This way, we only have to write one
definition to have both forms auto-generated. This patch refactors all
of Flang's boolean options to use two new multi-classes:
`OptInFC1FFOption` and `OptOutFC1FFOption`. These multi-classes are
based on `OptInFFOption`/`OptOutFFOption`, respectively. I've also
simplified the processing of the updated options in
CompilerInvocation.cpp.
With the new approach, "empty" help text (i.e. no `HelpText`) is now
replaced with an empty string (i.e. HelpText<"">). When running
flang-new --help, that's considered as non-empty help messages, which is
then printed (that's controlled by `printHelp` from
llvm/lib/Option/OptTable.cpp). This means that with this patch,
flang-new --help will start printing e.g. -fno-backslash, even though
there is no actual help text to print for this option (apart from the
empty string ""). Tests are updated accordingly.
Note that with this patch, both `-fxor-operator` and `-fno-xor-operator`
(and other boolean options refactored here) remain available in
`flang-new` and `flang-new -fc1`. In this respect, nothing changes. In a
forthcoming patch, I will refine this so that `flang-new -fc1` only
accepts `-ffoo` (`OptInFC1FFOption`) or `-fno-foo` (`OptOutCC1FFOption`).
For clarity, `OptInFFOption`/`OptOutFFOption` are renamed as
`OptInCC1FFOption`/`OptOutCC1FFOption`, respectively. Otherwise, this is
an NFC from Clang's perspective.
Differential Revision: https://reviews.llvm.org/D105881
2021-06-30 10:57:48 +00:00
|
|
|
|
[flang] Add -fno-automatic, refine IsSaved()
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
2021-11-18 11:48:42 -08:00
|
|
|
// -fno-automatic
|
|
|
|
if (args.hasArg(clang::driver::options::OPT_fno_automatic)) {
|
|
|
|
opts.features.Enable(Fortran::common::LanguageFeature::DefaultSave);
|
|
|
|
}
|
|
|
|
|
2021-02-04 21:11:22 +00:00
|
|
|
if (args.hasArg(
|
|
|
|
clang::driver::options::OPT_falternative_parameter_statement)) {
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.features.Enable(Fortran::common::LanguageFeature::OldStyleParameter);
|
2021-02-04 21:11:22 +00:00
|
|
|
}
|
|
|
|
if (const llvm::opt::Arg *arg =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_finput_charset_EQ)) {
|
|
|
|
llvm::StringRef argValue = arg->getValue();
|
|
|
|
if (argValue == "utf-8") {
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.encoding = Fortran::parser::Encoding::UTF_8;
|
2021-02-04 21:11:22 +00:00
|
|
|
} else if (argValue == "latin-1") {
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.encoding = Fortran::parser::Encoding::LATIN_1;
|
2021-02-04 21:11:22 +00:00
|
|
|
} else {
|
|
|
|
diags.Report(clang::diag::err_drv_invalid_value)
|
|
|
|
<< arg->getAsString(args) << argValue;
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 17:59:17 +00:00
|
|
|
|
|
|
|
setUpFrontendBasedOnAction(opts);
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.dashX = dashX;
|
2021-04-14 10:43:14 +00:00
|
|
|
|
|
|
|
return diags.getNumErrors() == numErrorsBefore;
|
2020-09-11 10:17:31 +01:00
|
|
|
}
|
|
|
|
|
2021-03-23 12:24:57 -04:00
|
|
|
// Generate the path to look for intrinsic modules
|
|
|
|
static std::string getIntrinsicDir() {
|
|
|
|
// TODO: Find a system independent API
|
|
|
|
llvm::SmallString<128> driverPath;
|
|
|
|
driverPath.assign(llvm::sys::fs::getMainExecutable(nullptr, nullptr));
|
|
|
|
llvm::sys::path::remove_filename(driverPath);
|
|
|
|
driverPath.append("/../include/flang/");
|
|
|
|
return std::string(driverPath);
|
|
|
|
}
|
|
|
|
|
2022-03-18 16:20:56 +00:00
|
|
|
// Generate the path to look for OpenMP headers
|
|
|
|
static std::string getOpenMPHeadersDir() {
|
|
|
|
llvm::SmallString<128> includePath;
|
|
|
|
includePath.assign(llvm::sys::fs::getMainExecutable(nullptr, nullptr));
|
|
|
|
llvm::sys::path::remove_filename(includePath);
|
|
|
|
includePath.append("/../include/flang/OpenMP/");
|
|
|
|
return std::string(includePath);
|
|
|
|
}
|
|
|
|
|
2021-01-06 15:42:24 +00:00
|
|
|
/// Parses all preprocessor input arguments and populates the preprocessor
|
|
|
|
/// options accordingly.
|
|
|
|
///
|
|
|
|
/// \param [in] opts The preprocessor options instance
|
|
|
|
/// \param [out] args The list of input arguments
|
2022-11-02 14:31:14 -07:00
|
|
|
static void parsePreprocessorArgs(Fortran::frontend::PreprocessorOptions &opts,
|
|
|
|
llvm::opt::ArgList &args) {
|
2021-01-06 15:42:24 +00:00
|
|
|
// Add macros from the command line.
|
2022-11-02 14:31:14 -07:00
|
|
|
for (const auto *currentArg : args.filtered(clang::driver::options::OPT_D,
|
|
|
|
clang::driver::options::OPT_U)) {
|
2021-01-06 15:42:24 +00:00
|
|
|
if (currentArg->getOption().matches(clang::driver::options::OPT_D)) {
|
|
|
|
opts.addMacroDef(currentArg->getValue());
|
|
|
|
} else {
|
|
|
|
opts.addMacroUndef(currentArg->getValue());
|
|
|
|
}
|
|
|
|
}
|
2021-01-19 10:01:38 +00:00
|
|
|
|
|
|
|
// Add the ordered list of -I's.
|
|
|
|
for (const auto *currentArg : args.filtered(clang::driver::options::OPT_I))
|
|
|
|
opts.searchDirectoriesFromDashI.emplace_back(currentArg->getValue());
|
2021-03-23 12:24:57 -04:00
|
|
|
|
|
|
|
// Prepend the ordered list of -intrinsic-modules-path
|
|
|
|
// to the default location to search.
|
|
|
|
for (const auto *currentArg :
|
2022-11-02 14:31:14 -07:00
|
|
|
args.filtered(clang::driver::options::OPT_fintrinsic_modules_path))
|
2021-03-23 12:24:57 -04:00
|
|
|
opts.searchDirectoriesFromIntrModPath.emplace_back(currentArg->getValue());
|
2021-04-07 11:42:37 +00:00
|
|
|
|
|
|
|
// -cpp/-nocpp
|
|
|
|
if (const auto *currentArg = args.getLastArg(
|
|
|
|
clang::driver::options::OPT_cpp, clang::driver::options::OPT_nocpp))
|
2021-07-29 12:39:10 +00:00
|
|
|
opts.macrosFlag =
|
2021-04-07 11:42:37 +00:00
|
|
|
(currentArg->getOption().matches(clang::driver::options::OPT_cpp))
|
2022-11-02 14:31:14 -07:00
|
|
|
? PPMacrosFlag::Include
|
|
|
|
: PPMacrosFlag::Exclude;
|
2021-07-23 16:41:04 -07:00
|
|
|
|
|
|
|
opts.noReformat = args.hasArg(clang::driver::options::OPT_fno_reformat);
|
|
|
|
opts.noLineDirectives = args.hasArg(clang::driver::options::OPT_P);
|
2021-01-06 15:42:24 +00:00
|
|
|
}
|
|
|
|
|
2021-02-04 16:13:04 +00:00
|
|
|
/// Parses all semantic related arguments and populates the variables
|
2021-04-14 11:42:11 +00:00
|
|
|
/// options accordingly. Returns false if new errors are generated.
|
|
|
|
static bool parseSemaArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
|
2022-11-02 14:31:14 -07:00
|
|
|
clang::DiagnosticsEngine &diags) {
|
2021-04-14 11:42:11 +00:00
|
|
|
unsigned numErrorsBefore = diags.getNumErrors();
|
2021-02-04 16:13:04 +00:00
|
|
|
|
2021-03-11 07:35:45 -05:00
|
|
|
// -J/module-dir option
|
2021-02-04 16:13:04 +00:00
|
|
|
auto moduleDirList =
|
|
|
|
args.getAllArgValues(clang::driver::options::OPT_module_dir);
|
|
|
|
// User can only specify -J/-module-dir once
|
|
|
|
// https://gcc.gnu.org/onlinedocs/gfortran/Directory-Options.html
|
|
|
|
if (moduleDirList.size() > 1) {
|
|
|
|
const unsigned diagID =
|
|
|
|
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
|
2022-11-02 14:31:14 -07:00
|
|
|
"Only one '-module-dir/-J' option allowed");
|
2021-02-04 16:13:04 +00:00
|
|
|
diags.Report(diagID);
|
|
|
|
}
|
|
|
|
if (moduleDirList.size() == 1)
|
2022-04-29 17:36:26 +00:00
|
|
|
res.setModuleDir(moduleDirList[0]);
|
2021-03-11 07:35:45 -05:00
|
|
|
|
|
|
|
// -fdebug-module-writer option
|
|
|
|
if (args.hasArg(clang::driver::options::OPT_fdebug_module_writer)) {
|
2022-04-29 17:36:26 +00:00
|
|
|
res.setDebugModuleDir(true);
|
2021-03-11 07:35:45 -05:00
|
|
|
}
|
2021-04-14 11:42:11 +00:00
|
|
|
|
2021-06-04 13:58:03 +01:00
|
|
|
// -module-suffix
|
|
|
|
if (const auto *moduleSuffix =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_module_suffix)) {
|
2022-04-29 17:36:26 +00:00
|
|
|
res.setModuleFileSuffix(moduleSuffix->getValue());
|
2021-06-04 13:58:03 +01:00
|
|
|
}
|
|
|
|
|
[flang][driver] Refactor boolean options
For boolean options, e.g. `-fxor-operator`/`-fno-xor-operator`, we ought
to be using TableGen multi-classes. This way, we only have to write one
definition to have both forms auto-generated. This patch refactors all
of Flang's boolean options to use two new multi-classes:
`OptInFC1FFOption` and `OptOutFC1FFOption`. These multi-classes are
based on `OptInFFOption`/`OptOutFFOption`, respectively. I've also
simplified the processing of the updated options in
CompilerInvocation.cpp.
With the new approach, "empty" help text (i.e. no `HelpText`) is now
replaced with an empty string (i.e. HelpText<"">). When running
flang-new --help, that's considered as non-empty help messages, which is
then printed (that's controlled by `printHelp` from
llvm/lib/Option/OptTable.cpp). This means that with this patch,
flang-new --help will start printing e.g. -fno-backslash, even though
there is no actual help text to print for this option (apart from the
empty string ""). Tests are updated accordingly.
Note that with this patch, both `-fxor-operator` and `-fno-xor-operator`
(and other boolean options refactored here) remain available in
`flang-new` and `flang-new -fc1`. In this respect, nothing changes. In a
forthcoming patch, I will refine this so that `flang-new -fc1` only
accepts `-ffoo` (`OptInFC1FFOption`) or `-fno-foo` (`OptOutCC1FFOption`).
For clarity, `OptInFFOption`/`OptOutFFOption` are renamed as
`OptInCC1FFOption`/`OptOutCC1FFOption`, respectively. Otherwise, this is
an NFC from Clang's perspective.
Differential Revision: https://reviews.llvm.org/D105881
2021-06-30 10:57:48 +00:00
|
|
|
// -f{no-}analyzed-objects-for-unparse
|
2022-04-29 17:36:26 +00:00
|
|
|
res.setUseAnalyzedObjectsForUnparse(args.hasFlag(
|
|
|
|
clang::driver::options::OPT_fanalyzed_objects_for_unparse,
|
|
|
|
clang::driver::options::OPT_fno_analyzed_objects_for_unparse, true));
|
2021-06-04 15:25:58 +01:00
|
|
|
|
2021-04-14 11:42:11 +00:00
|
|
|
return diags.getNumErrors() == numErrorsBefore;
|
2021-02-04 16:13:04 +00:00
|
|
|
}
|
|
|
|
|
2021-04-05 12:41:46 -04:00
|
|
|
/// Parses all diagnostics related arguments and populates the variables
|
2021-04-14 11:42:11 +00:00
|
|
|
/// options accordingly. Returns false if new errors are generated.
|
|
|
|
static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
|
2022-11-02 14:31:14 -07:00
|
|
|
clang::DiagnosticsEngine &diags) {
|
2021-04-14 11:42:11 +00:00
|
|
|
unsigned numErrorsBefore = diags.getNumErrors();
|
|
|
|
|
2021-04-05 12:41:46 -04:00
|
|
|
// -Werror option
|
|
|
|
// TODO: Currently throws a Diagnostic for anything other than -W<error>,
|
|
|
|
// this has to change when other -W<opt>'s are supported.
|
|
|
|
if (args.hasArg(clang::driver::options::OPT_W_Joined)) {
|
|
|
|
if (args.getLastArgValue(clang::driver::options::OPT_W_Joined)
|
|
|
|
.equals("error")) {
|
2022-04-29 17:36:26 +00:00
|
|
|
res.setWarnAsErr(true);
|
2021-04-05 12:41:46 -04:00
|
|
|
} else {
|
|
|
|
const unsigned diagID =
|
|
|
|
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
|
2022-11-02 14:31:14 -07:00
|
|
|
"Only `-Werror` is supported currently.");
|
2021-04-05 12:41:46 -04:00
|
|
|
diags.Report(diagID);
|
|
|
|
}
|
|
|
|
}
|
2021-04-14 11:42:11 +00:00
|
|
|
|
[flang][Driver] Refine _when_ driver diagnostics are formatted
This patch refines //when// driver diagnostics are formatted so that
`flang-new` and `flang-new -fc1` behave consistently with `clang` and
`clang -cc1`, respectively. This change only applies to driver diagnostics.
Scanning, parsing and semantic diagnostics are separate and not covered here.
**NEW BEHAVIOUR**
To illustrate the new behaviour, consider the following input file:
```! file.f90
program m
integer :: i = k
end
```
In the following invocations, "error: Semantic errors in file.f90" _will be_
formatted:
```
$ flang-new file.f90
error: Semantic errors in file.f90
./file.f90:2:18: error: Must be a constant value
integer :: i = k
$ flang-new -fc1 -fcolor-diagnostics file.f90
error: Semantic errors in file.f90
./file.f90:2:18: error: Must be a constant value
integer :: i = k
```
However, in the following invocations, "error: Semantic errors in file.f90"
_will not be_ formatted:
```
$ flang-new -fno-color-diagnostics file.f90
error: Semantic errors in file.f90
./file.f90:2:18: error: Must be a constant value
integer :: i = k
$ flang-new -fc1 file.f90
error: Semantic errors in file.f90
./file.f90:2:18: error: Must be a constant value
integer :: i = k
```
Before this change, none of the above would be formatted. Note also that the
default behaviour in `flang-new` is different to `flang-new -fc1` (this is
consistent with Clang).
**NOTES ON IMPLEMENTATION**
Note that the diagnostic options are parsed in `createAndPopulateDiagOpt`s in
driver.cpp. That's where the driver's `DiagnosticEngine` options are set. Like
most command-line compiler driver options, these flags are "claimed" in
Flang.cpp (i.e. when creating a frontend driver invocation) by calling
`getLastArg` rather than in driver.cpp.
In Clang's Options.td, `defm color_diagnostics` is replaced with two separate
definitions: `def fcolor_diagnostics` and def fno_color_diagnostics`. That's
because originally `color_diagnostics` derived from `OptInCC1FFlag`, which is a
multiclass for opt-in options in CC1. In order to preserve the current
behaviour in `clang -cc1` (i.e. to keep `-fno-color-diagnostics` unavailable in
`clang -cc1`) and to implement similar behaviour in `flang-new -fc1`, we can't
re-use `OptInCC1FFlag`.
Formatting is only available in consoles that support it and will normally mean that
the message is printed in bold + color.
Co-authored-by: Andrzej Warzynski <andrzej.warzynski@arm.com>
Reviewed By: rovka
Differential Revision: https://reviews.llvm.org/D126164
2022-06-22 23:56:34 +08:00
|
|
|
// Default to off for `flang-new -fc1`.
|
|
|
|
res.getFrontendOpts().showColors =
|
|
|
|
parseShowColorsArgs(args, /*defaultDiagColor=*/false);
|
|
|
|
|
2021-04-14 11:42:11 +00:00
|
|
|
return diags.getNumErrors() == numErrorsBefore;
|
2021-04-05 12:41:46 -04:00
|
|
|
}
|
|
|
|
|
2021-03-03 16:28:11 +00:00
|
|
|
/// Parses all Dialect related arguments and populates the variables
|
2021-04-14 11:42:11 +00:00
|
|
|
/// options accordingly. Returns false if new errors are generated.
|
|
|
|
static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
|
2022-11-02 14:31:14 -07:00
|
|
|
clang::DiagnosticsEngine &diags) {
|
2021-04-14 11:42:11 +00:00
|
|
|
unsigned numErrorsBefore = diags.getNumErrors();
|
2021-03-03 16:28:11 +00:00
|
|
|
|
|
|
|
// -fdefault* family
|
|
|
|
if (args.hasArg(clang::driver::options::OPT_fdefault_real_8)) {
|
2022-04-29 17:36:26 +00:00
|
|
|
res.getDefaultKinds().set_defaultRealKind(8);
|
|
|
|
res.getDefaultKinds().set_doublePrecisionKind(16);
|
2021-03-03 16:28:11 +00:00
|
|
|
}
|
|
|
|
if (args.hasArg(clang::driver::options::OPT_fdefault_integer_8)) {
|
2022-04-29 17:36:26 +00:00
|
|
|
res.getDefaultKinds().set_defaultIntegerKind(8);
|
|
|
|
res.getDefaultKinds().set_subscriptIntegerKind(8);
|
|
|
|
res.getDefaultKinds().set_sizeIntegerKind(8);
|
2021-03-03 16:28:11 +00:00
|
|
|
}
|
|
|
|
if (args.hasArg(clang::driver::options::OPT_fdefault_double_8)) {
|
|
|
|
if (!args.hasArg(clang::driver::options::OPT_fdefault_real_8)) {
|
|
|
|
// -fdefault-double-8 has to be used with -fdefault-real-8
|
|
|
|
// to be compatible with gfortran
|
2022-11-02 14:31:14 -07:00
|
|
|
const unsigned diagID = diags.getCustomDiagID(
|
|
|
|
clang::DiagnosticsEngine::Error,
|
|
|
|
"Use of `-fdefault-double-8` requires `-fdefault-real-8`");
|
2021-03-03 16:28:11 +00:00
|
|
|
diags.Report(diagID);
|
|
|
|
}
|
|
|
|
// https://gcc.gnu.org/onlinedocs/gfortran/Fortran-Dialect-Options.html
|
2022-04-29 17:36:26 +00:00
|
|
|
res.getDefaultKinds().set_doublePrecisionKind(8);
|
2021-03-03 16:28:11 +00:00
|
|
|
}
|
|
|
|
if (args.hasArg(clang::driver::options::OPT_flarge_sizes))
|
2022-04-29 17:36:26 +00:00
|
|
|
res.getDefaultKinds().set_sizeIntegerKind(8);
|
2021-03-03 16:28:11 +00:00
|
|
|
|
|
|
|
// -fopenmp and -fopenacc
|
|
|
|
if (args.hasArg(clang::driver::options::OPT_fopenacc)) {
|
2022-04-29 17:36:26 +00:00
|
|
|
res.getFrontendOpts().features.Enable(
|
2021-03-03 16:28:11 +00:00
|
|
|
Fortran::common::LanguageFeature::OpenACC);
|
|
|
|
}
|
|
|
|
if (args.hasArg(clang::driver::options::OPT_fopenmp)) {
|
2022-04-29 17:36:26 +00:00
|
|
|
res.getFrontendOpts().features.Enable(
|
2021-03-03 16:28:11 +00:00
|
|
|
Fortran::common::LanguageFeature::OpenMP);
|
|
|
|
}
|
2021-03-25 13:02:05 -04:00
|
|
|
|
2021-03-25 18:59:48 +00:00
|
|
|
// -pedantic
|
2021-03-25 13:02:05 -04:00
|
|
|
if (args.hasArg(clang::driver::options::OPT_pedantic)) {
|
2022-04-29 17:36:26 +00:00
|
|
|
res.setEnableConformanceChecks();
|
2021-03-25 13:02:05 -04:00
|
|
|
}
|
2021-03-25 18:59:48 +00:00
|
|
|
// -std=f2018 (currently this implies -pedantic)
|
2021-03-25 13:02:05 -04:00
|
|
|
// TODO: Set proper options when more fortran standards
|
|
|
|
// are supported.
|
|
|
|
if (args.hasArg(clang::driver::options::OPT_std_EQ)) {
|
|
|
|
auto standard = args.getLastArgValue(clang::driver::options::OPT_std_EQ);
|
|
|
|
// We only allow f2018 as the given standard
|
|
|
|
if (standard.equals("f2018")) {
|
2022-04-29 17:36:26 +00:00
|
|
|
res.setEnableConformanceChecks();
|
2021-03-25 13:02:05 -04:00
|
|
|
} else {
|
|
|
|
const unsigned diagID =
|
|
|
|
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
|
2022-11-02 14:31:14 -07:00
|
|
|
"Only -std=f2018 is allowed currently.");
|
2021-03-25 13:02:05 -04:00
|
|
|
diags.Report(diagID);
|
|
|
|
}
|
|
|
|
}
|
2021-04-14 11:42:11 +00:00
|
|
|
return diags.getNumErrors() == numErrorsBefore;
|
2021-03-03 16:28:11 +00:00
|
|
|
}
|
|
|
|
|
2022-10-31 11:30:32 +00:00
|
|
|
/// Parses all floating point related arguments and populates the
|
|
|
|
/// CompilerInvocation accordingly.
|
|
|
|
/// Returns false if new errors are generated.
|
|
|
|
///
|
|
|
|
/// \param [out] invoc Stores the processed arguments
|
|
|
|
/// \param [in] args The compiler invocation arguments to parse
|
|
|
|
/// \param [out] diags DiagnosticsEngine to report erros with
|
|
|
|
static bool parseFloatingPointArgs(CompilerInvocation &invoc,
|
|
|
|
llvm::opt::ArgList &args,
|
|
|
|
clang::DiagnosticsEngine &diags) {
|
|
|
|
LangOptions &opts = invoc.getLangOpts();
|
|
|
|
const unsigned diagUnimplemented = diags.getCustomDiagID(
|
|
|
|
clang::DiagnosticsEngine::Warning, "%0 is not currently implemented");
|
|
|
|
|
|
|
|
if (const llvm::opt::Arg *a =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_ffp_contract)) {
|
|
|
|
const llvm::StringRef val = a->getValue();
|
|
|
|
enum LangOptions::FPModeKind fpContractMode;
|
|
|
|
|
|
|
|
if (val == "off")
|
|
|
|
fpContractMode = LangOptions::FPM_Off;
|
|
|
|
else if (val == "fast")
|
|
|
|
fpContractMode = LangOptions::FPM_Fast;
|
|
|
|
else {
|
|
|
|
diags.Report(clang::diag::err_drv_unsupported_option_argument)
|
|
|
|
<< a->getOption().getName() << val;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
diags.Report(diagUnimplemented) << a->getOption().getName();
|
|
|
|
opts.setFPContractMode(fpContractMode);
|
|
|
|
}
|
|
|
|
|
2022-10-17 17:16:24 +00:00
|
|
|
if (const llvm::opt::Arg *a =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_menable_no_infinities)) {
|
|
|
|
diags.Report(diagUnimplemented) << a->getOption().getName();
|
|
|
|
opts.NoHonorInfs = true;
|
|
|
|
}
|
|
|
|
|
2022-10-17 17:45:15 +00:00
|
|
|
if (const llvm::opt::Arg *a =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_menable_no_nans)) {
|
|
|
|
diags.Report(diagUnimplemented) << a->getOption().getName();
|
|
|
|
opts.NoHonorNaNs = true;
|
|
|
|
}
|
|
|
|
|
2022-10-18 16:14:52 +00:00
|
|
|
if (const llvm::opt::Arg *a =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_fapprox_func)) {
|
|
|
|
diags.Report(diagUnimplemented) << a->getOption().getName();
|
|
|
|
opts.ApproxFunc = true;
|
|
|
|
}
|
|
|
|
|
2022-10-18 17:59:03 +00:00
|
|
|
if (const llvm::opt::Arg *a =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_fno_signed_zeros)) {
|
|
|
|
diags.Report(diagUnimplemented) << a->getOption().getName();
|
|
|
|
opts.NoSignedZeros = true;
|
|
|
|
}
|
|
|
|
|
2022-10-19 10:33:12 +00:00
|
|
|
if (const llvm::opt::Arg *a =
|
|
|
|
args.getLastArg(clang::driver::options::OPT_mreassociate)) {
|
|
|
|
diags.Report(diagUnimplemented) << a->getOption().getName();
|
|
|
|
opts.AssociativeMath = true;
|
|
|
|
}
|
|
|
|
|
2022-10-31 11:30:32 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
bool CompilerInvocation::createFromArgs(
|
|
|
|
CompilerInvocation &res, llvm::ArrayRef<const char *> commandLineArgs,
|
2020-09-11 10:17:31 +01:00
|
|
|
clang::DiagnosticsEngine &diags) {
|
|
|
|
|
|
|
|
bool success = true;
|
|
|
|
|
[flang][driver] Define the default frontend driver triple
*SUMMARY*
Currently, the frontend driver assumes that a target triple is either:
* provided by the frontend itself (e.g. when lowering and generating
code),
* specified through the `-triple/-target` command line flags.
If `-triple/-target` is not used, the frontend will simply use the host
triple.
This is going to be insufficient when e.g. consuming an LLVM IR file
that has no triple specified (reading LLVM files is WIP, see D124667).
We shouldn't require the triple to be specified via the command line in
such situation. Instead, the frontend driver should contain a good
default, e.g. the host triple.
This patch updates Flang's `CompilerInvocation` to do just that, i.e.
defines its default target triple. Similarly to Clang:
* the default `CompilerInvocation` triple is set as the host triple,
* the value specified with `-triple` takes precedence over the frontend
driver default and the current module triple,
* the frontend driver default takes precedence over the module triple.
*TESTS*
This change requires 2 unit tests to be updated. That's because relevant
frontend actions are updated to assume that there's always a valid
triple available in the current `CompilerInvocation`. This update is
required because the unit tests bypass the regular `CompilerInvocation`
set-up (in particular, they don't call
`CompilerInvocation::CreateFromArgs`). I've also taken the liberty to
disable the pre-precossor formatting in the affected unit tests as well
(it is not required).
No new tests are added. As `flang-new -fc1` does not support consuming
LLVM IR files just yet, it is not possible to compile an LLVM IR file
without a triple. More specifically, atm all LLVM IR files are generated
and stored internally and the driver makes sure that these contain a
valid target triple. This is about to change in D124667 (which adds
support for reading LLVM IR/BC files) and that's where tests for
exercising the default frontend driver triple will be added.
*WHAT DOES CLANG DO?*
For reference, the default target triple for Clang's
`CompilerInvocation` is set through option marshalling infra [1] in
Options.td. Please check the definition of the `-triple` flag:
```
def triple : Separate<["-"], "triple">,
HelpText<"Specify target triple (e.g. i686-apple-darwin9)">,
MarshallingInfoString<TargetOpts<"Triple">, "llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple())">,
AlwaysEmit, Normalizer<"normalizeTriple">;
```
Ideally, we should re-use the marshalling infra in Flang.
[1] https://clang.llvm.org/docs/InternalsManual.html#option-marshalling-infrastructure
Differential Revision: https://reviews.llvm.org/D124664
2022-04-28 14:12:32 +00:00
|
|
|
// Set the default triple for this CompilerInvocation. This might be
|
|
|
|
// overridden by users with `-triple` (see the call to `ParseTargetArgs`
|
|
|
|
// below).
|
|
|
|
// NOTE: Like in Clang, it would be nice to use option marshalling
|
|
|
|
// for this so that the entire logic for setting-up the triple is in one
|
|
|
|
// place.
|
2022-04-29 17:36:26 +00:00
|
|
|
res.getTargetOpts().triple =
|
[flang][driver] Define the default frontend driver triple
*SUMMARY*
Currently, the frontend driver assumes that a target triple is either:
* provided by the frontend itself (e.g. when lowering and generating
code),
* specified through the `-triple/-target` command line flags.
If `-triple/-target` is not used, the frontend will simply use the host
triple.
This is going to be insufficient when e.g. consuming an LLVM IR file
that has no triple specified (reading LLVM files is WIP, see D124667).
We shouldn't require the triple to be specified via the command line in
such situation. Instead, the frontend driver should contain a good
default, e.g. the host triple.
This patch updates Flang's `CompilerInvocation` to do just that, i.e.
defines its default target triple. Similarly to Clang:
* the default `CompilerInvocation` triple is set as the host triple,
* the value specified with `-triple` takes precedence over the frontend
driver default and the current module triple,
* the frontend driver default takes precedence over the module triple.
*TESTS*
This change requires 2 unit tests to be updated. That's because relevant
frontend actions are updated to assume that there's always a valid
triple available in the current `CompilerInvocation`. This update is
required because the unit tests bypass the regular `CompilerInvocation`
set-up (in particular, they don't call
`CompilerInvocation::CreateFromArgs`). I've also taken the liberty to
disable the pre-precossor formatting in the affected unit tests as well
(it is not required).
No new tests are added. As `flang-new -fc1` does not support consuming
LLVM IR files just yet, it is not possible to compile an LLVM IR file
without a triple. More specifically, atm all LLVM IR files are generated
and stored internally and the driver makes sure that these contain a
valid target triple. This is about to change in D124667 (which adds
support for reading LLVM IR/BC files) and that's where tests for
exercising the default frontend driver triple will be added.
*WHAT DOES CLANG DO?*
For reference, the default target triple for Clang's
`CompilerInvocation` is set through option marshalling infra [1] in
Options.td. Please check the definition of the `-triple` flag:
```
def triple : Separate<["-"], "triple">,
HelpText<"Specify target triple (e.g. i686-apple-darwin9)">,
MarshallingInfoString<TargetOpts<"Triple">, "llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple())">,
AlwaysEmit, Normalizer<"normalizeTriple">;
```
Ideally, we should re-use the marshalling infra in Flang.
[1] https://clang.llvm.org/docs/InternalsManual.html#option-marshalling-infrastructure
Differential Revision: https://reviews.llvm.org/D124664
2022-04-28 14:12:32 +00:00
|
|
|
llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
|
|
|
|
|
2020-09-11 10:17:31 +01:00
|
|
|
// Parse the arguments
|
|
|
|
const llvm::opt::OptTable &opts = clang::driver::getDriverOptTable();
|
2021-01-25 11:58:52 +00:00
|
|
|
const unsigned includedFlagsBitmask = clang::driver::options::FC1Option;
|
2020-09-11 10:17:31 +01:00
|
|
|
unsigned missingArgIndex, missingArgCount;
|
|
|
|
llvm::opt::InputArgList args = opts.ParseArgs(
|
|
|
|
commandLineArgs, missingArgIndex, missingArgCount, includedFlagsBitmask);
|
|
|
|
|
2021-06-02 21:53:02 +01:00
|
|
|
// Check for missing argument error.
|
|
|
|
if (missingArgCount) {
|
|
|
|
diags.Report(clang::diag::err_drv_missing_argument)
|
|
|
|
<< args.getArgString(missingArgIndex) << missingArgCount;
|
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
|
2020-09-11 10:17:31 +01:00
|
|
|
// Issue errors on unknown arguments
|
|
|
|
for (const auto *a : args.filtered(clang::driver::options::OPT_UNKNOWN)) {
|
|
|
|
auto argString = a->getAsString(args);
|
|
|
|
std::string nearest;
|
|
|
|
if (opts.findNearest(argString, nearest, includedFlagsBitmask) > 1)
|
|
|
|
diags.Report(clang::diag::err_drv_unknown_argument) << argString;
|
|
|
|
else
|
|
|
|
diags.Report(clang::diag::err_drv_unknown_argument_with_suggestion)
|
|
|
|
<< argString << nearest;
|
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
success &= parseFrontendArgs(res.getFrontendOpts(), args, diags);
|
|
|
|
parseTargetArgs(res.getTargetOpts(), args);
|
|
|
|
parsePreprocessorArgs(res.getPreprocessorOpts(), args);
|
2022-06-06 09:44:21 +00:00
|
|
|
parseCodeGenArgs(res.getCodeGenOpts(), args, diags);
|
2021-04-14 11:42:11 +00:00
|
|
|
success &= parseSemaArgs(res, args, diags);
|
|
|
|
success &= parseDialectArgs(res, args, diags);
|
|
|
|
success &= parseDiagArgs(res, args, diags);
|
2022-04-29 17:36:26 +00:00
|
|
|
res.frontendOpts.llvmArgs =
|
2022-03-02 15:40:16 +00:00
|
|
|
args.getAllArgValues(clang::driver::options::OPT_mllvm);
|
2020-09-11 10:17:31 +01:00
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
res.frontendOpts.mlirArgs =
|
2022-04-07 09:47:23 +00:00
|
|
|
args.getAllArgValues(clang::driver::options::OPT_mmlir);
|
|
|
|
|
2022-10-31 11:30:32 +00:00
|
|
|
success &= parseFloatingPointArgs(res, args, diags);
|
|
|
|
|
2020-09-11 10:17:31 +01:00
|
|
|
return success;
|
|
|
|
}
|
2020-10-27 12:26:47 +00:00
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
void CompilerInvocation::collectMacroDefinitions() {
|
|
|
|
auto &ppOpts = this->getPreprocessorOpts();
|
2021-04-07 11:42:37 +00:00
|
|
|
|
2021-01-06 15:42:24 +00:00
|
|
|
for (unsigned i = 0, n = ppOpts.macros.size(); i != n; ++i) {
|
|
|
|
llvm::StringRef macro = ppOpts.macros[i].first;
|
|
|
|
bool isUndef = ppOpts.macros[i].second;
|
|
|
|
|
|
|
|
std::pair<llvm::StringRef, llvm::StringRef> macroPair = macro.split('=');
|
|
|
|
llvm::StringRef macroName = macroPair.first;
|
|
|
|
llvm::StringRef macroBody = macroPair.second;
|
|
|
|
|
|
|
|
// For an #undef'd macro, we only care about the name.
|
|
|
|
if (isUndef) {
|
2022-04-29 17:36:26 +00:00
|
|
|
parserOpts.predefinitions.emplace_back(macroName.str(),
|
|
|
|
std::optional<std::string>{});
|
2021-01-06 15:42:24 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// For a #define'd macro, figure out the actual definition.
|
|
|
|
if (macroName.size() == macro.size())
|
|
|
|
macroBody = "1";
|
|
|
|
else {
|
|
|
|
// Note: GCC drops anything following an end-of-line character.
|
2022-04-29 17:36:26 +00:00
|
|
|
llvm::StringRef::size_type end = macroBody.find_first_of("\n\r");
|
|
|
|
macroBody = macroBody.substr(0, end);
|
2021-01-06 15:42:24 +00:00
|
|
|
}
|
2022-04-29 17:36:26 +00:00
|
|
|
parserOpts.predefinitions.emplace_back(
|
2021-01-06 15:42:24 +00:00
|
|
|
macroName, std::optional<std::string>(macroBody.str()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
void CompilerInvocation::setDefaultFortranOpts() {
|
|
|
|
auto &fortranOptions = getFortranOpts();
|
2020-10-27 12:26:47 +00:00
|
|
|
|
|
|
|
std::vector<std::string> searchDirectories{"."s};
|
|
|
|
fortranOptions.searchDirectories = searchDirectories;
|
2022-03-18 16:20:56 +00:00
|
|
|
|
|
|
|
// Add the location of omp_lib.h to the search directories. Currently this is
|
|
|
|
// identical to the modules' directory.
|
|
|
|
fortranOptions.searchDirectories.emplace_back(getOpenMPHeadersDir());
|
|
|
|
|
2020-10-27 12:26:47 +00:00
|
|
|
fortranOptions.isFixedForm = false;
|
2021-02-11 11:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: When expanding this method, consider creating a dedicated API for
|
|
|
|
// this. Also at some point we will need to differentiate between different
|
|
|
|
// targets and add dedicated predefines for each.
|
2022-04-29 17:36:26 +00:00
|
|
|
void CompilerInvocation::setDefaultPredefinitions() {
|
|
|
|
auto &fortranOptions = getFortranOpts();
|
|
|
|
const auto &frontendOptions = getFrontendOpts();
|
2021-01-19 13:15:53 +00:00
|
|
|
|
|
|
|
// Populate the macro list with version numbers and other predefinitions.
|
|
|
|
fortranOptions.predefinitions.emplace_back("__flang__", "1");
|
2022-11-02 14:31:14 -07:00
|
|
|
fortranOptions.predefinitions.emplace_back("__flang_major__",
|
|
|
|
FLANG_VERSION_MAJOR_STRING);
|
|
|
|
fortranOptions.predefinitions.emplace_back("__flang_minor__",
|
|
|
|
FLANG_VERSION_MINOR_STRING);
|
|
|
|
fortranOptions.predefinitions.emplace_back("__flang_patchlevel__",
|
|
|
|
FLANG_VERSION_PATCHLEVEL_STRING);
|
2021-02-10 09:24:45 +00:00
|
|
|
|
|
|
|
// Add predefinitions based on extensions enabled
|
2021-07-29 12:39:10 +00:00
|
|
|
if (frontendOptions.features.IsEnabled(
|
2021-02-10 09:24:45 +00:00
|
|
|
Fortran::common::LanguageFeature::OpenACC)) {
|
|
|
|
fortranOptions.predefinitions.emplace_back("_OPENACC", "202011");
|
|
|
|
}
|
2021-07-29 12:39:10 +00:00
|
|
|
if (frontendOptions.features.IsEnabled(
|
2021-02-10 09:24:45 +00:00
|
|
|
Fortran::common::LanguageFeature::OpenMP)) {
|
|
|
|
fortranOptions.predefinitions.emplace_back("_OPENMP", "201511");
|
|
|
|
}
|
2022-10-12 12:41:51 -07:00
|
|
|
llvm::Triple targetTriple{llvm::Triple(this->targetOpts.triple)};
|
|
|
|
if (targetTriple.getArch() == llvm::Triple::ArchType::x86_64) {
|
|
|
|
fortranOptions.predefinitions.emplace_back("__x86_64__", "1");
|
|
|
|
fortranOptions.predefinitions.emplace_back("__x86_64", "1");
|
|
|
|
}
|
2021-02-10 09:24:45 +00:00
|
|
|
}
|
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
void CompilerInvocation::setFortranOpts() {
|
|
|
|
auto &fortranOptions = getFortranOpts();
|
|
|
|
const auto &frontendOptions = getFrontendOpts();
|
|
|
|
const auto &preprocessorOptions = getPreprocessorOpts();
|
|
|
|
auto &moduleDirJ = getModuleDir();
|
2021-01-06 15:42:24 +00:00
|
|
|
|
2021-07-29 12:39:10 +00:00
|
|
|
if (frontendOptions.fortranForm != FortranForm::Unknown) {
|
2021-01-26 16:27:30 +00:00
|
|
|
fortranOptions.isFixedForm =
|
2021-07-29 12:39:10 +00:00
|
|
|
frontendOptions.fortranForm == FortranForm::FixedForm;
|
2021-01-26 16:27:30 +00:00
|
|
|
}
|
2021-07-29 12:39:10 +00:00
|
|
|
fortranOptions.fixedFormColumns = frontendOptions.fixedFormColumns;
|
2021-01-26 16:27:30 +00:00
|
|
|
|
2021-07-29 12:39:10 +00:00
|
|
|
fortranOptions.features = frontendOptions.features;
|
|
|
|
fortranOptions.encoding = frontendOptions.encoding;
|
2021-02-10 09:24:45 +00:00
|
|
|
|
2021-03-23 12:24:57 -04:00
|
|
|
// Adding search directories specified by -I
|
2021-01-19 10:01:38 +00:00
|
|
|
fortranOptions.searchDirectories.insert(
|
|
|
|
fortranOptions.searchDirectories.end(),
|
|
|
|
preprocessorOptions.searchDirectoriesFromDashI.begin(),
|
|
|
|
preprocessorOptions.searchDirectoriesFromDashI.end());
|
2021-02-04 16:13:04 +00:00
|
|
|
|
2021-03-23 12:24:57 -04:00
|
|
|
// Add the ordered list of -intrinsic-modules-path
|
|
|
|
fortranOptions.searchDirectories.insert(
|
|
|
|
fortranOptions.searchDirectories.end(),
|
|
|
|
preprocessorOptions.searchDirectoriesFromIntrModPath.begin(),
|
|
|
|
preprocessorOptions.searchDirectoriesFromIntrModPath.end());
|
|
|
|
|
2022-01-26 09:54:58 -08:00
|
|
|
// Add the default intrinsic module directory
|
|
|
|
fortranOptions.intrinsicModuleDirectories.emplace_back(getIntrinsicDir());
|
2021-03-23 12:24:57 -04:00
|
|
|
|
2021-02-04 16:13:04 +00:00
|
|
|
// Add the directory supplied through -J/-module-dir to the list of search
|
|
|
|
// directories
|
2022-08-27 21:21:04 -07:00
|
|
|
if (moduleDirJ != ".")
|
2021-02-04 16:13:04 +00:00
|
|
|
fortranOptions.searchDirectories.emplace_back(moduleDirJ);
|
2021-02-23 17:59:17 +00:00
|
|
|
|
2021-07-29 12:39:10 +00:00
|
|
|
if (frontendOptions.instrumentedParse)
|
2021-02-23 17:59:17 +00:00
|
|
|
fortranOptions.instrumentedParse = true;
|
2021-03-25 13:02:05 -04:00
|
|
|
|
[flang] Support the color diagnostics on scanning, parsing, and semantics
The options -f{no-}color-diagnostics have been supported in driver. This
supports the behaviors in scanning, parsing, and semantics, and the
behaviors are exactly the same as the driver.
To illustrate the added behaviour, consider the following input file:
```! file.f90
program m
integer :: i = k
end
```
In the following invocations, "error: Must be a constant value" _will be_
formatted:
```
$ flang-new file.f90
error: Semantic errors in file.f90
./file.f90:2:18: error: Must be a constant value
integer :: i = k
```
Note that "error: Semantic errors in file.f90" is also formatted, which
is supported in https://reviews.llvm.org/D126164.
Also note that only "error", "warning" and "portability" are formatted.
Check the following input file:
```! file2.f90
program m
integer :: i =
end
```
```
$ flang-new test2.f90
error: Could not parse test2.f90
./test2.f90:2:11: error: expected '('
integer :: i =
^
./test2.f90:2:3: in the context: statement function definition
integer :: i =
^
...
```
The "error: Could not parse test2.f90" and "error: expected '('" are
formatted. Others such as "in the context" are not formatted yet, which
may or may not be supported.
Reviewed By: awarzynski
Differential Revision: https://reviews.llvm.org/D126166
2022-07-27 23:45:41 +08:00
|
|
|
if (frontendOptions.showColors)
|
|
|
|
fortranOptions.showColors = true;
|
|
|
|
|
2021-07-29 12:39:10 +00:00
|
|
|
if (frontendOptions.needProvenanceRangeToCharBlockMappings)
|
2021-04-07 13:10:35 +00:00
|
|
|
fortranOptions.needProvenanceRangeToCharBlockMappings = true;
|
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
if (getEnableConformanceChecks()) {
|
2021-03-25 13:02:05 -04:00
|
|
|
fortranOptions.features.WarnOnAllNonstandard();
|
|
|
|
}
|
2021-02-04 16:13:04 +00:00
|
|
|
}
|
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
void CompilerInvocation::setSemanticsOpts(
|
2021-02-10 09:24:45 +00:00
|
|
|
Fortran::parser::AllCookedSources &allCookedSources) {
|
2022-10-12 12:41:51 -07:00
|
|
|
auto &fortranOptions = getFortranOpts();
|
2021-02-10 09:24:45 +00:00
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
semanticsContext = std::make_unique<semantics::SemanticsContext>(
|
|
|
|
getDefaultKinds(), fortranOptions.features, allCookedSources);
|
2021-02-10 09:24:45 +00:00
|
|
|
|
2022-04-29 17:36:26 +00:00
|
|
|
semanticsContext->set_moduleDirectory(getModuleDir())
|
2021-03-25 13:02:05 -04:00
|
|
|
.set_searchDirectories(fortranOptions.searchDirectories)
|
2022-01-26 09:54:58 -08:00
|
|
|
.set_intrinsicModuleDirectories(fortranOptions.intrinsicModuleDirectories)
|
2022-04-29 17:36:26 +00:00
|
|
|
.set_warnOnNonstandardUsage(getEnableConformanceChecks())
|
|
|
|
.set_warningsAreErrors(getWarnAsErr())
|
|
|
|
.set_moduleFileSuffix(getModuleFileSuffix());
|
2022-10-03 15:24:39 +08:00
|
|
|
|
|
|
|
llvm::Triple targetTriple{llvm::Triple(this->targetOpts.triple)};
|
|
|
|
// FIXME: Handle real(3) ?
|
2022-10-12 12:41:51 -07:00
|
|
|
if (targetTriple.getArch() != llvm::Triple::ArchType::x86_64) {
|
2022-10-03 15:24:39 +08:00
|
|
|
semanticsContext->targetCharacteristics().DisableType(
|
|
|
|
Fortran::common::TypeCategory::Real, /*kind=*/10);
|
|
|
|
}
|
2021-01-06 15:42:24 +00:00
|
|
|
}
|
2022-07-19 20:39:58 -07:00
|
|
|
|
|
|
|
/// Set \p loweringOptions controlling lowering behavior based
|
|
|
|
/// on the \p optimizationLevel.
|
|
|
|
void CompilerInvocation::setLoweringOptions() {
|
|
|
|
const auto &codegenOpts = getCodeGenOpts();
|
|
|
|
|
|
|
|
// Lower TRANSPOSE as a runtime call under -O0.
|
|
|
|
loweringOpts.setOptimizeTranspose(codegenOpts.OptimizationLevel > 0);
|
|
|
|
}
|