File riscv.patch of Package mono-core

From 2921130fa84b24287e6144d015b7010902cb18c2 Mon Sep 17 00:00:00 2001
From: Bernhard Urban-Forster <lewurm@gmail.com>
Date: Fri, 31 Jul 2020 01:20:45 +0200
Subject: [PATCH] [RISCV] Build fixes and simple exception handling (#20184)

* [riscv] add ELF machine definition

* [riscv] add mono_arch_get_cie_program to fix the build

* [interp] remove unused pointer

* [riscv] add offsets for MonoContext members

* [riscv] add pattern to nop_stub, so it is easier to spot in the debugger what caused the hang

* [riscv] minimal exception handling support
---
 mono/metadata/object-offsets.h  |   3 +
 mono/mini/exceptions-riscv.c    | 116 ++++++++++++++++++++++++++++----
 mono/mini/interp/interp.c       |   3 -
 mono/mini/mini-riscv.c          |  10 +++
 mono/mini/mini-runtime.c        |   2 +
 mono/utils/freebsd-elf_common.h |   1 +
 6 files changed, 119 insertions(+), 16 deletions(-)

Index: mono-6.12.0.107/mono/metadata/object-offsets.h
===================================================================
--- mono-6.12.0.107.orig/mono/metadata/object-offsets.h
+++ mono-6.12.0.107/mono/metadata/object-offsets.h
@@ -233,6 +233,9 @@ DECL_OFFSET(DynCallArgs, fpregs)
 DECL_OFFSET(DynCallArgs, n_stackargs)
 DECL_OFFSET(DynCallArgs, n_fpargs)
 DECL_OFFSET(DynCallArgs, n_fpret)
+#elif defined(TARGET_RISCV)
+DECL_OFFSET(MonoContext, gregs)
+DECL_OFFSET(MonoContext, fregs)
 #endif
 
 // Shared architecture offfsets
Index: mono-6.12.0.107/mono/mini/exceptions-riscv.c
===================================================================
--- mono-6.12.0.107.orig/mono/mini/exceptions-riscv.c
+++ mono-6.12.0.107/mono/mini/exceptions-riscv.c
@@ -13,14 +13,15 @@
 #ifndef DISABLE_JIT
 
 static gpointer
-nop_stub (void)
+nop_stub (unsigned int pattern)
 {
 	guint8 *code, *start;
 
 	start = code = mono_global_codeman_reserve (0x50);
 
-	/* nop */
-	riscv_addi (code, RISCV_X0, RISCV_X0, 0);
+	/* hang in debugger */
+	riscv_addi (code, RISCV_X0, RISCV_X0, pattern);
+	riscv_ebreak (code);
 
 	mono_arch_flush_icache (start, code - start);
 
@@ -30,43 +31,76 @@ nop_stub (void)
 gpointer
 mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
 {
-	*info = NULL;
-	return nop_stub ();
+	guint8 *start, *code;
+	MonoJumpInfo *ji = NULL;
+	GSList *unwind_ops = NULL;
+	int i, ctx_reg, size;
+
+	size = 512;
+	code = start = mono_global_codeman_reserve (size);
+
+	riscv_addi (code, RISCV_T0, RISCV_A0, 0);
+	ctx_reg = RISCV_T0;
+
+	/* Restore fregs */
+	for (i = 0; i < RISCV_N_FREGS; ++i)
+		riscv_flw (code, i, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, fregs) + (i * sizeof (double)));
+
+	/* Restore gregs */
+	for (i = 0; i < RISCV_N_FREGS; ++i) {
+		if (i == ctx_reg)
+			continue;
+		riscv_ld (code, i, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, gregs) + (i * sizeof (double)));
+	}
+
+	riscv_ld (code, ctx_reg, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, gregs) + (RISCV_ZERO * sizeof (double)));
+	riscv_jalr (code, RISCV_ZERO, ctx_reg, 0);
+	/* Not reached */
+	riscv_ebreak (code);
+
+	g_assert ((code - start) < size);
+	mono_arch_flush_icache (start, code - start);
+	MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
+
+	if (info)
+		*info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops);
+
+	return start;
 }
 
 gpointer
 mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
 {
 	*info = NULL;
-	return nop_stub ();
+	return nop_stub (0x37);
 }
 
 gpointer
 mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
 {
 	*info = NULL;
-	return nop_stub ();
+	return nop_stub (0x77);
 }
 
 gpointer
 mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
 {
 	*info = NULL;
-	return nop_stub ();
+	return nop_stub (0x88);
 }
 
 gpointer
 mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
 {
 	*info = NULL;
-	return nop_stub ();
+	return nop_stub (0x99);
 }
 
 gpointer
 mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
 {
 	*info = NULL;
-	return nop_stub ();
+	return nop_stub (0xaa);
 }
 
 #else
