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 | |
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(crate) 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 = (); |
35 | |
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: &Function) => { |
45 | func.serialize(ctx, self, stack, writer) |
46 | } |
47 | kind: &ItemKind => { |
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 | |
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 | |
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: &Item = ctx.resolve_item(*self); |
161 | item.expect_type().serialize(ctx, extra:item, stack, writer) |
162 | } |
163 | } |
164 | |
165 | impl<'a> CSerialize<'a> for Type { |
166 | type Extra = &'a Item; |
167 | |
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 | |
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: ::Item) = iter.next() { |
347 | f(item, ctx, buf)?; |
348 | let sep: &[u8] = sep.as_bytes(); |
349 | for item: ::Item in iter { |
350 | buf.write_all(buf:sep)?; |
351 | f(item, ctx, buf)?; |
352 | } |
353 | } |
354 | |
355 | Ok(()) |
356 | } |
357 | |