jit_emit_function.c 31 KB

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