[Mlir-commits] [mlir] [mlir] Add llvm.linker.options operation to the LLVM IR Dialect (PR #71720)

David Truby llvmlistbot at llvm.org
Wed Nov 8 10:39:36 PST 2023


https://github.com/DavidTruby created https://github.com/llvm/llvm-project/pull/71720

This patch adds a `llvm.linker.options` operation taking a list of
strings to pass to the linker when the resulting object file is linked.
This is particularly useful on Windows to specify the CRT version to use
for this object file.

>From 9d0fe8fb6b0c2dab436ad2fe3ced7504d19b5186 Mon Sep 17 00:00:00 2001
From: David Truby <david at truby.dev>
Date: Wed, 8 Nov 2023 18:35:23 +0000
Subject: [PATCH] [mlir] Add llvm.linker.options operation to the LLVM IR
 Dialect

This patch adds a `llvm.linker.options` operation taking a list of
strings to pass to the linker when the resulting object file is linked.
This is particularly useful on Windows to specify the CRT version to use
for this object file.
---
 mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td   | 38 +++++++++++++++++++
 .../include/mlir/Target/LLVMIR/ModuleImport.h |  4 ++
 mlir/lib/Target/LLVMIR/ModuleImport.cpp       | 23 +++++++++++
 .../LLVMIR/Import/metadata-linker-options.ll  | 15 ++++++++
 mlir/test/Target/LLVMIR/llvmir.mlir           |  6 +++
 5 files changed, 86 insertions(+)
 create mode 100644 mlir/test/Target/LLVMIR/Import/metadata-linker-options.ll

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 638c31b39682ea6..7635bc92be0e136 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -1825,4 +1825,42 @@ def LLVM_CallIntrinsicOp
   let hasVerifier = 1;
 }
 
+def LLVM_LinkerOptionsOp
+    : LLVM_Op<"linker.options"> {
+  let summary = "Options to pass to the linker when the object file is linked";
+  let description = [{
+    Pass the given options to the linker when the resulting object file is linked.
+    This is used extensively on Windows to determine the C runtime that the object
+    files should link against.
+
+    Examples:
+    ```mlir
+    // Link against the MSVC static threaded CRT.
+    llvm.linker.options ["/DEFAULTLIB:", "libcmt"]
+
+    // Link against aarch64 compiler-rt builtins
+    llvm.linker.options ["-l", "clang_rt.builtins-aarch64"]
+    ```
+  }];
+  let arguments  = (ins StrArrayAttr:$options);
+  let assemblyFormat = [{
+    $options attr-dict
+  }];
+
+  let llvmBuilder = [{
+    llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
+    llvm::LLVMContext &context = llvmModule->getContext();
+    llvm::NamedMDNode *linkerMDNode = llvmModule->getOrInsertNamedMetadata("llvm.linker.options");
+    SmallVector<llvm::Metadata*> MDNodes;
+    for (auto s : $options) {
+      auto str = cast<StringAttr>(s);
+      auto *MDNode = llvm::MDString::get(context, str.getValue());
+      MDNodes.push_back(MDNode);
+    }
+
+    auto *listMDNode = llvm::MDTuple::get(context, MDNodes);
+    linkerMDNode->addOperand(listMDNode);
+  }];
+}
+
 #endif // LLVMIR_OPS
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
index 9bedc84e0bfa169..5f5adbff6c04ef8 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
@@ -177,6 +177,10 @@ class ModuleImport {
   /// implement the fastmath interface.
   void setFastmathFlagsAttr(llvm::Instruction *inst, Operation *op) const;
 
+  /// Converts !llvm.linker.options metadata to the llvm.linker.options
+  /// LLVM dialect operation.
+  LogicalResult convertLinkerOptionsMetadata();
+
   /// 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/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index e3562049cd81c76..7d133b309f87a7c 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -487,6 +487,27 @@ void ModuleImport::addDebugIntrinsic(llvm::CallInst *intrinsic) {
   debugIntrinsics.insert(intrinsic);
 }
 
+LogicalResult ModuleImport::convertLinkerOptionsMetadata() {
+  for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
+    if (named.getName() != "llvm.linker.options")
+      continue;
+    // llvm.linker.options operands are lists of strings.
+    for (const llvm::MDNode *md : named.operands()) {
+      SmallVector<StringRef> options;
+      for (const llvm::MDOperand &option : md->operands()) {
+        if (auto str = dyn_cast_or_null<llvm::MDString>(option))
+          options.push_back(str->getString());
+        else
+          return emitError(mlirModule.getLoc(),
+                           "argument to llvm.linker.options is not a string");
+      }
+      builder.create<LLVM::LinkerOptionsOp>(mlirModule.getLoc(),
+                                            builder.getStrArrayAttr(options));
+    }
+  }
+  return success();
+}
+
 LogicalResult ModuleImport::convertMetadata() {
   OpBuilder::InsertionGuard guard(builder);
   builder.setInsertionPointToEnd(mlirModule.getBody());
@@ -513,6 +534,8 @@ LogicalResult ModuleImport::convertMetadata() {
           return failure();
     }
   }
+  if (failed(convertLinkerOptionsMetadata()))
+    return failure();
   return success();
 }
 
diff --git a/mlir/test/Target/LLVMIR/Import/metadata-linker-options.ll b/mlir/test/Target/LLVMIR/Import/metadata-linker-options.ll
new file mode 100644
index 000000000000000..473d26ecd598959
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/Import/metadata-linker-options.ll
@@ -0,0 +1,15 @@
+; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s
+
+; CHECK: llvm.linker.options ["DEFAULTLIB:", "libcmt"]
+!llvm.linker.options = !{!0}
+!0 = !{!"DEFAULTLIB:", !"libcmt"}
+
+; // -----
+
+!llvm.linker.options = !{!0, !1, !2}
+; CHECK: llvm.linker.options ["DEFAULTLIB:", "libcmt"]
+!0 = !{!"DEFAULTLIB:", !"libcmt"}
+; CHECK: llvm.linker.options ["DEFAULTLIB:", "libcmtd"]
+!1 = !{!"DEFAULTLIB:", !"libcmtd"}
+; CHECK: llvm.linker.options ["-lm"]
+!2 = !{!"-lm"}
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index 7da44b6fbe1ab33..fa3cd7679112440 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -2337,3 +2337,9 @@ llvm.func @zeroinit_complex_local_aggregate() {
 
   llvm.return
 }
+
+//CHECK: !llvm.linker.options = !{![[MD0:[0-9]+]], ![[MD1:[0-9]+]]}
+//CHECK: ![[MD0]] = !{!"/DEFAULTLIB:", !"libcmt"}
+llvm.linker.options ["/DEFAULTLIB:", "libcmt"]
+//CHECK: ![[MD1]] = !{!"/DEFAULTLIB:", !"libcmtd"}
+llvm.linker.options ["/DEFAULTLIB:", "libcmtd"]
\ No newline at end of file



More information about the Mlir-commits mailing list