diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3254,7 +3254,7 @@ def mkernel : Flag<["-"], "mkernel">, Group; def mlinker_version_EQ : Joined<["-"], "mlinker-version=">, Flags<[NoXarchOption]>; -def mllvm : Separate<["-"], "mllvm">, Flags<[CC1Option,CC1AsOption,CoreOption]>, +def mllvm : Separate<["-"], "mllvm">,Flags<[CC1Option,CC1AsOption,CoreOption,FC1Option,FlangOption]>, HelpText<"Additional arguments to forward to LLVM's option processing">, MarshallingInfoStringVector>; def ffuchsia_api_level_EQ : Joined<["-"], "ffuchsia-api-level=">, diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -106,6 +106,13 @@ // Forward -Xflang arguments to -fc1 Args.AddAllArgValues(CmdArgs, options::OPT_Xflang); + // Forward -mllvm options to the LLVM option parser. In practice, this means + // forwarding to `-fc1` as that's where the LLVM parser is run. + for (const Arg *A : Args.filtered(options::OPT_mllvm)) { + A->claim(); + A->render(Args, CmdArgs); + } + if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); diff --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h --- a/flang/include/flang/Frontend/FrontendOptions.h +++ b/flang/include/flang/Frontend/FrontendOptions.h @@ -266,6 +266,10 @@ /// The name of the action to run when using a plugin action. std::string ActionName; + /// A list of arguments to forward to LLVM's option processing; this + /// should only be used for debugging and experimental features. + std::vector llvmArgs; + // Return the appropriate input kind for a file extension. For example, /// "*.f" would return Language::Fortran. /// diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -584,6 +584,8 @@ success &= parseSemaArgs(res, args, diags); success &= parseDialectArgs(res, args, diags); success &= parseDiagArgs(res, args, diags); + res.frontendOpts_.llvmArgs = + args.getAllArgValues(clang::driver::options::OPT_mllvm); return success; } diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp --- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -135,6 +135,19 @@ } } + // Honor -mllvm. This should happen AFTER plugins have been loaded! + if (!flang->frontendOpts().llvmArgs.empty()) { + unsigned numArgs = flang->frontendOpts().llvmArgs.size(); + auto args = std::make_unique(numArgs + 2); + args[0] = "flang (LLVM option parsing)"; + + for (unsigned i = 0; i != numArgs; ++i) + args[i + 1] = flang->frontendOpts().llvmArgs[i].c_str(); + + args[numArgs + 1] = nullptr; + llvm::cl::ParseCommandLineOptions(numArgs + 1, args.get()); + } + // If there were errors in processing arguments, don't do anything else. if (flang->diagnostics().hasErrorOccurred()) { return false; diff --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90 --- a/flang/test/Driver/driver-help-hidden.f90 +++ b/flang/test/Driver/driver-help-hidden.f90 @@ -47,6 +47,7 @@ ! CHECK-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV. ! CHECK-NEXT: -help Display available options ! CHECK-NEXT: -I Add directory to the end of the list of include search paths +! CHECK-NEXT: -mllvm Additional arguments to forward to LLVM's option processing ! CHECK-NEXT: -module-dir Put MODULE files in ! CHECK-NEXT: -nocpp Disable predefined and command line preprocessor macros ! CHECK-NEXT: -o Write output to diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90 --- a/flang/test/Driver/driver-help.f90 +++ b/flang/test/Driver/driver-help.f90 @@ -47,6 +47,7 @@ ! HELP-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV. ! HELP-NEXT: -help Display available options ! HELP-NEXT: -I Add directory to the end of the list of include search paths +! HELP-NEXT: -mllvm Additional arguments to forward to LLVM's option processing ! HELP-NEXT: -module-dir Put MODULE files in ! HELP-NEXT: -nocpp Disable predefined and command line preprocessor macros ! HELP-NEXT: -o Write output to @@ -121,6 +122,7 @@ ! HELP-FC1-NEXT: -init-only Only execute frontend initialization ! HELP-FC1-NEXT: -I Add directory to the end of the list of include search paths ! HELP-FC1-NEXT: -load Load the named plugin (dynamic shared object) +! HELP-FC1-NEXT: -mllvm Additional arguments to forward to LLVM's option processing ! HELP-FC1-NEXT: -module-dir Put MODULE files in ! HELP-FC1-NEXT: -module-suffix Use as the suffix for module files (the default value is `.mod`) ! HELP-FC1-NEXT: -nocpp Disable predefined and command line preprocessor macros diff --git a/flang/test/Driver/mllvm.f90 b/flang/test/Driver/mllvm.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Driver/mllvm.f90 @@ -0,0 +1,32 @@ +! Test the `-mlvm` option + +!------------ +! RUN COMMAND +!------------ +! 1. Test typical usage. +! RUN: %flang -S -mllvm -print-before-all %s -o - 2>&1 | FileCheck %s --check-prefix=OUTPUT +! RUN: %flang_fc1 -S -mllvm -print-before-all %s -o - 2>&1 | FileCheck %s --check-prefix=OUTPUT + +! 2. Does the option forwarding from `flang-new` to `flang-new -fc1` work? +! RUN: %flang -### -S -mllvm -print-before-all %s -o - 2>&1 | FileCheck %s --check-prefix=OPTION_FORWARDING + +! 3. Test invalid usage (`-print-before` requires an argument) +! RUN: not %flang -S -mllvm -print-before %s -o - 2>&1 | FileCheck %s --check-prefix=INVALID_USAGE + +!---------------- +! EXPECTED OUTPUT +!---------------- +! OUTPUT: *** IR Dump Before Pre-ISel Intrinsic Lowering (pre-isel-intrinsic-lowering) *** +! OUTPUT-NEXT: ; ModuleID = 'FIRModule' +! OUTPUT-NEXT: source_filename = "FIRModule" + +! Verify that `-mllvm