[flang] [clang] [flang] Add depdendent-lib option to flang -fc1 on Windows (PR #72121)

David Truby via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 13 06:53:36 PST 2023


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 <david at 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



More information about the cfe-commits mailing list