Collect the outgoing block-call arguments for a given edge out of a lowered block.
(
&mut self,
block: BlockIndex,
succ_idx: usize,
buffer: &'a mut SmallVec<[Reg; 16]>,
)
| 1052 | /// Collect the outgoing block-call arguments for a given edge out |
| 1053 | /// of a lowered block. |
| 1054 | fn collect_block_call<'a>( |
| 1055 | &mut self, |
| 1056 | block: BlockIndex, |
| 1057 | succ_idx: usize, |
| 1058 | buffer: &'a mut SmallVec<[Reg; 16]>, |
| 1059 | ) -> (BlockIndex, &'a [Reg]) { |
| 1060 | let block_order = self.vcode.block_order(); |
| 1061 | let (_, succs) = block_order.succ_indices(block); |
| 1062 | let succ = succs[succ_idx]; |
| 1063 | let this_lb = block_order.lowered_order()[block.index()]; |
| 1064 | let succ_lb = block_order.lowered_order()[succ.index()]; |
| 1065 | |
| 1066 | let (branch_inst, succ_idx) = match (this_lb, succ_lb) { |
| 1067 | (_, LoweredBlock::CriticalEdge { .. }) => { |
| 1068 | // The successor is a split-critical-edge block. In this |
| 1069 | // case, this block-call has no arguments, and the |
| 1070 | // arguments go on the critical edge block's unconditional |
| 1071 | // branch instead. |
| 1072 | return (succ, &[]); |
| 1073 | } |
| 1074 | (LoweredBlock::CriticalEdge { pred, succ_idx, .. }, _) => { |
| 1075 | // This is a split-critical-edge block. In this case, our |
| 1076 | // block-call has the arguments that in the CLIF appear in |
| 1077 | // the predecessor's branch to this edge. |
| 1078 | let branch_inst = self.f.layout.last_inst(pred).unwrap(); |
| 1079 | (branch_inst, succ_idx as usize) |
| 1080 | } |
| 1081 | |
| 1082 | (this, _) => { |
| 1083 | let block = this.orig_block().unwrap(); |
| 1084 | // Ordinary block, with an ordinary block as |
| 1085 | // successor. Take the arguments from the branch. |
| 1086 | let branch_inst = self.f.layout.last_inst(block).unwrap(); |
| 1087 | (branch_inst, succ_idx) |
| 1088 | } |
| 1089 | }; |
| 1090 | |
| 1091 | let block_call = self.f.dfg.insts[branch_inst] |
| 1092 | .branch_destination(&self.f.dfg.jump_tables, &self.f.dfg.exception_tables)[succ_idx]; |
| 1093 | for arg in block_call.args(&self.f.dfg.value_lists) { |
| 1094 | match arg { |
| 1095 | BlockArg::Value(arg) => { |
| 1096 | debug_assert!(self.f.dfg.value_is_real(arg)); |
| 1097 | let regs = self.put_value_in_regs(arg); |
| 1098 | buffer.extend_from_slice(regs.regs()); |
| 1099 | } |
| 1100 | BlockArg::TryCallRet(i) => { |
| 1101 | let regs = self.try_call_rets.get(&branch_inst).unwrap()[i as usize] |
| 1102 | .map(|r| r.to_reg()); |
| 1103 | buffer.extend_from_slice(regs.regs()); |
| 1104 | } |
| 1105 | BlockArg::TryCallExn(i) => { |
| 1106 | let reg = |
| 1107 | self.try_call_payloads.get(&branch_inst).unwrap()[i as usize].to_reg(); |
| 1108 | buffer.push(reg); |
| 1109 | } |
| 1110 | } |
| 1111 | } |
no test coverage detected