@@ -3399,15 +3399,18 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
3399
3399
. map ( |operand| operand. id_ref_any ( ) )
3400
3400
. collect :: < Option < SmallVec < [ _ ; 4 ] > > > ( ) ?;
3401
3401
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
+
3402
3407
// Decode the instruction into one of our `Inst`s.
3403
3408
Some (
3404
3409
match ( inst. class . opcode , inst. result_id , & id_operands[ ..] ) {
3405
3410
( Op :: Bitcast , Some ( r) , & [ x] ) => Inst :: Bitcast ( r, x) ,
3406
3411
( 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)
3411
3414
} else {
3412
3415
Inst :: Unsupported ( inst. class . opcode )
3413
3416
}
@@ -3494,47 +3497,65 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
3494
3497
if rt_args_count > 0 {
3495
3498
let rt_args_array_ptr_id = rt_args_slice_ptr_id. unwrap ( ) ;
3496
3499
3497
- // Each runtime argument has 4 instructions to call one of
3500
+ // Each runtime argument has A instructions to call one of
3498
3501
// 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 ( || {
3504
3511
FormatArgsNotRecognized (
3505
- "[fmt::rt::Argument; N] copies : ran out of instructions" . into ( ) ,
3512
+ "[fmt::rt::Argument; N] copy : ran out of instructions" . into ( ) ,
3506
3513
)
3507
3514
} ) ?;
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 < _ , _ > > ( ) ?;
3515
3535
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[ ..] {
3520
3545
[
3521
3546
Inst :: Call ( call_ret_id, callee_id, ref call_args) ,
3522
3547
Inst :: InBoundsAccessChain ( tmp_slot_field_ptr, tmp_slot_ptr, 0 ) ,
3523
3548
Inst :: CompositeExtract ( field, wrapper_newtype, 0 ) ,
3524
3549
Inst :: Store ( st_dst_ptr, st_val) ,
3525
3550
] if wrapper_newtype == call_ret_id
3551
+ && tmp_slot_ptr == copy_to_rt_args_array_src_ptr
3526
3552
&& ( st_dst_ptr, st_val) == ( tmp_slot_field_ptr, field) =>
3527
3553
{
3528
3554
self . fmt_rt_arg_new_fn_ids_to_ty_and_spec
3529
3555
. borrow ( )
3530
3556
. get ( & callee_id)
3531
3557
. 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) ) ,
3538
3559
_ => None ,
3539
3560
} )
3540
3561
}
@@ -3544,26 +3565,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
3544
3565
FormatArgsNotRecognized ( format ! (
3545
3566
"fmt::rt::Argument::new call sequence ({rt_arg_new_call_insts:?})"
3546
3567
) )
3547
- } ) ?;
3568
+ } )
3569
+ } )
3570
+ . collect :: < Result < _ , _ > > ( ) ?;
3548
3571
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 ( ) ;
3567
3575
}
3568
3576
3569
3577
// If the `pieces: &[&str]` slice needs a bitcast, it'll be here.
0 commit comments