Author: Tarun Prabhu Date: 2024-10-14T08:44:24-06:00 New Revision: 839344f025fb7eff529735873f327330618b2ebb
URL: https://github.com/llvm/llvm-project/commit/839344f025fb7eff529735873f327330618b2ebb DIFF: https://github.com/llvm/llvm-project/commit/839344f025fb7eff529735873f327330618b2ebb.diff LOG: [clang][flang][mlir] Reapply "Support -frecord-command-line option (#102975)" The underlying issue was caused by a file included in two different places which resulted in duplicate definition errors when linking individual shared libraries. This was fixed in c3201ddaeac02a2c86a38b [#109874]. Added: flang/test/Driver/frecord-command-line.f90 flang/test/Lower/record-command-line.f90 mlir/test/Target/LLVMIR/Import/commandline.ll mlir/test/Target/LLVMIR/commandline.mlir Modified: clang/include/clang/Driver/Options.td clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Driver/ToolChains/CommonArgs.cpp clang/lib/Driver/ToolChains/CommonArgs.h clang/lib/Driver/ToolChains/Flang.cpp flang/include/flang/Frontend/CodeGenOptions.h flang/include/flang/Lower/Bridge.h flang/include/flang/Optimizer/Dialect/Support/FIRContext.h flang/lib/Frontend/CompilerInvocation.cpp flang/lib/Frontend/FrontendActions.cpp flang/lib/Lower/Bridge.cpp flang/lib/Optimizer/Dialect/Support/FIRContext.cpp flang/tools/bbc/CMakeLists.txt flang/tools/bbc/bbc.cpp mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td mlir/include/mlir/Target/LLVMIR/ModuleImport.h mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h mlir/lib/Target/LLVMIR/ModuleImport.cpp mlir/lib/Target/LLVMIR/ModuleTranslation.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index d306c751505e98..6491e9ac73ce99 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2002,16 +2002,18 @@ def fparse_all_comments : Flag<["-"], "fparse-all-comments">, Group<f_clang_Grou Visibility<[ClangOption, CC1Option]>, MarshallingInfoFlag<LangOpts<"CommentOpts.ParseAllComments">>; def frecord_command_line : Flag<["-"], "frecord-command-line">, - DocBrief<[{Generate a section named ".GCC.command.line" containing the clang + DocBrief<[{Generate a section named ".GCC.command.line" containing the driver command-line. After linking, the section may contain multiple command lines, which will be individually terminated by null bytes. Separate arguments within a command line are combined with spaces; spaces and backslashes within an argument are escaped with backslashes. This format diff ers from the format of the equivalent section produced by GCC with the -frecord-gcc-switches flag. This option is currently only supported on ELF targets.}]>, - Group<f_clang_Group>; + Group<f_Group>, + Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>; def fno_record_command_line : Flag<["-"], "fno-record-command-line">, - Group<f_clang_Group>; + Group<f_Group>, + Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>; def : Flag<["-"], "frecord-gcc-switches">, Alias<frecord_command_line>; def : Flag<["-"], "fno-record-gcc-switches">, Alias<fno_record_command_line>; def fcommon : Flag<["-"], "fcommon">, Group<f_Group>, @@ -7166,6 +7168,9 @@ def mrelocation_model : Separate<["-"], "mrelocation-model">, NormalizedValues<["Static", "PIC_", "ROPI", "RWPI", "ROPI_RWPI", "DynamicNoPIC"]>, MarshallingInfoEnum<CodeGenOpts<"RelocationModel">, "PIC_">; def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">; +def record_command_line : Separate<["-"], "record-command-line">, + HelpText<"The string to embed in the .LLVM.command.line section.">, + MarshallingInfoString<CodeGenOpts<"RecordCommandLine">>; } // let Visibility = [CC1Option, CC1AsOption, FC1Option] @@ -7186,9 +7191,6 @@ def debugger_tuning_EQ : Joined<["-"], "debugger-tuning=">, def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">, MarshallingInfoString<CodeGenOpts<"DwarfDebugFlags">>; -def record_command_line : Separate<["-"], "record-command-line">, - HelpText<"The string to embed in the .LLVM.command.line section.">, - MarshallingInfoString<CodeGenOpts<"RecordCommandLine">>; def compress_debug_sections_EQ : Joined<["-", "--"], "compress-debug-sections=">, HelpText<"DWARF debug sections compression type">, Values<"none,zlib,zstd">, NormalizedValuesScope<"llvm::DebugCompressionType">, NormalizedValues<["None", "Zlib", "Zstd"]>, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 49b07322a21a52..9d2f7a8960b45f 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -94,24 +94,6 @@ static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) { << "-static"; } -// Add backslashes to escape spaces and other backslashes. -// This is used for the space-separated argument list specified with -// the -dwarf-debug-flags option. -static void EscapeSpacesAndBackslashes(const char *Arg, - SmallVectorImpl<char> &Res) { - for (; *Arg; ++Arg) { - switch (*Arg) { - default: - break; - case ' ': - case '\\': - Res.push_back('\\'); - break; - } - Res.push_back(*Arg); - } -} - /// Apply \a Work on the current tool chain \a RegularToolChain and any other /// offloading tool chain that is associated with the current action \a JA. static void @@ -7724,31 +7706,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Also record command line arguments into the debug info if // -grecord-gcc-switches options is set on. // By default, -gno-record-gcc-switches is set on and no recording. - auto GRecordSwitches = - Args.hasFlag(options::OPT_grecord_command_line, - options::OPT_gno_record_command_line, false); - auto FRecordSwitches = - Args.hasFlag(options::OPT_frecord_command_line, - options::OPT_fno_record_command_line, false); - if (FRecordSwitches && !Triple.isOSBinFormatELF() && - !Triple.isOSBinFormatXCOFF() && !Triple.isOSBinFormatMachO()) - D.Diag(diag::err_drv_unsupported_opt_for_target) - << Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args) - << TripleStr; - if (TC.UseDwarfDebugFlags() || GRecordSwitches || FRecordSwitches) { - ArgStringList OriginalArgs; - for (const auto &Arg : Args) - Arg->render(Args, OriginalArgs); - - SmallString<256> Flags; - EscapeSpacesAndBackslashes(Exec, Flags); - for (const char *OriginalArg : OriginalArgs) { - SmallString<128> EscapedArg; - EscapeSpacesAndBackslashes(OriginalArg, EscapedArg); - Flags += " "; - Flags += EscapedArg; - } - auto FlagsArgString = Args.MakeArgString(Flags); + auto GRecordSwitches = false; + auto FRecordSwitches = false; + if (shouldRecordCommandLine(TC, Args, FRecordSwitches, GRecordSwitches)) { + auto FlagsArgString = renderEscapedCommandLine(TC, Args); if (TC.UseDwarfDebugFlags() || GRecordSwitches) { CmdArgs.push_back("-dwarf-debug-flags"); CmdArgs.push_back(FlagsArgString); @@ -8748,10 +8709,10 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, SmallString<256> Flags; const char *Exec = getToolChain().getDriver().getClangProgramPath(); - EscapeSpacesAndBackslashes(Exec, Flags); + escapeSpacesAndBackslashes(Exec, Flags); for (const char *OriginalArg : OriginalArgs) { SmallString<128> EscapedArg; - EscapeSpacesAndBackslashes(OriginalArg, EscapedArg); + escapeSpacesAndBackslashes(OriginalArg, EscapedArg); Flags += " "; Flags += EscapedArg; } diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 0c6a585c3acffd..3dd86ab7b99ca9 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -2979,3 +2979,62 @@ void tools::handleColorDiagnosticsArgs(const Driver &D, const ArgList &Args, if (D.getDiags().getDiagnosticOptions().ShowColors) CmdArgs.push_back("-fcolor-diagnostics"); } + +void tools::escapeSpacesAndBackslashes(const char *Arg, + llvm::SmallVectorImpl<char> &Res) { + for (; *Arg; ++Arg) { + switch (*Arg) { + default: + break; + case ' ': + case '\\': + Res.push_back('\\'); + break; + } + Res.push_back(*Arg); + } +} + +const char *tools::renderEscapedCommandLine(const ToolChain &TC, + const llvm::opt::ArgList &Args) { + const Driver &D = TC.getDriver(); + const char *Exec = D.getClangProgramPath(); + + llvm::opt::ArgStringList OriginalArgs; + for (const auto &Arg : Args) + Arg->render(Args, OriginalArgs); + + llvm::SmallString<256> Flags; + escapeSpacesAndBackslashes(Exec, Flags); + for (const char *OriginalArg : OriginalArgs) { + llvm::SmallString<128> EscapedArg; + escapeSpacesAndBackslashes(OriginalArg, EscapedArg); + Flags += " "; + Flags += EscapedArg; + } + + return Args.MakeArgString(Flags); +} + +bool tools::shouldRecordCommandLine(const ToolChain &TC, + const llvm::opt::ArgList &Args, + bool &FRecordCommandLine, + bool &GRecordCommandLine) { + const Driver &D = TC.getDriver(); + const llvm::Triple &Triple = TC.getEffectiveTriple(); + const std::string &TripleStr = Triple.getTriple(); + + FRecordCommandLine = + Args.hasFlag(options::OPT_frecord_command_line, + options::OPT_fno_record_command_line, false); + GRecordCommandLine = + Args.hasFlag(options::OPT_grecord_command_line, + options::OPT_gno_record_command_line, false); + if (FRecordCommandLine && !Triple.isOSBinFormatELF() && + !Triple.isOSBinFormatXCOFF() && !Triple.isOSBinFormatMachO()) + D.Diag(diag::err_drv_unsupported_opt_for_target) + << Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args) + << TripleStr; + + return FRecordCommandLine || TC.UseDwarfDebugFlags() || GRecordCommandLine; +} diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index eff21b210b4244..9cafac2538862a 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -237,6 +237,31 @@ void addMCModel(const Driver &D, const llvm::opt::ArgList &Args, void handleColorDiagnosticsArgs(const Driver &D, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs); +/// Add backslashes to escape spaces and other backslashes. +/// This is used for the space-separated argument list specified with +/// the -dwarf-debug-flags option. +void escapeSpacesAndBackslashes(const char *Arg, + llvm::SmallVectorImpl<char> &Res); + +/// Join the args in the given ArgList, escape spaces and backslashes and +/// return the joined string. This is used when saving the command line as a +/// result of using either the -frecord-command-line or -grecord-command-line +/// options. The lifetime of the returned c-string will match that of the Args +/// argument. +const char *renderEscapedCommandLine(const ToolChain &TC, + const llvm::opt::ArgList &Args); + +/// Check if the command line should be recorded in the object file. This is +/// done if either -frecord-command-line or -grecord-command-line options have +/// been passed. This also does some error checking since -frecord-command-line +/// is currently only supported on ELF platforms. The last two boolean +/// arguments are out parameters and will be set depending on the command +/// line options that were passed. +bool shouldRecordCommandLine(const ToolChain &TC, + const llvm::opt::ArgList &Args, + bool &FRecordCommandLine, + bool &GRecordCommandLine); + } // end namespace tools } // end namespace driver } // end namespace clang diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 19b43594b00815..e2f8f6e0cca1c6 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -882,6 +882,20 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA, addDashXForInput(Args, Input, CmdArgs); + bool FRecordCmdLine = false; + bool GRecordCmdLine = false; + if (shouldRecordCommandLine(TC, Args, FRecordCmdLine, GRecordCmdLine)) { + const char *CmdLine = renderEscapedCommandLine(TC, Args); + if (FRecordCmdLine) { + CmdArgs.push_back("-record-command-line"); + CmdArgs.push_back(CmdLine); + } + if (TC.UseDwarfDebugFlags() || GRecordCmdLine) { + CmdArgs.push_back("-dwarf-debug-flags"); + CmdArgs.push_back(CmdLine); + } + } + CmdArgs.push_back(Input.getFilename()); const char *Exec = Args.MakeArgString(D.GetProgramPath("flang", TC)); diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h index ac7fcbcba4f747..f19943335737b9 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.h +++ b/flang/include/flang/Frontend/CodeGenOptions.h @@ -63,6 +63,9 @@ class CodeGenOptions : public CodeGenOptionsBase { /// The directory where temp files are stored if specified by -save-temps std::optional<std::string> SaveTempsDir; + /// The string containing the commandline for the llvm.commandline metadata. + std::optional<std::string> RecordCommandLine; + /// The name of the file to which the backend should save YAML optimization /// records. std::string OptRecordFile; diff --git a/flang/include/flang/Lower/Bridge.h b/flang/include/flang/Lower/Bridge.h index 4379ed512cdf0a..8ea5ed52e28218 100644 --- a/flang/include/flang/Lower/Bridge.h +++ b/flang/include/flang/Lower/Bridge.h @@ -14,6 +14,8 @@ #define FORTRAN_LOWER_BRIDGE_H #include "flang/Common/Fortran.h" +#include "flang/Frontend/CodeGenOptions.h" +#include "flang/Frontend/TargetOptions.h" #include "flang/Lower/AbstractConverter.h" #include "flang/Lower/EnvironmentDefault.h" #include "flang/Lower/LoweringOptions.h" @@ -65,11 +67,13 @@ class LoweringBridge { const Fortran::lower::LoweringOptions &loweringOptions, const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults, const Fortran::common::LanguageFeatureControl &languageFeatures, - const llvm::TargetMachine &targetMachine, llvm::StringRef tuneCPU) { + const llvm::TargetMachine &targetMachine, + const Fortran::frontend::TargetOptions &targetOptions, + const Fortran::frontend::CodeGenOptions &codeGenOptions) { return LoweringBridge(ctx, semanticsContext, defaultKinds, intrinsics, targetCharacteristics, allCooked, triple, kindMap, loweringOptions, envDefaults, languageFeatures, - targetMachine, tuneCPU); + targetMachine, targetOptions, codeGenOptions); } //===--------------------------------------------------------------------===// @@ -148,7 +152,9 @@ class LoweringBridge { const Fortran::lower::LoweringOptions &loweringOptions, const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults, const Fortran::common::LanguageFeatureControl &languageFeatures, - const llvm::TargetMachine &targetMachine, const llvm::StringRef tuneCPU); + const llvm::TargetMachine &targetMachine, + const Fortran::frontend::TargetOptions &targetOptions, + const Fortran::frontend::CodeGenOptions &codeGenOptions); LoweringBridge() = delete; LoweringBridge(const LoweringBridge &) = delete; diff --git a/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h b/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h index e45011c8e02a33..2df14f83c11e17 100644 --- a/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h +++ b/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h @@ -77,6 +77,12 @@ void setIdent(mlir::ModuleOp mod, llvm::StringRef ident); /// Get the compiler identifier from the Module. llvm::StringRef getIdent(mlir::ModuleOp mod); +/// Set the command line used in this invocation. +void setCommandline(mlir::ModuleOp mod, llvm::StringRef cmdLine); + +/// Get the command line used in this invocation. +llvm::StringRef getCommandline(mlir::ModuleOp mod); + /// Helper for determining the target from the host, etc. Tools may use this /// function to provide a consistent interpretation of the `--target=<string>` /// command-line option. diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 849c6f53614f63..4607a33ffda6cc 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -349,6 +349,12 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, if (auto *a = args.getLastArg(clang::driver::options::OPT_save_temps_EQ)) opts.SaveTempsDir = a->getValue(); + // -record-command-line option. + if (const llvm::opt::Arg *a = + args.getLastArg(clang::driver::options::OPT_record_command_line)) { + opts.RecordCommandLine = a->getValue(); + } + // -mlink-builtin-bitcode for (auto *a : args.filtered(clang::driver::options::OPT_mlink_builtin_bitcode)) diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 8f882bff170909..f2e460fc53a67f 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -301,7 +301,7 @@ bool CodeGenAction::beginSourceFileAction() { kindMap, ci.getInvocation().getLoweringOpts(), ci.getInvocation().getFrontendOpts().envDefaults, ci.getInvocation().getFrontendOpts().features, targetMachine, - ci.getInvocation().getTargetOpts().cpuToTuneFor); + ci.getInvocation().getTargetOpts(), ci.getInvocation().getCodeGenOpts()); // Fetch module from lb, so we can set mlirModule = std::make_unique<mlir::ModuleOp>(lb.getModule()); diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 0894a5903635e1..877fe122265dd0 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -6062,7 +6062,9 @@ Fortran::lower::LoweringBridge::LoweringBridge( const Fortran::lower::LoweringOptions &loweringOptions, const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults, const Fortran::common::LanguageFeatureControl &languageFeatures, - const llvm::TargetMachine &targetMachine, const llvm::StringRef tuneCPU) + const llvm::TargetMachine &targetMachine, + const Fortran::frontend::TargetOptions &targetOpts, + const Fortran::frontend::CodeGenOptions &cgOpts) : semanticsContext{semanticsContext}, defaultKinds{defaultKinds}, intrinsics{intrinsics}, targetCharacteristics{targetCharacteristics}, cooked{&cooked}, context{context}, kindMap{kindMap}, @@ -6119,11 +6121,13 @@ Fortran::lower::LoweringBridge::LoweringBridge( fir::setTargetTriple(*module.get(), triple); fir::setKindMapping(*module.get(), kindMap); fir::setTargetCPU(*module.get(), targetMachine.getTargetCPU()); - fir::setTuneCPU(*module.get(), tuneCPU); + fir::setTuneCPU(*module.get(), targetOpts.cpuToTuneFor); fir::setTargetFeatures(*module.get(), targetMachine.getTargetFeatureString()); fir::support::setMLIRDataLayout(*module.get(), targetMachine.createDataLayout()); fir::setIdent(*module.get(), Fortran::common::getFlangFullVersion()); + if (cgOpts.RecordCommandLine) + fir::setCommandline(*module.get(), *cgOpts.RecordCommandLine); } void Fortran::lower::genCleanUpInRegionIfAny( diff --git a/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp b/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp index 5bd8e2d4336361..01c0be66d1ecc3 100644 --- a/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp +++ b/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp @@ -130,6 +130,22 @@ llvm::StringRef fir::getIdent(mlir::ModuleOp mod) { return {}; } +void fir::setCommandline(mlir::ModuleOp mod, llvm::StringRef cmdLine) { + if (cmdLine.empty()) + return; + + mlir::MLIRContext *ctx = mod.getContext(); + mod->setAttr(mlir::LLVM::LLVMDialect::getCommandlineAttrName(), + mlir::StringAttr::get(ctx, cmdLine)); +} + +llvm::StringRef fir::getCommandline(mlir::ModuleOp mod) { + if (auto attr = mod->getAttrOfType<mlir::StringAttr>( + mlir::LLVM::LLVMDialect::getCommandlineAttrName())) + return attr; + return {}; +} + std::string fir::determineTargetTriple(llvm::StringRef triple) { // Treat "" or "default" as stand-ins for the default machine. if (triple.empty() || triple == "default") diff --git a/flang/test/Driver/frecord-command-line.f90 b/flang/test/Driver/frecord-command-line.f90 new file mode 100644 index 00000000000000..bc4ce79e4a51c3 --- /dev/null +++ b/flang/test/Driver/frecord-command-line.f90 @@ -0,0 +1,16 @@ +! This only checks that the command line is correctly passed on to the +! -record-command-line option FC1 option and that the latter does not complain +! about anything. The correct lowering to a module attribute and beyond will +! be checked in other tests. +! +! RUN: %flang -### -target x86_64-unknown-linux -frecord-command-line %s 2>&1 | FileCheck --check-prefix=CHECK-RECORD %s +! RUN: %flang -### -target x86_64-unknown-macosx -frecord-command-line %s 2>&1 | FileCheck --check-prefix=CHECK-RECORD %s +! RUN: not %flang -### -target x86_64-unknown-windows -frecord-command-line %s 2>&1 | FileCheck --check-prefix=CHECK-RECORD-ERROR %s + +! RUN: %flang -### -target x86_64-unknown-linux -fno-record-command-line %s 2>&1 | FileCheck --check-prefix=CHECK-NO-RECORD %s +! RUN: %flang -### -target x86_64-unknown-macosx -fno-record-command-line %s 2>&1 | FileCheck --check-prefix=CHECK-NO-RECORD %s +! RUN: %flang -### -target x86_64-unknown-windows -fno-record-command-line %s 2>&1 | FileCheck --check-prefix=CHECK-NO-RECORD %s + +! CHECK-RECORD: "-record-command-line" +! CHECK-NO-RECORD-NOT: "-record-command-line" +! CHECK-RECORD-ERROR: error: unsupported option '-frecord-command-line' for target diff --git a/flang/test/Lower/record-command-line.f90 b/flang/test/Lower/record-command-line.f90 new file mode 100644 index 00000000000000..a7a25bb9e8725c --- /dev/null +++ b/flang/test/Lower/record-command-line.f90 @@ -0,0 +1,9 @@ +! The actual command line is recorded by the frontend and passed on to FC1 as +! the argument to -record-command-line, so in this test, we just match against +! some string with spaces that mimics what a hypothetical command line. + +! RUN: %flang_fc1 -record-command-line "exec -o infile" %s -emit-fir -o - | FileCheck %s + +! CHECK: module attributes { +! CHECK-SAME: llvm.commandline = "exec -o infile" + diff --git a/flang/tools/bbc/CMakeLists.txt b/flang/tools/bbc/CMakeLists.txt index 18fa7ac1d6cdc9..9abdcf17b6ebfd 100644 --- a/flang/tools/bbc/CMakeLists.txt +++ b/flang/tools/bbc/CMakeLists.txt @@ -25,6 +25,7 @@ target_link_libraries(bbc PRIVATE FIRBuilder HLFIRDialect HLFIRTransforms + flangFrontend flangPasses FlangOpenMPTransforms ${dialect_libs} diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp index 3a05f5f9844875..fe5e36f704c76c 100644 --- a/flang/tools/bbc/bbc.cpp +++ b/flang/tools/bbc/bbc.cpp @@ -19,6 +19,7 @@ #include "flang/Common/OpenMP-features.h" #include "flang/Common/Version.h" #include "flang/Common/default-kinds.h" +#include "flang/Frontend/CodeGenOptions.h" #include "flang/Frontend/TargetOptions.h" #include "flang/Lower/Bridge.h" #include "flang/Lower/PFTBuilder.h" @@ -382,12 +383,13 @@ static llvm::LogicalResult convertFortranSourceToMLIR( loweringOptions.setIntegerWrapAround(integerWrapAround); loweringOptions.setNSWOnLoopVarInc(setNSW); std::vector<Fortran::lower::EnvironmentDefault> envDefaults = {}; - constexpr const char *tuneCPU = ""; + Fortran::frontend::TargetOptions targetOpts; + Fortran::frontend::CodeGenOptions cgOpts; auto burnside = Fortran::lower::LoweringBridge::create( ctx, semanticsContext, defKinds, semanticsContext.intrinsics(), semanticsContext.targetCharacteristics(), parsing.allCooked(), targetTriple, kindMap, loweringOptions, envDefaults, - semanticsContext.languageFeatures(), targetMachine, tuneCPU); + semanticsContext.languageFeatures(), targetMachine, targetOpts, cgOpts); mlir::ModuleOp mlirModule = burnside.getModule(); if (enableOpenMP) { if (enableOpenMPGPU && !enableOpenMPDevice) { diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td index edcc34461f2f26..27a2b418aadb2a 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td @@ -33,6 +33,7 @@ def LLVM_Dialect : Dialect { static StringRef getAliasScopesAttrName() { return "alias_scopes"; } static StringRef getAccessGroupsAttrName() { return "access_groups"; } static StringRef getIdentAttrName() { return "llvm.ident"; } + static StringRef getCommandlineAttrName() { return "llvm.commandline"; } /// Names of llvm parameter attributes. static StringRef getAlignAttrName() { return "llvm.align"; } diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h index 436675793062eb..9f300bcafea537 100644 --- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h @@ -199,6 +199,10 @@ class ModuleImport { /// Converts !llvm.ident metadata to the llvm.ident LLVM ModuleOp attribute. LogicalResult convertIdentMetadata(); + /// Converts !llvm.commandline metadata to the llvm.commandline LLVM ModuleOp + /// attribute. + LogicalResult convertCommandlineMetadata(); + /// Converts all LLVM metadata nodes that translate to attributes such as /// alias analysis or access group metadata, and builds a map from the /// metadata nodes to the converted attributes. diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h index 3c85338bc642f6..ffeeeae57ae952 100644 --- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h @@ -332,6 +332,9 @@ class ModuleTranslation { /// Process the ident LLVM Metadata, if it exists. LogicalResult createIdentMetadata(); + /// Process the llvm.commandline LLVM Metadata, if it exists. + LogicalResult createCommandlineMetadata(); + /// Translates dialect attributes attached to the given operation. LogicalResult convertDialectAttributes(Operation *op, diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index da340f6c9b26d1..bd861f3a69e53c 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -535,6 +535,23 @@ LogicalResult ModuleImport::convertIdentMetadata() { return success(); } +LogicalResult ModuleImport::convertCommandlineMetadata() { + for (const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) { + // llvm.commandline should have a single operand. That operand is itself an + // MDNode with a single string operand. + if (nmd.getName() != LLVMDialect::getCommandlineAttrName()) + continue; + + if (nmd.getNumOperands() == 1) + if (auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0))) + if (md->getNumOperands() == 1) + if (auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0))) + mlirModule->setAttr(LLVMDialect::getCommandlineAttrName(), + builder.getStringAttr(mdStr->getString())); + } + return success(); +} + LogicalResult ModuleImport::convertMetadata() { OpBuilder::InsertionGuard guard(builder); builder.setInsertionPointToEnd(mlirModule.getBody()); @@ -565,6 +582,8 @@ LogicalResult ModuleImport::convertMetadata() { return failure(); if (failed(convertIdentMetadata())) return failure(); + if (failed(convertCommandlineMetadata())) + return failure(); return success(); } diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index 81a076717e73ee..6e005f9ec5df85 100644 --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -1837,6 +1837,21 @@ LogicalResult ModuleTranslation::createIdentMetadata() { return success(); } +LogicalResult ModuleTranslation::createCommandlineMetadata() { + if (auto attr = mlirModule->getAttrOfType<StringAttr>( + LLVMDialect::getCommandlineAttrName())) { + StringRef cmdLine = attr; + llvm::LLVMContext &ctx = llvmModule->getContext(); + llvm::NamedMDNode *nmd = llvmModule->getOrInsertNamedMetadata( + LLVMDialect::getCommandlineAttrName()); + llvm::MDNode *md = + llvm::MDNode::get(ctx, llvm::MDString::get(ctx, cmdLine)); + nmd->addOperand(md); + } + + return success(); +} + void ModuleTranslation::setLoopMetadata(Operation *op, llvm::Instruction *inst) { LoopAnnotationAttr attr = @@ -1990,6 +2005,8 @@ mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext, return nullptr; if (failed(translator.createIdentMetadata())) return nullptr; + if (failed(translator.createCommandlineMetadata())) + return nullptr; // Convert other top-level operations if possible. for (Operation &o : getModuleBody(module).getOperations()) { diff --git a/mlir/test/Target/LLVMIR/Import/commandline.ll b/mlir/test/Target/LLVMIR/Import/commandline.ll new file mode 100644 index 00000000000000..f31aec8cc5aac1 --- /dev/null +++ b/mlir/test/Target/LLVMIR/Import/commandline.ll @@ -0,0 +1,6 @@ +; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s + +; CHECK: module attributes { +; CHECK-SAME: llvm.commandline = "exec -o infile" +!llvm.commandline = !{!0} +!0 = !{!"exec -o infile"} diff --git a/mlir/test/Target/LLVMIR/commandline.mlir b/mlir/test/Target/LLVMIR/commandline.mlir new file mode 100644 index 00000000000000..817a5ac2164e9f --- /dev/null +++ b/mlir/test/Target/LLVMIR/commandline.mlir @@ -0,0 +1,6 @@ +// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s + +// CHECK: !llvm.commandline = !{![[S:[0-9]+]]} +// CHECK: ![[S]] = !{!"exec -o infile"} +module attributes {llvm.commandline = "exec -o infile"} { +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits