Do slightly better when it comes to PTX error recovery

This commit is contained in:
Andrzej Janik 2021-03-01 02:24:27 +01:00
parent eec55d9d02
commit d3cd2dc8b4
3 changed files with 61 additions and 44 deletions

View file

@ -10,8 +10,9 @@ edition = "2018"
lalrpop-util = "0.19"
regex = "1"
rspirv = "0.6"
spirv_headers = "~1.4.2"
spirv_headers = "~1.4.2"
quick-error = "1.2"
thiserror = "1.0"
bit-vec = "0.6"
half ="1.6"
bitflags = "1.2"

View file

@ -1,31 +1,37 @@
use half::f16;
use lalrpop_util::{lexer::Token, ParseError};
use std::convert::TryInto;
use std::{convert::From, convert::TryFrom, mem, num::ParseFloatError, str::FromStr};
use std::{marker::PhantomData, num::ParseIntError};
use half::f16;
quick_error! {
#[derive(Debug)]
pub enum PtxError {
ParseInt (err: ParseIntError) {
from()
display("{}", err)
cause(err)
}
ParseFloat (err: ParseFloatError) {
from()
display("{}", err)
cause(err)
}
SyntaxError {}
NonF32Ftz {}
WrongArrayType {}
WrongVectorElement {}
MultiArrayVariable {}
ZeroDimensionArray {}
ArrayInitalizer {}
NonExternPointer {}
}
#[derive(Debug, thiserror::Error)]
pub enum PtxError {
#[error("{source}")]
ParseInt {
#[from]
source: ParseIntError,
},
#[error("{source}")]
ParseFloat {
#[from]
source: ParseFloatError,
},
#[error("")]
SyntaxError,
#[error("")]
NonF32Ftz,
#[error("")]
WrongArrayType,
#[error("")]
WrongVectorElement,
#[error("")]
MultiArrayVariable,
#[error("")]
ZeroDimensionArray,
#[error("")]
ArrayInitalizer,
#[error("")]
NonExternPointer,
}
macro_rules! sub_enum {
@ -895,36 +901,36 @@ pub struct CvtDesc<Dst, Src> {
}
impl CvtDetails {
pub fn new_int_from_int_checked(
pub fn new_int_from_int_checked<'err, 'input>(
saturate: bool,
dst: IntType,
src: IntType,
err: &mut Vec<PtxError>,
err: &'err mut Vec<ParseError<usize, Token<'input>, PtxError>>,
) -> Self {
if saturate {
if src.is_signed() {
if dst.is_signed() && dst.width() >= src.width() {
err.push(PtxError::SyntaxError);
err.push(ParseError::from(PtxError::SyntaxError));
}
} else {
if dst == src || dst.width() >= src.width() {
err.push(PtxError::SyntaxError);
err.push(ParseError::from(PtxError::SyntaxError));
}
}
}
CvtDetails::IntFromInt(CvtIntToIntDesc { dst, src, saturate })
}
pub fn new_float_from_int_checked(
pub fn new_float_from_int_checked<'err, 'input>(
rounding: RoundingMode,
flush_to_zero: bool,
saturate: bool,
dst: FloatType,
src: IntType,
err: &mut Vec<PtxError>,
err: &'err mut Vec<ParseError<usize, Token<'input>, PtxError>>,
) -> Self {
if flush_to_zero && dst != FloatType::F32 {
err.push(PtxError::NonF32Ftz);
err.push(ParseError::from(PtxError::NonF32Ftz));
}
CvtDetails::FloatFromInt(CvtDesc {
dst,
@ -935,16 +941,16 @@ impl CvtDetails {
})
}
pub fn new_int_from_float_checked(
pub fn new_int_from_float_checked<'err, 'input>(
rounding: RoundingMode,
flush_to_zero: bool,
saturate: bool,
dst: IntType,
src: FloatType,
err: &mut Vec<PtxError>,
err: &'err mut Vec<ParseError<usize, Token<'input>, PtxError>>,
) -> Self {
if flush_to_zero && src != FloatType::F32 {
err.push(PtxError::NonF32Ftz);
err.push(ParseError::from(PtxError::NonF32Ftz));
}
CvtDetails::IntFromFloat(CvtDesc {
dst,

View file

@ -5,7 +5,7 @@ use crate::{without_none, vector_index};
use lalrpop_util::ParseError;
use std::convert::TryInto;
grammar<'a>(errors: &mut Vec<ast::PtxError>);
grammar<'err>(errors: &'err mut Vec<ParseError<usize, Token<'input>, ast::PtxError>>);
extern {
type Error = ast::PtxError;
@ -313,11 +313,11 @@ pub Module: ast::Module<'input> = {
};
Version: (u8, u8) = {
".version" <v:VersionNumber> => {
".version" <v:VersionNumber> =>? {
let dot = v.find('.').unwrap();
let major = v[..dot].parse::<u8>();
let minor = v[dot+1..].parse::<u8>();
(major,minor).unwrap_with(errors)
let major = v[..dot].parse::<u8>().map_err(|e| ParseError::from(ast::PtxError::from(e)))?;
let minor = v[dot+1..].parse::<u8>().map_err(|e| ParseError::from(ast::PtxError::from(e)))?;
Ok((major,minor))
}
}
@ -340,6 +340,11 @@ Directive: Option<ast::Directive<'input, ast::ParsedArgParams<'input>>> = {
File => None,
Section => None,
<v:ModuleVariable> ";" => Some(ast::Directive::Variable(v)),
! => {
let err = <>;
errors.push(err.error);
None
}
};
AddressSize = {
@ -446,7 +451,12 @@ Statement: Option<ast::Statement<ast::ParsedArgParams<'input>>> = {
<v:MultiVariable> ";" => Some(ast::Statement::Variable(v)),
<p:PredAt?> <i:Instruction> ";" => Some(ast::Statement::Instruction(p, i)),
PragmaStatement => None,
"{" <s:Statement*> "}" => Some(ast::Statement::Block(without_none(s)))
"{" <s:Statement*> "}" => Some(ast::Statement::Block(without_none(s))),
! ";" => {
let (err, _) = (<>);
errors.push(err.error);
None
}
};
PragmaStatement: () = {
@ -1754,12 +1764,12 @@ ImmediateValue: ast::ImmediateValue = {
if neg.is_some() {
match i64::from_str_radix(num, radix) {
Ok(x) => Ok(ast::ImmediateValue::S64(-x)),
Err(err) => Err(ParseError::User { error: ast::PtxError::ParseInt(err) })
Err(err) => Err(ParseError::User { error: ast::PtxError::from(err) })
}
} else if is_unsigned {
match u64::from_str_radix(num, radix) {
Ok(x) => Ok(ast::ImmediateValue::U64(x)),
Err(err) => Err(ParseError::User { error: ast::PtxError::ParseInt(err) })
Err(err) => Err(ParseError::User { error: ast::PtxError::from(err) })
}
} else {
match i64::from_str_radix(num, radix) {
@ -1767,7 +1777,7 @@ ImmediateValue: ast::ImmediateValue = {
Err(_) => {
match u64::from_str_radix(num, radix) {
Ok(x) => Ok(ast::ImmediateValue::U64(x)),
Err(err) => Err(ParseError::User { error: ast::PtxError::ParseInt(err) })
Err(err) => Err(ParseError::User { error: ast::PtxError::from(err) })
}
}
}