[meta] Simplify handling of variable arguments in legalization;

If a legalization contains varargs, it defers creating the binding for
the varargs, making the generated code easier to understand.
This commit is contained in:
Benjamin Bouvier
2019-10-01 17:21:52 +02:00
parent 687604d33a
commit d3ef80147b

View File

@@ -44,6 +44,10 @@ fn unwrap_inst(
.args .args
.iter() .iter()
.enumerate() .enumerate()
.filter(|(arg_num, _)| {
// Variable args are specially handled after extracting args.
!inst.operands_in[*arg_num].is_varargs()
})
.map(|(arg_num, arg)| match &arg { .map(|(arg_num, arg)| match &arg {
Expr::Var(var_index) => var_pool.get(*var_index).name.as_ref(), Expr::Var(var_index) => var_pool.get(*var_index).name.as_ref(),
Expr::Literal(_) => { Expr::Literal(_) => {
@@ -122,16 +126,9 @@ fn unwrap_inst(
} else if op.is_value() { } else if op.is_value() {
let n = inst.value_opnums.iter().position(|&i| i == op_num).unwrap(); let n = inst.value_opnums.iter().position(|&i| i == op_num).unwrap();
fmtln!(fmt, "pos.func.dfg.resolve_aliases(args[{}]),", n); fmtln!(fmt, "pos.func.dfg.resolve_aliases(args[{}]),", n);
} else if op.is_varargs() {
let n = inst.imm_opnums.iter().chain(inst.value_opnums.iter()).max().map(|n| n + 1).unwrap_or(0);
// We need to create a `Vec` here, as using a slice would result in a borrowck
// error later on.
fmtln!(fmt, "\
args.iter().skip({}).map(|&arg| pos.func.dfg.resolve_aliases(arg)).collect::<Vec<_>>(),\
", n);
} else { } else {
// This is a value list argument. // This is a value list argument or a varargs.
assert!(iform.has_value_list); assert!(iform.has_value_list || op.is_varargs());
} }
}; };
@@ -167,10 +164,14 @@ fn unwrap_inst(
let name = &var_pool let name = &var_pool
.get(apply.args[i].maybe_var().expect("vararg without name")) .get(apply.args[i].maybe_var().expect("vararg without name"))
.name; .name;
let n = inst
// Above name is set to an `Vec` representing the varargs. However it is expected to be .imm_opnums
// `&[Value]` below, so we borrow it. .iter()
fmtln!(fmt, "let {} = &{};", name, name); .chain(inst.value_opnums.iter())
.max()
.copied()
.unwrap_or(0);
fmtln!(fmt, "let {} = &Vec::from(&args[{}..]);", name, n);
} }
} }