use cursor::{Cursor, FuncCursor};
use flowgraph::ControlFlowGraph;
use ir::{self, InstBuilder};
use isa::TargetIsa;
pub fn expand_global_value(
inst: ir::Inst,
func: &mut ir::Function,
_cfg: &mut ControlFlowGraph,
_isa: &TargetIsa,
) {
let gv = match func.dfg[inst] {
ir::InstructionData::UnaryGlobalValue {
opcode,
global_value,
} => {
debug_assert_eq!(opcode, ir::Opcode::GlobalValue);
global_value
}
_ => panic!("Wanted global_value: {}", func.dfg.display_inst(inst, None)),
};
match func.global_values[gv] {
ir::GlobalValueData::VMContext { offset } => vmctx_addr(inst, func, offset.into()),
ir::GlobalValueData::Deref { base, offset } => deref_addr(inst, func, base, offset.into()),
ir::GlobalValueData::Sym { .. } => globalsym(inst, func, gv),
}
}
fn vmctx_addr(inst: ir::Inst, func: &mut ir::Function, offset: i64) {
let vmctx = func.special_param(ir::ArgumentPurpose::VMContext)
.expect("Missing vmctx parameter");
func.dfg.replace(inst).iadd_imm(vmctx, offset);
}
fn deref_addr(inst: ir::Inst, func: &mut ir::Function, base: ir::GlobalValue, offset: i64) {
let ptr_ty = func.dfg.value_type(func.dfg.first_result(inst));
let mut pos = FuncCursor::new(func).at_inst(inst);
pos.use_srcloc(inst);
let base_addr = pos.ins().global_value(ptr_ty, base);
let mut mflags = ir::MemFlags::new();
mflags.set_notrap();
mflags.set_aligned();
let base_ptr = pos.ins().load(ptr_ty, mflags, base_addr, 0);
pos.func.dfg.replace(inst).iadd_imm(base_ptr, offset);
}
fn globalsym(inst: ir::Inst, func: &mut ir::Function, gv: ir::GlobalValue) {
let ptr_ty = func.dfg.value_type(func.dfg.first_result(inst));
func.dfg.replace(inst).globalsym_addr(ptr_ty, gv);
}