aot_emit_function.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  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_function.h"
  6. #include "aot_emit_exception.h"
  7. #include "aot_emit_control.h"
  8. #include "../aot/aot_runtime.h"
  9. static bool
  10. create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  11. {
  12. LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
  13. AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
  14. /* Create function return block if it isn't created */
  15. if (!func_ctx->func_return_block) {
  16. if (!(func_ctx->func_return_block =
  17. LLVMAppendBasicBlockInContext(comp_ctx->context,
  18. func_ctx->func, "func_ret"))) {
  19. aot_set_last_error("llvm add basic block failed.");
  20. return false;
  21. }
  22. /* Create return IR */
  23. LLVMPositionBuilderAtEnd(comp_ctx->builder, func_ctx->func_return_block);
  24. if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) {
  25. return false;
  26. }
  27. }
  28. LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
  29. return true;
  30. }
  31. /* Check whether there was exception thrown, if yes, return directly */
  32. static bool
  33. check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  34. {
  35. LLVMBasicBlockRef block_curr, check_exce_succ;
  36. LLVMValueRef value, cmp;
  37. /* Create function return block if it isn't created */
  38. if (!create_func_return_block(comp_ctx, func_ctx))
  39. return false;
  40. /* Load the first byte of aot_module_inst->cur_exception, and check
  41. whether it is '\0'. If yes, no exception was thrown. */
  42. if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception,
  43. "exce_value"))
  44. || !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
  45. value, I8_ZERO, "cmp"))) {
  46. aot_set_last_error("llvm build icmp failed.");
  47. return false;
  48. }
  49. /* Add check exection success block */
  50. if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context,
  51. func_ctx->func,
  52. "check_exce_succ"))) {
  53. aot_set_last_error("llvm add basic block failed.");
  54. return false;
  55. }
  56. block_curr = LLVMGetInsertBlock(comp_ctx->builder);
  57. LLVMMoveBasicBlockAfter(check_exce_succ, block_curr);
  58. LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
  59. /* Create condition br */
  60. if (!LLVMBuildCondBr(comp_ctx->builder, cmp,
  61. check_exce_succ, func_ctx->func_return_block)) {
  62. aot_set_last_error("llvm build cond br failed.");
  63. return false;
  64. }
  65. LLVMPositionBuilderAtEnd(comp_ctx->builder, check_exce_succ);
  66. return true;
  67. }
  68. /* Check whether there was exception thrown, if yes, return directly */
  69. static bool
  70. check_call_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  71. LLVMValueRef res)
  72. {
  73. LLVMBasicBlockRef block_curr, check_call_succ;
  74. LLVMValueRef cmp;
  75. /* Create function return block if it isn't created */
  76. if (!create_func_return_block(comp_ctx, func_ctx))
  77. return false;
  78. if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE,
  79. res, I8_ZERO, "cmp"))) {
  80. aot_set_last_error("llvm build icmp failed.");
  81. return false;
  82. }
  83. /* Add check exection success block */
  84. if (!(check_call_succ = LLVMAppendBasicBlockInContext(comp_ctx->context,
  85. func_ctx->func,
  86. "check_call_succ"))) {
  87. aot_set_last_error("llvm add basic block failed.");
  88. return false;
  89. }
  90. block_curr = LLVMGetInsertBlock(comp_ctx->builder);
  91. LLVMMoveBasicBlockAfter(check_call_succ, block_curr);
  92. LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
  93. /* Create condition br */
  94. if (!LLVMBuildCondBr(comp_ctx->builder, cmp,
  95. check_call_succ, func_ctx->func_return_block)) {
  96. aot_set_last_error("llvm build cond br failed.");
  97. return false;
  98. }
  99. LLVMPositionBuilderAtEnd(comp_ctx->builder, check_call_succ);
  100. return true;
  101. }
  102. static bool
  103. call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  104. LLVMValueRef func_idx, AOTFuncType *aot_func_type,
  105. LLVMTypeRef *param_types, LLVMValueRef *param_values,
  106. uint32 param_count, uint32 param_cell_num,
  107. LLVMTypeRef ret_type, uint8 wasm_ret_type,
  108. LLVMValueRef *p_value_ret, LLVMValueRef *p_res)
  109. {
  110. LLVMTypeRef func_type, func_ptr_type, func_param_types[4];
  111. LLVMTypeRef ret_ptr_type, elem_ptr_type;
  112. LLVMValueRef func, elem_idx, elem_ptr;
  113. LLVMValueRef func_param_values[4], value_ret = NULL, res;
  114. char buf[32], *func_name = "aot_invoke_native";
  115. uint32 i, cell_num = 0;
  116. /* prepare function type of aot_invoke_native */
  117. func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */
  118. func_param_types[1] = I32_TYPE; /* func_idx */
  119. func_param_types[2] = I32_TYPE; /* argc */
  120. func_param_types[3] = INT32_PTR_TYPE; /* argv */
  121. if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 4, false))) {
  122. aot_set_last_error("llvm add function type failed.");
  123. return false;
  124. }
  125. /* prepare function pointer */
  126. if (comp_ctx->is_jit_mode) {
  127. if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
  128. aot_set_last_error("create LLVM function type failed.");
  129. return false;
  130. }
  131. /* JIT mode, call the function directly */
  132. if (!(func = I64_CONST((uint64)(uintptr_t)aot_invoke_native))
  133. || !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
  134. aot_set_last_error("create LLVM value failed.");
  135. return false;
  136. }
  137. }
  138. else {
  139. if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
  140. && !(func = LLVMAddFunction(comp_ctx->module,
  141. func_name, func_type))) {
  142. aot_set_last_error("add LLVM function failed.");
  143. return false;
  144. }
  145. }
  146. if (param_cell_num > 64) {
  147. aot_set_last_error("prepare native arguments failed: "
  148. "maximum 64 parameter cell number supported.");
  149. return false;
  150. }
  151. /* prepare frame_lp */
  152. for (i = 0; i < param_count; i++) {
  153. if (!(elem_idx = I32_CONST(cell_num))
  154. || !(elem_ptr_type = LLVMPointerType(param_types[i], 0))) {
  155. aot_set_last_error("llvm add const or pointer type failed.");
  156. return false;
  157. }
  158. snprintf(buf, sizeof(buf), "%s%d", "elem", i);
  159. if (!(elem_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
  160. func_ctx->argv_buf, &elem_idx, 1, buf))
  161. || !(elem_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_ptr,
  162. elem_ptr_type, buf))) {
  163. aot_set_last_error("llvm build bit cast failed.");
  164. return false;
  165. }
  166. if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i], elem_ptr))) {
  167. aot_set_last_error("llvm build store failed.");
  168. return false;
  169. }
  170. LLVMSetAlignment(res, 1);
  171. cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
  172. }
  173. func_param_values[0] = func_ctx->exec_env;
  174. func_param_values[1] = func_idx;
  175. func_param_values[2] = I32_CONST(param_cell_num);
  176. func_param_values[3] = func_ctx->argv_buf;
  177. if (!func_param_values[2]) {
  178. aot_set_last_error("llvm create const failed.");
  179. return false;
  180. }
  181. /* call aot_invoke_native() function */
  182. if (!(res = LLVMBuildCall(comp_ctx->builder, func,
  183. func_param_values, 4, "res"))) {
  184. aot_set_last_error("llvm build call failed.");
  185. return false;
  186. }
  187. /* get function return value */
  188. if (wasm_ret_type != VALUE_TYPE_VOID) {
  189. if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) {
  190. aot_set_last_error("llvm add pointer type failed.");
  191. return false;
  192. }
  193. if (!(value_ret = LLVMBuildBitCast(comp_ctx->builder, func_ctx->argv_buf,
  194. ret_ptr_type, "argv_ret"))) {
  195. aot_set_last_error("llvm build bit cast failed.");
  196. return false;
  197. }
  198. if (!(*p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret,
  199. "value_ret"))) {
  200. aot_set_last_error("llvm build load failed.");
  201. return false;
  202. }
  203. }
  204. *p_res = res;
  205. return true;
  206. }
  207. static bool
  208. check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  209. uint32 callee_cell_num)
  210. {
  211. LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
  212. LLVMBasicBlockRef check_stack;
  213. LLVMValueRef callee_local_size, stack_bound, cmp;
  214. if (!(callee_local_size = I32_CONST(callee_cell_num * 4))) {
  215. aot_set_last_error("llvm build const failed.");
  216. return false;
  217. }
  218. if (!(stack_bound = LLVMBuildInBoundsGEP(comp_ctx->builder,
  219. func_ctx->native_stack_bound,
  220. &callee_local_size, 1,
  221. "stack_bound"))) {
  222. aot_set_last_error("llvm build inbound gep failed.");
  223. return false;
  224. }
  225. if (!(check_stack = LLVMAppendBasicBlockInContext(comp_ctx->context,
  226. func_ctx->func,
  227. "check_stack"))) {
  228. aot_set_last_error("llvm add basic block failed.");
  229. return false;
  230. }
  231. LLVMMoveBasicBlockAfter(check_stack, block_curr);
  232. if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT,
  233. func_ctx->last_alloca, stack_bound,
  234. "cmp"))) {
  235. aot_set_last_error("llvm build icmp failed.");
  236. return false;
  237. }
  238. if (!aot_emit_exception(comp_ctx, func_ctx,
  239. EXCE_NATIVE_STACK_OVERFLOW,
  240. true, cmp, check_stack)) {
  241. return false;
  242. }
  243. LLVMPositionBuilderAtEnd(comp_ctx->builder, check_stack);
  244. return true;
  245. }
  246. bool
  247. aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  248. uint32 func_idx, bool tail_call)
  249. {
  250. uint32 import_func_count = comp_ctx->comp_data->import_func_count;
  251. AOTImportFunc *import_funcs = comp_ctx->comp_data->import_funcs;
  252. uint32 func_count = comp_ctx->func_ctx_count, param_cell_num = 0;
  253. uint32 ext_ret_cell_num = 0, cell_num = 0;
  254. AOTFuncContext **func_ctxes = comp_ctx->func_ctxes;
  255. AOTFuncType *func_type;
  256. AOTFunc *aot_func;
  257. LLVMTypeRef *param_types = NULL, ret_type;
  258. LLVMTypeRef ext_ret_ptr_type;
  259. LLVMValueRef *param_values = NULL, value_ret = NULL, func;
  260. LLVMValueRef import_func_idx, res;
  261. LLVMValueRef ext_ret, ext_ret_ptr, ext_ret_idx;
  262. int32 i, j = 0, param_count, result_count, ext_ret_count;
  263. uint64 total_size;
  264. uint32 callee_cell_num;
  265. uint8 wasm_ret_type;
  266. uint8 *ext_ret_types = NULL;
  267. bool ret = false;
  268. char buf[32];
  269. #if WASM_ENABLE_THREAD_MGR != 0
  270. /* Insert suspend check point */
  271. if (comp_ctx->enable_thread_mgr) {
  272. if (!check_suspend_flags(comp_ctx, func_ctx))
  273. return false;
  274. }
  275. #endif
  276. /* Check function index */
  277. if (func_idx >= import_func_count + func_count) {
  278. aot_set_last_error("Function index out of range.");
  279. return false;
  280. }
  281. /* Get function type */
  282. if (func_idx < import_func_count)
  283. func_type = import_funcs[func_idx].func_type;
  284. else
  285. func_type = func_ctxes[func_idx - import_func_count]->
  286. aot_func->func_type;
  287. /* Get param cell number */
  288. param_cell_num = func_type->param_cell_num;
  289. /* Allocate memory for parameters.
  290. * Parameters layout:
  291. * - exec env
  292. * - wasm function's parameters
  293. * - extra results'(except the first one) addresses
  294. */
  295. param_count = (int32)func_type->param_count;
  296. result_count = (int32)func_type->result_count;
  297. ext_ret_count = result_count > 1 ? result_count - 1 : 0;
  298. total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1
  299. + ext_ret_count);
  300. if (total_size >= UINT32_MAX
  301. || !(param_values = wasm_runtime_malloc((uint32)total_size))) {
  302. aot_set_last_error("Allocate memory failed.");
  303. return false;
  304. }
  305. /* First parameter is exec env */
  306. param_values[j++] = func_ctx->exec_env;
  307. /* Pop parameters from stack */
  308. for (i = param_count - 1; i >= 0; i--)
  309. POP(param_values[i + j], func_type->types[i]);
  310. /* Set parameters for multiple return values, the first return value
  311. is returned by function return value, and the other return values
  312. are returned by function parameters with pointer types */
  313. if (ext_ret_count > 0) {
  314. ext_ret_types = func_type->types + param_count + 1;
  315. ext_ret_cell_num = wasm_get_cell_num(ext_ret_types, ext_ret_count);
  316. if (ext_ret_cell_num > 64) {
  317. aot_set_last_error("prepare extra results's return "
  318. "address arguments failed: "
  319. "maximum 64 parameter cell number supported.");
  320. goto fail;
  321. }
  322. for (i = 0; i < ext_ret_count; i++) {
  323. if (!(ext_ret_idx = I32_CONST(cell_num))
  324. || !(ext_ret_ptr_type =
  325. LLVMPointerType(TO_LLVM_TYPE(ext_ret_types[i]), 0))) {
  326. aot_set_last_error("llvm add const or pointer type failed.");
  327. goto fail;
  328. }
  329. snprintf(buf, sizeof(buf), "ext_ret%d_ptr", i);
  330. if (!(ext_ret_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
  331. func_ctx->argv_buf,
  332. &ext_ret_idx, 1, buf))) {
  333. aot_set_last_error("llvm build GEP failed.");
  334. goto fail;
  335. }
  336. snprintf(buf, sizeof(buf), "ext_ret%d_ptr_cast", i);
  337. if (!(ext_ret_ptr = LLVMBuildBitCast(comp_ctx->builder,
  338. ext_ret_ptr, ext_ret_ptr_type,
  339. buf))) {
  340. aot_set_last_error("llvm build bit cast failed.");
  341. goto fail;
  342. }
  343. param_values[param_count + 1 + i] = ext_ret_ptr;
  344. cell_num += wasm_value_type_cell_num(ext_ret_types[i]);
  345. }
  346. }
  347. if (func_idx < import_func_count) {
  348. if (!(import_func_idx = I32_CONST(func_idx))) {
  349. aot_set_last_error("llvm build inbounds gep failed.");
  350. goto fail;
  351. }
  352. /* Initialize parameter types of the LLVM function */
  353. total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1);
  354. if (total_size >= UINT32_MAX
  355. || !(param_types = wasm_runtime_malloc((uint32)total_size))) {
  356. aot_set_last_error("Allocate memory failed.");
  357. goto fail;
  358. }
  359. j = 0;
  360. param_types[j++] = comp_ctx->exec_env_type;
  361. for (i = 0; i < param_count; i++)
  362. param_types[j++] = TO_LLVM_TYPE(func_type->types[i]);
  363. if (func_type->result_count) {
  364. wasm_ret_type = func_type->types[func_type->param_count];
  365. ret_type = TO_LLVM_TYPE(wasm_ret_type);
  366. }
  367. else {
  368. wasm_ret_type = VALUE_TYPE_VOID;
  369. ret_type = VOID_TYPE;
  370. }
  371. /* call aot_invoke_native() */
  372. if (!call_aot_invoke_native_func(comp_ctx, func_ctx, import_func_idx, func_type,
  373. param_types + 1, param_values + 1,
  374. param_count, param_cell_num,
  375. ret_type, wasm_ret_type, &value_ret, &res))
  376. goto fail;
  377. /* Check whether there was exception thrown when executing the function */
  378. if (!check_call_return(comp_ctx, func_ctx, res))
  379. goto fail;
  380. }
  381. else {
  382. func = func_ctxes[func_idx - import_func_count]->func;
  383. aot_func = func_ctxes[func_idx - import_func_count]->aot_func;
  384. callee_cell_num = aot_func->param_cell_num + aot_func->local_cell_num + 1;
  385. if (comp_ctx->enable_bound_check
  386. && !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num))
  387. goto fail;
  388. /* Call the function */
  389. if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func,
  390. param_values,
  391. (uint32)param_count + 1 + ext_ret_count,
  392. (func_type->result_count > 0
  393. ? "call" : "")))) {
  394. aot_set_last_error("LLVM build call failed.");
  395. goto fail;
  396. }
  397. /* Set calling convention for the call with the func's calling convention */
  398. LLVMSetInstructionCallConv(value_ret, LLVMGetFunctionCallConv(func));
  399. if (tail_call)
  400. LLVMSetTailCall(value_ret, true);
  401. /* Check whether there was exception thrown when executing the function */
  402. if (!tail_call
  403. && !check_exception_thrown(comp_ctx, func_ctx))
  404. goto fail;
  405. }
  406. if (func_type->result_count > 0) {
  407. /* Push the first result to stack */
  408. PUSH(value_ret, func_type->types[func_type->param_count]);
  409. /* Load extra result from its address and push to stack */
  410. for (i = 0; i < ext_ret_count; i++) {
  411. snprintf(buf, sizeof(buf), "func%d_ext_ret%d", func_idx, i);
  412. if (!(ext_ret = LLVMBuildLoad(comp_ctx->builder,
  413. param_values[1 + param_count + i],
  414. buf))) {
  415. aot_set_last_error("llvm build load failed.");
  416. goto fail;
  417. }
  418. PUSH(ext_ret, ext_ret_types[i]);
  419. }
  420. }
  421. ret = true;
  422. fail:
  423. if (param_types)
  424. wasm_runtime_free(param_types);
  425. if (param_values)
  426. wasm_runtime_free(param_values);
  427. return ret;
  428. }
  429. static bool
  430. call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  431. AOTFuncType *aot_func_type,
  432. LLVMValueRef func_type_idx, LLVMValueRef table_elem_idx,
  433. LLVMTypeRef *param_types, LLVMValueRef *param_values,
  434. uint32 param_count, uint32 param_cell_num,
  435. uint32 result_count, uint8 *wasm_ret_types,
  436. LLVMValueRef *value_rets, LLVMValueRef *p_res)
  437. {
  438. LLVMTypeRef func_type, func_ptr_type, func_param_types[6];
  439. LLVMTypeRef ret_type, ret_ptr_type, elem_ptr_type;
  440. LLVMValueRef func, ret_idx, ret_ptr, elem_idx, elem_ptr;
  441. LLVMValueRef func_param_values[6], res = NULL;
  442. char buf[32], *func_name = "aot_call_indirect";
  443. uint32 i, cell_num = 0, ret_cell_num, argv_cell_num;
  444. #if WASM_ENABLE_THREAD_MGR != 0
  445. /* Insert suspend check point */
  446. if (comp_ctx->enable_thread_mgr) {
  447. if (!check_suspend_flags(comp_ctx, func_ctx))
  448. return false;
  449. }
  450. #endif
  451. /* prepare function type of aot_call_indirect */
  452. func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */
  453. func_param_types[1] = INT8_TYPE; /* check_func_type */
  454. func_param_types[2] = I32_TYPE; /* func_type_idx */
  455. func_param_types[3] = I32_TYPE; /* table_elem_idx */
  456. func_param_types[4] = I32_TYPE; /* argc */
  457. func_param_types[5] = INT32_PTR_TYPE; /* argv */
  458. if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 6, false))) {
  459. aot_set_last_error("llvm add function type failed.");
  460. return false;
  461. }
  462. /* prepare function pointer */
  463. if (comp_ctx->is_jit_mode) {
  464. if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
  465. aot_set_last_error("create LLVM function type failed.");
  466. return false;
  467. }
  468. /* JIT mode, call the function directly */
  469. if (!(func = I64_CONST((uint64)(uintptr_t)aot_call_indirect))
  470. || !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
  471. aot_set_last_error("create LLVM value failed.");
  472. return false;
  473. }
  474. }
  475. else {
  476. if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
  477. && !(func = LLVMAddFunction(comp_ctx->module,
  478. func_name, func_type))) {
  479. aot_set_last_error("add LLVM function failed.");
  480. return false;
  481. }
  482. }
  483. ret_cell_num = wasm_get_cell_num(wasm_ret_types, result_count);
  484. argv_cell_num = param_cell_num > ret_cell_num ? param_cell_num : ret_cell_num;
  485. if (argv_cell_num > 64) {
  486. aot_set_last_error("prepare native arguments failed: "
  487. "maximum 64 parameter cell number supported.");
  488. return false;
  489. }
  490. /* prepare frame_lp */
  491. for (i = 0; i < param_count; i++) {
  492. if (!(elem_idx = I32_CONST(cell_num))
  493. || !(elem_ptr_type = LLVMPointerType(param_types[i], 0))) {
  494. aot_set_last_error("llvm add const or pointer type failed.");
  495. return false;
  496. }
  497. snprintf(buf, sizeof(buf), "%s%d", "elem", i);
  498. if (!(elem_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
  499. func_ctx->argv_buf, &elem_idx, 1, buf))
  500. || !(elem_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_ptr,
  501. elem_ptr_type, buf))) {
  502. aot_set_last_error("llvm build bit cast failed.");
  503. return false;
  504. }
  505. if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i], elem_ptr))) {
  506. aot_set_last_error("llvm build store failed.");
  507. return false;
  508. }
  509. LLVMSetAlignment(res, 1);
  510. cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
  511. }
  512. func_param_values[0] = func_ctx->exec_env;
  513. func_param_values[1] = I8_CONST(true);
  514. func_param_values[2] = func_type_idx;
  515. func_param_values[3] = table_elem_idx;
  516. func_param_values[4] = I32_CONST(param_cell_num);
  517. func_param_values[5] = func_ctx->argv_buf;
  518. if (!func_param_values[1] || !func_param_values[4]) {
  519. aot_set_last_error("llvm create const failed.");
  520. return false;
  521. }
  522. /* call aot_call_indirect() function */
  523. if (!(res = LLVMBuildCall(comp_ctx->builder, func,
  524. func_param_values, 6, "res"))) {
  525. aot_set_last_error("llvm build call failed.");
  526. return false;
  527. }
  528. /* get function result values */
  529. cell_num = 0;
  530. for (i = 0; i < result_count; i++) {
  531. ret_type = TO_LLVM_TYPE(wasm_ret_types[i]);
  532. if (!(ret_idx = I32_CONST(cell_num))
  533. || !(ret_ptr_type = LLVMPointerType(ret_type, 0))) {
  534. aot_set_last_error("llvm add const or pointer type failed.");
  535. return false;
  536. }
  537. snprintf(buf, sizeof(buf), "argv_ret%d", i);
  538. if (!(ret_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
  539. func_ctx->argv_buf, &ret_idx, 1, buf))
  540. || !(ret_ptr = LLVMBuildBitCast(comp_ctx->builder, ret_ptr,
  541. ret_ptr_type, buf))) {
  542. aot_set_last_error("llvm build GEP or bit cast failed.");
  543. return false;
  544. }
  545. snprintf(buf, sizeof(buf), "ret%d", i);
  546. if (!(value_rets[i] = LLVMBuildLoad(comp_ctx->builder, ret_ptr, buf))) {
  547. aot_set_last_error("llvm build load failed.");
  548. return false;
  549. }
  550. cell_num += wasm_value_type_cell_num(wasm_ret_types[i]);
  551. }
  552. *p_res = res;
  553. return true;
  554. }
  555. bool
  556. aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  557. uint32 type_idx)
  558. {
  559. AOTFuncType *func_type;
  560. LLVMValueRef elem_idx, ftype_idx;
  561. LLVMValueRef *param_values = NULL, *value_rets = NULL, res = NULL;
  562. LLVMTypeRef *param_types = NULL;
  563. int32 i, param_count, result_count;
  564. uint32 param_cell_num;
  565. uint64 total_size;
  566. uint8 *wasm_ret_types = NULL;
  567. bool ret = false;
  568. /* Check function type index */
  569. if (type_idx >= comp_ctx->comp_data->func_type_count) {
  570. aot_set_last_error("type index is overflow");
  571. return false;
  572. }
  573. ftype_idx = I32_CONST(type_idx);
  574. CHECK_LLVM_CONST(ftype_idx);
  575. func_type = comp_ctx->comp_data->func_types[type_idx];
  576. param_cell_num = func_type->param_cell_num;
  577. result_count = func_type->result_count;
  578. wasm_ret_types = func_type->types + func_type->param_count;
  579. POP_I32(elem_idx);
  580. /* Initialize parameter types of the LLVM function */
  581. param_count = (int32)func_type->param_count;
  582. total_size = sizeof(LLVMTypeRef) * (uint64)param_count;
  583. if (total_size >= UINT32_MAX
  584. || !(param_types = wasm_runtime_malloc((uint32)total_size))) {
  585. aot_set_last_error("Allocate memory failed.");
  586. goto fail;
  587. }
  588. for (i = 0; i < param_count; i++)
  589. param_types[i] = TO_LLVM_TYPE(func_type->types[i]);
  590. /* Allocate memory for parameters */
  591. total_size = sizeof(LLVMValueRef) * (uint64)param_count;
  592. if (total_size >= UINT32_MAX
  593. || !(param_values = wasm_runtime_malloc((uint32)total_size))) {
  594. aot_set_last_error("Allocate memory failed.");
  595. goto fail;
  596. }
  597. /* Pop parameters from stack */
  598. for (i = param_count - 1; i >= 0; i--)
  599. POP(param_values[i], func_type->types[i]);
  600. /* Allocate memory for result values */
  601. total_size = sizeof(LLVMValueRef) * (uint64)result_count;
  602. if (total_size >= UINT32_MAX
  603. || !(value_rets = wasm_runtime_malloc((uint32)total_size))) {
  604. aot_set_last_error("Allocate memory failed.");
  605. goto fail;
  606. }
  607. memset(value_rets, 0, total_size);
  608. if (!call_aot_call_indirect_func(comp_ctx, func_ctx,
  609. func_type, ftype_idx, elem_idx,
  610. param_types, param_values,
  611. param_count, param_cell_num,
  612. result_count, wasm_ret_types,
  613. value_rets, &res))
  614. goto fail;
  615. for (i = 0; i < func_type->result_count; i++)
  616. PUSH(value_rets[i], func_type->types[func_type->param_count + i]);
  617. /* Check whether there was exception thrown when executing the function */
  618. if (!check_call_return(comp_ctx, func_ctx, res))
  619. goto fail;
  620. ret = true;
  621. fail:
  622. if (value_rets)
  623. wasm_runtime_free(value_rets);
  624. if (param_values)
  625. wasm_runtime_free(param_values);
  626. if (param_types)
  627. wasm_runtime_free(param_types);
  628. return ret;
  629. }