1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | |
5 | use std::collections::HashMap; |
6 | use std::path::PathBuf; |
7 | |
8 | use crate::bindgen::bindings::Bindings; |
9 | use crate::bindgen::config::{Config, Language, SortKey}; |
10 | use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; |
11 | use crate::bindgen::dependencies::Dependencies; |
12 | use crate::bindgen::error::Error; |
13 | use crate::bindgen::ir::{Constant, Enum, Function, Item, ItemContainer, ItemMap}; |
14 | use crate::bindgen::ir::{OpaqueItem, Path, Static, Struct, Typedef, Union}; |
15 | use crate::bindgen::monomorph::Monomorphs; |
16 | use crate::bindgen::ItemType; |
17 | |
18 | #[derive (Debug, Clone)] |
19 | pub struct Library { |
20 | config: Config, |
21 | constants: ItemMap<Constant>, |
22 | globals: ItemMap<Static>, |
23 | enums: ItemMap<Enum>, |
24 | structs: ItemMap<Struct>, |
25 | unions: ItemMap<Union>, |
26 | opaque_items: ItemMap<OpaqueItem>, |
27 | typedefs: ItemMap<Typedef>, |
28 | functions: Vec<Function>, |
29 | source_files: Vec<PathBuf>, |
30 | } |
31 | |
32 | impl Library { |
33 | #[allow (clippy::too_many_arguments)] |
34 | pub fn new( |
35 | config: Config, |
36 | constants: ItemMap<Constant>, |
37 | globals: ItemMap<Static>, |
38 | enums: ItemMap<Enum>, |
39 | structs: ItemMap<Struct>, |
40 | unions: ItemMap<Union>, |
41 | opaque_items: ItemMap<OpaqueItem>, |
42 | typedefs: ItemMap<Typedef>, |
43 | functions: Vec<Function>, |
44 | source_files: Vec<PathBuf>, |
45 | ) -> Library { |
46 | Library { |
47 | config, |
48 | constants, |
49 | globals, |
50 | enums, |
51 | structs, |
52 | unions, |
53 | opaque_items, |
54 | typedefs, |
55 | functions, |
56 | source_files, |
57 | } |
58 | } |
59 | |
60 | pub fn generate(mut self) -> Result<Bindings, Error> { |
61 | self.transfer_annotations(); |
62 | self.simplify_standard_types(); |
63 | |
64 | match self.config.function.sort_by.unwrap_or(self.config.sort_by) { |
65 | SortKey::Name => self.functions.sort_by(|x, y| x.path.cmp(&y.path)), |
66 | SortKey::None => { /* keep input order */ } |
67 | } |
68 | |
69 | if self.config.language != Language::Cxx { |
70 | self.instantiate_monomorphs(); |
71 | } |
72 | self.remove_excluded(); |
73 | if self.config.language == Language::C { |
74 | self.resolve_declaration_types(); |
75 | } |
76 | |
77 | self.rename_items(); |
78 | |
79 | let mut dependencies = Dependencies::new(); |
80 | |
81 | for function in &self.functions { |
82 | function.add_dependencies(&self, &mut dependencies); |
83 | } |
84 | self.globals.for_all_items(|global| { |
85 | global.add_dependencies(&self, &mut dependencies); |
86 | }); |
87 | self.constants.for_all_items(|constant| { |
88 | constant.add_dependencies(&self, &mut dependencies); |
89 | }); |
90 | for name in &self.config.export.include { |
91 | let path = Path::new(name.clone()); |
92 | if let Some(items) = self.get_items(&path) { |
93 | if dependencies.items.insert(path) { |
94 | for item in &items { |
95 | item.deref().add_dependencies(&self, &mut dependencies); |
96 | } |
97 | for item in items { |
98 | dependencies.order.push(item); |
99 | } |
100 | } |
101 | } |
102 | } |
103 | |
104 | dependencies.sort(); |
105 | |
106 | let items = dependencies.order; |
107 | let constants = if self.config.export.should_generate(ItemType::Constants) { |
108 | let mut constants = self.constants.to_vec(); |
109 | match self.config.constant.sort_by.unwrap_or(self.config.sort_by) { |
110 | SortKey::Name => constants.sort_by(|x, y| x.path.cmp(&y.path)), |
111 | SortKey::None => { /* keep input order */ } |
112 | } |
113 | constants |
114 | } else { |
115 | vec![] |
116 | }; |
117 | |
118 | let globals = if self.config.export.should_generate(ItemType::Globals) { |
119 | let mut globals = self.globals.to_vec(); |
120 | match self.config.constant.sort_by.unwrap_or(self.config.sort_by) { |
121 | SortKey::Name => globals.sort_by(|x, y| x.path.cmp(&y.path)), |
122 | SortKey::None => { /* keep input order */ } |
123 | } |
124 | globals |
125 | } else { |
126 | vec![] |
127 | }; |
128 | let functions = if self.config.export.should_generate(ItemType::Functions) { |
129 | self.functions |
130 | } else { |
131 | vec![] |
132 | }; |
133 | |
134 | Ok(Bindings::new( |
135 | self.config, |
136 | self.structs, |
137 | self.typedefs, |
138 | constants, |
139 | globals, |
140 | items, |
141 | functions, |
142 | self.source_files, |
143 | false, |
144 | )) |
145 | } |
146 | |
147 | pub fn get_items(&self, p: &Path) -> Option<Vec<ItemContainer>> { |
148 | macro_rules! find { |
149 | ($field:ident, $kind:ident) => { |
150 | if self.config.export.should_generate(ItemType::$kind) { |
151 | if let Some(x) = self.$field.get_items(p) { |
152 | return Some(x); |
153 | } |
154 | } |
155 | }; |
156 | } |
157 | |
158 | find!(enums, Enums); |
159 | find!(structs, Structs); |
160 | find!(unions, Unions); |
161 | find!(opaque_items, OpaqueItems); |
162 | find!(typedefs, Typedefs); |
163 | |
164 | None |
165 | } |
166 | |
167 | pub fn get_config(&self) -> &Config { |
168 | &self.config |
169 | } |
170 | |
171 | fn remove_excluded(&mut self) { |
172 | let config = &self.config; |
173 | // FIXME: interpret `config.export.exclude` as `Path`s. |
174 | self.functions |
175 | .retain(|x| !config.export.exclude.iter().any(|y| y == x.path().name())); |
176 | self.enums |
177 | .filter(|x| config.export.exclude.iter().any(|y| y == x.path().name())); |
178 | self.structs |
179 | .filter(|x| config.export.exclude.iter().any(|y| y == x.path().name())); |
180 | self.unions |
181 | .filter(|x| config.export.exclude.iter().any(|y| y == x.path().name())); |
182 | self.opaque_items |
183 | .filter(|x| config.export.exclude.iter().any(|y| y == x.path().name())); |
184 | self.typedefs |
185 | .filter(|x| config.export.exclude.iter().any(|y| y == x.path().name())); |
186 | self.globals |
187 | .filter(|x| config.export.exclude.iter().any(|y| y == x.path().name())); |
188 | self.constants |
189 | .filter(|x| config.export.exclude.iter().any(|y| y == x.path().name())); |
190 | } |
191 | |
192 | fn transfer_annotations(&mut self) { |
193 | let mut annotations = HashMap::new(); |
194 | |
195 | self.typedefs.for_all_items_mut(|x| { |
196 | x.transfer_annotations(&mut annotations); |
197 | }); |
198 | |
199 | for (alias_path, annotations) in annotations { |
200 | // TODO |
201 | let mut transferred = false; |
202 | |
203 | self.enums.for_items_mut(&alias_path, |x| { |
204 | if x.annotations().is_empty() { |
205 | *x.annotations_mut() = annotations.clone(); |
206 | transferred = true; |
207 | } else { |
208 | warn!( |
209 | "Can't transfer annotations from typedef to alias ( {}) \ |
210 | that already has annotations." , |
211 | alias_path |
212 | ); |
213 | } |
214 | }); |
215 | if transferred { |
216 | continue; |
217 | } |
218 | self.structs.for_items_mut(&alias_path, |x| { |
219 | if x.annotations().is_empty() { |
220 | *x.annotations_mut() = annotations.clone(); |
221 | transferred = true; |
222 | } else { |
223 | warn!( |
224 | "Can't transfer annotations from typedef to alias ( {}) \ |
225 | that already has annotations." , |
226 | alias_path |
227 | ); |
228 | } |
229 | }); |
230 | if transferred { |
231 | continue; |
232 | } |
233 | self.unions.for_items_mut(&alias_path, |x| { |
234 | if x.annotations().is_empty() { |
235 | *x.annotations_mut() = annotations.clone(); |
236 | transferred = true; |
237 | } else { |
238 | warn!( |
239 | "Can't transfer annotations from typedef to alias ( {}) \ |
240 | that already has annotations." , |
241 | alias_path |
242 | ); |
243 | } |
244 | }); |
245 | if transferred { |
246 | continue; |
247 | } |
248 | self.opaque_items.for_items_mut(&alias_path, |x| { |
249 | if x.annotations().is_empty() { |
250 | *x.annotations_mut() = annotations.clone(); |
251 | transferred = true; |
252 | } else { |
253 | warn!( |
254 | "Can't transfer annotations from typedef to alias ( {}) \ |
255 | that already has annotations." , |
256 | alias_path |
257 | ); |
258 | } |
259 | }); |
260 | if transferred { |
261 | continue; |
262 | } |
263 | self.typedefs.for_items_mut(&alias_path, |x| { |
264 | if x.annotations().is_empty() { |
265 | *x.annotations_mut() = annotations.clone(); |
266 | transferred = true; |
267 | } else { |
268 | warn!( |
269 | "Can't transfer annotations from typedef to alias ( {}) \ |
270 | that already has annotations." , |
271 | alias_path |
272 | ); |
273 | } |
274 | }); |
275 | if transferred { |
276 | continue; |
277 | } |
278 | } |
279 | } |
280 | |
281 | fn rename_items(&mut self) { |
282 | let config = &self.config; |
283 | |
284 | self.globals |
285 | .for_all_items_mut(|x| x.rename_for_config(config)); |
286 | self.globals.rebuild(); |
287 | |
288 | self.constants |
289 | .for_all_items_mut(|x| x.rename_for_config(config)); |
290 | self.constants.rebuild(); |
291 | |
292 | self.structs |
293 | .for_all_items_mut(|x| x.rename_for_config(config)); |
294 | self.structs.rebuild(); |
295 | |
296 | self.unions |
297 | .for_all_items_mut(|x| x.rename_for_config(config)); |
298 | self.unions.rebuild(); |
299 | |
300 | self.enums |
301 | .for_all_items_mut(|x| x.rename_for_config(config)); |
302 | self.enums.rebuild(); |
303 | |
304 | self.opaque_items |
305 | .for_all_items_mut(|x| x.rename_for_config(config)); |
306 | self.opaque_items.rebuild(); |
307 | |
308 | self.typedefs |
309 | .for_all_items_mut(|x| x.rename_for_config(config)); |
310 | self.typedefs.rebuild(); |
311 | |
312 | for item in &mut self.functions { |
313 | item.rename_for_config(&self.config); |
314 | } |
315 | } |
316 | |
317 | fn resolve_declaration_types(&mut self) { |
318 | if !self.config.style.generate_tag() { |
319 | return; |
320 | } |
321 | |
322 | let mut resolver = DeclarationTypeResolver::default(); |
323 | |
324 | self.structs.for_all_items(|x| { |
325 | x.collect_declaration_types(&mut resolver); |
326 | }); |
327 | |
328 | self.enums.for_all_items(|x| { |
329 | x.collect_declaration_types(&mut resolver); |
330 | }); |
331 | |
332 | self.unions.for_all_items(|x| { |
333 | x.collect_declaration_types(&mut resolver); |
334 | }); |
335 | |
336 | self.typedefs.for_all_items(|x| { |
337 | x.collect_declaration_types(&mut resolver); |
338 | }); |
339 | |
340 | // NOTE: Intentionally last, so that in case there's an opaque type |
341 | // which is conflicting with a non-opaque one, the later wins. |
342 | self.opaque_items.for_all_items(|x| { |
343 | x.collect_declaration_types(&mut resolver); |
344 | }); |
345 | |
346 | self.enums |
347 | .for_all_items_mut(|x| x.resolve_declaration_types(&resolver)); |
348 | |
349 | self.structs |
350 | .for_all_items_mut(|x| x.resolve_declaration_types(&resolver)); |
351 | |
352 | self.unions |
353 | .for_all_items_mut(|x| x.resolve_declaration_types(&resolver)); |
354 | |
355 | self.typedefs |
356 | .for_all_items_mut(|x| x.resolve_declaration_types(&resolver)); |
357 | |
358 | self.globals |
359 | .for_all_items_mut(|x| x.resolve_declaration_types(&resolver)); |
360 | |
361 | for item in &mut self.functions { |
362 | item.resolve_declaration_types(&resolver); |
363 | } |
364 | } |
365 | |
366 | fn simplify_standard_types(&mut self) { |
367 | let config = &self.config; |
368 | |
369 | self.structs.for_all_items_mut(|x| { |
370 | x.simplify_standard_types(config); |
371 | }); |
372 | self.enums.for_all_items_mut(|x| { |
373 | x.simplify_standard_types(config); |
374 | }); |
375 | self.unions.for_all_items_mut(|x| { |
376 | x.simplify_standard_types(config); |
377 | }); |
378 | self.globals.for_all_items_mut(|x| { |
379 | x.simplify_standard_types(config); |
380 | }); |
381 | self.typedefs.for_all_items_mut(|x| { |
382 | x.simplify_standard_types(config); |
383 | }); |
384 | for x in &mut self.functions { |
385 | x.simplify_standard_types(config); |
386 | } |
387 | } |
388 | |
389 | fn instantiate_monomorphs(&mut self) { |
390 | // Collect a list of monomorphs |
391 | let mut monomorphs = Monomorphs::default(); |
392 | |
393 | self.structs.for_all_items(|x| { |
394 | x.add_monomorphs(self, &mut monomorphs); |
395 | }); |
396 | self.unions.for_all_items(|x| { |
397 | x.add_monomorphs(self, &mut monomorphs); |
398 | }); |
399 | self.enums.for_all_items(|x| { |
400 | x.add_monomorphs(self, &mut monomorphs); |
401 | }); |
402 | self.typedefs.for_all_items(|x| { |
403 | x.add_monomorphs(self, &mut monomorphs); |
404 | }); |
405 | for x in &self.functions { |
406 | x.add_monomorphs(self, &mut monomorphs); |
407 | } |
408 | |
409 | // Insert the monomorphs into self |
410 | for monomorph in monomorphs.drain_structs() { |
411 | self.structs.try_insert(monomorph); |
412 | } |
413 | for monomorph in monomorphs.drain_unions() { |
414 | self.unions.try_insert(monomorph); |
415 | } |
416 | for monomorph in monomorphs.drain_opaques() { |
417 | self.opaque_items.try_insert(monomorph); |
418 | } |
419 | for monomorph in monomorphs.drain_typedefs() { |
420 | self.typedefs.try_insert(monomorph); |
421 | } |
422 | for monomorph in monomorphs.drain_enums() { |
423 | self.enums.try_insert(monomorph); |
424 | } |
425 | |
426 | // Remove structs and opaque items that are generic |
427 | self.opaque_items.filter(|x| x.generic_params.len() > 0); |
428 | self.structs.filter(|x| x.generic_params.len() > 0); |
429 | self.unions.filter(|x| x.generic_params.len() > 0); |
430 | self.enums.filter(|x| x.generic_params.len() > 0); |
431 | self.typedefs.filter(|x| x.generic_params.len() > 0); |
432 | |
433 | // Mangle the paths that remain |
434 | self.unions |
435 | .for_all_items_mut(|x| x.mangle_paths(&monomorphs)); |
436 | self.structs |
437 | .for_all_items_mut(|x| x.mangle_paths(&monomorphs)); |
438 | self.enums |
439 | .for_all_items_mut(|x| x.mangle_paths(&monomorphs)); |
440 | self.typedefs |
441 | .for_all_items_mut(|x| x.mangle_paths(&monomorphs)); |
442 | for x in &mut self.functions { |
443 | x.mangle_paths(&monomorphs); |
444 | } |
445 | } |
446 | } |
447 | |