1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
use super::{HandleSet, ModuleMap};
use crate::{Handle, UniqueArena};
pub struct TypeTracer<'a> {
pub types: &'a UniqueArena<crate::Type>,
pub types_used: &'a mut HandleSet<crate::Type>,
}
impl TypeTracer<'_> {
/// Propagate usage through `self.types`, starting with `self.types_used`.
///
/// Treat `self.types_used` as the initial set of "known
/// live" types, and follow through to identify all
/// transitively used types.
pub fn trace_types(&mut self) {
// We don't need recursion or a work list. Because an
// expression may only refer to other expressions that precede
// it in the arena, it suffices to make a single pass over the
// arena from back to front, marking the referents of used
// expressions as used themselves.
for (handle, ty) in self.types.iter().rev() {
// If this type isn't used, it doesn't matter what it uses.
if !self.types_used.contains(handle) {
continue;
}
use crate::TypeInner as Ti;
match ty.inner {
// Types that do not contain handles.
Ti::Scalar { .. }
| Ti::Vector { .. }
| Ti::Matrix { .. }
| Ti::Atomic { .. }
| Ti::ValuePointer { .. }
| Ti::Image { .. }
| Ti::Sampler { .. }
| Ti::AccelerationStructure
| Ti::RayQuery => {}
// Types that do contain handles.
Ti::Pointer { base, space: _ }
| Ti::Array {
base,
size: _,
stride: _,
}
| Ti::BindingArray { base, size: _ } => {
self.types_used.insert(base);
}
Ti::Struct {
ref members,
span: _,
} => {
self.types_used.insert_iter(members.iter().map(|m| m.ty));
}
}
}
}
}
impl ModuleMap {
pub fn adjust_type(&self, ty: &mut crate::Type) {
let adjust = |ty: &mut Handle<crate::Type>| self.types.adjust(ty);
use crate::TypeInner as Ti;
match ty.inner {
// Types that do not contain handles.
Ti::Scalar(_)
| Ti::Vector { .. }
| Ti::Matrix { .. }
| Ti::Atomic(_)
| Ti::ValuePointer { .. }
| Ti::Image { .. }
| Ti::Sampler { .. }
| Ti::AccelerationStructure
| Ti::RayQuery => {}
// Types that do contain handles.
Ti::Pointer {
ref mut base,
space: _,
} => adjust(base),
Ti::Array {
ref mut base,
size: _,
stride: _,
} => adjust(base),
Ti::Struct {
ref mut members,
span: _,
} => {
for member in members {
self.types.adjust(&mut member.ty);
}
}
Ti::BindingArray {
ref mut base,
size: _,
} => {
adjust(base);
}
};
}
}