6
6
#include "mini-runtime.h"
7
7
8
8
#include <mono/metadata/abi-details.h>
9
+ #include <mono/metadata/tokentype.h>
9
10
#include <mono/utils/mono-sigcontext.h>
10
11
#include "mono/utils/mono-tls-inline.h"
11
12
@@ -67,18 +68,160 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
67
68
return start ;
68
69
}
69
70
71
+ void
72
+ mono_riscv_throw_exception (gpointer arg , host_mgreg_t pc , host_mgreg_t * int_regs , gdouble * fp_regs , gboolean corlib , gboolean rethrow , gboolean preserve_ips ){
73
+ ERROR_DECL (error );
74
+ MonoContext ctx ;
75
+ MonoObject * exc = NULL ;
76
+ guint32 ex_token_index , ex_token ;
77
+ if (!corlib )
78
+ exc = (MonoObject * )arg ;
79
+ else {
80
+ ex_token_index = (guint64 )arg ;
81
+ ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index ;
82
+ exc = (MonoObject * )mono_exception_from_token (mono_defaults .corlib , ex_token );
83
+ }
84
+
85
+ /* Adjust pc so it points into the call instruction */
86
+ pc -= 4 ;
87
+
88
+ /* Initialize a ctx based on the arguments */
89
+ memset (& ctx , 0 , sizeof (MonoContext ));
90
+ memcpy (& (ctx .gregs [0 ]), int_regs , sizeof (host_mgreg_t ) * RISCV_N_GREGS );
91
+ memcpy (& (ctx .fregs [0 ]), fp_regs , sizeof (host_mgreg_t ) * RISCV_N_FREGS );
92
+
93
+ ctx .gregs [0 ] = pc ;
94
+
95
+ if (mono_object_isinst_checked (exc , mono_defaults .exception_class , error )) {
96
+ MonoException * mono_ex = (MonoException * )exc ;
97
+ if (!rethrow && !mono_ex -> caught_in_unmanaged ) {
98
+ mono_ex -> stack_trace = NULL ;
99
+ mono_ex -> trace_ips = NULL ;
100
+ } else if (preserve_ips ) {
101
+ mono_ex -> caught_in_unmanaged = TRUE;
102
+ }
103
+ }
104
+
105
+ mono_error_assert_ok (error );
106
+
107
+ mono_handle_exception (& ctx , exc );
108
+
109
+ mono_restore_context (& ctx );
110
+ }
111
+
70
112
gpointer
71
113
mono_arch_get_call_filter (MonoTrampInfo * * info , gboolean aot )
72
114
{
73
115
* info = NULL ;
74
116
return nop_stub (0x37 );
75
117
}
76
118
119
+ static gpointer
120
+ get_throw_trampoline (int size , gboolean corlib , gboolean rethrow , gboolean llvm , gboolean resume_unwind , const char * tramp_name , MonoTrampInfo * * info , gboolean aot , gboolean preserve_ips ){
121
+ guint8 * start , * code ;
122
+ MonoJumpInfo * ji = NULL ;
123
+ GSList * unwind_ops = NULL ;
124
+ int i , offset , gregs_offset , fregs_offset , frame_size , num_fregs ;
125
+
126
+ code = start = mono_global_codeman_reserve (size );
127
+
128
+ /* This will being called by JITted code, the exception object/type token is in A0 */
129
+
130
+ /* Compute stack frame size and offsets */
131
+ offset = 0 ;
132
+ /* ra & fp */
133
+ offset += 2 * sizeof (host_mgreg_t );
134
+
135
+ /* gregs */
136
+ offset += RISCV_N_GREGS * sizeof (host_mgreg_t );
137
+ gregs_offset = offset ;
138
+
139
+ /* fregs */
140
+ num_fregs = RISCV_N_FREGS ;
141
+ offset += num_fregs * sizeof (host_mgreg_t );
142
+ fregs_offset = offset ;
143
+ frame_size = ALIGN_TO (offset , MONO_ARCH_FRAME_ALIGNMENT );
144
+
145
+ MINI_BEGIN_CODEGEN ();
146
+
147
+ /* Setup a frame */
148
+ g_assert (RISCV_VALID_I_IMM (- frame_size ));
149
+ riscv_addi (code , RISCV_SP , RISCV_SP , - frame_size );
150
+ code = mono_riscv_emit_store (code , RISCV_RA , RISCV_SP , frame_size - sizeof (host_mgreg_t ), 0 );
151
+ code = mono_riscv_emit_store (code , RISCV_FP , RISCV_SP , frame_size - 2 * sizeof (host_mgreg_t ), 0 );
152
+ riscv_addi (code , RISCV_FP , RISCV_SP , frame_size );
153
+
154
+ /* Save gregs */
155
+ code = mono_riscv_emit_store_stack (code , 0xffffffff , RISCV_FP , - gregs_offset , FALSE);
156
+ if (corlib && !llvm )
157
+ /* The real ra is in A1 */
158
+ code = mono_riscv_emit_store (code , RISCV_A1 , RISCV_FP , - gregs_offset + (RISCV_RA * sizeof (host_mgreg_t )), 0 );
159
+
160
+ /* Save previous fp/sp */
161
+ code = mono_riscv_emit_load (code , RISCV_T0 , RISCV_FP , -2 * sizeof (host_mgreg_t ), 0 );
162
+ code = mono_riscv_emit_store (code , RISCV_T0 , RISCV_FP , - gregs_offset + (RISCV_FP * sizeof (host_mgreg_t )), 0 );
163
+ // current fp is previous sp
164
+ code = mono_riscv_emit_store (code , RISCV_FP , RISCV_FP , - gregs_offset + (RISCV_SP * sizeof (host_mgreg_t )), 0 );
165
+
166
+ /* Save fregs */
167
+ if (riscv_stdext_f || riscv_stdext_d )
168
+ code = mono_riscv_emit_store_stack (code , 0xffffffff , RISCV_FP , - fregs_offset , TRUE);
169
+
170
+ /* Call the C trampoline function */
171
+ /* Arg1 = exception object/type token */
172
+ // riscv_addi (code, RISCV_A0, RISCV_A0, 0);
173
+ /* Arg2 = caller ip, should be return address in this case */
174
+ if (corlib ) {
175
+ // caller ip are set to A1 already
176
+ if (llvm )
177
+ NOT_IMPLEMENTED ;
178
+ } else
179
+ code = mono_riscv_emit_load (code , RISCV_A1 , RISCV_FP , - sizeof (host_mgreg_t ), 0 );
180
+ /* Arg 3 = gregs */
181
+ riscv_addi (code , RISCV_A2 , RISCV_FP , - gregs_offset );
182
+ /* Arg 4 = fregs */
183
+ riscv_addi (code , RISCV_A3 , RISCV_FP , - fregs_offset );
184
+ /* Arg 5 = corlib */
185
+ riscv_addi (code , RISCV_A4 , RISCV_ZERO , corlib ? 1 : 0 );
186
+ /* Arg 6 = rethrow */
187
+ riscv_addi (code , RISCV_A5 , RISCV_ZERO , rethrow ? 1 : 0 );
188
+ if (!resume_unwind ) {
189
+ /* Arg 7 = preserve_ips */
190
+ riscv_addi (code , RISCV_A6 , RISCV_ZERO , preserve_ips ? 1 : 0 );
191
+ }
192
+
193
+ /* Call the function */
194
+ if (aot ) {
195
+ NOT_IMPLEMENTED ;
196
+ } else {
197
+ gpointer icall_func ;
198
+
199
+ if (resume_unwind )
200
+ // icall_func = (gpointer)mono_riscv_resume_unwind;
201
+ NOT_IMPLEMENTED ;
202
+ else
203
+ icall_func = (gpointer )mono_riscv_throw_exception ;
204
+
205
+ code = mono_riscv_emit_imm (code , RISCV_RA , (guint64 )icall_func );
206
+ }
207
+ riscv_jalr (code , RISCV_ZERO , RISCV_RA , 0 );
208
+ /* This shouldn't return */
209
+ /* hang in debugger */
210
+ riscv_ebreak (code );
211
+
212
+ g_assert ((code - start ) < size );
213
+ MINI_END_CODEGEN (start , code - start , MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING , NULL );
214
+
215
+ if (info )
216
+ * info = mono_tramp_info_create (tramp_name , start , code - start , ji , unwind_ops );
217
+
218
+ return MINI_ADDR_TO_FTNPTR (start );
219
+ }
220
+
77
221
gpointer
78
222
mono_arch_get_throw_exception (MonoTrampInfo * * info , gboolean aot )
79
223
{
80
- * info = NULL ;
81
- return nop_stub (0x77 );
224
+ return get_throw_trampoline (384 , FALSE, FALSE, FALSE, FALSE, "throw_exception" , info , aot , FALSE);
82
225
}
83
226
84
227
gpointer
@@ -98,8 +241,7 @@ mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
98
241
gpointer
99
242
mono_arch_get_throw_corlib_exception (MonoTrampInfo * * info , gboolean aot )
100
243
{
101
- * info = NULL ;
102
- return nop_stub (0xaa );
244
+ return get_throw_trampoline (384 , TRUE, FALSE, FALSE, FALSE, "throw_corlib_exception" , info , aot , FALSE);
103
245
}
104
246
105
247
#else
@@ -160,8 +302,6 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MonoJitInfo *ji,
160
302
MonoContext * ctx , MonoContext * new_ctx , MonoLMF * * lmf ,
161
303
host_mgreg_t * * save_locations , StackFrameInfo * frame )
162
304
{
163
- gpointer ip = MONO_CONTEXT_GET_IP (ctx );
164
-
165
305
memset (frame , 0 , sizeof (StackFrameInfo ));
166
306
frame -> ji = ji ;
167
307
@@ -174,7 +314,6 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MonoJitInfo *ji,
174
314
guint32 unwind_info_len ;
175
315
guint8 * unwind_info ;
176
316
177
-
178
317
if (ji -> is_trampoline )
179
318
frame -> type = FRAME_TYPE_TRAMPOLINE ;
180
319
else
@@ -190,28 +329,32 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MonoJitInfo *ji,
190
329
for (int i = 0 ; i < 10 ; i ++ )
191
330
(regs + MONO_MAX_IREGS ) [i ] = * ((host_mgreg_t * )& new_ctx -> fregs [RISCV_F18 + i ]);
192
331
332
+ gpointer ip = MINI_FTNPTR_TO_ADDR (MONO_CONTEXT_GET_IP (ctx ));
333
+
193
334
gboolean success = mono_unwind_frame (unwind_info , unwind_info_len , (guint8 * )ji -> code_start ,
194
335
(guint8 * )ji -> code_start + ji -> code_size , (guint8 * )ip , NULL , regs ,
195
336
MONO_MAX_IREGS + 12 + 1 , save_locations , MONO_MAX_IREGS , (guint8 * * )& cfa );
196
337
197
338
if (!success )
198
339
return FALSE;
199
340
200
- memcpy (& new_ctx -> gregs , regs , sizeof (host_mgreg_t ) * 32 );
341
+ memcpy (new_ctx -> gregs , regs , sizeof (host_mgreg_t ) * MONO_MAX_IREGS );
201
342
for (int i = 0 ; i < 2 ; i ++ )
202
343
* ((host_mgreg_t * )& new_ctx -> fregs [RISCV_F8 + i ]) = (regs + MONO_MAX_IREGS ) [i ];
203
344
for (int i = 0 ; i < 10 ; i ++ )
204
- * ((host_mgreg_t * )& new_ctx -> fregs [RISCV_F18 + i ]) = (regs + MONO_MAX_IREGS ) [i ];
345
+ * ((host_mgreg_t * )& new_ctx -> fregs [RISCV_F18 + i ]) = (regs + MONO_MAX_IREGS ) [2 + i ];
205
346
347
+ new_ctx -> gregs [0 ] = regs [RISCV_RA ];
206
348
new_ctx -> gregs [RISCV_SP ] = (host_mgreg_t )(gsize )cfa ;
207
349
208
- if (* lmf && (* lmf )-> gregs [RISCV_FP ] && (MONO_CONTEXT_GET_SP (ctx ) >= (gpointer )(* lmf )-> gregs [RISCV_SP ])) {
350
+ if (* lmf && (* lmf )-> gregs [MONO_ARCH_LMF_REG_SP ] &&
351
+ (MONO_CONTEXT_GET_SP (ctx ) >= (gpointer )(* lmf )-> gregs [MONO_ARCH_LMF_REG_SP ])) {
209
352
/* remove any unused lmf */
210
353
* lmf = (MonoLMF * )(((gsize )(* lmf )-> previous_lmf ) & ~(TARGET_SIZEOF_VOID_P - 1 ));
211
354
}
212
355
213
- /* we substract 1, so that the pc points into the call instruction */
214
- new_ctx -> gregs [RISCV_ZERO ]-- ;
356
+ /* we subtract 1, so that the PC points into the call instruction */
357
+ new_ctx -> gregs [0 ]-- ;
215
358
216
359
return TRUE;
217
360
} else if (* lmf ) {
@@ -223,10 +366,14 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MonoJitInfo *ji,
223
366
if (!ji )
224
367
return FALSE;
225
368
226
- memcpy (& new_ctx -> gregs , (* lmf )-> gregs , sizeof (host_mgreg_t ) * RISCV_N_GREGS );
369
+ g_assert (MONO_ARCH_LMF_REGS == ((MONO_ARCH_CALLEE_SAVED_REGS ) | (1 << RISCV_SP )));
370
+
371
+ memcpy (& new_ctx -> gregs [0 ], & (* lmf )-> gregs [0 ], sizeof (host_mgreg_t ) * RISCV_N_GREGS );
372
+ // new_ctx->gregs [RISCV_FP] = (*lmf)->gregs [MONO_ARCH_LMF_REG_FP];
373
+ // new_ctx->gregs [RISCV_SP] = (*lmf)->gregs [MONO_ARCH_LMF_REG_SP];
227
374
new_ctx -> gregs [0 ] = (* lmf )-> pc ; // use [0] as pc reg since x0 is hard-wired zero
228
375
229
- /* we substract 1, so that the IP points into the call instruction */
376
+ /* we subtract 1, so that the PC points into the call instruction */
230
377
new_ctx -> gregs [0 ]-- ;
231
378
232
379
* lmf = (MonoLMF * )(((gsize )(* lmf )-> previous_lmf ) & ~(TARGET_SIZEOF_VOID_P - 1 ));
0 commit comments