(&mut self, vregs: &VRegAllocator<I>)
| 511 | } |
| 512 | |
| 513 | fn collect_operands(&mut self, vregs: &VRegAllocator<I>) { |
| 514 | let allocatable = PRegSet::from(self.vcode.abi.machine_env()); |
| 515 | for (i, insn) in self.vcode.insts.iter_mut().enumerate() { |
| 516 | // Push operands from the instruction onto the operand list. |
| 517 | // |
| 518 | // We rename through the vreg alias table as we collect |
| 519 | // the operands. This is better than a separate post-pass |
| 520 | // over operands, because it has more cache locality: |
| 521 | // operands only need to pass through L1 once. This is |
| 522 | // also better than renaming instructions' |
| 523 | // operands/registers while lowering, because here we only |
| 524 | // need to do the `match` over the instruction to visit |
| 525 | // its register fields (which is slow, branchy code) once. |
| 526 | |
| 527 | let mut op_collector = |
| 528 | OperandCollector::new(&mut self.vcode.operands, allocatable, |vreg| { |
| 529 | vregs.resolve_vreg_alias(vreg) |
| 530 | }); |
| 531 | insn.get_operands(&mut op_collector); |
| 532 | let (ops, clobbers) = op_collector.finish(); |
| 533 | self.vcode.operand_ranges.push_end(ops); |
| 534 | |
| 535 | if clobbers != PRegSet::default() { |
| 536 | self.vcode.clobbers.insert(InsnIndex::new(i), clobbers); |
| 537 | } |
| 538 | |
| 539 | if let Some((dst, src)) = insn.is_move() { |
| 540 | // We should never see non-virtual registers present in move |
| 541 | // instructions. |
| 542 | assert!( |
| 543 | src.is_virtual(), |
| 544 | "the real register {src:?} was used as the source of a move instruction" |
| 545 | ); |
| 546 | assert!( |
| 547 | dst.to_reg().is_virtual(), |
| 548 | "the real register {:?} was used as the destination of a move instruction", |
| 549 | dst.to_reg() |
| 550 | ); |
| 551 | } |
| 552 | } |
| 553 | |
| 554 | // Translate blockparam args via the vreg aliases table as well. |
| 555 | for arg in &mut self.vcode.branch_block_args { |
| 556 | let new_arg = vregs.resolve_vreg_alias(*arg); |
| 557 | trace!("operandcollector: block arg {:?} -> {:?}", arg, new_arg); |
| 558 | *arg = new_arg; |
| 559 | } |
| 560 | } |
| 561 | |
| 562 | /// Build the final VCode. |
| 563 | pub fn build(mut self, mut vregs: VRegAllocator<I>) -> VCode<I> { |
no test coverage detected