feat: add support for .so dylib files (#103)
* add support for .so dynamic lib files * implement a missing wasi_intruction (prestat) * seperate the wasm instructions from runtime code * temporary commit to figure out github CI wat2wasm version * add debug and release flags to makefile * apply the .so compilation logic to all Makefiles and Python scripts * separate wasm instructions from memory files * update the tests to for CI * make the Makefile independent of .so or .bc linked runtime * update submodule cmu * Specify clear rules for providing a ".so" librarypull/105/head
parent
e804863246
commit
f94cfea983
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
@ -0,0 +1,104 @@
|
||||
#include "runtime.h"
|
||||
#include <fenv.h>
|
||||
#include <math.h>
|
||||
|
||||
struct indirect_table_entry indirect_table[INDIRECT_TABLE_SIZE];
|
||||
|
||||
// TODO: Throughout here we use `assert` for error conditions, which isn't optimal
|
||||
// Instead we should use `unlikely` branches to a single trapping function (which should optimize better)
|
||||
|
||||
// We want to have some allocation logic here, so we can use it to implement libc
|
||||
WEAK u32 wasmg___heap_base = 0;
|
||||
u32 runtime_heap_base;
|
||||
|
||||
// If a function is registered using the (start) instruction, call it
|
||||
WEAK void start_fn() {}
|
||||
WEAK void wasmf__start() {}
|
||||
|
||||
extern struct dylib_handler so_handler;
|
||||
u32 starting_pages, max_pages;
|
||||
|
||||
static inline int dylib_handler_init(struct dylib_handler* handler, const char* path) {
|
||||
awsm_assert(handler != NULL);
|
||||
|
||||
int rc = 0;
|
||||
|
||||
handler->handle = dlopen(path, RTLD_LAZY | RTLD_DEEPBIND);
|
||||
if (handler->handle == NULL) {
|
||||
fprintf(stderr, "Failed to open %s with error: %s\n", path, dlerror());
|
||||
fprintf(stderr, "Either provide a \"lib.so\" file in the same dir "
|
||||
"or provide a path such as: SO_PATH=./app_name.so\n");
|
||||
goto dl_open_error;
|
||||
}
|
||||
|
||||
/* Resolve the symbols in the dynamic library *.so file */
|
||||
handler->entrypoint = (entrypoint_fn_t)dlsym(handler->handle, "wasmf__start");
|
||||
if (handler->entrypoint == NULL) {
|
||||
fprintf(stderr, "Failed to resolve symbol %s in %s with error: %s\n", "wasmf__start", path, dlerror());
|
||||
goto dl_error;
|
||||
}
|
||||
|
||||
/*
|
||||
* This symbol may or may not be present depending on whether the aWsm was
|
||||
* run with the --runtime-globals flag. It is not clear what the proper
|
||||
* configuration would be for SLEdge, so no validation is performed
|
||||
*/
|
||||
handler->initialize_globals = (init_globals_fn_t)dlsym(handler->handle, "populate_globals");
|
||||
|
||||
handler->initialize_memory = (init_mem_fn_t)dlsym(handler->handle, "populate_memory");
|
||||
if (handler->initialize_memory == NULL) {
|
||||
fprintf(stderr, "Failed to resolve symbol %s in %s with error: %s\n", "populate_memory", path, dlerror());
|
||||
goto dl_error;
|
||||
}
|
||||
|
||||
handler->initialize_tables = (init_tbl_fn_t)dlsym(handler->handle, "populate_table");
|
||||
if (handler->initialize_tables == NULL) {
|
||||
fprintf(stderr, "Failed to resolve symbol %s in %s with error: %s\n", "populate_table", path, dlerror());
|
||||
goto dl_error;
|
||||
}
|
||||
|
||||
handler->starting_pages = dlsym(handler->handle, "starting_pages");
|
||||
handler->max_pages = dlsym(handler->handle, "max_pages");
|
||||
handler->globals_len = dlsym(handler->handle, "globals_len");
|
||||
done:
|
||||
return rc;
|
||||
dl_error:
|
||||
dlclose(handler->handle);
|
||||
dl_open_error:
|
||||
rc = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
void runtime_init() {
|
||||
char* dl_path = getenv("SO_PATH");
|
||||
if (dl_path == NULL) {
|
||||
/* If no explicit path is provided, then look for lib.so in the same folder */
|
||||
dl_path = "./lib.so";
|
||||
}
|
||||
|
||||
int ret = dylib_handler_init(&so_handler, dl_path);
|
||||
if (ret != 0)
|
||||
exit(ret);
|
||||
|
||||
starting_pages = *so_handler.starting_pages;
|
||||
max_pages = *so_handler.max_pages;
|
||||
|
||||
if (likely(starting_pages > 0)) {
|
||||
alloc_linear_memory();
|
||||
}
|
||||
|
||||
so_handler.initialize_tables();
|
||||
if (so_handler.initialize_globals)
|
||||
so_handler.initialize_globals();
|
||||
so_handler.initialize_memory();
|
||||
|
||||
int rc = fesetround(FE_TONEAREST);
|
||||
awsm_assert(rc == 0);
|
||||
|
||||
runtime_heap_base = wasmg___heap_base;
|
||||
if (runtime_heap_base == 0) {
|
||||
runtime_heap_base = memory_size;
|
||||
}
|
||||
|
||||
start_fn();
|
||||
}
|
@ -0,0 +1,301 @@
|
||||
#include "../runtime.h"
|
||||
|
||||
__attribute__((noreturn)) __attribute__((always_inline)) void awsm_abi__trap_unreachable() {
|
||||
fprintf(stderr, "WebAssembly control flow unexpectedly reached unreachable instruction\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Instantiation */
|
||||
|
||||
// If we are using runtime globals, we need to populate them
|
||||
WEAK void populate_globals() {}
|
||||
|
||||
/* End of Instantiation */
|
||||
|
||||
|
||||
/* Memory Instructions:*/
|
||||
|
||||
INLINE i32 instruction_memory_size() {
|
||||
return memory_size / WASM_PAGE_SIZE;
|
||||
}
|
||||
|
||||
INLINE i32 instruction_memory_grow(i32 count) {
|
||||
i32 prev_size = instruction_memory_size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
expand_memory();
|
||||
}
|
||||
|
||||
return prev_size;
|
||||
}
|
||||
|
||||
INLINE void initialize_region(u32 offset, u32 data_count, char* data) {
|
||||
// FIXME: Hack around segmented and unsegmented access
|
||||
memcpy(get_memory_ptr_for_runtime(offset, data_count), data, data_count);
|
||||
}
|
||||
|
||||
/* End of Memory Instructions:*/
|
||||
|
||||
|
||||
/* Table Instructions:*/
|
||||
|
||||
INLINE void add_function_to_table(u32 idx, u32 type_id, char* pointer) {
|
||||
awsm_assert(idx < INDIRECT_TABLE_SIZE);
|
||||
indirect_table[idx] = (struct indirect_table_entry){ .type_id = type_id, .func_pointer = pointer };
|
||||
}
|
||||
|
||||
INLINE void clear_table() {
|
||||
for (int i = 0; i < INDIRECT_TABLE_SIZE; i++) {
|
||||
indirect_table[i] = (struct indirect_table_entry){ 0 };
|
||||
}
|
||||
}
|
||||
|
||||
/* End of Table Instructions:*/
|
||||
|
||||
|
||||
/* Numeric Instructions:*/
|
||||
|
||||
INLINE u32 rotl_u32(u32 n, u32 c_u32) {
|
||||
// WASM requires a modulus here (usually a single bitwise op, but it means we need no assert)
|
||||
unsigned int c = c_u32 % (CHAR_BIT * sizeof(n));
|
||||
const unsigned int mask = (CHAR_BIT * sizeof(n) - 1); // assumes width is a power of 2.
|
||||
|
||||
c &= mask;
|
||||
return (n << c) | (n >> ((-c) & mask));
|
||||
}
|
||||
|
||||
INLINE u32 rotr_u32(u32 n, u32 c_u32) {
|
||||
// WASM requires a modulus here (usually a single bitwise op, but it means we need no assert)
|
||||
unsigned int c = c_u32 % (CHAR_BIT * sizeof(n));
|
||||
const unsigned int mask = (CHAR_BIT * sizeof(n) - 1);
|
||||
|
||||
c &= mask;
|
||||
return (n >> c) | (n << ((-c) & mask));
|
||||
}
|
||||
|
||||
INLINE u64 rotl_u64(u64 n, u64 c_u64) {
|
||||
// WASM requires a modulus here (usually a single bitwise op, but it means we need no assert)
|
||||
unsigned int c = c_u64 % (CHAR_BIT * sizeof(n));
|
||||
const unsigned int mask = (CHAR_BIT * sizeof(n) - 1); // assumes width is a power of 2.
|
||||
|
||||
c &= mask;
|
||||
return (n << c) | (n >> ((-c) & mask));
|
||||
}
|
||||
|
||||
INLINE u64 rotr_u64(u64 n, u64 c_u64) {
|
||||
// WASM requires a modulus here (usually a single bitwise op, but it means we need no assert)
|
||||
unsigned int c = c_u64 % (CHAR_BIT * sizeof(n));
|
||||
const unsigned int mask = (CHAR_BIT * sizeof(n) - 1);
|
||||
|
||||
c &= mask;
|
||||
return (n >> c) | (n << ((-c) & mask));
|
||||
}
|
||||
|
||||
// Now safe division and remainder
|
||||
INLINE u32 u32_div(u32 a, u32 b) {
|
||||
awsm_assert(b);
|
||||
return a / b;
|
||||
}
|
||||
|
||||
INLINE u32 u32_rem(u32 a, u32 b) {
|
||||
awsm_assert(b);
|
||||
return a % b;
|
||||
}
|
||||
|
||||
INLINE i32 i32_div(i32 a, i32 b) {
|
||||
awsm_assert(b && (a != INT32_MIN || b != -1));
|
||||
return a / b;
|
||||
}
|
||||
|
||||
INLINE i32 i32_rem(i32 a, i32 b) {
|
||||
awsm_assert(b != 0);
|
||||
|
||||
/* Because MIN is one less than MAX, we can FPE here */
|
||||
if (unlikely(a == INT32_MIN)) {
|
||||
return (a + abs(b)) % b;
|
||||
}
|
||||
|
||||
return a % b;
|
||||
}
|
||||
|
||||
INLINE u64 u64_div(u64 a, u64 b) {
|
||||
awsm_assert(b);
|
||||
return a / b;
|
||||
}
|
||||
|
||||
INLINE u64 u64_rem(u64 a, u64 b) {
|
||||
awsm_assert(b);
|
||||
return a % b;
|
||||
}
|
||||
|
||||
INLINE i64 i64_div(i64 a, i64 b) {
|
||||
awsm_assert(b && (a != INT64_MIN || b != -1));
|
||||
return a / b;
|
||||
}
|
||||
|
||||
INLINE i64 i64_rem(i64 a, i64 b) {
|
||||
awsm_assert(b != 0);
|
||||
|
||||
/* Because MIN is one less than MAX, we can FPE here */
|
||||
if (unlikely(a == INT64_MIN)) {
|
||||
return (a + labs(b)) % b;
|
||||
}
|
||||
|
||||
return a % b;
|
||||
}
|
||||
|
||||
// float to integer conversion methods
|
||||
// In C, float => int conversions always truncate
|
||||
// If a int2float(int::min_value) <= float <= int2float(int::max_value), it must always be safe to truncate it
|
||||
u32 u32_trunc_f32(float f) {
|
||||
float integer_part = 0;
|
||||
float decimal_part = modff(f, &integer_part);
|
||||
|
||||
if (unlikely(integer_part < 0 || integer_part > (float)UINT32_MAX)) {
|
||||
fprintf(stderr, "integer overflow\n");
|
||||
awsm_assert(0);
|
||||
}
|
||||
|
||||
return (u32)f;
|
||||
}
|
||||
|
||||
i32 i32_trunc_f32(float f) {
|
||||
float integer_part = 0;
|
||||
float decimal_part = modff(f, &integer_part);
|
||||
|
||||
if (unlikely(integer_part < (float)INT32_MIN || integer_part > (float)INT32_MAX)) {
|
||||
fprintf(stderr, "integer overflow\n");
|
||||
awsm_assert(0);
|
||||
}
|
||||
|
||||
return (i32)f;
|
||||
}
|
||||
|
||||
u32 u32_trunc_f64(double f) {
|
||||
double integer_part = 0;
|
||||
double decimal_part = modf(f, &integer_part);
|
||||
|
||||
if (unlikely(integer_part < 0 || integer_part > (double)UINT32_MAX)) {
|
||||
fprintf(stderr, "integer overflow\n");
|
||||
awsm_assert(0);
|
||||
}
|
||||
return (u32)f;
|
||||
}
|
||||
|
||||
i32 i32_trunc_f64(double f) {
|
||||
double integer_part = 0;
|
||||
double decimal_part = modf(f, &integer_part);
|
||||
|
||||
if (unlikely(integer_part < (double)INT32_MIN || integer_part > (double)INT32_MAX)) {
|
||||
fprintf(stderr, "integer overflow\n");
|
||||
awsm_assert(0);
|
||||
}
|
||||
|
||||
return (i32)f;
|
||||
}
|
||||
|
||||
u64 u64_trunc_f32(float f) {
|
||||
float integer_part = 0;
|
||||
float decimal_part = modff(f, &integer_part);
|
||||
|
||||
if (unlikely(integer_part < 0 || integer_part > (float)UINT64_MAX)) {
|
||||
fprintf(stderr, "integer overflow\n");
|
||||
awsm_assert(0);
|
||||
}
|
||||
|
||||
return (u64)f;
|
||||
}
|
||||
|
||||
i64 i64_trunc_f32(float f) {
|
||||
float integer_part = 0;
|
||||
float decimal_part = modff(f, &integer_part);
|
||||
|
||||
if (unlikely(integer_part < (float)INT64_MIN || integer_part > (float)INT64_MAX)) {
|
||||
fprintf(stderr, "integer overflow\n");
|
||||
awsm_assert(0);
|
||||
}
|
||||
|
||||
return (i64)f;
|
||||
}
|
||||
|
||||
u64 u64_trunc_f64(double f) {
|
||||
double integer_part = 0;
|
||||
double decimal_part = modf(f, &integer_part);
|
||||
|
||||
if (unlikely(integer_part < 0 || integer_part > (double)UINT64_MAX)) {
|
||||
fprintf(stderr, "integer overflow\n");
|
||||
awsm_assert(0);
|
||||
}
|
||||
|
||||
return (u64)f;
|
||||
}
|
||||
|
||||
i64 i64_trunc_f64(double f) {
|
||||
double integer_part = 0;
|
||||
double decimal_part = modf(f, &integer_part);
|
||||
|
||||
if (unlikely(integer_part < (double)INT64_MIN || integer_part > (double)INT64_MAX)) {
|
||||
fprintf(stderr, "integer overflow\n");
|
||||
awsm_assert(0);
|
||||
}
|
||||
|
||||
return (i64)f;
|
||||
}
|
||||
|
||||
// Float => Float truncation functions
|
||||
INLINE float f32_trunc_f32(float f) {
|
||||
return truncf(f);
|
||||
}
|
||||
|
||||
INLINE float f32_min(float a, float b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
INLINE float f32_max(float a, float b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
INLINE float f32_floor(float a) {
|
||||
return floorf(a);
|
||||
}
|
||||
|
||||
INLINE float f32_ceil(float a) {
|
||||
return ceilf(a);
|
||||
}
|
||||
|
||||
INLINE float f32_nearest(float a) {
|
||||
return nearbyintf(a);
|
||||
}
|
||||
|
||||
INLINE float f32_copysign(float a, float b) {
|
||||
return copysignf(a, b);
|
||||
}
|
||||
|
||||
INLINE double f64_trunc_f64(double f) {
|
||||
return trunc(f);
|
||||
}
|
||||
|
||||
INLINE double f64_min(double a, double b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
INLINE double f64_max(double a, double b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
INLINE double f64_floor(double a) {
|
||||
return floor(a);
|
||||
}
|
||||
|
||||
INLINE double f64_ceil(double a) {
|
||||
return ceil(a);
|
||||
}
|
||||
|
||||
INLINE double f64_nearest(double a) {
|
||||
return nearbyint(a);
|
||||
}
|
||||
|
||||
INLINE double f64_copysign(double a, double b) {
|
||||
return copysign(a, b);
|
||||
}
|
||||
|
||||
/* End of Numeric Instructions */
|
@ -0,0 +1,86 @@
|
||||
#include "../../runtime.h"
|
||||
|
||||
INLINE float get_f32(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(float*)address;
|
||||
}
|
||||
|
||||
INLINE double get_f64(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(double*)address;
|
||||
}
|
||||
|
||||
INLINE i8 get_i8(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i8*)address;
|
||||
}
|
||||
|
||||
INLINE i16 get_i16(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i16*)address;
|
||||
}
|
||||
|
||||
INLINE i32 get_i32(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i32*)address;
|
||||
}
|
||||
|
||||
INLINE i64 get_i64(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i64*)address;
|
||||
}
|
||||
|
||||
INLINE void set_f32(u32 offset, float v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(float*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_f64(u32 offset, double v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(double*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i8(u32 offset, i8 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i8*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i16(u32 offset, i16 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i16*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i32(u32 offset, i32 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i32*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i64(u32 offset, i64 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i64*)address = v;
|
||||
}
|
||||
|
||||
INLINE char* get_function_from_table(u32 idx, u32 type_id) {
|
||||
awsm_assert(idx < INDIRECT_TABLE_SIZE);
|
||||
|
||||
struct indirect_table_entry f = indirect_table[idx];
|
||||
|
||||
// NOTE: Legacy C applications could fail this check if they typecast function pointers.
|
||||
// Additional reference: https://emscripten.org/docs/porting/guidelines/function_pointer_issues.html
|
||||
awsm_assert(f.type_id == type_id);
|
||||
awsm_assert(f.func_pointer);
|
||||
|
||||
return f.func_pointer;
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
#include "../../runtime.h"
|
||||
|
||||
INLINE float get_f32(u32 offset) {
|
||||
awsm_assert(offset <= memory_size - sizeof(float));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
|
||||
return *(float*)address;
|
||||
}
|
||||
|
||||
INLINE double get_f64(u32 offset) {
|
||||
awsm_assert(offset <= memory_size - sizeof(double));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(double*)address;
|
||||
}
|
||||
|
||||
INLINE i8 get_i8(u32 offset) {
|
||||
// printf_("get %d <= %d - %d\n", offset, memory_size, sizeof(i8));
|
||||
|
||||
awsm_assert(offset <= memory_size - sizeof(i8));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i8*)address;
|
||||
}
|
||||
|
||||
INLINE i16 get_i16(u32 offset) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i16));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i16*)address;
|
||||
}
|
||||
|
||||
INLINE i32 get_i32(u32 offset) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i32));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i32*)address;
|
||||
}
|
||||
|
||||
INLINE i64 get_i64(u32 offset) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i64));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i64*)address;
|
||||
}
|
||||
|
||||
INLINE void set_f32(u32 offset, float v) {
|
||||
awsm_assert(offset <= memory_size - sizeof(float));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(float*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_f64(u32 offset, double v) {
|
||||
awsm_assert(offset <= memory_size - sizeof(double));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(double*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i8(u32 offset, i8 v) {
|
||||
// printf_("set %d <= %d - %d\n", offset, memory_size, sizeof(i8));
|
||||
awsm_assert(offset <= memory_size - sizeof(i8));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i8*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i16(u32 offset, i16 v) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i16));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i16*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i32(u32 offset, i32 v) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i32));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i32*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i64(u32 offset, i64 v) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i64));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i64*)address = v;
|
||||
}
|
||||
|
||||
INLINE char* get_function_from_table(u32 idx, u32 type_id) {
|
||||
awsm_assert(idx < INDIRECT_TABLE_SIZE);
|
||||
|
||||
struct indirect_table_entry f = indirect_table[idx];
|
||||
|
||||
awsm_assert(f.type_id == type_id);
|
||||
awsm_assert(f.func_pointer);
|
||||
|
||||
return f.func_pointer;
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
#include "../../runtime.h"
|
||||
|
||||
INLINE float get_f32(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(float*)address;
|
||||
}
|
||||
|
||||
INLINE double get_f64(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(double*)address;
|
||||
}
|
||||
|
||||
INLINE i8 get_i8(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i8*)address;
|
||||
}
|
||||
|
||||
INLINE i16 get_i16(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i16*)address;
|
||||
}
|
||||
|
||||
INLINE i32 get_i32(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i32*)address;
|
||||
}
|
||||
|
||||
INLINE i64 get_i64(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i64*)address;
|
||||
}
|
||||
|
||||
INLINE void set_f32(u32 offset, float v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(float*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_f64(u32 offset, double v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(double*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i8(u32 offset, i8 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i8*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i16(u32 offset, i16 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i16*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i32(u32 offset, i32 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i32*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i64(u32 offset, i64 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i64*)address = v;
|
||||
}
|
||||
|
||||
INLINE char* get_function_from_table(u32 idx, u32 type_id) {
|
||||
struct indirect_table_entry f = indirect_table[idx];
|
||||
return f.func_pointer;
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
#include "../../runtime.h"
|
||||
|
||||
#define SPT_PAGE_COUNT_ORDER 8
|
||||
#define SPT_PAGE_COUNT (1 << SPT_PAGE_COUNT_ORDER)
|
||||
|
||||
#define SPT_PAGE_SIZE_ORDER 10
|
||||
#define SPT_PAGE_SIZE (1 << SPT_PAGE_SIZE_ORDER)
|
||||
|
||||
static void* PAGE_TABLE[SPT_PAGE_COUNT] = { 0 };
|
||||
|
||||
INLINE void* get_page(u32 offset) {
|
||||
u32 page_number = (offset >> SPT_PAGE_SIZE_ORDER) & ((1 << SPT_PAGE_COUNT_ORDER) - 1);
|
||||
awsm_assert(page_number < SPT_PAGE_COUNT);
|
||||
void* page = PAGE_TABLE[page_number];
|
||||
awsm_assert(page);
|
||||
return page;
|
||||
}
|
||||
|
||||
INLINE u32 get_page_offset(u32 offset) {
|
||||
return offset & ((1 << SPT_PAGE_SIZE_ORDER) - 1);
|
||||
}
|
||||
|
||||
INLINE i8 get_i8(u32 offset) {
|
||||
i8* page = get_page(offset);
|
||||
u32 page_offset = get_page_offset(offset);
|
||||
return page[page_offset];
|
||||
}
|
||||
|
||||
INLINE i16 get_i16(u32 offset) {
|
||||
u32 page_offset = get_page_offset(offset);
|
||||
if (page_offset < SPT_PAGE_SIZE - sizeof(i16)) {
|
||||
i8* page = get_page(offset);
|
||||
i16* page_adj = (void*)&page[page_offset];
|
||||
return *page_adj;
|
||||
} else {
|
||||
u8 a = (u8)get_i8(offset);
|
||||
u8 b = (u8)get_i8(offset + 1);
|
||||
return (i16)(((u16)b) << 8) | ((u16)a);
|
||||
}
|
||||
// u32 page_offset = get_page_offset(offset);
|
||||
// i8* page = get_page(offset);
|
||||
// i16* page_adj = (void*) &page[page_offset];
|
||||
// printf("Regularly loaded: %p\n", (void*) (u64) *page_adj);
|
||||
//
|
||||
// u8 a = (u8) get_i8(offset);
|
||||
// u8 b = (u8) get_i8(offset + 1);
|
||||
// i16 split = (i16) (((u16) b) << 8) | ((u16) a);
|
||||
// printf("Split from (%p, %p)\n", (void*) (u64) a, (void*) (u64) b);
|
||||
// printf("Split loaded: %p\n", (void*) (u64) split);
|
||||
//
|
||||
// awsm_assert(*page_adj == split);
|
||||
// return *page_adj;
|
||||
}
|
||||
|
||||
INLINE i32 get_i32(u32 offset) {
|
||||
u32 page_offset = get_page_offset(offset);
|
||||
if (page_offset < SPT_PAGE_SIZE - sizeof(i32)) {
|
||||
i8* page = get_page(offset);
|
||||
i32* page_adj = (void*)&page[page_offset];
|
||||
return *page_adj;
|
||||
} else {
|
||||
u16 a = (u16)get_i16(offset);
|
||||
u16 b = (u16)get_i16(offset + 2);
|
||||
return (i32)(((u32)b) << 16) | ((u32)a);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE i64 get_i64(u32 offset) {
|
||||
u32 page_offset = get_page_offset(offset);
|
||||
if (page_offset < SPT_PAGE_SIZE - sizeof(i64)) {
|
||||
i8* page = get_page(offset);
|
||||
i64* page_adj = (void*)&page[page_offset];
|
||||
return *page_adj;
|
||||
} else {
|
||||
u32 a = (u32)get_i32(offset);
|
||||
u32 b = (u32)get_i32(offset + 4);
|
||||
return (i64)(((u64)b) << 32) | ((u64)a);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE float get_f32(u32 offset) {
|
||||
union {
|
||||
i32 i;
|
||||
float f;
|
||||
} a;
|
||||
|
||||
a.i = get_i32(offset);
|
||||
return a.f;
|
||||
}
|
||||
|
||||
INLINE double get_f64(u32 offset) {
|
||||
union {
|
||||
i64 i;
|
||||
double f;
|
||||
} a;
|
||||
|
||||
a.i = get_i64(offset);
|
||||
return a.f;
|
||||
}
|
||||
|
||||
// Setting routines
|
||||
INLINE void set_i8(u32 offset, i8 v) {
|
||||
i8* page = get_page(offset);
|
||||
u32 page_offset = get_page_offset(offset);
|
||||
page[page_offset] = v;
|
||||
}
|
||||
|
||||
INLINE void set_i16(u32 offset, i16 v) {
|
||||
u32 page_offset = get_page_offset(offset);
|
||||
if (page_offset < SPT_PAGE_SIZE - sizeof(i16)) {
|
||||
i8* page = get_page(offset);
|
||||
i16* page_adj = (void*)&page[page_offset];
|
||||
*page_adj = v;
|
||||
} else {
|
||||
u16 v2 = (u16)v;
|
||||
|
||||
set_i8(offset, (i8)v2);
|
||||
set_i8(offset + 1, (i8)(v2 >> 8));
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void set_i32(u32 offset, i32 v) {
|
||||
u32 page_offset = get_page_offset(offset);
|
||||
if (page_offset < SPT_PAGE_SIZE - sizeof(i32)) {
|
||||
i8* page = get_page(offset);
|
||||
i32* page_adj = (void*)&page[page_offset];
|
||||
*page_adj = v;
|
||||
} else {
|
||||
u32 v2 = (u32)v;
|
||||
|
||||
set_i16(offset, (i16)v2);
|
||||
set_i16(offset + 2, (i16)(v2 >> 16));
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void set_i64(u32 offset, i64 v) {
|
||||
u32 page_offset = get_page_offset(offset);
|
||||
if (page_offset < SPT_PAGE_SIZE - sizeof(i64)) {
|
||||
i8* page = get_page(offset);
|
||||
i64* page_adj = (void*)&page[page_offset];
|
||||
*page_adj = v;
|
||||
} else {
|
||||
u64 v2 = (u64)v;
|
||||
|
||||
set_i32(offset, (i32)v2);
|
||||
set_i32(offset + 4, (i32)(v2 >> 32));
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void set_f32(u32 offset, float v) {
|
||||
union {
|
||||
i32 i;
|
||||
float f;
|
||||
} a;
|
||||
|
||||
a.f = v;
|
||||
set_i32(offset, a.i);
|
||||
}
|
||||
|
||||
INLINE void set_f64(u32 offset, double v) {
|
||||
union {
|
||||
i64 i;
|
||||
double f;
|
||||
} a;
|
||||
|
||||
a.f = v;
|
||||
set_i64(offset, a.i);
|
||||
}
|
||||
|
||||
|
||||
INLINE char* get_function_from_table(u32 idx, u32 type_id) {
|
||||
awsm_assert(idx < INDIRECT_TABLE_SIZE);
|
||||
|
||||
struct indirect_table_entry f = indirect_table[idx];
|
||||
|
||||
awsm_assert(f.type_id == type_id);
|
||||
awsm_assert(f.func_pointer);
|
||||
|
||||
return f.func_pointer;
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
#include "../../runtime.h"
|
||||
|
||||
#define MEM_SIZE (WASM_PAGE_SIZE * 1 << 2)
|
||||
char CORTEX_M_MEM[MEM_SIZE + sizeof(u64)] = { 0 };
|
||||
|
||||
INLINE float get_f32(u32 offset) {
|
||||
offset = offset % MEM_SIZE;
|
||||
|
||||
void* address = &CORTEX_M_MEM[offset];
|
||||
return *(float*)address;
|
||||
}
|
||||
|
||||
INLINE double get_f64(u32 offset) {
|
||||
offset = offset % MEM_SIZE;
|
||||
|
||||
void* address = &CORTEX_M_MEM[offset];
|
||||
return *(double*)address;
|
||||
}
|
||||
|
||||
INLINE i8 get_i8(u32 offset) {
|
||||
offset = offset % MEM_SIZE;
|
||||
|
||||
void* address = &CORTEX_M_MEM[offset];
|
||||
return *(i8*)address;
|
||||
}
|
||||
|
||||
INLINE i16 get_i16(u32 offset) {
|
||||
return *(i16*)&CORTEX_M_MEM[offset % MEM_SIZE];
|
||||
}
|
||||
|
||||
INLINE i32 get_i32(u32 offset) {
|
||||
return *(i32*)&CORTEX_M_MEM[offset % MEM_SIZE];
|
||||
}
|
||||
|
||||
INLINE i64 get_i64(u32 offset) {
|
||||
offset = offset % MEM_SIZE;
|
||||
|
||||
void* address = &CORTEX_M_MEM[offset];
|
||||
return *(i64*)address;
|
||||
}
|
||||
|
||||
INLINE void set_f32(u32 offset, float v) {
|
||||
offset = offset % MEM_SIZE;
|
||||
|
||||
void* address = &CORTEX_M_MEM[offset];
|
||||
*(float*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_f64(u32 offset, double v) {
|
||||
offset = offset % MEM_SIZE;
|
||||
|
||||
void* address = &CORTEX_M_MEM[offset];
|
||||
*(double*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i8(u32 offset, i8 v) {
|
||||
offset = offset % MEM_SIZE;
|
||||
|
||||
void* address = &CORTEX_M_MEM[offset];
|
||||
*(i8*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i16(u32 offset, i16 v) {
|
||||
offset = offset % MEM_SIZE;
|
||||
|
||||
void* address = &CORTEX_M_MEM[offset];
|
||||
*(i16*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i32(u32 offset, i32 v) {
|
||||
offset = offset % MEM_SIZE;
|
||||
|
||||
void* address = &CORTEX_M_MEM[offset];
|
||||
*(i32*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i64(u32 offset, i64 v) {
|
||||
offset = offset % MEM_SIZE;
|
||||
|
||||
void* address = &CORTEX_M_MEM[offset];
|
||||
*(i64*)address = v;
|
||||
}
|
||||
|
||||
INLINE char* get_function_from_table(u32 idx, u32 type_id) {
|
||||
awsm_assert(idx < INDIRECT_TABLE_SIZE);
|
||||
|
||||
struct indirect_table_entry f = indirect_table[idx];
|
||||
|
||||
awsm_assert(f.type_id == type_id);
|
||||
awsm_assert(f.func_pointer);
|
||||
|
||||
return f.func_pointer;
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
#include "../../runtime.h"
|
||||
|
||||
INLINE float get_f32(u32 offset) {
|
||||
awsm_assert(offset <= memory_size - sizeof(float));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(float*)address;
|
||||
}
|
||||
|
||||
INLINE double get_f64(u32 offset) {
|
||||
awsm_assert(offset <= memory_size - sizeof(double));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(double*)address;
|
||||
}
|
||||
|
||||
INLINE i8 get_i8(u32 offset) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i8));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i8*)address;
|
||||
}
|
||||
|
||||
INLINE i16 get_i16(u32 offset) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i16));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i16*)address;
|
||||
}
|
||||
|
||||
INLINE i32 get_i32(u32 offset) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i32));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i32*)address;
|
||||
}
|
||||
|
||||
INLINE i64 get_i64(u32 offset) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i64));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i64*)address;
|
||||
}
|
||||
|
||||
INLINE void set_f32(u32 offset, float v) {
|
||||
awsm_assert(offset <= memory_size - sizeof(float));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(float*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_f64(u32 offset, double v) {
|
||||
awsm_assert(offset <= memory_size - sizeof(double));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(double*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i8(u32 offset, i8 v) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i8));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i8*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i16(u32 offset, i16 v) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i16));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i16*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i32(u32 offset, i32 v) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i32));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i32*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i64(u32 offset, i64 v) {
|
||||
awsm_assert(offset <= memory_size - sizeof(i64));
|
||||
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i64*)address = v;
|
||||
}
|
||||
|
||||
INLINE char* get_function_from_table(u32 idx, u32 type_id) {
|
||||
awsm_assert(idx < INDIRECT_TABLE_SIZE);
|
||||
|
||||
struct indirect_table_entry f = indirect_table[idx];
|
||||
|
||||
awsm_assert(f.type_id == type_id);
|
||||
awsm_assert(f.func_pointer);
|
||||
|
||||
return f.func_pointer;
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
#include "../../runtime.h"
|
||||
|
||||
#define MPX_BC(adr, sz) \
|
||||
{ asm volatile("bndcu " #sz "(%0), %%bnd0" : : "r"(adr)); }
|
||||
|
||||
INLINE float get_f32(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
|
||||
// Bounds check
|
||||
MPX_BC(address, 0x3);
|
||||
|
||||
float v = *(float*)address;
|
||||
return v;
|
||||
}
|
||||
|
||||
INLINE double get_f64(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
|
||||
MPX_BC(address, 0x7);
|
||||
|
||||
double v = *(double*)address;
|
||||
return v;
|
||||
}
|
||||
|
||||
INLINE i8 get_i8(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
|
||||
MPX_BC(address, 0x0);
|
||||
|
||||
return *(i8*)address;
|
||||
}
|
||||
|
||||
INLINE i16 get_i16(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
|
||||
MPX_BC(address, 0x1);
|
||||
|
||||
return *(i16*)address;
|
||||
}
|
||||
|
||||
INLINE i32 get_i32(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
|
||||
MPX_BC(address, 0x3);
|
||||
|
||||
i32 v = *(i32*)address;
|
||||
return v;
|
||||
}
|
||||
|
||||
INLINE i64 get_i64(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
|
||||
MPX_BC(address, 0x7);
|
||||
|
||||
i64 v = *(i64*)address;
|
||||
return v;
|
||||
}
|
||||
|
||||
INLINE void set_f32(u32 offset, float v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
|
||||
MPX_BC(address, 0x3);
|
||||
|
||||
*(float*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_f64(u32 offset, double v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
|
||||
MPX_BC(address, 0x7);
|
||||
|
||||
*(double*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i8(u32 offset, i8 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
|
||||
MPX_BC(address, 0x0);
|
||||
|
||||
*(i8*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i16(u32 offset, i16 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
|
||||
MPX_BC(address, 0x1);
|
||||
|
||||
*(i16*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i32(u32 offset, i32 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
|
||||
MPX_BC(address, 0x3);
|
||||
|
||||
*(i32*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i64(u32 offset, i64 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
|
||||
MPX_BC(address, 0x7);
|
||||
|
||||
*(i64*)address = v;
|
||||
}
|
||||
|
||||
INLINE char* get_function_from_table(u32 idx, u32 type_id) {
|
||||
awsm_assert(idx < INDIRECT_TABLE_SIZE);
|
||||
|
||||
struct indirect_table_entry f = indirect_table[idx];
|
||||
|
||||
awsm_assert(f.type_id == type_id);
|
||||
awsm_assert(f.func_pointer);
|
||||
|
||||
return f.func_pointer;
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
#include "../../runtime.h"
|
||||
|
||||
INLINE float get_f32(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(float*)address;
|
||||
}
|
||||
|
||||
INLINE double get_f64(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(double*)address;
|
||||
}
|
||||
|
||||
INLINE i8 get_i8(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i8*)address;
|
||||
}
|
||||
|
||||
INLINE i16 get_i16(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i16*)address;
|
||||
}
|
||||
|
||||
INLINE i32 get_i32(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i32*)address;
|
||||
}
|
||||
|
||||
INLINE i64 get_i64(u32 offset) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
return *(i64*)address;
|
||||
}
|
||||
|
||||
INLINE void set_f32(u32 offset, float v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(float*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_f64(u32 offset, double v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(double*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i8(u32 offset, i8 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i8*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i16(u32 offset, i16 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i16*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i32(u32 offset, i32 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i32*)address = v;
|
||||
}
|
||||
|
||||
INLINE void set_i64(u32 offset, i64 v) {
|
||||
char* mem_as_chars = (char*)memory;
|
||||
void* address = &mem_as_chars[offset];
|
||||
*(i64*)address = v;
|
||||
}
|
||||
|
||||
INLINE char* get_function_from_table(u32 idx, u32 type_id) {
|
||||
struct indirect_table_entry f = indirect_table[idx];
|
||||
return f.func_pointer;
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
#include "../../runtime.h"
|
||||
|
||||
#define GS_REL __attribute__((address_space(256)))
|
||||
|
||||
INLINE float get_f32(u32 offset) {
|
||||
return *((GS_REL float*)offset);
|
||||
}
|
||||
|
||||
INLINE double get_f64(u32 offset) {
|
||||
return *((GS_REL double*)offset);
|
||||
}
|
||||
|
||||
INLINE i8 get_i8(u32 offset) {
|
||||
return *((GS_REL i8*)offset);
|
||||
}
|
||||
|
||||
INLINE i16 get_i16(u32 offset) {
|
||||
return *((GS_REL i16*)offset);
|
||||
}
|
||||
|
||||
INLINE i32 get_i32(u32 offset) {
|
||||
return *((GS_REL i32*)offset);
|
||||
}
|
||||
|
||||
INLINE i64 get_i64(u32 offset) {
|
||||
return *((GS_REL i64*)offset);
|
||||
}
|
||||
|
||||
INLINE void set_f32(u32 offset, float v) {
|
||||
GS_REL float* ptr = (GS_REL float*)offset;
|
||||
*ptr = v;
|
||||
}
|
||||
|
||||
INLINE void set_f64(u32 offset, double v) {
|
||||
GS_REL double* ptr = (GS_REL double*)offset;
|
||||
*ptr = v;
|
||||
}
|
||||
|
||||
INLINE void set_i8(u32 offset, i8 v) {
|
||||
GS_REL i8* ptr = (GS_REL i8*)offset;
|
||||
*ptr = v;
|
||||
}
|
||||
|
||||
INLINE void set_i16(u32 offset, i16 v) {
|
||||
GS_REL i16* ptr = (GS_REL i16*)offset;
|
||||
*ptr = v;
|
||||
}
|
||||
|
||||
INLINE void set_i32(u32 offset, i32 v) {
|
||||
GS_REL i32* ptr = (GS_REL i32*)offset;
|
||||
*ptr = v;
|
||||
}
|
||||
|
||||
INLINE void set_i64(u32 offset, i64 v) {
|
||||
GS_REL i64* ptr = (GS_REL i64*)offset;
|
||||
*ptr = v;
|
||||
}
|
||||
|
||||
INLINE char* get_function_from_table(u32 idx, u32 type_id) {
|
||||
awsm_assert(idx < INDIRECT_TABLE_SIZE);
|
||||
|
||||
struct indirect_table_entry f = indirect_table[idx];
|
||||
|
||||
awsm_assert(f.type_id == type_id);
|
||||
awsm_assert(f.func_pointer);
|
||||
|
||||
return f.func_pointer;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue