cranelift-codegen 0.129.2

Low-level code generator library
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
;; This is a prelude of standard definitions for ISLE, the instruction-selector
;; DSL, as we use it bound to our interfaces.
;;
;; Note that all `extern` functions here are typically defined in the
;; `isle_prelude_methods` macro defined in `src/isa/isle.rs`

;;;; Primitive and External Types ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; `()`
(type Unit (primitive Unit))
(model Unit (type Unit))

(decl pure unit () Unit)
(extern constructor unit unit)

(model bool (type Bool))

(model u8 (type (bv 8)))
(model u16 (type (bv 16)))
(model u32 (type (bv 32)))
(model u64 (type (bv 64)))
(model usize (type (bv)))

(model i8 (type (bv 8)))
(model i16 (type (bv 16)))
(model i32 (type (bv 32)))
(model i64 (type (bv 64)))

;; `cranelift-entity`-based identifiers.

(model Type (type Int))
(type Type (primitive Type))

(model Value (type (bv)))
(type Value (primitive Value))

(type ValueList (primitive ValueList))

(type BlockCall (primitive BlockCall))

(type Inst (primitive Inst))

;; Match the instruction that defines the given value, if any.
(spec (def_inst arg) (provide (= result arg)))
(decl def_inst (Inst) Value)
(extern extractor def_inst def_inst)

;; ISLE representation of `&[Value]`.
(type ValueSlice (primitive ValueSlice))

;; Extract the type of a `Value`.
(spec (value_type arg) (provide (= arg (widthof result))))
(decl value_type (Type) Value)
(extern extractor infallible value_type value_type)

;; Extractor that matches a `u32` only if non-negative.
(decl u32_nonnegative (u32) u32)
(extern extractor u32_nonnegative u32_nonnegative)

;; Extractor that pulls apart an Offset32 into a i32 with the raw
;; signed-32-bit twos-complement bits.
(decl offset32 (i32) Offset32)
(extern extractor infallible offset32 offset32)

;;;; Primitive Arithmetic ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(decl pure partial checked_add_with_type (Type u64 u64) u64)
(extern constructor checked_add_with_type checked_add_with_type)

(decl pure add_overflows_with_type (Type u64 u64) bool)
(extern constructor add_overflows_with_type add_overflows_with_type)

(decl pure partial imm64_sdiv (Type Imm64 Imm64) Imm64)
(extern constructor imm64_sdiv imm64_sdiv)

(decl pure partial imm64_srem (Type Imm64 Imm64) Imm64)
(extern constructor imm64_srem imm64_srem)

(decl pure imm64_shl (Type Imm64 Imm64) Imm64)
(extern constructor imm64_shl imm64_shl)

(decl pure imm64_ushr (Type Imm64 Imm64) Imm64)
(extern constructor imm64_ushr imm64_ushr)

(decl pure imm64_sshr (Type Imm64 Imm64) Imm64)
(extern constructor imm64_sshr imm64_sshr)

;; Sign extends a u64 from ty bits up to 64bits
(decl pure i64_sextend_u64 (Type u64) i64)
(extern constructor i64_sextend_u64 i64_sextend_u64)

(spec (i64_sextend_imm64 ty a) (provide (= result (sign_ext 64 (conv_to ty a)))))
(decl pure i64_sextend_imm64 (Type Imm64) i64)
(extern constructor i64_sextend_imm64 i64_sextend_imm64)

(decl pure u64_uextend_imm64 (Type Imm64) u64)
(extern constructor u64_uextend_imm64 u64_uextend_imm64)

(decl pure imm64_icmp (Type IntCC Imm64 Imm64) Imm64)
(extern constructor imm64_icmp imm64_icmp)

(decl pure imm64_clz (Type Imm64) Imm64)
(extern constructor imm64_clz imm64_clz)

(decl pure imm64_ctz (Type Imm64) Imm64)
(extern constructor imm64_ctz imm64_ctz)

;; Each of these extractors tests whether the upper half of the input equals the
;; lower half of the input
(decl u128_replicated_u64 (u64) u128)
(extern extractor u128_replicated_u64 u128_replicated_u64)
(decl u64_replicated_u32 (u64) u64)
(extern extractor u64_replicated_u32 u64_replicated_u32)
(decl u32_replicated_u16 (u64) u64)
(extern extractor u32_replicated_u16 u32_replicated_u16)
(decl u16_replicated_u8 (u8) u64)
(extern extractor u16_replicated_u8 u16_replicated_u8)

