Improve reporting of recovered unrecognized statement/directive

This commit is contained in:
Andrzej Janik 2021-12-14 00:02:23 +01:00
parent 0ca14d740f
commit 971951bc9e
5 changed files with 60 additions and 31 deletions

View file

@ -31,6 +31,16 @@ pub enum PtxError {
ArrayInitalizer, ArrayInitalizer,
#[error("")] #[error("")]
NonExternPointer, NonExternPointer,
#[error("{start}:{end}")]
UnrecognizedStatement {
start: usize,
end: usize,
},
#[error("{start}:{end}")]
UnrecognizedDirective {
start: usize,
end: usize,
},
} }
// For some weird reson this is illegal: // For some weird reson this is illegal:

View file

@ -31,6 +31,7 @@ mod translate;
use std::fmt; use std::fmt;
pub use crate::ptx::ModuleParser; pub use crate::ptx::ModuleParser;
use ast::PtxError;
pub use lalrpop_util::lexer::Token; pub use lalrpop_util::lexer::Token;
pub use lalrpop_util::ParseError; pub use lalrpop_util::ParseError;
pub use rspirv::dr::Error as SpirvError; pub use rspirv::dr::Error as SpirvError;
@ -91,33 +92,50 @@ impl ModuleParserExt for ModuleParser {
} }
} }
pub struct DisplayParseError<'a, Loc, Tok, Err>(pub &'a str, pub &'a ParseError<Loc, Tok, Err>); pub struct DisplayParseError<'a, Loc, Tok, Err>(&'a str, &'a ParseError<Loc, Tok, Err>);
impl<'a, Loc, Tok, Err> fmt::Display for DisplayParseError<'a, Loc, Tok, Err> impl<'a, Loc: fmt::Display + Into<usize> + Copy, Tok, Err> DisplayParseError<'a, Loc, Tok, Err> {
// unsafe because there's no guarantee that the input str is the one that this error was created from
pub unsafe fn new(error: &'a ParseError<Loc, Tok, Err>, text: &'a str) -> Self {
Self(text, error)
}
}
impl<'a, Loc, Tok> fmt::Display for DisplayParseError<'a, Loc, Tok, PtxError>
where where
Loc: fmt::Display + Into<usize> + Copy, Loc: fmt::Display,
Tok: fmt::Display, Tok: fmt::Display,
Err: fmt::Display,
{ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.1 { match self.1 {
ParseError::UnrecognizedToken { ParseError::User {
token: (start, token, end), error: PtxError::UnrecognizedStatement { start, end },
.. } => self.fmt_unrecognized(f, *start, *end, "statement"),
} => { ParseError::User {
let full_instruction = error: PtxError::UnrecognizedDirective { start, end },
unsafe { self.0.get_unchecked((*start).into()..(*end).into()) }; } => self.fmt_unrecognized(f, *start, *end, "directive"),
write!( _ => self.1.fmt(f),
f,
"`{}` unrecognized token `{}` found at {}:{}",
full_instruction, token, start, end
)
}
_ => self.fmt(f),
} }
} }
} }
impl<'a, Loc, Tok, Err> DisplayParseError<'a, Loc, Tok, Err> {
fn fmt_unrecognized(
&self,
f: &mut fmt::Formatter,
start: usize,
end: usize,
kind: &'static str,
) -> fmt::Result {
let full_substring = unsafe { self.0.get_unchecked(start..end) };
write!(
f,
"Unrecognized {} `{}` found at {}:{}",
kind, full_substring, start, end
)
}
}
pub(crate) fn without_none<T>(x: Vec<Option<T>>) -> Vec<T> { pub(crate) fn without_none<T>(x: Vec<Option<T>>) -> Vec<T> {
x.into_iter().filter_map(|x| x).collect() x.into_iter().filter_map(|x| x).collect()
} }

View file

@ -394,9 +394,11 @@ Directive: Option<ast::Directive<'input, ast::ParsedArgParams<'input>>> = {
let (linking, var) = v; let (linking, var) = v;
Some(ast::Directive::Variable(linking, var)) Some(ast::Directive::Variable(linking, var))
}, },
! => { @L ! @R => {
let err = <>; let (start, _, end)= (<>);
errors.push(err.error); errors.push(ParseError::User { error:
ast::PtxError::UnrecognizedDirective { start, end }
});
None None
} }
}; };
@ -527,15 +529,10 @@ Statement: Option<ast::Statement<ast::ParsedArgParams<'input>>> = {
PragmaStatement => None, PragmaStatement => None,
"{" <s:Statement*> "}" => Some(ast::Statement::Block(without_none(s))), "{" <s:Statement*> "}" => Some(ast::Statement::Block(without_none(s))),
@L ! ";" @R => { @L ! ";" @R => {
let (start, mut err, _, end) = (<>); let (start, _, _, end) = (<>);
// TODO: report this error more generally, perhaps in user error? errors.push(ParseError::User { error:
err.error = match err.error { ast::PtxError::UnrecognizedStatement { start, end }
ParseError::UnrecognizedToken { token: (_, token, _), expected } => { });
ParseError::UnrecognizedToken { token: (start, token, end), expected }
}
e => e
};
errors.push(err.error);
None None
} }
}; };

View file

@ -1 +1,3 @@
sed 's/(.*//g' log.txt | sort | uniq > uniq.txt grep -E '^cu.*' log.txt | sed 's/(.*//g' | sort | uniq > uniq_host.txt
cat *.log | grep "^Unrecognized s" | grep -Eo '`([^`]*)`' | sed -E 's/^`([^[:space:]]*).*`/\1/' | sort | uniq > uniq_statements.txt
cat *.log | grep "^Unrecognized d" | grep -Eo '`([^`]*)`' | sed -E 's/^`([^`]*)`/\1/' | sort | uniq > uniq_directives.txt

View file

@ -177,6 +177,7 @@ impl StateTracker {
DumpWriter::get_file_name(module_index, version, submodule_index, "log"), DumpWriter::get_file_name(module_index, version, submodule_index, "log"),
)); ));
fn_logger.log_io_error(self.writer.save_module_error_log( fn_logger.log_io_error(self.writer.save_module_error_log(
module_text,
module_index, module_index,
version, version,
submodule_index, submodule_index,
@ -230,6 +231,7 @@ impl DumpWriter {
fn save_module_error_log<'input>( fn save_module_error_log<'input>(
&self, &self,
module_text: &str,
module_index: usize, module_index: usize,
version: Option<usize>, version: Option<usize>,
submodule_index: Option<usize>, submodule_index: Option<usize>,
@ -247,7 +249,7 @@ impl DumpWriter {
)); ));
let mut file = File::create(log_file)?; let mut file = File::create(log_file)?;
for error in errors { for error in errors {
let pretty_print_error = DisplayParseError("", error); let pretty_print_error = unsafe { DisplayParseError::new(error, module_text) };
writeln!(file, "{}", pretty_print_error)?; writeln!(file, "{}", pretty_print_error)?;
} }
Ok(()) Ok(())