Skip to content

Commit cff1cd3

Browse files
committed
[MLIR][LLVM] Implement LLVM dialect support for global aliases
This includes support for module translation and module import and add tests for both. ClangIR cannot currently lower global aliases to LLVM because of missing support for this.
1 parent ffe3129 commit cff1cd3

File tree

8 files changed

+496
-3
lines changed

8 files changed

+496
-3
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,6 +1443,92 @@ def LLVM_GlobalDtorsOp : LLVM_Op<"mlir.global_dtors", [
14431443
let hasVerifier = 1;
14441444
}
14451445

1446+
def LLVM_AliasOp : LLVM_Op<"mlir.alias",
1447+
[IsolatedFromAbove, SingleBlockImplicitTerminator<"ReturnOp">, Symbol]> {
1448+
let arguments = (ins
1449+
TypeAttr:$alias_type,
1450+
StrAttr:$sym_name,
1451+
Linkage:$linkage,
1452+
UnitAttr:$dso_local,
1453+
UnitAttr:$thread_local_,
1454+
UnitAttr:$externally_initialized,
1455+
DefaultValuedAttr<ConfinedAttr<I32Attr, [IntNonNegative]>, "0">:$addr_space,
1456+
OptionalAttr<UnnamedAddr>:$unnamed_addr,
1457+
OptionalAttr<StrAttr>:$section,
1458+
OptionalAttr<SymbolRefAttr>:$comdat,
1459+
DefaultValuedAttr<Visibility, "mlir::LLVM::Visibility::Default">:$visibility_
1460+
);
1461+
let summary = "LLVM dialect alias.";
1462+
let description = [{
1463+
`llvm.mlir.alias` is a top level operation that defines a global alias for
1464+
global variables and functions. The operation is always initialized by
1465+
using a initializer region which could be a direct map to another global
1466+
value or contain some address computation on top of it.
1467+
1468+
It uses an @-identifier for its value, which will be uniqued by the module
1469+
with respect to other @-identifiers in it.
1470+
1471+
Similarly to functions and globals, they can also have a linkage attribute.
1472+
This attribute is placed between `llvm.mlir.alias` and the symbol name. If
1473+
the attribute is omitted, `external` linkage is assumed by default.
1474+
1475+
Examples:
1476+
1477+
```mlir
1478+
// Global alias use @-identifiers.
1479+
llvm.mlir.alias external @foo_alias {addr_space = 0 : i32} : !llvm.ptr {
1480+
%0 = llvm.mlir.addressof @some_function : !llvm.ptr
1481+
llvm.return %0 : !llvm.ptr
1482+
}
1483+
1484+
// More complex initialization.
1485+
llvm.mlir.alias linkonce_odr hidden @glob
1486+
{addr_space = 0 : i32, dso_local} : !llvm.array<32 x i32> {
1487+
%0 = llvm.mlir.constant(1234 : i64) : i64
1488+
%1 = llvm.mlir.addressof @glob.private : !llvm.ptr
1489+
%2 = llvm.ptrtoint %1 : !llvm.ptr to i64
1490+
%3 = llvm.add %2, %0 : i64
1491+
%4 = llvm.inttoptr %3 : i64 to !llvm.ptr
1492+
llvm.return %4 : !llvm.ptr
1493+
}
1494+
```
1495+
}];
1496+
let regions = (region AnyRegion:$initializer);
1497+
1498+
let builders = [
1499+
OpBuilder<(ins "Type":$type, "Linkage":$linkage,
1500+
"StringRef":$name,
1501+
CArg<"unsigned", "0">:$addrSpace,
1502+
CArg<"bool", "false">:$dsoLocal,
1503+
CArg<"bool", "false">:$thread_local_,
1504+
CArg<"SymbolRefAttr", "{}">:$comdat,
1505+
CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs,
1506+
CArg<"ArrayRef<Attribute>", "{}">:$dbgExprs)>
1507+
];
1508+
1509+
let extraClassDeclaration = [{
1510+
/// Return the LLVM type of the global alias.
1511+
Type getType() {
1512+
return getAliasType();
1513+
}
1514+
/// Return the initializer region. This may be empty, but if it is not it
1515+
/// terminates in an `llvm.return` op with the initializer value.
1516+
Region &getInitializerRegion() {
1517+
return getOperation()->getRegion(0);
1518+
}
1519+
/// Return the initializer block. The initializer region always exist
1520+
/// (differently from llvm.global) and it terminates with an `llvm.return`
1521+
/// op with the aliasee value.
1522+
Block *getInitializerBlock() {
1523+
return &getInitializerRegion().front();
1524+
}
1525+
}];
1526+
1527+
let hasCustomAssemblyFormat = 1;
1528+
let hasVerifier = 1;
1529+
let hasRegionVerifier = 1;
1530+
}
1531+
14461532
def LLVM_ComdatSelectorOp : LLVM_Op<"comdat_selector", [Symbol]> {
14471533
let arguments = (ins
14481534
SymbolNameAttr:$sym_name,

mlir/include/mlir/Target/LLVMIR/ModuleImport.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class ModuleImport {
6767
/// Converts all global variables of the LLVM module to MLIR global variables.
6868
LogicalResult convertGlobals();
6969

70+
/// Converts all aliases of the LLVM module to MLIR variables.
71+
LogicalResult convertAliases();
72+
7073
/// Converts the data layout of the LLVM module to an MLIR data layout
7174
/// specification.
7275
LogicalResult convertDataLayout();
@@ -288,6 +291,9 @@ class ModuleImport {
288291
LogicalResult convertGlobal(llvm::GlobalVariable *globalVar);
289292
/// Imports the magic globals "global_ctors" and "global_dtors".
290293
LogicalResult convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar);
294+
/// Converts an LLVM global alias variable into an MLIR LLVM dialect alias
295+
/// operation if a conversion exists. Otherwise, returns failure.
296+
LogicalResult convertAlias(llvm::GlobalAlias *alias);
291297
/// Returns personality of `func` as a FlatSymbolRefAttr.
292298
FlatSymbolRefAttr getPersonalityAsAttr(llvm::Function *func);
293299
/// Imports `bb` into `block`, which must be initially empty.
@@ -406,6 +412,8 @@ class ModuleImport {
406412
Operation *constantInsertionOp = nullptr;
407413
/// Operation to insert the next global after.
408414
Operation *globalInsertionOp = nullptr;
415+
/// Operation to insert the next alias after.
416+
Operation *aliasInsertionOp = nullptr;
409417
/// Operation to insert comdat selector operations into.
410418
ComdatOp globalComdatOp = nullptr;
411419
/// The current context.

mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,12 @@ class ModuleTranslation {
188188
return globalsMapping.lookup(op);
189189
}
190190

191+
/// Finds an LLVM IR global value that corresponds to the given MLIR operation
192+
/// defining a global alias value.
193+
llvm::GlobalValue *lookupAlias(Operation *op) {
194+
return aliasesMapping.lookup(op);
195+
}
196+
191197
/// Returns the OpenMP IR builder associated with the LLVM IR module being
192198
/// constructed.
193199
llvm::OpenMPIRBuilder *getOpenMPBuilder();
@@ -322,6 +328,7 @@ class ModuleTranslation {
322328
LogicalResult convertFunctions();
323329
LogicalResult convertComdats();
324330
LogicalResult convertGlobals();
331+
LogicalResult convertAliases();
325332
LogicalResult convertOneFunction(LLVMFuncOp func);
326333
LogicalResult convertBlockImpl(Block &bb, bool ignoreArguments,
327334
llvm::IRBuilderBase &builder,
@@ -366,6 +373,10 @@ class ModuleTranslation {
366373
/// Mappings between llvm.mlir.global definitions and corresponding globals.
367374
DenseMap<Operation *, llvm::GlobalValue *> globalsMapping;
368375

376+
/// Mappings between llvm.mlir.alias definitions and corresponding global
377+
/// aliases.
378+
DenseMap<Operation *, llvm::GlobalValue *> aliasesMapping;
379+
369380
/// A stateful object used to translate types.
370381
TypeToLLVMIRTranslator typeTranslator;
371382

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,6 +2422,178 @@ LogicalResult GlobalDtorsOp::verify() {
24222422
return success();
24232423
}
24242424

2425+
//===----------------------------------------------------------------------===//
2426+
// Builder, printer and verifier for LLVM::GlobalOp.
2427+
//===----------------------------------------------------------------------===//
2428+
2429+
void AliasOp::build(OpBuilder &builder, OperationState &result, Type type,
2430+
Linkage linkage, StringRef name, unsigned addrSpace,
2431+
bool dsoLocal, bool threadLocal, SymbolRefAttr comdat,
2432+
ArrayRef<NamedAttribute> attrs,
2433+
ArrayRef<Attribute> dbgExprs) {
2434+
result.addAttribute(getSymNameAttrName(result.name),
2435+
builder.getStringAttr(name));
2436+
result.addAttribute(getAliasTypeAttrName(result.name), TypeAttr::get(type));
2437+
if (dsoLocal)
2438+
result.addAttribute(getDsoLocalAttrName(result.name),
2439+
builder.getUnitAttr());
2440+
if (threadLocal)
2441+
result.addAttribute(getThreadLocal_AttrName(result.name),
2442+
builder.getUnitAttr());
2443+
if (comdat)
2444+
result.addAttribute(getComdatAttrName(result.name), comdat);
2445+
2446+
result.addAttribute(getLinkageAttrName(result.name),
2447+
LinkageAttr::get(builder.getContext(), linkage));
2448+
if (addrSpace != 0)
2449+
result.addAttribute(getAddrSpaceAttrName(result.name),
2450+
builder.getI32IntegerAttr(addrSpace));
2451+
result.attributes.append(attrs.begin(), attrs.end());
2452+
2453+
result.addRegion();
2454+
}
2455+
2456+
void AliasOp::print(OpAsmPrinter &p) {
2457+
p << ' ' << stringifyLinkage(getLinkage()) << ' ';
2458+
StringRef visibility = stringifyVisibility(getVisibility_());
2459+
if (!visibility.empty())
2460+
p << visibility << ' ';
2461+
if (getThreadLocal_())
2462+
p << "thread_local ";
2463+
if (auto unnamedAddr = getUnnamedAddr()) {
2464+
StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2465+
if (!str.empty())
2466+
p << str << ' ';
2467+
}
2468+
p.printSymbolName(getSymName());
2469+
if (auto comdat = getComdat())
2470+
p << " comdat(" << *comdat << ')';
2471+
2472+
// Note that the alignment attribute is printed using the
2473+
// default syntax here, even though it is an inherent attribute
2474+
// (as defined in https://mlir.llvm.org/docs/LangRef/#attributes)
2475+
p.printOptionalAttrDict((*this)->getAttrs(),
2476+
{SymbolTable::getSymbolAttrName(),
2477+
getAliasTypeAttrName(), getLinkageAttrName(),
2478+
getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2479+
getVisibility_AttrName(), getComdatAttrName(),
2480+
getUnnamedAddrAttrName()});
2481+
2482+
// Print the trailing type
2483+
p << " : " << getType();
2484+
2485+
Region &initializer = getInitializerRegion();
2486+
if (!initializer.empty()) {
2487+
p << ' ';
2488+
p.printRegion(initializer, /*printEntryBlockArgs=*/false);
2489+
}
2490+
}
2491+
2492+
// operation ::= `llvm.mlir.alias` linkage? visibility?
2493+
// (`unnamed_addr` | `local_unnamed_addr`)?
2494+
// `thread_local`? `@` identifier
2495+
// `(` attribute? `)` (`comdat(` symbol-ref-id `)`)?
2496+
// attribute-list? (`:` type)? region
2497+
//
2498+
// The type can be omitted for string attributes, in which case it will be
2499+
// inferred from the value of the string as [strlen(value) x i8].
2500+
ParseResult AliasOp::parse(OpAsmParser &parser, OperationState &result) {
2501+
MLIRContext *ctx = parser.getContext();
2502+
// Parse optional linkage, default to External.
2503+
result.addAttribute(getLinkageAttrName(result.name),
2504+
LLVM::LinkageAttr::get(
2505+
ctx, parseOptionalLLVMKeyword<Linkage>(
2506+
parser, result, LLVM::Linkage::External)));
2507+
2508+
// Parse optional visibility, default to Default.
2509+
result.addAttribute(getVisibility_AttrName(result.name),
2510+
parser.getBuilder().getI64IntegerAttr(
2511+
parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2512+
parser, result, LLVM::Visibility::Default)));
2513+
2514+
// Parse optional UnnamedAddr, default to None.
2515+
result.addAttribute(getUnnamedAddrAttrName(result.name),
2516+
parser.getBuilder().getI64IntegerAttr(
2517+
parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2518+
parser, result, LLVM::UnnamedAddr::None)));
2519+
2520+
if (succeeded(parser.parseOptionalKeyword("thread_local")))
2521+
result.addAttribute(getThreadLocal_AttrName(result.name),
2522+
parser.getBuilder().getUnitAttr());
2523+
2524+
StringAttr name;
2525+
if (parser.parseSymbolName(name, getSymNameAttrName(result.name),
2526+
result.attributes))
2527+
return failure();
2528+
2529+
if (succeeded(parser.parseOptionalKeyword("comdat"))) {
2530+
SymbolRefAttr comdat;
2531+
if (parser.parseLParen() || parser.parseAttribute(comdat) ||
2532+
parser.parseRParen())
2533+
return failure();
2534+
2535+
result.addAttribute(getComdatAttrName(result.name), comdat);
2536+
}
2537+
2538+
SmallVector<Type, 1> types;
2539+
if (parser.parseOptionalAttrDict(result.attributes) ||
2540+
parser.parseOptionalColonTypeList(types))
2541+
return failure();
2542+
2543+
if (types.size() > 1)
2544+
return parser.emitError(parser.getNameLoc(), "expected zero or one type");
2545+
2546+
Region &initRegion = *result.addRegion();
2547+
if (parser.parseRegion(initRegion).failed())
2548+
return failure();
2549+
2550+
result.addAttribute(getAliasTypeAttrName(result.name),
2551+
TypeAttr::get(types[0]));
2552+
return success();
2553+
}
2554+
2555+
LogicalResult AliasOp::verify() {
2556+
bool validType = isCompatibleOuterType(getType())
2557+
? !llvm::isa<LLVMVoidType, LLVMTokenType,
2558+
LLVMMetadataType, LLVMLabelType>(getType())
2559+
: llvm::isa<PointerElementTypeInterface>(getType());
2560+
if (!validType)
2561+
return emitOpError(
2562+
"expects type to be a valid element type for an LLVM global");
2563+
if ((*this)->getParentOp() && !satisfiesLLVMModule((*this)->getParentOp()))
2564+
return emitOpError("must appear at the module level");
2565+
2566+
if (getLinkage() == Linkage::Appending) {
2567+
if (!llvm::isa<LLVMArrayType>(getType())) {
2568+
return emitOpError() << "expected array type for '"
2569+
<< stringifyLinkage(Linkage::Appending)
2570+
<< "' linkage";
2571+
}
2572+
}
2573+
2574+
if (failed(verifyComdat(*this, getComdat())))
2575+
return failure();
2576+
2577+
return success();
2578+
}
2579+
2580+
LogicalResult AliasOp::verifyRegions() {
2581+
if (Block *b = getInitializerBlock()) {
2582+
ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2583+
if (ret.operand_type_begin() == ret.operand_type_end())
2584+
return emitOpError("initializer region cannot return void");
2585+
2586+
for (Operation &op : *b) {
2587+
auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2588+
if (!iface || !iface.hasNoEffect())
2589+
return op.emitError()
2590+
<< "ops with side effects not allowed in aliases initializers";
2591+
}
2592+
}
2593+
2594+
return success();
2595+
}
2596+
24252597
//===----------------------------------------------------------------------===//
24262598
// ShuffleVectorOp
24272599
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)