jit_emit_function.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  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_function.h"
  6. #include "jit_emit_exception.h"
  7. #include "jit_emit_control.h"
  8. #include "../jit_frontend.h"
  9. #include "../jit_codegen.h"
  10. #include "../../interpreter/wasm_runtime.h"
  11. static bool
  12. emit_callnative(JitCompContext *cc, JitReg native_func_reg, JitReg res,
  13. JitReg *params, uint32 param_count);
  14. /* Prepare parameters for the function to call */
  15. static bool
  16. pre_call(JitCompContext *cc, const WASMType *func_type)
  17. {
  18. JitReg value;
  19. uint32 i, outs_off;
  20. /* Prepare parameters for the function to call */
  21. outs_off =
  22. cc->total_frame_size + offsetof(WASMInterpFrame, lp)
  23. + wasm_get_cell_num(func_type->types, func_type->param_count) * 4;
  24. for (i = 0; i < func_type->param_count; i++) {
  25. switch (func_type->types[func_type->param_count - 1 - i]) {
  26. case VALUE_TYPE_I32:
  27. #if WASM_ENABLE_REF_TYPES != 0
  28. case VALUE_TYPE_EXTERNREF:
  29. case VALUE_TYPE_FUNCREF:
  30. #endif
  31. POP_I32(value);
  32. outs_off -= 4;
  33. GEN_INSN(STI32, value, cc->fp_reg, NEW_CONST(I32, outs_off));
  34. break;
  35. case VALUE_TYPE_I64:
  36. POP_I64(value);
  37. outs_off -= 8;
  38. GEN_INSN(STI64, value, cc->fp_reg, NEW_CONST(I32, outs_off));
  39. break;
  40. case VALUE_TYPE_F32:
  41. POP_F32(value);
  42. outs_off -= 4;
  43. GEN_INSN(STF32, value, cc->fp_reg, NEW_CONST(I32, outs_off));
  44. break;
  45. case VALUE_TYPE_F64:
  46. POP_F64(value);
  47. outs_off -= 8;
  48. GEN_INSN(STF64, value, cc->fp_reg, NEW_CONST(I32, outs_off));
  49. break;
  50. default:
  51. bh_assert(0);
  52. goto fail;
  53. }
  54. }
  55. /* Commit sp as the callee may use it to store the results */
  56. gen_commit_sp_ip(cc->jit_frame);
  57. return true;
  58. fail:
  59. return false;
  60. }
  61. /* Push results */
  62. static bool
  63. post_return(JitCompContext *cc, const WASMType *func_type, JitReg first_res,
  64. bool update_committed_sp)
  65. {
  66. uint32 i, n;
  67. JitReg value;
  68. n = cc->jit_frame->sp - cc->jit_frame->lp;
  69. for (i = 0; i < func_type->result_count; i++) {
  70. switch (func_type->types[func_type->param_count + i]) {
  71. case VALUE_TYPE_I32:
  72. #if WASM_ENABLE_REF_TYPES != 0
  73. case VALUE_TYPE_EXTERNREF:
  74. case VALUE_TYPE_FUNCREF:
  75. #endif
  76. if (i == 0 && first_res) {
  77. bh_assert(jit_reg_kind(first_res) == JIT_REG_KIND_I32);
  78. value = first_res;
  79. }
  80. else {
  81. value = jit_cc_new_reg_I32(cc);
  82. GEN_INSN(LDI32, value, cc->fp_reg,
  83. NEW_CONST(I32, offset_of_local(n)));
  84. }
  85. PUSH_I32(value);
  86. n++;
  87. break;
  88. case VALUE_TYPE_I64:
  89. if (i == 0 && first_res) {
  90. bh_assert(jit_reg_kind(first_res) == JIT_REG_KIND_I64);
  91. value = first_res;
  92. }
  93. else {
  94. value = jit_cc_new_reg_I64(cc);
  95. GEN_INSN(LDI64, value, cc->fp_reg,
  96. NEW_CONST(I32, offset_of_local(n)));
  97. }
  98. PUSH_I64(value);
  99. n += 2;
  100. break;
  101. case VALUE_TYPE_F32:
  102. if (i == 0 && first_res) {
  103. bh_assert(jit_reg_kind(first_res) == JIT_REG_KIND_F32);
  104. value = first_res;
  105. }
  106. else {
  107. value = jit_cc_new_reg_F32(cc);
  108. GEN_INSN(LDF32, value, cc->fp_reg,
  109. NEW_CONST(I32, offset_of_local(n)));
  110. }
  111. PUSH_F32(value);
  112. n++;
  113. break;
  114. case VALUE_TYPE_F64:
  115. if (i == 0 && first_res) {
  116. bh_assert(jit_reg_kind(first_res) == JIT_REG_KIND_F64);
  117. value = first_res;
  118. }
  119. else {
  120. value = jit_cc_new_reg_F64(cc);
  121. GEN_INSN(LDF64, value, cc->fp_reg,
  122. NEW_CONST(I32, offset_of_local(n)));
  123. }
  124. PUSH_F64(value);
  125. n += 2;
  126. break;
  127. default:
  128. bh_assert(0);
  129. goto fail;
  130. }
  131. }
  132. if (update_committed_sp)
  133. /* Update the committed_sp as the callee has updated the frame sp */
  134. cc->jit_frame->committed_sp = cc->jit_frame->sp;
  135. return true;
  136. fail:
  137. return false;
  138. }
  139. static bool
  140. pre_load(JitCompContext *cc, JitReg *argvs, const WASMType *func_type)
  141. {
  142. JitReg value;
  143. uint32 i;
  144. /* Prepare parameters for the function to call */
  145. for (i = 0; i < func_type->param_count; i++) {
  146. switch (func_type->types[func_type->param_count - 1 - i]) {
  147. case VALUE_TYPE_I32:
  148. #if WASM_ENABLE_REF_TYPES != 0
  149. case VALUE_TYPE_EXTERNREF:
  150. case VALUE_TYPE_FUNCREF:
  151. #endif
  152. POP_I32(value);
  153. argvs[func_type->param_count - 1 - i] = value;
  154. break;
  155. case VALUE_TYPE_I64:
  156. POP_I64(value);
  157. argvs[func_type->param_count - 1 - i] = value;
  158. break;
  159. case VALUE_TYPE_F32:
  160. POP_F32(value);
  161. argvs[func_type->param_count - 1 - i] = value;
  162. break;
  163. case VALUE_TYPE_F64:
  164. POP_F64(value);
  165. argvs[func_type->param_count - 1 - i] = value;
  166. break;
  167. default:
  168. bh_assert(0);
  169. goto fail;
  170. }
  171. }
  172. gen_commit_sp_ip(cc->jit_frame);
  173. return true;
  174. fail:
  175. return false;
  176. }
  177. static JitReg
  178. create_first_res_reg(JitCompContext *cc, const WASMType *func_type)
  179. {
  180. if (func_type->result_count) {
  181. switch (func_type->types[func_type->param_count]) {
  182. case VALUE_TYPE_I32:
  183. #if WASM_ENABLE_REF_TYPES != 0
  184. case VALUE_TYPE_EXTERNREF:
  185. case VALUE_TYPE_FUNCREF:
  186. #endif
  187. return jit_cc_new_reg_I32(cc);
  188. case VALUE_TYPE_I64:
  189. return jit_cc_new_reg_I64(cc);
  190. case VALUE_TYPE_F32:
  191. return jit_cc_new_reg_F32(cc);
  192. case VALUE_TYPE_F64:
  193. return jit_cc_new_reg_F64(cc);
  194. default:
  195. bh_assert(0);
  196. return 0;
  197. }
  198. }
  199. return 0;
  200. }
  201. bool
  202. jit_compile_op_call(JitCompContext *cc, uint32 func_idx, bool tail_call)
  203. {
  204. WASMModule *wasm_module = cc->cur_wasm_module;
  205. WASMFunctionImport *func_import;
  206. WASMFunction *func;
  207. WASMType *func_type;
  208. JitFrame *jit_frame = cc->jit_frame;
  209. JitReg fast_jit_func_ptrs, jitted_code = 0;
  210. JitReg native_func, *argvs = NULL, *argvs1 = NULL, func_params[5];
  211. JitReg native_addr_ptr, module_inst_reg, ret, res;
  212. uint32 jitted_func_idx, i;
  213. uint64 total_size;
  214. const char *signature = NULL;
  215. /* Whether the argument is a pointer/str argument and
  216. need to call jit_check_app_addr_and_convert */
  217. bool is_pointer_arg;
  218. bool return_value = false;
  219. #if WASM_ENABLE_THREAD_MGR != 0
  220. /* Insert suspend check point */
  221. if (!jit_check_suspend_flags(cc))
  222. goto fail;
  223. #endif
  224. if (func_idx < wasm_module->import_function_count) {
  225. /* The function to call is an import function */
  226. func_import = &wasm_module->import_functions[func_idx].u.function;
  227. func_type = func_import->func_type;
  228. /* Call fast_jit_invoke_native in some cases */
  229. if (!func_import->func_ptr_linked /* import func hasn't been linked */
  230. || func_import->call_conv_wasm_c_api /* linked by wasm_c_api */
  231. || func_import->call_conv_raw /* registered as raw mode */
  232. || func_type->param_count >= 5 /* registered as normal mode, but
  233. jit_emit_callnative only supports
  234. maximum 6 registers now
  235. (include exec_nev) */) {
  236. JitReg arg_regs[3];
  237. if (!pre_call(cc, func_type)) {
  238. goto fail;
  239. }
  240. /* Call fast_jit_invoke_native */
  241. ret = jit_cc_new_reg_I32(cc);
  242. arg_regs[0] = cc->exec_env_reg;
  243. arg_regs[1] = NEW_CONST(I32, func_idx);
  244. arg_regs[2] = cc->fp_reg;
  245. if (!jit_emit_callnative(cc, fast_jit_invoke_native, ret, arg_regs,
  246. 3)) {
  247. goto fail;
  248. }
  249. /* Convert the return value from bool to uint32 */
  250. GEN_INSN(AND, ret, ret, NEW_CONST(I32, 0xFF));
  251. /* Check whether there is exception thrown */
  252. GEN_INSN(CMP, cc->cmp_reg, ret, NEW_CONST(I32, 0));
  253. if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BEQ,
  254. cc->cmp_reg, NULL)) {
  255. goto fail;
  256. }
  257. if (!post_return(cc, func_type, 0, true)) {
  258. goto fail;
  259. }
  260. #if WASM_ENABLE_THREAD_MGR != 0
  261. /* Insert suspend check point */
  262. if (!jit_check_suspend_flags(cc))
  263. goto fail;
  264. #endif
  265. return true;
  266. }
  267. /* Import function was registered as normal mode, and its argument count
  268. is no more than 5, we directly call it */
  269. signature = func_import->signature;
  270. bh_assert(signature);
  271. /* Allocate memory for argvs*/
  272. total_size = sizeof(JitReg) * (uint64)(func_type->param_count);
  273. if (total_size > 0) {
  274. if (total_size >= UINT32_MAX
  275. || !(argvs = jit_malloc((uint32)total_size))) {
  276. goto fail;
  277. }
  278. }
  279. /* Pop function params from stack and store them into argvs */
  280. if (!pre_load(cc, argvs, func_type)) {
  281. goto fail;
  282. }
  283. ret = jit_cc_new_reg_I32(cc);
  284. func_params[0] = module_inst_reg = get_module_inst_reg(jit_frame);
  285. func_params[4] = native_addr_ptr = jit_cc_new_reg_ptr(cc);
  286. GEN_INSN(ADD, native_addr_ptr, cc->exec_env_reg,
  287. NEW_CONST(PTR, offsetof(WASMExecEnv, jit_cache)));
  288. /* Traverse each pointer/str argument, call
  289. jit_check_app_addr_and_convert to check whether it is
  290. in the range of linear memory and and convert it from
  291. app offset into native address */
  292. for (i = 0; i < func_type->param_count; i++) {
  293. is_pointer_arg = false;
  294. if (signature[i + 1] == '*') {
  295. /* param is a pointer */
  296. is_pointer_arg = true;
  297. func_params[1] = NEW_CONST(I32, false); /* is_str = false */
  298. func_params[2] = argvs[i];
  299. if (signature[i + 2] == '~') {
  300. /* pointer with length followed */
  301. func_params[3] = argvs[i + 1];
  302. }
  303. else {
  304. /* pointer with length followed */
  305. func_params[3] = NEW_CONST(I32, 1);
  306. }
  307. }
  308. else if (signature[i + 1] == '$') {
  309. /* param is a string */
  310. is_pointer_arg = true;
  311. func_params[1] = NEW_CONST(I32, true); /* is_str = true */
  312. func_params[2] = argvs[i];
  313. func_params[3] = NEW_CONST(I32, 1);
  314. }
  315. if (is_pointer_arg) {
  316. if (!jit_emit_callnative(cc, jit_check_app_addr_and_convert,
  317. ret, func_params, 5)) {
  318. goto fail;
  319. }
  320. /* Convert the return value from bool to uint32 */
  321. GEN_INSN(AND, ret, ret, NEW_CONST(I32, 0xFF));
  322. /* Check whether there is exception thrown */
  323. GEN_INSN(CMP, cc->cmp_reg, ret, NEW_CONST(I32, 0));
  324. if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BEQ,
  325. cc->cmp_reg, NULL)) {
  326. return false;
  327. }
  328. /* Load native addr from pointer of native addr,
  329. or exec_env->jit_cache */
  330. argvs[i] = jit_cc_new_reg_ptr(cc);
  331. GEN_INSN(LDPTR, argvs[i], native_addr_ptr, NEW_CONST(I32, 0));
  332. }
  333. }
  334. res = create_first_res_reg(cc, func_type);
  335. /* Prepare arguments of the native function */
  336. if (!(argvs1 =
  337. jit_calloc(sizeof(JitReg) * (func_type->param_count + 1)))) {
  338. goto fail;
  339. }
  340. argvs1[0] = cc->exec_env_reg;
  341. for (i = 0; i < func_type->param_count; i++) {
  342. argvs1[i + 1] = argvs[i];
  343. }
  344. /* Call the native function */
  345. native_func = NEW_CONST(PTR, (uintptr_t)func_import->func_ptr_linked);
  346. if (!emit_callnative(cc, native_func, res, argvs1,
  347. func_type->param_count + 1)) {
  348. jit_free(argvs1);
  349. goto fail;
  350. }
  351. jit_free(argvs1);
  352. /* Check whether there is exception thrown */
  353. GEN_INSN(LDI8, ret, module_inst_reg,
  354. NEW_CONST(I32, offsetof(WASMModuleInstance, cur_exception)));
  355. GEN_INSN(CMP, cc->cmp_reg, ret, NEW_CONST(I32, 0));
  356. if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BNE,
  357. cc->cmp_reg, NULL)) {
  358. goto fail;
  359. }
  360. if (!post_return(cc, func_type, res, false)) {
  361. goto fail;
  362. }
  363. }
  364. else {
  365. /* The function to call is a bytecode function */
  366. func = wasm_module
  367. ->functions[func_idx - wasm_module->import_function_count];
  368. func_type = func->func_type;
  369. /* jitted_code = func_ptrs[func_idx - import_function_count] */
  370. fast_jit_func_ptrs = get_fast_jit_func_ptrs_reg(jit_frame);
  371. jitted_code = jit_cc_new_reg_ptr(cc);
  372. jitted_func_idx = func_idx - wasm_module->import_function_count;
  373. GEN_INSN(LDPTR, jitted_code, fast_jit_func_ptrs,
  374. NEW_CONST(I32, (uint32)sizeof(void *) * jitted_func_idx));
  375. if (!pre_call(cc, func_type)) {
  376. goto fail;
  377. }
  378. res = create_first_res_reg(cc, func_type);
  379. GEN_INSN(CALLBC, res, 0, jitted_code, NEW_CONST(I32, func_idx));
  380. if (!post_return(cc, func_type, res, true)) {
  381. goto fail;
  382. }
  383. }
  384. #if WASM_ENABLE_THREAD_MGR != 0
  385. /* Insert suspend check point */
  386. if (!jit_check_suspend_flags(cc))
  387. goto fail;
  388. #endif
  389. /* Clear part of memory regs and table regs as their values
  390. may be changed in the function call */
  391. if (cc->cur_wasm_module->possible_memory_grow)
  392. clear_memory_regs(jit_frame);
  393. clear_table_regs(jit_frame);
  394. /* Ignore tail call currently */
  395. (void)tail_call;
  396. return_value = true;
  397. fail:
  398. if (argvs)
  399. jit_free(argvs);
  400. return return_value;
  401. }
  402. static JitReg
  403. pack_argv(JitCompContext *cc)
  404. {
  405. /* reuse the stack of the next frame */
  406. uint32 stack_base;
  407. JitReg argv;
  408. stack_base = cc->total_frame_size + offsetof(WASMInterpFrame, lp);
  409. argv = jit_cc_new_reg_ptr(cc);
  410. GEN_INSN(ADD, argv, cc->fp_reg, NEW_CONST(PTR, stack_base));
  411. if (jit_get_last_error(cc)) {
  412. return (JitReg)0;
  413. }
  414. return argv;
  415. }
  416. bool
  417. jit_compile_op_call_indirect(JitCompContext *cc, uint32 type_idx,
  418. uint32 tbl_idx)
  419. {
  420. WASMModule *wasm_module = cc->cur_wasm_module;
  421. JitBasicBlock *block_import, *block_nonimport, *func_return;
  422. JitReg elem_idx, native_ret, argv, arg_regs[6];
  423. JitFrame *jit_frame = cc->jit_frame;
  424. JitReg tbl_size, offset, offset_i32;
  425. JitReg func_import, func_idx, tbl_elems, func_count;
  426. JitReg func_type_indexes, func_type_idx, fast_jit_func_ptrs;
  427. JitReg offset1_i32, offset1, func_type_idx1, res;
  428. JitReg import_func_ptrs, jitted_code_idx, jitted_code;
  429. WASMType *func_type;
  430. uint32 n;
  431. POP_I32(elem_idx);
  432. /* check elem_idx */
  433. tbl_size = get_table_cur_size_reg(jit_frame, tbl_idx);
  434. GEN_INSN(CMP, cc->cmp_reg, elem_idx, tbl_size);
  435. if (!jit_emit_exception(cc, EXCE_UNDEFINED_ELEMENT, JIT_OP_BGEU,
  436. cc->cmp_reg, NULL))
  437. goto fail;
  438. /* check func_idx */
  439. if (UINTPTR_MAX == UINT64_MAX) {
  440. offset_i32 = jit_cc_new_reg_I32(cc);
  441. offset = jit_cc_new_reg_I64(cc);
  442. GEN_INSN(SHL, offset_i32, elem_idx, NEW_CONST(I32, 2));
  443. GEN_INSN(I32TOI64, offset, offset_i32);
  444. }
  445. else {
  446. offset = jit_cc_new_reg_I32(cc);
  447. GEN_INSN(SHL, offset, elem_idx, NEW_CONST(I32, 2));
  448. }
  449. func_idx = jit_cc_new_reg_I32(cc);
  450. tbl_elems = get_table_elems_reg(jit_frame, tbl_idx);
  451. GEN_INSN(LDI32, func_idx, tbl_elems, offset);
  452. GEN_INSN(CMP, cc->cmp_reg, func_idx, NEW_CONST(I32, -1));
  453. if (!jit_emit_exception(cc, EXCE_UNINITIALIZED_ELEMENT, JIT_OP_BEQ,
  454. cc->cmp_reg, NULL))
  455. goto fail;
  456. func_count = NEW_CONST(I32, wasm_module->import_function_count
  457. + wasm_module->function_count);
  458. GEN_INSN(CMP, cc->cmp_reg, func_idx, func_count);
  459. if (!jit_emit_exception(cc, EXCE_INVALID_FUNCTION_INDEX, JIT_OP_BGTU,
  460. cc->cmp_reg, NULL))
  461. goto fail;
  462. /* check func_type */
  463. /* get func_type_idx from func_type_indexes */
  464. if (UINTPTR_MAX == UINT64_MAX) {
  465. offset1_i32 = jit_cc_new_reg_I32(cc);
  466. offset1 = jit_cc_new_reg_I64(cc);
  467. GEN_INSN(SHL, offset1_i32, func_idx, NEW_CONST(I32, 2));
  468. GEN_INSN(I32TOI64, offset1, offset1_i32);
  469. }
  470. else {
  471. offset1 = jit_cc_new_reg_I32(cc);
  472. GEN_INSN(SHL, offset1, func_idx, NEW_CONST(I32, 2));
  473. }
  474. func_type_indexes = get_func_type_indexes_reg(jit_frame);
  475. func_type_idx = jit_cc_new_reg_I32(cc);
  476. GEN_INSN(LDI32, func_type_idx, func_type_indexes, offset1);
  477. type_idx = wasm_get_smallest_type_idx(wasm_module->types,
  478. wasm_module->type_count, type_idx);
  479. func_type_idx1 = NEW_CONST(I32, type_idx);
  480. GEN_INSN(CMP, cc->cmp_reg, func_type_idx, func_type_idx1);
  481. if (!jit_emit_exception(cc, EXCE_INVALID_FUNCTION_TYPE_INDEX, JIT_OP_BNE,
  482. cc->cmp_reg, NULL))
  483. goto fail;
  484. /* pop function arguments and store it to out area of callee stack frame */
  485. func_type = wasm_module->types[type_idx];
  486. if (!pre_call(cc, func_type)) {
  487. goto fail;
  488. }
  489. /* store elem_idx and func_idx to exec_env->jit_cache */
  490. GEN_INSN(STI32, elem_idx, cc->exec_env_reg,
  491. NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache)));
  492. GEN_INSN(STI32, func_idx, cc->exec_env_reg,
  493. NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache) + 4));
  494. #if WASM_ENABLE_THREAD_MGR != 0
  495. /* Insert suspend check point */
  496. if (!jit_check_suspend_flags(cc))
  497. goto fail;
  498. #endif
  499. block_import = jit_cc_new_basic_block(cc, 0);
  500. block_nonimport = jit_cc_new_basic_block(cc, 0);
  501. func_return = jit_cc_new_basic_block(cc, 0);
  502. if (!block_import || !block_nonimport || !func_return) {
  503. goto fail;
  504. }
  505. /* Commit register values to locals and stacks */
  506. gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
  507. /* Clear frame values */
  508. clear_values(jit_frame);
  509. /* jump to block_import or block_nonimport */
  510. GEN_INSN(CMP, cc->cmp_reg, func_idx,
  511. NEW_CONST(I32, cc->cur_wasm_module->import_function_count));
  512. GEN_INSN(BLTU, cc->cmp_reg, jit_basic_block_label(block_import),
  513. jit_basic_block_label(block_nonimport));
  514. /* block_import */
  515. cc->cur_basic_block = block_import;
  516. elem_idx = jit_cc_new_reg_I32(cc);
  517. GEN_INSN(LDI32, elem_idx, cc->exec_env_reg,
  518. NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache)));
  519. GEN_INSN(LDI32, func_idx, cc->exec_env_reg,
  520. NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache) + 4));
  521. argv = pack_argv(cc);
  522. if (!argv) {
  523. goto fail;
  524. }
  525. native_ret = jit_cc_new_reg_I32(cc);
  526. arg_regs[0] = cc->exec_env_reg;
  527. arg_regs[1] = NEW_CONST(I32, tbl_idx);
  528. arg_regs[2] = elem_idx;
  529. arg_regs[3] = NEW_CONST(I32, type_idx);
  530. arg_regs[4] = NEW_CONST(I32, func_type->param_cell_num);
  531. arg_regs[5] = argv;
  532. import_func_ptrs = get_import_func_ptrs_reg(jit_frame);
  533. func_import = jit_cc_new_reg_ptr(cc);
  534. if (UINTPTR_MAX == UINT64_MAX) {
  535. JitReg func_import_offset = jit_cc_new_reg_I32(cc);
  536. JitReg func_import_offset_i64 = jit_cc_new_reg_I64(cc);
  537. GEN_INSN(SHL, func_import_offset, func_idx, NEW_CONST(I32, 3));
  538. GEN_INSN(I32TOI64, func_import_offset_i64, func_import_offset);
  539. GEN_INSN(LDPTR, func_import, import_func_ptrs, func_import_offset_i64);
  540. }
  541. else {
  542. JitReg func_import_offset = jit_cc_new_reg_I32(cc);
  543. GEN_INSN(SHL, func_import_offset, func_idx, NEW_CONST(I32, 2));
  544. GEN_INSN(LDPTR, func_import, import_func_ptrs, func_import_offset);
  545. }
  546. if (!jit_emit_callnative(cc, fast_jit_call_indirect, native_ret, arg_regs,
  547. 6)) {
  548. goto fail;
  549. }
  550. /* Convert bool to uint32 */
  551. GEN_INSN(AND, native_ret, native_ret, NEW_CONST(I32, 0xFF));
  552. /* Check whether there is exception thrown */
  553. GEN_INSN(CMP, cc->cmp_reg, native_ret, NEW_CONST(I32, 0));
  554. if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BEQ, cc->cmp_reg,
  555. NULL)) {
  556. return false;
  557. }
  558. /* Store res into current frame, so that post_return in
  559. block func_return can get the value */
  560. n = cc->jit_frame->sp - cc->jit_frame->lp;
  561. if (func_type->result_count > 0) {
  562. switch (func_type->types[func_type->param_count]) {
  563. case VALUE_TYPE_I32:
  564. #if WASM_ENABLE_REF_TYPES != 0
  565. case VALUE_TYPE_EXTERNREF:
  566. case VALUE_TYPE_FUNCREF:
  567. #endif
  568. res = jit_cc_new_reg_I32(cc);
  569. GEN_INSN(LDI32, res, argv, NEW_CONST(I32, 0));
  570. GEN_INSN(STI32, res, cc->fp_reg,
  571. NEW_CONST(I32, offset_of_local(n)));
  572. break;
  573. case VALUE_TYPE_I64:
  574. res = jit_cc_new_reg_I64(cc);
  575. GEN_INSN(LDI64, res, argv, NEW_CONST(I32, 0));
  576. GEN_INSN(STI64, res, cc->fp_reg,
  577. NEW_CONST(I32, offset_of_local(n)));
  578. break;
  579. case VALUE_TYPE_F32:
  580. res = jit_cc_new_reg_F32(cc);
  581. GEN_INSN(LDF32, res, argv, NEW_CONST(I32, 0));
  582. GEN_INSN(STF32, res, cc->fp_reg,
  583. NEW_CONST(I32, offset_of_local(n)));
  584. break;
  585. case VALUE_TYPE_F64:
  586. res = jit_cc_new_reg_F64(cc);
  587. GEN_INSN(LDF64, res, argv, NEW_CONST(I32, 0));
  588. GEN_INSN(STF64, res, cc->fp_reg,
  589. NEW_CONST(I32, offset_of_local(n)));
  590. break;
  591. default:
  592. bh_assert(0);
  593. goto fail;
  594. }
  595. }
  596. gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
  597. clear_values(jit_frame);
  598. GEN_INSN(JMP, jit_basic_block_label(func_return));
  599. /* basic_block non_import */
  600. cc->cur_basic_block = block_nonimport;
  601. GEN_INSN(LDI32, func_idx, cc->exec_env_reg,
  602. NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache) + 4));
  603. /* get jitted_code */
  604. fast_jit_func_ptrs = get_fast_jit_func_ptrs_reg(jit_frame);
  605. jitted_code_idx = jit_cc_new_reg_I32(cc);
  606. jitted_code = jit_cc_new_reg_ptr(cc);
  607. GEN_INSN(SUB, jitted_code_idx, func_idx,
  608. NEW_CONST(I32, cc->cur_wasm_module->import_function_count));
  609. if (UINTPTR_MAX == UINT64_MAX) {
  610. JitReg jitted_code_offset = jit_cc_new_reg_I32(cc);
  611. JitReg jitted_code_offset_64 = jit_cc_new_reg_I64(cc);
  612. GEN_INSN(SHL, jitted_code_offset, jitted_code_idx, NEW_CONST(I32, 3));
  613. GEN_INSN(I32TOI64, jitted_code_offset_64, jitted_code_offset);
  614. GEN_INSN(LDPTR, jitted_code, fast_jit_func_ptrs, jitted_code_offset_64);
  615. }
  616. else {
  617. JitReg jitted_code_offset = jit_cc_new_reg_I32(cc);
  618. GEN_INSN(SHL, jitted_code_offset, jitted_code_idx, NEW_CONST(I32, 2));
  619. GEN_INSN(LDPTR, jitted_code, fast_jit_func_ptrs, jitted_code_offset);
  620. }
  621. res = 0;
  622. if (func_type->result_count > 0) {
  623. switch (func_type->types[func_type->param_count]) {
  624. case VALUE_TYPE_I32:
  625. #if WASM_ENABLE_REF_TYPES != 0
  626. case VALUE_TYPE_EXTERNREF:
  627. case VALUE_TYPE_FUNCREF:
  628. #endif
  629. res = jit_cc_new_reg_I32(cc);
  630. break;
  631. case VALUE_TYPE_I64:
  632. res = jit_cc_new_reg_I64(cc);
  633. break;
  634. case VALUE_TYPE_F32:
  635. res = jit_cc_new_reg_F32(cc);
  636. break;
  637. case VALUE_TYPE_F64:
  638. res = jit_cc_new_reg_F64(cc);
  639. break;
  640. default:
  641. bh_assert(0);
  642. goto fail;
  643. }
  644. }
  645. GEN_INSN(CALLBC, res, 0, jitted_code, func_idx);
  646. /* Store res into current frame, so that post_return in
  647. block func_return can get the value */
  648. n = cc->jit_frame->sp - cc->jit_frame->lp;
  649. if (func_type->result_count > 0) {
  650. switch (func_type->types[func_type->param_count]) {
  651. case VALUE_TYPE_I32:
  652. #if WASM_ENABLE_REF_TYPES != 0
  653. case VALUE_TYPE_EXTERNREF:
  654. case VALUE_TYPE_FUNCREF:
  655. #endif
  656. GEN_INSN(STI32, res, cc->fp_reg,
  657. NEW_CONST(I32, offset_of_local(n)));
  658. break;
  659. case VALUE_TYPE_I64:
  660. GEN_INSN(STI64, res, cc->fp_reg,
  661. NEW_CONST(I32, offset_of_local(n)));
  662. break;
  663. case VALUE_TYPE_F32:
  664. GEN_INSN(STF32, res, cc->fp_reg,
  665. NEW_CONST(I32, offset_of_local(n)));
  666. break;
  667. case VALUE_TYPE_F64:
  668. GEN_INSN(STF64, res, cc->fp_reg,
  669. NEW_CONST(I32, offset_of_local(n)));
  670. break;
  671. default:
  672. bh_assert(0);
  673. goto fail;
  674. }
  675. }
  676. /* commit and clear jit frame, then jump to block func_ret */
  677. gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
  678. clear_values(jit_frame);
  679. GEN_INSN(JMP, jit_basic_block_label(func_return));
  680. /* translate block func_return */
  681. cc->cur_basic_block = func_return;
  682. if (!post_return(cc, func_type, 0, true)) {
  683. goto fail;
  684. }
  685. #if WASM_ENABLE_THREAD_MGR != 0
  686. /* Insert suspend check point */
  687. if (!jit_check_suspend_flags(cc))
  688. goto fail;
  689. #endif
  690. /* Clear part of memory regs and table regs as their values
  691. may be changed in the function call */
  692. if (cc->cur_wasm_module->possible_memory_grow)
  693. clear_memory_regs(cc->jit_frame);
  694. clear_table_regs(cc->jit_frame);
  695. return true;
  696. fail:
  697. return false;
  698. }
  699. #if WASM_ENABLE_REF_TYPES != 0
  700. bool
  701. jit_compile_op_ref_null(JitCompContext *cc, uint32 ref_type)
  702. {
  703. PUSH_I32(NEW_CONST(I32, NULL_REF));
  704. (void)ref_type;
  705. return true;
  706. fail:
  707. return false;
  708. }
  709. bool
  710. jit_compile_op_ref_is_null(JitCompContext *cc)
  711. {
  712. JitReg ref, res;
  713. POP_I32(ref);
  714. GEN_INSN(CMP, cc->cmp_reg, ref, NEW_CONST(I32, NULL_REF));
  715. res = jit_cc_new_reg_I32(cc);
  716. GEN_INSN(SELECTEQ, res, cc->cmp_reg, NEW_CONST(I32, 1), NEW_CONST(I32, 0));
  717. PUSH_I32(res);
  718. return true;
  719. fail:
  720. return false;
  721. }
  722. bool
  723. jit_compile_op_ref_func(JitCompContext *cc, uint32 func_idx)
  724. {
  725. PUSH_I32(NEW_CONST(I32, func_idx));
  726. return true;
  727. fail:
  728. return false;
  729. }
  730. #endif
  731. #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
  732. static bool
  733. emit_callnative(JitCompContext *cc, JitReg native_func_reg, JitReg res,
  734. JitReg *params, uint32 param_count)
  735. {
  736. JitInsn *insn;
  737. char *i64_arg_names[] = { "rdi", "rsi", "rdx", "rcx", "r8", "r9" };
  738. char *f32_arg_names[] = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" };
  739. char *f64_arg_names[] = { "xmm0_f64", "xmm1_f64", "xmm2_f64",
  740. "xmm3_f64", "xmm4_f64", "xmm5_f64" };
  741. JitReg i64_arg_regs[6], f32_arg_regs[6], f64_arg_regs[6], res_reg = 0;
  742. JitReg eax_hreg = jit_codegen_get_hreg_by_name("eax");
  743. JitReg xmm0_hreg = jit_codegen_get_hreg_by_name("xmm0");
  744. uint32 i, i64_reg_idx, float_reg_idx;
  745. bh_assert(param_count <= 6);
  746. for (i = 0; i < 6; i++) {
  747. i64_arg_regs[i] = jit_codegen_get_hreg_by_name(i64_arg_names[i]);
  748. f32_arg_regs[i] = jit_codegen_get_hreg_by_name(f32_arg_names[i]);
  749. f64_arg_regs[i] = jit_codegen_get_hreg_by_name(f64_arg_names[i]);
  750. }
  751. i64_reg_idx = float_reg_idx = 0;
  752. for (i = 0; i < param_count; i++) {
  753. switch (jit_reg_kind(params[i])) {
  754. case JIT_REG_KIND_I32:
  755. GEN_INSN(I32TOI64, i64_arg_regs[i64_reg_idx++], params[i]);
  756. break;
  757. case JIT_REG_KIND_I64:
  758. GEN_INSN(MOV, i64_arg_regs[i64_reg_idx++], params[i]);
  759. break;
  760. case JIT_REG_KIND_F32:
  761. GEN_INSN(MOV, f32_arg_regs[float_reg_idx++], params[i]);
  762. break;
  763. case JIT_REG_KIND_F64:
  764. GEN_INSN(MOV, f64_arg_regs[float_reg_idx++], params[i]);
  765. break;
  766. default:
  767. bh_assert(0);
  768. return false;
  769. }
  770. }
  771. if (res) {
  772. switch (jit_reg_kind(res)) {
  773. case JIT_REG_KIND_I32:
  774. res_reg = eax_hreg;
  775. break;
  776. case JIT_REG_KIND_I64:
  777. res_reg = res;
  778. break;
  779. case JIT_REG_KIND_F32:
  780. res_reg = xmm0_hreg;
  781. break;
  782. case JIT_REG_KIND_F64:
  783. res_reg = res;
  784. break;
  785. default:
  786. bh_assert(0);
  787. return false;
  788. }
  789. }
  790. insn = GEN_INSN(CALLNATIVE, res_reg, native_func_reg, param_count);
  791. if (!insn) {
  792. return false;
  793. }
  794. i64_reg_idx = float_reg_idx = 0;
  795. for (i = 0; i < param_count; i++) {
  796. switch (jit_reg_kind(params[i])) {
  797. case JIT_REG_KIND_I32:
  798. case JIT_REG_KIND_I64:
  799. *(jit_insn_opndv(insn, i + 2)) = i64_arg_regs[i64_reg_idx++];
  800. break;
  801. case JIT_REG_KIND_F32:
  802. *(jit_insn_opndv(insn, i + 2)) = f32_arg_regs[float_reg_idx++];
  803. break;
  804. case JIT_REG_KIND_F64:
  805. *(jit_insn_opndv(insn, i + 2)) = f64_arg_regs[float_reg_idx++];
  806. break;
  807. default:
  808. bh_assert(0);
  809. return false;
  810. }
  811. }
  812. if (res && res != res_reg) {
  813. GEN_INSN(MOV, res, res_reg);
  814. }
  815. return true;
  816. }
  817. #else
  818. static bool
  819. emit_callnative(JitCompContext *cc, JitRef native_func_reg, JitReg res,
  820. JitReg *params, uint32 param_count)
  821. {
  822. JitInsn *insn;
  823. uint32 i;
  824. bh_assert(param_count <= 6);
  825. insn = GEN_INSN(CALLNATIVE, res, native_func_reg, param_count);
  826. if (!insn)
  827. return false;
  828. for (i = 0; i < param_count; i++) {
  829. *(jit_insn_opndv(insn, i + 2)) = params[i];
  830. }
  831. return true;
  832. }
  833. #endif
  834. bool
  835. jit_emit_callnative(JitCompContext *cc, void *native_func, JitReg res,
  836. JitReg *params, uint32 param_count)
  837. {
  838. return emit_callnative(cc, NEW_CONST(PTR, (uintptr_t)native_func), res,
  839. params, param_count);
  840. }