jit_emit_function.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  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. /* Calculate offset by pointer size (elem_idx *
  443. * sizeof(table_elem_type_t)) */
  444. GEN_INSN(SHL, offset_i32, elem_idx, NEW_CONST(I32, 3));
  445. GEN_INSN(I32TOI64, offset, offset_i32);
  446. }
  447. else {
  448. offset = jit_cc_new_reg_I32(cc);
  449. GEN_INSN(SHL, offset, elem_idx, NEW_CONST(I32, 2));
  450. }
  451. func_idx = jit_cc_new_reg_I32(cc);
  452. tbl_elems = get_table_elems_reg(jit_frame, tbl_idx);
  453. GEN_INSN(LDI32, func_idx, tbl_elems, offset);
  454. GEN_INSN(CMP, cc->cmp_reg, func_idx, NEW_CONST(I32, -1));
  455. if (!jit_emit_exception(cc, EXCE_UNINITIALIZED_ELEMENT, JIT_OP_BEQ,
  456. cc->cmp_reg, NULL))
  457. goto fail;
  458. func_count = NEW_CONST(I32, wasm_module->import_function_count
  459. + wasm_module->function_count);
  460. GEN_INSN(CMP, cc->cmp_reg, func_idx, func_count);
  461. if (!jit_emit_exception(cc, EXCE_INVALID_FUNCTION_INDEX, JIT_OP_BGTU,
  462. cc->cmp_reg, NULL))
  463. goto fail;
  464. /* check func_type */
  465. /* get func_type_idx from func_type_indexes */
  466. if (UINTPTR_MAX == UINT64_MAX) {
  467. offset1_i32 = jit_cc_new_reg_I32(cc);
  468. offset1 = jit_cc_new_reg_I64(cc);
  469. GEN_INSN(SHL, offset1_i32, func_idx, NEW_CONST(I32, 2));
  470. GEN_INSN(I32TOI64, offset1, offset1_i32);
  471. }
  472. else {
  473. offset1 = jit_cc_new_reg_I32(cc);
  474. GEN_INSN(SHL, offset1, func_idx, NEW_CONST(I32, 2));
  475. }
  476. func_type_indexes = get_func_type_indexes_reg(jit_frame);
  477. func_type_idx = jit_cc_new_reg_I32(cc);
  478. GEN_INSN(LDI32, func_type_idx, func_type_indexes, offset1);
  479. type_idx = wasm_get_smallest_type_idx(wasm_module->types,
  480. wasm_module->type_count, type_idx);
  481. func_type_idx1 = NEW_CONST(I32, type_idx);
  482. GEN_INSN(CMP, cc->cmp_reg, func_type_idx, func_type_idx1);
  483. if (!jit_emit_exception(cc, EXCE_INVALID_FUNCTION_TYPE_INDEX, JIT_OP_BNE,
  484. cc->cmp_reg, NULL))
  485. goto fail;
  486. /* pop function arguments and store it to out area of callee stack frame */
  487. func_type = wasm_module->types[type_idx];
  488. if (!pre_call(cc, func_type)) {
  489. goto fail;
  490. }
  491. /* store elem_idx and func_idx to exec_env->jit_cache */
  492. GEN_INSN(STI32, elem_idx, cc->exec_env_reg,
  493. NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache)));
  494. GEN_INSN(STI32, func_idx, cc->exec_env_reg,
  495. NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache) + 4));
  496. #if WASM_ENABLE_THREAD_MGR != 0
  497. /* Insert suspend check point */
  498. if (!jit_check_suspend_flags(cc))
  499. goto fail;
  500. #endif
  501. block_import = jit_cc_new_basic_block(cc, 0);
  502. block_nonimport = jit_cc_new_basic_block(cc, 0);
  503. func_return = jit_cc_new_basic_block(cc, 0);
  504. if (!block_import || !block_nonimport || !func_return) {
  505. goto fail;
  506. }
  507. /* Commit register values to locals and stacks */
  508. gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
  509. /* Clear frame values */
  510. clear_values(jit_frame);
  511. /* jump to block_import or block_nonimport */
  512. GEN_INSN(CMP, cc->cmp_reg, func_idx,
  513. NEW_CONST(I32, cc->cur_wasm_module->import_function_count));
  514. GEN_INSN(BLTU, cc->cmp_reg, jit_basic_block_label(block_import),
  515. jit_basic_block_label(block_nonimport));
  516. /* block_import */
  517. cc->cur_basic_block = block_import;
  518. elem_idx = jit_cc_new_reg_I32(cc);
  519. GEN_INSN(LDI32, elem_idx, cc->exec_env_reg,
  520. NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache)));
  521. GEN_INSN(LDI32, func_idx, cc->exec_env_reg,
  522. NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache) + 4));
  523. argv = pack_argv(cc);
  524. if (!argv) {
  525. goto fail;
  526. }
  527. native_ret = jit_cc_new_reg_I32(cc);
  528. arg_regs[0] = cc->exec_env_reg;
  529. arg_regs[1] = NEW_CONST(I32, tbl_idx);
  530. arg_regs[2] = elem_idx;
  531. arg_regs[3] = NEW_CONST(I32, type_idx);
  532. arg_regs[4] = NEW_CONST(I32, func_type->param_cell_num);
  533. arg_regs[5] = argv;
  534. import_func_ptrs = get_import_func_ptrs_reg(jit_frame);
  535. func_import = jit_cc_new_reg_ptr(cc);
  536. if (UINTPTR_MAX == UINT64_MAX) {
  537. JitReg func_import_offset = jit_cc_new_reg_I32(cc);
  538. JitReg func_import_offset_i64 = jit_cc_new_reg_I64(cc);
  539. GEN_INSN(SHL, func_import_offset, func_idx, NEW_CONST(I32, 3));
  540. GEN_INSN(I32TOI64, func_import_offset_i64, func_import_offset);
  541. GEN_INSN(LDPTR, func_import, import_func_ptrs, func_import_offset_i64);
  542. }
  543. else {
  544. JitReg func_import_offset = jit_cc_new_reg_I32(cc);
  545. GEN_INSN(SHL, func_import_offset, func_idx, NEW_CONST(I32, 2));
  546. GEN_INSN(LDPTR, func_import, import_func_ptrs, func_import_offset);
  547. }
  548. if (!jit_emit_callnative(cc, fast_jit_call_indirect, native_ret, arg_regs,
  549. 6)) {
  550. goto fail;
  551. }
  552. /* Convert bool to uint32 */
  553. GEN_INSN(AND, native_ret, native_ret, NEW_CONST(I32, 0xFF));
  554. /* Check whether there is exception thrown */
  555. GEN_INSN(CMP, cc->cmp_reg, native_ret, NEW_CONST(I32, 0));
  556. if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BEQ, cc->cmp_reg,
  557. NULL)) {
  558. return false;
  559. }
  560. /* Store res into current frame, so that post_return in
  561. block func_return can get the value */
  562. n = cc->jit_frame->sp - cc->jit_frame->lp;
  563. if (func_type->result_count > 0) {
  564. switch (func_type->types[func_type->param_count]) {
  565. case VALUE_TYPE_I32:
  566. #if WASM_ENABLE_REF_TYPES != 0
  567. case VALUE_TYPE_EXTERNREF:
  568. case VALUE_TYPE_FUNCREF:
  569. #endif
  570. res = jit_cc_new_reg_I32(cc);
  571. GEN_INSN(LDI32, res, argv, NEW_CONST(I32, 0));
  572. GEN_INSN(STI32, res, cc->fp_reg,
  573. NEW_CONST(I32, offset_of_local(n)));
  574. break;
  575. case VALUE_TYPE_I64:
  576. res = jit_cc_new_reg_I64(cc);
  577. GEN_INSN(LDI64, res, argv, NEW_CONST(I32, 0));
  578. GEN_INSN(STI64, res, cc->fp_reg,
  579. NEW_CONST(I32, offset_of_local(n)));
  580. break;
  581. case VALUE_TYPE_F32:
  582. res = jit_cc_new_reg_F32(cc);
  583. GEN_INSN(LDF32, res, argv, NEW_CONST(I32, 0));
  584. GEN_INSN(STF32, res, cc->fp_reg,
  585. NEW_CONST(I32, offset_of_local(n)));
  586. break;
  587. case VALUE_TYPE_F64:
  588. res = jit_cc_new_reg_F64(cc);
  589. GEN_INSN(LDF64, res, argv, NEW_CONST(I32, 0));
  590. GEN_INSN(STF64, res, cc->fp_reg,
  591. NEW_CONST(I32, offset_of_local(n)));
  592. break;
  593. default:
  594. bh_assert(0);
  595. goto fail;
  596. }
  597. }
  598. gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
  599. clear_values(jit_frame);
  600. GEN_INSN(JMP, jit_basic_block_label(func_return));
  601. /* basic_block non_import */
  602. cc->cur_basic_block = block_nonimport;
  603. GEN_INSN(LDI32, func_idx, cc->exec_env_reg,
  604. NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache) + 4));
  605. /* get jitted_code */
  606. fast_jit_func_ptrs = get_fast_jit_func_ptrs_reg(jit_frame);
  607. jitted_code_idx = jit_cc_new_reg_I32(cc);
  608. jitted_code = jit_cc_new_reg_ptr(cc);
  609. GEN_INSN(SUB, jitted_code_idx, func_idx,
  610. NEW_CONST(I32, cc->cur_wasm_module->import_function_count));
  611. if (UINTPTR_MAX == UINT64_MAX) {
  612. JitReg jitted_code_offset = jit_cc_new_reg_I32(cc);
  613. JitReg jitted_code_offset_64 = jit_cc_new_reg_I64(cc);
  614. GEN_INSN(SHL, jitted_code_offset, jitted_code_idx, NEW_CONST(I32, 3));
  615. GEN_INSN(I32TOI64, jitted_code_offset_64, jitted_code_offset);
  616. GEN_INSN(LDPTR, jitted_code, fast_jit_func_ptrs, jitted_code_offset_64);
  617. }
  618. else {
  619. JitReg jitted_code_offset = jit_cc_new_reg_I32(cc);
  620. GEN_INSN(SHL, jitted_code_offset, jitted_code_idx, NEW_CONST(I32, 2));
  621. GEN_INSN(LDPTR, jitted_code, fast_jit_func_ptrs, jitted_code_offset);
  622. }
  623. res = 0;
  624. if (func_type->result_count > 0) {
  625. switch (func_type->types[func_type->param_count]) {
  626. case VALUE_TYPE_I32:
  627. #if WASM_ENABLE_REF_TYPES != 0
  628. case VALUE_TYPE_EXTERNREF:
  629. case VALUE_TYPE_FUNCREF:
  630. #endif
  631. res = jit_cc_new_reg_I32(cc);
  632. break;
  633. case VALUE_TYPE_I64:
  634. res = jit_cc_new_reg_I64(cc);
  635. break;
  636. case VALUE_TYPE_F32:
  637. res = jit_cc_new_reg_F32(cc);
  638. break;
  639. case VALUE_TYPE_F64:
  640. res = jit_cc_new_reg_F64(cc);
  641. break;
  642. default:
  643. bh_assert(0);
  644. goto fail;
  645. }
  646. }
  647. GEN_INSN(CALLBC, res, 0, jitted_code, func_idx);
  648. /* Store res into current frame, so that post_return in
  649. block func_return can get the value */
  650. n = cc->jit_frame->sp - cc->jit_frame->lp;
  651. if (func_type->result_count > 0) {
  652. switch (func_type->types[func_type->param_count]) {
  653. case VALUE_TYPE_I32:
  654. #if WASM_ENABLE_REF_TYPES != 0
  655. case VALUE_TYPE_EXTERNREF:
  656. case VALUE_TYPE_FUNCREF:
  657. #endif
  658. GEN_INSN(STI32, res, cc->fp_reg,
  659. NEW_CONST(I32, offset_of_local(n)));
  660. break;
  661. case VALUE_TYPE_I64:
  662. GEN_INSN(STI64, res, cc->fp_reg,
  663. NEW_CONST(I32, offset_of_local(n)));
  664. break;
  665. case VALUE_TYPE_F32:
  666. GEN_INSN(STF32, res, cc->fp_reg,
  667. NEW_CONST(I32, offset_of_local(n)));
  668. break;
  669. case VALUE_TYPE_F64:
  670. GEN_INSN(STF64, res, cc->fp_reg,
  671. NEW_CONST(I32, offset_of_local(n)));
  672. break;
  673. default:
  674. bh_assert(0);
  675. goto fail;
  676. }
  677. }
  678. /* commit and clear jit frame, then jump to block func_ret */
  679. gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
  680. clear_values(jit_frame);
  681. GEN_INSN(JMP, jit_basic_block_label(func_return));
  682. /* translate block func_return */
  683. cc->cur_basic_block = func_return;
  684. if (!post_return(cc, func_type, 0, true)) {
  685. goto fail;
  686. }
  687. #if WASM_ENABLE_THREAD_MGR != 0
  688. /* Insert suspend check point */
  689. if (!jit_check_suspend_flags(cc))
  690. goto fail;
  691. #endif
  692. /* Clear part of memory regs and table regs as their values
  693. may be changed in the function call */
  694. if (cc->cur_wasm_module->possible_memory_grow)
  695. clear_memory_regs(cc->jit_frame);
  696. clear_table_regs(cc->jit_frame);
  697. return true;
  698. fail:
  699. return false;
  700. }
  701. #if WASM_ENABLE_REF_TYPES != 0
  702. bool
  703. jit_compile_op_ref_null(JitCompContext *cc, uint32 ref_type)
  704. {
  705. PUSH_I32(NEW_CONST(I32, NULL_REF));
  706. (void)ref_type;
  707. return true;
  708. fail:
  709. return false;
  710. }
  711. bool
  712. jit_compile_op_ref_is_null(JitCompContext *cc)
  713. {
  714. JitReg ref, res;
  715. POP_I32(ref);
  716. GEN_INSN(CMP, cc->cmp_reg, ref, NEW_CONST(I32, NULL_REF));
  717. res = jit_cc_new_reg_I32(cc);
  718. GEN_INSN(SELECTEQ, res, cc->cmp_reg, NEW_CONST(I32, 1), NEW_CONST(I32, 0));
  719. PUSH_I32(res);
  720. return true;
  721. fail:
  722. return false;
  723. }
  724. bool
  725. jit_compile_op_ref_func(JitCompContext *cc, uint32 func_idx)
  726. {
  727. PUSH_I32(NEW_CONST(I32, func_idx));
  728. return true;
  729. fail:
  730. return false;
  731. }
  732. #endif
  733. #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
  734. static bool
  735. emit_callnative(JitCompContext *cc, JitReg native_func_reg, JitReg res,
  736. JitReg *params, uint32 param_count)
  737. {
  738. JitInsn *insn;
  739. char *i32_arg_names[] = { "edi", "esi", "edx", "ecx" };
  740. char *i64_arg_names[] = { "rdi", "rsi", "rdx", "rcx", "r8", "r9" };
  741. char *f32_arg_names[] = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" };
  742. char *f64_arg_names[] = { "xmm0_f64", "xmm1_f64", "xmm2_f64",
  743. "xmm3_f64", "xmm4_f64", "xmm5_f64" };
  744. JitReg i32_arg_regs[4], i64_arg_regs[6];
  745. JitReg f32_arg_regs[6], f64_arg_regs[6], res_reg = 0;
  746. JitReg eax_hreg = jit_codegen_get_hreg_by_name("eax");
  747. JitReg xmm0_hreg = jit_codegen_get_hreg_by_name("xmm0");
  748. uint32 i, i64_reg_idx, float_reg_idx, lock_i32_reg_num;
  749. bh_assert(param_count <= 6);
  750. for (i = 0; i < 4; i++) {
  751. i32_arg_regs[i] = jit_codegen_get_hreg_by_name(i32_arg_names[i]);
  752. }
  753. for (i = 0; i < 6; i++) {
  754. i64_arg_regs[i] = jit_codegen_get_hreg_by_name(i64_arg_names[i]);
  755. f32_arg_regs[i] = jit_codegen_get_hreg_by_name(f32_arg_names[i]);
  756. f64_arg_regs[i] = jit_codegen_get_hreg_by_name(f64_arg_names[i]);
  757. }
  758. lock_i32_reg_num = param_count < 4 ? param_count : 4;
  759. /*
  760. * Lock i32 registers so that they won't be allocated for the operand
  761. * of below I32TOI64 insn, which may have been overwritten in the
  762. * previous MOV, for example, in the below insns:
  763. * MOV I5, I15
  764. * I32TOI64 I6, i5
  765. * CALLNATIVE VOID, native_func, I5, I6
  766. * i5 is used in the second insn, but it has been overwritten in I5
  767. * by the first insn
  768. */
  769. for (i = 0; i < lock_i32_reg_num; i++) {
  770. GEN_INSN(MOV, i32_arg_regs[i], i32_arg_regs[i]);
  771. }
  772. i64_reg_idx = float_reg_idx = 0;
  773. for (i = 0; i < param_count; i++) {
  774. switch (jit_reg_kind(params[i])) {
  775. case JIT_REG_KIND_I32:
  776. GEN_INSN(I32TOI64, i64_arg_regs[i64_reg_idx++], params[i]);
  777. break;
  778. case JIT_REG_KIND_I64:
  779. GEN_INSN(MOV, i64_arg_regs[i64_reg_idx++], params[i]);
  780. break;
  781. case JIT_REG_KIND_F32:
  782. GEN_INSN(MOV, f32_arg_regs[float_reg_idx++], params[i]);
  783. break;
  784. case JIT_REG_KIND_F64:
  785. GEN_INSN(MOV, f64_arg_regs[float_reg_idx++], params[i]);
  786. break;
  787. default:
  788. bh_assert(0);
  789. return false;
  790. }
  791. }
  792. /*
  793. * Announce the locked i32 registers are being used, and do necessary
  794. * spill ASAP
  795. */
  796. for (i = 0; i < lock_i32_reg_num; i++) {
  797. GEN_INSN(MOV, i32_arg_regs[i], i32_arg_regs[i]);
  798. }
  799. if (res) {
  800. switch (jit_reg_kind(res)) {
  801. case JIT_REG_KIND_I32:
  802. res_reg = eax_hreg;
  803. break;
  804. case JIT_REG_KIND_I64:
  805. res_reg = res;
  806. break;
  807. case JIT_REG_KIND_F32:
  808. res_reg = xmm0_hreg;
  809. break;
  810. case JIT_REG_KIND_F64:
  811. res_reg = res;
  812. break;
  813. default:
  814. bh_assert(0);
  815. return false;
  816. }
  817. }
  818. insn = GEN_INSN(CALLNATIVE, res_reg, native_func_reg, param_count);
  819. if (!insn) {
  820. return false;
  821. }
  822. i64_reg_idx = float_reg_idx = 0;
  823. for (i = 0; i < param_count; i++) {
  824. switch (jit_reg_kind(params[i])) {
  825. case JIT_REG_KIND_I32:
  826. case JIT_REG_KIND_I64:
  827. *(jit_insn_opndv(insn, i + 2)) = i64_arg_regs[i64_reg_idx++];
  828. break;
  829. case JIT_REG_KIND_F32:
  830. *(jit_insn_opndv(insn, i + 2)) = f32_arg_regs[float_reg_idx++];
  831. break;
  832. case JIT_REG_KIND_F64:
  833. *(jit_insn_opndv(insn, i + 2)) = f64_arg_regs[float_reg_idx++];
  834. break;
  835. default:
  836. bh_assert(0);
  837. return false;
  838. }
  839. }
  840. if (res && res != res_reg) {
  841. GEN_INSN(MOV, res, res_reg);
  842. }
  843. return true;
  844. }
  845. #else
  846. static bool
  847. emit_callnative(JitCompContext *cc, JitRef native_func_reg, JitReg res,
  848. JitReg *params, uint32 param_count)
  849. {
  850. JitInsn *insn;
  851. uint32 i;
  852. bh_assert(param_count <= 6);
  853. insn = GEN_INSN(CALLNATIVE, res, native_func_reg, param_count);
  854. if (!insn)
  855. return false;
  856. for (i = 0; i < param_count; i++) {
  857. *(jit_insn_opndv(insn, i + 2)) = params[i];
  858. }
  859. return true;
  860. }
  861. #endif
  862. bool
  863. jit_emit_callnative(JitCompContext *cc, void *native_func, JitReg res,
  864. JitReg *params, uint32 param_count)
  865. {
  866. return emit_callnative(cc, NEW_CONST(PTR, (uintptr_t)native_func), res,
  867. params, param_count);
  868. }