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