use std::collections::HashMap;
use super::types::UfSignature;
pub fn infer_uf_signatures(
pkg: &xlsynth_pir::ir::Package,
uf_map: &HashMap<String, String>,
) -> Result<HashMap<String, UfSignature>, String> {
let mut uf_sigs: HashMap<String, UfSignature> = HashMap::new();
for (fn_name, uf_sym) in uf_map {
let (ir_fn, skip_implicit) = match pkg.get_fn(fn_name) {
Some(f) => (f, false),
None => {
let itok_name = format!("__itok{}", fn_name);
match pkg.get_fn(&itok_name) {
Some(f) => (f, true),
None => {
return Err(format!(
"Unknown function '{}' when inferring UF signature for symbol '{}'",
fn_name, uf_sym
));
}
}
}
};
let arg_widths: Vec<usize> = if skip_implicit {
ir_fn
.param_nodes()
.skip(2)
.map(|p| p.ty.bit_count())
.collect()
} else {
ir_fn.param_nodes().map(|p| p.ty.bit_count()).collect()
};
let ret_width = ir_fn.ret_ty.bit_count();
let sig = UfSignature {
arg_widths,
ret_width,
};
if let Some(prev) = uf_sigs.get(uf_sym) {
if prev != &sig {
return Err(format!(
"Conflicting UF signature for symbol '{}': {:?} vs {:?}",
uf_sym, prev, sig
));
}
} else {
uf_sigs.insert(uf_sym.clone(), sig);
}
}
Ok(uf_sigs)
}
pub fn merge_uf_signatures(
mut lhs: HashMap<String, UfSignature>,
rhs: &HashMap<String, UfSignature>,
) -> Result<HashMap<String, UfSignature>, String> {
for (name, sig) in rhs {
if let Some(prev) = lhs.get(name) {
if prev != sig {
return Err(format!(
"Conflicting UF signature for symbol '{}': {:?} vs {:?}",
name, prev, sig
));
}
} else {
lhs.insert(name.clone(), sig.clone());
}
}
Ok(lhs)
}
pub fn infer_merged_uf_signatures(
lhs_pkg: &xlsynth_pir::ir::Package,
lhs_map: &HashMap<String, String>,
rhs_pkg: &xlsynth_pir::ir::Package,
rhs_map: &HashMap<String, String>,
) -> Result<HashMap<String, UfSignature>, String> {
let lhs = infer_uf_signatures(lhs_pkg, lhs_map)?;
let rhs = infer_uf_signatures(rhs_pkg, rhs_map)?;
merge_uf_signatures(lhs, &rhs)
}