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 | |
15 | fn get_loc(item: &Item) -> String { |
16 | itemOption.location() |
17 | .map(|x: &SourceLocation| x.to_string()) |
18 | .unwrap_or_else(|| "unknown" .to_owned()) |
19 | } |
20 | |
21 | pub(super) trait CSerialize<'a> { |
22 | type Extra; |
23 | |
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 | |
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: &Function) => { |
45 | func.serialize(ctx, (self, extra), stack, writer) |
46 | } |
47 | kind: &ItemKind => 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 | |
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 | |
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: &Item = ctx.resolve_item(*self); |
212 | item.expect_type().serialize(ctx, extra:item, stack, writer) |
213 | } |
214 | } |
215 | |
216 | impl<'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 {:?}" , |
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 | |
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 | sep:", " , |
411 | args.iter(), |
412 | ctx, |
413 | buf:writer, |
414 | |(name: &String, type_id: &TypeId), ctx: &BindgenContext, buf: &mut W| { |
415 | type_id.serialize(ctx, (), &mut vec![name.clone()], writer:buf) |
416 | }, |
417 | )?; |
418 | } |
419 | |
420 | Ok(()) |
421 | } |
422 | |
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: ::Item) = iter.next() { |
435 | f(item, ctx, buf)?; |
436 | let sep: &[u8] = sep.as_bytes(); |
437 | for item: ::Item in iter { |
438 | buf.write_all(buf:sep)?; |
439 | f(item, ctx, buf)?; |
440 | } |
441 | } |
442 | |
443 | Ok(()) |
444 | } |
445 | |