Passing function pointer as argument to external function

I tried to implement function pointers with a new LLVM::FunctionAddressOfOp op in order not to mess too much with the coupling between GlobalOp/AddressOfOp. Then I noticed that ConstantOp was already doing what I wanted to implement, so I reverted everything again. Later I regretted this because the verifier of ConstantOp is not very great (at least not with symbol references). For example, there is no type-checking against the function signature, which easily triggers assertion failures during translation to LLVM IR. Also it is not obvious whether ConstantOp’s result type should be a function type or a pointer to it (void(int) vs void(*)(int) in C++ speech).

I can see several options:

  1. Implement better builders and verification for ConstantOp.
  2. Create a FunctionAddressOfOp paired with LLVMFuncOp. AddressOfOp would work only with GlobalOp.
  3. Add AddressOfOp::getFuncOp() and something like AddressOfOp::isFuncOp().

#2 might actually be the most user-friendly option, IMHO.

Would we also need a way to declare a FuncOp in the case there are circular indirect calls? I don’t know at what point the verifier is run, i.e. can it be that the verifier is executed on an operator with a symbol reference whose symbol has not been defined, yet?

I’m asking because translation to LLVM IR has some special handling for cyclic call graphs (llvm-project/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp at main · llvm/llvm-project · GitHub).

Since ConstantOp does no verification, it can handle these cases already (which is important for me).