mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-06 15:05:19 +00:00
0ee5ffce85
# Change the data type representing linear memory address from u32 to u64 ## APIs signature changes - (Export)wasm_runtime_module_malloc - wasm_module_malloc - wasm_module_malloc_internal - aot_module_malloc - aot_module_malloc_internal - wasm_runtime_module_realloc - wasm_module_realloc - wasm_module_realloc_internal - aot_module_realloc - aot_module_realloc_internal - (Export)wasm_runtime_module_free - wasm_module_free - wasm_module_free_internal - aot_module_malloc - aot_module_free_internal - (Export)wasm_runtime_module_dup_data - wasm_module_dup_data - aot_module_dup_data - (Export)wasm_runtime_validate_app_addr - (Export)wasm_runtime_validate_app_str_addr - (Export)wasm_runtime_validate_native_addr - (Export)wasm_runtime_addr_app_to_native - (Export)wasm_runtime_addr_native_to_app - (Export)wasm_runtime_get_app_addr_range - aot_set_aux_stack - aot_get_aux_stack - wasm_set_aux_stack - wasm_get_aux_stack - aot_check_app_addr_and_convert, wasm_check_app_addr_and_convert and jit_check_app_addr_and_convert - wasm_exec_env_set_aux_stack - wasm_exec_env_get_aux_stack - wasm_cluster_create_thread - wasm_cluster_allocate_aux_stack - wasm_cluster_free_aux_stack ## Data structure changes - WASMModule and AOTModule - field aux_data_end, aux_heap_base and aux_stack_bottom - WASMExecEnv - field aux_stack_boundary and aux_stack_bottom - AOTCompData - field aux_data_end, aux_heap_base and aux_stack_bottom - WASMMemoryInstance(AOTMemoryInstance) - field memory_data_size and change __padding to is_memory64 - WASMModuleInstMemConsumption - field total_size and memories_size - WASMDebugExecutionMemory - field start_offset and current_pos - WASMCluster - field stack_tops ## Components that are affected by the APIs and data structure changes - libc-builtin - libc-emcc - libc-uvwasi - libc-wasi - Python and Go Language Embedding - Interpreter Debug engine - Multi-thread: lib-pthread, wasi-threads and thread manager
332 lines
11 KiB
C
332 lines
11 KiB
C
/*
|
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
*/
|
|
|
|
#include "aot_emit_variable.h"
|
|
#include "aot_emit_exception.h"
|
|
#include "../aot/aot_runtime.h"
|
|
|
|
#define CHECK_LOCAL(idx) \
|
|
do { \
|
|
if (idx >= func_ctx->aot_func->func_type->param_count \
|
|
+ func_ctx->aot_func->local_count) { \
|
|
aot_set_last_error("local index out of range"); \
|
|
return false; \
|
|
} \
|
|
} while (0)
|
|
|
|
static uint8
|
|
get_local_type(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
uint32 local_idx)
|
|
{
|
|
AOTFunc *aot_func = func_ctx->aot_func;
|
|
uint32 param_count = aot_func->func_type->param_count;
|
|
uint8 local_type;
|
|
|
|
local_type = local_idx < param_count
|
|
? aot_func->func_type->types[local_idx]
|
|
: aot_func->local_types_wp[local_idx - param_count];
|
|
|
|
if (comp_ctx->enable_gc && aot_is_type_gc_reftype(local_type))
|
|
local_type = VALUE_TYPE_GC_REF;
|
|
|
|
return local_type;
|
|
}
|
|
|
|
bool
|
|
aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
uint32 local_idx)
|
|
{
|
|
char name[32];
|
|
LLVMValueRef value;
|
|
AOTValue *aot_value_top;
|
|
uint8 local_type;
|
|
|
|
CHECK_LOCAL(local_idx);
|
|
|
|
local_type = get_local_type(comp_ctx, func_ctx, local_idx);
|
|
|
|
snprintf(name, sizeof(name), "%s%d%s", "local", local_idx, "#");
|
|
if (!(value = LLVMBuildLoad2(comp_ctx->builder, TO_LLVM_TYPE(local_type),
|
|
func_ctx->locals[local_idx], name))) {
|
|
aot_set_last_error("llvm build load fail");
|
|
return false;
|
|
}
|
|
|
|
PUSH(value, local_type);
|
|
|
|
aot_value_top =
|
|
func_ctx->block_stack.block_list_end->value_stack.value_list_end;
|
|
aot_value_top->is_local = true;
|
|
aot_value_top->local_idx = local_idx;
|
|
return true;
|
|
|
|
fail:
|
|
return false;
|
|
}
|
|
|
|
static bool
|
|
aot_compile_op_set_or_tee_local(AOTCompContext *comp_ctx,
|
|
AOTFuncContext *func_ctx, uint32 local_idx,
|
|
bool is_tee_local)
|
|
{
|
|
LLVMValueRef value;
|
|
uint8 local_type;
|
|
uint32 n;
|
|
|
|
CHECK_LOCAL(local_idx);
|
|
|
|
local_type = get_local_type(comp_ctx, func_ctx, local_idx);
|
|
|
|
POP(value, local_type);
|
|
|
|
if (comp_ctx->aot_frame) {
|
|
/* Get the slot index */
|
|
n = func_ctx->aot_func->local_offsets[local_idx];
|
|
bh_assert(comp_ctx->aot_frame->lp[n].type == local_type);
|
|
|
|
switch (local_type) {
|
|
case VALUE_TYPE_I32:
|
|
set_local_i32(comp_ctx->aot_frame, n, value);
|
|
break;
|
|
case VALUE_TYPE_I64:
|
|
set_local_i64(comp_ctx->aot_frame, n, value);
|
|
break;
|
|
case VALUE_TYPE_F32:
|
|
set_local_f32(comp_ctx->aot_frame, n, value);
|
|
break;
|
|
case VALUE_TYPE_F64:
|
|
set_local_f64(comp_ctx->aot_frame, n, value);
|
|
break;
|
|
case VALUE_TYPE_V128:
|
|
set_local_v128(comp_ctx->aot_frame, n, value);
|
|
break;
|
|
case VALUE_TYPE_FUNCREF:
|
|
case VALUE_TYPE_EXTERNREF:
|
|
set_local_ref(comp_ctx->aot_frame, n, value, local_type);
|
|
break;
|
|
#if WASM_ENABLE_GC != 0
|
|
case VALUE_TYPE_GC_REF:
|
|
set_local_gc_ref(comp_ctx->aot_frame, n, value, local_type);
|
|
break;
|
|
#endif
|
|
default:
|
|
bh_assert(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!LLVMBuildStore(comp_ctx->builder, value,
|
|
func_ctx->locals[local_idx])) {
|
|
aot_set_last_error("llvm build store fail");
|
|
return false;
|
|
}
|
|
|
|
if (is_tee_local) {
|
|
PUSH(value, local_type);
|
|
}
|
|
|
|
aot_checked_addr_list_del(func_ctx, local_idx);
|
|
return true;
|
|
|
|
fail:
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
aot_compile_op_set_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
uint32 local_idx)
|
|
{
|
|
return aot_compile_op_set_or_tee_local(comp_ctx, func_ctx, local_idx,
|
|
false);
|
|
}
|
|
|
|
bool
|
|
aot_compile_op_tee_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
uint32 local_idx)
|
|
{
|
|
return aot_compile_op_set_or_tee_local(comp_ctx, func_ctx, local_idx, true);
|
|
}
|
|
|
|
static bool
|
|
compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
uint32 global_idx, bool is_set, bool is_aux_stack)
|
|
{
|
|
const AOTCompData *comp_data = comp_ctx->comp_data;
|
|
uint32 import_global_count = comp_data->import_global_count;
|
|
uint32 global_base_offset;
|
|
uint32 global_offset;
|
|
uint8 global_type;
|
|
LLVMValueRef offset, global_ptr, global, res;
|
|
LLVMTypeRef ptr_type = NULL;
|
|
|
|
global_base_offset =
|
|
offsetof(AOTModuleInstance, global_table_data.bytes)
|
|
+ sizeof(AOTMemoryInstance) * comp_ctx->comp_data->memory_count;
|
|
|
|
bh_assert(global_idx < import_global_count + comp_data->global_count);
|
|
|
|
if (global_idx < import_global_count) {
|
|
global_offset =
|
|
global_base_offset
|
|
/* Get global data offset according to target info */
|
|
+ (comp_ctx->pointer_size == sizeof(uint64)
|
|
? comp_data->import_globals[global_idx].data_offset_64bit
|
|
: comp_data->import_globals[global_idx].data_offset_32bit);
|
|
global_type = comp_data->import_globals[global_idx].type;
|
|
}
|
|
else {
|
|
global_offset =
|
|
global_base_offset
|
|
/* Get global data offset according to target info */
|
|
+ (comp_ctx->pointer_size == sizeof(uint64)
|
|
? comp_data->globals[global_idx - import_global_count]
|
|
.data_offset_64bit
|
|
: comp_data->globals[global_idx - import_global_count]
|
|
.data_offset_32bit);
|
|
global_type = comp_data->globals[global_idx - import_global_count].type;
|
|
}
|
|
|
|
if (comp_ctx->enable_gc && aot_is_type_gc_reftype(global_type))
|
|
global_type = VALUE_TYPE_GC_REF;
|
|
|
|
offset = I32_CONST(global_offset);
|
|
if (!(global_ptr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
|
|
func_ctx->aot_inst, &offset, 1,
|
|
"global_ptr_tmp"))) {
|
|
aot_set_last_error("llvm build in bounds gep failed.");
|
|
return false;
|
|
}
|
|
|
|
switch (global_type) {
|
|
case VALUE_TYPE_I32:
|
|
case VALUE_TYPE_EXTERNREF:
|
|
case VALUE_TYPE_FUNCREF:
|
|
ptr_type = INT32_PTR_TYPE;
|
|
break;
|
|
case VALUE_TYPE_I64:
|
|
ptr_type = INT64_PTR_TYPE;
|
|
break;
|
|
case VALUE_TYPE_F32:
|
|
ptr_type = F32_PTR_TYPE;
|
|
break;
|
|
case VALUE_TYPE_F64:
|
|
ptr_type = F64_PTR_TYPE;
|
|
break;
|
|
case VALUE_TYPE_V128:
|
|
ptr_type = V128_PTR_TYPE;
|
|
break;
|
|
#if WASM_ENABLE_GC != 0
|
|
case VALUE_TYPE_GC_REF:
|
|
ptr_type = GC_REF_PTR_TYPE;
|
|
break;
|
|
#endif
|
|
default:
|
|
bh_assert("unknown type");
|
|
break;
|
|
}
|
|
|
|
if (!(global_ptr = LLVMBuildBitCast(comp_ctx->builder, global_ptr, ptr_type,
|
|
"global_ptr"))) {
|
|
aot_set_last_error("llvm build bit cast failed.");
|
|
return false;
|
|
}
|
|
|
|
if (!is_set) {
|
|
if (!(global =
|
|
LLVMBuildLoad2(comp_ctx->builder, TO_LLVM_TYPE(global_type),
|
|
global_ptr, "global"))) {
|
|
aot_set_last_error("llvm build load failed.");
|
|
return false;
|
|
}
|
|
/* All globals' data is 4-byte aligned */
|
|
LLVMSetAlignment(global, 4);
|
|
PUSH(global, global_type);
|
|
}
|
|
else {
|
|
POP(global, global_type);
|
|
|
|
if (is_aux_stack && comp_ctx->enable_aux_stack_check) {
|
|
LLVMBasicBlockRef block_curr =
|
|
LLVMGetInsertBlock(comp_ctx->builder);
|
|
LLVMBasicBlockRef check_overflow_succ, check_underflow_succ;
|
|
LLVMValueRef cmp, global_i64;
|
|
|
|
/* Add basic blocks */
|
|
if (!(check_overflow_succ = LLVMAppendBasicBlockInContext(
|
|
comp_ctx->context, func_ctx->func,
|
|
"check_overflow_succ"))) {
|
|
aot_set_last_error("llvm add basic block failed.");
|
|
return false;
|
|
}
|
|
LLVMMoveBasicBlockAfter(check_overflow_succ, block_curr);
|
|
|
|
if (!(check_underflow_succ = LLVMAppendBasicBlockInContext(
|
|
comp_ctx->context, func_ctx->func,
|
|
"check_underflow_succ"))) {
|
|
aot_set_last_error("llvm add basic block failed.");
|
|
return false;
|
|
}
|
|
LLVMMoveBasicBlockAfter(check_underflow_succ, check_overflow_succ);
|
|
|
|
if (!(global_i64 = LLVMBuildZExt(comp_ctx->builder, global,
|
|
I64_TYPE, "global_i64"))) {
|
|
aot_set_last_error("llvm build zext failed.");
|
|
return false;
|
|
}
|
|
|
|
/* Check aux stack overflow */
|
|
if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULE, global_i64,
|
|
func_ctx->aux_stack_bound, "cmp"))) {
|
|
aot_set_last_error("llvm build icmp failed.");
|
|
return false;
|
|
}
|
|
if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_AUX_STACK_OVERFLOW,
|
|
true, cmp, check_overflow_succ)) {
|
|
return false;
|
|
}
|
|
|
|
/* Check aux stack underflow */
|
|
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_overflow_succ);
|
|
if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, global_i64,
|
|
func_ctx->aux_stack_bottom, "cmp"))) {
|
|
aot_set_last_error("llvm build icmp failed.");
|
|
return false;
|
|
}
|
|
if (!aot_emit_exception(comp_ctx, func_ctx,
|
|
EXCE_AUX_STACK_UNDERFLOW, true, cmp,
|
|
check_underflow_succ)) {
|
|
return false;
|
|
}
|
|
|
|
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_underflow_succ);
|
|
}
|
|
|
|
if (!(res = LLVMBuildStore(comp_ctx->builder, global, global_ptr))) {
|
|
aot_set_last_error("llvm build store failed.");
|
|
return false;
|
|
}
|
|
/* All globals' data is 4-byte aligned */
|
|
LLVMSetAlignment(res, 4);
|
|
}
|
|
|
|
return true;
|
|
fail:
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
aot_compile_op_get_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
uint32 global_idx)
|
|
{
|
|
return compile_global(comp_ctx, func_ctx, global_idx, false, false);
|
|
}
|
|
|
|
bool
|
|
aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
uint32 global_idx, bool is_aux_stack)
|
|
{
|
|
return compile_global(comp_ctx, func_ctx, global_idx, true, is_aux_stack);
|
|
}
|