Просмотр исходного кода

Enable spectest on riscv64 (#2843)

Fix relocation issues on riscv and update test scripts and CI to enable
test spec cases on riscv QEMU.
Huang Qi 2 лет назад
Родитель
Сommit
453a29a9d4

+ 11 - 6
.github/workflows/spec_test_on_nuttx.yml

@@ -59,11 +59,11 @@ jobs:
           #   target: "riscv32_ilp32d",
           #   use_fpu: true
           # },
-          # {
-          #   config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh64",
-          #   target: "riscv64",
-          #   use_fpu: false
-          # },
+          {
+            config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh64",
+            target: "riscv64",
+            use_fpu: false
+          },
         ]
 
         wamr_test_option: [
@@ -85,6 +85,11 @@ jobs:
           },
         ]
 
+        exclude:
+          # XIP is not fully supported yet on RISCV64, some relocations can not be resolved
+          - target_config: { config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh64" }
+            wamr_test_option: { mode: "-t aot -X" }
+
     steps:
       - name: Install Utilities
         run: |
@@ -160,7 +165,7 @@ jobs:
           find nuttx/boards -name defconfig | xargs sed -i '$a\${{ matrix.wamr_test_option.option }}'
 
       - name: Disable FPU for NuttX
-        if: matrix.target_config.use_fpu== false
+        if: matrix.target_config.use_fpu == false
         run: |
           find nuttx/boards -name defconfig | xargs sed -i '$a\# CONFIG_ARCH_FPU is not set\n'
 

+ 67 - 49
core/iwasm/aot/arch/aot_reloc_riscv.c

@@ -11,6 +11,7 @@
 #define R_RISCV_CALL_PLT 19
 #define R_RISCV_PCREL_HI20 23
 #define R_RISCV_PCREL_LO12_I 24
+#define R_RISCV_PCREL_LO12_S 25
 #define R_RISCV_HI20 26
 #define R_RISCV_LO12_I 27
 #define R_RISCV_LO12_S 28
@@ -101,20 +102,20 @@ static SymbolMap target_sym_map[] = {
     REG_SYM(__truncdfsf2),
     REG_SYM(__unorddf2),
     REG_SYM(__unordsf2),
-#if __riscv_xlen == 32
+    REG_SYM(__mulsf3),
+    REG_SYM(__floatundidf),
     REG_SYM(__fixdfdi),
+    REG_SYM(__floatsidf),
+    REG_SYM(__floatunsidf),
+#if __riscv_xlen == 32
     REG_SYM(__fixdfsi),
     REG_SYM(__fixsfdi),
     REG_SYM(__fixsfsi),
     REG_SYM(__floatdidf),
     REG_SYM(__floatdisf),
-    REG_SYM(__floatsidf),
     REG_SYM(__floatsisf),
-    REG_SYM(__floatundidf),
     REG_SYM(__floatundisf),
-    REG_SYM(__floatunsidf),
     REG_SYM(__floatunsisf),
-    REG_SYM(__mulsf3),
     REG_SYM(__mulsi3),
 #endif
 #endif
@@ -269,9 +270,10 @@ typedef struct RelocTypeStrMap {
     }
 
 static RelocTypeStrMap reloc_type_str_maps[] = {
-    RELOC_TYPE_MAP(R_RISCV_32),           RELOC_TYPE_MAP(R_RISCV_CALL),
-    RELOC_TYPE_MAP(R_RISCV_CALL_PLT),     RELOC_TYPE_MAP(R_RISCV_PCREL_HI20),
-    RELOC_TYPE_MAP(R_RISCV_PCREL_LO12_I), RELOC_TYPE_MAP(R_RISCV_HI20),
+    RELOC_TYPE_MAP(R_RISCV_32),           RELOC_TYPE_MAP(R_RISCV_64),
+    RELOC_TYPE_MAP(R_RISCV_CALL),         RELOC_TYPE_MAP(R_RISCV_CALL_PLT),
+    RELOC_TYPE_MAP(R_RISCV_PCREL_HI20),   RELOC_TYPE_MAP(R_RISCV_PCREL_LO12_I),
+    RELOC_TYPE_MAP(R_RISCV_PCREL_LO12_S), RELOC_TYPE_MAP(R_RISCV_HI20),
     RELOC_TYPE_MAP(R_RISCV_LO12_I),       RELOC_TYPE_MAP(R_RISCV_LO12_S),
 };
 
@@ -327,21 +329,37 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
             rv_set_val((uint16 *)addr, val_32);
             break;
         }
+
+#if __riscv_xlen == 64
         case R_RISCV_64:
         {
             uint64 val_64 =
-                (uint64)((uintptr_t)symbol_addr + (intptr_t)reloc_addend);
+                (uint64)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
+
             CHECK_RELOC_OFFSET(sizeof(uint64));
+            if (val_64
+                != (uint64)((intptr_t)symbol_addr + (intptr_t)reloc_addend)) {
+                goto fail_addr_out_of_range;
+            }
+
             bh_memcpy_s(addr, 8, &val_64, 8);
+#ifdef __riscv_zifencei
+            __asm__ volatile("fence.i");
+#else
+            __asm__ volatile("fence");
+#endif
             break;
         }
+#endif
+
         case R_RISCV_CALL:
         case R_RISCV_CALL_PLT:
+        case R_RISCV_PCREL_HI20: /* S + A - P */
         {
-            val = (int32)(intptr_t)((uint8 *)symbol_addr - addr);
+            val = (int32)(intptr_t)((uint8 *)symbol_addr + reloc_addend - addr);
 
             CHECK_RELOC_OFFSET(sizeof(uint32));
-            if (val != (intptr_t)((uint8 *)symbol_addr - addr)) {
+            if (val != (intptr_t)((uint8 *)symbol_addr + reloc_addend - addr)) {
                 if (symbol_index >= 0) {
                     /* Call runtime function by plt code */
                     symbol_addr = (uint8 *)module->code + module->code_size
@@ -351,7 +369,7 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
                 }
             }
 
-            if (val != (intptr_t)((uint8 *)symbol_addr - addr)) {
+            if (val != (intptr_t)((uint8 *)symbol_addr + reloc_addend - addr)) {
                 goto fail_addr_out_of_range;
             }
 
@@ -372,32 +390,15 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
             break;
         }
 
-        case R_RISCV_HI20:       /* S + A */
-        case R_RISCV_PCREL_HI20: /* S + A - P */
+        case R_RISCV_HI20: /* S + A */
         {
-            if (reloc_type == R_RISCV_PCREL_HI20) {
-                val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend
-                              - (intptr_t)addr);
-            }
-            else {
-                val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
-            }
+            val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
 
             CHECK_RELOC_OFFSET(sizeof(uint32));
-            if (reloc_type == R_RISCV_PCREL_HI20) {
-                if (val
-                    != ((intptr_t)symbol_addr + (intptr_t)reloc_addend
-                        - (intptr_t)addr)) {
-                    goto fail_addr_out_of_range;
-                }
-            }
-            else {
-                if (val != ((intptr_t)symbol_addr + (intptr_t)reloc_addend)) {
-                    goto fail_addr_out_of_range;
-                }
+            if (val != ((intptr_t)symbol_addr + (intptr_t)reloc_addend)) {
+                goto fail_addr_out_of_range;
             }
 
-            addr = target_section_addr + reloc_offset;
             insn = rv_get_val((uint16 *)addr);
             rv_calc_imm(val, &imm_hi, &imm_lo);
             insn = (insn & 0x00000fff) | (imm_hi << 12);
@@ -405,27 +406,44 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
             break;
         }
 
-        case R_RISCV_LO12_I:       /* S + A */
         case R_RISCV_PCREL_LO12_I: /* S - P */
+        case R_RISCV_PCREL_LO12_S: /* S - P */
         {
-            if (reloc_type == R_RISCV_PCREL_LO12_I) {
-                /* A = 0 */
-                val = (int32)((intptr_t)symbol_addr - (intptr_t)addr);
-            }
-            else {
-                val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
+            /* Already handled in R_RISCV_PCREL_HI20, it should be skipped for
+             * most cases. But it is still needed for some special cases, e.g.
+             * ```
+             * label:
+             *    auipc t0, %pcrel_hi(symbol)   # R_RISCV_PCREL_HI20 (symbol)
+             *    lui t1, 1
+             *    lw t2, t0, %pcrel_lo(label)   # R_RISCV_PCREL_LO12_I (label)
+             *    add t2, t2, t1
+             *    sw t2, t0, %pcrel_lo(label)   # R_RISCV_PCREL_LO12_S (label)
+             * ```
+             * In this case, the R_RISCV_PCREL_LO12_I/S relocation should be
+             * handled after R_RISCV_PCREL_HI20 relocation.
+             *
+             * So, if the R_RISCV_PCREL_LO12_I/S relocation is not followed by
+             * R_RISCV_PCREL_HI20 relocation, it should be handled here but
+             * not implemented yet.
+             */
+
+            if ((uintptr_t)addr - (uintptr_t)symbol_addr
+                    - (uintptr_t)reloc_addend
+                != 4) {
+                goto fail_addr_out_of_range;
             }
+            break;
+        }
+
+        case R_RISCV_LO12_I: /* S + A */
+        {
+
+            val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
 
             CHECK_RELOC_OFFSET(sizeof(uint32));
-            if (reloc_type == R_RISCV_PCREL_LO12_I) {
-                if (val != (intptr_t)symbol_addr - (intptr_t)addr) {
-                    goto fail_addr_out_of_range;
-                }
-            }
-            else {
-                if (val != (intptr_t)symbol_addr + (intptr_t)reloc_addend) {
-                    goto fail_addr_out_of_range;
-                }
+
+            if (val != (intptr_t)symbol_addr + (intptr_t)reloc_addend) {
+                goto fail_addr_out_of_range;
             }
 
             addr = target_section_addr + reloc_offset;

+ 11 - 0
tests/wamr-test-suites/spec-test-script/runtest.py

@@ -1072,6 +1072,17 @@ def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = '
     # exception isn't thrown in several cases
     cmd.append("--disable-llvm-lto")
 
+    # Bounds checks is disabled by default for 64-bit targets, to
+    # use the hardware based bounds checks. But it is not supported
+    # in QEMU with NuttX.
+    # Enable bounds checks explicitly for all targets if running in QEMU.
+    if opts.qemu:
+        cmd.append("--bounds-checks=1")
+
+    # RISCV64 requires -mcmodel=medany, which can be set by --size-level=1
+    if test_target.startswith("riscv64"):
+        cmd.append("--size-level=1")
+
     cmd += ["-o", aot_tempfile, wasm_tempfile]
 
     log("Running: %s" % " ".join(cmd))