Skip to content

Commit 34aabd9

Browse files
LegNeatoFirestar99
authored andcommitted
scalar pair: remove abi patching scalar pairs to scalars, fixup fmt args and entry point
1 parent 9453497 commit 34aabd9

5 files changed

Lines changed: 111 additions & 63 deletions

File tree

crates/rustc_codegen_spirv/src/abi.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,6 @@ pub(crate) fn provide(providers: &mut Providers) {
9292
// <https://github.com/rust-lang/rust/commit/eaaa03faf77b157907894a4207d8378ecaec7b45>
9393
arg.make_direct_deprecated();
9494

95-
// FIXME(eddyb) detect `#[rust_gpu::vector::v1]` more specifically,
96-
// to avoid affecting anything should actually be passed as a pair.
97-
if let PassMode::Pair(..) = arg.mode {
98-
// HACK(eddyb) this avoids breaking e.g. `&[T]` pairs.
99-
if let TyKind::Adt(..) = arg.layout.ty.kind() {
100-
arg.mode = PassMode::Direct(ArgAttributes::new());
101-
}
102-
}
103-
10495
// Avoid pointlessly passing ZSTs, just like the official Rust ABI.
10596
if arg.layout.is_zst() {
10697
arg.mode = PassMode::Ignore;
@@ -461,7 +452,7 @@ pub fn scalar_pair_element_backend_type<'tcx>(
461452
ty: TyAndLayout<'tcx>,
462453
index: usize,
463454
) -> Word {
464-
let [a, b] = match ty.layout.backend_repr() {
455+
let [a, b] = match ty.backend_repr {
465456
BackendRepr::ScalarPair(a, b) => [a, b],
466457
other => span_bug!(
467458
span,

crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -557,35 +557,60 @@ impl<'tcx> DecodedFormatArgs<'tcx> {
557557
if let Some((template_id, template_ty_id, rt_args_ptr_id, rt_args_ptr_ty_id)) =
558558
split_fmt_args
559559
{
560-
let ctor = if let (Some(template_len), Some(rt_args_count)) = (
560+
if let (Some(template_len), Some(rt_args_count)) = (
561561
const_ptr_to_composite_len(template_id)
562562
.or_else(|| array_len_from_ptr_type(template_ty_id)),
563563
const_ptr_to_composite_len(rt_args_ptr_id)
564564
.or_else(|| array_len_from_ptr_type(rt_args_ptr_ty_id)),
565565
) {
566-
FmtArgsCtor::NewTemplate {
567-
template_len,
568-
rt_args_count,
569-
}
566+
(
567+
FmtArgsCtor::NewTemplate {
568+
template_len,
569+
rt_args_count,
570+
},
571+
SmallVec::<[Word; 8]>::from_slice(&[template_id, rt_args_ptr_id]),
572+
)
570573
} else if let Some(&[Inst::Call(_, callee_id, ref call_args)]) =
571574
try_rev_take(-1).as_deref()
572575
&& call_args.len() == 2
573576
&& [call_args[0], call_args[1]] == [template_id, rt_args_ptr_id]
574577
{
575578
// Consume the matched call instruction.
576579
try_rev_take(1).unwrap();
577-
lookup_fmt_args_ctor(callee_id)?
580+
(
581+
lookup_fmt_args_ctor(callee_id)?,
582+
SmallVec::<[Word; 8]>::from_slice(&[template_id, rt_args_ptr_id]),
583+
)
584+
} else if let Some(
585+
&[
586+
Inst::Call(call_ret_id, callee_id, ref call_args),
587+
Inst::CompositeExtract(extracted0, from0, 0),
588+
Inst::CompositeExtract(extracted1, from1, 1),
589+
],
590+
) = try_rev_take(-3).as_deref()
591+
&& [from0, from1] == [call_ret_id; 2]
592+
&& [extracted0, extracted1] == [template_id, rt_args_ptr_id]
593+
{
594+
// Newer rustc, since `BackendRepr::ScalarPair` args are no
595+
// longer forced to `PassMode::Direct`, returns the whole
596+
// `fmt::Arguments` from its `new_*` constructor as a scalar
597+
// pair, and splits it (via `OpCompositeExtract`s) into the
598+
// two scalar values passed to the panic entry-point.
599+
//
600+
// The constructor's own arguments (i.e. `pieces`/`template`
601+
// and the `rt::Argument` slice pointers) still carry the
602+
// recoverable const data, so use those, like the aggregate
603+
// (non-split) `Call`+`extract`+`insert` case does below.
604+
let call_args_storage = call_args.iter().copied().collect();
605+
// Consume the matched call + both `OpCompositeExtract`s.
606+
try_rev_take(3).unwrap();
607+
(lookup_fmt_args_ctor(callee_id)?, call_args_storage)
578608
} else {
579609
// We failed to recover constructor metadata for an already-split
580610
// `fmt::Arguments` value. Keep panic lowering sound by falling
581611
// back to an unknown panic message, without requiring decompilation.
582612
return Ok(decoded_format_args);
583-
};
584-
585-
(
586-
ctor,
587-
SmallVec::<[Word; 8]>::from_slice(&[template_id, rt_args_ptr_id]),
588-
)
613+
}
589614
} else {
590615
// Newer rustc can pass the `fmt::Arguments::new_*` result directly to
591616
// panic entry points (single trailing call), while older versions go

crates/rustc_codegen_spirv/src/codegen_cx/entry.rs

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ use rspirv::spirv::{
1212
BuiltIn, Decoration, Dim, ExecutionModel, FunctionControl, StorageClass, Word,
1313
};
1414
use rustc_abi::FieldsShape;
15-
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, MiscCodegenMethods as _};
15+
use rustc_codegen_ssa::traits::{
16+
BaseTypeCodegenMethods, BuilderMethods, LayoutTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods as _,
17+
};
1618
use rustc_data_structures::fx::FxHashMap;
1719
use rustc_errors::MultiSpan;
1820
use rustc_hir as hir;
@@ -87,22 +89,7 @@ impl<'tcx> CodegenCx<'tcx> {
8789
};
8890
for (arg_abi, hir_param) in fn_abi.args.iter().zip(hir_params) {
8991
match arg_abi.mode {
90-
PassMode::Direct(_) | PassMode::Ignore => {}
91-
PassMode::Pair(..) => {
92-
// FIXME(eddyb) implement `ScalarPair` `Input`s, or change
93-
// the `FnAbi` readjustment to only use `PassMode::Pair` for
94-
// pointers to `!Sized` types, but not other `ScalarPair`s.
95-
if !matches!(arg_abi.layout.ty.kind(), ty::Ref(..)) {
96-
self.tcx.dcx().span_err(
97-
hir_param.ty_span,
98-
format!(
99-
"entry point parameter type not yet supported \
100-
(`{}` has `ScalarPair` ABI but is not a `&T`)",
101-
arg_abi.layout.ty
102-
),
103-
);
104-
}
105-
}
92+
PassMode::Direct(_) | PassMode::Pair(..) | PassMode::Ignore => {}
10693
_ => span_bug!(
10794
hir_param.ty_span,
10895
"query hooks should've made this `PassMode` impossible: {:#?}",
@@ -517,14 +504,6 @@ impl<'tcx> CodegenCx<'tcx> {
517504
vs layout:\n{value_layout:#?}",
518505
entry_arg_abi.layout.ty
519506
);
520-
if is_pair && !is_unsized {
521-
// If PassMode is Pair, then we need to fill in the second part of the pair with a
522-
// value. We currently only do that with unsized types, so if a type is a pair for some
523-
// other reason (e.g. a tuple), we bail.
524-
self.tcx
525-
.dcx()
526-
.span_fatal(hir_param.ty_span, "pair type not supported yet")
527-
}
528507
// FIXME(eddyb) should this talk about "typed buffers" instead of "interface blocks"?
529508
// FIXME(eddyb) should we talk about "descriptor indexing" or
530509
// actually use more reasonable terms like "resource arrays"?
@@ -647,8 +626,8 @@ impl<'tcx> CodegenCx<'tcx> {
647626
}
648627
}
649628

650-
let value_len = if is_pair {
651-
// We've already emitted an error, fill in a placeholder value
629+
let value_len = if is_pair && is_unsized {
630+
// For wide references (e.g., slices), the second component is a length.
652631
Some(bx.undef(self.type_isize()))
653632
} else {
654633
None
@@ -693,6 +672,34 @@ impl<'tcx> CodegenCx<'tcx> {
693672
call_args.push(value);
694673
assert_eq!(value_len, None);
695674
}
675+
PassMode::Pair(..) => {
676+
// Load both elements of the scalar pair from the input variable.
677+
assert_eq!(storage_class, Ok(StorageClass::Input));
678+
let layout = entry_arg_abi.layout;
679+
let (a, b) = match layout.backend_repr {
680+
rustc_abi::BackendRepr::ScalarPair(a, b) => (a, b),
681+
other => span_bug!(
682+
hir_param.ty_span,
683+
"ScalarPair expected for entry param, found {other:?}"
684+
),
685+
};
686+
let b_offset = a
687+
.primitive()
688+
.size(self)
689+
.align_to(b.primitive().align(self).abi);
690+
691+
let elem0_ty = self.scalar_pair_element_backend_type(layout, 0, false);
692+
let elem1_ty = self.scalar_pair_element_backend_type(layout, 1, false);
693+
694+
let base_ptr = value_ptr.unwrap();
695+
let ptr1 = bx.inbounds_ptradd(base_ptr, self.const_usize(b_offset.bytes()));
696+
697+
let v0 = bx.load(elem0_ty, base_ptr, layout.align.abi);
698+
let v1 = bx.load(elem1_ty, ptr1, layout.align.restrict_for_offset(b_offset));
699+
call_args.push(v0);
700+
call_args.push(v1);
701+
assert_eq!(value_len, None);
702+
}
696703
_ => unreachable!(),
697704
}
698705
}

tests/compiletests/ui/dis/complex_image_sample_inst.stderr

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,17 @@
22
%4 = OpFunctionParameter %2
33
%5 = OpFunctionParameter %6
44
%7 = OpFunctionParameter %6
5-
%8 = OpLabel
6-
%9 = OpCompositeExtract %10 %5 0
7-
%11 = OpCompositeExtract %10 %5 1
8-
%12 = OpCompositeConstruct %6 %9 %11
9-
%13 = OpCompositeExtract %10 %7 0
10-
%14 = OpCompositeExtract %10 %7 1
11-
%15 = OpCompositeConstruct %6 %13 %14
12-
OpLine %16 29 13
13-
%17 = OpAccessChain %18 %19 %20
14-
OpLine %16 30 13
15-
%21 = OpLoad %22 %17
16-
OpLine %16 34 13
17-
%23 = OpImageSampleProjExplicitLod %2 %21 %4 Grad %12 %15
5+
%8 = OpFunctionParameter %6
6+
%9 = OpFunctionParameter %6
7+
%10 = OpLabel
8+
%11 = OpCompositeConstruct %12 %5 %7
9+
%13 = OpCompositeConstruct %12 %8 %9
10+
OpLine %14 29 13
11+
%15 = OpAccessChain %16 %17 %18
12+
OpLine %14 30 13
13+
%19 = OpLoad %20 %15
14+
OpLine %14 34 13
15+
%21 = OpImageSampleProjExplicitLod %2 %19 %4 Grad %11 %13
1816
OpNoLine
19-
OpReturnValue %23
17+
OpReturnValue %21
2018
OpFunctionEnd
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// build-pass
2+
// compile-flags: -C target-feature=+Int64
3+
4+
use spirv_std::spirv;
5+
6+
#[spirv(fragment)]
7+
pub fn main_future_proof(
8+
#[spirv(flat)] input: (u64, u32),
9+
out: &mut (u64, u32),
10+
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] buffer_in: &(u64, u32),
11+
#[spirv(storage_buffer, descriptor_set = 1, binding = 0)] buffer_out: &mut (u64, u32),
12+
) {
13+
*out = trans0(trans_ref(buffer_in));
14+
*buffer_out = trans1(input);
15+
}
16+
17+
pub fn trans0(arg: (u64, u32)) -> (u64, u32) {
18+
(arg.0 + 1, arg.1 - 1)
19+
}
20+
21+
pub fn trans1((a, b): (u64, u32)) -> (u64, u32) {
22+
(a * 2, b * 3)
23+
}
24+
25+
pub fn trans_ref((a, b): &(u64, u32)) -> (u64, u32) {
26+
(a - 1, b - 1)
27+
}

0 commit comments

Comments
 (0)