if test "x$enable_wasm" = "xyes"; then
-CFLAGS="$CFLAGS -D_REENTRANT -D_GNU_SOURCE -DNO_UNALIGNED_ACCESS -s WASM=1 -DWASM -Os"
-CPPFLAGS="$CPPFLAGS -D_REENTRANT -DUSE_MMAP -D_GNU_SOURCE -DNO_UNALIGNED_ACCESS -s WASM=1 -DWASM -Os"
+CFLAGS="$CFLAGS -D_REENTRANT -D_GNU_SOURCE -DNO_UNALIGNED_ACCESS -s WASM=1"
+CPPFLAGS="$CPPFLAGS -D_REENTRANT -DUSE_MMAP -D_GNU_SOURCE -DNO_UNALIGNED_ACCESS -s WASM=1"
libdl="-ldl"
libgc_threads=pthreads
AC_CHECK_HEADERS(linux/magic.h)
# not 64 bit clean in cross-compile
-AC_CHECK_SIZEOF(void *, 4)
+if test "x$enable_wasm" = "xyes"; then
+AC_DEFINE(SIZEOF_VOID_P,4)
+AC_DEFINE(SIZEOF_LONG,4)
+ac_cv_sizeof_void_p="4"
+ac_cv_sizeof_long="4"
+else
+AC_CHECK_SIZEOF(void *)
+AC_CHECK_SIZEOF(long)
+fi
+
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(long long)
AC_CACHE_CHECK([for clang],
mono_cv_clang,[
HOST=WASM
arch_target=wasm
AC_DEFINE(TARGET_WASM, 1, [Target wasm])
+AC_DEFINE(HOST_WASM, 1, [Host wasm])
BTLS_SUPPORTED=no
with_tls=pthread
target_mach=no
AC_DEFINE(HAVE_CLASSIC_WINAPI_SUPPORT, 1, [Use classic Windows API support])
AC_DEFINE(HAVE_UWP_WINAPI_SUPPORT, 0, [Don't use UWP Windows API support])
-AC_CHECK_SIZEOF(int)
-AC_CHECK_SIZEOF(void *)
-AC_CHECK_SIZEOF(long)
-AC_CHECK_SIZEOF(long long)
AC_CHECK_FUNCS(strlcpy stpcpy strtok_r rewinddir vasprintf strerror_r)
AC_CHECK_FUNCS(getrlimit)
AC_CHECK_FUNCS(fork execv execve)
AM_CONDITIONAL(ARM, test x$TARGET = xARM)
AM_CONDITIONAL(ARM64, test x$TARGET = xARM64)
AM_CONDITIONAL(S390X, test x$TARGET = xS390X)
+AM_CONDITIONAL(WASM, test x$TARGET = xWASM)
AM_CONDITIONAL(HOST_X86, test x$HOST = xX86)
AM_CONDITIONAL(HOST_AMD64, test x$HOST = xAMD64)
AM_CONDITIONAL(HOST_ARM, test x$HOST = xARM)
#define G_BREAKPOINT()
#endif
+#if defined (HOST_WASM)
+#undef G_BREAKPOINT
+#define G_BREAKPOINT() do { printf ("MONO: BREAKPOINT\n"); abort (); } while (0)
+#endif
+
typedef @PIDTYPE@ GPid;
#endif
return g_strdup (&r[1]);
}
-#ifndef HAVE_STRTOK_R
+//wasm does have strtok_r even though autoconf fails to find
+#if !defined (HAVE_STRTOK_R) && !defined (HOST_WASM)
// This is from BSD's strtok_r
char *
MonoVTable *vtable;
- vtable = mono_class_vtable (domain, klass);
- g_assert (vtable); /* FIXME don't swallow the error */
+ vtable = mono_class_vtable_full (domain, klass, error);
+ if (!is_ok (error))
+ return NULL;
MonoObject *o = mono_object_new_specific_checked (vtable, error);
return o;
$(GLIB_LIBS) \
$(LIBICONV)
+wasm_sources = \
+ mini-wasm.c \
+ mini-wasm.h \
+ exceptions-wasm.c \
+ tramp-wasm.c
+
x86_sources = \
mini-x86.c \
mini-x86.h \
aot-compiler.h \
aot-compiler.c \
aot-runtime.c \
+ aot-runtime-wasm.c \
graph.c \
mini-codegen.c \
mini-exceptions.c \
regtests = $(filter-out $(regtests_DISABLED),$(regtests_UNIVERSAL))
+if WASM
+arch_sources = $(wasm_sources)
+arch_built=cpu-wasm.h
+arch_define=__wasm__
+endif
+
if X86
arch_sources = $(x86_sources)
arch_built=cpu-x86.h
# build dependency for the poor windows users
# $(arch_define) is the preprocessor symbol that enables all the opcodes
# for the specific platform in mini-ops.h
+
if CROSS_COMPILING
GENMDESC_PRG=perl $(srcdir)/genmdesc.pl $(arch_define) $(srcdir) $(GENMDESC_OPTS)
-else !CROSS_COMPILING
+else
+if WASM
+GENMDESC_PRG=perl $(srcdir)/genmdesc.pl $(arch_define) $(srcdir) $(GENMDESC_OPTS)
+else
GENMDESC_PRG=./genmdesc $(GENMDESC_OPTS)
+endif
endif !CROSS_COMPILING
+cpu-wasm.h: cpu-wasm.md genmdesc$(EXEEXT)
+ $(GENMDESC_PRG) cpu-wasm.h wasm_desc $(srcdir)/cpu-wasm.md
+
cpu-x86.h: cpu-x86.md genmdesc$(EXEEXT)
$(GENMDESC_PRG) cpu-x86.h x86_desc $(srcdir)/cpu-x86.md
TestHelpers.cs \
genmdesc.pl \
$(test_sources) \
+ $(wasm_sources) cpu-wasm.md \
$(x86_sources) cpu-x86.md \
$(amd64_sources) cpu-amd64.md \
$(ppc_sources) cpu-ppc.md cpu-ppc64.md \
--- /dev/null
+/**
+ * \file
+ * WASM AOT runtime
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include "mini.h"
+#include "interp/interp.h"
+
+#ifdef TARGET_WASM
+
+static void
+wasm_restore_context (void)
+{
+ g_error ("wasm_restore_context");
+}
+
+static void
+wasm_call_filter (void)
+{
+ g_error ("wasm_call_filter");
+}
+
+static void
+wasm_throw_exception (void)
+{
+ g_error ("wasm_throw_exception");
+}
+
+static void
+wasm_rethrow_exception (void)
+{
+ g_error ("wasm_rethrow_exception");
+}
+
+static void
+wasm_throw_corlib_exception (void)
+{
+ g_error ("wasm_throw_corlib_exception");
+}
+
+static char
+type_to_c (MonoType *t)
+{
+ if (t->byref)
+ return 'I';
+
+handle_enum:
+ switch (t->type) {
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ return 'I';
+ case MONO_TYPE_R4:
+ return 'F';
+ case MONO_TYPE_R8:
+ return 'D';
+ break;
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ return 'L';
+ case MONO_TYPE_VOID:
+ return 'V';
+ case MONO_TYPE_VALUETYPE:
+ if (t->data.klass->enumtype) {
+ t = mono_class_enum_basetype (t->data.klass);
+ goto handle_enum;
+ }
+
+ return 'I';
+ case MONO_TYPE_GENERICINST:
+ if (t->data.klass->valuetype)
+ return 'S';
+ return 'I';
+ default:
+ g_warning ("CANT TRANSLATE %s", mono_type_full_name (t));
+ return 'X';
+ }
+}
+
+#if SIZEOF_VOID_P == 4
+#define FIDX(x) ((x) * 2)
+#else
+#define FIDX(x) (x)
+#endif
+
+static void
+wasm_invoke_v (void *target_func, InterpMethodArguments *margs)
+{
+ void (*func)(void) = target_func;
+ func ();
+}
+
+static void
+wasm_invoke_vi (void *target_func, InterpMethodArguments *margs)
+{
+ void (*func)(gpointer a) = target_func;
+ func (margs->iargs [0]);
+}
+
+static void
+wasm_invoke_vii (void *target_func, InterpMethodArguments *margs)
+{
+ void (*func)(gpointer a, gpointer b) = target_func;
+ func (margs->iargs [0], margs->iargs [1]);
+}
+
+static void
+wasm_invoke_viii (void *target_func, InterpMethodArguments *margs)
+{
+ void (*func)(gpointer a, gpointer b, gpointer c) = target_func;
+ func (margs->iargs [0], margs->iargs [1], margs->iargs [2]);
+}
+
+static void
+wasm_invoke_viiii (void *target_func, InterpMethodArguments *margs)
+{
+ void (*func)(gpointer a, gpointer b, gpointer c, gpointer d) = target_func;
+ func (margs->iargs [0], margs->iargs [1], margs->iargs [2], margs->iargs [3]);
+}
+
+static void
+wasm_invoke_viiiii (void *target_func, InterpMethodArguments *margs)
+{
+ void (*func)(gpointer a, gpointer b, gpointer c, gpointer d, gpointer e) = target_func;
+ func (margs->iargs [0], margs->iargs [1], margs->iargs [2], margs->iargs [3], margs->iargs [4]);
+}
+
+static void
+wasm_invoke_viiiiii (void *target_func, InterpMethodArguments *margs)
+{
+ void (*func)(gpointer a, gpointer b, gpointer c, gpointer d, gpointer e, gpointer f) = target_func;
+ func (margs->iargs [0], margs->iargs [1], margs->iargs [2], margs->iargs [3], margs->iargs [4], margs->iargs [5]);
+}
+
+static void
+wasm_invoke_i (void *target_func, InterpMethodArguments *margs)
+{
+ int (*func)(void) = target_func;
+ int res = func ();
+ *(int*)margs->retval = res;
+}
+
+static void
+wasm_invoke_ii (void *target_func, InterpMethodArguments *margs)
+{
+ int (*func)(gpointer a) = target_func;
+ int res = func (margs->iargs [0]);
+ *(int*)margs->retval = res;
+}
+
+static void
+wasm_invoke_iii (void *target_func, InterpMethodArguments *margs)
+{
+ int (*func)(gpointer a, gpointer b) = target_func;
+ int res = func (margs->iargs [0], margs->iargs [1]);
+ *(int*)margs->retval = res;
+}
+
+static void
+wasm_invoke_iiii (void *target_func, InterpMethodArguments *margs)
+{
+ int (*func)(gpointer a, gpointer b, gpointer c) = target_func;
+ int res = func (margs->iargs [0], margs->iargs [1], margs->iargs [2]);
+ *(int*)margs->retval = res;
+}
+
+static void
+wasm_invoke_iiiii (void *target_func, InterpMethodArguments *margs)
+{
+ int (*func)(gpointer a, gpointer b, gpointer c, gpointer d) = target_func;
+ int res = func (margs->iargs [0], margs->iargs [1], margs->iargs [2], margs->iargs [3]);
+ *(int*)margs->retval = res;
+}
+
+static void
+wasm_invoke_iiiiii (void *target_func, InterpMethodArguments *margs)
+{
+ int (*func)(gpointer a, gpointer b, gpointer c, gpointer d, gpointer e) = target_func;
+ int res = func (margs->iargs [0], margs->iargs [1], margs->iargs [2], margs->iargs [3], margs->iargs [4]);
+ *(int*)margs->retval = res;
+}
+
+typedef union {
+ gint64 l;
+ struct {
+ gint32 lo;
+ gint32 hi;
+ } pair;
+} interp_pair;
+
+static void
+wasm_invoke_ll (void *target_func, InterpMethodArguments *margs)
+{
+ gint64 (*func)(gint64 a) = target_func;
+
+ interp_pair p;
+ p.pair.lo = (gint32)margs->iargs [0];
+ p.pair.hi = (gint32)margs->iargs [1];
+
+ gint64 res = func (p.l);
+ *(gint64*)margs->retval = res;
+}
+
+static void
+wasm_invoke_li (void *target_func, InterpMethodArguments *margs)
+{
+ gint64 (*func)(gpointer a) = target_func;
+ gint64 res = func (margs->iargs [0]);
+ *(gint64*)margs->retval = res;
+}
+
+static void
+wasm_invoke_lil (void *target_func, InterpMethodArguments *margs)
+{
+ gint64 (*func)(gpointer a, gint64 b) = target_func;
+
+ interp_pair p;
+ p.pair.lo = (gint32)margs->iargs [1];
+ p.pair.hi = (gint32)margs->iargs [2];
+
+ gint64 res = func (margs->iargs [0], p.l);
+ *(gint64*)margs->retval = res;
+}
+
+static void
+wasm_invoke_dd (void *target_func, InterpMethodArguments *margs)
+{
+ double (*func)(double a) = target_func;
+
+ double res = func (margs->fargs [FIDX (0)]);
+ *(double*)margs->retval = res;
+}
+
+static void
+wasm_invoke_ddd (void *target_func, InterpMethodArguments *margs)
+{
+ double (*func)(double a, double b) = target_func;
+
+ double res = func (margs->fargs [FIDX (0)], margs->fargs [FIDX (1)]);
+ *(double*)margs->retval = res;
+}
+
+
+
+static void
+wasm_invoke_vif (void *target_func, InterpMethodArguments *margs)
+{
+ void (*func)(gpointer a, float b) = target_func;
+
+ func (margs->iargs [0],
+ *(float*)&margs->fargs [FIDX (0)]);
+}
+
+static void
+wasm_invoke_viff (void *target_func, InterpMethodArguments *margs)
+{
+ void (*func)(gpointer a, float b, float c) = target_func;
+
+ func (margs->iargs [0],
+ *(float*)&margs->fargs [FIDX (0)],
+ *(float*)&margs->fargs [FIDX (1)]);
+}
+
+static void
+wasm_invoke_viffff (void *target_func, InterpMethodArguments *margs)
+{
+ void (*func)(gpointer a, float b, float c, float d, float e) = target_func;
+
+ func (margs->iargs [0],
+ *(float*)&margs->fargs [FIDX (0)],
+ *(float*)&margs->fargs [FIDX (1)],
+ *(float*)&margs->fargs [FIDX (2)],
+ *(float*)&margs->fargs [FIDX (3)]);
+}
+
+static void
+wasm_invoke_vifffffi (void *target_func, InterpMethodArguments *margs)
+{
+ void (*func)(gpointer a, float b, float c, float d, float e, float f, int g) = target_func;
+
+ func (margs->iargs [0],
+ *(float*)&margs->fargs [FIDX (0)],
+ *(float*)&margs->fargs [FIDX (1)],
+ *(float*)&margs->fargs [FIDX (2)],
+ *(float*)&margs->fargs [FIDX (3)],
+ *(float*)&margs->fargs [FIDX (4)],
+ *(float*)&margs->iargs [1]);
+}
+
+static void
+wasm_enter_icall_trampoline (void *target_func, InterpMethodArguments *margs)
+{
+ static char cookie [8];
+ static int c_count;
+
+ MonoMethodSignature *sig = margs->sig;
+
+ c_count = sig->param_count + sig->hasthis + 1;
+ cookie [0] = type_to_c (sig->ret);
+ if (sig->hasthis)
+ cookie [1] = 'I';
+ for (int i = 0; i < sig->param_count; ++i)
+ cookie [1 + sig->hasthis + i ] = type_to_c (sig->params [i]);
+ cookie [c_count] = 0;
+
+ if (!strcmp ("V", cookie))
+ wasm_invoke_v (target_func, margs);
+ else if (!strcmp ("VI", cookie))
+ wasm_invoke_vi (target_func, margs);
+ else if (!strcmp ("VII", cookie))
+ wasm_invoke_vii (target_func, margs);
+ else if (!strcmp ("VIII", cookie))
+ wasm_invoke_viii (target_func, margs);
+ else if (!strcmp ("VIIII", cookie))
+ wasm_invoke_viiii (target_func, margs);
+ else if (!strcmp ("VIIIII", cookie))
+ wasm_invoke_viiiii (target_func, margs);
+ else if (!strcmp ("VIIIIII", cookie))
+ wasm_invoke_viiiiii (target_func, margs);
+ else if (!strcmp ("I", cookie))
+ wasm_invoke_i (target_func, margs);
+ else if (!strcmp ("II", cookie))
+ wasm_invoke_ii (target_func, margs);
+ else if (!strcmp ("III", cookie))
+ wasm_invoke_iii (target_func, margs);
+ else if (!strcmp ("IIII", cookie))
+ wasm_invoke_iiii (target_func, margs);
+ else if (!strcmp ("IIIII", cookie))
+ wasm_invoke_iiiii (target_func, margs);
+ else if (!strcmp ("IIIIII", cookie))
+ wasm_invoke_iiiiii (target_func, margs);
+ else if (!strcmp ("LL", cookie))
+ wasm_invoke_ll (target_func, margs);
+ else if (!strcmp ("LI", cookie))
+ wasm_invoke_li (target_func, margs);
+ else if (!strcmp ("LIL", cookie))
+ wasm_invoke_lil (target_func, margs);
+ else if (!strcmp ("DD", cookie))
+ wasm_invoke_dd (target_func, margs);
+ else if (!strcmp ("DDD", cookie))
+ wasm_invoke_ddd (target_func, margs);
+ else if (!strcmp ("VIF", cookie))
+ wasm_invoke_vif (target_func, margs);
+ else if (!strcmp ("VIFF", cookie))
+ wasm_invoke_viff (target_func, margs);
+ else if (!strcmp ("VIFFFF", cookie))
+ wasm_invoke_viffff (target_func, margs);
+ else if (!strcmp ("VIFFFFFI", cookie))
+ wasm_invoke_vifffffi (target_func, margs);
+ else {
+ printf ("CANNOT HANDLE COOKIE %s\n", cookie);
+ g_assert (0);
+ }
+}
+
+gpointer
+mono_aot_get_trampoline_full (const char *name, MonoTrampInfo **out_tinfo)
+{
+ gpointer code = NULL;
+
+ if (!strcmp (name, "restore_context"))
+ code = wasm_restore_context;
+ else if (!strcmp (name, "call_filter"))
+ code = wasm_call_filter;
+ else if (!strcmp (name, "throw_exception"))
+ code = wasm_throw_exception;
+ else if (!strcmp (name, "rethrow_exception"))
+ code = wasm_rethrow_exception;
+ else if (!strcmp (name, "throw_corlib_exception"))
+ code = wasm_throw_corlib_exception;
+ else if (!strcmp (name, "enter_icall_trampoline"))
+ code = wasm_enter_icall_trampoline;
+
+ g_assert (code);
+
+ if (out_tinfo) {
+ MonoTrampInfo *tinfo = g_new0 (MonoTrampInfo, 1);
+ tinfo->code = code;
+ tinfo->code_size = 1;
+ tinfo->name = g_strdup (name);
+ tinfo->ji = NULL;
+ tinfo->unwind_ops = NULL;
+ tinfo->uw_info = NULL;
+ tinfo->uw_info_len = 0;
+ tinfo->owns_uw_info = FALSE;
+
+ *out_tinfo = tinfo;
+ }
+
+ return code;
+}
+#endif
g_assert_not_reached ();
}
+
+#ifndef TARGET_WASM
/*
* Return the trampoline identified by NAME from the mscorlib AOT file.
* On ppc64, this returns a function descriptor.
return mono_create_ftnptr_malloc ((guint8 *)load_function_full (amodule, name, out_tinfo));
}
+#endif
+
gpointer
mono_aot_get_trampoline (const char *name)
mono_aot_only = TRUE;
mono_use_interpreter = TRUE;
}
+ if (mono_aot_mode == MONO_AOT_MODE_INTERP_LLVMONLY) {
+ mono_aot_only = TRUE;
+ mono_use_interpreter = TRUE;
+ mono_llvm_only = TRUE;
+ }
}
mono_bool
--- /dev/null
+#include "mini.h"
+
+
+gpointer
+mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
+{
+ g_error ("mono_arch_get_call_filter");
+ return NULL;
+}
+
+gpointer
+mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
+{
+ g_error ("mono_arch_get_restore_context");
+ return NULL;
+}
+
+gboolean
+mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
+ MonoJitInfo *ji, MonoContext *ctx,
+ MonoContext *new_ctx, MonoLMF **lmf,
+ mgreg_t **save_locations,
+ StackFrameInfo *frame)
+{
+ g_error ("mono_arch_unwind_frame");
+ return FALSE;
+}
+
+gpointer
+mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
+{
+ g_error ("mono_arch_get_throw_corlib_exception");
+ return NULL;
+}
\ No newline at end of file
# this must include all the #defines used in mini-ops.h
my @defines = qw (__i386__ __x86_64__ __ppc__ __powerpc__ __ppc64__ __arm__
- __sparc__ sparc __s390__ s390 __alpha__ __mips__ __aarch64__);
+ __sparc__ sparc __s390__ s390 __alpha__ __mips__ __aarch64__ __wasm__);
my %table =();
my %template_table =();
my @opcodes = ();
if ($arch =~ "__aarch64__") {
$arch_define = "TARGET_ARM64";
}
-
+ if ($arch =~ "__wasm__") {
+ $arch_define = "TARGET_WASM";
+ }
parse_file ($arch_define, "$srcdir/mini-ops.h");
return;
$cpp .= " -D$arch_define $srcdir/mini-ops.h|";
int i8_align = mono_arm_i8_align ();
#endif
+#ifdef TARGET_WASM
+ margs->sig = sig;
+#endif
+
if (sig->hasthis)
margs->ilen++;
#define __MONO_MINI_INTERPRETER_H__
#include <mono/mini/mini.h>
+#ifdef TARGET_WASM
+#define INTERP_ICALL_TRAMP_IARGS 12
+#define INTERP_ICALL_TRAMP_FARGS 12
+#else
#define INTERP_ICALL_TRAMP_IARGS 12
#define INTERP_ICALL_TRAMP_FARGS 4
+#endif
struct _InterpMethodArguments {
size_t ilen;
double *fargs;
gpointer *retval;
size_t is_float_ret;
+#ifdef TARGET_WASM
+ MonoMethodSignature *sig;
+#endif
};
typedef struct _InterpMethodArguments InterpMethodArguments;
MONO_AOT_MODE_LLVMONLY,
/* Uses Interpreter, JIT is disabled and not allowed,
* equivalent to "--full-aot --interpreter" */
- MONO_AOT_MODE_INTERP
+ MONO_AOT_MODE_INTERP,
+ /* Same as INTERP, but use only llvm compiled code */
+ MONO_AOT_MODE_INTERP_LLVMONLY,
} MonoAotMode;
MONO_API void
#include "mini-arm64.h"
#elif defined(__mips__)
#include "mini-mips.h"
+#elif TARGET_WASM
+#include "mini-wasm.h"
#else
#error add arch specific include file in mini-arch.h
#endif
if (mono_ex->trace_ips) {
GList *trace_ips = NULL;
- gpointer ip = __builtin_return_address (0);
+ gpointer ip = RETURN_ADDRESS ();
size_t upper = mono_array_length (mono_ex->trace_ips);
--- /dev/null
+#include "mini.h"
+
+
+gpointer
+mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
+{
+ g_error ("mono_arch_get_this_arg_from_call");
+}
+
+gpointer
+mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg)
+{
+ g_error ("mono_arch_get_delegate_virtual_invoke_impl");
+}
+
+
+void
+mono_arch_cpu_init (void)
+{
+ // printf ("mono_arch_cpu_init\n");
+}
+
+void
+mono_arch_finish_init (void)
+{
+ // printf ("mono_arch_finish_init\n");
+}
+
+void
+mono_arch_init (void)
+{
+ // printf ("mono_arch_init\n");
+}
+
+void
+mono_arch_cleanup (void)
+{
+}
+
+void
+mono_arch_register_lowlevel_calls (void)
+{
+}
+
+void
+mono_arch_flush_register_windows (void)
+{
+}
+
+void
+mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
+{
+}
+
+
+MonoMethod*
+mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
+{
+ g_error ("mono_arch_find_static_call_vtable");
+ return (MonoMethod*) regs [MONO_ARCH_IMT_REG];
+}
+
+MonoVTable*
+mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
+{
+ g_error ("mono_arch_find_static_call_vtable");
+ return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG];
+}
+
+gpointer
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
+{
+ g_error ("mono_arch_build_imt_trampoline");
+}
+
+guint32
+mono_arch_cpu_enumerate_simd_versions (void)
+{
+ return 0;
+}
+
+guint32
+mono_arch_cpu_optimizations (guint32 *exclude_mask)
+{
+ return 0;
+}
+
+GSList*
+mono_arch_get_delegate_invoke_impls (void)
+{
+ g_error ("mono_arch_get_delegate_invoke_impls");
+ return NULL;
+}
+
+gpointer
+mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
+{
+ g_error ("mono_arch_get_delegate_invoke_impl");
+ return NULL;
+}
+
+mgreg_t
+mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
+{
+ g_error ("mono_arch_context_get_int_reg");
+ return 0;
+}
+
+int
+mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info)
+{
+ g_error ("mono_arch_get_argument_info");
+ return 0;
+
+}
+
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+ ext->lmf.previous_lmf = (gsize)prev_lmf;
+ /* Mark that this is a MonoLMFExt */
+ ext->lmf.previous_lmf = (gsize)(gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+}
+
+
+
+void
+mono_runtime_setup_stat_profiler (void)
+{
+ g_error ("mono_runtime_setup_stat_profiler");
+}
+
+
+void
+mono_runtime_shutdown_stat_profiler (void)
+{
+ g_error ("mono_runtime_shutdown_stat_profiler");
+}
+
+
+gboolean
+MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
+{
+ g_error ("mono_chain_signal");
+
+ return FALSE;
+}
+
+void
+mono_runtime_install_handlers (void)
+{
+}
+
+void
+mono_runtime_cleanup_handlers (void)
+{
+}
+
+gboolean
+mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info)
+{
+ g_error ("WASM systems don't support mono_thread_state_init_from_handle");
+ return FALSE;
+}
+
+
+/*
+The following functions don't belong here, but are due to laziness.
+*/
+
+//w32file-wasm.c
+gboolean
+mono_w32file_get_volume_information (const gunichar2 *path, gunichar2 *volumename, gint volumesize, gint *outserial, gint *maxcomp, gint *fsflags, gunichar2 *fsbuffer, gint fsbuffersize)
+{
+ g_error ("mono_w32file_get_volume_information");
+}
+
+
+//llvm builtin's that we should not have used in the first place
+
+
+//libc / libpthread missing bits from musl or shit we didn't detect :facepalm:
+int pthread_getschedparam (pthread_t thread, int *policy, struct sched_param *param)
+{
+ g_error ("pthread_getschedparam");
+ return 0;
+}
+
+int
+pthread_attr_getstacksize (const pthread_attr_t *restrict attr, size_t *restrict stacksize)
+{
+ return 65536; //wasm page size
+}
+
+int
+pthread_sigmask (int how, const sigset_t * restrict set, sigset_t * restrict oset)
+{
+ return 0;
+}
+
+
+int
+sigsuspend(const sigset_t *sigmask)
+{
+ g_error ("sigsuspend");
+ return 0;
+}
+
+int
+getdtablesize (void)
+{
+ return 256; //random constant that is the fd limit
+}
+
+void *
+getgrnam (const char *name)
+{
+ return NULL;
+}
+
+void *
+getgrgid (gid_t gid)
+{
+ return NULL;
+}
+
+int
+inotify_init (void)
+{
+ g_error ("inotify_init");
+}
+
+int
+inotify_rm_watch (int fd, int wd)
+{
+ g_error ("inotify_rm_watch");
+ return 0;
+}
+
+int
+inotify_add_watch (int fd, const char *pathname, uint32_t mask)
+{
+ g_error ("inotify_add_watch");
+ return 0;
+}
+
+int
+sem_timedwait (sem_t *sem, const struct timespec *abs_timeout)
+{
+ g_error ("sem_timedwait");
+ return 0;
+
+}
--- /dev/null
+#ifndef __MONO_MINI_WASM_H__
+#define __MONO_MINI_WASM_H__
+
+#include <mono/utils/mono-sigcontext.h>
+#include <mono/utils/mono-context.h>
+
+#define MONO_ARCH_CPU_SPEC mono_wasm_desc
+
+#define MONO_ARCH_HAVE_INIT_LMF_EXT 1
+
+#define MONO_MAX_IREGS 1
+#define MONO_MAX_FREGS 1
+
+#define WASM_REG_0 0
+
+
+struct MonoLMF {
+ /*
+ * If the second lowest bit is set to 1, then this is a MonoLMFExt structure, and
+ * the other fields are not valid.
+ */
+ gpointer previous_lmf;
+ gpointer lmf_addr;
+
+ /* This is only set in trampoline LMF frames */
+ MonoMethod *method;
+
+ gboolean top_entry;
+};
+
+typedef struct {
+ int dummy;
+} MonoCompileArch;
+
+#define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf) do { (lmf)->top_entry = TRUE; } while (0)
+
+#define MONO_CONTEXT_SET_LLVM_EXC_REG(ctx, exc) do { (ctx)->llvm_exc_reg = (gsize)exc; } while (0)
+
+#define MONO_INIT_CONTEXT_FROM_FUNC(ctx,start_func) do { \
+ MONO_CONTEXT_SET_IP ((ctx), (start_func)); \
+ MONO_CONTEXT_SET_BP ((ctx), (0)); \
+ MONO_CONTEXT_SET_SP ((ctx), (0)); \
+ } while (0)
+
+
+#define MONO_ARCH_VTABLE_REG WASM_REG_0
+#define MONO_ARCH_IMT_REG WASM_REG_0
+#define MONO_ARCH_RGCTX_REG WASM_REG_0
+
+#endif /* __MONO_MINI_WASM_H__ */
*/
void mono_interruption_checkpoint_from_trampoline (void);
+
+#if defined (HOST_WASM)
+
+#define RETURN_ADDRESS_N(N) NULL
+#define RETURN_ADDRESS() RETURN_ADDRESS_N(0)
+
+
+#elif defined (__GNUC__)
+
+#define RETURN_ADDRESS_N(N) (__builtin_extract_return_addr (__builtin_return_address (N)))
+#define RETURN_ADDRESS() RETURN_ADDRESS_N(0)
+
+#elif defined(_MSC_VER)
+
+#include <intrin.h>
+#pragma intrinsic(_ReturnAddress)
+
+#define RETURN_ADDRESS() _ReturnAddress()
+#define RETURN_ADDRESS_N(N) NULL
+
+#else
+
+#error "Missing return address intrinsics implementation"
+
+#endif
+
+
#endif /* __MONO_MINI_H__ */
# define fprintf(__ignore, ...) g_log ("mono-gc", G_LOG_LEVEL_MESSAGE, __VA_ARGS__)
#endif
-#ifdef __GNUC__
-
-#define RETURN_ADDRESS_N(N) (__builtin_extract_return_addr (__builtin_return_address (N)))
-#define RETURN_ADDRESS() RETURN_ADDRESS_N(0)
-
-#elif defined(_MSC_VER)
-
-#include <intrin.h>
-#pragma intrinsic(_ReturnAddress)
-
-#define RETURN_ADDRESS() _ReturnAddress()
-#define RETURN_ADDRESS_N(N) NULL
-
-#else
-
-#error "Missing return address intrinsics implementation"
-
-#endif
-
static MonoTraceSpec trace_spec;
static volatile gint32 output_lock = 0;
--- /dev/null
+#include "mini.h"
+
+
+gpointer
+mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len)
+{
+ g_error ("mono_arch_create_specific_trampoline");
+}
+
+guchar*
+mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInfo **info, gboolean aot)
+{
+ g_error ("mono_arch_create_generic_trampoline");
+}
+
+gpointer
+mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot)
+{
+ g_error ("mono_arch_create_rgctx_lazy_fetch_trampoline");
+}
+
+void
+mono_arch_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr)
+{
+ g_error ("mono_arch_patch_plt_entry");
+}
+
+gpointer
+mono_arch_get_enter_icall_trampoline (MonoTrampInfo **info)
+{
+ printf ("mono_arch_get_enter_icall_trampoline");
+ g_assert (0);
+ return NULL;
+}
+
+void
+mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr)
+{
+ g_error ("mono_arch_patch_callsite");
+}
+
+gpointer
+mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
+{
+ g_error ("mono_arch_get_unbox_trampoline");
+ return NULL;
+}
+
+gpointer
+mono_arch_get_static_rgctx_trampoline (gpointer arg, gpointer addr)
+{
+ g_error ("mono_arch_get_static_rgctx_trampoline");
+ return NULL;
+}
\ No newline at end of file
#endif
#endif
+#if defined (TARGET_WASM)
+#define DEFAULT_MAJOR SGEN_MAJOR_SERIAL
+#define DEFAULT_SWEEP_MODE SGEN_SWEEP_SERIAL
+#elif defined(HAVE_CONC_GC_AS_DEFAULT)
+/* Use concurrent major on deskstop platforms */
+#define DEFAULT_MAJOR SGEN_MAJOR_CONCURRENT
+#define DEFAULT_SWEEP_MODE SGEN_SWEEP_CONCURRENT
+#else
+#define DEFAULT_MAJOR SGEN_MAJOR_SERIAL
+#define DEFAULT_SWEEP_MODE SGEN_SWEEP_CONCURRENT
+#endif
+
+
+
/*
* Maximum level of debug to enable on this build.
* Making this a constant enables us to put logging in a lot of places and
#define safe_object_get_size sgen_safe_object_get_size
-#if defined(HAVE_CONC_GC_AS_DEFAULT)
-/* Use concurrent major on deskstop platforms */
-#define DEFAULT_MAJOR SGEN_MAJOR_CONCURRENT
-#else
-#define DEFAULT_MAJOR SGEN_MAJOR_SERIAL
-#endif
-
typedef enum {
SGEN_MAJOR_DEFAULT,
SGEN_MAJOR_SERIAL,
SWEEP_STATE_COMPACTING
};
+typedef enum {
+ SGEN_SWEEP_SERIAL = FALSE,
+ SGEN_SWEEP_CONCURRENT = TRUE,
+} SgenSweepMode;
+
static volatile int sweep_state = SWEEP_STATE_SWEPT;
static gboolean concurrent_mark;
-static gboolean concurrent_sweep = TRUE;
+static gboolean concurrent_sweep = DEFAULT_SWEEP_MODE;
int sweep_pool_context = -1;
#include <unistd.h>
#endif
-#if defined(_POSIX_VERSION)
+#if defined(_POSIX_VERSION) && !defined (HOST_WASM)
#include "mono/utils/mono-dl.h"
#include "mono/utils/mono-embed.h"
#ifdef _MSC_VER
// TODO: Find MSVC replacement for __builtin_unwind_init
#define SAVE_REGS_ON_STACK g_assert_not_reached ();
+#elif defined (HOST_WASM)
+//TODO: figure out wasm stack scanning
+#define SAVE_REGS_ON_STACK do {} while (0)
#else
#define SAVE_REGS_ON_STACK __builtin_unwind_init ();
#endif
#define round_down(addr, val) ((void*)((addr) & ~((val) - 1)))
-void
-mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize)
+int
+mono_threads_get_max_stack_size (void)
{
- *staddr = round_down ((size_t)&staddr, 65536); //WASM pagesize is 64k
- *stsize = 65536 * 4; //we say it's 4 pages, there isn't much that uses this beyond the GC
+ return 65536 * 8; //totally arbitrary, this value is actually useless until WASM supports multiple threads.
}
+
void
mono_threads_suspend_init_signals (void)
{
{
}
+//----
+
+gboolean
+mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2)
+{
+ return id1 == id2;
+}
+
+
+MonoNativeThreadId
+mono_native_thread_id_get (void)
+{
+ return (MonoNativeThreadId)1;
+}
+
+MONO_API gboolean
+mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg)
+{
+ g_error ("WASM doesn't support threading");
+}
+
+static const char *thread_name;
+
+void
+mono_native_thread_set_name (MonoNativeThreadId tid, const char *name)
+{
+ thread_name = g_strdup (name);
+}
+
+gboolean
+mono_native_thread_join (MonoNativeThreadId tid)
+{
+ g_error ("WASM doesn't support threading");
+ return FALSE;
+}
+
+//----
+
+gboolean
+mono_threads_platform_yield (void)
+{
+ return TRUE;
+}
+
+void
+mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize)
+{
+ *staddr = round_down ((size_t)&staddr, 65536); //WASM pagesize is 64k
+ *stsize = 65536 * 4; //we say it's 4 pages, there isn't much that uses this beyond the GC
+}
+
+
+gboolean
+mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *tid)
+{
+ g_error ("WASM doesn't support threading");
+ return FALSE;
+}
+
+void mono_threads_platform_init (void)
+{
+}
+
+void
+mono_threads_platform_exit (gsize exit_code)
+{
+ g_error ("WASM doesn't support threading");
+}
+
+gboolean
+mono_threads_platform_in_critical_region (MonoNativeThreadId tid)
+{
+ return FALSE;
+}
+
#endif
#include <netdb.h>
#endif
-#ifndef HAVE_INET_PTON
+//wasm does have inet_pton even though autoconf fails to find
+#if !defined (HAVE_INET_PTON) && !defined (HOST_WASM)
int
inet_pton (int family, const char *address, void *inaddrp)