Write and parse value locations for EBB arguments
Fixes #56. We now have complete support for value location annotations in the textual IL format. Values defined by instructions as well as EBB arguments are covered.
This commit is contained in:
@@ -5,7 +5,7 @@ isa riscv
|
|||||||
; regex: WS=[ \t]*
|
; regex: WS=[ \t]*
|
||||||
|
|
||||||
function %foo(i32, i32) {
|
function %foo(i32, i32) {
|
||||||
ebb1(v0: i32, v1: i32):
|
ebb1(v0: i32 [%x8], v1: i32):
|
||||||
[-,-] v2 = iadd v0, v1
|
[-,-] v2 = iadd v0, v1
|
||||||
[-] trap
|
[-] trap
|
||||||
[R#1234, %x5, %x11] v6, v7 = iadd_cout v2, v0
|
[R#1234, %x5, %x11] v6, v7 = iadd_cout v2, v0
|
||||||
@@ -14,7 +14,7 @@ ebb1(v0: i32, v1: i32):
|
|||||||
[Iret#5] return v0, v8
|
[Iret#5] return v0, v8
|
||||||
}
|
}
|
||||||
; sameln: function %foo(i32, i32) native {
|
; sameln: function %foo(i32, i32) native {
|
||||||
; nextln: $ebb1($v0: i32, $v1: i32):
|
; nextln: $ebb1($v0: i32 [%x8], $v1: i32):
|
||||||
; nextln: [-,-]$WS $v2 = iadd $v0, $v1
|
; nextln: [-,-]$WS $v2 = iadd $v0, $v1
|
||||||
; nextln: [-]$WS trap
|
; nextln: [-]$WS trap
|
||||||
; nextln: [R#1234,%x5,%x11]$WS $v6, $v7 = iadd_cout $v2, $v0
|
; nextln: [R#1234,%x5,%x11]$WS $v6, $v7 = iadd_cout $v2, $v0
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ isa riscv
|
|||||||
; Test the coalescer.
|
; Test the coalescer.
|
||||||
; regex: V=v\d+
|
; regex: V=v\d+
|
||||||
; regex: WS=\s+
|
; regex: WS=\s+
|
||||||
|
; regex: LOC=%\w+
|
||||||
|
|
||||||
; This function is already CSSA, so no copies should be inserted.
|
; This function is already CSSA, so no copies should be inserted.
|
||||||
function %cssa(i32) -> i32 {
|
function %cssa(i32) -> i32 {
|
||||||
@@ -81,7 +82,7 @@ ebb0(v0: i32):
|
|||||||
|
|
||||||
ebb1(v10: i32, v11: i32):
|
ebb1(v10: i32, v11: i32):
|
||||||
; v11 needs to be isolated because it interferes with v10.
|
; v11 needs to be isolated because it interferes with v10.
|
||||||
; check: $ebb1($v10: i32, $(nv11a=$V): i32)
|
; check: $ebb1($v10: i32 [$LOC], $(nv11a=$V): i32 [$LOC])
|
||||||
; check: $v11 = copy $nv11a
|
; check: $v11 = copy $nv11a
|
||||||
v12 = iadd v10, v11
|
v12 = iadd v10, v11
|
||||||
v13 = icmp ult v12, v0
|
v13 = icmp ult v12, v0
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function %pyramid(i32) -> i32 {
|
|||||||
; check: ss2 = spill_slot 4
|
; check: ss2 = spill_slot 4
|
||||||
; not: spill_slot
|
; not: spill_slot
|
||||||
ebb0(v1: i32):
|
ebb0(v1: i32):
|
||||||
; check: $ebb0($(rv1=$V): i32, $(rlink=$V): i32)
|
; check: $ebb0($(rv1=$V): i32 [%x10], $(rlink=$V): i32 [%x1])
|
||||||
; check: ,ss0]$WS $v1 = spill $rv1
|
; check: ,ss0]$WS $v1 = spill $rv1
|
||||||
; nextln: ,ss1]$WS $(link=$V) = spill $rlink
|
; nextln: ,ss1]$WS $(link=$V) = spill $rlink
|
||||||
; not: spill
|
; not: spill
|
||||||
@@ -155,7 +155,7 @@ function %use_spilled_value(i32) -> i32 {
|
|||||||
; check: ss1 = spill_slot 4
|
; check: ss1 = spill_slot 4
|
||||||
; check: ss2 = spill_slot 4
|
; check: ss2 = spill_slot 4
|
||||||
ebb0(v1: i32):
|
ebb0(v1: i32):
|
||||||
; check: $ebb0($(rv1=$V): i32, $(rlink=$V): i32)
|
; check: $ebb0($(rv1=$V): i32 [%x10], $(rlink=$V): i32 [%x1])
|
||||||
; check: ,ss0]$WS $v1 = spill $rv1
|
; check: ,ss0]$WS $v1 = spill $rv1
|
||||||
; nextln: ,ss1]$WS $(link=$V) = spill $rlink
|
; nextln: ,ss1]$WS $(link=$V) = spill $rlink
|
||||||
; not: spill
|
; not: spill
|
||||||
|
|||||||
@@ -25,6 +25,14 @@ impl Default for ValueLoc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ValueLoc {
|
impl ValueLoc {
|
||||||
|
/// Is this an assigned location? (That is, not `Unassigned`).
|
||||||
|
pub fn is_assigned(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
ValueLoc::Unassigned => false,
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the register unit of this location, or panic.
|
/// Get the register unit of this location, or panic.
|
||||||
pub fn unwrap_reg(self) -> RegUnit {
|
pub fn unwrap_reg(self) -> RegUnit {
|
||||||
match self {
|
match self {
|
||||||
|
|||||||
@@ -91,11 +91,22 @@ fn write_preamble(
|
|||||||
//
|
//
|
||||||
// ====--------------------------------------------------------------------------------------====//
|
// ====--------------------------------------------------------------------------------------====//
|
||||||
|
|
||||||
pub fn write_arg(w: &mut Write, func: &Function, arg: Value) -> Result {
|
pub fn write_arg(w: &mut Write, func: &Function, regs: Option<&RegInfo>, arg: Value) -> Result {
|
||||||
write!(w, "{}: {}", arg, func.dfg.value_type(arg))
|
write!(w, "{}: {}", arg, func.dfg.value_type(arg))?;
|
||||||
|
let loc = func.locations[arg];
|
||||||
|
if loc.is_assigned() {
|
||||||
|
write!(w, " [{}]", loc.display(regs))?
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_ebb_header(w: &mut Write, func: &Function, ebb: Ebb) -> Result {
|
pub fn write_ebb_header(
|
||||||
|
w: &mut Write,
|
||||||
|
func: &Function,
|
||||||
|
isa: Option<&TargetIsa>,
|
||||||
|
ebb: Ebb,
|
||||||
|
) -> Result {
|
||||||
// Write out the basic block header, outdented:
|
// Write out the basic block header, outdented:
|
||||||
//
|
//
|
||||||
// ebb1:
|
// ebb1:
|
||||||
@@ -108,24 +119,27 @@ pub fn write_ebb_header(w: &mut Write, func: &Function, ebb: Ebb) -> Result {
|
|||||||
write!(w, " ")?;
|
write!(w, " ")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let regs = isa.map(TargetIsa::register_info);
|
||||||
|
let regs = regs.as_ref();
|
||||||
|
|
||||||
let mut args = func.dfg.ebb_args(ebb).iter().cloned();
|
let mut args = func.dfg.ebb_args(ebb).iter().cloned();
|
||||||
match args.next() {
|
match args.next() {
|
||||||
None => return writeln!(w, "{}:", ebb),
|
None => return writeln!(w, "{}:", ebb),
|
||||||
Some(arg) => {
|
Some(arg) => {
|
||||||
write!(w, "{}(", ebb)?;
|
write!(w, "{}(", ebb)?;
|
||||||
write_arg(w, func, arg)?;
|
write_arg(w, func, regs, arg)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remaining arguments.
|
// Remaining arguments.
|
||||||
for arg in args {
|
for arg in args {
|
||||||
write!(w, ", ")?;
|
write!(w, ", ")?;
|
||||||
write_arg(w, func, arg)?;
|
write_arg(w, func, regs, arg)?;
|
||||||
}
|
}
|
||||||
writeln!(w, "):")
|
writeln!(w, "):")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_ebb(w: &mut Write, func: &Function, isa: Option<&TargetIsa>, ebb: Ebb) -> Result {
|
pub fn write_ebb(w: &mut Write, func: &Function, isa: Option<&TargetIsa>, ebb: Ebb) -> Result {
|
||||||
write_ebb_header(w, func, ebb)?;
|
write_ebb_header(w, func, isa, ebb)?;
|
||||||
for inst in func.layout.ebb_insts(ebb) {
|
for inst in func.layout.ebb_insts(ebb) {
|
||||||
write_instruction(w, func, isa, inst)?;
|
write_instruction(w, func, isa, inst)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1449,22 +1449,35 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
// Parse a single EBB argument declaration, and append it to `ebb`.
|
// Parse a single EBB argument declaration, and append it to `ebb`.
|
||||||
//
|
//
|
||||||
// ebb-arg ::= * Value(v) ":" Type(t)
|
// ebb-arg ::= * Value(v) ":" Type(t) arg-loc?
|
||||||
|
// arg-loc ::= "[" value-location "]"
|
||||||
//
|
//
|
||||||
fn parse_ebb_arg(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> {
|
fn parse_ebb_arg(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> {
|
||||||
// ebb-arg ::= * Value(v) ":" Type(t)
|
// ebb-arg ::= * Value(v) ":" Type(t) arg-loc?
|
||||||
let v = self.match_value("EBB argument must be a value")?;
|
let v = self.match_value("EBB argument must be a value")?;
|
||||||
let v_location = self.loc;
|
let v_location = self.loc;
|
||||||
// ebb-arg ::= Value(v) * ":" Type(t)
|
// ebb-arg ::= Value(v) * ":" Type(t) arg-loc?
|
||||||
self.match_token(
|
self.match_token(
|
||||||
Token::Colon,
|
Token::Colon,
|
||||||
"expected ':' after EBB argument",
|
"expected ':' after EBB argument",
|
||||||
)?;
|
)?;
|
||||||
// ebb-arg ::= Value(v) ":" * Type(t)
|
// ebb-arg ::= Value(v) ":" * Type(t) arg-loc?
|
||||||
let t = self.match_type("expected EBB argument type")?;
|
let t = self.match_type("expected EBB argument type")?;
|
||||||
// Allocate the EBB argument and add the mapping.
|
// Allocate the EBB argument and add the mapping.
|
||||||
let value = ctx.function.dfg.append_ebb_arg(ebb, t);
|
let value = ctx.function.dfg.append_ebb_arg(ebb, t);
|
||||||
ctx.map.def_value(v, value, &v_location)
|
ctx.map.def_value(v, value, &v_location)?;
|
||||||
|
|
||||||
|
// ebb-arg ::= Value(v) ":" Type(t) * arg-loc?
|
||||||
|
if self.optional(Token::LBracket) {
|
||||||
|
let loc = self.parse_value_location(ctx)?;
|
||||||
|
ctx.function.locations[value] = loc;
|
||||||
|
self.match_token(
|
||||||
|
Token::RBracket,
|
||||||
|
"expected ']' after value location",
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_value_location(&mut self, ctx: &Context) -> Result<ValueLoc> {
|
fn parse_value_location(&mut self, ctx: &Context) -> Result<ValueLoc> {
|
||||||
|
|||||||
Reference in New Issue
Block a user