cranelift_codegen/legalizer/
globalvalue.rs1use super::WalkCommand;
7use crate::cursor::{Cursor, FuncCursor};
8use crate::ir::{self, InstBuilder, pcc::Fact};
9use crate::isa::TargetIsa;
10
11pub fn expand_global_value(
13 inst: ir::Inst,
14 func: &mut ir::Function,
15 isa: &dyn TargetIsa,
16 global_value: ir::GlobalValue,
17) -> WalkCommand {
18 crate::trace!(
19 "expanding global value: {:?}: {}",
20 inst,
21 func.dfg.display_inst(inst)
22 );
23
24 match func.global_values[global_value] {
25 ir::GlobalValueData::VMContext => vmctx_addr(global_value, inst, func),
26 ir::GlobalValueData::IAddImm {
27 base,
28 offset,
29 global_type,
30 } => iadd_imm_addr(inst, func, base, offset.into(), global_type),
31 ir::GlobalValueData::Load {
32 base,
33 offset,
34 global_type,
35 flags,
36 } => load_addr(inst, func, base, offset, global_type, flags, isa),
37 ir::GlobalValueData::Symbol { tls, .. } => symbol(inst, func, global_value, isa, tls),
38 ir::GlobalValueData::DynScaleTargetConst { vector_type } => {
39 const_vector_scale(inst, func, vector_type, isa)
40 }
41 }
42}
43
44fn const_vector_scale(
45 inst: ir::Inst,
46 func: &mut ir::Function,
47 ty: ir::Type,
48 isa: &dyn TargetIsa,
49) -> WalkCommand {
50 assert!(ty.bytes() <= 16);
51
52 let base_bytes = std::cmp::max(ty.bytes(), 16);
54 let scale = (isa.dynamic_vector_bytes(ty) / base_bytes) as i64;
55 assert!(scale > 0);
56 let pos = FuncCursor::new(func).at_inst(inst);
57 pos.func.dfg.replace(inst).iconst(isa.pointer_type(), scale);
58
59 WalkCommand::Continue
60}
61
62fn vmctx_addr(
64 global_value: ir::GlobalValue,
65 inst: ir::Inst,
66 func: &mut ir::Function,
67) -> WalkCommand {
68 let vmctx = func
70 .special_param(ir::ArgumentPurpose::VMContext)
71 .expect("Missing vmctx parameter");
72
73 let result = func.dfg.first_result(inst);
75 func.dfg.clear_results(inst);
76 func.dfg.change_to_alias(result, vmctx);
77 func.layout.remove_inst(inst);
78
79 if let Some(fact) = &func.global_value_facts[global_value] {
82 if func.dfg.facts[vmctx].is_none() {
83 let fact = fact.clone();
84 func.dfg.facts[vmctx] = Some(fact);
85 }
86 }
87
88 WalkCommand::Revisit
93}
94
95fn iadd_imm_addr(
97 inst: ir::Inst,
98 func: &mut ir::Function,
99 base: ir::GlobalValue,
100 offset: i64,
101 global_type: ir::Type,
102) -> WalkCommand {
103 let mut pos = FuncCursor::new(func).at_inst(inst);
104
105 let lhs = pos.ins().global_value(global_type, base);
107 if let Some(fact) = &pos.func.global_value_facts[base] {
108 pos.func.dfg.facts[lhs] = Some(fact.clone());
109 }
110
111 let constant = pos.ins().iconst(global_type, offset);
114 if pos.func.global_value_facts[base].is_some() {
115 let bits = u16::try_from(global_type.bits()).unwrap();
116 let unsigned_offset = offset as u64; pos.func.dfg.facts[constant] = Some(Fact::constant(bits, unsigned_offset));
118 }
119
120 pos.func.dfg.replace(inst).iadd(lhs, constant);
122
123 WalkCommand::Revisit
125}
126
127fn load_addr(
129 inst: ir::Inst,
130 func: &mut ir::Function,
131 base: ir::GlobalValue,
132 offset: ir::immediates::Offset32,
133 global_type: ir::Type,
134 flags: ir::MemFlags,
135 isa: &dyn TargetIsa,
136) -> WalkCommand {
137 let ptr_ty = isa.pointer_type();
141
142 let mut pos = FuncCursor::new(func).at_inst(inst);
143 pos.use_srcloc(inst);
144
145 let base_addr = pos.ins().global_value(ptr_ty, base);
147 if let Some(fact) = &pos.func.global_value_facts[base] {
148 pos.func.dfg.facts[base_addr] = Some(fact.clone());
149 }
150
151 pos.func
153 .dfg
154 .replace(inst)
155 .load(global_type, flags, base_addr, offset);
156
157 WalkCommand::Revisit
159}
160
161fn symbol(
163 inst: ir::Inst,
164 func: &mut ir::Function,
165 gv: ir::GlobalValue,
166 isa: &dyn TargetIsa,
167 tls: bool,
168) -> WalkCommand {
169 let ptr_ty = isa.pointer_type();
170
171 if tls {
172 func.dfg.replace(inst).tls_value(ptr_ty, gv);
173 } else {
174 func.dfg.replace(inst).symbol_value(ptr_ty, gv);
175 }
176
177 WalkCommand::Continue
178}