Skip to content

Commit 78344f0

Browse files
committed
WIP: builder: more robust format_args! "decompiling".
1 parent 0fc864f commit 78344f0

File tree

1 file changed

+48
-43
lines changed

1 file changed

+48
-43
lines changed

crates/rustc_codegen_spirv/src/builder/builder_methods.rs

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3510,47 +3510,65 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
35103510
if rt_args_count > 0 {
35113511
let rt_args_array_ptr_id = rt_args_slice_ptr_id.unwrap();
35123512

3513-
// Each runtime argument has 4 instructions to call one of
3513+
// Each runtime argument has A instructions to call one of
35143514
// 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(|| {
35203524
FormatArgsNotRecognized(
3521-
"[fmt::rt::Argument; N] copies: ran out of instructions".into(),
3525+
"[fmt::rt::Argument; N] copy: ran out of instructions".into(),
35223526
)
35233527
})?;
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<_, _>>()?;
35313548

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[..] {
35363558
[
35373559
Inst::Call(call_ret_id, callee_id, ref call_args),
35383560
Inst::InBoundsAccessChain(tmp_slot_field_ptr, tmp_slot_ptr, 0),
35393561
Inst::CompositeExtract(field, wrapper_newtype, 0),
35403562
Inst::Store(st_dst_ptr, st_val),
35413563
] if wrapper_newtype == call_ret_id
3564+
&& tmp_slot_ptr == copy_to_rt_args_array_src_ptr
35423565
&& (st_dst_ptr, st_val) == (tmp_slot_field_ptr, field) =>
35433566
{
35443567
self.fmt_rt_arg_new_fn_ids_to_ty_and_spec
35453568
.borrow()
35463569
.get(&callee_id)
35473570
.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)),
35543572
_ => None,
35553573
})
35563574
}
@@ -3560,26 +3578,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
35603578
FormatArgsNotRecognized(format!(
35613579
"fmt::rt::Argument::new call sequence ({rt_arg_new_call_insts:?})"
35623580
))
3563-
})?;
3581+
})
3582+
})
3583+
.collect::<Result<_, _>>()?;
35643584

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();
35833588
}
35843589

35853590
// If the `pieces: &[&str]` slice needs a bitcast, it'll be here.

0 commit comments

Comments
 (0)