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)
$(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 void
+wasm_enter_icall_trampoline (void *target_func, InterpMethodArguments *margs)
+{
+ g_error ("wasm_enter_icall_trampoline");
+
+}
+
+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
\ No newline at end of file
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)
--- /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|";
#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
--- /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
+gpointer
+llvm_returnaddress (void)
+{
+ g_error ("llvm_returnaddress");
+ return NULL;
+}
+
+void
+llvm_eh_unwind_init (void)
+{
+ g_error ("llvm_eh_unwind_init");
+}
+
+
+//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__ */
--- /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