use crate::cursor::{Cursor, FuncCursor};
use crate::flowgraph::ControlFlowGraph;
use crate::ir::{self, InstBuilder};
use crate::isa::TargetIsa;
pub fn expand_global_value(
inst: ir::Inst,
func: &mut ir::Function,
_cfg: &mut ControlFlowGraph,
isa: &dyn 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 => vmctx_addr(inst, func),
ir::GlobalValueData::IAddImm {
base,
offset,
global_type,
} => iadd_imm_addr(inst, func, base, offset.into(), global_type),
ir::GlobalValueData::Load {
base,
offset,
global_type,
readonly,
} => load_addr(inst, func, base, offset, global_type, readonly, isa),
ir::GlobalValueData::Symbol { .. } => symbol(inst, func, gv, isa),
}
}
fn vmctx_addr(inst: ir::Inst, func: &mut ir::Function) {
let vmctx = func
.special_param(ir::ArgumentPurpose::VMContext)
.expect("Missing vmctx parameter");
let result = func.dfg.first_result(inst);
func.dfg.clear_results(inst);
func.dfg.change_to_alias(result, vmctx);
func.layout.remove_inst(inst);
}
fn iadd_imm_addr(
inst: ir::Inst,
func: &mut ir::Function,
base: ir::GlobalValue,
offset: i64,
global_type: ir::Type,
) {
let mut pos = FuncCursor::new(func).at_inst(inst);
let lhs = if let ir::GlobalValueData::VMContext = pos.func.global_values[base] {
pos.func
.special_param(ir::ArgumentPurpose::VMContext)
.expect("Missing vmctx parameter")
} else {
pos.ins().global_value(global_type, base)
};
pos.func.dfg.replace(inst).iadd_imm(lhs, offset);
}
fn load_addr(
inst: ir::Inst,
func: &mut ir::Function,
base: ir::GlobalValue,
offset: ir::immediates::Offset32,
global_type: ir::Type,
readonly: bool,
isa: &dyn TargetIsa,
) {
let ptr_ty = isa.pointer_type();
let mut pos = FuncCursor::new(func).at_inst(inst);
pos.use_srcloc(inst);
let base_addr = if let ir::GlobalValueData::VMContext = pos.func.global_values[base] {
pos.func
.special_param(ir::ArgumentPurpose::VMContext)
.expect("Missing vmctx parameter")
} else {
pos.ins().global_value(ptr_ty, base)
};
let mut mflags = ir::MemFlags::trusted();
if readonly {
mflags.set_readonly();
}
pos.func
.dfg
.replace(inst)
.load(global_type, mflags, base_addr, offset);
}
fn symbol(inst: ir::Inst, func: &mut ir::Function, gv: ir::GlobalValue, isa: &dyn TargetIsa) {
let ptr_ty = isa.pointer_type();
func.dfg.replace(inst).symbol_value(ptr_ty, gv);
}