Need help understanding `ConstantOp` in the `Toy` dialect in the MLIR tutorial

I’m trying to work through some resources on MLIR dialects – this and this – and I’m having trouble understanding how functions are defined in ODS. I will use the ConstantOp from here as an example.

I can see that arguments and results are defined, which will be the inputs and outputs of the function. I also read from the tutorial that there will be build methods auto-gen’d from these definitions. Additionally, there is the builders field which is a list of OpBuilder objects that will also generate builders based on this specification. What I’m confused about is where the definition for this function lives? Specifically, where is the code that takes the input and performs the operation of making the input a constant? I understand that ODS is declarative, but I’m having trouble understanding where the definition for this ConstantOp is. Is it also auto-gen’d somehow? Is the definition given somewhere?

Any help is appreciated!

I am a bit confused by what you call “functions” here? Can you clarify a bit what you’re looking for?

I will try! LLVM and MLIR are still somewhat new to me, so I may not have the proper vocabulary to articulate what I mean.

What I think I understand is that there is a declarative description of what this ConstantOp function should do:

  • take in an argument of a particular type
  • output a result of a particular type
    • the above two bullets would make up a function signature

But where, then, would the function body of ConstantOp be defined? As I understand it, we have something that might look like this:

ResultType ConstantOp(argument) {
    <where is the function body defined?>
}

Hopefully this clarifies my question! If not, please let me know. I also recognize that there are probably gaps in my understanding, so please correct me where I’m wrong.

You seems to be looking for one possible implementation that would actually execute the operation: it does not exists.
MLIR allows you describe program but does not include or prescribe a particular implementation for the operation and types. There a multiple way to implement an actual execution that respect the high-level semantics we can define. The Toy tutorial goes ultimately to execution, but does so through lowering: that is we convert the high-level operation from the Toy dialect into sequence of operations from other dialects, down to LLVM, and then down to machine code.

1 Like

Ah, okay, this makes sense. Thanks!