Print a type suffix on some polymorphic instructions.

This commit is contained in:
Jakob Stoklund Olesen
2016-07-05 13:45:15 -07:00
parent 954fd015e0
commit a82554192a
3 changed files with 72 additions and 22 deletions

View File

@@ -7,6 +7,7 @@
use std::io::{self, Write}; use std::io::{self, Write};
use repr::Function; use repr::Function;
use entities::{Inst, Ebb, Value}; use entities::{Inst, Ebb, Value};
use types::Type;
pub type Result = io::Result<()>; pub type Result = io::Result<()>;
@@ -126,6 +127,35 @@ pub fn write_ebb(w: &mut Write, func: &Function, ebb: Ebb) -> Result {
// //
// ====--------------------------------------------------------------------------------------====// // ====--------------------------------------------------------------------------------------====//
// Should `inst` be printed with a type suffix?
//
// Polymorphic instructions may need a suffix indicating the value of the controlling type variable
// if it can't be trivially inferred.
//
fn type_suffix(func: &Function, inst: Inst) -> Option<Type> {
let constraints = func[inst].opcode().constraints();
if !constraints.is_polymorphic() {
return None;
}
// If the controlling type variable can be inferred from the type of the designated value input
// operand, we don't need the type suffix.
// TODO: Should we include the suffix when the input value is defined in another block? The
// parser needs to know the type of the value, so it must be defined in a block that lexically
// comes before this one.
if constraints.use_typevar_operand() {
return None;
}
// This polymorphic instruction doesn't support basic type inference.
// The controlling type variable is required to be the type of the first result.
let rtype = func.value_type(func.first_result(inst));
assert!(!rtype.is_void(),
"Polymorphic instruction must produce a result");
Some(rtype)
}
pub fn write_instruction(w: &mut Write, func: &Function, inst: Inst) -> Result { pub fn write_instruction(w: &mut Write, func: &Function, inst: Inst) -> Result {
try!(write!(w, " ")); try!(write!(w, " "));
@@ -143,30 +173,34 @@ pub fn write_instruction(w: &mut Write, func: &Function, inst: Inst) -> Result {
try!(write!(w, " = ")); try!(write!(w, " = "));
} }
// Then the opcode and operands, depending on format. // Then the opcode, possibly with a '.type' suffix.
let opcode = func[inst].opcode();
match type_suffix(func, inst) {
Some(suf) => try!(write!(w, "{}.{}", opcode, suf)),
None => try!(write!(w, "{}", opcode)),
}
// Then the operands, depending on format.
use instructions::InstructionData::*; use instructions::InstructionData::*;
match func[inst] { match func[inst] {
Nullary { opcode, .. } => writeln!(w, "{}", opcode), Nullary { .. } => writeln!(w, ""),
Unary { opcode, arg, .. } => writeln!(w, "{} {}", opcode, arg), Unary { arg, .. } => writeln!(w, " {}", arg),
UnaryImm { opcode, imm, .. } => writeln!(w, "{} {}", opcode, imm), UnaryImm { imm, .. } => writeln!(w, " {}", imm),
UnaryIeee32 { opcode, imm, .. } => writeln!(w, "{} {}", opcode, imm), UnaryIeee32 { imm, .. } => writeln!(w, " {}", imm),
UnaryIeee64 { opcode, imm, .. } => writeln!(w, "{} {}", opcode, imm), UnaryIeee64 { imm, .. } => writeln!(w, " {}", imm),
UnaryImmVector { opcode, .. } => writeln!(w, "{} [...]", opcode), UnaryImmVector { .. } => writeln!(w, " [...]"),
Binary { opcode, args, .. } => writeln!(w, "{} {}, {}", opcode, args[0], args[1]), Binary { args, .. } => writeln!(w, " {}, {}", args[0], args[1]),
BinaryImm { opcode, arg, imm, .. } => writeln!(w, "{} {}, {}", opcode, arg, imm), BinaryImm { arg, imm, .. } => writeln!(w, " {}, {}", arg, imm),
BinaryImmRev { opcode, imm, arg, .. } => writeln!(w, "{} {}, {}", opcode, imm, arg), BinaryImmRev { imm, arg, .. } => writeln!(w, " {}, {}", imm, arg),
BinaryOverflow { opcode, args, .. } => writeln!(w, "{} {}, {}", opcode, args[0], args[1]), BinaryOverflow { args, .. } => writeln!(w, " {}, {}", args[0], args[1]),
Select { opcode, args, .. } => { Select { args, .. } => writeln!(w, " {}, {}, {}", args[0], args[1], args[2]),
writeln!(w, "{} {}, {}, {}", opcode, args[0], args[1], args[2]) InsertLane { lane, args, .. } => writeln!(w, " {}, {}, {}", args[0], lane, args[1]),
} ExtractLane { lane, arg, .. } => writeln!(w, " {}, {}", arg, lane),
InsertLane { opcode, lane, args, .. } => { Jump { ref data, .. } => writeln!(w, " {}", data),
writeln!(w, "{} {}, {}, {}", opcode, args[0], lane, args[1]) Branch { ref data, .. } => writeln!(w, " {}", data),
} BranchTable { arg, table, .. } => writeln!(w, " {}, {}", arg, table),
ExtractLane { opcode, lane, arg, .. } => writeln!(w, "{} {}, {}", opcode, arg, lane), Call { ref data, .. } => writeln!(w, " {}", data),
Jump { opcode, ref data, .. } => writeln!(w, "{} {}", opcode, data),
Branch { opcode, ref data, .. } => writeln!(w, "{} {}", opcode, data),
BranchTable { opcode, arg, table, .. } => writeln!(w, "{} {}, {}", opcode, arg, table),
Call { opcode, ref data, .. } => writeln!(w, "{} {}", opcode, data),
} }
} }

View File

@@ -3,3 +3,12 @@ function minimal() {
ebb0: ebb0:
trap trap
} }
; Create and use values.
; Polymorphic instructions with type suffix.
function ivalues() {
ebb0:
v0 = iconst.i32 2
v1 = iconst.i8 6
v2 = ishl v0, v1
}

View File

@@ -2,3 +2,10 @@ function minimal() {
ebb0: ebb0:
trap trap
} }
function ivalues() {
ebb0:
v0 = iconst.i32 2
v1 = iconst.i8 6
v2 = ishl v0, v1
}