1mod expressions;
2mod functions;
3mod handle_set_map;
4mod statements;
5mod types;
6
7use crate::arena::HandleSet;
8use crate::{arena, compact::functions::FunctionTracer};
9use handle_set_map::HandleMap;
10
11pub fn compact(module: &mut crate::Module) {
33 let mut module_tracer = ModuleTracer::new(module);
34
35 log::trace!("tracing global variables");
37 {
38 for (_, global) in module.global_variables.iter() {
39 log::trace!("tracing global {:?}", global.name);
40 module_tracer.types_used.insert(global.ty);
41 if let Some(init) = global.init {
42 module_tracer.global_expressions_used.insert(init);
43 }
44 }
45 }
46
47 module_tracer.trace_special_types(&module.special_types);
49
50 for (handle, constant) in module.constants.iter() {
52 if constant.name.is_some() {
53 module_tracer.constants_used.insert(handle);
54 module_tracer.global_expressions_used.insert(constant.init);
55 }
56 }
57
58 for (_, override_) in module.overrides.iter() {
60 module_tracer.types_used.insert(override_.ty);
61 if let Some(init) = override_.init {
62 module_tracer.global_expressions_used.insert(init);
63 }
64 }
65
66 log::trace!("tracing functions");
73 let function_maps: Vec<FunctionMap> = module
74 .functions
75 .iter()
76 .map(|(_, f)| {
77 log::trace!("tracing function {:?}", f.name);
78 let mut function_tracer = module_tracer.as_function(f);
79 function_tracer.trace();
80 FunctionMap::from(function_tracer)
81 })
82 .collect();
83
84 log::trace!("tracing entry points");
86 let entry_point_maps: Vec<FunctionMap> = module
87 .entry_points
88 .iter()
89 .map(|e| {
90 log::trace!("tracing entry point {:?}", e.function.name);
91 let mut used = module_tracer.as_function(&e.function);
92 used.trace();
93 FunctionMap::from(used)
94 })
95 .collect();
96
97 module_tracer.as_const_expression().trace_expressions();
102
103 for (handle, constant) in module.constants.iter() {
107 if module_tracer.constants_used.contains(handle) {
108 module_tracer.types_used.insert(constant.ty);
109 }
110 }
111
112 for (handle, ty) in module.types.iter() {
114 log::trace!("tracing type {:?}, name {:?}", handle, ty.name);
115 if ty.name.is_some() {
116 module_tracer.types_used.insert(handle);
117 }
118 }
119
120 module_tracer.as_type().trace_types();
122
123 let module_map = ModuleMap::from(module_tracer);
128
129 log::trace!("compacting types");
135 let mut new_types = arena::UniqueArena::new();
136 for (old_handle, mut ty, span) in module.types.drain_all() {
137 if let Some(expected_new_handle) = module_map.types.try_adjust(old_handle) {
138 module_map.adjust_type(&mut ty);
139 let actual_new_handle = new_types.insert(ty, span);
140 assert_eq!(actual_new_handle, expected_new_handle);
141 }
142 }
143 module.types = new_types;
144 log::trace!("adjusting special types");
145 module_map.adjust_special_types(&mut module.special_types);
146
147 log::trace!("adjusting constant expressions");
149 module.global_expressions.retain_mut(|handle, expr| {
150 if module_map.global_expressions.used(handle) {
151 module_map.adjust_expression(expr, &module_map.global_expressions);
152 true
153 } else {
154 false
155 }
156 });
157
158 log::trace!("adjusting constants");
160 module.constants.retain_mut(|handle, constant| {
161 if module_map.constants.used(handle) {
162 module_map.types.adjust(&mut constant.ty);
163 module_map.global_expressions.adjust(&mut constant.init);
164 true
165 } else {
166 false
167 }
168 });
169
170 log::trace!("adjusting overrides");
172 for (_, override_) in module.overrides.iter_mut() {
173 module_map.types.adjust(&mut override_.ty);
174 if let Some(init) = override_.init.as_mut() {
175 module_map.global_expressions.adjust(init);
176 }
177 }
178
179 log::trace!("adjusting global variables");
181 for (_, global) in module.global_variables.iter_mut() {
182 log::trace!("adjusting global {:?}", global.name);
183 module_map.types.adjust(&mut global.ty);
184 if let Some(ref mut init) = global.init {
185 module_map.global_expressions.adjust(init);
186 }
187 }
188
189 let mut reused_named_expressions = crate::NamedExpressions::default();
192
193 for ((_, function), map) in module.functions.iter_mut().zip(function_maps.iter()) {
195 log::trace!("compacting function {:?}", function.name);
196 map.compact(function, &module_map, &mut reused_named_expressions);
197 }
198
199 for (entry, map) in module.entry_points.iter_mut().zip(entry_point_maps.iter()) {
201 log::trace!("compacting entry point {:?}", entry.function.name);
202 map.compact(
203 &mut entry.function,
204 &module_map,
205 &mut reused_named_expressions,
206 );
207 }
208}
209
210struct ModuleTracer<'module> {
211 module: &'module crate::Module,
212 types_used: HandleSet<crate::Type>,
213 constants_used: HandleSet<crate::Constant>,
214 global_expressions_used: HandleSet<crate::Expression>,
215}
216
217impl<'module> ModuleTracer<'module> {
218 fn new(module: &'module crate::Module) -> Self {
219 Self {
220 module,
221 types_used: HandleSet::for_arena(&module.types),
222 constants_used: HandleSet::for_arena(&module.constants),
223 global_expressions_used: HandleSet::for_arena(&module.global_expressions),
224 }
225 }
226
227 fn trace_special_types(&mut self, special_types: &crate::SpecialTypes) {
228 let crate::SpecialTypes {
229 ref ray_desc,
230 ref ray_intersection,
231 ref predeclared_types,
232 } = *special_types;
233
234 if let Some(ray_desc) = *ray_desc {
235 self.types_used.insert(ray_desc);
236 }
237 if let Some(ray_intersection) = *ray_intersection {
238 self.types_used.insert(ray_intersection);
239 }
240 for (_, &handle) in predeclared_types {
241 self.types_used.insert(handle);
242 }
243 }
244
245 fn as_type(&mut self) -> types::TypeTracer {
246 types::TypeTracer {
247 types: &self.module.types,
248 types_used: &mut self.types_used,
249 }
250 }
251
252 fn as_const_expression(&mut self) -> expressions::ExpressionTracer {
253 expressions::ExpressionTracer {
254 expressions: &self.module.global_expressions,
255 constants: &self.module.constants,
256 types_used: &mut self.types_used,
257 constants_used: &mut self.constants_used,
258 expressions_used: &mut self.global_expressions_used,
259 global_expressions_used: None,
260 }
261 }
262
263 pub fn as_function<'tracer>(
264 &'tracer mut self,
265 function: &'tracer crate::Function,
266 ) -> FunctionTracer<'tracer> {
267 FunctionTracer {
268 function,
269 constants: &self.module.constants,
270 types_used: &mut self.types_used,
271 constants_used: &mut self.constants_used,
272 global_expressions_used: &mut self.global_expressions_used,
273 expressions_used: HandleSet::for_arena(&function.expressions),
274 }
275 }
276}
277
278struct ModuleMap {
279 types: HandleMap<crate::Type>,
280 constants: HandleMap<crate::Constant>,
281 global_expressions: HandleMap<crate::Expression>,
282}
283
284impl From<ModuleTracer<'_>> for ModuleMap {
285 fn from(used: ModuleTracer) -> Self {
286 ModuleMap {
287 types: HandleMap::from_set(used.types_used),
288 constants: HandleMap::from_set(used.constants_used),
289 global_expressions: HandleMap::from_set(used.global_expressions_used),
290 }
291 }
292}
293
294impl ModuleMap {
295 fn adjust_special_types(&self, special: &mut crate::SpecialTypes) {
296 let crate::SpecialTypes {
297 ref mut ray_desc,
298 ref mut ray_intersection,
299 ref mut predeclared_types,
300 } = *special;
301
302 if let Some(ref mut ray_desc) = *ray_desc {
303 self.types.adjust(ray_desc);
304 }
305 if let Some(ref mut ray_intersection) = *ray_intersection {
306 self.types.adjust(ray_intersection);
307 }
308
309 for handle in predeclared_types.values_mut() {
310 self.types.adjust(handle);
311 }
312 }
313}
314
315struct FunctionMap {
316 expressions: HandleMap<crate::Expression>,
317}
318
319impl From<FunctionTracer<'_>> for FunctionMap {
320 fn from(used: FunctionTracer) -> Self {
321 FunctionMap {
322 expressions: HandleMap::from_set(used.expressions_used),
323 }
324 }
325}