Move the ctrl_typevar function into dfg.

Soon, InstructionData won't have sufficient information to compute this.

Give TargetIsa::encode() an explicit ctrl_typevar argument. This
function does not require the instruction to be inserted in the DFG
tables.
This commit is contained in:
Jakob Stoklund Olesen
2017-04-12 13:14:03 -07:00
parent e653d44f39
commit 28ff7b7925
11 changed files with 69 additions and 53 deletions

View File

@@ -1,12 +1,13 @@
//! Data flow graph tracking Instructions, Values, and EBBs.
use ir::{Ebb, Inst, Value, Type, SigRef, Signature, FuncRef, ValueList, ValueListPool};
use ir::entities::ExpandedValue;
use ir::instructions::{Opcode, InstructionData, CallInfo};
use ir::extfunc::ExtFuncData;
use entity_map::{EntityMap, PrimaryEntityData};
use ir::builder::{InsertBuilder, ReplaceBuilder};
use ir::entities::ExpandedValue;
use ir::extfunc::ExtFuncData;
use ir::instructions::{Opcode, InstructionData, CallInfo};
use ir::layout::Cursor;
use ir::types;
use ir::{Ebb, Inst, Value, Type, SigRef, Signature, FuncRef, ValueList, ValueListPool};
use write::write_operands;
use std::fmt;
@@ -541,6 +542,22 @@ impl DataFlowGraph {
.map(|&arg| arg.value_type)
})
}
/// Get the controlling type variable, or `VOID` if `inst` isn't polymorphic.
pub fn ctrl_typevar(&self, inst: Inst) -> Type {
let constraints = self[inst].opcode().constraints();
if !constraints.is_polymorphic() {
types::VOID
} else if constraints.requires_typevar_operand() {
// Not all instruction formats have a designated operand, but in that case
// `requires_typevar_operand()` should never be true.
self.value_type(self[inst].typevar_operand(&self.value_lists)
.expect("Instruction format doesn't have a designated operand, bad opcode."))
} else {
self.value_type(self.first_result(inst))
}
}
}
/// Allow immutable access to instructions via indexing.
@@ -688,7 +705,7 @@ impl<'a> fmt::Display for DisplayInst<'a> {
}
let typevar = inst.ctrl_typevar(dfg);
let typevar = dfg.ctrl_typevar(self.1);
if typevar.is_void() {
write!(f, "{}", inst.opcode())?;
} else {

View File

@@ -14,7 +14,6 @@ use ir::{Value, Type, Ebb, JumpTable, SigRef, FuncRef, StackSlot, MemFlags};
use ir::immediates::{Imm64, Uimm8, Ieee32, Ieee64, Offset32, Uoffset32};
use ir::condcodes::*;
use ir::types;
use ir::DataFlowGraph;
use entity_list;
use ref_slice::{ref_slice, ref_slice_mut};
@@ -397,27 +396,6 @@ impl InstructionData {
_ => CallInfo::NotACall,
}
}
/// Get the controlling type variable, or `VOID` if this instruction isn't polymorphic.
///
/// In most cases, the controlling type variable is the same as the first result type, but some
/// opcodes require us to read the type of the designated type variable operand from `dfg`.
pub fn ctrl_typevar(&self, dfg: &DataFlowGraph) -> Type {
let constraints = self.opcode().constraints();
if !constraints.is_polymorphic() {
types::VOID
} else if constraints.requires_typevar_operand() {
// Not all instruction formats have a designated operand, but in that case
// `requires_typevar_operand()` should never be true.
dfg.value_type(self.typevar_operand(&dfg.value_lists)
.expect("Instruction format doesn't have a designated operand, bad opcode."))
} else {
// For locality of reference, we prefer to get the controlling type variable from
// `idata` itself, when possible.
self.first_type()
}
}
}
/// Information about branch and jump instructions.