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