aot_emit_variable.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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(AOTFuncContext *func_ctx, uint32 local_idx)
  18. {
  19. AOTFunc *aot_func = func_ctx->aot_func;
  20. uint32 param_count = aot_func->func_type->param_count;
  21. return local_idx < param_count
  22. ? aot_func->func_type->types[local_idx]
  23. : aot_func->local_types[local_idx - param_count];
  24. }
  25. bool
  26. aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  27. uint32 local_idx)
  28. {
  29. char name[32];
  30. LLVMValueRef value;
  31. AOTValue *aot_value_top;
  32. uint8 local_type;
  33. CHECK_LOCAL(local_idx);
  34. local_type = get_local_type(func_ctx, local_idx);
  35. snprintf(name, sizeof(name), "%s%d%s", "local", local_idx, "#");
  36. if (!(value = LLVMBuildLoad2(comp_ctx->builder, TO_LLVM_TYPE(local_type),
  37. func_ctx->locals[local_idx], name))) {
  38. aot_set_last_error("llvm build load fail");
  39. return false;
  40. }
  41. PUSH(value, local_type);
  42. aot_value_top =
  43. func_ctx->block_stack.block_list_end->value_stack.value_list_end;
  44. aot_value_top->is_local = true;
  45. aot_value_top->local_idx = local_idx;
  46. return true;
  47. fail:
  48. return false;
  49. }
  50. bool
  51. aot_compile_op_set_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  52. uint32 local_idx)
  53. {
  54. LLVMValueRef value;
  55. CHECK_LOCAL(local_idx);
  56. POP(value, get_local_type(func_ctx, local_idx));
  57. if (!LLVMBuildStore(comp_ctx->builder, value,
  58. func_ctx->locals[local_idx])) {
  59. aot_set_last_error("llvm build store fail");
  60. return false;
  61. }
  62. aot_checked_addr_list_del(func_ctx, local_idx);
  63. return true;
  64. fail:
  65. return false;
  66. }
  67. bool
  68. aot_compile_op_tee_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  69. uint32 local_idx)
  70. {
  71. LLVMValueRef value;
  72. uint8 type;
  73. CHECK_LOCAL(local_idx);
  74. type = get_local_type(func_ctx, local_idx);
  75. POP(value, type);
  76. if (!LLVMBuildStore(comp_ctx->builder, value,
  77. func_ctx->locals[local_idx])) {
  78. aot_set_last_error("llvm build store fail");
  79. return false;
  80. }
  81. PUSH(value, type);
  82. aot_checked_addr_list_del(func_ctx, local_idx);
  83. return true;
  84. fail:
  85. return false;
  86. }
  87. static bool
  88. compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  89. uint32 global_idx, bool is_set, bool is_aux_stack)
  90. {
  91. AOTCompData *comp_data = comp_ctx->comp_data;
  92. uint32 import_global_count = comp_data->import_global_count;
  93. uint32 global_base_offset;
  94. uint32 global_offset;
  95. uint8 global_type;
  96. LLVMValueRef offset, global_ptr, global, res;
  97. LLVMTypeRef ptr_type = NULL;
  98. if (comp_ctx->is_jit_mode) {
  99. global_base_offset =
  100. offsetof(WASMModuleInstance, global_table_data.bytes)
  101. + sizeof(WASMMemoryInstance) * comp_ctx->comp_data->memory_count;
  102. }
  103. else {
  104. global_base_offset =
  105. offsetof(AOTModuleInstance, global_table_data.bytes)
  106. + sizeof(AOTMemoryInstance) * comp_ctx->comp_data->memory_count;
  107. }
  108. bh_assert(global_idx < import_global_count + comp_data->global_count);
  109. if (global_idx < import_global_count) {
  110. global_offset = global_base_offset
  111. + comp_data->import_globals[global_idx].data_offset;
  112. global_type = comp_data->import_globals[global_idx].type;
  113. }
  114. else {
  115. global_offset =
  116. global_base_offset
  117. + comp_data->globals[global_idx - import_global_count].data_offset;
  118. global_type = comp_data->globals[global_idx - import_global_count].type;
  119. }
  120. offset = I32_CONST(global_offset);
  121. if (!(global_ptr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
  122. func_ctx->aot_inst, &offset, 1,
  123. "global_ptr_tmp"))) {
  124. aot_set_last_error("llvm build in bounds gep failed.");
  125. return false;
  126. }
  127. switch (global_type) {
  128. case VALUE_TYPE_I32:
  129. case VALUE_TYPE_EXTERNREF:
  130. case VALUE_TYPE_FUNCREF:
  131. ptr_type = comp_ctx->basic_types.int32_ptr_type;
  132. break;
  133. case VALUE_TYPE_I64:
  134. ptr_type = comp_ctx->basic_types.int64_ptr_type;
  135. break;
  136. case VALUE_TYPE_F32:
  137. ptr_type = comp_ctx->basic_types.float32_ptr_type;
  138. break;
  139. case VALUE_TYPE_F64:
  140. ptr_type = comp_ctx->basic_types.float64_ptr_type;
  141. break;
  142. case VALUE_TYPE_V128:
  143. ptr_type = comp_ctx->basic_types.v128_ptr_type;
  144. break;
  145. default:
  146. bh_assert("unknown type");
  147. break;
  148. }
  149. if (!(global_ptr = LLVMBuildBitCast(comp_ctx->builder, global_ptr, ptr_type,
  150. "global_ptr"))) {
  151. aot_set_last_error("llvm build bit cast failed.");
  152. return false;
  153. }
  154. if (!is_set) {
  155. if (!(global =
  156. LLVMBuildLoad2(comp_ctx->builder, TO_LLVM_TYPE(global_type),
  157. global_ptr, "global"))) {
  158. aot_set_last_error("llvm build load failed.");
  159. return false;
  160. }
  161. /* All globals' data is 4-byte aligned */
  162. LLVMSetAlignment(global, 4);
  163. PUSH(global, global_type);
  164. }
  165. else {
  166. POP(global, global_type);
  167. if (is_aux_stack && comp_ctx->enable_aux_stack_check) {
  168. LLVMBasicBlockRef block_curr =
  169. LLVMGetInsertBlock(comp_ctx->builder);
  170. LLVMBasicBlockRef check_overflow_succ, check_underflow_succ;
  171. LLVMValueRef cmp;
  172. /* Add basic blocks */
  173. if (!(check_overflow_succ = LLVMAppendBasicBlockInContext(
  174. comp_ctx->context, func_ctx->func,
  175. "check_overflow_succ"))) {
  176. aot_set_last_error("llvm add basic block failed.");
  177. return false;
  178. }
  179. LLVMMoveBasicBlockAfter(check_overflow_succ, block_curr);
  180. if (!(check_underflow_succ = LLVMAppendBasicBlockInContext(
  181. comp_ctx->context, func_ctx->func,
  182. "check_underflow_succ"))) {
  183. aot_set_last_error("llvm add basic block failed.");
  184. return false;
  185. }
  186. LLVMMoveBasicBlockAfter(check_underflow_succ, check_overflow_succ);
  187. /* Check aux stack overflow */
  188. if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULE, global,
  189. func_ctx->aux_stack_bound, "cmp"))) {
  190. aot_set_last_error("llvm build icmp failed.");
  191. return false;
  192. }
  193. if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_AUX_STACK_OVERFLOW,
  194. true, cmp, check_overflow_succ)) {
  195. return false;
  196. }
  197. /* Check aux stack underflow */
  198. LLVMPositionBuilderAtEnd(comp_ctx->builder, check_overflow_succ);
  199. if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, global,
  200. func_ctx->aux_stack_bottom, "cmp"))) {
  201. aot_set_last_error("llvm build icmp failed.");
  202. return false;
  203. }
  204. if (!aot_emit_exception(comp_ctx, func_ctx,
  205. EXCE_AUX_STACK_UNDERFLOW, true, cmp,
  206. check_underflow_succ)) {
  207. return false;
  208. }
  209. LLVMPositionBuilderAtEnd(comp_ctx->builder, check_underflow_succ);
  210. }
  211. if (!(res = LLVMBuildStore(comp_ctx->builder, global, global_ptr))) {
  212. aot_set_last_error("llvm build store failed.");
  213. return false;
  214. }
  215. /* All globals' data is 4-byte aligned */
  216. LLVMSetAlignment(res, 4);
  217. }
  218. return true;
  219. fail:
  220. return false;
  221. }
  222. bool
  223. aot_compile_op_get_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  224. uint32 global_idx)
  225. {
  226. return compile_global(comp_ctx, func_ctx, global_idx, false, false);
  227. }
  228. bool
  229. aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  230. uint32 global_idx, bool is_aux_stack)
  231. {
  232. return compile_global(comp_ctx, func_ctx, global_idx, true, is_aux_stack);
  233. }