aot_emit_control.c 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842
  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_compiler.h"
  7. #include "aot_emit_exception.h"
  8. #include "aot_stack_frame_comp.h"
  9. #if WASM_ENABLE_GC != 0
  10. #include "aot_emit_gc.h"
  11. #endif
  12. #include "../aot/aot_runtime.h"
  13. #include "../interpreter/wasm_loader.h"
  14. #include "../common/wasm_loader_common.h"
  15. #if WASM_ENABLE_DEBUG_AOT != 0
  16. #include "debug/dwarf_extractor.h"
  17. #endif
  18. static char *block_name_prefix[] = { "block", "loop", "if" };
  19. static char *block_name_suffix[] = { "begin", "else", "end" };
  20. /* clang-format off */
  21. enum {
  22. LABEL_BEGIN = 0,
  23. LABEL_ELSE,
  24. LABEL_END
  25. };
  26. /* clang-format on */
  27. static void
  28. format_block_name(char *name, uint32 name_size, uint32 block_index,
  29. uint32 label_type, uint32 label_id)
  30. {
  31. if (label_type != LABEL_TYPE_FUNCTION)
  32. snprintf(name, name_size, "%s%d%s%s", block_name_prefix[label_type],
  33. block_index, "_", block_name_suffix[label_id]);
  34. else
  35. snprintf(name, name_size, "%s", "func_end");
  36. }
  37. #define CREATE_BLOCK(new_llvm_block, name) \
  38. do { \
  39. if (!(new_llvm_block = LLVMAppendBasicBlockInContext( \
  40. comp_ctx->context, func_ctx->func, name))) { \
  41. aot_set_last_error("add LLVM basic block failed."); \
  42. goto fail; \
  43. } \
  44. if (!strcmp(name, "func_end") && comp_ctx->aux_stack_frame_type \
  45. && comp_ctx->call_stack_features.frame_per_function) { \
  46. LLVMBasicBlockRef cur_block = \
  47. LLVMGetInsertBlock(comp_ctx->builder); \
  48. SET_BUILDER_POS(new_llvm_block); \
  49. if (!aot_free_frame_per_function_frame_for_aot_func(comp_ctx, \
  50. func_ctx)) { \
  51. goto fail; \
  52. } \
  53. SET_BUILDER_POS(cur_block); \
  54. } \
  55. } while (0)
  56. #define CURR_BLOCK() LLVMGetInsertBlock(comp_ctx->builder)
  57. #define MOVE_BLOCK_AFTER(llvm_block, llvm_block_after) \
  58. LLVMMoveBasicBlockAfter(llvm_block, llvm_block_after)
  59. #define MOVE_BLOCK_AFTER_CURR(llvm_block) \
  60. LLVMMoveBasicBlockAfter(llvm_block, CURR_BLOCK())
  61. #define MOVE_BLOCK_BEFORE(llvm_block, llvm_block_before) \
  62. LLVMMoveBasicBlockBefore(llvm_block, llvm_block_before)
  63. #define BUILD_BR(llvm_block) \
  64. do { \
  65. if (!LLVMBuildBr(comp_ctx->builder, llvm_block)) { \
  66. aot_set_last_error("llvm build br failed."); \
  67. goto fail; \
  68. } \
  69. } while (0)
  70. #define BUILD_COND_BR(value_if, block_then, block_else) \
  71. do { \
  72. if (!LLVMBuildCondBr(comp_ctx->builder, value_if, block_then, \
  73. block_else)) { \
  74. aot_set_last_error("llvm build cond br failed."); \
  75. goto fail; \
  76. } \
  77. } while (0)
  78. #define BUILD_COND_BR_V(value_if, block_then, block_else, instr) \
  79. do { \
  80. if (!(instr = LLVMBuildCondBr(comp_ctx->builder, value_if, block_then, \
  81. block_else))) { \
  82. aot_set_last_error("llvm build cond br failed."); \
  83. goto fail; \
  84. } \
  85. } while (0)
  86. #define SET_BUILDER_POS(llvm_block) \
  87. LLVMPositionBuilderAtEnd(comp_ctx->builder, llvm_block)
  88. #define CREATE_RESULT_VALUE_PHIS(block) \
  89. do { \
  90. if (block->result_count && !block->result_phis) { \
  91. uint32 _i; \
  92. uint64 _size; \
  93. LLVMBasicBlockRef _block_curr = CURR_BLOCK(); \
  94. /* Allocate memory */ \
  95. _size = sizeof(LLVMValueRef) * (uint64)block->result_count; \
  96. if (_size >= UINT32_MAX \
  97. || !(block->result_phis = \
  98. wasm_runtime_malloc((uint32)_size))) { \
  99. aot_set_last_error("allocate memory failed."); \
  100. goto fail; \
  101. } \
  102. SET_BUILDER_POS(block->llvm_end_block); \
  103. LLVMValueRef first_instr = \
  104. get_first_non_phi(block->llvm_end_block); \
  105. if (first_instr) { \
  106. LLVMPositionBuilderBefore(comp_ctx->builder, first_instr); \
  107. } \
  108. for (_i = 0; _i < block->result_count; _i++) { \
  109. if (!(block->result_phis[_i] = LLVMBuildPhi( \
  110. comp_ctx->builder, \
  111. TO_LLVM_TYPE(block->result_types[_i]), "phi"))) { \
  112. aot_set_last_error("llvm build phi failed."); \
  113. goto fail; \
  114. } \
  115. } \
  116. SET_BUILDER_POS(_block_curr); \
  117. } \
  118. } while (0)
  119. #define ADD_TO_RESULT_PHIS(block, value, idx) \
  120. do { \
  121. LLVMBasicBlockRef _block_curr = CURR_BLOCK(); \
  122. LLVMTypeRef phi_ty = LLVMTypeOf(block->result_phis[idx]); \
  123. LLVMTypeRef value_ty = LLVMTypeOf(value); \
  124. bh_assert(LLVMGetTypeKind(phi_ty) == LLVMGetTypeKind(value_ty)); \
  125. bh_assert(LLVMGetTypeContext(phi_ty) == LLVMGetTypeContext(value_ty)); \
  126. LLVMAddIncoming(block->result_phis[idx], &value, &_block_curr, 1); \
  127. (void)phi_ty; \
  128. (void)value_ty; \
  129. } while (0)
  130. #define BUILD_ICMP(op, left, right, res, name) \
  131. do { \
  132. if (!(res = \
  133. LLVMBuildICmp(comp_ctx->builder, op, left, right, name))) { \
  134. aot_set_last_error("llvm build icmp failed."); \
  135. goto fail; \
  136. } \
  137. } while (0)
  138. #define ADD_TO_PARAM_PHIS(block, value, idx) \
  139. do { \
  140. LLVMBasicBlockRef _block_curr = CURR_BLOCK(); \
  141. LLVMAddIncoming(block->param_phis[idx], &value, &_block_curr, 1); \
  142. } while (0)
  143. static LLVMBasicBlockRef
  144. find_next_llvm_end_block(AOTBlock *block)
  145. {
  146. block = block->prev;
  147. while (block && !block->llvm_end_block)
  148. block = block->prev;
  149. return block ? block->llvm_end_block : NULL;
  150. }
  151. static AOTBlock *
  152. get_target_block(AOTFuncContext *func_ctx, uint32 br_depth)
  153. {
  154. uint32 i = br_depth;
  155. AOTBlock *block = func_ctx->block_stack.block_list_end;
  156. while (i-- > 0 && block) {
  157. block = block->prev;
  158. }
  159. if (!block) {
  160. aot_set_last_error("WASM block stack underflow.");
  161. return NULL;
  162. }
  163. return block;
  164. }
  165. LLVMValueRef
  166. get_first_non_phi(LLVMBasicBlockRef block)
  167. {
  168. LLVMValueRef instr = LLVMGetFirstInstruction(block);
  169. while (instr && LLVMIsAPHINode(instr)) {
  170. instr = LLVMGetNextInstruction(instr);
  171. }
  172. return instr;
  173. }
  174. static void
  175. clear_frame_locals(AOTCompFrame *aot_frame)
  176. {
  177. uint32 i;
  178. for (i = 0; i < aot_frame->max_local_cell_num; i++) {
  179. aot_frame->lp[i].dirty = 0;
  180. aot_frame->lp[i].value = NULL;
  181. if (aot_frame->comp_ctx->enable_gc)
  182. /* Mark the ref flag as committed */
  183. aot_frame->lp[i].committed_ref = aot_frame->lp[i].ref + 1;
  184. }
  185. }
  186. static void
  187. restore_frame_sp_for_op_else(AOTBlock *block, AOTCompFrame *aot_frame)
  188. {
  189. uint32 all_cell_num =
  190. aot_frame->max_local_cell_num + aot_frame->max_stack_cell_num;
  191. AOTValueSlot *p_end = aot_frame->lp + all_cell_num, *p;
  192. /* Reset all the value slots from current frame sp for the else
  193. branch since they be the same as starting to translate the
  194. if branch */
  195. for (p = block->frame_sp_begin; p < p_end; p++) {
  196. p->dirty = 0;
  197. p->value = NULL;
  198. p->type = 0;
  199. if (aot_frame->comp_ctx->enable_gc) {
  200. p->ref = 0;
  201. p->committed_ref = 1;
  202. }
  203. }
  204. bh_assert(aot_frame->sp >= block->frame_sp_begin);
  205. aot_frame->sp = block->frame_sp_begin;
  206. }
  207. static void
  208. restore_frame_sp_for_op_end(AOTBlock *block, AOTCompFrame *aot_frame)
  209. {
  210. uint32 all_cell_num =
  211. aot_frame->max_local_cell_num + aot_frame->max_stack_cell_num;
  212. AOTValueSlot *p_end = aot_frame->lp + all_cell_num, *p;
  213. bh_assert(block->frame_sp_max_reached >= block->frame_sp_begin);
  214. /* Reset all the value slots from current frame sp to be same as
  215. starting to translate this block, except for the frame ref
  216. flags: set the flags to uncommitted before the max frame sp
  217. ever reached, set the flags to committed non-ref after that */
  218. for (p = block->frame_sp_begin; p < p_end; p++) {
  219. p->dirty = 0;
  220. p->value = NULL;
  221. p->type = 0;
  222. if (aot_frame->comp_ctx->enable_gc) {
  223. p->ref = 0;
  224. if (p < block->frame_sp_max_reached)
  225. p->committed_ref = 0;
  226. else
  227. p->committed_ref = 1;
  228. }
  229. }
  230. bh_assert(aot_frame->sp >= block->frame_sp_begin);
  231. aot_frame->sp = block->frame_sp_begin;
  232. }
  233. #if WASM_ENABLE_BRANCH_HINTS != 0
  234. static void
  235. aot_emit_branch_hint(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  236. uint32 offset, LLVMValueRef br_if_instr)
  237. {
  238. struct WASMCompilationHint *hint = func_ctx->function_hints;
  239. while (hint != NULL) {
  240. if (hint->type == WASM_COMPILATION_BRANCH_HINT
  241. && ((struct WASMCompilationHintBranchHint *)hint)->offset
  242. == offset) {
  243. break;
  244. }
  245. hint = hint->next;
  246. }
  247. if (hint != NULL) {
  248. // same weight llvm MDBuilder::createLikelyBranchWeights assigns
  249. const uint32_t likely_weight = (1U << 20) - 1;
  250. const uint32_t unlikely_weight = 1;
  251. aot_set_cond_br_weights(
  252. comp_ctx, br_if_instr,
  253. ((struct WASMCompilationHintBranchHint *)hint)->is_likely
  254. ? likely_weight
  255. : unlikely_weight,
  256. ((struct WASMCompilationHintBranchHint *)hint)->is_likely
  257. ? unlikely_weight
  258. : likely_weight);
  259. }
  260. }
  261. #endif
  262. static bool
  263. handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  264. uint8 **p_frame_ip)
  265. {
  266. AOTBlock *block = func_ctx->block_stack.block_list_end;
  267. AOTBlock *block_prev;
  268. AOTCompFrame *aot_frame = comp_ctx->aot_frame;
  269. uint8 *frame_ip = NULL;
  270. uint32 i;
  271. AOTFuncType *func_type;
  272. LLVMValueRef ret;
  273. #if WASM_ENABLE_DEBUG_AOT != 0
  274. LLVMMetadataRef return_location;
  275. #endif
  276. aot_checked_addr_list_destroy(func_ctx);
  277. bh_assert(block);
  278. #if WASM_ENABLE_DEBUG_AOT != 0
  279. return_location = dwarf_gen_location(
  280. comp_ctx, func_ctx,
  281. (*p_frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code);
  282. #endif
  283. if (aot_frame) {
  284. /* Clear frame local variables since they have been committed */
  285. clear_frame_locals(aot_frame);
  286. }
  287. if (block->label_type == LABEL_TYPE_IF && block->llvm_else_block
  288. && *p_frame_ip <= block->wasm_code_else) {
  289. /* Clear value stack and start to translate else branch */
  290. aot_value_stack_destroy(comp_ctx, &block->value_stack);
  291. if (aot_frame) {
  292. /* Restore the frame sp */
  293. restore_frame_sp_for_op_else(block, aot_frame);
  294. }
  295. /* Recover parameters of else branch */
  296. for (i = 0; i < block->param_count; i++)
  297. PUSH(block->else_param_phis[i], block->param_types[i]);
  298. SET_BUILDER_POS(block->llvm_else_block);
  299. *p_frame_ip = block->wasm_code_else + 1;
  300. return true;
  301. }
  302. while (block && !block->is_reachable) {
  303. block_prev = block->prev;
  304. block = aot_block_stack_pop(&func_ctx->block_stack);
  305. if (block->label_type == LABEL_TYPE_IF) {
  306. if (block->llvm_else_block && !block->skip_wasm_code_else
  307. && *p_frame_ip <= block->wasm_code_else) {
  308. /* Clear value stack and start to translate else branch */
  309. aot_value_stack_destroy(comp_ctx, &block->value_stack);
  310. if (aot_frame) {
  311. /* Restore the frame sp */
  312. restore_frame_sp_for_op_else(block, aot_frame);
  313. }
  314. SET_BUILDER_POS(block->llvm_else_block);
  315. *p_frame_ip = block->wasm_code_else + 1;
  316. /* Push back the block */
  317. aot_block_stack_push(&func_ctx->block_stack, block);
  318. /* Recover parameters of else branch */
  319. for (i = 0; i < block->param_count; i++)
  320. PUSH(block->else_param_phis[i], block->param_types[i]);
  321. return true;
  322. }
  323. else if (block->llvm_end_block) {
  324. /* Remove unreachable basic block */
  325. LLVMDeleteBasicBlock(block->llvm_end_block);
  326. block->llvm_end_block = NULL;
  327. }
  328. }
  329. frame_ip = block->wasm_code_end;
  330. aot_block_destroy(comp_ctx, block);
  331. block = block_prev;
  332. }
  333. if (!block) {
  334. *p_frame_ip = frame_ip + 1;
  335. return true;
  336. }
  337. if (block->label_type == LABEL_TYPE_IF && block->llvm_else_block
  338. && !block->skip_wasm_code_else
  339. && *p_frame_ip <= block->wasm_code_else) {
  340. /* Clear value stack and start to translate else branch */
  341. aot_value_stack_destroy(comp_ctx, &block->value_stack);
  342. if (aot_frame) {
  343. /* Restore the frame sp */
  344. restore_frame_sp_for_op_else(block, aot_frame);
  345. }
  346. /* Recover parameters of else branch */
  347. for (i = 0; i < block->param_count; i++)
  348. PUSH(block->else_param_phis[i], block->param_types[i]);
  349. SET_BUILDER_POS(block->llvm_else_block);
  350. *p_frame_ip = block->wasm_code_else + 1;
  351. return true;
  352. }
  353. *p_frame_ip = block->wasm_code_end + 1;
  354. SET_BUILDER_POS(block->llvm_end_block);
  355. /* Pop block, push its return value, and destroy the block */
  356. block = aot_block_stack_pop(&func_ctx->block_stack);
  357. if (aot_frame) {
  358. /* Restore the frame sp */
  359. restore_frame_sp_for_op_end(block, aot_frame);
  360. }
  361. func_type = func_ctx->aot_func->func_type;
  362. for (i = 0; i < block->result_count; i++) {
  363. bh_assert(block->result_phis[i]);
  364. if (block->label_type != LABEL_TYPE_FUNCTION) {
  365. PUSH(block->result_phis[i], block->result_types[i]);
  366. }
  367. else {
  368. /* Store extra return values to function parameters */
  369. if (i != 0) {
  370. LLVMValueRef res;
  371. uint32 param_index = func_type->param_count + i;
  372. if (!(res = LLVMBuildStore(
  373. comp_ctx->builder, block->result_phis[i],
  374. LLVMGetParam(func_ctx->func, param_index)))) {
  375. aot_set_last_error("llvm build store failed.");
  376. goto fail;
  377. }
  378. LLVMSetAlignment(res, 1);
  379. }
  380. }
  381. }
  382. if (block->label_type == LABEL_TYPE_FUNCTION) {
  383. if (block->result_count) {
  384. /* Return the first return value */
  385. if (!(ret =
  386. LLVMBuildRet(comp_ctx->builder, block->result_phis[0]))) {
  387. aot_set_last_error("llvm build return failed.");
  388. goto fail;
  389. }
  390. #if WASM_ENABLE_DEBUG_AOT != 0
  391. if (return_location != NULL) {
  392. LLVMInstructionSetDebugLoc(ret, return_location);
  393. }
  394. #endif
  395. }
  396. else {
  397. if (!(ret = LLVMBuildRetVoid(comp_ctx->builder))) {
  398. aot_set_last_error("llvm build return void failed.");
  399. goto fail;
  400. }
  401. #if WASM_ENABLE_DEBUG_AOT != 0
  402. if (return_location != NULL) {
  403. LLVMInstructionSetDebugLoc(ret, return_location);
  404. }
  405. #endif
  406. }
  407. }
  408. aot_block_destroy(comp_ctx, block);
  409. return true;
  410. fail:
  411. return false;
  412. }
  413. static bool
  414. push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx,
  415. AOTFuncContext *func_ctx,
  416. AOTBlock *block)
  417. {
  418. uint32 i, param_index;
  419. LLVMValueRef value, br_inst;
  420. uint64 size;
  421. char name[32];
  422. LLVMBasicBlockRef block_curr = CURR_BLOCK();
  423. if (block->param_count) {
  424. size = sizeof(LLVMValueRef) * (uint64)block->param_count;
  425. if (size >= UINT32_MAX
  426. || !(block->param_phis = wasm_runtime_malloc((uint32)size))) {
  427. aot_set_last_error("allocate memory failed.");
  428. return false;
  429. }
  430. if (block->label_type == LABEL_TYPE_IF && !block->skip_wasm_code_else
  431. && !(block->else_param_phis = wasm_runtime_malloc((uint32)size))) {
  432. wasm_runtime_free(block->param_phis);
  433. block->param_phis = NULL;
  434. aot_set_last_error("allocate memory failed.");
  435. return false;
  436. }
  437. /* Create param phis */
  438. for (i = 0; i < block->param_count; i++) {
  439. if (block->llvm_entry_block) {
  440. SET_BUILDER_POS(block->llvm_entry_block);
  441. snprintf(name, sizeof(name), "%s%d_phi%d",
  442. block_name_prefix[block->label_type],
  443. block->block_index, i);
  444. if (!(block->param_phis[i] = LLVMBuildPhi(
  445. comp_ctx->builder,
  446. TO_LLVM_TYPE(block->param_types[i]), name))) {
  447. aot_set_last_error("llvm build phi failed.");
  448. goto fail;
  449. }
  450. }
  451. if (block->label_type == LABEL_TYPE_IF
  452. && !block->skip_wasm_code_else && block->llvm_else_block) {
  453. /* Build else param phis */
  454. SET_BUILDER_POS(block->llvm_else_block);
  455. snprintf(name, sizeof(name), "else%d_phi%d", block->block_index,
  456. i);
  457. if (!(block->else_param_phis[i] = LLVMBuildPhi(
  458. comp_ctx->builder,
  459. TO_LLVM_TYPE(block->param_types[i]), name))) {
  460. aot_set_last_error("llvm build phi failed.");
  461. goto fail;
  462. }
  463. }
  464. }
  465. /* At this point, the branch instruction was already built to jump to
  466. * the new BB, to avoid generating zext instruction from the popped
  467. * operand that would come after branch instruction, we should position
  468. * the builder before the last branch instruction */
  469. br_inst = LLVMGetLastInstruction(block_curr);
  470. bh_assert(LLVMGetInstructionOpcode(br_inst) == LLVMBr);
  471. LLVMPositionBuilderBefore(comp_ctx->builder, br_inst);
  472. /* Pop param values from current block's
  473. * value stack and add to param phis.
  474. */
  475. for (i = 0; i < block->param_count; i++) {
  476. param_index = block->param_count - 1 - i;
  477. POP(value, block->param_types[param_index]);
  478. if (block->llvm_entry_block)
  479. /* Only add incoming phis if the entry block was created */
  480. ADD_TO_PARAM_PHIS(block, value, param_index);
  481. if (block->label_type == LABEL_TYPE_IF
  482. && !block->skip_wasm_code_else) {
  483. if (block->llvm_else_block) {
  484. /* has else branch, add to else param phis */
  485. LLVMAddIncoming(block->else_param_phis[param_index], &value,
  486. &block_curr, 1);
  487. }
  488. else {
  489. /* no else branch, add to result phis */
  490. CREATE_RESULT_VALUE_PHIS(block);
  491. ADD_TO_RESULT_PHIS(block, value, param_index);
  492. }
  493. }
  494. }
  495. }
  496. /* Push the new block to block stack */
  497. aot_block_stack_push(&func_ctx->block_stack, block);
  498. if (comp_ctx->aot_frame) {
  499. block->frame_sp_begin = block->frame_sp_max_reached =
  500. comp_ctx->aot_frame->sp;
  501. }
  502. /* Push param phis to the new block */
  503. for (i = 0; i < block->param_count; i++) {
  504. if (block->llvm_entry_block)
  505. /* Push param phis if the entry basic block was created */
  506. PUSH(block->param_phis[i], block->param_types[i]);
  507. else {
  508. bh_assert(block->label_type == LABEL_TYPE_IF
  509. && block->llvm_else_block && block->else_param_phis
  510. && !block->skip_wasm_code_else);
  511. /* Push else param phis if we start to translate the
  512. else branch */
  513. PUSH(block->else_param_phis[i], block->param_types[i]);
  514. }
  515. }
  516. return true;
  517. fail:
  518. if (block->param_phis) {
  519. wasm_runtime_free(block->param_phis);
  520. block->param_phis = NULL;
  521. }
  522. if (block->else_param_phis) {
  523. wasm_runtime_free(block->else_param_phis);
  524. block->else_param_phis = NULL;
  525. }
  526. return false;
  527. }
  528. bool
  529. aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  530. uint8 **p_frame_ip, uint8 *frame_ip_end, uint32 label_type,
  531. uint32 param_count, uint8 *param_types,
  532. uint32 result_count, uint8 *result_types)
  533. {
  534. BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
  535. AOTBlock *block;
  536. uint8 *else_addr, *end_addr;
  537. LLVMValueRef value;
  538. char name[32];
  539. /* Check block stack */
  540. if (!func_ctx->block_stack.block_list_end) {
  541. aot_set_last_error("WASM block stack underflow.");
  542. return false;
  543. }
  544. memset(block_addr_cache, 0, sizeof(block_addr_cache));
  545. /* Get block info */
  546. if (!(wasm_loader_find_block_addr(
  547. NULL, (BlockAddr *)block_addr_cache, *p_frame_ip, frame_ip_end,
  548. (uint8)label_type, &else_addr, &end_addr))) {
  549. aot_set_last_error("find block end addr failed.");
  550. return false;
  551. }
  552. /* Allocate memory */
  553. if (!(block = wasm_runtime_malloc(sizeof(AOTBlock)))) {
  554. aot_set_last_error("allocate memory failed.");
  555. return false;
  556. }
  557. memset(block, 0, sizeof(AOTBlock));
  558. if (param_count
  559. && !(block->param_types = wasm_runtime_malloc(param_count))) {
  560. aot_set_last_error("allocate memory failed.");
  561. goto fail;
  562. }
  563. if (result_count) {
  564. if (!(block->result_types = wasm_runtime_malloc(result_count))) {
  565. aot_set_last_error("allocate memory failed.");
  566. goto fail;
  567. }
  568. }
  569. /* Init aot block data */
  570. block->label_type = label_type;
  571. block->param_count = param_count;
  572. if (param_count) {
  573. bh_memcpy_s(block->param_types, param_count, param_types, param_count);
  574. }
  575. block->result_count = result_count;
  576. if (result_count) {
  577. bh_memcpy_s(block->result_types, result_count, result_types,
  578. result_count);
  579. }
  580. block->wasm_code_else = else_addr;
  581. block->wasm_code_end = end_addr;
  582. block->block_index = func_ctx->block_stack.block_index[label_type];
  583. func_ctx->block_stack.block_index[label_type]++;
  584. if (comp_ctx->aot_frame) {
  585. if (label_type != LABEL_TYPE_BLOCK && comp_ctx->enable_gc
  586. && !aot_gen_commit_values(comp_ctx->aot_frame)) {
  587. goto fail;
  588. }
  589. }
  590. if (label_type == LABEL_TYPE_BLOCK || label_type == LABEL_TYPE_LOOP) {
  591. /* Create block */
  592. format_block_name(name, sizeof(name), block->block_index, label_type,
  593. LABEL_BEGIN);
  594. CREATE_BLOCK(block->llvm_entry_block, name);
  595. MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
  596. /* Jump to the entry block */
  597. BUILD_BR(block->llvm_entry_block);
  598. if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
  599. goto fail;
  600. /* Start to translate the block */
  601. SET_BUILDER_POS(block->llvm_entry_block);
  602. if (label_type == LABEL_TYPE_LOOP)
  603. aot_checked_addr_list_destroy(func_ctx);
  604. }
  605. else if (label_type == LABEL_TYPE_IF) {
  606. POP_COND(value);
  607. if (LLVMIsUndef(value)
  608. #if LLVM_VERSION_NUMBER >= 12
  609. || LLVMIsPoison(value)
  610. #endif
  611. ) {
  612. if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW,
  613. false, NULL, NULL))) {
  614. goto fail;
  615. }
  616. aot_block_destroy(comp_ctx, block);
  617. return aot_handle_next_reachable_block(comp_ctx, func_ctx,
  618. p_frame_ip);
  619. }
  620. if (!LLVMIsEfficientConstInt(value)) {
  621. /* Compare value is not constant, create condition br IR */
  622. /* Create entry block */
  623. format_block_name(name, sizeof(name), block->block_index,
  624. label_type, LABEL_BEGIN);
  625. CREATE_BLOCK(block->llvm_entry_block, name);
  626. MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
  627. /* Create end block */
  628. format_block_name(name, sizeof(name), block->block_index,
  629. label_type, LABEL_END);
  630. CREATE_BLOCK(block->llvm_end_block, name);
  631. MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_entry_block);
  632. if (else_addr) {
  633. /* Create else block */
  634. format_block_name(name, sizeof(name), block->block_index,
  635. label_type, LABEL_ELSE);
  636. CREATE_BLOCK(block->llvm_else_block, name);
  637. MOVE_BLOCK_AFTER(block->llvm_else_block,
  638. block->llvm_entry_block);
  639. /* Create condition br IR */
  640. #if WASM_ENABLE_BRANCH_HINTS != 0
  641. LLVMValueRef br_if_val = NULL;
  642. BUILD_COND_BR_V(value, block->llvm_entry_block,
  643. block->llvm_else_block, br_if_val);
  644. const uint32 off =
  645. *p_frame_ip - func_ctx->aot_func->code_body_begin;
  646. aot_emit_branch_hint(comp_ctx, func_ctx, off, br_if_val);
  647. #else
  648. BUILD_COND_BR(value, block->llvm_entry_block,
  649. block->llvm_else_block);
  650. #endif
  651. }
  652. else {
  653. /* Create condition br IR */
  654. #if WASM_ENABLE_BRANCH_HINTS != 0
  655. LLVMValueRef br_if_val = NULL;
  656. BUILD_COND_BR_V(value, block->llvm_entry_block,
  657. block->llvm_end_block, br_if_val);
  658. const uint32 off =
  659. *p_frame_ip - func_ctx->aot_func->code_body_begin;
  660. aot_emit_branch_hint(comp_ctx, func_ctx, off, br_if_val);
  661. #else
  662. BUILD_COND_BR(value, block->llvm_entry_block,
  663. block->llvm_end_block);
  664. #endif
  665. block->is_reachable = true;
  666. }
  667. if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx,
  668. block))
  669. goto fail;
  670. /* Start to translate if branch of BLOCK if */
  671. SET_BUILDER_POS(block->llvm_entry_block);
  672. }
  673. else {
  674. if ((int32)LLVMConstIntGetZExtValue(value) != 0) {
  675. /* Compare value is not 0, condition is true, else branch of
  676. BLOCK if cannot be reached */
  677. block->skip_wasm_code_else = true;
  678. /* Create entry block */
  679. format_block_name(name, sizeof(name), block->block_index,
  680. label_type, LABEL_BEGIN);
  681. CREATE_BLOCK(block->llvm_entry_block, name);
  682. MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
  683. /* Jump to the entry block */
  684. BUILD_BR(block->llvm_entry_block);
  685. if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx,
  686. block))
  687. goto fail;
  688. /* Start to translate the if branch */
  689. SET_BUILDER_POS(block->llvm_entry_block);
  690. }
  691. else {
  692. /* Compare value is not 0, condition is false, if branch of
  693. BLOCK if cannot be reached */
  694. if (else_addr) {
  695. /* Create else block */
  696. format_block_name(name, sizeof(name), block->block_index,
  697. label_type, LABEL_ELSE);
  698. CREATE_BLOCK(block->llvm_else_block, name);
  699. MOVE_BLOCK_AFTER_CURR(block->llvm_else_block);
  700. /* Jump to the else block */
  701. BUILD_BR(block->llvm_else_block);
  702. if (!push_aot_block_to_stack_and_pass_params(
  703. comp_ctx, func_ctx, block))
  704. goto fail;
  705. /* Start to translate the else branch */
  706. SET_BUILDER_POS(block->llvm_else_block);
  707. *p_frame_ip = else_addr + 1;
  708. }
  709. else {
  710. /* skip the block */
  711. aot_block_destroy(comp_ctx, block);
  712. *p_frame_ip = end_addr + 1;
  713. }
  714. }
  715. }
  716. }
  717. else {
  718. aot_set_last_error("Invalid block type.");
  719. goto fail;
  720. }
  721. return true;
  722. fail:
  723. aot_block_destroy(comp_ctx, block);
  724. return false;
  725. }
  726. bool
  727. aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  728. uint8 **p_frame_ip)
  729. {
  730. AOTBlock *block = func_ctx->block_stack.block_list_end;
  731. LLVMValueRef value;
  732. AOTCompFrame *aot_frame = comp_ctx->aot_frame;
  733. char name[32];
  734. uint32 i, result_index;
  735. /* Check block */
  736. if (!block) {
  737. aot_set_last_error("WASM block stack underflow.");
  738. return false;
  739. }
  740. if (block->label_type != LABEL_TYPE_IF
  741. || (!block->skip_wasm_code_else && !block->llvm_else_block)) {
  742. aot_set_last_error("Invalid WASM block type.");
  743. return false;
  744. }
  745. /* Create end block if needed */
  746. if (!block->llvm_end_block) {
  747. format_block_name(name, sizeof(name), block->block_index,
  748. block->label_type, LABEL_END);
  749. CREATE_BLOCK(block->llvm_end_block, name);
  750. if (block->llvm_else_block)
  751. MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_else_block);
  752. else
  753. MOVE_BLOCK_AFTER_CURR(block->llvm_end_block);
  754. }
  755. block->is_reachable = true;
  756. /* Comes from the if branch of BLOCK if */
  757. CREATE_RESULT_VALUE_PHIS(block);
  758. for (i = 0; i < block->result_count; i++) {
  759. result_index = block->result_count - 1 - i;
  760. POP(value, block->result_types[result_index]);
  761. ADD_TO_RESULT_PHIS(block, value, result_index);
  762. }
  763. if (aot_frame) {
  764. bh_assert(block->frame_sp_begin == aot_frame->sp);
  765. if (comp_ctx->enable_gc && !aot_gen_commit_values(aot_frame)) {
  766. goto fail;
  767. }
  768. }
  769. /* Jump to end block */
  770. BUILD_BR(block->llvm_end_block);
  771. if (!block->skip_wasm_code_else && block->llvm_else_block) {
  772. /* Clear value stack, recover param values
  773. and start to translate else branch. */
  774. aot_value_stack_destroy(comp_ctx, &block->value_stack);
  775. if (comp_ctx->aot_frame) {
  776. clear_frame_locals(aot_frame);
  777. restore_frame_sp_for_op_else(block, aot_frame);
  778. }
  779. for (i = 0; i < block->param_count; i++)
  780. PUSH(block->else_param_phis[i], block->param_types[i]);
  781. SET_BUILDER_POS(block->llvm_else_block);
  782. aot_checked_addr_list_destroy(func_ctx);
  783. return true;
  784. }
  785. /* No else branch or no need to translate else branch */
  786. block->is_reachable = true;
  787. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  788. fail:
  789. return false;
  790. }
  791. bool
  792. aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  793. uint8 **p_frame_ip)
  794. {
  795. AOTBlock *block;
  796. LLVMValueRef value;
  797. LLVMBasicBlockRef next_llvm_end_block;
  798. char name[32];
  799. uint32 i, result_index;
  800. /* Check block stack */
  801. if (!(block = func_ctx->block_stack.block_list_end)) {
  802. aot_set_last_error("WASM block stack underflow.");
  803. return false;
  804. }
  805. /* Create the end block */
  806. if (!block->llvm_end_block) {
  807. format_block_name(name, sizeof(name), block->block_index,
  808. block->label_type, LABEL_END);
  809. CREATE_BLOCK(block->llvm_end_block, name);
  810. if ((next_llvm_end_block = find_next_llvm_end_block(block)))
  811. MOVE_BLOCK_BEFORE(block->llvm_end_block, next_llvm_end_block);
  812. }
  813. if (comp_ctx->aot_frame) {
  814. if (block->label_type != LABEL_TYPE_FUNCTION && comp_ctx->enable_gc
  815. && !aot_gen_commit_values(comp_ctx->aot_frame)) {
  816. return false;
  817. }
  818. }
  819. /* Handle block result values */
  820. CREATE_RESULT_VALUE_PHIS(block);
  821. for (i = 0; i < block->result_count; i++) {
  822. value = NULL;
  823. result_index = block->result_count - 1 - i;
  824. POP(value, block->result_types[result_index]);
  825. bh_assert(value);
  826. ADD_TO_RESULT_PHIS(block, value, result_index);
  827. }
  828. if (comp_ctx->aot_frame) {
  829. bh_assert(comp_ctx->aot_frame->sp == block->frame_sp_begin);
  830. }
  831. /* Jump to the end block */
  832. BUILD_BR(block->llvm_end_block);
  833. block->is_reachable = true;
  834. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  835. fail:
  836. return false;
  837. }
  838. bool
  839. check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  840. bool check_terminate_and_suspend)
  841. {
  842. LLVMValueRef terminate_addr, terminate_flags, flag, offset, res;
  843. LLVMBasicBlockRef terminate_block, non_terminate_block;
  844. AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
  845. bool is_shared_memory =
  846. comp_ctx->comp_data->memories[0].flags & 0x02 ? true : false;
  847. /* Only need to check the suspend flags when memory is shared since
  848. shared memory must be enabled for multi-threading */
  849. if (!is_shared_memory) {
  850. return true;
  851. }
  852. /* Offset of suspend_flags */
  853. offset = I32_FIVE;
  854. if (!(terminate_addr = LLVMBuildInBoundsGEP2(
  855. comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env, &offset, 1,
  856. "terminate_addr"))) {
  857. aot_set_last_error("llvm build in bounds gep failed");
  858. return false;
  859. }
  860. if (!(terminate_addr =
  861. LLVMBuildBitCast(comp_ctx->builder, terminate_addr,
  862. INT32_PTR_TYPE, "terminate_addr_ptr"))) {
  863. aot_set_last_error("llvm build bit cast failed");
  864. return false;
  865. }
  866. if (!(terminate_flags =
  867. LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, terminate_addr,
  868. "terminate_flags"))) {
  869. aot_set_last_error("llvm build LOAD failed");
  870. return false;
  871. }
  872. /* Set terminate_flags memory access to volatile, so that the value
  873. will always be loaded from memory rather than register */
  874. LLVMSetVolatile(terminate_flags, true);
  875. if (!(flag = LLVMBuildAnd(comp_ctx->builder, terminate_flags, I32_ONE,
  876. "termination_flag"))) {
  877. aot_set_last_error("llvm build AND failed");
  878. return false;
  879. }
  880. CREATE_BLOCK(non_terminate_block, "non_terminate");
  881. MOVE_BLOCK_AFTER_CURR(non_terminate_block);
  882. CREATE_BLOCK(terminate_block, "terminate");
  883. MOVE_BLOCK_AFTER_CURR(terminate_block);
  884. BUILD_ICMP(LLVMIntEQ, flag, I32_ZERO, res, "flag_terminate");
  885. BUILD_COND_BR(res, non_terminate_block, terminate_block);
  886. /* Move builder to terminate block */
  887. SET_BUILDER_POS(terminate_block);
  888. if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
  889. goto fail;
  890. }
  891. /* Move builder to non terminate block */
  892. SET_BUILDER_POS(non_terminate_block);
  893. return true;
  894. fail:
  895. return false;
  896. }
  897. bool
  898. aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  899. uint32 br_depth, uint8 **p_frame_ip)
  900. {
  901. AOTBlock *block_dst;
  902. LLVMValueRef value_ret, value_param;
  903. LLVMBasicBlockRef next_llvm_end_block;
  904. char name[32];
  905. uint32 i, param_index, result_index;
  906. if (!(block_dst = get_target_block(func_ctx, br_depth))) {
  907. return false;
  908. }
  909. if (comp_ctx->aot_frame) {
  910. if (comp_ctx->enable_gc && !aot_gen_commit_values(comp_ctx->aot_frame))
  911. return false;
  912. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  913. if (comp_ctx->enable_thread_mgr) {
  914. /* Commit sp when GC is enabled, don't commit ip */
  915. if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame,
  916. comp_ctx->enable_gc, false))
  917. return false;
  918. }
  919. }
  920. else {
  921. if (comp_ctx->aot_frame->sp > block_dst->frame_sp_max_reached)
  922. block_dst->frame_sp_max_reached = comp_ctx->aot_frame->sp;
  923. }
  924. }
  925. /* Terminate or suspend current thread only when this is a backward jump */
  926. if (comp_ctx->enable_thread_mgr
  927. && block_dst->label_type == LABEL_TYPE_LOOP) {
  928. if (!check_suspend_flags(comp_ctx, func_ctx, true))
  929. return false;
  930. }
  931. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  932. /* Dest block is Loop block */
  933. /* Handle Loop parameters */
  934. for (i = 0; i < block_dst->param_count; i++) {
  935. param_index = block_dst->param_count - 1 - i;
  936. POP(value_param, block_dst->param_types[param_index]);
  937. ADD_TO_PARAM_PHIS(block_dst, value_param, param_index);
  938. }
  939. BUILD_BR(block_dst->llvm_entry_block);
  940. }
  941. else {
  942. /* Dest block is Block/If/Function block */
  943. /* Create the end block */
  944. if (!block_dst->llvm_end_block) {
  945. format_block_name(name, sizeof(name), block_dst->block_index,
  946. block_dst->label_type, LABEL_END);
  947. CREATE_BLOCK(block_dst->llvm_end_block, name);
  948. if ((next_llvm_end_block = find_next_llvm_end_block(block_dst)))
  949. MOVE_BLOCK_BEFORE(block_dst->llvm_end_block,
  950. next_llvm_end_block);
  951. }
  952. block_dst->is_reachable = true;
  953. /* Handle result values */
  954. CREATE_RESULT_VALUE_PHIS(block_dst);
  955. for (i = 0; i < block_dst->result_count; i++) {
  956. result_index = block_dst->result_count - 1 - i;
  957. POP(value_ret, block_dst->result_types[result_index]);
  958. ADD_TO_RESULT_PHIS(block_dst, value_ret, result_index);
  959. }
  960. /* Jump to the end block */
  961. BUILD_BR(block_dst->llvm_end_block);
  962. }
  963. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  964. fail:
  965. return false;
  966. }
  967. static bool
  968. aot_compile_conditional_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  969. LLVMValueRef value_cmp, uint8 **p_frame_ip)
  970. {
  971. AOTBlock *block_dst;
  972. LLVMValueRef value, *values = NULL;
  973. LLVMBasicBlockRef llvm_else_block, next_llvm_end_block;
  974. char name[32];
  975. uint32 i, param_index, result_index;
  976. uint64 size;
  977. // ip is advanced by one byte for the opcode
  978. #if WASM_ENABLE_BRANCH_HINTS != 0
  979. uint32 instr_offset =
  980. (*p_frame_ip - 0x1) - (func_ctx->aot_func->code_body_begin);
  981. #else
  982. uint32 instr_offset = 0;
  983. #endif
  984. uint64 br_depth;
  985. if (!read_leb(p_frame_ip, *p_frame_ip + 5, 32, false, &br_depth, NULL, 0))
  986. return false;
  987. if (!(block_dst = get_target_block(func_ctx, br_depth))) {
  988. return false;
  989. }
  990. if (comp_ctx->aot_frame) {
  991. if (comp_ctx->enable_gc && !aot_gen_commit_values(comp_ctx->aot_frame))
  992. return false;
  993. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  994. if (comp_ctx->enable_thread_mgr) {
  995. /* Commit sp when GC is enabled, don't commit ip */
  996. if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame,
  997. comp_ctx->enable_gc, false))
  998. return false;
  999. }
  1000. }
  1001. else {
  1002. if (comp_ctx->aot_frame->sp > block_dst->frame_sp_max_reached)
  1003. block_dst->frame_sp_max_reached = comp_ctx->aot_frame->sp;
  1004. }
  1005. }
  1006. /* Terminate or suspend current thread only when this is
  1007. a backward jump */
  1008. if (comp_ctx->enable_thread_mgr
  1009. && block_dst->label_type == LABEL_TYPE_LOOP) {
  1010. if (!check_suspend_flags(comp_ctx, func_ctx, true))
  1011. return false;
  1012. }
  1013. if (LLVMIsUndef(value_cmp)
  1014. #if LLVM_VERSION_NUMBER >= 12
  1015. || LLVMIsPoison(value_cmp)
  1016. #endif
  1017. ) {
  1018. if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW,
  1019. false, NULL, NULL))) {
  1020. goto fail;
  1021. }
  1022. return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  1023. }
  1024. if (!LLVMIsEfficientConstInt(value_cmp)) {
  1025. /* Compare value is not constant, create condition br IR */
  1026. /* Create llvm else block */
  1027. CREATE_BLOCK(llvm_else_block, "br_if_else");
  1028. MOVE_BLOCK_AFTER_CURR(llvm_else_block);
  1029. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  1030. /* Dest block is Loop block */
  1031. /* Handle Loop parameters */
  1032. if (block_dst->param_count) {
  1033. size = sizeof(LLVMValueRef) * (uint64)block_dst->param_count;
  1034. if (size >= UINT32_MAX
  1035. || !(values = wasm_runtime_malloc((uint32)size))) {
  1036. aot_set_last_error("allocate memory failed.");
  1037. goto fail;
  1038. }
  1039. for (i = 0; i < block_dst->param_count; i++) {
  1040. param_index = block_dst->param_count - 1 - i;
  1041. POP(value, block_dst->param_types[param_index]);
  1042. ADD_TO_PARAM_PHIS(block_dst, value, param_index);
  1043. values[param_index] = value;
  1044. }
  1045. for (i = 0; i < block_dst->param_count; i++) {
  1046. PUSH(values[i], block_dst->param_types[i]);
  1047. }
  1048. wasm_runtime_free(values);
  1049. values = NULL;
  1050. }
  1051. #if WASM_ENABLE_BRANCH_HINTS != 0
  1052. LLVMValueRef br_if_val = NULL;
  1053. BUILD_COND_BR_V(value_cmp, block_dst->llvm_entry_block,
  1054. llvm_else_block, br_if_val);
  1055. aot_emit_branch_hint(comp_ctx, func_ctx, instr_offset, br_if_val);
  1056. #else
  1057. BUILD_COND_BR(value_cmp, block_dst->llvm_entry_block,
  1058. llvm_else_block);
  1059. #endif
  1060. /* Move builder to else block */
  1061. SET_BUILDER_POS(llvm_else_block);
  1062. }
  1063. else {
  1064. /* Dest block is Block/If/Function block */
  1065. /* Create the end block */
  1066. if (!block_dst->llvm_end_block) {
  1067. format_block_name(name, sizeof(name), block_dst->block_index,
  1068. block_dst->label_type, LABEL_END);
  1069. CREATE_BLOCK(block_dst->llvm_end_block, name);
  1070. if ((next_llvm_end_block = find_next_llvm_end_block(block_dst)))
  1071. MOVE_BLOCK_BEFORE(block_dst->llvm_end_block,
  1072. next_llvm_end_block);
  1073. }
  1074. /* Set reachable flag and create condition br IR */
  1075. block_dst->is_reachable = true;
  1076. /* Handle result values */
  1077. if (block_dst->result_count) {
  1078. size = sizeof(LLVMValueRef) * (uint64)block_dst->result_count;
  1079. if (size >= UINT32_MAX
  1080. || !(values = wasm_runtime_malloc((uint32)size))) {
  1081. aot_set_last_error("allocate memory failed.");
  1082. goto fail;
  1083. }
  1084. CREATE_RESULT_VALUE_PHIS(block_dst);
  1085. for (i = 0; i < block_dst->result_count; i++) {
  1086. result_index = block_dst->result_count - 1 - i;
  1087. POP(value, block_dst->result_types[result_index]);
  1088. values[result_index] = value;
  1089. ADD_TO_RESULT_PHIS(block_dst, value, result_index);
  1090. }
  1091. for (i = 0; i < block_dst->result_count; i++) {
  1092. PUSH(values[i], block_dst->result_types[i]);
  1093. }
  1094. wasm_runtime_free(values);
  1095. values = NULL;
  1096. }
  1097. /* Condition jump to end block */
  1098. #if WASM_ENABLE_BRANCH_HINTS != 0
  1099. LLVMValueRef br_if_val = NULL;
  1100. BUILD_COND_BR_V(value_cmp, block_dst->llvm_end_block,
  1101. llvm_else_block, br_if_val);
  1102. aot_emit_branch_hint(comp_ctx, func_ctx, instr_offset, br_if_val);
  1103. #else
  1104. BUILD_COND_BR(value_cmp, block_dst->llvm_end_block,
  1105. llvm_else_block);
  1106. #endif
  1107. /* Move builder to else block */
  1108. SET_BUILDER_POS(llvm_else_block);
  1109. }
  1110. }
  1111. else {
  1112. if ((int32)LLVMConstIntGetZExtValue(value_cmp) != 0) {
  1113. /* Compare value is not 0, condition is true, same as op_br */
  1114. return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip);
  1115. }
  1116. else {
  1117. /* Compare value is not 0, condition is false, skip br_if */
  1118. return true;
  1119. }
  1120. }
  1121. return true;
  1122. fail:
  1123. if (values)
  1124. wasm_runtime_free(values);
  1125. return false;
  1126. }
  1127. bool
  1128. aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  1129. uint8 **p_frame_ip)
  1130. {
  1131. LLVMValueRef value_cmp;
  1132. POP_COND(value_cmp);
  1133. return aot_compile_conditional_br(comp_ctx, func_ctx, value_cmp,
  1134. p_frame_ip);
  1135. fail:
  1136. return false;
  1137. }
  1138. bool
  1139. aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  1140. uint32 *br_depths, uint32 br_count, uint8 **p_frame_ip)
  1141. {
  1142. uint32 i, j;
  1143. LLVMValueRef value_switch, value_cmp, value_case, value, *values = NULL;
  1144. LLVMBasicBlockRef default_llvm_block = NULL, target_llvm_block;
  1145. LLVMBasicBlockRef next_llvm_end_block;
  1146. AOTBlock *target_block;
  1147. uint32 br_depth, depth_idx;
  1148. uint32 param_index, result_index;
  1149. uint64 size;
  1150. char name[32];
  1151. POP_I32(value_cmp);
  1152. if (LLVMIsUndef(value_cmp)
  1153. #if LLVM_VERSION_NUMBER >= 12
  1154. || LLVMIsPoison(value_cmp)
  1155. #endif
  1156. ) {
  1157. if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW,
  1158. false, NULL, NULL))) {
  1159. goto fail;
  1160. }
  1161. return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  1162. }
  1163. /*
  1164. * if (value_cmp > br_count)
  1165. * value_cmp = br_count;
  1166. */
  1167. LLVMValueRef br_count_value = I32_CONST(br_count);
  1168. CHECK_LLVM_CONST(br_count_value);
  1169. LLVMValueRef clap_value_cmp_cond =
  1170. LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, value_cmp, br_count_value,
  1171. "cmp_w_br_count");
  1172. if (!clap_value_cmp_cond) {
  1173. aot_set_last_error("llvm build icmp failed.");
  1174. return false;
  1175. }
  1176. value_cmp = LLVMBuildSelect(comp_ctx->builder, clap_value_cmp_cond,
  1177. br_count_value, value_cmp, "clap_value_cmp");
  1178. if (!value_cmp) {
  1179. aot_set_last_error("llvm build select failed.");
  1180. return false;
  1181. }
  1182. if (!LLVMIsEfficientConstInt(value_cmp)) {
  1183. if (comp_ctx->aot_frame) {
  1184. if (comp_ctx->enable_gc
  1185. && !aot_gen_commit_values(comp_ctx->aot_frame))
  1186. return false;
  1187. if (comp_ctx->enable_thread_mgr) {
  1188. /* Commit sp when GC is enabled, don't commit ip */
  1189. if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame,
  1190. comp_ctx->enable_gc, false))
  1191. return false;
  1192. }
  1193. for (i = 0; i <= br_count; i++) {
  1194. target_block = get_target_block(func_ctx, br_depths[i]);
  1195. if (!target_block)
  1196. return false;
  1197. if (target_block->label_type != LABEL_TYPE_LOOP) {
  1198. if (comp_ctx->aot_frame->sp
  1199. > target_block->frame_sp_max_reached)
  1200. target_block->frame_sp_max_reached =
  1201. comp_ctx->aot_frame->sp;
  1202. }
  1203. }
  1204. }
  1205. if (comp_ctx->enable_thread_mgr) {
  1206. for (i = 0; i <= br_count; i++) {
  1207. target_block = get_target_block(func_ctx, br_depths[i]);
  1208. if (!target_block)
  1209. return false;
  1210. /* Terminate or suspend current thread only when this is a
  1211. backward jump */
  1212. if (target_block->label_type == LABEL_TYPE_LOOP) {
  1213. if (!check_suspend_flags(comp_ctx, func_ctx, true))
  1214. return false;
  1215. break;
  1216. }
  1217. }
  1218. }
  1219. /* Compare value is not constant, create switch IR */
  1220. for (i = 0; i <= br_count; i++) {
  1221. target_block = get_target_block(func_ctx, br_depths[i]);
  1222. if (!target_block)
  1223. return false;
  1224. if (target_block->label_type != LABEL_TYPE_LOOP) {
  1225. /* Dest block is Block/If/Function block */
  1226. /* Create the end block */
  1227. if (!target_block->llvm_end_block) {
  1228. format_block_name(name, sizeof(name),
  1229. target_block->block_index,
  1230. target_block->label_type, LABEL_END);
  1231. CREATE_BLOCK(target_block->llvm_end_block, name);
  1232. if ((next_llvm_end_block =
  1233. find_next_llvm_end_block(target_block)))
  1234. MOVE_BLOCK_BEFORE(target_block->llvm_end_block,
  1235. next_llvm_end_block);
  1236. }
  1237. /* Handle result values */
  1238. if (target_block->result_count) {
  1239. size = sizeof(LLVMValueRef)
  1240. * (uint64)target_block->result_count;
  1241. if (size >= UINT32_MAX
  1242. || !(values = wasm_runtime_malloc((uint32)size))) {
  1243. aot_set_last_error("allocate memory failed.");
  1244. goto fail;
  1245. }
  1246. CREATE_RESULT_VALUE_PHIS(target_block);
  1247. for (j = 0; j < target_block->result_count; j++) {
  1248. result_index = target_block->result_count - 1 - j;
  1249. POP(value, target_block->result_types[result_index]);
  1250. values[result_index] = value;
  1251. ADD_TO_RESULT_PHIS(target_block, value, result_index);
  1252. }
  1253. for (j = 0; j < target_block->result_count; j++) {
  1254. PUSH(values[j], target_block->result_types[j]);
  1255. }
  1256. wasm_runtime_free(values);
  1257. values = NULL;
  1258. }
  1259. target_block->is_reachable = true;
  1260. if (i == br_count)
  1261. default_llvm_block = target_block->llvm_end_block;
  1262. }
  1263. else {
  1264. /* Handle Loop parameters */
  1265. if (target_block->param_count) {
  1266. size = sizeof(LLVMValueRef)
  1267. * (uint64)target_block->param_count;
  1268. if (size >= UINT32_MAX
  1269. || !(values = wasm_runtime_malloc((uint32)size))) {
  1270. aot_set_last_error("allocate memory failed.");
  1271. goto fail;
  1272. }
  1273. for (j = 0; j < target_block->param_count; j++) {
  1274. param_index = target_block->param_count - 1 - j;
  1275. POP(value, target_block->param_types[param_index]);
  1276. values[param_index] = value;
  1277. ADD_TO_PARAM_PHIS(target_block, value, param_index);
  1278. }
  1279. for (j = 0; j < target_block->param_count; j++) {
  1280. PUSH(values[j], target_block->param_types[j]);
  1281. }
  1282. wasm_runtime_free(values);
  1283. values = NULL;
  1284. }
  1285. if (i == br_count)
  1286. default_llvm_block = target_block->llvm_entry_block;
  1287. }
  1288. }
  1289. /* Create switch IR */
  1290. if (!(value_switch = LLVMBuildSwitch(comp_ctx->builder, value_cmp,
  1291. default_llvm_block, br_count))) {
  1292. aot_set_last_error("llvm build switch failed.");
  1293. return false;
  1294. }
  1295. /* Add each case for switch IR */
  1296. for (i = 0; i < br_count; i++) {
  1297. value_case = I32_CONST(i);
  1298. CHECK_LLVM_CONST(value_case);
  1299. target_block = get_target_block(func_ctx, br_depths[i]);
  1300. if (!target_block)
  1301. return false;
  1302. target_llvm_block = target_block->label_type != LABEL_TYPE_LOOP
  1303. ? target_block->llvm_end_block
  1304. : target_block->llvm_entry_block;
  1305. LLVMAddCase(value_switch, value_case, target_llvm_block);
  1306. }
  1307. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  1308. }
  1309. else {
  1310. /* Compare value is constant, create br IR */
  1311. depth_idx = (uint32)LLVMConstIntGetZExtValue(value_cmp);
  1312. br_depth = br_depths[br_count];
  1313. if (depth_idx < br_count) {
  1314. br_depth = br_depths[depth_idx];
  1315. }
  1316. return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip);
  1317. }
  1318. fail:
  1319. if (values)
  1320. wasm_runtime_free(values);
  1321. return false;
  1322. }
  1323. bool
  1324. aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  1325. uint8 **p_frame_ip)
  1326. {
  1327. AOTBlock *block_func = func_ctx->block_stack.block_list_head;
  1328. LLVMValueRef value;
  1329. LLVMValueRef ret;
  1330. AOTFuncType *func_type;
  1331. uint32 i, param_index, result_index;
  1332. #if WASM_ENABLE_DEBUG_AOT != 0
  1333. LLVMMetadataRef return_location;
  1334. #endif
  1335. bh_assert(block_func);
  1336. func_type = func_ctx->aot_func->func_type;
  1337. #if WASM_ENABLE_DEBUG_AOT != 0
  1338. return_location = dwarf_gen_location(
  1339. comp_ctx, func_ctx,
  1340. (*p_frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code);
  1341. #endif
  1342. if (comp_ctx->aux_stack_frame_type
  1343. && comp_ctx->call_stack_features.frame_per_function
  1344. && !aot_free_frame_per_function_frame_for_aot_func(comp_ctx,
  1345. func_ctx)) {
  1346. return false;
  1347. }
  1348. if (block_func->result_count) {
  1349. /* Store extra result values to function parameters */
  1350. for (i = 0; i < block_func->result_count - 1; i++) {
  1351. LLVMValueRef res;
  1352. result_index = block_func->result_count - 1 - i;
  1353. POP(value, block_func->result_types[result_index]);
  1354. param_index = func_type->param_count + result_index;
  1355. if (!(res = LLVMBuildStore(
  1356. comp_ctx->builder, value,
  1357. LLVMGetParam(func_ctx->func, param_index)))) {
  1358. aot_set_last_error("llvm build store failed.");
  1359. goto fail;
  1360. }
  1361. LLVMSetAlignment(res, 1);
  1362. }
  1363. /* Return the first result value */
  1364. POP(value, block_func->result_types[0]);
  1365. if (!(ret = LLVMBuildRet(comp_ctx->builder, value))) {
  1366. aot_set_last_error("llvm build return failed.");
  1367. goto fail;
  1368. }
  1369. #if WASM_ENABLE_DEBUG_AOT != 0
  1370. LLVMInstructionSetDebugLoc(ret, return_location);
  1371. #endif
  1372. }
  1373. else {
  1374. if (!(ret = LLVMBuildRetVoid(comp_ctx->builder))) {
  1375. aot_set_last_error("llvm build return void failed.");
  1376. goto fail;
  1377. }
  1378. #if WASM_ENABLE_DEBUG_AOT != 0
  1379. LLVMInstructionSetDebugLoc(ret, return_location);
  1380. #endif
  1381. }
  1382. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  1383. fail:
  1384. return false;
  1385. }
  1386. bool
  1387. aot_compile_op_unreachable(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  1388. uint8 **p_frame_ip)
  1389. {
  1390. if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_UNREACHABLE, false, NULL,
  1391. NULL))
  1392. return false;
  1393. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  1394. }
  1395. bool
  1396. aot_handle_next_reachable_block(AOTCompContext *comp_ctx,
  1397. AOTFuncContext *func_ctx, uint8 **p_frame_ip)
  1398. {
  1399. return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
  1400. }
  1401. #if WASM_ENABLE_GC != 0
  1402. static bool
  1403. commit_gc_and_check_suspend_flags(AOTCompContext *comp_ctx,
  1404. AOTFuncContext *func_ctx, uint32 br_depth)
  1405. {
  1406. AOTBlock *block_dst;
  1407. if (!(block_dst = get_target_block(func_ctx, br_depth))) {
  1408. return false;
  1409. }
  1410. if (comp_ctx->aot_frame) {
  1411. /* Note that GC is enabled, no need to check it again */
  1412. if (!aot_gen_commit_values(comp_ctx->aot_frame))
  1413. return false;
  1414. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  1415. if (comp_ctx->enable_thread_mgr) {
  1416. /* Note that GC is enabled, no need to check it again */
  1417. if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, true, false))
  1418. return false;
  1419. }
  1420. }
  1421. else {
  1422. if (comp_ctx->aot_frame->sp > block_dst->frame_sp_max_reached)
  1423. block_dst->frame_sp_max_reached = comp_ctx->aot_frame->sp;
  1424. }
  1425. }
  1426. /* Terminate or suspend current thread only when this is
  1427. a backward jump */
  1428. if (comp_ctx->enable_thread_mgr
  1429. && block_dst->label_type == LABEL_TYPE_LOOP) {
  1430. if (!check_suspend_flags(comp_ctx, func_ctx, true))
  1431. return false;
  1432. }
  1433. return true;
  1434. }
  1435. static bool
  1436. compile_gc_cond_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  1437. uint32 br_depth, LLVMValueRef value_cmp)
  1438. {
  1439. AOTBlock *block_dst;
  1440. LLVMValueRef value, *values = NULL;
  1441. LLVMBasicBlockRef llvm_else_block, next_llvm_end_block;
  1442. char name[32];
  1443. uint32 i, param_index, result_index;
  1444. uint64 size;
  1445. if (!(block_dst = get_target_block(func_ctx, br_depth))) {
  1446. return false;
  1447. }
  1448. /* Create llvm else block */
  1449. CREATE_BLOCK(llvm_else_block, "br_if_else");
  1450. MOVE_BLOCK_AFTER_CURR(llvm_else_block);
  1451. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  1452. /* Dest block is Loop block */
  1453. /* Handle Loop parameters */
  1454. if (block_dst->param_count) {
  1455. size = sizeof(LLVMValueRef) * (uint64)block_dst->param_count;
  1456. if (size >= UINT32_MAX
  1457. || !(values = wasm_runtime_malloc((uint32)size))) {
  1458. aot_set_last_error("allocate memory failed.");
  1459. goto fail;
  1460. }
  1461. for (i = 0; i < block_dst->param_count; i++) {
  1462. param_index = block_dst->param_count - 1 - i;
  1463. POP(value, block_dst->param_types[param_index]);
  1464. ADD_TO_PARAM_PHIS(block_dst, value, param_index);
  1465. values[param_index] = value;
  1466. }
  1467. for (i = 0; i < block_dst->param_count; i++) {
  1468. PUSH(values[i], block_dst->param_types[i]);
  1469. }
  1470. wasm_runtime_free(values);
  1471. values = NULL;
  1472. }
  1473. BUILD_COND_BR(value_cmp, block_dst->llvm_entry_block, llvm_else_block);
  1474. /* Move builder to else block */
  1475. SET_BUILDER_POS(llvm_else_block);
  1476. }
  1477. else {
  1478. /* Dest block is Block/If/Function block */
  1479. /* Create the end block */
  1480. if (!block_dst->llvm_end_block) {
  1481. format_block_name(name, sizeof(name), block_dst->block_index,
  1482. block_dst->label_type, LABEL_END);
  1483. CREATE_BLOCK(block_dst->llvm_end_block, name);
  1484. if ((next_llvm_end_block = find_next_llvm_end_block(block_dst)))
  1485. MOVE_BLOCK_BEFORE(block_dst->llvm_end_block,
  1486. next_llvm_end_block);
  1487. }
  1488. /* Set reachable flag and create condition br IR */
  1489. block_dst->is_reachable = true;
  1490. /* Handle result values */
  1491. if (block_dst->result_count) {
  1492. size = sizeof(LLVMValueRef) * (uint64)block_dst->result_count;
  1493. if (size >= UINT32_MAX
  1494. || !(values = wasm_runtime_malloc((uint32)size))) {
  1495. aot_set_last_error("allocate memory failed.");
  1496. goto fail;
  1497. }
  1498. CREATE_RESULT_VALUE_PHIS(block_dst);
  1499. for (i = 0; i < block_dst->result_count; i++) {
  1500. result_index = block_dst->result_count - 1 - i;
  1501. POP(value, block_dst->result_types[result_index]);
  1502. values[result_index] = value;
  1503. ADD_TO_RESULT_PHIS(block_dst, value, result_index);
  1504. }
  1505. for (i = 0; i < block_dst->result_count; i++) {
  1506. PUSH(values[i], block_dst->result_types[i]);
  1507. }
  1508. wasm_runtime_free(values);
  1509. values = NULL;
  1510. }
  1511. /* Condition jump to end block */
  1512. BUILD_COND_BR(value_cmp, block_dst->llvm_end_block, llvm_else_block);
  1513. /* Move builder to else block */
  1514. SET_BUILDER_POS(llvm_else_block);
  1515. }
  1516. return true;
  1517. fail:
  1518. if (values)
  1519. wasm_runtime_free(values);
  1520. return false;
  1521. }
  1522. bool
  1523. aot_compile_op_br_on_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  1524. uint32 br_depth, uint8 **p_frame_ip)
  1525. {
  1526. LLVMValueRef gc_obj, value_cmp;
  1527. if (!commit_gc_and_check_suspend_flags(comp_ctx, func_ctx, br_depth)) {
  1528. return false;
  1529. }
  1530. POP_GC_REF(gc_obj);
  1531. if (!(value_cmp =
  1532. LLVMBuildIsNull(comp_ctx->builder, gc_obj, "cmp_gc_obj"))) {
  1533. aot_set_last_error("llvm build isnull failed.");
  1534. goto fail;
  1535. }
  1536. if (!compile_gc_cond_br(comp_ctx, func_ctx, br_depth, value_cmp)) {
  1537. goto fail;
  1538. }
  1539. PUSH_GC_REF(gc_obj);
  1540. return true;
  1541. fail:
  1542. return false;
  1543. }
  1544. bool
  1545. aot_compile_op_br_on_non_null(AOTCompContext *comp_ctx,
  1546. AOTFuncContext *func_ctx, uint32 br_depth,
  1547. uint8 **p_frame_ip)
  1548. {
  1549. LLVMValueRef gc_obj, value_cmp;
  1550. if (!commit_gc_and_check_suspend_flags(comp_ctx, func_ctx, br_depth)) {
  1551. return false;
  1552. }
  1553. GET_GC_REF_FROM_STACK(gc_obj);
  1554. if (!(value_cmp =
  1555. LLVMBuildIsNotNull(comp_ctx->builder, gc_obj, "cmp_gc_obj"))) {
  1556. aot_set_last_error("llvm build isnotnull failed.");
  1557. goto fail;
  1558. }
  1559. if (!compile_gc_cond_br(comp_ctx, func_ctx, br_depth, value_cmp)) {
  1560. goto fail;
  1561. }
  1562. POP_GC_REF(gc_obj);
  1563. return true;
  1564. fail:
  1565. return false;
  1566. }
  1567. bool
  1568. aot_compile_op_br_on_cast(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  1569. int32 heap_type, bool nullable, bool br_on_fail,
  1570. uint32 br_depth, uint8 **p_frame_ip)
  1571. {
  1572. LLVMValueRef gc_obj, is_null, castable, not_castable, br_if_phi;
  1573. LLVMBasicBlockRef block_curr, block_non_null, block_br_if;
  1574. if (!commit_gc_and_check_suspend_flags(comp_ctx, func_ctx, br_depth)) {
  1575. return false;
  1576. }
  1577. GET_GC_REF_FROM_STACK(gc_obj);
  1578. block_curr = CURR_BLOCK();
  1579. CREATE_BLOCK(block_non_null, "obj_non_null");
  1580. MOVE_BLOCK_AFTER_CURR(block_non_null);
  1581. CREATE_BLOCK(block_br_if, "br_if");
  1582. MOVE_BLOCK_AFTER(block_br_if, block_non_null);
  1583. SET_BUILDER_POS(block_br_if);
  1584. if (!(br_if_phi =
  1585. LLVMBuildPhi(comp_ctx->builder, INT1_TYPE, "br_if_phi"))) {
  1586. aot_set_last_error("llvm build phi failed.");
  1587. goto fail;
  1588. }
  1589. SET_BUILDER_POS(block_curr);
  1590. if (!(is_null = LLVMBuildIsNull(comp_ctx->builder, gc_obj, "is_null"))) {
  1591. aot_set_last_error("llvm build isnull failed.");
  1592. goto fail;
  1593. }
  1594. BUILD_COND_BR(is_null, block_br_if, block_non_null);
  1595. if ((!br_on_fail && nullable) || (br_on_fail && !nullable)) {
  1596. LLVMAddIncoming(br_if_phi, &I1_ONE, &block_curr, 1);
  1597. }
  1598. else { /* (!br_on_fail && !nullable) || (br_on_fail && nullable)) */
  1599. LLVMAddIncoming(br_if_phi, &I1_ZERO, &block_curr, 1);
  1600. }
  1601. SET_BUILDER_POS(block_non_null);
  1602. if (heap_type >= 0) {
  1603. if (!aot_call_aot_obj_is_instance_of(comp_ctx, func_ctx, gc_obj,
  1604. I32_CONST(heap_type), &castable))
  1605. goto fail;
  1606. }
  1607. else {
  1608. if (!aot_call_wasm_obj_is_type_of(comp_ctx, func_ctx, gc_obj,
  1609. I32_CONST(heap_type), &castable))
  1610. goto fail;
  1611. }
  1612. if (!br_on_fail) {
  1613. if (!(castable = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, castable,
  1614. I8_ZERO, "castable"))) {
  1615. aot_set_last_error("llvm build icmp failed.");
  1616. return false;
  1617. }
  1618. LLVMAddIncoming(br_if_phi, &castable, &block_non_null, 1);
  1619. }
  1620. else {
  1621. if (!(not_castable = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
  1622. castable, I8_ZERO, "castable"))) {
  1623. aot_set_last_error("llvm build icmp failed.");
  1624. return false;
  1625. }
  1626. LLVMAddIncoming(br_if_phi, &not_castable, &block_non_null, 1);
  1627. }
  1628. BUILD_BR(block_br_if);
  1629. SET_BUILDER_POS(block_br_if);
  1630. if (!compile_gc_cond_br(comp_ctx, func_ctx, br_depth, br_if_phi)) {
  1631. goto fail;
  1632. }
  1633. return true;
  1634. fail:
  1635. return false;
  1636. }
  1637. #endif /* End of WASM_ENABLE_GC != 0 */