Generated code uses getArgAttrsAttr instead of getArgAttrs

Beginner to MLIR (and LLVM for that matter) here. I encountered a build error which may or may not be trivial to solve.

I’m trying to build my own dialect, which I declared using TableGen (.td) files. I can successfully generate the corresponding cpp.inc and h.inc files by building a target defined using add_mlir_dialect.

However, when trying to build the dialect library (target created using add_mlir_dialect_library) I get the following error:

/usr/local/include/mlir/IR/FunctionOpInterfaces.h.inc:1116:56: error: ‘class mlir::netqasm::SubroutineOp’ has no member named ‘getArgAttrsAttr’; did you mean ‘getArgAttrs’?
 1116 |   return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getArgAttrsAttr();
      |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
      |          getArgAttrs

In the past (half a year ago or so), I encountered similar errors (I think) which at that time I managed to fix by adding let emitAccessorPrefix = kEmitAccessorPrefix_Prefixed; to my dialect .td file. However, using the latest LLVM commit it seems this attribute is not available anymore.

Is the error that I have above related to this “emitAccessor” configuration, and if so, how could I fix this?

My library code itself is the bare minimal, only #includeing the generated cpp.inc files.

Could you show the ODS definition of that op here? (Or link to it?)

I’m assuming it has function op interface and arg_attrs defined like in llvm-project/Ops.td at 79571aa2103c95760a07e3549d8636379e4948f0 · llvm/llvm-project · GitHub ?

Here is the Op definition:

// `IsolatedFromAbove` is needed for running an OperationPass on it.
def SubroutineOp : Netqasm_Op<"subroutine", [FunctionOpInterface, IsolatedFromAbove]> {

  // part with "TypeAttrOf" is needed for compiling lib!
  // "$function_type" together with "kEmitAccessorPrefix_Prefixed" in Dialect
  // makes sure "getFunctionType()" exists
  let arguments = (ins SymbolNameAttr:$sym_name, TypeAttrOf<FunctionType>:$function_type);

  let regions = (region AnyRegion:$body);

  // Needed by the generated (in MLIR itself) FunctionOpInstances.h.inc
  let extraClassDeclaration = [{
    //===------------------------------------------------------------------===//
    // FunctionOpInterface Methods
    //===------------------------------------------------------------------===//

    /// Returns the argument types of this function.
    ArrayRef<Type> getArgumentTypes() { return getFunctionType().getInputs(); }

    /// Returns the result types of this function.
    ArrayRef<Type> getResultTypes() { return getFunctionType().getResults(); }
  }];
}

Note that all these comments are actually my own understanding and may or may not be accurate.
I added them when I worked on this a couple of months ago. This code worked back then but now that I have built and installed the latest LLVM and MLIR I get the aforementioned error.

I’m actually not sure why it worked, I expect arg_attrs and result_attrs would also be needed even back then, perhaps we were just using the less optimized query by name method that returns nullptr for any nonexistent attributes and switched to generated accessors. But adding both of these to the op def should work.

Ok, adding

OptionalAttr<DictArrayAttr>:$arg_attrs, OptionalAttr<DictArrayAttr>:$res_attrs

to the arguments works, awesome!

I’m trying to get an intuition of how I “should have known” this. Is there some part of the FunctionOpInterface that requires every op to have these OptionalAttrs? And where can I see this?

Just trying to get a sense of what things are relevant here, hoping to prevent similar issues in the future.

Very good question, this made me also realize we don’t seem to be generating docs for interfaces (nice pickup task for anyone interested!) and so one would need to see this from the interface source directly: