Skip to content

Commit 0b7919a

Browse files
committed
feat: multivalue
1 parent 4b3bc2c commit 0b7919a

File tree

4 files changed

+67
-31
lines changed

4 files changed

+67
-31
lines changed

src/Interpreter/instructions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ bool i_instr_if(Module *m, uint8_t *block_ptr) {
130130
sprintf(exception, "call stack exhausted");
131131
return false;
132132
}
133+
uint32_t cond = m->stack[m->sp--].value.uint32;
133134
m->warduino->interpreter->push_block(m, block, m->sp);
134135

135-
uint32_t cond = m->stack[m->sp--].value.uint32;
136136
if (cond == 0) { // if false (I32)
137137
// branch to else block or after end of if
138138
if (block->else_ptr == nullptr) {

src/Interpreter/interpreter.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,18 @@ Block *Interpreter::pop_block(Module *m) {
4545
m->fp = frame->fp; // Restore frame pointer
4646

4747
// Validate the return value
48-
if (t->result_count == 1) {
49-
if (m->stack[m->sp].value_type != t->results[0]) {
48+
for (uint32_t i = 0; i < t->result_count; i++) {
49+
if (m->stack[m->sp - (t->result_count - 1 - i)].value_type != t->results[i]) {
5050
sprintf(exception, "call type mismatch");
5151
return nullptr;
5252
}
5353
}
54-
5554
// Restore stack pointer
56-
if (t->result_count == 1) {
57-
// Save top value as result
58-
if (frame->sp < m->sp) {
59-
m->stack[frame->sp + 1] = m->stack[m->sp];
60-
m->sp = frame->sp + 1;
55+
if (t->result_count > 0) {
56+
for (uint32_t i = 0; i < t->result_count; i++) {
57+
m->stack[frame->sp + 1 + i] = m->stack[m->sp - (t->result_count - 1) + i];
6158
}
59+
m->sp = frame->sp + t->result_count;
6260
} else {
6361
if (frame->sp < m->sp) {
6462
m->sp = frame->sp;

src/WARDuino.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class WARDuino {
108108
void update_module(Module *old_module, uint8_t *wasm, uint32_t wasm_len);
109109

110110
bool invoke(Module *m, uint32_t fidx, uint32_t arity = 0,
111-
StackValue *args = nullptr);
111+
StackValue *args = nullptr, uint32_t max_results = 0, StackValue *out_results = nullptr, uint32_t *out_result_count = nullptr);
112112

113113
uint32_t get_export_fidx(Module *m, const char *name);
114114

src/WARDuino/WARDuino.cpp

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -74,24 +74,37 @@ void initTypes() {
7474
block_types[4].results = block_type_results[3];
7575
}
7676

77-
Type *get_block_type(uint8_t value_type) {
78-
switch (value_type) {
79-
case 0x40:
80-
return &block_types[0];
81-
case I32:
82-
return &block_types[1];
83-
case I64:
84-
return &block_types[2];
85-
case F32:
86-
return &block_types[3];
87-
case F64:
88-
return &block_types[4];
89-
default:
90-
FATAL("invalid block_type value_type: %d\n", value_type);
77+
Type *get_block_type(Module *m, uint8_t type) {
78+
uint8_t *pos = &type;
79+
int64_t type_s = read_LEB_signed(&pos, 33);
80+
81+
if (type_s < 0) {
82+
switch (type) {
83+
case 0x40:
84+
return &block_types[0]; // empty
85+
case I32:
86+
return &block_types[1];
87+
case I64:
88+
return &block_types[2];
89+
case F32:
90+
return &block_types[3];
91+
case F64:
92+
return &block_types[4];
93+
default:
94+
FATAL("invalid block_type value_type: %d\n", type);
95+
return nullptr;
96+
}
97+
} else {
98+
if ((uint32_t)type_s >= m->type_count) {
99+
FATAL("block_type index out of bounds: %lld >= %u\n",
100+
type_s, m->type_count);
91101
return nullptr;
102+
}
103+
return &m->types[type_s];
92104
}
93105
}
94106

107+
95108
// TODO: calculate this while parsing types
96109
uint64_t get_type_mask(Type *type) {
97110
uint64_t mask = 0x80;
@@ -215,7 +228,7 @@ void find_blocks(Module *m) {
215228
case 0x04: // if
216229
block = (Block *)acalloc(1, sizeof(Block), "Block");
217230
block->block_type = opcode;
218-
block->type = get_block_type(*(pos + 1));
231+
block->type = get_block_type(m, *(pos + 1));
219232
block->start_ptr = pos;
220233
blockstack[++top] = block;
221234
m->block_lookup[pos] = block;
@@ -261,7 +274,7 @@ void WARDuino::run_init_expr(Module *m, uint8_t type, uint8_t **pc) {
261274
WARDuino::instance()->program_state = WARDUINOinit;
262275
Block block;
263276
block.block_type = 0x01;
264-
block.type = get_block_type(type);
277+
block.type = get_block_type(m, type);
265278
block.start_ptr = *pc;
266279

267280
m->pc_ptr = *pc;
@@ -899,8 +912,7 @@ WARDuino::WARDuino() {
899912
}
900913

901914
// Return value of false means exception occurred
902-
bool WARDuino::invoke(Module *m, uint32_t fidx, uint32_t arity,
903-
StackValue *args) {
915+
bool WARDuino::invoke(Module *m, uint32_t fidx, uint32_t arity, StackValue *args, uint32_t max_results, StackValue *out_results, uint32_t *out_result_count) {
904916
bool result;
905917
m->sp = -1;
906918
m->fp = -1;
@@ -918,9 +930,29 @@ bool WARDuino::invoke(Module *m, uint32_t fidx, uint32_t arity,
918930
result = interpreter->interpret(m);
919931
dbg_trace("Interpretation ended\n");
920932
dbg_dump_stack(m);
921-
return result;
933+
934+
if (!result) {
935+
if (out_result_count) *out_result_count = 0;
936+
return false;
937+
}
938+
939+
uint32_t rescount = 0;
940+
Type *ftype = m->functions[fidx].type;
941+
rescount = ftype->result_count;
942+
943+
if (out_result_count)
944+
{
945+
*out_result_count = rescount > max_results ? max_results : rescount;
946+
947+
for (uint32_t i = 0; i < *out_result_count; ++i) {
948+
out_results[i] = m->stack[m->sp - (rescount - 1) + i];
949+
}
950+
}
951+
952+
return true;
922953
}
923954

955+
924956
void WARDuino::setInterpreter(Interpreter *interpreter) {
925957
this->interpreter = interpreter;
926958
}
@@ -930,9 +962,15 @@ int WARDuino::run_module(Module *m) {
930962

931963
// execute main
932964
if (fidx != UNDEF) {
933-
this->invoke(m, fidx);
934-
return m->stack->value.uint32;
965+
StackValue outputs[8];
966+
uint32_t out_count = 0;
967+
bool ok = this->invoke(m, fidx, 0, nullptr, 8, outputs, &out_count);
968+
if (!ok) {
969+
return 0;
970+
}
971+
return (int)outputs[0].value.uint32;
935972
}
973+
fflush(stdout);
936974

937975
// wait
938976
m->warduino->debugger->pauseRuntime(m);

0 commit comments

Comments
 (0)