jit_emit_table.c 8.4 KB

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