Skip to content
This repository was archived by the owner on Oct 31, 2025. It is now read-only.

Commit ee3e420

Browse files
committed
spirv-std: OpStore into MaybeUninit slots, instead of (UB) OpReturnValue.
1 parent beecb48 commit ee3e420

File tree

3 files changed

+52
-34
lines changed

3 files changed

+52
-34
lines changed

crates/spirv-std/src/arch.rs

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -250,15 +250,18 @@ pub trait IndexUnchecked<T> {
250250
impl<T> IndexUnchecked<T> for [T] {
251251
#[cfg(target_arch = "spirv")]
252252
unsafe fn index_unchecked(&self, index: usize) -> &T {
253-
asm!(
253+
// FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this.
254+
let mut result_slot = core::mem::MaybeUninit::uninit();
255+
asm! {
254256
"%slice_ptr = OpLoad _ {slice_ptr_ptr}",
255257
"%data_ptr = OpCompositeExtract _ %slice_ptr 0",
256-
"%val_ptr = OpAccessChain _ %data_ptr {index}",
257-
"OpReturnValue %val_ptr",
258+
"%result = OpAccessChain _ %data_ptr {index}",
259+
"OpStore {result_slot} %result",
258260
slice_ptr_ptr = in(reg) &self,
259261
index = in(reg) index,
260-
options(noreturn)
261-
)
262+
result_slot = in(reg) result_slot.as_mut_ptr(),
263+
}
264+
result_slot.assume_init()
262265
}
263266

264267
#[cfg(not(target_arch = "spirv"))]
@@ -268,15 +271,18 @@ impl<T> IndexUnchecked<T> for [T] {
268271

269272
#[cfg(target_arch = "spirv")]
270273
unsafe fn index_unchecked_mut(&mut self, index: usize) -> &mut T {
271-
asm!(
274+
// FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this.
275+
let mut result_slot = core::mem::MaybeUninit::uninit();
276+
asm! {
272277
"%slice_ptr = OpLoad _ {slice_ptr_ptr}",
273278
"%data_ptr = OpCompositeExtract _ %slice_ptr 0",
274-
"%val_ptr = OpAccessChain _ %data_ptr {index}",
275-
"OpReturnValue %val_ptr",
279+
"%result = OpAccessChain _ %data_ptr {index}",
280+
"OpStore {result_slot} %result",
276281
slice_ptr_ptr = in(reg) &self,
277282
index = in(reg) index,
278-
options(noreturn)
279-
)
283+
result_slot = in(reg) result_slot.as_mut_ptr(),
284+
}
285+
result_slot.assume_init()
280286
}
281287

282288
#[cfg(not(target_arch = "spirv"))]
@@ -288,13 +294,16 @@ impl<T> IndexUnchecked<T> for [T] {
288294
impl<T, const N: usize> IndexUnchecked<T> for [T; N] {
289295
#[cfg(target_arch = "spirv")]
290296
unsafe fn index_unchecked(&self, index: usize) -> &T {
291-
asm!(
292-
"%val_ptr = OpAccessChain _ {array_ptr} {index}",
293-
"OpReturnValue %val_ptr",
297+
// FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this.
298+
let mut result_slot = core::mem::MaybeUninit::uninit();
299+
asm! {
300+
"%result = OpAccessChain _ {array_ptr} {index}",
301+
"OpStore {result_slot} %result",
294302
array_ptr = in(reg) self,
295303
index = in(reg) index,
296-
options(noreturn)
297-
)
304+
result_slot = in(reg) result_slot.as_mut_ptr(),
305+
}
306+
result_slot.assume_init()
298307
}
299308

300309
#[cfg(not(target_arch = "spirv"))]
@@ -304,13 +313,16 @@ impl<T, const N: usize> IndexUnchecked<T> for [T; N] {
304313

305314
#[cfg(target_arch = "spirv")]
306315
unsafe fn index_unchecked_mut(&mut self, index: usize) -> &mut T {
307-
asm!(
308-
"%val_ptr = OpAccessChain _ {array_ptr} {index}",
309-
"OpReturnValue %val_ptr",
316+
// FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this.
317+
let mut result_slot = core::mem::MaybeUninit::uninit();
318+
asm! {
319+
"%result = OpAccessChain _ {array_ptr} {index}",
320+
"OpStore {result_slot} %result",
310321
array_ptr = in(reg) self,
311322
index = in(reg) index,
312-
options(noreturn)
313-
)
323+
result_slot = in(reg) result_slot.as_mut_ptr(),
324+
}
325+
result_slot.assume_init()
314326
}
315327

316328
#[cfg(not(target_arch = "spirv"))]

crates/spirv-std/src/ray_tracing.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@ impl AccelerationStructure {
2323
#[doc(alias = "OpConvertUToAccelerationStructureKHR")]
2424
#[inline]
2525
pub unsafe fn from_u64(id: u64) -> AccelerationStructure {
26-
// Since we can't represent an uninitalized opaque type in Rust at the
27-
// moment, we need to create and return the acceleration structure entirely
28-
// in assembly.
26+
// FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this.
27+
let mut result_slot = core::mem::MaybeUninit::uninit();
2928
asm! {
3029
"%ret = OpTypeAccelerationStructureKHR",
3130
"%result = OpConvertUToAccelerationStructureKHR %ret {id}",
32-
"OpReturnValue %result",
31+
"OpStore {result_slot} %result",
3332
id = in(reg) id,
34-
options(noreturn)
33+
result_slot = in(reg) result_slot.as_mut_ptr(),
3534
}
35+
result_slot.assume_init()
3636
}
3737

3838
/// Converts a vector of two 32 bit integers into an [`AccelerationStructure`].
@@ -42,17 +42,17 @@ impl AccelerationStructure {
4242
#[doc(alias = "OpConvertUToAccelerationStructureKHR")]
4343
#[inline]
4444
pub unsafe fn from_vec(id: impl Vector<u32, 2>) -> AccelerationStructure {
45-
// Since we can't represent an uninitalized opaque type in Rust at the
46-
// moment, we need to create and return the acceleration structure entirely
47-
// in assembly.
45+
// FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this.
46+
let mut result_slot = core::mem::MaybeUninit::uninit();
4847
asm! {
4948
"%ret = OpTypeAccelerationStructureKHR",
5049
"%id = OpLoad _ {id}",
5150
"%result = OpConvertUToAccelerationStructureKHR %ret %id",
52-
"OpReturnValue %result",
51+
"OpStore {result_slot} %result",
5352
id = in(reg) &id,
54-
options(noreturn),
53+
result_slot = in(reg) result_slot.as_mut_ptr(),
5554
}
55+
result_slot.assume_init()
5656
}
5757

5858
#[spirv_std_macros::gpu_only]

crates/spirv-std/src/runtime_array.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,16 @@ impl<T> RuntimeArray<T> {
2828
/// and lead to UB.
2929
#[spirv_std_macros::gpu_only]
3030
pub unsafe fn index(&self, index: usize) -> &T {
31+
// FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this.
32+
let mut result_slot = core::mem::MaybeUninit::uninit();
3133
asm! {
3234
"%result = OpAccessChain _ {arr} {index}",
33-
"OpReturnValue %result",
35+
"OpStore {result_slot} %result",
3436
arr = in(reg) self,
3537
index = in(reg) index,
36-
options(noreturn),
38+
result_slot = in(reg) result_slot.as_mut_ptr(),
3739
}
40+
result_slot.assume_init()
3841
}
3942

4043
/// Index the array, returning a mutable reference to an element. Unfortunately, because the
@@ -46,12 +49,15 @@ impl<T> RuntimeArray<T> {
4649
/// and lead to UB.
4750
#[spirv_std_macros::gpu_only]
4851
pub unsafe fn index_mut(&mut self, index: usize) -> &mut T {
52+
// FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this.
53+
let mut result_slot = core::mem::MaybeUninit::uninit();
4954
asm! {
5055
"%result = OpAccessChain _ {arr} {index}",
51-
"OpReturnValue %result",
56+
"OpStore {result_slot} %result",
5257
arr = in(reg) self,
5358
index = in(reg) index,
54-
options(noreturn),
59+
result_slot = in(reg) result_slot.as_mut_ptr(),
5560
}
61+
result_slot.assume_init()
5662
}
5763
}

0 commit comments

Comments
 (0)