;; Get the low and high bits of a `u128` as `u64`s.
(decl u128_low_bits (u128) u64)
(extern constructor u128_low_bits u128_low_bits)
(decl u128_high_bits (u128) u64)
(extern constructor u128_high_bits u128_high_bits)

;; Floating point operations

(decl pure partial f16_min (Ieee16 Ieee16) Ieee16)
(extern constructor f16_min f16_min)
(decl pure partial f16_max (Ieee16 Ieee16) Ieee16)
(extern constructor f16_max f16_max)
(decl pure f16_neg (Ieee16) Ieee16)
(extern constructor f16_neg f16_neg)
(decl pure f16_abs (Ieee16) Ieee16)
(extern constructor f16_abs f16_abs)
(decl pure f16_copysign (Ieee16 Ieee16) Ieee16)
(extern constructor f16_copysign f16_copysign)
(decl pure partial f32_add (Ieee32 Ieee32) Ieee32)
(extern constructor f32_add f32_add)
(decl pure partial f32_sub (Ieee32 Ieee32) Ieee32)
(extern constructor f32_sub f32_sub)
(decl pure partial f32_mul (Ieee32 Ieee32) Ieee32)
(extern constructor f32_mul f32_mul)
(decl pure partial f32_div (Ieee32 Ieee32) Ieee32)
(extern constructor f32_div f32_div)
(decl pure partial f32_sqrt (Ieee32) Ieee32)
(extern constructor f32_sqrt f32_sqrt)
(decl pure partial f32_ceil (Ieee32) Ieee32)
(extern constructor f32_ceil f32_ceil)
(decl pure partial f32_floor (Ieee32) Ieee32)
(extern constructor f32_floor f32_floor)
(decl pure partial f32_trunc (Ieee32) Ieee32)
(extern constructor f32_trunc f32_trunc)
(decl pure partial f32_nearest (Ieee32) Ieee32)
(extern constructor f32_nearest f32_nearest)
(decl pure partial f32_min (Ieee32 Ieee32) Ieee32)
(extern constructor f32_min f32_min)
(decl pure partial f32_max (Ieee32 Ieee32) Ieee32)
(extern constructor f32_max f32_max)
(decl pure f32_neg (Ieee32) Ieee32)
(extern constructor f32_neg f32_neg)
(decl pure f32_abs (Ieee32) Ieee32)
(extern constructor f32_abs f32_abs)
(decl pure f32_copysign (Ieee32 Ieee32) Ieee32)
(extern constructor f32_copysign f32_copysign)
(decl pure partial f64_add (Ieee64 Ieee64) Ieee64)
(extern constructor f64_add f64_add)
(decl pure partial f64_sub (Ieee64 Ieee64) Ieee64)
(extern constructor f64_sub f64_sub)
(decl pure partial f64_mul (Ieee64 Ieee64) Ieee64)
(extern constructor f64_mul f64_mul)
(decl pure partial f64_div (Ieee64 Ieee64) Ieee64)
(extern constructor f64_div f64_div)
(decl pure partial f64_sqrt (Ieee64) Ieee64)
(extern constructor f64_sqrt f64_sqrt)
(decl pure partial f64_ceil (Ieee64) Ieee64)
(extern constructor f64_ceil f64_ceil)
(decl pure partial f64_floor (Ieee64) Ieee64)
(extern constructor f64_floor f64_floor)
(decl pure partial f64_trunc (Ieee64) Ieee64)
(extern constructor f64_trunc f64_trunc)
(decl pure partial f64_nearest (Ieee64) Ieee64)
(extern constructor f64_nearest f64_nearest)
(decl pure partial f64_min (Ieee64 Ieee64) Ieee64)
(extern constructor f64_min f64_min)
(decl pure partial f64_max (Ieee64 Ieee64) Ieee64)
(extern constructor f64_max f64_max)
(decl pure f64_neg (Ieee64) Ieee64)
(extern constructor f64_neg f64_neg)
(decl pure f64_abs (Ieee64) Ieee64)
(extern constructor f64_abs f64_abs)
(decl pure f64_copysign (Ieee64 Ieee64) Ieee64)
(extern constructor f64_copysign f64_copysign)
(decl pure partial f128_min (Ieee128 Ieee128) Ieee128)
(extern constructor f128_min f128_min)
(decl pure partial f128_max (Ieee128 Ieee128) Ieee128)
(extern constructor f128_max f128_max)
(decl pure f128_neg (Ieee128) Ieee128)
(extern constructor f128_neg f128_neg)
(decl pure f128_abs (Ieee128) Ieee128)
(extern constructor f128_abs f128_abs)
(decl pure f128_copysign (Ieee128 Ieee128) Ieee128)
(extern constructor f128_copysign f128_copysign)
(type Ieee128 (primitive Ieee128))

