jit_emit_control.c 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "jit_emit_control.h"
  6. #include "jit_emit_exception.h"
  7. #include "jit_emit_function.h"
  8. #include "../jit_frontend.h"
  9. #include "../interpreter/wasm_loader.h"
  10. #define CREATE_BASIC_BLOCK(new_basic_block) \
  11. do { \
  12. bh_assert(!new_basic_block); \
  13. if (!(new_basic_block = jit_cc_new_basic_block(cc, 0))) { \
  14. jit_set_last_error(cc, "create basic block failed"); \
  15. goto fail; \
  16. } \
  17. } while (0)
  18. #define CURR_BASIC_BLOCK() cc->cur_basic_block
  19. #define BUILD_BR(target_block) \
  20. do { \
  21. if (!GEN_INSN(JMP, jit_basic_block_label(target_block))) { \
  22. jit_set_last_error(cc, "generate jmp insn failed"); \
  23. goto fail; \
  24. } \
  25. } while (0)
  26. #define BUILD_COND_BR(value_if, block_then, block_else) \
  27. do { \
  28. if (!GEN_INSN(CMP, cc->cmp_reg, value_if, NEW_CONST(I32, 0)) \
  29. || !GEN_INSN(BNE, cc->cmp_reg, jit_basic_block_label(block_then), \
  30. jit_basic_block_label(block_else))) { \
  31. jit_set_last_error(cc, "generate bne insn failed"); \
  32. goto fail; \
  33. } \
  34. } while (0)
  35. #define SET_BUILDER_POS(basic_block) \
  36. do { \
  37. cc->cur_basic_block = basic_block; \
  38. } while (0)
  39. #define SET_BB_BEGIN_BCIP(basic_block, bcip) \
  40. do { \
  41. *(jit_annl_begin_bcip(cc, jit_basic_block_label(basic_block))) = bcip; \
  42. } while (0)
  43. #define SET_BB_END_BCIP(basic_block, bcip) \
  44. do { \
  45. *(jit_annl_end_bcip(cc, jit_basic_block_label(basic_block))) = bcip; \
  46. } while (0)
  47. static JitBlock *
  48. get_target_block(JitCompContext *cc, uint32 br_depth)
  49. {
  50. uint32 i = br_depth;
  51. JitBlock *block = jit_block_stack_top(&cc->block_stack);
  52. while (i-- > 0 && block) {
  53. block = block->prev;
  54. }
  55. if (!block) {
  56. jit_set_last_error(cc, "WASM block stack underflow");
  57. return NULL;
  58. }
  59. return block;
  60. }
  61. static bool
  62. load_block_params(JitCompContext *cc, JitBlock *block)
  63. {
  64. JitFrame *jit_frame = cc->jit_frame;
  65. uint32 offset, i;
  66. JitReg value = 0;
  67. /* Clear jit frame's locals and stacks */
  68. clear_values(jit_frame);
  69. /* Restore jit frame's sp to block's sp begin */
  70. jit_frame->sp = block->frame_sp_begin;
  71. /* Load params to new block */
  72. offset = (uint32)(jit_frame->sp - jit_frame->lp);
  73. for (i = 0; i < block->param_count; i++) {
  74. switch (block->param_types[i]) {
  75. case VALUE_TYPE_I32:
  76. #if WASM_ENABLE_REF_TYPES != 0
  77. case VALUE_TYPE_EXTERNREF:
  78. case VALUE_TYPE_FUNCREF:
  79. #endif
  80. value = gen_load_i32(jit_frame, offset);
  81. offset++;
  82. break;
  83. case VALUE_TYPE_I64:
  84. value = gen_load_i64(jit_frame, offset);
  85. offset += 2;
  86. break;
  87. case VALUE_TYPE_F32:
  88. value = gen_load_f32(jit_frame, offset);
  89. offset++;
  90. break;
  91. case VALUE_TYPE_F64:
  92. value = gen_load_f64(jit_frame, offset);
  93. offset += 2;
  94. break;
  95. default:
  96. bh_assert(0);
  97. break;
  98. }
  99. PUSH(value, block->param_types[i]);
  100. }
  101. return true;
  102. fail:
  103. return false;
  104. }
  105. static bool
  106. load_block_results(JitCompContext *cc, JitBlock *block)
  107. {
  108. JitFrame *jit_frame = cc->jit_frame;
  109. uint32 offset, i;
  110. JitReg value = 0;
  111. /* Restore jit frame's sp to block's sp begin */
  112. jit_frame->sp = block->frame_sp_begin;
  113. /* Load results to new block */
  114. offset = (uint32)(jit_frame->sp - jit_frame->lp);
  115. for (i = 0; i < block->result_count; i++) {
  116. switch (block->result_types[i]) {
  117. case VALUE_TYPE_I32:
  118. #if WASM_ENABLE_REF_TYPES != 0
  119. case VALUE_TYPE_EXTERNREF:
  120. case VALUE_TYPE_FUNCREF:
  121. #endif
  122. value = gen_load_i32(jit_frame, offset);
  123. offset++;
  124. break;
  125. case VALUE_TYPE_I64:
  126. value = gen_load_i64(jit_frame, offset);
  127. offset += 2;
  128. break;
  129. case VALUE_TYPE_F32:
  130. value = gen_load_f32(jit_frame, offset);
  131. offset++;
  132. break;
  133. case VALUE_TYPE_F64:
  134. value = gen_load_f64(jit_frame, offset);
  135. offset += 2;
  136. break;
  137. default:
  138. bh_assert(0);
  139. break;
  140. }
  141. PUSH(value, block->result_types[i]);
  142. }
  143. return true;
  144. fail:
  145. return false;
  146. }
  147. static bool
  148. jit_reg_is_i32_const(JitCompContext *cc, JitReg reg, int32 val)
  149. {
  150. return (jit_reg_kind(reg) == JIT_REG_KIND_I32 && jit_reg_is_const(reg)
  151. && jit_cc_get_const_I32(cc, reg) == val)
  152. ? true
  153. : false;
  154. }
  155. /**
  156. * get the last two insns:
  157. * CMP cmp_reg, r0, r1
  158. * SELECTcc r2, cmp_reg, 1, 0
  159. */
  160. static void
  161. get_last_cmp_and_selectcc(JitCompContext *cc, JitReg cond, JitInsn **p_insn_cmp,
  162. JitInsn **p_insn_select)
  163. {
  164. JitInsn *insn = jit_basic_block_last_insn(cc->cur_basic_block);
  165. if (insn && insn->prev && insn->prev->opcode == JIT_OP_CMP
  166. && insn->opcode >= JIT_OP_SELECTEQ && insn->opcode <= JIT_OP_SELECTLEU
  167. && *jit_insn_opnd(insn, 0) == cond
  168. && jit_reg_is_i32_const(cc, *jit_insn_opnd(insn, 2), 1)
  169. && jit_reg_is_i32_const(cc, *jit_insn_opnd(insn, 3), 0)) {
  170. *p_insn_cmp = insn->prev;
  171. *p_insn_select = insn;
  172. }
  173. }
  174. static bool
  175. push_jit_block_to_stack_and_pass_params(JitCompContext *cc, JitBlock *block,
  176. JitBasicBlock *basic_block, JitReg cond,
  177. bool merge_cmp_and_if)
  178. {
  179. JitFrame *jit_frame = cc->jit_frame;
  180. JitValue *value_list_head = NULL, *value_list_end = NULL, *jit_value;
  181. JitInsn *insn;
  182. JitReg value;
  183. uint32 i, param_index, cell_num;
  184. if (cc->cur_basic_block == basic_block) {
  185. /* Reuse the current basic block and no need to commit values,
  186. we just move param values from current block's value stack to
  187. the new block's value stack */
  188. for (i = 0; i < block->param_count; i++) {
  189. jit_value = jit_value_stack_pop(
  190. &jit_block_stack_top(&cc->block_stack)->value_stack);
  191. if (!value_list_head) {
  192. value_list_head = value_list_end = jit_value;
  193. jit_value->prev = jit_value->next = NULL;
  194. }
  195. else {
  196. jit_value->prev = NULL;
  197. jit_value->next = value_list_head;
  198. value_list_head->prev = jit_value;
  199. value_list_head = jit_value;
  200. }
  201. }
  202. block->value_stack.value_list_head = value_list_head;
  203. block->value_stack.value_list_end = value_list_end;
  204. /* Save block's begin frame sp */
  205. cell_num = wasm_get_cell_num(block->param_types, block->param_count);
  206. block->frame_sp_begin = jit_frame->sp - cell_num;
  207. /* Push the new block to block stack */
  208. jit_block_stack_push(&cc->block_stack, block);
  209. /* Continue to translate current block */
  210. }
  211. else {
  212. JitInsn *insn_select = NULL, *insn_cmp = NULL;
  213. if (merge_cmp_and_if) {
  214. get_last_cmp_and_selectcc(cc, cond, &insn_cmp, &insn_select);
  215. }
  216. /* Commit register values to locals and stacks */
  217. gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
  218. /* Pop param values from current block's value stack */
  219. for (i = 0; i < block->param_count; i++) {
  220. param_index = block->param_count - 1 - i;
  221. POP(value, block->param_types[param_index]);
  222. }
  223. /* Clear frame values */
  224. clear_values(jit_frame);
  225. /* Save block's begin frame sp */
  226. block->frame_sp_begin = jit_frame->sp;
  227. /* Push the new block to block stack */
  228. jit_block_stack_push(&cc->block_stack, block);
  229. if (block->label_type == LABEL_TYPE_LOOP) {
  230. BUILD_BR(basic_block);
  231. }
  232. else {
  233. /* IF block with condition br insn */
  234. if (insn_select && insn_cmp) {
  235. /* Change `CMP + SELECTcc` into `CMP + Bcc` */
  236. if (!(insn = GEN_INSN(BEQ, cc->cmp_reg,
  237. jit_basic_block_label(basic_block), 0))) {
  238. jit_set_last_error(cc, "generate cond br failed");
  239. goto fail;
  240. }
  241. insn->opcode =
  242. JIT_OP_BEQ + (insn_select->opcode - JIT_OP_SELECTEQ);
  243. jit_insn_unlink(insn_select);
  244. jit_insn_delete(insn_select);
  245. }
  246. else {
  247. if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0))
  248. || !(insn =
  249. GEN_INSN(BNE, cc->cmp_reg,
  250. jit_basic_block_label(basic_block), 0))) {
  251. jit_set_last_error(cc, "generate cond br failed");
  252. goto fail;
  253. }
  254. }
  255. /* Don't create else basic block or end basic block now, just
  256. save its incoming BNE insn, and patch the insn's else label
  257. when the basic block is lazily created */
  258. if (block->wasm_code_else) {
  259. block->incoming_insn_for_else_bb = insn;
  260. }
  261. else {
  262. if (!jit_block_add_incoming_insn(block, insn, 2)) {
  263. jit_set_last_error(cc, "add incoming insn failed");
  264. goto fail;
  265. }
  266. }
  267. }
  268. /* Start to translate the block */
  269. SET_BUILDER_POS(basic_block);
  270. /* Push the block parameters */
  271. if (!load_block_params(cc, block)) {
  272. goto fail;
  273. }
  274. }
  275. return true;
  276. fail:
  277. return false;
  278. }
  279. static void
  280. copy_block_arities(JitCompContext *cc, JitReg dst_frame_sp, uint8 *dst_types,
  281. uint32 dst_type_count, JitReg *p_first_res_reg)
  282. {
  283. JitFrame *jit_frame;
  284. uint32 offset_src, offset_dst, i;
  285. JitReg value;
  286. jit_frame = cc->jit_frame;
  287. offset_src = (uint32)(jit_frame->sp - jit_frame->lp)
  288. - wasm_get_cell_num(dst_types, dst_type_count);
  289. offset_dst = 0;
  290. /* pop values from stack and store to dest frame */
  291. for (i = 0; i < dst_type_count; i++) {
  292. switch (dst_types[i]) {
  293. case VALUE_TYPE_I32:
  294. #if WASM_ENABLE_REF_TYPES != 0
  295. case VALUE_TYPE_EXTERNREF:
  296. case VALUE_TYPE_FUNCREF:
  297. #endif
  298. value = gen_load_i32(jit_frame, offset_src);
  299. if (i == 0 && p_first_res_reg)
  300. *p_first_res_reg = value;
  301. else
  302. GEN_INSN(STI32, value, dst_frame_sp,
  303. NEW_CONST(I32, offset_dst * 4));
  304. offset_src++;
  305. offset_dst++;
  306. break;
  307. case VALUE_TYPE_I64:
  308. value = gen_load_i64(jit_frame, offset_src);
  309. if (i == 0 && p_first_res_reg)
  310. *p_first_res_reg = value;
  311. else
  312. GEN_INSN(STI64, value, dst_frame_sp,
  313. NEW_CONST(I32, offset_dst * 4));
  314. offset_src += 2;
  315. offset_dst += 2;
  316. break;
  317. case VALUE_TYPE_F32:
  318. value = gen_load_f32(jit_frame, offset_src);
  319. if (i == 0 && p_first_res_reg)
  320. *p_first_res_reg = value;
  321. else
  322. GEN_INSN(STF32, value, dst_frame_sp,
  323. NEW_CONST(I32, offset_dst * 4));
  324. offset_src++;
  325. offset_dst++;
  326. break;
  327. case VALUE_TYPE_F64:
  328. value = gen_load_f64(jit_frame, offset_src);
  329. if (i == 0 && p_first_res_reg)
  330. *p_first_res_reg = value;
  331. else
  332. GEN_INSN(STF64, value, dst_frame_sp,
  333. NEW_CONST(I32, offset_dst * 4));
  334. offset_src += 2;
  335. offset_dst += 2;
  336. break;
  337. default:
  338. bh_assert(0);
  339. break;
  340. }
  341. }
  342. }
  343. static bool
  344. handle_func_return(JitCompContext *cc, JitBlock *block)
  345. {
  346. JitReg prev_frame, prev_frame_sp;
  347. JitReg ret_reg = 0;
  348. #if WASM_ENABLE_PERF_PROFILING != 0
  349. JitReg func_inst = jit_cc_new_reg_ptr(cc);
  350. JitReg time_start = jit_cc_new_reg_I64(cc);
  351. JitReg time_end = jit_cc_new_reg_I64(cc);
  352. JitReg cur_exec_time = jit_cc_new_reg_I64(cc);
  353. JitReg total_exec_time = jit_cc_new_reg_I64(cc);
  354. JitReg total_exec_cnt = jit_cc_new_reg_I32(cc);
  355. #endif
  356. #if WASM_ENABLE_PERF_PROFILING != 0
  357. /* time_end = os_time_get_boot_us() */
  358. if (!jit_emit_callnative(cc, os_time_get_boot_us, time_end, NULL, 0)) {
  359. return false;
  360. }
  361. /* time_start = cur_frame->time_started */
  362. GEN_INSN(LDI64, time_start, cc->fp_reg,
  363. NEW_CONST(I32, offsetof(WASMInterpFrame, time_started)));
  364. /* cur_exec_time = time_end - time_start */
  365. GEN_INSN(SUB, cur_exec_time, time_end, time_start);
  366. /* func_inst = cur_frame->function */
  367. GEN_INSN(LDPTR, func_inst, cc->fp_reg,
  368. NEW_CONST(I32, offsetof(WASMInterpFrame, function)));
  369. /* total_exec_time = func_inst->total_exec_time */
  370. GEN_INSN(LDI64, total_exec_time, func_inst,
  371. NEW_CONST(I32, offsetof(WASMFunctionInstance, total_exec_time)));
  372. /* total_exec_time += cur_exec_time */
  373. GEN_INSN(ADD, total_exec_time, total_exec_time, cur_exec_time);
  374. /* func_inst->total_exec_time = total_exec_time */
  375. GEN_INSN(STI64, total_exec_time, func_inst,
  376. NEW_CONST(I32, offsetof(WASMFunctionInstance, total_exec_time)));
  377. /* totoal_exec_cnt = func_inst->total_exec_cnt */
  378. GEN_INSN(LDI32, total_exec_cnt, func_inst,
  379. NEW_CONST(I32, offsetof(WASMFunctionInstance, total_exec_cnt)));
  380. /* total_exec_cnt++ */
  381. GEN_INSN(ADD, total_exec_cnt, total_exec_cnt, NEW_CONST(I32, 1));
  382. /* func_inst->total_exec_cnt = total_exec_cnt */
  383. GEN_INSN(STI32, total_exec_cnt, func_inst,
  384. NEW_CONST(I32, offsetof(WASMFunctionInstance, total_exec_cnt)));
  385. #endif
  386. prev_frame = jit_cc_new_reg_ptr(cc);
  387. prev_frame_sp = jit_cc_new_reg_ptr(cc);
  388. /* prev_frame = cur_frame->prev_frame */
  389. GEN_INSN(LDPTR, prev_frame, cc->fp_reg,
  390. NEW_CONST(I32, offsetof(WASMInterpFrame, prev_frame)));
  391. GEN_INSN(LDPTR, prev_frame_sp, prev_frame,
  392. NEW_CONST(I32, offsetof(WASMInterpFrame, sp)));
  393. if (block->result_count) {
  394. uint32 cell_num =
  395. wasm_get_cell_num(block->result_types, block->result_count);
  396. copy_block_arities(cc, prev_frame_sp, block->result_types,
  397. block->result_count, &ret_reg);
  398. /* prev_frame->sp += cell_num */
  399. GEN_INSN(ADD, prev_frame_sp, prev_frame_sp,
  400. NEW_CONST(PTR, cell_num * 4));
  401. GEN_INSN(STPTR, prev_frame_sp, prev_frame,
  402. NEW_CONST(I32, offsetof(WASMInterpFrame, sp)));
  403. }
  404. /* Free stack space of the current frame:
  405. exec_env->wasm_stack.s.top = cur_frame */
  406. GEN_INSN(STPTR, cc->fp_reg, cc->exec_env_reg,
  407. NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.s.top)));
  408. /* Set the prev_frame as the current frame:
  409. exec_env->cur_frame = prev_frame */
  410. GEN_INSN(STPTR, prev_frame, cc->exec_env_reg,
  411. NEW_CONST(I32, offsetof(WASMExecEnv, cur_frame)));
  412. /* fp_reg = prev_frame */
  413. GEN_INSN(MOV, cc->fp_reg, prev_frame);
  414. /* return 0 */
  415. GEN_INSN(RETURNBC, NEW_CONST(I32, JIT_INTERP_ACTION_NORMAL), ret_reg, 0);
  416. return true;
  417. }
  418. /**
  419. * is_block_polymorphic: whether current block's stack is in polymorphic state,
  420. * if the opcode is one of unreachable/br/br_table/return, stack is marked
  421. * to polymorphic state until the block's 'end' opcode is processed
  422. */
  423. static bool
  424. handle_op_end(JitCompContext *cc, uint8 **p_frame_ip, bool is_block_polymorphic)
  425. {
  426. JitFrame *jit_frame = cc->jit_frame;
  427. JitBlock *block, *block_prev;
  428. JitIncomingInsn *incoming_insn;
  429. JitInsn *insn;
  430. /* Check block stack */
  431. if (!(block = jit_block_stack_top(&cc->block_stack))) {
  432. jit_set_last_error(cc, "WASM block stack underflow");
  433. return false;
  434. }
  435. if (!block->incoming_insns_for_end_bb) {
  436. /* No other basic blocks jumping to this end, no need to
  437. create the end basic block, just continue to translate
  438. the following opcodes */
  439. if (block->label_type == LABEL_TYPE_FUNCTION) {
  440. if (!handle_func_return(cc, block)) {
  441. return false;
  442. }
  443. SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
  444. clear_values(jit_frame);
  445. }
  446. else if (block->result_count > 0) {
  447. JitValue *value_list_head = NULL, *value_list_end = NULL;
  448. JitValue *jit_value;
  449. uint32 i;
  450. /* No need to change cc->jit_frame, just move result values
  451. from current block's value stack to previous block's
  452. value stack */
  453. block_prev = block->prev;
  454. for (i = 0; i < block->result_count; i++) {
  455. jit_value = jit_value_stack_pop(&block->value_stack);
  456. bh_assert(jit_value);
  457. if (!value_list_head) {
  458. value_list_head = value_list_end = jit_value;
  459. jit_value->prev = jit_value->next = NULL;
  460. }
  461. else {
  462. jit_value->prev = NULL;
  463. jit_value->next = value_list_head;
  464. value_list_head->prev = jit_value;
  465. value_list_head = jit_value;
  466. }
  467. }
  468. if (!block_prev->value_stack.value_list_head) {
  469. block_prev->value_stack.value_list_head = value_list_head;
  470. block_prev->value_stack.value_list_end = value_list_end;
  471. }
  472. else {
  473. /* Link to the end of previous block's value stack */
  474. block_prev->value_stack.value_list_end->next = value_list_head;
  475. value_list_head->prev = block_prev->value_stack.value_list_end;
  476. block_prev->value_stack.value_list_end = value_list_end;
  477. }
  478. }
  479. /* Pop block and destroy the block */
  480. block = jit_block_stack_pop(&cc->block_stack);
  481. jit_block_destroy(block);
  482. return true;
  483. }
  484. else {
  485. /* Commit register values to locals and stacks */
  486. gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
  487. /* Clear frame values */
  488. clear_values(jit_frame);
  489. /* Create the end basic block */
  490. CREATE_BASIC_BLOCK(block->basic_block_end);
  491. SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
  492. SET_BB_BEGIN_BCIP(block->basic_block_end, *p_frame_ip);
  493. /* No need to create 'JMP' insn if block is in stack polymorphic
  494. state, as previous br/br_table opcode has created 'JMP' insn
  495. to this end basic block */
  496. if (!is_block_polymorphic) {
  497. /* Jump to the end basic block */
  498. BUILD_BR(block->basic_block_end);
  499. }
  500. /* Patch the INSNs which jump to this basic block */
  501. incoming_insn = block->incoming_insns_for_end_bb;
  502. while (incoming_insn) {
  503. insn = incoming_insn->insn;
  504. bh_assert(
  505. insn->opcode == JIT_OP_JMP
  506. || (insn->opcode >= JIT_OP_BEQ && insn->opcode <= JIT_OP_BLEU)
  507. || insn->opcode == JIT_OP_LOOKUPSWITCH);
  508. if (insn->opcode == JIT_OP_JMP
  509. || (insn->opcode >= JIT_OP_BEQ
  510. && insn->opcode <= JIT_OP_BLEU)) {
  511. *(jit_insn_opnd(insn, incoming_insn->opnd_idx)) =
  512. jit_basic_block_label(block->basic_block_end);
  513. }
  514. else {
  515. /* Patch LOOKUPSWITCH INSN */
  516. JitOpndLookupSwitch *opnd = jit_insn_opndls(insn);
  517. if (incoming_insn->opnd_idx < opnd->match_pairs_num) {
  518. opnd->match_pairs[incoming_insn->opnd_idx].target =
  519. jit_basic_block_label(block->basic_block_end);
  520. }
  521. else {
  522. opnd->default_target =
  523. jit_basic_block_label(block->basic_block_end);
  524. }
  525. }
  526. incoming_insn = incoming_insn->next;
  527. }
  528. SET_BUILDER_POS(block->basic_block_end);
  529. /* Pop block and load block results */
  530. block = jit_block_stack_pop(&cc->block_stack);
  531. if (block->label_type == LABEL_TYPE_FUNCTION) {
  532. if (!handle_func_return(cc, block)) {
  533. jit_block_destroy(block);
  534. goto fail;
  535. }
  536. SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
  537. clear_values(jit_frame);
  538. }
  539. else {
  540. if (!load_block_results(cc, block)) {
  541. jit_block_destroy(block);
  542. goto fail;
  543. }
  544. }
  545. jit_block_destroy(block);
  546. return true;
  547. }
  548. return true;
  549. fail:
  550. return false;
  551. }
  552. /**
  553. * is_block_polymorphic: whether current block's stack is in polymorphic state,
  554. * if the opcode is one of unreachable/br/br_table/return, stack is marked
  555. * to polymorphic state until the block's 'end' opcode is processed
  556. */
  557. static bool
  558. handle_op_else(JitCompContext *cc, uint8 **p_frame_ip,
  559. bool is_block_polymorphic)
  560. {
  561. JitBlock *block = jit_block_stack_top(&cc->block_stack);
  562. JitFrame *jit_frame = cc->jit_frame;
  563. JitInsn *insn;
  564. /* Check block */
  565. if (!block) {
  566. jit_set_last_error(cc, "WASM block stack underflow");
  567. return false;
  568. }
  569. if (block->label_type != LABEL_TYPE_IF) {
  570. jit_set_last_error(cc, "Invalid WASM block type");
  571. return false;
  572. }
  573. if (!block->incoming_insn_for_else_bb) {
  574. /* The if branch is handled like OP_BLOCK (cond is const and != 0),
  575. just skip the else branch and handle OP_END */
  576. *p_frame_ip = block->wasm_code_end + 1;
  577. return handle_op_end(cc, p_frame_ip, false);
  578. }
  579. else {
  580. /* Has else branch and need to translate else branch */
  581. /* Commit register values to locals and stacks */
  582. gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
  583. /* Clear frame values */
  584. clear_values(jit_frame);
  585. /* No need to create 'JMP' insn if block is in stack polymorphic
  586. state, as previous br/br_table opcode has created 'JMP' insn
  587. to this end basic block */
  588. if (!is_block_polymorphic) {
  589. /* Jump to end basic block */
  590. if (!(insn = GEN_INSN(JMP, 0))) {
  591. jit_set_last_error(cc, "generate jmp insn failed");
  592. return false;
  593. }
  594. if (!jit_block_add_incoming_insn(block, insn, 0)) {
  595. jit_set_last_error(cc, "add incoming insn failed");
  596. return false;
  597. }
  598. }
  599. /* Clear value stack, restore param values and
  600. start to translate the else branch. */
  601. jit_value_stack_destroy(&block->value_stack);
  602. /* create else basic block */
  603. CREATE_BASIC_BLOCK(block->basic_block_else);
  604. SET_BB_END_BCIP(block->basic_block_entry, *p_frame_ip - 1);
  605. SET_BB_BEGIN_BCIP(block->basic_block_else, *p_frame_ip);
  606. /* Patch the insn which conditionly jumps to the else basic block */
  607. insn = block->incoming_insn_for_else_bb;
  608. *(jit_insn_opnd(insn, 2)) =
  609. jit_basic_block_label(block->basic_block_else);
  610. SET_BUILDER_POS(block->basic_block_else);
  611. /* Reload block parameters */
  612. if (!load_block_params(cc, block)) {
  613. return false;
  614. }
  615. return true;
  616. }
  617. return true;
  618. fail:
  619. return false;
  620. }
  621. static bool
  622. handle_next_reachable_block(JitCompContext *cc, uint8 **p_frame_ip)
  623. {
  624. JitBlock *block = jit_block_stack_top(&cc->block_stack);
  625. bh_assert(block);
  626. do {
  627. if (block->label_type == LABEL_TYPE_IF
  628. && block->incoming_insn_for_else_bb
  629. && *p_frame_ip <= block->wasm_code_else) {
  630. /* Else branch hasn't been translated,
  631. start to translate the else branch */
  632. *p_frame_ip = block->wasm_code_else + 1;
  633. /* Restore jit frame's sp to block's sp begin */
  634. cc->jit_frame->sp = block->frame_sp_begin;
  635. return handle_op_else(cc, p_frame_ip, true);
  636. }
  637. else if (block->incoming_insns_for_end_bb) {
  638. *p_frame_ip = block->wasm_code_end + 1;
  639. /* Restore jit frame's sp to block's sp end */
  640. cc->jit_frame->sp =
  641. block->frame_sp_begin
  642. + wasm_get_cell_num(block->result_types, block->result_count);
  643. return handle_op_end(cc, p_frame_ip, true);
  644. }
  645. else {
  646. *p_frame_ip = block->wasm_code_end + 1;
  647. jit_block_stack_pop(&cc->block_stack);
  648. jit_block_destroy(block);
  649. block = jit_block_stack_top(&cc->block_stack);
  650. }
  651. } while (block != NULL);
  652. return true;
  653. }
  654. bool
  655. jit_compile_op_block(JitCompContext *cc, uint8 **p_frame_ip,
  656. uint8 *frame_ip_end, uint32 label_type, uint32 param_count,
  657. uint8 *param_types, uint32 result_count,
  658. uint8 *result_types, bool merge_cmp_and_if)
  659. {
  660. BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
  661. JitBlock *block;
  662. JitReg value;
  663. uint8 *else_addr, *end_addr;
  664. /* Check block stack */
  665. if (!jit_block_stack_top(&cc->block_stack)) {
  666. jit_set_last_error(cc, "WASM block stack underflow");
  667. return false;
  668. }
  669. memset(block_addr_cache, 0, sizeof(block_addr_cache));
  670. /* Get block info */
  671. if (!(wasm_loader_find_block_addr(
  672. NULL, (BlockAddr *)block_addr_cache, *p_frame_ip, frame_ip_end,
  673. (uint8)label_type, &else_addr, &end_addr))) {
  674. jit_set_last_error(cc, "find block end addr failed");
  675. return false;
  676. }
  677. /* Allocate memory */
  678. if (!(block = jit_calloc(sizeof(JitBlock)))) {
  679. jit_set_last_error(cc, "allocate memory failed");
  680. return false;
  681. }
  682. if (param_count && !(block->param_types = jit_calloc(param_count))) {
  683. jit_set_last_error(cc, "allocate memory failed");
  684. goto fail;
  685. }
  686. if (result_count && !(block->result_types = jit_calloc(result_count))) {
  687. jit_set_last_error(cc, "allocate memory failed");
  688. goto fail;
  689. }
  690. /* Initialize block data */
  691. block->label_type = label_type;
  692. block->param_count = param_count;
  693. if (param_count) {
  694. bh_memcpy_s(block->param_types, param_count, param_types, param_count);
  695. }
  696. block->result_count = result_count;
  697. if (result_count) {
  698. bh_memcpy_s(block->result_types, result_count, result_types,
  699. result_count);
  700. }
  701. block->wasm_code_else = else_addr;
  702. block->wasm_code_end = end_addr;
  703. if (label_type == LABEL_TYPE_BLOCK) {
  704. /* Push the new jit block to block stack and continue to
  705. translate current basic block */
  706. if (!push_jit_block_to_stack_and_pass_params(
  707. cc, block, cc->cur_basic_block, 0, false))
  708. goto fail;
  709. }
  710. else if (label_type == LABEL_TYPE_LOOP) {
  711. CREATE_BASIC_BLOCK(block->basic_block_entry);
  712. SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
  713. SET_BB_BEGIN_BCIP(block->basic_block_entry, *p_frame_ip);
  714. /* Push the new jit block to block stack and continue to
  715. translate the new basic block */
  716. if (!push_jit_block_to_stack_and_pass_params(
  717. cc, block, block->basic_block_entry, 0, false))
  718. goto fail;
  719. }
  720. else if (label_type == LABEL_TYPE_IF) {
  721. POP_I32(value);
  722. if (!jit_reg_is_const(value)) {
  723. /* Compare value is not constant, create condition br IR */
  724. /* Create entry block */
  725. CREATE_BASIC_BLOCK(block->basic_block_entry);
  726. SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
  727. SET_BB_BEGIN_BCIP(block->basic_block_entry, *p_frame_ip);
  728. if (!push_jit_block_to_stack_and_pass_params(
  729. cc, block, block->basic_block_entry, value,
  730. merge_cmp_and_if))
  731. goto fail;
  732. }
  733. else {
  734. if (jit_cc_get_const_I32(cc, value) != 0) {
  735. /* Compare value is not 0, condition is true, else branch of
  736. BASIC_BLOCK if cannot be reached, we treat it same as
  737. LABEL_TYPE_BLOCK and start to translate if branch */
  738. if (!push_jit_block_to_stack_and_pass_params(
  739. cc, block, cc->cur_basic_block, 0, false))
  740. goto fail;
  741. }
  742. else {
  743. if (else_addr) {
  744. /* Compare value is not 0, condition is false, if branch of
  745. BASIC_BLOCK if cannot be reached, we treat it same as
  746. LABEL_TYPE_BLOCK and start to translate else branch */
  747. if (!push_jit_block_to_stack_and_pass_params(
  748. cc, block, cc->cur_basic_block, 0, false))
  749. goto fail;
  750. *p_frame_ip = else_addr + 1;
  751. }
  752. else {
  753. /* The whole if block cannot be reached, skip it */
  754. jit_block_destroy(block);
  755. *p_frame_ip = end_addr + 1;
  756. }
  757. }
  758. }
  759. }
  760. else {
  761. jit_set_last_error(cc, "Invalid block type");
  762. goto fail;
  763. }
  764. return true;
  765. fail:
  766. /* Only destroy the block if it hasn't been pushed into
  767. the block stack, or if will be destroyed again when
  768. destroying the block stack */
  769. if (jit_block_stack_top(&cc->block_stack) != block)
  770. jit_block_destroy(block);
  771. return false;
  772. }
  773. bool
  774. jit_compile_op_else(JitCompContext *cc, uint8 **p_frame_ip)
  775. {
  776. return handle_op_else(cc, p_frame_ip, false);
  777. }
  778. bool
  779. jit_compile_op_end(JitCompContext *cc, uint8 **p_frame_ip)
  780. {
  781. return handle_op_end(cc, p_frame_ip, false);
  782. }
  783. /* Check whether need to copy arities when jumping from current block
  784. to the dest block */
  785. static bool
  786. check_copy_arities(const JitBlock *block_dst, JitFrame *jit_frame)
  787. {
  788. JitValueSlot *frame_sp_src = NULL;
  789. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  790. frame_sp_src =
  791. jit_frame->sp
  792. - wasm_get_cell_num(block_dst->param_types, block_dst->param_count);
  793. /* There are parameters to copy and the src/dst addr are different */
  794. return (block_dst->param_count > 0
  795. && block_dst->frame_sp_begin != frame_sp_src)
  796. ? true
  797. : false;
  798. }
  799. else {
  800. frame_sp_src = jit_frame->sp
  801. - wasm_get_cell_num(block_dst->result_types,
  802. block_dst->result_count);
  803. /* There are results to copy and the src/dst addr are different */
  804. return (block_dst->result_count > 0
  805. && block_dst->frame_sp_begin != frame_sp_src)
  806. ? true
  807. : false;
  808. }
  809. }
  810. #if WASM_ENABLE_THREAD_MGR != 0
  811. bool
  812. jit_check_suspend_flags(JitCompContext *cc)
  813. {
  814. JitReg exec_env, suspend_flags, terminate_flag, offset;
  815. JitBasicBlock *terminate_block, *cur_basic_block;
  816. JitFrame *jit_frame = cc->jit_frame;
  817. cur_basic_block = cc->cur_basic_block;
  818. terminate_block = jit_cc_new_basic_block(cc, 0);
  819. if (!terminate_block) {
  820. return false;
  821. }
  822. gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
  823. exec_env = cc->exec_env_reg;
  824. suspend_flags = jit_cc_new_reg_I32(cc);
  825. terminate_flag = jit_cc_new_reg_I32(cc);
  826. offset = jit_cc_new_const_I32(cc, offsetof(WASMExecEnv, suspend_flags));
  827. GEN_INSN(LDI32, suspend_flags, exec_env, offset);
  828. GEN_INSN(AND, terminate_flag, suspend_flags, NEW_CONST(I32, 1));
  829. GEN_INSN(CMP, cc->cmp_reg, terminate_flag, NEW_CONST(I32, 0));
  830. GEN_INSN(BNE, cc->cmp_reg, jit_basic_block_label(terminate_block), 0);
  831. cc->cur_basic_block = terminate_block;
  832. GEN_INSN(RETURN, NEW_CONST(I32, 0));
  833. cc->cur_basic_block = cur_basic_block;
  834. return true;
  835. }
  836. #endif
  837. static bool
  838. handle_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
  839. {
  840. JitFrame *jit_frame;
  841. JitBlock *block_dst, *block;
  842. JitReg frame_sp_dst;
  843. JitInsn *insn;
  844. bool copy_arities;
  845. uint32 offset;
  846. /* Check block stack */
  847. if (!(block = jit_block_stack_top(&cc->block_stack))) {
  848. jit_set_last_error(cc, "WASM block stack underflow");
  849. return false;
  850. }
  851. if (!(block_dst = get_target_block(cc, br_depth))) {
  852. return false;
  853. }
  854. jit_frame = cc->jit_frame;
  855. /* Only opy parameters or results when their count > 0 and
  856. the src/dst addr are different */
  857. copy_arities = check_copy_arities(block_dst, jit_frame);
  858. if (copy_arities) {
  859. frame_sp_dst = jit_cc_new_reg_ptr(cc);
  860. offset = offsetof(WASMInterpFrame, lp)
  861. + (block_dst->frame_sp_begin - jit_frame->lp) * 4;
  862. GEN_INSN(ADD, frame_sp_dst, cc->fp_reg, NEW_CONST(PTR, offset));
  863. /* No need to commit results as they will be copied to dest block */
  864. gen_commit_values(jit_frame, jit_frame->lp, block->frame_sp_begin);
  865. }
  866. else {
  867. /* Commit all including results as they won't be copied */
  868. gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
  869. }
  870. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  871. if (copy_arities) {
  872. /* Dest block is Loop block, copy loop parameters */
  873. copy_block_arities(cc, frame_sp_dst, block_dst->param_types,
  874. block_dst->param_count, NULL);
  875. }
  876. clear_values(jit_frame);
  877. /* Jump to the begin basic block */
  878. BUILD_BR(block_dst->basic_block_entry);
  879. SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
  880. }
  881. else {
  882. if (copy_arities) {
  883. /* Dest block is Block/If/Function block, copy block results */
  884. copy_block_arities(cc, frame_sp_dst, block_dst->result_types,
  885. block_dst->result_count, NULL);
  886. }
  887. clear_values(jit_frame);
  888. /* Jump to the end basic block */
  889. if (!(insn = GEN_INSN(JMP, 0))) {
  890. jit_set_last_error(cc, "generate jmp insn failed");
  891. goto fail;
  892. }
  893. if (!jit_block_add_incoming_insn(block_dst, insn, 0)) {
  894. jit_set_last_error(cc, "add incoming insn failed");
  895. goto fail;
  896. }
  897. SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
  898. }
  899. return true;
  900. fail:
  901. return false;
  902. }
  903. bool
  904. jit_compile_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
  905. {
  906. #if WASM_ENABLE_THREAD_MGR != 0
  907. /* Insert suspend check point */
  908. if (!jit_check_suspend_flags(cc))
  909. return false;
  910. #endif
  911. return handle_op_br(cc, br_depth, p_frame_ip)
  912. && handle_next_reachable_block(cc, p_frame_ip);
  913. }
  914. static JitFrame *
  915. jit_frame_clone(const JitFrame *jit_frame)
  916. {
  917. JitFrame *jit_frame_cloned;
  918. uint32 max_locals = jit_frame->max_locals;
  919. uint32 max_stacks = jit_frame->max_stacks;
  920. uint32 total_size;
  921. total_size = (uint32)(offsetof(JitFrame, lp)
  922. + sizeof(*jit_frame->lp) * (max_locals + max_stacks));
  923. jit_frame_cloned = jit_calloc(total_size);
  924. if (jit_frame_cloned) {
  925. bh_memcpy_s(jit_frame_cloned, total_size, jit_frame, total_size);
  926. jit_frame_cloned->sp =
  927. jit_frame_cloned->lp + (jit_frame->sp - jit_frame->lp);
  928. }
  929. return jit_frame_cloned;
  930. }
  931. static void
  932. jit_frame_copy(JitFrame *jit_frame_dst, const JitFrame *jit_frame_src)
  933. {
  934. uint32 max_locals = jit_frame_src->max_locals;
  935. uint32 max_stacks = jit_frame_src->max_stacks;
  936. uint32 total_size;
  937. total_size =
  938. (uint32)(offsetof(JitFrame, lp)
  939. + sizeof(*jit_frame_src->lp) * (max_locals + max_stacks));
  940. bh_memcpy_s(jit_frame_dst, total_size, jit_frame_src, total_size);
  941. jit_frame_dst->sp =
  942. jit_frame_dst->lp + (jit_frame_src->sp - jit_frame_src->lp);
  943. }
  944. bool
  945. jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth,
  946. bool merge_cmp_and_br_if, uint8 **p_frame_ip)
  947. {
  948. JitFrame *jit_frame, *jit_frame_cloned;
  949. JitBlock *block_dst;
  950. JitReg cond;
  951. JitBasicBlock *cur_basic_block, *if_basic_block = NULL;
  952. JitInsn *insn, *insn_select = NULL, *insn_cmp = NULL;
  953. bool copy_arities;
  954. if (!(block_dst = get_target_block(cc, br_depth))) {
  955. return false;
  956. }
  957. /* append IF to current basic block */
  958. POP_I32(cond);
  959. if (merge_cmp_and_br_if) {
  960. get_last_cmp_and_selectcc(cc, cond, &insn_cmp, &insn_select);
  961. }
  962. jit_frame = cc->jit_frame;
  963. cur_basic_block = cc->cur_basic_block;
  964. gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
  965. if (!(insn_select && insn_cmp)) {
  966. if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0))) {
  967. jit_set_last_error(cc, "generate cmp insn failed");
  968. goto fail;
  969. }
  970. }
  971. /* Only opy parameters or results when their count > 0 and
  972. the src/dst addr are different */
  973. copy_arities = check_copy_arities(block_dst, jit_frame);
  974. if (!copy_arities) {
  975. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  976. if (!(insn = GEN_INSN(
  977. BNE, cc->cmp_reg,
  978. jit_basic_block_label(block_dst->basic_block_entry),
  979. 0))) {
  980. jit_set_last_error(cc, "generate bne insn failed");
  981. goto fail;
  982. }
  983. }
  984. else {
  985. if (!(insn = GEN_INSN(BNE, cc->cmp_reg, 0, 0))) {
  986. jit_set_last_error(cc, "generate bne insn failed");
  987. goto fail;
  988. }
  989. if (!jit_block_add_incoming_insn(block_dst, insn, 1)) {
  990. jit_set_last_error(cc, "add incoming insn failed");
  991. goto fail;
  992. }
  993. }
  994. if (insn_select && insn_cmp) {
  995. /* Change `CMP + SELECTcc` into `CMP + Bcc` */
  996. insn->opcode = JIT_OP_BEQ + (insn_select->opcode - JIT_OP_SELECTEQ);
  997. jit_insn_unlink(insn_select);
  998. jit_insn_delete(insn_select);
  999. }
  1000. return true;
  1001. }
  1002. CREATE_BASIC_BLOCK(if_basic_block);
  1003. if (!(insn = GEN_INSN(BNE, cc->cmp_reg,
  1004. jit_basic_block_label(if_basic_block), 0))) {
  1005. jit_set_last_error(cc, "generate bne insn failed");
  1006. goto fail;
  1007. }
  1008. if (insn_select && insn_cmp) {
  1009. /* Change `CMP + SELECTcc` into `CMP + Bcc` */
  1010. insn->opcode = JIT_OP_BEQ + (insn_select->opcode - JIT_OP_SELECTEQ);
  1011. jit_insn_unlink(insn_select);
  1012. jit_insn_delete(insn_select);
  1013. }
  1014. #if WASM_ENABLE_THREAD_MGR != 0
  1015. /* Insert suspend check point */
  1016. if (!jit_check_suspend_flags(cc))
  1017. return false;
  1018. #endif
  1019. SET_BUILDER_POS(if_basic_block);
  1020. SET_BB_BEGIN_BCIP(if_basic_block, *p_frame_ip - 1);
  1021. /* Clone current jit frame to a new jit fame */
  1022. if (!(jit_frame_cloned = jit_frame_clone(jit_frame))) {
  1023. jit_set_last_error(cc, "allocate memory failed");
  1024. goto fail;
  1025. }
  1026. /* Clear current jit frame so that the registers
  1027. in the new basic block will be loaded again */
  1028. clear_values(jit_frame);
  1029. if (!handle_op_br(cc, br_depth, p_frame_ip)) {
  1030. jit_free(jit_frame_cloned);
  1031. goto fail;
  1032. }
  1033. /* Restore the jit frame so that the registers can
  1034. be used again in current basic block */
  1035. jit_frame_copy(jit_frame, jit_frame_cloned);
  1036. jit_free(jit_frame_cloned);
  1037. /* Continue processing opcodes after BR_IF */
  1038. SET_BUILDER_POS(cur_basic_block);
  1039. return true;
  1040. fail:
  1041. return false;
  1042. }
  1043. bool
  1044. jit_compile_op_br_table(JitCompContext *cc, uint32 *br_depths, uint32 br_count,
  1045. uint8 **p_frame_ip)
  1046. {
  1047. JitBasicBlock *cur_basic_block;
  1048. JitReg value;
  1049. JitInsn *insn;
  1050. uint32 i = 0;
  1051. JitOpndLookupSwitch *opnd = NULL;
  1052. #if WASM_ENABLE_THREAD_MGR != 0
  1053. /* Insert suspend check point */
  1054. if (!jit_check_suspend_flags(cc))
  1055. return false;
  1056. #endif
  1057. cur_basic_block = cc->cur_basic_block;
  1058. POP_I32(value);
  1059. /* append LOOKUPSWITCH to current basic block */
  1060. gen_commit_values(cc->jit_frame, cc->jit_frame->lp, cc->jit_frame->sp);
  1061. /* Clear frame values */
  1062. clear_values(cc->jit_frame);
  1063. SET_BB_END_BCIP(cur_basic_block, *p_frame_ip - 1);
  1064. /* prepare basic blocks for br */
  1065. insn = GEN_INSN(LOOKUPSWITCH, value, br_count);
  1066. if (NULL == insn) {
  1067. jit_set_last_error(cc, "generate insn LOOKUPSWITCH failed");
  1068. goto fail;
  1069. }
  1070. for (i = 0, opnd = jit_insn_opndls(insn); i < br_count + 1; i++) {
  1071. JitBasicBlock *basic_block = NULL;
  1072. JitBlock *block_dst;
  1073. bool copy_arities;
  1074. if (!(block_dst = get_target_block(cc, br_depths[i]))) {
  1075. goto fail;
  1076. }
  1077. /* Only opy parameters or results when their count > 0 and
  1078. the src/dst addr are different */
  1079. copy_arities = check_copy_arities(block_dst, cc->jit_frame);
  1080. if (!copy_arities) {
  1081. /* No need to create new basic block, direclty jump to
  1082. the existing basic block when no need to copy arities */
  1083. if (i == br_count) {
  1084. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  1085. opnd->default_target =
  1086. jit_basic_block_label(block_dst->basic_block_entry);
  1087. }
  1088. else {
  1089. bh_assert(!block_dst->basic_block_end);
  1090. if (!jit_block_add_incoming_insn(block_dst, insn, i)) {
  1091. jit_set_last_error(cc, "add incoming insn failed");
  1092. goto fail;
  1093. }
  1094. }
  1095. }
  1096. else {
  1097. opnd->match_pairs[i].value = i;
  1098. if (block_dst->label_type == LABEL_TYPE_LOOP) {
  1099. opnd->match_pairs[i].target =
  1100. jit_basic_block_label(block_dst->basic_block_entry);
  1101. }
  1102. else {
  1103. bh_assert(!block_dst->basic_block_end);
  1104. if (!jit_block_add_incoming_insn(block_dst, insn, i)) {
  1105. jit_set_last_error(cc, "add incoming insn failed");
  1106. goto fail;
  1107. }
  1108. }
  1109. }
  1110. continue;
  1111. }
  1112. /* Create new basic block when need to copy arities */
  1113. CREATE_BASIC_BLOCK(basic_block);
  1114. SET_BB_BEGIN_BCIP(basic_block, *p_frame_ip - 1);
  1115. if (i == br_count) {
  1116. opnd->default_target = jit_basic_block_label(basic_block);
  1117. }
  1118. else {
  1119. opnd->match_pairs[i].value = i;
  1120. opnd->match_pairs[i].target = jit_basic_block_label(basic_block);
  1121. }
  1122. SET_BUILDER_POS(basic_block);
  1123. if (!handle_op_br(cc, br_depths[i], p_frame_ip))
  1124. goto fail;
  1125. }
  1126. /* Search next available block to handle */
  1127. return handle_next_reachable_block(cc, p_frame_ip);
  1128. fail:
  1129. return false;
  1130. }
  1131. bool
  1132. jit_compile_op_return(JitCompContext *cc, uint8 **p_frame_ip)
  1133. {
  1134. JitBlock *block_func = cc->block_stack.block_list_head;
  1135. bh_assert(block_func);
  1136. if (!handle_func_return(cc, block_func)) {
  1137. return false;
  1138. }
  1139. SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
  1140. clear_values(cc->jit_frame);
  1141. return handle_next_reachable_block(cc, p_frame_ip);
  1142. }
  1143. bool
  1144. jit_compile_op_unreachable(JitCompContext *cc, uint8 **p_frame_ip)
  1145. {
  1146. if (!jit_emit_exception(cc, EXCE_UNREACHABLE, JIT_OP_JMP, 0, NULL))
  1147. return false;
  1148. return handle_next_reachable_block(cc, p_frame_ip);
  1149. }
  1150. bool
  1151. jit_handle_next_reachable_block(JitCompContext *cc, uint8 **p_frame_ip)
  1152. {
  1153. return handle_next_reachable_block(cc, p_frame_ip);
  1154. }