aot_emit_control.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  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_control.h"
  6. #include "aot_emit_exception.h"
  7. #include "../aot/aot_runtime.h"
  8. #include "../interpreter/wasm_loader.h"
  9. static char *block_name_prefix[] = { "block", "loop", "if" };
  10. static char *block_name_suffix[] = { "begin", "else", "end" };
  11. enum {
  12. LABEL_BEGIN = 0,
  13. LABEL_ELSE,
  14. LABEL_END
  15. };
  16. static void
  17. format_block_name(char *name, uint32 name_size,
  18. uint32 block_index, uint32 label_type,
  19. uint32 label_id)
  20. {
  21. if (label_type != LABEL_TYPE_FUNCTION)
  22. snprintf(name, name_size, "%s%d%s%s",
  23. block_name_prefix[label_type], block_index,
  24. "_", block_name_suffix[label_id]);
  25. else
  26. snprintf(name, name_size, "%s", "func_end");
  27. }
  28. #define CREATE_BLOCK(new_llvm_block, name) do { \
  29. if (!(new_llvm_block = \
  30. LLVMAppendBasicBlockInContext(comp_ctx->context, \
  31. func_ctx->func, \
  32. name))) { \
  33. aot_set_last_error("add LLVM basic block failed.");\
  34. goto fail; \
  35. } \
  36. } while (0)
  37. #define CURR_BLOCK() LLVMGetInsertBlock(comp_ctx->builder)
  38. #define MOVE_BLOCK_AFTER(llvm_block, llvm_block_after) \
  39. LLVMMoveBasicBlockAfter(llvm_block, llvm_block_after)
  40. #define MOVE_BLOCK_AFTER_CURR(llvm_block) \
  41. LLVMMoveBasicBlockAfter(llvm_block, CURR_BLOCK())
  42. #define MOVE_BLOCK_BEFORE(llvm_block, llvm_block_before) \
  43. LLVMMoveBasicBlockBefore(llvm_block, llvm_block_before)
  44. #define BUILD_BR(llvm_block) do { \
  45. if (!LLVMBuildBr(comp_ctx->builder, llvm_block)) { \
  46. aot_set_last_error("llvm build br failed."); \
  47. goto fail; \
  48. } \
  49. } while (0)
  50. #define BUILD_COND_BR(value_if, block_then, block_else) do {\
  51. if (!LLVMBuildCondBr(comp_ctx->builder, value_if, \
  52. block_then, block_else)) { \
  53. aot_set_last_error("llvm build cond br failed."); \
  54. goto fail; \
  55. } \
  56. } while (0)
  57. #define SET_BUILDER_POS(llvm_block) \
  58. LLVMPositionBuilderAtEnd(comp_ctx->builder, llvm_block)
  59. #define CREATE_RESULT_VALUE_PHIS(block) do { \
  60. if (block->result_count && !block->result_phis) { \
  61. uint32 i; \
  62. uint64 size; \
  63. LLVMBasicBlockRef block_curr = CURR_BLOCK(); \
  64. /* Allocate memory */ \
  65. size = sizeof(LLVMValueRef) * (uint64)block->result_count; \
  66. if (size >= UINT32_MAX \
  67. || !(block->result_phis = \
  68. wasm_runtime_malloc((uint32)size))) { \
  69. aot_set_last_error("allocate memory failed."); \
  70. goto fail; \
  71. } \
  72. SET_BUILDER_POS(block->llvm_end_block); \
  73. for (i = 0; i < block->result_count; i++) { \
  74. if (!(block->result_phis[i] = \
  75. LLVMBuildPhi(comp_ctx->builder, \
  76. TO_LLVM_TYPE(block->result_types[i]), \
  77. "phi"))) { \
  78. aot_set_last_error("llvm build phi failed."); \
  79. goto fail; \
  80. } \
  81. } \
  82. SET_BUILDER_POS(block_curr); \
  83. } \
  84. } while (0)
  85. #define ADD_TO_RESULT_PHIS(block, value, idx) do { \
  86. LLVMBasicBlockRef block_curr = CURR_BLOCK(); \
  87. LLVMAddIncoming(block->result_phis[idx], \
  88. &value, &block_curr, 1); \
  89. } while (0)
  90. #define BUILD_ICMP(op, left, right, res, name) do { \
  91. if (!(res = LLVMBuildICmp(comp_ctx->builder, op, \
  92. left, right, name))) { \
  93. aot_set_last_error("llvm build icmp failed."); \
  94. goto fail; \
  95. } \
  96. } while (0)
  97. #define ADD_TO_PARAM_PHIS(block, value, idx) do { \
  98. LLVMBasicBlockRef block_curr = CURR_BLOCK(); \
  99. LLVMAddIncoming(block->param_phis[idx], \
  100. &value, &block_curr, 1); \
  101. } while (0)
  102. static LLVMBasicBlockRef
  103. find_next_llvm_end_block(AOTBlock *block)
  104. {
  105. block = block->prev;
  106. while (block && !block->llvm_end_block)
  107. block = block->prev;
  108. return block ? block->llvm_end_block : NULL;
  109. }
  110. static AOTBlock*
  111. get_target_block(AOTFuncContext *func_ctx, uint32 br_depth)
  112. {
  113. uint32 i = br_depth;
  114. AOTBlock *block = func_ctx->block_stack.block_list_end;
  115. while (i-- > 0 && block) {
  116. block = block->prev;
  117. }
  118. if (!block) {
  119. aot_set_last_error("WASM block stack underflow.");
  120. return NULL;
  121. }
  122. return block;
  123. }
  124. static bool
  125. handle_next_reachable_block(AOTCompContext *comp_ctx,
  126. AOTFuncContext *func_ctx,
  127. uint8 **p_frame_ip)
  128. {
  129. AOTBlock *block = func_ctx->block_stack.block_list_end;
  130. AOTBlock *block_prev;
  131. uint8 *frame_ip;
  132. uint32 i;
  133. AOTFuncType *func_type;
  134. aot_checked_addr_list_destroy(func_ctx);
  135. if (block->label_type == LABEL_TYPE_IF
  136. && block->llvm_else_block
  137. && !block->skip_wasm_code_else
  138. && *p_frame_ip <= block->wasm_code_else) {
  139. /* Clear value stack and start to translate else branch */
  140. aot_value_stack_destroy(&block->value_stack);
  141. /* Recover parameters of else branch */
  142. for (i = 0; i < block->param_count; i++)
  143. PUSH(block->else_param_phis[i], block->param_types[i]);
  144. SET_BUILDER_POS(block->llvm_else_block);
  145. *p_frame_ip = block->wasm_code_else + 1;
  146. return true;
  147. }
  148. while (block && !block->is_reachable) {
  149. block_prev = block->prev;
  150. block = aot_block_stack_pop(&func_ctx->block_stack);
  151. if (block->label_type == LABEL_TYPE_IF) {
  152. if (block->llvm_else_block
  153. && !block->skip_wasm_code_else
  154. && *p_frame_ip <= block->wasm_code_else) {
  155. /* Clear value stack and start to translate else branch */
  156. aot_value_stack_destroy(&block->value_stack);
  157. SET_BUILDER_POS(block->llvm_else_block);
  158. *p_frame_ip = block->wasm_code_else + 1;
  159. /* Push back the block */
  160. aot_block_stack_push(&func_ctx->block_stack, block);
  161. return true;
  162. }
  163. else if (block->llvm_end_block) {
  164. /* Remove unreachable basic block */
  165. LLVMDeleteBasicBlock(block->llvm_end_block);
  166. block->llvm_end_block = NULL;
  167. }
  168. }
  169. frame_ip = block->wasm_code_end;
  170. aot_block_destroy(block);
  171. block = block_prev;
  172. }
  173. if (!block) {
  174. *p_frame_ip = frame_ip + 1;
  175. return true;
  176. }
  177. *p_frame_ip = block->wasm_code_end + 1;
  178. SET_BUILDER_POS(block->llvm_end_block);
  179. /* Pop block, push its return value, and destroy the block */
  180. block = aot_block_stack_pop(&func_ctx->block_stack);
  181. func_type = func_ctx->aot_func->func_type;
  182. for (i = 0; i < block->result_count; i++) {
  183. bh_assert(block->result_phis[i]);
  184. if (block->label_type != LABEL_TYPE_FUNCTION) {
  185. PUSH(block->result_phis[i], block->result_types[i]);
  186. }
  187. else {
  188. /* Store extra return values to function parameters */
  189. if (i != 0) {
  190. uint32 param_index = func_type->param_count + i;
  191. if (!LLVMBuildStore(comp_ctx->builder,
  192. block->result_phis[i],
  193. LLVMGetParam(func_ctx->func, param_index))) {
  194. aot_set_last_error("llvm build store failed.");
  195. goto fail;
  196. }
  197. }
  198. }
  199. }
  200. if (block->label_type == LABEL_TYPE_FUNCTION) {
  201. if (block->result_count) {
  202. /* Return the first return value */
  203. if (!LLVMBuildRet(comp_ctx->builder, block->result_phis[0])) {
  204. aot_set_last_error("llvm build return failed.");
  205. goto fail;
  206. }
  207. }
  208. else {
  209. if (!LLVMBuildRetVoid(comp_ctx->builder)) {
  210. aot_set_last_error("llvm build return void failed.");
  211. goto fail;
  212. }
  213. }
  214. }
  215. aot_block_destroy(block);
  216. return true;
  217. fail:
  218. return false;
  219. }
  220. static bool
  221. push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx,
  222. AOTFuncContext *func_ctx,
  223. AOTBlock *block)
  224. {
  225. uint32 i, param_index;
  226. LLVMValueRef value;
  227. uint64 size;
  228. char name[32];
  229. LLVMBasicBlockRef block_curr = CURR_BLOCK();
  230. if (block->param_count) {
  231. size = sizeof(LLVMValueRef) * (uint64)block->param_count;
  232. if (size >= UINT32_MAX
  233. || !(block->param_phis = wasm_runtime_malloc((uint32)size))) {
  234. aot_set_last_error("allocate memory failed.");
  235. return false;
  236. }
  237. if (block->label_type == LABEL_TYPE_IF
  238. && !block->skip_wasm_code_else
  239. && !(block->else_param_phis = wasm_runtime_malloc((uint32)size))) {
  240. wasm_runtime_free(block->param_phis);
  241. block->param_phis = NULL;
  242. aot_set_last_error("allocate memory failed.");
  243. return false;
  244. }
  245. /* Create param phis */
  246. for (i = 0; i < block->param_count; i++) {
  247. SET_BUILDER_POS(block->llvm_entry_block);
  248. snprintf(name, sizeof(name), "%s%d_phi%d",
  249. block_name_prefix[block->label_type],
  250. block->block_index, i);
  251. if (!(block->param_phis[i] =
  252. LLVMBuildPhi(comp_ctx->builder,
  253. TO_LLVM_TYPE(block->param_types[i]),
  254. name))) {
  255. aot_set_last_error("llvm build phi failed.");
  256. goto fail;
  257. }
  258. if (block->label_type == LABEL_TYPE_IF
  259. && !block->skip_wasm_code_else
  260. && block->llvm_else_block) {
  261. /* Build else param phis */
  262. SET_BUILDER_POS(block->llvm_else_block);
  263. snprintf(name, sizeof(name), "else%d_phi%d",
  264. block->block_index, i);
  265. if (!(block->else_param_phis[i] =
  266. LLVMBuildPhi(comp_ctx->builder,
  267. TO_LLVM_TYPE(block->param_types[i]),
  268. name))) {
  269. aot_set_last_error("llvm build phi failed.");
  270. goto fail;
  271. }
  272. }
  273. }
  274. SET_BUILDER_POS(block_curr);
  275. /* Pop param values from current block's
  276. * value stack and add to param phis.
  277. */
  278. for (i = 0; i < block->param_count; i++) {
  279. param_index = block->param_count - 1 - i;
  280. POP(value, block->param_types[param_index]);
  281. ADD_TO_PARAM_PHIS(block, value, param_index);
  282. if (block->label_type == LABEL_TYPE_IF
  283. && !block->skip_wasm_code_else) {
  284. if (block->llvm_else_block) {
  285. /* has else branch, add to else param phis */
  286. LLVMAddIncoming(block->else_param_phis[param_index],
  287. &value, &block_curr, 1);
  288. }
  289. else {
  290. /* no else branch, add to result phis */
  291. CREATE_RESULT_VALUE_PHIS(block);
  292. ADD_TO_RESULT_PHIS(block, value, param_index);
  293. }
  294. }
  295. }
  296. }
  297. /* Push the new block to block stack */
  298. aot_block_stack_push(&func_ctx->block_stack, block);
  299. /* Push param phis to the new block */
  300. for (i = 0; i < block->param_count; i++) {
  301. PUSH(block->param_phis[i], block->param_types[i]);
  302. }
  303. return true;
  304. fail:
  305. if (block->param_phis) {
  306. wasm_runtime_free(block->param_phis);
  307. block->param_phis = NULL;
  308. }
  309. if (block->else_param_phis) {
  310. wasm_runtime_free(block->else_param_phis);
  311. block->else_param_phis = NULL;
  312. }
  313. return false;
  314. }
  315. bool
  316. aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  317. uint8 **p_frame_ip, uint8 *frame_ip_end,
  318. uint32 label_type, uint32 param_count, uint8 *param_types,
  319. uint32 result_count, uint8 *result_types)
  320. {
  321. BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
  322. AOTBlock *block;
  323. uint8 *else_addr, *end_addr;
  324. LLVMValueRef value;
  325. char name[32];
  326. /* Check block stack */
  327. if (!func_ctx->block_stack.block_list_end) {
  328. aot_set_last_error("WASM block stack underflow.");
  329. return false;
  330. }
  331. memset(block_addr_cache, 0, sizeof(block_addr_cache));
  332. /* Get block info */
  333. if (!(wasm_loader_find_block_addr((BlockAddr*)block_addr_cache,
  334. *p_frame_ip, frame_ip_end, (uint8)label_type,
  335. &else_addr, &end_addr, NULL, 0))) {
  336. aot_set_last_error("find block end addr failed.");
  337. return false;
  338. }
  339. /* Allocate memory */
  340. if (!(block = wasm_runtime_malloc(sizeof(AOTBlock)))) {
  341. aot_set_last_error("allocate memory failed.");
  342. return false;
  343. }
  344. memset(block, 0, sizeof(AOTBlock));
  345. if (param_count
  346. && !(block->param_types = wasm_runtime_malloc(param_count))) {
  347. aot_set_last_error("allocate memory failed.");
  348. goto fail;
  349. }
  350. if (result_count) {
  351. if (!(block->result_types = wasm_runtime_malloc(result_count))) {
  352. aot_set_last_error("allocate memory failed.");
  353. goto fail;
  354. }
  355. }
  356. /* Init aot block data */
  357. block->label_type = label_type;
  358. block->param_count = param_count;
  359. memcpy(block->param_types, param_types, param_count);
  360. block->result_count = result_count;
  361. memcpy(block->result_types, result_types, result_count);
  362. block->wasm_code_else = else_addr;
  363. block->wasm_code_end = end_addr;
  364. block->block_index = func_ctx->block_stack.block_index[label_type];
  365. func_ctx->block_stack.block_index[label_type]++;
  366. if (label_type == LABEL_TYPE_BLOCK
  367. || label_type == LABEL_TYPE_LOOP) {
  368. /* Create block */
  369. format_block_name(name, sizeof(name),
  370. block->block_index, label_type, LABEL_BEGIN);
  371. CREATE_BLOCK(block->llvm_entry_block, name);
  372. MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
  373. /* Jump to the entry block */
  374. BUILD_BR(block->llvm_entry_block);
  375. if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
  376. goto fail;
  377. /* Start to translate the block */
  378. SET_BUILDER_POS(block->llvm_entry_block);
  379. if (label_type == LABEL_TYPE_LOOP)
  380. aot_checked_addr_list_destroy(func_ctx);
  381. }
  382. else if (label_type == LABEL_TYPE_IF) {
  383. POP_COND(value);
  384. if (!LLVMIsConstant(value)) {
  385. /* Compare value is not constant, create condition br IR */
  386. /* Create entry block */
  387. format_block_name(name, sizeof(name),
  388. block->block_index, label_type, LABEL_BEGIN);
  389. CREATE_BLOCK(block->llvm_entry_block, name);
  390. MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
  391. /* Create end block */
  392. format_block_name(name, sizeof(name),
  393. block->block_index, label_type, LABEL_END);
  394. CREATE_BLOCK(block->llvm_end_block, name);
  395. MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_entry_block);
  396. if (else_addr) {
  397. /* Create else block */
  398. format_block_name(name, sizeof(name),
  399. block->block_index, label_type, LABEL_ELSE);
  400. CREATE_BLOCK(block->llvm_else_block, name);
  401. MOVE_BLOCK_AFTER(block->llvm_else_block, block->llvm_entry_block);
  402. /* Create condition br IR */
  403. BUILD_COND_BR(value, block->llvm_entry_block,
  404. block->llvm_else_block);
  405. }
  406. else {
  407. /* Create condition br IR */
  408. BUILD_COND_BR(value, block->llvm_entry_block,
  409. block->llvm_end_block);
  410. block->is_reachable = true;
  411. }
  412. if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
  413. goto fail;
  414. /* Start to translate if branch of BLOCK if */
  415. SET_BUILDER_POS(block->llvm_entry_block);
  416. }
  417. else {
  418. if ((int32)LLVMConstIntGetZExtValue(value) != 0) {
  419. /* Compare value is not 0, condition is true, else branch of
  420. BLOCK if cannot be reached */
  421. block->skip_wasm_code_else = true;
  422. /* Create entry block */
  423. format_block_name(name, sizeof(name),
  424. block->block_index, label_type, LABEL_BEGIN);
  425. CREATE_BLOCK(block->llvm_entry_block, name);
  426. MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
  427. /* Jump to the entry block */
  428. BUILD_BR(block->llvm_entry_block);
  429. if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
  430. goto fail;
  431. /* Start to translate the if branch */
  432. SET_BUILDER_POS(block->llvm_entry_block);
  433. }
  434. else {
  435. /* Compare value is not 0, condition is false, if branch of
  436. BLOCK if cannot be reached */
  437. if (else_addr) {
  438. /* Create else block */
  439. format_block_name(name, sizeof(name),
  440. block->block_index, label_type, LABEL_ELSE);
  441. CREATE_BLOCK(block->llvm_else_block, name);
  442. MOVE_BLOCK_AFTER_CURR(block->llvm_else_block);
  443. /* Jump to the else block */
  444. BUILD_BR(block->llvm_else_block);
  445. if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
  446. goto fail;
  447. /* Start to translate the else branch */
  448. SET_BUILDER_POS(block->llvm_else_block);
  449. *p_frame_ip = else_addr + 1;
  450. }
  451. else {
  452. /* skip the block */
  453. aot_block_destroy(block);
  454. *p_frame_ip = end_addr + 1;
  455. }
  456. }
  457. }
  458. }
  459. else {
  460. aot_set_last_error("Invalid block type.");
  461. goto fail;
  462. }
  463. return true;
  464. fail:
  465. aot_block_destroy(block);
  466. return false;
  467. }
  468. bool
  469. aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  470. uint8 **p_frame_ip)
  471. {
  472. AOTBlock *block = func_ctx->block_stack.block_list_end;
  473. LLVMValueRef value;
  474. char name[32];
  475. uint32 i, result_index;
  476. /* Check block */
  477. if (!block) {
  478. aot_set_last_error("WASM block stack underflow.");
  479. return false;
  480. }
  481. if (block->label_type != LABEL_TYPE_IF
  482. || (!block->skip_wasm_code_else
  483. && !block->llvm_else_block)) {
  484. aot_set_last_error("Invalid WASM block type.");
  485. return false;
  486. }
  487. /* Create end block if needed */
  488. if (!block->llvm_end_block) {
  489. format_block_name(name, sizeof(name),
  490. block->block_index, block->label_type, LABEL_END);
  491. CREATE_BLOCK(block->llvm_end_block, name);
  492. if (block->llvm_else_block)
  493. MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_else_block);
  494. else
  495. MOVE_BLOCK_AFTER_CURR(block->llvm_end_block);
  496. }
  497. block->is_reachable = true;
  498. /* Comes from the if branch of BLOCK if */
  499. CREATE_RESULT_VALUE_PHIS(block);
  500. for (i = 0; i < block->result_count; i++) {
  501. result_index = block->result_count - 1 - i;
  502. POP(value, block->result_types[result_index]);
  503. ADD_TO_RESULT_PHIS(block, value, result_index);
  504. }
  505. /* Jump to end block */
  506. BUILD_BR(block->llvm_end_block);
  507. if (!block->skip_wasm_code_else
  508. && block->llvm_else_block) {
  509. /* Clear value stack, recover param values
  510. * and start to translate else branch.
  511. */
  512. aot_value_stack_destroy(&block->value_stack);
  513. for (i = 0; i < block->param_count; i++)
  514. PUSH(block->else_param_phis[i], block->param_types[i]);
  515. SET_BUILDER_POS(block->llvm_else_block);
  516. aot_checked_addr_list_destroy(func_ctx);
  517. return true;
  518. }
  519. /* No else branch or no need to translate else branch */
  520. block->is_reachable = true;
  521. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  522. fail:
  523. return false;
  524. }
  525. bool
  526. aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  527. uint8 **p_frame_ip)
  528. {
  529. AOTBlock *block;
  530. LLVMValueRef value;
  531. LLVMBasicBlockRef next_llvm_end_block;
  532. char name[32];
  533. uint32 i, result_index;
  534. /* Check block stack */
  535. if (!(block = func_ctx->block_stack.block_list_end)) {
  536. aot_set_last_error("WASM block stack underflow.");
  537. return false;
  538. }
  539. /* Create the end block */
  540. if (!block->llvm_end_block) {
  541. format_block_name(name, sizeof(name),
  542. block->block_index, block->label_type, LABEL_END);
  543. CREATE_BLOCK(block->llvm_end_block, name);
  544. if ((next_llvm_end_block = find_next_llvm_end_block(block)))
  545. MOVE_BLOCK_BEFORE(block->llvm_end_block, next_llvm_end_block);
  546. }
  547. /* Handle block result values */
  548. CREATE_RESULT_VALUE_PHIS(block);
  549. for (i = 0; i < block->result_count; i++) {
  550. result_index = block->result_count - 1 - i;
  551. POP(value, block->result_types[result_index]);
  552. ADD_TO_RESULT_PHIS(block, value, result_index);
  553. }
  554. /* Jump to the end block */
  555. BUILD_BR(block->llvm_end_block);
  556. block->is_reachable = true;
  557. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  558. fail:
  559. return false;
  560. }
  561. #if WASM_ENABLE_THREAD_MGR != 0
  562. bool
  563. check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  564. {
  565. LLVMValueRef terminate_addr, terminate_flags, flag, offset, res;
  566. LLVMBasicBlockRef terminate_check_block, non_terminate_block;
  567. AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
  568. LLVMBasicBlockRef terminate_block;
  569. /* Offset of suspend_flags */
  570. offset = I32_CONST(5);
  571. CHECK_LLVM_CONST(offset);
  572. if (!(terminate_addr =
  573. LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,
  574. &offset, 1, "terminate_addr"))) {
  575. aot_set_last_error("llvm build in bounds gep failed");
  576. return false;
  577. }
  578. if (!(terminate_addr =
  579. LLVMBuildBitCast(comp_ctx->builder,
  580. terminate_addr,
  581. INT32_PTR_TYPE, "terminate_addr_ptr"))) {
  582. aot_set_last_error("llvm build bit cast failed");
  583. return false;
  584. }
  585. if (!(terminate_flags =
  586. LLVMBuildLoad(comp_ctx->builder,
  587. terminate_addr, "terminate_flags"))) {
  588. aot_set_last_error("llvm build bit cast failed");
  589. return false;
  590. }
  591. /* Set terminate_flags memory accecc to volatile, so that the value
  592. will always be loaded from memory rather than register */
  593. LLVMSetVolatile(terminate_flags, true);
  594. CREATE_BLOCK(terminate_check_block, "terminate_check");
  595. MOVE_BLOCK_AFTER_CURR(terminate_check_block);
  596. CREATE_BLOCK(non_terminate_block, "non_terminate");
  597. MOVE_BLOCK_AFTER_CURR(non_terminate_block);
  598. BUILD_ICMP(LLVMIntSGT, terminate_flags, I32_ZERO, res, "need_terminate");
  599. BUILD_COND_BR(res, terminate_check_block, non_terminate_block);
  600. /* Move builder to terminate check block */
  601. SET_BUILDER_POS(terminate_check_block);
  602. CREATE_BLOCK(terminate_block, "terminate");
  603. MOVE_BLOCK_AFTER_CURR(terminate_block);
  604. if (!(flag =
  605. LLVMBuildAnd(comp_ctx->builder, terminate_flags,
  606. I32_ONE, "termination_flag"))) {
  607. aot_set_last_error("llvm build AND failed");
  608. return false;
  609. }
  610. BUILD_ICMP(LLVMIntSGT, flag, I32_ZERO, res, "need_terminate");
  611. BUILD_COND_BR(res, terminate_block, non_terminate_block);
  612. /* Move builder to terminate block */
  613. SET_BUILDER_POS(terminate_block);
  614. if (aot_func_type->result_count) {
  615. switch (aot_func_type->types[aot_func_type->param_count]) {
  616. case VALUE_TYPE_I32:
  617. LLVMBuildRet(comp_ctx->builder, I32_ZERO);
  618. break;
  619. case VALUE_TYPE_I64:
  620. LLVMBuildRet(comp_ctx->builder, I64_ZERO);
  621. break;
  622. case VALUE_TYPE_F32:
  623. LLVMBuildRet(comp_ctx->builder, F32_ZERO);
  624. break;
  625. case VALUE_TYPE_F64:
  626. LLVMBuildRet(comp_ctx->builder, F64_ZERO);
  627. break;
  628. }
  629. }
  630. else {
  631. LLVMBuildRetVoid(comp_ctx->builder);
  632. }
  633. /* Move builder to terminate block */
  634. SET_BUILDER_POS(non_terminate_block);
  635. return true;
  636. fail:
  637. return false;
  638. }
  639. #endif /* End of WASM_ENABLE_THREAD_MGR */
  640. bool
  641. aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  642. uint32 br_depth, uint8 **p_frame_ip)
  643. {
  644. AOTBlock *block_dst;
  645. LLVMValueRef value_ret, value_param;
  646. LLVMBasicBlockRef next_llvm_end_block;
  647. char name[32];
  648. uint32 i, param_index, result_index;
  649. #if WASM_ENABLE_THREAD_MGR != 0
  650. /* Insert suspend check point */
  651. if (comp_ctx->enable_thread_mgr) {
  652. if (!check_suspend_flags(comp_ctx, func_ctx))
  653. return false;
  654. }
  655. #endif
  656. if (!(block_dst = get_target_block(func_ctx, br_depth))) {
  657. return false;
  658. }
  659. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  660. /* Dest block is Loop block */
  661. /* Handle Loop parameters */
  662. for (i = 0; i < block_dst->param_count; i++) {
  663. param_index = block_dst->param_count - 1 - i;
  664. POP(value_param, block_dst->param_types[param_index]);
  665. ADD_TO_PARAM_PHIS(block_dst, value_param, param_index);
  666. }
  667. BUILD_BR(block_dst->llvm_entry_block);
  668. }
  669. else {
  670. /* Dest block is Block/If/Function block */
  671. /* Create the end block */
  672. if (!block_dst->llvm_end_block) {
  673. format_block_name(name, sizeof(name),
  674. block_dst->block_index, block_dst->label_type,
  675. LABEL_END);
  676. CREATE_BLOCK(block_dst->llvm_end_block, name);
  677. if ((next_llvm_end_block = find_next_llvm_end_block(block_dst)))
  678. MOVE_BLOCK_BEFORE(block_dst->llvm_end_block,
  679. next_llvm_end_block);
  680. }
  681. block_dst->is_reachable = true;
  682. /* Handle result values */
  683. CREATE_RESULT_VALUE_PHIS(block_dst);
  684. for (i = 0; i < block_dst->result_count; i++) {
  685. result_index = block_dst->result_count - 1 - i;
  686. POP(value_ret, block_dst->result_types[result_index]);
  687. ADD_TO_RESULT_PHIS(block_dst, value_ret, result_index);
  688. }
  689. /* Jump to the end block */
  690. BUILD_BR(block_dst->llvm_end_block);
  691. }
  692. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  693. fail:
  694. return false;
  695. }
  696. bool
  697. aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  698. uint32 br_depth, uint8 **p_frame_ip)
  699. {
  700. AOTBlock *block_dst;
  701. LLVMValueRef value_cmp, value, *values = NULL;
  702. LLVMBasicBlockRef llvm_else_block, next_llvm_end_block;
  703. char name[32];
  704. uint32 i, param_index, result_index;
  705. uint64 size;
  706. #if WASM_ENABLE_THREAD_MGR != 0
  707. /* Insert suspend check point */
  708. if (comp_ctx->enable_thread_mgr) {
  709. if (!check_suspend_flags(comp_ctx, func_ctx))
  710. return false;
  711. }
  712. #endif
  713. POP_COND(value_cmp);
  714. if (!LLVMIsConstant(value_cmp)) {
  715. /* Compare value is not constant, create condition br IR */
  716. if (!(block_dst = get_target_block(func_ctx, br_depth))) {
  717. return false;
  718. }
  719. /* Create llvm else block */
  720. CREATE_BLOCK(llvm_else_block, "br_if_else");
  721. MOVE_BLOCK_AFTER_CURR(llvm_else_block);
  722. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  723. /* Dest block is Loop block */
  724. /* Handle Loop parameters */
  725. if (block_dst->param_count) {
  726. size = sizeof(LLVMValueRef) * (uint64)block_dst->param_count;
  727. if (size >= UINT32_MAX
  728. || !(values = wasm_runtime_malloc((uint32)size))) {
  729. aot_set_last_error("allocate memory failed.");
  730. goto fail;
  731. }
  732. for (i = 0; i < block_dst->param_count; i++) {
  733. param_index = block_dst->param_count - 1 - i;
  734. POP(value, block_dst->param_types[param_index]);
  735. ADD_TO_PARAM_PHIS(block_dst, value, param_index);
  736. values[param_index] = value;
  737. }
  738. for (i = 0; i < block_dst->param_count; i++) {
  739. PUSH(values[i], block_dst->param_types[i]);
  740. }
  741. wasm_runtime_free(values);
  742. values = NULL;
  743. }
  744. BUILD_COND_BR(value_cmp, block_dst->llvm_entry_block,
  745. llvm_else_block);
  746. /* Move builder to else block */
  747. SET_BUILDER_POS(llvm_else_block);
  748. }
  749. else {
  750. /* Dest block is Block/If/Function block */
  751. /* Create the end block */
  752. if (!block_dst->llvm_end_block) {
  753. format_block_name(name, sizeof(name),
  754. block_dst->block_index, block_dst->label_type,
  755. LABEL_END);
  756. CREATE_BLOCK(block_dst->llvm_end_block, name);
  757. if ((next_llvm_end_block = find_next_llvm_end_block(block_dst)))
  758. MOVE_BLOCK_BEFORE(block_dst->llvm_end_block,
  759. next_llvm_end_block);
  760. }
  761. /* Set reachable flag and create condition br IR */
  762. block_dst->is_reachable = true;
  763. /* Handle result values */
  764. if (block_dst->result_count) {
  765. size = sizeof(LLVMValueRef) * (uint64)block_dst->result_count;
  766. if (size >= UINT32_MAX
  767. || !(values = wasm_runtime_malloc((uint32)size))) {
  768. aot_set_last_error("allocate memory failed.");
  769. goto fail;
  770. }
  771. CREATE_RESULT_VALUE_PHIS(block_dst);
  772. for (i = 0; i < block_dst->result_count; i++) {
  773. result_index = block_dst->result_count - 1 - i;
  774. POP(value, block_dst->result_types[result_index]);
  775. values[result_index] = value;
  776. ADD_TO_RESULT_PHIS(block_dst, value, result_index);
  777. }
  778. for (i = 0; i < block_dst->result_count; i++) {
  779. PUSH(values[i], block_dst->result_types[i]);
  780. }
  781. wasm_runtime_free(values);
  782. values = NULL;
  783. }
  784. /* Condition jump to end block */
  785. BUILD_COND_BR(value_cmp, block_dst->llvm_end_block,
  786. llvm_else_block);
  787. /* Move builder to else block */
  788. SET_BUILDER_POS(llvm_else_block);
  789. }
  790. }
  791. else {
  792. if ((int32)LLVMConstIntGetZExtValue(value_cmp) != 0) {
  793. /* Compare value is not 0, condition is true, same as op_br */
  794. return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip);
  795. }
  796. else {
  797. /* Compare value is not 0, condition is false, skip br_if */
  798. return true;
  799. }
  800. }
  801. return true;
  802. fail:
  803. if (values)
  804. wasm_runtime_free(values);
  805. return false;
  806. }
  807. bool
  808. aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  809. uint32 *br_depths, uint32 br_count,
  810. uint8 **p_frame_ip)
  811. {
  812. uint32 i, j;
  813. LLVMValueRef value_switch, value_cmp, value_case, value, *values = NULL;
  814. LLVMBasicBlockRef default_llvm_block = NULL, target_llvm_block;
  815. LLVMBasicBlockRef next_llvm_end_block;
  816. AOTBlock *target_block;
  817. uint32 br_depth, depth_idx;
  818. uint32 param_index, result_index;
  819. uint64 size;
  820. char name[32];
  821. #if WASM_ENABLE_THREAD_MGR != 0
  822. /* Insert suspend check point */
  823. if (comp_ctx->enable_thread_mgr) {
  824. if (!check_suspend_flags(comp_ctx, func_ctx))
  825. return false;
  826. }
  827. #endif
  828. POP_I32(value_cmp);
  829. if (!LLVMIsConstant(value_cmp)) {
  830. /* Compare value is not constant, create switch IR */
  831. for (i = 0; i <= br_count; i++) {
  832. target_block = get_target_block(func_ctx, br_depths[i]);
  833. if (!target_block)
  834. return false;
  835. if (target_block->label_type != LABEL_TYPE_LOOP) {
  836. /* Dest block is Block/If/Function block */
  837. /* Create the end block */
  838. if (!target_block->llvm_end_block) {
  839. format_block_name(name, sizeof(name),
  840. target_block->block_index,
  841. target_block->label_type,
  842. LABEL_END);
  843. CREATE_BLOCK(target_block->llvm_end_block, name);
  844. if ((next_llvm_end_block =
  845. find_next_llvm_end_block(target_block)))
  846. MOVE_BLOCK_BEFORE(target_block->llvm_end_block,
  847. next_llvm_end_block);
  848. }
  849. /* Handle result values */
  850. if (target_block->result_count) {
  851. size = sizeof(LLVMValueRef) * (uint64)target_block->result_count;
  852. if (size >= UINT32_MAX
  853. || !(values = wasm_runtime_malloc((uint32)size))) {
  854. aot_set_last_error("allocate memory failed.");
  855. goto fail;
  856. }
  857. CREATE_RESULT_VALUE_PHIS(target_block);
  858. for (j = 0; j < target_block->result_count; j++) {
  859. result_index = target_block->result_count - 1 - j;
  860. POP(value, target_block->result_types[result_index]);
  861. values[result_index] = value;
  862. ADD_TO_RESULT_PHIS(target_block, value, result_index);
  863. }
  864. for (j = 0; j < target_block->result_count; j++) {
  865. PUSH(values[j], target_block->result_types[j]);
  866. }
  867. wasm_runtime_free(values);
  868. }
  869. target_block->is_reachable = true;
  870. if (i == br_count)
  871. default_llvm_block = target_block->llvm_end_block;
  872. }
  873. else {
  874. /* Handle Loop parameters */
  875. if (target_block->param_count) {
  876. size = sizeof(LLVMValueRef) * (uint64)target_block->param_count;
  877. if (size >= UINT32_MAX
  878. || !(values = wasm_runtime_malloc((uint32)size))) {
  879. aot_set_last_error("allocate memory failed.");
  880. goto fail;
  881. }
  882. for (j = 0; j < target_block->param_count; j++) {
  883. param_index = target_block->param_count - 1 - j;
  884. POP(value, target_block->param_types[param_index]);
  885. values[param_index] = value;
  886. ADD_TO_PARAM_PHIS(target_block, value, param_index);
  887. }
  888. for (j = 0; j < target_block->param_count; j++) {
  889. PUSH(values[j], target_block->param_types[j]);
  890. }
  891. wasm_runtime_free(values);
  892. }
  893. if (i == br_count)
  894. default_llvm_block = target_block->llvm_entry_block;
  895. }
  896. }
  897. /* Create switch IR */
  898. if (!(value_switch = LLVMBuildSwitch(comp_ctx->builder, value_cmp,
  899. default_llvm_block, br_count))) {
  900. aot_set_last_error("llvm build switch failed.");
  901. return false;
  902. }
  903. /* Add each case for switch IR */
  904. for (i = 0; i < br_count; i++) {
  905. value_case = I32_CONST(i);
  906. CHECK_LLVM_CONST(value_case);
  907. target_block = get_target_block(func_ctx, br_depths[i]);
  908. if (!target_block)
  909. return false;
  910. target_llvm_block = target_block->label_type != LABEL_TYPE_LOOP
  911. ? target_block->llvm_end_block
  912. : target_block->llvm_entry_block;
  913. LLVMAddCase(value_switch, value_case, target_llvm_block);
  914. }
  915. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  916. }
  917. else {
  918. /* Compare value is constant, create br IR */
  919. depth_idx = (uint32)LLVMConstIntGetZExtValue(value_cmp);
  920. br_depth = br_depths[br_count];
  921. if (depth_idx < br_count) {
  922. br_depth = br_depths[depth_idx];
  923. }
  924. return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip);
  925. }
  926. fail:
  927. if (values)
  928. wasm_runtime_free(values);
  929. return false;
  930. }
  931. bool
  932. aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  933. uint8 **p_frame_ip)
  934. {
  935. AOTBlock *block_func = func_ctx->block_stack.block_list_head;
  936. LLVMValueRef value;
  937. AOTFuncType *func_type;
  938. uint32 i, param_index, result_index;
  939. bh_assert(block_func);
  940. func_type = func_ctx->aot_func->func_type;
  941. if (block_func->result_count) {
  942. /* Store extra result values to function parameters */
  943. for (i = 0; i < block_func->result_count - 1; i++) {
  944. result_index = block_func->result_count - 1 - i;
  945. POP(value, block_func->result_types[result_index]);
  946. param_index = func_type->param_count + result_index;
  947. if (!LLVMBuildStore(comp_ctx->builder,
  948. value,
  949. LLVMGetParam(func_ctx->func, param_index))) {
  950. aot_set_last_error("llvm build store failed.");
  951. goto fail;
  952. }
  953. }
  954. /* Return the first result value */
  955. POP(value, block_func->result_types[0]);
  956. if (!LLVMBuildRet(comp_ctx->builder, value)) {
  957. aot_set_last_error("llvm build return failed.");
  958. goto fail;
  959. }
  960. }
  961. else {
  962. if (!LLVMBuildRetVoid(comp_ctx->builder)) {
  963. aot_set_last_error("llvm build return void failed.");
  964. goto fail;
  965. }
  966. }
  967. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  968. fail:
  969. return false;
  970. }
  971. bool
  972. aot_compile_op_unreachable(AOTCompContext *comp_ctx,
  973. AOTFuncContext *func_ctx,
  974. uint8 **p_frame_ip)
  975. {
  976. if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_UNREACHABLE,
  977. false, NULL, NULL))
  978. return false;
  979. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  980. }
  981. bool
  982. aot_handle_next_reachable_block(AOTCompContext *comp_ctx,
  983. AOTFuncContext *func_ctx,
  984. uint8 **p_frame_ip)
  985. {
  986. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  987. }