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