Print a type suffix on some polymorphic instructions.
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
use std::io::{self, Write};
|
||||
use repr::Function;
|
||||
use entities::{Inst, Ebb, Value};
|
||||
use types::Type;
|
||||
|
||||
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 {
|
||||
try!(write!(w, " "));
|
||||
|
||||
@@ -143,30 +173,34 @@ pub fn write_instruction(w: &mut Write, func: &Function, inst: Inst) -> Result {
|
||||
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::*;
|
||||
match func[inst] {
|
||||
Nullary { opcode, .. } => writeln!(w, "{}", opcode),
|
||||
Unary { opcode, arg, .. } => writeln!(w, "{} {}", opcode, arg),
|
||||
UnaryImm { opcode, imm, .. } => writeln!(w, "{} {}", opcode, imm),
|
||||
UnaryIeee32 { opcode, imm, .. } => writeln!(w, "{} {}", opcode, imm),
|
||||
UnaryIeee64 { opcode, imm, .. } => writeln!(w, "{} {}", opcode, imm),
|
||||
UnaryImmVector { opcode, .. } => writeln!(w, "{} [...]", opcode),
|
||||
Binary { opcode, args, .. } => writeln!(w, "{} {}, {}", opcode, args[0], args[1]),
|
||||
BinaryImm { opcode, arg, imm, .. } => writeln!(w, "{} {}, {}", opcode, arg, imm),
|
||||
BinaryImmRev { opcode, imm, arg, .. } => writeln!(w, "{} {}, {}", opcode, imm, arg),
|
||||
BinaryOverflow { opcode, args, .. } => writeln!(w, "{} {}, {}", opcode, args[0], args[1]),
|
||||
Select { opcode, args, .. } => {
|
||||
writeln!(w, "{} {}, {}, {}", opcode, args[0], args[1], args[2])
|
||||
}
|
||||
InsertLane { opcode, lane, args, .. } => {
|
||||
writeln!(w, "{} {}, {}, {}", opcode, args[0], lane, args[1])
|
||||
}
|
||||
ExtractLane { opcode, lane, arg, .. } => writeln!(w, "{} {}, {}", opcode, arg, lane),
|
||||
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),
|
||||
Nullary { .. } => writeln!(w, ""),
|
||||
Unary { arg, .. } => writeln!(w, " {}", arg),
|
||||
UnaryImm { imm, .. } => writeln!(w, " {}", imm),
|
||||
UnaryIeee32 { imm, .. } => writeln!(w, " {}", imm),
|
||||
UnaryIeee64 { imm, .. } => writeln!(w, " {}", imm),
|
||||
UnaryImmVector { .. } => writeln!(w, " [...]"),
|
||||
Binary { args, .. } => writeln!(w, " {}, {}", args[0], args[1]),
|
||||
BinaryImm { arg, imm, .. } => writeln!(w, " {}, {}", arg, imm),
|
||||
BinaryImmRev { imm, arg, .. } => writeln!(w, " {}, {}", imm, arg),
|
||||
BinaryOverflow { args, .. } => writeln!(w, " {}, {}", args[0], args[1]),
|
||||
Select { args, .. } => writeln!(w, " {}, {}, {}", args[0], args[1], args[2]),
|
||||
InsertLane { lane, args, .. } => writeln!(w, " {}, {}, {}", args[0], lane, args[1]),
|
||||
ExtractLane { lane, arg, .. } => writeln!(w, " {}, {}", arg, lane),
|
||||
Jump { ref data, .. } => writeln!(w, " {}", data),
|
||||
Branch { ref data, .. } => writeln!(w, " {}", data),
|
||||
BranchTable { arg, table, .. } => writeln!(w, " {}, {}", arg, table),
|
||||
Call { ref data, .. } => writeln!(w, " {}", data),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,3 +3,12 @@ function minimal() {
|
||||
ebb0:
|
||||
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
|
||||
}
|
||||
|
||||
@@ -2,3 +2,10 @@ function minimal() {
|
||||
ebb0:
|
||||
trap
|
||||
}
|
||||
|
||||
function ivalues() {
|
||||
ebb0:
|
||||
v0 = iconst.i32 2
|
||||
v1 = iconst.i8 6
|
||||
v2 = ishl v0, v1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user