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
5use std::collections::HashMap;
6use std::path::PathBuf;
7
8use crate::bindgen::bindings::Bindings;
9use crate::bindgen::config::{Config, Language, SortKey};
10use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
11use crate::bindgen::dependencies::Dependencies;
12use crate::bindgen::error::Error;
13use crate::bindgen::ir::{Constant, Enum, Function, Item, ItemContainer, ItemMap};
14use crate::bindgen::ir::{OpaqueItem, Path, Static, Struct, Typedef, Union};
15use crate::bindgen::monomorph::Monomorphs;
16use crate::bindgen::ItemType;
17
18#[derive(Debug, Clone)]
19pub 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
32impl 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