[RFC] Rebooting C APIs for core IR

Online discussion yesterday resulted in an alternative proposal: reflect ownership transfer in the naming convention instead of the type system. It can reduce the number of types exposed in the API, form 12 to 8 in the current prototype, and remove one function per owning/non-owning pair, that is 4 functions in the current prototype. This will not be consistent with the C++ API, in particular there will be no visible counterpart for OwningModuleRef and std::unique_ptr<Region>, that will become plain pointers instead. Note that the current proposal is also inconsistent with the C++ API as the latter doesn’t have owning types for Operation and Block.

The naming scheme could resemble the following:

  • a function that returns an object that the caller will own must include Create after it mentions the object, usually its type: mlirContextCreate, mlirBlockCreate; the keyword is used as suffix to preserve the convention of the functions related to mlir<Obj> starting with mlir<Obj>;
  • a function that takes ownership of its argument must include Owned before it mentions the object it intends to take ownership of: mlirRegionAppendOwnedBlock(mlirRegion, mlirBlock) does not take ownership of the Region argument but does take ownership of the Block argument;
  • any other function does not take or transfer ownership.

This does not allow the compiler to catch some ownership transfer issues, e.g. attempting to transfer the ownership twice would not have been caught by the initial proposal either but attempting to transfer ownership of a non-owned pointer would have, but makes the API slightly simpler. This is also slightly more in line with what many existing C APIs provide.

Any further thoughts or suggestions on this subject?


In the same call, we seemed to reach consensus that the API headers should be located in mlir/include/mlir-c wrt to the LLVM monorepo. We did not have the time to discuss the library/implementation layout though. The following alternatives were mentioned previously:

  • mlir/lib/CAPI
  • mlir/lib/Bindings/C
  • distributed across relevant files under mlir/lib/IR/*

I am less favorable to the last option as it makes C APIs less hermetic.

Any opinions?