diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 1ab63c1159..293d0df24b 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -66,6 +66,35 @@ jobs: nmake /f w3i6mv.nmk all testci testansi testpollnone shell: cmd + emscripten: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: emsdk + run: | + git clone https://github.com/emscripten-core/emsdk.git + cd emsdk + ./emsdk install latest + ./emsdk activate latest + - name: build via emscripten + run: | + source emsdk/emsdk_env.sh + mkdir build + cd build + emcc -I../code -o mps.o -c ../code/mps.c + emcc -Icode -o testlib.o -c ../code/testlib.c + emcc -Icode -o fmtdy.o -c ../code/fmtdy.c + emcc -Icode -o fmtdytst.o -c ../code/fmtdytst.c + emcc -Icode -o amsss.o -c ../code/amsss.c + emcc -o amsss amsss.o mps.o testlib.o fmtdy.o fmtdytst.o + - name: test via node + run: | + source emsdk/emsdk_env.sh + cd build + node ./amsss + # A. REFERENCES # diff --git a/code/.gitignore b/code/.gitignore index ff483930b8..d10117236b 100644 --- a/code/.gitignore +++ b/code/.gitignore @@ -4,6 +4,8 @@ anangc ananll ananmv +emj3ll +emj6ll fri3gc fri3ll fri6gc diff --git a/code/config.h b/code/config.h index 83f985a885..eb6deaaf84 100644 --- a/code/config.h +++ b/code/config.h @@ -506,6 +506,30 @@ #define VMJunkBYTE ((unsigned char)0xA9) #define VMParamSize (sizeof(Word)) +/* .feature.em: Emscripten feature specification + * + * The MPS needs the following symbols which are not defined by default: + * + * Source Symbols Header Feature + * =========== ========================= ============= ==================== + * djbench.c alloca _GNU_SOURCE + * eventtxt.c setenv _GNU_SOURCE + * gcbench.c alloca _GNU_SOURCE + * + * It is not possible to localize these feature specifications around + * the individual headers: all headers share a common set of features + * (via ) and so all sources in the same compilation unit + * must turn on the same set of features. + */ + +#if defined(MPS_OS_EM) + +#if !defined(_GNU_SOURCE) +#define _GNU_SOURCE +#endif + +#endif + /* .feature.li: Linux feature specification * diff --git a/code/emj3ll.gmk b/code/emj3ll.gmk new file mode 100644 index 0000000000..58bcc5e1ed --- /dev/null +++ b/code/emj3ll.gmk @@ -0,0 +1,70 @@ +# -*- makefile -*- +# +# emj3ll.gmk: BUILD FOR Emscripten/WebAssembly 32-bit/Clang PLATFORM +# +# $Id$ +# Copyright (c) 2001-2020 Ravenbrook Limited. See end of file for license. + +PFM = emj3ll + +MPMPF = \ + lockan.c \ + protan.c \ + prmcan.c \ + prmcanan.c \ + span.c \ + than.c \ + vman.c + +LIBS = -lm + +# We suppress unused warnings until the corresponding PR lands. +CFLAGS += -Wno-error=unused + +# We ask that memory growth be enabled rather than hardcoding +# the size of the WebAssembly memory. +# The limited postlink optimizations warning is from binaryen +# and emcc when debug info is requested in an optimized build +# as not all optimizations will be run in that scenario. +LINKFLAGS = \ + -s ALLOW_MEMORY_GROWTH \ + -Wno-error=limited-postlink-optimizations + +include ll.gmk + +CFLAGSCOMPILER += -DCONFIG_THREAD_SINGLE + +include comm.gmk + +CC=emcc +AR=emar + + +# C. COPYRIGHT AND LICENSE +# +# Copyright (C) 2001-2020 Ravenbrook Limited . +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the +# distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/code/emj6ll.gmk b/code/emj6ll.gmk new file mode 100644 index 0000000000..078b0e0535 --- /dev/null +++ b/code/emj6ll.gmk @@ -0,0 +1,76 @@ +# -*- makefile -*- +# +# emj6ll.gmk: BUILD FOR Emscripten/WebAssembly 64-bit/Clang PLATFORM +# +# $Id$ +# Copyright (c) 2001-2020 Ravenbrook Limited. See end of file for license. + +PFM = emj6ll + +MPMPF = \ + lockan.c \ + protan.c \ + prmcan.c \ + prmcanan.c \ + span.c \ + than.c \ + vman.c + +LIBS = -lm + +# Doing a 64 bit build issues a warning that this is experimental +# on every file and we don't want that to kill the build. +# We also suppress unused warnings until the corresponding PR lands. +CFLAGS += \ + -Wno-experimental \ + -Wno-error=unused \ + -s MEMORY64 + +# We ask that memory growth be enabled rather than hardcoding +# the size of the WebAssembly memory. +# The limited postlink optimizations warning is from binaryen +# and emcc when debug info is requested in an optimized build +# as not all optimizations will be run in that scenario. +LINKFLAGS = \ + -s ALLOW_MEMORY_GROWTH \ + -s MEMORY64 \ + -Wno-limited-postlink-optimizations + +include ll.gmk + +CFLAGSCOMPILER += -DCONFIG_THREAD_SINGLE + +include comm.gmk + +CC=emcc +AR=emar + + +# C. COPYRIGHT AND LICENSE +# +# Copyright (C) 2001-2020 Ravenbrook Limited . +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the +# distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/code/eventpy.c b/code/eventpy.c index c8990ddc5b..974f38f707 100644 --- a/code/eventpy.c +++ b/code/eventpy.c @@ -15,7 +15,7 @@ #include "event.h" /* See */ -#if defined(MPS_ARCH_A6) || defined(MPS_ARCH_I3) || defined(MPS_ARCH_I6) +#if defined(MPS_ARCH_A6) || defined(MPS_ARCH_I3) || defined(MPS_ARCH_I6) || defined(MPS_ARCH_J3) || defined(MPS_ARCH_J6) #define BYTE_ORDER "<" #else #error "Can't determine byte order for platform architecture." diff --git a/code/lockix.c b/code/lockix.c index 038a58dd0c..2c24837d84 100644 --- a/code/lockix.c +++ b/code/lockix.c @@ -31,8 +31,8 @@ #include "mpm.h" -#if !defined(MPS_OS_FR) && !defined(MPS_OS_LI) && !defined(MPS_OS_XC) -#error "lockix.c is specific to MPS_OS_FR, MPS_OS_LI or MPS_OS_XC" +#if !defined(MPS_OS_EM) && !defined(MPS_OS_FR) && !defined(MPS_OS_LI) && !defined(MPS_OS_XC) +#error "lockix.c is specific to MPS_OS_EM, MPS_OS_FR, MPS_OS_LI or MPS_OS_XC" #endif #include "lock.h" diff --git a/code/mps.c b/code/mps.c index 41c8d076af..b809189f4e 100644 --- a/code/mps.c +++ b/code/mps.c @@ -255,6 +255,19 @@ #include "spw3i6.c" /* Windows on x86-64 stack probe */ #include "mpsiw3.c" /* Windows interface layer extras */ +/* Emscripten */ + +#elif defined(MPS_PF_EMJ3LL) || defined(MPS_PF_EMJ6LL) + +#include "lockan.c" /* generic locks */ +#include "than.c" /* generic threads manager */ +#include "vman.c" /* malloc-based pseudo memory mapping */ +#include "protan.c" /* generic memory protection */ +#include "prmcan.c" /* generic operating system mutator context */ +#include "prmcanan.c" /* generic architecture mutator context */ +#include "span.c" /* generic stack probe */ + + #else #error "Unknown platform -- can't determine platform specific parts." diff --git a/code/mpstd.h b/code/mpstd.h index 7df1c2a12f..394fae61bc 100644 --- a/code/mpstd.h +++ b/code/mpstd.h @@ -392,6 +392,38 @@ #define MPS_PF_ALIGN 8 +#elif defined(__EMSCRIPTEN__) && defined(__wasm32__) +#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_EMJ3LL) +#error "specified CONFIG_PF_... inconsistent with detected emj3ll" +#endif +#define MPS_PF_EMJ3LL +#define MPS_PF_STRING "emj3ll" +#define MPS_OS_EM +#define MPS_ARCH_J3 +#define MPS_BUILD_LL +#define MPS_T_WORD unsigned long +#define MPS_T_ULONGEST unsigned long +#define MPS_WORD_WIDTH 32 +#define MPS_WORD_SHIFT 5 +#define MPS_PF_ALIGN 4 + + +#elif defined(__EMSCRIPTEN__) && defined(__wasm64__) +#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_EMJ6LL) +#error "specified CONFIG_PF_... inconsistent with detected emj6ll" +#endif +#define MPS_PF_EMJ6LL +#define MPS_PF_STRING "emj6ll" +#define MPS_OS_EM +#define MPS_ARCH_J6 +#define MPS_BUILD_LL +#define MPS_T_WORD unsigned long +#define MPS_T_ULONGEST unsigned long +#define MPS_WORD_WIDTH 64 +#define MPS_WORD_SHIFT 6 +#define MPS_PF_ALIGN 8 + + #else #error "The MPS Kit does not have a configuration for this platform out of the box; see manual/build.txt" #endif diff --git a/code/testlib.h b/code/testlib.h index f140b0a9e1..df37a1feb3 100644 --- a/code/testlib.h +++ b/code/testlib.h @@ -104,9 +104,9 @@ * tests to root out any incompatible assumptions by breaking. */ -#if defined(MPS_ARCH_A6) || defined(MPS_ARCH_I6) +#if defined(MPS_ARCH_A6) || defined(MPS_ARCH_I6) || defined(MPS_ARCH_J6) #define PRIwWORD "16" -#elif defined(MPS_ARCH_I3) +#elif defined(MPS_ARCH_I3) || defined(MPS_ARCH_J3) #define PRIwWORD "8" #else #error "How many beans make five?" diff --git a/code/testthr.h b/code/testthr.h index a50dad1e5d..a627bb714f 100644 --- a/code/testthr.h +++ b/code/testthr.h @@ -45,7 +45,8 @@ typedef struct testthr_t { void *result; /* result returned from start */ } testthr_t; -#elif defined(MPS_OS_FR) || defined(MPS_OS_LI) || defined(MPS_OS_XC) +/* FIXME: This isn't always true for MPS_OS_EM. Only when threads are enabled. */ +#elif defined(MPS_OS_EM) || defined(MPS_OS_FR) || defined(MPS_OS_LI) || defined(MPS_OS_XC) #include diff --git a/design/tests.txt b/design/tests.txt index eed0c4fc85..b3938c4160 100644 --- a/design/tests.txt +++ b/design/tests.txt @@ -311,6 +311,9 @@ least:: as defined by the `.ci.github.config`_. +_`.ci.run.emscripten`: On Windows, the CI services run commands to install +the Emscripten SDK and then perform some basic builds with it. + _`.ci.run.other.targets`: On some platforms we arrange to run the testansi, testpollnone, testratio, and testscheme targets. [Need to explain why, where, etc. RB 2023-01-15] diff --git a/manual/source/topic/platform.rst b/manual/source/topic/platform.rst index 3e3671d49a..d12d5313f9 100644 --- a/manual/source/topic/platform.rst +++ b/manual/source/topic/platform.rst @@ -17,6 +17,7 @@ six-character code breaks down into three pairs of characters: ====== ================ ==================== ``OS`` Operating system Constant ====== ================ ==================== +``em`` Emscripten :c:macro:`MPS_OS_EM` ``fr`` FreeBSD :c:macro:`MPS_OS_FR` ``li`` Linux :c:macro:`MPS_OS_LI` ``w3`` Windows :c:macro:`MPS_OS_W3` @@ -31,6 +32,8 @@ The second pair of characters names the processor architecture: ``a6`` ARM64 :c:macro:`MPS_ARCH_A6` ``i3`` Intel/AMD IA-32 :c:macro:`MPS_ARCH_I3` ``i6`` Intel/AMD x86-64 :c:macro:`MPS_ARCH_I6` +``j3`` WebAssembly (32 bit) :c:macro:`MPS_ARCH_WA` +``j6`` WebAssembly (64 bit) :c:macro:`MPS_ARCH_WA` ====== ====================== ====================== The third pair of characters names the compiler toolchain: @@ -92,6 +95,20 @@ Platform interface The MPS is not supported on IA-64 (Itanium). +.. c:macro:: MPS_ARCH_J3 + + A :term:`C` preprocessor macro that indicates, if defined, that + the target processor architecture of the compilation is 32-bit + WebAssembly. + + +.. c:macro:: MPS_ARCH_J6 + + A :term:`C` preprocessor macro that indicates, if defined, that + the target processor architecture of the compilation is 64-bit + WebAssembly. + + .. c:macro:: MPS_BUILD_GC A :term:`C` preprocessor macro that indicates, if defined, that @@ -113,6 +130,12 @@ Platform interface Studio. +.. c:macro:: MPS_OS_EM + + A :term:`C` preprocessor macro that indicates, if defined, that + the MPS was compiled for Emscripten. + + .. c:macro:: MPS_OS_FR A :term:`C` preprocessor macro that indicates, if defined, that @@ -143,6 +166,20 @@ Platform interface the :term:`natural alignment` of the :term:`platform`. +.. c:macro:: MPS_PF_EMJ3LL + + A :term:`C` preprocessor macro that indicates, if defined, that + the :term:`platform` consists of the Emscripten operating environment, + the 32-bit WebAssembly target architecture, and the Clang/LLVM compiler. + + +.. c:macro:: MPS_PF_EMJ6LL + + A :term:`C` preprocessor macro that indicates, if defined, that + the :term:`platform` consists of the Emscripten operating environment, + the 64-bit WebAssembly target architecture, and the Clang/LLVM compiler. + + .. c:macro:: MPS_PF_FRI3GC A :term:`C` preprocessor macro that indicates, if defined, that @@ -381,6 +418,8 @@ the Memory Pool System, with their current status. ========== ======================= Platform Status ========== ======================= +``emj3ll`` In development +``emj6ll`` In development ``fri3gc`` Supported ``fri3ll`` Supported ``fri4gc`` Corrected to ``fri3gc``