Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Structured module items #63

Merged
merged 1 commit into from
Aug 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still want to have separate ops for these function components? I think they should be folded into the function SR itself. I mean, FunctionEnd is useful for marking the end of a function in SPIR-V binary, but not useful for SR. Similarly for Label, it should be implicit for BasicBlock SR. Letting each pass processing Function or BasicBlock to worry about FunctionEnd and Label is not helpful.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, we'll need to set up a list of ops that don't need SR autogen generation, and which we are going to be converting to and from DR manually. We'll do it as a follow-up.

#[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");
54 changes: 54 additions & 0 deletions rspirv/sr/items.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use crate::{
mr::ModuleHeader,
sr::{op, Token},
sr::instructions::{Instruction, 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 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the Vector for instructions?

pub terminator: Terminator,
pub instructions: Vec<Instruction>,
}

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: 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: 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");