1use alloc::{
2 format,
3 string::{String, ToString},
4};
5
6use codespan_reporting::diagnostic::Diagnostic;
7use codespan_reporting::files::SimpleFile;
8use codespan_reporting::term;
9
10use super::ModuleState;
11#[cfg(feature = "stderr")]
12use crate::error::ErrorWrite;
13use crate::{arena::Handle, error::replace_control_chars, front::atomic_upgrade};
14
15#[derive(Clone, Debug, thiserror::Error)]
16pub enum Error {
17 #[error("invalid header")]
18 InvalidHeader,
19 #[error("invalid word count")]
20 InvalidWordCount,
21 #[error("unknown instruction {0}")]
22 UnknownInstruction(u16),
23 #[error("unknown capability %{0}")]
24 UnknownCapability(spirv::Word),
25 #[error("unsupported instruction {1:?} at {0:?}")]
26 UnsupportedInstruction(ModuleState, spirv::Op),
27 #[error("unsupported capability {0:?}")]
28 UnsupportedCapability(spirv::Capability),
29 #[error("unsupported extension {0}")]
30 UnsupportedExtension(String),
31 #[error("unsupported extension set {0}")]
32 UnsupportedExtSet(String),
33 #[error("unsupported extension instantiation set %{0}")]
34 UnsupportedExtInstSet(spirv::Word),
35 #[error("unsupported extension instantiation %{0}")]
36 UnsupportedExtInst(spirv::Word),
37 #[error("unsupported type {0:?}")]
38 UnsupportedType(Handle<crate::Type>),
39 #[error("unsupported execution model %{0}")]
40 UnsupportedExecutionModel(spirv::Word),
41 #[error("unsupported execution mode %{0}")]
42 UnsupportedExecutionMode(spirv::Word),
43 #[error("unsupported storage class %{0}")]
44 UnsupportedStorageClass(spirv::Word),
45 #[error("unsupported image dimension %{0}")]
46 UnsupportedImageDim(spirv::Word),
47 #[error("unsupported image format %{0}")]
48 UnsupportedImageFormat(spirv::Word),
49 #[error("unsupported builtin %{0}")]
50 UnsupportedBuiltIn(spirv::Word),
51 #[error("unsupported control flow %{0}")]
52 UnsupportedControlFlow(spirv::Word),
53 #[error("unsupported binary operator %{0}")]
54 UnsupportedBinaryOperator(spirv::Word),
55 #[error("Naga supports OpTypeRuntimeArray in the StorageBuffer storage class only")]
56 UnsupportedRuntimeArrayStorageClass,
57 #[error(
58 "unsupported matrix stride {} for a {}x{} matrix with scalar width={}",
59 stride,
60 columns,
61 rows,
62 width
63 )]
64 UnsupportedMatrixStride {
65 stride: u32,
66 columns: u8,
67 rows: u8,
68 width: u8,
69 },
70 #[error("unknown binary operator {0:?}")]
71 UnknownBinaryOperator(spirv::Op),
72 #[error("unknown relational function {0:?}")]
73 UnknownRelationalFunction(spirv::Op),
74 #[error("unsupported group operation %{0}")]
75 UnsupportedGroupOperation(spirv::Word),
76 #[error("invalid parameter {0:?}")]
77 InvalidParameter(spirv::Op),
78 #[error("invalid operand count {1} for {0:?}")]
79 InvalidOperandCount(spirv::Op, u16),
80 #[error("invalid operand")]
81 InvalidOperand,
82 #[error("invalid id %{0}")]
83 InvalidId(spirv::Word),
84 #[error("invalid decoration %{0}")]
85 InvalidDecoration(spirv::Word),
86 #[error("invalid type width %{0}")]
87 InvalidTypeWidth(spirv::Word),
88 #[error("invalid sign %{0}")]
89 InvalidSign(spirv::Word),
90 #[error("invalid inner type %{0}")]
91 InvalidInnerType(spirv::Word),
92 #[error("invalid vector size %{0}")]
93 InvalidVectorSize(spirv::Word),
94 #[error("invalid access type %{0}")]
95 InvalidAccessType(spirv::Word),
96 #[error("invalid access {0:?}")]
97 InvalidAccess(crate::Expression),
98 #[error("invalid access index %{0}")]
99 InvalidAccessIndex(spirv::Word),
100 #[error("invalid index type %{0}")]
101 InvalidIndexType(spirv::Word),
102 #[error("invalid binding %{0}")]
103 InvalidBinding(spirv::Word),
104 #[error("invalid global var {0:?}")]
105 InvalidGlobalVar(crate::Expression),
106 #[error("invalid image/sampler expression {0:?}")]
107 InvalidImageExpression(crate::Expression),
108 #[error("cannot create a OpTypeImage as both a depth and storage image")]
109 InvalidImageDepthStorage,
110 #[error("image read/write without format is not currently supported. See https://github.com/gfx-rs/wgpu/issues/6797")]
111 InvalidStorageImageWithoutFormat,
112 #[error("invalid image base type {0:?}")]
113 InvalidImageBaseType(Handle<crate::Type>),
114 #[error("invalid image {0:?}")]
115 InvalidImage(Handle<crate::Type>),
116 #[error("invalid as type {0:?}")]
117 InvalidAsType(Handle<crate::Type>),
118 #[error("invalid vector type {0:?}")]
119 InvalidVectorType(Handle<crate::Type>),
120 #[error("inconsistent comparison sampling {0:?}")]
121 InconsistentComparisonSampling(Handle<crate::GlobalVariable>),
122 #[error("wrong function result type %{0}")]
123 WrongFunctionResultType(spirv::Word),
124 #[error("wrong function argument type %{0}")]
125 WrongFunctionArgumentType(spirv::Word),
126 #[error("missing decoration {0:?}")]
127 MissingDecoration(spirv::Decoration),
128 #[error("bad string")]
129 BadString,
130 #[error("incomplete data")]
131 IncompleteData,
132 #[error("invalid terminator")]
133 InvalidTerminator,
134 #[error("invalid edge classification")]
135 InvalidEdgeClassification,
136 #[error("cycle detected in the CFG during traversal at {0}")]
137 ControlFlowGraphCycle(crate::front::spv::BlockId),
138 #[error("recursive function call %{0}")]
139 FunctionCallCycle(spirv::Word),
140 #[error("invalid array size %{0}")]
141 InvalidArraySize(spirv::Word),
142 #[error("invalid barrier scope %{0}")]
143 InvalidBarrierScope(spirv::Word),
144 #[error("invalid barrier memory semantics %{0}")]
145 InvalidBarrierMemorySemantics(spirv::Word),
146 #[error(
147 "arrays of images / samplers are supported only through bindings for \
148 now (i.e. you can't create an array of images or samplers that doesn't \
149 come from a binding)"
150 )]
151 NonBindingArrayOfImageOrSamplers,
152 #[error("naga only supports specialization constant IDs up to 65535 but was given {0}")]
153 SpecIdTooHigh(u32),
154
155 #[error("atomic upgrade error: {0}")]
156 AtomicUpgradeError(atomic_upgrade::Error),
157}
158
159impl Error {
160 #[cfg(feature = "stderr")]
161 pub fn emit_to_writer(&self, writer: &mut impl ErrorWrite, source: &str) {
162 self.emit_to_writer_with_path(writer, source, "spv");
163 }
164
165 #[cfg(feature = "stderr")]
166 pub fn emit_to_writer_with_path(&self, writer: &mut impl ErrorWrite, source: &str, path: &str) {
167 let path = path.to_string();
168 let files = SimpleFile::new(path, replace_control_chars(source));
169 let config = term::Config::default();
170 let diagnostic = Diagnostic::error().with_message(format!("{self:?}"));
171
172 crate::error::emit_to_writer(writer, &config, &files, &diagnostic)
173 .expect("cannot write error");
174 }
175
176 pub fn emit_to_string(&self, source: &str) -> String {
177 self.emit_to_string_with_path(source, "spv")
178 }
179
180 pub fn emit_to_string_with_path(&self, source: &str, path: &str) -> String {
181 let path = path.to_string();
182 let files = SimpleFile::new(path, replace_control_chars(source));
183 let config = term::Config::default();
184 let diagnostic = Diagnostic::error().with_message(format!("{self:?}"));
185
186 let mut writer = crate::error::DiagnosticBuffer::new();
187 writer
188 .emit_to_self(&config, &files, &diagnostic)
189 .expect("cannot write error");
190 writer.into_string()
191 }
192}
193
194impl From<atomic_upgrade::Error> for Error {
195 fn from(source: atomic_upgrade::Error) -> Self {
196 Error::AtomicUpgradeError(source)
197 }
198}