[llvm] 7b73ca3 - [flang][driver] Delete `f18` (i.e. the old Flang driver)

Andrzej Warzynski via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 5 05:59:32 PDT 2021


Author: Andrzej Warzynski
Date: 2021-08-05T12:57:15Z
New Revision: 7b73ca3043fecfc5fa6bbf5b28edfee61a83ff9f

URL: https://github.com/llvm/llvm-project/commit/7b73ca3043fecfc5fa6bbf5b28edfee61a83ff9f
DIFF: https://github.com/llvm/llvm-project/commit/7b73ca3043fecfc5fa6bbf5b28edfee61a83ff9f.diff

LOG: [flang][driver] Delete `f18` (i.e. the old Flang driver)

This patch removes `f18`, a.k.a. the old driver. It is being replaced
with the new driver, `flang-new`, which has reached feature parity with
`f18` a while ago. This was discussed in [1] and also in [2].

With this change, `FLANG_BUILD_NEW_DRIVER` is no longer needed and is
also deleted. This means that we are making the dependency on Clang permanent
(i.e. it cannot be disabled with a CMake flag).

LIT set-up is updated accordingly. All references to `f18` or `f18.cpp`
are either updated or removed.

The `F18_FC` variable from the `flang` bash script is replaced with
`FLANG_FC`. The former is still supported for backwards compatibility.

[1] https://lists.llvm.org/pipermail/flang-dev/2021-June/000742.html
[2] https://reviews.llvm.org/D103177

Differential Revision: https://reviews.llvm.org/D105811

Added: 
    flang/tools/f18/flang

Modified: 
    flang/CMakeLists.txt
    flang/docs/ImplementingASemanticCheck.md
    flang/docs/Overview.md
    flang/include/flang/Frontend/CompilerInvocation.h
    flang/include/flang/Frontend/FrontendOptions.h
    flang/lib/CMakeLists.txt
    flang/lib/Frontend/CompilerInvocation.cpp
    flang/test/CMakeLists.txt
    flang/test/lit.cfg.py
    flang/test/lit.site.cfg.py.in
    flang/tools/CMakeLists.txt
    flang/tools/f18/CMakeLists.txt
    flang/unittests/CMakeLists.txt
    llvm/CMakeLists.txt

Removed: 
    flang/test/Driver/help-f18.f90
    flang/tools/f18/f18.cpp
    flang/tools/f18/flang.in


################################################################################
diff  --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt
index adf3dc819dc93..fc85f44513163 100644
--- a/flang/CMakeLists.txt
+++ b/flang/CMakeLists.txt
@@ -26,11 +26,6 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
   project(Flang)
   set(FLANG_STANDALONE_BUILD ON)
 
