The way to inspect c++ interfaces for certain operations

Hi, I found that for some of the operations under certain dialect, it seems difficult to find explanation for their c++ interface. I hope to get advice about if we have other recommended document or method to find it?

Here’s an example invocation of memref::load . I didn’t find related document nor source code for it. And I am interested in its parameter definitions.
`

rewriter.create<memref::LoadOp>(loc, ValueRange{at, mid, end});

What you provide when creating an op depends on the Operation definition: 'memref' Dialect - MLIR
Source: https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td#L1177

You may look at build/tools/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.h.inc and search for "class LoadOp " in this file. You should find the following build method:

  static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value memref, ::mlir::ValueRange indices, /*optional*/::mlir::BoolAttr nontemporal);
  static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value memref, ::mlir::ValueRange indices, /*optional*/::mlir::BoolAttr nontemporal);
  static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value memref, ::mlir::ValueRange indices, /*optional*/::mlir::BoolAttr nontemporal);
  static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value memref, ::mlir::ValueRange indices, /*optional*/bool nontemporal = false);
  static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value memref, ::mlir::ValueRange indices, /*optional*/bool nontemporal = false);
  static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value memref, ::mlir::ValueRange indices, /*optional*/bool nontemporal = false);
  static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {});
  static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {});

The first two operands are handled by the builder, the rest is just the arguments you’re passing in.

2 Likes

Thank you for directing me to these, they are exactly what I need.
Meanwhile I am having a problem with operation for an external function call. I understand it may be better to get a new thread but since the I have this thread just started.
The new operation led to a error saying it’s not registered, but for external function call I am not aware of any other declaration I should make. Do you have suggestions on this?

Code for adding this operation:

  mlir::func::FuncOp ticker;
  auto tickerType = rewriter.getFunctionType(nullopt, nullopt);
  ticker = rewriter.create<func::FuncOp>(loc, "LogPrint", tickerType);
  rewriter.create<func::CallOp>(loc, ticker, ValueRange{});

Error showed:

demo.llvm:7:26: error: operation being parsed with an unregistered dialect. If this is intended, please use -allow-unregistered-dialect with the MLIR tool used

The error you have is during parsing, not during IR emission I believe.

What is inside this file at this line?

Actually I found something weird.
If the “ticker” op (from my prior reply) is not added, then the generated code looks like normal mlir code and could be processed by mlir-translate with correct result.
The normal mlir code would be generated like this:

1 module attributes {llvm.data_layout = “”} {
2 llvm.func @malloc(i64) → !llvm.ptr
3 llvm.func @printNewline()
4 llvm.func @printU64(i64)
5 llvm.func @main() {
6 %0 = llvm.mlir.constant(2 : index) : i64
7 %1 = llvm.mlir.constant(5 : index) : i64
8 %2 = llvm.mlir.constant(true) : i1
9 %3 = llvm.mlir.constant(0 : i64) : i64

However after adding the “ticker” op to call the external function, the emitted code looks like not properly lowered to mlir, instead it contains lot of other dialects. But the weird thing is, it still could be digested by mlir-translate to show the results, despite the parsing error message and that the “ticker” op could not take any effect.

1 “builtin.module”() ({
2 “llvm.func”() <{CConv = LLVM Project.cconv, function_type = !llvm.func<void ()>, linkage = LLVM Project.link age, sym_name = “printNewline”, visibility_ = 0 : i64}> ({
3 }) : () → ()
4 “llvm.func”() <{CConv = LLVM Project.cconv, function_type = !llvm.func<void (i64)>, linkage = LLVM Project.l inkage, sym_name = “printU64”, visibility_ = 0 : i64}> ({
5 }) : () → ()
6 “func.func”() <{function_type = () → (), sym_name = “main”}> ({
7 %0 = “arith.constant”() <{value = 2 : index}> : () → index
8 %1 = “builtin.unrealized_conversion_cast”(%0) : (index) → i64
9 %2 = “arith.constant”() <{value = 5 : index}> : () → index
10 %3 = “builtin.unrealized_conversion_cast”(%2) : (index) → i64
11 %4 = “arith.constant”() <{value = true}> : () → i1
12 %5 = “arith.constant”() <{value = 0 : i64}> : () → i64

So if the “error: operation being parsed with an unregistered dialect.” is from mlir-translate that’s less surprising: you likely didn’t convert all the dialects to LLVM Dialect and mlir-translate does not know how to parse them.

A sanity check for knowing if the file is well-formed would be to round-trip through your mlir-opt tool.

Thanks for the hint.
The interesting part is, if not adding that “ticker” op, everything is lowered correctly.
By checking again, seems I gave wrong definition to the arguments of function which was called. After some fixing the mlir code could be fully lowered now, but still something not working on the function side.