Skip to content

Commit 6c73bd3

Browse files
committed
Fix computation of fill size in array.fill implementation
We were incorrectly reusing the offset of the first-element-to-be-filled's address (`index * size_of(elem)`) as the size-in-bytes of the whole fill (which should actually be `n * size_of(elem)`). This led to the wrong number of iterations for our element-filling loop. Fixes bytecodealliance#10467
1 parent 3f53021 commit 6c73bd3

File tree

4 files changed

+64
-41
lines changed

4 files changed

+64
-41
lines changed

crates/cranelift/src/gc/enabled.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,8 @@ pub fn translate_array_fill(
637637
);
638638

639639
// Calculate the end address, just after the filled region.
640-
let fill_size = uextend_i32_to_pointer_type(builder, func_env.pointer_type(), offset_in_elems);
640+
let fill_size = builder.ins().imul(n, one_elem_size);
641+
let fill_size = uextend_i32_to_pointer_type(builder, func_env.pointer_type(), fill_size);
641642
let fill_end = builder.ins().iadd(elem_addr, fill_size);
642643

643644
let one_elem_size =
@@ -657,9 +658,9 @@ pub fn translate_array_fill(
657658
.element_type;
658659
write_field_at_addr(func_env, builder, elem_ty, elem_addr, value)
659660
},
660-
)?;
661+
);
661662
log::trace!("translate_array_fill(..) -> {result:?}");
662-
Ok(result)
663+
result
663664
}
664665

