[mini] Add skeleton WebAssembly mini backend. It's not functional and some code needs...
authorRodrigo Kumpera <kumpera@gmail.com>
Tue, 22 Aug 2017 23:24:53 +0000 (16:24 -0700)
committerRodrigo Kumpera <kumpera@gmail.com>
Wed, 23 Aug 2017 23:04:58 +0000 (16:04 -0700)
The wasm backend is inspired on the x86 one with a few key differences:

1) It assumes a different aot runtime will be used to deal with all the weirdness of wasm.
In particular, it can run under MONO_AOT_MODE_INTERP_LLVMONLY without an actual working AOT compiler.

2) It's the only non-ISA based backend, so lots of weird things.
Like, no registers or addressable stack - for realsies.

configure.ac
mono/mini/Makefile.am.in
mono/mini/aot-runtime-wasm.c [new file with mode: 0644]
mono/mini/aot-runtime.c
mono/mini/cpu-wasm.md [new file with mode: 0644]
mono/mini/exceptions-wasm.c [new file with mode: 0644]
mono/mini/genmdesc.pl [changed mode: 0644->0755]
mono/mini/mini-arch.h
mono/mini/mini-wasm.c [new file with mode: 0644]
mono/mini/mini-wasm.h [new file with mode: 0644]
mono/mini/tramp-wasm.c [new file with mode: 0644]

index c3000129cfc00d37b5a7afe38fc1f658d2d3e734..5112665a15e9b850ef4a63f6acfc8aa6997fc902 100644 (file)
@@ -4340,6 +4340,7 @@ AM_CONDITIONAL(POWERPC64, test x$TARGET = xPOWERPC64)
 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)
index e33441b6d35a4218910e493ff5375292217e37b7..28fb9ee5b8d2fdbc6a19ed9ea8541ad4814c313b 100755 (executable)
@@ -312,6 +312,12 @@ genmdesc_LDADD = \
        $(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              \
@@ -456,6 +462,7 @@ common_sources = \
        aot-compiler.h          \
        aot-compiler.c          \
        aot-runtime.c           \
+       aot-runtime-wasm.c      \
        graph.c                 \
        mini-codegen.c          \
        mini-exceptions.c       \
@@ -541,6 +548,12 @@ endif
 
 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
@@ -687,12 +700,20 @@ GENMDESC_OPTS=
 # 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
 
@@ -882,6 +903,7 @@ EXTRA_DIST = TestDriver.cs \
        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  \
diff --git a/mono/mini/aot-runtime-wasm.c b/mono/mini/aot-runtime-wasm.c
new file mode 100644 (file)
index 0000000..7025fa8
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+ * \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
index d6c2486414f3278b960ec7480d50137ea27e7cee..4e86a5a3f32dc0f21460bfb23046f2a12f34f55b 100644 (file)
@@ -5143,6 +5143,8 @@ no_trampolines (void)
        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.
@@ -5159,6 +5161,8 @@ mono_aot_get_trampoline_full (const char *name, MonoTrampInfo **out_tinfo)
 
        return mono_create_ftnptr_malloc ((guint8 *)load_function_full (amodule, name, out_tinfo));
 }
+#endif
+
 
 gpointer
 mono_aot_get_trampoline (const char *name)
diff --git a/mono/mini/cpu-wasm.md b/mono/mini/cpu-wasm.md
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mono/mini/exceptions-wasm.c b/mono/mini/exceptions-wasm.c
new file mode 100644 (file)
index 0000000..63e72b0
--- /dev/null
@@ -0,0 +1,34 @@
+#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
old mode 100644 (file)
new mode 100755 (executable)
index 8c8e7ea..ae49ecb
@@ -20,7 +20,7 @@ sub INST_MAX   () {return 6;}
 
 # 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 = ();
@@ -88,7 +88,9 @@ sub load_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|";
index eb50de0f5e4aebe8a94ce6bea359635255c92c11..c49ed5a41d569c71627c295a89ac0de4365ac1aa 100644 (file)
@@ -25,6 +25,8 @@
 #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
diff --git a/mono/mini/mini-wasm.c b/mono/mini/mini-wasm.c
new file mode 100644 (file)
index 0000000..acf71e8
--- /dev/null
@@ -0,0 +1,265 @@
+#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;
+       
+}
diff --git a/mono/mini/mini-wasm.h b/mono/mini/mini-wasm.h
new file mode 100644 (file)
index 0000000..8205dc1
--- /dev/null
@@ -0,0 +1,50 @@
+#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__ */  
diff --git a/mono/mini/tramp-wasm.c b/mono/mini/tramp-wasm.c
new file mode 100644 (file)
index 0000000..50447fb
--- /dev/null
@@ -0,0 +1,54 @@
+#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