Skip to content

Commit

Permalink
sr: Module and items
Browse files Browse the repository at this point in the history
  • Loading branch information
kvark committed Jul 17, 2019
1 parent 1403960 commit 4fe0937
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 92 deletions.
1 change: 1 addition & 0 deletions codegen/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
96 changes: 63 additions & 33 deletions codegen/sr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
2 changes: 1 addition & 1 deletion rspirv/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
125 changes: 70 additions & 55 deletions rspirv/sr/autogen_instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<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,
}
#[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<u32>,
},
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 {
Expand Down Expand Up @@ -48,40 +117,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,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<u32>,
},
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,
Expand Down Expand Up @@ -1162,10 +1181,6 @@ enum Instruction {
ModuleProcessed {
process: String,
},
ExecutionModeId {
entry_point: spirv::Word,
mode: spirv::ExecutionMode,
},
DecorateId {
target: spirv::Word,
decoration: spirv::Decoration,
Expand Down
8 changes: 7 additions & 1 deletion rspirv/sr/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand All @@ -31,13 +31,15 @@ pub struct Context {
/// All type objects.
types: Vec<Type>,
constants: Vec<Constant>,
instructions: Vec<Instruction>,
}

impl Context {
pub fn new() -> Self {
Context {
types: vec![],
constants: vec![],
instructions: vec![],
}
}
}
Expand All @@ -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 {
Expand Down
19 changes: 19 additions & 0 deletions rspirv/sr/instructions.rs
Original file line number Diff line number Diff line change
@@ -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");
Loading

0 comments on commit 4fe0937

Please sign in to comment.