1 | mod dyngen; |
2 | mod error; |
3 | mod helpers; |
4 | mod impl_debug; |
5 | mod impl_partialeq; |
6 | mod postprocessing; |
7 | mod serialize; |
8 | pub mod struct_layout; |
9 | |
10 | #[cfg (test)] |
11 | #[allow (warnings)] |
12 | pub(crate) mod bitfield_unit; |
13 | #[cfg (all(test, target_endian = "little" ))] |
14 | mod bitfield_unit_tests; |
15 | |
16 | use self::dyngen::DynamicItems; |
17 | use self::helpers::attributes; |
18 | use self::struct_layout::StructLayoutTracker; |
19 | |
20 | use super::BindgenOptions; |
21 | |
22 | use crate::callbacks::{DeriveInfo, TypeKind as DeriveTypeKind}; |
23 | use crate::ir::analysis::{HasVtable, Sizedness}; |
24 | use crate::ir::annotations::FieldAccessorKind; |
25 | use crate::ir::comp::{ |
26 | Bitfield, BitfieldUnit, CompInfo, CompKind, Field, FieldData, FieldMethods, |
27 | Method, MethodKind, |
28 | }; |
29 | use crate::ir::context::{BindgenContext, ItemId}; |
30 | use crate::ir::derive::{ |
31 | CanDerive, CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq, |
32 | CanDeriveHash, CanDeriveOrd, CanDerivePartialEq, CanDerivePartialOrd, |
33 | }; |
34 | use crate::ir::dot; |
35 | use crate::ir::enum_ty::{Enum, EnumVariant, EnumVariantValue}; |
36 | use crate::ir::function::{ |
37 | Abi, ClangAbi, Function, FunctionKind, FunctionSig, Linkage, |
38 | }; |
39 | use crate::ir::int::IntKind; |
40 | use crate::ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath}; |
41 | use crate::ir::item_kind::ItemKind; |
42 | use crate::ir::layout::Layout; |
43 | use crate::ir::module::Module; |
44 | use crate::ir::objc::{ObjCInterface, ObjCMethod}; |
45 | use crate::ir::template::{ |
46 | AsTemplateParam, TemplateInstantiation, TemplateParameters, |
47 | }; |
48 | use crate::ir::ty::{Type, TypeKind}; |
49 | use crate::ir::var::Var; |
50 | |
51 | use proc_macro2::{self, Ident, Span}; |
52 | use quote::TokenStreamExt; |
53 | |
54 | use crate::{Entry, HashMap, HashSet}; |
55 | use std::borrow::Cow; |
56 | use std::cell::Cell; |
57 | use std::collections::VecDeque; |
58 | use std::fmt::Write; |
59 | use std::iter; |
60 | use std::ops; |
61 | use std::str::FromStr; |
62 | |
63 | #[derive (Debug, Clone, PartialEq, Eq, Hash)] |
64 | pub enum CodegenError { |
65 | Serialize { msg: String, loc: String }, |
66 | Io(String), |
67 | } |
68 | |
69 | impl From<std::io::Error> for CodegenError { |
70 | fn from(err: std::io::Error) -> Self { |
71 | Self::Io(err.to_string()) |
72 | } |
73 | } |
74 | |
75 | impl std::fmt::Display for CodegenError { |
76 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
77 | match self { |
78 | CodegenError::Serialize { msg: &String, loc: &String } => { |
79 | write!(f, "serialization error at {}: {}" , loc, msg) |
80 | } |
81 | CodegenError::Io(err: &String) => err.fmt(f), |
82 | } |
83 | } |
84 | } |
85 | |
86 | // Name of type defined in constified enum module |
87 | pub static CONSTIFIED_ENUM_MODULE_REPR_NAME: &str = "Type" ; |
88 | |
89 | fn top_level_path( |
90 | ctx: &BindgenContext, |
91 | item: &Item, |
92 | ) -> Vec<proc_macro2::TokenStream> { |
93 | let mut path: Vec = vec![quote! { self }]; |
94 | |
95 | if ctx.options().enable_cxx_namespaces { |
96 | for _ in 0..item.codegen_depth(ctx) { |
97 | path.push(quote! { super }); |
98 | } |
99 | } |
100 | |
101 | path |
102 | } |
103 | |
104 | fn root_import( |
105 | ctx: &BindgenContext, |
106 | module: &Item, |
107 | ) -> proc_macro2::TokenStream { |
108 | assert!(ctx.options().enable_cxx_namespaces, "Somebody messed it up" ); |
109 | assert!(module.is_module()); |
110 | |
111 | let mut path: Vec = top_level_path(ctx, item:module); |
112 | |
113 | let root: String = ctx.root_module().canonical_name(ctx); |
114 | let root_ident: Ident = ctx.rust_ident(name:root); |
115 | path.push(quote! { #root_ident }); |
116 | |
117 | let mut tokens: TokenStream = quote! {}; |
118 | tokens.append_separated(iter:path, op:quote!(::)); |
119 | |
120 | quote! { |
121 | #[allow(unused_imports)] |
122 | use #tokens ; |
123 | } |
124 | } |
125 | |
126 | bitflags! { |
127 | struct DerivableTraits: u16 { |
128 | const DEBUG = 1 << 0; |
129 | const DEFAULT = 1 << 1; |
130 | const COPY = 1 << 2; |
131 | const CLONE = 1 << 3; |
132 | const HASH = 1 << 4; |
133 | const PARTIAL_ORD = 1 << 5; |
134 | const ORD = 1 << 6; |
135 | const PARTIAL_EQ = 1 << 7; |
136 | const EQ = 1 << 8; |
137 | } |
138 | } |
139 | |
140 | fn derives_of_item( |
141 | item: &Item, |
142 | ctx: &BindgenContext, |
143 | packed: bool, |
144 | ) -> DerivableTraits { |
145 | let mut derivable_traits = DerivableTraits::empty(); |
146 | |
147 | let all_template_params = item.all_template_params(ctx); |
148 | |
149 | if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() { |
150 | derivable_traits |= DerivableTraits::COPY; |
151 | |
152 | if ctx.options().rust_features().builtin_clone_impls || |
153 | !all_template_params.is_empty() |
154 | { |
155 | // FIXME: This requires extra logic if you have a big array in a |
156 | // templated struct. The reason for this is that the magic: |
157 | // fn clone(&self) -> Self { *self } |
158 | // doesn't work for templates. |
159 | // |
160 | // It's not hard to fix though. |
161 | derivable_traits |= DerivableTraits::CLONE; |
162 | } |
163 | } else if packed { |
164 | // If the struct or union is packed, deriving from Copy is required for |
165 | // deriving from any other trait. |
166 | return derivable_traits; |
167 | } |
168 | |
169 | if item.can_derive_debug(ctx) && !item.annotations().disallow_debug() { |
170 | derivable_traits |= DerivableTraits::DEBUG; |
171 | } |
172 | |
173 | if item.can_derive_default(ctx) && !item.annotations().disallow_default() { |
174 | derivable_traits |= DerivableTraits::DEFAULT; |
175 | } |
176 | |
177 | if item.can_derive_hash(ctx) { |
178 | derivable_traits |= DerivableTraits::HASH; |
179 | } |
180 | |
181 | if item.can_derive_partialord(ctx) { |
182 | derivable_traits |= DerivableTraits::PARTIAL_ORD; |
183 | } |
184 | |
185 | if item.can_derive_ord(ctx) { |
186 | derivable_traits |= DerivableTraits::ORD; |
187 | } |
188 | |
189 | if item.can_derive_partialeq(ctx) { |
190 | derivable_traits |= DerivableTraits::PARTIAL_EQ; |
191 | } |
192 | |
193 | if item.can_derive_eq(ctx) { |
194 | derivable_traits |= DerivableTraits::EQ; |
195 | } |
196 | |
197 | derivable_traits |
198 | } |
199 | |
200 | impl From<DerivableTraits> for Vec<&'static str> { |
201 | fn from(derivable_traits: DerivableTraits) -> Vec<&'static str> { |
202 | [ |
203 | (DerivableTraits::DEBUG, "Debug" ), |
204 | (DerivableTraits::DEFAULT, "Default" ), |
205 | (DerivableTraits::COPY, "Copy" ), |
206 | (DerivableTraits::CLONE, "Clone" ), |
207 | (DerivableTraits::HASH, "Hash" ), |
208 | (DerivableTraits::PARTIAL_ORD, "PartialOrd" ), |
209 | (DerivableTraits::ORD, "Ord" ), |
210 | (DerivableTraits::PARTIAL_EQ, "PartialEq" ), |
211 | (DerivableTraits::EQ, "Eq" ), |
212 | ] |
213 | .iter() |
214 | .filter_map(|&(flag: DerivableTraits, derive: &str)| { |
215 | Some(derive).filter(|_| derivable_traits.contains(flag)) |
216 | }) |
217 | .collect() |
218 | } |
219 | } |
220 | |
221 | struct CodegenResult<'a> { |
222 | items: Vec<proc_macro2::TokenStream>, |
223 | dynamic_items: DynamicItems, |
224 | |
225 | /// A monotonic counter used to add stable unique id's to stuff that doesn't |
226 | /// need to be referenced by anything. |
227 | codegen_id: &'a Cell<usize>, |
228 | |
229 | /// Whether a bindgen union has been generated at least once. |
230 | saw_bindgen_union: bool, |
231 | |
232 | /// Whether an incomplete array has been generated at least once. |
233 | saw_incomplete_array: bool, |
234 | |
235 | /// Whether Objective C types have been seen at least once. |
236 | saw_objc: bool, |
237 | |
238 | /// Whether Apple block types have been seen at least once. |
239 | saw_block: bool, |
240 | |
241 | /// Whether a bitfield allocation unit has been seen at least once. |
242 | saw_bitfield_unit: bool, |
243 | |
244 | items_seen: HashSet<ItemId>, |
245 | /// The set of generated function/var names, needed because in C/C++ is |
246 | /// legal to do something like: |
247 | /// |
248 | /// ```c++ |
249 | /// extern "C" { |
250 | /// void foo(); |
251 | /// extern int bar; |
252 | /// } |
253 | /// |
254 | /// extern "C" { |
255 | /// void foo(); |
256 | /// extern int bar; |
257 | /// } |
258 | /// ``` |
259 | /// |
260 | /// Being these two different declarations. |
261 | functions_seen: HashSet<String>, |
262 | vars_seen: HashSet<String>, |
263 | |
264 | /// Used for making bindings to overloaded functions. Maps from a canonical |
265 | /// function name to the number of overloads we have already codegen'd for |
266 | /// that name. This lets us give each overload a unique suffix. |
267 | overload_counters: HashMap<String, u32>, |
268 | |
269 | items_to_serialize: Vec<ItemId>, |
270 | } |
271 | |
272 | impl<'a> CodegenResult<'a> { |
273 | fn new(codegen_id: &'a Cell<usize>) -> Self { |
274 | CodegenResult { |
275 | items: vec![], |
276 | dynamic_items: DynamicItems::new(), |
277 | saw_bindgen_union: false, |
278 | saw_incomplete_array: false, |
279 | saw_objc: false, |
280 | saw_block: false, |
281 | saw_bitfield_unit: false, |
282 | codegen_id, |
283 | items_seen: Default::default(), |
284 | functions_seen: Default::default(), |
285 | vars_seen: Default::default(), |
286 | overload_counters: Default::default(), |
287 | items_to_serialize: Default::default(), |
288 | } |
289 | } |
290 | |
291 | fn dynamic_items(&mut self) -> &mut DynamicItems { |
292 | &mut self.dynamic_items |
293 | } |
294 | |
295 | fn saw_bindgen_union(&mut self) { |
296 | self.saw_bindgen_union = true; |
297 | } |
298 | |
299 | fn saw_incomplete_array(&mut self) { |
300 | self.saw_incomplete_array = true; |
301 | } |
302 | |
303 | fn saw_objc(&mut self) { |
304 | self.saw_objc = true; |
305 | } |
306 | |
307 | fn saw_block(&mut self) { |
308 | self.saw_block = true; |
309 | } |
310 | |
311 | fn saw_bitfield_unit(&mut self) { |
312 | self.saw_bitfield_unit = true; |
313 | } |
314 | |
315 | fn seen<Id: Into<ItemId>>(&self, item: Id) -> bool { |
316 | self.items_seen.contains(&item.into()) |
317 | } |
318 | |
319 | fn set_seen<Id: Into<ItemId>>(&mut self, item: Id) { |
320 | self.items_seen.insert(item.into()); |
321 | } |
322 | |
323 | fn seen_function(&self, name: &str) -> bool { |
324 | self.functions_seen.contains(name) |
325 | } |
326 | |
327 | fn saw_function(&mut self, name: &str) { |
328 | self.functions_seen.insert(name.into()); |
329 | } |
330 | |
331 | /// Get the overload number for the given function name. Increments the |
332 | /// counter internally so the next time we ask for the overload for this |
333 | /// name, we get the incremented value, and so on. |
334 | fn overload_number(&mut self, name: &str) -> u32 { |
335 | let counter = self.overload_counters.entry(name.into()).or_insert(0); |
336 | let number = *counter; |
337 | *counter += 1; |
338 | number |
339 | } |
340 | |
341 | fn seen_var(&self, name: &str) -> bool { |
342 | self.vars_seen.contains(name) |
343 | } |
344 | |
345 | fn saw_var(&mut self, name: &str) { |
346 | self.vars_seen.insert(name.into()); |
347 | } |
348 | |
349 | fn inner<F>(&mut self, cb: F) -> Vec<proc_macro2::TokenStream> |
350 | where |
351 | F: FnOnce(&mut Self), |
352 | { |
353 | let mut new = Self::new(self.codegen_id); |
354 | |
355 | cb(&mut new); |
356 | |
357 | self.saw_incomplete_array |= new.saw_incomplete_array; |
358 | self.saw_objc |= new.saw_objc; |
359 | self.saw_block |= new.saw_block; |
360 | self.saw_bitfield_unit |= new.saw_bitfield_unit; |
361 | self.saw_bindgen_union |= new.saw_bindgen_union; |
362 | |
363 | new.items |
364 | } |
365 | } |
366 | |
367 | impl<'a> ops::Deref for CodegenResult<'a> { |
368 | type Target = Vec<proc_macro2::TokenStream>; |
369 | |
370 | fn deref(&self) -> &Self::Target { |
371 | &self.items |
372 | } |
373 | } |
374 | |
375 | impl<'a> ops::DerefMut for CodegenResult<'a> { |
376 | fn deref_mut(&mut self) -> &mut Self::Target { |
377 | &mut self.items |
378 | } |
379 | } |
380 | |
381 | /// A trait to convert a rust type into a pointer, optionally const, to the same |
382 | /// type. |
383 | trait ToPtr { |
384 | fn to_ptr(self, is_const: bool) -> proc_macro2::TokenStream; |
385 | } |
386 | |
387 | impl ToPtr for proc_macro2::TokenStream { |
388 | fn to_ptr(self, is_const: bool) -> proc_macro2::TokenStream { |
389 | if is_const { |
390 | quote! { *const #self } |
391 | } else { |
392 | quote! { *mut #self } |
393 | } |
394 | } |
395 | } |
396 | |
397 | /// An extension trait for `proc_macro2::TokenStream` that lets us append any implicit |
398 | /// template parameters that exist for some type, if necessary. |
399 | trait AppendImplicitTemplateParams { |
400 | fn append_implicit_template_params( |
401 | &mut self, |
402 | ctx: &BindgenContext, |
403 | item: &Item, |
404 | ); |
405 | } |
406 | |
407 | impl AppendImplicitTemplateParams for proc_macro2::TokenStream { |
408 | fn append_implicit_template_params( |
409 | &mut self, |
410 | ctx: &BindgenContext, |
411 | item: &Item, |
412 | ) { |
413 | let item = item.id().into_resolver().through_type_refs().resolve(ctx); |
414 | |
415 | match *item.expect_type().kind() { |
416 | TypeKind::UnresolvedTypeRef(..) => { |
417 | unreachable!("already resolved unresolved type refs" ) |
418 | } |
419 | TypeKind::ResolvedTypeRef(..) => { |
420 | unreachable!("we resolved item through type refs" ) |
421 | } |
422 | |
423 | // None of these types ever have implicit template parameters. |
424 | TypeKind::Void | |
425 | TypeKind::NullPtr | |
426 | TypeKind::Pointer(..) | |
427 | TypeKind::Reference(..) | |
428 | TypeKind::Int(..) | |
429 | TypeKind::Float(..) | |
430 | TypeKind::Complex(..) | |
431 | TypeKind::Array(..) | |
432 | TypeKind::TypeParam | |
433 | TypeKind::Opaque | |
434 | TypeKind::Function(..) | |
435 | TypeKind::Enum(..) | |
436 | TypeKind::ObjCId | |
437 | TypeKind::ObjCSel | |
438 | TypeKind::TemplateInstantiation(..) => return, |
439 | _ => {} |
440 | } |
441 | |
442 | let params: Vec<_> = item |
443 | .used_template_params(ctx) |
444 | .iter() |
445 | .map(|p| { |
446 | p.try_to_rust_ty(ctx, &()) |
447 | .expect("template params cannot fail to be a rust type" ) |
448 | }) |
449 | .collect(); |
450 | if !params.is_empty() { |
451 | self.append_all(quote! { |
452 | < #( #params ),* > |
453 | }); |
454 | } |
455 | } |
456 | } |
457 | |
458 | trait CodeGenerator { |
459 | /// Extra information from the caller. |
460 | type Extra; |
461 | |
462 | /// Extra information returned to the caller. |
463 | type Return; |
464 | |
465 | fn codegen( |
466 | &self, |
467 | ctx: &BindgenContext, |
468 | result: &mut CodegenResult<'_>, |
469 | extra: &Self::Extra, |
470 | ) -> Self::Return; |
471 | } |
472 | |
473 | impl Item { |
474 | fn process_before_codegen( |
475 | &self, |
476 | ctx: &BindgenContext, |
477 | result: &mut CodegenResult, |
478 | ) -> bool { |
479 | if !self.is_enabled_for_codegen(ctx) { |
480 | return false; |
481 | } |
482 | |
483 | if self.is_blocklisted(ctx) || result.seen(self.id()) { |
484 | debug!( |
485 | "<Item as CodeGenerator>::process_before_codegen: Ignoring hidden or seen: \ |
486 | self = {:?}" , |
487 | self |
488 | ); |
489 | return false; |
490 | } |
491 | |
492 | if !ctx.codegen_items().contains(&self.id()) { |
493 | // TODO(emilio, #453): Figure out what to do when this happens |
494 | // legitimately, we could track the opaque stuff and disable the |
495 | // assertion there I guess. |
496 | warn!("Found non-allowlisted item in code generation: {:?}" , self); |
497 | } |
498 | |
499 | result.set_seen(self.id()); |
500 | true |
501 | } |
502 | } |
503 | |
504 | impl CodeGenerator for Item { |
505 | type Extra = (); |
506 | type Return = (); |
507 | |
508 | fn codegen( |
509 | &self, |
510 | ctx: &BindgenContext, |
511 | result: &mut CodegenResult<'_>, |
512 | _extra: &(), |
513 | ) { |
514 | debug!("<Item as CodeGenerator>::codegen: self = {:?}" , self); |
515 | if !self.process_before_codegen(ctx, result) { |
516 | return; |
517 | } |
518 | |
519 | match *self.kind() { |
520 | ItemKind::Module(ref module) => { |
521 | module.codegen(ctx, result, self); |
522 | } |
523 | ItemKind::Function(ref fun) => { |
524 | fun.codegen(ctx, result, self); |
525 | } |
526 | ItemKind::Var(ref var) => { |
527 | var.codegen(ctx, result, self); |
528 | } |
529 | ItemKind::Type(ref ty) => { |
530 | ty.codegen(ctx, result, self); |
531 | } |
532 | } |
533 | } |
534 | } |
535 | |
536 | impl CodeGenerator for Module { |
537 | type Extra = Item; |
538 | type Return = (); |
539 | |
540 | fn codegen( |
541 | &self, |
542 | ctx: &BindgenContext, |
543 | result: &mut CodegenResult<'_>, |
544 | item: &Item, |
545 | ) { |
546 | debug!("<Module as CodeGenerator>::codegen: item = {:?}" , item); |
547 | |
548 | let codegen_self = |result: &mut CodegenResult, |
549 | found_any: &mut bool| { |
550 | for child in self.children() { |
551 | if ctx.codegen_items().contains(child) { |
552 | *found_any = true; |
553 | ctx.resolve_item(*child).codegen(ctx, result, &()); |
554 | } |
555 | } |
556 | |
557 | if item.id() == ctx.root_module() { |
558 | if result.saw_block { |
559 | utils::prepend_block_header(ctx, &mut *result); |
560 | } |
561 | if result.saw_bindgen_union { |
562 | utils::prepend_union_types(ctx, &mut *result); |
563 | } |
564 | if result.saw_incomplete_array { |
565 | utils::prepend_incomplete_array_types(ctx, &mut *result); |
566 | } |
567 | if ctx.need_bindgen_complex_type() { |
568 | utils::prepend_complex_type(&mut *result); |
569 | } |
570 | if result.saw_objc { |
571 | utils::prepend_objc_header(ctx, &mut *result); |
572 | } |
573 | if result.saw_bitfield_unit { |
574 | utils::prepend_bitfield_unit_type(ctx, &mut *result); |
575 | } |
576 | } |
577 | }; |
578 | |
579 | if !ctx.options().enable_cxx_namespaces || |
580 | (self.is_inline() && |
581 | !ctx.options().conservative_inline_namespaces) |
582 | { |
583 | codegen_self(result, &mut false); |
584 | return; |
585 | } |
586 | |
587 | let mut found_any = false; |
588 | let inner_items = result.inner(|result| { |
589 | result.push(root_import(ctx, item)); |
590 | |
591 | let path = item.namespace_aware_canonical_path(ctx).join("::" ); |
592 | if let Some(raw_lines) = ctx.options().module_lines.get(&path) { |
593 | for raw_line in raw_lines { |
594 | found_any = true; |
595 | result.push( |
596 | proc_macro2::TokenStream::from_str(raw_line).unwrap(), |
597 | ); |
598 | } |
599 | } |
600 | |
601 | codegen_self(result, &mut found_any); |
602 | }); |
603 | |
604 | // Don't bother creating an empty module. |
605 | if !found_any { |
606 | return; |
607 | } |
608 | |
609 | let name = item.canonical_name(ctx); |
610 | let ident = ctx.rust_ident(name); |
611 | result.push(if item.id() == ctx.root_module() { |
612 | quote! { |
613 | #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] |
614 | pub mod #ident { |
615 | #( #inner_items )* |
616 | } |
617 | } |
618 | } else { |
619 | quote! { |
620 | pub mod #ident { |
621 | #( #inner_items )* |
622 | } |
623 | } |
624 | }); |
625 | } |
626 | } |
627 | |
628 | impl CodeGenerator for Var { |
629 | type Extra = Item; |
630 | type Return = (); |
631 | |
632 | fn codegen( |
633 | &self, |
634 | ctx: &BindgenContext, |
635 | result: &mut CodegenResult<'_>, |
636 | item: &Item, |
637 | ) { |
638 | use crate::ir::var::VarType; |
639 | debug!("<Var as CodeGenerator>::codegen: item = {:?}" , item); |
640 | debug_assert!(item.is_enabled_for_codegen(ctx)); |
641 | |
642 | let canonical_name = item.canonical_name(ctx); |
643 | |
644 | if result.seen_var(&canonical_name) { |
645 | return; |
646 | } |
647 | result.saw_var(&canonical_name); |
648 | |
649 | let canonical_ident = ctx.rust_ident(&canonical_name); |
650 | |
651 | // We can't generate bindings to static variables of templates. The |
652 | // number of actual variables for a single declaration are open ended |
653 | // and we don't know what instantiations do or don't exist. |
654 | if !item.all_template_params(ctx).is_empty() { |
655 | return; |
656 | } |
657 | |
658 | let mut attrs = vec![]; |
659 | if let Some(comment) = item.comment(ctx) { |
660 | attrs.push(attributes::doc(comment)); |
661 | } |
662 | |
663 | let ty = self.ty().to_rust_ty_or_opaque(ctx, &()); |
664 | |
665 | if let Some(val) = self.val() { |
666 | match *val { |
667 | VarType::Bool(val) => { |
668 | result.push(quote! { |
669 | #(#attrs)* |
670 | pub const #canonical_ident : #ty = #val ; |
671 | }); |
672 | } |
673 | VarType::Int(val) => { |
674 | let int_kind = self |
675 | .ty() |
676 | .into_resolver() |
677 | .through_type_aliases() |
678 | .through_type_refs() |
679 | .resolve(ctx) |
680 | .expect_type() |
681 | .as_integer() |
682 | .unwrap(); |
683 | let val = if int_kind.is_signed() { |
684 | helpers::ast_ty::int_expr(val) |
685 | } else { |
686 | helpers::ast_ty::uint_expr(val as _) |
687 | }; |
688 | result.push(quote! { |
689 | #(#attrs)* |
690 | pub const #canonical_ident : #ty = #val ; |
691 | }); |
692 | } |
693 | VarType::String(ref bytes) => { |
694 | // Account the trailing zero. |
695 | // |
696 | // TODO: Here we ignore the type we just made up, probably |
697 | // we should refactor how the variable type and ty id work. |
698 | let len = bytes.len() + 1; |
699 | let ty = quote! { |
700 | [u8; #len] |
701 | }; |
702 | |
703 | match String::from_utf8(bytes.clone()) { |
704 | Ok(string) => { |
705 | let cstr = helpers::ast_ty::cstr_expr(string); |
706 | if ctx |
707 | .options() |
708 | .rust_features |
709 | .static_lifetime_elision |
710 | { |
711 | result.push(quote! { |
712 | #(#attrs)* |
713 | pub const #canonical_ident : &#ty = #cstr ; |
714 | }); |
715 | } else { |
716 | result.push(quote! { |
717 | #(#attrs)* |
718 | pub const #canonical_ident : &'static #ty = #cstr ; |
719 | }); |
720 | } |
721 | } |
722 | Err(..) => { |
723 | let bytes = helpers::ast_ty::byte_array_expr(bytes); |
724 | result.push(quote! { |
725 | #(#attrs)* |
726 | pub const #canonical_ident : #ty = #bytes ; |
727 | }); |
728 | } |
729 | } |
730 | } |
731 | VarType::Float(f) => { |
732 | if let Ok(expr) = helpers::ast_ty::float_expr(ctx, f) { |
733 | result.push(quote! { |
734 | #(#attrs)* |
735 | pub const #canonical_ident : #ty = #expr ; |
736 | }); |
737 | } |
738 | } |
739 | VarType::Char(c) => { |
740 | result.push(quote! { |
741 | #(#attrs)* |
742 | pub const #canonical_ident : #ty = #c ; |
743 | }); |
744 | } |
745 | } |
746 | } else { |
747 | // If necessary, apply a `#[link_name]` attribute |
748 | let link_name = self.mangled_name().unwrap_or_else(|| self.name()); |
749 | if !utils::names_will_be_identical_after_mangling( |
750 | &canonical_name, |
751 | link_name, |
752 | None, |
753 | ) { |
754 | attrs.push(attributes::link_name(link_name)); |
755 | } |
756 | |
757 | let maybe_mut = if self.is_const() { |
758 | quote! {} |
759 | } else { |
760 | quote! { mut } |
761 | }; |
762 | |
763 | let tokens = quote!( |
764 | extern "C" { |
765 | #(#attrs)* |
766 | pub static #maybe_mut #canonical_ident: #ty; |
767 | } |
768 | ); |
769 | |
770 | result.push(tokens); |
771 | } |
772 | } |
773 | } |
774 | |
775 | impl CodeGenerator for Type { |
776 | type Extra = Item; |
777 | type Return = (); |
778 | |
779 | fn codegen( |
780 | &self, |
781 | ctx: &BindgenContext, |
782 | result: &mut CodegenResult<'_>, |
783 | item: &Item, |
784 | ) { |
785 | debug!("<Type as CodeGenerator>::codegen: item = {:?}" , item); |
786 | debug_assert!(item.is_enabled_for_codegen(ctx)); |
787 | |
788 | match *self.kind() { |
789 | TypeKind::Void | |
790 | TypeKind::NullPtr | |
791 | TypeKind::Int(..) | |
792 | TypeKind::Float(..) | |
793 | TypeKind::Complex(..) | |
794 | TypeKind::Array(..) | |
795 | TypeKind::Vector(..) | |
796 | TypeKind::Pointer(..) | |
797 | TypeKind::Reference(..) | |
798 | TypeKind::Function(..) | |
799 | TypeKind::ResolvedTypeRef(..) | |
800 | TypeKind::Opaque | |
801 | TypeKind::TypeParam => { |
802 | // These items don't need code generation, they only need to be |
803 | // converted to rust types in fields, arguments, and such. |
804 | // NOTE(emilio): If you add to this list, make sure to also add |
805 | // it to BindgenContext::compute_allowlisted_and_codegen_items. |
806 | } |
807 | TypeKind::TemplateInstantiation(ref inst) => { |
808 | inst.codegen(ctx, result, item) |
809 | } |
810 | TypeKind::BlockPointer(inner) => { |
811 | if !ctx.options().generate_block { |
812 | return; |
813 | } |
814 | |
815 | let inner_item = |
816 | inner.into_resolver().through_type_refs().resolve(ctx); |
817 | let name = item.canonical_name(ctx); |
818 | |
819 | let inner_rust_type = { |
820 | if let TypeKind::Function(fnsig) = |
821 | inner_item.kind().expect_type().kind() |
822 | { |
823 | utils::fnsig_block(ctx, fnsig) |
824 | } else { |
825 | panic!("invalid block typedef: {:?}" , inner_item) |
826 | } |
827 | }; |
828 | |
829 | let rust_name = ctx.rust_ident(name); |
830 | |
831 | let mut tokens = if let Some(comment) = item.comment(ctx) { |
832 | attributes::doc(comment) |
833 | } else { |
834 | quote! {} |
835 | }; |
836 | |
837 | tokens.append_all(quote! { |
838 | pub type #rust_name = #inner_rust_type ; |
839 | }); |
840 | |
841 | result.push(tokens); |
842 | result.saw_block(); |
843 | } |
844 | TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item), |
845 | TypeKind::TemplateAlias(inner, _) | TypeKind::Alias(inner) => { |
846 | let inner_item = |
847 | inner.into_resolver().through_type_refs().resolve(ctx); |
848 | let name = item.canonical_name(ctx); |
849 | let path = item.canonical_path(ctx); |
850 | |
851 | { |
852 | let through_type_aliases = inner |
853 | .into_resolver() |
854 | .through_type_refs() |
855 | .through_type_aliases() |
856 | .resolve(ctx); |
857 | |
858 | // Try to catch the common pattern: |
859 | // |
860 | // typedef struct foo { ... } foo; |
861 | // |
862 | // here, and also other more complex cases like #946. |
863 | if through_type_aliases.canonical_path(ctx) == path { |
864 | return; |
865 | } |
866 | } |
867 | |
868 | // If this is a known named type, disallow generating anything |
869 | // for it too. If size_t -> usize conversions are enabled, we |
870 | // need to check that these conversions are permissible, but |
871 | // nothing needs to be generated, still. |
872 | let spelling = self.name().expect("Unnamed alias?" ); |
873 | if utils::type_from_named(ctx, spelling).is_some() { |
874 | if let "size_t" | "ssize_t" = spelling { |
875 | let layout = inner_item |
876 | .kind() |
877 | .expect_type() |
878 | .layout(ctx) |
879 | .expect("No layout?" ); |
880 | assert_eq!( |
881 | layout.size, |
882 | ctx.target_pointer_size(), |
883 | "Target platform requires `--no-size_t-is-usize`. The size of ` {}` ( {}) does not match the target pointer size ( {})" , |
884 | spelling, |
885 | layout.size, |
886 | ctx.target_pointer_size(), |
887 | ); |
888 | assert_eq!( |
889 | layout.align, |
890 | ctx.target_pointer_size(), |
891 | "Target platform requires `--no-size_t-is-usize`. The alignment of ` {}` ( {}) does not match the target pointer size ( {})" , |
892 | spelling, |
893 | layout.align, |
894 | ctx.target_pointer_size(), |
895 | ); |
896 | } |
897 | return; |
898 | } |
899 | |
900 | let mut outer_params = item.used_template_params(ctx); |
901 | |
902 | let is_opaque = item.is_opaque(ctx, &()); |
903 | let inner_rust_type = if is_opaque { |
904 | outer_params = vec![]; |
905 | self.to_opaque(ctx, item) |
906 | } else { |
907 | // Its possible that we have better layout information than |
908 | // the inner type does, so fall back to an opaque blob based |
909 | // on our layout if converting the inner item fails. |
910 | let mut inner_ty = inner_item |
911 | .try_to_rust_ty_or_opaque(ctx, &()) |
912 | .unwrap_or_else(|_| self.to_opaque(ctx, item)); |
913 | inner_ty.append_implicit_template_params(ctx, inner_item); |
914 | inner_ty |
915 | }; |
916 | |
917 | { |
918 | // FIXME(emilio): This is a workaround to avoid generating |
919 | // incorrect type aliases because of types that we haven't |
920 | // been able to resolve (because, eg, they depend on a |
921 | // template parameter). |
922 | // |
923 | // It's kind of a shame not generating them even when they |
924 | // could be referenced, but we already do the same for items |
925 | // with invalid template parameters, and at least this way |
926 | // they can be replaced, instead of generating plain invalid |
927 | // code. |
928 | let inner_canon_type = |
929 | inner_item.expect_type().canonical_type(ctx); |
930 | if inner_canon_type.is_invalid_type_param() { |
931 | warn!( |
932 | "Item contained invalid named type, skipping: \ |
933 | {:?}, {:?}" , |
934 | item, inner_item |
935 | ); |
936 | return; |
937 | } |
938 | } |
939 | |
940 | let rust_name = ctx.rust_ident(&name); |
941 | |
942 | let mut tokens = if let Some(comment) = item.comment(ctx) { |
943 | attributes::doc(comment) |
944 | } else { |
945 | quote! {} |
946 | }; |
947 | |
948 | let alias_style = if ctx.options().type_alias.matches(&name) { |
949 | AliasVariation::TypeAlias |
950 | } else if ctx.options().new_type_alias.matches(&name) { |
951 | AliasVariation::NewType |
952 | } else if ctx.options().new_type_alias_deref.matches(&name) { |
953 | AliasVariation::NewTypeDeref |
954 | } else { |
955 | ctx.options().default_alias_style |
956 | }; |
957 | |
958 | // We prefer using `pub use` over `pub type` because of: |
959 | // https://github.com/rust-lang/rust/issues/26264 |
960 | // These are the only characters allowed in simple |
961 | // paths, eg `good::dogs::Bront`. |
962 | if inner_rust_type.to_string().chars().all(|c| matches!(c, 'A' ..='Z' | 'a' ..='z' | '0' ..='9' | ':' | '_' | ' ' )) && outer_params.is_empty() && |
963 | !is_opaque && |
964 | alias_style == AliasVariation::TypeAlias && |
965 | inner_item.expect_type().canonical_type(ctx).is_enum() |
966 | { |
967 | tokens.append_all(quote! { |
968 | pub use |
969 | }); |
970 | let path = top_level_path(ctx, item); |
971 | tokens.append_separated(path, quote!(::)); |
972 | tokens.append_all(quote! { |
973 | :: #inner_rust_type as #rust_name ; |
974 | }); |
975 | result.push(tokens); |
976 | return; |
977 | } |
978 | |
979 | tokens.append_all(match alias_style { |
980 | AliasVariation::TypeAlias => quote! { |
981 | pub type #rust_name |
982 | }, |
983 | AliasVariation::NewType | AliasVariation::NewTypeDeref => { |
984 | assert!( |
985 | ctx.options().rust_features().repr_transparent, |
986 | "repr_transparent feature is required to use {:?}" , |
987 | alias_style |
988 | ); |
989 | |
990 | let mut attributes = |
991 | vec![attributes::repr("transparent" )]; |
992 | let packed = false; // Types can't be packed in Rust. |
993 | let derivable_traits = |
994 | derives_of_item(item, ctx, packed); |
995 | if !derivable_traits.is_empty() { |
996 | let derives: Vec<_> = derivable_traits.into(); |
997 | attributes.push(attributes::derives(&derives)) |
998 | } |
999 | |
1000 | quote! { |
1001 | #( #attributes )* |
1002 | pub struct #rust_name |
1003 | } |
1004 | } |
1005 | }); |
1006 | |
1007 | let params: Vec<_> = outer_params |
1008 | .into_iter() |
1009 | .filter_map(|p| p.as_template_param(ctx, &())) |
1010 | .collect(); |
1011 | if params |
1012 | .iter() |
1013 | .any(|p| ctx.resolve_type(*p).is_invalid_type_param()) |
1014 | { |
1015 | warn!( |
1016 | "Item contained invalid template \ |
1017 | parameter: {:?}" , |
1018 | item |
1019 | ); |
1020 | return; |
1021 | } |
1022 | let params: Vec<_> = params |
1023 | .iter() |
1024 | .map(|p| { |
1025 | p.try_to_rust_ty(ctx, &()).expect( |
1026 | "type parameters can always convert to rust ty OK" , |
1027 | ) |
1028 | }) |
1029 | .collect(); |
1030 | |
1031 | if !params.is_empty() { |
1032 | tokens.append_all(quote! { |
1033 | < #( #params ),* > |
1034 | }); |
1035 | } |
1036 | |
1037 | tokens.append_all(match alias_style { |
1038 | AliasVariation::TypeAlias => quote! { |
1039 | = #inner_rust_type ; |
1040 | }, |
1041 | AliasVariation::NewType | AliasVariation::NewTypeDeref => { |
1042 | quote! { |
1043 | (pub #inner_rust_type) ; |
1044 | } |
1045 | } |
1046 | }); |
1047 | |
1048 | if alias_style == AliasVariation::NewTypeDeref { |
1049 | let prefix = ctx.trait_prefix(); |
1050 | tokens.append_all(quote! { |
1051 | impl ::#prefix::ops::Deref for #rust_name { |
1052 | type Target = #inner_rust_type; |
1053 | #[inline] |
1054 | fn deref(&self) -> &Self::Target { |
1055 | &self.0 |
1056 | } |
1057 | } |
1058 | impl ::#prefix::ops::DerefMut for #rust_name { |
1059 | #[inline] |
1060 | fn deref_mut(&mut self) -> &mut Self::Target { |
1061 | &mut self.0 |
1062 | } |
1063 | } |
1064 | }); |
1065 | } |
1066 | |
1067 | result.push(tokens); |
1068 | } |
1069 | TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item), |
1070 | TypeKind::ObjCId | TypeKind::ObjCSel => { |
1071 | result.saw_objc(); |
1072 | } |
1073 | TypeKind::ObjCInterface(ref interface) => { |
1074 | interface.codegen(ctx, result, item) |
1075 | } |
1076 | ref u @ TypeKind::UnresolvedTypeRef(..) => { |
1077 | unreachable!("Should have been resolved after parsing {:?}!" , u) |
1078 | } |
1079 | } |
1080 | } |
1081 | } |
1082 | |
1083 | struct Vtable<'a> { |
1084 | item_id: ItemId, |
1085 | /// A reference to the originating compound object. |
1086 | #[allow (dead_code)] |
1087 | comp_info: &'a CompInfo, |
1088 | } |
1089 | |
1090 | impl<'a> Vtable<'a> { |
1091 | fn new(item_id: ItemId, comp_info: &'a CompInfo) -> Self { |
1092 | Vtable { item_id, comp_info } |
1093 | } |
1094 | } |
1095 | |
1096 | impl<'a> CodeGenerator for Vtable<'a> { |
1097 | type Extra = Item; |
1098 | type Return = (); |
1099 | |
1100 | fn codegen( |
1101 | &self, |
1102 | ctx: &BindgenContext, |
1103 | result: &mut CodegenResult<'_>, |
1104 | item: &Item, |
1105 | ) { |
1106 | assert_eq!(item.id(), self.item_id); |
1107 | debug_assert!(item.is_enabled_for_codegen(ctx)); |
1108 | let name = ctx.rust_ident(self.canonical_name(ctx)); |
1109 | |
1110 | // For now, we will only generate vtables for classes that: |
1111 | // - do not inherit from others (compilers merge VTable from primary parent class). |
1112 | // - do not contain a virtual destructor (requires ordering; platforms generate different vtables). |
1113 | if ctx.options().vtable_generation && |
1114 | self.comp_info.base_members().is_empty() && |
1115 | self.comp_info.destructor().is_none() |
1116 | { |
1117 | let class_ident = ctx.rust_ident(self.item_id.canonical_name(ctx)); |
1118 | |
1119 | let methods = self |
1120 | .comp_info |
1121 | .methods() |
1122 | .iter() |
1123 | .filter_map(|m| { |
1124 | if !m.is_virtual() { |
1125 | return None; |
1126 | } |
1127 | |
1128 | let function_item = ctx.resolve_item(m.signature()); |
1129 | let function = function_item.expect_function(); |
1130 | let signature_item = ctx.resolve_item(function.signature()); |
1131 | let signature = match signature_item.expect_type().kind() { |
1132 | TypeKind::Function(ref sig) => sig, |
1133 | _ => panic!("Function signature type mismatch" ), |
1134 | }; |
1135 | |
1136 | // FIXME: Is there a canonical name without the class prepended? |
1137 | let function_name = function_item.canonical_name(ctx); |
1138 | |
1139 | // FIXME: Need to account for overloading with times_seen (separately from regular function path). |
1140 | let function_name = ctx.rust_ident(function_name); |
1141 | let mut args = utils::fnsig_arguments(ctx, signature); |
1142 | let ret = utils::fnsig_return_ty(ctx, signature); |
1143 | |
1144 | args[0] = if m.is_const() { |
1145 | quote! { this: *const #class_ident } |
1146 | } else { |
1147 | quote! { this: *mut #class_ident } |
1148 | }; |
1149 | |
1150 | Some(quote! { |
1151 | pub #function_name : unsafe extern "C" fn( #( #args ),* ) #ret |
1152 | }) |
1153 | }) |
1154 | .collect::<Vec<_>>(); |
1155 | |
1156 | result.push(quote! { |
1157 | #[repr(C)] |
1158 | pub struct #name { |
1159 | #( #methods ),* |
1160 | } |
1161 | }) |
1162 | } else { |
1163 | // For the cases we don't support, simply generate an empty struct. |
1164 | let void = helpers::ast_ty::c_void(ctx); |
1165 | |
1166 | result.push(quote! { |
1167 | #[repr(C)] |
1168 | pub struct #name ( #void ); |
1169 | }); |
1170 | } |
1171 | } |
1172 | } |
1173 | |
1174 | impl<'a> ItemCanonicalName for Vtable<'a> { |
1175 | fn canonical_name(&self, ctx: &BindgenContext) -> String { |
1176 | format!(" {}__bindgen_vtable" , self.item_id.canonical_name(ctx)) |
1177 | } |
1178 | } |
1179 | |
1180 | impl<'a> TryToRustTy for Vtable<'a> { |
1181 | type Extra = (); |
1182 | |
1183 | fn try_to_rust_ty( |
1184 | &self, |
1185 | ctx: &BindgenContext, |
1186 | _: &(), |
1187 | ) -> error::Result<proc_macro2::TokenStream> { |
1188 | let name: Ident = ctx.rust_ident(self.canonical_name(ctx)); |
1189 | Ok(quote! { |
1190 | #name |
1191 | }) |
1192 | } |
1193 | } |
1194 | |
1195 | impl CodeGenerator for TemplateInstantiation { |
1196 | type Extra = Item; |
1197 | type Return = (); |
1198 | |
1199 | fn codegen( |
1200 | &self, |
1201 | ctx: &BindgenContext, |
1202 | result: &mut CodegenResult<'_>, |
1203 | item: &Item, |
1204 | ) { |
1205 | debug_assert!(item.is_enabled_for_codegen(ctx)); |
1206 | |
1207 | // Although uses of instantiations don't need code generation, and are |
1208 | // just converted to rust types in fields, vars, etc, we take this |
1209 | // opportunity to generate tests for their layout here. If the |
1210 | // instantiation is opaque, then its presumably because we don't |
1211 | // properly understand it (maybe because of specializations), and so we |
1212 | // shouldn't emit layout tests either. |
1213 | if !ctx.options().layout_tests || self.is_opaque(ctx, item) { |
1214 | return; |
1215 | } |
1216 | |
1217 | // If there are any unbound type parameters, then we can't generate a |
1218 | // layout test because we aren't dealing with a concrete type with a |
1219 | // concrete size and alignment. |
1220 | if ctx.uses_any_template_parameters(item.id()) { |
1221 | return; |
1222 | } |
1223 | |
1224 | let layout = item.kind().expect_type().layout(ctx); |
1225 | |
1226 | if let Some(layout) = layout { |
1227 | let size = layout.size; |
1228 | let align = layout.align; |
1229 | |
1230 | let name = item.full_disambiguated_name(ctx); |
1231 | let mut fn_name = |
1232 | format!("__bindgen_test_layout_ {}_instantiation" , name); |
1233 | let times_seen = result.overload_number(&fn_name); |
1234 | if times_seen > 0 { |
1235 | write!(&mut fn_name, "_ {}" , times_seen).unwrap(); |
1236 | } |
1237 | |
1238 | let fn_name = ctx.rust_ident_raw(fn_name); |
1239 | |
1240 | let prefix = ctx.trait_prefix(); |
1241 | let ident = item.to_rust_ty_or_opaque(ctx, &()); |
1242 | let size_of_expr = quote! { |
1243 | ::#prefix::mem::size_of::<#ident>() |
1244 | }; |
1245 | let align_of_expr = quote! { |
1246 | ::#prefix::mem::align_of::<#ident>() |
1247 | }; |
1248 | |
1249 | let item = quote! { |
1250 | #[test] |
1251 | fn #fn_name() { |
1252 | assert_eq!(#size_of_expr, #size, |
1253 | concat!("Size of template specialization: " , |
1254 | stringify!(#ident))); |
1255 | assert_eq!(#align_of_expr, #align, |
1256 | concat!("Alignment of template specialization: " , |
1257 | stringify!(#ident))); |
1258 | } |
1259 | }; |
1260 | |
1261 | result.push(item); |
1262 | } |
1263 | } |
1264 | } |
1265 | |
1266 | /// Trait for implementing the code generation of a struct or union field. |
1267 | trait FieldCodegen<'a> { |
1268 | type Extra; |
1269 | |
1270 | #[allow (clippy::too_many_arguments)] |
1271 | fn codegen<F, M>( |
1272 | &self, |
1273 | ctx: &BindgenContext, |
1274 | fields_should_be_private: bool, |
1275 | accessor_kind: FieldAccessorKind, |
1276 | parent: &CompInfo, |
1277 | result: &mut CodegenResult, |
1278 | struct_layout: &mut StructLayoutTracker, |
1279 | fields: &mut F, |
1280 | methods: &mut M, |
1281 | extra: Self::Extra, |
1282 | ) where |
1283 | F: Extend<proc_macro2::TokenStream>, |
1284 | M: Extend<proc_macro2::TokenStream>; |
1285 | } |
1286 | |
1287 | impl<'a> FieldCodegen<'a> for Field { |
1288 | type Extra = (); |
1289 | |
1290 | fn codegen<F, M>( |
1291 | &self, |
1292 | ctx: &BindgenContext, |
1293 | fields_should_be_private: bool, |
1294 | accessor_kind: FieldAccessorKind, |
1295 | parent: &CompInfo, |
1296 | result: &mut CodegenResult, |
1297 | struct_layout: &mut StructLayoutTracker, |
1298 | fields: &mut F, |
1299 | methods: &mut M, |
1300 | _: (), |
1301 | ) where |
1302 | F: Extend<proc_macro2::TokenStream>, |
1303 | M: Extend<proc_macro2::TokenStream>, |
1304 | { |
1305 | match *self { |
1306 | Field::DataMember(ref data) => { |
1307 | data.codegen( |
1308 | ctx, |
1309 | fields_should_be_private, |
1310 | accessor_kind, |
1311 | parent, |
1312 | result, |
1313 | struct_layout, |
1314 | fields, |
1315 | methods, |
1316 | (), |
1317 | ); |
1318 | } |
1319 | Field::Bitfields(ref unit) => { |
1320 | unit.codegen( |
1321 | ctx, |
1322 | fields_should_be_private, |
1323 | accessor_kind, |
1324 | parent, |
1325 | result, |
1326 | struct_layout, |
1327 | fields, |
1328 | methods, |
1329 | (), |
1330 | ); |
1331 | } |
1332 | } |
1333 | } |
1334 | } |
1335 | |
1336 | fn wrap_union_field_if_needed( |
1337 | ctx: &BindgenContext, |
1338 | struct_layout: &StructLayoutTracker, |
1339 | ty: proc_macro2::TokenStream, |
1340 | result: &mut CodegenResult, |
1341 | ) -> proc_macro2::TokenStream { |
1342 | if struct_layout.is_rust_union() { |
1343 | if struct_layout.can_copy_union_fields() { |
1344 | ty |
1345 | } else { |
1346 | let prefix: Ident = ctx.trait_prefix(); |
1347 | quote! { |
1348 | ::#prefix::mem::ManuallyDrop<#ty> |
1349 | } |
1350 | } |
1351 | } else { |
1352 | result.saw_bindgen_union(); |
1353 | if ctx.options().enable_cxx_namespaces { |
1354 | quote! { |
1355 | root::__BindgenUnionField<#ty> |
1356 | } |
1357 | } else { |
1358 | quote! { |
1359 | __BindgenUnionField<#ty> |
1360 | } |
1361 | } |
1362 | } |
1363 | } |
1364 | |
1365 | impl<'a> FieldCodegen<'a> for FieldData { |
1366 | type Extra = (); |
1367 | |
1368 | fn codegen<F, M>( |
1369 | &self, |
1370 | ctx: &BindgenContext, |
1371 | fields_should_be_private: bool, |
1372 | accessor_kind: FieldAccessorKind, |
1373 | parent: &CompInfo, |
1374 | result: &mut CodegenResult, |
1375 | struct_layout: &mut StructLayoutTracker, |
1376 | fields: &mut F, |
1377 | methods: &mut M, |
1378 | _: (), |
1379 | ) where |
1380 | F: Extend<proc_macro2::TokenStream>, |
1381 | M: Extend<proc_macro2::TokenStream>, |
1382 | { |
1383 | // Bitfields are handled by `FieldCodegen` implementations for |
1384 | // `BitfieldUnit` and `Bitfield`. |
1385 | assert!(self.bitfield_width().is_none()); |
1386 | |
1387 | let field_item = |
1388 | self.ty().into_resolver().through_type_refs().resolve(ctx); |
1389 | let field_ty = field_item.expect_type(); |
1390 | let mut ty = self.ty().to_rust_ty_or_opaque(ctx, &()); |
1391 | ty.append_implicit_template_params(ctx, field_item); |
1392 | |
1393 | // NB: If supported, we use proper `union` types. |
1394 | let ty = if parent.is_union() { |
1395 | wrap_union_field_if_needed(ctx, struct_layout, ty, result) |
1396 | } else if let Some(item) = field_ty.is_incomplete_array(ctx) { |
1397 | result.saw_incomplete_array(); |
1398 | |
1399 | let inner = item.to_rust_ty_or_opaque(ctx, &()); |
1400 | |
1401 | if ctx.options().enable_cxx_namespaces { |
1402 | quote! { |
1403 | root::__IncompleteArrayField<#inner> |
1404 | } |
1405 | } else { |
1406 | quote! { |
1407 | __IncompleteArrayField<#inner> |
1408 | } |
1409 | } |
1410 | } else { |
1411 | ty |
1412 | }; |
1413 | |
1414 | let mut field = quote! {}; |
1415 | if ctx.options().generate_comments { |
1416 | if let Some(raw_comment) = self.comment() { |
1417 | let comment = ctx.options().process_comment(raw_comment); |
1418 | field = attributes::doc(comment); |
1419 | } |
1420 | } |
1421 | |
1422 | let field_name = self |
1423 | .name() |
1424 | .map(|name| ctx.rust_mangle(name).into_owned()) |
1425 | .expect("Each field should have a name in codegen!" ); |
1426 | let field_ident = ctx.rust_ident_raw(field_name.as_str()); |
1427 | |
1428 | if let Some(padding_field) = |
1429 | struct_layout.saw_field(&field_name, field_ty, self.offset()) |
1430 | { |
1431 | fields.extend(Some(padding_field)); |
1432 | } |
1433 | |
1434 | let is_private = (!self.is_public() && |
1435 | ctx.options().respect_cxx_access_specs) || |
1436 | self.annotations() |
1437 | .private_fields() |
1438 | .unwrap_or(fields_should_be_private); |
1439 | |
1440 | let accessor_kind = |
1441 | self.annotations().accessor_kind().unwrap_or(accessor_kind); |
1442 | |
1443 | if is_private { |
1444 | field.append_all(quote! { |
1445 | #field_ident : #ty , |
1446 | }); |
1447 | } else { |
1448 | field.append_all(quote! { |
1449 | pub #field_ident : #ty , |
1450 | }); |
1451 | } |
1452 | |
1453 | fields.extend(Some(field)); |
1454 | |
1455 | // TODO: Factor the following code out, please! |
1456 | if accessor_kind == FieldAccessorKind::None { |
1457 | return; |
1458 | } |
1459 | |
1460 | let getter_name = ctx.rust_ident_raw(format!("get_ {}" , field_name)); |
1461 | let mutable_getter_name = |
1462 | ctx.rust_ident_raw(format!("get_ {}_mut" , field_name)); |
1463 | let field_name = ctx.rust_ident_raw(field_name); |
1464 | |
1465 | methods.extend(Some(match accessor_kind { |
1466 | FieldAccessorKind::None => unreachable!(), |
1467 | FieldAccessorKind::Regular => { |
1468 | quote! { |
1469 | #[inline] |
1470 | pub fn #getter_name(&self) -> & #ty { |
1471 | &self.#field_name |
1472 | } |
1473 | |
1474 | #[inline] |
1475 | pub fn #mutable_getter_name(&mut self) -> &mut #ty { |
1476 | &mut self.#field_name |
1477 | } |
1478 | } |
1479 | } |
1480 | FieldAccessorKind::Unsafe => { |
1481 | quote! { |
1482 | #[inline] |
1483 | pub unsafe fn #getter_name(&self) -> & #ty { |
1484 | &self.#field_name |
1485 | } |
1486 | |
1487 | #[inline] |
1488 | pub unsafe fn #mutable_getter_name(&mut self) -> &mut #ty { |
1489 | &mut self.#field_name |
1490 | } |
1491 | } |
1492 | } |
1493 | FieldAccessorKind::Immutable => { |
1494 | quote! { |
1495 | #[inline] |
1496 | pub fn #getter_name(&self) -> & #ty { |
1497 | &self.#field_name |
1498 | } |
1499 | } |
1500 | } |
1501 | })); |
1502 | } |
1503 | } |
1504 | |
1505 | impl BitfieldUnit { |
1506 | /// Get the constructor name for this bitfield unit. |
1507 | fn ctor_name(&self) -> proc_macro2::TokenStream { |
1508 | let ctor_name: Ident = Ident::new( |
1509 | &format!("new_bitfield_ {}" , self.nth()), |
1510 | Span::call_site(), |
1511 | ); |
1512 | quote! { |
1513 | #ctor_name |
1514 | } |
1515 | } |
1516 | } |
1517 | |
1518 | impl Bitfield { |
1519 | /// Extend an under construction bitfield unit constructor with this |
1520 | /// bitfield. This sets the relevant bits on the `__bindgen_bitfield_unit` |
1521 | /// variable that's being constructed. |
1522 | fn extend_ctor_impl( |
1523 | &self, |
1524 | ctx: &BindgenContext, |
1525 | param_name: proc_macro2::TokenStream, |
1526 | mut ctor_impl: proc_macro2::TokenStream, |
1527 | ) -> proc_macro2::TokenStream { |
1528 | let bitfield_ty = ctx.resolve_type(self.ty()); |
1529 | let bitfield_ty_layout = bitfield_ty |
1530 | .layout(ctx) |
1531 | .expect("Bitfield without layout? Gah!" ); |
1532 | let bitfield_int_ty = helpers::integer_type(ctx, bitfield_ty_layout) |
1533 | .expect( |
1534 | "Should already have verified that the bitfield is \ |
1535 | representable as an int" , |
1536 | ); |
1537 | |
1538 | let offset = self.offset_into_unit(); |
1539 | let width = self.width() as u8; |
1540 | let prefix = ctx.trait_prefix(); |
1541 | |
1542 | ctor_impl.append_all(quote! { |
1543 | __bindgen_bitfield_unit.set( |
1544 | #offset, |
1545 | #width, |
1546 | { |
1547 | let #param_name: #bitfield_int_ty = unsafe { |
1548 | ::#prefix::mem::transmute(#param_name) |
1549 | }; |
1550 | #param_name as u64 |
1551 | } |
1552 | ); |
1553 | }); |
1554 | |
1555 | ctor_impl |
1556 | } |
1557 | } |
1558 | |
1559 | fn access_specifier( |
1560 | ctx: &BindgenContext, |
1561 | is_pub: bool, |
1562 | ) -> proc_macro2::TokenStream { |
1563 | if is_pub || !ctx.options().respect_cxx_access_specs { |
1564 | quote! { pub } |
1565 | } else { |
1566 | quote! {} |
1567 | } |
1568 | } |
1569 | |
1570 | impl<'a> FieldCodegen<'a> for BitfieldUnit { |
1571 | type Extra = (); |
1572 | |
1573 | fn codegen<F, M>( |
1574 | &self, |
1575 | ctx: &BindgenContext, |
1576 | fields_should_be_private: bool, |
1577 | accessor_kind: FieldAccessorKind, |
1578 | parent: &CompInfo, |
1579 | result: &mut CodegenResult, |
1580 | struct_layout: &mut StructLayoutTracker, |
1581 | fields: &mut F, |
1582 | methods: &mut M, |
1583 | _: (), |
1584 | ) where |
1585 | F: Extend<proc_macro2::TokenStream>, |
1586 | M: Extend<proc_macro2::TokenStream>, |
1587 | { |
1588 | use crate::ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; |
1589 | |
1590 | result.saw_bitfield_unit(); |
1591 | |
1592 | let layout = self.layout(); |
1593 | let unit_field_ty = helpers::bitfield_unit(ctx, layout); |
1594 | let field_ty = if parent.is_union() { |
1595 | wrap_union_field_if_needed( |
1596 | ctx, |
1597 | struct_layout, |
1598 | unit_field_ty.clone(), |
1599 | result, |
1600 | ) |
1601 | } else { |
1602 | unit_field_ty.clone() |
1603 | }; |
1604 | |
1605 | { |
1606 | let align_field_name = format!("_bitfield_align_ {}" , self.nth()); |
1607 | let align_field_ident = ctx.rust_ident(align_field_name); |
1608 | let align_ty = match self.layout().align { |
1609 | n if n >= 8 => quote! { u64 }, |
1610 | 4 => quote! { u32 }, |
1611 | 2 => quote! { u16 }, |
1612 | _ => quote! { u8 }, |
1613 | }; |
1614 | let align_field = quote! { |
1615 | pub #align_field_ident: [#align_ty; 0], |
1616 | }; |
1617 | fields.extend(Some(align_field)); |
1618 | } |
1619 | |
1620 | let unit_field_name = format!("_bitfield_ {}" , self.nth()); |
1621 | let unit_field_ident = ctx.rust_ident(&unit_field_name); |
1622 | |
1623 | let ctor_name = self.ctor_name(); |
1624 | let mut ctor_params = vec![]; |
1625 | let mut ctor_impl = quote! {}; |
1626 | |
1627 | // We cannot generate any constructor if the underlying storage can't |
1628 | // implement AsRef<[u8]> / AsMut<[u8]> / etc, or can't derive Default. |
1629 | // |
1630 | // We don't check `larger_arrays` here because Default does still have |
1631 | // the 32 items limitation. |
1632 | let mut generate_ctor = layout.size <= RUST_DERIVE_IN_ARRAY_LIMIT; |
1633 | |
1634 | let mut access_spec = !fields_should_be_private; |
1635 | for bf in self.bitfields() { |
1636 | // Codegen not allowed for anonymous bitfields |
1637 | if bf.name().is_none() { |
1638 | continue; |
1639 | } |
1640 | |
1641 | if layout.size > RUST_DERIVE_IN_ARRAY_LIMIT && |
1642 | !ctx.options().rust_features().larger_arrays |
1643 | { |
1644 | continue; |
1645 | } |
1646 | |
1647 | access_spec &= bf.is_public(); |
1648 | let mut bitfield_representable_as_int = true; |
1649 | |
1650 | bf.codegen( |
1651 | ctx, |
1652 | fields_should_be_private, |
1653 | accessor_kind, |
1654 | parent, |
1655 | result, |
1656 | struct_layout, |
1657 | fields, |
1658 | methods, |
1659 | (&unit_field_name, &mut bitfield_representable_as_int), |
1660 | ); |
1661 | |
1662 | // Generating a constructor requires the bitfield to be representable as an integer. |
1663 | if !bitfield_representable_as_int { |
1664 | generate_ctor = false; |
1665 | continue; |
1666 | } |
1667 | |
1668 | let param_name = bitfield_getter_name(ctx, bf); |
1669 | let bitfield_ty_item = ctx.resolve_item(bf.ty()); |
1670 | let bitfield_ty = bitfield_ty_item.expect_type(); |
1671 | let bitfield_ty = |
1672 | bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); |
1673 | |
1674 | ctor_params.push(quote! { |
1675 | #param_name : #bitfield_ty |
1676 | }); |
1677 | ctor_impl = bf.extend_ctor_impl(ctx, param_name, ctor_impl); |
1678 | } |
1679 | |
1680 | let access_spec = access_specifier(ctx, access_spec); |
1681 | |
1682 | let field = quote! { |
1683 | #access_spec #unit_field_ident : #field_ty , |
1684 | }; |
1685 | fields.extend(Some(field)); |
1686 | |
1687 | if generate_ctor { |
1688 | methods.extend(Some(quote! { |
1689 | #[inline] |
1690 | #access_spec fn #ctor_name ( #( #ctor_params ),* ) -> #unit_field_ty { |
1691 | let mut __bindgen_bitfield_unit: #unit_field_ty = Default::default(); |
1692 | #ctor_impl |
1693 | __bindgen_bitfield_unit |
1694 | } |
1695 | })); |
1696 | } |
1697 | |
1698 | struct_layout.saw_bitfield_unit(layout); |
1699 | } |
1700 | } |
1701 | |
1702 | fn bitfield_getter_name( |
1703 | ctx: &BindgenContext, |
1704 | bitfield: &Bitfield, |
1705 | ) -> proc_macro2::TokenStream { |
1706 | let name: &str = bitfield.getter_name(); |
1707 | let name: Ident = ctx.rust_ident_raw(name); |
1708 | quote! { #name } |
1709 | } |
1710 | |
1711 | fn bitfield_setter_name( |
1712 | ctx: &BindgenContext, |
1713 | bitfield: &Bitfield, |
1714 | ) -> proc_macro2::TokenStream { |
1715 | let setter: &str = bitfield.setter_name(); |
1716 | let setter: Ident = ctx.rust_ident_raw(name:setter); |
1717 | quote! { #setter } |
1718 | } |
1719 | |
1720 | impl<'a> FieldCodegen<'a> for Bitfield { |
1721 | type Extra = (&'a str, &'a mut bool); |
1722 | |
1723 | fn codegen<F, M>( |
1724 | &self, |
1725 | ctx: &BindgenContext, |
1726 | fields_should_be_private: bool, |
1727 | _accessor_kind: FieldAccessorKind, |
1728 | parent: &CompInfo, |
1729 | _result: &mut CodegenResult, |
1730 | struct_layout: &mut StructLayoutTracker, |
1731 | _fields: &mut F, |
1732 | methods: &mut M, |
1733 | (unit_field_name, bitfield_representable_as_int): (&'a str, &mut bool), |
1734 | ) where |
1735 | F: Extend<proc_macro2::TokenStream>, |
1736 | M: Extend<proc_macro2::TokenStream>, |
1737 | { |
1738 | let prefix = ctx.trait_prefix(); |
1739 | let getter_name = bitfield_getter_name(ctx, self); |
1740 | let setter_name = bitfield_setter_name(ctx, self); |
1741 | let unit_field_ident = Ident::new(unit_field_name, Span::call_site()); |
1742 | |
1743 | let bitfield_ty_item = ctx.resolve_item(self.ty()); |
1744 | let bitfield_ty = bitfield_ty_item.expect_type(); |
1745 | |
1746 | let bitfield_ty_layout = bitfield_ty |
1747 | .layout(ctx) |
1748 | .expect("Bitfield without layout? Gah!" ); |
1749 | let bitfield_int_ty = |
1750 | match helpers::integer_type(ctx, bitfield_ty_layout) { |
1751 | Some(int_ty) => { |
1752 | *bitfield_representable_as_int = true; |
1753 | int_ty |
1754 | } |
1755 | None => { |
1756 | *bitfield_representable_as_int = false; |
1757 | return; |
1758 | } |
1759 | }; |
1760 | |
1761 | let bitfield_ty = |
1762 | bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); |
1763 | |
1764 | let offset = self.offset_into_unit(); |
1765 | let width = self.width() as u8; |
1766 | let access_spec = access_specifier( |
1767 | ctx, |
1768 | self.is_public() && !fields_should_be_private, |
1769 | ); |
1770 | |
1771 | if parent.is_union() && !struct_layout.is_rust_union() { |
1772 | methods.extend(Some(quote! { |
1773 | #[inline] |
1774 | #access_spec fn #getter_name(&self) -> #bitfield_ty { |
1775 | unsafe { |
1776 | ::#prefix::mem::transmute( |
1777 | self.#unit_field_ident.as_ref().get(#offset, #width) |
1778 | as #bitfield_int_ty |
1779 | ) |
1780 | } |
1781 | } |
1782 | |
1783 | #[inline] |
1784 | #access_spec fn #setter_name(&mut self, val: #bitfield_ty) { |
1785 | unsafe { |
1786 | let val: #bitfield_int_ty = ::#prefix::mem::transmute(val); |
1787 | self.#unit_field_ident.as_mut().set( |
1788 | #offset, |
1789 | #width, |
1790 | val as u64 |
1791 | ) |
1792 | } |
1793 | } |
1794 | })); |
1795 | } else { |
1796 | methods.extend(Some(quote! { |
1797 | #[inline] |
1798 | #access_spec fn #getter_name(&self) -> #bitfield_ty { |
1799 | unsafe { |
1800 | ::#prefix::mem::transmute( |
1801 | self.#unit_field_ident.get(#offset, #width) |
1802 | as #bitfield_int_ty |
1803 | ) |
1804 | } |
1805 | } |
1806 | |
1807 | #[inline] |
1808 | #access_spec fn #setter_name(&mut self, val: #bitfield_ty) { |
1809 | unsafe { |
1810 | let val: #bitfield_int_ty = ::#prefix::mem::transmute(val); |
1811 | self.#unit_field_ident.set( |
1812 | #offset, |
1813 | #width, |
1814 | val as u64 |
1815 | ) |
1816 | } |
1817 | } |
1818 | })); |
1819 | } |
1820 | } |
1821 | } |
1822 | |
1823 | impl CodeGenerator for CompInfo { |
1824 | type Extra = Item; |
1825 | type Return = (); |
1826 | |
1827 | fn codegen( |
1828 | &self, |
1829 | ctx: &BindgenContext, |
1830 | result: &mut CodegenResult<'_>, |
1831 | item: &Item, |
1832 | ) { |
1833 | debug!("<CompInfo as CodeGenerator>::codegen: item = {:?}" , item); |
1834 | debug_assert!(item.is_enabled_for_codegen(ctx)); |
1835 | |
1836 | // Don't output classes with template parameters that aren't types, and |
1837 | // also don't output template specializations, neither total or partial. |
1838 | if self.has_non_type_template_params() { |
1839 | return; |
1840 | } |
1841 | |
1842 | let ty = item.expect_type(); |
1843 | let layout = ty.layout(ctx); |
1844 | let mut packed = self.is_packed(ctx, layout.as_ref()); |
1845 | |
1846 | let canonical_name = item.canonical_name(ctx); |
1847 | let canonical_ident = ctx.rust_ident(&canonical_name); |
1848 | |
1849 | // Generate the vtable from the method list if appropriate. |
1850 | // |
1851 | // TODO: I don't know how this could play with virtual methods that are |
1852 | // not in the list of methods found by us, we'll see. Also, could the |
1853 | // order of the vtable pointers vary? |
1854 | // |
1855 | // FIXME: Once we generate proper vtables, we need to codegen the |
1856 | // vtable, but *not* generate a field for it in the case that |
1857 | // HasVtable::has_vtable_ptr is false but HasVtable::has_vtable is true. |
1858 | // |
1859 | // Also, we need to generate the vtable in such a way it "inherits" from |
1860 | // the parent too. |
1861 | let is_opaque = item.is_opaque(ctx, &()); |
1862 | let mut fields = vec![]; |
1863 | let mut struct_layout = |
1864 | StructLayoutTracker::new(ctx, self, ty, &canonical_name); |
1865 | |
1866 | if !is_opaque { |
1867 | if item.has_vtable_ptr(ctx) { |
1868 | let vtable = Vtable::new(item.id(), self); |
1869 | vtable.codegen(ctx, result, item); |
1870 | |
1871 | let vtable_type = vtable |
1872 | .try_to_rust_ty(ctx, &()) |
1873 | .expect("vtable to Rust type conversion is infallible" ) |
1874 | .to_ptr(true); |
1875 | |
1876 | fields.push(quote! { |
1877 | pub vtable_: #vtable_type , |
1878 | }); |
1879 | |
1880 | struct_layout.saw_vtable(); |
1881 | } |
1882 | |
1883 | for base in self.base_members() { |
1884 | if !base.requires_storage(ctx) { |
1885 | continue; |
1886 | } |
1887 | |
1888 | let inner_item = ctx.resolve_item(base.ty); |
1889 | let mut inner = inner_item.to_rust_ty_or_opaque(ctx, &()); |
1890 | inner.append_implicit_template_params(ctx, inner_item); |
1891 | let field_name = ctx.rust_ident(&base.field_name); |
1892 | |
1893 | struct_layout.saw_base(inner_item.expect_type()); |
1894 | |
1895 | let access_spec = access_specifier(ctx, base.is_public()); |
1896 | fields.push(quote! { |
1897 | #access_spec #field_name: #inner, |
1898 | }); |
1899 | } |
1900 | } |
1901 | |
1902 | let mut methods = vec![]; |
1903 | if !is_opaque { |
1904 | let fields_should_be_private = |
1905 | item.annotations().private_fields().unwrap_or(false); |
1906 | let struct_accessor_kind = item |
1907 | .annotations() |
1908 | .accessor_kind() |
1909 | .unwrap_or(FieldAccessorKind::None); |
1910 | for field in self.fields() { |
1911 | field.codegen( |
1912 | ctx, |
1913 | fields_should_be_private, |
1914 | struct_accessor_kind, |
1915 | self, |
1916 | result, |
1917 | &mut struct_layout, |
1918 | &mut fields, |
1919 | &mut methods, |
1920 | (), |
1921 | ); |
1922 | } |
1923 | // Check whether an explicit padding field is needed |
1924 | // at the end. |
1925 | if let Some(comp_layout) = layout { |
1926 | fields.extend( |
1927 | struct_layout |
1928 | .add_tail_padding(&canonical_name, comp_layout), |
1929 | ); |
1930 | } |
1931 | } |
1932 | |
1933 | if is_opaque { |
1934 | // Opaque item should not have generated methods, fields. |
1935 | debug_assert!(fields.is_empty()); |
1936 | debug_assert!(methods.is_empty()); |
1937 | } |
1938 | |
1939 | let is_union = self.kind() == CompKind::Union; |
1940 | let layout = item.kind().expect_type().layout(ctx); |
1941 | let zero_sized = item.is_zero_sized(ctx); |
1942 | let forward_decl = self.is_forward_declaration(); |
1943 | |
1944 | let mut explicit_align = None; |
1945 | |
1946 | // C++ requires every struct to be addressable, so what C++ compilers do |
1947 | // is making the struct 1-byte sized. |
1948 | // |
1949 | // This is apparently not the case for C, see: |
1950 | // https://github.com/rust-lang/rust-bindgen/issues/551 |
1951 | // |
1952 | // Just get the layout, and assume C++ if not. |
1953 | // |
1954 | // NOTE: This check is conveniently here to avoid the dummy fields we |
1955 | // may add for unused template parameters. |
1956 | if !forward_decl && zero_sized { |
1957 | let has_address = if is_opaque { |
1958 | // Generate the address field if it's an opaque type and |
1959 | // couldn't determine the layout of the blob. |
1960 | layout.is_none() |
1961 | } else { |
1962 | layout.map_or(true, |l| l.size != 0) |
1963 | }; |
1964 | |
1965 | if has_address { |
1966 | let layout = Layout::new(1, 1); |
1967 | let ty = helpers::blob(ctx, Layout::new(1, 1)); |
1968 | struct_layout.saw_field_with_layout( |
1969 | "_address" , |
1970 | layout, |
1971 | /* offset = */ Some(0), |
1972 | ); |
1973 | fields.push(quote! { |
1974 | pub _address: #ty, |
1975 | }); |
1976 | } |
1977 | } |
1978 | |
1979 | if is_opaque { |
1980 | match layout { |
1981 | Some(l) => { |
1982 | explicit_align = Some(l.align); |
1983 | |
1984 | let ty = helpers::blob(ctx, l); |
1985 | fields.push(quote! { |
1986 | pub _bindgen_opaque_blob: #ty , |
1987 | }); |
1988 | } |
1989 | None => { |
1990 | warn!("Opaque type without layout! Expect dragons!" ); |
1991 | } |
1992 | } |
1993 | } else if !is_union && !zero_sized { |
1994 | if let Some(padding_field) = |
1995 | layout.and_then(|layout| struct_layout.pad_struct(layout)) |
1996 | { |
1997 | fields.push(padding_field); |
1998 | } |
1999 | |
2000 | if let Some(layout) = layout { |
2001 | if struct_layout.requires_explicit_align(layout) { |
2002 | if layout.align == 1 { |
2003 | packed = true; |
2004 | } else { |
2005 | explicit_align = Some(layout.align); |
2006 | if !ctx.options().rust_features.repr_align { |
2007 | let ty = helpers::blob( |
2008 | ctx, |
2009 | Layout::new(0, layout.align), |
2010 | ); |
2011 | fields.push(quote! { |
2012 | pub __bindgen_align: #ty , |
2013 | }); |
2014 | } |
2015 | } |
2016 | } |
2017 | } |
2018 | } else if is_union && !forward_decl { |
2019 | // TODO(emilio): It'd be nice to unify this with the struct path |
2020 | // above somehow. |
2021 | let layout = layout.expect("Unable to get layout information?" ); |
2022 | if struct_layout.requires_explicit_align(layout) { |
2023 | explicit_align = Some(layout.align); |
2024 | } |
2025 | |
2026 | if !struct_layout.is_rust_union() { |
2027 | let ty = helpers::blob(ctx, layout); |
2028 | fields.push(quote! { |
2029 | pub bindgen_union_field: #ty , |
2030 | }) |
2031 | } |
2032 | } |
2033 | |
2034 | if forward_decl { |
2035 | fields.push(quote! { |
2036 | _unused: [u8; 0], |
2037 | }); |
2038 | } |
2039 | |
2040 | let mut generic_param_names = vec![]; |
2041 | |
2042 | for (idx, ty) in item.used_template_params(ctx).iter().enumerate() { |
2043 | let param = ctx.resolve_type(*ty); |
2044 | let name = param.name().unwrap(); |
2045 | let ident = ctx.rust_ident(name); |
2046 | generic_param_names.push(ident.clone()); |
2047 | |
2048 | let prefix = ctx.trait_prefix(); |
2049 | let field_name = ctx.rust_ident(format!("_phantom_ {}" , idx)); |
2050 | fields.push(quote! { |
2051 | pub #field_name : ::#prefix::marker::PhantomData< |
2052 | ::#prefix::cell::UnsafeCell<#ident> |
2053 | > , |
2054 | }); |
2055 | } |
2056 | |
2057 | let generics = if !generic_param_names.is_empty() { |
2058 | let generic_param_names = generic_param_names.clone(); |
2059 | quote! { |
2060 | < #( #generic_param_names ),* > |
2061 | } |
2062 | } else { |
2063 | quote! {} |
2064 | }; |
2065 | |
2066 | let mut attributes = vec![]; |
2067 | let mut needs_clone_impl = false; |
2068 | let mut needs_default_impl = false; |
2069 | let mut needs_debug_impl = false; |
2070 | let mut needs_partialeq_impl = false; |
2071 | if let Some(comment) = item.comment(ctx) { |
2072 | attributes.push(attributes::doc(comment)); |
2073 | } |
2074 | if packed && !is_opaque { |
2075 | let n = layout.map_or(1, |l| l.align); |
2076 | assert!(ctx.options().rust_features().repr_packed_n || n == 1); |
2077 | let packed_repr = if n == 1 { |
2078 | "packed" .to_string() |
2079 | } else { |
2080 | format!("packed( {})" , n) |
2081 | }; |
2082 | attributes.push(attributes::repr_list(&["C" , &packed_repr])); |
2083 | } else { |
2084 | attributes.push(attributes::repr("C" )); |
2085 | } |
2086 | |
2087 | if ctx.options().rust_features().repr_align { |
2088 | if let Some(explicit) = explicit_align { |
2089 | // Ensure that the struct has the correct alignment even in |
2090 | // presence of alignas. |
2091 | let explicit = helpers::ast_ty::int_expr(explicit as i64); |
2092 | attributes.push(quote! { |
2093 | #[repr(align(#explicit))] |
2094 | }); |
2095 | } |
2096 | } |
2097 | |
2098 | let derivable_traits = derives_of_item(item, ctx, packed); |
2099 | if !derivable_traits.contains(DerivableTraits::DEBUG) { |
2100 | needs_debug_impl = ctx.options().derive_debug && |
2101 | ctx.options().impl_debug && |
2102 | !ctx.no_debug_by_name(item) && |
2103 | !item.annotations().disallow_debug(); |
2104 | } |
2105 | |
2106 | if !derivable_traits.contains(DerivableTraits::DEFAULT) { |
2107 | needs_default_impl = ctx.options().derive_default && |
2108 | !self.is_forward_declaration() && |
2109 | !ctx.no_default_by_name(item) && |
2110 | !item.annotations().disallow_default(); |
2111 | } |
2112 | |
2113 | let all_template_params = item.all_template_params(ctx); |
2114 | |
2115 | if derivable_traits.contains(DerivableTraits::COPY) && |
2116 | !derivable_traits.contains(DerivableTraits::CLONE) |
2117 | { |
2118 | needs_clone_impl = true; |
2119 | } |
2120 | |
2121 | if !derivable_traits.contains(DerivableTraits::PARTIAL_EQ) { |
2122 | needs_partialeq_impl = ctx.options().derive_partialeq && |
2123 | ctx.options().impl_partialeq && |
2124 | ctx.lookup_can_derive_partialeq_or_partialord(item.id()) == |
2125 | CanDerive::Manually; |
2126 | } |
2127 | |
2128 | let mut derives: Vec<_> = derivable_traits.into(); |
2129 | derives.extend(item.annotations().derives().iter().map(String::as_str)); |
2130 | |
2131 | let is_rust_union = is_union && struct_layout.is_rust_union(); |
2132 | |
2133 | // The custom derives callback may return a list of derive attributes; |
2134 | // add them to the end of the list. |
2135 | let custom_derives = ctx.options().all_callbacks(|cb| { |
2136 | cb.add_derives(&DeriveInfo { |
2137 | name: &canonical_name, |
2138 | kind: if is_rust_union { |
2139 | DeriveTypeKind::Union |
2140 | } else { |
2141 | DeriveTypeKind::Struct |
2142 | }, |
2143 | }) |
2144 | }); |
2145 | // In most cases this will be a no-op, since custom_derives will be empty. |
2146 | derives.extend(custom_derives.iter().map(|s| s.as_str())); |
2147 | |
2148 | if !derives.is_empty() { |
2149 | attributes.push(attributes::derives(&derives)) |
2150 | } |
2151 | |
2152 | if item.must_use(ctx) { |
2153 | attributes.push(attributes::must_use()); |
2154 | } |
2155 | |
2156 | let mut tokens = if is_rust_union { |
2157 | quote! { |
2158 | #( #attributes )* |
2159 | pub union #canonical_ident |
2160 | } |
2161 | } else { |
2162 | quote! { |
2163 | #( #attributes )* |
2164 | pub struct #canonical_ident |
2165 | } |
2166 | }; |
2167 | |
2168 | tokens.append_all(quote! { |
2169 | #generics { |
2170 | #( #fields )* |
2171 | } |
2172 | }); |
2173 | result.push(tokens); |
2174 | |
2175 | // Generate the inner types and all that stuff. |
2176 | // |
2177 | // TODO: In the future we might want to be smart, and use nested |
2178 | // modules, and whatnot. |
2179 | for ty in self.inner_types() { |
2180 | let child_item = ctx.resolve_item(*ty); |
2181 | // assert_eq!(child_item.parent_id(), item.id()); |
2182 | child_item.codegen(ctx, result, &()); |
2183 | } |
2184 | |
2185 | // NOTE: Some unexposed attributes (like alignment attributes) may |
2186 | // affect layout, so we're bad and pray to the gods for avoid sending |
2187 | // all the tests to shit when parsing things like max_align_t. |
2188 | if self.found_unknown_attr() { |
2189 | warn!( |
2190 | "Type {} has an unknown attribute that may affect layout" , |
2191 | canonical_ident |
2192 | ); |
2193 | } |
2194 | |
2195 | if all_template_params.is_empty() { |
2196 | if !is_opaque { |
2197 | for var in self.inner_vars() { |
2198 | ctx.resolve_item(*var).codegen(ctx, result, &()); |
2199 | } |
2200 | } |
2201 | |
2202 | if ctx.options().layout_tests && !self.is_forward_declaration() { |
2203 | if let Some(layout) = layout { |
2204 | let fn_name = |
2205 | format!("bindgen_test_layout_ {}" , canonical_ident); |
2206 | let fn_name = ctx.rust_ident_raw(fn_name); |
2207 | let prefix = ctx.trait_prefix(); |
2208 | let size_of_expr = quote! { |
2209 | ::#prefix::mem::size_of::<#canonical_ident>() |
2210 | }; |
2211 | let align_of_expr = quote! { |
2212 | ::#prefix::mem::align_of::<#canonical_ident>() |
2213 | }; |
2214 | let size = layout.size; |
2215 | let align = layout.align; |
2216 | |
2217 | let check_struct_align = if align > |
2218 | ctx.target_pointer_size() && |
2219 | !ctx.options().rust_features().repr_align |
2220 | { |
2221 | None |
2222 | } else { |
2223 | Some(quote! { |
2224 | assert_eq!(#align_of_expr, |
2225 | #align, |
2226 | concat!("Alignment of " , stringify!(#canonical_ident))); |
2227 | |
2228 | }) |
2229 | }; |
2230 | |
2231 | let should_skip_field_offset_checks = is_opaque; |
2232 | |
2233 | let check_field_offset = if should_skip_field_offset_checks |
2234 | { |
2235 | vec![] |
2236 | } else { |
2237 | self.fields() |
2238 | .iter() |
2239 | .filter_map(|field| match *field { |
2240 | Field::DataMember(ref f) if f.name().is_some() => Some(f), |
2241 | _ => None, |
2242 | }) |
2243 | .flat_map(|field| { |
2244 | let name = field.name().unwrap(); |
2245 | field.offset().map(|offset| { |
2246 | let field_offset = offset / 8; |
2247 | let field_name = ctx.rust_ident(name); |
2248 | quote! { |
2249 | assert_eq!( |
2250 | unsafe { |
2251 | ::#prefix::ptr::addr_of!((*ptr).#field_name) as usize - ptr as usize |
2252 | }, |
2253 | #field_offset, |
2254 | concat!("Offset of field: " , stringify!(#canonical_ident), "::" , stringify!(#field_name)) |
2255 | ); |
2256 | } |
2257 | }) |
2258 | }) |
2259 | .collect() |
2260 | }; |
2261 | |
2262 | let uninit_decl = if !check_field_offset.is_empty() { |
2263 | // FIXME: When MSRV >= 1.59.0, we can use |
2264 | // > const PTR: *const #canonical_ident = ::#prefix::mem::MaybeUninit::uninit().as_ptr(); |
2265 | Some(quote! { |
2266 | // Use a shared MaybeUninit so that rustc with |
2267 | // opt-level=0 doesn't take too much stack space, |
2268 | // see #2218. |
2269 | const UNINIT: ::#prefix::mem::MaybeUninit<#canonical_ident> = ::#prefix::mem::MaybeUninit::uninit(); |
2270 | let ptr = UNINIT.as_ptr(); |
2271 | }) |
2272 | } else { |
2273 | None |
2274 | }; |
2275 | |
2276 | let item = quote! { |
2277 | #[test] |
2278 | fn #fn_name() { |
2279 | #uninit_decl |
2280 | assert_eq!(#size_of_expr, |
2281 | #size, |
2282 | concat!("Size of: " , stringify!(#canonical_ident))); |
2283 | #check_struct_align |
2284 | #( #check_field_offset )* |
2285 | } |
2286 | }; |
2287 | result.push(item); |
2288 | } |
2289 | } |
2290 | |
2291 | let mut method_names = Default::default(); |
2292 | if ctx.options().codegen_config.methods() { |
2293 | for method in self.methods() { |
2294 | assert!(method.kind() != MethodKind::Constructor); |
2295 | method.codegen_method( |
2296 | ctx, |
2297 | &mut methods, |
2298 | &mut method_names, |
2299 | result, |
2300 | self, |
2301 | ); |
2302 | } |
2303 | } |
2304 | |
2305 | if ctx.options().codegen_config.constructors() { |
2306 | for sig in self.constructors() { |
2307 | Method::new( |
2308 | MethodKind::Constructor, |
2309 | *sig, |
2310 | /* const */ |
2311 | false, |
2312 | ) |
2313 | .codegen_method( |
2314 | ctx, |
2315 | &mut methods, |
2316 | &mut method_names, |
2317 | result, |
2318 | self, |
2319 | ); |
2320 | } |
2321 | } |
2322 | |
2323 | if ctx.options().codegen_config.destructors() { |
2324 | if let Some((kind, destructor)) = self.destructor() { |
2325 | debug_assert!(kind.is_destructor()); |
2326 | Method::new(kind, destructor, false).codegen_method( |
2327 | ctx, |
2328 | &mut methods, |
2329 | &mut method_names, |
2330 | result, |
2331 | self, |
2332 | ); |
2333 | } |
2334 | } |
2335 | } |
2336 | |
2337 | // NB: We can't use to_rust_ty here since for opaque types this tries to |
2338 | // use the specialization knowledge to generate a blob field. |
2339 | let ty_for_impl = quote! { |
2340 | #canonical_ident #generics |
2341 | }; |
2342 | |
2343 | if needs_clone_impl { |
2344 | result.push(quote! { |
2345 | impl #generics Clone for #ty_for_impl { |
2346 | fn clone(&self) -> Self { *self } |
2347 | } |
2348 | }); |
2349 | } |
2350 | |
2351 | if needs_default_impl { |
2352 | let prefix = ctx.trait_prefix(); |
2353 | let body = if ctx.options().rust_features().maybe_uninit { |
2354 | quote! { |
2355 | let mut s = ::#prefix::mem::MaybeUninit::<Self>::uninit(); |
2356 | unsafe { |
2357 | ::#prefix::ptr::write_bytes(s.as_mut_ptr(), 0, 1); |
2358 | s.assume_init() |
2359 | } |
2360 | } |
2361 | } else { |
2362 | quote! { |
2363 | unsafe { |
2364 | let mut s: Self = ::#prefix::mem::uninitialized(); |
2365 | ::#prefix::ptr::write_bytes(&mut s, 0, 1); |
2366 | s |
2367 | } |
2368 | } |
2369 | }; |
2370 | // Note we use `ptr::write_bytes()` instead of `mem::zeroed()` because the latter does |
2371 | // not necessarily ensure padding bytes are zeroed. Some C libraries are sensitive to |
2372 | // non-zero padding bytes, especially when forwards/backwards compatability is |
2373 | // involved. |
2374 | result.push(quote! { |
2375 | impl #generics Default for #ty_for_impl { |
2376 | fn default() -> Self { |
2377 | #body |
2378 | } |
2379 | } |
2380 | }); |
2381 | } |
2382 | |
2383 | if needs_debug_impl { |
2384 | let impl_ = impl_debug::gen_debug_impl( |
2385 | ctx, |
2386 | self.fields(), |
2387 | item, |
2388 | self.kind(), |
2389 | ); |
2390 | |
2391 | let prefix = ctx.trait_prefix(); |
2392 | |
2393 | result.push(quote! { |
2394 | impl #generics ::#prefix::fmt::Debug for #ty_for_impl { |
2395 | #impl_ |
2396 | } |
2397 | }); |
2398 | } |
2399 | |
2400 | if needs_partialeq_impl { |
2401 | if let Some(impl_) = impl_partialeq::gen_partialeq_impl( |
2402 | ctx, |
2403 | self, |
2404 | item, |
2405 | &ty_for_impl, |
2406 | ) { |
2407 | let partialeq_bounds = if !generic_param_names.is_empty() { |
2408 | let bounds = generic_param_names.iter().map(|t| { |
2409 | quote! { #t: PartialEq } |
2410 | }); |
2411 | quote! { where #( #bounds ),* } |
2412 | } else { |
2413 | quote! {} |
2414 | }; |
2415 | |
2416 | let prefix = ctx.trait_prefix(); |
2417 | result.push(quote! { |
2418 | impl #generics ::#prefix::cmp::PartialEq for #ty_for_impl #partialeq_bounds { |
2419 | #impl_ |
2420 | } |
2421 | }); |
2422 | } |
2423 | } |
2424 | |
2425 | if !methods.is_empty() { |
2426 | result.push(quote! { |
2427 | impl #generics #ty_for_impl { |
2428 | #( #methods )* |
2429 | } |
2430 | }); |
2431 | } |
2432 | } |
2433 | } |
2434 | |
2435 | impl Method { |
2436 | fn codegen_method( |
2437 | &self, |
2438 | ctx: &BindgenContext, |
2439 | methods: &mut Vec<proc_macro2::TokenStream>, |
2440 | method_names: &mut HashSet<String>, |
2441 | result: &mut CodegenResult<'_>, |
2442 | _parent: &CompInfo, |
2443 | ) { |
2444 | assert!({ |
2445 | let cc = &ctx.options().codegen_config; |
2446 | match self.kind() { |
2447 | MethodKind::Constructor => cc.constructors(), |
2448 | MethodKind::Destructor => cc.destructors(), |
2449 | MethodKind::VirtualDestructor { .. } => cc.destructors(), |
2450 | MethodKind::Static | |
2451 | MethodKind::Normal | |
2452 | MethodKind::Virtual { .. } => cc.methods(), |
2453 | } |
2454 | }); |
2455 | |
2456 | // TODO(emilio): We could generate final stuff at least. |
2457 | if self.is_virtual() { |
2458 | return; // FIXME |
2459 | } |
2460 | |
2461 | // First of all, output the actual function. |
2462 | let function_item = ctx.resolve_item(self.signature()); |
2463 | if !function_item.process_before_codegen(ctx, result) { |
2464 | return; |
2465 | } |
2466 | let function = function_item.expect_function(); |
2467 | let times_seen = function.codegen(ctx, result, function_item); |
2468 | let times_seen = match times_seen { |
2469 | Some(seen) => seen, |
2470 | None => return, |
2471 | }; |
2472 | let signature_item = ctx.resolve_item(function.signature()); |
2473 | let mut name = match self.kind() { |
2474 | MethodKind::Constructor => "new" .into(), |
2475 | MethodKind::Destructor => "destruct" .into(), |
2476 | _ => function.name().to_owned(), |
2477 | }; |
2478 | |
2479 | let signature = match *signature_item.expect_type().kind() { |
2480 | TypeKind::Function(ref sig) => sig, |
2481 | _ => panic!("How in the world?" ), |
2482 | }; |
2483 | |
2484 | let supported_abi = match signature.abi(ctx, Some(&*name)) { |
2485 | ClangAbi::Known(Abi::ThisCall) => { |
2486 | ctx.options().rust_features().thiscall_abi |
2487 | } |
2488 | ClangAbi::Known(Abi::Vectorcall) => { |
2489 | ctx.options().rust_features().vectorcall_abi |
2490 | } |
2491 | ClangAbi::Known(Abi::CUnwind) => { |
2492 | ctx.options().rust_features().c_unwind_abi |
2493 | } |
2494 | _ => true, |
2495 | }; |
2496 | |
2497 | if !supported_abi { |
2498 | return; |
2499 | } |
2500 | |
2501 | // Do not generate variadic methods, since rust does not allow |
2502 | // implementing them, and we don't do a good job at it anyway. |
2503 | if signature.is_variadic() { |
2504 | return; |
2505 | } |
2506 | |
2507 | if method_names.contains(&name) { |
2508 | let mut count = 1; |
2509 | let mut new_name; |
2510 | |
2511 | while { |
2512 | new_name = format!(" {}{}" , name, count); |
2513 | method_names.contains(&new_name) |
2514 | } { |
2515 | count += 1; |
2516 | } |
2517 | |
2518 | name = new_name; |
2519 | } |
2520 | |
2521 | method_names.insert(name.clone()); |
2522 | |
2523 | let mut function_name = function_item.canonical_name(ctx); |
2524 | if times_seen > 0 { |
2525 | write!(&mut function_name, " {}" , times_seen).unwrap(); |
2526 | } |
2527 | let function_name = ctx.rust_ident(function_name); |
2528 | let mut args = utils::fnsig_arguments(ctx, signature); |
2529 | let mut ret = utils::fnsig_return_ty(ctx, signature); |
2530 | |
2531 | if !self.is_static() && !self.is_constructor() { |
2532 | args[0] = if self.is_const() { |
2533 | quote! { &self } |
2534 | } else { |
2535 | quote! { &mut self } |
2536 | }; |
2537 | } |
2538 | |
2539 | // If it's a constructor, we always return `Self`, and we inject the |
2540 | // "this" parameter, so there's no need to ask the user for it. |
2541 | // |
2542 | // Note that constructors in Clang are represented as functions with |
2543 | // return-type = void. |
2544 | if self.is_constructor() { |
2545 | args.remove(0); |
2546 | ret = quote! { -> Self }; |
2547 | } |
2548 | |
2549 | let mut exprs = |
2550 | helpers::ast_ty::arguments_from_signature(signature, ctx); |
2551 | |
2552 | let mut stmts = vec![]; |
2553 | |
2554 | // If it's a constructor, we need to insert an extra parameter with a |
2555 | // variable called `__bindgen_tmp` we're going to create. |
2556 | if self.is_constructor() { |
2557 | let prefix = ctx.trait_prefix(); |
2558 | let tmp_variable_decl = if ctx |
2559 | .options() |
2560 | .rust_features() |
2561 | .maybe_uninit |
2562 | { |
2563 | exprs[0] = quote! { |
2564 | __bindgen_tmp.as_mut_ptr() |
2565 | }; |
2566 | quote! { |
2567 | let mut __bindgen_tmp = ::#prefix::mem::MaybeUninit::uninit() |
2568 | } |
2569 | } else { |
2570 | exprs[0] = quote! { |
2571 | &mut __bindgen_tmp |
2572 | }; |
2573 | quote! { |
2574 | let mut __bindgen_tmp = ::#prefix::mem::uninitialized() |
2575 | } |
2576 | }; |
2577 | stmts.push(tmp_variable_decl); |
2578 | } else if !self.is_static() { |
2579 | assert!(!exprs.is_empty()); |
2580 | exprs[0] = quote! { |
2581 | self |
2582 | }; |
2583 | }; |
2584 | |
2585 | let call = quote! { |
2586 | #function_name (#( #exprs ),* ) |
2587 | }; |
2588 | |
2589 | stmts.push(call); |
2590 | |
2591 | if self.is_constructor() { |
2592 | stmts.push(if ctx.options().rust_features().maybe_uninit { |
2593 | quote! { |
2594 | __bindgen_tmp.assume_init() |
2595 | } |
2596 | } else { |
2597 | quote! { |
2598 | __bindgen_tmp |
2599 | } |
2600 | }) |
2601 | } |
2602 | |
2603 | let block = ctx.wrap_unsafe_ops(quote! ( #( #stmts );*)); |
2604 | |
2605 | let mut attrs = vec![attributes::inline()]; |
2606 | |
2607 | if signature.must_use() && |
2608 | ctx.options().rust_features().must_use_function |
2609 | { |
2610 | attrs.push(attributes::must_use()); |
2611 | } |
2612 | |
2613 | let name = ctx.rust_ident(&name); |
2614 | methods.push(quote! { |
2615 | #(#attrs)* |
2616 | pub unsafe fn #name ( #( #args ),* ) #ret { |
2617 | #block |
2618 | } |
2619 | }); |
2620 | } |
2621 | } |
2622 | |
2623 | /// A helper type that represents different enum variations. |
2624 | #[derive (Copy, Clone, PartialEq, Eq, Debug)] |
2625 | pub enum EnumVariation { |
2626 | /// The code for this enum will use a Rust enum. Note that creating this in unsafe code |
2627 | /// (including FFI) with an invalid value will invoke undefined behaviour, whether or not |
2628 | /// its marked as non_exhaustive. |
2629 | Rust { |
2630 | /// Indicates whether the generated struct should be `#[non_exhaustive]` |
2631 | non_exhaustive: bool, |
2632 | }, |
2633 | /// The code for this enum will use a newtype |
2634 | NewType { |
2635 | /// Indicates whether the newtype will have bitwise operators |
2636 | is_bitfield: bool, |
2637 | /// Indicates whether the variants will be represented as global constants |
2638 | is_global: bool, |
2639 | }, |
2640 | /// The code for this enum will use consts |
2641 | Consts, |
2642 | /// The code for this enum will use a module containing consts |
2643 | ModuleConsts, |
2644 | } |
2645 | |
2646 | impl EnumVariation { |
2647 | fn is_rust(&self) -> bool { |
2648 | matches!(*self, EnumVariation::Rust { .. }) |
2649 | } |
2650 | |
2651 | /// Both the `Const` and `ModuleConsts` variants will cause this to return |
2652 | /// true. |
2653 | fn is_const(&self) -> bool { |
2654 | matches!(*self, EnumVariation::Consts | EnumVariation::ModuleConsts) |
2655 | } |
2656 | } |
2657 | |
2658 | impl Default for EnumVariation { |
2659 | fn default() -> EnumVariation { |
2660 | EnumVariation::Consts |
2661 | } |
2662 | } |
2663 | |
2664 | impl std::str::FromStr for EnumVariation { |
2665 | type Err = std::io::Error; |
2666 | |
2667 | /// Create a `EnumVariation` from a string. |
2668 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
2669 | match s { |
2670 | "rust" => Ok(EnumVariation::Rust { |
2671 | non_exhaustive: false, |
2672 | }), |
2673 | "rust_non_exhaustive" => Ok(EnumVariation::Rust { |
2674 | non_exhaustive: true, |
2675 | }), |
2676 | "bitfield" => Ok(EnumVariation::NewType { |
2677 | is_bitfield: true, |
2678 | is_global: false, |
2679 | }), |
2680 | "consts" => Ok(EnumVariation::Consts), |
2681 | "moduleconsts" => Ok(EnumVariation::ModuleConsts), |
2682 | "newtype" => Ok(EnumVariation::NewType { |
2683 | is_bitfield: false, |
2684 | is_global: false, |
2685 | }), |
2686 | "newtype_global" => Ok(EnumVariation::NewType { |
2687 | is_bitfield: false, |
2688 | is_global: true, |
2689 | }), |
2690 | _ => Err(std::io::Error::new( |
2691 | std::io::ErrorKind::InvalidInput, |
2692 | concat!( |
2693 | "Got an invalid EnumVariation. Accepted values " , |
2694 | "are 'rust', 'rust_non_exhaustive', 'bitfield', 'consts'," , |
2695 | "'moduleconsts', 'newtype' and 'newtype_global'." |
2696 | ), |
2697 | )), |
2698 | } |
2699 | } |
2700 | } |
2701 | |
2702 | /// A helper type to construct different enum variations. |
2703 | enum EnumBuilder<'a> { |
2704 | Rust { |
2705 | attrs: Vec<proc_macro2::TokenStream>, |
2706 | ident: Ident, |
2707 | tokens: proc_macro2::TokenStream, |
2708 | emitted_any_variants: bool, |
2709 | }, |
2710 | NewType { |
2711 | canonical_name: &'a str, |
2712 | tokens: proc_macro2::TokenStream, |
2713 | is_bitfield: bool, |
2714 | is_global: bool, |
2715 | }, |
2716 | Consts { |
2717 | variants: Vec<proc_macro2::TokenStream>, |
2718 | }, |
2719 | ModuleConsts { |
2720 | module_name: &'a str, |
2721 | module_items: Vec<proc_macro2::TokenStream>, |
2722 | }, |
2723 | } |
2724 | |
2725 | impl<'a> EnumBuilder<'a> { |
2726 | /// Returns true if the builder is for a rustified enum. |
2727 | fn is_rust_enum(&self) -> bool { |
2728 | matches!(*self, EnumBuilder::Rust { .. }) |
2729 | } |
2730 | |
2731 | /// Create a new enum given an item builder, a canonical name, a name for |
2732 | /// the representation, and which variation it should be generated as. |
2733 | fn new( |
2734 | name: &'a str, |
2735 | mut attrs: Vec<proc_macro2::TokenStream>, |
2736 | repr: proc_macro2::TokenStream, |
2737 | enum_variation: EnumVariation, |
2738 | has_typedef: bool, |
2739 | ) -> Self { |
2740 | let ident = Ident::new(name, Span::call_site()); |
2741 | |
2742 | match enum_variation { |
2743 | EnumVariation::NewType { |
2744 | is_bitfield, |
2745 | is_global, |
2746 | } => EnumBuilder::NewType { |
2747 | canonical_name: name, |
2748 | tokens: quote! { |
2749 | #( #attrs )* |
2750 | pub struct #ident (pub #repr); |
2751 | }, |
2752 | is_bitfield, |
2753 | is_global, |
2754 | }, |
2755 | |
2756 | EnumVariation::Rust { .. } => { |
2757 | // `repr` is guaranteed to be Rustified in Enum::codegen |
2758 | attrs.insert(0, quote! { #[repr( #repr )] }); |
2759 | let tokens = quote!(); |
2760 | EnumBuilder::Rust { |
2761 | attrs, |
2762 | ident, |
2763 | tokens, |
2764 | emitted_any_variants: false, |
2765 | } |
2766 | } |
2767 | |
2768 | EnumVariation::Consts => { |
2769 | let mut variants = Vec::new(); |
2770 | |
2771 | if !has_typedef { |
2772 | variants.push(quote! { |
2773 | #( #attrs )* |
2774 | pub type #ident = #repr; |
2775 | }); |
2776 | } |
2777 | |
2778 | EnumBuilder::Consts { variants } |
2779 | } |
2780 | |
2781 | EnumVariation::ModuleConsts => { |
2782 | let ident = Ident::new( |
2783 | CONSTIFIED_ENUM_MODULE_REPR_NAME, |
2784 | Span::call_site(), |
2785 | ); |
2786 | let type_definition = quote! { |
2787 | #( #attrs )* |
2788 | pub type #ident = #repr; |
2789 | }; |
2790 | |
2791 | EnumBuilder::ModuleConsts { |
2792 | module_name: name, |
2793 | module_items: vec![type_definition], |
2794 | } |
2795 | } |
2796 | } |
2797 | } |
2798 | |
2799 | /// Add a variant to this enum. |
2800 | fn with_variant( |
2801 | self, |
2802 | ctx: &BindgenContext, |
2803 | variant: &EnumVariant, |
2804 | mangling_prefix: Option<&str>, |
2805 | rust_ty: proc_macro2::TokenStream, |
2806 | result: &mut CodegenResult<'_>, |
2807 | is_ty_named: bool, |
2808 | ) -> Self { |
2809 | let variant_name = ctx.rust_mangle(variant.name()); |
2810 | let is_rust_enum = self.is_rust_enum(); |
2811 | let expr = match variant.val() { |
2812 | EnumVariantValue::Boolean(v) if is_rust_enum => { |
2813 | helpers::ast_ty::uint_expr(v as u64) |
2814 | } |
2815 | EnumVariantValue::Boolean(v) => quote!(#v), |
2816 | EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v), |
2817 | EnumVariantValue::Unsigned(v) => helpers::ast_ty::uint_expr(v), |
2818 | }; |
2819 | |
2820 | let mut doc = quote! {}; |
2821 | if ctx.options().generate_comments { |
2822 | if let Some(raw_comment) = variant.comment() { |
2823 | let comment = ctx.options().process_comment(raw_comment); |
2824 | doc = attributes::doc(comment); |
2825 | } |
2826 | } |
2827 | |
2828 | match self { |
2829 | EnumBuilder::Rust { |
2830 | attrs, |
2831 | ident, |
2832 | tokens, |
2833 | emitted_any_variants: _, |
2834 | } => { |
2835 | let name = ctx.rust_ident(variant_name); |
2836 | EnumBuilder::Rust { |
2837 | attrs, |
2838 | ident, |
2839 | tokens: quote! { |
2840 | #tokens |
2841 | #doc |
2842 | #name = #expr, |
2843 | }, |
2844 | emitted_any_variants: true, |
2845 | } |
2846 | } |
2847 | |
2848 | EnumBuilder::NewType { |
2849 | canonical_name, |
2850 | is_global, |
2851 | .. |
2852 | } => { |
2853 | if ctx.options().rust_features().associated_const && |
2854 | is_ty_named && |
2855 | !is_global |
2856 | { |
2857 | let enum_ident = ctx.rust_ident(canonical_name); |
2858 | let variant_ident = ctx.rust_ident(variant_name); |
2859 | |
2860 | result.push(quote! { |
2861 | impl #enum_ident { |
2862 | #doc |
2863 | pub const #variant_ident : #rust_ty = #rust_ty ( #expr ); |
2864 | } |
2865 | }); |
2866 | } else { |
2867 | let ident = ctx.rust_ident(match mangling_prefix { |
2868 | Some(prefix) => { |
2869 | Cow::Owned(format!(" {}_ {}" , prefix, variant_name)) |
2870 | } |
2871 | None => variant_name, |
2872 | }); |
2873 | result.push(quote! { |
2874 | #doc |
2875 | pub const #ident : #rust_ty = #rust_ty ( #expr ); |
2876 | }); |
2877 | } |
2878 | |
2879 | self |
2880 | } |
2881 | |
2882 | EnumBuilder::Consts { .. } => { |
2883 | let constant_name = match mangling_prefix { |
2884 | Some(prefix) => { |
2885 | Cow::Owned(format!(" {}_ {}" , prefix, variant_name)) |
2886 | } |
2887 | None => variant_name, |
2888 | }; |
2889 | |
2890 | let ident = ctx.rust_ident(constant_name); |
2891 | result.push(quote! { |
2892 | #doc |
2893 | pub const #ident : #rust_ty = #expr ; |
2894 | }); |
2895 | |
2896 | self |
2897 | } |
2898 | EnumBuilder::ModuleConsts { |
2899 | module_name, |
2900 | mut module_items, |
2901 | } => { |
2902 | let name = ctx.rust_ident(variant_name); |
2903 | let ty = ctx.rust_ident(CONSTIFIED_ENUM_MODULE_REPR_NAME); |
2904 | module_items.push(quote! { |
2905 | #doc |
2906 | pub const #name : #ty = #expr ; |
2907 | }); |
2908 | |
2909 | EnumBuilder::ModuleConsts { |
2910 | module_name, |
2911 | module_items, |
2912 | } |
2913 | } |
2914 | } |
2915 | } |
2916 | |
2917 | fn build( |
2918 | self, |
2919 | ctx: &BindgenContext, |
2920 | rust_ty: proc_macro2::TokenStream, |
2921 | result: &mut CodegenResult<'_>, |
2922 | ) -> proc_macro2::TokenStream { |
2923 | match self { |
2924 | EnumBuilder::Rust { |
2925 | attrs, |
2926 | ident, |
2927 | tokens, |
2928 | emitted_any_variants, |
2929 | .. |
2930 | } => { |
2931 | let variants = if !emitted_any_variants { |
2932 | quote!(__bindgen_cannot_repr_c_on_empty_enum = 0) |
2933 | } else { |
2934 | tokens |
2935 | }; |
2936 | |
2937 | quote! { |
2938 | #( #attrs )* |
2939 | pub enum #ident { |
2940 | #variants |
2941 | } |
2942 | } |
2943 | } |
2944 | EnumBuilder::NewType { |
2945 | canonical_name, |
2946 | tokens, |
2947 | is_bitfield, |
2948 | .. |
2949 | } => { |
2950 | if !is_bitfield { |
2951 | return tokens; |
2952 | } |
2953 | |
2954 | let rust_ty_name = ctx.rust_ident_raw(canonical_name); |
2955 | let prefix = ctx.trait_prefix(); |
2956 | |
2957 | result.push(quote! { |
2958 | impl ::#prefix::ops::BitOr<#rust_ty> for #rust_ty { |
2959 | type Output = Self; |
2960 | |
2961 | #[inline] |
2962 | fn bitor(self, other: Self) -> Self { |
2963 | #rust_ty_name(self.0 | other.0) |
2964 | } |
2965 | } |
2966 | }); |
2967 | |
2968 | result.push(quote! { |
2969 | impl ::#prefix::ops::BitOrAssign for #rust_ty { |
2970 | #[inline] |
2971 | fn bitor_assign(&mut self, rhs: #rust_ty) { |
2972 | self.0 |= rhs.0; |
2973 | } |
2974 | } |
2975 | }); |
2976 | |
2977 | result.push(quote! { |
2978 | impl ::#prefix::ops::BitAnd<#rust_ty> for #rust_ty { |
2979 | type Output = Self; |
2980 | |
2981 | #[inline] |
2982 | fn bitand(self, other: Self) -> Self { |
2983 | #rust_ty_name(self.0 & other.0) |
2984 | } |
2985 | } |
2986 | }); |
2987 | |
2988 | result.push(quote! { |
2989 | impl ::#prefix::ops::BitAndAssign for #rust_ty { |
2990 | #[inline] |
2991 | fn bitand_assign(&mut self, rhs: #rust_ty) { |
2992 | self.0 &= rhs.0; |
2993 | } |
2994 | } |
2995 | }); |
2996 | |
2997 | tokens |
2998 | } |
2999 | EnumBuilder::Consts { variants, .. } => quote! { #( #variants )* }, |
3000 | EnumBuilder::ModuleConsts { |
3001 | module_items, |
3002 | module_name, |
3003 | .. |
3004 | } => { |
3005 | let ident = ctx.rust_ident(module_name); |
3006 | quote! { |
3007 | pub mod #ident { |
3008 | #( #module_items )* |
3009 | } |
3010 | } |
3011 | } |
3012 | } |
3013 | } |
3014 | } |
3015 | |
3016 | impl CodeGenerator for Enum { |
3017 | type Extra = Item; |
3018 | type Return = (); |
3019 | |
3020 | fn codegen( |
3021 | &self, |
3022 | ctx: &BindgenContext, |
3023 | result: &mut CodegenResult<'_>, |
3024 | item: &Item, |
3025 | ) { |
3026 | debug!("<Enum as CodeGenerator>::codegen: item = {:?}" , item); |
3027 | debug_assert!(item.is_enabled_for_codegen(ctx)); |
3028 | |
3029 | let name = item.canonical_name(ctx); |
3030 | let ident = ctx.rust_ident(&name); |
3031 | let enum_ty = item.expect_type(); |
3032 | let layout = enum_ty.layout(ctx); |
3033 | let variation = self.computed_enum_variation(ctx, item); |
3034 | |
3035 | let repr_translated; |
3036 | let repr = match self.repr().map(|repr| ctx.resolve_type(repr)) { |
3037 | Some(repr) |
3038 | if !ctx.options().translate_enum_integer_types && |
3039 | !variation.is_rust() => |
3040 | { |
3041 | repr |
3042 | } |
3043 | repr => { |
3044 | // An enum's integer type is translated to a native Rust |
3045 | // integer type in 3 cases: |
3046 | // * the enum is Rustified and we need a translated type for |
3047 | // the repr attribute |
3048 | // * the representation couldn't be determined from the C source |
3049 | // * it was explicitly requested as a bindgen option |
3050 | |
3051 | let kind = match repr { |
3052 | Some(repr) => match *repr.canonical_type(ctx).kind() { |
3053 | TypeKind::Int(int_kind) => int_kind, |
3054 | _ => panic!("Unexpected type as enum repr" ), |
3055 | }, |
3056 | None => { |
3057 | warn!( |
3058 | "Guessing type of enum! Forward declarations of enums \ |
3059 | shouldn't be legal!" |
3060 | ); |
3061 | IntKind::Int |
3062 | } |
3063 | }; |
3064 | |
3065 | let signed = kind.is_signed(); |
3066 | let size = layout |
3067 | .map(|l| l.size) |
3068 | .or_else(|| kind.known_size()) |
3069 | .unwrap_or(0); |
3070 | |
3071 | let translated = match (signed, size) { |
3072 | (true, 1) => IntKind::I8, |
3073 | (false, 1) => IntKind::U8, |
3074 | (true, 2) => IntKind::I16, |
3075 | (false, 2) => IntKind::U16, |
3076 | (true, 4) => IntKind::I32, |
3077 | (false, 4) => IntKind::U32, |
3078 | (true, 8) => IntKind::I64, |
3079 | (false, 8) => IntKind::U64, |
3080 | _ => { |
3081 | warn!( |
3082 | "invalid enum decl: signed: {}, size: {}" , |
3083 | signed, size |
3084 | ); |
3085 | IntKind::I32 |
3086 | } |
3087 | }; |
3088 | |
3089 | repr_translated = |
3090 | Type::new(None, None, TypeKind::Int(translated), false); |
3091 | &repr_translated |
3092 | } |
3093 | }; |
3094 | |
3095 | let mut attrs = vec![]; |
3096 | |
3097 | // TODO(emilio): Delegate this to the builders? |
3098 | match variation { |
3099 | EnumVariation::Rust { non_exhaustive } => { |
3100 | if non_exhaustive && |
3101 | ctx.options().rust_features().non_exhaustive |
3102 | { |
3103 | attrs.push(attributes::non_exhaustive()); |
3104 | } else if non_exhaustive && |
3105 | !ctx.options().rust_features().non_exhaustive |
3106 | { |
3107 | panic!("The rust target you're using doesn't seem to support non_exhaustive enums" ); |
3108 | } |
3109 | } |
3110 | EnumVariation::NewType { .. } => { |
3111 | if ctx.options().rust_features.repr_transparent { |
3112 | attrs.push(attributes::repr("transparent" )); |
3113 | } else { |
3114 | attrs.push(attributes::repr("C" )); |
3115 | } |
3116 | } |
3117 | _ => {} |
3118 | }; |
3119 | |
3120 | if let Some(comment) = item.comment(ctx) { |
3121 | attrs.push(attributes::doc(comment)); |
3122 | } |
3123 | |
3124 | if item.must_use(ctx) { |
3125 | attrs.push(attributes::must_use()); |
3126 | } |
3127 | |
3128 | if !variation.is_const() { |
3129 | let packed = false; // Enums can't be packed in Rust. |
3130 | let mut derives = derives_of_item(item, ctx, packed); |
3131 | // For backwards compat, enums always derive |
3132 | // Clone/Eq/PartialEq/Hash, even if we don't generate those by |
3133 | // default. |
3134 | derives.insert( |
3135 | DerivableTraits::CLONE | |
3136 | DerivableTraits::HASH | |
3137 | DerivableTraits::PARTIAL_EQ | |
3138 | DerivableTraits::EQ, |
3139 | ); |
3140 | let mut derives: Vec<_> = derives.into(); |
3141 | for derive in item.annotations().derives().iter() { |
3142 | if !derives.contains(&derive.as_str()) { |
3143 | derives.push(derive); |
3144 | } |
3145 | } |
3146 | |
3147 | // The custom derives callback may return a list of derive attributes; |
3148 | // add them to the end of the list. |
3149 | let custom_derives = ctx.options().all_callbacks(|cb| { |
3150 | cb.add_derives(&DeriveInfo { |
3151 | name: &name, |
3152 | kind: DeriveTypeKind::Enum, |
3153 | }) |
3154 | }); |
3155 | // In most cases this will be a no-op, since custom_derives will be empty. |
3156 | derives.extend(custom_derives.iter().map(|s| s.as_str())); |
3157 | |
3158 | attrs.push(attributes::derives(&derives)); |
3159 | } |
3160 | |
3161 | fn add_constant( |
3162 | ctx: &BindgenContext, |
3163 | enum_: &Type, |
3164 | // Only to avoid recomputing every time. |
3165 | enum_canonical_name: &Ident, |
3166 | // May be the same as "variant" if it's because the |
3167 | // enum is unnamed and we still haven't seen the |
3168 | // value. |
3169 | variant_name: &Ident, |
3170 | referenced_name: &Ident, |
3171 | enum_rust_ty: proc_macro2::TokenStream, |
3172 | result: &mut CodegenResult<'_>, |
3173 | ) { |
3174 | let constant_name = if enum_.name().is_some() { |
3175 | if ctx.options().prepend_enum_name { |
3176 | format!(" {}_ {}" , enum_canonical_name, variant_name) |
3177 | } else { |
3178 | format!(" {}" , variant_name) |
3179 | } |
3180 | } else { |
3181 | format!(" {}" , variant_name) |
3182 | }; |
3183 | let constant_name = ctx.rust_ident(constant_name); |
3184 | |
3185 | result.push(quote! { |
3186 | pub const #constant_name : #enum_rust_ty = |
3187 | #enum_canonical_name :: #referenced_name ; |
3188 | }); |
3189 | } |
3190 | |
3191 | let repr = repr.to_rust_ty_or_opaque(ctx, item); |
3192 | let has_typedef = ctx.is_enum_typedef_combo(item.id()); |
3193 | |
3194 | let mut builder = |
3195 | EnumBuilder::new(&name, attrs, repr, variation, has_typedef); |
3196 | |
3197 | // A map where we keep a value -> variant relation. |
3198 | let mut seen_values = HashMap::<_, Ident>::default(); |
3199 | let enum_rust_ty = item.to_rust_ty_or_opaque(ctx, &()); |
3200 | let is_toplevel = item.is_toplevel(ctx); |
3201 | |
3202 | // Used to mangle the constants we generate in the unnamed-enum case. |
3203 | let parent_canonical_name = if is_toplevel { |
3204 | None |
3205 | } else { |
3206 | Some(item.parent_id().canonical_name(ctx)) |
3207 | }; |
3208 | |
3209 | let constant_mangling_prefix = if ctx.options().prepend_enum_name { |
3210 | if enum_ty.name().is_none() { |
3211 | parent_canonical_name.as_deref() |
3212 | } else { |
3213 | Some(&*name) |
3214 | } |
3215 | } else { |
3216 | None |
3217 | }; |
3218 | |
3219 | // NB: We defer the creation of constified variants, in case we find |
3220 | // another variant with the same value (which is the common thing to |
3221 | // do). |
3222 | let mut constified_variants = VecDeque::new(); |
3223 | |
3224 | let mut iter = self.variants().iter().peekable(); |
3225 | while let Some(variant) = |
3226 | iter.next().or_else(|| constified_variants.pop_front()) |
3227 | { |
3228 | if variant.hidden() { |
3229 | continue; |
3230 | } |
3231 | |
3232 | if variant.force_constification() && iter.peek().is_some() { |
3233 | constified_variants.push_back(variant); |
3234 | continue; |
3235 | } |
3236 | |
3237 | match seen_values.entry(variant.val()) { |
3238 | Entry::Occupied(ref entry) => { |
3239 | if variation.is_rust() { |
3240 | let variant_name = ctx.rust_mangle(variant.name()); |
3241 | let mangled_name = |
3242 | if is_toplevel || enum_ty.name().is_some() { |
3243 | variant_name |
3244 | } else { |
3245 | let parent_name = |
3246 | parent_canonical_name.as_ref().unwrap(); |
3247 | |
3248 | Cow::Owned(format!( |
3249 | " {}_ {}" , |
3250 | parent_name, variant_name |
3251 | )) |
3252 | }; |
3253 | |
3254 | let existing_variant_name = entry.get(); |
3255 | // Use associated constants for named enums. |
3256 | if enum_ty.name().is_some() && |
3257 | ctx.options().rust_features().associated_const |
3258 | { |
3259 | let enum_canonical_name = &ident; |
3260 | let variant_name = |
3261 | ctx.rust_ident_raw(&*mangled_name); |
3262 | result.push(quote! { |
3263 | impl #enum_rust_ty { |
3264 | pub const #variant_name : #enum_rust_ty = |
3265 | #enum_canonical_name :: #existing_variant_name ; |
3266 | } |
3267 | }); |
3268 | } else { |
3269 | add_constant( |
3270 | ctx, |
3271 | enum_ty, |
3272 | &ident, |
3273 | &Ident::new(&mangled_name, Span::call_site()), |
3274 | existing_variant_name, |
3275 | enum_rust_ty.clone(), |
3276 | result, |
3277 | ); |
3278 | } |
3279 | } else { |
3280 | builder = builder.with_variant( |
3281 | ctx, |
3282 | variant, |
3283 | constant_mangling_prefix, |
3284 | enum_rust_ty.clone(), |
3285 | result, |
3286 | enum_ty.name().is_some(), |
3287 | ); |
3288 | } |
3289 | } |
3290 | Entry::Vacant(entry) => { |
3291 | builder = builder.with_variant( |
3292 | ctx, |
3293 | variant, |
3294 | constant_mangling_prefix, |
3295 | enum_rust_ty.clone(), |
3296 | result, |
3297 | enum_ty.name().is_some(), |
3298 | ); |
3299 | |
3300 | let variant_name = ctx.rust_ident(variant.name()); |
3301 | |
3302 | // If it's an unnamed enum, or constification is enforced, |
3303 | // we also generate a constant so it can be properly |
3304 | // accessed. |
3305 | if (variation.is_rust() && enum_ty.name().is_none()) || |
3306 | variant.force_constification() |
3307 | { |
3308 | let mangled_name = if is_toplevel { |
3309 | variant_name.clone() |
3310 | } else { |
3311 | let parent_name = |
3312 | parent_canonical_name.as_ref().unwrap(); |
3313 | |
3314 | Ident::new( |
3315 | &format!(" {}_ {}" , parent_name, variant_name), |
3316 | Span::call_site(), |
3317 | ) |
3318 | }; |
3319 | |
3320 | add_constant( |
3321 | ctx, |
3322 | enum_ty, |
3323 | &ident, |
3324 | &mangled_name, |
3325 | &variant_name, |
3326 | enum_rust_ty.clone(), |
3327 | result, |
3328 | ); |
3329 | } |
3330 | |
3331 | entry.insert(variant_name); |
3332 | } |
3333 | } |
3334 | } |
3335 | |
3336 | let item = builder.build(ctx, enum_rust_ty, result); |
3337 | result.push(item); |
3338 | } |
3339 | } |
3340 | |
3341 | /// Enum for the default type of macro constants. |
3342 | #[derive (Copy, Clone, PartialEq, Eq, Debug)] |
3343 | pub enum MacroTypeVariation { |
3344 | /// Use i32 or i64 |
3345 | Signed, |
3346 | /// Use u32 or u64 |
3347 | Unsigned, |
3348 | } |
3349 | |
3350 | impl MacroTypeVariation { |
3351 | /// Convert a `MacroTypeVariation` to its str representation. |
3352 | pub fn as_str(&self) -> &str { |
3353 | match self { |
3354 | MacroTypeVariation::Signed => "signed" , |
3355 | MacroTypeVariation::Unsigned => "unsigned" , |
3356 | } |
3357 | } |
3358 | } |
3359 | |
3360 | impl Default for MacroTypeVariation { |
3361 | fn default() -> MacroTypeVariation { |
3362 | MacroTypeVariation::Unsigned |
3363 | } |
3364 | } |
3365 | |
3366 | impl std::str::FromStr for MacroTypeVariation { |
3367 | type Err = std::io::Error; |
3368 | |
3369 | /// Create a `MacroTypeVariation` from a string. |
3370 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
3371 | match s { |
3372 | "signed" => Ok(MacroTypeVariation::Signed), |
3373 | "unsigned" => Ok(MacroTypeVariation::Unsigned), |
3374 | _ => Err(std::io::Error::new( |
3375 | kind:std::io::ErrorKind::InvalidInput, |
3376 | error:concat!( |
3377 | "Got an invalid MacroTypeVariation. Accepted values " , |
3378 | "are 'signed' and 'unsigned'" |
3379 | ), |
3380 | )), |
3381 | } |
3382 | } |
3383 | } |
3384 | |
3385 | /// Enum for how aliases should be translated. |
3386 | #[derive (Copy, Clone, PartialEq, Eq, Debug)] |
3387 | pub enum AliasVariation { |
3388 | /// Convert to regular Rust alias |
3389 | TypeAlias, |
3390 | /// Create a new type by wrapping the old type in a struct and using #[repr(transparent)] |
3391 | NewType, |
3392 | /// Same as NewStruct but also impl Deref to be able to use the methods of the wrapped type |
3393 | NewTypeDeref, |
3394 | } |
3395 | |
3396 | impl AliasVariation { |
3397 | /// Convert an `AliasVariation` to its str representation. |
3398 | pub fn as_str(&self) -> &str { |
3399 | match self { |
3400 | AliasVariation::TypeAlias => "type_alias" , |
3401 | AliasVariation::NewType => "new_type" , |
3402 | AliasVariation::NewTypeDeref => "new_type_deref" , |
3403 | } |
3404 | } |
3405 | } |
3406 | |
3407 | impl Default for AliasVariation { |
3408 | fn default() -> AliasVariation { |
3409 | AliasVariation::TypeAlias |
3410 | } |
3411 | } |
3412 | |
3413 | impl std::str::FromStr for AliasVariation { |
3414 | type Err = std::io::Error; |
3415 | |
3416 | /// Create an `AliasVariation` from a string. |
3417 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
3418 | match s { |
3419 | "type_alias" => Ok(AliasVariation::TypeAlias), |
3420 | "new_type" => Ok(AliasVariation::NewType), |
3421 | "new_type_deref" => Ok(AliasVariation::NewTypeDeref), |
3422 | _ => Err(std::io::Error::new( |
3423 | kind:std::io::ErrorKind::InvalidInput, |
3424 | error:concat!( |
3425 | "Got an invalid AliasVariation. Accepted values " , |
3426 | "are 'type_alias', 'new_type', and 'new_type_deref'" |
3427 | ), |
3428 | )), |
3429 | } |
3430 | } |
3431 | } |
3432 | |
3433 | /// Enum for how non-Copy unions should be translated. |
3434 | #[derive (Copy, Clone, PartialEq, Eq, Debug)] |
3435 | pub enum NonCopyUnionStyle { |
3436 | /// Wrap members in a type generated by bindgen. |
3437 | BindgenWrapper, |
3438 | /// Wrap members in [`::core::mem::ManuallyDrop`]. |
3439 | /// |
3440 | /// Note: `ManuallyDrop` was stabilized in Rust 1.20.0, do not use it if your |
3441 | /// MSRV is lower. |
3442 | ManuallyDrop, |
3443 | } |
3444 | |
3445 | impl NonCopyUnionStyle { |
3446 | /// Convert an `NonCopyUnionStyle` to its str representation. |
3447 | pub fn as_str(&self) -> &'static str { |
3448 | match self { |
3449 | Self::BindgenWrapper => "bindgen_wrapper" , |
3450 | Self::ManuallyDrop => "manually_drop" , |
3451 | } |
3452 | } |
3453 | } |
3454 | |
3455 | impl Default for NonCopyUnionStyle { |
3456 | fn default() -> Self { |
3457 | Self::BindgenWrapper |
3458 | } |
3459 | } |
3460 | |
3461 | impl std::str::FromStr for NonCopyUnionStyle { |
3462 | type Err = std::io::Error; |
3463 | |
3464 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
3465 | match s { |
3466 | "bindgen_wrapper" => Ok(Self::BindgenWrapper), |
3467 | "manually_drop" => Ok(Self::ManuallyDrop), |
3468 | _ => Err(std::io::Error::new( |
3469 | kind:std::io::ErrorKind::InvalidInput, |
3470 | error:concat!( |
3471 | "Got an invalid NonCopyUnionStyle. Accepted values " , |
3472 | "are 'bindgen_wrapper' and 'manually_drop'" |
3473 | ), |
3474 | )), |
3475 | } |
3476 | } |
3477 | } |
3478 | |
3479 | /// Fallible conversion to an opaque blob. |
3480 | /// |
3481 | /// Implementors of this trait should provide the `try_get_layout` method to |
3482 | /// fallibly get this thing's layout, which the provided `try_to_opaque` trait |
3483 | /// method will use to convert the `Layout` into an opaque blob Rust type. |
3484 | trait TryToOpaque { |
3485 | type Extra; |
3486 | |
3487 | /// Get the layout for this thing, if one is available. |
3488 | fn try_get_layout( |
3489 | &self, |
3490 | ctx: &BindgenContext, |
3491 | extra: &Self::Extra, |
3492 | ) -> error::Result<Layout>; |
3493 | |
3494 | /// Do not override this provided trait method. |
3495 | fn try_to_opaque( |
3496 | &self, |
3497 | ctx: &BindgenContext, |
3498 | extra: &Self::Extra, |
3499 | ) -> error::Result<proc_macro2::TokenStream> { |
3500 | self.try_get_layout(ctx, extra) |
3501 | .map(|layout: Layout| helpers::blob(ctx, layout)) |
3502 | } |
3503 | } |
3504 | |
3505 | /// Infallible conversion of an IR thing to an opaque blob. |
3506 | /// |
3507 | /// The resulting layout is best effort, and is unfortunately not guaranteed to |
3508 | /// be correct. When all else fails, we fall back to a single byte layout as a |
3509 | /// last resort, because C++ does not permit zero-sized types. See the note in |
3510 | /// the `ToRustTyOrOpaque` doc comment about fallible versus infallible traits |
3511 | /// and when each is appropriate. |
3512 | /// |
3513 | /// Don't implement this directly. Instead implement `TryToOpaque`, and then |
3514 | /// leverage the blanket impl for this trait. |
3515 | trait ToOpaque: TryToOpaque { |
3516 | fn get_layout(&self, ctx: &BindgenContext, extra: &Self::Extra) -> Layout { |
3517 | self.try_get_layout(ctx, extra) |
3518 | .unwrap_or_else(|_| Layout::for_size(ctx, size:1)) |
3519 | } |
3520 | |
3521 | fn to_opaque( |
3522 | &self, |
3523 | ctx: &BindgenContext, |
3524 | extra: &Self::Extra, |
3525 | ) -> proc_macro2::TokenStream { |
3526 | let layout: Layout = self.get_layout(ctx, extra); |
3527 | helpers::blob(ctx, layout) |
3528 | } |
3529 | } |
3530 | |
3531 | impl<T> ToOpaque for T where T: TryToOpaque {} |
3532 | |
3533 | /// Fallible conversion from an IR thing to an *equivalent* Rust type. |
3534 | /// |
3535 | /// If the C/C++ construct represented by the IR thing cannot (currently) be |
3536 | /// represented in Rust (for example, instantiations of templates with |
3537 | /// const-value generic parameters) then the impl should return an `Err`. It |
3538 | /// should *not* attempt to return an opaque blob with the correct size and |
3539 | /// alignment. That is the responsibility of the `TryToOpaque` trait. |
3540 | trait TryToRustTy { |
3541 | type Extra; |
3542 | |
3543 | fn try_to_rust_ty( |
3544 | &self, |
3545 | ctx: &BindgenContext, |
3546 | extra: &Self::Extra, |
3547 | ) -> error::Result<proc_macro2::TokenStream>; |
3548 | } |
3549 | |
3550 | /// Fallible conversion to a Rust type or an opaque blob with the correct size |
3551 | /// and alignment. |
3552 | /// |
3553 | /// Don't implement this directly. Instead implement `TryToRustTy` and |
3554 | /// `TryToOpaque`, and then leverage the blanket impl for this trait below. |
3555 | trait TryToRustTyOrOpaque: TryToRustTy + TryToOpaque { |
3556 | type Extra; |
3557 | |
3558 | fn try_to_rust_ty_or_opaque( |
3559 | &self, |
3560 | ctx: &BindgenContext, |
3561 | extra: &<Self as TryToRustTyOrOpaque>::Extra, |
3562 | ) -> error::Result<proc_macro2::TokenStream>; |
3563 | } |
3564 | |
3565 | impl<E, T> TryToRustTyOrOpaque for T |
3566 | where |
3567 | T: TryToRustTy<Extra = E> + TryToOpaque<Extra = E>, |
3568 | { |
3569 | type Extra = E; |
3570 | |
3571 | fn try_to_rust_ty_or_opaque( |
3572 | &self, |
3573 | ctx: &BindgenContext, |
3574 | extra: &E, |
3575 | ) -> error::Result<proc_macro2::TokenStream> { |
3576 | self.try_to_rust_ty(ctx, extra).or_else(|_| { |
3577 | if let Ok(layout: Layout) = self.try_get_layout(ctx, extra) { |
3578 | Ok(helpers::blob(ctx, layout)) |
3579 | } else { |
3580 | Err(error::Error::NoLayoutForOpaqueBlob) |
3581 | } |
3582 | }) |
3583 | } |
3584 | } |
3585 | |
3586 | /// Infallible conversion to a Rust type, or an opaque blob with a best effort |
3587 | /// of correct size and alignment. |
3588 | /// |
3589 | /// Don't implement this directly. Instead implement `TryToRustTy` and |
3590 | /// `TryToOpaque`, and then leverage the blanket impl for this trait below. |
3591 | /// |
3592 | /// ### Fallible vs. Infallible Conversions to Rust Types |
3593 | /// |
3594 | /// When should one use this infallible `ToRustTyOrOpaque` trait versus the |
3595 | /// fallible `TryTo{RustTy, Opaque, RustTyOrOpaque}` triats? All fallible trait |
3596 | /// implementations that need to convert another thing into a Rust type or |
3597 | /// opaque blob in a nested manner should also use fallible trait methods and |
3598 | /// propagate failure up the stack. Only infallible functions and methods like |
3599 | /// CodeGenerator implementations should use the infallible |
3600 | /// `ToRustTyOrOpaque`. The further out we push error recovery, the more likely |
3601 | /// we are to get a usable `Layout` even if we can't generate an equivalent Rust |
3602 | /// type for a C++ construct. |
3603 | trait ToRustTyOrOpaque: TryToRustTy + ToOpaque { |
3604 | type Extra; |
3605 | |
3606 | fn to_rust_ty_or_opaque( |
3607 | &self, |
3608 | ctx: &BindgenContext, |
3609 | extra: &<Self as ToRustTyOrOpaque>::Extra, |
3610 | ) -> proc_macro2::TokenStream; |
3611 | } |
3612 | |
3613 | impl<E, T> ToRustTyOrOpaque for T |
3614 | where |
3615 | T: TryToRustTy<Extra = E> + ToOpaque<Extra = E>, |
3616 | { |
3617 | type Extra = E; |
3618 | |
3619 | fn to_rust_ty_or_opaque( |
3620 | &self, |
3621 | ctx: &BindgenContext, |
3622 | extra: &E, |
3623 | ) -> proc_macro2::TokenStream { |
3624 | self.try_to_rust_ty(ctx, extra) |
3625 | .unwrap_or_else(|_| self.to_opaque(ctx, extra)) |
3626 | } |
3627 | } |
3628 | |
3629 | impl<T> TryToOpaque for T |
3630 | where |
3631 | T: Copy + Into<ItemId>, |
3632 | { |
3633 | type Extra = (); |
3634 | |
3635 | fn try_get_layout( |
3636 | &self, |
3637 | ctx: &BindgenContext, |
3638 | _: &(), |
3639 | ) -> error::Result<Layout> { |
3640 | ctx.resolve_item((*self).into()).try_get_layout(ctx, &()) |
3641 | } |
3642 | } |
3643 | |
3644 | impl<T> TryToRustTy for T |
3645 | where |
3646 | T: Copy + Into<ItemId>, |
3647 | { |
3648 | type Extra = (); |
3649 | |
3650 | fn try_to_rust_ty( |
3651 | &self, |
3652 | ctx: &BindgenContext, |
3653 | _: &(), |
3654 | ) -> error::Result<proc_macro2::TokenStream> { |
3655 | ctx.resolve_item((*self).into()).try_to_rust_ty(ctx, &()) |
3656 | } |
3657 | } |
3658 | |
3659 | impl TryToOpaque for Item { |
3660 | type Extra = (); |
3661 | |
3662 | fn try_get_layout( |
3663 | &self, |
3664 | ctx: &BindgenContext, |
3665 | _: &(), |
3666 | ) -> error::Result<Layout> { |
3667 | self.kind().expect_type().try_get_layout(ctx, self) |
3668 | } |
3669 | } |
3670 | |
3671 | impl TryToRustTy for Item { |
3672 | type Extra = (); |
3673 | |
3674 | fn try_to_rust_ty( |
3675 | &self, |
3676 | ctx: &BindgenContext, |
3677 | _: &(), |
3678 | ) -> error::Result<proc_macro2::TokenStream> { |
3679 | self.kind().expect_type().try_to_rust_ty(ctx, self) |
3680 | } |
3681 | } |
3682 | |
3683 | impl TryToOpaque for Type { |
3684 | type Extra = Item; |
3685 | |
3686 | fn try_get_layout( |
3687 | &self, |
3688 | ctx: &BindgenContext, |
3689 | _: &Item, |
3690 | ) -> error::Result<Layout> { |
3691 | self.layout(ctx).ok_or(err:error::Error::NoLayoutForOpaqueBlob) |
3692 | } |
3693 | } |
3694 | |
3695 | impl TryToRustTy for Type { |
3696 | type Extra = Item; |
3697 | |
3698 | fn try_to_rust_ty( |
3699 | &self, |
3700 | ctx: &BindgenContext, |
3701 | item: &Item, |
3702 | ) -> error::Result<proc_macro2::TokenStream> { |
3703 | use self::helpers::ast_ty::*; |
3704 | |
3705 | match *self.kind() { |
3706 | TypeKind::Void => Ok(c_void(ctx)), |
3707 | // TODO: we should do something smart with nullptr, or maybe *const |
3708 | // c_void is enough? |
3709 | TypeKind::NullPtr => Ok(c_void(ctx).to_ptr(true)), |
3710 | TypeKind::Int(ik) => { |
3711 | match ik { |
3712 | IntKind::Bool => Ok(quote! { bool }), |
3713 | IntKind::Char { .. } => Ok(raw_type(ctx, "c_char" )), |
3714 | IntKind::SChar => Ok(raw_type(ctx, "c_schar" )), |
3715 | IntKind::UChar => Ok(raw_type(ctx, "c_uchar" )), |
3716 | IntKind::Short => Ok(raw_type(ctx, "c_short" )), |
3717 | IntKind::UShort => Ok(raw_type(ctx, "c_ushort" )), |
3718 | IntKind::Int => Ok(raw_type(ctx, "c_int" )), |
3719 | IntKind::UInt => Ok(raw_type(ctx, "c_uint" )), |
3720 | IntKind::Long => Ok(raw_type(ctx, "c_long" )), |
3721 | IntKind::ULong => Ok(raw_type(ctx, "c_ulong" )), |
3722 | IntKind::LongLong => Ok(raw_type(ctx, "c_longlong" )), |
3723 | IntKind::ULongLong => Ok(raw_type(ctx, "c_ulonglong" )), |
3724 | IntKind::WChar => { |
3725 | let layout = self |
3726 | .layout(ctx) |
3727 | .expect("Couldn't compute wchar_t's layout?" ); |
3728 | let ty = Layout::known_type_for_size(ctx, layout.size) |
3729 | .expect("Non-representable wchar_t?" ); |
3730 | let ident = ctx.rust_ident_raw(ty); |
3731 | Ok(quote! { #ident }) |
3732 | } |
3733 | |
3734 | IntKind::I8 => Ok(quote! { i8 }), |
3735 | IntKind::U8 => Ok(quote! { u8 }), |
3736 | IntKind::I16 => Ok(quote! { i16 }), |
3737 | IntKind::U16 => Ok(quote! { u16 }), |
3738 | IntKind::I32 => Ok(quote! { i32 }), |
3739 | IntKind::U32 => Ok(quote! { u32 }), |
3740 | IntKind::I64 => Ok(quote! { i64 }), |
3741 | IntKind::U64 => Ok(quote! { u64 }), |
3742 | IntKind::Custom { name, .. } => { |
3743 | Ok(proc_macro2::TokenStream::from_str(name).unwrap()) |
3744 | } |
3745 | IntKind::U128 => { |
3746 | Ok(if ctx.options().rust_features.i128_and_u128 { |
3747 | quote! { u128 } |
3748 | } else { |
3749 | // Best effort thing, but wrong alignment |
3750 | // unfortunately. |
3751 | quote! { [u64; 2] } |
3752 | }) |
3753 | } |
3754 | IntKind::I128 => { |
3755 | Ok(if ctx.options().rust_features.i128_and_u128 { |
3756 | quote! { i128 } |
3757 | } else { |
3758 | quote! { [u64; 2] } |
3759 | }) |
3760 | } |
3761 | } |
3762 | } |
3763 | TypeKind::Float(fk) => { |
3764 | Ok(float_kind_rust_type(ctx, fk, self.layout(ctx))) |
3765 | } |
3766 | TypeKind::Complex(fk) => { |
3767 | let float_path = |
3768 | float_kind_rust_type(ctx, fk, self.layout(ctx)); |
3769 | |
3770 | ctx.generated_bindgen_complex(); |
3771 | Ok(if ctx.options().enable_cxx_namespaces { |
3772 | quote! { |
3773 | root::__BindgenComplex<#float_path> |
3774 | } |
3775 | } else { |
3776 | quote! { |
3777 | __BindgenComplex<#float_path> |
3778 | } |
3779 | }) |
3780 | } |
3781 | TypeKind::Function(ref fs) => { |
3782 | // We can't rely on the sizeof(Option<NonZero<_>>) == |
3783 | // sizeof(NonZero<_>) optimization with opaque blobs (because |
3784 | // they aren't NonZero), so don't *ever* use an or_opaque |
3785 | // variant here. |
3786 | let ty = fs.try_to_rust_ty(ctx, &())?; |
3787 | |
3788 | let prefix = ctx.trait_prefix(); |
3789 | Ok(quote! { |
3790 | ::#prefix::option::Option<#ty> |
3791 | }) |
3792 | } |
3793 | TypeKind::Array(item, len) | TypeKind::Vector(item, len) => { |
3794 | let ty = item.try_to_rust_ty(ctx, &())?; |
3795 | Ok(quote! { |
3796 | [ #ty ; #len ] |
3797 | }) |
3798 | } |
3799 | TypeKind::Enum(..) => { |
3800 | let path = item.namespace_aware_canonical_path(ctx); |
3801 | let path = proc_macro2::TokenStream::from_str(&path.join("::" )) |
3802 | .unwrap(); |
3803 | Ok(quote!(#path)) |
3804 | } |
3805 | TypeKind::TemplateInstantiation(ref inst) => { |
3806 | inst.try_to_rust_ty(ctx, item) |
3807 | } |
3808 | TypeKind::ResolvedTypeRef(inner) => inner.try_to_rust_ty(ctx, &()), |
3809 | TypeKind::TemplateAlias(..) | |
3810 | TypeKind::Alias(..) | |
3811 | TypeKind::BlockPointer(..) => { |
3812 | if self.is_block_pointer() && !ctx.options().generate_block { |
3813 | let void = c_void(ctx); |
3814 | return Ok(void.to_ptr(/* is_const = */ false)); |
3815 | } |
3816 | |
3817 | if item.is_opaque(ctx, &()) && |
3818 | item.used_template_params(ctx) |
3819 | .into_iter() |
3820 | .any(|param| param.is_template_param(ctx, &())) |
3821 | { |
3822 | self.try_to_opaque(ctx, item) |
3823 | } else if let Some(ty) = self |
3824 | .name() |
3825 | .and_then(|name| utils::type_from_named(ctx, name)) |
3826 | { |
3827 | Ok(ty) |
3828 | } else { |
3829 | utils::build_path(item, ctx) |
3830 | } |
3831 | } |
3832 | TypeKind::Comp(ref info) => { |
3833 | let template_params = item.all_template_params(ctx); |
3834 | if info.has_non_type_template_params() || |
3835 | (item.is_opaque(ctx, &()) && !template_params.is_empty()) |
3836 | { |
3837 | return self.try_to_opaque(ctx, item); |
3838 | } |
3839 | |
3840 | utils::build_path(item, ctx) |
3841 | } |
3842 | TypeKind::Opaque => self.try_to_opaque(ctx, item), |
3843 | TypeKind::Pointer(inner) | TypeKind::Reference(inner) => { |
3844 | let is_const = ctx.resolve_type(inner).is_const(); |
3845 | |
3846 | let inner = |
3847 | inner.into_resolver().through_type_refs().resolve(ctx); |
3848 | let inner_ty = inner.expect_type(); |
3849 | |
3850 | let is_objc_pointer = |
3851 | matches!(inner_ty.kind(), TypeKind::ObjCInterface(..)); |
3852 | |
3853 | // Regardless if we can properly represent the inner type, we |
3854 | // should always generate a proper pointer here, so use |
3855 | // infallible conversion of the inner type. |
3856 | let mut ty = inner.to_rust_ty_or_opaque(ctx, &()); |
3857 | ty.append_implicit_template_params(ctx, inner); |
3858 | |
3859 | // Avoid the first function pointer level, since it's already |
3860 | // represented in Rust. |
3861 | if inner_ty.canonical_type(ctx).is_function() || is_objc_pointer |
3862 | { |
3863 | Ok(ty) |
3864 | } else { |
3865 | Ok(ty.to_ptr(is_const)) |
3866 | } |
3867 | } |
3868 | TypeKind::TypeParam => { |
3869 | let name = item.canonical_name(ctx); |
3870 | let ident = ctx.rust_ident(name); |
3871 | Ok(quote! { |
3872 | #ident |
3873 | }) |
3874 | } |
3875 | TypeKind::ObjCSel => Ok(quote! { |
3876 | objc::runtime::Sel |
3877 | }), |
3878 | TypeKind::ObjCId => Ok(quote! { |
3879 | id |
3880 | }), |
3881 | TypeKind::ObjCInterface(ref interface) => { |
3882 | let name = ctx.rust_ident(interface.name()); |
3883 | Ok(quote! { |
3884 | #name |
3885 | }) |
3886 | } |
3887 | ref u @ TypeKind::UnresolvedTypeRef(..) => { |
3888 | unreachable!("Should have been resolved after parsing {:?}!" , u) |
3889 | } |
3890 | } |
3891 | } |
3892 | } |
3893 | |
3894 | impl TryToOpaque for TemplateInstantiation { |
3895 | type Extra = Item; |
3896 | |
3897 | fn try_get_layout( |
3898 | &self, |
3899 | ctx: &BindgenContext, |
3900 | item: &Item, |
3901 | ) -> error::Result<Layout> { |
3902 | item.expect_type() |
3903 | .layout(ctx) |
3904 | .ok_or(err:error::Error::NoLayoutForOpaqueBlob) |
3905 | } |
3906 | } |
3907 | |
3908 | impl TryToRustTy for TemplateInstantiation { |
3909 | type Extra = Item; |
3910 | |
3911 | fn try_to_rust_ty( |
3912 | &self, |
3913 | ctx: &BindgenContext, |
3914 | item: &Item, |
3915 | ) -> error::Result<proc_macro2::TokenStream> { |
3916 | if self.is_opaque(ctx, item) { |
3917 | return Err(error::Error::InstantiationOfOpaqueType); |
3918 | } |
3919 | |
3920 | let def = self |
3921 | .template_definition() |
3922 | .into_resolver() |
3923 | .through_type_refs() |
3924 | .resolve(ctx); |
3925 | |
3926 | let mut ty = quote! {}; |
3927 | let def_path = def.namespace_aware_canonical_path(ctx); |
3928 | ty.append_separated( |
3929 | def_path.into_iter().map(|p| ctx.rust_ident(p)), |
3930 | quote!(::), |
3931 | ); |
3932 | |
3933 | let def_params = def.self_template_params(ctx); |
3934 | if def_params.is_empty() { |
3935 | // This can happen if we generated an opaque type for a partial |
3936 | // template specialization, and we've hit an instantiation of |
3937 | // that partial specialization. |
3938 | extra_assert!(def.is_opaque(ctx, &())); |
3939 | return Err(error::Error::InstantiationOfOpaqueType); |
3940 | } |
3941 | |
3942 | // TODO: If the definition type is a template class/struct |
3943 | // definition's member template definition, it could rely on |
3944 | // generic template parameters from its outer template |
3945 | // class/struct. When we emit bindings for it, it could require |
3946 | // *more* type arguments than we have here, and we will need to |
3947 | // reconstruct them somehow. We don't have any means of doing |
3948 | // that reconstruction at this time. |
3949 | |
3950 | let template_args = self |
3951 | .template_arguments() |
3952 | .iter() |
3953 | .zip(def_params.iter()) |
3954 | // Only pass type arguments for the type parameters that |
3955 | // the def uses. |
3956 | .filter(|&(_, param)| ctx.uses_template_parameter(def.id(), *param)) |
3957 | .map(|(arg, _)| { |
3958 | let arg = arg.into_resolver().through_type_refs().resolve(ctx); |
3959 | let mut ty = arg.try_to_rust_ty(ctx, &())?; |
3960 | ty.append_implicit_template_params(ctx, arg); |
3961 | Ok(ty) |
3962 | }) |
3963 | .collect::<error::Result<Vec<_>>>()?; |
3964 | |
3965 | if template_args.is_empty() { |
3966 | return Ok(ty); |
3967 | } |
3968 | |
3969 | Ok(quote! { |
3970 | #ty < #( #template_args ),* > |
3971 | }) |
3972 | } |
3973 | } |
3974 | |
3975 | impl TryToRustTy for FunctionSig { |
3976 | type Extra = (); |
3977 | |
3978 | fn try_to_rust_ty( |
3979 | &self, |
3980 | ctx: &BindgenContext, |
3981 | _: &(), |
3982 | ) -> error::Result<proc_macro2::TokenStream> { |
3983 | // TODO: we might want to consider ignoring the reference return value. |
3984 | let ret = utils::fnsig_return_ty(ctx, self); |
3985 | let arguments = utils::fnsig_arguments(ctx, self); |
3986 | let abi = self.abi(ctx, None); |
3987 | |
3988 | match abi { |
3989 | ClangAbi::Known(Abi::ThisCall) |
3990 | if !ctx.options().rust_features().thiscall_abi => |
3991 | { |
3992 | warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target" ); |
3993 | Ok(proc_macro2::TokenStream::new()) |
3994 | } |
3995 | ClangAbi::Known(Abi::Vectorcall) |
3996 | if !ctx.options().rust_features().vectorcall_abi => |
3997 | { |
3998 | warn!("Skipping function with vectorcall ABI that isn't supported by the configured Rust target" ); |
3999 | Ok(proc_macro2::TokenStream::new()) |
4000 | } |
4001 | ClangAbi::Known(Abi::CUnwind) |
4002 | if !ctx.options().rust_features().c_unwind_abi => |
4003 | { |
4004 | warn!("Skipping function with C-unwind ABI that isn't supported by the configured Rust target" ); |
4005 | Ok(proc_macro2::TokenStream::new()) |
4006 | } |
4007 | _ => Ok(quote! { |
4008 | unsafe extern #abi fn ( #( #arguments ),* ) #ret |
4009 | }), |
4010 | } |
4011 | } |
4012 | } |
4013 | |
4014 | impl CodeGenerator for Function { |
4015 | type Extra = Item; |
4016 | |
4017 | /// If we've actually generated the symbol, the number of times we've seen |
4018 | /// it. |
4019 | type Return = Option<u32>; |
4020 | |
4021 | fn codegen( |
4022 | &self, |
4023 | ctx: &BindgenContext, |
4024 | result: &mut CodegenResult<'_>, |
4025 | item: &Item, |
4026 | ) -> Self::Return { |
4027 | debug!("<Function as CodeGenerator>::codegen: item = {:?}" , item); |
4028 | debug_assert!(item.is_enabled_for_codegen(ctx)); |
4029 | |
4030 | let is_internal = matches!(self.linkage(), Linkage::Internal); |
4031 | |
4032 | if is_internal { |
4033 | if ctx.options().wrap_static_fns { |
4034 | result.items_to_serialize.push(item.id()); |
4035 | } else { |
4036 | // We can't do anything with Internal functions if we are not wrapping them so just |
4037 | // avoid generating anything for them. |
4038 | return None; |
4039 | } |
4040 | } |
4041 | |
4042 | // Pure virtual methods have no actual symbol, so we can't generate |
4043 | // something meaningful for them. |
4044 | let is_dynamic_function = match self.kind() { |
4045 | FunctionKind::Method(ref method_kind) |
4046 | if method_kind.is_pure_virtual() => |
4047 | { |
4048 | return None; |
4049 | } |
4050 | FunctionKind::Function => { |
4051 | ctx.options().dynamic_library_name.is_some() |
4052 | } |
4053 | _ => false, |
4054 | }; |
4055 | |
4056 | // Similar to static member variables in a class template, we can't |
4057 | // generate bindings to template functions, because the set of |
4058 | // instantiations is open ended and we have no way of knowing which |
4059 | // monomorphizations actually exist. |
4060 | if !item.all_template_params(ctx).is_empty() { |
4061 | return None; |
4062 | } |
4063 | |
4064 | let name = self.name(); |
4065 | let mut canonical_name = item.canonical_name(ctx); |
4066 | let mangled_name = self.mangled_name(); |
4067 | |
4068 | { |
4069 | let seen_symbol_name = mangled_name.unwrap_or(&canonical_name); |
4070 | |
4071 | // TODO: Maybe warn here if there's a type/argument mismatch, or |
4072 | // something? |
4073 | if result.seen_function(seen_symbol_name) { |
4074 | return None; |
4075 | } |
4076 | result.saw_function(seen_symbol_name); |
4077 | } |
4078 | |
4079 | let signature_item = ctx.resolve_item(self.signature()); |
4080 | let signature = signature_item.kind().expect_type().canonical_type(ctx); |
4081 | let signature = match *signature.kind() { |
4082 | TypeKind::Function(ref sig) => sig, |
4083 | _ => panic!("Signature kind is not a Function: {:?}" , signature), |
4084 | }; |
4085 | |
4086 | let args = utils::fnsig_arguments(ctx, signature); |
4087 | let ret = utils::fnsig_return_ty(ctx, signature); |
4088 | |
4089 | let mut attributes = vec![]; |
4090 | |
4091 | if ctx.options().rust_features().must_use_function { |
4092 | let must_use = signature.must_use() || { |
4093 | let ret_ty = signature |
4094 | .return_type() |
4095 | .into_resolver() |
4096 | .through_type_refs() |
4097 | .resolve(ctx); |
4098 | ret_ty.must_use(ctx) |
4099 | }; |
4100 | |
4101 | if must_use { |
4102 | attributes.push(attributes::must_use()); |
4103 | } |
4104 | } |
4105 | |
4106 | if let Some(comment) = item.comment(ctx) { |
4107 | attributes.push(attributes::doc(comment)); |
4108 | } |
4109 | |
4110 | let abi = match signature.abi(ctx, Some(name)) { |
4111 | ClangAbi::Known(Abi::ThisCall) |
4112 | if !ctx.options().rust_features().thiscall_abi => |
4113 | { |
4114 | warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target" ); |
4115 | return None; |
4116 | } |
4117 | ClangAbi::Known(Abi::Vectorcall) |
4118 | if !ctx.options().rust_features().vectorcall_abi => |
4119 | { |
4120 | warn!("Skipping function with vectorcall ABI that isn't supported by the configured Rust target" ); |
4121 | return None; |
4122 | } |
4123 | ClangAbi::Known(Abi::CUnwind) |
4124 | if !ctx.options().rust_features().c_unwind_abi => |
4125 | { |
4126 | warn!("Skipping function with C-unwind ABI that isn't supported by the configured Rust target" ); |
4127 | return None; |
4128 | } |
4129 | ClangAbi::Known(Abi::Win64) if signature.is_variadic() => { |
4130 | warn!("Skipping variadic function with Win64 ABI that isn't supported" ); |
4131 | return None; |
4132 | } |
4133 | ClangAbi::Unknown(unknown_abi) => { |
4134 | panic!( |
4135 | "Invalid or unknown abi {:?} for function {:?} ( {:?})" , |
4136 | unknown_abi, canonical_name, self |
4137 | ); |
4138 | } |
4139 | abi => abi, |
4140 | }; |
4141 | |
4142 | // Handle overloaded functions by giving each overload its own unique |
4143 | // suffix. |
4144 | let times_seen = result.overload_number(&canonical_name); |
4145 | if times_seen > 0 { |
4146 | write!(&mut canonical_name, " {}" , times_seen).unwrap(); |
4147 | } |
4148 | |
4149 | let mut has_link_name_attr = false; |
4150 | let link_name = mangled_name.unwrap_or(name); |
4151 | if !is_dynamic_function && |
4152 | !utils::names_will_be_identical_after_mangling( |
4153 | &canonical_name, |
4154 | link_name, |
4155 | Some(abi), |
4156 | ) |
4157 | { |
4158 | attributes.push(attributes::link_name(link_name)); |
4159 | has_link_name_attr = true; |
4160 | } |
4161 | |
4162 | // Unfortunately this can't piggyback on the `attributes` list because |
4163 | // the #[link(wasm_import_module)] needs to happen before the `extern |
4164 | // "C"` block. It doesn't get picked up properly otherwise |
4165 | let wasm_link_attribute = |
4166 | ctx.options().wasm_import_module_name.as_ref().map(|name| { |
4167 | quote! { #[link(wasm_import_module = #name)] } |
4168 | }); |
4169 | |
4170 | if is_internal && ctx.options().wrap_static_fns && !has_link_name_attr { |
4171 | let name = canonical_name.clone() + ctx.wrap_static_fns_suffix(); |
4172 | attributes.push(attributes::link_name(&name)); |
4173 | } |
4174 | |
4175 | let ident = ctx.rust_ident(canonical_name); |
4176 | let tokens = quote! { |
4177 | #wasm_link_attribute |
4178 | extern #abi { |
4179 | #(#attributes)* |
4180 | pub fn #ident ( #( #args ),* ) #ret; |
4181 | } |
4182 | }; |
4183 | |
4184 | // If we're doing dynamic binding generation, add to the dynamic items. |
4185 | if is_dynamic_function { |
4186 | let args_identifiers = |
4187 | utils::fnsig_argument_identifiers(ctx, signature); |
4188 | let ret_ty = utils::fnsig_return_ty(ctx, signature); |
4189 | result.dynamic_items().push( |
4190 | ident, |
4191 | abi, |
4192 | signature.is_variadic(), |
4193 | ctx.options().dynamic_link_require_all, |
4194 | args, |
4195 | args_identifiers, |
4196 | ret, |
4197 | ret_ty, |
4198 | attributes, |
4199 | ctx, |
4200 | ); |
4201 | } else { |
4202 | result.push(tokens); |
4203 | } |
4204 | Some(times_seen) |
4205 | } |
4206 | } |
4207 | |
4208 | fn objc_method_codegen( |
4209 | ctx: &BindgenContext, |
4210 | method: &ObjCMethod, |
4211 | methods: &mut Vec<proc_macro2::TokenStream>, |
4212 | class_name: Option<&str>, |
4213 | rust_class_name: &str, |
4214 | prefix: &str, |
4215 | ) { |
4216 | // This would ideally resolve the method into an Item, and use |
4217 | // Item::process_before_codegen; however, ObjC methods are not currently |
4218 | // made into function items. |
4219 | let name = format!(" {}:: {}{}" , rust_class_name, prefix, method.rust_name()); |
4220 | if ctx.options().blocklisted_items.matches(name) { |
4221 | return; |
4222 | } |
4223 | |
4224 | let signature = method.signature(); |
4225 | let fn_args = utils::fnsig_arguments(ctx, signature); |
4226 | let fn_ret = utils::fnsig_return_ty(ctx, signature); |
4227 | |
4228 | let sig = if method.is_class_method() { |
4229 | let fn_args = fn_args.clone(); |
4230 | quote! { |
4231 | ( #( #fn_args ),* ) #fn_ret |
4232 | } |
4233 | } else { |
4234 | let fn_args = fn_args.clone(); |
4235 | let args = iter::once(quote! { &self }).chain(fn_args.into_iter()); |
4236 | quote! { |
4237 | ( #( #args ),* ) #fn_ret |
4238 | } |
4239 | }; |
4240 | |
4241 | let methods_and_args = method.format_method_call(&fn_args); |
4242 | |
4243 | let body = { |
4244 | let body = if method.is_class_method() { |
4245 | let class_name = ctx.rust_ident( |
4246 | class_name |
4247 | .expect("Generating a class method without class name?" ), |
4248 | ); |
4249 | quote!(msg_send!(class!(#class_name), #methods_and_args)) |
4250 | } else { |
4251 | quote!(msg_send!(*self, #methods_and_args)) |
4252 | }; |
4253 | |
4254 | ctx.wrap_unsafe_ops(body) |
4255 | }; |
4256 | |
4257 | let method_name = |
4258 | ctx.rust_ident(format!(" {}{}" , prefix, method.rust_name())); |
4259 | |
4260 | methods.push(quote! { |
4261 | unsafe fn #method_name #sig where <Self as std::ops::Deref>::Target: objc::Message + Sized { |
4262 | #body |
4263 | } |
4264 | }); |
4265 | } |
4266 | |
4267 | impl CodeGenerator for ObjCInterface { |
4268 | type Extra = Item; |
4269 | type Return = (); |
4270 | |
4271 | fn codegen( |
4272 | &self, |
4273 | ctx: &BindgenContext, |
4274 | result: &mut CodegenResult<'_>, |
4275 | item: &Item, |
4276 | ) { |
4277 | debug_assert!(item.is_enabled_for_codegen(ctx)); |
4278 | |
4279 | let mut impl_items = vec![]; |
4280 | let rust_class_name = item.path_for_allowlisting(ctx)[1..].join("::" ); |
4281 | |
4282 | for method in self.methods() { |
4283 | objc_method_codegen( |
4284 | ctx, |
4285 | method, |
4286 | &mut impl_items, |
4287 | None, |
4288 | &rust_class_name, |
4289 | "" , |
4290 | ); |
4291 | } |
4292 | |
4293 | for class_method in self.class_methods() { |
4294 | let ambiquity = self |
4295 | .methods() |
4296 | .iter() |
4297 | .map(|m| m.rust_name()) |
4298 | .any(|x| x == class_method.rust_name()); |
4299 | let prefix = if ambiquity { "class_" } else { "" }; |
4300 | objc_method_codegen( |
4301 | ctx, |
4302 | class_method, |
4303 | &mut impl_items, |
4304 | Some(self.name()), |
4305 | &rust_class_name, |
4306 | prefix, |
4307 | ); |
4308 | } |
4309 | |
4310 | let trait_name = ctx.rust_ident(self.rust_name()); |
4311 | let trait_constraints = quote! { |
4312 | Sized + std::ops::Deref |
4313 | }; |
4314 | let trait_block = if self.is_template() { |
4315 | let template_names: Vec<Ident> = self |
4316 | .template_names |
4317 | .iter() |
4318 | .map(|g| ctx.rust_ident(g)) |
4319 | .collect(); |
4320 | |
4321 | quote! { |
4322 | pub trait #trait_name <#(#template_names:'static),*> : #trait_constraints { |
4323 | #( #impl_items )* |
4324 | } |
4325 | } |
4326 | } else { |
4327 | quote! { |
4328 | pub trait #trait_name : #trait_constraints { |
4329 | #( #impl_items )* |
4330 | } |
4331 | } |
4332 | }; |
4333 | |
4334 | let class_name = ctx.rust_ident(self.name()); |
4335 | if !self.is_category() && !self.is_protocol() { |
4336 | let struct_block = quote! { |
4337 | #[repr(transparent)] |
4338 | #[derive(Debug, Copy, Clone)] |
4339 | pub struct #class_name(pub id); |
4340 | impl std::ops::Deref for #class_name { |
4341 | type Target = objc::runtime::Object; |
4342 | fn deref(&self) -> &Self::Target { |
4343 | unsafe { |
4344 | &*self.0 |
4345 | } |
4346 | } |
4347 | } |
4348 | unsafe impl objc::Message for #class_name { } |
4349 | impl #class_name { |
4350 | pub fn alloc() -> Self { |
4351 | Self(unsafe { |
4352 | msg_send!(class!(#class_name), alloc) |
4353 | }) |
4354 | } |
4355 | } |
4356 | }; |
4357 | result.push(struct_block); |
4358 | let mut protocol_set: HashSet<ItemId> = Default::default(); |
4359 | for protocol_id in self.conforms_to.iter() { |
4360 | protocol_set.insert(*protocol_id); |
4361 | let protocol_name = ctx.rust_ident( |
4362 | ctx.resolve_type(protocol_id.expect_type_id(ctx)) |
4363 | .name() |
4364 | .unwrap(), |
4365 | ); |
4366 | let impl_trait = quote! { |
4367 | impl #protocol_name for #class_name { } |
4368 | }; |
4369 | result.push(impl_trait); |
4370 | } |
4371 | let mut parent_class = self.parent_class; |
4372 | while let Some(parent_id) = parent_class { |
4373 | let parent = parent_id |
4374 | .expect_type_id(ctx) |
4375 | .into_resolver() |
4376 | .through_type_refs() |
4377 | .resolve(ctx) |
4378 | .expect_type() |
4379 | .kind(); |
4380 | |
4381 | let parent = match parent { |
4382 | TypeKind::ObjCInterface(ref parent) => parent, |
4383 | _ => break, |
4384 | }; |
4385 | parent_class = parent.parent_class; |
4386 | |
4387 | let parent_name = ctx.rust_ident(parent.rust_name()); |
4388 | let impl_trait = if parent.is_template() { |
4389 | let template_names: Vec<Ident> = parent |
4390 | .template_names |
4391 | .iter() |
4392 | .map(|g| ctx.rust_ident(g)) |
4393 | .collect(); |
4394 | quote! { |
4395 | impl <#(#template_names :'static),*> #parent_name <#(#template_names),*> for #class_name { |
4396 | } |
4397 | } |
4398 | } else { |
4399 | quote! { |
4400 | impl #parent_name for #class_name { } |
4401 | } |
4402 | }; |
4403 | result.push(impl_trait); |
4404 | for protocol_id in parent.conforms_to.iter() { |
4405 | if protocol_set.insert(*protocol_id) { |
4406 | let protocol_name = ctx.rust_ident( |
4407 | ctx.resolve_type(protocol_id.expect_type_id(ctx)) |
4408 | .name() |
4409 | .unwrap(), |
4410 | ); |
4411 | let impl_trait = quote! { |
4412 | impl #protocol_name for #class_name { } |
4413 | }; |
4414 | result.push(impl_trait); |
4415 | } |
4416 | } |
4417 | if !parent.is_template() { |
4418 | let parent_struct_name = parent.name(); |
4419 | let child_struct_name = self.name(); |
4420 | let parent_struct = ctx.rust_ident(parent_struct_name); |
4421 | let from_block = quote! { |
4422 | impl From<#class_name> for #parent_struct { |
4423 | fn from(child: #class_name) -> #parent_struct { |
4424 | #parent_struct(child.0) |
4425 | } |
4426 | } |
4427 | }; |
4428 | result.push(from_block); |
4429 | |
4430 | let error_msg = format!( |
4431 | "This {} cannot be downcasted to {}" , |
4432 | parent_struct_name, child_struct_name |
4433 | ); |
4434 | let try_into_block = quote! { |
4435 | impl std::convert::TryFrom<#parent_struct> for #class_name { |
4436 | type Error = &'static str; |
4437 | fn try_from(parent: #parent_struct) -> Result<#class_name, Self::Error> { |
4438 | let is_kind_of : bool = unsafe { msg_send!(parent, isKindOfClass:class!(#class_name))}; |
4439 | if is_kind_of { |
4440 | Ok(#class_name(parent.0)) |
4441 | } else { |
4442 | Err(#error_msg) |
4443 | } |
4444 | } |
4445 | } |
4446 | }; |
4447 | result.push(try_into_block); |
4448 | } |
4449 | } |
4450 | } |
4451 | |
4452 | if !self.is_protocol() { |
4453 | let impl_block = if self.is_template() { |
4454 | let template_names: Vec<Ident> = self |
4455 | .template_names |
4456 | .iter() |
4457 | .map(|g| ctx.rust_ident(g)) |
4458 | .collect(); |
4459 | quote! { |
4460 | impl <#(#template_names :'static),*> #trait_name <#(#template_names),*> for #class_name { |
4461 | } |
4462 | } |
4463 | } else { |
4464 | quote! { |
4465 | impl #trait_name for #class_name { |
4466 | } |
4467 | } |
4468 | }; |
4469 | result.push(impl_block); |
4470 | } |
4471 | |
4472 | result.push(trait_block); |
4473 | result.saw_objc(); |
4474 | } |
4475 | } |
4476 | |
4477 | pub(crate) fn codegen( |
4478 | context: BindgenContext, |
4479 | ) -> Result<(proc_macro2::TokenStream, BindgenOptions, Vec<String>), CodegenError> |
4480 | { |
4481 | context.gen(|context| { |
4482 | let _t = context.timer("codegen" ); |
4483 | let counter = Cell::new(0); |
4484 | let mut result = CodegenResult::new(&counter); |
4485 | |
4486 | debug!("codegen: {:?}" , context.options()); |
4487 | |
4488 | if context.options().emit_ir { |
4489 | let codegen_items = context.codegen_items(); |
4490 | for (id, item) in context.items() { |
4491 | if codegen_items.contains(&id) { |
4492 | println!("ir: {:?} = {:#?}" , id, item); |
4493 | } |
4494 | } |
4495 | } |
4496 | |
4497 | if let Some(path) = context.options().emit_ir_graphviz.as_ref() { |
4498 | match dot::write_dot_file(context, path) { |
4499 | Ok(()) => info!( |
4500 | "Your dot file was generated successfully into: {}" , |
4501 | path |
4502 | ), |
4503 | Err(e) => warn!(" {}" , e), |
4504 | } |
4505 | } |
4506 | |
4507 | if let Some(spec) = context.options().depfile.as_ref() { |
4508 | match spec.write(context.deps()) { |
4509 | Ok(()) => info!( |
4510 | "Your depfile was generated successfully into: {}" , |
4511 | spec.depfile_path.display() |
4512 | ), |
4513 | Err(e) => warn!(" {}" , e), |
4514 | } |
4515 | } |
4516 | |
4517 | context.resolve_item(context.root_module()).codegen( |
4518 | context, |
4519 | &mut result, |
4520 | &(), |
4521 | ); |
4522 | |
4523 | if let Some(ref lib_name) = context.options().dynamic_library_name { |
4524 | let lib_ident = context.rust_ident(lib_name); |
4525 | let dynamic_items_tokens = |
4526 | result.dynamic_items().get_tokens(lib_ident, context); |
4527 | result.push(dynamic_items_tokens); |
4528 | } |
4529 | |
4530 | utils::serialize_items(&result, context)?; |
4531 | |
4532 | Ok(postprocessing::postprocessing( |
4533 | result.items, |
4534 | context.options(), |
4535 | )) |
4536 | }) |
4537 | } |
4538 | |
4539 | pub mod utils { |
4540 | use super::serialize::CSerialize; |
4541 | use super::{error, CodegenError, CodegenResult, ToRustTyOrOpaque}; |
4542 | use crate::ir::context::BindgenContext; |
4543 | use crate::ir::function::{Abi, ClangAbi, FunctionSig}; |
4544 | use crate::ir::item::{Item, ItemCanonicalPath}; |
4545 | use crate::ir::ty::TypeKind; |
4546 | use crate::{args_are_cpp, file_is_cpp}; |
4547 | use proc_macro2; |
4548 | use std::borrow::Cow; |
4549 | use std::mem; |
4550 | use std::path::PathBuf; |
4551 | use std::str::FromStr; |
4552 | |
4553 | pub(super) fn serialize_items( |
4554 | result: &CodegenResult, |
4555 | context: &BindgenContext, |
4556 | ) -> Result<(), CodegenError> { |
4557 | if result.items_to_serialize.is_empty() { |
4558 | return Ok(()); |
4559 | } |
4560 | |
4561 | let path = context |
4562 | .options() |
4563 | .wrap_static_fns_path |
4564 | .as_ref() |
4565 | .map(PathBuf::from) |
4566 | .unwrap_or_else(|| { |
4567 | std::env::temp_dir().join("bindgen" ).join("extern" ) |
4568 | }); |
4569 | |
4570 | let dir = path.parent().unwrap(); |
4571 | |
4572 | if !dir.exists() { |
4573 | std::fs::create_dir_all(&dir)?; |
4574 | } |
4575 | |
4576 | let is_cpp = args_are_cpp(&context.options().clang_args) || |
4577 | context |
4578 | .options() |
4579 | .input_headers |
4580 | .iter() |
4581 | .any(|h| file_is_cpp(h)); |
4582 | |
4583 | let source_path = path.with_extension(if is_cpp { "cpp" } else { "c" }); |
4584 | |
4585 | let mut code = Vec::new(); |
4586 | |
4587 | for &id in &result.items_to_serialize { |
4588 | let item = context.resolve_item(id); |
4589 | item.serialize(context, (), &mut vec![], &mut code)?; |
4590 | } |
4591 | |
4592 | std::fs::write(source_path, code)?; |
4593 | |
4594 | Ok(()) |
4595 | } |
4596 | |
4597 | pub fn prepend_bitfield_unit_type( |
4598 | ctx: &BindgenContext, |
4599 | result: &mut Vec<proc_macro2::TokenStream>, |
4600 | ) { |
4601 | let bitfield_unit_src = include_str!("./bitfield_unit.rs" ); |
4602 | let bitfield_unit_src = if ctx.options().rust_features().min_const_fn { |
4603 | Cow::Borrowed(bitfield_unit_src) |
4604 | } else { |
4605 | Cow::Owned(bitfield_unit_src.replace("const fn " , "fn " )) |
4606 | }; |
4607 | let bitfield_unit_type = |
4608 | proc_macro2::TokenStream::from_str(&bitfield_unit_src).unwrap(); |
4609 | let bitfield_unit_type = quote!(#bitfield_unit_type); |
4610 | |
4611 | let items = vec![bitfield_unit_type]; |
4612 | let old_items = mem::replace(result, items); |
4613 | result.extend(old_items); |
4614 | } |
4615 | |
4616 | pub fn prepend_objc_header( |
4617 | ctx: &BindgenContext, |
4618 | result: &mut Vec<proc_macro2::TokenStream>, |
4619 | ) { |
4620 | let use_objc = if ctx.options().objc_extern_crate { |
4621 | quote! { |
4622 | #[macro_use] |
4623 | extern crate objc; |
4624 | } |
4625 | } else { |
4626 | quote! { |
4627 | use objc::{self, msg_send, sel, sel_impl, class}; |
4628 | } |
4629 | }; |
4630 | |
4631 | let id_type = quote! { |
4632 | #[allow(non_camel_case_types)] |
4633 | pub type id = *mut objc::runtime::Object; |
4634 | }; |
4635 | |
4636 | let items = vec![use_objc, id_type]; |
4637 | let old_items = mem::replace(result, items); |
4638 | result.extend(old_items.into_iter()); |
4639 | } |
4640 | |
4641 | pub fn prepend_block_header( |
4642 | ctx: &BindgenContext, |
4643 | result: &mut Vec<proc_macro2::TokenStream>, |
4644 | ) { |
4645 | let use_block = if ctx.options().block_extern_crate { |
4646 | quote! { |
4647 | extern crate block; |
4648 | } |
4649 | } else { |
4650 | quote! { |
4651 | use block; |
4652 | } |
4653 | }; |
4654 | |
4655 | let items = vec![use_block]; |
4656 | let old_items = mem::replace(result, items); |
4657 | result.extend(old_items.into_iter()); |
4658 | } |
4659 | |
4660 | pub fn prepend_union_types( |
4661 | ctx: &BindgenContext, |
4662 | result: &mut Vec<proc_macro2::TokenStream>, |
4663 | ) { |
4664 | let prefix = ctx.trait_prefix(); |
4665 | |
4666 | // If the target supports `const fn`, declare eligible functions |
4667 | // as `const fn` else just `fn`. |
4668 | let const_fn = if ctx.options().rust_features().min_const_fn { |
4669 | quote! { const fn } |
4670 | } else { |
4671 | quote! { fn } |
4672 | }; |
4673 | |
4674 | // TODO(emilio): The fmt::Debug impl could be way nicer with |
4675 | // std::intrinsics::type_name, but... |
4676 | let union_field_decl = quote! { |
4677 | #[repr(C)] |
4678 | pub struct __BindgenUnionField<T>(::#prefix::marker::PhantomData<T>); |
4679 | }; |
4680 | |
4681 | let transmute = |
4682 | ctx.wrap_unsafe_ops(quote!(::#prefix::mem::transmute(self))); |
4683 | |
4684 | let union_field_impl = quote! { |
4685 | impl<T> __BindgenUnionField<T> { |
4686 | #[inline] |
4687 | pub #const_fn new() -> Self { |
4688 | __BindgenUnionField(::#prefix::marker::PhantomData) |
4689 | } |
4690 | |
4691 | #[inline] |
4692 | pub unsafe fn as_ref(&self) -> &T { |
4693 | #transmute |
4694 | } |
4695 | |
4696 | #[inline] |
4697 | pub unsafe fn as_mut(&mut self) -> &mut T { |
4698 | #transmute |
4699 | } |
4700 | } |
4701 | }; |
4702 | |
4703 | let union_field_default_impl = quote! { |
4704 | impl<T> ::#prefix::default::Default for __BindgenUnionField<T> { |
4705 | #[inline] |
4706 | fn default() -> Self { |
4707 | Self::new() |
4708 | } |
4709 | } |
4710 | }; |
4711 | |
4712 | let union_field_clone_impl = quote! { |
4713 | impl<T> ::#prefix::clone::Clone for __BindgenUnionField<T> { |
4714 | #[inline] |
4715 | fn clone(&self) -> Self { |
4716 | Self::new() |
4717 | } |
4718 | } |
4719 | }; |
4720 | |
4721 | let union_field_copy_impl = quote! { |
4722 | impl<T> ::#prefix::marker::Copy for __BindgenUnionField<T> {} |
4723 | }; |
4724 | |
4725 | let union_field_debug_impl = quote! { |
4726 | impl<T> ::#prefix::fmt::Debug for __BindgenUnionField<T> { |
4727 | fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter<'_>) |
4728 | -> ::#prefix::fmt::Result { |
4729 | fmt.write_str("__BindgenUnionField" ) |
4730 | } |
4731 | } |
4732 | }; |
4733 | |
4734 | // The actual memory of the filed will be hashed, so that's why these |
4735 | // field doesn't do anything with the hash. |
4736 | let union_field_hash_impl = quote! { |
4737 | impl<T> ::#prefix::hash::Hash for __BindgenUnionField<T> { |
4738 | fn hash<H: ::#prefix::hash::Hasher>(&self, _state: &mut H) { |
4739 | } |
4740 | } |
4741 | }; |
4742 | |
4743 | let union_field_partialeq_impl = quote! { |
4744 | impl<T> ::#prefix::cmp::PartialEq for __BindgenUnionField<T> { |
4745 | fn eq(&self, _other: &__BindgenUnionField<T>) -> bool { |
4746 | true |
4747 | } |
4748 | } |
4749 | }; |
4750 | |
4751 | let union_field_eq_impl = quote! { |
4752 | impl<T> ::#prefix::cmp::Eq for __BindgenUnionField<T> { |
4753 | } |
4754 | }; |
4755 | |
4756 | let items = vec![ |
4757 | union_field_decl, |
4758 | union_field_impl, |
4759 | union_field_default_impl, |
4760 | union_field_clone_impl, |
4761 | union_field_copy_impl, |
4762 | union_field_debug_impl, |
4763 | union_field_hash_impl, |
4764 | union_field_partialeq_impl, |
4765 | union_field_eq_impl, |
4766 | ]; |
4767 | |
4768 | let old_items = mem::replace(result, items); |
4769 | result.extend(old_items.into_iter()); |
4770 | } |
4771 | |
4772 | pub fn prepend_incomplete_array_types( |
4773 | ctx: &BindgenContext, |
4774 | result: &mut Vec<proc_macro2::TokenStream>, |
4775 | ) { |
4776 | let prefix = ctx.trait_prefix(); |
4777 | |
4778 | // If the target supports `const fn`, declare eligible functions |
4779 | // as `const fn` else just `fn`. |
4780 | let const_fn = if ctx.options().rust_features().min_const_fn { |
4781 | quote! { const fn } |
4782 | } else { |
4783 | quote! { fn } |
4784 | }; |
4785 | |
4786 | let incomplete_array_decl = quote! { |
4787 | #[repr(C)] |
4788 | #[derive(Default)] |
4789 | pub struct __IncompleteArrayField<T>( |
4790 | ::#prefix::marker::PhantomData<T>, [T; 0]); |
4791 | }; |
4792 | |
4793 | let from_raw_parts = ctx.wrap_unsafe_ops(quote! ( |
4794 | ::#prefix::slice::from_raw_parts(self.as_ptr(), len) |
4795 | )); |
4796 | let from_raw_parts_mut = ctx.wrap_unsafe_ops(quote! ( |
4797 | ::#prefix::slice::from_raw_parts_mut(self.as_mut_ptr(), len) |
4798 | )); |
4799 | |
4800 | let incomplete_array_impl = quote! { |
4801 | impl<T> __IncompleteArrayField<T> { |
4802 | #[inline] |
4803 | pub #const_fn new() -> Self { |
4804 | __IncompleteArrayField(::#prefix::marker::PhantomData, []) |
4805 | } |
4806 | |
4807 | #[inline] |
4808 | pub fn as_ptr(&self) -> *const T { |
4809 | self as *const _ as *const T |
4810 | } |
4811 | |
4812 | #[inline] |
4813 | pub fn as_mut_ptr(&mut self) -> *mut T { |
4814 | self as *mut _ as *mut T |
4815 | } |
4816 | |
4817 | #[inline] |
4818 | pub unsafe fn as_slice(&self, len: usize) -> &[T] { |
4819 | #from_raw_parts |
4820 | } |
4821 | |
4822 | #[inline] |
4823 | pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { |
4824 | #from_raw_parts_mut |
4825 | } |
4826 | } |
4827 | }; |
4828 | |
4829 | let incomplete_array_debug_impl = quote! { |
4830 | impl<T> ::#prefix::fmt::Debug for __IncompleteArrayField<T> { |
4831 | fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter<'_>) |
4832 | -> ::#prefix::fmt::Result { |
4833 | fmt.write_str("__IncompleteArrayField" ) |
4834 | } |
4835 | } |
4836 | }; |
4837 | |
4838 | let items = vec![ |
4839 | incomplete_array_decl, |
4840 | incomplete_array_impl, |
4841 | incomplete_array_debug_impl, |
4842 | ]; |
4843 | |
4844 | let old_items = mem::replace(result, items); |
4845 | result.extend(old_items.into_iter()); |
4846 | } |
4847 | |
4848 | pub fn prepend_complex_type(result: &mut Vec<proc_macro2::TokenStream>) { |
4849 | let complex_type = quote! { |
4850 | #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] |
4851 | #[repr(C)] |
4852 | pub struct __BindgenComplex<T> { |
4853 | pub re: T, |
4854 | pub im: T |
4855 | } |
4856 | }; |
4857 | |
4858 | let items = vec![complex_type]; |
4859 | let old_items = mem::replace(result, items); |
4860 | result.extend(old_items.into_iter()); |
4861 | } |
4862 | |
4863 | pub fn build_path( |
4864 | item: &Item, |
4865 | ctx: &BindgenContext, |
4866 | ) -> error::Result<proc_macro2::TokenStream> { |
4867 | let path = item.namespace_aware_canonical_path(ctx); |
4868 | let tokens = |
4869 | proc_macro2::TokenStream::from_str(&path.join("::" )).unwrap(); |
4870 | |
4871 | Ok(tokens) |
4872 | } |
4873 | |
4874 | fn primitive_ty( |
4875 | ctx: &BindgenContext, |
4876 | name: &str, |
4877 | ) -> proc_macro2::TokenStream { |
4878 | let ident = ctx.rust_ident_raw(name); |
4879 | quote! { |
4880 | #ident |
4881 | } |
4882 | } |
4883 | |
4884 | pub fn type_from_named( |
4885 | ctx: &BindgenContext, |
4886 | name: &str, |
4887 | ) -> Option<proc_macro2::TokenStream> { |
4888 | // FIXME: We could use the inner item to check this is really a |
4889 | // primitive type but, who the heck overrides these anyway? |
4890 | Some(match name { |
4891 | "int8_t" => primitive_ty(ctx, "i8" ), |
4892 | "uint8_t" => primitive_ty(ctx, "u8" ), |
4893 | "int16_t" => primitive_ty(ctx, "i16" ), |
4894 | "uint16_t" => primitive_ty(ctx, "u16" ), |
4895 | "int32_t" => primitive_ty(ctx, "i32" ), |
4896 | "uint32_t" => primitive_ty(ctx, "u32" ), |
4897 | "int64_t" => primitive_ty(ctx, "i64" ), |
4898 | "uint64_t" => primitive_ty(ctx, "u64" ), |
4899 | |
4900 | "size_t" if ctx.options().size_t_is_usize => { |
4901 | primitive_ty(ctx, "usize" ) |
4902 | } |
4903 | "uintptr_t" => primitive_ty(ctx, "usize" ), |
4904 | |
4905 | "ssize_t" if ctx.options().size_t_is_usize => { |
4906 | primitive_ty(ctx, "isize" ) |
4907 | } |
4908 | "intptr_t" | "ptrdiff_t" => primitive_ty(ctx, "isize" ), |
4909 | _ => return None, |
4910 | }) |
4911 | } |
4912 | |
4913 | fn fnsig_return_ty_internal( |
4914 | ctx: &BindgenContext, |
4915 | sig: &FunctionSig, |
4916 | include_arrow: bool, |
4917 | ) -> proc_macro2::TokenStream { |
4918 | if sig.is_divergent() { |
4919 | return if include_arrow { |
4920 | quote! { -> ! } |
4921 | } else { |
4922 | quote! { ! } |
4923 | }; |
4924 | } |
4925 | |
4926 | let canonical_type_kind = sig |
4927 | .return_type() |
4928 | .into_resolver() |
4929 | .through_type_refs() |
4930 | .through_type_aliases() |
4931 | .resolve(ctx) |
4932 | .kind() |
4933 | .expect_type() |
4934 | .kind(); |
4935 | |
4936 | if let TypeKind::Void = canonical_type_kind { |
4937 | return if include_arrow { |
4938 | quote! {} |
4939 | } else { |
4940 | quote! { () } |
4941 | }; |
4942 | } |
4943 | |
4944 | let ret_ty = sig.return_type().to_rust_ty_or_opaque(ctx, &()); |
4945 | if include_arrow { |
4946 | quote! { -> #ret_ty } |
4947 | } else { |
4948 | ret_ty |
4949 | } |
4950 | } |
4951 | |
4952 | pub fn fnsig_return_ty( |
4953 | ctx: &BindgenContext, |
4954 | sig: &FunctionSig, |
4955 | ) -> proc_macro2::TokenStream { |
4956 | fnsig_return_ty_internal(ctx, sig, /* include_arrow = */ true) |
4957 | } |
4958 | |
4959 | pub fn fnsig_arguments( |
4960 | ctx: &BindgenContext, |
4961 | sig: &FunctionSig, |
4962 | ) -> Vec<proc_macro2::TokenStream> { |
4963 | use super::ToPtr; |
4964 | |
4965 | let mut unnamed_arguments = 0; |
4966 | let mut args = sig |
4967 | .argument_types() |
4968 | .iter() |
4969 | .map(|&(ref name, ty)| { |
4970 | let arg_item = ctx.resolve_item(ty); |
4971 | let arg_ty = arg_item.kind().expect_type(); |
4972 | |
4973 | // From the C90 standard[1]: |
4974 | // |
4975 | // A declaration of a parameter as "array of type" shall be |
4976 | // adjusted to "qualified pointer to type", where the type |
4977 | // qualifiers (if any) are those specified within the [ and ] of |
4978 | // the array type derivation. |
4979 | // |
4980 | // [1]: http://c0x.coding-guidelines.com/6.7.5.3.html |
4981 | let arg_ty = match *arg_ty.canonical_type(ctx).kind() { |
4982 | TypeKind::Array(t, _) => { |
4983 | let stream = |
4984 | if ctx.options().array_pointers_in_arguments { |
4985 | arg_ty.to_rust_ty_or_opaque(ctx, arg_item) |
4986 | } else { |
4987 | t.to_rust_ty_or_opaque(ctx, &()) |
4988 | }; |
4989 | stream.to_ptr(ctx.resolve_type(t).is_const()) |
4990 | } |
4991 | TypeKind::Pointer(inner) => { |
4992 | let inner = ctx.resolve_item(inner); |
4993 | let inner_ty = inner.expect_type(); |
4994 | if let TypeKind::ObjCInterface(ref interface) = |
4995 | *inner_ty.canonical_type(ctx).kind() |
4996 | { |
4997 | let name = ctx.rust_ident(interface.name()); |
4998 | quote! { |
4999 | #name |
5000 | } |
5001 | } else { |
5002 | arg_item.to_rust_ty_or_opaque(ctx, &()) |
5003 | } |
5004 | } |
5005 | _ => arg_item.to_rust_ty_or_opaque(ctx, &()), |
5006 | }; |
5007 | |
5008 | let arg_name = match *name { |
5009 | Some(ref name) => ctx.rust_mangle(name).into_owned(), |
5010 | None => { |
5011 | unnamed_arguments += 1; |
5012 | format!("arg {}" , unnamed_arguments) |
5013 | } |
5014 | }; |
5015 | |
5016 | assert!(!arg_name.is_empty()); |
5017 | let arg_name = ctx.rust_ident(arg_name); |
5018 | |
5019 | quote! { |
5020 | #arg_name : #arg_ty |
5021 | } |
5022 | }) |
5023 | .collect::<Vec<_>>(); |
5024 | |
5025 | if sig.is_variadic() { |
5026 | args.push(quote! { ... }) |
5027 | } |
5028 | |
5029 | args |
5030 | } |
5031 | |
5032 | pub fn fnsig_argument_identifiers( |
5033 | ctx: &BindgenContext, |
5034 | sig: &FunctionSig, |
5035 | ) -> Vec<proc_macro2::TokenStream> { |
5036 | let mut unnamed_arguments = 0; |
5037 | let args = sig |
5038 | .argument_types() |
5039 | .iter() |
5040 | .map(|&(ref name, _ty)| { |
5041 | let arg_name = match *name { |
5042 | Some(ref name) => ctx.rust_mangle(name).into_owned(), |
5043 | None => { |
5044 | unnamed_arguments += 1; |
5045 | format!("arg {}" , unnamed_arguments) |
5046 | } |
5047 | }; |
5048 | |
5049 | assert!(!arg_name.is_empty()); |
5050 | let arg_name = ctx.rust_ident(arg_name); |
5051 | |
5052 | quote! { |
5053 | #arg_name |
5054 | } |
5055 | }) |
5056 | .collect::<Vec<_>>(); |
5057 | |
5058 | args |
5059 | } |
5060 | |
5061 | pub fn fnsig_block( |
5062 | ctx: &BindgenContext, |
5063 | sig: &FunctionSig, |
5064 | ) -> proc_macro2::TokenStream { |
5065 | let args = sig.argument_types().iter().map(|&(_, ty)| { |
5066 | let arg_item = ctx.resolve_item(ty); |
5067 | |
5068 | arg_item.to_rust_ty_or_opaque(ctx, &()) |
5069 | }); |
5070 | |
5071 | let ret_ty = fnsig_return_ty_internal( |
5072 | ctx, sig, /* include_arrow = */ false, |
5073 | ); |
5074 | quote! { |
5075 | *const ::block::Block<(#(#args,)*), #ret_ty> |
5076 | } |
5077 | } |
5078 | |
5079 | // Returns true if `canonical_name` will end up as `mangled_name` at the |
5080 | // machine code level, i.e. after LLVM has applied any target specific |
5081 | // mangling. |
5082 | pub(crate) fn names_will_be_identical_after_mangling( |
5083 | canonical_name: &str, |
5084 | mangled_name: &str, |
5085 | call_conv: Option<ClangAbi>, |
5086 | ) -> bool { |
5087 | // If the mangled name and the canonical name are the same then no |
5088 | // mangling can have happened between the two versions. |
5089 | if canonical_name == mangled_name { |
5090 | return true; |
5091 | } |
5092 | |
5093 | // Working with &[u8] makes indexing simpler than with &str |
5094 | let canonical_name = canonical_name.as_bytes(); |
5095 | let mangled_name = mangled_name.as_bytes(); |
5096 | |
5097 | let (mangling_prefix, expect_suffix) = match call_conv { |
5098 | Some(ClangAbi::Known(Abi::C)) | |
5099 | // None is the case for global variables |
5100 | None => { |
5101 | (b'_' , false) |
5102 | } |
5103 | Some(ClangAbi::Known(Abi::Stdcall)) => (b'_' , true), |
5104 | Some(ClangAbi::Known(Abi::Fastcall)) => (b'@' , true), |
5105 | |
5106 | // This is something we don't recognize, stay on the safe side |
5107 | // by emitting the `#[link_name]` attribute |
5108 | Some(_) => return false, |
5109 | }; |
5110 | |
5111 | // Check that the mangled name is long enough to at least contain the |
5112 | // canonical name plus the expected prefix. |
5113 | if mangled_name.len() < canonical_name.len() + 1 { |
5114 | return false; |
5115 | } |
5116 | |
5117 | // Return if the mangled name does not start with the prefix expected |
5118 | // for the given calling convention. |
5119 | if mangled_name[0] != mangling_prefix { |
5120 | return false; |
5121 | } |
5122 | |
5123 | // Check that the mangled name contains the canonical name after the |
5124 | // prefix |
5125 | if &mangled_name[1..canonical_name.len() + 1] != canonical_name { |
5126 | return false; |
5127 | } |
5128 | |
5129 | // If the given calling convention also prescribes a suffix, check that |
5130 | // it exists too |
5131 | if expect_suffix { |
5132 | let suffix = &mangled_name[canonical_name.len() + 1..]; |
5133 | |
5134 | // The shortest suffix is "@0" |
5135 | if suffix.len() < 2 { |
5136 | return false; |
5137 | } |
5138 | |
5139 | // Check that the suffix starts with '@' and is all ASCII decimals |
5140 | // after that. |
5141 | if suffix[0] != b'@' || !suffix[1..].iter().all(u8::is_ascii_digit) |
5142 | { |
5143 | return false; |
5144 | } |
5145 | } else if mangled_name.len() != canonical_name.len() + 1 { |
5146 | // If we don't expect a prefix but there is one, we need the |
5147 | // #[link_name] attribute |
5148 | return false; |
5149 | } |
5150 | |
5151 | true |
5152 | } |
5153 | } |
5154 | |