jit_emit_variable.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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;
  152. }
  153. else {
  154. const WASMGlobal *global =
  155. module->globals + (global_idx - module->import_global_count);
  156. return global->type;
  157. }
  158. }
  159. static uint32
  160. get_global_data_offset(const WASMModule *module, uint32 global_idx)
  161. {
  162. if (global_idx < module->import_global_count) {
  163. const WASMGlobalImport *import_global =
  164. &((module->import_globals + global_idx)->u.global);
  165. return import_global->data_offset;
  166. }
  167. else {
  168. const WASMGlobal *global =
  169. module->globals + (global_idx - module->import_global_count);
  170. return global->data_offset;
  171. }
  172. }
  173. bool
  174. jit_compile_op_get_global(JitCompContext *cc, uint32 global_idx)
  175. {
  176. uint32 data_offset;
  177. uint8 global_type = 0;
  178. JitReg value = 0;
  179. bh_assert(global_idx < cc->cur_wasm_module->import_global_count
  180. + cc->cur_wasm_module->global_count);
  181. data_offset = get_global_data_offset(cc->cur_wasm_module, global_idx);
  182. global_type = get_global_type(cc->cur_wasm_module, global_idx);
  183. switch (global_type) {
  184. case VALUE_TYPE_I32:
  185. #if WASM_ENABLE_REF_TYPES != 0
  186. case VALUE_TYPE_EXTERNREF:
  187. case VALUE_TYPE_FUNCREF:
  188. #endif
  189. {
  190. value = jit_cc_new_reg_I32(cc);
  191. GEN_INSN(LDI32, value, get_global_data_reg(cc->jit_frame),
  192. NEW_CONST(I32, data_offset));
  193. break;
  194. }
  195. case VALUE_TYPE_I64:
  196. {
  197. value = jit_cc_new_reg_I64(cc);
  198. GEN_INSN(LDI64, value, get_global_data_reg(cc->jit_frame),
  199. NEW_CONST(I32, data_offset));
  200. break;
  201. }
  202. case VALUE_TYPE_F32:
  203. {
  204. value = jit_cc_new_reg_F32(cc);
  205. GEN_INSN(LDF32, value, get_global_data_reg(cc->jit_frame),
  206. NEW_CONST(I32, data_offset));
  207. break;
  208. }
  209. case VALUE_TYPE_F64:
  210. {
  211. value = jit_cc_new_reg_F64(cc);
  212. GEN_INSN(LDF64, value, get_global_data_reg(cc->jit_frame),
  213. NEW_CONST(I32, data_offset));
  214. break;
  215. }
  216. default:
  217. {
  218. jit_set_last_error(cc, "unexpected global type");
  219. goto fail;
  220. }
  221. }
  222. PUSH(value, global_type);
  223. return true;
  224. fail:
  225. return false;
  226. }
  227. bool
  228. jit_compile_op_set_global(JitCompContext *cc, uint32 global_idx,
  229. bool is_aux_stack)
  230. {
  231. uint32 data_offset;
  232. uint8 global_type = 0;
  233. JitReg value = 0;
  234. bh_assert(global_idx < cc->cur_wasm_module->import_global_count
  235. + cc->cur_wasm_module->global_count);
  236. data_offset = get_global_data_offset(cc->cur_wasm_module, global_idx);
  237. global_type = get_global_type(cc->cur_wasm_module, global_idx);
  238. switch (global_type) {
  239. case VALUE_TYPE_I32:
  240. #if WASM_ENABLE_REF_TYPES != 0
  241. case VALUE_TYPE_EXTERNREF:
  242. case VALUE_TYPE_FUNCREF:
  243. #endif
  244. {
  245. POP_I32(value);
  246. if (is_aux_stack) {
  247. JitReg aux_stack_bound = get_aux_stack_bound_reg(cc->jit_frame);
  248. JitReg aux_stack_bottom =
  249. get_aux_stack_bottom_reg(cc->jit_frame);
  250. GEN_INSN(CMP, cc->cmp_reg, value, aux_stack_bound);
  251. if (!(jit_emit_exception(cc, JIT_EXCE_AUX_STACK_OVERFLOW,
  252. JIT_OP_BLEU, cc->cmp_reg, NULL)))
  253. goto fail;
  254. GEN_INSN(CMP, cc->cmp_reg, value, aux_stack_bottom);
  255. if (!(jit_emit_exception(cc, JIT_EXCE_AUX_STACK_UNDERFLOW,
  256. JIT_OP_BGTU, cc->cmp_reg, NULL)))
  257. goto fail;
  258. }
  259. GEN_INSN(STI32, value, get_global_data_reg(cc->jit_frame),
  260. NEW_CONST(I32, data_offset));
  261. break;
  262. }
  263. case VALUE_TYPE_I64:
  264. {
  265. POP_I64(value);
  266. GEN_INSN(STI64, value, get_global_data_reg(cc->jit_frame),
  267. NEW_CONST(I32, data_offset));
  268. break;
  269. }
  270. case VALUE_TYPE_F32:
  271. {
  272. POP_F32(value);
  273. GEN_INSN(STF32, value, get_global_data_reg(cc->jit_frame),
  274. NEW_CONST(I32, data_offset));
  275. break;
  276. }
  277. case VALUE_TYPE_F64:
  278. {
  279. POP_F64(value);
  280. GEN_INSN(STF64, value, get_global_data_reg(cc->jit_frame),
  281. NEW_CONST(I32, data_offset));
  282. break;
  283. }
  284. default:
  285. {
  286. jit_set_last_error(cc, "unexpected global type");
  287. goto fail;
  288. }
  289. }
  290. return true;
  291. fail:
  292. return false;
  293. }