cranelift_codegen/legalizer/
mod.rs1use crate::cursor::{Cursor, FuncCursor};
17use crate::ir::immediates::Imm64;
18use crate::ir::types::{self, I128, I64};
19use crate::ir::{self, InstBuilder, InstructionData, MemFlags, Value};
20use crate::isa::TargetIsa;
21use crate::trace;
22
23mod globalvalue;
24
25use self::globalvalue::expand_global_value;
26
27fn imm_const(pos: &mut FuncCursor, arg: Value, imm: Imm64, is_signed: bool) -> Value {
28 let ty = pos.func.dfg.value_type(arg);
29 match (ty, is_signed) {
30 (I128, true) => {
31 let imm = pos.ins().iconst(I64, imm);
32 pos.ins().sextend(I128, imm)
33 }
34 (I128, false) => {
35 let imm = pos.ins().iconst(I64, imm);
36 pos.ins().uextend(I128, imm)
37 }
38 _ => {
39 let bits = imm.bits();
40 let unsigned = match ty.lane_type() {
41 types::I8 => bits as u8 as i64,
42 types::I16 => bits as u16 as i64,
43 types::I32 => bits as u32 as i64,
44 types::I64 => bits,
45 _ => unreachable!(),
46 };
47 pos.ins().iconst(ty.lane_type(), unsigned)
48 }
49 }
50}
51
52pub fn simple_legalize(func: &mut ir::Function, isa: &dyn TargetIsa) {
55 trace!("Pre-legalization function:\n{}", func.display());
56
57 let mut pos = FuncCursor::new(func);
58 let func_begin = pos.position();
59 pos.set_position(func_begin);
60 while let Some(_block) = pos.next_block() {
61 let mut prev_pos = pos.position();
62 while let Some(inst) = pos.next_inst() {
63 match pos.func.dfg.insts[inst] {
64 InstructionData::UnaryGlobalValue {
66 opcode: ir::Opcode::GlobalValue,
67 global_value,
68 } => expand_global_value(inst, &mut pos.func, isa, global_value),
69 InstructionData::StackLoad {
70 opcode: ir::Opcode::StackLoad,
71 stack_slot,
72 offset,
73 } => {
74 let ty = pos.func.dfg.value_type(pos.func.dfg.first_result(inst));
75 let addr_ty = isa.pointer_type();
76
77 let mut pos = FuncCursor::new(pos.func).at_inst(inst);
78 pos.use_srcloc(inst);
79
80 let addr = pos.ins().stack_addr(addr_ty, stack_slot, offset);
81
82 let mut mflags = MemFlags::new();
85 mflags.set_notrap();
86 pos.func.dfg.replace(inst).load(ty, mflags, addr, 0);
87 }
88 InstructionData::StackStore {
89 opcode: ir::Opcode::StackStore,
90 arg,
91 stack_slot,
92 offset,
93 } => {
94 let addr_ty = isa.pointer_type();
95
96 let mut pos = FuncCursor::new(pos.func).at_inst(inst);
97 pos.use_srcloc(inst);
98
99 let addr = pos.ins().stack_addr(addr_ty, stack_slot, offset);
100
101 let mut mflags = MemFlags::new();
104 mflags.set_notrap();
105 pos.func.dfg.replace(inst).store(mflags, arg, addr, 0);
106 }
107 InstructionData::DynamicStackLoad {
108 opcode: ir::Opcode::DynamicStackLoad,
109 dynamic_stack_slot,
110 } => {
111 let ty = pos.func.dfg.value_type(pos.func.dfg.first_result(inst));
112 assert!(ty.is_dynamic_vector());
113 let addr_ty = isa.pointer_type();
114
115 let mut pos = FuncCursor::new(pos.func).at_inst(inst);
116 pos.use_srcloc(inst);
117
118 let addr = pos.ins().dynamic_stack_addr(addr_ty, dynamic_stack_slot);
119
120 let mflags = MemFlags::trusted();
122 pos.func.dfg.replace(inst).load(ty, mflags, addr, 0);
123 }
124 InstructionData::DynamicStackStore {
125 opcode: ir::Opcode::DynamicStackStore,
126 arg,
127 dynamic_stack_slot,
128 } => {
129 pos.use_srcloc(inst);
130 let addr_ty = isa.pointer_type();
131 let vector_ty = pos.func.dfg.value_type(arg);
132 assert!(vector_ty.is_dynamic_vector());
133
134 let addr = pos.ins().dynamic_stack_addr(addr_ty, dynamic_stack_slot);
135
136 let mut mflags = MemFlags::new();
137 mflags.set_notrap();
139 mflags.set_aligned();
140 pos.func.dfg.replace(inst).store(mflags, arg, addr, 0);
141 }
142
143 InstructionData::BinaryImm64 { opcode, arg, imm } => {
144 let is_signed = match opcode {
145 ir::Opcode::IaddImm
146 | ir::Opcode::IrsubImm
147 | ir::Opcode::ImulImm
148 | ir::Opcode::SdivImm
149 | ir::Opcode::SremImm => true,
150 _ => false,
151 };
152
153 let imm = imm_const(&mut pos, arg, imm, is_signed);
154 let replace = pos.func.dfg.replace(inst);
155 match opcode {
156 ir::Opcode::BandImm => {
158 replace.band(arg, imm);
159 }
160 ir::Opcode::BorImm => {
161 replace.bor(arg, imm);
162 }
163 ir::Opcode::BxorImm => {
164 replace.bxor(arg, imm);
165 }
166 ir::Opcode::IshlImm => {
168 replace.ishl(arg, imm);
169 }
170 ir::Opcode::RotlImm => {
171 replace.rotl(arg, imm);
172 }
173 ir::Opcode::RotrImm => {
174 replace.rotr(arg, imm);
175 }
176 ir::Opcode::SshrImm => {
177 replace.sshr(arg, imm);
178 }
179 ir::Opcode::UshrImm => {
180 replace.ushr(arg, imm);
181 }
182 ir::Opcode::IaddImm => {
184 replace.iadd(arg, imm);
185 }
186 ir::Opcode::IrsubImm => {
187 replace.isub(imm, arg);
189 }
190 ir::Opcode::ImulImm => {
191 replace.imul(arg, imm);
192 }
193 ir::Opcode::SdivImm => {
194 replace.sdiv(arg, imm);
195 }
196 ir::Opcode::SremImm => {
197 replace.srem(arg, imm);
198 }
199 ir::Opcode::UdivImm => {
200 replace.udiv(arg, imm);
201 }
202 ir::Opcode::UremImm => {
203 replace.urem(arg, imm);
204 }
205 _ => prev_pos = pos.position(),
206 };
207 }
208
209 InstructionData::IntCompareImm {
211 opcode: ir::Opcode::IcmpImm,
212 cond,
213 arg,
214 imm,
215 } => {
216 let imm = imm_const(&mut pos, arg, imm, true);
217 pos.func.dfg.replace(inst).icmp(cond, arg, imm);
218 }
219
220 InstructionData::Binary { opcode, args } => {
225 match opcode {
226 ir::Opcode::BandNot => {
227 let neg = pos.ins().bnot(args[1]);
228 pos.func.dfg.replace(inst).band(args[0], neg);
229 }
230 ir::Opcode::BorNot => {
231 let neg = pos.ins().bnot(args[1]);
232 pos.func.dfg.replace(inst).bor(args[0], neg);
233 }
234 ir::Opcode::BxorNot => {
235 let neg = pos.ins().bnot(args[1]);
236 pos.func.dfg.replace(inst).bxor(args[0], neg);
237 }
238 _ => prev_pos = pos.position(),
239 };
240 }
241
242 _ => {
243 prev_pos = pos.position();
244 continue;
245 }
246 }
247
248 pos.set_position(prev_pos);
251 }
252 }
253
254 trace!("Post-legalization function:\n{}", func.display());
255}