├── LICENSE ├── README.md ├── examples ├── Wasm_Blink │ └── Wasm_Blink.ino ├── Wasm_CoreMark │ ├── README.md │ ├── Wasm_CoreMark.ino │ └── coremark_minimal.wasm.h ├── Wasm_Dino_ESP32_TDisplay │ ├── NotoSansBold15.h │ ├── Wasm_Dino_ESP32_TDisplay.ino │ ├── dino.wasm │ ├── dino.wasm.h │ ├── dino.wat │ └── dino.wat.orig ├── Wasm_Dino_PyBadge │ ├── Wasm_Dino_PyBadge.ino │ ├── dino.wasm │ ├── dino.wasm.h │ └── dino.wat └── Wasm_Fibonacci │ └── Wasm_Fibonacci.ino ├── examples_pio └── Wasm_Advanced │ ├── .gitignore │ ├── README.md │ ├── platformio.ini │ ├── wasm_apps │ ├── assemblyscript │ │ ├── .gitignore │ │ ├── app.ts │ │ ├── app.wasm │ │ ├── app.wasm.h │ │ ├── arduino.ts │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── tsconfig.json │ │ └── yarn.lock │ ├── cpp │ │ ├── app.cpp │ │ ├── app.wasm │ │ ├── app.wasm.h │ │ ├── arduino_api.h │ │ ├── arduino_api.syms │ │ └── build.sh │ ├── rust │ │ ├── .cargo │ │ │ └── config │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── app.wasm │ │ ├── app.wasm.h │ │ ├── build.sh │ │ └── src │ │ │ ├── app.rs │ │ │ └── arduino.rs │ └── tinygo │ │ ├── app.go │ │ ├── app.wasm │ │ ├── app.wasm.h │ │ ├── arduino │ │ └── arduino.go │ │ └── build.sh │ └── wasm_vm │ └── wasm_vm.ino ├── keywords.txt ├── library.json ├── library.properties ├── src ├── m3_api_libc.c ├── m3_api_libc.h ├── m3_bind.c ├── m3_bind.h ├── m3_code.c ├── m3_code.h ├── m3_compile.c ├── m3_compile.h ├── m3_config.h ├── m3_config_platforms.h ├── m3_core.c ├── m3_core.h ├── m3_emit.c ├── m3_emit.h ├── m3_env.c ├── m3_env.h ├── m3_exception.h ├── m3_exec.c ├── m3_exec.h ├── m3_exec_defs.h ├── m3_function.c ├── m3_function.h ├── m3_info.c ├── m3_info.h ├── m3_math_utils.h ├── m3_module.c ├── m3_parse.c ├── wasm3.h └── wasm3_defs.h ├── verification.txt └── wasm_apps ├── README.md ├── assemblyscript ├── .gitignore ├── app.ts ├── app.wasm ├── app.wasm.h ├── arduino.ts ├── package-lock.json ├── package.json ├── tsconfig.json └── yarn.lock ├── cpp ├── app.cpp ├── app.wasm ├── app.wasm.h ├── arduino_api.h ├── arduino_api.syms └── build.sh ├── rust ├── .cargo │ └── config ├── .gitignore ├── Cargo.toml ├── app.wasm ├── app.wasm.h ├── build.sh └── src │ ├── app.rs │ └── arduino.rs └── tinygo ├── app.go ├── app.wasm ├── app.wasm.h └── build.sh /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Steven Massey, Volodymyr Shymanskyy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![SWUbanner](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct.svg)](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md) 2 | 3 | # Wasm3 4 | 🚀 A fast WebAssembly interpreter and the most universal WASM runtime 5 | 6 | [![WAPM](https://wapm.io/package/vshymanskyy/wasm3/badge.svg)](https://wapm.io/package/vshymanskyy/wasm3) 7 | [![GitHub issues](https://img.shields.io/github/issues-raw/wasm3/wasm3?style=flat-square&label=issues&color=success)](https://github.com/wasm3/wasm3/issues) 8 | [![Tests status](https://img.shields.io/github/actions/workflow/status/wasm3/wasm3/tests.yml?branch=main&style=flat-square&logo=github&label=tests)](https://github.com/wasm3/wasm3/actions) 9 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/wasm3/wasm3) 10 | 11 | 12 | Main repository: [**Wasm3 project**](https://github.com/wasm3/wasm3) 13 | This library can be used with 14 | [`Arduino`](https://www.arduinolibraries.info/libraries/wasm3), 15 | [`PlatformIO`](https://platformio.org/lib/show/6973/Wasm3) and 16 | [`Particle`](https://build.particle.io/libs/Wasm3/latest/tab/example/Wasm_Blink.ino). 17 | 18 | ## Supported devices 19 | 20 | Wasm3 requires at least **~64Kb** Flash and **~10Kb** RAM for minimal functionality. 21 | 22 | The library was verified to work with: 23 | `ESP32`, `ESP8266`, `Arduino MKR`, `Particle`, 24 | `RTL8711`, `ST Nucleo WB55RG`, `BluePill`, 25 | `Nordic nRF5`, `Teensy`, ... [see full list](https://github.com/wasm3/wasm3/blob/master/docs/Hardware.md) 26 | 27 | ## Disclaimer 28 | 29 | Please also note that Arduino API here is just for an example. We do not encourage this way of programming, and we have to come up with a better API (i.e. **Event-Driven**, **Resource-Oriented** or similar). 30 | 31 | ### License 32 | This project is released under The MIT License (MIT) 33 | -------------------------------------------------------------------------------- /examples/Wasm_Blink/Wasm_Blink.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Wasm3 - high performance WebAssembly interpreter written in C. 3 | * Copyright © 2020 Volodymyr Shymanskyy, Steven Massey. 4 | * All rights reserved. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | /* 11 | * Configuration 12 | */ 13 | 14 | // Redefine the default LED pin here, if needed 15 | #ifndef LED_PIN 16 | #define LED_PIN LED_BUILTIN 17 | #endif 18 | 19 | #define WASM_STACK_SLOTS 1024 20 | #define NATIVE_STACK_SIZE (32*1024) 21 | 22 | // For (most) devices that cannot allocate a 64KiB wasm page 23 | #define WASM_MEMORY_LIMIT 4096 24 | 25 | /* 26 | * WebAssembly app 27 | * 28 | * This is essentially a simple "Blink" sketch, compiled to WebAssembly 29 | * You can build a wasm binary using C/C++, Rust, AssemblyScript, TinyGo, ... 30 | * See https://github.com/wasm3/wasm3-arduino/tree/master/wasm_apps for details 31 | */ 32 | 33 | unsigned char app_wasm[] = { 34 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x04, 0x60, 35 | 0x02, 0x7f, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60, 36 | 0x00, 0x01, 0x7f, 0x02, 0x4e, 0x04, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 37 | 0x6e, 0x6f, 0x09, 0x67, 0x65, 0x74, 0x50, 0x69, 0x6e, 0x4c, 0x45, 0x44, 38 | 0x00, 0x03, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x07, 0x70, 39 | 0x69, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x00, 0x00, 0x07, 0x61, 0x72, 0x64, 40 | 0x75, 0x69, 0x6e, 0x6f, 0x0c, 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 41 | 0x57, 0x72, 0x69, 0x74, 0x65, 0x00, 0x00, 0x07, 0x61, 0x72, 0x64, 0x75, 42 | 0x69, 0x6e, 0x6f, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x00, 0x02, 0x03, 43 | 0x02, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01, 0x07, 0x13, 0x02, 0x06, 44 | 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x5f, 0x73, 0x74, 45 | 0x61, 0x72, 0x74, 0x00, 0x04, 0x0a, 0x3a, 0x01, 0x38, 0x01, 0x01, 0x7f, 46 | 0x41, 0x80, 0x08, 0x10, 0x00, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 47 | 0x41, 0x01, 0x10, 0x01, 0x03, 0x40, 0x41, 0x80, 0x08, 0x28, 0x02, 0x00, 48 | 0x41, 0x01, 0x10, 0x02, 0x41, 0xe4, 0x00, 0x10, 0x03, 0x41, 0x80, 0x08, 49 | 0x28, 0x02, 0x00, 0x41, 0x00, 0x10, 0x02, 0x41, 0x84, 0x07, 0x10, 0x03, 50 | 0x0c, 0x00, 0x0b, 0x00, 0x0b 51 | }; 52 | unsigned int app_wasm_len = 197; 53 | 54 | /* 55 | * API bindings 56 | * 57 | * Note: each RawFunction should complete with one of these calls: 58 | * m3ApiReturn(val) - Returns a value 59 | * m3ApiSuccess() - Returns void (and no traps) 60 | * m3ApiTrap(trap) - Returns a trap 61 | */ 62 | 63 | m3ApiRawFunction(m3_arduino_millis) 64 | { 65 | m3ApiReturnType (uint32_t) 66 | 67 | m3ApiReturn(millis()); 68 | } 69 | 70 | m3ApiRawFunction(m3_arduino_delay) 71 | { 72 | m3ApiGetArg (uint32_t, ms) 73 | 74 | // You can also trace API calls 75 | //Serial.print("api: delay "); Serial.println(ms); 76 | 77 | delay(ms); 78 | 79 | m3ApiSuccess(); 80 | } 81 | 82 | // This maps pin modes from arduino_wasm_api.h 83 | // to actual platform-specific values 84 | uint8_t mapPinMode(uint8_t mode) 85 | { 86 | switch(mode) { 87 | case 0: return INPUT; 88 | case 1: return OUTPUT; 89 | case 2: return INPUT_PULLUP; 90 | } 91 | return INPUT; 92 | } 93 | 94 | m3ApiRawFunction(m3_arduino_pinMode) 95 | { 96 | m3ApiGetArg (uint32_t, pin) 97 | m3ApiGetArg (uint32_t, mode) 98 | 99 | #if !defined(PARTICLE) 100 | typedef uint8_t PinMode; 101 | #endif 102 | pinMode(pin, (PinMode)mapPinMode(mode)); 103 | 104 | m3ApiSuccess(); 105 | } 106 | 107 | m3ApiRawFunction(m3_arduino_digitalWrite) 108 | { 109 | m3ApiGetArg (uint32_t, pin) 110 | m3ApiGetArg (uint32_t, value) 111 | 112 | digitalWrite(pin, value); 113 | 114 | m3ApiSuccess(); 115 | } 116 | 117 | m3ApiRawFunction(m3_arduino_getPinLED) 118 | { 119 | m3ApiReturnType (uint32_t) 120 | 121 | m3ApiReturn(LED_PIN); 122 | } 123 | 124 | m3ApiRawFunction(m3_arduino_print) 125 | { 126 | m3ApiGetArgMem (const uint8_t *, buf) 127 | m3ApiGetArg (uint32_t, len) 128 | 129 | Serial.write(buf, len); 130 | m3ApiSuccess(); 131 | } 132 | 133 | M3Result LinkArduino (IM3Runtime runtime) 134 | { 135 | IM3Module module = runtime->modules; 136 | const char* arduino = "arduino"; 137 | 138 | m3_LinkRawFunction (module, arduino, "millis", "i()", &m3_arduino_millis); 139 | m3_LinkRawFunction (module, arduino, "delay", "v(i)", &m3_arduino_delay); 140 | m3_LinkRawFunction (module, arduino, "pinMode", "v(ii)", &m3_arduino_pinMode); 141 | m3_LinkRawFunction (module, arduino, "digitalWrite", "v(ii)", &m3_arduino_digitalWrite); 142 | 143 | // Test functions 144 | m3_LinkRawFunction (module, arduino, "getPinLED", "i()", &m3_arduino_getPinLED); 145 | m3_LinkRawFunction (module, arduino, "print", "v(*i)", &m3_arduino_print); 146 | 147 | return m3Err_none; 148 | } 149 | 150 | /* 151 | * Engine start, liftoff! 152 | */ 153 | 154 | #define FATAL(func, msg) { Serial.print("Fatal: " func " "); Serial.println(msg); return; } 155 | 156 | void wasm_task(void*) 157 | { 158 | M3Result result = m3Err_none; 159 | 160 | IM3Environment env = m3_NewEnvironment (); 161 | if (!env) FATAL("NewEnvironment", "failed"); 162 | 163 | IM3Runtime runtime = m3_NewRuntime (env, WASM_STACK_SLOTS, NULL); 164 | if (!runtime) FATAL("NewRuntime", "failed"); 165 | 166 | #ifdef WASM_MEMORY_LIMIT 167 | runtime->memoryLimit = WASM_MEMORY_LIMIT; 168 | #endif 169 | 170 | IM3Module module; 171 | result = m3_ParseModule (env, &module, app_wasm, app_wasm_len); 172 | if (result) FATAL("ParseModule", result); 173 | 174 | result = m3_LoadModule (runtime, module); 175 | if (result) FATAL("LoadModule", result); 176 | 177 | result = LinkArduino (runtime); 178 | if (result) FATAL("LinkArduino", result); 179 | 180 | IM3Function f; 181 | result = m3_FindFunction (&f, runtime, "_start"); 182 | if (result) FATAL("FindFunction", result); 183 | 184 | Serial.println("Running WebAssembly..."); 185 | 186 | result = m3_CallV (f); 187 | 188 | // Should not arrive here 189 | 190 | if (result) { 191 | M3ErrorInfo info; 192 | m3_GetErrorInfo (runtime, &info); 193 | Serial.print("Error: "); 194 | Serial.print(result); 195 | Serial.print(" ("); 196 | Serial.print(info.message); 197 | Serial.println(")"); 198 | if (info.file && strlen(info.file) && info.line) { 199 | Serial.print("At "); 200 | Serial.print(info.file); 201 | Serial.print(":"); 202 | Serial.println(info.line); 203 | } 204 | } 205 | } 206 | 207 | void setup() 208 | { 209 | Serial.begin(115200); 210 | delay(100); 211 | 212 | // Wait for serial port to connect 213 | // Needed for native USB port only 214 | while(!Serial) {} 215 | 216 | Serial.println("\nWasm3 v" M3_VERSION " (" M3_ARCH "), build " __DATE__ " " __TIME__); 217 | 218 | #ifdef ESP32 219 | // On ESP32, we can launch in a separate thread 220 | xTaskCreate(&wasm_task, "wasm3", NATIVE_STACK_SIZE, NULL, 5, NULL); 221 | #else 222 | wasm_task(NULL); 223 | #endif 224 | } 225 | 226 | void loop() 227 | { 228 | delay(100); 229 | } 230 | 231 | -------------------------------------------------------------------------------- /examples/Wasm_CoreMark/README.md: -------------------------------------------------------------------------------- 1 | ## CoreMark 1.0 2 | 3 | ### RAM requirements 4 | 5 | - Wasm binary: `7.6 Kb` 6 | - Wasm3 dynamic structures: `~34Kb` 7 | - Linear Memory: `3 Kb` 8 | - Wasm Stack: `2 Kb` 9 | - Native stack: `~2 Kb` 10 | - **Total: `~44Kb`** 11 | 12 | Note: if no TCO is available, native stack can get much larger. 13 | I.e. it grows to `48 Kb` for ESP32. And this causes ESP8266 to hang. 14 | This will be improved in future. 🦄 15 | 16 | ### Results for some boards 17 | ```log 18 | Board | MCU | Freq | CoreMark 19 | ----------------------------------------------------------------- 20 | Teensy 4.0 iMXRT1062 1 GHz 109.842 21 | Teensy 4.0 iMXRT1062 816 MHz 88.925 22 | Teensy 4.0 iMXRT1062 600 MHz 65.383 23 | Sipeed MAIX BiT Kendryte K210 400 MHz 60.730 24 | Adafruit pyBadge ATSAMD51J19 200 MHz 15.315 25 | Adafruit pyBadge ATSAMD51J19 120 MHz 9.193 26 | ESP32 ESP32 240 MHz 8.778 27 | ESP8266 ESP8266 80 MHz (hangs) 28 | Teensy 3.2 fastest+lto MK20DX256 120 MHz 6.800 29 | BLE Nano 2 nRF52832 64 MHz 3.938 30 | BBC micro:bit v2 nRF52833 64 MHz 3.908 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /examples/Wasm_CoreMark/Wasm_CoreMark.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Wasm3 - high performance WebAssembly interpreter written in C. 3 | * Copyright © 2020 Volodymyr Shymanskyy, Steven Massey. 4 | * All rights reserved. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "coremark_minimal.wasm.h" 11 | 12 | m3ApiRawFunction(env_clock_ms) 13 | { 14 | m3ApiReturnType (uint32_t) 15 | m3ApiReturn(millis()); 16 | } 17 | 18 | IM3Environment env; 19 | IM3Runtime runtime; 20 | IM3Module module; 21 | IM3Function func_run; 22 | 23 | #define FATAL(func, msg) { Serial.print("Fatal: " func " "); Serial.println(msg); while(1) { delay(100); } } 24 | 25 | void wasm_task(void*) 26 | { 27 | M3Result result = m3Err_none; 28 | 29 | result = m3_FindFunction (&func_run, runtime, "run"); 30 | if (result) FATAL("FindFunction", result); 31 | 32 | Serial.println("Running CoreMark 1.0..."); 33 | 34 | result = m3_CallV (func_run); 35 | if (result) FATAL("Call", result); 36 | 37 | float value = 0; 38 | result = m3_GetResultsV (func_run, &value); 39 | if (result) FATAL("GetResults: %s", result); 40 | 41 | Serial.print("Result: "); 42 | Serial.println(value, 3); 43 | 44 | if (result != m3Err_none) { 45 | M3ErrorInfo info; 46 | m3_GetErrorInfo (runtime, &info); 47 | Serial.print("Error: "); 48 | Serial.print(result); 49 | Serial.print(" ("); 50 | Serial.print(info.message); 51 | Serial.println(")"); 52 | if (info.file && strlen(info.file) && info.line) { 53 | Serial.print("At "); 54 | Serial.print(info.file); 55 | Serial.print(":"); 56 | Serial.println(info.line); 57 | } 58 | } 59 | 60 | #ifdef ESP32 61 | vTaskDelete(NULL); 62 | #endif 63 | } 64 | 65 | void setup() 66 | { 67 | Serial.begin(115200); 68 | delay(500); 69 | 70 | // Wait for serial port to connect 71 | // Needed for native USB port only 72 | //while(!Serial) {} 73 | 74 | Serial.println(); 75 | Serial.println("Wasm3 v" M3_VERSION " build " __DATE__ " " __TIME__); 76 | Serial.println("CPU: " M3_ARCH " @ " + String(F_CPU/1000000) + " MHz"); 77 | 78 | M3Result result = m3Err_none; 79 | 80 | env = m3_NewEnvironment (); 81 | if (!env) FATAL("NewEnvironment", "failed"); 82 | 83 | runtime = m3_NewRuntime (env, 2048, NULL); 84 | if (!runtime) FATAL("NewRuntime", "failed"); 85 | 86 | runtime->memoryLimit = 3*1024; 87 | 88 | result = m3_ParseModule (env, &module, coremark_minimal_wasm, coremark_minimal_wasm_len); 89 | if (result) FATAL("ParseModule", result); 90 | 91 | result = m3_LoadModule (runtime, module); 92 | if (result) FATAL("LoadModule", result); 93 | 94 | m3_LinkRawFunction (module, "env", "clock_ms", "i()", &env_clock_ms); 95 | 96 | #if defined(ESP8266) 97 | ESP.wdtDisable(); 98 | *((volatile uint32_t*) 0x60000900) &= ~(1); // Hardware WDT OFF 99 | wasm_task(NULL); 100 | #elif defined(ESP32) 101 | Serial.println("Launching a separate task"); 102 | disableCore0WDT(); 103 | xTaskCreate(&wasm_task, "wasm3", 64*1024, NULL, 5, NULL); 104 | #else 105 | wasm_task(NULL); 106 | #endif 107 | } 108 | 109 | void loop() 110 | { 111 | delay(100); 112 | } 113 | -------------------------------------------------------------------------------- /examples/Wasm_Dino_ESP32_TDisplay/Wasm_Dino_ESP32_TDisplay.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Wasm3 - high performance WebAssembly interpreter written in C. 3 | * Copyright © 2021 Volodymyr Shymanskyy, Steven Massey. 4 | * All rights reserved. 5 | */ 6 | 7 | #include 8 | #include 9 | #include "NotoSansBold15.h" 10 | 11 | #include 12 | 13 | #define NATIVE_STACK_SIZE (32*1024) 14 | 15 | #define BUTTON_UP 35 16 | #define BUTTON_DOWN 0 17 | 18 | #define DISPLAY_BRIGHTESS 128 // 0..255 19 | 20 | TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library 21 | 22 | /* 23 | * Dino game by by Ben Smith (binji) 24 | * https://github.com/binji/raw-wasm/tree/master/dino 25 | * To build: 26 | * export PATH=/opt/wasp/build/src/tools:$PATH 27 | * wasp wat2wasm --enable-numeric-values -o dino.wasm dino.wat 28 | * xxd -iC dino.wasm > dino.wasm.h 29 | * 30 | * Note: In Arduino IDE, select Tools->Optimize->Faster (-O3) 31 | */ 32 | #include "dino.wasm.h" 33 | 34 | /* 35 | * Engine start, liftoff! 36 | */ 37 | 38 | #define FATAL(func, msg) { Serial.print("Fatal: " func " "); Serial.println(msg); while(1) { delay(100); } } 39 | #define TSTART() { tstart = micros(); } 40 | #define TFINISH(s) { tend = micros(); Serial.print(s " in "); Serial.print(tend-tstart); Serial.println(" us"); } 41 | 42 | // The Math.random() function returns a floating-point, 43 | // pseudo-random number in the range 0 to less than 1 44 | m3ApiRawFunction(Math_random) 45 | { 46 | m3ApiReturnType (float) 47 | 48 | float r = (float)random(INT_MAX)/INT_MAX; 49 | //Serial.print("Random: "); Serial.println(r); 50 | 51 | m3ApiReturn(r); 52 | } 53 | 54 | // Memcpy is generic, and much faster in native code 55 | m3ApiRawFunction(Dino_memcpy) 56 | { 57 | m3ApiGetArgMem (uint8_t *, dst) 58 | m3ApiGetArgMem (uint8_t *, src) 59 | m3ApiGetArgMem (uint8_t *, dstend) 60 | 61 | do { 62 | *dst++ = *src++; 63 | } while (dst < dstend); 64 | 65 | m3ApiSuccess(); 66 | } 67 | 68 | IM3Environment env; 69 | IM3Runtime runtime; 70 | IM3Module module; 71 | IM3Function func_run; 72 | uint8_t* mem; 73 | 74 | void load_wasm() 75 | { 76 | M3Result result = m3Err_none; 77 | 78 | if (!env) { 79 | env = m3_NewEnvironment (); 80 | if (!env) FATAL("NewEnvironment", "failed"); 81 | } 82 | 83 | m3_FreeRuntime(runtime); 84 | 85 | runtime = m3_NewRuntime (env, 1024, NULL); 86 | if (!runtime) FATAL("NewRuntime", "failed"); 87 | 88 | result = m3_ParseModule (env, &module, dino_wasm, sizeof(dino_wasm)); 89 | if (result) FATAL("ParseModule", result); 90 | 91 | result = m3_LoadModule (runtime, module); 92 | if (result) FATAL("LoadModule", result); 93 | 94 | m3_LinkRawFunction (module, "Math", "random", "f()", &Math_random); 95 | m3_LinkRawFunction (module, "Dino", "memcpy", "v(iii)", &Dino_memcpy); 96 | 97 | mem = m3_GetMemory (runtime, NULL, 0); 98 | if (!mem) FATAL("GetMemory", "failed"); 99 | 100 | result = m3_FindFunction (&func_run, runtime, "run"); 101 | if (result) FATAL("FindFunction", result); 102 | } 103 | 104 | void init_device() 105 | { 106 | pinMode(BUTTON_UP, INPUT); 107 | pinMode(BUTTON_DOWN, INPUT); 108 | 109 | // Try to randomize seed 110 | randomSeed((analogRead(A5) << 16) + analogRead(A4)); 111 | Serial.print("Random: 0x"); Serial.println(random(INT_MAX), HEX); 112 | 113 | tft.init(); 114 | tft.setRotation(1); 115 | tft.setSwapBytes(true); 116 | tft.loadFont(NotoSansBold15); 117 | 118 | // Set backlight brightness 119 | ledcSetup(0, 5000, 8); 120 | ledcAttachPin(TFT_BL, 0); 121 | ledcWrite(0, DISPLAY_BRIGHTESS); 122 | } 123 | 124 | void display_info() 125 | { 126 | tft.fillScreen(TFT_WHITE); 127 | tft.setTextColor(TFT_BLACK, TFT_WHITE); 128 | tft.setCursor(0, 5); 129 | tft.println(" Wasm3 v" M3_VERSION " (ESP32)"); 130 | tft.println(" Dino game"); 131 | tft.println(" by Ben Smith (binji)"); 132 | } 133 | 134 | void setup() 135 | { 136 | Serial.begin(115200); 137 | 138 | Serial.println("\nWasm3 v" M3_VERSION " (" M3_ARCH "), build " __DATE__ " " __TIME__); 139 | 140 | uint32_t tend, tstart; 141 | TSTART(); 142 | init_device(); 143 | display_info(); 144 | TFINISH("Device init"); 145 | 146 | TSTART(); 147 | load_wasm(); 148 | TFINISH("Wasm3 init"); 149 | 150 | Serial.println("Running WebAssembly..."); 151 | 152 | xTaskCreate(&wasm_task, "wasm3", NATIVE_STACK_SIZE, NULL, 5, NULL); 153 | } 154 | 155 | void wasm_task(void*) 156 | { 157 | M3Result result; 158 | uint64_t last_fps_print = 0; 159 | 160 | while (true) { 161 | const uint64_t framestart = micros(); 162 | 163 | // Process inputs 164 | uint32_t* input = (uint32_t*)(mem + 0x0000); 165 | *input = 0; 166 | if (LOW == digitalRead(BUTTON_UP)) { 167 | *input |= 0x1; 168 | } 169 | if (LOW == digitalRead(BUTTON_DOWN)) { 170 | *input |= 0x2; 171 | } 172 | 173 | // Render frame 174 | result = m3_CallV (func_run); 175 | if (result) break; 176 | 177 | // Output to display 178 | tft.pushImage(0, 135-10-75, 240, 75, (uint16_t*)(mem+0x5000)); 179 | 180 | const uint64_t frametime = micros() - framestart; 181 | const uint32_t target_frametime = 1000000/50; 182 | if (target_frametime > frametime) { 183 | delay((target_frametime - frametime)/1000); 184 | } 185 | if (framestart - last_fps_print > 1000000) { 186 | Serial.print("FPS: "); Serial.println((uint32_t)(1000000/frametime)); 187 | last_fps_print = framestart; 188 | } 189 | } 190 | 191 | if (result != m3Err_none) { 192 | M3ErrorInfo info; 193 | m3_GetErrorInfo (runtime, &info); 194 | Serial.print("Error: "); 195 | Serial.print(result); 196 | Serial.print(" ("); 197 | Serial.print(info.message); 198 | Serial.println(")"); 199 | if (info.file && strlen(info.file) && info.line) { 200 | Serial.print("At "); 201 | Serial.print(info.file); 202 | Serial.print(":"); 203 | Serial.println(info.line); 204 | } 205 | } 206 | } 207 | 208 | void loop() 209 | { 210 | delay(100); 211 | } 212 | -------------------------------------------------------------------------------- /examples/Wasm_Dino_ESP32_TDisplay/dino.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wasm3/wasm3-arduino/0dcff083f369f89d7bd5d434d60e63d789fab133/examples/Wasm_Dino_ESP32_TDisplay/dino.wasm -------------------------------------------------------------------------------- /examples/Wasm_Dino_ESP32_TDisplay/dino.wasm.h: -------------------------------------------------------------------------------- 1 | unsigned char dino_wasm[] = { 2 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1b, 0x05, 0x60, 3 | 0x00, 0x00, 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x00, 0x60, 0x01, 0x7f, 0x01, 4 | 0x7f, 0x60, 0x04, 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 5 | 0x7d, 0x02, 0x1d, 0x02, 0x04, 0x4d, 0x61, 0x74, 0x68, 0x06, 0x72, 0x61, 6 | 0x6e, 0x64, 0x6f, 0x6d, 0x00, 0x04, 0x04, 0x44, 0x69, 0x6e, 0x6f, 0x06, 7 | 0x6d, 0x65, 0x6d, 0x63, 0x70, 0x79, 0x00, 0x01, 0x03, 0x05, 0x04, 0x00, 8 | 0x02, 0x03, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x20, 0x05, 0x7f, 9 | 0x01, 0x41, 0x00, 0x0b, 0x7f, 0x01, 0x41, 0x00, 0x0b, 0x7f, 0x01, 0x41, 10 | 0x00, 0x0b, 0x7d, 0x01, 0x43, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x7d, 0x01, 11 | 0x43, 0x00, 0x00, 0x00, 0xbf, 0x0b, 0x07, 0x18, 0x03, 0x03, 0x6d, 0x65, 12 | 0x6d, 0x02, 0x00, 0x08, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x36, 0x35, 13 | 0x00, 0x03, 0x03, 0x72, 0x75, 0x6e, 0x00, 0x05, 0x08, 0x01, 0x02, 0x0a, 14 | 0xab, 0x08, 0x04, 0xf5, 0x01, 0x01, 0x0a, 0x7f, 0x41, 0x07, 0x21, 0x03, 15 | 0x41, 0xbb, 0x06, 0x21, 0x00, 0x03, 0x40, 0x20, 0x04, 0x41, 0x10, 0x49, 16 | 0x04, 0x40, 0x20, 0x05, 0x20, 0x01, 0x2f, 0x01, 0xd0, 0x02, 0x20, 0x04, 17 | 0x74, 0x72, 0x21, 0x05, 0x20, 0x04, 0x41, 0x10, 0x6a, 0x21, 0x04, 0x20, 18 | 0x01, 0x41, 0x02, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x05, 0x41, 0x01, 0x20, 19 | 0x03, 0x74, 0x41, 0x01, 0x6b, 0x71, 0x21, 0x02, 0x20, 0x05, 0x20, 0x03, 20 | 0x76, 0x21, 0x05, 0x20, 0x04, 0x20, 0x03, 0x6b, 0x21, 0x04, 0x02, 0x40, 21 | 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x06, 0x0e, 0x03, 22 | 0x00, 0x01, 0x04, 0x03, 0x0b, 0x20, 0x02, 0x22, 0x07, 0x45, 0x0d, 0x01, 23 | 0x41, 0x01, 0x21, 0x06, 0x41, 0x04, 0x21, 0x03, 0x0c, 0x04, 0x0b, 0x20, 24 | 0x00, 0x20, 0x02, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 25 | 0x00, 0x20, 0x07, 0x41, 0x01, 0x6b, 0x22, 0x07, 0x0d, 0x03, 0x0b, 0x41, 26 | 0x02, 0x21, 0x06, 0x41, 0x07, 0x21, 0x03, 0x0c, 0x02, 0x0b, 0x20, 0x00, 27 | 0x20, 0x00, 0x20, 0x09, 0x6b, 0x20, 0x00, 0x20, 0x02, 0x6a, 0x22, 0x00, 28 | 0x10, 0x01, 0x41, 0x00, 0x21, 0x06, 0x0c, 0x01, 0x0b, 0x20, 0x02, 0x21, 29 | 0x09, 0x41, 0x03, 0x21, 0x06, 0x20, 0x01, 0x41, 0xee, 0x03, 0x49, 0x0d, 30 | 0x00, 0x0b, 0x03, 0x40, 0x20, 0x01, 0x2d, 0x00, 0xcd, 0x02, 0x22, 0x02, 31 | 0x04, 0x40, 0x20, 0x00, 0x20, 0x08, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x41, 32 | 0x01, 0x6a, 0x20, 0x00, 0x20, 0x00, 0x20, 0x02, 0x6a, 0x22, 0x00, 0x10, 33 | 0x01, 0x0b, 0x20, 0x08, 0x45, 0x21, 0x08, 0x20, 0x01, 0x41, 0x01, 0x6a, 34 | 0x22, 0x01, 0x41, 0xc0, 0x0f, 0x49, 0x0d, 0x00, 0x0b, 0x0b, 0x2b, 0x00, 35 | 0x41, 0xff, 0x01, 0x20, 0x00, 0x6b, 0x22, 0x00, 0x41, 0x1f, 0x6c, 0x41, 36 | 0xff, 0x01, 0x6e, 0x20, 0x00, 0x41, 0x3f, 0x6c, 0x41, 0xff, 0x01, 0x6e, 37 | 0x41, 0x05, 0x74, 0x20, 0x00, 0x41, 0x1f, 0x6c, 0x41, 0xff, 0x01, 0x6e, 38 | 0x41, 0x0b, 0x74, 0x72, 0x72, 0x0b, 0xc0, 0x01, 0x01, 0x05, 0x7f, 0x20, 39 | 0x02, 0x2d, 0x00, 0xa9, 0x02, 0x22, 0x04, 0x21, 0x07, 0x20, 0x02, 0x2d, 40 | 0x00, 0xaa, 0x02, 0x21, 0x05, 0x20, 0x02, 0x2d, 0x00, 0xab, 0x02, 0x10, 41 | 0x03, 0x21, 0x02, 0x20, 0x00, 0x41, 0x00, 0x48, 0x04, 0x40, 0x20, 0x00, 42 | 0x20, 0x04, 0x6a, 0x21, 0x04, 0x20, 0x03, 0x20, 0x00, 0x6b, 0x21, 0x03, 43 | 0x41, 0x00, 0x21, 0x00, 0x05, 0x41, 0xf0, 0x01, 0x20, 0x00, 0x6b, 0x20, 44 | 0x04, 0x20, 0x00, 0x20, 0x04, 0x6a, 0x41, 0xf0, 0x01, 0x4a, 0x1b, 0x21, 45 | 0x04, 0x0b, 0x20, 0x04, 0x41, 0x00, 0x4a, 0x04, 0x40, 0x20, 0x01, 0x41, 46 | 0xf0, 0x01, 0x6c, 0x20, 0x00, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x41, 0x00, 47 | 0x21, 0x00, 0x03, 0x40, 0x20, 0x00, 0x20, 0x03, 0x6a, 0x2d, 0x00, 0x8d, 48 | 0x12, 0x04, 0x40, 0x20, 0x06, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x41, 0x01, 49 | 0x74, 0x22, 0x08, 0x2f, 0x01, 0x80, 0xa0, 0x01, 0x41, 0x8a, 0xa5, 0x01, 50 | 0x46, 0x72, 0x21, 0x06, 0x20, 0x08, 0x20, 0x02, 0x3b, 0x01, 0x80, 0xa0, 51 | 0x01, 0x0b, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x22, 0x00, 0x20, 0x04, 0x48, 52 | 0x0d, 0x00, 0x0b, 0x20, 0x01, 0x41, 0xf0, 0x01, 0x6a, 0x21, 0x01, 0x20, 53 | 0x03, 0x20, 0x07, 0x6a, 0x21, 0x03, 0x20, 0x05, 0x41, 0x01, 0x6b, 0x22, 54 | 0x05, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x06, 0x0b, 0xc3, 0x04, 0x02, 0x03, 55 | 0x7f, 0x01, 0x7d, 0x41, 0x80, 0xa0, 0x01, 0x41, 0xff, 0x9f, 0x01, 0x41, 56 | 0xa0, 0xb9, 0x03, 0x10, 0x01, 0x23, 0x00, 0x41, 0x01, 0x6a, 0x24, 0x00, 57 | 0x23, 0x04, 0x43, 0x00, 0x00, 0x00, 0x3b, 0x93, 0x43, 0x00, 0x00, 0x80, 58 | 0xbf, 0x97, 0x24, 0x04, 0x41, 0x00, 0x2d, 0x00, 0x00, 0x21, 0x00, 0x41, 59 | 0x05, 0x2a, 0x02, 0x00, 0x21, 0x03, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 60 | 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x23, 0x02, 0x0e, 0x04, 61 | 0x01, 0x02, 0x03, 0x04, 0x00, 0x0b, 0x41, 0x0b, 0x21, 0x01, 0x43, 0x00, 62 | 0x00, 0x00, 0x00, 0x24, 0x04, 0x20, 0x00, 0x45, 0x23, 0x00, 0x23, 0x01, 63 | 0x6b, 0x41, 0x14, 0x4d, 0x72, 0x0d, 0x05, 0x41, 0x00, 0x24, 0x01, 0x41, 64 | 0x00, 0x24, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x24, 0x03, 0x43, 0x00, 65 | 0x00, 0x00, 0xbf, 0x24, 0x04, 0x0b, 0x43, 0x00, 0x00, 0x48, 0x42, 0x21, 66 | 0x03, 0x41, 0x04, 0x41, 0xdb, 0x9f, 0x01, 0x41, 0x28, 0x10, 0x01, 0x41, 67 | 0x01, 0x24, 0x02, 0x0b, 0x20, 0x00, 0x41, 0x02, 0x46, 0x41, 0x09, 0x6a, 68 | 0x21, 0x01, 0x20, 0x00, 0x41, 0x01, 0x47, 0x0d, 0x02, 0x41, 0x02, 0x24, 69 | 0x02, 0x43, 0x00, 0x00, 0xc0, 0xc0, 0x24, 0x03, 0x0b, 0x20, 0x00, 0x41, 70 | 0x01, 0x46, 0x20, 0x03, 0x43, 0x00, 0x00, 0xf0, 0x41, 0x60, 0x72, 0x20, 71 | 0x03, 0x43, 0x00, 0x00, 0x20, 0x41, 0x60, 0x71, 0x0d, 0x00, 0x41, 0x03, 72 | 0x24, 0x02, 0x43, 0x00, 0x00, 0x80, 0xbf, 0x24, 0x03, 0x0b, 0x41, 0x08, 73 | 0x21, 0x01, 0x20, 0x03, 0x23, 0x03, 0x92, 0x21, 0x03, 0x23, 0x03, 0x43, 74 | 0xcd, 0xcc, 0xcc, 0x3e, 0x92, 0x24, 0x03, 0x20, 0x03, 0x43, 0x00, 0x00, 75 | 0x48, 0x42, 0x5f, 0x0d, 0x00, 0x41, 0x01, 0x24, 0x02, 0x43, 0x00, 0x00, 76 | 0x48, 0x42, 0x21, 0x03, 0x43, 0x00, 0x00, 0x00, 0x00, 0x24, 0x03, 0x0b, 77 | 0x23, 0x01, 0x41, 0x01, 0x6a, 0x24, 0x01, 0x0b, 0x41, 0x04, 0x20, 0x01, 78 | 0x3a, 0x00, 0x00, 0x41, 0x05, 0x20, 0x03, 0x38, 0x02, 0x00, 0x41, 0xf9, 79 | 0x00, 0x21, 0x00, 0x03, 0x40, 0x20, 0x00, 0x2a, 0x02, 0x05, 0xa8, 0x20, 80 | 0x00, 0x2d, 0x00, 0x00, 0x41, 0x07, 0x6c, 0x22, 0x01, 0x2d, 0x00, 0x83, 81 | 0x01, 0x41, 0x02, 0x74, 0x23, 0x00, 0x41, 0x0f, 0x71, 0x41, 0x02, 0x76, 82 | 0x6a, 0x22, 0x02, 0x2d, 0x00, 0xdc, 0x01, 0x20, 0x00, 0x2a, 0x02, 0x01, 83 | 0xa8, 0x6a, 0x20, 0x01, 0x2d, 0x00, 0x84, 0x01, 0x20, 0x02, 0x2d, 0x00, 84 | 0xec, 0x01, 0x6a, 0x22, 0x02, 0x2d, 0x00, 0xfc, 0x01, 0x20, 0x02, 0x2f, 85 | 0x01, 0xfd, 0x01, 0x10, 0x04, 0x20, 0x00, 0x41, 0x04, 0x46, 0x71, 0x04, 86 | 0x40, 0x41, 0x04, 0x24, 0x02, 0x0b, 0x20, 0x00, 0x2a, 0x02, 0x05, 0x20, 87 | 0x01, 0x2d, 0x00, 0x88, 0x01, 0xb3, 0x23, 0x04, 0x94, 0x92, 0x22, 0x03, 88 | 0x43, 0x00, 0x00, 0x80, 0xc2, 0x5d, 0x04, 0x40, 0x20, 0x00, 0x10, 0x00, 89 | 0x20, 0x01, 0x2d, 0x00, 0x82, 0x01, 0x41, 0x01, 0x74, 0x22, 0x01, 0x2d, 90 | 0x00, 0xd7, 0x01, 0xb3, 0x94, 0xa8, 0x20, 0x01, 0x2d, 0x00, 0xd6, 0x01, 91 | 0x6a, 0x22, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x43, 0x00, 0x00, 0x98, 92 | 0x43, 0x92, 0x20, 0x01, 0x41, 0x07, 0x6c, 0x22, 0x01, 0x2d, 0x00, 0x85, 93 | 0x01, 0x41, 0x03, 0x74, 0xb3, 0x92, 0x21, 0x03, 0x20, 0x00, 0x20, 0x01, 94 | 0x2d, 0x00, 0x86, 0x01, 0xb3, 0x10, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x87, 95 | 0x01, 0xb3, 0x94, 0x92, 0x38, 0x02, 0x01, 0x0b, 0x20, 0x00, 0x20, 0x03, 96 | 0x38, 0x02, 0x05, 0x20, 0x00, 0x41, 0x09, 0x6b, 0x22, 0x00, 0x41, 0x00, 97 | 0x4a, 0x0d, 0x00, 0x0b, 0x23, 0x01, 0x21, 0x00, 0x41, 0xe6, 0x01, 0x21, 98 | 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, 0x04, 0x6b, 0x22, 0x01, 0x41, 0x04, 99 | 0x41, 0x21, 0x20, 0x00, 0x41, 0x0a, 0x70, 0x41, 0x0f, 0x6c, 0x41, 0xcc, 100 | 0x2f, 0x6a, 0x10, 0x04, 0x1a, 0x20, 0x00, 0x41, 0x0a, 0x6e, 0x22, 0x00, 101 | 0x0d, 0x00, 0x0b, 0x23, 0x02, 0x41, 0x04, 0x46, 0x04, 0x40, 0x41, 0xe4, 102 | 0x00, 0x41, 0x21, 0x41, 0x24, 0x41, 0xe2, 0x30, 0x10, 0x04, 0x1a, 0x0b, 103 | 0x0b, 0x0b, 0xc6, 0x06, 0x02, 0x00, 0x41, 0x28, 0x0b, 0x93, 0x06, 0x07, 104 | 0x00, 0x00, 0x86, 0x42, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x86, 105 | 0x42, 0x00, 0x00, 0x80, 0x42, 0x07, 0x00, 0x00, 0x86, 0x42, 0x00, 0x00, 106 | 0x00, 0x43, 0x07, 0x00, 0x00, 0x86, 0x42, 0x00, 0x00, 0x40, 0x43, 0x07, 107 | 0x00, 0x00, 0x86, 0x42, 0x00, 0x00, 0x80, 0x43, 0x07, 0x00, 0x00, 0x86, 108 | 0x42, 0x00, 0x00, 0xa0, 0x43, 0x06, 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 109 | 0x00, 0x00, 0x06, 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0x00, 0x43, 0x06, 110 | 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0x80, 0x43, 0x06, 0x00, 0x00, 0x20, 111 | 0x42, 0x00, 0x00, 0xc0, 0x43, 0x00, 0x00, 0x12, 0x4b, 0x2e, 0x00, 0x04, 112 | 0x00, 0x00, 0x15, 0x4b, 0x36, 0x00, 0x04, 0x00, 0x00, 0x18, 0x4b, 0x36, 113 | 0x00, 0x04, 0x00, 0x00, 0x1b, 0x4b, 0x36, 0x00, 0x04, 0x00, 0x00, 0x1e, 114 | 0x4b, 0x2e, 0x00, 0x04, 0x00, 0x03, 0x27, 0x4b, 0x19, 0x19, 0x05, 0x01, 115 | 0x00, 0x21, 0x1e, 0x0f, 0x19, 0x01, 0x02, 0x00, 0x24, 0x00, 0x43, 0x00, 116 | 0x04, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x06, 0x00, 117 | 0x00, 0x00, 0x00, 0x03, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 118 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x01, 0x07, 0x01, 0x00, 119 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x00, 120 | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 121 | 0x03, 0x00, 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0xb8, 122 | 0x01, 0x00, 0x70, 0x03, 0x00, 0x28, 0x05, 0x03, 0xe0, 0x06, 0x03, 0x4c, 123 | 0x08, 0x06, 0xb8, 0x09, 0x09, 0x0a, 0x0b, 0x0c, 0x60, 0x0c, 0x0f, 0x58, 124 | 0x0e, 0x12, 0xfa, 0x0e, 0x15, 0x0a, 0x13, 0x18, 0xda, 0x13, 0x1b, 0x1a, 125 | 0x15, 0x1e, 0x5c, 0x16, 0x14, 0x16, 0xaa, 0x1c, 0x0d, 0xaa, 0x0d, 0x1a, 126 | 0xac, 0x13, 0x12, 0xac, 0x1c, 0x12, 0xac, 0x09, 0x12, 0xac, 0x28, 0x1a, 127 | 0xac, 0x1a, 0x08, 0x25, 0x40, 0x05, 0xaa, 0x17, 0x0e, 0xac, 0x17, 0x10, 128 | 0xac, 0x03, 0x05, 0xac, 0x32, 0x08, 0xac, 0x91, 0xc5, 0x95, 0x29, 0x95, 129 | 0x88, 0x28, 0x95, 0x29, 0x0d, 0x18, 0x72, 0x28, 0x81, 0x65, 0x71, 0x66, 130 | 0x42, 0x4a, 0x23, 0x19, 0x41, 0x6e, 0x7e, 0x9c, 0xab, 0xc9, 0xe7, 0x13, 131 | 0xe2, 0x32, 0xe1, 0x41, 0xe1, 0x32, 0xf2, 0x40, 0xb8, 0xaa, 0x12, 0x07, 132 | 0x3c, 0x08, 0xea, 0x85, 0xe3, 0x87, 0x0c, 0xcb, 0xc3, 0xc4, 0x03, 0xc9, 133 | 0x43, 0x02, 0x61, 0x48, 0x11, 0x79, 0x91, 0x78, 0xa0, 0x78, 0x20, 0xc1, 134 | 0x78, 0x18, 0x8c, 0xa1, 0x94, 0x87, 0x8f, 0x8b, 0x07, 0x96, 0x87, 0x9d, 135 | 0x07, 0xa5, 0x07, 0x52, 0x96, 0x43, 0x9b, 0x78, 0x98, 0x90, 0x19, 0x79, 136 | 0x10, 0x09, 0x79, 0xd8, 0xd4, 0x21, 0x20, 0x40, 0x15, 0x62, 0x64, 0x42, 137 | 0x1e, 0xc4, 0xb7, 0x28, 0xe8, 0x64, 0xa1, 0x20, 0x91, 0x90, 0x90, 0x90, 138 | 0x0a, 0x0b, 0x82, 0xa6, 0xf0, 0xb1, 0x83, 0x32, 0x05, 0x40, 0x60, 0xe8, 139 | 0x9c, 0xa0, 0xdc, 0xdc, 0xd8, 0x48, 0x84, 0xc4, 0x44, 0xd0, 0x84, 0x84, 140 | 0xc4, 0xc4, 0x88, 0x02, 0x21, 0xa0, 0x50, 0x60, 0x2a, 0x16, 0x14, 0x26, 141 | 0x15, 0x14, 0x55, 0x7c, 0x25, 0x75, 0x63, 0x43, 0xd0, 0x08, 0x4e, 0x0c, 142 | 0x08, 0x80, 0xd1, 0x30, 0x20, 0x09, 0x46, 0x63, 0x10, 0x32, 0x60, 0x44, 143 | 0x41, 0x42, 0x42, 0xe0, 0x0b, 0x00, 0x04, 0x15, 0x30, 0xc7, 0xc1, 0x55, 144 | 0x41, 0x51, 0x22, 0x31, 0x21, 0xd2, 0x24, 0x31, 0x21, 0x44, 0x52, 0x64, 145 | 0x21, 0x24, 0x36, 0x85, 0x24, 0x36, 0x57, 0x25, 0x36, 0x37, 0x67, 0xa8, 146 | 0x00, 0x04, 0x86, 0x41, 0x50, 0x10, 0x20, 0x07, 0x8c, 0x0a, 0xa3, 0x12, 147 | 0x21, 0x2a, 0x36, 0x36, 0x29, 0x0f, 0x2a, 0x4a, 0x19, 0x4d, 0x49, 0x38, 148 | 0x6c, 0x58, 0x2c, 0x70, 0x82, 0x92, 0x70, 0x42, 0x4a, 0xd1, 0x38, 0x54, 149 | 0x0c, 0x89, 0x90, 0xe3, 0x30, 0x90, 0x12, 0xc7, 0x87, 0x10, 0x12, 0xe6, 150 | 0x68, 0x14, 0x6a, 0x42, 0xd0, 0x91, 0x28, 0x0c, 0xc9, 0x9c, 0x83, 0x21, 151 | 0x20, 0x73, 0x28, 0x18, 0x21, 0x21, 0x21, 0x43, 0x22, 0xc1, 0x90, 0x05, 152 | 0x01, 0x63, 0xc5, 0xa1, 0x28, 0x1c, 0x59, 0x99, 0x0a, 0x41, 0x48, 0xb2, 153 | 0x62, 0x28, 0x08, 0x38, 0x81, 0x08, 0xc3, 0x42, 0x8c, 0x28, 0x09, 0x87, 154 | 0xc4, 0x10, 0xa1, 0xd4, 0xdb, 0x03, 0x49, 0xc5, 0x83, 0xc4, 0xc9, 0x8b, 155 | 0x85, 0x0c, 0x92, 0x4b, 0xc5, 0x43, 0x05, 0xc5, 0x83, 0x49, 0xc4, 0x3c, 156 | 0x08, 0x10, 0x81, 0x4c, 0x20, 0x18, 0x15, 0x0f, 0x1b, 0x0f, 0x1f, 0x2a, 157 | 0x1f, 0x45, 0x71, 0x84, 0x23, 0xe3, 0x21, 0xe5, 0xc1, 0xe6, 0xa1, 0xe8, 158 | 0x21, 0x44, 0xc8, 0x47, 0x8a, 0x2b, 0x4c, 0x2d, 0x0e, 0xdf, 0xd5, 0x1f, 159 | 0x02, 0x99, 0x7b, 0xf3, 0x2f, 0xe5, 0xa1, 0xe6, 0x81, 0xea, 0x41, 0xec, 160 | 0x21, 0x40, 0x09, 0xe0, 0x7a, 0x2e, 0x6b, 0xd3, 0x03, 0xcd, 0x43, 0xc9, 161 | 0x83, 0xc9, 0x83, 0x85, 0x53, 0x48, 0x48, 0x98, 0x84, 0x84, 0x44, 0x98, 162 | 0x94, 0x98, 0x90, 0x54, 0x48, 0x90, 0x84, 0x94, 0x8c, 0xa0, 0x50, 0x1c, 163 | 0xc8, 0x20, 0x92, 0x8a, 0x0a, 0x0c, 0x92, 0x90, 0x08, 0x9a, 0x19, 0x11, 164 | 0x11, 0x9a, 0x11, 0x09, 0x09, 0x0a, 0x0a, 0x03, 0x1d, 0x04, 0x15, 0x12, 165 | 0x83, 0xe0, 0x24, 0x67, 0x20, 0x60, 0x08, 0x0d, 0x0f, 0x87, 0x90, 0x91, 166 | 0xa0, 0x12, 0x19, 0x06, 0x12, 0x24, 0x3a, 0x00, 0x80, 0x06, 0x82, 0xc4, 167 | 0x84, 0x86, 0x02, 0x40, 0x22, 0x00, 0x82, 0x03, 0x83, 0x24, 0x24, 0x2a, 168 | 0x64, 0x24, 0x10, 0xb3, 0x38, 0x90, 0x94, 0x8c, 0x90, 0xef, 0xd1, 0x90, 169 | 0xa0, 0x19, 0x8a, 0xa1, 0x90, 0x10, 0x00, 0x41, 0xdb, 0x9f, 0x01, 0x0b, 170 | 0x25, 0x09, 0x00, 0x00, 0x48, 0x42, 0x00, 0x00, 0xb0, 0x41, 0x01, 0x00, 171 | 0x00, 0x5c, 0x42, 0x00, 0x00, 0x96, 0x43, 0x01, 0x00, 0x00, 0x5c, 0x42, 172 | 0x00, 0x00, 0x16, 0x44, 0x01, 0x00, 0x00, 0x5c, 0x42, 0x00, 0x00, 0x61, 173 | 0x44, 0xff 174 | }; 175 | unsigned int dino_wasm_len = 2054; 176 | -------------------------------------------------------------------------------- /examples/Wasm_Dino_PyBadge/Wasm_Dino_PyBadge.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Wasm3 - high performance WebAssembly interpreter written in C. 3 | * Copyright © 2020 Volodymyr Shymanskyy, Steven Massey. 4 | * All rights reserved. 5 | */ 6 | 7 | #include "Adafruit_Arcada.h" 8 | 9 | #include 10 | 11 | #define DISPLAY_BRIGHTESS 128 // 0..255 12 | 13 | /* 14 | * Dino game by by Ben Smith (binji) 15 | * https://github.com/binji/raw-wasm/tree/master/dino 16 | * To build: 17 | * export PATH=/opt/wasp/build/src/tools:$PATH 18 | * wasp wat2wasm --enable-numeric-values -o dino.wasm dino.wat 19 | * xxd -iC dino.wasm > dino.wasm.h 20 | * 21 | * Note: In Arduino IDE, select Tools->Optimize->Faster (-O3) 22 | */ 23 | #include "dino.wasm.h" 24 | 25 | /* 26 | * Engine start, liftoff! 27 | */ 28 | 29 | #define FATAL(func, msg) { Serial.print("Fatal: " func " "); Serial.println(msg); while(1) { delay(100); } } 30 | #define TSTART() { tstart = micros(); } 31 | #define TFINISH(s) { tend = micros(); Serial.print(s " in "); Serial.print(tend-tstart); Serial.println(" us"); } 32 | 33 | // The Math.random() function returns a floating-point, 34 | // pseudo-random number in the range 0 to less than 1 35 | m3ApiRawFunction(Math_random) 36 | { 37 | m3ApiReturnType (float) 38 | 39 | float r = (float)random(INT_MAX)/INT_MAX; 40 | //Serial.print("Random: "); Serial.println(r); 41 | 42 | m3ApiReturn(r); 43 | } 44 | 45 | // Memcpy is generic, and much faster in native code 46 | m3ApiRawFunction(Dino_memcpy) 47 | { 48 | m3ApiGetArgMem (uint8_t *, dst) 49 | m3ApiGetArgMem (uint8_t *, src) 50 | m3ApiGetArgMem (uint8_t *, dstend) 51 | 52 | do { 53 | *dst++ = *src++; 54 | } while (dst < dstend); 55 | 56 | m3ApiSuccess(); 57 | } 58 | 59 | Adafruit_Arcada arcada; 60 | 61 | IM3Environment env; 62 | IM3Runtime runtime; 63 | IM3Module module; 64 | IM3Function func_run; 65 | uint8_t* mem; 66 | 67 | void load_wasm() 68 | { 69 | M3Result result = m3Err_none; 70 | 71 | if (!env) { 72 | env = m3_NewEnvironment (); 73 | if (!env) FATAL("NewEnvironment", "failed"); 74 | } 75 | 76 | m3_FreeRuntime(runtime); 77 | 78 | runtime = m3_NewRuntime (env, 1024, NULL); 79 | if (!runtime) FATAL("NewRuntime", "failed"); 80 | 81 | result = m3_ParseModule (env, &module, dino_wasm, sizeof(dino_wasm)); 82 | if (result) FATAL("ParseModule", result); 83 | 84 | result = m3_LoadModule (runtime, module); 85 | if (result) FATAL("LoadModule", result); 86 | 87 | m3_LinkRawFunction (module, "Math", "random", "f()", &Math_random); 88 | m3_LinkRawFunction (module, "Dino", "memcpy", "v(iii)", &Dino_memcpy); 89 | 90 | mem = m3_GetMemory (runtime, NULL, 0); 91 | if (!mem) FATAL("GetMemory", "failed"); 92 | 93 | result = m3_FindFunction (&func_run, runtime, "run"); 94 | if (result) FATAL("FindFunction", result); 95 | } 96 | 97 | void init_device() 98 | { 99 | // Try to randomize seed 100 | randomSeed((analogRead(A5) << 16) + analogRead(A4)); 101 | Serial.print("Random: 0x"); Serial.println(random(INT_MAX), HEX); 102 | 103 | if (!arcada.arcadaBegin()) { 104 | FATAL("arcadaBegin", "failed"); 105 | } 106 | arcada.displayBegin(); 107 | arcada.setBacklight(DISPLAY_BRIGHTESS); 108 | } 109 | 110 | void display_info() 111 | { 112 | arcada.display->fillScreen(ARCADA_WHITE); 113 | arcada.display->setTextColor(ARCADA_BLACK); 114 | arcada.display->setTextWrap(true); 115 | arcada.display->setCursor(0, 5); 116 | arcada.display->println(" Wasm3 v" M3_VERSION " (" M3_ARCH "@" + String(F_CPU/1000000) + "MHz)\n"); 117 | arcada.display->println(" Dino game"); 118 | arcada.display->println(" by Ben Smith (binji)"); 119 | } 120 | 121 | void setup() 122 | { 123 | Serial.begin(115200); 124 | 125 | // Wait for serial port to connect 126 | // Needed for native USB port only 127 | //while(!Serial) {} 128 | 129 | Serial.println("\nWasm3 v" M3_VERSION " (" M3_ARCH "), build " __DATE__ " " __TIME__); 130 | 131 | uint32_t tend, tstart; 132 | TSTART(); 133 | init_device(); 134 | display_info(); 135 | TFINISH("Device init"); 136 | 137 | TSTART(); 138 | load_wasm(); 139 | TFINISH("Wasm3 init"); 140 | 141 | Serial.println("Running WebAssembly..."); 142 | 143 | M3Result result; 144 | uint64_t last_fps_print = 0; 145 | 146 | while (true) { 147 | const uint64_t framestart = micros(); 148 | 149 | // Process inputs 150 | uint32_t pressed_buttons = arcada.readButtons(); 151 | if (arcada.justPressedButtons() & ARCADA_BUTTONMASK_START) { 152 | //NVIC_SystemReset(); 153 | 154 | // Restart Dino game 155 | display_info(); 156 | load_wasm(); 157 | } 158 | 159 | uint32_t* input = (uint32_t*)(mem + 0x0000); 160 | *input = 0; 161 | if (pressed_buttons & ARCADA_BUTTONMASK_A) { // Up 162 | *input |= 0x1; 163 | } 164 | if (pressed_buttons & ARCADA_BUTTONMASK_B) { // Down 165 | *input |= 0x2; 166 | } 167 | 168 | // Render frame 169 | result = m3_CallV (func_run); 170 | if (result) break; 171 | 172 | // Output to display 173 | arcada.display->drawRGBBitmap(0, 40, (uint16_t*)(mem+0x5000), 160, 75); 174 | 175 | const uint64_t frametime = micros() - framestart; 176 | 177 | // Limit to 50..70 fps, depending on CPU/overclock setting (120..200MHz) 178 | //const int target_frametime = 1000000/map(F_CPU/1000000, 120, 200, 50, 70); 179 | const uint32_t target_frametime = 1000000/50; 180 | if (target_frametime > frametime) { 181 | delay((target_frametime - frametime)/1000); 182 | } 183 | if (framestart - last_fps_print > 1000000) { 184 | Serial.print("FPS: "); Serial.println((uint32_t)(1000000/frametime)); 185 | last_fps_print = framestart; 186 | } 187 | } 188 | 189 | if (result != m3Err_none) { 190 | M3ErrorInfo info; 191 | m3_GetErrorInfo (runtime, &info); 192 | Serial.print("Error: "); 193 | Serial.print(result); 194 | Serial.print(" ("); 195 | Serial.print(info.message); 196 | Serial.println(")"); 197 | if (info.file && strlen(info.file) && info.line) { 198 | Serial.print("At "); 199 | Serial.print(info.file); 200 | Serial.print(":"); 201 | Serial.println(info.line); 202 | } 203 | } 204 | } 205 | 206 | void loop() 207 | { 208 | delay(100); 209 | } 210 | -------------------------------------------------------------------------------- /examples/Wasm_Dino_PyBadge/dino.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wasm3/wasm3-arduino/0dcff083f369f89d7bd5d434d60e63d789fab133/examples/Wasm_Dino_PyBadge/dino.wasm -------------------------------------------------------------------------------- /examples/Wasm_Dino_PyBadge/dino.wasm.h: -------------------------------------------------------------------------------- 1 | unsigned char dino_wasm[] = { 2 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1b, 0x05, 0x60, 3 | 0x00, 0x00, 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x00, 0x60, 0x01, 0x7f, 0x01, 4 | 0x7f, 0x60, 0x04, 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 5 | 0x7d, 0x02, 0x1d, 0x02, 0x04, 0x4d, 0x61, 0x74, 0x68, 0x06, 0x72, 0x61, 6 | 0x6e, 0x64, 0x6f, 0x6d, 0x00, 0x04, 0x04, 0x44, 0x69, 0x6e, 0x6f, 0x06, 7 | 0x6d, 0x65, 0x6d, 0x63, 0x70, 0x79, 0x00, 0x01, 0x03, 0x05, 0x04, 0x00, 8 | 0x02, 0x03, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x20, 0x05, 0x7f, 9 | 0x01, 0x41, 0x00, 0x0b, 0x7f, 0x01, 0x41, 0x00, 0x0b, 0x7f, 0x01, 0x41, 10 | 0x00, 0x0b, 0x7d, 0x01, 0x43, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x7d, 0x01, 11 | 0x43, 0x00, 0x00, 0x00, 0xbf, 0x0b, 0x07, 0x18, 0x03, 0x03, 0x6d, 0x65, 12 | 0x6d, 0x02, 0x00, 0x08, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x36, 0x35, 13 | 0x00, 0x03, 0x03, 0x72, 0x75, 0x6e, 0x00, 0x05, 0x08, 0x01, 0x02, 0x0a, 14 | 0xaa, 0x08, 0x04, 0xf5, 0x01, 0x01, 0x0a, 0x7f, 0x41, 0x07, 0x21, 0x03, 15 | 0x41, 0xbb, 0x06, 0x21, 0x00, 0x03, 0x40, 0x20, 0x04, 0x41, 0x10, 0x49, 16 | 0x04, 0x40, 0x20, 0x05, 0x20, 0x01, 0x2f, 0x01, 0xd0, 0x02, 0x20, 0x04, 17 | 0x74, 0x72, 0x21, 0x05, 0x20, 0x04, 0x41, 0x10, 0x6a, 0x21, 0x04, 0x20, 18 | 0x01, 0x41, 0x02, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x05, 0x41, 0x01, 0x20, 19 | 0x03, 0x74, 0x41, 0x01, 0x6b, 0x71, 0x21, 0x02, 0x20, 0x05, 0x20, 0x03, 20 | 0x76, 0x21, 0x05, 0x20, 0x04, 0x20, 0x03, 0x6b, 0x21, 0x04, 0x02, 0x40, 21 | 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x06, 0x0e, 0x03, 22 | 0x00, 0x01, 0x04, 0x03, 0x0b, 0x20, 0x02, 0x22, 0x07, 0x45, 0x0d, 0x01, 23 | 0x41, 0x01, 0x21, 0x06, 0x41, 0x04, 0x21, 0x03, 0x0c, 0x04, 0x0b, 0x20, 24 | 0x00, 0x20, 0x02, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 25 | 0x00, 0x20, 0x07, 0x41, 0x01, 0x6b, 0x22, 0x07, 0x0d, 0x03, 0x0b, 0x41, 26 | 0x02, 0x21, 0x06, 0x41, 0x07, 0x21, 0x03, 0x0c, 0x02, 0x0b, 0x20, 0x00, 27 | 0x20, 0x00, 0x20, 0x09, 0x6b, 0x20, 0x00, 0x20, 0x02, 0x6a, 0x22, 0x00, 28 | 0x10, 0x01, 0x41, 0x00, 0x21, 0x06, 0x0c, 0x01, 0x0b, 0x20, 0x02, 0x21, 29 | 0x09, 0x41, 0x03, 0x21, 0x06, 0x20, 0x01, 0x41, 0xee, 0x03, 0x49, 0x0d, 30 | 0x00, 0x0b, 0x03, 0x40, 0x20, 0x01, 0x2d, 0x00, 0xcd, 0x02, 0x22, 0x02, 31 | 0x04, 0x40, 0x20, 0x00, 0x20, 0x08, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x41, 32 | 0x01, 0x6a, 0x20, 0x00, 0x20, 0x00, 0x20, 0x02, 0x6a, 0x22, 0x00, 0x10, 33 | 0x01, 0x0b, 0x20, 0x08, 0x45, 0x21, 0x08, 0x20, 0x01, 0x41, 0x01, 0x6a, 34 | 0x22, 0x01, 0x41, 0xc0, 0x0f, 0x49, 0x0d, 0x00, 0x0b, 0x0b, 0x2b, 0x00, 35 | 0x41, 0xff, 0x01, 0x20, 0x00, 0x6b, 0x22, 0x00, 0x41, 0x1f, 0x6c, 0x41, 36 | 0xff, 0x01, 0x6e, 0x20, 0x00, 0x41, 0x3f, 0x6c, 0x41, 0xff, 0x01, 0x6e, 37 | 0x41, 0x05, 0x74, 0x20, 0x00, 0x41, 0x1f, 0x6c, 0x41, 0xff, 0x01, 0x6e, 38 | 0x41, 0x0b, 0x74, 0x72, 0x72, 0x0b, 0xc0, 0x01, 0x01, 0x05, 0x7f, 0x20, 39 | 0x02, 0x2d, 0x00, 0xa9, 0x02, 0x22, 0x04, 0x21, 0x07, 0x20, 0x02, 0x2d, 40 | 0x00, 0xaa, 0x02, 0x21, 0x05, 0x20, 0x02, 0x2d, 0x00, 0xab, 0x02, 0x10, 41 | 0x03, 0x21, 0x02, 0x20, 0x00, 0x41, 0x00, 0x48, 0x04, 0x40, 0x20, 0x00, 42 | 0x20, 0x04, 0x6a, 0x21, 0x04, 0x20, 0x03, 0x20, 0x00, 0x6b, 0x21, 0x03, 43 | 0x41, 0x00, 0x21, 0x00, 0x05, 0x41, 0xa0, 0x01, 0x20, 0x00, 0x6b, 0x20, 44 | 0x04, 0x20, 0x00, 0x20, 0x04, 0x6a, 0x41, 0xa0, 0x01, 0x4a, 0x1b, 0x21, 45 | 0x04, 0x0b, 0x20, 0x04, 0x41, 0x00, 0x4a, 0x04, 0x40, 0x20, 0x01, 0x41, 46 | 0xa0, 0x01, 0x6c, 0x20, 0x00, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x41, 0x00, 47 | 0x21, 0x00, 0x03, 0x40, 0x20, 0x00, 0x20, 0x03, 0x6a, 0x2d, 0x00, 0x8d, 48 | 0x12, 0x04, 0x40, 0x20, 0x06, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x41, 0x01, 49 | 0x74, 0x22, 0x08, 0x2f, 0x01, 0x80, 0xa0, 0x01, 0x41, 0x8a, 0xa5, 0x01, 50 | 0x46, 0x72, 0x21, 0x06, 0x20, 0x08, 0x20, 0x02, 0x3b, 0x01, 0x80, 0xa0, 51 | 0x01, 0x0b, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x22, 0x00, 0x20, 0x04, 0x48, 52 | 0x0d, 0x00, 0x0b, 0x20, 0x01, 0x41, 0xa0, 0x01, 0x6a, 0x21, 0x01, 0x20, 53 | 0x03, 0x20, 0x07, 0x6a, 0x21, 0x03, 0x20, 0x05, 0x41, 0x01, 0x6b, 0x22, 54 | 0x05, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x06, 0x0b, 0xc2, 0x04, 0x02, 0x03, 55 | 0x7f, 0x01, 0x7d, 0x41, 0x80, 0xa0, 0x01, 0x41, 0xff, 0x9f, 0x01, 0x41, 56 | 0xc0, 0xdb, 0x02, 0x10, 0x01, 0x23, 0x00, 0x41, 0x01, 0x6a, 0x24, 0x00, 57 | 0x23, 0x04, 0x43, 0x00, 0x00, 0x00, 0x3b, 0x93, 0x43, 0x00, 0x00, 0x80, 58 | 0xbf, 0x97, 0x24, 0x04, 0x41, 0x00, 0x2d, 0x00, 0x00, 0x21, 0x00, 0x41, 59 | 0x05, 0x2a, 0x02, 0x00, 0x21, 0x03, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 60 | 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x23, 0x02, 0x0e, 0x04, 61 | 0x01, 0x02, 0x03, 0x04, 0x00, 0x0b, 0x41, 0x0b, 0x21, 0x01, 0x43, 0x00, 62 | 0x00, 0x00, 0x00, 0x24, 0x04, 0x20, 0x00, 0x45, 0x23, 0x00, 0x23, 0x01, 63 | 0x6b, 0x41, 0x14, 0x4d, 0x72, 0x0d, 0x05, 0x41, 0x00, 0x24, 0x01, 0x41, 64 | 0x00, 0x24, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x24, 0x03, 0x43, 0x00, 65 | 0x00, 0x00, 0xbf, 0x24, 0x04, 0x0b, 0x43, 0x00, 0x00, 0x48, 0x42, 0x21, 66 | 0x03, 0x41, 0x04, 0x41, 0xdb, 0x9f, 0x01, 0x41, 0x28, 0x10, 0x01, 0x41, 67 | 0x01, 0x24, 0x02, 0x0b, 0x20, 0x00, 0x41, 0x02, 0x46, 0x41, 0x09, 0x6a, 68 | 0x21, 0x01, 0x20, 0x00, 0x41, 0x01, 0x47, 0x0d, 0x02, 0x41, 0x02, 0x24, 69 | 0x02, 0x43, 0x00, 0x00, 0xc0, 0xc0, 0x24, 0x03, 0x0b, 0x20, 0x00, 0x41, 70 | 0x01, 0x46, 0x20, 0x03, 0x43, 0x00, 0x00, 0xf0, 0x41, 0x60, 0x72, 0x20, 71 | 0x03, 0x43, 0x00, 0x00, 0x20, 0x41, 0x60, 0x71, 0x0d, 0x00, 0x41, 0x03, 72 | 0x24, 0x02, 0x43, 0x00, 0x00, 0x80, 0xbf, 0x24, 0x03, 0x0b, 0x41, 0x08, 73 | 0x21, 0x01, 0x20, 0x03, 0x23, 0x03, 0x92, 0x21, 0x03, 0x23, 0x03, 0x43, 74 | 0xcd, 0xcc, 0xcc, 0x3e, 0x92, 0x24, 0x03, 0x20, 0x03, 0x43, 0x00, 0x00, 75 | 0x48, 0x42, 0x5f, 0x0d, 0x00, 0x41, 0x01, 0x24, 0x02, 0x43, 0x00, 0x00, 76 | 0x48, 0x42, 0x21, 0x03, 0x43, 0x00, 0x00, 0x00, 0x00, 0x24, 0x03, 0x0b, 77 | 0x23, 0x01, 0x41, 0x01, 0x6a, 0x24, 0x01, 0x0b, 0x41, 0x04, 0x20, 0x01, 78 | 0x3a, 0x00, 0x00, 0x41, 0x05, 0x20, 0x03, 0x38, 0x02, 0x00, 0x41, 0xf9, 79 | 0x00, 0x21, 0x00, 0x03, 0x40, 0x20, 0x00, 0x2a, 0x02, 0x05, 0xa8, 0x20, 80 | 0x00, 0x2d, 0x00, 0x00, 0x41, 0x07, 0x6c, 0x22, 0x01, 0x2d, 0x00, 0x83, 81 | 0x01, 0x41, 0x02, 0x74, 0x23, 0x00, 0x41, 0x0f, 0x71, 0x41, 0x02, 0x76, 82 | 0x6a, 0x22, 0x02, 0x2d, 0x00, 0xdc, 0x01, 0x20, 0x00, 0x2a, 0x02, 0x01, 83 | 0xa8, 0x6a, 0x20, 0x01, 0x2d, 0x00, 0x84, 0x01, 0x20, 0x02, 0x2d, 0x00, 84 | 0xec, 0x01, 0x6a, 0x22, 0x02, 0x2d, 0x00, 0xfc, 0x01, 0x20, 0x02, 0x2f, 85 | 0x01, 0xfd, 0x01, 0x10, 0x04, 0x20, 0x00, 0x41, 0x04, 0x46, 0x71, 0x04, 86 | 0x40, 0x41, 0x04, 0x24, 0x02, 0x0b, 0x20, 0x00, 0x2a, 0x02, 0x05, 0x20, 87 | 0x01, 0x2d, 0x00, 0x88, 0x01, 0xb3, 0x23, 0x04, 0x94, 0x92, 0x22, 0x03, 88 | 0x43, 0x00, 0x00, 0x80, 0xc2, 0x5d, 0x04, 0x40, 0x20, 0x00, 0x10, 0x00, 89 | 0x20, 0x01, 0x2d, 0x00, 0x82, 0x01, 0x41, 0x01, 0x74, 0x22, 0x01, 0x2d, 90 | 0x00, 0xd7, 0x01, 0xb3, 0x94, 0xa8, 0x20, 0x01, 0x2d, 0x00, 0xd6, 0x01, 91 | 0x6a, 0x22, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x43, 0x00, 0x00, 0x60, 92 | 0x43, 0x92, 0x20, 0x01, 0x41, 0x07, 0x6c, 0x22, 0x01, 0x2d, 0x00, 0x85, 93 | 0x01, 0x41, 0x03, 0x74, 0xb3, 0x92, 0x21, 0x03, 0x20, 0x00, 0x20, 0x01, 94 | 0x2d, 0x00, 0x86, 0x01, 0xb3, 0x10, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x87, 95 | 0x01, 0xb3, 0x94, 0x92, 0x38, 0x02, 0x01, 0x0b, 0x20, 0x00, 0x20, 0x03, 96 | 0x38, 0x02, 0x05, 0x20, 0x00, 0x41, 0x09, 0x6b, 0x22, 0x00, 0x41, 0x00, 97 | 0x4a, 0x0d, 0x00, 0x0b, 0x23, 0x01, 0x21, 0x00, 0x41, 0x9b, 0x01, 0x21, 98 | 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, 0x04, 0x6b, 0x22, 0x01, 0x41, 0x04, 99 | 0x41, 0x21, 0x20, 0x00, 0x41, 0x0a, 0x70, 0x41, 0x0f, 0x6c, 0x41, 0xcc, 100 | 0x2f, 0x6a, 0x10, 0x04, 0x1a, 0x20, 0x00, 0x41, 0x0a, 0x6e, 0x22, 0x00, 101 | 0x0d, 0x00, 0x0b, 0x23, 0x02, 0x41, 0x04, 0x46, 0x04, 0x40, 0x41, 0x34, 102 | 0x41, 0x21, 0x41, 0x24, 0x41, 0xe2, 0x30, 0x10, 0x04, 0x1a, 0x0b, 0x0b, 103 | 0x0b, 0xc6, 0x06, 0x02, 0x00, 0x41, 0x28, 0x0b, 0x93, 0x06, 0x07, 0x00, 104 | 0x00, 0x86, 0x42, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x86, 0x42, 105 | 0x00, 0x00, 0x80, 0x42, 0x07, 0x00, 0x00, 0x86, 0x42, 0x00, 0x00, 0x00, 106 | 0x43, 0x07, 0x00, 0x00, 0x86, 0x42, 0x00, 0x00, 0x40, 0x43, 0x07, 0x00, 107 | 0x00, 0x86, 0x42, 0x00, 0x00, 0x80, 0x43, 0x07, 0x00, 0x00, 0x86, 0x42, 108 | 0x00, 0x00, 0xa0, 0x43, 0x06, 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0x00, 109 | 0x00, 0x06, 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0x00, 0x43, 0x06, 0x00, 110 | 0x00, 0x20, 0x42, 0x00, 0x00, 0x80, 0x43, 0x06, 0x00, 0x00, 0x20, 0x42, 111 | 0x00, 0x00, 0xc0, 0x43, 0x00, 0x00, 0x12, 0x4b, 0x2e, 0x00, 0x04, 0x00, 112 | 0x00, 0x15, 0x4b, 0x36, 0x00, 0x04, 0x00, 0x00, 0x18, 0x4b, 0x36, 0x00, 113 | 0x04, 0x00, 0x00, 0x1b, 0x4b, 0x36, 0x00, 0x04, 0x00, 0x00, 0x1e, 0x4b, 114 | 0x2e, 0x00, 0x04, 0x00, 0x03, 0x27, 0x4b, 0x19, 0x19, 0x05, 0x01, 0x00, 115 | 0x21, 0x1e, 0x0f, 0x19, 0x01, 0x02, 0x00, 0x24, 0x00, 0x43, 0x00, 0x04, 116 | 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x06, 0x00, 0x00, 117 | 0x00, 0x00, 0x03, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 118 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x01, 0x07, 0x01, 0x00, 0x00, 119 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 120 | 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 121 | 0x00, 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x01, 122 | 0x00, 0x70, 0x03, 0x00, 0x28, 0x05, 0x03, 0xe0, 0x06, 0x03, 0x4c, 0x08, 123 | 0x06, 0xb8, 0x09, 0x09, 0x0a, 0x0b, 0x0c, 0x60, 0x0c, 0x0f, 0x58, 0x0e, 124 | 0x12, 0xfa, 0x0e, 0x15, 0x0a, 0x13, 0x18, 0xda, 0x13, 0x1b, 0x1a, 0x15, 125 | 0x1e, 0x5c, 0x16, 0x14, 0x16, 0xaa, 0x1c, 0x0d, 0xaa, 0x0d, 0x1a, 0xac, 126 | 0x13, 0x12, 0xac, 0x1c, 0x12, 0xac, 0x09, 0x12, 0xac, 0x28, 0x1a, 0xac, 127 | 0x1a, 0x08, 0x25, 0x40, 0x05, 0xaa, 0x17, 0x0e, 0xac, 0x17, 0x10, 0xac, 128 | 0x03, 0x05, 0xac, 0x32, 0x08, 0xac, 0x91, 0xc5, 0x95, 0x29, 0x95, 0x88, 129 | 0x28, 0x95, 0x29, 0x0d, 0x18, 0x72, 0x28, 0x81, 0x65, 0x71, 0x66, 0x42, 130 | 0x4a, 0x23, 0x19, 0x41, 0x6e, 0x7e, 0x9c, 0xab, 0xc9, 0xe7, 0x13, 0xe2, 131 | 0x32, 0xe1, 0x41, 0xe1, 0x32, 0xf2, 0x40, 0xb8, 0xaa, 0x12, 0x07, 0x3c, 132 | 0x08, 0xea, 0x85, 0xe3, 0x87, 0x0c, 0xcb, 0xc3, 0xc4, 0x03, 0xc9, 0x43, 133 | 0x02, 0x61, 0x48, 0x11, 0x79, 0x91, 0x78, 0xa0, 0x78, 0x20, 0xc1, 0x78, 134 | 0x18, 0x8c, 0xa1, 0x94, 0x87, 0x8f, 0x8b, 0x07, 0x96, 0x87, 0x9d, 0x07, 135 | 0xa5, 0x07, 0x52, 0x96, 0x43, 0x9b, 0x78, 0x98, 0x90, 0x19, 0x79, 0x10, 136 | 0x09, 0x79, 0xd8, 0xd4, 0x21, 0x20, 0x40, 0x15, 0x62, 0x64, 0x42, 0x1e, 137 | 0xc4, 0xb7, 0x28, 0xe8, 0x64, 0xa1, 0x20, 0x91, 0x90, 0x90, 0x90, 0x0a, 138 | 0x0b, 0x82, 0xa6, 0xf0, 0xb1, 0x83, 0x32, 0x05, 0x40, 0x60, 0xe8, 0x9c, 139 | 0xa0, 0xdc, 0xdc, 0xd8, 0x48, 0x84, 0xc4, 0x44, 0xd0, 0x84, 0x84, 0xc4, 140 | 0xc4, 0x88, 0x02, 0x21, 0xa0, 0x50, 0x60, 0x2a, 0x16, 0x14, 0x26, 0x15, 141 | 0x14, 0x55, 0x7c, 0x25, 0x75, 0x63, 0x43, 0xd0, 0x08, 0x4e, 0x0c, 0x08, 142 | 0x80, 0xd1, 0x30, 0x20, 0x09, 0x46, 0x63, 0x10, 0x32, 0x60, 0x44, 0x41, 143 | 0x42, 0x42, 0xe0, 0x0b, 0x00, 0x04, 0x15, 0x30, 0xc7, 0xc1, 0x55, 0x41, 144 | 0x51, 0x22, 0x31, 0x21, 0xd2, 0x24, 0x31, 0x21, 0x44, 0x52, 0x64, 0x21, 145 | 0x24, 0x36, 0x85, 0x24, 0x36, 0x57, 0x25, 0x36, 0x37, 0x67, 0xa8, 0x00, 146 | 0x04, 0x86, 0x41, 0x50, 0x10, 0x20, 0x07, 0x8c, 0x0a, 0xa3, 0x12, 0x21, 147 | 0x2a, 0x36, 0x36, 0x29, 0x0f, 0x2a, 0x4a, 0x19, 0x4d, 0x49, 0x38, 0x6c, 148 | 0x58, 0x2c, 0x70, 0x82, 0x92, 0x70, 0x42, 0x4a, 0xd1, 0x38, 0x54, 0x0c, 149 | 0x89, 0x90, 0xe3, 0x30, 0x90, 0x12, 0xc7, 0x87, 0x10, 0x12, 0xe6, 0x68, 150 | 0x14, 0x6a, 0x42, 0xd0, 0x91, 0x28, 0x0c, 0xc9, 0x9c, 0x83, 0x21, 0x20, 151 | 0x73, 0x28, 0x18, 0x21, 0x21, 0x21, 0x43, 0x22, 0xc1, 0x90, 0x05, 0x01, 152 | 0x63, 0xc5, 0xa1, 0x28, 0x1c, 0x59, 0x99, 0x0a, 0x41, 0x48, 0xb2, 0x62, 153 | 0x28, 0x08, 0x38, 0x81, 0x08, 0xc3, 0x42, 0x8c, 0x28, 0x09, 0x87, 0xc4, 154 | 0x10, 0xa1, 0xd4, 0xdb, 0x03, 0x49, 0xc5, 0x83, 0xc4, 0xc9, 0x8b, 0x85, 155 | 0x0c, 0x92, 0x4b, 0xc5, 0x43, 0x05, 0xc5, 0x83, 0x49, 0xc4, 0x3c, 0x08, 156 | 0x10, 0x81, 0x4c, 0x20, 0x18, 0x15, 0x0f, 0x1b, 0x0f, 0x1f, 0x2a, 0x1f, 157 | 0x45, 0x71, 0x84, 0x23, 0xe3, 0x21, 0xe5, 0xc1, 0xe6, 0xa1, 0xe8, 0x21, 158 | 0x44, 0xc8, 0x47, 0x8a, 0x2b, 0x4c, 0x2d, 0x0e, 0xdf, 0xd5, 0x1f, 0x02, 159 | 0x99, 0x7b, 0xf3, 0x2f, 0xe5, 0xa1, 0xe6, 0x81, 0xea, 0x41, 0xec, 0x21, 160 | 0x40, 0x09, 0xe0, 0x7a, 0x2e, 0x6b, 0xd3, 0x03, 0xcd, 0x43, 0xc9, 0x83, 161 | 0xc9, 0x83, 0x85, 0x53, 0x48, 0x48, 0x98, 0x84, 0x84, 0x44, 0x98, 0x94, 162 | 0x98, 0x90, 0x54, 0x48, 0x90, 0x84, 0x94, 0x8c, 0xa0, 0x50, 0x1c, 0xc8, 163 | 0x20, 0x92, 0x8a, 0x0a, 0x0c, 0x92, 0x90, 0x08, 0x9a, 0x19, 0x11, 0x11, 164 | 0x9a, 0x11, 0x09, 0x09, 0x0a, 0x0a, 0x03, 0x1d, 0x04, 0x15, 0x12, 0x83, 165 | 0xe0, 0x24, 0x67, 0x20, 0x60, 0x08, 0x0d, 0x0f, 0x87, 0x90, 0x91, 0xa0, 166 | 0x12, 0x19, 0x06, 0x12, 0x24, 0x3a, 0x00, 0x80, 0x06, 0x82, 0xc4, 0x84, 167 | 0x86, 0x02, 0x40, 0x22, 0x00, 0x82, 0x03, 0x83, 0x24, 0x24, 0x2a, 0x64, 168 | 0x24, 0x10, 0xb3, 0x38, 0x90, 0x94, 0x8c, 0x90, 0xef, 0xd1, 0x90, 0xa0, 169 | 0x19, 0x8a, 0xa1, 0x90, 0x10, 0x00, 0x41, 0xdb, 0x9f, 0x01, 0x0b, 0x25, 170 | 0x09, 0x00, 0x00, 0x48, 0x42, 0x00, 0x00, 0xb0, 0x41, 0x01, 0x00, 0x00, 171 | 0x5c, 0x42, 0x00, 0x00, 0x96, 0x43, 0x01, 0x00, 0x00, 0x5c, 0x42, 0x00, 172 | 0x00, 0x16, 0x44, 0x01, 0x00, 0x00, 0x5c, 0x42, 0x00, 0x00, 0x61, 0x44, 173 | 0xff 174 | }; 175 | unsigned int dino_wasm_len = 2053; 176 | -------------------------------------------------------------------------------- /examples/Wasm_Fibonacci/Wasm_Fibonacci.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Wasm3 - high performance WebAssembly interpreter written in C. 3 | * Copyright © 2020 Volodymyr Shymanskyy, Steven Massey. 4 | * All rights reserved. 5 | */ 6 | 7 | #include 8 | 9 | /* 10 | * WebAssembly app (recursive Fibonacci) 11 | */ 12 | 13 | unsigned char fib_wasm[] = { 14 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 15 | 0x01, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, 16 | 0x66, 0x69, 0x62, 0x00, 0x00, 0x0a, 0x1f, 0x01, 0x1d, 0x00, 0x20, 0x00, 17 | 0x41, 0x02, 0x49, 0x04, 0x40, 0x20, 0x00, 0x0f, 0x0b, 0x20, 0x00, 0x41, 18 | 0x02, 0x6b, 0x10, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6b, 0x10, 0x00, 0x6a, 19 | 0x0f, 0x0b 20 | }; 21 | 22 | /* 23 | * Engine start, liftoff! 24 | */ 25 | 26 | #define FATAL(func, msg) { Serial.print("Fatal: " func " "); Serial.println(msg); return; } 27 | #define TSTART() { tstart = micros(); } 28 | #define TFINISH(s) { tend = micros(); Serial.print(s " in "); Serial.print(tend-tstart); Serial.println(" us"); } 29 | 30 | void wasm_task(void*) 31 | { 32 | uint32_t tend, tstart; 33 | TSTART(); 34 | 35 | M3Result result = m3Err_none; 36 | 37 | IM3Environment env = m3_NewEnvironment (); 38 | if (!env) FATAL("NewEnvironment", "failed"); 39 | 40 | IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); 41 | if (!runtime) FATAL("NewRuntime", "failed"); 42 | 43 | IM3Module module; 44 | result = m3_ParseModule (env, &module, fib_wasm, sizeof(fib_wasm)); 45 | if (result) FATAL("ParseModule", result); 46 | 47 | result = m3_LoadModule (runtime, module); 48 | if (result) FATAL("LoadModule", result); 49 | 50 | IM3Function f; 51 | result = m3_FindFunction (&f, runtime, "fib"); 52 | if (result) FATAL("FindFunction", result); 53 | 54 | TFINISH("Init"); 55 | 56 | Serial.println("Running fib(24)..."); 57 | 58 | TSTART(); 59 | 60 | result = m3_CallV (f, 24); 61 | 62 | TFINISH("Done"); 63 | 64 | if (result == m3Err_none) { 65 | uint32_t value = 0; 66 | result = m3_GetResultsV (f, &value); 67 | if (result) FATAL("GetResults: %s", result); 68 | 69 | Serial.print("Result: "); 70 | Serial.println(value); 71 | } else { 72 | M3ErrorInfo info; 73 | m3_GetErrorInfo (runtime, &info); 74 | Serial.print("Error: "); 75 | Serial.print(result); 76 | Serial.print(" ("); 77 | Serial.print(info.message); 78 | Serial.println(")"); 79 | if (info.file && strlen(info.file) && info.line) { 80 | Serial.print("At "); 81 | Serial.print(info.file); 82 | Serial.print(":"); 83 | Serial.println(info.line); 84 | } 85 | } 86 | #ifdef ESP32 87 | vTaskDelete(NULL); 88 | #endif 89 | } 90 | 91 | void setup() 92 | { 93 | Serial.begin(115200); 94 | delay(100); 95 | 96 | // Wait for serial port to connect 97 | // Needed for native USB port only 98 | while(!Serial) {} 99 | 100 | Serial.println("\nWasm3 v" M3_VERSION " (" M3_ARCH "), build " __DATE__ " " __TIME__); 101 | 102 | #ifdef ESP32 103 | // On ESP32, we can launch in a separate thread (with 16Kb stack) 104 | Serial.println("Running a separate task"); 105 | xTaskCreate(&wasm_task, "wasm3", 16*1024, NULL, 5, NULL); 106 | #else 107 | wasm_task(NULL); 108 | #endif 109 | } 110 | 111 | void loop() 112 | { 113 | delay(100); 114 | } 115 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/README.md: -------------------------------------------------------------------------------- 1 | ## PlatformIO example (advanced) 2 | 3 | `./wasm_apps` contains sample apps in `C/C++`, `Rust`, `AssemblyScript`, `TinyGo` 4 | 5 | `./wasm_vm` contains the host interpreter/VM. 6 | You can add your device type in `platformio.ini`. 7 | Adjust the LED pin number with `-DLED_PIN` option. 8 | 9 | To run the example: 10 | ```sh 11 | pio run -e -t upload && pio device monitor 12 | ``` 13 | Where `` is one of: 14 | `ESP32`, `ESP8266`, `Arduino101`, `MKR1000`, `NucleoWB55RG`, `BluePill`, `TinyBLE`, `Teensy31`, `Teensy40`, `WildFireV3` 15 | 16 | **Note:** This example uses Wasm Linear Memory. You should be able to run it on any device that can afford to allocate 1-2 pages of Wasm Linear Memory (i.e. have >= 128KiB RAM). 17 | 18 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | ; Common configuration 12 | 13 | [platformio] 14 | src_dir = wasm_vm 15 | 16 | [env] 17 | framework = arduino 18 | monitor_speed = 115200 19 | 20 | lib_deps = Wasm3 21 | 22 | src_build_flags = 23 | -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter 24 | -Wno-missing-field-initializers 25 | 26 | ; Device-specific configuration 27 | 28 | [env:ESP32] 29 | platform = espressif32 30 | board = esp32dev 31 | board_build.f_cpu = 240000000L 32 | 33 | src_build_flags = 34 | ${env.src_build_flags} 35 | -DLED_PIN=19 36 | -DESP32 37 | -O3 -flto 38 | 39 | [env:ESP8266] 40 | platform = espressif8266 41 | board = nodemcuv2 42 | board_build.f_cpu = 160000000L 43 | 44 | upload_speed = 460800 45 | 46 | src_build_flags = 47 | ${env.src_build_flags} 48 | -DLED_PIN=13 49 | -DESP8266 -Dd_m3FixedHeap=0x6000 50 | -O3 -flto 51 | 52 | [env:AdafruitPyBadge] 53 | platform = atmelsam 54 | board = adafruit_pybadge_m4 55 | 56 | src_build_flags = 57 | ${env.src_build_flags} 58 | -DLED_PIN=13 59 | -O3 -flto 60 | 61 | #build_flags = 62 | # -Dd_m3LogNativeStack=1 63 | # -Dd_m3LogOutput=1 64 | # -Dd_m3VerboseLogs=1 65 | 66 | [env:MAIX] 67 | platform = kendryte210 68 | board = sipeed-maix-one-dock 69 | 70 | src_build_flags = 71 | ${env.src_build_flags} 72 | -DLED_PIN=13 73 | -O3 -flto 74 | 75 | build_flags = 76 | -DOVERRIDE_PRINTF 77 | -Dd_m3Use32BitSlots=0 78 | -Dd_m3VerboseLogs=1 79 | -Dd_m3LogNativeStack=1 80 | -Dd_m3LogOutput=1 81 | -Dd_m3LogParse=1 82 | -Dd_m3LogModule=1 83 | -Dd_m3LogCompile=1 84 | -Dd_m3LogEmit=1 85 | -Dd_m3LogExec=1 86 | 87 | [env:Arduino101] 88 | platform = intel_arc32 89 | board = genuino101 90 | 91 | src_build_flags = 92 | ${env.src_build_flags} 93 | -DLED_PIN=13 94 | -Os -flto 95 | 96 | [env:MKR1000] 97 | platform = atmelsam 98 | board = mkr1000USB 99 | 100 | src_build_flags = 101 | ${env.src_build_flags} 102 | -DLED_PIN=6 103 | -O3 -flto 104 | 105 | [env:NucleoWB55RG] 106 | platform = ststm32 107 | board = nucleo_wb55rg_p 108 | upload_protocol = mbed 109 | 110 | src_build_flags = 111 | ${env.src_build_flags} 112 | -DLED_PIN=PB5 113 | -O3 -flto 114 | 115 | [env:BluePill] 116 | platform = ststm32 117 | board = bluepill_f103c8 118 | upload_protocol = stlink 119 | 120 | src_build_flags = 121 | ${env.src_build_flags} 122 | -DLED_PIN=PC13 123 | -Os -flto 124 | 125 | [env:TinyBLE] 126 | platform = nordicnrf51 127 | board = seeedTinyBLE 128 | 129 | src_build_flags = 130 | ${env.src_build_flags} 131 | -DLED_PIN=23 132 | -Os -flto 133 | 134 | [env:Teensy31] 135 | platform = teensy 136 | board = teensy31 137 | upload_protocol = teensy-cli 138 | 139 | src_build_flags = 140 | ${env.src_build_flags} 141 | -DLED_PIN=13 142 | -O3 -flto 143 | 144 | [env:Teensy40] 145 | platform = teensy 146 | board = teensy40 147 | upload_protocol = teensy-cli 148 | 149 | src_build_flags = 150 | ${env.src_build_flags} 151 | -DLED_PIN=13 152 | -O3 -flto 153 | 154 | # d_m3SkipMemoryBoundsCheck was needed here, 155 | # as 64-bit operations seem to be broken on AVR 156 | [env:WildFireV3] 157 | platform = atmelavr 158 | board = wildfirev3 159 | 160 | src_build_flags = 161 | ${env.src_build_flags} 162 | -DLED_PIN=6 163 | -Dd_m3SkipMemoryBoundsCheck=1 164 | -Dd_m3CodePageAlignSize=512 165 | -Os -flto 166 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/assemblyscript/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | *.wat 3 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/assemblyscript/app.ts: -------------------------------------------------------------------------------- 1 | import * as dev from "./arduino"; 2 | 3 | let LED = dev.getPinLED(); 4 | 5 | function setup(): void { 6 | dev.pinMode(LED, dev.OUTPUT); 7 | 8 | dev.println('AssemblyScript is running 😎') 9 | dev.print('Greeting: ' + dev.getGreeting() + '\n'); 10 | } 11 | 12 | function run(): void { 13 | const time = dev.millis(); 14 | dev.println(time.toString()); 15 | 16 | dev.digitalWrite(LED, dev.HIGH); 17 | dev.delay(100); 18 | dev.digitalWrite(LED, dev.LOW); 19 | dev.delay(900); 20 | } 21 | 22 | /* 23 | * Entry point 24 | */ 25 | export function _start(): void { 26 | setup(); 27 | while (1) { 28 | run(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/assemblyscript/app.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wasm3/wasm3-arduino/0dcff083f369f89d7bd5d434d60e63d789fab133/examples_pio/Wasm_Advanced/wasm_apps/assemblyscript/app.wasm -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/assemblyscript/arduino.ts: -------------------------------------------------------------------------------- 1 | export const LOW = 0; 2 | export const HIGH = 1; 3 | 4 | export const INPUT = 0x0; 5 | export const OUTPUT = 0x1; 6 | export const INPUT_PULLUP = 0x2; 7 | 8 | export declare function millis(): u32; 9 | export declare function delay(ms: u32): void; 10 | export declare function pinMode(pin: u32, mode: u32): void; 11 | export declare function digitalWrite(pin: u32, value: u32): void; 12 | export declare function getPinLED(): u32; 13 | 14 | @external("getGreeting") 15 | declare function _getGreeting(ptr: usize, maxlen: usize): void; 16 | 17 | @external("print") 18 | declare function _print(ptr: usize, len: usize): void; 19 | 20 | export function print(str: string): void { 21 | const buffer = String.UTF8.encode(str); 22 | _print(changetype(buffer), buffer.byteLength); 23 | } 24 | 25 | export function println(str: string): void { 26 | print(str); 27 | print('\n'); 28 | } 29 | 30 | export function getGreeting(): string { 31 | const arr = new ArrayBuffer(64); 32 | _getGreeting(changetype(arr), 64); 33 | return String.UTF8.decode(arr, true); 34 | } 35 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/assemblyscript/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "assemblyscript": { 6 | "version": "0.18.12", 7 | "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.18.12.tgz", 8 | "integrity": "sha512-a0zJlb4xgEtxdadrrIP9MuLmQuRE6ZVzXPi2RZoVG6zgz+nLYLt1mkiP/TbJRY+4wvf1peTCZok+vyRAxFjppQ==", 9 | "dev": true, 10 | "requires": { 11 | "binaryen": "98.0.0-nightly.20210106", 12 | "long": "^4.0.0" 13 | } 14 | }, 15 | "binaryen": { 16 | "version": "98.0.0-nightly.20210106", 17 | "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-98.0.0-nightly.20210106.tgz", 18 | "integrity": "sha512-iunAgesqT9PXVYCc72FA4h0sCCKLifruT6NuUH63xqlFJGpChhZLgOtyIb/fIgTibN5Pd692cxfBViyCWFsJ9Q==", 19 | "dev": true 20 | }, 21 | "long": { 22 | "version": "4.0.0", 23 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 24 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", 25 | "dev": true 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/assemblyscript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": "MIT", 3 | "scripts": { 4 | "build": "npm run asbuild:optimized && xxd -i app.wasm > app.wasm.h", 5 | "asbuild:optimized": "npx asc app.ts -b app.wasm -t app.wat -O3z --runtime stub --noAssert --use abort=" 6 | }, 7 | "devDependencies": { 8 | "assemblyscript": "^0.18.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/assemblyscript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/assemblyscript/std/assembly.json", 3 | "include": [ 4 | "./**/*.ts" 5 | ] 6 | } -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/assemblyscript/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | assemblyscript@^0.9.0: 6 | version "0.9.0" 7 | resolved "https://registry.yarnpkg.com/assemblyscript/-/assemblyscript-0.9.0.tgz#2c85f0ff3bad7385484007d10ac65d29416f46c2" 8 | integrity sha512-HDDoaDfdnp0Ki/k272ib12sKz3ytVlXsIDise5meamInLC1qZAcmwwO+aqNyiVksmPYyLhQlaVZRPKWibHqo3g== 9 | dependencies: 10 | binaryen "90.0.0-nightly.20200111" 11 | long "^4.0.0" 12 | 13 | binaryen@90.0.0-nightly.20200111: 14 | version "90.0.0-nightly.20200111" 15 | resolved "https://registry.yarnpkg.com/binaryen/-/binaryen-90.0.0-nightly.20200111.tgz#dc5cfa53a7c2cb97a785a64ca041effd6ae66c4a" 16 | integrity sha512-2uihf1tqfkG2OJB54LjIDu5/fqbGgbj9VSwnj8hYtsRfML61y0uHeMkPfWctyl99m7hsgyDu7xUbJ7iyqBz6BA== 17 | 18 | long@^4.0.0: 19 | version "4.0.0" 20 | resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" 21 | integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== 22 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/cpp/app.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "arduino_api.h" 3 | 4 | int LED_BUILTIN; 5 | 6 | void setup() { 7 | println("C++ is running 😎"); 8 | 9 | LED_BUILTIN = getPinLED(); 10 | 11 | // initialize digital pin LED_BUILTIN as an output. 12 | pinMode(LED_BUILTIN, OUTPUT); 13 | 14 | print("Greeting: "); 15 | char greeting[64]; 16 | getGreeting(greeting, sizeof(greeting)); 17 | println(greeting); 18 | } 19 | 20 | // the loop function runs over and over again forever 21 | void loop() { 22 | digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) 23 | delay(100); // wait 100ms 24 | digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW 25 | delay(900); // wait 900ms 26 | } 27 | 28 | /* 29 | * Entry point 30 | */ 31 | 32 | WASM_EXPORT 33 | void _start() { 34 | setup(); 35 | while (1) { loop(); } 36 | } 37 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/cpp/app.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wasm3/wasm3-arduino/0dcff083f369f89d7bd5d434d60e63d789fab133/examples_pio/Wasm_Advanced/wasm_apps/cpp/app.wasm -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/cpp/app.wasm.h: -------------------------------------------------------------------------------- 1 | unsigned char app_wasm[] = { 2 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x04, 0x60, 3 | 0x02, 0x7f, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60, 4 | 0x00, 0x01, 0x7f, 0x02, 0x74, 0x06, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 5 | 0x6e, 0x6f, 0x05, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x00, 0x00, 0x07, 0x61, 6 | 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x09, 0x67, 0x65, 0x74, 0x50, 0x69, 7 | 0x6e, 0x4c, 0x45, 0x44, 0x00, 0x03, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 8 | 0x6e, 0x6f, 0x07, 0x70, 0x69, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x00, 0x00, 9 | 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x0b, 0x67, 0x65, 0x74, 10 | 0x47, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x07, 0x61, 11 | 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x0c, 0x64, 0x69, 0x67, 0x69, 0x74, 12 | 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x00, 0x00, 0x07, 0x61, 0x72, 13 | 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x00, 14 | 0x02, 0x03, 0x03, 0x02, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 15 | 0x07, 0x01, 0x7f, 0x01, 0x41, 0xa0, 0x28, 0x0b, 0x07, 0x13, 0x02, 0x06, 16 | 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x5f, 0x73, 0x74, 17 | 0x61, 0x72, 0x74, 0x00, 0x07, 0x0a, 0x91, 0x01, 0x02, 0x66, 0x01, 0x02, 18 | 0x7f, 0x23, 0x00, 0x41, 0x40, 0x6a, 0x22, 0x00, 0x24, 0x00, 0x41, 0x84, 19 | 0x08, 0x41, 0x0e, 0x10, 0x00, 0x41, 0x9e, 0x08, 0x41, 0x01, 0x10, 0x00, 20 | 0x41, 0x80, 0x08, 0x10, 0x01, 0x22, 0x01, 0x36, 0x02, 0x00, 0x20, 0x01, 21 | 0x41, 0x01, 0x10, 0x02, 0x41, 0x93, 0x08, 0x41, 0x0a, 0x10, 0x00, 0x20, 22 | 0x00, 0x41, 0xc0, 0x00, 0x10, 0x03, 0x20, 0x00, 0x41, 0x7f, 0x6a, 0x21, 23 | 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x22, 0x01, 0x2d, 0x00, 24 | 0x00, 0x0d, 0x00, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x20, 0x00, 0x6b, 0x10, 25 | 0x00, 0x41, 0x9e, 0x08, 0x41, 0x01, 0x10, 0x00, 0x20, 0x00, 0x41, 0x40, 26 | 0x6b, 0x24, 0x00, 0x0b, 0x28, 0x00, 0x10, 0x06, 0x03, 0x40, 0x41, 0x80, 27 | 0x08, 0x28, 0x02, 0x00, 0x41, 0x01, 0x10, 0x04, 0x41, 0xe4, 0x00, 0x10, 28 | 0x05, 0x41, 0x80, 0x08, 0x28, 0x02, 0x00, 0x41, 0x00, 0x10, 0x04, 0x41, 29 | 0x84, 0x07, 0x10, 0x05, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x0b, 0x22, 0x01, 30 | 0x00, 0x41, 0x84, 0x08, 0x0b, 0x1b, 0x43, 0x2b, 0x2b, 0x20, 0x69, 0x73, 31 | 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0x47, 0x72, 0x65, 32 | 0x65, 0x74, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x00, 0x0a 33 | }; 34 | unsigned int app_wasm_len = 369; 35 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/cpp/arduino_api.h: -------------------------------------------------------------------------------- 1 | #ifndef arduino_wasm_api_h 2 | #define arduino_wasm_api_h 3 | 4 | #include 5 | 6 | #define WASM_EXPORT extern "C" __attribute__((used)) __attribute__((visibility ("default"))) 7 | #define WASM_EXPORT_AS(NAME) WASM_EXPORT __attribute__((export_name(NAME))) 8 | #define WASM_IMPORT(MODULE,NAME) __attribute__((import_module(MODULE))) __attribute__((import_name(NAME))) 9 | #define WASM_CONSTRUCTOR __attribute__((constructor)) 10 | 11 | #define LOW 0x0 12 | #define HIGH 0x1 13 | 14 | #define INPUT 0x0 15 | #define OUTPUT 0x1 16 | #define INPUT_PULLUP 0x2 17 | 18 | extern "C" { 19 | 20 | WASM_IMPORT("arduino", "millis") uint32_t millis (void); 21 | WASM_IMPORT("arduino", "delay") void delay (uint32_t ms); 22 | WASM_IMPORT("arduino", "pinMode") void pinMode (uint32_t pin, uint32_t mode); 23 | WASM_IMPORT("arduino", "digitalWrite") void digitalWrite (uint32_t pin, uint32_t value); 24 | 25 | // This is a convenience function 26 | WASM_IMPORT("arduino", "getPinLED") uint32_t getPinLED (void); 27 | WASM_IMPORT("arduino", "getGreeting") void getGreeting (char* buff, size_t maxlen); 28 | WASM_IMPORT("arduino", "print") void print (const char* s, size_t len); 29 | 30 | static inline size_t strlen(const char *str) { 31 | const char *s; 32 | for (s = str; *s; ++s); 33 | return (s - str); 34 | } 35 | 36 | static inline void print (const char* s) { 37 | print(s, strlen(s)); 38 | } 39 | 40 | static inline void println (const char* s) { 41 | print(s); print("\n"); 42 | } 43 | 44 | } 45 | 46 | #endif // arduino_wasm_api_h 47 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/cpp/arduino_api.syms: -------------------------------------------------------------------------------- 1 | millis 2 | delay 3 | pinMode 4 | digitalWrite 5 | getPinLED 6 | getGreeting 7 | print 8 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/cpp/build.sh: -------------------------------------------------------------------------------- 1 | # Compile 2 | wasicc -Os \ 3 | -z stack-size=4096 -Wl,--initial-memory=65536 \ 4 | -Wl,--allow-undefined-file=arduino_api.syms \ 5 | -Wl,--strip-all -nostdlib \ 6 | -o app.wasm app.cpp 7 | 8 | # Optimize (optional) 9 | wasm-opt -O3 app.wasm -o app.wasm 10 | wasm-strip app.wasm 11 | 12 | # Convert to WAT 13 | #wasm2wat --generate-names app.wasm -o app.wat 14 | 15 | # Convert to C header 16 | xxd -i app.wasm > app.wasm.h 17 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/rust/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "wasm32-unknown-unknown" 3 | rustflags = [ 4 | "-C", "link-args=-zstack-size=2048 -s", 5 | ] 6 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/rust/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target/ 3 | *.wat 4 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "app" 3 | version = "0.1.0" 4 | authors = ["Volodymyr Shymanskyy "] 5 | edition = "2018" 6 | 7 | [lib] 8 | path = "src/app.rs" 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | 13 | [profile.dev] 14 | panic = "abort" 15 | 16 | [profile.release] 17 | panic = "abort" 18 | opt-level = "s" 19 | codegen-units = 1 20 | lto = true 21 | #debug = true 22 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/rust/app.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wasm3/wasm3-arduino/0dcff083f369f89d7bd5d434d60e63d789fab133/examples_pio/Wasm_Advanced/wasm_apps/rust/app.wasm -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/rust/app.wasm.h: -------------------------------------------------------------------------------- 1 | unsigned char app_wasm[] = { 2 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x04, 0x60, 3 | 0x02, 0x7f, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60, 4 | 0x00, 0x01, 0x7f, 0x02, 0x5e, 0x05, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 5 | 0x6e, 0x6f, 0x05, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x00, 0x00, 0x07, 0x61, 6 | 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x09, 0x67, 0x65, 0x74, 0x50, 0x69, 7 | 0x6e, 0x4c, 0x45, 0x44, 0x00, 0x03, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 8 | 0x6e, 0x6f, 0x07, 0x70, 0x69, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x00, 0x00, 9 | 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x0c, 0x64, 0x69, 0x67, 10 | 0x69, 0x74, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x00, 0x00, 0x07, 11 | 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x05, 0x64, 0x65, 0x6c, 0x61, 12 | 0x79, 0x00, 0x02, 0x03, 0x02, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01, 13 | 0x06, 0x0d, 0x02, 0x7f, 0x00, 0x41, 0x95, 0x10, 0x0b, 0x7f, 0x00, 0x41, 14 | 0x95, 0x10, 0x0b, 0x07, 0x2e, 0x04, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 15 | 0x79, 0x02, 0x00, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x05, 16 | 0x0a, 0x5f, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x65, 0x6e, 0x64, 0x03, 17 | 0x00, 0x0b, 0x5f, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x62, 0x61, 0x73, 18 | 0x65, 0x03, 0x01, 0x0a, 0x38, 0x01, 0x36, 0x01, 0x01, 0x7f, 0x41, 0x81, 19 | 0x10, 0x41, 0x14, 0x10, 0x00, 0x41, 0x80, 0x10, 0x41, 0x01, 0x10, 0x00, 20 | 0x10, 0x01, 0x22, 0x00, 0x41, 0x01, 0x10, 0x02, 0x03, 0x40, 0x20, 0x00, 21 | 0x41, 0x01, 0x10, 0x03, 0x41, 0xe4, 0x00, 0x10, 0x04, 0x20, 0x00, 0x41, 22 | 0x00, 0x10, 0x03, 0x41, 0x84, 0x07, 0x10, 0x04, 0x0c, 0x00, 0x0b, 0x00, 23 | 0x0b, 0x0b, 0x1c, 0x01, 0x00, 0x41, 0x80, 0x10, 0x0b, 0x15, 0x0a, 0x52, 24 | 0x75, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 25 | 0x6e, 0x67, 0x20, 0xf0, 0x9f, 0x98, 0x8e 26 | }; 27 | unsigned int app_wasm_len = 283; 28 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/rust/build.sh: -------------------------------------------------------------------------------- 1 | # Compile 2 | cargo build --release 3 | cp ./target/wasm32-unknown-unknown/release/app.wasm ./ 4 | 5 | # Optimize (optional) 6 | wasm-opt -O3 app.wasm -o app.wasm 7 | wasm-strip app.wasm 8 | 9 | # Convert to WAT 10 | #wasm2wat --generate-names app.wasm -o app.wat 11 | 12 | # Convert to C header 13 | xxd -i app.wasm > app.wasm.h 14 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/rust/src/app.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | mod arduino; 4 | use arduino::*; 5 | 6 | struct App { 7 | led: u32, 8 | } 9 | 10 | impl App { 11 | fn new() -> Self { 12 | println("Rust is running 😎"); 13 | 14 | let led = getPinLED(); 15 | pinMode(led, OUTPUT); 16 | Self { led } 17 | } 18 | 19 | fn run(&self) { 20 | digitalWrite(self.led, HIGH); 21 | delay(100); 22 | digitalWrite(self.led, LOW); 23 | delay(900); 24 | } 25 | } 26 | 27 | #[no_mangle] 28 | pub extern fn _start() { 29 | let app = App::new(); 30 | loop { 31 | app.run() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/rust/src/arduino.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | #![allow(non_snake_case)] 3 | 4 | #[link(wasm_import_module = "arduino")] 5 | extern { 6 | #[link_name = "millis"] fn _millis() -> u32; 7 | #[link_name = "delay"] fn _delay(ms: u32); 8 | #[link_name = "pinMode"] fn _pinMode(pin: u32, mode: u32); 9 | #[link_name = "digitalWrite"] fn _digitalWrite(pin: u32, value: u32); 10 | #[link_name = "getPinLED"] fn _getPinLED() -> u32; 11 | #[link_name = "getGreeting"] fn _getGreeting(utf8: * mut u8, maxlen: usize); 12 | #[link_name = "print"] fn _print(utf8: *const u8, len: usize); 13 | } 14 | 15 | pub static LOW: u32 = 0; 16 | pub static HIGH: u32 = 1; 17 | 18 | pub static INPUT: u32 = 0x0; 19 | pub static OUTPUT: u32 = 0x1; 20 | pub static INPUT_PULLUP: u32 = 0x2; 21 | 22 | pub fn millis () -> u32 { unsafe { _millis() } } 23 | pub fn delay (ms: u32) { unsafe { _delay(ms); } } 24 | pub fn pinMode (pin: u32, mode: u32) { unsafe { _pinMode(pin, mode) } } 25 | pub fn digitalWrite (pin: u32, value: u32) { unsafe { _digitalWrite(pin, value) } } 26 | pub fn getPinLED () -> u32 { unsafe { _getPinLED() } } 27 | 28 | pub fn print(string: &str) { 29 | unsafe { _print(string.as_ptr(), string.len()) } 30 | } 31 | 32 | pub fn println(string: &str) { 33 | print(string); 34 | print("\n"); 35 | } 36 | 37 | //TODO: getGreeting 38 | 39 | #[panic_handler] 40 | fn handle_panic(_: &core::panic::PanicInfo) -> ! { 41 | unsafe { core::arch::wasm32::unreachable() } 42 | } 43 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/tinygo/app.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | . "./arduino" 5 | "strconv" 6 | ) 7 | 8 | var LED = GetPinLED() 9 | 10 | func setup() { 11 | PinMode(LED, 1) 12 | 13 | Println("TinyGo is running 😎") 14 | Println("Greeting: " + GetGreeting()) 15 | } 16 | 17 | func loop() { 18 | time := Millis() 19 | Println(strconv.FormatUint(uint64(time), 10)) 20 | 21 | DigitalWrite(LED, HIGH) 22 | Delay(100) 23 | DigitalWrite(LED, LOW) 24 | Delay(900) 25 | } 26 | 27 | /* 28 | * Entry point 29 | */ 30 | 31 | func main() { 32 | setup() 33 | for { 34 | loop() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/tinygo/app.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wasm3/wasm3-arduino/0dcff083f369f89d7bd5d434d60e63d789fab133/examples_pio/Wasm_Advanced/wasm_apps/tinygo/app.wasm -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/tinygo/arduino/arduino.go: -------------------------------------------------------------------------------- 1 | package arduino 2 | 3 | const ( 4 | LOW = 0 5 | HIGH = 1 6 | 7 | INPUT = 0 8 | OUTPUT = 1 9 | INPUT_PULLUP = 2 10 | ) 11 | 12 | //go:wasm-module arduino 13 | //go:export millis 14 | func Millis() uint 15 | 16 | //go:wasm-module arduino 17 | //go:export delay 18 | func Delay(ms uint) 19 | 20 | //go:wasm-module arduino 21 | //go:export pinMode 22 | func PinMode(pin, mode uint) 23 | 24 | //go:wasm-module arduino 25 | //go:export digitalWrite 26 | func DigitalWrite(pin, value uint) 27 | 28 | //go:wasm-module arduino 29 | //go:export getPinLED 30 | func GetPinLED() uint 31 | 32 | //go:wasm-module arduino 33 | //go:export print 34 | func Print(s string) 35 | 36 | //go:wasm-module arduino 37 | //go:export getGreeting 38 | func _getGreeting(buf *byte, maxlen uint) 39 | 40 | func Println(s string) { 41 | Print(s) 42 | Print("\n") 43 | } 44 | 45 | func GetGreeting() string { 46 | var buf = make([]byte, 64) 47 | _getGreeting(&buf[0], 64) 48 | // Find '\0' 49 | n := -1 50 | for i, b := range buf { 51 | if b == 0 { 52 | break 53 | } 54 | n = i 55 | } 56 | return string(buf[:n+1]) 57 | } 58 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_apps/tinygo/build.sh: -------------------------------------------------------------------------------- 1 | # Prepare 2 | export PATH=/opt/tinygo0.17.0/bin:$PATH 3 | export PATH=/opt/go1.15.2/bin:$PATH 4 | export GOROOT=/opt/go1.15.2 5 | 6 | # Compile 7 | tinygo build -target wasm \ 8 | -panic trap -wasm-abi generic \ 9 | -ldflags="-z stack-size=2048 --max-memory=65536" \ 10 | -o app.wasm app.go 11 | 12 | # Optimize (optional) 13 | wasm-opt -Os app.wasm -o app.wasm 14 | wasm-strip app.wasm 15 | 16 | # Convert to WAT 17 | #wasm2wat --generate-names app.wasm -o app.wat 18 | 19 | # Convert to C header 20 | xxd -i app.wasm > app.wasm.h 21 | -------------------------------------------------------------------------------- /examples_pio/Wasm_Advanced/wasm_vm/wasm_vm.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Wasm3 - high performance WebAssembly interpreter written in C. 3 | * Copyright © 2020 Volodymyr Shymanskyy, Steven Massey. 4 | * All rights reserved. 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | 11 | /* 12 | * Configuration 13 | */ 14 | 15 | // Redefine the default LED pin here, if needed 16 | #ifndef LED_PIN 17 | #define LED_PIN LED_BUILTIN 18 | #endif 19 | 20 | #define WASM_STACK_SLOTS 2048 21 | #define NATIVE_STACK_SIZE (32*1024) 22 | 23 | // For (most) devices that cannot allocate a 64KiB wasm page 24 | //#define WASM_MEMORY_LIMIT 4096 25 | 26 | /* 27 | * WebAssembly app 28 | */ 29 | 30 | #include "../wasm_apps/assemblyscript/app.wasm.h" 31 | //#include "../wasm_apps/rust/app.wasm.h" 32 | //#include "../wasm_apps/tinygo/app.wasm.h" 33 | //#include "../wasm_apps/cpp/app.wasm.h" 34 | 35 | /* 36 | * API bindings 37 | * 38 | * Note: each RawFunction should complete with one of these calls: 39 | * m3ApiReturn(val) - Returns a value 40 | * m3ApiSuccess() - Returns void (and no traps) 41 | * m3ApiTrap(trap) - Returns a trap 42 | */ 43 | 44 | m3ApiRawFunction(m3_arduino_millis) 45 | { 46 | m3ApiReturnType (uint32_t) 47 | 48 | m3ApiReturn(millis()); 49 | } 50 | 51 | m3ApiRawFunction(m3_arduino_delay) 52 | { 53 | m3ApiGetArg (uint32_t, ms) 54 | 55 | // You can also trace API calls 56 | //Serial.print("api: delay "); Serial.println(ms); 57 | 58 | delay(ms); 59 | 60 | m3ApiSuccess(); 61 | } 62 | 63 | // This maps pin modes from arduino_wasm_api.h 64 | // to actual platform-specific values 65 | uint8_t mapPinMode(uint8_t mode) 66 | { 67 | switch(mode) { 68 | case 0: return INPUT; 69 | case 1: return OUTPUT; 70 | case 2: return INPUT_PULLUP; 71 | } 72 | return INPUT; 73 | } 74 | 75 | m3ApiRawFunction(m3_arduino_pinMode) 76 | { 77 | m3ApiGetArg (uint32_t, pin) 78 | m3ApiGetArg (uint32_t, mode) 79 | 80 | #if !defined(PARTICLE) 81 | typedef uint8_t PinMode; 82 | #endif 83 | pinMode(pin, (PinMode)mapPinMode(mode)); 84 | 85 | m3ApiSuccess(); 86 | } 87 | 88 | m3ApiRawFunction(m3_arduino_digitalWrite) 89 | { 90 | m3ApiGetArg (uint32_t, pin) 91 | m3ApiGetArg (uint32_t, value) 92 | 93 | digitalWrite(pin, value); 94 | 95 | m3ApiSuccess(); 96 | } 97 | 98 | m3ApiRawFunction(m3_arduino_getPinLED) 99 | { 100 | m3ApiReturnType (uint32_t) 101 | 102 | m3ApiReturn(LED_PIN); 103 | } 104 | 105 | m3ApiRawFunction(m3_arduino_print) 106 | { 107 | m3ApiGetArgMem (const uint8_t *, buf) 108 | m3ApiGetArg (uint32_t, len) 109 | 110 | //printf("api: print %p %d\n", buf, len); 111 | Serial.write(buf, len); 112 | 113 | m3ApiSuccess(); 114 | } 115 | 116 | m3ApiRawFunction(m3_arduino_getGreeting) 117 | { 118 | m3ApiGetArgMem (uint8_t *, out) 119 | m3ApiGetArg (uint32_t, out_len) 120 | 121 | const char buff[] = "Hello WASM world! 😊"; 122 | memcpy(out, buff, min(sizeof(buff), out_len)); 123 | 124 | m3ApiSuccess(); 125 | } 126 | 127 | M3Result LinkArduino (IM3Runtime runtime) 128 | { 129 | IM3Module module = runtime->modules; 130 | const char* arduino = "arduino"; 131 | 132 | m3_LinkRawFunction (module, arduino, "millis", "i()", &m3_arduino_millis); 133 | m3_LinkRawFunction (module, arduino, "delay", "v(i)", &m3_arduino_delay); 134 | m3_LinkRawFunction (module, arduino, "pinMode", "v(ii)", &m3_arduino_pinMode); 135 | m3_LinkRawFunction (module, arduino, "digitalWrite", "v(ii)", &m3_arduino_digitalWrite); 136 | 137 | // Test functions 138 | m3_LinkRawFunction (module, arduino, "getPinLED", "i()", &m3_arduino_getPinLED); 139 | m3_LinkRawFunction (module, arduino, "getGreeting", "v(*i)", &m3_arduino_getGreeting); 140 | m3_LinkRawFunction (module, arduino, "print", "v(*i)", &m3_arduino_print); 141 | 142 | return m3Err_none; 143 | } 144 | 145 | /* 146 | * Engine start, liftoff! 147 | */ 148 | 149 | #define FATAL(func, msg) { Serial.print("Fatal: " func " "); Serial.println(msg); return; } 150 | 151 | void wasm_task(void*) 152 | { 153 | M3Result result = m3Err_none; 154 | 155 | IM3Environment env = m3_NewEnvironment (); 156 | if (!env) FATAL("NewEnvironment", "failed"); 157 | 158 | IM3Runtime runtime = m3_NewRuntime (env, WASM_STACK_SLOTS, NULL); 159 | if (!runtime) FATAL("NewRuntime", "failed"); 160 | 161 | #ifdef WASM_MEMORY_LIMIT 162 | runtime->memoryLimit = WASM_MEMORY_LIMIT; 163 | #endif 164 | 165 | IM3Module module; 166 | result = m3_ParseModule (env, &module, app_wasm, app_wasm_len); 167 | if (result) FATAL("ParseModule", result); 168 | 169 | result = m3_LoadModule (runtime, module); 170 | if (result) FATAL("LoadModule", result); 171 | 172 | result = LinkArduino (runtime); 173 | if (result) FATAL("LinkArduino", result); 174 | 175 | IM3Function f; 176 | result = m3_FindFunction (&f, runtime, "_start"); 177 | if (result) FATAL("FindFunction", result); 178 | 179 | Serial.println("Running WebAssembly..."); 180 | 181 | result = m3_CallV (f); 182 | 183 | // Should not arrive here 184 | 185 | if (result) { 186 | M3ErrorInfo info; 187 | m3_GetErrorInfo (runtime, &info); 188 | Serial.print("Error: "); 189 | Serial.print(result); 190 | Serial.print(" ("); 191 | Serial.print(info.message); 192 | Serial.println(")"); 193 | if (info.file && strlen(info.file) && info.line) { 194 | Serial.print("At "); 195 | Serial.print(info.file); 196 | Serial.print(":"); 197 | Serial.println(info.line); 198 | } 199 | } 200 | } 201 | 202 | void setup() 203 | { 204 | Serial.begin(115200); 205 | delay(100); 206 | 207 | // Wait for serial port to connect 208 | // Needed for native USB port only 209 | while(!Serial) {} 210 | 211 | Serial.println("\nWasm3 v" M3_VERSION " (" M3_ARCH "), build " __DATE__ " " __TIME__); 212 | 213 | #ifdef ESP32 214 | // On ESP32, we can launch in a separate thread 215 | xTaskCreate(&wasm_task, "wasm3", NATIVE_STACK_SIZE, NULL, 5, NULL); 216 | #else 217 | wasm_task(NULL); 218 | #endif 219 | } 220 | 221 | void loop() 222 | { 223 | delay(100); 224 | } 225 | 226 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Data types (KEYWORD1) 3 | ####################################### 4 | M3Result KEYWORD1 5 | IM3Environment KEYWORD1 6 | IM3Runtime KEYWORD1 7 | IM3Module KEYWORD1 8 | IM3Function KEYWORD1 9 | m3ApiRawFunction KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | wasm3 KEYWORD2 15 | m3_NewEnvironment KEYWORD2 16 | m3_NewRuntime KEYWORD2 17 | m3_FreeRuntime KEYWORD2 18 | m3_FreeModule KEYWORD2 19 | m3_ParseModule KEYWORD2 20 | m3_LoadModule KEYWORD2 21 | m3_FindFunction KEYWORD2 22 | m3_RunStart KEYWORD2 23 | m3_GetArgCount KEYWORD2 24 | m3_GetRetCount KEYWORD2 25 | m3_GetArgType KEYWORD2 26 | m3_GetRetType KEYWORD2 27 | m3_Call KEYWORD2 28 | m3_CallV KEYWORD2 29 | m3_CallVL KEYWORD2 30 | m3_CallArgv KEYWORD2 31 | m3_GetResults KEYWORD2 32 | m3_GetResultsV KEYWORD2 33 | m3_GetResultsVL KEYWORD2 34 | m3_LinkRawFunction KEYWORD2 35 | m3_GetMemory KEYWORD2 36 | m3_GetUserData KEYWORD2 37 | 38 | ####################################### 39 | # Literals (LITERAL1) 40 | ####################################### 41 | I32 LITERAL1 42 | I64 LITERAL1 43 | F32 LITERAL1 44 | F64 LITERAL1 45 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Wasm3", 3 | "version": "0.5.0", 4 | "description": "The fastest WebAssembly interpreter (and the most universal runtime). Run WASM files directly on a wide range of devices, including microcontrollers, routers, smartphones and of course within browsers", 5 | "keywords": "esp32, esp8266, wasm, webassembly, interpreter, iot, edge computing", 6 | "authors": [ 7 | { 8 | "name": "Volodymyr Shymanskyy", 9 | "url": "https://github.com/vshymanskyy", 10 | "maintainer": true 11 | }, 12 | { 13 | "name": "Steven Massey", 14 | "url": "https://github.com/soundandform" 15 | } 16 | ], 17 | "repository": 18 | { 19 | "type": "git", 20 | "url": "https://github.com/wasm3/wasm3-arduino.git" 21 | }, 22 | "homepage": "https://github.com/wasm3/wasm3", 23 | "frameworks": "*", 24 | "platforms": "*", 25 | "build": { 26 | "libArchive": false 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Wasm3 2 | version=0.5.0 3 | author=Volodymyr Shymanskyy , Steven Massey 4 | license=MIT 5 | maintainer=Volodymyr Shymanskyy 6 | sentence=The fastest WebAssembly interpreter (and the most universal runtime) 7 | paragraph=Run WASM files directly on a wide range of devices, including microcontrollers, smartphones, routers, and of course within browsers 8 | category=Other 9 | url=https://github.com/wasm3/wasm3 10 | repository=https://github.com/wasm3/wasm3-arduino.git 11 | architectures=* 12 | includes=wasm3.h 13 | -------------------------------------------------------------------------------- /src/m3_api_libc.c: -------------------------------------------------------------------------------- 1 | // 2 | // m3_api_libc.c 3 | // 4 | // Created by Volodymyr Shymanskyy on 11/20/19. 5 | // Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. 6 | // 7 | 8 | #define _POSIX_C_SOURCE 200809L 9 | 10 | #include "m3_api_libc.h" 11 | 12 | #include "m3_env.h" 13 | #include "m3_exception.h" 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | typedef uint32_t wasm_ptr_t; 20 | typedef uint32_t wasm_size_t; 21 | 22 | m3ApiRawFunction(m3_libc_abort) 23 | { 24 | m3ApiTrap(m3Err_trapAbort); 25 | } 26 | 27 | m3ApiRawFunction(m3_libc_exit) 28 | { 29 | m3ApiGetArg (int32_t, code) 30 | 31 | m3ApiTrap(m3Err_trapExit); 32 | } 33 | 34 | 35 | m3ApiRawFunction(m3_libc_memset) 36 | { 37 | m3ApiReturnType (int32_t) 38 | 39 | m3ApiGetArgMem (void*, i_ptr) 40 | m3ApiGetArg (int32_t, i_value) 41 | m3ApiGetArg (wasm_size_t, i_size) 42 | 43 | m3ApiCheckMem(i_ptr, i_size); 44 | 45 | u32 result = m3ApiPtrToOffset(memset (i_ptr, i_value, i_size)); 46 | m3ApiReturn(result); 47 | } 48 | 49 | m3ApiRawFunction(m3_libc_memmove) 50 | { 51 | m3ApiReturnType (int32_t) 52 | 53 | m3ApiGetArgMem (void*, o_dst) 54 | m3ApiGetArgMem (void*, i_src) 55 | m3ApiGetArg (wasm_size_t, i_size) 56 | 57 | m3ApiCheckMem(o_dst, i_size); 58 | m3ApiCheckMem(i_src, i_size); 59 | 60 | u32 result = m3ApiPtrToOffset(memmove (o_dst, i_src, i_size)); 61 | m3ApiReturn(result); 62 | } 63 | 64 | m3ApiRawFunction(m3_libc_print) 65 | { 66 | m3ApiReturnType (uint32_t) 67 | 68 | m3ApiGetArgMem (void*, i_ptr) 69 | m3ApiGetArg (wasm_size_t, i_size) 70 | 71 | m3ApiCheckMem(i_ptr, i_size); 72 | 73 | fwrite(i_ptr, i_size, 1, stdout); 74 | fflush(stdout); 75 | 76 | m3ApiReturn(i_size); 77 | } 78 | 79 | static 80 | void internal_itoa(int n, char s[], int radix) 81 | { 82 | static char const HEXDIGITS[0x10] = { 83 | '0', '1', '2', '3', '4', '5', '6', '7', 84 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 85 | }; 86 | 87 | int i, j, sign; 88 | char c; 89 | 90 | if ((sign = n) < 0) { n = -n; } 91 | i = 0; 92 | do { 93 | s[i++] = HEXDIGITS[n % radix]; 94 | } while ((n /= radix) > 0); 95 | 96 | if (sign < 0) { s[i++] = '-'; } 97 | s[i] = '\0'; 98 | 99 | // reverse 100 | for (i = 0, j = strlen(s)-1; i d_m3MaxSaneFunctionArgRetCount); 50 | 51 | _ (AllocFuncType (& funcType, (u32) maxNumTypes)); 52 | 53 | u8 * typelist = funcType->types; 54 | 55 | bool parsingRets = true; 56 | while (* sig) 57 | { 58 | char typeChar = * sig++; 59 | 60 | if (typeChar == '(') 61 | { 62 | parsingRets = false; 63 | continue; 64 | } 65 | else if ( typeChar == ' ') 66 | continue; 67 | else if (typeChar == ')') 68 | break; 69 | 70 | u8 type = ConvertTypeCharToTypeId (typeChar); 71 | 72 | _throwif ("unknown argument type char", c_m3Type_unknown == type); 73 | 74 | if (type == c_m3Type_none) 75 | continue; 76 | 77 | if (parsingRets) 78 | { 79 | _throwif ("malformed signature; return count overflow", funcType->numRets >= maxNumTypes); 80 | funcType->numRets++; 81 | *typelist++ = type; 82 | } 83 | else 84 | { 85 | _throwif ("malformed signature; arg count overflow", (u32)(funcType->numRets) + funcType->numArgs >= maxNumTypes); 86 | funcType->numArgs++; 87 | *typelist++ = type; 88 | } 89 | } 90 | 91 | } _catch: 92 | 93 | if (result) 94 | m3_Free (funcType); 95 | 96 | * o_functionType = funcType; 97 | 98 | return result; 99 | } 100 | 101 | 102 | static 103 | M3Result ValidateSignature (IM3Function i_function, ccstr_t i_linkingSignature) 104 | { 105 | M3Result result = m3Err_none; 106 | 107 | IM3FuncType ftype = NULL; 108 | _ (SignatureToFuncType (& ftype, i_linkingSignature)); 109 | 110 | if (not AreFuncTypesEqual (ftype, i_function->funcType)) 111 | { 112 | m3log (module, "expected: %s", SPrintFuncTypeSignature (ftype)); 113 | m3log (module, " found: %s", SPrintFuncTypeSignature (i_function->funcType)); 114 | 115 | _throw ("function signature mismatch"); 116 | } 117 | 118 | _catch: 119 | 120 | m3_Free (ftype); 121 | 122 | return result; 123 | } 124 | 125 | 126 | M3Result LinkRawFunction (IM3Module io_module, IM3Function io_function, ccstr_t signature, const void * i_function, const void * i_userdata) 127 | { 128 | M3Result result = m3Err_none; d_m3Assert (io_module->runtime); 129 | 130 | _try { 131 | if (signature) { 132 | _ (ValidateSignature (io_function, signature)); 133 | } 134 | IM3CodePage page = AcquireCodePageWithCapacity (io_module->runtime, 4); 135 | 136 | if (page) 137 | { 138 | io_function->compiled = GetPagePC (page); 139 | io_function->module = io_module; 140 | 141 | EmitWord (page, op_CallRawFunction); 142 | EmitWord (page, i_function); 143 | EmitWord (page, io_function); 144 | EmitWord (page, i_userdata); 145 | 146 | ReleaseCodePage (io_module->runtime, page); 147 | } 148 | else _throw(m3Err_mallocFailedCodePage); 149 | 150 | } _catch: 151 | return result; 152 | } 153 | 154 | M3Result FindAndLinkFunction (IM3Module io_module, 155 | ccstr_t i_moduleName, 156 | ccstr_t i_functionName, 157 | ccstr_t i_signature, 158 | voidptr_t i_function, 159 | voidptr_t i_userdata) 160 | { 161 | M3Result result = m3Err_functionLookupFailed; 162 | 163 | bool wildcardModule = (strcmp (i_moduleName, "*") == 0); 164 | 165 | for (u32 i = 0; i < io_module->numFunctions; ++i) 166 | { 167 | IM3Function f = & io_module->functions [i]; 168 | 169 | if (f->import.moduleUtf8 and f->import.fieldUtf8) 170 | { 171 | if (strcmp (f->import.fieldUtf8, i_functionName) == 0 and 172 | (wildcardModule or strcmp (f->import.moduleUtf8, i_moduleName) == 0)) 173 | { 174 | result = LinkRawFunction (io_module, f, i_signature, i_function, i_userdata); 175 | if (result) return result; 176 | } 177 | } 178 | } 179 | 180 | return result; 181 | } 182 | 183 | M3Result m3_LinkRawFunctionEx (IM3Module io_module, 184 | const char * const i_moduleName, 185 | const char * const i_functionName, 186 | const char * const i_signature, 187 | M3RawCall i_function, 188 | const void * i_userdata) 189 | { 190 | return FindAndLinkFunction (io_module, i_moduleName, i_functionName, i_signature, (voidptr_t)i_function, i_userdata); 191 | } 192 | 193 | M3Result m3_LinkRawFunction (IM3Module io_module, 194 | const char * const i_moduleName, 195 | const char * const i_functionName, 196 | const char * const i_signature, 197 | M3RawCall i_function) 198 | { 199 | return FindAndLinkFunction (io_module, i_moduleName, i_functionName, i_signature, (voidptr_t)i_function, NULL); 200 | } 201 | 202 | -------------------------------------------------------------------------------- /src/m3_bind.h: -------------------------------------------------------------------------------- 1 | // 2 | // m3_bind.h 3 | // 4 | // Created by Steven Massey on 2/27/20. 5 | // Copyright © 2020 Steven Massey. All rights reserved. 6 | // 7 | 8 | #ifndef m3_bind_h 9 | #define m3_bind_h 10 | 11 | #include "m3_env.h" 12 | 13 | d_m3BeginExternC 14 | 15 | u8 ConvertTypeCharToTypeId (char i_code); 16 | M3Result SignatureToFuncType (IM3FuncType * o_functionType, ccstr_t i_signature); 17 | 18 | d_m3EndExternC 19 | 20 | #endif /* m3_bind_h */ 21 | -------------------------------------------------------------------------------- /src/m3_code.c: -------------------------------------------------------------------------------- 1 | // 2 | // m3_code.c 3 | // 4 | // Created by Steven Massey on 4/19/19. 5 | // Copyright © 2019 Steven Massey. All rights reserved. 6 | // 7 | 8 | #include "m3_code.h" 9 | 10 | 11 | //--------------------------------------------------------------------------------------------------------------------------------- 12 | 13 | 14 | IM3CodePage NewCodePage (u32 i_minNumLines) 15 | { 16 | static u32 s_sequence = 0; 17 | 18 | IM3CodePage page; 19 | 20 | u32 pageSize = sizeof (M3CodePageHeader) + sizeof (code_t) * i_minNumLines; 21 | 22 | pageSize = (pageSize + (d_m3CodePageAlignSize-1)) & ~(d_m3CodePageAlignSize-1); // align 23 | page = (IM3CodePage)m3_Malloc (pageSize); 24 | 25 | if (page) 26 | { 27 | page->info.sequence = ++s_sequence; 28 | page->info.numLines = (pageSize - sizeof (M3CodePageHeader)) / sizeof (code_t); 29 | 30 | #if d_m3RecordBacktraces 31 | u32 pageSizeBt = sizeof (M3CodeMappingPage) + sizeof (M3CodeMapEntry) * page->info.numLines; 32 | page->info.mapping = (M3CodeMappingPage *)m3_Malloc (pageSizeBt); 33 | 34 | if (page->info.mapping) 35 | { 36 | page->info.mapping->size = 0; 37 | page->info.mapping->capacity = page->info.numLines; 38 | } 39 | else 40 | { 41 | m3_Free (page); 42 | return NULL; 43 | } 44 | page->info.mapping->basePC = GetPageStartPC(page); 45 | #endif // d_m3RecordBacktraces 46 | 47 | m3log (runtime, "new page: %p; seq: %d; bytes: %d; lines: %d", GetPagePC (page), page->info.sequence, pageSize, page->info.numLines); 48 | } 49 | 50 | return page; 51 | } 52 | 53 | 54 | void FreeCodePages (IM3CodePage * io_list) 55 | { 56 | IM3CodePage page = * io_list; 57 | 58 | while (page) 59 | { 60 | m3log (code, "free page: %d; %p; util: %3.1f%%", page->info.sequence, page, 100. * page->info.lineIndex / page->info.numLines); 61 | 62 | IM3CodePage next = page->info.next; 63 | #if d_m3RecordBacktraces 64 | m3_Free (page->info.mapping); 65 | #endif // d_m3RecordBacktraces 66 | m3_Free (page); 67 | page = next; 68 | } 69 | 70 | * io_list = NULL; 71 | } 72 | 73 | 74 | u32 NumFreeLines (IM3CodePage i_page) 75 | { 76 | d_m3Assert (i_page->info.lineIndex <= i_page->info.numLines); 77 | 78 | return i_page->info.numLines - i_page->info.lineIndex; 79 | } 80 | 81 | 82 | void EmitWord_impl (IM3CodePage i_page, void * i_word) 83 | { d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines); 84 | i_page->code [i_page->info.lineIndex++] = i_word; 85 | } 86 | 87 | void EmitWord32 (IM3CodePage i_page, const u32 i_word) 88 | { d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines); 89 | * ((u32 *) & i_page->code [i_page->info.lineIndex++]) = i_word; 90 | } 91 | 92 | void EmitWord64 (IM3CodePage i_page, const u64 i_word) 93 | { 94 | #if M3_SIZEOF_PTR == 4 95 | d_m3Assert (i_page->info.lineIndex+2 <= i_page->info.numLines); 96 | * ((u64 *) & i_page->code [i_page->info.lineIndex]) = i_word; 97 | i_page->info.lineIndex += 2; 98 | #else 99 | d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines); 100 | * ((u64 *) & i_page->code [i_page->info.lineIndex]) = i_word; 101 | i_page->info.lineIndex += 1; 102 | #endif 103 | } 104 | 105 | 106 | #if d_m3RecordBacktraces 107 | void EmitMappingEntry (IM3CodePage i_page, u32 i_moduleOffset) 108 | { 109 | M3CodeMappingPage * page = i_page->info.mapping; 110 | d_m3Assert (page->size < page->capacity); 111 | 112 | M3CodeMapEntry * entry = & page->entries[page->size++]; 113 | pc_t pc = GetPagePC (i_page); 114 | 115 | entry->pcOffset = pc - page->basePC; 116 | entry->moduleOffset = i_moduleOffset; 117 | } 118 | #endif // d_m3RecordBacktraces 119 | 120 | pc_t GetPageStartPC (IM3CodePage i_page) 121 | { 122 | return & i_page->code [0]; 123 | } 124 | 125 | 126 | pc_t GetPagePC (IM3CodePage i_page) 127 | { 128 | if (i_page) 129 | return & i_page->code [i_page->info.lineIndex]; 130 | else 131 | return NULL; 132 | } 133 | 134 | 135 | void PushCodePage (IM3CodePage * i_list, IM3CodePage i_codePage) 136 | { 137 | IM3CodePage next = * i_list; 138 | i_codePage->info.next = next; 139 | * i_list = i_codePage; 140 | } 141 | 142 | 143 | IM3CodePage PopCodePage (IM3CodePage * i_list) 144 | { 145 | IM3CodePage page = * i_list; 146 | * i_list = page->info.next; 147 | page->info.next = NULL; 148 | 149 | return page; 150 | } 151 | 152 | 153 | 154 | u32 FindCodePageEnd (IM3CodePage i_list, IM3CodePage * o_end) 155 | { 156 | u32 numPages = 0; 157 | * o_end = NULL; 158 | 159 | while (i_list) 160 | { 161 | * o_end = i_list; 162 | ++numPages; 163 | i_list = i_list->info.next; 164 | } 165 | 166 | return numPages; 167 | } 168 | 169 | 170 | u32 CountCodePages (IM3CodePage i_list) 171 | { 172 | IM3CodePage unused; 173 | return FindCodePageEnd (i_list, & unused); 174 | } 175 | 176 | 177 | IM3CodePage GetEndCodePage (IM3CodePage i_list) 178 | { 179 | IM3CodePage end; 180 | FindCodePageEnd (i_list, & end); 181 | 182 | return end; 183 | } 184 | 185 | #if d_m3RecordBacktraces 186 | bool ContainsPC (IM3CodePage i_page, pc_t i_pc) 187 | { 188 | return GetPageStartPC (i_page) <= i_pc && i_pc < GetPagePC (i_page); 189 | } 190 | 191 | 192 | bool MapPCToOffset (IM3CodePage i_page, pc_t i_pc, u32 * o_moduleOffset) 193 | { 194 | M3CodeMappingPage * mapping = i_page->info.mapping; 195 | 196 | u32 pcOffset = i_pc - mapping->basePC; 197 | 198 | u32 left = 0; 199 | u32 right = mapping->size; 200 | 201 | while (left < right) 202 | { 203 | u32 mid = left + (right - left) / 2; 204 | 205 | if (mapping->entries[mid].pcOffset < pcOffset) 206 | { 207 | left = mid + 1; 208 | } 209 | else if (mapping->entries[mid].pcOffset > pcOffset) 210 | { 211 | right = mid; 212 | } 213 | else 214 | { 215 | *o_moduleOffset = mapping->entries[mid].moduleOffset; 216 | return true; 217 | } 218 | } 219 | 220 | // Getting here means left is now one more than the element we want. 221 | if (left > 0) 222 | { 223 | left--; 224 | *o_moduleOffset = mapping->entries[left].moduleOffset; 225 | return true; 226 | } 227 | else return false; 228 | } 229 | #endif // d_m3RecordBacktraces 230 | 231 | //--------------------------------------------------------------------------------------------------------------------------------- 232 | 233 | 234 | -------------------------------------------------------------------------------- /src/m3_code.h: -------------------------------------------------------------------------------- 1 | // 2 | // m3_code.h 3 | // 4 | // Created by Steven Massey on 4/19/19. 5 | // Copyright © 2019 Steven Massey. All rights reserved. 6 | // 7 | 8 | #ifndef m3_code_h 9 | #define m3_code_h 10 | 11 | #include "m3_core.h" 12 | 13 | d_m3BeginExternC 14 | 15 | typedef struct M3CodePage 16 | { 17 | M3CodePageHeader info; 18 | code_t code [1]; 19 | } 20 | M3CodePage; 21 | 22 | typedef M3CodePage * IM3CodePage; 23 | 24 | 25 | IM3CodePage NewCodePage (u32 i_minNumLines); 26 | 27 | void FreeCodePages (IM3CodePage * io_list); 28 | 29 | u32 NumFreeLines (IM3CodePage i_page); 30 | pc_t GetPageStartPC (IM3CodePage i_page); 31 | pc_t GetPagePC (IM3CodePage i_page); 32 | void EmitWord_impl (IM3CodePage i_page, void* i_word); 33 | void EmitWord32 (IM3CodePage i_page, u32 i_word); 34 | void EmitWord64 (IM3CodePage i_page, u64 i_word); 35 | # if d_m3RecordBacktraces 36 | void EmitMappingEntry (IM3CodePage i_page, u32 i_moduleOffset); 37 | # endif // d_m3RecordBacktraces 38 | 39 | void PushCodePage (IM3CodePage * io_list, IM3CodePage i_codePage); 40 | IM3CodePage PopCodePage (IM3CodePage * io_list); 41 | 42 | IM3CodePage GetEndCodePage (IM3CodePage i_list); // i_list = NULL is valid 43 | u32 CountCodePages (IM3CodePage i_list); // i_list = NULL is valid 44 | 45 | # if d_m3RecordBacktraces 46 | bool ContainsPC (IM3CodePage i_page, pc_t i_pc); 47 | bool MapPCToOffset (IM3CodePage i_page, pc_t i_pc, u32 * o_moduleOffset); 48 | # endif // d_m3RecordBacktraces 49 | 50 | # ifdef DEBUG 51 | void dump_code_page (IM3CodePage i_codePage, pc_t i_startPC); 52 | # endif 53 | 54 | #define EmitWord(page, val) EmitWord_impl(page, (void*)(val)) 55 | 56 | //--------------------------------------------------------------------------------------------------------------------------------- 57 | 58 | # if d_m3RecordBacktraces 59 | 60 | typedef struct M3CodeMapEntry 61 | { 62 | u32 pcOffset; 63 | u32 moduleOffset; 64 | } 65 | M3CodeMapEntry; 66 | 67 | typedef struct M3CodeMappingPage 68 | { 69 | pc_t basePC; 70 | u32 size; 71 | u32 capacity; 72 | M3CodeMapEntry entries []; 73 | } 74 | M3CodeMappingPage; 75 | 76 | # endif // d_m3RecordBacktraces 77 | 78 | d_m3EndExternC 79 | 80 | #endif // m3_code_h 81 | -------------------------------------------------------------------------------- /src/m3_compile.h: -------------------------------------------------------------------------------- 1 | // 2 | // m3_compile.h 3 | // 4 | // Created by Steven Massey on 4/17/19. 5 | // Copyright © 2019 Steven Massey. All rights reserved. 6 | // 7 | 8 | #ifndef m3_compile_h 9 | #define m3_compile_h 10 | 11 | #include "m3_code.h" 12 | #include "m3_exec_defs.h" 13 | #include "m3_function.h" 14 | 15 | d_m3BeginExternC 16 | 17 | enum 18 | { 19 | c_waOp_block = 0x02, 20 | c_waOp_loop = 0x03, 21 | c_waOp_if = 0x04, 22 | c_waOp_else = 0x05, 23 | c_waOp_end = 0x0b, 24 | c_waOp_branch = 0x0c, 25 | c_waOp_branchTable = 0x0e, 26 | c_waOp_branchIf = 0x0d, 27 | c_waOp_call = 0x10, 28 | c_waOp_getLocal = 0x20, 29 | c_waOp_setLocal = 0x21, 30 | c_waOp_teeLocal = 0x22, 31 | 32 | c_waOp_getGlobal = 0x23, 33 | 34 | c_waOp_i32_const = 0x41, 35 | c_waOp_i64_const = 0x42, 36 | c_waOp_f32_const = 0x43, 37 | c_waOp_f64_const = 0x44, 38 | 39 | c_waOp_memoryCopy = 0xfc0a, 40 | c_waOp_memoryFill = 0xfc0b 41 | }; 42 | 43 | 44 | #define d_FuncRetType(ftype,i) ((ftype)->types[(i)]) 45 | #define d_FuncArgType(ftype,i) ((ftype)->types[(ftype)->numRets + (i)]) 46 | 47 | //----------------------------------------------------------------------------------------------------------------------------------- 48 | 49 | typedef struct M3CompilationScope 50 | { 51 | struct M3CompilationScope * outer; 52 | 53 | pc_t pc; // used by ContinueLoop's 54 | pc_t patches; 55 | i32 depth; 56 | u16 exitStackIndex; 57 | i16 blockStackIndex; 58 | // u16 topSlot; 59 | IM3FuncType type; 60 | m3opcode_t opcode; 61 | bool isPolymorphic; 62 | } 63 | M3CompilationScope; 64 | 65 | typedef M3CompilationScope * IM3CompilationScope; 66 | 67 | typedef struct 68 | { 69 | IM3Runtime runtime; 70 | IM3Module module; 71 | 72 | bytes_t wasm; 73 | bytes_t wasmEnd; 74 | bytes_t lastOpcodeStart; 75 | 76 | M3CompilationScope block; 77 | 78 | IM3Function function; 79 | 80 | IM3CodePage page; 81 | 82 | #ifdef DEBUG 83 | u32 numEmits; 84 | u32 numOpcodes; 85 | #endif 86 | 87 | u16 stackFirstDynamicIndex; // args and locals are pushed to the stack so that their slot locations can be tracked. the wasm model itself doesn't 88 | // treat these values as being on the stack, so stackFirstDynamicIndex marks the start of the real Wasm stack 89 | u16 stackIndex; // current stack top 90 | 91 | u16 slotFirstConstIndex; 92 | u16 slotMaxConstIndex; // as const's are encountered during compilation this tracks their location in the "real" stack 93 | 94 | u16 slotFirstLocalIndex; 95 | u16 slotFirstDynamicIndex; // numArgs + numLocals + numReservedConstants. the first mutable slot available to the compiler. 96 | 97 | u16 maxStackSlots; 98 | 99 | m3slot_t constants [d_m3MaxConstantTableSize]; 100 | 101 | // 'wasmStack' holds slot locations 102 | u16 wasmStack [d_m3MaxFunctionStackHeight]; 103 | u8 typeStack [d_m3MaxFunctionStackHeight]; 104 | 105 | // 'm3Slots' contains allocation usage counts 106 | u8 m3Slots [d_m3MaxFunctionSlots]; 107 | 108 | u16 slotMaxAllocatedIndexPlusOne; 109 | 110 | u16 regStackIndexPlusOne [2]; 111 | 112 | m3opcode_t previousOpcode; 113 | } 114 | M3Compilation; 115 | 116 | typedef M3Compilation * IM3Compilation; 117 | 118 | typedef M3Result (* M3Compiler) (IM3Compilation, m3opcode_t); 119 | 120 | 121 | //----------------------------------------------------------------------------------------------------------------------------------- 122 | 123 | 124 | typedef struct M3OpInfo 125 | { 126 | #ifdef DEBUG 127 | const char * const name; 128 | #endif 129 | 130 | i8 stackOffset; 131 | u8 type; 132 | 133 | // for most operations: 134 | // [0]= top operand in register, [1]= top operand in stack, [2]= both operands in stack 135 | IM3Operation operations [4]; 136 | 137 | M3Compiler compiler; 138 | } 139 | M3OpInfo; 140 | 141 | typedef const M3OpInfo * IM3OpInfo; 142 | 143 | IM3OpInfo GetOpInfo (m3opcode_t opcode); 144 | 145 | // TODO: This helper should be removed, when MultiValue is implemented 146 | static inline 147 | u8 GetSingleRetType(IM3FuncType ftype) { 148 | return (ftype && ftype->numRets) ? ftype->types[0] : (u8)c_m3Type_none; 149 | } 150 | 151 | #ifdef DEBUG 152 | #define M3OP(...) { __VA_ARGS__ } 153 | #define M3OP_RESERVED { "reserved" } 154 | #else 155 | // Strip-off name 156 | #define M3OP(name, ...) { __VA_ARGS__ } 157 | #define M3OP_RESERVED { 0 } 158 | #endif 159 | 160 | #if d_m3HasFloat 161 | #define M3OP_F M3OP 162 | #elif d_m3NoFloatDynamic 163 | #define M3OP_F(n,o,t,op,...) M3OP(n, o, t, { op_Unsupported, op_Unsupported, op_Unsupported, op_Unsupported }, __VA_ARGS__) 164 | #else 165 | #define M3OP_F(...) { 0 } 166 | #endif 167 | 168 | //----------------------------------------------------------------------------------------------------------------------------------- 169 | 170 | u16 GetTypeNumSlots (u8 i_type); 171 | void AlignSlotToType (u16 * io_slotIndex, u8 i_type); 172 | 173 | bool IsRegisterAllocated (IM3Compilation o, u32 i_register); 174 | bool IsRegisterSlotAlias (u16 i_slot); 175 | bool IsFpRegisterSlotAlias (u16 i_slot); 176 | bool IsIntRegisterSlotAlias (u16 i_slot); 177 | 178 | bool IsStackPolymorphic (IM3Compilation o); 179 | 180 | M3Result CompileBlock (IM3Compilation io, IM3FuncType i_blockType, m3opcode_t i_blockOpcode); 181 | 182 | M3Result CompileBlockStatements (IM3Compilation io); 183 | M3Result CompileFunction (IM3Function io_function); 184 | 185 | u16 GetMaxUsedSlotPlusOne (IM3Compilation o); 186 | 187 | d_m3EndExternC 188 | 189 | #endif // m3_compile_h 190 | -------------------------------------------------------------------------------- /src/m3_config.h: -------------------------------------------------------------------------------- 1 | // 2 | // m3_config.h 3 | // 4 | // Created by Steven Massey on 5/4/19. 5 | // Copyright © 2019 Steven Massey. All rights reserved. 6 | // 7 | 8 | #ifndef m3_config_h 9 | #define m3_config_h 10 | 11 | #include "m3_config_platforms.h" 12 | 13 | // general -------------------------------------------------------------------- 14 | 15 | # ifndef d_m3CodePageAlignSize 16 | # define d_m3CodePageAlignSize 4096 17 | # endif 18 | 19 | # ifndef d_m3EnableCodePageRefCounting 20 | # define d_m3EnableCodePageRefCounting 0 21 | # endif 22 | 23 | # ifndef d_m3MaxFunctionStackHeight 24 | # define d_m3MaxFunctionStackHeight 2000 // TODO: comment on upper limit 25 | # endif 26 | 27 | # ifndef d_m3MaxLinearMemoryPages 28 | # define d_m3MaxLinearMemoryPages 32768 29 | # endif 30 | 31 | # ifndef d_m3MaxFunctionSlots 32 | # define d_m3MaxFunctionSlots ((d_m3MaxFunctionStackHeight)*2) 33 | # endif 34 | 35 | # ifndef d_m3MaxConstantTableSize 36 | # define d_m3MaxConstantTableSize 120 37 | # endif 38 | 39 | # ifndef d_m3MaxDuplicateFunctionImpl 40 | # define d_m3MaxDuplicateFunctionImpl 3 41 | # endif 42 | 43 | # ifndef d_m3EnableExtendedOpcodes 44 | # define d_m3EnableExtendedOpcodes 1 45 | # endif 46 | 47 | # ifndef d_m3VerboseErrorMessages 48 | # define d_m3VerboseErrorMessages 1 49 | # endif 50 | 51 | # ifndef d_m3FixedHeap 52 | # define d_m3FixedHeap false 53 | //# define d_m3FixedHeap (32*1024) 54 | # endif 55 | 56 | # ifndef d_m3FixedHeapAlign 57 | # define d_m3FixedHeapAlign 16 58 | # endif 59 | 60 | # ifndef d_m3Use32BitSlots 61 | # define d_m3Use32BitSlots 1 62 | # endif 63 | 64 | # ifndef d_m3ProfilerSlotMask 65 | # define d_m3ProfilerSlotMask 0xFFFF 66 | # endif 67 | 68 | # ifndef d_m3RecordBacktraces 69 | # define d_m3RecordBacktraces 0 70 | # endif 71 | 72 | # ifndef d_m3EnableExceptionBreakpoint 73 | # define d_m3EnableExceptionBreakpoint 0 // see m3_exception.h 74 | # endif 75 | 76 | 77 | // profiling and tracing ------------------------------------------------------ 78 | 79 | # ifndef d_m3EnableOpProfiling 80 | # define d_m3EnableOpProfiling 0 // opcode usage counters 81 | # endif 82 | 83 | # ifndef d_m3EnableOpTracing 84 | # define d_m3EnableOpTracing 0 // only works with DEBUG 85 | # endif 86 | 87 | # ifndef d_m3EnableStrace 88 | # define d_m3EnableStrace 0 // 1 - trace exported function calls 89 | // 2 - trace all calls (structured) - requires DEBUG 90 | // 3 - all calls + loops + memory operations 91 | # endif 92 | 93 | 94 | // logging -------------------------------------------------------------------- 95 | 96 | # ifndef d_m3LogParse 97 | # define d_m3LogParse 0 // .wasm binary decoding info 98 | # endif 99 | 100 | # ifndef d_m3LogModule 101 | # define d_m3LogModule 0 // wasm module info 102 | # endif 103 | 104 | # ifndef d_m3LogCompile 105 | # define d_m3LogCompile 0 // wasm -> metacode generation phase 106 | # endif 107 | 108 | # ifndef d_m3LogWasmStack 109 | # define d_m3LogWasmStack 0 // dump the wasm stack when pushed or popped 110 | # endif 111 | 112 | # ifndef d_m3LogEmit 113 | # define d_m3LogEmit 0 // metacode generation info 114 | # endif 115 | 116 | # ifndef d_m3LogCodePages 117 | # define d_m3LogCodePages 0 // dump metacode pages when released 118 | # endif 119 | 120 | # ifndef d_m3LogRuntime 121 | # define d_m3LogRuntime 0 // higher-level runtime information 122 | # endif 123 | 124 | # ifndef d_m3LogNativeStack 125 | # define d_m3LogNativeStack 0 // track the memory usage of the C-stack 126 | # endif 127 | 128 | 129 | // other ---------------------------------------------------------------------- 130 | 131 | # ifndef d_m3HasFloat 132 | # define d_m3HasFloat 1 // implement floating point ops 133 | # endif 134 | 135 | #if !d_m3HasFloat && !defined(d_m3NoFloatDynamic) 136 | # define d_m3NoFloatDynamic 1 // if no floats, do not fail until flops are actually executed 137 | #endif 138 | 139 | # ifndef d_m3SkipStackCheck 140 | # define d_m3SkipStackCheck 0 // skip stack overrun checks 141 | # endif 142 | 143 | # ifndef d_m3SkipMemoryBoundsCheck 144 | # define d_m3SkipMemoryBoundsCheck 0 // skip memory bounds checks 145 | # endif 146 | 147 | #endif // m3_config_h 148 | -------------------------------------------------------------------------------- /src/m3_config_platforms.h: -------------------------------------------------------------------------------- 1 | // 2 | // m3_config_platforms.h 3 | // 4 | // Created by Volodymyr Shymanskyy on 11/20/19. 5 | // Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. 6 | // 7 | 8 | #ifndef m3_config_platforms_h 9 | #define m3_config_platforms_h 10 | 11 | #include "wasm3_defs.h" 12 | 13 | /* 14 | * Internal helpers 15 | */ 16 | 17 | # if !defined(__cplusplus) || defined(_MSC_VER) 18 | # define not ! 19 | # define and && 20 | # define or || 21 | # endif 22 | 23 | /* 24 | * Detect/define features 25 | */ 26 | 27 | # if defined(M3_COMPILER_MSVC) 28 | # include 29 | # if UINTPTR_MAX == 0xFFFFFFFF 30 | # define M3_SIZEOF_PTR 4 31 | # elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFu 32 | # define M3_SIZEOF_PTR 8 33 | # else 34 | # error "Pointer size not supported" 35 | # endif 36 | # elif defined(__SIZEOF_POINTER__) 37 | # define M3_SIZEOF_PTR __SIZEOF_POINTER__ 38 | #else 39 | # error "Pointer size not detected" 40 | # endif 41 | 42 | # if defined(M3_BIG_ENDIAN) 43 | # define M3_BSWAP_u8(X) {} 44 | # define M3_BSWAP_u16(X) { (X)=m3_bswap16((X)); } 45 | # define M3_BSWAP_u32(X) { (X)=m3_bswap32((X)); } 46 | # define M3_BSWAP_u64(X) { (X)=m3_bswap64((X)); } 47 | # define M3_BSWAP_i8(X) {} 48 | # define M3_BSWAP_i16(X) M3_BSWAP_u16(X) 49 | # define M3_BSWAP_i32(X) M3_BSWAP_u32(X) 50 | # define M3_BSWAP_i64(X) M3_BSWAP_u64(X) 51 | # define M3_BSWAP_f32(X) { union { f32 f; u32 i; } u; u.f = (X); M3_BSWAP_u32(u.i); (X) = u.f; } 52 | # define M3_BSWAP_f64(X) { union { f64 f; u64 i; } u; u.f = (X); M3_BSWAP_u64(u.i); (X) = u.f; } 53 | # else 54 | # define M3_BSWAP_u8(X) {} 55 | # define M3_BSWAP_u16(x) {} 56 | # define M3_BSWAP_u32(x) {} 57 | # define M3_BSWAP_u64(x) {} 58 | # define M3_BSWAP_i8(X) {} 59 | # define M3_BSWAP_i16(X) {} 60 | # define M3_BSWAP_i32(X) {} 61 | # define M3_BSWAP_i64(X) {} 62 | # define M3_BSWAP_f32(X) {} 63 | # define M3_BSWAP_f64(X) {} 64 | # endif 65 | 66 | # if defined(M3_COMPILER_MSVC) 67 | # define M3_WEAK //__declspec(selectany) 68 | # define M3_NO_UBSAN 69 | # elif defined(__MINGW32__) 70 | # define M3_WEAK //__attribute__((selectany)) 71 | # define M3_NO_UBSAN 72 | # else 73 | # define M3_WEAK __attribute__((weak)) 74 | # define M3_NO_UBSAN //__attribute__((no_sanitize("undefined"))) 75 | # endif 76 | 77 | # ifndef M3_MIN 78 | # define M3_MIN(A,B) (((A) < (B)) ? (A) : (B)) 79 | # endif 80 | # ifndef M3_MAX 81 | # define M3_MAX(A,B) (((A) > (B)) ? (A) : (B)) 82 | # endif 83 | 84 | #define M3_INIT(field) memset(&field, 0, sizeof(field)) 85 | 86 | #define M3_COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) 87 | 88 | #if defined(__AVR__) 89 | 90 | # define PRIu64 "llu" 91 | # define PRIi64 "lli" 92 | 93 | # define d_m3ShortTypesDefined 94 | typedef double f64; 95 | typedef float f32; 96 | typedef uint64_t u64; 97 | typedef int64_t i64; 98 | typedef uint32_t u32; 99 | typedef int32_t i32; 100 | typedef short unsigned u16; 101 | typedef short i16; 102 | typedef uint8_t u8; 103 | typedef int8_t i8; 104 | 105 | #endif 106 | 107 | /* 108 | * Apply settings 109 | */ 110 | 111 | # if defined (M3_COMPILER_MSVC) 112 | # define vectorcall // For MSVC, better not to specify any call convention 113 | # elif defined(__MINGW32__) 114 | # define vectorcall 115 | # elif defined(WIN32) 116 | # define vectorcall __vectorcall 117 | # elif defined (ESP8266) 118 | # include 119 | # define op_section //ICACHE_FLASH_ATTR 120 | # elif defined (ESP32) 121 | # if defined(M3_IN_IRAM) // the interpreter is in IRAM, attribute not needed 122 | # define op_section 123 | # else 124 | # include "esp_system.h" 125 | # define op_section IRAM_ATTR 126 | # endif 127 | # elif defined (FOMU) 128 | # define op_section __attribute__((section(".ramtext"))) 129 | # endif 130 | 131 | #ifndef vectorcall 132 | #define vectorcall 133 | #endif 134 | 135 | #ifndef op_section 136 | #define op_section 137 | #endif 138 | 139 | 140 | /* 141 | * Device-specific defaults 142 | */ 143 | 144 | # ifndef d_m3MaxFunctionStackHeight 145 | # if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AMEBA) || defined(TEENSYDUINO) 146 | # define d_m3MaxFunctionStackHeight 128 147 | # endif 148 | # endif 149 | 150 | # ifndef d_m3FixedHeap 151 | # if defined(ARDUINO_AMEBA) 152 | # define d_m3FixedHeap (128*1024) 153 | # elif defined(BLUE_PILL) || defined(FOMU) 154 | # define d_m3FixedHeap (12*1024) 155 | # elif defined(ARDUINO_ARCH_ARC32) // Arduino 101 156 | # define d_m3FixedHeap (10*1024) 157 | # endif 158 | # endif 159 | 160 | /* 161 | * Platform-specific defaults 162 | */ 163 | 164 | # if defined(ARDUINO) || defined(PARTICLE) || defined(PLATFORMIO) || defined(__MBED__) || \ 165 | defined(ESP8266) || defined(ESP32) || defined(BLUE_PILL) || defined(WM_W600) || defined(FOMU) 166 | # ifndef d_m3VerboseErrorMessages 167 | # define d_m3VerboseErrorMessages 0 168 | # endif 169 | # ifndef d_m3MaxConstantTableSize 170 | # define d_m3MaxConstantTableSize 64 171 | # endif 172 | # ifndef d_m3MaxFunctionStackHeight 173 | # define d_m3MaxFunctionStackHeight 64 174 | # endif 175 | # ifndef d_m3CodePageAlignSize 176 | # define d_m3CodePageAlignSize 1024 177 | # endif 178 | # endif 179 | 180 | /* 181 | * Arch-specific defaults 182 | */ 183 | #if defined(__riscv) && __riscv_xlen == 64 184 | # ifndef d_m3Use32BitSlots 185 | # define d_m3Use32BitSlots 0 186 | # endif 187 | #endif 188 | 189 | #endif // m3_config_platforms_h 190 | -------------------------------------------------------------------------------- /src/m3_core.h: -------------------------------------------------------------------------------- 1 | // 2 | // m3_core.h 3 | // 4 | // Created by Steven Massey on 4/15/19. 5 | // Copyright © 2019 Steven Massey. All rights reserved. 6 | // 7 | 8 | #ifndef m3_core_h 9 | #define m3_core_h 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "wasm3.h" 18 | #include "m3_config.h" 19 | 20 | # if defined(__cplusplus) 21 | # define d_m3BeginExternC extern "C" { 22 | # define d_m3EndExternC } 23 | # else 24 | # define d_m3BeginExternC 25 | # define d_m3EndExternC 26 | # endif 27 | 28 | d_m3BeginExternC 29 | 30 | #define d_m3ImplementFloat (d_m3HasFloat || d_m3NoFloatDynamic) 31 | 32 | #if !defined(d_m3ShortTypesDefined) 33 | 34 | typedef uint64_t u64; 35 | typedef int64_t i64; 36 | typedef uint32_t u32; 37 | typedef int32_t i32; 38 | typedef uint16_t u16; 39 | typedef int16_t i16; 40 | typedef uint8_t u8; 41 | typedef int8_t i8; 42 | 43 | #if d_m3ImplementFloat 44 | typedef double f64; 45 | typedef float f32; 46 | #endif 47 | 48 | #endif // d_m3ShortTypesDefined 49 | 50 | #define PRIf32 "f" 51 | #define PRIf64 "lf" 52 | 53 | typedef const void * m3ret_t; 54 | typedef const void * voidptr_t; 55 | typedef const char * cstr_t; 56 | typedef const char * const ccstr_t; 57 | typedef const u8 * bytes_t; 58 | typedef const u8 * const cbytes_t; 59 | 60 | typedef u16 m3opcode_t; 61 | 62 | typedef i64 m3reg_t; 63 | 64 | # if d_m3Use32BitSlots 65 | typedef u32 m3slot_t; 66 | # else 67 | typedef u64 m3slot_t; 68 | # endif 69 | 70 | typedef m3slot_t * m3stack_t; 71 | 72 | typedef 73 | const void * const cvptr_t; 74 | 75 | # if defined (DEBUG) 76 | 77 | # define d_m3Log(CATEGORY, FMT, ...) printf (" %8s | " FMT, #CATEGORY, ##__VA_ARGS__); 78 | 79 | # if d_m3LogParse 80 | # define m3log_parse(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) 81 | # else 82 | # define m3log_parse(...) {} 83 | # endif 84 | 85 | # if d_m3LogCompile 86 | # define m3log_compile(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) 87 | # else 88 | # define m3log_compile(...) {} 89 | # endif 90 | 91 | # if d_m3LogEmit 92 | # define m3log_emit(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) 93 | # else 94 | # define m3log_emit(...) {} 95 | # endif 96 | 97 | # if d_m3LogCodePages 98 | # define m3log_code(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) 99 | # else 100 | # define m3log_code(...) {} 101 | # endif 102 | 103 | # if d_m3LogModule 104 | # define m3log_module(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) 105 | # else 106 | # define m3log_module(...) {} 107 | # endif 108 | 109 | # if d_m3LogRuntime 110 | # define m3log_runtime(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) 111 | # else 112 | # define m3log_runtime(...) {} 113 | # endif 114 | 115 | # define m3log(CATEGORY, FMT, ...) m3log_##CATEGORY (CATEGORY, FMT "\n", ##__VA_ARGS__) 116 | # else 117 | # define d_m3Log(CATEGORY, FMT, ...) {} 118 | # define m3log(CATEGORY, FMT, ...) {} 119 | # endif 120 | 121 | 122 | # if defined(ASSERTS) || (defined(DEBUG) && !defined(NASSERTS)) 123 | # define d_m3Assert(ASS) if (!(ASS)) { printf("Assertion failed at %s:%d : %s\n", __FILE__, __LINE__, #ASS); abort(); } 124 | # else 125 | # define d_m3Assert(ASS) 126 | # endif 127 | 128 | typedef void /*const*/ * code_t; 129 | typedef code_t const * /*__restrict__*/ pc_t; 130 | 131 | 132 | typedef struct M3MemoryHeader 133 | { 134 | IM3Runtime runtime; 135 | void * maxStack; 136 | size_t length; 137 | } 138 | M3MemoryHeader; 139 | 140 | struct M3CodeMappingPage; 141 | 142 | typedef struct M3CodePageHeader 143 | { 144 | struct M3CodePage * next; 145 | 146 | u32 lineIndex; 147 | u32 numLines; 148 | u32 sequence; // this is just used for debugging; could be removed 149 | u32 usageCount; 150 | 151 | # if d_m3RecordBacktraces 152 | struct M3CodeMappingPage * mapping; 153 | # endif // d_m3RecordBacktraces 154 | } 155 | M3CodePageHeader; 156 | 157 | 158 | #define d_m3CodePageFreeLinesThreshold 4+2 // max is: select _sss & CallIndirect + 2 for bridge 159 | 160 | #define d_m3MemPageSize 65536 161 | 162 | #define d_m3Reg0SlotAlias 60000 163 | #define d_m3Fp0SlotAlias (d_m3Reg0SlotAlias + 2) 164 | 165 | #define d_m3MaxSaneTypesCount 100000 166 | #define d_m3MaxSaneFunctionsCount 100000 167 | #define d_m3MaxSaneImportsCount 10000 168 | #define d_m3MaxSaneExportsCount 10000 169 | #define d_m3MaxSaneGlobalsCount 100000 170 | #define d_m3MaxSaneElementSegments 100000 171 | #define d_m3MaxSaneDataSegments 100000 172 | #define d_m3MaxSaneTableSize 100000 173 | #define d_m3MaxSaneUtf8Length 10000 174 | #define d_m3MaxSaneFunctionArgRetCount 1000 // still insane, but whatever 175 | 176 | #define d_externalKind_function 0 177 | #define d_externalKind_table 1 178 | #define d_externalKind_memory 2 179 | #define d_externalKind_global 3 180 | 181 | static const char * const c_waTypes [] = { "nil", "i32", "i64", "f32", "f64", "unknown" }; 182 | static const char * const c_waCompactTypes [] = { "_", "i", "I", "f", "F", "?" }; 183 | 184 | 185 | # if d_m3VerboseErrorMessages 186 | 187 | M3Result m3Error (M3Result i_result, IM3Runtime i_runtime, IM3Module i_module, IM3Function i_function, 188 | const char * const i_file, u32 i_lineNum, const char * const i_errorMessage, ...); 189 | 190 | # define _m3Error(RESULT, RT, MOD, FUN, FILE, LINE, FORMAT, ...) \ 191 | m3Error (RESULT, RT, MOD, FUN, FILE, LINE, FORMAT, ##__VA_ARGS__) 192 | 193 | # else 194 | # define _m3Error(RESULT, RT, MOD, FUN, FILE, LINE, FORMAT, ...) (RESULT) 195 | # endif 196 | 197 | #define ErrorRuntime(RESULT, RUNTIME, FORMAT, ...) _m3Error (RESULT, RUNTIME, NULL, NULL, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__) 198 | #define ErrorModule(RESULT, MOD, FORMAT, ...) _m3Error (RESULT, MOD->runtime, MOD, NULL, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__) 199 | #define ErrorCompile(RESULT, COMP, FORMAT, ...) _m3Error (RESULT, COMP->runtime, COMP->module, NULL, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__) 200 | 201 | #if d_m3LogNativeStack 202 | void m3StackCheckInit (); 203 | void m3StackCheck (); 204 | int m3StackGetMax (); 205 | #else 206 | #define m3StackCheckInit() 207 | #define m3StackCheck() 208 | #define m3StackGetMax() 0 209 | #endif 210 | 211 | void m3_Abort (const char* message); 212 | void * m3_Malloc (size_t i_size); 213 | void * m3_Realloc (void *i_ptr, size_t i_newSize, size_t i_oldSize); 214 | void m3_FreeImpl (void * i_ptr); 215 | void * m3_CopyMem (const void * i_from, size_t i_size); 216 | 217 | #define m3_AllocStruct(STRUCT) (STRUCT *)m3_Malloc (sizeof (STRUCT)) 218 | #define m3_AllocArray(STRUCT, NUM) (STRUCT *)m3_Malloc (sizeof (STRUCT) * (NUM)) 219 | #define m3_ReallocArray(STRUCT, PTR, NEW, OLD) (STRUCT *)m3_Realloc ((void *)(PTR), sizeof (STRUCT) * (NEW), sizeof (STRUCT) * (OLD)) 220 | #define m3_Free(P) do { m3_FreeImpl ((void*)(P)); (P) = NULL; } while(0) 221 | 222 | M3Result NormalizeType (u8 * o_type, i8 i_convolutedWasmType); 223 | 224 | bool IsIntType (u8 i_wasmType); 225 | bool IsFpType (u8 i_wasmType); 226 | bool Is64BitType (u8 i_m3Type); 227 | u32 SizeOfType (u8 i_m3Type); 228 | 229 | M3Result Read_u64 (u64 * o_value, bytes_t * io_bytes, cbytes_t i_end); 230 | M3Result Read_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end); 231 | #if d_m3ImplementFloat 232 | M3Result Read_f64 (f64 * o_value, bytes_t * io_bytes, cbytes_t i_end); 233 | M3Result Read_f32 (f32 * o_value, bytes_t * io_bytes, cbytes_t i_end); 234 | #endif 235 | M3Result Read_u8 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end); 236 | M3Result Read_opcode (m3opcode_t * o_value, bytes_t * io_bytes, cbytes_t i_end); 237 | 238 | M3Result ReadLebUnsigned (u64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end); 239 | M3Result ReadLebSigned (i64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end); 240 | M3Result ReadLEB_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end); 241 | M3Result ReadLEB_u7 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end); 242 | M3Result ReadLEB_i7 (i8 * o_value, bytes_t * io_bytes, cbytes_t i_end); 243 | M3Result ReadLEB_i32 (i32 * o_value, bytes_t * io_bytes, cbytes_t i_end); 244 | M3Result ReadLEB_i64 (i64 * o_value, bytes_t * io_bytes, cbytes_t i_end); 245 | M3Result Read_utf8 (cstr_t * o_utf8, bytes_t * io_bytes, cbytes_t i_end); 246 | 247 | cstr_t SPrintValue (void * i_value, u8 i_type); 248 | size_t SPrintArg (char * o_string, size_t i_stringBufferSize, voidptr_t i_sp, u8 i_type); 249 | 250 | void ReportError (IM3Runtime io_runtime, IM3Module i_module, IM3Function i_function, ccstr_t i_errorMessage, ccstr_t i_file, u32 i_lineNum); 251 | 252 | # if d_m3RecordBacktraces 253 | void PushBacktraceFrame (IM3Runtime io_runtime, pc_t i_pc); 254 | void FillBacktraceFunctionInfo (IM3Runtime io_runtime, IM3Function i_function); 255 | void ClearBacktrace (IM3Runtime io_runtime); 256 | # endif 257 | 258 | d_m3EndExternC 259 | 260 | #endif // m3_core_h 261 | -------------------------------------------------------------------------------- /src/m3_emit.c: -------------------------------------------------------------------------------- 1 | // 2 | // m3_emit.c 3 | // 4 | // Created by Steven Massey on 7/9/19. 5 | // Copyright © 2019 Steven Massey. All rights reserved. 6 | // 7 | 8 | #include "m3_env.h" 9 | #include "m3_emit.h" 10 | #include "m3_info.h" 11 | #include "m3_exec.h" 12 | 13 | M3Result EnsureCodePageNumLines (IM3Compilation o, u32 i_numLines) 14 | { 15 | M3Result result = m3Err_none; 16 | 17 | i_numLines += 2; // room for Bridge 18 | 19 | if (NumFreeLines (o->page) < i_numLines) 20 | { 21 | IM3CodePage page = AcquireCodePageWithCapacity (o->runtime, i_numLines); 22 | 23 | if (page) 24 | { 25 | m3log (emit, "bridging new code page from: %d %p (free slots: %d) to: %d", o->page->info.sequence, GetPC (o), NumFreeLines (o->page), page->info.sequence); 26 | d_m3Assert (NumFreeLines (o->page) >= 2); 27 | 28 | EmitWord (o->page, op_Branch); 29 | EmitWord (o->page, GetPagePC (page)); 30 | 31 | ReleaseCodePage (o->runtime, o->page); 32 | 33 | o->page = page; 34 | } 35 | else result = m3Err_mallocFailedCodePage; 36 | } 37 | 38 | return result; 39 | } 40 | 41 | 42 | // have execution jump to a new page if slots are critically low 43 | M3Result BridgeToNewPageIfNecessary (IM3Compilation o) 44 | { 45 | return EnsureCodePageNumLines (o, d_m3CodePageFreeLinesThreshold); 46 | } 47 | 48 | 49 | M3Result EmitOp (IM3Compilation o, IM3Operation i_operation) 50 | { 51 | M3Result result = m3Err_none; d_m3Assert (i_operation or IsStackPolymorphic (o)); 52 | 53 | // it's OK for page to be null; when compile-walking the bytecode without emitting 54 | if (o->page) 55 | { 56 | # if d_m3EnableOpTracing 57 | if (i_operation != op_DumpStack) 58 | o->numEmits++; 59 | # endif 60 | 61 | result = BridgeToNewPageIfNecessary (o); 62 | 63 | if (not result) 64 | { if (d_m3LogEmit) log_emit (o, i_operation); 65 | # if d_m3RecordBacktraces 66 | EmitMappingEntry (o->page, o->lastOpcodeStart - o->module->wasmStart); 67 | # endif // d_m3RecordBacktraces 68 | EmitWord (o->page, i_operation); 69 | } 70 | } 71 | 72 | return result; 73 | } 74 | 75 | 76 | // Push an immediate constant into the M3 codestream 77 | void EmitConstant32 (IM3Compilation o, const u32 i_immediate) 78 | { 79 | if (o->page) 80 | EmitWord32 (o->page, i_immediate); 81 | } 82 | 83 | void EmitSlotOffset (IM3Compilation o, const i32 i_offset) 84 | { 85 | if (o->page) 86 | EmitWord32 (o->page, i_offset); 87 | } 88 | 89 | 90 | pc_t EmitPointer (IM3Compilation o, const void * const i_pointer) 91 | { 92 | pc_t ptr = GetPagePC (o->page); 93 | 94 | if (o->page) 95 | EmitWord (o->page, i_pointer); 96 | 97 | return ptr; 98 | } 99 | 100 | void * ReservePointer (IM3Compilation o) 101 | { 102 | pc_t ptr = GetPagePC (o->page); 103 | EmitPointer (o, NULL); 104 | return (void *) ptr; 105 | } 106 | 107 | 108 | pc_t GetPC (IM3Compilation o) 109 | { 110 | return GetPagePC (o->page); 111 | } 112 | -------------------------------------------------------------------------------- /src/m3_emit.h: -------------------------------------------------------------------------------- 1 | // 2 | // m3_emit.h 3 | // 4 | // Created by Steven Massey on 7/9/19. 5 | // Copyright © 2019 Steven Massey. All rights reserved. 6 | // 7 | 8 | #ifndef m3_emit_h 9 | #define m3_emit_h 10 | 11 | #include "m3_compile.h" 12 | 13 | d_m3BeginExternC 14 | 15 | M3Result BridgeToNewPageIfNecessary (IM3Compilation o); 16 | M3Result EnsureCodePageNumLines (IM3Compilation o, u32 i_numLines); 17 | 18 | M3Result EmitOp (IM3Compilation o, IM3Operation i_operation); 19 | void EmitConstant32 (IM3Compilation o, const u32 i_immediate); 20 | void EmitSlotOffset (IM3Compilation o, const i32 i_offset); 21 | pc_t EmitPointer (IM3Compilation o, const void * const i_pointer); 22 | void * ReservePointer (IM3Compilation o); 23 | 24 | pc_t GetPC (IM3Compilation o); 25 | 26 | d_m3EndExternC 27 | 28 | #endif // m3_emit_h 29 | -------------------------------------------------------------------------------- /src/m3_env.h: -------------------------------------------------------------------------------- 1 | // 2 | // m3_env.h 3 | // 4 | // Created by Steven Massey on 4/19/19. 5 | // Copyright © 2019 Steven Massey. All rights reserved. 6 | // 7 | 8 | #ifndef m3_env_h 9 | #define m3_env_h 10 | 11 | #include "wasm3.h" 12 | #include "m3_code.h" 13 | #include "m3_compile.h" 14 | 15 | d_m3BeginExternC 16 | 17 | 18 | //--------------------------------------------------------------------------------------------------------------------------------- 19 | 20 | typedef struct M3MemoryInfo 21 | { 22 | u32 initPages; 23 | u32 maxPages; 24 | } 25 | M3MemoryInfo; 26 | 27 | 28 | typedef struct M3Memory 29 | { 30 | M3MemoryHeader * mallocated; 31 | 32 | u32 numPages; 33 | u32 maxPages; 34 | } 35 | M3Memory; 36 | 37 | typedef M3Memory * IM3Memory; 38 | 39 | 40 | //--------------------------------------------------------------------------------------------------------------------------------- 41 | 42 | typedef struct M3DataSegment 43 | { 44 | const u8 * initExpr; // wasm code 45 | const u8 * data; 46 | 47 | u32 initExprSize; 48 | u32 memoryRegion; 49 | u32 size; 50 | } 51 | M3DataSegment; 52 | 53 | //--------------------------------------------------------------------------------------------------------------------------------- 54 | 55 | typedef struct M3Global 56 | { 57 | M3ImportInfo import; 58 | 59 | union 60 | { 61 | i64 intValue; 62 | #if d_m3HasFloat 63 | f64 f64Value; 64 | f32 f32Value; 65 | #endif 66 | }; 67 | 68 | cstr_t name; 69 | bytes_t initExpr; // wasm code 70 | u32 initExprSize; 71 | u8 type; 72 | bool imported; 73 | bool isMutable; 74 | } 75 | M3Global; 76 | 77 | 78 | //--------------------------------------------------------------------------------------------------------------------------------- 79 | typedef struct M3Module 80 | { 81 | struct M3Runtime * runtime; 82 | struct M3Environment * environment; 83 | 84 | bytes_t wasmStart; 85 | bytes_t wasmEnd; 86 | 87 | cstr_t name; 88 | 89 | u32 numFuncTypes; 90 | IM3FuncType * funcTypes; // array of pointers to list of FuncTypes 91 | 92 | u32 numFuncImports; 93 | u32 numFunctions; 94 | M3Function * functions; 95 | 96 | i32 startFunction; 97 | 98 | u32 numDataSegments; 99 | M3DataSegment * dataSegments; 100 | 101 | //u32 importedGlobals; 102 | u32 numGlobals; 103 | M3Global * globals; 104 | 105 | u32 numElementSegments; 106 | bytes_t elementSection; 107 | bytes_t elementSectionEnd; 108 | 109 | IM3Function * table0; 110 | u32 table0Size; 111 | 112 | M3MemoryInfo memoryInfo; 113 | bool memoryImported; 114 | 115 | //bool hasWasmCodeCopy; 116 | 117 | struct M3Module * next; 118 | } 119 | M3Module; 120 | 121 | M3Result Module_AddGlobal (IM3Module io_module, IM3Global * o_global, u8 i_type, bool i_mutable, bool i_isImported); 122 | 123 | M3Result Module_AddFunction (IM3Module io_module, u32 i_typeIndex, IM3ImportInfo i_importInfo /* can be null */); 124 | IM3Function Module_GetFunction (IM3Module i_module, u32 i_functionIndex); 125 | 126 | void Module_GenerateNames (IM3Module i_module); 127 | 128 | void FreeImportInfo (M3ImportInfo * i_info); 129 | 130 | //--------------------------------------------------------------------------------------------------------------------------------- 131 | 132 | typedef struct M3Environment 133 | { 134 | // struct M3Runtime * runtimes; 135 | 136 | IM3FuncType funcTypes; // linked list of unique M3FuncType structs that can be compared using pointer-equivalence 137 | 138 | IM3FuncType retFuncTypes [c_m3Type_unknown]; // these 'point' to elements in the linked list above. 139 | // the number of elements must match the basic types as per M3ValueType 140 | M3CodePage * pagesReleased; 141 | } 142 | M3Environment; 143 | 144 | void Environment_Release (IM3Environment i_environment); 145 | 146 | // takes ownership of io_funcType and returns a pointer to the persistent version (could be same or different) 147 | void Environment_AddFuncType (IM3Environment i_environment, IM3FuncType * io_funcType); 148 | 149 | //--------------------------------------------------------------------------------------------------------------------------------- 150 | 151 | typedef struct M3Runtime 152 | { 153 | M3Compilation compilation; 154 | 155 | IM3Environment environment; 156 | 157 | M3CodePage * pagesOpen; // linked list of code pages with writable space on them 158 | M3CodePage * pagesFull; // linked list of at-capacity pages 159 | 160 | u32 numCodePages; 161 | u32 numActiveCodePages; 162 | 163 | IM3Module modules; // linked list of imported modules 164 | 165 | void * stack; 166 | u32 stackSize; 167 | u32 numStackSlots; 168 | IM3Function lastCalled; // last function that successfully executed 169 | 170 | void * userdata; 171 | 172 | M3Memory memory; 173 | u32 memoryLimit; 174 | 175 | #if d_m3EnableStrace >= 2 176 | u32 callDepth; 177 | #endif 178 | 179 | M3ErrorInfo error; 180 | #if d_m3VerboseErrorMessages 181 | char error_message[256]; // the actual buffer. M3ErrorInfo can point to this 182 | #endif 183 | 184 | #if d_m3RecordBacktraces 185 | M3BacktraceInfo backtrace; 186 | #endif 187 | } 188 | M3Runtime; 189 | 190 | void InitRuntime (IM3Runtime io_runtime, u32 i_stackSizeInBytes); 191 | void Runtime_Release (IM3Runtime io_runtime); 192 | 193 | M3Result ResizeMemory (IM3Runtime io_runtime, u32 i_numPages); 194 | 195 | typedef void * (* ModuleVisitor) (IM3Module i_module, void * i_info); 196 | void * ForEachModule (IM3Runtime i_runtime, ModuleVisitor i_visitor, void * i_info); 197 | 198 | void * v_FindFunction (IM3Module i_module, const char * const i_name); 199 | 200 | IM3CodePage AcquireCodePage (IM3Runtime io_runtime); 201 | IM3CodePage AcquireCodePageWithCapacity (IM3Runtime io_runtime, u32 i_lineCount); 202 | void ReleaseCodePage (IM3Runtime io_runtime, IM3CodePage i_codePage); 203 | 204 | d_m3EndExternC 205 | 206 | #endif // m3_env_h 207 | -------------------------------------------------------------------------------- /src/m3_exception.h: -------------------------------------------------------------------------------- 1 | // 2 | // m3_exception.h 3 | // 4 | // Created by Steven Massey on 7/5/19. 5 | // Copyright © 2019 Steven Massey. All rights reserved. 6 | // 7 | // some macros to emulate try/catch 8 | 9 | #ifndef m3_exception_h 10 | #define m3_exception_h 11 | 12 | #include "m3_config.h" 13 | 14 | # if d_m3EnableExceptionBreakpoint 15 | 16 | // declared in m3_info.c 17 | void ExceptionBreakpoint (cstr_t i_exception, cstr_t i_message); 18 | 19 | # define EXCEPTION_PRINT(ERROR) ExceptionBreakpoint (ERROR, (__FILE__ ":" M3_STR(__LINE__))) 20 | 21 | # else 22 | # define EXCEPTION_PRINT(...) 23 | # endif 24 | 25 | 26 | #define _try 27 | #define _(TRY) { result = TRY; if (result) { EXCEPTION_PRINT (result); goto _catch; } } 28 | #define _throw(ERROR) { result = ERROR; EXCEPTION_PRINT (result); goto _catch; } 29 | #define _throwif(ERROR, COND) if (UNLIKELY(COND)) \ 30 | { result = ERROR; EXCEPTION_PRINT (result); goto _catch; } 31 | 32 | #define _throwifnull(PTR) _throwif (m3Err_mallocFailed, !(PTR)) 33 | 34 | #endif // m3_exception_h 35 | -------------------------------------------------------------------------------- /src/m3_exec.c: -------------------------------------------------------------------------------- 1 | // 2 | // m3_exec.c 3 | // 4 | // Created by Steven Massey on 4/17/19. 5 | // Copyright © 2019 Steven Massey. All rights reserved. 6 | // 7 | 8 | #include "m3_env.h" 9 | #include "m3_exec.h" 10 | #include "m3_compile.h" 11 | 12 | 13 | # if d_m3EnableOpProfiling 14 | //-------------------------------------------------------------------------------------------------------- 15 | static M3ProfilerSlot s_opProfilerCounts [d_m3ProfilerSlotMask + 1] = {}; 16 | 17 | void ProfileHit (cstr_t i_operationName) 18 | { 19 | u64 ptr = (u64) i_operationName; 20 | 21 | M3ProfilerSlot * slot = & s_opProfilerCounts [ptr & d_m3ProfilerSlotMask]; 22 | 23 | if (slot->opName) 24 | { 25 | if (slot->opName != i_operationName) 26 | { 27 | m3_Abort ("profiler slot collision; increase d_m3ProfilerSlotMask"); 28 | } 29 | } 30 | 31 | slot->opName = i_operationName; 32 | slot->hitCount++; 33 | } 34 | 35 | 36 | void m3_PrintProfilerInfo () 37 | { 38 | M3ProfilerSlot dummy; 39 | M3ProfilerSlot * maxSlot = & dummy; 40 | 41 | do 42 | { 43 | maxSlot->hitCount = 0; 44 | 45 | for (u32 i = 0; i <= d_m3ProfilerSlotMask; ++i) 46 | { 47 | M3ProfilerSlot * slot = & s_opProfilerCounts [i]; 48 | 49 | if (slot->opName) 50 | { 51 | if (slot->hitCount > maxSlot->hitCount) 52 | maxSlot = slot; 53 | } 54 | } 55 | 56 | if (maxSlot->opName) 57 | { 58 | fprintf (stderr, "%13llu %s\n", maxSlot->hitCount, maxSlot->opName); 59 | maxSlot->opName = NULL; 60 | } 61 | } 62 | while (maxSlot->hitCount); 63 | } 64 | 65 | # else 66 | 67 | void m3_PrintProfilerInfo () {} 68 | 69 | # endif 70 | -------------------------------------------------------------------------------- /src/m3_exec_defs.h: -------------------------------------------------------------------------------- 1 | // 2 | // m3_exec_defs.h 3 | // 4 | // Created by Steven Massey on 5/1/19. 5 | // Copyright © 2019 Steven Massey. All rights reserved. 6 | // 7 | 8 | #ifndef m3_exec_defs_h 9 | #define m3_exec_defs_h 10 | 11 | #include "m3_core.h" 12 | 13 | d_m3BeginExternC 14 | 15 | # define m3MemData(mem) (u8*)(((M3MemoryHeader*)(mem))+1) 16 | # define m3MemRuntime(mem) (((M3MemoryHeader*)(mem))->runtime) 17 | # define m3MemInfo(mem) (&(((M3MemoryHeader*)(mem))->runtime->memory)) 18 | 19 | # define d_m3BaseOpSig pc_t _pc, m3stack_t _sp, M3MemoryHeader * _mem, m3reg_t _r0 20 | # define d_m3BaseOpArgs _sp, _mem, _r0 21 | # define d_m3BaseOpAllArgs _pc, _sp, _mem, _r0 22 | # define d_m3BaseOpDefaultArgs 0 23 | # define d_m3BaseClearRegisters _r0 = 0; 24 | 25 | # define d_m3ExpOpSig(...) d_m3BaseOpSig, __VA_ARGS__ 26 | # define d_m3ExpOpArgs(...) d_m3BaseOpArgs, __VA_ARGS__ 27 | # define d_m3ExpOpAllArgs(...) d_m3BaseOpAllArgs, __VA_ARGS__ 28 | # define d_m3ExpOpDefaultArgs(...) d_m3BaseOpDefaultArgs, __VA_ARGS__ 29 | # define d_m3ExpClearRegisters(...) d_m3BaseClearRegisters; __VA_ARGS__ 30 | 31 | # if d_m3HasFloat 32 | # define d_m3OpSig d_m3ExpOpSig (f64 _fp0) 33 | # define d_m3OpArgs d_m3ExpOpArgs (_fp0) 34 | # define d_m3OpAllArgs d_m3ExpOpAllArgs (_fp0) 35 | # define d_m3OpDefaultArgs d_m3ExpOpDefaultArgs (0.) 36 | # define d_m3ClearRegisters d_m3ExpClearRegisters (_fp0 = 0.;) 37 | # else 38 | # define d_m3OpSig d_m3BaseOpSig 39 | # define d_m3OpArgs d_m3BaseOpArgs 40 | # define d_m3OpAllArgs d_m3BaseOpAllArgs 41 | # define d_m3OpDefaultArgs d_m3BaseOpDefaultArgs 42 | # define d_m3ClearRegisters d_m3BaseClearRegisters 43 | # endif 44 | 45 | typedef m3ret_t (vectorcall * IM3Operation) (d_m3OpSig); 46 | 47 | #define d_m3RetSig static inline m3ret_t vectorcall 48 | #define d_m3Op(NAME) M3_NO_UBSAN op_section d_m3RetSig op_##NAME (d_m3OpSig) 49 | 50 | #define nextOpImpl() ((IM3Operation)(* _pc))(_pc + 1, d_m3OpArgs) 51 | #define jumpOpImpl(PC) ((IM3Operation)(* PC))( PC + 1, d_m3OpArgs) 52 | 53 | #define nextOpDirect() return nextOpImpl() 54 | #define jumpOpDirect(PC) return jumpOpImpl((pc_t)(PC)) 55 | 56 | d_m3EndExternC 57 | 58 | #endif // m3_exec_defs_h 59 | -------------------------------------------------------------------------------- /src/m3_function.c: -------------------------------------------------------------------------------- 1 | // 2 | // m3_function.c 3 | // 4 | // Created by Steven Massey on 4/7/21. 5 | // Copyright © 2021 Steven Massey. All rights reserved. 6 | // 7 | 8 | #include "m3_function.h" 9 | #include "m3_env.h" 10 | 11 | 12 | M3Result AllocFuncType (IM3FuncType * o_functionType, u32 i_numTypes) 13 | { 14 | *o_functionType = (IM3FuncType) m3_Malloc (sizeof (M3FuncType) + i_numTypes); 15 | return (*o_functionType) ? m3Err_none : m3Err_mallocFailed; 16 | } 17 | 18 | 19 | bool AreFuncTypesEqual (const IM3FuncType i_typeA, const IM3FuncType i_typeB) 20 | { 21 | if (i_typeA->numRets == i_typeB->numRets && i_typeA->numArgs == i_typeB->numArgs) 22 | { 23 | return (memcmp (i_typeA->types, i_typeB->types, i_typeA->numRets + i_typeA->numArgs) == 0); 24 | } 25 | 26 | return false; 27 | } 28 | 29 | u16 GetFuncTypeNumParams (const IM3FuncType i_funcType) 30 | { 31 | return i_funcType ? i_funcType->numArgs : 0; 32 | } 33 | 34 | 35 | u8 GetFuncTypeParamType (const IM3FuncType i_funcType, u16 i_index) 36 | { 37 | u8 type = c_m3Type_unknown; 38 | 39 | if (i_funcType) 40 | { 41 | if (i_index < i_funcType->numArgs) 42 | { 43 | type = i_funcType->types [i_funcType->numRets + i_index]; 44 | } 45 | } 46 | 47 | return type; 48 | } 49 | 50 | 51 | 52 | u16 GetFuncTypeNumResults (const IM3FuncType i_funcType) 53 | { 54 | return i_funcType ? i_funcType->numRets : 0; 55 | } 56 | 57 | 58 | u8 GetFuncTypeResultType (const IM3FuncType i_funcType, u16 i_index) 59 | { 60 | u8 type = c_m3Type_unknown; 61 | 62 | if (i_funcType) 63 | { 64 | if (i_index < i_funcType->numRets) 65 | { 66 | type = i_funcType->types [i_index]; 67 | } 68 | } 69 | 70 | return type; 71 | } 72 | 73 | 74 | //--------------------------------------------------------------------------------------------------------------- 75 | 76 | 77 | void FreeImportInfo (M3ImportInfo * i_info) 78 | { 79 | m3_Free (i_info->moduleUtf8); 80 | m3_Free (i_info->fieldUtf8); 81 | } 82 | 83 | 84 | void Function_Release (IM3Function i_function) 85 | { 86 | m3_Free (i_function->constants); 87 | 88 | for (int i = 0; i < i_function->numNames; i++) 89 | { 90 | // name can be an alias of fieldUtf8 91 | if (i_function->names[i] != i_function->import.fieldUtf8) 92 | { 93 | m3_Free (i_function->names[i]); 94 | } 95 | } 96 | 97 | FreeImportInfo (& i_function->import); 98 | 99 | if (i_function->ownsWasmCode) 100 | m3_Free (i_function->wasm); 101 | 102 | // Function_FreeCompiledCode (func); 103 | 104 | # if (d_m3EnableCodePageRefCounting) 105 | { 106 | m3_Free (i_function->codePageRefs); 107 | i_function->numCodePageRefs = 0; 108 | } 109 | # endif 110 | } 111 | 112 | 113 | void Function_FreeCompiledCode (IM3Function i_function) 114 | { 115 | # if (d_m3EnableCodePageRefCounting) 116 | { 117 | i_function->compiled = NULL; 118 | 119 | while (i_function->numCodePageRefs--) 120 | { 121 | IM3CodePage page = i_function->codePageRefs [i_function->numCodePageRefs]; 122 | 123 | if (--(page->info.usageCount) == 0) 124 | { 125 | // printf ("free %p\n", page); 126 | } 127 | } 128 | 129 | m3_Free (i_function->codePageRefs); 130 | 131 | Runtime_ReleaseCodePages (i_function->module->runtime); 132 | } 133 | # endif 134 | } 135 | 136 | 137 | cstr_t m3_GetFunctionName (IM3Function i_function) 138 | { 139 | u16 numNames = 0; 140 | cstr_t *names = GetFunctionNames(i_function, &numNames); 141 | if (numNames > 0) 142 | return names[0]; 143 | else 144 | return ""; 145 | } 146 | 147 | 148 | IM3Module m3_GetFunctionModule (IM3Function i_function) 149 | { 150 | return i_function ? i_function->module : NULL; 151 | } 152 | 153 | 154 | cstr_t * GetFunctionNames (IM3Function i_function, u16 * o_numNames) 155 | { 156 | if (!i_function || !o_numNames) 157 | return NULL; 158 | 159 | if (i_function->import.fieldUtf8) 160 | { 161 | *o_numNames = 1; 162 | return &i_function->import.fieldUtf8; 163 | } 164 | else 165 | { 166 | *o_numNames = i_function->numNames; 167 | return i_function->names; 168 | } 169 | } 170 | 171 | 172 | cstr_t GetFunctionImportModuleName (IM3Function i_function) 173 | { 174 | return (i_function->import.moduleUtf8) ? i_function->import.moduleUtf8 : ""; 175 | } 176 | 177 | 178 | u16 GetFunctionNumArgs (IM3Function i_function) 179 | { 180 | u16 numArgs = 0; 181 | 182 | if (i_function) 183 | { 184 | if (i_function->funcType) 185 | numArgs = i_function->funcType->numArgs; 186 | } 187 | 188 | return numArgs; 189 | } 190 | 191 | u8 GetFunctionArgType (IM3Function i_function, u32 i_index) 192 | { 193 | u8 type = c_m3Type_none; 194 | 195 | if (i_index < GetFunctionNumArgs (i_function)) 196 | { 197 | u32 numReturns = i_function->funcType->numRets; 198 | 199 | type = i_function->funcType->types [numReturns + i_index]; 200 | } 201 | 202 | return type; 203 | } 204 | 205 | 206 | u16 GetFunctionNumReturns (IM3Function i_function) 207 | { 208 | u16 numReturns = 0; 209 | 210 | if (i_function) 211 | { 212 | if (i_function->funcType) 213 | numReturns = i_function->funcType->numRets; 214 | } 215 | 216 | return numReturns; 217 | } 218 | 219 | 220 | u8 GetFunctionReturnType (const IM3Function i_function, u16 i_index) 221 | { 222 | return i_function ? GetFuncTypeResultType (i_function->funcType, i_index) : c_m3Type_unknown; 223 | } 224 | 225 | 226 | u32 GetFunctionNumArgsAndLocals (IM3Function i_function) 227 | { 228 | if (i_function) 229 | return i_function->numLocals + GetFunctionNumArgs (i_function); 230 | else 231 | return 0; 232 | } 233 | 234 | -------------------------------------------------------------------------------- /src/m3_function.h: -------------------------------------------------------------------------------- 1 | // 2 | // m3_function.h 3 | // 4 | // Created by Steven Massey on 4/7/21. 5 | // Copyright © 2021 Steven Massey. All rights reserved. 6 | // 7 | 8 | #ifndef m3_function_h 9 | #define m3_function_h 10 | 11 | #include "m3_core.h" 12 | 13 | d_m3BeginExternC 14 | 15 | //--------------------------------------------------------------------------------------------------------------------------------- 16 | 17 | typedef struct M3FuncType 18 | { 19 | struct M3FuncType * next; 20 | 21 | u16 numRets; 22 | u16 numArgs; 23 | u8 types []; // returns, then args 24 | } 25 | M3FuncType; 26 | 27 | typedef M3FuncType * IM3FuncType; 28 | 29 | 30 | M3Result AllocFuncType (IM3FuncType * o_functionType, u32 i_numTypes); 31 | bool AreFuncTypesEqual (const IM3FuncType i_typeA, const IM3FuncType i_typeB); 32 | 33 | u16 GetFuncTypeNumParams (const IM3FuncType i_funcType); 34 | u8 GetFuncTypeParamType (const IM3FuncType i_funcType, u16 i_index); 35 | 36 | u16 GetFuncTypeNumResults (const IM3FuncType i_funcType); 37 | u8 GetFuncTypeResultType (const IM3FuncType i_funcType, u16 i_index); 38 | 39 | //--------------------------------------------------------------------------------------------------------------------------------- 40 | 41 | typedef struct M3Function 42 | { 43 | struct M3Module * module; 44 | 45 | M3ImportInfo import; 46 | 47 | bytes_t wasm; 48 | bytes_t wasmEnd; 49 | 50 | cstr_t names[d_m3MaxDuplicateFunctionImpl]; 51 | u16 numNames; // maximum of d_m3MaxDuplicateFunctionImpl 52 | 53 | IM3FuncType funcType; 54 | 55 | pc_t compiled; 56 | 57 | # if (d_m3EnableCodePageRefCounting) 58 | IM3CodePage * codePageRefs; // array of all pages used 59 | u32 numCodePageRefs; 60 | # endif 61 | 62 | # if defined (DEBUG) 63 | u32 hits; 64 | u32 index; 65 | # endif 66 | 67 | u16 maxStackSlots; 68 | 69 | u16 numRetSlots; 70 | u16 numRetAndArgSlots; 71 | 72 | u16 numLocals; // not including args 73 | u16 numLocalBytes; 74 | 75 | bool ownsWasmCode; 76 | 77 | u16 numConstantBytes; 78 | void * constants; 79 | } 80 | M3Function; 81 | 82 | void Function_Release (IM3Function i_function); 83 | void Function_FreeCompiledCode (IM3Function i_function); 84 | 85 | cstr_t GetFunctionImportModuleName (IM3Function i_function); 86 | cstr_t * GetFunctionNames (IM3Function i_function, u16 * o_numNames); 87 | u16 GetFunctionNumArgs (IM3Function i_function); 88 | u8 GetFunctionArgType (IM3Function i_function, u32 i_index); 89 | 90 | u16 GetFunctionNumReturns (IM3Function i_function); 91 | u8 GetFunctionReturnType (const IM3Function i_function, u16 i_index); 92 | 93 | u32 GetFunctionNumArgsAndLocals (IM3Function i_function); 94 | 95 | cstr_t SPrintFunctionArgList (IM3Function i_function, m3stack_t i_sp); 96 | 97 | //--------------------------------------------------------------------------------------------------------------------------------- 98 | 99 | 100 | d_m3EndExternC 101 | 102 | #endif /* m3_function_h */ 103 | -------------------------------------------------------------------------------- /src/m3_info.h: -------------------------------------------------------------------------------- 1 | // 2 | // m3_info.h 3 | // 4 | // Created by Steven Massey on 12/6/19. 5 | // Copyright © 2019 Steven Massey. All rights reserved. 6 | // 7 | 8 | #ifndef m3_info_h 9 | #define m3_info_h 10 | 11 | #include "m3_compile.h" 12 | 13 | d_m3BeginExternC 14 | 15 | #ifdef DEBUG 16 | 17 | void dump_type_stack (IM3Compilation o); 18 | void log_opcode (IM3Compilation o, m3opcode_t i_opcode); 19 | const char * get_indention_string (IM3Compilation o); 20 | void emit_stack_dump (IM3Compilation o); 21 | void log_emit (IM3Compilation o, IM3Operation i_operation); 22 | 23 | cstr_t SPrintFuncTypeSignature (IM3FuncType i_funcType); 24 | 25 | #else // DEBUG 26 | 27 | #define dump_type_stack(...) {} 28 | #define log_opcode(...) {} 29 | #define get_indention_string(...) "" 30 | #define emit_stack_dump(...) {} 31 | #define log_emit(...) {} 32 | 33 | #endif // DEBUG 34 | 35 | d_m3EndExternC 36 | 37 | #endif // m3_info_h 38 | -------------------------------------------------------------------------------- /src/m3_math_utils.h: -------------------------------------------------------------------------------- 1 | // 2 | // m3_math_utils.h 3 | // 4 | // Created by Volodymyr Shymanksyy on 8/10/19. 5 | // Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. 6 | // 7 | 8 | #ifndef m3_math_utils_h 9 | #define m3_math_utils_h 10 | 11 | #include "m3_core.h" 12 | 13 | #include 14 | 15 | #if defined(M3_COMPILER_MSVC) 16 | 17 | #include 18 | 19 | #define __builtin_popcount __popcnt 20 | 21 | static inline 22 | int __builtin_ctz(uint32_t x) { 23 | unsigned long ret; 24 | _BitScanForward(&ret, x); 25 | return (int)ret; 26 | } 27 | 28 | static inline 29 | int __builtin_clz(uint32_t x) { 30 | unsigned long ret; 31 | _BitScanReverse(&ret, x); 32 | return (int)(31 ^ ret); 33 | } 34 | 35 | 36 | 37 | #ifdef _WIN64 38 | 39 | #define __builtin_popcountll __popcnt64 40 | 41 | static inline 42 | int __builtin_ctzll(uint64_t value) { 43 | unsigned long ret; 44 | _BitScanForward64(&ret, value); 45 | return (int)ret; 46 | } 47 | 48 | static inline 49 | int __builtin_clzll(uint64_t value) { 50 | unsigned long ret; 51 | _BitScanReverse64(&ret, value); 52 | return (int)(63 ^ ret); 53 | } 54 | 55 | #else // _WIN64 56 | 57 | #define __builtin_popcountll(x) (__popcnt((x) & 0xFFFFFFFF) + __popcnt((x) >> 32)) 58 | 59 | static inline 60 | int __builtin_ctzll(uint64_t value) { 61 | //if (value == 0) return 64; // Note: ctz(0) result is undefined anyway 62 | uint32_t msh = (uint32_t)(value >> 32); 63 | uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF); 64 | if (lsh != 0) return __builtin_ctz(lsh); 65 | return 32 + __builtin_ctz(msh); 66 | } 67 | 68 | static inline 69 | int __builtin_clzll(uint64_t value) { 70 | //if (value == 0) return 64; // Note: clz(0) result is undefined anyway 71 | uint32_t msh = (uint32_t)(value >> 32); 72 | uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF); 73 | if (msh != 0) return __builtin_clz(msh); 74 | return 32 + __builtin_clz(lsh); 75 | } 76 | 77 | #endif // _WIN64 78 | 79 | #endif // defined(M3_COMPILER_MSVC) 80 | 81 | 82 | // TODO: not sure why, signbit is actually defined in math.h 83 | #if (defined(ESP8266) || defined(ESP32)) && !defined(signbit) 84 | #define signbit(__x) \ 85 | ((sizeof(__x) == sizeof(float)) ? __signbitf(__x) : __signbitd(__x)) 86 | #endif 87 | 88 | #if defined(__AVR__) 89 | 90 | static inline 91 | float rintf( float arg ) { 92 | union { float f; uint32_t i; } u; 93 | u.f = arg; 94 | uint32_t ux = u.i & 0x7FFFFFFF; 95 | if (UNLIKELY(ux == 0 || ux > 0x5A000000)) { 96 | return arg; 97 | } 98 | return (float)lrint(arg); 99 | } 100 | 101 | static inline 102 | double rint( double arg ) { 103 | union { double f; uint32_t i[2]; } u; 104 | u.f = arg; 105 | uint32_t ux = u.i[1] & 0x7FFFFFFF; 106 | if (UNLIKELY((ux == 0 && u.i[0] == 0) || ux > 0x433FFFFF)) { 107 | return arg; 108 | } 109 | return (double)lrint(arg); 110 | } 111 | 112 | //TODO 113 | static inline 114 | uint64_t strtoull(const char* str, char** endptr, int base) { 115 | return 0; 116 | } 117 | 118 | #endif 119 | 120 | /* 121 | * Rotr, Rotl 122 | */ 123 | 124 | static inline 125 | u32 rotl32(u32 n, unsigned c) { 126 | const unsigned mask = CHAR_BIT * sizeof(n) - 1; 127 | c &= mask & 31; 128 | return (n << c) | (n >> ((-c) & mask)); 129 | } 130 | 131 | static inline 132 | u32 rotr32(u32 n, unsigned c) { 133 | const unsigned mask = CHAR_BIT * sizeof(n) - 1; 134 | c &= mask & 31; 135 | return (n >> c) | (n << ((-c) & mask)); 136 | } 137 | 138 | static inline 139 | u64 rotl64(u64 n, unsigned c) { 140 | const unsigned mask = CHAR_BIT * sizeof(n) - 1; 141 | c &= mask & 63; 142 | return (n << c) | (n >> ((-c) & mask)); 143 | } 144 | 145 | static inline 146 | u64 rotr64(u64 n, unsigned c) { 147 | const unsigned mask = CHAR_BIT * sizeof(n) - 1; 148 | c &= mask & 63; 149 | return (n >> c) | (n << ((-c) & mask)); 150 | } 151 | 152 | /* 153 | * Integer Div, Rem 154 | */ 155 | 156 | #define OP_DIV_U(RES, A, B) \ 157 | if (UNLIKELY(B == 0)) newTrap (m3Err_trapDivisionByZero); \ 158 | RES = A / B; 159 | 160 | #define OP_REM_U(RES, A, B) \ 161 | if (UNLIKELY(B == 0)) newTrap (m3Err_trapDivisionByZero); \ 162 | RES = A % B; 163 | 164 | // 2's complement detection 165 | #if (INT_MIN != -INT_MAX) 166 | 167 | #define OP_DIV_S(RES, A, B, TYPE_MIN) \ 168 | if (UNLIKELY(B == 0)) newTrap (m3Err_trapDivisionByZero); \ 169 | if (UNLIKELY(B == -1 and A == TYPE_MIN)) { \ 170 | newTrap (m3Err_trapIntegerOverflow); \ 171 | } \ 172 | RES = A / B; 173 | 174 | #define OP_REM_S(RES, A, B, TYPE_MIN) \ 175 | if (UNLIKELY(B == 0)) newTrap (m3Err_trapDivisionByZero); \ 176 | if (UNLIKELY(B == -1 and A == TYPE_MIN)) RES = 0; \ 177 | else RES = A % B; 178 | 179 | #else 180 | 181 | #define OP_DIV_S(RES, A, B, TYPE_MIN) OP_DIV_U(RES, A, B) 182 | #define OP_REM_S(RES, A, B, TYPE_MIN) OP_REM_U(RES, A, B) 183 | 184 | #endif 185 | 186 | /* 187 | * Trunc 188 | */ 189 | 190 | #define OP_TRUNC(RES, A, TYPE, RMIN, RMAX) \ 191 | if (UNLIKELY(isnan(A))) { \ 192 | newTrap (m3Err_trapIntegerConversion); \ 193 | } \ 194 | if (UNLIKELY(A <= RMIN or A >= RMAX)) { \ 195 | newTrap (m3Err_trapIntegerOverflow); \ 196 | } \ 197 | RES = (TYPE)A; 198 | 199 | 200 | #define OP_I32_TRUNC_F32(RES, A) OP_TRUNC(RES, A, i32, -2147483904.0f, 2147483648.0f) 201 | #define OP_U32_TRUNC_F32(RES, A) OP_TRUNC(RES, A, u32, -1.0f, 4294967296.0f) 202 | #define OP_I32_TRUNC_F64(RES, A) OP_TRUNC(RES, A, i32, -2147483649.0 , 2147483648.0 ) 203 | #define OP_U32_TRUNC_F64(RES, A) OP_TRUNC(RES, A, u32, -1.0 , 4294967296.0 ) 204 | 205 | #define OP_I64_TRUNC_F32(RES, A) OP_TRUNC(RES, A, i64, -9223373136366403584.0f, 9223372036854775808.0f) 206 | #define OP_U64_TRUNC_F32(RES, A) OP_TRUNC(RES, A, u64, -1.0f, 18446744073709551616.0f) 207 | #define OP_I64_TRUNC_F64(RES, A) OP_TRUNC(RES, A, i64, -9223372036854777856.0 , 9223372036854775808.0 ) 208 | #define OP_U64_TRUNC_F64(RES, A) OP_TRUNC(RES, A, u64, -1.0 , 18446744073709551616.0 ) 209 | 210 | #define OP_TRUNC_SAT(RES, A, TYPE, RMIN, RMAX, IMIN, IMAX) \ 211 | if (UNLIKELY(isnan(A))) { \ 212 | RES = 0; \ 213 | } else if (UNLIKELY(A <= RMIN)) { \ 214 | RES = IMIN; \ 215 | } else if (UNLIKELY(A >= RMAX)) { \ 216 | RES = IMAX; \ 217 | } else { \ 218 | RES = (TYPE)A; \ 219 | } 220 | 221 | #define OP_I32_TRUNC_SAT_F32(RES, A) OP_TRUNC_SAT(RES, A, i32, -2147483904.0f, 2147483648.0f, INT32_MIN, INT32_MAX) 222 | #define OP_U32_TRUNC_SAT_F32(RES, A) OP_TRUNC_SAT(RES, A, u32, -1.0f, 4294967296.0f, 0UL, UINT32_MAX) 223 | #define OP_I32_TRUNC_SAT_F64(RES, A) OP_TRUNC_SAT(RES, A, i32, -2147483649.0 , 2147483648.0, INT32_MIN, INT32_MAX) 224 | #define OP_U32_TRUNC_SAT_F64(RES, A) OP_TRUNC_SAT(RES, A, u32, -1.0 , 4294967296.0, 0UL, UINT32_MAX) 225 | 226 | #define OP_I64_TRUNC_SAT_F32(RES, A) OP_TRUNC_SAT(RES, A, i64, -9223373136366403584.0f, 9223372036854775808.0f, INT64_MIN, INT64_MAX) 227 | #define OP_U64_TRUNC_SAT_F32(RES, A) OP_TRUNC_SAT(RES, A, u64, -1.0f, 18446744073709551616.0f, 0ULL, UINT64_MAX) 228 | #define OP_I64_TRUNC_SAT_F64(RES, A) OP_TRUNC_SAT(RES, A, i64, -9223372036854777856.0 , 9223372036854775808.0, INT64_MIN, INT64_MAX) 229 | #define OP_U64_TRUNC_SAT_F64(RES, A) OP_TRUNC_SAT(RES, A, u64, -1.0 , 18446744073709551616.0, 0ULL, UINT64_MAX) 230 | 231 | /* 232 | * Min, Max 233 | */ 234 | 235 | #if d_m3HasFloat 236 | 237 | #include 238 | 239 | static inline 240 | f32 min_f32(f32 a, f32 b) { 241 | if (UNLIKELY(isnan(a) or isnan(b))) return NAN; 242 | if (UNLIKELY(a == 0 and a == b)) return signbit(a) ? a : b; 243 | return a > b ? b : a; 244 | } 245 | 246 | static inline 247 | f32 max_f32(f32 a, f32 b) { 248 | if (UNLIKELY(isnan(a) or isnan(b))) return NAN; 249 | if (UNLIKELY(a == 0 and a == b)) return signbit(a) ? b : a; 250 | return a > b ? a : b; 251 | } 252 | 253 | static inline 254 | f64 min_f64(f64 a, f64 b) { 255 | if (UNLIKELY(isnan(a) or isnan(b))) return NAN; 256 | if (UNLIKELY(a == 0 and a == b)) return signbit(a) ? a : b; 257 | return a > b ? b : a; 258 | } 259 | 260 | static inline 261 | f64 max_f64(f64 a, f64 b) { 262 | if (UNLIKELY(isnan(a) or isnan(b))) return NAN; 263 | if (UNLIKELY(a == 0 and a == b)) return signbit(a) ? b : a; 264 | return a > b ? a : b; 265 | } 266 | #endif 267 | 268 | #endif // m3_math_utils_h 269 | -------------------------------------------------------------------------------- /src/m3_module.c: -------------------------------------------------------------------------------- 1 | // 2 | // m3_module.c 3 | // 4 | // Created by Steven Massey on 5/7/19. 5 | // Copyright © 2019 Steven Massey. All rights reserved. 6 | // 7 | 8 | #include "m3_env.h" 9 | #include "m3_exception.h" 10 | 11 | 12 | void Module_FreeFunctions (IM3Module i_module) 13 | { 14 | for (u32 i = 0; i < i_module->numFunctions; ++i) 15 | { 16 | IM3Function func = & i_module->functions [i]; 17 | Function_Release (func); 18 | } 19 | } 20 | 21 | 22 | void m3_FreeModule (IM3Module i_module) 23 | { 24 | if (i_module) 25 | { 26 | m3log (module, "freeing module: %s (funcs: %d; segments: %d)", 27 | i_module->name, i_module->numFunctions, i_module->numDataSegments); 28 | 29 | Module_FreeFunctions (i_module); 30 | 31 | m3_Free (i_module->functions); 32 | //m3_Free (i_module->imports); 33 | m3_Free (i_module->funcTypes); 34 | m3_Free (i_module->dataSegments); 35 | m3_Free (i_module->table0); 36 | 37 | for (u32 i = 0; i < i_module->numGlobals; ++i) 38 | { 39 | m3_Free (i_module->globals[i].name); 40 | FreeImportInfo(&(i_module->globals[i].import)); 41 | } 42 | m3_Free (i_module->globals); 43 | 44 | m3_Free (i_module); 45 | } 46 | } 47 | 48 | 49 | M3Result Module_AddGlobal (IM3Module io_module, IM3Global * o_global, u8 i_type, bool i_mutable, bool i_isImported) 50 | { 51 | M3Result result = m3Err_none; 52 | _try { 53 | u32 index = io_module->numGlobals++; 54 | io_module->globals = m3_ReallocArray (M3Global, io_module->globals, io_module->numGlobals, index); 55 | _throwifnull(io_module->globals); 56 | M3Global * global = & io_module->globals [index]; 57 | 58 | global->type = i_type; 59 | global->imported = i_isImported; 60 | global->isMutable = i_mutable; 61 | 62 | if (o_global) 63 | * o_global = global; 64 | 65 | } _catch: 66 | return result; 67 | } 68 | 69 | 70 | M3Result Module_AddFunction (IM3Module io_module, u32 i_typeIndex, IM3ImportInfo i_importInfo) 71 | { 72 | M3Result result = m3Err_none; 73 | 74 | _try { 75 | 76 | u32 index = io_module->numFunctions++; 77 | io_module->functions = m3_ReallocArray (M3Function, io_module->functions, io_module->numFunctions, index); 78 | 79 | _throwifnull (io_module->functions); 80 | _throwif ("type sig index out of bounds", i_typeIndex >= io_module->numFuncTypes); 81 | 82 | IM3FuncType ft = io_module->funcTypes [i_typeIndex]; 83 | 84 | IM3Function func = Module_GetFunction (io_module, index); 85 | func->funcType = ft; 86 | 87 | # ifdef DEBUG 88 | func->index = index; 89 | # endif 90 | 91 | if (i_importInfo and func->numNames == 0) 92 | { 93 | func->import = * i_importInfo; 94 | func->names[0] = i_importInfo->fieldUtf8; 95 | func->numNames = 1; 96 | } 97 | 98 | m3log (module, " added function: %3d; sig: %d", index, i_typeIndex); 99 | 100 | } _catch: 101 | return result; 102 | } 103 | 104 | #ifdef DEBUG 105 | void Module_GenerateNames (IM3Module i_module) 106 | { 107 | for (u32 i = 0; i < i_module->numFunctions; ++i) 108 | { 109 | IM3Function func = & i_module->functions [i]; 110 | 111 | if (func->numNames == 0) 112 | { 113 | char* buff = m3_AllocArray(char, 16); 114 | snprintf(buff, 16, "$func%d", i); 115 | func->names[0] = buff; 116 | func->numNames = 1; 117 | } 118 | } 119 | for (u32 i = 0; i < i_module->numGlobals; ++i) 120 | { 121 | IM3Global global = & i_module->globals [i]; 122 | 123 | if (global->name == NULL) 124 | { 125 | char* buff = m3_AllocArray(char, 16); 126 | snprintf(buff, 16, "$global%d", i); 127 | global->name = buff; 128 | } 129 | } 130 | } 131 | #endif 132 | 133 | IM3Function Module_GetFunction (IM3Module i_module, u32 i_functionIndex) 134 | { 135 | IM3Function func = NULL; 136 | 137 | if (i_functionIndex < i_module->numFunctions) 138 | { 139 | func = & i_module->functions [i_functionIndex]; 140 | //func->module = i_module; 141 | } 142 | 143 | return func; 144 | } 145 | 146 | 147 | const char* m3_GetModuleName (IM3Module i_module) 148 | { 149 | if (!i_module || !i_module->name) 150 | return ".unnamed"; 151 | 152 | return i_module->name; 153 | } 154 | 155 | void m3_SetModuleName (IM3Module i_module, const char* name) 156 | { 157 | if (i_module) i_module->name = name; 158 | } 159 | 160 | IM3Runtime m3_GetModuleRuntime (IM3Module i_module) 161 | { 162 | return i_module ? i_module->runtime : NULL; 163 | } 164 | 165 | -------------------------------------------------------------------------------- /src/wasm3_defs.h: -------------------------------------------------------------------------------- 1 | // 2 | // wasm3_defs.h 3 | // 4 | // Created by Volodymyr Shymanskyy on 11/20/19. 5 | // Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. 6 | // 7 | 8 | #ifndef wasm3_defs_h 9 | #define wasm3_defs_h 10 | 11 | #define M3_STR__(x) #x 12 | #define M3_STR(x) M3_STR__(x) 13 | 14 | #define M3_CONCAT__(a,b) a##b 15 | #define M3_CONCAT(a,b) M3_CONCAT__(a,b) 16 | 17 | /* 18 | * Detect compiler 19 | */ 20 | 21 | # if defined(__clang__) 22 | # define M3_COMPILER_CLANG 1 23 | # elif defined(__INTEL_COMPILER) 24 | # define M3_COMPILER_ICC 1 25 | # elif defined(__GNUC__) || defined(__GNUG__) 26 | # define M3_COMPILER_GCC 1 27 | # elif defined(_MSC_VER) 28 | # define M3_COMPILER_MSVC 1 29 | # else 30 | # warning "Compiler not detected" 31 | # endif 32 | 33 | # if defined(M3_COMPILER_CLANG) 34 | # if defined(WIN32) 35 | # define M3_COMPILER_VER __VERSION__ " for Windows" 36 | # else 37 | # define M3_COMPILER_VER __VERSION__ 38 | # endif 39 | # elif defined(M3_COMPILER_GCC) 40 | # define M3_COMPILER_VER "GCC " __VERSION__ 41 | # elif defined(M3_COMPILER_MSVC) 42 | # define M3_COMPILER_VER "MSVC " M3_STR(_MSC_VER) 43 | # else 44 | # define M3_COMPILER_VER "unknown" 45 | # endif 46 | 47 | # ifdef __has_feature 48 | # define M3_COMPILER_HAS_FEATURE(x) __has_feature(x) 49 | # else 50 | # define M3_COMPILER_HAS_FEATURE(x) 0 51 | # endif 52 | 53 | # ifdef __has_builtin 54 | # define M3_COMPILER_HAS_BUILTIN(x) __has_builtin(x) 55 | # else 56 | # define M3_COMPILER_HAS_BUILTIN(x) 0 57 | # endif 58 | 59 | /* 60 | * Detect endianness 61 | */ 62 | 63 | # if defined(M3_COMPILER_MSVC) 64 | # define M3_LITTLE_ENDIAN //_byteswap_ushort, _byteswap_ulong, _byteswap_uint64 65 | # elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 66 | # define M3_LITTLE_ENDIAN 67 | # elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 68 | # define M3_BIG_ENDIAN 69 | # else 70 | # error "Byte order not detected" 71 | # endif 72 | 73 | /* 74 | * Detect platform 75 | */ 76 | 77 | # if defined(M3_COMPILER_CLANG) || defined(M3_COMPILER_GCC) 78 | # if defined(__wasm__) 79 | # define M3_ARCH "wasm" 80 | 81 | # elif defined(__x86_64__) 82 | # define M3_ARCH "x86_64" 83 | 84 | # elif defined(__i386__) 85 | # define M3_ARCH "i386" 86 | 87 | # elif defined(__aarch64__) 88 | # define M3_ARCH "arm64-v8a" 89 | 90 | # elif defined(__arm__) 91 | # if defined(__ARM_ARCH_7A__) 92 | # if defined(__ARM_NEON__) 93 | # if defined(__ARM_PCS_VFP) 94 | # define M3_ARCH "arm-v7a/NEON hard-float" 95 | # else 96 | # define M3_ARCH "arm-v7a/NEON" 97 | # endif 98 | # else 99 | # if defined(__ARM_PCS_VFP) 100 | # define M3_ARCH "arm-v7a hard-float" 101 | # else 102 | # define M3_ARCH "arm-v7a" 103 | # endif 104 | # endif 105 | # else 106 | # define M3_ARCH "arm" 107 | # endif 108 | 109 | # elif defined(__riscv) 110 | # if defined(__riscv_32e) 111 | # define _M3_ARCH_RV "rv32e" 112 | # elif __riscv_xlen == 128 113 | # define _M3_ARCH_RV "rv128i" 114 | # elif __riscv_xlen == 64 115 | # define _M3_ARCH_RV "rv64i" 116 | # elif __riscv_xlen == 32 117 | # define _M3_ARCH_RV "rv32i" 118 | # endif 119 | # if defined(__riscv_muldiv) 120 | # define _M3_ARCH_RV_M _M3_ARCH_RV "m" 121 | # else 122 | # define _M3_ARCH_RV_M _M3_ARCH_RV 123 | # endif 124 | # if defined(__riscv_atomic) 125 | # define _M3_ARCH_RV_A _M3_ARCH_RV_M "a" 126 | # else 127 | # define _M3_ARCH_RV_A _M3_ARCH_RV_M 128 | # endif 129 | # if defined(__riscv_flen) 130 | # define _M3_ARCH_RV_F _M3_ARCH_RV_A "f" 131 | # else 132 | # define _M3_ARCH_RV_F _M3_ARCH_RV_A 133 | # endif 134 | # if defined(__riscv_flen) && __riscv_flen >= 64 135 | # define _M3_ARCH_RV_D _M3_ARCH_RV_F "d" 136 | # else 137 | # define _M3_ARCH_RV_D _M3_ARCH_RV_F 138 | # endif 139 | # if defined(__riscv_compressed) 140 | # define _M3_ARCH_RV_C _M3_ARCH_RV_D "c" 141 | # else 142 | # define _M3_ARCH_RV_C _M3_ARCH_RV_D 143 | # endif 144 | # define M3_ARCH _M3_ARCH_RV_C 145 | 146 | # elif defined(__mips__) 147 | # if defined(__MIPSEB__) && defined(__mips64) 148 | # define M3_ARCH "mips64 " _MIPS_ARCH 149 | # elif defined(__MIPSEL__) && defined(__mips64) 150 | # define M3_ARCH "mips64el " _MIPS_ARCH 151 | # elif defined(__MIPSEB__) 152 | # define M3_ARCH "mips " _MIPS_ARCH 153 | # elif defined(__MIPSEL__) 154 | # define M3_ARCH "mipsel " _MIPS_ARCH 155 | # endif 156 | 157 | # elif defined(__PPC__) 158 | # if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) 159 | # define M3_ARCH "ppc64le" 160 | # elif defined(__PPC64__) 161 | # define M3_ARCH "ppc64" 162 | # else 163 | # define M3_ARCH "ppc" 164 | # endif 165 | 166 | # elif defined(__sparc__) 167 | # if defined(__arch64__) 168 | # define M3_ARCH "sparc64" 169 | # else 170 | # define M3_ARCH "sparc" 171 | # endif 172 | 173 | # elif defined(__s390x__) 174 | # define M3_ARCH "s390x" 175 | 176 | # elif defined(__alpha__) 177 | # define M3_ARCH "alpha" 178 | 179 | # elif defined(__m68k__) 180 | # define M3_ARCH "m68k" 181 | 182 | # elif defined(__xtensa__) 183 | # define M3_ARCH "xtensa" 184 | 185 | # elif defined(__arc__) 186 | # define M3_ARCH "arc32" 187 | 188 | # elif defined(__AVR__) 189 | # define M3_ARCH "avr" 190 | # endif 191 | # endif 192 | 193 | # if defined(M3_COMPILER_MSVC) 194 | # if defined(_M_X64) 195 | # define M3_ARCH "x86_64" 196 | # elif defined(_M_IX86) 197 | # define M3_ARCH "i386" 198 | # elif defined(_M_ARM64) 199 | # define M3_ARCH "arm64" 200 | # elif defined(_M_ARM) 201 | # define M3_ARCH "arm" 202 | # endif 203 | # endif 204 | 205 | # if !defined(M3_ARCH) 206 | # warning "Architecture not detected" 207 | # define M3_ARCH "unknown" 208 | # endif 209 | 210 | /* 211 | * Byte swapping (for Big-Endian systems only) 212 | */ 213 | 214 | # if defined(M3_COMPILER_MSVC) 215 | # define m3_bswap16(x) _byteswap_ushort((x)) 216 | # define m3_bswap32(x) _byteswap_ulong((x)) 217 | # define m3_bswap64(x) _byteswap_uint64((x)) 218 | # elif defined(M3_COMPILER_GCC) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) 219 | // __builtin_bswap32/64 added in gcc 4.3, __builtin_bswap16 added in gcc 4.8 220 | # define m3_bswap16(x) __builtin_bswap16((x)) 221 | # define m3_bswap32(x) __builtin_bswap32((x)) 222 | # define m3_bswap64(x) __builtin_bswap64((x)) 223 | # elif defined(M3_COMPILER_CLANG) && M3_COMPILER_HAS_BUILTIN(__builtin_bswap16) 224 | # define m3_bswap16(x) __builtin_bswap16((x)) 225 | # define m3_bswap32(x) __builtin_bswap32((x)) 226 | # define m3_bswap64(x) __builtin_bswap64((x)) 227 | # else 228 | # include 229 | # if defined(__bswap_16) 230 | # define m3_bswap16(x) __bswap_16((x)) 231 | # define m3_bswap32(x) __bswap_32((x)) 232 | # define m3_bswap64(x) __bswap_64((x)) 233 | # else 234 | # warning "Using naive (probably slow) bswap operations" 235 | static inline 236 | uint16_t m3_bswap16(uint16_t x) { 237 | return ((( x >> 8 ) & 0xffu ) | (( x & 0xffu ) << 8 )); 238 | } 239 | static inline 240 | uint32_t m3_bswap32(uint32_t x) { 241 | return ((( x & 0xff000000u ) >> 24 ) | 242 | (( x & 0x00ff0000u ) >> 8 ) | 243 | (( x & 0x0000ff00u ) << 8 ) | 244 | (( x & 0x000000ffu ) << 24 )); 245 | } 246 | static inline 247 | uint64_t m3_bswap64(uint64_t x) { 248 | return ((( x & 0xff00000000000000ull ) >> 56 ) | 249 | (( x & 0x00ff000000000000ull ) >> 40 ) | 250 | (( x & 0x0000ff0000000000ull ) >> 24 ) | 251 | (( x & 0x000000ff00000000ull ) >> 8 ) | 252 | (( x & 0x00000000ff000000ull ) << 8 ) | 253 | (( x & 0x0000000000ff0000ull ) << 24 ) | 254 | (( x & 0x000000000000ff00ull ) << 40 ) | 255 | (( x & 0x00000000000000ffull ) << 56 )); 256 | } 257 | # endif 258 | # endif 259 | 260 | /* 261 | * Other 262 | */ 263 | 264 | # if defined(M3_COMPILER_GCC) || defined(M3_COMPILER_CLANG) || defined(M3_COMPILER_ICC) 265 | # define M3_UNLIKELY(x) __builtin_expect(!!(x), 0) 266 | # define M3_LIKELY(x) __builtin_expect(!!(x), 1) 267 | # else 268 | # define M3_UNLIKELY(x) (x) 269 | # define M3_LIKELY(x) (x) 270 | # endif 271 | 272 | // TODO: remove 273 | # if defined(M3_COMPILER_GCC) || defined(M3_COMPILER_CLANG) || defined(M3_COMPILER_ICC) 274 | # define UNLIKELY(x) __builtin_expect(!!(x), 0) 275 | # define LIKELY(x) __builtin_expect(!!(x), 1) 276 | # else 277 | # define UNLIKELY(x) (x) 278 | # define LIKELY(x) (x) 279 | # endif 280 | 281 | 282 | #endif // wasm3_defs_h 283 | -------------------------------------------------------------------------------- /verification.txt: -------------------------------------------------------------------------------- 1 | 2 | === VERIFICATION HOWTO === 3 | 4 | 1. Open Wasm_Blink example 5 | 2. Adjust LED_PIN if needed 6 | 3. Upload it to the board 7 | 4. The specified LED should blink 8 | -------------------------------------------------------------------------------- /wasm_apps/README.md: -------------------------------------------------------------------------------- 1 | ## WebAssembly example apps 2 | 3 | ## C++ app 4 | 5 | `./wasm_cpp` directory contains an example Arduino app (sketch) that is compiled to WebAssembly. 6 | Compilation is performed using `wasicc` here, but `clang --target=wasm32` can be used as well. 7 | See `build.sh` for details. 8 | 9 | ## Rust app 10 | 11 | Before building the app, please install the toolchain: 12 | ```sh 13 | rustup target add wasm32-unknown-unknown 14 | ``` 15 | To rebuild, use `build.sh`. 16 | 17 | ## AssemblyScript app 18 | 19 | Before building the app, please install npm dependencies: 20 | ```sh 21 | npm install # or yarn install 22 | ``` 23 | To rebuild, use `npm run build`. 24 | 25 | ## TinyGo app 26 | 27 | To rebuild, use `build.sh`. 28 | 29 | ___ 30 | 31 | **Note:** for all examples, the resulting `wasm` binary is converted to a C header using `xxd`. 32 | -------------------------------------------------------------------------------- /wasm_apps/assemblyscript/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | *.wat 3 | -------------------------------------------------------------------------------- /wasm_apps/assemblyscript/app.ts: -------------------------------------------------------------------------------- 1 | import * as dev from "./arduino"; 2 | 3 | let LED = dev.getPinLED(); 4 | 5 | function setup(): void { 6 | dev.pinMode(LED, dev.OUTPUT); 7 | } 8 | 9 | function run(): void { 10 | dev.digitalWrite(LED, dev.HIGH); 11 | dev.delay(100); 12 | dev.digitalWrite(LED, dev.LOW); 13 | dev.delay(900); 14 | } 15 | 16 | /* 17 | * Entry point 18 | */ 19 | export function _start(): void { 20 | setup(); 21 | while (1) { 22 | run(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /wasm_apps/assemblyscript/app.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wasm3/wasm3-arduino/0dcff083f369f89d7bd5d434d60e63d789fab133/wasm_apps/assemblyscript/app.wasm -------------------------------------------------------------------------------- /wasm_apps/assemblyscript/app.wasm.h: -------------------------------------------------------------------------------- 1 | unsigned char app_wasm[] = { 2 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x04, 0x60, 3 | 0x00, 0x00, 0x60, 0x02, 0x7f, 0x7f, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60, 4 | 0x00, 0x01, 0x7f, 0x02, 0x4e, 0x04, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 5 | 0x6e, 0x6f, 0x09, 0x67, 0x65, 0x74, 0x50, 0x69, 0x6e, 0x4c, 0x45, 0x44, 6 | 0x00, 0x03, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x07, 0x70, 7 | 0x69, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x00, 0x01, 0x07, 0x61, 0x72, 0x64, 8 | 0x75, 0x69, 0x6e, 0x6f, 0x0c, 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 9 | 0x57, 0x72, 0x69, 0x74, 0x65, 0x00, 0x01, 0x07, 0x61, 0x72, 0x64, 0x75, 10 | 0x69, 0x6e, 0x6f, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x00, 0x02, 0x03, 11 | 0x03, 0x02, 0x00, 0x00, 0x05, 0x03, 0x01, 0x00, 0x00, 0x06, 0x06, 0x01, 12 | 0x7f, 0x01, 0x41, 0x00, 0x0b, 0x07, 0x13, 0x02, 0x06, 0x5f, 0x73, 0x74, 13 | 0x61, 0x72, 0x74, 0x00, 0x04, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 14 | 0x02, 0x00, 0x08, 0x01, 0x05, 0x0a, 0x2d, 0x02, 0x24, 0x00, 0x23, 0x00, 15 | 0x41, 0x01, 0x10, 0x01, 0x03, 0x40, 0x23, 0x00, 0x41, 0x01, 0x10, 0x02, 16 | 0x41, 0xe4, 0x00, 0x10, 0x03, 0x23, 0x00, 0x41, 0x00, 0x10, 0x02, 0x41, 17 | 0x84, 0x07, 0x10, 0x03, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x06, 0x00, 0x10, 18 | 0x00, 0x24, 0x00, 0x0b 19 | }; 20 | unsigned int app_wasm_len = 196; 21 | -------------------------------------------------------------------------------- /wasm_apps/assemblyscript/arduino.ts: -------------------------------------------------------------------------------- 1 | export const LOW = 0; 2 | export const HIGH = 1; 3 | 4 | export const INPUT = 0x0; 5 | export const OUTPUT = 0x1; 6 | export const INPUT_PULLUP = 0x2; 7 | 8 | export declare function millis(): u32; 9 | export declare function delay(ms: u32): void; 10 | export declare function pinMode(pin: u32, mode: u32): void; 11 | export declare function digitalWrite(pin: u32, value: u32): void; 12 | export declare function getPinLED(): u32; 13 | 14 | -------------------------------------------------------------------------------- /wasm_apps/assemblyscript/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "assemblyscript": { 6 | "version": "0.18.12", 7 | "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.18.12.tgz", 8 | "integrity": "sha512-a0zJlb4xgEtxdadrrIP9MuLmQuRE6ZVzXPi2RZoVG6zgz+nLYLt1mkiP/TbJRY+4wvf1peTCZok+vyRAxFjppQ==", 9 | "dev": true, 10 | "requires": { 11 | "binaryen": "98.0.0-nightly.20210106", 12 | "long": "^4.0.0" 13 | } 14 | }, 15 | "binaryen": { 16 | "version": "98.0.0-nightly.20210106", 17 | "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-98.0.0-nightly.20210106.tgz", 18 | "integrity": "sha512-iunAgesqT9PXVYCc72FA4h0sCCKLifruT6NuUH63xqlFJGpChhZLgOtyIb/fIgTibN5Pd692cxfBViyCWFsJ9Q==", 19 | "dev": true 20 | }, 21 | "long": { 22 | "version": "4.0.0", 23 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 24 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", 25 | "dev": true 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /wasm_apps/assemblyscript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": "MIT", 3 | "scripts": { 4 | "build": "npm run asbuild:optimized && xxd -i app.wasm > app.wasm.h", 5 | "asbuild:optimized": "npx asc app.ts -b app.wasm -t app.wat -O3z --runtime stub --noAssert --use abort=" 6 | }, 7 | "devDependencies": { 8 | "assemblyscript": "^0.18.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /wasm_apps/assemblyscript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/assemblyscript/std/assembly.json", 3 | "include": [ 4 | "./**/*.ts" 5 | ] 6 | } -------------------------------------------------------------------------------- /wasm_apps/assemblyscript/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | assemblyscript@^0.9.0: 6 | version "0.9.0" 7 | resolved "https://registry.yarnpkg.com/assemblyscript/-/assemblyscript-0.9.0.tgz#2c85f0ff3bad7385484007d10ac65d29416f46c2" 8 | integrity sha512-HDDoaDfdnp0Ki/k272ib12sKz3ytVlXsIDise5meamInLC1qZAcmwwO+aqNyiVksmPYyLhQlaVZRPKWibHqo3g== 9 | dependencies: 10 | binaryen "90.0.0-nightly.20200111" 11 | long "^4.0.0" 12 | 13 | binaryen@90.0.0-nightly.20200111: 14 | version "90.0.0-nightly.20200111" 15 | resolved "https://registry.yarnpkg.com/binaryen/-/binaryen-90.0.0-nightly.20200111.tgz#dc5cfa53a7c2cb97a785a64ca041effd6ae66c4a" 16 | integrity sha512-2uihf1tqfkG2OJB54LjIDu5/fqbGgbj9VSwnj8hYtsRfML61y0uHeMkPfWctyl99m7hsgyDu7xUbJ7iyqBz6BA== 17 | 18 | long@^4.0.0: 19 | version "4.0.0" 20 | resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" 21 | integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== 22 | -------------------------------------------------------------------------------- /wasm_apps/cpp/app.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "arduino_api.h" 3 | 4 | int LED_BUILTIN; 5 | 6 | void setup() { 7 | LED_BUILTIN = getPinLED(); 8 | 9 | // initialize digital pin LED_BUILTIN as an output. 10 | pinMode(LED_BUILTIN, OUTPUT); 11 | } 12 | 13 | // the loop function runs over and over again forever 14 | void loop() { 15 | digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) 16 | delay(100); // wait 100ms 17 | digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW 18 | delay(900); // wait 900ms 19 | } 20 | 21 | /* 22 | * Entry point 23 | */ 24 | 25 | WASM_EXPORT 26 | void _start() { 27 | setup(); 28 | while (1) { loop(); } 29 | } 30 | -------------------------------------------------------------------------------- /wasm_apps/cpp/app.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wasm3/wasm3-arduino/0dcff083f369f89d7bd5d434d60e63d789fab133/wasm_apps/cpp/app.wasm -------------------------------------------------------------------------------- /wasm_apps/cpp/app.wasm.h: -------------------------------------------------------------------------------- 1 | unsigned char app_wasm[] = { 2 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x04, 0x60, 3 | 0x02, 0x7f, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60, 4 | 0x00, 0x01, 0x7f, 0x02, 0x4e, 0x04, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 5 | 0x6e, 0x6f, 0x09, 0x67, 0x65, 0x74, 0x50, 0x69, 0x6e, 0x4c, 0x45, 0x44, 6 | 0x00, 0x03, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x07, 0x70, 7 | 0x69, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x00, 0x00, 0x07, 0x61, 0x72, 0x64, 8 | 0x75, 0x69, 0x6e, 0x6f, 0x0c, 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 9 | 0x57, 0x72, 0x69, 0x74, 0x65, 0x00, 0x00, 0x07, 0x61, 0x72, 0x64, 0x75, 10 | 0x69, 0x6e, 0x6f, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x00, 0x02, 0x03, 11 | 0x02, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01, 0x07, 0x13, 0x02, 0x06, 12 | 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x5f, 0x73, 0x74, 13 | 0x61, 0x72, 0x74, 0x00, 0x04, 0x0a, 0x3a, 0x01, 0x38, 0x01, 0x01, 0x7f, 14 | 0x41, 0x80, 0x08, 0x10, 0x00, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 15 | 0x41, 0x01, 0x10, 0x01, 0x03, 0x40, 0x41, 0x80, 0x08, 0x28, 0x02, 0x00, 16 | 0x41, 0x01, 0x10, 0x02, 0x41, 0xe4, 0x00, 0x10, 0x03, 0x41, 0x80, 0x08, 17 | 0x28, 0x02, 0x00, 0x41, 0x00, 0x10, 0x02, 0x41, 0x84, 0x07, 0x10, 0x03, 18 | 0x0c, 0x00, 0x0b, 0x00, 0x0b 19 | }; 20 | unsigned int app_wasm_len = 197; 21 | -------------------------------------------------------------------------------- /wasm_apps/cpp/arduino_api.h: -------------------------------------------------------------------------------- 1 | #ifndef arduino_wasm_api_h 2 | #define arduino_wasm_api_h 3 | 4 | #include 5 | 6 | #define WASM_EXPORT extern "C" __attribute__((used)) __attribute__((visibility ("default"))) 7 | #define WASM_EXPORT_AS(NAME) WASM_EXPORT __attribute__((export_name(NAME))) 8 | #define WASM_IMPORT(MODULE,NAME) __attribute__((import_module(MODULE))) __attribute__((import_name(NAME))) 9 | #define WASM_CONSTRUCTOR __attribute__((constructor)) 10 | 11 | #define LOW 0x0 12 | #define HIGH 0x1 13 | 14 | #define INPUT 0x0 15 | #define OUTPUT 0x1 16 | #define INPUT_PULLUP 0x2 17 | 18 | extern "C" { 19 | 20 | WASM_IMPORT("arduino", "millis") uint32_t millis (void); 21 | WASM_IMPORT("arduino", "delay") void delay (uint32_t ms); 22 | WASM_IMPORT("arduino", "pinMode") void pinMode (uint32_t pin, uint32_t mode); 23 | WASM_IMPORT("arduino", "digitalWrite") void digitalWrite (uint32_t pin, uint32_t value); 24 | 25 | // This is a convenience function 26 | WASM_IMPORT("arduino", "getPinLED") uint32_t getPinLED (void); 27 | 28 | } 29 | 30 | #endif // arduino_wasm_api_h 31 | -------------------------------------------------------------------------------- /wasm_apps/cpp/arduino_api.syms: -------------------------------------------------------------------------------- 1 | millis 2 | delay 3 | pinMode 4 | digitalWrite 5 | getPinLED 6 | -------------------------------------------------------------------------------- /wasm_apps/cpp/build.sh: -------------------------------------------------------------------------------- 1 | # Compile 2 | wasicc -Os \ 3 | -z stack-size=4096 -Wl,--initial-memory=65536 \ 4 | -Wl,--allow-undefined-file=arduino_api.syms \ 5 | -Wl,--strip-all -nostdlib \ 6 | -o app.wasm app.cpp 7 | 8 | # Optimize (optional) 9 | wasm-opt -O3 app.wasm -o app.wasm 10 | wasm-strip app.wasm 11 | 12 | # Convert to WAT 13 | #wasm2wat --generate-names app.wasm -o app.wat 14 | 15 | # Convert to C header 16 | xxd -i app.wasm > app.wasm.h 17 | -------------------------------------------------------------------------------- /wasm_apps/rust/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "wasm32-unknown-unknown" 3 | rustflags = [ 4 | "-C", "link-args=-zstack-size=2048 -s", 5 | ] 6 | -------------------------------------------------------------------------------- /wasm_apps/rust/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target/ 3 | *.wat 4 | -------------------------------------------------------------------------------- /wasm_apps/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "app" 3 | version = "0.1.0" 4 | authors = ["Volodymyr Shymanskyy "] 5 | edition = "2018" 6 | 7 | [lib] 8 | path = "src/app.rs" 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | 13 | [profile.dev] 14 | panic = "abort" 15 | 16 | [profile.release] 17 | panic = "abort" 18 | opt-level = "s" 19 | codegen-units = 1 20 | lto = true 21 | #debug = true 22 | -------------------------------------------------------------------------------- /wasm_apps/rust/app.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wasm3/wasm3-arduino/0dcff083f369f89d7bd5d434d60e63d789fab133/wasm_apps/rust/app.wasm -------------------------------------------------------------------------------- /wasm_apps/rust/app.wasm.h: -------------------------------------------------------------------------------- 1 | unsigned char app_wasm[] = { 2 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x04, 0x60, 3 | 0x02, 0x7f, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60, 4 | 0x00, 0x01, 0x7f, 0x02, 0x4e, 0x04, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 5 | 0x6e, 0x6f, 0x09, 0x67, 0x65, 0x74, 0x50, 0x69, 0x6e, 0x4c, 0x45, 0x44, 6 | 0x00, 0x03, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x07, 0x70, 7 | 0x69, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x00, 0x00, 0x07, 0x61, 0x72, 0x64, 8 | 0x75, 0x69, 0x6e, 0x6f, 0x0c, 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 9 | 0x57, 0x72, 0x69, 0x74, 0x65, 0x00, 0x00, 0x07, 0x61, 0x72, 0x64, 0x75, 10 | 0x69, 0x6e, 0x6f, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x00, 0x02, 0x03, 11 | 0x02, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x0d, 0x02, 0x7f, 12 | 0x00, 0x41, 0x80, 0x10, 0x0b, 0x7f, 0x00, 0x41, 0x80, 0x10, 0x0b, 0x07, 13 | 0x2e, 0x04, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 14 | 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x04, 0x0a, 0x5f, 0x5f, 0x64, 15 | 0x61, 0x74, 0x61, 0x5f, 0x65, 0x6e, 0x64, 0x03, 0x00, 0x0b, 0x5f, 0x5f, 16 | 0x68, 0x65, 0x61, 0x70, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x03, 0x01, 0x0a, 17 | 0x2a, 0x01, 0x28, 0x01, 0x01, 0x7f, 0x10, 0x00, 0x22, 0x00, 0x41, 0x01, 18 | 0x10, 0x01, 0x03, 0x40, 0x20, 0x00, 0x41, 0x01, 0x10, 0x02, 0x41, 0xe4, 19 | 0x00, 0x10, 0x03, 0x20, 0x00, 0x41, 0x00, 0x10, 0x02, 0x41, 0x84, 0x07, 20 | 0x10, 0x03, 0x0c, 0x00, 0x0b, 0x00, 0x0b 21 | }; 22 | unsigned int app_wasm_len = 223; 23 | -------------------------------------------------------------------------------- /wasm_apps/rust/build.sh: -------------------------------------------------------------------------------- 1 | # Compile 2 | cargo build --release 3 | cp ./target/wasm32-unknown-unknown/release/app.wasm ./ 4 | 5 | # Optimize (optional) 6 | wasm-opt -O3 app.wasm -o app.wasm 7 | wasm-strip app.wasm 8 | 9 | # Convert to WAT 10 | #wasm2wat --generate-names app.wasm -o app.wat 11 | 12 | # Convert to C header 13 | xxd -i app.wasm > app.wasm.h 14 | -------------------------------------------------------------------------------- /wasm_apps/rust/src/app.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | mod arduino; 4 | use arduino::*; 5 | 6 | struct App { 7 | led: u32, 8 | } 9 | 10 | impl App { 11 | fn new() -> Self { 12 | let led = getPinLED(); 13 | pinMode(led, OUTPUT); 14 | Self { led } 15 | } 16 | 17 | fn run(&self) { 18 | digitalWrite(self.led, HIGH); 19 | delay(100); 20 | digitalWrite(self.led, LOW); 21 | delay(900); 22 | } 23 | } 24 | 25 | #[no_mangle] 26 | pub extern fn _start() { 27 | let app = App::new(); 28 | loop { 29 | app.run() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /wasm_apps/rust/src/arduino.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | #![allow(non_snake_case)] 3 | 4 | #[link(wasm_import_module = "arduino")] 5 | extern { 6 | #[link_name = "millis"] fn _millis() -> u32; 7 | #[link_name = "delay"] fn _delay(ms: u32); 8 | #[link_name = "pinMode"] fn _pinMode(pin: u32, mode: u32); 9 | #[link_name = "digitalWrite"] fn _digitalWrite(pin: u32, value: u32); 10 | #[link_name = "getPinLED"] fn _getPinLED() -> u32; 11 | } 12 | 13 | pub static LOW: u32 = 0; 14 | pub static HIGH: u32 = 1; 15 | 16 | pub static INPUT: u32 = 0x0; 17 | pub static OUTPUT: u32 = 0x1; 18 | pub static INPUT_PULLUP: u32 = 0x2; 19 | 20 | pub fn millis () -> u32 { unsafe { _millis() } } 21 | pub fn delay (ms: u32) { unsafe { _delay(ms); } } 22 | pub fn pinMode (pin: u32, mode: u32) { unsafe { _pinMode(pin, mode) } } 23 | pub fn digitalWrite (pin: u32, value: u32) { unsafe { _digitalWrite(pin, value) } } 24 | pub fn getPinLED () -> u32 { unsafe { _getPinLED() } } 25 | 26 | #[panic_handler] 27 | fn handle_panic(_: &core::panic::PanicInfo) -> ! { 28 | unsafe { core::arch::wasm32::unreachable() } 29 | } 30 | -------------------------------------------------------------------------------- /wasm_apps/tinygo/app.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | * Arduino API 5 | */ 6 | 7 | const ( 8 | LOW = 0 9 | HIGH = 1 10 | 11 | INPUT = 0 12 | OUTPUT = 1 13 | INPUT_PULLUP = 2 14 | ) 15 | 16 | //go:wasm-module arduino 17 | //go:export millis 18 | func millis() uint 19 | 20 | //go:wasm-module arduino 21 | //go:export delay 22 | func delay(ms uint) 23 | 24 | //go:wasm-module arduino 25 | //go:export pinMode 26 | func pinMode(pin, mode uint) 27 | 28 | //go:wasm-module arduino 29 | //go:export digitalWrite 30 | func digitalWrite(pin, value uint) 31 | 32 | //go:wasm-module arduino 33 | //go:export getPinLED 34 | func getPinLED() uint 35 | 36 | 37 | /* 38 | * App 39 | */ 40 | 41 | var LED = getPinLED() 42 | 43 | func setup() { 44 | pinMode(LED, 1) 45 | } 46 | 47 | func loop() { 48 | digitalWrite(LED, HIGH) 49 | delay(100) 50 | digitalWrite(LED, LOW) 51 | delay(900) 52 | } 53 | 54 | /* 55 | * Entry point 56 | */ 57 | 58 | func main() { 59 | setup() 60 | for { 61 | loop() 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /wasm_apps/tinygo/app.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wasm3/wasm3-arduino/0dcff083f369f89d7bd5d434d60e63d789fab133/wasm_apps/tinygo/app.wasm -------------------------------------------------------------------------------- /wasm_apps/tinygo/app.wasm.h: -------------------------------------------------------------------------------- 1 | unsigned char app_wasm[] = { 2 | 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x18, 0x05, 0x60, 3 | 0x00, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60, 0x02, 0x7f, 0x7f, 0x00, 0x60, 4 | 0x00, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x02, 0x4e, 5 | 0x04, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x09, 0x67, 0x65, 6 | 0x74, 0x50, 0x69, 0x6e, 0x4c, 0x45, 0x44, 0x00, 0x03, 0x07, 0x61, 0x72, 7 | 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x07, 0x70, 0x69, 0x6e, 0x4d, 0x6f, 0x64, 8 | 0x65, 0x00, 0x02, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x0c, 9 | 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 10 | 0x00, 0x02, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x05, 0x64, 11 | 0x65, 0x6c, 0x61, 0x79, 0x00, 0x01, 0x03, 0x09, 0x08, 0x00, 0x00, 0x00, 12 | 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01, 0x01, 13 | 0x05, 0x04, 0x01, 0x01, 0x01, 0x01, 0x06, 0x23, 0x06, 0x7f, 0x00, 0x41, 14 | 0x90, 0x10, 0x0b, 0x7f, 0x00, 0x41, 0x80, 0x10, 0x0b, 0x7f, 0x00, 0x41, 15 | 0x90, 0x10, 0x0b, 0x7f, 0x00, 0x41, 0x80, 0x10, 0x0b, 0x7f, 0x00, 0x41, 16 | 0x00, 0x0b, 0x7f, 0x00, 0x41, 0x01, 0x0b, 0x07, 0xa1, 0x01, 0x0c, 0x06, 17 | 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x11, 0x5f, 0x5f, 0x77, 18 | 0x61, 0x73, 0x6d, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x63, 0x74, 0x6f, 19 | 0x72, 0x73, 0x00, 0x04, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 20 | 0x05, 0x0c, 0x67, 0x6f, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 21 | 0x65, 0x72, 0x00, 0x07, 0x0b, 0x5f, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 22 | 0x62, 0x61, 0x73, 0x65, 0x03, 0x00, 0x06, 0x6d, 0x65, 0x6d, 0x73, 0x65, 23 | 0x74, 0x00, 0x0b, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x00, 0x09, 24 | 0x0c, 0x5f, 0x5f, 0x64, 0x73, 0x6f, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 25 | 0x65, 0x03, 0x01, 0x0a, 0x5f, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x65, 26 | 0x6e, 0x64, 0x03, 0x02, 0x0d, 0x5f, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 27 | 0x6c, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x03, 0x03, 0x0d, 0x5f, 0x5f, 0x6d, 28 | 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x03, 0x04, 29 | 0x0c, 0x5f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x73, 30 | 0x65, 0x03, 0x05, 0x0a, 0xc3, 0x04, 0x08, 0x03, 0x00, 0x01, 0x0b, 0x25, 31 | 0x00, 0x41, 0x80, 0x10, 0x3f, 0x00, 0x41, 0x10, 0x74, 0x36, 0x02, 0x00, 32 | 0x10, 0x06, 0x41, 0x80, 0x10, 0x3f, 0x00, 0x41, 0x10, 0x74, 0x36, 0x02, 33 | 0x00, 0x41, 0x88, 0x10, 0x10, 0x00, 0x36, 0x02, 0x00, 0x10, 0x0a, 0x00, 34 | 0x0b, 0x29, 0x01, 0x02, 0x7f, 0x41, 0x84, 0x10, 0x41, 0x80, 0x10, 0x28, 35 | 0x02, 0x00, 0x22, 0x00, 0x20, 0x00, 0x41, 0x90, 0x10, 0x6b, 0x41, 0x06, 36 | 0x76, 0x22, 0x00, 0x6b, 0x22, 0x01, 0x36, 0x02, 0x00, 0x20, 0x01, 0x41, 37 | 0x00, 0x20, 0x00, 0x10, 0x0b, 0x1a, 0x0b, 0x04, 0x00, 0x10, 0x08, 0x0b, 38 | 0x35, 0x01, 0x01, 0x7f, 0x03, 0x40, 0x41, 0x8c, 0x10, 0x28, 0x02, 0x00, 39 | 0x22, 0x00, 0x04, 0x40, 0x41, 0x8c, 0x10, 0x20, 0x00, 0x28, 0x02, 0x00, 40 | 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 41 | 0x28, 0x02, 0x0c, 0x22, 0x00, 0x20, 0x00, 0x28, 0x02, 0x00, 0x11, 0x01, 42 | 0x00, 0x0c, 0x01, 0x0b, 0x0b, 0x0b, 0x03, 0x00, 0x00, 0x0b, 0x30, 0x00, 43 | 0x41, 0x88, 0x10, 0x28, 0x02, 0x00, 0x41, 0x01, 0x10, 0x01, 0x03, 0x40, 44 | 0x41, 0x88, 0x10, 0x28, 0x02, 0x00, 0x41, 0x01, 0x10, 0x02, 0x41, 0xe4, 45 | 0x00, 0x10, 0x03, 0x41, 0x88, 0x10, 0x28, 0x02, 0x00, 0x41, 0x00, 0x10, 46 | 0x02, 0x41, 0x84, 0x07, 0x10, 0x03, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0xfc, 47 | 0x02, 0x02, 0x02, 0x7f, 0x01, 0x7e, 0x02, 0x40, 0x20, 0x02, 0x45, 0x0d, 48 | 0x00, 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x20, 0x02, 49 | 0x6a, 0x22, 0x03, 0x41, 0x7f, 0x6a, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 50 | 0x02, 0x41, 0x03, 0x49, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 51 | 0x02, 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x01, 0x20, 0x03, 0x41, 0x7d, 52 | 0x6a, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x41, 0x7e, 0x6a, 0x20, 53 | 0x01, 0x3a, 0x00, 0x00, 0x20, 0x02, 0x41, 0x07, 0x49, 0x0d, 0x00, 0x20, 54 | 0x00, 0x20, 0x01, 0x3a, 0x00, 0x03, 0x20, 0x03, 0x41, 0x7c, 0x6a, 0x20, 55 | 0x01, 0x3a, 0x00, 0x00, 0x20, 0x02, 0x41, 0x09, 0x49, 0x0d, 0x00, 0x20, 56 | 0x00, 0x41, 0x00, 0x20, 0x00, 0x6b, 0x41, 0x03, 0x71, 0x22, 0x04, 0x6a, 57 | 0x22, 0x03, 0x20, 0x01, 0x41, 0xff, 0x01, 0x71, 0x41, 0x81, 0x82, 0x84, 58 | 0x08, 0x6c, 0x22, 0x01, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x02, 0x20, 59 | 0x04, 0x6b, 0x41, 0x7c, 0x71, 0x22, 0x04, 0x6a, 0x22, 0x02, 0x41, 0x7c, 60 | 0x6a, 0x20, 0x01, 0x36, 0x02, 0x00, 0x20, 0x04, 0x41, 0x09, 0x49, 0x0d, 61 | 0x00, 0x20, 0x03, 0x20, 0x01, 0x36, 0x02, 0x08, 0x20, 0x03, 0x20, 0x01, 62 | 0x36, 0x02, 0x04, 0x20, 0x02, 0x41, 0x78, 0x6a, 0x20, 0x01, 0x36, 0x02, 63 | 0x00, 0x20, 0x02, 0x41, 0x74, 0x6a, 0x20, 0x01, 0x36, 0x02, 0x00, 0x20, 64 | 0x04, 0x41, 0x19, 0x49, 0x0d, 0x00, 0x20, 0x03, 0x20, 0x01, 0x36, 0x02, 65 | 0x18, 0x20, 0x03, 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, 0x03, 0x20, 0x01, 66 | 0x36, 0x02, 0x10, 0x20, 0x03, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x20, 0x02, 67 | 0x41, 0x70, 0x6a, 0x20, 0x01, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x6c, 68 | 0x6a, 0x20, 0x01, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x68, 0x6a, 0x20, 69 | 0x01, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x64, 0x6a, 0x20, 0x01, 0x36, 70 | 0x02, 0x00, 0x20, 0x04, 0x20, 0x03, 0x41, 0x04, 0x71, 0x41, 0x18, 0x72, 71 | 0x22, 0x04, 0x6b, 0x22, 0x02, 0x41, 0x20, 0x49, 0x0d, 0x00, 0x20, 0x01, 72 | 0xad, 0x22, 0x05, 0x42, 0x20, 0x86, 0x20, 0x05, 0x84, 0x21, 0x05, 0x20, 73 | 0x03, 0x20, 0x04, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x20, 0x05, 74 | 0x37, 0x03, 0x00, 0x20, 0x01, 0x41, 0x18, 0x6a, 0x20, 0x05, 0x37, 0x03, 75 | 0x00, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x20, 0x05, 0x37, 0x03, 0x00, 0x20, 76 | 0x01, 0x41, 0x08, 0x6a, 0x20, 0x05, 0x37, 0x03, 0x00, 0x20, 0x01, 0x41, 77 | 0x20, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x41, 0x60, 0x6a, 0x22, 0x02, 0x41, 78 | 0x1f, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x0b 79 | }; 80 | unsigned int app_wasm_len = 921; 81 | -------------------------------------------------------------------------------- /wasm_apps/tinygo/build.sh: -------------------------------------------------------------------------------- 1 | # Prepare 2 | export PATH=/opt/tinygo0.17.0/bin:$PATH 3 | export PATH=/opt/go1.15.2/bin:$PATH 4 | export GOROOT=/opt/go1.15.2 5 | 6 | # Compile 7 | tinygo build -target wasm \ 8 | -panic trap -wasm-abi generic \ 9 | -ldflags="-z stack-size=2048 --max-memory=65536" \ 10 | -o app.wasm app.go 11 | 12 | # Optimize (optional) 13 | wasm-opt -Os app.wasm -o app.wasm 14 | wasm-strip app.wasm 15 | 16 | # Convert to WAT 17 | #wasm2wat --generate-names app.wasm -o app.wat 18 | 19 | # Convert to C header 20 | xxd -i app.wasm > app.wasm.h 21 | --------------------------------------------------------------------------------