diff --git a/lib/reader/src/lexer.rs b/lib/reader/src/lexer.rs index e1e4cc31c4..0e8eaccd0f 100644 --- a/lib/reader/src/lexer.rs +++ b/lib/reader/src/lexer.rs @@ -223,7 +223,7 @@ impl<'a> Lexer<'a> { // - `0x0.4p-34`: Float // // This function does not filter out all invalid numbers. It depends in the context-sensitive - // decoding of the text for that. For example, the number of allowed digits an an Ieee32` and + // decoding of the text for that. For example, the number of allowed digits in an `Ieee32` and // an `Ieee64` constant are different. fn scan_number(&mut self) -> Result, LocatedError> { let begin = self.pos; @@ -231,15 +231,21 @@ impl<'a> Lexer<'a> { let mut is_float = false; // Skip a leading sign. - if self.lookahead == Some('-') { - self.next_ch(); + match self.lookahead { + Some('-') => { + self.next_ch(); - if let Some(c) = self.lookahead { - // If the next character won't parse as a number, we return Token::Minus - if !c.is_alphanumeric() && c != '.' { - return token(Token::Minus, loc); + if let Some(c) = self.lookahead { + // If the next character won't parse as a number, we return Token::Minus + if !c.is_alphanumeric() && c != '.' { + return token(Token::Minus, loc); + } } } + Some('+') => { + self.next_ch(); + } + _ => {} } // Check for NaNs with payloads. @@ -395,6 +401,7 @@ impl<'a> Lexer<'a> { Some('.') => Some(self.scan_char(Token::Dot)), Some(':') => Some(self.scan_char(Token::Colon)), Some('=') => Some(self.scan_char(Token::Equal)), + Some('+') => Some(self.scan_number()), Some('-') => { if self.looking_at("->") { Some(self.scan_chars(2, Token::Arrow)) @@ -506,7 +513,7 @@ mod tests { #[test] fn lex_numbers() { - let mut lex = Lexer::new(" 0 2_000 -1,0xf -0x0 0.0 0x0.4p-34"); + let mut lex = Lexer::new(" 0 2_000 -1,0xf -0x0 0.0 0x0.4p-34 +5"); assert_eq!(lex.next(), token(Token::Integer("0"), 1)); assert_eq!(lex.next(), token(Token::Integer("2_000"), 1)); assert_eq!(lex.next(), token(Token::Integer("-1"), 1)); @@ -515,6 +522,7 @@ mod tests { assert_eq!(lex.next(), token(Token::Integer("-0x0"), 1)); assert_eq!(lex.next(), token(Token::Float("0.0"), 1)); assert_eq!(lex.next(), token(Token::Float("0x0.4p-34"), 1)); + assert_eq!(lex.next(), token(Token::Integer("+5"), 1)); assert_eq!(lex.next(), None); } diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index b9ee4acd58..741621ed08 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -13,7 +13,7 @@ use cretonne::ir::{Function, Ebb, Opcode, Value, Type, FunctionName, StackSlotDa JumpTableData, Signature, ArgumentType, ArgumentExtension, ExtFuncData, SigRef, FuncRef, ValueLoc, ArgumentLoc}; use cretonne::ir::types::VOID; -use cretonne::ir::immediates::{Imm64, Ieee32, Ieee64}; +use cretonne::ir::immediates::{Imm64, Offset32, Ieee32, Ieee64}; use cretonne::ir::entities::AnyEntity; use cretonne::ir::instructions::{InstructionFormat, InstructionData, VariableArgs}; use cretonne::isa::{self, TargetIsa, Encoding}; @@ -497,6 +497,22 @@ impl<'a> Parser<'a> { } } + // Match and consume an optional offset32 immediate. + // + // Note that that this will match an empty string as an empty offset, and that if an offset is + // present, it must contain a sign. + fn optional_offset32(&mut self) -> Result { + if let Some(Token::Integer(text)) = self.token() { + self.consume(); + // Lexer just gives us raw text that looks like an integer. + // Parse it as an `Offset32` to check for overflow and other issues. + text.parse().map_err(|e| self.error(e)) + } else { + // An offset32 operand can be absent. + Ok(Offset32::new(0)) + } + } + // Match and consume an Ieee32 immediate. fn match_ieee32(&mut self, err_msg: &str) -> Result { if let Some(Token::Float(text)) = self.token() {