[clang][driver] Add basic --driver-mode=flang support for fortran
This patch adds a new Flang mode. When in Flang mode, the driver will
invoke flang for fortran inputs instead of falling back to the GCC
toolchain as it would otherwise do.
The behaviour of other driver modes are left unmodified to preserve
backwards compatibility.
It is intended that a soon to be implemented binary in the flang project
will import libclangDriver and run the clang driver in the new flang
mode.
Please note that since the binary invoked by the driver is under
development, there will no doubt be further tweaks necessary in future
commits.
* Initial support is added for basic driver phases
* -E, -fsyntax-only, -emit-llvm -S, -emit-llvm, -S, (none specified)
* -### tests are added for all of the above
* This is more than is supported by f18 so far, which will emit errors
for those options which are unimplemented.
* A test is added that ensures that clang gives a reasonable error
message if flang is not available in the path (without -###).
* Test that the driver accepts multiple inputs in --driver-mode=flang.
* Test that a combination of C and Fortran inputs run both clang and
flang in --driver-mode=flang.
* clang/test/Driver/fortran.f95 is fixed to use the correct fortran
comment character.
Differential revision: https://reviews.llvm.org/D63607
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
new file mode 100644
index 0000000..9b9eb81
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -0,0 +1,79 @@
+//===-- Flang.cpp - Flang+LLVM ToolChain Implementations --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "Flang.h"
+#include "CommonArgs.h"
+
+#include "clang/Driver/Options.h"
+
+#include <cassert>
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+void Flang::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const ArgList &Args, const char *LinkingOutput) const {
+ const auto &TC = getToolChain();
+ const llvm::Triple &Triple = TC.getEffectiveTriple();
+ const std::string &TripleStr = Triple.getTriple();
+
+ ArgStringList CmdArgs;
+
+ CmdArgs.push_back("-fc1");
+
+ CmdArgs.push_back("-triple");
+ CmdArgs.push_back(Args.MakeArgString(TripleStr));
+
+ if (isa<PreprocessJobAction>(JA)) {
+ CmdArgs.push_back("-E");
+ } else if (isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) {
+ if (JA.getType() == types::TY_Nothing) {
+ CmdArgs.push_back("-fsyntax-only");
+ } else if (JA.getType() == types::TY_AST) {
+ CmdArgs.push_back("-emit-ast");
+ } else if (JA.getType() == types::TY_LLVM_IR ||
+ JA.getType() == types::TY_LTO_IR) {
+ CmdArgs.push_back("-emit-llvm");
+ } else if (JA.getType() == types::TY_LLVM_BC ||
+ JA.getType() == types::TY_LTO_BC) {
+ CmdArgs.push_back("-emit-llvm-bc");
+ } else if (JA.getType() == types::TY_PP_Asm) {
+ CmdArgs.push_back("-S");
+ } else {
+ assert(false && "Unexpected output type!");
+ }
+ } else if (isa<AssembleJobAction>(JA)) {
+ CmdArgs.push_back("-emit-obj");
+ } else {
+ assert(false && "Unexpected action class for Flang tool.");
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ const InputInfo &Input = Inputs[0];
+ assert(Input.isFilename() && "Invalid input.");
+ CmdArgs.push_back(Input.getFilename());
+
+ const auto& D = C.getDriver();
+ const char* Exec = Args.MakeArgString(D.GetProgramPath("flang", TC));
+ C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+}
+
+Flang::Flang(const ToolChain &TC)
+ : Tool("flang", "flang frontend", TC, RF_Full) {}
+
+Flang::~Flang() {}