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,18 +396,21 @@ 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(
version, "module",
target, (
opt(address_size),
repeat_without_none(directive),
eof,
)
.map(|(version, _, _, directives, _)| ast::Module {
version, version,
directives, target,
}) opt(address_size),
.parse_next(stream) repeat_without_none(directive),
eof,
)
.map(|(version, _, _, directives, _)| ast::Module {
version,
directives,
}),
)
.parse_next(stream)
} }
fn address_size<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> { fn address_size<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> {
@ -440,18 +443,20 @@ 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>>>> {
with_recovery( trace(
alt(( "directive",
// When adding a new variant here remember to add its first token into recovery parser down below with_recovery(
function.map(|(linking, func)| Some(ast::Directive::Method(linking, func))), alt((
file.map(|_| None), // When adding a new variant here remember to add its first token into recovery parser down below
section.map(|_| None), function.map(|(linking, func)| Some(ast::Directive::Method(linking, func))),
(module_variable, Token::Semicolon) file.map(|_| None),
.map(|((linking, var), _)| Some(ast::Directive::Variable(linking, var))), section.map(|_| None),
)), (module_variable, Token::Semicolon)
( .map(|((linking, var), _)| Some(ast::Directive::Variable(linking, var))),
any, )),
take_till(1.., |(token, _)| match token { (
any,
take_till(1.., |(token, _)| match token {
// visibility // visibility
Token::DotExtern | Token::DotVisible | Token::DotWeak Token::DotExtern | Token::DotVisible | Token::DotWeak
// methods // methods
@ -462,11 +467,12 @@ fn directive<'a, 'input>(
| Token::DotFile | Token::DotSection => true, | Token::DotFile | Token::DotSection => true,
_ => false, _ => false,
}), }),
)
.map(|(_, x)| x),
|text| PtxError::UnrecognizedDirective(text.unwrap_or("")),
) )
.map(|(_, x)| x), .map(Option::flatten),
|text| PtxError::UnrecognizedDirective(text.unwrap_or("")),
) )
.map(Option::flatten)
.parse_next(stream) .parse_next(stream)
} }
@ -483,26 +489,32 @@ 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(
Token::DotFile, "file",
u32, (
Token::String, Token::DotFile,
opt((Token::Comma, u32, Token::Comma, u32)), u32,
Token::String,
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(
Token::DotSection.void(), "section",
dot_ident.void(), (
Token::LBrace.void(), Token::DotSection.void(),
repeat::<_, _, (), _, _>(0.., section_dwarf_line), dot_ident.void(),
Token::RBrace.void(), Token::LBrace.void(),
repeat::<_, _, (), _, _>(0.., section_dwarf_line),
Token::RBrace.void(),
)
.void(),
) )
.void() .parse_next(stream)
.parse_next(stream)
} }
fn section_dwarf_line<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> { fn section_dwarf_line<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> {
@ -535,23 +547,26 @@ 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(
linking_directives, "function",
method_declaration, (
repeat(0.., tuning_directive), linking_directives,
function_body, method_declaration,
repeat(0.., tuning_directive),
function_body,
)
.map(|(linking, func_directive, tuning, body)| {
(
linking,
ast::Function {
func_directive,
tuning,
body,
},
)
}),
) )
.map(|(linking, func_directive, tuning, body)| { .parse_next(stream)?;
(
linking,
ast::Function {
func_directive,
tuning,
body,
},
)
})
.parse_next(stream)?;
stream.state.record_function(&function.func_directive); stream.state.record_function(&function.func_directive);
Ok((linking, function)) Ok((linking, function))
} }
@ -559,16 +574,19 @@ 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> {
repeat( trace(
0.., "linking_directives",
dispatch! { any; repeat(
(Token::DotExtern, _) => empty.value(ast::LinkingDirective::EXTERN), 0..,
(Token::DotVisible, _) => empty.value(ast::LinkingDirective::VISIBLE), dispatch! { any;
(Token::DotWeak, _) => empty.value(ast::LinkingDirective::WEAK), (Token::DotExtern, _) => empty.value(ast::LinkingDirective::EXTERN),
_ => fail (Token::DotVisible, _) => empty.value(ast::LinkingDirective::VISIBLE),
}, (Token::DotWeak, _) => empty.value(ast::LinkingDirective::WEAK),
_ => 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,27 +801,30 @@ 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> {
move |stream: &mut PtxParser<'a, 'input>| { trace(
let input_start = stream.input.first().map(|(_, s)| s).cloned(); "with_recovery",
let stream_start = stream.checkpoint(); move |stream: &mut PtxParser<'a, 'input>| {
match parser.parse_next(stream) { let input_start = stream.input.first().map(|(_, s)| s).cloned();
Ok(value) => Ok(Some(value)), let stream_start = stream.checkpoint();
Err(_) => { match parser.parse_next(stream) {
stream.reset(&stream_start); Ok(value) => Ok(Some(value)),
let tokens = recovery.parse_next(stream)?; Err(_) => {
let range = match input_start { stream.reset(&stream_start);
Some(start) => { let tokens = recovery.parse_next(stream)?;
Some(&stream.state.text[start.start..tokens.last().unwrap().1.end]) let range = match input_start {
} Some(start) => {
// We could handle `(Some(start), None)``, but this whole error recovery is to Some(&stream.state.text[start.start..tokens.last().unwrap().1.end])
// recover from unknown instructions, so we don't care about early end of stream }
_ => None, // We could handle `(Some(start), None)``, but this whole error recovery is to
}; // recover from unknown instructions, so we don't care about early end of stream
stream.state.errors.push(error(range)); _ => None,
Ok(None) };
stream.state.errors.push(error(range));
Ok(None)
}
} }
} },
} )
} }
fn pragma<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> { fn pragma<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> {
@ -815,207 +836,225 @@ 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> {
move |stream: &mut PtxParser<'a, 'input>| { trace(
let (align, vector, type_, name) = variable_declaration.parse_next(stream)?; "method_parameter",
let array_dimensions = if state_space != StateSpace::Reg { move |stream: &mut PtxParser<'a, 'input>| {
opt(array_dimensions).parse_next(stream)? let (align, vector, type_, name) = variable_declaration.parse_next(stream)?;
} else { let array_dimensions = if state_space != StateSpace::Reg {
None opt(array_dimensions).parse_next(stream)?
}; } else {
// TODO: push this check into array_dimensions(...) None
if let Some(ref dims) = array_dimensions { };
if dims[0] == 0 { // TODO: push this check into array_dimensions(...)
return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify)); if let Some(ref dims) = array_dimensions {
if dims[0] == 0 {
return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify));
}
} }
} Ok(Variable {
Ok(Variable { align,
align, v_type: Type::maybe_array(vector, type_, array_dimensions),
v_type: Type::maybe_array(vector, type_, array_dimensions), state_space,
state_space, 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(
opt(align.verify(|x| x.count_ones() == 1)), "variable_declaration",
vector_prefix, (
scalar_type, opt(align.verify(|x| x.count_ones() == 1)),
ident, vector_prefix,
scalar_type,
ident,
),
) )
.parse_next(stream) .parse_next(stream)
} }
fn multi_variable<'a, 'input: 'a>( 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> {
move |stream: &mut PtxParser<'a, 'input>| { trace(
let ((align, vector, type_, name), count) = ( "multi_variable",
variable_declaration, move |stream: &mut PtxParser<'a, 'input>| {
// https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parameterized-variable-names let ((align, vector, type_, name), count) = (
opt(delimited(Token::Lt, u32.verify(|x| *x != 0), Token::Gt)), variable_declaration,
) // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parameterized-variable-names
.parse_next(stream)?; opt(delimited(Token::Lt, u32.verify(|x| *x != 0), Token::Gt)),
if count.is_some() { )
return Ok(MultiVariable { .parse_next(stream)?;
if count.is_some() {
return Ok(MultiVariable {
var: Variable {
align,
v_type: Type::maybe_vector_parsed(vector, type_),
state_space,
name,
array_init: Vec::new(),
},
count,
});
}
let mut array_dimensions = if state_space != StateSpace::Reg {
opt(array_dimensions).parse_next(stream)?
} else {
None
};
let initializer = match state_space {
StateSpace::Global | StateSpace::Const => match array_dimensions {
Some(ref mut dimensions) => {
opt(array_initializer(vector, type_, dimensions)).parse_next(stream)?
}
None => opt(value_initializer(vector, type_)).parse_next(stream)?,
},
_ => None,
};
if let Some(ref dims) = array_dimensions {
if !extern_ && dims[0] == 0 {
return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify));
}
}
Ok(MultiVariable {
var: Variable { var: Variable {
align, align,
v_type: Type::maybe_vector_parsed(vector, type_), v_type: Type::maybe_array(vector, type_, array_dimensions),
state_space, state_space,
name, name,
array_init: Vec::new(), array_init: initializer.unwrap_or(Vec::new()),
}, },
count, count,
}); })
} },
let mut array_dimensions = if state_space != StateSpace::Reg { )
opt(array_dimensions).parse_next(stream)?
} else {
None
};
let initializer = match state_space {
StateSpace::Global | StateSpace::Const => match array_dimensions {
Some(ref mut dimensions) => {
opt(array_initializer(vector, type_, dimensions)).parse_next(stream)?
}
None => opt(value_initializer(vector, type_)).parse_next(stream)?,
},
_ => None,
};
if let Some(ref dims) = array_dimensions {
if !extern_ && dims[0] == 0 {
return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify));
}
}
Ok(MultiVariable {
var: Variable {
align,
v_type: Type::maybe_array(vector, type_, array_dimensions),
state_space,
name,
array_init: initializer.unwrap_or(Vec::new()),
},
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 {
move |stream: &mut PtxParser<'a, 'input>| { trace(
Token::Eq.parse_next(stream)?; "array_initializer",
let mut result = Vec::new(); move |stream: &mut PtxParser<'a, 'input>| {
// TODO: vector constants and multi dim arrays Token::Eq.parse_next(stream)?;
if vector.is_some() || array_dimensions[0] == 0 || array_dimensions.len() > 1 { let mut result = Vec::new();
return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify)); // TODO: vector constants and multi dim arrays
} if vector.is_some() || array_dimensions[0] == 0 || array_dimensions.len() > 1 {
delimited( return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify));
Token::LBrace, }
separated::<_, (), (), _, _, _, _>( delimited(
0..=array_dimensions[0] as usize, Token::LBrace,
single_value_append(&mut result, type_), separated::<_, (), (), _, _, _, _>(
Token::Comma, 0..=array_dimensions[0] as usize,
), single_value_append(&mut result, type_),
Token::RBrace, Token::Comma,
) ),
.parse_next(stream)?; Token::RBrace,
// pad with zeros )
let result_size = type_.size_of() as usize * array_dimensions[0] as usize; .parse_next(stream)?;
result.extend(iter::repeat(0u8).take(result_size - result.len())); // pad with zeros
Ok(result) 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>( 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> {
move |stream: &mut PtxParser<'a, 'input>| { trace(
Token::Eq.parse_next(stream)?; "value_initializer",
let mut result = Vec::new(); move |stream: &mut PtxParser<'a, 'input>| {
// TODO: vector constants Token::Eq.parse_next(stream)?;
if vector.is_some() { let mut result = Vec::new();
return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify)); // TODO: vector constants
} if vector.is_some() {
single_value_append(&mut result, type_).parse_next(stream)?; return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify));
Ok(result) }
} single_value_append(&mut result, type_).parse_next(stream)?;
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 {
move |stream: &mut PtxParser<'a, 'input>| { trace(
let value = immediate_value.parse_next(stream)?; "single_value_append",
match (type_, value) { move |stream: &mut PtxParser<'a, 'input>| {
(ScalarType::U8 | ScalarType::B8, ImmediateValue::U64(x)) => { let value = immediate_value.parse_next(stream)?;
accumulator.extend_from_slice(&(x as u8).to_le_bytes()) match (type_, value) {
(ScalarType::U8 | ScalarType::B8, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as u8).to_le_bytes())
}
(ScalarType::U8 | ScalarType::B8, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as u8).to_le_bytes())
}
(ScalarType::U16 | ScalarType::B16, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as u16).to_le_bytes())
}
(ScalarType::U16 | ScalarType::B16, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as u16).to_le_bytes())
}
(ScalarType::U32 | ScalarType::B32, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as u32).to_le_bytes())
}
(ScalarType::U32 | ScalarType::B32, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as u32).to_le_bytes())
}
(ScalarType::U64 | ScalarType::B64, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as u64).to_le_bytes())
}
(ScalarType::U64 | ScalarType::B64, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as u64).to_le_bytes())
}
(ScalarType::S8, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as i8).to_le_bytes())
}
(ScalarType::S8, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as i8).to_le_bytes())
}
(ScalarType::S16, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as i16).to_le_bytes())
}
(ScalarType::S16, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as i16).to_le_bytes())
}
(ScalarType::S32, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as i32).to_le_bytes())
}
(ScalarType::S32, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as i32).to_le_bytes())
}
(ScalarType::S64, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as i64).to_le_bytes())
}
(ScalarType::S64, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as i64).to_le_bytes())
}
(ScalarType::F32, ImmediateValue::F32(x)) => {
accumulator.extend_from_slice(&x.to_le_bytes())
}
(ScalarType::F64, ImmediateValue::F64(x)) => {
accumulator.extend_from_slice(&x.to_le_bytes())
}
_ => return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify)),
} }
(ScalarType::U8 | ScalarType::B8, ImmediateValue::S64(x)) => { Ok(())
accumulator.extend_from_slice(&(x as u8).to_le_bytes()) },
} )
(ScalarType::U16 | ScalarType::B16, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as u16).to_le_bytes())
}
(ScalarType::U16 | ScalarType::B16, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as u16).to_le_bytes())
}
(ScalarType::U32 | ScalarType::B32, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as u32).to_le_bytes())
}
(ScalarType::U32 | ScalarType::B32, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as u32).to_le_bytes())
}
(ScalarType::U64 | ScalarType::B64, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as u64).to_le_bytes())
}
(ScalarType::U64 | ScalarType::B64, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as u64).to_le_bytes())
}
(ScalarType::S8, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as i8).to_le_bytes())
}
(ScalarType::S8, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as i8).to_le_bytes())
}
(ScalarType::S16, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as i16).to_le_bytes())
}
(ScalarType::S16, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as i16).to_le_bytes())
}
(ScalarType::S32, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as i32).to_le_bytes())
}
(ScalarType::S32, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as i32).to_le_bytes())
}
(ScalarType::S64, ImmediateValue::U64(x)) => {
accumulator.extend_from_slice(&(x as i64).to_le_bytes())
}
(ScalarType::S64, ImmediateValue::S64(x)) => {
accumulator.extend_from_slice(&(x as i64).to_le_bytes())
}
(ScalarType::F32, ImmediateValue::F32(x)) => {
accumulator.extend_from_slice(&x.to_le_bytes())
}
(ScalarType::F64, ImmediateValue::F64(x)) => {
accumulator.extend_from_slice(&x.to_le_bytes())
}
_ => return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify)),
}
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>>> {
delimited(Token::LBrace, repeat_without_none(statement), Token::RBrace) trace(
.map(|s| ast::Statement::Block(s)) "block_statement",
.parse_next(stream) delimited(Token::LBrace, repeat_without_none(statement), Token::RBrace)
.map(|s| ast::Statement::Block(s)),
)
.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> {
repeat(0.., parser).fold(Vec::new, |mut acc: Vec<_>, item| { trace(
if let Some(item) = item { "repeat_without_none",
acc.push(item); repeat(0.., parser).fold(Vec::new, |mut acc: Vec<_>, item| {
} if let Some(item) = item {
acc acc.push(item);
}) }
acc
}),
)
} }
fn ident_literal< fn ident_literal<
@ -1267,11 +1312,14 @@ impl<Ident> ast::ParsedOperand<Ident> {
} }
.parse_next(stream) .parse_next(stream)
} }
alt(( trace(
ident_operands, "operand",
immediate_value.map(ast::ParsedOperand::Imm), alt((
vector_operand.map(ast::ParsedOperand::VecPack), ident_operands,
)) immediate_value.map(ast::ParsedOperand::Imm),
vector_operand.map(ast::ParsedOperand::VecPack),
)),
)
.parse_next(stream) .parse_next(stream)
} }
} }
@ -1445,25 +1493,29 @@ 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(
opt(Token::DotUni), "call",
opt(( (
Token::LParen, opt(Token::DotUni),
separated(1.., ident, Token::Comma).map(|x: Vec<_>| x), opt((
Token::RParen, Token::LParen,
Token::Comma, separated(1.., ident, Token::Comma).map(|x: Vec<_>| x),
) Token::RParen,
.map(|(_, arguments, _, _)| arguments)), Token::Comma,
ident, )
opt(( .map(|(_, arguments, _, _)| arguments)),
Token::Comma.void(), ident,
Token::LParen.void(), opt((
separated(1.., ParsedOperand::<&'input str>::parse, Token::Comma).map(|x: Vec<_>| x), Token::Comma.void(),
Token::RParen.void(), Token::LParen.void(),
) separated(1.., ParsedOperand::<&'input str>::parse, Token::Comma)
.map(|(_, _, arguments, _)| arguments)), .map(|x: Vec<_>| x),
Token::RParen.void(),
)
.map(|(_, _, arguments, _)| arguments)),
),
) )
.parse_next(stream)?; .parse_next(stream)?;
let uniform = uni.is_some(); let uniform = uni.is_some();
let recorded_fn = match stream.state.function_declarations.get(name) { let recorded_fn = match stream.state.function_declarations.get(name) {
Some(decl) => decl, Some(decl) => decl,
@ -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.