HACK(eddyb) the second and third return values are additional debuginfo instructions that need to be inserted just before/after the callsite.
(
&mut self,
callee: &Function,
call_debug_insts: impl Iterator<Item = &'a Instruction>,
return_variable: Option<Word>,
return_jump: Word,
)
| 791 | // HACK(eddyb) the second and third return values are additional debuginfo |
| 792 | // instructions that need to be inserted just before/after the callsite. |
| 793 | fn get_inlined_blocks<'a>( |
| 794 | &mut self, |
| 795 | callee: &Function, |
| 796 | call_debug_insts: impl Iterator<Item = &'a Instruction>, |
| 797 | return_variable: Option<Word>, |
| 798 | return_jump: Word, |
| 799 | ) -> ( |
| 800 | Vec<Block>, |
| 801 | SmallVec<[Instruction; 8]>, |
| 802 | SmallVec<[Instruction; 8]>, |
| 803 | ) { |
| 804 | let Self { |
| 805 | custom_ext_inst_set_import, |
| 806 | op_type_void_id, |
| 807 | .. |
| 808 | } = *self; |
| 809 | |
| 810 | // HACK(eddyb) this is terrible, but we have to deal with it becasue of |
| 811 | // how this inliner is outside-in, instead of inside-out, meaning that |
| 812 | // context builds up "outside" of the callee blocks, inside the caller. |
| 813 | let mut enclosing_inlined_frames = SmallVec::<[_; 8]>::new(); |
| 814 | let mut current_debug_src_loc_inst = None; |
| 815 | for inst in call_debug_insts { |
| 816 | match inst.class.opcode { |
| 817 | Op::Line => current_debug_src_loc_inst = Some(inst), |
| 818 | Op::NoLine => current_debug_src_loc_inst = None, |
| 819 | Op::ExtInst |
| 820 | if inst.operands[0].unwrap_id_ref() == self.custom_ext_inst_set_import => |
| 821 | { |
| 822 | match CustomOp::decode_from_ext_inst(inst) { |
| 823 | CustomOp::SetDebugSrcLoc => current_debug_src_loc_inst = Some(inst), |
| 824 | CustomOp::ClearDebugSrcLoc => current_debug_src_loc_inst = None, |
| 825 | CustomOp::PushInlinedCallFrame => { |
| 826 | enclosing_inlined_frames |
| 827 | .push((current_debug_src_loc_inst.take(), inst)); |
| 828 | } |
| 829 | CustomOp::PopInlinedCallFrame => { |
| 830 | if let Some((callsite_debug_src_loc_inst, _)) = |
| 831 | enclosing_inlined_frames.pop() |
| 832 | { |
| 833 | current_debug_src_loc_inst = callsite_debug_src_loc_inst; |
| 834 | } |
| 835 | } |
| 836 | CustomOp::Abort => {} |
| 837 | } |
| 838 | } |
| 839 | _ => {} |
| 840 | } |
| 841 | } |
| 842 | |
| 843 | // Prepare the debuginfo insts to prepend/append to every block. |
| 844 | // FIXME(eddyb) this could be more efficient if we only used one pair of |
| 845 | // `{Push,Pop}InlinedCallFrame` for the whole inlined callee, but there |
| 846 | // is no way to hint the SPIR-T CFG (re)structurizer that it should keep |
| 847 | // the entire callee in one region - a SPIR-T inliner wouldn't have this |
| 848 | // issue, as it would require a fully structured callee. |
| 849 | let callee_name = self |
| 850 | .id_to_name |