• 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;
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(crate) 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 = ();
35 
serialize<W: Write>( &self, ctx: &BindgenContext, (): Self::Extra, stack: &mut Vec<String>, writer: &mut W, ) -> Result<(), CodegenError>36     fn serialize<W: Write>(
37         &self,
38         ctx: &BindgenContext,
39         (): 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, stack, writer)
46             }
47             kind => {
48                 return Err(CodegenError::Serialize {
49                     msg: format!("Cannot serialize item kind {:?}", kind),
50                     loc: get_loc(self),
51                 });
52             }
53         }
54     }
55 }
56 
57 impl<'a> CSerialize<'a> for Function {
58     type Extra = &'a Item;
59 
serialize<W: Write>( &self, ctx: &BindgenContext, item: Self::Extra, stack: &mut Vec<String>, writer: &mut W, ) -> Result<(), CodegenError>60     fn serialize<W: Write>(
61         &self,
62         ctx: &BindgenContext,
63         item: Self::Extra,
64         stack: &mut Vec<String>,
65         writer: &mut W,
66     ) -> Result<(), CodegenError> {
67         if self.kind() != FunctionKind::Function {
68             return Err(CodegenError::Serialize {
69                 msg: format!(
70                     "Cannot serialize function kind {:?}",
71                     self.kind(),
72                 ),
73                 loc: get_loc(item),
74             });
75         }
76 
77         let signature = match ctx.resolve_type(self.signature()).kind() {
78             TypeKind::Function(signature) => signature,
79             _ => unreachable!(),
80         };
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             signature
89                 .argument_types()
90                 .iter()
91                 .cloned()
92                 .map(|(opt_name, type_id)| {
93                     (
94                         opt_name.unwrap_or_else(|| {
95                             let name = format!("arg_{}", count);
96                             count += 1;
97                             name
98                         }),
99                         type_id,
100                     )
101                 })
102                 .collect::<Vec<_>>()
103         };
104 
105         // The name used for the wrapper self.
106         let wrap_name = format!("{}{}", name, ctx.wrap_static_fns_suffix());
107         // The function's return type
108         let ret_ty = signature.return_type();
109 
110         // Write `ret_ty wrap_name(args) asm("wrap_name");`
111         ret_ty.serialize(ctx, (), stack, writer)?;
112         write!(writer, " {}(", wrap_name)?;
113         if args.is_empty() {
114             write!(writer, "void")?;
115         } else {
116             serialize_sep(
117                 ", ",
118                 args.iter(),
119                 ctx,
120                 writer,
121                 |(name, type_id), ctx, buf| {
122                     type_id.serialize(ctx, (), &mut vec![name.clone()], buf)
123                 },
124             )?;
125         }
126         writeln!(writer, ") asm(\"{}\");", wrap_name)?;
127 
128         // Write `ret_ty wrap_name(args) { return name(arg_names)' }`
129         ret_ty.serialize(ctx, (), stack, writer)?;
130         write!(writer, " {}(", wrap_name)?;
131         serialize_sep(
132             ", ",
133             args.iter(),
134             ctx,
135             writer,
136             |(name, type_id), _, buf| {
137                 type_id.serialize(ctx, (), &mut vec![name.clone()], buf)
138             },
139         )?;
140         write!(writer, ") {{ return {}(", name)?;
141         serialize_sep(", ", args.iter(), ctx, writer, |(name, _), _, buf| {
142             write!(buf, "{}", name).map_err(From::from)
143         })?;
144         writeln!(writer, "); }}")?;
145 
146         Ok(())
147     }
148 }
149 
150 impl<'a> CSerialize<'a> for TypeId {
151     type Extra = ();
152 
serialize<W: Write>( &self, ctx: &BindgenContext, (): Self::Extra, stack: &mut Vec<String>, writer: &mut W, ) -> Result<(), CodegenError>153     fn serialize<W: Write>(
154         &self,
155         ctx: &BindgenContext,
156         (): Self::Extra,
157         stack: &mut Vec<String>,
158         writer: &mut W,
159     ) -> Result<(), CodegenError> {
160         let item = ctx.resolve_item(*self);
161         item.expect_type().serialize(ctx, item, stack, writer)
162     }
163 }
164 
165 impl<'a> CSerialize<'a> for Type {
166     type Extra = &'a Item;
167 
serialize<W: Write>( &self, ctx: &BindgenContext, item: Self::Extra, stack: &mut Vec<String>, writer: &mut W, ) -> Result<(), CodegenError>168     fn serialize<W: Write>(
169         &self,
170         ctx: &BindgenContext,
171         item: Self::Extra,
172         stack: &mut Vec<String>,
173         writer: &mut W,
174     ) -> Result<(), CodegenError> {
175         match self.kind() {
176             TypeKind::Void => {
177                 if self.is_const() {
178                     write!(writer, "const ")?;
179                 }
180                 write!(writer, "void")?
181             }
182             TypeKind::NullPtr => {
183                 if self.is_const() {
184                     write!(writer, "const ")?;
185                 }
186                 write!(writer, "nullptr_t")?
187             }
188             TypeKind::Int(int_kind) => {
189                 if self.is_const() {
190                     write!(writer, "const ")?;
191                 }
192                 match int_kind {
193                     IntKind::Bool => write!(writer, "bool")?,
194                     IntKind::SChar => write!(writer, "signed char")?,
195                     IntKind::UChar => write!(writer, "unsigned char")?,
196                     IntKind::WChar => write!(writer, "wchar_t")?,
197                     IntKind::Short => write!(writer, "short")?,
198                     IntKind::UShort => write!(writer, "unsigned short")?,
199                     IntKind::Int => write!(writer, "int")?,
200                     IntKind::UInt => write!(writer, "unsigned int")?,
201                     IntKind::Long => write!(writer, "long")?,
202                     IntKind::ULong => write!(writer, "unsigned long")?,
203                     IntKind::LongLong => write!(writer, "long long")?,
204                     IntKind::ULongLong => write!(writer, "unsigned long long")?,
205                     IntKind::Char { .. } => write!(writer, "char")?,
206                     int_kind => {
207                         return Err(CodegenError::Serialize {
208                             msg: format!(
209                                 "Cannot serialize integer kind {:?}",
210                                 int_kind
211                             ),
212                             loc: get_loc(item),
213                         })
214                     }
215                 }
216             }
217             TypeKind::Float(float_kind) => {
218                 if self.is_const() {
219                     write!(writer, "const ")?;
220                 }
221                 match float_kind {
222                     FloatKind::Float => write!(writer, "float")?,
223                     FloatKind::Double => write!(writer, "double")?,
224                     FloatKind::LongDouble => write!(writer, "long double")?,
225                     FloatKind::Float128 => write!(writer, "__float128")?,
226                 }
227             }
228             TypeKind::Complex(float_kind) => {
229                 if self.is_const() {
230                     write!(writer, "const ")?;
231                 }
232                 match float_kind {
233                     FloatKind::Float => write!(writer, "float complex")?,
234                     FloatKind::Double => write!(writer, "double complex")?,
235                     FloatKind::LongDouble => {
236                         write!(writer, "long double complex")?
237                     }
238                     FloatKind::Float128 => write!(writer, "__complex128")?,
239                 }
240             }
241             TypeKind::Alias(type_id) => {
242                 if let Some(name) = self.name() {
243                     if self.is_const() {
244                         write!(writer, "const {}", name)?;
245                     } else {
246                         write!(writer, "{}", name)?;
247                     }
248                 } else {
249                     type_id.serialize(ctx, (), stack, writer)?;
250                 }
251             }
252             TypeKind::Array(type_id, length) => {
253                 type_id.serialize(ctx, (), stack, writer)?;
254                 write!(writer, " [{}]", length)?
255             }
256             TypeKind::Function(signature) => {
257                 if self.is_const() {
258                     stack.push("const ".to_string());
259                 }
260 
261                 signature.return_type().serialize(
262                     ctx,
263                     (),
264                     &mut vec![],
265                     writer,
266                 )?;
267 
268                 write!(writer, " (")?;
269                 while let Some(item) = stack.pop() {
270                     write!(writer, "{}", item)?;
271                 }
272                 write!(writer, ")")?;
273 
274                 write!(writer, " (")?;
275                 serialize_sep(
276                     ", ",
277                     signature.argument_types().iter(),
278                     ctx,
279                     writer,
280                     |(name, type_id), ctx, buf| {
281                         let mut stack = vec![];
282                         if let Some(name) = name {
283                             stack.push(name.clone());
284                         }
285                         type_id.serialize(ctx, (), &mut stack, buf)
286                     },
287                 )?;
288                 write!(writer, ")")?
289             }
290             TypeKind::ResolvedTypeRef(type_id) => {
291                 if self.is_const() {
292                     write!(writer, "const ")?;
293                 }
294                 type_id.serialize(ctx, (), stack, writer)?
295             }
296             TypeKind::Pointer(type_id) => {
297                 if self.is_const() {
298                     stack.push("*const ".to_owned());
299                 } else {
300                     stack.push("*".to_owned());
301                 }
302                 type_id.serialize(ctx, (), stack, writer)?
303             }
304             TypeKind::Comp(comp_info) => {
305                 if self.is_const() {
306                     write!(writer, "const ")?;
307                 }
308 
309                 let name = item.canonical_name(ctx);
310 
311                 match comp_info.kind() {
312                     CompKind::Struct => write!(writer, "struct {}", name)?,
313                     CompKind::Union => write!(writer, "union {}", name)?,
314                 };
315             }
316             ty => {
317                 return Err(CodegenError::Serialize {
318                     msg: format!("Cannot serialize type kind {:?}", ty),
319                     loc: get_loc(item),
320                 })
321             }
322         };
323 
324         if !stack.is_empty() {
325             write!(writer, " ")?;
326             while let Some(item) = stack.pop() {
327                 write!(writer, "{}", item)?;
328             }
329         }
330 
331         Ok(())
332     }
333 }
334 
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>335 fn serialize_sep<
336     W: Write,
337     F: FnMut(I::Item, &BindgenContext, &mut W) -> Result<(), CodegenError>,
338     I: Iterator,
339 >(
340     sep: &str,
341     mut iter: I,
342     ctx: &BindgenContext,
343     buf: &mut W,
344     mut f: F,
345 ) -> Result<(), CodegenError> {
346     if let Some(item) = iter.next() {
347         f(item, ctx, buf)?;
348         let sep = sep.as_bytes();
349         for item in iter {
350             buf.write_all(sep)?;
351             f(item, ctx, buf)?;
352         }
353     }
354 
355     Ok(())
356 }
357