[llvm-branch-commits] [clang] a1a0f84 - [ClassicFlang] Port flang-driver release_90 changes to release/10.x

Bryan Chan via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Jun 24 08:41:01 PDT 2020


Author: Bryan Chan
Date: 2020-06-23T11:27:10-04:00
New Revision: a1a0f84b986d6a3cc7b81edb9ff20a78a0c2aca2

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

LOG: [ClassicFlang] Port flang-driver release_90 changes to release/10.x

Cherry-picked c51f89679135f84675f492d560ec5535c2000cfe by Varun Jayathirtha,
and resolved merge conflicts.

To avoid conflicts with the new Flang, lib/Driver/ToolChains/Flang.{cpp,h}
have been renamed to Flang1.{cpp,h}, and the USE_CLASSIC_FLANG macro is
introduced to select which incarnation of Flang to build. The macro is set
by running CMake with -DLLVM_ENABLE_CLASSIC_FLANG.

Added: 
    clang/lib/Driver/ToolChains/Flang1.cpp
    clang/lib/Driver/ToolChains/Flang1.h

Modified: 
    clang/CMakeLists.txt
    clang/include/clang/Basic/CodeGenOptions.def
    clang/include/clang/Basic/CodeGenOptions.h
    clang/include/clang/Basic/DiagnosticDriverKinds.td
    clang/include/clang/Basic/MacroBuilder.h
    clang/include/clang/Basic/Sanitizers.def
    clang/include/clang/Driver/Action.h
    clang/include/clang/Driver/Options.td
    clang/include/clang/Driver/Phases.h
    clang/include/clang/Driver/ToolChain.h
    clang/include/clang/Driver/Types.def
    clang/include/clang/Driver/Types.h
    clang/include/clang/Frontend/Utils.h
    clang/lib/CodeGen/BackendUtil.cpp
    clang/lib/CodeGen/CodeGenAction.cpp
    clang/lib/Driver/Action.cpp
    clang/lib/Driver/CMakeLists.txt
    clang/lib/Driver/Driver.cpp
    clang/lib/Driver/Phases.cpp
    clang/lib/Driver/ToolChain.cpp
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Driver/ToolChains/CommonArgs.cpp
    clang/lib/Driver/ToolChains/CommonArgs.h
    clang/lib/Driver/ToolChains/Cuda.cpp
    clang/lib/Driver/ToolChains/Cuda.h
    clang/lib/Driver/ToolChains/Gnu.cpp
    clang/lib/Driver/ToolChains/Linux.cpp
    clang/lib/Driver/ToolChains/Linux.h
    clang/lib/Driver/Types.cpp
    clang/lib/Frontend/CompilerInvocation.cpp
    clang/lib/Frontend/InitPreprocessor.cpp
    clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
    clang/tools/driver/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt
index dc1413f4b597..d7ebdb48f5b5 100644
--- a/clang/CMakeLists.txt
+++ b/clang/CMakeLists.txt
@@ -458,6 +458,16 @@ endif()
 
 add_definitions( -D_GNU_SOURCE )
 
+option(LLVM_ENABLE_CLASSIC_FLANG "Build support for classic Flang instead of the new built-in Flang" OFF)
+if(LLVM_ENABLE_CLASSIC_FLANG)
+  add_definitions( -DUSE_CLASSIC_FLANG )
+endif()
+
+option(FLANG_LLVM_EXTENSIONS "enable the Flang LLVM extensions" OFF)
+if(FLANG_LLVM_EXTENSIONS)
+  add_definitions( -DFLANG_LLVM_EXTENSIONS )
+endif()
+
 option(CLANG_BUILD_TOOLS
   "Build the Clang tools. If OFF, just generate build targets." ON)
 

diff  --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 1ecae98b13b1..5ce83d904387 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -329,7 +329,7 @@ CODEGENOPT(CodeViewGHash, 1, 0)
 ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining)
 
 // Vector functions library to use.
-ENUM_CODEGENOPT(VecLib, VectorLibrary, 2, NoLibrary)
+ENUM_CODEGENOPT(VecLib, VectorLibrary, 3, NoLibrary)
 
 /// The default TLS model to use.
 ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel)

diff  --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index 21ac54e8ee12..520adf446ea6 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -55,6 +55,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
     NoLibrary,  // Don't use any vector library.
     Accelerate, // Use the Accelerate framework.
     MASSV,      // IBM MASS vector library.
+#ifdef FLANG_LLVM_EXTENSIONS
+    PGMATH,     // PGI math library.
+#endif
     SVML        // Intel short vector math library.
   };
 

diff  --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 48ece91d3c45..8580c5933524 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -73,6 +73,10 @@ def err_drv_invalid_pgo_instrumentor : Error<
   "invalid PGO instrumentor in argument '%0'">;
 def err_drv_invalid_rtlib_name : Error<
   "invalid runtime library name in argument '%0'">;
+def err_drv_invalid_allocatable_mode : Error<
+  "invalid semantic mode for assignments to allocatables in argument '%0'">;
+def err_drv_unsupported_fixed_line_length : Error<
+  "unsupported fixed-format line length in argument '%0'">;
 def err_drv_unsupported_rtlib_for_platform : Error<
   "unsupported runtime library '%0' for platform '%1'">;
 def err_drv_invalid_unwindlib_name : Error<
@@ -252,6 +256,8 @@ def err_drv_unsupported_embed_bitcode
     : Error<"%0 is not supported with -fembed-bitcode">;
 def err_drv_bitcode_unsupported_on_toolchain : Error<
   "-fembed-bitcode is not supported on versions of iOS prior to 6.0">;
+def err_drv_clang_unsupported_minfo_arg : Error<
+  "'%0' option does not support '%1' value">;
 
 def err_drv_invalid_malign_branch_EQ : Error<
   "invalid argument '%0' to -malign-branch=; each element must be one of: %1">;

