| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489 |
- /*
- * Copyright (C) 2019 Intel Corporation. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
- #include "aot_emit_table.h"
- #include "aot_emit_exception.h"
- #include "../aot/aot_runtime.h"
- uint64
- get_tbl_inst_offset(const AOTCompContext *comp_ctx,
- const AOTFuncContext *func_ctx,
- uint32 tbl_idx)
- {
- uint64 offset = 0, i = 0;
- AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables;
- AOTTable *tbls = comp_ctx->comp_data->tables;
- /* from the head of AOTModuleInstance */
- offset =
- offsetof(AOTModuleInstance, global_table_data.bytes)
- + (uint64)comp_ctx->comp_data->memory_count * sizeof(AOTMemoryInstance)
- + comp_ctx->comp_data->global_data_size;
- while (i < tbl_idx && i < comp_ctx->comp_data->import_table_count) {
- offset += offsetof(AOTTableInstance, data);
- /* avoid loading from current AOTTableInstance */
- offset += sizeof(uint32) * aot_get_imp_tbl_data_slots(imp_tbls + i);
- ++i;
- }
- if (i == tbl_idx) {
- return offset;
- }
- tbl_idx -= comp_ctx->comp_data->import_table_count;
- i -= comp_ctx->comp_data->import_table_count;
- while (i < tbl_idx && i < comp_ctx->comp_data->table_count) {
- offset += offsetof(AOTTableInstance, data);
- /* avoid loading from current AOTTableInstance */
- offset += sizeof(uint32) * aot_get_tbl_data_slots(tbls + i);
- ++i;
- }
- return offset;
- }
- #if WASM_ENABLE_REF_TYPES != 0
- LLVMValueRef
- aot_compile_get_tbl_inst(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx,
- uint32 tbl_idx)
- {
- LLVMValueRef offset, tbl_inst;
- if (!(offset =
- I64_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)))) {
- HANDLE_FAILURE("LLVMConstInt");
- goto fail;
- }
- if (!(tbl_inst = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst,
- &offset, 1, "tbl_inst"))) {
- HANDLE_FAILURE("LLVMBuildGEP");
- goto fail;
- }
- return tbl_inst;
- fail:
- return NULL;
- }
- bool
- aot_compile_op_elem_drop(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx,
- uint32 tbl_seg_idx)
- {
- LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
- LLVMValueRef param_values[2], ret_value, func, value;
- /* void aot_drop_table_seg(AOTModuleInstance *, uint32 ) */
- param_types[0] = INT8_PTR_TYPE;
- param_types[1] = I32_TYPE;
- ret_type = VOID_TYPE;
- GET_AOT_FUNCTION(aot_drop_table_seg, 2);
- param_values[0] = func_ctx->aot_inst;
- if (!(param_values[1] = I32_CONST(tbl_seg_idx))) {
- HANDLE_FAILURE("LLVMConstInt");
- goto fail;
- }
- /* "" means return void */
- if (!(ret_value =
- LLVMBuildCall(comp_ctx->builder, func, param_values, 2, ""))) {
- HANDLE_FAILURE("LLVMBuildCall");
- goto fail;
- }
- return true;
- fail:
- return false;
- }
- static bool
- aot_check_table_access(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx,
- uint32 tbl_idx,
- LLVMValueRef elem_idx)
- {
- LLVMValueRef offset, tbl_sz, cmp_elem_idx;
- LLVMBasicBlockRef check_elem_idx_succ;
- /* get the cur size of the table instance */
- if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
- + offsetof(AOTTableInstance, cur_size)))) {
- HANDLE_FAILURE("LLVMConstInt");
- goto fail;
- }
- if (!(tbl_sz = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst, &offset,
- 1, "cur_size_i8p"))) {
- HANDLE_FAILURE("LLVMBuildGEP");
- goto fail;
- }
- if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
- "cur_siuze_i32p"))) {
- HANDLE_FAILURE("LLVMBuildBitCast");
- goto fail;
- }
- if (!(tbl_sz = LLVMBuildLoad(comp_ctx->builder, tbl_sz, "cur_size"))) {
- HANDLE_FAILURE("LLVMBuildLoad");
- goto fail;
- }
- /* Check if (uint32)elem index >= table size */
- if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, elem_idx,
- tbl_sz, "cmp_elem_idx"))) {
- aot_set_last_error("llvm build icmp failed.");
- goto fail;
- }
- /* Throw exception if elem index >= table size */
- if (!(check_elem_idx_succ = LLVMAppendBasicBlockInContext(
- comp_ctx->context, func_ctx->func, "check_elem_idx_succ"))) {
- aot_set_last_error("llvm add basic block failed.");
- goto fail;
- }
- LLVMMoveBasicBlockAfter(check_elem_idx_succ,
- LLVMGetInsertBlock(comp_ctx->builder));
- if (!(aot_emit_exception(comp_ctx, func_ctx,
- EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, true,
- cmp_elem_idx, check_elem_idx_succ)))
- goto fail;
- return true;
- fail:
- return false;
- }
- bool
- aot_compile_op_table_get(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx,
- uint32 tbl_idx)
- {
- LLVMValueRef elem_idx, offset, table_elem, func_idx;
- POP_I32(elem_idx);
- if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
- goto fail;
- }
- /* load data as i32* */
- if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
- + offsetof(AOTTableInstance, data)))) {
- HANDLE_FAILURE("LLVMConstInt");
- goto fail;
- }
- if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst,
- &offset, 1, "table_elem_i8p"))) {
- aot_set_last_error("llvm build add failed.");
- goto fail;
- }
- if (!(table_elem = LLVMBuildBitCast(comp_ctx->builder, table_elem,
- INT32_PTR_TYPE, "table_elem_i32p"))) {
- HANDLE_FAILURE("LLVMBuildBitCast");
- goto fail;
- }
- /* Load function index */
- if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx,
- 1, "table_elem"))) {
- HANDLE_FAILURE("LLVMBuildNUWAdd");
- goto fail;
- }
- if (!(func_idx =
- LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) {
- HANDLE_FAILURE("LLVMBuildLoad");
- goto fail;
- }
- PUSH_I32(func_idx);
- return true;
- fail:
- return false;
- }
- bool
- aot_compile_op_table_set(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx,
- uint32 tbl_idx)
- {
- LLVMValueRef val, elem_idx, offset, table_elem;
- POP_I32(val);
- POP_I32(elem_idx);
- if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
- goto fail;
- }
- /* load data as i32* */
- if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
- + offsetof(AOTTableInstance, data)))) {
- HANDLE_FAILURE("LLVMConstInt");
- goto fail;
- }
- if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst,
- &offset, 1, "table_elem_i8p"))) {
- HANDLE_FAILURE("LLVMBuildGEP");
- goto fail;
- }
- if (!(table_elem = LLVMBuildBitCast(comp_ctx->builder, table_elem,
- INT32_PTR_TYPE, "table_elem_i32p"))) {
- HANDLE_FAILURE("LLVMBuildBitCast");
- goto fail;
- }
- /* Load function index */
- if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx,
- 1, "table_elem"))) {
- HANDLE_FAILURE("LLVMBuildGEP");
- goto fail;
- }
- if (!(LLVMBuildStore(comp_ctx->builder, val, table_elem))) {
- HANDLE_FAILURE("LLVMBuildStore");
- goto fail;
- }
- return true;
- fail:
- return false;
- }
- bool
- aot_compile_op_table_init(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx,
- uint32 tbl_idx,
- uint32 tbl_seg_idx)
- {
- LLVMValueRef func, param_values[6], value;
- LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
- param_types[0] = INT8_PTR_TYPE;
- param_types[1] = I32_TYPE;
- param_types[2] = I32_TYPE;
- param_types[3] = I32_TYPE;
- param_types[4] = I32_TYPE;
- param_types[5] = I32_TYPE;
- ret_type = VOID_TYPE;
- GET_AOT_FUNCTION(aot_table_init, 6);
- param_values[0] = func_ctx->aot_inst;
- if (!(param_values[1] = I32_CONST(tbl_idx))) {
- HANDLE_FAILURE("LLVMConstInt");
- goto fail;
- }
- if (!(param_values[2] = I32_CONST(tbl_seg_idx))) {
- HANDLE_FAILURE("LLVMConstInt");
- goto fail;
- }
- /* n */
- POP_I32(param_values[3]);
- /* s */
- POP_I32(param_values[4]);
- /* d */
- POP_I32(param_values[5]);
- /* "" means return void */
- if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 6, ""))) {
- HANDLE_FAILURE("LLVMBuildCall");
- goto fail;
- }
- return true;
- fail:
- return false;
- }
- bool
- aot_compile_op_table_copy(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx,
- uint32 src_tbl_idx,
- uint32 dst_tbl_idx)
- {
- LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
- LLVMValueRef func, param_values[6], value;
- param_types[0] = INT8_PTR_TYPE;
- param_types[1] = I32_TYPE;
- param_types[2] = I32_TYPE;
- param_types[3] = I32_TYPE;
- param_types[4] = I32_TYPE;
- param_types[5] = I32_TYPE;
- ret_type = VOID_TYPE;
- GET_AOT_FUNCTION(aot_table_copy, 6);
- param_values[0] = func_ctx->aot_inst;
- if (!(param_values[1] = I32_CONST(src_tbl_idx))) {
- HANDLE_FAILURE("LLVMConstInt");
- goto fail;
- }
- if (!(param_values[2] = I32_CONST(dst_tbl_idx))) {
- HANDLE_FAILURE("LLVMConstInt");
- goto fail;
- }
- /* n */
- POP_I32(param_values[3]);
- /* s */
- POP_I32(param_values[4]);
- /* d */
- POP_I32(param_values[5]);
- /* "" means return void */
- if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 6, ""))) {
- HANDLE_FAILURE("LLVMBuildCall");
- goto fail;
- }
- return true;
- fail:
- return false;
- }
- bool
- aot_compile_op_table_size(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx,
- uint32 tbl_idx)
- {
- LLVMValueRef offset, tbl_sz;
- if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
- + offsetof(AOTTableInstance, cur_size)))) {
- HANDLE_FAILURE("LLVMConstInt");
- goto fail;
- }
- if (!(tbl_sz = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst, &offset,
- 1, "tbl_sz_ptr_i8"))) {
- HANDLE_FAILURE("LLVMBuildGEP");
- goto fail;
- }
- if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
- "tbl_sz_ptr"))) {
- HANDLE_FAILURE("LLVMBuildBitCast");
- goto fail;
- }
- if (!(tbl_sz = LLVMBuildLoad(comp_ctx->builder, tbl_sz, "tbl_sz"))) {
- HANDLE_FAILURE("LLVMBuildLoad");
- goto fail;
- }
- PUSH_I32(tbl_sz);
- return true;
- fail:
- return false;
- }
- bool
- aot_compile_op_table_grow(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx,
- uint32 tbl_idx)
- {
- LLVMTypeRef param_types[4], ret_type, func_type, func_ptr_type;
- LLVMValueRef func, param_values[4], ret, value;
- param_types[0] = INT8_PTR_TYPE;
- param_types[1] = I32_TYPE;
- param_types[2] = I32_TYPE;
- param_types[3] = I32_TYPE;
- ret_type = I32_TYPE;
- GET_AOT_FUNCTION(aot_table_grow, 4);
- param_values[0] = func_ctx->aot_inst;
- if (!(param_values[1] = I32_CONST(tbl_idx))) {
- HANDLE_FAILURE("LLVMConstInt");
- goto fail;
- }
- /* n */
- POP_I32(param_values[2]);
- /* v */
- POP_I32(param_values[3]);
- if (!(ret = LLVMBuildCall(comp_ctx->builder, func, param_values, 4,
- "table_grow"))) {
- HANDLE_FAILURE("LLVMBuildCall");
- goto fail;
- }
- PUSH_I32(ret);
- return true;
- fail:
- return false;
- }
- bool
- aot_compile_op_table_fill(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx,
- uint32 tbl_idx)
- {
- LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type;
- LLVMValueRef func, param_values[5], value;
- param_types[0] = INT8_PTR_TYPE;
- param_types[1] = I32_TYPE;
- param_types[2] = I32_TYPE;
- param_types[3] = I32_TYPE;
- param_types[4] = I32_TYPE;
- ret_type = VOID_TYPE;
- GET_AOT_FUNCTION(aot_table_fill, 5);
- param_values[0] = func_ctx->aot_inst;
- if (!(param_values[1] = I32_CONST(tbl_idx))) {
- HANDLE_FAILURE("LLVMConstInt");
- goto fail;
- }
- /* n */
- POP_I32(param_values[2]);
- /* v */
- POP_I32(param_values[3]);
- /* i */
- POP_I32(param_values[4]);
- /* "" means return void */
- if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 5, ""))) {
- HANDLE_FAILURE("LLVMBuildCall");
- goto fail;
- }
- return true;
- fail:
- return false;
- }
- #endif /* WASM_ENABLE_REF_TYPES != 0 */
|