Enable aarch64 support, add component test framework and test suite (#211)
and refine aot call indirect op
This commit is contained in:
@ -140,6 +140,7 @@ GET_U64_FROM_ADDR(uint32 *addr)
|
||||
#define E_MACHINE_MIPS 8 /* MIPS R3000 big-endian */
|
||||
#define E_MACHINE_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */
|
||||
#define E_MACHINE_ARM 40 /* ARM/Thumb */
|
||||
#define E_MACHINE_AARCH64 183 /* AArch64 */
|
||||
#define E_MACHINE_ARC 45 /* Argonaut RISC Core */
|
||||
#define E_MACHINE_IA_64 50 /* Intel Merced */
|
||||
#define E_MACHINE_MIPS_X 51 /* Stanford MIPS-X */
|
||||
@ -196,6 +197,7 @@ get_aot_file_target(AOTTargetInfo *target_info,
|
||||
machine_type = "i386";
|
||||
break;
|
||||
case E_MACHINE_ARM:
|
||||
case E_MACHINE_AARCH64:
|
||||
machine_type = target_info->arch;
|
||||
break;
|
||||
case E_MACHINE_MIPS:
|
||||
|
||||
@ -14,9 +14,8 @@ typedef struct {
|
||||
|
||||
#define REG_COMMON_SYMBOLS \
|
||||
REG_SYM(aot_set_exception_with_id), \
|
||||
REG_SYM(aot_get_exception), \
|
||||
REG_SYM(aot_is_wasm_type_equal), \
|
||||
REG_SYM(aot_invoke_native), \
|
||||
REG_SYM(aot_call_indirect), \
|
||||
REG_SYM(wasm_runtime_enlarge_memory), \
|
||||
REG_SYM(wasm_runtime_set_exception), \
|
||||
REG_SYM(fmin), \
|
||||
|
||||
@ -811,7 +811,7 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
|
||||
return wasm_type_equal(type1, type2);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
|
||||
uint32 *frame_lp, uint32 argc, uint32 *argv_ret)
|
||||
{
|
||||
@ -827,18 +827,76 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
|
||||
const char *signature = NULL;
|
||||
char buf[128];
|
||||
|
||||
if (func_idx < aot_module->import_func_count) {
|
||||
import_func = aot_module->import_funcs + func_idx;
|
||||
if (!func_ptr) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"fail to call unlinked import function (%s, %s)",
|
||||
import_func->module_name, import_func->func_name);
|
||||
aot_set_exception(module_inst, buf);
|
||||
return;
|
||||
}
|
||||
signature = import_func->signature;
|
||||
bh_assert(func_idx < aot_module->import_func_count);
|
||||
|
||||
import_func = aot_module->import_funcs + func_idx;
|
||||
if (!func_ptr) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"fail to call unlinked import function (%s, %s)",
|
||||
import_func->module_name, import_func->func_name);
|
||||
aot_set_exception(module_inst, buf);
|
||||
return false;
|
||||
}
|
||||
wasm_runtime_invoke_native(exec_env, func_ptr,
|
||||
func_type, signature, frame_lp, argc, argv_ret);
|
||||
|
||||
signature = import_func->signature;
|
||||
return wasm_runtime_invoke_native(exec_env, func_ptr,
|
||||
func_type, signature,
|
||||
frame_lp, argc, argv_ret);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_call_indirect(WASMExecEnv *exec_env,
|
||||
uint32 func_type_idx, uint32 table_elem_idx,
|
||||
uint32 *frame_lp, uint32 argc, uint32 *argv_ret)
|
||||
{
|
||||
AOTModuleInstance *module_inst = (AOTModuleInstance*)
|
||||
wasm_runtime_get_module_inst(exec_env);
|
||||
AOTModule *aot_module = (AOTModule*)module_inst->aot_module.ptr;
|
||||
uint32 *func_type_indexes = (uint32*)module_inst->func_type_indexes.ptr;
|
||||
uint32 *table_data = (uint32*)module_inst->table_data.ptr;
|
||||
AOTFuncType *func_type = aot_module->func_types[func_type_idx];;
|
||||
void **func_ptrs = (void**)module_inst->func_ptrs.ptr, *func_ptr;
|
||||
uint32 table_size = module_inst->table_size;
|
||||
uint32 func_idx, func_type_idx1;
|
||||
AOTImportFunc *import_func;
|
||||
const char *signature = NULL;
|
||||
char buf[128];
|
||||
|
||||
if (table_elem_idx >= table_size) {
|
||||
aot_set_exception_with_id(module_inst, EXCE_UNDEFINED_ELEMENT);
|
||||
return false;
|
||||
}
|
||||
|
||||
func_idx = table_data[table_elem_idx];
|
||||
if (func_idx == (uint32)-1) {
|
||||
aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT);
|
||||
return false;
|
||||
}
|
||||
|
||||
func_type_idx1 = func_type_indexes[func_idx];
|
||||
if (!aot_is_wasm_type_equal(module_inst, func_type_idx, func_type_idx1)) {
|
||||
aot_set_exception_with_id(module_inst, EXCE_INVALID_FUNCTION_TYPE_INDEX);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (func_idx < aot_module->import_func_count) {
|
||||
/* Call native function */
|
||||
import_func = aot_module->import_funcs + func_idx;
|
||||
signature = import_func->signature;
|
||||
}
|
||||
|
||||
if (!(func_ptr = func_ptrs[func_idx])) {
|
||||
bh_assert(func_idx < aot_module->import_func_count);
|
||||
import_func = aot_module->import_funcs + func_idx;
|
||||
snprintf(buf, sizeof(buf),
|
||||
"fail to call unlinked import function (%s, %s)",
|
||||
import_func->module_name, import_func->func_name);
|
||||
aot_set_exception(module_inst, buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
return wasm_runtime_invoke_native(exec_env, func_ptr,
|
||||
func_type, signature,
|
||||
frame_lp, argc, argv_ret);
|
||||
}
|
||||
|
||||
|
||||
@ -435,10 +435,15 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
|
||||
/**
|
||||
* Invoke native function from aot code
|
||||
*/
|
||||
void
|
||||
bool
|
||||
aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
|
||||
uint32 *frame_lp, uint32 argc, uint32 *argv_ret);
|
||||
|
||||
bool
|
||||
aot_call_indirect(WASMExecEnv *exec_env,
|
||||
uint32 func_type_idx, uint32 table_elem_idx,
|
||||
uint32 *frame_lp, uint32 argc, uint32 *argv_ret);
|
||||
|
||||
uint32
|
||||
aot_get_plt_table_size();
|
||||
|
||||
|
||||
238
core/iwasm/aot/arch/aot_reloc_aarch64.c
Normal file
238
core/iwasm/aot/arch/aot_reloc_aarch64.c
Normal file
@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_reloc.h"
|
||||
|
||||
#define R_AARCH64_ADR_PREL_PG_HI21 275
|
||||
#define R_AARCH64_ADD_ABS_LO12_NC 277
|
||||
#define R_AARCH64_CALL26 283
|
||||
|
||||
static SymbolMap target_sym_map[] = {
|
||||
REG_COMMON_SYMBOLS
|
||||
};
|
||||
|
||||
static void
|
||||
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
|
||||
{
|
||||
if (error_buf != NULL)
|
||||
snprintf(error_buf, error_buf_size, "%s", string);
|
||||
}
|
||||
|
||||
SymbolMap *
|
||||
get_target_symbol_map(uint32 *sym_num)
|
||||
{
|
||||
*sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
|
||||
return target_sym_map;
|
||||
}
|
||||
|
||||
void
|
||||
get_current_target(char *target_buf, uint32 target_buf_size)
|
||||
{
|
||||
char *build_target = BUILD_TARGET;
|
||||
char *p = target_buf, *p_end;
|
||||
snprintf(target_buf, target_buf_size, "%s", build_target);
|
||||
p_end = p + strlen(target_buf);
|
||||
while (p < p_end) {
|
||||
if (*p >= 'A' && *p <= 'Z')
|
||||
*p++ += 'a' - 'A';
|
||||
else
|
||||
p++;
|
||||
}
|
||||
if (!strcmp(target_buf, "aarch64"))
|
||||
snprintf(target_buf, target_buf_size, "aarch64v8");
|
||||
}
|
||||
|
||||
static uint32
|
||||
get_plt_item_size()
|
||||
{
|
||||
/* 8*4 bytes instructions and 8 bytes symbol address */
|
||||
return 40;
|
||||
}
|
||||
|
||||
void
|
||||
init_plt_table(uint8 *plt)
|
||||
{
|
||||
uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
|
||||
for (i = 0; i < num; i++) {
|
||||
uint32 *p = (uint32*)plt;
|
||||
*p++ = 0xd10023ff; /* sub sp, sp, #0x8 */
|
||||
*p++ = 0xf90003fe; /* str x30, [sp] */
|
||||
*p++ = 0x100000de; /* adr x30, #24 */
|
||||
*p++ = 0xf94003de; /* ldr x30, [x30] */
|
||||
*p++ = 0xd63f03c0; /* blr x30 */
|
||||
*p++ = 0xf94003fe; /* ldr x30, [sp] */
|
||||
*p++ = 0x910023ff; /* add sp, sp, #0x8 */
|
||||
*p++ = 0xd61f03c0; /* br x30 */
|
||||
/* symbol addr */
|
||||
*(uint64*)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr;
|
||||
p += 2;
|
||||
plt += get_plt_item_size();
|
||||
}
|
||||
}
|
||||
|
||||
uint32
|
||||
get_plt_table_size()
|
||||
{
|
||||
return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
|
||||
}
|
||||
|
||||
#define SIGN_EXTEND_TO_INT64(val, bits, val_ext) do { \
|
||||
int64 m = ((int64)1 << (bits - 1)); \
|
||||
val_ext = ((int64)val ^ m) - m; \
|
||||
} while (0)
|
||||
|
||||
#define Page(expr) ((expr) & ~0xFFF)
|
||||
|
||||
static bool
|
||||
check_reloc_offset(uint32 target_section_size,
|
||||
uint64 reloc_offset, uint32 reloc_data_size,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
if (!(reloc_offset < (uint64)target_section_size
|
||||
&& reloc_offset + reloc_data_size <= (uint64)target_section_size)) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module load failed: invalid relocation offset.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
apply_relocation(AOTModule *module,
|
||||
uint8 *target_section_addr, uint32 target_section_size,
|
||||
uint64 reloc_offset, uint64 reloc_addend,
|
||||
uint32 reloc_type, void *symbol_addr, int32 symbol_index,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
case R_AARCH64_CALL26:
|
||||
{
|
||||
void *S, *P = (void*)(target_section_addr + reloc_offset);
|
||||
int64 X, A, initial_addend;
|
||||
int32 insn, imm26;
|
||||
|
||||
CHECK_RELOC_OFFSET(sizeof(int32));
|
||||
|
||||
insn = *(int32*)P;
|
||||
imm26 = insn & 0x3FFFFFF;
|
||||
SIGN_EXTEND_TO_INT64(imm26 << 2, 28, initial_addend);
|
||||
A = initial_addend;
|
||||
A += (int64)reloc_addend;
|
||||
|
||||
if (symbol_index < 0) {
|
||||
/* Symbol address itself is an AOT function.
|
||||
* Apply relocation with the symbol directly.
|
||||
* Suppose the symbol address is in +-128MB relative
|
||||
* to the relocation address.
|
||||
*/
|
||||
S = symbol_addr;
|
||||
}
|
||||
else {
|
||||
uint8 *plt;
|
||||
if (reloc_addend > 0) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module load failed: relocate to plt table "
|
||||
"with reloc addend larger than 0 is unsupported.");
|
||||
return false;
|
||||
}
|
||||
/* Symbol address is not an AOT function,
|
||||
* but a function of runtime or native. Its address is
|
||||
* beyond of the +-128MB space. Apply relocation with
|
||||
* the PLT which branch to the target symbol address.
|
||||
*/
|
||||
S = plt = (uint8*)module->code + module->code_size
|
||||
- get_plt_table_size()
|
||||
+ get_plt_item_size() * symbol_index;
|
||||
}
|
||||
|
||||
/* S + A - P */
|
||||
X = (int64)S + A - (int64)P;
|
||||
|
||||
/* Check overflow: +-128MB */
|
||||
if (X > (128 * BH_MB) || X < (-128 * BH_MB)) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module load failed: "
|
||||
"target address out of range.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* write the imm26 back to instruction */
|
||||
*(int32*)P = (insn & 0xFC000000) | ((int32)((X >> 2) & 0x3FFFFFF));
|
||||
break;
|
||||
}
|
||||
|
||||
case R_AARCH64_ADR_PREL_PG_HI21:
|
||||
{
|
||||
void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
|
||||
int64 X, A, initial_addend;
|
||||
int32 insn, immhi19, immlo2, imm21;
|
||||
|
||||
CHECK_RELOC_OFFSET(sizeof(int32));
|
||||
|
||||
insn = *(int32*)P;
|
||||
immhi19 = (insn >> 5) & 0x7FFFF;
|
||||
immlo2 = (insn >> 29) & 0x3;
|
||||
imm21 = (immhi19 << 2) | immlo2;
|
||||
|
||||
SIGN_EXTEND_TO_INT64(imm21 << 12, 33, initial_addend);
|
||||
A = initial_addend;
|
||||
A += (int64)reloc_addend;
|
||||
|
||||
/* Page(S+A) - Page(P) */
|
||||
X = Page((int64)S + A) - Page((int64)P);
|
||||
|
||||
/* Check overflow: +-4GB */
|
||||
if (X > ((int64)4 * BH_GB) || X < ((int64)-4 * BH_GB)) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module load failed: "
|
||||
"target address out of range.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* write the imm21 back to instruction */
|
||||
immhi19 = (int32)(((X >> 12) >> 2) & 0x7FFFF);
|
||||
immlo2 = (int32)((X >> 12) & 0x3);
|
||||
*(int32*)P = (insn & 0x9F00001F) | (immlo2 << 29) | (immhi19 << 5);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case R_AARCH64_ADD_ABS_LO12_NC:
|
||||
{
|
||||
void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
|
||||
int64 X, A, initial_addend;
|
||||
int32 insn, imm12;
|
||||
|
||||
CHECK_RELOC_OFFSET(sizeof(int32));
|
||||
|
||||
insn = *(int32*)P;
|
||||
imm12 = (insn >> 10) & 0xFFF;
|
||||
|
||||
SIGN_EXTEND_TO_INT64(imm12, 12, initial_addend);
|
||||
A = initial_addend;
|
||||
A += (int64)reloc_addend;
|
||||
|
||||
/* S + A */
|
||||
X = (int64)S + A;
|
||||
|
||||
/* No need to check overflow for this reloction type */
|
||||
|
||||
/* write the imm12 back to instruction */
|
||||
*(int32*)P = (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (error_buf != NULL)
|
||||
snprintf(error_buf, error_buf_size,
|
||||
"Load relocation section failed: "
|
||||
"invalid relocation type %d.",
|
||||
reloc_type);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -9,10 +9,6 @@
|
||||
#define R_ARM_JMP24 29 /* PC relative 24 bit (B/BL<cond>). */
|
||||
#define R_ARM_ABS32 2 /* Direct 32 bit */
|
||||
|
||||
#ifndef BH_MB
|
||||
#define BH_MB 1024 * 1024
|
||||
#endif
|
||||
|
||||
void __divdi3();
|
||||
void __udivdi3();
|
||||
void __moddi3();
|
||||
@ -163,7 +159,7 @@ init_plt_table(uint8 *plt)
|
||||
/* nop */
|
||||
*p++ = 0xe1a00000;
|
||||
/* symbol addr */
|
||||
*p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;;
|
||||
*p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;
|
||||
plt += get_plt_item_size();
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,10 +8,6 @@
|
||||
#define R_ARM_THM_CALL 10 /* PC relative (Thumb BL and ARMv5 Thumb BLX). */
|
||||
#define R_ARM_THM_JMP24 30 /* B.W */
|
||||
|
||||
#ifndef BH_MB
|
||||
#define BH_MB 1024 * 1024
|
||||
#endif
|
||||
|
||||
void __divdi3();
|
||||
void __udivdi3();
|
||||
void __moddi3();
|
||||
|
||||
@ -13,6 +13,8 @@ if (${WAMR_BUILD_TARGET} STREQUAL "X86_64" OR ${WAMR_BUILD_TARGET} STREQUAL "AMD
|
||||
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_64.c)
|
||||
elseif (${WAMR_BUILD_TARGET} STREQUAL "X86_32")
|
||||
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_32.c)
|
||||
elseif (${WAMR_BUILD_TARGET} MATCHES "AARCH64.*")
|
||||
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_aarch64.c)
|
||||
elseif (${WAMR_BUILD_TARGET} MATCHES "ARM.*")
|
||||
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_arm.c)
|
||||
elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*")
|
||||
|
||||
Reference in New Issue
Block a user