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