Update rustfmt to 0.9.0.
This commit is contained in:
@@ -98,9 +98,11 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
|
||||
// Compute the value we want for `arg` from the legalized ABI arguments.
|
||||
let mut get_arg = |dfg: &mut DataFlowGraph, ty| {
|
||||
let abi_type = abi_types[abi_arg];
|
||||
assert_eq!(abi_type.purpose,
|
||||
ArgumentPurpose::Normal,
|
||||
"Can't legalize special-purpose argument");
|
||||
assert_eq!(
|
||||
abi_type.purpose,
|
||||
ArgumentPurpose::Normal,
|
||||
"Can't legalize special-purpose argument"
|
||||
);
|
||||
if ty == abi_type.value_type {
|
||||
abi_arg += 1;
|
||||
Ok(dfg.append_ebb_arg(entry, ty))
|
||||
@@ -159,14 +161,17 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
|
||||
/// This function is very similar to the `legalize_entry_arguments` function above.
|
||||
///
|
||||
/// Returns the possibly new instruction representing the call.
|
||||
fn legalize_inst_results<ResType>(dfg: &mut DataFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
mut get_abi_type: ResType)
|
||||
-> Inst
|
||||
where ResType: FnMut(&DataFlowGraph, usize) -> ArgumentType
|
||||
fn legalize_inst_results<ResType>(
|
||||
dfg: &mut DataFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
mut get_abi_type: ResType,
|
||||
) -> Inst
|
||||
where
|
||||
ResType: FnMut(&DataFlowGraph, usize) -> ArgumentType,
|
||||
{
|
||||
let call = pos.current_inst()
|
||||
.expect("Cursor must point to a call instruction");
|
||||
let call = pos.current_inst().expect(
|
||||
"Cursor must point to a call instruction",
|
||||
);
|
||||
|
||||
// We theoretically allow for call instructions that return a number of fixed results before
|
||||
// the call return values. In practice, it doesn't happen.
|
||||
@@ -216,13 +221,15 @@ fn legalize_inst_results<ResType>(dfg: &mut DataFlowGraph,
|
||||
/// - `Err(arg_type)` if further conversions are needed from the ABI argument `arg_type`.
|
||||
///
|
||||
/// If the `into_result` value is provided, the converted result will be written into that value.
|
||||
fn convert_from_abi<GetArg>(dfg: &mut DataFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
ty: Type,
|
||||
into_result: Option<Value>,
|
||||
get_arg: &mut GetArg)
|
||||
-> Value
|
||||
where GetArg: FnMut(&mut DataFlowGraph, Type) -> Result<Value, ArgumentType>
|
||||
fn convert_from_abi<GetArg>(
|
||||
dfg: &mut DataFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
ty: Type,
|
||||
into_result: Option<Value>,
|
||||
get_arg: &mut GetArg,
|
||||
) -> Value
|
||||
where
|
||||
GetArg: FnMut(&mut DataFlowGraph, Type) -> Result<Value, ArgumentType>,
|
||||
{
|
||||
// Terminate the recursion when we get the desired type.
|
||||
let arg_type = match get_arg(dfg, ty) {
|
||||
@@ -246,11 +253,13 @@ fn convert_from_abi<GetArg>(dfg: &mut DataFlowGraph,
|
||||
let abi_ty = ty.half_width().expect("Invalid type for conversion");
|
||||
let lo = convert_from_abi(dfg, pos, abi_ty, None, get_arg);
|
||||
let hi = convert_from_abi(dfg, pos, abi_ty, None, get_arg);
|
||||
dbg!("intsplit {}: {}, {}: {}",
|
||||
lo,
|
||||
dfg.value_type(lo),
|
||||
hi,
|
||||
dfg.value_type(hi));
|
||||
dbg!(
|
||||
"intsplit {}: {}, {}: {}",
|
||||
lo,
|
||||
dfg.value_type(lo),
|
||||
hi,
|
||||
dfg.value_type(hi)
|
||||
);
|
||||
dfg.ins(pos).with_results([into_result]).iconcat(lo, hi)
|
||||
}
|
||||
// Construct a `ty` by concatenating two halves of a vector.
|
||||
@@ -296,12 +305,14 @@ fn convert_from_abi<GetArg>(dfg: &mut DataFlowGraph,
|
||||
/// 2. If the suggested argument doesn't have the right value type, don't change anything, but
|
||||
/// 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)
|
||||
where PutArg: FnMut(&mut DataFlowGraph, Value) -> Result<(), ArgumentType>
|
||||
fn convert_to_abi<PutArg>(
|
||||
dfg: &mut DataFlowGraph,
|
||||
cfg: &ControlFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
value: Value,
|
||||
put_arg: &mut PutArg,
|
||||
) where
|
||||
PutArg: FnMut(&mut DataFlowGraph, Value) -> Result<(), ArgumentType>,
|
||||
{
|
||||
// Start by invoking the closure to either terminate the recursion or get the argument type
|
||||
// we're trying to match.
|
||||
@@ -360,7 +371,8 @@ fn check_call_signature(dfg: &DataFlowGraph, inst: Inst) -> Result<(), SigRef> {
|
||||
let sig = &dfg.signatures[sig_ref];
|
||||
|
||||
if check_arg_types(dfg, args, &sig.argument_types[..]) &&
|
||||
check_arg_types(dfg, dfg.inst_results(inst), &sig.return_types[..]) {
|
||||
check_arg_types(dfg, dfg.inst_results(inst), &sig.return_types[..])
|
||||
{
|
||||
// All types check out.
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -380,20 +392,23 @@ fn check_return_signature(dfg: &DataFlowGraph, inst: Inst, sig: &Signature) -> b
|
||||
/// - `get_abi_type` is a closure that can provide the desired `ArgumentType` for a given ABI
|
||||
/// 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)
|
||||
where ArgType: FnMut(&DataFlowGraph, usize) -> ArgumentType
|
||||
fn legalize_inst_arguments<ArgType>(
|
||||
dfg: &mut DataFlowGraph,
|
||||
cfg: &ControlFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
abi_args: usize,
|
||||
mut get_abi_type: ArgType,
|
||||
) where
|
||||
ArgType: FnMut(&DataFlowGraph, usize) -> ArgumentType,
|
||||
{
|
||||
let inst = pos.current_inst()
|
||||
.expect("Cursor must point to a call instruction");
|
||||
let inst = pos.current_inst().expect(
|
||||
"Cursor must point to a call instruction",
|
||||
);
|
||||
|
||||
// Lift the value list out of the call instruction so we modify it.
|
||||
let mut vlist = dfg[inst]
|
||||
.take_value_list()
|
||||
.expect("Call must have a value list");
|
||||
let mut vlist = dfg[inst].take_value_list().expect(
|
||||
"Call must have a value list",
|
||||
);
|
||||
|
||||
// The value list contains all arguments to the instruction, including the callee on an
|
||||
// indirect call which isn't part of the call arguments that must match the ABI signature.
|
||||
@@ -474,23 +489,23 @@ pub fn handle_call_abi(mut inst: Inst, func: &mut Function, cfg: &ControlFlowGra
|
||||
|
||||
// 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]);
|
||||
legalize_inst_arguments(dfg, cfg, pos, abi_args, |dfg, abi_arg| {
|
||||
dfg.signatures[sig_ref].argument_types[abi_arg]
|
||||
});
|
||||
|
||||
if !dfg.signatures[sig_ref].return_types.is_empty() {
|
||||
inst = legalize_inst_results(dfg,
|
||||
pos,
|
||||
|dfg, abi_res| dfg.signatures[sig_ref].return_types[abi_res]);
|
||||
inst = legalize_inst_results(dfg, pos, |dfg, abi_res| {
|
||||
dfg.signatures[sig_ref].return_types[abi_res]
|
||||
});
|
||||
}
|
||||
|
||||
debug_assert!(check_call_signature(dfg, inst).is_ok(),
|
||||
"Signature still wrong: {}, {}{}",
|
||||
dfg.display_inst(inst, None),
|
||||
sig_ref,
|
||||
dfg.signatures[sig_ref]);
|
||||
debug_assert!(
|
||||
check_call_signature(dfg, inst).is_ok(),
|
||||
"Signature still wrong: {}, {}{}",
|
||||
dfg.display_inst(inst, None),
|
||||
sig_ref,
|
||||
dfg.signatures[sig_ref]
|
||||
);
|
||||
|
||||
// Go back and insert spills for any stack arguments.
|
||||
pos.goto_inst(inst);
|
||||
@@ -519,27 +534,30 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
|
||||
.iter()
|
||||
.rev()
|
||||
.take_while(|&rt| {
|
||||
rt.purpose == ArgumentPurpose::Link ||
|
||||
rt.purpose == ArgumentPurpose::StructReturn ||
|
||||
rt.purpose == ArgumentPurpose::VMContext
|
||||
})
|
||||
rt.purpose == ArgumentPurpose::Link || rt.purpose == ArgumentPurpose::StructReturn ||
|
||||
rt.purpose == ArgumentPurpose::VMContext
|
||||
})
|
||||
.count();
|
||||
|
||||
let abi_args = sig.return_types.len() - special_args;
|
||||
legalize_inst_arguments(dfg,
|
||||
cfg,
|
||||
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],
|
||||
);
|
||||
assert_eq!(dfg.inst_variable_args(inst).len(), abi_args);
|
||||
|
||||
// Append special return arguments for any `sret`, `link`, and `vmctx` return values added to
|
||||
// the legalized signature. These values should simply be propagated from the entry block
|
||||
// arguments.
|
||||
if special_args > 0 {
|
||||
dbg!("Adding {} special-purpose arguments to {}",
|
||||
special_args,
|
||||
dfg.display_inst(inst, None));
|
||||
dbg!(
|
||||
"Adding {} special-purpose arguments to {}",
|
||||
special_args,
|
||||
dfg.display_inst(inst, None)
|
||||
);
|
||||
let mut vlist = dfg[inst].take_value_list().unwrap();
|
||||
for arg in &sig.return_types[abi_args..] {
|
||||
match arg.purpose {
|
||||
@@ -565,10 +583,12 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
|
||||
dfg[inst].put_value_list(vlist);
|
||||
}
|
||||
|
||||
debug_assert!(check_return_signature(dfg, inst, sig),
|
||||
"Signature still wrong: {} / signature {}",
|
||||
dfg.display_inst(inst, None),
|
||||
sig);
|
||||
debug_assert!(
|
||||
check_return_signature(dfg, inst, sig),
|
||||
"Signature still wrong: {} / signature {}",
|
||||
dfg.display_inst(inst, None),
|
||||
sig
|
||||
);
|
||||
|
||||
// Yes, we changed stuff.
|
||||
true
|
||||
@@ -579,10 +599,10 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
|
||||
/// Values that are passed into the function on the stack must be assigned to an `IncomingArg`
|
||||
/// stack slot already during legalization.
|
||||
fn spill_entry_arguments(func: &mut Function, entry: Ebb) {
|
||||
for (abi, &arg) in func.signature
|
||||
.argument_types
|
||||
.iter()
|
||||
.zip(func.dfg.ebb_args(entry)) {
|
||||
for (abi, &arg) in func.signature.argument_types.iter().zip(
|
||||
func.dfg.ebb_args(entry),
|
||||
)
|
||||
{
|
||||
if let ArgumentLoc::Stack(offset) = abi.location {
|
||||
let ss = func.stack_slots.make_incoming_arg(abi.value_type, offset);
|
||||
func.locations[arg] = ValueLoc::Stack(ss);
|
||||
@@ -598,15 +618,18 @@ fn spill_entry_arguments(func: &mut Function, entry: Ebb) {
|
||||
/// TODO: The outgoing stack slots can be written a bit earlier, as long as there are no branches
|
||||
/// or calls between writing the stack slots and the call instruction. Writing the slots earlier
|
||||
/// could help reduce register pressure before the call.
|
||||
fn spill_call_arguments(dfg: &mut DataFlowGraph,
|
||||
locations: &mut ValueLocations,
|
||||
stack_slots: &mut StackSlots,
|
||||
pos: &mut Cursor)
|
||||
-> bool {
|
||||
let inst = pos.current_inst()
|
||||
.expect("Cursor must point to a call instruction");
|
||||
let sig_ref = dfg.call_signature(inst)
|
||||
.expect("Call instruction expected.");
|
||||
fn spill_call_arguments(
|
||||
dfg: &mut DataFlowGraph,
|
||||
locations: &mut ValueLocations,
|
||||
stack_slots: &mut StackSlots,
|
||||
pos: &mut Cursor,
|
||||
) -> bool {
|
||||
let inst = pos.current_inst().expect(
|
||||
"Cursor must point to a call instruction",
|
||||
);
|
||||
let sig_ref = dfg.call_signature(inst).expect(
|
||||
"Call instruction expected.",
|
||||
);
|
||||
|
||||
// Start by building a list of stack slots and arguments to be replaced.
|
||||
// This requires borrowing `dfg`, so we can't change anything.
|
||||
|
||||
@@ -35,12 +35,14 @@ pub fn expand_heap_addr(inst: ir::Inst, func: &mut ir::Function, _cfg: &mut Cont
|
||||
}
|
||||
|
||||
/// Expand a `heap_addr` for a dynamic heap.
|
||||
fn dynamic_addr(inst: ir::Inst,
|
||||
heap: ir::Heap,
|
||||
offset: ir::Value,
|
||||
size: u32,
|
||||
bound_gv: ir::GlobalVar,
|
||||
func: &mut ir::Function) {
|
||||
fn dynamic_addr(
|
||||
inst: ir::Inst,
|
||||
heap: ir::Heap,
|
||||
offset: ir::Value,
|
||||
size: u32,
|
||||
bound_gv: ir::GlobalVar,
|
||||
func: &mut ir::Function,
|
||||
) {
|
||||
let size = size as i64;
|
||||
let offset_ty = func.dfg.value_type(offset);
|
||||
let addr_ty = func.dfg.value_type(func.dfg.first_result(inst));
|
||||
@@ -54,21 +56,30 @@ fn dynamic_addr(inst: ir::Inst,
|
||||
let oob;
|
||||
if size == 1 {
|
||||
// `offset > bound - 1` is the same as `offset >= bound`.
|
||||
oob = pos.ins()
|
||||
.icmp(IntCC::UnsignedGreaterThanOrEqual, offset, bound);
|
||||
oob = pos.ins().icmp(
|
||||
IntCC::UnsignedGreaterThanOrEqual,
|
||||
offset,
|
||||
bound,
|
||||
);
|
||||
} else if size <= min_size {
|
||||
// We know that bound >= min_size, so here we can compare `offset > bound - size` without
|
||||
// wrapping.
|
||||
let adj_bound = pos.ins().iadd_imm(bound, -size);
|
||||
oob = pos.ins()
|
||||
.icmp(IntCC::UnsignedGreaterThan, offset, adj_bound);
|
||||
oob = pos.ins().icmp(
|
||||
IntCC::UnsignedGreaterThan,
|
||||
offset,
|
||||
adj_bound,
|
||||
);
|
||||
} else {
|
||||
// We need an overflow check for the adjusted offset.
|
||||
let size_val = pos.ins().iconst(offset_ty, size);
|
||||
let (adj_offset, overflow) = pos.ins().iadd_cout(offset, size_val);
|
||||
pos.ins().trapnz(overflow);
|
||||
oob = pos.ins()
|
||||
.icmp(IntCC::UnsignedGreaterThan, adj_offset, bound);
|
||||
oob = pos.ins().icmp(
|
||||
IntCC::UnsignedGreaterThan,
|
||||
adj_offset,
|
||||
bound,
|
||||
);
|
||||
}
|
||||
pos.ins().trapnz(oob);
|
||||
|
||||
@@ -76,12 +87,14 @@ fn dynamic_addr(inst: ir::Inst,
|
||||
}
|
||||
|
||||
/// Expand a `heap_addr` for a static heap.
|
||||
fn static_addr(inst: ir::Inst,
|
||||
heap: ir::Heap,
|
||||
offset: ir::Value,
|
||||
size: u32,
|
||||
bound: i64,
|
||||
func: &mut ir::Function) {
|
||||
fn static_addr(
|
||||
inst: ir::Inst,
|
||||
heap: ir::Heap,
|
||||
offset: ir::Value,
|
||||
size: u32,
|
||||
bound: i64,
|
||||
func: &mut ir::Function,
|
||||
) {
|
||||
let size = size as i64;
|
||||
let offset_ty = func.dfg.value_type(offset);
|
||||
let addr_ty = func.dfg.value_type(func.dfg.first_result(inst));
|
||||
@@ -104,11 +117,17 @@ fn static_addr(inst: ir::Inst,
|
||||
let oob = if limit & 1 == 1 {
|
||||
// Prefer testing `offset >= limit - 1` when limit is odd because an even number is
|
||||
// likely to be a convenient constant on ARM and other RISC architectures.
|
||||
pos.ins()
|
||||
.icmp_imm(IntCC::UnsignedGreaterThanOrEqual, offset, limit - 1)
|
||||
pos.ins().icmp_imm(
|
||||
IntCC::UnsignedGreaterThanOrEqual,
|
||||
offset,
|
||||
limit - 1,
|
||||
)
|
||||
} else {
|
||||
pos.ins()
|
||||
.icmp_imm(IntCC::UnsignedGreaterThan, offset, limit)
|
||||
pos.ins().icmp_imm(
|
||||
IntCC::UnsignedGreaterThan,
|
||||
offset,
|
||||
limit,
|
||||
)
|
||||
};
|
||||
pos.ins().trapnz(oob);
|
||||
}
|
||||
@@ -119,12 +138,14 @@ fn static_addr(inst: ir::Inst,
|
||||
/// Emit code for the base address computation of a `heap_addr` instruction.
|
||||
///
|
||||
///
|
||||
fn offset_addr(inst: ir::Inst,
|
||||
heap: ir::Heap,
|
||||
addr_ty: ir::Type,
|
||||
mut offset: ir::Value,
|
||||
offset_ty: ir::Type,
|
||||
func: &mut ir::Function) {
|
||||
fn offset_addr(
|
||||
inst: ir::Inst,
|
||||
heap: ir::Heap,
|
||||
addr_ty: ir::Type,
|
||||
mut offset: ir::Value,
|
||||
offset_ty: ir::Type,
|
||||
func: &mut ir::Function,
|
||||
) {
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
|
||||
// Convert `offset` to `addr_ty`.
|
||||
|
||||
@@ -66,9 +66,11 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is
|
||||
split::simplify_branch_arguments(&mut pos.func.dfg, inst);
|
||||
}
|
||||
|
||||
match isa.encode(&pos.func.dfg,
|
||||
&pos.func.dfg[inst],
|
||||
pos.func.dfg.ctrl_typevar(inst)) {
|
||||
match isa.encode(
|
||||
&pos.func.dfg,
|
||||
&pos.func.dfg[inst],
|
||||
pos.func.dfg.ctrl_typevar(inst),
|
||||
) {
|
||||
Ok(encoding) => pos.func.encodings[inst] = encoding,
|
||||
Err(action) => {
|
||||
// We should transform the instruction into legal equivalents.
|
||||
|
||||
@@ -71,21 +71,23 @@ use std::iter;
|
||||
|
||||
/// Split `value` into two values using the `isplit` semantics. Do this by reusing existing values
|
||||
/// if possible.
|
||||
pub fn isplit(dfg: &mut DataFlowGraph,
|
||||
cfg: &ControlFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
value: Value)
|
||||
-> (Value, Value) {
|
||||
pub fn isplit(
|
||||
dfg: &mut DataFlowGraph,
|
||||
cfg: &ControlFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
value: Value,
|
||||
) -> (Value, Value) {
|
||||
split_any(dfg, cfg, pos, value, Opcode::Iconcat)
|
||||
}
|
||||
|
||||
/// Split `value` into halves using the `vsplit` semantics. Do this by reusing existing values if
|
||||
/// possible.
|
||||
pub fn vsplit(dfg: &mut DataFlowGraph,
|
||||
cfg: &ControlFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
value: Value)
|
||||
-> (Value, Value) {
|
||||
pub fn vsplit(
|
||||
dfg: &mut DataFlowGraph,
|
||||
cfg: &ControlFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
value: Value,
|
||||
) -> (Value, Value) {
|
||||
split_any(dfg, cfg, pos, value, Opcode::Vconcat)
|
||||
}
|
||||
|
||||
@@ -107,12 +109,13 @@ struct Repair {
|
||||
}
|
||||
|
||||
/// Generic version of `isplit` and `vsplit` controlled by the `concat` opcode.
|
||||
fn split_any(dfg: &mut DataFlowGraph,
|
||||
cfg: &ControlFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
value: Value,
|
||||
concat: Opcode)
|
||||
-> (Value, Value) {
|
||||
fn split_any(
|
||||
dfg: &mut DataFlowGraph,
|
||||
cfg: &ControlFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
value: Value,
|
||||
concat: Opcode,
|
||||
) -> (Value, Value) {
|
||||
let saved_pos = pos.position();
|
||||
let mut repairs = Vec::new();
|
||||
let result = split_value(dfg, pos, value, concat, &mut repairs);
|
||||
@@ -121,17 +124,20 @@ fn split_any(dfg: &mut DataFlowGraph,
|
||||
while let Some(repair) = repairs.pop() {
|
||||
for &(_, inst) in cfg.get_predecessors(repair.ebb) {
|
||||
let branch_opc = dfg[inst].opcode();
|
||||
assert!(branch_opc.is_branch(),
|
||||
"Predecessor not a branch: {}",
|
||||
dfg.display_inst(inst, None));
|
||||
assert!(
|
||||
branch_opc.is_branch(),
|
||||
"Predecessor not a branch: {}",
|
||||
dfg.display_inst(inst, None)
|
||||
);
|
||||
let fixed_args = branch_opc.constraints().fixed_value_arguments();
|
||||
let mut args = dfg[inst]
|
||||
.take_value_list()
|
||||
.expect("Branches must have value lists.");
|
||||
let mut args = dfg[inst].take_value_list().expect(
|
||||
"Branches must have value lists.",
|
||||
);
|
||||
let num_args = args.len(&dfg.value_lists);
|
||||
// Get the old value passed to the EBB argument we're repairing.
|
||||
let old_arg = args.get(fixed_args + repair.num, &dfg.value_lists)
|
||||
.expect("Too few branch arguments");
|
||||
let old_arg = args.get(fixed_args + repair.num, &dfg.value_lists).expect(
|
||||
"Too few branch arguments",
|
||||
);
|
||||
|
||||
// It's possible that the CFG's predecessor list has duplicates. Detect them here.
|
||||
if dfg.value_type(old_arg) == repair.split_type {
|
||||
@@ -145,19 +151,21 @@ fn split_any(dfg: &mut DataFlowGraph,
|
||||
|
||||
// The `lo` part replaces the original argument.
|
||||
*args.get_mut(fixed_args + repair.num, &mut dfg.value_lists)
|
||||
.unwrap() = lo;
|
||||
.unwrap() = lo;
|
||||
|
||||
// The `hi` part goes at the end. Since multiple repairs may have been scheduled to the
|
||||
// same EBB, there could be multiple arguments missing.
|
||||
if num_args > fixed_args + repair.hi_num {
|
||||
*args.get_mut(fixed_args + repair.hi_num, &mut dfg.value_lists)
|
||||
.unwrap() = hi;
|
||||
.unwrap() = hi;
|
||||
} else {
|
||||
// We need to append one or more arguments. If we're adding more than one argument,
|
||||
// there must be pending repairs on the stack that will fill in the correct values
|
||||
// instead of `hi`.
|
||||
args.extend(iter::repeat(hi).take(1 + fixed_args + repair.hi_num - num_args),
|
||||
&mut dfg.value_lists);
|
||||
args.extend(
|
||||
iter::repeat(hi).take(1 + fixed_args + repair.hi_num - num_args),
|
||||
&mut dfg.value_lists,
|
||||
);
|
||||
}
|
||||
|
||||
// Put the value list back after manipulating it.
|
||||
@@ -175,12 +183,13 @@ fn split_any(dfg: &mut DataFlowGraph,
|
||||
/// instruction.
|
||||
///
|
||||
/// Return the two new values representing the parts of `value`.
|
||||
fn split_value(dfg: &mut DataFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
value: Value,
|
||||
concat: Opcode,
|
||||
repairs: &mut Vec<Repair>)
|
||||
-> (Value, Value) {
|
||||
fn split_value(
|
||||
dfg: &mut DataFlowGraph,
|
||||
pos: &mut Cursor,
|
||||
value: Value,
|
||||
concat: Opcode,
|
||||
repairs: &mut Vec<Repair>,
|
||||
) -> (Value, Value) {
|
||||
let value = dfg.resolve_copies(value);
|
||||
let mut reuse = None;
|
||||
|
||||
@@ -228,9 +237,12 @@ fn split_value(dfg: &mut DataFlowGraph,
|
||||
// need to insert a split instruction before returning.
|
||||
pos.goto_top(ebb);
|
||||
pos.next_inst();
|
||||
dfg.ins(pos)
|
||||
.with_result(value)
|
||||
.Binary(concat, split_type, lo, hi);
|
||||
dfg.ins(pos).with_result(value).Binary(
|
||||
concat,
|
||||
split_type,
|
||||
lo,
|
||||
hi,
|
||||
);
|
||||
|
||||
// Finally, splitting the EBB argument is not enough. We also have to repair all
|
||||
// of the predecessor instructions that branch here.
|
||||
@@ -254,19 +266,21 @@ fn split_value(dfg: &mut DataFlowGraph,
|
||||
}
|
||||
|
||||
// Add a repair entry to the work list.
|
||||
fn add_repair(concat: Opcode,
|
||||
split_type: Type,
|
||||
ebb: Ebb,
|
||||
num: usize,
|
||||
hi_num: usize,
|
||||
repairs: &mut Vec<Repair>) {
|
||||
fn add_repair(
|
||||
concat: Opcode,
|
||||
split_type: Type,
|
||||
ebb: Ebb,
|
||||
num: usize,
|
||||
hi_num: usize,
|
||||
repairs: &mut Vec<Repair>,
|
||||
) {
|
||||
repairs.push(Repair {
|
||||
concat,
|
||||
split_type,
|
||||
ebb,
|
||||
num,
|
||||
hi_num,
|
||||
});
|
||||
concat,
|
||||
split_type,
|
||||
ebb,
|
||||
num,
|
||||
hi_num,
|
||||
});
|
||||
}
|
||||
|
||||
/// Strip concat-split chains. Return a simpler way of computing the same value.
|
||||
|
||||
Reference in New Issue
Block a user