il2cpp-codegen-il2cpp.h 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581
  1. #pragma once
  2. #include "il2cpp-codegen-common.h"
  3. #include "il2cpp-pinvoke-support.h"
  4. #include "il2cpp-object-internals.h"
  5. #include "il2cpp-class-internals.h"
  6. #include "il2cpp-tabledefs.h"
  7. #include "icalls/mscorlib/System.Runtime.InteropServices/Marshal.h"
  8. #include "vm-utils/icalls/mscorlib/System.Threading/Interlocked.h"
  9. #include "vm-utils/VmThreadUtils.h"
  10. #include "vm-utils/Debugger.h"
  11. #include "vm-utils/Finally.h"
  12. #include "vm/ClassInlines.h"
  13. #include "vm/ScopedThreadAttacher.h"
  14. #include "vm/Il2CppHStringReference.h"
  15. #include "vm/String.h"
  16. #include "utils/ExceptionSupportStack.h"
  17. #include "utils/Output.h"
  18. #include <cstdlib>
  19. #include <cstddef>
  20. REAL_NORETURN IL2CPP_NO_INLINE void il2cpp_codegen_no_return();
  21. NORETURN void il2cpp_codegen_raise_exception(Exception_t *ex, MethodInfo* lastManagedFrame);
  22. NORETURN void il2cpp_codegen_rethrow_exception(Exception_t *ex);
  23. NORETURN void il2cpp_codegen_raise_exception(il2cpp_hresult_t hresult, bool defaultToCOMException);
  24. // Exception support macros
  25. #define IL2CPP_PUSH_ACTIVE_EXCEPTION(Exception) \
  26. __active_exceptions.push(Exception)
  27. #define IL2CPP_POP_ACTIVE_EXCEPTION(ExcType) \
  28. (ExcType)__active_exceptions.pop()
  29. #define IL2CPP_GET_ACTIVE_EXCEPTION(ExcType) \
  30. (ExcType)__active_exceptions.top()
  31. #define IL2CPP_RAISE_NULL_REFERENCE_EXCEPTION() \
  32. do {\
  33. il2cpp_codegen_raise_null_reference_exception();\
  34. il2cpp_codegen_no_return();\
  35. } while (0)
  36. #define IL2CPP_RAISE_MANAGED_EXCEPTION(ex, lastManagedFrame) \
  37. do {\
  38. il2cpp_codegen_raise_exception((Exception_t*)ex, (RuntimeMethod*)lastManagedFrame);\
  39. il2cpp_codegen_no_return();\
  40. } while (0)
  41. #define IL2CPP_RETHROW_MANAGED_EXCEPTION(ex) \
  42. do {\
  43. il2cpp_codegen_rethrow_exception((Exception_t*)ex);\
  44. il2cpp_codegen_no_return();\
  45. } while (0)
  46. #if IL2CPP_ENABLE_PROFILER
  47. void il2cpp_codegen_profiler_method_enter(const RuntimeMethod* method);
  48. void il2cpp_codegen_profiler_method_exit(const RuntimeMethod* method);
  49. #endif
  50. struct ProfilerMethodSentry
  51. {
  52. ProfilerMethodSentry(const RuntimeMethod* method)
  53. #if IL2CPP_ENABLE_PROFILER
  54. : m_method(method)
  55. #endif
  56. {
  57. #if IL2CPP_ENABLE_PROFILER
  58. il2cpp_codegen_profiler_method_enter(m_method);
  59. #endif
  60. }
  61. ~ProfilerMethodSentry()
  62. {
  63. #if IL2CPP_ENABLE_PROFILER
  64. il2cpp_codegen_profiler_method_exit(m_method);
  65. #endif
  66. }
  67. private:
  68. const RuntimeMethod* m_method;
  69. };
  70. void il2cpp_codegen_stacktrace_push_frame(Il2CppStackFrameInfo& frame);
  71. void il2cpp_codegen_stacktrace_pop_frame();
  72. uint32_t il2cpp_codegen_sizeof(RuntimeClass* klass);
  73. struct StackTraceSentry
  74. {
  75. StackTraceSentry(const RuntimeMethod* method) : m_method(method)
  76. {
  77. Il2CppStackFrameInfo frame_info = { 0 };
  78. frame_info.method = method;
  79. il2cpp_codegen_stacktrace_push_frame(frame_info);
  80. }
  81. ~StackTraceSentry()
  82. {
  83. il2cpp_codegen_stacktrace_pop_frame();
  84. }
  85. private:
  86. const RuntimeMethod* m_method;
  87. };
  88. #define IL2CPP_FAKE_BOX_SENTRY (MonitorData*)UINTPTR_MAX
  89. template<typename T>
  90. struct Il2CppFakeBox : RuntimeObject
  91. {
  92. T m_Value;
  93. Il2CppFakeBox(RuntimeClass* boxedType, T* value)
  94. {
  95. klass = boxedType;
  96. monitor = IL2CPP_FAKE_BOX_SENTRY;
  97. m_Value = *value;
  98. }
  99. };
  100. struct Il2CppFakeBoxBuffer : RuntimeObject
  101. {
  102. char m_Value[];
  103. Il2CppFakeBoxBuffer(RuntimeClass* boxedType, void* value)
  104. {
  105. klass = boxedType;
  106. monitor = IL2CPP_FAKE_BOX_SENTRY;
  107. memcpy(&m_Value, value, il2cpp_codegen_sizeof(boxedType));
  108. }
  109. static uint32_t SizeNeededFor(RuntimeClass* boxedType)
  110. {
  111. return sizeof(Il2CppFakeBoxBuffer) + il2cpp_codegen_sizeof(boxedType);
  112. }
  113. };
  114. inline bool il2cpp_codegen_is_fake_boxed_object(RuntimeObject* object)
  115. {
  116. return object->monitor == IL2CPP_FAKE_BOX_SENTRY;
  117. }
  118. // TODO: This file should contain all the functions and type declarations needed for the generated code.
  119. // Hopefully, we stop including everything in the generated code and know exactly what dependencies we have.
  120. // Note that all parameter and return types should match the generated types not the runtime types.
  121. void il2cpp_codegen_register(const Il2CppCodeRegistration* const codeRegistration, const Il2CppMetadataRegistration* const metadataRegistration, const Il2CppCodeGenOptions* const codeGenOptions);
  122. typedef void (*MetadataInitializerCleanupFunc)();
  123. void il2cpp_codegen_register_metadata_initialized_cleanup(MetadataInitializerCleanupFunc cleanup);
  124. // type registration
  125. void* il2cpp_codegen_get_thread_static_data(RuntimeClass* klass);
  126. String_t* il2cpp_codegen_string_new_wrapper(const char* str);
  127. String_t* il2cpp_codegen_string_new_utf16(const il2cpp::utils::StringView<Il2CppChar>& str);
  128. Type_t* il2cpp_codegen_type_get_object(const RuntimeType* type);
  129. void il2cpp_codegen_raise_execution_engine_exception_if_method_is_not_found(const RuntimeMethod* method);
  130. void il2cpp_codegen_raise_execution_engine_exception(const RuntimeMethod* method);
  131. void il2cpp_codegen_raise_execution_engine_exception_missing_virtual(const RuntimeMethod* method);
  132. NORETURN void il2cpp_codegen_raise_out_of_memory_exception();
  133. NORETURN void il2cpp_codegen_raise_null_reference_exception();
  134. NORETURN void il2cpp_codegen_raise_divide_by_zero_exception();
  135. NORETURN void il2cpp_codegen_raise_index_out_of_range_exception();
  136. Exception_t* il2cpp_codegen_get_argument_exception(const char* param, const char* msg);
  137. Exception_t* il2cpp_codegen_get_argument_null_exception(const char* param);
  138. Exception_t* il2cpp_codegen_get_overflow_exception();
  139. Exception_t* il2cpp_codegen_get_not_supported_exception(const char* msg);
  140. Exception_t* il2cpp_codegen_get_array_type_mismatch_exception();
  141. Exception_t* il2cpp_codegen_get_invalid_cast_exception(const char* msg);
  142. Exception_t* il2cpp_codegen_get_invalid_operation_exception(const char* msg);
  143. Exception_t* il2cpp_codegen_get_marshal_directive_exception(const char* msg);
  144. Exception_t* il2cpp_codegen_get_marshal_directive_exception(const char* msg, const RuntimeType* type);
  145. // format string will require first instance as a field and second instance as a type or this will break
  146. Exception_t* il2cpp_codegen_get_marshal_directive_exception(const char* msg, const RuntimeField* field, const RuntimeType* type);
  147. Exception_t* il2cpp_codegen_get_missing_method_exception(const char* msg);
  148. Exception_t* il2cpp_codegen_get_maximum_nested_generics_exception();
  149. Exception_t* il2cpp_codegen_get_engine_execution_exception(const char* msg);
  150. Exception_t* il2cpp_codegen_get_index_out_of_range_exception();
  151. Exception_t* il2cpp_codegen_get_exception(il2cpp_hresult_t hresult, bool defaultToCOMException);
  152. inline RuntimeClass* il2cpp_codegen_object_class(RuntimeObject* obj)
  153. {
  154. return obj->klass;
  155. }
  156. // OpCode.IsInst
  157. RuntimeObject* IsInst(RuntimeObject *obj, RuntimeClass* targetType);
  158. inline RuntimeObject* IsInstSealed(RuntimeObject *obj, RuntimeClass* targetType)
  159. {
  160. #if IL2CPP_DEBUG
  161. IL2CPP_ASSERT((targetType->flags & TYPE_ATTRIBUTE_SEALED) != 0);
  162. IL2CPP_ASSERT((targetType->flags & TYPE_ATTRIBUTE_INTERFACE) == 0);
  163. #endif
  164. if (!obj)
  165. return NULL;
  166. // optimized version to compare sealed classes
  167. return (obj->klass == targetType ? obj : NULL);
  168. }
  169. inline RuntimeObject* IsInstClass(RuntimeObject *obj, RuntimeClass* targetType)
  170. {
  171. #if IL2CPP_DEBUG
  172. IL2CPP_ASSERT((targetType->flags & TYPE_ATTRIBUTE_INTERFACE) == 0);
  173. #endif
  174. if (!obj)
  175. return NULL;
  176. // optimized version to compare classes
  177. return il2cpp::vm::ClassInlines::HasParentUnsafe(obj->klass, targetType) ? obj : NULL;
  178. }
  179. // OpCode.Castclass
  180. NORETURN void RaiseInvalidCastException(RuntimeObject* obj, RuntimeClass* targetType);
  181. inline RuntimeObject* Castclass(RuntimeObject *obj, RuntimeClass* targetType)
  182. {
  183. if (!obj)
  184. return NULL;
  185. RuntimeObject* result = IsInst(obj, targetType);
  186. if (result)
  187. return result;
  188. RaiseInvalidCastException(obj, targetType);
  189. return NULL;
  190. }
  191. inline RuntimeObject* CastclassSealed(RuntimeObject *obj, RuntimeClass* targetType)
  192. {
  193. if (!obj)
  194. return NULL;
  195. RuntimeObject* result = IsInstSealed(obj, targetType);
  196. if (result)
  197. return result;
  198. RaiseInvalidCastException(obj, targetType);
  199. return NULL;
  200. }
  201. inline RuntimeObject* CastclassClass(RuntimeObject *obj, RuntimeClass* targetType)
  202. {
  203. if (!obj)
  204. return NULL;
  205. RuntimeObject* result = IsInstClass(obj, targetType);
  206. if (result)
  207. return result;
  208. RaiseInvalidCastException(obj, targetType);
  209. return NULL;
  210. }
  211. inline void NullCheck(void* this_ptr)
  212. {
  213. if (this_ptr != NULL)
  214. return;
  215. il2cpp_codegen_raise_null_reference_exception();
  216. }
  217. // OpCode.Box
  218. RuntimeObject* Box(RuntimeClass* type, void* data);
  219. // OpCode.UnBox
  220. void* Unbox_internal(Il2CppObject* obj);
  221. inline void* UnBox(RuntimeObject* obj)
  222. {
  223. NullCheck(obj);
  224. return Unbox_internal(obj);
  225. }
  226. inline void* UnBox(RuntimeObject* obj, RuntimeClass* expectedBoxedClass)
  227. {
  228. NullCheck(obj);
  229. if (obj->klass->element_class == expectedBoxedClass->element_class)
  230. return Unbox_internal(obj);
  231. RaiseInvalidCastException(obj, expectedBoxedClass);
  232. return NULL;
  233. }
  234. void UnBoxNullable_internal(RuntimeObject* obj, RuntimeClass* nullableClass, void* storage);
  235. inline void UnBoxNullable(RuntimeObject* obj, RuntimeClass* nullableClass, void* storage)
  236. {
  237. // We only need to do type checks if obj is not null
  238. // Unboxing null nullable is perfectly valid and returns an instance that has no value
  239. if (obj != NULL)
  240. {
  241. if (obj->klass != nullableClass->element_class)
  242. RaiseInvalidCastException(obj, nullableClass->element_class);
  243. }
  244. UnBoxNullable_internal(obj, nullableClass, storage);
  245. }
  246. // Implements OpCode.UnBox_Any at runtime, obj may be any type, even a reference type
  247. // unboxStorage must always be a buffer large enough to store the unboxed result
  248. // It always returns a pointer to a data buffer - either a pointer to a value type or a pointer to a reference type
  249. void* UnBox_Any(RuntimeObject* obj, RuntimeClass* expectedBoxedClass, void* unboxStorage);
  250. // objBuffer is a pointer to the obj - either a pointer to a value type or a pointer to a reference type
  251. bool il2cpp_codegen_would_box_to_non_null(RuntimeClass* klass, void* objBuffer);
  252. int32_t il2cpp_codgen_class_get_instance_size(RuntimeClass* klass);
  253. inline uint32_t il2cpp_codegen_sizeof(RuntimeClass* klass)
  254. {
  255. IL2CPP_ASSERT(klass->size_inited);
  256. return klass->stack_slot_size;
  257. }
  258. inline bool il2cpp_codegen_method_is_virtual(RuntimeMethod* method)
  259. {
  260. return method->slot != kInvalidIl2CppMethodSlot;
  261. }
  262. inline bool il2cpp_codegen_object_is_of_sealed_type(RuntimeObject* obj)
  263. {
  264. IL2CPP_ASSERT(obj);
  265. return (obj->klass->flags & TYPE_ATTRIBUTE_SEALED) != 0;
  266. }
  267. bool il2cpp_codegen_method_is_generic_instance_method(RuntimeMethod* method);
  268. RuntimeClass* il2cpp_codegen_method_get_declaring_type(const RuntimeMethod* method);
  269. bool il2cpp_codegen_method_is_interface_method(RuntimeMethod* method);
  270. inline uint16_t il2cpp_codegen_method_get_slot(const RuntimeMethod* method)
  271. {
  272. return method->slot;
  273. }
  274. IL2CPP_FORCE_INLINE const VirtualInvokeData& il2cpp_codegen_get_virtual_invoke_data(Il2CppMethodSlot slot, const RuntimeObject* obj)
  275. {
  276. Assert(slot != kInvalidIl2CppMethodSlot && "il2cpp_codegen_get_virtual_invoke_data got called on a non-virtual method");
  277. return obj->klass->vtable[slot];
  278. }
  279. IL2CPP_FORCE_INLINE const VirtualInvokeData& il2cpp_codegen_get_interface_invoke_data(Il2CppMethodSlot slot, RuntimeObject* obj, const RuntimeClass* declaringInterface)
  280. {
  281. Assert(slot != kInvalidIl2CppMethodSlot && "il2cpp_codegen_get_interface_invoke_data got called on a non-virtual method");
  282. return il2cpp::vm::ClassInlines::GetInterfaceInvokeDataFromVTable(obj, declaringInterface, slot);
  283. }
  284. const RuntimeMethod* il2cpp_codegen_get_generic_virtual_method_internal(const RuntimeMethod* methodDefinition, const RuntimeMethod* inflatedMethod);
  285. IL2CPP_FORCE_INLINE const RuntimeMethod* il2cpp_codegen_get_generic_virtual_method(const RuntimeMethod* method, const RuntimeObject* obj)
  286. {
  287. uint16_t slot = method->slot;
  288. const RuntimeMethod* methodDefinition = obj->klass->vtable[slot].method;
  289. return il2cpp_codegen_get_generic_virtual_method_internal(methodDefinition, method);
  290. }
  291. IL2CPP_FORCE_INLINE void il2cpp_codegen_get_generic_virtual_invoke_data(const RuntimeMethod* method, const RuntimeObject* obj, VirtualInvokeData* invokeData)
  292. {
  293. invokeData->method = il2cpp_codegen_get_generic_virtual_method(method, obj);
  294. invokeData->methodPtr = invokeData->method->virtualMethodPointer;
  295. IL2CPP_ASSERT(invokeData->method);
  296. }
  297. IL2CPP_FORCE_INLINE const RuntimeMethod* il2cpp_codegen_get_generic_interface_method(const RuntimeMethod* method, RuntimeObject* obj)
  298. {
  299. const RuntimeMethod* methodDefinition = il2cpp::vm::ClassInlines::GetInterfaceInvokeDataFromVTable(obj, method->klass, method->slot).method;
  300. return il2cpp_codegen_get_generic_virtual_method_internal(methodDefinition, method);
  301. }
  302. IL2CPP_FORCE_INLINE void il2cpp_codegen_get_generic_interface_invoke_data(const RuntimeMethod* method, RuntimeObject* obj, VirtualInvokeData* invokeData)
  303. {
  304. invokeData->method = il2cpp_codegen_get_generic_interface_method(method, obj);
  305. invokeData->methodPtr = invokeData->method->virtualMethodPointer;
  306. IL2CPP_ASSERT(invokeData->method);
  307. }
  308. inline RuntimeClass* InitializedTypeInfo(RuntimeClass* klass)
  309. {
  310. return il2cpp::vm::ClassInlines::InitFromCodegen(klass);
  311. }
  312. RuntimeClass* il2cpp_codegen_class_from_type_internal(const RuntimeType* type);
  313. inline RuntimeClass* il2cpp_codegen_class_from_type(const RuntimeType *type)
  314. {
  315. return InitializedTypeInfo(il2cpp_codegen_class_from_type_internal(type));
  316. }
  317. inline const RuntimeType* il2cpp_codegen_type_from_class(RuntimeClass *klass)
  318. {
  319. return &klass->byval_arg;
  320. }
  321. inline void* InterlockedExchangeImplRef(void** location, void* value)
  322. {
  323. return il2cpp::icalls::mscorlib::System::Threading::Interlocked::ExchangePointer(location, value);
  324. }
  325. template<typename T>
  326. inline T InterlockedCompareExchangeImpl(T* location, T value, T comparand)
  327. {
  328. return (T)il2cpp::icalls::mscorlib::System::Threading::Interlocked::CompareExchange_T((void**)location, value, comparand);
  329. }
  330. template<typename T>
  331. inline T InterlockedExchangeImpl(T* location, T value)
  332. {
  333. return (T)InterlockedExchangeImplRef((void**)location, value);
  334. }
  335. void il2cpp_codegen_memory_barrier();
  336. inline void GetGenericValueImpl(RuntimeArray* thisPtr, int32_t pos, void* value)
  337. {
  338. // GetGenericValueImpl is only called from the class libs internally and T is never a field
  339. IL2CPP_ASSERT_STACK_PTR(value);
  340. memcpy(value, il2cpp_array_addr_with_size(thisPtr, thisPtr->klass->element_size, pos), thisPtr->klass->element_size);
  341. }
  342. void SetGenericValueImpl(RuntimeArray* thisPtr, int32_t pos, void* value);
  343. RuntimeArray* SZArrayNew(RuntimeClass* arrayType, uint32_t length);
  344. RuntimeArray* GenArrayNew(RuntimeClass* arrayType, il2cpp_array_size_t* dimensions);
  345. // Performance optimization as detailed here: http://blogs.msdn.com/b/clrcodegeneration/archive/2009/08/13/array-bounds-check-elimination-in-the-clr.aspx
  346. // Since array size is a signed int32_t, a single unsigned check can be performed to determine if index is less than array size.
  347. // Negative indices will map to a unsigned number greater than or equal to 2^31 which is larger than allowed for a valid array.
  348. #define IL2CPP_ARRAY_BOUNDS_CHECK(index, length) \
  349. do { \
  350. if (((uint32_t)(index)) >= ((uint32_t)length)) il2cpp_codegen_raise_index_out_of_range_exception(); \
  351. } while (0)
  352. bool il2cpp_codegen_class_is_assignable_from(RuntimeClass *klass, RuntimeClass *oklass);
  353. RuntimeObject* il2cpp_codegen_object_new(RuntimeClass *klass);
  354. Il2CppMethodPointer il2cpp_codegen_resolve_icall(const char* name);
  355. Il2CppMethodPointer il2cpp_codegen_resolve(const PInvokeArguments& pinvokeArgs);
  356. template<typename FunctionPointerType, size_t dynamicLibraryLength, size_t entryPointLength>
  357. inline FunctionPointerType il2cpp_codegen_resolve_pinvoke(const Il2CppNativeChar(&nativeDynamicLibrary)[dynamicLibraryLength], const char(&entryPoint)[entryPointLength],
  358. Il2CppCallConvention callingConvention, Il2CppCharSet charSet, int parameterSize, bool isNoMangle)
  359. {
  360. const PInvokeArguments pinvokeArgs =
  361. {
  362. il2cpp::utils::StringView<Il2CppNativeChar>(nativeDynamicLibrary),
  363. il2cpp::utils::StringView<char>(entryPoint),
  364. callingConvention,
  365. charSet,
  366. parameterSize,
  367. isNoMangle
  368. };
  369. return reinterpret_cast<FunctionPointerType>(il2cpp_codegen_resolve(pinvokeArgs));
  370. }
  371. void* il2cpp_codegen_marshal_allocate(size_t size);
  372. template<typename T>
  373. inline T* il2cpp_codegen_marshal_allocate_array(size_t length)
  374. {
  375. return static_cast<T*>(il2cpp_codegen_marshal_allocate((il2cpp_array_size_t)(sizeof(T) * length)));
  376. }
  377. template<typename T>
  378. inline T* il2cpp_codegen_marshal_allocate()
  379. {
  380. return static_cast<T*>(il2cpp_codegen_marshal_allocate(sizeof(T)));
  381. }
  382. char* il2cpp_codegen_marshal_string(String_t* string);
  383. void il2cpp_codegen_marshal_string_fixed(String_t* string, char* buffer, int numberOfCharacters);
  384. Il2CppChar* il2cpp_codegen_marshal_wstring(String_t* string);
  385. void il2cpp_codegen_marshal_wstring_fixed(String_t* string, Il2CppChar* buffer, int numberOfCharacters);
  386. Il2CppChar* il2cpp_codegen_marshal_bstring(String_t* string);
  387. String_t* il2cpp_codegen_marshal_string_result(const char* value);
  388. String_t* il2cpp_codegen_marshal_wstring_result(const Il2CppChar* value);
  389. String_t* il2cpp_codegen_marshal_bstring_result(const Il2CppChar* value);
  390. void il2cpp_codegen_marshal_free_bstring(Il2CppChar* value);
  391. char* il2cpp_codegen_marshal_empty_string_builder(StringBuilder_t* stringBuilder);
  392. char* il2cpp_codegen_marshal_string_builder(StringBuilder_t* stringBuilder);
  393. Il2CppChar* il2cpp_codegen_marshal_empty_wstring_builder(StringBuilder_t* stringBuilder);
  394. Il2CppChar* il2cpp_codegen_marshal_wstring_builder(StringBuilder_t* stringBuilder);
  395. void il2cpp_codegen_marshal_string_builder_result(StringBuilder_t* stringBuilder, char* buffer);
  396. void il2cpp_codegen_marshal_wstring_builder_result(StringBuilder_t* stringBuilder, Il2CppChar* buffer);
  397. Il2CppHString il2cpp_codegen_create_hstring(String_t* str);
  398. String_t* il2cpp_codegen_marshal_hstring_result(Il2CppHString hstring);
  399. void il2cpp_codegen_marshal_free_hstring(Il2CppHString hstring);
  400. void il2cpp_codegen_marshal_type_to_native(Type_t* type, Il2CppWindowsRuntimeTypeName& nativeType);
  401. const Il2CppType* il2cpp_codegen_marshal_type_from_native_internal(Il2CppWindowsRuntimeTypeName& nativeType);
  402. inline Type_t* il2cpp_codegen_marshal_type_from_native(Il2CppWindowsRuntimeTypeName& nativeType)
  403. {
  404. const Il2CppType* type = il2cpp_codegen_marshal_type_from_native_internal(nativeType);
  405. if (type == NULL)
  406. return NULL;
  407. return il2cpp_codegen_type_get_object(type);
  408. }
  409. void il2cpp_codegen_delete_native_type(Il2CppWindowsRuntimeTypeName& nativeType);
  410. void il2cpp_codegen_marshal_free(void* ptr);
  411. Il2CppMethodPointer il2cpp_codegen_marshal_delegate(MulticastDelegate_t* d);
  412. Il2CppDelegate* il2cpp_codegen_marshal_function_ptr_to_delegate_internal(void* functionPtr, Il2CppClass* delegateType);
  413. bool il2cpp_codegen_is_marshalled_delegate(MulticastDelegate_t* d);
  414. #if !IL2CPP_TINY
  415. inline void* il2cpp_codegen_get_reverse_pinvoke_function_ptr(const MulticastDelegate_t* d)
  416. {
  417. return ((Il2CppDelegate*)d)->delegate_trampoline;
  418. }
  419. #endif
  420. template<typename T>
  421. inline T* il2cpp_codegen_marshal_function_ptr_to_delegate(Il2CppMethodPointer functionPtr, RuntimeClass* delegateType)
  422. {
  423. return (T*)il2cpp_codegen_marshal_function_ptr_to_delegate_internal(reinterpret_cast<void*>(functionPtr), delegateType);
  424. }
  425. void il2cpp_codegen_marshal_store_last_error();
  426. template<typename R, typename S>
  427. inline R il2cpp_codegen_cast_struct(S* s)
  428. {
  429. static_assert(sizeof(S) == sizeof(R), "Types with different sizes passed to il2cpp_codegen_cast_struct");
  430. R r;
  431. il2cpp_codegen_memcpy(&r, s, sizeof(R));
  432. return r;
  433. }
  434. #if _DEBUG
  435. void il2cpp_codegen_marshal_allocate_push_allocation_frame();
  436. void il2cpp_codegen_marshal_allocate_pop_allocation_frame();
  437. bool il2cpp_codegen_marshal_allocate_has_unfreed_allocations();
  438. void il2cpp_codegen_marshal_allocate_clear_all_tracked_allocations();
  439. struct ScopedMarshallingAllocationFrame
  440. {
  441. ScopedMarshallingAllocationFrame()
  442. {
  443. il2cpp_codegen_marshal_allocate_push_allocation_frame();
  444. }
  445. ~ScopedMarshallingAllocationFrame()
  446. {
  447. il2cpp_codegen_marshal_allocate_pop_allocation_frame();
  448. }
  449. };
  450. struct ScopedMarshallingAllocationCheck
  451. {
  452. ~ScopedMarshallingAllocationCheck()
  453. {
  454. if (il2cpp_codegen_marshal_allocate_has_unfreed_allocations())
  455. il2cpp_codegen_raise_exception(il2cpp_codegen_get_invalid_operation_exception("Error in marshaling allocation. Some memory has been leaked."));
  456. }
  457. private:
  458. ScopedMarshallingAllocationFrame m_AllocationFrame;
  459. };
  460. struct ScopedMarshalingAllocationClearer
  461. {
  462. ~ScopedMarshalingAllocationClearer()
  463. {
  464. il2cpp_codegen_marshal_allocate_clear_all_tracked_allocations();
  465. }
  466. private:
  467. ScopedMarshallingAllocationFrame m_AllocationFrame;
  468. };
  469. #endif
  470. inline void DivideByZeroCheck(int64_t denominator)
  471. {
  472. if (denominator != 0)
  473. return;
  474. il2cpp_codegen_raise_divide_by_zero_exception();
  475. }
  476. bool MethodIsStatic(const RuntimeMethod* method);
  477. bool MethodHasParameters(const RuntimeMethod* method);
  478. void il2cpp_codegen_runtime_class_init(RuntimeClass* klass);
  479. inline void il2cpp_codegen_runtime_class_init_inline(RuntimeClass* klass)
  480. {
  481. if (!klass->cctor_finished_or_no_cctor)
  482. il2cpp_codegen_runtime_class_init(klass);
  483. }
  484. // generic sharing
  485. inline RuntimeClass* il2cpp_rgctx_data(const Il2CppRGCTXData* rgctxVar, int32_t index)
  486. {
  487. return InitializedTypeInfo(rgctxVar[index].klass);
  488. }
  489. inline RuntimeClass* il2cpp_rgctx_data_no_init(const Il2CppRGCTXData* rgctxVar, int32_t index)
  490. {
  491. return rgctxVar[index].klass;
  492. }
  493. inline const Il2CppType* il2cpp_rgctx_type(const Il2CppRGCTXData* rgctxVar, int32_t index)
  494. {
  495. return rgctxVar[index].type;
  496. }
  497. inline const MethodInfo* il2cpp_rgctx_method(const Il2CppRGCTXData* rgctxVar, int32_t index)
  498. {
  499. return rgctxVar[index].method;
  500. }
  501. inline FieldInfo* il2cpp_rgctx_field(RuntimeClass* klass, int32_t index)
  502. {
  503. return klass->fields + index;
  504. }
  505. inline bool il2cpp_rgctx_is_initialized(const RuntimeMethod* method)
  506. {
  507. IL2CPP_ASSERT(method->is_inflated);
  508. return method->rgctx_data != NULL;
  509. }
  510. inline void il2cpp_rgctx_method_init(const RuntimeMethod* method)
  511. {
  512. il2cpp::vm::ClassInlines::InitRgcxFromCodegen(method);
  513. }
  514. inline uintptr_t il2cpp_array_calc_byte_offset(RuntimeArray* runtimeArray, il2cpp_array_size_t index)
  515. {
  516. return runtimeArray->klass->element_size * index;
  517. }
  518. inline void ArrayElementTypeCheck(RuntimeArray* array, void* value)
  519. {
  520. #if !IL2CPP_TINY
  521. if (value != NULL && IsInst((RuntimeObject*)value, array->klass->element_class) == NULL)
  522. il2cpp_codegen_raise_exception(il2cpp_codegen_get_array_type_mismatch_exception());
  523. #endif
  524. }
  525. inline const RuntimeMethod* GetVirtualMethodInfo(RuntimeObject* pThis, Il2CppMethodSlot slot)
  526. {
  527. if (!pThis)
  528. il2cpp_codegen_raise_null_reference_exception();
  529. return pThis->klass->vtable[slot].method;
  530. }
  531. inline const RuntimeMethod* GetInterfaceMethodInfo(RuntimeObject* pThis, Il2CppMethodSlot slot, RuntimeClass* declaringInterface)
  532. {
  533. if (!pThis)
  534. il2cpp_codegen_raise_null_reference_exception();
  535. return il2cpp::vm::ClassInlines::GetInterfaceInvokeDataFromVTable(pThis, declaringInterface, slot).method;
  536. }
  537. void il2cpp_codegen_initialize_runtime_metadata(uintptr_t* metadataPointer);
  538. void* il2cpp_codegen_initialize_runtime_metadata_inline(uintptr_t* metadataPointer);
  539. inline bool il2cpp_codegen_type_is_value_type(const RuntimeType* type)
  540. {
  541. return type->valuetype;
  542. }
  543. inline bool il2cpp_codegen_class_is_value_type(RuntimeClass* type)
  544. {
  545. return il2cpp_codegen_type_is_value_type(&type->byval_arg);
  546. }
  547. bool il2cpp_codegen_class_is_nullable(RuntimeClass* type);
  548. inline bool il2cpp_codegen_type_implements_virtual_method(RuntimeClass* type, const RuntimeMethod* method)
  549. {
  550. IL2CPP_ASSERT(il2cpp_codegen_class_is_value_type(type));
  551. return method->klass == type;
  552. }
  553. MethodBase_t* il2cpp_codegen_get_method_object_internal(const RuntimeMethod* method, RuntimeClass* refclass);
  554. const RuntimeClass* il2cpp_codegen_get_generic_type_definition(const RuntimeClass* klass);
  555. const RuntimeMethod* il2cpp_codegen_get_generic_method_definition(const RuntimeMethod* method);
  556. const RuntimeMethod* il2cpp_codegen_get_generic_instance_method_from_method_definition(RuntimeClass* genericInstanceClass, const RuntimeMethod* methodDefinition);
  557. inline MethodBase_t* il2cpp_codegen_get_method_object(const RuntimeMethod* method)
  558. {
  559. if (method->is_inflated)
  560. method = il2cpp_codegen_get_generic_method_definition(method);
  561. return il2cpp_codegen_get_method_object_internal(method, method->klass);
  562. }
  563. Type_t* il2cpp_codegen_get_type(String_t* typeName, const RuntimeMethod* getTypeMethod, const RuntimeMethod* callingMethod);
  564. Type_t* il2cpp_codegen_get_type(String_t* typeName, bool throwOnError, const RuntimeMethod* getTypeMethod, const RuntimeMethod* callingMethod);
  565. Type_t* il2cpp_codegen_get_type(String_t* typeName, bool throwOnError, bool ignoreCase, const RuntimeMethod* getTypeMethod, const RuntimeMethod* callingMethod);
  566. Assembly_t* il2cpp_codegen_get_executing_assembly(const RuntimeMethod* method);
  567. // Atomic
  568. void* il2cpp_codegen_atomic_compare_exchange_pointer(void** dest, void* exchange, void* comparand);
  569. // COM
  570. void il2cpp_codegen_com_marshal_variant(RuntimeObject* obj, Il2CppVariant* variant);
  571. RuntimeObject* il2cpp_codegen_com_marshal_variant_result(const Il2CppVariant* variant);
  572. void il2cpp_codegen_com_destroy_variant(Il2CppVariant* variant);
  573. Il2CppSafeArray* il2cpp_codegen_com_marshal_safe_array(Il2CppChar type, RuntimeArray* managedArray);
  574. RuntimeArray* il2cpp_codegen_com_marshal_safe_array_result(Il2CppChar variantType, RuntimeClass* type, Il2CppSafeArray* safeArray);
  575. Il2CppSafeArray* il2cpp_codegen_com_marshal_safe_array_bstring(RuntimeArray* managedArray);
  576. RuntimeArray* il2cpp_codegen_com_marshal_safe_array_bstring_result(RuntimeClass* type, Il2CppSafeArray* safeArray);
  577. void il2cpp_codegen_com_destroy_safe_array(Il2CppSafeArray* safeArray);
  578. void il2cpp_codegen_com_create_instance(const Il2CppGuid& clsid, Il2CppIUnknown** identity);
  579. void il2cpp_codegen_com_register_rcw(Il2CppComObject* rcw);
  580. RuntimeObject* il2cpp_codegen_com_get_or_create_rcw_from_iunknown_internal(Il2CppIUnknown* unknown, RuntimeClass* fallbackClass);
  581. template<typename T>
  582. inline T* il2cpp_codegen_com_get_or_create_rcw_from_iunknown(Il2CppIUnknown* unknown, RuntimeClass* fallbackClass)
  583. {
  584. return static_cast<T*>(il2cpp_codegen_com_get_or_create_rcw_from_iunknown_internal(unknown, fallbackClass));
  585. }
  586. RuntimeObject* il2cpp_codegen_com_get_or_create_rcw_from_iinspectable_internal(Il2CppIInspectable* unknown, RuntimeClass* fallbackClass);
  587. template<typename T>
  588. inline T* il2cpp_codegen_com_get_or_create_rcw_from_iinspectable(Il2CppIInspectable* unknown, RuntimeClass* fallbackClass)
  589. {
  590. return static_cast<T*>(il2cpp_codegen_com_get_or_create_rcw_from_iinspectable_internal(unknown, fallbackClass));
  591. }
  592. RuntimeObject* il2cpp_codegen_com_get_or_create_rcw_for_sealed_class_internal(Il2CppIUnknown* unknown, RuntimeClass* objectClass);
  593. template<typename T>
  594. inline T* il2cpp_codegen_com_get_or_create_rcw_for_sealed_class(Il2CppIUnknown* unknown, RuntimeClass* objectClass)
  595. {
  596. return static_cast<T*>(il2cpp_codegen_com_get_or_create_rcw_for_sealed_class_internal(unknown, objectClass));
  597. }
  598. Il2CppIUnknown* il2cpp_codegen_com_query_interface_internal(Il2CppComObject* rcw, const Il2CppGuid& guid);
  599. Il2CppIUnknown* il2cpp_codegen_com_query_interface_no_throw_internal(Il2CppComObject* rcw, const Il2CppGuid& guid);
  600. void il2cpp_codegen_com_cache_queried_interface(Il2CppComObject* rcw, const Il2CppGuid& guid, Il2CppIUnknown* queriedInterface);
  601. template<typename T>
  602. inline T* il2cpp_codegen_com_query_interface(Il2CppComObject* rcw)
  603. {
  604. return static_cast<T*>(il2cpp_codegen_com_query_interface_internal(rcw, T::IID));
  605. }
  606. template<typename T>
  607. inline T* il2cpp_codegen_com_query_interface_no_throw(Il2CppComObject* rcw)
  608. {
  609. return static_cast<T*>(il2cpp_codegen_com_query_interface_no_throw_internal(rcw, T::IID));
  610. }
  611. void il2cpp_codegen_il2cpp_com_object_cleanup(Il2CppComObject* rcw);
  612. Il2CppIUnknown* il2cpp_codegen_com_get_or_create_ccw_internal(RuntimeObject* obj, const Il2CppGuid& iid);
  613. template<typename InterfaceType>
  614. inline InterfaceType* il2cpp_codegen_com_get_or_create_ccw(RuntimeObject* obj)
  615. {
  616. return static_cast<InterfaceType*>(il2cpp_codegen_com_get_or_create_ccw_internal(obj, InterfaceType::IID));
  617. }
  618. inline intptr_t il2cpp_codegen_com_get_iunknown_for_object(RuntimeObject* obj)
  619. {
  620. return reinterpret_cast<intptr_t>(il2cpp_codegen_com_get_or_create_ccw_internal(obj, Il2CppIUnknown::IID));
  621. }
  622. Il2CppObject* il2cpp_codegen_com_unpack_ccw(Il2CppIUnknown* obj);
  623. inline void il2cpp_codegen_com_raise_exception_if_failed(il2cpp_hresult_t hr, bool defaultToCOMException)
  624. {
  625. // Copied from il2cpp::vm::Exception::RaiseIfFailed to keep inlined
  626. if (IL2CPP_HR_FAILED(hr))
  627. il2cpp_codegen_raise_exception(hr, defaultToCOMException);
  628. }
  629. inline RuntimeException* il2cpp_codegen_com_get_exception(il2cpp_hresult_t hr, bool defaultToCOMException)
  630. {
  631. return (RuntimeException*)il2cpp_codegen_get_exception(hr, defaultToCOMException);
  632. }
  633. il2cpp_hresult_t il2cpp_codegen_com_handle_invalid_iproperty_conversion(const char* fromType, const char* toType);
  634. il2cpp_hresult_t il2cpp_codegen_com_handle_invalid_iproperty_conversion(RuntimeObject* value, const char* fromType, const char* toType);
  635. il2cpp_hresult_t il2cpp_codegen_com_handle_invalid_ipropertyarray_conversion(const char* fromArrayType, const char* fromElementType, const char* toElementType, il2cpp_array_size_t index);
  636. il2cpp_hresult_t il2cpp_codegen_com_handle_invalid_ipropertyarray_conversion(RuntimeObject* value, const char* fromArrayType, const char* fromElementType, const char* toElementType, il2cpp_array_size_t index);
  637. void il2cpp_codegen_store_exception_info(RuntimeException* ex, String_t* exceptionString);
  638. Il2CppIActivationFactory* il2cpp_codegen_windows_runtime_get_activation_factory(const il2cpp::utils::StringView<Il2CppNativeChar>& runtimeClassName);
  639. // delegate
  640. Il2CppAsyncResult* il2cpp_codegen_delegate_begin_invoke(RuntimeDelegate* delegate, void** params, RuntimeDelegate* asyncCallback, RuntimeObject* state);
  641. RuntimeObject* il2cpp_codegen_delegate_end_invoke(Il2CppAsyncResult* asyncResult, void **out_args);
  642. void il2cpp_codegen_set_closed_delegate_invoke(RuntimeObject* delegate, RuntimeObject* target, void* methodPtr);
  643. inline const Il2CppGenericInst* il2cpp_codegen_get_generic_class_inst(RuntimeClass* genericClass)
  644. {
  645. IL2CPP_ASSERT(genericClass->generic_class);
  646. return genericClass->generic_class->context.class_inst;
  647. }
  648. RuntimeClass* il2cpp_codegen_get_generic_argument(RuntimeClass* klass, uint32_t argNum);
  649. // Inflate a generic class from an existing generic instance
  650. RuntimeClass* il2cpp_codegen_inflate_generic_class(RuntimeClass* genericClassDefinition, const Il2CppGenericInst* genericInst);
  651. // Inflate a generic class from types
  652. RuntimeClass* il2cpp_codegen_inflate_generic_class(RuntimeClass* genericClassDefinition, const RuntimeType*, /*const RuntimeType*, const RuntimeType* */ ...);
  653. inline void* il2cpp_codegen_static_fields_for(RuntimeClass* klass)
  654. {
  655. return klass->static_fields;
  656. }
  657. void il2cpp_codegen_assert_field_size(RuntimeField* field, size_t size);
  658. void* il2cpp_codegen_get_instance_field_data_pointer(void* instance, RuntimeField* field);
  659. inline void* il2cpp_codegen_get_instance_field_data_pointer(intptr_t instance, RuntimeField* field)
  660. {
  661. return il2cpp_codegen_get_instance_field_data_pointer((void*)instance, field);
  662. }
  663. inline void* il2cpp_codegen_get_instance_field_data_pointer(uintptr_t instance, RuntimeField* field)
  664. {
  665. return il2cpp_codegen_get_instance_field_data_pointer((void*)instance, field);
  666. }
  667. void il2cpp_codegen_write_instance_field_data(void* instance, RuntimeField* field, void* data, uint32_t size);
  668. inline void il2cpp_codegen_write_instance_field_data(intptr_t instance, RuntimeField* field, void* data, uint32_t size)
  669. {
  670. il2cpp_codegen_write_instance_field_data((void*)instance, field, data, size);
  671. }
  672. inline void il2cpp_codegen_write_instance_field_data(uintptr_t instance, RuntimeField* field, void* data, uint32_t size)
  673. {
  674. il2cpp_codegen_write_instance_field_data((void*)instance, field, data, size);
  675. }
  676. void* il2cpp_codegen_get_static_field_data_pointer(RuntimeField* field);
  677. void il2cpp_codegen_write_static_field_data(RuntimeField* field, void* data, uint32_t size);
  678. void* il2cpp_codegen_get_thread_static_field_data_pointer(RuntimeField* field);
  679. void il2cpp_codegen_write_thread_static_field_data(RuntimeField* field, void* data, uint32_t size);
  680. template<typename T>
  681. void il2cpp_codegen_write_instance_field_data(void* instance, RuntimeField* field, no_infer<T> data)
  682. {
  683. il2cpp_codegen_assert_field_size(field, sizeof(T));
  684. void* fieldPointer = il2cpp_codegen_get_instance_field_data_pointer(instance, field);
  685. *(T*)fieldPointer = data;
  686. Il2CppCodeGenWriteBarrierForType(field->type, (void**)fieldPointer, NULL);
  687. }
  688. template<typename T>
  689. inline void il2cpp_codegen_write_instance_field_data(intptr_t instance, RuntimeField* field, no_infer<T> data)
  690. {
  691. il2cpp_codegen_write_instance_field_data<T>((void*)instance, field, data);
  692. }
  693. template<typename T>
  694. inline void il2cpp_codegen_write_instance_field_data(uintptr_t instance, RuntimeField* field, no_infer<T> data)
  695. {
  696. il2cpp_codegen_write_instance_field_data<T>((void*)instance, field, data);
  697. }
  698. template<typename T>
  699. void il2cpp_codegen_write_static_field_data(RuntimeField* field, no_infer<T> data)
  700. {
  701. il2cpp_codegen_assert_field_size(field, sizeof(T));
  702. void* fieldPointer = il2cpp_codegen_get_static_field_data_pointer(field);
  703. *(T*)fieldPointer = data;
  704. Il2CppCodeGenWriteBarrierForType(field->type, (void**)fieldPointer, NULL);
  705. }
  706. template<typename T>
  707. void il2cpp_codegen_write_thread_static_field_data(RuntimeField* field, no_infer<T> data)
  708. {
  709. il2cpp_codegen_assert_field_size(field, sizeof(T));
  710. void* fieldPointer = il2cpp_codegen_get_thread_static_field_data_pointer(field);
  711. *(T*)fieldPointer = data;
  712. Il2CppCodeGenWriteBarrierForType(field->type, (void**)fieldPointer, NULL);
  713. }
  714. inline Il2CppMethodPointer il2cpp_codegen_get_method_pointer(const RuntimeMethod* method)
  715. {
  716. return method->virtualMethodPointer;
  717. }
  718. inline Il2CppMethodPointer il2cpp_codegen_get_direct_method_pointer(const RuntimeMethod* method)
  719. {
  720. return method->methodPointer;
  721. }
  722. inline const RuntimeType* il2cpp_codegen_method_return_type(const RuntimeMethod* method)
  723. {
  724. return method->return_type;
  725. }
  726. inline int il2cpp_codegen_method_parameter_count(const RuntimeMethod* method)
  727. {
  728. return method->parameters_count;
  729. }
  730. inline const RuntimeType* il2cpp_codegen_method_parameter_type(const RuntimeMethod* method, int parameterIndex)
  731. {
  732. IL2CPP_ASSERT(parameterIndex >= 0 && parameterIndex < method->parameters_count);
  733. return method->parameters[parameterIndex];
  734. }
  735. inline bool il2cpp_codegen_is_import_or_windows_runtime(const RuntimeObject *object)
  736. {
  737. return object->klass->is_import_or_windows_runtime;
  738. }
  739. inline intptr_t il2cpp_codegen_get_com_interface_for_object(Il2CppObject* object, Type_t* type)
  740. {
  741. return il2cpp::icalls::mscorlib::System::Runtime::InteropServices::Marshal::GetCCW(object, reinterpret_cast<Il2CppReflectionType*>(type));
  742. }
  743. NORETURN void il2cpp_codegen_raise_profile_exception(const RuntimeMethod* method);
  744. void il2cpp_codegen_array_unsafe_mov(RuntimeClass * destClass, void* dest, RuntimeClass * srcClass, void* src);
  745. NORETURN void il2cpp_codegen_array_unsafe_mov_type_exception(const RuntimeType * destType, const RuntimeType* srcType);
  746. template<typename T>
  747. T il2cpp_codegen_read_to_aligned_value(void* src)
  748. {
  749. T value;
  750. memcpy(&value, src, sizeof(T));
  751. return value;
  752. }
  753. template<typename TDest>
  754. inline void il2cpp_codegen_array_unsafe_mov_primitive(const RuntimeType * destType, TDest* dest, const RuntimeType* srcType, void* src)
  755. {
  756. switch (srcType->type)
  757. {
  758. case IL2CPP_TYPE_BOOLEAN:
  759. *dest = (TDest)il2cpp_codegen_read_to_aligned_value<bool>(src);
  760. break;
  761. case IL2CPP_TYPE_I1:
  762. *dest = (TDest)il2cpp_codegen_read_to_aligned_value<int8_t>(src);
  763. break;
  764. case IL2CPP_TYPE_U1:
  765. *dest = (TDest)il2cpp_codegen_read_to_aligned_value<uint8_t>(src);
  766. break;
  767. case IL2CPP_TYPE_I2:
  768. *dest = (TDest)il2cpp_codegen_read_to_aligned_value<int16_t>(src);
  769. break;
  770. case IL2CPP_TYPE_CHAR:
  771. case IL2CPP_TYPE_U2:
  772. *dest = (TDest)il2cpp_codegen_read_to_aligned_value<uint16_t>(src);
  773. break;
  774. case IL2CPP_TYPE_I4:
  775. *dest = (TDest)il2cpp_codegen_read_to_aligned_value<int32_t>(src);
  776. break;
  777. case IL2CPP_TYPE_U4:
  778. *dest = (TDest)il2cpp_codegen_read_to_aligned_value<uint32_t>(src);
  779. break;
  780. case IL2CPP_TYPE_I8:
  781. *dest = (TDest)il2cpp_codegen_read_to_aligned_value<int64_t>(src);
  782. break;
  783. case IL2CPP_TYPE_U8:
  784. *dest = (TDest)il2cpp_codegen_read_to_aligned_value<uint64_t>(src);
  785. break;
  786. case IL2CPP_TYPE_I:
  787. *dest = (TDest)il2cpp_codegen_read_to_aligned_value<intptr_t>(src);
  788. break;
  789. case IL2CPP_TYPE_U:
  790. *dest = (TDest)il2cpp_codegen_read_to_aligned_value<uintptr_t>(src);
  791. break;
  792. default:
  793. il2cpp_codegen_array_unsafe_mov_type_exception(destType, srcType);
  794. }
  795. }
  796. template<typename TDest, bool checkOverflow, bool inputUnsigned>
  797. TDest il2cpp_codegen_conv(const RuntimeClass* srcType, void* src, const RuntimeMethod* method)
  798. {
  799. switch (srcType->castClass->byval_arg.type)
  800. {
  801. case IL2CPP_TYPE_BOOLEAN:
  802. case IL2CPP_TYPE_I1:
  803. return il2cpp_codegen_conv<TDest, int8_t, int32_t, checkOverflow, inputUnsigned>(il2cpp_codegen_read_to_aligned_value<int8_t>(src), method);
  804. case IL2CPP_TYPE_U1:
  805. return il2cpp_codegen_conv<TDest, uint8_t, int32_t, checkOverflow, inputUnsigned>(il2cpp_codegen_read_to_aligned_value<uint8_t>(src), method);
  806. case IL2CPP_TYPE_I2:
  807. return il2cpp_codegen_conv<TDest, int16_t, int32_t, checkOverflow, inputUnsigned>(il2cpp_codegen_read_to_aligned_value<int16_t>(src), method);
  808. case IL2CPP_TYPE_CHAR:
  809. case IL2CPP_TYPE_U2:
  810. return il2cpp_codegen_conv<TDest, uint16_t, int32_t, checkOverflow, inputUnsigned>(il2cpp_codegen_read_to_aligned_value<uint16_t>(src), method);
  811. case IL2CPP_TYPE_I4:
  812. return il2cpp_codegen_conv<TDest, int32_t, int32_t, checkOverflow, inputUnsigned>(il2cpp_codegen_read_to_aligned_value<int32_t>(src), method);
  813. case IL2CPP_TYPE_U4:
  814. return il2cpp_codegen_conv<TDest, uint32_t, int32_t, checkOverflow, inputUnsigned>(il2cpp_codegen_read_to_aligned_value<uint32_t>(src), method);
  815. case IL2CPP_TYPE_I8:
  816. return il2cpp_codegen_conv<TDest, int64_t, int64_t, checkOverflow, inputUnsigned>(il2cpp_codegen_read_to_aligned_value<int64_t>(src), method);
  817. case IL2CPP_TYPE_U8:
  818. return il2cpp_codegen_conv<TDest, uint64_t, int64_t, checkOverflow, inputUnsigned>(il2cpp_codegen_read_to_aligned_value<uint64_t>(src), method);
  819. case IL2CPP_TYPE_I:
  820. case IL2CPP_TYPE_PTR:
  821. case IL2CPP_TYPE_OBJECT:
  822. return il2cpp_codegen_conv<TDest, intptr_t, intptr_t, checkOverflow, inputUnsigned>(il2cpp_codegen_read_to_aligned_value<intptr_t>(src), method);
  823. case IL2CPP_TYPE_U:
  824. return il2cpp_codegen_conv<TDest, uintptr_t, intptr_t, checkOverflow, inputUnsigned>(il2cpp_codegen_read_to_aligned_value<uintptr_t>(src), method);
  825. case IL2CPP_TYPE_R4:
  826. return il2cpp_codegen_conv<TDest, float, float, checkOverflow, inputUnsigned>(il2cpp_codegen_read_to_aligned_value<float>(src), method);
  827. case IL2CPP_TYPE_R8:
  828. return il2cpp_codegen_conv<TDest, double, double, checkOverflow, inputUnsigned>(il2cpp_codegen_read_to_aligned_value<double>(src), method);
  829. default:
  830. IL2CPP_RAISE_MANAGED_EXCEPTION(il2cpp_codegen_get_invalid_operation_exception("Unsupported conv opcode"), method);
  831. }
  832. return 0;
  833. }
  834. // objBuffer is a pointer to the obj, either a pointer to a struct's data or a pointer to a reference type pointer
  835. void il2cpp_codegen_runtime_constrained_call(RuntimeClass* type, const RuntimeMethod* constrainedMethod, void* boxBuffer, void* objBuffer, void** args, void* retVal);
  836. void* il2cpp_codegen_runtime_box_constrained_this(RuntimeClass* type, const RuntimeMethod* constrainedMethod, void* obj);
  837. template<typename T>
  838. inline void* il2cpp_codegen_unsafe_cast(T* ptr)
  839. {
  840. return reinterpret_cast<void*>(ptr);
  841. }
  842. inline void il2cpp_codegen_by_reference_constructor(Il2CppByReference* byReference, void* value)
  843. {
  844. IL2CPP_ASSERT_STACK_PTR(byReference);
  845. byReference->value = (intptr_t)value;
  846. }
  847. inline intptr_t il2cpp_codegen_by_reference_get_value(Il2CppByReference* byReference)
  848. {
  849. return byReference->value;
  850. }
  851. #define IL2CPP_BY_REFERENCE_GET_VALUE(TReturnType, byReference) (TReturnType*)il2cpp_codegen_by_reference_get_value(byReference)
  852. bool il2cpp_codegen_is_reference_or_contains_references(const RuntimeMethod* method);
  853. bool il2cpp_codegen_is_unmanaged(const RuntimeMethod* method);
  854. #if IL2CPP_TINY
  855. // Add intrinsics used by Tiny.
  856. #include "utils/MemoryUtils.h"
  857. Type_t* il2cpp_codegen_get_type(Il2CppObject* obj);
  858. inline int32_t il2cpp_codegen_get_array_length(Il2CppArray* genArray, int32_t dimension)
  859. {
  860. if (genArray->bounds == NULL)
  861. return il2cpp_codegen_get_array_length(genArray);
  862. return static_cast<int32_t>(genArray->bounds[dimension].length);
  863. }
  864. MulticastDelegate_t* il2cpp_codegen_create_combined_delegate(Type_t* type, Il2CppArray* delegates, int delegateCount);
  865. inline String_t* il2cpp_codegen_marshal_ptr_to_string_ansi(intptr_t ptr)
  866. {
  867. return il2cpp_codegen_marshal_string_result(reinterpret_cast<const char*>(ptr));
  868. }
  869. inline intptr_t il2cpp_codegen_marshal_string_to_co_task_mem_ansi(String_t* ptr)
  870. {
  871. return reinterpret_cast<intptr_t>(il2cpp_codegen_marshal_string(ptr));
  872. }
  873. inline void il2cpp_codegen_marshal_string_free_co_task_mem(intptr_t ptr)
  874. {
  875. il2cpp_codegen_marshal_free(reinterpret_cast<void*>(ptr));
  876. }
  877. struct Delegate_t;
  878. inline String_t* il2cpp_codegen_string_new_length(int length)
  879. {
  880. return reinterpret_cast<String_t*>(il2cpp::vm::String::NewSize(length));
  881. }
  882. Type_t* il2cpp_codegen_get_base_type(const Type_t* t);
  883. bool il2cpp_codegen_is_assignable_from(Type_t* left, Type_t* right);
  884. template<typename T>
  885. struct Il2CppReversePInvokeMethodHolder
  886. {
  887. Il2CppReversePInvokeMethodHolder(T** storageAddress) :
  888. m_LastValue(*storageAddress),
  889. m_StorageAddress(storageAddress)
  890. {
  891. }
  892. ~Il2CppReversePInvokeMethodHolder()
  893. {
  894. *m_StorageAddress = m_LastValue;
  895. }
  896. private:
  897. T* const m_LastValue;
  898. T** const m_StorageAddress;
  899. };
  900. void il2cpp_codegen_no_reverse_pinvoke_wrapper(const char* methodName, const char* reason);
  901. bool il2cpp_codegen_type_is_interface(Type_t* t);
  902. bool il2cpp_codegen_type_is_abstract(Type_t* t);
  903. bool il2cpp_codegen_type_is_pointer(Type_t* t);
  904. NORETURN void il2cpp_codegen_raise_exception(const char* message);
  905. #endif
  906. template<typename T>
  907. inline T* il2cpp_span_get_item(T* refPtrValue, int32_t index, int32_t length)
  908. {
  909. IL2CPP_ARRAY_BOUNDS_CHECK(index, length);
  910. return &refPtrValue[index];
  911. }
  912. template<typename T>
  913. inline T* il2cpp_unsafe_unbox(RuntimeObject* obj, RuntimeClass* klass)
  914. {
  915. return reinterpret_cast<T*>(UnBox(obj, klass));
  916. }
  917. #if IL2CPP_COMPILER_MSVC
  918. #define DEFAULT_CALL STDCALL
  919. #else
  920. #define DEFAULT_CALL
  921. #endif
  922. #if defined(__ARMCC_VERSION)
  923. inline double bankers_round(double x)
  924. {
  925. return __builtin_round(x);
  926. }
  927. inline float bankers_roundf(float x)
  928. {
  929. return __builtin_roundf(x);
  930. }
  931. #else
  932. inline double bankers_round(double x)
  933. {
  934. double integerPart;
  935. if (x >= 0.0)
  936. {
  937. if (modf(x, &integerPart) == 0.5)
  938. return (int64_t)integerPart % 2 == 0 ? integerPart : integerPart + 1.0;
  939. return floor(x + 0.5);
  940. }
  941. else
  942. {
  943. if (modf(x, &integerPart) == -0.5)
  944. return (int64_t)integerPart % 2 == 0 ? integerPart : integerPart - 1.0;
  945. return ceil(x - 0.5);
  946. }
  947. }
  948. inline float bankers_roundf(float x)
  949. {
  950. double integerPart;
  951. if (x >= 0.0f)
  952. {
  953. if (modf(x, &integerPart) == 0.5)
  954. return (int64_t)integerPart % 2 == 0 ? (float)integerPart : (float)integerPart + 1.0f;
  955. return floorf(x + 0.5f);
  956. }
  957. else
  958. {
  959. if (modf(x, &integerPart) == -0.5)
  960. return (int64_t)integerPart % 2 == 0 ? (float)integerPart : (float)integerPart - 1.0f;
  961. return ceilf(x - 0.5f);
  962. }
  963. }
  964. #endif
  965. // returns true if overflow occurs
  966. inline bool il2cpp_codegen_check_mul_overflow_i64(int64_t a, int64_t b, int64_t imin, int64_t imax)
  967. {
  968. // TODO: use a better algorithm without division
  969. uint64_t ua = (uint64_t)llabs(a);
  970. uint64_t ub = (uint64_t)llabs(b);
  971. uint64_t c;
  972. if ((a > 0 && b > 0) || (a <= 0 && b <= 0))
  973. c = (uint64_t)llabs(imax);
  974. else
  975. c = (uint64_t)llabs(imin);
  976. return ua != 0 && ub > c / ua;
  977. }
  978. inline bool il2cpp_codegen_check_mul_oveflow_u64(uint64_t a, uint64_t b)
  979. {
  980. return b != 0 && (a * b) / b != a;
  981. }
  982. inline int32_t il2cpp_codegen_abs(uint32_t value)
  983. {
  984. return abs(static_cast<int32_t>(value));
  985. }
  986. inline int32_t il2cpp_codegen_abs(int32_t value)
  987. {
  988. return abs(value);
  989. }
  990. inline int64_t il2cpp_codegen_abs(uint64_t value)
  991. {
  992. return llabs(static_cast<int64_t>(value));
  993. }
  994. inline int64_t il2cpp_codegen_abs(int64_t value)
  995. {
  996. return llabs(value);
  997. }
  998. void il2cpp_codegen_memory_barrier();
  999. template<typename T>
  1000. inline T VolatileRead(T* location)
  1001. {
  1002. T result = *location;
  1003. il2cpp_codegen_memory_barrier();
  1004. return result;
  1005. }
  1006. template<typename T, typename U>
  1007. inline void VolatileWrite(T** location, U* value)
  1008. {
  1009. il2cpp_codegen_memory_barrier();
  1010. *location = value;
  1011. Il2CppCodeGenWriteBarrier((void**)location, value);
  1012. }
  1013. template<typename T, typename U>
  1014. inline void VolatileWrite(T* location, U value)
  1015. {
  1016. il2cpp_codegen_memory_barrier();
  1017. *location = value;
  1018. }
  1019. inline void il2cpp_codegen_write_to_stdout(const char* str)
  1020. {
  1021. il2cpp::utils::Output::WriteToStdout(str);
  1022. }
  1023. inline void il2cpp_codegen_write_to_stderr(const char* str)
  1024. {
  1025. il2cpp::utils::Output::WriteToStderr(str);
  1026. }
  1027. REAL_NORETURN void il2cpp_codegen_abort();
  1028. inline bool il2cpp_codegen_check_add_overflow(int64_t left, int64_t right)
  1029. {
  1030. return (right >= 0 && left > kIl2CppInt64Max - right) ||
  1031. (left < 0 && right < kIl2CppInt64Min - left);
  1032. }
  1033. inline bool il2cpp_codegen_check_sub_overflow(int64_t left, int64_t right)
  1034. {
  1035. return (right >= 0 && left < kIl2CppInt64Min + right) ||
  1036. (right < 0 && left > kIl2CppInt64Max + right);
  1037. }
  1038. inline void il2cpp_codegen_register_debugger_data(const Il2CppDebuggerMetadataRegistration *data)
  1039. {
  1040. #if IL2CPP_MONO_DEBUGGER
  1041. il2cpp::utils::Debugger::RegisterMetadata(data);
  1042. #endif
  1043. }
  1044. inline void il2cpp_codegen_check_sequence_point(Il2CppSequencePointExecutionContext* executionContext, Il2CppSequencePoint* seqPoint)
  1045. {
  1046. #if IL2CPP_MONO_DEBUGGER
  1047. il2cpp::utils::Debugger::CheckSequencePoint(executionContext, seqPoint);
  1048. #endif
  1049. }
  1050. inline void il2cpp_codegen_check_sequence_point_entry(Il2CppSequencePointExecutionContext* executionContext, Il2CppSequencePoint* seqPoint)
  1051. {
  1052. #if IL2CPP_MONO_DEBUGGER
  1053. il2cpp::utils::Debugger::CheckSequencePointEntry(executionContext, seqPoint);
  1054. #endif
  1055. }
  1056. inline void il2cpp_codegen_check_sequence_point_exit(Il2CppSequencePointExecutionContext* executionContext, Il2CppSequencePoint* seqPoint)
  1057. {
  1058. #if IL2CPP_MONO_DEBUGGER
  1059. il2cpp::utils::Debugger::CheckSequencePointExit(executionContext, seqPoint);
  1060. #endif
  1061. }
  1062. inline void il2cpp_codegen_check_pause_point()
  1063. {
  1064. #if IL2CPP_MONO_DEBUGGER
  1065. il2cpp::utils::Debugger::CheckPausePoint();
  1066. #endif
  1067. }
  1068. class MethodExitSequencePointChecker
  1069. {
  1070. private:
  1071. Il2CppSequencePoint* m_seqPoint;
  1072. Il2CppSequencePointExecutionContext* m_seqPointStorage;
  1073. public:
  1074. MethodExitSequencePointChecker(Il2CppSequencePointExecutionContext* seqPointStorage, Il2CppSequencePoint* seqPoint) :
  1075. m_seqPointStorage(seqPointStorage), m_seqPoint(seqPoint)
  1076. {
  1077. }
  1078. ~MethodExitSequencePointChecker()
  1079. {
  1080. #if IL2CPP_MONO_DEBUGGER
  1081. il2cpp_codegen_check_sequence_point_exit(m_seqPointStorage, m_seqPoint);
  1082. #endif
  1083. }
  1084. };
  1085. #ifdef _MSC_VER
  1086. #define IL2CPP_DISABLE_OPTIMIZATIONS __pragma(optimize("", off))
  1087. #define IL2CPP_ENABLE_OPTIMIZATIONS __pragma(optimize("", on))
  1088. #elif IL2CPP_TARGET_LINUX || IL2CPP_TARGET_QNX
  1089. #define IL2CPP_DISABLE_OPTIMIZATIONS
  1090. #define IL2CPP_ENABLE_OPTIMIZATIONS
  1091. #else
  1092. #define IL2CPP_DISABLE_OPTIMIZATIONS __attribute__ ((optnone))
  1093. #define IL2CPP_ENABLE_OPTIMIZATIONS
  1094. #endif
  1095. // Array Unsafe
  1096. #define IL2CPP_ARRAY_UNSAFE_LOAD(TArray, TIndex) \
  1097. (TArray)->GetAtUnchecked(static_cast<il2cpp_array_size_t>(TIndex))
  1098. inline bool il2cpp_codegen_object_reference_equals(const RuntimeObject *obj1, const RuntimeObject *obj2)
  1099. {
  1100. return obj1 == obj2;
  1101. }
  1102. inline bool il2cpp_codegen_platform_is_osx_or_ios()
  1103. {
  1104. return IL2CPP_TARGET_OSX != 0 || IL2CPP_TARGET_IOS != 0;
  1105. }
  1106. inline bool il2cpp_codegen_platform_is_freebsd()
  1107. {
  1108. // we don't currently support FreeBSD
  1109. return false;
  1110. }
  1111. inline bool il2cpp_codegen_platform_is_uwp()
  1112. {
  1113. return IL2CPP_TARGET_WINRT != 0;
  1114. }
  1115. inline bool il2cpp_codegen_platform_disable_libc_pinvoke()
  1116. {
  1117. return IL2CPP_PLATFORM_DISABLE_LIBC_PINVOKE;
  1118. }
  1119. template<typename T>
  1120. inline T il2cpp_unsafe_read_unaligned(void* location)
  1121. {
  1122. T result;
  1123. #if IL2CPP_TARGET_ARMV7 || IL2CPP_TARGET_JAVASCRIPT
  1124. memcpy(&result, location, sizeof(T));
  1125. #else
  1126. result = *((T*)location);
  1127. #endif
  1128. return result;
  1129. }
  1130. template<typename T>
  1131. inline void il2cpp_unsafe_write_unaligned(void* location, T value)
  1132. {
  1133. #if IL2CPP_TARGET_ARMV7 || IL2CPP_TARGET_JAVASCRIPT
  1134. memcpy(location, &value, sizeof(T));
  1135. #else
  1136. *((T*)location) = value;
  1137. #endif
  1138. }
  1139. template<typename T>
  1140. inline T il2cpp_unsafe_read(void* location)
  1141. {
  1142. return *((T*)location);
  1143. }
  1144. template<typename T>
  1145. inline void il2cpp_unsafe_write(void* location, T value)
  1146. {
  1147. *((T*)location) = value;
  1148. }
  1149. template<typename T, typename TOffset>
  1150. inline T* il2cpp_unsafe_add(void* source, TOffset offset)
  1151. {
  1152. return reinterpret_cast<T*>(source) + offset;
  1153. }
  1154. template<typename T, typename TOffset>
  1155. inline T* il2cpp_unsafe_add_byte_offset(void* source, TOffset offset)
  1156. {
  1157. return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(source) + offset);
  1158. }
  1159. template<typename T, typename TOffset>
  1160. inline T* il2cpp_unsafe_subtract(void* source, TOffset offset)
  1161. {
  1162. return reinterpret_cast<T*>(source) - offset;
  1163. }
  1164. template<typename T, typename TOffset>
  1165. inline T* il2cpp_unsafe_subtract_byte_offset(void* source, TOffset offset)
  1166. {
  1167. return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(source) - offset);
  1168. }
  1169. template<typename T>
  1170. inline T il2cpp_unsafe_as(void* source)
  1171. {
  1172. return reinterpret_cast<T>(source);
  1173. }
  1174. template<typename T>
  1175. inline T* il2cpp_unsafe_as_ref(void* source)
  1176. {
  1177. return reinterpret_cast<T*>(source);
  1178. }
  1179. inline void* il2cpp_unsafe_as_pointer(void* source)
  1180. {
  1181. return source;
  1182. }
  1183. template<typename T>
  1184. inline T* il2cpp_unsafe_null_ref()
  1185. {
  1186. return reinterpret_cast<T*>(NULL);
  1187. }
  1188. inline bool il2cpp_unsafe_are_same(void* left, void* right)
  1189. {
  1190. return left == right;
  1191. }
  1192. inline bool il2cpp_unsafe_is_addr_gt(void* left, void* right)
  1193. {
  1194. return left > right;
  1195. }
  1196. inline bool il2cpp_unsafe_is_addr_lt(void* left, void* right)
  1197. {
  1198. return left < right;
  1199. }
  1200. inline bool il2cpp_unsafe_is_null_ref(void* source)
  1201. {
  1202. return source == NULL;
  1203. }
  1204. template<typename T>
  1205. inline int32_t il2cpp_unsafe_sizeof()
  1206. {
  1207. return sizeof(T);
  1208. }
  1209. inline intptr_t il2cpp_unsafe_byte_offset(void* origin, void* target)
  1210. {
  1211. return reinterpret_cast<uint8_t*>(target) - reinterpret_cast<uint8_t*>(origin);
  1212. }