Merge branch 'main' of https://github.com/wasm3/wasm3 into main

extensions
Steven Massey 3 years ago
commit 7028cb9624

@ -48,10 +48,10 @@ Minimum useful system requirements: **~64Kb** for code and **~10Kb** RAM
- <img src="https://cdn.rawgit.com/simple-icons/simple-icons/develop/icons/linux.svg" width="18" height="18" /> Linux,
<img src="https://cdn.rawgit.com/simple-icons/simple-icons/develop/icons/windows.svg" width="18" height="18" /> Windows,
<img src="https://cdn.rawgit.com/simple-icons/simple-icons/develop/icons/apple.svg" width="18" height="18" /> OS X,
<img src="https://cdn.rawgit.com/simple-icons/simple-icons/develop/icons/freebsd.svg" width="18" height="18" /> FreeBSD
- <img src="https://cdn.rawgit.com/simple-icons/simple-icons/develop/icons/android.svg" width="18" height="18" /> Android,
<img src="https://cdn.rawgit.com/simple-icons/simple-icons/develop/icons/freebsd.svg" width="18" height="18" /> FreeBSD,
<img src="https://cdn.rawgit.com/simple-icons/simple-icons/develop/icons/android.svg" width="18" height="18" /> Android,
<img src="https://cdn.rawgit.com/simple-icons/simple-icons/develop/icons/apple.svg" width="18" height="18" /> iOS
- <img src="https://cdn.rawgit.com/feathericons/feather/master/icons/wifi.svg" width="18" height="18" /> **OpenWRT**-enabled routers
- <img src="https://cdn.rawgit.com/feathericons/feather/master/icons/wifi.svg" width="18" height="18" /> OpenWrt, Yocto, Buildroot (routers, modems, etc.)
- <img src="https://cdn.rawgit.com/simple-icons/simple-icons/develop/icons/raspberrypi.svg" width="18" height="18" /> Raspberry Pi, Orange Pi and other **SBC**s
- <img src="https://cdn.rawgit.com/feathericons/feather/master/icons/cpu.svg" width="18" height="18" /> **MCU**s: Arduino, ESP8266, ESP32, Particle, ... [see full list](./docs/Hardware.md)
- <img src="https://cdn.rawgit.com/simple-icons/simple-icons/develop/icons/firefoxbrowser.svg" width="18" height="18" /> <img src="https://cdn.rawgit.com/simple-icons/simple-icons/develop/icons/googlechrome.svg" width="18" height="18" /> <img src="https://cdn.rawgit.com/simple-icons/simple-icons/develop/icons/safari.svg" width="18" height="18" /> <img src="https://cdn.rawgit.com/simple-icons/simple-icons/develop/icons/microsoftedge.svg" width="18" height="18" /> Browsers... yes, using WebAssembly itself!
@ -61,14 +61,14 @@ Minimum useful system requirements: **~64Kb** for code and **~10Kb** RAM
☑ Sign-extension operators
☑ Non-trapping float-to-int conversions
☑ Import/Export of Mutable Globals
☑ Structured execution tracing
☑ Self-hosting
☑ Gas metering
☐ Multi-value
☐ Bulk memory operations
☐ Reference types
☐ Bulk memory operations
☐ Tail call optimization
☐ Fixed-width SIMD
## Motivation
@ -76,7 +76,7 @@ Minimum useful system requirements: **~64Kb** for code and **~10Kb** RAM
In many situations, speed is not the main concern. Runtime executable size, code density, memory usage, startup latency can be all improved with the interpreter approach. Portability and security are much easier to achieve and maintain. Additionally, development impedance is much lower. A simple library like Wasm3 is easy to compile and integrate into an existing project. (Wasm3 builds in a just few seconds). Finally, on some platforms (i.e. iOS and WebAssembly itself) you can't generate executable code pages in runtime, so JIT is unavailable.
**Why would you want to run WASM on microcontrollers?**
**Why would you want to run WASM on embedded devices?**
Wasm3 started as a research project and remains so by many means. Evaluating the engine in different environments is part of the research. Given that we have `Lua`, `JS`, `Python`, `Lisp`, `...` running on MCUs, `WebAssembly` is actually a promising alternative. It provides toolchain decoupling as well as a completely sandboxed, well-defined, predictable environment. Among practical use cases we can list `edge computing`, `scripting`, running `IoT rules`, `smart contracts`, etc.

