Skip to content

Commit 203c750

Browse files
committed
codegen: fix panic entry-point classification and arg decoding
1 parent f9d718f commit 203c750

2 files changed

Lines changed: 31 additions & 74 deletions

File tree

crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs

Lines changed: 31 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@ use std::cell::Cell;
1919

2020
use crate::maybe_pqp_cg_ssa::traits::BuilderMethods;
2121

22-
// HACK(eddyb) Rust 2021 `panic!` always uses `format_args!`, even
23-
// in the simple case that used to pass a `&str` constant, which
24-
// would not remain reachable in the SPIR-V - but `format_args!` is
25-
// more complex and neither immediate (`fmt::Arguments` is too big)
26-
// nor simplified in MIR (e.g. promoted to a constant) in any way,
27-
// so we have to try and remove the `fmt::Arguments::new` call here.
22+
// HACK(eddyb) even after `core::fmt::Arguments::from_str` became common
23+
// for const-string panics, `core`/`std` still lower many panic paths
24+
// (e.g. `assert_unsafe_precondition!`) through `fmt::Arguments::new*`
25+
// constructors. We still need this decompiler to strip those builder
26+
// call sequences and recover panic messages/arguments when possible.
2827
#[derive(Default)]
2928
pub struct DecodedFormatArgs<'tcx> {
3029
/// If fully constant, the `pieces: &'a [&'static str]` input
@@ -302,6 +301,11 @@ impl<'tcx> DecodedFormatArgs<'tcx> {
302301
}
303302
}
304303

