Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Interpreter/instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ bool i_instr_if(Module *m, uint8_t *block_ptr) {
sprintf(exception, "call stack exhausted");
return false;
}
uint32_t cond = m->stack[m->sp--].value.uint32;
m->warduino->interpreter->push_block(m, block, m->sp);

uint32_t cond = m->stack[m->sp--].value.uint32;
if (cond == 0) { // if false (I32)
// branch to else block or after end of if
if (block->else_ptr == nullptr) {
Expand Down
16 changes: 8 additions & 8 deletions src/Interpreter/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,20 @@ Block *Interpreter::pop_block(Module *m) {
m->fp = frame->fp; // Restore frame pointer

// Validate the return value
if (t->result_count == 1) {
if (m->stack[m->sp].value_type != t->results[0]) {
for (uint32_t i = 0; i < t->result_count; i++) {
if (m->stack[m->sp - (t->result_count - 1 - i)].value_type !=
t->results[i]) {
sprintf(exception, "call type mismatch");
return nullptr;
}
}

// Restore stack pointer
if (t->result_count == 1) {
// Save top value as result
if (frame->sp < m->sp) {
m->stack[frame->sp + 1] = m->stack[m->sp];
m->sp = frame->sp + 1;
if (t->result_count > 0) {
for (uint32_t i = 0; i < t->result_count; i++) {
m->stack[frame->sp + 1 + i] =
m->stack[m->sp - (t->result_count - 1) + i];
}
m->sp = frame->sp + t->result_count;
} else {
if (frame->sp < m->sp) {
m->sp = frame->sp;
Expand Down
4 changes: 3 additions & 1 deletion src/WARDuino.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ class WARDuino {
void update_module(Module *old_module, uint8_t *wasm, uint32_t wasm_len);

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

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

Expand Down
77 changes: 57 additions & 20 deletions src/WARDuino/WARDuino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,33 @@ void initTypes() {
block_types[4].results = block_type_results[3];
}

Type *get_block_type(uint8_t value_type) {
switch (value_type) {
case 0x40:
return &block_types[0];
case I32:
return &block_types[1];
case I64:
return &block_types[2];
case F32:
return &block_types[3];
case F64:
return &block_types[4];
default:
FATAL("invalid block_type value_type: %d\n", value_type);
Type *get_block_type(Module *m, uint8_t type) {
uint8_t *pos = &type;
int64_t type_s = read_LEB_signed(&pos, 33);

if (type_s < 0) {
switch (type) {
case 0x40:
return &block_types[0]; // empty
case I32:
return &block_types[1];
case I64:
return &block_types[2];
case F32:
return &block_types[3];
case F64:
return &block_types[4];
default:
FATAL("invalid block_type value_type: %d\n", type);
return nullptr;
}
} else {
if ((uint32_t)type_s >= m->type_count) {
FATAL("block_type index out of bounds: %lld >= %u\n",
(long long)type_s, (unsigned int)m->type_count);
return nullptr;
}
return &m->types[type_s];
}
}

Expand Down Expand Up @@ -215,7 +227,7 @@ void find_blocks(Module *m) {
case 0x04: // if
block = (Block *)acalloc(1, sizeof(Block), "Block");
block->block_type = opcode;
block->type = get_block_type(*(pos + 1));
block->type = get_block_type(m, *(pos + 1));
block->start_ptr = pos;
blockstack[++top] = block;
m->block_lookup[pos] = block;
Expand Down Expand Up @@ -261,7 +273,7 @@ void WARDuino::run_init_expr(Module *m, uint8_t type, uint8_t **pc) {
WARDuino::instance()->program_state = WARDUINOinit;
Block block;
block.block_type = 0x01;
block.type = get_block_type(type);
block.type = get_block_type(m, type);
block.start_ptr = *pc;

m->pc_ptr = *pc;
Expand Down Expand Up @@ -900,7 +912,8 @@ WARDuino::WARDuino() {

// Return value of false means exception occurred
bool WARDuino::invoke(Module *m, uint32_t fidx, uint32_t arity,
StackValue *args) {
StackValue *args, uint32_t max_results,
StackValue *out_results, uint32_t *out_result_count) {
bool result;
m->sp = -1;
m->fp = -1;
Expand All @@ -918,7 +931,25 @@ bool WARDuino::invoke(Module *m, uint32_t fidx, uint32_t arity,
result = interpreter->interpret(m);
dbg_trace("Interpretation ended\n");
dbg_dump_stack(m);
return result;

if (!result) {
if (out_result_count) *out_result_count = 0;
return false;
}

uint32_t rescount = 0;
Type *ftype = m->functions[fidx].type;
rescount = ftype->result_count;

if (out_result_count) {
*out_result_count = rescount > max_results ? max_results : rescount;

for (uint32_t i = 0; i < *out_result_count; ++i) {
out_results[i] = m->stack[m->sp - (rescount - 1) + i];
}
}

return true;
}

void WARDuino::setInterpreter(Interpreter *interpreter) {
Expand All @@ -930,9 +961,15 @@ int WARDuino::run_module(Module *m) {

// execute main
if (fidx != UNDEF) {
this->invoke(m, fidx);
return m->stack->value.uint32;
StackValue outputs[8];
uint32_t out_count = 0;
bool ok = this->invoke(m, fidx, 0, nullptr, 8, outputs, &out_count);
if (!ok) {
return 0;
}
return (int)outputs[0].value.uint32;
}
fflush(stdout);

// wait
m->warduino->debugger->pauseRuntime(m);
Expand Down