-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[mlir][LLVMIR] Add IFuncOp to LLVM dialect #147697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
36b982f
2593954
1126fe2
21ccdf8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -1285,6 +1285,10 @@ def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof", | |||||
| /// Return the llvm.mlir.alias operation that defined the value referenced | ||||||
| /// here. | ||||||
| AliasOp getAlias(SymbolTableCollection &symbolTable); | ||||||
|
|
||||||
| /// Return the llvm.mlir.ifunc operation that defined the value referenced | ||||||
| /// here. | ||||||
| IFuncOp getIFunc(SymbolTableCollection &symbolTable); | ||||||
| }]; | ||||||
|
|
||||||
| let assemblyFormat = "$global_name attr-dict `:` qualified(type($res))"; | ||||||
|
|
@@ -1601,6 +1605,67 @@ def LLVM_AliasOp : LLVM_Op<"mlir.alias", | |||||
| let hasRegionVerifier = 1; | ||||||
| } | ||||||
|
|
||||||
| def LLVM_IFuncOp : LLVM_Op<"mlir.ifunc", | ||||||
| [IsolatedFromAbove, Symbol, DeclareOpInterfaceMethods<SymbolUserOpInterface>]> { | ||||||
| let arguments = (ins | ||||||
| SymbolNameAttr:$sym_name, | ||||||
| TypeAttr:$i_func_type, | ||||||
| FlatSymbolRefAttr:$resolver, | ||||||
| TypeAttr:$resolver_type, | ||||||
| Linkage:$linkage, | ||||||
| UnitAttr:$dso_local, | ||||||
| DefaultValuedAttr<ConfinedAttr<I32Attr, [IntNonNegative]>, "0">:$address_space, | ||||||
| DefaultValuedAttr<UnnamedAddr, "mlir::LLVM::UnnamedAddr::None">:$unnamed_addr, | ||||||
| DefaultValuedAttr<Visibility, "mlir::LLVM::Visibility::Default">:$visibility_ | ||||||
| ); | ||||||
| let summary = "LLVM dialect ifunc"; | ||||||
| let description = [{ | ||||||
| `llvm.mlir.ifunc` is a top level operation that defines a global ifunc. | ||||||
| It defines a new symbol and takes a symbol refering to a resolver function. | ||||||
| IFuncs can be called as regular functions. The function type is the same | ||||||
| as the IFuncType. The symbol is resolved at runtime by calling a resolver | ||||||
| function. | ||||||
|
|
||||||
| Examples: | ||||||
|
|
||||||
| ```mlir | ||||||
| // IFuncs have @-identifier and use a resolver function. | ||||||
|
||||||
| // IFuncs have @-identifier and use a resolver function. | |
| // IFuncs resolve a symbol at runtime using a resovler function. |
nit: I would make it a bit more specific.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -71,6 +71,9 @@ class ModuleImport { | |||||
| /// Converts all aliases of the LLVM module to MLIR variables. | ||||||
| LogicalResult convertAliases(); | ||||||
|
|
||||||
| /// Converts all ifuncs of the LLVM module to MLIR variables. | ||||||
| LogicalResult convertIFuncs(); | ||||||
|
|
||||||
| /// Converts the data layout of the LLVM module to an MLIR data layout | ||||||
| /// specification. | ||||||
| LogicalResult convertDataLayout(); | ||||||
|
|
@@ -320,6 +323,8 @@ class ModuleImport { | |||||
| /// Converts an LLVM global alias variable into an MLIR LLVM dialect alias | ||||||
| /// operation if a conversion exists. Otherwise, returns failure. | ||||||
| LogicalResult convertAlias(llvm::GlobalAlias *alias); | ||||||
| // Converts an LLVM global ifunc into an MLIR LLVM dialect ifunc operation | ||||||
|
||||||
| // Converts an LLVM global ifunc into an MLIR LLVM dialect ifunc operation | |
| // Converts an LLVM global ifunc into an MLIR LLVM dialect ifunc operation. |
nit: missing dot
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -139,6 +139,17 @@ static RetTy parseOptionalLLVMKeyword(OpAsmParser &parser, | |||||
| return static_cast<RetTy>(index); | ||||||
| } | ||||||
|
|
||||||
| static void printLLVMLinkage(OpAsmPrinter &p, Operation *, LinkageAttr val) { | ||||||
| p << stringifyLinkage(val.getLinkage()); | ||||||
| } | ||||||
|
|
||||||
| static ParseResult parseLLVMLinkage(OpAsmParser &p, LinkageAttr &val) { | ||||||
| val = LinkageAttr::get( | ||||||
| p.getContext(), | ||||||
| parseOptionalLLVMKeyword<LLVM::Linkage>(p, LLVM::Linkage::External)); | ||||||
| return success(); | ||||||
| } | ||||||
|
|
||||||
| //===----------------------------------------------------------------------===// | ||||||
| // Operand bundle helpers. | ||||||
| //===----------------------------------------------------------------------===// | ||||||
|
|
@@ -1175,14 +1186,17 @@ LogicalResult CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) { | |||||
| return emitOpError() | ||||||
| << "'" << calleeName.getValue() | ||||||
| << "' does not reference a symbol in the current scope"; | ||||||
| auto fn = dyn_cast<LLVMFuncOp>(callee); | ||||||
| if (!fn) | ||||||
| return emitOpError() << "'" << calleeName.getValue() | ||||||
| << "' does not reference a valid LLVM function"; | ||||||
|
|
||||||
| if (failed(verifyCallOpDebugInfo(*this, fn))) | ||||||
| return failure(); | ||||||
| fnType = fn.getFunctionType(); | ||||||
| if (auto fn = dyn_cast<LLVMFuncOp>(callee)) { | ||||||
| if (failed(verifyCallOpDebugInfo(*this, fn))) | ||||||
| return failure(); | ||||||
| fnType = fn.getFunctionType(); | ||||||
| } else if (auto ifunc = dyn_cast<IFuncOp>(callee)) { | ||||||
| fnType = ifunc.getIFuncType(); | ||||||
| } else { | ||||||
| return emitOpError() | ||||||
| << "'" << calleeName.getValue() | ||||||
| << "' does not reference a valid LLVM function or IFunc"; | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType); | ||||||
|
|
@@ -2038,14 +2052,6 @@ LogicalResult ReturnOp::verify() { | |||||
| // LLVM::AddressOfOp. | ||||||
| //===----------------------------------------------------------------------===// | ||||||
|
|
||||||
| static Operation *parentLLVMModule(Operation *op) { | ||||||
| Operation *module = op->getParentOp(); | ||||||
| while (module && !satisfiesLLVMModule(module)) | ||||||
| module = module->getParentOp(); | ||||||
| assert(module && "unexpected operation outside of a module"); | ||||||
| return module; | ||||||
| } | ||||||
|
|
||||||
| GlobalOp AddressOfOp::getGlobal(SymbolTableCollection &symbolTable) { | ||||||
| return dyn_cast_or_null<GlobalOp>( | ||||||
| symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr())); | ||||||
|
|
@@ -2061,6 +2067,11 @@ AliasOp AddressOfOp::getAlias(SymbolTableCollection &symbolTable) { | |||||
| symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr())); | ||||||
| } | ||||||
|
|
||||||
| IFuncOp AddressOfOp::getIFunc(SymbolTableCollection &symbolTable) { | ||||||
| return dyn_cast_or_null<IFuncOp>( | ||||||
| symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr())); | ||||||
| } | ||||||
|
|
||||||
| LogicalResult | ||||||
| AddressOfOp::verifySymbolUses(SymbolTableCollection &symbolTable) { | ||||||
| Operation *symbol = | ||||||
|
|
@@ -2069,10 +2080,11 @@ AddressOfOp::verifySymbolUses(SymbolTableCollection &symbolTable) { | |||||
| auto global = dyn_cast_or_null<GlobalOp>(symbol); | ||||||
| auto function = dyn_cast_or_null<LLVMFuncOp>(symbol); | ||||||
| auto alias = dyn_cast_or_null<AliasOp>(symbol); | ||||||
| auto ifunc = dyn_cast_or_null<IFuncOp>(symbol); | ||||||
|
|
||||||
| if (!global && !function && !alias) | ||||||
| if (!global && !function && !alias && !ifunc) | ||||||
| return emitOpError("must reference a global defined by 'llvm.mlir.global', " | ||||||
| "'llvm.mlir.alias' or 'llvm.func'"); | ||||||
| "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'"); | ||||||
|
|
||||||
| LLVMPointerType type = getType(); | ||||||
| if ((global && global.getAddrSpace() != type.getAddressSpace()) || | ||||||
|
|
@@ -2682,6 +2694,59 @@ unsigned AliasOp::getAddrSpace() { | |||||
| return ptrTy.getAddressSpace(); | ||||||
| } | ||||||
|
|
||||||
| //===----------------------------------------------------------------------===// | ||||||
| // IFuncOp | ||||||
| //===----------------------------------------------------------------------===// | ||||||
|
|
||||||
| void IFuncOp::build(OpBuilder &builder, OperationState &result, StringRef name, | ||||||
| Type iFuncType, StringRef resolverName, Type resolverType, | ||||||
| Linkage linkage, LLVM::Visibility visibility) { | ||||||
| return build(builder, result, name, iFuncType, resolverName, resolverType, | ||||||
| linkage, /*dso_local=*/false, /*address_space=*/0, | ||||||
| UnnamedAddr::None, visibility); | ||||||
| } | ||||||
|
|
||||||
| LogicalResult IFuncOp::verifySymbolUses(SymbolTableCollection &symbolTable) { | ||||||
| Operation *symbol = | ||||||
| symbolTable.lookupSymbolIn(parentLLVMModule(*this), getResolverAttr()); | ||||||
| auto resolver = dyn_cast<LLVMFuncOp>(symbol); | ||||||
| if (!resolver) { | ||||||
| // FIXME: Strip aliases to find the called function | ||||||
| if (isa<AliasOp>(symbol)) | ||||||
| return success(); | ||||||
|
||||||
| return emitOpError("must have a function resolver"); | ||||||
| } | ||||||
| // This matches LLVM IR verification logic, see from llvm/lib/IR/Verifier.cpp | ||||||
|
||||||
| // This matches LLVM IR verification logic, see from llvm/lib/IR/Verifier.cpp | |
| // This matches LLVM IR verification logic, see llvm/lib/IR/Verifier.cpp |
nit: sorry that was probably my fish.
Uh oh!
There was an error while loading. Please reload this page.