Skip to content

Commit 099a711

Browse files
Fix call indirect (#96)
1 parent 8b2eff1 commit 099a711

File tree

4 files changed

+197
-57
lines changed

4 files changed

+197
-57
lines changed

benchmarks/wasm/call_indirect_test.wat

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
(type (;1;) (func (param i32 i32) (result i32)))
44
(type (;2;) (func (result i32)))
55
(func (;0;) (type 0) (param i32) (result i32)
6+
(local i32 i32 i32 i32 i32)
7+
local.get 3
8+
drop
69
local.get 0
710
i32.const 1
811
i32.add)

headers/wasm/concrete_rt.hpp

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "concrete_num.hpp"
55
#include "controls.hpp"
6+
#include "immer/vector_transient.hpp"
67
#include "wasm/profile.hpp"
78
#include "wasm/utils.hpp"
89
#include <cassert>
@@ -49,8 +50,8 @@ class Stack_t {
4950

5051
Num pop() {
5152
Profile.step(StepProfileKind::POP);
52-
#ifdef DEBUG
5353
assert(count > 0 && "Stack underflow");
54+
#ifdef DEBUG
5455
printf("[Debug] popping a value %ld from stack, size of concrete stack is: "
5556
"%d\n",
5657
stack_ptr[count - 1].value, count);
@@ -123,45 +124,86 @@ class Stack_t {
123124
Num *stack_ptr;
124125
};
125126
static Stack_t Stack;
127+
class SymFrames_t;
126128

127129
const int FRAME_SIZE = 1024 * 8;
128130
class Frames_t {
129131
public:
130-
Frames_t() : count(0), stack_ptr(new Num[FRAME_SIZE]) {
132+
Frames_t() : count(0), stack_ptr(new Num[FRAME_SIZE]), frame_ptrs() {
131133
size_t page_size = (size_t)sysconf(_SC_PAGESIZE);
132134
// pre touch the memory to avoid page faults during execution
133135
for (int i = 0; i < FRAME_SIZE; i += page_size) {
134136
stack_ptr[i] = Num(0);
135137
}
136138
}
137139

138-
std::monostate popFrame(std::int32_t size) {
140+
std::monostate popFrameCaller(std::int32_t size) {
141+
assert(size >= 0);
142+
assert(size <= count);
143+
assert(!frame_ptrs.empty());
144+
auto frame_base = current_frame_base();
145+
assert(frame_base + size == count);
146+
count -= size;
147+
#ifdef USE_IMM
148+
frame_ptrs.take(frame_ptrs.size() - 1);
149+
#else
150+
frame_ptrs.pop_back();
151+
#endif
152+
return std::monostate{};
153+
}
154+
155+
std::monostate popFrameCallee(std::int32_t size) {
139156
assert(size >= 0);
157+
assert(size <= count);
140158
count -= size;
141159
return std::monostate{};
142160
}
143161

144162
Num get(std::int32_t index) {
163+
assert(!frame_ptrs.empty() && "No active frame");
164+
auto frame_base = current_frame_base();
165+
assert(index >= 0 && frame_base + index < count && "Index out of bounds");
145166
Profile.step(StepProfileKind::GET);
146-
auto ret = stack_ptr[count - 1 - index];
167+
auto ret = stack_ptr[frame_base + index];
147168
return ret;
148169
}
149170

150171
void set(std::int32_t index, Num num) {
172+
assert(!frame_ptrs.empty() && "No active frame");
173+
auto frame_base = current_frame_base();
174+
assert(index >= 0 && frame_base + index < count && "Index out of bounds");
151175
Profile.step(StepProfileKind::SET);
152-
stack_ptr[count - 1 - index] = num;
176+
stack_ptr[frame_base + index] = num;
153177
}
154178

155-
void pushFrame(std::int32_t size) {
179+
void pushFrameCaller(std::int32_t size) {
156180
assert(size >= 0);
181+
frame_ptrs.push_back(count);
157182
count += size;
158183
// Zero-initialize the new stack frames.
159184
for (std::int32_t i = 0; i < size; ++i) {
160-
stack_ptr[count - 1 - i] = Num(0);
185+
stack_ptr[count - size + i] = Num(0);
161186
}
162187
}
163188

164-
void reset() { count = 0; }
189+
void pushFrameCallee(std::int32_t size) {
190+
assert(size >= 0);
191+
assert(!frame_ptrs.empty() && "No active frame");
192+
auto old_count = count;
193+
count += size;
194+
for (std::int32_t i = 0; i < size; ++i) {
195+
stack_ptr[old_count + i] = Num(0);
196+
}
197+
}
198+
199+
void reset() {
200+
count = 0;
201+
#ifdef USE_IMM
202+
frame_ptrs = immer::vector_transient<size_t>();
203+
#else
204+
frame_ptrs.clear();
205+
#endif
206+
}
165207

166208
size_t size() const { return count; }
167209

@@ -176,8 +218,23 @@ class Frames_t {
176218
}
177219

178220
private:
221+
friend class SymFrames_t;
222+
223+
size_t current_frame_base() const {
224+
#ifdef USE_IMM
225+
return *(frame_ptrs.end() - 1);
226+
#else
227+
return frame_ptrs.back();
228+
#endif
229+
}
230+
179231
int32_t count;
180232
Num *stack_ptr;
233+
#ifdef USE_IMM
234+
immer::vector_transient<size_t> frame_ptrs;
235+
#else
236+
std::vector<size_t> frame_ptrs;
237+
#endif
181238
};
182239

183240
static Frames_t Frames;
@@ -319,4 +376,4 @@ struct FuncTable_t {
319376

320377
static FuncTable_t FuncTable;
321378

322-
#endif // WASM_CONCRETE_RT_HPP
379+
#endif // WASM_CONCRETE_RT_HPP

headers/wasm/sym_rt.hpp

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
#include "immer/vector.hpp"
1111
#include "immer/vector_transient.hpp"
1212
#include "profile.hpp"
13+
#include "symbolic_decl.hpp"
14+
#include "symbolic_impl.hpp"
1315
#include "symval_decl.hpp"
1416
#include "symval_factory.hpp"
1517
#include "symval_impl.hpp"
16-
#include "symbolic_decl.hpp"
17-
#include "symbolic_impl.hpp"
1818
#include "utils.hpp"
1919
#include "wasm/concrete_num.hpp"
2020
#include "wasm/z3_env.hpp"
@@ -35,7 +35,6 @@
3535
#include <variant>
3636
#include <vector>
3737

38-
3938
class Snapshot_t;
4039

4140
class SymStack_t {
@@ -125,6 +124,16 @@ static SymStack_t SymStack;
125124
class SymFrames_t {
126125

127126
public:
127+
void restore_frame_ptr(Frames_t &frame) const;
128+
129+
void pushFramePtr() {
130+
#ifdef USE_IMM
131+
frame_ptrs.push_back(stack.size());
132+
#else
133+
frame_ptrs.push_back(stack.size());
134+
#endif
135+
}
136+
128137
void pushFrameSlot(int width) {
129138
#ifdef USE_IMM
130139
stack.push_back(SVFactory::make_concrete_bv(I64V(0), width));
@@ -133,7 +142,33 @@ class SymFrames_t {
133142
#endif
134143
}
135144

136-
std::monostate popFrame(int size) {
145+
std::monostate popFrameCaller(int size) {
146+
assert(size >= 0);
147+
assert(static_cast<size_t>(size) <= stack.size());
148+
assert(!frame_ptrs.empty());
149+
auto frame_base = current_frame_base();
150+
assert(frame_base + size == stack.size());
151+
152+
for (int i = 0; i < size; ++i) {
153+
symbolic_size -= stack[stack.size() - 1 - i]->size();
154+
}
155+
156+
#ifdef USE_IMM
157+
stack.take(stack.size() - size);
158+
#else
159+
stack.erase(stack.end() - size, stack.end());
160+
#endif
161+
162+
#ifdef USE_IMM
163+
frame_ptrs.take(frame_ptrs.size() - 1);
164+
#else
165+
frame_ptrs.pop_back();
166+
#endif
167+
168+
return std::monostate{};
169+
}
170+
171+
std::monostate popFrameCallee(int size) {
137172
// Pop the frame of the given size
138173
assert(size >= 0);
139174
assert(static_cast<size_t>(size) <= stack.size());
@@ -153,18 +188,26 @@ class SymFrames_t {
153188

154189
SymVal get(int index) {
155190
// Get the symbolic value at the given frame index
156-
auto res = stack[stack.size() - 1 - index];
191+
assert(!frame_ptrs.empty());
192+
auto frame_base = current_frame_base();
193+
assert(index >= 0 &&
194+
static_cast<size_t>(frame_base + index) < stack.size());
195+
auto res = stack[frame_base + index];
157196
return res;
158197
}
159198

160199
void set(int index, SymVal val) {
161200
// Set the symbolic value at the given index
162201
assert(val.symptr != nullptr);
163-
symbolic_size += val->size() - stack[stack.size() - 1 - index]->size();
202+
assert(!frame_ptrs.empty());
203+
auto frame_base = current_frame_base();
204+
assert(index >= 0 &&
205+
static_cast<size_t>(frame_base + index) < stack.size());
206+
symbolic_size += val->size() - stack[frame_base + index]->size();
164207
#ifdef USE_IMM
165-
stack.set(stack.size() - 1 - index, val);
208+
stack.set(frame_base + index, val);
166209
#else
167-
stack[stack.size() - 1 - index] = val;
210+
stack[frame_base + index] = val;
168211
#endif
169212
}
170213

@@ -173,8 +216,10 @@ class SymFrames_t {
173216

174217
#ifdef USE_IMM
175218
stack = immer::vector_transient<SymVal>();
219+
frame_ptrs = immer::vector_transient<size_t>();
176220
#else
177221
stack.clear();
222+
frame_ptrs.clear();
178223
#endif
179224
symbolic_size = 0;
180225
}
@@ -193,10 +238,20 @@ class SymFrames_t {
193238
}
194239

195240
private:
241+
size_t current_frame_base() const {
242+
#ifdef USE_IMM
243+
return *(frame_ptrs.end() - 1);
244+
#else
245+
return frame_ptrs.back();
246+
#endif
247+
}
248+
196249
int symbolic_size = 0;
197250
#ifdef USE_IMM
251+
immer::vector_transient<size_t> frame_ptrs;
198252
immer::vector_transient<SymVal> stack;
199253
#else
254+
std::vector<size_t> frame_ptrs;
200255
std::vector<SymVal> stack;
201256
#endif
202257
};
@@ -324,6 +379,10 @@ class SymMemory_t {
324379
}
325380
};
326381

382+
inline void SymFrames_t::restore_frame_ptr(Frames_t &frame) const {
383+
frame.frame_ptrs = frame_ptrs;
384+
}
385+
327386
static SymMemory_t SymMemory;
328387

329388
static std::monostate memoryInitialize(int32_t offset,
@@ -1563,6 +1622,7 @@ static void resume_conc_frames(const SymFrames_t &sym_frame, Frames_t &frames,
15631622
auto conc = res.value;
15641623
frames.set_from_front(i, conc);
15651624
}
1625+
sym_frame.restore_frame_ptr(frames);
15661626
}
15671627

15681628
static void resume_conc_frames_by_model(const SymFrames_t &sym_frame,
@@ -1576,6 +1636,7 @@ static void resume_conc_frames_by_model(const SymFrames_t &sym_frame,
15761636
auto conc = res.value;
15771637
frames.set_from_front(i, conc);
15781638
}
1639+
sym_frame.restore_frame_ptr(frames);
15791640
}
15801641

15811642
static void resume_conc_memory(const SymMemory_t &sym_memory, Memory_t &memory,

0 commit comments

Comments
 (0)