mlirlite.build_call composes the llvm.call function type from the argument values and the
caller-supplied return type; it never consults the callee. Declares are synthesized the same
way (_ensure_method_declare appends missing params from the caller's own argument values and
never compares return types), so nothing verified that a call site agreed with the definition.
Two modules could therefore emit incompatible calls for the same symbol, which only the MLIR
verifier rejected later:
llvm.func @MapHHDM(i64, i64, i64) (definition, void)
llvm.call @MapHHDM(i64, i64, i32) -> i32 (caller)
- after the declare/definition exists, conform every fixed argument to its parameter type and
emit the call with the symbol's return type (_conform_call_args / _call_symbol_ret_ty)
- fail fast when a cross-module call site resolves a return type the symbol disagrees with,
instead of emitting both and letting mlir-opt report an operand type mismatch
- record a module-level `def` without a return annotation as `void` in the vpi return-annotation
cache (previously a hardcoded i32, so callers invented an i32 return for void exports);
extern/state C declarations and methods keep the legacy default