Refine code, fix some issues and add codegen framework (#1045)

Add more return value checks and set lass error
Implement exception throw and add operand stack overflow check
Remove lower_fe pass
Use cc->cmp_reg for cmp/branch IRs
Fix jit dump issues
Fix some compile warnings
Add part of codegen framework
Remove some unused JIT IRs
This commit is contained in:
Wenyong Huang 2022-03-14 15:32:32 +08:00 committed by GitHub
parent 24aae4f0d6
commit eb518c0423
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 3801 additions and 322 deletions

View File

@ -94,6 +94,14 @@
#define WASM_ENABLE_LAZY_JIT 0
#endif
#ifndef WASM_ENABLE_FAST_JIT
#define WASM_ENABLE_FAST_JIT 0
#endif
#ifndef WASM_ENABLE_FAST_JIT_DUMP
#define WASM_ENABLE_FAST_JIT_DUMP 0
#endif
#ifndef WASM_ENABLE_WAMR_COMPILER
#define WASM_ENABLE_WAMR_COMPILER 0
#endif

View File

@ -1,120 +0,0 @@
/*
* Copyright (C) 2021 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "jit_codegen.h"
bool
jit_codegen_init()
{
return true;
}
void
jit_codegen_destroy()
{}
/* clang-format off */
static const uint8 hreg_info_I4[3][7] = {
/* ebp, eax, ebx, ecx, edx, edi, esi */
{ 1, 0, 0, 0, 0, 0, 1 }, /* fixed, esi is freely used */
{ 0, 1, 0, 1, 1, 0, 0 }, /* caller_saved_native */
{ 0, 1, 0, 1, 1, 1, 0 } /* caller_saved_jitted */
};
static const uint8 hreg_info_I8[3][16] = {
/* rbp, rax, rbx, rcx, rdx, rdi, rsi, rsp,
r8, r9, r10, r11, r12, r13, r14, r15 */
{ 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 1 }, /* fixed, rsi is freely used */
{ 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0 }, /* caller_saved_native */
{ 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0 }, /* caller_saved_jitted */
};
static uint8 hreg_info_F4[3][16] = {
{ 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1 }, /* fixed, rsi is freely used */
{ 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1 }, /* caller_saved_native */
{ 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1 }, /* caller_saved_jitted */
};
static uint8 hreg_info_F8[3][16] = {
{ 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0 }, /* fixed, rsi is freely used */
{ 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1 }, /* caller_saved_native */
{ 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1 }, /* caller_saved_jitted */
};
static const JitHardRegInfo hreg_info = {
{
{ 0, NULL, NULL, NULL }, /* VOID */
{ sizeof(hreg_info_I4[0]), /* I4 */
hreg_info_I4[0],
hreg_info_I4[1],
hreg_info_I4[2] },
{ sizeof(hreg_info_I8[0]), /* I8 */
hreg_info_I8[0],
hreg_info_I8[1],
hreg_info_I8[2] },
{ sizeof(hreg_info_F4[0]), /* F4 */
hreg_info_F4[0],
hreg_info_F4[1],
hreg_info_F4[2] },
{ sizeof(hreg_info_F8[0]), /* F8 */
hreg_info_F8[0],
hreg_info_F8[1],
hreg_info_F8[2] },
{ 0, NULL, NULL, NULL }, /* V8 */
{ 0, NULL, NULL, NULL }, /* V16 */
{ 0, NULL, NULL, NULL } /* V32 */
},
/* frame pointer hreg index: rbp */
0,
/* exec_env hreg index: r15 */
15,
/* cmp hreg index: esi */
6
};
/* clang-format on */
const JitHardRegInfo *
jit_codegen_get_hreg_info()
{
return &hreg_info;
}
bool
jit_codegen_gen_native(JitCompContext *cc)
{
jit_set_last_error(cc, "jit_codegen_gen_native failed");
return false;
}
bool
jit_codegen_lower(JitCompContext *cc)
{
return true;
}
void
jit_codegen_dump_native(void *begin_addr, void *end_addr)
{}
bool
jit_codegen_call_func_jitted(void *exec_env, void *frame, void *func_inst,
void *target)
{
return false;
}

File diff suppressed because it is too large Load Diff

View File

@ -27,13 +27,14 @@
} \
} while (0)
#define BUILD_COND_BR(value_if, block_then, block_else) \
do { \
if (!GEN_INSN(BNE, value_if, jit_basic_block_label(block_then), \
jit_basic_block_label(block_else))) { \
jit_set_last_error(cc, "generate bne insn failed"); \
goto fail; \
} \
#define BUILD_COND_BR(value_if, block_then, block_else) \
do { \
if (!GEN_INSN(CMP, cc->cmp_reg, value_if, NEW_CONST(cc, 0)) \
|| !GEN_INSN(BNE, cc->cmp_reg, jit_basic_block_label(block_then), \
jit_basic_block_label(block_else))) { \
jit_set_last_error(cc, "generate bne insn failed"); \
goto fail; \
} \
} while (0)
#define SET_BUILDER_POS(basic_block) \
@ -73,7 +74,7 @@ load_block_params(JitCompContext *cc, JitBlock *block)
{
JitFrame *jit_frame = cc->jit_frame;
uint32 offset, i;
JitReg value;
JitReg value = 0;
/* Clear jit frame's locals and stacks */
clear_values(jit_frame);
@ -181,8 +182,9 @@ push_jit_block_to_stack_and_pass_params(JitCompContext *cc, JitBlock *block,
BUILD_BR(basic_block);
}
else { /* IF block with condition br insn */
if (!(insn = GEN_INSN(BNE, cond, jit_basic_block_label(basic_block),
0))) {
if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0))
|| !(insn = GEN_INSN(BNE, cc->cmp_reg,
jit_basic_block_label(basic_block), 0))) {
jit_set_last_error(cc, "generate cond br failed");
goto fail;
}
@ -318,7 +320,7 @@ handle_func_return(JitCompContext *cc, JitBlock *block)
/* fp_reg = prev_frame */
GEN_INSN(MOV, cc->fp_reg, prev_frame);
/* return 0 */
GEN_INSN(RETURN, NEW_CONST(I32, 0));
GEN_INSN(RETURNBC, NEW_CONST(I32, 0));
}
static bool
@ -836,7 +838,9 @@ jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
clear_values(jit_frame);
CREATE_BASIC_BLOCK(if_basic_block);
if (!GEN_INSN(BNE, cond, jit_basic_block_label(if_basic_block), 0)) {
if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0))
|| !GEN_INSN(BNE, cc->cmp_reg, jit_basic_block_label(if_basic_block),
0)) {
jit_set_last_error(cc, "generate bne insn failed");
goto fail;
}

View File

