Implement jump tables (#453)
* Add 'jump_table_entry' and 'indirect_jump' instructions. * Update CodeSink to keep track of code size. Pretty up clif-util's disassembly output. * Only disassemble the machine portion of output. Pretty print the read-only data after it. * Update switch frontend code to use new br_table instruction w/ default.
This commit is contained in:
committed by
Dan Gohman
parent
de1d82b4ba
commit
79cea5e18b
@@ -11,7 +11,8 @@ use ir::{
|
||||
Ebb, ExtFuncData, FuncRef, GlobalValue, GlobalValueData, Heap, HeapData, JumpTable,
|
||||
JumpTableData, SigRef, StackSlot, StackSlotData, Table, TableData,
|
||||
};
|
||||
use ir::{EbbOffsets, InstEncodings, JumpTables, SourceLocs, StackSlots, ValueLocations};
|
||||
use ir::{EbbOffsets, InstEncodings, SourceLocs, StackSlots, ValueLocations};
|
||||
use ir::{JumpTableOffsets, JumpTables};
|
||||
use isa::{EncInfo, Encoding, Legalize, TargetIsa};
|
||||
use settings::CallConv;
|
||||
use std::fmt;
|
||||
@@ -64,6 +65,9 @@ pub struct Function {
|
||||
/// in the textual IR format.
|
||||
pub offsets: EbbOffsets,
|
||||
|
||||
/// Code offsets of Jump Table headers.
|
||||
pub jt_offsets: JumpTableOffsets,
|
||||
|
||||
/// Source locations.
|
||||
///
|
||||
/// Track the original source location for each instruction. The source locations are not
|
||||
@@ -87,6 +91,7 @@ impl Function {
|
||||
encodings: SecondaryMap::new(),
|
||||
locations: SecondaryMap::new(),
|
||||
offsets: SecondaryMap::new(),
|
||||
jt_offsets: SecondaryMap::new(),
|
||||
srclocs: SecondaryMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +194,10 @@ impl InstructionData {
|
||||
ref args,
|
||||
..
|
||||
} => BranchInfo::SingleDest(destination, &args.as_slice(pool)[2..]),
|
||||
InstructionData::BranchTable { table, .. } => BranchInfo::Table(table),
|
||||
InstructionData::BranchTable {
|
||||
table, destination, ..
|
||||
} => BranchInfo::Table(table, Some(destination)),
|
||||
InstructionData::IndirectJump { table, .. } => BranchInfo::Table(table, None),
|
||||
_ => {
|
||||
debug_assert!(!self.opcode().is_branch());
|
||||
BranchInfo::NotABranch
|
||||
@@ -213,7 +216,7 @@ impl InstructionData {
|
||||
| InstructionData::BranchInt { destination, .. }
|
||||
| InstructionData::BranchFloat { destination, .. }
|
||||
| InstructionData::BranchIcmp { destination, .. } => Some(destination),
|
||||
InstructionData::BranchTable { .. } => None,
|
||||
InstructionData::BranchTable { .. } | InstructionData::IndirectJump { .. } => None,
|
||||
_ => {
|
||||
debug_assert!(!self.opcode().is_branch());
|
||||
None
|
||||
@@ -284,8 +287,8 @@ pub enum BranchInfo<'a> {
|
||||
/// This is a branch or jump to a single destination EBB, possibly taking value arguments.
|
||||
SingleDest(Ebb, &'a [Value]),
|
||||
|
||||
/// This is a jump table branch which can have many destination EBBs.
|
||||
Table(JumpTable),
|
||||
/// This is a jump table branch which can have many destination EBBs and maybe one default EBB.
|
||||
Table(JumpTable, Option<Ebb>),
|
||||
}
|
||||
|
||||
/// Information about call instructions.
|
||||
|
||||
@@ -45,6 +45,11 @@ impl JumpTableData {
|
||||
self.table.len()
|
||||
}
|
||||
|
||||
/// Boolean that is false if the table has missing entries.
|
||||
pub fn fully_dense(&self) -> bool {
|
||||
self.holes == 0
|
||||
}
|
||||
|
||||
/// Set a table entry.
|
||||
///
|
||||
/// The table will grow as needed to fit `idx`.
|
||||
|
||||
@@ -62,5 +62,8 @@ pub type InstEncodings = SecondaryMap<Inst, isa::Encoding>;
|
||||
/// Code offsets for EBBs.
|
||||
pub type EbbOffsets = SecondaryMap<Ebb, binemit::CodeOffset>;
|
||||
|
||||
/// Code offsets for Jump Tables.
|
||||
pub type JumpTableOffsets = SecondaryMap<JumpTable, binemit::CodeOffset>;
|
||||
|
||||
/// Source locations for instructions.
|
||||
pub type SourceLocs = SecondaryMap<Inst, SourceLoc>;
|
||||
|
||||
Reference in New Issue
Block a user