Skip to content

Commit c0fda94

Browse files
committed
Handle unsupported int/float widths (i128/u128/f128) in check_type_capabilities.
1 parent a108277 commit c0fda94

File tree

2 files changed

+54
-64
lines changed

2 files changed

+54
-64
lines changed

crates/rustc_codegen_spirv/src/linker/simple_passes.rs

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{Result, get_name, get_names};
1+
use super::{get_name, get_names};
22
use rspirv::dr::{Block, Function, Module};
33
use rspirv::spirv::{Decoration, ExecutionModel, Op, Word};
44
use rustc_codegen_spirv_types::Capability;
@@ -7,23 +7,32 @@ use rustc_session::Session;
77
use std::iter::once;
88
use std::mem::take;
99

10+
/// Error marker type, indicating an integer/float type SPIR-V lacks support for.
11+
struct UnsupportedType;
12+
1013
/// Returns the capability required for an integer type of the given width, if any.
11-
fn capability_for_int_width(width: u32) -> Option<rspirv::spirv::Capability> {
12-
match width {
14+
fn capability_for_int_width(
15+
width: u32,
16+
) -> Result<Option<rspirv::spirv::Capability>, UnsupportedType> {
17+
Ok(match width {
1318
8 => Some(rspirv::spirv::Capability::Int8),
1419
16 => Some(rspirv::spirv::Capability::Int16),
20+
32 => None,
1521
64 => Some(rspirv::spirv::Capability::Int64),
16-
_ => None,
17-
}
22+
_ => return Err(UnsupportedType),
23+
})
1824
}
1925

2026
/// Returns the capability required for a float type of the given width, if any.
21-
fn capability_for_float_width(width: u32) -> Option<rspirv::spirv::Capability> {
22-
match width {
27+
fn capability_for_float_width(
28+
width: u32,
29+
) -> Result<Option<rspirv::spirv::Capability>, UnsupportedType> {
30+
Ok(match width {
2331
16 => Some(rspirv::spirv::Capability::Float16),
32+
32 => None,
2433
64 => Some(rspirv::spirv::Capability::Float64),
25-
_ => None,
26-
}
34+
_ => return Err(UnsupportedType),
35+
})
2736
}
2837

2938
pub fn shift_ids(module: &mut Module, add: u32) {
@@ -177,7 +186,7 @@ pub fn name_variables_pass(module: &mut Module) {
177186
}
178187

179188
// Some instructions are only valid in fragment shaders. Check them.
180-
pub fn check_fragment_insts(sess: &Session, module: &Module) -> Result<()> {
189+
pub fn check_fragment_insts(sess: &Session, module: &Module) -> super::Result<()> {
181190
let mut visited = vec![false; module.functions.len()];
182191
let mut stack = Vec::new();
183192
let mut names = None;
@@ -219,7 +228,7 @@ pub fn check_fragment_insts(sess: &Session, module: &Module) -> Result<()> {
219228
names: &mut Option<FxHashMap<Word, &'m str>>,
220229
index: usize,
221230
func_id_to_idx: &FxHashMap<Word, usize>,
222-
) -> Result<()> {
231+
) -> super::Result<()> {
223232
if visited[index] {
224233
return Ok(());
225234
}
@@ -288,7 +297,7 @@ pub fn check_fragment_insts(sess: &Session, module: &Module) -> Result<()> {
288297
///
289298
/// This function validates that if a module uses types like u8/i8 (requiring Int8),
290299
/// u16/i16 (requiring Int16), etc., the corresponding capabilities are declared.
291-
pub fn check_type_capabilities(sess: &Session, module: &Module) -> Result<()> {
300+
pub fn check_type_capabilities(sess: &Session, module: &Module) -> super::Result<()> {
292301
use rspirv::spirv::Capability;
293302

294303
// Collect declared capabilities
@@ -298,44 +307,48 @@ pub fn check_type_capabilities(sess: &Session, module: &Module) -> Result<()> {
298307
.map(|inst| inst.operands[0].unwrap_capability())
299308
.collect();
300309

301-
let mut errors = Vec::new();
310+
let mut missing_caps = vec![];
302311

303312
for inst in &module.types_global_values {
304-
match inst.class.opcode {
313+
let (prefix, width, maybe_required_cap) = match inst.class.opcode {
305314
Op::TypeInt => {
306315
let width = inst.operands[0].unwrap_literal_bit32();
307-
let signedness = inst.operands[1].unwrap_literal_bit32() != 0;
308-
let type_name = if signedness { "i" } else { "u" };
309-
310-
if let Some(required_cap) = capability_for_int_width(width)
311-
&& !declared_capabilities.contains(&required_cap)
312-
{
313-
errors.push(format!(
314-
"`{type_name}{width}` type used without `OpCapability {required_cap:?}`"
315-
));
316-
}
316+
let signed = inst.operands[1].unwrap_literal_bit32() != 0;
317+
318+
(
319+
if signed { "i" } else { "u" },
320+
width,
321+
capability_for_int_width(width),
322+
)
317323
}
318324
Op::TypeFloat => {
319325
let width = inst.operands[0].unwrap_literal_bit32();
320326

321-
if let Some(required_cap) = capability_for_float_width(width)
322-
&& !declared_capabilities.contains(&required_cap)
323-
{
324-
errors.push(format!(
325-
"`f{width}` type used without `OpCapability {required_cap:?}`"
326-
));
327-
}
327+
("f", width, capability_for_float_width(width))
328328
}
329-
_ => {}
329+
_ => continue,
330+
};
331+
332+
match maybe_required_cap {
333+
Err(UnsupportedType) => {
334+
sess.dcx()
335+
.err(format!("`{prefix}{width}` unsupported in SPIR-V"));
336+
}
337+
Ok(Some(required_cap)) if !declared_capabilities.contains(&required_cap) => {
338+
missing_caps.push(format!(
339+
"`{prefix}{width}` type used without `OpCapability {required_cap:?}`"
340+
));
341+
}
342+
Ok(_) => {}
330343
}
331344
}
332345

333-
if !errors.is_empty() {
346+
if !missing_caps.is_empty() {
334347
let mut err = sess
335348
.dcx()
336-
.struct_err("Missing required capabilities for types");
337-
for error in errors {
338-
err = err.with_note(error);
349+
.struct_err("missing required capabilities for types");
350+
for msg in missing_caps {
351+
err.note(msg);
339352
}
340353
Err(err.emit())
341354
} else {
@@ -359,13 +372,13 @@ pub fn remove_unused_type_capabilities(module: &mut Module) {
359372
match inst.class.opcode {
360373
Op::TypeInt => {
361374
let width = inst.operands[0].unwrap_literal_bit32();
362-
if let Some(cap) = capability_for_int_width(width) {
375+
if let Ok(Some(cap)) = capability_for_int_width(width) {
363376
needed_type_capabilities.insert(cap);
364377
}
365378
}
366379
Op::TypeFloat => {
367380
let width = inst.operands[0].unwrap_literal_bit32();
368-
if let Some(cap) = capability_for_float_width(width) {
381+
if let Ok(Some(cap)) = capability_for_float_width(width) {
369382
needed_type_capabilities.insert(cap);
370383
}
371384
}
@@ -391,7 +404,7 @@ pub fn remove_unused_type_capabilities(module: &mut Module) {
391404

392405
/// Remove all [`Decoration::NonUniform`] if this module does *not* have [`Capability::ShaderNonUniform`].
393406
/// This allows image asm to always declare `NonUniform` and not worry about conditional compilation.
394-
pub fn remove_non_uniform_decorations(_sess: &Session, module: &mut Module) -> Result<()> {
407+
pub fn remove_non_uniform_decorations(_sess: &Session, module: &mut Module) -> super::Result<()> {
395408
let has_shader_non_uniform_capability = module.capabilities.iter().any(|inst| {
396409
inst.class.opcode == Op::Capability
397410
&& inst.operands[0].unwrap_capability() == Capability::ShaderNonUniform

crates/rustc_codegen_spirv/src/spirv_type.rs

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -101,31 +101,8 @@ impl SpirvType<'_> {
101101
let result = match self {
102102
Self::Void => cx.emit_global().type_void_id(id),
103103
Self::Bool => cx.emit_global().type_bool_id(id),
104-
Self::Integer(width, signedness) => {
105-
let result = cx.emit_global().type_int_id(id, width, signedness as u32);
106-
let u_or_i = if signedness { "i" } else { "u" };
107-
match width {
108-
8 | 16 | 32 | 64 => {}
109-
w => cx.zombie_with_span(
110-
result,
111-
def_span,
112-
&format!("`{u_or_i}{w}` unsupported in SPIR-V"),
113-
),
114-
};
115-
result
116-
}
117-
Self::Float(width) => {
118-
let result = cx.emit_global().type_float_id(id, width);
119-
match width {
120-
16 | 32 | 64 => (),
121-
other => cx.zombie_with_span(
122-
result,
123-
def_span,
124-
&format!("`f{other}` unsupported in SPIR-V"),
125-
),
126-
};
127-
result
128-
}
104+
Self::Integer(width, signed) => cx.emit_global().type_int_id(id, width, signed as u32),
105+
Self::Float(width) => cx.emit_global().type_float_id(id, width),
129106
Self::Adt {
130107
def_id: _,
131108
align: _,

0 commit comments

Comments
 (0)