Skip to content

Commit 3d4bd05

Browse files
authored
Cranelift: Split out computation of where to move a cursor from actually updating its position (#11464)
This allows users to query what the next/prev position in their traversal would be without actually changing the cursor's current location. Otherwise, they would have to do something like ```rust cursor.next_block(); let next_pos = cursor.current_position(); cursor.prev_block(); ``` These new methods aren't used anywhere yet, other than the implementation of the cursor-position-updating methods they were split out from, but it seems useful to expose. I almost needed it for some inlining stuff, but ultimately took a slightly different approach.
1 parent f46b92a commit 3d4bd05

File tree

1 file changed

+92
-58
lines changed

1 file changed

+92
-58
lines changed

cranelift/codegen/src/cursor.rs

Lines changed: 92 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,34 @@ pub trait Cursor {
299299
self.set_position(CursorPosition::After(block));
300300
}
301301

302+
/// Get the next position that a forwards traversal will move to, but do not
303+
/// move this cursor.
304+
fn next_position(&self) -> CursorPosition {
305+
self.next_inst_position()
306+
.unwrap_or_else(|| self.next_block_position())
307+
}
308+
309+
/// Get the next position that a backwards traversal will move to, but do
310+
/// not move this cursor.
311+
fn prev_position(&self) -> CursorPosition {
312+
self.prev_inst_position()
313+
.unwrap_or_else(|| self.prev_block_position())
314+
}
315+
316+
/// Get the position that a `cursor.next_block()` call would move this
317+
/// cursor to, but do not update this cursor's position.
318+
fn next_block_position(&self) -> CursorPosition {
319+
let next = if let Some(block) = self.current_block() {
320+
self.layout().next_block(block)
321+
} else {
322+
self.layout().entry_block()
323+
};
324+
match next {
325+
Some(block) => CursorPosition::Before(block),
326+
None => CursorPosition::Nowhere,
327+
}
328+
}
329+
302330
/// Go to the top of the next block in layout order and return it.
303331
///
304332
/// - If the cursor wasn't pointing at anything, go to the top of the first block in the
@@ -320,16 +348,23 @@ pub trait Cursor {
320348
/// }
321349
/// ```
322350
fn next_block(&mut self) -> Option<ir::Block> {
323-
let next = if let Some(block) = self.current_block() {
324-
self.layout().next_block(block)
351+
let pos = self.next_block_position();
352+
self.set_position(pos);
353+
self.current_block()
354+
}
355+
356+
/// Get the position that a `cursor.prev_block()` call would move this
357+
/// cursor to, but do not update this cursor's position.
358+
fn prev_block_position(&self) -> CursorPosition {
359+
let prev = if let Some(block) = self.current_block() {
360+
self.layout().prev_block(block)
325361
} else {
326-
self.layout().entry_block()
362+
self.layout().last_block()
327363
};
328-
self.set_position(match next {
329-
Some(block) => CursorPosition::Before(block),
364+
match prev {
365+
Some(block) => CursorPosition::After(block),
330366
None => CursorPosition::Nowhere,
331-
});
332-
next
367+
}
333368
}
334369

335370
/// Go to the bottom of the previous block in layout order and return it.
@@ -353,16 +388,36 @@ pub trait Cursor {
353388
/// }
354389
/// ```
355390
fn prev_block(&mut self) -> Option<ir::Block> {
356-
let prev = if let Some(block) = self.current_block() {
357-
self.layout().prev_block(block)
358-
} else {
359-
self.layout().last_block()
360-
};
361-
self.set_position(match prev {
362-
Some(block) => CursorPosition::After(block),
363-
None => CursorPosition::Nowhere,
364-
});
365-
prev
391+
let pos = self.prev_block_position();
392+
self.set_position(pos);
393+
self.current_block()
394+
}
395+
396+
/// Get the position that a `cursor.next_inst()` call would move this cursor
397+
/// to, but do not update this cursor's position.
398+
fn next_inst_position(&self) -> Option<CursorPosition> {
399+
use self::CursorPosition::*;
400+
match self.position() {
401+
Nowhere | After(..) => None,
402+
At(inst) => {
403+
if let Some(next) = self.layout().next_inst(inst) {
404+
Some(At(next))
405+
} else {
406+
Some(After(
407+
self.layout()
408+
.inst_block(inst)
409+
.expect("current instruction removed?"),
410+
))
411+
}
412+
}
413+
Before(block) => {
414+
if let Some(next) = self.layout().first_inst(block) {
415+
Some(At(next))
416+
} else {
417+
Some(After(block))
418+
}
419+
}
420+
}
366421
}
367422

368423
/// Move to the next instruction in the same block and return it.
@@ -406,30 +461,33 @@ pub trait Cursor {
406461
/// }
407462
/// ```
408463
fn next_inst(&mut self) -> Option<ir::Inst> {
464+
let pos = self.next_inst_position()?;
465+
self.set_position(pos);
466+
self.current_inst()
467+
}
468+
469+
/// Get the position that a `cursor.prev_inst()` call would move this cursor
470+
/// to, but do not update this cursor's position.
471+
fn prev_inst_position(&self) -> Option<CursorPosition> {
409472
use self::CursorPosition::*;
410473
match self.position() {
411-
Nowhere | After(..) => None,
474+
Nowhere | Before(..) => None,
412475
At(inst) => {
413-
if let Some(next) = self.layout().next_inst(inst) {
414-
self.set_position(At(next));
415-
Some(next)
476+
if let Some(prev) = self.layout().prev_inst(inst) {
477+
Some(At(prev))
416478
} else {
417-
let pos = After(
479+
Some(Before(
418480
self.layout()
419481
.inst_block(inst)
420482
.expect("current instruction removed?"),
421-
);
422-
self.set_position(pos);
423-
None
483+
))
424484
}
425485
}
426-
Before(block) => {
427-
if let Some(next) = self.layout().first_inst(block) {
428-
self.set_position(At(next));
429-
Some(next)
486+
After(block) => {
487+
if let Some(prev) = self.layout().last_inst(block) {
488+
Some(At(prev))
430489
} else {
431-
self.set_position(After(block));
432-
None
490+
Some(Before(block))
433491
}
434492
}
435493
}
@@ -460,33 +518,9 @@ pub trait Cursor {
460518
/// }
461519
/// ```
462520
fn prev_inst(&mut self) -> Option<ir::Inst> {
463-
use self::CursorPosition::*;
464-
match self.position() {
465-
Nowhere | Before(..) => None,
466-
At(inst) => {
467-
if let Some(prev) = self.layout().prev_inst(inst) {
468-
self.set_position(At(prev));
469-
Some(prev)
470-
} else {
471-
let pos = Before(
472-
self.layout()
473-
.inst_block(inst)
474-
.expect("current instruction removed?"),
475-
);
476-
self.set_position(pos);
477-
None
478-
}
479-
}
480-
After(block) => {
481-
if let Some(prev) = self.layout().last_inst(block) {
482-
self.set_position(At(prev));
483-
Some(prev)
484-
} else {
485-
self.set_position(Before(block));
486-
None
487-
}
488-
}
489-
}
521+
let pos = self.prev_inst_position()?;
522+
self.set_position(pos);
523+
self.current_inst()
490524
}
491525

492526
/// Insert an instruction at the current position.

0 commit comments

Comments
 (0)