Enable spectest on riscv64 (#2843)

Fix relocation issues on riscv and update test scripts and CI to enable
test spec cases on riscv QEMU.
This commit is contained in:
Huang Qi 2023-12-04 14:22:47 +08:00 committed by GitHub
parent 157c289d07
commit 453a29a9d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 55 deletions

View File

@ -59,11 +59,11 @@ jobs:
# target: "riscv32_ilp32d", # target: "riscv32_ilp32d",
# use_fpu: true # use_fpu: true
# }, # },
# { {
# config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh64", config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh64",
# target: "riscv64", target: "riscv64",
# use_fpu: false use_fpu: false
# }, },
] ]
wamr_test_option: [ 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: steps:
- name: Install Utilities - name: Install Utilities
run: | run: |

View File

@ -11,6 +11,7 @@
#define R_RISCV_CALL_PLT 19 #define R_RISCV_CALL_PLT 19
#define R_RISCV_PCREL_HI20 23 #define R_RISCV_PCREL_HI20 23
#define R_RISCV_PCREL_LO12_I 24 #define R_RISCV_PCREL_LO12_I 24
#define R_RISCV_PCREL_LO12_S 25
#define R_RISCV_HI20 26 #define R_RISCV_HI20 26
#define R_RISCV_LO12_I 27 #define R_RISCV_LO12_I 27
#define R_RISCV_LO12_S 28 #define R_RISCV_LO12_S 28
@ -101,20 +102,20 @@ static SymbolMap target_sym_map[] = {
REG_SYM(__truncdfsf2), REG_SYM(__truncdfsf2),
REG_SYM(__unorddf2), REG_SYM(__unorddf2),
REG_SYM(__unordsf2), REG_SYM(__unordsf2),
#if __riscv_xlen == 32 REG_SYM(__mulsf3),
REG_SYM(__floatundidf),
REG_SYM(__fixdfdi), REG_SYM(__fixdfdi),
REG_SYM(__floatsidf),
REG_SYM(__floatunsidf),
#if __riscv_xlen == 32
REG_SYM(__fixdfsi), REG_SYM(__fixdfsi),
REG_SYM(__fixsfdi), REG_SYM(__fixsfdi),
REG_SYM(__fixsfsi), REG_SYM(__fixsfsi),
REG_SYM(__floatdidf), REG_SYM(__floatdidf),
REG_SYM(__floatdisf), REG_SYM(__floatdisf),
REG_SYM(__floatsidf),
REG_SYM(__floatsisf), REG_SYM(__floatsisf),
REG_SYM(__floatundidf),
REG_SYM(__floatundisf), REG_SYM(__floatundisf),
REG_SYM(__floatunsidf),
REG_SYM(__floatunsisf), REG_SYM(__floatunsisf),
REG_SYM(__mulsf3),
REG_SYM(__mulsi3), REG_SYM(__mulsi3),
#endif #endif
#endif #endif
@ -269,9 +270,10 @@ typedef struct RelocTypeStrMap {
} }
static RelocTypeStrMap reloc_type_str_maps[] = { static RelocTypeStrMap reloc_type_str_maps[] = {
RELOC_TYPE_MAP(R_RISCV_32), RELOC_TYPE_MAP(R_RISCV_CALL), RELOC_TYPE_MAP(R_RISCV_32), RELOC_TYPE_MAP(R_RISCV_64),
RELOC_TYPE_MAP(R_RISCV_CALL_PLT), RELOC_TYPE_MAP(R_RISCV_PCREL_HI20), RELOC_TYPE_MAP(R_RISCV_CALL), RELOC_TYPE_MAP(R_RISCV_CALL_PLT),
RELOC_TYPE_MAP(R_RISCV_PCREL_LO12_I), RELOC_TYPE_MAP(R_RISCV_HI20), 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), 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); rv_set_val((uint16 *)addr, val_32);
break; break;
} }
#if __riscv_xlen == 64
case R_RISCV_64: case R_RISCV_64:
{ {
uint64 val_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)); 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); bh_memcpy_s(addr, 8, &val_64, 8);
#ifdef __riscv_zifencei
__asm__ volatile("fence.i");
#else
__asm__ volatile("fence");
#endif
break; break;
} }
#endif
case R_RISCV_CALL: case R_RISCV_CALL:
case R_RISCV_CALL_PLT: 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)); 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) { if (symbol_index >= 0) {
/* Call runtime function by plt code */ /* Call runtime function by plt code */
symbol_addr = (uint8 *)module->code + module->code_size 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; goto fail_addr_out_of_range;
} }
@ -373,31 +391,14 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
} }
case R_RISCV_HI20: /* S + A */ case R_RISCV_HI20: /* S + A */
case R_RISCV_PCREL_HI20: /* S + A - P */
{ {
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)); 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)) { if (val != ((intptr_t)symbol_addr + (intptr_t)reloc_addend)) {
goto fail_addr_out_of_range; goto fail_addr_out_of_range;
} }
}
addr = target_section_addr + reloc_offset;
insn = rv_get_val((uint16 *)addr); insn = rv_get_val((uint16 *)addr);
rv_calc_imm(val, &imm_hi, &imm_lo); rv_calc_imm(val, &imm_hi, &imm_lo);
insn = (insn & 0x00000fff) | (imm_hi << 12); insn = (insn & 0x00000fff) | (imm_hi << 12);
@ -405,28 +406,45 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
break; break;
} }
case R_RISCV_LO12_I: /* S + A */
case R_RISCV_PCREL_LO12_I: /* S - P */ case R_RISCV_PCREL_LO12_I: /* S - P */
case R_RISCV_PCREL_LO12_S: /* S - P */
{ {
if (reloc_type == R_RISCV_PCREL_LO12_I) { /* Already handled in R_RISCV_PCREL_HI20, it should be skipped for
/* A = 0 */ * most cases. But it is still needed for some special cases, e.g.
val = (int32)((intptr_t)symbol_addr - (intptr_t)addr); * ```
* 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;
} }
else { break;
val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
} }
case R_RISCV_LO12_I: /* S + A */
{
val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
CHECK_RELOC_OFFSET(sizeof(uint32)); 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) { if (val != (intptr_t)symbol_addr + (intptr_t)reloc_addend) {
goto fail_addr_out_of_range; goto fail_addr_out_of_range;
} }
}
addr = target_section_addr + reloc_offset; addr = target_section_addr + reloc_offset;
insn = rv_get_val((uint16 *)addr); insn = rv_get_val((uint16 *)addr);

View File

@ -1072,6 +1072,17 @@ def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = '
# exception isn't thrown in several cases # exception isn't thrown in several cases
cmd.append("--disable-llvm-lto") 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] cmd += ["-o", aot_tempfile, wasm_tempfile]
log("Running: %s" % " ".join(cmd)) log("Running: %s" % " ".join(cmd))