mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-14 05:31:13 +00:00

Implement part of codegen and fix some frontend issues Add asmjit to emit native code and add zydis to disassemble native code Can successfully run some simple cases
198 lines
4.7 KiB
C
198 lines
4.7 KiB
C
/*
|
|
* Copyright (C) 2021 Intel Corporation. All rights reserved.
|
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
*/
|
|
|
|
#include "jit_compiler.h"
|
|
#include "jit_ir.h"
|
|
#include "jit_codegen.h"
|
|
#include "jit_codecache.h"
|
|
#include "../interpreter/wasm.h"
|
|
|
|
typedef struct JitCompilerPass {
|
|
/* Name of the pass. */
|
|
const char *name;
|
|
/* The entry of the compiler pass. */
|
|
bool (*run)(JitCompContext *cc);
|
|
} JitCompilerPass;
|
|
|
|
/* clang-format off */
|
|
static JitCompilerPass compiler_passes[] = {
|
|
{ NULL, NULL },
|
|
#define REG_PASS(name) { #name, jit_pass_##name }
|
|
REG_PASS(dump),
|
|
REG_PASS(update_cfg),
|
|
REG_PASS(frontend),
|
|
REG_PASS(lower_cg),
|
|
REG_PASS(regalloc),
|
|
REG_PASS(codegen),
|
|
REG_PASS(register_jitted_code)
|
|
#undef REG_PASS
|
|
};
|
|
|
|
/* Number of compiler passes. */
|
|
#define COMPILER_PASS_NUM (sizeof(compiler_passes) / sizeof(compiler_passes[0]))
|
|
|
|
#if WASM_ENABLE_FAST_JIT_DUMP == 0
|
|
static const uint8 compiler_passes_without_dump[] = {
|
|
3, 4, 5, 6, 7, 0
|
|
};
|
|
#else
|
|
static const uint8 compiler_passes_with_dump[] = {
|
|
3, 2, 1, 4, 1, 5, 1, 6, 1, 7, 0
|
|
};
|
|
#endif
|
|
|
|
/* The exported global data of JIT compiler. */
|
|
static JitGlobals jit_globals = {
|
|
#if WASM_ENABLE_FAST_JIT_DUMP == 0
|
|
.passes = compiler_passes_without_dump,
|
|
#else
|
|
.passes = compiler_passes_with_dump,
|
|
#endif
|
|
.code_cache_size = 10 * 1024 * 1024,
|
|
.return_to_interp_from_jitted = NULL
|
|
};
|
|
/* clang-format on */
|
|
|
|
static bool
|
|
apply_compiler_passes(JitCompContext *cc)
|
|
{
|
|
const uint8 *p = jit_globals.passes;
|
|
|
|
for (; *p; p++) {
|
|
/* Set the pass NO. */
|
|
cc->cur_pass_no = p - jit_globals.passes;
|
|
bh_assert(*p < COMPILER_PASS_NUM);
|
|
|
|
if (!compiler_passes[*p].run(cc)) {
|
|
LOG_VERBOSE("JIT: compilation failed at pass[%d] = %s\n",
|
|
p - jit_globals.passes, compiler_passes[*p].name);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
jit_compiler_init()
|
|
{
|
|
/* TODO: get code cache size with global configs */
|
|
if (!jit_code_cache_init(jit_globals.code_cache_size))
|
|
return false;
|
|
|
|
if (!jit_codegen_init())
|
|
goto fail1;
|
|
|
|
return true;
|
|
|
|
fail1:
|
|
jit_code_cache_destroy();
|
|
return false;
|
|
}
|
|
|
|
void
|
|
jit_compiler_destroy()
|
|
{
|
|
jit_codegen_destroy();
|
|
|
|
jit_code_cache_destroy();
|
|
}
|
|
|
|
JitGlobals *
|
|
jit_compiler_get_jit_globals()
|
|
{
|
|
return &jit_globals;
|
|
}
|
|
|
|
const char *
|
|
jit_compiler_get_pass_name(unsigned i)
|
|
{
|
|
return i < COMPILER_PASS_NUM ? compiler_passes[i].name : NULL;
|
|
}
|
|
|
|
bool
|
|
jit_compiler_compile(WASMModule *module, uint32 func_idx)
|
|
{
|
|
JitCompContext *cc;
|
|
char *last_error;
|
|
bool ret = true;
|
|
|
|
/* Initialize compilation context. */
|
|
if (!(cc = jit_calloc(sizeof(*cc))))
|
|
return false;
|
|
|
|
if (!jit_cc_init(cc, 64)) {
|
|
jit_free(cc);
|
|
return false;
|
|
}
|
|
|
|
cc->cur_wasm_module = module;
|
|
cc->cur_wasm_func = module->functions[func_idx];
|
|
cc->cur_wasm_func_idx = func_idx;
|
|
cc->mem_space_unchanged = (!cc->cur_wasm_func->has_op_memory_grow
|
|
&& !cc->cur_wasm_func->has_op_func_call)
|
|
|| (!module->possible_memory_grow);
|
|
|
|
/* Apply compiler passes. */
|
|
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;
|
|
}
|
|
|
|
/* Delete the compilation context. */
|
|
jit_cc_delete(cc);
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool
|
|
jit_compiler_compile_all(WASMModule *module)
|
|
{
|
|
JitCompContext *cc;
|
|
char *last_error;
|
|
bool ret = true;
|
|
uint32 i;
|
|
|
|
/* Initialize compilation context. */
|
|
if (!(cc = jit_calloc(sizeof(*cc))))
|
|
return false;
|
|
|
|
if (!jit_cc_init(cc, 64)) {
|
|
jit_free(cc);
|
|
return false;
|
|
}
|
|
|
|
for (i = 0; i < module->function_count; i++) {
|
|
cc->cur_wasm_module = module;
|
|
cc->cur_wasm_func = module->functions[i];
|
|
cc->cur_wasm_func_idx = i;
|
|
cc->mem_space_unchanged = (!cc->cur_wasm_func->has_op_memory_grow
|
|
&& !cc->cur_wasm_func->has_op_func_call)
|
|
|| (!module->possible_memory_grow);
|
|
|
|
/* Apply compiler passes. */
|
|
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;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Delete the compilation context. */
|
|
jit_cc_delete(cc);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
jit_interp_switch_to_jitted(void *exec_env, JitInterpSwitchInfo *info, void *pc)
|
|
{
|
|
return jit_codegen_interp_jitted_glue(exec_env, info, pc);
|
|
}
|