bindgen/codegen/
serialize.rs

1use std::io::Write;
2
3use crate::callbacks::IntKind;
4
5use crate::ir::comp::CompKind;
6use crate::ir::context::{BindgenContext, TypeId};
7use crate::ir::function::{Function, FunctionKind};
8use crate::ir::item::Item;
9use crate::ir::item::ItemCanonicalName;
10use crate::ir::item_kind::ItemKind;
11use crate::ir::ty::{FloatKind, Type, TypeKind};
12
13use super::{CodegenError, WrapAsVariadic};
14
15fn get_loc(item: &Item) -> String {
16    item.location()
17        .map_or_else(|| "unknown".to_owned(), |x| x.to_string())
18}
19
20pub(super) trait CSerialize<'a> {
21    type Extra;
22
23    fn serialize<W: Write>(
24        &self,
25        ctx: &BindgenContext,
26        extra: Self::Extra,
27        stack: &mut Vec<String>,
28        writer: &mut W,
29    ) -> Result<(), CodegenError>;
30}
31
32impl<'a> CSerialize<'a> for Item {
33    type Extra = &'a Option<WrapAsVariadic>;
34
35    fn serialize<W: Write>(
36        &self,
37        ctx: &BindgenContext,
38        extra: Self::Extra,
39        stack: &mut Vec<String>,
40        writer: &mut W,
41    ) -> Result<(), CodegenError> {
42        match self.kind() {
43            ItemKind::Function(func) => {
44                func.serialize(ctx, (self, extra), stack, writer)
45            }
46            kind => Err(CodegenError::Serialize {
47                msg: format!("Cannot serialize item kind {kind:?}"),
48                loc: get_loc(self),
49            }),
50        }
51    }
52}
53
54impl<'a> CSerialize<'a> for Function {
55    type Extra = (&'a Item, &'a Option<WrapAsVariadic>);
56
57    fn serialize<W: Write>(
58        &self,
59        ctx: &BindgenContext,
60        (item, wrap_as_variadic): Self::Extra,
61        stack: &mut Vec<String>,
62        writer: &mut W,
63    ) -> Result<(), CodegenError> {
64        if self.kind() != FunctionKind::Function {
65            return Err(CodegenError::Serialize {
66                msg: format!(
67                    "Cannot serialize function kind {:?}",
68                    self.kind(),
69                ),
70                loc: get_loc(item),
71            });
72        }
73
74        let TypeKind::Function(signature) =
75            ctx.resolve_type(self.signature()).kind()
76        else {
77            unreachable!()
78        };
79
80        assert!(!signature.is_variadic());
81
82        let name = self.name();
83
84        // Function arguments 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
201impl CSerialize<'_> for TypeId {
202    type Extra = ();
203
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
216impl<'a> CSerialize<'a> for Type {
217    type Extra = &'a Item;
218
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 {int_kind:?}"
261                            ),
262                            loc: get_loc(item),
263                        })
264                    }
265                }
266            }
267            TypeKind::Float(float_kind) => {
268                if self.is_const() {
269                    write!(writer, "const ")?;
270                }
271                match float_kind {
272                    FloatKind::Float16 => write!(writer, "_Float16")?,
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::Float16 => write!(writer, "_Float16 complex")?,
285                    FloatKind::Float => write!(writer, "float complex")?,
286                    FloatKind::Double => write!(writer, "double complex")?,
287                    FloatKind::LongDouble => {
288                        write!(writer, "long double complex")?;
289                    }
290                    FloatKind::Float128 => write!(writer, "__complex128")?,
291                }
292            }
293            TypeKind::Alias(type_id) => {
294                if let Some(name) = self.name() {
295                    if self.is_const() {
296                        write!(writer, "const {name}")?;
297                    } else {
298                        write!(writer, "{name}")?;
299                    }
300                } else {
301                    type_id.serialize(ctx, (), stack, writer)?;
302                }
303            }
304            TypeKind::Array(type_id, length) => {
305                type_id.serialize(ctx, (), stack, writer)?;
306                write!(writer, " [{length}]")?;
307            }
308            TypeKind::Function(signature) => {
309                if self.is_const() {
310                    stack.push("const ".to_string());
311                }
312
313                signature.return_type().serialize(
314                    ctx,
315                    (),
316                    &mut vec![],
317                    writer,
318                )?;
319
320                write!(writer, " (")?;
321                while let Some(item) = stack.pop() {
322                    write!(writer, "{item}")?;
323                }
324                write!(writer, ")")?;
325
326                let args = signature.argument_types();
327                if args.is_empty() {
328                    write!(writer, " (void)")?;
329                } else {
330                    write!(writer, " (")?;
331                    serialize_sep(
332                        ", ",
333                        args.iter(),
334                        ctx,
335                        writer,
336                        |(name, type_id), ctx, buf| {
337                            let mut stack = vec![];
338                            if let Some(name) = name {
339                                stack.push(name.clone());
340                            }
341                            type_id.serialize(ctx, (), &mut stack, buf)
342                        },
343                    )?;
344                    write!(writer, ")")?;
345                }
346            }
347            TypeKind::ResolvedTypeRef(type_id) => {
348                if self.is_const() {
349                    write!(writer, "const ")?;
350                }
351                type_id.serialize(ctx, (), stack, writer)?;
352            }
353            TypeKind::Pointer(type_id) => {
354                if self.is_const() {
355                    stack.push("*const ".to_owned());
356                } else {
357                    stack.push("*".to_owned());
358                }
359                type_id.serialize(ctx, (), stack, writer)?;
360            }
361            TypeKind::Comp(comp_info) => {
362                if self.is_const() {
363                    write!(writer, "const ")?;
364                }
365
366                let name = item.canonical_name(ctx);
367
368                match comp_info.kind() {
369                    CompKind::Struct => write!(writer, "struct {name}")?,
370                    CompKind::Union => write!(writer, "union {name}")?,
371                };
372            }
373            TypeKind::Enum(_enum_ty) => {
374                if self.is_const() {
375                    write!(writer, "const ")?;
376                }
377
378                let name = item.canonical_name(ctx);
379                write!(writer, "enum {name}")?;
380            }
381            ty => {
382                return Err(CodegenError::Serialize {
383                    msg: format!("Cannot serialize type kind {ty:?}"),
384                    loc: get_loc(item),
385                })
386            }
387        };
388
389        if !stack.is_empty() {
390            write!(writer, " ")?;
391            while let Some(item) = stack.pop() {
392                write!(writer, "{item}")?;
393            }
394        }
395
396        Ok(())
397    }
398}
399
400fn serialize_args<W: Write>(
401    args: &[(String, TypeId)],
402    ctx: &BindgenContext,
403    writer: &mut W,
404) -> Result<(), CodegenError> {
405    if args.is_empty() {
406        write!(writer, "void")?;
407    } else {
408        serialize_sep(
409            ", ",
410            args.iter(),
411            ctx,
412            writer,
413            |(name, type_id), ctx, buf| {
414                type_id.serialize(ctx, (), &mut vec![name.clone()], buf)
415            },
416        )?;
417    }
418
419    Ok(())
420}
421
422fn serialize_sep<
423    W: Write,
424    F: FnMut(I::Item, &BindgenContext, &mut W) -> Result<(), CodegenError>,
425    I: Iterator,
426>(
427    sep: &str,
428    mut iter: I,
429    ctx: &BindgenContext,
430    buf: &mut W,
431    mut f: F,
432) -> Result<(), CodegenError> {
433    if let Some(item) = iter.next() {
434        f(item, ctx, buf)?;
435        let sep = sep.as_bytes();
436        for item in iter {
437            buf.write_all(sep)?;
438            f(item, ctx, buf)?;
439        }
440    }
441
442    Ok(())
443}