Skip to content

Commit

Permalink
sr: Turn some of the instructions into sesparate structs, add module …
Browse files Browse the repository at this point in the history
…types
  • Loading branch information
kvark committed Jul 30, 2019
1 parent e186b0d commit fcb5974
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 72 deletions.
9 changes: 7 additions & 2 deletions codegen/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
);
}
94 changes: 63 additions & 31 deletions codegen/sr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -48,40 +54,11 @@ enum Instruction {
line: u32,
column: u32,
},
Extension {
name: String,
},
ExtInstImport {
name: String,
},
ExtInst {
set: spirv::Word,
instruction: u32,
operands: Vec<spirv::Word>,
},
MemoryModel {
addressing_model: spirv::AddressingModel,
memory_model: spirv::MemoryModel,
},
EntryPoint {
execution_model: spirv::ExecutionModel,
entry_point: spirv::Word,
name: String,
interface: Vec<spirv::Word>,
},
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<spirv::Word>,
Expand Down Expand Up @@ -794,7 +771,6 @@ enum Instruction {
merge_block: spirv::Word,
selection_control: spirv::SelectionControl,
},
Label,
Branch {
target_label: spirv::Word,
},
Expand All @@ -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,
Expand Down Expand Up @@ -1162,10 +1136,6 @@ enum Instruction {
ModuleProcessed {
process: String,
},
ExecutionModeId {
entry_point: spirv::Word,
mode: spirv::ExecutionMode,
},
DecorateId {
target: spirv::Word,
decoration: spirv::Decoration,
Expand Down
63 changes: 63 additions & 0 deletions rspirv/sr/autogen_instruction_structs.rs
Original file line number Diff line number Diff line change
@@ -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<spirv::Word>,
}
#[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,
}
3 changes: 3 additions & 0 deletions rspirv/sr/instructions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use spirv;

include!("autogen_instruction_enums.rs");
53 changes: 53 additions & 0 deletions rspirv/sr/items.rs
Original file line number Diff line number Diff line change
@@ -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<Function>,
pub name: String,
//pub interface: Vec<spirv::Word>,
}

pub struct BasicBlock {
pub terminator: Terminator,
}

pub struct Function {
pub control: spirv::FunctionControl,
/// Function result type.
pub result: Token<Type>,
/// Function parameters.
pub parameters: Vec<Token<Type>>,
/// Basic blocks in this function.
pub basic_blocks: Vec<BasicBlock>,
}

pub struct Module {
/// The module header.
pub header: Option<ModuleHeader>,
/// All OpCapability instructions.
pub capabilities: Vec<op::Capability>,
/// All OpExtension instructions.
pub extensions: Vec<op::Extension>,
/// All OpExtInstImport instructions.
pub ext_inst_imports: Vec<op::ExtInstImport>,
/// 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<op::MemoryModel>,
/// All entry point declarations, using OpEntryPoint.
pub entry_points: Vec<op::EntryPoint>,
/// All execution mode declarations, using OpExecutionMode.
pub execution_modes: Vec<op::ExecutionMode>,

// some missing here...

/// All functions.
pub functions: Vec<Function>,
}
8 changes: 6 additions & 2 deletions rspirv/sr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
3 changes: 3 additions & 0 deletions rspirv/sr/op.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use spirv;

include!("autogen_instruction_structs.rs");

0 comments on commit fcb5974

Please sign in to comment.