aot_emit_table.c 13 KB

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