Skip to content
Open
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
7 changes: 4 additions & 3 deletions src/Debug/debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#endif

#include "../Memory/mem.h"
#include "../Primitives/primitives.h"
#include "../Utils//util.h"
#include "../Utils/macros.h"
#include "../WARDuino/CallbackHandler.h"
Expand Down Expand Up @@ -922,7 +921,8 @@ void Debugger::inspect(Module *m, const uint16_t sizeStateArray,
this->channel->write("%s", addComma ? "," : "");
this->channel->write("\"io\": [");
bool comma = false;
std::vector<IOStateElement *> external_state = get_io_state(m);
std::vector<IOStateElement *> external_state =
m->warduino->interpreter->get_io_state(m);
for (auto state_elem : external_state) {
this->channel->write("%s{", comma ? ", " : "");
this->channel->write(
Expand Down Expand Up @@ -1383,7 +1383,8 @@ bool Debugger::saveState(Module *m, uint8_t *interruptData) {
state_elem.output ? "output" : "input",
state_elem.value);
}
restore_external_state(m, external_state);
m->warduino->interpreter->restore_external_state(
m, external_state);
break;
}
case overridesState: {
Expand Down
57 changes: 57 additions & 0 deletions src/Interpreter/interpreter.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#pragma once

#include <cstdint>
#include <cstring>
#include <set>

#include "../Utils/macros.h"
#include "../WARDuino/internals.h"

class Interpreter {
Expand Down Expand Up @@ -54,6 +57,60 @@ class Interpreter {

static void report_overflow(Module *m, uint8_t *maddr);

void register_primitive(const PrimitiveEntry &entry) {
primitives.push_back(entry);
}

//------------------------------------------------------
// resolving the primitives
//------------------------------------------------------
// ReSharper disable once CppDFAConstantFunctionResult
bool resolve_primitive(const char *symbol, Primitive *val) {
debug("Resolve primitive %s\n", symbol);

for (auto &primitive : primitives) {
// printf("Checking %s = %s \n", symbol, primitive.name);
if (!strcmp(symbol, primitive.name)) {
debug("FOUND PRIMITIVE\n");
*val = primitive.f;
return true;
}
}
FATAL("Could not find primitive %s \n", symbol);
return false; // unreachable
}

//------------------------------------------------------
// Restore external state when restoring a snapshot
//------------------------------------------------------
void restore_external_state(
Module *m, const std::vector<IOStateElement> &external_state) {
std::set<std::string> prim_names;
for (uint32_t i = 0; i < m->import_count; i++) {
prim_names.emplace(m->functions[i].import_field);
}

for (PrimitiveEntry &p : primitives) {
if (prim_names.find(p.name) != prim_names.end()) {
if (p.f_reverse) {
dbg_info("Reversing state for primitive %s\n", p.name);
p.f_reverse(m, external_state);
}
}
}
}

std::vector<IOStateElement *> get_io_state(Module *) const {
std::vector<IOStateElement *> ioState;
for (auto &primitive : primitives) {
if (primitive.f_serialize_state) {
primitive.f_serialize_state(ioState);
}
}
return ioState;
}

protected:
private:
std::vector<PrimitiveEntry> primitives;
};
257 changes: 2 additions & 255 deletions src/Primitives/arduino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,199 +129,6 @@ int resolve_isr(int pin) {
return -1;
}

// Primitives

#define NUM_PRIMITIVES 0
#define NUM_PRIMITIVES_ARDUINO 38

#define ALL_PRIMITIVES (NUM_PRIMITIVES + NUM_PRIMITIVES_ARDUINO)

// Global index for installing primitives
int prim_index = 0;

/*
Private macros to install a primitive
*/
#define install_primitive(prim_name) \
{ \
dbg_info("installing primitive number: %d of %d with name: %s\n", \
prim_index + 1, ALL_PRIMITIVES, #prim_name); \
if (prim_index < ALL_PRIMITIVES) { \
PrimitiveEntry *p = &primitives[prim_index++]; \
p->name = #prim_name; \
p->t = &(prim_name##_type); \
p->f = &(prim_name); \
p->f_reverse = nullptr; \
p->f_serialize_state = nullptr; \
} else { \
FATAL("prim_index out of bounds"); \
} \
}

#define install_primitive_reverse(prim_name) \
{ \
PrimitiveEntry *p = &primitives[prim_index - 1]; \
p->f_reverse = &(prim_name##_reverse); \
p->f_serialize_state = &(prim_name##_serialize); \
}

#define def_prim(function_name, type) \
Type function_name##_type = type; \
bool function_name(Module *m)

#define def_prim_reverse(function_name) \
void function_name##_reverse(Module *m, \
std::vector<IOStateElement> external_state)

#define def_prim_serialize(function_name) \
void function_name##_serialize( \
std::vector<IOStateElement *> &external_state)

// TODO: use fp
#define pop_args(n) m->sp -= n
#define get_arg(m, arg) m->stack[(m)->sp - (arg)].value
#define pushUInt32(arg) m->stack[++m->sp].value.uint32 = arg
#define pushInt32(arg) m->stack[++m->sp].value.int32 = arg
#define pushUInt64(arg) \
m->stack[++m->sp].value_type = I64; \
m->stack[m->sp].value.uint64 = arg
#define arg0 get_arg(m, 0)
#define arg1 get_arg(m, 1)
#define arg2 get_arg(m, 2)
#define arg3 get_arg(m, 3)
#define arg4 get_arg(m, 4)
#define arg5 get_arg(m, 5)
#define arg6 get_arg(m, 6)
#define arg7 get_arg(m, 7)
#define arg8 get_arg(m, 8)
#define arg9 get_arg(m, 9)

// The primitive table
PrimitiveEntry primitives[ALL_PRIMITIVES];

//
uint32_t param_arr_len0[0] = {};
uint32_t param_I32_arr_len1[1] = {I32};
uint32_t param_I32_arr_len2[2] = {I32, I32};
uint32_t param_I32_arr_len3[3] = {I32, I32, I32};
uint32_t param_I32_arr_len4[4] = {I32, I32, I32, I32};
uint32_t param_I32_arr_len10[10] = {I32, I32, I32, I32, I32,
I32, I32, I32, I32, I32};

uint32_t param_I64_arr_len1[1] = {I64};

Type oneToNoneU32 = {
.form = FUNC,
.param_count = 1,
.params = param_I32_arr_len1,
.result_count = 0,
.results = nullptr,
.mask = 0x8001 /* 0x800 = no return ; 1 = I32*/
};

Type twoToNoneU32 = {
.form = FUNC,
.param_count = 2,
.params = param_I32_arr_len2,
.result_count = 0,
.results = nullptr,
.mask = 0x80011 /* 0x800 = no return ; 1 = I32; 1 = I32*/
};

Type threeToNoneU32 = {
.form = FUNC,
.param_count = 3,
.params = param_I32_arr_len3,
.result_count = 0,
.results = nullptr,
.mask = 0x800111 /* 0x800 = no return ; 1=I32; 1=I32; 1=I32*/
};

Type fourToNoneU32 = {
.form = FUNC,
.param_count = 4,
.params = param_I32_arr_len4,
.result_count = 0,
.results = nullptr,
.mask =
0x8001111 /* 0x800 = no return ; 1 = I32; 1 = I32; 1 = I32; 1 = I32*/
};

Type oneToOneU32 = {
.form = FUNC,
.param_count = 1,
.params = param_I32_arr_len1,
.result_count = 1,
.results = param_I32_arr_len1,
.mask = 0x80011 /* 0x8 1=I32 0=endRet ; 1=I32; 1=I32*/
};

Type oneToOneI32 = {
.form = FUNC,
.param_count = 1,
.params = param_I32_arr_len1,
.result_count = 1,
.results = param_I32_arr_len1,
.mask = 0x80011 /* 0x8 1=I32 0=endRet ; 1=I32; 1=I32*/
};

Type twoToOneU32 = {
.form = FUNC,
.param_count = 2,
.params = param_I32_arr_len2,
.result_count = 1,
.results = param_I32_arr_len1,
.mask = 0x81011 /* 0x8 1=I32 0=endRet ; 1=I32; 1=I32*/
};

Type threeToOneU32 = {
.form = FUNC,
.param_count = 3,
.params = param_I32_arr_len3,
.result_count = 1,
.results = param_I32_arr_len1,
.mask = 0x810111 /* 0x8 1=I32 0=endRet ; 1=I32; 1=I32; 1=I32*/
};

Type fourToOneU32 = {
.form = FUNC,
.param_count = 4,
.params = param_I32_arr_len4,
.result_count = 1,
.results = param_I32_arr_len1,
.mask = 0x8101111 /* 0x8 1=I32 0=endRet ; 1=I32; 1=I32; 1=I32; 1=I32*/
};

Type tenToOneU32 = {
.form = FUNC,
.param_count = 10,
.params = param_I32_arr_len10,
.result_count = 1,
.results = param_I32_arr_len1,
.mask = 0x8101111111111 /* 0x8 1=I32 0=endRet ; 10 params 1=I32*/
};

Type NoneToNoneU32 = {.form = FUNC,
.param_count = 0,
.params = nullptr,
.result_count = 0,
.results = nullptr,
.mask = 0x80000};

Type NoneToOneU32 = {.form = FUNC,
.param_count = 0,
.params = nullptr,
.result_count = 1,
.results = param_I32_arr_len1,
.mask = 0x81000};

Type NoneToOneU64 = {.form = FUNC,
.param_count = 0,
.params = nullptr,
.result_count = 1,
.results = param_I64_arr_len1,
.mask = 0x82000};

// Util function declarations

void connect(const String ssid, const String password);
Expand Down Expand Up @@ -983,7 +790,7 @@ void install_isrs() {
install_isr(39);
}

void install_primitives() {
void install_primitives(Interpreter *interpreter) {
dbg_info("INSTALLING PRIMITIVES\n");
install_primitive(abort);
install_primitive(millis);
Expand All @@ -1001,8 +808,7 @@ void install_primitives() {
install_primitive(http_post);

install_primitive(chip_pin_mode);
install_primitive(chip_digital_write);
install_primitive_reverse(chip_digital_write);
install_reversible_primitive(chip_digital_write);
install_primitive(chip_delay);
install_primitive(chip_digital_read);
install_primitive(chip_analog_read);
Expand Down Expand Up @@ -1038,24 +844,6 @@ void install_primitives() {
install_isrs();
}

//------------------------------------------------------
// resolving the primitives
//------------------------------------------------------
bool resolve_primitive(char *symbol, Primitive *val) {
debug("Resolve primitives (%d) for %s \n", ALL_PRIMITIVES, symbol);

for (auto &primitive : primitives) {
// printf("Checking %s = %s \n", symbol, primitive.name);
if (!strcmp(symbol, primitive.name)) {
debug("FOUND PRIMITIVE\n");
*val = primitive.f;
return true;
}
}
FATAL("Could not find primitive %s \n", symbol);
return false;
}

Memory external_mem{};

bool resolve_external_memory(char *symbol, Memory **val) {
Expand All @@ -1075,44 +863,3 @@ bool resolve_external_memory(char *symbol, Memory **val) {
FATAL("Could not find memory %s \n", symbol);
return false;
}

//------------------------------------------------------
// Restore external state when restoring a snapshot
//------------------------------------------------------
void restore_external_state(Module *m,
const std::vector<IOStateElement> &external_state) {
uint8_t opcode = *m->pc_ptr;
// TODO: Maybe primitives can also be called using the other call
// instructions such as call_indirect
// maybe there should just be a function that checks if a certain function
// is being called that handles all these cases?
if (opcode == 0x10) { // call opcode
uint8_t *pc_copy = m->pc_ptr + 1;
uint32_t fidx = read_LEB_32(&pc_copy);
if (fidx < m->import_count) {
for (auto &primitive : primitives) {
if (!strcmp(primitive.name, m->functions[fidx].import_field)) {
if (primitive.f_reverse) {
debug("Reversing action for primitive %s\n",
primitive.name);
primitive.f_reverse(m, external_state);
}
return;
}
}
}
}
}

//------------------------------------------------------
// Serialize external state into a snapshot
//------------------------------------------------------
std::vector<IOStateElement *> get_io_state(Module *m) {
std::vector<IOStateElement *> ioState;
for (auto &primitive : primitives) {
if (primitive.f_serialize_state) {
primitive.f_serialize_state(ioState);
}
}
return ioState;
}
Loading