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",
# 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'

View File

@ -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;

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
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))