-  # For in-tree builds, this variable is inherited from
-  # llvm-project/llvm/CMakeLists.txt. For out-of-tree builds, we need a
-  # separate definition.
-  option(FLANG_BUILD_NEW_DRIVER "Build the flang compiler driver" ON)
-
   set(FLANG_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
   if (NOT MSVC_IDE)
     set(LLVM_ENABLE_ASSERTIONS ${ENABLE_ASSERTIONS}
@@ -46,24 +41,22 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
   get_filename_component(LLVM_DIR_ABSOLUTE ${LLVM_DIR} REALPATH)
   list(APPEND CMAKE_MODULE_PATH ${LLVM_DIR_ABSOLUTE})
 
-  if(FLANG_BUILD_NEW_DRIVER)
-    # Users might specify a path to CLANG_DIR that's:
-    #   * a full path, or
-    #   * a path relative to the path of this script.
-    # Append the absolute path to CLANG_DIR so that find_package works in both
-    # cases.
-    get_filename_component(
-      CLANG_DIR_ABSOLUTE
-      ${CLANG_DIR}
-      REALPATH
-      ${CMAKE_CURRENT_SOURCE_DIR})
-    list(APPEND CMAKE_MODULE_PATH ${CLANG_DIR_ABSOLUTE})
-
-    # TODO: Remove when libclangDriver is lifted out of Clang
-    find_package(Clang REQUIRED PATHS "${CLANG_DIR_ABSOLUTE}" NO_DEFAULT_PATH)
-    if (NOT Clang_FOUND)
-      message(FATAL_ERROR "Failed to find Clang")
-    endif()
+  # Users might specify a path to CLANG_DIR that's:
+  #   * a full path, or
+  #   * a path relative to the path of this script.
+  # Append the absolute path to CLANG_DIR so that find_package works in both
+  # cases.
+  get_filename_component(
+    CLANG_DIR_ABSOLUTE
+    ${CLANG_DIR}
+    REALPATH
+    ${CMAKE_CURRENT_SOURCE_DIR})
+  list(APPEND CMAKE_MODULE_PATH ${CLANG_DIR_ABSOLUTE})
+
+  # TODO: Remove when libclangDriver is lifted out of Clang
+  find_package(Clang REQUIRED PATHS "${CLANG_DIR_ABSOLUTE}" NO_DEFAULT_PATH)
+  if (NOT Clang_FOUND)
+    message(FATAL_ERROR "Failed to find Clang")
   endif()
 
   # If LLVM links to zlib we need the imported targets so we can too.
@@ -80,9 +73,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
   include(HandleLLVMOptions)
   include(VersionFromVCS)
 
-  if(FLANG_BUILD_NEW_DRIVER)
-    include(AddClang)
-  endif()
+  include(AddClang)
 
   include(TableGen)
   find_package(MLIR REQUIRED CONFIG)
@@ -206,20 +197,18 @@ endif()
 set(FLANG_INTRINSIC_MODULES_DIR ${CMAKE_BINARY_DIR}/include/flang)
 set(FLANG_INCLUDE_DIR ${FLANG_BINARY_DIR}/include)
 
-if(FLANG_BUILD_NEW_DRIVER)
-    # TODO: Remove when libclangDriver is lifted out of Clang
-    if(FLANG_STANDALONE_BUILD)
-      set(CLANG_INCLUDE_DIR ${CLANG_INCLUDE_DIRS} )
-      # No need to specify TableGen output dir as that's embedded in CLANG_DIR
-    else()
-      set(CLANG_INCLUDE_DIR ${LLVM_MAIN_SRC_DIR}/../clang/include )
-      # Specify TableGen output dir for things like DiagnosticCommonKinds.inc,
-      # DiagnosticDriverKinds.inc (required for reporting diagnostics)
-      set(CLANG_TABLEGEN_OUTPUT_DIR ${CMAKE_BINARY_DIR}/tools/clang/include)
-      include_directories(SYSTEM ${CLANG_TABLEGEN_OUTPUT_DIR})
-    endif()
-    include_directories(SYSTEM ${CLANG_INCLUDE_DIR})
+# TODO: Remove when libclangDriver is lifted out of Clang
+if(FLANG_STANDALONE_BUILD)
+  set(CLANG_INCLUDE_DIR ${CLANG_INCLUDE_DIRS} )
+  # No need to specify TableGen output dir as that's embedded in CLANG_DIR
+else()
+  set(CLANG_INCLUDE_DIR ${LLVM_MAIN_SRC_DIR}/../clang/include )
+  # Specify TableGen output dir for things like DiagnosticCommonKinds.inc,
+  # DiagnosticDriverKinds.inc (required for reporting diagnostics)
+  set(CLANG_TABLEGEN_OUTPUT_DIR ${CMAKE_BINARY_DIR}/tools/clang/include)
+  include_directories(SYSTEM ${CLANG_TABLEGEN_OUTPUT_DIR})
 endif()
+include_directories(SYSTEM ${CLANG_INCLUDE_DIR})
 
 # tco tool and FIR lib output directories
 if(FLANG_STANDALONE_BUILD)

diff  --git a/flang/docs/ImplementingASemanticCheck.md b/flang/docs/ImplementingASemanticCheck.md
index 4a6fe133f21f6..4e19b041c3920 100644
--- a/flang/docs/ImplementingASemanticCheck.md
+++ b/flang/docs/ImplementingASemanticCheck.md
@@ -12,7 +12,7 @@
    :local:
 ```
 
-I recently added a semantic check to the f18 compiler front end.  This document
+I recently added a semantic check to the Flang compiler front end.  This document
 describes my thought process and the resulting implementation.
 
 For more information about the compiler, start with the 
@@ -67,7 +67,7 @@ of the call to `intentOutFunc()`:
 
 I also used this program to produce a parse tree for the program using the command:
 ```bash
-  f18 -fdebug-dump-parse-tree -fsyntax-only testfun.f90
+  flang-new -fc1 -fdebug-dump-parse-tree testfun.f90
 ```
 
 Here's the relevant fragment of the parse tree produced by the compiler:
@@ -295,7 +295,7 @@ In `lib/Semantics/check-do.cpp`, I added an (almost empty) implementation:
 I then built the compiler with these changes and ran it on my test program.
 This time, I made sure to invoke semantic checking.  Here's the command I used:
 ```bash
-  f18 -fdebug-resolve-names -fdebug-dump-parse-tree -funparse-with-symbols testfun.f90
+  flang-new -fc1 -fdebug-unparse-with-symbols testfun.f90
 ```
 
 This produced the output:
@@ -361,7 +361,7 @@ I noted that a `SymbolSet` did not actually contain an
 full `semantics::Symbol` objects into the set.  Ideally, we would be able to create an
 `std::set<Symbol &>` (a set of C++ references to symbols).  But C++ doesn't
 support sets that contain references.  This limitation is part of the rationale
-for the f18 implementation of type `common::Reference`, which is defined in
+for the Flang implementation of type `common::Reference`, which is defined in
   `include/flang/Common/reference.h`.
 
 `SymbolRef`, the specialization of the template `common::Reference` for

diff  --git a/flang/docs/Overview.md b/flang/docs/Overview.md
index 4ef04f865083e..517303cb15bf3 100644
--- a/flang/docs/Overview.md
+++ b/flang/docs/Overview.md
@@ -6,6 +6,11 @@
   
 -->
 
+# Intro
+This document goes briefly over compiler phases in Flang. It focuses on the
+internal implementation and as such, it is intended for Flang developers rather
+than end-users.
+
 # Overview of Compiler Phases
 
 ```eval_rst
@@ -33,7 +38,7 @@ See: [Preprocessing.md](Preprocessing.md).
 
 **Entry point:** `parser::Parsing::Prescan`
 
-**Command:** `f18 -E src.f90` dumps the cooked character stream
+**Command:** `flang-new -fc1 -E src.f90` dumps the cooked character stream
 
 ## Parse
 
@@ -46,8 +51,8 @@ See: [Preprocessing.md](Preprocessing.md).
 **Entry point:** `parser::Parsing::Parse`
 
 **Command:**
-  - `f18 -fdebug-dump-parse-tree -fsyntax-only src.f90` dumps the parse tree
-  - `f18 -funparse src.f90` converts the parse tree to normalized Fortran
+  - `flang-new -fc1 -fdebug-dump-parse-tree src.f90` dumps the parse tree
+  - `flang-new -fc1 -fdebug-unparse src.f90` converts the parse tree to normalized Fortran
 
 ## Validate Labels and Canonicalize Do Statements
 
@@ -74,7 +79,7 @@ See: [Preprocessing.md](Preprocessing.md).
 
 **Entry points:** `semantics::ResolveNames`, `semantics::RewriteParseTree`
 
-**Command:** `f18 -fdebug-dump-symbols -fsyntax-only src.f90` dumps the
+**Command:** `flang-new -fc1 -fdebug-dump-symbols src.f90` dumps the
   tree of scopes and symbols in each scope
 
 ## Check DO CONCURRENT Constraints

diff  --git a/flang/include/flang/Frontend/CompilerInvocation.h b/flang/include/flang/Frontend/CompilerInvocation.h
index ad25c39b48507..16b069e9a3285 100644
--- a/flang/include/flang/Frontend/CompilerInvocation.h
+++ b/flang/include/flang/Frontend/CompilerInvocation.h
@@ -184,8 +184,7 @@ class CompilerInvocation : public CompilerInvocationBase {
     useAnalyzedObjectsForUnparse_ = flag;
   }
 
-  /// Set the Fortran options to predifined defaults. These defaults are
-  /// consistend with f18/f18.cpp.
+  /// Set the Fortran options to predefined defaults.
   // TODO: We should map frontendOpts_ to parserOpts_ instead. For that, we
   // need to extend frontendOpts_ first. Next, we need to add the corresponding
   // compiler driver options in libclangDriver.

diff  --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h
index 5f910febd4b6e..6dc397104efa1 100644
--- a/flang/include/flang/Frontend/FrontendOptions.h
+++ b/flang/include/flang/Frontend/FrontendOptions.h
@@ -87,10 +87,6 @@ enum ActionKind {
 /// \return True if the file extension should be processed as fixed form
 bool isFixedFormSuffix(llvm::StringRef suffix);
 
-// TODO: Find a more suitable location for this. Added for compability with
-// f18.cpp (this is equivalent to `asFortran` defined there).
-Fortran::parser::AnalyzedObjectsAsFortran getBasicAsFortran();
-
 /// \param suffix The file extension
 /// \return True if the file extension should be processed as free form
 bool isFreeFormSuffix(llvm::StringRef suffix);

diff  --git a/flang/lib/CMakeLists.txt b/flang/lib/CMakeLists.txt
index 9ebb9f6a72ca5..f41d4df1f07e3 100644
--- a/flang/lib/CMakeLists.txt
+++ b/flang/lib/CMakeLists.txt
@@ -4,10 +4,7 @@ add_subdirectory(Decimal)
 add_subdirectory(Lower)
 add_subdirectory(Parser)
 add_subdirectory(Semantics)
-
-if(FLANG_BUILD_NEW_DRIVER)
-  add_subdirectory(Frontend)
-  add_subdirectory(FrontendTool)
-endif()
+add_subdirectory(Frontend)
+add_subdirectory(FrontendTool)
 
 add_subdirectory(Optimizer)

diff  --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 68ff16713c38c..baa0f32c55c87 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -571,7 +571,6 @@ void CompilerInvocation::collectMacroDefinitions() {
 void CompilerInvocation::SetDefaultFortranOpts() {
   auto &fortranOptions = fortranOpts();
 
-  // These defaults are based on the defaults in f18/f18.cpp.
   std::vector<std::string> searchDirectories{"."s};
   fortranOptions.searchDirectories = searchDirectories;
   fortranOptions.isFixedForm = false;

diff  --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt
index 738e00cdd1e28..e2e95596d30b8 100644
--- a/flang/test/CMakeLists.txt
+++ b/flang/test/CMakeLists.txt
@@ -32,13 +32,9 @@ set(FLANG_TEST_PARAMS
   flang_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py)
 
 set(FLANG_TEST_DEPENDS
-  f18 FileCheck count not module_files fir-opt tco
+  flang-new FileCheck count not module_files fir-opt tco
 )
 
-if (FLANG_BUILD_NEW_DRIVER)
-  list(APPEND FLANG_TEST_DEPENDS flang-new)
-endif()
-
 if (FLANG_INCLUDE_TESTS)
   if (FLANG_GTEST_AVAIL)
     list(APPEND FLANG_TEST_DEPENDS FlangUnitTests)

diff  --git a/flang/test/Driver/help-f18.f90 b/flang/test/Driver/help-f18.f90
deleted file mode 100644
index c98e7f6f6ea6b..0000000000000
--- a/flang/test/Driver/help-f18.f90
+++ /dev/null
@@ -1,12 +0,0 @@
-! REQUIRES: old-flang-driver
-
-! RUN: %flang -h 2>&1 | FileCheck %s
-! RUN: %flang -help 2>&1 | FileCheck %s
-! RUN: %flang --help 2>&1 | FileCheck %s
-! RUN: %flang -? 2>&1 | FileCheck %s
-
-! CHECK: f18: LLVM Fortran compiler
-
-! CHECK:   -help                print this again
-! CHECK: Unrecognised options are passed through to the external compiler
-! CHECK: set by F18_FC (see defaults).

diff  --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py
index 374047e6c5755..854b4e723884a 100644
--- a/flang/test/lit.cfg.py
+++ b/flang/test/lit.cfg.py
@@ -40,10 +40,7 @@
 
 # If the new Flang driver is enabled, add the corresponding feature to
 # config.
-if config.include_flang_new_driver_test:
-  config.available_features.add('new-flang-driver')
-else:
-  config.available_features.add('old-flang-driver')
+config.available_features.add('new-flang-driver')
 
 # test_source_root: The root path where tests are located.
 config.test_source_root = os.path.dirname(__file__)
@@ -64,16 +61,10 @@
 
 # For each occurrence of a flang tool name, replace it with the full path to
 # the build directory holding that tool.
-tools = []
-if config.include_flang_new_driver_test:
-   tools.append(ToolSubst('%flang', command=FindTool('flang-new'), unresolved='fatal'))
-   tools.append(ToolSubst('%flang_fc1', command=FindTool('flang-new'),
-    extra_args=['-fc1'], unresolved='fatal'))
-else:
-   tools.append(ToolSubst('%flang', command=FindTool('f18'),
-    unresolved='fatal'))
-   tools.append(ToolSubst('%flang_fc1', command=FindTool('f18'),
-    unresolved='fatal'))
+tools = [
+        ToolSubst('%flang', command=FindTool('flang-new'), unresolved='fatal'),
+    ToolSubst('%flang_fc1', command=FindTool('flang-new'), extra_args=['-fc1'],
+        unresolved='fatal')]
 
 # Define some variables to help us test that the flang runtime doesn't depend on
 # the C++ runtime libraries. For this we need a C compiler. If for some reason

diff  --git a/flang/test/lit.site.cfg.py.in b/flang/test/lit.site.cfg.py.in
index bcafd8ac43023..746866bd722a6 100644
--- a/flang/test/lit.site.cfg.py.in
+++ b/flang/test/lit.site.cfg.py.in
@@ -14,11 +14,6 @@ config.python_executable = "@PYTHON_EXECUTABLE@"
 config.flang_standalone_build = @FLANG_STANDALONE_BUILD@
 config.cc = "@CMAKE_C_COMPILER@"
 
-# Control the regression test for flang-new driver
-import lit.util
-config.include_flang_new_driver_test = \
-    lit.util.pythonize_bool("@FLANG_BUILD_NEW_DRIVER@")
-
 # Support substitution of the tools_dir with user parameters. This is
 # used when we can't determine the tool dir at configuration time.
 try:

diff  --git a/flang/tools/CMakeLists.txt b/flang/tools/CMakeLists.txt
index 98b20a1ff358b..5e7fe993b0987 100644
--- a/flang/tools/CMakeLists.txt
+++ b/flang/tools/CMakeLists.txt
@@ -7,9 +7,7 @@
 #===------------------------------------------------------------------------===#
 
 add_subdirectory(f18)
-if(FLANG_BUILD_NEW_DRIVER)
-  add_subdirectory(flang-driver)
-endif()
+add_subdirectory(flang-driver)
 add_subdirectory(tco)
 add_subdirectory(f18-parse-demo)
 add_subdirectory(fir-opt)

diff  --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt
index 239859b5e5b9d..5cd9d758d30cc 100644
--- a/flang/tools/f18/CMakeLists.txt
+++ b/flang/tools/f18/CMakeLists.txt
@@ -3,19 +3,6 @@ set(LLVM_LINK_COMPONENTS
   FrontendOpenMP
   Support
   )
-add_flang_tool(f18
-  dump.cpp
-  f18.cpp
-  )
-
-target_link_libraries(f18
-  PRIVATE
-  FortranCommon
-  FortranParser
-  FortranEvaluate
-  FortranSemantics
-  FortranLower
-)
 
 set(MODULES
   "__fortran_builtins"
@@ -30,11 +17,6 @@ set(MODULES
   "__fortran_type_info"
 )
 
-target_include_directories(f18
-  PRIVATE
-  ${CMAKE_CURRENT_BINARY_DIR}
-)
-
 # Create module files directly from the top-level module source directory
 foreach(filename ${MODULES})
   set(base ${FLANG_INTRINSIC_MODULES_DIR}/${filename})
@@ -47,9 +29,9 @@ foreach(filename ${MODULES})
   endif()
   add_custom_command(OUTPUT ${base}.mod
     COMMAND ${CMAKE_COMMAND} -E make_directory ${FLANG_INTRINSIC_MODULES_DIR}
-    COMMAND f18 -fsyntax-only -module-dir ${FLANG_INTRINSIC_MODULES_DIR}
+    COMMAND flang-new -fc1 -fsyntax-only -module-dir ${FLANG_INTRINSIC_MODULES_DIR}
       ${FLANG_SOURCE_DIR}/module/${filename}.f90
-    DEPENDS f18 ${FLANG_SOURCE_DIR}/module/${filename}.f90 ${depends}
+    DEPENDS flang-new ${FLANG_SOURCE_DIR}/module/${filename}.f90 ${depends}
   )
   add_custom_command(OUTPUT ${base}.f18.mod
     DEPENDS ${base}.mod
@@ -60,15 +42,10 @@ endforeach()
 
 add_custom_target(module_files ALL DEPENDS ${MODULE_FILES})
 
-install(TARGETS f18 DESTINATION bin)
-
-set(FLANG_DEFAULT_DRIVER "flang-new")
-if (NOT FLANG_BUILD_NEW_DRIVER)
-  set(FLANG_DEFAULT_DRIVER "f18")
-endif()
-
 # This flang shell script will only work in a POSIX shell.
 if (NOT WIN32)
-  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/flang.in ${CMAKE_BINARY_DIR}/bin/flang @ONLY)
+  file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/flang
+    DESTINATION ${CMAKE_BINARY_DIR}/bin
+    FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE)
   install(PROGRAMS ${CMAKE_BINARY_DIR}/bin/flang DESTINATION bin)
 endif()

diff  --git a/flang/tools/f18/f18.cpp b/flang/tools/f18/f18.cpp
deleted file mode 100644
index 3748adb6d5743..0000000000000
--- a/flang/tools/f18/f18.cpp
+++ /dev/null
@@ -1,849 +0,0 @@
-//===-- tools/f18/f18.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
-//
-//===----------------------------------------------------------------------===//
-
-// Temporary Fortran front end driver main program for development scaffolding.
-
-#include "flang/Common/Fortran-features.h"
-#include "flang/Common/default-kinds.h"
-#include "flang/Evaluate/expression.h"
-#include "flang/Lower/PFTBuilder.h"
-#include "flang/Parser/characters.h"
-#include "flang/Parser/dump-parse-tree.h"
-#include "flang/Parser/message.h"
-#include "flang/Parser/parse-tree-visitor.h"
-#include "flang/Parser/parse-tree.h"
-#include "flang/Parser/parsing.h"
-#include "flang/Parser/provenance.h"
-#include "flang/Parser/unparse.h"
-#include "flang/Semantics/expression.h"
-#include "flang/Semantics/runtime-type-info.h"
-#include "flang/Semantics/semantics.h"
-#include "flang/Semantics/unparse-with-symbols.h"
-#include "flang/Version.inc"
-#include "llvm/Support/Errno.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/Program.h"
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstdio>
-#include <cstring>
-#include <fstream>
-#include <list>
-#include <memory>
-#include <optional>
-#include <stdlib.h>
-#include <string>
-#include <vector>
-
-static std::list<std::string> argList(int argc, char *const argv[]) {
-  std::list<std::string> result;
-  for (int j = 0; j < argc; ++j) {
-    result.emplace_back(argv[j]);
-  }
-  return result;
-}
-
-struct MeasurementVisitor {
-  template <typename A> bool Pre(const A &) { return true; }
-  template <typename A> void Post(const A &) {
-    ++objects;
-    bytes += sizeof(A);
-  }
-  size_t objects{0}, bytes{0};
-};
-
-void MeasureParseTree(const Fortran::parser::Program &program) {
-  MeasurementVisitor visitor;
-  Fortran::parser::Walk(program, visitor);
-  llvm::outs() << "Parse tree comprises " << visitor.objects
-               << " objects and occupies " << visitor.bytes
-               << " total bytes.\n";
-}
-
-std::vector<std::string> filesToDelete;
-
-void CleanUpAtExit() {
-  for (const auto &path : filesToDelete) {
-    if (!path.empty()) {
-      llvm::sys::fs::remove(path);
-    }
-  }
-}
-
-struct GetDefinitionArgs {
-  int line, startColumn, endColumn;
-};
-
-struct DriverOptions {
-  DriverOptions() {}
-  bool verbose{false}; // -v
-  bool compileOnly{false}; // -c
-  std::string outputPath; // -o path
-  std::vector<std::string> searchDirectories; // -I dir
-  std::string moduleDirectory{"."s}; // -module dir
-  std::string moduleFileSuffix{".mod"}; // -moduleSuffix suff
-  bool forcedForm{false}; // -Mfixed or -Mfree appeared
-  bool warnOnNonstandardUsage{false}; // -Mstandard
-  bool warningsAreErrors{false}; // -Werror
-  bool byteswapio{false}; // -byteswapio
-  Fortran::parser::Encoding encoding{Fortran::parser::Encoding::UTF_8};
-  bool lineDirectives{true}; // -P disables
-  bool syntaxOnly{false};
-  bool dumpProvenance{false};
-  bool noReformat{false}; // -E -fno-reformat
-  bool dumpUnparse{false};
-  bool dumpUnparseWithSymbols{false};
-  bool dumpParseTree{false};
-  bool dumpPreFirTree{false};
-  bool dumpSymbols{false};
-  bool debugNoSemantics{false};
-  bool debugModuleWriter{false};
-  bool defaultReal8{false};
-  bool measureTree{false};
-  bool useAnalyzedObjectsForUnparse{true};
-  std::vector<std::string> F18_FCArgs;
-  const char *prefix{nullptr};
-  bool getDefinition{false};
-  GetDefinitionArgs getDefinitionArgs{0, 0, 0};
-  bool getSymbolsSources{false};
-  std::optional<bool> forcePreprocessing; // -cpp & -nocpp
-};
-
-void Exec(std::vector<llvm::StringRef> &argv, bool verbose = false) {
-  if (verbose) {
-    for (size_t j{0}; j < argv.size(); ++j) {
-      llvm::errs() << (j > 0 ? " " : "") << argv[j];
-    }
-    llvm::errs() << '\n';
-  }
-  std::string ErrMsg;
-  llvm::ErrorOr<std::string> Program = llvm::sys::findProgramByName(argv[0]);
-  if (!Program)
-    ErrMsg = Program.getError().message();
-  if (!Program ||
-      llvm::sys::ExecuteAndWait(
-          Program.get(), argv, llvm::None, {}, 0, 0, &ErrMsg)) {
-    llvm::errs() << "execvp(" << argv[0] << ") failed: " << ErrMsg << '\n';
-    exit(EXIT_FAILURE);
-  }
-}
-
-void RunOtherCompiler(DriverOptions &driver, char *source, char *relo) {
-  std::vector<llvm::StringRef> argv;
-  for (size_t j{0}; j < driver.F18_FCArgs.size(); ++j) {
-    argv.push_back(driver.F18_FCArgs[j]);
-  }
-  char dashC[3] = "-c", dashO[3] = "-o";
-  argv.push_back(dashC);
-  argv.push_back(dashO);
-  argv.push_back(relo);
-  argv.push_back(source);
-  Exec(argv, driver.verbose);
-}
-
-std::string RelocatableName(const DriverOptions &driver, std::string path) {
-  if (driver.compileOnly && !driver.outputPath.empty()) {
-    return driver.outputPath;
-  }
-  std::string base{path};
-  auto slash{base.rfind("/")};
-  if (slash != std::string::npos) {
-    base = base.substr(slash + 1);
-  }
-  std::string relo{base};
-  auto dot{base.rfind(".")};
-  if (dot != std::string::npos) {
-    relo = base.substr(0, dot);
-  }
-  relo += ".o";
-  return relo;
-}
-
-int exitStatus{EXIT_SUCCESS};
-
-static Fortran::parser::AnalyzedObjectsAsFortran asFortran{
-    [](llvm::raw_ostream &o, const Fortran::evaluate::GenericExprWrapper &x) {
-      if (x.v) {
-        x.v->AsFortran(o);
-      } else {
-        o << "(bad expression)";
-      }
-    },
-    [](llvm::raw_ostream &o,
-        const Fortran::evaluate::GenericAssignmentWrapper &x) {
-      if (x.v) {
-        x.v->AsFortran(o);
-      } else {
-        o << "(bad assignment)";
-      }
-    },
-    [](llvm::raw_ostream &o, const Fortran::evaluate::ProcedureRef &x) {
-      x.AsFortran(o << "CALL ");
-    },
-};
-
-std::string CompileFortran(std::string path, Fortran::parser::Options options,
-    DriverOptions &driver,
-    const Fortran::common::IntrinsicTypeDefaultKinds &defaultKinds) {
-  Fortran::parser::AllSources allSources;
-  Fortran::parser::AllCookedSources allCookedSources{allSources};
-  allSources.set_encoding(driver.encoding);
-  Fortran::semantics::SemanticsContext semanticsContext{
-      defaultKinds, options.features, allCookedSources};
-  semanticsContext.set_moduleDirectory(driver.moduleDirectory)
-      .set_moduleFileSuffix(driver.moduleFileSuffix)
-      .set_searchDirectories(driver.searchDirectories)
-      .set_warnOnNonstandardUsage(driver.warnOnNonstandardUsage)
-      .set_warningsAreErrors(driver.warningsAreErrors);
-  if (!driver.forcedForm) {
-    auto dot{path.rfind(".")};
-    if (dot != std::string::npos) {
-      std::string suffix{path.substr(dot + 1)};
-      options.isFixedForm = suffix == "f" || suffix == "F" || suffix == "ff";
-    }
-  }
-  options.searchDirectories = driver.searchDirectories;
-  Fortran::parser::Parsing parsing{allCookedSources};
-  parsing.Prescan(path, options);
-  if (!parsing.messages().empty() &&
-      (driver.warningsAreErrors || parsing.messages().AnyFatalError())) {
-    llvm::errs() << driver.prefix << "Could not scan " << path << '\n';
-    parsing.messages().Emit(llvm::errs(), allCookedSources);
-    exitStatus = EXIT_FAILURE;
-    return {};
-  }
-  if (driver.dumpProvenance) {
-    parsing.DumpProvenance(llvm::outs());
-    return {};
-  }
-  if (options.prescanAndReformat) {
-    parsing.messages().Emit(llvm::errs(), allCookedSources);
-    if (driver.noReformat) {
-      parsing.DumpCookedChars(llvm::outs());
-    } else {
-      parsing.EmitPreprocessedSource(llvm::outs(), driver.lineDirectives);
-    }
-    return {};
-  }
-  parsing.Parse(llvm::outs());
-  if (options.instrumentedParse) {
-    parsing.DumpParsingLog(llvm::outs());
-    return {};
-  }
-  parsing.ClearLog();
-  parsing.messages().Emit(llvm::errs(), allCookedSources);
-  if (!parsing.consumedWholeFile()) {
-    parsing.EmitMessage(llvm::errs(), parsing.finalRestingPlace(),
-        "Parser FAIL (final position)");
-    exitStatus = EXIT_FAILURE;
-    return {};
-  }
-  if ((!parsing.messages().empty() &&
-          (driver.warningsAreErrors || parsing.messages().AnyFatalError())) ||
-      !parsing.parseTree()) {
-    llvm::errs() << driver.prefix << "Could not parse " << path << '\n';
-    exitStatus = EXIT_FAILURE;
-    return {};
-  }
-  auto &parseTree{*parsing.parseTree()};
-  if (driver.measureTree) {
-    MeasureParseTree(parseTree);
-  }
-  if (!driver.debugNoSemantics || driver.dumpSymbols ||
-      driver.dumpUnparseWithSymbols || driver.getDefinition ||
-      driver.getSymbolsSources) {
-    Fortran::semantics::Semantics semantics{
-        semanticsContext, parseTree, driver.debugModuleWriter};
-    semantics.Perform();
-    Fortran::semantics::RuntimeDerivedTypeTables tables;
-    if (!semantics.AnyFatalError()) {
-      tables =
-          Fortran::semantics::BuildRuntimeDerivedTypeTables(semanticsContext);
-      if (!tables.schemata) {
-        llvm::errs() << driver.prefix
-                     << "could not find module file for __fortran_type_info\n";
-      }
-    }
-    semantics.EmitMessages(llvm::errs());
-    if (semantics.AnyFatalError()) {
-      if (driver.dumpSymbols) {
-        semantics.DumpSymbols(llvm::outs());
-      }
-      llvm::errs() << driver.prefix << "Semantic errors in " << path << '\n';
-      exitStatus = EXIT_FAILURE;
-      if (driver.dumpParseTree) {
-        Fortran::parser::DumpTree(llvm::outs(), parseTree, &asFortran);
-      }
-      return {};
-    }
-    if (driver.dumpSymbols) {
-      semantics.DumpSymbols(llvm::outs());
-    }
-    if (driver.dumpUnparseWithSymbols) {
-      Fortran::semantics::UnparseWithSymbols(
-          llvm::outs(), parseTree, driver.encoding);
-      return {};
-    }
-    if (driver.getSymbolsSources) {
-      semantics.DumpSymbolsSources(llvm::outs());
-      return {};
-    }
-    if (driver.getDefinition) {
-      if (auto cb{allCookedSources.GetCharBlockFromLineAndColumns(
-              driver.getDefinitionArgs.line,
-              driver.getDefinitionArgs.startColumn,
-              driver.getDefinitionArgs.endColumn)}) {
-        llvm::errs() << "String range: >" << cb->ToString() << "<\n";
-        if (auto symbol{semanticsContext.FindScope(*cb).FindSymbol(*cb)}) {
-          llvm::errs() << "Found symbol name: " << symbol->name().ToString()
-                       << "\n";
-          if (auto sourceInfo{
-                  allCookedSources.GetSourcePositionRange(symbol->name())}) {
-            llvm::outs() << symbol->name().ToString() << ": "
-                         << sourceInfo->first.file.path() << ", "
-                         << sourceInfo->first.line << ", "
-                         << sourceInfo->first.column << "-"
-                         << sourceInfo->second.column << "\n";
-            exitStatus = EXIT_SUCCESS;
-            return {};
-          }
-        }
-      }
-      llvm::errs() << "Symbol not found.\n";
-      exitStatus = EXIT_FAILURE;
-      return {};
-    }
-  }
-  if (driver.dumpParseTree) {
-    Fortran::parser::DumpTree(llvm::outs(), parseTree, &asFortran);
-  }
-  if (driver.dumpUnparse) {
-    // Prepare the output stream
-    std::unique_ptr<llvm::raw_fd_ostream> os;
-    std::string outputFile = "-";
-    if (!driver.outputPath.empty()) {
-      outputFile = driver.outputPath;
-    }
-
-    std::error_code EC;
-    os.reset(new llvm::raw_fd_ostream(
-        outputFile, EC, llvm::sys::fs::OF_TextWithCRLF));
-    if (EC) {
-      llvm::errs() << EC.message() << "\n";
-      std::exit(EXIT_FAILURE);
-    }
-
-    Unparse(*os, parseTree, driver.encoding, true /*capitalize*/,
-        options.features.IsEnabled(
-            Fortran::common::LanguageFeature::BackslashEscapes),
-        nullptr /* action before each statement */,
-        driver.useAnalyzedObjectsForUnparse ? &asFortran : nullptr);
-    return {};
-  }
-  if (driver.dumpPreFirTree) {
-    if (auto ast{Fortran::lower::createPFT(parseTree, semanticsContext)}) {
-      Fortran::lower::dumpPFT(llvm::outs(), *ast);
-    } else {
-      llvm::errs() << "Pre FIR Tree is NULL.\n";
-      exitStatus = EXIT_FAILURE;
-    }
-  }
-  if (driver.syntaxOnly) {
-    return {};
-  }
-
-  std::string relo{RelocatableName(driver, path)};
-
-  llvm::SmallString<32> tmpSourcePath;
-  {
-    int fd;
-    std::error_code EC =
-        llvm::sys::fs::createUniqueFile("f18-%%%%.f90", fd, tmpSourcePath);
-    if (EC) {
-      llvm::errs() << EC.message() << "\n";
-      std::exit(EXIT_FAILURE);
-    }
-    llvm::raw_fd_ostream tmpSource(fd, /*shouldClose*/ true);
-    Unparse(tmpSource, parseTree, driver.encoding, true /*capitalize*/,
-        options.features.IsEnabled(
-            Fortran::common::LanguageFeature::BackslashEscapes),
-        nullptr /* action before each statement */,
-        driver.useAnalyzedObjectsForUnparse ? &asFortran : nullptr);
-  }
-
-  RunOtherCompiler(driver, tmpSourcePath.data(), relo.data());
-  filesToDelete.emplace_back(tmpSourcePath);
-  if (!driver.compileOnly && driver.outputPath.empty()) {
-    filesToDelete.push_back(relo);
-  }
-  return relo;
-}
-
-std::string CompileOtherLanguage(std::string path, DriverOptions &driver) {
-  std::string relo{RelocatableName(driver, path)};
-  RunOtherCompiler(driver, path.data(), relo.data());
-  if (!driver.compileOnly && driver.outputPath.empty()) {
-    filesToDelete.push_back(relo);
-  }
-  return relo;
-}
-
-void Link(std::vector<std::string> &liblist, std::vector<std::string> &objects,
-    DriverOptions &driver) {
-  std::vector<llvm::StringRef> argv;
-  for (size_t j{0}; j < driver.F18_FCArgs.size(); ++j) {
-    argv.push_back(driver.F18_FCArgs[j].data());
-  }
-  for (auto &obj : objects) {
-    argv.push_back(obj.data());
-  }
-  if (!driver.outputPath.empty()) {
-    char dashO[3] = "-o";
-    argv.push_back(dashO);
-    argv.push_back(driver.outputPath.data());
-  }
-  for (auto &lib : liblist) {
-    argv.push_back(lib.data());
-  }
-  Exec(argv, driver.verbose);
-}
-
-int printVersion() {
-  llvm::errs() << "\nf18 compiler (under development), version "
-               << FLANG_VERSION_STRING << "\n";
-  return exitStatus;
-}
-
-// 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);
-}
-
-int main(int argc, char *const argv[]) {
-
-  atexit(CleanUpAtExit);
-
-  DriverOptions driver;
-  const char *F18_FC{getenv("F18_FC")};
-  driver.F18_FCArgs.push_back(F18_FC ? F18_FC : "gfortran");
-  bool isPGF90{driver.F18_FCArgs.back().rfind("pgf90") != std::string::npos};
-
-  std::list<std::string> args{argList(argc, argv)};
-  std::vector<std::string> objlist, liblist;
-  std::string prefix{args.front()};
-  args.pop_front();
-  prefix += ": ";
-  driver.prefix = prefix.data();
-
-  Fortran::parser::Options options;
-  std::vector<Fortran::parser::Options::Predefinition> predefinitions;
-  predefinitions.emplace_back("__F18", "1");
-  predefinitions.emplace_back("__F18_MAJOR__", "1");
-  predefinitions.emplace_back("__F18_MINOR__", "1");
-  predefinitions.emplace_back("__F18_PATCHLEVEL__", "1");
-  predefinitions.emplace_back("__flang__", FLANG_VERSION_STRING);
-  predefinitions.emplace_back("__flang_major__", FLANG_VERSION_MAJOR_STRING);
-  predefinitions.emplace_back("__flang_minor__", FLANG_VERSION_MINOR_STRING);
-  predefinitions.emplace_back(
-      "__flang_patchlevel__", FLANG_VERSION_PATCHLEVEL_STRING);
-#if __x86_64__
-  predefinitions.emplace_back("__x86_64__", "1");
-#endif
-
-  Fortran::common::IntrinsicTypeDefaultKinds defaultKinds;
-
-  std::vector<std::string> fortranSources, otherSources;
-  bool anyFiles{false};
-
-  // Add the default intrinsic module directory to the list of search
-  // directories
-  driver.searchDirectories.push_back(getIntrinsicDir());
-
-  while (!args.empty()) {
-    std::string arg{std::move(args.front())};
-    auto dot{arg.rfind(".")};
-    std::string suffix{arg.substr(dot + 1)};
-    std::string prefix{arg.substr(0, 2)};
-    args.pop_front();
-    if (arg.empty() || arg == "-Xflang") {
-    } else if (arg.at(0) != '-') {
-      anyFiles = true;
-      if (dot == std::string::npos) {
-        driver.F18_FCArgs.push_back(arg);
-      } else {
-        if (suffix == "f" || suffix == "F" || suffix == "ff" ||
-            suffix == "f90" || suffix == "F90" || suffix == "ff90" ||
-            suffix == "f95" || suffix == "F95" || suffix == "ff95" ||
-            suffix == "cuf" || suffix == "CUF" || suffix == "f18" ||
-            suffix == "F18" || suffix == "ff18") {
-          fortranSources.push_back(arg);
-        } else if (suffix == "o" || suffix == "so") {
-          objlist.push_back(arg);
-        } else if (suffix == "a") {
-          liblist.push_back(arg);
-        } else {
-          otherSources.push_back(arg);
-        }
-      }
-    } else if (prefix == "-l" || suffix == "a") {
-      liblist.push_back(arg);
-    } else if (arg == "-") {
-      fortranSources.push_back("-");
-    } else if (arg == "--") {
-      while (!args.empty()) {
-        fortranSources.emplace_back(std::move(args.front()));
-        args.pop_front();
-      }
-      break;
-    } else if (arg == "-Mfixed" || arg == "-ffixed-form") {
-      driver.forcedForm = true;
-      options.isFixedForm = true;
-    } else if (arg == "-Mfree" || arg == "-ffree-form") {
-      driver.forcedForm = true;
-      options.isFixedForm = false;
-    } else if (arg == "-Mextend" || arg == "-ffixed-line-length-132") {
-      options.fixedFormColumns = 132;
-    } else if (arg == "-Munlimited" || arg == "-ffree-line-length-none" ||
-        arg == "-ffree-line-length-0" || arg == "-ffixed-line-length-none" ||
-        arg == "-ffixed-line-length-0") {
-      // For reparsing f18's -E -fno-reformat output of fixed-form
-      // cooked character stream
-      options.fixedFormColumns = 1000000;
-    } else if (arg == "-Mbackslash") {
-      options.features.Enable(
-          Fortran::common::LanguageFeature::BackslashEscapes, false);
-    } else if (arg == "-Mnobackslash") {
-      options.features.Enable(
-          Fortran::common::LanguageFeature::BackslashEscapes, true);
-    } else if (arg == "-Mstandard" || arg == "-std=f95" ||
-        arg == "-std=f2003" || arg == "-std=f2008" || arg == "-std=legacy" ||
-        arg == "-std=f2018" || arg == "-pedantic") {
-      driver.warnOnNonstandardUsage = true;
-    } else if (arg == "-fopenacc") {
-      options.features.Enable(Fortran::common::LanguageFeature::OpenACC);
-      predefinitions.emplace_back("_OPENACC", "202011");
-    } else if (arg == "-fopenmp") {
-      options.features.Enable(Fortran::common::LanguageFeature::OpenMP);
-      predefinitions.emplace_back("_OPENMP", "201511");
-    } else if (arg.find("-W") != std::string::npos) {
-      if (arg == "-Werror")
-        driver.warningsAreErrors = true;
-    } else if (arg == "-ed") {
-      options.features.Enable(Fortran::common::LanguageFeature::OldDebugLines);
-    } else if (arg == "-E") {
-      options.prescanAndReformat = true;
-    } else if (arg == "-P") {
-      driver.lineDirectives = false;
-    } else if (arg == "-fno-reformat") {
-      driver.noReformat = true;
-    } else if (arg == "-fbackslash" || arg == "-fno-backslash") {
-      options.features.Enable(
-          Fortran::common::LanguageFeature::BackslashEscapes,
-          arg == "-fbackslash");
-    } else if (arg == "-fxor-operator" || arg == "-fno-xor-operator") {
-      options.features.Enable(Fortran::common::LanguageFeature::XOROperator,
-          arg == "-fxor-operator");
-    } else if (arg == "-flogical-abbreviations" ||
-        arg == "-fno-logical-abbreviations") {
-      options.features.Enable(
-          Fortran::parser::LanguageFeature::LogicalAbbreviations,
-          arg == "-flogical-abbreviations");
-    } else if (arg == "-fimplicit-none-type-always" ||
-        arg == "-fimplicit-none") {
-      options.features.Enable(
-          Fortran::common::LanguageFeature::ImplicitNoneTypeAlways);
-    } else if (arg == "-fno-implicit-none") {
-      options.features.Enable(
-          Fortran::common::LanguageFeature::ImplicitNoneTypeAlways, false);
-    } else if (arg == "-fimplicit-none-type-never") {
-      options.features.Enable(
-          Fortran::common::LanguageFeature::ImplicitNoneTypeNever);
-    } else if (arg == "-falternative-parameter-statement") {
-      options.features.Enable(
-          Fortran::common::LanguageFeature::OldStyleParameter, true);
-    } else if (arg == "-fdebug-dump-provenance") {
-      driver.dumpProvenance = true;
-      options.needProvenanceRangeToCharBlockMappings = true;
-    } else if (arg == "-fdebug-dump-parse-tree") {
-      driver.dumpParseTree = true;
-      driver.syntaxOnly = true;
-    } else if (arg == "-fdebug-pre-fir-tree") {
-      driver.dumpPreFirTree = true;
-    } else if (arg == "-fdebug-dump-symbols") {
-      driver.dumpSymbols = true;
-      driver.syntaxOnly = true;
-    } else if (arg == "-fdebug-module-writer") {
-      driver.debugModuleWriter = true;
-    } else if (arg == "-fdebug-measure-parse-tree") {
-      driver.measureTree = true;
-    } else if (arg == "-fdebug-instrumented-parse" ||
-        arg == "-fdebug-dump-parsing-log") {
-      options.instrumentedParse = true;
-    } else if (arg == "-fdebug-no-semantics") {
-      driver.debugNoSemantics = true;
-    } else if (arg == "-fdebug-unparse-no-sema") {
-      driver.debugNoSemantics = true;
-      driver.dumpUnparse = true;
-    } else if (arg == "-fdebug-dump-parse-tree-no-sema") {
-      driver.debugNoSemantics = true;
-      driver.dumpParseTree = true;
-      driver.syntaxOnly = true;
-    } else if (arg == "-funparse" || arg == "-fdebug-unparse") {
-      driver.dumpUnparse = true;
-    } else if (arg == "-funparse-with-symbols" ||
-        arg == "-fdebug-unparse-with-symbols") {
-      driver.dumpUnparseWithSymbols = true;
-    } else if (arg == "-fno-analyzed-objects-for-unparse") {
-      driver.useAnalyzedObjectsForUnparse = false;
-    } else if (arg == "-fparse-only" || arg == "-fsyntax-only") {
-      driver.syntaxOnly = true;
-    } else if (arg == "-c") {
-      driver.compileOnly = true;
-    } else if (arg == "-o") {
-      driver.outputPath = args.front();
-      args.pop_front();
-    } else if (arg.substr(0, 2) == "-D") {
-      auto eq{arg.find('=')};
-      if (eq == std::string::npos) {
-        predefinitions.emplace_back(arg.substr(2), "1");
-      } else {
-        predefinitions.emplace_back(arg.substr(2, eq - 2), arg.substr(eq + 1));
-      }
-    } else if (arg.substr(0, 2) == "-U") {
-      predefinitions.emplace_back(arg.substr(2), std::optional<std::string>{});
-    } else if (arg == "-r8" || arg == "-fdefault-real-8") {
-      driver.defaultReal8 = true;
-      defaultKinds.set_defaultRealKind(8);
-      defaultKinds.set_doublePrecisionKind(16);
-    } else if (arg == "-fdefault-double-8") {
-      if (!driver.defaultReal8) {
-        // -fdefault-double-8 has to be used with -fdefault-real-8
-        // to be compatible with gfortran. See:
-        // https://gcc.gnu.org/onlinedocs/gfortran/Fortran-Dialect-Options.html
-        llvm::errs()
-            << "Use of `-fdefault-double-8` requires `-fdefault-real-8`\n";
-        return EXIT_FAILURE;
-      }
-      defaultKinds.set_doublePrecisionKind(8);
-    } else if (arg == "-i8" || arg == "-fdefault-integer-8") {
-      defaultKinds.set_defaultIntegerKind(8);
-      defaultKinds.set_subscriptIntegerKind(8);
-      defaultKinds.set_sizeIntegerKind(8);
-      if (isPGF90) {
-        driver.F18_FCArgs.push_back("-i8");
-      } else {
-        driver.F18_FCArgs.push_back("-fdefault-integer-8");
-      }
-    } else if (arg == "-flarge-sizes") {
-      defaultKinds.set_sizeIntegerKind(8);
-    } else if (arg == "-fno-large-sizes") {
-      defaultKinds.set_sizeIntegerKind(4);
-    } else if (arg == "-module") {
-      driver.moduleDirectory = args.front();
-      args.pop_front();
-    } else if (arg == "-module-dir") {
-      driver.moduleDirectory = args.front();
-      driver.searchDirectories.push_back(driver.moduleDirectory);
-      args.pop_front();
-    } else if (arg == "-module-suffix") {
-      driver.moduleFileSuffix = args.front();
-      args.pop_front();
-    } else if (arg == "-intrinsic-module-directory" ||
-        arg == "-fintrinsic-modules-path") {
-      // prepend to the list of search directories
-      driver.searchDirectories.insert(
-          driver.searchDirectories.begin(), args.front());
-      args.pop_front();
-    } else if (arg == "-futf-8") {
-      driver.encoding = Fortran::parser::Encoding::UTF_8;
-    } else if (arg == "-flatin") {
-      driver.encoding = Fortran::parser::Encoding::LATIN_1;
-    } else if (arg == "-fget-definition") {
-      // Receives 3 arguments: line, startColumn, endColumn.
-      options.needProvenanceRangeToCharBlockMappings = true;
-      driver.getDefinition = true;
-      char *endptr;
-      int arguments[3];
-      for (int i = 0; i < 3; i++) {
-        if (args.empty()) {
-          llvm::errs() << "Must provide 3 arguments for -fget-definitions.\n";
-          return EXIT_FAILURE;
-        }
-        arguments[i] = std::strtol(args.front().c_str(), &endptr, 10);
-        if (*endptr != '\0') {
-          llvm::errs() << "error: invalid value '" << args.front()
-                       << "' in 'fget-definition'" << '\n';
-          return EXIT_FAILURE;
-        }
-        args.pop_front();
-      }
-      driver.getDefinitionArgs = {arguments[0], arguments[1], arguments[2]};
-    } else if (arg == "-fget-symbols-sources") {
-      driver.getSymbolsSources = true;
-    } else if (arg == "-byteswapio") {
-      driver.byteswapio = true; // TODO: Pass to lowering, generate call
-    } else if (arg == "-cpp") {
-      driver.forcePreprocessing = true;
-    } else if (arg == "-nocpp") {
-      driver.forcePreprocessing = false;
-    } else if (arg == "-h" || arg == "-help" || arg == "--help" ||
-        arg == "-?") {
-      llvm::errs()
-          << "f18: LLVM Fortran compiler\n"
-          << "\n"
-          << "Usage: f18 [options] <input files>\n"
-          << "\n"
-          << "Defaults:\n"
-          << "  When invoked with input files, and no options to tell\n"
-          << "  it otherwise, f18 will unparse its input and pass that on to "
-             "an\n"
-          << "  external compiler to continue the compilation.\n"
-          << "  The external compiler is specified by the F18_FC environment\n"
-          << "  variable. The default is 'gfortran'.\n"
-          << "  If invoked with no input files, f18 reads source code from\n"
-          << "  stdin and runs with -fdebug-measure-parse-tree -funparse.\n"
-          << "\n"
-          << "f18 options:\n"
-          << "  -Mfixed | -Mfree | -ffixed-form | -ffree-form   force the "
-             "source form\n"
-          << "  -Mextend | -ffixed-line-length-132   132-column fixed form\n"
-          << "  -f[no-]backslash     enable[disable] \\escapes in literals\n"
-          << "  -M[no]backslash      disable[enable] \\escapes in literals\n"
-          << "  -Mstandard           enable conformance warnings\n"
-          << "  -std=<standard>      enable conformance warnings\n"
-          << "  -r8 | -fdefault-real-8 | -i8 | -fdefault-integer-8 | "
-             "-fdefault-double-8   change default kinds of intrinsic types\n"
-          << "  -Werror              treat warnings as errors\n"
-          << "  -ed                  enable fixed form D lines\n"
-          << "  -E                   prescan & preprocess only\n"
-          << "  -module dir          module output directory (default .)\n"
-          << "  -module-dir/-J <dir> Put MODULE files in <dir>\n"
-          << "  -flatin              interpret source as Latin-1 (ISO 8859-1) "
-             "rather than UTF-8\n"
-          << "  -fsyntax-only        parsing and semantics only, no output "
-             "except messages\n"
-          << "  -funparse            parse & reformat only, no code "
-             "generation\n"
-          << "  -funparse-with-symbols  parse, resolve symbols, and unparse\n"
-          << "  -fdebug-measure-parse-tree\n"
-          << "  -fdebug-dump-provenance\n"
-          << "  -fdebug-dump-parse-tree\n"
-          << "  -fdebug-dump-symbols\n"
-          << "  -fdebug-instrumented-parse\n"
-          << "  -fdebug-no-semantics  disable semantic checks\n"
-          << "  -fget-definition\n"
-          << "  -fget-symbols-sources\n"
-          << "  -v -c -o -I -D -U    have their usual meanings\n"
-          << "  -cpp / -nocpp        force / inhibit macro replacement\n"
-          << "  -help                print this again\n"
-          << "Unrecognised options are passed through to the external "
-             "compiler\n"
-          << "set by F18_FC (see defaults).\n";
-      return exitStatus;
-    } else if (arg == "-V" || arg == "--version") {
-      return printVersion();
-    } else if (arg == "-fdebug-stack-trace") {
-      llvm::sys::PrintStackTraceOnErrorSignal(llvm::StringRef{}, true);
-    } else {
-      driver.F18_FCArgs.push_back(arg);
-      if (arg == "-v") {
-        if (args.size() > 1) {
-          driver.verbose = true;
-        } else {
-          return printVersion();
-        }
-      } else if (arg == "-I") {
-        driver.F18_FCArgs.push_back(args.front());
-        driver.searchDirectories.push_back(args.front());
-        args.pop_front();
-      } else if (arg.substr(0, 2) == "-I") {
-        driver.searchDirectories.push_back(arg.substr(2));
-      } else if (arg == "-J") {
-        driver.F18_FCArgs.push_back(args.front());
-        driver.moduleDirectory = args.front();
-        driver.searchDirectories.push_back(driver.moduleDirectory);
-        args.pop_front();
-      } else if (arg.substr(0, 2) == "-J") {
-        driver.moduleDirectory = arg.substr(2);
-        driver.searchDirectories.push_back(driver.moduleDirectory);
-      }
-    }
-  }
-
-  if (driver.warnOnNonstandardUsage) {
-    options.features.WarnOnAllNonstandard();
-  }
-  if (isPGF90) {
-    if (!options.features.IsEnabled(
-            Fortran::common::LanguageFeature::BackslashEscapes)) {
-      driver.F18_FCArgs.push_back(
-          "-Mbackslash"); // yes, this *disables* them in pgf90
-    }
-    if (options.features.IsEnabled(Fortran::common::LanguageFeature::OpenMP)) {
-      driver.F18_FCArgs.push_back("-mp");
-    }
-
-    Fortran::parser::useHexadecimalEscapeSequences = false;
-  } else {
-    if (options.features.IsEnabled(
-            Fortran::common::LanguageFeature::BackslashEscapes)) {
-      driver.F18_FCArgs.push_back("-fbackslash");
-    }
-    if (options.features.IsEnabled(Fortran::common::LanguageFeature::OpenMP)) {
-      driver.F18_FCArgs.push_back("-fopenmp");
-    }
-
-    Fortran::parser::useHexadecimalEscapeSequences = true;
-  }
-
-  if (!anyFiles) {
-    driver.measureTree = true;
-    driver.dumpUnparse = true;
-    llvm::outs() << "Enter Fortran source\n"
-                 << "Use EOF character (^D) to end file\n";
-    CompileFortran("-", options, driver, defaultKinds);
-    return exitStatus;
-  }
-  for (const auto &path : fortranSources) {
-    options.predefinitions.clear();
-    if (driver.forcePreprocessing) {
-      if (*driver.forcePreprocessing) {
-        options.predefinitions = predefinitions;
-      }
-    } else {
-      auto dot{path.rfind(".")};
-      if (dot != std::string::npos) {
-        std::string suffix{path.substr(dot + 1)};
-        if (suffix == "F" || suffix == "F90" || suffix == "F95" ||
-            suffix == "CUF" || suffix == "F18") {
-          options.predefinitions = predefinitions;
-        }
-      }
-    }
-    std::string relo{CompileFortran(path, options, driver, defaultKinds)};
-    if (!driver.compileOnly && !relo.empty()) {
-      objlist.push_back(relo);
-    }
-  }
-  for (const auto &path : otherSources) {
-    std::string relo{CompileOtherLanguage(path, driver)};
-    if (!driver.compileOnly && !relo.empty()) {
-      objlist.push_back(relo);
-    }
-  }
-  if (!driver.compileOnly && !objlist.empty()) {
-    Link(liblist, objlist, driver);
-  }
-  return exitStatus;
-}

diff  --git a/flang/tools/f18/flang.in b/flang/tools/f18/flang
similarity index 94%
rename from flang/tools/f18/flang.in
rename to flang/tools/f18/flang
index 284e89bd5e481..bdd00f58e3945 100755
--- a/flang/tools/f18/flang.in
+++ b/flang/tools/f18/flang
@@ -10,7 +10,7 @@
 # experimenting. You should be able to use it as a regular compiler driver. It
 # will:
 #   * run Flang's compiler driver to unparse the input source files
-#   * use the external compiler (defined via F18_FC environment variable) to
+#   * use the external compiler (defined via FLANG_FC environment variable) to
 #   compile the unparsed source files
 #===------------------------------------------------------------------------===#
 set -euo pipefail
@@ -182,7 +182,7 @@ categorise_opts()
 
     if
       # The options claimed by Flang. This list needs to be compatible with
-      # what's supported by Flang's compiler driver (i.e. `flang-new` and f18).
+      # what's supported by Flang's compiler driver (i.e. `flang-new`).
       [[ $opt == "-cpp" ]] ||
       [[ $opt =~ ^-D.* ]] ||
       [[ $opt == "-E" ]] ||
@@ -244,7 +244,18 @@ preprocess() {
   local -n other_srcs=$2
   local -n opts=$3
 
-  local -r ext_fc="${F18_FC:-gfortran}"
+  local ext_fc=""
+  if [[ -v $FLANG_FC ]]; then
+    ext_fc="${FLANG_FC}"
+  elif [[ -v $F18_FC ]]; then
+    # We support F18_FC for backwards compatibility.
+    ext_fc="${F18_FC}"
+  else
+    ext_fc=gfortran
+  fi
+
+
+  local ext_fc="${FLANG_FC:-gfortran}"
   local -r wd=$(cd "$(dirname "$0")/.." && pwd)
 
   # Use the provided output file name.
@@ -254,9 +265,9 @@ preprocess() {
 
   # Preprocess fortran sources using Flang
   for idx in "${!fortran_srcs[@]}"; do
-    if ! "$wd/bin/@FLANG_DEFAULT_DRIVER@" -E "${opts[@]}" "${fortran_srcs[$idx]}" ${output_definition:+$output_definition}
+    if ! "$wd/bin/flang-new" -E "${opts[@]}" "${fortran_srcs[$idx]}" ${output_definition:+$output_definition}
     then status=$?
-         echo flang: in "$PWD", @FLANG_DEFAULT_DRIVER@ failed with exit status $status: "$wd/bin/@FLANG_DEFAULT_DRIVER@" "${opts[@]}" "$@" >&2
+         echo flang: in "$PWD", flang-new failed with exit status $status: "$wd/bin/flang-new" "${opts[@]}" "$@" >&2
          exit $status
     fi
   done
@@ -323,8 +334,7 @@ main() {
   # NOTE: We need `-fc1` to make sure that the frontend driver rather than
   # compiler driver is used. We also need to make sure that that's the first
   # flag that the driver will see (otherwise it assumes compiler/toolchain
-  # driver mode).`f18` will just ignore this flag when uparsing, so it's fine
-  # to add it here unconditionally.
+  # driver mode).
   local flang_options=("-fc1")
   # Options for the external Fortran Compiler
   local ext_fc_options=()
@@ -349,11 +359,11 @@ main() {
   [[ ! -z ${INTRINSICS_MOD_DIR} ]] && flang_options+=("-intrinsics-module-directory ${INTRINSICS_MOD_DIR}")
   for idx in "${!fortran_source_files[@]}"; do
     set +e
-    "$wd/bin/@FLANG_DEFAULT_DRIVER@" "${flang_options[@]}" "${fortran_source_files[$idx]}" -o "${unparsed_file_base}_${idx}.f90"
+    "$wd/bin/flang-new" "${flang_options[@]}" "${fortran_source_files[$idx]}" -o "${unparsed_file_base}_${idx}.f90"
     ret_status=$?
     set -e
     if [[ $ret_status != 0 ]]; then
-         echo flang: in "$PWD", @FLANG_DEFAULT_DRIVER@ failed with exit status "$ret_status": "$wd/bin/@FLANG_DEFAULT_DRIVER@" "${flang_options[@]}" "$@" >&2
+         echo flang: in "$PWD", flang-new failed with exit status "$ret_status": "$wd/bin/flang-new" "${flang_options[@]}" "$@" >&2
          exit "$ret_status"
     fi
   done

diff  --git a/flang/unittests/CMakeLists.txt b/flang/unittests/CMakeLists.txt
index 54af3aff21d62..5acebce7192af 100644
--- a/flang/unittests/CMakeLists.txt
+++ b/flang/unittests/CMakeLists.txt
@@ -40,7 +40,4 @@ add_subdirectory(Optimizer)
 add_subdirectory(Decimal)
 add_subdirectory(Evaluate)
 add_subdirectory(Runtime)
-
-if (FLANG_BUILD_NEW_DRIVER)
-  add_subdirectory(Frontend)
-endif()
+add_subdirectory(Frontend)

diff  --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index 50ba9b3be1b8f..db6d119156717 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -81,9 +81,8 @@ if ("flang" IN_LIST LLVM_ENABLE_PROJECTS)
     list(APPEND LLVM_ENABLE_PROJECTS "mlir")
   endif()
 
-  option(FLANG_BUILD_NEW_DRIVER "Build the flang compiler driver" ON)
-  if (FLANG_BUILD_NEW_DRIVER AND NOT "clang" IN_LIST LLVM_ENABLE_PROJECTS)
-    message(FATAL_ERROR "Clang is not enabled, but it's required by the new Flang driver")
+  if (NOT "clang" IN_LIST LLVM_ENABLE_PROJECTS)
+    message(FATAL_ERROR "Clang is not enabled, but is required for the Flang driver")
   endif()
 endif()
 


        


More information about the llvm-commits mailing list