mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-25 00:04:11 +00:00
linker/zombies: keep &Instruction
for OpLine
, instead of extracting operands.
This commit is contained in:
parent
a42b7edbea
commit
0160d1dc75
@ -326,12 +326,19 @@ impl<'a> SpanRegenerator<'a> {
|
|||||||
.map(|zombie| zombie.decode())
|
.map(|zombie| zombie.decode())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn src_loc_from_op_line(
|
/// Extract the equivalent `SrcLocDecoration` from a debug instruction that
|
||||||
&mut self,
|
/// specifies some source location (currently only `OpLine` is supported).
|
||||||
file_id: Word,
|
pub fn src_loc_from_debug_inst(&mut self, inst: &Instruction) -> Option<SrcLocDecoration<'a>> {
|
||||||
line: u32,
|
assert_eq!(inst.class.opcode, Op::Line);
|
||||||
col: u32,
|
let (file_id, line, col) = match inst.class.opcode {
|
||||||
) -> Option<SrcLocDecoration<'a>> {
|
Op::Line => (
|
||||||
|
inst.operands[0].unwrap_id_ref(),
|
||||||
|
inst.operands[1].unwrap_literal_int32(),
|
||||||
|
inst.operands[2].unwrap_literal_int32(),
|
||||||
|
),
|
||||||
|
_ => unreachable!("src_loc_from_debug_inst({inst:?})"),
|
||||||
|
};
|
||||||
|
|
||||||
self.spv_debug_info
|
self.spv_debug_info
|
||||||
.get_or_insert_with(|| SpvDebugInfo::collect(self.module))
|
.get_or_insert_with(|| SpvDebugInfo::collect(self.module))
|
||||||
.id_to_op_string
|
.id_to_op_string
|
||||||
|
@ -4,7 +4,7 @@ use super::{get_name, get_names};
|
|||||||
use crate::custom_decorations::{CustomDecoration, SpanRegenerator, ZombieDecoration};
|
use crate::custom_decorations::{CustomDecoration, SpanRegenerator, ZombieDecoration};
|
||||||
use rspirv::dr::{Instruction, Module, Operand};
|
use rspirv::dr::{Instruction, Module, Operand};
|
||||||
use rspirv::spirv::{Op, Word};
|
use rspirv::spirv::{Op, Word};
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||||
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
|
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
@ -13,22 +13,22 @@ use smallvec::SmallVec;
|
|||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct Zombie<'a> {
|
struct Zombie<'a> {
|
||||||
id: Word,
|
id: Word,
|
||||||
kind: &'a ZombieKind,
|
kind: &'a ZombieKind<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ZombieKind {
|
enum ZombieKind<'a> {
|
||||||
/// Definition annotated with `ZombieDecoration`.
|
/// Definition annotated with `ZombieDecoration`.
|
||||||
Leaf,
|
Leaf,
|
||||||
|
|
||||||
/// Transitively zombie'd by using other zombies, from an instruction.
|
/// Transitively zombie'd by using other zombies, from an instruction.
|
||||||
Uses(Vec<ZombieUse>),
|
Uses(Vec<ZombieUse<'a>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ZombieUse {
|
struct ZombieUse<'a> {
|
||||||
used_zombie_id: Word,
|
used_zombie_id: Word,
|
||||||
|
|
||||||
/// Operands of the active `OpLine` at the time of the use, if any.
|
/// Active `OpLine` instruction at the time of the use, if any.
|
||||||
use_file_id_line_col: Option<(Word, u32, u32)>,
|
use_debug_src_loc_inst: Option<&'a Instruction>,
|
||||||
|
|
||||||
origin: UseOrigin,
|
origin: UseOrigin,
|
||||||
}
|
}
|
||||||
@ -39,11 +39,11 @@ enum UseOrigin {
|
|||||||
CallCalleeOperand { caller_func_id: Word },
|
CallCalleeOperand { caller_func_id: Word },
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Zombies {
|
struct Zombies<'a> {
|
||||||
id_to_zombie_kind: FxIndexMap<Word, ZombieKind>,
|
id_to_zombie_kind: FxIndexMap<Word, ZombieKind<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Zombies {
|
impl<'a> Zombies<'a> {
|
||||||
// FIXME(eddyb) rename all the other methods to say `_inst` explicitly.
|
// FIXME(eddyb) rename all the other methods to say `_inst` explicitly.
|
||||||
fn get_zombie_by_id(&self, id: Word) -> Option<Zombie<'_>> {
|
fn get_zombie_by_id(&self, id: Word) -> Option<Zombie<'_>> {
|
||||||
self.id_to_zombie_kind
|
self.id_to_zombie_kind
|
||||||
@ -51,31 +51,25 @@ impl Zombies {
|
|||||||
.map(|kind| Zombie { id, kind })
|
.map(|kind| Zombie { id, kind })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zombies_used_from_inst<'a>(
|
fn zombies_used_from_inst<'b>(
|
||||||
&'a self,
|
&'b self,
|
||||||
inst: &'a Instruction,
|
inst: &'b Instruction,
|
||||||
) -> impl Iterator<Item = Zombie<'a>> + 'a {
|
) -> impl Iterator<Item = Zombie<'b>> + 'b {
|
||||||
inst.result_type
|
inst.result_type
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(inst.operands.iter().filter_map(|op| op.id_ref_any()))
|
.chain(inst.operands.iter().filter_map(|op| op.id_ref_any()))
|
||||||
.filter_map(move |id| self.get_zombie_by_id(id))
|
.filter_map(move |id| self.get_zombie_by_id(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spread(&mut self, module: &Module) -> bool {
|
fn spread(&mut self, module: &'a Module) -> bool {
|
||||||
let mut any = false;
|
let mut any = false;
|
||||||
// globals are easy
|
// globals are easy
|
||||||
{
|
{
|
||||||
let mut file_id_line_col = None;
|
let mut debug_src_loc_inst = None;
|
||||||
for inst in module.global_inst_iter() {
|
for inst in module.global_inst_iter() {
|
||||||
match inst.class.opcode {
|
match inst.class.opcode {
|
||||||
Op::Line => {
|
Op::Line => debug_src_loc_inst = Some(inst),
|
||||||
file_id_line_col = Some((
|
Op::NoLine => debug_src_loc_inst = None,
|
||||||
inst.operands[0].unwrap_id_ref(),
|
|
||||||
inst.operands[1].unwrap_literal_int32(),
|
|
||||||
inst.operands[2].unwrap_literal_int32(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
Op::NoLine => file_id_line_col = None,
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +81,7 @@ impl Zombies {
|
|||||||
.zombies_used_from_inst(inst)
|
.zombies_used_from_inst(inst)
|
||||||
.map(|zombie| ZombieUse {
|
.map(|zombie| ZombieUse {
|
||||||
used_zombie_id: zombie.id,
|
used_zombie_id: zombie.id,
|
||||||
use_file_id_line_col: file_id_line_col,
|
use_debug_src_loc_inst: debug_src_loc_inst,
|
||||||
origin: UseOrigin::GlobalOperandOrResultType,
|
origin: UseOrigin::GlobalOperandOrResultType,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -113,17 +107,12 @@ impl Zombies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut all_zombie_uses_in_func = vec![];
|
let mut all_zombie_uses_in_func = vec![];
|
||||||
let mut file_id_line_col = None;
|
let mut debug_src_loc_inst = None;
|
||||||
for inst in func.all_inst_iter() {
|
for inst in func.all_inst_iter() {
|
||||||
match inst.class.opcode {
|
match inst.class.opcode {
|
||||||
Op::Line => {
|
Op::Line => debug_src_loc_inst = Some(inst),
|
||||||
file_id_line_col = Some((
|
// NOTE(eddyb) each block starts out with cleared debuginfo.
|
||||||
inst.operands[0].unwrap_id_ref(),
|
Op::Label | Op::NoLine => debug_src_loc_inst = None,
|
||||||
inst.operands[1].unwrap_literal_int32(),
|
|
||||||
inst.operands[2].unwrap_literal_int32(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
Op::NoLine => file_id_line_col = None,
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +125,7 @@ impl Zombies {
|
|||||||
.zombies_used_from_inst(inst)
|
.zombies_used_from_inst(inst)
|
||||||
.map(|zombie| ZombieUse {
|
.map(|zombie| ZombieUse {
|
||||||
used_zombie_id: zombie.id,
|
used_zombie_id: zombie.id,
|
||||||
use_file_id_line_col: file_id_line_col,
|
use_debug_src_loc_inst: debug_src_loc_inst,
|
||||||
origin: UseOrigin::IntraFuncOperandOrResultType {
|
origin: UseOrigin::IntraFuncOperandOrResultType {
|
||||||
parent_func_id: func_id,
|
parent_func_id: func_id,
|
||||||
},
|
},
|
||||||
@ -169,7 +158,7 @@ impl Zombies {
|
|||||||
};
|
};
|
||||||
ZombieUse {
|
ZombieUse {
|
||||||
used_zombie_id: zombie.id,
|
used_zombie_id: zombie.id,
|
||||||
use_file_id_line_col: file_id_line_col,
|
use_debug_src_loc_inst: debug_src_loc_inst,
|
||||||
origin,
|
origin,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@ -188,13 +177,13 @@ impl Zombies {
|
|||||||
struct ZombieReporter<'a> {
|
struct ZombieReporter<'a> {
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
module: &'a Module,
|
module: &'a Module,
|
||||||
zombies: &'a Zombies,
|
zombies: &'a Zombies<'a>,
|
||||||
|
|
||||||
id_to_name: Option<FxHashMap<Word, &'a str>>,
|
id_to_name: Option<FxHashMap<Word, &'a str>>,
|
||||||
span_regen: SpanRegenerator<'a>,
|
span_regen: SpanRegenerator<'a>,
|
||||||
}
|
}
|
||||||
impl<'a> ZombieReporter<'a> {
|
impl<'a> ZombieReporter<'a> {
|
||||||
fn new(sess: &'a Session, module: &'a Module, zombies: &'a Zombies) -> Self {
|
fn new(sess: &'a Session, module: &'a Module, zombies: &'a Zombies<'a>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
sess,
|
sess,
|
||||||
module,
|
module,
|
||||||
@ -227,7 +216,7 @@ impl<'a> ZombieReporter<'a> {
|
|||||||
err: &mut DiagnosticBuilder<'a, ErrorGuaranteed>,
|
err: &mut DiagnosticBuilder<'a, ErrorGuaranteed>,
|
||||||
span: Span,
|
span: Span,
|
||||||
zombie: Zombie<'_>,
|
zombie: Zombie<'_>,
|
||||||
zombie_use: &ZombieUse,
|
zombie_use: &ZombieUse<'_>,
|
||||||
) {
|
) {
|
||||||
let mut id_to_name = |id, kind| {
|
let mut id_to_name = |id, kind| {
|
||||||
self.id_to_name
|
self.id_to_name
|
||||||
@ -252,12 +241,9 @@ impl<'a> ZombieReporter<'a> {
|
|||||||
format!("called by {}", id_to_name(caller_func_id, "function"))
|
format!("called by {}", id_to_name(caller_func_id, "function"))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let span = zombie_use
|
let span = zombie_use
|
||||||
.use_file_id_line_col
|
.use_debug_src_loc_inst
|
||||||
.and_then(|(file_id, line, col)| {
|
.and_then(|inst| self.span_regen.src_loc_from_debug_inst(inst))
|
||||||
self.span_regen.src_loc_from_op_line(file_id, line, col)
|
|
||||||
})
|
|
||||||
.and_then(|src_loc| self.span_regen.src_loc_to_rustc(src_loc))
|
.and_then(|src_loc| self.span_regen.src_loc_to_rustc(src_loc))
|
||||||
.unwrap_or(span);
|
.unwrap_or(span);
|
||||||
err.span_note(span, note);
|
err.span_note(span, note);
|
||||||
@ -372,11 +358,17 @@ pub fn report_and_remove_zombies(
|
|||||||
// FIXME(eddyb) this should be unnecessary, either something is unused, and
|
// FIXME(eddyb) this should be unnecessary, either something is unused, and
|
||||||
// it will get DCE'd *anyway*, or it caused an error.
|
// it will get DCE'd *anyway*, or it caused an error.
|
||||||
{
|
{
|
||||||
|
// HACK(eddyb) cannot use the original map because it borrows the `Module`.
|
||||||
|
let all_zombies: FxHashSet<_> = zombies.id_to_zombie_kind.into_keys().collect();
|
||||||
let keep = |inst: &Instruction| {
|
let keep = |inst: &Instruction| {
|
||||||
if let Some(result_id) = inst.result_id {
|
if let Some(result_id) = inst.result_id {
|
||||||
zombies.get_zombie_by_id(result_id).is_none()
|
!all_zombies.contains(&result_id)
|
||||||
} else {
|
} else {
|
||||||
zombies.zombies_used_from_inst(inst).next().is_none()
|
let mut inst_ids = inst
|
||||||
|
.result_type
|
||||||
|
.into_iter()
|
||||||
|
.chain(inst.operands.iter().filter_map(|op| op.id_ref_any()));
|
||||||
|
!inst_ids.any(|id| all_zombies.contains(&id))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
module.capabilities.retain(keep);
|
module.capabilities.retain(keep);
|
||||||
|
Loading…
Reference in New Issue
Block a user