Use indirect call in pre-checker function to avoid relocation in XIP mode (#3142)
The stack profiler `aot_func#xxx` calls the wrapped function of `aot_func_internal#xxx` by using symbol reference, but in some platform like xtensa, it’s translated into a native long call, which needs to resolve the indirect address by relocation and breaks the XIP feature which requires the eliminating of relocation. The solution is to change the symbol reference into an indirect call through the lookup table, the code will be like this: ```llvm call_wrapped_func: ; preds = %stack_bound_check_block %func_addr1 = getelementptr inbounds ptr, ptr %func_ptrs_ptr, i32 75 %func_tmp2 = load ptr, ptr %func_addr1, align 4 tail call void %func_tmp2(ptr %exec_env) ret void ```
This commit is contained in:
committed by
GitHub
parent
2349df1271
commit
4f6d70bc52
@ -24,6 +24,8 @@ create_native_stack_bound(const AOTCompContext *comp_ctx,
|
||||
static bool
|
||||
create_native_stack_top_min(const AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
static bool
|
||||
create_func_ptrs(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
LLVMTypeRef
|
||||
wasm_type_to_llvm_type(const AOTCompContext *comp_ctx,
|
||||
@ -537,8 +539,51 @@ aot_build_precheck_function(AOTCompContext *comp_ctx, LLVMModuleRef module,
|
||||
if (ret_type == VOID_TYPE) {
|
||||
name = "";
|
||||
}
|
||||
LLVMValueRef retval =
|
||||
LLVMBuildCall2(b, func_type, wrapped_func, params, param_count, name);
|
||||
|
||||
LLVMValueRef retval;
|
||||
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) {
|
||||
goto fail;
|
||||
}
|
||||
@ -734,7 +779,9 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module,
|
||||
}
|
||||
|
||||
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);
|
||||
unsigned int kind =
|
||||
LLVMGetEnumAttributeKindForName("noinline", strlen("noinline"));
|
||||
|
||||
Reference in New Issue
Block a user