665666
pub fn translate_array_len(

tests/disas/gc/drc/array-fill.wat

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,38 +33,39 @@
3333
;; @0027 v19 = icmp ugt v18, v17
3434
;; @0027 trapnz v19, user17
3535
;; @0027 v21 = uextend.i64 v17
36-
;; v48 = iconst.i64 3
37-
;; v49 = ishl v21, v48 ; v48 = 3
38-
;; v47 = iconst.i64 32
39-
;; @0027 v23 = ushr v49, v47 ; v47 = 32
36+
;; v49 = iconst.i64 3
37+
;; v50 = ishl v21, v49 ; v49 = 3
38+
;; v48 = iconst.i64 32
39+
;; @0027 v23 = ushr v50, v48 ; v48 = 32
4040
;; @0027 trapnz v23, user1
41-
;; v58 = iconst.i32 3
42-
;; v59 = ishl v17, v58 ; v58 = 3
41+
;; v59 = iconst.i32 3
42+
;; v60 = ishl v17, v59 ; v59 = 3
4343
;; @0027 v25 = iconst.i32 32
44-
;; @0027 v26 = uadd_overflow_trap v59, v25, user1 ; v25 = 32
45-
;; v66 = ishl v3, v58 ; v58 = 3
46-
;; v68 = iadd v66, v25 ; v25 = 32
47-
;; @0027 v35 = uextend.i64 v68
44+
;; @0027 v26 = uadd_overflow_trap v60, v25, user1 ; v25 = 32
45+
;; v67 = ishl v3, v59 ; v59 = 3
46+
;; v69 = iadd v67, v25 ; v25 = 32
47+
;; @0027 v35 = uextend.i64 v69
4848
;; @0027 v36 = uadd_overflow_trap v10, v35, user1
4949
;; @0027 v37 = uextend.i64 v26
5050
;; @0027 v38 = uadd_overflow_trap v10, v37, user1
5151
;; @0027 v39 = icmp ule v38, v9
5252
;; @0027 trapz v39, user1
5353
;; @0027 v40 = iadd v7, v36
54-
;; @0027 v41 = uextend.i64 v66
55-
;; @0027 v42 = iadd v40, v41
54+
;; v71 = ishl v5, v59 ; v59 = 3
55+
;; @0027 v42 = uextend.i64 v71
56+
;; @0027 v43 = iadd v40, v42
5657
;; @0027 v20 = iconst.i64 8
5758
;; @0027 jump block2(v40)
5859
;;
59-
;; block2(v44: i64):
60-
;; @0027 v45 = icmp eq v44, v42
61-
;; @0027 brif v45, block4, block3
60+
;; block2(v45: i64):
61+
;; @0027 v46 = icmp eq v45, v43
62+
;; @0027 brif v46, block4, block3
6263
;;
6364
;; block3:
64-
;; @0027 store.i64 notrap aligned little v4, v44
65-
;; v70 = iconst.i64 8
66-
;; v71 = iadd.i64 v44, v70 ; v70 = 8
67-
;; @0027 jump block2(v71)
65+
;; @0027 store.i64 notrap aligned little v4, v45
66+
;; v73 = iconst.i64 8
67+
;; v74 = iadd.i64 v45, v73 ; v73 = 8
68+
;; @0027 jump block2(v74)
6869
;;
6970
;; block4:
7071
;; @002a jump block1

tests/disas/gc/null/array-fill.wat

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,37 +33,38 @@
3333
;; @0027 v19 = icmp ugt v18, v17
3434
;; @0027 trapnz v19, user17
3535
;; @0027 v21 = uextend.i64 v17
36-
;; v48 = iconst.i64 3
37-
;; v49 = ishl v21, v48 ; v48 = 3
38-
;; v47 = iconst.i64 32
39-
;; @0027 v23 = ushr v49, v47 ; v47 = 32
36+
;; v49 = iconst.i64 3
37+
;; v50 = ishl v21, v49 ; v49 = 3
38+
;; v48 = iconst.i64 32
39+
;; @0027 v23 = ushr v50, v48 ; v48 = 32
4040
;; @0027 trapnz v23, user1
41-
;; v58 = iconst.i32 3
42-
;; v59 = ishl v17, v58 ; v58 = 3
41+
;; v59 = iconst.i32 3
42+
;; v60 = ishl v17, v59 ; v59 = 3
4343
;; @0027 v25 = iconst.i32 16
44-
;; @0027 v26 = uadd_overflow_trap v59, v25, user1 ; v25 = 16
45-
;; v66 = ishl v3, v58 ; v58 = 3
46-
;; v68 = iadd v66, v25 ; v25 = 16
47-
;; @0027 v35 = uextend.i64 v68
44+
;; @0027 v26 = uadd_overflow_trap v60, v25, user1 ; v25 = 16
45+
;; v67 = ishl v3, v59 ; v59 = 3
46+
;; v69 = iadd v67, v25 ; v25 = 16
47+
;; @0027 v35 = uextend.i64 v69
4848
;; @0027 v36 = uadd_overflow_trap v10, v35, user1
4949
;; @0027 v37 = uextend.i64 v26
5050
;; @0027 v38 = uadd_overflow_trap v10, v37, user1
5151
;; @0027 v39 = icmp ule v38, v9
5252
;; @0027 trapz v39, user1
5353
;; @0027 v40 = iadd v7, v36
54-
;; @0027 v41 = uextend.i64 v66
55-
;; @0027 v42 = iadd v40, v41
54+
;; v71 = ishl v5, v59 ; v59 = 3
55+
;; @0027 v42 = uextend.i64 v71
56+
;; @0027 v43 = iadd v40, v42
5657
;; @0027 jump block2(v40)
5758
;;
58-
;; block2(v44: i64):
59-
;; @0027 v45 = icmp eq v44, v42
60-
;; @0027 brif v45, block4, block3
59+
;; block2(v45: i64):
60+
;; @0027 v46 = icmp eq v45, v43
61+
;; @0027 brif v46, block4, block3
6162
;;
6263
;; block3:
63-
;; @0027 store.i64 notrap aligned little v4, v44
64-
;; v70 = iconst.i64 8
65-
;; v71 = iadd.i64 v44, v70 ; v70 = 8
66-
;; @0027 jump block2(v71)
64+
;; @0027 store.i64 notrap aligned little v4, v45
65+
;; v73 = iconst.i64 8
66+
;; v74 = iadd.i64 v45, v73 ; v73 = 8
67+
;; @0027 jump block2(v74)
6768
;;
6869
;; block4:
6970
;; @002a jump block1
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
;;! gc = true
2+
3+
(module
4+
(type $string (array (mut i8)))
5+
(func (export "f")
6+
(local $s (ref $string))
7+
(local.set $s (array.new_default $string (i32.const 1)))
8+
(array.fill $string
9+
(local.get $s)
10+
(i32.const 0)
11+
(i32.const 32)
12+
(i32.const 1))
13+
(if (i32.ne (array.get_u $string (local.get $s) (i32.const 0))
14+
(i32.const 32))
15+
(then
16+
(unreachable)))
17+
)
18+
)
19+
20+
(assert_return (invoke "f"))

0 commit comments

Comments
 (0)