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