Skip to content

Commit a6f7dbd

Browse files
committed
cranelift: Add virtual addresses to cranelift interpreter
Adds a Virtual Addressing scheme that was discussed as a better alternative to returning the real addresses. The virtual addresses are split into 4 regions (stack, heap, tables and global values), and the address itself is composed of an `entry` field and an `offset` field. In general the `entry` field corresponds to the instance of the resource (e.g. table5 is entry 5) and the `offset` field is a byte offset inside that entry. There is one exception to this which is the stack, where due to only having one stack, the whole address is an offset field. The number of bits in entry vs offset fields is variable with respect to the `region` and the address size (32bits vs 64bits). This is done because with 32 bit addresses we would have to compromise on heap size, or have a small number of global values / tables. With 64 bit addresses we do not have to compromise on this, but we need to support 32 bit addresses.
1 parent 67d605d commit a6f7dbd

File tree

11 files changed

+600
-238
lines changed

11 files changed

+600
-238
lines changed

cranelift/codegen/src/ir/trapcode.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ pub enum TrapCode {
2020
/// A store was performed to an unmapped address
2121
OutOfBoundsStore,
2222

23+
/// An operation was performed with an invalid address
24+
InvalidAddress,
25+
2326
/// A `heap_addr` instruction detected an out-of-bounds error.
2427
///
2528
/// Note that not all out-of-bounds heap accesses are reported this way;
@@ -64,6 +67,7 @@ impl Display for TrapCode {
6467
use self::TrapCode::*;
6568
let identifier = match *self {
6669
StackOverflow => "stk_ovf",
70+
InvalidAddress => "invalid_addr",
6771
OutOfBoundsLoad => "oob_load",
6872
OutOfBoundsStore => "oob_store",
6973
HeapOutOfBounds => "heap_oob",
@@ -89,6 +93,7 @@ impl FromStr for TrapCode {
8993
use self::TrapCode::*;
9094
match s {
9195
"stk_ovf" => Ok(StackOverflow),
96+
"invalid_addr" => Ok(InvalidAddress),
9297
"oob_load" => Ok(OutOfBoundsLoad),
9398
"oob_store" => Ok(OutOfBoundsStore),
9499
"heap_oob" => Ok(HeapOutOfBounds),
@@ -113,8 +118,9 @@ mod tests {
113118
use alloc::string::ToString;
114119

115120
// Everything but user-defined codes.
116-
const CODES: [TrapCode; 13] = [
121+
const CODES: [TrapCode; 14] = [
117122
TrapCode::StackOverflow,
123+
TrapCode::InvalidAddress,
118124
TrapCode::OutOfBoundsLoad,
119125
TrapCode::OutOfBoundsStore,
120126
TrapCode::HeapOutOfBounds,
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
test interpret
2+
3+
function %stack_addr_iadd(i64) -> b1 {
4+
ss0 = explicit_slot 16
5+
6+
block0(v0: i64):
7+
v1 = stack_addr.i32 ss0
8+
v2 = iadd_imm.i32 v1, 8
9+
10+
stack_store.i64 v0, ss0+8
11+
v3 = load.i64 v2
12+
13+
v5 = iadd_imm.i64 v0, 20
14+
store.i64 v5, v2
15+
v6 = stack_load.i64 ss0+8
16+
17+
v7 = icmp eq v0, v3
18+
v8 = icmp eq v5, v6
19+
v9 = band v7, v8
20+
return v9
21+
}
22+
; run: %stack_addr_iadd(0) == true
23+
; run: %stack_addr_iadd(1) == true
24+
; run: %stack_addr_iadd(-1) == true
25+
26+
27+
function %stack_addr_32(i64) -> b1 {
28+
ss0 = explicit_slot 24
29+
30+
block0(v0: i64):
31+
v1 = stack_addr.i32 ss0
32+
stack_store.i64 v0, ss0
33+
v2 = load.i64 v1
34+
v3 = icmp eq v0, v2
35+
36+
v4 = stack_addr.i32 ss0+8
37+
store.i64 v0, v4
38+
v5 = stack_load.i64 ss0+8
39+
v6 = icmp eq v0, v5
40+
41+
v7 = stack_addr.i32 ss0+16
42+
store.i64 v0, v7
43+
v8 = load.i64 v7
44+
v9 = icmp eq v0, v8
45+
46+
v10 = band v3, v6
47+
v11 = band v10, v9
48+
return v11
49+
}
50+
; run: %stack_addr_32(0) == true
51+
; run: %stack_addr_32(1) == true
52+
; run: %stack_addr_32(-1) == true
53+
54+
55+
56+
function %addr32_64(i64) -> b1 {
57+
ss0 = explicit_slot 16
58+
59+
block0(v0: i64):
60+
v1 = stack_addr.i32 ss0+8
61+
v2 = stack_addr.i64 ss0+8
62+
63+
store.i64 v0, v1
64+
v3 = load.i64 v2
65+
66+
v4 = icmp eq v3, v0
67+
68+
return v4
69+
}
70+
; run: %addr32_64(0) == true
71+
; run: %addr32_64(1) == true
72+
; run: %addr32_64(-1) == true
73+
74+
75+
function %multi_slot_different_addrs() -> b1 {
76+
ss0 = explicit_slot 8
77+
ss1 = explicit_slot 8
78+
79+
block0:
80+
v0 = stack_addr.i32 ss0
81+
v1 = stack_addr.i32 ss1
82+
v2 = icmp ne v0, v1
83+
return v2
84+
}
85+
; run: %multi_slot_diffe() == true
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
test interpret
2+
test run
3+
target x86_64 machinst
4+
target s390x
5+
target aarch64
6+
7+
8+
function %stack_addr_iadd(i64) -> b1 {
9+
ss0 = explicit_slot 16
10+
11+
block0(v0: i64):
12+
v1 = stack_addr.i64 ss0
13+
v2 = iadd_imm.i64 v1, 8
14+
15+
stack_store.i64 v0, ss0+8
16+
v3 = load.i64 v2
17+
18+
v5 = iadd_imm.i64 v0, 20
19+
store.i64 v5, v2
20+
v6 = stack_load.i64 ss0+8
21+
22+
v7 = icmp eq v0, v3
23+
v8 = icmp eq v5, v6
24+
v9 = band v7, v8
25+
return v9
26+
}
27+
; run: %stack_addr_iadd(0) == true
28+
; run: %stack_addr_iadd(1) == true
29+
; run: %stack_addr_iadd(-1) == true
30+
31+
function %stack_addr_64(i64) -> b1 {
32+
ss0 = explicit_slot 24
33+
34+
block0(v0: i64):
35+
v1 = stack_addr.i64 ss0
36+
stack_store.i64 v0, ss0
37+
v2 = load.i64 v1
38+
v3 = icmp eq v0, v2
39+
40+
v4 = stack_addr.i64 ss0+8
41+
store.i64 v0, v4
42+
v5 = stack_load.i64 ss0+8
43+
v6 = icmp eq v0, v5
44+
45+
v7 = stack_addr.i64 ss0+16
46+
store.i64 v0, v7
47+
v8 = load.i64 v7
48+
v9 = icmp eq v0, v8
49+
50+
v10 = band v3, v6
51+
v11 = band v10, v9
52+
return v11
53+
}
54+
; run: %stack_addr_64(0) == true
55+
; run: %stack_addr_64(1) == true
56+
; run: %stack_addr_64(-1) == true

cranelift/filetests/filetests/runtests/stack.clif

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -55,33 +55,6 @@ block0(v0: i64):
5555
; run: %offset_unaligned(-1) == -1
5656

5757

58-
function %stack_addr(i64) -> b1 {
59-
ss0 = explicit_slot 24
60-
61-
block0(v0: i64):
62-
v1 = stack_addr.i64 ss0
63-
stack_store.i64 v0, ss0
64-
v2 = load.i64 v1
65-
v3 = icmp eq v0, v2
66-
67-
v4 = stack_addr.i64 ss0+8
68-
store.i64 v0, v4
69-
v5 = stack_load.i64 ss0+8
70-
v6 = icmp eq v0, v5
71-
72-
v7 = stack_addr.i64 ss0+16
73-
store.i64 v0, v7
74-
v8 = load.i64 v7
75-
v9 = icmp eq v0, v8
76-
77-
v10 = band v3, v6
78-
v11 = band v10, v9
79-
return v11
80-
}
81-
; run: %stack_addr(0) == true
82-
; run: %stack_addr(1) == true
83-
; run: %stack_addr(-1) == true
84-
8558

8659
function %multi_slot_stack(i64, i64) -> i64 {
8760
ss0 = explicit_slot 8
@@ -99,18 +72,6 @@ block0(v0: i64, v1: i64):
9972
; run: %multi_slot_stack(1, 2) == 3
10073

10174

102-
function %multi_slot_different_addrs() -> b1 {
103-
ss0 = explicit_slot 8
104-
ss1 = explicit_slot 8
105-
106-
block0:
107-
v0 = stack_addr.i64 ss0
108-
v1 = stack_addr.i64 ss1
109-
v2 = icmp ne v0, v1
110-
return v2
111-
}
112-
; run: %multi_slot_diffe() == true
113-
11475

11576
function %multi_slot_out_of_bounds_writes(i8, i64) -> i8, i64 {
11677
ss0 = explicit_slot 1

0 commit comments

Comments
 (0)