jit_emit_table.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "jit_emit_table.h"
  6. #include "jit_emit_exception.h"
  7. #include "jit_emit_function.h"
  8. #include "../../interpreter/wasm_runtime.h"
  9. #include "../jit_frontend.h"
  10. #if WASM_ENABLE_REF_TYPES != 0
  11. static void
  12. wasm_elem_drop(WASMModuleInstance *inst, uint32 tbl_seg_idx)
  13. {
  14. bh_bitmap_set_bit(inst->e->common.elem_dropped, tbl_seg_idx);
  15. }
  16. bool
  17. jit_compile_op_elem_drop(JitCompContext *cc, uint32 tbl_seg_idx)
  18. {
  19. JitReg args[2] = { 0 };
  20. args[0] = get_module_inst_reg(cc->jit_frame);
  21. args[1] = NEW_CONST(I32, tbl_seg_idx);
  22. return jit_emit_callnative(cc, wasm_elem_drop, 0, args,
  23. sizeof(args) / sizeof(args[0]));
  24. }
  25. bool
  26. jit_compile_op_table_get(JitCompContext *cc, uint32 tbl_idx)
  27. {
  28. JitReg elem_idx, tbl_sz, tbl_elems, elem_idx_long, offset, res;
  29. POP_I32(elem_idx);
  30. /* if (elem_idx >= tbl_sz) goto exception; */
  31. tbl_sz = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
  32. GEN_INSN(CMP, cc->cmp_reg, elem_idx, tbl_sz);
  33. if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, JIT_OP_BGEU,
  34. cc->cmp_reg, NULL))
  35. goto fail;
  36. elem_idx_long = jit_cc_new_reg_I64(cc);
  37. GEN_INSN(I32TOI64, elem_idx_long, elem_idx);
  38. offset = jit_cc_new_reg_I64(cc);
  39. GEN_INSN(MUL, offset, elem_idx_long, NEW_CONST(I64, sizeof(uint32)));
  40. res = jit_cc_new_reg_I32(cc);
  41. tbl_elems = get_table_elems_reg(cc->jit_frame, tbl_idx);
  42. GEN_INSN(LDI32, res, tbl_elems, offset);
  43. PUSH_I32(res);
  44. return true;
  45. fail:
  46. return false;
  47. }
  48. bool
  49. jit_compile_op_table_set(JitCompContext *cc, uint32 tbl_idx)
  50. {
  51. JitReg elem_idx, elem_val, tbl_sz, tbl_elems, elem_idx_long, offset;
  52. POP_I32(elem_val);
  53. POP_I32(elem_idx);
  54. /* if (elem_idx >= tbl_sz) goto exception; */
  55. tbl_sz = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
  56. GEN_INSN(CMP, cc->cmp_reg, elem_idx, tbl_sz);
  57. if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, JIT_OP_BGEU,
  58. cc->cmp_reg, NULL))
  59. goto fail;
  60. elem_idx_long = jit_cc_new_reg_I64(cc);
  61. GEN_INSN(I32TOI64, elem_idx_long, elem_idx);
  62. offset = jit_cc_new_reg_I64(cc);
  63. GEN_INSN(MUL, offset, elem_idx_long, NEW_CONST(I64, sizeof(uint32)));
  64. tbl_elems = get_table_elems_reg(cc->jit_frame, tbl_idx);
  65. GEN_INSN(STI32, elem_val, tbl_elems, offset);
  66. return true;
  67. fail:
  68. return false;
  69. }
  70. static int
  71. wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 seg_idx,
  72. uint32 dst_offset, uint32 len, uint32 src_offset)
  73. {
  74. WASMTableInstance *tbl;
  75. uint32 tbl_sz;
  76. WASMTableSeg *tbl_seg = inst->module->table_segments + seg_idx;
  77. uint32 *tbl_seg_elems = NULL, tbl_seg_len = 0;
  78. if (!bh_bitmap_get_bit(inst->e->common.elem_dropped, seg_idx)) {
  79. /* table segment isn't dropped */
  80. tbl_seg_elems = tbl_seg->func_indexes;
  81. tbl_seg_len = tbl_seg->function_count;
  82. }
  83. if (offset_len_out_of_bounds(src_offset, len, tbl_seg_len))
  84. goto out_of_bounds;
  85. tbl = inst->tables[tbl_idx];
  86. tbl_sz = tbl->cur_size;
  87. if (offset_len_out_of_bounds(dst_offset, len, tbl_sz))
  88. goto out_of_bounds;
  89. if (!len)
  90. return 0;
  91. bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems)
  92. + dst_offset * sizeof(uint32),
  93. (uint32)((tbl_sz - dst_offset) * sizeof(uint32)),
  94. tbl_seg_elems + src_offset, (uint32)(len * sizeof(uint32)));
  95. return 0;
  96. out_of_bounds:
  97. wasm_set_exception(inst, "out of bounds table access");
  98. return -1;
  99. }
  100. bool
  101. jit_compile_op_table_init(JitCompContext *cc, uint32 tbl_idx,
  102. uint32 tbl_seg_idx)
  103. {
  104. JitReg len, src, dst, res;
  105. JitReg args[6] = { 0 };
  106. POP_I32(len);
  107. POP_I32(src);
  108. POP_I32(dst);
  109. res = jit_cc_new_reg_I32(cc);
  110. args[0] = get_module_inst_reg(cc->jit_frame);
  111. args[1] = NEW_CONST(I32, tbl_idx);
  112. args[2] = NEW_CONST(I32, tbl_seg_idx);
  113. args[3] = dst;
  114. args[4] = len;
  115. args[5] = src;
  116. if (!jit_emit_callnative(cc, wasm_init_table, res, args,
  117. sizeof(args) / sizeof(args[0])))
  118. goto fail;
  119. GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
  120. if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
  121. NULL))
  122. goto fail;
  123. return true;
  124. fail:
  125. return false;
  126. }
  127. static int
  128. wasm_copy_table(WASMModuleInstance *inst, uint32 src_tbl_idx,
  129. uint32 dst_tbl_idx, uint32 dst_offset, uint32 len,
  130. uint32 src_offset)
  131. {
  132. WASMTableInstance *src_tbl, *dst_tbl;
  133. uint32 src_tbl_sz, dst_tbl_sz;
  134. dst_tbl = inst->tables[dst_tbl_idx];
  135. dst_tbl_sz = dst_tbl->cur_size;
  136. if (offset_len_out_of_bounds(dst_offset, len, dst_tbl_sz))
  137. goto out_of_bounds;
  138. src_tbl = inst->tables[src_tbl_idx];
  139. src_tbl_sz = src_tbl->cur_size;
  140. if (offset_len_out_of_bounds(src_offset, len, src_tbl_sz))
  141. goto out_of_bounds;
  142. bh_memmove_s((uint8 *)dst_tbl + offsetof(WASMTableInstance, elems)
  143. + dst_offset * sizeof(uint32),
  144. (uint32)((dst_tbl_sz - dst_offset) * sizeof(uint32)),
  145. (uint8 *)src_tbl + offsetof(WASMTableInstance, elems)
  146. + src_offset * sizeof(uint32),
  147. (uint32)(len * sizeof(uint32)));
  148. return 0;
  149. out_of_bounds:
  150. wasm_set_exception(inst, "out of bounds table access");
  151. return -1;
  152. }
  153. bool
  154. jit_compile_op_table_copy(JitCompContext *cc, uint32 src_tbl_idx,
  155. uint32 dst_tbl_idx)
  156. {
  157. JitReg len, src, dst, res;
  158. JitReg args[6] = { 0 };
  159. POP_I32(len);
  160. POP_I32(src);
  161. POP_I32(dst);
  162. res = jit_cc_new_reg_I32(cc);
  163. args[0] = get_module_inst_reg(cc->jit_frame);
  164. args[1] = NEW_CONST(I32, src_tbl_idx);
  165. args[2] = NEW_CONST(I32, dst_tbl_idx);
  166. args[3] = dst;
  167. args[4] = len;
  168. args[5] = src;
  169. if (!jit_emit_callnative(cc, wasm_copy_table, res, args,
  170. sizeof(args) / sizeof(args[0])))
  171. goto fail;
  172. GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
  173. if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
  174. NULL))
  175. goto fail;
  176. return true;
  177. fail:
  178. return false;
  179. }
  180. bool
  181. jit_compile_op_table_size(JitCompContext *cc, uint32 tbl_idx)
  182. {
  183. JitReg res;
  184. res = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
  185. PUSH_I32(res);
  186. return true;
  187. fail:
  188. return false;
  189. }
  190. bool
  191. jit_compile_op_table_grow(JitCompContext *cc, uint32 tbl_idx)
  192. {
  193. JitReg tbl_sz, n, val, enlarge_ret, res;
  194. JitReg args[4] = { 0 };
  195. POP_I32(n);
  196. POP_I32(val);
  197. tbl_sz = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
  198. enlarge_ret = jit_cc_new_reg_I32(cc);
  199. args[0] = get_module_inst_reg(cc->jit_frame);
  200. args[1] = NEW_CONST(I32, tbl_idx);
  201. args[2] = n;
  202. args[3] = val;
  203. if (!jit_emit_callnative(cc, wasm_enlarge_table, enlarge_ret, args,
  204. sizeof(args) / sizeof(args[0])))
  205. goto fail;
  206. /* Convert bool to uint32 */
  207. GEN_INSN(AND, enlarge_ret, enlarge_ret, NEW_CONST(I32, 0xFF));
  208. res = jit_cc_new_reg_I32(cc);
  209. GEN_INSN(CMP, cc->cmp_reg, enlarge_ret, NEW_CONST(I32, 1));
  210. GEN_INSN(SELECTEQ, res, cc->cmp_reg, tbl_sz, NEW_CONST(I32, -1));
  211. PUSH_I32(res);
  212. /* Ensure a refresh in next get memory related registers */
  213. clear_table_regs(cc->jit_frame);
  214. return true;
  215. fail:
  216. return false;
  217. }
  218. static int
  219. wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst_offset,
  220. uint32 val, uint32 len)
  221. {
  222. WASMTableInstance *tbl;
  223. uint32 tbl_sz;
  224. tbl = inst->tables[tbl_idx];
  225. tbl_sz = tbl->cur_size;
  226. if (offset_len_out_of_bounds(dst_offset, len, tbl_sz))
  227. goto out_of_bounds;
  228. for (; len != 0; dst_offset++, len--) {
  229. tbl->elems[dst_offset] = val;
  230. }
  231. return 0;
  232. out_of_bounds:
  233. wasm_set_exception(inst, "out of bounds table access");
  234. return -1;
  235. }
  236. bool
  237. jit_compile_op_table_fill(JitCompContext *cc, uint32 tbl_idx)
  238. {
  239. JitReg len, val, dst, res;
  240. JitReg args[5] = { 0 };
  241. POP_I32(len);
  242. POP_I32(val);
  243. POP_I32(dst);
  244. res = jit_cc_new_reg_I32(cc);
  245. args[0] = get_module_inst_reg(cc->jit_frame);
  246. args[1] = NEW_CONST(I32, tbl_idx);
  247. args[2] = dst;
  248. args[3] = val;
  249. args[4] = len;
  250. if (!jit_emit_callnative(cc, wasm_fill_table, res, args,
  251. sizeof(args) / sizeof(args[0])))
  252. goto fail;
  253. GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
  254. if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
  255. NULL))
  256. goto fail;
  257. return true;
  258. fail:
  259. return false;
  260. }
  261. #endif