Expand every "generic" global/function, and `OpName`/decorations applied to them, to their respective full set of instances, treating the original "generic" definition and its inferred `Replacements` as a template.
(mut self)
| 2298 | /// to them, to their respective full set of instances, treating the original |
| 2299 | /// "generic" definition and its inferred `Replacements` as a template. |
| 2300 | fn expand_module(mut self) -> Module { |
| 2301 | // From here on out we assume all instances are known, so ensure there |
| 2302 | // aren't any left unpropagated. |
| 2303 | self.propagate_instances(); |
| 2304 | |
| 2305 | // HACK(eddyb) steal `Vec`s so that we can still call methods on `self` below. |
| 2306 | let module = self.builder.module_mut(); |
| 2307 | let mut entry_points = mem::take(&mut module.entry_points); |
| 2308 | let debug_names = mem::take(&mut module.debug_names); |
| 2309 | let annotations = mem::take(&mut module.annotations); |
| 2310 | let types_global_values = mem::take(&mut module.types_global_values); |
| 2311 | let functions = mem::take(&mut module.functions); |
| 2312 | |
| 2313 | // Adjust `OpEntryPoint ...` in-place to use the new IDs for *Interface* |
| 2314 | // module-scoped `OpVariable`s (which should each have one instance). |
| 2315 | for inst in &mut entry_points { |
| 2316 | let func_id = inst.operands[1].unwrap_id_ref(); |
| 2317 | assert!( |
| 2318 | !self.specializer.generics.contains_key(&func_id), |
| 2319 | "entry-point %{func_id} shouldn't be \"generic\"" |
| 2320 | ); |
| 2321 | |
| 2322 | for interface_operand in &mut inst.operands[3..] { |
| 2323 | let interface_id = interface_operand.unwrap_id_ref(); |
| 2324 | let mut instances = self.all_instances_of(interface_id); |
| 2325 | match (instances.next(), instances.next()) { |
| 2326 | (None, _) => unreachable!( |
| 2327 | "entry-point %{} has overly-\"generic\" \ |
| 2328 | interface variable %{}, with no instances", |
| 2329 | func_id, interface_id |
| 2330 | ), |
| 2331 | (Some(_), Some(_)) => unreachable!( |
| 2332 | "entry-point %{} has overly-\"generic\" \ |
| 2333 | interface variable %{}, with too many instances: {:?}", |
| 2334 | func_id, |
| 2335 | interface_id, |
| 2336 | FmtBy(|f| f |
| 2337 | .debug_list() |
| 2338 | .entries(self.all_instances_of(interface_id).map( |
| 2339 | |(instance, _)| FmtBy(move |f| write!( |
| 2340 | f, |
| 2341 | "{}", |
| 2342 | instance.display(|generic_args| generic_args.iter().copied()) |
| 2343 | )) |
| 2344 | )) |
| 2345 | .finish()) |
| 2346 | ), |
| 2347 | (Some((_, &instance_id)), None) => { |
| 2348 | *interface_operand = Operand::IdRef(instance_id); |
| 2349 | } |
| 2350 | } |
| 2351 | } |
| 2352 | } |
| 2353 | |
| 2354 | // FIXME(eddyb) bucket `instances` into global vs function, and count |
| 2355 | // annotations separately, so that we can know exact capacities below. |
| 2356 | |
| 2357 | // Expand `Op* %target ...` when `target` is "generic". |
no test coverage detected