Skip to content

Commit 065190f

Browse files
afonso360abrown
authored andcommitted
cranelift: Implement br_table on the interpreter
1 parent ebbe399 commit 065190f

File tree

4 files changed

+181
-4
lines changed

4 files changed

+181
-4
lines changed
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
test interpret
2+
test run
3+
target aarch64
4+
target s390x
5+
6+
7+
function %br_table_i8(i8) -> i8 {
8+
jt0 = jump_table [block1, block2, block2, block3]
9+
10+
block0(v0: i8):
11+
br_table v0, block4, jt0
12+
13+
block1:
14+
v1 = iconst.i8 1
15+
jump block5(v1)
16+
17+
block2:
18+
v2 = iconst.i8 2
19+
jump block5(v2)
20+
21+
block3:
22+
v3 = iconst.i8 3
23+
jump block5(v3)
24+
25+
block4:
26+
v4 = iconst.i8 4
27+
jump block5(v4)
28+
29+
block5(v5: i8):
30+
v6 = iadd.i8 v0, v5
31+
return v6
32+
}
33+
; run: %br_table_i8(0) == 1
34+
; run: %br_table_i8(1) == 3
35+
; run: %br_table_i8(2) == 4
36+
; run: %br_table_i8(3) == 6
37+
; run: %br_table_i8(4) == 8
38+
; run: %br_table_i8(5) == 9
39+
; run: %br_table_i8(6) == 10
40+
; run: %br_table_i8(-1) == 3
41+
42+
43+
function %br_table_i16(i16) -> i16 {
44+
jt0 = jump_table [block1, block2, block2, block3]
45+
46+
block0(v0: i16):
47+
br_table v0, block4, jt0
48+
49+
block1:
50+
v1 = iconst.i16 1
51+
jump block5(v1)
52+
53+
block2:
54+
v2 = iconst.i16 2
55+
jump block5(v2)
56+
57+
block3:
58+
v3 = iconst.i16 3
59+
jump block5(v3)
60+
61+
block4:
62+
v4 = iconst.i16 4
63+
jump block5(v4)
64+
65+
block5(v5: i16):
66+
v6 = iadd.i16 v0, v5
67+
return v6
68+
}
69+
; run: %br_table_i16(0) == 1
70+
; run: %br_table_i16(1) == 3
71+
; run: %br_table_i16(2) == 4
72+
; run: %br_table_i16(3) == 6
73+
; run: %br_table_i16(4) == 8
74+
; run: %br_table_i16(5) == 9
75+
; run: %br_table_i16(6) == 10
76+
; run: %br_table_i16(-1) == 3
77+
78+
79+
function %br_table_i32(i32) -> i32 {
80+
jt0 = jump_table [block1, block2, block2, block3]
81+
82+
block0(v0: i32):
83+
br_table v0, block4, jt0
84+
85+
block1:
86+
v1 = iconst.i32 1
87+
jump block5(v1)
88+
89+
block2:
90+
v2 = iconst.i32 2
91+
jump block5(v2)
92+
93+
block3:
94+
v3 = iconst.i32 3
95+
jump block5(v3)
96+
97+
block4:
98+
v4 = iconst.i32 4
99+
jump block5(v4)
100+
101+
block5(v5: i32):
102+
v6 = iadd.i32 v0, v5
103+
return v6
104+
}
105+
; run: %br_table_i32(0) == 1
106+
; run: %br_table_i32(1) == 3
107+
; run: %br_table_i32(2) == 4
108+
; run: %br_table_i32(3) == 6
109+
; run: %br_table_i32(4) == 8
110+
; run: %br_table_i32(5) == 9
111+
; run: %br_table_i32(6) == 10
112+
; run: %br_table_i32(-1) == 3
113+
114+
115+
function %br_table_i64(i64) -> i64 {
116+
jt0 = jump_table [block1, block2, block2, block3]
117+
118+
block0(v0: i64):
119+
br_table v0, block4, jt0
120+
121+
block1:
122+
v1 = iconst.i64 1
123+
jump block5(v1)
124+
125+
block2:
126+
v2 = iconst.i64 2
127+
jump block5(v2)
128+
129+
block3:
130+
v3 = iconst.i64 3
131+
jump block5(v3)
132+
133+
block4:
134+
v4 = iconst.i64 4
135+
jump block5(v4)
136+
137+
block5(v5: i64):
138+
v6 = iadd.i64 v0, v5
139+
return v6
140+
}
141+
; run: %br_table_i64(0) == 1
142+
; run: %br_table_i64(1) == 3
143+
; run: %br_table_i64(2) == 4
144+
; run: %br_table_i64(3) == 6
145+
; run: %br_table_i64(4) == 8
146+
; run: %br_table_i64(5) == 9
147+
; run: %br_table_i64(6) == 10
148+
; run: %br_table_i64(-1) == 3

