https://github.com/DavidTruby created https://github.com/llvm/llvm-project/pull/72121
This patch adds a --depdendent-lib option to flang -fc1 on Windows to embed library link options into the object file. This is needed to properly select the Windows CRT to link against. >From cfd46a8825aa34b3e513d898ceb57f4e48e78faf Mon Sep 17 00:00:00 2001 From: David Truby <da...@truby.dev> Date: Mon, 13 Nov 2023 14:48:44 +0000 Subject: [PATCH] [flang] Add depdendent-lib option to flang -fc1 on Windows This patch adds a --depdendent-lib option to flang -fc1 on Windows to embed library link options into the object file. This is needed to properly select the Windows CRT to link against. --- clang/include/clang/Driver/Options.td | 8 ++++--- flang/include/flang/Frontend/CodeGenOptions.h | 3 +++ flang/lib/Frontend/CompilerInvocation.cpp | 23 +++++++++++++++++++ flang/lib/Frontend/FrontendActions.cpp | 23 +++++++++++++++++++ flang/test/Driver/dependent-lib.f90 | 7 ++++++ flang/test/Driver/driver-help.f90 | 1 + 6 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 flang/test/Driver/dependent-lib.f90 diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index d1b67a448b2a59b..c7eb52145f614b4 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -6796,9 +6796,6 @@ def vectorize_loops : Flag<["-"], "vectorize-loops">, def vectorize_slp : Flag<["-"], "vectorize-slp">, HelpText<"Run the SLP vectorization passes">, MarshallingInfoFlag<CodeGenOpts<"VectorizeSLP">>; -def dependent_lib : Joined<["--"], "dependent-lib=">, - HelpText<"Add dependent library">, - MarshallingInfoStringVector<CodeGenOpts<"DependentLibraries">>; def linker_option : Joined<["--"], "linker-option=">, HelpText<"Add linker option">, MarshallingInfoStringVector<CodeGenOpts<"LinkerOptions">>; @@ -7369,6 +7366,11 @@ def pic_is_pie : Flag<["-"], "pic-is-pie">, HelpText<"File is for a position independent executable">, MarshallingInfoFlag<LangOpts<"PIE">>; + +def dependent_lib : Joined<["--"], "dependent-lib=">, + HelpText<"Add dependent library">, + MarshallingInfoStringVector<CodeGenOpts<"DependentLibraries">>; + } // let Visibility = [CC1Option, FC1Option] let Visibility = [CC1Option] in { diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h index a3c39bda10667be..b86bb88610a9a4a 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.h +++ b/flang/include/flang/Frontend/CodeGenOptions.h @@ -70,6 +70,9 @@ class CodeGenOptions : public CodeGenOptionsBase { /// The format used for serializing remarks (default: YAML) std::string OptRecordFormat; + /// Options to add to the linker for the object file + std::vector<std::string> DependentLibs; + // The RemarkKind enum class and OptRemark struct are identical to what Clang // has // TODO: Share with clang instead of re-implementing here diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 334da3ac287e3bf..cb4f2d6a6225205 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -1054,6 +1054,27 @@ static bool parseVScaleArgs(CompilerInvocation &invoc, llvm::opt::ArgList &args, return true; } +static bool parseLinkerOptionsArgs(CompilerInvocation &invoc, + llvm::opt::ArgList &args, + clang::DiagnosticsEngine &diags) { + llvm::Triple triple = llvm::Triple(invoc.getTargetOpts().triple); + + // TODO: support --dependent-lib on other platforms when MLIR supports + // !llvm.dependent.lib + if (args.hasArg(clang::driver::options::OPT_dependent_lib) && + !triple.isOSWindows()) { + const unsigned diagID = + diags.getCustomDiagID(clang::DiagnosticsEngine::Error, + "--dependent-lib is only supported on Windows"); + diags.Report(diagID); + return false; + } + + invoc.getCodeGenOpts().DependentLibs = + args.getAllArgValues(clang::driver::options::OPT_dependent_lib); + return true; +} + bool CompilerInvocation::createFromArgs( CompilerInvocation &res, llvm::ArrayRef<const char *> commandLineArgs, clang::DiagnosticsEngine &diags, const char *argv0) { @@ -1163,6 +1184,8 @@ bool CompilerInvocation::createFromArgs( success &= parseVScaleArgs(res, args, diags); + success &= parseLinkerOptionsArgs(res, args, diags); + // Set the string to be used as the return value of the COMPILER_OPTIONS // intrinsic of iso_fortran_env. This is either passed in from the parent // compiler driver invocation with an environment variable, or failing that diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index d7ca7b66584dd52..8df966571bc39ab 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -203,6 +203,26 @@ static void setMLIRDataLayout(mlir::ModuleOp &mlirModule, mlirModule->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dlSpec); } +static void addDepdendentLibs(mlir::ModuleOp &mlirModule, + CompilerInstance &ci) { + const std::vector<std::string> &libs = + ci.getInvocation().getCodeGenOpts().DependentLibs; + if (libs.empty()) { + return; + } + // dependent-lib is currently only supported on Windows, so the list should be + // empty on non-Windows platforms + assert( + llvm::Triple(ci.getInvocation().getTargetOpts().triple).isOSWindows() && + "--dependent-lib is only supported on Windows"); + // Add linker options specified by --dependent-lib + auto builder = mlir::OpBuilder(mlirModule.getRegion()); + for (const std::string &lib : libs) { + builder.create<mlir::LLVM::LinkerOptionsOp>( + mlirModule.getLoc(), builder.getStrArrayAttr({"/DEFAULTLIB:", lib})); + } +} + bool CodeGenAction::beginSourceFileAction() { llvmCtx = std::make_unique<llvm::LLVMContext>(); CompilerInstance &ci = this->getInstance(); @@ -303,6 +323,9 @@ bool CodeGenAction::beginSourceFileAction() { Fortran::parser::Program &parseTree{*ci.getParsing().parseTree()}; lb.lower(parseTree, ci.getInvocation().getSemanticsContext()); + // Add dependent libraries + addDepdendentLibs(*mlirModule, ci); + // run the default passes. mlir::PassManager pm((*mlirModule)->getName(), mlir::OpPassManager::Nesting::Implicit); diff --git a/flang/test/Driver/dependent-lib.f90 b/flang/test/Driver/dependent-lib.f90 new file mode 100644 index 000000000000000..e455d06258662a1 --- /dev/null +++ b/flang/test/Driver/dependent-lib.f90 @@ -0,0 +1,7 @@ + +! RUN: %flang_fc1 -emit-mlir -triple aarch64-pc-windows-msvc --dependent-lib=libtest %s -o - 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-mlir -triple x86_64-pc-windows-msvc --dependent-lib=libtest %s -o - 2>&1 | FileCheck %s + +! CHECK: llvm.linker_options ["/DEFAULTLIB:", "libtest"] +program test +end program test \ No newline at end of file diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90 index ea9c892bd621058..452c62541e72e61 100644 --- a/flang/test/Driver/driver-help.f90 +++ b/flang/test/Driver/driver-help.f90 @@ -141,6 +141,7 @@ ! HELP-FC1-EMPTY: ! HELP-FC1-NEXT:OPTIONS: ! HELP-FC1-NEXT: -cpp Enable predefined and command line preprocessor macros +! HELP-FC1-NEXT: --dependent-lib=<value> Add dependent library ! HELP-FC1-NEXT: -D <macro>=<value> Define <macro> to <value> (or 1 if <value> omitted) ! HELP-FC1-NEXT: -emit-fir Build the parse tree, then lower it to FIR ! HELP-FC1-NEXT: -emit-hlfir Build the parse tree, then lower it to HLFIR _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits