Skip to content

Commit bcddce5

Browse files
authored
Simplify ssa builder (#1340)
* Simplify SSABuilder with basic block * Simplify FunctionBuilder with basic block * Update SSABuilder test * Update SSABuilder doc
1 parent adff432 commit bcddce5

File tree

2 files changed

+454
-514
lines changed

2 files changed

+454
-514
lines changed

cranelift/frontend/src/frontend.rs

Lines changed: 27 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! A frontend for building Cranelift IR from other languages.
2-
use crate::ssa::{SSABlock, SSABuilder, SideEffects};
2+
use crate::ssa::{SSABuilder, SideEffects};
33
use crate::variable::Variable;
44
use cranelift_codegen::cursor::{Cursor, FuncCursor};
55
use cranelift_codegen::entity::{EntitySet, SecondaryMap};
@@ -35,7 +35,7 @@ pub struct FunctionBuilder<'a> {
3535
srcloc: ir::SourceLoc,
3636

3737
func_ctx: &'a mut FunctionBuilderContext,
38-
position: Position,
38+
position: PackedOption<Block>,
3939
}
4040

4141
#[derive(Clone, Default)]
@@ -54,25 +54,6 @@ struct BlockData {
5454
user_param_count: usize,
5555
}
5656

57-
#[derive(Default)]
58-
struct Position {
59-
block: PackedOption<Block>,
60-
basic_block: PackedOption<SSABlock>,
61-
}
62-
63-
impl Position {
64-
fn at(block: Block, basic_block: SSABlock) -> Self {
65-
Self {
66-
block: PackedOption::from(block),
67-
basic_block: PackedOption::from(basic_block),
68-
}
69-
}
70-
71-
fn is_default(&self) -> bool {
72-
self.block.is_none() && self.basic_block.is_none()
73-
}
74-
}
75-
7657
impl FunctionBuilderContext {
7758
/// Creates a FunctionBuilderContext structure. The structure is automatically cleared after
7859
/// each [`FunctionBuilder`](struct.FunctionBuilder.html) completes translating a function.
@@ -158,25 +139,22 @@ impl<'short, 'long> InstBuilderBase<'short> for FuncInstBuilder<'short, 'long> {
158139
.iter()
159140
.filter(|&dest_block| unique.insert(*dest_block))
160141
{
142+
// Call `declare_block_predecessor` instead of `declare_successor` for
143+
// avoiding the borrow checker.
161144
self.builder.func_ctx.ssa.declare_block_predecessor(
162145
*dest_block,
163-
self.builder.position.basic_block.unwrap(),
146+
self.builder.position.unwrap(),
164147
inst,
165148
);
166149
}
167-
self.builder.func_ctx.ssa.declare_block_predecessor(
168-
destination,
169-
self.builder.position.basic_block.unwrap(),
170-
inst,
171-
);
150+
self.builder.declare_successor(destination, inst);
172151
}
173152
}
174153
}
175154
}
155+
176156
if data.opcode().is_terminator() {
177157
self.builder.fill_current_block()
178-
} else if data.opcode().is_branch() {
179-
self.builder.move_to_next_basic_block()
180158
}
181159
(inst, &mut self.builder.func.dfg)
182160
}
@@ -224,7 +202,7 @@ impl<'a> FunctionBuilder<'a> {
224202
func,
225203
srcloc: Default::default(),
226204
func_ctx,
227-
position: Position::default(),
205+
position: Default::default(),
228206
}
229207
}
230208

