Skip to content
This repository was archived by the owner on Oct 4, 2022. It is now read-only.

Commit 12cdcc5

Browse files
committed
Add orig_insn_map: mapping from new to original insn indices.
This is needed in the Cranelift client code in order to track source-location mapping for debug info: we need to be able to shuffle the source locations into the new locations after the regalloc has done its instruction-stream editing. The `target_map` result is not quite good enough, because it only provides old --> new mappings at a basic block granularity. This commit also adds "invalid" values to the index types; this is useful to represent "new instruction maps to no old instruction" without the memory-layout waste of an `Option<u32>`.
1 parent 497c2ed commit 12cdcc5

File tree

5 files changed

+75
-17
lines changed

5 files changed

+75
-17
lines changed

lib/src/backtracking.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ impl SpillSlotAllocator {
180180
self.slots.push(LogicalSpillSlot::Unavail);
181181
}
182182
// And now the new slot.
183-
let dflt = RangeFragIx::new(0xFFFF_FFFF); // value is unimportant
183+
let dflt = RangeFragIx::invalid_value();
184184
let tree = AVLTree::<RangeFragIx>::new(dflt);
185185
let res = self.slots.len() as u32;
186186
self.slots.push(LogicalSpillSlot::InUse {
@@ -1108,12 +1108,11 @@ fn cmp_tree_entries_for_CommitmentMapFAST(
11081108
impl CommitmentMapFAST {
11091109
pub fn new() -> Self {
11101110
// The AVL tree constructor needs a default value for the elements. It
1111-
// will never be used. To be on the safe side, give it something that
1112-
// will show as obviously bogus if we ever try to "dereference" any part
1113-
// of it.
1111+
// will never be used. The not-present index value will show as
1112+
// obviously bogus if we ever try to "dereference" any part of it.
11141113
let dflt = FIxAndVLRIx::new(
1115-
RangeFragIx::new(0xFFFF_FFFF),
1116-
Some(VirtualRangeIx::new(0xFFFF_FFFF)),
1114+
RangeFragIx::invalid_value(),
1115+
Some(VirtualRangeIx::invalid_value()),
11171116
);
11181117
Self {
11191118
tree: AVLTree::<FIxAndVLRIx>::new(dflt),
@@ -1740,7 +1739,7 @@ fn frags_are_mergeable(frag1: &RangeFrag, frag2: &RangeFrag) -> bool {
17401739
false
17411740
}
17421741

1743-
const Z_INVALID_BLOCKIX: BlockIx = BlockIx::BlockIx(0xFFFF_FFFF);
1742+
const Z_INVALID_BLOCKIX: BlockIx = BlockIx::invalid_value();
17441743
const Z_INVALID_COUNT: u16 = 0xFFFF;
17451744

17461745
// Try and compress the fragments for each virtual range in `vlr_env`, adding
@@ -2803,7 +2802,7 @@ pub fn alloc_main<F: Function>(
28032802
// ======== BEGIN Create the RegAllocResult ========
28042803

28052804
match final_insns_and_targetmap__or_err {
2806-
Ok((ref final_insns, ref _targetmap)) => {
2805+
Ok((ref final_insns, ..)) => {
28072806
info!(
28082807
"alloc_main: out: VLRs: {} initially, {} processed",
28092808
num_vlrs_initial, num_vlrs_processed
@@ -2829,7 +2828,7 @@ pub fn alloc_main<F: Function>(
28292828
}
28302829
}
28312830

2832-
let (final_insns, target_map) = match final_insns_and_targetmap__or_err {
2831+
let (final_insns, target_map, orig_insn_map) = match final_insns_and_targetmap__or_err {
28332832
Err(e) => {
28342833
info!("alloc_main: fail");
28352834
return Err(e);
@@ -2891,6 +2890,7 @@ pub fn alloc_main<F: Function>(
28912890
let ra_res = RegAllocResult {
28922891
insns: final_insns,
28932892
target_map,
2893+
orig_insn_map,
28942894
clobbered_registers,
28952895
num_spill_slots: spill_slot_allocator.slots.len() as u32,
28962896
block_annotations,

lib/src/data_structures.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -435,61 +435,88 @@ macro_rules! generate_boilerplate {
435435
#[allow(dead_code)]
436436
#[inline(always)]
437437
pub fn new(n: u32) -> Self {
438+
debug_assert!(n != u32::max_value());
438439
Self::$TypeIx(n)
439440
}
440441
#[allow(dead_code)]
441442
#[inline(always)]
442-
pub fn max_value() -> Self {
443-
Self::$TypeIx(u32::max_value())
443+
pub const fn max_value() -> Self {
444+
Self::$TypeIx(u32::max_value() - 1)
444445
}
445446
#[allow(dead_code)]
446447
#[inline(always)]
447-
pub fn min_value() -> Self {
448+
pub const fn min_value() -> Self {
448449
Self::$TypeIx(u32::min_value())
449450
}
450451
#[allow(dead_code)]
451452
#[inline(always)]
453+
pub const fn invalid_value() -> Self {
454+
Self::$TypeIx(u32::max_value())
455+
}
456+
#[allow(dead_code)]
457+
#[inline(always)]
458+
pub fn is_valid(self) -> bool {
459+
self != Self::invalid_value()
460+
}
461+
#[allow(dead_code)]
462+
#[inline(always)]
463+
pub fn is_invalid(self) -> bool {
464+
self == Self::invalid_value()
465+
}
466+
#[allow(dead_code)]
467+
#[inline(always)]
452468
pub fn get(self) -> u32 {
469+
debug_assert!(self.is_valid());
453470
match self {
454471
$TypeIx::$TypeIx(n) => n,
455472
}
456473
}
457474
#[allow(dead_code)]
458475
#[inline(always)]
459476
pub fn plus(self, delta: u32) -> $TypeIx {
477+
debug_assert!(self.is_valid());
460478
$TypeIx::$TypeIx(self.get() + delta)
461479
}
462480
#[allow(dead_code)]
463481
#[inline(always)]
464482
pub fn minus(self, delta: u32) -> $TypeIx {
483+
debug_assert!(self.is_valid());
465484
$TypeIx::$TypeIx(self.get() - delta)
466485
}
467486
#[allow(dead_code)]
468487
pub fn dotdot(&self, last_plus1: $TypeIx) -> Range<$TypeIx> {
488+
debug_assert!(self.is_valid());
469489
let len = (last_plus1.get() - self.get()) as usize;
470490
Range::new(*self, len)
471491
}
472492
}
473493
impl fmt::Debug for $TypeIx {
474494
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
475-
write!(fmt, "{}{}", $PrintingPrefix, &self.get())
495+
if self.is_invalid() {
496+
write!(fmt, "{}<NONE>", $PrintingPrefix)
497+
} else {
498+
write!(fmt, "{}{}", $PrintingPrefix, &self.get())
499+
}
476500
}
477501
}
478502
impl PlusOne for $TypeIx {
479503
#[inline(always)]
480504
fn plus_one(&self) -> Self {
505+
debug_assert!(self.is_valid());
481506
self.plus(1)
482507
}
483508
}
484509
impl PlusN for $TypeIx {
485510
#[inline(always)]
486511
fn plus_n(&self, n: usize) -> Self {
512+
debug_assert!(self.is_valid());
487513
self.plus(n as u32)
488514
}
489515
}
490516
impl Into<u32> for $TypeIx {
491517
#[inline(always)]
492518
fn into(self) -> u32 {
519+
debug_assert!(self.is_valid());
493520
self.get()
494521
}
495522
}

lib/src/inst_stream.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,14 @@ fn map_vregs_to_rregs<F: Function>(
432432
fn add_spills_reloads_and_moves<F: Function>(
433433
func: &mut F,
434434
mut insts_to_add: Vec<InstToInsertAndPoint>,
435-
) -> Result<(Vec<F::Inst>, TypedIxVec<BlockIx, InstIx>), String> {
435+
) -> Result<
436+
(
437+
Vec<F::Inst>,
438+
TypedIxVec<BlockIx, InstIx>,
439+
TypedIxVec<InstIx, InstIx>,
440+
),
441+
String,
442+
> {
436443
// Construct the final code by interleaving the mapped code with the the
437444
// spills, reloads and moves that we have been requested to insert. To do
438445
// that requires having the latter sorted by InstPoint.
@@ -447,6 +454,9 @@ fn add_spills_reloads_and_moves<F: Function>(
447454

448455
let mut insns: Vec<F::Inst> = vec![];
449456
let mut target_map: TypedIxVec<BlockIx, InstIx> = TypedIxVec::new();
457+
let mut orig_insn_map: TypedIxVec<InstIx, InstIx> = TypedIxVec::new();
458+
target_map.reserve(func.blocks().len());
459+
orig_insn_map.reserve(func.insn_indices().len() + insts_to_add.len());
450460

451461
for iix in func.insn_indices() {
452462
// Is `iix` the first instruction in a block? Meaning, are we
@@ -463,15 +473,18 @@ fn add_spills_reloads_and_moves<F: Function>(
463473
&& insts_to_add[curITA].point == InstPoint::new_reload(iix)
464474
{
465475
insns.push(insts_to_add[curITA].inst.construct(func));
476+
orig_insn_map.push(InstIx::invalid_value());
466477
curITA += 1;
467478
}
468479
// Copy the inst at `iix` itself
480+
orig_insn_map.push(iix);
469481
insns.push(func.get_insn(iix).clone());
470482
// And copy the extra insts that are to be placed at the spill point of
471483
// `iix`.
472484
while curITA < insts_to_add.len() && insts_to_add[curITA].point == InstPoint::new_spill(iix)
473485
{
474486
insns.push(insts_to_add[curITA].inst.construct(func));
487+
orig_insn_map.push(InstIx::invalid_value());
475488
curITA += 1;
476489
}
477490

@@ -485,7 +498,7 @@ fn add_spills_reloads_and_moves<F: Function>(
485498
debug_assert!(curITA == insts_to_add.len());
486499
debug_assert!(curB.get() == func.blocks().len() as u32);
487500

488-
Ok((insns, target_map))
501+
Ok((insns, target_map, orig_insn_map))
489502
}
490503

491504
//=============================================================================
@@ -501,7 +514,14 @@ pub(crate) fn edit_inst_stream<F: Function>(
501514
reg_universe: &RealRegUniverse,
502515
has_multiple_blocks_per_frag: bool,
503516
use_checker: bool,
504-
) -> Result<(Vec<F::Inst>, TypedIxVec<BlockIx, InstIx>), RegAllocError> {
517+
) -> Result<
518+
(
519+
Vec<F::Inst>,
520+
TypedIxVec<BlockIx, InstIx>,
521+
TypedIxVec<InstIx, InstIx>,
522+
),
523+
RegAllocError,
524+
> {
505525
map_vregs_to_rregs(
506526
func,
507527
frag_map,

lib/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,16 @@ pub struct RegAllocResult<F: Function> {
313313
/// branch targets appropriately.
314314
pub target_map: TypedIxVec<BlockIx, InstIx>,
315315

316+
/// Full mapping from new instruction indices to original instruction
317+
/// indices. May be needed by the client to, for example, update metadata
318+
/// such as debug/source-location info as the instructions are spliced
319+
/// and reordered.
320+
///
321+
/// Each entry is an `InstIx`, but may be `InstIx::invalid_value()` if the
322+
/// new instruction at this new index was inserted by the allocator
323+
/// (i.e., if it is a load, spill or move instruction).
324+
pub orig_insn_map: TypedIxVec</* new */ InstIx, /* orig */ InstIx>,
325+
316326
/// Which real registers were overwritten? This will contain all real regs
317327
/// that appear as defs or modifies in register slots of the output
318328
/// instruction list. This will only list registers that are available to

lib/src/linear_scan.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3251,7 +3251,7 @@ fn apply_registers<F: Function>(
32513251
use_checker,
32523252
);
32533253

3254-
let (final_insns, target_map) = match final_insns_and_targetmap_or_err {
3254+
let (final_insns, target_map, orig_insn_map) = match final_insns_and_targetmap_or_err {
32553255
Err(e) => return Err(e),
32563256
Ok(pair) => pair,
32573257
};
@@ -3295,6 +3295,7 @@ fn apply_registers<F: Function>(
32953295
let ra_res = RegAllocResult {
32963296
insns: final_insns,
32973297
target_map,
3298+
orig_insn_map,
32983299
clobbered_registers,
32993300
num_spill_slots,
33003301
block_annotations: None,

0 commit comments

Comments
 (0)