Browse Source

Print a type suffix on some polymorphic instructions.

pull/1019/head
Jakob Stoklund Olesen 8 years ago
parent
commit
cbf78c294b
  1. 78
      cranelift/src/libcretonne/write.rs
  2. 9
      cranelift/tests/parser/tiny.cton
  3. 7
      cranelift/tests/parser/tiny.cton.ref

78
cranelift/src/libcretonne/write.rs

@ -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),
}
}

9
cranelift/tests/parser/tiny.cton

@ -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
}

7
cranelift/tests/parser/tiny.cton.ref

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

Loading…
Cancel
Save