[Mlir-commits] [mlir] aa1058e - [mlir][LLVM] Preserve !associated and !absolute_symbol on llvm.mlir.global (#218839)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sun Aug 30 01:45:45 PDT 2026
Author: Tanishq Khurana
Date: 2026-08-30T17:45:40+09:00
New Revision: aa1058e34a6127df91898829b0e60cbae3111cbf
URL: https://github.com/llvm/llvm-project/commit/aa1058e34a6127df91898829b0e60cbae3111cbf
DIFF: https://github.com/llvm/llvm-project/commit/aa1058e34a6127df91898829b0e60cbae3111cbf.diff
LOG: [mlir][LLVM] Preserve !associated and !absolute_symbol on llvm.mlir.global (#218839)
Add optional `associated` and `absolute_symbol` attributes on
`llvm.mlir.global` so the corresponding LLVM IR metadata is preserved
through import and export.
`associated` is a symbol ref to another global, alias, or function (used
for ELF `SHF_LINK_ORDER`). `absolute_symbol` is an array of `[lower,
upper)` integer range pairs, with `[-1, -1]` for the full set.
Verifier rejects a self-associated global and malformed range lists.
Translation attaches the metadata after all globals, aliases, and
function signatures exist so symbol refs can be resolved.
Fixes #215549
Assisted-by: Cursor
---------
Co-authored-by: Cursor <cursoragent at cursor.com>
Added:
Modified:
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
mlir/include/mlir/Target/LLVMIR/ModuleImport.h
mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
mlir/lib/Target/LLVMIR/ModuleImport.cpp
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
mlir/test/Dialect/LLVMIR/global.mlir
mlir/test/Target/LLVMIR/Import/global-variables.ll
mlir/test/Target/LLVMIR/llvmir.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index d5373d4bc6186..42b10d3df6d2c 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -1416,6 +1416,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_,
@@ -1518,6 +1520,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/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
index da6471a2e001d..3bb024a88f283 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
@@ -382,6 +382,8 @@ class ModuleImport {
/// Returns the symbol reference for a global value that has a corresponding
/// imported MLIR symbol, or a null attribute otherwise.
FlatSymbolRefAttr getMetadataGlobalValueSymbolRef(llvm::GlobalValue *global);
+ /// Returns a symbol ref if `md` refers to an imported global value.
+ FlatSymbolRefAttr getMetadataOperandSymbolRef(const llvm::Metadata *md);
/// Converts `md` to the matching LLVM dialect metadata attribute, or returns
/// a null attribute if the metadata cannot be represented.
Attribute convertMetadataToAttr(const llvm::Metadata *md);
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
index 6db1951dbdd35..5f1f73dbb9f4f 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
@@ -428,7 +428,18 @@ 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();
+ /// Converts a symbol ref to LLVM IR metadata, or fails if unresolved.
+ FailureOr<llvm::Metadata *>
+ convertSymbolRefToMetadata(FlatSymbolRefAttr name,
+ function_ref<InFlightDiagnostic()> emitError);
LogicalResult convertOneFunction(LLVMFuncOp func);
LogicalResult convertBlockImpl(Block &bb, bool ignoreArguments,
llvm::IRBuilderBase &builder,
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 858425f80ee31..c58d5b07cd296 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -2724,6 +2724,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 02cdb6088b6ac..ef2363fb4dfd9 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -173,6 +173,20 @@ ModuleImport::getMetadataGlobalValueSymbolRef(llvm::GlobalValue *global) {
return FlatSymbolRefAttr::get(context, global->getName());
}
+FlatSymbolRefAttr
+ModuleImport::getMetadataOperandSymbolRef(const llvm::Metadata *md) {
+ auto *valueAsMD = dyn_cast_or_null<llvm::ValueAsMetadata>(md);
+ if (!valueAsMD)
+ return {};
+ llvm::Value *value = valueAsMD->getValue();
+ llvm::GlobalValue *gv = dyn_cast<llvm::GlobalValue>(value);
+ if (!gv)
+ gv = dyn_cast<llvm::GlobalValue>(value->stripPointerCastsAndAliases());
+ if (!gv)
+ return {};
+ return getMetadataGlobalValueSymbolRef(gv);
+}
+
/// Depth-first conversion of the metadata node `md` to the matching LLVM
/// dialect metadata attribute. Returns a null attribute for shapes that the
/// dialect's metadata-attribute hierarchy does not currently model. `path`
@@ -1687,6 +1701,42 @@ 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)) {
+ FlatSymbolRefAttr symbolRef;
+ if (associatedMD->getNumOperands() == 1)
+ symbolRef =
+ getMetadataOperandSymbolRef(associatedMD->getOperand(0).get());
+ if (!symbolRef) {
+ emitWarning(globalOp.getLoc()) << "unhandled associated metadata: "
+ << diagMD(associatedMD, llvmModule.get())
+ << " on " << diag(*globalVar);
+ } else {
+ globalOp.setAssociatedAttr(symbolRef);
+ }
+ }
+
+ if (llvm::MDNode *absSymMD =
+ globalVar->getMetadata(llvm::LLVMContext::MD_absolute_symbol)) {
+ unsigned numOps = absSymMD->getNumOperands();
+ if (numOps >= 2 && numOps % 2 == 0) {
+ SmallVector<Attribute> rangeAttrs;
+ rangeAttrs.reserve(numOps);
+
+ for (const llvm::MDOperand &op : absSymMD->operands()) {
+ auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(op);
+ if (!constInt)
+ break;
+
+ auto intType = IntegerType::get(context, constInt->getBitWidth());
+ rangeAttrs.push_back(IntegerAttr::get(intType, constInt->getValue()));
+ }
+
+ if (rangeAttrs.size() == numOps)
+ 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 5bb42575a0955..76fa43cd376cd 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"
@@ -1598,22 +1599,7 @@ FailureOr<llvm::Metadata *> ModuleTranslation::convertMetadataAttr(
intAttr.getValue()));
})
.Case([&](MDGlobalValueAttr a) -> FailureOr<llvm::Metadata *> {
- if (llvm::Function *fn = lookupFunction(a.getName().getValue()))
- return llvm::ValueAsMetadata::get(fn);
- if (llvm::GlobalValue *global = lookupGlobal(a.getName().getValue()))
- return llvm::ValueAsMetadata::get(global);
- Operation *symbol =
- symbolTable().lookupSymbolIn(mlirModule, a.getName());
- if (auto alias = dyn_cast_if_present<LLVM::AliasOp>(symbol)) {
- if (llvm::GlobalValue *global = lookupAlias(alias))
- return llvm::ValueAsMetadata::get(global);
- }
- if (auto ifunc = dyn_cast_if_present<LLVM::IFuncOp>(symbol)) {
- if (llvm::GlobalValue *global = lookupIFunc(ifunc))
- return llvm::ValueAsMetadata::get(global);
- }
- return emitError() << "could not resolve metadata reference '"
- << a.getName() << "'";
+ return convertSymbolRefToMetadata(a.getName(), emitError);
})
.Case([&](MDNullAttr a) -> FailureOr<llvm::Metadata *> {
return llvm::ConstantAsMetadata::get(llvm::ConstantPointerNull::get(
@@ -1648,6 +1634,24 @@ FailureOr<llvm::Metadata *> ModuleTranslation::convertMetadataAttr(
});
}
+FailureOr<llvm::Metadata *> ModuleTranslation::convertSymbolRefToMetadata(
+ FlatSymbolRefAttr name, function_ref<InFlightDiagnostic()> emitError) {
+ if (llvm::Function *fn = lookupFunction(name.getValue()))
+ return llvm::ValueAsMetadata::get(fn);
+ if (llvm::GlobalValue *global = lookupGlobal(name.getValue()))
+ return llvm::ValueAsMetadata::get(global);
+ Operation *symbol = symbolTable().lookupSymbolIn(mlirModule, name);
+ if (auto alias = dyn_cast_if_present<LLVM::AliasOp>(symbol)) {
+ if (llvm::GlobalValue *global = lookupAlias(alias))
+ return llvm::ValueAsMetadata::get(global);
+ }
+ if (auto ifunc = dyn_cast_if_present<LLVM::IFuncOp>(symbol)) {
+ if (llvm::GlobalValue *global = lookupIFunc(ifunc))
+ return llvm::ValueAsMetadata::get(global);
+ }
+ return emitError() << "could not resolve metadata reference '" << name << "'";
+}
+
LogicalResult ModuleTranslation::convertFunctionMetadata() {
for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
ArrayAttr metadata = function.getFunctionMetadataAttr();
@@ -2235,6 +2239,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()) {
+ FailureOr<llvm::Metadata *> md =
+ convertSymbolRefToMetadata(associated, [&]() {
+ 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 = 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>()) {
@@ -2694,6 +2733,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.convertFunctionMetadata()))
return nullptr;
if (failed(translator.createTBAAMetadata()))
diff --git a/mlir/test/Dialect/LLVMIR/global.mlir b/mlir/test/Dialect/LLVMIR/global.mlir
index 2e6459386389e..69ccbb4eaac32 100644
--- a/mlir/test/Dialect/LLVMIR/global.mlir
+++ b/mlir/test/Dialect/LLVMIR/global.mlir
@@ -304,3 +304,46 @@ 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 @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
+
+// 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 bf2f48f26fdbc..905e9cf3982e5 100644
--- a/mlir/test/Target/LLVMIR/Import/global-variables.ll
+++ b/mlir/test/Target/LLVMIR/Import/global-variables.ll
@@ -1,4 +1,5 @@
; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s
+; RUN: mlir-translate -import-llvm -split-input-file %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=WARN
%sub_struct = type {}
%my_struct = type { %sub_struct, i64 }
@@ -388,3 +389,64 @@ 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 @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}
+
+; // -----
+
+; WARN: warning: unhandled associated metadata: {{.*}}ptr null{{.*}} on @associated_null
+; CHECK: llvm.mlir.global external @associated_null() {addr_space = 0 : i32} : i8
+ at associated_null = external global i8, !associated !0
+!0 = !{ptr null}
+
+; // -----
+
+; CHECK: llvm.mlir.global external @a()
+; CHECK-SAME: {absolute_symbol = [0, 42], 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, -1], 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 718f19f32131d..5edc4a0fce9b4 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -3645,6 +3645,59 @@ 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: @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
+
+// -----
+
+// 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>
More information about the Mlir-commits
mailing list