diff  --git a/clang/include/clang/Basic/MacroBuilder.h b/clang/include/clang/Basic/MacroBuilder.h
index 96e67cbbfa3f..a5fb7e73f287 100644
--- a/clang/include/clang/Basic/MacroBuilder.h
+++ b/clang/include/clang/Basic/MacroBuilder.h
@@ -26,7 +26,7 @@ class MacroBuilder {
   MacroBuilder(raw_ostream &Output) : Out(Output) {}
 
   /// Append a \#define line for macro of the form "\#define Name Value\n".
-  void defineMacro(const Twine &Name, const Twine &Value = "1") {
+  virtual void defineMacro(const Twine &Name, const Twine &Value = "1") {
     Out << "#define " << Name << ' ' << Value << '\n';
   }
 

diff  --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def
index 0037cc2146f2..0f51cd0e001e 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -104,6 +104,8 @@ SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
 SANITIZER("unreachable", Unreachable)
 SANITIZER("vla-bound", VLABound)
 SANITIZER("vptr", Vptr)
+// fortran contiguous pointer checks
+SANITIZER("discontiguous", Discontiguous)
 
 // IntegerSanitizer
 SANITIZER("unsigned-integer-overflow", UnsignedIntegerOverflow)

diff  --git a/clang/include/clang/Driver/Action.h b/clang/include/clang/Driver/Action.h
index 8ccbb6c2bbfa..40ded1c839de 100644
--- a/clang/include/clang/Driver/Action.h
+++ b/clang/include/clang/Driver/Action.h
@@ -62,6 +62,7 @@ class Action {
     AnalyzeJobClass,
     MigrateJobClass,
     CompileJobClass,
+    FortranFrontendJobClass,
     BackendJobClass,
     AssembleJobClass,
     LinkJobClass,
@@ -454,6 +455,16 @@ class MigrateJobAction : public JobAction {
   }
 };
 
+class FortranFrontendJobAction : public JobAction {
+  void anchor() override;
+public:
+  FortranFrontendJobAction(Action *Input, types::ID OutputType);
+
+  static bool classof(const Action *A) {
+    return A->getKind() == FortranFrontendJobClass;
+  }
+};
+
 class CompileJobAction : public JobAction {
   void anchor() override;
 

diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 0a60873443fc..2b0a00c570e0 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -254,7 +254,7 @@ class InternalDriverOpt : Group<internal_driver_Group>,
   Flags<[DriverOption, HelpHidden]>;
 def driver_mode : Joined<["--"], "driver-mode=">, Group<internal_driver_Group>,
   Flags<[CoreOption, DriverOption, HelpHidden]>,
-  HelpText<"Set the driver mode to either 'gcc', 'g++', 'cpp', or 'cl'">;
+  HelpText<"Set the driver mode to either 'gcc', 'g++', 'cpp', 'cl', or 'fortran'">;
 def rsp_quoting : Joined<["--"], "rsp-quoting=">, Group<internal_driver_Group>,
   Flags<[CoreOption, DriverOption, HelpHidden]>,
   HelpText<"Set the rsp quoting to either 'posix', or 'windows'">;
@@ -1511,7 +1511,7 @@ def fno_experimental_new_pass_manager : Flag<["-"], "fno-experimental-new-pass-m
   Group<f_clang_Group>, Flags<[CC1Option]>,
   HelpText<"Disables an experimental new pass manager in LLVM.">;
 def fveclib : Joined<["-"], "fveclib=">, Group<f_Group>, Flags<[CC1Option]>,
-    HelpText<"Use the given vector functions library">, Values<"Accelerate,MASSV,SVML,none">;
+    HelpText<"Use the given vector functions library">, Values<"Accelerate,MASSV,PGMATH,SVML,none">;
 def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group<f_Group>,
   Alias<flax_vector_conversions_EQ>, AliasArgs<["none"]>;
 def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group<f_Group>,
@@ -3318,11 +3318,19 @@ defm devirtualize : BooleanFFlag<"devirtualize">, Group<clang_ignored_gcc_optimi
 defm devirtualize_speculatively : BooleanFFlag<"devirtualize-speculatively">,
     Group<clang_ignored_gcc_optimization_f_Group>;
 
+// gfortran options that we recognize in the driver and pass along when
+// invoking GCC to compile Fortran code.
+def flang_rt_Group : OptionGroup<"Flang runtime library Group">;
+def pgi_fortran_Group : OptionGroup<"PGI Fortran compatibility Group">,
+  Flags<[HelpHidden]>;
+
 // Generic gfortran options.
 def A_DASH : Joined<["-"], "A-">, Group<gfortran_Group>;
 def J : JoinedOrSeparate<["-"], "J">, Flags<[RenderJoined]>, Group<gfortran_Group>;
-def cpp : Flag<["-"], "cpp">, Group<gfortran_Group>;
-def nocpp : Flag<["-"], "nocpp">, Group<gfortran_Group>;
+def cpp : Flag<["-"], "cpp">, Group<gfortran_Group>,
+  HelpText<"Preprocess Fortran files">;
+def nocpp : Flag<["-"], "nocpp">, Group<gfortran_Group>,
+  HelpText<"Don't preprocess Fortran files">;
 def static_libgfortran : Flag<["-"], "static-libgfortran">, Group<gfortran_Group>;
 
 // "f" options with values for gfortran.
@@ -3330,7 +3338,8 @@ def fblas_matmul_limit_EQ : Joined<["-"], "fblas-matmul-limit=">, Group<gfortran
 def fcheck_EQ : Joined<["-"], "fcheck=">, Group<gfortran_Group>;
 def fcoarray_EQ : Joined<["-"], "fcoarray=">, Group<gfortran_Group>;
 def fconvert_EQ : Joined<["-"], "fconvert=">, Group<gfortran_Group>;
-def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group<gfortran_Group>;
+def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group<gfortran_Group>,
+  HelpText<"Set line length in fixed-form format Fortran, current supporting only 72 and 132 characters">;
 def ffpe_trap_EQ : Joined<["-"], "ffpe-trap=">, Group<gfortran_Group>;
 def ffree_line_length_VALUE : Joined<["-"], "ffree-line-length-">, Group<gfortran_Group>;
 def finit_character_EQ : Joined<["-"], "finit-character=">, Group<gfortran_Group>;
@@ -3343,12 +3352,17 @@ def fmax_stack_var_size_EQ : Joined<["-"], "fmax-stack-var-size=">, Group<gfortr
 def fmax_subrecord_length_EQ : Joined<["-"], "fmax-subrecord-length=">, Group<gfortran_Group>;
 def frecord_marker_EQ : Joined<["-"], "frecord-marker=">, Group<gfortran_Group>;
 
+// Define a group for Fortran source format
+def fortran_format_Group : OptionGroup<"Fortran format Group">, Group<gfortran_Group>;
 // "f" flags for gfortran.
 defm aggressive_function_elimination : BooleanFFlag<"aggressive-function-elimination">, Group<gfortran_Group>;
 defm align_commons : BooleanFFlag<"align-commons">, Group<gfortran_Group>;
 defm all_intrinsics : BooleanFFlag<"all-intrinsics">, Group<gfortran_Group>;
 defm automatic : BooleanFFlag<"automatic">, Group<gfortran_Group>;
-defm backslash : BooleanFFlag<"backslash">, Group<gfortran_Group>;
+def fbackslash: Flag<["-"], "fbackslash">, Group<gfortran_Group>,
+  HelpText<"Treat backslash as C-style escape character">;
+def fnobackslash: Flag<["-"], "fno-backslash">, Group<gfortran_Group>,
+  HelpText<"Treat backslash like any other character in character strings">;
 defm backtrace : BooleanFFlag<"backtrace">, Group<gfortran_Group>;
 defm bounds_check : BooleanFFlag<"bounds-check">, Group<gfortran_Group>;
 defm check_array_temporaries : BooleanFFlag<"check-array-temporaries">, Group<gfortran_Group>;
@@ -3356,17 +3370,27 @@ defm cray_pointer : BooleanFFlag<"cray-pointer">, Group<gfortran_Group>;
 defm d_lines_as_code : BooleanFFlag<"d-lines-as-code">, Group<gfortran_Group>;
 defm d_lines_as_comments : BooleanFFlag<"d-lines-as-comments">, Group<gfortran_Group>;
 defm default_double_8 : BooleanFFlag<"default-double-8">, Group<gfortran_Group>;
-defm default_integer_8 : BooleanFFlag<"default-integer-8">, Group<gfortran_Group>;
-defm default_real_8 : BooleanFFlag<"default-real-8">, Group<gfortran_Group>;
+def default_integer_8_f : Flag<["-"], "fdefault-integer-8">, Group<gfortran_Group>,
+  HelpText<"Treat INTEGER and LOGICAL as INTEGER*8 and LOGICAL*8">;
+def default_integer_8_fno : Flag<["-"], "fno-default-integer-8">, Group<gfortran_Group>;
+def default_real_8_f : Flag<["-"], "fdefault-real-8">, Group<gfortran_Group>,
+  HelpText<"Treat REAL as REAL*8">;
+def default_real_8_fno : Flag<["-"], "fno-default-real-8">, Group<gfortran_Group>;
 defm dollar_ok : BooleanFFlag<"dollar-ok">, Group<gfortran_Group>;
 defm dump_fortran_optimized : BooleanFFlag<"dump-fortran-optimized">, Group<gfortran_Group>;
 defm dump_fortran_original : BooleanFFlag<"dump-fortran-original">, Group<gfortran_Group>;
 defm dump_parse_tree : BooleanFFlag<"dump-parse-tree">, Group<gfortran_Group>;
 defm external_blas : BooleanFFlag<"external-blas">, Group<gfortran_Group>;
 defm f2c : BooleanFFlag<"f2c">, Group<gfortran_Group>;
-defm fixed_form : BooleanFFlag<"fixed-form">, Group<gfortran_Group>;
-defm free_form : BooleanFFlag<"free-form">, Group<gfortran_Group>;
-defm frontend_optimize : BooleanFFlag<"frontend-optimize">, Group<gfortran_Group>;
+def fixed_form_on : Flag<["-"], "ffixed-form">, Group<fortran_format_Group>,
+  HelpText<"Enable fixed-form format for Fortran">;
+def fixed_form_off : Flag<["-"], "fno-fixed-form">, Group<fortran_format_Group>,
+  HelpText<"Disable fixed-form format for Fortran">;
+def free_form_on : Flag<["-"], "ffree-form">, Group<fortran_format_Group>,
+  HelpText<"Enable free-form format for Fortran">;
+def free_form_off : Flag<["-"], "fno-free-form">, Group<fortran_format_Group>,
+  HelpText<"Disable free-form format for Fortran">;
+defm frontend_optimize : BooleanFFlag<"frontend-optimize">, Group<fortran_format_Group>;
 defm implicit_none : BooleanFFlag<"implicit-none">, Group<gfortran_Group>;
 defm init_local_zero : BooleanFFlag<"init-local-zero">, Group<gfortran_Group>;
 defm integer_4_integer_8 : BooleanFFlag<"integer-4-integer-8">, Group<gfortran_Group>;
@@ -3391,6 +3415,137 @@ defm stack_arrays : BooleanFFlag<"stack-arrays">, Group<gfortran_Group>;
 defm underscoring : BooleanFFlag<"underscoring">, Group<gfortran_Group>;
 defm whole_file : BooleanFFlag<"whole-file">, Group<gfortran_Group>;
 
+// Flang-specific options
+multiclass BooleanKFlag<string name> {
+  def _on : Flag<["-"], "K"#name>;
+  def _off : Flag<["-"], "Kno"#name>;
+}
+
+multiclass BooleanMFlag<string name> {
+  def _on : Flag<["-"], "M"#name>;
+  def _off : Flag<["-"], "Mno"#name>;
+}
+
+def Mfixed : Flag<["-"], "Mfixed">, Group<fortran_format_Group>,
+  HelpText<"Force fixed-form format Fortran">,
+  Flags<[HelpHidden]>;
+def Mfree_on: Flag<["-"], "Mfree">, Group<fortran_format_Group>,
+  HelpText<"Enable free-form format for Fortran">,
+  Flags<[HelpHidden]>;
+def Mfree_off: Flag<["-"], "Mnofree">, Group<fortran_format_Group>,
+  HelpText<"Disable free-form format for Fortran">,
+  Flags<[HelpHidden]>;
+def Mfreeform_on: Flag<["-"], "Mfreeform">, Group<fortran_format_Group>,
+  HelpText<"Enable free-form format for Fortran">,
+  Flags<[HelpHidden]>;
+def Mfreeform_off: Flag<["-"], "Mnofreeform">, Group<fortran_format_Group>,
+  HelpText<"Disable free-form format for Fortran">,
+  Flags<[HelpHidden]>;
+
+def Minfo_EQ : CommaJoined<["-"], "Minfo=">,
+  HelpText<"Diagnostic information about successful optimizations">,
+  Values<"all,vect,inline">;
+def Minfoall : Flag<["-"], "Minfo">,
+  HelpText<"Diagnostic information about all successful optimizations">;
+def Mneginfo_EQ : CommaJoined<["-"], "Mneginfo=">,
+  HelpText<"Diagnostic information about missed optimizations">,
+  Values<"all,vect,inline">;
+def Mneginfoall : Flag<["-"], "Mneginfo">,
+  HelpText<"Diagnostic information about all missed optimizations">;
+def Mipa: Joined<["-"], "Mipa">, Group<pgi_fortran_Group>;
+def Mstackarrays: Joined<["-"], "Mstack_arrays">, Group<pgi_fortran_Group>;
+def pc: JoinedOrSeparate<["-"], "pc">, Group<pgi_fortran_Group>;
+def Mfprelaxed: Joined<["-"], "Mfprelaxed">, Group<pgi_fortran_Group>;
+def Mnofprelaxed: Joined<["-"], "Mnofprelaxed">, Group<pgi_fortran_Group>;
+defm Mstride0: BooleanMFlag<"stride0">, Group<pgi_fortran_Group>;
+defm Mrecursive: BooleanMFlag<"recursive">, Group<pgi_fortran_Group>;
+defm Mreentrant: BooleanMFlag<"reentrant">, Group<pgi_fortran_Group>;
+defm Mbounds: BooleanMFlag<"bounds">, Group<pgi_fortran_Group>;
+def Mdaz_on: Flag<["-"], "Mdaz">, Group<pgi_fortran_Group>,
+  HelpText<"Treat denormalized numbers as zero">;
+def Mdaz_off: Flag<["-"], "Mnodaz">, Group<pgi_fortran_Group>,
+  HelpText<"Disable treating denormalized numbers as zero">;
+def Kieee_on : Flag<["-"], "Kieee">, Group<pgi_fortran_Group>,
+  HelpText<"Enable IEEE division">;
+def Kieee_off : Flag<["-"], "Knoieee">, Group<pgi_fortran_Group>,
+  HelpText<"Disable IEEE division">;
+def Mextend : Flag<["-"], "Mextend">, Group<pgi_fortran_Group>,
+  HelpText<"Allow lines up to 132 characters in Fortran sources">;
+def Mpreprocess : Flag<["-"], "Mpreprocess">, Group<pgi_fortran_Group>,
+  HelpText<"Preprocess Fortran files">;
+def Mstandard: Flag<["-"], "Mstandard">, Group<pgi_fortran_Group>,
+  HelpText<"Check Fortran standard conformance">;
+def Mchkptr: Flag<["-"], "Mchkptr">, Group<pgi_fortran_Group>;
+def Mwritable_constants: Flag<["-"], "Mwritable-constants">, Group<pgi_fortran_Group>,
+  HelpText<"Store constants in the writable data segment">;
+defm Minline: BooleanMFlag<"inline">, Group<pgi_fortran_Group>;
+def fma: Flag<["-"], "fma">, Group<pgi_fortran_Group>,
+  HelpText<"Enable generation of FMA instructions">;
+def nofma: Flag<["-"], "nofma">, Group<pgi_fortran_Group>,
+  HelpText<"Disable generation of FMA instructions">;
+defm Mfma: BooleanMFlag<"fma">, Group<pgi_fortran_Group>,
+  HelpText<"Enable generation of FMA instructions">;
+def mp: Flag<["-"], "mp">, Group<pgi_fortran_Group>,
+  HelpText<"Enable OpenMP">;
+def nomp: Flag<["-"], "nomp">, Group<pgi_fortran_Group>,
+  HelpText<"Do not link with OpenMP library libomp">;
+def Mflushz_on: Flag<["-"], "Mflushz">, Group<pgi_fortran_Group>,
+  HelpText<"Set SSE to flush-to-zero mode">;
+def Mflushz_off: Flag<["-"], "Mnoflushz">, Group<pgi_fortran_Group>,
+  HelpText<"Disabling setting SSE to flush-to-zero mode">;
+def Msave_on: Flag<["-"], "Msave">, Group<pgi_fortran_Group>,
+  HelpText<"Assume all Fortran variables have SAVE attribute">;
+def Msave_off: Flag<["-"], "Mnosave">, Group<pgi_fortran_Group>,
+  HelpText<"Assume no Fortran variables have SAVE attribute">;
+def Mcache_align_on: Flag<["-"], "Mcache_align">, Group<pgi_fortran_Group>,
+  HelpText<"Align large objects on cache-line boundaries">;
+def Mcache_align_off: Flag<["-"], "Mnocache_align">, Group<pgi_fortran_Group>,
+  HelpText<"Disable aligning large objects on cache-line boundaries">;
+def ModuleDir : Separate<["-"], "module">, Group<pgi_fortran_Group>,
+  HelpText<"Fortran module path">;
+def Minform_EQ : Joined<["-"], "Minform=">,
+  HelpText<"Set error level of messages to display">;
+def Mallocatable_EQ : Joined<["-"], "Mallocatable=">,
+  HelpText<"Select semantics for assignments to allocatables (F03 or F95)">;
+def Mbyteswapio: Flag<["-"], "Mbyteswapio">, Group<pgi_fortran_Group>,
+  HelpText<"Swap byte-order for unformatted input/output">;
+def byteswapio: Flag<["-"], "byteswapio">, Group<gfortran_Group>,
+  HelpText<"Swap byte-order for unformatted input/output">;
+def Mbackslash: Flag<["-"], "Mbackslash">, Group<pgi_fortran_Group>,
+  HelpText<"Treat backslash like any other character in character strings">;
+def Mnobackslash: Flag<["-"], "Mnobackslash">, Group<pgi_fortran_Group>,
+  HelpText<"Treat backslash as C-style escape character">;
+def staticFlangLibs: Flag<["-"], "static-flang-libs">, Group<flang_rt_Group>,
+  HelpText<"Link using static Flang libraries">;
+def noFlangLibs: Flag<["-"], "no-flang-libs">, Group<flang_rt_Group>,
+  HelpText<"Do not link against Flang libraries">;
+def r8: Flag<["-"], "r8">, Group<pgi_fortran_Group>,
+  HelpText<"Treat REAL as REAL*8">;
+def i8: Flag<["-"], "i8">, Group<pgi_fortran_Group>,
+  HelpText<"Treat INTEGER and LOGICAL as INTEGER*8 and LOGICAL*8">;
+def no_fortran_main: Flag<["-"], "fno-fortran-main">, Group<gfortran_Group>,
+  HelpText<"Don't link in Fortran main">;
+def Mnomain: Flag<["-"], "Mnomain">, Group<pgi_fortran_Group>,
+  HelpText<"Don't link in Fortran main">;
+def frelaxed_math : Flag<["-"], "frelaxed-math">, Group<pgi_fortran_Group>,
+  HelpText<"Use relaxed Math intrinsic functions">;
+def Memit_dwarf_common_blocks_name: Flag<["-"], "Memit-dwarf-common-blocks-name">,
+  Group<pgi_fortran_Group>, HelpText<"Emit COMMON blocks name in DWARF">;
+def Munixlogical: Flag<["-"], "Munixlogical">, Group<pgi_fortran_Group>,
+  HelpText<"Use unixlogical for all loigical operations">;
+
+// Flang internal debug options
+def Mx_EQ : Joined<["-"], "Mx,">, Group<pgi_fortran_Group>;
+def My_EQ : Joined<["-"], "My,">, Group<pgi_fortran_Group>;
+def Hx_EQ : Joined<["-"], "Hx,">, Group<pgi_fortran_Group>;
+def Hy_EQ : Joined<["-"], "Hy,">, Group<pgi_fortran_Group>;
+def Wm_EQ : Joined<["-"], "Wm,">, Group<pgi_fortran_Group>;
+
+def Mq_EQ : Joined<["-"], "Mq,">, Group<pgi_fortran_Group>;
+def Hq_EQ : Joined<["-"], "Hq,">, Group<pgi_fortran_Group>;
+def Mqq_EQ : Joined<["-"], "Mqq,">, Group<pgi_fortran_Group>;
+def Hqq_EQ : Joined<["-"], "Hqq,">, Group<pgi_fortran_Group>;
+def Wh_EQ : Joined<["-"], "Wh,">, Group<pgi_fortran_Group>;
 
 include "CC1Options.td"
 

diff  --git a/clang/include/clang/Driver/Phases.h b/clang/include/clang/Driver/Phases.h
index 63931c00c890..994d5608fb18 100644
--- a/clang/include/clang/Driver/Phases.h
+++ b/clang/include/clang/Driver/Phases.h
@@ -17,6 +17,7 @@ namespace phases {
   enum ID {
     Preprocess,
     Precompile,
+    FortranFrontend,
     Compile,
     Backend,
     Assemble,

diff  --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 26d8d43dd2fc..c7800a3c43d4 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -135,6 +135,7 @@ class ToolChain {
 
   mutable std::unique_ptr<Tool> Clang;
   mutable std::unique_ptr<Tool> Flang;
+  mutable std::unique_ptr<Tool> FortranFrontend;
   mutable std::unique_ptr<Tool> Assemble;
   mutable std::unique_ptr<Tool> Link;
   mutable std::unique_ptr<Tool> IfsMerge;
@@ -143,6 +144,7 @@ class ToolChain {
 
   Tool *getClang() const;
   Tool *getFlang() const;
+  Tool *getFortranFrontend() const;
   Tool *getAssemble() const;
   Tool *getLink() const;
   Tool *getIfsMerge() const;
@@ -521,6 +523,14 @@ class ToolChain {
   AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                             llvm::opt::ArgStringList &CC1Args) const;
 
+  /// \brief Add the flang arguments for system include paths.
+  ///
+  /// This routine is responsible for adding the -stdinc argument to
+  /// include headers and module files from standard system header directories.
+  virtual void
+  AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+                            llvm::opt::ArgStringList &Flang1Args) const { }
+
   /// Add options that need to be passed to cc1 for this target.
   virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
                                      llvm::opt::ArgStringList &CC1Args,
@@ -595,6 +605,11 @@ class ToolChain {
   virtual VersionTuple computeMSVCVersion(const Driver *D,
                                           const llvm::opt::ArgList &Args) const;
 
+  /// AddFortranStdlibLibArgs - Add the system specific linker arguments to use
+  /// for the given Fortran runtime library type.
+  virtual void AddFortranStdlibLibArgs(const llvm::opt::ArgList &Args,
+                                       llvm::opt::ArgStringList &CmdArgs) const;
+
   /// Return sanitizers which are available in this toolchain.
   virtual SanitizerMask getSupportedSanitizers() const;
 

diff  --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def
index 79e8d109cd97..382175dabcce 100644
--- a/clang/include/clang/Driver/Types.def
+++ b/clang/include/clang/Driver/Types.def
@@ -71,8 +71,15 @@ TYPE("c++-module-cpp-output",    PP_CXXModule, INVALID,         "iim",    phases
 TYPE("ada",                      Ada,          INVALID,         nullptr,  phases::Compile, phases::Backend, phases::Assemble, phases::Link)
 TYPE("assembler",                PP_Asm,       INVALID,         "s",      phases::Assemble, phases::Link)
 TYPE("assembler-with-cpp",       Asm,          PP_Asm,          "S",      phases::Preprocess, phases::Assemble, phases::Link)
+#ifdef USE_CLASSIC_FLANG
+TYPE("f77",                      PP_F_FixedForm, INVALID,       "f",      phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("f77-cpp-input",            F_FixedForm,  PP_F_FixedForm,  "F",      phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("f95",                      PP_F_FreeForm, INVALID,        "f95",    phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("f95-cpp-input",            F_FreeForm,   PP_F_FreeForm,   "F95",    phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+#else
 TYPE("f95",                      PP_Fortran,   INVALID,         nullptr,  phases::Compile, phases::Backend, phases::Assemble, phases::Link)
 TYPE("f95-cpp-input",            Fortran,      PP_Fortran,      nullptr,  phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+#endif
 TYPE("java",                     Java,         INVALID,         nullptr,  phases::Compile, phases::Backend, phases::Assemble, phases::Link)
 
 // LLVM IR/LTO types. We define separate types for IR and LTO because LTO

diff  --git a/clang/include/clang/Driver/Types.h b/clang/include/clang/Driver/Types.h
index c7c38fa52593..80226792477c 100644
--- a/clang/include/clang/Driver/Types.h
+++ b/clang/include/clang/Driver/Types.h
@@ -87,6 +87,14 @@ namespace types {
   /// isFortran - Is this a Fortran input.
   bool isFortran(ID Id);
 
+#ifdef USE_CLASSIC_FLANG
+  /// isFreeFormFortran -- is it a free form layout Fortran input
+  bool isFreeFormFortran(ID Id);
+
+  /// isFixedFormFortran -- is it a fixed form layout Fortran input
+  bool isFixedFormFortran(ID Id);
+#endif
+
   /// isSrcFile - Is this a source file, i.e. something that still has to be
   /// preprocessed. The logic behind this is the same that decides if the first
   /// compilation phase is a preprocessing one.

diff  --git a/clang/include/clang/Frontend/Utils.h b/clang/include/clang/Frontend/Utils.h
index b5834921b9ed..680710b9118f 100644
--- a/clang/include/clang/Frontend/Utils.h
+++ b/clang/include/clang/Frontend/Utils.h
@@ -17,6 +17,7 @@
 #include "clang/Basic/LLVM.h"
 #include "clang/Driver/OptionUtils.h"
 #include "clang/Frontend/DependencyOutputOptions.h"
+#include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/StringMap.h"
@@ -34,6 +35,7 @@
 namespace llvm {
 
 class Triple;
+class StringRef;
 
 } // namespace llvm
 
@@ -48,6 +50,7 @@ class FrontendOptions;
 class HeaderSearch;
 class HeaderSearchOptions;
 class LangOptions;
+class MacroBuilder;
 class PCHContainerReader;
 class Preprocessor;
 class PreprocessorOptions;
@@ -69,6 +72,29 @@ void InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &PPOpts,
 void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,
                               const PreprocessorOutputOptions &Opts);
 
+/// DefineTypeSize - Emit a macro to the predefines buffer that declares a macro
+/// named MacroName with the max value for a type with width 'TypeWidth' a
+/// signedness of 'isSigned' and with a value suffix of 'ValSuffix' (e.g. LL).
+template<typename T>
+static void DefineTypeSize(const Twine &MacroName, unsigned TypeWidth,
+                           StringRef ValSuffix, bool isSigned,
+                           T &Builder) {
+  static_assert(std::is_base_of<MacroBuilder, T>::value, "Illegal T value");
+  llvm::APInt MaxVal = isSigned ? llvm::APInt::getSignedMaxValue(TypeWidth)
+                                : llvm::APInt::getMaxValue(TypeWidth);
+  Builder.defineMacro(MacroName, MaxVal.toString(10, isSigned) + ValSuffix);
+}
+
+/// DefineTypeSize - An overloaded helper that uses TargetInfo to determine
+/// the width, suffix, and signedness of the given type
+template<typename T>
+static void DefineTypeSize(const Twine &MacroName, TargetInfo::IntType Ty,
+                           const TargetInfo &TI, T &Builder) {
+  static_assert(std::is_base_of<MacroBuilder, T>::value, "Illegal T value");
+  DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty),
+                 TI.isTypeSigned(Ty), Builder);
+}
+
 /// An interface for collecting the dependencies of a compilation. Users should
 /// use \c attachToPreprocessor and \c attachToASTReader to get all of the
 /// dependencies.

diff  --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 0bfcab88a3a9..59afa7aad484 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -354,6 +354,11 @@ static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple,
   case CodeGenOptions::SVML:
     TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::SVML);
     break;
+#ifdef FLANG_LLVM_EXTENSIONS
+  case CodeGenOptions::PGMATH:
+    TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::PGMATH);
+    break;
+#endif
   default:
     break;
   }

diff  --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index 20ebaf3578d6..594cc85e3510 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -1165,13 +1165,14 @@ void CodeGenAction::ExecuteAction() {
     std::unique_ptr<llvm::ToolOutputFile> OptRecordFile =
         std::move(*OptRecordFileOrErr);
 
-    EmitBackendOutput(Diagnostics, CI.getHeaderSearchOpts(), CodeGenOpts,
-                      TargetOpts, CI.getLangOpts(),
+    EmitBackendOutput(CI.getDiagnostics(), CI.getHeaderSearchOpts(),
+                      CI.getCodeGenOpts(), TargetOpts, CI.getLangOpts(),
                       CI.getTarget().getDataLayout(), TheModule.get(), BA,
                       std::move(OS));
 
     if (OptRecordFile)
       OptRecordFile->keep();
+
     return;
   }
 

diff  --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp
index 0eb4c7257e7a..a0a1d9953fe4 100644
--- a/clang/lib/Driver/Action.cpp
+++ b/clang/lib/Driver/Action.cpp
@@ -28,6 +28,7 @@ const char *Action::getClassName(ActionClass AC) {
   case HeaderModulePrecompileJobClass: return "header-module-precompiler";
   case AnalyzeJobClass: return "analyzer";
   case MigrateJobClass: return "migrator";
+  case FortranFrontendJobClass: return "fortran-frontend";
   case CompileJobClass: return "compiler";
   case BackendJobClass: return "backend";
   case AssembleJobClass: return "assembler";
@@ -345,6 +346,12 @@ void MigrateJobAction::anchor() {}
 MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
     : JobAction(MigrateJobClass, Input, OutputType) {}
 
+void FortranFrontendJobAction::anchor() {}
+
+FortranFrontendJobAction::FortranFrontendJobAction(Action *Input,
+                                             types::ID OutputType)
+    : JobAction(FortranFrontendJobClass, Input, OutputType) {}
+
 void CompileJobAction::anchor() {}
 
 CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)

diff  --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index 6f25d3588ebb..561939e6dc5c 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -46,6 +46,7 @@ add_clang_library(clangDriver
   ToolChains/Darwin.cpp
   ToolChains/DragonFly.cpp
   ToolChains/Flang.cpp
+  ToolChains/Flang1.cpp
   ToolChains/FreeBSD.cpp
   ToolChains/Fuchsia.cpp
   ToolChains/Gnu.cpp

diff  --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index fb8335a3695d..5b5053f3bb73 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -271,18 +271,42 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
 
   // -{E,EP,P,M,MM} only run the preprocessor.
   if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) ||
+#ifdef USE_CLASSIC_FLANG
+      (PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
+#endif
       (PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) ||
       (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) ||
       (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) {
+#ifdef USE_CLASSIC_FLANG
+    // -fsyntax-only or -E stops Fortran compilation after FortranFrontend
+    if (IsFlangMode() && (DAL.getLastArg(options::OPT_E) ||
+      DAL.getLastArg(options::OPT_fsyntax_only))) {
+      FinalPhase = phases::FortranFrontend;
+
+      // if not Fortran, fsyntax_only implies 'Compile' is the FinalPhase
+    } else if (DAL.getLastArg(options::OPT_fsyntax_only)) {
+      FinalPhase = phases::Compile;
+
+      // everything else has 'Preprocess' as its FinalPhase
+    } else {
+      FinalPhase = phases::Preprocess;
+    }
+#else
     FinalPhase = phases::Preprocess;
+#endif
 
   // --precompile only runs up to precompilation.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile))) {
     FinalPhase = phases::Precompile;
 
+#ifdef USE_CLASSIC_FLANG
+  // -{analyze,emit-ast} only run up to the compiler.
+  } else if ((PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) ||
+#else
   // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
              (PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) ||
+#endif
              (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
              (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) ||
              (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||
@@ -3648,6 +3672,13 @@ Action *Driver::ConstructPhaseAction(
                                                            ModName);
     return C.MakeAction<PrecompileJobAction>(Input, OutputTy);
   }
+  case phases::FortranFrontend: {
+    if (Args.hasArg(options::OPT_fsyntax_only))
+      return C.MakeAction<FortranFrontendJobAction>(Input,
+                                                    types::TY_Nothing);
+    return C.MakeAction<FortranFrontendJobAction>(Input,
+                                                  types::TY_LLVM_IR);
+  }
   case phases::Compile: {
     if (Args.hasArg(options::OPT_fsyntax_only))
       return C.MakeAction<CompileJobAction>(Input, types::TY_Nothing);

diff  --git a/clang/lib/Driver/Phases.cpp b/clang/lib/Driver/Phases.cpp
index 01598c59bd9e..f0216c5ab7c2 100644
--- a/clang/lib/Driver/Phases.cpp
+++ b/clang/lib/Driver/Phases.cpp
@@ -16,6 +16,7 @@ const char *phases::getPhaseName(ID Id) {
   switch (Id) {
   case Preprocess: return "preprocessor";
   case Precompile: return "precompiler";
+  case FortranFrontend: return "fortran-frontend";
   case Compile: return "compiler";
   case Backend: return "backend";
   case Assemble: return "assembler";

diff  --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index cab97b1a601a..86e6e0c469a1 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -10,6 +10,7 @@
 #include "InputInfo.h"
 #include "ToolChains/Arch/ARM.h"
 #include "ToolChains/Clang.h"
+#include "ToolChains/Flang1.h"
 #include "ToolChains/InterfaceStubs.h"
 #include "ToolChains/Flang.h"
 #include "clang/Basic/ObjCRuntime.h"
@@ -276,6 +277,12 @@ Tool *ToolChain::getAssemble() const {
   return Assemble.get();
 }
 
+Tool *ToolChain::getFortranFrontend() const {
+  if (!FortranFrontend)
+    FortranFrontend.reset(new tools::FlangFrontend(*this));
+  return FortranFrontend.get();
+}
+
 Tool *ToolChain::getClangAs() const {
   if (!Assemble)
     Assemble.reset(new tools::ClangAs(*this));
@@ -341,6 +348,9 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
 
   case Action::OffloadWrapperJobClass:
     return getOffloadWrapper();
+
+  case Action::FortranFrontendJobClass:
+    return getFortranFrontend();
   }
 
   llvm_unreachable("Invalid tool kind.");
@@ -551,13 +561,13 @@ std::string ToolChain::GetLinkerPath() const {
 
 types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {
   types::ID id = types::lookupTypeForExtension(Ext);
-
+#ifndef USE_CLASSIC_FLANG
   // Flang always runs the preprocessor and has no notion of "preprocessed
   // fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating
   // them 
diff erently.
   if (D.IsFlangMode() && id == types::TY_PP_Fortran)
     id = types::TY_Fortran;
-
+#endif
   return id;
 }
 
@@ -915,6 +925,49 @@ void ToolChain::AddCCKextLibArgs(const ArgList &Args,
   CmdArgs.push_back("-lcc_kext");
 }
 
+void ToolChain::AddFortranStdlibLibArgs(const ArgList &Args,
+                                    ArgStringList &CmdArgs) const {
+ bool staticFlangLibs = false;
+ bool useOpenMP = false;
+
+  if (Args.hasArg(options::OPT_staticFlangLibs)) {
+    for (auto *A: Args.filtered(options::OPT_staticFlangLibs)) {
+      A->claim();
+      staticFlangLibs = true;
+    }
+  }
+
+  Arg *A = Args.getLastArg(options::OPT_mp, options::OPT_nomp,
+                           options::OPT_fopenmp, options::OPT_fno_openmp);
+  if (A &&
+      (A->getOption().matches(options::OPT_mp) ||
+       A->getOption().matches(options::OPT_fopenmp))) {
+      useOpenMP = true;
+  }
+
+  if (staticFlangLibs) {
+    CmdArgs.push_back("-Bstatic");
+  }
+  CmdArgs.push_back("-lflang");
+  CmdArgs.push_back("-lflangrti");
+  CmdArgs.push_back("-lpgmath");
+  if( useOpenMP ) {
+    CmdArgs.push_back("-lomp");
+  }
+  else {
+    CmdArgs.push_back("-lompstub");
+  }
+  if( staticFlangLibs ) {
+    CmdArgs.push_back("-Bdynamic");
+  }
+
+  CmdArgs.push_back("-lm");
+  CmdArgs.push_back("-lrt");
+
+  // Allways link Fortran executables with Pthreads
+  CmdArgs.push_back("-lpthread");
+}
+
 bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args,
                                               ArgStringList &CmdArgs) const {
   // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index fa025be14e43..d004c1975926 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -4370,7 +4370,68 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   else
     CmdArgs.push_back(Args.MakeArgString(TC.getThreadModel()));
 
+#ifdef FLANG_LLVM_EXTENSIONS
+  if(Args.getLastArg(options::OPT_fveclib))
+    Args.AddLastArg(CmdArgs, options::OPT_fveclib);
+  else
+    CmdArgs.push_back("-fveclib=PGMATH");
+#else
   Args.AddLastArg(CmdArgs, options::OPT_fveclib);
+#endif
+
+  std::string PassRemarkVal(""), PassRemarkOpt("");
+  if (Args.getLastArg(options::OPT_Minfoall)) {
+    PassRemarkVal = ".*";
+    Args.ClaimAllArgs(options::OPT_Minfoall);
+  } else if (Arg *A = Args.getLastArg(options::OPT_Minfo_EQ)) {
+    for (const StringRef &val : A->getValues()) {
+      if(val.equals("all")) {
+        PassRemarkVal = ".*";
+        break;
+      } else if(val.equals("inline") || val.equals("vect")) {
+        PassRemarkVal += PassRemarkVal.empty() ? "" : "|";
+        PassRemarkVal += val;
+      } else {
+        D.Diag(diag::err_drv_clang_unsupported_minfo_arg)
+          << A->getOption().getName()
+          << val.str();
+        break;
+      }
+    }
+  }
+  PassRemarkOpt = "-pass-remarks=" + PassRemarkVal;
+  CmdArgs.push_back("-mllvm");
+  CmdArgs.push_back(Args.MakeArgString(PassRemarkOpt));
+  Args.ClaimAllArgs(options::OPT_Minfo_EQ);
+  PassRemarkVal.clear();
+  PassRemarkOpt.clear();
+
+  if (Args.getLastArg(options::OPT_Mneginfoall)) {
+    PassRemarkVal = ".*";
+    Args.ClaimAllArgs(options::OPT_Mneginfoall);
+  } else if (Arg *A = Args.getLastArg(options::OPT_Mneginfo_EQ)) {
+    for (const StringRef &val : A->getValues()) {
+      if(val.equals("all")) {
+        PassRemarkVal = ".*";
+        break;
+      } else if(val.equals("inline") || val.equals("vect")) {
+        PassRemarkVal += PassRemarkVal.empty() ? "" : "|";
+        PassRemarkVal += val;
+      } else {
+        D.Diag(diag::err_drv_clang_unsupported_minfo_arg)
+          << A->getOption().getName()
+          << val.str();
+        break;
+      }
+    }
+  }
+  PassRemarkOpt = "-pass-remarks-missed=" + PassRemarkVal;
+  CmdArgs.push_back("-mllvm");
+  CmdArgs.push_back(Args.MakeArgString(PassRemarkOpt));
+  PassRemarkOpt = "-pass-remarks-analysis=" + PassRemarkVal;
+  CmdArgs.push_back("-mllvm");
+  CmdArgs.push_back(Args.MakeArgString(PassRemarkOpt));
+  Args.ClaimAllArgs(options::OPT_Mneginfo_EQ);
 
   if (Args.hasFlag(options::OPT_fmerge_all_constants,
                    options::OPT_fno_merge_all_constants, false))

diff  --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 37ec73468570..e7cb13592d55 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -58,6 +58,23 @@ using namespace clang::driver::tools;
 using namespace clang;
 using namespace llvm::opt;
 
+/// \brief Determine if Fortran link libraies are needed
+bool tools::needFortranLibs(const Driver &D, const ArgList &Args) {
+  if (D.IsFlangMode() && !Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_noFlangLibs)) {
+    return true;
+  }
+
+  return false;
+}
+
+/// \brief Determine if Fortran "main" object is needed
+static bool needFortranMain(const Driver &D, const ArgList &Args) {
+  return (needFortranLibs(D, Args)
+       && (!Args.hasArg(options::OPT_Mnomain) ||
+           !Args.hasArg(options::OPT_no_fortran_main)));
+}
+
 void tools::addPathIfExists(const Driver &D, const Twine &Path,
                             ToolChain::path_list &Paths) {
   if (D.getVFS().exists(Path))
@@ -140,6 +157,7 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
                             const ArgList &Args, ArgStringList &CmdArgs,
                             const JobAction &JA) {
   const Driver &D = TC.getDriver();
+  bool SeenFirstLinkerInput = false;
 
   // Add extra linker input arguments which are not treated as inputs
   // (constructed via -Xarch_).
@@ -171,6 +189,14 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
       continue;
     }
 
+    // Add Fortan "main" before the first linker input
+    if (!SeenFirstLinkerInput) {
+      if (needFortranMain(D, Args)) {
+        CmdArgs.push_back("-lflangmain");
+      }
+      SeenFirstLinkerInput = true;
+    }
+
     // Otherwise, this is a linker input argument.
     const Arg &A = II.getInputArg();
 
@@ -187,6 +213,15 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
       A.renderAsInput(Args, CmdArgs);
     }
   }
+
+  if (!SeenFirstLinkerInput && needFortranMain(D, Args)) {
+    CmdArgs.push_back("-lflangmain");
+  }
+
+  // Claim "no Fortran main" arguments
+  for (auto Arg : Args.filtered(options::OPT_no_fortran_main, options::OPT_Mnomain)) {
+    Arg->claim();
+  }
 }
 
 void tools::AddTargetFeature(const ArgList &Args,

diff  --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h
index 84b9d2cf59b4..8e0d423970bf 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -20,6 +20,8 @@ namespace clang {
 namespace driver {
 namespace tools {
 
+bool needFortranLibs(const Driver &D, const llvm::opt::ArgList &Args);
+
 void addPathIfExists(const Driver &D, const Twine &Path,
                      ToolChain::path_list &Paths);
 

diff  --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index 50d22a2a8ea7..c0fc247bd343 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -877,3 +877,36 @@ VersionTuple CudaToolChain::computeMSVCVersion(const Driver *D,
                                                const ArgList &Args) const {
   return HostTC.computeMSVCVersion(D, Args);
 }
+
+static void AddFlangSysIncludeArg(const ArgList &DriverArgs,
+                                  ArgStringList &Flang1Args,
+                                  ToolChain::path_list IncludePathList) {
+  std::string ArgValue; // Path argument value
+
+  // Make up argument value consisting of paths separated by colons
+  bool first = true;
+  for (auto P : IncludePathList) {
+    if (first) {
+      first = false;
+    } else {
+      ArgValue += ":";
+    }
+    ArgValue += P;
+  }
+
+  // Add the argument
+  Flang1Args.push_back("-stdinc");
+  Flang1Args.push_back(DriverArgs.MakeArgString(ArgValue));
+}
+
+void CudaToolChain::AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+                                              llvm::opt::ArgStringList &Flang1Args) const {
+  path_list IncludePathList;
+  const Driver &D = getDriver();
+  if (DriverArgs.hasArg(options::OPT_nostdinc))
+    return;
+  SmallString<128> P(D.InstalledDir);
+  llvm::sys::path::append(P, "../include");
+  IncludePathList.push_back(P.str());
+  AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList);
+}

diff  --git a/clang/lib/Driver/ToolChains/Cuda.h b/clang/lib/Driver/ToolChains/Cuda.h
index d1e066f93dfb..075f6eab36e8 100644
--- a/clang/lib/Driver/ToolChains/Cuda.h
+++ b/clang/lib/Driver/ToolChains/Cuda.h
@@ -193,6 +193,9 @@ class LLVM_LIBRARY_VISIBILITY CudaToolChain : public ToolChain {
   const ToolChain &HostTC;
   CudaInstallationDetector CudaInstallation;
 
+  void
+  AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+                            llvm::opt::ArgStringList &Flang1Args) const override;
 protected:
   Tool *buildAssembler() const override;  // ptxas
   Tool *buildLinker() const override;     // fatbinary (ok, not really a linker)

diff  --git a/clang/lib/Driver/ToolChains/Flang1.cpp b/clang/lib/Driver/ToolChains/Flang1.cpp
new file mode 100644
index 000000000000..17961d0bb499
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Flang1.cpp
@@ -0,0 +1,1064 @@
+//===--- Flang.cpp - Flang+LLVM ToolChain Implementations -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Flang1.h"
+#include "CommonArgs.h"
+#include "InputInfo.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/Version.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
+#include "clang/Driver/XRayArgs.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/Utils.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/Compression.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/YAMLParser.h"
+
+#ifdef LLVM_ON_UNIX
+#include <unistd.h> // For getuid().
+#endif
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+class FlangMacroBuilder : public MacroBuilder {
+  ArgStringList &CmdArgs;
+  const ArgList &DriverArgs;
+  public:
+    FlangMacroBuilder(ArgStringList &UpperCmdArgs, const ArgList &DriverArgs, llvm::raw_string_ostream &Output)
+      : MacroBuilder(Output), CmdArgs(UpperCmdArgs), DriverArgs(DriverArgs) {
+    }
+    virtual void defineMacro(const Twine &Name, const Twine &Value = "1") {
+      CmdArgs.push_back("-def");
+      CmdArgs.push_back(DriverArgs.MakeArgString(Name + Twine('=') + Value));
+    }
+};
+
+void FlangFrontend::ConstructJob(Compilation &C, const JobAction &JA,
+                         const InputInfo &Output, const InputInfoList &Inputs,
+                         const ArgList &Args, const char *LinkingOutput) const {
+  ArgStringList CommonCmdArgs;
+  ArgStringList UpperCmdArgs;
+  ArgStringList LowerCmdArgs;
+  SmallString<256> Stem;
+  std::string OutFile;
+  bool NeedIEEE = false;
+  bool NeedFastMath = false;
+  bool NeedRelaxedMath = false;
+
+  // Check number of inputs for sanity. We need at least one input.
+  assert(Inputs.size() >= 1 && "Must have at least one input.");
+
+  /***** Process file arguments to both parts *****/
+  const InputInfo &Input = Inputs[0];
+  types::ID InputType = Input.getType();
+  // Check file type sanity
+  assert(types::isFortran(InputType) && "Can only accept Fortran");
+
+  if (Args.hasArg(options::OPT_fsyntax_only)) {
+    // For -fsyntax-only produce temp files only
+    Stem = C.getDriver().GetTemporaryPath("", "");
+  } else {
+    OutFile = Output.getFilename();
+    Stem = llvm::sys::path::filename(OutFile);
+    llvm::sys::path::replace_extension(Stem, "");
+  }
+
+  // Add input file name to the compilation line
+  UpperCmdArgs.push_back(Input.getBaseInput());
+
+  // Add temporary output for ILM
+  const char * ILMFile = Args.MakeArgString(Stem + ".ilm");
+  LowerCmdArgs.push_back(ILMFile);
+  C.addTempFile(ILMFile);
+
+  // Generate -cmdline
+  std::string CmdLine("'+flang");
+  // ignore the first argument which reads "--driver-mode=fortran"
+  for (unsigned i = 1; i < Args.getNumInputArgStrings(); ++i) {
+    CmdLine.append(" ");
+    CmdLine.append(Args.getArgString(i));
+  }
+  CmdLine.append("'");
+
+  CommonCmdArgs.push_back("-cmdline");
+  CommonCmdArgs.push_back(Args.MakeArgString(CmdLine));
+
+  /***** Process common args *****/
+
+  // Add "inform level" flag
+  if (Args.hasArg(options::OPT_Minform_EQ)) {
+    // Parse arguments to set its value
+    for (Arg *A : Args.filtered(options::OPT_Minform_EQ)) {
+      A->claim();
+      CommonCmdArgs.push_back("-inform");
+      CommonCmdArgs.push_back(A->getValue(0));
+    }
+  } else {
+    // Default value
+    CommonCmdArgs.push_back("-inform");
+    CommonCmdArgs.push_back("warn");
+  }
+
+  for (auto Arg : Args.filtered(options::OPT_Msave_on)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-save");
+  }
+
+  for (auto Arg : Args.filtered(options::OPT_Msave_off)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-nosave");
+  }
+
+  // Treat denormalized numbers as zero: On
+  for (auto Arg : Args.filtered(options::OPT_Mdaz_on)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-x");
+    CommonCmdArgs.push_back("129");
+    CommonCmdArgs.push_back("4");
+    CommonCmdArgs.push_back("-y");
+    CommonCmdArgs.push_back("129");
+    CommonCmdArgs.push_back("0x400");
+  }
+
+  // Treat denormalized numbers as zero: Off
+  for (auto Arg : Args.filtered(options::OPT_Mdaz_off)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-y");
+    CommonCmdArgs.push_back("129");
+    CommonCmdArgs.push_back("4");
+    CommonCmdArgs.push_back("-x");
+    CommonCmdArgs.push_back("129");
+    CommonCmdArgs.push_back("0x400");
+  }
+
+  // Store constants in writable data segment
+  for (auto Arg : Args.filtered(options::OPT_Mwritable_constants)) {
+    Arg->claim();
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("183");
+    LowerCmdArgs.push_back("0x20000000");
+  }
+
+  // Bounds checking: On
+  for (auto Arg : Args.filtered(options::OPT_Mbounds_on)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-x");
+    CommonCmdArgs.push_back("70");
+    CommonCmdArgs.push_back("2");
+  }
+
+  // Bounds checking: Off
+  for (auto Arg : Args.filtered(options::OPT_Mbounds_off)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-y");
+    CommonCmdArgs.push_back("70");
+    CommonCmdArgs.push_back("2");
+  }
+
+  // Generate code allowing recursive subprograms
+  for (auto Arg : Args.filtered(options::OPT_Mrecursive_on)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-recursive");
+  }
+
+  // Disable recursive subprograms
+  for (auto Arg : Args.filtered(options::OPT_Mrecursive_off)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-norecursive");
+  }
+
+  // Enable generating reentrant code (disable optimizations that inhibit it)
+  for (auto Arg : Args.filtered(options::OPT_Mreentrant_on)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-reentrant");
+  }
+
+  // Allow optimizations inhibiting reentrancy
+  for (auto Arg : Args.filtered(options::OPT_Mreentrant_off)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-noreentrant");
+  }
+
+  // Swap byte order for unformatted IO
+  for (auto Arg : Args.filtered(options::OPT_Mbyteswapio, options::OPT_byteswapio)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-x");
+    CommonCmdArgs.push_back("125");
+    CommonCmdArgs.push_back("2");
+  }
+
+  // Contiguous pointer checks
+  if (Arg *A = Args.getLastArg(options::OPT_fsanitize_EQ)) {
+    for (const StringRef &val : A->getValues()) {
+      if (val.equals("discontiguous") || val.equals("undefined") ) {
+        // -x 54 0x40 -x 54 0x80 -x 54 0x200
+        UpperCmdArgs.push_back("-x");
+        UpperCmdArgs.push_back("54");
+        UpperCmdArgs.push_back("0x2c0");
+
+        // -fsanitze=discontiguous has no meaning in LLVM, only flang driver needs to
+        // recognize it. However -fsanitize=undefined needs to be passed on for further
+        // processing by the non-flang part of the driver.
+        if (val.equals("discontiguous"))
+          A->claim();
+        break;
+      }
+    }
+  }
+
+  // Treat backslashes as regular characters
+  for (auto Arg : Args.filtered(options::OPT_fnobackslash, options::OPT_Mbackslash)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-x");
+    CommonCmdArgs.push_back("124");
+    CommonCmdArgs.push_back("0x40");
+  }
+
+  // Treat backslashes as C-style escape characters
+  for (auto Arg : Args.filtered(options::OPT_fbackslash, options::OPT_Mnobackslash)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-y");
+    CommonCmdArgs.push_back("124");
+    CommonCmdArgs.push_back("0x40");
+  }
+
+  // handle OpemMP options
+  if (auto *A = Args.getLastArg(options::OPT_mp, options::OPT_nomp,
+                             options::OPT_fopenmp, options::OPT_fno_openmp)) {
+    for (auto Arg : Args.filtered(options::OPT_mp, options::OPT_nomp)) {
+      Arg->claim();
+    }
+    for (auto Arg : Args.filtered(options::OPT_fopenmp,
+                                  options::OPT_fno_openmp)) {
+      Arg->claim();
+    }
+
+    if (A->getOption().matches(options::OPT_mp) ||
+        A->getOption().matches(options::OPT_fopenmp)) {
+
+      CommonCmdArgs.push_back("-mp");
+
+       // Allocate threadprivate data local to the thread
+      CommonCmdArgs.push_back("-x");
+      CommonCmdArgs.push_back("69");
+      CommonCmdArgs.push_back("0x200");
+
+      // Use the 'fair' schedule as the default static schedule
+      // for parallel do loops
+      CommonCmdArgs.push_back("-x");
+      CommonCmdArgs.push_back("69");
+      CommonCmdArgs.push_back("0x400");
+
+      // Disable use of native atomic instructions
+      // for OpenMP atomics pending either a named
+      // option or a libatomic bundled with flang.
+      UpperCmdArgs.push_back("-x");
+      UpperCmdArgs.push_back("69");
+      UpperCmdArgs.push_back("0x1000");
+    }
+  }
+
+  // Align large objects on cache lines
+  for (auto Arg : Args.filtered(options::OPT_Mcache_align_on)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-x");
+    CommonCmdArgs.push_back("119");
+    CommonCmdArgs.push_back("0x10000000");
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("129");
+    LowerCmdArgs.push_back("0x40000000");
+  }
+
+  // Disable special alignment of large objects
+  for (auto Arg : Args.filtered(options::OPT_Mcache_align_off)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-y");
+    CommonCmdArgs.push_back("119");
+    CommonCmdArgs.push_back("0x10000000");
+    LowerCmdArgs.push_back("-y");
+    LowerCmdArgs.push_back("129");
+    LowerCmdArgs.push_back("0x40000000");
+  }
+
+  // -Mstack_arrays
+  for (auto Arg : Args.filtered(options::OPT_Mstackarrays)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-x");
+    CommonCmdArgs.push_back("54");
+    CommonCmdArgs.push_back("8");
+  }
+
+  // -Memit-dwarf-common-blocks-name, only add xbit to flang2.
+  for (auto Arg : Args.filtered(options::OPT_Memit_dwarf_common_blocks_name)) {
+    Arg->claim();
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("183");
+    LowerCmdArgs.push_back("0x40000000");
+  }
+
+  // -Munixlogical, only add xbit to flang2.
+  for (auto Arg : Args.filtered(options::OPT_Munixlogical)) {
+    Arg->claim();
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("125");
+    LowerCmdArgs.push_back("0x8");
+  }
+
+  // -g should produce DWARFv2
+  for (auto Arg : Args.filtered(options::OPT_g_Flag)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-x");
+    CommonCmdArgs.push_back("120");
+    CommonCmdArgs.push_back("0x200");
+  }
+
+  // -gdwarf-2
+  for (auto Arg : Args.filtered(options::OPT_gdwarf_2)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-x");
+    CommonCmdArgs.push_back("120");
+    CommonCmdArgs.push_back("0x200");
+  }
+
+  // -gdwarf-3
+  for (auto Arg : Args.filtered(options::OPT_gdwarf_3)) {
+    Arg->claim();
+    CommonCmdArgs.push_back("-x");
+    CommonCmdArgs.push_back("120");
+    CommonCmdArgs.push_back("0x4000");
+  }
+
+  // -Mipa has no effect
+  if (Arg *A = Args.getLastArg(options::OPT_Mipa)) {
+    getToolChain().getDriver().Diag(diag::warn_drv_clang_unsupported)
+      << A->getAsString(Args);
+  }
+
+  // -Minline has no effect
+  if (Arg *A = Args.getLastArg(options::OPT_Minline_on)) {
+    getToolChain().getDriver().Diag(diag::warn_drv_clang_unsupported)
+      << A->getAsString(Args);
+  }
+
+  // Handle -fdefault-real-8 (and its alias, -r8) and -fno-default-real-8
+  if (Arg *A = Args.getLastArg(options::OPT_r8,
+                               options::OPT_default_real_8_f,
+                               options::OPT_default_real_8_fno)) {
+    const char * fl;
+    // For -f version add -x flag, for -fno add -y
+    if (A->getOption().matches(options::OPT_default_real_8_fno)) {
+      fl = "-y";
+    } else {
+      fl = "-x";
+    }
+
+    for (Arg *A : Args.filtered(options::OPT_r8,
+                                options::OPT_default_real_8_f,
+                                options::OPT_default_real_8_fno)) {
+      A->claim();
+    }
+
+    UpperCmdArgs.push_back(fl);
+    UpperCmdArgs.push_back("124");
+    UpperCmdArgs.push_back("0x8");
+    UpperCmdArgs.push_back(fl);
+    UpperCmdArgs.push_back("124");
+    UpperCmdArgs.push_back("0x80000");
+  }
+
+  // Process and claim -i8/-fdefault-integer-8/-fno-default-integer-8 argument
+  if (Arg *A = Args.getLastArg(options::OPT_i8,
+                               options::OPT_default_integer_8_f,
+                               options::OPT_default_integer_8_fno)) {
+    const char * fl;
+
+    if (A->getOption().matches(options::OPT_default_integer_8_fno)) {
+      fl = "-y";
+    } else {
+      fl = "-x";
+    }
+
+    for (Arg *A : Args.filtered(options::OPT_i8,
+                                options::OPT_default_integer_8_f,
+                                options::OPT_default_integer_8_fno)) {
+      A->claim();
+    }
+
+    UpperCmdArgs.push_back(fl);
+    UpperCmdArgs.push_back("124");
+    UpperCmdArgs.push_back("0x10");
+  }
+
+  // Pass an arbitrary flag for first part of Fortran frontend
+  for (Arg *A : Args.filtered(options::OPT_Wh_EQ)) {
+    A->claim();
+    StringRef Value = A->getValue();
+    SmallVector<StringRef, 8> PassArgs;
+    Value.split(PassArgs, StringRef(","));
+    for (StringRef PassArg : PassArgs) {
+      UpperCmdArgs.push_back(Args.MakeArgString(PassArg));
+    }
+  }
+
+  // Flush to zero mode
+  // Disabled by default, but can be enabled by a switch
+  if (Args.hasArg(options::OPT_Mflushz_on)) {
+    // For -Mflushz set -x 129 2 for second part of Fortran frontend
+    for (Arg *A: Args.filtered(options::OPT_Mflushz_on)) {
+      A->claim();
+      LowerCmdArgs.push_back("-x");
+      LowerCmdArgs.push_back("129");
+      LowerCmdArgs.push_back("2");
+    }
+  } else {
+    LowerCmdArgs.push_back("-y");
+    LowerCmdArgs.push_back("129");
+    LowerCmdArgs.push_back("2");
+    for (Arg *A: Args.filtered(options::OPT_Mflushz_off)) {
+      A->claim();
+    }
+  }
+
+  // Enable FMA
+  for (Arg *A: Args.filtered(options::OPT_Mfma_on, options::OPT_fma)) {
+    A->claim();
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("172");
+    LowerCmdArgs.push_back("0x40000000");
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("179");
+    LowerCmdArgs.push_back("1");
+  }
+
+  // Disable FMA
+  for (Arg *A: Args.filtered(options::OPT_Mfma_off, options::OPT_nofma)) {
+    A->claim();
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("171");
+    LowerCmdArgs.push_back("0x40000000");
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("178");
+    LowerCmdArgs.push_back("1");
+  }
+
+  // For -fPIC set -x 62 8 for second part of Fortran frontend
+  for (Arg *A: Args.filtered(options::OPT_fPIC)) {
+    A->claim();
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("62");
+    LowerCmdArgs.push_back("8");
+  }
+
+  StringRef OptOStr("0");
+  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+    if (A->getOption().matches(options::OPT_O4)) {
+      OptOStr = "4"; // FIXME what should this be?
+    } else if (A->getOption().matches(options::OPT_Ofast)) {
+      OptOStr = "2"; // FIXME what should this be?
+    } else if (A->getOption().matches(options::OPT_O0)) {
+      // intentionally do nothing
+    } else {
+      assert(A->getOption().matches(options::OPT_O) && "Must have a -O flag");
+      StringRef S(A->getValue());
+      if ((S == "s") || (S == "z")) {
+	// -Os = size; -Oz = more size
+	OptOStr = "2"; // FIXME -Os|-Oz => -opt ?
+      } else if ((S == "1") || (S == "2") || (S == "3")) {
+	OptOStr = S;
+      } else {
+	OptOStr = "4";
+      }
+    }
+  }
+  unsigned OptLevel = std::stoi(OptOStr.str());
+
+  if (Args.hasArg(options::OPT_g_Group)) {
+    // pass -g to lower and upper
+    CommonCmdArgs.push_back("-debug");
+  }
+
+  /* Pick the last among conflicting flags, if a positive and negative flag
+     exists for ex. "-ffast-math -fno-fast-math" they get nullified. Also any
+     previously overwritten flag remains that way.
+     For ex. "-Kieee -ffast-math -fno-fast-math". -Kieee gets overwritten by
+     -ffast-math which then gets negated by -fno-fast-math, finally behaving as
+     if none of those flags were passed.
+  */
+  for(Arg *A: Args.filtered(options::OPT_ffast_math, options::OPT_fno_fast_math,
+                        options::OPT_Ofast, options::OPT_Kieee_off,
+                        options::OPT_Kieee_on, options::OPT_frelaxed_math)) {
+    if (A->getOption().matches(options::OPT_ffast_math) ||
+        A->getOption().matches(options::OPT_Ofast)) {
+      NeedIEEE = NeedRelaxedMath = false;
+      NeedFastMath = true;
+    } else if (A->getOption().matches(options::OPT_Kieee_on)) {
+      NeedFastMath = NeedRelaxedMath = false;
+      NeedIEEE = true;
+    } else if (A->getOption().matches(options::OPT_frelaxed_math)) {
+      NeedFastMath = NeedIEEE = false;
+      NeedRelaxedMath = true;
+    } else if (A->getOption().matches(options::OPT_fno_fast_math)) {
+      NeedFastMath = false;
+    } else if (A->getOption().matches(options::OPT_Kieee_off)) {
+      NeedIEEE = false;
+    }
+    A->claim();
+  }
+
+  if (NeedFastMath) {
+    // Lower: -x 216 1
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("216");
+    LowerCmdArgs.push_back("1");
+    // Lower: -ieee 0
+    CommonCmdArgs.push_back("-ieee");
+    CommonCmdArgs.push_back("0");
+  } else if (NeedIEEE) {
+    // Common: -y 129 2
+    CommonCmdArgs.push_back("-y");
+    CommonCmdArgs.push_back("129");
+    CommonCmdArgs.push_back("2");
+    // Lower: -x 6 0x100
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("6");
+    LowerCmdArgs.push_back("0x100");
+    // Lower: -x 42 0x400000
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("42");
+    LowerCmdArgs.push_back("0x400000");
+    // Lower: -y 129 4
+    LowerCmdArgs.push_back("-y");
+    LowerCmdArgs.push_back("129");
+    LowerCmdArgs.push_back("4");
+    // Lower: -x 129 0x400
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("129");
+    LowerCmdArgs.push_back("0x400");
+    // Lower: -y 216 1 (OPT_fno_fast_math)
+    LowerCmdArgs.push_back("-y");
+    LowerCmdArgs.push_back("216");
+    LowerCmdArgs.push_back("1");
+    // Lower: -ieee 1
+    CommonCmdArgs.push_back("-ieee");
+    CommonCmdArgs.push_back("1");
+  } else if (NeedRelaxedMath) {
+    // Lower: -x 15 0x400
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back("15");
+    LowerCmdArgs.push_back("0x400");
+    // Lower: -y 216 1 (OPT_fno_fast_math)
+    LowerCmdArgs.push_back("-y");
+    LowerCmdArgs.push_back("216");
+    LowerCmdArgs.push_back("1");
+    // Lower: -ieee 0
+    CommonCmdArgs.push_back("-ieee");
+    CommonCmdArgs.push_back("0");
+  } else {
+    // Lower: -ieee 0
+    CommonCmdArgs.push_back("-ieee");
+    CommonCmdArgs.push_back("0");
+  }
+
+  /***** Upper part of the Fortran frontend *****/
+
+  // TODO do we need to invoke this under GDB sometimes?
+  const char *UpperExec = Args.MakeArgString(getToolChain().GetProgramPath("flang1"));
+
+  UpperCmdArgs.push_back("-opt"); UpperCmdArgs.push_back(Args.MakeArgString(OptOStr));
+  UpperCmdArgs.push_back("-terse"); UpperCmdArgs.push_back("1");
+  UpperCmdArgs.push_back("-inform"); UpperCmdArgs.push_back("warn");
+  UpperCmdArgs.push_back("-nohpf");
+  UpperCmdArgs.push_back("-nostatic");
+  UpperCmdArgs.append(CommonCmdArgs.begin(), CommonCmdArgs.end()); // Append common arguments
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("19"); UpperCmdArgs.push_back("0x400000");
+  UpperCmdArgs.push_back("-quad");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("68"); UpperCmdArgs.push_back("0x1");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("59"); UpperCmdArgs.push_back("4");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("15"); UpperCmdArgs.push_back("2");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("49"); UpperCmdArgs.push_back("0x400004");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("51"); UpperCmdArgs.push_back("0x20");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("57"); UpperCmdArgs.push_back("0x4c");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("58"); UpperCmdArgs.push_back("0x10000");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("124"); UpperCmdArgs.push_back("0x1000");
+  UpperCmdArgs.push_back("-tp"); UpperCmdArgs.push_back("px");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("57"); UpperCmdArgs.push_back("0xfb0000");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("58"); UpperCmdArgs.push_back("0x78031040");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("47"); UpperCmdArgs.push_back("0x08");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("48"); UpperCmdArgs.push_back("4608");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("49"); UpperCmdArgs.push_back("0x100");
+  if (OptLevel >= 2) {
+    UpperCmdArgs.push_back("-x");
+    UpperCmdArgs.push_back("70");
+    UpperCmdArgs.push_back("0x6c00");
+    UpperCmdArgs.push_back("-x");
+    UpperCmdArgs.push_back("119");
+    UpperCmdArgs.push_back("0x10000000");
+    UpperCmdArgs.push_back("-x");
+    UpperCmdArgs.push_back("129");
+    UpperCmdArgs.push_back("2");
+    UpperCmdArgs.push_back("-x");
+    UpperCmdArgs.push_back("47");
+    UpperCmdArgs.push_back("0x400000");
+    UpperCmdArgs.push_back("-x");
+    UpperCmdArgs.push_back("52");
+    UpperCmdArgs.push_back("2");
+  }
+
+  // Add system include arguments.
+  getToolChain().AddFlangSystemIncludeArgs(Args, UpperCmdArgs);
+
+  // Use clang's predefined macros
+  DiagnosticsEngine DE(new DiagnosticIDs(), new DiagnosticOptions, new IgnoringDiagConsumer());
+  std::shared_ptr<clang::TargetOptions> TO = std::make_shared<clang::TargetOptions>();
+  TO->Triple = getToolChain().getEffectiveTriple().getTriple();
+  std::shared_ptr<TargetInfo> TI(clang::TargetInfo::CreateTargetInfo(DE, TO));
+  std::string PredefineBuffer;
+  llvm::raw_string_ostream Predefines(PredefineBuffer);
+  FlangMacroBuilder Builder(UpperCmdArgs, Args, Predefines);
+
+  LangOptions LO;
+  VersionTuple VT = getToolChain().computeMSVCVersion(&getToolChain().getDriver(), Args);
+  if (!VT.empty()) {
+    // Set the MSCompatibility version. Subminor version has 5 decimal digits.
+    // Minor and major versions have 2 decimal digits each.
+    LO.MSCompatibilityVersion = VT.getMajor() * 10000000 +
+                                VT.getMinor().getValueOr(0) * 100000 +
+                                VT.getSubminor().getValueOr(0);
+  }
+
+  // Define Target specific macros like __linux__
+  TI->getTargetDefines(LO, Builder);
+
+  Builder.defineMacro("__SIZE_TYPE__", TargetInfo::getTypeName(TI->getSizeType()));
+  Builder.defineMacro("__PTRDIFF_TYPE__", TargetInfo::getTypeName(TI->getPtrDiffType(0)));
+
+  if (TI->getPointerWidth(0) == 64 && TI->getLongWidth() == 64
+      && TI->getIntWidth() == 32) {
+    Builder.defineMacro("_LP64");
+    Builder.defineMacro("__LP64__");
+  }
+
+  if (TI->getPointerWidth(0) == 32 && TI->getLongWidth() == 32
+      && TI->getIntWidth() == 32) {
+    Builder.defineMacro("_ILP32");
+    Builder.defineMacro("__ILP32__");
+  }
+
+  DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, *TI, Builder);
+
+  // Add additional predefined macros
+  switch (getToolChain().getEffectiveTriple().getArch()) {
+  case llvm::Triple::aarch64:
+    UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__ARM_ARCH__=8");
+    break;
+  case llvm::Triple::x86_64:
+    UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__amd_64__amd64__");
+    UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__k8");
+    UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__k8__");
+    break;
+  default: /* generic 64-bit */
+    ;
+  }
+  UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__THROW=");
+  UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__extension__=");
+  UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__PGLLVM__");
+
+  // Enable preprocessor
+  if (Args.hasArg(options::OPT_Mpreprocess) ||
+      Args.hasArg(options::OPT_cpp) ||
+      Args.hasArg(options::OPT_E) ||
+      types::getPreprocessedType(InputType) != types::TY_INVALID) {
+    UpperCmdArgs.push_back("-preprocess");
+    for (auto Arg : Args.filtered(options::OPT_Mpreprocess, options::OPT_cpp, options::OPT_E)) {
+      Arg->claim();
+    }
+
+    // When -E option is provided, run only the fortran preprocessor.
+    // Only in -E mode, consume -P if it exists
+    if (Args.hasArg(options::OPT_E)) {
+      UpperCmdArgs.push_back("-es");
+      // Line marker mode is disabled
+      if (Args.hasArg(options::OPT_P)) {
+        Args.ClaimAllArgs(options::OPT_P);
+      } else {
+        // -pp enables line marker mode in fortran preprocessor
+        UpperCmdArgs.push_back("-pp");
+      }
+    }
+  }
+
+  // Enable standards checking
+  if (Args.hasArg(options::OPT_Mstandard)) {
+    UpperCmdArgs.push_back("-standard");
+    for (auto Arg : Args.filtered(options::OPT_Mstandard)) {
+      Arg->claim();
+    }
+  }
+
+  // Free or fixed form file
+  if (Args.hasArg(options::OPT_fortran_format_Group)) {
+    // Override file name suffix, scan arguments for that
+    for (Arg *A : Args.filtered(options::OPT_fortran_format_Group)) {
+      A->claim();
+      switch (A->getOption().getID()) {
+        default:
+          llvm_unreachable("missed a case");
+         case options::OPT_fixed_form_on:
+         case options::OPT_free_form_off:
+         case options::OPT_Mfixed:
+         case options::OPT_Mfree_off:
+         case options::OPT_Mfreeform_off:
+           UpperCmdArgs.push_back("-nofreeform");
+           break;
+         case options::OPT_free_form_on:
+         case options::OPT_fixed_form_off:
+         case options::OPT_Mfree_on:
+         case options::OPT_Mfreeform_on:
+           UpperCmdArgs.push_back("-freeform");
+           break;
+      }
+    }
+  } else {
+    // Deduce format from file name suffix
+    if (types::isFreeFormFortran(InputType)) {
+      UpperCmdArgs.push_back("-freeform");
+    } else {
+      UpperCmdArgs.push_back("-nofreeform");
+    }
+  }
+
+  // Extend lines to 132 characters
+  for (auto Arg : Args.filtered(options::OPT_Mextend)) {
+    Arg->claim();
+    UpperCmdArgs.push_back("-extend");
+  }
+
+  for (auto Arg : Args.filtered(options::OPT_ffixed_line_length_VALUE)) {
+    StringRef Value = Arg->getValue();
+    if (Value == "72") {
+      Arg->claim();
+    } else if (Value == "132") {
+      Arg->claim();
+      UpperCmdArgs.push_back("-extend");
+    } else {
+      getToolChain().getDriver().Diag(diag::err_drv_unsupported_fixed_line_length)
+        << Arg->getAsString(Args);
+    }
+  }
+
+  // Add user-defined include directories
+  for (auto Arg : Args.filtered(options::OPT_I)) {
+    Arg->claim();
+    UpperCmdArgs.push_back("-idir");
+    UpperCmdArgs.push_back(Arg->getValue(0));
+  }
+
+  // Add user-defined module directories
+  for (auto Arg : Args.filtered(options::OPT_ModuleDir, options::OPT_J)) {
+    Arg->claim();
+    UpperCmdArgs.push_back("-moddir");
+    UpperCmdArgs.push_back(Arg->getValue(0));
+  }
+
+  // "Define" preprocessor flags
+  for (auto Arg : Args.filtered(options::OPT_D)) {
+    Arg->claim();
+    UpperCmdArgs.push_back("-def");
+    UpperCmdArgs.push_back(Arg->getValue(0));
+  }
+
+  // "Define" preprocessor flags
+  for (auto Arg : Args.filtered(options::OPT_U)) {
+    Arg->claim();
+    UpperCmdArgs.push_back("-undef");
+    UpperCmdArgs.push_back(Arg->getValue(0));
+  }
+
+  UpperCmdArgs.push_back("-vect"); UpperCmdArgs.push_back("48");
+
+  // Semantics for assignments to allocatables
+  if (Arg *A = Args.getLastArg(options::OPT_Mallocatable_EQ)) {
+    // Argument is passed explicitly
+    StringRef Value = A->getValue();
+    if (Value == "03") { // Enable Fortran 2003 semantics
+      UpperCmdArgs.push_back("-x"); // Set XBIT
+    } else if (Value == "95") { // Enable Fortran 2003 semantics
+      UpperCmdArgs.push_back("-y"); // Unset XBIT
+    } else {
+      getToolChain().getDriver().Diag(diag::err_drv_invalid_allocatable_mode)
+        << A->getAsString(Args);
+    }
+  } else { // No argument passed
+    UpperCmdArgs.push_back("-x"); // Default is 03
+  }
+  UpperCmdArgs.push_back("54"); UpperCmdArgs.push_back("1"); // XBIT value
+
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("70"); UpperCmdArgs.push_back("0x40000000");
+  UpperCmdArgs.push_back("-y"); UpperCmdArgs.push_back("163"); UpperCmdArgs.push_back("0xc0000000");
+  UpperCmdArgs.push_back("-x"); UpperCmdArgs.push_back("189"); UpperCmdArgs.push_back("0x10");
+
+  // Enable NULL pointer checking
+  if (Args.hasArg(options::OPT_Mchkptr)) {
+    UpperCmdArgs.push_back("-x");
+    UpperCmdArgs.push_back("70");
+    UpperCmdArgs.push_back("4");
+    for (auto Arg : Args.filtered(options::OPT_Mchkptr)) {
+      Arg->claim();
+    }
+  }
+
+  // Set a -x flag for first part of Fortran frontend
+  for (Arg *A : Args.filtered(options::OPT_Hx_EQ)) {
+    A->claim();
+    StringRef Value = A->getValue();
+    auto XFlag = Value.split(",");
+    UpperCmdArgs.push_back("-x");
+    UpperCmdArgs.push_back(Args.MakeArgString(XFlag.first));
+    UpperCmdArgs.push_back(Args.MakeArgString(XFlag.second));
+  }
+
+  // Set a -y flag for first part of Fortran frontend
+  for (Arg *A : Args.filtered(options::OPT_Hy_EQ)) {
+    A->claim();
+    StringRef Value = A->getValue();
+    auto XFlag = Value.split(",");
+    UpperCmdArgs.push_back("-y");
+    UpperCmdArgs.push_back(Args.MakeArgString(XFlag.first));
+    UpperCmdArgs.push_back(Args.MakeArgString(XFlag.second));
+  }
+
+  // Set a -q (debug) flag for first part of Fortran frontend
+  for (Arg *A : Args.filtered(options::OPT_Hq_EQ)) {
+    A->claim();
+    StringRef Value = A->getValue();
+    auto XFlag = Value.split(",");
+    UpperCmdArgs.push_back("-q");
+    UpperCmdArgs.push_back(Args.MakeArgString(XFlag.first));
+    UpperCmdArgs.push_back(Args.MakeArgString(XFlag.second));
+  }
+
+  // Set a -qq (debug) flag for first part of Fortran frontend
+  for (Arg *A : Args.filtered(options::OPT_Hqq_EQ)) {
+    A->claim();
+    StringRef Value = A->getValue();
+    auto XFlag = Value.split(",");
+    UpperCmdArgs.push_back("-qq");
+    UpperCmdArgs.push_back(Args.MakeArgString(XFlag.first));
+    UpperCmdArgs.push_back(Args.MakeArgString(XFlag.second));
+  }
+
+  const char * STBFile = Args.MakeArgString(Stem + ".stb");
+  C.addTempFile(STBFile);
+  UpperCmdArgs.push_back("-stbfile");
+  UpperCmdArgs.push_back(STBFile);
+
+  const char * ModuleExportFile = Args.MakeArgString(Stem + ".cmod");
+  C.addTempFile(ModuleExportFile);
+  UpperCmdArgs.push_back("-modexport");
+  UpperCmdArgs.push_back(ModuleExportFile);
+
+  const char * ModuleIndexFile = Args.MakeArgString(Stem + ".cmdx");
+  C.addTempFile(ModuleIndexFile);
+  UpperCmdArgs.push_back("-modindex");
+  UpperCmdArgs.push_back(ModuleIndexFile);
+
+  UpperCmdArgs.push_back("-output");
+  UpperCmdArgs.push_back(ILMFile);
+
+  SmallString<256> Path;
+  if(Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() > 0) {
+    SmallString<128> TargetInfo;
+    Path = llvm::sys::path::parent_path(Output.getFilename());
+    Arg* Tgts = Args.getLastArg(options::OPT_fopenmp_targets_EQ);
+    assert(Tgts && Tgts->getNumValues() &&
+           "OpenMP offloading has to have targets specified.");
+    for (unsigned i = 0; i < Tgts->getNumValues(); ++i) {
+      if (i)
+        TargetInfo += ',';
+      llvm::Triple T(Tgts->getValue(i));
+      TargetInfo += T.getTriple();
+    }
+    UpperCmdArgs.push_back("-fopenmp-targets");
+    UpperCmdArgs.push_back(Args.MakeArgString(TargetInfo.str()));
+  }
+
+  C.addCommand(std::make_unique<Command>(JA, *this, UpperExec, UpperCmdArgs, Inputs));
+
+  // For -fsyntax-only or -E that is it
+  if (Args.hasArg(options::OPT_fsyntax_only) ||
+      Args.hasArg(options::OPT_E)) return;
+
+  /***** Lower part of Fortran frontend *****/
+
+  const char *LowerExec = Args.MakeArgString(getToolChain().GetProgramPath("flang2"));
+
+  // TODO FLANG arg handling
+  LowerCmdArgs.push_back("-fn"); LowerCmdArgs.push_back(Input.getBaseInput());
+  LowerCmdArgs.push_back("-opt"); LowerCmdArgs.push_back(Args.MakeArgString(OptOStr));
+  LowerCmdArgs.push_back("-terse"); LowerCmdArgs.push_back("1");
+  LowerCmdArgs.push_back("-inform"); LowerCmdArgs.push_back("warn");
+  LowerCmdArgs.append(CommonCmdArgs.begin(), CommonCmdArgs.end()); // Append common arguments
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("68"); LowerCmdArgs.push_back("0x1");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("51"); LowerCmdArgs.push_back("0x20");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("119"); LowerCmdArgs.push_back("0xa10000");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("122"); LowerCmdArgs.push_back("0x40");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("123"); LowerCmdArgs.push_back("0x1000");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("127"); LowerCmdArgs.push_back("4");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("127"); LowerCmdArgs.push_back("17");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("19"); LowerCmdArgs.push_back("0x400000");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("28"); LowerCmdArgs.push_back("0x40000");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("120"); LowerCmdArgs.push_back("0x10000000");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("70"); LowerCmdArgs.push_back("0x8000");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("122"); LowerCmdArgs.push_back("1");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("125"); LowerCmdArgs.push_back("0x20000");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("164"); LowerCmdArgs.push_back("0x800000");
+  LowerCmdArgs.push_back("-quad");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("59"); LowerCmdArgs.push_back("4");
+  LowerCmdArgs.push_back("-tp"); LowerCmdArgs.push_back("px");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("120"); LowerCmdArgs.push_back("0x1000"); // debug lite
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("124"); LowerCmdArgs.push_back("0x1400");
+  LowerCmdArgs.push_back("-y"); LowerCmdArgs.push_back("15"); LowerCmdArgs.push_back("2");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("57"); LowerCmdArgs.push_back("0x3b0000");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("58"); LowerCmdArgs.push_back("0x48000000");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("49"); LowerCmdArgs.push_back("0x100");
+  LowerCmdArgs.push_back("-astype"); LowerCmdArgs.push_back("0");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("183"); LowerCmdArgs.push_back("4");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("121"); LowerCmdArgs.push_back("0x800");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("54"); LowerCmdArgs.push_back("0x10");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("70"); LowerCmdArgs.push_back("0x40000000");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("249"); LowerCmdArgs.push_back("90"); // LLVM version
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("124"); LowerCmdArgs.push_back("1");
+  LowerCmdArgs.push_back("-y"); LowerCmdArgs.push_back("163"); LowerCmdArgs.push_back("0xc0000000");
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("189"); LowerCmdArgs.push_back("0x10");
+  LowerCmdArgs.push_back("-y"); LowerCmdArgs.push_back("189"); LowerCmdArgs.push_back("0x4000000");
+
+  // Remove "noinline" attriblute
+  LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("183"); LowerCmdArgs.push_back("0x10");
+
+  // Set a -x flag for second part of Fortran frontend
+  for (Arg *A : Args.filtered(options::OPT_Mx_EQ)) {
+    A->claim();
+    StringRef Value = A->getValue();
+    auto XFlag = Value.split(",");
+    LowerCmdArgs.push_back("-x");
+    LowerCmdArgs.push_back(Args.MakeArgString(XFlag.first));
+    LowerCmdArgs.push_back(Args.MakeArgString(XFlag.second));
+  }
+
+  // Set a -y flag for second part of Fortran frontend
+  for (Arg *A : Args.filtered(options::OPT_My_EQ)) {
+    A->claim();
+    StringRef Value = A->getValue();
+    auto XFlag = Value.split(",");
+    LowerCmdArgs.push_back("-y");
+    LowerCmdArgs.push_back(Args.MakeArgString(XFlag.first));
+    LowerCmdArgs.push_back(Args.MakeArgString(XFlag.second));
+  }
+
+  // Set a -q (debug) flag for second part of Fortran frontend
+  for (Arg *A : Args.filtered(options::OPT_Mq_EQ)) {
+    A->claim();
+    StringRef Value = A->getValue();
+    auto XFlag = Value.split(",");
+    LowerCmdArgs.push_back("-q");
+    LowerCmdArgs.push_back(Args.MakeArgString(XFlag.first));
+    LowerCmdArgs.push_back(Args.MakeArgString(XFlag.second));
+  }
+
+  // Set a -qq (debug) flag for second part of Fortran frontend
+  for (Arg *A : Args.filtered(options::OPT_Mqq_EQ)) {
+    A->claim();
+    StringRef Value = A->getValue();
+    auto XFlag = Value.split(",");
+    LowerCmdArgs.push_back("-qq");
+    LowerCmdArgs.push_back(Args.MakeArgString(XFlag.first));
+    LowerCmdArgs.push_back(Args.MakeArgString(XFlag.second));
+  }
+
+  // Pass an arbitrary flag for second part of Fortran frontend
+  for (Arg *A : Args.filtered(options::OPT_Wm_EQ)) {
+    A->claim();
+    StringRef Value = A->getValue();
+    SmallVector<StringRef, 8> PassArgs;
+    Value.split(PassArgs, StringRef(","));
+    for (StringRef PassArg : PassArgs) {
+      LowerCmdArgs.push_back(Args.MakeArgString(PassArg));
+    }
+  }
+
+  LowerCmdArgs.push_back("-stbfile");
+  LowerCmdArgs.push_back(STBFile);
+
+  Path = llvm::sys::path::parent_path(Output.getFilename());
+  bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
+
+  /* OpenMP GPU Offload */
+  if(Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() > 0) {
+    SmallString<128> TargetInfo;//("-fopenmp-targets ");
+    SmallString<256> TargetInfoAsm;//("-fopenmp-targets-asm ");
+
+    Arg* Tgts = Args.getLastArg(options::OPT_fopenmp_targets_EQ);
+    assert(Tgts && Tgts->getNumValues() &&
+           "OpenMP offloading has to have targets specified.");
+    for (unsigned i = 0; i < Tgts->getNumValues(); ++i) {
+      if (i)
+        TargetInfo += ',';
+      // We need to get the string from the triple because it may be not exactly
+      // the same as the one we get directly from the arguments.
+      llvm::Triple T(Tgts->getValue(i));
+      TargetInfo += T.getTriple();
+      // We also need to give a output file
+      TargetInfoAsm += Path;
+      TargetInfoAsm += "/";
+      TargetInfoAsm += Stem;
+      TargetInfoAsm += "-";
+      TargetInfoAsm += T.getTriple();
+      TargetInfoAsm += ".ll";
+    }
+    // The driver is aware that flang2 can generate multiple files at the same time.
+    // We mimic it here by exchanging the output files.
+    // The driver always uses the output file of -asm.
+    LowerCmdArgs.push_back("-fopenmp-targets");
+    LowerCmdArgs.push_back(Args.MakeArgString(TargetInfo.str()));
+    if(IsOpenMPDevice) {
+      LowerCmdArgs.push_back("-fopenmp-targets-asm");
+      LowerCmdArgs.push_back(Args.MakeArgString(OutFile));
+      LowerCmdArgs.push_back("-asm");
+      LowerCmdArgs.push_back(Args.MakeArgString(TargetInfoAsm.str()));
+    } else {
+      LowerCmdArgs.push_back("-fopenmp-targets-asm");
+      LowerCmdArgs.push_back(Args.MakeArgString(TargetInfoAsm.str()));
+      LowerCmdArgs.push_back("-asm");
+      LowerCmdArgs.push_back(Args.MakeArgString(OutFile));
+    }
+  } else {
+    LowerCmdArgs.push_back("-asm");
+    LowerCmdArgs.push_back(Args.MakeArgString(OutFile));
+  }
+
+  C.addCommand(std::make_unique<Command>(JA, *this, LowerExec, LowerCmdArgs, Inputs));
+}
+

diff  --git a/clang/lib/Driver/ToolChains/Flang1.h b/clang/lib/Driver/ToolChains/Flang1.h
new file mode 100644
index 000000000000..2c3eb7c895a0
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Flang1.h
@@ -0,0 +1,50 @@
+//===--- Flang.h - Flang Tool and ToolChain Implementations ====-*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Flang_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Flang_H
+
+#include "MSVC.h"
+#include "clang/Basic/DebugInfoOptions.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/Types.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace driver {
+
+namespace tools {
+
+/// \brief Flang Fortran frontend
+class LLVM_LIBRARY_VISIBILITY FlangFrontend : public Tool {
+public:
+  FlangFrontend(const ToolChain &TC)
+      : Tool("flang:frontend",
+             "Fortran frontend to LLVM", TC,
+             RF_Full) {}
+
+  bool hasGoodDiagnostics() const override { return true; }
+  bool hasIntegratedAssembler() const override { return false; }
+  bool hasIntegratedCPP() const override { return false; }
+
+  void ConstructJob(Compilation &C, const JobAction &JA,
+                    const InputInfo &Output, const InputInfoList &Inputs,
+                    const llvm::opt::ArgList &TCArgs,
+                    const char *LinkingOutput) const override;
+};
+
+} // end namespace tools
+
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CLANG_H

diff  --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index e8ef881e89ac..61ad241eef70 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -527,6 +527,16 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   // The profile runtime also needs access to system libraries.
   getToolChain().addProfileRTLibs(Args, CmdArgs);
 
+  // Add Fortran runtime libraries
+  if (needFortranLibs(D, Args)) {
+    ToolChain.AddFortranStdlibLibArgs(Args, CmdArgs);
+  } else {
+  // Claim "no Flang libraries" arguments if any
+    for (auto Arg : Args.filtered(options::OPT_noFlangLibs)) {
+      Arg->claim();
+    }
+  }
+
   if (D.CCCIsCXX() &&
       !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
     if (ToolChain.ShouldLinkCXXStdlib(Args)) {

diff  --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 6532c899492a..97067947686a 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -647,6 +647,194 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
   return "/" + LibDir + "/" + Loader;
 }
 
+/// Convert path list to Fortran frontend argument
+static void AddFlangSysIncludeArg(const ArgList &DriverArgs,
+                                  ArgStringList &Flang1Args,
+                                  ToolChain::path_list IncludePathList) {
+  std::string ArgValue; // Path argument value
+
+  // Make up argument value consisting of paths separated by colons
+  bool first = true;
+  for (auto P : IncludePathList) {
+    if (first) {
+      first = false;
+    } else {
+      ArgValue += ":";
+    }
+    ArgValue += P;
+  }
+
+  // Add the argument
+  Flang1Args.push_back("-stdinc");
+  Flang1Args.push_back(DriverArgs.MakeArgString(ArgValue));
+}
+
+void Linux::AddFlangSystemIncludeArgs(const ArgList &DriverArgs,
+                                      ArgStringList &Flang1Args) const {
+  path_list IncludePathList;
+  const Driver &D = getDriver();
+  std::string SysRoot = computeSysRoot();
+
+  if (DriverArgs.hasArg(options::OPT_nostdinc))
+    return;
+
+  {
+    SmallString<128> P(D.InstalledDir);
+    llvm::sys::path::append(P, "../include");
+    IncludePathList.push_back(P.str());
+  }
+
+  if (!DriverArgs.hasArg(options::OPT_nostdlibinc))
+    IncludePathList.push_back(SysRoot + "/usr/local/include");
+
+  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+    SmallString<128> P(D.ResourceDir);
+    llvm::sys::path::append(P, "include");
+    IncludePathList.push_back(P.str());
+  }
+
+  if (DriverArgs.hasArg(options::OPT_nostdlibinc)) {
+    AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList);
+    return;
+  }
+
+  // Check for configure-time C include directories.
+  StringRef CIncludeDirs(C_INCLUDE_DIRS);
+  if (CIncludeDirs != "") {
+    SmallVector<StringRef, 5> dirs;
+    CIncludeDirs.split(dirs, ":");
+    for (StringRef dir : dirs) {
+      StringRef Prefix =
+          llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : "";
+      IncludePathList.push_back(Prefix.str() + dir.str());
+    }
+    AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList);
+    return;
+  }
+
+  // Lacking those, try to detect the correct set of system includes for the
+  // target triple.
+
+  // Add include directories specific to the selected multilib set and multilib.
+  if (GCCInstallation.isValid()) {
+    const auto &Callback = Multilibs.includeDirsCallback();
+    if (Callback) {
+      for (const auto &Path : Callback(GCCInstallation.getMultilib()))
+        addExternCSystemIncludeIfExists(
+            DriverArgs, Flang1Args, GCCInstallation.getInstallPath() + Path);
+    }
+  }
+
+  // Implement generic Debian multiarch support.
+  const StringRef X86_64MultiarchIncludeDirs[] = {
+      "/usr/include/x86_64-linux-gnu",
+
+      // FIXME: These are older forms of multiarch. It's not clear that they're
+      // in use in any released version of Debian, so we should consider
+      // removing them.
+      "/usr/include/i686-linux-gnu/64", "/usr/include/i486-linux-gnu/64"};
+  const StringRef X86MultiarchIncludeDirs[] = {
+      "/usr/include/i386-linux-gnu",
+
+      // FIXME: These are older forms of multiarch. It's not clear that they're
+      // in use in any released version of Debian, so we should consider
+      // removing them.
+      "/usr/include/x86_64-linux-gnu/32", "/usr/include/i686-linux-gnu",
+      "/usr/include/i486-linux-gnu"};
+  const StringRef AArch64MultiarchIncludeDirs[] = {
+      "/usr/include/aarch64-linux-gnu"};
+  const StringRef ARMMultiarchIncludeDirs[] = {
+      "/usr/include/arm-linux-gnueabi"};
+  const StringRef ARMHFMultiarchIncludeDirs[] = {
+      "/usr/include/arm-linux-gnueabihf"};
+  const StringRef MIPSMultiarchIncludeDirs[] = {"/usr/include/mips-linux-gnu"};
+  const StringRef MIPSELMultiarchIncludeDirs[] = {
+      "/usr/include/mipsel-linux-gnu"};
+  const StringRef MIPS64MultiarchIncludeDirs[] = {
+      "/usr/include/mips64-linux-gnu", "/usr/include/mips64-linux-gnuabi64"};
+  const StringRef MIPS64ELMultiarchIncludeDirs[] = {
+      "/usr/include/mips64el-linux-gnu",
+      "/usr/include/mips64el-linux-gnuabi64"};
+  const StringRef PPCMultiarchIncludeDirs[] = {
+      "/usr/include/powerpc-linux-gnu"};
+  const StringRef PPC64MultiarchIncludeDirs[] = {
+      "/usr/include/powerpc64-linux-gnu"};
+  const StringRef PPC64LEMultiarchIncludeDirs[] = {
+      "/usr/include/powerpc64le-linux-gnu"};
+  const StringRef SparcMultiarchIncludeDirs[] = {
+      "/usr/include/sparc-linux-gnu"};
+  const StringRef Sparc64MultiarchIncludeDirs[] = {
+      "/usr/include/sparc64-linux-gnu"};
+  ArrayRef<StringRef> MultiarchIncludeDirs;
+  switch (getTriple().getArch()) {
+  case llvm::Triple::x86_64:
+    MultiarchIncludeDirs = X86_64MultiarchIncludeDirs;
+    break;
+  case llvm::Triple::x86:
+    MultiarchIncludeDirs = X86MultiarchIncludeDirs;
+    break;
+  case llvm::Triple::aarch64:
+  case llvm::Triple::aarch64_be:
+    MultiarchIncludeDirs = AArch64MultiarchIncludeDirs;
+    break;
+  case llvm::Triple::arm:
+    if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
+      MultiarchIncludeDirs = ARMHFMultiarchIncludeDirs;
+    else
+      MultiarchIncludeDirs = ARMMultiarchIncludeDirs;
+    break;
+  case llvm::Triple::mips:
+    MultiarchIncludeDirs = MIPSMultiarchIncludeDirs;
+    break;
+  case llvm::Triple::mipsel:
+    MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs;
+    break;
+  case llvm::Triple::mips64:
+    MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs;
+    break;
+  case llvm::Triple::mips64el:
+    MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs;
+    break;
+  case llvm::Triple::ppc:
+    MultiarchIncludeDirs = PPCMultiarchIncludeDirs;
+    break;
+  case llvm::Triple::ppc64:
+    MultiarchIncludeDirs = PPC64MultiarchIncludeDirs;
+    break;
+  case llvm::Triple::ppc64le:
+    MultiarchIncludeDirs = PPC64LEMultiarchIncludeDirs;
+    break;
+  case llvm::Triple::sparc:
+    MultiarchIncludeDirs = SparcMultiarchIncludeDirs;
+    break;
+  case llvm::Triple::sparcv9:
+    MultiarchIncludeDirs = Sparc64MultiarchIncludeDirs;
+    break;
+  default:
+    break;
+  }
+  for (StringRef Dir : MultiarchIncludeDirs) {
+    if (llvm::sys::fs::exists(SysRoot + Dir)) {
+      IncludePathList.push_back(SysRoot + Dir.str());
+      break;
+    }
+  }
+
+  if (getTriple().getOS() == llvm::Triple::RTEMS) {
+    AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList);
+    return;
+  }
+
+  // Add an include of '/include' directly. This isn't provided by default by
+  // system GCCs, but is often used with cross-compiling GCCs, and harmless to
+  // add even when Clang is acting as-if it were a system compiler.
+  IncludePathList.push_back(SysRoot + "/include");
+
+  IncludePathList.push_back(SysRoot + "/usr/include");
+
+  AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList);
+}
+
 void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
                                       ArgStringList &CC1Args) const {
   const Driver &D = getDriver();

diff  --git a/clang/lib/Driver/ToolChains/Linux.h b/clang/lib/Driver/ToolChains/Linux.h
index 923ebecbd215..50471c265ffc 100644
--- a/clang/lib/Driver/ToolChains/Linux.h
+++ b/clang/lib/Driver/ToolChains/Linux.h
@@ -23,6 +23,9 @@ class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
 
   bool HasNativeLLVMSupport() const override;
 
+  void
+  AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+                           llvm::opt::ArgStringList &Flang1Args) const override;
   void
   AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                             llvm::opt::ArgStringList &CC1Args) const override;

diff  --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp
old mode 100644
new mode 100755
index 7d83be2521e7..2f2d46cfde66
--- a/clang/lib/Driver/Types.cpp
+++ b/clang/lib/Driver/Types.cpp
@@ -123,6 +123,8 @@ bool types::isAcceptedByClang(ID Id) {
 
   case TY_Asm:
   case TY_C: case TY_PP_C:
+  case TY_F_FreeForm: case TY_PP_F_FreeForm:
+  case TY_F_FixedForm: case TY_PP_F_FixedForm:
   case TY_CL:
   case TY_CUDA: case TY_PP_CUDA:
   case TY_CUDA_DEVICE:
@@ -217,11 +219,33 @@ bool types::isFortran(ID Id) {
   default:
     return false;
 
-  case TY_Fortran: case TY_PP_Fortran:
+#ifdef USE_CLASSIC_FLANG
+  case TY_F_FreeForm:
+  case TY_PP_F_FreeForm:
+  case TY_F_FixedForm:
+  case TY_PP_F_FixedForm:
+#else
+  case TY_Fortran:
+  case TY_PP_Fortran:
+#endif
     return true;
   }
 }
 
+bool types::isFreeFormFortran(ID Id) {
+  if (!isFortran(Id))
+    return false;
+
+  return (Id == TY_F_FreeForm || Id == TY_PP_F_FreeForm);
+}
+
+bool types::isFixedFormFortran(ID Id) {
+  if (!isFortran(Id))
+    return false;
+
+  return (Id == TY_F_FixedForm || Id == TY_PP_F_FixedForm);
+}
+
 bool types::isSrcFile(ID Id) {
   return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID;
 }
@@ -230,8 +254,8 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
   return llvm::StringSwitch<types::ID>(Ext)
            .Case("c", TY_C)
            .Case("C", TY_CXX)
-           .Case("F", TY_Fortran)
-           .Case("f", TY_PP_Fortran)
+           .Case("F", TY_F_FixedForm)
+           .Case("f", TY_PP_F_FixedForm)
            .Case("h", TY_CHeader)
            .Case("H", TY_CXXHeader)
            .Case("i", TY_PP_C)
@@ -264,6 +288,20 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
            .Case("cui", TY_PP_CUDA)
            .Case("cxx", TY_CXX)
            .Case("CXX", TY_CXX)
+#ifdef USE_CLASSIC_FLANG
+           .Case("for", TY_PP_F_FixedForm)
+           .Case("FOR", TY_PP_F_FixedForm)
+           .Case("fpp", TY_F_FixedForm)
+           .Case("FPP", TY_F_FixedForm)
+           .Case("f90", TY_PP_F_FreeForm)
+           .Case("f95", TY_PP_F_FreeForm)
+           .Case("f03", TY_PP_F_FreeForm)
+           .Case("f08", TY_PP_F_FreeForm)
+           .Case("F90", TY_F_FreeForm)
+           .Case("F95", TY_F_FreeForm)
+           .Case("F03", TY_F_FreeForm)
+           .Case("F08", TY_F_FreeForm)
+#else
            .Case("F90", TY_Fortran)
            .Case("f90", TY_PP_Fortran)
            .Case("F95", TY_Fortran)
@@ -272,6 +310,7 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
            .Case("FOR", TY_PP_Fortran)
            .Case("fpp", TY_Fortran)
            .Case("FPP", TY_Fortran)
+#endif
            .Case("gch", TY_PCH)
            .Case("hip", TY_HIP)
            .Case("hpp", TY_CXXHeader)

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index e98a407ac42f..d30d8aa7fc91 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -720,6 +720,10 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
       Opts.setVecLib(CodeGenOptions::MASSV);
     else if (Name == "SVML")
       Opts.setVecLib(CodeGenOptions::SVML);
+#ifdef FLANG_LLVM_EXTENSIONS
+    else if (Name == "PGMATH")
+      Opts.setVecLib(CodeGenOptions::PGMATH);
+#endif
     else if (Name == "none")
       Opts.setVecLib(CodeGenOptions::NoLibrary);
     else

diff  --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index c273cb96d9b9..7ab33d5847e9 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -159,26 +159,6 @@ static void DefineFloatMacros(MacroBuilder &Builder, StringRef Prefix,
   Builder.defineMacro(DefPrefix + "MIN__", Twine(Min)+Ext);
 }
 
-
-/// DefineTypeSize - Emit a macro to the predefines buffer that declares a macro
-/// named MacroName with the max value for a type with width 'TypeWidth' a
-/// signedness of 'isSigned' and with a value suffix of 'ValSuffix' (e.g. LL).
-static void DefineTypeSize(const Twine &MacroName, unsigned TypeWidth,
-                           StringRef ValSuffix, bool isSigned,
-                           MacroBuilder &Builder) {
-  llvm::APInt MaxVal = isSigned ? llvm::APInt::getSignedMaxValue(TypeWidth)
-                                : llvm::APInt::getMaxValue(TypeWidth);
-  Builder.defineMacro(MacroName, MaxVal.toString(10, isSigned) + ValSuffix);
-}
-
-/// DefineTypeSize - An overloaded helper that uses TargetInfo to determine
-/// the width, suffix, and signedness of the given type
-static void DefineTypeSize(const Twine &MacroName, TargetInfo::IntType Ty,
-                           const TargetInfo &TI, MacroBuilder &Builder) {
-  DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty),
-                 TI.isTypeSigned(Ty), Builder);
-}
-
 static void DefineFmt(const Twine &Prefix, TargetInfo::IntType Ty,
                       const TargetInfo &TI, MacroBuilder &Builder) {
   bool IsSigned = TI.isTypeSigned(Ty);

diff  --git a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
index a75d2a630cf4..86cea5a5b96f 100644
--- a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
+++ b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
@@ -646,6 +646,8 @@ CreateFileHandler(MemoryBuffer &FirstInput) {
     return std::make_unique<TextFileHandler>(/*Comment=*/"#");
   if (FilesType == "ll")
     return std::make_unique<TextFileHandler>(/*Comment=*/";");
+  if (FilesType == "f95")
+    return std::make_unique<TextFileHandler>(/*Comment=*/"!");
   if (FilesType == "bc")
     return std::make_unique<BinaryFileHandler>();
   if (FilesType == "s")

diff  --git a/clang/tools/driver/CMakeLists.txt b/clang/tools/driver/CMakeLists.txt
index 2b783cff0955..b0d6172f845d 100644
--- a/clang/tools/driver/CMakeLists.txt
+++ b/clang/tools/driver/CMakeLists.txt
@@ -63,7 +63,7 @@ endif()
 add_dependencies(clang clang-resource-headers)
 
 if(NOT CLANG_LINKS_TO_CREATE)
-  set(CLANG_LINKS_TO_CREATE clang++ clang-cl clang-cpp)
+  set(CLANG_LINKS_TO_CREATE clang++ clang-cl clang-cpp flang)
 endif()
 
 foreach(link ${CLANG_LINKS_TO_CREATE})


        


More information about the llvm-branch-commits mailing list