aot_emit_variable.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "aot_emit_variable.h"
  6. #include "aot_emit_exception.h"
  7. #include "../aot/aot_runtime.h"
  8. #define CHECK_LOCAL(idx) \
  9. do { \
  10. if (idx >= func_ctx->aot_func->func_type->param_count \
  11. + func_ctx->aot_func->local_count) { \
  12. aot_set_last_error("local index out of range"); \
  13. return false; \
  14. } \
  15. } while (0)
  16. static uint8
  17. get_local_type(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  18. uint32 local_idx)
  19. {
  20. AOTFunc *aot_func = func_ctx->aot_func;
  21. uint32 param_count = aot_func->func_type->param_count;
  22. uint8 local_type;
  23. local_type = local_idx < param_count
  24. ? aot_func->func_type->types[local_idx]
  25. : aot_func->local_types[local_idx - param_count];
  26. #if WASM_ENABLE_GC != 0
  27. if (comp_ctx->enable_gc && wasm_is_type_reftype(local_type))
  28. local_type = VALUE_TYPE_GC_REF;
  29. #endif
  30. return local_type;
  31. }
  32. bool
  33. aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  34. uint32 local_idx)
  35. {
  36. char name[32];
  37. LLVMValueRef value;
  38. AOTValue *aot_value_top;
  39. uint8 local_type;
  40. CHECK_LOCAL(local_idx);
  41. local_type = get_local_type(comp_ctx, func_ctx, local_idx);
  42. snprintf(name, sizeof(name), "%s%d%s", "local", local_idx, "#");
  43. if (!(value = LLVMBuildLoad2(comp_ctx->builder, TO_LLVM_TYPE(local_type),
  44. func_ctx->locals[local_idx], name))) {
  45. aot_set_last_error("llvm build load fail");
  46. return false;
  47. }
  48. PUSH(value, local_type);
  49. aot_value_top =
  50. func_ctx->block_stack.block_list_end->value_stack.value_list_end;
  51. aot_value_top->is_local = true;
  52. aot_value_top->local_idx = local_idx;
  53. return true;
  54. fail:
  55. return false;
  56. }
  57. bool
  58. aot_compile_op_set_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  59. uint32 local_idx)
  60. {
  61. LLVMValueRef value;
  62. uint8 local_type;
  63. uint32 n;
  64. CHECK_LOCAL(local_idx);
  65. local_type = get_local_type(comp_ctx, func_ctx, local_idx);
  66. POP(value, local_type);
  67. if (comp_ctx->aot_frame) {
  68. /* Get the slot index */
  69. n = comp_ctx->aot_frame->cur_wasm_func->local_offsets[local_idx];
  70. bh_assert(comp_ctx->aot_frame->lp[n].type == local_type);
  71. switch (local_type) {
  72. case VALUE_TYPE_I32:
  73. set_local_i32(comp_ctx->aot_frame, n, value);
  74. break;
  75. case VALUE_TYPE_I64:
  76. set_local_i64(comp_ctx->aot_frame, n, value);
  77. break;
  78. case VALUE_TYPE_F32:
  79. set_local_f32(comp_ctx->aot_frame, n, value);
  80. break;
  81. case VALUE_TYPE_F64:
  82. set_local_f64(comp_ctx->aot_frame, n, value);
  83. break;
  84. case VALUE_TYPE_V128:
  85. set_local_v128(comp_ctx->aot_frame, n, value);
  86. break;
  87. case VALUE_TYPE_FUNCREF:
  88. case VALUE_TYPE_EXTERNREF:
  89. set_local_ref(comp_ctx->aot_frame, n, value, local_type);
  90. break;
  91. /* TODO: handle GC ref types */
  92. default:
  93. bh_assert(0);
  94. break;
  95. }
  96. }
  97. if (!LLVMBuildStore(comp_ctx->builder, value,
  98. func_ctx->locals[local_idx])) {
  99. aot_set_last_error("llvm build store fail");
  100. return false;
  101. }
  102. aot_checked_addr_list_del(func_ctx, local_idx);
  103. return true;
  104. fail:
  105. return false;
  106. }
  107. bool
  108. aot_compile_op_tee_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  109. uint32 local_idx)
  110. {
  111. LLVMValueRef value;
  112. uint8 type;
  113. CHECK_LOCAL(local_idx);
  114. type = get_local_type(comp_ctx, func_ctx, local_idx);
  115. POP(value, type);
  116. if (!LLVMBuildStore(comp_ctx->builder, value,
  117. func_ctx->locals[local_idx])) {
  118. aot_set_last_error("llvm build store fail");
  119. return false;
  120. }
  121. PUSH(value, type);
  122. aot_checked_addr_list_del(func_ctx, local_idx);
  123. return true;
  124. fail:
  125. return false;
  126. }
  127. static bool
  128. compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  129. uint32 global_idx, bool is_set, bool is_aux_stack)
  130. {
  131. const AOTCompData *comp_data = comp_ctx->comp_data;
  132. uint32 import_global_count = comp_data->import_global_count;
  133. uint32 global_base_offset;
  134. uint32 global_offset;
  135. uint8 global_type;
  136. LLVMValueRef offset, global_ptr, global, res;
  137. LLVMTypeRef ptr_type = NULL;
  138. global_base_offset =
  139. offsetof(AOTModuleInstance, global_table_data.bytes)
  140. + sizeof(AOTMemoryInstance) * comp_ctx->comp_data->memory_count;
  141. bh_assert(global_idx < import_global_count + comp_data->global_count);
  142. if (global_idx < import_global_count) {
  143. global_offset = global_base_offset
  144. + comp_data->import_globals[global_idx].data_offset;
  145. global_type = comp_data->import_globals[global_idx].type;
  146. }
  147. else {
  148. global_offset =
  149. global_base_offset
  150. + comp_data->globals[global_idx - import_global_count].data_offset;
  151. global_type = comp_data->globals[global_idx - import_global_count].type;
  152. }
  153. offset = I32_CONST(global_offset);
  154. if (!(global_ptr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
  155. func_ctx->aot_inst, &offset, 1,
  156. "global_ptr_tmp"))) {
  157. aot_set_last_error("llvm build in bounds gep failed.");
  158. return false;
  159. }
  160. switch (global_type) {
  161. case VALUE_TYPE_I32:
  162. case VALUE_TYPE_EXTERNREF:
  163. case VALUE_TYPE_FUNCREF:
  164. ptr_type = comp_ctx->basic_types.int32_ptr_type;
  165. break;
  166. case VALUE_TYPE_I64:
  167. ptr_type = comp_ctx->basic_types.int64_ptr_type;
  168. break;
  169. case VALUE_TYPE_F32:
  170. ptr_type = comp_ctx->basic_types.float32_ptr_type;
  171. break;
  172. case VALUE_TYPE_F64:
  173. ptr_type = comp_ctx->basic_types.float64_ptr_type;
  174. break;
  175. case VALUE_TYPE_V128:
  176. ptr_type = comp_ctx->basic_types.v128_ptr_type;
  177. break;
  178. default:
  179. bh_assert("unknown type");
  180. break;
  181. }
  182. if (!(global_ptr = LLVMBuildBitCast(comp_ctx->builder, global_ptr, ptr_type,
  183. "global_ptr"))) {
  184. aot_set_last_error("llvm build bit cast failed.");
  185. return false;
  186. }
  187. if (!is_set) {
  188. if (!(global =
  189. LLVMBuildLoad2(comp_ctx->builder, TO_LLVM_TYPE(global_type),
  190. global_ptr, "global"))) {
  191. aot_set_last_error("llvm build load failed.");
  192. return false;
  193. }
  194. /* All globals' data is 4-byte aligned */
  195. LLVMSetAlignment(global, 4);
  196. PUSH(global, global_type);
  197. }
  198. else {
  199. POP(global, global_type);
  200. if (is_aux_stack && comp_ctx->enable_aux_stack_check) {
  201. LLVMBasicBlockRef block_curr =
  202. LLVMGetInsertBlock(comp_ctx->builder);
  203. LLVMBasicBlockRef check_overflow_succ, check_underflow_succ;
  204. LLVMValueRef cmp;
  205. /* Add basic blocks */
  206. if (!(check_overflow_succ = LLVMAppendBasicBlockInContext(
  207. comp_ctx->context, func_ctx->func,
  208. "check_overflow_succ"))) {
  209. aot_set_last_error("llvm add basic block failed.");
  210. return false;
  211. }
  212. LLVMMoveBasicBlockAfter(check_overflow_succ, block_curr);
  213. if (!(check_underflow_succ = LLVMAppendBasicBlockInContext(
  214. comp_ctx->context, func_ctx->func,
  215. "check_underflow_succ"))) {
  216. aot_set_last_error("llvm add basic block failed.");
  217. return false;
  218. }
  219. LLVMMoveBasicBlockAfter(check_underflow_succ, check_overflow_succ);
  220. /* Check aux stack overflow */
  221. if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULE, global,
  222. func_ctx->aux_stack_bound, "cmp"))) {
  223. aot_set_last_error("llvm build icmp failed.");
  224. return false;
  225. }
  226. if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_AUX_STACK_OVERFLOW,
  227. true, cmp, check_overflow_succ)) {
  228. return false;
  229. }
  230. /* Check aux stack underflow */
  231. LLVMPositionBuilderAtEnd(comp_ctx->builder, check_overflow_succ);
  232. if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, global,
  233. func_ctx->aux_stack_bottom, "cmp"))) {
  234. aot_set_last_error("llvm build icmp failed.");
  235. return false;
  236. }
  237. if (!aot_emit_exception(comp_ctx, func_ctx,
  238. EXCE_AUX_STACK_UNDERFLOW, true, cmp,
  239. check_underflow_succ)) {
  240. return false;
  241. }
  242. LLVMPositionBuilderAtEnd(comp_ctx->builder, check_underflow_succ);
  243. }
  244. if (!(res = LLVMBuildStore(comp_ctx->builder, global, global_ptr))) {
  245. aot_set_last_error("llvm build store failed.");
  246. return false;
  247. }
  248. /* All globals' data is 4-byte aligned */
  249. LLVMSetAlignment(res, 4);
  250. }
  251. return true;
  252. fail:
  253. return false;
  254. }
  255. bool
  256. aot_compile_op_get_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  257. uint32 global_idx)
  258. {
  259. return compile_global(comp_ctx, func_ctx, global_idx, false, false);
  260. }
  261. bool
  262. aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  263. uint32 global_idx, bool is_aux_stack)
  264. {
  265. return compile_global(comp_ctx, func_ctx, global_idx, true, is_aux_stack);
  266. }