From 4fe0937f7aa85c6b767986fadd8a8dbfd3f12828 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 15 Jul 2019 21:23:47 -0400 Subject: [PATCH] sr: Module and items --- codegen/build.rs | 1 + codegen/sr.rs | 96 ++++++++++++++++-------- rspirv/lib.rs | 2 +- rspirv/sr/autogen_instruction.rs | 125 +++++++++++++++++-------------- rspirv/sr/context.rs | 8 +- rspirv/sr/instructions.rs | 19 +++++ rspirv/sr/items.rs | 57 ++++++++++++++ rspirv/sr/mod.rs | 8 +- 8 files changed, 224 insertions(+), 92 deletions(-) create mode 100644 rspirv/sr/instructions.rs create mode 100644 rspirv/sr/items.rs diff --git a/codegen/build.rs b/codegen/build.rs index 337445b4..2ee3850d 100644 --- a/codegen/build.rs +++ b/codegen/build.rs @@ -217,6 +217,7 @@ fn main() { fmt_write!(c, path); } { + //TODO: move items into a separate source let path = codegen_src_dir.join("../rspirv/sr/autogen_instruction.rs"); let c = sr::gen_sr_instruction(&grammar); fmt_write!(c, path); diff --git a/codegen/sr.rs b/codegen/sr.rs index 73f9812b..bc9fb05e 100644 --- a/codegen/sr.rs +++ b/codegen/sr.rs @@ -281,50 +281,80 @@ pub fn gen_sr_type_creation(grammar: &structs::Grammar) -> String { } pub fn gen_sr_instruction(grammar: &structs::Grammar) -> 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 + // 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_sr_tokens(operand); + let field_type = get_operand_type_sr_tokens(&operand.kind); + if operand.quantifier == "" { + Some(quote! { #field_name : #field_type }) + } else if operand.quantifier == "?" { + Some(quote! { #field_name : Option<#field_type> }) } else { - let field_name = get_operand_name_sr_tokens(operand); - let field_type = get_operand_type_sr_tokens(&operand.kind); - if operand.quantifier == "" { - Some(quote! { #field_name : #field_type }) - } else if operand.quantifier == "?" { - Some(quote! { #field_name : Option<#field_type> }) - } else { - Some(quote! { #field_name : Vec<#field_type> }) - } + Some(quote! { #field_name : Vec<#field_type> }) } - }).collect(); - let params = if params.is_empty() { - quote!{} - } else { - // Create a list parameter tokens separated by comma - quote! { {#( #params ),*} } - }; + } + }).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 all = quote! { + #( #structs )* + + #[derive(Clone, Debug, Eq, PartialEq)] + pub enum Terminator { + #( #terminators ),* + } + + #[derive(Clone, Debug, Eq, PartialEq)] + pub enum Instruction { + #( #instructions ),* } }; - insts.to_string() + all.to_string() } diff --git a/rspirv/lib.rs b/rspirv/lib.rs index cd10a7d5..5ae11477 100644 --- a/rspirv/lib.rs +++ b/rspirv/lib.rs @@ -103,7 +103,7 @@ extern crate assert_matches; #[macro_use] extern crate derive_more; extern crate num; -extern crate spirv_headers as spirv; +pub extern crate spirv_headers as spirv; pub mod binary; pub mod grammar; diff --git a/rspirv/sr/autogen_instruction.rs b/rspirv/sr/autogen_instruction.rs index ed30bc9a..97a4fb82 100644 --- a/rspirv/sr/autogen_instruction.rs +++ b/rspirv/sr/autogen_instruction.rs @@ -16,7 +16,76 @@ // external/spirv.core.grammar.json. // DO NOT MODIFY! -enum Instruction { +#[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, +} +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum Terminator { + Branch { + target_label: spirv::Word, + }, + BranchConditional { + condition: spirv::Word, + true_label: spirv::Word, + false_label: spirv::Word, + branch_weights: Vec, + }, + Switch { + selector: spirv::Word, + default: spirv::Word, + target: Vec<(u32, spirv::Word)>, + }, + Kill {}, + Return {}, + ReturnValue { + value: spirv::Word, + }, + Unreachable {}, +} +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum Instruction { Nop, Undef, SourceContinued { @@ -48,40 +117,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,27 +834,6 @@ enum Instruction { merge_block: spirv::Word, selection_control: spirv::SelectionControl, }, - Label, - Branch { - target_label: spirv::Word, - }, - BranchConditional { - condition: spirv::Word, - true_label: spirv::Word, - false_label: spirv::Word, - branch_weights: Vec, - }, - Switch { - selector: spirv::Word, - default: spirv::Word, - target: Vec<(u32, spirv::Word)>, - }, - Kill, - Return, - ReturnValue { - value: spirv::Word, - }, - Unreachable, LifetimeStart { pointer: spirv::Word, size: u32, @@ -1162,10 +1181,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/context.rs b/rspirv/sr/context.rs index c5c13c7a..bb7d6e2d 100644 --- a/rspirv/sr/context.rs +++ b/rspirv/sr/context.rs @@ -14,7 +14,7 @@ use spirv; -use super::{Type, TypeToken, Constant, ConstantToken}; +use super::{Type, TypeToken, Constant, ConstantToken, Instruction, InstructionToken}; use sr::constants::ConstantEnum; use sr::types::{StructMember, TypeEnum}; @@ -31,6 +31,7 @@ pub struct Context { /// All type objects. types: Vec, constants: Vec, + instructions: Vec, } impl Context { @@ -38,6 +39,7 @@ impl Context { Context { types: vec![], constants: vec![], + instructions: vec![], } } } @@ -64,6 +66,10 @@ impl Context { // Note: we assume the vector doesn't shrink so we always have a valid index. &self.types[token.get()] } + + pub fn get_instruction(&self, token: InstructionToken) -> &Instruction { + &self.instructions[token.get()] + } } macro_rules! fetch_or_append { diff --git a/rspirv/sr/instructions.rs b/rspirv/sr/instructions.rs new file mode 100644 index 00000000..1e92949a --- /dev/null +++ b/rspirv/sr/instructions.rs @@ -0,0 +1,19 @@ +use spirv; + +/// A token for representing a SPIR-V instruction. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct InstructionToken { + index: usize, +} + +impl InstructionToken { + pub fn new(index: usize) -> Self { + InstructionToken { index: index } + } + + pub fn get(&self) -> usize { + self.index + } +} + +include!("autogen_instruction.rs"); diff --git a/rspirv/sr/items.rs b/rspirv/sr/items.rs new file mode 100644 index 00000000..76f5fbf8 --- /dev/null +++ b/rspirv/sr/items.rs @@ -0,0 +1,57 @@ +use crate::{ + mr::ModuleHeader, + spirv, + sr::TypeToken, +}; +use super::instructions as inst; + +pub struct EntryPoint { + pub execution_model: spirv::ExecutionModel, + pub entry_point: FunctionToken, + pub name: String, + //pub interface: Vec, +} + +pub struct BasicBlock { + //line: Line, + terminator: inst::Terminator, +} + +pub struct Function { + pub control: spirv::FunctionControl, + /// Function result type. + pub result: TypeToken, + /// Function parameters. + pub parameters: Vec, + /// Basic blocks in this function. + pub basic_blocks: Vec, +} + +pub struct FunctionToken { + index: usize, +} + +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 74ce58f8..9701739c 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, ConstantToken}; pub use self::context::Context; -pub use self::autogen_decoration::Decoration; +pub use self::instructions::{Instruction, InstructionToken}; +pub use self::items::Module; pub use self::types::{Type, TypeToken}; +mod autogen_decoration; mod constants; mod context; -mod autogen_decoration; +mod instructions; +mod items; mod types;