1313//! The legalizer does not deal with register allocation constraints. These constraints are derived
1414//! from the encoding recipes, and solved later by the register allocator.
1515
16+ #[ cfg( any( feature = "x86" , feature = "riscv" ) ) ]
1617use crate :: bitset:: BitSet ;
1718use crate :: cursor:: { Cursor , FuncCursor } ;
1819use crate :: flowgraph:: ControlFlowGraph ;
1920use crate :: ir:: types:: { I32 , I64 } ;
2021use crate :: ir:: { self , InstBuilder , MemFlags } ;
2122use crate :: isa:: TargetIsa ;
2223
23- #[ cfg( any(
24- feature = "x86" ,
25- feature = "arm32" ,
26- feature = "arm64" ,
27- feature = "riscv"
28- ) ) ]
24+ #[ cfg( any( feature = "x86" , feature = "riscv" ) ) ]
2925use crate :: predicates;
30- #[ cfg( any(
31- feature = "x86" ,
32- feature = "arm32" ,
33- feature = "arm64" ,
34- feature = "riscv"
35- ) ) ]
26+ #[ cfg( any( feature = "x86" , feature = "riscv" ) ) ]
3627use alloc:: vec:: Vec ;
3728
3829use crate :: timing;
@@ -46,6 +37,7 @@ mod libcall;
4637mod split;
4738mod table;
4839
40+ #[ cfg( any( feature = "x86" , feature = "riscv" ) ) ]
4941use self :: call:: expand_call;
5042use self :: globalvalue:: expand_global_value;
5143use self :: heap:: expand_heap_addr;
@@ -213,49 +205,126 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is
213205/// Perform a simple legalization by expansion of the function, without
214206/// platform-specific transforms.
215207pub fn simple_legalize ( func : & mut ir:: Function , cfg : & mut ControlFlowGraph , isa : & dyn TargetIsa ) {
208+ macro_rules! expand_imm_op {
209+ ( $pos: ident, $inst: ident: $from: ident => $to: ident) => { {
210+ let ( arg, imm) = match $pos. func. dfg[ $inst] {
211+ ir:: InstructionData :: BinaryImm64 {
212+ opcode: _,
213+ arg,
214+ imm,
215+ } => ( arg, imm) ,
216+ _ => panic!(
217+ concat!( "Expected " , stringify!( $from) , ": {}" ) ,
218+ $pos. func. dfg. display_inst( $inst, None )
219+ ) ,
220+ } ;
221+ let ty = $pos. func. dfg. value_type( arg) ;
222+ let imm = $pos. ins( ) . iconst( ty, imm) ;
223+ $pos. func. dfg. replace( $inst) . $to( arg, imm) ;
224+ } } ;
225+
226+ ( $pos: ident, $inst: ident<$ty: ident>: $from: ident => $to: ident) => { {
227+ let ( arg, imm) = match $pos. func. dfg[ $inst] {
228+ ir:: InstructionData :: BinaryImm64 {
229+ opcode: _,
230+ arg,
231+ imm,
232+ } => ( arg, imm) ,
233+ _ => panic!(
234+ concat!( "Expected " , stringify!( $from) , ": {}" ) ,
235+ $pos. func. dfg. display_inst( $inst, None )
236+ ) ,
237+ } ;
238+ let imm = $pos. ins( ) . iconst( $ty, imm) ;
239+ $pos. func. dfg. replace( $inst) . $to( arg, imm) ;
240+ } } ;
241+ }
242+
216243 let mut pos = FuncCursor :: new ( func) ;
217244 let func_begin = pos. position ( ) ;
218245 pos. set_position ( func_begin) ;
219246 while let Some ( _block) = pos. next_block ( ) {
220247 let mut prev_pos = pos. position ( ) ;
221248 while let Some ( inst) = pos. next_inst ( ) {
222- let expanded = match pos. func . dfg [ inst] . opcode ( ) {
223- ir:: Opcode :: BrIcmp
224- | ir:: Opcode :: GlobalValue
225- | ir:: Opcode :: HeapAddr
226- | ir:: Opcode :: StackLoad
227- | ir:: Opcode :: StackStore
228- | ir:: Opcode :: TableAddr
229- | ir:: Opcode :: Trapnz
230- | ir:: Opcode :: Trapz
231- | ir:: Opcode :: ResumableTrapnz
232- | ir:: Opcode :: BandImm
233- | ir:: Opcode :: BorImm
234- | ir:: Opcode :: BxorImm
235- | ir:: Opcode :: IaddImm
236- | ir:: Opcode :: IfcmpImm
237- | ir:: Opcode :: ImulImm
238- | ir:: Opcode :: IrsubImm
239- | ir:: Opcode :: IshlImm
240- | ir:: Opcode :: RotlImm
241- | ir:: Opcode :: RotrImm
242- | ir:: Opcode :: SdivImm
243- | ir:: Opcode :: SremImm
244- | ir:: Opcode :: SshrImm
245- | ir:: Opcode :: UdivImm
246- | ir:: Opcode :: UremImm
247- | ir:: Opcode :: UshrImm
248- | ir:: Opcode :: IcmpImm => expand ( inst, & mut pos. func , cfg, isa) ,
249- _ => false ,
249+ match pos. func . dfg [ inst] . opcode ( ) {
250+ // control flow
251+ ir:: Opcode :: BrIcmp => expand_br_icmp ( inst, & mut pos. func , cfg, isa) ,
252+ ir:: Opcode :: Trapnz | ir:: Opcode :: Trapz | ir:: Opcode :: ResumableTrapnz => {
253+ expand_cond_trap ( inst, & mut pos. func , cfg, isa) ;
254+ }
255+
256+ // memory and constants
257+ ir:: Opcode :: GlobalValue => expand_global_value ( inst, & mut pos. func , cfg, isa) ,
258+ ir:: Opcode :: HeapAddr => expand_heap_addr ( inst, & mut pos. func , cfg, isa) ,
259+ ir:: Opcode :: StackLoad => expand_stack_load ( inst, & mut pos. func , cfg, isa) ,
260+ ir:: Opcode :: StackStore => expand_stack_store ( inst, & mut pos. func , cfg, isa) ,
261+ ir:: Opcode :: TableAddr => expand_table_addr ( inst, & mut pos. func , cfg, isa) ,
262+
263+ // bitops
264+ ir:: Opcode :: BandImm => expand_imm_op ! ( pos, inst: band_imm => band) ,
265+ ir:: Opcode :: BorImm => expand_imm_op ! ( pos, inst: bor_imm => bor) ,
266+ ir:: Opcode :: BxorImm => expand_imm_op ! ( pos, inst: bxor_imm => bxor) ,
267+ ir:: Opcode :: IaddImm => expand_imm_op ! ( pos, inst: iadd_imm => iadd) ,
268+
269+ // bitshifting
270+ ir:: Opcode :: IshlImm => expand_imm_op ! ( pos, inst<I32 >: ishl_imm => ishl) ,
271+ ir:: Opcode :: RotlImm => expand_imm_op ! ( pos, inst<I32 >: rotl_imm => rotl) ,
272+ ir:: Opcode :: RotrImm => expand_imm_op ! ( pos, inst<I32 >: rotr_imm => rotr) ,
273+ ir:: Opcode :: SshrImm => expand_imm_op ! ( pos, inst<I32 >: sshr_imm => sshr) ,
274+ ir:: Opcode :: UshrImm => expand_imm_op ! ( pos, inst<I32 >: ushr_imm => ushr) ,
275+
276+ // math
277+ ir:: Opcode :: IrsubImm => {
278+ let ( arg, imm) = match pos. func . dfg [ inst] {
279+ ir:: InstructionData :: BinaryImm64 {
280+ opcode : _,
281+ arg,
282+ imm,
283+ } => ( arg, imm) ,
284+ _ => panic ! (
285+ "Expected irsub_imm: {}" ,
286+ pos. func. dfg. display_inst( inst, None )
287+ ) ,
288+ } ;
289+ let ty = pos. func . dfg . value_type ( arg) ;
290+ let imm = pos. ins ( ) . iconst ( ty, imm) ;
291+ pos. func . dfg . replace ( inst) . isub ( imm, arg) ; // note: arg order reversed
292+ }
293+ ir:: Opcode :: ImulImm => expand_imm_op ! ( pos, inst: imul_imm => imul) ,
294+ ir:: Opcode :: SdivImm => expand_imm_op ! ( pos, inst: sdiv_imm => sdiv) ,
295+ ir:: Opcode :: SremImm => expand_imm_op ! ( pos, inst: srem_imm => srem) ,
296+ ir:: Opcode :: UdivImm => expand_imm_op ! ( pos, inst: udiv_imm => udiv) ,
297+ ir:: Opcode :: UremImm => expand_imm_op ! ( pos, inst: urem_imm => urem) ,
298+
299+ // comparisons
300+ ir:: Opcode :: IfcmpImm => expand_imm_op ! ( pos, inst: ifcmp_imm => ifcmp) ,
301+ ir:: Opcode :: IcmpImm => {
302+ let ( cc, x, y) = match pos. func . dfg [ inst] {
303+ ir:: InstructionData :: IntCompareImm {
304+ opcode : _,
305+ cond,
306+ arg,
307+ imm,
308+ } => ( cond, arg, imm) ,
309+ _ => panic ! (
310+ "Expected ircmp_imm: {}" ,
311+ pos. func. dfg. display_inst( inst, None )
312+ ) ,
313+ } ;
314+ let ty = pos. func . dfg . value_type ( x) ;
315+ let y = pos. ins ( ) . iconst ( ty, y) ;
316+ pos. func . dfg . replace ( inst) . icmp ( cc, x, y) ;
317+ }
318+
319+ _ => {
320+ prev_pos = pos. position ( ) ;
321+ continue ;
322+ }
250323 } ;
251324
252- if expanded {
253- // Legalization implementations require fixpoint loop
254- // here. TODO: fix this.
255- pos. set_position ( prev_pos) ;
256- } else {
257- prev_pos = pos. position ( ) ;
258- }
325+ // Legalization implementations require fixpoint loop here.
326+ // TODO: fix this.
327+ pos. set_position ( prev_pos) ;
259328 }
260329 }
261330}
0 commit comments