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