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

@@ -26,7 +26,7 @@ use super::{hash_map, HashMap};
use crate::environ::{FuncEnvironment, GlobalVariable, ReturnMode, WasmResult};
use crate::state::{ControlStackFrame, ElseData, FuncTranslationState, ModuleTranslationState};
use crate::translation_utils::{
blocktype_params_results, ebb_with_params, f32_translation, f64_translation,
block_with_params, blocktype_params_results, f32_translation, f64_translation,
};
use crate::translation_utils::{FuncIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex};
use crate::wasm_unsupported;
@@ -147,32 +147,34 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
state.reachable = false;
}
/***************************** Control flow blocks **********************************
* When starting a control flow block, we create a new `Ebb` that will hold the code
* When starting a control flow block, we create a new `Block` that will hold the code
* after the block, and we push a frame on the control stack. Depending on the type
* of block, we create a new `Ebb` for the body of the block with an associated
* of block, we create a new `Block` for the body of the block with an associated
* jump instruction.
*
* The `End` instruction pops the last control frame from the control stack, seals
* the destination block (since `br` instructions targeting it only appear inside the
* block and have already been translated) and modify the value stack to use the
* possible `Ebb`'s arguments values.
* possible `Block`'s arguments values.
***********************************************************************************/
Operator::Block { ty } => {
let (params, results) = blocktype_params_results(module_translation_state, *ty)?;
let next = ebb_with_params(builder, results, environ)?;
let next = block_with_params(builder, results, environ)?;
state.push_block(next, params.len(), results.len());
}
Operator::Loop { ty } => {
let (params, results) = blocktype_params_results(module_translation_state, *ty)?;
let loop_body = ebb_with_params(builder, params, environ)?;
let next = ebb_with_params(builder, results, environ)?;
let loop_body = block_with_params(builder, params, environ)?;
let next = block_with_params(builder, results, environ)?;
builder.ins().jump(loop_body, state.peekn(params.len()));
state.push_loop(loop_body, next, params.len(), results.len());
// Pop the initial `Ebb` actuals and replace them with the `Ebb`'s
// Pop the initial `Block` actuals and replace them with the `Block`'s
// params since control flow joins at the top of the loop.
state.popn(params.len());
state.stack.extend_from_slice(builder.ebb_params(loop_body));
state
.stack
.extend_from_slice(builder.block_params(loop_body));
builder.switch_to_block(loop_body);
environ.translate_loop_header(builder.cursor())?;
@@ -183,12 +185,12 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
let (params, results) = blocktype_params_results(module_translation_state, *ty)?;
let (destination, else_data) = if params == results {
// It is possible there is no `else` block, so we will only
// allocate an ebb for it if/when we find the `else`. For now,
// allocate an block for it if/when we find the `else`. For now,
// we if the condition isn't true, then we jump directly to the
// destination ebb following the whole `if...end`. If we do end
// up discovering an `else`, then we will allocate an ebb for it
// destination block following the whole `if...end`. If we do end
// up discovering an `else`, then we will allocate an block for it
// and go back and patch the jump.
let destination = ebb_with_params(builder, results, environ)?;
let destination = block_with_params(builder, results, environ)?;
let branch_inst = builder
.ins()
.brz(val, destination, state.peekn(params.len()));
@@ -196,8 +198,8 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
} else {
// The `if` type signature is not valid without an `else` block,
// so we eagerly allocate the `else` block here.
let destination = ebb_with_params(builder, results, environ)?;
let else_block = ebb_with_params(builder, params, environ)?;
let destination = block_with_params(builder, results, environ)?;
let else_block = block_with_params(builder, params, environ)?;
builder
.ins()
.brz(val, else_block, state.peekn(params.len()));
@@ -205,12 +207,12 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
(destination, ElseData::WithElse { else_block })
};
let next_ebb = builder.create_ebb();
builder.ins().jump(next_ebb, &[]);
builder.seal_block(next_ebb); // Only predecessor is the current block.
builder.switch_to_block(next_ebb);
let next_block = builder.create_block();
builder.ins().jump(next_block, &[]);
builder.seal_block(next_block); // Only predecessor is the current block.
builder.switch_to_block(next_block);
// Here we append an argument to an Ebb targeted by an argumentless jump instruction
// Here we append an argument to an Block targeted by an argumentless jump instruction
// But in fact there are two cases:
// - either the If does not have a Else clause, in that case ty = EmptyBlock
// and we add nothing;
@@ -239,20 +241,20 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
// We have a branch from the head of the `if` to the `else`.
state.reachable = true;
// Ensure we have an ebb for the `else` block (it may have
// Ensure we have an block for the `else` block (it may have
// already been pre-allocated, see `ElseData` for details).
let else_ebb = match *else_data {
let else_block = match *else_data {
ElseData::NoElse { branch_inst } => {
let (params, _results) =
blocktype_params_results(module_translation_state, blocktype)?;
debug_assert_eq!(params.len(), num_return_values);
let else_ebb = ebb_with_params(builder, params, environ)?;
let else_block = block_with_params(builder, params, environ)?;
builder.ins().jump(destination, state.peekn(params.len()));
state.popn(params.len());
builder.change_jump_destination(branch_inst, else_ebb);
builder.seal_block(else_ebb);
else_ebb
builder.change_jump_destination(branch_inst, else_block);
builder.seal_block(else_block);
else_block
}
ElseData::WithElse { else_block } => {
builder
@@ -273,7 +275,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
// `if` so that we wouldn't have to save the parameters in the
// `ControlStackFrame` as another `Vec` allocation.
builder.switch_to_block(else_ebb);
builder.switch_to_block(else_block);
// We don't bother updating the control frame's `ElseData`
// to `WithElse` because nothing else will read it.
@@ -284,13 +286,13 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
}
Operator::End => {
let frame = state.control_stack.pop().unwrap();
let next_ebb = frame.following_code();
let next_block = frame.following_code();
if !builder.is_unreachable() || !builder.is_pristine() {
let return_count = frame.num_return_values();
let return_args = state.peekn_mut(return_count);
let next_ebb_types = builder.func.dfg.ebb_param_types(next_ebb);
bitcast_arguments(return_args, &next_ebb_types, builder);
let next_block_types = builder.func.dfg.block_param_types(next_block);
bitcast_arguments(return_args, &next_block_types, builder);
builder.ins().jump(frame.following_code(), return_args);
// You might expect that if we just finished an `if` block that
// didn't have a corresponding `else` block, then we would clean
@@ -299,33 +301,35 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
// since we truncate the stack back to the original height
// below.
}
builder.switch_to_block(next_ebb);
builder.seal_block(next_ebb);
builder.switch_to_block(next_block);
builder.seal_block(next_block);
// If it is a loop we also have to seal the body loop block
if let ControlStackFrame::Loop { header, .. } = frame {
builder.seal_block(header)
}
state.stack.truncate(frame.original_stack_size());
state.stack.extend_from_slice(builder.ebb_params(next_ebb));
state
.stack
.extend_from_slice(builder.block_params(next_block));
}
/**************************** Branch instructions *********************************
* The branch instructions all have as arguments a target nesting level, which
* corresponds to how many control stack frames do we have to pop to get the
* destination `Ebb`.
* destination `Block`.
*
* Once the destination `Ebb` is found, we sometimes have to declare a certain depth
* Once the destination `Block` is found, we sometimes have to declare a certain depth
* of the stack unreachable, because some branch instructions are terminator.
*
* The `br_table` case is much more complicated because Cranelift's `br_table` instruction
* does not support jump arguments like all the other branch instructions. That is why, in
* the case where we would use jump arguments for every other branch instructions, we
* need to split the critical edges leaving the `br_tables` by creating one `Ebb` per
* table destination; the `br_table` will point to these newly created `Ebbs` and these
* `Ebb`s contain only a jump instruction pointing to the final destination, this time with
* need to split the critical edges leaving the `br_tables` by creating one `Block` per
* table destination; the `br_table` will point to these newly created `Blocks` and these
* `Block`s contain only a jump instruction pointing to the final destination, this time with
* jump arguments.
*
* This system is also implemented in Cranelift's SSA construction algorithm, because
* `use_var` located in a destination `Ebb` of a `br_table` might trigger the addition
* `use_var` located in a destination `Block` of a `br_table` might trigger the addition
* of jump arguments in each predecessor branch instruction, one of which might be a
* `br_table`.
***********************************************************************************/
@@ -345,7 +349,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
// Bitcast any vector arguments to their default type, I8X16, before jumping.
let destination_args = state.peekn_mut(return_count);
let destination_types = builder.func.dfg.ebb_param_types(br_destination);
let destination_types = builder.func.dfg.block_param_types(br_destination);
bitcast_arguments(
destination_args,
&destination_types[..return_count],
@@ -379,53 +383,53 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
if jump_args_count == 0 {
// No jump arguments
for depth in &*depths {
let ebb = {
let block = {
let i = state.control_stack.len() - 1 - (*depth as usize);
let frame = &mut state.control_stack[i];
frame.set_branched_to_exit();
frame.br_destination()
};
data.push_entry(ebb);
data.push_entry(block);
}
let jt = builder.create_jump_table(data);
let ebb = {
let block = {
let i = state.control_stack.len() - 1 - (default as usize);
let frame = &mut state.control_stack[i];
frame.set_branched_to_exit();
frame.br_destination()
};
builder.ins().br_table(val, ebb, jt);
builder.ins().br_table(val, block, jt);
} else {
// Here we have jump arguments, but Cranelift's br_table doesn't support them
// We then proceed to split the edges going out of the br_table
let return_count = jump_args_count;
let mut dest_ebb_sequence = vec![];
let mut dest_ebb_map = HashMap::new();
let mut dest_block_sequence = vec![];
let mut dest_block_map = HashMap::new();
for depth in &*depths {
let branch_ebb = match dest_ebb_map.entry(*depth as usize) {
let branch_block = match dest_block_map.entry(*depth as usize) {
hash_map::Entry::Occupied(entry) => *entry.get(),
hash_map::Entry::Vacant(entry) => {
let ebb = builder.create_ebb();
dest_ebb_sequence.push((*depth as usize, ebb));
*entry.insert(ebb)
let block = builder.create_block();
dest_block_sequence.push((*depth as usize, block));
*entry.insert(block)
}
};
data.push_entry(branch_ebb);
data.push_entry(branch_block);
}
let default_branch_ebb = match dest_ebb_map.entry(default as usize) {
let default_branch_block = match dest_block_map.entry(default as usize) {
hash_map::Entry::Occupied(entry) => *entry.get(),
hash_map::Entry::Vacant(entry) => {
let ebb = builder.create_ebb();
dest_ebb_sequence.push((default as usize, ebb));
*entry.insert(ebb)
let block = builder.create_block();
dest_block_sequence.push((default as usize, block));
*entry.insert(block)
}
};
let jt = builder.create_jump_table(data);
builder.ins().br_table(val, default_branch_ebb, jt);
for (depth, dest_ebb) in dest_ebb_sequence {
builder.switch_to_block(dest_ebb);
builder.seal_block(dest_ebb);
let real_dest_ebb = {
builder.ins().br_table(val, default_branch_block, jt);
for (depth, dest_block) in dest_block_sequence {
builder.switch_to_block(dest_block);
builder.seal_block(dest_block);
let real_dest_block = {
let i = state.control_stack.len() - 1 - depth;
let frame = &mut state.control_stack[i];
frame.set_branched_to_exit();
@@ -434,14 +438,14 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
// Bitcast any vector arguments to their default type, I8X16, before jumping.
let destination_args = state.peekn_mut(return_count);
let destination_types = builder.func.dfg.ebb_param_types(real_dest_ebb);
let destination_types = builder.func.dfg.block_param_types(real_dest_block);
bitcast_arguments(
destination_args,
&destination_types[..return_count],
builder,
);
builder.ins().jump(real_dest_ebb, destination_args);
builder.ins().jump(real_dest_block, destination_args);
}
state.popn(return_count);
}
@@ -1498,7 +1502,7 @@ fn translate_unreachable_operator<FE: FuncEnvironment + ?Sized>(
// Push a placeholder control stack entry. The if isn't reachable,
// so we don't have any branches anywhere.
state.push_if(
ir::Ebb::reserved_value(),
ir::Block::reserved_value(),
ElseData::NoElse {
branch_inst: ir::Inst::reserved_value(),
},
@@ -1508,7 +1512,7 @@ fn translate_unreachable_operator<FE: FuncEnvironment + ?Sized>(
);
}
Operator::Loop { ty: _ } | Operator::Block { ty: _ } => {
state.push_block(ir::Ebb::reserved_value(), 0, 0);
state.push_block(ir::Block::reserved_value(), 0, 0);
}
Operator::Else => {
let i = state.control_stack.len() - 1;
@@ -1527,21 +1531,21 @@ fn translate_unreachable_operator<FE: FuncEnvironment + ?Sized>(
// We have a branch from the head of the `if` to the `else`.
state.reachable = true;
let else_ebb = match *else_data {
let else_block = match *else_data {
ElseData::NoElse { branch_inst } => {
let (params, _results) =
blocktype_params_results(module_translation_state, blocktype)?;
let else_ebb = ebb_with_params(builder, params, environ)?;
let else_block = block_with_params(builder, params, environ)?;
// We change the target of the branch instruction.
builder.change_jump_destination(branch_inst, else_ebb);
builder.seal_block(else_ebb);
else_ebb
builder.change_jump_destination(branch_inst, else_block);
builder.seal_block(else_block);
else_block
}
ElseData::WithElse { else_block } => else_block,
};
builder.switch_to_block(else_ebb);
builder.switch_to_block(else_block);
// Again, no need to push the parameters for the `else`,
// since we already did when we saw the original `if`. See
@@ -1596,7 +1600,7 @@ fn translate_unreachable_operator<FE: FuncEnvironment + ?Sized>(
// And add the return values of the block but only if the next block is reachable
// (which corresponds to testing if the stack depth is 1)
stack.extend_from_slice(builder.ebb_params(frame.following_code()));
stack.extend_from_slice(builder.block_params(frame.following_code()));
state.reachable = true;
}
}
@@ -1736,21 +1740,21 @@ fn translate_br_if(
let (br_destination, inputs) = translate_br_if_args(relative_depth, state);
// Bitcast any vector arguments to their default type, I8X16, before jumping.
let destination_types = builder.func.dfg.ebb_param_types(br_destination);
let destination_types = builder.func.dfg.block_param_types(br_destination);
bitcast_arguments(inputs, &destination_types[..inputs.len()], builder);
builder.ins().brnz(val, br_destination, inputs);
let next_ebb = builder.create_ebb();
builder.ins().jump(next_ebb, &[]);
builder.seal_block(next_ebb); // The only predecessor is the current block.
builder.switch_to_block(next_ebb);
let next_block = builder.create_block();
builder.ins().jump(next_block, &[]);
builder.seal_block(next_block); // The only predecessor is the current block.
builder.switch_to_block(next_block);
}
fn translate_br_if_args(
relative_depth: u32,
state: &mut FuncTranslationState,
) -> (ir::Ebb, &mut [ir::Value]) {
) -> (ir::Block, &mut [ir::Value]) {
let i = state.control_stack.len() - 1 - (relative_depth as usize);
let (return_count, br_destination) = {
let frame = &mut state.control_stack[i];
@@ -1973,7 +1977,7 @@ fn pop2_with_bitcast(
/// A helper for bitcasting a sequence of values (e.g. function arguments). If a value is a
/// vector type that does not match its expected type, this will modify the value in place to point
/// to the result of a `raw_bitcast`. This conversion is necessary to translate Wasm code that
/// uses `V128` as function parameters (or implicitly in EBB parameters) and still use specific
/// uses `V128` as function parameters (or implicitly in block parameters) and still use specific
/// CLIF types (e.g. `I32X4`) in the function body.
pub fn bitcast_arguments(
arguments: &mut [Value],