| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- /*
- * Copyright (C) 2019 Intel Corporation. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
- #include "jit_emit_table.h"
- #include "jit_emit_exception.h"
- #include "jit_emit_function.h"
- #include "../../interpreter/wasm_runtime.h"
- #include "../jit_frontend.h"
- #if WASM_ENABLE_REF_TYPES != 0
- bool
- jit_compile_op_elem_drop(JitCompContext *cc, uint32 tbl_seg_idx)
- {
- JitReg module, tbl_segs;
- module = get_module_reg(cc->jit_frame);
- tbl_segs = jit_cc_new_reg_ptr(cc);
- GEN_INSN(LDPTR, tbl_segs, module,
- NEW_CONST(I32, offsetof(WASMModule, table_segments)));
- GEN_INSN(STI32, NEW_CONST(I32, true), tbl_segs,
- NEW_CONST(I32, tbl_seg_idx * sizeof(WASMTableSeg)
- + offsetof(WASMTableSeg, is_dropped)));
- return true;
- }
- bool
- jit_compile_op_table_get(JitCompContext *cc, uint32 tbl_idx)
- {
- JitReg elem_idx, tbl_sz, tbl_elems, elem_idx_long, offset, res;
- POP_I32(elem_idx);
- /* if (elem_idx >= tbl_sz) goto exception; */
- tbl_sz = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
- GEN_INSN(CMP, cc->cmp_reg, elem_idx, tbl_sz);
- if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, JIT_OP_BGEU,
- cc->cmp_reg, NULL))
- goto fail;
- elem_idx_long = jit_cc_new_reg_I64(cc);
- GEN_INSN(I32TOI64, elem_idx_long, elem_idx);
- offset = jit_cc_new_reg_I64(cc);
- GEN_INSN(MUL, offset, elem_idx_long, NEW_CONST(I64, sizeof(uint32)));
- res = jit_cc_new_reg_I32(cc);
- tbl_elems = get_table_elems_reg(cc->jit_frame, tbl_idx);
- GEN_INSN(LDI32, res, tbl_elems, offset);
- PUSH_I32(res);
- return true;
- fail:
- return false;
- }
- bool
- jit_compile_op_table_set(JitCompContext *cc, uint32 tbl_idx)
- {
- JitReg elem_idx, elem_val, tbl_sz, tbl_elems, elem_idx_long, offset;
- POP_I32(elem_val);
- POP_I32(elem_idx);
- /* if (elem_idx >= tbl_sz) goto exception; */
- tbl_sz = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
- GEN_INSN(CMP, cc->cmp_reg, elem_idx, tbl_sz);
- if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, JIT_OP_BGEU,
- cc->cmp_reg, NULL))
- goto fail;
- elem_idx_long = jit_cc_new_reg_I64(cc);
- GEN_INSN(I32TOI64, elem_idx_long, elem_idx);
- offset = jit_cc_new_reg_I64(cc);
- GEN_INSN(MUL, offset, elem_idx_long, NEW_CONST(I64, sizeof(uint32)));
- tbl_elems = get_table_elems_reg(cc->jit_frame, tbl_idx);
- GEN_INSN(STI32, elem_val, tbl_elems, offset);
- return true;
- fail:
- return false;
- }
- static int
- wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx,
- uint32 dst, uint32 len, uint32 src)
- {
- WASMTableInstance *tbl;
- uint32 tbl_sz;
- WASMTableSeg *elem;
- uint32 elem_len;
- tbl = inst->tables[tbl_idx];
- tbl_sz = tbl->cur_size;
- if (dst > tbl_sz || tbl_sz - dst < len)
- goto out_of_bounds;
- elem = inst->module->table_segments + elem_idx;
- elem_len = elem->function_count;
- if (src > elem_len || elem_len - src < len)
- goto out_of_bounds;
- bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems)
- + dst * sizeof(uint32),
- (uint32)((tbl_sz - dst) * sizeof(uint32)),
- elem->func_indexes + src, (uint32)(len * sizeof(uint32)));
- return 0;
- out_of_bounds:
- wasm_set_exception(inst, "out of bounds table access");
- return -1;
- }
- bool
- jit_compile_op_table_init(JitCompContext *cc, uint32 tbl_idx,
- uint32 tbl_seg_idx)
- {
- JitReg len, src, dst, res;
- JitReg args[6] = { 0 };
- POP_I32(len);
- POP_I32(src);
- POP_I32(dst);
- res = jit_cc_new_reg_I32(cc);
- args[0] = get_module_inst_reg(cc->jit_frame);
- args[1] = NEW_CONST(I32, tbl_idx);
- args[2] = NEW_CONST(I32, tbl_seg_idx);
- args[3] = dst;
- args[4] = len;
- args[5] = src;
- if (!jit_emit_callnative(cc, wasm_init_table, res, args,
- sizeof(args) / sizeof(args[0])))
- goto fail;
- GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
- if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
- NULL))
- goto fail;
- return true;
- fail:
- return false;
- }
- static int
- wasm_copy_table(WASMModuleInstance *inst, uint32 src_tbl_idx,
- uint32 dst_tbl_idx, uint32 dst_offset, uint32 len,
- uint32 src_offset)
- {
- WASMTableInstance *src_tbl, *dst_tbl;
- uint32 src_tbl_sz, dst_tbl_sz;
- src_tbl = inst->tables[src_tbl_idx];
- src_tbl_sz = src_tbl->cur_size;
- if (src_offset > src_tbl_sz || src_tbl_sz - src_offset < len)
- goto out_of_bounds;
- dst_tbl = inst->tables[dst_tbl_idx];
- dst_tbl_sz = dst_tbl->cur_size;
- if (dst_offset > dst_tbl_sz || dst_tbl_sz - dst_offset < len)
- goto out_of_bounds;
- bh_memmove_s((uint8 *)dst_tbl + offsetof(WASMTableInstance, elems)
- + dst_offset * sizeof(uint32),
- (uint32)((dst_tbl_sz - dst_offset) * sizeof(uint32)),
- (uint8 *)src_tbl + offsetof(WASMTableInstance, elems)
- + src_offset * sizeof(uint32),
- (uint32)(len * sizeof(uint32)));
- return 0;
- out_of_bounds:
- wasm_set_exception(inst, "out of bounds table access");
- return -1;
- }
- bool
- jit_compile_op_table_copy(JitCompContext *cc, uint32 src_tbl_idx,
- uint32 dst_tbl_idx)
- {
- JitReg len, src, dst, res;
- JitReg args[6] = { 0 };
- POP_I32(len);
- POP_I32(src);
- POP_I32(dst);
- res = jit_cc_new_reg_I32(cc);
- args[0] = get_module_inst_reg(cc->jit_frame);
- args[1] = NEW_CONST(I32, src_tbl_idx);
- args[2] = NEW_CONST(I32, dst_tbl_idx);
- args[3] = dst;
- args[4] = len;
- args[5] = src;
- if (!jit_emit_callnative(cc, wasm_copy_table, res, args,
- sizeof(args) / sizeof(args[0])))
- goto fail;
- GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
- if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
- NULL))
- goto fail;
- return true;
- fail:
- return false;
- }
- bool
- jit_compile_op_table_size(JitCompContext *cc, uint32 tbl_idx)
- {
- JitReg res;
- res = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
- PUSH_I32(res);
- return true;
- fail:
- return false;
- }
- bool
- jit_compile_op_table_grow(JitCompContext *cc, uint32 tbl_idx)
- {
- JitReg tbl_sz, n, val, enlarge_ret, res;
- JitReg args[4] = { 0 };
- POP_I32(n);
- POP_I32(val);
- tbl_sz = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
- enlarge_ret = jit_cc_new_reg_I32(cc);
- args[0] = get_module_inst_reg(cc->jit_frame);
- args[1] = NEW_CONST(I32, tbl_idx);
- args[2] = n;
- args[3] = val;
- if (!jit_emit_callnative(cc, wasm_enlarge_table, enlarge_ret, args,
- sizeof(args) / sizeof(args[0])))
- goto fail;
- /* Convert bool to uint32 */
- GEN_INSN(AND, enlarge_ret, enlarge_ret, NEW_CONST(I32, 0xFF));
- res = jit_cc_new_reg_I32(cc);
- GEN_INSN(CMP, cc->cmp_reg, enlarge_ret, NEW_CONST(I32, 1));
- GEN_INSN(SELECTEQ, res, cc->cmp_reg, tbl_sz, NEW_CONST(I32, -1));
- PUSH_I32(res);
- /* Ensure a refresh in next get memory related registers */
- clear_table_regs(cc->jit_frame);
- return true;
- fail:
- return false;
- }
- static int
- wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst,
- uint32 val, uint32 len)
- {
- WASMTableInstance *tbl;
- uint32 tbl_sz;
- tbl = inst->tables[tbl_idx];
- tbl_sz = tbl->cur_size;
- if (dst > tbl_sz || tbl_sz - dst < len)
- goto out_of_bounds;
- for (; len != 0; dst++, len--) {
- tbl->elems[dst] = val;
- }
- return 0;
- out_of_bounds:
- wasm_set_exception(inst, "out of bounds table access");
- return -1;
- }
- bool
- jit_compile_op_table_fill(JitCompContext *cc, uint32 tbl_idx)
- {
- JitReg len, val, dst, res;
- JitReg args[5] = { 0 };
- POP_I32(len);
- POP_I32(val);
- POP_I32(dst);
- res = jit_cc_new_reg_I32(cc);
- args[0] = get_module_inst_reg(cc->jit_frame);
- args[1] = NEW_CONST(I32, tbl_idx);
- args[2] = dst;
- args[3] = val;
- args[4] = len;
- if (!jit_emit_callnative(cc, wasm_fill_table, res, args,
- sizeof(args) / sizeof(args[0])))
- goto fail;
- GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
- if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
- NULL))
- goto fail;
- return true;
- fail:
- return false;
- }
- #endif
|