aot_emit_control.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
  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. if (param_count) {
  380. bh_memcpy_s(block->param_types, param_count, param_types, param_count);
  381. }
  382. block->result_count = result_count;
  383. if (result_count) {
  384. bh_memcpy_s(block->result_types, result_count, result_types,
  385. result_count);
  386. }
  387. block->wasm_code_else = else_addr;
  388. block->wasm_code_end = end_addr;
  389. block->block_index = func_ctx->block_stack.block_index[label_type];
  390. func_ctx->block_stack.block_index[label_type]++;
  391. if (label_type == LABEL_TYPE_BLOCK || label_type == LABEL_TYPE_LOOP) {
  392. /* Create block */
  393. format_block_name(name, sizeof(name), block->block_index, label_type,
  394. LABEL_BEGIN);
  395. CREATE_BLOCK(block->llvm_entry_block, name);
  396. MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
  397. /* Jump to the entry block */
  398. BUILD_BR(block->llvm_entry_block);
  399. if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
  400. goto fail;
  401. /* Start to translate the block */
  402. SET_BUILDER_POS(block->llvm_entry_block);
  403. if (label_type == LABEL_TYPE_LOOP)
  404. aot_checked_addr_list_destroy(func_ctx);
  405. }
  406. else if (label_type == LABEL_TYPE_IF) {
  407. POP_COND(value);
  408. if (LLVMIsUndef(value)
  409. #if LLVM_VERSION_NUMBER >= 12
  410. || LLVMIsPoison(value)
  411. #endif
  412. ) {
  413. if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW,
  414. false, NULL, NULL))) {
  415. goto fail;
  416. }
  417. return aot_handle_next_reachable_block(comp_ctx, func_ctx,
  418. p_frame_ip);
  419. }
  420. if (!LLVMIsConstant(value)) {
  421. /* Compare value is not constant, create condition br IR */
  422. /* Create entry block */
  423. format_block_name(name, sizeof(name), block->block_index,
  424. label_type, LABEL_BEGIN);
  425. CREATE_BLOCK(block->llvm_entry_block, name);
  426. MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
  427. /* Create end block */
  428. format_block_name(name, sizeof(name), block->block_index,
  429. label_type, LABEL_END);
  430. CREATE_BLOCK(block->llvm_end_block, name);
  431. MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_entry_block);
  432. if (else_addr) {
  433. /* Create else block */
  434. format_block_name(name, sizeof(name), block->block_index,
  435. label_type, LABEL_ELSE);
  436. CREATE_BLOCK(block->llvm_else_block, name);
  437. MOVE_BLOCK_AFTER(block->llvm_else_block,
  438. block->llvm_entry_block);
  439. /* Create condition br IR */
  440. BUILD_COND_BR(value, block->llvm_entry_block,
  441. block->llvm_else_block);
  442. }
  443. else {
  444. /* Create condition br IR */
  445. BUILD_COND_BR(value, block->llvm_entry_block,
  446. block->llvm_end_block);
  447. block->is_reachable = true;
  448. }
  449. if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx,
  450. block))
  451. goto fail;
  452. /* Start to translate if branch of BLOCK if */
  453. SET_BUILDER_POS(block->llvm_entry_block);
  454. }
  455. else {
  456. if ((int32)LLVMConstIntGetZExtValue(value) != 0) {
  457. /* Compare value is not 0, condition is true, else branch of
  458. BLOCK if cannot be reached */
  459. block->skip_wasm_code_else = true;
  460. /* Create entry block */
  461. format_block_name(name, sizeof(name), block->block_index,
  462. label_type, LABEL_BEGIN);
  463. CREATE_BLOCK(block->llvm_entry_block, name);
  464. MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
  465. /* Jump to the entry block */
  466. BUILD_BR(block->llvm_entry_block);
  467. if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx,
  468. block))
  469. goto fail;
  470. /* Start to translate the if branch */
  471. SET_BUILDER_POS(block->llvm_entry_block);
  472. }
  473. else {
  474. /* Compare value is not 0, condition is false, if branch of
  475. BLOCK if cannot be reached */
  476. if (else_addr) {
  477. /* Create else block */
  478. format_block_name(name, sizeof(name), block->block_index,
  479. label_type, LABEL_ELSE);
  480. CREATE_BLOCK(block->llvm_else_block, name);
  481. MOVE_BLOCK_AFTER_CURR(block->llvm_else_block);
  482. /* Jump to the else block */
  483. BUILD_BR(block->llvm_else_block);
  484. if (!push_aot_block_to_stack_and_pass_params(
  485. comp_ctx, func_ctx, block))
  486. goto fail;
  487. /* Start to translate the else branch */
  488. SET_BUILDER_POS(block->llvm_else_block);
  489. *p_frame_ip = else_addr + 1;
  490. }
  491. else {
  492. /* skip the block */
  493. aot_block_destroy(block);
  494. *p_frame_ip = end_addr + 1;
  495. }
  496. }
  497. }
  498. }
  499. else {
  500. aot_set_last_error("Invalid block type.");
  501. goto fail;
  502. }
  503. return true;
  504. fail:
  505. aot_block_destroy(block);
  506. return false;
  507. }
  508. bool
  509. aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  510. uint8 **p_frame_ip)
  511. {
  512. AOTBlock *block = func_ctx->block_stack.block_list_end;
  513. LLVMValueRef value;
  514. char name[32];
  515. uint32 i, result_index;
  516. /* Check block */
  517. if (!block) {
  518. aot_set_last_error("WASM block stack underflow.");
  519. return false;
  520. }
  521. if (block->label_type != LABEL_TYPE_IF
  522. || (!block->skip_wasm_code_else && !block->llvm_else_block)) {
  523. aot_set_last_error("Invalid WASM block type.");
  524. return false;
  525. }
  526. /* Create end block if needed */
  527. if (!block->llvm_end_block) {
  528. format_block_name(name, sizeof(name), block->block_index,
  529. block->label_type, LABEL_END);
  530. CREATE_BLOCK(block->llvm_end_block, name);
  531. if (block->llvm_else_block)
  532. MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_else_block);
  533. else
  534. MOVE_BLOCK_AFTER_CURR(block->llvm_end_block);
  535. }
  536. block->is_reachable = true;
  537. /* Comes from the if branch of BLOCK if */
  538. CREATE_RESULT_VALUE_PHIS(block);
  539. for (i = 0; i < block->result_count; i++) {
  540. result_index = block->result_count - 1 - i;
  541. POP(value, block->result_types[result_index]);
  542. ADD_TO_RESULT_PHIS(block, value, result_index);
  543. }
  544. /* Jump to end block */
  545. BUILD_BR(block->llvm_end_block);
  546. if (!block->skip_wasm_code_else && block->llvm_else_block) {
  547. /* Clear value stack, recover param values
  548. * and start to translate else branch.
  549. */
  550. aot_value_stack_destroy(&block->value_stack);
  551. for (i = 0; i < block->param_count; i++)
  552. PUSH(block->else_param_phis[i], block->param_types[i]);
  553. SET_BUILDER_POS(block->llvm_else_block);
  554. aot_checked_addr_list_destroy(func_ctx);
  555. return true;
  556. }
  557. /* No else branch or no need to translate else branch */
  558. block->is_reachable = true;
  559. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  560. fail:
  561. return false;
  562. }
  563. bool
  564. aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  565. uint8 **p_frame_ip)
  566. {
  567. AOTBlock *block;
  568. LLVMValueRef value;
  569. LLVMBasicBlockRef next_llvm_end_block;
  570. char name[32];
  571. uint32 i, result_index;
  572. /* Check block stack */
  573. if (!(block = func_ctx->block_stack.block_list_end)) {
  574. aot_set_last_error("WASM block stack underflow.");
  575. return false;
  576. }
  577. /* Create the end block */
  578. if (!block->llvm_end_block) {
  579. format_block_name(name, sizeof(name), block->block_index,
  580. block->label_type, LABEL_END);
  581. CREATE_BLOCK(block->llvm_end_block, name);
  582. if ((next_llvm_end_block = find_next_llvm_end_block(block)))
  583. MOVE_BLOCK_BEFORE(block->llvm_end_block, next_llvm_end_block);
  584. }
  585. /* Handle block result values */
  586. CREATE_RESULT_VALUE_PHIS(block);
  587. for (i = 0; i < block->result_count; i++) {
  588. value = NULL;
  589. result_index = block->result_count - 1 - i;
  590. POP(value, block->result_types[result_index]);
  591. bh_assert(value);
  592. ADD_TO_RESULT_PHIS(block, value, result_index);
  593. }
  594. /* Jump to the end block */
  595. BUILD_BR(block->llvm_end_block);
  596. block->is_reachable = true;
  597. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  598. fail:
  599. return false;
  600. }
  601. #if WASM_ENABLE_THREAD_MGR != 0
  602. bool
  603. check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  604. {
  605. LLVMValueRef terminate_addr, terminate_flags, flag, offset, res;
  606. LLVMBasicBlockRef terminate_check_block, non_terminate_block;
  607. AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
  608. LLVMBasicBlockRef terminate_block;
  609. /* Offset of suspend_flags */
  610. offset = I32_FIVE;
  611. if (!(terminate_addr =
  612. LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,
  613. &offset, 1, "terminate_addr"))) {
  614. aot_set_last_error("llvm build in bounds gep failed");
  615. return false;
  616. }
  617. if (!(terminate_addr =
  618. LLVMBuildBitCast(comp_ctx->builder, terminate_addr,
  619. INT32_PTR_TYPE, "terminate_addr_ptr"))) {
  620. aot_set_last_error("llvm build bit cast failed");
  621. return false;
  622. }
  623. if (!(terminate_flags = LLVMBuildLoad(comp_ctx->builder, terminate_addr,
  624. "terminate_flags"))) {
  625. aot_set_last_error("llvm build bit cast failed");
  626. return false;
  627. }
  628. /* Set terminate_flags memory accecc to volatile, so that the value
  629. will always be loaded from memory rather than register */
  630. LLVMSetVolatile(terminate_flags, true);
  631. CREATE_BLOCK(terminate_check_block, "terminate_check");
  632. MOVE_BLOCK_AFTER_CURR(terminate_check_block);
  633. CREATE_BLOCK(non_terminate_block, "non_terminate");
  634. MOVE_BLOCK_AFTER_CURR(non_terminate_block);
  635. BUILD_ICMP(LLVMIntSGT, terminate_flags, I32_ZERO, res, "need_terminate");
  636. BUILD_COND_BR(res, terminate_check_block, non_terminate_block);
  637. /* Move builder to terminate check block */
  638. SET_BUILDER_POS(terminate_check_block);
  639. CREATE_BLOCK(terminate_block, "terminate");
  640. MOVE_BLOCK_AFTER_CURR(terminate_block);
  641. if (!(flag = LLVMBuildAnd(comp_ctx->builder, terminate_flags, I32_ONE,
  642. "termination_flag"))) {
  643. aot_set_last_error("llvm build AND failed");
  644. return false;
  645. }
  646. BUILD_ICMP(LLVMIntSGT, flag, I32_ZERO, res, "need_terminate");
  647. BUILD_COND_BR(res, terminate_block, non_terminate_block);
  648. /* Move builder to terminate block */
  649. SET_BUILDER_POS(terminate_block);
  650. if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
  651. goto fail;
  652. }
  653. /* Move builder to terminate block */
  654. SET_BUILDER_POS(non_terminate_block);
  655. return true;
  656. fail:
  657. return false;
  658. }
  659. #endif /* End of WASM_ENABLE_THREAD_MGR */
  660. bool
  661. aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  662. uint32 br_depth, uint8 **p_frame_ip)
  663. {
  664. AOTBlock *block_dst;
  665. LLVMValueRef value_ret, value_param;
  666. LLVMBasicBlockRef next_llvm_end_block;
  667. char name[32];
  668. uint32 i, param_index, result_index;
  669. #if WASM_ENABLE_THREAD_MGR != 0
  670. /* Insert suspend check point */
  671. if (comp_ctx->enable_thread_mgr) {
  672. if (!check_suspend_flags(comp_ctx, func_ctx))
  673. return false;
  674. }
  675. #endif
  676. if (!(block_dst = get_target_block(func_ctx, br_depth))) {
  677. return false;
  678. }
  679. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  680. /* Dest block is Loop block */
  681. /* Handle Loop parameters */
  682. for (i = 0; i < block_dst->param_count; i++) {
  683. param_index = block_dst->param_count - 1 - i;
  684. POP(value_param, block_dst->param_types[param_index]);
  685. ADD_TO_PARAM_PHIS(block_dst, value_param, param_index);
  686. }
  687. BUILD_BR(block_dst->llvm_entry_block);
  688. }
  689. else {
  690. /* Dest block is Block/If/Function block */
  691. /* Create the end block */
  692. if (!block_dst->llvm_end_block) {
  693. format_block_name(name, sizeof(name), block_dst->block_index,
  694. block_dst->label_type, LABEL_END);
  695. CREATE_BLOCK(block_dst->llvm_end_block, name);
  696. if ((next_llvm_end_block = find_next_llvm_end_block(block_dst)))
  697. MOVE_BLOCK_BEFORE(block_dst->llvm_end_block,
  698. next_llvm_end_block);
  699. }
  700. block_dst->is_reachable = true;
  701. /* Handle result values */
  702. CREATE_RESULT_VALUE_PHIS(block_dst);
  703. for (i = 0; i < block_dst->result_count; i++) {
  704. result_index = block_dst->result_count - 1 - i;
  705. POP(value_ret, block_dst->result_types[result_index]);
  706. ADD_TO_RESULT_PHIS(block_dst, value_ret, result_index);
  707. }
  708. /* Jump to the end block */
  709. BUILD_BR(block_dst->llvm_end_block);
  710. }
  711. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  712. fail:
  713. return false;
  714. }
  715. bool
  716. aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  717. uint32 br_depth, uint8 **p_frame_ip)
  718. {
  719. AOTBlock *block_dst;
  720. LLVMValueRef value_cmp, value, *values = NULL;
  721. LLVMBasicBlockRef llvm_else_block, next_llvm_end_block;
  722. char name[32];
  723. uint32 i, param_index, result_index;
  724. uint64 size;
  725. #if WASM_ENABLE_THREAD_MGR != 0
  726. /* Insert suspend check point */
  727. if (comp_ctx->enable_thread_mgr) {
  728. if (!check_suspend_flags(comp_ctx, func_ctx))
  729. return false;
  730. }
  731. #endif
  732. POP_COND(value_cmp);
  733. if (LLVMIsUndef(value_cmp)
  734. #if LLVM_VERSION_NUMBER >= 12
  735. || LLVMIsPoison(value_cmp)
  736. #endif
  737. ) {
  738. if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW,
  739. false, NULL, NULL))) {
  740. goto fail;
  741. }
  742. return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  743. }
  744. if (!LLVMIsConstant(value_cmp)) {
  745. /* Compare value is not constant, create condition br IR */
  746. if (!(block_dst = get_target_block(func_ctx, br_depth))) {
  747. return false;
  748. }
  749. /* Create llvm else block */
  750. CREATE_BLOCK(llvm_else_block, "br_if_else");
  751. MOVE_BLOCK_AFTER_CURR(llvm_else_block);
  752. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  753. /* Dest block is Loop block */
  754. /* Handle Loop parameters */
  755. if (block_dst->param_count) {
  756. size = sizeof(LLVMValueRef) * (uint64)block_dst->param_count;
  757. if (size >= UINT32_MAX
  758. || !(values = wasm_runtime_malloc((uint32)size))) {
  759. aot_set_last_error("allocate memory failed.");
  760. goto fail;
  761. }
  762. for (i = 0; i < block_dst->param_count; i++) {
  763. param_index = block_dst->param_count - 1 - i;
  764. POP(value, block_dst->param_types[param_index]);
  765. ADD_TO_PARAM_PHIS(block_dst, value, param_index);
  766. values[param_index] = value;
  767. }
  768. for (i = 0; i < block_dst->param_count; i++) {
  769. PUSH(values[i], block_dst->param_types[i]);
  770. }
  771. wasm_runtime_free(values);
  772. values = NULL;
  773. }
  774. BUILD_COND_BR(value_cmp, block_dst->llvm_entry_block,
  775. llvm_else_block);
  776. /* Move builder to else block */
  777. SET_BUILDER_POS(llvm_else_block);
  778. }
  779. else {
  780. /* Dest block is Block/If/Function block */
  781. /* Create the end block */
  782. if (!block_dst->llvm_end_block) {
  783. format_block_name(name, sizeof(name), block_dst->block_index,
  784. block_dst->label_type, LABEL_END);
  785. CREATE_BLOCK(block_dst->llvm_end_block, name);
  786. if ((next_llvm_end_block = find_next_llvm_end_block(block_dst)))
  787. MOVE_BLOCK_BEFORE(block_dst->llvm_end_block,
  788. next_llvm_end_block);
  789. }
  790. /* Set reachable flag and create condition br IR */
  791. block_dst->is_reachable = true;
  792. /* Handle result values */
  793. if (block_dst->result_count) {
  794. size = sizeof(LLVMValueRef) * (uint64)block_dst->result_count;
  795. if (size >= UINT32_MAX
  796. || !(values = wasm_runtime_malloc((uint32)size))) {
  797. aot_set_last_error("allocate memory failed.");
  798. goto fail;
  799. }
  800. CREATE_RESULT_VALUE_PHIS(block_dst);
  801. for (i = 0; i < block_dst->result_count; i++) {
  802. result_index = block_dst->result_count - 1 - i;
  803. POP(value, block_dst->result_types[result_index]);
  804. values[result_index] = value;
  805. ADD_TO_RESULT_PHIS(block_dst, value, result_index);
  806. }
  807. for (i = 0; i < block_dst->result_count; i++) {
  808. PUSH(values[i], block_dst->result_types[i]);
  809. }
  810. wasm_runtime_free(values);
  811. values = NULL;
  812. }
  813. /* Condition jump to end block */
  814. BUILD_COND_BR(value_cmp, block_dst->llvm_end_block,
  815. llvm_else_block);
  816. /* Move builder to else block */
  817. SET_BUILDER_POS(llvm_else_block);
  818. }
  819. }
  820. else {
  821. if ((int32)LLVMConstIntGetZExtValue(value_cmp) != 0) {
  822. /* Compare value is not 0, condition is true, same as op_br */
  823. return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip);
  824. }
  825. else {
  826. /* Compare value is not 0, condition is false, skip br_if */
  827. return true;
  828. }
  829. }
  830. return true;
  831. fail:
  832. if (values)
  833. wasm_runtime_free(values);
  834. return false;
  835. }
  836. bool
  837. aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  838. uint32 *br_depths, uint32 br_count, uint8 **p_frame_ip)
  839. {
  840. uint32 i, j;
  841. LLVMValueRef value_switch, value_cmp, value_case, value, *values = NULL;
  842. LLVMBasicBlockRef default_llvm_block = NULL, target_llvm_block;
  843. LLVMBasicBlockRef next_llvm_end_block;
  844. AOTBlock *target_block;
  845. uint32 br_depth, depth_idx;
  846. uint32 param_index, result_index;
  847. uint64 size;
  848. char name[32];
  849. #if WASM_ENABLE_THREAD_MGR != 0
  850. /* Insert suspend check point */
  851. if (comp_ctx->enable_thread_mgr) {
  852. if (!check_suspend_flags(comp_ctx, func_ctx))
  853. return false;
  854. }
  855. #endif
  856. POP_I32(value_cmp);
  857. if (LLVMIsUndef(value_cmp)
  858. #if LLVM_VERSION_NUMBER >= 12
  859. || LLVMIsPoison(value_cmp)
  860. #endif
  861. ) {
  862. if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW,
  863. false, NULL, NULL))) {
  864. goto fail;
  865. }
  866. return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  867. }
  868. if (!LLVMIsConstant(value_cmp)) {
  869. /* Compare value is not constant, create switch IR */
  870. for (i = 0; i <= br_count; i++) {
  871. target_block = get_target_block(func_ctx, br_depths[i]);
  872. if (!target_block)
  873. return false;
  874. if (target_block->label_type != LABEL_TYPE_LOOP) {
  875. /* Dest block is Block/If/Function block */
  876. /* Create the end block */
  877. if (!target_block->llvm_end_block) {
  878. format_block_name(name, sizeof(name),
  879. target_block->block_index,
  880. target_block->label_type, LABEL_END);
  881. CREATE_BLOCK(target_block->llvm_end_block, name);
  882. if ((next_llvm_end_block =
  883. find_next_llvm_end_block(target_block)))
  884. MOVE_BLOCK_BEFORE(target_block->llvm_end_block,
  885. next_llvm_end_block);
  886. }
  887. /* Handle result values */
  888. if (target_block->result_count) {
  889. size = sizeof(LLVMValueRef)
  890. * (uint64)target_block->result_count;
  891. if (size >= UINT32_MAX
  892. || !(values = wasm_runtime_malloc((uint32)size))) {
  893. aot_set_last_error("allocate memory failed.");
  894. goto fail;
  895. }
  896. CREATE_RESULT_VALUE_PHIS(target_block);
  897. for (j = 0; j < target_block->result_count; j++) {
  898. result_index = target_block->result_count - 1 - j;
  899. POP(value, target_block->result_types[result_index]);
  900. values[result_index] = value;
  901. ADD_TO_RESULT_PHIS(target_block, value, result_index);
  902. }
  903. for (j = 0; j < target_block->result_count; j++) {
  904. PUSH(values[j], target_block->result_types[j]);
  905. }
  906. wasm_runtime_free(values);
  907. }
  908. target_block->is_reachable = true;
  909. if (i == br_count)
  910. default_llvm_block = target_block->llvm_end_block;
  911. }
  912. else {
  913. /* Handle Loop parameters */
  914. if (target_block->param_count) {
  915. size = sizeof(LLVMValueRef)
  916. * (uint64)target_block->param_count;
  917. if (size >= UINT32_MAX
  918. || !(values = wasm_runtime_malloc((uint32)size))) {
  919. aot_set_last_error("allocate memory failed.");
  920. goto fail;
  921. }
  922. for (j = 0; j < target_block->param_count; j++) {
  923. param_index = target_block->param_count - 1 - j;
  924. POP(value, target_block->param_types[param_index]);
  925. values[param_index] = value;
  926. ADD_TO_PARAM_PHIS(target_block, value, param_index);
  927. }
  928. for (j = 0; j < target_block->param_count; j++) {
  929. PUSH(values[j], target_block->param_types[j]);
  930. }
  931. wasm_runtime_free(values);
  932. }
  933. if (i == br_count)
  934. default_llvm_block = target_block->llvm_entry_block;
  935. }
  936. }
  937. /* Create switch IR */
  938. if (!(value_switch = LLVMBuildSwitch(comp_ctx->builder, value_cmp,
  939. default_llvm_block, br_count))) {
  940. aot_set_last_error("llvm build switch failed.");
  941. return false;
  942. }
  943. /* Add each case for switch IR */
  944. for (i = 0; i < br_count; i++) {
  945. value_case = I32_CONST(i);
  946. CHECK_LLVM_CONST(value_case);
  947. target_block = get_target_block(func_ctx, br_depths[i]);
  948. if (!target_block)
  949. return false;
  950. target_llvm_block = target_block->label_type != LABEL_TYPE_LOOP
  951. ? target_block->llvm_end_block
  952. : target_block->llvm_entry_block;
  953. LLVMAddCase(value_switch, value_case, target_llvm_block);
  954. }
  955. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  956. }
  957. else {
  958. /* Compare value is constant, create br IR */
  959. depth_idx = (uint32)LLVMConstIntGetZExtValue(value_cmp);
  960. br_depth = br_depths[br_count];
  961. if (depth_idx < br_count) {
  962. br_depth = br_depths[depth_idx];
  963. }
  964. return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip);
  965. }
  966. fail:
  967. if (values)
  968. wasm_runtime_free(values);
  969. return false;
  970. }
  971. bool
  972. aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  973. uint8 **p_frame_ip)
  974. {
  975. AOTBlock *block_func = func_ctx->block_stack.block_list_head;
  976. LLVMValueRef value;
  977. LLVMValueRef ret;
  978. AOTFuncType *func_type;
  979. uint32 i, param_index, result_index;
  980. #if WASM_ENABLE_DEBUG_AOT != 0
  981. LLVMMetadataRef return_location;
  982. #endif
  983. bh_assert(block_func);
  984. func_type = func_ctx->aot_func->func_type;
  985. #if WASM_ENABLE_DEBUG_AOT != 0
  986. return_location = dwarf_gen_location(
  987. comp_ctx, func_ctx,
  988. (*p_frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code);
  989. #endif
  990. if (block_func->result_count) {
  991. /* Store extra result values to function parameters */
  992. for (i = 0; i < block_func->result_count - 1; i++) {
  993. result_index = block_func->result_count - 1 - i;
  994. POP(value, block_func->result_types[result_index]);
  995. param_index = func_type->param_count + result_index;
  996. if (!LLVMBuildStore(comp_ctx->builder, value,
  997. LLVMGetParam(func_ctx->func, param_index))) {
  998. aot_set_last_error("llvm build store failed.");
  999. goto fail;
  1000. }
  1001. }
  1002. /* Return the first result value */
  1003. POP(value, block_func->result_types[0]);
  1004. if (!(ret = LLVMBuildRet(comp_ctx->builder, value))) {
  1005. aot_set_last_error("llvm build return failed.");
  1006. goto fail;
  1007. }
  1008. #if WASM_ENABLE_DEBUG_AOT != 0
  1009. LLVMInstructionSetDebugLoc(ret, return_location);
  1010. #endif
  1011. }
  1012. else {
  1013. if (!(ret = LLVMBuildRetVoid(comp_ctx->builder))) {
  1014. aot_set_last_error("llvm build return void failed.");
  1015. goto fail;
  1016. }
  1017. #if WASM_ENABLE_DEBUG_AOT != 0
  1018. LLVMInstructionSetDebugLoc(ret, return_location);
  1019. #endif
  1020. }
  1021. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  1022. fail:
  1023. return false;
  1024. }
  1025. bool
  1026. aot_compile_op_unreachable(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  1027. uint8 **p_frame_ip)
  1028. {
  1029. if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_UNREACHABLE, false, NULL,
  1030. NULL))
  1031. return false;
  1032. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  1033. }
  1034. bool
  1035. aot_handle_next_reachable_block(AOTCompContext *comp_ctx,
  1036. AOTFuncContext *func_ctx, uint8 **p_frame_ip)
  1037. {
  1038. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  1039. }