MENU

Mono RISCV Issues

November 13, 2022 • 实习

在Port mono RISCV的过程中发现了一些可以优化/可能有问题的点,就此记录下来,未来可能会处理。

1. Load Imm的实现:

在函数mono_riscv_emit_imm中,有一段代码被用来加载超过32位的立即数,很tricky。
后期要是优化的话,参考LLVM中的实现使用了位移运算指令。

/*
* This is not pretty, but RV64I doesn't make it easy to load constants.
* Need to figure out something better.
*/
riscv_jal (code, rd, sizeof (guint64));
*(guint64 *) code = imm;
code += sizeof (guint64);
riscv_ld (code, rd, rd, 0);

2.会分配Zero(X0)寄存器

C#源码如下

namespace HelloWorld
{
  class Program
  {
    static void Main()
    {
      int a = 0;
    }
  }
}

CIL如下

 iconst R59 <- [0]
 store_membase_reg [s0 + 0xfffffffffffffff0] <- R59
 il_seq_point intr il: 0x0
 load_membase R44 <- [s0 + 0xfffffffffffffff8]
 load_membase R48 <- [R44 + 0x8]
 load_membase R49 <- [s0 + 0xfffffffffffffff8]
 load_membase R50 <- [R49 + 0x0]
 add_imm R51 <- s0 [-16]
 add_imm R52 <- s0 [-32]
 add_imm R53 <- s0 [-40]
 add_imm R54 <- s0 [-48]
 add_imm R55 <- s0 [-56]
 add_imm R56 <- R48 [0]
 voidcall_reg R50 clobbers: c
 il_seq_point il: 0x18
 load_membase ra <- [s0 + 0xfffffffffffffff0]
 il_seq_point intr il: 0x19

接着mono会进行基于线性扫描分配寄存器。
liveness如下:

liveness: ra [16 - 16]
liveness: s0 [2 - 0]
liveness: R44 [4 - 4]
liveness: R48 [5 - 5]
liveness: R49 [6 - 6]
liveness: R50 [7 - 7]
liveness: R51 [8 - 8]
liveness: R52 [9 - 9]
liveness: R53 [10 - 10]
liveness: R54 [11 - 11]
liveness: R55 [12 - 12]
liveness: R56 [13 - 13]

分配结果如下:

processing:     17 il_seq_point intr il: 0x19
        17 il_seq_point intr il: 0x19
processing:     16 load_membase ra <- [s0 + 0xfffffffffffffff0]
        16 load_membase ra <- [s0 + 0xfffffffffffffff0]
processing:     15 il_seq_point il: 0x18
        15 il_seq_point il: 0x18
processing:     14 voidcall_reg R50 clobbers: c
        assigned arg reg zero to R51
        assigned arg reg a0 to R52
        assigned arg reg a1 to R53
        assigned arg reg a2 to R54
        assigned arg reg a3 to R55
        assigned arg reg a4 to R56
        assigned sreg1 a5 to R50
        14 voidcall_reg a5 clobbers: c
processing:     13 add_imm R56 <- R48 [0]
        assigned dreg a4 to dest R56
        freeable a4 (R56) (born in 13)
        assigned sreg1 a4 to R48
        13 add_imm a4 <- a4 [0]
processing:     12 add_imm R55 <- s0 [-56]
        assigned dreg a3 to dest R55
        freeable a3 (R55) (born in 12)
        12 add_imm a3 <- s0 [-56]
processing:     11 add_imm R54 <- s0 [-48]
        assigned dreg a2 to dest R54
        freeable a2 (R54) (born in 11)
        11 add_imm a2 <- s0 [-48]
processing:     10 add_imm R53 <- s0 [-40]
        assigned dreg a1 to dest R53
        freeable a1 (R53) (born in 10)
        10 add_imm a1 <- s0 [-40]
processing:     9  add_imm R52 <- s0 [-32]
        assigned dreg a0 to dest R52
        freeable a0 (R52) (born in 9)
        9  add_imm a0 <- s0 [-32]
processing:     8  add_imm R51 <- s0 [-16]
        assigned dreg zero to dest R51
        freeable zero (R51) (born in 8)
        8  add_imm zero <- s0 [-16]
processing:     7  load_membase R50 <- [R49 + 0x0]
        assigned dreg a5 to dest R50
        freeable a5 (R50) (born in 7)
        assigned sreg1 a0 to R49
        7  load_membase a5 <- [a0 + 0x0]
processing:     6  load_membase R49 <- [s0 + 0xfffffffffffffff8]
        assigned dreg a0 to dest R49
        freeable a0 (R49) (born in 6)
        6  load_membase a0 <- [s0 + 0xfffffffffffffff8]
processing:     5  load_membase R48 <- [R44 + 0x8]
        assigned dreg a4 to dest R48
        freeable a4 (R48) (born in 5)
        assigned sreg1 a0 to R44
        5  load_membase a4 <- [a0 + 0x8]
processing:     4  load_membase R44 <- [s0 + 0xfffffffffffffff8]
        assigned dreg a0 to dest R44
        freeable a0 (R44) (born in 4)
        4  load_membase a0 <- [s0 + 0xfffffffffffffff8]
processing:     3  il_seq_point intr il: 0x0
        3  il_seq_point intr il: 0x0
processing:     2  store_membase_reg [s0 + 0xfffffffffffffff0] <- R59
        assigned sreg1 a0 to R59
        2  store_membase_reg [s0 + 0xfffffffffffffff0] <- a0
processing:     1  iconst R59 <- [0]
        assigned dreg a0 to dest R59
        freeable a0 (R59) (born in 1)
        1  iconst a0 <- [0]

R51被分配了zero寄存器,从IR来看,R51应该是一个参数寄存器ax,被用来给之后的voidcall_reg传参。