From 0daa560368d168ea6b992354771de976b22e72cf Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 7 Jun 2018 15:56:23 -0700 Subject: [PATCH] Accept redundant alias definitions. In the text format, allow aliases to be defined multiple times, as long as they're always aliasing the same value. write.rs is already emitting redundant aliases, because it emits them at their uses, so this change allows the parser to be able to parse such code. --- cranelift/filetests/parser/alias.cton | 32 +++++++++++++++++++++++++++ lib/codegen/src/ir/dfg.rs | 12 ++++++++++ lib/reader/src/parser.rs | 31 +++++++++++++++++++++----- 3 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 cranelift/filetests/parser/alias.cton diff --git a/cranelift/filetests/parser/alias.cton b/cranelift/filetests/parser/alias.cton new file mode 100644 index 0000000000..4e253bdb03 --- /dev/null +++ b/cranelift/filetests/parser/alias.cton @@ -0,0 +1,32 @@ +test cat +test verifier + +function %basic(i32, i32) -> i32 { +ebb0(v0: i32, v1: i32): + v2 -> v0 + v3 -> v1 + v4 = iadd.i32 v2, v3 + return v4 +} + +function %transitive() -> i32 { +ebb0: + v0 = iconst.i32 0 + v1 -> v0 + v2 -> v1 + v3 -> v2 + v4 -> v3 + return v4 +} + +function %duplicate(i32, i32) -> i32 { +ebb0(v0: i32, v1: i32): + v2 -> v0 + v2 -> v0 + v2 -> v0 + v3 -> v1 + v3 -> v1 + v3 -> v1 + v4 = iadd.i32 v2, v3 + return v4 +} diff --git a/lib/codegen/src/ir/dfg.rs b/lib/codegen/src/ir/dfg.rs index 21c3cc9b66..9db7364002 100644 --- a/lib/codegen/src/ir/dfg.rs +++ b/lib/codegen/src/ir/dfg.rs @@ -949,6 +949,18 @@ impl DataFlowGraph { self.values[dest] = data; } + /// If `v` is already defined as an alias, return its destination value. + /// Otherwise return None. This allows the parser to coalesce identical + /// alias definitions. + #[cold] + pub fn value_alias_dest_for_parser(&self, v: Value) -> Option { + if let ValueData::Alias { original, .. } = self.values[v] { + Some(original) + } else { + None + } + } + /// Compute the type of an alias. This is only for use in the parser. /// Returns false if an alias cycle was encountered. #[cold] diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index a6586fea74..256ba50847 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -1580,13 +1580,34 @@ impl<'a> Parser<'a> { if results.len() != 1 { return err!(self.loc, "wrong number of aliases"); } + let result = results[0]; let dest = self.match_value("expected value alias")?; - ctx.function - .dfg - .make_value_alias_for_parser(dest, results[0]); - ctx.map.def_value(results[0], &self.loc)?; - ctx.aliases.push(results[0]); + // Allow duplicate definitions of aliases, as long as they are identical. + if ctx.map.contains_value(result) { + if let Some(old) = ctx.function.dfg.value_alias_dest_for_parser(result) { + if old != dest { + return err!( + self.loc, + "value {} is already defined as an alias with destination {}", + result, + old + ); + } + } else { + return err!(self.loc, "value {} is already defined"); + } + } else { + ctx.map.def_value(result, &self.loc)?; + } + + if !ctx.map.contains_value(dest) { + return err!(self.loc, "value {} is not yet defined", dest); + } + + ctx.function.dfg.make_value_alias_for_parser(dest, result); + + ctx.aliases.push(result); Ok(()) }