1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use quote::{quote, ToTokens};
5use syn;
6
7static mut FUNC_NUMBER: i32 = 0;
8
9enum RetTypes {
10 U8 = 1,
11 I8 = 2,
12 U16 = 3,
13 I16 = 4,
14 U32 = 5,
15 I32 = 6,
16 U64 = 7,
17 I64 = 8,
18 F32 = 9,
19 F64 = 10,
20 Bool = 11,
21 Char = 12,
22 U8Array = 21,
23 I8Array = 22,
24 U16Array = 23,
25 I16Array = 24,
26 U32Array = 25,
27 I32Array = 26,
28 U64Array = 27,
29 I64Array = 28,
30 String = 31,
31}
32
33#[proc_macro_attribute]
34pub fn wasmedge_bindgen(_: TokenStream, item: TokenStream) -> TokenStream {
35 let mut ast: syn::ItemFn = syn::parse(item).unwrap();
36
37 let func_ident = ast.sig.ident;
38
39 let ori_run: String;
40 unsafe {
41 ori_run = format!("run{}", FUNC_NUMBER);
42 FUNC_NUMBER += 1;
43 }
44 let ori_run_ident = proc_macro2::Ident::new(ori_run.as_str(), proc_macro2::Span::call_site());
45 ast.sig.ident = ori_run_ident.clone();
46
47 let (arg_names, arg_values) = parse_params(&ast);
48 let (ret_names, ret_pointers, ret_types, ret_sizes, is_rust_result) = parse_returns(&ast);
49 let ret_len = ret_names.len();
50 let ret_i = (0..ret_len).map(syn::Index::from);
51
52 let params_len = arg_names.len();
53 let i = (0..params_len).map(syn::Index::from);
54
55 let ret_result = match is_rust_result {
56 true => quote! {
57 match #ori_run_ident(#(#arg_names),*) {
58 Ok((#(#ret_names),*)) => {
59 let mut result_vec = vec![0; #ret_len * 3];
60 #(
61 result_vec[#ret_i * 3 + 2] = #ret_sizes;
62 result_vec[#ret_i * 3] = #ret_pointers;
63 result_vec[#ret_i * 3 + 1] = #ret_types;
64 )*
65 let result_vec = std::mem::ManuallyDrop::new(result_vec);
66 let mut rvec = vec![0 as u8; 9];
68 rvec.splice(1..5, (result_vec.as_ptr() as i32).to_le_bytes());
69 rvec.splice(5..9, (#ret_len as i32).to_le_bytes());
70 let rvec = std::mem::ManuallyDrop::new(rvec);
71 return rvec.as_ptr() as i32;
72 }
73 Err(message) => {
74 let message = std::mem::ManuallyDrop::new(message);
75 let mut rvec = vec![1 as u8; 9];
77 rvec.splice(1..5, (message.as_ptr() as i32).to_le_bytes());
78 rvec.splice(5..9, (message.len() as i32).to_le_bytes());
79 let rvec = std::mem::ManuallyDrop::new(rvec);
80 return rvec.as_ptr() as i32;
81 }
82 }
83 },
84 false => quote! {
85 let (#(#ret_names),*) = #ori_run_ident(#(#arg_names),*);
86 let mut result_vec = vec![0; #ret_len * 3];
87 #(
88 result_vec[#ret_i * 3 + 2] = #ret_sizes;
89 result_vec[#ret_i * 3] = #ret_pointers;
90 result_vec[#ret_i * 3 + 1] = #ret_types;
91 )*
92 let result_vec = std::mem::ManuallyDrop::new(result_vec);
93 let mut rvec = vec![0 as u8; 9];
95 rvec.splice(1..5, (result_vec.as_ptr() as i32).to_le_bytes());
96 rvec.splice(5..9, (#ret_len as i32).to_le_bytes());
97 let rvec = std::mem::ManuallyDrop::new(rvec);
98 return rvec.as_ptr() as i32;
99 }
100 };
101
102 let gen = quote! {
103
104 #[no_mangle]
105 pub unsafe extern "C" fn #func_ident(params_pointer: *mut u32, params_count: i32) -> i32 {
106 if #params_len != params_count as usize {
107 let err_msg = format!("Invalid params count, expect {}, got {}", #params_len, params_count);
108 let err_msg = std::mem::ManuallyDrop::new(err_msg);
109 let mut rvec = vec![1 as u8; 9];
111 rvec.splice(1..5, (err_msg.as_ptr() as i32).to_le_bytes());
112 rvec.splice(5..9, (err_msg.len() as i32).to_le_bytes());
113 let rvec = std::mem::ManuallyDrop::new(rvec);
114 return rvec.as_ptr() as i32;
115 }
116
117 #(
118 let pointer = *params_pointer.offset(#i * 2) as *mut u8;
119 let size= *params_pointer.offset(#i * 2 + 1);
120 let #arg_names = #arg_values;
121 )*
122
123 #ret_result;
124 }
125 };
126
127 let ori_run_str = ast.to_token_stream().to_string();
128 let x = gen.to_string() + &ori_run_str;
129 x.parse().unwrap()
130}
131
132
133fn parse_returns(ast: &syn::ItemFn) -> (Vec::<syn::Ident>, Vec::<proc_macro2::TokenStream>, Vec::<i32>, Vec::<proc_macro2::TokenStream>, bool) {
134 let mut ret_names = Vec::<syn::Ident>::new();
135 let mut ret_pointers = Vec::<proc_macro2::TokenStream>::new();
136 let mut ret_types = Vec::<i32>::new();
137 let mut ret_sizes = Vec::<proc_macro2::TokenStream>::new();
138 let mut is_rust_result = false;
139
140 let mut prep_types = |seg: &syn::PathSegment, pos: usize| {
141 let ret_name = quote::format_ident!("ret{}", pos.to_string());
142 match seg.ident.to_string().as_str() {
143 "u8" => {
144 ret_pointers.push(quote! {{
145 let x = #ret_name.to_le_bytes()[..].to_vec();
146 std::mem::ManuallyDrop::new(x).as_ptr() as *const u8 as i32
147 }});
148 ret_names.push(ret_name);
149 ret_types.push(RetTypes::U8 as i32);
150 ret_sizes.push(quote! {
151 1
152 });
153 }
154 "i8" => {
155 ret_pointers.push(quote! {{
156 let x = #ret_name.to_le_bytes()[..].to_vec();
157 std::mem::ManuallyDrop::new(x).as_ptr() as *const i8 as i32
158 }});
159 ret_names.push(ret_name);
160 ret_types.push(RetTypes::I8 as i32);
161 ret_sizes.push(quote! {
162 1
163 });
164 }
165 "u16" => {
166 ret_pointers.push(quote! {{
167 let x = #ret_name.to_le_bytes()[..].to_vec();
168 std::mem::ManuallyDrop::new(x).as_ptr() as *const u16 as i32
169 }});
170 ret_names.push(ret_name);
171 ret_types.push(RetTypes::U16 as i32);
172 ret_sizes.push(quote! {
173 2
174 });
175 }
176 "i16" => {
177 ret_pointers.push(quote! {{
178 let x = #ret_name.to_le_bytes()[..].to_vec();
179 std::mem::ManuallyDrop::new(x).as_ptr() as *const i16 as i32
180 }});
181 ret_names.push(ret_name);
182 ret_types.push(RetTypes::I16 as i32);
183 ret_sizes.push(quote! {
184 2
185 });
186 }
187 "u32" => {
188 ret_pointers.push(quote! {{
189 let x = #ret_name.to_le_bytes()[..].to_vec();
190 std::mem::ManuallyDrop::new(x).as_ptr() as *const u32 as i32
191 }});
192 ret_names.push(ret_name);
193 ret_types.push(RetTypes::U32 as i32);
194 ret_sizes.push(quote! {
195 4
196 });
197 }
198 "i32" => {
199 ret_pointers.push(quote! {{
200 let x = #ret_name.to_le_bytes()[..].to_vec();
201 std::mem::ManuallyDrop::new(x).as_ptr() as *const i32 as i32
202 }});
203 ret_names.push(ret_name);
204 ret_types.push(RetTypes::I32 as i32);
205 ret_sizes.push(quote! {
206 4
207 });
208 }
209 "u64" => {
210 ret_pointers.push(quote! {{
211 let x = #ret_name.to_le_bytes()[..].to_vec();
212 std::mem::ManuallyDrop::new(x).as_ptr() as *const u64 as i32
213 }});
214 ret_names.push(ret_name);
215 ret_types.push(RetTypes::U64 as i32);
216 ret_sizes.push(quote! {
217 8
218 });
219 }
220 "i64" => {
221 ret_pointers.push(quote! {{
222 let x = #ret_name.to_le_bytes()[..].to_vec();
223 std::mem::ManuallyDrop::new(x).as_ptr() as *const i64 as i32
224 }});
225 ret_names.push(ret_name);
226 ret_types.push(RetTypes::I64 as i32);
227 ret_sizes.push(quote! {
228 8
229 });
230 }
231 "f32" => {
232 ret_pointers.push(quote! {{
233 let x = #ret_name.to_le_bytes()[..].to_vec();
234 std::mem::ManuallyDrop::new(x).as_ptr() as *const f32 as i32
235 }});
236 ret_names.push(ret_name);
237 ret_types.push(RetTypes::F32 as i32);
238 ret_sizes.push(quote! {
239 4
240 });
241 }
242 "f64" => {
243 ret_pointers.push(quote! {{
244 let x = #ret_name.to_le_bytes()[..].to_vec();
245 std::mem::ManuallyDrop::new(x).as_ptr() as *const f64 as i32
246 }});
247 ret_names.push(ret_name);
248 ret_types.push(RetTypes::F64 as i32);
249 ret_sizes.push(quote! {
250 8
251 });
252 }
253 "bool" => {
254 ret_pointers.push(quote! {{
255 let x = #ret_name.to_le_bytes()[..].to_vec();
256 std::mem::ManuallyDrop::new(x).as_ptr() as *const bool as i32
257 }});
258 ret_names.push(ret_name);
259 ret_types.push(RetTypes::Bool as i32);
260 ret_sizes.push(quote! {
261 1
262 });
263 }
264 "char" => {
265 ret_pointers.push(quote! {{
266 let x = #ret_name.to_le_bytes()[..].to_vec();
267 std::mem::ManuallyDrop::new(x).as_ptr() as *const char as i32
268 }});
269 ret_names.push(ret_name);
270 ret_types.push(RetTypes::Char as i32);
271 ret_sizes.push(quote! {
272 4
273 });
274 }
275 "String" => {
276 ret_pointers.push(quote! {
277 std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
278 });
279 ret_types.push(RetTypes::String as i32);
280 ret_sizes.push(quote! {
281 #ret_name.len() as i32
282 });
283 ret_names.push(ret_name);
284 }
285 "Vec" => {
286 match &seg.arguments {
287 syn::PathArguments::AngleBracketed(args) => {
288 match args.args.first().unwrap() {
289 syn::GenericArgument::Type(arg_type) => {
290 match arg_type {
291 syn::Type::Path(arg_type_path) => {
292 let arg_seg = arg_type_path.path.segments.first().unwrap();
293 match arg_seg.ident.to_string().as_str() {
294 "u8" => {
295 ret_pointers.push(quote! {
296 std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
297 });
298 ret_sizes.push(quote! {
299 #ret_name.len() as i32
300 });
301 ret_types.push(RetTypes::U8Array as i32);
302 ret_names.push(ret_name);
303 }
304 "i8" => {
305 ret_pointers.push(quote! {
306 std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
307 });
308 ret_sizes.push(quote! {
309 #ret_name.len() as i32
310 });
311 ret_types.push(RetTypes::I8Array as i32);
312 ret_names.push(ret_name);
313 }
314 "u16" => {
315 ret_pointers.push(quote! {
316 std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
317 });
318 ret_sizes.push(quote! {
319 #ret_name.len() as i32 * 2
320 });
321 ret_types.push(RetTypes::U16Array as i32);
322 ret_names.push(ret_name);
323 }
324 "i16" => {
325 ret_pointers.push(quote! {
326 std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
327 });
328 ret_sizes.push(quote! {
329 #ret_name.len() as i32 * 2
330 });
331 ret_types.push(RetTypes::I16Array as i32);
332 ret_names.push(ret_name);
333 }
334 "u32" => {
335 ret_pointers.push(quote! {
336 std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
337 });
338 ret_sizes.push(quote! {
339 #ret_name.len() as i32 * 4
340 });
341 ret_types.push(RetTypes::U32Array as i32);
342 ret_names.push(ret_name);
343 }
344 "i32" => {
345 ret_pointers.push(quote! {
346 std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
347 });
348 ret_sizes.push(quote! {
349 #ret_name.len() as i32 * 4
350 });
351 ret_types.push(RetTypes::I32Array as i32);
352 ret_names.push(ret_name);
353 }
354 "u64" => {
355 ret_pointers.push(quote! {
356 std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
357 });
358 ret_sizes.push(quote! {
359 #ret_name.len() as i32 * 8
360 });
361 ret_types.push(RetTypes::U64Array as i32);
362 ret_names.push(ret_name);
363 }
364 "i64" => {
365 ret_pointers.push(quote! {
366 std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
367 });
368 ret_sizes.push(quote! {
369 #ret_name.len() as i32 * 8
370 });
371 ret_types.push(RetTypes::I64Array as i32);
372 ret_names.push(ret_name);
373 }
374 _ => {}
375 }
376 }
377 _ => {}
378 }
379 }
380 _ => {}
381 }
382 }
383 _ => {}
384 }
385 }
386 _ => {}
387 }
388 };
389
390 match ast.sig.output {
391 syn::ReturnType::Type(_, ref rt) => {
392 match &**rt {
393 syn::Type::Path(type_path) => {
394 let seg = &type_path.path.segments.first().unwrap();
395 let seg_type = seg.ident.to_string();
396 if seg_type == "Result" {
397 is_rust_result = true;
398 match &seg.arguments {
399 syn::PathArguments::AngleBracketed(args) => {
400 match args.args.first().unwrap() {
401 syn::GenericArgument::Type(arg_type) => {
402 match arg_type {
403 syn::Type::Path(arg_type_path) => {
404 let arg_seg = arg_type_path.path.segments.first().unwrap();
405 prep_types(&arg_seg, 0)
406 }
407 syn::Type::Tuple(arg_type_tuple) => {
408 for (pos, elem) in arg_type_tuple.elems.iter().enumerate() {
409 match elem {
410 syn::Type::Path(type_path) => {
411 let seg = &type_path.path.segments.first().unwrap();
412 prep_types(&seg, pos);
413 }
414 _ => {}
415 }
416 }
417 }
418 _ => {}
419 }
420 }
421 _ => {}
422 }
423 }
424 _ => {}
425 }
426 } else {
427 prep_types(&seg, 0);
428 }
429 }
430 syn::Type::Tuple(type_tuple) => {
431 for (pos, elem) in type_tuple.elems.iter().enumerate() {
432 match elem {
433 syn::Type::Path(type_path) => {
434 let seg = &type_path.path.segments.first().unwrap();
435 prep_types(&seg, pos);
436 }
437 _ => {}
438 }
439 }
440 }
441 _ => {}
442 }
443 }
444 _ => {}
445 }
446
447 (ret_names, ret_pointers, ret_types, ret_sizes, is_rust_result)
448}
449
450fn parse_params(ast: &syn::ItemFn) -> (Vec::<syn::Ident>, Vec::<proc_macro2::TokenStream>) {
451 let mut arg_names = Vec::<syn::Ident>::new();
452 let mut arg_values = Vec::<proc_macro2::TokenStream>::new();
453
454 let params_iter = ast.sig.inputs.iter();
455 for (pos, param) in params_iter.enumerate() {
456 match param {
457 syn::FnArg::Typed(param_type) => {
458 match &*param_type.ty {
459 syn::Type::Path(type_path) => {
460 let seg = &type_path.path.segments.first().unwrap();
461 match seg.ident.to_string().as_str() {
462 "Vec" => {
463 match &seg.arguments {
464 syn::PathArguments::AngleBracketed(args) => {
465 match args.args.first().unwrap() {
466 syn::GenericArgument::Type(arg_type) => {
467 match arg_type {
468 syn::Type::Path(arg_type_path) => {
469 let arg_seg = arg_type_path.path.segments.first().unwrap();
470 match arg_seg.ident.to_string().as_str() {
471 "u8" => {
472 arg_names.push(quote::format_ident!("arg{}", pos));
473 arg_values.push(quote! {
474 Vec::from_raw_parts(pointer, size as usize, size as usize)
475 })
476 }
477 "i8" => {
478 arg_names.push(quote::format_ident!("arg{}", pos));
479 arg_values.push(quote! {
480 Vec::from_raw_parts(pointer as *mut i8, size as usize, size as usize)
481 })
482 }
483 "u16" => {
484 arg_names.push(quote::format_ident!("arg{}", pos));
485 arg_values.push(quote! {
486 Vec::from_raw_parts(pointer as *mut u16, size as usize, size as usize)
487 })
488 }
489 "i16" => {
490 arg_names.push(quote::format_ident!("arg{}", pos));
491 arg_values.push(quote! {
492 Vec::from_raw_parts(pointer as *mut i16, size as usize, size as usize)
493 })
494 }
495 "u32" => {
496 arg_names.push(quote::format_ident!("arg{}", pos));
497 arg_values.push(quote! {
498 Vec::from_raw_parts(pointer as *mut u32, size as usize, size as usize)
499 })
500 }
501 "i32" => {
502 arg_names.push(quote::format_ident!("arg{}", pos));
503 arg_values.push(quote! {
504 Vec::from_raw_parts(pointer as *mut i32, size as usize, size as usize)
505 })
506 }
507 "u64" => {
508 arg_names.push(quote::format_ident!("arg{}", pos));
509 arg_values.push(quote! {
510 Vec::from_raw_parts(pointer as *mut u64, size as usize, size as usize)
511 })
512 }
513 "i64" => {
514 arg_names.push(quote::format_ident!("arg{}", pos));
515 arg_values.push(quote! {
516 Vec::from_raw_parts(pointer as *mut i64, size as usize, size as usize)
517 })
518 }
519 _ => {}
520 }
521 }
522 _ => {}
523 }
524 }
525 _ => {}
526 }
527 }
528 _ => {}
529 }
530 }
531 "bool" => {
532 arg_names.push(quote::format_ident!("arg{}", pos));
533 arg_values.push(quote! {
534 Vec::from_raw_parts(pointer as *mut bool, size as usize, size as usize)[0]
535 })
536 }
537 "char" => {
538 arg_names.push(quote::format_ident!("arg{}", pos));
539 arg_values.push(quote! {
540 Vec::from_raw_parts(pointer as *mut char, size as usize, size as usize)[0]
541 })
542 }
543 "i8" => {
544 arg_names.push(quote::format_ident!("arg{}", pos));
545 arg_values.push(quote! {
546 Vec::from_raw_parts(pointer as *mut i8, size as usize, size as usize)[0]
547 })
548 }
549 "u8" => {
550 arg_names.push(quote::format_ident!("arg{}", pos));
551 arg_values.push(quote! {
552 Vec::from_raw_parts(pointer as *mut u8, size as usize, size as usize)[0]
553 })
554 }
555 "i16" => {
556 arg_names.push(quote::format_ident!("arg{}", pos));
557 arg_values.push(quote! {
558 Vec::from_raw_parts(pointer as *mut i16, size as usize, size as usize)[0]
559 })
560 }
561 "u16" => {
562 arg_names.push(quote::format_ident!("arg{}", pos));
563 arg_values.push(quote! {
564 Vec::from_raw_parts(pointer as *mut u16, size as usize, size as usize)[0]
565 })
566 }
567 "i32" => {
568 arg_names.push(quote::format_ident!("arg{}", pos));
569 arg_values.push(quote! {
570 Vec::from_raw_parts(pointer as *mut i32, size as usize, size as usize)[0]
571 })
572 }
573 "u32" => {
574 arg_names.push(quote::format_ident!("arg{}", pos));
575 arg_values.push(quote! {
576 Vec::from_raw_parts(pointer as *mut u32, size as usize, size as usize)[0]
577 })
578 }
579 "i64" => {
580 arg_names.push(quote::format_ident!("arg{}", pos));
581 arg_values.push(quote! {
582 Vec::from_raw_parts(pointer as *mut i64, size as usize, size as usize)[0]
583 })
584 }
585 "u64" => {
586 arg_names.push(quote::format_ident!("arg{}", pos));
587 arg_values.push(quote! {
588 Vec::from_raw_parts(pointer as *mut u64, size as usize, size as usize)[0]
589 })
590 }
591 "f32" => {
592 arg_names.push(quote::format_ident!("arg{}", pos));
593 arg_values.push(quote! {
594 Vec::from_raw_parts(pointer as *mut f32, size as usize, size as usize)[0]
595 })
596 }
597 "f64" => {
598 arg_names.push(quote::format_ident!("arg{}", pos));
599 arg_values.push(quote! {
600 Vec::from_raw_parts(pointer as *mut f64, size as usize, size as usize)[0]
601 })
602 }
603 "String" => {
604 arg_names.push(quote::format_ident!("arg{}", pos));
605 arg_values.push(quote! {
606 std::str::from_utf8(&Vec::from_raw_parts(pointer, size as usize, size as usize)).unwrap().to_string()
607 })
608 }
609 _ => {}
610 }
611 }
612 syn::Type::Reference(_) => {
613
614 }
615 syn::Type::Slice(_) => {
616
617 }
618 _ => {}
619 }
620 }
621 _ => {}
622 }
623 }
624
625 (arg_names, arg_values)
626}