;;;; `cranelift_codegen::ir::Type` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(extern const $I8 Type)
(extern const $I16 Type)
(extern const $I32 Type)
(extern const $I64 Type)
(extern const $I128 Type)

(extern const $F16 Type)
(extern const $F32 Type)
(extern const $F64 Type)
(extern const $F128 Type)

(extern const $I8X8 Type)
(extern const $I8X16 Type)
(extern const $I16X4 Type)
(extern const $I16X8 Type)
(extern const $I32X2 Type)
(extern const $I32X4 Type)
(extern const $I64X2 Type)

(extern const $F16X8 Type)
(extern const $F32X4 Type)
(extern const $F64X2 Type)

(extern const $I32X4XN Type)

;; Get the unsigned minimum value for a given type.
;; This always zero, but is included for completeness.
(decl pure ty_umin (Type) u64)
(extern constructor ty_umin ty_umin)

;; Get the unsigned maximum value for a given type.
(decl pure ty_umax (Type) u64)
(extern constructor ty_umax ty_umax)

;; Get the signed minimum value for a given type.
(decl pure ty_smin (Type) u64)
(extern constructor ty_smin ty_smin)

;; Get the signed maximum value for a given type.
(decl pure ty_smax (Type) u64)
(extern constructor ty_smax ty_smax)

;; Get the bit width of a given type.
(spec (ty_bits x) (provide (= result (int2bv 8 x))))
(decl pure ty_bits (Type) u8)
(extern constructor ty_bits ty_bits)

;; Get the bit width of a given type.
(spec (ty_bits_u16 x)
      (provide (= result (int2bv 16 x))))
(decl pure ty_bits_u16 (Type) u16)
(extern constructor ty_bits_u16 ty_bits_u16)

;; Get the bit width of a given type.
(decl pure ty_bits_u64 (Type) u64)
(extern constructor ty_bits_u64 ty_bits_u64)

;; Get a mask for the width of a given type.
(decl pure ty_mask (Type) u64)
(extern constructor ty_mask ty_mask)

;; Get a mask that is set for each lane in a given type.
(decl pure ty_lane_mask (Type) u64)
(extern constructor ty_lane_mask ty_lane_mask)

;; Get the number of lanes for a given type.
(decl pure ty_lane_count (Type) u64)
(extern constructor ty_lane_count ty_lane_count)

;; Get the byte width of a given type.
(decl pure ty_bytes (Type) u16)
(extern constructor ty_bytes ty_bytes)

;; Get the type of each lane in the given type.
(decl pure lane_type (Type) Type)
(extern constructor lane_type lane_type)

;; Get a type with the same element type, but half the number of lanes.
(decl pure partial ty_half_lanes (Type) Type)
(extern constructor ty_half_lanes ty_half_lanes)

;; Get a type with the same number of lanes but a lane type that is half as small.
(decl pure partial ty_half_width (Type) Type)
(extern constructor ty_half_width ty_half_width)

;; Generate a mask for the maximum shift amount for a given type. i.e 31 for I32.
(decl pure ty_shift_mask (Type) u64)
(rule (ty_shift_mask ty) (u64_sub (ty_bits (lane_type ty)) 1))

;; Compare two types for equality.
(decl pure ty_equal (Type Type) bool)
(extern constructor ty_equal ty_equal)

