Skip to content

Commit 9a8b4fc

Browse files
committed
Revert "linker/inline: fix OpVariable debuginfo collection and insertion."
This reverts commit 355122d.
1 parent f864a26 commit 9a8b4fc

File tree

1 file changed

+52
-150
lines changed
  • crates/rustc_codegen_spirv/src/linker

1 file changed

+52
-150
lines changed

crates/rustc_codegen_spirv/src/linker/inline.rs

Lines changed: 52 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1515
use rustc_errors::ErrorGuaranteed;
1616
use rustc_session::Session;
1717
use smallvec::SmallVec;
18-
use std::mem;
18+
use std::mem::{self, take};
1919

2020
type FunctionMap = FxHashMap<Word, Function>;
2121

@@ -658,13 +658,15 @@ impl Inliner<'_, '_> {
658658
if let Some(call_result_type) = call_result_type {
659659
// Generate the storage space for the return value: Do this *after* the split above,
660660
// because if block_idx=0, inserting a variable here shifts call_index.
661-
let ret_var_inst = Instruction::new(
662-
Op::Variable,
663-
Some(self.ptr_ty(call_result_type)),
664-
Some(return_variable.unwrap()),
665-
vec![Operand::StorageClass(StorageClass::Function)],
661+
insert_opvariables(
662+
&mut caller.blocks[0],
663+
[Instruction::new(
664+
Op::Variable,
665+
Some(self.ptr_ty(call_result_type)),
666+
Some(return_variable.unwrap()),
667+
vec![Operand::StorageClass(StorageClass::Function)],
668+
)],
666669
);
667-
self.insert_opvariables(&mut caller.blocks[0], [ret_var_inst]);
668670
}
669671

670672
// Insert non-entry inlined callee blocks just after the pre-call block.
@@ -710,115 +712,52 @@ impl Inliner<'_, '_> {
710712
// Fuse the inlined callee entry block into the pre-call block.
711713
// This is okay because it's illegal to branch to the first BB in a function.
712714
{
713-
// NOTE(eddyb) `OpExtInst`s have a result ID, even if unused, and
714-
// it has to be unique, so this allocates new IDs as-needed.
715-
let instantiate_debuginfo = |this: &mut Self, inst: &Instruction| {
716-
let mut inst = inst.clone();
717-
if let Some(id) = &mut inst.result_id {
718-
*id = this.id();
719-
}
720-
inst
721-
};
722-
723-
let custom_inst_to_inst = |this: &mut Self, inst: CustomInst<_>| {
724-
Instruction::new(
725-
Op::ExtInst,
726-
Some(this.op_type_void_id),
727-
Some(this.id()),
728-
[
729-
Operand::IdRef(this.custom_ext_inst_set_import),
730-
Operand::LiteralExtInstInteger(inst.op() as u32),
731-
]
732-
.into_iter()
733-
.chain(inst.into_operands())
734-
.collect(),
735-
)
736-
};
737-
738715
// Return the subsequence of `insts` made from `OpVariable`s, and any
739716
// debuginfo instructions (which may apply to them), while removing
740717
// *only* `OpVariable`s from `insts` (and keeping debuginfo in both).
741718
let mut steal_vars = |insts: &mut Vec<Instruction>| {
742-
// HACK(eddyb) this duplicates some code from `get_inlined_blocks`,
743-
// but that will be removed once the inliner is refactored to be
744-
// inside-out instead of outside-in (already finished in a branch).
745-
let mut enclosing_inlined_frames = SmallVec::<[_; 8]>::new();
746-
let mut current_debug_src_loc_inst = None;
747-
let mut vars_and_debuginfo_range = 0..0;
748-
while vars_and_debuginfo_range.end < insts.len() {
749-
let inst = &insts[vars_and_debuginfo_range.end];
750-
match inst.class.opcode {
751-
Op::Line => current_debug_src_loc_inst = Some(inst),
752-
Op::NoLine => current_debug_src_loc_inst = None,
753-
Op::ExtInst
754-
if inst.operands[0].unwrap_id_ref()
755-
== self.custom_ext_inst_set_import =>
756-
{
757-
match CustomOp::decode_from_ext_inst(inst) {
758-
CustomOp::SetDebugSrcLoc => current_debug_src_loc_inst = Some(inst),
759-
CustomOp::ClearDebugSrcLoc => current_debug_src_loc_inst = None,
760-
CustomOp::PushInlinedCallFrame => {
761-
enclosing_inlined_frames
762-
.push((current_debug_src_loc_inst.take(), inst));
763-
}
764-
CustomOp::PopInlinedCallFrame => {
765-
if let Some((callsite_debug_src_loc_inst, _)) =
766-
enclosing_inlined_frames.pop()
767-
{
768-
current_debug_src_loc_inst = callsite_debug_src_loc_inst;
769-
}
770-
}
771-
CustomOp::Abort => break,
772-
}
719+
let mut vars_and_debuginfo = vec![];
720+
insts.retain_mut(|inst| {
721+
let is_debuginfo = match inst.class.opcode {
722+
Op::Line | Op::NoLine => true,
723+
Op::ExtInst => {
724+
inst.operands[0].unwrap_id_ref() == self.custom_ext_inst_set_import
725+
&& CustomOp::decode_from_ext_inst(inst).is_debuginfo()
773726
}
774-
Op::Variable => {}
775-
_ => break,
727+
_ => false,
728+
};
729+
if is_debuginfo {
730+
// NOTE(eddyb) `OpExtInst`s have a result ID,
731+
// even if unused, and it has to be unique.
732+
let mut inst = inst.clone();
733+
if let Some(id) = &mut inst.result_id {
734+
*id = self.id();
735+
}
736+
vars_and_debuginfo.push(inst);
737+
true
738+
} else if inst.class.opcode == Op::Variable {
739+
// HACK(eddyb) we're removing this `Instruction` from
740+
// `inst`, so it doesn't really matter what we use here.
741+
vars_and_debuginfo.push(mem::replace(
742+
inst,
743+
Instruction::new(Op::Nop, None, None, vec![]),
744+
));
745+
false
746+
} else {
747+
true
776748
}
777-
vars_and_debuginfo_range.end += 1;
778-
}
779-
780-
// `vars_and_debuginfo_range.end` indicates where `OpVariable`s
781-
// end and other instructions start (module debuginfo), but to
782-
// split the block in two, both sides of the "cut" need "repair":
783-
// - the variables are missing "inlined call frames" pops, that
784-
// may happen later in the block, and have to be synthesized
785-
// - the non-variables are missing "inlined call frames" pushes,
786-
// that must be recreated to avoid ending up with dangling pops
787-
//
788-
// FIXME(eddyb) this only collects to avoid borrow conflicts,
789-
// between e.g. `enclosing_inlined_frames` and mutating `insts`,
790-
// but also between different uses of `self`.
791-
let all_pops_after_vars: SmallVec<[_; 8]> = enclosing_inlined_frames
792-
.iter()
793-
.map(|_| custom_inst_to_inst(self, CustomInst::PopInlinedCallFrame))
794-
.collect();
795-
let all_repushes_before_non_vars: SmallVec<[_; 8]> =
796-
(enclosing_inlined_frames.into_iter().flat_map(
797-
|(callsite_debug_src_loc_inst, push_inlined_call_frame_inst)| {
798-
(callsite_debug_src_loc_inst.into_iter())
799-
.chain([push_inlined_call_frame_inst])
800-
},
801-
))
802-
.chain(current_debug_src_loc_inst)
803-
.map(|inst| instantiate_debuginfo(self, inst))
804-
.collect();
805-
806-
let vars_and_debuginfo =
807-
insts.splice(vars_and_debuginfo_range, all_repushes_before_non_vars);
808-
let repaired_vars_and_debuginfo = vars_and_debuginfo.chain(all_pops_after_vars);
809-
810-
// FIXME(eddyb) collecting shouldn't be necessary but this is
811-
// nested in a closure, and `splice` borrows the original `Vec`.
812-
repaired_vars_and_debuginfo.collect::<SmallVec<[_; 8]>>()
749+
});
750+
vars_and_debuginfo
813751
};
814752

815753
let [mut inlined_callee_entry_block]: [_; 1] =
816754
inlined_callee_blocks.try_into().unwrap();
817755

818756
// Move the `OpVariable`s of the callee to the caller.
819-
let callee_vars_and_debuginfo =
820-
steal_vars(&mut inlined_callee_entry_block.instructions);
821-
self.insert_opvariables(&mut caller.blocks[0], callee_vars_and_debuginfo);
757+
insert_opvariables(
758+
&mut caller.blocks[0],
759+
steal_vars(&mut inlined_callee_entry_block.instructions),
760+
);
822761

823762
caller.blocks[pre_call_block_idx]
824763
.instructions
@@ -1051,52 +990,15 @@ impl Inliner<'_, '_> {
1051990
caller_restore_debuginfo_after_call,
1052991
)
1053992
}
993+
}
1054994

1055-
fn insert_opvariables(&self, block: &mut Block, insts: impl IntoIterator<Item = Instruction>) {
1056-
// HACK(eddyb) this isn't as efficient as it could be in theory, but it's
1057-
// very important to make sure sure to never insert new instructions in
1058-
// the middle of debuginfo (as it would be affected by it).
1059-
let mut inlined_frames_depth = 0usize;
1060-
let mut outermost_has_debug_src_loc = false;
1061-
let mut last_debugless_var_insertion_point_candidate = None;
1062-
for (i, inst) in block.instructions.iter().enumerate() {
1063-
last_debugless_var_insertion_point_candidate =
1064-
(inlined_frames_depth == 0 && !outermost_has_debug_src_loc).then_some(i);
1065-
1066-
let changed_has_debug_src_loc = match inst.class.opcode {
1067-
Op::Line => true,
1068-
Op::NoLine => false,
1069-
Op::ExtInst
1070-
if inst.operands[0].unwrap_id_ref() == self.custom_ext_inst_set_import =>
1071-
{
1072-
match CustomOp::decode_from_ext_inst(inst) {
1073-
CustomOp::SetDebugSrcLoc => true,
1074-
CustomOp::ClearDebugSrcLoc => false,
1075-
CustomOp::PushInlinedCallFrame => {
1076-
inlined_frames_depth += 1;
1077-
continue;
1078-
}
1079-
CustomOp::PopInlinedCallFrame => {
1080-
inlined_frames_depth = inlined_frames_depth.saturating_sub(1);
1081-
continue;
1082-
}
1083-
CustomOp::Abort => break,
1084-
}
1085-
}
1086-
Op::Variable => continue,
1087-
_ => break,
1088-
};
1089-
1090-
if inlined_frames_depth == 0 {
1091-
outermost_has_debug_src_loc = changed_has_debug_src_loc;
1092-
}
1093-
}
1094-
1095-
// HACK(eddyb) fallback to inserting at the start, which should be correct.
1096-
// FIXME(eddyb) some level of debuginfo repair could prevent needing this.
1097-
let i = last_debugless_var_insertion_point_candidate.unwrap_or(0);
1098-
block.instructions.splice(i..i, insts);
1099-
}
995+
fn insert_opvariables(block: &mut Block, insts: impl IntoIterator<Item = Instruction>) {
996+
let first_non_variable = block
997+
.instructions
998+
.iter()
999+
.position(|inst| inst.class.opcode != Op::Variable);
1000+
let i = first_non_variable.unwrap_or(block.instructions.len());
1001+
block.instructions.splice(i..i, insts);
11001002
}
11011003

11021004
fn fuse_trivial_branches(function: &mut Function) {
@@ -1131,7 +1033,7 @@ fn fuse_trivial_branches(function: &mut Function) {
11311033
};
11321034
let pred_insts = &function.blocks[pred].instructions;
11331035
if pred_insts.last().unwrap().class.opcode == Op::Branch {
1134-
let mut dest_insts = mem::take(&mut function.blocks[dest_block].instructions);
1036+
let mut dest_insts = take(&mut function.blocks[dest_block].instructions);
11351037
let pred_insts = &mut function.blocks[pred].instructions;
11361038
pred_insts.pop(); // pop the branch
11371039
pred_insts.append(&mut dest_insts);

0 commit comments

Comments
 (0)