@@ -3510,47 +3510,65 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
3510
3510
if rt_args_count > 0 {
3511
3511
let rt_args_array_ptr_id = rt_args_slice_ptr_id. unwrap ( ) ;
3512
3512
3513
- // Each runtime argument has 4 instructions to call one of
3513
+ // Each runtime argument has A instructions to call one of
3514
3514
// the `fmt::rt::Argument::new_*` functions (and temporarily
3515
- // store its result), and 4 instructions to copy it into
3516
- // the appropriate slot in the array. The groups of 4 and 4
3517
- // instructions, for all runtime args, are each separate.
3518
- let copies_to_rt_args_array =
3519
- try_rev_take ( rt_args_count * 4 ) . ok_or_else ( || {
3515
+ // store its result), and B instructions to copy it into
3516
+ // the appropriate slot in the array. The groups of A and B
3517
+ // instructions, for all runtime args, are each separate,
3518
+ // so the B×N later instructions are all processed first,
3519
+ // before moving (backwards) to the A×N earlier instructions.
3520
+
3521
+ let rev_copies_to_rt_args_array_src_ptrs: SmallVec < [ _ ; 4 ] > =
3522
+ ( 0 ..rt_args_count) . rev ( ) . map ( |rt_arg_idx| {
3523
+ let copy_to_rt_args_array_insts = try_rev_take ( 4 ) . ok_or_else ( || {
3520
3524
FormatArgsNotRecognized (
3521
- "[fmt::rt::Argument; N] copies : ran out of instructions" . into ( ) ,
3525
+ "[fmt::rt::Argument; N] copy : ran out of instructions" . into ( ) ,
3522
3526
)
3523
3527
} ) ?;
3524
- let copies_to_rt_args_array = copies_to_rt_args_array. chunks ( 4 ) ;
3525
- let rt_arg_new_calls = try_rev_take ( rt_args_count * 4 ) . ok_or_else ( || {
3526
- FormatArgsNotRecognized (
3527
- "fmt::rt::Argument::new calls: ran out of instructions" . into ( ) ,
3528
- )
3529
- } ) ?;
3530
- let rt_arg_new_calls = rt_arg_new_calls. chunks ( 4 ) ;
3528
+ match copy_to_rt_args_array_insts[ ..] {
3529
+ [
3530
+ Inst :: InBoundsAccessChain ( array_slot, array_base, array_idx) ,
3531
+ Inst :: InBoundsAccessChain ( dst_field_ptr, dst_base_ptr, 0 ) ,
3532
+ Inst :: InBoundsAccessChain ( src_field_ptr, src_base_ptr, 0 ) ,
3533
+ Inst :: CopyMemory ( copy_dst, copy_src) ,
3534
+ ] if array_base == rt_args_array_ptr_id
3535
+ && array_idx as usize == rt_arg_idx
3536
+ && dst_base_ptr == array_slot
3537
+ && ( copy_dst, copy_src) == ( dst_field_ptr, src_field_ptr) =>
3538
+ {
3539
+ Ok ( src_base_ptr)
3540
+ }
3541
+ _ => {
3542
+ Err ( FormatArgsNotRecognized ( format ! (
3543
+ "[fmt::rt::Argument; N] copy sequence ({copy_to_rt_args_array_insts:?})"
3544
+ ) ) )
3545
+ }
3546
+ }
3547
+ } ) . collect :: < Result < _ , _ > > ( ) ?;
3531
3548
3532
- for ( rt_arg_idx, ( rt_arg_new_call_insts, copy_to_rt_args_array_insts) ) in
3533
- rt_arg_new_calls. zip ( copies_to_rt_args_array) . enumerate ( )
3534
- {
3535
- let call_ret_slot_ptr = match rt_arg_new_call_insts[ ..] {
3549
+ let rev_ref_arg_ids_with_ty_and_spec = ( rev_copies_to_rt_args_array_src_ptrs
3550
+ . into_iter ( ) )
3551
+ . map ( |copy_to_rt_args_array_src_ptr| {
3552
+ let rt_arg_new_call_insts = try_rev_take ( 4 ) . ok_or_else ( || {
3553
+ FormatArgsNotRecognized (
3554
+ "fmt::rt::Argument::new call: ran out of instructions" . into ( ) ,
3555
+ )
3556
+ } ) ?;
3557
+ match rt_arg_new_call_insts[ ..] {
3536
3558
[
3537
3559
Inst :: Call ( call_ret_id, callee_id, ref call_args) ,
3538
3560
Inst :: InBoundsAccessChain ( tmp_slot_field_ptr, tmp_slot_ptr, 0 ) ,
3539
3561
Inst :: CompositeExtract ( field, wrapper_newtype, 0 ) ,
3540
3562
Inst :: Store ( st_dst_ptr, st_val) ,
3541
3563
] if wrapper_newtype == call_ret_id
3564
+ && tmp_slot_ptr == copy_to_rt_args_array_src_ptr
3542
3565
&& ( st_dst_ptr, st_val) == ( tmp_slot_field_ptr, field) =>
3543
3566
{
3544
3567
self . fmt_rt_arg_new_fn_ids_to_ty_and_spec
3545
3568
. borrow ( )
3546
3569
. get ( & callee_id)
3547
3570
. and_then ( |& ( ty, spec) | match call_args[ ..] {
3548
- [ x] => {
3549
- decoded_format_args
3550
- . ref_arg_ids_with_ty_and_spec
3551
- . push ( ( x, ty, spec) ) ;
3552
- Some ( tmp_slot_ptr)
3553
- }
3571
+ [ x] => Some ( ( x, ty, spec) ) ,
3554
3572
_ => None ,
3555
3573
} )
3556
3574
}
@@ -3560,26 +3578,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
3560
3578
FormatArgsNotRecognized ( format ! (
3561
3579
"fmt::rt::Argument::new call sequence ({rt_arg_new_call_insts:?})"
3562
3580
) )
3563
- } ) ?;
3581
+ } )
3582
+ } )
3583
+ . collect :: < Result < _ , _ > > ( ) ?;
3564
3584
3565
- match copy_to_rt_args_array_insts[ ..] {
3566
- [
3567
- Inst :: InBoundsAccessChain ( array_slot, array_base, array_idx) ,
3568
- Inst :: InBoundsAccessChain ( dst_field_ptr, dst_base_ptr, 0 ) ,
3569
- Inst :: InBoundsAccessChain ( src_field_ptr, src_base_ptr, 0 ) ,
3570
- Inst :: CopyMemory ( copy_dst, copy_src) ,
3571
- ] if array_base == rt_args_array_ptr_id
3572
- && array_idx as usize == rt_arg_idx
3573
- && dst_base_ptr == array_slot
3574
- && src_base_ptr == call_ret_slot_ptr
3575
- && ( copy_dst, copy_src) == ( dst_field_ptr, src_field_ptr) => { }
3576
- _ => {
3577
- return Err ( FormatArgsNotRecognized ( format ! (
3578
- "[fmt::rt::Argument; N] copies sequence ({copy_to_rt_args_array_insts:?})"
3579
- ) ) ) ;
3580
- }
3581
- }
3582
- }
3585
+ decoded_format_args. ref_arg_ids_with_ty_and_spec =
3586
+ rev_ref_arg_ids_with_ty_and_spec;
3587
+ decoded_format_args. ref_arg_ids_with_ty_and_spec . reverse ( ) ;
3583
3588
}
3584
3589
3585
3590
// If the `pieces: &[&str]` slice needs a bitcast, it'll be here.
0 commit comments