Mass rename Ebb and relatives to Block (#1365)

* Manually rename BasicBlock to BlockPredecessor

BasicBlock is a pair of (Ebb, Inst) that is used to represent the
basic block subcomponent of an Ebb that is a predecessor to an Ebb.

Eventually we will be able to remove this struct, but for now it
makes sense to give it a non-conflicting name so that we can start
to transition Ebb to represent a basic block.

I have not updated any comments that refer to BasicBlock, as
eventually we will remove BlockPredecessor and replace with Block,
which is a basic block, so the comments will become correct.

* Manually rename SSABuilder block types to avoid conflict

SSABuilder has its own Block and BlockData types. These along with
associated identifier will cause conflicts in a later commit, so
they are renamed to be more verbose here.

* Automatically rename 'Ebb' to 'Block' in *.rs

* Automatically rename 'EBB' to 'block' in *.rs

* Automatically rename 'ebb' to 'block' in *.rs

* Automatically rename 'extended basic block' to 'basic block' in *.rs

* Automatically rename 'an basic block' to 'a basic block' in *.rs

* Manually update comment for `Block`

`Block`'s wikipedia article required an update.

* Automatically rename 'an `Block`' to 'a `Block`' in *.rs

* Automatically rename 'extended_basic_block' to 'basic_block' in *.rs

* Automatically rename 'ebb' to 'block' in *.clif

* Manually rename clif constant that contains 'ebb' as substring to avoid conflict

* Automatically rename filecheck uses of 'EBB' to 'BB'

'regex: EBB' -> 'regex: BB'
'$EBB' -> '$BB'

* Automatically rename 'EBB' 'Ebb' to 'block' in *.clif

* Automatically rename 'an block' to 'a block' in *.clif

* Fix broken testcase when function name length increases

Test function names are limited to 16 characters. This causes
the new longer name to be truncated and fail a filecheck test. An
outdated comment was also fixed.
This commit is contained in:
Ryan Hunt
2020-02-07 10:46:47 -06:00
committed by GitHub
parent a136d1cb00
commit 832666c45e
370 changed files with 8090 additions and 7988 deletions

View File

@@ -223,10 +223,10 @@ mod tests {
#[test]
fn types() {
let mut func = Function::new();
let ebb0 = func.dfg.make_ebb();
let arg0 = func.dfg.append_ebb_param(ebb0, I32);
let block0 = func.dfg.make_block();
let arg0 = func.dfg.append_block_param(block0, I32);
let mut pos = FuncCursor::new(&mut func);
pos.insert_ebb(ebb0);
pos.insert_block(block0);
// Explicit types.
let v0 = pos.ins().iconst(I32, 3);
@@ -244,10 +244,10 @@ mod tests {
#[test]
fn reuse_results() {
let mut func = Function::new();
let ebb0 = func.dfg.make_ebb();
let arg0 = func.dfg.append_ebb_param(ebb0, I32);
let block0 = func.dfg.make_block();
let arg0 = func.dfg.append_block_param(block0, I32);
let mut pos = FuncCursor::new(&mut func);
pos.insert_ebb(ebb0);
pos.insert_block(block0);
let v0 = pos.ins().iadd_imm(arg0, 17);
assert_eq!(pos.func.dfg.value_type(v0), I32);

View File

@@ -1,4 +1,4 @@
//! Data flow graph tracking Instructions, Values, and EBBs.
//! Data flow graph tracking Instructions, Values, and blocks.
use crate::entity::{self, PrimaryMap, SecondaryMap};
use crate::ir;
@@ -7,7 +7,7 @@ use crate::ir::extfunc::ExtFuncData;
use crate::ir::instructions::{BranchInfo, CallInfo, InstructionData};
use crate::ir::{types, ConstantData, ConstantPool, Immediate};
use crate::ir::{
Ebb, FuncRef, Inst, SigRef, Signature, Type, Value, ValueLabelAssignments, ValueList,
Block, FuncRef, Inst, SigRef, Signature, Type, Value, ValueLabelAssignments, ValueList,
ValueListPool,
};
use crate::isa::TargetIsa;
@@ -21,18 +21,18 @@ use core::mem;
use core::ops::{Index, IndexMut};
use core::u16;
/// A data flow graph defines all instructions and extended basic blocks in a function as well as
/// A data flow graph defines all instructions and basic blocks in a function as well as
/// the data flow dependencies between them. The DFG also tracks values which can be either
/// instruction results or EBB parameters.
/// instruction results or block parameters.
///
/// The layout of EBBs in the function and of instructions in each EBB is recorded by the
/// The layout of blocks in the function and of instructions in each block is recorded by the
/// `Layout` data structure which forms the other half of the function representation.
///
#[derive(Clone)]
pub struct DataFlowGraph {
/// Data about all of the instructions in the function, including opcodes and operands.
/// The instructions in this map are not in program order. That is tracked by `Layout`, along
/// with the EBB containing each instruction.
/// with the block containing each instruction.
insts: PrimaryMap<Inst, InstructionData>,
/// List of result values for each instruction.
@@ -41,11 +41,11 @@ pub struct DataFlowGraph {
/// primary `insts` map.
results: SecondaryMap<Inst, ValueList>,
/// Extended basic blocks in the function and their parameters.
/// basic blocks in the function and their parameters.
///
/// This map is not in program order. That is handled by `Layout`, and so is the sequence of
/// instructions contained in each EBB.
ebbs: PrimaryMap<Ebb, EbbData>,
/// instructions contained in each block.
blocks: PrimaryMap<Block, BlockData>,
/// Memory pool of value lists.
///
@@ -53,7 +53,7 @@ pub struct DataFlowGraph {
///
/// - Instructions in `insts` that don't have room for their entire argument list inline.
/// - Instruction result values in `results`.
/// - EBB parameters in `ebbs`.
/// - block parameters in `blocks`.
pub value_lists: ValueListPool,
/// Primary value table with entries for all values.
@@ -85,7 +85,7 @@ impl DataFlowGraph {
Self {
insts: PrimaryMap::new(),
results: SecondaryMap::new(),
ebbs: PrimaryMap::new(),
blocks: PrimaryMap::new(),
value_lists: ValueListPool::new(),
values: PrimaryMap::new(),
signatures: PrimaryMap::new(),
@@ -101,7 +101,7 @@ impl DataFlowGraph {
pub fn clear(&mut self) {
self.insts.clear();
self.results.clear();
self.ebbs.clear();
self.blocks.clear();
self.value_lists.clear();
self.values.clear();
self.signatures.clear();
@@ -125,17 +125,17 @@ impl DataFlowGraph {
self.insts.is_valid(inst)
}
/// Get the total number of extended basic blocks created in this function, whether they are
/// Get the total number of basic blocks created in this function, whether they are
/// currently inserted in the layout or not.
///
/// This is intended for use with `SecondaryMap::with_capacity`.
pub fn num_ebbs(&self) -> usize {
self.ebbs.len()
pub fn num_blocks(&self) -> usize {
self.blocks.len()
}
/// Returns `true` if the given ebb reference is valid.
pub fn ebb_is_valid(&self, ebb: Ebb) -> bool {
self.ebbs.is_valid(ebb)
/// Returns `true` if the given block reference is valid.
pub fn block_is_valid(&self, block: Block) -> bool {
self.blocks.is_valid(block)
}
/// Get the total number of values.
@@ -213,7 +213,7 @@ impl<'a> Iterator for Values<'a> {
/// Handling values.
///
/// Values are either EBB parameters or instruction results.
/// Values are either block parameters or instruction results.
impl DataFlowGraph {
/// Allocate an extended value entry.
fn make_value(&mut self, data: ValueData) -> Value {
@@ -243,12 +243,12 @@ impl DataFlowGraph {
/// Get the definition of a value.
///
/// This is either the instruction that defined it or the Ebb that has the value as an
/// This is either the instruction that defined it or the Block that has the value as an
/// parameter.
pub fn value_def(&self, v: Value) -> ValueDef {
match self.values[v] {
ValueData::Inst { inst, num, .. } => ValueDef::Result(inst, num as usize),
ValueData::Param { ebb, num, .. } => ValueDef::Param(ebb, num as usize),
ValueData::Param { block, num, .. } => ValueDef::Param(block, num as usize),
ValueData::Alias { original, .. } => {
// Make sure we only recurse one level. `resolve_aliases` has safeguards to
// detect alias loops without overrunning the stack.
@@ -257,7 +257,7 @@ impl DataFlowGraph {
}
}
/// Determine if `v` is an attached instruction result / EBB parameter.
/// Determine if `v` is an attached instruction result / block parameter.
///
/// An attached value can't be attached to something else without first being detached.
///
@@ -267,7 +267,7 @@ impl DataFlowGraph {
use self::ValueData::*;
match self.values[v] {
Inst { inst, num, .. } => Some(&v) == self.inst_results(inst).get(num as usize),
Param { ebb, num, .. } => Some(&v) == self.ebb_params(ebb).get(num as usize),
Param { block, num, .. } => Some(&v) == self.block_params(block).get(num as usize),
Alias { .. } => false,
}
}
@@ -297,7 +297,7 @@ impl DataFlowGraph {
/// Change the `dest` value to behave as an alias of `src`. This means that all uses of `dest`
/// will behave as if they used that value `src`.
///
/// The `dest` value can't be attached to an instruction or EBB.
/// The `dest` value can't be attached to an instruction or block.
pub fn change_to_alias(&mut self, dest: Value, src: Value) {
debug_assert!(!self.value_is_attached(dest));
// Try to create short alias chains by finding the original source value.
@@ -376,8 +376,8 @@ impl DataFlowGraph {
pub enum ValueDef {
/// Value is the n'th result of an instruction.
Result(Inst, usize),
/// Value is the n'th parameter to an EBB.
Param(Ebb, usize),
/// Value is the n'th parameter to an block.
Param(Block, usize),
}
impl ValueDef {
@@ -389,11 +389,11 @@ impl ValueDef {
}
}
/// Unwrap the EBB there the parameter is defined, or panic.
pub fn unwrap_ebb(&self) -> Ebb {
/// Unwrap the block there the parameter is defined, or panic.
pub fn unwrap_block(&self) -> Block {
match *self {
Self::Param(ebb, _) => ebb,
_ => panic!("Value is not an EBB parameter"),
Self::Param(block, _) => block,
_ => panic!("Value is not an block parameter"),
}
}
@@ -419,12 +419,12 @@ enum ValueData {
/// Value is defined by an instruction.
Inst { ty: Type, num: u16, inst: Inst },
/// Value is an EBB parameter.
Param { ty: Type, num: u16, ebb: Ebb },
/// Value is an block parameter.
Param { ty: Type, num: u16, block: Block },
/// Value is an alias of another value.
/// An alias value can't be linked as an instruction result or EBB parameter. It is used as a
/// placeholder when the original instruction or EBB has been rewritten or modified.
/// An alias value can't be linked as an instruction result or block parameter. It is used as a
/// placeholder when the original instruction or block has been rewritten or modified.
Alias { ty: Type, original: Value },
}
@@ -760,61 +760,64 @@ impl IndexMut<Inst> for DataFlowGraph {
}
}
/// Extended basic blocks.
/// basic blocks.
impl DataFlowGraph {
/// Create a new basic block.
pub fn make_ebb(&mut self) -> Ebb {
self.ebbs.push(EbbData::new())
pub fn make_block(&mut self) -> Block {
self.blocks.push(BlockData::new())
}
/// Get the number of parameters on `ebb`.
pub fn num_ebb_params(&self, ebb: Ebb) -> usize {
self.ebbs[ebb].params.len(&self.value_lists)
/// Get the number of parameters on `block`.
pub fn num_block_params(&self, block: Block) -> usize {
self.blocks[block].params.len(&self.value_lists)
}
/// Get the parameters on `ebb`.
pub fn ebb_params(&self, ebb: Ebb) -> &[Value] {
self.ebbs[ebb].params.as_slice(&self.value_lists)
/// Get the parameters on `block`.
pub fn block_params(&self, block: Block) -> &[Value] {
self.blocks[block].params.as_slice(&self.value_lists)
}
/// Get the types of the parameters on `ebb`.
pub fn ebb_param_types(&self, ebb: Ebb) -> Vec<Type> {
self.ebb_params(ebb)
/// Get the types of the parameters on `block`.
pub fn block_param_types(&self, block: Block) -> Vec<Type> {
self.block_params(block)
.iter()
.map(|&v| self.value_type(v))
.collect()
}
/// Append a parameter with type `ty` to `ebb`.
pub fn append_ebb_param(&mut self, ebb: Ebb, ty: Type) -> Value {
/// Append a parameter with type `ty` to `block`.
pub fn append_block_param(&mut self, block: Block, ty: Type) -> Value {
let param = self.values.next_key();
let num = self.ebbs[ebb].params.push(param, &mut self.value_lists);
debug_assert!(num <= u16::MAX as usize, "Too many parameters on EBB");
let num = self.blocks[block].params.push(param, &mut self.value_lists);
debug_assert!(num <= u16::MAX as usize, "Too many parameters on block");
self.make_value(ValueData::Param {
ty,
num: num as u16,
ebb,
block,
})
}
/// Removes `val` from `ebb`'s parameters by swapping it with the last parameter on `ebb`.
/// Removes `val` from `block`'s parameters by swapping it with the last parameter on `block`.
/// Returns the position of `val` before removal.
///
/// *Important*: to ensure O(1) deletion, this method swaps the removed parameter with the
/// last `ebb` parameter. This can disrupt all the branch instructions jumping to this
/// `ebb` for which you have to change the branch argument order if necessary.
/// last `block` parameter. This can disrupt all the branch instructions jumping to this
/// `block` for which you have to change the branch argument order if necessary.
///
/// Panics if `val` is not an EBB parameter.
pub fn swap_remove_ebb_param(&mut self, val: Value) -> usize {
let (ebb, num) = if let ValueData::Param { num, ebb, .. } = self.values[val] {
(ebb, num)
/// Panics if `val` is not an block parameter.
pub fn swap_remove_block_param(&mut self, val: Value) -> usize {
let (block, num) = if let ValueData::Param { num, block, .. } = self.values[val] {
(block, num)
} else {
panic!("{} must be an EBB parameter", val);
panic!("{} must be an block parameter", val);
};
self.ebbs[ebb]
self.blocks[block]
.params
.swap_remove(num as usize, &mut self.value_lists);
if let Some(last_arg_val) = self.ebbs[ebb].params.get(num as usize, &self.value_lists) {
if let Some(last_arg_val) = self.blocks[block]
.params
.get(num as usize, &self.value_lists)
{
// We update the position of the old last arg.
if let ValueData::Param {
num: ref mut old_num,
@@ -823,25 +826,25 @@ impl DataFlowGraph {
{
*old_num = num;
} else {
panic!("{} should be an Ebb parameter", last_arg_val);
panic!("{} should be an Block parameter", last_arg_val);
}
}
num as usize
}
/// Removes `val` from `ebb`'s parameters by a standard linear time list removal which
/// Removes `val` from `block`'s parameters by a standard linear time list removal which
/// preserves ordering. Also updates the values' data.
pub fn remove_ebb_param(&mut self, val: Value) {
let (ebb, num) = if let ValueData::Param { num, ebb, .. } = self.values[val] {
(ebb, num)
pub fn remove_block_param(&mut self, val: Value) {
let (block, num) = if let ValueData::Param { num, block, .. } = self.values[val] {
(block, num)
} else {
panic!("{} must be an EBB parameter", val);
panic!("{} must be an block parameter", val);
};
self.ebbs[ebb]
self.blocks[block]
.params
.remove(num as usize, &mut self.value_lists);
for index in num..(self.num_ebb_params(ebb) as u16) {
match self.values[self.ebbs[ebb]
for index in num..(self.num_block_params(block) as u16) {
match self.values[self.blocks[block]
.params
.get(index as usize, &self.value_lists)
.unwrap()]
@@ -850,8 +853,8 @@ impl DataFlowGraph {
*num -= 1;
}
_ => panic!(
"{} must be an EBB parameter",
self.ebbs[ebb]
"{} must be an block parameter",
self.blocks[block]
.params
.get(index as usize, &self.value_lists)
.unwrap()
@@ -860,71 +863,73 @@ impl DataFlowGraph {
}
}
/// Append an existing value to `ebb`'s parameters.
/// Append an existing value to `block`'s parameters.
///
/// The appended value can't already be attached to something else.
///
/// In almost all cases, you should be using `append_ebb_param()` instead of this method.
pub fn attach_ebb_param(&mut self, ebb: Ebb, param: Value) {
/// In almost all cases, you should be using `append_block_param()` instead of this method.
pub fn attach_block_param(&mut self, block: Block, param: Value) {
debug_assert!(!self.value_is_attached(param));
let num = self.ebbs[ebb].params.push(param, &mut self.value_lists);
debug_assert!(num <= u16::MAX as usize, "Too many parameters on EBB");
let num = self.blocks[block].params.push(param, &mut self.value_lists);
debug_assert!(num <= u16::MAX as usize, "Too many parameters on block");
let ty = self.value_type(param);
self.values[param] = ValueData::Param {
ty,
num: num as u16,
ebb,
block,
};
}
/// Replace an EBB parameter with a new value of type `ty`.
/// Replace an block parameter with a new value of type `ty`.
///
/// The `old_value` must be an attached EBB parameter. It is removed from its place in the list
/// The `old_value` must be an attached block parameter. It is removed from its place in the list
/// of parameters and replaced by a new value of type `new_type`. The new value gets the same
/// position in the list, and other parameters are not disturbed.
///
/// The old value is left detached, so it should probably be changed into something else.
///
/// Returns the new value.
pub fn replace_ebb_param(&mut self, old_value: Value, new_type: Type) -> Value {
pub fn replace_block_param(&mut self, old_value: Value, new_type: Type) -> Value {
// Create new value identical to the old one except for the type.
let (ebb, num) = if let ValueData::Param { num, ebb, .. } = self.values[old_value] {
(ebb, num)
let (block, num) = if let ValueData::Param { num, block, .. } = self.values[old_value] {
(block, num)
} else {
panic!("{} must be an EBB parameter", old_value);
panic!("{} must be an block parameter", old_value);
};
let new_arg = self.make_value(ValueData::Param {
ty: new_type,
num,
ebb,
block,
});
self.ebbs[ebb].params.as_mut_slice(&mut self.value_lists)[num as usize] = new_arg;
self.blocks[block]
.params
.as_mut_slice(&mut self.value_lists)[num as usize] = new_arg;
new_arg
}
/// Detach all the parameters from `ebb` and return them as a `ValueList`.
/// Detach all the parameters from `block` and return them as a `ValueList`.
///
/// This is a quite low-level operation. Sensible things to do with the detached EBB parameters
/// is to put them back on the same EBB with `attach_ebb_param()` or change them into aliases
/// This is a quite low-level operation. Sensible things to do with the detached block parameters
/// is to put them back on the same block with `attach_block_param()` or change them into aliases
/// with `change_to_alias()`.
pub fn detach_ebb_params(&mut self, ebb: Ebb) -> ValueList {
self.ebbs[ebb].params.take()
pub fn detach_block_params(&mut self, block: Block) -> ValueList {
self.blocks[block].params.take()
}
}
/// Contents of an extended basic block.
/// Contents of a basic block.
///
/// Parameters on an extended basic block are values that dominate everything in the EBB. All
/// branches to this EBB must provide matching arguments, and the arguments to the entry EBB must
/// Parameters on a basic block are values that dominate everything in the block. All
/// branches to this block must provide matching arguments, and the arguments to the entry block must
/// match the function arguments.
#[derive(Clone)]
struct EbbData {
/// List of parameters to this EBB.
struct BlockData {
/// List of parameters to this block.
params: ValueList,
}
impl EbbData {
impl BlockData {
fn new() -> Self {
Self {
params: ValueList::new(),
@@ -1012,17 +1017,17 @@ impl DataFlowGraph {
self.make_inst_results_reusing(inst, ctrl_typevar, reuse.iter().map(|x| Some(*x)))
}
/// Similar to `append_ebb_param`, append a parameter with type `ty` to
/// `ebb`, but using value `val`. This is only for use by the parser to
/// Similar to `append_block_param`, append a parameter with type `ty` to
/// `block`, but using value `val`. This is only for use by the parser to
/// create parameters with specific values.
#[cold]
pub fn append_ebb_param_for_parser(&mut self, ebb: Ebb, ty: Type, val: Value) {
let num = self.ebbs[ebb].params.push(val, &mut self.value_lists);
assert!(num <= u16::MAX as usize, "Too many parameters on EBB");
pub fn append_block_param_for_parser(&mut self, block: Block, ty: Type, val: Value) {
let num = self.blocks[block].params.push(val, &mut self.value_lists);
assert!(num <= u16::MAX as usize, "Too many parameters on block");
self.values[val] = ValueData::Param {
ty,
num: num as u16,
ebb,
block,
};
}
@@ -1165,95 +1170,95 @@ mod tests {
}
#[test]
fn ebb() {
fn block() {
let mut dfg = DataFlowGraph::new();
let ebb = dfg.make_ebb();
assert_eq!(ebb.to_string(), "ebb0");
assert_eq!(dfg.num_ebb_params(ebb), 0);
assert_eq!(dfg.ebb_params(ebb), &[]);
assert!(dfg.detach_ebb_params(ebb).is_empty());
assert_eq!(dfg.num_ebb_params(ebb), 0);
assert_eq!(dfg.ebb_params(ebb), &[]);
let block = dfg.make_block();
assert_eq!(block.to_string(), "block0");
assert_eq!(dfg.num_block_params(block), 0);
assert_eq!(dfg.block_params(block), &[]);
assert!(dfg.detach_block_params(block).is_empty());
assert_eq!(dfg.num_block_params(block), 0);
assert_eq!(dfg.block_params(block), &[]);
let arg1 = dfg.append_ebb_param(ebb, types::F32);
let arg1 = dfg.append_block_param(block, types::F32);
assert_eq!(arg1.to_string(), "v0");
assert_eq!(dfg.num_ebb_params(ebb), 1);
assert_eq!(dfg.ebb_params(ebb), &[arg1]);
assert_eq!(dfg.num_block_params(block), 1);
assert_eq!(dfg.block_params(block), &[arg1]);
let arg2 = dfg.append_ebb_param(ebb, types::I16);
let arg2 = dfg.append_block_param(block, types::I16);
assert_eq!(arg2.to_string(), "v1");
assert_eq!(dfg.num_ebb_params(ebb), 2);
assert_eq!(dfg.ebb_params(ebb), &[arg1, arg2]);
assert_eq!(dfg.num_block_params(block), 2);
assert_eq!(dfg.block_params(block), &[arg1, arg2]);
assert_eq!(dfg.value_def(arg1), ValueDef::Param(ebb, 0));
assert_eq!(dfg.value_def(arg2), ValueDef::Param(ebb, 1));
assert_eq!(dfg.value_def(arg1), ValueDef::Param(block, 0));
assert_eq!(dfg.value_def(arg2), ValueDef::Param(block, 1));
assert_eq!(dfg.value_type(arg1), types::F32);
assert_eq!(dfg.value_type(arg2), types::I16);
// Swap the two EBB parameters.
let vlist = dfg.detach_ebb_params(ebb);
assert_eq!(dfg.num_ebb_params(ebb), 0);
assert_eq!(dfg.ebb_params(ebb), &[]);
// Swap the two block parameters.
let vlist = dfg.detach_block_params(block);
assert_eq!(dfg.num_block_params(block), 0);
assert_eq!(dfg.block_params(block), &[]);
assert_eq!(vlist.as_slice(&dfg.value_lists), &[arg1, arg2]);
dfg.attach_ebb_param(ebb, arg2);
let arg3 = dfg.append_ebb_param(ebb, types::I32);
dfg.attach_ebb_param(ebb, arg1);
assert_eq!(dfg.ebb_params(ebb), &[arg2, arg3, arg1]);
dfg.attach_block_param(block, arg2);
let arg3 = dfg.append_block_param(block, types::I32);
dfg.attach_block_param(block, arg1);
assert_eq!(dfg.block_params(block), &[arg2, arg3, arg1]);
}
#[test]
fn replace_ebb_params() {
fn replace_block_params() {
let mut dfg = DataFlowGraph::new();
let ebb = dfg.make_ebb();
let arg1 = dfg.append_ebb_param(ebb, types::F32);
let block = dfg.make_block();
let arg1 = dfg.append_block_param(block, types::F32);
let new1 = dfg.replace_ebb_param(arg1, types::I64);
let new1 = dfg.replace_block_param(arg1, types::I64);
assert_eq!(dfg.value_type(arg1), types::F32);
assert_eq!(dfg.value_type(new1), types::I64);
assert_eq!(dfg.ebb_params(ebb), &[new1]);
assert_eq!(dfg.block_params(block), &[new1]);
dfg.attach_ebb_param(ebb, arg1);
assert_eq!(dfg.ebb_params(ebb), &[new1, arg1]);
dfg.attach_block_param(block, arg1);
assert_eq!(dfg.block_params(block), &[new1, arg1]);
let new2 = dfg.replace_ebb_param(arg1, types::I8);
let new2 = dfg.replace_block_param(arg1, types::I8);
assert_eq!(dfg.value_type(arg1), types::F32);
assert_eq!(dfg.value_type(new2), types::I8);
assert_eq!(dfg.ebb_params(ebb), &[new1, new2]);
assert_eq!(dfg.block_params(block), &[new1, new2]);
dfg.attach_ebb_param(ebb, arg1);
assert_eq!(dfg.ebb_params(ebb), &[new1, new2, arg1]);
dfg.attach_block_param(block, arg1);
assert_eq!(dfg.block_params(block), &[new1, new2, arg1]);
let new3 = dfg.replace_ebb_param(new2, types::I16);
let new3 = dfg.replace_block_param(new2, types::I16);
assert_eq!(dfg.value_type(new1), types::I64);
assert_eq!(dfg.value_type(new2), types::I8);
assert_eq!(dfg.value_type(new3), types::I16);
assert_eq!(dfg.ebb_params(ebb), &[new1, new3, arg1]);
assert_eq!(dfg.block_params(block), &[new1, new3, arg1]);
}
#[test]
fn swap_remove_ebb_params() {
fn swap_remove_block_params() {
let mut dfg = DataFlowGraph::new();
let ebb = dfg.make_ebb();
let arg1 = dfg.append_ebb_param(ebb, types::F32);
let arg2 = dfg.append_ebb_param(ebb, types::F32);
let arg3 = dfg.append_ebb_param(ebb, types::F32);
assert_eq!(dfg.ebb_params(ebb), &[arg1, arg2, arg3]);
let block = dfg.make_block();
let arg1 = dfg.append_block_param(block, types::F32);
let arg2 = dfg.append_block_param(block, types::F32);
let arg3 = dfg.append_block_param(block, types::F32);
assert_eq!(dfg.block_params(block), &[arg1, arg2, arg3]);
dfg.swap_remove_ebb_param(arg1);
dfg.swap_remove_block_param(arg1);
assert_eq!(dfg.value_is_attached(arg1), false);
assert_eq!(dfg.value_is_attached(arg2), true);
assert_eq!(dfg.value_is_attached(arg3), true);
assert_eq!(dfg.ebb_params(ebb), &[arg3, arg2]);
dfg.swap_remove_ebb_param(arg2);
assert_eq!(dfg.block_params(block), &[arg3, arg2]);
dfg.swap_remove_block_param(arg2);
assert_eq!(dfg.value_is_attached(arg2), false);
assert_eq!(dfg.value_is_attached(arg3), true);
assert_eq!(dfg.ebb_params(ebb), &[arg3]);
dfg.swap_remove_ebb_param(arg3);
assert_eq!(dfg.block_params(block), &[arg3]);
dfg.swap_remove_block_param(arg3);
assert_eq!(dfg.value_is_attached(arg3), false);
assert_eq!(dfg.ebb_params(ebb), &[]);
assert_eq!(dfg.block_params(block), &[]);
}
#[test]
@@ -1261,9 +1266,9 @@ mod tests {
use crate::ir::InstBuilder;
let mut func = Function::new();
let ebb0 = func.dfg.make_ebb();
let block0 = func.dfg.make_block();
let mut pos = FuncCursor::new(&mut func);
pos.insert_ebb(ebb0);
pos.insert_block(block0);
// Build a little test program.
let v1 = pos.ins().iconst(types::I32, 42);
@@ -1271,7 +1276,7 @@ mod tests {
// Make sure we can resolve value aliases even when values is empty.
assert_eq!(pos.func.dfg.resolve_aliases(v1), v1);
let arg0 = pos.func.dfg.append_ebb_param(ebb0, types::I32);
let arg0 = pos.func.dfg.append_block_param(block0, types::I32);
let (s, c) = pos.ins().iadd_ifcout(v1, arg0);
let iadd = match pos.func.dfg.value_def(s) {
ValueDef::Result(i, 0) => i,

View File

@@ -1,7 +1,7 @@
//! Cranelift IR entity references.
//!
//! Instructions in Cranelift IR need to reference other entities in the function. This can be other
//! parts of the function like extended basic blocks or stack slots, or it can be external entities
//! parts of the function like basic blocks or stack slots, or it can be external entities
//! that are declared in the function preamble in the text format.
//!
//! These entity references in instruction operands are not implemented as Rust references both
@@ -25,20 +25,19 @@ use core::u32;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// An opaque reference to an [extended basic
/// block](https://en.wikipedia.org/wiki/Extended_basic_block) in a
/// An opaque reference to a [basic block](https://en.wikipedia.org/wiki/Basic_block) in a
/// [`Function`](super::function::Function).
///
/// You can get an `Ebb` using
/// [`FunctionBuilder::create_ebb`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_ebb)
/// You can get a `Block` using
/// [`FunctionBuilder::create_block`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_block)
///
/// While the order is stable, it is arbitrary and does not necessarily resemble the layout order.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Ebb(u32);
entity_impl!(Ebb, "ebb");
pub struct Block(u32);
entity_impl!(Block, "block");
impl Ebb {
/// Create a new EBB reference from its number. This corresponds to the `ebbNN` representation.
impl Block {
/// Create a new block reference from its number. This corresponds to the `blockNN` representation.
///
/// This method is for use by the parser.
pub fn with_number(n: u32) -> Option<Self> {
@@ -371,8 +370,8 @@ impl Table {
pub enum AnyEntity {
/// The whole function.
Function,
/// An extended basic block.
Ebb(Ebb),
/// a basic block.
Block(Block),
/// An instruction.
Inst(Inst),
/// An SSA value.
@@ -397,7 +396,7 @@ impl fmt::Display for AnyEntity {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Function => write!(f, "function"),
Self::Ebb(r) => r.fmt(f),
Self::Block(r) => r.fmt(f),
Self::Inst(r) => r.fmt(f),
Self::Value(r) => r.fmt(f),
Self::StackSlot(r) => r.fmt(f),
@@ -417,9 +416,9 @@ impl fmt::Debug for AnyEntity {
}
}
impl From<Ebb> for AnyEntity {
fn from(r: Ebb) -> Self {
Self::Ebb(r)
impl From<Block> for AnyEntity {
fn from(r: Block) -> Self {
Self::Block(r)
}
}

View File

@@ -32,8 +32,8 @@ pub enum ExternalName {
/// Arbitrary.
index: u32,
},
/// A test case function name of up to 10 ascii characters. This is
/// not intended to be used outside test cases.
/// A test case function name of up to a hardcoded amount of ascii
/// characters. This is not intended to be used outside test cases.
TestCase {
/// How many of the bytes in `ascii` are valid?
length: u8,

View File

@@ -1,17 +1,17 @@
//! Intermediate representation of a function.
//!
//! The `Function` struct defined in this module owns all of its extended basic blocks and
//! The `Function` struct defined in this module owns all of its basic blocks and
//! instructions.
use crate::binemit::CodeOffset;
use crate::entity::{PrimaryMap, SecondaryMap};
use crate::ir;
use crate::ir::{DataFlowGraph, ExternalName, Layout, Signature};
use crate::ir::{
Ebb, ExtFuncData, FuncRef, GlobalValue, GlobalValueData, Heap, HeapData, Inst, JumpTable,
Block, ExtFuncData, FuncRef, GlobalValue, GlobalValueData, Heap, HeapData, Inst, JumpTable,
JumpTableData, Opcode, SigRef, StackSlot, StackSlotData, Table, TableData,
};
use crate::ir::{EbbOffsets, FrameLayout, InstEncodings, SourceLocs, StackSlots, ValueLocations};
use crate::ir::{BlockOffsets, FrameLayout, InstEncodings, SourceLocs, StackSlots, ValueLocations};
use crate::ir::{DataFlowGraph, ExternalName, Layout, Signature};
use crate::ir::{JumpTableOffsets, JumpTables};
use crate::isa::{CallConv, EncInfo, Encoding, Legalize, TargetIsa};
use crate::regalloc::{EntryRegDiversions, RegDiversions};
@@ -50,10 +50,10 @@ pub struct Function {
/// Jump tables used in this function.
pub jump_tables: JumpTables,
/// Data flow graph containing the primary definition of all instructions, EBBs and values.
/// Data flow graph containing the primary definition of all instructions, blocks and values.
pub dfg: DataFlowGraph,
/// Layout of EBBs and instructions in the function body.
/// Layout of blocks and instructions in the function body.
pub layout: Layout,
/// Encoding recipe and bits for the legal instructions.
@@ -69,12 +69,12 @@ pub struct Function {
/// ValueLocation. This field records these register-to-register moves as Diversions.
pub entry_diversions: EntryRegDiversions,
/// Code offsets of the EBB headers.
/// Code offsets of the block headers.
///
/// This information is only transiently available after the `binemit::relax_branches` function
/// computes it, and it can easily be recomputed by calling that function. It is not included
/// in the textual IR format.
pub offsets: EbbOffsets,
pub offsets: BlockOffsets,
/// Code offsets of Jump Table headers.
pub jt_offsets: JumpTableOffsets,
@@ -207,10 +207,10 @@ impl Function {
let entry = self.layout.entry_block().expect("Function is empty");
self.signature
.special_param_index(purpose)
.map(|i| self.dfg.ebb_params(entry)[i])
.map(|i| self.dfg.block_params(entry)[i])
}
/// Get an iterator over the instructions in `ebb`, including offsets and encoded instruction
/// Get an iterator over the instructions in `block`, including offsets and encoded instruction
/// sizes.
///
/// The iterator returns `(offset, inst, size)` tuples, where `offset` if the offset in bytes
@@ -219,20 +219,20 @@ impl Function {
///
/// This function can only be used after the code layout has been computed by the
/// `binemit::relax_branches()` function.
pub fn inst_offsets<'a>(&'a self, ebb: Ebb, encinfo: &EncInfo) -> InstOffsetIter<'a> {
pub fn inst_offsets<'a>(&'a self, block: Block, encinfo: &EncInfo) -> InstOffsetIter<'a> {
assert!(
!self.offsets.is_empty(),
"Code layout must be computed first"
);
let mut divert = RegDiversions::new();
divert.at_ebb(&self.entry_diversions, ebb);
divert.at_block(&self.entry_diversions, block);
InstOffsetIter {
encinfo: encinfo.clone(),
func: self,
divert,
encodings: &self.encodings,
offset: self.offsets[ebb],
iter: self.layout.ebb_insts(ebb),
offset: self.offsets[block],
iter: self.layout.block_insts(block),
}
}
@@ -260,19 +260,19 @@ impl Function {
/// Changes the destination of a jump or branch instruction.
/// Does nothing if called with a non-jump or non-branch instruction.
pub fn change_branch_destination(&mut self, inst: Inst, new_dest: Ebb) {
pub fn change_branch_destination(&mut self, inst: Inst, new_dest: Block) {
match self.dfg[inst].branch_destination_mut() {
None => (),
Some(inst_dest) => *inst_dest = new_dest,
}
}
/// Checks that the specified EBB can be encoded as a basic block.
/// Checks that the specified block can be encoded as a basic block.
///
/// On error, returns the first invalid instruction and an error message.
pub fn is_ebb_basic(&self, ebb: Ebb) -> Result<(), (Inst, &'static str)> {
pub fn is_block_basic(&self, block: Block) -> Result<(), (Inst, &'static str)> {
let dfg = &self.dfg;
let inst_iter = self.layout.ebb_insts(ebb);
let inst_iter = self.layout.block_insts(block);
// Ignore all instructions prior to the first branch.
let mut inst_iter = inst_iter.skip_while(|&inst| !dfg[inst].opcode().is_branch());

View File

@@ -13,7 +13,7 @@ use core::str::FromStr;
use crate::ir;
use crate::ir::types;
use crate::ir::{Ebb, FuncRef, JumpTable, SigRef, Type, Value};
use crate::ir::{Block, FuncRef, JumpTable, SigRef, Type, Value};
use crate::isa;
use crate::bitset::BitSet;
@@ -164,7 +164,7 @@ impl Default for VariableArgs {
impl InstructionData {
/// Return information about the destination of a branch or jump instruction.
///
/// Any instruction that can transfer control to another EBB reveals its possible destinations
/// Any instruction that can transfer control to another block reveals its possible destinations
/// here.
pub fn analyze_branch<'a>(&'a self, pool: &'a ValueListPool) -> BranchInfo<'a> {
match *self {
@@ -208,7 +208,7 @@ impl InstructionData {
/// branch or jump.
///
/// Multi-destination branches like `br_table` return `None`.
pub fn branch_destination(&self) -> Option<Ebb> {
pub fn branch_destination(&self) -> Option<Block> {
match *self {
Self::Jump { destination, .. }
| Self::Branch { destination, .. }
@@ -227,7 +227,7 @@ impl InstructionData {
/// single destination branch or jump.
///
/// Multi-destination branches like `br_table` return `None`.
pub fn branch_destination_mut(&mut self) -> Option<&mut Ebb> {
pub fn branch_destination_mut(&mut self) -> Option<&mut Block> {
match *self {
Self::Jump {
ref mut destination,
@@ -279,15 +279,15 @@ impl InstructionData {
/// Information about branch and jump instructions.
pub enum BranchInfo<'a> {
/// This is not a branch or jump instruction.
/// This instruction will not transfer control to another EBB in the function, but it may still
/// This instruction will not transfer control to another block in the function, but it may still
/// affect control flow by returning or trapping.
NotABranch,
/// This is a branch or jump to a single destination EBB, possibly taking value arguments.
SingleDest(Ebb, &'a [Value]),
/// This is a branch or jump to a single destination block, possibly taking value arguments.
SingleDest(Block, &'a [Value]),
/// This is a jump table branch which can have many destination EBBs and maybe one default EBB.
Table(JumpTable, Option<Ebb>),
/// This is a jump table branch which can have many destination blocks and maybe one default block.
Table(JumpTable, Option<Block>),
}
/// Information about call instructions.

View File

@@ -3,7 +3,7 @@
//! Jump tables are declared in the preamble and assigned an `ir::entities::JumpTable` reference.
//! The actual table of destinations is stored in a `JumpTableData` struct defined in this module.
use crate::ir::entities::Ebb;
use crate::ir::entities::Block;
use alloc::vec::Vec;
use core::fmt::{self, Display, Formatter};
use core::slice::{Iter, IterMut};
@@ -14,7 +14,7 @@ use core::slice::{Iter, IterMut};
#[derive(Clone)]
pub struct JumpTableData {
// Table entries.
table: Vec<Ebb>,
table: Vec<Block>,
}
impl JumpTableData {
@@ -36,32 +36,32 @@ impl JumpTableData {
}
/// Append a table entry.
pub fn push_entry(&mut self, dest: Ebb) {
pub fn push_entry(&mut self, dest: Block) {
self.table.push(dest)
}
/// Checks if any of the entries branch to `ebb`.
pub fn branches_to(&self, ebb: Ebb) -> bool {
self.table.iter().any(|target_ebb| *target_ebb == ebb)
/// Checks if any of the entries branch to `block`.
pub fn branches_to(&self, block: Block) -> bool {
self.table.iter().any(|target_block| *target_block == block)
}
/// Access the whole table as a slice.
pub fn as_slice(&self) -> &[Ebb] {
pub fn as_slice(&self) -> &[Block] {
self.table.as_slice()
}
/// Access the whole table as a mutable slice.
pub fn as_mut_slice(&mut self) -> &mut [Ebb] {
pub fn as_mut_slice(&mut self) -> &mut [Block] {
self.table.as_mut_slice()
}
/// Returns an iterator over the table.
pub fn iter(&self) -> Iter<Ebb> {
pub fn iter(&self) -> Iter<Block> {
self.table.iter()
}
/// Returns an iterator that allows modifying each value.
pub fn iter_mut(&mut self) -> IterMut<Ebb> {
pub fn iter_mut(&mut self) -> IterMut<Block> {
self.table.iter_mut()
}
}
@@ -73,8 +73,8 @@ impl Display for JumpTableData {
None => (),
Some(first) => write!(fmt, "{}", first)?,
}
for ebb in self.table.iter().skip(1) {
write!(fmt, ", {}", ebb)?;
for block in self.table.iter().skip(1) {
write!(fmt, ", {}", block)?;
}
write!(fmt, "]")
}
@@ -84,7 +84,7 @@ impl Display for JumpTableData {
mod tests {
use super::JumpTableData;
use crate::entity::EntityRef;
use crate::ir::Ebb;
use crate::ir::Block;
use alloc::string::ToString;
#[test]
@@ -102,8 +102,8 @@ mod tests {
#[test]
fn insert() {
let e1 = Ebb::new(1);
let e2 = Ebb::new(2);
let e1 = Block::new(1);
let e2 = Block::new(2);
let mut jt = JumpTableData::new();
@@ -111,7 +111,7 @@ mod tests {
jt.push_entry(e2);
jt.push_entry(e1);
assert_eq!(jt.to_string(), "jump_table [ebb1, ebb2, ebb1]");
assert_eq!(jt.to_string(), "jump_table [block1, block2, block1]");
let v = jt.as_slice();
assert_eq!(v, [e1, e2, e1]);

File diff suppressed because it is too large Load Diff

View File

@@ -33,7 +33,7 @@ pub use crate::ir::builder::{
pub use crate::ir::constant::{ConstantData, ConstantOffset, ConstantPool};
pub use crate::ir::dfg::{DataFlowGraph, ValueDef};
pub use crate::ir::entities::{
Constant, Ebb, FuncRef, GlobalValue, Heap, Immediate, Inst, JumpTable, SigRef, StackSlot,
Block, Constant, FuncRef, GlobalValue, Heap, Immediate, Inst, JumpTable, SigRef, StackSlot,
Table, Value,
};
pub use crate::ir::extfunc::{
@@ -73,8 +73,8 @@ pub type JumpTables = PrimaryMap<JumpTable, JumpTableData>;
/// Map of instruction encodings.
pub type InstEncodings = SecondaryMap<Inst, isa::Encoding>;
/// Code offsets for EBBs.
pub type EbbOffsets = SecondaryMap<Ebb, binemit::CodeOffset>;
/// Code offsets for blocks.
pub type BlockOffsets = SecondaryMap<Block, binemit::CodeOffset>;
/// Code offsets for Jump Tables.
pub type JumpTableOffsets = SecondaryMap<JumpTable, binemit::CodeOffset>;

View File

@@ -1,7 +1,7 @@
//! Program points.
use crate::entity::EntityRef;
use crate::ir::{Ebb, Inst, ValueDef};
use crate::ir::{Block, Inst, ValueDef};
use core::cmp;
use core::fmt;
use core::u32;
@@ -10,7 +10,7 @@ use core::u32;
/// begin or end. It can be either:
///
/// 1. An instruction or
/// 2. An EBB header.
/// 2. An block header.
///
/// This corresponds more or less to the lines in the textual form of Cranelift IR.
#[derive(PartialEq, Eq, Clone, Copy)]
@@ -24,9 +24,9 @@ impl From<Inst> for ProgramPoint {
}
}
impl From<Ebb> for ProgramPoint {
fn from(ebb: Ebb) -> Self {
let idx = ebb.index();
impl From<Block> for ProgramPoint {
fn from(block: Block) -> Self {
let idx = block.index();
debug_assert!(idx < (u32::MAX / 2) as usize);
Self((idx * 2 + 1) as u32)
}
@@ -36,7 +36,7 @@ impl From<ValueDef> for ProgramPoint {
fn from(def: ValueDef) -> Self {
match def {
ValueDef::Result(inst, _) => inst.into(),
ValueDef::Param(ebb, _) => ebb.into(),
ValueDef::Param(block, _) => block.into(),
}
}
}
@@ -47,8 +47,8 @@ impl From<ValueDef> for ProgramPoint {
pub enum ExpandedProgramPoint {
/// An instruction in the function.
Inst(Inst),
/// An EBB header.
Ebb(Ebb),
/// An block header.
Block(Block),
}
impl ExpandedProgramPoint {
@@ -56,7 +56,7 @@ impl ExpandedProgramPoint {
pub fn unwrap_inst(self) -> Inst {
match self {
Self::Inst(x) => x,
Self::Ebb(x) => panic!("expected inst: {}", x),
Self::Block(x) => panic!("expected inst: {}", x),
}
}
}
@@ -67,9 +67,9 @@ impl From<Inst> for ExpandedProgramPoint {
}
}
impl From<Ebb> for ExpandedProgramPoint {
fn from(ebb: Ebb) -> Self {
Self::Ebb(ebb)
impl From<Block> for ExpandedProgramPoint {
fn from(block: Block) -> Self {
Self::Block(block)
}
}
@@ -77,7 +77,7 @@ impl From<ValueDef> for ExpandedProgramPoint {
fn from(def: ValueDef) -> Self {
match def {
ValueDef::Result(inst, _) => inst.into(),
ValueDef::Param(ebb, _) => ebb.into(),
ValueDef::Param(block, _) => block.into(),
}
}
}
@@ -87,7 +87,7 @@ impl From<ProgramPoint> for ExpandedProgramPoint {
if pp.0 & 1 == 0 {
Self::Inst(Inst::from_u32(pp.0 / 2))
} else {
Self::Ebb(Ebb::from_u32(pp.0 / 2))
Self::Block(Block::from_u32(pp.0 / 2))
}
}
}
@@ -96,7 +96,7 @@ impl fmt::Display for ExpandedProgramPoint {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Inst(x) => write!(f, "{}", x),
Self::Ebb(x) => write!(f, "{}", x),
Self::Block(x) => write!(f, "{}", x),
}
}
}
@@ -129,7 +129,7 @@ pub trait ProgramOrder {
///
/// Return `Less` if `a` appears in the program before `b`.
///
/// This is declared as a generic such that it can be called with `Inst` and `Ebb` arguments
/// This is declared as a generic such that it can be called with `Inst` and `Block` arguments
/// directly. Depending on the implementation, there is a good chance performance will be
/// improved for those cases where the type of either argument is known statically.
fn cmp<A, B>(&self, a: A, b: B) -> cmp::Ordering
@@ -137,28 +137,28 @@ pub trait ProgramOrder {
A: Into<ExpandedProgramPoint>,
B: Into<ExpandedProgramPoint>;
/// Is the range from `inst` to `ebb` just the gap between consecutive EBBs?
/// Is the range from `inst` to `block` just the gap between consecutive blocks?
///
/// This returns true if `inst` is the terminator in the EBB immediately before `ebb`.
fn is_ebb_gap(&self, inst: Inst, ebb: Ebb) -> bool;
/// This returns true if `inst` is the terminator in the block immediately before `block`.
fn is_block_gap(&self, inst: Inst, block: Block) -> bool;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::entity::EntityRef;
use crate::ir::{Ebb, Inst};
use crate::ir::{Block, Inst};
use alloc::string::ToString;
#[test]
fn convert() {
let i5 = Inst::new(5);
let b3 = Ebb::new(3);
let b3 = Block::new(3);
let pp1: ProgramPoint = i5.into();
let pp2: ProgramPoint = b3.into();
assert_eq!(pp1.to_string(), "inst5");
assert_eq!(pp2.to_string(), "ebb3");
assert_eq!(pp2.to_string(), "block3");
}
}