Skip to content

Commit 366fe55

Browse files
committed
only require wasm dependencies when targetting wasm
1 parent aab2431 commit 366fe55

File tree

4 files changed

+329
-316
lines changed

4 files changed

+329
-316
lines changed

crates/stdsimd-test/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ backtrace = "0.3"
1010
cc = "1.0"
1111
lazy_static = "1.0"
1212
rustc-demangle = "0.1.8"
13+
cfg-if = "0.1"
14+
15+
[target.wasm32-unknown-unknown.dependencies]
1316
wasm-bindgen = "=0.2.19"
1417

1518
[features]
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
//! Disassembly calling function for most targets.
2+
3+
use ::*;
4+
use std::process::Command;
5+
6+
pub(crate) fn disassemble_myself() -> HashMap<String, Vec<Function>> {
7+
let me = env::current_exe().expect("failed to get current exe");
8+
9+
if cfg!(target_arch = "x86_64")
10+
&& cfg!(target_os = "windows")
11+
&& cfg!(target_env = "msvc")
12+
{
13+
let mut cmd = cc::windows_registry::find(
14+
"x86_64-pc-windows-msvc",
15+
"dumpbin.exe",
16+
).expect("failed to find `dumpbin` tool");
17+
let output = cmd
18+
.arg("/DISASM")
19+
.arg(&me)
20+
.output()
21+
.expect("failed to execute dumpbin");
22+
println!(
23+
"{}\n{}",
24+
output.status,
25+
String::from_utf8_lossy(&output.stderr)
26+
);
27+
assert!(output.status.success());
28+
parse_dumpbin(&String::from_utf8_lossy(&output.stdout))
29+
} else if cfg!(target_os = "windows") {
30+
panic!("disassembly unimplemented")
31+
} else if cfg!(target_os = "macos") {
32+
let output = Command::new("otool")
33+
.arg("-vt")
34+
.arg(&me)
35+
.output()
36+
.expect("failed to execute otool");
37+
println!(
38+
"{}\n{}",
39+
output.status,
40+
String::from_utf8_lossy(&output.stderr)
41+
);
42+
assert!(output.status.success());
43+
44+
parse_otool(str::from_utf8(&output.stdout).expect("stdout not utf8"))
45+
} else {
46+
let objdump =
47+
env::var("OBJDUMP").unwrap_or_else(|_| "objdump".to_string());
48+
let output = Command::new(objdump.clone())
49+
.arg("--disassemble")
50+
.arg(&me)
51+
.output()
52+
.expect(&format!(
53+
"failed to execute objdump. OBJDUMP={}",
54+
objdump
55+
));
56+
println!(
57+
"{}\n{}",
58+
output.status,
59+
String::from_utf8_lossy(&output.stderr)
60+
);
61+
assert!(output.status.success());
62+
63+
parse_objdump(str::from_utf8(&output.stdout).expect("stdout not utf8"))
64+
}
65+
}
66+
67+
fn parse_objdump(output: &str) -> HashMap<String, Vec<Function>> {
68+
let mut lines = output.lines();
69+
let expected_len =
70+
if cfg!(target_arch = "arm") || cfg!(target_arch = "aarch64") {
71+
8
72+
} else {
73+
2
74+
};
75+
76+
for line in output.lines().take(100) {
77+
println!("{}", line);
78+
}
79+
80+
let mut ret = HashMap::new();
81+
while let Some(header) = lines.next() {
82+
// symbols should start with `$hex_addr <$name>:`
83+
if !header.ends_with(">:") {
84+
continue;
85+
}
86+
let start = header.find('<')
87+
.expect(&format!("\"<\" not found in symbol pattern of the form \"$hex_addr <$name>\": {}", header));
88+
let symbol = &header[start + 1..header.len() - 2];
89+
90+
let mut instructions = Vec::new();
91+
while let Some(instruction) = lines.next() {
92+
if instruction.is_empty() {
93+
break;
94+
}
95+
// Each line of instructions should look like:
96+
//
97+
// $rel_offset: ab cd ef 00 $instruction...
98+
let parts = instruction
99+
.split_whitespace()
100+
.skip(1)
101+
.skip_while(|s| {
102+
s.len() == expected_len
103+
&& usize::from_str_radix(s, 16).is_ok()
104+
}).map(|s| s.to_string())
105+
.collect::<Vec<String>>();
106+
instructions.push(Instruction { parts });
107+
}
108+
109+
ret.entry(normalize(symbol))
110+
.or_insert_with(Vec::new)
111+
.push(Function {
112+
addr: None,
113+
instrs: instructions,
114+
});
115+
}
116+
117+
ret
118+
}
119+
120+
fn parse_otool(output: &str) -> HashMap<String, Vec<Function>> {
121+
let mut lines = output.lines();
122+
123+
for line in output.lines().take(100) {
124+
println!("{}", line);
125+
}
126+
127+
let mut ret = HashMap::new();
128+
let mut cached_header = None;
129+
while let Some(header) = cached_header.take().or_else(|| lines.next()) {
130+
// symbols should start with `$symbol:`
131+
if !header.ends_with(':') {
132+
continue;
133+
}
134+
// strip the leading underscore and the trailing colon
135+
let symbol = &header[1..header.len() - 1];
136+
137+
let mut instructions = Vec::new();
138+
while let Some(instruction) = lines.next() {
139+
if instruction.ends_with(':') {
140+
cached_header = Some(instruction);
141+
break;
142+
}
143+
// Each line of instructions should look like:
144+
//
145+
// $addr $instruction...
146+
let parts = instruction
147+
.split_whitespace()
148+
.skip(1)
149+
.map(|s| s.to_string())
150+
.collect::<Vec<String>>();
151+
instructions.push(Instruction { parts });
152+
}
153+
154+
ret.entry(normalize(symbol))
155+
.or_insert_with(Vec::new)
156+
.push(Function {
157+
addr: None,
158+
instrs: instructions,
159+
});
160+
}
161+
162+
ret
163+
}
164+
165+
fn parse_dumpbin(output: &str) -> HashMap<String, Vec<Function>> {
166+
let mut lines = output.lines();
167+
168+
for line in output.lines().take(100) {
169+
println!("{}", line);
170+
}
171+
172+
let mut ret = HashMap::new();
173+
let mut cached_header = None;
174+
while let Some(header) = cached_header.take().or_else(|| lines.next()) {
175+
// symbols should start with `$symbol:`
176+
if !header.ends_with(':') {
177+
continue;
178+
}
179+
// strip the trailing colon
180+
let symbol = &header[..header.len() - 1];
181+
182+
let mut instructions = Vec::new();
183+
while let Some(instruction) = lines.next() {
184+
if !instruction.starts_with(" ") {
185+
cached_header = Some(instruction);
186+
break;
187+
}
188+
// Each line looks like:
189+
//
190+
// > $addr: ab cd ef $instr..
191+
// > 00 12 # this line os optional
192+
if instruction.starts_with(" ") {
193+
continue;
194+
}
195+
let parts = instruction
196+
.split_whitespace()
197+
.skip(1)
198+
.skip_while(|s| {
199+
s.len() == 2 && usize::from_str_radix(s, 16).is_ok()
200+
}).map(|s| s.to_string())
201+
.collect::<Vec<String>>();
202+
instructions.push(Instruction { parts });
203+
}
204+
205+
ret.entry(normalize(symbol))
206+
.or_insert_with(Vec::new)
207+
.push(Function {
208+
addr: None,
209+
instrs: instructions,
210+
});
211+
}
212+
213+
ret
214+
}

0 commit comments

Comments
 (0)