cranelift/interpreter/src/interpreter.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ impl<'a> State<'a, DataValue> for InterpreterState<'a> {
217217
self.functions
218218
.get_from_func_ref(func_ref, self.frame_stack.last().unwrap().function)
219219
}
220+
fn get_current_function(&self) -> &'a Function {
221+
self.current_frame().function
222+
}
223+
220224
fn push_frame(&mut self, function: &'a Function) {
221225
self.frame_stack.push(Frame::new(function));
222226
}

cranelift/interpreter/src/state.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ use thiserror::Error;
1919
pub trait State<'a, V> {
2020
/// Retrieve a reference to a [Function].
2121
fn get_function(&self, func_ref: FuncRef) -> Option<&'a Function>;
22+
/// Retrieve a reference to the currently executing [Function].
23+
fn get_current_function(&self) -> &'a Function;
2224
/// Record that an interpreter has called into a new [Function].
2325
fn push_frame(&mut self, function: &'a Function);
2426
/// Record that an interpreter has returned from a called [Function].
@@ -92,6 +94,10 @@ where
9294
None
9395
}
9496

97+
fn get_current_function(&self) -> &'a Function {
98+
unimplemented!()
99+
}
100+
95101
fn push_frame(&mut self, _function: &'a Function) {
96102
unimplemented!()
97103
}

cranelift/interpreter/src/step.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use cranelift_codegen::ir::{
99
};
1010
use log::trace;
1111
use smallvec::{smallvec, SmallVec};
12+
use std::convert::TryFrom;
1213
use std::ops::RangeFrom;
1314
use thiserror::Error;
1415

@@ -155,10 +156,25 @@ where
155156
Opcode::BrIcmp => branch_when(icmp(inst.cond_code().unwrap(), &arg(0)?, &arg(1)?)?)?,
156157
Opcode::Brif => branch_when(state.has_iflag(inst.cond_code().unwrap()))?,
157158
Opcode::Brff => branch_when(state.has_fflag(inst.fp_cond_code().unwrap()))?,
158-
Opcode::BrTable => unimplemented!("BrTable"),
159-
Opcode::JumpTableEntry => unimplemented!("JumpTableEntry"),
160-
Opcode::JumpTableBase => unimplemented!("JumpTableBase"),
161-
Opcode::IndirectJumpTableBr => unimplemented!("IndirectJumpTableBr"),
159+
Opcode::BrTable => {
160+
if let InstructionData::BranchTable {
161+
table, destination, ..
162+
} = inst
163+
{
164+
let jt_data = &state.get_current_function().jump_tables[table];
165+
166+
// Convert to usize to remove negative indexes from the following operations
167+
let jump_target = usize::try_from(arg(0)?.into_int()?)
168+
.ok()
169+
.and_then(|i| jt_data.as_slice().get(i))
170+
.copied()
171+
.unwrap_or(destination);
172+
173+
ControlFlow::ContinueAt(jump_target, SmallVec::new())
174+
} else {
175+
unreachable!()
176+
}
177+
}
162178
Opcode::Trap => ControlFlow::Trap(CraneliftTrap::User(trap_code())),
163179
Opcode::Debugtrap => ControlFlow::Trap(CraneliftTrap::Debug),
164180
Opcode::ResumableTrap => ControlFlow::Trap(CraneliftTrap::Resumable),
@@ -632,6 +648,9 @@ where
632648
| Opcode::X86Palignr
633649
| Opcode::X86ElfTlsGetAddr
634650
| Opcode::X86MachoTlsGetAddr => unimplemented!("x86 instruction: {}", inst.opcode()),
651+
Opcode::JumpTableBase | Opcode::JumpTableEntry | Opcode::IndirectJumpTableBr => {
652+
unimplemented!("Legacy instruction: {}", inst.opcode())
653+
}
635654
})
636655
}
637656

0 commit comments

Comments
 (0)