diff --git a/ptx_parser/src/ast.rs b/ptx_parser/src/ast.rs index ee9f968..5175b2d 100644 --- a/ptx_parser/src/ast.rs +++ b/ptx_parser/src/ast.rs @@ -27,7 +27,10 @@ ptx_parser_macros::generate_instruction_type!( type: { &data.typ }, data: LdDetails, arguments: { - dst: T, + dst: { + repr: T, + relaxed_type_check: true, + }, src: { repr: T, space: { data.state_space }, @@ -51,7 +54,10 @@ ptx_parser_macros::generate_instruction_type!( repr: T, space: { data.state_space }, }, - src2: T, + src2: { + repr: T, + relaxed_type_check: true, + } } }, Mul { @@ -157,10 +163,13 @@ ptx_parser_macros::generate_instruction_type!( dst: { repr: T, type: { Type::Scalar(data.to) }, + // TODO: double check + relaxed_type_check: true, }, src: { repr: T, type: { Type::Scalar(data.from) }, + relaxed_type_check: true, }, } }, @@ -494,16 +503,18 @@ pub trait Visitor { args: &T, type_space: Option<(&Type, StateSpace)>, is_dst: bool, + relaxed_type_check: bool, ) -> Result<(), Err>; fn visit_ident( &mut self, args: &T::Ident, type_space: Option<(&Type, StateSpace)>, is_dst: bool, + relaxed_type_check: bool, ) -> Result<(), Err>; } -impl, bool) -> Result<(), Err>> +impl, bool, bool) -> Result<(), Err>> Visitor for Fn { fn visit( @@ -511,8 +522,9 @@ impl, bool) -> Result args: &T, type_space: Option<(&Type, StateSpace)>, is_dst: bool, + relaxed_type_check: bool, ) -> Result<(), Err> { - (self)(args, type_space, is_dst) + (self)(args, type_space, is_dst, relaxed_type_check) } fn visit_ident( @@ -520,8 +532,14 @@ impl, bool) -> Result args: &T::Ident, type_space: Option<(&Type, StateSpace)>, is_dst: bool, + relaxed_type_check: bool, ) -> Result<(), Err> { - (self)(&T::from_ident(*args), type_space, is_dst) + (self)( + &T::from_ident(*args), + type_space, + is_dst, + relaxed_type_check, + ) } } @@ -531,12 +549,14 @@ pub trait VisitorMut { args: &mut T, type_space: Option<(&Type, StateSpace)>, is_dst: bool, + relaxed_type_check: bool, ) -> Result<(), Err>; fn visit_ident( &mut self, args: &mut T::Ident, type_space: Option<(&Type, StateSpace)>, is_dst: bool, + relaxed_type_check: bool, ) -> Result<(), Err>; } @@ -546,37 +566,44 @@ pub trait VisitorMap { args: From, type_space: Option<(&Type, StateSpace)>, is_dst: bool, + relaxed_type_check: bool, ) -> Result; fn visit_ident( &mut self, args: From::Ident, type_space: Option<(&Type, StateSpace)>, is_dst: bool, + relaxed_type_check: bool, ) -> Result; } impl VisitorMap, ParsedOperand, Err> for Fn where - Fn: FnMut(T, Option<(&Type, StateSpace)>, bool) -> Result, + Fn: FnMut(T, Option<(&Type, StateSpace)>, bool, bool) -> Result, { fn visit( &mut self, args: ParsedOperand, type_space: Option<(&Type, StateSpace)>, is_dst: bool, + relaxed_type_check: bool, ) -> Result, Err> { Ok(match args { - ParsedOperand::Reg(ident) => ParsedOperand::Reg((self)(ident, type_space, is_dst)?), - ParsedOperand::RegOffset(ident, imm) => { - ParsedOperand::RegOffset((self)(ident, type_space, is_dst)?, imm) + ParsedOperand::Reg(ident) => { + ParsedOperand::Reg((self)(ident, type_space, is_dst, relaxed_type_check)?) } + ParsedOperand::RegOffset(ident, imm) => ParsedOperand::RegOffset( + (self)(ident, type_space, is_dst, relaxed_type_check)?, + imm, + ), ParsedOperand::Imm(imm) => ParsedOperand::Imm(imm), - ParsedOperand::VecMember(ident, index) => { - ParsedOperand::VecMember((self)(ident, type_space, is_dst)?, index) - } + ParsedOperand::VecMember(ident, index) => ParsedOperand::VecMember( + (self)(ident, type_space, is_dst, relaxed_type_check)?, + index, + ), ParsedOperand::VecPack(vec) => ParsedOperand::VecPack( vec.into_iter() - .map(|ident| (self)(ident, type_space, is_dst)) + .map(|ident| (self)(ident, type_space, is_dst, relaxed_type_check)) .collect::, _>>()?, ), }) @@ -587,22 +614,24 @@ where args: T, type_space: Option<(&Type, StateSpace)>, is_dst: bool, + relaxed_type_check: bool, ) -> Result { - (self)(args, type_space, is_dst) + (self)(args, type_space, is_dst, relaxed_type_check) } } impl, U: Operand, Err, Fn> VisitorMap for Fn where - Fn: FnMut(T, Option<(&Type, StateSpace)>, bool) -> Result, + Fn: FnMut(T, Option<(&Type, StateSpace)>, bool, bool) -> Result, { fn visit( &mut self, args: T, type_space: Option<(&Type, StateSpace)>, is_dst: bool, + relaxed_type_check: bool, ) -> Result { - (self)(args, type_space, is_dst) + (self)(args, type_space, is_dst, relaxed_type_check) } fn visit_ident( @@ -610,8 +639,9 @@ where args: T, type_space: Option<(&Type, StateSpace)>, is_dst: bool, + relaxed_type_check: bool, ) -> Result { - (self)(args, type_space, is_dst) + (self)(args, type_space, is_dst, relaxed_type_check) } } @@ -1198,15 +1228,15 @@ impl CallArgs { .iter() .zip(details.return_arguments.iter()) { - visitor.visit_ident(param, Some((type_, *space)), true)?; + visitor.visit_ident(param, Some((type_, *space)), true, false)?; } - visitor.visit_ident(&self.func, None, false)?; + visitor.visit_ident(&self.func, None, false, false)?; for (param, (type_, space)) in self .input_arguments .iter() .zip(details.input_arguments.iter()) { - visitor.visit(param, Some((type_, *space)), true)?; + visitor.visit(param, Some((type_, *space)), true, false)?; } Ok(()) } @@ -1222,15 +1252,15 @@ impl CallArgs { .iter_mut() .zip(details.return_arguments.iter()) { - visitor.visit_ident(param, Some((type_, *space)), true)?; + visitor.visit_ident(param, Some((type_, *space)), true, false)?; } - visitor.visit_ident(&mut self.func, None, false)?; + visitor.visit_ident(&mut self.func, None, false, false)?; for (param, (type_, space)) in self .input_arguments .iter_mut() .zip(details.input_arguments.iter()) { - visitor.visit(param, Some((type_, *space)), true)?; + visitor.visit(param, Some((type_, *space)), true, false)?; } Ok(()) } @@ -1245,14 +1275,14 @@ impl CallArgs { .return_arguments .into_iter() .zip(details.return_arguments.iter()) - .map(|(param, (type_, space))| visitor.visit_ident(param, Some((type_, *space)), true)) + .map(|(param, (type_, space))| visitor.visit_ident(param, Some((type_, *space)), true, false)) .collect::, _>>()?; - let func = visitor.visit_ident(self.func, None, false)?; + let func = visitor.visit_ident(self.func, None, false, false)?; let input_arguments = self .input_arguments .into_iter() .zip(details.input_arguments.iter()) - .map(|(param, (type_, space))| visitor.visit(param, Some((type_, *space)), true)) + .map(|(param, (type_, space))| visitor.visit(param, Some((type_, *space)), true, false)) .collect::, _>>()?; Ok(CallArgs { return_arguments, diff --git a/ptx_parser_macros/src/lib.rs b/ptx_parser_macros/src/lib.rs index 4502c95..a2f8396 100644 --- a/ptx_parser_macros/src/lib.rs +++ b/ptx_parser_macros/src/lib.rs @@ -1017,7 +1017,7 @@ pub fn generate_instruction_type(tokens: proc_macro::TokenStream) -> proc_macro: input.emit_arg_types(&mut result); input.emit_instruction_type(&mut result); input.emit_visit(&mut result); - //input.emit_visit_mut(&mut result); + input.emit_visit_mut(&mut result); input.emit_visit_map(&mut result); result.into() } diff --git a/ptx_parser_macros_impl/src/lib.rs b/ptx_parser_macros_impl/src/lib.rs index 3e53607..2f2c87a 100644 --- a/ptx_parser_macros_impl/src/lib.rs +++ b/ptx_parser_macros_impl/src/lib.rs @@ -512,12 +512,13 @@ pub struct ArgumentField { pub repr: Type, pub space: Option, pub type_: Option, + pub relaxed_type_check: bool, } impl ArgumentField { fn parse_block( input: syn::parse::ParseStream, - ) -> syn::Result<(Type, Option, Option, Option)> { + ) -> syn::Result<(Type, Option, Option, Option, bool)> { let content; braced!(content in input); let all_fields = @@ -531,6 +532,9 @@ impl ArgumentField { let name_ident = content.parse::()?; content.parse::()?; match &*name_ident.to_string() { + "relaxed_type_check" => { + ExprOrPath::RelaxedTypeCheck(content.parse::()?.value) + } "repr" => ExprOrPath::Repr(content.parse::()?), "space" => ExprOrPath::Space(content.parse::()?), "dst" => { @@ -552,15 +556,17 @@ impl ArgumentField { let mut type_ = None; let mut space = None; let mut is_dst = None; + let mut relaxed_type_check = false; for exp_or_path in all_fields { match exp_or_path { ExprOrPath::Repr(r) => repr = Some(r), ExprOrPath::Type(t) => type_ = Some(t), ExprOrPath::Space(s) => space = Some(s), ExprOrPath::Dst(x) => is_dst = Some(x), + ExprOrPath::RelaxedTypeCheck(relaxed) => relaxed_type_check = relaxed, } } - Ok((repr.unwrap(), type_, space, is_dst)) + Ok((repr.unwrap(), type_, space, is_dst, relaxed_type_check)) } fn parse_basic(input: &syn::parse::ParseBuffer) -> syn::Result { @@ -605,6 +611,7 @@ impl ArgumentField { .map(|space| quote! { #space }) .unwrap_or_else(|| quote! { StateSpace::Reg }); let is_dst = self.is_dst; + let relaxed_type_check = self.relaxed_type_check; let name = &self.name; let type_space = if is_typeless { quote! { @@ -622,14 +629,14 @@ impl ArgumentField { quote! { { #type_space - visitor.visit_ident(&mut arguments.#name, type_space, #is_dst)?; + visitor.visit_ident(&mut arguments.#name, type_space, #is_dst, #relaxed_type_check)?; } } } else { quote! { { #type_space - visitor.visit_ident(& arguments.#name, type_space, #is_dst)?; + visitor.visit_ident(& arguments.#name, type_space, #is_dst, #relaxed_type_check)?; } } } @@ -655,7 +662,7 @@ impl ArgumentField { }; quote! {{ #type_space - #operand_fn(#arguments_name, |x| visitor.visit(x, type_space, #is_dst))?; + #operand_fn(#arguments_name, |x| visitor.visit(x, type_space, #is_dst, #relaxed_type_check))?; }} } } @@ -679,6 +686,7 @@ impl ArgumentField { .map(|space| quote! { #space }) .unwrap_or_else(|| quote! { StateSpace::Reg }); let is_dst = self.is_dst; + let relaxed_type_check = self.relaxed_type_check; let name = &self.name; let type_space = if is_typeless { quote! { @@ -693,11 +701,11 @@ impl ArgumentField { }; let map_call = if is_ident { quote! { - visitor.visit_ident(arguments.#name, type_space, #is_dst)? + visitor.visit_ident(arguments.#name, type_space, #is_dst, #relaxed_type_check)? } } else { quote! { - MapOperand::map(arguments.#name, |x| visitor.visit(x, type_space, #is_dst))? + MapOperand::map(arguments.#name, |x| visitor.visit(x, type_space, #is_dst, #relaxed_type_check))? } }; quote! { @@ -739,10 +747,10 @@ impl Parse for ArgumentField { input.parse::()?; let lookahead = input.lookahead1(); - let (repr, type_, space, is_dst) = if lookahead.peek(token::Brace) { + let (repr, type_, space, is_dst, relaxed_type_check) = if lookahead.peek(token::Brace) { Self::parse_block(input)? } else if lookahead.peek(syn::Ident) { - (Self::parse_basic(input)?, None, None, None) + (Self::parse_basic(input)?, None, None, None, false) } else { return Err(lookahead.error()); }; @@ -756,6 +764,7 @@ impl Parse for ArgumentField { repr, type_, space, + relaxed_type_check }) } } @@ -765,6 +774,7 @@ enum ExprOrPath { Type(Expr), Space(Expr), Dst(bool), + RelaxedTypeCheck(bool), } #[cfg(test)]