• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::io::Write;
2 
3 use crate::callbacks::IntKind;
4 
5 use crate::ir::comp::CompKind;
6 use crate::ir::context::{BindgenContext, TypeId};
7 use crate::ir::function::{Function, FunctionKind};
8 use crate::ir::item::Item;
9 use crate::ir::item::ItemCanonicalName;
10 use crate::ir::item_kind::ItemKind;
11 use crate::ir::ty::{FloatKind, Type, TypeKind};
12 
13 use super::{CodegenError, WrapAsVariadic};
14 
get_loc(item: &Item) -> String15 fn get_loc(item: &Item) -> String {
16     item.location()
17         .map(|x| x.to_string())
18         .unwrap_or_else(|| "unknown".to_owned())
19 }
20 
21 pub(super) trait CSerialize<'a> {
22     type Extra;
23 
serialize<W: Write>( &self, ctx: &BindgenContext, extra: Self::Extra, stack: &mut Vec<String>, writer: &mut W, ) -> Result<(), CodegenError>24     fn serialize<W: Write>(
25         &self,
26         ctx: &BindgenContext,
27         extra: Self::Extra,
28         stack: &mut Vec<String>,
29         writer: &mut W,
30     ) -> Result<(), CodegenError>;
31 }
32 
33 impl<'a> CSerialize<'a> for Item {
34     type Extra = &'a Option<WrapAsVariadic>;
35 
serialize<W: Write>( &self, ctx: &BindgenContext, extra: Self::Extra, stack: &mut Vec<String>, writer: &mut W, ) -> Result<(), CodegenError>36     fn serialize<W: Write>(
37         &self,
38         ctx: &BindgenContext,
39         extra: Self::Extra,
40         stack: &mut Vec<String>,
41         writer: &mut W,
42     ) -> Result<(), CodegenError> {
43         match self.kind() {
44             ItemKind::Function(func) => {
45                 func.serialize(ctx, (self, extra), stack, writer)
46             }
47             kind => Err(CodegenError::Serialize {
48                 msg: format!("Cannot serialize item kind {:?}", kind),
49                 loc: get_loc(self),
50             }),
51         }
52     }
53 }
54 
55 impl<'a> CSerialize<'a> for Function {
56     type Extra = (&'a Item, &'a Option<WrapAsVariadic>);
57 
serialize<W: Write>( &self, ctx: &BindgenContext, (item, wrap_as_variadic): Self::Extra, stack: &mut Vec<String>, writer: &mut W, ) -> Result<(), CodegenError>58     fn serialize<W: Write>(
59         &self,
60         ctx: &BindgenContext,
61         (item, wrap_as_variadic): Self::Extra,
62         stack: &mut Vec<String>,
63         writer: &mut W,
64     ) -> Result<(), CodegenError> {
65         if self.kind() != FunctionKind::Function {
66             return Err(CodegenError::Serialize {
67                 msg: format!(
68                     "Cannot serialize function kind {:?}",
69                     self.kind(),
70                 ),
71                 loc: get_loc(item),
72             });
73         }
74 
75         let signature = match ctx.resolve_type(self.signature()).kind() {
76             TypeKind::Function(signature) => signature,
77             _ => unreachable!(),
78         };
79 
80         assert!(!signature.is_variadic());
81 
82         let name = self.name();
83 
84         // Function argoments stored as `(name, type_id)` tuples.
85         let args = {
86             let mut count = 0;
87 
88             let idx_to_prune = wrap_as_variadic.as_ref().map(
89                 |WrapAsVariadic {
90                      idx_of_va_list_arg, ..
91                  }| *idx_of_va_list_arg,
92             );
93 
94             signature
95                 .argument_types()
96                 .iter()
97                 .cloned()
98                 .enumerate()
99                 .filter_map(|(idx, (opt_name, type_id))| {
100                     if Some(idx) == idx_to_prune {
101                         None
102                     } else {
103                         Some((
104                             opt_name.unwrap_or_else(|| {
105                                 let name = format!("arg_{}", count);
106                                 count += 1;
107                                 name
108                             }),
109                             type_id,
110                         ))
111                     }
112                 })
113                 .collect::<Vec<_>>()
114         };
115 
116         // The name used for the wrapper self.
117         let wrap_name = format!("{}{}", name, ctx.wrap_static_fns_suffix());
118 
119         // The function's return type
120         let (ret_item, ret_ty) = {
121             let type_id = signature.return_type();
122             let ret_item = ctx.resolve_item(type_id);
123             let ret_ty = ret_item.expect_type();
124 
125             // Write `ret_ty`.
126             ret_ty.serialize(ctx, ret_item, stack, writer)?;
127 
128             (ret_item, ret_ty)
129         };
130 
131         const INDENT: &str = "    ";
132 
133         // Write `wrap_name(args`.
134         write!(writer, " {}(", wrap_name)?;
135         serialize_args(&args, ctx, writer)?;
136 
137         if wrap_as_variadic.is_none() {
138             // Write `) { name(` if the function returns void and `) { return name(` if it does not.
139             if ret_ty.is_void() {
140                 write!(writer, ") {{ {}(", name)?;
141             } else {
142                 write!(writer, ") {{ return {}(", name)?;
143             }
144         } else {
145             // Write `, ...) {`
146             writeln!(writer, ", ...) {{")?;
147 
148             // Declare the return type `RET_TY ret;` if their is a need to do so
149             if !ret_ty.is_void() {
150                 write!(writer, "{INDENT}")?;
151                 ret_ty.serialize(ctx, ret_item, stack, writer)?;
152                 writeln!(writer, " ret;")?;
153             }
154 
155             // Setup va_list
156             writeln!(writer, "{INDENT}va_list ap;\n")?;
157             writeln!(
158                 writer,
159                 "{INDENT}va_start(ap, {});",
160                 args.last().unwrap().0
161             )?;
162 
163             write!(writer, "{INDENT}")?;
164             // Write `ret = name(` or `name(` depending if the function returns something
165             if !ret_ty.is_void() {
166                 write!(writer, "ret = ")?;
167             }
168             write!(writer, "{}(", name)?;
169         }
170 
171         // Get the arguments names and insert at the right place if necessary `ap`
172         let mut args: Vec<_> = args.into_iter().map(|(name, _)| name).collect();
173         if let Some(WrapAsVariadic {
174             idx_of_va_list_arg, ..
175         }) = wrap_as_variadic
176         {
177             args.insert(*idx_of_va_list_arg, "ap".to_owned());
178         }
179 
180         // Write `arg_names);`.
181         serialize_sep(", ", args.iter(), ctx, writer, |name, _, buf| {
182             write!(buf, "{}", name).map_err(From::from)
183         })?;
184         #[rustfmt::skip]
185         write!(writer, ");{}", if wrap_as_variadic.is_none() { " " } else { "\n" })?;
186 
187         if wrap_as_variadic.is_some() {
188             // End va_list and return the result if their is one
189             writeln!(writer, "{INDENT}va_end(ap);")?;
190             if !ret_ty.is_void() {
191                 writeln!(writer, "{INDENT}return ret;")?;
192             }
193         }
194 
195         writeln!(writer, "}}")?;
196 
197         Ok(())
198     }
199 }
200 
201 impl<'a> CSerialize<'a> for TypeId {
202     type Extra = ();
203 
serialize<W: Write>( &self, ctx: &BindgenContext, (): Self::Extra, stack: &mut Vec<String>, writer: &mut W, ) -> Result<(), CodegenError>204     fn serialize<W: Write>(
205         &self,
206         ctx: &BindgenContext,
207         (): Self::Extra,
208         stack: &mut Vec<String>,
209         writer: &mut W,
210     ) -> Result<(), CodegenError> {
211         let item = ctx.resolve_item(*self);
212         item.expect_type().serialize(ctx, item, stack, writer)
213     }
214 }
215 
216 impl<'a> CSerialize<'a> for Type {
217     type Extra = &'a Item;
218 
serialize<W: Write>( &self, ctx: &BindgenContext, item: Self::Extra, stack: &mut Vec<String>, writer: &mut W, ) -> Result<(), CodegenError>219     fn serialize<W: Write>(
220         &self,
221         ctx: &BindgenContext,
222         item: Self::Extra,
223         stack: &mut Vec<String>,
224         writer: &mut W,
225     ) -> Result<(), CodegenError> {
226         match self.kind() {
227             TypeKind::Void => {
228                 if self.is_const() {
229                     write!(writer, "const ")?;
230                 }
231                 write!(writer, "void")?
232             }
233             TypeKind::NullPtr => {
234                 if self.is_const() {
235                     write!(writer, "const ")?;
236                 }
237                 write!(writer, "nullptr_t")?
238             }
239             TypeKind::Int(int_kind) => {
240                 if self.is_const() {
241                     write!(writer, "const ")?;
242                 }
243                 match int_kind {
244                     IntKind::Bool => write!(writer, "bool")?,
245                     IntKind::SChar => write!(writer, "signed char")?,
246                     IntKind::UChar => write!(writer, "unsigned char")?,
247                     IntKind::WChar => write!(writer, "wchar_t")?,
248                     IntKind::Short => write!(writer, "short")?,
249                     IntKind::UShort => write!(writer, "unsigned short")?,
250                     IntKind::Int => write!(writer, "int")?,
251                     IntKind::UInt => write!(writer, "unsigned int")?,
252                     IntKind::Long => write!(writer, "long")?,
253                     IntKind::ULong => write!(writer, "unsigned long")?,
254                     IntKind::LongLong => write!(writer, "long long")?,
255                     IntKind::ULongLong => write!(writer, "unsigned long long")?,
256                     IntKind::Char { .. } => write!(writer, "char")?,
257                     int_kind => {
258                         return Err(CodegenError::Serialize {
259                             msg: format!(
260                                 "Cannot serialize integer kind {:?}",
261                                 int_kind
262                             ),
263                             loc: get_loc(item),
264                         })
265                     }
266                 }
267             }
268             TypeKind::Float(float_kind) => {
269                 if self.is_const() {
270                     write!(writer, "const ")?;
271                 }
272                 match float_kind {
273                     FloatKind::Float => write!(writer, "float")?,
274                     FloatKind::Double => write!(writer, "double")?,
275                     FloatKind::LongDouble => write!(writer, "long double")?,
276                     FloatKind::Float128 => write!(writer, "__float128")?,
277                 }
278             }
279             TypeKind::Complex(float_kind) => {
280                 if self.is_const() {
281                     write!(writer, "const ")?;
282                 }
283                 match float_kind {
284                     FloatKind::Float => write!(writer, "float complex")?,
285                     FloatKind::Double => write!(writer, "double complex")?,
286                     FloatKind::LongDouble => {
287                         write!(writer, "long double complex")?
288                     }
289                     FloatKind::Float128 => write!(writer, "__complex128")?,
290                 }
291             }
292             TypeKind::Alias(type_id) => {
293                 if let Some(name) = self.name() {
294                     if self.is_const() {
295                         write!(writer, "const {}", name)?;
296                     } else {
297                         write!(writer, "{}", name)?;
298                     }
299                 } else {
300                     type_id.serialize(ctx, (), stack, writer)?;
301                 }
302             }
303             TypeKind::Array(type_id, length) => {
304                 type_id.serialize(ctx, (), stack, writer)?;
305                 write!(writer, " [{}]", length)?
306             }
307             TypeKind::Function(signature) => {
308                 if self.is_const() {
309                     stack.push("const ".to_string());
310                 }
311 
312                 signature.return_type().serialize(
313                     ctx,
314                     (),
315                     &mut vec![],
316                     writer,
317                 )?;
318 
319                 write!(writer, " (")?;
320                 while let Some(item) = stack.pop() {
321                     write!(writer, "{}", item)?;
322                 }
323                 write!(writer, ")")?;
324 
325                 let args = signature.argument_types();
326                 if args.is_empty() {
327                     write!(writer, " (void)")?;
328                 } else {
329                     write!(writer, " (")?;
330                     serialize_sep(
331                         ", ",
332                         args.iter(),
333                         ctx,
334                         writer,
335                         |(name, type_id), ctx, buf| {
336                             let mut stack = vec![];
337                             if let Some(name) = name {
338                                 stack.push(name.clone());
339                             }
340                             type_id.serialize(ctx, (), &mut stack, buf)
341                         },
342                     )?;
343                     write!(writer, ")")?
344                 }
345             }
346             TypeKind::ResolvedTypeRef(type_id) => {
347                 if self.is_const() {
348                     write!(writer, "const ")?;
349                 }
350                 type_id.serialize(ctx, (), stack, writer)?
351             }
352             TypeKind::Pointer(type_id) => {
353                 if self.is_const() {
354                     stack.push("*const ".to_owned());
355                 } else {
356                     stack.push("*".to_owned());
357                 }
358                 type_id.serialize(ctx, (), stack, writer)?
359             }
360             TypeKind::Comp(comp_info) => {
361                 if self.is_const() {
362                     write!(writer, "const ")?;
363                 }
364 
365                 let name = item.canonical_name(ctx);
366 
367                 match comp_info.kind() {
368                     CompKind::Struct => write!(writer, "struct {}", name)?,
369                     CompKind::Union => write!(writer, "union {}", name)?,
370                 };
371             }
372             TypeKind::Enum(_enum_ty) => {
373                 if self.is_const() {
374                     write!(writer, "const ")?;
375                 }
376 
377                 let name = item.canonical_name(ctx);
378                 write!(writer, "enum {}", name)?;
379             }
380             ty => {
381                 return Err(CodegenError::Serialize {
382                     msg: format!("Cannot serialize type kind {:?}", ty),
383                     loc: get_loc(item),
384                 })
385             }
386         };
387 
388         if !stack.is_empty() {
389             write!(writer, " ")?;
390             while let Some(item) = stack.pop() {
391                 write!(writer, "{}", item)?;
392             }
393         }
394 
395         Ok(())
396     }
397 }
398 
serialize_args<W: Write>( args: &[(String, TypeId)], ctx: &BindgenContext, writer: &mut W, ) -> Result<(), CodegenError>399 fn serialize_args<W: Write>(
400     args: &[(String, TypeId)],
401     ctx: &BindgenContext,
402     writer: &mut W,
403 ) -> Result<(), CodegenError> {
404     if args.is_empty() {
405         write!(writer, "void")?;
406     } else {
407         serialize_sep(
408             ", ",
409             args.iter(),
410             ctx,
411             writer,
412             |(name, type_id), ctx, buf| {
413                 type_id.serialize(ctx, (), &mut vec![name.clone()], buf)
414             },
415         )?;
416     }
417 
418     Ok(())
419 }
420 
serialize_sep< W: Write, F: FnMut(I::Item, &BindgenContext, &mut W) -> Result<(), CodegenError>, I: Iterator, >( sep: &str, mut iter: I, ctx: &BindgenContext, buf: &mut W, mut f: F, ) -> Result<(), CodegenError>421 fn serialize_sep<
422     W: Write,
423     F: FnMut(I::Item, &BindgenContext, &mut W) -> Result<(), CodegenError>,
424     I: Iterator,
425 >(
426     sep: &str,
427     mut iter: I,
428     ctx: &BindgenContext,
429     buf: &mut W,
430     mut f: F,
431 ) -> Result<(), CodegenError> {
432     if let Some(item) = iter.next() {
433         f(item, ctx, buf)?;
434         let sep = sep.as_bytes();
435         for item in iter {
436             buf.write_all(sep)?;
437             f(item, ctx, buf)?;
438         }
439     }
440 
441     Ok(())
442 }
443