cranelift_codegen/legalizer/
globalvalue.rs1use crate::cursor::{Cursor, FuncCursor};
7use crate::flowgraph::ControlFlowGraph;
8use crate::ir::{self, InstBuilder};
9use crate::isa::TargetIsa;
10
11pub fn expand_global_value(
13 inst: ir::Inst,
14 func: &mut ir::Function,
15 _cfg: &mut ControlFlowGraph,
16 isa: &dyn TargetIsa,
17) {
18 let gv = match func.dfg[inst] {
20 ir::InstructionData::UnaryGlobalValue {
21 opcode,
22 global_value,
23 } => {
24 debug_assert_eq!(opcode, ir::Opcode::GlobalValue);
25 global_value
26 }
27 _ => panic!("Wanted global_value: {}", func.dfg.display_inst(inst, None)),
28 };
29
30 match func.global_values[gv] {
31 ir::GlobalValueData::VMContext => vmctx_addr(inst, func),
32 ir::GlobalValueData::IAddImm {
33 base,
34 offset,
35 global_type,
36 } => iadd_imm_addr(inst, func, base, offset.into(), global_type),
37 ir::GlobalValueData::Load {
38 base,
39 offset,
40 global_type,
41 readonly,
42 } => load_addr(inst, func, base, offset, global_type, readonly, isa),
43 ir::GlobalValueData::Symbol { .. } => symbol(inst, func, gv, isa),
44 }
45}
46
47fn vmctx_addr(inst: ir::Inst, func: &mut ir::Function) {
49 let vmctx = func
51 .special_param(ir::ArgumentPurpose::VMContext)
52 .expect("Missing vmctx parameter");
53
54 let result = func.dfg.first_result(inst);
56 func.dfg.clear_results(inst);
57 func.dfg.change_to_alias(result, vmctx);
58 func.layout.remove_inst(inst);
59}
60
61fn iadd_imm_addr(
63 inst: ir::Inst,
64 func: &mut ir::Function,
65 base: ir::GlobalValue,
66 offset: i64,
67 global_type: ir::Type,
68) {
69 let mut pos = FuncCursor::new(func).at_inst(inst);
70
71 let lhs = if let ir::GlobalValueData::VMContext = pos.func.global_values[base] {
74 pos.func
75 .special_param(ir::ArgumentPurpose::VMContext)
76 .expect("Missing vmctx parameter")
77 } else {
78 pos.ins().global_value(global_type, base)
79 };
80
81 pos.func.dfg.replace(inst).iadd_imm(lhs, offset);
83}
84
85fn load_addr(
87 inst: ir::Inst,
88 func: &mut ir::Function,
89 base: ir::GlobalValue,
90 offset: ir::immediates::Offset32,
91 global_type: ir::Type,
92 readonly: bool,
93 isa: &dyn TargetIsa,
94) {
95 let ptr_ty = isa.pointer_type();
99 let mut pos = FuncCursor::new(func).at_inst(inst);
100 pos.use_srcloc(inst);
101
102 let base_addr = if let ir::GlobalValueData::VMContext = pos.func.global_values[base] {
105 pos.func
106 .special_param(ir::ArgumentPurpose::VMContext)
107 .expect("Missing vmctx parameter")
108 } else {
109 pos.ins().global_value(ptr_ty, base)
110 };
111
112 let mut mflags = ir::MemFlags::trusted();
114 if readonly {
115 mflags.set_readonly();
116 }
117
118 pos.func
120 .dfg
121 .replace(inst)
122 .load(global_type, mflags, base_addr, offset);
123}
124
125fn symbol(inst: ir::Inst, func: &mut ir::Function, gv: ir::GlobalValue, isa: &dyn TargetIsa) {
127 let ptr_ty = isa.pointer_type();
128 func.dfg.replace(inst).symbol_value(ptr_ty, gv);
129}