From 7f8479e0971e55de6142d3720547cdf3afdca812 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 6 Jul 2016 13:36:15 -0700 Subject: [PATCH] Parse insertlane and extractlane instruction formats. These instruction formats take immediate lane index operands. We store these as u8 fields and require them to be in decimal format in the source. No hexadecimal lane indexes are supported. --- cranelift/src/libreader/parser.rs | 39 ++++++++++++++++++++++++++-- cranelift/tests/parser/tiny.cton | 10 ++++++- cranelift/tests/parser/tiny.cton.ref | 7 +++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/cranelift/src/libreader/parser.rs b/cranelift/src/libreader/parser.rs index 82e17aea5f..ca8f56232b 100644 --- a/cranelift/src/libreader/parser.rs +++ b/cranelift/src/libreader/parser.rs @@ -247,6 +247,19 @@ impl<'a> Parser<'a> { } } + // Match and consume a u8 immediate. + // This is used for lane numbers in SIMD vectors. + fn match_u8(&mut self, err_msg: &str) -> 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 a u8 to check for overflow and other issues. + text.parse().map_err(|_| self.error("expected u8 decimal immediate")) + } else { + err!(self.loc, err_msg) + } + } + // Match and consume an Ieee32 immediate. fn match_ieee32(&mut self, err_msg: &str) -> Result { if let Some(Token::Float(text)) = self.token() { @@ -831,8 +844,30 @@ impl<'a> Parser<'a> { }), } } - InstructionFormat::InsertLane | - InstructionFormat::ExtractLane | + InstructionFormat::InsertLane => { + let lhs = try!(self.match_value("expected SSA value first operand")); + try!(self.match_token(Token::Comma, "expected ',' between operands")); + let lane = try!(self.match_u8("expected lane number")); + try!(self.match_token(Token::Comma, "expected ',' between operands")); + let rhs = try!(self.match_value("expected SSA value last operand")); + InstructionData::InsertLane { + opcode: opcode, + ty: VOID, + lane: lane, + args: [lhs, rhs], + } + } + InstructionFormat::ExtractLane => { + let arg = try!(self.match_value("expected SSA value last operand")); + try!(self.match_token(Token::Comma, "expected ',' between operands")); + let lane = try!(self.match_u8("expected lane number")); + InstructionData::ExtractLane { + opcode: opcode, + ty: VOID, + lane: lane, + arg: arg, + } + } InstructionFormat::BranchTable | InstructionFormat::Call => { unimplemented!(); diff --git a/cranelift/tests/parser/tiny.cton b/cranelift/tests/parser/tiny.cton index 5e38d5efbb..6be261e273 100644 --- a/cranelift/tests/parser/tiny.cton +++ b/cranelift/tests/parser/tiny.cton @@ -15,6 +15,14 @@ ebb0: ; Polymorphic istruction controlled by second operand. function select() { -ebb0(vx0: i32, vx1:i32, vx2: b1): +ebb0(vx0: i32, vx1: i32, vx2: b1): v0 = select vx2, vx0, vx1 } + +; Lane indexes. +function lanes() { +ebb0: + v0 = iconst.i32x4 2 + v1 = extractlane v0, 3 + v2 = insertlane v0, 1, v1 +} diff --git a/cranelift/tests/parser/tiny.cton.ref b/cranelift/tests/parser/tiny.cton.ref index 29b604f29d..1fc1745a34 100644 --- a/cranelift/tests/parser/tiny.cton.ref +++ b/cranelift/tests/parser/tiny.cton.ref @@ -14,3 +14,10 @@ function select() { ebb0(vx0: i32, vx1: i32, vx2: b1): v0 = select vx2, vx0, vx1 } + +function lanes() { +ebb0: + v0 = iconst.i32x4 2 + v1 = extractlane v0, 3 + v2 = insertlane v0, 1, v1 +}