Skip to content

Commit fffc949

Browse files
committed
Implemented custom WASM build for near-vm
In this commit I make another attempt to build Micropython into a portable WASM which can be run on near-vm. In Makefile new target is "wasm" which is stripped of many runtime dependencies and builds a simple "hello" program.
1 parent a41dd1c commit fffc949

File tree

6 files changed

+162
-53
lines changed

6 files changed

+162
-53
lines changed

ports/webassembly/Makefile

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ INC += -I$(BUILD)
4646
INC += -I$(VARIANT_DIR)
4747

4848
CFLAGS += -std=c99 -Wall -Werror -Wdouble-promotion -Wfloat-conversion
49-
CFLAGS += -Os -DNDEBUG
49+
CFLAGS += -Oz -fdata-sections -ffunction-sections -DNDEBUG
5050
CFLAGS += $(INC)
5151

5252
EXPORTED_FUNCTIONS_EXTRA += ,\
@@ -107,6 +107,7 @@ SRC_SHARED = $(addprefix shared/,\
107107
)
108108

109109
SRC_C += \
110+
mp_stubs.c \
110111
lexer_dedent.c \
111112
main.c \
112113
modjs.c \
@@ -164,40 +165,28 @@ test_min: $(BUILD)/micropython.min.mjs $(TOP)/tests/run-tests.py
164165

165166
include $(TOP)/py/mkrules.mk
166167

167-
################################################################################
168-
# Relocatable WebAssembly build
169-
170-
RELOCATABLE_BUILD = $(BUILD)/micropython_relocatable.wasm
171-
RELOCATABLE_PY_O = $(addprefix $(BUILD)/, $(PY_CORE_O_BASENAME:.o=.relocatable.o))
172-
RELOCATABLE_EXTMOD_O = $(addprefix $(BUILD)/, $(EXTMOD_O_BASENAME:.o=.relocatable.o))
173-
RELOCATABLE_PORT_O = $(addprefix $(BUILD)/, $(SRC_C_ALL_RELOCATABLE:.c=.relocatable.o) $(SRC_SHARED:.c=.relocatable.o))
174-
RELOCATABLE_OBJ = $(RELOCATABLE_PY_O) $(RELOCATABLE_EXTMOD_O) $(RELOCATABLE_PORT_O)
175-
176-
# Flags for relocatable build
177-
RELOCATABLE_CFLAGS = $(CFLAGS) -fPIC
178-
RELOCATABLE_JSFLAGS = -s SIDE_MODULE=2 -s LINKABLE=1 -s EXPORT_ALL=1 -s WASM_BIGINT=1
179-
180-
# Rules to build relocatable object files
181-
$(BUILD)/%.relocatable.o: %.c
182-
$(ECHO) "CC $<"
183-
$(Q)$(CC) $(RELOCATABLE_CFLAGS) -c $< -o $@
168+
OBJ_EXCLUDE = \
169+
$(BUILD)/py/modio.o \
170+
$(BUILD)/py/modsys.o \
171+
$(BUILD)/py/modbuiltins.o
184172

185-
$(BUILD)/%.relocatable.o: $(BUILD)/%.c
186-
$(ECHO) "CC $<"
187-
$(Q)$(CC) $(RELOCATABLE_CFLAGS) -c $< -o $@
188173

189-
# Target for building the relocatable WebAssembly module
190-
.PHONY: relocatable
191-
relocatable: $(RELOCATABLE_BUILD)
174+
#OBJ_WASM = $(filter-out $(OBJ_EXCLUDE),$(OBJ))
175+
OBJ_WASM = $(OBJ)
176+
OBJ_WASM += $(BUILD)/mp_stubs.o
192177

193-
$(RELOCATABLE_BUILD): $(RELOCATABLE_OBJ)
194-
$(ECHO) "LINK $@"
195-
$(Q)$(CC) $(LDFLAGS) -o $@ $(RELOCATABLE_OBJ) $(RELOCATABLE_JSFLAGS)
178+
WASM_CFLAGS = -O0 -std=c99 -Wall -Werror -Wdouble-promotion -Wfloat-conversion $(INC)
179+
WASM_LDFLAGS = -Wl,--gc-sections -sSTANDALONE_WASM=0 -sSINGLE_FILE=1 -sALLOW_MEMORY_GROWTH=0 -sWASM_BIGINT=1
196180

