Print a type suffix on some polymorphic instructions.
This commit is contained in:
@@ -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),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user