@@ -126,7 +160,63 @@ mono_arch_unwind_frame (MonoDomain *doma
                         MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf,
                         host_mgreg_t **save_locations, StackFrameInfo *frame)
 {
-	NOT_IMPLEMENTED;
+	gpointer ip = MONO_CONTEXT_GET_IP (ctx);
+
+	memset (frame, 0, sizeof (StackFrameInfo));
+	frame->ji = ji;
+
+	*new_ctx = *ctx;
+
+	if (ji != NULL) {
+		NOT_IMPLEMENTED;
+		host_mgreg_t regs [MONO_MAX_IREGS + 12 + 1];
+		guint8 *cfa;
+		guint32 unwind_info_len;
+		guint8 *unwind_info;
+
+
+		if (ji->is_trampoline)
+			frame->type = FRAME_TYPE_TRAMPOLINE;
+		else
+			frame->type = FRAME_TYPE_MANAGED;
+
+		unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
+
+		memcpy (regs, &new_ctx->gregs, sizeof (host_mgreg_t) * 32);
+
+		/* f8..f9 & f18..f27 are callee saved */
+		for (int i = 0; i < 2; i++)
+			(regs + MONO_MAX_IREGS) [i] = *((host_mgreg_t*)&new_ctx->fregs [RISCV_F8 + i]);
+		for (int i = 0; i < 10; i++)
+			(regs + MONO_MAX_IREGS) [i] = *((host_mgreg_t*)&new_ctx->fregs [RISCV_F18 + i]);
+
+		gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, (guint8*)ji->code_start,
+						   (guint8*)ji->code_start + ji->code_size,
+						   (guint8*)ip, NULL, regs, MONO_MAX_IREGS + 8,
+						   save_locations, MONO_MAX_IREGS, (guint8**)&cfa);
+
+		if (!success)
+			return FALSE;
+
+		memcpy (&new_ctx->gregs, regs, sizeof (host_mgreg_t) * 32);
+		for (int i = 0; i < 2; i++)
+			*((host_mgreg_t*)&new_ctx->fregs [RISCV_F8 + i]) = (regs + MONO_MAX_IREGS) [i];
+		for (int i = 0; i < 10; i++)
+			*((host_mgreg_t*)&new_ctx->fregs [RISCV_F18 + i]) = (regs + MONO_MAX_IREGS) [i];
+
+		new_ctx->gregs [RISCV_SP] = (host_mgreg_t)(gsize)cfa;
+
+		if (*lmf)
+			NOT_IMPLEMENTED;
+
+		/* we substract 1, so that the IP points into the call instruction */
+		new_ctx->gregs [RISCV_ZERO]--;
+
+		return TRUE;
+	} else if (*lmf) {
+		NOT_IMPLEMENTED;
+	}
+
 	return FALSE;
 }
 
@@ -178,11 +268,11 @@ mono_arch_setup_resume_sighandler_ctx (M
 void
 mono_arch_undo_ip_adjustment (MonoContext *context)
 {
-	NOT_IMPLEMENTED;
+	context->gregs[RISCV_ZERO]++;
 }
 
 void
 mono_arch_do_ip_adjustment (MonoContext *context)
 {
-	g_assert_not_reached ();
+	context->gregs[RISCV_ZERO]--;
 }
Index: mono-6.12.0.107/mono/mini/mini-riscv.c
===================================================================
--- mono-6.12.0.107.orig/mono/mini/mini-riscv.c
+++ mono-6.12.0.107/mono/mini/mini-riscv.c
@@ -239,6 +239,16 @@ mono_arch_find_static_call_vtable (host_
 	return (MonoVTable *) regs [MONO_ARCH_VTABLE_REG];
 }
 
+GSList*
+mono_arch_get_cie_program (void)
+{
+	GSList *l = NULL;
+
+	mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, RISCV_SP, 0);
+
+	return l;
+}
+
 host_mgreg_t
 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
 {
Index: mono-6.12.0.107/mono/utils/freebsd-elf_common.h
===================================================================
--- mono-6.12.0.107.orig/mono/utils/freebsd-elf_common.h
+++ mono-6.12.0.107/mono/utils/freebsd-elf_common.h
@@ -169,6 +169,7 @@ typedef struct {
 #define EM_TINYJ	61	/* Advanced Logic Corp. TinyJ processor. */
 #define EM_X86_64	62	/* Advanced Micro Devices x86-64 */
 #define	EM_AMD64	EM_X86_64	/* Advanced Micro Devices x86-64 (compat) */
+#define EM_RISCV	243	/* RISC-V. */
 
 /* Non-standard or deprecated. */
 #define EM_486		6	/* Intel i486. */
openSUSE Build Service is sponsored by