@ -7,8 +7,72 @@
#include "../jit_frontend.h"
bool
jit_emit_exception(JitCompContext *cc, int32 exception_id, bool is_cond_br,
jit_emit_exception(JitCompContext *cc, int32 exception_id, uint8 jit_opcode,
JitReg cond_br_if, JitBasicBlock *cond_br_else_block)
{
return false;
JitInsn *insn = NULL;
JitIncomingInsn *incoming_insn;
JitReg else_label;
bh_assert(exception_id < EXCE_NUM);
if (jit_opcode >= JIT_OP_BNE && jit_opcode <= JIT_OP_BLEU) {
bh_assert(cond_br_if == cc->cmp_reg);
else_label =
cond_br_else_block ? jit_basic_block_label(cond_br_else_block) : 0;
switch (jit_opcode) {
case JIT_OP_BEQ:
insn = GEN_INSN(BEQ, cond_br_if, 0, else_label);
break;
case JIT_OP_BNE:
insn = GEN_INSN(BNE, cond_br_if, 0, else_label);
break;
case JIT_OP_BGTS:
insn = GEN_INSN(BGTS, cond_br_if, 0, else_label);
break;
case JIT_OP_BGES:
insn = GEN_INSN(BGES, cond_br_if, 0, else_label);
break;
case JIT_OP_BLTS:
insn = GEN_INSN(BLTS, cond_br_if, 0, else_label);
break;
case JIT_OP_BLES:
insn = GEN_INSN(BLES, cond_br_if, 0, else_label);
break;
case JIT_OP_BGTU:
insn = GEN_INSN(BGTU, cond_br_if, 0, else_label);
break;
case JIT_OP_BGEU:
insn = GEN_INSN(BGEU, cond_br_if, 0, else_label);
break;
case JIT_OP_BLTU:
insn = GEN_INSN(BLTU, cond_br_if, 0, else_label);
break;
case JIT_OP_BLEU:
insn = GEN_INSN(BLEU, cond_br_if, 0, else_label);
break;
}
if (!insn) {
jit_set_last_error(cc, "generate cond br insn failed");
return false;
}
}
else if (jit_opcode == JIT_OP_JMP) {
insn = GEN_INSN(JMP, 0);
if (!insn) {
jit_set_last_error(cc, "generate jmp insn failed");
return false;
}
}
incoming_insn = jit_calloc(sizeof(JitIncomingInsn));
if (!incoming_insn) {
jit_set_last_error(cc, "allocate memory failed");
return false;
}
incoming_insn->insn = insn;
incoming_insn->next = cc->incoming_insns_for_exec_bbs[exception_id];
cc->incoming_insns_for_exec_bbs[exception_id] = incoming_insn;
return true;
}

View File

@ -13,7 +13,7 @@ extern "C" {
#endif
bool
jit_emit_exception(JitCompContext *cc, int32 exception_id, bool is_cond_br,
jit_emit_exception(JitCompContext *cc, int32 exception_id, uint8 jit_opcode,
JitReg cond_br_if, JitBasicBlock *cond_br_else_block);
#ifdef __cplusplus

View File

@ -31,7 +31,7 @@ jit_compile_op_get_local(JitCompContext *cc, uint32 local_idx)
uint16 *local_offsets = wasm_func->local_offsets;
uint16 local_offset;
uint8 local_type;
JitReg value;
JitReg value = 0;
CHECK_LOCAL(local_idx);
@ -119,7 +119,7 @@ jit_compile_op_tee_local(JitCompContext *cc, uint32 local_idx)
uint16 *local_offsets = wasm_func->local_offsets;
uint16 local_offset;
uint8 local_type;
JitReg value;
JitReg value = 0;
CHECK_LOCAL(local_idx);

View File

@ -3,16 +3,84 @@
set (IWASM_FAST_JIT_DIR ${CMAKE_CURRENT_LIST_DIR})
add_definitions (-DWASM_ENABLE_FAST_JIT=1)
add_definitions(-DWASM_ENABLE_FAST_JIT=1)
if (WAMR_BUILD_FAST_JIT_DUMP EQUAL 1)
add_definitions(-DWASM_ENABLE_FAST_JIT_DUMP=1)
endif ()
include_directories (${IWASM_FAST_JIT_DIR})
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
include(FetchContent)
FetchContent_Declare(
asmjit
GIT_REPOSITORY https://github.com/asmjit/asmjit.git
)
FetchContent_GetProperties(asmjit)
if (NOT asmjit_POPULATED)
message ("-- Fetching asmjit ..")
FetchContent_Populate(asmjit)
add_definitions(-DASMJIT_STATIC)
add_definitions(-DASMJIT_NO_DEPRECATED)
add_definitions(-DASMJIT_NO_BUILDER)
add_definitions(-DASMJIT_NO_COMPILER)
add_definitions(-DASMJIT_NO_JIT)
add_definitions(-DASMJIT_NO_LOGGING)
add_definitions(-DASMJIT_NO_TEXT)
add_definitions(-DASMJIT_NO_VALIDATION)
add_definitions(-DASMJIT_NO_INTROSPECTION)
add_definitions(-DASMJIT_NO_INTRINSICS)
add_definitions(-DASMJIT_NO_AARCH64)
add_definitions(-DASMJIT_NO_AARCH32)
include_directories("${asmjit_SOURCE_DIR}/src")
add_subdirectory(${asmjit_SOURCE_DIR} ${asmjit_BINARY_DIR} EXCLUDE_FROM_ALL)
file (GLOB_RECURSE cpp_source_asmjit
${asmjit_SOURCE_DIR}/src/asmjit/core/*.cpp
${asmjit_SOURCE_DIR}/src/asmjit/x86/*.cpp
)
endif ()
if (WAMR_BUILD_FAST_JIT_DUMP EQUAL 1)
FetchContent_Declare(
zycore
GIT_REPOSITORY https://github.com/zyantific/zycore-c.git
)
FetchContent_GetProperties(zycore)
if (NOT zycore_POPULATED)
message ("-- Fetching zycore ..")
FetchContent_Populate(zycore)
option(ZYDIS_BUILD_TOOLS "" OFF)
option(ZYDIS_BUILD_EXAMPLES "" OFF)
include_directories("${zycore_SOURCE_DIR}/include")
include_directories("${zycore_BINARY_DIR}")
add_subdirectory(${zycore_SOURCE_DIR} ${zycore_BINARY_DIR} EXCLUDE_FROM_ALL)
file (GLOB_RECURSE c_source_zycore ${zycore_SOURCE_DIR}/src/*.c)
endif ()
FetchContent_Declare(
zydis
GIT_REPOSITORY https://github.com/zyantific/zydis.git
)
FetchContent_GetProperties(zydis)
if (NOT zydis_POPULATED)
message ("-- Fetching zydis ..")
FetchContent_Populate(zydis)
option(ZYDIS_BUILD_TOOLS "" OFF)
option(ZYDIS_BUILD_EXAMPLES "" OFF)
include_directories("${zydis_BINARY_DIR}")
include_directories("${zydis_SOURCE_DIR}/include")
include_directories("${zydis_SOURCE_DIR}/src")
add_subdirectory(${zydis_SOURCE_DIR} ${zydis_BINARY_DIR} EXCLUDE_FROM_ALL)
file (GLOB_RECURSE c_source_zydis ${zydis_SOURCE_DIR}/src/*.c)
endif ()
endif ()
endif ()
file (GLOB c_source_jit ${IWASM_FAST_JIT_DIR}/*.c ${IWASM_FAST_JIT_DIR}/fe/*.c)
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
file (GLOB_RECURSE c_source_jit_cg ${IWASM_FAST_JIT_DIR}/cg/x86-64/*.c)
file (GLOB_RECURSE cpp_source_jit_cg ${IWASM_FAST_JIT_DIR}/cg/x86-64/*.cpp)
else ()
message (FATAL_ERROR "Fast JIT codegen for target ${WAMR_BUILD_TARGET} isn't implemented")
endif ()
set (IWASM_FAST_JIT_SOURCE ${c_source_jit} ${c_source_jit_cg})
set (IWASM_FAST_JIT_SOURCE ${c_source_jit} ${cpp_source_jit_cg}
${cpp_source_asmjit} ${c_source_zycore} ${c_source_zydis})

View File

@ -41,7 +41,7 @@ jit_code_cache_destroy()
}
void *
jit_code_cache_malloc(uint32 size)
jit_code_cache_alloc(uint32 size)
{
return mem_allocator_malloc(code_cache_pool_allocator, size);
}

View File

@ -7,7 +7,7 @@
#define _JIT_CODEGEN_H_
#include "bh_platform.h"
#include "jit_ir.h"
#include "jit_compiler.h"
#ifdef __cplusplus
extern "C" {
@ -64,14 +64,8 @@ jit_codegen_lower(JitCompContext *cc);
void
jit_codegen_dump_native(void *begin_addr, void *end_addr);
/**
* Call jitted code
*
* @param exec_env the current exec_env
*/
bool
jit_codegen_call_func_jitted(void *exec_env, void *frame, void *func_inst,
void *target);
int
jit_codegen_interp_jitted_glue(void *self, JitInterpSwitchInfo *info, void *pc);
#ifdef __cplusplus
}

View File

@ -9,13 +9,6 @@
#include "jit_codecache.h"
#include "../interpreter/wasm.h"
typedef struct JitGlobals {
/* Compiler pass sequence. The last element must be 0. */
const uint8 *passes;
/* Code cache size. */
uint32 code_cache_size;
} JitGlobals;
typedef struct JitCompilerPass {
/* Name of the pass. */
const char *name;
@ -30,7 +23,6 @@ static JitCompilerPass compiler_passes[] = {
REG_PASS(dump),
REG_PASS(update_cfg),
REG_PASS(frontend),
REG_PASS(lower_fe),
REG_PASS(lower_cg),
REG_PASS(regalloc),
REG_PASS(codegen),
@ -41,20 +33,18 @@ static JitCompilerPass compiler_passes[] = {
/* Number of compiler passes. */
#define COMPILER_PASS_NUM (sizeof(compiler_passes) / sizeof(compiler_passes[0]))
#define WASM_ENABLE_FAST_JIT_DUMP 1
#if WASM_ENABLE_FAST_JIT_DUMP == 0
static const uint8 compiler_passes_without_dump[] = {
3, 4, 5, 6, 7, 8, 0
3, 4, 5, 6, 7, 0
};
#else
static const uint8 compiler_passes_with_dump[] = {
3, 2, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 0
3, 2, 1, 4, 1, 5, 1, 6, 1, 7, 0
};
#endif
/* The exported global data of JIT compiler. */
JitGlobals jit_globals = {
static JitGlobals jit_globals = {
#if WASM_ENABLE_FAST_JIT_DUMP == 0
.passes = compiler_passes_without_dump,
#else
@ -109,6 +99,12 @@ jit_compiler_destroy()
jit_code_cache_destroy();
}
const JitGlobals *
jit_compiler_get_jit_globals()
{
return &jit_globals;
}
const char *
jit_compiler_get_pass_name(unsigned i)
{
@ -119,6 +115,7 @@ bool
jit_compiler_compile(WASMModule *module, uint32 func_idx)
{
JitCompContext *cc;
char *last_error;
bool ret = true;
/* Initialize compilation context. */
@ -138,8 +135,10 @@ jit_compiler_compile(WASMModule *module, uint32 func_idx)
|| (!module->possible_memory_grow);
/* Apply compiler passes. */
if (!apply_compiler_passes(cc)) {
os_printf("fast jit compilation failed: %s\n", jit_get_last_error(cc));
if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) {
last_error = jit_get_last_error(cc);
os_printf("fast jit compilation failed: %s\n",
last_error ? last_error : "unknown error");
ret = false;
}
@ -153,6 +152,7 @@ bool
jit_compiler_compile_all(WASMModule *module)
{
JitCompContext *cc;
char *last_error;
bool ret = false;
uint32 i;
@ -174,9 +174,10 @@ jit_compiler_compile_all(WASMModule *module)
|| (!module->possible_memory_grow);
/* Apply compiler passes. */
if (!apply_compiler_passes(cc)) {
if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) {
last_error = jit_get_last_error(cc);
os_printf("fast jit compilation failed: %s\n",
jit_get_last_error(cc));
last_error ? last_error : "unknown error");
ret = false;
break;
}
@ -188,9 +189,8 @@ jit_compiler_compile_all(WASMModule *module)
return ret;
}
bool
jit_interp_switch_to_jitted(void *exec_env, void *frame,
WASMFunctionInstance *func_inst, void *target)
int
jit_interp_switch_to_jitted(void *exec_env, JitInterpSwitchInfo *info, void *pc)
{
return jit_codegen_call_func_jitted(exec_env, func_inst, frame, target);
return jit_codegen_interp_jitted_glue(exec_env, info, pc);
}

View File

@ -14,12 +14,31 @@
extern "C" {
#endif
typedef struct JitGlobals {
/* Compiler pass sequence, the last element must be 0 */
const uint8 *passes;
/* Code cache size. */
uint32 code_cache_size;
} JitGlobals;
/**
* Information exchanged between JITed code and interpreter.
*/
typedef struct JitInterpSwitchInfo {
/* Points to the frame that is passed to JITed code and the frame
that is returned from JITed code. */
void *frame;
} JitInterpSwitchInfo;
bool
jit_compiler_init();
void
jit_compiler_destroy();
const JitGlobals *
jit_compiler_get_jit_globals();
const char *
jit_compiler_get_pass_name(unsigned i);
@ -29,9 +48,8 @@ jit_compiler_compile(WASMModule *module, uint32 func_idx);
bool
jit_compiler_compile_all(WASMModule *module);
bool
jit_interp_switch_to_jitted(void *exec_env, void *frame,
WASMFunctionInstance *func_inst, void *target);
int
jit_interp_switch_to_jitted(void *self, JitInterpSwitchInfo *info, void *pc);
/*
* Pass declarations:
@ -55,11 +73,13 @@ jit_pass_update_cfg(JitCompContext *cc);
bool
jit_pass_frontend(JitCompContext *cc);
#if 0
/**
* Convert MIR to LIR.
*/
bool
jit_pass_lower_fe(JitCompContext *cc);
#endif
/**
* Lower unsupported operations into supported ones.

View File

@ -89,6 +89,7 @@ jit_dump_insn_VReg(JitCompContext *cc, JitInsn *insn, unsigned opnd_num)
os_printf("\n");
}
#if 0
static void
jit_dump_insn_TableSwitch(JitCompContext *cc, JitInsn *insn, unsigned opnd_num)
{
@ -107,6 +108,7 @@ jit_dump_insn_TableSwitch(JitCompContext *cc, JitInsn *insn, unsigned opnd_num)
os_printf("\n");
}
}
#endif
static void
jit_dump_insn_LookupSwitch(JitCompContext *cc, JitInsn *insn, unsigned opnd_num)
@ -307,9 +309,14 @@ jit_dump_cc(JitCompContext *cc)
bool
jit_pass_dump(JitCompContext *cc)
{
os_printf("JIT.COMPILER.DUMP: PASS_NO=%d PREV_PASS=%s\n\n", cc->cur_pass_no,
(cc->cur_pass_no > 0 ? jit_compiler_get_pass_name(cc->cur_pass_no)
: "NULL"));
const JitGlobals *jit_globals = jit_compiler_get_jit_globals();
const uint8 *passes = jit_globals->passes;
uint8 pass_no = cc->cur_pass_no;
const char *pass_name =
pass_no > 0 ? jit_compiler_get_pass_name(passes[pass_no - 1]) : "NULL";
os_printf("JIT.COMPILER.DUMP: PASS_NO=%d PREV_PASS=%s\n\n", pass_no,
pass_name);
jit_dump_cc(cc);
os_printf("\n");
return true;

View File

@ -20,6 +20,28 @@
#include "../interpreter/wasm_opcode.h"
#include "../common/wasm_exec_env.h"
/* clang-format off */
static const char *jit_exception_msgs[] = {
"unreachable", /* EXCE_UNREACHABLE */
"allocate memory failed", /* EXCE_OUT_OF_MEMORY */
"out of bounds memory access", /* EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS */
"integer overflow", /* EXCE_INTEGER_OVERFLOW */
"integer divide by zero", /* EXCE_INTEGER_DIVIDE_BY_ZERO */
"invalid conversion to integer", /* EXCE_INVALID_CONVERSION_TO_INTEGER */
"indirect call type mismatch", /* EXCE_INVALID_FUNCTION_TYPE_INDEX */
"invalid function index", /* EXCE_INVALID_FUNCTION_INDEX */
"undefined element", /* EXCE_UNDEFINED_ELEMENT */
"uninitialized element", /* EXCE_UNINITIALIZED_ELEMENT */
"failed to call unlinked import function", /* EXCE_CALL_UNLINKED_IMPORT_FUNC */
"native stack overflow", /* EXCE_NATIVE_STACK_OVERFLOW */
"unaligned atomic", /* EXCE_UNALIGNED_ATOMIC */
"wasm auxiliary stack overflow", /* EXCE_AUX_STACK_OVERFLOW */
"wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */
"out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
"wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */
};
/* clang-format on */
JitReg
gen_load_i32(JitFrame *frame, unsigned n)
{
@ -124,29 +146,41 @@ gen_commit_sp_ip(JitFrame *frame)
JitReg sp;
if (frame->sp != frame->committed_sp) {
#if UINTPTR_MAX == UINT32_MAX
GEN_INSN_NORM(I32, sp, ADD, 0, cc->fp_reg,
NEW_CONST(I32, offset_of_local(frame->sp - frame->lp)));
GEN_INSN(STI32, sp, cc->fp_reg,
#if UINTPTR_MAX == UINT64_MAX
sp = jit_cc_new_reg_I64(cc);
GEN_INSN(ADD, sp, cc->fp_reg,
NEW_CONST(I32, offset_of_local(frame->sp - frame->lp)));
GEN_INSN(STI64, sp, cc->fp_reg,
NEW_CONST(I32, offsetof(WASMInterpFrame, sp)));
#else
GEN_INSN_NORM(I64, sp, ADD, 0, cc->fp_reg,
NEW_CONST(I32, offset_of_local(frame->sp - frame->lp)));
GEN_INSN(STI64, sp, cc->fp_reg,
sp = jit_cc_new_reg_I32(cc);
GEN_INSN(ADD, sp, cc->fp_reg,
NEW_CONST(I32, offset_of_local(frame->sp - frame->lp)));
GEN_INSN(STI32, sp, cc->fp_reg,
NEW_CONST(I32, offsetof(WASMInterpFrame, sp)));
#endif
frame->committed_sp = frame->sp;
}
#if 0
if (frame->ip != frame->committed_ip) {
GEN_INSN (STI32,
NEW_REL (BCIP, NONE, offset_of_addr (frame, frame->ip), frame->ip),
cc->fp_reg,
NEW_CONST (I32, offsetof (WASMInterpFrame, ip)));
frame->committed_ip = frame->ip;
}
if (frame->ip != frame->committed_ip) {
#if UINTPTR_MAX == UINT64_MAX
GEN_INSN(STI64, NEW_CONST(I64, (uint64)(uintptr_t)frame->ip),
cc->fp_reg, NEW_CONST(I32, offsetof(WASMInterpFrame, ip)));
#else
GEN_INSN(STI32, NEW_CONST(I32, (uint32)(uintptr_t)frame->ip),
cc->fp_reg, NEW_CONST(I32, offsetof(WASMInterpFrame, ip)));
#endif
frame->committed_ip = frame->ip;
}
}
static void
jit_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id)
{
if (id < EXCE_NUM)
wasm_set_exception(module_inst, jit_exception_msgs[id]);
else
wasm_set_exception(module_inst, "unknown exception");
}
static bool
@ -154,7 +188,9 @@ form_and_translate_func(JitCompContext *cc)
{
JitBasicBlock *func_entry_basic_block;
JitReg func_entry_label;
JitInsn *jmp_insn;
JitInsn *insn;
JitIncomingInsn *incoming_insn, *incoming_insn_next;
uint32 i;
if (!(func_entry_basic_block = jit_frontend_translate_func(cc)))
return false;
@ -165,11 +201,58 @@ form_and_translate_func(JitCompContext *cc)
func_entry_label = jit_basic_block_label(func_entry_basic_block);
/* Create a JMP instruction jumping to the func entry. */
if (!(jmp_insn = jit_cc_new_insn(cc, JMP, func_entry_label)))
if (!(insn = jit_cc_new_insn(cc, JMP, func_entry_label)))
return false;
/* Insert the instruction into the cc entry block. */
jit_basic_block_append_insn(jit_cc_entry_basic_block(cc), jmp_insn);
jit_basic_block_append_insn(jit_cc_entry_basic_block(cc), insn);
/* Patch INSNs jumping to exception basic blocks. */
for (i = 0; i < EXCE_NUM; i++) {
incoming_insn = cc->incoming_insns_for_exec_bbs[i];
if (incoming_insn) {
if (!(cc->exce_basic_blocks[i] = jit_cc_new_basic_block(cc, 0))) {
jit_set_last_error(cc, "create basic block failed");
return false;
}
while (incoming_insn) {
incoming_insn_next = incoming_insn->next;
insn = incoming_insn->insn;
if (insn->opcode == JIT_OP_JMP) {
*(jit_insn_opnd(insn, 0)) =
jit_basic_block_label(cc->exce_basic_blocks[i]);
}
else if (insn->opcode >= JIT_OP_BNE
&& insn->opcode <= JIT_OP_BLEU) {
*(jit_insn_opnd(insn, 1)) =
jit_basic_block_label(cc->exce_basic_blocks[i]);
}
incoming_insn = incoming_insn_next;
}
cc->cur_basic_block = cc->exce_basic_blocks[i];
#if UINTPTR_MAX == UINT64_MAX
insn = GEN_INSN(
CALLNATIVE, 0,
NEW_CONST(I64, (uint64)(uintptr_t)jit_set_exception_with_id),
1);
#else
insn = GEN_INSN(
CALLNATIVE, 0,
NEW_CONST(I32, (uint32)(uintptr_t)jit_set_exception_with_id),
1);
#endif
if (insn) {
*(jit_insn_opndv(insn, 2)) = NEW_CONST(I32, i);
}
GEN_INSN(RETURNBC, NEW_CONST(I32, i));
*(jit_annl_begin_bcip(cc,
jit_basic_block_label(cc->cur_basic_block))) =
*(jit_annl_end_bcip(
cc, jit_basic_block_label(cc->cur_basic_block))) =
cc->cur_wasm_module->load_addr;
}
}
*(jit_annl_begin_bcip(cc, cc->entry_label)) =
*(jit_annl_end_bcip(cc, cc->entry_label)) =
@ -199,11 +282,13 @@ jit_pass_frontend(JitCompContext *cc)
return true;
}
#if 0
bool
jit_pass_lower_fe(JitCompContext *cc)
{
return true;
}
#endif
static JitFrame *
init_func_translation(JitCompContext *cc)
@ -239,6 +324,7 @@ init_func_translation(JitCompContext *cc)
jit_frame->max_locals = max_locals;
jit_frame->max_stacks = max_stacks;
jit_frame->sp = jit_frame->lp + max_locals;
jit_frame->ip = cur_wasm_func->code;
cc->jit_frame = jit_frame;
cc->cur_basic_block = jit_cc_entry_basic_block(cc);
@ -266,9 +352,14 @@ init_func_translation(JitCompContext *cc)
NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.s.top_boundary)));
/* frame_boundary = top + frame_size + outs_size */
GEN_INSN(ADD, frame_boundary, top, NEW_CONST(I32, frame_size + outs_size));
GEN_INSN(CHECK_SOE, NEW_CONST(I32, 0), frame_boundary, top_boundary);
/* if frame_boundary > top_boundary, throw stack overflow exception */
GEN_INSN(CMP, cc->cmp_reg, frame_boundary, top_boundary);
if (!jit_emit_exception(cc, EXCE_OPERAND_STACK_OVERFLOW, JIT_OP_BGTU,
cc->cmp_reg, 0)) {
return NULL;
}
/* Add first and then sub to reduce one used register. */
/* Add first and then sub to reduce one used register */
/* new_top = frame_boundary - outs_size = top + frame_size */
GEN_INSN(SUB, new_top, frame_boundary, NEW_CONST(I32, outs_size));
/* exec_env->wasm_stack.s.top = new_top */
@ -283,6 +374,7 @@ init_func_translation(JitCompContext *cc)
/* frame->prev_frame = fp_reg */
GEN_INSN(STI64, cc->fp_reg, top,
NEW_CONST(I32, offsetof(WASMInterpFrame, prev_frame)));
/* TODO: do we need to set frame->function? */
/*
GEN_INSN(STI64, func_inst, top,
NEW_CONST(I32, offsetof(WASMInterpFrame, function)));
@ -293,6 +385,52 @@ init_func_translation(JitCompContext *cc)
/* fp_reg = top */
GEN_INSN(MOV, cc->fp_reg, top);
#else
top = jit_cc_new_reg_I32(cc);
top_boundary = jit_cc_new_reg_I32(cc);
new_top = jit_cc_new_reg_I32(cc);
frame_boundary = jit_cc_new_reg_I32(cc);
frame_sp = jit_cc_new_reg_I32(cc);
/* top = exec_env->wasm_stack.s.top */
GEN_INSN(LDI32, top, cc->exec_env_reg,
NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.s.top)));
/* top_boundary = exec_env->wasm_stack.s.top_boundary */
GEN_INSN(LDI32, top_boundary, cc->exec_env_reg,
NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.s.top_boundary)));
/* frame_boundary = top + frame_size + outs_size */
GEN_INSN(ADD, frame_boundary, top, NEW_CONST(I32, frame_size + outs_size));
/* if frame_boundary > top_boundary, throw stack overflow exception */
GEN_INSN(CMP, cc->cmp_reg, frame_boundary, top_boundary);
if (!jit_emit_exception(cc, EXCE_OPERAND_STACK_OVERFLOW, JIT_OP_BGTU,
cc->cmp_reg, 0)) {
return NULL;
}
/* Add first and then sub to reduce one used register */
/* new_top = frame_boundary - outs_size = top + frame_size */
GEN_INSN(SUB, new_top, frame_boundary, NEW_CONST(I32, outs_size));
/* exec_env->wasm_stack.s.top = new_top */
GEN_INSN(STI32, new_top, cc->exec_env_reg,
NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.s.top)));
/* frame_sp = frame->lp + local_size */
GEN_INSN(ADD, frame_sp, top,
NEW_CONST(I32, offsetof(WASMInterpFrame, lp) + local_size));
/* frame->sp = frame_sp */
GEN_INSN(STI32, frame_sp, top,
NEW_CONST(I32, offsetof(WASMInterpFrame, sp)));
/* frame->prev_frame = fp_reg */
GEN_INSN(STI32, cc->fp_reg, top,
NEW_CONST(I32, offsetof(WASMInterpFrame, prev_frame)));
/* TODO: do we need to set frame->function? */
/*
GEN_INSN(STI32, func_inst, top,
NEW_CONST(I32, offsetof(WASMInterpFrame, function)));
*/
/* exec_env->cur_frame = top */
GEN_INSN(STI32, top, cc->exec_env_reg,
NEW_CONST(I32, offsetof(WASMExecEnv, cur_frame)));
/* fp_reg = top */
GEN_INSN(MOV, cc->fp_reg, top);
#endif
return jit_frame;
@ -1535,6 +1673,12 @@ jit_compile_func(JitCompContext *cc)
jit_set_last_error(cc, "unsupported opcode");
return false;
}
/* Error may occur when creating registers, basic blocks, insns,
consts and labels, in which the return value may be unchecked,
here we check again */
if (jit_get_last_error(cc)) {
return false;
}
}
(void)func_idx;

