Skip to content

Commit 561bd23

Browse files
committed
Add simple weval smoketest.
1 parent 01b4f69 commit 561bd23

File tree

3 files changed

+240
-0
lines changed

3 files changed

+240
-0
lines changed

tests/simple/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.wasm
2+
*.o

tests/simple/Makefile

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
NAME := simple
2+
3+
CC := /opt/wasi-sdk/bin/clang
4+
CXX := /opt/wasi-sdk/bin/clang++
5+
CFLAGS := -I../../include -O2 -g
6+
CXXFLAGS := $(CFLAGS) -std=c++17
7+
WEVAL := ../../target/release/weval
8+
9+
.PHONY: all
10+
all: $(NAME).wasm $(NAME)-wevaled.wasm
11+
12+
$(NAME).wasm: $(NAME).o
13+
$(CXX) $(CXXFLAGS) -o $@ $^
14+
15+
$(NAME)-wevaled.wasm: $(NAME).wasm
16+
$(WEVAL) weval -w -i $^ -o $@
17+
18+
$(NAME).o: $(NAME).cpp ../../include/weval.h
19+
$(CXX) $(CXXFLAGS) -c -o $@ $<
20+
21+
.PHONY: clean
22+
clean:
23+
rm -f $(NAME).wasm $(NAME)-wevaled.wasm *.o
24+
25+
.PHONY: run-base
26+
run-base: $(NAME).wasm
27+
wasmtime run --preload weval=../../lib/weval-stubs.wat $(NAME).wasm
28+
29+
.PHONY: run-wevaled
30+
run-wevaled: $(NAME)-wevaled.wasm
31+
wasmtime run $(NAME)-wevaled.wasm
32+

