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
commit d3cd2dc8b4
3 changed files with 61 additions and 44 deletions

View file

@ -12,6 +12,7 @@ regex = "1"
rspirv = "0.6" rspirv = "0.6"
spirv_headers = "~1.4.2" spirv_headers = "~1.4.2"
quick-error = "1.2" quick-error = "1.2"
thiserror = "1.0"
bit-vec = "0.6" bit-vec = "0.6"
half ="1.6" half ="1.6"
bitflags = "1.2" 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::TryInto;
use std::{convert::From, convert::TryFrom, mem, num::ParseFloatError, str::FromStr}; use std::{convert::From, convert::TryFrom, mem, num::ParseFloatError, str::FromStr};
use std::{marker::PhantomData, num::ParseIntError}; use std::{marker::PhantomData, num::ParseIntError};
use half::f16; #[derive(Debug, thiserror::Error)]
pub enum PtxError {
quick_error! { #[error("{source}")]
#[derive(Debug)] ParseInt {
pub enum PtxError { #[from]
ParseInt (err: ParseIntError) { source: ParseIntError,
from() },
display("{}", err) #[error("{source}")]
cause(err) ParseFloat {
} #[from]
ParseFloat (err: ParseFloatError) { source: ParseFloatError,
from() },
display("{}", err) #[error("")]
cause(err) SyntaxError,
} #[error("")]
SyntaxError {} NonF32Ftz,
NonF32Ftz {} #[error("")]
WrongArrayType {} WrongArrayType,
WrongVectorElement {} #[error("")]
MultiArrayVariable {} WrongVectorElement,
ZeroDimensionArray {} #[error("")]
ArrayInitalizer {} MultiArrayVariable,
NonExternPointer {} #[error("")]
} ZeroDimensionArray,
#[error("")]
ArrayInitalizer,
#[error("")]
NonExternPointer,
} }
macro_rules! sub_enum { macro_rules! sub_enum {
@ -895,36 +901,36 @@ pub struct CvtDesc<Dst, Src> {
} }
impl CvtDetails { impl CvtDetails {
pub fn new_int_from_int_checked( pub fn new_int_from_int_checked<'err, 'input>(
saturate: bool, saturate: bool,
dst: IntType, dst: IntType,
src: IntType, src: IntType,
err: &mut Vec<PtxError>, err: &'err mut Vec<ParseError<usize, Token<'input>, PtxError>>,
) -> Self { ) -> Self {
if saturate { if saturate {
if src.is_signed() { if src.is_signed() {
if dst.is_signed() && dst.width() >= src.width() { if dst.is_signed() && dst.width() >= src.width() {
err.push(PtxError::SyntaxError); err.push(ParseError::from(PtxError::SyntaxError));
} }
} else { } else {
if dst == src || dst.width() >= src.width() { if dst == src || dst.width() >= src.width() {
err.push(PtxError::SyntaxError); err.push(ParseError::from(PtxError::SyntaxError));
} }
} }
} }
CvtDetails::IntFromInt(CvtIntToIntDesc { dst, src, saturate }) CvtDetails::IntFromInt(CvtIntToIntDesc { dst, src, saturate })
} }
pub fn new_float_from_int_checked( pub fn new_float_from_int_checked<'err, 'input>(
rounding: RoundingMode, rounding: RoundingMode,
flush_to_zero: bool, flush_to_zero: bool,
saturate: bool, saturate: bool,
dst: FloatType, dst: FloatType,
src: IntType, src: IntType,
err: &mut Vec<PtxError>, err: &'err mut Vec<ParseError<usize, Token<'input>, PtxError>>,
) -> Self { ) -> Self {
if flush_to_zero && dst != FloatType::F32 { if flush_to_zero && dst != FloatType::F32 {
err.push(PtxError::NonF32Ftz); err.push(ParseError::from(PtxError::NonF32Ftz));
} }
CvtDetails::FloatFromInt(CvtDesc { CvtDetails::FloatFromInt(CvtDesc {
dst, 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, rounding: RoundingMode,
flush_to_zero: bool, flush_to_zero: bool,
saturate: bool, saturate: bool,
dst: IntType, dst: IntType,
src: FloatType, src: FloatType,
err: &mut Vec<PtxError>, err: &'err mut Vec<ParseError<usize, Token<'input>, PtxError>>,
) -> Self { ) -> Self {
if flush_to_zero && src != FloatType::F32 { if flush_to_zero && src != FloatType::F32 {
err.push(PtxError::NonF32Ftz); err.push(ParseError::from(PtxError::NonF32Ftz));
} }
CvtDetails::IntFromFloat(CvtDesc { CvtDetails::IntFromFloat(CvtDesc {
dst, dst,

View file

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