Skip to content
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
61 changes: 59 additions & 2 deletions autogen/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,16 +291,42 @@ pub fn gen_spirv_header(grammar: &structs::Grammar) -> TokenStream {
// Use associated constants for these aliases.
let mut aliases = vec![];
let mut variants = vec![];
let mut types = vec![];
let mut constants = vec![];
let mut annotations = vec![];
let mut debugs = vec![];
let mut control_flows = vec![];

// Get the instruction table.
for inst in &grammar.instructions {
let opname = as_ident(inst.opname.strip_prefix("Op").unwrap());
let opcode = inst.opcode;
variants.push((opcode, opname.clone()));

let opname = quote!(Self::#opname);
for alias in &inst.aliases {
let alias = as_ident(alias.strip_prefix("Op").unwrap());
aliases.push(quote! { pub const #alias: Op = Op::#opname; });
aliases.push(quote! { pub const #alias: Self = #opname; });
}

match inst.class {
Some(structs::Class::Type) => {
types.push(opname);
}
Some(structs::Class::Constant) => {
constants.push(opname);
}
Some(structs::Class::Annotation) => {
annotations.push(opname);
}
Some(structs::Class::Debug) => {
debugs.push(opname);
}
Some(structs::Class::Branch) => {
control_flows.push(opname);
}
_ => {}
}
variants.push((opcode, opname.clone()));
}

let the_enum = generate_enum(
Expand All @@ -325,6 +351,37 @@ pub fn gen_spirv_header(grammar: &structs::Grammar) -> TokenStream {
#[allow(non_upper_case_globals)]
impl Op {
#(#aliases)*

/// Returns [`true`] if the given opcode is a type-declaring instruction.
///
/// <https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_type_declaration_instructions>
pub fn is_type(self) -> bool {
matches!(self, #(#types)|*)
}
/// Returns [`true`] if the given opcode is a constant-defining instruction.
///
/// <https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_constant_creation_instructions>
pub fn is_constant(self) -> bool {
matches!(self, #(#constants)|*)
}
/// Returns [`true`] if the given opcode is an annotation instruction.
///
/// <https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Annotation>
pub fn is_annotation(self) -> bool {
matches!(self, #(#annotations)|*)
}
/// Returns [`true`] if the given opcode is a debug instruction.
///
/// <https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_debug_instructions>
pub fn is_debug(self) -> bool {
matches!(self, #(#debugs)|*)
}
/// Returns [`true`] if the given opcode is a control-flow instruction.
///
/// <https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_control_flow_instructions>
pub fn is_control_flow(self) -> bool {
matches!(self, #(#control_flows)|*)
}
}
}
}
Expand Down
1 change: 0 additions & 1 deletion autogen/src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ pub enum Class {
#[serde(rename = "Constant-Creation")]
Constant,
Debug,
DebugLine,
#[serde(rename = "Extension")]
ExtensionDecl,
#[serde(rename = "Function")]
Expand Down
2 changes: 1 addition & 1 deletion rspirv/binary/tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl TypeTracker {

pub fn track(&mut self, inst: &dr::Instruction) {
if let Some(rid) = inst.result_id {
if grammar::reflect::is_type(inst.class.opcode) {
if inst.class.opcode.is_type() {
match inst.class.opcode {
spirv::Op::TypeInt => {
if let (
Expand Down
6 changes: 2 additions & 4 deletions rspirv/dr/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,8 @@ impl binary::Consumer for Loader {
None => self.module.types_global_values.push(inst),
}
}
opcode if grammar::reflect::is_annotation(opcode) => self.module.annotations.push(inst),
opcode
if grammar::reflect::is_type(opcode) || grammar::reflect::is_constant(opcode) =>
{
opcode if opcode.is_annotation() => self.module.annotations.push(inst),
opcode if opcode.is_type() || opcode.is_constant() => {
self.module.types_global_values.push(inst)
}
spirv::Op::Variable if self.function.is_none() => {
Expand Down
104 changes: 13 additions & 91 deletions rspirv/grammar/reflect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,105 +2,22 @@

use crate::spirv;

/// Returns true if the given opcode is for a location debug instruction.
/// Returns [`true`] if the given opcode is for a location debug instruction.
pub fn is_location_debug(opcode: spirv::Op) -> bool {
matches!(opcode, spirv::Op::Line | spirv::Op::NoLine)
}

/// Returns true if the given opcode is for a non-location debug instruction.
pub fn is_nonlocation_debug(opcode: spirv::Op) -> bool {
matches!(
opcode,
spirv::Op::SourceContinued
| spirv::Op::Source
| spirv::Op::SourceExtension
| spirv::Op::Name
| spirv::Op::MemberName
| spirv::Op::String
)
}

/// Returns true if the given opcode is for a debug instruction.
pub fn is_debug(opcode: spirv::Op) -> bool {
is_location_debug(opcode) || is_nonlocation_debug(opcode)
}

/// Returns true if the given opcode is for an annotation instruction.
pub fn is_annotation(opcode: spirv::Op) -> bool {
matches!(
opcode,
spirv::Op::Decorate
| spirv::Op::MemberDecorate
| spirv::Op::DecorationGroup
| spirv::Op::GroupDecorate
| spirv::Op::GroupMemberDecorate
| spirv::Op::DecorateString
| spirv::Op::MemberDecorateStringGOOGLE
)
}

/// Returns true if the given opcode is for a type-declaring instruction.
pub fn is_type(opcode: spirv::Op) -> bool {
matches!(
opcode,
spirv::Op::TypeVoid
| spirv::Op::TypeBool
| spirv::Op::TypeInt
| spirv::Op::TypeFloat
| spirv::Op::TypeVector
| spirv::Op::TypeMatrix
| spirv::Op::TypeImage
| spirv::Op::TypeSampler
| spirv::Op::TypeSampledImage
| spirv::Op::TypeArray
| spirv::Op::TypeRuntimeArray
| spirv::Op::TypeStruct
| spirv::Op::TypeOpaque
| spirv::Op::TypePointer
| spirv::Op::TypeFunction
| spirv::Op::TypeEvent
| spirv::Op::TypeDeviceEvent
| spirv::Op::TypeReserveId
| spirv::Op::TypeQueue
| spirv::Op::TypePipe
| spirv::Op::TypeAccelerationStructureKHR
| spirv::Op::TypeRayQueryKHR
| spirv::Op::TypeForwardPointer
| spirv::Op::TypeCooperativeMatrixKHR
)
}

/// Returns true if the given opcode is for a constant-defining instruction.
pub fn is_constant(opcode: spirv::Op) -> bool {
matches!(
opcode,
spirv::Op::ConstantTrue
| spirv::Op::ConstantFalse
| spirv::Op::Constant
| spirv::Op::ConstantComposite
| spirv::Op::ConstantSampler
| spirv::Op::ConstantNull
| spirv::Op::SpecConstantTrue
| spirv::Op::SpecConstantFalse
| spirv::Op::SpecConstant
| spirv::Op::SpecConstantComposite
| spirv::Op::SpecConstantOp
| spirv::Op::ConstantCompositeContinuedINTEL
| spirv::Op::SpecConstantCompositeContinuedINTEL
)
}

/// Returns true if the given opcode is for a variable-defining instruction.
/// Returns [`true`] if the given opcode is for a variable-defining instruction.
pub fn is_variable(opcode: spirv::Op) -> bool {
opcode == spirv::Op::Variable
}

/// Returns true if the given opcode is a return instruction.
/// Returns [`true`] if the given opcode is a return instruction.
pub fn is_return(opcode: spirv::Op) -> bool {
matches!(opcode, spirv::Op::Return | spirv::Op::ReturnValue)
}

/// Returns true if the given opcode aborts execution.
/// Returns [`true`] if the given opcode aborts execution.
pub fn is_abort(opcode: spirv::Op) -> bool {
matches!(
opcode,
Expand All @@ -113,21 +30,26 @@ pub fn is_abort(opcode: spirv::Op) -> bool {
)
}

/// Returns true if the given opcode is a return instruction or it aborts
/// execution.
/// Returns [`true`] if the given opcode is a return instruction or it aborts execution.
///
/// <https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#FunctionTermination>
pub fn is_return_or_abort(opcode: spirv::Op) -> bool {
is_return(opcode) || is_abort(opcode)
}

/// Returns true if the given opcode is a branch instruction.
/// Returns [`true`] if the given opcode is a branch instruction.
///
/// <https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Branch> and <https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#ConditionalBranch>
pub fn is_branch(opcode: spirv::Op) -> bool {
matches!(
opcode,
spirv::Op::Branch | spirv::Op::BranchConditional | spirv::Op::Switch
)
}

/// Returns true if the given opcode is for a terminator instruction.
/// Returns [`true`] if the given opcode is for a terminator instruction.
///
/// <https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Termination>
pub fn is_block_terminator(opcode: spirv::Op) -> bool {
is_branch(opcode) || is_return_or_abort(opcode)
}
Loading
Loading