Skip to content

Commit 553f79e

Browse files
authored
asm: support OpCompositeExtract inference for OpTypeStruct fields. (#803)
1 parent 2f3f298 commit 553f79e

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

crates/rustc_codegen_spirv/src/builder/spirv_asm.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_hir::LlvmInlineAsmInner;
1616
use rustc_middle::bug;
1717
use rustc_span::{Span, DUMMY_SP};
1818
use rustc_target::asm::{InlineAsmRegClass, InlineAsmRegOrRegClass, SpirVInlineAsmRegClass};
19+
use std::convert::TryFrom;
1920

2021
pub struct InstructionTable {
2122
table: FxHashMap<&'static str, &'static rspirv::grammar::Instruction<'static>>,
@@ -698,13 +699,23 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
698699

699700
TyPat::IndexComposite(pat) => {
700701
let mut ty = subst_ty_pat(cx, pat, ty_vars, leftover_operands)?;
701-
for _index in leftover_operands {
702-
// FIXME(eddyb) support more than just arrays, by looking
703-
// up the indices (of struct fields) as constant integers.
702+
for index in leftover_operands {
703+
let index_to_usize = || match *index {
704+
// FIXME(eddyb) support more than just literals,
705+
// by looking up `IdRef`s as constant integers.
706+
dr::Operand::LiteralInt32(i) => usize::try_from(i).ok(),
707+
708+
_ => None,
709+
};
704710
ty = match cx.lookup_type(ty) {
705711
SpirvType::Array { element, .. }
706712
| SpirvType::RuntimeArray { element } => element,
707713

714+
SpirvType::Adt { field_types, .. } => *index_to_usize()
715+
.and_then(|i| field_types.get(i))
716+
.ok_or(Ambiguous)?,
717+
718+
// FIXME(eddyb) support more than just arrays and structs.
708719
_ => return Err(Ambiguous),
709720
};
710721
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Tests that `asm!` can infer the result type of `OpAccessChain`,
2+
// when used to index slices.
3+
4+
// build-pass
5+
6+
use spirv_std as _;
7+
8+
use glam::Vec4;
9+
10+
#[spirv(fragment)]
11+
pub fn main(
12+
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slice_in: &[Vec4],
13+
i: u32,
14+
out: &mut Vec4,
15+
) {
16+
unsafe {
17+
asm!(
18+
// HACK(eddyb) we can't pass in the `&[T]` to `asm!` directly,
19+
// and `as *const T` casts would require some special-casing
20+
// to avoid actually going through an `OpTypePointer T`, so
21+
// instead we extract the data pointer in the `asm!` itself.
22+
"%slice_ptr = OpLoad _ {slice_ptr_ptr}",
23+
"%data_ptr = OpCompositeExtract _ %slice_ptr 0",
24+
"%val_ptr = OpAccessChain _ %data_ptr {index}",
25+
"%val = OpLoad _ %val_ptr",
26+
"OpStore {out_ptr} %val",
27+
slice_ptr_ptr = in(reg) &slice_in,
28+
index = in(reg) i,
29+
out_ptr = in(reg) out,
30+
);
31+
}
32+
}

0 commit comments

Comments
 (0)