From fcb59748e7d04bddabf1d5d4cf27639d287f7617 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 29 Jul 2019 09:56:46 -0400 Subject: [PATCH] sr: Turn some of the instructions into sesparate structs, add module types --- codegen/build.rs | 9 +- codegen/sr.rs | 94 +++++++++++++------ ...uction.rs => autogen_instruction_enums.rs} | 44 ++------- rspirv/sr/autogen_instruction_structs.rs | 63 +++++++++++++ rspirv/sr/instructions.rs | 3 + rspirv/sr/items.rs | 53 +++++++++++ rspirv/sr/mod.rs | 8 +- rspirv/sr/op.rs | 3 + 8 files changed, 205 insertions(+), 72 deletions(-) rename rspirv/sr/{autogen_instruction.rs => autogen_instruction_enums.rs} (97%) create mode 100644 rspirv/sr/autogen_instruction_structs.rs create mode 100644 rspirv/sr/instructions.rs create mode 100644 rspirv/sr/items.rs create mode 100644 rspirv/sr/op.rs diff --git a/codegen/build.rs b/codegen/build.rs index eb9ce2fa..bc373449 100644 --- a/codegen/build.rs +++ b/codegen/build.rs @@ -184,8 +184,13 @@ fn main() { &codegen_src_dir.join("../rspirv/sr/autogen_type_creation.rs"), sr::gen_sr_type_creation(&grammar), ); + let (inst_enums, inst_structs) = sr::gen_sr_instruction(&grammar); write_formatted( - &codegen_src_dir.join("../rspirv/sr/autogen_instruction.rs"), - sr::gen_sr_instruction(&grammar), + &codegen_src_dir.join("../rspirv/sr/autogen_instruction_enums.rs"), + inst_enums, + ); + write_formatted( + &codegen_src_dir.join("../rspirv/sr/autogen_instruction_structs.rs"), + inst_structs, ); } diff --git a/codegen/sr.rs b/codegen/sr.rs index f2e777aa..445cbb76 100644 --- a/codegen/sr.rs +++ b/codegen/sr.rs @@ -263,46 +263,78 @@ pub fn gen_sr_type_creation(grammar: &structs::Grammar) -> String { tokens.to_string() } -pub fn gen_sr_instruction(grammar: &structs::Grammar) -> String { +/// Generates instruction enums and standalone structs. +pub fn gen_sr_instruction(grammar: &structs::Grammar) -> (String, String) { + let mut structs = Vec::new(); + let mut terminators = Vec::new(); + let mut instructions = Vec::new(); + // Compose the token stream for all instructions - let insts: Vec<_> = grammar + for inst in grammar .instructions .iter() // Loop over all instructions .filter(|i| i.class != "Type") // Skip types .filter(|i| i.class != "Constant") // Skip constants - .map(|inst| { - // Get the token for its enumerant - let name = Ident::new(&inst.opname[2..], Span::call_site()); + { + // Get the token for its enumerant + let name = Ident::new(&inst.opname[2..], Span::call_site()); - // Compose the token stream for all parameters - let params: Vec<_> = inst.operands - .iter() // Loop over all parameters - .filter_map(|operand| { - if operand.kind.starts_with("IdResult") { - None - } else { - let field_name = get_operand_name_ident(operand); - let field_type = get_operand_type_sr_tokens(&operand.kind); - let quantified = get_quantified_type_tokens(field_type, &operand.quantifier); - Some(quote! { #field_name : #quantified }) - } - }).collect(); - let params = if params.is_empty() { - quote!{} - } else { - // Create a list parameter tokens separated by comma - quote! { {#( #params ),*} } - }; + // Compose the token stream for all parameters + let params: Vec<_> = inst.operands + .iter() // Loop over all parameters + .filter_map(|operand| { + if operand.kind.starts_with("IdResult") { + None + } else { + let field_name = get_operand_name_ident(operand); + let field_type = get_operand_type_sr_tokens(&operand.kind); + let quantified = get_quantified_type_tokens(field_type, &operand.quantifier); + Some(quote! { #field_name : #quantified }) + } + }).collect(); - // Get token stream for this enumerant - quote! { #name #params } - }).collect(); + match inst.class.as_str() { + "ModeSetting" | + "ExtensionDecl" | + "FunctionStruct" => { + // Create a standalone struct + structs.push(quote! { + #[derive(Clone, Debug, Eq, PartialEq)] + pub struct #name { + #( #params ),* + } + }) + } + "Terminator" => { + terminators.push(quote! { + #name {#( #params ),*} + }); + } + _ => { + let params = if params.is_empty() { + quote!{} + } else { + quote! { {#( #params ),*} } + }; + instructions.push(quote! { #name #params }); + } + } + } // Wrap it up with enum definition boilerplate - let insts = quote! { - enum Instruction { - #( #insts ),* + let structs = quote! { + #( #structs )* + }; + let enums = quote! { + #[derive(Clone, Debug, Eq, PartialEq)] + pub enum Terminator { + #( #terminators ),* + } + + #[derive(Clone, Debug, Eq, PartialEq)] + pub enum Instruction { + #( #instructions ),* } }; - insts.to_string() + (enums.to_string(), structs.to_string()) } diff --git a/rspirv/sr/autogen_instruction.rs b/rspirv/sr/autogen_instruction_enums.rs similarity index 97% rename from rspirv/sr/autogen_instruction.rs rename to rspirv/sr/autogen_instruction_enums.rs index ed30bc9a..1eda4b87 100644 --- a/rspirv/sr/autogen_instruction.rs +++ b/rspirv/sr/autogen_instruction_enums.rs @@ -16,7 +16,13 @@ // external/spirv.core.grammar.json. // DO NOT MODIFY! -enum Instruction { +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum Terminator { + Kill {}, + Unreachable {}, +} +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum Instruction { Nop, Undef, SourceContinued { @@ -48,40 +54,11 @@ enum Instruction { line: u32, column: u32, }, - Extension { - name: String, - }, - ExtInstImport { - name: String, - }, ExtInst { set: spirv::Word, instruction: u32, operands: Vec, }, - MemoryModel { - addressing_model: spirv::AddressingModel, - memory_model: spirv::MemoryModel, - }, - EntryPoint { - execution_model: spirv::ExecutionModel, - entry_point: spirv::Word, - name: String, - interface: Vec, - }, - ExecutionMode { - entry_point: spirv::Word, - mode: spirv::ExecutionMode, - }, - Capability { - capability: spirv::Capability, - }, - Function { - function_control: spirv::FunctionControl, - function_type: spirv::Word, - }, - FunctionParameter, - FunctionEnd, FunctionCall { function: spirv::Word, arguments: Vec, @@ -794,7 +771,6 @@ enum Instruction { merge_block: spirv::Word, selection_control: spirv::SelectionControl, }, - Label, Branch { target_label: spirv::Word, }, @@ -809,12 +785,10 @@ enum Instruction { default: spirv::Word, target: Vec<(u32, spirv::Word)>, }, - Kill, Return, ReturnValue { value: spirv::Word, }, - Unreachable, LifetimeStart { pointer: spirv::Word, size: u32, @@ -1162,10 +1136,6 @@ enum Instruction { ModuleProcessed { process: String, }, - ExecutionModeId { - entry_point: spirv::Word, - mode: spirv::ExecutionMode, - }, DecorateId { target: spirv::Word, decoration: spirv::Decoration, diff --git a/rspirv/sr/autogen_instruction_structs.rs b/rspirv/sr/autogen_instruction_structs.rs new file mode 100644 index 00000000..6be5ffa6 --- /dev/null +++ b/rspirv/sr/autogen_instruction_structs.rs @@ -0,0 +1,63 @@ +// Copyright 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// AUTOMATICALLY GENERATED from the SPIR-V JSON grammar: +// external/spirv.core.grammar.json. +// DO NOT MODIFY! + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Extension { + name: String, +} +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ExtInstImport { + name: String, +} +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct MemoryModel { + addressing_model: spirv::AddressingModel, + memory_model: spirv::MemoryModel, +} +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct EntryPoint { + execution_model: spirv::ExecutionModel, + entry_point: spirv::Word, + name: String, + interface: Vec, +} +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ExecutionMode { + entry_point: spirv::Word, + mode: spirv::ExecutionMode, +} +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Capability { + capability: spirv::Capability, +} +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Function { + function_control: spirv::FunctionControl, + function_type: spirv::Word, +} +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct FunctionParameter {} +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct FunctionEnd {} +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Label {} +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ExecutionModeId { + entry_point: spirv::Word, + mode: spirv::ExecutionMode, +} diff --git a/rspirv/sr/instructions.rs b/rspirv/sr/instructions.rs new file mode 100644 index 00000000..a93eb6a2 --- /dev/null +++ b/rspirv/sr/instructions.rs @@ -0,0 +1,3 @@ +use spirv; + +include!("autogen_instruction_enums.rs"); diff --git a/rspirv/sr/items.rs b/rspirv/sr/items.rs new file mode 100644 index 00000000..18d68154 --- /dev/null +++ b/rspirv/sr/items.rs @@ -0,0 +1,53 @@ +use crate::{ + mr::ModuleHeader, + sr::{op, Token}, + sr::instructions::Terminator, + sr::types::{Type}, +}; +use spirv; + +pub struct EntryPoint { + pub execution_model: spirv::ExecutionModel, + pub entry_point: Token, + pub name: String, + //pub interface: Vec, +} + +pub struct BasicBlock { + pub terminator: Terminator, +} + +pub struct Function { + pub control: spirv::FunctionControl, + /// Function result type. + pub result: Token, + /// Function parameters. + pub parameters: Vec>, + /// Basic blocks in this function. + pub basic_blocks: Vec, +} + +pub struct Module { + /// The module header. + pub header: Option, + /// All OpCapability instructions. + pub capabilities: Vec, + /// All OpExtension instructions. + pub extensions: Vec, + /// All OpExtInstImport instructions. + pub ext_inst_imports: Vec, + /// The OpMemoryModel instruction. + /// + /// Although it is required by the specification to appear exactly once + /// per module, we keep it optional here to allow flexibility. + pub memory_model: Option, + /// All entry point declarations, using OpEntryPoint. + pub entry_points: Vec, + /// All execution mode declarations, using OpExecutionMode. + pub execution_modes: Vec, + + // some missing here... + + /// All functions. + pub functions: Vec, +} diff --git a/rspirv/sr/mod.rs b/rspirv/sr/mod.rs index ad3d45d3..8f0f49eb 100644 --- a/rspirv/sr/mod.rs +++ b/rspirv/sr/mod.rs @@ -14,12 +14,16 @@ //! **S**tructured **r**epresentation of various SPIR-V language constructs. +pub use self::autogen_decoration::Decoration; pub use self::constants::{Constant}; pub use self::context::{Context, Token}; -pub use self::autogen_decoration::Decoration; +pub use self::instructions::{Instruction, Terminator}; pub use self::types::{Type}; +mod autogen_decoration; mod constants; mod context; -mod autogen_decoration; +mod instructions; +pub mod items; +pub mod op; mod types; diff --git a/rspirv/sr/op.rs b/rspirv/sr/op.rs new file mode 100644 index 00000000..2ea09377 --- /dev/null +++ b/rspirv/sr/op.rs @@ -0,0 +1,3 @@ +use spirv; + +include!("autogen_instruction_structs.rs");