aot_emit_table.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  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. uint64
  12. get_tbl_inst_offset(const AOTCompContext *comp_ctx,
  13. const AOTFuncContext *func_ctx, uint32 tbl_idx)
  14. {
  15. uint64 offset = 0, i = 0;
  16. AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables;
  17. AOTTable *tbls = comp_ctx->comp_data->tables;
  18. offset =
  19. offsetof(AOTModuleInstance, global_table_data.bytes)
  20. + (uint64)comp_ctx->comp_data->memory_count * sizeof(AOTMemoryInstance)
  21. /* Get global data size according to target info */
  22. + (comp_ctx->pointer_size == sizeof(uint64)
  23. ? comp_ctx->comp_data->global_data_size_64bit
  24. : comp_ctx->comp_data->global_data_size_32bit);
  25. while (i < tbl_idx && i < comp_ctx->comp_data->import_table_count) {
  26. offset += offsetof(AOTTableInstance, elems);
  27. /* avoid loading from current AOTTableInstance */
  28. offset +=
  29. (uint64)comp_ctx->pointer_size
  30. * aot_get_imp_tbl_data_slots(imp_tbls + i, comp_ctx->is_jit_mode);
  31. ++i;
  32. }
  33. if (i == tbl_idx) {
  34. return offset;
  35. }
  36. tbl_idx -= comp_ctx->comp_data->import_table_count;
  37. i -= comp_ctx->comp_data->import_table_count;
  38. while (i < tbl_idx && i < comp_ctx->comp_data->table_count) {
  39. offset += offsetof(AOTTableInstance, elems);
  40. /* avoid loading from current AOTTableInstance */
  41. offset += (uint64)comp_ctx->pointer_size
  42. * aot_get_tbl_data_slots(tbls + i, comp_ctx->is_jit_mode);
  43. ++i;
  44. }
  45. return offset;
  46. }
  47. uint32
  48. get_module_inst_extra_offset(AOTCompContext *comp_ctx)
  49. {
  50. const AOTCompData *comp_data = comp_ctx->comp_data;
  51. uint32 table_count = comp_data->import_table_count + comp_data->table_count;
  52. uint64 offset = get_tbl_inst_offset(comp_ctx, NULL, table_count);
  53. uint32 offset_32 = (uint32)offset;
  54. bh_assert(offset <= UINT32_MAX);
  55. offset_32 = align_uint(offset_32, 8);
  56. return offset_32;
  57. }
  58. #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
  59. LLVMValueRef
  60. aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  61. uint32 tbl_idx)
  62. {
  63. LLVMValueRef offset, tbl_inst;
  64. if (!(offset =
  65. I64_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)))) {
  66. HANDLE_FAILURE("LLVMConstInt");
  67. goto fail;
  68. }
  69. if (!(tbl_inst = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
  70. func_ctx->aot_inst, &offset, 1,
  71. "tbl_inst"))) {
  72. HANDLE_FAILURE("LLVMBuildInBoundsGEP");
  73. goto fail;
  74. }
  75. return tbl_inst;
  76. fail:
  77. return NULL;
  78. }
  79. bool
  80. aot_compile_op_elem_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  81. uint32 tbl_seg_idx)
  82. {
  83. LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
  84. LLVMValueRef param_values[2], ret_value, func, value;
  85. /* void aot_drop_table_seg(AOTModuleInstance *, uint32 ) */
  86. param_types[0] = INT8_PTR_TYPE;
  87. param_types[1] = I32_TYPE;
  88. ret_type = VOID_TYPE;
  89. if (comp_ctx->is_jit_mode)
  90. GET_AOT_FUNCTION(llvm_jit_drop_table_seg, 2);
  91. else
  92. GET_AOT_FUNCTION(aot_drop_table_seg, 2);
  93. param_values[0] = func_ctx->aot_inst;
  94. if (!(param_values[1] = I32_CONST(tbl_seg_idx))) {
  95. HANDLE_FAILURE("LLVMConstInt");
  96. goto fail;
  97. }
  98. /* "" means return void */
  99. if (!(ret_value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
  100. param_values, 2, ""))) {
  101. HANDLE_FAILURE("LLVMBuildCall");
  102. goto fail;
  103. }
  104. return true;
  105. fail:
  106. return false;
  107. }
  108. static bool
  109. aot_check_table_access(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  110. uint32 tbl_idx, LLVMValueRef elem_idx)
  111. {
  112. LLVMValueRef offset, tbl_sz, cmp_elem_idx;
  113. LLVMBasicBlockRef check_elem_idx_succ;
  114. /* get the cur size of the table instance */
  115. if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
  116. + offsetof(AOTTableInstance, cur_size)))) {
  117. HANDLE_FAILURE("LLVMConstInt");
  118. goto fail;
  119. }
  120. if (!(tbl_sz = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
  121. func_ctx->aot_inst, &offset, 1,
  122. "cur_size_i8p"))) {
  123. HANDLE_FAILURE("LLVMBuildInBoundsGEP");
  124. goto fail;
  125. }
  126. if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
  127. "cur_siuze_i32p"))) {
  128. HANDLE_FAILURE("LLVMBuildBitCast");
  129. goto fail;
  130. }
  131. if (!(tbl_sz = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, tbl_sz,
  132. "cur_size"))) {
  133. HANDLE_FAILURE("LLVMBuildLoad");
  134. goto fail;
  135. }
  136. /* Check if (uint32)elem index >= table size */
  137. if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, elem_idx,
  138. tbl_sz, "cmp_elem_idx"))) {
  139. aot_set_last_error("llvm build icmp failed.");
  140. goto fail;
  141. }
  142. /* Throw exception if elem index >= table size */
  143. if (!(check_elem_idx_succ = LLVMAppendBasicBlockInContext(
  144. comp_ctx->context, func_ctx->func, "check_elem_idx_succ"))) {
  145. aot_set_last_error("llvm add basic block failed.");
  146. goto fail;
  147. }
  148. LLVMMoveBasicBlockAfter(check_elem_idx_succ,
  149. LLVMGetInsertBlock(comp_ctx->builder));
  150. if (!(aot_emit_exception(comp_ctx, func_ctx,
  151. EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, true,
  152. cmp_elem_idx, check_elem_idx_succ)))
  153. goto fail;
  154. return true;
  155. fail:
  156. return false;
  157. }
  158. bool
  159. aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  160. uint32 tbl_idx)
  161. {
  162. LLVMValueRef elem_idx, offset, func_idx;
  163. LLVMValueRef table_elem_base, table_elem_addr, table_elem;
  164. POP_I32(elem_idx);
  165. if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
  166. goto fail;
  167. }
  168. /* load data as i32* */
  169. if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
  170. + offsetof(AOTTableInstance, elems)))) {
  171. HANDLE_FAILURE("LLVMConstInt");
  172. goto fail;
  173. }
  174. if (!(table_elem_base = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
  175. func_ctx->aot_inst, &offset,
  176. 1, "table_elem_base_i8p"))) {
  177. aot_set_last_error("llvm build add failed.");
  178. goto fail;
  179. }
  180. /* Load function object reference or function index */
  181. if (comp_ctx->enable_gc) {
  182. if (!(table_elem_base =
  183. LLVMBuildBitCast(comp_ctx->builder, table_elem_base,
  184. GC_REF_PTR_TYPE, "table_elem_base"))) {
  185. HANDLE_FAILURE("LLVMBuildBitCast");
  186. goto fail;
  187. }
  188. if (!(table_elem_addr = LLVMBuildInBoundsGEP2(
  189. comp_ctx->builder, GC_REF_TYPE, table_elem_base, &elem_idx, 1,
  190. "table_elem_addr"))) {
  191. HANDLE_FAILURE("LLVMBuildNUWAdd");
  192. goto fail;
  193. }
  194. if (!(table_elem = LLVMBuildLoad2(comp_ctx->builder, GC_REF_TYPE,
  195. table_elem_addr, "table_elem"))) {
  196. HANDLE_FAILURE("LLVMBuildLoad");
  197. goto fail;
  198. }
  199. PUSH_GC_REF(table_elem);
  200. }
  201. else {
  202. if (!(table_elem_base =
  203. LLVMBuildBitCast(comp_ctx->builder, table_elem_base,
  204. INTPTR_T_PTR_TYPE, "table_elem_base"))) {
  205. HANDLE_FAILURE("LLVMBuildBitCast");
  206. goto fail;
  207. }
  208. if (!(table_elem_addr = LLVMBuildInBoundsGEP2(
  209. comp_ctx->builder, INTPTR_T_TYPE, table_elem_base, &elem_idx,
  210. 1, "table_elem_addr"))) {
  211. HANDLE_FAILURE("LLVMBuildNUWAdd");
  212. goto fail;
  213. }
  214. if (!(table_elem = LLVMBuildLoad2(comp_ctx->builder, INTPTR_T_TYPE,
  215. table_elem_addr, "table_elem"))) {
  216. HANDLE_FAILURE("LLVMBuildLoad");
  217. goto fail;
  218. }
  219. if (!(func_idx = LLVMBuildIntCast2(comp_ctx->builder, table_elem,
  220. I32_TYPE, true, "func_idx"))) {
  221. HANDLE_FAILURE("LLVMBuildIntCast");
  222. goto fail;
  223. }
  224. PUSH_I32(func_idx);
  225. }
  226. return true;
  227. fail:
  228. return false;
  229. }
  230. bool
  231. aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  232. uint32 tbl_idx)
  233. {
  234. LLVMValueRef val = NULL, elem_idx, offset, table_elem_base, table_elem_addr;
  235. if (comp_ctx->enable_gc)
  236. POP_GC_REF(val);
  237. else {
  238. POP_I32(val);
  239. if (!(val = LLVMBuildIntCast2(comp_ctx->builder, val, INTPTR_T_TYPE,
  240. true, "val_intptr_t"))) {
  241. HANDLE_FAILURE("LLVMBuildBitCast");
  242. goto fail;
  243. }
  244. }
  245. POP_I32(elem_idx);
  246. if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
  247. goto fail;
  248. }
  249. /* load data as gc_obj_ref* or i32* */
  250. if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
  251. + offsetof(AOTTableInstance, elems)))) {
  252. HANDLE_FAILURE("LLVMConstInt");
  253. goto fail;
  254. }
  255. if (!(table_elem_base = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
  256. func_ctx->aot_inst, &offset,
  257. 1, "table_elem_base_i8p"))) {
  258. HANDLE_FAILURE("LLVMBuildInBoundsGEP");
  259. goto fail;
  260. }
  261. if (comp_ctx->enable_gc) {
  262. if (!(table_elem_base =
  263. LLVMBuildBitCast(comp_ctx->builder, table_elem_base,
  264. GC_REF_PTR_TYPE, "table_elem_base"))) {
  265. HANDLE_FAILURE("LLVMBuildBitCast");
  266. goto fail;
  267. }
  268. if (!(table_elem_addr = LLVMBuildInBoundsGEP2(
  269. comp_ctx->builder, GC_REF_TYPE, table_elem_base, &elem_idx, 1,
  270. "table_elem_addr"))) {
  271. HANDLE_FAILURE("LLVMBuildInBoundsGEP");
  272. goto fail;
  273. }
  274. }
  275. else {
  276. if (!(table_elem_base =
  277. LLVMBuildBitCast(comp_ctx->builder, table_elem_base,
  278. INTPTR_T_PTR_TYPE, "table_elem_base"))) {
  279. HANDLE_FAILURE("LLVMBuildBitCast");
  280. goto fail;
  281. }
  282. if (!(table_elem_addr = LLVMBuildInBoundsGEP2(
  283. comp_ctx->builder, INTPTR_T_TYPE, table_elem_base, &elem_idx,
  284. 1, "table_elem_addr"))) {
  285. HANDLE_FAILURE("LLVMBuildInBoundsGEP");
  286. goto fail;
  287. }
  288. }
  289. if (!(LLVMBuildStore(comp_ctx->builder, val, table_elem_addr))) {
  290. HANDLE_FAILURE("LLVMBuildStore");
  291. goto fail;
  292. }
  293. return true;
  294. fail:
  295. return false;
  296. }
  297. bool
  298. aot_compile_op_table_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  299. uint32 tbl_idx, uint32 tbl_seg_idx)
  300. {
  301. LLVMValueRef func, param_values[6], value;
  302. LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
  303. param_types[0] = INT8_PTR_TYPE;
  304. param_types[1] = I32_TYPE;
  305. param_types[2] = I32_TYPE;
  306. param_types[3] = I32_TYPE;
  307. param_types[4] = I32_TYPE;
  308. param_types[5] = I32_TYPE;
  309. ret_type = VOID_TYPE;
  310. if (comp_ctx->is_jit_mode)
  311. GET_AOT_FUNCTION(llvm_jit_table_init, 6);
  312. else
  313. GET_AOT_FUNCTION(aot_table_init, 6);
  314. param_values[0] = func_ctx->aot_inst;
  315. if (!(param_values[1] = I32_CONST(tbl_idx))) {
  316. HANDLE_FAILURE("LLVMConstInt");
  317. goto fail;
  318. }
  319. if (!(param_values[2] = I32_CONST(tbl_seg_idx))) {
  320. HANDLE_FAILURE("LLVMConstInt");
  321. goto fail;
  322. }
  323. /* n */
  324. POP_I32(param_values[3]);
  325. /* s */
  326. POP_I32(param_values[4]);
  327. /* d */
  328. POP_I32(param_values[5]);
  329. /* "" means return void */
  330. if (!(LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 6,
  331. ""))) {
  332. HANDLE_FAILURE("LLVMBuildCall");
  333. goto fail;
  334. }
  335. return true;
  336. fail:
  337. return false;
  338. }
  339. bool
  340. aot_compile_op_table_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  341. uint32 src_tbl_idx, uint32 dst_tbl_idx)
  342. {
  343. LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
  344. LLVMValueRef func, param_values[6], value;
  345. param_types[0] = INT8_PTR_TYPE;
  346. param_types[1] = I32_TYPE;
  347. param_types[2] = I32_TYPE;
  348. param_types[3] = I32_TYPE;
  349. param_types[4] = I32_TYPE;
  350. param_types[5] = I32_TYPE;
  351. ret_type = VOID_TYPE;
  352. if (comp_ctx->is_jit_mode)
  353. GET_AOT_FUNCTION(llvm_jit_table_copy, 6);
  354. else
  355. GET_AOT_FUNCTION(aot_table_copy, 6);
  356. param_values[0] = func_ctx->aot_inst;
  357. if (!(param_values[1] = I32_CONST(src_tbl_idx))) {
  358. HANDLE_FAILURE("LLVMConstInt");
  359. goto fail;
  360. }
  361. if (!(param_values[2] = I32_CONST(dst_tbl_idx))) {
  362. HANDLE_FAILURE("LLVMConstInt");
  363. goto fail;
  364. }
  365. /* n */
  366. POP_I32(param_values[3]);
  367. /* s */
  368. POP_I32(param_values[4]);
  369. /* d */
  370. POP_I32(param_values[5]);
  371. /* "" means return void */
  372. if (!(LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 6,
  373. ""))) {
  374. HANDLE_FAILURE("LLVMBuildCall");
  375. goto fail;
  376. }
  377. return true;
  378. fail:
  379. return false;
  380. }
  381. bool
  382. aot_compile_op_table_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  383. uint32 tbl_idx)
  384. {
  385. LLVMValueRef offset, tbl_sz;
  386. if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
  387. + offsetof(AOTTableInstance, cur_size)))) {
  388. HANDLE_FAILURE("LLVMConstInt");
  389. goto fail;
  390. }
  391. if (!(tbl_sz = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
  392. func_ctx->aot_inst, &offset, 1,
  393. "tbl_sz_ptr_i8"))) {
  394. HANDLE_FAILURE("LLVMBuildInBoundsGEP");
  395. goto fail;
  396. }
  397. if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
  398. "tbl_sz_ptr"))) {
  399. HANDLE_FAILURE("LLVMBuildBitCast");
  400. goto fail;
  401. }
  402. if (!(tbl_sz =
  403. LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, tbl_sz, "tbl_sz"))) {
  404. HANDLE_FAILURE("LLVMBuildLoad");
  405. goto fail;
  406. }
  407. PUSH_I32(tbl_sz);
  408. return true;
  409. fail:
  410. return false;
  411. }
  412. bool
  413. aot_compile_op_table_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  414. uint32 tbl_idx)
  415. {
  416. LLVMTypeRef param_types[4], ret_type, func_type, func_ptr_type;
  417. LLVMValueRef func, param_values[4], ret, value;
  418. param_types[0] = INT8_PTR_TYPE;
  419. param_types[1] = I32_TYPE;
  420. param_types[2] = I32_TYPE;
  421. param_types[3] = INT8_PTR_TYPE;
  422. ret_type = I32_TYPE;
  423. if (comp_ctx->is_jit_mode)
  424. GET_AOT_FUNCTION(llvm_jit_table_grow, 4);
  425. else
  426. GET_AOT_FUNCTION(aot_table_grow, 4);
  427. param_values[0] = func_ctx->aot_inst;
  428. if (!(param_values[1] = I32_CONST(tbl_idx))) {
  429. HANDLE_FAILURE("LLVMConstInt");
  430. goto fail;
  431. }
  432. /* n */
  433. POP_I32(param_values[2]);
  434. /* v */
  435. if (comp_ctx->enable_gc) {
  436. POP_GC_REF(param_values[3]);
  437. if (!(param_values[3] =
  438. LLVMBuildBitCast(comp_ctx->builder, param_values[3],
  439. INT8_PTR_TYPE, "table_elem_i8p"))) {
  440. HANDLE_FAILURE("LLVMBuildBitCast");
  441. goto fail;
  442. }
  443. }
  444. else {
  445. POP_I32(param_values[3]);
  446. if (!(param_values[3] =
  447. LLVMBuildIntToPtr(comp_ctx->builder, param_values[3],
  448. INT8_PTR_TYPE, "table_elem_i8p"))) {
  449. HANDLE_FAILURE("LLVMBuildIntToPtr");
  450. goto fail;
  451. }
  452. }
  453. if (!(ret = LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values,
  454. 4, "table_grow"))) {
  455. HANDLE_FAILURE("LLVMBuildCall");
  456. goto fail;
  457. }
  458. PUSH_I32(ret);
  459. return true;
  460. fail:
  461. return false;
  462. }
  463. bool
  464. aot_compile_op_table_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  465. uint32 tbl_idx)
  466. {
  467. LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type;
  468. LLVMValueRef func, param_values[5], value;
  469. param_types[0] = INT8_PTR_TYPE;
  470. param_types[1] = I32_TYPE;
  471. param_types[2] = I32_TYPE;
  472. param_types[3] = INT8_PTR_TYPE;
  473. param_types[4] = I32_TYPE;
  474. ret_type = VOID_TYPE;
  475. if (comp_ctx->is_jit_mode)
  476. GET_AOT_FUNCTION(llvm_jit_table_fill, 5);
  477. else
  478. GET_AOT_FUNCTION(aot_table_fill, 5);
  479. param_values[0] = func_ctx->aot_inst;
  480. if (!(param_values[1] = I32_CONST(tbl_idx))) {
  481. HANDLE_FAILURE("LLVMConstInt");
  482. goto fail;
  483. }
  484. /* n */
  485. POP_I32(param_values[2]);
  486. /* v */
  487. if (comp_ctx->enable_gc) {
  488. POP_GC_REF(param_values[3]);
  489. if (!(param_values[3] =
  490. LLVMBuildBitCast(comp_ctx->builder, param_values[3],
  491. INT8_PTR_TYPE, "table_elem_i8p"))) {
  492. HANDLE_FAILURE("LLVMBuildBitCast");
  493. goto fail;
  494. }
  495. }
  496. else {
  497. POP_I32(param_values[3]);
  498. if (!(param_values[3] =
  499. LLVMBuildIntToPtr(comp_ctx->builder, param_values[3],
  500. INT8_PTR_TYPE, "table_elem_i8p"))) {
  501. HANDLE_FAILURE("LLVMBuildIntToPtr");
  502. goto fail;
  503. }
  504. }
  505. /* i */
  506. POP_I32(param_values[4]);
  507. /* "" means return void */
  508. if (!(LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 5,
  509. ""))) {
  510. HANDLE_FAILURE("LLVMBuildCall");
  511. goto fail;
  512. }
  513. return true;
  514. fail:
  515. return false;
  516. }
  517. #endif /* WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC !=0 */