@@ -236,7 +214,7 @@ impl<'a> FunctionBuilder<'a> {
236214
/// Creates a new `Block` and returns its reference.
237215
pub fn create_block(&mut self) -> Block {
238216
let block = self.func.dfg.make_block();
239-
self.func_ctx.ssa.declare_block_header_block(block);
217+
self.func_ctx.ssa.declare_block(block);
240218
self.func_ctx.blocks[block] = BlockData {
241219
filled: false,
242220
pristine: true,
@@ -255,7 +233,7 @@ impl<'a> FunctionBuilder<'a> {
255233
pub fn switch_to_block(&mut self, block: Block) {
256234
// First we check that the previous block has been filled.
257235
debug_assert!(
258-
self.position.is_default()
236+
self.position.is_none()
259237
|| self.is_unreachable()
260238
|| self.is_pristine()
261239
|| self.is_filled(),
@@ -267,9 +245,8 @@ impl<'a> FunctionBuilder<'a> {
267245
"you cannot switch to a block which is already filled"
268246
);
269247

270-
let basic_block = self.func_ctx.ssa.header_block(block);
271248
// Then we change the cursor position.
272-
self.position = Position::at(block, basic_block);
249+
self.position = PackedOption::from(block);
273250
}
274251

275252
/// Declares that all the predecessors of this block are known.
@@ -278,7 +255,7 @@ impl<'a> FunctionBuilder<'a> {
278255
/// created. Forgetting to call this method on every block will cause inconsistencies in the
279256
/// produced functions.
280257
pub fn seal_block(&mut self, block: Block) {
281-
let side_effects = self.func_ctx.ssa.seal_block_header_block(block, self.func);
258+
let side_effects = self.func_ctx.ssa.seal_block(block, self.func);
282259
self.handle_ssa_side_effects(side_effects);
283260
}
284261

@@ -289,7 +266,7 @@ impl<'a> FunctionBuilder<'a> {
289266
/// function can be used at the end of translating all blocks to ensure
290267
/// that everything is sealed.
291268
pub fn seal_all_blocks(&mut self) {
292-
let side_effects = self.func_ctx.ssa.seal_all_block_header_blocks(self.func);
269+
let side_effects = self.func_ctx.ssa.seal_all_blocks(self.func);
293270
self.handle_ssa_side_effects(side_effects);
294271
}
295272

@@ -310,7 +287,7 @@ impl<'a> FunctionBuilder<'a> {
310287
});
311288
self.func_ctx
312289
.ssa
313-
.use_var(self.func, var, ty, self.position.basic_block.unwrap())
290+
.use_var(self.func, var, ty, self.position.unwrap())
314291
};
315292
self.handle_ssa_side_effects(side_effects);
316293
val
@@ -330,9 +307,7 @@ impl<'a> FunctionBuilder<'a> {
330307
val
331308
);
332309

333-
self.func_ctx
334-
.ssa
335-
.def_var(var, val, self.position.basic_block.unwrap());
310+
self.func_ctx.ssa.def_var(var, val, self.position.unwrap());
336311
}
337312

338313
/// Set label for Value
@@ -395,14 +370,13 @@ impl<'a> FunctionBuilder<'a> {
395370
pub fn ins<'short>(&'short mut self) -> FuncInstBuilder<'short, 'a> {
396371
let block = self
397372
.position
398-
.block
399373
.expect("Please call switch_to_block before inserting instructions");
400374
FuncInstBuilder::new(self, block)
401375
}
402376

403377
/// Make sure that the current block is inserted in the layout.
404378
pub fn ensure_inserted_block(&mut self) {
405-
let block = self.position.block.unwrap();
379+
let block = self.position.unwrap();
406380
if self.func_ctx.blocks[block].pristine {
407381
if !self.func.layout.is_block_inserted(block) {
408382
self.func.layout.append_block(block);
@@ -424,7 +398,7 @@ impl<'a> FunctionBuilder<'a> {
424398
self.ensure_inserted_block();
425399
FuncCursor::new(self.func)
426400
.with_srcloc(self.srcloc)
427-
.at_bottom(self.position.block.unwrap())
401+
.at_bottom(self.position.unwrap())
428402
}
429403

430404
/// Append parameters to the given `Block` corresponding to the function
@@ -495,7 +469,7 @@ impl<'a> FunctionBuilder<'a> {
495469

496470
// Reset srcloc and position to initial states.
497471
self.srcloc = Default::default();
498-
self.position = Position::default();
472+
self.position = Default::default();
499473
}
500474
}
501475

@@ -560,26 +534,26 @@ impl<'a> FunctionBuilder<'a> {
560534
pub fn is_unreachable(&self) -> bool {
561535
let is_entry = match self.func.layout.entry_block() {
562536
None => false,
563-
Some(entry) => self.position.block.unwrap() == entry,
537+
Some(entry) => self.position.unwrap() == entry,
564538
};
565539
!is_entry
566-
&& self.func_ctx.ssa.is_sealed(self.position.block.unwrap())
540+
&& self.func_ctx.ssa.is_sealed(self.position.unwrap())
567541
&& !self
568542
.func_ctx
569543
.ssa
570-
.has_any_predecessors(self.position.block.unwrap())
544+
.has_any_predecessors(self.position.unwrap())
571545
}
572546

573547
/// Returns `true` if and only if no instructions have been added since the last call to
574548
/// `switch_to_block`.
575549
pub fn is_pristine(&self) -> bool {
576-
self.func_ctx.blocks[self.position.block.unwrap()].pristine
550+
self.func_ctx.blocks[self.position.unwrap()].pristine
577551
}
578552

579553
/// Returns `true` if and only if a terminator instruction has been inserted since the
580554
/// last call to `switch_to_block`.
581555
pub fn is_filled(&self) -> bool {
582-
self.func_ctx.blocks[self.position.block.unwrap()].filled
556+
self.func_ctx.blocks[self.position.unwrap()].filled
583557
}
584558

585559
/// Returns a displayable object for the function as it is.
@@ -824,25 +798,15 @@ fn greatest_divisible_power_of_two(size: u64) -> u64 {
824798

825799
// Helper functions
826800
impl<'a> FunctionBuilder<'a> {
827-
fn move_to_next_basic_block(&mut self) {
828-
self.position.basic_block = PackedOption::from(
829-
self.func_ctx
830-
.ssa
831-
.declare_block_body_block(self.position.basic_block.unwrap()),
832-
);
833-
}
834-
835801
/// A Block is 'filled' when a terminator instruction is present.
836802
fn fill_current_block(&mut self) {
837-
self.func_ctx.blocks[self.position.block.unwrap()].filled = true;
803+
self.func_ctx.blocks[self.position.unwrap()].filled = true;
838804
}
839805

840806
fn declare_successor(&mut self, dest_block: Block, jump_inst: Inst) {
841-
self.func_ctx.ssa.declare_block_predecessor(
842-
dest_block,
843-
self.position.basic_block.unwrap(),
844-
jump_inst,
845-
);
807+
self.func_ctx
808+
.ssa
809+
.declare_block_predecessor(dest_block, self.position.unwrap(), jump_inst);
846810
}
847811

848812
fn handle_ssa_side_effects(&mut self, side_effects: SideEffects) {

0 commit comments

Comments
 (0)