Skip to content
Closed
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
22 changes: 18 additions & 4 deletions crates/grammar-parser/src/codegen/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use crate::codegen::{GrammarWriter, OPERAND_ID_RESULT, OPERAND_ID_RESULT_TYPE};
use crate::parse::{Grammar, InstMeta, Operand, Quantifier};
use quote::{format_ident, quote};

const OP_SWITCH: &str = "OpSwitch";
const OPERAND_PAIR_LITERAL_INTEGER_ID_REF: &str = "PairLiteralIntegerIdRef";

pub fn write_inst(writer: &mut GrammarWriter, grammar: &Grammar<'_>) -> anyhow::Result<()> {
let insts = grammar.insts.iter().map(|inst| {
let struct_ident = InstMeta::type_ident(&inst.opname);
Expand All @@ -25,10 +28,15 @@ pub fn write_inst(writer: &mut GrammarWriter, grammar: &Grammar<'_>) -> anyhow::
meta,
ref name,
ref ty,
}| match meta.quantifier {
Quantifier::One => quote!(pub #name: #ty),
Quantifier::ZeroOrOne => quote!(pub #name: ZeroOrOne<#ty>),
Quantifier::ZeroOrMore => quote!(pub #name: ZeroOrMore<#ty>),
}| {
if is_op_switch_targets(inst.opname.as_ref(), meta.kind.as_ref(), meta.quantifier) {
return quote!(pub #name: SwitchTargets);
}
match meta.quantifier {
Quantifier::One => quote!(pub #name: #ty),
Quantifier::ZeroOrOne => quote!(pub #name: ZeroOrOne<#ty>),
Quantifier::ZeroOrMore => quote!(pub #name: ZeroOrMore<#ty>),
}
},
);

Expand Down Expand Up @@ -157,6 +165,12 @@ pub fn write_inst(writer: &mut GrammarWriter, grammar: &Grammar<'_>) -> anyhow::
)
}

fn is_op_switch_targets(opname: &str, operand_kind: &str, quantifier: Quantifier) -> bool {
opname == OP_SWITCH
&& operand_kind == OPERAND_PAIR_LITERAL_INTEGER_ID_REF
&& quantifier == Quantifier::ZeroOrMore
}

pub fn write_inst_enum(
writer: &mut GrammarWriter,
grammar: &Grammar<'_>,
Expand Down
2 changes: 2 additions & 0 deletions crates/grammar-parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ pub mod timer;
#[cfg(feature = "codegen")]
pub mod codegen;

#[cfg(feature = "codegen")]
pub use proc_macro2;
#[cfg(feature = "codegen")]
pub use quote;
7 changes: 7 additions & 0 deletions crates/rspirv2-types/src/binary/decode_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ pub enum DecodeErrorKind {
op_len: usize,
expected_multiple: usize,
},
InvalidSwitchTargets {
word_len: usize,
},
InstructionTooLong {
op_len: usize,
module_remaining: usize,
Expand Down Expand Up @@ -111,6 +114,10 @@ impl Display for DecodeErrorKind {
"The variable-sized Instruction has an unexpected operand length {op_len} \
which was expected to be a multiple of {expected_multiple}."
),
Self::InvalidSwitchTargets { word_len } => write!(
f,
"OpSwitch target table has {word_len} words, which is neither valid 32-bit nor 64-bit case encoding."
),
Self::InstructionTooLong {
op_len,
module_remaining,
Expand Down
12 changes: 9 additions & 3 deletions crates/rspirv2-types/src/operand/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod literal_float;
mod literal_integer;
mod literal_string;
mod parameterized_bitmask;
mod switch;
mod tuple;

use crate::binary::{
Expand All @@ -20,6 +21,7 @@ pub use parameterized_bitmask::*;
use smallvec::SmallVec;
use std::fmt::{Debug, Display, Formatter};
use std::ops::Deref;
pub use switch::*;
pub use tuple::*;

/// A SPIR-V operand. The associated const [`Self::KIND`] links to it's [`OperandKind`].
Expand Down Expand Up @@ -126,10 +128,14 @@ pub unsafe trait OperandEncoding: Sized + Debug {
/// Disassemble this operand
///
/// Returns a type that impl [`Display`], so it's usable with `format!`:
/// ```no_run
/// # use rspirv2_types::operand::IdResult;
/// ```
/// # use rspirv2_types::Word;
/// # use rspirv2_types::dis::{DisContext, DisOptions};
/// # use rspirv2_types::operand::{IdResult, OperandDisContext, OperandEncoding};
/// let ctx = DisContext::no_context(DisOptions::simple());
/// let ctx = OperandDisContext::new(&ctx);
/// let my_op = IdResult(Word(42));
/// let dis = format!("OpMyInst {}", my_op.dis());
/// let dis = format!("OpMyInst {}", my_op.dis(&ctx));
/// assert_eq!(dis, "OpMyInst %42");
/// ```
#[inline]
Expand Down
Loading
Loading