Add tracing to custom parsers (#469)
Some checks are pending
ZLUDA / Build (Linux) (push) Waiting to run
ZLUDA / Build (Windows) (push) Waiting to run
ZLUDA / Build AMD GPU unit tests (push) Waiting to run
ZLUDA / Run AMD GPU unit tests (push) Blocked by required conditions

This commit is contained in:
Violet 2025-08-07 11:51:56 -07:00 committed by GitHub
commit ef98c1e0ba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -396,6 +396,8 @@ pub fn parse_module_checked<'input>(
} }
fn module<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<ast::Module<'input>> { fn module<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<ast::Module<'input>> {
trace(
"module",
( (
version, version,
target, target,
@ -406,7 +408,8 @@ fn module<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<ast::Module
.map(|(version, _, _, directives, _)| ast::Module { .map(|(version, _, _, directives, _)| ast::Module {
version, version,
directives, directives,
}) }),
)
.parse_next(stream) .parse_next(stream)
} }
@ -440,6 +443,8 @@ fn shader_model<'a>(stream: &mut &str) -> PResult<(u32, Option<char>)> {
fn directive<'a, 'input>( fn directive<'a, 'input>(
stream: &mut PtxParser<'a, 'input>, stream: &mut PtxParser<'a, 'input>,
) -> PResult<Option<ast::Directive<'input, ast::ParsedOperand<&'input str>>>> { ) -> PResult<Option<ast::Directive<'input, ast::ParsedOperand<&'input str>>>> {
trace(
"directive",
with_recovery( with_recovery(
alt(( alt((
// When adding a new variant here remember to add its first token into recovery parser down below // When adding a new variant here remember to add its first token into recovery parser down below
@ -466,7 +471,8 @@ fn directive<'a, 'input>(
.map(|(_, x)| x), .map(|(_, x)| x),
|text| PtxError::UnrecognizedDirective(text.unwrap_or("")), |text| PtxError::UnrecognizedDirective(text.unwrap_or("")),
) )
.map(Option::flatten) .map(Option::flatten),
)
.parse_next(stream) .parse_next(stream)
} }
@ -483,17 +489,22 @@ fn module_variable<'a, 'input>(
} }
fn file<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> { fn file<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> {
trace(
"file",
( (
Token::DotFile, Token::DotFile,
u32, u32,
Token::String, Token::String,
opt((Token::Comma, u32, Token::Comma, u32)), opt((Token::Comma, u32, Token::Comma, u32)),
) )
.void() .void(),
)
.parse_next(stream) .parse_next(stream)
} }
fn section<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> { fn section<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> {
trace(
"section",
( (
Token::DotSection.void(), Token::DotSection.void(),
dot_ident.void(), dot_ident.void(),
@ -501,7 +512,8 @@ fn section<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> {
repeat::<_, _, (), _, _>(0.., section_dwarf_line), repeat::<_, _, (), _, _>(0.., section_dwarf_line),
Token::RBrace.void(), Token::RBrace.void(),
) )
.void() .void(),
)
.parse_next(stream) .parse_next(stream)
} }
@ -535,7 +547,9 @@ fn function<'a, 'input>(
ast::LinkingDirective, ast::LinkingDirective,
ast::Function<'input, &'input str, ast::Statement<ParsedOperand<&'input str>>>, ast::Function<'input, &'input str, ast::Statement<ParsedOperand<&'input str>>>,
)> { )> {
let (linking, function) = ( let (linking, function) = trace(
"function",
(
linking_directives, linking_directives,
method_declaration, method_declaration,
repeat(0.., tuning_directive), repeat(0.., tuning_directive),
@ -550,7 +564,8 @@ fn function<'a, 'input>(
body, body,
}, },
) )
}) }),
)
.parse_next(stream)?; .parse_next(stream)?;
stream.state.record_function(&function.func_directive); stream.state.record_function(&function.func_directive);
Ok((linking, function)) Ok((linking, function))
@ -559,6 +574,8 @@ fn function<'a, 'input>(
fn linking_directives<'a, 'input>( fn linking_directives<'a, 'input>(
stream: &mut PtxParser<'a, 'input>, stream: &mut PtxParser<'a, 'input>,
) -> PResult<ast::LinkingDirective> { ) -> PResult<ast::LinkingDirective> {
trace(
"linking_directives",
repeat( repeat(
0.., 0..,
dispatch! { any; dispatch! { any;
@ -568,7 +585,8 @@ fn linking_directives<'a, 'input>(
_ => fail _ => fail
}, },
) )
.fold(|| ast::LinkingDirective::NONE, |x, y| x | y) .fold(|| ast::LinkingDirective::NONE, |x, y| x | y),
)
.parse_next(stream) .parse_next(stream)
} }
@ -680,11 +698,11 @@ fn tuple1to3_u32<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<(u32
fn function_body<'a, 'input>( fn function_body<'a, 'input>(
stream: &mut PtxParser<'a, 'input>, stream: &mut PtxParser<'a, 'input>,
) -> PResult<Option<Vec<ast::Statement<ParsedOperandStr<'input>>>>> { ) -> PResult<Option<Vec<ast::Statement<ParsedOperandStr<'input>>>>> {
dispatch! {any; trace("function_body", dispatch! {any;
(Token::LBrace, _) => terminated(repeat_without_none(statement), Token::RBrace).map(Some), (Token::LBrace, _) => terminated(repeat_without_none(statement), Token::RBrace).map(Some),
(Token::Semicolon, _) => empty.map(|_| None), (Token::Semicolon, _) => empty.map(|_| None),
_ => fail _ => fail
} })
.parse_next(stream) .parse_next(stream)
} }
@ -745,7 +763,7 @@ fn take_till_inclusive<I: Stream, E: ParserError<I>>(
} }
Err(ParserError::from_error_kind(input, ErrorKind::Eof)) Err(ParserError::from_error_kind(input, ErrorKind::Eof))
} }
move |stream: &mut I| { trace("take_till_inclusive", move |stream: &mut I| {
let mut should_backtrack = false; let mut should_backtrack = false;
let offset = get_offset(stream, &backtrack_token, &end_token, &mut should_backtrack)?; let offset = get_offset(stream, &backtrack_token, &end_token, &mut should_backtrack)?;
let result = stream.next_slice(offset); let result = stream.next_slice(offset);
@ -757,7 +775,7 @@ fn take_till_inclusive<I: Stream, E: ParserError<I>>(
} else { } else {
Ok(result) Ok(result)
} }
} })
} }
/* /*
@ -783,6 +801,8 @@ fn with_recovery<'a, 'input: 'a, T>(
mut recovery: impl Parser<PtxParser<'a, 'input>, &'a [(Token<'input>, logos::Span)], ContextError>, mut recovery: impl Parser<PtxParser<'a, 'input>, &'a [(Token<'input>, logos::Span)], ContextError>,
mut error: impl FnMut(Option<&'input str>) -> PtxError<'input>, mut error: impl FnMut(Option<&'input str>) -> PtxError<'input>,
) -> impl Parser<PtxParser<'a, 'input>, Option<T>, ContextError> { ) -> impl Parser<PtxParser<'a, 'input>, Option<T>, ContextError> {
trace(
"with_recovery",
move |stream: &mut PtxParser<'a, 'input>| { move |stream: &mut PtxParser<'a, 'input>| {
let input_start = stream.input.first().map(|(_, s)| s).cloned(); let input_start = stream.input.first().map(|(_, s)| s).cloned();
let stream_start = stream.checkpoint(); let stream_start = stream.checkpoint();
@ -803,7 +823,8 @@ fn with_recovery<'a, 'input: 'a, T>(
Ok(None) Ok(None)
} }
} }
} },
)
} }
fn pragma<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> { fn pragma<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> {
@ -815,6 +836,8 @@ fn pragma<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> {
fn method_parameter<'a, 'input: 'a>( fn method_parameter<'a, 'input: 'a>(
state_space: StateSpace, state_space: StateSpace,
) -> impl Parser<PtxParser<'a, 'input>, Variable<&'input str>, ContextError> { ) -> impl Parser<PtxParser<'a, 'input>, Variable<&'input str>, ContextError> {
trace(
"method_parameter",
move |stream: &mut PtxParser<'a, 'input>| { move |stream: &mut PtxParser<'a, 'input>| {
let (align, vector, type_, name) = variable_declaration.parse_next(stream)?; let (align, vector, type_, name) = variable_declaration.parse_next(stream)?;
let array_dimensions = if state_space != StateSpace::Reg { let array_dimensions = if state_space != StateSpace::Reg {
@ -835,18 +858,22 @@ fn method_parameter<'a, 'input: 'a>(
name, name,
array_init: Vec::new(), array_init: Vec::new(),
}) })
} },
)
} }
// TODO: split to a separate type // TODO: split to a separate type
fn variable_declaration<'a, 'input>( fn variable_declaration<'a, 'input>(
stream: &mut PtxParser<'a, 'input>, stream: &mut PtxParser<'a, 'input>,
) -> PResult<(Option<u32>, Option<NonZeroU8>, ScalarType, &'input str)> { ) -> PResult<(Option<u32>, Option<NonZeroU8>, ScalarType, &'input str)> {
trace(
"variable_declaration",
( (
opt(align.verify(|x| x.count_ones() == 1)), opt(align.verify(|x| x.count_ones() == 1)),
vector_prefix, vector_prefix,
scalar_type, scalar_type,
ident, ident,
),
) )
.parse_next(stream) .parse_next(stream)
} }
@ -855,6 +882,8 @@ fn multi_variable<'a, 'input: 'a>(
extern_: bool, extern_: bool,
state_space: StateSpace, state_space: StateSpace,
) -> impl Parser<PtxParser<'a, 'input>, MultiVariable<&'input str>, ContextError> { ) -> impl Parser<PtxParser<'a, 'input>, MultiVariable<&'input str>, ContextError> {
trace(
"multi_variable",
move |stream: &mut PtxParser<'a, 'input>| { move |stream: &mut PtxParser<'a, 'input>| {
let ((align, vector, type_, name), count) = ( let ((align, vector, type_, name), count) = (
variable_declaration, variable_declaration,
@ -903,14 +932,17 @@ fn multi_variable<'a, 'input: 'a>(
}, },
count, count,
}) })
} },
)
} }
fn array_initializer<'a, 'input: 'a>( fn array_initializer<'b, 'a: 'b, 'input: 'a>(
vector: Option<NonZeroU8>, vector: Option<NonZeroU8>,
type_: ScalarType, type_: ScalarType,
array_dimensions: &mut Vec<u32>, array_dimensions: &'b mut Vec<u32>,
) -> impl Parser<PtxParser<'a, 'input>, Vec<u8>, ContextError> + '_ { ) -> impl Parser<PtxParser<'a, 'input>, Vec<u8>, ContextError> + 'b {
trace(
"array_initializer",
move |stream: &mut PtxParser<'a, 'input>| { move |stream: &mut PtxParser<'a, 'input>| {
Token::Eq.parse_next(stream)?; Token::Eq.parse_next(stream)?;
let mut result = Vec::new(); let mut result = Vec::new();
@ -932,13 +964,16 @@ fn array_initializer<'a, 'input: 'a>(
let result_size = type_.size_of() as usize * array_dimensions[0] as usize; let result_size = type_.size_of() as usize * array_dimensions[0] as usize;
result.extend(iter::repeat(0u8).take(result_size - result.len())); result.extend(iter::repeat(0u8).take(result_size - result.len()));
Ok(result) Ok(result)
} },
)
} }
fn value_initializer<'a, 'input: 'a>( fn value_initializer<'a, 'input: 'a>(
vector: Option<NonZeroU8>, vector: Option<NonZeroU8>,
type_: ScalarType, type_: ScalarType,
) -> impl Parser<PtxParser<'a, 'input>, Vec<u8>, ContextError> { ) -> impl Parser<PtxParser<'a, 'input>, Vec<u8>, ContextError> {
trace(
"value_initializer",
move |stream: &mut PtxParser<'a, 'input>| { move |stream: &mut PtxParser<'a, 'input>| {
Token::Eq.parse_next(stream)?; Token::Eq.parse_next(stream)?;
let mut result = Vec::new(); let mut result = Vec::new();
@ -948,13 +983,16 @@ fn value_initializer<'a, 'input: 'a>(
} }
single_value_append(&mut result, type_).parse_next(stream)?; single_value_append(&mut result, type_).parse_next(stream)?;
Ok(result) Ok(result)
} },
)
} }
fn single_value_append<'a, 'input: 'a>( fn single_value_append<'b, 'a: 'b, 'input: 'a>(
accumulator: &mut Vec<u8>, accumulator: &'b mut Vec<u8>,
type_: ScalarType, type_: ScalarType,
) -> impl Parser<PtxParser<'a, 'input>, (), ContextError> + '_ { ) -> impl Parser<PtxParser<'a, 'input>, (), ContextError> + 'b {
trace(
"single_value_append",
move |stream: &mut PtxParser<'a, 'input>| { move |stream: &mut PtxParser<'a, 'input>| {
let value = immediate_value.parse_next(stream)?; let value = immediate_value.parse_next(stream)?;
match (type_, value) { match (type_, value) {
@ -1015,7 +1053,8 @@ fn single_value_append<'a, 'input: 'a>(
_ => return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify)), _ => return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify)),
} }
Ok(()) Ok(())
} },
)
} }
fn array_dimensions<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<Vec<u32>> { fn array_dimensions<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<Vec<u32>> {
@ -1188,20 +1227,26 @@ fn debug_directive<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()
fn block_statement<'a, 'input>( fn block_statement<'a, 'input>(
stream: &mut PtxParser<'a, 'input>, stream: &mut PtxParser<'a, 'input>,
) -> PResult<ast::Statement<ParsedOperandStr<'input>>> { ) -> PResult<ast::Statement<ParsedOperandStr<'input>>> {
trace(
"block_statement",
delimited(Token::LBrace, repeat_without_none(statement), Token::RBrace) delimited(Token::LBrace, repeat_without_none(statement), Token::RBrace)
.map(|s| ast::Statement::Block(s)) .map(|s| ast::Statement::Block(s)),
)
.parse_next(stream) .parse_next(stream)
} }
fn repeat_without_none<Input: Stream, Output, Error: ParserError<Input>>( fn repeat_without_none<Input: Stream, Output, Error: ParserError<Input>>(
parser: impl Parser<Input, Option<Output>, Error>, parser: impl Parser<Input, Option<Output>, Error>,
) -> impl Parser<Input, Vec<Output>, Error> { ) -> impl Parser<Input, Vec<Output>, Error> {
trace(
"repeat_without_none",
repeat(0.., parser).fold(Vec::new, |mut acc: Vec<_>, item| { repeat(0.., parser).fold(Vec::new, |mut acc: Vec<_>, item| {
if let Some(item) = item { if let Some(item) = item {
acc.push(item); acc.push(item);
} }
acc acc
}) }),
)
} }
fn ident_literal< fn ident_literal<
@ -1267,11 +1312,14 @@ impl<Ident> ast::ParsedOperand<Ident> {
} }
.parse_next(stream) .parse_next(stream)
} }
trace(
"operand",
alt(( alt((
ident_operands, ident_operands,
immediate_value.map(ast::ParsedOperand::Imm), immediate_value.map(ast::ParsedOperand::Imm),
vector_operand.map(ast::ParsedOperand::VecPack), vector_operand.map(ast::ParsedOperand::VecPack),
)) )),
)
.parse_next(stream) .parse_next(stream)
} }
} }
@ -1445,7 +1493,9 @@ fn bra<'a, 'input>(
fn call<'a, 'input>( fn call<'a, 'input>(
stream: &mut PtxParser<'a, 'input>, stream: &mut PtxParser<'a, 'input>,
) -> PResult<ast::Instruction<ParsedOperandStr<'input>>> { ) -> PResult<ast::Instruction<ParsedOperandStr<'input>>> {
let (uni, return_arguments, name, input_arguments) = ( let (uni, return_arguments, name, input_arguments) = trace(
"call",
(
opt(Token::DotUni), opt(Token::DotUni),
opt(( opt((
Token::LParen, Token::LParen,
@ -1458,10 +1508,12 @@ fn call<'a, 'input>(
opt(( opt((
Token::Comma.void(), Token::Comma.void(),
Token::LParen.void(), Token::LParen.void(),
separated(1.., ParsedOperand::<&'input str>::parse, Token::Comma).map(|x: Vec<_>| x), separated(1.., ParsedOperand::<&'input str>::parse, Token::Comma)
.map(|x: Vec<_>| x),
Token::RParen.void(), Token::RParen.void(),
) )
.map(|(_, _, arguments, _)| arguments)), .map(|(_, _, arguments, _)| arguments)),
),
) )
.parse_next(stream)?; .parse_next(stream)?;
let uniform = uni.is_some(); let uniform = uni.is_some();
@ -1536,7 +1588,7 @@ where
ParseRequired: Parser<Input, RequiredOutput, Error>, ParseRequired: Parser<Input, RequiredOutput, Error>,
Error: ParserError<Input>, Error: ParserError<Input>,
{ {
move |input: &mut Input| -> Result<(Option<OptionalOutput>, RequiredOutput), ErrMode<Error>> { trace("first_optional", move |input: &mut Input| -> Result<(Option<OptionalOutput>, RequiredOutput), ErrMode<Error>> {
let start = input.checkpoint(); let start = input.checkpoint();
let parsed_optional = match optional.parse_next(input) { let parsed_optional = match optional.parse_next(input) {
@ -1555,7 +1607,7 @@ where
}; };
Ok((None, required.parse_next(input)?)) Ok((None, required.parse_next(input)?))
} })
} }
// This macro is responsible for generating parser code for instruction parser. // This macro is responsible for generating parser code for instruction parser.