I’ve decided that it’s best to have Callee::Global and Callee::Local in the Call instruction. It ensures that I don’t have to duplicate code in places that I don’t care about the callee.
Type Inference
I’m trying to figure out the type inference for function pointers. I’ve started by looking at SourceTypes::gen_constraints in lang/stypes.rs. Specifically, I’m looking at the SIInstr::Call branch to understand it better.
It looks like it currently uses func_id (for global functions) in two places:
// lhs type inference
if let Some(lhs) = lhs {
let ty = &llvm_instr.get_type(&ctx.module.types);
constraints.add_has_type(*lhs, ty.clone());
constraints.add_type_equiv(*lhs, func_id.clone());
}// parameter type inference
let params = &ctx
.funcs
.get(func_id)
.expect(
"All called functions should have been \
declared, and thus appear in `funcs`.",
)
.param_vars;
for ((param, arg_var), arg_tl) in
params.iter().zip(args.iter()).zip(args_tl)
{
if let Some(arg_var) = arg_var {
constraints.add_type_equiv(*arg_var, *arg_tl);
}
constraints.add_type_equiv(*param, *arg_tl);
}I’m going to focus first on understanding LHS type inference.
LHS Type Inference
// lhs type inference
if let Some(lhs) = lhs {
let ty = &llvm_instr.get_type(&ctx.module.types);
constraints.add_has_type(*lhs, ty.clone());
constraints.add_type_equiv(*lhs, func_id.clone());
}My first note is that func_id implements the refinator::slang::stype::AsValue trait. I’m not sure what this trait does. Based on the documentation, it looks like it turns anything that can represent a type into an i64, which I think represents a unique type.
Why is it
i64and notu64?It’s because that’s what egglog uses