jit_emit_variable.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  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_variable.h"
  6. #include "jit_emit_exception.h"
  7. #include "../jit_frontend.h"
  8. #define CHECK_LOCAL(idx) \
  9. do { \
  10. if (idx \
  11. >= wasm_func->func_type->param_count + wasm_func->local_count) { \
  12. jit_set_last_error(cc, "local index out of range"); \
  13. goto fail; \
  14. } \
  15. } while (0)
  16. static uint8
  17. get_local_type(const WASMFunction *wasm_func, uint32 local_idx)
  18. {
  19. uint32 param_count = wasm_func->func_type->param_count;
  20. return local_idx < param_count
  21. ? wasm_func->func_type->types[local_idx]
  22. : wasm_func->local_types[local_idx - param_count];
  23. }
  24. bool
  25. jit_compile_op_get_local(JitCompContext *cc, uint32 local_idx)
  26. {
  27. WASMFunction *wasm_func = cc->cur_wasm_func;
  28. uint16 *local_offsets = wasm_func->local_offsets;
  29. uint16 local_offset;
  30. uint8 local_type;
  31. JitReg value = 0;
  32. CHECK_LOCAL(local_idx);
  33. local_offset = local_offsets[local_idx];
  34. local_type = get_local_type(wasm_func, local_idx);
  35. switch (local_type) {
  36. case VALUE_TYPE_I32:
  37. #if WASM_ENABLE_REF_TYPES != 0
  38. case VALUE_TYPE_EXTERNREF:
  39. case VALUE_TYPE_FUNCREF:
  40. #endif
  41. value = local_i32(cc->jit_frame, local_offset);
  42. break;
  43. case VALUE_TYPE_I64:
  44. value = local_i64(cc->jit_frame, local_offset);
  45. break;
  46. case VALUE_TYPE_F32:
  47. value = local_f32(cc->jit_frame, local_offset);
  48. break;
  49. case VALUE_TYPE_F64:
  50. value = local_f64(cc->jit_frame, local_offset);
  51. break;
  52. default:
  53. bh_assert(0);
  54. break;
  55. }
  56. PUSH(value, local_type);
  57. return true;
  58. fail:
  59. return false;
  60. }
  61. bool
  62. jit_compile_op_set_local(JitCompContext *cc, uint32 local_idx)
  63. {
  64. WASMFunction *wasm_func = cc->cur_wasm_func;
  65. uint16 *local_offsets = wasm_func->local_offsets;
  66. uint16 local_offset;
  67. uint8 local_type;
  68. JitReg value;
  69. CHECK_LOCAL(local_idx);
  70. local_offset = local_offsets[local_idx];
  71. local_type = get_local_type(wasm_func, local_idx);
  72. switch (local_type) {
  73. case VALUE_TYPE_I32:
  74. #if WASM_ENABLE_REF_TYPES != 0
  75. case VALUE_TYPE_EXTERNREF:
  76. case VALUE_TYPE_FUNCREF:
  77. #endif
  78. POP_I32(value);
  79. set_local_i32(cc->jit_frame, local_offset, value);
  80. break;
  81. case VALUE_TYPE_I64:
  82. POP_I64(value);
  83. set_local_i64(cc->jit_frame, local_offset, value);
  84. break;
  85. case VALUE_TYPE_F32:
  86. POP_F32(value);
  87. set_local_f32(cc->jit_frame, local_offset, value);
  88. break;
  89. case VALUE_TYPE_F64:
  90. POP_F64(value);
  91. set_local_f64(cc->jit_frame, local_offset, value);
  92. break;
  93. default:
  94. bh_assert(0);
  95. break;
  96. }
  97. return true;
  98. fail:
  99. return false;
  100. }
  101. bool
  102. jit_compile_op_tee_local(JitCompContext *cc, uint32 local_idx)
  103. {
  104. WASMFunction *wasm_func = cc->cur_wasm_func;
  105. uint16 *local_offsets = wasm_func->local_offsets;
  106. uint16 local_offset;
  107. uint8 local_type;
  108. JitReg value = 0;
  109. CHECK_LOCAL(local_idx);
  110. local_offset = local_offsets[local_idx];
  111. local_type = get_local_type(wasm_func, local_idx);
  112. switch (local_type) {
  113. case VALUE_TYPE_I32:
  114. #if WASM_ENABLE_REF_TYPES != 0
  115. case VALUE_TYPE_EXTERNREF:
  116. case VALUE_TYPE_FUNCREF:
  117. #endif
  118. POP_I32(value);
  119. set_local_i32(cc->jit_frame, local_offset, value);
  120. PUSH_I32(value);
  121. break;
  122. case VALUE_TYPE_I64:
  123. POP_I64(value);
  124. set_local_i64(cc->jit_frame, local_offset, value);
  125. PUSH_I64(value);
  126. break;
  127. case VALUE_TYPE_F32:
  128. POP_F32(value);
  129. set_local_f32(cc->jit_frame, local_offset, value);
  130. PUSH_F32(value);
  131. break;
  132. case VALUE_TYPE_F64:
  133. POP_F64(value);
  134. set_local_f64(cc->jit_frame, local_offset, value);
  135. PUSH_F64(value);
  136. break;
  137. default:
  138. bh_assert(0);
  139. goto fail;
  140. }
  141. return true;
  142. fail:
  143. return false;
  144. }
  145. static uint8
  146. get_global_type(const WASMModule *module, uint32 global_idx)
  147. {
  148. if (global_idx < module->import_global_count) {
  149. const WASMGlobalImport *import_global =
  150. &((module->import_globals + global_idx)->u.global);
  151. return import_global->type.val_type;
  152. }
  153. else {
  154. const WASMGlobal *global =
  155. module->globals + (global_idx - module->import_global_count);
  156. return global->type.val_type;
  157. }
  158. }
  159. bool
  160. jit_compile_op_get_global(JitCompContext *cc, uint32 global_idx)
  161. {
  162. uint32 data_offset;
  163. uint8 global_type = 0;
  164. JitReg value = 0;
  165. bh_assert(global_idx < cc->cur_wasm_module->import_global_count
  166. + cc->cur_wasm_module->global_count);
  167. data_offset =
  168. jit_frontend_get_global_data_offset(cc->cur_wasm_module, global_idx);
  169. global_type = get_global_type(cc->cur_wasm_module, global_idx);
  170. switch (global_type) {
  171. case VALUE_TYPE_I32:
  172. #if WASM_ENABLE_REF_TYPES != 0
  173. case VALUE_TYPE_EXTERNREF:
  174. case VALUE_TYPE_FUNCREF:
  175. #endif
  176. {
  177. value = jit_cc_new_reg_I32(cc);
  178. GEN_INSN(LDI32, value, get_module_inst_reg(cc->jit_frame),
  179. NEW_CONST(I32, data_offset));
  180. break;
  181. }
  182. case VALUE_TYPE_I64:
  183. {
  184. value = jit_cc_new_reg_I64(cc);
  185. GEN_INSN(LDI64, value, get_module_inst_reg(cc->jit_frame),
  186. NEW_CONST(I32, data_offset));
  187. break;
  188. }
  189. case VALUE_TYPE_F32:
  190. {
  191. value = jit_cc_new_reg_F32(cc);
  192. GEN_INSN(LDF32, value, get_module_inst_reg(cc->jit_frame),
  193. NEW_CONST(I32, data_offset));
  194. break;
  195. }
  196. case VALUE_TYPE_F64:
  197. {
  198. value = jit_cc_new_reg_F64(cc);
  199. GEN_INSN(LDF64, value, get_module_inst_reg(cc->jit_frame),
  200. NEW_CONST(I32, data_offset));
  201. break;
  202. }
  203. default:
  204. {
  205. jit_set_last_error(cc, "unexpected global type");
  206. goto fail;
  207. }
  208. }
  209. PUSH(value, global_type);
  210. return true;
  211. fail:
  212. return false;
  213. }
  214. bool
  215. jit_compile_op_set_global(JitCompContext *cc, uint32 global_idx,
  216. bool is_aux_stack)
  217. {
  218. uint32 data_offset;
  219. uint8 global_type = 0;
  220. JitReg value = 0;
  221. bh_assert(global_idx < cc->cur_wasm_module->import_global_count
  222. + cc->cur_wasm_module->global_count);
  223. data_offset =
  224. jit_frontend_get_global_data_offset(cc->cur_wasm_module, global_idx);
  225. global_type = get_global_type(cc->cur_wasm_module, global_idx);
  226. switch (global_type) {
  227. case VALUE_TYPE_I32:
  228. #if WASM_ENABLE_REF_TYPES != 0
  229. case VALUE_TYPE_EXTERNREF:
  230. case VALUE_TYPE_FUNCREF:
  231. #endif
  232. {
  233. POP_I32(value);
  234. if (is_aux_stack) {
  235. JitReg aux_stack_bound = get_aux_stack_bound_reg(cc->jit_frame);
  236. JitReg aux_stack_bottom =
  237. get_aux_stack_bottom_reg(cc->jit_frame);
  238. GEN_INSN(CMP, cc->cmp_reg, value, aux_stack_bound);
  239. if (!(jit_emit_exception(cc, EXCE_AUX_STACK_OVERFLOW,
  240. JIT_OP_BLEU, cc->cmp_reg, NULL)))
  241. goto fail;
  242. GEN_INSN(CMP, cc->cmp_reg, value, aux_stack_bottom);
  243. if (!(jit_emit_exception(cc, EXCE_AUX_STACK_UNDERFLOW,
  244. JIT_OP_BGTU, cc->cmp_reg, NULL)))
  245. goto fail;
  246. }
  247. GEN_INSN(STI32, value, get_module_inst_reg(cc->jit_frame),
  248. NEW_CONST(I32, data_offset));
  249. break;
  250. }
  251. case VALUE_TYPE_I64:
  252. {
  253. POP_I64(value);
  254. GEN_INSN(STI64, value, get_module_inst_reg(cc->jit_frame),
  255. NEW_CONST(I32, data_offset));
  256. break;
  257. }
  258. case VALUE_TYPE_F32:
  259. {
  260. POP_F32(value);
  261. GEN_INSN(STF32, value, get_module_inst_reg(cc->jit_frame),
  262. NEW_CONST(I32, data_offset));
  263. break;
  264. }
  265. case VALUE_TYPE_F64:
  266. {
  267. POP_F64(value);
  268. GEN_INSN(STF64, value, get_module_inst_reg(cc->jit_frame),
  269. NEW_CONST(I32, data_offset));
  270. break;
  271. }
  272. default:
  273. {
  274. jit_set_last_error(cc, "unexpected global type");
  275. goto fail;
  276. }
  277. }
  278. return true;
  279. fail:
  280. return false;
  281. }