il2cpp-codegen-common.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #pragma once
  2. #include "il2cpp-config.h"
  3. #include <cassert>
  4. #include <cstdlib>
  5. #include <limits>
  6. #include <string>
  7. #include <math.h>
  8. #include <vector>
  9. #include "il2cpp-object-internals.h"
  10. #include "il2cpp-class-internals.h"
  11. #include "il2cpp-tabledefs.h"
  12. #include "vm/PlatformInvoke.h"
  13. #include "vm/StackTrace.h"
  14. #include "vm/PlatformInvoke.h"
  15. #include "vm/StackTrace.h"
  16. #include "utils/StringUtils.h"
  17. #include "utils/StringView.h"
  18. #include "utils/Exception.h"
  19. #include "utils/Output.h"
  20. #include "utils/Runtime.h"
  21. #ifdef _MSC_VER
  22. #define IL2CPP_DEBUG_BREAK() __debugbreak()
  23. #else
  24. #define IL2CPP_DEBUG_BREAK()
  25. #endif
  26. REAL_NORETURN IL2CPP_NO_INLINE void il2cpp_codegen_no_return();
  27. #if IL2CPP_COMPILER_MSVC
  28. #define DEFAULT_CALL STDCALL
  29. #else
  30. #define DEFAULT_CALL
  31. #endif
  32. #if defined(__ARMCC_VERSION)
  33. inline double bankers_round(double x)
  34. {
  35. return __builtin_round(x);
  36. }
  37. inline float bankers_roundf(float x)
  38. {
  39. return __builtin_roundf(x);
  40. }
  41. #else
  42. inline double bankers_round(double x)
  43. {
  44. double integerPart;
  45. if (x >= 0.0)
  46. {
  47. if (modf(x, &integerPart) == 0.5)
  48. return (int64_t)integerPart % 2 == 0 ? integerPart : integerPart + 1.0;
  49. return floor(x + 0.5);
  50. }
  51. else
  52. {
  53. if (modf(x, &integerPart) == -0.5)
  54. return (int64_t)integerPart % 2 == 0 ? integerPart : integerPart - 1.0;
  55. return ceil(x - 0.5);
  56. }
  57. }
  58. inline float bankers_roundf(float x)
  59. {
  60. double integerPart;
  61. if (x >= 0.0f)
  62. {
  63. if (modf(x, &integerPart) == 0.5)
  64. return (int64_t)integerPart % 2 == 0 ? (float)integerPart : (float)integerPart + 1.0f;
  65. return floorf(x + 0.5f);
  66. }
  67. else
  68. {
  69. if (modf(x, &integerPart) == -0.5)
  70. return (int64_t)integerPart % 2 == 0 ? (float)integerPart : (float)integerPart - 1.0f;
  71. return ceilf(x - 0.5f);
  72. }
  73. }
  74. #endif
  75. // returns true if overflow occurs
  76. inline bool il2cpp_codegen_check_mul_overflow_i64(int64_t a, int64_t b, int64_t imin, int64_t imax)
  77. {
  78. // TODO: use a better algorithm without division
  79. uint64_t ua = (uint64_t)llabs(a);
  80. uint64_t ub = (uint64_t)llabs(b);
  81. uint64_t c;
  82. if ((a > 0 && b > 0) || (a <= 0 && b <= 0))
  83. c = (uint64_t)llabs(imax);
  84. else
  85. c = (uint64_t)llabs(imin);
  86. return ua != 0 && ub > c / ua;
  87. }
  88. inline bool il2cpp_codegen_check_mul_oveflow_u64(uint64_t a, uint64_t b)
  89. {
  90. return b != 0 && (a * b) / b != a;
  91. }
  92. inline int32_t il2cpp_codegen_abs(uint32_t value)
  93. {
  94. return abs(static_cast<int32_t>(value));
  95. }
  96. inline int32_t il2cpp_codegen_abs(int32_t value)
  97. {
  98. return abs(value);
  99. }
  100. inline int64_t il2cpp_codegen_abs(uint64_t value)
  101. {
  102. return llabs(static_cast<int64_t>(value));
  103. }
  104. inline int64_t il2cpp_codegen_abs(int64_t value)
  105. {
  106. return llabs(value);
  107. }
  108. // Exception support macros
  109. #define IL2CPP_LEAVE(Offset, Target) \
  110. __leave_target = Offset; \
  111. goto Target;
  112. #define IL2CPP_END_FINALLY(Id) \
  113. goto __CLEANUP_ ## Id;
  114. #define IL2CPP_CLEANUP(Id) \
  115. __CLEANUP_ ## Id:
  116. #define IL2CPP_RETHROW_IF_UNHANDLED(ExcType) \
  117. if(__last_unhandled_exception) { \
  118. ExcType _tmp_exception_local = __last_unhandled_exception; \
  119. __last_unhandled_exception = 0; \
  120. il2cpp_codegen_raise_exception(_tmp_exception_local); \
  121. }
  122. #define IL2CPP_JUMP_TBL(Offset, Target) \
  123. if(__leave_target == Offset) { \
  124. __leave_target = 0; \
  125. goto Target; \
  126. }
  127. #define IL2CPP_END_CLEANUP(Offset, Target) \
  128. if(__leave_target == Offset) \
  129. goto Target;
  130. #define IL2CPP_RAISE_MANAGED_EXCEPTION(message, lastManagedFrame) \
  131. do {\
  132. il2cpp_codegen_raise_exception((Exception_t*)message, (MethodInfo*)lastManagedFrame);\
  133. il2cpp_codegen_no_return();\
  134. } while (0)
  135. template<typename T>
  136. inline void Il2CppCodeGenWriteBarrier(T** targetAddress, T* object)
  137. {
  138. // TODO
  139. }
  140. void il2cpp_codegen_memory_barrier();
  141. template<typename T>
  142. inline T VolatileRead(T* location)
  143. {
  144. T result = *location;
  145. il2cpp_codegen_memory_barrier();
  146. return result;
  147. }
  148. template<typename T>
  149. inline void VolatileWrite(T* location, T value)
  150. {
  151. il2cpp_codegen_memory_barrier();
  152. *location = value;
  153. }
  154. inline void il2cpp_codegen_write_to_stdout(const char* str)
  155. {
  156. il2cpp::utils::Output::WriteToStdout(str);
  157. }
  158. inline void il2cpp_codegen_write_to_stderr(const char* str)
  159. {
  160. il2cpp::utils::Output::WriteToStderr(str);
  161. }
  162. REAL_NORETURN void il2cpp_codegen_abort();
  163. inline bool il2cpp_codegen_check_add_overflow(int64_t left, int64_t right)
  164. {
  165. return (right >= 0 && left > kIl2CppInt64Max - right) ||
  166. (left < 0 && right < kIl2CppInt64Min - left);
  167. }
  168. inline bool il2cpp_codegen_check_sub_overflow(int64_t left, int64_t right)
  169. {
  170. return (right >= 0 && left < kIl2CppInt64Min + right) ||
  171. (right < 0 && left > kIl2CppInt64Max + right);
  172. }
  173. template<bool, class T, class U>
  174. struct pick_first;
  175. template<class T, class U>
  176. struct pick_first<true, T, U>
  177. {
  178. typedef T type;
  179. };
  180. template<class T, class U>
  181. struct pick_first<false, T, U>
  182. {
  183. typedef U type;
  184. };
  185. template<class T, class U>
  186. struct pick_bigger
  187. {
  188. typedef typename pick_first<(sizeof(T) >= sizeof(U)), T, U>::type type;
  189. };
  190. template<typename T, typename U>
  191. inline typename pick_bigger<T, U>::type il2cpp_codegen_multiply(T left, U right)
  192. {
  193. return left * right;
  194. }
  195. template<typename T, typename U>
  196. inline typename pick_bigger<T, U>::type il2cpp_codegen_add(T left, U right)
  197. {
  198. return left + right;
  199. }
  200. template<typename T, typename U>
  201. inline typename pick_bigger<T, U>::type il2cpp_codegen_subtract(T left, U right)
  202. {
  203. return left - right;
  204. }
  205. #ifdef _MSC_VER
  206. #define IL2CPP_DISABLE_OPTIMIZATIONS __pragma(optimize("", off))
  207. #define IL2CPP_ENABLE_OPTIMIZATIONS __pragma(optimize("", on))
  208. #else
  209. #define IL2CPP_DISABLE_OPTIMIZATIONS __attribute__ ((optnone))
  210. #define IL2CPP_ENABLE_OPTIMIZATIONS
  211. #endif