Skip to content

Commit 454e90c

Browse files
committed
cranelift: force little-endian on inline bulk copy chunks
Pulley's `VLoad`/`VStore` for `v128` only encode the little-endian variant, so `MemFlagsData::trusted()` (which inherits the target's native endianness) tripped an emitter assertion when targeting `pulley32be`/`pulley64be`. Pinning the chunk load/store endianness to `Little` is safe because each loaded value feeds only its paired store and is never observed as a number, so the destination's byte sequence is independent of the chosen endianness as long as load and store agree.
1 parent fa4a65f commit 454e90c

3 files changed

Lines changed: 18 additions & 9 deletions

File tree

crates/cranelift/src/func_environ.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4461,7 +4461,16 @@ impl FuncEnvironment<'_> {
44614461
// operand that requires alignment, so the backend selects unaligned
44624462
// moves regardless of the `aligned` flag. The range was already
44634463
// bounds-checked, so `notrap` is fine too.
4464-
let flags = ir::MemFlagsData::trusted();
4464+
//
4465+
// Endianness is pinned to `Little` rather than inheriting the target's
4466+
// native endianness for two reasons: (1) Pulley's `v128` load/store only
4467+
// encode the little-endian variant and would assert otherwise, and (2)
4468+
// the byte sequence written to the destination is independent of the
4469+
// chosen endianness as long as load and store agree, since each loaded
4470+
// chunk is fed straight back to its paired store without being observed
4471+
// as a number. On big-endian native targets this costs two byteswaps
4472+
// per chunk that cancel each other out, which we accept.
4473+
let flags = ir::MemFlagsData::trusted().with_endianness(Endianness::Little);
44654474
const WIDTHS: &[(u64, ir::Type)] = &[
44664475
(16, ir::types::I8X16),
44674476
(8, ir::types::I64),

tests/disas/array-copy-inline.wat

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,12 @@
6767
;; @002a v56 = uadd_overflow_trap v44, v98, user2 ; v98 = 28
6868
;; @002a v57 = icmp ugt v56, v50
6969
;; @002a trapnz v57, user2
70-
;; @002a v58 = load.i8x16 notrap aligned v44
71-
;; @002a v59 = load.i64 notrap aligned v44+16
72-
;; @002a v60 = load.i32 notrap aligned v44+24
73-
;; @002a store notrap aligned v58, v25
74-
;; @002a store notrap aligned v59, v25+16
75-
;; @002a store notrap aligned v60, v25+24
70+
;; @002a v58 = load.i8x16 notrap aligned little v44
71+
;; @002a v59 = load.i64 notrap aligned little v44+16
72+
;; @002a v60 = load.i32 notrap aligned little v44+24
73+
;; @002a store notrap aligned little v58, v25
74+
;; @002a store notrap aligned little v59, v25+16
75+
;; @002a store notrap aligned little v60, v25+24
7676
;; @002e jump block1
7777
;;
7878
;; block1:

tests/disas/memory-copy-inline.wat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@
3333
;; @0024 trapnz v22, heap_oob
3434
;; @0024 v12 = load.i64 notrap aligned readonly can_move v0+56
3535
;; @0024 v26 = iadd v12, v18
36-
;; @0024 v28 = load.i8x16 notrap aligned v26
36+
;; @0024 v28 = load.i8x16 notrap aligned little v26
3737
;; @0024 v15 = iadd v12, v7
38-
;; @0024 store notrap aligned v28, v15
38+
;; @0024 store notrap aligned little v28, v15
3939
;; @0028 jump block1
4040
;;
4141
;; block1:

0 commit comments

Comments
 (0)