@@ -573,43 +573,30 @@ pub(crate) fn tableswitch(
573573 program_counter : usize ,
574574 table_switch : & TableSwitch ,
575575) -> Result < ( ) > {
576- // TODO: evaluate if the table switch can be optimized to a jump table.
577576 let index = stack. pop ( ) ?;
578- let block_arguments = stack. as_block_arguments ( ) ;
579- let stack_types = stack. to_type_vec ( function_builder) ;
577+ // Create a Switch for efficient jump table generation; Cranelift will optimize it to use
578+ // branches, jump tables, or a combination of both
579+ let mut switch = Switch :: new ( ) ;
580580
581581 for ( offset_index, & offset) in table_switch. offsets . iter ( ) . enumerate ( ) {
582- let else_block = function_builder. create_block ( ) ;
583- append_block_params ( function_builder, else_block, & stack_types) ;
584-
585- // PC = start of tableswitch + offset (signed arithmetic)
586- let target_address = usize:: try_from ( i32:: try_from ( program_counter) ?. wrapping_add ( offset) ) ?;
587- let block = * blocks
582+ let target_address =
583+ usize:: try_from ( i32:: try_from ( program_counter) ?. saturating_add ( offset) ) ?;
584+ let target_block = * blocks
588585 . get ( & target_address)
589586 . ok_or_else ( || InvalidBlockAddress ( target_address) ) ?;
590- let offset_value = i64:: from ( table_switch. low ) . saturating_add ( i64:: try_from ( offset_index) ?) ;
591- let block_address = function_builder. ins ( ) . iconst ( types:: I32 , offset_value) ;
592- let condition_value = function_builder
593- . ins ( )
594- . icmp ( IntCC :: Equal , index, block_address) ;
595- function_builder. ins ( ) . brif (
596- condition_value,
597- block,
598- & block_arguments,
599- else_block,
600- & block_arguments,
601- ) ;
602- function_builder. switch_to_block ( else_block) ;
587+
588+ let case_value = i64:: from ( table_switch. low ) . saturating_add ( i64:: try_from ( offset_index) ?) ;
589+ let case_value = u128:: try_from ( case_value) ?;
590+ switch. set_entry ( case_value, target_block) ;
603591 }
604592
605- // PC = start of tableswitch + default (signed arithmetic)
606593 let default_address =
607- usize:: try_from ( i32:: try_from ( program_counter) ?. wrapping_add ( table_switch. default ) ) ?;
608- let block = blocks
594+ usize:: try_from ( i32:: try_from ( program_counter) ?. saturating_add ( table_switch. default ) ) ?;
595+ let default_block = * blocks
609596 . get ( & default_address)
610597 . ok_or_else ( || InvalidBlockAddress ( default_address) ) ?;
611- let block_arguments = stack . as_block_arguments ( ) ;
612- function_builder . ins ( ) . jump ( * block , & block_arguments ) ;
598+
599+ switch . emit ( function_builder , index , default_block ) ;
613600 stack. reset ( function_builder) ?;
614601 Ok ( ( ) )
615602}
0 commit comments