]>
Commit | Line | Data |
---|---|---|
0bf4aa26 XL |
1 | //! Disassembly calling function for `wasm32` targets. |
2 | use wasm_bindgen::prelude::*; | |
3 | ||
416331ca XL |
4 | use crate::Function; |
5 | use std::collections::HashSet; | |
0bf4aa26 XL |
6 | |
7 | #[wasm_bindgen(module = "child_process")] | |
8 | extern "C" { | |
416331ca XL |
9 | #[wasm_bindgen(js_name = execFileSync)] |
10 | fn exec_file_sync(cmd: &str, args: &js_sys::Array, opts: &js_sys::Object) -> Buffer; | |
0bf4aa26 XL |
11 | } |
12 | ||
13 | #[wasm_bindgen(module = "buffer")] | |
14 | extern "C" { | |
15 | type Buffer; | |
16 | #[wasm_bindgen(method, js_name = toString)] | |
17 | fn to_string(this: &Buffer) -> String; | |
18 | } | |
19 | ||
20 | #[wasm_bindgen] | |
21 | extern "C" { | |
22 | #[wasm_bindgen(js_namespace = require)] | |
23 | fn resolve(module: &str) -> String; | |
24 | #[wasm_bindgen(js_namespace = console, js_name = log)] | |
0731742a | 25 | pub fn js_console_log(s: &str); |
0bf4aa26 XL |
26 | } |
27 | ||
416331ca | 28 | pub(crate) fn disassemble_myself() -> HashSet<Function> { |
0bf4aa26 XL |
29 | use std::path::Path; |
30 | ::console_error_panic_hook::set_once(); | |
31 | // Our wasm module in the wasm-bindgen test harness is called | |
32 | // "wasm-bindgen-test_bg". When running in node this is actually a shim JS | |
33 | // file. Ask node where that JS file is, and then we use that with a wasm | |
34 | // extension to find the wasm file itself. | |
ba9703b0 XL |
35 | let js_shim = resolve("wasm-bindgen-test"); |
36 | let js_shim = Path::new(&js_shim).with_file_name("wasm-bindgen-test_bg.wasm"); | |
0bf4aa26 XL |
37 | |
38 | // Execute `wasm2wat` synchronously, waiting for and capturing all of its | |
416331ca XL |
39 | // output. Note that we pass in a custom `maxBuffer` parameter because we're |
40 | // generating a ton of output that needs to be buffered. | |
41 | let args = js_sys::Array::new(); | |
42 | args.push(&js_shim.display().to_string().into()); | |
43 | args.push(&"--enable-simd".into()); | |
44 | let opts = js_sys::Object::new(); | |
74b04a01 | 45 | js_sys::Reflect::set(&opts, &"maxBuffer".into(), &(200 * 1024 * 1024).into()).unwrap(); |
416331ca | 46 | let output = exec_file_sync("wasm2wat", &args, &opts).to_string(); |
0bf4aa26 | 47 | |
416331ca | 48 | let mut ret: HashSet<Function> = HashSet::new(); |
0bf4aa26 XL |
49 | let mut lines = output.lines().map(|s| s.trim()); |
50 | while let Some(line) = lines.next() { | |
0bf4aa26 XL |
51 | // If this isn't a function, we don't care about it. |
52 | if !line.starts_with("(func ") { | |
53 | continue; | |
54 | } | |
55 | ||
56 | let mut function = Function { | |
416331ca | 57 | name: String::new(), |
0bf4aa26 | 58 | instrs: Vec::new(), |
0bf4aa26 XL |
59 | }; |
60 | ||
61 | // Empty functions will end in `))` so there's nothing to do, otherwise | |
62 | // we'll have a bunch of following lines which are instructions. | |
63 | // | |
64 | // Lines that have an imbalanced `)` mark the end of a function. | |
65 | if !line.ends_with("))") { | |
66 | while let Some(line) = lines.next() { | |
416331ca | 67 | function.instrs.push(line.to_string()); |
0bf4aa26 XL |
68 | if !line.starts_with("(") && line.ends_with(")") { |
69 | break; | |
70 | } | |
71 | } | |
72 | } | |
0bf4aa26 XL |
73 | // The second element here split on whitespace should be the name of |
74 | // the function, skipping the type/params/results | |
416331ca XL |
75 | function.name = line.split_whitespace().nth(1).unwrap().to_string(); |
76 | if function.name.starts_with("$") { | |
77 | function.name = function.name[1..].to_string() | |
78 | } | |
79 | ||
80 | if !function.name.contains("stdarch_test_shim") { | |
81 | continue; | |
82 | } | |
83 | ||
84 | assert!(ret.insert(function)); | |
0bf4aa26 XL |
85 | } |
86 | return ret; | |
87 | } |