From 4cc9bd9e4e3a3ef3ab9b16b6d40e9bf2e4f3a418 Mon Sep 17 00:00:00 2001 From: Karl Fessel Date: Thu, 26 Nov 2020 16:18:48 +0100 Subject: [PATCH] example/wasm: a basic wamr example * using makefile blobs * improve usability of example * add sample with memory saving Makefile --- examples/wasm/Makefile | 32 ++++++ examples/wasm/README.md | 8 ++ examples/wasm/config.cmake | 21 ++++ examples/wasm/iwasmt.c | 178 +++++++++++++++++++++++++++++ examples/wasm/main.wasm | Bin 0 -> 416 bytes examples/wasm/wasm_sample/Makefile | 101 ++++++++++++++++ examples/wasm/wasm_sample/hello.c | 15 +++ 7 files changed, 355 insertions(+) create mode 100644 examples/wasm/Makefile create mode 100644 examples/wasm/README.md create mode 100644 examples/wasm/config.cmake create mode 100644 examples/wasm/iwasmt.c create mode 100755 examples/wasm/main.wasm create mode 100644 examples/wasm/wasm_sample/Makefile create mode 100644 examples/wasm/wasm_sample/hello.c diff --git a/examples/wasm/Makefile b/examples/wasm/Makefile new file mode 100644 index 0000000000..5afab016fc --- /dev/null +++ b/examples/wasm/Makefile @@ -0,0 +1,32 @@ +APPLICATION = wasm-example +# If no BOARD is defined in the environment, use this default: +BOARD ?= native + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../.. + +USEPKG += wamr + +USEMODULE += xtimer +USEMODULE += sema + +export WAMR_CONFIG := $(abspath config.cmake) + +WPEDANTIC := 0 +WERROR := 0 + +BLOBS += main.wasm + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +###################################################### +# Load the rest of the usual RIOT make infastructure # +###################################################### + +include $(RIOTBASE)/Makefile.include diff --git a/examples/wasm/README.md b/examples/wasm/README.md new file mode 100644 index 0000000000..d95393de86 --- /dev/null +++ b/examples/wasm/README.md @@ -0,0 +1,8 @@ +# building WASM + +The source for main.wasm can be found in +/build/pkg/wamr/product-mini/app-samples/hello-world/ + +https://github.com/bytecodealliance/wasm-micro-runtime/tree/main/product-mini/app-samples/hello-world + + diff --git a/examples/wasm/config.cmake b/examples/wasm/config.cmake new file mode 100644 index 0000000000..601794add0 --- /dev/null +++ b/examples/wasm/config.cmake @@ -0,0 +1,21 @@ +# following line a hints for build options mostly untested +# some are not matching RIOTs application targets +# they default to off + +# set (WAMR_BUILD_LIBC_WASI 1) #enable libc wasi support +# set (WAMR_BUILD_THREAD_MGR 1) #enable thread manager support +# set (WAMR_BUILD_APP_FRAMEWORK 1) #enable WAMR app framework support +# set (WAMR_BUILD_LIB_PTHREAD 1) #enable pthread support + +# set (WAMR_BUILD_JIT 1) #enable WAMR JIT +# set (WAMR_BUILD_FAST_INTERP 1) #enable Fast interpreter +# set (WAMR_BUILD_MULTI_MODULE 1) #enable Multiple modules +# set (WAMR_BUILD_SPEC_TEST 1) #enable spec test compatible mode is on +# set (WAMR_BUILD_BULK_MEMORY 1) #enable Bulk memory feature +# set (WAMR_BUILD_SHARED_MEMORY 1) #enable Shared memory +# set (WAMR_BUILD_MINI_LOADER 1) #enable WASM mini loader +# set (WAMR_DISABLE_HW_BOUND_CHECK 1) #enable Hardware boundary check disabled +# set (WAMR_BUILD_MEMORY_PROFILING 1) #enable Memory profiling +# set (WAMR_APP_THREAD_STACK_SIZE_MAX ${WAMR_APP_THREAD_STACK_SIZE_MAX}) #set maximum thread stack size +# set (WAMR_BUILD_CUSTOM_NAME_SECTION 1) #enable Custom name section +# set (WAMR_BUILD_TAIL_CALL 1) #enable Tail call diff --git a/examples/wasm/iwasmt.c b/examples/wasm/iwasmt.c new file mode 100644 index 0000000000..0069ea08a0 --- /dev/null +++ b/examples/wasm/iwasmt.c @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * Copyright (C) 2020 TU Bergakademie Freiberg Karl Fessel + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +// +#include +#include +#include + +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#include "wasm_export.h" +#pragma GCC diagnostic pop + +#include + +/*provide some test program*/ +#include "blob/main.wasm.h" + +#define DEFAULT_THREAD_STACKSIZE (6 * 1024) +#define DEFAULT_THREAD_PRIORITY 50 + +static int app_argc; +static char **app_argv; + +/* execs the main function in an instantiated module */ +static int iwasm_instance_exec_main(wasm_module_inst_t module_inst, int argc, char **argv) +{ + const char *exception = 0; + int ret = 0; + wasm_application_execute_main(module_inst, argc, argv); + if ((exception = wasm_runtime_get_exception(module_inst))){ + puts(exception); + return -1; + } + if(argc > 0) ret = *((int*)argv); + return ret; +} + +/* execs the main function of a loaded module */ +int iwasm_module_exec_main(wasm_module_t wasm_module , int argc, char **argv) +{ + wasm_module_inst_t wasm_module_inst = NULL; + char error_buf[128]; + int ret = 0; + + /* instantiate the module */ + if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, 8 * 1024, + 8 * 1024, error_buf, sizeof(error_buf)))) { + puts(error_buf); + return -1; + } + ret = iwasm_instance_exec_main(wasm_module_inst, argc, argv); + /* destroy the module instance */ + wasm_runtime_deinstantiate(wasm_module_inst); + return ret; +} + +/* bytecode needs to be writeable*/ +int iwasm_bytecode_exec_main(void *bytecode, size_t bytecode_len, int argc, char **argv){ +// (uint8_t *) bytecode; + int ret = 0; + wasm_module_t wasm_module = NULL; + + { /* load WASM module */ + char error_buf[128]; + if (!(wasm_module = wasm_runtime_load((uint8_t * )bytecode, bytecode_len, + error_buf, sizeof(error_buf)))) { + puts(error_buf); + return -1; + } + } + ret = iwasm_module_exec_main(wasm_module, argc, argv); + /* unload WASM module */ + wasm_runtime_unload(wasm_module); + return ret; +} + +/* running this initialises the wamr runtime*/ +bool iwasm_runtime_init(void) +{ + RuntimeInitArgs init_args; +/* chose allocator non defaults to system allocator */ +#define FUNC_ALLOC +//#define POOL_ALLOC + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); +#ifdef POOL_ALLOC + static char global_heap_buf[256 * 1024] = { 0 };//(256 kB) + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); +#elif defined(FUNC_ALLOC) + init_args.mem_alloc_type = Alloc_With_Allocator; +/*deactivate Wpedantic for some lines*/ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" + init_args.mem_alloc_option.allocator.malloc_func = malloc; + init_args.mem_alloc_option.allocator.realloc_func = realloc; + init_args.mem_alloc_option.allocator.free_func = free; +#pragma GCC diagnostic pop +#else + init_args.mem_alloc_type = Alloc_With_System_Allocator; +#endif + + /* initialize runtime environment */ + if (!wasm_runtime_full_init(&init_args)) { + puts("Init runtime environment failed."); + return false; + } + return true; +} + +void * iwasm_thread(void *arg1) +{ + (void) arg1; /*unused*/ + uint8_t *wasm_buf = NULL; + unsigned wasm_buf_size = 0; + + if(!iwasm_runtime_init()) + return (void *)-1; + + /* we need the bytecode to be writable while loading + * loading adds size information to stack POPs */ + //static uint8_t wasm_test_file[] = main_wasm; + wasm_buf = malloc(main_wasm_len); + memcpy(wasm_buf, main_wasm, main_wasm_len); + /* no copy need if architecture has const in writable mem */ + /* wasm_buf = (uint8_t *) main_wasm; */ + wasm_buf_size = main_wasm_len; + + iwasm_bytecode_exec_main(wasm_buf, wasm_buf_size, app_argc, app_argv); + + free(wasm_buf); + wasm_runtime_destroy(); + return NULL; +} + +bool iwasm_start_thread(void) +{ + struct{ + char * stack; + int stacksize; + uint8_t priority; + int flags; + thread_task_func_t task_func; + void * arg; + const char * name; + } b = { + .stacksize = DEFAULT_THREAD_STACKSIZE, + .priority = 8, + .flags = 0, + .task_func = iwasm_thread, + .arg = NULL, + .name = "simple_wamr" + }; + + b.stack=malloc(b.stacksize); + kernel_pid_t tpid = thread_create (b.stack, b.stacksize, b.priority, b.flags, b.task_func, b.arg, b.name); + + return tpid != 0 ? true : false;; +} + +/* this seems to be a very direct interpretation of i like to have a wamr_run */ +int wamr_run(void *bytecode, size_t bytecode_len, int argc, char **argv){ + return iwasm_bytecode_exec_main(bytecode, bytecode_len, argc, argv); +} + +#define telltruth(X) ((X) ? "true" : "false") +int main(void) +{ + printf("iwasm_thread_initilised: %s\n",telltruth(iwasm_start_thread())); +} diff --git a/examples/wasm/main.wasm b/examples/wasm/main.wasm new file mode 100755 index 0000000000000000000000000000000000000000..ad784d6cd60f6168b0dda7805b84a2a5bb4ddf35 GIT binary patch literal 416 zcmXYtu};G<5QhJ=-BKkWMe5ecEg*G3LIu>JEcJlITcj>=L`#xJNeg01frW)<-~|{e z1_mY`4Lhla(|!Nl?>ilInGyi%iW#das%F##%m6kL++>gKyjW!G7^orDNwT^FIS_GS z3|O7!n{{bb&NxJiaw2MR0=2umBK0@)E9~QM$3Hj|?bM{J;+eq@!+WFiaIQ)M#+O$_x&OH>cds`vsKj> zzMUYK&07cH +# --initial-memory=65536 + +# --export-all Export all symbols (normally combined with --no-gc-sections) +# --export-dynamic Put symbols in the dynamic symbol table +# --export-table Export function table to the environment +# --export= Force a symbol to be exported +# --fatal-warnings Treat warnings as errors +# --import-memory Import memory from the environment +# --import-table Import function table from the environment +# --initial-memory= +# Initial size of the linear memory +# --lto-O Optimization level for LTO +# --lto-partitions= +# Number of LTO codegen partitions +# -L Add a directory to the library search path +# -l Root name of library to use +# --max-memory= Maximum size of the linear memory +# --merge-data-segments Enable merging data segments +# --mllvm Options to pass to LLVM +# --pie Create a position independent executable +# --print-gc-sections List removed unused sections +# --relocatable Create relocatable object file +# --shared-memory Use shared linear memory +# --shared Build a shared object +# --stack-first Place stack at start of linear memory rather than after data +# --strip-all Strip all symbols +# --strip-debug Strip debugging information +# -S Alias for --strip-debug +# -s Alias for --strip-all +# --thinlto-cache-dir= +# Path to ThinLTO cached object file directory +# --thinlto-cache-policy= +# Pruning policy for the ThinLTO cache +# --thinlto-jobs= Number of ThinLTO jobs +# --threads Run the linker multi-threaded +# --undefined= Force undefined symbol during linking +# --verbose Verbose mode +# --version Display the version number and exit +# -z