@ -1,7 +1,7 @@
# Wasm3 demos
- **In-browser Wasm3 (with MetaWASI support) on Webassembly.sh** │ [try it](https://webassembly.sh/?run-command=wasm3)
- **A set of Pygame + pywasm3 demos** | [github](https://github.com/wasm3/wasm3/tree/main/platforms/python/examples)
- **Pygame + pywasm3 demos** | [github](https://github.com/wasm3/pywasm3/tree/main/examples)
- **Dino game**
- on PyBadge/Arduino | [video](https://twitter.com/vshymanskyy/status/1345048053041029121), [github](https://github.com/wasm3/wasm3-arduino/tree/main/examples/Wasm_Dino_PyBadge)
- on Raspberry Pi Pico | [github](https://github.com/vshymanskyy/wasm3_dino_rpi_pico)

@ -16,6 +16,9 @@
#include "m3_api_libc.h"
#include "m3_api_tracer.h"
// TODO: remove
#include "m3_env.h"
/*
* NOTE: Gas metering/limit only applies to pre-instrumented modules.
* You can generate a metered version from any wasm file automatically, using
@ -358,6 +361,44 @@ M3Result repl_invoke (const char* name, int argc, const char* argv[])
return result;
}
M3Result repl_global_get (const char* name)
{
IM3Global g = m3_FindGlobal(runtime->modules, name);
M3TaggedValue tagged;
M3Result err = m3_GetGlobal (g, &tagged);
if (err) return err;
switch (tagged.type) {
case c_m3Type_i32: fprintf (stderr, "%" PRIu32 ":i32\n", tagged.value.i32); break;
case c_m3Type_i64: fprintf (stderr, "%" PRIu64 ":i64\n", tagged.value.i64); break;
case c_m3Type_f32: fprintf (stderr, "%" PRIf32 ":f32\n", tagged.value.f32); break;
case c_m3Type_f64: fprintf (stderr, "%" PRIf64 ":f64\n", tagged.value.f64); break;
default: return m3Err_invalidTypeId;
}
return m3Err_none;
}
M3Result repl_global_set (const char* name, const char* value)
{
IM3Global g = m3_FindGlobal(runtime->modules, name);
M3TaggedValue tagged = {
.type = m3_GetGlobalType(g)
};
switch (tagged.type) {
case c_m3Type_i32: tagged.value.i32 = strtoul(value, NULL, 10); break;
case c_m3Type_i64: tagged.value.i64 = strtoull(value, NULL, 10); break;
case c_m3Type_f32: tagged.value.f32 = strtod(value, NULL); break;
case c_m3Type_f64: tagged.value.f64 = strtod(value, NULL); break;
default: return m3Err_invalidTypeId;
}
return m3_SetGlobal (g, &tagged);
}
M3Result repl_dump()
{
uint32_t len;
@ -581,6 +622,10 @@ int main (int i_argc, const char* i_argv[])
result = repl_load(argv[1]);
} else if (!strcmp(":load-hex", argv[0])) { // :load-hex <size>\n <hex-encoded-binary>
result = repl_load_hex(atol(argv[1]));
} else if (!strcmp(":get-global", argv[0])) {
result = repl_global_get(argv[1]);
} else if (!strcmp(":set-global", argv[0])) {
result = repl_global_set(argv[1], argv[2]);
} else if (!strcmp(":dump", argv[0])) {
result = repl_dump();
} else if (!strcmp(":invoke", argv[0])) {

@ -750,6 +750,76 @@ _ (InitElements (io_module));
_catch: return result;
}
IM3Global m3_FindGlobal (IM3Module io_module,
const char * const i_globalName)
{
// Search exports
for (u32 i = 0; i < io_module->numGlobals; ++i)
{
IM3Global g = & io_module->globals [i];
if (g->name and strcmp (g->name, i_globalName) == 0)
{
return g;
}
}
// Search imports
for (u32 i = 0; i < io_module->numGlobals; ++i)
{
IM3Global g = & io_module->globals [i];
if (g->import.moduleUtf8 and g->import.fieldUtf8)
{
if (strcmp (g->import.fieldUtf8, i_globalName) == 0)
{
return g;
}
}
}
return NULL;
}
M3Result m3_GetGlobal (IM3Global i_global,
IM3TaggedValue o_value)
{
if (not i_global) return m3Err_globalLookupFailed;
switch (i_global->type) {
case c_m3Type_i32: o_value->value.i32 = i_global->intValue; break;
case c_m3Type_i64: o_value->value.i64 = i_global->intValue; break;
case c_m3Type_f32: o_value->value.f32 = i_global->f32Value; break;
case c_m3Type_f64: o_value->value.f64 = i_global->f64Value; break;
default: return m3Err_invalidTypeId;
}
o_value->type = i_global->type;
return m3Err_none;
}
M3Result m3_SetGlobal (IM3Global i_global,
const IM3TaggedValue i_value)
{
if (not i_global) return m3Err_globalLookupFailed;
// TODO: if (not g->isMutable) return m3Err_globalNotMutable;
if (i_global->type != i_value->type) return m3Err_globalTypeMismatch;
switch (i_value->type) {
case c_m3Type_i32: i_global->intValue = i_value->value.i32; break;
case c_m3Type_i64: i_global->intValue = i_value->value.i64; break;
case c_m3Type_f32: i_global->f32Value = i_value->value.f32; break;
case c_m3Type_f64: i_global->f64Value = i_value->value.f64; break;
default: return m3Err_invalidTypeId;
}
return m3Err_none;
}
M3ValueType m3_GetGlobalType (IM3Global i_global)
{
return (i_global) ? i_global->type : c_m3Type_none;
}
void * v_FindFunction (IM3Module i_module, const char * const i_name)
{

@ -129,6 +129,7 @@ typedef struct M3Global
#endif
};
cstr_t name;
bytes_t initExpr; // wasm code
u32 initExprSize;
u8 type;

@ -237,6 +237,12 @@ _ (ReadLEB_u32 (& index, & i_bytes, i_end));
utf8 = NULL; // ownership transferred to M3Function
}
}
else if (exportKind == d_externalKind_global)
{
_throwif(m3Err_wasmMalformed, index >= io_module->numGlobals);
io_module->globals[index].name = utf8;
utf8 = NULL; // ownership transferred to M3Global
}
m3_Free (utf8);
}

@ -28,6 +28,7 @@ struct M3Environment; typedef struct M3Environment * IM3Environment;
struct M3Runtime; typedef struct M3Runtime * IM3Runtime;
struct M3Module; typedef struct M3Module * IM3Module;
struct M3Function; typedef struct M3Function * IM3Function;
struct M3Global; typedef struct M3Global * IM3Global;
typedef struct M3ErrorInfo
{
@ -73,6 +74,18 @@ typedef enum M3ValueType
c_m3Type_unknown
} M3ValueType;
typedef struct M3TaggedValue
{
M3ValueType type;
union M3ValueUnion
{
uint32_t i32;
uint64_t i64;
float f32;
double f64;
} value;
}
M3TaggedValue, * IM3TaggedValue;
typedef struct M3ImportInfo
{
@ -143,6 +156,10 @@ d_m3ErrorConst (wasmMemoryOverflow, "runtime ran out of memory")
d_m3ErrorConst (globalMemoryNotAllocated, "global memory is missing from a module")
d_m3ErrorConst (globaIndexOutOfBounds, "global index is too large")
d_m3ErrorConst (argumentCountMismatch, "argument count mismatch")
d_m3ErrorConst (argumentTypeMismatch, "argument type mismatch")
d_m3ErrorConst (globalLookupFailed, "global lookup failed")
d_m3ErrorConst (globalTypeMismatch, "global type mismatch")
d_m3ErrorConst (globalNotMutable, "global is not mutable")
// traps
d_m3ErrorConst (trapOutOfBoundsMemoryAccess, "[trap] out of bounds memory access")
@ -224,6 +241,20 @@ d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow")
const char* m3_GetModuleName (IM3Module i_module);
IM3Runtime m3_GetModuleRuntime (IM3Module i_module);
//-------------------------------------------------------------------------------------------------------------------------------
// globals
//-------------------------------------------------------------------------------------------------------------------------------
IM3Global m3_FindGlobal (IM3Module io_module,
const char * const i_globalName);
M3Result m3_GetGlobal (IM3Global i_global,
IM3TaggedValue o_value);
M3Result m3_SetGlobal (IM3Global i_global,
const IM3TaggedValue i_value);
M3ValueType m3_GetGlobalType (IM3Global i_global);
//-------------------------------------------------------------------------------------------------------------------------------
// functions
//-------------------------------------------------------------------------------------------------------------------------------

Loading…
Cancel
Save