1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // Copyright 2018 Jacob Lifshay
5 extern crate serde_derive;
7 extern crate serde_json;
9 use std::collections::HashMap;
15 use std::path::PathBuf;
20 pub const SPIRV_CORE_GRAMMAR_JSON_FILE_NAME: &str = "spirv.core.grammar.json";
22 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
23 pub enum ExtensionInstructionSet {
28 impl ExtensionInstructionSet {
29 pub fn get_grammar_json_file_name(self) -> &'static str {
31 ExtensionInstructionSet::GLSLStd450 => "extinst.glsl.std.450.grammar.json",
32 ExtensionInstructionSet::OpenCLStd => "extinst.opencl.std.100.grammar.json",
40 JSONError(serde_json::Error),
41 DeducingNameForInstructionOperandFailed,
42 DeducingNameForEnumerantParameterFailed,
45 impl From<io::Error> for Error {
46 fn from(v: io::Error) -> Error {
51 impl From<serde_json::Error> for Error {
52 fn from(v: serde_json::Error) -> Error {
53 if let serde_json::error::Category::Io = v.classify() {
54 Error::IOError(v.into())
61 impl fmt::Display for Error {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64 Error::IOError(v) => fmt::Display::fmt(v, f),
65 Error::JSONError(v) => fmt::Display::fmt(v, f),
66 Error::DeducingNameForInstructionOperandFailed => {
67 write!(f, "deducing name for InstructionOperand failed")
69 Error::DeducingNameForEnumerantParameterFailed => {
70 write!(f, "deducing name for EnumerantParameter failed")
76 impl error::Error for Error {}
78 impl From<Error> for io::Error {
79 fn from(error: Error) -> Self {
81 Error::IOError(v) => v,
82 Error::JSONError(v) => v.into(),
83 error @ Error::DeducingNameForInstructionOperandFailed
84 | error @ Error::DeducingNameForEnumerantParameterFailed => {
85 io::Error::new(io::ErrorKind::Other, format!("{}", error))
94 spirv_core_grammar_json_path: PathBuf,
95 extension_instruction_sets: HashMap<ExtensionInstructionSet, PathBuf>,
99 pub fn new<T: AsRef<Path>>(spirv_core_grammar_json_path: T) -> Input {
101 spirv_core_grammar_json_path: spirv_core_grammar_json_path.as_ref().into(),
102 extension_instruction_sets: HashMap::new(),
105 pub fn add_extension_instruction_set<T: AsRef<Path>>(
107 extension_instruction_set: ExtensionInstructionSet,
111 self.extension_instruction_sets
112 .insert(extension_instruction_set, path.as_ref().into())
114 "duplicate extension instruction set: {:?}",
115 extension_instruction_set
119 pub fn generate(self) -> Result<Output, Error> {
121 spirv_core_grammar_json_path,
122 extension_instruction_sets,
124 let mut core_grammar: ast::CoreGrammar =
125 serde_json::from_reader(File::open(spirv_core_grammar_json_path)?)?;
126 core_grammar.guess_names()?;
127 let mut parsed_extension_instruction_sets: HashMap<
128 ExtensionInstructionSet,
129 ast::ExtensionInstructionSet,
130 > = Default::default();
131 for (extension_instruction_set, path) in extension_instruction_sets {
132 let mut parsed_extension_instruction_set: ast::ExtensionInstructionSet =
133 serde_json::from_reader(File::open(path)?)?;
134 parsed_extension_instruction_set.guess_names()?;
136 parsed_extension_instruction_sets
137 .insert(extension_instruction_set, parsed_extension_instruction_set)
148 fn get_spirv_grammar_path<T: AsRef<Path>>(name: T) -> PathBuf {
149 Path::new(env!("CARGO_MANIFEST_DIR"))
150 .join("../external/SPIRV-Headers/include/spirv/unified1")
154 fn create_input(extension_instruction_sets: &[ExtensionInstructionSet]) -> Input {
155 let mut retval = Input::new(get_spirv_grammar_path("spirv.core.grammar.json"));
156 for &extension_instruction_set in extension_instruction_sets {
157 retval = retval.add_extension_instruction_set(
158 extension_instruction_set,
159 get_spirv_grammar_path(extension_instruction_set.get_grammar_json_file_name()),
166 fn parse_core_grammar() -> Result<(), Error> {
167 create_input(&[]).generate()?;
172 fn parse_core_grammar_with_opencl() -> Result<(), Error> {
173 create_input(&[ExtensionInstructionSet::OpenCLStd]).generate()?;
178 fn parse_core_grammar_with_opencl_and_glsl() -> Result<(), Error> {
180 ExtensionInstructionSet::OpenCLStd,
181 ExtensionInstructionSet::GLSLStd450,
188 fn parse_core_grammar_with_glsl() -> Result<(), Error> {
189 create_input(&[ExtensionInstructionSet::GLSLStd450]).generate()?;