aot_stack_frame_comp.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * Copyright (C) 2024 Amazon Inc. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "aot_stack_frame_comp.h"
  6. #include "aot_emit_exception.h"
  7. #define ADD_IN_BOUNDS_GEP(variable, type, pointer, indices, num_indices) \
  8. do { \
  9. if (!(variable = \
  10. LLVMBuildInBoundsGEP2(comp_ctx->builder, type, pointer, \
  11. indices, num_indices, #variable))) { \
  12. aot_set_last_error("llvm build in bounds gep failed"); \
  13. return false; \
  14. } \
  15. } while (0)
  16. #define ADD_STORE(value, pointer) \
  17. do { \
  18. if (!LLVMBuildStore(comp_ctx->builder, value, pointer)) { \
  19. aot_set_last_error("llvm build store failed"); \
  20. return false; \
  21. } \
  22. } while (0)
  23. #define ADD_LOAD(value, type, pointer) \
  24. do { \
  25. if (!(value = \
  26. LLVMBuildLoad2(comp_ctx->builder, type, pointer, #value))) { \
  27. aot_set_last_error("llvm build load failed"); \
  28. return false; \
  29. } \
  30. } while (0)
  31. static bool
  32. aot_alloc_tiny_frame_for_aot_func(AOTCompContext *comp_ctx,
  33. AOTFuncContext *func_ctx,
  34. LLVMValueRef func_index)
  35. {
  36. LLVMValueRef wasm_stack_top_ptr = func_ctx->wasm_stack_top_ptr,
  37. wasm_stack_top_bound = func_ctx->wasm_stack_top_bound,
  38. wasm_stack_top, cmp;
  39. LLVMBasicBlockRef check_wasm_stack_succ;
  40. LLVMValueRef offset;
  41. ADD_LOAD(wasm_stack_top, INT8_PTR_TYPE, wasm_stack_top_ptr);
  42. if (comp_ctx->call_stack_features.bounds_checks) {
  43. if (!(check_wasm_stack_succ = LLVMAppendBasicBlockInContext(
  44. comp_ctx->context, func_ctx->func,
  45. "check_wasm_stack_succ"))) {
  46. aot_set_last_error("llvm add basic block failed.");
  47. return false;
  48. }
  49. LLVMMoveBasicBlockAfter(check_wasm_stack_succ,
  50. LLVMGetInsertBlock(comp_ctx->builder));
  51. if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, wasm_stack_top,
  52. wasm_stack_top_bound, "cmp"))) {
  53. aot_set_last_error("llvm build icmp failed");
  54. return false;
  55. }
  56. if (!(aot_emit_exception(comp_ctx, func_ctx,
  57. EXCE_OPERAND_STACK_OVERFLOW, true, cmp,
  58. check_wasm_stack_succ))) {
  59. return false;
  60. }
  61. }
  62. /* Save the func_idx on the top of the stack */
  63. if (comp_ctx->call_stack_features.func_idx) {
  64. ADD_STORE(func_index, wasm_stack_top);
  65. }
  66. /* increment the stack pointer */
  67. INT_CONST(offset, sizeof(AOTTinyFrame), I32_TYPE, true);
  68. ADD_IN_BOUNDS_GEP(wasm_stack_top, INT8_TYPE, wasm_stack_top, &offset, 1);
  69. ADD_STORE(wasm_stack_top, wasm_stack_top_ptr);
  70. return true;
  71. }
  72. static bool
  73. aot_free_tiny_frame_for_aot_func(AOTCompContext *comp_ctx,
  74. AOTFuncContext *func_ctx)
  75. {
  76. LLVMValueRef wasm_stack_top_ptr = func_ctx->wasm_stack_top_ptr,
  77. wasm_stack_top;
  78. LLVMValueRef offset;
  79. ADD_LOAD(wasm_stack_top, INT8_PTR_TYPE, wasm_stack_top_ptr);
  80. INT_CONST(offset, -sizeof(AOTTinyFrame),
  81. comp_ctx->pointer_size == 8 ? I64_TYPE : I32_TYPE, true);
  82. ADD_IN_BOUNDS_GEP(wasm_stack_top, INT8_TYPE, wasm_stack_top, &offset, 1);
  83. ADD_STORE(wasm_stack_top, wasm_stack_top_ptr);
  84. return true;
  85. }
  86. bool
  87. aot_tiny_frame_gen_commit_ip(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  88. LLVMValueRef ip_value)
  89. {
  90. LLVMValueRef wasm_stack_top_ptr = func_ctx->wasm_stack_top_ptr,
  91. wasm_stack_top;
  92. LLVMValueRef offset, ip_addr;
  93. bh_assert(ip_value);
  94. ADD_LOAD(wasm_stack_top, INT8_PTR_TYPE, wasm_stack_top_ptr);
  95. INT_CONST(offset, -4, comp_ctx->pointer_size == 8 ? I64_TYPE : I32_TYPE,
  96. true);
  97. ADD_IN_BOUNDS_GEP(ip_addr, INT8_TYPE, wasm_stack_top, &offset, 1);
  98. ADD_STORE(ip_value, ip_addr);
  99. return true;
  100. }
  101. bool
  102. aot_alloc_frame_per_function_frame_for_aot_func(AOTCompContext *comp_ctx,
  103. AOTFuncContext *func_ctx,
  104. LLVMValueRef func_index)
  105. {
  106. switch (comp_ctx->aux_stack_frame_type) {
  107. case AOT_STACK_FRAME_TYPE_TINY:
  108. return aot_alloc_tiny_frame_for_aot_func(comp_ctx, func_ctx,
  109. func_index);
  110. default:
  111. aot_set_last_error("unsupported mode");
  112. return false;
  113. }
  114. }
  115. bool
  116. aot_free_frame_per_function_frame_for_aot_func(AOTCompContext *comp_ctx,
  117. AOTFuncContext *func_ctx)
  118. {
  119. switch (comp_ctx->aux_stack_frame_type) {
  120. case AOT_STACK_FRAME_TYPE_TINY:
  121. return aot_free_tiny_frame_for_aot_func(comp_ctx, func_ctx);
  122. default:
  123. aot_set_last_error("unsupported mode");
  124. return false;
  125. }
  126. }