;;;; `cranelift_codegen::ir::MemFlags ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Provide model for the MemFlags type (declared in generated clif_lower.isle).
(model MemFlags (type (bv 16)))

;; `MemFlags::trusted`
(spec (mem_flags_trusted)
      (provide (= result #x0003)))
(decl pure mem_flags_trusted () MemFlags)
(extern constructor mem_flags_trusted mem_flags_trusted)

;; Determine if flags specify little- or native-endian.
(decl little_or_native_endian (MemFlags) MemFlags)
(extern extractor little_or_native_endian little_or_native_endian)

;;;; Helpers for Working with Flags ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Swap args of an IntCC flag.
(decl intcc_swap_args (IntCC) IntCC)
(extern constructor intcc_swap_args intcc_swap_args)

;; Complement an IntCC flag.
(decl intcc_complement (IntCC) IntCC)
(extern constructor intcc_complement intcc_complement)

;; This is a direct import of `IntCC::without_equal`.
;; Get the corresponding IntCC with the equal component removed.
;; For conditions without a zero component, this is a no-op.
(decl pure intcc_without_eq (IntCC) IntCC)
(extern constructor intcc_without_eq intcc_without_eq)

;; Swap args of a FloatCC flag.
(decl floatcc_swap_args (FloatCC) FloatCC)
(extern constructor floatcc_swap_args floatcc_swap_args)

;; Complement a FloatCC flag.
(decl floatcc_complement (FloatCC) FloatCC)
(extern constructor floatcc_complement floatcc_complement)

;; True when this FloatCC involves an unordered comparison.
(decl pure floatcc_unordered (FloatCC) bool)
(extern constructor floatcc_unordered floatcc_unordered)

;;;; Helper Clif Extractors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; An extractor that only matches types that can fit in 16 bits.
(spec (fits_in_16 arg)
      (provide (= result arg))
      (require (<= arg 16)))
(decl fits_in_16 (Type) Type)
(extern extractor fits_in_16 fits_in_16)

;; An extractor that only matches types that can fit in 32 bits.
(spec (fits_in_32 arg)
      (provide (= result arg))
      (require (<= arg 32)))
(decl fits_in_32 (Type) Type)
(extern extractor fits_in_32 fits_in_32)

;; An extractor that only matches types that can fit in 32 bits.
(decl lane_fits_in_32 (Type) Type)
(extern extractor lane_fits_in_32 lane_fits_in_32)

;; An extractor that only matches types that can fit in 64 bits.
(spec (fits_in_64 arg)
      (provide (= result arg))
      (require (<= arg 64)))
(decl fits_in_64 (Type) Type)
(extern extractor fits_in_64 fits_in_64)

;; An extractor that only matches types that fit in exactly 16 bits.
(decl ty_16 (Type) Type)
(extern extractor ty_16 ty_16)

;; An extractor that only matches types that fit in exactly 32 bits.
(decl ty_32 (Type) Type)
(extern extractor ty_32 ty_32)

;; An extractor that only matches types that fit in exactly 64 bits.
(decl ty_64 (Type) Type)
(extern extractor ty_64 ty_64)

;; An extractor that only matches types that fit in exactly 128 bits.
(decl ty_128 (Type) Type)
(extern extractor ty_128 ty_128)

;; A pure constructor/extractor that only matches scalar integers, and
;; references that can fit in 64 bits.
(spec (ty_int_ref_scalar_64 arg)
    (provide (= result arg))
    (require (<= arg 64)))
(decl pure partial ty_int_ref_scalar_64 (Type) Type)
(extern constructor ty_int_ref_scalar_64 ty_int_ref_scalar_64)
(extern extractor ty_int_ref_scalar_64 ty_int_ref_scalar_64_extract)

;; An extractor that matches 32- and 64-bit types only.
(spec (ty_32_or_64 arg)
      (provide (= result arg))
      (require (or (= arg 32) (= arg 64))))
(decl ty_32_or_64 (Type) Type)
(extern extractor ty_32_or_64 ty_32_or_64)

;; An extractor that matches 8- and 16-bit types only.
(decl ty_8_or_16 (Type) Type)
(extern extractor ty_8_or_16 ty_8_or_16)

;; An extractor that matches 16- and 32-bit types only.
(decl ty_16_or_32 (Type) Type)
(extern extractor ty_16_or_32 ty_16_or_32)

;; An extractor that matches int types that fit in 32 bits.
(decl int_fits_in_32 (Type) Type)
(extern extractor int_fits_in_32 int_fits_in_32)

;; An extractor that matches I64.
(decl ty_int_ref_64 (Type) Type)
(extern extractor ty_int_ref_64 ty_int_ref_64)

;; An extractor that matches int or reference types bigger than 16 bits but at most 64 bits.
(decl ty_int_ref_16_to_64 (Type) Type)
(extern extractor ty_int_ref_16_to_64 ty_int_ref_16_to_64)

;; An extractor that only matches integers.
(spec (ty_int a) (provide (= result a)))
(decl ty_int (Type) Type)
(extern extractor ty_int ty_int)

;; An extractor that only matches scalar types, float or int or ref's.
(decl ty_scalar (Type) Type)
(extern extractor ty_scalar ty_scalar)

;; An extractor that only matches scalar floating-point types.
(decl ty_scalar_float (Type) Type)
(extern extractor ty_scalar_float ty_scalar_float)

;; An extractor that matches scalar floating-point types or vector types.
(decl ty_float_or_vec (Type) Type)
(extern extractor ty_float_or_vec ty_float_or_vec)

;; A pure constructor that only matches vector floating-point types.
(decl pure partial ty_vector_float (Type) Type)
(extern constructor ty_vector_float ty_vector_float)

;; A pure constructor that only matches vector types with lanes which
;; are not floating-point.
(decl pure partial ty_vector_not_float (Type) Type)
(extern constructor ty_vector_not_float ty_vector_not_float)

;; A pure constructor/extractor that only matches 64-bit vector types.
(decl pure partial ty_vec64 (Type) Type)
(extern constructor ty_vec64 ty_vec64_ctor)
(extern extractor ty_vec64 ty_vec64)

;; An extractor that only matches 128-bit vector types.
(decl ty_vec128 (Type) Type)
(extern extractor ty_vec128 ty_vec128)

;; An extractor that only matches dynamic vector types with a 64-bit
;; base type.
(decl ty_dyn_vec64 (Type) Type)
(extern extractor ty_dyn_vec64 ty_dyn_vec64)

;; An extractor that only matches dynamic vector types with a 128-bit
;; base type.
(decl ty_dyn_vec128 (Type) Type)
(extern extractor ty_dyn_vec128 ty_dyn_vec128)

;; An extractor that only matches 64-bit vector types with integer
;; lanes (I8X8, I16X4, I32X2)
(decl ty_vec64_int (Type) Type)
(extern extractor ty_vec64_int ty_vec64_int)

;; An extractor that only matches 128-bit vector types with integer
;; lanes (I8X16, I16X8, I32X4, I64X2).
(decl ty_vec128_int (Type) Type)
(extern extractor ty_vec128_int ty_vec128_int)

;; An extractor that only matches types that can be a 64-bit address.
(decl ty_addr64 (Type) Type)
(extern extractor ty_addr64 ty_addr64)

;; A pure constructor that matches everything except vectors with size 32X2.
(decl pure partial not_vec32x2 (Type) Type)
(extern constructor not_vec32x2 not_vec32x2)

;; An extractor that matches everything except I64X2
(decl not_i64x2 () Type)
(extern extractor not_i64x2 not_i64x2)

;; Extract a `u8` from an `Uimm8`.
(decl u8_from_uimm8 (u8) Uimm8)
(extern extractor infallible u8_from_uimm8 u8_from_uimm8)

;; Extract a `u64` from a `bool`.
(decl u64_from_bool (u64) bool)
(extern extractor infallible u64_from_bool u64_from_bool)

;; Extract a `u64` from an `Imm64`.
(spec (u64_from_imm64 arg) (provide (= arg result)))
(decl u64_from_imm64 (u64) Imm64)
(extern extractor infallible u64_from_imm64 u64_from_imm64)

;; Extract a `u64` from an `Imm64` which is not zero.
(decl nonzero_u64_from_imm64 (u64) Imm64)
(extern extractor nonzero_u64_from_imm64 nonzero_u64_from_imm64)

;; If the given `Imm64` is a power-of-two, extract its log2 value.
(decl imm64_power_of_two (u64) Imm64)
(extern extractor imm64_power_of_two imm64_power_of_two)

;; Create a new Imm64.
(decl pure imm64 (u64) Imm64)
(extern constructor imm64 imm64)

;; Create a new Imm64, masked to the width of the given type.
(decl pure imm64_masked (Type u64) Imm64)
(extern constructor imm64_masked imm64_masked)

;; Extract a `u16` from an `Ieee16`.
(decl u16_from_ieee16 (u16) Ieee16)
(extern extractor infallible u16_from_ieee16 u16_from_ieee16)

;; Extract a `u32` from an `Ieee32`.
(decl u32_from_ieee32 (u32) Ieee32)
(extern extractor infallible u32_from_ieee32 u32_from_ieee32)

;; Extract a `u64` from an `Ieee64`.
(decl u64_from_ieee64 (u64) Ieee64)
(extern extractor infallible u64_from_ieee64 u64_from_ieee64)

;; Match a multi-lane type, extracting (# bits per lane, # lanes) from the given
;; type. Will only match when there is more than one lane.
(decl multi_lane (u32 u32) Type)
(extern extractor multi_lane multi_lane)

;; Match a dynamic-lane type, extracting (# bits per lane) from the given
;; type.
(decl dynamic_lane (u32 u32) Type)
(extern extractor dynamic_lane dynamic_lane)

;; An extractor that only matches 64-bit dynamic vector types with integer
;; lanes (I8X8XN, I16X4XN, I32X2XN)
(decl ty_dyn64_int (Type) Type)
(extern extractor ty_dyn64_int ty_dyn64_int)

;; An extractor that only matches 128-bit dynamic vector types with integer
;; lanes (I8X16XN, I16X8XN, I32X4XN, I64X2XN).
(decl ty_dyn128_int (Type) Type)
(extern extractor ty_dyn128_int ty_dyn128_int)

;; Convert an `Offset32` to a primitive number.
(spec (offset32_to_i32 offset) (provide (= result offset)))
(decl pure offset32_to_i32 (Offset32) i32)
(extern constructor offset32_to_i32 offset32_to_i32)

;; Convert a number to an `Offset32`
(spec (i32_to_offset32 x) (provide (= result x)))
(decl pure i32_to_offset32 (i32) Offset32)
(extern constructor i32_to_offset32 i32_to_offset32)

;; This is a direct import of `IntCC::unsigned`.
;; Get the corresponding IntCC with the signed component removed.
;; For conditions without a signed component, this is a no-op.
(decl pure intcc_unsigned (IntCC) IntCC)
(extern constructor intcc_unsigned intcc_unsigned)

;; Pure constructor that only matches signed integer cond codes.
(spec (signed_cond_code c)
    (provide (= result c))
    (require (and (bvuge c #x02) (bvule c #x05))))
(decl pure partial signed_cond_code (IntCC) IntCC)
(extern constructor signed_cond_code signed_cond_code)

;;;; Helpers for Working with TrapCode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(decl pure trap_code_division_by_zero () TrapCode)
(extern constructor trap_code_division_by_zero trap_code_division_by_zero)

(decl pure trap_code_integer_overflow () TrapCode)
(extern constructor trap_code_integer_overflow trap_code_integer_overflow)

(decl pure trap_code_bad_conversion_to_integer () TrapCode)
(extern constructor trap_code_bad_conversion_to_integer trap_code_bad_conversion_to_integer)

;;;; Automatic conversions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(convert Offset32 i32 offset32_to_i32)
(convert i32 Offset32 i32_to_offset32)

;;;; Common Term Signatures ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(form
  bv_unary_8_to_64
  ((args (bv  8)) (ret (bv  8)) (canon (bv  8)))
  ((args (bv 16)) (ret (bv 16)) (canon (bv 16)))
  ((args (bv 32)) (ret (bv 32)) (canon (bv 32)))
  ((args (bv 64)) (ret (bv 64)) (canon (bv 64)))
)

(form
  bv_binary_8_to_64
  ((args (bv  8) (bv  8)) (ret (bv  8)) (canon (bv  8)))
  ((args (bv 16) (bv 16)) (ret (bv 16)) (canon (bv 16)))
  ((args (bv 32) (bv 32)) (ret (bv 32)) (canon (bv 32)))
  ((args (bv 64) (bv 64)) (ret (bv 64)) (canon (bv 64)))
)

(form
  bv_ternary_8_to_64
  ((args (bv  8) (bv  8) (bv  8)) (ret (bv  8)) (canon (bv  8)))
  ((args (bv 16) (bv 16) (bv 16)) (ret (bv 16)) (canon (bv 16)))
  ((args (bv 32) (bv 32) (bv 32)) (ret (bv 32)) (canon (bv 32)))
  ((args (bv 64) (bv 64) (bv 64)) (ret (bv 64)) (canon (bv 64)))
)