diff --git a/gen/src/lib.rs b/gen/src/lib.rs index 30e4595..3ab5e43 100644 --- a/gen/src/lib.rs +++ b/gen/src/lib.rs @@ -55,6 +55,7 @@ impl OpcodeDefinitions { let candidate = if let DotModifierRef::Direct { optional: false, value, + .. } = candidate { value @@ -227,11 +228,13 @@ impl SingleOpcodeDefinition { DotModifierRef::Direct { optional, value: alts.alternatives[0].clone(), + name: modifier, } } else { DotModifierRef::Indirect { optional, value: alts.clone(), + name: modifier, } } } @@ -239,7 +242,8 @@ impl SingleOpcodeDefinition { possible_modifiers.insert(modifier.clone()); DotModifierRef::Direct { optional, - value: modifier, + value: modifier.clone(), + name: modifier, } } }, @@ -306,8 +310,9 @@ pub fn derive_parser(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream }) .collect::>(); let mut token_enum = parse_definitions.token_type; - let (_, all_modifier) = write_definitions_into_tokens(&definitions, &mut token_enum.variants); - let token_impl = emit_parse_function(&token_enum.ident, &definitions, all_modifier); + let (all_opcode, all_modifier) = + write_definitions_into_tokens(&definitions, &mut token_enum.variants); + let token_impl = emit_parse_function(&token_enum.ident, &definitions, all_opcode, all_modifier); let tokens = quote! { #enum_types_tokens @@ -364,6 +369,7 @@ fn emit_enum_types( fn emit_parse_function( type_name: &Ident, defs: &FxHashMap, + all_opcode: Vec<&Ident>, all_modifier: FxHashSet<&parser::DotModifier>, ) -> TokenStream { use std::fmt::Write; @@ -437,9 +443,24 @@ fn emit_parse_function( .to_tokens(&mut result); result }); + let opcodes = all_opcode.into_iter().map(|op_ident| { + let op = op_ident.to_string(); + let variant = Ident::new(&capitalize(&op), op_ident.span()); + let value = op; + quote! { + #type_name :: #variant => Some(#value), + } + }); let modifier_names = all_modifier.iter().map(|m| m.dot_capitalized()); quote! { impl<'input> #type_name<'input> { + fn opcode_text(self) -> Option<&'static str> { + match self { + #(#opcodes)* + _ => None + } + } + fn modifier(self) -> bool { match self { #( @@ -452,7 +473,7 @@ fn emit_parse_function( #(#fns_)* - fn parse_instruction<'a, 'input>(stream: &mut ParserState<'a, 'input>) -> winnow::error::PResult>> + fn parse_instruction<'a, 'input>(stream: &mut ParserState<'a, 'input>) -> winnow::error::PResult>> { use winnow::Parser; use winnow::token::*; @@ -490,9 +511,8 @@ fn emit_definition_parser( }); let ordered_parse = definition.ordered_modifiers.iter().rev().map(|modifier| { let arg_name = modifier.ident(); - let arg_type = modifier.type_of(); match modifier { - DotModifierRef::Direct { optional, value } => { + DotModifierRef::Direct { optional, value, .. } => { let variant = value.dot_capitalized(); if *optional { quote! { @@ -504,7 +524,7 @@ fn emit_definition_parser( } } } - DotModifierRef::Indirect { optional, value } => { + DotModifierRef::Indirect { optional, value, .. } => { let variants = value.alternatives.iter().map(|alt| { let type_ = value.type_.as_ref().unwrap(); let token_variant = alt.dot_capitalized(); @@ -546,8 +566,8 @@ fn emit_definition_parser( .unordered_modifiers .iter() .map(|modifier| match modifier { - DotModifierRef::Direct { value, .. } => { - let name = value.ident(); + DotModifierRef::Direct { name, value, .. } => { + let name = name.ident(); let token_variant = value.dot_capitalized(); quote! { #token_type :: #token_variant => { @@ -558,8 +578,8 @@ fn emit_definition_parser( } } } - DotModifierRef::Indirect { value, .. } => { - let variable = value.modifier.ident(); + DotModifierRef::Indirect { value, name, .. } => { + let variable = name.ident(); let type_ = value.type_.as_ref().unwrap(); let alternatives = value.alternatives.iter().map(|alt| { let token_variant = alt.dot_capitalized(); @@ -585,9 +605,10 @@ fn emit_definition_parser( .map(|modifier| match modifier { DotModifierRef::Direct { optional: false, - value, + name, + .. } => { - let variable = value.ident(); + let variable = name.ident(); quote! { if !#variable { #return_error; @@ -597,9 +618,10 @@ fn emit_definition_parser( DotModifierRef::Direct { optional: true, .. } => TokenStream::new(), DotModifierRef::Indirect { optional: false, - value, + name, + .. } => { - let variable = value.modifier.ident(); + let variable = name.ident(); quote! { let #variable = match #variable { Some(x) => x, @@ -749,9 +771,11 @@ enum DotModifierRef { Direct { optional: bool, value: parser::DotModifier, + name: parser::DotModifier, }, Indirect { optional: bool, + name: parser::DotModifier, value: Rc, }, } @@ -759,8 +783,8 @@ enum DotModifierRef { impl DotModifierRef { fn ident(&self) -> Ident { match self { - DotModifierRef::Direct { value, .. } => value.ident(), - DotModifierRef::Indirect { value, .. } => value.modifier.ident(), + DotModifierRef::Direct { name, .. } => name.ident(), + DotModifierRef::Indirect { name, .. } => name.ident(), } } @@ -770,7 +794,9 @@ impl DotModifierRef { DotModifierRef::Direct { optional: false, .. } => return None, - DotModifierRef::Indirect { optional, value } => { + DotModifierRef::Indirect { + optional, value, .. + } => { let type_ = value .type_ .as_ref() @@ -798,55 +824,6 @@ impl DotModifierRef { } } -impl Hash for DotModifierRef { - fn hash(&self, state: &mut H) { - match self { - DotModifierRef::Direct { optional, value } => { - optional.hash(state); - value.hash(state); - } - DotModifierRef::Indirect { optional, value } => { - optional.hash(state); - (value.as_ref() as *const parser::Rule).hash(state); - } - } - } -} - -impl PartialEq for DotModifierRef { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - ( - Self::Direct { - optional: l_optional, - value: l_value, - }, - Self::Direct { - optional: r_optional, - value: r_value, - }, - ) => l_optional == r_optional && l_value == r_value, - ( - Self::Indirect { - optional: l_optional, - value: l_value, - }, - Self::Indirect { - optional: r_optional, - value: r_value, - }, - ) => { - l_optional == r_optional - && l_value.as_ref() as *const parser::Rule - == r_value.as_ref() as *const parser::Rule - } - _ => false, - } - } -} - -impl Eq for DotModifierRef {} - #[proc_macro] pub fn generate_instruction_type(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = parse_macro_input!(tokens as gen_impl::GenerateInstructionType); diff --git a/gen_impl/src/parser.rs b/gen_impl/src/parser.rs index c8da61d..b57d6ec 100644 --- a/gen_impl/src/parser.rs +++ b/gen_impl/src/parser.rs @@ -7,6 +7,7 @@ use std::fmt::Write; use syn::bracketed; use syn::parse::Peek; use syn::punctuated::Punctuated; +use syn::spanned::Spanned; use syn::LitInt; use syn::Type; use syn::{braced, parse::Parse, token, Ident, ItemEnum, Token}; @@ -155,6 +156,10 @@ impl Rule { struct IdentOrTypeSuffix(IdentLike); impl IdentOrTypeSuffix { + fn span(&self) -> Span { + self.0.span() + } + fn peek(input: syn::parse::ParseStream) -> bool { input.peek(Token![::]) } @@ -278,6 +283,15 @@ impl std::fmt::Debug for DotModifier { } impl DotModifier { + pub fn span(&self) -> Span { + let part1 = self.part1.span(); + if let Some(ref part2) = self.part2 { + part1.join(part2.span()).unwrap_or(part1) + } else { + part1 + } + } + pub fn ident(&self) -> Ident { let mut result = String::new(); write!(&mut result, "{}", self.part1).unwrap(); @@ -285,11 +299,11 @@ impl DotModifier { write!(&mut result, "_{}", part2.0).unwrap(); } else { match self.part1 { - IdentLike::Type | IdentLike::Const => result.push('_'), + IdentLike::Type(_) | IdentLike::Const(_) => result.push('_'), IdentLike::Ident(_) | IdentLike::Integer(_) => {} } } - Ident::new(&result.to_ascii_lowercase(), Span::call_site()) + Ident::new(&result.to_ascii_lowercase(), self.span()) } pub fn variant_capitalized(&self) -> Ident { @@ -321,7 +335,7 @@ impl DotModifier { }; result.push(c); } - Ident::new(&result, Span::call_site()) + Ident::new(&result, self.span()) } pub fn tokens(&self) -> TokenStream { @@ -353,17 +367,28 @@ impl Parse for DotModifier { #[derive(PartialEq, Eq, Hash, Clone)] enum IdentLike { - Type, - Const, + Type(Token![type]), + Const(Token![const]), Ident(Ident), Integer(LitInt), } +impl IdentLike { + fn span(&self) -> Span { + match self { + IdentLike::Type(c) => c.span(), + IdentLike::Const(t) => t.span(), + IdentLike::Ident(i) => i.span(), + IdentLike::Integer(l) => l.span(), + } + } +} + impl std::fmt::Display for IdentLike { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - IdentLike::Type => f.write_str("type"), - IdentLike::Const => f.write_str("const"), + IdentLike::Type(_) => f.write_str("type"), + IdentLike::Const(_) => f.write_str("const"), IdentLike::Ident(ident) => write!(f, "{}", ident), IdentLike::Integer(integer) => write!(f, "{}", integer), } @@ -373,8 +398,8 @@ impl std::fmt::Display for IdentLike { impl ToTokens for IdentLike { fn to_tokens(&self, tokens: &mut TokenStream) { match self { - IdentLike::Type => quote! { type }.to_tokens(tokens), - IdentLike::Const => quote! { const }.to_tokens(tokens), + IdentLike::Type(_) => quote! { type }.to_tokens(tokens), + IdentLike::Const(_) => quote! { const }.to_tokens(tokens), IdentLike::Ident(ident) => quote! { #ident }.to_tokens(tokens), IdentLike::Integer(int) => quote! { #int }.to_tokens(tokens), } @@ -385,11 +410,9 @@ impl Parse for IdentLike { fn parse(input: syn::parse::ParseStream) -> syn::Result { let lookahead = input.lookahead1(); Ok(if lookahead.peek(Token![const]) { - input.parse::()?; - IdentLike::Const + IdentLike::Const(input.parse::()?) } else if lookahead.peek(Token![type]) { - input.parse::()?; - IdentLike::Type + IdentLike::Type(input.parse::()?) } else if lookahead.peek(Ident) { IdentLike::Ident(input.parse::()?) } else if lookahead.peek(LitInt) { diff --git a/ptx_parser/src/main.rs b/ptx_parser/src/main.rs index 4f3ed41..96f08b6 100644 --- a/ptx_parser/src/main.rs +++ b/ptx_parser/src/main.rs @@ -2,9 +2,8 @@ use gen::derive_parser; use logos::Logos; use std::mem; use std::num::{ParseFloatError, ParseIntError}; -use winnow::combinator::{alt, empty, fail, opt}; -use winnow::stream::SliceLen; -use winnow::token::{any, literal}; +use winnow::combinator::*; +use winnow::token::any; use winnow::{ error::{ContextError, ParserError}, stream::{Offset, Stream, StreamIsPartial}, @@ -206,6 +205,8 @@ fn ident<'a, 'input>(stream: &mut ParserState<'a, 'input>) -> PResult<&'input st any.verify_map(|t| { if let Token::Ident(text) = t { Some(text) + } else if let Some(text) = t.opcode_text() { + Some(text) } else { None } @@ -563,7 +564,6 @@ derive_parser!( pub enum ScalarType { } // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-mov - mov.type d, a => { Instruction::Mov{ data: MovDetails::new(type_.into()),