Called once, when a build in Backward order is complete, to perform the overall reversal (into final forward order) and finalize metadata accordingly.
(&mut self, vregs: &VRegAllocator<I>)
| 456 | /// perform the overall reversal (into final forward order) and |
| 457 | /// finalize metadata accordingly. |
| 458 | fn reverse_and_finalize(&mut self, vregs: &VRegAllocator<I>) { |
| 459 | let n_insts = self.vcode.insts.len(); |
| 460 | if n_insts == 0 { |
| 461 | return; |
| 462 | } |
| 463 | |
| 464 | // Reverse the per-block and per-inst sequences. |
| 465 | self.vcode.block_ranges.reverse_index(); |
| 466 | self.vcode.block_ranges.reverse_target(n_insts); |
| 467 | // block_params_range is indexed by block (and blocks were |
| 468 | // traversed in reverse) so we reverse it; but block-param |
| 469 | // sequences in the concatenated vec can remain in reverse |
| 470 | // order (it is effectively an arena of arbitrarily-placed |
| 471 | // referenced sequences). |
| 472 | self.vcode.block_params_range.reverse_index(); |
| 473 | // Likewise, we reverse block_succ_range, but the block_succ |
| 474 | // concatenated array can remain as-is. |
| 475 | self.vcode.block_succ_range.reverse_index(); |
| 476 | self.vcode.insts.reverse(); |
| 477 | self.vcode.srclocs.reverse(); |
| 478 | // Likewise, branch_block_arg_succ_range is indexed by block |
| 479 | // so must be reversed. |
| 480 | self.vcode.branch_block_arg_succ_range.reverse_index(); |
| 481 | |
| 482 | // To translate an instruction index *endpoint* in reversed |
| 483 | // order to forward order, compute `n_insts - i`. |
| 484 | // |
| 485 | // Why not `n_insts - 1 - i`? That would be correct to |
| 486 | // translate an individual instruction index (for ten insts 0 |
| 487 | // to 9 inclusive, inst 0 becomes 9, and inst 9 becomes |
| 488 | // 0). But for the usual inclusive-start, exclusive-end range |
| 489 | // idiom, inclusive starts become exclusive ends and |
| 490 | // vice-versa, so e.g. an (inclusive) start of 0 becomes an |
| 491 | // (exclusive) end of 10. |
| 492 | let translate = |inst: InsnIndex| InsnIndex::new(n_insts - inst.index()); |
| 493 | |
| 494 | // Generate debug-value labels based on per-label maps. |
| 495 | for (label, tuples) in &self.debug_info { |
| 496 | for &(start, end, vreg) in tuples { |
| 497 | let vreg = vregs.resolve_vreg_alias(vreg); |
| 498 | let fwd_start = translate(end); |
| 499 | let fwd_end = translate(start); |
| 500 | self.vcode |
| 501 | .debug_value_labels |
| 502 | .push((vreg, fwd_start, fwd_end, label.as_u32())); |
| 503 | } |
| 504 | } |
| 505 | |
| 506 | // Now sort debug value labels by VReg, as required |
| 507 | // by regalloc2. |
| 508 | self.vcode |
| 509 | .debug_value_labels |
| 510 | .sort_unstable_by_key(|(vreg, _, _, _)| *vreg); |
| 511 | } |
| 512 | |
| 513 | fn collect_operands(&mut self, vregs: &VRegAllocator<I>) { |
| 514 | let allocatable = PRegSet::from(self.vcode.abi.machine_env()); |
no test coverage detected