[Mlir-commits] [mlir] [mlir][LLVM] Preserve !associated and !absolute_symbol on llvm.mlir.global (PR #218839)
Tanishq Khurana
llvmlistbot at llvm.org
Wed Aug 26 08:55:58 PDT 2026
https://github.com/ktanishqk updated https://github.com/llvm/llvm-project/pull/218839
>From e4473d4ea20ef6e8b0e39049e14dd12dd76157ad Mon Sep 17 00:00:00 2001
From: ktanishqk <tanishqk0102 at gmail.com>
Date: Tue, 25 Aug 2026 22:27:03 -0700
Subject: [PATCH 1/2] tests + storage of metadata globals in dialect
---
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 21 +++++++++
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 21 +++++++++
mlir/lib/Target/LLVMIR/ModuleImport.cpp | 44 +++++++++++++++++++
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 32 ++++++++++++++
mlir/test/Dialect/LLVMIR/global.mlir | 34 ++++++++++++++
.../Target/LLVMIR/Import/global-variables.ll | 42 ++++++++++++++++++
mlir/test/Target/LLVMIR/llvmir.mlir | 41 +++++++++++++++++
7 files changed, 235 insertions(+)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 84f71054994f4..83bc0dad5d137 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -1393,6 +1393,8 @@ def LLVM_GlobalOp : LLVM_Op<"mlir.global",
DefaultValuedAttr<ConfinedAttr<I32Attr, [IntNonNegative]>, "0">:$addr_space,
OptionalAttr<UnnamedAddr>:$unnamed_addr,
OptionalAttr<StrAttr>:$section,
+ OptionalAttr<FlatSymbolRefAttr>:$associated,
+ OptionalAttr<ArrayAttr>:$absolute_symbol,
OptionalAttr<SymbolRefAttr>:$comdat,
OptionalAttr<DIGlobalVariableExpressionArrayAttr>:$dbg_exprs,
DefaultValuedAttr<Visibility, "mlir::LLVM::Visibility::Default">:$visibility_,
@@ -1494,6 +1496,25 @@ def LLVM_GlobalOp : LLVM_Op<"mlir.global",
llvm.mlir.global private constant @y(dense<1.0> : tensor<8xf32>) { alignment = 32 : i64 } : !llvm.array<8 x f32>
```
+ The optional `associated` attribute models LLVM IR `!associated` metadata
+ on a global. It is a symbol reference to another global object (or an
+ alias of one) and is used to emit `SHF_LINK_ORDER` on ELF.
+
+ The optional `absolute_symbol` attribute models LLVM IR `!absolute_symbol`
+ metadata. It is an array of integer attributes forming one or more
+ `[lower, upper)` range pairs for the global's address, using the same
+ encoding as LLVM `range` metadata. The pair `[-1, -1]` represents the
+ full set.
+
+ Examples:
+
+ ```mlir
+ llvm.mlir.global external @b(0 : i32) : i32
+ llvm.mlir.global external @a(0 : i32) {associated = @b} : i32
+
+ llvm.mlir.global external @abs_sym() {absolute_symbol = [0 : i64, 42 : i64]} : i8
+ ```
+
The `target_specific_attrs` attribute provides a mechanism to preserve
target-specific LLVM IR attributes that are not explicitly modeled in the
LLVM dialect.
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 6382dfcbc8ad2..3b2f7d129fb3a 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -2671,6 +2671,27 @@ LogicalResult GlobalOp::verify() {
return emitError() << "alignment attribute is not a power of 2";
}
+ if (FlatSymbolRefAttr associated = getAssociatedAttr()) {
+ if (associated.getValue() == getSymName())
+ return emitOpError("associated cannot refer to the global itself");
+ }
+
+ if (ArrayAttr absSym = getAbsoluteSymbolAttr()) {
+ if (absSym.empty() || absSym.size() % 2 != 0)
+ return emitOpError(
+ "absolute_symbol must contain one or more integer range pairs");
+ Type pairType;
+ for (Attribute attr : absSym) {
+ auto intAttr = dyn_cast<IntegerAttr>(attr);
+ if (!intAttr)
+ return emitOpError("absolute_symbol operands must be integers");
+ if (!pairType)
+ pairType = intAttr.getType();
+ else if (intAttr.getType() != pairType)
+ return emitOpError("absolute_symbol range pair types must match");
+ }
+ }
+
return success();
}
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 725d7cf6c8413..8730b5d67b901 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -1648,6 +1648,50 @@ LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
if (globalVar->hasComdat())
globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
+ if (llvm::MDNode *associatedMD =
+ globalVar->getMetadata(llvm::LLVMContext::MD_associated)) {
+ if (associatedMD->getNumOperands() == 1) {
+ if (auto *valueAsMD = dyn_cast_or_null<llvm::ValueAsMetadata>(
+ associatedMD->getOperand(0).get())) {
+ llvm::Value *value = valueAsMD->getValue();
+ llvm::GlobalValue *gv = dyn_cast<llvm::GlobalValue>(value);
+ if (!gv)
+ gv = dyn_cast<llvm::GlobalValue>(value->stripPointerCastsAndAliases());
+ if (gv) {
+ StringRef name = gv->getName();
+ FlatSymbolRefAttr symbolRef;
+ if (name.empty()) {
+ if (auto *namelessVar = dyn_cast<llvm::GlobalVariable>(gv))
+ symbolRef = getOrCreateNamelessSymbolName(namelessVar);
+ } else {
+ symbolRef = FlatSymbolRefAttr::get(context, name);
+ }
+ if (symbolRef)
+ globalOp.setAssociatedAttr(symbolRef);
+ }
+ }
+ }
+ }
+
+ if (llvm::MDNode *absSymMD =
+ globalVar->getMetadata(llvm::LLVMContext::MD_absolute_symbol)) {
+ SmallVector<Attribute> rangeAttrs;
+ rangeAttrs.reserve(absSymMD->getNumOperands());
+ bool valid = absSymMD->getNumOperands() >= 2 &&
+ absSymMD->getNumOperands() % 2 == 0;
+ for (const llvm::MDOperand &op : absSymMD->operands()) {
+ auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(op);
+ if (!constInt) {
+ valid = false;
+ break;
+ }
+ auto intType = IntegerType::get(context, constInt->getBitWidth());
+ rangeAttrs.push_back(IntegerAttr::get(intType, constInt->getValue()));
+ }
+ if (valid)
+ globalOp.setAbsoluteSymbolAttr(ArrayAttr::get(context, rangeAttrs));
+ }
+
processTargetSpecificAttrs(globalVar, globalOp);
return success();
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 47e63e2aa279a..d6b5287d78bf2 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -45,6 +45,7 @@
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/Debug.h"
@@ -1383,6 +1384,37 @@ LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
aliasesMapping.try_emplace(op, var);
}
+ // Attach global metadata after all globals, aliases, and function signatures
+ // exist so symbol references can be resolved.
+ for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
+ auto *var = cast<llvm::GlobalVariable>(lookupGlobal(op));
+ if (FlatSymbolRefAttr associated = op.getAssociatedAttr()) {
+ auto mdAttr = MDGlobalValueAttr::get(op.getContext(), associated);
+ FailureOr<llvm::Metadata *> md = convertMetadataAttr(mdAttr, [&]() {
+ return op.emitError("failed to convert associated metadata");
+ });
+ if (failed(md))
+ return failure();
+ var->setMetadata(llvm::LLVMContext::MD_associated,
+ llvm::MDNode::get(var->getContext(), *md));
+ }
+
+ if (ArrayAttr absSym = op.getAbsoluteSymbolAttr()) {
+ SmallVector<llvm::Metadata *> mdOps;
+ llvm::LLVMContext &ctx = var->getContext();
+ mdOps.reserve(absSym.size());
+ for (Attribute attr : absSym) {
+ auto intAttr = llvm::cast<IntegerAttr>(attr);
+ llvm::IntegerType *ty = llvm::IntegerType::get(
+ ctx, intAttr.getType().getIntOrFloatBitWidth());
+ mdOps.push_back(llvm::ConstantAsMetadata::get(
+ llvm::ConstantInt::get(ty, intAttr.getValue())));
+ }
+ var->setMetadata(llvm::LLVMContext::MD_absolute_symbol,
+ llvm::MDNode::get(ctx, mdOps));
+ }
+ }
+
// Convert global variable bodies.
for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
if (Block *initializer = op.getInitializerBlock()) {
diff --git a/mlir/test/Dialect/LLVMIR/global.mlir b/mlir/test/Dialect/LLVMIR/global.mlir
index 193ab7987a2b6..a72dad1f796a5 100644
--- a/mlir/test/Dialect/LLVMIR/global.mlir
+++ b/mlir/test/Dialect/LLVMIR/global.mlir
@@ -292,3 +292,37 @@ llvm.mlir.global external @global_with_expr1() {addr_space = 0 : i32, dbg_expr =
llvm.mlir.global external @global_with_expr2() {addr_space = 0 : i32, dbg_expr = [#llvm.di_global_variable_expression<var = <scope = #di_compile_unit, name = "global_with_expr_2", linkageName = "global_with_expr_2", file = #di_file, line = 371, type = #di_basic_type, isLocalToUnit = true, isDefined = true, alignInBits = 8>, expr = <[DW_OP_push_object_address, DW_OP_deref]>>]} : i64
llvm.mlir.global external @global_with_expr3() {addr_space = 0 : i32, dbg_expr = [#llvm.di_global_variable_expression<var = <scope = #di_compile_unit, name = "global_with_expr_3", linkageName = "global_with_expr_3", file = #di_file, line = 372, type = #di_basic_type, isLocalToUnit = true, isDefined = true, alignInBits = 8>, expr = <[DW_OP_LLVM_arg(0), DW_OP_LLVM_arg(1), DW_OP_plus]>>]} : i64
llvm.mlir.global external @global_with_expr4() {addr_space = 0 : i32, dbg_expr = [#llvm.di_global_variable_expression<var = <scope = #di_compile_unit, name = "global_with_expr_4", linkageName = "global_with_expr_4", file = #di_file, line = 373, type = #di_basic_type, isLocalToUnit = true, isDefined = true, alignInBits = 8>, expr = <[DW_OP_LLVM_convert(16, DW_ATE_signed)]>>]} : i64
+
+// -----
+
+// CHECK: llvm.mlir.global external @associated_target(0 : i32) {addr_space = 0 : i32} : i32
+// CHECK: llvm.mlir.global external @associated_global(0 : i32) {addr_space = 0 : i32, associated = @associated_target} : i32
+llvm.mlir.global external @associated_target(0 : i32) : i32
+llvm.mlir.global external @associated_global(0 : i32) {associated = @associated_target} : i32
+
+// CHECK: llvm.mlir.global external @absolute_symbol_global() {absolute_symbol = [0, 42], addr_space = 0 : i32} : i8
+llvm.mlir.global external @absolute_symbol_global() {absolute_symbol = [0 : i64, 42 : i64]} : i8
+
+// CHECK: llvm.mlir.global external @absolute_symbol_full() {absolute_symbol = [-1, -1], addr_space = 0 : i32} : i8
+llvm.mlir.global external @absolute_symbol_full() {absolute_symbol = [-1 : i64, -1 : i64]} : i8
+
+// -----
+
+// expected-error @+1 {{associated cannot refer to the global itself}}
+llvm.mlir.global @self_associated(0 : i32) {associated = @self_associated} : i32
+
+// -----
+
+// expected-error @+1 {{absolute_symbol must contain one or more integer range pairs}}
+llvm.mlir.global @odd_absolute_symbol() {absolute_symbol = [0 : i64]} : i8
+
+// -----
+
+// expected-error @+1 {{absolute_symbol operands must be integers}}
+llvm.mlir.global @non_int_absolute_symbol() {absolute_symbol = ["foo", "bar"]} : i8
+
+// -----
+
+// expected-error @+1 {{absolute_symbol range pair types must match}}
+llvm.mlir.global @mixed_absolute_symbol() {absolute_symbol = [0 : i32, 42 : i64]} : i8
+
diff --git a/mlir/test/Target/LLVMIR/Import/global-variables.ll b/mlir/test/Target/LLVMIR/Import/global-variables.ll
index 2be36c4366304..1d49726fb8966 100644
--- a/mlir/test/Target/LLVMIR/Import/global-variables.ll
+++ b/mlir/test/Target/LLVMIR/Import/global-variables.ll
@@ -373,3 +373,45 @@ attributes #0 = { readnone "int-attr"="4" "no-enum-attr" "string-attr"="string"
; CHECK-SAME: target_specific_attrs = ["norecurse", ["bss-section", "my_bss.1"]]}
@target_specific_attrs_combined = global i32 2, align 4, section "mysection" #0
attributes #0 = { norecurse "bss-section"="my_bss.1" }
+
+; // -----
+
+; CHECK: llvm.mlir.global external @a
+; CHECK-SAME: {addr_space = 0 : i32, associated = @b} : i32
+; CHECK: llvm.mlir.global external @b
+; CHECK-SAME: {addr_space = 0 : i32} : i32
+ at a = global i32 0, !associated !0
+ at b = global i32 0
+!0 = !{ptr @b}
+
+; // -----
+
+; CHECK: llvm.mlir.global external @a
+; CHECK-SAME: {addr_space = 0 : i32, associated = @f} : i32
+ at a = global i32 0, !associated !0
+declare void @f()
+!0 = !{ptr @f}
+
+; // -----
+
+; CHECK: llvm.mlir.global external @associated_via_alias
+; CHECK-SAME: associated = @alias_of_target
+ at alias_target = global i32 1
+ at alias_of_target = alias i32, ptr @alias_target
+ at associated_via_alias = global i32 2, !associated !0
+!0 = !{ptr @alias_of_target}
+
+; // -----
+
+; CHECK: llvm.mlir.global external @a()
+; CHECK-SAME: {absolute_symbol = [0 : i64, 42 : i64], addr_space = 0 : i32} : i8
+ at a = external global i8, !absolute_symbol !0
+!0 = !{i64 0, i64 42}
+
+; // -----
+
+; CHECK: llvm.mlir.global external @a()
+; CHECK-SAME: {absolute_symbol = [-1 : i64, -1 : i64], addr_space = 0 : i32} : i8
+ at a = external global i8, !absolute_symbol !0
+!0 = !{i64 -1, i64 -1}
+
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index 5ffbb3eef7bb0..c00b69bdbeb3b 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -3633,6 +3633,47 @@ llvm.mlir.global external @target_specific_attrs_combined(2 : i32) {alignment =
// -----
+// CHECK: @associated_target = global i32 0
+// CHECK: @associated_global = global i32 0, !associated ![[ASSOC:[0-9]+]]
+// CHECK: ![[ASSOC]] = !{ptr @associated_target}
+llvm.mlir.global external @associated_target(0 : i32) {addr_space = 0 : i32} : i32
+llvm.mlir.global external @associated_global(0 : i32) {addr_space = 0 : i32, associated = @associated_target} : i32
+
+// -----
+
+// CHECK: @associated_fn_global = global i32 0, !associated ![[ASSOC_FN:[0-9]+]]
+// CHECK: declare void @associated_fn()
+// CHECK: ![[ASSOC_FN]] = !{ptr @associated_fn}
+llvm.mlir.global external @associated_fn_global(0 : i32) {associated = @associated_fn} : i32
+llvm.func @associated_fn()
+
+// -----
+
+// CHECK: @alias_target = global i32 1
+// CHECK: @associated_via_alias = global i32 2, !associated ![[ASSOC_ALIAS:[0-9]+]]
+// CHECK: @alias_of_target = alias i32, ptr @alias_target
+// CHECK: ![[ASSOC_ALIAS]] = !{ptr @alias_of_target}
+llvm.mlir.global @alias_target(1 : i32) : i32
+llvm.mlir.alias external @alias_of_target : i32 {
+ %0 = llvm.mlir.addressof @alias_target : !llvm.ptr
+ llvm.return %0 : !llvm.ptr
+}
+llvm.mlir.global @associated_via_alias(2 : i32) {associated = @alias_of_target} : i32
+
+// -----
+
+// CHECK: @absolute_symbol_global = external global i8, !absolute_symbol ![[ABS:[0-9]+]]
+// CHECK: ![[ABS]] = !{i64 0, i64 42}
+llvm.mlir.global external @absolute_symbol_global() {absolute_symbol = [0 : i64, 42 : i64]} : i8
+
+// -----
+
+// CHECK: @absolute_symbol_full = external global i8, !absolute_symbol ![[ABS_FULL:[0-9]+]]
+// CHECK: ![[ABS_FULL]] = !{i64 -1, i64 -1}
+llvm.mlir.global external @absolute_symbol_full() {absolute_symbol = [-1 : i64, -1 : i64]} : i8
+
+// -----
+
// CHECK-LABEL: define b8 @byte_type(b8 %0)
llvm.func @byte_type(%arg0: !llvm.byte<8>) -> !llvm.byte<8> {
llvm.return %arg0 : !llvm.byte<8>
>From 8c86d63c426d1ed6941a789ab0263de6fe36ccf1 Mon Sep 17 00:00:00 2001
From: ktanishqk <tanishqk0102 at gmail.com>
Date: Wed, 26 Aug 2026 08:55:43 -0700
Subject: [PATCH 2/2] export failure fix
---
.../mlir/Target/LLVMIR/ModuleTranslation.h | 7 ++
mlir/lib/Target/LLVMIR/ModuleImport.cpp | 7 +-
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 68 ++++++++++---------
mlir/test/Dialect/LLVMIR/global.mlir | 9 +++
.../Target/LLVMIR/Import/global-variables.ll | 16 ++++-
mlir/test/Target/LLVMIR/llvmir.mlir | 12 ++++
6 files changed, 83 insertions(+), 36 deletions(-)
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
index b23f78ff0f98a..59b48c6c1cc7c 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
@@ -427,7 +427,14 @@ class ModuleTranslation {
/// - Create named global variables that correspond to llvm.mlir.global
/// definitions, similarly Convert llvm.global_ctors and global_dtors ops.
/// - Create global alias that correspond to llvm.mlir.alias.
+ /// Global metadata that can reference other global objects (including
+ /// ifuncs) is converted later by `convertGlobalMetadata`.
LogicalResult convertGlobalsAndAliases();
+
+ /// Attach metadata on LLVM globals after all global objects exist so that
+ /// symbol references (globals, aliases, functions, and ifuncs) can be
+ /// resolved.
+ LogicalResult convertGlobalMetadata();
LogicalResult convertOneFunction(LLVMFuncOp func);
LogicalResult convertBlockImpl(Block &bb, bool ignoreArguments,
llvm::IRBuilderBase &builder,
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 8730b5d67b901..af93c0043da37 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -1656,7 +1656,8 @@ LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
llvm::Value *value = valueAsMD->getValue();
llvm::GlobalValue *gv = dyn_cast<llvm::GlobalValue>(value);
if (!gv)
- gv = dyn_cast<llvm::GlobalValue>(value->stripPointerCastsAndAliases());
+ gv =
+ dyn_cast<llvm::GlobalValue>(value->stripPointerCastsAndAliases());
if (gv) {
StringRef name = gv->getName();
FlatSymbolRefAttr symbolRef;
@@ -1677,8 +1678,8 @@ LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
globalVar->getMetadata(llvm::LLVMContext::MD_absolute_symbol)) {
SmallVector<Attribute> rangeAttrs;
rangeAttrs.reserve(absSymMD->getNumOperands());
- bool valid = absSymMD->getNumOperands() >= 2 &&
- absSymMD->getNumOperands() % 2 == 0;
+ bool valid =
+ absSymMD->getNumOperands() >= 2 && absSymMD->getNumOperands() % 2 == 0;
for (const llvm::MDOperand &op : absSymMD->operands()) {
auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(op);
if (!constInt) {
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index d6b5287d78bf2..e0a6e704b2957 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1384,37 +1384,6 @@ LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
aliasesMapping.try_emplace(op, var);
}
- // Attach global metadata after all globals, aliases, and function signatures
- // exist so symbol references can be resolved.
- for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
- auto *var = cast<llvm::GlobalVariable>(lookupGlobal(op));
- if (FlatSymbolRefAttr associated = op.getAssociatedAttr()) {
- auto mdAttr = MDGlobalValueAttr::get(op.getContext(), associated);
- FailureOr<llvm::Metadata *> md = convertMetadataAttr(mdAttr, [&]() {
- return op.emitError("failed to convert associated metadata");
- });
- if (failed(md))
- return failure();
- var->setMetadata(llvm::LLVMContext::MD_associated,
- llvm::MDNode::get(var->getContext(), *md));
- }
-
- if (ArrayAttr absSym = op.getAbsoluteSymbolAttr()) {
- SmallVector<llvm::Metadata *> mdOps;
- llvm::LLVMContext &ctx = var->getContext();
- mdOps.reserve(absSym.size());
- for (Attribute attr : absSym) {
- auto intAttr = llvm::cast<IntegerAttr>(attr);
- llvm::IntegerType *ty = llvm::IntegerType::get(
- ctx, intAttr.getType().getIntOrFloatBitWidth());
- mdOps.push_back(llvm::ConstantAsMetadata::get(
- llvm::ConstantInt::get(ty, intAttr.getValue())));
- }
- var->setMetadata(llvm::LLVMContext::MD_absolute_symbol,
- llvm::MDNode::get(ctx, mdOps));
- }
- }
-
// Convert global variable bodies.
for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
if (Block *initializer = op.getInitializerBlock()) {
@@ -2219,6 +2188,41 @@ LogicalResult ModuleTranslation::convertIFuncs() {
return success();
}
+// Attach global metadata after all globals, aliases, ifuncs, and function
+// signatures exist so symbol references can be resolved.
+LogicalResult ModuleTranslation::convertGlobalMetadata() {
+ for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
+ auto *var = cast<llvm::GlobalVariable>(lookupGlobal(op));
+ if (FlatSymbolRefAttr associated = op.getAssociatedAttr()) {
+ auto mdAttr = MDGlobalValueAttr::get(op.getContext(), associated);
+ FailureOr<llvm::Metadata *> md = convertMetadataAttr(mdAttr, [&]() {
+ return op.emitError("failed to convert associated metadata");
+ });
+ if (failed(md))
+ return failure();
+ var->setMetadata(llvm::LLVMContext::MD_associated,
+ llvm::MDNode::get(var->getContext(), *md));
+ }
+
+ if (ArrayAttr absSym = op.getAbsoluteSymbolAttr()) {
+ SmallVector<llvm::Metadata *> mdOps;
+ llvm::LLVMContext &ctx = var->getContext();
+ mdOps.reserve(absSym.size());
+ for (Attribute attr : absSym) {
+ auto intAttr = llvm::cast<IntegerAttr>(attr);
+ llvm::IntegerType *ty = llvm::IntegerType::get(
+ ctx, intAttr.getType().getIntOrFloatBitWidth());
+ mdOps.push_back(llvm::ConstantAsMetadata::get(
+ llvm::ConstantInt::get(ty, intAttr.getValue())));
+ }
+ var->setMetadata(llvm::LLVMContext::MD_absolute_symbol,
+ llvm::MDNode::get(ctx, mdOps));
+ }
+ }
+
+ return success();
+}
+
LogicalResult ModuleTranslation::convertComdats() {
for (auto comdatOp : getModuleBody(mlirModule).getOps<ComdatOp>()) {
for (auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
@@ -2678,6 +2682,8 @@ mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
return nullptr;
if (failed(translator.convertIFuncs()))
return nullptr;
+ if (failed(translator.convertGlobalMetadata()))
+ return nullptr;
if (failed(translator.createTBAAMetadata()))
return nullptr;
if (failed(translator.createIdentMetadata()))
diff --git a/mlir/test/Dialect/LLVMIR/global.mlir b/mlir/test/Dialect/LLVMIR/global.mlir
index a72dad1f796a5..37c7d433c5dd3 100644
--- a/mlir/test/Dialect/LLVMIR/global.mlir
+++ b/mlir/test/Dialect/LLVMIR/global.mlir
@@ -300,6 +300,15 @@ llvm.mlir.global external @global_with_expr4() {addr_space = 0 : i32, dbg_expr =
llvm.mlir.global external @associated_target(0 : i32) : i32
llvm.mlir.global external @associated_global(0 : i32) {associated = @associated_target} : i32
+// CHECK: llvm.mlir.global external @associated_ifunc_global(0 : i32) {addr_space = 0 : i32, associated = @associated_ifunc} : i32
+// CHECK: llvm.mlir.ifunc external @associated_ifunc : !llvm.func<i32 (i32)>, !llvm.ptr @associated_ifunc_resolver
+llvm.mlir.global external @associated_ifunc_global(0 : i32) {associated = @associated_ifunc} : i32
+llvm.mlir.ifunc external @associated_ifunc : !llvm.func<i32 (i32)>, !llvm.ptr @associated_ifunc_resolver
+llvm.func @associated_ifunc_resolver() -> !llvm.ptr {
+ %0 = llvm.mlir.zero : !llvm.ptr
+ llvm.return %0 : !llvm.ptr
+}
+
// CHECK: llvm.mlir.global external @absolute_symbol_global() {absolute_symbol = [0, 42], addr_space = 0 : i32} : i8
llvm.mlir.global external @absolute_symbol_global() {absolute_symbol = [0 : i64, 42 : i64]} : i8
diff --git a/mlir/test/Target/LLVMIR/Import/global-variables.ll b/mlir/test/Target/LLVMIR/Import/global-variables.ll
index 1d49726fb8966..5ca3c5a93e5ca 100644
--- a/mlir/test/Target/LLVMIR/Import/global-variables.ll
+++ b/mlir/test/Target/LLVMIR/Import/global-variables.ll
@@ -403,15 +403,27 @@ declare void @f()
; // -----
+; CHECK: llvm.mlir.global external @associated_ifunc_global
+; CHECK-SAME: associated = @associated_ifunc
+; CHECK: llvm.mlir.ifunc external @associated_ifunc
+ at associated_ifunc = ifunc i32 (i32), ptr @associated_ifunc_resolver
+ at associated_ifunc_global = global i32 0, !associated !0
+define ptr @associated_ifunc_resolver() {
+ ret ptr null
+}
+!0 = !{ptr @associated_ifunc}
+
+; // -----
+
; CHECK: llvm.mlir.global external @a()
-; CHECK-SAME: {absolute_symbol = [0 : i64, 42 : i64], addr_space = 0 : i32} : i8
+; CHECK-SAME: {absolute_symbol = [0, 42], addr_space = 0 : i32} : i8
@a = external global i8, !absolute_symbol !0
!0 = !{i64 0, i64 42}
; // -----
; CHECK: llvm.mlir.global external @a()
-; CHECK-SAME: {absolute_symbol = [-1 : i64, -1 : i64], addr_space = 0 : i32} : i8
+; CHECK-SAME: {absolute_symbol = [-1, -1], addr_space = 0 : i32} : i8
@a = external global i8, !absolute_symbol !0
!0 = !{i64 -1, i64 -1}
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index c00b69bdbeb3b..55447c9945537 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -3662,6 +3662,18 @@ llvm.mlir.global @associated_via_alias(2 : i32) {associated = @alias_of_target}
// -----
+// CHECK: @associated_ifunc_global = global i32 0, !associated ![[ASSOC_IFUNC:[0-9]+]]
+// CHECK: @associated_ifunc = ifunc i32 (i32), ptr @associated_ifunc_resolver
+// CHECK: ![[ASSOC_IFUNC]] = !{ptr @associated_ifunc}
+llvm.mlir.global @associated_ifunc_global(0 : i32) {associated = @associated_ifunc} : i32
+llvm.mlir.ifunc @associated_ifunc : !llvm.func<i32 (i32)>, !llvm.ptr @associated_ifunc_resolver
+llvm.func @associated_ifunc_resolver() -> !llvm.ptr {
+ %0 = llvm.mlir.zero : !llvm.ptr
+ llvm.return %0 : !llvm.ptr
+}
+
+// -----
+
// CHECK: @absolute_symbol_global = external global i8, !absolute_symbol ![[ABS:[0-9]+]]
// CHECK: ![[ABS]] = !{i64 0, i64 42}
llvm.mlir.global external @absolute_symbol_global() {absolute_symbol = [0 : i64, 42 : i64]} : i8
More information about the Mlir-commits
mailing list