From d3cd2dc8b4695eee12189c4eb9d465f538878a29 Mon Sep 17 00:00:00 2001 From: Andrzej Janik Date: Mon, 1 Mar 2021 02:24:27 +0100 Subject: [PATCH] Do slightly better when it comes to PTX error recovery --- ptx/Cargo.toml | 3 +- ptx/src/ast.rs | 74 ++++++++++++++++++++++++--------------------- ptx/src/ptx.lalrpop | 28 +++++++++++------ 3 files changed, 61 insertions(+), 44 deletions(-) diff --git a/ptx/Cargo.toml b/ptx/Cargo.toml index 409cd1f..1d51e8b 100644 --- a/ptx/Cargo.toml +++ b/ptx/Cargo.toml @@ -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" diff --git a/ptx/src/ast.rs b/ptx/src/ast.rs index d81cd66..59d9f96 100644 --- a/ptx/src/ast.rs +++ b/ptx/src/ast.rs @@ -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 { } 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, + err: &'err mut Vec, 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, + err: &'err mut Vec, 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, + err: &'err mut Vec, PtxError>>, ) -> Self { if flush_to_zero && src != FloatType::F32 { - err.push(PtxError::NonF32Ftz); + err.push(ParseError::from(PtxError::NonF32Ftz)); } CvtDetails::IntFromFloat(CvtDesc { dst, diff --git a/ptx/src/ptx.lalrpop b/ptx/src/ptx.lalrpop index fd2a3f1..50d6767 100644 --- a/ptx/src/ptx.lalrpop +++ b/ptx/src/ptx.lalrpop @@ -5,7 +5,7 @@ use crate::{without_none, vector_index}; use lalrpop_util::ParseError; use std::convert::TryInto; -grammar<'a>(errors: &mut Vec); +grammar<'err>(errors: &'err mut Vec, ast::PtxError>>); extern { type Error = ast::PtxError; @@ -313,11 +313,11 @@ pub Module: ast::Module<'input> = { }; Version: (u8, u8) = { - ".version" => { + ".version" =>? { let dot = v.find('.').unwrap(); - let major = v[..dot].parse::(); - let minor = v[dot+1..].parse::(); - (major,minor).unwrap_with(errors) + let major = v[..dot].parse::().map_err(|e| ParseError::from(ast::PtxError::from(e)))?; + let minor = v[dot+1..].parse::().map_err(|e| ParseError::from(ast::PtxError::from(e)))?; + Ok((major,minor)) } } @@ -340,6 +340,11 @@ Directive: Option>> = { File => None, Section => None, ";" => Some(ast::Directive::Variable(v)), + ! => { + let err = <>; + errors.push(err.error); + None + } }; AddressSize = { @@ -446,7 +451,12 @@ Statement: Option>> = { ";" => Some(ast::Statement::Variable(v)), ";" => Some(ast::Statement::Instruction(p, i)), PragmaStatement => None, - "{" "}" => Some(ast::Statement::Block(without_none(s))) + "{" "}" => 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) }) } } }