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

Commit a653c61

Browse files
authored
Get closer to testing NO_DCE in CI (#321)
* Get closer to testing NO_DCE in CI The only remaining validation issues are due to the SROA pass not being implemented yet * Revert mistakenly included change
1 parent c70cee8 commit a653c61

File tree

4 files changed

+81
-12
lines changed

4 files changed

+81
-12
lines changed

crates/rustc_codegen_spirv/src/abi.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use crate::codegen_cx::CodegenCx;
55
use crate::spirv_type::SpirvType;
66
use crate::symbols::{parse_attrs, SpirvAttribute};
7-
use rspirv::spirv::{StorageClass, Word};
7+
use rspirv::spirv::{Capability, StorageClass, Word};
88
use rustc_middle::bug;
99
use rustc_middle::ty::layout::{FnAbiExt, TyAndLayout};
1010
use rustc_middle::ty::{GeneratorSubsts, PolyFnSig, Ty, TyKind, TypeAndMut};
@@ -33,6 +33,7 @@ impl<'tcx> RecursivePointeeCache<'tcx> {
3333
fn begin(
3434
&self,
3535
cx: &CodegenCx<'tcx>,
36+
span: Span,
3637
pointee: PointeeTy<'tcx>,
3738
storage_class: StorageClass,
3839
) -> Option<Word> {
@@ -52,6 +53,18 @@ impl<'tcx> RecursivePointeeCache<'tcx> {
5253
let new_id = cx.emit_global().id();
5354
cx.emit_global().type_forward_pointer(new_id, storage_class);
5455
entry.insert(PointeeDefState::DefiningWithForward(new_id));
56+
if !cx.builder.has_capability(Capability::Addresses)
57+
&& !cx
58+
.builder
59+
.has_capability(Capability::PhysicalStorageBufferAddresses)
60+
{
61+
cx.zombie_with_span(
62+
new_id,
63+
span,
64+
"OpTypeForwardPointer without OpCapability \
65+
Addresses or PhysicalStorageBufferAddresses",
66+
);
67+
}
5568
Some(new_id)
5669
}
5770
// State: This is the third or more time we've seen this type, and we've already emitted an
@@ -459,7 +472,7 @@ fn trans_scalar<'tcx>(
459472
if let Some(predefined_result) =
460473
cx.type_cache
461474
.recursive_pointee_cache
462-
.begin(cx, pointee_ty, storage_class)
475+
.begin(cx, span, pointee_ty, storage_class)
463476
{
464477
predefined_result
465478
} else {

crates/rustc_codegen_spirv/src/codegen_cx/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,15 @@ impl<'tcx> CodegenCx<'tcx> {
216216
self.emit_global()
217217
.variable(ty, None, StorageClass::Function, Some(initializer));
218218

219+
// In all likelihood, this zombie message will get overwritten in SpirvValue::def_with_span
220+
// to the use site of this constant. However, if this constant happens to never get used, we
221+
// still want to zobmie it, so zombie here.
222+
self.zombie_even_in_user_code(
223+
global_var,
224+
span,
225+
"Cannot use this pointer directly, it must be dereferenced first",
226+
);
227+
219228
SpirvValue {
220229
kind: SpirvValueKind::ConstantPointer {
221230
initializer,

crates/rustc_codegen_spirv/src/spirv_type.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,16 @@ impl SpirvType {
189189
storage_class,
190190
pointee,
191191
} => {
192-
// Note: pointers to functions are always illegal in SPIR-V. However, the type of a
193-
// pointer to a function is sometimes used in e.g. get_fn_addr, which creates a
194-
// `SpirvValueKind::ConstantPointer`. So, pointers to functions are made illegal by
195-
// the fact it's impossible to create a pointer to function *value*, so the type
196-
// existing is fine.
197-
cx.emit_global().type_pointer(None, storage_class, pointee)
192+
let result = cx.emit_global().type_pointer(None, storage_class, pointee);
193+
// no pointers to functions
194+
if let Self::Function { .. } = cx.lookup_type(pointee) {
195+
cx.zombie_even_in_user_code(
196+
result,
197+
def_span,
198+
"function pointer types are not allowed",
199+
)
200+
}
201+
result
198202
}
199203
Self::Function {
200204
return_type,
@@ -229,7 +233,7 @@ impl SpirvType {
229233

230234
/// `def_with_id` is used by the `RecursivePointeeCache` to handle `OpTypeForwardPointer`: when
231235
/// emitting the subsequent `OpTypePointer`, the ID is already known and must be re-used.
232-
pub fn def_with_id(self, cx: &CodegenCx<'_>, _def_span: Span, id: Word) -> Word {
236+
pub fn def_with_id(self, cx: &CodegenCx<'_>, def_span: Span, id: Word) -> Word {
233237
if let Some(cached) = cx.type_cache.get(&self) {
234238
assert_eq!(cached, id);
235239
return cached;
@@ -238,9 +242,20 @@ impl SpirvType {
238242
Self::Pointer {
239243
storage_class,
240244
pointee,
241-
} => cx
242-
.emit_global()
243-
.type_pointer(Some(id), storage_class, pointee),
245+
} => {
246+
let result = cx
247+
.emit_global()
248+
.type_pointer(Some(id), storage_class, pointee);
249+
// no pointers to functions
250+
if let Self::Function { .. } = cx.lookup_type(pointee) {
251+
cx.zombie_even_in_user_code(
252+
result,
253+
def_span,
254+
"function pointer types are not allowed",
255+
)
256+
}
257+
result
258+
}
244259
ref other => cx
245260
.tcx
246261
.sess

crates/spirv-builder/src/test/basic.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,23 @@
11
use super::{dis_fn, val, val_vulkan};
2+
use std::ffi::OsStr;
3+
4+
struct SetEnvVar<'a> {
5+
k: &'a OsStr,
6+
}
7+
8+
impl<'a> SetEnvVar<'a> {
9+
fn new(k: &'a impl AsRef<OsStr>, v: impl AsRef<OsStr>) -> Self {
10+
let k = k.as_ref();
11+
std::env::set_var(k, v);
12+
Self { k }
13+
}
14+
}
15+
16+
impl<'a> Drop for SetEnvVar<'a> {
17+
fn drop(&mut self) {
18+
std::env::remove_var(self.k)
19+
}
20+
}
221

322
#[test]
423
fn hello_world() {
@@ -10,6 +29,19 @@ pub fn main() {
1029
"#);
1130
}
1231

32+
#[test]
33+
// blocked on: https://github.com/EmbarkStudios/rust-gpu/issues/69
34+
#[ignore]
35+
fn no_dce() {
36+
let _var = SetEnvVar::new(&"NO_DCE", "1");
37+
val(r#"
38+
#[allow(unused_attributes)]
39+
#[spirv(fragment)]
40+
pub fn no_dce() {
41+
}
42+
"#);
43+
}
44+
1345
#[test]
1446
fn add_two_ints() {
1547
dis_fn(

0 commit comments

Comments
 (0)