304+
let value_id = |value: SpirvValue| match value.kind {
305+
SpirvValueKind::Def(id) | SpirvValueKind::IllegalConst(id) => Some(id),
306+
_ => None,
307+
};
308+
305309
// HACK(eddyb) `panic_explicit` doesn't take any regular arguments,
306310
// only an (implicit) `&'static panic::Location<'static>`.
307311
if args.len() == 1 {
@@ -314,20 +318,13 @@ impl<'tcx> DecodedFormatArgs<'tcx> {
314318
}
315319

316320
// HACK(eddyb) some entry-points only take a `&str`, not `fmt::Arguments`.
317-
if let [
318-
SpirvValue {
319-
kind: SpirvValueKind::Def(a_id),
320-
ty: a_ty,
321-
},
322-
SpirvValue {
323-
kind: SpirvValueKind::Def(b_id),
324-
ty: b_ty,
325-
},
326-
ref other_args @ ..,
327-
] = args[..]
321+
if let [a, b, other_args @ ..] = args
322+
&& let (Some(a_id), Some(b_id)) = (value_id(*a), value_id(*b))
328323
{
329-
// Optional `force_no_backtrace` and/or `&'static panic::Location<'static>`.
330-
if other_args.len() <= 2
324+
let [a_ty, b_ty] = [a.ty, b.ty];
325+
326+
// Optional panic flags and/or `&'static panic::Location<'static>`.
327+
if other_args.len() <= 3
331328
&& let Some(const_msg) = const_str_as_utf8(&[a_id, b_id])
332329
{
333330
decoded_format_args.const_pieces = Some([const_msg].into_iter().collect());
@@ -336,7 +333,7 @@ impl<'tcx> DecodedFormatArgs<'tcx> {
336333

337334
// Dynamic `&str` panic messages (e.g. `panic_display(&msg)` where
338335
// `msg` isn't a directly recoverable constant).
339-
if other_args.len() <= 2
336+
if other_args.len() <= 3
340337
&& matches!(cx.lookup_type(a_ty), SpirvType::Pointer { .. })
341338
&& matches!(cx.lookup_type(b_ty), SpirvType::Integer(..))
342339
{
@@ -350,23 +347,16 @@ impl<'tcx> DecodedFormatArgs<'tcx> {
350347
// (`template: *const u8`, `args: *const fmt::rt::Argument`), instead of
351348
// being passed as one aggregate value.
352349
let split_fmt_args = match *args {
353-
[
354-
SpirvValue {
355-
kind: SpirvValueKind::Def(template_id),
356-
ty: template_ty_id,
357-
},
358-
SpirvValue {
359-
kind: SpirvValueKind::Def(rt_args_or_tagged_len_id),
360-
ty: rt_args_or_tagged_len_ty_id,
361-
},
362-
ref trailing @ ..,
363-
] if trailing.len() <= 2
364-
&& matches!(cx.lookup_type(template_ty_id), SpirvType::Pointer { .. })
365-
&& matches!(
366-
cx.lookup_type(rt_args_or_tagged_len_ty_id),
367-
SpirvType::Pointer { .. } | SpirvType::Integer(..)
368-
)
369-
&& const_str_as_utf8(&[template_id, rt_args_or_tagged_len_id]).is_none() =>
350+
[template, rt_args_or_tagged_len, ref trailing @ ..]
351+
if trailing.len() <= 3
352+
&& matches!(cx.lookup_type(template.ty), SpirvType::Pointer { .. })
353+
&& matches!(
354+
cx.lookup_type(rt_args_or_tagged_len.ty),
355+
SpirvType::Pointer { .. } | SpirvType::Integer(..)
356+
)
357+
&& let (Some(template_id), Some(rt_args_or_tagged_len_id)) =
358+
(value_id(template), value_id(rt_args_or_tagged_len))
359+
&& const_str_as_utf8(&[template_id, rt_args_or_tagged_len_id]).is_none() =>
370360
{
371361
let looks_like_bool = matches!(
372362
cx.builder.lookup_const_by_id(rt_args_or_tagged_len_id),
@@ -377,9 +367,9 @@ impl<'tcx> DecodedFormatArgs<'tcx> {
377367
} else {
378368
Some((
379369
template_id,
380-
template_ty_id,
370+
template.ty,
381371
rt_args_or_tagged_len_id,
382-
rt_args_or_tagged_len_ty_id,
372+
rt_args_or_tagged_len.ty,
383373
))
384374
}
385375
}
@@ -389,21 +379,8 @@ impl<'tcx> DecodedFormatArgs<'tcx> {
389379
let format_args_id = if split_fmt_args.is_none() {
390380
match *args {
391381
// HACK(eddyb) `panic_nounwind_fmt` takes an extra argument.
392-
[
393-
SpirvValue {
394-
kind: SpirvValueKind::Def(format_args_id),
395-
..
396-
},
397-
_, // `&'static panic::Location<'static>`
398-
]
399-
| [
400-
SpirvValue {
401-
kind: SpirvValueKind::Def(format_args_id),
402-
..
403-
},
404-
_, // `force_no_backtrace: bool`
405-
_, // `&'static panic::Location<'static>`
406-
] => format_args_id,
382+
[format_args, ref trailing @ ..] if trailing.len() <= 3 => value_id(format_args)
383+
.ok_or_else(|| FormatArgsNotRecognized("panic entry-point call args".into()))?,
407384

408385
_ => {
409386
return Err(FormatArgsNotRecognized(

crates/rustc_codegen_spirv/src/codegen_cx/declare.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
1919
use rustc_middle::ty::{self, Instance, TypeVisitableExt, TypingEnv};
2020
use rustc_span::Span;
2121
use rustc_span::def_id::DefId;
22-
use rustc_span::symbol::sym;
2322

2423
fn attrs_to_spirv(attrs: &CodegenFnAttrs) -> FunctionControl {
2524
let mut control = FunctionControl::NONE;
@@ -228,25 +227,6 @@ impl<'tcx> CodegenCx<'tcx> {
228227
{
229228
self.panic_entry_points.borrow_mut().insert(def_id);
230229
}
231-
let is_nonlocal = !def_id.is_local();
232-
let is_nonlocal_core = is_nonlocal && self.tcx.crate_name(def_id.krate) == sym::core;
233-
let nonlocal_def_path = is_nonlocal.then(|| self.tcx.def_path_str(def_id));
234-
let is_nonlocal_core_bounds_check = is_nonlocal_core
235-
&& nonlocal_def_path
236-
.as_deref()
237-
.is_some_and(|path| path.ends_with("::bounds_check"));
238-
let is_nonlocal_core_precondition_check = is_nonlocal_core
239-
&& nonlocal_def_path
240-
.as_deref()
241-
.is_some_and(|path| path.ends_with("::precondition_check"));
242-
let is_spirv_std_byte_addressable_bounds_check = nonlocal_def_path.as_deref()
243-
== Some("spirv_std::byte_addressable_buffer::bounds_check");
244-
if is_nonlocal_core_bounds_check
245-
|| is_nonlocal_core_precondition_check
246-
|| is_spirv_std_byte_addressable_bounds_check
247-
{
248-
self.panic_entry_points.borrow_mut().insert(def_id);
249-
}
250230
if let Some(generics) = demangled_symbol_name
251231
.strip_prefix("<core::fmt::Arguments>::new::<")
252232
.and_then(|s| s.strip_suffix(">"))

0 commit comments

Comments
 (0)