jit_emit_table.c 8.9 KB

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