From cfdecfdcbf738a7017aa543a7542265fc77231df Mon Sep 17 00:00:00 2001 From: Angus Holder Date: Thu, 9 Mar 2017 02:45:20 +0000 Subject: [PATCH] We now parse and record a ValueLoc for each SSA value result of each instruction. Code currently not passing tests. --- filetests/parser/instruction_encoding.cton | 9 ++- lib/reader/src/parser.rs | 67 +++++++++++++++++----- 2 files changed, 57 insertions(+), 19 deletions(-) diff --git a/filetests/parser/instruction_encoding.cton b/filetests/parser/instruction_encoding.cton index 0e40d0b2f1..4971cba510 100644 --- a/filetests/parser/instruction_encoding.cton +++ b/filetests/parser/instruction_encoding.cton @@ -15,11 +15,10 @@ ebb1(v0: i32, v1: i32): } ; sameln: function foo(i32, i32) { ; nextln: $ebb1($v0: i32, $v1: i32): -; nextln: [-]$WS $v2 = iadd $v0, $v1 +; nextln: [-,-]$WS $v2 = iadd $v0, $v1 ; nextln: [-]$WS trap -; nextln: [R#1234]$WS $v6, $v7 = iadd_cout $v2, $v0 -; TODO Add the full encoding information available: instruction recipe name and architectural registers if specified -; nextln: [Rshamt#beef]$WS $v8 = ishl_imm $v6, 2 -; nextln: [-]$WS $v9 = iadd $v8, $v7 +; nextln: [R#1234,%x5,%x11]$WS $v6, $v7 = iadd_cout $v2, $v0 +; nextln: [Rshamt#beef,%x25]$WS $v8 = ishl_imm $v6, 2 +; nextln: [-,-]$WS $v9 = iadd $v8, $v7 ; nextln: [Iret#05]$WS return $v0, $v8 ; nextln: } diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index 1c71f9f4f5..7427139a4d 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -10,7 +10,7 @@ use std::{u16, u32}; use std::mem; use cretonne::ir::{Function, Ebb, Opcode, Value, Type, FunctionName, StackSlotData, JumpTable, JumpTableData, Signature, ArgumentType, ArgumentExtension, ExtFuncData, SigRef, - FuncRef}; + FuncRef, ValueLoc}; use cretonne::ir::types::VOID; use cretonne::ir::immediates::{Imm64, Ieee32, Ieee64}; use cretonne::ir::entities::AnyEntity; @@ -959,9 +959,32 @@ impl<'a> Parser<'a> { ctx.map.def_value(vx, value, &vx_location) } + fn parse_value_location(&mut self, ctx: &Context, isa: &TargetIsa) -> Result { + let reginfo = isa.register_info(); + match self.token() { + Some(Token::StackSlot(src_num)) => { + self.consume(); + if let Some(ss) = ctx.map.get_ss(src_num) { + Ok(ValueLoc::Stack(ss)) + } else { + err!(self.loc, + "attempted to use undefined stack slot ss{}", + src_num) + } + } + Some(Token::Name(name)) => { + self.consume(); + reginfo.parse_regunit(name) + .map(ValueLoc::Reg) + .ok_or(self.error("invalid register value location")) + } + _ => err!(self.loc, "invalid value location"), + } + } + fn parse_instruction_encoding(&mut self, ctx: &Context) - -> Result<(Option, Option>)> { + -> Result<(Option, Option>)> { let (mut encoding, mut result_registers) = (None, None); // encoding ::= "[" encoding_literal result_registers "]" @@ -984,11 +1007,13 @@ impl<'a> Parser<'a> { // result_registers ::= ("," ( "-" | names ) )? // names ::= Name { "," Name } if self.optional(Token::Comma) && !self.optional(Token::Minus) { + let isa = ctx.unique_isa + .ok_or(self.error("value locations specified without a unique isa"))?; let mut result = Vec::new(); - result.push(self.match_name("expected register")?); + result.push(self.parse_value_location(ctx, isa)?); while self.optional(Token::Comma) { - result.push(self.match_name("expected register")?); + result.push(self.parse_value_location(ctx, isa)?); } result_registers = Some(result); @@ -1010,7 +1035,7 @@ impl<'a> Parser<'a> { // Collect comments for the next instruction to be allocated. self.gather_comments(ctx.function.dfg.next_inst()); - let (encoding, result_registers) = self.parse_instruction_encoding(ctx)?; + let (encoding, result_locations) = self.parse_instruction_encoding(ctx)?; // Result value numbers. let mut results = Vec::new(); @@ -1030,13 +1055,6 @@ impl<'a> Parser<'a> { self.match_token(Token::Equal, "expected '=' before opcode")?; } - if let Some(ref result_registers) = result_registers { - if result_registers.len() != results.len() { - return err!(self.loc, - "must have same number of result registers as results"); - } - } - // instruction ::= [inst-results "="] * Opcode(opc) ["." Type] ... let opcode = if let Some(Token::Identifier(text)) = self.token() { match text.parse() { @@ -1086,8 +1104,29 @@ impl<'a> Parser<'a> { // Pass a reference to `ctx.values` instead of `ctx` itself since the `Values` iterator // holds a reference to `ctx.function`. self.add_values(&mut ctx.map, - results.into_iter(), - ctx.function.dfg.inst_results(inst)) + results.iter().map(|v| *v), + ctx.function.dfg.inst_results(inst))?; + + if let Some(ref result_locations) = result_locations { + if result_locations.len() != results.len() { + return err!(self.loc, + "must have same number of result locations as results"); + } else { + for (&src_value, &loc) in results.iter().zip(result_locations) { + // We are safe to unwrap here because all values should have been added to the + // map in the above call to self.add_values() + let value = ctx.map.get_value(src_value).unwrap(); + *ctx.function.locations.ensure(value) = loc; + } + } + } else { + for &src_value in results.iter() { + let value = ctx.map.get_value(src_value).unwrap(); + *ctx.function.locations.ensure(value) = ValueLoc::Unassigned; + } + } + + Ok(()) } // Type inference for polymorphic instructions.