Rewriting function calls and signatures


Is there any infrastructure for rewriting function calls and signatures?

The target of my dialect is LLVM, and I am having a hard time dealing with calling conventions properly. E.g. converting foo({i64, i64}) to foo(i64, i64) where applicable.

If you’re lowering into the LLVM dialect directly your best reference is probably the StandardToLLVM conversion. I don’t know that there’s any generic transformation that does what you’re looking for directly, however.

I wrote this a while back as a somewhat generic utility for rewriting functions:

There’s a thread on here somewhere where we were discussing how to get something like it into the core APIs, but honestly, it feel off my radar. If it looks useful, we could revive that, or you’re welcome to take it.

Could you elaborate?

The dialect conversion framework has the signature conversion mechanism for converting things like function signatures, Dialect Conversion - MLIR. This will have to be coupled with patterns that convert function-like operations (for declarations that don’t have regions) and function calls.

Thanks, I missed the region signature converter part in the manual. It was a bit challenging to figure out the interaction between the signature converter and the argument materialisation logic though.

I ended up with a signature converter in a FuncOp rewriter pattern that splits the structs into separate arguments per fields, and an argument materialiser that reassembles the struct from the split arguments. This combined with a type rewriter for function pointers, and a CallOp-like rewriter pattern for unpacking the structs before actually calling the functions.

This was all hacked into our LLVM lowering pass, I am sure I could make it better, especially as the pass is now tightly tied to the target architecture. I suppose the long term approach in our case would be to lower to CIL instead.

You might be interested in the new DecomposeCallGraphTypes pass which I think does exactly what you are looking for.