cranelift_codegen/legalizer/
globalvalue.rs1use crate::cursor::{Cursor, FuncCursor};
7use crate::ir::{self, pcc::Fact, InstBuilder};
8use crate::isa::TargetIsa;
9
10pub fn expand_global_value(
12 inst: ir::Inst,
13 func: &mut ir::Function,
14 isa: &dyn TargetIsa,
15 global_value: ir::GlobalValue,
16) {
17 crate::trace!(
18 "expanding global value: {:?}: {}",
19 inst,
20 func.dfg.display_inst(inst)
21 );
22
23 match func.global_values[global_value] {
24 ir::GlobalValueData::VMContext => vmctx_addr(global_value, inst, func),
25 ir::GlobalValueData::IAddImm {
26 base,
27 offset,
28 global_type,
29 } => iadd_imm_addr(inst, func, base, offset.into(), global_type),
30 ir::GlobalValueData::Load {
31 base,
32 offset,
33 global_type,
34 flags,
35 } => load_addr(inst, func, base, offset, global_type, flags, isa),
36 ir::GlobalValueData::Symbol { tls, .. } => symbol(inst, func, global_value, isa, tls),
37 ir::GlobalValueData::DynScaleTargetConst { vector_type } => {
38 const_vector_scale(inst, func, vector_type, isa)
39 }
40 }
41}
42
43fn const_vector_scale(inst: ir::Inst, func: &mut ir::Function, ty: ir::Type, isa: &dyn TargetIsa) {
44 assert!(ty.bytes() <= 16);
45
46 let base_bytes = std::cmp::max(ty.bytes(), 16);
48 let scale = (isa.dynamic_vector_bytes(ty) / base_bytes) as i64;
49 assert!(scale > 0);
50 let pos = FuncCursor::new(func).at_inst(inst);
51 pos.func.dfg.replace(inst).iconst(isa.pointer_type(), scale);
52}
53
54fn vmctx_addr(global_value: ir::GlobalValue, inst: ir::Inst, func: &mut ir::Function) {
56 let vmctx = func
58 .special_param(ir::ArgumentPurpose::VMContext)
59 .expect("Missing vmctx parameter");
60
61 let result = func.dfg.first_result(inst);
63 func.dfg.clear_results(inst);
64 func.dfg.change_to_alias(result, vmctx);
65 func.layout.remove_inst(inst);
66
67 if let Some(fact) = &func.global_value_facts[global_value] {
70 if func.dfg.facts[vmctx].is_none() {
71 let fact = fact.clone();
72 func.dfg.facts[vmctx] = Some(fact);
73 }
74 }
75}
76
77fn iadd_imm_addr(
79 inst: ir::Inst,
80 func: &mut ir::Function,
81 base: ir::GlobalValue,
82 offset: i64,
83 global_type: ir::Type,
84) {
85 let mut pos = FuncCursor::new(func).at_inst(inst);
86
87 let lhs = pos.ins().global_value(global_type, base);
89 if let Some(fact) = &pos.func.global_value_facts[base] {
90 pos.func.dfg.facts[lhs] = Some(fact.clone());
91 }
92
93 let constant = pos.ins().iconst(global_type, offset);
96 if pos.func.global_value_facts[base].is_some() {
97 let bits = u16::try_from(global_type.bits()).unwrap();
98 let unsigned_offset = offset as u64; pos.func.dfg.facts[constant] = Some(Fact::constant(bits, unsigned_offset));
100 }
101
102 pos.func.dfg.replace(inst).iadd(lhs, constant);
104}
105
106fn load_addr(
108 inst: ir::Inst,
109 func: &mut ir::Function,
110 base: ir::GlobalValue,
111 offset: ir::immediates::Offset32,
112 global_type: ir::Type,
113 flags: ir::MemFlags,
114 isa: &dyn TargetIsa,
115) {
116 let ptr_ty = isa.pointer_type();
120 let mut pos = FuncCursor::new(func).at_inst(inst);
121 pos.use_srcloc(inst);
122
123 let base_addr = pos.ins().global_value(ptr_ty, base);
125 if let Some(fact) = &pos.func.global_value_facts[base] {
126 pos.func.dfg.facts[base_addr] = Some(fact.clone());
127 }
128
129 pos.func
131 .dfg
132 .replace(inst)
133 .load(global_type, flags, base_addr, offset);
134}
135
136fn symbol(
138 inst: ir::Inst,
139 func: &mut ir::Function,
140 gv: ir::GlobalValue,
141 isa: &dyn TargetIsa,
142 tls: bool,
143) {
144 let ptr_ty = isa.pointer_type();
145
146 if tls {
147 func.dfg.replace(inst).tls_value(ptr_ty, gv);
148 } else {
149 func.dfg.replace(inst).symbol_value(ptr_ty, gv);
150 }
151}