aot_emit_control.c 63 KB

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