@@ -3399,15 +3399,18 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
33993399 . map ( |operand| operand. id_ref_any ( ) )
34003400 . collect :: < Option < SmallVec < [ _ ; 4 ] > > > ( ) ?;
34013401
3402+ let const_as_u32 = |id| match self . builder . lookup_const_by_id ( id) ? {
3403+ SpirvConst :: Scalar ( x) => u32:: try_from ( x) . ok ( ) ,
3404+ _ => None ,
3405+ } ;
3406+
34023407 // Decode the instruction into one of our `Inst`s.
34033408 Some (
34043409 match ( inst. class . opcode , inst. result_id , & id_operands[ ..] ) {
34053410 ( Op :: Bitcast , Some ( r) , & [ x] ) => Inst :: Bitcast ( r, x) ,
34063411 ( Op :: InBoundsAccessChain , Some ( r) , & [ p, i] ) => {
3407- if let Some ( SpirvConst :: Scalar ( i) ) =
3408- self . builder . lookup_const_by_id ( i)
3409- {
3410- Inst :: InBoundsAccessChain ( r, p, i as u32 )
3412+ if let Some ( i) = const_as_u32 ( i) {
3413+ Inst :: InBoundsAccessChain ( r, p, i)
34113414 } else {
34123415 Inst :: Unsupported ( inst. class . opcode )
34133416 }
@@ -3494,47 +3497,65 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
34943497 if rt_args_count > 0 {
34953498 let rt_args_array_ptr_id = rt_args_slice_ptr_id. unwrap ( ) ;
34963499
3497- // Each runtime argument has 4 instructions to call one of
3500+ // Each runtime argument has A instructions to call one of
34983501 // the `fmt::rt::Argument::new_*` functions (and temporarily
3499- // store its result), and 4 instructions to copy it into
3500- // the appropriate slot in the array. The groups of 4 and 4
3501- // instructions, for all runtime args, are each separate.
3502- let copies_to_rt_args_array =
3503- try_rev_take ( rt_args_count * 4 ) . ok_or_else ( || {
3502+ // store its result), and B instructions to copy it into
3503+ // the appropriate slot in the array. The groups of A and B
3504+ // instructions, for all runtime args, are each separate,
3505+ // so the B×N later instructions are all processed first,
3506+ // before moving (backwards) to the A×N earlier instructions.
3507+
3508+ let rev_copies_to_rt_args_array_src_ptrs: SmallVec < [ _ ; 4 ] > =
3509+ ( 0 ..rt_args_count) . rev ( ) . map ( |rt_arg_idx| {
3510+ let copy_to_rt_args_array_insts = try_rev_take ( 4 ) . ok_or_else ( || {
35043511 FormatArgsNotRecognized (
3505- "[fmt::rt::Argument; N] copies : ran out of instructions" . into ( ) ,
3512+ "[fmt::rt::Argument; N] copy : ran out of instructions" . into ( ) ,
35063513 )
35073514 } ) ?;
3508- let copies_to_rt_args_array = copies_to_rt_args_array. chunks ( 4 ) ;
3509- let rt_arg_new_calls = try_rev_take ( rt_args_count * 4 ) . ok_or_else ( || {
3510- FormatArgsNotRecognized (
3511- "fmt::rt::Argument::new calls: ran out of instructions" . into ( ) ,
3512- )
3513- } ) ?;
3514- let rt_arg_new_calls = rt_arg_new_calls. chunks ( 4 ) ;
3515+ match copy_to_rt_args_array_insts[ ..] {
3516+ [
3517+ Inst :: InBoundsAccessChain ( array_slot, array_base, array_idx) ,
3518+ Inst :: InBoundsAccessChain ( dst_field_ptr, dst_base_ptr, 0 ) ,
3519+ Inst :: InBoundsAccessChain ( src_field_ptr, src_base_ptr, 0 ) ,
3520+ Inst :: CopyMemory ( copy_dst, copy_src) ,
3521+ ] if array_base == rt_args_array_ptr_id
3522+ && array_idx as usize == rt_arg_idx
3523+ && dst_base_ptr == array_slot
3524+ && ( copy_dst, copy_src) == ( dst_field_ptr, src_field_ptr) =>
3525+ {
3526+ Ok ( src_base_ptr)
3527+ }
3528+ _ => {
3529+ Err ( FormatArgsNotRecognized ( format ! (
3530+ "[fmt::rt::Argument; N] copy sequence ({copy_to_rt_args_array_insts:?})"
3531+ ) ) )
3532+ }
3533+ }
3534+ } ) . collect :: < Result < _ , _ > > ( ) ?;
35153535
3516- for ( rt_arg_idx, ( rt_arg_new_call_insts, copy_to_rt_args_array_insts) ) in
3517- rt_arg_new_calls. zip ( copies_to_rt_args_array) . enumerate ( )
3518- {
3519- let call_ret_slot_ptr = match rt_arg_new_call_insts[ ..] {
3536+ let rev_ref_arg_ids_with_ty_and_spec = ( rev_copies_to_rt_args_array_src_ptrs
3537+ . into_iter ( ) )
3538+ . map ( |copy_to_rt_args_array_src_ptr| {
3539+ let rt_arg_new_call_insts = try_rev_take ( 4 ) . ok_or_else ( || {
3540+ FormatArgsNotRecognized (
3541+ "fmt::rt::Argument::new call: ran out of instructions" . into ( ) ,
3542+ )
3543+ } ) ?;
3544+ match rt_arg_new_call_insts[ ..] {
35203545 [
35213546 Inst :: Call ( call_ret_id, callee_id, ref call_args) ,
35223547 Inst :: InBoundsAccessChain ( tmp_slot_field_ptr, tmp_slot_ptr, 0 ) ,
35233548 Inst :: CompositeExtract ( field, wrapper_newtype, 0 ) ,
35243549 Inst :: Store ( st_dst_ptr, st_val) ,
35253550 ] if wrapper_newtype == call_ret_id
3551+ && tmp_slot_ptr == copy_to_rt_args_array_src_ptr
35263552 && ( st_dst_ptr, st_val) == ( tmp_slot_field_ptr, field) =>
35273553 {
35283554 self . fmt_rt_arg_new_fn_ids_to_ty_and_spec
35293555 . borrow ( )
35303556 . get ( & callee_id)
35313557 . and_then ( |& ( ty, spec) | match call_args[ ..] {
3532- [ x] => {
3533- decoded_format_args
3534- . ref_arg_ids_with_ty_and_spec
3535- . push ( ( x, ty, spec) ) ;
3536- Some ( tmp_slot_ptr)
3537- }
3558+ [ x] => Some ( ( x, ty, spec) ) ,
35383559 _ => None ,
35393560 } )
35403561 }
@@ -3544,26 +3565,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
35443565 FormatArgsNotRecognized ( format ! (
35453566 "fmt::rt::Argument::new call sequence ({rt_arg_new_call_insts:?})"
35463567 ) )
3547- } ) ?;
3568+ } )
3569+ } )
3570+ . collect :: < Result < _ , _ > > ( ) ?;
35483571
3549- match copy_to_rt_args_array_insts[ ..] {
3550- [
3551- Inst :: InBoundsAccessChain ( array_slot, array_base, array_idx) ,
3552- Inst :: InBoundsAccessChain ( dst_field_ptr, dst_base_ptr, 0 ) ,
3553- Inst :: InBoundsAccessChain ( src_field_ptr, src_base_ptr, 0 ) ,
3554- Inst :: CopyMemory ( copy_dst, copy_src) ,
3555- ] if array_base == rt_args_array_ptr_id
3556- && array_idx as usize == rt_arg_idx
3557- && dst_base_ptr == array_slot
3558- && src_base_ptr == call_ret_slot_ptr
3559- && ( copy_dst, copy_src) == ( dst_field_ptr, src_field_ptr) => { }
3560- _ => {
3561- return Err ( FormatArgsNotRecognized ( format ! (
3562- "[fmt::rt::Argument; N] copies sequence ({copy_to_rt_args_array_insts:?})"
3563- ) ) ) ;
3564- }
3565- }
3566- }
3572+ decoded_format_args. ref_arg_ids_with_ty_and_spec =
3573+ rev_ref_arg_ids_with_ty_and_spec;
3574+ decoded_format_args. ref_arg_ids_with_ty_and_spec . reverse ( ) ;
35673575 }
35683576
35693577 // If the `pieces: &[&str]` slice needs a bitcast, it'll be here.
0 commit comments