tests/simple/simple.cpp

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
#include <weval.h>
2+
#include <wizer.h>
3+
#include <stdlib.h>
4+
#include <stdio.h>
5+
6+
WIZER_DEFAULT_INIT();
7+
WEVAL_DEFINE_GLOBALS();
8+
9+
enum Opcode {
10+
PushConst,
11+
Drop,
12+
Dup,
13+
GetLocal,
14+
SetLocal,
15+
Add,
16+
Sub,
17+
Print,
18+
Goto,
19+
GotoIf,
20+
Exit,
21+
};
22+
23+
struct Inst {
24+
Opcode opcode;
25+
uint32_t imm;
26+
27+
explicit Inst(Opcode opcode_) : opcode(opcode_), imm(0) {}
28+
Inst(Opcode opcode_, uint32_t imm_) : opcode(opcode_), imm(imm_) {}
29+
};
30+
31+
#define OPSTACK_SIZE 32
32+
#define LOCAL_SIZE 32
33+
34+
struct State {
35+
uint32_t opstack[OPSTACK_SIZE];
36+
uint32_t locals[LOCAL_SIZE];
37+
};
38+
39+
template<bool Specialized>
40+
bool Interpret(const Inst* insts, uint32_t ninsts, State* state) {
41+
uint32_t pc = 0;
42+
uint32_t steps = 0;
43+
uint32_t* opstack = state->opstack;
44+
uint32_t* locals = state->locals;
45+
int sp = 0;
46+
47+
if (Specialized) {
48+
weval::push_context(pc);
49+
}
50+
while (true) {
51+
steps++;
52+
const Inst* inst = &insts[pc];
53+
pc++;
54+
if (Specialized) {
55+
weval::update_context(pc);
56+
}
57+
switch (inst->opcode) {
58+
case PushConst:
59+
if (sp + 1 > OPSTACK_SIZE) {
60+
return false;
61+
}
62+
opstack[sp++] = inst->imm;
63+
break;
64+
case Drop:
65+
if (sp == 0) {
66+
return false;
67+
}
68+
sp--;
69+
break;
70+
case Dup:
71+
if (sp + 1 > OPSTACK_SIZE) {
72+
return false;
73+
}
74+
if (sp == 0) {
75+
return false;
76+
}
77+
opstack[sp] = opstack[sp - 1];
78+
sp++;
79+
break;
80+
case GetLocal:
81+
if (sp + 1 > OPSTACK_SIZE) {
82+
return false;
83+
}
84+
if (inst->imm >= LOCAL_SIZE) {
85+
return false;
86+
}
87+
opstack[sp++] = locals[inst->imm];
88+
break;
89+
case SetLocal:
90+
if (sp == 0) {
91+
return false;
92+
}
93+
if (inst->imm >= LOCAL_SIZE) {
94+
return false;
95+
}
96+
locals[inst->imm] = opstack[--sp];
97+
break;
98+
case Add:
99+
if (sp < 2) {
100+
return false;
101+
}
102+
opstack[sp - 2] += opstack[sp - 1];
103+
sp--;
104+
break;
105+
case Sub:
106+
if (sp < 2) {
107+
return false;
108+
}
109+
opstack[sp - 2] -= opstack[sp - 1];
110+
sp--;
111+
break;
112+
case Print:
113+
if (sp == 0) {
114+
return false;
115+
}
116+
printf("%u\n", opstack[--sp]);
117+
break;
118+
case Goto:
119+
if (inst->imm >= ninsts) {
120+
return false;
121+
}
122+
pc = inst->imm;
123+
if (Specialized) {
124+
weval::update_context(pc);
125+
}
126+
break;
127+
case GotoIf:
128+
if (sp == 0) {
129+
return false;
130+
}
131+
if (inst->imm >= ninsts) {
132+
return false;
133+
}
134+
sp--;
135+
if (opstack[sp] != 0) {
136+
pc = inst->imm;
137+
if (Specialized) {
138+
weval::update_context(pc);
139+
}
140+
continue;
141+
}
142+
break;
143+
case Exit:
144+
goto out;
145+
}
146+
}
147+
out:
148+
if (Specialized) {
149+
weval::pop_context();
150+
}
151+
152+
printf("Exiting after %d steps at PC %d.\n", steps, pc);
153+
return true;
154+
}
155+
156+
Inst prog[] = {
157+
Inst(PushConst, 0),
158+
Inst(Dup),
159+
Inst(PushConst, 10000000),
160+
Inst(Sub),
161+
Inst(GotoIf, 6),
162+
Inst(Exit),
163+
Inst(PushConst, 1),
164+
Inst(Add),
165+
Inst(Goto, 1),
166+
};
167+
168+
typedef bool (*InterpretFunc)(const Inst* insts, uint32_t ninsts, State* state);
169+
170+
WEVAL_DEFINE_TARGET(1, Interpret<true>);
171+
172+
struct Func {
173+
const Inst* insts;
174+
uint32_t ninsts;
175+
InterpretFunc specialized;
176+
177+
Func(const Inst* insts_, uint32_t ninsts_)
178+
: insts(insts_), ninsts(ninsts_), specialized(nullptr) {
179+
printf("ctor: ptr %p\n", &specialized);
180+
weval::weval(
181+
&specialized,
182+
&Interpret<true>,
183+
1,
184+
0,
185+
weval::SpecializeMemory<const Inst*>(insts, ninsts * sizeof(Inst)),
186+
weval::Specialize(ninsts),
187+
weval::Runtime<State*>());
188+
}
189+
190+
bool invoke(State* state) {
191+
printf("Inspecting func ptr at: %p -> %p (size %lu)\n", &specialized, specialized, sizeof(specialized));
192+
if (specialized) {
193+
printf("Calling specialized function: %p\n", specialized);
194+
return specialized(insts, ninsts, state);
195+
}
196+
return Interpret<false>(insts, ninsts, state);
197+
}
198+
};
199+
200+
Func prog_func(prog, sizeof(prog)/sizeof(Inst));
201+
202+
int main(int argc, char** argv) {
203+
State* state = (State*)calloc(sizeof(State), 1);
204+
prog_func.invoke(state);
205+
fflush(stdout);
206+
}

0 commit comments

Comments
 (0)