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::Float16 => write!(writer, "_Float16")?,
274                     FloatKind::Float => write!(writer, "float")?,
275                     FloatKind::Double => write!(writer, "double")?,
276                     FloatKind::LongDouble => write!(writer, "long double")?,
277                     FloatKind::Float128 => write!(writer, "__float128")?,
278                 }
279             }
280             TypeKind::Complex(float_kind) => {
281                 if self.is_const() {
282                     write!(writer, "const ")?;
283                 }
284                 match float_kind {
285                     FloatKind::Float16 => write!(writer, "_Float16 complex")?,
286                     FloatKind::Float => write!(writer, "float complex")?,
287                     FloatKind::Double => write!(writer, "double complex")?,
288                     FloatKind::LongDouble => {
289                         write!(writer, "long double complex")?
290                     }
291                     FloatKind::Float128 => write!(writer, "__complex128")?,
292                 }
293             }
294             TypeKind::Alias(type_id) => {
295                 if let Some(name) = self.name() {
296                     if self.is_const() {
297                         write!(writer, "const {}", name)?;
298                     } else {
299                         write!(writer, "{}", name)?;
300                     }
301                 } else {
302                     type_id.serialize(ctx, (), stack, writer)?;
303                 }
304             }
305             TypeKind::Array(type_id, length) => {
306                 type_id.serialize(ctx, (), stack, writer)?;
307                 write!(writer, " [{}]", length)?
308             }
309             TypeKind::Function(signature) => {
310                 if self.is_const() {
311                     stack.push("const ".to_string());
312                 }
313 
314                 signature.return_type().serialize(
315                     ctx,
316                     (),
317                     &mut vec![],
318                     writer,
319                 )?;
320 
321                 write!(writer, " (")?;
322                 while let Some(item) = stack.pop() {
323                     write!(writer, "{}", item)?;
324                 }
325                 write!(writer, ")")?;
326 
327                 let args = signature.argument_types();
328                 if args.is_empty() {
329                     write!(writer, " (void)")?;
330                 } else {
331                     write!(writer, " (")?;
332                     serialize_sep(
333                         ", ",
334                         args.iter(),
335                         ctx,
336                         writer,
337                         |(name, type_id), ctx, buf| {
338                             let mut stack = vec![];
339                             if let Some(name) = name {
340                                 stack.push(name.clone());
341                             }
342                             type_id.serialize(ctx, (), &mut stack, buf)
343                         },
344                     )?;
345                     write!(writer, ")")?
346                 }
347             }
348             TypeKind::ResolvedTypeRef(type_id) => {
349                 if self.is_const() {
350                     write!(writer, "const ")?;
351                 }
352                 type_id.serialize(ctx, (), stack, writer)?
353             }
354             TypeKind::Pointer(type_id) => {
355                 if self.is_const() {
356                     stack.push("*const ".to_owned());
357                 } else {
358                     stack.push("*".to_owned());
359                 }
360                 type_id.serialize(ctx, (), stack, writer)?
361             }
362             TypeKind::Comp(comp_info) => {
363                 if self.is_const() {
364                     write!(writer, "const ")?;
365                 }
366 
367                 let name = item.canonical_name(ctx);
368 
369                 match comp_info.kind() {
370                     CompKind::Struct => write!(writer, "struct {}", name)?,
371                     CompKind::Union => write!(writer, "union {}", name)?,
372                 };
373             }
374             TypeKind::Enum(_enum_ty) => {
375                 if self.is_const() {
376                     write!(writer, "const ")?;
377                 }
378 
379                 let name = item.canonical_name(ctx);
380                 write!(writer, "enum {}", name)?;
381             }
382             ty => {
383                 return Err(CodegenError::Serialize {
384                     msg: format!("Cannot serialize type kind {:?}", ty),
385                     loc: get_loc(item),
386                 })
387             }
388         };
389 
390         if !stack.is_empty() {
391             write!(writer, " ")?;
392             while let Some(item) = stack.pop() {
393                 write!(writer, "{}", item)?;
394             }
395         }
396 
397         Ok(())
398     }
399 }
400 
serialize_args<W: Write>( args: &[(String, TypeId)], ctx: &BindgenContext, writer: &mut W, ) -> Result<(), CodegenError>401 fn serialize_args<W: Write>(
402     args: &[(String, TypeId)],
403     ctx: &BindgenContext,
404     writer: &mut W,
405 ) -> Result<(), CodegenError> {
406     if args.is_empty() {
407         write!(writer, "void")?;
408     } else {
409         serialize_sep(
410             ", ",
411             args.iter(),
412             ctx,
413             writer,
414             |(name, type_id), ctx, buf| {
415                 type_id.serialize(ctx, (), &mut vec![name.clone()], buf)
416             },
417         )?;
418     }
419 
420     Ok(())
421 }
422 
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>423 fn serialize_sep<
424     W: Write,
425     F: FnMut(I::Item, &BindgenContext, &mut W) -> Result<(), CodegenError>,
426     I: Iterator,
427 >(
428     sep: &str,
429     mut iter: I,
430     ctx: &BindgenContext,
431     buf: &mut W,
432     mut f: F,
433 ) -> Result<(), CodegenError> {
434     if let Some(item) = iter.next() {
435         f(item, ctx, buf)?;
436         let sep = sep.as_bytes();
437         for item in iter {
438             buf.write_all(sep)?;
439             f(item, ctx, buf)?;
440         }
441     }
442 
443     Ok(())
444 }
445