@@ -299,6 +299,79 @@ static inline void offset_map_insert(struct jit_state *state, block_t *block)
299
299
__builtin___clear_cache((char *) (addr), (char *) (addr) + (size));
300
300
#endif
301
301
302
+ /* JIT debug helpers - enable with ENABLE_JIT_DEBUG=1 to detect issues early */
303
+ #ifndef ENABLE_JIT_DEBUG
304
+ #define ENABLE_JIT_DEBUG 0
305
+ #endif
306
+
307
+ #if ENABLE_JIT_DEBUG
308
+ static void jit_dump_regmap (const char * ctx )
309
+ {
310
+ rv_log_debug ("JIT RegMap [%s]:" , ctx );
311
+ for (int i = 0 ; i < n_host_regs ; i ++ ) {
312
+ if (register_map [i ].vm_reg_idx >= 0 ) {
313
+ rv_log_debug (" Host R%d -> VM x%d (dirty=%d)" ,
314
+ register_map [i ].reg_idx ,
315
+ register_map [i ].vm_reg_idx ,
316
+ register_map [i ].dirty );
317
+ }
318
+ }
319
+ }
320
+
321
+ static void jit_check_regmap_conflict (int vm_reg , int host_reg , const char * insn )
322
+ {
323
+ int found_idx = -1 ;
324
+ /* Check if VM register is already mapped */
325
+ for (int i = 0 ; i < n_host_regs ; i ++ ) {
326
+ if (register_map [i ].vm_reg_idx == vm_reg ) {
327
+ if (found_idx >= 0 && found_idx != i ) {
328
+ /* VM register mapped to multiple host registers */
329
+ rv_log_error ("JIT RegMap CONFLICT in %s: VM x%d mapped to "
330
+ "Host R%d (idx %d) and R%d (idx %d)" ,
331
+ insn , vm_reg ,
332
+ register_map [found_idx ].reg_idx , found_idx ,
333
+ register_map [i ].reg_idx , i );
334
+ jit_dump_regmap ("CONFLICT" );
335
+ assert (false);
336
+ }
337
+ found_idx = i ;
338
+ /* Verify the found mapping is correct */
339
+ if (register_map [i ].reg_idx != host_reg ) {
340
+ rv_log_error ("JIT RegMap CONFLICT in %s: VM x%d expected at "
341
+ "Host R%d but found at R%d" ,
342
+ insn , vm_reg , host_reg , register_map [i ].reg_idx );
343
+ jit_dump_regmap ("CONFLICT" );
344
+ assert (false);
345
+ }
346
+ } else if (register_map [i ].reg_idx == host_reg &&
347
+ register_map [i ].vm_reg_idx >= 0 ) {
348
+ /* Host register holds different VM register */
349
+ rv_log_error ("JIT RegMap CONFLICT in %s: Host R%d already holds "
350
+ "VM x%d, cannot map VM x%d" ,
351
+ insn , host_reg , register_map [i ].vm_reg_idx , vm_reg );
352
+ jit_dump_regmap ("CONFLICT" );
353
+ assert (false);
354
+ }
355
+ }
356
+ }
357
+
358
+ static void jit_verify_cache_coherency (struct jit_state * state , uint32_t pc ) UNUSED ;
359
+ static void jit_verify_cache_coherency (struct jit_state * state , uint32_t pc )
360
+ {
361
+ /* On ARM64, verify instruction cache was properly invalidated */
362
+ #if defined(__aarch64__ )
363
+ if (state -> offset > 0 ) {
364
+ rv_log_debug ("JIT: Cache coherency check at PC=0x%08x, offset=%u" ,
365
+ pc , state -> offset );
366
+ }
367
+ #endif
368
+ }
369
+ #else
370
+ #define jit_dump_regmap (ctx ) do { } while (0)
371
+ #define jit_check_regmap_conflict (vm_reg , host_reg , insn ) do { } while (0)
372
+ #define jit_verify_cache_coherency (state , pc ) do { } while (0)
373
+ #endif
374
+
302
375
static bool should_flush = false;
303
376
static void emit_bytes (struct jit_state * state , void * data , uint32_t len )
304
377
{
@@ -1890,6 +1963,7 @@ static inline int map_vm_reg(struct jit_state *state, int vm_reg_idx)
1890
1963
save_reg (state , idx );
1891
1964
unmap_vm_reg (idx );
1892
1965
set_vm_reg (idx , vm_reg_idx );
1966
+ jit_check_regmap_conflict (vm_reg_idx , target_reg , "map_vm_reg" );
1893
1967
return target_reg ;
1894
1968
}
1895
1969
@@ -1933,6 +2007,14 @@ static inline int map_vm_reg_reserved(struct jit_state *state,
1933
2007
save_reg (state , idx );
1934
2008
unmap_vm_reg (idx );
1935
2009
set_vm_reg (idx , vm_reg_idx );
2010
+ jit_check_regmap_conflict (vm_reg_idx , target_reg , "map_vm_reg_reserved" );
2011
+ /* Additional check: ensure we didn't allocate the reserved register */
2012
+ if (target_reg == reserved_reg_idx ) {
2013
+ rv_log_error ("JIT RegMap ERROR: map_vm_reg_reserved allocated reserved "
2014
+ "register R%d for VM x%d" ,
2015
+ reserved_reg_idx , vm_reg_idx );
2016
+ assert (false);
2017
+ }
1936
2018
return target_reg ;
1937
2019
}
1938
2020
0 commit comments