1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // Copyright 2018 Jacob Lifshay
7 use std::collections::HashMap;
8 use std::collections::HashSet;
10 use std::io::{self, Read, Write};
12 use std::process::{Child, Command, ExitStatus, Stdio};
14 use util::{self, NameFormat::*};
22 WhichError(which::Error),
23 RustFmtFailed(ExitStatus),
26 impl fmt::Display for FormatError {
27 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29 FormatError::IOError(v) => fmt::Display::fmt(v, f),
30 FormatError::WhichError(v) => fmt::Display::fmt(v, f),
31 FormatError::RustFmtFailed(v) => write!(f, "rustfmt failed: {:?}", v),
36 impl From<which::Error> for FormatError {
37 fn from(v: which::Error) -> Self {
38 FormatError::WhichError(v)
42 impl From<io::Error> for FormatError {
43 fn from(v: io::Error) -> Self {
44 FormatError::IOError(v)
48 fn format_source<'a>(options: &Options, source: &'a str) -> Result<Cow<'a, str>, FormatError> {
49 if !options.run_rustfmt {
50 return Ok(Cow::Borrowed(source));
52 let rustfmt_path = match options.rustfmt_path.clone() {
54 None => which::which("rustfmt")?,
56 let mut command = Command::new(rustfmt_path)
57 .stdin(Stdio::piped())
58 .stdout(Stdio::piped())
60 let stdin = command.stdin.take().unwrap();
61 let reader_thread = thread::spawn(move || -> io::Result<(String, Child)> {
62 let mut output = String::new();
63 command.stdout.take().unwrap().read_to_string(&mut output)?;
66 { stdin }.write_all(source.as_bytes())?;
67 let (output, mut command) = reader_thread.join().unwrap()?;
68 let exit_status = command.wait()?;
69 if exit_status.success() {
70 Ok(Cow::Owned(output))
72 Err(FormatError::RustFmtFailed(exit_status))
76 fn remove_initial_op(name: &str) -> &str {
77 const INITIAL_OP: &str = "Op";
78 assert!(name.starts_with(INITIAL_OP));
79 &name[INITIAL_OP.len()..]
82 fn new_id<T: AsRef<str>>(name: T, name_format: util::NameFormat) -> proc_macro2::Ident {
83 proc_macro2::Ident::new(
85 .name_from_words(util::WordIterator::new(name.as_ref()))
87 proc_macro2::Span::call_site(),
91 fn new_enumerant_id<T1: AsRef<str>, T2: AsRef<str>>(
94 ) -> proc_macro2::Ident {
95 let enumerant_name_words = util::WordIterator::new(enumerant_name.as_ref());
96 let enumerant_name_first_word = enumerant_name_words.clone().next();
97 let name = if enumerant_name_first_word
100 .and_then(Iterator::next)
101 .filter(char::is_ascii_digit)
106 util::WordIterator::new(enum_name.as_ref()).chain(enumerant_name_words),
110 CamelCase.name_from_words(enumerant_name_words).unwrap()
112 proc_macro2::Ident::new(&name, proc_macro2::Span::call_site())
115 fn new_combined_id<I: IntoIterator>(names: I, name_format: util::NameFormat) -> proc_macro2::Ident
119 let names: Vec<I::Item> = names.into_iter().collect();
120 proc_macro2::Ident::new(
126 .flat_map(util::WordIterator::new),
129 proc_macro2::Span::call_site(),
133 struct ParsedExtensionInstructionSet {
134 ast: ast::ExtensionInstructionSet,
135 enumerant_name: proc_macro2::Ident,
136 spirv_instruction_set_name: &'static str,
139 #[cfg_attr(feature = "cargo-clippy", allow(clippy::cyclomatic_complexity))]
140 pub(crate) fn generate(
141 core_grammar: ast::CoreGrammar,
142 parsed_extension_instruction_sets: HashMap<
143 super::ExtensionInstructionSet,
144 ast::ExtensionInstructionSet,
147 ) -> Result<String, Error> {
148 let mut out = Vec::new();
149 let ast::CoreGrammar {
150 copyright: core_grammar_copyright,
154 revision: core_revision,
155 instructions: core_instructions,
158 let parsed_extension_instruction_sets: Vec<_> = parsed_extension_instruction_sets
160 .map(|(key, ast)| match key {
161 super::ExtensionInstructionSet::GLSLStd450 => ParsedExtensionInstructionSet {
163 enumerant_name: new_id("GLSLStd450", CamelCase),
164 spirv_instruction_set_name: "GLSL.std.450",
166 super::ExtensionInstructionSet::OpenCLStd => ParsedExtensionInstructionSet {
168 enumerant_name: new_id("OpenCLStd", CamelCase),
169 spirv_instruction_set_name: "OpenCL.std",
173 writeln!(&mut out, "// automatically generated file")?;
175 let mut copyright_set = HashSet::new();
176 for copyright in iter::once(&core_grammar_copyright).chain(
177 parsed_extension_instruction_sets
179 .map(|v| &v.ast.copyright),
181 if !copyright_set.insert(copyright) {
184 writeln!(&mut out, "//")?;
185 for line in copyright.iter() {
186 assert_eq!(line.find('\r'), None);
187 assert_eq!(line.find('\n'), None);
189 writeln!(&mut out, "//")?;
191 writeln!(&mut out, "// {}", line)?;
200 use std::borrow::Cow;
206 use std::str::Utf8Error;
207 use std::string::FromUtf8Error;
209 trait SPIRVParse: Sized {
210 fn spirv_parse<'a>(words: &'a [u32], parse_state: &mut ParseState)
211 -> Result<(Self, &'a [u32])>;
215 fn spirv_display(&self, f: &mut fmt::Formatter) -> fmt::Result;
218 impl<T: SPIRVParse> SPIRVParse for Option<T> {
221 parse_state: &mut ParseState,
222 ) -> Result<(Self, &'a [u32])> {
223 if words.is_empty() {
226 let (value, words) = T::spirv_parse(words, parse_state)?;
227 Ok((Some(value), words))
232 impl<T: SPIRVDisplay> SPIRVDisplay for Option<T> {
233 fn spirv_display(&self, f: &mut fmt::Formatter) -> fmt::Result {
235 Some(v) => v.spirv_display(f),
241 impl<T: SPIRVParse> SPIRVParse for Vec<T> {
243 mut words: &'a [u32],
244 parse_state: &mut ParseState,
245 ) -> Result<(Self, &'a [u32])> {
246 let mut retval = Vec::new();
247 while !words.is_empty() {
248 let result = T::spirv_parse(words, parse_state)?;
250 retval.push(result.0);
256 impl<T: SPIRVDisplay> SPIRVDisplay for Vec<T> {
257 fn spirv_display(&self, f: &mut fmt::Formatter) -> fmt::Result {
265 impl<A: SPIRVParse, B: SPIRVParse> SPIRVParse for (A, B) {
268 parse_state: &mut ParseState,
269 ) -> Result<(Self, &'a [u32])> {
270 let (a, words) = A::spirv_parse(words, parse_state)?;
271 let (b, words) = B::spirv_parse(words, parse_state)?;
276 impl<A: SPIRVDisplay, B: SPIRVDisplay> SPIRVDisplay for (A, B) {
277 fn spirv_display(&self, f: &mut fmt::Formatter) -> fmt::Result {
278 self.0.spirv_display(f)?;
279 self.1.spirv_display(f)
283 const BYTES_PER_WORD: usize = 4;
285 struct ByteIterator<'a> {
286 current_word: [u8; BYTES_PER_WORD],
287 current_word_index: usize,
291 impl<'a> ByteIterator<'a> {
292 fn new(words: &'a [u32]) -> Self {
294 current_word: [0; BYTES_PER_WORD],
295 current_word_index: BYTES_PER_WORD,
299 fn take_unread_words(&mut self) -> &'a [u32] {
300 mem::replace(&mut self.words, &[])
304 impl<'a> Iterator for ByteIterator<'a> {
306 fn next(&mut self) -> Option<u8> {
307 if self.current_word_index >= BYTES_PER_WORD {
308 let (¤t_word, words) = self.words.split_first()?;
310 self.current_word = unsafe { mem::transmute(current_word.to_le()) };
311 self.current_word_index = 0;
313 let byte = self.current_word[self.current_word_index];
314 self.current_word_index += 1;
319 impl SPIRVParse for String {
322 _parse_state: &mut ParseState,
323 ) -> Result<(Self, &'a [u32])> {
324 let mut byte_count_excluding_null_terminator = None;
325 for (index, byte) in ByteIterator::new(words).enumerate() {
327 byte_count_excluding_null_terminator = Some(index);
331 let byte_count_excluding_null_terminator =
332 byte_count_excluding_null_terminator.ok_or(Error::InstructionPrematurelyEnded)?;
333 let mut bytes = Vec::with_capacity(byte_count_excluding_null_terminator);
334 let mut byte_iter = ByteIterator::new(words);
335 for _ in 0..byte_count_excluding_null_terminator {
336 let byte = byte_iter.next().unwrap();
339 let _null_terminator = byte_iter.next().unwrap();
340 let words = byte_iter.take_unread_words();
343 return Err(Error::InvalidStringTermination);
346 assert_eq!(bytes.len(), byte_count_excluding_null_terminator);
347 Ok((String::from_utf8(bytes)?, words))
351 impl SPIRVDisplay for String {
352 fn spirv_display(&self, f: &mut fmt::Formatter) -> fmt::Result {
353 write!(f, " {:?}", self)
357 impl SPIRVParse for u32 {
360 _parse_state: &mut ParseState,
361 ) -> Result<(Self, &'a [u32])> {
362 let (&value, words) = words
364 .ok_or(Error::InstructionPrematurelyEnded)?;
369 impl SPIRVDisplay for u32 {
370 fn spirv_display(&self, f: &mut fmt::Formatter) -> fmt::Result {
371 write!(f, " {}", self)
375 impl SPIRVParse for u64 {
378 _parse_state: &mut ParseState,
379 ) -> Result<(Self, &'a [u32])> {
380 let (&low, words) = words
382 .ok_or(Error::InstructionPrematurelyEnded)?;
383 let (&high, words) = words
385 .ok_or(Error::InstructionPrematurelyEnded)?;
386 Ok(((u64::from(high) << 32) | u64::from(low), words))
390 impl SPIRVDisplay for u64 {
391 fn spirv_display(&self, f: &mut fmt::Formatter) -> fmt::Result {
392 write!(f, " {}", self)
396 impl SPIRVParse for IdRef {
399 parse_state: &mut ParseState,
400 ) -> Result<(Self, &'a [u32])> {
401 let (value, words) = u32::spirv_parse(words, parse_state)?;
402 if value == 0 || value as usize >= parse_state.id_states.len() {
403 Err(Error::IdOutOfBounds(value))
405 Ok((IdRef(value), words))
410 impl SPIRVDisplay for IdRef {
411 fn spirv_display(&self, f: &mut fmt::Formatter) -> fmt::Result {
412 write!(f, " {}", self)
421 pub const MAGIC_NUMBER: u32 = #magic_number;
422 pub const MAJOR_VERSION: u32 = #major_version;
423 pub const MINOR_VERSION: u32 = #minor_version;
424 pub const REVISION: u32 = #core_revision;
427 for operand_kind in &operand_kinds {
429 ast::OperandKind::BitEnum { kind, enumerants } => {
430 let kind_id = new_id(kind, CamelCase);
431 let mut enumerant_members = Vec::new();
432 let mut enumerant_member_names = Vec::new();
433 let mut enumerant_items = Vec::new();
434 let mut enumerant_parse_operations = Vec::new();
435 let mut enumerant_display_mask_operations = Vec::new();
436 let mut enumerant_display_operations = Vec::new();
437 let mut none_name = "None";
438 for enumerant in enumerants {
439 if enumerant.value.0 == 0 {
440 none_name = enumerant.enumerant.as_ref();
443 let enumerant_name = &enumerant.enumerant;
444 let member_name = new_id(&enumerant.enumerant, SnakeCase);
445 let member_name = &member_name;
446 enumerant_member_names.push(member_name.clone());
448 new_combined_id(&[kind.as_ref(), &enumerant.enumerant], CamelCase);
449 let enumerant_parse_operation;
450 if enumerant.parameters.is_empty() {
451 enumerant_items.push(quote!{
452 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
453 pub struct #type_name;
455 enumerant_parse_operation = quote!{(Some(#type_name), words)};
456 enumerant_display_mask_operations.push(quote!{
457 if self.#member_name.is_some() {
459 write!(f, "|{}", #enumerant_name)?;
461 write!(f, " {}", #enumerant_name)?;
466 enumerant_display_operations.push(quote!{});
468 let mut enumerant_parameter_declarations = Vec::new();
469 let mut enumerant_parameter_names = Vec::new();
470 let mut parse_enumerant_members = Vec::new();
471 let mut display_enumerant_members = Vec::new();
472 for (index, parameter) in enumerant.parameters.iter().enumerate() {
473 let name = new_id(format!("parameter_{}", index), SnakeCase);
474 let kind = new_id(¶meter.kind, CamelCase);
475 enumerant_parameter_declarations.push(quote!{
478 enumerant_parameter_names.push(quote!{
481 parse_enumerant_members.push(quote!{
482 let (#name, words) = #kind::spirv_parse(words, parse_state)?;
484 display_enumerant_members.push(quote!{
485 #name.spirv_display(f)?;
488 enumerant_items.push(quote!{
489 #[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
490 pub struct #type_name(#(#enumerant_parameter_declarations)*);
492 let enumerant_parameter_names = &enumerant_parameter_names;
493 enumerant_parse_operation = quote!{
494 #(#parse_enumerant_members)*
495 (Some(#type_name(#(#enumerant_parameter_names)*)), words)
497 enumerant_display_mask_operations.push(quote!{
498 if self.#member_name.is_some() {
500 write!(f, "|{}", #enumerant_name)?;
502 write!(f, " {}", #enumerant_name)?;
507 enumerant_display_operations.push(quote!{
508 if let Some(#type_name(#(#enumerant_parameter_names)*)) = &self.#member_name {
509 #(#display_enumerant_members)*
513 enumerant_members.push(quote!{
514 pub #member_name: Option<#type_name>
516 let enumerant_value = enumerant.value;
517 enumerant_parse_operations.push(quote!{
518 let (#member_name, words) = if (mask & #enumerant_value) != 0 {
519 mask &= !#enumerant_value;
520 #enumerant_parse_operation
530 #[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
531 pub struct #kind_id {
532 #(#enumerant_members),*
537 let parse_body = quote!{
538 let (mut mask, words) = u32::spirv_parse(words, parse_state)?;
539 #(#enumerant_parse_operations)*
541 Err(Error::InvalidEnumValue)
544 #(#enumerant_member_names,)*
552 impl SPIRVParse for #kind_id {
555 parse_state: &mut ParseState,
556 ) -> Result<(Self, &'a [u32])> {
566 impl SPIRVDisplay for #kind_id {
567 fn spirv_display(&self, f: &mut fmt::Formatter) -> fmt::Result {
568 let mut any_members = false;
569 #(#enumerant_display_mask_operations)*
571 write!(f, " {}", #none_name)?;
573 #(#enumerant_display_operations)*
580 ast::OperandKind::ValueEnum { kind, enumerants } => {
581 let mut has_any_parameters = false;
582 for enumerant in enumerants {
583 if !enumerant.parameters.is_empty() {
584 has_any_parameters = true;
587 let kind_id = new_id(&kind, CamelCase);
588 let mut generated_enumerants = Vec::new();
589 let mut enumerant_parse_cases = Vec::new();
590 let mut enumerant_display_cases = Vec::new();
591 for enumerant in enumerants {
592 let name = new_enumerant_id(&kind, &enumerant.enumerant);
593 let enumerant_value = enumerant.value;
594 let display_name = &enumerant.enumerant;
595 if enumerant.parameters.is_empty() {
596 generated_enumerants.push(quote!{#name});
597 enumerant_parse_cases.push(quote!{
598 #enumerant_value => Ok((#kind_id::#name, words)),
600 enumerant_display_cases.push(quote!{
601 #kind_id::#name => write!(f, " {}", #display_name),
604 let mut enumerant_member_declarations = Vec::new();
605 let mut enumerant_member_names = Vec::new();
606 let mut parse_enumerant_members = Vec::new();
607 let mut display_enumerant_members = Vec::new();
608 for parameter in enumerant.parameters.iter() {
609 let name = new_id(parameter.name.as_ref().unwrap(), SnakeCase);
610 let kind = new_id(¶meter.kind, CamelCase);
611 enumerant_member_declarations.push(quote!{
614 enumerant_member_names.push(quote!{
617 parse_enumerant_members.push(quote!{
618 let (#name, words) = #kind::spirv_parse(words, parse_state)?;
620 display_enumerant_members.push(quote!{
621 #name.spirv_display(f)?;
624 generated_enumerants.push(quote!{
626 #(#enumerant_member_declarations)*
629 let enumerant_member_names = &enumerant_member_names;
630 enumerant_parse_cases.push(quote!{
631 #enumerant_value => {
632 #(#parse_enumerant_members)*
633 Ok((#kind_id::#name {
634 #(#enumerant_member_names)*
638 enumerant_display_cases.push(quote!{
640 #(#enumerant_member_names)*
642 write!(f, " {}", #display_name)?;
643 #(#display_enumerant_members)*
649 let mut derives = vec![
656 if !has_any_parameters {
657 derives.push(quote!{Copy});
663 #[derive(#(#derives),*)]
665 #(#generated_enumerants,)*
673 impl SPIRVParse for #kind_id {
676 parse_state: &mut ParseState,
677 ) -> Result<(Self, &'a [u32])> {
678 let (enumerant, words) = u32::spirv_parse(words, parse_state)?;
680 #(#enumerant_parse_cases)*
681 _ => Err(Error::InvalidEnumValue),
691 impl SPIRVDisplay for #kind_id {
692 fn spirv_display(&self, f: &mut fmt::Formatter) -> fmt::Result {
694 #(#enumerant_display_cases)*
701 ast::OperandKind::Id { kind, .. } => {
702 let base = if *kind == ast::Kind::IdRef {
707 let kind_id = new_id(kind, CamelCase);
712 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
714 pub struct #kind_id(pub #base);
717 if *kind != ast::Kind::IdRef {
722 impl SPIRVParse for #kind_id {
725 parse_state: &mut ParseState,
726 ) -> Result<(Self, &'a [u32])> {
727 IdRef::spirv_parse(words, parse_state).map(|(value, words)| (#kind_id(value), words))
736 impl fmt::Display for #kind_id {
737 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
738 fmt::Display::fmt(&self.0, f)
747 impl SPIRVDisplay for #kind_id {
748 fn spirv_display(&self, f: &mut fmt::Formatter) -> fmt::Result {
749 self.0.spirv_display(f)
756 ast::OperandKind::Literal { kind, .. } => {
757 let kind_id = new_id(kind, CamelCase);
762 ast::LiteralKind::LiteralInteger
763 | ast::LiteralKind::LiteralContextDependentNumber => unreachable!(),
764 ast::LiteralKind::LiteralInteger32
765 | ast::LiteralKind::LiteralContextDependentNumber32 => {
766 quote!{pub type #kind_id = u32;}
768 ast::LiteralKind::LiteralInteger64
769 | ast::LiteralKind::LiteralContextDependentNumber64 => {
770 quote!{pub type #kind_id = u64;}
772 ast::LiteralKind::LiteralString => quote!{pub type #kind_id = String;},
773 ast::LiteralKind::LiteralExtInstInteger => {
774 quote!{pub type #kind_id = u32;}
776 ast::LiteralKind::LiteralSpecConstantOpInteger => continue,
780 ast::OperandKind::Composite { kind, bases } => {
781 let kind = new_id(kind, CamelCase);
782 let bases = bases.iter().map(|base| new_id(base, CamelCase));
783 writeln!(&mut out, "{}", quote!{pub type #kind = (#(#bases),*);})?;
788 let mut instruction_enumerants = Vec::new();
789 let mut spec_constant_op_instruction_enumerants = Vec::new();
790 let mut instruction_parse_cases = Vec::new();
791 let mut instruction_display_cases = Vec::new();
792 let mut instruction_spec_constant_parse_cases = Vec::new();
793 let mut instruction_spec_constant_display_cases = Vec::new();
794 let mut instruction_extension_enumerants = Vec::new();
795 let mut instruction_extension_parse_cases = Vec::new();
796 let mut instruction_extension_display_cases = Vec::new();
797 for parsed_extension_instruction_set in &parsed_extension_instruction_sets {
798 let extension_instruction_set = &parsed_extension_instruction_set.enumerant_name;
799 for instruction in &parsed_extension_instruction_set.ast.instructions {
800 let instruction_enumerant_name = new_combined_id(
802 parsed_extension_instruction_set.spirv_instruction_set_name,
803 instruction.opname.as_ref(),
807 let opcode = instruction.opcode;
808 let mut fields = Vec::new();
809 for operand in instruction.operands.iter() {
810 let kind = new_id(&operand.kind, CamelCase);
811 let name = new_id(operand.name.as_ref().unwrap(), SnakeCase);
812 let kind = match &operand.quantifier {
813 None => quote!{#kind},
814 Some(ast::Quantifier::Optional) => quote!{Option<#kind>},
815 Some(ast::Quantifier::Variadic) => quote!{Vec<#kind>},
817 fields.push(quote!{#name: #kind});
819 let instruction_extension_enumerant = quote!{
820 #instruction_enumerant_name {
821 id_result_type: IdResultType,
827 instruction_extension_enumerants.push(instruction_extension_enumerant);
828 let mut parse_operations = Vec::new();
829 let mut display_operations = Vec::new();
830 let mut operand_names = Vec::new();
831 for operand in &instruction.operands {
832 let kind = new_id(&operand.kind, CamelCase);
833 let name = new_id(operand.name.as_ref().unwrap(), SnakeCase);
834 let kind = match operand.quantifier {
835 None => quote!{#kind},
836 Some(ast::Quantifier::Optional) => quote!{Option::<#kind>},
837 Some(ast::Quantifier::Variadic) => quote!{Vec::<#kind>},
839 parse_operations.push(quote!{
840 let (#name, words) = #kind::spirv_parse(words, parse_state)?;
842 display_operations.push(quote!{
843 #name.spirv_display(f)?;
845 operand_names.push(name);
847 let operand_names = &operand_names;
849 #(#parse_operations)*
850 if words.is_empty() {
851 Ok(Instruction::#instruction_enumerant_name {
858 Err(Error::InstructionTooLong)
861 let instruction_extension_parse_case = quote!{
862 (ExtensionInstructionSet::#extension_instruction_set, #opcode) => {
866 instruction_extension_parse_cases.push(instruction_extension_parse_case);
867 let display_opname = &instruction.opname;
868 let instruction_extension_display_case = quote!{
869 Instruction::#instruction_enumerant_name {
877 "{}OpExtInst {} {} {}",
878 InstructionIndentAndResult(Some(*id_result)),
883 #(#display_operations)*
887 instruction_extension_display_cases.push(instruction_extension_display_case);
890 let instruction_extension_parse_cases = &instruction_extension_parse_cases;
891 for instruction in core_instructions.iter() {
892 let opcode = instruction.opcode;
893 let opname = new_id(remove_initial_op(instruction.opname.as_ref()), CamelCase);
894 let display_opname = instruction.opname.as_ref();
895 let display_opname_without_initial_op = remove_initial_op(display_opname);
896 let instruction_parse_case;
897 let instruction_display_case;
898 match &instruction.opname {
899 ast::InstructionName::OpExtInstImport => {
901 parse_state.define_id(
903 IdState::ExtensionInstructionSet(ExtensionInstructionSet::from(&*name)),
905 if words.is_empty() {
906 Ok(Instruction::ExtInstImport { id_result, name })
908 Err(Error::InstructionTooLong)
911 instruction_parse_case = quote!{#opcode => {
912 let (id_result, words) = IdResult::spirv_parse(words, parse_state)?;
913 let (name, words) = LiteralString::spirv_parse(words, parse_state)?;
916 instruction_display_case = quote!{
917 Instruction::ExtInstImport { id_result, name } => {
918 writeln!(f, "{}{} {:?}", InstructionIndentAndResult(Some(*id_result)), #display_opname, name)
922 ast::InstructionName::OpExtInst => {
924 let extension_instruction_set;
925 match parse_state.id_states[set.0 as usize].clone() {
926 IdState::ExtensionInstructionSet(ExtensionInstructionSet::Other(_)) => {
927 let (operands, words) = Vec::<LiteralInteger32>::spirv_parse(words, parse_state)?;
928 if words.is_empty() {
929 return Ok(Instruction::ExtInst {
937 return Err(Error::InstructionTooLong);
940 IdState::ExtensionInstructionSet(v) => {
941 extension_instruction_set = v;
943 _ => return Err(Error::IdIsNotExtInstImport(set)),
945 match (extension_instruction_set, instruction) {
946 #(#instruction_extension_parse_cases)*
947 (extension_instruction_set, instruction) => Err(Error::UnknownExtensionOpcode(extension_instruction_set, instruction)),
950 instruction_parse_case = quote!{
952 let (id_result_type, words) = IdResultType::spirv_parse(words, parse_state)?;
953 let (id_result, words) = IdResult::spirv_parse(words, parse_state)?;
954 parse_state.define_value(id_result_type, id_result)?;
955 let (set, words) = IdRef::spirv_parse(words, parse_state)?;
956 let (instruction, words) = LiteralExtInstInteger::spirv_parse(words, parse_state)?;
960 instruction_display_case = quote!{
961 Instruction::ExtInst {
968 write!(f, "{}{}", InstructionIndentAndResult(Some(*id_result)), #display_opname)?;
969 id_result_type.spirv_display(f)?;
970 set.spirv_display(f)?;
971 instruction.spirv_display(f)?;
972 operands.spirv_display(f)?;
977 ast::InstructionName::OpTypeInt => {
979 let (signedness, words) = LiteralInteger32::spirv_parse(words, parse_state)?;
980 let id_state = match width {
981 8 | 16 | 32 => IdState::Type(IdStateType(BitWidth::Width32OrLess)),
982 64 => IdState::Type(IdStateType(BitWidth::Width64)),
983 _ => return Err(Error::UnsupportedIntSize),
985 parse_state.define_id(id_result, id_state)?;
986 if words.is_empty() {
987 Ok(Instruction::TypeInt {
993 Err(Error::InstructionTooLong)
996 instruction_parse_case = quote!{
998 let (id_result, words) = IdResult::spirv_parse(words, parse_state)?;
999 let (width, words) = LiteralInteger32::spirv_parse(words, parse_state)?;
1003 instruction_display_case = quote!{
1004 Instruction::TypeInt {
1012 InstructionIndentAndResult(Some(*id_result)),
1015 width.spirv_display(f)?;
1016 signedness.spirv_display(f)?;
1021 ast::InstructionName::OpTypeFloat => {
1022 instruction_parse_case = quote!{
1024 let (id_result, words) = IdResult::spirv_parse(words, parse_state)?;
1025 let (width, words) = LiteralInteger32::spirv_parse(words, parse_state)?;
1026 let id_state = match width {
1027 16 | 32 => IdState::Type(IdStateType(BitWidth::Width32OrLess)),
1028 64 => IdState::Type(IdStateType(BitWidth::Width64)),
1029 _ => return Err(Error::UnsupportedFloatSize),
1031 parse_state.define_id(id_result, id_state)?;
1032 if words.is_empty() {
1033 Ok(Instruction::TypeFloat {
1038 Err(Error::InstructionTooLong)
1042 instruction_display_case = quote!{
1043 Instruction::TypeFloat { id_result, width } => {
1047 InstructionIndentAndResult(Some(*id_result)),
1050 width.spirv_display(f)?;
1055 ast::InstructionName::OpSwitch32 => {
1056 let body32 = quote!{
1057 IdState::Value(IdStateValue(BitWidth::Width32OrLess)) => {
1058 let (target, words) = Vec::<PairLiteralInteger32IdRef>::spirv_parse(words, parse_state)?;
1059 if words.is_empty() {
1060 Ok(Instruction::Switch32 {
1066 Err(Error::InstructionTooLong)
1070 let body64 = quote!{
1071 IdState::Value(IdStateValue(BitWidth::Width64)) => {
1072 let (target, words) = Vec::<PairLiteralInteger64IdRef>::spirv_parse(words, parse_state)?;
1073 if words.is_empty() {
1074 Ok(Instruction::Switch64 {
1080 Err(Error::InstructionTooLong)
1084 instruction_parse_case = quote!{
1086 let (selector, words) = IdRef::spirv_parse(words, parse_state)?;
1087 let (default, words) = IdRef::spirv_parse(words, parse_state)?;
1088 match &parse_state.id_states[selector.0 as usize] {
1091 _ => Err(Error::SwitchSelectorIsInvalid(selector)),
1095 instruction_display_case = quote!{
1096 Instruction::Switch32 {
1104 InstructionIndentAndResult(None),
1107 selector.spirv_display(f)?;
1108 default.spirv_display(f)?;
1109 target.spirv_display(f)?;
1112 Instruction::Switch64 {
1120 InstructionIndentAndResult(None),
1123 selector.spirv_display(f)?;
1124 default.spirv_display(f)?;
1125 target.spirv_display(f)?;
1130 ast::InstructionName::OpSwitch64 => {
1131 instruction_parse_case = quote!{};
1132 instruction_display_case = quote!{};
1134 ast::InstructionName::OpConstant32 => {
1135 let body32 = quote!{
1136 IdStateType(BitWidth::Width32OrLess) => {
1137 let (value, words) = LiteralContextDependentNumber32::spirv_parse(words, parse_state)?;
1138 if words.is_empty() {
1139 Ok(Instruction::Constant32 {
1145 Err(Error::InstructionTooLong)
1149 let body64 = quote!{
1150 IdStateType(BitWidth::Width64) => {
1151 let (value, words) = LiteralContextDependentNumber64::spirv_parse(words, parse_state)?;
1152 if words.is_empty() {
1153 Ok(Instruction::Constant64 {
1159 Err(Error::InstructionTooLong)
1163 instruction_parse_case = quote!{
1165 let (id_result_type, words) = IdResultType::spirv_parse(words, parse_state)?;
1166 let (id_result, words) = IdResult::spirv_parse(words, parse_state)?;
1167 parse_state.define_value(id_result_type, id_result)?;
1168 match parse_state.get_type(id_result_type.0)? {
1174 instruction_display_case = quote!{
1175 Instruction::Constant32 {
1183 InstructionIndentAndResult(Some(*id_result)),
1186 id_result_type.spirv_display(f)?;
1187 writeln!(f, " {:#010X}", value)
1189 Instruction::Constant64 {
1197 InstructionIndentAndResult(Some(*id_result)),
1200 id_result_type.spirv_display(f)?;
1201 writeln!(f, " {:#018X}", value)
1205 ast::InstructionName::OpConstant64 => {
1206 instruction_parse_case = quote!{};
1207 instruction_display_case = quote!{};
1209 ast::InstructionName::OpSpecConstant32 => {
1210 let body32 = quote!{
1211 IdStateType(BitWidth::Width32OrLess) => {
1212 let (value, words) = LiteralContextDependentNumber32::spirv_parse(words, parse_state)?;
1213 if words.is_empty() {
1214 Ok(Instruction::SpecConstant32 {
1220 Err(Error::InstructionTooLong)
1224 let body64 = quote!{
1225 IdStateType(BitWidth::Width64) => {
1226 let (value, words) = LiteralContextDependentNumber64::spirv_parse(words, parse_state)?;
1227 if words.is_empty() {
1228 Ok(Instruction::SpecConstant64 {
1234 Err(Error::InstructionTooLong)
1238 instruction_parse_case = quote!{
1240 let (id_result_type, words) = IdResultType::spirv_parse(words, parse_state)?;
1241 let (id_result, words) = IdResult::spirv_parse(words, parse_state)?;
1242 parse_state.define_value(id_result_type, id_result)?;
1243 match parse_state.get_type(id_result_type.0)? {
1249 instruction_display_case = quote!{
1250 Instruction::SpecConstant32 {
1258 InstructionIndentAndResult(Some(*id_result)),
1261 id_result_type.spirv_display(f)?;
1262 writeln!(f, " {:#010X}", value)
1264 Instruction::SpecConstant64 {
1272 InstructionIndentAndResult(Some(*id_result)),
1275 id_result_type.spirv_display(f)?;
1276 writeln!(f, " {:#018X}", value)
1280 ast::InstructionName::OpSpecConstant64 => {
1281 instruction_parse_case = quote!{};
1282 instruction_display_case = quote!{};
1284 ast::InstructionName::OpSpecConstantOp => {
1285 instruction_parse_case = quote!{#opcode => {
1286 let (operation, words) = OpSpecConstantOp::spirv_parse(words, parse_state)?;
1287 if words.is_empty() {
1288 Ok(Instruction::#opname { operation })
1290 Err(Error::InstructionTooLong)
1293 instruction_display_case = quote!{
1294 Instruction::#opname { operation } => fmt::Display::fmt(operation, f),
1298 let mut parse_operations = Vec::new();
1299 let mut display_operations = Vec::new();
1300 let mut operand_names = Vec::new();
1301 let mut result_name = None;
1302 for operand in &instruction.operands {
1303 let kind = new_id(&operand.kind, CamelCase);
1304 let name = new_id(operand.name.as_ref().unwrap(), SnakeCase);
1305 let kind = match operand.quantifier {
1306 None => quote!{#kind},
1307 Some(ast::Quantifier::Optional) => quote!{Option::<#kind>},
1308 Some(ast::Quantifier::Variadic) => quote!{Vec::<#kind>},
1310 parse_operations.push(quote!{
1311 let (#name, words) = #kind::spirv_parse(words, parse_state)?;
1313 operand_names.push(name.clone());
1314 if operand.kind == ast::Kind::IdResult {
1315 assert_eq!(result_name, None);
1316 result_name = Some(name);
1318 display_operations.push(quote!{
1319 #name.spirv_display(f)?;
1323 if let Some([operand1, operand2]) = instruction.operands.get(..2) {
1324 if operand1.kind == ast::Kind::IdResultType
1325 && operand2.kind == ast::Kind::IdResult
1327 let operand1_name = new_id(operand1.name.as_ref().unwrap(), SnakeCase);
1328 let operand2_name = new_id(operand2.name.as_ref().unwrap(), SnakeCase);
1329 parse_operations.push(quote!{
1330 parse_state.define_value(#operand1_name, #operand2_name)?;
1334 let operand_names = &operand_names;
1335 instruction_parse_case = quote!{#opcode => {
1336 #(#parse_operations)*
1337 if words.is_empty() {
1338 Ok(Instruction::#opname {
1342 Err(Error::InstructionTooLong)
1345 let result_value = match result_name {
1346 None => quote!{None},
1347 Some(result_name) => quote!{Some(*#result_name)},
1349 instruction_display_case = quote!{
1350 Instruction::#opname { #(#operand_names,)* } => {
1351 write!(f, "{}{}", InstructionIndentAndResult(#result_value), #display_opname)?;
1352 #(#display_operations)*
1358 instruction_parse_cases.push(instruction_parse_case);
1359 instruction_display_cases.push(instruction_display_case);
1360 let instruction_enumerant =
1361 if instruction.opname == ast::InstructionName::OpSpecConstantOp {
1364 operation: OpSpecConstantOp,
1367 } else if instruction.operands.is_empty() {
1370 let mut fields = Vec::new();
1371 for operand in instruction.operands.iter() {
1372 let kind = new_id(&operand.kind, CamelCase);
1373 let name = new_id(operand.name.as_ref().unwrap(), SnakeCase);
1374 let kind = match &operand.quantifier {
1375 None => quote!{#kind},
1376 Some(ast::Quantifier::Optional) => quote!{Option<#kind>},
1377 Some(ast::Quantifier::Variadic) => quote!{Vec<#kind>},
1379 fields.push(quote!{#name: #kind});
1387 if ast::OP_SPEC_CONSTANT_OP_SUPPORTED_INSTRUCTIONS.contains(&instruction.opname) {
1388 let opcode = u32::from(opcode);
1389 spec_constant_op_instruction_enumerants.push(instruction_enumerant.clone());
1390 let mut parse_operations = Vec::new();
1391 let mut display_operations = Vec::new();
1392 let mut operand_names = Vec::new();
1393 operand_names.push(new_id("id_result_type", SnakeCase));
1394 operand_names.push(new_id("id_result", SnakeCase));
1395 for operand in instruction.operands.iter().skip(2) {
1396 let kind = new_id(&operand.kind, CamelCase);
1397 let name = new_id(operand.name.as_ref().unwrap(), SnakeCase);
1398 let kind = match operand.quantifier {
1399 None => quote!{#kind},
1400 Some(ast::Quantifier::Optional) => quote!{Option::<#kind>},
1401 Some(ast::Quantifier::Variadic) => quote!{Vec::<#kind>},
1403 parse_operations.push(quote!{
1404 let (#name, words) = #kind::spirv_parse(words, parse_state)?;
1406 display_operations.push(quote!{
1407 #name.spirv_display(f)?;
1409 operand_names.push(name);
1411 if let Some([operand1, operand2]) = instruction.operands.get(..2) {
1412 assert_eq!(operand1.kind, ast::Kind::IdResultType);
1413 assert_eq!(operand2.kind, ast::Kind::IdResult);
1414 let operand1_name = new_id(operand1.name.as_ref().unwrap(), SnakeCase);
1415 let operand2_name = new_id(operand2.name.as_ref().unwrap(), SnakeCase);
1416 parse_operations.push(quote!{
1417 parse_state.define_value(#operand1_name, #operand2_name)?;
1422 "spec constant op is missing id_result_type and id_result"
1425 let operand_names = &operand_names;
1426 instruction_spec_constant_parse_cases.push(quote!{#opcode => {
1427 #(#parse_operations)*
1428 if words.is_empty() {
1429 Ok((OpSpecConstantOp::#opname {
1433 Err(Error::InstructionTooLong)
1436 instruction_spec_constant_display_cases.push(quote!{
1437 OpSpecConstantOp::#opname {
1440 write!(f, "{}{}", InstructionIndentAndResult(Some(*id_result)), "OpSpecConstantOp")?;
1441 id_result_type.spirv_display(f)?;
1442 write!(f, " {}", #display_opname_without_initial_op)?;
1443 #(#display_operations)*
1448 instruction_enumerants.push(instruction_enumerant);
1454 #[derive(Clone, Debug)]
1455 pub enum OpSpecConstantOp {
1456 #(#spec_constant_op_instruction_enumerants,)*
1464 impl fmt::Display for OpSpecConstantOp {
1465 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1467 #(#instruction_spec_constant_display_cases)*
1477 #[derive(Clone, Debug)]
1478 pub enum Instruction {
1479 #(#instruction_enumerants,)*
1480 #(#instruction_extension_enumerants,)*
1488 #[derive(Copy, Clone, Debug)]
1490 pub version: (u32, u32),
1493 pub instruction_schema: u32,
1496 impl fmt::Display for Header {
1497 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1498 writeln!(f, "; SPIR-V")?;
1499 writeln!(f, "; Version: {}.{}", self.version.0, self.version.1)?;
1500 writeln!(f, "; Generator: {:#X}", self.generator)?;
1501 writeln!(f, "; Bound: {}", self.bound)?;
1502 writeln!(f, "; Schema: {}", self.instruction_schema)
1506 struct InstructionIndentAndResult(Option<IdResult>);
1508 impl fmt::Display for InstructionIndentAndResult {
1509 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1510 write!(f, "{:>15}", self.0.map(|v| format!("{} = ", v.0)).unwrap_or_default())
1514 impl fmt::Display for IdRef {
1515 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1516 write!(f, "%{}", self.0)
1520 #[derive(Clone, Debug)]
1525 UnsupportedVersion(u32, u32),
1526 ZeroInstructionLength,
1527 SourcePrematurelyEnded,
1529 UnknownSpecConstantOpcode(u32),
1530 UnknownExtensionOpcode(ExtensionInstructionSet, u32),
1531 Utf8Error(Utf8Error),
1532 InstructionPrematurelyEnded,
1533 InvalidStringTermination,
1537 IdAlreadyDefined(IdResult),
1538 UnsupportedFloatSize,
1540 UndefinedType(IdRef),
1541 SwitchSelectorIsInvalid(IdRef),
1542 IdIsNotExtInstImport(IdRef),
1545 impl From<Utf8Error> for Error {
1546 fn from(v: Utf8Error) -> Self {
1551 impl From<FromUtf8Error> for Error {
1552 fn from(v: FromUtf8Error) -> Self {
1553 Error::Utf8Error(v.utf8_error())
1557 impl fmt::Display for Error {
1558 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1560 Error::MissingHeader => write!(f, "SPIR-V source is missing the file header"),
1561 Error::InvalidHeader => write!(f, "SPIR-V source has an invalid file header"),
1562 Error::BoundTooBig(bound) => write!(
1564 "SPIR-V source has an invalid file header; the id bound is way bigger than needed: {}",
1567 Error::UnsupportedVersion(major, minor) => write!(
1569 "SPIR-V source has an unsupported version: {}.{}",
1573 Error::ZeroInstructionLength => write!(f, "SPIR-V instruction has a length of zero"),
1574 Error::SourcePrematurelyEnded => write!(f, "SPIR-V source prematurely ended"),
1575 Error::UnknownOpcode(opcode) => {
1576 write!(f, "SPIR-V instruction has an unknown opcode: {}", opcode)
1578 Error::UnknownSpecConstantOpcode(opcode) => {
1579 write!(f, "SPIR-V OpSpecConstantOp instruction has an unknown opcode: {}", opcode)
1581 Error::UnknownExtensionOpcode(ref extension_instruction_set, opcode) => {
1582 write!(f, "SPIR-V OpExtInst instruction has an unknown opcode: {} in {}", opcode, extension_instruction_set)
1584 Error::Utf8Error(error) => fmt::Display::fmt(&error, f),
1585 Error::InstructionPrematurelyEnded => write!(f, "SPIR-V instruction prematurely ended"),
1586 Error::InvalidStringTermination => write!(f, "SPIR-V LiteralString has an invalid termination word"),
1587 Error::InstructionTooLong => write!(f, "SPIR-V instruction is too long"),
1588 Error::InvalidEnumValue => write!(f, "enum has invalid value"),
1589 Error::IdOutOfBounds(id) => write!(f, "id is out of bounds: {}", id),
1590 Error::IdAlreadyDefined(id) => write!(f, "id is already defined: {}", id),
1591 Error::UnsupportedFloatSize => write!(f, "unsupported float size"),
1592 Error::UnsupportedIntSize => write!(f, "unsupported int size"),
1593 Error::UndefinedType(id) => write!(f, "undefined type {}", id),
1594 Error::SwitchSelectorIsInvalid(id) => write!(f, "Switch selector is invalid: {}", id),
1595 Error::IdIsNotExtInstImport(id) => write!(f, "id is not the result of an OpExtInstImport instruction: {}", id),
1600 impl error::Error for Error {}
1602 type Result<T> = result::Result<T, Error>;
1604 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1610 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1611 struct IdStateType(BitWidth);
1613 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1614 struct IdStateValue(BitWidth);
1616 #[derive(Clone, Debug, Eq, PartialEq, Hash)]
1620 Value(IdStateValue),
1621 ExtensionInstructionSet(ExtensionInstructionSet),
1624 #[derive(Clone, Debug)]
1626 id_states: Vec<IdState>,
1630 fn define_id(&mut self, id_result: IdResult, new_id_state: IdState) -> Result<()> {
1631 let id_state = &mut self.id_states[(id_result.0).0 as usize];
1632 if *id_state != IdState::Unknown {
1633 return Err(Error::IdAlreadyDefined(id_result));
1635 *id_state = new_id_state;
1638 fn get_type(&self, id: IdRef) -> Result<IdStateType> {
1639 if let IdState::Type(retval) = self.id_states[id.0 as usize] {
1642 Err(Error::UndefinedType(id))
1645 fn define_value(&mut self, id_result_type: IdResultType, id_result: IdResult) -> Result<()> {
1646 if let IdState::Type(IdStateType(bit_width)) = self.id_states[(id_result_type.0).0 as usize] {
1647 self.define_id(id_result, IdState::Value(IdStateValue(bit_width)))?;
1653 #[derive(Clone, Debug)]
1654 pub struct Parser<'a> {
1657 parse_state: ParseState,
1660 fn parse_version(v: u32) -> Result<(u32, u32)> {
1661 if (v & 0xFF0000FF) != 0 {
1662 return Err(Error::InvalidHeader);
1664 let major = (v >> 16) & 0xFF;
1665 let minor = (v >> 8) & 0xFF;
1669 impl<'a> Parser<'a> {
1670 pub fn header(&self) -> &Header {
1673 pub fn start(mut words: &'a [u32]) -> Result<Self> {
1674 let header = words.get(0..5).ok_or(Error::MissingHeader)?;
1675 words = &words[5..];
1676 let header = match *header {
1677 [MAGIC_NUMBER, version, generator, bound, instruction_schema @ 0] if bound >= 1 => {
1678 let version = parse_version(version)?;
1679 if version.0 != MAJOR_VERSION || version.1 > MINOR_VERSION {
1680 return Err(Error::UnsupportedVersion(version.0, version.1));
1689 _ => return Err(Error::InvalidHeader),
1691 if header.bound as usize > words.len() && header.bound > 0x10000 {
1692 Err(Error::BoundTooBig(header.bound))
1697 parse_state: ParseState {
1698 id_states: vec![IdState::Unknown; header.bound as usize],
1703 fn next_helper(&mut self, length_and_opcode: u32) -> Result<Instruction> {
1704 let length = (length_and_opcode >> 16) as usize;
1705 let opcode = length_and_opcode as u16;
1707 return Err(Error::ZeroInstructionLength);
1709 let instruction_words = self.words.get(1..length).ok_or(Error::SourcePrematurelyEnded)?;
1710 self.words = &self.words[length..];
1711 parse_instruction(opcode, instruction_words, &mut self.parse_state)
1715 impl<'a> Iterator for Parser<'a> {
1716 type Item = Result<Instruction>;
1717 fn next(&mut self) -> Option<Result<Instruction>> {
1718 let length_and_opcode = self.words.get(0)?;
1719 Some(self.next_helper(*length_and_opcode))
1728 fn parse_instruction(opcode: u16, words: &[u32], parse_state: &mut ParseState) -> Result<Instruction> {
1730 #(#instruction_parse_cases)*
1731 opcode => Err(Error::UnknownOpcode(opcode)),
1740 impl fmt::Display for Instruction {
1741 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1743 #(#instruction_display_cases)*
1744 #(#instruction_extension_display_cases)*
1751 let (id_result_type, words) = IdResultType::spirv_parse(words, parse_state)?;
1752 let (id_result, words) = IdResult::spirv_parse(words, parse_state)?;
1753 let (opcode, words) = u32::spirv_parse(words, parse_state)?;
1755 #(#instruction_spec_constant_parse_cases)*
1756 opcode => Err(Error::UnknownSpecConstantOpcode(opcode)),
1763 impl SPIRVParse for OpSpecConstantOp {
1766 parse_state: &mut ParseState
1767 ) -> Result<(Self, &'a [u32])> {
1775 let extension_instruction_set_enumerants: Vec<_> = parsed_extension_instruction_sets
1777 .map(|v| &v.enumerant_name)
1779 let extension_instruction_set_enumerants = &extension_instruction_set_enumerants;
1780 let spirv_instruction_set_names: Vec<_> = parsed_extension_instruction_sets
1782 .map(|v| v.spirv_instruction_set_name)
1784 let spirv_instruction_set_names = &spirv_instruction_set_names;
1785 for parsed_extension_instruction_set in parsed_extension_instruction_sets.iter() {
1786 let version_name = new_combined_id(
1788 parsed_extension_instruction_set.spirv_instruction_set_name,
1793 let version = parsed_extension_instruction_set.ast.version;
1794 let revision_name = new_combined_id(
1796 parsed_extension_instruction_set.spirv_instruction_set_name,
1801 let revision = parsed_extension_instruction_set.ast.revision;
1806 pub const #version_name: u32 = #version;
1807 pub const #revision_name: u32 = #revision;
1815 #[derive(Clone, Eq, PartialEq, Hash, Debug)]
1816 pub enum ExtensionInstructionSet {
1817 #(#extension_instruction_set_enumerants,)*
1826 impl<'a> From<Cow<'a, str>> for ExtensionInstructionSet {
1827 fn from(s: Cow<'a, str>) -> ExtensionInstructionSet {
1829 #(#spirv_instruction_set_names => return ExtensionInstructionSet::#extension_instruction_set_enumerants,)*
1832 ExtensionInstructionSet::Other(s.into_owned())
1841 impl Deref for ExtensionInstructionSet {
1843 fn deref(&self) -> &str {
1845 #(ExtensionInstructionSet::#extension_instruction_set_enumerants => #spirv_instruction_set_names,)*
1846 ExtensionInstructionSet::Other(s) => &**s,
1856 impl AsRef<str> for ExtensionInstructionSet {
1857 fn as_ref(&self) -> &str {
1862 impl From<ExtensionInstructionSet> for String {
1863 fn from(v: ExtensionInstructionSet) -> String {
1865 ExtensionInstructionSet::Other(v) => v,
1866 v => String::from(v.as_ref()),
1871 impl<'a> From<&'a str> for ExtensionInstructionSet {
1872 fn from(s: &'a str) -> Self {
1873 Cow::Borrowed(s).into()
1877 impl From<String> for ExtensionInstructionSet {
1878 fn from(s: String) -> Self {
1879 Self::from(Cow::Owned(s))
1883 impl fmt::Display for ExtensionInstructionSet {
1884 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1885 let s: &str = &**self;
1886 fmt::Display::fmt(s, f)
1892 let source = String::from_utf8(out).unwrap();
1893 let source = match format_source(&options, &source) {
1894 Ok(source) => source.into_owned(),
1896 eprintln!("formatting source failed: {}", error);