diff --git a/.gitignore b/.gitignore index 23bd48c86..794f52e36 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ *.lib *.lst *.o +*.wo *.obj *.rel *.src @@ -28,6 +29,7 @@ /romfs.img /staging /symtab_apps.c +/wasm cscope.out Make.dep .context diff --git a/Application.mk b/Application.mk index cd196b740..c54829a13 100644 --- a/Application.mk +++ b/Application.mk @@ -262,3 +262,9 @@ distclean:: clean $(call DELFILE, .depend) -include Make.dep + +ifeq ($(WASM_BUILD),y) + ifneq ($(CONFIG_INTERPRETERS_WAMR)$(CONFIG_INTERPRETERS_WAMR3),) + include $(APPDIR)$(DELIM)interpreters$(DELIM)Wasm.mk + endif # CONFIG_INTERPRETERS_WAMR || CONFIG_INTERPRETERS_WAMR3 +endif # WASM_BUILD diff --git a/Make.defs b/Make.defs index f1f66f4c4..d87cd0072 100644 --- a/Make.defs +++ b/Make.defs @@ -65,7 +65,8 @@ BINDIR ?= $(APPDIR)$(DELIM)bin # The final build target -BIN ?= $(APPDIR)$(DELIM)libapps$(LIBEXT) +BIN ?= $(APPDIR)$(DELIM)libapps$(LIBEXT) +WBIN ?= $(APPDIR)$(DELIM)wasm$(DELIM)libwasm$(LIBEXT) # Tools @@ -105,3 +106,19 @@ CFLAGS += ${INCDIR_PREFIX}"$(APPDIR)$(DELIM)include" CXXFLAGS += ${INCDIR_PREFIX}"$(APPDIR)$(DELIM)include" NUTTXLIB ?= $(call CONVERT_PATH,$(TOPDIR)$(DELIM)staging) + +# Function to get entry index + +define GETINDEX + $(eval i=1) + $(eval entry=) + $(foreach e,$(2), \ + $(if $(filter $(notdir $(1)),$(notdir $(e))), \ + $(eval entry=$(1)), \ + $(if $(entry), \ + ,$(eval i=$(shell expr $(i) + 1)) \ + ) \ + ) \ + ) + $(i) +endef diff --git a/Makefile b/Makefile index 28a3b0c77..e21ddd09e 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,10 @@ export APPDIR = $(CURDIR) include $(APPDIR)/Make.defs +ifeq ($(CONFIG_INTERPRETERS_WAMR),y) + include $(APPDIR)$(DELIM)interpreters$(DELIM)wamr$(DELIM)Toolchain.defs +endif + # The GNU make CURDIR will always be a POSIX-like path with forward slashes # as path segment separators. This is fine for the above inclusions but # will cause problems later for the native build. If we know that this is @@ -101,6 +105,9 @@ $(BIN): $(foreach SDIR, $(CONFIGURED_APPS), $(SDIR)_all) $(Q) for app in ${CONFIGURED_APPS}; do \ $(MAKE) -C "$${app}" archive ; \ done +ifeq ($(CONFIG_INTERPRETERS_WAMR),y) + $(call LINK_WAMR) +endif endif else @@ -118,6 +125,9 @@ $(SYMTABOBJ): %$(OBJEXT): %.c $(BIN): $(SYMTABOBJ) $(call ARCHIVE_ADD, $(call CONVERT_PATH,$(BIN)), $^) +ifeq ($(CONFIG_INTERPRETERS_WAMR),y) + $(call LINK_WAMR) +endif endif # !CONFIG_BUILD_LOADABLE @@ -211,4 +221,5 @@ distclean: $(foreach SDIR, $(CLEANDIRS), $(SDIR)_distclean) $(call DELFILE, $(BIN)) $(call DELFILE, Kconfig) $(call DELDIR, $(BINDIR)) + $(call DELDIR, wasm) $(call CLEAN) diff --git a/benchmarks/coremark/Makefile b/benchmarks/coremark/Makefile index 50012e9f5..31277712e 100644 --- a/benchmarks/coremark/Makefile +++ b/benchmarks/coremark/Makefile @@ -105,4 +105,8 @@ STACKSIZE += $(CONFIG_COREMARK_STACKSIZE) MAINSRC += core_main.c +# Build with WebAssembly when CONFIG_INTERPRETERS_WAMR is enabled + +WASM_BUILD = y + include $(APPDIR)/Application.mk diff --git a/examples/hello/Makefile b/examples/hello/Makefile index 1a95f1ae9..9a73b642c 100644 --- a/examples/hello/Makefile +++ b/examples/hello/Makefile @@ -31,4 +31,12 @@ MODULE = $(CONFIG_EXAMPLES_HELLO) MAINSRC = hello_main.c +# Build with WebAssembly when CONFIG_INTERPRETERS_WAMR is enabled + +WASM_BUILD = y + +# Mode of WebAssembly Micro Runtime + +WAMR_MODE = AOT + include $(APPDIR)/Application.mk diff --git a/interpreters/Wasm.mk b/interpreters/Wasm.mk new file mode 100644 index 000000000..8e7f5890f --- /dev/null +++ b/interpreters/Wasm.mk @@ -0,0 +1,68 @@ +############################################################################ +# apps/interpreters/Wasm.mk +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifeq ($(WASM_BUILD),y) + ifneq ($(CONFIG_INTERPRETERS_WAMR)$(CONFIG_INTERPRETERS_WAMR3),) + +WASM_INITIAL_MEMORY ?= 65536 +STACKSIZE ?= $(CONFIG_DEFAULT_TASK_STACKSIZE) +PRIORITY ?= SCHED_PRIORITY_DEFAULT + +# Wamr mode: +# INT: Interpreter (Default) +# AOT: Ahead-of-Time +# XIP: Execution In Place +# JIT: Just In Time + +WAMR_MODE ?= INT + +# WebAssembly Micro Runtime Toolchain Setting + +-include $(APPDIR)$(DELIM)interpreters$(DELIM)wamr$(DELIM)Toolchain.defs + +# Targets follow + +.PRECIOUS: $(WBIN) + +WSRCS := $(MAINSRC) $(CSRCS) +WOBJS := $(WSRCS:%.c=%.wo) + +all:: $(WBIN) + +$(WOBJS): %.wo : %.c + $(Q) $(WCC) $(WCFLAGS) -c $^ -o $@ + +$(WBIN): $(WOBJS) + $(shell mkdir -p $(APPDIR)/wasm) + $(Q) $(WAR) $@ $(filter-out $(MAINSRC:%.c=%.wo),$^) + $(foreach main,$(MAINSRC), \ + $(eval mainindex=$(strip $(call GETINDEX,$(main),$(MAINSRC)))) \ + $(eval dstname=$(shell echo $(main:%.c=%.wo) | sed -e 's/\//_/g')) \ + $(shell cp -rf $(strip $(main:%.c=%.wo)) \ + $(strip $(APPDIR)/wasm/$(word $(mainindex),$(PROGNAME))#$(WASM_INITIAL_MEMORY)#$(STACKSIZE)#$(PRIORITY)#$(WAMR_MODE)#$(dstname)) \ + ) \ + ) + +clean:: + $(call DELFILE, $(WOBJS)) + $(call DELFILE, $(WBIN)) + + endif # CONFIG_INTERPRETERS_WAMR || CONFIG_INTERPRETERS_WAMR3 +endif # WASM_BUILD diff --git a/interpreters/wamr/Toolchain.defs b/interpreters/wamr/Toolchain.defs new file mode 100644 index 000000000..0d4d9f9c3 --- /dev/null +++ b/interpreters/wamr/Toolchain.defs @@ -0,0 +1,149 @@ +############################################################################ +# apps/interpreters/wamr/Toolchain.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +# Wasm32 toolchain setting +# Target: wasm32-unknown-wasi + +WCC ?= $(WASI_SDK_PATH)/bin/clang +WAR ?= $(WASI_SDK_PATH)/bin/llvm-ar rcs +WRC ?= wamrc +WSYSROOT ?= $(TOPDIR) + +CFLAGS_STRIP = -fsanitize=kernel-address -fsanitize=address -fsanitize=undefined +CFLAGS_STRIP += $(ARCHCPUFLAGS) $(ARCHCFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(ARCHOPTIMIZATION) $(EXTRAFLAGS) + +WCFLAGS += $(filter-out $(CFLAGS_STRIP),$(CFLAGS)) +WCFLAGS += --sysroot=$(WSYSROOT) -nostdlib -D__NuttX__ + +WLDFLAGS = -z stack-size=$(STACKSIZE) -Wl,--initial-memory=$(INITIAL_MEMORY) +WLDFLAGS += -Wl,--export=main -Wl,--export=__main_argc_argv +WLDFLAGS += -Wl,--export=__heap_base -Wl,--export=__data_end +WLDFLAGS += -Wl,--no-entry -Wl,--strip-all -Wl,--allow-undefined + +ifeq ($(CONFIG_ARCH_ARM),y) + ifeq ($(CONFIG_ARM_THUMB),y) + WTARGET = thumb + else + WTARGET = arm + endif + + ifeq ($(CONFIG_ARCH_CORTEXM85),y) + WTARGET := $(WTARGET)v8.1m.main + WCPU = --cpu=cortex-m85 + else ifeq ($(CONFIG_ARCH_CORTEXM55),y) + WTARGET := $(WTARGET)v8.1m.main + WCPU = --cpu=cortex-m55 + else ifeq ($(CONFIG_ARCH_CORTEXM35P),y) + WTARGET := $(WTARGET)v8m.main + WCPU = --cpu=cortex-m35p + else ifeq ($(CONFIG_ARCH_CORTEXM33),y) + WTARGET := $(WTARGET)v8m.main + WCPU = --cpu=cortex-m33 + else ifeq ($(CONFIG_ARCH_CORTEXM23),y) + WTARGET := $(WTARGET)v8m.main + WCPU = --cpu=cortex-m23 + else ifeq ($(CONFIG_ARCH_CORTEXM7),y) + WTARGET := $(WTARGET)v7em + WCPU = --cpu=cortex-m7 + else ifeq ($(CONFIG_ARCH_CORTEXM4),y) + WTARGET := $(WTARGET)v7em + WCPU = --cpu=cortex-m4 + else ifeq ($(CONFIG_ARCH_CORTEXM3),y) + WTARGET := $(WTARGET)v7em + WCPU = --cpu=cortex-m3 + else ifeq ($(CONFIG_ARCH_CORTEXM0),y) + WTARGET := $(WTARGET)v6m + WCPU = --cpu=cortex-m0 + endif + + ifeq ($(CONFIG_ARCH_CORTEXA5),y) + WTARGET := $(WTARGET)armv7 + WCPU = --cpu=cortex-a5 + else ifeq ($(CONFIG_ARCH_CORTEXA7),y) + WTARGET := $(WTARGET)armv7 + WCPU = --cpu=cortex-a7 + else ifeq ($(CONFIG_ARCH_CORTEXA8),y) + WTARGET := $(WTARGET)armv8a + WCPU = --cpu=cortex-a8 + else ifeq ($(CONFIG_ARCH_CORTEXA9),y) + WTARGET := $(WTARGET)armv7 + WCPU = --cpu=cortex-a9 + endif + + ifeq ($(CONFIG_ARCH_CORTEXR4),y) + WTARGET := $(WTARGET)armv7 + WCPU = --cpu=cortex-r4 + else ifeq ($(CONFIG_ARCH_CORTEXR5),y) + WTARGET := $(WTARGET)armv7 + WCPU = --cpu=cortex-r5 + else ifeq ($(CONFIG_ARCH_CORTEXR7),y) + WTARGET := $(WTARGET)armv7 + WCPU = --cpu=cortex-r7 + endif + +else ifeq ($(CONFIG_ARCH_RISCV),y) + ifeq ($(CONFIG_ARCH_RV64),y) + WTARGET = riscv64 + else + WTARGET = riscv32 + endif +else ifeq ($(CONFIG_ARCH_XTENSA),y) + WTARGET = xtensa +else ifeq ($(CONFIG_ARCH_X86_64),y) + WTARGET = x86_64 +else ifeq ($(CONFIG_ARCH_X86),y) + WTARGET = i386 +else ifeq ($(CONFIG_ARCH_MIPS),y) + WTARGET = mips +else ifeq ($(CONFIG_ARCH_SIM),y) + RCFLAGS += --disable-simd + ifeq ($(CONFIG_SIM_M32),y) + WTARGET = i386 + else + WTARGET = x86_64 + endif +endif + +RCFLAGS += --target=$(WTARGET) $(WCPU) + +define LINK_WAMR + $(if $(wildcard $(APPDIR)$(DELIM)wasm$(DELIM)*.wo), \ + $(foreach bin,$(wildcard $(APPDIR)$(DELIM)wasm$(DELIM)*.wo), \ + $(eval INITIAL_MEMORY=$(shell echo $(notdir $(bin)) | cut -d'#' -f2)) \ + $(eval STACKSIZE=$(shell echo $(notdir $(bin)) | cut -d'#' -f3)) \ + $(eval PROGNAME=$(shell echo $(notdir $(bin)) | cut -d'#' -f1)) \ + $(eval WAMRMODE=$(shell echo $(notdir $(bin)) | cut -d'#' -f5)) \ + $(shell $(WCC) $(bin) $(WBIN) $(WCFLAGS) $(WLDFLAGS) -o $(APPDIR)$(DELIM)wasm$(DELIM)$(PROGNAME).wasm) \ + $(if $(CONFIG_INTERPRETERS_WAMR_AOT), \ + $(if $(filter AOT,$(WAMRMODE)), \ + $(info Wamrc Generate AoT: $(APPDIR)$(DELIM)wasm$(DELIM)$(PROGNAME).aot) \ + $(shell $(WRC) $(RCFLAGS) -o $(APPDIR)$(DELIM)wasm$(DELIM)$(PROGNAME).aot \ + $(APPDIR)$(DELIM)wasm$(DELIM)$(PROGNAME).wasm > /dev/null), \ + $(if $(filter XIP,$(WAMRMODE)), \ + $(info Wamrc Generate XiP: $(APPDIR)$(DELIM)wasm$(DELIM)$(PROGNAME).xip) \ + $(shell $(WRC) $(RCFLAGS) --enable-indirect-mode --disable-llvm-intrinsics \ + -o $(APPDIR)$(DELIM)wasm$(DELIM)$(PROGNAME).xip \ + $(APPDIR)$(DELIM)wasm$(DELIM)$(PROGNAME).wasm > /dev/null) \ + ) \ + ) \ + ) \ + ) \ + ) +endef