aot_emit_control.c 43 KB

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