aot: Make precheck functions use short-call for xtensa (#3418)

Note: this breaks AOT ABI for xtensa again because of a revert of an ABI-breaking change.
This commit is contained in:
YAMAMOTO Takashi 2024-05-13 17:55:00 +09:00 committed by GitHub
parent c6d42db598
commit 8f098a5905
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 28 additions and 134 deletions

View File

@ -261,7 +261,7 @@ def main():
"xtensa": { "xtensa": {
"repo": "https://github.com/espressif/llvm-project.git", "repo": "https://github.com/espressif/llvm-project.git",
"repo_ssh": "git@github.com:espressif/llvm-project.git", "repo_ssh": "git@github.com:espressif/llvm-project.git",
"branch": "xtensa_release_15.x", "branch": "xtensa_release_17.0.1",
}, },
"default": { "default": {
"repo": "https://github.com/llvm/llvm-project.git", "repo": "https://github.com/llvm/llvm-project.git",

View File

@ -2522,26 +2522,15 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module,
const uint8 *p = buf, *p_end = buf_end; const uint8 *p = buf, *p_end = buf_end;
uint32 i; uint32 i;
uint64 size, text_offset; uint64 size, text_offset;
uint32 func_count = module->func_count;
#if defined(BUILD_TARGET_XTENSA) size = sizeof(void *) * (uint64)module->func_count;
/*
* For Xtensa XIP, real func_count is doubled, including aot_func and
* aot_func_internal, so need to multiply func_count by 2 here.
*/
if (module->is_indirect_mode) {
func_count *= 2;
}
#endif
size = sizeof(void *) * (uint64)func_count;
if (size > 0 if (size > 0
&& !(module->func_ptrs = && !(module->func_ptrs =
loader_malloc(size, error_buf, error_buf_size))) { loader_malloc(size, error_buf, error_buf_size))) {
return false; return false;
} }
for (i = 0; i < func_count; i++) { for (i = 0; i < module->func_count; i++) {
if (sizeof(void *) == 8) { if (sizeof(void *) == 8) {
read_uint64(p, p_end, text_offset); read_uint64(p, p_end, text_offset);
} }
@ -2576,14 +2565,14 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module,
module->start_function = NULL; module->start_function = NULL;
} }
size = sizeof(uint32) * (uint64)func_count; size = sizeof(uint32) * (uint64)module->func_count;
if (size > 0 if (size > 0
&& !(module->func_type_indexes = && !(module->func_type_indexes =
loader_malloc(size, error_buf, error_buf_size))) { loader_malloc(size, error_buf, error_buf_size))) {
return false; return false;
} }
for (i = 0; i < func_count; i++) { for (i = 0; i < module->func_count; i++) {
read_uint32(p, p_end, module->func_type_indexes[i]); read_uint32(p, p_end, module->func_type_indexes[i]);
if (module->func_type_indexes[i] >= module->type_count) { if (module->func_type_indexes[i] >= module->type_count) {
set_error_buf(error_buf, error_buf_size, "unknown type"); set_error_buf(error_buf, error_buf_size, "unknown type");

View File

@ -1153,21 +1153,10 @@ init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module,
{ {
uint32 i; uint32 i;
void **func_ptrs; void **func_ptrs;
uint32 func_count = module->func_count; uint64 total_size = ((uint64)module->import_func_count + module->func_count)
#if defined(BUILD_TARGET_XTENSA) * sizeof(void *);
/*
* For Xtensa XIP, real func_count is doubled, including aot_func and
* aot_func_internal, so need to multiply func_count by 2 here.
*/
if (module->is_indirect_mode) {
func_count *= 2;
}
#endif
uint64 total_size = if (module->import_func_count + module->func_count == 0)
((uint64)module->import_func_count + func_count) * sizeof(void *);
if (module->import_func_count + func_count == 0)
return true; return true;
/* Allocate memory */ /* Allocate memory */
@ -1189,8 +1178,8 @@ init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module,
} }
/* Set defined function pointers */ /* Set defined function pointers */
bh_memcpy_s(func_ptrs, sizeof(void *) * func_count, module->func_ptrs, bh_memcpy_s(func_ptrs, sizeof(void *) * module->func_count,
sizeof(void *) * func_count); module->func_ptrs, sizeof(void *) * module->func_count);
return true; return true;
} }
@ -1200,21 +1189,10 @@ init_func_type_indexes(AOTModuleInstance *module_inst, AOTModule *module,
{ {
uint32 i; uint32 i;
uint32 *func_type_index; uint32 *func_type_index;
uint32 func_count = module->func_count; uint64 total_size = ((uint64)module->import_func_count + module->func_count)
#if defined(BUILD_TARGET_XTENSA) * sizeof(uint32);
/*
* For Xtensa XIP, real func_count is doubled, including aot_func and
* aot_func_internal, so need to multiply func_count by 2 here.
*/
if (module->is_indirect_mode) {
func_count *= 2;
}
#endif
uint64 total_size = if (module->import_func_count + module->func_count == 0)
((uint64)module->import_func_count + func_count) * sizeof(uint32);
if (module->import_func_count + func_count == 0)
return true; return true;
/* Allocate memory */ /* Allocate memory */
@ -1228,8 +1206,8 @@ init_func_type_indexes(AOTModuleInstance *module_inst, AOTModule *module,
for (i = 0; i < module->import_func_count; i++, func_type_index++) for (i = 0; i < module->import_func_count; i++, func_type_index++)
*func_type_index = module->import_funcs[i].func_type_index; *func_type_index = module->import_funcs[i].func_type_index;
bh_memcpy_s(func_type_index, sizeof(uint32) * func_count, bh_memcpy_s(func_type_index, sizeof(uint32) * module->func_count,
module->func_type_indexes, sizeof(uint32) * func_count); module->func_type_indexes, sizeof(uint32) * module->func_count);
return true; return true;
} }

View File

@ -112,16 +112,6 @@ is_little_endian_binary(const AOTObjectData *obj_data)
return obj_data->target_info.bin_type & 1 ? false : true; return obj_data->target_info.bin_type & 1 ? false : true;
} }
static bool
need_call_wrapped_indirect(const AOTObjectData *obj_data)
{
const bool need_precheck = obj_data->comp_ctx->enable_stack_bound_check
|| obj_data->comp_ctx->enable_stack_estimation;
return obj_data->comp_ctx->is_indirect_mode && need_precheck
&& !strncmp(obj_data->comp_ctx->target_arch, "xtensa", 6);
}
static bool static bool
str_starts_with(const char *str, const char *prefix) str_starts_with(const char *str, const char *prefix)
{ {
@ -828,10 +818,6 @@ get_func_section_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
/* function type indexes */ /* function type indexes */
size += (uint32)sizeof(uint32) * comp_data->func_count; size += (uint32)sizeof(uint32) * comp_data->func_count;
/* aot_func#xxx + aot_func_internal#xxx in XIP mode for xtensa */
if (need_call_wrapped_indirect(obj_data))
size *= 2;
/* max_local_cell_nums */ /* max_local_cell_nums */
size += (uint32)sizeof(uint32) * comp_data->func_count; size += (uint32)sizeof(uint32) * comp_data->func_count;
@ -2590,30 +2576,9 @@ aot_emit_func_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
EMIT_U64(func->text_offset); EMIT_U64(func->text_offset);
} }
if (need_call_wrapped_indirect(obj_data)) {
/*
* Explicitly emit aot_func_internal#xxx for Xtensa XIP, therefore,
* for aot_func#xxx, func_indexes ranged from 0 ~ func_count,
* for aot_func_internal#xxxx, from func_count + 1 ~ 2 * func_count.
*/
for (i = 0, func = obj_data->funcs; i < obj_data->func_count;
i++, func++) {
if (is_32bit_binary(obj_data))
EMIT_U32(func->text_offset_of_aot_func_internal);
else
EMIT_U64(func->text_offset_of_aot_func_internal);
}
}
for (i = 0; i < comp_data->func_count; i++) for (i = 0; i < comp_data->func_count; i++)
EMIT_U32(funcs[i]->func_type_index); EMIT_U32(funcs[i]->func_type_index);
if (need_call_wrapped_indirect(obj_data)) {
/* func_type_index for aot_func_internal#xxxx */
for (i = 0; i < comp_data->func_count; i++)
EMIT_U32(funcs[i]->func_type_index);
}
for (i = 0; i < comp_data->func_count; i++) { for (i = 0; i < comp_data->func_count; i++) {
uint32 max_local_cell_num = uint32 max_local_cell_num =
funcs[i]->param_cell_num + funcs[i]->local_cell_num; funcs[i]->param_cell_num + funcs[i]->local_cell_num;

View File

@ -24,8 +24,6 @@ create_native_stack_bound(const AOTCompContext *comp_ctx,
static bool static bool
create_native_stack_top_min(const AOTCompContext *comp_ctx, create_native_stack_top_min(const AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx); AOTFuncContext *func_ctx);
static bool
create_func_ptrs(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
LLVMTypeRef LLVMTypeRef
wasm_type_to_llvm_type(const AOTCompContext *comp_ctx, wasm_type_to_llvm_type(const AOTCompContext *comp_ctx,
@ -539,51 +537,8 @@ aot_build_precheck_function(AOTCompContext *comp_ctx, LLVMModuleRef module,
if (ret_type == VOID_TYPE) { if (ret_type == VOID_TYPE) {
name = ""; name = "";
} }
LLVMValueRef retval =
LLVMValueRef retval; LLVMBuildCall2(b, func_type, wrapped_func, params, param_count, name);
if (comp_ctx->is_indirect_mode
&& !strncmp(comp_ctx->target_arch, "xtensa", 6)) {
/* call wrapped_func indirectly */
if (!create_func_ptrs(comp_ctx, func_ctx)) {
goto fail;
}
LLVMTypeRef func_ptr_type;
LLVMValueRef wrapped_func_indirect;
uint32 import_func_count = comp_ctx->comp_data->import_func_count;
uint32 func_count = comp_ctx->func_ctx_count;
/* Check function index */
if (func_index >= import_func_count + func_count) {
aot_set_last_error("Function index out of range.");
goto fail;
}
/* Get function type */
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
aot_set_last_error("create LLVM function type failed.");
goto fail;
}
/*
* func_index layout :
* aot_func#xxx, range from 0 ~ func_conut - 1;
* aot_func#internal#xxx, range from func_conut ~ 2 * func_conut - 1;
*/
if (!(wrapped_func_indirect = aot_get_func_from_table(
comp_ctx, func_ctx->func_ptrs, func_ptr_type,
func_index + func_count + import_func_count))) {
goto fail;
}
/* Call the function indirectly */
retval = LLVMBuildCall2(b, func_type, wrapped_func_indirect, params,
param_count, name);
}
else
retval = LLVMBuildCall2(b, func_type, wrapped_func, params, param_count,
name);
if (!retval) { if (!retval) {
goto fail; goto fail;
} }
@ -780,9 +735,7 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module,
} }
if (need_precheck) { if (need_precheck) {
if (!comp_ctx->is_jit_mode if (!comp_ctx->is_jit_mode)
&& !(comp_ctx->is_indirect_mode
&& !strncmp(comp_ctx->target_arch, "xtensa", 6)))
LLVMSetLinkage(func, LLVMInternalLinkage); LLVMSetLinkage(func, LLVMInternalLinkage);
unsigned int kind = unsigned int kind =
LLVMGetEnumAttributeKindForName("noinline", strlen("noinline")); LLVMGetEnumAttributeKindForName("noinline", strlen("noinline"));
@ -790,7 +743,16 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module,
LLVMCreateEnumAttribute(comp_ctx->context, kind, 0); LLVMCreateEnumAttribute(comp_ctx->context, kind, 0);
LLVMAddAttributeAtIndex(func, LLVMAttributeFunctionIndex, LLVMAddAttributeAtIndex(func, LLVMAttributeFunctionIndex,
attr_noinline); attr_noinline);
if (!strcmp(comp_ctx->target_arch, "xtensa")) {
/* Because "func" is only called by "precheck_func", short-call
* should be ok. We prefer short-call because it's smaller
* and more importantly doesn't involve relocations.
*/
LLVMAttributeRef attr_short_call = LLVMCreateStringAttribute(
comp_ctx->context, "short-call", strlen("short-call"), "", 0);
LLVMAddAttributeAtIndex(func, LLVMAttributeFunctionIndex,
attr_short_call);
}
if (!aot_build_precheck_function(comp_ctx, module, precheck_func, if (!aot_build_precheck_function(comp_ctx, module, precheck_func,
func_index, func_type, func)) func_index, func_type, func))
goto fail; goto fail;