OperationState vs OpBuilder

I’m hoping someone can shed some light on the difference between OperationState and OpBuilder.

The CAPI seems to use OperationState

Which does not seem to use OpBuilder under the hood…

OpBuilder seems to be related, but I don’t quite understand the difference:

OpBuilder is a convenience around OperationState. In particular if you know the C++ class of the Operation you want to build (the common case), OpBuilder exposes a template method: builder.create<OpClass>(...) which is managing the OperationState and the dispatch to a specific builder for the OpClass: https://github.com/llvm/llvm-project/blob/master/mlir/include/mlir/IR/Builders.h#L390-L402
If you don’t have a C++ class to call the template, you can use OperationState with a string to identify the op.

Another aspect is that OpBuilder keeps an “insertion point” and will automatically insert the operation in the block at the current position, while OperationState has to manage the insertion manually.

1 Like

It also holds a context, so it can provide shortcuts for constructing common types and attributes.

Generally, C++ code is expected to use OpBuilder unless it has a strong reason not to. Since you are looking at C API, I suppose you want to provide bindings for another language. It’s up to those bindings to define what is the most idiomatic to the host language way to build the IR.

1 Like

Right - something like OpBuilder should be recreated in the high level language. The C bindings should go to OperationState.

Think of OpBuilder as being part of the C++ binding :slight_smile:

1 Like