mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-09-07 10:06:09 +00:00
Add tracing to custom parsers (#469)
This commit is contained in:
parent
94eec34bdb
commit
ef98c1e0ba
1 changed files with 343 additions and 291 deletions
|
@ -396,18 +396,21 @@ pub fn parse_module_checked<'input>(
|
|||
}
|
||||
|
||||
fn module<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<ast::Module<'input>> {
|
||||
(
|
||||
version,
|
||||
target,
|
||||
opt(address_size),
|
||||
repeat_without_none(directive),
|
||||
eof,
|
||||
)
|
||||
.map(|(version, _, _, directives, _)| ast::Module {
|
||||
trace(
|
||||
"module",
|
||||
(
|
||||
version,
|
||||
directives,
|
||||
})
|
||||
.parse_next(stream)
|
||||
target,
|
||||
opt(address_size),
|
||||
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<()> {
|
||||
|
@ -440,18 +443,20 @@ 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>>>> {
|
||||
with_recovery(
|
||||
alt((
|
||||
// When adding a new variant here remember to add its first token into recovery parser down below
|
||||
function.map(|(linking, func)| Some(ast::Directive::Method(linking, func))),
|
||||
file.map(|_| None),
|
||||
section.map(|_| None),
|
||||
(module_variable, Token::Semicolon)
|
||||
.map(|((linking, var), _)| Some(ast::Directive::Variable(linking, var))),
|
||||
)),
|
||||
(
|
||||
any,
|
||||
take_till(1.., |(token, _)| match token {
|
||||
trace(
|
||||
"directive",
|
||||
with_recovery(
|
||||
alt((
|
||||
// When adding a new variant here remember to add its first token into recovery parser down below
|
||||
function.map(|(linking, func)| Some(ast::Directive::Method(linking, func))),
|
||||
file.map(|_| None),
|
||||
section.map(|_| None),
|
||||
(module_variable, Token::Semicolon)
|
||||
.map(|((linking, var), _)| Some(ast::Directive::Variable(linking, var))),
|
||||
)),
|
||||
(
|
||||
any,
|
||||
take_till(1.., |(token, _)| match token {
|
||||
// visibility
|
||||
Token::DotExtern | Token::DotVisible | Token::DotWeak
|
||||
// methods
|
||||
|
@ -462,11 +467,12 @@ fn directive<'a, 'input>(
|
|||
| Token::DotFile | Token::DotSection => true,
|
||||
_ => false,
|
||||
}),
|
||||
)
|
||||
.map(|(_, x)| x),
|
||||
|text| PtxError::UnrecognizedDirective(text.unwrap_or("")),
|
||||
)
|
||||
.map(|(_, x)| x),
|
||||
|text| PtxError::UnrecognizedDirective(text.unwrap_or("")),
|
||||
.map(Option::flatten),
|
||||
)
|
||||
.map(Option::flatten)
|
||||
.parse_next(stream)
|
||||
}
|
||||
|
||||
|
@ -483,26 +489,32 @@ fn module_variable<'a, 'input>(
|
|||
}
|
||||
|
||||
fn file<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<()> {
|
||||
(
|
||||
Token::DotFile,
|
||||
u32,
|
||||
Token::String,
|
||||
opt((Token::Comma, u32, Token::Comma, u32)),
|
||||
trace(
|
||||
"file",
|
||||
(
|
||||
Token::DotFile,
|
||||
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<()> {
|
||||
(
|
||||
Token::DotSection.void(),
|
||||
dot_ident.void(),
|
||||
Token::LBrace.void(),
|
||||
repeat::<_, _, (), _, _>(0.., section_dwarf_line),
|
||||
Token::RBrace.void(),
|
||||
trace(
|
||||
"section",
|
||||
(
|
||||
Token::DotSection.void(),
|
||||
dot_ident.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<()> {
|
||||
|
@ -535,23 +547,26 @@ fn function<'a, 'input>(
|
|||
ast::LinkingDirective,
|
||||
ast::Function<'input, &'input str, ast::Statement<ParsedOperand<&'input str>>>,
|
||||
)> {
|
||||
let (linking, function) = (
|
||||
linking_directives,
|
||||
method_declaration,
|
||||
repeat(0.., tuning_directive),
|
||||
function_body,
|
||||
let (linking, function) = trace(
|
||||
"function",
|
||||
(
|
||||
linking_directives,
|
||||
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)| {
|
||||
(
|
||||
linking,
|
||||
ast::Function {
|
||||
func_directive,
|
||||
tuning,
|
||||
body,
|
||||
},
|
||||
)
|
||||
})
|
||||
.parse_next(stream)?;
|
||||
.parse_next(stream)?;
|
||||
stream.state.record_function(&function.func_directive);
|
||||
Ok((linking, function))
|
||||
}
|
||||
|
@ -559,16 +574,19 @@ fn function<'a, 'input>(
|
|||
fn linking_directives<'a, 'input>(
|
||||
stream: &mut PtxParser<'a, 'input>,
|
||||
) -> PResult<ast::LinkingDirective> {
|
||||
repeat(
|
||||
0..,
|
||||
dispatch! { any;
|
||||
(Token::DotExtern, _) => empty.value(ast::LinkingDirective::EXTERN),
|
||||
(Token::DotVisible, _) => empty.value(ast::LinkingDirective::VISIBLE),
|
||||
(Token::DotWeak, _) => empty.value(ast::LinkingDirective::WEAK),
|
||||
_ => fail
|
||||
},
|
||||
trace(
|
||||
"linking_directives",
|
||||
repeat(
|
||||
0..,
|
||||
dispatch! { any;
|
||||
(Token::DotExtern, _) => empty.value(ast::LinkingDirective::EXTERN),
|
||||
(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)
|
||||
}
|
||||
|
||||
|
@ -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,27 +801,30 @@ 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> {
|
||||
move |stream: &mut PtxParser<'a, 'input>| {
|
||||
let input_start = stream.input.first().map(|(_, s)| s).cloned();
|
||||
let stream_start = stream.checkpoint();
|
||||
match parser.parse_next(stream) {
|
||||
Ok(value) => Ok(Some(value)),
|
||||
Err(_) => {
|
||||
stream.reset(&stream_start);
|
||||
let tokens = recovery.parse_next(stream)?;
|
||||
let range = match input_start {
|
||||
Some(start) => {
|
||||
Some(&stream.state.text[start.start..tokens.last().unwrap().1.end])
|
||||
}
|
||||
// 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
|
||||
_ => None,
|
||||
};
|
||||
stream.state.errors.push(error(range));
|
||||
Ok(None)
|
||||
trace(
|
||||
"with_recovery",
|
||||
move |stream: &mut PtxParser<'a, 'input>| {
|
||||
let input_start = stream.input.first().map(|(_, s)| s).cloned();
|
||||
let stream_start = stream.checkpoint();
|
||||
match parser.parse_next(stream) {
|
||||
Ok(value) => Ok(Some(value)),
|
||||
Err(_) => {
|
||||
stream.reset(&stream_start);
|
||||
let tokens = recovery.parse_next(stream)?;
|
||||
let range = match input_start {
|
||||
Some(start) => {
|
||||
Some(&stream.state.text[start.start..tokens.last().unwrap().1.end])
|
||||
}
|
||||
// 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
|
||||
_ => None,
|
||||
};
|
||||
stream.state.errors.push(error(range));
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
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>(
|
||||
state_space: StateSpace,
|
||||
) -> impl Parser<PtxParser<'a, 'input>, Variable<&'input str>, ContextError> {
|
||||
move |stream: &mut PtxParser<'a, 'input>| {
|
||||
let (align, vector, type_, name) = variable_declaration.parse_next(stream)?;
|
||||
let array_dimensions = if state_space != StateSpace::Reg {
|
||||
opt(array_dimensions).parse_next(stream)?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
// TODO: push this check into array_dimensions(...)
|
||||
if let Some(ref dims) = array_dimensions {
|
||||
if dims[0] == 0 {
|
||||
return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify));
|
||||
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 {
|
||||
opt(array_dimensions).parse_next(stream)?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
// TODO: push this check into array_dimensions(...)
|
||||
if let Some(ref dims) = array_dimensions {
|
||||
if dims[0] == 0 {
|
||||
return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Variable {
|
||||
align,
|
||||
v_type: Type::maybe_array(vector, type_, array_dimensions),
|
||||
state_space,
|
||||
name,
|
||||
array_init: Vec::new(),
|
||||
})
|
||||
}
|
||||
Ok(Variable {
|
||||
align,
|
||||
v_type: Type::maybe_array(vector, type_, array_dimensions),
|
||||
state_space,
|
||||
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)> {
|
||||
(
|
||||
opt(align.verify(|x| x.count_ones() == 1)),
|
||||
vector_prefix,
|
||||
scalar_type,
|
||||
ident,
|
||||
trace(
|
||||
"variable_declaration",
|
||||
(
|
||||
opt(align.verify(|x| x.count_ones() == 1)),
|
||||
vector_prefix,
|
||||
scalar_type,
|
||||
ident,
|
||||
),
|
||||
)
|
||||
.parse_next(stream)
|
||||
.parse_next(stream)
|
||||
}
|
||||
|
||||
fn multi_variable<'a, 'input: 'a>(
|
||||
extern_: bool,
|
||||
state_space: StateSpace,
|
||||
) -> impl Parser<PtxParser<'a, 'input>, MultiVariable<&'input str>, ContextError> {
|
||||
move |stream: &mut PtxParser<'a, 'input>| {
|
||||
let ((align, vector, type_, name), count) = (
|
||||
variable_declaration,
|
||||
// https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parameterized-variable-names
|
||||
opt(delimited(Token::Lt, u32.verify(|x| *x != 0), Token::Gt)),
|
||||
)
|
||||
.parse_next(stream)?;
|
||||
if count.is_some() {
|
||||
return Ok(MultiVariable {
|
||||
trace(
|
||||
"multi_variable",
|
||||
move |stream: &mut PtxParser<'a, 'input>| {
|
||||
let ((align, vector, type_, name), count) = (
|
||||
variable_declaration,
|
||||
// https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parameterized-variable-names
|
||||
opt(delimited(Token::Lt, u32.verify(|x| *x != 0), Token::Gt)),
|
||||
)
|
||||
.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 {
|
||||
align,
|
||||
v_type: Type::maybe_vector_parsed(vector, type_),
|
||||
v_type: Type::maybe_array(vector, type_, array_dimensions),
|
||||
state_space,
|
||||
name,
|
||||
array_init: Vec::new(),
|
||||
array_init: initializer.unwrap_or(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 {
|
||||
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>,
|
||||
type_: ScalarType,
|
||||
array_dimensions: &mut Vec<u32>,
|
||||
) -> impl Parser<PtxParser<'a, 'input>, Vec<u8>, ContextError> + '_ {
|
||||
move |stream: &mut PtxParser<'a, 'input>| {
|
||||
Token::Eq.parse_next(stream)?;
|
||||
let mut result = Vec::new();
|
||||
// TODO: vector constants and multi dim arrays
|
||||
if vector.is_some() || array_dimensions[0] == 0 || array_dimensions.len() > 1 {
|
||||
return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify));
|
||||
}
|
||||
delimited(
|
||||
Token::LBrace,
|
||||
separated::<_, (), (), _, _, _, _>(
|
||||
0..=array_dimensions[0] as usize,
|
||||
single_value_append(&mut result, type_),
|
||||
Token::Comma,
|
||||
),
|
||||
Token::RBrace,
|
||||
)
|
||||
.parse_next(stream)?;
|
||||
// pad with zeros
|
||||
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)
|
||||
}
|
||||
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();
|
||||
// TODO: vector constants and multi dim arrays
|
||||
if vector.is_some() || array_dimensions[0] == 0 || array_dimensions.len() > 1 {
|
||||
return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify));
|
||||
}
|
||||
delimited(
|
||||
Token::LBrace,
|
||||
separated::<_, (), (), _, _, _, _>(
|
||||
0..=array_dimensions[0] as usize,
|
||||
single_value_append(&mut result, type_),
|
||||
Token::Comma,
|
||||
),
|
||||
Token::RBrace,
|
||||
)
|
||||
.parse_next(stream)?;
|
||||
// pad with zeros
|
||||
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> {
|
||||
move |stream: &mut PtxParser<'a, 'input>| {
|
||||
Token::Eq.parse_next(stream)?;
|
||||
let mut result = Vec::new();
|
||||
// TODO: vector constants
|
||||
if vector.is_some() {
|
||||
return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify));
|
||||
}
|
||||
single_value_append(&mut result, type_).parse_next(stream)?;
|
||||
Ok(result)
|
||||
}
|
||||
trace(
|
||||
"value_initializer",
|
||||
move |stream: &mut PtxParser<'a, 'input>| {
|
||||
Token::Eq.parse_next(stream)?;
|
||||
let mut result = Vec::new();
|
||||
// TODO: vector constants
|
||||
if vector.is_some() {
|
||||
return Err(ErrMode::from_error_kind(stream, ErrorKind::Verify));
|
||||
}
|
||||
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> + '_ {
|
||||
move |stream: &mut PtxParser<'a, 'input>| {
|
||||
let value = immediate_value.parse_next(stream)?;
|
||||
match (type_, value) {
|
||||
(ScalarType::U8 | ScalarType::B8, ImmediateValue::U64(x)) => {
|
||||
accumulator.extend_from_slice(&(x as u8).to_le_bytes())
|
||||
) -> 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) {
|
||||
(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)) => {
|
||||
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(())
|
||||
}
|
||||
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>>> {
|
||||
delimited(Token::LBrace, repeat_without_none(statement), Token::RBrace)
|
||||
.map(|s| ast::Statement::Block(s))
|
||||
.parse_next(stream)
|
||||
trace(
|
||||
"block_statement",
|
||||
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>>(
|
||||
parser: impl Parser<Input, Option<Output>, Error>,
|
||||
) -> impl Parser<Input, Vec<Output>, Error> {
|
||||
repeat(0.., parser).fold(Vec::new, |mut acc: Vec<_>, item| {
|
||||
if let Some(item) = item {
|
||||
acc.push(item);
|
||||
}
|
||||
acc
|
||||
})
|
||||
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)
|
||||
}
|
||||
alt((
|
||||
ident_operands,
|
||||
immediate_value.map(ast::ParsedOperand::Imm),
|
||||
vector_operand.map(ast::ParsedOperand::VecPack),
|
||||
))
|
||||
trace(
|
||||
"operand",
|
||||
alt((
|
||||
ident_operands,
|
||||
immediate_value.map(ast::ParsedOperand::Imm),
|
||||
vector_operand.map(ast::ParsedOperand::VecPack),
|
||||
)),
|
||||
)
|
||||
.parse_next(stream)
|
||||
}
|
||||
}
|
||||
|
@ -1445,25 +1493,29 @@ 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) = (
|
||||
opt(Token::DotUni),
|
||||
opt((
|
||||
Token::LParen,
|
||||
separated(1.., ident, Token::Comma).map(|x: Vec<_>| x),
|
||||
Token::RParen,
|
||||
Token::Comma,
|
||||
)
|
||||
.map(|(_, arguments, _, _)| arguments)),
|
||||
ident,
|
||||
opt((
|
||||
Token::Comma.void(),
|
||||
Token::LParen.void(),
|
||||
separated(1.., ParsedOperand::<&'input str>::parse, Token::Comma).map(|x: Vec<_>| x),
|
||||
Token::RParen.void(),
|
||||
)
|
||||
.map(|(_, _, arguments, _)| arguments)),
|
||||
let (uni, return_arguments, name, input_arguments) = trace(
|
||||
"call",
|
||||
(
|
||||
opt(Token::DotUni),
|
||||
opt((
|
||||
Token::LParen,
|
||||
separated(1.., ident, Token::Comma).map(|x: Vec<_>| x),
|
||||
Token::RParen,
|
||||
Token::Comma,
|
||||
)
|
||||
.map(|(_, arguments, _, _)| arguments)),
|
||||
ident,
|
||||
opt((
|
||||
Token::Comma.void(),
|
||||
Token::LParen.void(),
|
||||
separated(1.., ParsedOperand::<&'input str>::parse, Token::Comma)
|
||||
.map(|x: Vec<_>| x),
|
||||
Token::RParen.void(),
|
||||
)
|
||||
.map(|(_, _, arguments, _)| arguments)),
|
||||
),
|
||||
)
|
||||
.parse_next(stream)?;
|
||||
.parse_next(stream)?;
|
||||
let uniform = uni.is_some();
|
||||
let recorded_fn = match stream.state.function_declarations.get(name) {
|
||||
Some(decl) => decl,
|
||||
|
@ -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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue