From eba0382068cd0e2d7d9c6917fbb23b31c6f6951d Mon Sep 17 00:00:00 2001 From: luofeng14 Date: Fri, 19 Apr 2024 16:07:18 +0800 Subject: [PATCH] Fix declaration definition mismatch for classic flang --- 0011-Add-the-support-for-classic-flang.patch | 4031 +++++++++++++++++ ...efinition-mismatch-for-classic-flang.patch | 326 ++ clang.spec | 14 +- 3 files changed, 4370 insertions(+), 1 deletion(-) create mode 100644 0011-Add-the-support-for-classic-flang.patch create mode 100644 0012-Fix-declaration-definition-mismatch-for-classic-flang.patch diff --git a/0011-Add-the-support-for-classic-flang.patch b/0011-Add-the-support-for-classic-flang.patch new file mode 100644 index 0000000..ec80f31 --- /dev/null +++ b/0011-Add-the-support-for-classic-flang.patch @@ -0,0 +1,4031 @@ +From 3d36d3891f2a654d5ec2a0ce3c2ff47b597d1c42 Mon Sep 17 00:00:00 2001 +From: luofeng14 +Date: Mon, 11 Mar 2024 21:25:03 +0800 +Subject: [PATCH] sync classic flang patch + +--- + clang/CMakeLists.txt | 5 + + clang/include/clang/Basic/CodeGenOptions.h | 3 + + .../clang/Basic/DiagnosticDriverKinds.td | 6 + + clang/include/clang/Basic/MacroBuilder.h | 3 +- + clang/include/clang/Basic/Sanitizers.def | 2 + + clang/include/clang/Driver/CMakeLists.txt | 13 +- + clang/include/clang/Driver/Options.td | 197 ++- + clang/include/clang/Driver/ToolChain.h | 17 + + clang/include/clang/Driver/Types.def | 7 + + clang/include/clang/Driver/Types.h | 8 + + clang/include/clang/Frontend/Utils.h | 32 + + clang/lib/CodeGen/BackendUtil.cpp | 6 + + clang/lib/CodeGen/CGDebugInfo.cpp | 10 +- + clang/lib/Driver/CMakeLists.txt | 8 +- + clang/lib/Driver/Driver.cpp | 60 +- + clang/lib/Driver/OffloadBundler.cpp | 4 + + clang/lib/Driver/ToolChain.cpp | 36 +- + clang/lib/Driver/ToolChains/Clang.cpp | 60 + + clang/lib/Driver/ToolChains/ClassicFlang.cpp | 1217 +++++++++++++++++ + clang/lib/Driver/ToolChains/ClassicFlang.h | 49 + + clang/lib/Driver/ToolChains/CommonArgs.cpp | 69 +- + clang/lib/Driver/ToolChains/CommonArgs.h | 20 + + clang/lib/Driver/ToolChains/Cuda.cpp | 35 + + clang/lib/Driver/ToolChains/Cuda.h | 5 + + clang/lib/Driver/ToolChains/Darwin.cpp | 4 + + clang/lib/Driver/ToolChains/Gnu.cpp | 4 + + clang/lib/Driver/ToolChains/Linux.cpp | 190 +++ + clang/lib/Driver/ToolChains/Linux.h | 5 + + clang/lib/Driver/ToolChains/MSVC.cpp | 115 ++ + clang/lib/Driver/ToolChains/MSVC.h | 11 + + clang/lib/Driver/ToolChains/MinGW.cpp | 4 + + clang/lib/Driver/Types.cpp | 50 + + clang/lib/Frontend/InitPreprocessor.cpp | 20 - + clang/test/CMakeLists.txt | 1 + + .../test/CodeGen/libpgmath-logfun-aarch64.ll | 58 + + clang/test/CodeGen/libpgmath-logfun-x86_64.ll | 57 + + clang/test/Driver/autocomplete.c | 2 +- + clang/test/Driver/emit-flang-attrs.f90 | 58 + + .../test/Driver/flang/Inputs/llvm-ir-input.ll | 0 + .../flang/classic-flang-emit-flang-llvm.f95 | 10 + + .../flang/classic-flang-fp-contract.f95 | 27 + + .../flang/classic-flang-must-preprocess.F | 12 + + .../flang/classic-flang-must-preprocess.F95 | 12 + + .../test/Driver/flang/classic-flang-version.f | 3 + + .../flang/classic-flang-vscale-mbits.f95 | 28 + + .../Driver/flang/classic-flang-vscale.f95 | 28 + + clang/test/Driver/flang/classic-flang.f | 26 + + clang/test/Driver/flang/classic-flang.f95 | 120 ++ + clang/test/Driver/flang/flang.f90 | 2 + + clang/test/Driver/flang/flang_ucase.F90 | 2 + + clang/test/Driver/flang/llvm-ir-input.f | 7 + + .../Driver/flang/multiple-inputs-mixed.f90 | 2 + + clang/test/Driver/flang/multiple-inputs.f90 | 2 + + clang/test/Driver/flang/reassoc.f90 | 59 + + clang/test/Driver/fortran-phases.f90 | 119 ++ + clang/test/Driver/fortran-preprocessor.f90 | 48 + + clang/test/Driver/fortran.f95 | 2 + + clang/test/Driver/gfortran.f90 | 1 + + clang/test/Driver/lit.local.cfg | 3 + + clang/test/lit.cfg.py | 3 + + clang/test/lit.site.cfg.py.in | 1 + + clang/tools/driver/CMakeLists.txt | 2 +- + 62 files changed, 2933 insertions(+), 37 deletions(-) + create mode 100644 clang/lib/Driver/ToolChains/ClassicFlang.cpp + create mode 100644 clang/lib/Driver/ToolChains/ClassicFlang.h + mode change 100644 => 100755 clang/lib/Driver/Types.cpp + create mode 100644 clang/test/CodeGen/libpgmath-logfun-aarch64.ll + create mode 100644 clang/test/CodeGen/libpgmath-logfun-x86_64.ll + create mode 100644 clang/test/Driver/emit-flang-attrs.f90 + create mode 100644 clang/test/Driver/flang/Inputs/llvm-ir-input.ll + create mode 100644 clang/test/Driver/flang/classic-flang-emit-flang-llvm.f95 + create mode 100644 clang/test/Driver/flang/classic-flang-fp-contract.f95 + create mode 100644 clang/test/Driver/flang/classic-flang-must-preprocess.F + create mode 100644 clang/test/Driver/flang/classic-flang-must-preprocess.F95 + create mode 100644 clang/test/Driver/flang/classic-flang-version.f + create mode 100644 clang/test/Driver/flang/classic-flang-vscale-mbits.f95 + create mode 100644 clang/test/Driver/flang/classic-flang-vscale.f95 + create mode 100644 clang/test/Driver/flang/classic-flang.f + create mode 100644 clang/test/Driver/flang/classic-flang.f95 + create mode 100644 clang/test/Driver/flang/llvm-ir-input.f + create mode 100644 clang/test/Driver/flang/reassoc.f90 + create mode 100644 clang/test/Driver/fortran-phases.f90 + create mode 100644 clang/test/Driver/fortran-preprocessor.f90 + +diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt +index d558b0522e82..949f12d3ce8c 100644 +--- a/clang/CMakeLists.txt ++++ b/clang/CMakeLists.txt +@@ -392,6 +392,11 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + endif() + endif() + ++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( -DENABLE_CLASSIC_FLANG ) ++endif() ++ + option(CLANG_BUILD_TOOLS + "Build the Clang tools. If OFF, just generate build targets." ON) + +diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h +index 14fc94fe27f9..41577b97e030 100644 +--- a/clang/include/clang/Basic/CodeGenOptions.h ++++ b/clang/include/clang/Basic/CodeGenOptions.h +@@ -59,6 +59,9 @@ public: + Accelerate, // Use the Accelerate framework. + LIBMVEC, // GLIBC vector math library. + MASSV, // IBM MASS vector library. ++#ifdef ENABLE_CLASSIC_FLANG ++ PGMATH, // PGI math library. ++#endif + SVML, // Intel short vector math library. + SLEEF, // SLEEF SIMD Library for Evaluating Elementary Functions. + Darwin_libsystem_m, // Use Darwin's libsytem_m vector functions. +diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td +index 1b69324d073a..09a1949d7596 100644 +--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td ++++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td +@@ -131,6 +131,10 @@ def err_drv_invalid_linker_name : Error< + "invalid linker name 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< +@@ -354,6 +358,8 @@ def err_drv_negative_columns : Error< + "invalid value '%1' in '%0', value must be 'none' or a positive integer">; + def err_drv_small_columns : Error< + "invalid value '%1' in '%0', value must be '%2' or greater">; ++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..bfc5e38c15e3 100644 +--- a/clang/include/clang/Basic/MacroBuilder.h ++++ b/clang/include/clang/Basic/MacroBuilder.h +@@ -24,9 +24,10 @@ class MacroBuilder { + raw_ostream &Out; + public: + MacroBuilder(raw_ostream &Output) : Out(Output) {} ++ virtual ~MacroBuilder() {} + + /// 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 c2137e3f61f6..4f0a2bf332ef 100644 +--- a/clang/include/clang/Basic/Sanitizers.def ++++ b/clang/include/clang/Basic/Sanitizers.def +@@ -107,6 +107,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/CMakeLists.txt b/clang/include/clang/Driver/CMakeLists.txt +index ea55ba0f1f27..8c0af1528a96 100644 +--- a/clang/include/clang/Driver/CMakeLists.txt ++++ b/clang/include/clang/Driver/CMakeLists.txt +@@ -1,7 +1,14 @@ + set(LLVM_TARGET_DEFINITIONS Options.td) ++ ++set(CLANG_DRIVER_OPTIONS) + if (BUILD_FOR_OPENEULER) +-tablegen(LLVM Options.inc -gen-opt-parser-defs -DBUILD_FOR_OPENEULER) +-else() +-tablegen(LLVM Options.inc -gen-opt-parser-defs) ++ list(APPEND CLANG_DRIVER_OPTIONS -DBUILD_FOR_OPENEULER ) + endif() ++ ++if (LLVM_ENABLE_CLASSIC_FLANG) ++ list(APPEND CLANG_DRIVER_OPTIONS -DENABLE_CLASSIC_FLANG ) ++endif() ++ ++tablegen(LLVM Options.inc ${CLANG_DRIVER_OPTIONS} -gen-opt-parser-defs ) ++ + add_public_tablegen_target(ClangDriverOptions) +diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td +index d4f7315bf8cb..365285966a67 100644 +--- a/clang/include/clang/Driver/Options.td ++++ b/clang/include/clang/Driver/Options.td +@@ -590,7 +590,11 @@ class InternalDriverOpt : Group, + Flags<[NoXarchOption, HelpHidden]>; + def driver_mode : Joined<["--"], "driver-mode=">, Group, + Flags<[CoreOption, NoXarchOption, HelpHidden]>, ++#ifdef ENABLE_CLASSIC_FLANG ++ HelpText<"Set the driver mode to one of: 'gcc', 'g++', 'cpp', 'cl', or 'flang'">; ++#else + HelpText<"Set the driver mode to either 'gcc', 'g++', 'cpp', or 'cl'">; ++#endif + def rsp_quoting : Joined<["--"], "rsp-quoting=">, Group, + Flags<[CoreOption, NoXarchOption, HelpHidden]>, + HelpText<"Set the rsp quoting to either 'posix', or 'windows'">; +@@ -1183,6 +1187,10 @@ def d_Flag : Flag<["-"], "d">, Group; + def d_Joined : Joined<["-"], "d">, Group; + def emit_ast : Flag<["-"], "emit-ast">, Flags<[CoreOption]>, + HelpText<"Emit Clang AST files for source inputs">; ++#ifdef ENABLE_CLASSIC_FLANG ++def emit_flang_llvm : Flag<["-"], "emit-flang-llvm">, ++ HelpText<"Emit Flang LLVM files for source inputs">; ++#endif + def emit_llvm : Flag<["-"], "emit-llvm">, Flags<[CC1Option, FC1Option, FlangOption]>, Group, + HelpText<"Use the LLVM representation for assembler and object files">; + def emit_interface_stubs : Flag<["-"], "emit-interface-stubs">, Flags<[CC1Option]>, Group, +@@ -2640,10 +2648,17 @@ def fno_experimental_isel : Flag<["-"], "fno-experimental-isel">, Group; + def fveclib : Joined<["-"], "fveclib=">, Group, Flags<[CC1Option]>, + HelpText<"Use the given vector functions library">, ++#ifdef ENABLE_CLASSIC_FLANG ++ Values<"Accelerate,libmvec,MASSV,PGMATH,SVML,SLEEF,Darwin_libsystem_m,ArmPL,none">, ++ NormalizedValuesScope<"CodeGenOptions">, ++ NormalizedValues<["Accelerate", "LIBMVEC", "MASSV", "PGMATH", "SVML", "SLEEF", ++ "Darwin_libsystem_m", "ArmPL", "NoLibrary"]>, ++#else + Values<"Accelerate,libmvec,MASSV,SVML,SLEEF,Darwin_libsystem_m,ArmPL,none">, + NormalizedValuesScope<"CodeGenOptions">, + NormalizedValues<["Accelerate", "LIBMVEC", "MASSV", "SVML", "SLEEF", + "Darwin_libsystem_m", "ArmPL", "NoLibrary"]>, ++#endif + MarshallingInfoEnum, "NoLibrary">; + def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group, + Alias, AliasArgs<["none"]>; +@@ -5382,6 +5397,20 @@ def module_dir : JoinedOrSeparate<["-"], "module-dir">, MetaVarName<"">, + It is also added to the list of directories to be searched by an USE statement. + The default is the current directory.}]>; + ++#ifdef ENABLE_CLASSIC_FLANG ++// Define a group for Fortran source format options. ++def fortran_format_Group : OptionGroup<"Fortran format Group">, Group; ++def ffixed_form : Flag<["-"], "ffixed-form">, Group, ++ HelpText<"Process source files in fixed form">; ++def fno_fixed_form : Flag<["-"], "fno-fixed-form">, Group, ++ HelpText<"Disable fixed-form format for Fortran">; ++def ffree_form : Flag<["-"], "ffree-form">, Group, ++ HelpText<"Process source files in free form">; ++def fno_free_form : Flag<["-"], "fno-free-form">, Group, ++ HelpText<"Disable free-form format for Fortran">; ++def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group, ++ HelpText<"Set line length in fixed-form format Fortran, current supporting only 72 and 132 characters">; ++#else + def ffixed_form : Flag<["-"], "ffixed-form">, Group, + HelpText<"Process source files in fixed form">; + def ffree_form : Flag<["-"], "ffree-form">, Group, +@@ -5391,6 +5420,7 @@ def ffixed_line_length_EQ : Joined<["-"], "ffixed-line-length=">, Group + DocBrief<[{Set column after which characters are ignored in typical fixed-form lines in the source + file}]>; + def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group, Alias; ++#endif + def fconvert_EQ : Joined<["-"], "fconvert=">, Group, + HelpText<"Set endian conversion of data for unformatted files">; + def fopenacc : Flag<["-"], "fopenacc">, Group, +@@ -5399,8 +5429,14 @@ def fdefault_double_8 : Flag<["-"],"fdefault-double-8">, Group, + HelpText<"Set the default double precision kind to an 8 byte wide type">; + def fdefault_integer_8 : Flag<["-"],"fdefault-integer-8">, Group, + HelpText<"Set the default integer and logical kind to an 8 byte wide type">; ++#ifdef ENABLE_CLASSIC_FLANG ++def fno_default_integer_8 : Flag<["-"], "fno-default-integer-8">, Group; ++#endif + def fdefault_real_8 : Flag<["-"],"fdefault-real-8">, Group, + HelpText<"Set the default real kind to an 8 byte wide type">; ++#ifdef ENABLE_CLASSIC_FLANG ++def fno_default_real_8 : Flag<["-"], "fno-default-real-8">, Group; ++#endif + def flarge_sizes : Flag<["-"],"flarge-sizes">, Group, + HelpText<"Use INTEGER(KIND=8) for the result type in size-related intrinsics">; + +@@ -5410,7 +5446,17 @@ def fintrinsic_modules_path : Separate<["-"], "fintrinsic-modules-path">, Group + HelpText<"Specify where to find the compiled intrinsic modules">, + DocBrief<[{This option specifies the location of pre-compiled intrinsic modules, + if they are not in the default location expected by the compiler.}]>; +- ++#ifdef ENABLE_CLASSIC_FLANG ++def fbackslash : Flag<["-"], "fbackslash">, Group, ++ HelpText<"Specify that backslash in string introduces an escape character">, ++ DocBrief<[{Change the interpretation of backslashes in string literals from ++a single backslash character to "C-style" escape characters.}]>; ++def fno_backslash : Flag<["-"], "fno-backslash">, Group; ++// Add the options -f(no-)implicit-none and -f(no-)automatic for compatibility ++// reason. They are not implemented yet in Classic Flang for now. ++defm implicit_none : BooleanFFlag<"implicit-none">, Group; ++def fno_automatic : Flag<["-"], "fno-automatic">, Group; ++#else + defm backslash : OptInFC1FFlag<"backslash", "Specify that backslash in string introduces an escape character">; + defm xor_operator : OptInFC1FFlag<"xor-operator", "Enable .XOR. as a synonym of .NEQV.">; + defm logical_abbreviations : OptInFC1FFlag<"logical-abbreviations", "Enable logical abbreviations">; +@@ -5419,6 +5465,7 @@ defm underscoring : OptInFC1FFlag<"underscoring", "Appends one trailing undersco + + def fno_automatic : Flag<["-"], "fno-automatic">, Group, + HelpText<"Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE">; ++#endif + + defm stack_arrays : BoolOptionWithoutMarshalling<"f", "stack-arrays", + PosFlag, +@@ -5426,12 +5473,19 @@ defm stack_arrays : BoolOptionWithoutMarshalling<"f", "stack-arrays", + defm loop_versioning : BoolOptionWithoutMarshalling<"f", "version-loops-for-stride", + PosFlag, + NegFlag>; ++ + } // let Flags = [FC1Option, FlangOption, FlangOnlyOption] + ++#ifdef ENABLE_CLASSIC_FLANG ++def J : JoinedOrSeparate<["-"], "J">, ++ Flags<[RenderJoined]>, ++ Group; ++#else + def J : JoinedOrSeparate<["-"], "J">, + Flags<[RenderJoined, FlangOption, FC1Option, FlangOnlyOption]>, + Group, + Alias; ++#endif + + //===----------------------------------------------------------------------===// + // FC1 Options +@@ -7458,6 +7512,147 @@ def fcgl : DXCFlag<"fcgl">, Alias; + def enable_16bit_types : DXCFlag<"enable-16bit-types">, Alias, + HelpText<"Enable 16-bit types and disable min precision types." + "Available in HLSL 2018 and shader model 6.2.">; ++ ++#ifdef ENABLE_CLASSIC_FLANG ++// Classic Flang options that we recognize in the driver and pass along when ++// invoking flang1/flang2 to compile Fortran code. ++def flang_rt_Group : OptionGroup<"Flang runtime library Group">; ++def pgi_fortran_Group : OptionGroup<"PGI Fortran compatibility Group">, ++ Flags<[HelpHidden]>; ++ ++// Classic Flang-specific options ++multiclass BooleanKFlag { ++ def _on : Flag<["-"], "K"#name>; ++ def _off : Flag<["-"], "Kno"#name>; ++} ++ ++multiclass BooleanMFlag { ++ def _on : Flag<["-"], "M"#name>; ++ def _off : Flag<["-"], "Mno"#name>; ++} ++ ++def Mfixed : Flag<["-"], "Mfixed">, Group, ++ HelpText<"Force fixed-form format Fortran">, ++ Flags<[HelpHidden]>; ++def Mfree_on: Flag<["-"], "Mfree">, Group, ++ HelpText<"Enable free-form format for Fortran">, ++ Flags<[HelpHidden]>; ++def Mfree_off: Flag<["-"], "Mnofree">, Group, ++ HelpText<"Disable free-form format for Fortran">, ++ Flags<[HelpHidden]>; ++def Mfreeform_on: Flag<["-"], "Mfreeform">, Group, ++ HelpText<"Enable free-form format for Fortran">, ++ Flags<[HelpHidden]>; ++def Mfreeform_off: Flag<["-"], "Mnofreeform">, 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; ++def Mstackarrays: Joined<["-"], "Mstack_arrays">, Group; ++def pc: JoinedOrSeparate<["-"], "pc">, Group; ++def Mfprelaxed: Joined<["-"], "Mfprelaxed">, Group; ++def Mnofprelaxed: Joined<["-"], "Mnofprelaxed">, Group; ++defm Mstride0: BooleanMFlag<"stride0">, Group; ++defm Mrecursive: BooleanMFlag<"recursive">, Group; ++defm Mreentrant: BooleanMFlag<"reentrant">, Group; ++defm Mbounds: BooleanMFlag<"bounds">, Group; ++def Mdaz_on: Flag<["-"], "Mdaz">, Group, ++ HelpText<"Treat denormalized numbers as zero">; ++def Mdaz_off: Flag<["-"], "Mnodaz">, Group, ++ HelpText<"Disable treating denormalized numbers as zero">; ++def Kieee_on : Flag<["-"], "Kieee">, Group, ++ HelpText<"Enable IEEE division">; ++def Kieee_off : Flag<["-"], "Knoieee">, Group, ++ HelpText<"Disable IEEE division">; ++def Mextend : Flag<["-"], "Mextend">, Group, ++ HelpText<"Allow lines up to 132 characters in Fortran sources">; ++def Mpreprocess : Flag<["-"], "Mpreprocess">, Group, ++ HelpText<"Preprocess Fortran files">; ++def Mstandard: Flag<["-"], "Mstandard">, Group, ++ HelpText<"Check Fortran standard conformance">; ++def Mchkptr: Flag<["-"], "Mchkptr">, Group; ++def Mwritable_constants: Flag<["-"], "Mwritable-constants">, Group, ++ HelpText<"Store constants in the writable data segment">; ++defm Minline: BooleanMFlag<"inline">, Group; ++def fma: Flag<["-"], "fma">, Group, ++ HelpText<"Enable generation of FMA instructions">; ++def nofma: Flag<["-"], "nofma">, Group, ++ HelpText<"Disable generation of FMA instructions">; ++defm Mfma: BooleanMFlag<"fma">, Group, ++ HelpText<"Enable generation of FMA instructions">; ++def mp: Flag<["-"], "mp">, Group, ++ HelpText<"Enable OpenMP">; ++def nomp: Flag<["-"], "nomp">, Group, ++ HelpText<"Do not link with OpenMP library libomp">; ++def Mflushz_on: Flag<["-"], "Mflushz">, Group, ++ HelpText<"Set SSE to flush-to-zero mode">; ++def Mflushz_off: Flag<["-"], "Mnoflushz">, Group, ++ HelpText<"Disabling setting SSE to flush-to-zero mode">; ++def Msave_on: Flag<["-"], "Msave">, Group, ++ HelpText<"Assume all Fortran variables have SAVE attribute">; ++def Msave_off: Flag<["-"], "Mnosave">, Group, ++ HelpText<"Assume no Fortran variables have SAVE attribute">; ++def Mcache_align_on: Flag<["-"], "Mcache_align">, Group, ++ HelpText<"Align large objects on cache-line boundaries">; ++def Mcache_align_off: Flag<["-"], "Mnocache_align">, Group, ++ HelpText<"Disable aligning large objects on cache-line boundaries">; ++def ModuleDir : Separate<["-"], "module">, 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, ++ HelpText<"Swap byte-order for unformatted input/output">; ++def byteswapio: Flag<["-"], "byteswapio">, Group, ++ HelpText<"Swap byte-order for unformatted input/output">; ++def Mbackslash: Flag<["-"], "Mbackslash">, Group, ++ HelpText<"Treat backslash like any other character in character strings">; ++def Mnobackslash: Flag<["-"], "Mnobackslash">, Group, ++ HelpText<"Treat backslash as C-style escape character">; ++def staticFlangLibs: Flag<["-"], "static-flang-libs">, Group, ++ HelpText<"Link using static Flang libraries">; ++def noFlangLibs: Flag<["-"], "no-flang-libs">, Group, ++ HelpText<"Do not link against Flang libraries">; ++def r8: Flag<["-"], "r8">, Group, ++ HelpText<"Treat REAL as REAL*8">; ++def i8: Flag<["-"], "i8">, Group, ++ HelpText<"Treat INTEGER and LOGICAL as INTEGER*8 and LOGICAL*8">; ++def no_fortran_main: Flag<["-"], "fno-fortran-main">, Group, ++ HelpText<"Don't link in Fortran main">; ++def Mnomain: Flag<["-"], "Mnomain">, Group, ++ HelpText<"Don't link in Fortran main">; ++def frelaxed_math : Flag<["-"], "frelaxed-math">, Group, ++ HelpText<"Use relaxed Math intrinsic functions">; ++def Memit_dwarf_common_blocks_name: Flag<["-"], "Memit-dwarf-common-blocks-name">, ++ Group, HelpText<"Emit COMMON blocks name in DWARF">; ++def Munixlogical: Flag<["-"], "Munixlogical">, Group, ++ HelpText<"Use unixlogical for all loigical operations">; ++ ++// Flang internal debug options ++def Mx_EQ : Joined<["-"], "Mx,">, Group; ++def My_EQ : Joined<["-"], "My,">, Group; ++def Hx_EQ : Joined<["-"], "Hx,">, Group; ++def Hy_EQ : Joined<["-"], "Hy,">, Group; ++def Wm_EQ : Joined<["-"], "Wm,">, Group; ++ ++def Mq_EQ : Joined<["-"], "Mq,">, Group; ++def Hq_EQ : Joined<["-"], "Hq,">, Group; ++def Mqq_EQ : Joined<["-"], "Mqq,">, Group; ++def Hqq_EQ : Joined<["-"], "Hqq,">, Group; ++def Wh_EQ : Joined<["-"], "Wh,">, Group; ++#endif + def hlsl_entrypoint : Option<["-"], "hlsl-entry", KIND_SEPARATE>, + Group, + Flags<[CC1Option]>, +diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h +index 2e74507f7126..735e72491488 100644 +--- a/clang/include/clang/Driver/ToolChain.h ++++ b/clang/include/clang/Driver/ToolChain.h +@@ -651,6 +651,16 @@ public: + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; + ++#ifdef ENABLE_CLASSIC_FLANG ++ /// \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 { } ++#endif ++ + /// Add options that need to be passed to cc1 for this target. + virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, +@@ -757,6 +767,13 @@ public: + virtual void AddHIPRuntimeLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const {} + ++#ifdef ENABLE_CLASSIC_FLANG ++ /// 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; ++#endif ++ + /// 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 aaea3ec0f9c8..2f241b02676b 100644 +--- a/clang/include/clang/Driver/Types.def ++++ b/clang/include/clang/Driver/Types.def +@@ -77,8 +77,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 ENABLE_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, "i", 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 4a21af3534de..3a8b785a4c39 100644 +--- a/clang/include/clang/Driver/Types.h ++++ b/clang/include/clang/Driver/Types.h +@@ -95,6 +95,14 @@ namespace types { + /// isOpenCL - Is this an "OpenCL" input. + bool isOpenCL(ID Id); + ++#ifdef ENABLE_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 ++ + /// isHLSL - Is this an HLSL input. + bool isHLSL(ID Id); + +diff --git a/clang/include/clang/Frontend/Utils.h b/clang/include/clang/Frontend/Utils.h +index 143cf4359f00..c51c617c1379 100644 +--- a/clang/include/clang/Frontend/Utils.h ++++ b/clang/include/clang/Frontend/Utils.h +@@ -17,8 +17,10 @@ + #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/StringExtras.h" + #include "llvm/ADT/StringMap.h" + #include "llvm/ADT/StringRef.h" + #include "llvm/ADT/StringSet.h" +@@ -31,6 +33,12 @@ + #include + #include + ++namespace llvm { ++ ++class StringRef; ++ ++} // namespace llvm ++ + namespace clang { + + class ASTReader; +@@ -39,6 +47,7 @@ class CompilerInvocation; + class DiagnosticsEngine; + class ExternalSemaSource; + class FrontendOptions; ++class MacroBuilder; + class PCHContainerReader; + class Preprocessor; + class PreprocessorOptions; +@@ -54,6 +63,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 ++static void DefineTypeSize(const Twine &MacroName, unsigned TypeWidth, ++ StringRef ValSuffix, bool isSigned, ++ T &Builder) { ++ static_assert(std::is_base_of::value, "Illegal T value"); ++ llvm::APInt MaxVal = isSigned ? llvm::APInt::getSignedMaxValue(TypeWidth) ++ : llvm::APInt::getMaxValue(TypeWidth); ++ Builder.defineMacro(MacroName, toString(MaxVal, 10, isSigned) + ValSuffix); ++} ++ ++/// DefineTypeSize - An overloaded helper that uses TargetInfo to determine ++/// the width, suffix, and signedness of the given type ++template ++static void DefineTypeSize(const Twine &MacroName, TargetInfo::IntType Ty, ++ const TargetInfo &TI, T &Builder) { ++ static_assert(std::is_base_of::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 483f3e787a78..f962d60870d1 100644 +--- a/clang/lib/CodeGen/BackendUtil.cpp ++++ b/clang/lib/CodeGen/BackendUtil.cpp +@@ -272,6 +272,12 @@ static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple, + TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::MASSV, + TargetTriple); + break; ++#ifdef ENABLE_CLASSIC_FLANG ++ case CodeGenOptions::PGMATH: ++ TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::PGMATH, ++ TargetTriple); ++ break; ++#endif + case CodeGenOptions::SVML: + TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::SVML, + TargetTriple); +diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp +index d8eb2aecb87a..3b140860cce4 100644 +--- a/clang/lib/CodeGen/CGDebugInfo.cpp ++++ b/clang/lib/CodeGen/CGDebugInfo.cpp +@@ -3980,7 +3980,8 @@ CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) { + auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); + auto *GV = DBuilder.createTempGlobalVariableFwdDecl( + DContext, Name, LinkageName, Unit, Line, getOrCreateType(T, Unit), +- !VD->isExternallyVisible(), nullptr, TemplateParameters, Align); ++ !VD->isExternallyVisible(), nullptr, TemplateParameters, ++ llvm::DINode::FlagZero, Align); + FwdDeclReplaceMap.emplace_back( + std::piecewise_construct, + std::make_tuple(cast(VD->getCanonicalDecl())), +@@ -5467,7 +5468,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, + Var->hasLocalLinkage(), true, + Expr.empty() ? nullptr : DBuilder.createExpression(Expr), + getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters, +- Align, Annotations); ++ llvm::DINode::FlagZero, Align, Annotations); + Var->addDebugInfo(GVE); + } + DeclCache[D->getCanonicalDecl()].reset(GVE); +@@ -5563,7 +5564,7 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) { + GV.reset(DBuilder.createGlobalVariableExpression( + DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty, + true, true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VarD), +- TemplateParameters, Align)); ++ TemplateParameters, llvm::DINode::FlagZero, Align)); + } + + void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var, +@@ -5581,7 +5582,8 @@ void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var, + llvm::DIGlobalVariableExpression *GVE = + DBuilder.createGlobalVariableExpression( + DContext, Name, StringRef(), Unit, getLineNumber(D->getLocation()), +- Ty, false, false, nullptr, nullptr, nullptr, Align); ++ Ty, false, false, nullptr, nullptr, nullptr, llvm::DINode::FlagZero, ++ Align); + Var->addDebugInfo(GVE); + } + +diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt +index a6bd2d41e797..ac30007588b1 100644 +--- a/clang/lib/Driver/CMakeLists.txt ++++ b/clang/lib/Driver/CMakeLists.txt +@@ -14,6 +14,12 @@ if(WIN32) + set(system_libs version) + endif() + ++if(LLVM_ENABLE_CLASSIC_FLANG) ++ set(TOOLCHAINS_FLANG_CPP ToolChains/ClassicFlang.cpp) ++else() ++ set(TOOLCHAINS_FLANG_CPP ToolChains/Flang.cpp) ++endif() ++ + add_clang_library(clangDriver + Action.cpp + Compilation.cpp +@@ -56,7 +62,7 @@ add_clang_library(clangDriver + ToolChains/Cuda.cpp + ToolChains/Darwin.cpp + ToolChains/DragonFly.cpp +- ToolChains/Flang.cpp ++ ${TOOLCHAINS_FLANG_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 a7e4edb3ab5a..8bfee5928fe5 100644 +--- a/clang/lib/Driver/Driver.cpp ++++ b/clang/lib/Driver/Driver.cpp +@@ -377,10 +377,14 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, + (PhaseArg = DAL.getLastArg(options::OPT_fmodule_header, + options::OPT_fmodule_header_EQ))) { + FinalPhase = phases::Precompile; ++ + // -{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)) || + (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) || ++#ifdef ENABLE_CLASSIC_FLANG ++ (PhaseArg = DAL.getLastArg(options::OPT_emit_flang_llvm)) || ++#endif + (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) || + (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) || + (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) || +@@ -1983,7 +1987,11 @@ void Driver::PrintHelp(bool ShowHidden) const { + + void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const { + if (IsFlangMode()) { ++#ifdef ENABLE_CLASSIC_FLANG ++ OS << getClangToolFullVersion("flang") << '\n'; ++#else + OS << getClangToolFullVersion("flang-new") << '\n'; ++#endif + } else { + // FIXME: The following handlers should use a callback mechanism, we don't + // know what the client would like to do. +@@ -2665,7 +2673,15 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, + // stdin must be handled specially. + if (memcmp(Value, "-", 2) == 0) { + if (IsFlangMode()) { ++#ifdef ENABLE_CLASSIC_FLANG ++ // If running with -E, treat as needing preprocessing ++ if (!Args.hasArgNoClaim(options::OPT_E)) ++ Ty = types::TY_PP_F_FreeForm; ++ else ++ Ty = types::TY_F_FreeForm; ++#else + Ty = types::TY_Fortran; ++#endif + } else { + // If running with -E, treat as a C input (this changes the + // builtin macros, for example). This may be overridden by -ObjC +@@ -2687,6 +2703,16 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, + // idea of what .s is. + if (const char *Ext = strrchr(Value, '.')) + Ty = TC.LookupTypeForExtension(Ext + 1); ++#ifdef ENABLE_CLASSIC_FLANG ++ // If called with -E, treat the inputs as needing preprocessing ++ // regardless of extension ++ if (IsFlangMode() && Args.hasArgNoClaim(options::OPT_E)) { ++ if (Ty == types::TY_PP_F_FreeForm) ++ Ty = types::TY_F_FreeForm; ++ else if (Ty == types::TY_PP_F_FixedForm) ++ Ty = types::TY_F_FixedForm; ++ } ++#endif + + if (Ty == types::TY_INVALID) { + if (IsCLMode() && (Args.hasArgNoClaim(options::OPT_E) || CCGenDiagnostics)) +@@ -4011,6 +4037,14 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args, + if (InputArg->isClaimed()) + continue; + ++#ifdef ENABLE_CLASSIC_FLANG ++ // If the input is detected as already preprocessed (e.g. has the .f95 ++ // extension), and the user specifies -E, preprocess the file anyway. ++ if (IsFlangMode() && InitialPhase == phases::Compile && ++ FinalPhase == phases::Preprocess) ++ continue; ++#endif ++ + // Claim here to avoid the more general unused warning. + InputArg->claim(); + +@@ -4745,6 +4779,10 @@ Action *Driver::ConstructPhaseAction( + return C.MakeAction(Input, types::TY_Nothing); + if (Args.hasArg(options::OPT_extract_api)) + return C.MakeAction(Input, types::TY_API_INFO); ++#ifdef ENABLE_CLASSIC_FLANG ++ if (IsFlangMode()) ++ return C.MakeAction(Input, types::TY_LLVM_IR); ++#endif + return C.MakeAction(Input, types::TY_LLVM_BC); + } + case phases::Backend: { +@@ -5199,6 +5237,12 @@ class ToolSelector final { + if (!T->hasIntegratedBackend() && !(OutputIsLLVM && T->canEmitIR())) + return nullptr; + ++#ifdef ENABLE_CLASSIC_FLANG ++ // Classic Flang is not integrated with the backend. ++ if (C.getDriver().IsFlangMode() && !T->hasIntegratedAssembler()) ++ return nullptr; ++#endif ++ + if (T->canEmitIR() && ((SaveTemps && !InputIsBitcode) || EmbedBitcode)) + return nullptr; + +@@ -5214,8 +5258,17 @@ class ToolSelector final { + /// are appended to \a CollapsedOffloadAction. + void combineWithPreprocessor(const Tool *T, ActionList &Inputs, + ActionList &CollapsedOffloadAction) { ++#ifdef ENABLE_CLASSIC_FLANG ++ // flang1 always combines preprocessing and compilation. ++ // Do not return early even when -save-temps is used. ++ if (!T || !T->hasIntegratedCPP() || ++ (strcmp(T->getName(), "classic-flang") && ++ !canCollapsePreprocessorAction())) ++ return; ++#else + if (!T || !canCollapsePreprocessorAction() || !T->hasIntegratedCPP()) + return; ++#endif + + // Attempt to get a preprocessor action dependence. + ActionList PreprocessJobOffloadActions; +@@ -6418,8 +6471,11 @@ bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const { + return false; + + // And say "no" if this is not a kind of action flang understands. +- if (!isa(JA) && !isa(JA) && +- !isa(JA)) ++ if (!isa(JA) && !isa(JA) ++#ifndef ENABLE_CLASSIC_FLANG ++ && !isa(JA) ++#endif ++ ) + return false; + + return true; +diff --git a/clang/lib/Driver/OffloadBundler.cpp b/clang/lib/Driver/OffloadBundler.cpp +index 0ddfb07fdad5..acc4e9128cb1 100644 +--- a/clang/lib/Driver/OffloadBundler.cpp ++++ b/clang/lib/Driver/OffloadBundler.cpp +@@ -864,6 +864,10 @@ CreateFileHandler(MemoryBuffer &FirstInput, + return std::make_unique(/*Comment=*/"#"); + if (FilesType == "ll") + return std::make_unique(/*Comment=*/";"); ++#ifdef ENABLE_CLASSIC_FLANG ++ if (FilesType == "f95") ++ return std::make_unique(/*Comment=*/"!"); ++#endif + if (FilesType == "bc") + return std::make_unique(BundlerConfig); + if (FilesType == "s") +diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp +index 0146d8af3549..3d92b7c2a3bd 100644 +--- a/clang/lib/Driver/ToolChain.cpp ++++ b/clang/lib/Driver/ToolChain.cpp +@@ -10,6 +10,9 @@ + #include "ToolChains/Arch/AArch64.h" + #include "ToolChains/Arch/ARM.h" + #include "ToolChains/Clang.h" ++#ifdef ENABLE_CLASSIC_FLANG ++#include "ToolChains/ClassicFlang.h" ++#endif + #include "ToolChains/CommonArgs.h" + #include "ToolChains/Flang.h" + #include "ToolChains/InterfaceStubs.h" +@@ -441,7 +444,11 @@ Tool *ToolChain::getClang() const { + + Tool *ToolChain::getFlang() const { + if (!Flang) ++#ifdef ENABLE_CLASSIC_FLANG ++ Flang.reset(new tools::ClassicFlang(*this)); ++#else + Flang.reset(new tools::Flang(*this)); ++#endif + return Flang.get(); + } + +@@ -864,13 +871,13 @@ std::string ToolChain::GetStaticLibToolPath() const { + + types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const { + types::ID id = types::lookupTypeForExtension(Ext); +- ++#ifndef ENABLE_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 differently. + if (D.IsFlangMode() && id == types::TY_PP_Fortran) + id = types::TY_Fortran; +- ++#endif + return id; + } + +@@ -1223,6 +1230,31 @@ void ToolChain::AddCCKextLibArgs(const ArgList &Args, + CmdArgs.push_back("-lcc_kext"); + } + ++#ifdef ENABLE_CLASSIC_FLANG ++void ToolChain::AddFortranStdlibLibArgs(const ArgList &Args, ++ ArgStringList &CmdArgs) const { ++ bool StaticFlangLibs = false; ++ if (Args.hasArg(options::OPT_staticFlangLibs)) { ++ StaticFlangLibs = true; ++ Args.ClaimAllArgs(options::OPT_staticFlangLibs); ++ } ++ ++ if (StaticFlangLibs && !Args.hasArg(options::OPT_static)) ++ CmdArgs.push_back("-Bstatic"); ++ CmdArgs.push_back("-lflang"); ++ CmdArgs.push_back("-lflangrti"); ++ CmdArgs.push_back("-lpgmath"); ++ if (StaticFlangLibs && !Args.hasArg(options::OPT_static)) ++ CmdArgs.push_back("-Bdynamic"); ++ ++ // Always link Fortran executables with pthreads. ++ CmdArgs.push_back("-lpthread"); ++ ++ if (!Triple.isOSDarwin()) ++ CmdArgs.push_back("-lrt"); ++} ++#endif ++ + bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args, + std::string &Path) 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 793af55a1e5f..c5ba8a690687 100644 +--- a/clang/lib/Driver/ToolChains/Clang.cpp ++++ b/clang/lib/Driver/ToolChains/Clang.cpp +@@ -5367,6 +5367,66 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, + } + A->render(Args, CmdArgs); + } ++#ifdef ENABLE_CLASSIC_FLANG ++ // Use PGMATH for Classic Flang by default. ++ else { ++ CmdArgs.push_back("-fveclib=PGMATH"); ++ } ++ ++ 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 (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 (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); ++#endif + + if (Args.hasFlag(options::OPT_fmerge_all_constants, + options::OPT_fno_merge_all_constants, false)) +diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.cpp b/clang/lib/Driver/ToolChains/ClassicFlang.cpp +new file mode 100644 +index 000000000000..b8be0be20b07 +--- /dev/null ++++ b/clang/lib/Driver/ToolChains/ClassicFlang.cpp +@@ -0,0 +1,1217 @@ ++//===-- ClassicFlang.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 "ClassicFlang.h" ++#include "CommonArgs.h" ++#include "clang/Driver/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/YAMLParser.h" ++#include "llvm/TargetParser/TargetParser.h" ++ ++#ifdef LLVM_ON_UNIX ++#include // For getuid(). ++#endif ++ ++using namespace clang::driver; ++using namespace clang::driver::tools; ++using namespace clang; ++using namespace llvm::opt; ++ ++class ClassicFlangMacroBuilder : public MacroBuilder { ++ ArgStringList &CmdArgs; ++ const ArgList &DriverArgs; ++ public: ++ ClassicFlangMacroBuilder(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") override { ++ CmdArgs.push_back("-def"); ++ CmdArgs.push_back(DriverArgs.MakeArgString(Name + Twine('=') + Value)); ++ } ++}; ++ ++void ClassicFlang::ConstructJob(Compilation &C, const JobAction &JA, ++ const InputInfo &Output, const InputInfoList &Inputs, ++ const ArgList &Args, const char *LinkingOutput) const { ++ const Driver &D = getToolChain().getDriver(); ++ const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); ++ ArgStringList CommonCmdArgs; ++ ArgStringList UpperCmdArgs; ++ ArgStringList LowerCmdArgs; ++ SmallString<256> Stem; ++ std::string OutFile; ++ bool NeedIEEE = true; ++ bool NeedFastMath = false; ++ bool NeedRelaxedMath = false; ++ bool AssociativeMath = false; ++ bool SignedZeros = true; ++ ++ // 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::isAcceptedByFlang(InputType) && "Can only accept Fortran"); ++ ++ if (Args.hasArg(options::OPT_fsyntax_only, options::OPT_E)) { ++ // For -fsyntax-only and -E produce temp files only ++ Stem = C.getDriver().GetTemporaryPath("", ""); ++ } else { ++ OutFile = Output.getFilename(); ++ Stem = llvm::sys::path::filename(OutFile); ++ llvm::sys::path::replace_extension(Stem, ""); ++ } ++ ++#ifdef ENABLE_CLASSIC_FLANG ++ if (Args.hasArg(options::OPT_emit_flang_llvm)) { ++ // -emit-flang-llvm only supports asm output so claim -S to prevent warning ++ Args.ClaimAllArgs(options::OPT_S); ++ } ++#endif ++ ++ // 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 (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_fno_backslash, 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"); ++ } ++ ++ // Last argument of -g/-gdwarfX should be taken. ++ Arg *GArg = Args.getLastArg(options::OPT_g_Flag); ++ Arg *GDwarfArg = Args.getLastArg(options::OPT_gdwarf_2, ++ options::OPT_gdwarf_3, ++ options::OPT_gdwarf_4, ++ options::OPT_gdwarf_5); ++ ++ if (GArg || GDwarfArg) { ++ ++ for (auto Arg : Args.filtered(options::OPT_g_Flag, options::OPT_gdwarf_2, ++ options::OPT_gdwarf_3, options::OPT_gdwarf_4, ++ options::OPT_gdwarf_5)) { ++ Arg->claim(); ++ } ++ ++ CommonCmdArgs.push_back("-x"); ++ CommonCmdArgs.push_back("120"); ++ ++ if (!GDwarfArg) // -g without -gdwarf-X produces default (DWARFv4) ++ CommonCmdArgs.push_back("0x1000000"); ++ else if (GDwarfArg->getOption().matches(options::OPT_gdwarf_2)) // -gdwarf-2 ++ CommonCmdArgs.push_back("0x200"); ++ else if (GDwarfArg->getOption().matches(options::OPT_gdwarf_3)) // -gdwarf-3 ++ CommonCmdArgs.push_back("0x4000"); ++ else if (GDwarfArg->getOption().matches(options::OPT_gdwarf_4)) // -gdwarf-4 ++ CommonCmdArgs.push_back("0x1000000"); ++ else if (GDwarfArg->getOption().matches(options::OPT_gdwarf_5)) // -gdwarf-5 ++ CommonCmdArgs.push_back("0x2000000"); ++ // Handle `-gpubnames` option separately. ++ for (auto Arg : Args.filtered(options::OPT_gpubnames)) { ++ Arg->claim(); ++ CommonCmdArgs.push_back("-x"); ++ CommonCmdArgs.push_back("120"); ++ CommonCmdArgs.push_back("0x40000000"); // -gpubnames ++ } ++ } ++ ++ // -Mipa has no effect ++ if (Arg *A = Args.getLastArg(options::OPT_Mipa)) { ++ D.Diag(diag::warn_drv_clang_unsupported) ++ << A->getAsString(Args); ++ } ++ ++ // -Minline has no effect ++ if (Arg *A = Args.getLastArg(options::OPT_Minline_on)) { ++ D.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_fdefault_real_8, ++ options::OPT_fno_default_real_8)) { ++ const char * fl; ++ // For -f version add -x flag, for -fno add -y ++ if (A->getOption().matches(options::OPT_fno_default_real_8)) { ++ fl = "-y"; ++ } else { ++ fl = "-x"; ++ } ++ ++ for (Arg *A : Args.filtered(options::OPT_r8, ++ options::OPT_fdefault_real_8, ++ options::OPT_fno_default_real_8)) { ++ 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_fdefault_integer_8, ++ options::OPT_fno_default_integer_8)) { ++ const char * fl; ++ ++ if (A->getOption().matches(options::OPT_fno_default_integer_8)) { ++ fl = "-y"; ++ } else { ++ fl = "-x"; ++ } ++ ++ for (Arg *A : Args.filtered(options::OPT_i8, ++ options::OPT_fdefault_integer_8, ++ options::OPT_fno_default_integer_8)) { ++ 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 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(); ++ } ++ } ++ ++ // 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, ++ options::OPT_fassociative_math, ++ options::OPT_fno_associative_math, ++ options::OPT_fsigned_zeros, ++ options::OPT_fno_signed_zeros)) { ++ 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 = AssociativeMath = false; ++ NeedIEEE = SignedZeros = 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; ++ } else if (A->getOption().matches(options::OPT_fassociative_math)) { ++ AssociativeMath = true; ++ NeedIEEE = SignedZeros = false; ++ } else if (A->getOption().matches(options::OPT_fno_associative_math)) { ++ AssociativeMath = false; ++ } else if (A->getOption().matches(options::OPT_fsigned_zeros)) { ++ SignedZeros = true; ++ AssociativeMath = false; ++ } else if (A->getOption().matches(options::OPT_fno_signed_zeros)) { ++ SignedZeros = NeedIEEE = false; ++ } ++ A->claim(); ++ } ++ ++ // fp-contract=fast is the default ++ bool EnableFPContraction = true; ++ if (Arg *A = Args.getLastArg(options::OPT_ffp_contract, ++ options::OPT_Mfma_on, ++ options::OPT_fma, ++ options::OPT_Mfma_off, ++ options::OPT_nofma)) { ++ auto Opt = A->getOption(); ++ if (Opt.matches(options::OPT_ffp_contract)) { ++ StringRef Val = A->getValue(); ++ if ((Val == "fast") || (Val == "on")) { ++ EnableFPContraction = true; ++ } else if (Val == "off") { ++ EnableFPContraction = false; ++ } else { ++ D.Diag(diag::err_drv_unsupported_option_argument) ++ << A->getOption().getName() << Val; ++ } ++ } else if(Opt.matches(options::OPT_Mfma_on) || ++ Opt.matches(options::OPT_fma)) { ++ EnableFPContraction = true; ++ } else { ++ EnableFPContraction = false; ++ } ++ } ++ ++ if(OptLevel == 0) ++ EnableFPContraction = false; ++ ++ // Emit contract math instructions. ++ // Step 1 : Generate fma instructions in flang (can override with fma flag) ++ // Step 2 : Propagate fma contract information to LLVM to further ++ // exploit contraction opportunities ++ if (EnableFPContraction) { ++ LowerCmdArgs.push_back("-x"); ++ LowerCmdArgs.push_back("172"); ++ LowerCmdArgs.push_back("0x40000000"); ++ LowerCmdArgs.push_back("-x"); ++ LowerCmdArgs.push_back("179"); ++ LowerCmdArgs.push_back("1"); ++ // Step 2 ++ LowerCmdArgs.push_back("-x"); ++ LowerCmdArgs.push_back("216"); ++ LowerCmdArgs.push_back("0x1000"); ++ } else { ++ LowerCmdArgs.push_back("-x"); ++ LowerCmdArgs.push_back("171"); ++ LowerCmdArgs.push_back("0x40000000"); ++ LowerCmdArgs.push_back("-x"); ++ LowerCmdArgs.push_back("178"); ++ LowerCmdArgs.push_back("1"); ++ } ++ ++ if (NeedFastMath) { ++ // Lower: -x 216 1 ++ LowerCmdArgs.push_back("-x"); ++ LowerCmdArgs.push_back("216"); ++ LowerCmdArgs.push_back("1"); ++ // Common: -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"); ++ // Common: -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"); ++ // Common: -ieee 0 ++ CommonCmdArgs.push_back("-ieee"); ++ CommonCmdArgs.push_back("0"); ++ } else { ++ // Common: -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 TO = std::make_shared(); ++ TO->Triple = Triple.getTriple(); ++ std::shared_ptr TI(clang::TargetInfo::CreateTargetInfo(DE, TO)); ++ std::string PredefineBuffer; ++ llvm::raw_string_ostream Predefines(PredefineBuffer); ++ ClassicFlangMacroBuilder Builder(UpperCmdArgs, Args, Predefines); ++ ++ LangOptions LO; ++ VersionTuple VT = getToolChain().computeMSVCVersion(&D, 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().value_or(0) * 100000 + ++ VT.getSubminor().value_or(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(LangAS::Default))); ++ ++ if (TI->getPointerWidth(LangAS::Default) == 64 && TI->getLongWidth() == 64 ++ && TI->getIntWidth() == 32) { ++ Builder.defineMacro("_LP64"); ++ Builder.defineMacro("__LP64__"); ++ } ++ ++ if (TI->getPointerWidth(LangAS::Default) == 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 (Triple.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_ffixed_form: ++ case options::OPT_fno_free_form: ++ case options::OPT_Mfixed: ++ case options::OPT_Mfree_off: ++ case options::OPT_Mfreeform_off: ++ UpperCmdArgs.push_back("-nofreeform"); ++ break; ++ case options::OPT_ffree_form: ++ case options::OPT_fno_fixed_form: ++ 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 { ++ D.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 { ++ D.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(JA, *this, ResponseFileSupport::AtFileUTF8(), 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("170"); // 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"); ++ ++ if (!SignedZeros) { ++ LowerCmdArgs.push_back("-x"); ++ LowerCmdArgs.push_back("216"); ++ LowerCmdArgs.push_back("0x8"); ++ } ++ if (AssociativeMath) { ++ LowerCmdArgs.push_back("-x"); ++ LowerCmdArgs.push_back("216"); ++ LowerCmdArgs.push_back("0x10"); ++ } ++ ++ // Remove "noinline" attriblute ++ LowerCmdArgs.push_back("-x"); LowerCmdArgs.push_back("183"); LowerCmdArgs.push_back("0x10"); ++ ++ // Add target features ++ std::vector Features; ++ std::string FeatureList = ""; ++ getTargetFeatureList(D, Triple, Args, UpperCmdArgs, false, Features); ++ if (!Features.empty()) { ++ for (auto Feature : unifyTargetFeatures(Features)) { ++ if (!FeatureList.empty()) ++ FeatureList += ','; ++ FeatureList += Feature; ++ } ++ ++ LowerCmdArgs.push_back("-target_features"); ++ LowerCmdArgs.push_back(Args.MakeArgString(FeatureList)); ++ } ++ ++ // Add vscale range ++ unsigned vscaleMin = 0; ++ unsigned vscaleMax = 0; ++ bool hasSVE = false; ++ if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) { ++ StringRef Val = A->getValue(); ++ if (Val.equals("128") || Val.equals("256") || Val.equals("512") || ++ Val.equals("1024") || Val.equals("2048") || Val.equals("128+") || ++ Val.equals("256+") || Val.equals("512+") || Val.equals("1024+") || ++ Val.equals("2048+")) { ++ unsigned Bits = 0; ++ if (Val.endswith("+")) ++ Val = Val.substr(0, Val.size() - 1); ++ else { ++ bool Invalid = Val.getAsInteger(10, Bits); (void)Invalid; ++ assert(!Invalid && "Failed to parse value"); ++ vscaleMax = Bits / 128; ++ } ++ ++ bool Invalid = Val.getAsInteger(10, Bits); (void)Invalid; ++ assert(!Invalid && "Failed to parse value"); ++ vscaleMin = Bits / 128; ++ } else if (!Val.equals("scalable")) ++ getToolChain().getDriver().Diag(diag::warn_drv_clang_unsupported) ++ << A->getOption().getName() << Val; ++ } ++ for (auto Feature : unifyTargetFeatures(Features)) { ++ if (Feature.startswith("+sve")) { ++ hasSVE = true; ++ break; ++ } ++ } ++ if (vscaleMin || vscaleMax) { ++ LowerCmdArgs.push_back("-vscale_range_min"); ++ LowerCmdArgs.push_back(Args.MakeArgString( ++ std::to_string(vscaleMin ? vscaleMin : 1))); ++ LowerCmdArgs.push_back("-vscale_range_max"); ++ LowerCmdArgs.push_back(Args.MakeArgString(std::to_string(vscaleMax))); ++ } else { ++ if (hasSVE) { ++ LowerCmdArgs.push_back("-vscale_range_min"); ++ LowerCmdArgs.push_back(Args.MakeArgString(std::to_string(1))); ++ LowerCmdArgs.push_back("-vscale_range_max"); ++ LowerCmdArgs.push_back(Args.MakeArgString(std::to_string(16))); ++ } ++ } ++ ++ // 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 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)); ++ } ++ ++ bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment(); ++ if (IsWindowsMSVC && !Args.hasArg(options::OPT_noFlangLibs)) { ++ getToolChain().AddFortranStdlibLibArgs(Args, LowerCmdArgs); ++ for (auto Arg : Args.filtered(options::OPT_noFlangLibs)) { ++ Arg->claim(); ++ } ++ } ++ ++ C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::AtFileUTF8(), LowerExec, LowerCmdArgs, Inputs)); ++} ++ +diff --git a/clang/lib/Driver/ToolChains/ClassicFlang.h b/clang/lib/Driver/ToolChains/ClassicFlang.h +new file mode 100644 +index 000000000000..5864e0776601 +--- /dev/null ++++ b/clang/lib/Driver/ToolChains/ClassicFlang.h +@@ -0,0 +1,49 @@ ++//===--- ClassicFlang.h - Flang 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_ClassicFlang_H ++#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ClassicFlang_H ++ ++#include "MSVC.h" ++#include "clang/Driver/Driver.h" ++#include "clang/Driver/Tool.h" ++#include "clang/Driver/Types.h" ++#include "llvm/Frontend/Debug/Options.h" ++#include "llvm/Option/Option.h" ++#include "llvm/Support/raw_ostream.h" ++#include "llvm/TargetParser/Triple.h" ++ ++namespace clang { ++namespace driver { ++ ++namespace tools { ++ ++/// \brief Flang Fortran frontend ++class LLVM_LIBRARY_VISIBILITY ClassicFlang : public Tool { ++public: ++ ClassicFlang(const ToolChain &TC) ++ : Tool("classic-flang", ++ "Fortran frontend to LLVM", TC) {} ++ ++ bool hasGoodDiagnostics() const override { return true; } ++ bool hasIntegratedAssembler() const override { return false; } ++ bool hasIntegratedCPP() const override { return true; } ++ ++ 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_ClassicFlang_H +diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp +index 0d6907b8e5c7..1ccc83a468ce 100644 +--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp ++++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp +@@ -146,6 +146,20 @@ static bool shouldIgnoreUnsupportedTargetFeature(const Arg &TargetFeatureArg, + return TargetFeatureArg.getOption().matches(options::OPT_mno_cumode); + } + ++#ifdef ENABLE_CLASSIC_FLANG ++/// \brief Determine if Fortran "main" object is needed ++bool tools::needFortranMain(const Driver &D, const ArgList &Args) { ++ return (needFortranLibs(D, Args) && !Args.hasArg(options::OPT_Mnomain) && ++ !Args.hasArg(options::OPT_no_fortran_main)); ++} ++ ++/// \brief Determine if Fortran link libraies are needed ++bool tools::needFortranLibs(const Driver &D, const ArgList &Args) { ++ return (D.IsFlangMode() && !Args.hasArg(options::OPT_nostdlib) && ++ !Args.hasArg(options::OPT_noFlangLibs)); ++} ++#endif ++ + void tools::addPathIfExists(const Driver &D, const Twine &Path, + ToolChain::path_list &Paths) { + if (D.getVFS().exists(Path)) +@@ -256,6 +270,9 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, + const ArgList &Args, ArgStringList &CmdArgs, + const JobAction &JA) { + const Driver &D = TC.getDriver(); ++#ifdef ENABLE_CLASSIC_FLANG ++ bool SeenFirstLinkerInput = false; ++#endif + + // Add extra linker input arguments which are not treated as inputs + // (constructed via -Xarch_). +@@ -289,6 +306,15 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, + if (II.isNothing()) + continue; + ++#ifdef ENABLE_CLASSIC_FLANG ++ // Add Fortan "main" before the first linker input ++ if (!SeenFirstLinkerInput) { ++ if (needFortranMain(D, Args)) { ++ CmdArgs.push_back("-lflangmain"); ++ } ++ SeenFirstLinkerInput = true; ++ } ++#endif + // Otherwise, this is a linker input argument. + const Arg &A = II.getInputArg(); + +@@ -300,6 +326,16 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, + else + A.renderAsInput(Args, CmdArgs); + } ++#ifdef ENABLE_CLASSIC_FLANG ++ 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(); ++ } ++#endif + } + + void tools::addLinkerCompressDebugSectionsOption( +@@ -489,10 +525,18 @@ static void getWebAssemblyTargetFeatures(const Driver &D, + options::OPT_m_wasm_Features_Group); + } + ++#ifndef ENABLE_CLASSIC_FLANG + void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, ArgStringList &CmdArgs, + bool ForAS, bool IsAux) { + std::vector Features; ++#else ++void tools::getTargetFeatureList(const Driver &D, ++ const llvm::Triple &Triple, ++ const ArgList &Args, ArgStringList &CmdArgs, ++ bool ForAS, ++ std::vector &Features) { ++#endif + switch (Triple.getArch()) { + default: + break; +@@ -567,6 +611,15 @@ void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple, + loongarch::getLoongArchTargetFeatures(D, Triple, Args, Features); + break; + } ++#ifdef ENABLE_CLASSIC_FLANG ++} ++ ++void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple, ++ const ArgList &Args, ArgStringList &CmdArgs, ++ bool ForAS, bool IsAux) { ++ std::vector Features; ++ getTargetFeatureList(D, Triple, Args, CmdArgs, ForAS, Features); ++#endif + + for (auto Feature : unifyTargetFeatures(Features)) { + CmdArgs.push_back(IsAux ? "-aux-target-feature" : "-target-feature"); +@@ -889,7 +942,11 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, + const ArgList &Args, bool ForceStaticHostRuntime, + bool IsOffloadingHost, bool GompNeedsRT) { + if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, +- options::OPT_fno_openmp, false)) ++ options::OPT_fno_openmp, false) ++#ifdef ENABLE_CLASSIC_FLANG ++ && !Args.hasFlag(options::OPT_mp, options::OPT_nomp, false) ++#endif ++ ) + return false; + + Driver::OpenMPRuntimeKind RTKind = TC.getDriver().getOpenMPRuntime(Args); +@@ -934,7 +991,16 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, + } + + void tools::addFortranRuntimeLibs(const ToolChain &TC, ++#ifdef ENABLE_CLASSIC_FLANG ++ const llvm::opt::ArgList &Args, ++#endif + llvm::opt::ArgStringList &CmdArgs) { ++#ifdef ENABLE_CLASSIC_FLANG ++ if (needFortranLibs(TC.getDriver(), Args)) ++ TC.AddFortranStdlibLibArgs(Args, CmdArgs); ++ else ++ Args.ClaimAllArgs(options::OPT_noFlangLibs); ++#else + if (TC.getTriple().isKnownWindowsMSVCEnvironment()) { + CmdArgs.push_back("Fortran_main.lib"); + CmdArgs.push_back("FortranRuntime.lib"); +@@ -944,6 +1010,7 @@ void tools::addFortranRuntimeLibs(const ToolChain &TC, + CmdArgs.push_back("-lFortranRuntime"); + CmdArgs.push_back("-lFortranDecimal"); + } ++#endif + } + + void tools::addFortranRuntimeLibraryPath(const ToolChain &TC, +diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h +index 6a8de0f1c36d..bd5cb1bb866e 100644 +--- a/clang/lib/Driver/ToolChains/CommonArgs.h ++++ b/clang/lib/Driver/ToolChains/CommonArgs.h +@@ -23,6 +23,12 @@ namespace clang { + namespace driver { + namespace tools { + ++#ifdef ENABLE_CLASSIC_FLANG ++bool needFortranLibs(const Driver &D, const llvm::opt::ArgList &Args); ++ ++bool needFortranMain(const Driver &D, const llvm::opt::ArgList &Args); ++#endif ++ + void addPathIfExists(const Driver &D, const Twine &Path, + ToolChain::path_list &Paths); + +@@ -131,6 +137,9 @@ bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC, + + /// Adds Fortran runtime libraries to \p CmdArgs. + void addFortranRuntimeLibs(const ToolChain &TC, ++#ifdef ENABLE_CLASSIC_FLANG ++ const llvm::opt::ArgList &Args, ++#endif + llvm::opt::ArgStringList &CmdArgs); + + /// Adds the path for the Fortran runtime libraries to \p CmdArgs. +@@ -173,6 +182,17 @@ void AddTargetFeature(const llvm::opt::ArgList &Args, + std::string getCPUName(const Driver &D, const llvm::opt::ArgList &Args, + const llvm::Triple &T, bool FromAs = false); + ++#ifdef ENABLE_CLASSIC_FLANG ++// Helper function extracted from upstream getTargetFeatures. Classic Flang ++// uses this helper to render the target feature options for the Fortran ++// frontend. ++void getTargetFeatureList(const Driver &D, ++ const llvm::Triple &Triple, ++ const llvm::opt::ArgList &Args, ++ llvm::opt::ArgStringList &CmdArgs, ++ bool ForAS, std::vector &Features); ++#endif ++ + void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, bool ForAS, +diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp +index 3a577650eb08..36fddca2d177 100644 +--- a/clang/lib/Driver/ToolChains/Cuda.cpp ++++ b/clang/lib/Driver/ToolChains/Cuda.cpp +@@ -1034,3 +1034,38 @@ VersionTuple CudaToolChain::computeMSVCVersion(const Driver *D, + const ArgList &Args) const { + return HostTC.computeMSVCVersion(D, Args); + } ++ ++#ifdef ENABLE_CLASSIC_FLANG ++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.c_str()); ++ AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList); ++} ++#endif +diff --git a/clang/lib/Driver/ToolChains/Cuda.h b/clang/lib/Driver/ToolChains/Cuda.h +index 39df6e06fb26..3eded1f53e42 100644 +--- a/clang/lib/Driver/ToolChains/Cuda.h ++++ b/clang/lib/Driver/ToolChains/Cuda.h +@@ -214,6 +214,11 @@ public: + llvm::opt::ArgStringList &CC1Args) const override; + void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; ++#ifdef ENABLE_CLASSIC_FLANG ++ void ++ AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, ++ llvm::opt::ArgStringList &Flang1Args) const override; ++#endif + + SanitizerMask getSupportedSanitizers() const override; + +diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp +index 65bd6c6a7eb3..3b8e4d7e133a 100644 +--- a/clang/lib/Driver/ToolChains/Darwin.cpp ++++ b/clang/lib/Driver/ToolChains/Darwin.cpp +@@ -679,7 +679,11 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, + // to generate executables. + if (getToolChain().getDriver().IsFlangMode()) { + addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs); ++#ifdef ENABLE_CLASSIC_FLANG ++ addFortranRuntimeLibs(getToolChain(), Args, CmdArgs); ++#else + addFortranRuntimeLibs(getToolChain(), CmdArgs); ++#endif + } + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) +diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp +index 0bb5433a658a..076a2d4a21d8 100644 +--- a/clang/lib/Driver/ToolChains/Gnu.cpp ++++ b/clang/lib/Driver/ToolChains/Gnu.cpp +@@ -578,7 +578,11 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, + // AddRuntTimeLibs). + if (D.IsFlangMode()) { + addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs); ++#ifdef ENABLE_CLASSIC_FLANG ++ addFortranRuntimeLibs(ToolChain, Args, CmdArgs); ++#else + addFortranRuntimeLibs(ToolChain, CmdArgs); ++#endif + CmdArgs.push_back("-lm"); + } + +diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp +index 1ba222bf83b1..7f0714676a9d 100644 +--- a/clang/lib/Driver/ToolChains/Linux.cpp ++++ b/clang/lib/Driver/ToolChains/Linux.cpp +@@ -608,6 +608,196 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const { + return "/" + LibDir + "/" + Loader; + } + ++#ifdef ENABLE_CLASSIC_FLANG ++/// 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.c_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.c_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 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 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); ++} ++#endif ++ + 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 524391743090..b6db4160811d 100644 +--- a/clang/lib/Driver/ToolChains/Linux.h ++++ b/clang/lib/Driver/ToolChains/Linux.h +@@ -27,6 +27,11 @@ public: + const llvm::Triple &TargetTriple, + StringRef SysRoot) const override; + ++#ifdef ENABLE_CLASSIC_FLANG ++ void ++ AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, ++ llvm::opt::ArgStringList &Flang1Args) const override; ++#endif + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; +diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp +index a9fe9da4620f..1562e1a4b8eb 100644 +--- a/clang/lib/Driver/ToolChains/MSVC.cpp ++++ b/clang/lib/Driver/ToolChains/MSVC.cpp +@@ -131,7 +131,11 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, + + if (C.getDriver().IsFlangMode()) { + addFortranRuntimeLibraryPath(TC, Args, CmdArgs); ++#ifdef ENABLE_CLASSIC_FLANG ++ addFortranRuntimeLibs(TC, Args, CmdArgs); ++#else + addFortranRuntimeLibs(TC, CmdArgs); ++#endif + + // Inform the MSVC linker that we're generating a console application, i.e. + // one with `main` as the "user-defined" entry point. The `main` function is +@@ -263,6 +267,13 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, + } + } + ++#ifdef ENABLE_CLASSIC_FLANG ++ if (C.getDriver().IsFlangMode()) { ++ CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") + ++ TC.getDriver().Dir + "/../lib")); ++ } ++#endif ++ + // Add compiler-rt lib in case if it was explicitly + // specified as an argument for --rtlib option. + if (!Args.hasArg(options::OPT_nostdlib)) { +@@ -510,6 +521,74 @@ void MSVCToolChain::AddHIPRuntimeLibArgs(const ArgList &Args, + "amdhip64.lib"}); + } + ++#ifdef ENABLE_CLASSIC_FLANG ++void MSVCToolChain::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 (needFortranMain(getDriver(), Args)) { ++ // flangmain is always static ++ CmdArgs.push_back("-linker"); ++ CmdArgs.push_back("/subsystem:console"); ++ CmdArgs.push_back("-linker"); ++ CmdArgs.push_back("/defaultlib:flangmain.lib"); ++ } ++ ++ if (staticFlangLibs) { ++ CmdArgs.push_back("-linker"); ++ CmdArgs.push_back("/defaultlib:libflang.lib"); ++ CmdArgs.push_back("-linker"); ++ CmdArgs.push_back("/defaultlib:libflangrti.lib"); ++ CmdArgs.push_back("-linker"); ++ CmdArgs.push_back("/defaultlib:libpgmath.lib"); ++ } else { ++ CmdArgs.push_back("-linker"); ++ CmdArgs.push_back("/defaultlib:flang.lib"); ++ CmdArgs.push_back("-linker"); ++ CmdArgs.push_back("/defaultlib:flangrti.lib"); ++ CmdArgs.push_back("-linker"); ++ CmdArgs.push_back("/defaultlib:pgmath.lib"); ++ } ++ if (useOpenMP) { ++ CmdArgs.push_back("-linker"); ++ CmdArgs.push_back("/nodefaultlib:vcomp.lib"); ++ CmdArgs.push_back("-linker"); ++ CmdArgs.push_back("/nodefaultlib:vcompd.lib"); ++ CmdArgs.push_back("-linker"); ++ CmdArgs.push_back("/defaultlib:libomp.lib"); ++ } ++ ++ // Allways link Fortran executables with Pthreads ++ // CmdArgs.push_back("-lpthread"); ++ ++ // These options are added clang-cl in Clang.cpp for C/C++ ++ // In clang-cl.exe -MD and -MT control these options, but in ++ // flang.exe like clang.exe these are different options for ++ // dependency tracking. Let's assume that if somebody needs ++ // static flang libs, they don't need static C runtime libs. ++ // FIXME: Use LLVM_USE_CRT_ variable ++ // to use libcmt.lib or msvcrt.lib ++ CmdArgs.push_back("-linker"); ++ CmdArgs.push_back("/defaultlib:libcmt.lib"); ++} ++#endif ++ + void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const { + CudaInstallation.print(OS); + RocmInstallation.print(OS); +@@ -634,6 +713,42 @@ void MSVCToolChain::AddSystemIncludeWithSubfolder( + addSystemInclude(DriverArgs, CC1Args, path); + } + ++#ifdef ENABLE_CLASSIC_FLANG ++/// 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 MSVCToolChain::AddFlangSystemIncludeArgs(const ArgList &DriverArgs, ++ 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.c_str()); ++ AddFlangSysIncludeArg(DriverArgs, Flang1Args, IncludePathList); ++} ++#endif ++ + void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdinc)) +diff --git a/clang/lib/Driver/ToolChains/MSVC.h b/clang/lib/Driver/ToolChains/MSVC.h +index 0f687bc70ae4..46d5af9d114f 100644 +--- a/clang/lib/Driver/ToolChains/MSVC.h ++++ b/clang/lib/Driver/ToolChains/MSVC.h +@@ -84,6 +84,12 @@ public: + return VSLayout == llvm::ToolsetLayout::VS2017OrNewer; + } + ++#ifdef ENABLE_CLASSIC_FLANG ++ void ++ AddFlangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, ++ llvm::opt::ArgStringList &Flang1Args) const override; ++#endif ++ + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; +@@ -100,6 +106,11 @@ public: + void AddHIPRuntimeLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + ++#ifdef ENABLE_CLASSIC_FLANG ++ void AddFortranStdlibLibArgs(const llvm::opt::ArgList &Args, ++ llvm::opt::ArgStringList &CmdArgs) const override; ++#endif ++ + bool getWindowsSDKLibraryPath( + const llvm::opt::ArgList &Args, std::string &path) const; + bool getUniversalCRTLibraryPath(const llvm::opt::ArgList &Args, +diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp +index 503dbf3f0dea..264cc7ab06c8 100644 +--- a/clang/lib/Driver/ToolChains/MinGW.cpp ++++ b/clang/lib/Driver/ToolChains/MinGW.cpp +@@ -240,7 +240,11 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, + + if (C.getDriver().IsFlangMode()) { + addFortranRuntimeLibraryPath(TC, Args, CmdArgs); ++#ifdef ENABLE_CLASSIC_FLANG ++ addFortranRuntimeLibs(TC, Args, CmdArgs); ++#else + addFortranRuntimeLibs(TC, CmdArgs); ++#endif + } + + // TODO: Add profile stuff here +diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp +old mode 100644 +new mode 100755 +index 7d6308d757bc..a10c6e2c6c42 +--- a/clang/lib/Driver/Types.cpp ++++ b/clang/lib/Driver/Types.cpp +@@ -55,9 +55,11 @@ const char *types::getTypeName(ID Id) { + + types::ID types::getPreprocessedType(ID Id) { + ID PPT = getInfo(Id).PreprocessedType; ++#ifndef ENABLE_CLASSIC_FLANG + assert((getInfo(Id).Phases.contains(phases::Preprocess) != + (PPT == TY_INVALID)) && + "Unexpected Preprocess Type."); ++#endif + return PPT; + } + +@@ -134,6 +136,10 @@ bool types::isAcceptedByClang(ID Id) { + case TY_Asm: + case TY_C: case TY_PP_C: + case TY_CL: case TY_CLCXX: ++#ifdef ENABLE_CLASSIC_FLANG ++ case TY_F_FreeForm: case TY_PP_F_FreeForm: ++ case TY_F_FixedForm: case TY_PP_F_FixedForm: ++#endif + case TY_CUDA: case TY_PP_CUDA: + case TY_CUDA_DEVICE: + case TY_HIP: +@@ -164,12 +170,20 @@ bool types::isAcceptedByFlang(ID Id) { + default: + return false; + ++#ifdef ENABLE_CLASSIC_FLANG ++ case TY_F_FreeForm: ++ case TY_PP_F_FreeForm: ++ case TY_F_FixedForm: ++ case TY_PP_F_FixedForm: ++ return true; ++#else + case TY_Fortran: + case TY_PP_Fortran: + return true; + case TY_LLVM_IR: + case TY_LLVM_BC: + return true; ++#endif + } + } + +@@ -286,6 +300,22 @@ bool types::isHIP(ID Id) { + } + } + ++#ifdef ENABLE_CLASSIC_FLANG ++bool types::isFreeFormFortran(ID Id) { ++ if (!isAcceptedByFlang(Id)) ++ return false; ++ ++ return (Id == TY_F_FreeForm || Id == TY_PP_F_FreeForm); ++} ++ ++bool types::isFixedFormFortran(ID Id) { ++ if (!isAcceptedByFlang(Id)) ++ return false; ++ ++ return (Id == TY_F_FixedForm || Id == TY_PP_F_FixedForm); ++} ++#endif ++ + bool types::isHLSL(ID Id) { return Id == TY_HLSL; } + + bool types::isSrcFile(ID Id) { +@@ -296,8 +326,13 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) { + return llvm::StringSwitch(Ext) + .Case("c", TY_C) + .Case("C", TY_CXX) ++#ifdef ENABLE_CLASSIC_FLANG ++ .Case("F", TY_F_FixedForm) ++ .Case("f", TY_PP_F_FixedForm) ++#else + .Case("F", TY_Fortran) + .Case("f", TY_PP_Fortran) ++#endif + .Case("h", TY_CHeader) + .Case("H", TY_CXXHeader) + .Case("i", TY_PP_C) +@@ -331,6 +366,20 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) { + .Case("cui", TY_PP_CUDA) + .Case("cxx", TY_CXX) + .Case("CXX", TY_CXX) ++#ifdef ENABLE_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("F03", TY_Fortran) + .Case("f03", TY_PP_Fortran) + .Case("F08", TY_Fortran) +@@ -343,6 +392,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("hipi", TY_PP_HIP) +diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp +index f8fae82fba12..7b01cb01a45e 100644 +--- a/clang/lib/Frontend/InitPreprocessor.cpp ++++ b/clang/lib/Frontend/InitPreprocessor.cpp +@@ -161,26 +161,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, toString(MaxVal, 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/test/CMakeLists.txt b/clang/test/CMakeLists.txt +index 31b494f39cce..b88694deb818 100644 +--- a/clang/test/CMakeLists.txt ++++ b/clang/test/CMakeLists.txt +@@ -10,6 +10,7 @@ llvm_canonicalize_cmake_booleans( + CLANG_PLUGIN_SUPPORT + CLANG_SPAWN_CC1 + ENABLE_BACKTRACES ++ LLVM_ENABLE_CLASSIC_FLANG + LLVM_ENABLE_ZLIB + LLVM_ENABLE_ZSTD + LLVM_ENABLE_PER_TARGET_RUNTIME_DIR +diff --git a/clang/test/CodeGen/libpgmath-logfun-aarch64.ll b/clang/test/CodeGen/libpgmath-logfun-aarch64.ll +new file mode 100644 +index 000000000000..141fed29ccd1 +--- /dev/null ++++ b/clang/test/CodeGen/libpgmath-logfun-aarch64.ll +@@ -0,0 +1,58 @@ ++; REQUIRES: aarch64-registered-target ++ ++; RUN: %clang -target aarch64-unknown-linux-gnu -Ofast -S %s -o - | FileCheck %s ++ ++target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" ++ ++define void @fun_(i64* nocapture %z) local_unnamed_addr #0 { ++L.entry: ++ %0 = bitcast i64* %z to i8* ++ %1 = bitcast i64* %z to float* ++ %2 = load float, float* %1, align 4 ++ %3 = fpext float %2 to double ++ %4 = fadd double %3, 5.000000e-01 ++ %5 = tail call double @__pd_log_1(double %4) #1 ++ %6 = fptrunc double %5 to float ++ %7 = tail call float @__ps_exp_1(float %6) #2 ++ store float %7, float* %1, align 4 ++ %8 = getelementptr i8, i8* %0, i64 4 ++ %9 = bitcast i8* %8 to float* ++ %10 = load float, float* %9, align 4 ++ %11 = fpext float %10 to double ++ %12 = fadd double %11, 5.000000e-01 ++ %13 = tail call double @__pd_log_1(double %12) #1 ++ %14 = fptrunc double %13 to float ++ %15 = tail call float @__ps_exp_1(float %14) #2 ++ store float %15, float* %9, align 4 ++ %16 = getelementptr i64, i64* %z, i64 1 ++ %17 = bitcast i64* %16 to float* ++ %18 = load float, float* %17, align 4 ++ %19 = fpext float %18 to double ++ %20 = fadd double %19, 5.000000e-01 ++ %21 = tail call double @__pd_log_1(double %20) #1 ++ %22 = fptrunc double %21 to float ++ %23 = tail call float @__ps_exp_1(float %22) #2 ++ store float %23, float* %17, align 4 ++ %24 = getelementptr i8, i8* %0, i64 12 ++ %25 = bitcast i8* %24 to float* ++ %26 = load float, float* %25, align 4 ++ %27 = fpext float %26 to double ++ %28 = fadd double %27, 5.000000e-01 ++ %29 = tail call double @__pd_log_1(double %28) #1 ++ %30 = fptrunc double %29 to float ++ %31 = tail call float @__ps_exp_1(float %30) #2 ++ store float %31, float* %25, align 4 ++ ret void ++ ++; CHECK-NOT: __pd_log_4 ++; CHECK: __pd_log_2 ++; CHECK: __pd_log_2 ++} ++ ++; Function Attrs: nounwind readnone willreturn ++declare float @__ps_exp_1(float) #0 ++ ++; Function Attrs: nounwind readnone willreturn ++declare double @__pd_log_1(double) #0 ++ ++attributes #0 = { nounwind readnone willreturn } +diff --git a/clang/test/CodeGen/libpgmath-logfun-x86_64.ll b/clang/test/CodeGen/libpgmath-logfun-x86_64.ll +new file mode 100644 +index 000000000000..3ce1d910947f +--- /dev/null ++++ b/clang/test/CodeGen/libpgmath-logfun-x86_64.ll +@@ -0,0 +1,57 @@ ++; REQUIRES: x86-registered-target ++ ++; RUN: %clang -target x86_64-unknown-linux-gnu -msse -Ofast -S %s -o - | FileCheck %s ++ ++target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" ++ ++define void @fun_(i64* nocapture %z) local_unnamed_addr #0 { ++L.entry: ++ %0 = bitcast i64* %z to i8* ++ %1 = bitcast i64* %z to float* ++ %2 = load float, float* %1, align 4 ++ %3 = fpext float %2 to double ++ %4 = fadd double %3, 5.000000e-01 ++ %5 = tail call double @__pd_log_1(double %4) #1 ++ %6 = fptrunc double %5 to float ++ %7 = tail call float @__ps_exp_1(float %6) #2 ++ store float %7, float* %1, align 4 ++ %8 = getelementptr i8, i8* %0, i64 4 ++ %9 = bitcast i8* %8 to float* ++ %10 = load float, float* %9, align 4 ++ %11 = fpext float %10 to double ++ %12 = fadd double %11, 5.000000e-01 ++ %13 = tail call double @__pd_log_1(double %12) #1 ++ %14 = fptrunc double %13 to float ++ %15 = tail call float @__ps_exp_1(float %14) #2 ++ store float %15, float* %9, align 4 ++ %16 = getelementptr i64, i64* %z, i64 1 ++ %17 = bitcast i64* %16 to float* ++ %18 = load float, float* %17, align 4 ++ %19 = fpext float %18 to double ++ %20 = fadd double %19, 5.000000e-01 ++ %21 = tail call double @__pd_log_1(double %20) #1 ++ %22 = fptrunc double %21 to float ++ %23 = tail call float @__ps_exp_1(float %22) #2 ++ store float %23, float* %17, align 4 ++ %24 = getelementptr i8, i8* %0, i64 12 ++ %25 = bitcast i8* %24 to float* ++ %26 = load float, float* %25, align 4 ++ %27 = fpext float %26 to double ++ %28 = fadd double %27, 5.000000e-01 ++ %29 = tail call double @__pd_log_1(double %28) #1 ++ %30 = fptrunc double %29 to float ++ %31 = tail call float @__ps_exp_1(float %30) #2 ++ store float %31, float* %25, align 4 ++ ret void ++ ++; CHECK-NOT: __pd_log_1 ++; CHECK: __pd_log_4 ++} ++ ++; Function Attrs: nounwind readnone willreturn ++declare float @__ps_exp_1(float) #0 ++ ++; Function Attrs: nounwind readnone willreturn ++declare double @__pd_log_1(double) #0 ++ ++attributes #0 = { nounwind readnone willreturn } +diff --git a/clang/test/Driver/autocomplete.c b/clang/test/Driver/autocomplete.c +index d6f57708b67e..8c4921c9dbd5 100644 +--- a/clang/test/Driver/autocomplete.c ++++ b/clang/test/Driver/autocomplete.c +@@ -85,7 +85,7 @@ + // FVECLIBALL-NEXT: libmvec + // FVECLIBALL-NEXT: MASSV + // FVECLIBALL-NEXT: none +-// FVECLIBALL-NEXT: SLEEF ++// FVECLIBALL: SLEEF + // FVECLIBALL-NEXT: SVML + // RUN: %clang --autocomplete=-fshow-overloads= | FileCheck %s -check-prefix=FSOVERALL + // FSOVERALL: all +diff --git a/clang/test/Driver/emit-flang-attrs.f90 b/clang/test/Driver/emit-flang-attrs.f90 +new file mode 100644 +index 000000000000..df23a8aa6e87 +--- /dev/null ++++ b/clang/test/Driver/emit-flang-attrs.f90 +@@ -0,0 +1,58 @@ ++! REQUIRES: aarch64-registered-target ++! REQUIRES: classic_flang ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NEON %s ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-SVE %s ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+nosve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NOSVE %s ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve+nosve -c %s 2>&1 | FileCheck --check-prefix=CHECK-ATTRS-NOSVE %s ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2+nosve2 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-REVERT ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-aes -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-AES ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-sm4 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-SM4 ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-sha3 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-SHA3 ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-bitperm+nosve2-bitperm -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-BITPERM-REVERT ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-IMPLY ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+nosve+sve2 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-CONFLICT-REV ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve+sve2 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE-SVE2 ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-bitperm -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-BITPERM ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+nosve+sve2-aes -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE-SUBFEATURE-CONFLICT-REV ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-sm4+nosve2 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-SUBFEATURE-CONFLICT ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-bitperm+nosve2-aes -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-SUBFEATURE-MIX ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-sm4+nosve2-sm4 -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-SM4-REVERT ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-sha3+nosve2-sha3 %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-SHA3-REVERT ++! RUN: %flang -### -target aarch64-linux-gnu -march=armv8-a+sve2-aes+nosve2-aes %s 2>&1 | FileCheck %s --check-prefix=CHECK-SVE2-AES-REVERT ++ ++! CHECK-ATTRS-NEON: "{{.*}}flang2" ++! CHECK-ATTRS-NEON-SAME: "-target_features" "+neon,+v8a" ++! CHECK-ATTRS-SVE: "{{.*}}flang2" ++! CHECK-ATTRS-SVE-SAME: "-target_features" "+neon,+v8a,+sve" ++! CHECK-ATTRS-NOSVE: "{{.*}}flang2" ++! CHECK-ATTRS-NOSVE-SAME: "-target_features" "+neon,+v8a,-sve,-sve2,-sve2-bitperm,-sve2-sha3,-sve2-aes,-sve2-sm4" ++! CHECK-SVE2-REVERT: "{{.*}}flang2" ++! CHECK-SVE2-REVERT-SAME: "-target_features" "+neon,+v8a,+sve,-sve2,-sve2-bitperm,-sve2-sha3,-sve2-aes,-sve2-sm4" ++! CHECK-SVE2-AES: "{{.*}}flang2" ++! CHECK-SVE2-AES-SAME: "-target_features" "+neon,+v8a,+sve2-aes,+sve,+sve2" ++! CHECK-SVE2-SM4: "{{.*}}flang2" ++! CHECK-SVE2-SM4-SAME: "-target_features" "+neon,+v8a,+sve2-sm4,+sve,+sve2" ++! CHECK-SVE2-SHA3: "{{.*}}flang2" ++! CHECK-SVE2-SHA3-SAME: "-target_features" "+neon,+v8a,+sve2-sha3,+sve,+sve2" ++! CHECK-SVE2-BITPERM-REVERT: "{{.*}}flang2" ++! CHECK-SVE2-BITPERM-REVERT-SAME: "-target_features" "+neon,+v8a,+sve,+sve2,-sve2-bitperm" ++! CHECK-SVE2-IMPLY: "{{.*}}flang2" ++! CHECK-SVE2-IMPLY-SAME: "-target_features" "+neon,+v8a,+sve2,+sve" ++! CHECK-SVE2-CONFLICT-REV: "{{.*}}flang2" ++! CHECK-SVE2-CONFLICT-REV-SAME: "-target_features" "+neon,+v8a,-sve2-bitperm,-sve2-sha3,-sve2-aes,-sve2-sm4,+sve2,+sve" ++! CHECK-SVE-SVE2: "{{.*}}flang2" ++! CHECK-SVE-SVE2-SAME: "-target_features" "+neon,+v8a,+sve2,+sve" ++! CHECK-SVE2-BITPERM: "{{.*}}flang2" ++! CHECK-SVE2-BITPERM-SAME: "-target_features" "+neon,+v8a,+sve2-bitperm,+sve,+sve2" ++! CHECK-SVE-SUBFEATURE-CONFLICT-REV: "{{.*}}flang2" ++! CHECK-SVE-SUBFEATURE-CONFLICT-REV-SAME: "-target_features" "+neon,+v8a,-sve2-bitperm,-sve2-sha3,-sve2-sm4,+sve2-aes,+sve,+sve2" ++! CHECK-SVE2-SUBFEATURE-CONFLICT: "{{.*}}flang2" ++! CHECK-SVE2-SUBFEATURE-CONFLICT-SAME: "-target_features" "+neon,+v8a,+sve,-sve2,-sve2-bitperm,-sve2-sha3,-sve2-aes,-sve2-sm4" ++! CHECK-SVE2-SUBFEATURE-MIX: "{{.*}}flang2" ++! CHECK-SVE2-SUBFEATURE-MIX-SAME: "-target_features" "+neon,+v8a,+sve2-bitperm,+sve,+sve2,-sve2-aes" ++! CHECK-SVE2-SM4-REVERT: "{{.*}}flang2" ++! CHECK-SVE2-SM4-REVERT-SAME: "-target_features" "+neon,+v8a,+sve,+sve2,-sve2-sm4" ++! CHECK-SVE2-SHA3-REVERT: "{{.*}}flang2" ++! CHECK-SVE2-SHA3-REVERT-SAME: "-target_features" "+neon,+v8a,+sve,+sve2,-sve2-sha3" ++! CHECK-SVE2-AES-REVERT: "{{.*}}flang2" ++! CHECK-SVE2-AES-REVERT-SAME: "-target_features" "+neon,+v8a,+sve,+sve2,-sve2-aes" +diff --git a/clang/test/Driver/flang/Inputs/llvm-ir-input.ll b/clang/test/Driver/flang/Inputs/llvm-ir-input.ll +new file mode 100644 +index 000000000000..e69de29bb2d1 +diff --git a/clang/test/Driver/flang/classic-flang-emit-flang-llvm.f95 b/clang/test/Driver/flang/classic-flang-emit-flang-llvm.f95 +new file mode 100644 +index 000000000000..225207c85db7 +--- /dev/null ++++ b/clang/test/Driver/flang/classic-flang-emit-flang-llvm.f95 +@@ -0,0 +1,10 @@ ++! REQUIRES: classic_flang ++ ++! Check that the -emit-flang-llvm option dumps LLVM IR pre-optimisation ++ ++! RUN: %clang --driver-mode=flang -emit-flang-llvm -S -o %t.ll %s -### 2>&1 \ ++! RUN: | FileCheck %s ++! CHECK-NOT: argument unused during compilation: '-S' ++! CHECK: "{{.*}}flang1" ++! CHECK-NEXT: "{{.*}}flang2" ++! CHECK-NOT: "{{.*}}clang{{.*}}" "-cc1" +diff --git a/clang/test/Driver/flang/classic-flang-fp-contract.f95 b/clang/test/Driver/flang/classic-flang-fp-contract.f95 +new file mode 100644 +index 000000000000..b181065d1cac +--- /dev/null ++++ b/clang/test/Driver/flang/classic-flang-fp-contract.f95 +@@ -0,0 +1,27 @@ ++! REQUIRES: classic_flang ++ ++! RUN: %flang -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE ++! RUN: %flang -O1 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT ++! RUN: %flang -O2 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT ++! RUN: %flang -O3 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT ++! RUN: %flang -Ofast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT ++! RUN: %flang -ffp-contract=fast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE ++! RUN: %flang -O1 -ffp-contract=fast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT ++! RUN: %flang -O2 -ffp-contract=fast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT ++! RUN: %flang -O3 -ffp-contract=fast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT ++! RUN: %flang -Ofast -ffp-contract=fast -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT ++! RUN: %flang -ffp-contract=on -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE ++! RUN: %flang -O1 -ffp-contract=on -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT ++! RUN: %flang -O2 -ffp-contract=on -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT ++! RUN: %flang -O3 -ffp-contract=on -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT ++! RUN: %flang -Ofast -ffp-contract=on -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT ++! RUN: %flang -ffp-contract=off -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE ++! RUN: %flang -O1 -ffp-contract=off -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE ++! RUN: %flang -O2 -ffp-contract=off -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE ++! RUN: %flang -O3 -ffp-contract=off -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE ++! RUN: %flang -Ofast -ffp-contract=off -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FLANG2-FP-CONTRACT-ABSENCE ++ ++! CHECK-FLANG2-FP-CONTRACT: "{{.*}}flang2" ++! CHECK-FLANG2-FP-CONTRACT-SAME: "-x" "172" "0x40000000" "-x" "179" "1" "-x" "216" "0x1000" ++! CHECK-FLANG2-FP-CONTRACT-ABSENCE: "{{.*}}flang2" ++! CHECK-FLANG2-FP-CONTRACT-ABSENCE-SAME: "-x" "171" "0x40000000" "-x" "178" "1" +diff --git a/clang/test/Driver/flang/classic-flang-must-preprocess.F b/clang/test/Driver/flang/classic-flang-must-preprocess.F +new file mode 100644 +index 000000000000..d52c1cf8d3c0 +--- /dev/null ++++ b/clang/test/Driver/flang/classic-flang-must-preprocess.F +@@ -0,0 +1,12 @@ ++! REQUIRES: classic_flang ++ ++! Check that the driver invokes flang1 correctly for fixed-form Fortran code ++! which requires preprocessing. ++ ++! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \ ++! RUN: | FileCheck %s ++! CHECK: "flang1" ++! CHECK-SAME: "-preprocess" ++! CHECK-SAME: "-nofreeform" ++! CHECK-NEXT: "flang2" ++! CHECK-NEXT: {{clang.* "-cc1"}} +diff --git a/clang/test/Driver/flang/classic-flang-must-preprocess.F95 b/clang/test/Driver/flang/classic-flang-must-preprocess.F95 +new file mode 100644 +index 000000000000..7d452a535784 +--- /dev/null ++++ b/clang/test/Driver/flang/classic-flang-must-preprocess.F95 +@@ -0,0 +1,12 @@ ++! REQUIRES: classic_flang ++ ++! Check that the driver invokes flang1 correctly for free-form Fortran code ++! which requires preprocessing. ++ ++! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \ ++! RUN: | FileCheck %s ++! CHECK: "flang1" ++! CHECK-SAME: "-preprocess" ++! CHECK-SAME: "-freeform" ++! CHECK-NEXT: "flang2" ++! CHECK-NEXT: {{clang.* "-cc1"}} +diff --git a/clang/test/Driver/flang/classic-flang-version.f b/clang/test/Driver/flang/classic-flang-version.f +new file mode 100644 +index 000000000000..c2082d3af8b7 +--- /dev/null ++++ b/clang/test/Driver/flang/classic-flang-version.f +@@ -0,0 +1,3 @@ ++! REQUIRES: classic-flang ++! RUN: %flang --version | FileCheck %s ++! CHECK: flang version {{.*}} ({{.*}}flang-compiler/classic-flang-llvm-project.git {{.*}}) +diff --git a/clang/test/Driver/flang/classic-flang-vscale-mbits.f95 b/clang/test/Driver/flang/classic-flang-vscale-mbits.f95 +new file mode 100644 +index 000000000000..f0ed43aa027a +--- /dev/null ++++ b/clang/test/Driver/flang/classic-flang-vscale-mbits.f95 +@@ -0,0 +1,28 @@ ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve -msve-vector-bits=128 %s 2>&1 | FileCheck -check-prefix=CHECK-SVE-128 %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve -msve-vector-bits=128+ %s 2>&1 | FileCheck -check-prefix=CHECK-SVE-128PLUS %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve -msve-vector-bits=256 %s 2>&1 | FileCheck -check-prefix=CHECK-SVE-256 %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve -msve-vector-bits=256+ %s 2>&1 | FileCheck -check-prefix=CHECK-SVE-256PLUS %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve2 -msve-vector-bits=512 %s 2>&1 | FileCheck -check-prefix=CHECK-SVE2-512 %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve2 -msve-vector-bits=512+ %s 2>&1 | FileCheck -check-prefix=CHECK-SVE2-512PLUS %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve2-sha3 -msve-vector-bits=2048 %s 2>&1 | FileCheck -check-prefix=CHECK-SVE2SHA3-2048 %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve2-sha3 -msve-vector-bits=2048+ %s 2>&1 | FileCheck -check-prefix=CHECK-SVE2SHA3-2048PLUS %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve2 -msve-vector-bits=scalable %s 2>&1 | FileCheck -check-prefix=CHECK-SVE2-SCALABLE %s ++ ++// CHECK-SVE-128: "-target_features" "+neon,+v8a,+sve" ++// CHECK-SVE-128-DAG: "-vscale_range_min" "1" "-vscale_range_max" "1" ++// CHECK-SVE-128PLUS: "-target_features" "+neon,+v8a,+sve" ++// CHECK-SVE-128PLUS-DAG: "-vscale_range_min" "1" "-vscale_range_max" "0" ++// CHECK-SVE-256: "-target_features" "+neon,+v8a,+sve" ++// CHECK-SVE-256-DAG: "-vscale_range_min" "2" "-vscale_range_max" "2" ++// CHECK-SVE-256PLUS: "-target_features" "+neon,+v8a,+sve" ++// CHECK-SVE-256PLUS-DAG: "-vscale_range_min" "2" "-vscale_range_max" "0" ++// CHECK-SVE2-512: "-target_features" "+neon,+v8a,+sve2,+sve" ++// CHECK-SVE2-512-DAG: "-vscale_range_min" "4" "-vscale_range_max" "4" ++// CHECK-SVE2-512PLUS: "-target_features" "+neon,+v8a,+sve2,+sve" ++// CHECK-SVE2-512PLUS-DAG: "-vscale_range_min" "4" "-vscale_range_max" "0" ++// CHECK-SVE2SHA3-2048: "-target_features" "+neon,+v8a,+sve2-sha3,+sve,+sve2" ++// CHECK-SVE2SHA3-2048-DAG: "-vscale_range_min" "16" "-vscale_range_max" "16" ++// CHECK-SVE2SHA3-2048PLUS: "-target_features" "+neon,+v8a,+sve2-sha3,+sve,+sve2" ++// CHECK-SVE2SHA3-2048PLUS-DAG: "-vscale_range_min" "16" "-vscale_range_max" "0" ++// CHECK-SVE2-SCALABLE: "-target_features" "+neon,+v8a,+sve2,+sve" ++// CHECK-SVE2-SCALABLE-DAG: "-vscale_range_min" "1" "-vscale_range_max" "16" +diff --git a/clang/test/Driver/flang/classic-flang-vscale.f95 b/clang/test/Driver/flang/classic-flang-vscale.f95 +new file mode 100644 +index 000000000000..8110be594db5 +--- /dev/null ++++ b/clang/test/Driver/flang/classic-flang-vscale.f95 +@@ -0,0 +1,28 @@ ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a %s 2>&1 | FileCheck -check-prefix=CHECK-NEON %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve %s 2>&1 | FileCheck -check-prefix=CHECK-SVE %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve2 %s 2>&1 | FileCheck -check-prefix=CHECK-SVE2 %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve2-sha3 %s 2>&1 | FileCheck -check-prefix=CHECK-SVE2SHA3 %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve+nosve %s 2>&1 | FileCheck -check-prefix=CHECK-SVE-NOSVE %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve2+nosve2-sha3 %s 2>&1 | FileCheck -check-prefix=CHECK-SVE2-NOSVE2SHA3 %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve2-sha3+nosve2 %s 2>&1 | FileCheck -check-prefix=CHECK-SVE2SHA3-NOSVE2 %s ++// RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve2-sha3+nosve %s 2>&1 | FileCheck -check-prefix=CHECK-SVE2SHA3-NOSVE %s ++ ++// CHECK-NEON: "-target_features" "+neon,+v8a" ++// CHECK-NEON-NOT: "-vscale_range_min" ++// CHECK-NEON-NOT: "-vscale_range_max" ++// CHECK-SVE: "-target_features" "+neon,+v8a,+sve" ++// CHECK-SVE-DAG: "-vscale_range_min" "1" "-vscale_range_max" "16" ++// CHECK-SVE2: "-target_features" "+neon,+v8a,+sve2,+sve" ++// CHECK-SVE2-DAG: "-vscale_range_min" "1" "-vscale_range_max" "16" ++// CHECK-SVE2SHA3: "-target_features" "+neon,+v8a,+sve2-sha3,+sve,+sve2" ++// CHECK-SVE2SHA3-DAG: "-vscale_range_min" "1" "-vscale_range_max" "16" ++// CHECK-SVE-NOSVE: "-target_features" "+neon,+v8a,-sve,-sve2,-sve2-bitperm,-sve2-sha3,-sve2-aes,-sve2-sm4" ++// CHECK-SVE-NOSVE-NOT: "-vscale_range_min" ++// CHECK-SVE-NOSVE-NOT: "-vscale_range_max" ++// CHECK-SVE2-NOSVE2SHA3: "-target_features" "+neon,+v8a,+sve2,+sve,-sve2-sha3" ++// CHECK-SVE2-NOSVE2SHA3-DAG: "-vscale_range_min" "1" "-vscale_range_max" "16" ++// CHECK-SVE2SHA3-NOSVE2: "-target_features" "+neon,+v8a,+sve,-sve2,-sve2-bitperm,-sve2-sha3,-sve2-aes,-sve2-sm4" ++// CHECK-SVE2SHA3-NOSVE2-DAG: "-vscale_range_min" "1" "-vscale_range_max" "16" ++// CHECK-SVE2SHA3-NOSVE: "-target_features" "+neon,+v8a,-sve,-sve2,-sve2-bitperm,-sve2-sha3,-sve2-aes,-sve2-sm4" ++// CHECK-SVE2SHA3-NOSVE-NOT: "-vscale_range_min" ++// CHECK-SVE2SHA3-NOSVE-NOT: "-vscale_range_max" +diff --git a/clang/test/Driver/flang/classic-flang.f b/clang/test/Driver/flang/classic-flang.f +new file mode 100644 +index 000000000000..98f74d9626d7 +--- /dev/null ++++ b/clang/test/Driver/flang/classic-flang.f +@@ -0,0 +1,26 @@ ++! REQUIRES: classic_flang ++ ++! Check that the driver invokes flang1 correctly for preprocessed fixed-form ++! Fortran code. ++ ++! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \ ++! RUN: | FileCheck %s ++! CHECK: "flang1" ++! CHECK-NOT: "-preprocess" ++! CHECK-SAME: "-nofreeform" ++! CHECK-NEXT: "flang2" ++! CHECK-NEXT: {{clang.* "-cc1"}} ++ ++! Check that the driver invokes flang1 correctly when preprocessing is ++! explicitly requested. ++ ++! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -E %s -### 2>&1 \ ++! RUN: | FileCheck --check-prefix=CHECK-PREPROCESS %s ++! CHECK-PREPROCESS: "flang1" ++! CHECK-PREPROCESS-SAME: "-preprocess" ++! CHECK-PREPROCESS-SAME: "-es" ++! CHECK-PREPROCESS-SAME: "-pp" ++! CHECK-PREPROCESS-NOT: "flang1" ++! CHECK-PREPROCESS-NOT: "flang2" ++! CHECK-PREPROCESS-NOT: {{clang.* "-cc1"}} ++! CHECK-PREPROCESS-NOT: {{clang.* "-cc1as"}} +diff --git a/clang/test/Driver/flang/classic-flang.f95 b/clang/test/Driver/flang/classic-flang.f95 +new file mode 100644 +index 000000000000..3350bd45550f +--- /dev/null ++++ b/clang/test/Driver/flang/classic-flang.f95 +@@ -0,0 +1,120 @@ ++! REQUIRES: classic_flang ++ ++! Check that the driver invokes flang1 correctly for preprocessed free-form ++! Fortran code. Also check that the backend is invoked correctly. ++ ++! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \ ++! RUN: | FileCheck --check-prefix=CHECK-OBJECT %s ++! CHECK-OBJECT: "flang1" ++! CHECK-OBJECT-NOT: "-preprocess" ++! CHECK-OBJECT-SAME: "-freeform" ++! CHECK-OBJECT-NEXT: "flang2" ++! CHECK-OBJECT-SAME: "-asm" [[LLFILE:.*.ll]] ++! CHECK-OBJECT-NEXT: {{clang.* "-cc1"}} ++! CHECK-OBJECT-SAME: "-o" "classic-flang.o" ++! CHECK-OBJECT-SAME: "-x" "ir" ++! CHECK-OBJECT-SAME: [[LLFILE]] ++ ++! Check that the driver invokes flang1 correctly when preprocessing is ++! explicitly requested. ++ ++! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -E %s -### 2>&1 \ ++! RUN: | FileCheck --check-prefix=CHECK-PREPROCESS %s ++! CHECK-PREPROCESS: "flang1" ++! CHECK-PREPROCESS-SAME: "-preprocess" ++! CHECK-PREPROCESS-SAME: "-es" ++! CHECK-PREPROCESS-SAME: "-pp" ++! CHECK-PREPROCESS-NOT: "flang1" ++! CHECK-PREPROCESS-NOT: "flang2" ++! CHECK-PREPROCESS-NOT: {{clang.* "-cc1"}} ++! CHECK-PREPROCESS-NOT: {{clang.* "-cc1as"}} ++ ++! Check that the backend job (clang -cc1) is not combined into the compile job ++! (flang2) even if -integrated-as is specified. ++ ++! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -integrated-as -S %s -### 2>&1 \ ++! RUN: | FileCheck --check-prefix=CHECK-ASM %s ++! CHECK-ASM: "flang1" ++! CHECK-ASM-NEXT: "flang2" ++! CHECK-ASM-SAME: "-asm" [[LLFILE:.*.ll]] ++! CHECK-ASM-NEXT: {{clang.* "-cc1"}} ++! CHECK-ASM-SAME: "-o" "classic-flang.s" ++! CHECK-ASM-SAME: "-x" "ir" ++! CHECK-ASM-SAME: [[LLFILE]] ++ ++! Check that the linker job is given the correct libraries and library paths. ++ ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -mp \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-MAIN,CHECK-DYNAMIC-FLANG,CHECK-DYNAMIC-OMP %s ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -mp -nomp \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-MAIN,CHECK-DYNAMIC-FLANG,CHECK-NO-OMP %s ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -fopenmp \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-MAIN,CHECK-DYNAMIC-FLANG,CHECK-DYNAMIC-OMP %s ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -fopenmp -fno-openmp \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-MAIN,CHECK-DYNAMIC-FLANG,CHECK-NO-OMP %s ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -fopenmp -static-openmp \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-MAIN,CHECK-DYNAMIC-FLANG,CHECK-STATIC-OMP %s ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -fopenmp -static-flang-libs \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-MAIN,CHECK-STATIC-FLANG,CHECK-DYNAMIC-OMP %s ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -static-flang-libs \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-MAIN,CHECK-STATIC-FLANG,CHECK-NO-OMP %s ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -Mnomain \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-NOMAIN,CHECK-DYNAMIC-FLANG %s ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -fno-fortran-main \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-NOMAIN,CHECK-DYNAMIC-FLANG %s ++! CHECK-LD: "{{.*}}ld{{(.exe)?}}" ++! CHECK-LD-NOT: "-static" ++! CHECK-LD-SAME: "{{[^"]*}}classic-flang-{{[^ ]*}}.o" ++! CHECK-MAIN-SAME: "-lflangmain" ++! CHECK-NOMAIN-NOT: "-lflangmain" ++! CHECK-LD-SAME: "-lfoo" "-L{{[^ ]*[/\\]+}}basic_linux_tree{{[/\\]+}}usr{{[/\\]+}}lib" ++! CHECK-DYNAMIC-FLANG-NOT: "-Bstatic" ++! CHECK-DYNAMIC-FLANG: "-lflang" "-lflangrti" "-lpgmath" "-lpthread" "-lrt" "-lm" ++! CHECK-DYNAMIC-FLANG-NOT: "-Bdynamic" ++! CHECK-STATIC-FLANG: "-Bstatic" "-lflang" "-lflangrti" "-lpgmath" "-Bdynamic" "-lpthread" "-lrt" "-lm" ++! CHECK-DYNAMIC-OMP-NOT: "-Bstatic" ++! CHECK-DYNAMIC-OMP: "-lomp" "-L{{[^ ]*[/\\]+}}basic_linux_tree{{[/\\]+}}usr{{[/\\]+}}lib" ++! CHECK-DYNAMIC-OMP-NOT: "-Bdynamic" ++! CHECK-STATIC-OMP: "-Bstatic" "-lomp" "-Bdynamic" "-L{{[^ ]*[/\\]+}}basic_linux_tree{{[/\\]+}}usr{{[/\\]+}}lib" ++! CHECK-NO-OMP-NOT: "-lomp" ++ ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -static -static-flang-libs \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD-STATIC,CHECK-NO-OMP %s ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -static -fopenmp \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD-STATIC,CHECK-STATIC-BOTH %s ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -static -fopenmp -static-openmp \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-LD-STATIC,CHECK-STATIC-BOTH %s ++! CHECK-LD-STATIC: "{{.*}}ld{{(.exe)?}}" ++! CHECK-LD-STATIC: "-static" "-o" "a.out" ++! CHECK-LD-STATIC: "{{[^"]*}}classic-flang-{{[^ ]*}}.o" "-lflangmain" "-lfoo" "-L{{[^ ]*[/\\]+}}basic_linux_tree{{[/\\]+}}usr{{[/\\]+}}lib" ++! CHECK-LD-STATIC-NOT: "-Bstatic" ++! CHECK-LD-STATIC: "-lflang" "-lflangrti" "-lpgmath" "-lpthread" "-lrt" "-lm" ++! CHECK-LD-STATIC-NOT: "-Bdynamic" ++! CHECK-STATIC-BOTH-NOT: "-Bstatic" ++! CHECK-STATIC-BOTH: "-lomp" ++! CHECK-STATIC-BOTH-NOT: "-Bdynamic" ++ ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -no-flang-libs \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-NOFLANGLIBS %s ++! CHECK-NOFLANGLIBS: "{{.*}}ld{{(.exe)?}}" ++! CHECK-NOFLANGLIBS-SAME: "{{[^"]*}}classic-flang-{{[^ ]*}}.o" ++! CHECK-NOFLANGLIBS-NOT: "-lflangmain" ++! CHECK-NOFLANGLIBS-SAME: "-lfoo" "-L{{[^ ]*[/\\]+}}basic_linux_tree{{[/\\]+}}usr{{[/\\]+}}lib" ++! CHECK-NOFLANGLIBS-NOT: "-lflang" "-lflangrti" "-lpgmath" ++! CHECK-NOFLANGLIBS: "-lm" "-lgcc" ++! CHECK-NOFLANGLIBS: "-lgcc_s" ++! CHECK-NOFLANGLIBS: "-lc" ++ ++! In Flang mode, we always link with libm, even with -nostdlib. ++! RUN: %flang -target x86_64-linux-gnu -ccc-install-dir %S/../Inputs/basic_linux_tree/usr/bin -nostdlib \ ++! RUN: %s -lfoo -### 2>&1 | FileCheck --check-prefixes=CHECK-NOSTDLIB %s ++! CHECK-NOSTDLIB: "{{.*}}ld{{(.exe)?}}" ++! CHECK-NOSTDLIB-SAME: "{{[^"]*}}classic-flang-{{[^ ]*}}.o" ++! CHECK-NOSTDLIB-NOT: "-lflangmain" ++! CHECK-NOSTDLIB-SAME: "-lfoo" "-L{{[^ ]*[/\\]+}}basic_linux_tree{{[/\\]+}}usr{{[/\\]+}}lib" ++! CHECK-NOSTDLIB-NOT: "-lflang" "-lflangrti" "-lpgmath" ++! CHECK-NOSTDLIB-NOT: "-lpthread" "-lrt" ++! CHECK-NOSTDLIB: "-lm" ++! CHECK-NOSTDLIB-NOT: "-lgcc" ++! CHECK-NOSTDLIB-NOT: "-lgcc_s" ++! CHECK-NOSTDLIB-NOT: "-lc" +diff --git a/clang/test/Driver/flang/flang.f90 b/clang/test/Driver/flang/flang.f90 +index 5d8edf6308b0..8caa45f6342c 100644 +--- a/clang/test/Driver/flang/flang.f90 ++++ b/clang/test/Driver/flang/flang.f90 +@@ -1,5 +1,7 @@ + ! Check that flang -fc1 is invoked when in --driver-mode=flang. + ++! UNSUPPORTED: classic_flang ++ + ! This is a copy of flang_ucase.F90 because the driver has logic in it which + ! differentiates between F90 and f90 files. Flang will not treat these files + ! differently. +diff --git a/clang/test/Driver/flang/flang_ucase.F90 b/clang/test/Driver/flang/flang_ucase.F90 +index 50305ee337e1..21f7c469144b 100644 +--- a/clang/test/Driver/flang/flang_ucase.F90 ++++ b/clang/test/Driver/flang/flang_ucase.F90 +@@ -1,5 +1,7 @@ + ! Check that flang -fc1 is invoked when in --driver-mode=flang. + ++! UNSUPPORTED: classic_flang ++ + ! This is a copy of flang.f90 because the driver has logic in it which + ! differentiates between F90 and f90 files. Flang will not treat these files + ! differently. +diff --git a/clang/test/Driver/flang/llvm-ir-input.f b/clang/test/Driver/flang/llvm-ir-input.f +new file mode 100644 +index 000000000000..c34bf28328cb +--- /dev/null ++++ b/clang/test/Driver/flang/llvm-ir-input.f +@@ -0,0 +1,7 @@ ++! Check that LLVM IR input is passed to clang instead of flang1. ++ ++! REQUIRES: classic_flang ++! RUN: %clang --driver-mode=flang -S %S/Inputs/llvm-ir-input.ll -### 2>&1 | FileCheck %s ++ ++! CHECK-NOT: flang1 ++! CHECK: "{{.*}}clang{{.*}}" "-cc1" +diff --git a/clang/test/Driver/flang/multiple-inputs-mixed.f90 b/clang/test/Driver/flang/multiple-inputs-mixed.f90 +index 2395dbecf1fe..8f3918f7cb21 100644 +--- a/clang/test/Driver/flang/multiple-inputs-mixed.f90 ++++ b/clang/test/Driver/flang/multiple-inputs-mixed.f90 +@@ -1,5 +1,7 @@ + ! Check that flang can handle mixed C and fortran inputs. + ++! UNSUPPORTED: classic_flang ++ + ! RUN: %clang --driver-mode=flang -### -fsyntax-only %S/Inputs/one.f90 %S/Inputs/other.c 2>&1 | FileCheck --check-prefixes=CHECK-SYNTAX-ONLY %s + ! CHECK-SYNTAX-ONLY-LABEL: "{{[^"]*}}flang-new{{[^"/]*}}" "-fc1" + ! CHECK-SYNTAX-ONLY: "{{[^"]*}}/Inputs/one.f90" +diff --git a/clang/test/Driver/flang/multiple-inputs.f90 b/clang/test/Driver/flang/multiple-inputs.f90 +index ada999e927a6..4068ac3a0966 100644 +--- a/clang/test/Driver/flang/multiple-inputs.f90 ++++ b/clang/test/Driver/flang/multiple-inputs.f90 +@@ -1,5 +1,7 @@ + ! Check that flang driver can handle multiple inputs at once. + ++! UNSUPPORTED: classic_flang ++ + ! RUN: %clang --driver-mode=flang -### -fsyntax-only %S/Inputs/one.f90 %S/Inputs/two.f90 2>&1 | FileCheck --check-prefixes=CHECK-SYNTAX-ONLY %s + ! CHECK-SYNTAX-ONLY-LABEL: "{{[^"]*}}flang-new{{[^"/]*}}" "-fc1" + ! CHECK-SYNTAX-ONLY: "{{[^"]*}}/Inputs/one.f90" +diff --git a/clang/test/Driver/flang/reassoc.f90 b/clang/test/Driver/flang/reassoc.f90 +new file mode 100644 +index 000000000000..fe42087f7070 +--- /dev/null ++++ b/clang/test/Driver/flang/reassoc.f90 +@@ -0,0 +1,59 @@ ++! REQUIRES: classic_flang ++ ++! Tests for flags which generate nsw, reassoc attributes ++ ++! RUN: %flang -Kieee %s -### 2>&1 | FileCheck --check-prefixes=IEEE,NO_FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -Knoieee %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -ffast-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -fno-fast-math %s -### 2>&1 | FileCheck --check-prefixes=NO_FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -frelaxed-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -fassociative-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,NO_RELAXED,REASSOC_NSZ %s ++! RUN: %flang -fno-associative-math %s -### 2>&1 | FileCheck --check-prefixes=NO_FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -fsigned-zeros %s -### 2>&1 | FileCheck --check-prefixes=NO_FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -fno-signed-zeros %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,NO_RELAXED,NO_REASSOC,NSZ %s ++ ++! RUN: %flang -fno-associative-math -fno-signed-zeros %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,NO_RELAXED,NO_REASSOC,NSZ %s ++! RUN: %flang -fno-associative-math -fsigned-zeros %s -### 2>&1 | FileCheck --check-prefixes=NO_FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -fassociative-math -fno-signed-zeros %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,NO_RELAXED,REASSOC_NSZ %s ++! RUN: %flang -fassociative-math -fsigned-zeros %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++ ++! RUN: %flang -Kieee -fassociative-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,NO_RELAXED,REASSOC_NSZ %s ++! RUN: %flang -Kieee -fno-associative-math %s -### 2>&1 | FileCheck --check-prefixes=IEEE,NO_FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -Kieee -fsigned-zeros %s -### 2>&1 | FileCheck --check-prefixes=IEEE,NO_FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -Kieee -fno-signed-zeros %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,NO_RELAXED,NO_REASSOC,NSZ %s ++! RUN: %flang -ffast-math -fassociative-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_RELAXED,REASSOC_NSZ %s ++! RUN: %flang -ffast-math -fno-associative-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -ffast-math -fsigned-zeros %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -ffast-math -fno-signed-zeros %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_RELAXED,NO_REASSOC,NSZ %s ++! RUN: %flang -frelaxed-math -fassociative-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,REASSOC_NSZ %s ++! RUN: %flang -frelaxed-math -fno-associative-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -frelaxed-math -fsigned-zeros %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -frelaxed-math -fno-signed-zeros %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,NO_REASSOC,NSZ %s ++ ++! RUN: %flang -fassociative-math -Kieee %s -### 2>&1 | FileCheck --check-prefixes=IEEE,NO_FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -fno-associative-math -Kieee %s -### 2>&1 | FileCheck --check-prefixes=IEEE,NO_FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -fsigned-zeros -Kieee %s -### 2>&1 | FileCheck --check-prefixes=IEEE,NO_FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -fno-signed-zeros -Kieee %s -### 2>&1 | FileCheck --check-prefixes=IEEE,NO_FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -fassociative-math -ffast-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_RELAXED,REASSOC_NSZ %s ++! RUN: %flang -fno-associative-math -ffast-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -fsigned-zeros -ffast-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,FAST,NO_RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -fno-signed-zeros -ffast-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_RELAXED,NO_REASSOC,NSZ %s ++! RUN: %flang -fassociative-math -frelaxed-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,REASSOC_NSZ %s ++! RUN: %flang -fno-associative-math -frelaxed-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -fsigned-zeros -frelaxed-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,RELAXED,NO_REASSOC,NO_NSZ %s ++! RUN: %flang -fno-signed-zeros -frelaxed-math %s -### 2>&1 | FileCheck --check-prefixes=NO_IEEE,NO_FAST,NO_REASSOC,NSZ %s ++ ++! IEEE: {{.*}}flang2{{.*}} "-ieee" "1" ++! NO_IEEE-NOT: {{.*}}flang2{{.*}} "-ieee" "1" ++ ++! FAST: {{.*}}flang2{{.*}} "-x" "216" "1" ++! NO_FAST-NOT: {{.*}}flang2{{.*}} "-x" "216" "1" ++ ++! RELAXED: {{.*}}flang2{{.*}} "-x" "15" "0x400" ++! NO_RELAXED-NOT: {{.*}}flang2{{.*}} "-x" "15" "0x400" ++ ++! REASSOC_NSZ: {{.*}}flang2{{.*}} "-x" "216" "0x8" "-x" "216" "0x10" ++! NO_REASSOC-NOT: {{.*}}flang2{{.*}} "-x" "216" "0x10" ++ ++! NSZ: {{.*}}flang2{{.*}} "-x" "216" "0x8" ++! NO_NSZ-NOT: {{.*}}flang2{{.*}} "-x" "216" "0x8" +diff --git a/clang/test/Driver/fortran-phases.f90 b/clang/test/Driver/fortran-phases.f90 +new file mode 100644 +index 000000000000..57d5f2c92b78 +--- /dev/null ++++ b/clang/test/Driver/fortran-phases.f90 +@@ -0,0 +1,119 @@ ++! Test to see that the correct phases are run for the commandline input ++ ++! REQUIRES: classic_flang ++ ++! RUN: %flang -ccc-print-phases 2>&1 %s | FileCheck %s --check-prefix=LINK-NOPP ++! RUN: %flang -ccc-print-phases -c 2>&1 %s | FileCheck %s --check-prefix=CONLY-NOPP ++! RUN: %flang -ccc-print-phases -S 2>&1 %s | FileCheck %s --check-prefix=AONLY-NOPP ++! RUN: %flang -ccc-print-phases -c -emit-llvm 2>&1 %s | FileCheck %s --check-prefix=LLONLY-NOPP ++! RUN: %flang -ccc-print-phases -S -emit-llvm 2>&1 %s | FileCheck %s --check-prefix=LLONLY-NOPP ++! RUN: %flang -ccc-print-phases -emit-flang-llvm 2>&1 %s | FileCheck %s --check-prefix=FLLONLY-NOPP ++! RUN: %flang -ccc-print-phases -fsyntax-only 2>&1 %s | FileCheck %s --check-prefix=SONLY-NOPP ++! RUN: %flang -ccc-print-phases -E 2>&1 %s | FileCheck %s --check-prefix=PPONLY-NOPP ++ ++! RUN: %flang -ccc-print-phases 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=LINK ++! RUN: %flang -ccc-print-phases 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=LINK ++! RUN: %flang -ccc-print-phases -c 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=CONLY ++! RUN: %flang -ccc-print-phases -S 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=AONLY ++! RUN: %flang -ccc-print-phases -c -emit-llvm 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=LLONLY ++! RUN: %flang -ccc-print-phases -S -emit-llvm 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=LLONLY ++! RUN: %flang -ccc-print-phases -emit-flang-llvm 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=FLLONLY ++! RUN: %flang -ccc-print-phases -fsyntax-only 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=SONLY ++! RUN: %flang -ccc-print-phases -E 2>&1 -x f95-cpp-input %s | FileCheck %s --check-prefix=PPONLY ++ ++! LINK-NOPP: 0: input, {{.*}}, f95 ++! LINK-NOPP: 1: compiler, {0}, ir ++! LINK-NOPP: 2: backend, {1}, assembler ++! LINK-NOPP: 3: assembler, {2}, object ++! LINK-NOPP: 4: linker, {3}, image ++ ++! CONLY-NOPP: 0: input, {{.*}}, f95 ++! CONLY-NOPP: 1: compiler, {0}, ir ++! CONLY-NOPP: 2: backend, {1}, assembler ++! CONLY-NOPP: 3: assembler, {2}, object ++! CONLY-NOPP-NOT: {{.*}}: linker, {{{.*}}}, image ++ ++! AONLY-NOPP: 0: input, {{.*}}, f95 ++! AONLY-NOPP: 1: compiler, {0}, ir ++! AONLY-NOPP: 2: backend, {1}, assembler ++! AONLY-NOPP-NOT: {{.*}}: assembler, {{{.*}}}, object ++! AONLY-NOPP-NOT: {{.*}}: linker, {{{.*}}}, image ++ ++! LLONLY-NOPP: 0: input, {{.*}}, f95 ++! LLONLY-NOPP: 1: compiler, {0}, ir ++! LLONLY-NOPP-NOT: {{.*}}: backend, {{{.*}}}, assembler ++! LLONLY-NOPP-NOT: {{.*}}: assembler, {{{.*}}}, object ++! LLONLY-NOPP-NOT: {{.*}}: linker, {{{.*}}}, image ++ ++! FLLONLY-NOPP: 0: input, {{.*}}, f95 ++! FLLONLY-NOPP: 1: compiler, {0}, ir ++! FLLONLY-NOPP-NOT: {{.*}}: backend, {{{.*}}}, assembler ++! FLLONLY-NOPP-NOT: {{.*}}: assembler, {{{.*}}}, object ++! FLLONLY-NOPP-NOT: {{.*}}: linker, {{{.*}}}, image ++ ++! SONLY-NOPP: 0: input, {{.*}}, f95 ++! SONLY-NOPP-NOT: {{.*}}: compiler, {{{.*}}}, ir ++! SONLY-NOPP-NOT: {{.*}}: backend, {{{.*}}}, assembler ++! SONLY-NOPP-NOT: {{.*}}: assembler, {{{.*}}}, object ++! SONLY-NOPP-NOT: {{.*}}: linker, {{{.*}}}, image ++ ++! flang always preprocesses with -E regardless of file extension ++! PPONLY-NOPP: 0: input, {{.*}}, f95 ++! PPONLY-NOPP: 1: preprocessor, {0}, f95 ++! PPONLY-NOPP-NOT: {{.*}}: compiler, {{{.*}}}, ir ++! PPONLY-NOPP-NOT: {{.*}}: backend, {{{.*}}}, assembler ++! PPONLY-NOPP-NOT: {{.*}}: assembler, {{{.*}}}, object ++! PPONLY-NOPP-NOT: {{.*}}: linker, {{{.*}}}, image ++ ++! LINK: 0: input, {{.*}}, f95-cpp-input ++! LINK: 1: preprocessor, {0}, f95 ++! LINK: 2: compiler, {1}, ir ++! LINK: 3: backend, {2}, assembler ++! LINK: 4: assembler, {3}, object ++! LINK: 5: linker, {4}, image ++ ++! CONLY: 0: input, {{.*}}, f95-cpp-input ++! CONLY: 1: preprocessor, {0}, f95 ++! CONLY: 2: compiler, {1}, ir ++! CONLY: 3: backend, {2}, assembler ++! CONLY: 4: assembler, {3}, object ++! CONLY-NOT: {{.*}}: linker, {{{.*}}}, image ++ ++! AONLY: 0: input, {{.*}}, f95-cpp-input ++! AONLY: 1: preprocessor, {0}, f95 ++! AONLY: 2: compiler, {1}, ir ++! AONLY: 3: backend, {2}, assembler ++! AONLY-NOT: {{.*}}: assembler, {{{.*}}}, object ++! AONLY-NOT: {{.*}}: linker, {{{.*}}}, image ++ ++! LLONLY: 0: input, {{.*}}, f95-cpp-input ++! LLONLY: 1: preprocessor, {0}, f95 ++! LLONLY: 2: compiler, {1}, ir ++! LLONLY-NOT: {{.*}}: backend, {{{.*}}}, assembler ++! LLONLY-NOT: {{.*}}: assembler, {{{.*}}}, object ++! LLONLY-NOT: {{.*}}: linker, {{{.*}}}, image ++ ++! FLLONLY: 0: input, {{.*}}, f95-cpp-input ++! FLLONLY: 1: preprocessor, {0}, f95 ++! FLLONLY: 2: compiler, {1}, ir ++! FLLONLY-NOT: {{.*}}: backend, {{{.*}}}, assembler ++! FLLONLY-NOT: {{.*}}: assembler, {{{.*}}}, object ++! FLLONLY-NOT: {{.*}}: linker, {{{.*}}}, image ++ ++! SONLY: 0: input, {{.*}}, f95-cpp-input ++! SONLY: 1: preprocessor, {0}, f95 ++! SONLY-NOT: {{.*}}: compiler, {{{.*}}}, ir ++! SONLY-NOT: {{.*}}: backend, {{{.*}}}, assembler ++! SONLY-NOT: {{.*}}: assembler, {{{.*}}}, object ++! SONLY-NOT: {{.*}}: linker, {{{.*}}}, image ++ ++! PPONLY: 0: input, {{.*}}, f95-cpp-input ++! PPONLY: 1: preprocessor, {0}, f95 ++! PPONLY-NOT: {{.*}}: compiler, {{{.*}}}, ir ++! PPONLY-NOT: {{.*}}: backend, {{{.*}}}, assembler ++! PPONLY-NOT: {{.*}}: assembler, {{{.*}}}, object ++! PPONLY-NOT: {{.*}}: linker, {{{.*}}}, image ++ ++program hello ++ write(*, *) "Hello" ++end program hello +diff --git a/clang/test/Driver/fortran-preprocessor.f90 b/clang/test/Driver/fortran-preprocessor.f90 +new file mode 100644 +index 000000000000..d9e5620145ac +--- /dev/null ++++ b/clang/test/Driver/fortran-preprocessor.f90 +@@ -0,0 +1,48 @@ ++! REQUIRES: classic_flang ++ ++! -cpp should preprocess as it goes, regardless of input file extension ++! RUN: %flang -cpp -c -DHELLO="hello all" -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,CPP,PP ++! RUN: %flang -cpp -c -DHELLO="hello all" -### -x f95-cpp-input %s 2>&1 | FileCheck %s --check-prefixes=ALL,CPP,PP ++! -E should preprocess then stop, regardless of input file extension ++! RUN: %flang -E -DHELLO="hello all" -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY ++! RUN: %flang -E -DHELLO="hello all" -### -x f95-cpp-input %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY ++! -cpp and -E are redundant ++! RUN: %flang -E -cpp -DHELLO="hello all" -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY ++ ++! Don't link when given linker input ++! RUN: %flang -E -cpp -Wl,-rpath=blah -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY ++ ++! Explicitly test this nonsence case causing a bug with LLVM 13/14 ++! RUN: %flang -E -traditional-cpp -DHELLO="hello all" -x f95-cpp-input -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY ++ ++! Test -save-temps does not break things (same codepath as -traditional-cpp bug above) ++! RUN: %flang -E -DHELLO="hello all" -save-temps -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY ++! RUN: %flang -E -DHELLO="hello all" -save-temps -### -x f95-cpp-input %s 2>&1 | FileCheck %s --check-prefixes=ALL,E,PPONLY ++! RUN: %flang -cpp -c -DHELLO="hello all" -save-temps -### %s 2>&1 | FileCheck %s --check-prefixes=ALL,CPP,PP ++! RUN: %flang -cpp -c -DHELLO="hello all" -save-temps -### -x f95-cpp-input %s 2>&1 | FileCheck %s --check-prefixes=ALL,CPP,PP ++ ++! Test for the correct cmdline flags ++! Consume up to flang1 line ++! ALL-LABEL: "{{.*}}flang1" ++! CPP-NOT: "-es" ++! CPP: "-preprocess" ++! CPP-NOT: "-es" ++ ++! E-DAG: "-es" ++! E-DAG: "-preprocess" ++ ++! CPP should continue to build object ++! PP: "{{.*}}flang2" ++! PPONLY-NOT: "{{.*}}flang2" ++ ++! flang1 and flang2 should only be called at most once! ++! ALL-NOT: "{{.*}}flang1" ++! ALL-NOT: "{{.*}}flang2" ++ ++! These commands should never call a linker! ++! ALL-NOT: "{{.*}}ld" ++ ++program hello ++ write(*, *) HELLO ++end program hello ++ +diff --git a/clang/test/Driver/fortran.f95 b/clang/test/Driver/fortran.f95 +index db3ff2da17e8..e364180a1f9c 100644 +--- a/clang/test/Driver/fortran.f95 ++++ b/clang/test/Driver/fortran.f95 +@@ -1,6 +1,8 @@ + ! Check that the clang driver can invoke gcc to compile Fortran when in + ! --driver-mode=clang. This is legacy behaviour - see also --driver-mode=flang. + ++! UNSUPPORTED: classic_flang ++ + ! RUN: %clang -target x86_64-unknown-linux-gnu -integrated-as -c %s -### 2>&1 \ + ! RUN: | FileCheck --check-prefix=CHECK-OBJECT %s + ! CHECK-OBJECT: gcc +diff --git a/clang/test/Driver/gfortran.f90 b/clang/test/Driver/gfortran.f90 +index c985428650ec..1276703b1f6e 100644 +--- a/clang/test/Driver/gfortran.f90 ++++ b/clang/test/Driver/gfortran.f90 +@@ -1,4 +1,5 @@ + ! XFAIL: * ++! UNSUPPORTED: classic_flang + ! Test that Clang can forward all of the flags which are documented as + ! being supported by gfortran to GCC when falling back to GCC for + ! a fortran input file. +diff --git a/clang/test/Driver/lit.local.cfg b/clang/test/Driver/lit.local.cfg +index 6370e9f92d89..5ec1f9a8fc71 100644 +--- a/clang/test/Driver/lit.local.cfg ++++ b/clang/test/Driver/lit.local.cfg +@@ -12,6 +12,9 @@ config.suffixes = [ + ".f90", + ".F90", + ".f95", ++ '.F95', ++ '.f', ++ '.F', + ".cu", + ".rs", + ".cl", +diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py +index 68e038475a5c..bb6fb1ae5146 100644 +--- a/clang/test/lit.cfg.py ++++ b/clang/test/lit.cfg.py +@@ -395,3 +395,6 @@ if "system-aix" in config.available_features: + # possibly be present in system and user configuration files, so disable + # default configs for the test runs. + config.environment["CLANG_NO_DEFAULT_CONFIG"] = "1" ++ ++if config.use_classic_flang: ++ config.available_features.add("classic_flang") +diff --git a/clang/test/lit.site.cfg.py.in b/clang/test/lit.site.cfg.py.in +index ef75770a2c3c..bc278740e0d0 100644 +--- a/clang/test/lit.site.cfg.py.in ++++ b/clang/test/lit.site.cfg.py.in +@@ -41,6 +41,7 @@ config.llvm_external_lit = path(r"@LLVM_EXTERNAL_LIT@") + config.standalone_build = @CLANG_BUILT_STANDALONE@ + config.ppc_linux_default_ieeelongdouble = @PPC_LINUX_DEFAULT_IEEELONGDOUBLE@ + config.have_llvm_driver = @LLVM_TOOL_LLVM_DRIVER_BUILD@ ++config.use_classic_flang = @LLVM_ENABLE_CLASSIC_FLANG@ + + import lit.llvm + lit.llvm.initialize(lit_config, config) +diff --git a/clang/tools/driver/CMakeLists.txt b/clang/tools/driver/CMakeLists.txt +index 2182486f93a5..c269561fde69 100644 +--- a/clang/tools/driver/CMakeLists.txt ++++ b/clang/tools/driver/CMakeLists.txt +@@ -59,7 +59,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() + + if (CLANG_ENABLE_HLSL) +-- +2.24.3 (Apple Git-128) + diff --git a/0012-Fix-declaration-definition-mismatch-for-classic-flang.patch b/0012-Fix-declaration-definition-mismatch-for-classic-flang.patch new file mode 100644 index 0000000..8d75040 --- /dev/null +++ b/0012-Fix-declaration-definition-mismatch-for-classic-flang.patch @@ -0,0 +1,326 @@ +From bf04bad2c43a69730e1cdf4dcd2d06ab786bda33 Mon Sep 17 00:00:00 2001 +From: luofeng14 +Date: Wed, 17 Apr 2024 10:49:19 +0800 +Subject: [PATCH] Fix declaration definition mismatch for classic flang + +--- + .../clang/Basic/DiagnosticDriverKinds.td | 4 ++++ + clang/include/clang/Basic/MacroBuilder.h | 7 ++++++- + clang/include/clang/Basic/Sanitizers.def | 2 ++ + clang/include/clang/Driver/Options.td | 1 - + clang/include/clang/Frontend/Utils.h | 10 ++++++++- + clang/lib/CodeGen/CGDebugInfo.cpp | 21 +++++++++++++++---- + clang/lib/Driver/Driver.cpp | 1 - + clang/lib/Frontend/InitPreprocessor.cpp | 21 +++++++++++++++++++ + .../test/CodeGen/libpgmath-logfun-aarch64.ll | 1 + + clang/test/CodeGen/libpgmath-logfun-x86_64.ll | 2 +- + clang/test/Driver/autocomplete.c | 2 +- + .../flang/classic-flang-vscale-mbits.f95 | 2 ++ + .../Driver/flang/classic-flang-vscale.f95 | 2 ++ + clang/tools/driver/CMakeLists.txt | 6 +++++- + 14 files changed, 71 insertions(+), 11 deletions(-) + +diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td +index 09a1949d7596..62a60e65c6a4 100644 +--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td ++++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td +@@ -131,10 +131,12 @@ def err_drv_invalid_linker_name : Error< + "invalid linker name in argument '%0'">; + def err_drv_invalid_rtlib_name : Error< + "invalid runtime library name in argument '%0'">; ++#ifdef ENABLE_CLASSIC_FLANG + 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'">; ++#endif + def err_drv_unsupported_rtlib_for_platform : Error< + "unsupported runtime library '%0' for platform '%1'">; + def err_drv_invalid_unwindlib_name : Error< +@@ -358,8 +360,10 @@ def err_drv_negative_columns : Error< + "invalid value '%1' in '%0', value must be 'none' or a positive integer">; + def err_drv_small_columns : Error< + "invalid value '%1' in '%0', value must be '%2' or greater">; ++#ifdef ENABLE_CLASSIC_FLANG + def err_drv_clang_unsupported_minfo_arg : Error< + "'%0' option does not support '%1' value">; ++#endif + + 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 bfc5e38c15e3..54e9ea643394 100644 +--- a/clang/include/clang/Basic/MacroBuilder.h ++++ b/clang/include/clang/Basic/MacroBuilder.h +@@ -24,10 +24,15 @@ class MacroBuilder { + raw_ostream &Out; + public: + MacroBuilder(raw_ostream &Output) : Out(Output) {} ++ #ifdef ENABLE_CLASSIC_FLANG + virtual ~MacroBuilder() {} +- ++ #endif + /// Append a \#define line for macro of the form "\#define Name Value\n". ++ #ifdef ENABLE_CLASSIC_FLANG + virtual void defineMacro(const Twine &Name, const Twine &Value = "1") { ++ #else ++ void defineMacro(const Twine &Name, const Twine &Value = "1") { ++ #endif + Out << "#define " << Name << ' ' << Value << '\n'; + } + +diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def +index 4f0a2bf332ef..a8fcba677ee5 100644 +--- a/clang/include/clang/Basic/Sanitizers.def ++++ b/clang/include/clang/Basic/Sanitizers.def +@@ -107,8 +107,10 @@ SANITIZER("signed-integer-overflow", SignedIntegerOverflow) + SANITIZER("unreachable", Unreachable) + SANITIZER("vla-bound", VLABound) + SANITIZER("vptr", Vptr) ++#ifdef ENABLE_CLASSIC_FLANG + // fortran contiguous pointer checks + SANITIZER("discontiguous", Discontiguous) ++#endif + + // IntegerSanitizer + SANITIZER("unsigned-integer-overflow", UnsignedIntegerOverflow) +diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td +index 365285966a67..dab35f22e4ac 100644 +--- a/clang/include/clang/Driver/Options.td ++++ b/clang/include/clang/Driver/Options.td +@@ -5473,7 +5473,6 @@ defm stack_arrays : BoolOptionWithoutMarshalling<"f", "stack-arrays", + defm loop_versioning : BoolOptionWithoutMarshalling<"f", "version-loops-for-stride", + PosFlag, + NegFlag>; +- + } // let Flags = [FC1Option, FlangOption, FlangOnlyOption] + + #ifdef ENABLE_CLASSIC_FLANG +diff --git a/clang/include/clang/Frontend/Utils.h b/clang/include/clang/Frontend/Utils.h +index c51c617c1379..4ac76dd348c6 100644 +--- a/clang/include/clang/Frontend/Utils.h ++++ b/clang/include/clang/Frontend/Utils.h +@@ -17,10 +17,12 @@ + #include "clang/Basic/LLVM.h" + #include "clang/Driver/OptionUtils.h" + #include "clang/Frontend/DependencyOutputOptions.h" ++#ifdef ENABLE_CLASSIC_FLANG + #include "clang/Basic/TargetInfo.h" ++#include "llvm/ADT/StringExtras.h" ++#endif + #include "llvm/ADT/ArrayRef.h" + #include "llvm/ADT/IntrusiveRefCntPtr.h" +-#include "llvm/ADT/StringExtras.h" + #include "llvm/ADT/StringMap.h" + #include "llvm/ADT/StringRef.h" + #include "llvm/ADT/StringSet.h" +@@ -33,11 +35,13 @@ + #include + #include + ++#ifdef ENABLE_CLASSIC_FLANG + namespace llvm { + + class StringRef; + + } // namespace llvm ++#endif + + namespace clang { + +@@ -47,7 +51,9 @@ class CompilerInvocation; + class DiagnosticsEngine; + class ExternalSemaSource; + class FrontendOptions; ++#ifdef ENABLE_CLASSIC_FLANG + class MacroBuilder; ++#endif + class PCHContainerReader; + class Preprocessor; + class PreprocessorOptions; +@@ -63,6 +69,7 @@ void InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &PPOpts, + void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, + const PreprocessorOutputOptions &Opts); + ++#ifdef ENABLE_CLASSIC_FLANG + /// 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). +@@ -85,6 +92,7 @@ static void DefineTypeSize(const Twine &MacroName, TargetInfo::IntType Ty, + DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty), + TI.isTypeSigned(Ty), Builder); + } ++#endif + + /// An interface for collecting the dependencies of a compilation. Users should + /// use \c attachToPreprocessor and \c attachToASTReader to get all of the +diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp +index 3b140860cce4..30d62ae8faf6 100644 +--- a/clang/lib/CodeGen/CGDebugInfo.cpp ++++ b/clang/lib/CodeGen/CGDebugInfo.cpp +@@ -3981,7 +3981,10 @@ CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) { + auto *GV = DBuilder.createTempGlobalVariableFwdDecl( + DContext, Name, LinkageName, Unit, Line, getOrCreateType(T, Unit), + !VD->isExternallyVisible(), nullptr, TemplateParameters, +- llvm::DINode::FlagZero, Align); ++#ifdef ENABLE_CLASSIC_FLANG ++ llvm::DINode::FlagZero, ++#endif ++ Align); + FwdDeclReplaceMap.emplace_back( + std::piecewise_construct, + std::make_tuple(cast(VD->getCanonicalDecl())), +@@ -5468,7 +5471,10 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, + Var->hasLocalLinkage(), true, + Expr.empty() ? nullptr : DBuilder.createExpression(Expr), + getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters, +- llvm::DINode::FlagZero, Align, Annotations); ++#ifdef ENABLE_CLASSIC_FLANG ++ llvm::DINode::FlagZero, ++#endif ++ Align, Annotations); + Var->addDebugInfo(GVE); + } + DeclCache[D->getCanonicalDecl()].reset(GVE); +@@ -5564,7 +5570,11 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) { + GV.reset(DBuilder.createGlobalVariableExpression( + DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty, + true, true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VarD), +- TemplateParameters, llvm::DINode::FlagZero, Align)); ++ TemplateParameters, ++#ifdef ENABLE_CLASSIC_FLANG ++ llvm::DINode::FlagZero, ++#endif ++ Align)); + } + + void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var, +@@ -5582,7 +5592,10 @@ void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var, + llvm::DIGlobalVariableExpression *GVE = + DBuilder.createGlobalVariableExpression( + DContext, Name, StringRef(), Unit, getLineNumber(D->getLocation()), +- Ty, false, false, nullptr, nullptr, nullptr, llvm::DINode::FlagZero, ++ Ty, false, false, nullptr, nullptr, nullptr, ++#ifdef ENABLE_CLASSIC_FLANG ++ llvm::DINode::FlagZero, ++#endif + Align); + Var->addDebugInfo(GVE); + } +diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp +index 8bfee5928fe5..819d7703b2e7 100644 +--- a/clang/lib/Driver/Driver.cpp ++++ b/clang/lib/Driver/Driver.cpp +@@ -377,7 +377,6 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, + (PhaseArg = DAL.getLastArg(options::OPT_fmodule_header, + options::OPT_fmodule_header_EQ))) { + FinalPhase = phases::Precompile; +- + // -{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)) || +diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp +index 7b01cb01a45e..05682ae9f135 100644 +--- a/clang/lib/Frontend/InitPreprocessor.cpp ++++ b/clang/lib/Frontend/InitPreprocessor.cpp +@@ -161,6 +161,27 @@ static void DefineFloatMacros(MacroBuilder &Builder, StringRef Prefix, + Builder.defineMacro(DefPrefix + "MIN__", Twine(Min)+Ext); + } + ++#ifndef ENABLE_CLASSIC_FLANG ++/// 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, toString(MaxVal, 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); ++} ++#endif ++ + static void DefineFmt(const Twine &Prefix, TargetInfo::IntType Ty, + const TargetInfo &TI, MacroBuilder &Builder) { + bool IsSigned = TI.isTypeSigned(Ty); +diff --git a/clang/test/CodeGen/libpgmath-logfun-aarch64.ll b/clang/test/CodeGen/libpgmath-logfun-aarch64.ll +index 141fed29ccd1..be05a472016c 100644 +--- a/clang/test/CodeGen/libpgmath-logfun-aarch64.ll ++++ b/clang/test/CodeGen/libpgmath-logfun-aarch64.ll +@@ -1,3 +1,4 @@ ++; REQUIRES: classic_flang + ; REQUIRES: aarch64-registered-target + + ; RUN: %clang -target aarch64-unknown-linux-gnu -Ofast -S %s -o - | FileCheck %s +diff --git a/clang/test/CodeGen/libpgmath-logfun-x86_64.ll b/clang/test/CodeGen/libpgmath-logfun-x86_64.ll +index 3ce1d910947f..c89e538f34e3 100644 +--- a/clang/test/CodeGen/libpgmath-logfun-x86_64.ll ++++ b/clang/test/CodeGen/libpgmath-logfun-x86_64.ll +@@ -1,5 +1,5 @@ + ; REQUIRES: x86-registered-target +- ++; REQUIRES: classic_flang + ; RUN: %clang -target x86_64-unknown-linux-gnu -msse -Ofast -S %s -o - | FileCheck %s + + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +diff --git a/clang/test/Driver/autocomplete.c b/clang/test/Driver/autocomplete.c +index 8c4921c9dbd5..d6f57708b67e 100644 +--- a/clang/test/Driver/autocomplete.c ++++ b/clang/test/Driver/autocomplete.c +@@ -85,7 +85,7 @@ + // FVECLIBALL-NEXT: libmvec + // FVECLIBALL-NEXT: MASSV + // FVECLIBALL-NEXT: none +-// FVECLIBALL: SLEEF ++// FVECLIBALL-NEXT: SLEEF + // FVECLIBALL-NEXT: SVML + // RUN: %clang --autocomplete=-fshow-overloads= | FileCheck %s -check-prefix=FSOVERALL + // FSOVERALL: all +diff --git a/clang/test/Driver/flang/classic-flang-vscale-mbits.f95 b/clang/test/Driver/flang/classic-flang-vscale-mbits.f95 +index f0ed43aa027a..089993be7b04 100644 +--- a/clang/test/Driver/flang/classic-flang-vscale-mbits.f95 ++++ b/clang/test/Driver/flang/classic-flang-vscale-mbits.f95 +@@ -1,3 +1,5 @@ ++! REQUIRES: classic_flang ++ + // RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve -msve-vector-bits=128 %s 2>&1 | FileCheck -check-prefix=CHECK-SVE-128 %s + // RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve -msve-vector-bits=128+ %s 2>&1 | FileCheck -check-prefix=CHECK-SVE-128PLUS %s + // RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve -msve-vector-bits=256 %s 2>&1 | FileCheck -check-prefix=CHECK-SVE-256 %s +diff --git a/clang/test/Driver/flang/classic-flang-vscale.f95 b/clang/test/Driver/flang/classic-flang-vscale.f95 +index 8110be594db5..b8496975758f 100644 +--- a/clang/test/Driver/flang/classic-flang-vscale.f95 ++++ b/clang/test/Driver/flang/classic-flang-vscale.f95 +@@ -1,3 +1,5 @@ ++! REQUIRES: classic_flang ++ + // RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a %s 2>&1 | FileCheck -check-prefix=CHECK-NEON %s + // RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve %s 2>&1 | FileCheck -check-prefix=CHECK-SVE %s + // RUN: %clang --driver-mode=flang -### -S --target=aarch64 -march=armv8-a+sve2 %s 2>&1 | FileCheck -check-prefix=CHECK-SVE2 %s +diff --git a/clang/tools/driver/CMakeLists.txt b/clang/tools/driver/CMakeLists.txt +index c269561fde69..465b05c9c0e9 100644 +--- a/clang/tools/driver/CMakeLists.txt ++++ b/clang/tools/driver/CMakeLists.txt +@@ -59,7 +59,11 @@ endif() + add_dependencies(clang clang-resource-headers) + + if(NOT CLANG_LINKS_TO_CREATE) +- set(CLANG_LINKS_TO_CREATE clang++ clang-cl clang-cpp flang) ++ if (LLVM_ENABLE_CLASSIC_FLANG) ++ set(CLANG_LINKS_TO_CREATE clang++ clang-cl clang-cpp flang) ++ else() ++ set(CLANG_LINKS_TO_CREATE clang++ clang-cl clang-cpp) ++ endif() + endif() + + if (CLANG_ENABLE_HLSL) +-- +2.24.3 (Apple Git-128) + diff --git a/clang.spec b/clang.spec index 10517b4..5e03a75 100644 --- a/clang.spec +++ b/clang.spec @@ -1,5 +1,6 @@ %bcond_without sys_llvm %bcond_without check +%bcond_with classic_flang %global maj_ver 17 %global min_ver 0 @@ -36,7 +37,7 @@ Name: %{pkg_name} Version: %{clang_version} -Release: 14 +Release: 15 Summary: A C language family front-end for LLVM License: NCSA @@ -55,6 +56,8 @@ Patch7: 0007-add-more-warning-options-to-fgcc-compatible.patch Patch8: 0008-Backport-LoongArch-Add-the-support-for-vector.patch Patch9: 0009-Backport-LoongArch-improve-the-support-for-compiler-rt-and-bugfix.patch Patch10: 0010-Backport-clang-Avoid-Wshadow-warning-when-init-capture-named.patch +Patch11: 0011-Add-the-support-for-classic-flang.patch +Patch12: 0012-Fix-declaration-definition-mismatch-for-classic-flang.patch # Patches for clang-tools-extra # See https://reviews.llvm.org/D120301 @@ -258,6 +261,9 @@ cd _build -DLLVM_LIBDIR_SUFFIX=64 \ %else -DLLVM_LIBDIR_SUFFIX= \ +%endif +%if %{with classic_flang} + -DLLVM_ENABLE_CLASSIC_FLANG=ON \ %endif -DBUILD_FOR_OPENEULER=ON \ -DCLANG_DEFAULT_UNWINDLIB=libgcc @@ -296,6 +302,9 @@ LD_LIBRARY_PATH=%{buildroot}/%{install_libdir} %{__ninja} check-all -C ./_build %{install_bindir}/clang-cl %{install_bindir}/clang-cpp %{install_prefix}/share/man/man1/* +%if %{with classic_flang} +%{install_bindir}/flang +%endif %files libs %{install_libdir}/*.so.* @@ -383,6 +392,9 @@ LD_LIBRARY_PATH=%{buildroot}/%{install_libdir} %{__ninja} check-all -C ./_build %{install_bindir}/git-clang-format %changelog +* Wed Apr 17 2024 luofeng -17.0.6-15 +- Add the support for classic flang + * Tue Apr 16 2024 wangqiang -17.0.6-14 - Avoid -Wshadow warning when init-capture named same as class field. -- Gitee