1 use super::{BlockType, Elements, FuncType, Instruction, MemArg, Module, ValType};
2 use arbitrary::{Result, Unstructured};
3 use std::collections::{BTreeMap, BTreeSet};
4 use std::convert::TryFrom;
5
6 macro_rules! instructions {
7 (
8 $(
9 ($predicate:expr, $generator_fn:ident $(, $cost:tt)?),
10 )*
11 ) => {
12 static NUM_OPTIONS: usize = instructions!(
13 @count;
14 $( $generator_fn )*
15 );
16
17 fn choose_instruction(
18 u: &mut Unstructured<'_>,
19 module: &Module,
20 builder: &mut CodeBuilder,
21 ) -> Option<
22 fn(&mut Unstructured<'_>, &Module, &mut CodeBuilder) -> Result<Instruction>
23 > {
24 builder.allocs.options.clear();
25 let mut cost = 0;
26 // Unroll the loop that checks whether each instruction is valid in
27 // the current context and, if it is valid, pushes it onto our
28 // options. Unrolling this loops lets us avoid dynamic calls through
29 // function pointers and, furthermore, each call site can be branch
30 // predicted and even inlined. This saved us about 30% of time in
31 // the `corpus` benchmark.
32 $(
33 let predicate: Option<fn(&Module, &mut CodeBuilder) -> bool> = $predicate;
34 if predicate.map_or(true, |f| f(module, builder)) {
35
36 builder.allocs.options.push(($generator_fn, cost));
37 cost += 1000 $(- $cost)?;
38 }
39 )*
40
41 debug_assert!(cost > 0);
42
43 let i = u.int_in_range(0..=cost).ok()?;
44 let idx = builder
45 .allocs
46 .options
47 .binary_search_by_key(&i,|p| p.1)
48 .unwrap_or_else(|i| i - 1);
49 Some(builder.allocs.options[idx].0)
50 }
51 };
52
53 ( @count; ) => {
54 0
55 };
56 ( @count; $x:ident $( $xs:ident )* ) => {
57 1 + instructions!( @count; $( $xs )* )
58 };
59 }
60
61 // The static set of options of instruction to generate that could be valid at
62 // some given time. One entry per Wasm instruction.
63 //
64 // Each entry is made up of up to three parts:
65 //
66 // 1. A predicate for whether this is a valid choice, if any. `None` means that
67 // the choice is always applicable.
68 //
69 // 2. The function to generate the instruction, given that we've made this
70 // choice.
71 //
72 // 3. An optional number used to weight how often this instruction is chosen.
73 // Higher numbers are less likely to be chosen, and number specified must be
74 // less than 1000.
75 instructions! {
76 // Control instructions.
77 (None, unreachable, 990),
78 (None, nop, 800),
79 (None, block),
80 (None, r#loop),
81 (Some(try_valid), r#try),
82 (Some(delegate_valid), delegate),
83 (Some(catch_valid), catch),
84 (Some(catch_all_valid), catch_all),
85 (Some(if_valid), r#if),
86 (Some(else_valid), r#else),
87 (Some(end_valid), end),
88 (Some(br_valid), br),
89 (Some(br_if_valid), br_if),
90 (Some(br_table_valid), br_table),
91 (Some(return_valid), r#return, 900),
92 (Some(call_valid), call),
93 (Some(call_indirect_valid), call_indirect),
94 (Some(throw_valid), throw, 850),
95 (Some(rethrow_valid), rethrow),
96 // Parametric instructions.
97 (Some(drop_valid), drop),
98 (Some(select_valid), select),
99 // Variable instructions.
100 (Some(local_get_valid), local_get),
101 (Some(local_set_valid), local_set),
102 (Some(local_set_valid), local_tee),
103 (Some(global_get_valid), global_get),
104 (Some(global_set_valid), global_set),
105 // Memory instructions.
106 (Some(have_memory_and_offset), i32_load),
107 (Some(have_memory_and_offset), i64_load),
108 (Some(have_memory_and_offset), f32_load),
109 (Some(have_memory_and_offset), f64_load),
110 (Some(have_memory_and_offset), i32_load_8_s),
111 (Some(have_memory_and_offset), i32_load_8_u),
112 (Some(have_memory_and_offset), i32_load_16_s),
113 (Some(have_memory_and_offset), i32_load_16_u),
114 (Some(have_memory_and_offset), i64_load_8_s),
115 (Some(have_memory_and_offset), i64_load_16_s),
116 (Some(have_memory_and_offset), i64_load_32_s),
117 (Some(have_memory_and_offset), i64_load_8_u),
118 (Some(have_memory_and_offset), i64_load_16_u),
119 (Some(have_memory_and_offset), i64_load_32_u),
120 (Some(i32_store_valid), i32_store),
121 (Some(i64_store_valid), i64_store),
122 (Some(f32_store_valid), f32_store),
123 (Some(f64_store_valid), f64_store),
124 (Some(i32_store_valid), i32_store_8),
125 (Some(i32_store_valid), i32_store_16),
126 (Some(i64_store_valid), i64_store_8),
127 (Some(i64_store_valid), i64_store_16),
128 (Some(i64_store_valid), i64_store_32),
129 (Some(have_memory), memory_size),
130 (Some(memory_grow_valid), memory_grow),
131 (Some(memory_init_valid), memory_init),
132 (Some(data_drop_valid), data_drop),
133 (Some(memory_copy_valid), memory_copy),
134 (Some(memory_fill_valid), memory_fill),
135 // Numeric instructions.
136 (None, i32_const),
137 (None, i64_const),
138 (None, f32_const),
139 (None, f64_const),
140 (Some(i32_on_stack), i32_eqz),
141 (Some(i32_i32_on_stack), i32_eq),
142 (Some(i32_i32_on_stack), i32_neq),
143 (Some(i32_i32_on_stack), i32_lt_s),
144 (Some(i32_i32_on_stack), i32_lt_u),
145 (Some(i32_i32_on_stack), i32_gt_s),
146 (Some(i32_i32_on_stack), i32_gt_u),
147 (Some(i32_i32_on_stack), i32_le_s),
148 (Some(i32_i32_on_stack), i32_le_u),
149 (Some(i32_i32_on_stack), i32_ge_s),
150 (Some(i32_i32_on_stack), i32_ge_u),
151 (Some(i64_on_stack), i64_eqz),
152 (Some(i64_i64_on_stack), i64_eq),
153 (Some(i64_i64_on_stack), i64_neq),
154 (Some(i64_i64_on_stack), i64_lt_s),
155 (Some(i64_i64_on_stack), i64_lt_u),
156 (Some(i64_i64_on_stack), i64_gt_s),
157 (Some(i64_i64_on_stack), i64_gt_u),
158 (Some(i64_i64_on_stack), i64_le_s),
159 (Some(i64_i64_on_stack), i64_le_u),
160 (Some(i64_i64_on_stack), i64_ge_s),
161 (Some(i64_i64_on_stack), i64_ge_u),
162 (Some(f32_f32_on_stack), f32_eq),
163 (Some(f32_f32_on_stack), f32_neq),
164 (Some(f32_f32_on_stack), f32_lt),
165 (Some(f32_f32_on_stack), f32_gt),
166 (Some(f32_f32_on_stack), f32_le),
167 (Some(f32_f32_on_stack), f32_ge),
168 (Some(f64_f64_on_stack), f64_eq),
169 (Some(f64_f64_on_stack), f64_neq),
170 (Some(f64_f64_on_stack), f64_lt),
171 (Some(f64_f64_on_stack), f64_gt),
172 (Some(f64_f64_on_stack), f64_le),
173 (Some(f64_f64_on_stack), f64_ge),
174 (Some(i32_on_stack), i32_clz),
175 (Some(i32_on_stack), i32_ctz),
176 (Some(i32_on_stack), i32_popcnt),
177 (Some(i32_i32_on_stack), i32_add),
178 (Some(i32_i32_on_stack), i32_sub),
179 (Some(i32_i32_on_stack), i32_mul),
180 (Some(i32_i32_on_stack), i32_div_s),
181 (Some(i32_i32_on_stack), i32_div_u),
182 (Some(i32_i32_on_stack), i32_rem_s),
183 (Some(i32_i32_on_stack), i32_rem_u),
184 (Some(i32_i32_on_stack), i32_and),
185 (Some(i32_i32_on_stack), i32_or),
186 (Some(i32_i32_on_stack), i32_xor),
187 (Some(i32_i32_on_stack), i32_shl),
188 (Some(i32_i32_on_stack), i32_shr_s),
189 (Some(i32_i32_on_stack), i32_shr_u),
190 (Some(i32_i32_on_stack), i32_rotl),
191 (Some(i32_i32_on_stack), i32_rotr),
192 (Some(i64_on_stack), i64_clz),
193 (Some(i64_on_stack), i64_ctz),
194 (Some(i64_on_stack), i64_popcnt),
195 (Some(i64_i64_on_stack), i64_add),
196 (Some(i64_i64_on_stack), i64_sub),
197 (Some(i64_i64_on_stack), i64_mul),
198 (Some(i64_i64_on_stack), i64_div_s),
199 (Some(i64_i64_on_stack), i64_div_u),
200 (Some(i64_i64_on_stack), i64_rem_s),
201 (Some(i64_i64_on_stack), i64_rem_u),
202 (Some(i64_i64_on_stack), i64_and),
203 (Some(i64_i64_on_stack), i64_or),
204 (Some(i64_i64_on_stack), i64_xor),
205 (Some(i64_i64_on_stack), i64_shl),
206 (Some(i64_i64_on_stack), i64_shr_s),
207 (Some(i64_i64_on_stack), i64_shr_u),
208 (Some(i64_i64_on_stack), i64_rotl),
209 (Some(i64_i64_on_stack), i64_rotr),
210 (Some(f32_on_stack), f32_abs),
211 (Some(f32_on_stack), f32_neg),
212 (Some(f32_on_stack), f32_ceil),
213 (Some(f32_on_stack), f32_floor),
214 (Some(f32_on_stack), f32_trunc),
215 (Some(f32_on_stack), f32_nearest),
216 (Some(f32_on_stack), f32_sqrt),
217 (Some(f32_f32_on_stack), f32_add),
218 (Some(f32_f32_on_stack), f32_sub),
219 (Some(f32_f32_on_stack), f32_mul),
220 (Some(f32_f32_on_stack), f32_div),
221 (Some(f32_f32_on_stack), f32_min),
222 (Some(f32_f32_on_stack), f32_max),
223 (Some(f32_f32_on_stack), f32_copysign),
224 (Some(f64_on_stack), f64_abs),
225 (Some(f64_on_stack), f64_neg),
226 (Some(f64_on_stack), f64_ceil),
227 (Some(f64_on_stack), f64_floor),
228 (Some(f64_on_stack), f64_trunc),
229 (Some(f64_on_stack), f64_nearest),
230 (Some(f64_on_stack), f64_sqrt),
231 (Some(f64_f64_on_stack), f64_add),
232 (Some(f64_f64_on_stack), f64_sub),
233 (Some(f64_f64_on_stack), f64_mul),
234 (Some(f64_f64_on_stack), f64_div),
235 (Some(f64_f64_on_stack), f64_min),
236 (Some(f64_f64_on_stack), f64_max),
237 (Some(f64_f64_on_stack), f64_copysign),
238 (Some(i64_on_stack), i32_wrap_i64),
239 (Some(f32_on_stack), i32_trunc_f32_s),
240 (Some(f32_on_stack), i32_trunc_f32_u),
241 (Some(f64_on_stack), i32_trunc_f64_s),
242 (Some(f64_on_stack), i32_trunc_f64_u),
243 (Some(i32_on_stack), i64_extend_i32_s),
244 (Some(i32_on_stack), i64_extend_i32_u),
245 (Some(f32_on_stack), i64_trunc_f32_s),
246 (Some(f32_on_stack), i64_trunc_f32_u),
247 (Some(f64_on_stack), i64_trunc_f64_s),
248 (Some(f64_on_stack), i64_trunc_f64_u),
249 (Some(i32_on_stack), f32_convert_i32_s),
250 (Some(i32_on_stack), f32_convert_i32_u),
251 (Some(i64_on_stack), f32_convert_i64_s),
252 (Some(i64_on_stack), f32_convert_i64_u),
253 (Some(f64_on_stack), f32_demote_f64),
254 (Some(i32_on_stack), f64_convert_i32_s),
255 (Some(i32_on_stack), f64_convert_i32_u),
256 (Some(i64_on_stack), f64_convert_i64_s),
257 (Some(i64_on_stack), f64_convert_i64_u),
258 (Some(f32_on_stack), f64_promote_f32),
259 (Some(f32_on_stack), i32_reinterpret_f32),
260 (Some(f64_on_stack), i64_reinterpret_f64),
261 (Some(i32_on_stack), f32_reinterpret_i32),
262 (Some(i64_on_stack), f64_reinterpret_i64),
263 (Some(i32_on_stack), i32_extend_8_s),
264 (Some(i32_on_stack), i32_extend_16_s),
265 (Some(i64_on_stack), i64_extend_8_s),
266 (Some(i64_on_stack), i64_extend_16_s),
267 (Some(i64_on_stack), i64_extend_32_s),
268 (Some(f32_on_stack), i32_trunc_sat_f32_s),
269 (Some(f32_on_stack), i32_trunc_sat_f32_u),
270 (Some(f64_on_stack), i32_trunc_sat_f64_s),
271 (Some(f64_on_stack), i32_trunc_sat_f64_u),
272 (Some(f32_on_stack), i64_trunc_sat_f32_s),
273 (Some(f32_on_stack), i64_trunc_sat_f32_u),
274 (Some(f64_on_stack), i64_trunc_sat_f64_s),
275 (Some(f64_on_stack), i64_trunc_sat_f64_u),
276 // reference types proposal
277 (Some(ref_null_valid), ref_null),
278 (Some(ref_func_valid), ref_func),
279 (Some(ref_is_null_valid), ref_is_null),
280 (Some(table_fill_valid), table_fill),
281 (Some(table_set_valid), table_set),
282 (Some(table_get_valid), table_get),
283 (Some(table_size_valid), table_size),
284 (Some(table_grow_valid), table_grow),
285 (Some(table_copy_valid), table_copy),
286 (Some(table_init_valid), table_init),
287 (Some(elem_drop_valid), elem_drop),
288 // SIMD instructions.
289 (Some(simd_have_memory_and_offset), v128_load),
290 (Some(simd_have_memory_and_offset), v128_load8x8s),
291 (Some(simd_have_memory_and_offset), v128_load8x8u),
292 (Some(simd_have_memory_and_offset), v128_load16x4s),
293 (Some(simd_have_memory_and_offset), v128_load16x4u),
294 (Some(simd_have_memory_and_offset), v128_load32x2s),
295 (Some(simd_have_memory_and_offset), v128_load32x2u),
296 (Some(simd_have_memory_and_offset), v128_load8_splat),
297 (Some(simd_have_memory_and_offset), v128_load16_splat),
298 (Some(simd_have_memory_and_offset), v128_load32_splat),
299 (Some(simd_have_memory_and_offset), v128_load64_splat),
300 (Some(simd_have_memory_and_offset), v128_load32_zero),
301 (Some(simd_have_memory_and_offset), v128_load64_zero),
302 (Some(simd_v128_store_valid), v128_store),
303 (Some(simd_have_memory_and_offset_and_v128), v128_load8_lane),
304 (Some(simd_have_memory_and_offset_and_v128), v128_load16_lane),
305 (Some(simd_have_memory_and_offset_and_v128), v128_load32_lane),
306 (Some(simd_have_memory_and_offset_and_v128), v128_load64_lane),
307 (Some(simd_v128_store_valid), v128_store8_lane),
308 (Some(simd_v128_store_valid), v128_store16_lane),
309 (Some(simd_v128_store_valid), v128_store32_lane),
310 (Some(simd_v128_store_valid), v128_store64_lane),
311 (Some(simd_enabled), v128_const),
312 (Some(simd_v128_v128_on_stack), i8x16_shuffle),
313 (Some(simd_v128_on_stack), i8x16_extract_lane_s),
314 (Some(simd_v128_on_stack), i8x16_extract_lane_u),
315 (Some(simd_v128_i32_on_stack), i8x16_replace_lane),
316 (Some(simd_v128_on_stack), i16x8_extract_lane_s),
317 (Some(simd_v128_on_stack), i16x8_extract_lane_u),
318 (Some(simd_v128_i32_on_stack), i16x8_replace_lane),
319 (Some(simd_v128_on_stack), i32x4_extract_lane),
320 (Some(simd_v128_i32_on_stack), i32x4_replace_lane),
321 (Some(simd_v128_on_stack), i64x2_extract_lane),
322 (Some(simd_v128_i64_on_stack), i64x2_replace_lane),
323 (Some(simd_v128_on_stack), f32x4_extract_lane),
324 (Some(simd_v128_f32_on_stack), f32x4_replace_lane),
325 (Some(simd_v128_on_stack), f64x2_extract_lane),
326 (Some(simd_v128_f64_on_stack), f64x2_replace_lane),
327 (Some(simd_v128_v128_on_stack), i8x16_swizzle),
328 (Some(simd_i32_on_stack), i8x16_splat),
329 (Some(simd_i32_on_stack), i16x8_splat),
330 (Some(simd_i32_on_stack), i32x4_splat),
331 (Some(simd_i64_on_stack), i64x2_splat),
332 (Some(simd_f32_on_stack), f32x4_splat),
333 (Some(simd_f64_on_stack), f64x2_splat),
334 (Some(simd_v128_v128_on_stack), i8x16_swizzle),
335 (Some(simd_v128_v128_v128_on_stack), v128_bitselect),
336 (Some(simd_v128_v128_on_stack), i8x16_eq),
337 (Some(simd_v128_v128_on_stack), i8x16_ne),
338 (Some(simd_v128_v128_on_stack), i8x16_lt_s),
339 (Some(simd_v128_v128_on_stack), i8x16_lt_u),
340 (Some(simd_v128_v128_on_stack), i8x16_gt_s),
341 (Some(simd_v128_v128_on_stack), i8x16_gt_u),
342 (Some(simd_v128_v128_on_stack), i8x16_le_s),
343 (Some(simd_v128_v128_on_stack), i8x16_le_u),
344 (Some(simd_v128_v128_on_stack), i8x16_ge_s),
345 (Some(simd_v128_v128_on_stack), i8x16_ge_u),
346 (Some(simd_v128_v128_on_stack), i16x8_eq),
347 (Some(simd_v128_v128_on_stack), i16x8_ne),
348 (Some(simd_v128_v128_on_stack), i16x8_lt_s),
349 (Some(simd_v128_v128_on_stack), i16x8_lt_u),
350 (Some(simd_v128_v128_on_stack), i16x8_gt_s),
351 (Some(simd_v128_v128_on_stack), i16x8_gt_u),
352 (Some(simd_v128_v128_on_stack), i16x8_le_s),
353 (Some(simd_v128_v128_on_stack), i16x8_le_u),
354 (Some(simd_v128_v128_on_stack), i16x8_ge_s),
355 (Some(simd_v128_v128_on_stack), i16x8_ge_u),
356 (Some(simd_v128_v128_on_stack), i32x4_eq),
357 (Some(simd_v128_v128_on_stack), i32x4_ne),
358 (Some(simd_v128_v128_on_stack), i32x4_lt_s),
359 (Some(simd_v128_v128_on_stack), i32x4_lt_u),
360 (Some(simd_v128_v128_on_stack), i32x4_gt_s),
361 (Some(simd_v128_v128_on_stack), i32x4_gt_u),
362 (Some(simd_v128_v128_on_stack), i32x4_le_s),
363 (Some(simd_v128_v128_on_stack), i32x4_le_u),
364 (Some(simd_v128_v128_on_stack), i32x4_ge_s),
365 (Some(simd_v128_v128_on_stack), i32x4_ge_u),
366 (Some(simd_v128_v128_on_stack), i64x2_eq),
367 (Some(simd_v128_v128_on_stack), i64x2_ne),
368 (Some(simd_v128_v128_on_stack), i64x2_lt_s),
369 (Some(simd_v128_v128_on_stack), i64x2_gt_s),
370 (Some(simd_v128_v128_on_stack), i64x2_le_s),
371 (Some(simd_v128_v128_on_stack), i64x2_ge_s),
372 (Some(simd_v128_v128_on_stack), f32x4_eq),
373 (Some(simd_v128_v128_on_stack), f32x4_ne),
374 (Some(simd_v128_v128_on_stack), f32x4_lt),
375 (Some(simd_v128_v128_on_stack), f32x4_gt),
376 (Some(simd_v128_v128_on_stack), f32x4_le),
377 (Some(simd_v128_v128_on_stack), f32x4_ge),
378 (Some(simd_v128_v128_on_stack), f64x2_eq),
379 (Some(simd_v128_v128_on_stack), f64x2_ne),
380 (Some(simd_v128_v128_on_stack), f64x2_lt),
381 (Some(simd_v128_v128_on_stack), f64x2_gt),
382 (Some(simd_v128_v128_on_stack), f64x2_le),
383 (Some(simd_v128_v128_on_stack), f64x2_ge),
384 (Some(simd_v128_on_stack), v128_not),
385 (Some(simd_v128_v128_on_stack), v128_and),
386 (Some(simd_v128_v128_on_stack), v128_and_not),
387 (Some(simd_v128_v128_on_stack), v128_or),
388 (Some(simd_v128_v128_on_stack), v128_xor),
389 (Some(simd_v128_v128_on_stack), v128_any_true),
390 (Some(simd_v128_on_stack), i8x16_abs),
391 (Some(simd_v128_on_stack), i8x16_neg),
392 (Some(simd_v128_on_stack), i8x16_popcnt),
393 (Some(simd_v128_on_stack), i8x16_all_true),
394 (Some(simd_v128_on_stack), i8x16_bitmask),
395 (Some(simd_v128_v128_on_stack), i8x16_narrow_i16x8s),
396 (Some(simd_v128_v128_on_stack), i8x16_narrow_i16x8u),
397 (Some(simd_v128_i32_on_stack), i8x16_shl),
398 (Some(simd_v128_i32_on_stack), i8x16_shr_s),
399 (Some(simd_v128_i32_on_stack), i8x16_shr_u),
400 (Some(simd_v128_v128_on_stack), i8x16_add),
401 (Some(simd_v128_v128_on_stack), i8x16_add_sat_s),
402 (Some(simd_v128_v128_on_stack), i8x16_add_sat_u),
403 (Some(simd_v128_v128_on_stack), i8x16_sub),
404 (Some(simd_v128_v128_on_stack), i8x16_sub_sat_s),
405 (Some(simd_v128_v128_on_stack), i8x16_sub_sat_u),
406 (Some(simd_v128_v128_on_stack), i8x16_min_s),
407 (Some(simd_v128_v128_on_stack), i8x16_min_u),
408 (Some(simd_v128_v128_on_stack), i8x16_max_s),
409 (Some(simd_v128_v128_on_stack), i8x16_max_u),
410 (Some(simd_v128_v128_on_stack), i8x16_rounding_average_u),
411 (Some(simd_v128_on_stack), i16x8_ext_add_pairwise_i8x16s),
412 (Some(simd_v128_on_stack), i16x8_ext_add_pairwise_i8x16u),
413 (Some(simd_v128_on_stack), i16x8_abs),
414 (Some(simd_v128_on_stack), i16x8_neg),
415 (Some(simd_v128_v128_on_stack), i16x8q15_mulr_sat_s),
416 (Some(simd_v128_on_stack), i16x8_all_true),
417 (Some(simd_v128_on_stack), i16x8_bitmask),
418 (Some(simd_v128_v128_on_stack), i16x8_narrow_i32x4s),
419 (Some(simd_v128_v128_on_stack), i16x8_narrow_i32x4u),
420 (Some(simd_v128_on_stack), i16x8_extend_low_i8x16s),
421 (Some(simd_v128_on_stack), i16x8_extend_high_i8x16s),
422 (Some(simd_v128_on_stack), i16x8_extend_low_i8x16u),
423 (Some(simd_v128_on_stack), i16x8_extend_high_i8x16u),
424 (Some(simd_v128_i32_on_stack), i16x8_shl),
425 (Some(simd_v128_i32_on_stack), i16x8_shr_s),
426 (Some(simd_v128_i32_on_stack), i16x8_shr_u),
427 (Some(simd_v128_v128_on_stack), i16x8_add),
428 (Some(simd_v128_v128_on_stack), i16x8_add_sat_s),
429 (Some(simd_v128_v128_on_stack), i16x8_add_sat_u),
430 (Some(simd_v128_v128_on_stack), i16x8_sub),
431 (Some(simd_v128_v128_on_stack), i16x8_sub_sat_s),
432 (Some(simd_v128_v128_on_stack), i16x8_sub_sat_u),
433 (Some(simd_v128_v128_on_stack), i16x8_mul),
434 (Some(simd_v128_v128_on_stack), i16x8_min_s),
435 (Some(simd_v128_v128_on_stack), i16x8_min_u),
436 (Some(simd_v128_v128_on_stack), i16x8_max_s),
437 (Some(simd_v128_v128_on_stack), i16x8_max_u),
438 (Some(simd_v128_v128_on_stack), i16x8_rounding_average_u),
439 (Some(simd_v128_v128_on_stack), i16x8_ext_mul_low_i8x16s),
440 (Some(simd_v128_v128_on_stack), i16x8_ext_mul_high_i8x16s),
441 (Some(simd_v128_v128_on_stack), i16x8_ext_mul_low_i8x16u),
442 (Some(simd_v128_v128_on_stack), i16x8_ext_mul_high_i8x16u),
443 (Some(simd_v128_on_stack), i32x4_ext_add_pairwise_i16x8s),
444 (Some(simd_v128_on_stack), i32x4_ext_add_pairwise_i16x8u),
445 (Some(simd_v128_on_stack), i32x4_abs),
446 (Some(simd_v128_on_stack), i32x4_neg),
447 (Some(simd_v128_on_stack), i32x4_all_true),
448 (Some(simd_v128_on_stack), i32x4_bitmask),
449 (Some(simd_v128_on_stack), i32x4_extend_low_i16x8s),
450 (Some(simd_v128_on_stack), i32x4_extend_high_i16x8s),
451 (Some(simd_v128_on_stack), i32x4_extend_low_i16x8u),
452 (Some(simd_v128_on_stack), i32x4_extend_high_i16x8u),
453 (Some(simd_v128_i32_on_stack), i32x4_shl),
454 (Some(simd_v128_i32_on_stack), i32x4_shr_s),
455 (Some(simd_v128_i32_on_stack), i32x4_shr_u),
456 (Some(simd_v128_v128_on_stack), i32x4_add),
457 (Some(simd_v128_v128_on_stack), i32x4_sub),
458 (Some(simd_v128_v128_on_stack), i32x4_mul),
459 (Some(simd_v128_v128_on_stack), i32x4_min_s),
460 (Some(simd_v128_v128_on_stack), i32x4_min_u),
461 (Some(simd_v128_v128_on_stack), i32x4_max_s),
462 (Some(simd_v128_v128_on_stack), i32x4_max_u),
463 (Some(simd_v128_v128_on_stack), i32x4_dot_i16x8s),
464 (Some(simd_v128_v128_on_stack), i32x4_ext_mul_low_i16x8s),
465 (Some(simd_v128_v128_on_stack), i32x4_ext_mul_high_i16x8s),
466 (Some(simd_v128_v128_on_stack), i32x4_ext_mul_low_i16x8u),
467 (Some(simd_v128_v128_on_stack), i32x4_ext_mul_high_i16x8u),
468 (Some(simd_v128_on_stack), i64x2_abs),
469 (Some(simd_v128_on_stack), i64x2_neg),
470 (Some(simd_v128_on_stack), i64x2_all_true),
471 (Some(simd_v128_on_stack), i64x2_bitmask),
472 (Some(simd_v128_on_stack), i64x2_extend_low_i32x4s),
473 (Some(simd_v128_on_stack), i64x2_extend_high_i32x4s),
474 (Some(simd_v128_on_stack), i64x2_extend_low_i32x4u),
475 (Some(simd_v128_on_stack), i64x2_extend_high_i32x4u),
476 (Some(simd_v128_i32_on_stack), i64x2_shl),
477 (Some(simd_v128_i32_on_stack), i64x2_shr_s),
478 (Some(simd_v128_i32_on_stack), i64x2_shr_u),
479 (Some(simd_v128_v128_on_stack), i64x2_add),
480 (Some(simd_v128_v128_on_stack), i64x2_sub),
481 (Some(simd_v128_v128_on_stack), i64x2_mul),
482 (Some(simd_v128_v128_on_stack), i64x2_ext_mul_low_i32x4s),
483 (Some(simd_v128_v128_on_stack), i64x2_ext_mul_high_i32x4s),
484 (Some(simd_v128_v128_on_stack), i64x2_ext_mul_low_i32x4u),
485 (Some(simd_v128_v128_on_stack), i64x2_ext_mul_high_i32x4u),
486 (Some(simd_v128_on_stack), f32x4_ceil),
487 (Some(simd_v128_on_stack), f32x4_floor),
488 (Some(simd_v128_on_stack), f32x4_trunc),
489 (Some(simd_v128_on_stack), f32x4_nearest),
490 (Some(simd_v128_on_stack), f32x4_abs),
491 (Some(simd_v128_on_stack), f32x4_neg),
492 (Some(simd_v128_on_stack), f32x4_sqrt),
493 (Some(simd_v128_v128_on_stack), f32x4_add),
494 (Some(simd_v128_v128_on_stack), f32x4_sub),
495 (Some(simd_v128_v128_on_stack), f32x4_mul),
496 (Some(simd_v128_v128_on_stack), f32x4_div),
497 (Some(simd_v128_v128_on_stack), f32x4_min),
498 (Some(simd_v128_v128_on_stack), f32x4_max),
499 (Some(simd_v128_v128_on_stack), f32x4p_min),
500 (Some(simd_v128_v128_on_stack), f32x4p_max),
501 (Some(simd_v128_on_stack), f64x2_ceil),
502 (Some(simd_v128_on_stack), f64x2_floor),
503 (Some(simd_v128_on_stack), f64x2_trunc),
504 (Some(simd_v128_on_stack), f64x2_nearest),
505 (Some(simd_v128_on_stack), f64x2_abs),
506 (Some(simd_v128_on_stack), f64x2_neg),
507 (Some(simd_v128_on_stack), f64x2_sqrt),
508 (Some(simd_v128_v128_on_stack), f64x2_add),
509 (Some(simd_v128_v128_on_stack), f64x2_sub),
510 (Some(simd_v128_v128_on_stack), f64x2_mul),
511 (Some(simd_v128_v128_on_stack), f64x2_div),
512 (Some(simd_v128_v128_on_stack), f64x2_min),
513 (Some(simd_v128_v128_on_stack), f64x2_max),
514 (Some(simd_v128_v128_on_stack), f64x2p_min),
515 (Some(simd_v128_v128_on_stack), f64x2p_max),
516 (Some(simd_v128_on_stack), i32x4_trunc_sat_f32x4s),
517 (Some(simd_v128_on_stack), i32x4_trunc_sat_f32x4u),
518 (Some(simd_v128_on_stack), f32x4_convert_i32x4s),
519 (Some(simd_v128_on_stack), f32x4_convert_i32x4u),
520 (Some(simd_v128_on_stack), i32x4_trunc_sat_f64x2s_zero),
521 (Some(simd_v128_on_stack), i32x4_trunc_sat_f64x2u_zero),
522 (Some(simd_v128_on_stack), f64x2_convert_low_i32x4s),
523 (Some(simd_v128_on_stack), f64x2_convert_low_i32x4u),
524 (Some(simd_v128_on_stack), f32x4_demote_f64x2_zero),
525 (Some(simd_v128_on_stack), f64x2_promote_low_f32x4),
526 }
527
528 pub(crate) struct CodeBuilderAllocations {
529 // The control labels in scope right now.
530 controls: Vec<Control>,
531
532 // The types on the operand stack right now.
533 operands: Vec<Option<ValType>>,
534
535 // Dynamic set of options of instruction we can generate that are known to
536 // be valid right now.
537 options: Vec<(
538 fn(&mut Unstructured, &Module, &mut CodeBuilder) -> Result<Instruction>,
539 u32,
540 )>,
541
542 // Cached information about the module that we're generating functions for,
543 // used to speed up validity checks. The mutable globals map is a map of the
544 // type of global to the global indices which have that type (and they're
545 // all mutable).
546 mutable_globals: BTreeMap<ValType, Vec<u32>>,
547
548 // Like mutable globals above this is a map from function types to the list
549 // of functions that have that function type.
550 functions: BTreeMap<Vec<ValType>, Vec<u32>>,
551
552 // Like functions above this is a map from tag types to the list of tags
553 // have that tag type.
554 tags: BTreeMap<Vec<ValType>, Vec<u32>>,
555
556 // Tables in this module which have a funcref element type.
557 funcref_tables: Vec<u32>,
558
559 // Functions that are referenced in the module through globals and segments.
560 referenced_functions: Vec<u32>,
561
562 // Flag that indicates if any element segments have the same type as any
563 // table
564 table_init_possible: bool,
565
566 // Lists of memory indices which are either 32-bit or 64-bit. This is used
567 // for faster lookup in validating instructions to know which memories have
568 // which types. For example if there are no 64-bit memories then we
569 // shouldn't ever look for i64 on the stack for `i32.load`.
570 memory32: Vec<u32>,
571 memory64: Vec<u32>,
572 }
573
574 pub(crate) struct CodeBuilder<'a> {
575 func_ty: &'a FuncType,
576 locals: &'a mut Vec<ValType>,
577 allocs: &'a mut CodeBuilderAllocations,
578
579 // Temporary locals injected and used by nan canonicalization. Note that
580 // this list of extra locals is appended to `self.locals` at the end of code
581 // generation, and it's kept separate here to avoid using these locals in
582 // `local.get` and similar instructions.
583 extra_locals: Vec<ValType>,
584 f32_scratch: Option<usize>,
585 f64_scratch: Option<usize>,
586 v128_scratch: Option<usize>,
587 }
588
589 /// A control frame.
590 #[derive(Debug, Clone)]
591 struct Control {
592 kind: ControlKind,
593 /// Value types that must be on the stack when entering this control frame.
594 params: Vec<ValType>,
595 /// Value types that are left on the stack when exiting this control frame.
596 results: Vec<ValType>,
597 /// How far down the operand stack instructions inside this control frame
598 /// can reach.
599 height: usize,
600 }
601
602 impl Control {
label_types(&self) -> &[ValType]603 fn label_types(&self) -> &[ValType] {
604 if self.kind == ControlKind::Loop {
605 &self.params
606 } else {
607 &self.results
608 }
609 }
610 }
611
612 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
613 enum ControlKind {
614 Block,
615 If,
616 Loop,
617 Try,
618 Catch,
619 CatchAll,
620 }
621
622 enum Float {
623 F32,
624 F64,
625 F32x4,
626 F64x2,
627 }
628
629 impl CodeBuilderAllocations {
new(module: &Module) -> Self630 pub(crate) fn new(module: &Module) -> Self {
631 let mut mutable_globals = BTreeMap::new();
632 for (i, global) in module.globals.iter().enumerate() {
633 if global.mutable {
634 mutable_globals
635 .entry(global.val_type)
636 .or_insert(Vec::new())
637 .push(i as u32);
638 }
639 }
640
641 let mut tags = BTreeMap::new();
642 for (idx, tag_type) in module.tags() {
643 tags.entry(tag_type.func_type.params.clone())
644 .or_insert(Vec::new())
645 .push(idx);
646 }
647
648 let mut functions = BTreeMap::new();
649 for (idx, func) in module.funcs() {
650 functions
651 .entry(func.params.clone())
652 .or_insert(Vec::new())
653 .push(idx);
654 }
655
656 let mut funcref_tables = Vec::new();
657 let mut table_tys = Vec::new();
658 for (i, table) in module.tables.iter().enumerate() {
659 table_tys.push(table.elem_ty);
660 if table.elem_ty == ValType::FuncRef {
661 funcref_tables.push(i as u32);
662 }
663 }
664
665 let mut referenced_functions = BTreeSet::new();
666 for (_, expr) in module.defined_globals.iter() {
667 if let Instruction::RefFunc(i) = *expr {
668 referenced_functions.insert(i);
669 }
670 }
671 for g in module.elems.iter() {
672 match &g.items {
673 Elements::Expressions(e) => {
674 let iter = e.iter().filter_map(|i| *i);
675 referenced_functions.extend(iter);
676 }
677 Elements::Functions(e) => {
678 referenced_functions.extend(e.iter().cloned());
679 }
680 }
681 }
682
683 let table_init_possible = module.elems.iter().any(|e| table_tys.contains(&e.ty));
684
685 let mut memory32 = Vec::new();
686 let mut memory64 = Vec::new();
687 for (i, mem) in module.memories.iter().enumerate() {
688 if mem.memory64 {
689 memory64.push(i as u32);
690 } else {
691 memory32.push(i as u32);
692 }
693 }
694
695 CodeBuilderAllocations {
696 controls: Vec::with_capacity(4),
697 operands: Vec::with_capacity(16),
698 options: Vec::with_capacity(NUM_OPTIONS),
699 functions,
700 tags,
701 mutable_globals,
702 funcref_tables,
703 referenced_functions: referenced_functions.into_iter().collect(),
704 table_init_possible,
705 memory32,
706 memory64,
707 }
708 }
709
builder<'a>( &'a mut self, func_ty: &'a FuncType, locals: &'a mut Vec<ValType>, ) -> CodeBuilder<'a>710 pub(crate) fn builder<'a>(
711 &'a mut self,
712 func_ty: &'a FuncType,
713 locals: &'a mut Vec<ValType>,
714 ) -> CodeBuilder<'a> {
715 self.controls.clear();
716 self.controls.push(Control {
717 kind: ControlKind::Block,
718 params: vec![],
719 results: func_ty.results.clone(),
720 height: 0,
721 });
722
723 self.operands.clear();
724 self.options.clear();
725
726 CodeBuilder {
727 func_ty,
728 locals,
729 allocs: self,
730 extra_locals: Vec::new(),
731 f32_scratch: None,
732 f64_scratch: None,
733 v128_scratch: None,
734 }
735 }
736 }
737
738 impl CodeBuilder<'_> {
739 /// Get the operands that are in-scope within the current control frame.
operands(&self) -> &[Option<ValType>]740 fn operands(&self) -> &[Option<ValType>] {
741 let height = self.allocs.controls.last().map_or(0, |c| c.height);
742 &self.allocs.operands[height..]
743 }
744
pop_operands(&mut self, to_pop: &[ValType])745 fn pop_operands(&mut self, to_pop: &[ValType]) {
746 debug_assert!(self.types_on_stack(to_pop));
747 self.allocs
748 .operands
749 .truncate(self.allocs.operands.len() - to_pop.len());
750 }
751
push_operands(&mut self, to_push: &[ValType])752 fn push_operands(&mut self, to_push: &[ValType]) {
753 self.allocs
754 .operands
755 .extend(to_push.iter().copied().map(Some));
756 }
757
label_types_on_stack(&self, to_check: &Control) -> bool758 fn label_types_on_stack(&self, to_check: &Control) -> bool {
759 self.types_on_stack(to_check.label_types())
760 }
761
type_on_stack(&self, ty: ValType) -> bool762 fn type_on_stack(&self, ty: ValType) -> bool {
763 match self.operands().last() {
764 None => false,
765 Some(None) => true,
766 Some(Some(x)) => *x == ty,
767 }
768 }
769
types_on_stack(&self, types: &[ValType]) -> bool770 fn types_on_stack(&self, types: &[ValType]) -> bool {
771 self.operands().len() >= types.len()
772 && self
773 .operands()
774 .iter()
775 .rev()
776 .zip(types.iter().rev())
777 .all(|(a, b)| match (a, b) {
778 (None, _) => true,
779 (Some(x), y) => x == y,
780 })
781 }
782
783 #[inline(never)]
arbitrary_block_type(&self, u: &mut Unstructured, module: &Module) -> Result<BlockType>784 fn arbitrary_block_type(&self, u: &mut Unstructured, module: &Module) -> Result<BlockType> {
785 let mut options: Vec<Box<dyn Fn(&mut Unstructured) -> Result<BlockType>>> = vec![
786 Box::new(|_| Ok(BlockType::Empty)),
787 Box::new(|u| Ok(BlockType::Result(module.arbitrary_valtype(u)?))),
788 ];
789
790 for (i, ty) in module.func_types() {
791 if self.types_on_stack(&ty.params) {
792 options.push(Box::new(move |_| Ok(BlockType::FuncType(i as u32))));
793 }
794 }
795
796 let f = u.choose(&options)?;
797 f(u)
798 }
799
arbitrary( mut self, u: &mut Unstructured, module: &Module, ) -> Result<Vec<Instruction>>800 pub(crate) fn arbitrary(
801 mut self,
802 u: &mut Unstructured,
803 module: &Module,
804 ) -> Result<Vec<Instruction>> {
805 let max_instructions = module.config.max_instructions();
806 let mut instructions = vec![];
807
808 while !self.allocs.controls.is_empty() {
809 let keep_going = instructions.len() < max_instructions
810 && u.arbitrary().map_or(false, |b: u8| b != 0);
811 if !keep_going {
812 self.end_active_control_frames(u, &mut instructions);
813 break;
814 }
815
816 match choose_instruction(u, module, &mut self) {
817 Some(f) => {
818 let inst = f(u, module, &mut self)?;
819 instructions.push(inst);
820 }
821 // Choosing an instruction can fail because there is not enough
822 // underlying data, so we really cannot generate any more
823 // instructions. In this case we swallow that error and instead
824 // just terminate our wasm function's frames.
825 None => {
826 self.end_active_control_frames(u, &mut instructions);
827 break;
828 }
829 }
830
831 // If the configuration for this module requests nan
832 // canonicalization then perform that here based on whether or not
833 // the previous instruction needs canonicalization. Note that this
834 // is based off Cranelift's pass for nan canonicalization for which
835 // instructions to canonicalize, but the general idea is most
836 // floating-point operations.
837 if module.config.canonicalize_nans() {
838 match instructions.last().unwrap() {
839 Instruction::F32Ceil
840 | Instruction::F32Floor
841 | Instruction::F32Nearest
842 | Instruction::F32Sqrt
843 | Instruction::F32Trunc
844 | Instruction::F32Div
845 | Instruction::F32Max
846 | Instruction::F32Min
847 | Instruction::F32Mul
848 | Instruction::F32Sub
849 | Instruction::F32Add => self.canonicalize_nan(Float::F32, &mut instructions),
850 Instruction::F64Ceil
851 | Instruction::F64Floor
852 | Instruction::F64Nearest
853 | Instruction::F64Sqrt
854 | Instruction::F64Trunc
855 | Instruction::F64Div
856 | Instruction::F64Max
857 | Instruction::F64Min
858 | Instruction::F64Mul
859 | Instruction::F64Sub
860 | Instruction::F64Add => self.canonicalize_nan(Float::F64, &mut instructions),
861 Instruction::F32x4Ceil
862 | Instruction::F32x4Floor
863 | Instruction::F32x4Nearest
864 | Instruction::F32x4Sqrt
865 | Instruction::F32x4Trunc
866 | Instruction::F32x4Div
867 | Instruction::F32x4Max
868 | Instruction::F32x4Min
869 | Instruction::F32x4Mul
870 | Instruction::F32x4Sub
871 | Instruction::F32x4Add => {
872 self.canonicalize_nan(Float::F32x4, &mut instructions)
873 }
874 Instruction::F64x2Ceil
875 | Instruction::F64x2Floor
876 | Instruction::F64x2Nearest
877 | Instruction::F64x2Sqrt
878 | Instruction::F64x2Trunc
879 | Instruction::F64x2Div
880 | Instruction::F64x2Max
881 | Instruction::F64x2Min
882 | Instruction::F64x2Mul
883 | Instruction::F64x2Sub
884 | Instruction::F64x2Add => {
885 self.canonicalize_nan(Float::F64x2, &mut instructions)
886 }
887 _ => {}
888 }
889 }
890 }
891
892 self.locals.extend(self.extra_locals.drain(..));
893
894 Ok(instructions)
895 }
896
canonicalize_nan(&mut self, ty: Float, ins: &mut Vec<Instruction>)897 fn canonicalize_nan(&mut self, ty: Float, ins: &mut Vec<Instruction>) {
898 // We'll need to temporarily save the top of the stack into a local, so
899 // figure out that local here. Note that this tries to use the same
900 // local if canonicalization happens more than once in a function.
901 let local = match ty {
902 Float::F32 => &mut self.f32_scratch,
903 Float::F64 => &mut self.f64_scratch,
904 Float::F32x4 | Float::F64x2 => &mut self.v128_scratch,
905 };
906 let local = match *local {
907 Some(i) => i,
908 None => {
909 let val = self.locals.len() + self.func_ty.params.len() + self.extra_locals.len();
910 *local = Some(val);
911 self.extra_locals.push(match ty {
912 Float::F32 => ValType::F32,
913 Float::F64 => ValType::F64,
914 Float::F32x4 | Float::F64x2 => ValType::V128,
915 });
916 val
917 }
918 };
919 let local = local as u32;
920
921 // Save the previous instruction's result into a local. This also leaves
922 // a value on the stack as `val1` for the `select` instruction.
923 ins.push(Instruction::LocalTee(local));
924
925 // The `val2` value input to the `select` below, our nan pattern.
926 //
927 // The nan patterns here are chosen to be a canonical representation
928 // which is still NaN but the wasm will always produce the same bits of
929 // a nan so if the wasm takes a look at the nan inside it'll always see
930 // the same representation.
931 const CANON_32BIT_NAN: u32 = 0b01111111110000000000000000000000;
932 const CANON_64BIT_NAN: u64 =
933 0b0111111111111000000000000000000000000000000000000000000000000000;
934 ins.push(match ty {
935 Float::F32 => Instruction::F32Const(f32::from_bits(CANON_32BIT_NAN)),
936 Float::F64 => Instruction::F64Const(f64::from_bits(CANON_64BIT_NAN)),
937 Float::F32x4 => {
938 let nan = CANON_32BIT_NAN as i128;
939 let nan = nan | (nan << 32) | (nan << 64) | (nan << 96);
940 Instruction::V128Const(nan)
941 }
942 Float::F64x2 => {
943 let nan = CANON_64BIT_NAN as i128;
944 let nan = nan | (nan << 64);
945 Instruction::V128Const(nan)
946 }
947 });
948
949 // the condition of the `select`, which is the float's equality test
950 // with itself.
951 ins.push(Instruction::LocalGet(local));
952 ins.push(Instruction::LocalGet(local));
953 ins.push(match ty {
954 Float::F32 => Instruction::F32Eq,
955 Float::F64 => Instruction::F64Eq,
956 Float::F32x4 => Instruction::F32x4Eq,
957 Float::F64x2 => Instruction::F64x2Eq,
958 });
959
960 // Select the result. If the condition is nonzero (aka the float is
961 // equal to itself) it picks `val1`, otherwise if zero (aka the float
962 // is nan) it picks `val2`.
963 ins.push(match ty {
964 Float::F32 | Float::F64 => Instruction::Select,
965 Float::F32x4 | Float::F64x2 => Instruction::V128Bitselect,
966 });
967 }
968
end_active_control_frames( &mut self, u: &mut Unstructured<'_>, instructions: &mut Vec<Instruction>, )969 fn end_active_control_frames(
970 &mut self,
971 u: &mut Unstructured<'_>,
972 instructions: &mut Vec<Instruction>,
973 ) {
974 while !self.allocs.controls.is_empty() {
975 // Ensure that this label is valid by placing the right types onto
976 // the operand stack for the end of the label.
977 self.guarantee_label_results(u, instructions);
978
979 // Remove the label and clear the operand stack since the label has
980 // been removed.
981 let label = self.allocs.controls.pop().unwrap();
982 self.allocs.operands.truncate(label.height);
983
984 // If this is an `if` that is not stack neutral, then it
985 // must have an `else`. Generate synthetic results here in the same
986 // manner we did above.
987 if label.kind == ControlKind::If && label.params != label.results {
988 instructions.push(Instruction::Else);
989 self.allocs.controls.push(label.clone());
990 self.allocs
991 .operands
992 .extend(label.params.into_iter().map(Some));
993 self.guarantee_label_results(u, instructions);
994 self.allocs.controls.pop();
995 self.allocs.operands.truncate(label.height);
996 }
997
998 // The last control frame for the function return does not
999 // need an `end` instruction.
1000 if !self.allocs.controls.is_empty() {
1001 instructions.push(Instruction::End);
1002 }
1003
1004 // Place the results of the label onto the operand stack for use
1005 // after the label.
1006 self.allocs
1007 .operands
1008 .extend(label.results.into_iter().map(Some));
1009 }
1010 }
1011
1012 /// Modifies the instruction stream to guarantee that the current control
1013 /// label's results are on the stack and ready for the control label to return.
guarantee_label_results( &mut self, u: &mut Unstructured<'_>, instructions: &mut Vec<Instruction>, )1014 fn guarantee_label_results(
1015 &mut self,
1016 u: &mut Unstructured<'_>,
1017 instructions: &mut Vec<Instruction>,
1018 ) {
1019 let mut operands = self.operands();
1020 let label = self.allocs.controls.last().unwrap();
1021
1022 // Already done, yay!
1023 if label.results.len() == operands.len() && self.types_on_stack(&label.results) {
1024 return;
1025 }
1026
1027 // Generating an unreachable instruction is always a valid way to
1028 // generate any types for a label, but it's not too interesting, so
1029 // don't favor it.
1030 if u.arbitrary::<u16>().unwrap_or(0) == 1 {
1031 instructions.push(Instruction::Unreachable);
1032 return;
1033 }
1034
1035 // Arbitrarily massage the stack to get the expected results. First we
1036 // drop all extraneous results to we're only dealing with those we want
1037 // to deal with. Afterwards we start at the bottom of the stack and move
1038 // up, figuring out what matches and what doesn't. As soon as something
1039 // doesn't match we throw out that and everything else remaining,
1040 // filling in results with dummy values.
1041 while operands.len() > label.results.len() {
1042 instructions.push(Instruction::Drop);
1043 operands = &operands[..operands.len() - 1];
1044 }
1045 for (i, expected) in label.results.iter().enumerate() {
1046 if let Some(actual) = operands.get(i) {
1047 if Some(*expected) == *actual {
1048 continue;
1049 }
1050 for _ in operands[i..].iter() {
1051 instructions.push(Instruction::Drop);
1052 }
1053 operands = &[];
1054 }
1055 instructions.push(arbitrary_val(*expected, u));
1056 }
1057 }
1058 }
1059
arbitrary_val(ty: ValType, u: &mut Unstructured<'_>) -> Instruction1060 fn arbitrary_val(ty: ValType, u: &mut Unstructured<'_>) -> Instruction {
1061 match ty {
1062 ValType::I32 => Instruction::I32Const(u.arbitrary().unwrap_or(0)),
1063 ValType::I64 => Instruction::I64Const(u.arbitrary().unwrap_or(0)),
1064 ValType::F32 => Instruction::F32Const(u.arbitrary().unwrap_or(0.0)),
1065 ValType::F64 => Instruction::F64Const(u.arbitrary().unwrap_or(0.0)),
1066 ValType::V128 => Instruction::V128Const(u.arbitrary().unwrap_or(0)),
1067 ValType::ExternRef => Instruction::RefNull(ValType::ExternRef),
1068 ValType::FuncRef => Instruction::RefNull(ValType::FuncRef),
1069 }
1070 }
1071
unreachable(_: &mut Unstructured, _: &Module, _: &mut CodeBuilder) -> Result<Instruction>1072 fn unreachable(_: &mut Unstructured, _: &Module, _: &mut CodeBuilder) -> Result<Instruction> {
1073 Ok(Instruction::Unreachable)
1074 }
1075
nop(_: &mut Unstructured, _: &Module, _: &mut CodeBuilder) -> Result<Instruction>1076 fn nop(_: &mut Unstructured, _: &Module, _: &mut CodeBuilder) -> Result<Instruction> {
1077 Ok(Instruction::Nop)
1078 }
1079
block(u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1080 fn block(u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1081 let block_ty = builder.arbitrary_block_type(u, module)?;
1082 let (params, results) = block_ty.params_results(module);
1083 let height = builder.allocs.operands.len() - params.len();
1084 builder.allocs.controls.push(Control {
1085 kind: ControlKind::Block,
1086 params,
1087 results,
1088 height,
1089 });
1090 Ok(Instruction::Block(block_ty))
1091 }
1092
1093 #[inline]
try_valid(module: &Module, _: &mut CodeBuilder) -> bool1094 fn try_valid(module: &Module, _: &mut CodeBuilder) -> bool {
1095 module.config.exceptions_enabled()
1096 }
1097
1098 fn r#try(u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1099 let block_ty = builder.arbitrary_block_type(u, module)?;
1100 let (params, results) = block_ty.params_results(module);
1101 let height = builder.allocs.operands.len() - params.len();
1102 builder.allocs.controls.push(Control {
1103 kind: ControlKind::Try,
1104 params,
1105 results,
1106 height,
1107 });
1108 Ok(Instruction::Try(block_ty))
1109 }
1110
1111 #[inline]
delegate_valid(module: &Module, builder: &mut CodeBuilder) -> bool1112 fn delegate_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
1113 let control_kind = builder.allocs.controls.last().unwrap().kind;
1114 // delegate is only valid if end could be used in a try control frame
1115 module.config.exceptions_enabled()
1116 && control_kind == ControlKind::Try
1117 && end_valid(module, builder)
1118 }
1119
delegate(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1120 fn delegate(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1121 // There will always be at least the function's return frame and try
1122 // control frame if we are emitting delegate
1123 let n = builder.allocs.controls.iter().count();
1124 debug_assert!(n >= 2);
1125 // Delegate must target an outer control from the try block, and is
1126 // encoded with relative depth from the outer control
1127 let target_relative_from_last = u.int_in_range(1..=n - 1)?;
1128 let target_relative_from_outer = target_relative_from_last - 1;
1129 // Delegate ends the try block
1130 builder.allocs.controls.pop();
1131 Ok(Instruction::Delegate(target_relative_from_outer as u32))
1132 }
1133
1134 #[inline]
catch_valid(module: &Module, builder: &mut CodeBuilder) -> bool1135 fn catch_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
1136 let control_kind = builder.allocs.controls.last().unwrap().kind;
1137 // catch is only valid if end could be used in a try or catch (not
1138 // catch_all) control frame. There must also be a tag that we can catch.
1139 module.config.exceptions_enabled()
1140 && (control_kind == ControlKind::Try || control_kind == ControlKind::Catch)
1141 && end_valid(module, builder)
1142 && module.tags.len() > 0
1143 }
1144
catch(u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1145 fn catch(u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1146 let tag_idx = u.int_in_range(0..=(module.tags.len() - 1))?;
1147 let tag_type = &module.tags[tag_idx];
1148 let control = builder.allocs.controls.pop().unwrap();
1149 // Pop the results for the previous try or catch
1150 builder.pop_operands(&control.results);
1151 // Push the params of the tag we're catching
1152 builder.push_operands(&tag_type.func_type.params);
1153 builder.allocs.controls.push(Control {
1154 kind: ControlKind::Catch,
1155 ..control
1156 });
1157 Ok(Instruction::Catch(tag_idx as u32))
1158 }
1159
1160 #[inline]
catch_all_valid(module: &Module, builder: &mut CodeBuilder) -> bool1161 fn catch_all_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
1162 let control_kind = builder.allocs.controls.last().unwrap().kind;
1163 // catch_all is only valid if end could be used in a try or catch (not
1164 // catch_all) control frame.
1165 module.config.exceptions_enabled()
1166 && (control_kind == ControlKind::Try || control_kind == ControlKind::Catch)
1167 && end_valid(module, builder)
1168 }
1169
catch_all(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1170 fn catch_all(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1171 let control = builder.allocs.controls.pop().unwrap();
1172 // Pop the results for the previous try or catch
1173 builder.pop_operands(&control.results);
1174 builder.allocs.controls.push(Control {
1175 kind: ControlKind::CatchAll,
1176 ..control
1177 });
1178 Ok(Instruction::CatchAll)
1179 }
1180
1181 fn r#loop(u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1182 let block_ty = builder.arbitrary_block_type(u, module)?;
1183 let (params, results) = block_ty.params_results(module);
1184 let height = builder.allocs.operands.len() - params.len();
1185 builder.allocs.controls.push(Control {
1186 kind: ControlKind::Loop,
1187 params,
1188 results,
1189 height,
1190 });
1191 Ok(Instruction::Loop(block_ty))
1192 }
1193
1194 #[inline]
if_valid(_: &Module, builder: &mut CodeBuilder) -> bool1195 fn if_valid(_: &Module, builder: &mut CodeBuilder) -> bool {
1196 builder.type_on_stack(ValType::I32)
1197 }
1198
1199 fn r#if(u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1200 builder.pop_operands(&[ValType::I32]);
1201
1202 let block_ty = builder.arbitrary_block_type(u, module)?;
1203 let (params, results) = block_ty.params_results(module);
1204 let height = builder.allocs.operands.len() - params.len();
1205 builder.allocs.controls.push(Control {
1206 kind: ControlKind::If,
1207 params,
1208 results,
1209 height,
1210 });
1211 Ok(Instruction::If(block_ty))
1212 }
1213
1214 #[inline]
else_valid(_: &Module, builder: &mut CodeBuilder) -> bool1215 fn else_valid(_: &Module, builder: &mut CodeBuilder) -> bool {
1216 let last_control = builder.allocs.controls.last().unwrap();
1217 last_control.kind == ControlKind::If
1218 && builder.operands().len() == last_control.results.len()
1219 && builder.types_on_stack(&last_control.results)
1220 }
1221
1222 fn r#else(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1223 let control = builder.allocs.controls.pop().unwrap();
1224 builder.pop_operands(&control.results);
1225 builder.push_operands(&control.params);
1226 builder.allocs.controls.push(Control {
1227 kind: ControlKind::Block,
1228 ..control
1229 });
1230 Ok(Instruction::Else)
1231 }
1232
1233 #[inline]
end_valid(_: &Module, builder: &mut CodeBuilder) -> bool1234 fn end_valid(_: &Module, builder: &mut CodeBuilder) -> bool {
1235 // Note: first control frame is the function return's control frame, which
1236 // does not have an associated `end`.
1237 if builder.allocs.controls.len() <= 1 {
1238 return false;
1239 }
1240 let control = builder.allocs.controls.last().unwrap();
1241 builder.operands().len() == control.results.len()
1242 && builder.types_on_stack(&control.results)
1243 // `if`s that don't leave the stack as they found it must have an
1244 // `else`.
1245 && !(control.kind == ControlKind::If && control.params != control.results)
1246 }
1247
end(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1248 fn end(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1249 builder.allocs.controls.pop();
1250 Ok(Instruction::End)
1251 }
1252
1253 #[inline]
br_valid(_: &Module, builder: &mut CodeBuilder) -> bool1254 fn br_valid(_: &Module, builder: &mut CodeBuilder) -> bool {
1255 builder
1256 .allocs
1257 .controls
1258 .iter()
1259 .any(|l| builder.label_types_on_stack(l))
1260 }
1261
br(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1262 fn br(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1263 let n = builder
1264 .allocs
1265 .controls
1266 .iter()
1267 .filter(|l| builder.label_types_on_stack(l))
1268 .count();
1269 debug_assert!(n > 0);
1270 let i = u.int_in_range(0..=n - 1)?;
1271 let (target, _) = builder
1272 .allocs
1273 .controls
1274 .iter()
1275 .rev()
1276 .enumerate()
1277 .filter(|(_, l)| builder.label_types_on_stack(l))
1278 .nth(i)
1279 .unwrap();
1280 let control = &builder.allocs.controls[builder.allocs.controls.len() - 1 - target];
1281 let tys = control.label_types().to_vec();
1282 builder.pop_operands(&tys);
1283 Ok(Instruction::Br(target as u32))
1284 }
1285
1286 #[inline]
br_if_valid(_: &Module, builder: &mut CodeBuilder) -> bool1287 fn br_if_valid(_: &Module, builder: &mut CodeBuilder) -> bool {
1288 if !builder.type_on_stack(ValType::I32) {
1289 return false;
1290 }
1291 let ty = builder.allocs.operands.pop().unwrap();
1292 let is_valid = builder
1293 .allocs
1294 .controls
1295 .iter()
1296 .any(|l| builder.label_types_on_stack(l));
1297 builder.allocs.operands.push(ty);
1298 is_valid
1299 }
1300
br_if(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1301 fn br_if(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1302 builder.pop_operands(&[ValType::I32]);
1303
1304 let n = builder
1305 .allocs
1306 .controls
1307 .iter()
1308 .filter(|l| builder.label_types_on_stack(l))
1309 .count();
1310 debug_assert!(n > 0);
1311 let i = u.int_in_range(0..=n - 1)?;
1312 let (target, _) = builder
1313 .allocs
1314 .controls
1315 .iter()
1316 .rev()
1317 .enumerate()
1318 .filter(|(_, l)| builder.label_types_on_stack(l))
1319 .nth(i)
1320 .unwrap();
1321 Ok(Instruction::BrIf(target as u32))
1322 }
1323
1324 #[inline]
br_table_valid(module: &Module, builder: &mut CodeBuilder) -> bool1325 fn br_table_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
1326 if !builder.type_on_stack(ValType::I32) {
1327 return false;
1328 }
1329 let ty = builder.allocs.operands.pop().unwrap();
1330 let is_valid = br_valid(module, builder);
1331 builder.allocs.operands.push(ty);
1332 is_valid
1333 }
1334
br_table(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1335 fn br_table(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1336 builder.pop_operands(&[ValType::I32]);
1337
1338 let n = builder
1339 .allocs
1340 .controls
1341 .iter()
1342 .filter(|l| builder.label_types_on_stack(l))
1343 .count();
1344 debug_assert!(n > 0);
1345
1346 let i = u.int_in_range(0..=n - 1)?;
1347 let (default_target, _) = builder
1348 .allocs
1349 .controls
1350 .iter()
1351 .rev()
1352 .enumerate()
1353 .filter(|(_, l)| builder.label_types_on_stack(l))
1354 .nth(i)
1355 .unwrap();
1356 let control = &builder.allocs.controls[builder.allocs.controls.len() - 1 - default_target];
1357
1358 let targets = builder
1359 .allocs
1360 .controls
1361 .iter()
1362 .rev()
1363 .enumerate()
1364 .filter(|(_, l)| l.label_types() == control.label_types())
1365 .map(|(t, _)| t as u32)
1366 .collect();
1367
1368 let tys = control.label_types().to_vec();
1369 builder.pop_operands(&tys);
1370
1371 Ok(Instruction::BrTable(targets, default_target as u32))
1372 }
1373
1374 #[inline]
return_valid(_: &Module, builder: &mut CodeBuilder) -> bool1375 fn return_valid(_: &Module, builder: &mut CodeBuilder) -> bool {
1376 builder.label_types_on_stack(&builder.allocs.controls[0])
1377 }
1378
1379 fn r#return(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1380 let results = builder.allocs.controls[0].results.clone();
1381 builder.pop_operands(&results);
1382 Ok(Instruction::Return)
1383 }
1384
1385 #[inline]
call_valid(_: &Module, builder: &mut CodeBuilder) -> bool1386 fn call_valid(_: &Module, builder: &mut CodeBuilder) -> bool {
1387 builder
1388 .allocs
1389 .functions
1390 .keys()
1391 .any(|k| builder.types_on_stack(k))
1392 }
1393
call(u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1394 fn call(u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1395 let candidates = builder
1396 .allocs
1397 .functions
1398 .iter()
1399 .filter(|(k, _)| builder.types_on_stack(k))
1400 .flat_map(|(_, v)| v.iter().copied())
1401 .collect::<Vec<_>>();
1402 assert!(candidates.len() > 0);
1403 let i = u.int_in_range(0..=candidates.len() - 1)?;
1404 let (func_idx, ty) = module.funcs().nth(candidates[i] as usize).unwrap();
1405 builder.pop_operands(&ty.params);
1406 builder.push_operands(&ty.results);
1407 Ok(Instruction::Call(func_idx as u32))
1408 }
1409
1410 #[inline]
call_indirect_valid(module: &Module, builder: &mut CodeBuilder) -> bool1411 fn call_indirect_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
1412 if builder.allocs.funcref_tables.is_empty() || !builder.type_on_stack(ValType::I32) {
1413 return false;
1414 }
1415 let ty = builder.allocs.operands.pop().unwrap();
1416 let is_valid = module
1417 .func_types()
1418 .any(|(_, ty)| builder.types_on_stack(&ty.params));
1419 builder.allocs.operands.push(ty);
1420 is_valid
1421 }
1422
call_indirect( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1423 fn call_indirect(
1424 u: &mut Unstructured,
1425 module: &Module,
1426 builder: &mut CodeBuilder,
1427 ) -> Result<Instruction> {
1428 builder.pop_operands(&[ValType::I32]);
1429
1430 let choices = module
1431 .func_types()
1432 .filter(|(_, ty)| builder.types_on_stack(&ty.params))
1433 .collect::<Vec<_>>();
1434 let (type_idx, ty) = u.choose(&choices)?;
1435 builder.pop_operands(&ty.params);
1436 builder.push_operands(&ty.results);
1437 let table = *u.choose(&builder.allocs.funcref_tables)?;
1438 Ok(Instruction::CallIndirect {
1439 ty: *type_idx as u32,
1440 table,
1441 })
1442 }
1443
1444 #[inline]
throw_valid(module: &Module, builder: &mut CodeBuilder) -> bool1445 fn throw_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
1446 module.config.exceptions_enabled()
1447 && builder
1448 .allocs
1449 .tags
1450 .keys()
1451 .any(|k| builder.types_on_stack(k))
1452 }
1453
throw(u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1454 fn throw(u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1455 let candidates = builder
1456 .allocs
1457 .tags
1458 .iter()
1459 .filter(|(k, _)| builder.types_on_stack(k))
1460 .flat_map(|(_, v)| v.iter().copied())
1461 .collect::<Vec<_>>();
1462 assert!(candidates.len() > 0);
1463 let i = u.int_in_range(0..=candidates.len() - 1)?;
1464 let (tag_idx, tag_type) = module.tags().nth(candidates[i] as usize).unwrap();
1465 // Tags have no results, throwing cannot return
1466 assert!(tag_type.func_type.results.len() == 0);
1467 builder.pop_operands(&tag_type.func_type.params);
1468 Ok(Instruction::Throw(tag_idx as u32))
1469 }
1470
1471 #[inline]
rethrow_valid(module: &Module, builder: &mut CodeBuilder) -> bool1472 fn rethrow_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
1473 // There must be a catch or catch_all control on the stack
1474 module.config.exceptions_enabled()
1475 && builder
1476 .allocs
1477 .controls
1478 .iter()
1479 .any(|l| l.kind == ControlKind::Catch || l.kind == ControlKind::CatchAll)
1480 }
1481
rethrow(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1482 fn rethrow(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1483 let n = builder
1484 .allocs
1485 .controls
1486 .iter()
1487 .filter(|l| l.kind == ControlKind::Catch || l.kind == ControlKind::CatchAll)
1488 .count();
1489 debug_assert!(n > 0);
1490 let i = u.int_in_range(0..=n - 1)?;
1491 let (target, _) = builder
1492 .allocs
1493 .controls
1494 .iter()
1495 .rev()
1496 .enumerate()
1497 .filter(|(_, l)| l.kind == ControlKind::Catch || l.kind == ControlKind::CatchAll)
1498 .nth(i)
1499 .unwrap();
1500 Ok(Instruction::Rethrow(target as u32))
1501 }
1502
1503 #[inline]
drop_valid(_: &Module, builder: &mut CodeBuilder) -> bool1504 fn drop_valid(_: &Module, builder: &mut CodeBuilder) -> bool {
1505 !builder.operands().is_empty()
1506 }
1507
drop(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1508 fn drop(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1509 builder.allocs.operands.pop();
1510 Ok(Instruction::Drop)
1511 }
1512
1513 #[inline]
select_valid(_: &Module, builder: &mut CodeBuilder) -> bool1514 fn select_valid(_: &Module, builder: &mut CodeBuilder) -> bool {
1515 if !(builder.operands().len() >= 3 && builder.type_on_stack(ValType::I32)) {
1516 return false;
1517 }
1518 let t = builder.operands()[builder.operands().len() - 2];
1519 let u = builder.operands()[builder.operands().len() - 3];
1520 t.is_none() || u.is_none() || t == u
1521 }
1522
select(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1523 fn select(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1524 builder.allocs.operands.pop();
1525 let t = builder.allocs.operands.pop().unwrap();
1526 let u = builder.allocs.operands.pop().unwrap();
1527 let ty = t.or(u);
1528 builder.allocs.operands.push(ty);
1529 match ty {
1530 Some(ty @ ValType::ExternRef) | Some(ty @ ValType::FuncRef) => {
1531 Ok(Instruction::TypedSelect(ty))
1532 }
1533 Some(ValType::I32) | Some(ValType::I64) | Some(ValType::F32) | Some(ValType::F64)
1534 | Some(ValType::V128) | None => Ok(Instruction::Select),
1535 }
1536 }
1537
1538 #[inline]
local_get_valid(_: &Module, builder: &mut CodeBuilder) -> bool1539 fn local_get_valid(_: &Module, builder: &mut CodeBuilder) -> bool {
1540 !builder.func_ty.params.is_empty() || !builder.locals.is_empty()
1541 }
1542
local_get(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1543 fn local_get(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1544 let num_params = builder.func_ty.params.len();
1545 let n = num_params + builder.locals.len();
1546 debug_assert!(n > 0);
1547 let i = u.int_in_range(0..=n - 1)?;
1548 builder.allocs.operands.push(Some(if i < num_params {
1549 builder.func_ty.params[i]
1550 } else {
1551 builder.locals[i - num_params]
1552 }));
1553 Ok(Instruction::LocalGet(i as u32))
1554 }
1555
1556 #[inline]
local_set_valid(_: &Module, builder: &mut CodeBuilder) -> bool1557 fn local_set_valid(_: &Module, builder: &mut CodeBuilder) -> bool {
1558 builder
1559 .func_ty
1560 .params
1561 .iter()
1562 .chain(builder.locals.iter())
1563 .any(|ty| builder.type_on_stack(*ty))
1564 }
1565
local_set(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1566 fn local_set(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1567 let n = builder
1568 .func_ty
1569 .params
1570 .iter()
1571 .chain(builder.locals.iter())
1572 .filter(|ty| builder.type_on_stack(**ty))
1573 .count();
1574 debug_assert!(n > 0);
1575 let i = u.int_in_range(0..=n - 1)?;
1576 let (j, _) = builder
1577 .func_ty
1578 .params
1579 .iter()
1580 .chain(builder.locals.iter())
1581 .enumerate()
1582 .filter(|(_, ty)| builder.type_on_stack(**ty))
1583 .nth(i)
1584 .unwrap();
1585 builder.allocs.operands.pop();
1586 Ok(Instruction::LocalSet(j as u32))
1587 }
1588
local_tee(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1589 fn local_tee(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1590 let n = builder
1591 .func_ty
1592 .params
1593 .iter()
1594 .chain(builder.locals.iter())
1595 .filter(|ty| builder.type_on_stack(**ty))
1596 .count();
1597 debug_assert!(n > 0);
1598 let i = u.int_in_range(0..=n - 1)?;
1599 let (j, _) = builder
1600 .func_ty
1601 .params
1602 .iter()
1603 .chain(builder.locals.iter())
1604 .enumerate()
1605 .filter(|(_, ty)| builder.type_on_stack(**ty))
1606 .nth(i)
1607 .unwrap();
1608 Ok(Instruction::LocalTee(j as u32))
1609 }
1610
1611 #[inline]
global_get_valid(module: &Module, _: &mut CodeBuilder) -> bool1612 fn global_get_valid(module: &Module, _: &mut CodeBuilder) -> bool {
1613 module.globals.len() > 0
1614 }
1615
global_get( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1616 fn global_get(
1617 u: &mut Unstructured,
1618 module: &Module,
1619 builder: &mut CodeBuilder,
1620 ) -> Result<Instruction> {
1621 debug_assert!(module.globals.len() > 0);
1622 let global_idx = u.int_in_range(0..=module.globals.len() - 1)?;
1623 builder
1624 .allocs
1625 .operands
1626 .push(Some(module.globals[global_idx].val_type));
1627 Ok(Instruction::GlobalGet(global_idx as u32))
1628 }
1629
1630 #[inline]
global_set_valid(_: &Module, builder: &mut CodeBuilder) -> bool1631 fn global_set_valid(_: &Module, builder: &mut CodeBuilder) -> bool {
1632 builder
1633 .allocs
1634 .mutable_globals
1635 .iter()
1636 .any(|(ty, _)| builder.type_on_stack(*ty))
1637 }
1638
global_set(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>1639 fn global_set(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
1640 let candidates = builder
1641 .allocs
1642 .mutable_globals
1643 .iter()
1644 .find(|(ty, _)| builder.type_on_stack(**ty))
1645 .unwrap()
1646 .1;
1647 let i = u.int_in_range(0..=candidates.len() - 1)?;
1648 builder.allocs.operands.pop();
1649 Ok(Instruction::GlobalSet(candidates[i]))
1650 }
1651
1652 #[inline]
have_memory(module: &Module, _: &mut CodeBuilder) -> bool1653 fn have_memory(module: &Module, _: &mut CodeBuilder) -> bool {
1654 module.memories.len() > 0
1655 }
1656
1657 #[inline]
have_memory_and_offset(_module: &Module, builder: &mut CodeBuilder) -> bool1658 fn have_memory_and_offset(_module: &Module, builder: &mut CodeBuilder) -> bool {
1659 (builder.allocs.memory32.len() > 0 && builder.type_on_stack(ValType::I32))
1660 || (builder.allocs.memory64.len() > 0 && builder.type_on_stack(ValType::I64))
1661 }
1662
1663 #[inline]
have_data(module: &Module, _: &mut CodeBuilder) -> bool1664 fn have_data(module: &Module, _: &mut CodeBuilder) -> bool {
1665 module.data.len() > 0
1666 }
1667
i32_load( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1668 fn i32_load(
1669 u: &mut Unstructured,
1670 module: &Module,
1671 builder: &mut CodeBuilder,
1672 ) -> Result<Instruction> {
1673 let memarg = mem_arg(u, module, builder, &[0, 1])?;
1674 builder.allocs.operands.push(Some(ValType::I32));
1675 Ok(Instruction::I32Load(memarg))
1676 }
1677
i64_load( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1678 fn i64_load(
1679 u: &mut Unstructured,
1680 module: &Module,
1681 builder: &mut CodeBuilder,
1682 ) -> Result<Instruction> {
1683 let memarg = mem_arg(u, module, builder, &[0, 1, 2])?;
1684 builder.allocs.operands.push(Some(ValType::I64));
1685 Ok(Instruction::I64Load(memarg))
1686 }
1687
f32_load( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1688 fn f32_load(
1689 u: &mut Unstructured,
1690 module: &Module,
1691 builder: &mut CodeBuilder,
1692 ) -> Result<Instruction> {
1693 let memarg = mem_arg(u, module, builder, &[0, 1])?;
1694 builder.allocs.operands.push(Some(ValType::F32));
1695 Ok(Instruction::F32Load(memarg))
1696 }
1697
f64_load( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1698 fn f64_load(
1699 u: &mut Unstructured,
1700 module: &Module,
1701 builder: &mut CodeBuilder,
1702 ) -> Result<Instruction> {
1703 let memarg = mem_arg(u, module, builder, &[0, 1, 2])?;
1704 builder.allocs.operands.push(Some(ValType::F64));
1705 Ok(Instruction::F64Load(memarg))
1706 }
1707
i32_load_8_s( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1708 fn i32_load_8_s(
1709 u: &mut Unstructured,
1710 module: &Module,
1711 builder: &mut CodeBuilder,
1712 ) -> Result<Instruction> {
1713 let memarg = mem_arg(u, module, builder, &[0])?;
1714 builder.allocs.operands.push(Some(ValType::I32));
1715 Ok(Instruction::I32Load8_S(memarg))
1716 }
1717
i32_load_8_u( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1718 fn i32_load_8_u(
1719 u: &mut Unstructured,
1720 module: &Module,
1721 builder: &mut CodeBuilder,
1722 ) -> Result<Instruction> {
1723 let memarg = mem_arg(u, module, builder, &[0])?;
1724 builder.allocs.operands.push(Some(ValType::I32));
1725 Ok(Instruction::I32Load8_U(memarg))
1726 }
1727
i32_load_16_s( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1728 fn i32_load_16_s(
1729 u: &mut Unstructured,
1730 module: &Module,
1731 builder: &mut CodeBuilder,
1732 ) -> Result<Instruction> {
1733 let memarg = mem_arg(u, module, builder, &[0, 1])?;
1734 builder.allocs.operands.push(Some(ValType::I32));
1735 Ok(Instruction::I32Load16_S(memarg))
1736 }
1737
i32_load_16_u( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1738 fn i32_load_16_u(
1739 u: &mut Unstructured,
1740 module: &Module,
1741 builder: &mut CodeBuilder,
1742 ) -> Result<Instruction> {
1743 let memarg = mem_arg(u, module, builder, &[0, 1])?;
1744 builder.allocs.operands.push(Some(ValType::I32));
1745 Ok(Instruction::I32Load16_U(memarg))
1746 }
1747
i64_load_8_s( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1748 fn i64_load_8_s(
1749 u: &mut Unstructured,
1750 module: &Module,
1751 builder: &mut CodeBuilder,
1752 ) -> Result<Instruction> {
1753 let memarg = mem_arg(u, module, builder, &[0])?;
1754 builder.allocs.operands.push(Some(ValType::I64));
1755 Ok(Instruction::I64Load8_S(memarg))
1756 }
1757
i64_load_16_s( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1758 fn i64_load_16_s(
1759 u: &mut Unstructured,
1760 module: &Module,
1761 builder: &mut CodeBuilder,
1762 ) -> Result<Instruction> {
1763 let memarg = mem_arg(u, module, builder, &[0, 1])?;
1764 builder.allocs.operands.push(Some(ValType::I64));
1765 Ok(Instruction::I64Load16_S(memarg))
1766 }
1767
i64_load_32_s( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1768 fn i64_load_32_s(
1769 u: &mut Unstructured,
1770 module: &Module,
1771 builder: &mut CodeBuilder,
1772 ) -> Result<Instruction> {
1773 let memarg = mem_arg(u, module, builder, &[0, 1, 2])?;
1774 builder.allocs.operands.push(Some(ValType::I64));
1775 Ok(Instruction::I64Load32_S(memarg))
1776 }
1777
i64_load_8_u( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1778 fn i64_load_8_u(
1779 u: &mut Unstructured,
1780 module: &Module,
1781 builder: &mut CodeBuilder,
1782 ) -> Result<Instruction> {
1783 let memarg = mem_arg(u, module, builder, &[0])?;
1784 builder.allocs.operands.push(Some(ValType::I64));
1785 Ok(Instruction::I64Load8_U(memarg))
1786 }
1787
i64_load_16_u( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1788 fn i64_load_16_u(
1789 u: &mut Unstructured,
1790 module: &Module,
1791 builder: &mut CodeBuilder,
1792 ) -> Result<Instruction> {
1793 let memarg = mem_arg(u, module, builder, &[0, 1])?;
1794 builder.allocs.operands.push(Some(ValType::I64));
1795 Ok(Instruction::I64Load16_U(memarg))
1796 }
1797
i64_load_32_u( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1798 fn i64_load_32_u(
1799 u: &mut Unstructured,
1800 module: &Module,
1801 builder: &mut CodeBuilder,
1802 ) -> Result<Instruction> {
1803 let memarg = mem_arg(u, module, builder, &[0, 1, 2])?;
1804 builder.allocs.operands.push(Some(ValType::I64));
1805 Ok(Instruction::I64Load32_U(memarg))
1806 }
1807
1808 #[inline]
store_valid(_module: &Module, builder: &mut CodeBuilder, f: impl Fn() -> ValType) -> bool1809 fn store_valid(_module: &Module, builder: &mut CodeBuilder, f: impl Fn() -> ValType) -> bool {
1810 (builder.allocs.memory32.len() > 0 && builder.types_on_stack(&[ValType::I32, f()]))
1811 || (builder.allocs.memory64.len() > 0 && builder.types_on_stack(&[ValType::I64, f()]))
1812 }
1813
1814 #[inline]
i32_store_valid(module: &Module, builder: &mut CodeBuilder) -> bool1815 fn i32_store_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
1816 store_valid(module, builder, || ValType::I32)
1817 }
1818
i32_store( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1819 fn i32_store(
1820 u: &mut Unstructured,
1821 module: &Module,
1822 builder: &mut CodeBuilder,
1823 ) -> Result<Instruction> {
1824 builder.pop_operands(&[ValType::I32]);
1825 let memarg = mem_arg(u, module, builder, &[0, 1])?;
1826 Ok(Instruction::I32Store(memarg))
1827 }
1828
1829 #[inline]
i64_store_valid(module: &Module, builder: &mut CodeBuilder) -> bool1830 fn i64_store_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
1831 store_valid(module, builder, || ValType::I64)
1832 }
1833
i64_store( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1834 fn i64_store(
1835 u: &mut Unstructured,
1836 module: &Module,
1837 builder: &mut CodeBuilder,
1838 ) -> Result<Instruction> {
1839 builder.pop_operands(&[ValType::I64]);
1840 let memarg = mem_arg(u, module, builder, &[0, 1, 2])?;
1841 Ok(Instruction::I64Store(memarg))
1842 }
1843
1844 #[inline]
f32_store_valid(module: &Module, builder: &mut CodeBuilder) -> bool1845 fn f32_store_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
1846 store_valid(module, builder, || ValType::F32)
1847 }
1848
f32_store( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1849 fn f32_store(
1850 u: &mut Unstructured,
1851 module: &Module,
1852 builder: &mut CodeBuilder,
1853 ) -> Result<Instruction> {
1854 builder.pop_operands(&[ValType::F32]);
1855 let memarg = mem_arg(u, module, builder, &[0, 1])?;
1856 Ok(Instruction::F32Store(memarg))
1857 }
1858
1859 #[inline]
f64_store_valid(module: &Module, builder: &mut CodeBuilder) -> bool1860 fn f64_store_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
1861 store_valid(module, builder, || ValType::F64)
1862 }
1863
f64_store( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1864 fn f64_store(
1865 u: &mut Unstructured,
1866 module: &Module,
1867 builder: &mut CodeBuilder,
1868 ) -> Result<Instruction> {
1869 builder.pop_operands(&[ValType::F64]);
1870 let memarg = mem_arg(u, module, builder, &[0, 1, 2])?;
1871 Ok(Instruction::F64Store(memarg))
1872 }
1873
i32_store_8( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1874 fn i32_store_8(
1875 u: &mut Unstructured,
1876 module: &Module,
1877 builder: &mut CodeBuilder,
1878 ) -> Result<Instruction> {
1879 builder.pop_operands(&[ValType::I32]);
1880 let memarg = mem_arg(u, module, builder, &[0])?;
1881 Ok(Instruction::I32Store8(memarg))
1882 }
1883
i32_store_16( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1884 fn i32_store_16(
1885 u: &mut Unstructured,
1886 module: &Module,
1887 builder: &mut CodeBuilder,
1888 ) -> Result<Instruction> {
1889 builder.pop_operands(&[ValType::I32]);
1890 let memarg = mem_arg(u, module, builder, &[0, 1])?;
1891 Ok(Instruction::I32Store16(memarg))
1892 }
1893
i64_store_8( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1894 fn i64_store_8(
1895 u: &mut Unstructured,
1896 module: &Module,
1897 builder: &mut CodeBuilder,
1898 ) -> Result<Instruction> {
1899 builder.pop_operands(&[ValType::I64]);
1900 let memarg = mem_arg(u, module, builder, &[0])?;
1901 Ok(Instruction::I64Store8(memarg))
1902 }
1903
i64_store_16( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1904 fn i64_store_16(
1905 u: &mut Unstructured,
1906 module: &Module,
1907 builder: &mut CodeBuilder,
1908 ) -> Result<Instruction> {
1909 builder.pop_operands(&[ValType::I64]);
1910 let memarg = mem_arg(u, module, builder, &[0, 1])?;
1911 Ok(Instruction::I64Store16(memarg))
1912 }
1913
i64_store_32( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1914 fn i64_store_32(
1915 u: &mut Unstructured,
1916 module: &Module,
1917 builder: &mut CodeBuilder,
1918 ) -> Result<Instruction> {
1919 builder.pop_operands(&[ValType::I64]);
1920 let memarg = mem_arg(u, module, builder, &[0, 1, 2])?;
1921 Ok(Instruction::I64Store32(memarg))
1922 }
1923
memory_size( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1924 fn memory_size(
1925 u: &mut Unstructured,
1926 module: &Module,
1927 builder: &mut CodeBuilder,
1928 ) -> Result<Instruction> {
1929 let i = u.int_in_range(0..=module.memories.len() - 1)?;
1930 let ty = if module.memories[i].memory64 {
1931 ValType::I64
1932 } else {
1933 ValType::I32
1934 };
1935 builder.push_operands(&[ty]);
1936 Ok(Instruction::MemorySize(i as u32))
1937 }
1938
1939 #[inline]
memory_grow_valid(_module: &Module, builder: &mut CodeBuilder) -> bool1940 fn memory_grow_valid(_module: &Module, builder: &mut CodeBuilder) -> bool {
1941 (builder.allocs.memory32.len() > 0 && builder.type_on_stack(ValType::I32))
1942 || (builder.allocs.memory64.len() > 0 && builder.type_on_stack(ValType::I64))
1943 }
1944
memory_grow( u: &mut Unstructured, _module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1945 fn memory_grow(
1946 u: &mut Unstructured,
1947 _module: &Module,
1948 builder: &mut CodeBuilder,
1949 ) -> Result<Instruction> {
1950 let ty = if builder.type_on_stack(ValType::I32) {
1951 ValType::I32
1952 } else {
1953 ValType::I64
1954 };
1955 let index = memory_index(u, builder, ty)?;
1956 builder.pop_operands(&[ty]);
1957 builder.push_operands(&[ty]);
1958 Ok(Instruction::MemoryGrow(index))
1959 }
1960
1961 #[inline]
memory_init_valid(module: &Module, builder: &mut CodeBuilder) -> bool1962 fn memory_init_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
1963 module.config.bulk_memory_enabled()
1964 && have_data(module, builder)
1965 && (builder.allocs.memory32.len() > 0
1966 && builder.types_on_stack(&[ValType::I32, ValType::I32, ValType::I32])
1967 || (builder.allocs.memory64.len() > 0
1968 && builder.types_on_stack(&[ValType::I64, ValType::I32, ValType::I32])))
1969 }
1970
memory_init( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1971 fn memory_init(
1972 u: &mut Unstructured,
1973 module: &Module,
1974 builder: &mut CodeBuilder,
1975 ) -> Result<Instruction> {
1976 builder.pop_operands(&[ValType::I32, ValType::I32]);
1977 let ty = if builder.type_on_stack(ValType::I32) {
1978 ValType::I32
1979 } else {
1980 ValType::I64
1981 };
1982 let mem = memory_index(u, builder, ty)?;
1983 let data = data_index(u, module)?;
1984 builder.pop_operands(&[ty]);
1985 Ok(Instruction::MemoryInit { mem, data })
1986 }
1987
1988 #[inline]
memory_fill_valid(module: &Module, builder: &mut CodeBuilder) -> bool1989 fn memory_fill_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
1990 module.config.bulk_memory_enabled()
1991 && (builder.allocs.memory32.len() > 0
1992 && builder.types_on_stack(&[ValType::I32, ValType::I32, ValType::I32])
1993 || (builder.allocs.memory64.len() > 0
1994 && builder.types_on_stack(&[ValType::I64, ValType::I32, ValType::I64])))
1995 }
1996
memory_fill( u: &mut Unstructured, _module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>1997 fn memory_fill(
1998 u: &mut Unstructured,
1999 _module: &Module,
2000 builder: &mut CodeBuilder,
2001 ) -> Result<Instruction> {
2002 let ty = if builder.type_on_stack(ValType::I32) {
2003 ValType::I32
2004 } else {
2005 ValType::I64
2006 };
2007 let mem = memory_index(u, builder, ty)?;
2008 builder.pop_operands(&[ty, ValType::I32, ty]);
2009 Ok(Instruction::MemoryFill(mem))
2010 }
2011
2012 #[inline]
memory_copy_valid(module: &Module, builder: &mut CodeBuilder) -> bool2013 fn memory_copy_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
2014 if !module.config.bulk_memory_enabled() {
2015 return false;
2016 }
2017
2018 if builder.types_on_stack(&[ValType::I64, ValType::I64, ValType::I64])
2019 && builder.allocs.memory64.len() > 0
2020 {
2021 return true;
2022 }
2023 if builder.types_on_stack(&[ValType::I32, ValType::I32, ValType::I32])
2024 && builder.allocs.memory32.len() > 0
2025 {
2026 return true;
2027 }
2028 if builder.types_on_stack(&[ValType::I64, ValType::I32, ValType::I32])
2029 && builder.allocs.memory32.len() > 0
2030 && builder.allocs.memory64.len() > 0
2031 {
2032 return true;
2033 }
2034 if builder.types_on_stack(&[ValType::I32, ValType::I64, ValType::I32])
2035 && builder.allocs.memory32.len() > 0
2036 && builder.allocs.memory64.len() > 0
2037 {
2038 return true;
2039 }
2040 false
2041 }
2042
memory_copy( u: &mut Unstructured, _module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2043 fn memory_copy(
2044 u: &mut Unstructured,
2045 _module: &Module,
2046 builder: &mut CodeBuilder,
2047 ) -> Result<Instruction> {
2048 let (src, dst) = if builder.types_on_stack(&[ValType::I64, ValType::I64, ValType::I64]) {
2049 builder.pop_operands(&[ValType::I64, ValType::I64, ValType::I64]);
2050 (
2051 memory_index(u, builder, ValType::I64)?,
2052 memory_index(u, builder, ValType::I64)?,
2053 )
2054 } else if builder.types_on_stack(&[ValType::I32, ValType::I32, ValType::I32]) {
2055 builder.pop_operands(&[ValType::I32, ValType::I32, ValType::I32]);
2056 (
2057 memory_index(u, builder, ValType::I32)?,
2058 memory_index(u, builder, ValType::I32)?,
2059 )
2060 } else if builder.types_on_stack(&[ValType::I64, ValType::I32, ValType::I32]) {
2061 builder.pop_operands(&[ValType::I64, ValType::I32, ValType::I32]);
2062 (
2063 memory_index(u, builder, ValType::I32)?,
2064 memory_index(u, builder, ValType::I64)?,
2065 )
2066 } else if builder.types_on_stack(&[ValType::I32, ValType::I64, ValType::I32]) {
2067 builder.pop_operands(&[ValType::I32, ValType::I64, ValType::I32]);
2068 (
2069 memory_index(u, builder, ValType::I64)?,
2070 memory_index(u, builder, ValType::I32)?,
2071 )
2072 } else {
2073 unreachable!()
2074 };
2075 Ok(Instruction::MemoryCopy { dst, src })
2076 }
2077
2078 #[inline]
data_drop_valid(module: &Module, builder: &mut CodeBuilder) -> bool2079 fn data_drop_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
2080 have_data(module, builder) && module.config.bulk_memory_enabled()
2081 }
2082
data_drop( u: &mut Unstructured, module: &Module, _builder: &mut CodeBuilder, ) -> Result<Instruction>2083 fn data_drop(
2084 u: &mut Unstructured,
2085 module: &Module,
2086 _builder: &mut CodeBuilder,
2087 ) -> Result<Instruction> {
2088 Ok(Instruction::DataDrop(data_index(u, module)?))
2089 }
2090
i32_const(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2091 fn i32_const(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2092 let x = u.arbitrary()?;
2093 builder.push_operands(&[ValType::I32]);
2094 Ok(Instruction::I32Const(x))
2095 }
2096
i64_const(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2097 fn i64_const(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2098 let x = u.arbitrary()?;
2099 builder.push_operands(&[ValType::I64]);
2100 Ok(Instruction::I64Const(x))
2101 }
2102
f32_const(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2103 fn f32_const(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2104 let x = u.arbitrary()?;
2105 builder.push_operands(&[ValType::F32]);
2106 Ok(Instruction::F32Const(x))
2107 }
2108
f64_const(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2109 fn f64_const(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2110 let x = u.arbitrary()?;
2111 builder.push_operands(&[ValType::F64]);
2112 Ok(Instruction::F64Const(x))
2113 }
2114
2115 #[inline]
i32_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool2116 fn i32_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool {
2117 builder.type_on_stack(ValType::I32)
2118 }
2119
i32_eqz(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2120 fn i32_eqz(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2121 builder.pop_operands(&[ValType::I32]);
2122 builder.push_operands(&[ValType::I32]);
2123 Ok(Instruction::I32Eqz)
2124 }
2125
2126 #[inline]
i32_i32_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool2127 fn i32_i32_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool {
2128 builder.types_on_stack(&[ValType::I32, ValType::I32])
2129 }
2130
i32_eq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2131 fn i32_eq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2132 builder.pop_operands(&[ValType::I32, ValType::I32]);
2133 builder.push_operands(&[ValType::I32]);
2134 Ok(Instruction::I32Eq)
2135 }
2136
i32_neq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2137 fn i32_neq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2138 builder.pop_operands(&[ValType::I32, ValType::I32]);
2139 builder.push_operands(&[ValType::I32]);
2140 Ok(Instruction::I32Neq)
2141 }
2142
i32_lt_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2143 fn i32_lt_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2144 builder.pop_operands(&[ValType::I32, ValType::I32]);
2145 builder.push_operands(&[ValType::I32]);
2146 Ok(Instruction::I32LtS)
2147 }
2148
i32_lt_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2149 fn i32_lt_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2150 builder.pop_operands(&[ValType::I32, ValType::I32]);
2151 builder.push_operands(&[ValType::I32]);
2152 Ok(Instruction::I32LtU)
2153 }
2154
i32_gt_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2155 fn i32_gt_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2156 builder.pop_operands(&[ValType::I32, ValType::I32]);
2157 builder.push_operands(&[ValType::I32]);
2158 Ok(Instruction::I32GtS)
2159 }
2160
i32_gt_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2161 fn i32_gt_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2162 builder.pop_operands(&[ValType::I32, ValType::I32]);
2163 builder.push_operands(&[ValType::I32]);
2164 Ok(Instruction::I32GtU)
2165 }
2166
i32_le_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2167 fn i32_le_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2168 builder.pop_operands(&[ValType::I32, ValType::I32]);
2169 builder.push_operands(&[ValType::I32]);
2170 Ok(Instruction::I32LeS)
2171 }
2172
i32_le_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2173 fn i32_le_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2174 builder.pop_operands(&[ValType::I32, ValType::I32]);
2175 builder.push_operands(&[ValType::I32]);
2176 Ok(Instruction::I32LeU)
2177 }
2178
i32_ge_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2179 fn i32_ge_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2180 builder.pop_operands(&[ValType::I32, ValType::I32]);
2181 builder.push_operands(&[ValType::I32]);
2182 Ok(Instruction::I32GeS)
2183 }
2184
i32_ge_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2185 fn i32_ge_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2186 builder.pop_operands(&[ValType::I32, ValType::I32]);
2187 builder.push_operands(&[ValType::I32]);
2188 Ok(Instruction::I32GeU)
2189 }
2190
2191 #[inline]
i64_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool2192 fn i64_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool {
2193 builder.types_on_stack(&[ValType::I64])
2194 }
2195
i64_eqz(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2196 fn i64_eqz(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2197 builder.pop_operands(&[ValType::I64]);
2198 builder.push_operands(&[ValType::I32]);
2199 Ok(Instruction::I64Eqz)
2200 }
2201
2202 #[inline]
i64_i64_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool2203 fn i64_i64_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool {
2204 builder.types_on_stack(&[ValType::I64, ValType::I64])
2205 }
2206
i64_eq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2207 fn i64_eq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2208 builder.pop_operands(&[ValType::I64, ValType::I64]);
2209 builder.push_operands(&[ValType::I32]);
2210 Ok(Instruction::I64Eq)
2211 }
2212
i64_neq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2213 fn i64_neq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2214 builder.pop_operands(&[ValType::I64, ValType::I64]);
2215 builder.push_operands(&[ValType::I32]);
2216 Ok(Instruction::I64Neq)
2217 }
2218
i64_lt_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2219 fn i64_lt_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2220 builder.pop_operands(&[ValType::I64, ValType::I64]);
2221 builder.push_operands(&[ValType::I32]);
2222 Ok(Instruction::I64LtS)
2223 }
2224
i64_lt_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2225 fn i64_lt_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2226 builder.pop_operands(&[ValType::I64, ValType::I64]);
2227 builder.push_operands(&[ValType::I32]);
2228 Ok(Instruction::I64LtU)
2229 }
2230
i64_gt_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2231 fn i64_gt_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2232 builder.pop_operands(&[ValType::I64, ValType::I64]);
2233 builder.push_operands(&[ValType::I32]);
2234 Ok(Instruction::I64GtS)
2235 }
2236
i64_gt_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2237 fn i64_gt_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2238 builder.pop_operands(&[ValType::I64, ValType::I64]);
2239 builder.push_operands(&[ValType::I32]);
2240 Ok(Instruction::I64GtU)
2241 }
2242
i64_le_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2243 fn i64_le_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2244 builder.pop_operands(&[ValType::I64, ValType::I64]);
2245 builder.push_operands(&[ValType::I32]);
2246 Ok(Instruction::I64LeS)
2247 }
2248
i64_le_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2249 fn i64_le_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2250 builder.pop_operands(&[ValType::I64, ValType::I64]);
2251 builder.push_operands(&[ValType::I32]);
2252 Ok(Instruction::I64LeU)
2253 }
2254
i64_ge_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2255 fn i64_ge_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2256 builder.pop_operands(&[ValType::I64, ValType::I64]);
2257 builder.push_operands(&[ValType::I32]);
2258 Ok(Instruction::I64GeS)
2259 }
2260
i64_ge_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2261 fn i64_ge_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2262 builder.pop_operands(&[ValType::I64, ValType::I64]);
2263 builder.push_operands(&[ValType::I32]);
2264 Ok(Instruction::I64GeU)
2265 }
2266
f32_f32_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool2267 fn f32_f32_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool {
2268 builder.types_on_stack(&[ValType::F32, ValType::F32])
2269 }
2270
f32_eq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2271 fn f32_eq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2272 builder.pop_operands(&[ValType::F32, ValType::F32]);
2273 builder.push_operands(&[ValType::I32]);
2274 Ok(Instruction::F32Eq)
2275 }
2276
f32_neq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2277 fn f32_neq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2278 builder.pop_operands(&[ValType::F32, ValType::F32]);
2279 builder.push_operands(&[ValType::I32]);
2280 Ok(Instruction::F32Neq)
2281 }
2282
f32_lt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2283 fn f32_lt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2284 builder.pop_operands(&[ValType::F32, ValType::F32]);
2285 builder.push_operands(&[ValType::I32]);
2286 Ok(Instruction::F32Lt)
2287 }
2288
f32_gt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2289 fn f32_gt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2290 builder.pop_operands(&[ValType::F32, ValType::F32]);
2291 builder.push_operands(&[ValType::I32]);
2292 Ok(Instruction::F32Gt)
2293 }
2294
f32_le(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2295 fn f32_le(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2296 builder.pop_operands(&[ValType::F32, ValType::F32]);
2297 builder.push_operands(&[ValType::I32]);
2298 Ok(Instruction::F32Le)
2299 }
2300
f32_ge(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2301 fn f32_ge(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2302 builder.pop_operands(&[ValType::F32, ValType::F32]);
2303 builder.push_operands(&[ValType::I32]);
2304 Ok(Instruction::F32Ge)
2305 }
2306
f64_f64_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool2307 fn f64_f64_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool {
2308 builder.types_on_stack(&[ValType::F64, ValType::F64])
2309 }
2310
f64_eq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2311 fn f64_eq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2312 builder.pop_operands(&[ValType::F64, ValType::F64]);
2313 builder.push_operands(&[ValType::I32]);
2314 Ok(Instruction::F64Eq)
2315 }
2316
f64_neq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2317 fn f64_neq(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2318 builder.pop_operands(&[ValType::F64, ValType::F64]);
2319 builder.push_operands(&[ValType::I32]);
2320 Ok(Instruction::F64Neq)
2321 }
2322
f64_lt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2323 fn f64_lt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2324 builder.pop_operands(&[ValType::F64, ValType::F64]);
2325 builder.push_operands(&[ValType::I32]);
2326 Ok(Instruction::F64Lt)
2327 }
2328
f64_gt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2329 fn f64_gt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2330 builder.pop_operands(&[ValType::F64, ValType::F64]);
2331 builder.push_operands(&[ValType::I32]);
2332 Ok(Instruction::F64Gt)
2333 }
2334
f64_le(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2335 fn f64_le(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2336 builder.pop_operands(&[ValType::F64, ValType::F64]);
2337 builder.push_operands(&[ValType::I32]);
2338 Ok(Instruction::F64Le)
2339 }
2340
f64_ge(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2341 fn f64_ge(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2342 builder.pop_operands(&[ValType::F64, ValType::F64]);
2343 builder.push_operands(&[ValType::I32]);
2344 Ok(Instruction::F64Ge)
2345 }
2346
i32_clz(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2347 fn i32_clz(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2348 builder.pop_operands(&[ValType::I32]);
2349 builder.push_operands(&[ValType::I32]);
2350 Ok(Instruction::I32Clz)
2351 }
2352
i32_ctz(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2353 fn i32_ctz(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2354 builder.pop_operands(&[ValType::I32]);
2355 builder.push_operands(&[ValType::I32]);
2356 Ok(Instruction::I32Ctz)
2357 }
2358
i32_popcnt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2359 fn i32_popcnt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2360 builder.pop_operands(&[ValType::I32]);
2361 builder.push_operands(&[ValType::I32]);
2362 Ok(Instruction::I32Popcnt)
2363 }
2364
i32_add(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2365 fn i32_add(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2366 builder.pop_operands(&[ValType::I32, ValType::I32]);
2367 builder.push_operands(&[ValType::I32]);
2368 Ok(Instruction::I32Add)
2369 }
2370
i32_sub(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2371 fn i32_sub(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2372 builder.pop_operands(&[ValType::I32, ValType::I32]);
2373 builder.push_operands(&[ValType::I32]);
2374 Ok(Instruction::I32Sub)
2375 }
2376
i32_mul(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2377 fn i32_mul(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2378 builder.pop_operands(&[ValType::I32, ValType::I32]);
2379 builder.push_operands(&[ValType::I32]);
2380 Ok(Instruction::I32Mul)
2381 }
2382
i32_div_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2383 fn i32_div_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2384 builder.pop_operands(&[ValType::I32, ValType::I32]);
2385 builder.push_operands(&[ValType::I32]);
2386 Ok(Instruction::I32DivS)
2387 }
2388
i32_div_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2389 fn i32_div_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2390 builder.pop_operands(&[ValType::I32, ValType::I32]);
2391 builder.push_operands(&[ValType::I32]);
2392 Ok(Instruction::I32DivU)
2393 }
2394
i32_rem_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2395 fn i32_rem_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2396 builder.pop_operands(&[ValType::I32, ValType::I32]);
2397 builder.push_operands(&[ValType::I32]);
2398 Ok(Instruction::I32RemS)
2399 }
2400
i32_rem_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2401 fn i32_rem_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2402 builder.pop_operands(&[ValType::I32, ValType::I32]);
2403 builder.push_operands(&[ValType::I32]);
2404 Ok(Instruction::I32RemU)
2405 }
2406
i32_and(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2407 fn i32_and(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2408 builder.pop_operands(&[ValType::I32, ValType::I32]);
2409 builder.push_operands(&[ValType::I32]);
2410 Ok(Instruction::I32And)
2411 }
2412
i32_or(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2413 fn i32_or(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2414 builder.pop_operands(&[ValType::I32, ValType::I32]);
2415 builder.push_operands(&[ValType::I32]);
2416 Ok(Instruction::I32Or)
2417 }
2418
i32_xor(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2419 fn i32_xor(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2420 builder.pop_operands(&[ValType::I32, ValType::I32]);
2421 builder.push_operands(&[ValType::I32]);
2422 Ok(Instruction::I32Xor)
2423 }
2424
i32_shl(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2425 fn i32_shl(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2426 builder.pop_operands(&[ValType::I32, ValType::I32]);
2427 builder.push_operands(&[ValType::I32]);
2428 Ok(Instruction::I32Shl)
2429 }
2430
i32_shr_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2431 fn i32_shr_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2432 builder.pop_operands(&[ValType::I32, ValType::I32]);
2433 builder.push_operands(&[ValType::I32]);
2434 Ok(Instruction::I32ShrS)
2435 }
2436
i32_shr_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2437 fn i32_shr_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2438 builder.pop_operands(&[ValType::I32, ValType::I32]);
2439 builder.push_operands(&[ValType::I32]);
2440 Ok(Instruction::I32ShrU)
2441 }
2442
i32_rotl(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2443 fn i32_rotl(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2444 builder.pop_operands(&[ValType::I32, ValType::I32]);
2445 builder.push_operands(&[ValType::I32]);
2446 Ok(Instruction::I32Rotl)
2447 }
2448
i32_rotr(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2449 fn i32_rotr(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2450 builder.pop_operands(&[ValType::I32, ValType::I32]);
2451 builder.push_operands(&[ValType::I32]);
2452 Ok(Instruction::I32Rotr)
2453 }
2454
i64_clz(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2455 fn i64_clz(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2456 builder.pop_operands(&[ValType::I64]);
2457 builder.push_operands(&[ValType::I64]);
2458 Ok(Instruction::I64Clz)
2459 }
2460
i64_ctz(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2461 fn i64_ctz(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2462 builder.pop_operands(&[ValType::I64]);
2463 builder.push_operands(&[ValType::I64]);
2464 Ok(Instruction::I64Ctz)
2465 }
2466
i64_popcnt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2467 fn i64_popcnt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2468 builder.pop_operands(&[ValType::I64]);
2469 builder.push_operands(&[ValType::I64]);
2470 Ok(Instruction::I64Popcnt)
2471 }
2472
i64_add(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2473 fn i64_add(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2474 builder.pop_operands(&[ValType::I64, ValType::I64]);
2475 builder.push_operands(&[ValType::I64]);
2476 Ok(Instruction::I64Add)
2477 }
2478
i64_sub(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2479 fn i64_sub(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2480 builder.pop_operands(&[ValType::I64, ValType::I64]);
2481 builder.push_operands(&[ValType::I64]);
2482 Ok(Instruction::I64Sub)
2483 }
2484
i64_mul(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2485 fn i64_mul(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2486 builder.pop_operands(&[ValType::I64, ValType::I64]);
2487 builder.push_operands(&[ValType::I64]);
2488 Ok(Instruction::I64Mul)
2489 }
2490
i64_div_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2491 fn i64_div_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2492 builder.pop_operands(&[ValType::I64, ValType::I64]);
2493 builder.push_operands(&[ValType::I64]);
2494 Ok(Instruction::I64DivS)
2495 }
2496
i64_div_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2497 fn i64_div_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2498 builder.pop_operands(&[ValType::I64, ValType::I64]);
2499 builder.push_operands(&[ValType::I64]);
2500 Ok(Instruction::I64DivU)
2501 }
2502
i64_rem_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2503 fn i64_rem_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2504 builder.pop_operands(&[ValType::I64, ValType::I64]);
2505 builder.push_operands(&[ValType::I64]);
2506 Ok(Instruction::I64RemS)
2507 }
2508
i64_rem_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2509 fn i64_rem_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2510 builder.pop_operands(&[ValType::I64, ValType::I64]);
2511 builder.push_operands(&[ValType::I64]);
2512 Ok(Instruction::I64RemU)
2513 }
2514
i64_and(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2515 fn i64_and(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2516 builder.pop_operands(&[ValType::I64, ValType::I64]);
2517 builder.push_operands(&[ValType::I64]);
2518 Ok(Instruction::I64And)
2519 }
2520
i64_or(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2521 fn i64_or(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2522 builder.pop_operands(&[ValType::I64, ValType::I64]);
2523 builder.push_operands(&[ValType::I64]);
2524 Ok(Instruction::I64Or)
2525 }
2526
i64_xor(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2527 fn i64_xor(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2528 builder.pop_operands(&[ValType::I64, ValType::I64]);
2529 builder.push_operands(&[ValType::I64]);
2530 Ok(Instruction::I64Xor)
2531 }
2532
i64_shl(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2533 fn i64_shl(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2534 builder.pop_operands(&[ValType::I64, ValType::I64]);
2535 builder.push_operands(&[ValType::I64]);
2536 Ok(Instruction::I64Shl)
2537 }
2538
i64_shr_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2539 fn i64_shr_s(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2540 builder.pop_operands(&[ValType::I64, ValType::I64]);
2541 builder.push_operands(&[ValType::I64]);
2542 Ok(Instruction::I64ShrS)
2543 }
2544
i64_shr_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2545 fn i64_shr_u(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2546 builder.pop_operands(&[ValType::I64, ValType::I64]);
2547 builder.push_operands(&[ValType::I64]);
2548 Ok(Instruction::I64ShrU)
2549 }
2550
i64_rotl(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2551 fn i64_rotl(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2552 builder.pop_operands(&[ValType::I64, ValType::I64]);
2553 builder.push_operands(&[ValType::I64]);
2554 Ok(Instruction::I64Rotl)
2555 }
2556
i64_rotr(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2557 fn i64_rotr(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2558 builder.pop_operands(&[ValType::I64, ValType::I64]);
2559 builder.push_operands(&[ValType::I64]);
2560 Ok(Instruction::I64Rotr)
2561 }
2562
2563 #[inline]
f32_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool2564 fn f32_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool {
2565 builder.types_on_stack(&[ValType::F32])
2566 }
2567
f32_abs(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2568 fn f32_abs(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2569 builder.pop_operands(&[ValType::F32]);
2570 builder.push_operands(&[ValType::F32]);
2571 Ok(Instruction::F32Abs)
2572 }
2573
f32_neg(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2574 fn f32_neg(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2575 builder.pop_operands(&[ValType::F32]);
2576 builder.push_operands(&[ValType::F32]);
2577 Ok(Instruction::F32Neg)
2578 }
2579
f32_ceil(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2580 fn f32_ceil(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2581 builder.pop_operands(&[ValType::F32]);
2582 builder.push_operands(&[ValType::F32]);
2583 Ok(Instruction::F32Ceil)
2584 }
2585
f32_floor(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2586 fn f32_floor(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2587 builder.pop_operands(&[ValType::F32]);
2588 builder.push_operands(&[ValType::F32]);
2589 Ok(Instruction::F32Floor)
2590 }
2591
f32_trunc(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2592 fn f32_trunc(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2593 builder.pop_operands(&[ValType::F32]);
2594 builder.push_operands(&[ValType::F32]);
2595 Ok(Instruction::F32Trunc)
2596 }
2597
f32_nearest(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2598 fn f32_nearest(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2599 builder.pop_operands(&[ValType::F32]);
2600 builder.push_operands(&[ValType::F32]);
2601 Ok(Instruction::F32Nearest)
2602 }
2603
f32_sqrt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2604 fn f32_sqrt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2605 builder.pop_operands(&[ValType::F32]);
2606 builder.push_operands(&[ValType::F32]);
2607 Ok(Instruction::F32Sqrt)
2608 }
2609
f32_add(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2610 fn f32_add(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2611 builder.pop_operands(&[ValType::F32, ValType::F32]);
2612 builder.push_operands(&[ValType::F32]);
2613 Ok(Instruction::F32Add)
2614 }
2615
f32_sub(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2616 fn f32_sub(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2617 builder.pop_operands(&[ValType::F32, ValType::F32]);
2618 builder.push_operands(&[ValType::F32]);
2619 Ok(Instruction::F32Sub)
2620 }
2621
f32_mul(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2622 fn f32_mul(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2623 builder.pop_operands(&[ValType::F32, ValType::F32]);
2624 builder.push_operands(&[ValType::F32]);
2625 Ok(Instruction::F32Mul)
2626 }
2627
f32_div(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2628 fn f32_div(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2629 builder.pop_operands(&[ValType::F32, ValType::F32]);
2630 builder.push_operands(&[ValType::F32]);
2631 Ok(Instruction::F32Div)
2632 }
2633
f32_min(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2634 fn f32_min(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2635 builder.pop_operands(&[ValType::F32, ValType::F32]);
2636 builder.push_operands(&[ValType::F32]);
2637 Ok(Instruction::F32Min)
2638 }
2639
f32_max(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2640 fn f32_max(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2641 builder.pop_operands(&[ValType::F32, ValType::F32]);
2642 builder.push_operands(&[ValType::F32]);
2643 Ok(Instruction::F32Max)
2644 }
2645
f32_copysign( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2646 fn f32_copysign(
2647 _: &mut Unstructured,
2648 _: &Module,
2649 builder: &mut CodeBuilder,
2650 ) -> Result<Instruction> {
2651 builder.pop_operands(&[ValType::F32, ValType::F32]);
2652 builder.push_operands(&[ValType::F32]);
2653 Ok(Instruction::F32Copysign)
2654 }
2655
2656 #[inline]
f64_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool2657 fn f64_on_stack(_: &Module, builder: &mut CodeBuilder) -> bool {
2658 builder.types_on_stack(&[ValType::F64])
2659 }
2660
f64_abs(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2661 fn f64_abs(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2662 builder.pop_operands(&[ValType::F64]);
2663 builder.push_operands(&[ValType::F64]);
2664 Ok(Instruction::F64Abs)
2665 }
2666
f64_neg(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2667 fn f64_neg(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2668 builder.pop_operands(&[ValType::F64]);
2669 builder.push_operands(&[ValType::F64]);
2670 Ok(Instruction::F64Neg)
2671 }
2672
f64_ceil(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2673 fn f64_ceil(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2674 builder.pop_operands(&[ValType::F64]);
2675 builder.push_operands(&[ValType::F64]);
2676 Ok(Instruction::F64Ceil)
2677 }
2678
f64_floor(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2679 fn f64_floor(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2680 builder.pop_operands(&[ValType::F64]);
2681 builder.push_operands(&[ValType::F64]);
2682 Ok(Instruction::F64Floor)
2683 }
2684
f64_trunc(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2685 fn f64_trunc(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2686 builder.pop_operands(&[ValType::F64]);
2687 builder.push_operands(&[ValType::F64]);
2688 Ok(Instruction::F64Trunc)
2689 }
2690
f64_nearest(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2691 fn f64_nearest(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2692 builder.pop_operands(&[ValType::F64]);
2693 builder.push_operands(&[ValType::F64]);
2694 Ok(Instruction::F64Nearest)
2695 }
2696
f64_sqrt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2697 fn f64_sqrt(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2698 builder.pop_operands(&[ValType::F64]);
2699 builder.push_operands(&[ValType::F64]);
2700 Ok(Instruction::F64Sqrt)
2701 }
2702
f64_add(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2703 fn f64_add(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2704 builder.pop_operands(&[ValType::F64, ValType::F64]);
2705 builder.push_operands(&[ValType::F64]);
2706 Ok(Instruction::F64Add)
2707 }
2708
f64_sub(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2709 fn f64_sub(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2710 builder.pop_operands(&[ValType::F64, ValType::F64]);
2711 builder.push_operands(&[ValType::F64]);
2712 Ok(Instruction::F64Sub)
2713 }
2714
f64_mul(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2715 fn f64_mul(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2716 builder.pop_operands(&[ValType::F64, ValType::F64]);
2717 builder.push_operands(&[ValType::F64]);
2718 Ok(Instruction::F64Mul)
2719 }
2720
f64_div(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2721 fn f64_div(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2722 builder.pop_operands(&[ValType::F64, ValType::F64]);
2723 builder.push_operands(&[ValType::F64]);
2724 Ok(Instruction::F64Div)
2725 }
2726
f64_min(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2727 fn f64_min(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2728 builder.pop_operands(&[ValType::F64, ValType::F64]);
2729 builder.push_operands(&[ValType::F64]);
2730 Ok(Instruction::F64Min)
2731 }
2732
f64_max(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>2733 fn f64_max(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
2734 builder.pop_operands(&[ValType::F64, ValType::F64]);
2735 builder.push_operands(&[ValType::F64]);
2736 Ok(Instruction::F64Max)
2737 }
2738
f64_copysign( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2739 fn f64_copysign(
2740 _: &mut Unstructured,
2741 _: &Module,
2742 builder: &mut CodeBuilder,
2743 ) -> Result<Instruction> {
2744 builder.pop_operands(&[ValType::F64, ValType::F64]);
2745 builder.push_operands(&[ValType::F64]);
2746 Ok(Instruction::F64Copysign)
2747 }
2748
i32_wrap_i64( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2749 fn i32_wrap_i64(
2750 _: &mut Unstructured,
2751 _: &Module,
2752 builder: &mut CodeBuilder,
2753 ) -> Result<Instruction> {
2754 builder.pop_operands(&[ValType::I64]);
2755 builder.push_operands(&[ValType::I32]);
2756 Ok(Instruction::I32WrapI64)
2757 }
2758
i32_trunc_f32_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2759 fn i32_trunc_f32_s(
2760 _: &mut Unstructured,
2761 _: &Module,
2762 builder: &mut CodeBuilder,
2763 ) -> Result<Instruction> {
2764 builder.pop_operands(&[ValType::F32]);
2765 builder.push_operands(&[ValType::I32]);
2766 Ok(Instruction::I32TruncF32S)
2767 }
2768
i32_trunc_f32_u( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2769 fn i32_trunc_f32_u(
2770 _: &mut Unstructured,
2771 _: &Module,
2772 builder: &mut CodeBuilder,
2773 ) -> Result<Instruction> {
2774 builder.pop_operands(&[ValType::F32]);
2775 builder.push_operands(&[ValType::I32]);
2776 Ok(Instruction::I32TruncF32U)
2777 }
2778
i32_trunc_f64_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2779 fn i32_trunc_f64_s(
2780 _: &mut Unstructured,
2781 _: &Module,
2782 builder: &mut CodeBuilder,
2783 ) -> Result<Instruction> {
2784 builder.pop_operands(&[ValType::F64]);
2785 builder.push_operands(&[ValType::I32]);
2786 Ok(Instruction::I32TruncF64S)
2787 }
2788
i32_trunc_f64_u( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2789 fn i32_trunc_f64_u(
2790 _: &mut Unstructured,
2791 _: &Module,
2792 builder: &mut CodeBuilder,
2793 ) -> Result<Instruction> {
2794 builder.pop_operands(&[ValType::F64]);
2795 builder.push_operands(&[ValType::I32]);
2796 Ok(Instruction::I32TruncF64U)
2797 }
2798
i64_extend_i32_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2799 fn i64_extend_i32_s(
2800 _: &mut Unstructured,
2801 _: &Module,
2802 builder: &mut CodeBuilder,
2803 ) -> Result<Instruction> {
2804 builder.pop_operands(&[ValType::I32]);
2805 builder.push_operands(&[ValType::I64]);
2806 Ok(Instruction::I64ExtendI32S)
2807 }
2808
i64_extend_i32_u( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2809 fn i64_extend_i32_u(
2810 _: &mut Unstructured,
2811 _: &Module,
2812 builder: &mut CodeBuilder,
2813 ) -> Result<Instruction> {
2814 builder.pop_operands(&[ValType::I32]);
2815 builder.push_operands(&[ValType::I64]);
2816 Ok(Instruction::I64ExtendI32U)
2817 }
2818
i64_trunc_f32_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2819 fn i64_trunc_f32_s(
2820 _: &mut Unstructured,
2821 _: &Module,
2822 builder: &mut CodeBuilder,
2823 ) -> Result<Instruction> {
2824 builder.pop_operands(&[ValType::F32]);
2825 builder.push_operands(&[ValType::I64]);
2826 Ok(Instruction::I64TruncF32S)
2827 }
2828
i64_trunc_f32_u( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2829 fn i64_trunc_f32_u(
2830 _: &mut Unstructured,
2831 _: &Module,
2832 builder: &mut CodeBuilder,
2833 ) -> Result<Instruction> {
2834 builder.pop_operands(&[ValType::F32]);
2835 builder.push_operands(&[ValType::I64]);
2836 Ok(Instruction::I64TruncF32U)
2837 }
2838
i64_trunc_f64_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2839 fn i64_trunc_f64_s(
2840 _: &mut Unstructured,
2841 _: &Module,
2842 builder: &mut CodeBuilder,
2843 ) -> Result<Instruction> {
2844 builder.pop_operands(&[ValType::F64]);
2845 builder.push_operands(&[ValType::I64]);
2846 Ok(Instruction::I64TruncF64S)
2847 }
2848
i64_trunc_f64_u( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2849 fn i64_trunc_f64_u(
2850 _: &mut Unstructured,
2851 _: &Module,
2852 builder: &mut CodeBuilder,
2853 ) -> Result<Instruction> {
2854 builder.pop_operands(&[ValType::F64]);
2855 builder.push_operands(&[ValType::I64]);
2856 Ok(Instruction::I64TruncF64U)
2857 }
2858
f32_convert_i32_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2859 fn f32_convert_i32_s(
2860 _: &mut Unstructured,
2861 _: &Module,
2862 builder: &mut CodeBuilder,
2863 ) -> Result<Instruction> {
2864 builder.pop_operands(&[ValType::I32]);
2865 builder.push_operands(&[ValType::F32]);
2866 Ok(Instruction::F32ConvertI32S)
2867 }
2868
f32_convert_i32_u( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2869 fn f32_convert_i32_u(
2870 _: &mut Unstructured,
2871 _: &Module,
2872 builder: &mut CodeBuilder,
2873 ) -> Result<Instruction> {
2874 builder.pop_operands(&[ValType::I32]);
2875 builder.push_operands(&[ValType::F32]);
2876 Ok(Instruction::F32ConvertI32U)
2877 }
2878
f32_convert_i64_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2879 fn f32_convert_i64_s(
2880 _: &mut Unstructured,
2881 _: &Module,
2882 builder: &mut CodeBuilder,
2883 ) -> Result<Instruction> {
2884 builder.pop_operands(&[ValType::I64]);
2885 builder.push_operands(&[ValType::F32]);
2886 Ok(Instruction::F32ConvertI64S)
2887 }
2888
f32_convert_i64_u( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2889 fn f32_convert_i64_u(
2890 _: &mut Unstructured,
2891 _: &Module,
2892 builder: &mut CodeBuilder,
2893 ) -> Result<Instruction> {
2894 builder.pop_operands(&[ValType::I64]);
2895 builder.push_operands(&[ValType::F32]);
2896 Ok(Instruction::F32ConvertI64U)
2897 }
2898
f32_demote_f64( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2899 fn f32_demote_f64(
2900 _: &mut Unstructured,
2901 _: &Module,
2902 builder: &mut CodeBuilder,
2903 ) -> Result<Instruction> {
2904 builder.pop_operands(&[ValType::F64]);
2905 builder.push_operands(&[ValType::F32]);
2906 Ok(Instruction::F32DemoteF64)
2907 }
2908
f64_convert_i32_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2909 fn f64_convert_i32_s(
2910 _: &mut Unstructured,
2911 _: &Module,
2912 builder: &mut CodeBuilder,
2913 ) -> Result<Instruction> {
2914 builder.pop_operands(&[ValType::I32]);
2915 builder.push_operands(&[ValType::F64]);
2916 Ok(Instruction::F64ConvertI32S)
2917 }
2918
f64_convert_i32_u( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2919 fn f64_convert_i32_u(
2920 _: &mut Unstructured,
2921 _: &Module,
2922 builder: &mut CodeBuilder,
2923 ) -> Result<Instruction> {
2924 builder.pop_operands(&[ValType::I32]);
2925 builder.push_operands(&[ValType::F64]);
2926 Ok(Instruction::F64ConvertI32U)
2927 }
2928
f64_convert_i64_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2929 fn f64_convert_i64_s(
2930 _: &mut Unstructured,
2931 _: &Module,
2932 builder: &mut CodeBuilder,
2933 ) -> Result<Instruction> {
2934 builder.pop_operands(&[ValType::I64]);
2935 builder.push_operands(&[ValType::F64]);
2936 Ok(Instruction::F64ConvertI64S)
2937 }
2938
f64_convert_i64_u( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2939 fn f64_convert_i64_u(
2940 _: &mut Unstructured,
2941 _: &Module,
2942 builder: &mut CodeBuilder,
2943 ) -> Result<Instruction> {
2944 builder.pop_operands(&[ValType::I64]);
2945 builder.push_operands(&[ValType::F64]);
2946 Ok(Instruction::F64ConvertI64U)
2947 }
2948
f64_promote_f32( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2949 fn f64_promote_f32(
2950 _: &mut Unstructured,
2951 _: &Module,
2952 builder: &mut CodeBuilder,
2953 ) -> Result<Instruction> {
2954 builder.pop_operands(&[ValType::F32]);
2955 builder.push_operands(&[ValType::F64]);
2956 Ok(Instruction::F64PromoteF32)
2957 }
2958
i32_reinterpret_f32( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2959 fn i32_reinterpret_f32(
2960 _: &mut Unstructured,
2961 _: &Module,
2962 builder: &mut CodeBuilder,
2963 ) -> Result<Instruction> {
2964 builder.pop_operands(&[ValType::F32]);
2965 builder.push_operands(&[ValType::I32]);
2966 Ok(Instruction::I32ReinterpretF32)
2967 }
2968
i64_reinterpret_f64( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2969 fn i64_reinterpret_f64(
2970 _: &mut Unstructured,
2971 _: &Module,
2972 builder: &mut CodeBuilder,
2973 ) -> Result<Instruction> {
2974 builder.pop_operands(&[ValType::F64]);
2975 builder.push_operands(&[ValType::I64]);
2976 Ok(Instruction::I64ReinterpretF64)
2977 }
2978
f32_reinterpret_i32( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2979 fn f32_reinterpret_i32(
2980 _: &mut Unstructured,
2981 _: &Module,
2982 builder: &mut CodeBuilder,
2983 ) -> Result<Instruction> {
2984 builder.pop_operands(&[ValType::I32]);
2985 builder.push_operands(&[ValType::F32]);
2986 Ok(Instruction::F32ReinterpretI32)
2987 }
2988
f64_reinterpret_i64( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2989 fn f64_reinterpret_i64(
2990 _: &mut Unstructured,
2991 _: &Module,
2992 builder: &mut CodeBuilder,
2993 ) -> Result<Instruction> {
2994 builder.pop_operands(&[ValType::I64]);
2995 builder.push_operands(&[ValType::F64]);
2996 Ok(Instruction::F64ReinterpretI64)
2997 }
2998
i32_extend_8_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>2999 fn i32_extend_8_s(
3000 _: &mut Unstructured,
3001 _: &Module,
3002 builder: &mut CodeBuilder,
3003 ) -> Result<Instruction> {
3004 builder.pop_operands(&[ValType::I32]);
3005 builder.push_operands(&[ValType::I32]);
3006 Ok(Instruction::I32Extend8S)
3007 }
3008
i32_extend_16_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3009 fn i32_extend_16_s(
3010 _: &mut Unstructured,
3011 _: &Module,
3012 builder: &mut CodeBuilder,
3013 ) -> Result<Instruction> {
3014 builder.pop_operands(&[ValType::I32]);
3015 builder.push_operands(&[ValType::I32]);
3016 Ok(Instruction::I32Extend16S)
3017 }
3018
i64_extend_8_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3019 fn i64_extend_8_s(
3020 _: &mut Unstructured,
3021 _: &Module,
3022 builder: &mut CodeBuilder,
3023 ) -> Result<Instruction> {
3024 builder.pop_operands(&[ValType::I64]);
3025 builder.push_operands(&[ValType::I64]);
3026 Ok(Instruction::I64Extend8S)
3027 }
3028
i64_extend_16_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3029 fn i64_extend_16_s(
3030 _: &mut Unstructured,
3031 _: &Module,
3032 builder: &mut CodeBuilder,
3033 ) -> Result<Instruction> {
3034 builder.pop_operands(&[ValType::I64]);
3035 builder.push_operands(&[ValType::I64]);
3036 Ok(Instruction::I64Extend16S)
3037 }
3038
i64_extend_32_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3039 fn i64_extend_32_s(
3040 _: &mut Unstructured,
3041 _: &Module,
3042 builder: &mut CodeBuilder,
3043 ) -> Result<Instruction> {
3044 builder.pop_operands(&[ValType::I64]);
3045 builder.push_operands(&[ValType::I64]);
3046 Ok(Instruction::I64Extend32S)
3047 }
3048
i32_trunc_sat_f32_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3049 fn i32_trunc_sat_f32_s(
3050 _: &mut Unstructured,
3051 _: &Module,
3052 builder: &mut CodeBuilder,
3053 ) -> Result<Instruction> {
3054 builder.pop_operands(&[ValType::F32]);
3055 builder.push_operands(&[ValType::I32]);
3056 Ok(Instruction::I32TruncSatF32S)
3057 }
3058
i32_trunc_sat_f32_u( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3059 fn i32_trunc_sat_f32_u(
3060 _: &mut Unstructured,
3061 _: &Module,
3062 builder: &mut CodeBuilder,
3063 ) -> Result<Instruction> {
3064 builder.pop_operands(&[ValType::F32]);
3065 builder.push_operands(&[ValType::I32]);
3066 Ok(Instruction::I32TruncSatF32U)
3067 }
3068
i32_trunc_sat_f64_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3069 fn i32_trunc_sat_f64_s(
3070 _: &mut Unstructured,
3071 _: &Module,
3072 builder: &mut CodeBuilder,
3073 ) -> Result<Instruction> {
3074 builder.pop_operands(&[ValType::F64]);
3075 builder.push_operands(&[ValType::I32]);
3076 Ok(Instruction::I32TruncSatF64S)
3077 }
3078
i32_trunc_sat_f64_u( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3079 fn i32_trunc_sat_f64_u(
3080 _: &mut Unstructured,
3081 _: &Module,
3082 builder: &mut CodeBuilder,
3083 ) -> Result<Instruction> {
3084 builder.pop_operands(&[ValType::F64]);
3085 builder.push_operands(&[ValType::I32]);
3086 Ok(Instruction::I32TruncSatF64U)
3087 }
3088
i64_trunc_sat_f32_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3089 fn i64_trunc_sat_f32_s(
3090 _: &mut Unstructured,
3091 _: &Module,
3092 builder: &mut CodeBuilder,
3093 ) -> Result<Instruction> {
3094 builder.pop_operands(&[ValType::F32]);
3095 builder.push_operands(&[ValType::I64]);
3096 Ok(Instruction::I64TruncSatF32S)
3097 }
3098
i64_trunc_sat_f32_u( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3099 fn i64_trunc_sat_f32_u(
3100 _: &mut Unstructured,
3101 _: &Module,
3102 builder: &mut CodeBuilder,
3103 ) -> Result<Instruction> {
3104 builder.pop_operands(&[ValType::F32]);
3105 builder.push_operands(&[ValType::I64]);
3106 Ok(Instruction::I64TruncSatF32U)
3107 }
3108
i64_trunc_sat_f64_s( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3109 fn i64_trunc_sat_f64_s(
3110 _: &mut Unstructured,
3111 _: &Module,
3112 builder: &mut CodeBuilder,
3113 ) -> Result<Instruction> {
3114 builder.pop_operands(&[ValType::F64]);
3115 builder.push_operands(&[ValType::I64]);
3116 Ok(Instruction::I64TruncSatF64S)
3117 }
3118
i64_trunc_sat_f64_u( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3119 fn i64_trunc_sat_f64_u(
3120 _: &mut Unstructured,
3121 _: &Module,
3122 builder: &mut CodeBuilder,
3123 ) -> Result<Instruction> {
3124 builder.pop_operands(&[ValType::F64]);
3125 builder.push_operands(&[ValType::I64]);
3126 Ok(Instruction::I64TruncSatF64U)
3127 }
3128
memory_offset(u: &mut Unstructured, module: &Module, memory_index: u32) -> Result<u64>3129 fn memory_offset(u: &mut Unstructured, module: &Module, memory_index: u32) -> Result<u64> {
3130 let (a, b, c) = module.config.memory_offset_choices();
3131 assert!(a + b + c != 0);
3132
3133 let memory_type = &module.memories[memory_index as usize];
3134 let min = memory_type.minimum.saturating_mul(65536);
3135 let max = memory_type
3136 .maximum
3137 .map(|max| max.saturating_mul(65536))
3138 .unwrap_or(u64::MAX);
3139 let (min, max, true_max) = if memory_type.memory64 {
3140 // 64-bit memories can use the limits calculated above as-is
3141 (min, max, u64::MAX)
3142 } else {
3143 // 32-bit memories can't represent a full 4gb offset, so if that's the
3144 // min/max sizes then we need to switch the m to `u32::MAX`.
3145 (
3146 u64::from(u32::try_from(min).unwrap_or(u32::MAX)),
3147 u64::from(u32::try_from(max).unwrap_or(u32::MAX)),
3148 u64::from(u32::MAX),
3149 )
3150 };
3151
3152 let choice = u.int_in_range(0..=a + b + c - 1)?;
3153 if choice < a {
3154 u.int_in_range(0..=min)
3155 } else if choice < a + b {
3156 u.int_in_range(min..=max)
3157 } else {
3158 u.int_in_range(max..=true_max)
3159 }
3160 }
3161
mem_arg( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, alignments: &[u32], ) -> Result<MemArg>3162 fn mem_arg(
3163 u: &mut Unstructured,
3164 module: &Module,
3165 builder: &mut CodeBuilder,
3166 alignments: &[u32],
3167 ) -> Result<MemArg> {
3168 let memory_index = if builder.type_on_stack(ValType::I32) {
3169 builder.pop_operands(&[ValType::I32]);
3170 memory_index(u, builder, ValType::I32)?
3171 } else {
3172 builder.pop_operands(&[ValType::I64]);
3173 memory_index(u, builder, ValType::I64)?
3174 };
3175 let offset = memory_offset(u, module, memory_index)?;
3176 let align = *u.choose(alignments)?;
3177 Ok(MemArg {
3178 memory_index,
3179 offset,
3180 align,
3181 })
3182 }
3183
memory_index(u: &mut Unstructured, builder: &CodeBuilder, ty: ValType) -> Result<u32>3184 fn memory_index(u: &mut Unstructured, builder: &CodeBuilder, ty: ValType) -> Result<u32> {
3185 if ty == ValType::I32 {
3186 Ok(*u.choose(&builder.allocs.memory32)?)
3187 } else {
3188 Ok(*u.choose(&builder.allocs.memory64)?)
3189 }
3190 }
3191
data_index(u: &mut Unstructured, module: &Module) -> Result<u32>3192 fn data_index(u: &mut Unstructured, module: &Module) -> Result<u32> {
3193 let data = module.data.len() as u32;
3194 assert!(data > 0);
3195 if data == 1 {
3196 Ok(0)
3197 } else {
3198 u.int_in_range(0..=data - 1)
3199 }
3200 }
3201
3202 #[inline]
ref_null_valid(module: &Module, _: &mut CodeBuilder) -> bool3203 fn ref_null_valid(module: &Module, _: &mut CodeBuilder) -> bool {
3204 module.config.reference_types_enabled()
3205 }
3206
ref_null(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>3207 fn ref_null(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
3208 let ty = *u.choose(&[ValType::ExternRef, ValType::FuncRef])?;
3209 builder.push_operands(&[ty]);
3210 Ok(Instruction::RefNull(ty))
3211 }
3212
3213 #[inline]
ref_func_valid(module: &Module, builder: &mut CodeBuilder) -> bool3214 fn ref_func_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
3215 module.config.reference_types_enabled() && builder.allocs.referenced_functions.len() > 0
3216 }
3217
ref_func(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>3218 fn ref_func(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
3219 let i = *u.choose(&builder.allocs.referenced_functions)?;
3220 builder.push_operands(&[ValType::FuncRef]);
3221 Ok(Instruction::RefFunc(i))
3222 }
3223
3224 #[inline]
ref_is_null_valid(module: &Module, builder: &mut CodeBuilder) -> bool3225 fn ref_is_null_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
3226 module.config.reference_types_enabled()
3227 && (builder.type_on_stack(ValType::ExternRef) || builder.type_on_stack(ValType::FuncRef))
3228 }
3229
ref_is_null(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>3230 fn ref_is_null(_: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
3231 pop_reference_type(builder);
3232 builder.push_operands(&[ValType::I32]);
3233 Ok(Instruction::RefIsNull)
3234 }
3235
3236 #[inline]
table_fill_valid(module: &Module, builder: &mut CodeBuilder) -> bool3237 fn table_fill_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
3238 module.config.reference_types_enabled()
3239 && module.config.bulk_memory_enabled()
3240 && [ValType::ExternRef, ValType::FuncRef].iter().any(|ty| {
3241 builder.types_on_stack(&[ValType::I32, *ty, ValType::I32])
3242 && module.tables.iter().any(|t| t.elem_ty == *ty)
3243 })
3244 }
3245
table_fill( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3246 fn table_fill(
3247 u: &mut Unstructured,
3248 module: &Module,
3249 builder: &mut CodeBuilder,
3250 ) -> Result<Instruction> {
3251 builder.pop_operands(&[ValType::I32]);
3252 let ty = pop_reference_type(builder);
3253 builder.pop_operands(&[ValType::I32]);
3254 let table = table_index(ty, u, module)?;
3255 Ok(Instruction::TableFill { table })
3256 }
3257
3258 #[inline]
table_set_valid(module: &Module, builder: &mut CodeBuilder) -> bool3259 fn table_set_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
3260 module.config.reference_types_enabled()
3261 && [ValType::ExternRef, ValType::FuncRef].iter().any(|ty| {
3262 builder.types_on_stack(&[ValType::I32, *ty])
3263 && module.tables.iter().any(|t| t.elem_ty == *ty)
3264 })
3265 }
3266
table_set( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3267 fn table_set(
3268 u: &mut Unstructured,
3269 module: &Module,
3270 builder: &mut CodeBuilder,
3271 ) -> Result<Instruction> {
3272 let ty = pop_reference_type(builder);
3273 builder.pop_operands(&[ValType::I32]);
3274 let table = table_index(ty, u, module)?;
3275 Ok(Instruction::TableSet { table })
3276 }
3277
3278 #[inline]
table_get_valid(module: &Module, builder: &mut CodeBuilder) -> bool3279 fn table_get_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
3280 module.config.reference_types_enabled()
3281 && builder.type_on_stack(ValType::I32)
3282 && module.tables.len() > 0
3283 }
3284
table_get( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3285 fn table_get(
3286 u: &mut Unstructured,
3287 module: &Module,
3288 builder: &mut CodeBuilder,
3289 ) -> Result<Instruction> {
3290 builder.pop_operands(&[ValType::I32]);
3291 let idx = u.int_in_range(0..=module.tables.len() - 1)?;
3292 let ty = module.tables[idx].elem_ty;
3293 builder.push_operands(&[ty]);
3294 Ok(Instruction::TableGet { table: idx as u32 })
3295 }
3296
3297 #[inline]
table_size_valid(module: &Module, _: &mut CodeBuilder) -> bool3298 fn table_size_valid(module: &Module, _: &mut CodeBuilder) -> bool {
3299 module.config.reference_types_enabled() && module.tables.len() > 0
3300 }
3301
table_size( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3302 fn table_size(
3303 u: &mut Unstructured,
3304 module: &Module,
3305 builder: &mut CodeBuilder,
3306 ) -> Result<Instruction> {
3307 let table = u.int_in_range(0..=module.tables.len() - 1)? as u32;
3308 builder.push_operands(&[ValType::I32]);
3309 Ok(Instruction::TableSize { table })
3310 }
3311
3312 #[inline]
table_grow_valid(module: &Module, builder: &mut CodeBuilder) -> bool3313 fn table_grow_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
3314 module.config.reference_types_enabled()
3315 && [ValType::ExternRef, ValType::FuncRef].iter().any(|ty| {
3316 builder.types_on_stack(&[*ty, ValType::I32])
3317 && module.tables.iter().any(|t| t.elem_ty == *ty)
3318 })
3319 }
3320
table_grow( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3321 fn table_grow(
3322 u: &mut Unstructured,
3323 module: &Module,
3324 builder: &mut CodeBuilder,
3325 ) -> Result<Instruction> {
3326 builder.pop_operands(&[ValType::I32]);
3327 let ty = pop_reference_type(builder);
3328 let table = table_index(ty, u, module)?;
3329 builder.push_operands(&[ValType::I32]);
3330 Ok(Instruction::TableGrow { table })
3331 }
3332
3333 #[inline]
table_copy_valid(module: &Module, builder: &mut CodeBuilder) -> bool3334 fn table_copy_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
3335 module.config.reference_types_enabled()
3336 && module.tables.len() > 0
3337 && builder.types_on_stack(&[ValType::I32, ValType::I32, ValType::I32])
3338 }
3339
table_copy( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3340 fn table_copy(
3341 u: &mut Unstructured,
3342 module: &Module,
3343 builder: &mut CodeBuilder,
3344 ) -> Result<Instruction> {
3345 builder.pop_operands(&[ValType::I32, ValType::I32, ValType::I32]);
3346 let src = u.int_in_range(0..=module.tables.len() - 1)? as u32;
3347 let dst = table_index(module.tables[src as usize].elem_ty, u, module)?;
3348 Ok(Instruction::TableCopy { src, dst })
3349 }
3350
3351 #[inline]
table_init_valid(module: &Module, builder: &mut CodeBuilder) -> bool3352 fn table_init_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
3353 module.config.reference_types_enabled()
3354 && builder.allocs.table_init_possible
3355 && builder.types_on_stack(&[ValType::I32, ValType::I32, ValType::I32])
3356 }
3357
table_init( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3358 fn table_init(
3359 u: &mut Unstructured,
3360 module: &Module,
3361 builder: &mut CodeBuilder,
3362 ) -> Result<Instruction> {
3363 builder.pop_operands(&[ValType::I32, ValType::I32, ValType::I32]);
3364 let segments = module
3365 .elems
3366 .iter()
3367 .enumerate()
3368 .filter(|(_, e)| module.tables.iter().any(|t| t.elem_ty == e.ty))
3369 .map(|(i, _)| i)
3370 .collect::<Vec<_>>();
3371 let segment = *u.choose(&segments)?;
3372 let table = table_index(module.elems[segment].ty, u, module)?;
3373 Ok(Instruction::TableInit {
3374 segment: segment as u32,
3375 table,
3376 })
3377 }
3378
3379 #[inline]
elem_drop_valid(module: &Module, _builder: &mut CodeBuilder) -> bool3380 fn elem_drop_valid(module: &Module, _builder: &mut CodeBuilder) -> bool {
3381 module.config.reference_types_enabled() && module.elems.len() > 0
3382 }
3383
elem_drop( u: &mut Unstructured, module: &Module, _builder: &mut CodeBuilder, ) -> Result<Instruction>3384 fn elem_drop(
3385 u: &mut Unstructured,
3386 module: &Module,
3387 _builder: &mut CodeBuilder,
3388 ) -> Result<Instruction> {
3389 let segment = u.int_in_range(0..=module.elems.len() - 1)? as u32;
3390 Ok(Instruction::ElemDrop { segment })
3391 }
3392
pop_reference_type(builder: &mut CodeBuilder) -> ValType3393 fn pop_reference_type(builder: &mut CodeBuilder) -> ValType {
3394 if builder.type_on_stack(ValType::ExternRef) {
3395 builder.pop_operands(&[ValType::ExternRef]);
3396 ValType::ExternRef
3397 } else {
3398 builder.pop_operands(&[ValType::FuncRef]);
3399 ValType::FuncRef
3400 }
3401 }
3402
table_index(ty: ValType, u: &mut Unstructured, module: &Module) -> Result<u32>3403 fn table_index(ty: ValType, u: &mut Unstructured, module: &Module) -> Result<u32> {
3404 let tables = module
3405 .tables
3406 .iter()
3407 .enumerate()
3408 .filter(|(_, t)| t.elem_ty == ty)
3409 .map(|t| t.0 as u32)
3410 .collect::<Vec<_>>();
3411 Ok(*u.choose(&tables)?)
3412 }
3413
lane_index(u: &mut Unstructured, number_of_lanes: u8) -> Result<u8>3414 fn lane_index(u: &mut Unstructured, number_of_lanes: u8) -> Result<u8> {
3415 u.int_in_range(0..=(number_of_lanes - 1))
3416 }
3417
3418 #[inline]
simd_v128_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool3419 fn simd_v128_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool {
3420 module.config.simd_enabled() && builder.types_on_stack(&[ValType::V128])
3421 }
3422
3423 #[inline]
simd_v128_v128_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool3424 fn simd_v128_v128_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool {
3425 module.config.simd_enabled() && builder.types_on_stack(&[ValType::V128, ValType::V128])
3426 }
3427
3428 #[inline]
simd_v128_v128_v128_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool3429 fn simd_v128_v128_v128_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool {
3430 module.config.simd_enabled()
3431 && builder.types_on_stack(&[ValType::V128, ValType::V128, ValType::V128])
3432 }
3433
3434 #[inline]
simd_v128_i32_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool3435 fn simd_v128_i32_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool {
3436 module.config.simd_enabled() && builder.types_on_stack(&[ValType::V128, ValType::I32])
3437 }
3438
3439 #[inline]
simd_v128_i64_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool3440 fn simd_v128_i64_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool {
3441 module.config.simd_enabled() && builder.types_on_stack(&[ValType::V128, ValType::I64])
3442 }
3443
3444 #[inline]
simd_v128_f32_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool3445 fn simd_v128_f32_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool {
3446 module.config.simd_enabled() && builder.types_on_stack(&[ValType::V128, ValType::F32])
3447 }
3448
3449 #[inline]
simd_v128_f64_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool3450 fn simd_v128_f64_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool {
3451 module.config.simd_enabled() && builder.types_on_stack(&[ValType::V128, ValType::F64])
3452 }
3453
3454 #[inline]
simd_i32_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool3455 fn simd_i32_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool {
3456 module.config.simd_enabled() && builder.type_on_stack(ValType::I32)
3457 }
3458
3459 #[inline]
simd_i64_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool3460 fn simd_i64_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool {
3461 module.config.simd_enabled() && builder.type_on_stack(ValType::I64)
3462 }
3463
3464 #[inline]
simd_f32_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool3465 fn simd_f32_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool {
3466 module.config.simd_enabled() && builder.type_on_stack(ValType::F32)
3467 }
3468
3469 #[inline]
simd_f64_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool3470 fn simd_f64_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool {
3471 module.config.simd_enabled() && builder.type_on_stack(ValType::F64)
3472 }
3473
3474 #[inline]
simd_have_memory_and_offset(module: &Module, builder: &mut CodeBuilder) -> bool3475 fn simd_have_memory_and_offset(module: &Module, builder: &mut CodeBuilder) -> bool {
3476 module.config.simd_enabled() && have_memory_and_offset(module, builder)
3477 }
3478
3479 #[inline]
simd_have_memory_and_offset_and_v128(module: &Module, builder: &mut CodeBuilder) -> bool3480 fn simd_have_memory_and_offset_and_v128(module: &Module, builder: &mut CodeBuilder) -> bool {
3481 module.config.simd_enabled() && store_valid(module, builder, || ValType::V128)
3482 }
3483
3484 #[inline]
simd_v128_store_valid(module: &Module, builder: &mut CodeBuilder) -> bool3485 fn simd_v128_store_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
3486 module.config.simd_enabled() && store_valid(module, builder, || ValType::V128)
3487 }
3488
3489 #[inline]
simd_enabled(module: &Module, _: &mut CodeBuilder) -> bool3490 fn simd_enabled(module: &Module, _: &mut CodeBuilder) -> bool {
3491 module.config.simd_enabled()
3492 }
3493
3494 macro_rules! simd_load {
3495 ($instruction:ident, $generator_fn_name:ident, $alignments:expr) => {
3496 fn $generator_fn_name(
3497 u: &mut Unstructured,
3498 module: &Module,
3499 builder: &mut CodeBuilder,
3500 ) -> Result<Instruction> {
3501 let memarg = mem_arg(u, module, builder, $alignments)?;
3502 builder.push_operands(&[ValType::V128]);
3503 Ok(Instruction::$instruction { memarg })
3504 }
3505 };
3506 }
3507
3508 simd_load!(V128Load, v128_load, &[0, 1, 2, 3, 4]);
3509 simd_load!(V128Load8x8S, v128_load8x8s, &[0, 1, 2, 3]);
3510 simd_load!(V128Load8x8U, v128_load8x8u, &[0, 1, 2, 3]);
3511 simd_load!(V128Load16x4S, v128_load16x4s, &[0, 1, 2, 3]);
3512 simd_load!(V128Load16x4U, v128_load16x4u, &[0, 1, 2, 3]);
3513 simd_load!(V128Load32x2S, v128_load32x2s, &[0, 1, 2, 3]);
3514 simd_load!(V128Load32x2U, v128_load32x2u, &[0, 1, 2, 3]);
3515 simd_load!(V128Load8Splat, v128_load8_splat, &[0]);
3516 simd_load!(V128Load16Splat, v128_load16_splat, &[0, 1]);
3517 simd_load!(V128Load32Splat, v128_load32_splat, &[0, 1, 2]);
3518 simd_load!(V128Load64Splat, v128_load64_splat, &[0, 1, 2, 3]);
3519 simd_load!(V128Load32Zero, v128_load32_zero, &[0, 1, 2]);
3520 simd_load!(V128Load64Zero, v128_load64_zero, &[0, 1, 2, 3]);
3521
v128_store( u: &mut Unstructured, module: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3522 fn v128_store(
3523 u: &mut Unstructured,
3524 module: &Module,
3525 builder: &mut CodeBuilder,
3526 ) -> Result<Instruction> {
3527 builder.pop_operands(&[ValType::V128]);
3528 let memarg = mem_arg(u, module, builder, &[0, 1, 2, 3, 4])?;
3529 Ok(Instruction::V128Store { memarg })
3530 }
3531
3532 macro_rules! simd_load_lane {
3533 ($instruction:ident, $generator_fn_name:ident, $alignments:expr, $number_of_lanes:expr) => {
3534 fn $generator_fn_name(
3535 u: &mut Unstructured,
3536 module: &Module,
3537 builder: &mut CodeBuilder,
3538 ) -> Result<Instruction> {
3539 builder.pop_operands(&[ValType::V128]);
3540 let memarg = mem_arg(u, module, builder, $alignments)?;
3541 builder.push_operands(&[ValType::V128]);
3542 Ok(Instruction::$instruction {
3543 memarg,
3544 lane: lane_index(u, $number_of_lanes)?,
3545 })
3546 }
3547 };
3548 }
3549
3550 simd_load_lane!(V128Load8Lane, v128_load8_lane, &[0], 16);
3551 simd_load_lane!(V128Load16Lane, v128_load16_lane, &[0, 1], 8);
3552 simd_load_lane!(V128Load32Lane, v128_load32_lane, &[0, 1, 2], 4);
3553 simd_load_lane!(V128Load64Lane, v128_load64_lane, &[0, 1, 2, 3], 2);
3554
3555 macro_rules! simd_store_lane {
3556 ($instruction:ident, $generator_fn_name:ident, $alignments:expr, $number_of_lanes:expr) => {
3557 fn $generator_fn_name(
3558 u: &mut Unstructured,
3559 module: &Module,
3560 builder: &mut CodeBuilder,
3561 ) -> Result<Instruction> {
3562 builder.pop_operands(&[ValType::V128]);
3563 let memarg = mem_arg(u, module, builder, $alignments)?;
3564 Ok(Instruction::$instruction {
3565 memarg,
3566 lane: lane_index(u, $number_of_lanes)?,
3567 })
3568 }
3569 };
3570 }
3571
3572 simd_store_lane!(V128Store8Lane, v128_store8_lane, &[0], 16);
3573 simd_store_lane!(V128Store16Lane, v128_store16_lane, &[0, 1], 8);
3574 simd_store_lane!(V128Store32Lane, v128_store32_lane, &[0, 1, 2], 4);
3575 simd_store_lane!(V128Store64Lane, v128_store64_lane, &[0, 1, 2, 3], 2);
3576
v128_const(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction>3577 fn v128_const(u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder) -> Result<Instruction> {
3578 builder.push_operands(&[ValType::V128]);
3579 let c = i128::from_le_bytes(u.arbitrary()?);
3580 Ok(Instruction::V128Const(c))
3581 }
3582
i8x16_shuffle( u: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3583 fn i8x16_shuffle(
3584 u: &mut Unstructured,
3585 _: &Module,
3586 builder: &mut CodeBuilder,
3587 ) -> Result<Instruction> {
3588 builder.pop_operands(&[ValType::V128, ValType::V128]);
3589 builder.push_operands(&[ValType::V128]);
3590 let mut lanes = [0; 16];
3591 for i in 0..16 {
3592 lanes[i] = u.int_in_range(0..=31)?;
3593 }
3594 Ok(Instruction::I8x16Shuffle { lanes: lanes })
3595 }
3596
3597 macro_rules! simd_lane_access {
3598 ($instruction:ident, $generator_fn_name:ident, $in_types:expr => $out_types:expr, $number_of_lanes:expr) => {
3599 fn $generator_fn_name(
3600 u: &mut Unstructured,
3601 _: &Module,
3602 builder: &mut CodeBuilder,
3603 ) -> Result<Instruction> {
3604 builder.pop_operands($in_types);
3605 builder.push_operands($out_types);
3606 Ok(Instruction::$instruction {
3607 lane: lane_index(u, $number_of_lanes)?,
3608 })
3609 }
3610 };
3611 }
3612
3613 simd_lane_access!(I8x16ExtractLaneS, i8x16_extract_lane_s, &[ValType::V128] => &[ValType::I32], 16);
3614 simd_lane_access!(I8x16ExtractLaneU, i8x16_extract_lane_u, &[ValType::V128] => &[ValType::I32], 16);
3615 simd_lane_access!(I8x16ReplaceLane, i8x16_replace_lane, &[ValType::V128, ValType::I32] => &[ValType::V128], 16);
3616 simd_lane_access!(I16x8ExtractLaneS, i16x8_extract_lane_s, &[ValType::V128] => &[ValType::I32], 8);
3617 simd_lane_access!(I16x8ExtractLaneU, i16x8_extract_lane_u, &[ValType::V128] => &[ValType::I32], 8);
3618 simd_lane_access!(I16x8ReplaceLane, i16x8_replace_lane, &[ValType::V128, ValType::I32] => &[ValType::V128], 8);
3619 simd_lane_access!(I32x4ExtractLane, i32x4_extract_lane, &[ValType::V128] => &[ValType::I32], 4);
3620 simd_lane_access!(I32x4ReplaceLane, i32x4_replace_lane, &[ValType::V128, ValType::I32] => &[ValType::V128], 4);
3621 simd_lane_access!(I64x2ExtractLane, i64x2_extract_lane, &[ValType::V128] => &[ValType::I64], 2);
3622 simd_lane_access!(I64x2ReplaceLane, i64x2_replace_lane, &[ValType::V128, ValType::I64] => &[ValType::V128], 2);
3623 simd_lane_access!(F32x4ExtractLane, f32x4_extract_lane, &[ValType::V128] => &[ValType::F32], 4);
3624 simd_lane_access!(F32x4ReplaceLane, f32x4_replace_lane, &[ValType::V128, ValType::F32] => &[ValType::V128], 4);
3625 simd_lane_access!(F64x2ExtractLane, f64x2_extract_lane, &[ValType::V128] => &[ValType::F64], 2);
3626 simd_lane_access!(F64x2ReplaceLane, f64x2_replace_lane, &[ValType::V128, ValType::F64] => &[ValType::V128], 2);
3627
3628 macro_rules! simd_binop {
3629 ($instruction:ident, $generator_fn_name:ident) => {
3630 fn $generator_fn_name(
3631 _: &mut Unstructured,
3632 _: &Module,
3633 builder: &mut CodeBuilder,
3634 ) -> Result<Instruction> {
3635 builder.pop_operands(&[ValType::V128, ValType::V128]);
3636 builder.push_operands(&[ValType::V128]);
3637 Ok(Instruction::$instruction)
3638 }
3639 };
3640 }
3641
3642 macro_rules! simd_unop {
3643 ($instruction:ident, $generator_fn_name:ident) => {
3644 simd_unop!($instruction, $generator_fn_name, V128 -> V128);
3645 };
3646
3647 ($instruction:ident, $generator_fn_name:ident, $in_type:ident -> $out_type:ident) => {
3648 fn $generator_fn_name(
3649 _: &mut Unstructured,
3650 _: &Module,
3651 builder: &mut CodeBuilder,
3652 ) -> Result<Instruction> {
3653 builder.pop_operands(&[ValType::$in_type]);
3654 builder.push_operands(&[ValType::$out_type]);
3655 Ok(Instruction::$instruction)
3656 }
3657 };
3658 }
3659
3660 macro_rules! simd_shift {
3661 ($instruction:ident, $generator_fn_name:ident) => {
3662 fn $generator_fn_name(
3663 _: &mut Unstructured,
3664 _: &Module,
3665 builder: &mut CodeBuilder,
3666 ) -> Result<Instruction> {
3667 builder.pop_operands(&[ValType::V128, ValType::I32]);
3668 builder.push_operands(&[ValType::V128]);
3669 Ok(Instruction::$instruction)
3670 }
3671 };
3672 }
3673
3674 simd_unop!(I8x16Splat, i8x16_splat, I32 -> V128);
3675 simd_unop!(I16x8Splat, i16x8_splat, I32 -> V128);
3676 simd_unop!(I32x4Splat, i32x4_splat, I32 -> V128);
3677 simd_unop!(I64x2Splat, i64x2_splat, I64 -> V128);
3678 simd_unop!(F32x4Splat, f32x4_splat, F32 -> V128);
3679 simd_unop!(F64x2Splat, f64x2_splat, F64 -> V128);
3680 simd_binop!(I8x16Swizzle, i8x16_swizzle);
3681 simd_binop!(I8x16Eq, i8x16_eq);
3682 simd_binop!(I8x16Ne, i8x16_ne);
3683 simd_binop!(I8x16LtS, i8x16_lt_s);
3684 simd_binop!(I8x16LtU, i8x16_lt_u);
3685 simd_binop!(I8x16GtS, i8x16_gt_s);
3686 simd_binop!(I8x16GtU, i8x16_gt_u);
3687 simd_binop!(I8x16LeS, i8x16_le_s);
3688 simd_binop!(I8x16LeU, i8x16_le_u);
3689 simd_binop!(I8x16GeS, i8x16_ge_s);
3690 simd_binop!(I8x16GeU, i8x16_ge_u);
3691 simd_binop!(I16x8Eq, i16x8_eq);
3692 simd_binop!(I16x8Ne, i16x8_ne);
3693 simd_binop!(I16x8LtS, i16x8_lt_s);
3694 simd_binop!(I16x8LtU, i16x8_lt_u);
3695 simd_binop!(I16x8GtS, i16x8_gt_s);
3696 simd_binop!(I16x8GtU, i16x8_gt_u);
3697 simd_binop!(I16x8LeS, i16x8_le_s);
3698 simd_binop!(I16x8LeU, i16x8_le_u);
3699 simd_binop!(I16x8GeS, i16x8_ge_s);
3700 simd_binop!(I16x8GeU, i16x8_ge_u);
3701 simd_binop!(I32x4Eq, i32x4_eq);
3702 simd_binop!(I32x4Ne, i32x4_ne);
3703 simd_binop!(I32x4LtS, i32x4_lt_s);
3704 simd_binop!(I32x4LtU, i32x4_lt_u);
3705 simd_binop!(I32x4GtS, i32x4_gt_s);
3706 simd_binop!(I32x4GtU, i32x4_gt_u);
3707 simd_binop!(I32x4LeS, i32x4_le_s);
3708 simd_binop!(I32x4LeU, i32x4_le_u);
3709 simd_binop!(I32x4GeS, i32x4_ge_s);
3710 simd_binop!(I32x4GeU, i32x4_ge_u);
3711 simd_binop!(I64x2Eq, i64x2_eq);
3712 simd_binop!(I64x2Ne, i64x2_ne);
3713 simd_binop!(I64x2LtS, i64x2_lt_s);
3714 simd_binop!(I64x2GtS, i64x2_gt_s);
3715 simd_binop!(I64x2LeS, i64x2_le_s);
3716 simd_binop!(I64x2GeS, i64x2_ge_s);
3717 simd_binop!(F32x4Eq, f32x4_eq);
3718 simd_binop!(F32x4Ne, f32x4_ne);
3719 simd_binop!(F32x4Lt, f32x4_lt);
3720 simd_binop!(F32x4Gt, f32x4_gt);
3721 simd_binop!(F32x4Le, f32x4_le);
3722 simd_binop!(F32x4Ge, f32x4_ge);
3723 simd_binop!(F64x2Eq, f64x2_eq);
3724 simd_binop!(F64x2Ne, f64x2_ne);
3725 simd_binop!(F64x2Lt, f64x2_lt);
3726 simd_binop!(F64x2Gt, f64x2_gt);
3727 simd_binop!(F64x2Le, f64x2_le);
3728 simd_binop!(F64x2Ge, f64x2_ge);
3729 simd_unop!(V128Not, v128_not);
3730 simd_binop!(V128And, v128_and);
3731 simd_binop!(V128AndNot, v128_and_not);
3732 simd_binop!(V128Or, v128_or);
3733 simd_binop!(V128Xor, v128_xor);
3734 simd_unop!(V128AnyTrue, v128_any_true, V128 -> I32);
3735 simd_unop!(I8x16Abs, i8x16_abs);
3736 simd_unop!(I8x16Neg, i8x16_neg);
3737 simd_unop!(I8x16Popcnt, i8x16_popcnt);
3738 simd_unop!(I8x16AllTrue, i8x16_all_true, V128 -> I32);
3739 simd_unop!(I8x16Bitmask, i8x16_bitmask, V128 -> I32);
3740 simd_binop!(I8x16NarrowI16x8S, i8x16_narrow_i16x8s);
3741 simd_binop!(I8x16NarrowI16x8U, i8x16_narrow_i16x8u);
3742 simd_shift!(I8x16Shl, i8x16_shl);
3743 simd_shift!(I8x16ShrS, i8x16_shr_s);
3744 simd_shift!(I8x16ShrU, i8x16_shr_u);
3745 simd_binop!(I8x16Add, i8x16_add);
3746 simd_binop!(I8x16AddSatS, i8x16_add_sat_s);
3747 simd_binop!(I8x16AddSatU, i8x16_add_sat_u);
3748 simd_binop!(I8x16Sub, i8x16_sub);
3749 simd_binop!(I8x16SubSatS, i8x16_sub_sat_s);
3750 simd_binop!(I8x16SubSatU, i8x16_sub_sat_u);
3751 simd_binop!(I8x16MinS, i8x16_min_s);
3752 simd_binop!(I8x16MinU, i8x16_min_u);
3753 simd_binop!(I8x16MaxS, i8x16_max_s);
3754 simd_binop!(I8x16MaxU, i8x16_max_u);
3755 simd_binop!(I8x16RoundingAverageU, i8x16_rounding_average_u);
3756 simd_unop!(I16x8ExtAddPairwiseI8x16S, i16x8_ext_add_pairwise_i8x16s);
3757 simd_unop!(I16x8ExtAddPairwiseI8x16U, i16x8_ext_add_pairwise_i8x16u);
3758 simd_unop!(I16x8Abs, i16x8_abs);
3759 simd_unop!(I16x8Neg, i16x8_neg);
3760 simd_binop!(I16x8Q15MulrSatS, i16x8q15_mulr_sat_s);
3761 simd_unop!(I16x8AllTrue, i16x8_all_true, V128 -> I32);
3762 simd_unop!(I16x8Bitmask, i16x8_bitmask, V128 -> I32);
3763 simd_binop!(I16x8NarrowI32x4S, i16x8_narrow_i32x4s);
3764 simd_binop!(I16x8NarrowI32x4U, i16x8_narrow_i32x4u);
3765 simd_unop!(I16x8ExtendLowI8x16S, i16x8_extend_low_i8x16s);
3766 simd_unop!(I16x8ExtendHighI8x16S, i16x8_extend_high_i8x16s);
3767 simd_unop!(I16x8ExtendLowI8x16U, i16x8_extend_low_i8x16u);
3768 simd_unop!(I16x8ExtendHighI8x16U, i16x8_extend_high_i8x16u);
3769 simd_shift!(I16x8Shl, i16x8_shl);
3770 simd_shift!(I16x8ShrS, i16x8_shr_s);
3771 simd_shift!(I16x8ShrU, i16x8_shr_u);
3772 simd_binop!(I16x8Add, i16x8_add);
3773 simd_binop!(I16x8AddSatS, i16x8_add_sat_s);
3774 simd_binop!(I16x8AddSatU, i16x8_add_sat_u);
3775 simd_binop!(I16x8Sub, i16x8_sub);
3776 simd_binop!(I16x8SubSatS, i16x8_sub_sat_s);
3777 simd_binop!(I16x8SubSatU, i16x8_sub_sat_u);
3778 simd_binop!(I16x8Mul, i16x8_mul);
3779 simd_binop!(I16x8MinS, i16x8_min_s);
3780 simd_binop!(I16x8MinU, i16x8_min_u);
3781 simd_binop!(I16x8MaxS, i16x8_max_s);
3782 simd_binop!(I16x8MaxU, i16x8_max_u);
3783 simd_binop!(I16x8RoundingAverageU, i16x8_rounding_average_u);
3784 simd_binop!(I16x8ExtMulLowI8x16S, i16x8_ext_mul_low_i8x16s);
3785 simd_binop!(I16x8ExtMulHighI8x16S, i16x8_ext_mul_high_i8x16s);
3786 simd_binop!(I16x8ExtMulLowI8x16U, i16x8_ext_mul_low_i8x16u);
3787 simd_binop!(I16x8ExtMulHighI8x16U, i16x8_ext_mul_high_i8x16u);
3788 simd_unop!(I32x4ExtAddPairwiseI16x8S, i32x4_ext_add_pairwise_i16x8s);
3789 simd_unop!(I32x4ExtAddPairwiseI16x8U, i32x4_ext_add_pairwise_i16x8u);
3790 simd_unop!(I32x4Abs, i32x4_abs);
3791 simd_unop!(I32x4Neg, i32x4_neg);
3792 simd_unop!(I32x4AllTrue, i32x4_all_true, V128 -> I32);
3793 simd_unop!(I32x4Bitmask, i32x4_bitmask, V128 -> I32);
3794 simd_unop!(I32x4ExtendLowI16x8S, i32x4_extend_low_i16x8s);
3795 simd_unop!(I32x4ExtendHighI16x8S, i32x4_extend_high_i16x8s);
3796 simd_unop!(I32x4ExtendLowI16x8U, i32x4_extend_low_i16x8u);
3797 simd_unop!(I32x4ExtendHighI16x8U, i32x4_extend_high_i16x8u);
3798 simd_shift!(I32x4Shl, i32x4_shl);
3799 simd_shift!(I32x4ShrS, i32x4_shr_s);
3800 simd_shift!(I32x4ShrU, i32x4_shr_u);
3801 simd_binop!(I32x4Add, i32x4_add);
3802 simd_binop!(I32x4Sub, i32x4_sub);
3803 simd_binop!(I32x4Mul, i32x4_mul);
3804 simd_binop!(I32x4MinS, i32x4_min_s);
3805 simd_binop!(I32x4MinU, i32x4_min_u);
3806 simd_binop!(I32x4MaxS, i32x4_max_s);
3807 simd_binop!(I32x4MaxU, i32x4_max_u);
3808 simd_binop!(I32x4DotI16x8S, i32x4_dot_i16x8s);
3809 simd_binop!(I32x4ExtMulLowI16x8S, i32x4_ext_mul_low_i16x8s);
3810 simd_binop!(I32x4ExtMulHighI16x8S, i32x4_ext_mul_high_i16x8s);
3811 simd_binop!(I32x4ExtMulLowI16x8U, i32x4_ext_mul_low_i16x8u);
3812 simd_binop!(I32x4ExtMulHighI16x8U, i32x4_ext_mul_high_i16x8u);
3813 simd_unop!(I64x2Abs, i64x2_abs);
3814 simd_unop!(I64x2Neg, i64x2_neg);
3815 simd_unop!(I64x2AllTrue, i64x2_all_true, V128 -> I32);
3816 simd_unop!(I64x2Bitmask, i64x2_bitmask, V128 -> I32);
3817 simd_unop!(I64x2ExtendLowI32x4S, i64x2_extend_low_i32x4s);
3818 simd_unop!(I64x2ExtendHighI32x4S, i64x2_extend_high_i32x4s);
3819 simd_unop!(I64x2ExtendLowI32x4U, i64x2_extend_low_i32x4u);
3820 simd_unop!(I64x2ExtendHighI32x4U, i64x2_extend_high_i32x4u);
3821 simd_shift!(I64x2Shl, i64x2_shl);
3822 simd_shift!(I64x2ShrS, i64x2_shr_s);
3823 simd_shift!(I64x2ShrU, i64x2_shr_u);
3824 simd_binop!(I64x2Add, i64x2_add);
3825 simd_binop!(I64x2Sub, i64x2_sub);
3826 simd_binop!(I64x2Mul, i64x2_mul);
3827 simd_binop!(I64x2ExtMulLowI32x4S, i64x2_ext_mul_low_i32x4s);
3828 simd_binop!(I64x2ExtMulHighI32x4S, i64x2_ext_mul_high_i32x4s);
3829 simd_binop!(I64x2ExtMulLowI32x4U, i64x2_ext_mul_low_i32x4u);
3830 simd_binop!(I64x2ExtMulHighI32x4U, i64x2_ext_mul_high_i32x4u);
3831 simd_unop!(F32x4Ceil, f32x4_ceil);
3832 simd_unop!(F32x4Floor, f32x4_floor);
3833 simd_unop!(F32x4Trunc, f32x4_trunc);
3834 simd_unop!(F32x4Nearest, f32x4_nearest);
3835 simd_unop!(F32x4Abs, f32x4_abs);
3836 simd_unop!(F32x4Neg, f32x4_neg);
3837 simd_unop!(F32x4Sqrt, f32x4_sqrt);
3838 simd_binop!(F32x4Add, f32x4_add);
3839 simd_binop!(F32x4Sub, f32x4_sub);
3840 simd_binop!(F32x4Mul, f32x4_mul);
3841 simd_binop!(F32x4Div, f32x4_div);
3842 simd_binop!(F32x4Min, f32x4_min);
3843 simd_binop!(F32x4Max, f32x4_max);
3844 simd_binop!(F32x4PMin, f32x4p_min);
3845 simd_binop!(F32x4PMax, f32x4p_max);
3846 simd_unop!(F64x2Ceil, f64x2_ceil);
3847 simd_unop!(F64x2Floor, f64x2_floor);
3848 simd_unop!(F64x2Trunc, f64x2_trunc);
3849 simd_unop!(F64x2Nearest, f64x2_nearest);
3850 simd_unop!(F64x2Abs, f64x2_abs);
3851 simd_unop!(F64x2Neg, f64x2_neg);
3852 simd_unop!(F64x2Sqrt, f64x2_sqrt);
3853 simd_binop!(F64x2Add, f64x2_add);
3854 simd_binop!(F64x2Sub, f64x2_sub);
3855 simd_binop!(F64x2Mul, f64x2_mul);
3856 simd_binop!(F64x2Div, f64x2_div);
3857 simd_binop!(F64x2Min, f64x2_min);
3858 simd_binop!(F64x2Max, f64x2_max);
3859 simd_binop!(F64x2PMin, f64x2p_min);
3860 simd_binop!(F64x2PMax, f64x2p_max);
3861 simd_unop!(I32x4TruncSatF32x4S, i32x4_trunc_sat_f32x4s);
3862 simd_unop!(I32x4TruncSatF32x4U, i32x4_trunc_sat_f32x4u);
3863 simd_unop!(F32x4ConvertI32x4S, f32x4_convert_i32x4s);
3864 simd_unop!(F32x4ConvertI32x4U, f32x4_convert_i32x4u);
3865 simd_unop!(I32x4TruncSatF64x2SZero, i32x4_trunc_sat_f64x2s_zero);
3866 simd_unop!(I32x4TruncSatF64x2UZero, i32x4_trunc_sat_f64x2u_zero);
3867 simd_unop!(F64x2ConvertLowI32x4S, f64x2_convert_low_i32x4s);
3868 simd_unop!(F64x2ConvertLowI32x4U, f64x2_convert_low_i32x4u);
3869 simd_unop!(F32x4DemoteF64x2Zero, f32x4_demote_f64x2_zero);
3870 simd_unop!(F64x2PromoteLowF32x4, f64x2_promote_low_f32x4);
3871
v128_bitselect( _: &mut Unstructured, _: &Module, builder: &mut CodeBuilder, ) -> Result<Instruction>3872 fn v128_bitselect(
3873 _: &mut Unstructured,
3874 _: &Module,
3875 builder: &mut CodeBuilder,
3876 ) -> Result<Instruction> {
3877 builder.pop_operands(&[ValType::V128, ValType::V128, ValType::V128]);
3878 builder.push_operands(&[ValType::V128]);
3879 Ok(Instruction::V128Bitselect)
3880 }
3881