diff --git a/docs/cton_lexer.py b/docs/cton_lexer.py index b40cb70e41..1c7224b593 100644 --- a/docs/cton_lexer.py +++ b/docs/cton_lexer.py @@ -47,10 +47,9 @@ class CretonneLexer(RegexLexer): # Well known value types. (r'\b(b\d+|i\d+|f32|f64)(x\d+)?\b', Keyword.Type), # v = value - # vx = value # ss = stack slot # jt = jump table - (r'(vx?|ss|jt)\d+', Name.Variable), + (r'(v|ss|jt)\d+', Name.Variable), # ebb = extended basic block (r'(ebb)\d+', Name.Label), # Match instruction names in context. diff --git a/filetests/isa/riscv/abi.cton b/filetests/isa/riscv/abi.cton index d75813e220..d168fd768c 100644 --- a/filetests/isa/riscv/abi.cton +++ b/filetests/isa/riscv/abi.cton @@ -3,7 +3,6 @@ test legalizer isa riscv ; regex: V=v\d+ -; regex: VX=vx\d+ function f(i32) { sig0 = signature(i32) -> i32 diff --git a/filetests/isa/riscv/expand-i32.cton b/filetests/isa/riscv/expand-i32.cton index 0415c6026c..ce335fb551 100644 --- a/filetests/isa/riscv/expand-i32.cton +++ b/filetests/isa/riscv/expand-i32.cton @@ -7,7 +7,7 @@ isa riscv supports_m=1 set is_64bit=1 isa riscv supports_m=1 -; regex: V=vx?\d+ +; regex: V=v\d+ function carry_out(i32, i32) -> i32, b1 { ebb0(v1: i32, v2: i32): diff --git a/filetests/isa/riscv/legalize-abi.cton b/filetests/isa/riscv/legalize-abi.cton index 06d68768bd..85b06b5755 100644 --- a/filetests/isa/riscv/legalize-abi.cton +++ b/filetests/isa/riscv/legalize-abi.cton @@ -2,7 +2,7 @@ test legalizer isa riscv -; regex: V=vx?\d+ +; regex: V=v\d+ function int_split_args(i64) -> i64 { ebb0(v0: i64): diff --git a/filetests/isa/riscv/legalize-i64.cton b/filetests/isa/riscv/legalize-i64.cton index dbe26f824c..dc8604f358 100644 --- a/filetests/isa/riscv/legalize-i64.cton +++ b/filetests/isa/riscv/legalize-i64.cton @@ -2,7 +2,7 @@ test legalizer isa riscv supports_m=1 -; regex: V=vx?\d+ +; regex: V=v\d+ function bitwise_and(i64, i64) -> i64 { ebb0(v1: i64, v2: i64): diff --git a/filetests/isa/riscv/split-args.cton b/filetests/isa/riscv/split-args.cton index 8c69378f42..06b09bd6d1 100644 --- a/filetests/isa/riscv/split-args.cton +++ b/filetests/isa/riscv/split-args.cton @@ -2,7 +2,7 @@ test legalizer isa riscv -; regex: V=vx?\d+ +; regex: V=v\d+ function simple(i64, i64) -> i64 { ebb0(v1: i64, v2: i64): diff --git a/filetests/parser/rewrite.cton b/filetests/parser/rewrite.cton index ffd1851114..e01391d156 100644 --- a/filetests/parser/rewrite.cton +++ b/filetests/parser/rewrite.cton @@ -12,13 +12,13 @@ test cat function defs() { ebb100(v20: i32): v1000 = iconst.i32x8 5 - vx200 = f64const 0x4.0p0 + v9200 = f64const 0x4.0p0 trap } ; sameln: function defs() { ; nextln: $ebb100($v20: i32): ; nextln: $v1000 = iconst.i32x8 5 -; nextln: $vx200 = f64const 0x1.0000000000000p2 +; nextln: $v9200 = f64const 0x1.0000000000000p2 ; nextln: trap ; nextln: } diff --git a/lib/cretonne/src/ir/dfg.rs b/lib/cretonne/src/ir/dfg.rs index 49392d8bfb..a6a85ba24c 100644 --- a/lib/cretonne/src/ir/dfg.rs +++ b/lib/cretonne/src/ir/dfg.rs @@ -2,7 +2,6 @@ use entity_map::{EntityMap, PrimaryEntityData}; use ir::builder::{InsertBuilder, ReplaceBuilder}; -use ir::entities::ExpandedValue; use ir::extfunc::ExtFuncData; use ir::instructions::{Opcode, InstructionData, CallInfo}; use ir::layout::Cursor; @@ -48,12 +47,8 @@ pub struct DataFlowGraph { /// - EBB arguments in `ebbs`. pub value_lists: ValueListPool, - /// Extended value table. Most `Value` references refer directly to their defining instruction. - /// Others index into this table. - /// - /// This is implemented directly with a `Vec` rather than an `EntityMap` because - /// the Value entity references can refer to two things -- an instruction or an extended value. - extended_values: Vec, + /// Primary value table with entries for all values. + values: EntityMap, /// Function signature table. These signatures are referenced by indirect call instructions as /// well as the external function references. @@ -65,6 +60,7 @@ pub struct DataFlowGraph { impl PrimaryEntityData for InstructionData {} impl PrimaryEntityData for EbbData {} +impl PrimaryEntityData for ValueData {} impl PrimaryEntityData for Signature {} impl PrimaryEntityData for ExtFuncData {} @@ -76,7 +72,7 @@ impl DataFlowGraph { results: EntityMap::new(), ebbs: EntityMap::new(), value_lists: ValueListPool::new(), - extended_values: Vec::new(), + values: EntityMap::new(), signatures: EntityMap::new(), ext_funcs: EntityMap::new(), } @@ -115,31 +111,20 @@ impl DataFlowGraph { impl DataFlowGraph { // Allocate an extended value entry. fn make_value(&mut self, data: ValueData) -> Value { - let vref = Value::new_table(self.extended_values.len()); - self.extended_values.push(data); - vref + self.values.push(data) } /// Check if a value reference is valid. pub fn value_is_valid(&self, v: Value) -> bool { - match v.expand() { - ExpandedValue::Direct(inst) => self.insts.is_valid(inst), - ExpandedValue::Table(index) => index < self.extended_values.len(), - } + self.values.is_valid(v) } /// Get the type of a value. pub fn value_type(&self, v: Value) -> Type { - use ir::entities::ExpandedValue::*; - match v.expand() { - Direct(_) => panic!("Unexpected direct value"), - Table(i) => { - match self.extended_values[i] { - ValueData::Inst { ty, .. } => ty, - ValueData::Arg { ty, .. } => ty, - ValueData::Alias { ty, .. } => ty, - } - } + match self.values[v] { + ValueData::Inst { ty, .. } | + ValueData::Arg { ty, .. } | + ValueData::Alias { ty, .. } => ty, } } @@ -148,31 +133,25 @@ impl DataFlowGraph { /// This is either the instruction that defined it or the Ebb that has the value as an /// argument. pub fn value_def(&self, v: Value) -> ValueDef { - use ir::entities::ExpandedValue::*; - match v.expand() { - Direct(inst) => ValueDef::Res(inst, 0), - Table(idx) => { - match self.extended_values[idx] { - ValueData::Inst { inst, num, .. } => { - assert_eq!(Some(v), - self.results[inst].get(num as usize, &self.value_lists), - "Dangling result value {}: {}", - v, - self.display_inst(inst)); - ValueDef::Res(inst, num as usize) - } - ValueData::Arg { ebb, num, .. } => { - assert_eq!(Some(v), - self.ebbs[ebb].args.get(num as usize, &self.value_lists), - "Dangling EBB argument value"); - ValueDef::Arg(ebb, num as usize) - } - ValueData::Alias { original, .. } => { - // Make sure we only recurse one level. `resolve_aliases` has safeguards to - // detect alias loops without overrunning the stack. - self.value_def(self.resolve_aliases(original)) - } - } + match self.values[v] { + ValueData::Inst { inst, num, .. } => { + assert_eq!(Some(v), + self.results[inst].get(num as usize, &self.value_lists), + "Dangling result value {}: {}", + v, + self.display_inst(inst)); + ValueDef::Res(inst, num as usize) + } + ValueData::Arg { ebb, num, .. } => { + assert_eq!(Some(v), + self.ebbs[ebb].args.get(num as usize, &self.value_lists), + "Dangling EBB argument value"); + ValueDef::Arg(ebb, num as usize) + } + ValueData::Alias { original, .. } => { + // Make sure we only recurse one level. `resolve_aliases` has safeguards to + // detect alias loops without overrunning the stack. + self.value_def(self.resolve_aliases(original)) } } } @@ -181,23 +160,15 @@ impl DataFlowGraph { /// /// Find the original SSA value that `value` aliases. pub fn resolve_aliases(&self, value: Value) -> Value { - use ir::entities::ExpandedValue::Table; let mut v = value; // Note that extended_values may be empty here. - for _ in 0..1 + self.extended_values.len() { - v = match v.expand() { - Table(idx) => { - match self.extended_values[idx] { - ValueData::Alias { original, .. } => { - // Follow alias values. - original - } - _ => return v, - } - } - _ => return v, - }; + for _ in 0..1 + self.values.len() { + if let ValueData::Alias { original, .. } = self.values[v] { + v = original; + } else { + return v; + } } panic!("Value alias loop detected for {}", value); } @@ -233,13 +204,7 @@ impl DataFlowGraph { /// /// Change the `dest` value to behave as an alias of `src`. This means that all uses of `dest` /// will behave as if they used that value `src`. - /// - /// The `dest` value cannot be a direct value defined as the first result of an instruction. To - /// replace a direct value with `src`, its defining instruction should be replaced with a - /// `copy src` instruction. See `replace()`. pub fn change_to_alias(&mut self, dest: Value, src: Value) { - use ir::entities::ExpandedValue::Table; - // Try to create short alias chains by finding the original source value. // This also avoids the creation of loops. let original = self.resolve_aliases(src); @@ -256,14 +221,10 @@ impl DataFlowGraph { self.value_type(dest), ty); - if let Table(idx) = dest.expand() { - self.extended_values[idx] = ValueData::Alias { - ty: ty, - original: original, - }; - } else { - panic!("Cannot change direct value {} into an alias", dest); - } + self.values[dest] = ValueData::Alias { + ty: ty, + original: original, + }; } /// Create a new value alias. @@ -458,15 +419,11 @@ impl DataFlowGraph { let num = self.results[inst].push(res, &mut self.value_lists); assert!(num <= u16::MAX as usize, "Too many result values"); let ty = self.value_type(res); - if let ExpandedValue::Table(idx) = res.expand() { - self.extended_values[idx] = ValueData::Inst { - ty: ty, - num: num as u16, - inst: inst, - }; - } else { - panic!("Unexpected direct value"); - } + self.values[res] = ValueData::Inst { + ty: ty, + num: num as u16, + inst: inst, + }; } /// Append a new instruction result value to `inst`. @@ -609,11 +566,7 @@ impl DataFlowGraph { /// /// Returns the new value. pub fn replace_ebb_arg(&mut self, old_arg: Value, new_type: Type) -> Value { - let old_data = if let ExpandedValue::Table(index) = old_arg.expand() { - self.extended_values[index].clone() - } else { - panic!("old_arg: {} must be an EBB argument", old_arg); - }; + let old_data = self.values[old_arg].clone(); // Create new value identical to the old one except for the type. let (ebb, num) = if let ValueData::Arg { num, ebb, .. } = old_data { @@ -655,12 +608,10 @@ impl DataFlowGraph { // Now update `arg` itself. let arg_ebb = ebb; - if let ExpandedValue::Table(idx) = arg.expand() { - if let ValueData::Arg { ref mut num, ebb, .. } = self.extended_values[idx] { - *num = arg_num as u16; - assert_eq!(arg_ebb, ebb, "{} should already belong to EBB", arg); - return; - } + if let ValueData::Arg { ref mut num, ebb, .. } = self.values[arg] { + *num = arg_num as u16; + assert_eq!(arg_ebb, ebb, "{} should already belong to EBB", arg); + return; } panic!("{} must be an EBB argument value", arg); } @@ -724,7 +675,7 @@ mod tests { let inst = dfg.make_inst(idata); dfg.make_inst_results(inst, types::I32); assert_eq!(inst.to_string(), "inst0"); - assert_eq!(dfg.display_inst(inst).to_string(), "vx0 = iconst.i32"); + assert_eq!(dfg.display_inst(inst).to_string(), "v0 = iconst.i32"); // Immutable reference resolution. { @@ -766,12 +717,12 @@ mod tests { assert_eq!(dfg.ebb_args(ebb), &[]); let arg1 = dfg.append_ebb_arg(ebb, types::F32); - assert_eq!(arg1.to_string(), "vx0"); + assert_eq!(arg1.to_string(), "v0"); assert_eq!(dfg.num_ebb_args(ebb), 1); assert_eq!(dfg.ebb_args(ebb), &[arg1]); let arg2 = dfg.append_ebb_arg(ebb, types::I16); - assert_eq!(arg2.to_string(), "vx1"); + assert_eq!(arg2.to_string(), "v1"); assert_eq!(dfg.num_ebb_args(ebb), 2); assert_eq!(dfg.ebb_args(ebb), &[arg1, arg2]); @@ -835,7 +786,7 @@ mod tests { // Build a little test program. let v1 = dfg.ins(pos).iconst(types::I32, 42); - // Make sure we can resolve value aliases even when extended_values is empty. + // Make sure we can resolve value aliases even when values is empty. assert_eq!(dfg.resolve_aliases(v1), v1); let arg0 = dfg.append_ebb_arg(ebb0, types::I32); diff --git a/lib/cretonne/src/ir/entities.rs b/lib/cretonne/src/ir/entities.rs index 876598d13a..813ec978c2 100644 --- a/lib/cretonne/src/ir/entities.rs +++ b/lib/cretonne/src/ir/entities.rs @@ -76,97 +76,20 @@ impl Ebb { /// An opaque reference to an SSA value. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct Value(u32); -entity_impl!(Value); - -/// Value references can either reference an instruction directly, or they can refer to the -/// extended value table. -pub enum ExpandedValue { - /// This is the first value produced by the referenced instruction. - Direct(Inst), - - /// This value is described in the extended value table. - Table(usize), -} +entity_impl!(Value, "v"); impl Value { - /// Create a `Direct` value from its number representation. + /// Create a value from its number representation. /// This is the number in the `vNN` notation. /// /// This method is for use by the parser. - pub fn direct_with_number(n: u32) -> Option { + pub fn with_number(n: u32) -> Option { if n < u32::MAX / 2 { - let encoding = n * 2; - assert!(encoding < u32::MAX); - Some(Value(encoding)) + Some(Value(n)) } else { None } } - - /// Create a `Table` value from its number representation. - /// This is the number in the `vxNN` notation. - /// - /// This method is for use by the parser. - pub fn table_with_number(n: u32) -> Option { - if n < u32::MAX / 2 { - let encoding = n * 2 + 1; - assert!(encoding < u32::MAX); - Some(Value(encoding)) - } else { - None - } - } - - /// Create a `Direct` value corresponding to the first value produced by `i`. - pub fn new_direct(i: Inst) -> Value { - let encoding = i.index() * 2; - assert!(encoding < u32::MAX as usize); - Value(encoding as u32) - } - - /// Create a `Table` value referring to entry `i` in the `DataFlowGraph.extended_values` table. - /// This constructor should not be used directly. Use the public `DataFlowGraph` methods to - /// manipulate values. - pub fn new_table(index: usize) -> Value { - let encoding = index * 2 + 1; - assert!(encoding < u32::MAX as usize); - Value(encoding as u32) - } - - /// Expand the internal representation into something useful. - pub fn expand(&self) -> ExpandedValue { - use self::ExpandedValue::*; - let index = (self.0 / 2) as usize; - if self.0 % 2 == 0 { - Direct(Inst::new(index)) - } else { - Table(index) - } - } - - /// Assuming that this is a direct value, get the referenced instruction. - /// - /// # Panics - /// - /// If this is not a value created with `new_direct()`. - pub fn unwrap_direct(&self) -> Inst { - if let ExpandedValue::Direct(inst) = self.expand() { - inst - } else { - panic!("{} is not a direct value", self) - } - } -} - -/// Display a `Value` reference as "v7" or "v2x". -impl Display for Value { - fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - use self::ExpandedValue::*; - match self.expand() { - Direct(i) => write!(fmt, "v{}", i.0), - Table(i) => write!(fmt, "vx{}", i), - } - } } /// An opaque reference to an instruction in a function. @@ -276,32 +199,14 @@ impl From for AnyEntity { mod tests { use super::*; use std::u32; - use entity_map::EntityRef; #[test] fn value_with_number() { - assert_eq!(Value::direct_with_number(0).unwrap().to_string(), "v0"); - assert_eq!(Value::direct_with_number(1).unwrap().to_string(), "v1"); - assert_eq!(Value::table_with_number(0).unwrap().to_string(), "vx0"); - assert_eq!(Value::table_with_number(1).unwrap().to_string(), "vx1"); + assert_eq!(Value::with_number(0).unwrap().to_string(), "v0"); + assert_eq!(Value::with_number(1).unwrap().to_string(), "v1"); - assert_eq!(Value::direct_with_number(u32::MAX / 2), None); - assert_eq!(match Value::direct_with_number(u32::MAX / 2 - 1) - .unwrap() - .expand() { - ExpandedValue::Direct(i) => i.index() as u32, - _ => u32::MAX, - }, - u32::MAX / 2 - 1); - - assert_eq!(Value::table_with_number(u32::MAX / 2), None); - assert_eq!(match Value::table_with_number(u32::MAX / 2 - 1) - .unwrap() - .expand() { - ExpandedValue::Table(i) => i as u32, - _ => u32::MAX, - }, - u32::MAX / 2 - 1); + assert_eq!(Value::with_number(u32::MAX / 2), None); + assert!(Value::with_number(u32::MAX / 2 - 1).is_some()); } #[test] diff --git a/lib/cretonne/src/isa/riscv/mod.rs b/lib/cretonne/src/isa/riscv/mod.rs index 8bf9d7b732..778e3b85aa 100644 --- a/lib/cretonne/src/isa/riscv/mod.rs +++ b/lib/cretonne/src/isa/riscv/mod.rs @@ -115,7 +115,7 @@ mod tests { let arg64 = dfg.append_ebb_arg(ebb, types::I64); let arg32 = dfg.append_ebb_arg(ebb, types::I32); - // Try to encode iadd_imm.i64 vx1, -10. + // Try to encode iadd_imm.i64 v1, -10. let inst64 = InstructionData::BinaryImm { opcode: Opcode::IaddImm, arg: arg64, @@ -126,7 +126,7 @@ mod tests { assert_eq!(encstr(&*isa, isa.encode(&dfg, &inst64, types::I64).unwrap()), "I#04"); - // Try to encode iadd_imm.i64 vx1, -10000. + // Try to encode iadd_imm.i64 v1, -10000. let inst64_large = InstructionData::BinaryImm { opcode: Opcode::IaddImm, arg: arg64, @@ -162,7 +162,7 @@ mod tests { let arg64 = dfg.append_ebb_arg(ebb, types::I64); let arg32 = dfg.append_ebb_arg(ebb, types::I32); - // Try to encode iadd_imm.i64 vx1, -10. + // Try to encode iadd_imm.i64 v1, -10. let inst64 = InstructionData::BinaryImm { opcode: Opcode::IaddImm, arg: arg64, @@ -173,7 +173,7 @@ mod tests { assert_eq!(isa.encode(&dfg, &inst64, types::I64), Err(isa::Legalize::Narrow)); - // Try to encode iadd_imm.i64 vx1, -10000. + // Try to encode iadd_imm.i64 v1, -10000. let inst64_large = InstructionData::BinaryImm { opcode: Opcode::IaddImm, arg: arg64, diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index 023eb4ee7a..09e5ee6641 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -86,8 +86,8 @@ pub fn write_ebb_header(w: &mut Write, func: &Function, ebb: Ebb) -> Result { // Write out the basic block header, outdented: // // ebb1: - // ebb1(vx1: i32): - // ebb10(vx4: f64, vx5: b1): + // ebb1(v1: i32): + // ebb10(v4: f64, v5: b1): // // If we're writing encoding annotations, shift by 20. @@ -372,10 +372,10 @@ mod tests { f.dfg.append_ebb_arg(ebb, types::I8); assert_eq!(f.to_string(), - "function foo() {\n ss0 = stack_slot 4\n\nebb0(vx0: i8):\n}\n"); + "function foo() {\n ss0 = stack_slot 4\n\nebb0(v0: i8):\n}\n"); f.dfg.append_ebb_arg(ebb, types::F32.by(4).unwrap()); assert_eq!(f.to_string(), - "function foo() {\n ss0 = stack_slot 4\n\nebb0(vx0: i8, vx1: f32x4):\n}\n"); + "function foo() {\n ss0 = stack_slot 4\n\nebb0(v0: i8, v1: f32x4):\n}\n"); } } diff --git a/lib/reader/src/lexer.rs b/lib/reader/src/lexer.rs index 0e8eaccd0f..14a0fe45a4 100644 --- a/lib/reader/src/lexer.rs +++ b/lib/reader/src/lexer.rs @@ -34,7 +34,7 @@ pub enum Token<'a> { Float(&'a str), // Floating point immediate Integer(&'a str), // Integer immediate Type(types::Type), // i32, f32, b32x4, ... - Value(Value), // v12, vx7 + Value(Value), // v12, v7 Ebb(Ebb), // ebb3 StackSlot(u32), // ss3 JumpTable(u32), // jt2 @@ -306,8 +306,7 @@ impl<'a> Lexer<'a> { // decoded token. fn numbered_entity(prefix: &str, number: u32) -> Option> { match prefix { - "v" => Value::direct_with_number(number).map(|v| Token::Value(v)), - "vx" => Value::table_with_number(number).map(|v| Token::Value(v)), + "v" => Value::with_number(number).map(|v| Token::Value(v)), "ebb" => Ebb::with_number(number).map(|ebb| Token::Ebb(ebb)), "ss" => Some(Token::StackSlot(number)), "jt" => Some(Token::JumpTable(number)), @@ -531,15 +530,14 @@ mod tests { let mut lex = Lexer::new("v0 v00 vx01 ebb1234567890 ebb5234567890 v1x vx1 vxvx4 \ function0 function b1 i32x4 f32x5"); assert_eq!(lex.next(), - token(Token::Value(Value::direct_with_number(0).unwrap()), 1)); + token(Token::Value(Value::with_number(0).unwrap()), 1)); assert_eq!(lex.next(), token(Token::Identifier("v00"), 1)); assert_eq!(lex.next(), token(Token::Identifier("vx01"), 1)); assert_eq!(lex.next(), token(Token::Ebb(Ebb::with_number(1234567890).unwrap()), 1)); assert_eq!(lex.next(), token(Token::Identifier("ebb5234567890"), 1)); assert_eq!(lex.next(), token(Token::Identifier("v1x"), 1)); - assert_eq!(lex.next(), - token(Token::Value(Value::table_with_number(1).unwrap()), 1)); + assert_eq!(lex.next(), token(Token::Identifier("vx1"), 1)); assert_eq!(lex.next(), token(Token::Identifier("vxvx4"), 1)); assert_eq!(lex.next(), token(Token::Identifier("function0"), 1)); assert_eq!(lex.next(), token(Token::Identifier("function"), 1)); diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index dcc76b1b15..ac2754a46c 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -1011,7 +1011,7 @@ impl<'a> Parser<'a> { // We need to parse instruction results here because they are shared // between the parsing of value aliases and the parsing of instructions. // - // inst-results ::= Value(v) { "," Value(vx) } + // inst-results ::= Value(v) { "," Value(v) } let results = self.parse_inst_results()?; match self.token() { @@ -1032,7 +1032,7 @@ impl<'a> Parser<'a> { } // Parse parenthesized list of EBB arguments. Returns a vector of (u32, Type) pairs with the - // source vx numbers of the defined values and the defined types. + // source value numbers of the defined values and the defined types. // // ebb-args ::= * "(" ebb-arg { "," ebb-arg } ")" fn parse_ebb_args(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> { @@ -1056,19 +1056,19 @@ impl<'a> Parser<'a> { // Parse a single EBB argument declaration, and append it to `ebb`. // - // ebb-arg ::= * Value(vx) ":" Type(t) + // ebb-arg ::= * Value(v) ":" Type(t) // fn parse_ebb_arg(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> { - // ebb-arg ::= * Value(vx) ":" Type(t) - let vx = self.match_value("EBB argument must be a value")?; - let vx_location = self.loc; - // ebb-arg ::= Value(vx) * ":" Type(t) + // ebb-arg ::= * Value(v) ":" Type(t) + let v = self.match_value("EBB argument must be a value")?; + let v_location = self.loc; + // ebb-arg ::= Value(v) * ":" Type(t) self.match_token(Token::Colon, "expected ':' after EBB argument")?; - // ebb-arg ::= Value(vx) ":" * Type(t) + // ebb-arg ::= Value(v) ":" * Type(t) let t = self.match_type("expected EBB argument type")?; // Allocate the EBB argument and add the mapping. let value = ctx.function.dfg.append_ebb_arg(ebb, t); - ctx.map.def_value(vx, value, &vx_location) + ctx.map.def_value(v, value, &v_location) } fn parse_value_location(&mut self, ctx: &Context) -> Result { @@ -1147,21 +1147,21 @@ impl<'a> Parser<'a> { // Parse instruction results and return them. // - // inst-results ::= Value(v) { "," Value(vx) } + // inst-results ::= Value(v) { "," Value(v) } // fn parse_inst_results(&mut self) -> Result> { // Result value numbers. let mut results = Vec::new(); // instruction ::= * [inst-results "="] Opcode(opc) ["." Type] ... - // inst-results ::= * Value(v) { "," Value(vx) } + // inst-results ::= * Value(v) { "," Value(v) } if let Some(Token::Value(v)) = self.token() { self.consume(); results.push(v); - // inst-results ::= Value(v) * { "," Value(vx) } + // inst-results ::= Value(v) * { "," Value(v) } while self.optional(Token::Comma) { - // inst-results ::= Value(v) { "," * Value(vx) } + // inst-results ::= Value(v) { "," * Value(v) } results.push(self.match_value("expected result value")?); } } @@ -1171,7 +1171,7 @@ impl<'a> Parser<'a> { // Parse a value alias, and append it to `ebb`. // - // value_alias ::= [inst-results] "->" Value(vx) + // value_alias ::= [inst-results] "->" Value(v) // fn parse_value_alias(&mut self, results: Vec, ctx: &mut Context) -> Result<()> { if results.len() != 1 { @@ -1711,19 +1711,23 @@ mod tests { let (func, details) = Parser::new("function qux() { ebb0: v4 = iconst.i8 6 - vx3 -> v4 - v1 = iadd_imm vx3, 17 + v3 -> v4 + v1 = iadd_imm v3, 17 }") .parse_function(None) .unwrap(); assert_eq!(func.name.to_string(), "qux"); let v4 = details.map.lookup_str("v4").unwrap(); - assert_eq!(v4.to_string(), "vx0"); - let vx3 = details.map.lookup_str("vx3").unwrap(); - assert_eq!(vx3.to_string(), "vx2"); - let aliased_to = func.dfg - .resolve_aliases(Value::table_with_number(0).unwrap()); - assert_eq!(aliased_to.to_string(), "vx0"); + assert_eq!(v4.to_string(), "v0"); + let v3 = details.map.lookup_str("v3").unwrap(); + assert_eq!(v3.to_string(), "v2"); + match v3 { + AnyEntity::Value(v3) => { + let aliased_to = func.dfg.resolve_aliases(v3); + assert_eq!(aliased_to.to_string(), "v0"); + } + _ => panic!("expected value: {}", v3), + } } #[test] @@ -1789,7 +1793,7 @@ mod tests { fn ebb_header() { let (func, _) = Parser::new("function ebbs() { ebb0: - ebb4(vx3: i32): + ebb4(v3: i32): }") .parse_function(None) .unwrap(); diff --git a/lib/reader/src/sourcemap.rs b/lib/reader/src/sourcemap.rs index 7f387ccee2..f84c792d89 100644 --- a/lib/reader/src/sourcemap.rs +++ b/lib/reader/src/sourcemap.rs @@ -16,7 +16,7 @@ use lexer::split_entity_name; /// Mapping from source entity names to entity references that are valid in the parsed function. #[derive(Debug)] pub struct SourceMap { - values: HashMap, // vNN, vxNN + values: HashMap, // vNN ebbs: HashMap, // ebbNN stack_slots: HashMap, // ssNN signatures: HashMap, // sigNN @@ -64,12 +64,7 @@ impl SourceMap { pub fn lookup_str(&self, name: &str) -> Option { split_entity_name(name).and_then(|(ent, num)| match ent { "v" => { - Value::direct_with_number(num) - .and_then(|v| self.get_value(v)) - .map(AnyEntity::Value) - } - "vx" => { - Value::table_with_number(num) + Value::with_number(num) .and_then(|v| self.get_value(v)) .map(AnyEntity::Value) } @@ -230,8 +225,8 @@ mod tests { let tf = parse_test("function detail() { ss10 = stack_slot 13 jt10 = jump_table ebb0 - ebb0(v4: i32, vx7: i32): - v10 = iadd v4, vx7 + ebb0(v4: i32, v7: i32): + v10 = iadd v4, v7 }") .unwrap(); let map = &tf.functions[0].1.map; @@ -241,8 +236,8 @@ mod tests { assert_eq!(map.lookup_str("ss10").unwrap().to_string(), "ss0"); assert_eq!(map.lookup_str("jt10").unwrap().to_string(), "jt0"); assert_eq!(map.lookup_str("ebb0").unwrap().to_string(), "ebb0"); - assert_eq!(map.lookup_str("v4").unwrap().to_string(), "vx0"); - assert_eq!(map.lookup_str("vx7").unwrap().to_string(), "vx1"); - assert_eq!(map.lookup_str("v10").unwrap().to_string(), "vx2"); + assert_eq!(map.lookup_str("v4").unwrap().to_string(), "v0"); + assert_eq!(map.lookup_str("v7").unwrap().to_string(), "v1"); + assert_eq!(map.lookup_str("v10").unwrap().to_string(), "v2"); } } diff --git a/misc/vim/syntax/cton.vim b/misc/vim/syntax/cton.vim index 7d6bdab08c..86162d8a50 100644 --- a/misc/vim/syntax/cton.vim +++ b/misc/vim/syntax/cton.vim @@ -18,7 +18,7 @@ syn keyword ctonDecl function stack_slot jump_table syn keyword ctonFilecheck check sameln nextln unordered not regex contained syn match ctonType /\<[bif]\d\+\(x\d\+\)\?\>/ -syn match ctonEntity /\<\(v\|vx\|ss\|jt\|fn\|sig\)\d\+\>/ +syn match ctonEntity /\<\(v\|ss\|jt\|fn\|sig\)\d\+\>/ syn match ctonLabel /\/ syn match ctonName /%\w\+\>/