197-
# Clean rule for relocatable build
198-
.PHONY: clean_relocatable
199-
clean_relocatable:
200-
$(RM) -f $(RELOCATABLE_OBJ) $(RELOCATABLE_BUILD)
181+
wasm: $(BUILD)/custom_wasm.o $(OBJ_WASM)
182+
$(ECHO) "LINK $@ $(OBJ_WASM)"
183+
$(Q)emcc $(WASM_CFLAGS) $(WASM_LDFLAGS) \
184+
-o $(BUILD)/micropython.wasm \
185+
$^ \
186+
-s IMPORTED_MEMORY=0 -s ERROR_ON_UNDEFINED_SYMBOLS=0 \
187+
-sEXPORTED_FUNCTIONS='["_mp_sum","_c_sum","_sanity_check"]' \
188+
--no-entry
201189

202-
# Add relocatable to the clean target
203-
clean: clean_relocatable
190+
$(BUILD)/custom_wasm.o: custom_wasm.c
191+
$(ECHO) "CC $<"
192+
$(Q)emcc $(WASM_CFLAGS) -c -o $@ $^

ports/webassembly/custom_wasm.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include <stdint.h>
2+
#include "py/mpconfig.h"
3+
#include "py/mpstate.h"
4+
#include "py/builtin.h"
5+
#include "py/obj.h"
6+
#include "py/compile.h"
7+
#include "py/runtime.h"
8+
#include "py/gc.h"
9+
10+
extern void value_return(uint64_t value_len, uint64_t value_ptr);
11+
12+
//#define HEAP_SIZE 32768
13+
14+
//static char heap[HEAP_SIZE];
15+
16+
void init_micropython(void) {
17+
// gc_init(heap, heap + sizeof(heap));
18+
mp_init();
19+
}
20+
21+
22+
void mp_sum() {
23+
init_micropython();
24+
25+
//mp_obj_t args[2] = {mp_obj_new_int(40), mp_obj_new_int(2)};
26+
//mp_obj_t fun = mp_load_name(qstr_from_str("sum"));
27+
//mp_obj_t result = mp_call_function_n_kw(fun, 2, 0, args);
28+
29+
//mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, "sum(a, b)", 9, false);
30+
//mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_EVAL_INPUT);
31+
//mp_obj_t module_fun = mp_compile(&pt, lex->source_name, false);
32+
33+
//mp_obj_t result = mp_call_function_n_kw(module_fun, 2, 0, args);
34+
35+
//value_return(mp_obj_get_int(result), sizeof(uint32_t));
36+
value_return(4, 0);
37+
}
38+
39+
void c_sum(uint32_t a, uint32_t b) {
40+
value_return(sizeof(uint32_t), (a + b));
41+
}
42+
43+
void sanity_check() {
44+
value_return(0, 4);
45+
}

ports/webassembly/mp_stubs.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#include "py/obj.h"
2+
#include "py/mpconfig.h"
3+
4+
mp_obj_t mp_sys_stdin_obj = MP_OBJ_NULL;
5+
mp_obj_t mp_sys_stdout_obj = MP_OBJ_NULL;
6+
mp_obj_t mp_sys_stderr_obj = MP_OBJ_NULL;
7+
8+
9+
#include <stdint.h>
10+
11+
#include <stdint.h>
12+
13+
int32_t invoke_ii(int32_t a, int32_t b) {
14+
return 0;
15+
}
16+
17+
void invoke_viii(int32_t a, int32_t b, int32_t c, int32_t d) {
18+
}
19+
20+
int32_t invoke_iiii(int32_t a, int32_t b, int32_t c, int32_t d) {
21+
return 0;
22+
}
23+
24+
void invoke_v(int32_t a) {
25+
}
26+
27+
int32_t invoke_iii(int32_t a, int32_t b, int32_t c) {
28+
return 0;
29+
}
30+
31+
void invoke_vi(int32_t a, int32_t b) {
32+
}
33+
34+
void invoke_vii(int32_t a, int32_t b, int32_t c) {
35+
}
36+
37+
int32_t invoke_i(int32_t a) {
38+
return 0;
39+
}
40+
41+
void mp_js_hook(void) {
42+
}
43+
44+
int32_t invoke_iiiii(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e) {
45+
return 0;
46+
}
47+
48+
void invoke_viiii(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e) {
49+
}
50+
51+
void emscripten_scan_registers(int32_t a) {
52+
}
53+
54+
uint32_t mp_js_ticks_ms(void) {
55+
return 0;
56+
}
57+
58+
int fd_write(void) {
59+
return 0;
60+
}
61+
62+
void _emscripten_throw_longjmp(void) {
63+
}
64+
65+
uint32_t mp_hal_stdout_tx_strn(const char *str, size_t len) {
66+
return 0;
67+
}
68+
69+
int __wasi_fd_close(int a) {
70+
return 0;
71+
}
72+
73+
int __wasi_fd_write(int a, int b, int c, int d) {
74+
return 0;
75+
}

