il2cpp-codegen-common-big.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. #pragma once
  2. #include "il2cpp-config.h"
  3. #include <cmath>
  4. #include <cstdlib>
  5. #include "il2cpp-object-internals.h"
  6. #include "il2cpp-class-internals.h"
  7. #include "il2cpp-tabledefs.h"
  8. #include "vm-utils/Debugger.h"
  9. #include "utils/ExceptionSupportStack.h"
  10. #include "utils/Output.h"
  11. REAL_NORETURN IL2CPP_NO_INLINE void il2cpp_codegen_no_return();
  12. #if IL2CPP_COMPILER_MSVC
  13. #define DEFAULT_CALL STDCALL
  14. #else
  15. #define DEFAULT_CALL
  16. #endif
  17. #if defined(__ARMCC_VERSION)
  18. inline double bankers_round(double x)
  19. {
  20. return __builtin_round(x);
  21. }
  22. inline float bankers_roundf(float x)
  23. {
  24. return __builtin_roundf(x);
  25. }
  26. #else
  27. inline double bankers_round(double x)
  28. {
  29. double integerPart;
  30. if (x >= 0.0)
  31. {
  32. if (modf(x, &integerPart) == 0.5)
  33. return (int64_t)integerPart % 2 == 0 ? integerPart : integerPart + 1.0;
  34. return floor(x + 0.5);
  35. }
  36. else
  37. {
  38. if (modf(x, &integerPart) == -0.5)
  39. return (int64_t)integerPart % 2 == 0 ? integerPart : integerPart - 1.0;
  40. return ceil(x - 0.5);
  41. }
  42. }
  43. inline float bankers_roundf(float x)
  44. {
  45. double integerPart;
  46. if (x >= 0.0f)
  47. {
  48. if (modf(x, &integerPart) == 0.5)
  49. return (int64_t)integerPart % 2 == 0 ? (float)integerPart : (float)integerPart + 1.0f;
  50. return floorf(x + 0.5f);
  51. }
  52. else
  53. {
  54. if (modf(x, &integerPart) == -0.5)
  55. return (int64_t)integerPart % 2 == 0 ? (float)integerPart : (float)integerPart - 1.0f;
  56. return ceilf(x - 0.5f);
  57. }
  58. }
  59. #endif
  60. // returns true if overflow occurs
  61. inline bool il2cpp_codegen_check_mul_overflow_i64(int64_t a, int64_t b, int64_t imin, int64_t imax)
  62. {
  63. // TODO: use a better algorithm without division
  64. uint64_t ua = (uint64_t)llabs(a);
  65. uint64_t ub = (uint64_t)llabs(b);
  66. uint64_t c;
  67. if ((a > 0 && b > 0) || (a <= 0 && b <= 0))
  68. c = (uint64_t)llabs(imax);
  69. else
  70. c = (uint64_t)llabs(imin);
  71. return ua != 0 && ub > c / ua;
  72. }
  73. inline bool il2cpp_codegen_check_mul_oveflow_u64(uint64_t a, uint64_t b)
  74. {
  75. return b != 0 && (a * b) / b != a;
  76. }
  77. inline int32_t il2cpp_codegen_abs(uint32_t value)
  78. {
  79. return abs(static_cast<int32_t>(value));
  80. }
  81. inline int32_t il2cpp_codegen_abs(int32_t value)
  82. {
  83. return abs(value);
  84. }
  85. inline int64_t il2cpp_codegen_abs(uint64_t value)
  86. {
  87. return llabs(static_cast<int64_t>(value));
  88. }
  89. inline int64_t il2cpp_codegen_abs(int64_t value)
  90. {
  91. return llabs(value);
  92. }
  93. // Exception support macros
  94. #define IL2CPP_LEAVE(Offset, Target) \
  95. __leave_targets.push(Offset); \
  96. goto Target;
  97. #define IL2CPP_END_FINALLY(Id) \
  98. goto __CLEANUP_ ## Id;
  99. #define IL2CPP_CLEANUP(Id) \
  100. __CLEANUP_ ## Id:
  101. #define IL2CPP_PUSH_ACTIVE_EXCEPTION(Exception) \
  102. __active_exceptions.push(Exception)
  103. #define IL2CPP_POP_ACTIVE_EXCEPTION() \
  104. __active_exceptions.pop()
  105. #define IL2CPP_GET_ACTIVE_EXCEPTION(ExcType) \
  106. (ExcType)__active_exceptions.top()
  107. #define IL2CPP_RETHROW_IF_UNHANDLED(ExcType) \
  108. if(__last_unhandled_exception) { \
  109. ExcType _tmp_exception_local = __last_unhandled_exception; \
  110. __last_unhandled_exception = 0; \
  111. il2cpp_codegen_raise_exception(_tmp_exception_local); \
  112. }
  113. #define IL2CPP_JUMP_TBL(Offset, Target) \
  114. if(!__leave_targets.empty() && __leave_targets.top() == Offset) { \
  115. __leave_targets.pop(); \
  116. goto Target; \
  117. }
  118. #define IL2CPP_END_CLEANUP(Offset, Target) \
  119. if(!__leave_targets.empty() && __leave_targets.top() == Offset) \
  120. goto Target;
  121. #define IL2CPP_RAISE_MANAGED_EXCEPTION(message, lastManagedFrame) \
  122. do {\
  123. il2cpp_codegen_raise_exception((Exception_t*)message, (RuntimeMethod*)lastManagedFrame);\
  124. il2cpp_codegen_no_return();\
  125. } while (0)
  126. #if IL2CPP_ENABLE_WRITE_BARRIERS
  127. void Il2CppCodeGenWriteBarrier(void** targetAddress, void* object);
  128. #else
  129. inline void Il2CppCodeGenWriteBarrier(void** targetAddress, void* object) {}
  130. #endif
  131. void il2cpp_codegen_memory_barrier();
  132. template<typename T>
  133. inline T VolatileRead(T* location)
  134. {
  135. T result = *location;
  136. il2cpp_codegen_memory_barrier();
  137. return result;
  138. }
  139. template<typename T, typename U>
  140. inline void VolatileWrite(T** location, U* value)
  141. {
  142. il2cpp_codegen_memory_barrier();
  143. *location = value;
  144. Il2CppCodeGenWriteBarrier((void**)location, value);
  145. }
  146. template<typename T, typename U>
  147. inline void VolatileWrite(T* location, U value)
  148. {
  149. il2cpp_codegen_memory_barrier();
  150. *location = value;
  151. }
  152. inline void il2cpp_codegen_write_to_stdout(const char* str)
  153. {
  154. il2cpp::utils::Output::WriteToStdout(str);
  155. }
  156. #if IL2CPP_TARGET_LUMIN
  157. #include <stdarg.h>
  158. #include <stdio.h>
  159. inline void il2cpp_codegen_write_to_stdout_args(const char* str, ...)
  160. {
  161. va_list args, local;
  162. char* buffer = nullptr;
  163. va_start(args, str);
  164. va_copy(local, args);
  165. int size = vsnprintf(nullptr, 0, str, local);
  166. if (size < 0)
  167. {
  168. va_end(local);
  169. va_end(args);
  170. return;
  171. }
  172. va_end(local);
  173. va_copy(local, args);
  174. buffer = new char[size + 1];
  175. vsnprintf(buffer, size + 1, str, local);
  176. il2cpp::utils::Output::WriteToStdout(buffer);
  177. if (buffer != nullptr)
  178. delete[] buffer;
  179. va_end(local);
  180. va_end(args);
  181. }
  182. #endif
  183. inline void il2cpp_codegen_write_to_stderr(const char* str)
  184. {
  185. il2cpp::utils::Output::WriteToStderr(str);
  186. }
  187. #if IL2CPP_TARGET_LUMIN
  188. inline void il2cpp_codegen_write_to_stderr_args(const char* str, ...)
  189. {
  190. va_list args, local;
  191. char* buffer = nullptr;
  192. va_start(args, str);
  193. va_copy(local, args);
  194. int size = vsnprintf(nullptr, 0, str, local);
  195. if (size < 0)
  196. {
  197. va_end(local);
  198. va_end(args);
  199. return;
  200. }
  201. va_end(local);
  202. va_copy(local, args);
  203. buffer = new char[size + 1];
  204. vsnprintf(buffer, size + 1, str, local);
  205. il2cpp::utils::Output::WriteToStderr(buffer);
  206. if (buffer != nullptr)
  207. delete[] buffer;
  208. va_end(local);
  209. va_end(args);
  210. }
  211. #endif
  212. REAL_NORETURN void il2cpp_codegen_abort();
  213. inline bool il2cpp_codegen_check_add_overflow(int64_t left, int64_t right)
  214. {
  215. return (right >= 0 && left > kIl2CppInt64Max - right) ||
  216. (left < 0 && right < kIl2CppInt64Min - left);
  217. }
  218. inline bool il2cpp_codegen_check_sub_overflow(int64_t left, int64_t right)
  219. {
  220. return (right >= 0 && left < kIl2CppInt64Min + right) ||
  221. (right < 0 && left > kIl2CppInt64Max + right);
  222. }
  223. inline void il2cpp_codegen_memcpy(void* dest, const void* src, size_t count)
  224. {
  225. memcpy(dest, src, count);
  226. }
  227. inline void il2cpp_codegen_memset(void* ptr, int value, size_t num)
  228. {
  229. memset(ptr, value, num);
  230. }
  231. inline void il2cpp_codegen_register_debugger_data(const Il2CppDebuggerMetadataRegistration *data)
  232. {
  233. #if IL2CPP_MONO_DEBUGGER
  234. il2cpp::utils::Debugger::RegisterMetadata(data);
  235. #endif
  236. }
  237. inline void il2cpp_codegen_check_sequence_point(Il2CppSequencePointExecutionContext* executionContext, Il2CppSequencePoint* seqPoint)
  238. {
  239. #if IL2CPP_MONO_DEBUGGER
  240. il2cpp::utils::Debugger::CheckSequencePoint(executionContext, seqPoint);
  241. #endif
  242. }
  243. inline void il2cpp_codegen_check_sequence_point_entry(Il2CppSequencePointExecutionContext* executionContext, Il2CppSequencePoint* seqPoint)
  244. {
  245. #if IL2CPP_MONO_DEBUGGER
  246. il2cpp::utils::Debugger::CheckSequencePointEntry(executionContext, seqPoint);
  247. #endif
  248. }
  249. inline void il2cpp_codegen_check_sequence_point_exit(Il2CppSequencePointExecutionContext* executionContext, Il2CppSequencePoint* seqPoint)
  250. {
  251. #if IL2CPP_MONO_DEBUGGER
  252. il2cpp::utils::Debugger::CheckSequencePointExit(executionContext, seqPoint);
  253. #endif
  254. }
  255. inline void il2cpp_codegen_check_pause_point()
  256. {
  257. #if IL2CPP_MONO_DEBUGGER
  258. il2cpp::utils::Debugger::CheckPausePoint();
  259. #endif
  260. }
  261. class MethodExitSequencePointChecker
  262. {
  263. private:
  264. Il2CppSequencePoint* m_seqPoint;
  265. Il2CppSequencePointExecutionContext* m_seqPointStorage;
  266. public:
  267. MethodExitSequencePointChecker(Il2CppSequencePointExecutionContext* seqPointStorage, Il2CppSequencePoint* seqPoint) :
  268. m_seqPointStorage(seqPointStorage), m_seqPoint(seqPoint)
  269. {
  270. }
  271. ~MethodExitSequencePointChecker()
  272. {
  273. #if IL2CPP_MONO_DEBUGGER
  274. il2cpp_codegen_check_sequence_point_exit(m_seqPointStorage, m_seqPoint);
  275. #endif
  276. }
  277. };
  278. #ifdef _MSC_VER
  279. #define IL2CPP_DISABLE_OPTIMIZATIONS __pragma(optimize("", off))
  280. #define IL2CPP_ENABLE_OPTIMIZATIONS __pragma(optimize("", on))
  281. #elif IL2CPP_TARGET_LINUX
  282. #define IL2CPP_DISABLE_OPTIMIZATIONS
  283. #define IL2CPP_ENABLE_OPTIMIZATIONS
  284. #else
  285. #define IL2CPP_DISABLE_OPTIMIZATIONS __attribute__ ((optnone))
  286. #define IL2CPP_ENABLE_OPTIMIZATIONS
  287. #endif
  288. // Array Unsafe
  289. #define IL2CPP_ARRAY_UNSAFE_LOAD(TArray, TIndex) \
  290. (TArray)->GetAtUnchecked(static_cast<il2cpp_array_size_t>(TIndex))
  291. inline bool il2cpp_codegen_object_reference_equals(const RuntimeObject *obj1, const RuntimeObject *obj2)
  292. {
  293. return obj1 == obj2;
  294. }
  295. inline bool il2cpp_codegen_platform_is_osx_or_ios()
  296. {
  297. return IL2CPP_TARGET_OSX != 0 || IL2CPP_TARGET_IOS != 0;
  298. }
  299. inline bool il2cpp_codegen_platform_is_freebsd()
  300. {
  301. // we don't currently support FreeBSD
  302. return false;
  303. }
  304. inline bool il2cpp_codegen_platform_disable_libc_pinvoke()
  305. {
  306. return IL2CPP_PLATFORM_DISABLE_LIBC_PINVOKE;
  307. }