aot_emit_table.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  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. uint64
  9. get_tbl_inst_offset(const AOTCompContext *comp_ctx,
  10. const AOTFuncContext *func_ctx, uint32 tbl_idx)
  11. {
  12. uint64 offset = 0, i = 0;
  13. AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables;
  14. AOTTable *tbls = comp_ctx->comp_data->tables;
  15. /* from the head of AOTModuleInstance */
  16. offset =
  17. offsetof(AOTModuleInstance, global_table_data.bytes)
  18. + (uint64)comp_ctx->comp_data->memory_count * sizeof(AOTMemoryInstance)
  19. + comp_ctx->comp_data->global_data_size;
  20. while (i < tbl_idx && i < comp_ctx->comp_data->import_table_count) {
  21. offset += offsetof(AOTTableInstance, data);
  22. /* avoid loading from current AOTTableInstance */
  23. offset += sizeof(uint32) * aot_get_imp_tbl_data_slots(imp_tbls + i);
  24. ++i;
  25. }
  26. if (i == tbl_idx) {
  27. return offset;
  28. }
  29. tbl_idx -= comp_ctx->comp_data->import_table_count;
  30. i -= comp_ctx->comp_data->import_table_count;
  31. while (i < tbl_idx && i < comp_ctx->comp_data->table_count) {
  32. offset += offsetof(AOTTableInstance, data);
  33. /* avoid loading from current AOTTableInstance */
  34. offset += sizeof(uint32) * aot_get_tbl_data_slots(tbls + i);
  35. ++i;
  36. }
  37. return offset;
  38. }
  39. #if WASM_ENABLE_REF_TYPES != 0
  40. LLVMValueRef
  41. aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  42. uint32 tbl_idx)
  43. {
  44. LLVMValueRef offset, tbl_inst;
  45. if (!(offset =
  46. I64_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)))) {
  47. HANDLE_FAILURE("LLVMConstInt");
  48. goto fail;
  49. }
  50. if (!(tbl_inst = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst,
  51. &offset, 1, "tbl_inst"))) {
  52. HANDLE_FAILURE("LLVMBuildGEP");
  53. goto fail;
  54. }
  55. return tbl_inst;
  56. fail:
  57. return NULL;
  58. }
  59. bool
  60. aot_compile_op_elem_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  61. uint32 tbl_seg_idx)
  62. {
  63. LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
  64. LLVMValueRef param_values[2], ret_value, func, value;
  65. /* void aot_drop_table_seg(AOTModuleInstance *, uint32 ) */
  66. param_types[0] = INT8_PTR_TYPE;
  67. param_types[1] = I32_TYPE;
  68. ret_type = VOID_TYPE;
  69. GET_AOT_FUNCTION(aot_drop_table_seg, 2);
  70. param_values[0] = func_ctx->aot_inst;
  71. if (!(param_values[1] = I32_CONST(tbl_seg_idx))) {
  72. HANDLE_FAILURE("LLVMConstInt");
  73. goto fail;
  74. }
  75. /* "" means return void */
  76. if (!(ret_value =
  77. LLVMBuildCall(comp_ctx->builder, func, param_values, 2, ""))) {
  78. HANDLE_FAILURE("LLVMBuildCall");
  79. goto fail;
  80. }
  81. return true;
  82. fail:
  83. return false;
  84. }
  85. static bool
  86. aot_check_table_access(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  87. uint32 tbl_idx, LLVMValueRef elem_idx)
  88. {
  89. LLVMValueRef offset, tbl_sz, cmp_elem_idx;
  90. LLVMBasicBlockRef check_elem_idx_succ;
  91. /* get the cur size of the table instance */
  92. if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
  93. + offsetof(AOTTableInstance, cur_size)))) {
  94. HANDLE_FAILURE("LLVMConstInt");
  95. goto fail;
  96. }
  97. if (!(tbl_sz = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst, &offset,
  98. 1, "cur_size_i8p"))) {
  99. HANDLE_FAILURE("LLVMBuildGEP");
  100. goto fail;
  101. }
  102. if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
  103. "cur_siuze_i32p"))) {
  104. HANDLE_FAILURE("LLVMBuildBitCast");
  105. goto fail;
  106. }
  107. if (!(tbl_sz = LLVMBuildLoad(comp_ctx->builder, tbl_sz, "cur_size"))) {
  108. HANDLE_FAILURE("LLVMBuildLoad");
  109. goto fail;
  110. }
  111. /* Check if (uint32)elem index >= table size */
  112. if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, elem_idx,
  113. tbl_sz, "cmp_elem_idx"))) {
  114. aot_set_last_error("llvm build icmp failed.");
  115. goto fail;
  116. }
  117. /* Throw exception if elem index >= table size */
  118. if (!(check_elem_idx_succ = LLVMAppendBasicBlockInContext(
  119. comp_ctx->context, func_ctx->func, "check_elem_idx_succ"))) {
  120. aot_set_last_error("llvm add basic block failed.");
  121. goto fail;
  122. }
  123. LLVMMoveBasicBlockAfter(check_elem_idx_succ,
  124. LLVMGetInsertBlock(comp_ctx->builder));
  125. if (!(aot_emit_exception(comp_ctx, func_ctx,
  126. EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, true,
  127. cmp_elem_idx, check_elem_idx_succ)))
  128. goto fail;
  129. return true;
  130. fail:
  131. return false;
  132. }
  133. bool
  134. aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  135. uint32 tbl_idx)
  136. {
  137. LLVMValueRef elem_idx, offset, table_elem, func_idx;
  138. POP_I32(elem_idx);
  139. if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
  140. goto fail;
  141. }
  142. /* load data as i32* */
  143. if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
  144. + offsetof(AOTTableInstance, data)))) {
  145. HANDLE_FAILURE("LLVMConstInt");
  146. goto fail;
  147. }
  148. if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst,
  149. &offset, 1, "table_elem_i8p"))) {
  150. aot_set_last_error("llvm build add failed.");
  151. goto fail;
  152. }
  153. if (!(table_elem = LLVMBuildBitCast(comp_ctx->builder, table_elem,
  154. INT32_PTR_TYPE, "table_elem_i32p"))) {
  155. HANDLE_FAILURE("LLVMBuildBitCast");
  156. goto fail;
  157. }
  158. /* Load function index */
  159. if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx, 1,
  160. "table_elem"))) {
  161. HANDLE_FAILURE("LLVMBuildNUWAdd");
  162. goto fail;
  163. }
  164. if (!(func_idx =
  165. LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) {
  166. HANDLE_FAILURE("LLVMBuildLoad");
  167. goto fail;
  168. }
  169. PUSH_I32(func_idx);
  170. return true;
  171. fail:
  172. return false;
  173. }
  174. bool
  175. aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  176. uint32 tbl_idx)
  177. {
  178. LLVMValueRef val, elem_idx, offset, table_elem;
  179. POP_I32(val);
  180. POP_I32(elem_idx);
  181. if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
  182. goto fail;
  183. }
  184. /* load data as i32* */
  185. if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
  186. + offsetof(AOTTableInstance, data)))) {
  187. HANDLE_FAILURE("LLVMConstInt");
  188. goto fail;
  189. }
  190. if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst,
  191. &offset, 1, "table_elem_i8p"))) {
  192. HANDLE_FAILURE("LLVMBuildGEP");
  193. goto fail;
  194. }
  195. if (!(table_elem = LLVMBuildBitCast(comp_ctx->builder, table_elem,
  196. INT32_PTR_TYPE, "table_elem_i32p"))) {
  197. HANDLE_FAILURE("LLVMBuildBitCast");
  198. goto fail;
  199. }
  200. /* Load function index */
  201. if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx, 1,
  202. "table_elem"))) {
  203. HANDLE_FAILURE("LLVMBuildGEP");
  204. goto fail;
  205. }
  206. if (!(LLVMBuildStore(comp_ctx->builder, val, table_elem))) {
  207. HANDLE_FAILURE("LLVMBuildStore");
  208. goto fail;
  209. }
  210. return true;
  211. fail:
  212. return false;
  213. }
  214. bool
  215. aot_compile_op_table_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  216. uint32 tbl_idx, uint32 tbl_seg_idx)
  217. {
  218. LLVMValueRef func, param_values[6], value;
  219. LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
  220. param_types[0] = INT8_PTR_TYPE;
  221. param_types[1] = I32_TYPE;
  222. param_types[2] = I32_TYPE;
  223. param_types[3] = I32_TYPE;
  224. param_types[4] = I32_TYPE;
  225. param_types[5] = I32_TYPE;
  226. ret_type = VOID_TYPE;
  227. GET_AOT_FUNCTION(aot_table_init, 6);
  228. param_values[0] = func_ctx->aot_inst;
  229. if (!(param_values[1] = I32_CONST(tbl_idx))) {
  230. HANDLE_FAILURE("LLVMConstInt");
  231. goto fail;
  232. }
  233. if (!(param_values[2] = I32_CONST(tbl_seg_idx))) {
  234. HANDLE_FAILURE("LLVMConstInt");
  235. goto fail;
  236. }
  237. /* n */
  238. POP_I32(param_values[3]);
  239. /* s */
  240. POP_I32(param_values[4]);
  241. /* d */
  242. POP_I32(param_values[5]);
  243. /* "" means return void */
  244. if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 6, ""))) {
  245. HANDLE_FAILURE("LLVMBuildCall");
  246. goto fail;
  247. }
  248. return true;
  249. fail:
  250. return false;
  251. }
  252. bool
  253. aot_compile_op_table_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  254. uint32 src_tbl_idx, uint32 dst_tbl_idx)
  255. {
  256. LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
  257. LLVMValueRef func, param_values[6], value;
  258. param_types[0] = INT8_PTR_TYPE;
  259. param_types[1] = I32_TYPE;
  260. param_types[2] = I32_TYPE;
  261. param_types[3] = I32_TYPE;
  262. param_types[4] = I32_TYPE;
  263. param_types[5] = I32_TYPE;
  264. ret_type = VOID_TYPE;
  265. GET_AOT_FUNCTION(aot_table_copy, 6);
  266. param_values[0] = func_ctx->aot_inst;
  267. if (!(param_values[1] = I32_CONST(src_tbl_idx))) {
  268. HANDLE_FAILURE("LLVMConstInt");
  269. goto fail;
  270. }
  271. if (!(param_values[2] = I32_CONST(dst_tbl_idx))) {
  272. HANDLE_FAILURE("LLVMConstInt");
  273. goto fail;
  274. }
  275. /* n */
  276. POP_I32(param_values[3]);
  277. /* s */
  278. POP_I32(param_values[4]);
  279. /* d */
  280. POP_I32(param_values[5]);
  281. /* "" means return void */
  282. if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 6, ""))) {
  283. HANDLE_FAILURE("LLVMBuildCall");
  284. goto fail;
  285. }
  286. return true;
  287. fail:
  288. return false;
  289. }
  290. bool
  291. aot_compile_op_table_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  292. uint32 tbl_idx)
  293. {
  294. LLVMValueRef offset, tbl_sz;
  295. if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
  296. + offsetof(AOTTableInstance, cur_size)))) {
  297. HANDLE_FAILURE("LLVMConstInt");
  298. goto fail;
  299. }
  300. if (!(tbl_sz = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst, &offset,
  301. 1, "tbl_sz_ptr_i8"))) {
  302. HANDLE_FAILURE("LLVMBuildGEP");
  303. goto fail;
  304. }
  305. if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
  306. "tbl_sz_ptr"))) {
  307. HANDLE_FAILURE("LLVMBuildBitCast");
  308. goto fail;
  309. }
  310. if (!(tbl_sz = LLVMBuildLoad(comp_ctx->builder, tbl_sz, "tbl_sz"))) {
  311. HANDLE_FAILURE("LLVMBuildLoad");
  312. goto fail;
  313. }
  314. PUSH_I32(tbl_sz);
  315. return true;
  316. fail:
  317. return false;
  318. }
  319. bool
  320. aot_compile_op_table_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  321. uint32 tbl_idx)
  322. {
  323. LLVMTypeRef param_types[4], ret_type, func_type, func_ptr_type;
  324. LLVMValueRef func, param_values[4], ret, value;
  325. param_types[0] = INT8_PTR_TYPE;
  326. param_types[1] = I32_TYPE;
  327. param_types[2] = I32_TYPE;
  328. param_types[3] = I32_TYPE;
  329. ret_type = I32_TYPE;
  330. GET_AOT_FUNCTION(aot_table_grow, 4);
  331. param_values[0] = func_ctx->aot_inst;
  332. if (!(param_values[1] = I32_CONST(tbl_idx))) {
  333. HANDLE_FAILURE("LLVMConstInt");
  334. goto fail;
  335. }
  336. /* n */
  337. POP_I32(param_values[2]);
  338. /* v */
  339. POP_I32(param_values[3]);
  340. if (!(ret = LLVMBuildCall(comp_ctx->builder, func, param_values, 4,
  341. "table_grow"))) {
  342. HANDLE_FAILURE("LLVMBuildCall");
  343. goto fail;
  344. }
  345. PUSH_I32(ret);
  346. return true;
  347. fail:
  348. return false;
  349. }
  350. bool
  351. aot_compile_op_table_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  352. uint32 tbl_idx)
  353. {
  354. LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type;
  355. LLVMValueRef func, param_values[5], value;
  356. param_types[0] = INT8_PTR_TYPE;
  357. param_types[1] = I32_TYPE;
  358. param_types[2] = I32_TYPE;
  359. param_types[3] = I32_TYPE;
  360. param_types[4] = I32_TYPE;
  361. ret_type = VOID_TYPE;
  362. GET_AOT_FUNCTION(aot_table_fill, 5);
  363. param_values[0] = func_ctx->aot_inst;
  364. if (!(param_values[1] = I32_CONST(tbl_idx))) {
  365. HANDLE_FAILURE("LLVMConstInt");
  366. goto fail;
  367. }
  368. /* n */
  369. POP_I32(param_values[2]);
  370. /* v */
  371. POP_I32(param_values[3]);
  372. /* i */
  373. POP_I32(param_values[4]);
  374. /* "" means return void */
  375. if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 5, ""))) {
  376. HANDLE_FAILURE("LLVMBuildCall");
  377. goto fail;
  378. }
  379. return true;
  380. fail:
  381. return false;
  382. }
  383. #endif /* WASM_ENABLE_REF_TYPES != 0 */