Add a ControlFlowGraph argument to legalize_function.

Legalizing some instructions may require modifications to the control
flow graph, and some operations need to use the CFG analysis.

The CFG reference is threaded through all the legalization functions to
reach the generated expansion functions as well as the legalizer::split
module where it will be used first.
This commit is contained in:
Jakob Stoklund Olesen
2017-03-21 15:48:08 -07:00
parent f84e218a93
commit e941a7db5f
7 changed files with 52 additions and 28 deletions

View File

@@ -18,6 +18,7 @@
//! intermediate state doesn't type check.
use abi::{legalize_abi_value, ValueConversion};
use flowgraph::ControlFlowGraph;
use ir::{Function, Cursor, DataFlowGraph, Inst, InstBuilder, Ebb, Type, Value, Signature, SigRef,
ArgumentType};
use ir::instructions::CallInfo;
@@ -257,6 +258,7 @@ fn convert_from_abi<GetArg>(dfg: &mut DataFlowGraph,
/// return the `Err(ArgumentType)` that is needed.
///
fn convert_to_abi<PutArg>(dfg: &mut DataFlowGraph,
cfg: &ControlFlowGraph,
pos: &mut Cursor,
value: Value,
put_arg: &mut PutArg)
@@ -272,28 +274,28 @@ fn convert_to_abi<PutArg>(dfg: &mut DataFlowGraph,
let ty = dfg.value_type(value);
match legalize_abi_value(ty, &arg_type) {
ValueConversion::IntSplit => {
let (lo, hi) = isplit(dfg, pos, value);
convert_to_abi(dfg, pos, lo, put_arg);
convert_to_abi(dfg, pos, hi, put_arg);
let (lo, hi) = isplit(dfg, cfg, pos, value);
convert_to_abi(dfg, cfg, pos, lo, put_arg);
convert_to_abi(dfg, cfg, pos, hi, put_arg);
}
ValueConversion::VectorSplit => {
let (lo, hi) = vsplit(dfg, pos, value);
convert_to_abi(dfg, pos, lo, put_arg);
convert_to_abi(dfg, pos, hi, put_arg);
let (lo, hi) = vsplit(dfg, cfg, pos, value);
convert_to_abi(dfg, cfg, pos, lo, put_arg);
convert_to_abi(dfg, cfg, pos, hi, put_arg);
}
ValueConversion::IntBits => {
assert!(!ty.is_int());
let abi_ty = Type::int(ty.bits()).expect("Invalid type for conversion");
let arg = dfg.ins(pos).bitcast(abi_ty, value);
convert_to_abi(dfg, pos, arg, put_arg);
convert_to_abi(dfg, cfg, pos, arg, put_arg);
}
ValueConversion::Sext(abi_ty) => {
let arg = dfg.ins(pos).sextend(abi_ty, value);
convert_to_abi(dfg, pos, arg, put_arg);
convert_to_abi(dfg, cfg, pos, arg, put_arg);
}
ValueConversion::Uext(abi_ty) => {
let arg = dfg.ins(pos).uextend(abi_ty, value);
convert_to_abi(dfg, pos, arg, put_arg);
convert_to_abi(dfg, cfg, pos, arg, put_arg);
}
}
}
@@ -361,6 +363,7 @@ fn check_return_signature(dfg: &DataFlowGraph, inst: Inst, sig: &Signature) -> b
/// argument number in `0..abi_args`.
///
fn legalize_inst_arguments<ArgType>(dfg: &mut DataFlowGraph,
cfg: &ControlFlowGraph,
pos: &mut Cursor,
abi_args: usize,
mut get_abi_type: ArgType)
@@ -419,7 +422,7 @@ fn legalize_inst_arguments<ArgType>(dfg: &mut DataFlowGraph,
Err(abi_type)
}
};
convert_to_abi(dfg, pos, old_value, &mut put_arg);
convert_to_abi(dfg, cfg, pos, old_value, &mut put_arg);
}
// Put the modified value list back.
@@ -436,7 +439,7 @@ fn legalize_inst_arguments<ArgType>(dfg: &mut DataFlowGraph,
/// original return values. The call's result values will be adapted to match the new signature.
///
/// Returns `true` if any instructions were inserted.
pub fn handle_call_abi(dfg: &mut DataFlowGraph, pos: &mut Cursor) -> bool {
pub fn handle_call_abi(dfg: &mut DataFlowGraph, cfg: &ControlFlowGraph, pos: &mut Cursor) -> bool {
let mut inst = pos.current_inst().expect("Cursor must point to a call instruction");
// Start by checking if the argument types already match the signature.
@@ -448,6 +451,7 @@ pub fn handle_call_abi(dfg: &mut DataFlowGraph, pos: &mut Cursor) -> bool {
// OK, we need to fix the call arguments to match the ABI signature.
let abi_args = dfg.signatures[sig_ref].argument_types.len();
legalize_inst_arguments(dfg,
cfg,
pos,
abi_args,
|dfg, abi_arg| dfg.signatures[sig_ref].argument_types[abi_arg]);
@@ -471,7 +475,11 @@ pub fn handle_call_abi(dfg: &mut DataFlowGraph, pos: &mut Cursor) -> bool {
/// Insert ABI conversion code before and after the call instruction at `pos`.
///
/// Return `true` if any instructions were inserted.
pub fn handle_return_abi(dfg: &mut DataFlowGraph, pos: &mut Cursor, sig: &Signature) -> bool {
pub fn handle_return_abi(dfg: &mut DataFlowGraph,
cfg: &ControlFlowGraph,
pos: &mut Cursor,
sig: &Signature)
-> bool {
let inst = pos.current_inst().expect("Cursor must point to a return instruction");
// Check if the returned types already match the signature.
@@ -480,7 +488,11 @@ pub fn handle_return_abi(dfg: &mut DataFlowGraph, pos: &mut Cursor, sig: &Signat
}
let abi_args = sig.return_types.len();
legalize_inst_arguments(dfg, pos, abi_args, |_, abi_arg| sig.return_types[abi_arg]);
legalize_inst_arguments(dfg,
cfg,
pos,
abi_args,
|_, abi_arg| sig.return_types[abi_arg]);
debug_assert!(check_return_signature(dfg, inst, sig),
"Signature still wrong: {}, sig{}",