ports/webassembly/mpconfigport.h

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,41 +45,41 @@
4545
#define MICROPY_ENABLE_GC (1)
4646
#define MICROPY_ENABLE_PYSTACK (1)
4747
#define MICROPY_STACK_CHECK (0)
48-
#define MICROPY_KBD_EXCEPTION (1)
49-
#define MICROPY_REPL_EVENT_DRIVEN (1)
48+
#define MICROPY_KBD_EXCEPTION (0)
49+
#define MICROPY_REPL_EVENT_DRIVEN (0)
5050
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
5151
#define MICROPY_ENABLE_DOC_STRING (1)
5252
#define MICROPY_WARNINGS (1)
5353
#define MICROPY_ERROR_PRINTER (&mp_stderr_print)
5454
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
5555
#define MICROPY_USE_INTERNAL_ERRNO (1)
56-
#define MICROPY_USE_INTERNAL_PRINTF (0)
56+
#define MICROPY_USE_INTERNAL_PRINTF (1)
5757

5858
#define MICROPY_EPOCH_IS_1970 (1)
59-
#define MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK (1)
60-
#define MICROPY_PY_RANDOM_SEED_INIT_FUNC (mp_js_random_u32())
61-
#define MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME (1)
62-
#define MICROPY_PY_TIME_TIME_TIME_NS (1)
63-
#define MICROPY_PY_TIME_INCLUDEFILE "ports/webassembly/modtime.c"
59+
#define MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK (0)
60+
//#define MICROPY_PY_RANDOM_SEED_INIT_FUNC (mp_js_random_u32())
61+
#define MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME (0)
62+
#define MICROPY_PY_TIME_TIME_TIME_NS (0)
63+
//#define MICROPY_PY_TIME_INCLUDEFILE "ports/webassembly/modtime.c"
6464
#ifndef MICROPY_VFS
65-
#define MICROPY_VFS (1)
65+
#define MICROPY_VFS (0)
6666
#endif
67-
#define MICROPY_VFS_POSIX (MICROPY_VFS)
67+
#define MICROPY_VFS_POSIX (0)
6868
#define MICROPY_PY_SYS_PLATFORM "webassembly"
6969

7070
#ifndef MICROPY_PY_JS
71-
#define MICROPY_PY_JS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES)
71+
#define MICROPY_PY_JS (0)
7272
#endif
7373

7474
#ifndef MICROPY_PY_JSFFI
75-
#define MICROPY_PY_JSFFI (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES)
75+
#define MICROPY_PY_JSFFI (0)
7676
#endif
7777

78-
#define MICROPY_EVENT_POLL_HOOK \
79-
do { \
80-
extern void mp_handle_pending(bool); \
81-
mp_handle_pending(true); \
82-
} while (0);
78+
//#define MICROPY_EVENT_POLL_HOOK \
79+
// do { \
80+
// extern void mp_handle_pending(bool); \
81+
// mp_handle_pending(true); \
82+
// } while (0);
8383

8484
// Whether the VM will periodically call mp_js_hook(), which checks for
8585
// interrupt characters on stdin (or equivalent input).

ports/webassembly/mphalport.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ static void stderr_print_strn(void *env, const char *str, size_t len) {
3535

3636
const mp_print_t mp_stderr_print = {NULL, stderr_print_strn};
3737

38-
mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) {
38+
mp_uint_t __attribute__((weak)) mp_hal_stdout_tx_strn(const char *str, size_t len) {
3939
return write(1, str, len);
4040
}
4141

py/misc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,8 @@ static uint32_t mp_ctz(uint32_t x) {
374374

375375
// mp_int_t can be larger than long, i.e. Windows 64-bit, nan-box variants
376376
static inline uint32_t mp_clz_mpi(mp_int_t x) {
377-
MP_STATIC_ASSERT(sizeof(mp_int_t) == sizeof(long long)
378-
|| sizeof(mp_int_t) == sizeof(long));
377+
//MP_STATIC_ASSERT(sizeof(mp_int_t) == sizeof(long long)
378+
// || sizeof(mp_int_t) == sizeof(long));
379379

380380
// ugly, but should compile to single intrinsic unless O0 is set
381381
if (sizeof(mp_int_t) == sizeof(long)) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy