working on spirv parser generator
[kazan.git] / spirv-parser-generator / src / ast.rs
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // Copyright 2018 Jacob Lifshay
3
4 use proc_macro2::TokenStream;
5 use quote::ToTokens;
6 use serde::de::{self, Deserialize, Deserializer};
7 use std::borrow::Cow;
8 use std::fmt;
9 use std::mem;
10 use std::num::ParseIntError;
11 use util::NameFormat::*;
12 use util::WordIterator;
13
14 #[derive(Copy, Clone)]
15 pub struct QuotedInteger<T>(pub T);
16
17 pub trait QuotedIntegerProperties: Sized {
18 const DIGIT_COUNT: usize;
19 fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError>;
20 }
21
22 impl QuotedIntegerProperties for QuotedInteger<u16> {
23 const DIGIT_COUNT: usize = 4;
24 fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
25 Ok(QuotedInteger(u16::from_str_radix(src, radix)?))
26 }
27 }
28
29 impl QuotedIntegerProperties for QuotedInteger<u32> {
30 const DIGIT_COUNT: usize = 8;
31 fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
32 Ok(QuotedInteger(u32::from_str_radix(src, radix)?))
33 }
34 }
35
36 impl<T: ToTokens> ToTokens for QuotedInteger<T> {
37 fn to_tokens(&self, tokens: &mut TokenStream) {
38 self.0.to_tokens(tokens)
39 }
40 }
41
42 impl fmt::Display for QuotedInteger<u16> {
43 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44 write!(f, "{:#06X}", self.0)
45 }
46 }
47
48 impl fmt::Display for QuotedInteger<u32> {
49 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
50 write!(f, "{:#010X}", self.0)
51 }
52 }
53
54 impl<T> fmt::Debug for QuotedInteger<T>
55 where
56 Self: fmt::Display + Copy,
57 {
58 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59 struct DisplayQuotedInteger<T>(QuotedInteger<T>);
60 impl<T> fmt::Debug for DisplayQuotedInteger<T>
61 where
62 QuotedInteger<T>: fmt::Display,
63 {
64 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 fmt::Display::fmt(&self.0, f)
66 }
67 }
68 f.debug_tuple("QuotedInteger")
69 .field(&DisplayQuotedInteger(*self))
70 .finish()
71 }
72 }
73
74 impl<'de, T> Deserialize<'de> for QuotedInteger<T>
75 where
76 Self: QuotedIntegerProperties,
77 {
78 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
79 let s = String::deserialize(deserializer)?;
80 let prefix = "0x";
81 if !s.starts_with(prefix) {
82 return Err(de::Error::custom(format!(
83 "invalid quoted integer -- must start with {:?}",
84 prefix
85 )));
86 }
87 let digits = s.split_at(prefix.len()).1;
88 let radix = 0x10;
89 if digits.find(|c: char| !c.is_digit(radix)).is_some() {
90 return Err(de::Error::custom(
91 "invalid quoted integer -- not a hexadecimal digit",
92 ));
93 }
94 if digits.len() != Self::DIGIT_COUNT {
95 return Err(de::Error::custom(
96 "invalid quoted integer -- wrong number of hex digits",
97 ));
98 }
99 Ok(Self::from_str_radix(digits, radix).unwrap())
100 }
101 }
102
103 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
104 pub enum SPIRVVersion {
105 Any,
106 None,
107 AtLeast { major: u32, minor: u32 },
108 }
109
110 impl Default for SPIRVVersion {
111 fn default() -> Self {
112 SPIRVVersion::Any
113 }
114 }
115
116 impl<'de> Deserialize<'de> for SPIRVVersion {
117 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
118 let s = String::deserialize(deserializer)?;
119 if s == "None" {
120 return Ok(SPIRVVersion::None);
121 }
122 let dot_pos = s
123 .find('.')
124 .ok_or_else(|| de::Error::custom("invalid SPIR-V version -- no decimal place"))?;
125 let (major_digits, minor_digits) = s.split_at(dot_pos);
126 let minor_digits = minor_digits.split_at(1).1;
127 let parse_digits = |digits: &str| -> Result<u32, D::Error> {
128 if digits == "" {
129 return Err(de::Error::custom(
130 "invalid SPIR-V version -- expected a decimal digit",
131 ));
132 }
133 if digits.find(|c: char| !c.is_ascii_digit()).is_some() {
134 return Err(de::Error::custom(
135 "invalid SPIR-V version -- expected a decimal digit",
136 ));
137 }
138 if digits.len() > 5 {
139 return Err(de::Error::custom(
140 "invalid SPIR-V version -- too many digits",
141 ));
142 }
143 Ok(digits.parse().unwrap())
144 };
145 let major = parse_digits(major_digits)?;
146 let minor = parse_digits(minor_digits)?;
147 Ok(SPIRVVersion::AtLeast { major, minor })
148 }
149 }
150
151 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Deserialize)]
152 pub enum Quantifier {
153 #[serde(rename = "?")]
154 Optional,
155 #[serde(rename = "*")]
156 Variadic,
157 }
158
159 #[derive(Clone, Deserialize, Debug)]
160 #[serde(deny_unknown_fields)]
161 pub struct InstructionOperand {
162 pub kind: Kind,
163 pub name: Option<String>,
164 pub quantifier: Option<Quantifier>,
165 }
166
167 impl InstructionOperand {
168 pub fn fixup(&mut self) -> Result<(), ::Error> {
169 if self.name.is_none() {
170 self.name = Some(
171 SnakeCase
172 .name_from_words(WordIterator::new(self.kind.as_ref()))
173 .ok_or(::Error::DeducingNameForInstructionOperandFailed)?,
174 );
175 }
176 self.kind.set_bit_width(BitWidth::Bits32);
177 Ok(())
178 }
179 }
180
181 #[derive(Clone, Eq, PartialEq, Hash, Debug)]
182 pub enum InstructionName {
183 OpSwitch,
184 OpSwitch32,
185 OpSwitch64,
186 OpConstant,
187 OpConstant32,
188 OpConstant64,
189 OpSpecConstant,
190 OpSpecConstant32,
191 OpSpecConstant64,
192 OpSpecConstantOp,
193 OpAccessChain,
194 OpBitcast,
195 OpBitwiseAnd,
196 OpBitwiseOr,
197 OpBitwiseXor,
198 OpCompositeExtract,
199 OpCompositeInsert,
200 OpConvertFToS,
201 OpConvertFToU,
202 OpConvertPtrToU,
203 OpConvertSToF,
204 OpConvertUToF,
205 OpConvertUToPtr,
206 OpFAdd,
207 OpFConvert,
208 OpFDiv,
209 OpFMod,
210 OpFMul,
211 OpFNegate,
212 OpFRem,
213 OpFSub,
214 OpGenericCastToPtr,
215 OpIAdd,
216 OpIEqual,
217 OpIMul,
218 OpINotEqual,
219 OpISub,
220 OpInBoundsAccessChain,
221 OpInBoundsPtrAccessChain,
222 OpLogicalAnd,
223 OpLogicalEqual,
224 OpLogicalNot,
225 OpLogicalNotEqual,
226 OpLogicalOr,
227 OpNot,
228 OpPtrAccessChain,
229 OpPtrCastToGeneric,
230 OpQuantizeToF16,
231 OpSConvert,
232 OpSDiv,
233 OpSGreaterThan,
234 OpSGreaterThanEqual,
235 OpSLessThan,
236 OpSLessThanEqual,
237 OpSMod,
238 OpSNegate,
239 OpSRem,
240 OpSelect,
241 OpShiftLeftLogical,
242 OpShiftRightArithmetic,
243 OpShiftRightLogical,
244 OpUConvert,
245 OpUDiv,
246 OpUGreaterThan,
247 OpUGreaterThanEqual,
248 OpULessThan,
249 OpULessThanEqual,
250 OpUMod,
251 OpVectorShuffle,
252 Other(String),
253 }
254
255 pub const OP_SPEC_CONSTANT_OP_SUPPORTED_INSTRUCTIONS: &[InstructionName] = &[
256 InstructionName::OpAccessChain,
257 InstructionName::OpBitcast,
258 InstructionName::OpBitwiseAnd,
259 InstructionName::OpBitwiseOr,
260 InstructionName::OpBitwiseXor,
261 InstructionName::OpCompositeExtract,
262 InstructionName::OpCompositeInsert,
263 InstructionName::OpConvertFToS,
264 InstructionName::OpConvertFToU,
265 InstructionName::OpConvertPtrToU,
266 InstructionName::OpConvertSToF,
267 InstructionName::OpConvertUToF,
268 InstructionName::OpConvertUToPtr,
269 InstructionName::OpFAdd,
270 InstructionName::OpFConvert,
271 InstructionName::OpFDiv,
272 InstructionName::OpFMod,
273 InstructionName::OpFMul,
274 InstructionName::OpFNegate,
275 InstructionName::OpFRem,
276 InstructionName::OpFSub,
277 InstructionName::OpGenericCastToPtr,
278 InstructionName::OpIAdd,
279 InstructionName::OpIEqual,
280 InstructionName::OpIMul,
281 InstructionName::OpINotEqual,
282 InstructionName::OpISub,
283 InstructionName::OpInBoundsAccessChain,
284 InstructionName::OpInBoundsPtrAccessChain,
285 InstructionName::OpLogicalAnd,
286 InstructionName::OpLogicalEqual,
287 InstructionName::OpLogicalNot,
288 InstructionName::OpLogicalNotEqual,
289 InstructionName::OpLogicalOr,
290 InstructionName::OpNot,
291 InstructionName::OpPtrAccessChain,
292 InstructionName::OpPtrCastToGeneric,
293 InstructionName::OpQuantizeToF16,
294 InstructionName::OpSConvert,
295 InstructionName::OpSDiv,
296 InstructionName::OpSGreaterThan,
297 InstructionName::OpSGreaterThanEqual,
298 InstructionName::OpSLessThan,
299 InstructionName::OpSLessThanEqual,
300 InstructionName::OpSMod,
301 InstructionName::OpSNegate,
302 InstructionName::OpSRem,
303 InstructionName::OpSelect,
304 InstructionName::OpShiftLeftLogical,
305 InstructionName::OpShiftRightArithmetic,
306 InstructionName::OpShiftRightLogical,
307 InstructionName::OpUConvert,
308 InstructionName::OpUDiv,
309 InstructionName::OpUGreaterThan,
310 InstructionName::OpUGreaterThanEqual,
311 InstructionName::OpULessThan,
312 InstructionName::OpULessThanEqual,
313 InstructionName::OpUMod,
314 InstructionName::OpVectorShuffle,
315 ];
316
317 impl Default for InstructionName {
318 fn default() -> Self {
319 InstructionName::Other(String::new())
320 }
321 }
322
323 impl From<String> for InstructionName {
324 fn from(v: String) -> Self {
325 match &*v {
326 "OpSwitch" => return InstructionName::OpSwitch,
327 "OpConstant" => return InstructionName::OpConstant,
328 "OpSpecConstant" => return InstructionName::OpSpecConstant,
329 "OpSpecConstantOp" => return InstructionName::OpSpecConstantOp,
330 "OpAccessChain" => return InstructionName::OpAccessChain,
331 "OpBitcast" => return InstructionName::OpBitcast,
332 "OpBitwiseAnd" => return InstructionName::OpBitwiseAnd,
333 "OpBitwiseOr" => return InstructionName::OpBitwiseOr,
334 "OpBitwiseXor" => return InstructionName::OpBitwiseXor,
335 "OpCompositeExtract" => return InstructionName::OpCompositeExtract,
336 "OpCompositeInsert" => return InstructionName::OpCompositeInsert,
337 "OpConvertFToS" => return InstructionName::OpConvertFToS,
338 "OpConvertFToU" => return InstructionName::OpConvertFToU,
339 "OpConvertPtrToU" => return InstructionName::OpConvertPtrToU,
340 "OpConvertSToF" => return InstructionName::OpConvertSToF,
341 "OpConvertUToF" => return InstructionName::OpConvertUToF,
342 "OpConvertUToPtr" => return InstructionName::OpConvertUToPtr,
343 "OpFAdd" => return InstructionName::OpFAdd,
344 "OpFConvert" => return InstructionName::OpFConvert,
345 "OpFDiv" => return InstructionName::OpFDiv,
346 "OpFMod" => return InstructionName::OpFMod,
347 "OpFMul" => return InstructionName::OpFMul,
348 "OpFNegate" => return InstructionName::OpFNegate,
349 "OpFRem" => return InstructionName::OpFRem,
350 "OpFSub" => return InstructionName::OpFSub,
351 "OpGenericCastToPtr" => return InstructionName::OpGenericCastToPtr,
352 "OpIAdd" => return InstructionName::OpIAdd,
353 "OpIEqual" => return InstructionName::OpIEqual,
354 "OpIMul" => return InstructionName::OpIMul,
355 "OpINotEqual" => return InstructionName::OpINotEqual,
356 "OpISub" => return InstructionName::OpISub,
357 "OpInBoundsAccessChain" => return InstructionName::OpInBoundsAccessChain,
358 "OpInBoundsPtrAccessChain" => return InstructionName::OpInBoundsPtrAccessChain,
359 "OpLogicalAnd" => return InstructionName::OpLogicalAnd,
360 "OpLogicalEqual" => return InstructionName::OpLogicalEqual,
361 "OpLogicalNot" => return InstructionName::OpLogicalNot,
362 "OpLogicalNotEqual" => return InstructionName::OpLogicalNotEqual,
363 "OpLogicalOr" => return InstructionName::OpLogicalOr,
364 "OpNot" => return InstructionName::OpNot,
365 "OpPtrAccessChain" => return InstructionName::OpPtrAccessChain,
366 "OpPtrCastToGeneric" => return InstructionName::OpPtrCastToGeneric,
367 "OpQuantizeToF16" => return InstructionName::OpQuantizeToF16,
368 "OpSConvert" => return InstructionName::OpSConvert,
369 "OpSDiv" => return InstructionName::OpSDiv,
370 "OpSGreaterThan" => return InstructionName::OpSGreaterThan,
371 "OpSGreaterThanEqual" => return InstructionName::OpSGreaterThanEqual,
372 "OpSLessThan" => return InstructionName::OpSLessThan,
373 "OpSLessThanEqual" => return InstructionName::OpSLessThanEqual,
374 "OpSMod" => return InstructionName::OpSMod,
375 "OpSNegate" => return InstructionName::OpSNegate,
376 "OpSRem" => return InstructionName::OpSRem,
377 "OpSelect" => return InstructionName::OpSelect,
378 "OpShiftLeftLogical" => return InstructionName::OpShiftLeftLogical,
379 "OpShiftRightArithmetic" => return InstructionName::OpShiftRightArithmetic,
380 "OpShiftRightLogical" => return InstructionName::OpShiftRightLogical,
381 "OpUConvert" => return InstructionName::OpUConvert,
382 "OpUDiv" => return InstructionName::OpUDiv,
383 "OpUGreaterThan" => return InstructionName::OpUGreaterThan,
384 "OpUGreaterThanEqual" => return InstructionName::OpUGreaterThanEqual,
385 "OpULessThan" => return InstructionName::OpULessThan,
386 "OpULessThanEqual" => return InstructionName::OpULessThanEqual,
387 "OpUMod" => return InstructionName::OpUMod,
388 "OpVectorShuffle" => return InstructionName::OpVectorShuffle,
389 _ => {}
390 }
391 InstructionName::Other(v)
392 }
393 }
394
395 impl AsRef<str> for InstructionName {
396 fn as_ref(&self) -> &str {
397 match self {
398 InstructionName::OpSwitch => "OpSwitch",
399 InstructionName::OpSwitch32 => "OpSwitch32",
400 InstructionName::OpSwitch64 => "OpSwitch64",
401 InstructionName::OpConstant => "OpConstant",
402 InstructionName::OpConstant32 => "OpConstant32",
403 InstructionName::OpConstant64 => "OpConstant64",
404 InstructionName::OpSpecConstant => "OpSpecConstant",
405 InstructionName::OpSpecConstant32 => "OpSpecConstant32",
406 InstructionName::OpSpecConstant64 => "OpSpecConstant64",
407 InstructionName::OpSpecConstantOp => "OpSpecConstantOp",
408 InstructionName::OpAccessChain => "OpAccessChain",
409 InstructionName::OpBitcast => "OpBitcast",
410 InstructionName::OpBitwiseAnd => "OpBitwiseAnd",
411 InstructionName::OpBitwiseOr => "OpBitwiseOr",
412 InstructionName::OpBitwiseXor => "OpBitwiseXor",
413 InstructionName::OpCompositeExtract => "OpCompositeExtract",
414 InstructionName::OpCompositeInsert => "OpCompositeInsert",
415 InstructionName::OpConvertFToS => "OpConvertFToS",
416 InstructionName::OpConvertFToU => "OpConvertFToU",
417 InstructionName::OpConvertPtrToU => "OpConvertPtrToU",
418 InstructionName::OpConvertSToF => "OpConvertSToF",
419 InstructionName::OpConvertUToF => "OpConvertUToF",
420 InstructionName::OpConvertUToPtr => "OpConvertUToPtr",
421 InstructionName::OpFAdd => "OpFAdd",
422 InstructionName::OpFConvert => "OpFConvert",
423 InstructionName::OpFDiv => "OpFDiv",
424 InstructionName::OpFMod => "OpFMod",
425 InstructionName::OpFMul => "OpFMul",
426 InstructionName::OpFNegate => "OpFNegate",
427 InstructionName::OpFRem => "OpFRem",
428 InstructionName::OpFSub => "OpFSub",
429 InstructionName::OpGenericCastToPtr => "OpGenericCastToPtr",
430 InstructionName::OpIAdd => "OpIAdd",
431 InstructionName::OpIEqual => "OpIEqual",
432 InstructionName::OpIMul => "OpIMul",
433 InstructionName::OpINotEqual => "OpINotEqual",
434 InstructionName::OpISub => "OpISub",
435 InstructionName::OpInBoundsAccessChain => "OpInBoundsAccessChain",
436 InstructionName::OpInBoundsPtrAccessChain => "OpInBoundsPtrAccessChain",
437 InstructionName::OpLogicalAnd => "OpLogicalAnd",
438 InstructionName::OpLogicalEqual => "OpLogicalEqual",
439 InstructionName::OpLogicalNot => "OpLogicalNot",
440 InstructionName::OpLogicalNotEqual => "OpLogicalNotEqual",
441 InstructionName::OpLogicalOr => "OpLogicalOr",
442 InstructionName::OpNot => "OpNot",
443 InstructionName::OpPtrAccessChain => "OpPtrAccessChain",
444 InstructionName::OpPtrCastToGeneric => "OpPtrCastToGeneric",
445 InstructionName::OpQuantizeToF16 => "OpQuantizeToF16",
446 InstructionName::OpSConvert => "OpSConvert",
447 InstructionName::OpSDiv => "OpSDiv",
448 InstructionName::OpSGreaterThan => "OpSGreaterThan",
449 InstructionName::OpSGreaterThanEqual => "OpSGreaterThanEqual",
450 InstructionName::OpSLessThan => "OpSLessThan",
451 InstructionName::OpSLessThanEqual => "OpSLessThanEqual",
452 InstructionName::OpSMod => "OpSMod",
453 InstructionName::OpSNegate => "OpSNegate",
454 InstructionName::OpSRem => "OpSRem",
455 InstructionName::OpSelect => "OpSelect",
456 InstructionName::OpShiftLeftLogical => "OpShiftLeftLogical",
457 InstructionName::OpShiftRightArithmetic => "OpShiftRightArithmetic",
458 InstructionName::OpShiftRightLogical => "OpShiftRightLogical",
459 InstructionName::OpUConvert => "OpUConvert",
460 InstructionName::OpUDiv => "OpUDiv",
461 InstructionName::OpUGreaterThan => "OpUGreaterThan",
462 InstructionName::OpUGreaterThanEqual => "OpUGreaterThanEqual",
463 InstructionName::OpULessThan => "OpULessThan",
464 InstructionName::OpULessThanEqual => "OpULessThanEqual",
465 InstructionName::OpUMod => "OpUMod",
466 InstructionName::OpVectorShuffle => "OpVectorShuffle",
467 InstructionName::Other(v) => v,
468 }
469 }
470 }
471
472 impl<'de> Deserialize<'de> for InstructionName {
473 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
474 Ok(Self::from(String::deserialize(deserializer)?))
475 }
476 }
477
478 #[derive(Clone, Deserialize, Debug)]
479 #[serde(deny_unknown_fields)]
480 pub struct Instruction {
481 pub opname: InstructionName,
482 pub opcode: u16,
483 #[serde(default)]
484 pub operands: Vec<InstructionOperand>,
485 #[serde(default)]
486 pub capabilities: Vec<String>,
487 #[serde(default)]
488 pub extensions: Vec<String>,
489 #[serde(default)]
490 pub version: SPIRVVersion,
491 }
492
493 impl Instruction {
494 pub fn fixup(&mut self) -> Result<(), ::Error> {
495 for operand in self.operands.iter_mut() {
496 operand.fixup()?;
497 }
498 Ok(())
499 }
500 }
501
502 #[derive(Deserialize, Debug)]
503 #[serde(deny_unknown_fields)]
504 pub struct ExtensionInstruction {
505 pub opname: String,
506 pub opcode: u16,
507 #[serde(default)]
508 pub operands: Vec<InstructionOperand>,
509 #[serde(default)]
510 pub capabilities: Vec<String>,
511 }
512
513 impl ExtensionInstruction {
514 pub fn fixup(&mut self) -> Result<(), ::Error> {
515 for operand in self.operands.iter_mut() {
516 operand.fixup()?;
517 }
518 Ok(())
519 }
520 }
521
522 #[derive(Deserialize, Debug, Default)]
523 #[serde(deny_unknown_fields)]
524 pub struct BitwiseEnumerantParameter {
525 pub kind: Kind,
526 }
527
528 impl BitwiseEnumerantParameter {
529 pub fn fixup(&mut self) -> Result<(), ::Error> {
530 self.kind.set_bit_width(BitWidth::Bits32);
531 Ok(())
532 }
533 }
534
535 #[derive(Deserialize, Debug, Default)]
536 #[serde(deny_unknown_fields)]
537 pub struct ValueEnumerantParameter {
538 pub kind: Kind,
539 pub name: Option<String>,
540 }
541
542 impl ValueEnumerantParameter {
543 pub fn fixup(&mut self) -> Result<(), ::Error> {
544 if self.name.is_none() {
545 self.name = Some(
546 SnakeCase
547 .name_from_words(WordIterator::new(self.kind.as_ref()))
548 .ok_or(::Error::DeducingNameForEnumerantParameterFailed)?,
549 );
550 }
551 self.kind.set_bit_width(BitWidth::Bits32);
552 Ok(())
553 }
554 }
555
556 #[derive(Deserialize, Debug)]
557 #[serde(deny_unknown_fields)]
558 pub struct Enumerant<Value, EnumerantParameter> {
559 pub enumerant: String,
560 pub value: Value,
561 #[serde(default)]
562 pub capabilities: Vec<String>,
563 #[serde(default)]
564 pub parameters: Vec<EnumerantParameter>,
565 #[serde(default)]
566 pub extensions: Vec<String>,
567 #[serde(default)]
568 pub version: SPIRVVersion,
569 }
570
571 impl Enumerant<u32, ValueEnumerantParameter> {
572 pub fn fixup(&mut self) -> Result<(), ::Error> {
573 for parameter in self.parameters.iter_mut() {
574 parameter.fixup()?;
575 }
576 Ok(())
577 }
578 }
579
580 impl Enumerant<QuotedInteger<u16>, BitwiseEnumerantParameter> {
581 pub fn fixup(&mut self) -> Result<(), ::Error> {
582 for parameter in self.parameters.iter_mut() {
583 parameter.fixup()?;
584 }
585 Ok(())
586 }
587 }
588
589 #[derive(Clone, Eq, PartialEq, Hash, Debug)]
590 pub enum Kind {
591 Literal(LiteralKind),
592 IdRef,
593 PairLiteralIntegerIdRef,
594 PairLiteralInteger32IdRef,
595 PairLiteralInteger64IdRef,
596 Other(String),
597 }
598
599 impl Kind {
600 pub fn set_bit_width(&mut self, bit_width: BitWidth) {
601 match (self, bit_width) {
602 (Kind::Literal(literal), bit_width) => literal.set_bit_width(bit_width),
603 (this @ Kind::PairLiteralIntegerIdRef, BitWidth::Bits32) => {
604 *this = Kind::PairLiteralInteger32IdRef
605 }
606 (this @ Kind::PairLiteralIntegerIdRef, BitWidth::Bits64) => {
607 *this = Kind::PairLiteralInteger64IdRef
608 }
609 (Kind::IdRef, _)
610 | (Kind::PairLiteralInteger32IdRef, _)
611 | (Kind::PairLiteralInteger64IdRef, _)
612 | (Kind::Other(_), _) => {}
613 }
614 }
615 }
616
617 impl Default for Kind {
618 fn default() -> Self {
619 Kind::Other(String::new())
620 }
621 }
622
623 impl<'a> From<Cow<'a, str>> for Kind {
624 fn from(v: Cow<'a, str>) -> Self {
625 if let Some(v) = LiteralKind::from_str(&v) {
626 Kind::Literal(v)
627 } else if v == "IdRef" {
628 Kind::IdRef
629 } else if v == "PairLiteralIntegerIdRef" {
630 Kind::PairLiteralIntegerIdRef
631 } else {
632 Kind::Other(v.into_owned())
633 }
634 }
635 }
636
637 impl<'a> From<&'a str> for Kind {
638 fn from(v: &'a str) -> Self {
639 Kind::from(Cow::Borrowed(v))
640 }
641 }
642
643 impl From<String> for Kind {
644 fn from(v: String) -> Self {
645 Kind::from(Cow::Owned(v))
646 }
647 }
648
649 impl AsRef<str> for Kind {
650 fn as_ref(&self) -> &str {
651 match self {
652 Kind::Literal(v) => v.as_ref(),
653 Kind::IdRef => "IdRef",
654 Kind::PairLiteralIntegerIdRef => "PairLiteralIntegerIdRef",
655 Kind::PairLiteralInteger32IdRef => "PairLiteralInteger32IdRef",
656 Kind::PairLiteralInteger64IdRef => "PairLiteralInteger64IdRef",
657 Kind::Other(v) => v,
658 }
659 }
660 }
661
662 impl<'de> Deserialize<'de> for Kind {
663 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
664 Ok(Self::from(String::deserialize(deserializer)?))
665 }
666 }
667
668 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Deserialize)]
669 pub enum LiteralKind {
670 LiteralInteger,
671 #[serde(skip_deserializing)]
672 LiteralInteger32,
673 #[serde(skip_deserializing)]
674 LiteralInteger64,
675 LiteralString,
676 LiteralContextDependentNumber,
677 #[serde(skip_deserializing)]
678 LiteralContextDependentNumber32,
679 #[serde(skip_deserializing)]
680 LiteralContextDependentNumber64,
681 LiteralExtInstInteger,
682 LiteralSpecConstantOpInteger,
683 }
684
685 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
686 pub enum BitWidth {
687 Bits32,
688 Bits64,
689 }
690
691 impl LiteralKind {
692 pub fn from_str<T: AsRef<str>>(v: T) -> Option<Self> {
693 match v.as_ref() {
694 "LiteralInteger" => Some(LiteralKind::LiteralInteger),
695 "LiteralString" => Some(LiteralKind::LiteralString),
696 "LiteralContextDependentNumber" => Some(LiteralKind::LiteralContextDependentNumber),
697 "LiteralExtInstInteger" => Some(LiteralKind::LiteralExtInstInteger),
698 "LiteralSpecConstantOpInteger" => Some(LiteralKind::LiteralSpecConstantOpInteger),
699 _ => None,
700 }
701 }
702 pub fn set_bit_width(&mut self, bit_width: BitWidth) {
703 *self = match (*self, bit_width) {
704 (LiteralKind::LiteralInteger, BitWidth::Bits32) => LiteralKind::LiteralInteger32,
705 (LiteralKind::LiteralInteger, BitWidth::Bits64) => LiteralKind::LiteralInteger64,
706 (LiteralKind::LiteralContextDependentNumber, BitWidth::Bits32) => {
707 LiteralKind::LiteralContextDependentNumber32
708 }
709 (LiteralKind::LiteralContextDependentNumber, BitWidth::Bits64) => {
710 LiteralKind::LiteralContextDependentNumber64
711 }
712 (LiteralKind::LiteralInteger32, _)
713 | (LiteralKind::LiteralInteger64, _)
714 | (LiteralKind::LiteralString, _)
715 | (LiteralKind::LiteralContextDependentNumber32, _)
716 | (LiteralKind::LiteralContextDependentNumber64, _)
717 | (LiteralKind::LiteralExtInstInteger, _)
718 | (LiteralKind::LiteralSpecConstantOpInteger, _) => return,
719 }
720 }
721 }
722
723 impl AsRef<str> for LiteralKind {
724 fn as_ref(&self) -> &str {
725 match self {
726 LiteralKind::LiteralInteger => "LiteralInteger",
727 LiteralKind::LiteralInteger32 => "LiteralInteger32",
728 LiteralKind::LiteralInteger64 => "LiteralInteger64",
729 LiteralKind::LiteralString => "LiteralString",
730 LiteralKind::LiteralContextDependentNumber => "LiteralContextDependentNumber",
731 LiteralKind::LiteralContextDependentNumber32 => "LiteralContextDependentNumber32",
732 LiteralKind::LiteralContextDependentNumber64 => "LiteralContextDependentNumber64",
733 LiteralKind::LiteralExtInstInteger => "LiteralExtInstInteger",
734 LiteralKind::LiteralSpecConstantOpInteger => "LiteralSpecConstantOpInteger",
735 }
736 }
737 }
738
739 #[derive(Deserialize, Debug)]
740 #[serde(deny_unknown_fields)]
741 #[serde(tag = "category")]
742 pub enum OperandKind {
743 BitEnum {
744 kind: Kind,
745 enumerants: Vec<Enumerant<QuotedInteger<u16>, BitwiseEnumerantParameter>>,
746 },
747 ValueEnum {
748 kind: Kind,
749 enumerants: Vec<Enumerant<u32, ValueEnumerantParameter>>,
750 },
751 Id {
752 kind: Kind,
753 doc: Option<String>,
754 },
755 Literal {
756 kind: LiteralKind,
757 doc: Option<String>,
758 },
759 Composite {
760 kind: Kind,
761 bases: Vec<Kind>,
762 },
763 }
764
765 #[derive(Deserialize, Debug)]
766 #[serde(deny_unknown_fields)]
767 pub struct CoreGrammar {
768 pub copyright: Vec<String>,
769 pub magic_number: QuotedInteger<u32>,
770 pub major_version: u32,
771 pub minor_version: u32,
772 pub revision: u32,
773 pub instructions: Vec<Instruction>,
774 pub operand_kinds: Vec<OperandKind>,
775 }
776
777 impl CoreGrammar {
778 pub fn fixup(&mut self) -> Result<(), ::Error> {
779 let instructions = mem::replace(&mut self.instructions, Vec::new());
780 for mut instruction in instructions {
781 if instruction.version == SPIRVVersion::None {
782 continue;
783 }
784 let (opname_32, opname_64) = match instruction.opname {
785 InstructionName::OpSwitch => {
786 (InstructionName::OpSwitch32, InstructionName::OpSwitch64)
787 }
788 InstructionName::OpConstant => {
789 (InstructionName::OpConstant32, InstructionName::OpConstant64)
790 }
791 InstructionName::OpSpecConstant => (
792 InstructionName::OpSpecConstant32,
793 InstructionName::OpSpecConstant64,
794 ),
795 opname => {
796 instruction.opname = opname;
797 instruction.fixup()?;
798 self.instructions.push(instruction);
799 continue;
800 }
801 };
802 instruction.opname = InstructionName::default();
803 let mut op_32 = Instruction {
804 opname: opname_32,
805 ..instruction.clone()
806 };
807 for operand in op_32.operands.iter_mut() {
808 operand.kind.set_bit_width(BitWidth::Bits32);
809 }
810 op_32.fixup()?;
811 self.instructions.push(op_32);
812 let mut op_64 = Instruction {
813 opname: opname_64,
814 ..instruction
815 };
816 for operand in op_64.operands.iter_mut() {
817 operand.kind.set_bit_width(BitWidth::Bits64);
818 }
819 op_64.fixup()?;
820 self.instructions.push(op_64);
821 }
822 let operand_kinds = mem::replace(&mut self.operand_kinds, Vec::new());
823 for operand_kind in operand_kinds {
824 match operand_kind {
825 OperandKind::BitEnum {
826 kind,
827 mut enumerants,
828 } => {
829 enumerants.retain(|enumerant| enumerant.version != SPIRVVersion::None);
830 for enumerant in enumerants.iter_mut() {
831 enumerant.fixup()?;
832 }
833 self.operand_kinds
834 .push(OperandKind::BitEnum { kind, enumerants });
835 }
836 OperandKind::ValueEnum {
837 kind,
838 mut enumerants,
839 } => {
840 enumerants.retain(|enumerant| enumerant.version != SPIRVVersion::None);
841 for enumerant in enumerants.iter_mut() {
842 enumerant.fixup()?;
843 }
844 self.operand_kinds
845 .push(OperandKind::ValueEnum { kind, enumerants });
846 }
847 OperandKind::Composite { kind, mut bases } => match kind {
848 Kind::PairLiteralIntegerIdRef => {
849 let mut bases_32 = bases.clone();
850 let mut bases_64 = bases;
851 for base in bases_32.iter_mut() {
852 base.set_bit_width(BitWidth::Bits32);
853 }
854 for base in bases_64.iter_mut() {
855 base.set_bit_width(BitWidth::Bits64);
856 }
857 self.operand_kinds.push(OperandKind::Composite {
858 kind: Kind::PairLiteralInteger32IdRef,
859 bases: bases_32,
860 });
861 self.operand_kinds.push(OperandKind::Composite {
862 kind: Kind::PairLiteralInteger64IdRef,
863 bases: bases_64,
864 });
865 }
866 kind => {
867 for base in bases.iter_mut() {
868 base.set_bit_width(BitWidth::Bits32);
869 }
870 self.operand_kinds
871 .push(OperandKind::Composite { kind, bases });
872 }
873 },
874 OperandKind::Literal { kind, doc } => match kind {
875 LiteralKind::LiteralInteger => {
876 self.operand_kinds.push(OperandKind::Literal {
877 kind: LiteralKind::LiteralInteger32,
878 doc: doc.clone(),
879 });
880 self.operand_kinds.push(OperandKind::Literal {
881 kind: LiteralKind::LiteralInteger64,
882 doc,
883 });
884 }
885 LiteralKind::LiteralContextDependentNumber => {
886 self.operand_kinds.push(OperandKind::Literal {
887 kind: LiteralKind::LiteralContextDependentNumber32,
888 doc: doc.clone(),
889 });
890 self.operand_kinds.push(OperandKind::Literal {
891 kind: LiteralKind::LiteralContextDependentNumber64,
892 doc,
893 });
894 }
895 kind => self.operand_kinds.push(OperandKind::Literal { kind, doc }),
896 },
897 OperandKind::Id { kind, doc } => {
898 self.operand_kinds.push(OperandKind::Id { kind, doc })
899 }
900 }
901 }
902 Ok(())
903 }
904 }
905
906 #[derive(Deserialize, Debug)]
907 #[serde(deny_unknown_fields)]
908 pub struct ExtensionInstructionSet {
909 pub copyright: Vec<String>,
910 pub version: u32,
911 pub revision: u32,
912 pub instructions: Vec<ExtensionInstruction>,
913 }
914
915 impl ExtensionInstructionSet {
916 pub fn fixup(&mut self) -> Result<(), ::Error> {
917 for instruction in self.instructions.iter_mut() {
918 instruction.fixup()?;
919 }
920 Ok(())
921 }
922 }