aot_emit_table.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "aot_emit_table.h"
  6. #include "aot_emit_exception.h"
  7. #include "../aot/aot_runtime.h"
  8. #if WASM_ENABLE_GC != 0
  9. #include "aot_emit_gc.h"
  10. #endif
  11. #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
  12. #if WASM_ENABLE_MEMORY64 != 0
  13. static bool
  14. zero_extend_u64(AOTCompContext *comp_ctx, LLVMValueRef *value, const char *name)
  15. {
  16. if (comp_ctx->pointer_size == sizeof(uint64)) {
  17. /* zero extend to uint64 if the target is 64-bit */
  18. *value = LLVMBuildZExt(comp_ctx->builder, *value, I64_TYPE, name);
  19. if (!*value) {
  20. aot_set_last_error("llvm build zero extend failed.");
  21. return false;
  22. }
  23. }
  24. return true;
  25. }
  26. #endif
  27. /* check whether a table64 elem idx is greater than UINT32_MAX, if so, throw
  28. * exception, otherwise trunc it to uint32 */
  29. static bool
  30. check_tbl_elem_idx_and_trunc(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  31. LLVMValueRef *elem_idx, uint32 tbl_idx)
  32. {
  33. #if WASM_ENABLE_MEMORY64 != 0
  34. LLVMValueRef u32_max, u32_cmp_result;
  35. LLVMBasicBlockRef check_elem_idx_succ;
  36. if (!IS_TABLE64(tbl_idx)) {
  37. return true;
  38. }
  39. /* Check if elem index >= UINT32_MAX */
  40. if (!(u32_max = I64_CONST(UINT32_MAX))) {
  41. aot_set_last_error("llvm build const failed");
  42. goto fail;
  43. }
  44. if (!(u32_cmp_result =
  45. LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, *elem_idx, u32_max,
  46. "cmp_elem_idx_u32_max"))) {
  47. aot_set_last_error("llvm build icmp failed.");
  48. goto fail;
  49. }
  50. if (!(*elem_idx = LLVMBuildTrunc(comp_ctx->builder, *elem_idx, I32_TYPE,
  51. "elem_idx_i32"))) {
  52. aot_set_last_error("llvm build trunc failed.");
  53. goto fail;
  54. }
  55. /* Throw exception if elem index >= UINT32_MAX*/
  56. if (!(check_elem_idx_succ = LLVMAppendBasicBlockInContext(
  57. comp_ctx->context, func_ctx->func, "check_elem_idx_succ"))) {
  58. aot_set_last_error("llvm add basic block failed.");
  59. goto fail;
  60. }
  61. LLVMMoveBasicBlockAfter(check_elem_idx_succ,
  62. LLVMGetInsertBlock(comp_ctx->builder));
  63. if (!(aot_emit_exception(comp_ctx, func_ctx,
  64. EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, true,
  65. u32_cmp_result, check_elem_idx_succ)))
  66. goto fail;
  67. return true;
  68. fail:
  69. return false;
  70. #else
  71. return true;
  72. #endif
  73. }
  74. #endif /* WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC !=0 */
  75. uint64
  76. get_tbl_inst_offset(const AOTCompContext *comp_ctx,
  77. const AOTFuncContext *func_ctx, uint32 tbl_idx)
  78. {
  79. uint64 offset = 0, i = 0;
  80. AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables;
  81. AOTTable *tbls = comp_ctx->comp_data->tables;
  82. offset =
  83. offsetof(AOTModuleInstance, global_table_data.bytes)
  84. + (uint64)comp_ctx->comp_data->memory_count * sizeof(AOTMemoryInstance)
  85. /* Get global data size according to target info */
  86. + (comp_ctx->pointer_size == sizeof(uint64)
  87. ? comp_ctx->comp_data->global_data_size_64bit
  88. : comp_ctx->comp_data->global_data_size_32bit);
  89. while (i < tbl_idx && i < comp_ctx->comp_data->import_table_count) {
  90. offset += offsetof(AOTTableInstance, elems);
  91. /* avoid loading from current AOTTableInstance */
  92. offset +=
  93. (uint64)comp_ctx->pointer_size
  94. * aot_get_imp_tbl_data_slots(imp_tbls + i, comp_ctx->is_jit_mode);
  95. ++i;
  96. }
  97. if (i == tbl_idx) {
  98. return offset;
  99. }
  100. tbl_idx -= comp_ctx->comp_data->import_table_count;
  101. i -= comp_ctx->comp_data->import_table_count;
  102. while (i < tbl_idx && i < comp_ctx->comp_data->table_count) {
  103. offset += offsetof(AOTTableInstance, elems);
  104. /* avoid loading from current AOTTableInstance */
  105. offset += (uint64)comp_ctx->pointer_size
  106. * aot_get_tbl_data_slots(tbls + i, comp_ctx->is_jit_mode);
  107. ++i;
  108. }
  109. return offset;
  110. }
  111. uint32
  112. get_module_inst_extra_offset(AOTCompContext *comp_ctx)
  113. {
  114. const AOTCompData *comp_data = comp_ctx->comp_data;
  115. uint32 table_count = comp_data->import_table_count + comp_data->table_count;
  116. uint64 offset = get_tbl_inst_offset(comp_ctx, NULL, table_count);
  117. uint32 offset_32 = (uint32)offset;
  118. bh_assert(offset <= UINT32_MAX);
  119. offset_32 = align_uint(offset_32, 8);
  120. return offset_32;
  121. }
  122. #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
  123. LLVMValueRef
  124. aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  125. uint32 tbl_idx)
  126. {
  127. LLVMValueRef offset, tbl_inst;
  128. if (!(offset =
  129. I64_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)))) {
  130. HANDLE_FAILURE("LLVMConstInt");
  131. goto fail;
  132. }
  133. if (!(tbl_inst = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
  134. func_ctx->aot_inst, &offset, 1,
  135. "tbl_inst"))) {
  136. HANDLE_FAILURE("LLVMBuildInBoundsGEP");
  137. goto fail;
  138. }
  139. return tbl_inst;
  140. fail:
  141. return NULL;
  142. }
  143. bool
  144. aot_compile_op_elem_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  145. uint32 tbl_seg_idx)
  146. {
  147. LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
  148. LLVMValueRef param_values[2], ret_value, func, value;
  149. /* void aot_drop_table_seg(AOTModuleInstance *, uint32 ) */
  150. param_types[0] = INT8_PTR_TYPE;
  151. param_types[1] = I32_TYPE;
  152. ret_type = VOID_TYPE;
  153. if (comp_ctx->is_jit_mode)
  154. GET_AOT_FUNCTION(llvm_jit_drop_table_seg, 2);
  155. else
  156. GET_AOT_FUNCTION(aot_drop_table_seg, 2);
  157. param_values[0] = func_ctx->aot_inst;
  158. if (!(param_values[1] = I32_CONST(tbl_seg_idx))) {
  159. HANDLE_FAILURE("LLVMConstInt");
  160. goto fail;
  161. }
  162. /* "" means return void */
  163. if (!(ret_value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
  164. param_values, 2, ""))) {
  165. HANDLE_FAILURE("LLVMBuildCall");
  166. goto fail;
  167. }
  168. return true;
  169. fail:
  170. return false;
  171. }
  172. static bool
  173. aot_check_table_access(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  174. uint32 tbl_idx, LLVMValueRef elem_idx)
  175. {
  176. LLVMValueRef offset, tbl_sz, cmp_elem_idx;
  177. LLVMBasicBlockRef check_elem_idx_succ;
  178. /* get the cur size of the table instance */
  179. if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
  180. + offsetof(AOTTableInstance, cur_size)))) {
  181. HANDLE_FAILURE("LLVMConstInt");
  182. goto fail;
  183. }
  184. if (!(tbl_sz = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
  185. func_ctx->aot_inst, &offset, 1,
  186. "cur_size_i8p"))) {
  187. HANDLE_FAILURE("LLVMBuildInBoundsGEP");
  188. goto fail;
  189. }
  190. if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
  191. "cur_size_i32p"))) {
  192. HANDLE_FAILURE("LLVMBuildBitCast");
  193. goto fail;
  194. }
  195. if (!(tbl_sz = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, tbl_sz,
  196. "cur_size"))) {
  197. HANDLE_FAILURE("LLVMBuildLoad");
  198. goto fail;
  199. }
  200. if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &elem_idx, tbl_idx)) {
  201. goto fail;
  202. }
  203. /* Check if (uint32)elem index >= table size */
  204. if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, elem_idx,
  205. tbl_sz, "cmp_elem_idx"))) {
  206. aot_set_last_error("llvm build icmp failed.");
  207. goto fail;
  208. }
  209. /* Throw exception if elem index >= table size */
  210. if (!(check_elem_idx_succ = LLVMAppendBasicBlockInContext(
  211. comp_ctx->context, func_ctx->func, "check_elem_idx_succ"))) {
  212. aot_set_last_error("llvm add basic block failed.");
  213. goto fail;
  214. }
  215. LLVMMoveBasicBlockAfter(check_elem_idx_succ,
  216. LLVMGetInsertBlock(comp_ctx->builder));
  217. if (!(aot_emit_exception(comp_ctx, func_ctx,
  218. EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, true,
  219. cmp_elem_idx, check_elem_idx_succ)))
  220. goto fail;
  221. return true;
  222. fail:
  223. return false;
  224. }
  225. bool
  226. aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  227. uint32 tbl_idx)
  228. {
  229. LLVMValueRef elem_idx, offset, func_idx;
  230. LLVMValueRef table_elem_base, table_elem_addr, table_elem;
  231. POP_TBL_ELEM_IDX(elem_idx);
  232. if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
  233. goto fail;
  234. }
  235. /* load data as i32* */
  236. if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
  237. + offsetof(AOTTableInstance, elems)))) {
  238. HANDLE_FAILURE("LLVMConstInt");
  239. goto fail;
  240. }
  241. if (!(table_elem_base = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
  242. func_ctx->aot_inst, &offset,
  243. 1, "table_elem_base_i8p"))) {
  244. aot_set_last_error("llvm build add failed.");
  245. goto fail;
  246. }
  247. /* Load function object reference or function index */
  248. if (comp_ctx->enable_gc) {
  249. if (!(table_elem_base =
  250. LLVMBuildBitCast(comp_ctx->builder, table_elem_base,
  251. GC_REF_PTR_TYPE, "table_elem_base"))) {
  252. HANDLE_FAILURE("LLVMBuildBitCast");
  253. goto fail;
  254. }
  255. if (!(table_elem_addr = LLVMBuildInBoundsGEP2(
  256. comp_ctx->builder, GC_REF_TYPE, table_elem_base, &elem_idx, 1,
  257. "table_elem_addr"))) {
  258. HANDLE_FAILURE("LLVMBuildNUWAdd");
  259. goto fail;
  260. }
  261. if (!(table_elem = LLVMBuildLoad2(comp_ctx->builder, GC_REF_TYPE,
  262. table_elem_addr, "table_elem"))) {
  263. HANDLE_FAILURE("LLVMBuildLoad");
  264. goto fail;
  265. }
  266. PUSH_GC_REF(table_elem);
  267. }
  268. else {
  269. if (!(table_elem_base =
  270. LLVMBuildBitCast(comp_ctx->builder, table_elem_base,
  271. INTPTR_T_PTR_TYPE, "table_elem_base"))) {
  272. HANDLE_FAILURE("LLVMBuildBitCast");
  273. goto fail;
  274. }
  275. if (!(table_elem_addr = LLVMBuildInBoundsGEP2(
  276. comp_ctx->builder, INTPTR_T_TYPE, table_elem_base, &elem_idx,
  277. 1, "table_elem_addr"))) {
  278. HANDLE_FAILURE("LLVMBuildNUWAdd");
  279. goto fail;
  280. }
  281. if (!(table_elem = LLVMBuildLoad2(comp_ctx->builder, INTPTR_T_TYPE,
  282. table_elem_addr, "table_elem"))) {
  283. HANDLE_FAILURE("LLVMBuildLoad");
  284. goto fail;
  285. }
  286. if (!(func_idx = LLVMBuildIntCast2(comp_ctx->builder, table_elem,
  287. I32_TYPE, true, "func_idx"))) {
  288. HANDLE_FAILURE("LLVMBuildIntCast");
  289. goto fail;
  290. }
  291. PUSH_I32(func_idx);
  292. }
  293. return true;
  294. fail:
  295. return false;
  296. }
  297. bool
  298. aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  299. uint32 tbl_idx)
  300. {
  301. LLVMValueRef val = NULL, elem_idx, offset, table_elem_base, table_elem_addr;
  302. if (comp_ctx->enable_gc)
  303. POP_GC_REF(val);
  304. else {
  305. POP_I32(val);
  306. if (!(val = LLVMBuildIntCast2(comp_ctx->builder, val, INTPTR_T_TYPE,
  307. true, "val_intptr_t"))) {
  308. HANDLE_FAILURE("LLVMBuildBitCast");
  309. goto fail;
  310. }
  311. }
  312. POP_TBL_ELEM_IDX(elem_idx);
  313. if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
  314. goto fail;
  315. }
  316. /* load data as gc_obj_ref* or i32* */
  317. if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
  318. + offsetof(AOTTableInstance, elems)))) {
  319. HANDLE_FAILURE("LLVMConstInt");
  320. goto fail;
  321. }
  322. if (!(table_elem_base = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
  323. func_ctx->aot_inst, &offset,
  324. 1, "table_elem_base_i8p"))) {
  325. HANDLE_FAILURE("LLVMBuildInBoundsGEP");
  326. goto fail;
  327. }
  328. if (comp_ctx->enable_gc) {
  329. if (!(table_elem_base =
  330. LLVMBuildBitCast(comp_ctx->builder, table_elem_base,
  331. GC_REF_PTR_TYPE, "table_elem_base"))) {
  332. HANDLE_FAILURE("LLVMBuildBitCast");
  333. goto fail;
  334. }
  335. if (!(table_elem_addr = LLVMBuildInBoundsGEP2(
  336. comp_ctx->builder, GC_REF_TYPE, table_elem_base, &elem_idx, 1,
  337. "table_elem_addr"))) {
  338. HANDLE_FAILURE("LLVMBuildInBoundsGEP");
  339. goto fail;
  340. }
  341. }
  342. else {
  343. if (!(table_elem_base =
  344. LLVMBuildBitCast(comp_ctx->builder, table_elem_base,
  345. INTPTR_T_PTR_TYPE, "table_elem_base"))) {
  346. HANDLE_FAILURE("LLVMBuildBitCast");
  347. goto fail;
  348. }
  349. if (!(table_elem_addr = LLVMBuildInBoundsGEP2(
  350. comp_ctx->builder, INTPTR_T_TYPE, table_elem_base, &elem_idx,
  351. 1, "table_elem_addr"))) {
  352. HANDLE_FAILURE("LLVMBuildInBoundsGEP");
  353. goto fail;
  354. }
  355. }
  356. if (!(LLVMBuildStore(comp_ctx->builder, val, table_elem_addr))) {
  357. HANDLE_FAILURE("LLVMBuildStore");
  358. goto fail;
  359. }
  360. return true;
  361. fail:
  362. return false;
  363. }
  364. bool
  365. aot_compile_op_table_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  366. uint32 tbl_idx, uint32 tbl_seg_idx)
  367. {
  368. LLVMValueRef func, param_values[6], value;
  369. LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
  370. param_types[0] = INT8_PTR_TYPE;
  371. param_types[1] = I32_TYPE;
  372. param_types[2] = I32_TYPE;
  373. param_types[3] = I32_TYPE;
  374. param_types[4] = I32_TYPE;
  375. param_types[5] = I32_TYPE;
  376. ret_type = VOID_TYPE;
  377. if (comp_ctx->is_jit_mode)
  378. GET_AOT_FUNCTION(llvm_jit_table_init, 6);
  379. else
  380. GET_AOT_FUNCTION(aot_table_init, 6);
  381. param_values[0] = func_ctx->aot_inst;
  382. if (!(param_values[1] = I32_CONST(tbl_idx))) {
  383. HANDLE_FAILURE("LLVMConstInt");
  384. goto fail;
  385. }
  386. if (!(param_values[2] = I32_CONST(tbl_seg_idx))) {
  387. HANDLE_FAILURE("LLVMConstInt");
  388. goto fail;
  389. }
  390. /* n */
  391. POP_I32(param_values[3]);
  392. /* s */
  393. POP_I32(param_values[4]);
  394. /* d */
  395. POP_TBL_ELEM_IDX(param_values[5]);
  396. if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[5],
  397. tbl_idx)) {
  398. goto fail;
  399. }
  400. /* "" means return void */
  401. if (!(LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 6,
  402. ""))) {
  403. HANDLE_FAILURE("LLVMBuildCall");
  404. goto fail;
  405. }
  406. return true;
  407. fail:
  408. return false;
  409. }
  410. bool
  411. aot_compile_op_table_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  412. uint32 src_tbl_idx, uint32 dst_tbl_idx)
  413. {
  414. LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
  415. LLVMValueRef func, param_values[6], value;
  416. uint32 tbl_idx;
  417. param_types[0] = INT8_PTR_TYPE;
  418. param_types[1] = I32_TYPE;
  419. param_types[2] = I32_TYPE;
  420. param_types[3] = I32_TYPE;
  421. param_types[4] = I32_TYPE;
  422. param_types[5] = I32_TYPE;
  423. ret_type = VOID_TYPE;
  424. if (comp_ctx->is_jit_mode)
  425. GET_AOT_FUNCTION(llvm_jit_table_copy, 6);
  426. else
  427. GET_AOT_FUNCTION(aot_table_copy, 6);
  428. param_values[0] = func_ctx->aot_inst;
  429. if (!(param_values[1] = I32_CONST(src_tbl_idx))) {
  430. HANDLE_FAILURE("LLVMConstInt");
  431. goto fail;
  432. }
  433. if (!(param_values[2] = I32_CONST(dst_tbl_idx))) {
  434. HANDLE_FAILURE("LLVMConstInt");
  435. goto fail;
  436. }
  437. /* In table64, the length should be i32 type if any one of src/dst table
  438. * is i32 type, set the table index to the lesser-or-equal table when
  439. * popping length n */
  440. if (!(comp_ctx->comp_data->tables[src_tbl_idx].table_type.flags
  441. & TABLE64_FLAG))
  442. tbl_idx = src_tbl_idx;
  443. else
  444. tbl_idx = dst_tbl_idx;
  445. /* n */
  446. POP_TBL_ELEM_LEN(param_values[3]);
  447. if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[3],
  448. tbl_idx)) {
  449. goto fail;
  450. }
  451. /* s */
  452. tbl_idx = src_tbl_idx;
  453. POP_TBL_ELEM_IDX(param_values[4]);
  454. if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[4],
  455. tbl_idx)) {
  456. goto fail;
  457. }
  458. /* d */
  459. tbl_idx = dst_tbl_idx;
  460. POP_TBL_ELEM_IDX(param_values[5]);
  461. if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[5],
  462. tbl_idx)) {
  463. goto fail;
  464. }
  465. /* "" means return void */
  466. if (!(LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 6,
  467. ""))) {
  468. HANDLE_FAILURE("LLVMBuildCall");
  469. goto fail;
  470. }
  471. return true;
  472. fail:
  473. return false;
  474. }
  475. bool
  476. aot_compile_op_table_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  477. uint32 tbl_idx)
  478. {
  479. LLVMValueRef offset, tbl_sz;
  480. if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
  481. + offsetof(AOTTableInstance, cur_size)))) {
  482. HANDLE_FAILURE("LLVMConstInt");
  483. goto fail;
  484. }
  485. if (!(tbl_sz = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
  486. func_ctx->aot_inst, &offset, 1,
  487. "tbl_sz_ptr_i8"))) {
  488. HANDLE_FAILURE("LLVMBuildInBoundsGEP");
  489. goto fail;
  490. }
  491. if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
  492. "tbl_sz_ptr"))) {
  493. HANDLE_FAILURE("LLVMBuildBitCast");
  494. goto fail;
  495. }
  496. if (!(tbl_sz =
  497. LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, tbl_sz, "tbl_sz"))) {
  498. HANDLE_FAILURE("LLVMBuildLoad");
  499. goto fail;
  500. }
  501. #if WASM_ENABLE_MEMORY64 != 0
  502. if (IS_TABLE64(tbl_idx)) {
  503. if (!zero_extend_u64(comp_ctx, &tbl_sz, "length64")) {
  504. goto fail;
  505. }
  506. }
  507. #endif
  508. PUSH_TBL_ELEM_IDX(tbl_sz);
  509. return true;
  510. fail:
  511. return false;
  512. }
  513. bool
  514. aot_compile_op_table_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  515. uint32 tbl_idx)
  516. {
  517. LLVMTypeRef param_types[4], ret_type, func_type, func_ptr_type;
  518. LLVMValueRef func, param_values[4], ret, value;
  519. param_types[0] = INT8_PTR_TYPE;
  520. param_types[1] = I32_TYPE;
  521. param_types[2] = I32_TYPE;
  522. param_types[3] = INT8_PTR_TYPE;
  523. ret_type = I32_TYPE;
  524. if (comp_ctx->is_jit_mode)
  525. GET_AOT_FUNCTION(llvm_jit_table_grow, 4);
  526. else
  527. GET_AOT_FUNCTION(aot_table_grow, 4);
  528. param_values[0] = func_ctx->aot_inst;
  529. if (!(param_values[1] = I32_CONST(tbl_idx))) {
  530. HANDLE_FAILURE("LLVMConstInt");
  531. goto fail;
  532. }
  533. /* n */
  534. POP_TBL_ELEM_LEN(param_values[2]);
  535. if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[2],
  536. tbl_idx)) {
  537. goto fail;
  538. }
  539. /* v */
  540. if (comp_ctx->enable_gc) {
  541. POP_GC_REF(param_values[3]);
  542. if (!(param_values[3] =
  543. LLVMBuildBitCast(comp_ctx->builder, param_values[3],
  544. INT8_PTR_TYPE, "table_elem_i8p"))) {
  545. HANDLE_FAILURE("LLVMBuildBitCast");
  546. goto fail;
  547. }
  548. }
  549. else {
  550. POP_I32(param_values[3]);
  551. if (!(param_values[3] =
  552. LLVMBuildIntToPtr(comp_ctx->builder, param_values[3],
  553. INT8_PTR_TYPE, "table_elem_i8p"))) {
  554. HANDLE_FAILURE("LLVMBuildIntToPtr");
  555. goto fail;
  556. }
  557. }
  558. if (!(ret = LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values,
  559. 4, "table_grow"))) {
  560. HANDLE_FAILURE("LLVMBuildCall");
  561. goto fail;
  562. }
  563. #if WASM_ENABLE_MEMORY64 != 0
  564. if (IS_TABLE64(tbl_idx)) {
  565. if (!zero_extend_u64(comp_ctx, &ret, "table_size64")) {
  566. goto fail;
  567. }
  568. }
  569. #endif
  570. PUSH_TBL_ELEM_LEN(ret);
  571. return true;
  572. fail:
  573. return false;
  574. }
  575. bool
  576. aot_compile_op_table_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  577. uint32 tbl_idx)
  578. {
  579. LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type;
  580. LLVMValueRef func, param_values[5], value;
  581. param_types[0] = INT8_PTR_TYPE;
  582. param_types[1] = I32_TYPE;
  583. param_types[2] = I32_TYPE;
  584. param_types[3] = INT8_PTR_TYPE;
  585. param_types[4] = I32_TYPE;
  586. ret_type = VOID_TYPE;
  587. if (comp_ctx->is_jit_mode)
  588. GET_AOT_FUNCTION(llvm_jit_table_fill, 5);
  589. else
  590. GET_AOT_FUNCTION(aot_table_fill, 5);
  591. param_values[0] = func_ctx->aot_inst;
  592. if (!(param_values[1] = I32_CONST(tbl_idx))) {
  593. HANDLE_FAILURE("LLVMConstInt");
  594. goto fail;
  595. }
  596. /* n */
  597. POP_TBL_ELEM_LEN(param_values[2]);
  598. if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[2],
  599. tbl_idx)) {
  600. goto fail;
  601. }
  602. /* v */
  603. if (comp_ctx->enable_gc) {
  604. POP_GC_REF(param_values[3]);
  605. if (!(param_values[3] =
  606. LLVMBuildBitCast(comp_ctx->builder, param_values[3],
  607. INT8_PTR_TYPE, "table_elem_i8p"))) {
  608. HANDLE_FAILURE("LLVMBuildBitCast");
  609. goto fail;
  610. }
  611. }
  612. else {
  613. POP_I32(param_values[3]);
  614. if (!(param_values[3] =
  615. LLVMBuildIntToPtr(comp_ctx->builder, param_values[3],
  616. INT8_PTR_TYPE, "table_elem_i8p"))) {
  617. HANDLE_FAILURE("LLVMBuildIntToPtr");
  618. goto fail;
  619. }
  620. }
  621. /* i */
  622. POP_TBL_ELEM_IDX(param_values[4]);
  623. if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[4],
  624. tbl_idx)) {
  625. goto fail;
  626. }
  627. /* "" means return void */
  628. if (!(LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 5,
  629. ""))) {
  630. HANDLE_FAILURE("LLVMBuildCall");
  631. goto fail;
  632. }
  633. return true;
  634. fail:
  635. return false;
  636. }
  637. #endif /* WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC !=0 */