55 lines
1.6 KiB
Rust
55 lines
1.6 KiB
Rust
//! Legalization of calls.
|
|
//!
|
|
//! This module exports the `expand_call` function which transforms a `call`
|
|
//! instruction into `func_addr` and `call_indirect` instructions.
|
|
|
|
use crate::cursor::{Cursor, FuncCursor};
|
|
use crate::flowgraph::ControlFlowGraph;
|
|
use crate::ir::{self, InstBuilder};
|
|
use crate::isa::TargetIsa;
|
|
|
|
/// Expand a `call` instruction. This lowers it to a `call_indirect`, which
|
|
/// is only done if the ABI doesn't support direct calls.
|
|
pub fn expand_call(
|
|
inst: ir::Inst,
|
|
func: &mut ir::Function,
|
|
_cfg: &mut ControlFlowGraph,
|
|
isa: &dyn TargetIsa,
|
|
) {
|
|
// Unpack the instruction.
|
|
let (func_ref, old_args) = match func.dfg[inst] {
|
|
ir::InstructionData::Call {
|
|
opcode,
|
|
ref args,
|
|
func_ref,
|
|
} => {
|
|
debug_assert_eq!(opcode, ir::Opcode::Call);
|
|
(func_ref, args.clone())
|
|
}
|
|
_ => panic!("Wanted call: {}", func.dfg.display_inst(inst, None)),
|
|
};
|
|
|
|
let ptr_ty = isa.pointer_type();
|
|
|
|
let sig = func.dfg.ext_funcs[func_ref].signature;
|
|
|
|
let callee = {
|
|
let mut pos = FuncCursor::new(func).at_inst(inst);
|
|
pos.use_srcloc(inst);
|
|
pos.ins().func_addr(ptr_ty, func_ref)
|
|
};
|
|
|
|
let mut new_args = ir::ValueList::default();
|
|
new_args.push(callee, &mut func.dfg.value_lists);
|
|
for i in 0..old_args.len(&func.dfg.value_lists) {
|
|
new_args.push(
|
|
old_args.as_slice(&func.dfg.value_lists)[i],
|
|
&mut func.dfg.value_lists,
|
|
);
|
|
}
|
|
|
|
func.dfg
|
|
.replace(inst)
|
|
.CallIndirect(ir::Opcode::CallIndirect, ptr_ty, sig, new_args);
|
|
}
|