diff --git a/src/libreader/parser.rs b/src/libreader/parser.rs index f55604f32a..41742b54e7 100644 --- a/src/libreader/parser.rs +++ b/src/libreader/parser.rs @@ -110,6 +110,14 @@ impl Context { } } + // Resolve a reference to a jump table. + fn get_jt(&self, number: u32, loc: &Location) -> Result { + match self.jump_tables.get(&number) { + Some(&jt) => Ok(jt), + None => err!(loc, "undefined jump table jt{}", number), + } + } + // Allocate a new EBB and add a mapping src_ebb -> Ebb. fn add_ebb(&mut self, src_ebb: Ebb, loc: &Location) -> Result { let ebb = self.function.dfg.make_ebb(); @@ -332,12 +340,12 @@ impl<'a> Parser<'a> { } // Match and consume a jump table reference. - fn match_jt(&mut self, err_msg: &str) -> Result { + fn match_jt(&mut self) -> Result { if let Some(Token::JumpTable(jt)) = self.token() { self.consume(); Ok(jt) } else { - err!(self.loc, err_msg) + err!(self.loc, "expected jump table number: jt«n»") } } @@ -602,7 +610,7 @@ impl<'a> Parser<'a> { // // jump-table-decl ::= * JumpTable(jt) "=" "jump_table" jt-entry {"," jt-entry} fn parse_jump_table_decl(&mut self) -> Result<(u32, JumpTableData)> { - let number = try!(self.match_jt("expected jump table number: jt«n»")); + let number = try!(self.match_jt()); try!(self.match_token(Token::Equal, "expected '=' in jump_table decl")); try!(self.match_identifier("jump_table", "expected 'jump_table'")); @@ -763,7 +771,7 @@ impl<'a> Parser<'a> { }; // instruction ::= [inst-results "="] Opcode(opc) ["." Type] * ... - let inst_data = try!(self.parse_inst_operands(opcode)); + let inst_data = try!(self.parse_inst_operands(ctx, opcode)); // We're done parsing the instruction now. // @@ -914,7 +922,7 @@ impl<'a> Parser<'a> { // Parse the operands following the instruction opcode. // This depends on the format of the opcode. - fn parse_inst_operands(&mut self, opcode: Opcode) -> Result { + fn parse_inst_operands(&mut self, ctx: &Context, opcode: Opcode) -> Result { Ok(match opcode.format().unwrap() { InstructionFormat::Nullary => { InstructionData::Nullary { @@ -1096,7 +1104,17 @@ impl<'a> Parser<'a> { data: Box::new(ReturnData { args: args }), } } - InstructionFormat::BranchTable | + InstructionFormat::BranchTable => { + let arg = try!(self.match_value("expected SSA value operand")); + try!(self.match_token(Token::Comma, "expected ',' between operands")); + let table = try!(self.match_jt().and_then(|num| ctx.get_jt(num, &self.loc))); + InstructionData::BranchTable { + opcode: opcode, + ty: VOID, + arg: arg, + table: table, + } + } InstructionFormat::Call => { unimplemented!(); } diff --git a/tests/parser/branch.cton b/tests/parser/branch.cton index 148b59325c..05526fd910 100644 --- a/tests/parser/branch.cton +++ b/tests/parser/branch.cton @@ -44,11 +44,12 @@ ebb1(vx2: i32, vx3: f32): brnz vx0, ebb0(vx2, vx3) } -function jumptable() { +function jumptable(i32) { jt200 = jump_table 0, 0 jt2 = jump_table 0, 0, ebb10, ebb40, ebb20, ebb30 -ebb10: +ebb10(v3: i32): + br_table v3, jt2 trap ebb20: trap diff --git a/tests/parser/branch.cton.ref b/tests/parser/branch.cton.ref index c640a6b793..8f395c885c 100644 --- a/tests/parser/branch.cton.ref +++ b/tests/parser/branch.cton.ref @@ -38,11 +38,12 @@ ebb1(vx2: i32, vx3: f32): brnz vx0, ebb0(vx2, vx3) } -function jumptable() { +function jumptable(i32) { jt0 = jump_table 0 jt1 = jump_table 0, 0, ebb0, ebb3, ebb1, ebb2 -ebb0: +ebb0(vx0: i32): + br_table vx0, jt1 trap ebb1: