aot_emit_control.c 61 KB

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