View File

@ -308,6 +308,7 @@ static inline void
gen_commit_for_exception(JitFrame *frame)
{
gen_commit_values(frame, frame->lp, frame->lp + frame->max_locals);
gen_commit_sp_ip(frame);
}
/**

View File

@ -315,6 +315,9 @@ JitBasicBlock *
jit_basic_block_new(JitReg label, int n)
{
JitBasicBlock *block = jit_insn_new_PHI(label, n);
if (!block)
return NULL;
block->prev = block->next = block;
return block;
}
@ -380,7 +383,7 @@ jit_basic_block_succs(JitBasicBlock *block)
vec._base = jit_insn_opnd(last_insn, 1);
break;
case JIT_OP_LOOKUP_SWITCH:
case JIT_OP_LOOKUPSWITCH:
{
JitOpndLookupSwitch *opnd = jit_insn_opndls(last_insn);
vec.num = opnd->match_pairs_num + 1;
@ -412,10 +415,14 @@ jit_cc_init(JitCompContext *cc, unsigned htab_size)
|| !(exit_block = jit_cc_new_basic_block(cc, 0)))
goto fail;
if (!(cc->exception_basic_blocks =
if (!(cc->exce_basic_blocks =
jit_calloc(sizeof(JitBasicBlock *) * EXCE_NUM)))
goto fail;
if (!(cc->incoming_insns_for_exec_bbs =
jit_calloc(sizeof(JitIncomingInsnList) * EXCE_NUM)))
goto fail;
/* Record the entry and exit labels, whose indexes must be 0 and 1
respectively. */
cc->entry_label = jit_basic_block_label(entry_block);
@ -437,14 +444,14 @@ jit_cc_init(JitCompContext *cc, unsigned htab_size)
}
/* Create registers for frame pointer, exec_env and cmp. */
#if UINTPTR_MAX == UINT32_MAX
cc->fp_reg = jit_reg_new(JIT_REG_KIND_I32, cc->hreg_info->fp_hreg_index);
cc->exec_env_reg =
jit_reg_new(JIT_REG_KIND_I32, cc->hreg_info->exec_env_hreg_index);
#else
#if UINTPTR_MAX == UINT64_MAX
cc->fp_reg = jit_reg_new(JIT_REG_KIND_I64, cc->hreg_info->fp_hreg_index);
cc->exec_env_reg =
jit_reg_new(JIT_REG_KIND_I64, cc->hreg_info->exec_env_hreg_index);
#else
cc->fp_reg = jit_reg_new(JIT_REG_KIND_I32, cc->hreg_info->fp_hreg_index);
cc->exec_env_reg =
jit_reg_new(JIT_REG_KIND_I32, cc->hreg_info->exec_env_hreg_index);
#endif
cc->cmp_reg = jit_reg_new(JIT_REG_KIND_I32, cc->hreg_info->cmp_hreg_index);
@ -466,6 +473,7 @@ jit_cc_destroy(JitCompContext *cc)
{
unsigned i, end;
JitBasicBlock *block;
JitIncomingInsn *incoming_insn, *incoming_insn_next;
jit_block_stack_destroy(&cc->block_stack);
@ -476,7 +484,19 @@ jit_cc_destroy(JitCompContext *cc)
/* Release the instruction hash table. */
jit_cc_disable_insn_hash(cc);
jit_free(cc->exception_basic_blocks);
jit_free(cc->exce_basic_blocks);
if (cc->incoming_insns_for_exec_bbs) {
for (i = 0; i < EXCE_NUM; i++) {
incoming_insn = cc->incoming_insns_for_exec_bbs[i];
while (incoming_insn) {
incoming_insn_next = incoming_insn->next;
jit_free(incoming_insn);
incoming_insn = incoming_insn_next;
}
}
jit_free(cc->incoming_insns_for_exec_bbs);
}
/* Release entry and exit blocks. */
jit_basic_block_delete(jit_cc_entry_basic_block(cc));
@ -619,6 +639,7 @@ _jit_cc_new_const(JitCompContext *cc, int kind, unsigned size, void *val)
cc->_const_val._next[kind] = new_next;
}
else {
jit_set_last_error(cc, "create const register failed");
jit_free(new_value);
jit_free(new_next);
return 0;
@ -770,8 +791,10 @@ jit_cc_new_label(JitCompContext *cc)
#undef ANN_LABEL
#undef EMPTY_POSTFIX
if (!successful)
if (!successful) {
jit_set_last_error(cc, "create label register failed");
return 0;
}
cc->_ann._label_capacity = capacity;
}
@ -790,6 +813,8 @@ jit_cc_new_basic_block(JitCompContext *cc, int n)
if (label && (block = jit_basic_block_new(label, n)))
/* Void 0 register indicates error in creation. */
*(jit_annl_basic_block(cc, label)) = block;
else
jit_set_last_error(cc, "create basic block failed");
return block;
}
@ -801,8 +826,10 @@ jit_cc_resize_basic_block(JitCompContext *cc, JitBasicBlock *block, int n)
JitInsn *insn = jit_basic_block_first_insn(block);
JitBasicBlock *new_block = jit_basic_block_new(label, n);
if (!new_block)
if (!new_block) {
jit_set_last_error(cc, "resize basic block failed");
return NULL;
}
jit_insn_unlink(block);
@ -877,8 +904,10 @@ jit_cc_set_insn_uid(JitCompContext *cc, JitInsn *insn)
#undef ANN_INSN
#undef EMPTY_POSTFIX
if (!successful)
if (!successful) {
jit_set_last_error(cc, "set insn uid failed");
return NULL;
}
cc->_ann._insn_capacity = capacity;
}
@ -900,6 +929,7 @@ _jit_cc_set_insn_uid_for_new_insn(JitCompContext *cc, JitInsn *insn)
return NULL;
}
#if 0
static JitReg
normalize_insn(JitCompContext *cc, JitInsn **pinsn)
{
@ -1059,6 +1089,7 @@ _gen_insn_norm_1(JitCompContext *cc, JitBasicBlock *block, unsigned kind,
return NULL;
}
#endif
JitReg
jit_cc_new_reg(JitCompContext *cc, unsigned kind)
@ -1080,8 +1111,10 @@ jit_cc_new_reg(JitCompContext *cc, unsigned kind)
#include "jit_ir.def"
#undef ANN_REG
if (!successful)
if (!successful) {
jit_set_last_error(cc, "create register failed");
return 0;
}
cc->_ann._reg_capacity[kind] = capacity;
}
@ -1093,33 +1126,37 @@ jit_cc_new_reg(JitCompContext *cc, unsigned kind)
#undef _JIT_REALLOC_ANN
#define ANN_LABEL(TYPE, NAME) \
bool jit_annl_enable_##NAME(JitCompContext *cc) \
{ \
if (cc->_ann._label_##NAME##_enabled) \
return true; \
\
if (cc->_ann._label_capacity > 0 \
&& !(cc->_ann._label_##NAME = \
jit_calloc(cc->_ann._label_capacity * sizeof(TYPE)))) \
return false; \
\
cc->_ann._label_##NAME##_enabled = 1; \
return true; \
#define ANN_LABEL(TYPE, NAME) \
bool jit_annl_enable_##NAME(JitCompContext *cc) \
{ \
if (cc->_ann._label_##NAME##_enabled) \
return true; \
\
if (cc->_ann._label_capacity > 0 \
&& !(cc->_ann._label_##NAME = \
jit_calloc(cc->_ann._label_capacity * sizeof(TYPE)))) { \
jit_set_last_error(cc, "annl enable " #NAME "failed"); \
return false; \
} \
\
cc->_ann._label_##NAME##_enabled = 1; \
return true; \
}
#define ANN_INSN(TYPE, NAME) \
bool jit_anni_enable_##NAME(JitCompContext *cc) \
{ \
if (cc->_ann._insn_##NAME##_enabled) \
return true; \
\
if (cc->_ann._insn_capacity > 0 \
&& !(cc->_ann._insn_##NAME = \
jit_calloc(cc->_ann._insn_capacity * sizeof(TYPE)))) \
return false; \
\
cc->_ann._insn_##NAME##_enabled = 1; \
return true; \
#define ANN_INSN(TYPE, NAME) \
bool jit_anni_enable_##NAME(JitCompContext *cc) \
{ \
if (cc->_ann._insn_##NAME##_enabled) \
return true; \
\
if (cc->_ann._insn_capacity > 0 \
&& !(cc->_ann._insn_##NAME = \
jit_calloc(cc->_ann._insn_capacity * sizeof(TYPE)))) { \
jit_set_last_error(cc, "anni enable " #NAME "failed"); \
return false; \
} \
\
cc->_ann._insn_##NAME##_enabled = 1; \
return true; \
}
#define ANN_REG(TYPE, NAME) \
bool jit_annr_enable_##NAME(JitCompContext *cc) \
@ -1133,6 +1170,7 @@ jit_cc_new_reg(JitCompContext *cc, unsigned kind)
if (cc->_ann._reg_capacity[k] > 0 \
&& !(cc->_ann._reg_##NAME[k] = jit_calloc( \
cc->_ann._reg_capacity[k] * sizeof(TYPE)))) { \
jit_set_last_error(cc, "annr enable " #NAME "failed"); \
jit_annr_disable_##NAME(cc); \
return false; \
} \
@ -1179,7 +1217,7 @@ jit_cc_new_reg(JitCompContext *cc, unsigned kind)
char *
jit_get_last_error(JitCompContext *cc)
{
return cc->last_error[0] == '\0' ? "" : cc->last_error;
return cc->last_error[0] == '\0' ? NULL : cc->last_error;
}
void
@ -1385,8 +1423,8 @@ to_stack_value_type(uint8 type)
bool
jit_cc_pop_value(JitCompContext *cc, uint8 type, JitReg *p_value)
{
JitValue *jit_value;
JitReg value;
JitValue *jit_value = NULL;
JitReg value = 0;
if (!cc->block_stack.block_list_end) {
jit_set_last_error(cc, "WASM block stack underflow");

View File

@ -72,78 +72,10 @@
#define INSN(NAME, OPND_KIND, OPND_NUM, FIRST_USE)
#endif
/* Comparison instructions */
INSN(I32_EQZ, Reg, 3, 1)
INSN(I32_EQ, Reg, 3, 1)
INSN(I32_NE, Reg, 3, 1)
INSN(I32_LT_S, Reg, 3, 1)
INSN(I32_LT_U, Reg, 3, 1)
INSN(I32_GT_S, Reg, 3, 1)
INSN(I32_GT_U, Reg, 3, 1)
INSN(I32_LE_S, Reg, 3, 1)
INSN(I32_LE_U, Reg, 3, 1)
INSN(I32_GE_S, Reg, 3, 1)
INSN(I32_GE_U, Reg, 3, 1)
INSN(I64_EQZ, Reg, 3, 1)
INSN(I64_EQ, Reg, 3, 1)
INSN(I64_NE, Reg, 3, 1)
INSN(I64_LT_S, Reg, 3, 1)
INSN(I64_LT_U, Reg, 3, 1)
INSN(I64_GT_S, Reg, 3, 1)
INSN(I64_GT_U, Reg, 3, 1)
INSN(I64_LE_S, Reg, 3, 1)
INSN(I64_LE_U, Reg, 3, 1)
INSN(I64_GE_S, Reg, 3, 1)
INSN(I64_GE_U, Reg, 3, 1)
INSN(F32_EQ, Reg, 3, 1)
INSN(F32_NE, Reg, 3, 1)
INSN(F32_LT, Reg, 3, 1)
INSN(F32_GT, Reg, 3, 1)
INSN(F32_LE, Reg, 3, 1)
INSN(F32_GE, Reg, 3, 1)
INSN(F64_EQ, Reg, 3, 1)
INSN(F64_NE, Reg, 3, 1)
INSN(F64_LT, Reg, 3, 1)
INSN(F64_GT, Reg, 3, 1)
INSN(F64_LE, Reg, 3, 1)
INSN(F64_GE, Reg, 3, 1)
/* Select instruction */
INSN(SELECT, Reg, 4, 1)
/* Control instructions */
INSN(JMP, Reg, 1, 0)
INSN(BEQ, Reg, 3, 0)
INSN(BNE, Reg, 3, 0)
INSN(BGTS, Reg, 3, 0)
INSN(BGES, Reg, 3, 0)
INSN(BLTS, Reg, 3, 0)
INSN(BLES, Reg, 3, 0)
INSN(BGTU, Reg, 3, 0)
INSN(BGEU, Reg, 3, 0)
INSN(BLTU, Reg, 3, 0)
INSN(BLEU, Reg, 3, 0)
INSN(TABLE_SWITCH, TableSwitch, 1, 0)
INSN(LOOKUP_SWITCH, LookupSwitch, 1, 0)
/* check zero divisor */
INSN(CHECK_DIV_ZERO, Reg, 3, 0)
/* check stack overflow */
INSN(CHECK_SOE, Reg, 3, 0)
/* Call and return instructions */
INSN(CALLNATIVE, VReg, 2, 1)
INSN(CALLBC, Reg, 3, 0)
INSN(RETURN, Reg, 1, 0)
/* Move and conversion instructions that transfer values among
registers of the same kind (move) or different kinds (convert) */
INSN(MOV, Reg, 2, 1)
INSN(PHI, VReg, 1, 1)
INSN(I32TOI8, Reg, 2, 1)
INSN(I32TOU8, Reg, 2, 1)
INSN(I32TOI16, Reg, 2, 1)
@ -193,7 +125,7 @@ INSN(SELECTLTU, Reg, 4, 1)
INSN(SELECTLEU, Reg, 4, 1)
/* Memory access instructions: */
INSN(LDSELF, Reg, 1, 1)
INSN(LDEXECENV, Reg, 1, 1)
INSN(LDJITINFO, Reg, 1, 1)
INSN(LDI8, Reg, 3, 1)
INSN(LDU8, Reg, 3, 1)
@ -218,7 +150,69 @@ INSN(STV64, Reg, 3, 1)
INSN(STV128, Reg, 3, 1)
INSN(STV256, Reg, 3, 1)
/* Control instructions */
INSN(JMP, Reg, 1, 0)
INSN(BEQ, Reg, 3, 0)
INSN(BNE, Reg, 3, 0)
INSN(BGTS, Reg, 3, 0)
INSN(BGES, Reg, 3, 0)
INSN(BLTS, Reg, 3, 0)
INSN(BLES, Reg, 3, 0)
INSN(BGTU, Reg, 3, 0)
INSN(BGEU, Reg, 3, 0)
INSN(BLTU, Reg, 3, 0)
INSN(BLEU, Reg, 3, 0)
INSN(LOOKUPSWITCH, LookupSwitch, 1, 0)
/* INSN(TABLESWITCH, TableSwitch, 1, 0) */
/* Call and return instructions */
INSN(CALLNATIVE, VReg, 2, 1)
INSN(CALLBC, Reg, 3, 0)
INSN(RETURNBC, Reg, 1, 0)
#if 0
/* Comparison instructions, can be translate to SELECTXXX */
INSN(I32_EQZ, Reg, 3, 1)
INSN(I32_EQ, Reg, 3, 1)
INSN(I32_NE, Reg, 3, 1)
INSN(I32_LT_S, Reg, 3, 1)
INSN(I32_LT_U, Reg, 3, 1)
INSN(I32_GT_S, Reg, 3, 1)
INSN(I32_GT_U, Reg, 3, 1)
INSN(I32_LE_S, Reg, 3, 1)
INSN(I32_LE_U, Reg, 3, 1)
INSN(I32_GE_S, Reg, 3, 1)
INSN(I32_GE_U, Reg, 3, 1)
INSN(I64_EQZ, Reg, 3, 1)
INSN(I64_EQ, Reg, 3, 1)
INSN(I64_NE, Reg, 3, 1)
INSN(I64_LT_S, Reg, 3, 1)
INSN(I64_LT_U, Reg, 3, 1)
INSN(I64_GT_S, Reg, 3, 1)
INSN(I64_GT_U, Reg, 3, 1)
INSN(I64_LE_S, Reg, 3, 1)
INSN(I64_LE_U, Reg, 3, 1)
INSN(I64_GE_S, Reg, 3, 1)
INSN(I64_GE_U, Reg, 3, 1)
INSN(F32_EQ, Reg, 3, 1)
INSN(F32_NE, Reg, 3, 1)
INSN(F32_LT, Reg, 3, 1)
INSN(F32_GT, Reg, 3, 1)
INSN(F32_LE, Reg, 3, 1)
INSN(F32_GE, Reg, 3, 1)
INSN(F64_EQ, Reg, 3, 1)
INSN(F64_NE, Reg, 3, 1)
INSN(F64_LT, Reg, 3, 1)
INSN(F64_GT, Reg, 3, 1)
INSN(F64_LE, Reg, 3, 1)
INSN(F64_GE, Reg, 3, 1)
/* Select instruction */
INSN(SELECT, Reg, 4, 1)
/* Memory instructions */
INSN(I32_LOAD, Reg, 2, 1)
INSN(I64_LOAD, Reg, 2, 1)

View File

@ -907,9 +907,15 @@ typedef struct JitFrame {
/* Max operand stack slot number. */
uint32 max_stacks;
/* Instruction pointer */
uint8 *ip;
/* Stack top pointer */
JitValueSlot *sp;
/* Committed instruction pointer */
uint8 *committed_ip;
/* Committed stack top pointer */
JitValueSlot *committed_sp;
@ -998,7 +1004,8 @@ typedef struct JitCompContext {
be 0 and 1 respectively (see JIT_FOREACH_BLOCK). */
JitReg entry_label;
JitReg exit_label;
JitBasicBlock *exception_basic_blocks;
JitBasicBlock **exce_basic_blocks;
JitIncomingInsnList *incoming_insns_for_exec_bbs;
/* The current basic block to generate instructions */
JitBasicBlock *cur_basic_block;
@ -1229,6 +1236,15 @@ jit_cc_inc_ref(JitCompContext *cc)
void
jit_cc_delete(JitCompContext *cc);
char *
jit_get_last_error(JitCompContext *cc);
void
jit_set_last_error(JitCompContext *cc, const char *error);
void
jit_set_last_error_v(JitCompContext *cc, const char *format, ...);
/**
* Create a I32 constant value with relocatable into the compilation
* context. A constant value that has relocation info cannot be
@ -1520,6 +1536,8 @@ _gen_insn(JitCompContext *cc, JitInsn *insn)
{
if (insn)
jit_basic_block_append_insn(cc->cur_basic_block, insn);
else
jit_set_last_error(cc, "generate insn failed");
return insn;
}
@ -1529,6 +1547,7 @@ _gen_insn(JitCompContext *cc, JitInsn *insn)
*/
#define GEN_INSN(...) _gen_insn(cc, jit_cc_new_insn(cc, __VA_ARGS__))
#if 0
/**
* Helper function for GEN_INSN_NORM_1
*
@ -1559,6 +1578,7 @@ _gen_insn_norm_1(JitCompContext *cc, JitBasicBlock *block, unsigned kind,
*/
#define GEN_INSN_NORM(Type, result, ...) \
GEN_INSN_NORM_1(JIT_REG_KIND_##Type, result, __VA_ARGS__)
#endif
/**
* Create a constant register without relocation info.
@ -1737,15 +1757,6 @@ jit_cc_exit_basic_block(JitCompContext *cc)
return *(jit_annl_basic_block(cc, cc->exit_label));
}
char *
jit_get_last_error(JitCompContext *cc);
void
jit_set_last_error(JitCompContext *cc, const char *error);
void
jit_set_last_error_v(JitCompContext *cc, const char *format, ...);
void
jit_value_stack_push(JitValueStack *stack, JitValue *value);

View File

@ -312,8 +312,11 @@ rc_init(RegallocContext *rc, JitCompContext *cc)
const unsigned vreg_num = jit_cc_reg_num(cc, i);
const unsigned hreg_num = jit_cc_hreg_num(cc, i);
if (!(rc->vregs[i] = jit_calloc(sizeof(VirtualReg) * vreg_num))
|| !(rc->hregs[i] = jit_calloc(sizeof(HardReg) * hreg_num)))
if (vreg_num > 0
&& !(rc->vregs[i] = jit_calloc(sizeof(VirtualReg) * vreg_num)))
goto fail;
if (hreg_num > 0
&& !(rc->hregs[i] = jit_calloc(sizeof(HardReg) * hreg_num)))
goto fail;
/* Hard registers can only be allocated to themselves. */
@ -407,8 +410,8 @@ reload_vreg(RegallocContext *rc, JitReg vreg, JitInsn *cur_insn)
JitInsn *insn = NULL;
if (vreg == rc->cc->exec_env_reg)
/* Reload exec_env_reg with LDSELF. */
insn = jit_cc_new_insn(rc->cc, LDSELF, vr->hreg);
/* Reload exec_env_reg with LDEXECENV. */
insn = jit_cc_new_insn(rc->cc, LDEXECENV, vr->hreg);
else
/* Allocate spill slot if not yet and reload from there. */
{

View File

@ -3767,8 +3767,11 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
#if WASM_ENABLE_FAST_JIT == 0
wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame);
#else
jit_interp_switch_to_jitted(exec_env, frame, function,
JitInterpSwitchInfo info;
info.frame = frame;
jit_interp_switch_to_jitted(exec_env, &info,
function->u.func->jitted_code);
(void)wasm_interp_call_func_bytecode;
#endif
}

View File

@ -123,11 +123,15 @@ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security -W
if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mindirect-branch-register")
# UNDEFINED BEHAVIOR, refer to https://en.cppreference.com/w/cpp/language/ub
if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT WAMR_BUILD_JIT EQUAL 1)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined \
-fno-sanitize=bounds,bounds-strict,alignment \
-fno-sanitize-recover")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined \
-fno-sanitize=bounds,bounds-strict,alignment \
-fno-sanitize-recover")
endif()
else ()
# UNDEFINED BEHAVIOR, refer to https://en.cppreference.com/w/cpp/language/ub
@ -135,6 +139,9 @@ if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined \
-fno-sanitize=bounds,alignment \
-fno-sanitize-recover")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined \
-fno-sanitize=bounds,alignment \
-fno-sanitize-recover")
endif()
endif ()
endif ()