Implement XIP feature and enable ARC target support (#694)
Implement XIP (Execution In Place) feature for AOT mode to enable running the AOT code inside AOT file directly, without memory mapping the executable memory for AOT code and applying relocations for text section. Developer can use wamrc with "--enable-indirect-mode --disable-llvm-intrinsics" flags to generate the AOT file and run iwasm with "--xip" flag. Known issues: there might still be some relocations in the text section which access the ".rodata" like sections. And also enable ARC target support for both interpreter mode and AOT mode. Signed-off-by: Wenyong Huang <wenyong.huang@intel.com>
This commit is contained in:
@ -229,6 +229,12 @@ typedef struct AOTCompData {
|
||||
WASMModule *wasm_module;
|
||||
} AOTCompData;
|
||||
|
||||
typedef struct AOTNativeSymbol {
|
||||
bh_list_link link;
|
||||
const char *symbol;
|
||||
int32 index;
|
||||
} AOTNativeSymbol;
|
||||
|
||||
AOTCompData*
|
||||
aot_create_comp_data(WASMModule *module);
|
||||
|
||||
|
||||
@ -2111,19 +2111,26 @@ bool
|
||||
aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
|
||||
{
|
||||
char *err = NULL;
|
||||
LLVMCodeGenFileType file_type = LLVMObjectFile;
|
||||
LLVMTargetRef target =
|
||||
LLVMGetTargetMachineTarget(comp_ctx->target_machine);
|
||||
|
||||
bh_print_time("Begin to emit object file");
|
||||
|
||||
if (!strncmp(LLVMGetTargetName(target), "arc", 3))
|
||||
/* Emit to assmelby file instead for arc target
|
||||
as it cannot emit to object file */
|
||||
file_type = LLVMAssemblyFile;
|
||||
|
||||
if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine,
|
||||
comp_ctx->module,
|
||||
file_name,
|
||||
LLVMObjectFile,
|
||||
file_name, file_type,
|
||||
&err) != 0) {
|
||||
if (err) {
|
||||
LLVMDisposeMessage(err);
|
||||
err = NULL;
|
||||
}
|
||||
aot_set_last_error("emit elf to memory buffer failed.");
|
||||
aot_set_last_error("emit elf to object file failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -790,6 +790,23 @@ get_relocation_section_size(AOTObjectData *obj_data)
|
||||
is_32bit_binary(obj_data->binary));
|
||||
}
|
||||
|
||||
static uint32
|
||||
get_native_symbol_list_size(AOTCompContext *comp_ctx)
|
||||
{
|
||||
uint32 len = 0;
|
||||
AOTNativeSymbol *sym = NULL;
|
||||
|
||||
sym = bh_list_first_elem(&comp_ctx->native_symbols);
|
||||
|
||||
while (sym) {
|
||||
len = align_uint(len, 2);
|
||||
len += get_string_size(sym->symbol);
|
||||
sym = bh_list_elem_next(sym);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static uint32
|
||||
get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
||||
AOTObjectData *obj_data)
|
||||
@ -835,6 +852,14 @@ get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
||||
size += (uint32)sizeof(uint32) * 2;
|
||||
size += get_relocation_section_size(obj_data);
|
||||
|
||||
if (get_native_symbol_list_size(comp_ctx) > 0) {
|
||||
/* emit only when threre are native symbols */
|
||||
size = align_uint(size, 4);
|
||||
/* section id + section size + sub section id + symbol count */
|
||||
size += (uint32)sizeof(uint32) * 4;
|
||||
size += get_native_symbol_list_size(comp_ctx);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@ -1505,6 +1530,38 @@ aot_emit_relocation_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
aot_emit_native_symbol(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
||||
AOTCompContext *comp_ctx)
|
||||
{
|
||||
uint32 offset = *p_offset;
|
||||
AOTNativeSymbol *sym = NULL;
|
||||
|
||||
if (bh_list_length(&comp_ctx->native_symbols) == 0)
|
||||
/* emit only when threre are native symbols */
|
||||
return true;
|
||||
|
||||
*p_offset = offset = align_uint(offset, 4);
|
||||
|
||||
EMIT_U32(AOT_SECTION_TYPE_CUSTOM);
|
||||
/* sub section id + symbol count + symbol list */
|
||||
EMIT_U32(sizeof(uint32) * 2 + get_native_symbol_list_size(comp_ctx));
|
||||
EMIT_U32(AOT_CUSTOM_SECTION_NATIVE_SYMBOL);
|
||||
EMIT_U32(bh_list_length(&comp_ctx->native_symbols));
|
||||
|
||||
sym = bh_list_first_elem(&comp_ctx->native_symbols);
|
||||
|
||||
while (sym) {
|
||||
offset = align_uint(offset, 2);
|
||||
EMIT_STR(sym->symbol);
|
||||
sym = bh_list_elem_next(sym);
|
||||
}
|
||||
|
||||
*p_offset = offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef uint32 U32;
|
||||
typedef int32 I32;
|
||||
typedef uint16 U16;
|
||||
@ -2164,6 +2221,8 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
|
||||
{
|
||||
char *err = NULL;
|
||||
AOTObjectData *obj_data;
|
||||
LLVMTargetRef target =
|
||||
LLVMGetTargetMachineTarget(comp_ctx->target_machine);
|
||||
|
||||
bh_print_time("Begin to emit object file to buffer");
|
||||
|
||||
@ -2173,11 +2232,76 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
|
||||
}
|
||||
memset(obj_data, 0, sizeof(AOTObjectData));
|
||||
|
||||
if (LLVMTargetMachineEmitToMemoryBuffer(comp_ctx->target_machine,
|
||||
comp_ctx->module,
|
||||
LLVMObjectFile,
|
||||
&err,
|
||||
&obj_data->mem_buf) != 0) {
|
||||
bh_print_time("Begin to emit object file");
|
||||
|
||||
if (!strncmp(LLVMGetTargetName(target), "arc", 3)) {
|
||||
/* Emit to assmelby file instead for arc target
|
||||
as it cannot emit to object file */
|
||||
char file_name[] = "wasm-XXXXXX", buf[128];
|
||||
int fd, ret;
|
||||
|
||||
if ((fd = mkstemp(file_name)) <= 0) {
|
||||
aot_set_last_error("make temp file failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* close and remove temp file */
|
||||
close(fd);
|
||||
unlink(file_name);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s%s", file_name, ".s");
|
||||
if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine,
|
||||
comp_ctx->module,
|
||||
buf, LLVMAssemblyFile,
|
||||
&err) != 0) {
|
||||
if (err) {
|
||||
LLVMDisposeMessage(err);
|
||||
err = NULL;
|
||||
}
|
||||
aot_set_last_error("emit elf to object file failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* call arc gcc to compile assembly file to object file */
|
||||
/* TODO: get arc gcc from environment variable firstly
|
||||
and check whether the toolchain exists actually */
|
||||
snprintf(buf, sizeof(buf), "%s%s%s%s%s%s",
|
||||
"/opt/zephyr-sdk/arc-zephyr-elf/bin/arc-zephyr-elf-gcc ",
|
||||
"-mcpu=arcem -o ", file_name, ".o -c ", file_name, ".s");
|
||||
/* TODO: use try..catch to handle possible exceptions */
|
||||
ret = system(buf);
|
||||
/* remove temp assembly file */
|
||||
snprintf(buf, sizeof(buf), "%s%s", file_name, ".s");
|
||||
unlink(buf);
|
||||
|
||||
if (ret != 0) {
|
||||
aot_set_last_error("failed to compile asm file to obj file "
|
||||
"with arc gcc toolchain.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* create memory buffer from object file */
|
||||
snprintf(buf, sizeof(buf), "%s%s", file_name, ".o");
|
||||
ret = LLVMCreateMemoryBufferWithContentsOfFile(buf,
|
||||
&obj_data->mem_buf,
|
||||
&err);
|
||||
/* remove temp object file */
|
||||
snprintf(buf, sizeof(buf), "%s%s",file_name, ".o");
|
||||
unlink(buf);
|
||||
|
||||
if (ret != 0) {
|
||||
if (err) {
|
||||
LLVMDisposeMessage(err);
|
||||
err = NULL;
|
||||
}
|
||||
aot_set_last_error("create mem buffer with file failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else if (LLVMTargetMachineEmitToMemoryBuffer(comp_ctx->target_machine,
|
||||
comp_ctx->module,
|
||||
LLVMObjectFile, &err,
|
||||
&obj_data->mem_buf) != 0) {
|
||||
if (err) {
|
||||
LLVMDisposeMessage(err);
|
||||
err = NULL;
|
||||
@ -2242,7 +2366,8 @@ aot_emit_aot_file_buf(AOTCompContext *comp_ctx,
|
||||
|| !aot_emit_text_section(buf, buf_end, &offset, comp_data, obj_data)
|
||||
|| !aot_emit_func_section(buf, buf_end, &offset, comp_data, obj_data)
|
||||
|| !aot_emit_export_section(buf, buf_end, &offset, comp_data, obj_data)
|
||||
|| !aot_emit_relocation_section(buf, buf_end, &offset, comp_data, obj_data))
|
||||
|| !aot_emit_relocation_section(buf, buf_end, &offset, comp_data, obj_data)
|
||||
|| !aot_emit_native_symbol(buf, buf_end, &offset, comp_ctx))
|
||||
goto fail2;
|
||||
|
||||
#if 0
|
||||
|
||||
@ -68,6 +68,24 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (comp_ctx->is_indirect_mode) {
|
||||
int32 func_index;
|
||||
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
func_index = aot_get_native_symbol_index(
|
||||
comp_ctx, "aot_set_exception_with_id");
|
||||
if (func_index < 0) {
|
||||
return false;
|
||||
}
|
||||
if (!(func =
|
||||
aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
|
||||
func_ptr_type, func_index))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Create LLVM function with external function pointer */
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module,
|
||||
|
||||
@ -168,10 +168,26 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (comp_ctx->is_indirect_mode) {
|
||||
int32 func_index;
|
||||
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
return false;
|
||||
}
|
||||
func_index =
|
||||
aot_get_native_symbol_index(comp_ctx, func_name);
|
||||
if (func_index < 0) {
|
||||
return false;
|
||||
}
|
||||
if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
|
||||
func_ptr_type, func_index))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
|
||||
&& !(func = LLVMAddFunction(comp_ctx->module,
|
||||
func_name, func_type))) {
|
||||
&& !(func =
|
||||
LLVMAddFunction(comp_ctx->module, func_name, func_type))) {
|
||||
aot_set_last_error("add LLVM function failed.");
|
||||
return false;
|
||||
}
|
||||
@ -547,7 +563,22 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
func = func_ctxes[func_idx - import_func_count]->func;
|
||||
if (comp_ctx->is_indirect_mode) {
|
||||
LLVMTypeRef func_ptr_type;
|
||||
|
||||
if (!(func_ptr_type = LLVMPointerType(
|
||||
func_ctxes[func_idx - import_func_count]->func_type, 0))) {
|
||||
aot_set_last_error("construct func ptr type failed.");
|
||||
goto fail;
|
||||
}
|
||||
if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->func_ptrs,
|
||||
func_ptr_type, func_idx))) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
func = func_ctxes[func_idx - import_func_count]->func;
|
||||
}
|
||||
aot_func = func_ctxes[func_idx - import_func_count]->aot_func;
|
||||
callee_cell_num = aot_func->param_cell_num + aot_func->local_cell_num + 1;
|
||||
|
||||
@ -650,6 +681,22 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (comp_ctx->is_indirect_mode) {
|
||||
int32 func_index;
|
||||
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
return false;
|
||||
}
|
||||
func_index =
|
||||
aot_get_native_symbol_index(comp_ctx, func_name);
|
||||
if (func_index < 0) {
|
||||
return false;
|
||||
}
|
||||
if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
|
||||
func_ptr_type, func_index))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
|
||||
&& !(func = LLVMAddFunction(comp_ctx->module,
|
||||
|
||||
@ -651,6 +651,7 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
LLVMValueRef mem_size = get_memory_curr_page_count(comp_ctx, func_ctx);
|
||||
LLVMValueRef delta, param_values[2], ret_value, func, value;
|
||||
LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
|
||||
int32 func_index;
|
||||
|
||||
if (!mem_size)
|
||||
return false;
|
||||
@ -679,6 +680,21 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (comp_ctx->is_indirect_mode) {
|
||||
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
return false;
|
||||
}
|
||||
func_index =
|
||||
aot_get_native_symbol_index(comp_ctx, "aot_enlarge_memory");
|
||||
if (func_index < 0) {
|
||||
return false;
|
||||
}
|
||||
if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
|
||||
func_ptr_type, func_index))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
char *func_name = "aot_enlarge_memory";
|
||||
/* AOT mode, delcare the function */
|
||||
@ -715,7 +731,6 @@ fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
|
||||
static LLVMValueRef
|
||||
@ -924,6 +939,8 @@ aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len)))
|
||||
return false;
|
||||
|
||||
/* TODO: lookup func ptr of "memmove" to call for XIP mode */
|
||||
|
||||
if (!(res = LLVMBuildMemMove(comp_ctx->builder, dst_addr, 1,
|
||||
src_addr, 1, len))) {
|
||||
aot_set_last_error("llvm build memmove failed.");
|
||||
@ -947,7 +964,13 @@ aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len)))
|
||||
return false;
|
||||
|
||||
val = LLVMBuildIntCast2(comp_ctx->builder, val, INT8_TYPE, true, "mem_set_value");
|
||||
if (!(val = LLVMBuildIntCast2(comp_ctx->builder, val, INT8_TYPE,
|
||||
true, "mem_set_value"))) {
|
||||
aot_set_last_error("llvm build int cast2 failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* TODO: lookup func ptr of "memset" to call for XIP mode */
|
||||
|
||||
if (!(res = LLVMBuildMemSet(comp_ctx->builder, dst_addr,
|
||||
val, len, 1))) {
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "aot_emit_exception.h"
|
||||
#include "aot_emit_control.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
#include "../aot/aot_intrinsic.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
@ -138,6 +139,7 @@
|
||||
/* Call llvm constrained floating-point intrinsic */
|
||||
static LLVMValueRef
|
||||
call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_f32,
|
||||
const char *intrinsic,
|
||||
...)
|
||||
@ -145,14 +147,18 @@ call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
|
||||
va_list param_value_list;
|
||||
LLVMValueRef ret;
|
||||
LLVMTypeRef param_types[4], ret_type = is_f32 ? F32_TYPE : F64_TYPE;
|
||||
int param_count = ((comp_ctx->disable_llvm_intrinsics == false)
|
||||
|| aot_intrinsic_check_capability(comp_ctx, intrinsic))
|
||||
? 4 : 2;
|
||||
|
||||
param_types[0] = param_types[1] = ret_type;
|
||||
param_types[2] = param_types[3] = MD_TYPE;
|
||||
|
||||
va_start(param_value_list, intrinsic);
|
||||
|
||||
ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, param_types,
|
||||
4, param_value_list);
|
||||
ret =
|
||||
aot_call_llvm_intrinsic_v(comp_ctx, func_ctx, intrinsic, ret_type,
|
||||
param_types, param_count, param_value_list);
|
||||
|
||||
va_end(param_value_list);
|
||||
|
||||
@ -162,6 +168,7 @@ call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
|
||||
/* Call llvm constrained libm-equivalent intrinsic */
|
||||
static LLVMValueRef
|
||||
call_llvm_libm_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_f32,
|
||||
const char *intrinsic,
|
||||
...)
|
||||
@ -175,7 +182,7 @@ call_llvm_libm_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
|
||||
|
||||
va_start(param_value_list, intrinsic);
|
||||
|
||||
ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, param_types,
|
||||
ret = aot_call_llvm_intrinsic_v(comp_ctx, func_ctx, intrinsic, ret_type, param_types,
|
||||
3, param_value_list);
|
||||
|
||||
va_end(param_value_list);
|
||||
@ -185,6 +192,7 @@ call_llvm_libm_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
|
||||
|
||||
static LLVMValueRef
|
||||
compile_op_float_min_max(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_f32,
|
||||
LLVMValueRef left,
|
||||
LLVMValueRef right,
|
||||
@ -230,8 +238,9 @@ compile_op_float_min_max(AOTCompContext *comp_ctx,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(cmp = aot_call_llvm_intrinsic(comp_ctx, intrinsic, ret_type,
|
||||
param_types, 2, left, right)))
|
||||
if (!(cmp =
|
||||
aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, ret_type,
|
||||
param_types, 2, left, right)))
|
||||
return NULL;
|
||||
|
||||
if (!(cmp = LLVMBuildSelect(comp_ctx->builder,
|
||||
@ -266,13 +275,14 @@ typedef enum BitCountType {
|
||||
POP_CNT64
|
||||
} BitCountType;
|
||||
|
||||
static char *bit_cnt_llvm_intrinsic[] = { "llvm.ctlz.i32",
|
||||
"llvm.ctlz.i64",
|
||||
"llvm.cttz.i32",
|
||||
"llvm.cttz.i64",
|
||||
"llvm.ctpop.i32",
|
||||
"llvm.ctpop.i64",
|
||||
};
|
||||
static char *bit_cnt_llvm_intrinsic[] = {
|
||||
"llvm.ctlz.i32",
|
||||
"llvm.ctlz.i64",
|
||||
"llvm.cttz.i32",
|
||||
"llvm.cttz.i64",
|
||||
"llvm.ctpop.i32",
|
||||
"llvm.ctpop.i64",
|
||||
};
|
||||
|
||||
static bool
|
||||
aot_compile_int_bit_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
@ -290,6 +300,7 @@ aot_compile_int_bit_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
/* Call the LLVM intrinsic function */
|
||||
if (type < POP_CNT32)
|
||||
DEF_INT_UNARY_OP(aot_call_llvm_intrinsic(comp_ctx,
|
||||
func_ctx,
|
||||
bit_cnt_llvm_intrinsic[type],
|
||||
ret_type,
|
||||
param_types,
|
||||
@ -299,6 +310,7 @@ aot_compile_int_bit_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
NULL);
|
||||
else
|
||||
DEF_INT_UNARY_OP(aot_call_llvm_intrinsic(comp_ctx,
|
||||
func_ctx,
|
||||
bit_cnt_llvm_intrinsic[type],
|
||||
ret_type,
|
||||
param_types,
|
||||
@ -823,6 +835,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
else
|
||||
DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
|
||||
comp_ctx,
|
||||
func_ctx,
|
||||
is_f32,
|
||||
(is_f32
|
||||
? "llvm.experimental.constrained.fadd.f32"
|
||||
@ -840,6 +853,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
else
|
||||
DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
|
||||
comp_ctx,
|
||||
func_ctx,
|
||||
is_f32,
|
||||
(is_f32
|
||||
? "llvm.experimental.constrained.fsub.f32"
|
||||
@ -857,6 +871,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
else
|
||||
DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
|
||||
comp_ctx,
|
||||
func_ctx,
|
||||
is_f32,
|
||||
(is_f32
|
||||
? "llvm.experimental.constrained.fmul.f32"
|
||||
@ -874,6 +889,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
else
|
||||
DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
|
||||
comp_ctx,
|
||||
func_ctx,
|
||||
is_f32,
|
||||
(is_f32
|
||||
? "llvm.experimental.constrained.fdiv.f32"
|
||||
@ -886,6 +902,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
return true;
|
||||
case FLOAT_MIN:
|
||||
DEF_FP_BINARY_OP(compile_op_float_min_max(comp_ctx,
|
||||
func_ctx,
|
||||
is_f32,
|
||||
left,
|
||||
right,
|
||||
@ -894,6 +911,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
return true;
|
||||
case FLOAT_MAX:
|
||||
DEF_FP_BINARY_OP(compile_op_float_min_max(comp_ctx,
|
||||
func_ctx,
|
||||
is_f32,
|
||||
left,
|
||||
right,
|
||||
@ -912,6 +930,7 @@ fail:
|
||||
|
||||
static LLVMValueRef
|
||||
call_llvm_float_math_intrinsic(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_f32,
|
||||
const char *intrinsic,
|
||||
...)
|
||||
@ -924,8 +943,8 @@ call_llvm_float_math_intrinsic(AOTCompContext *comp_ctx,
|
||||
|
||||
va_start(param_value_list, intrinsic);
|
||||
|
||||
ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, ¶m_type,
|
||||
1, param_value_list);
|
||||
ret = aot_call_llvm_intrinsic_v(comp_ctx, func_ctx, intrinsic, ret_type,
|
||||
¶m_type, 1, param_value_list);
|
||||
|
||||
va_end(param_value_list);
|
||||
|
||||
@ -939,6 +958,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
switch (math_op) {
|
||||
case FLOAT_ABS:
|
||||
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
|
||||
func_ctx,
|
||||
is_f32,
|
||||
is_f32 ? "llvm.fabs.f32" :
|
||||
"llvm.fabs.f64",
|
||||
@ -952,6 +972,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
|
||||
case FLOAT_CEIL:
|
||||
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
|
||||
func_ctx,
|
||||
is_f32,
|
||||
is_f32 ? "llvm.ceil.f32" :
|
||||
"llvm.ceil.f64",
|
||||
@ -960,6 +981,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
return true;
|
||||
case FLOAT_FLOOR:
|
||||
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
|
||||
func_ctx,
|
||||
is_f32,
|
||||
is_f32 ? "llvm.floor.f32":
|
||||
"llvm.floor.f64",
|
||||
@ -968,6 +990,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
return true;
|
||||
case FLOAT_TRUNC:
|
||||
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
|
||||
func_ctx,
|
||||
is_f32,
|
||||
is_f32 ? "llvm.trunc.f32" :
|
||||
"llvm.trunc.f64",
|
||||
@ -976,6 +999,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
return true;
|
||||
case FLOAT_NEAREST:
|
||||
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
|
||||
func_ctx,
|
||||
is_f32,
|
||||
is_f32 ? "llvm.rint.f32" :
|
||||
"llvm.rint.f64",
|
||||
@ -983,8 +1007,10 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
NULL);
|
||||
return true;
|
||||
case FLOAT_SQRT:
|
||||
if (is_targeting_soft_float(comp_ctx, is_f32))
|
||||
if (is_targeting_soft_float(comp_ctx, is_f32)
|
||||
|| comp_ctx->disable_llvm_intrinsics)
|
||||
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
|
||||
func_ctx,
|
||||
is_f32,
|
||||
is_f32 ? "llvm.sqrt.f32" :
|
||||
"llvm.sqrt.f64",
|
||||
@ -993,6 +1019,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
else
|
||||
DEF_FP_UNARY_OP(call_llvm_libm_experimental_constrained_intrinsic(
|
||||
comp_ctx,
|
||||
func_ctx,
|
||||
is_f32,
|
||||
(is_f32
|
||||
? "llvm.experimental.constrained.sqrt.f32"
|
||||
@ -1022,6 +1049,7 @@ compile_float_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
param_types[0] = param_types[1] = ret_type = is_f32 ? F32_TYPE : F64_TYPE;
|
||||
|
||||
DEF_FP_BINARY_OP(aot_call_llvm_intrinsic(comp_ctx,
|
||||
func_ctx,
|
||||
is_f32 ? "llvm.copysign.f32" :
|
||||
"llvm.copysign.f64",
|
||||
ret_type,
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
#include "aot_compiler.h"
|
||||
#include "aot_emit_exception.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
|
||||
#include "../aot/aot_intrinsic.h"
|
||||
|
||||
LLVMTypeRef
|
||||
wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type)
|
||||
@ -38,7 +38,7 @@ wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type)
|
||||
*/
|
||||
static LLVMValueRef
|
||||
aot_add_llvm_func(AOTCompContext *comp_ctx, AOTFuncType *aot_func_type,
|
||||
uint32 func_index)
|
||||
uint32 func_index, LLVMTypeRef *p_func_type)
|
||||
{
|
||||
LLVMValueRef func = NULL;
|
||||
LLVMTypeRef *param_types, ret_type, func_type;
|
||||
@ -107,6 +107,9 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, AOTFuncType *aot_func_type,
|
||||
LLVMSetValueName(local_value, "");
|
||||
}
|
||||
|
||||
if (p_func_type)
|
||||
*p_func_type = func_type;
|
||||
|
||||
fail:
|
||||
wasm_runtime_free(param_types);
|
||||
return func;
|
||||
@ -604,6 +607,7 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
||||
LLVMValueRef stack_bound_offset = I32_FOUR, stack_bound_addr;
|
||||
LLVMValueRef aux_stack_bound_offset = I32_SIX, aux_stack_bound_addr;
|
||||
LLVMValueRef aux_stack_bottom_offset = I32_SEVEN, aux_stack_bottom_addr;
|
||||
LLVMValueRef native_symbol_offset = I32_EIGHT, native_symbol_addr;
|
||||
char local_name[32];
|
||||
uint64 size;
|
||||
uint32 i, j = 0;
|
||||
@ -621,7 +625,8 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
||||
func_ctx->aot_func = func;
|
||||
|
||||
/* Add LLVM function */
|
||||
if (!(func_ctx->func = aot_add_llvm_func(comp_ctx, aot_func_type, func_index)))
|
||||
if (!(func_ctx->func = aot_add_llvm_func(comp_ctx, aot_func_type,
|
||||
func_index, &func_ctx->func_type)))
|
||||
goto fail;
|
||||
|
||||
/* Create function's first AOTBlock */
|
||||
@ -741,6 +746,27 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(native_symbol_addr =
|
||||
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,
|
||||
&native_symbol_offset, 1, "native_symbol_addr"))) {
|
||||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(func_ctx->native_symbol =
|
||||
LLVMBuildLoad(comp_ctx->builder, native_symbol_addr,
|
||||
"native_symbol_tmp"))) {
|
||||
aot_set_last_error("llvm build bit cast failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(func_ctx->native_symbol =
|
||||
LLVMBuildBitCast(comp_ctx->builder, func_ctx->native_symbol,
|
||||
comp_ctx->exec_env_type, "native_symbol"))) {
|
||||
aot_set_last_error("llvm build bit cast failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < aot_func_type->param_count; i++, j++) {
|
||||
snprintf(local_name, sizeof(local_name), "l%d", i);
|
||||
func_ctx->locals[i] =
|
||||
@ -814,7 +840,7 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
||||
}
|
||||
else {
|
||||
if (!(func_ctx->last_alloca = LLVMBuildAlloca(comp_ctx->builder, INT8_TYPE,
|
||||
"stack_ptr"))) {
|
||||
"stack_ptr"))) {
|
||||
aot_set_last_error("llvm build alloca failed.");
|
||||
goto fail;
|
||||
}
|
||||
@ -1089,7 +1115,8 @@ static ArchItem valid_archs[] = {
|
||||
{ "thumbv8m.main", true },
|
||||
{ "thumbv8.1m.main", true },
|
||||
{ "riscv32", true},
|
||||
{ "riscv64", true}
|
||||
{ "riscv64", true},
|
||||
{ "arc", true }
|
||||
};
|
||||
|
||||
static const char *valid_abis[] = {
|
||||
@ -1230,6 +1257,10 @@ aot_create_comp_context(AOTCompData *comp_data,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (BH_LIST_ERROR == bh_list_init(&comp_ctx->native_symbols)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (option->enable_bulk_memory)
|
||||
comp_ctx->enable_bulk_memory = true;
|
||||
|
||||
@ -1248,6 +1279,12 @@ aot_create_comp_context(AOTCompData *comp_data,
|
||||
if (option->enable_aux_stack_check)
|
||||
comp_ctx->enable_aux_stack_check = true;
|
||||
|
||||
if (option->is_indirect_mode)
|
||||
comp_ctx->is_indirect_mode = true;
|
||||
|
||||
if (option->disable_llvm_intrinsics)
|
||||
comp_ctx->disable_llvm_intrinsics = true;
|
||||
|
||||
if (option->is_jit_mode) {
|
||||
char *triple_jit = NULL;
|
||||
|
||||
@ -1496,7 +1533,12 @@ aot_create_comp_context(AOTCompData *comp_data,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!LLVMTargetHasAsmBackend(target)) {
|
||||
/* Report error if target isn't arc and hasn't asm backend.
|
||||
For arc target, as it cannot emit to memory buffer of elf file currently,
|
||||
we let it emit to assembly file instead, and then call arc-gcc to compile
|
||||
asm file to elf file, and read elf file to memory buffer. */
|
||||
if (strncmp(comp_ctx->target_arch, "arc", 3)
|
||||
&& !LLVMTargetHasAsmBackend(target)) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"no asm backend for this target (%s).", LLVMGetTargetName(target));
|
||||
aot_set_last_error(buf);
|
||||
@ -1631,6 +1673,18 @@ aot_create_comp_context(AOTCompData *comp_data,
|
||||
aot_create_func_contexts(comp_data, comp_ctx)))
|
||||
goto fail;
|
||||
|
||||
if (cpu) {
|
||||
int len = strlen(cpu) + 1;
|
||||
if (!(comp_ctx->target_cpu = wasm_runtime_malloc(len))) {
|
||||
aot_set_last_error("allocate memory failed");
|
||||
goto fail;
|
||||
}
|
||||
bh_memcpy_s(comp_ctx->target_cpu, len, cpu, len);
|
||||
}
|
||||
|
||||
if (comp_ctx->disable_llvm_intrinsics)
|
||||
aot_intrinsic_fill_capability_flags(comp_ctx);
|
||||
|
||||
ret = comp_ctx;
|
||||
|
||||
fail:
|
||||
@ -1676,9 +1730,65 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx)
|
||||
aot_destroy_func_contexts(comp_ctx->func_ctxes,
|
||||
comp_ctx->func_ctx_count);
|
||||
|
||||
if (bh_list_length(&comp_ctx->native_symbols) > 0) {
|
||||
AOTNativeSymbol *sym = bh_list_first_elem(&comp_ctx->native_symbols);
|
||||
while (sym) {
|
||||
AOTNativeSymbol *t = bh_list_elem_next(sym);
|
||||
bh_list_remove(&comp_ctx->native_symbols, sym);
|
||||
wasm_runtime_free(sym);
|
||||
sym = t;
|
||||
}
|
||||
}
|
||||
|
||||
if (comp_ctx->target_cpu) {
|
||||
wasm_runtime_free(comp_ctx->target_cpu);
|
||||
}
|
||||
|
||||
wasm_runtime_free(comp_ctx);
|
||||
}
|
||||
|
||||
int32
|
||||
aot_get_native_symbol_index(AOTCompContext *comp_ctx, const char *symbol)
|
||||
{
|
||||
int32 idx = -1;
|
||||
AOTNativeSymbol *sym = NULL;
|
||||
|
||||
sym = bh_list_first_elem(&comp_ctx->native_symbols);
|
||||
|
||||
/* Lookup an existing symobl record */
|
||||
|
||||
while (sym) {
|
||||
if (strcmp(sym->symbol, symbol) == 0) {
|
||||
idx = sym->index;
|
||||
break;
|
||||
}
|
||||
sym = bh_list_elem_next(sym);
|
||||
}
|
||||
|
||||
/* Given symbol is not exist in list, then we alloc a new index for it */
|
||||
|
||||
if (idx < 0) {
|
||||
sym = wasm_runtime_malloc(sizeof(AOTNativeSymbol));
|
||||
|
||||
if (!sym) {
|
||||
aot_set_last_error("alloc native symbol failed.");
|
||||
return idx;
|
||||
}
|
||||
|
||||
idx = bh_list_length(&comp_ctx->native_symbols);
|
||||
sym->symbol = symbol;
|
||||
sym->index = idx;
|
||||
|
||||
if (BH_LIST_ERROR == bh_list_insert(&comp_ctx->native_symbols, sym)) {
|
||||
wasm_runtime_free(sym);
|
||||
aot_set_last_error("alloc index for native symbol failed.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void
|
||||
aot_value_stack_push(AOTValueStack *stack, AOTValue *value)
|
||||
{
|
||||
@ -1901,6 +2011,7 @@ aot_build_zero_function_ret(AOTCompContext *comp_ctx,
|
||||
|
||||
static LLVMValueRef
|
||||
__call_llvm_intrinsic(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMTypeRef *param_types,
|
||||
@ -1909,25 +2020,67 @@ __call_llvm_intrinsic(const AOTCompContext *comp_ctx,
|
||||
{
|
||||
LLVMValueRef func, ret;
|
||||
LLVMTypeRef func_type;
|
||||
const char *symname;
|
||||
int32 func_idx;
|
||||
|
||||
/* Declare llvm intrinsic function if necessary */
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, name))) {
|
||||
if (!(func_type = LLVMFunctionType(ret_type, param_types,
|
||||
(uint32)param_count, false))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
if (comp_ctx->disable_llvm_intrinsics
|
||||
&& (aot_intrinsic_check_capability(comp_ctx, name) == false)) {
|
||||
if (func_ctx == NULL) {
|
||||
aot_set_last_error_v("invalid func_ctx for intrinsic: %s", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(func = LLVMAddFunction(comp_ctx->module, name, func_type))) {
|
||||
aot_set_last_error("add LLVM function failed.");
|
||||
if (!(func_type = LLVMFunctionType(ret_type, param_types,
|
||||
(uint32)param_count, false))) {
|
||||
aot_set_last_error("create LLVM intrinsic function type failed.");
|
||||
return NULL;
|
||||
}
|
||||
if (!(func_type = LLVMPointerType(func_type, 0))) {
|
||||
aot_set_last_error(
|
||||
"create LLVM intrinsic function pointer type failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(symname = aot_intrinsic_get_symbol(name))) {
|
||||
aot_set_last_error_v("runtime intrinsic not implemented: %s\n",
|
||||
name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
func_idx =
|
||||
aot_get_native_symbol_index((AOTCompContext *)comp_ctx, symname);
|
||||
if (func_idx < 0) {
|
||||
aot_set_last_error_v("get runtime intrinsc index failed: %s\n",
|
||||
name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
|
||||
func_type, func_idx))) {
|
||||
aot_set_last_error_v("get runtime intrinsc failed: %s\n", name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Declare llvm intrinsic function if necessary */
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, name))) {
|
||||
if (!(func_type = LLVMFunctionType(ret_type, param_types,
|
||||
(uint32)param_count, false))) {
|
||||
aot_set_last_error("create LLVM intrinsic function type failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(func = LLVMAddFunction(comp_ctx->module, name, func_type))) {
|
||||
aot_set_last_error("add LLVM intrinsic function failed.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the LLVM intrinsic function */
|
||||
if (!(ret = LLVMBuildCall(comp_ctx->builder, func, param_values,
|
||||
(uint32)param_count, "call"))) {
|
||||
aot_set_last_error("llvm build call failed.");
|
||||
aot_set_last_error("llvm build intrinsic call failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1936,6 +2089,7 @@ __call_llvm_intrinsic(const AOTCompContext *comp_ctx,
|
||||
|
||||
LLVMValueRef
|
||||
aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMTypeRef *param_types,
|
||||
@ -1961,7 +2115,7 @@ aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
|
||||
param_values[i++] = va_arg(argptr, LLVMValueRef);
|
||||
va_end(argptr);
|
||||
|
||||
ret = __call_llvm_intrinsic(comp_ctx, name, ret_type, param_types,
|
||||
ret = __call_llvm_intrinsic(comp_ctx, func_ctx, name, ret_type, param_types,
|
||||
param_count, param_values);
|
||||
|
||||
wasm_runtime_free(param_values);
|
||||
@ -1971,6 +2125,7 @@ aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
|
||||
|
||||
LLVMValueRef
|
||||
aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMTypeRef *param_types,
|
||||
@ -1993,10 +2148,46 @@ aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx,
|
||||
while (i < param_count)
|
||||
param_values[i++] = va_arg(param_value_list, LLVMValueRef);
|
||||
|
||||
ret = __call_llvm_intrinsic(comp_ctx, name, ret_type, param_types,
|
||||
ret = __call_llvm_intrinsic(comp_ctx, func_ctx, name, ret_type, param_types,
|
||||
param_count, param_values);
|
||||
|
||||
wasm_runtime_free(param_values);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LLVMValueRef
|
||||
aot_get_func_from_table(const AOTCompContext *comp_ctx, LLVMValueRef base,
|
||||
LLVMTypeRef func_type, int32 index)
|
||||
{
|
||||
LLVMValueRef func;
|
||||
LLVMValueRef func_addr;
|
||||
|
||||
if (!(func_addr = I32_CONST(index))) {
|
||||
aot_set_last_error("construct function index failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(func_addr = LLVMBuildInBoundsGEP(comp_ctx->builder, base, &func_addr,
|
||||
1, "func_addr"))) {
|
||||
aot_set_last_error("get function addr by index failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
func = LLVMBuildLoad(comp_ctx->builder, func_addr, "func_tmp");
|
||||
|
||||
if (func == NULL) {
|
||||
aot_set_last_error("get function pointer failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(func = LLVMBuildBitCast(comp_ctx->builder, func, func_type,
|
||||
"func"))) {
|
||||
aot_set_last_error("cast function fialed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return func;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -116,6 +116,7 @@ typedef struct AOTMemInfo {
|
||||
typedef struct AOTFuncContext {
|
||||
AOTFunc *aot_func;
|
||||
LLVMValueRef func;
|
||||
LLVMTypeRef func_type;
|
||||
AOTBlockStack block_stack;
|
||||
|
||||
LLVMValueRef exec_env;
|
||||
@ -124,6 +125,7 @@ typedef struct AOTFuncContext {
|
||||
LLVMValueRef native_stack_bound;
|
||||
LLVMValueRef aux_stack_bound;
|
||||
LLVMValueRef aux_stack_bottom;
|
||||
LLVMValueRef native_symbol;
|
||||
LLVMValueRef last_alloca;
|
||||
LLVMValueRef func_ptrs;
|
||||
|
||||
@ -221,10 +223,17 @@ typedef struct AOTCompContext {
|
||||
char target_arch[16];
|
||||
unsigned pointer_size;
|
||||
|
||||
/* Hardware intrinsic compability flags */
|
||||
uint64 flags[8];
|
||||
|
||||
/* LLVM execution engine required by JIT */
|
||||
LLVMExecutionEngineRef exec_engine;
|
||||
bool is_jit_mode;
|
||||
|
||||
/* AOT indirect mode flag & symbol list */
|
||||
bool is_indirect_mode;
|
||||
bh_list native_symbols;
|
||||
|
||||
/* Bulk memory feature */
|
||||
bool enable_bulk_memory;
|
||||
|
||||
@ -249,6 +258,9 @@ typedef struct AOTCompContext {
|
||||
/* Reference Types */
|
||||
bool enable_ref_types;
|
||||
|
||||
/* Disable LLVM built-in intrinsics */
|
||||
bool disable_llvm_intrinsics;
|
||||
|
||||
/* Whether optimize the JITed code */
|
||||
bool optimize;
|
||||
|
||||
@ -283,10 +295,12 @@ enum {
|
||||
|
||||
typedef struct AOTCompOption{
|
||||
bool is_jit_mode;
|
||||
bool is_indirect_mode;
|
||||
char *target_arch;
|
||||
char *target_abi;
|
||||
char *target_cpu;
|
||||
char *cpu_features;
|
||||
bool is_sgx_platform;
|
||||
bool enable_bulk_memory;
|
||||
bool enable_thread_mgr;
|
||||
bool enable_tail_call;
|
||||
@ -294,7 +308,7 @@ typedef struct AOTCompOption{
|
||||
bool enable_ref_types;
|
||||
bool enable_aux_stack_check;
|
||||
bool enable_aux_stack_frame;
|
||||
bool is_sgx_platform;
|
||||
bool disable_llvm_intrinsics;
|
||||
uint32 opt_level;
|
||||
uint32 size_level;
|
||||
uint32 output_format;
|
||||
@ -308,6 +322,9 @@ aot_create_comp_context(AOTCompData *comp_data,
|
||||
void
|
||||
aot_destroy_comp_context(AOTCompContext *comp_ctx);
|
||||
|
||||
int32
|
||||
aot_get_native_symbol_index(AOTCompContext *comp_ctx, const char *symbol);
|
||||
|
||||
bool
|
||||
aot_compile_wasm(AOTCompContext *comp_ctx);
|
||||
|
||||
@ -361,6 +378,7 @@ aot_build_zero_function_ret(AOTCompContext *comp_ctx,
|
||||
|
||||
LLVMValueRef
|
||||
aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMTypeRef *param_types,
|
||||
@ -369,12 +387,19 @@ aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
|
||||
|
||||
LLVMValueRef
|
||||
aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMTypeRef *param_types,
|
||||
int param_count,
|
||||
va_list param_value_list);
|
||||
|
||||
LLVMValueRef
|
||||
aot_get_func_from_table(const AOTCompContext *comp_ctx,
|
||||
LLVMValueRef base,
|
||||
LLVMTypeRef func_type,
|
||||
int32 index);
|
||||
|
||||
bool
|
||||
aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
|
||||
|
||||
|
||||
@ -138,7 +138,7 @@ aot_compile_simd_swizzle_x86(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
param_types[0] = V128_i8x16_TYPE;
|
||||
param_types[1] = V128_i8x16_TYPE;
|
||||
if (!(result = aot_call_llvm_intrinsic(
|
||||
comp_ctx, "llvm.x86.ssse3.pshuf.b.128", V128_i8x16_TYPE,
|
||||
comp_ctx, func_ctx, "llvm.x86.ssse3.pshuf.b.128", V128_i8x16_TYPE,
|
||||
param_types, 2, vector, mask))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
|
||||
@ -69,7 +69,7 @@ simd_build_bitmask(const AOTCompContext *comp_ctx,
|
||||
}
|
||||
|
||||
param_types[0] = vector_ext_type;
|
||||
if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, I32_TYPE,
|
||||
if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, I32_TYPE,
|
||||
param_types, 1, result))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
|
||||
@ -41,7 +41,7 @@ simd_any_true(AOTCompContext *comp_ctx,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, element_type,
|
||||
if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, element_type,
|
||||
&vector_type, 1, non_zero))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
@ -128,7 +128,7 @@ simd_all_true(AOTCompContext *comp_ctx,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, element_type,
|
||||
if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, element_type,
|
||||
&vector_type, 1, is_zero))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
|
||||
@ -38,7 +38,7 @@ simd_integer_narrow(AOTCompContext *comp_ctx,
|
||||
}
|
||||
|
||||
if (!(result =
|
||||
aot_call_llvm_intrinsic(comp_ctx, instrinsic, out_vector_type,
|
||||
aot_call_llvm_intrinsic(comp_ctx, func_ctx, instrinsic, out_vector_type,
|
||||
param_types, 2, vector1, vector2))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
|
||||
@ -191,7 +191,7 @@ simd_v128_float_intrinsic(AOTCompContext *comp_ctx,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, vector_type,
|
||||
if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, vector_type,
|
||||
param_types, 1, number))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
|
||||
@ -32,7 +32,7 @@ simd_v128_integer_arith(AOTCompContext *comp_ctx,
|
||||
param_types[1] = vector_type;
|
||||
|
||||
if (!(result = aot_call_llvm_intrinsic(
|
||||
comp_ctx, is_signed ? intrinsics_s_u[0] : intrinsics_s_u[1],
|
||||
comp_ctx, func_ctx, is_signed ? intrinsics_s_u[0] : intrinsics_s_u[1],
|
||||
vector_type, param_types, 2, lhs, rhs))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
|
||||
Reference in New Issue
Block a user