MethodBridge.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #include "MethodBridge.h"
  2. #include "vm/Object.h"
  3. #include "vm/Class.h"
  4. #include "metadata/GenericMetadata.h"
  5. #include "../metadata/MetadataModule.h"
  6. #include "../metadata/MetadataUtil.h"
  7. #include "Interpreter.h"
  8. #include "InterpreterModule.h"
  9. #include "MemoryUtil.h"
  10. namespace hybridclr
  11. {
  12. namespace interpreter
  13. {
  14. void ConvertInvokeArgs(StackObject* resultArgs, const MethodInfo* method, MethodArgDesc* argDescs, void** args)
  15. {
  16. int32_t dstIdx = 0;
  17. for (uint8_t i = 0; i < method->parameters_count; i++)
  18. {
  19. StackObject* dst = resultArgs + dstIdx;
  20. MethodArgDesc& argDesc = argDescs[i];
  21. if (argDesc.passbyValWhenInvoke)
  22. {
  23. dst->ptr = args[i];
  24. ++dstIdx;
  25. }
  26. else
  27. {
  28. #if SUPPORT_MEMORY_NOT_ALIGMENT_ACCESS
  29. CopyStackObject(dst, args[i], argDesc.stackObjectSize);
  30. #else
  31. std::memcpy(dst, args[i], argDesc.stackObjectSize * sizeof(StackObject));
  32. #endif
  33. dstIdx += argDesc.stackObjectSize;
  34. }
  35. }
  36. }
  37. static void AppendString(char* sigBuf, size_t bufSize, size_t& pos, const char* str)
  38. {
  39. size_t len = std::strlen(str);
  40. if (pos + len < bufSize)
  41. {
  42. std::strcpy(sigBuf + pos, str);
  43. pos += len;
  44. }
  45. else
  46. {
  47. RaiseExecutionEngineException("");
  48. }
  49. }
  50. inline void AppendSignatureObjOrRefOrPointer(char* sigBuf, size_t bufSize, size_t& pos)
  51. {
  52. AppendString(sigBuf, bufSize, pos, "u");
  53. }
  54. inline void AppendSignatureInterpreterValueType(char* sigBuf, size_t bufSize, size_t& pos)
  55. {
  56. AppendString(sigBuf, bufSize, pos, "$");
  57. }
  58. static void AppendSignature(const Il2CppType* type, char* sigBuf, size_t bufferSize, size_t& pos, bool convertTypeName2SigName = true);
  59. static bool IsSystemOrUnityAssembly(const Il2CppImage* image)
  60. {
  61. const char* assName = image->nameNoExt;
  62. if (std::strcmp(assName, "mscorlib") == 0)
  63. {
  64. return true;
  65. }
  66. if (std::strncmp(assName, "System.", 7) == 0)
  67. {
  68. return true;
  69. }
  70. if (std::strncmp(assName, "UnityEngine.", 12) == 0)
  71. {
  72. return true;
  73. }
  74. return false;
  75. }
  76. static void BuildValueTypeFullName(const Il2CppClass* klass, char* sigBuf, size_t bufferSize, size_t& pos)
  77. {
  78. if (klass->declaringType)
  79. {
  80. BuildValueTypeFullName(klass->declaringType, sigBuf, bufferSize, pos);
  81. AppendString(sigBuf, bufferSize, pos, "/");
  82. AppendString(sigBuf, bufferSize, pos, klass->name);
  83. return;
  84. }
  85. if (!IsSystemOrUnityAssembly(klass->image))
  86. {
  87. AppendString(sigBuf, bufferSize, pos, klass->image->nameNoExt);
  88. AppendString(sigBuf, bufferSize, pos, ":");
  89. }
  90. if (klass->namespaze[0])
  91. {
  92. AppendString(sigBuf, bufferSize, pos, klass->namespaze);
  93. AppendString(sigBuf, bufferSize, pos, ".");
  94. }
  95. AppendString(sigBuf, bufferSize, pos, klass->name);
  96. }
  97. static void BuildGenericValueTypeFullName(const Il2CppType* type, char* sigBuf, size_t bufferSize, size_t& pos)
  98. {
  99. const Il2CppType* underlyingGenericType = type->data.generic_class->type;
  100. const Il2CppClass* underlyingGenericClass = il2cpp::vm::Class::FromIl2CppType(underlyingGenericType);
  101. BuildValueTypeFullName(underlyingGenericClass, sigBuf, bufferSize, pos);
  102. AppendString(sigBuf, bufferSize, pos, "<");
  103. const Il2CppGenericInst* classInst = type->data.generic_class->context.class_inst;
  104. for (uint32_t i = 0 ; i < classInst->type_argc; ++i)
  105. {
  106. if (i != 0)
  107. {
  108. AppendString(sigBuf, bufferSize, pos, ",");
  109. }
  110. AppendSignature(classInst->type_argv[i], sigBuf, bufferSize, pos, false);
  111. }
  112. AppendString(sigBuf, bufferSize, pos, ">");
  113. }
  114. static void AppendSignature(const Il2CppType* type, char* sigBuf, size_t bufferSize, size_t& pos, bool convertTypeName2SigName)
  115. {
  116. if (type->byref)
  117. {
  118. AppendSignatureObjOrRefOrPointer(sigBuf, bufferSize, pos);
  119. return;
  120. }
  121. switch (type->type)
  122. {
  123. case IL2CPP_TYPE_VOID: AppendString(sigBuf, bufferSize, pos, "v"); break;
  124. case IL2CPP_TYPE_BOOLEAN: AppendString(sigBuf, bufferSize, pos, "u1"); break;
  125. case IL2CPP_TYPE_I1: AppendString(sigBuf, bufferSize, pos, "i1"); break;
  126. case IL2CPP_TYPE_U1: AppendString(sigBuf, bufferSize, pos, "u1"); break;
  127. case IL2CPP_TYPE_I2: AppendString(sigBuf, bufferSize, pos, "i2"); break;
  128. case IL2CPP_TYPE_U2:
  129. case IL2CPP_TYPE_CHAR: AppendString(sigBuf, bufferSize, pos, "u2"); break;
  130. case IL2CPP_TYPE_I4: AppendString(sigBuf, bufferSize, pos, "i4"); break;
  131. case IL2CPP_TYPE_U4: AppendString(sigBuf, bufferSize, pos, "u4"); break;
  132. case IL2CPP_TYPE_R4: AppendString(sigBuf, bufferSize, pos, "r4"); break;
  133. case IL2CPP_TYPE_R8: AppendString(sigBuf, bufferSize, pos, "r8"); break;
  134. case IL2CPP_TYPE_I8: AppendString(sigBuf, bufferSize, pos, "i8"); break;
  135. case IL2CPP_TYPE_U8: AppendString(sigBuf, bufferSize, pos, "u8"); break;
  136. case IL2CPP_TYPE_I: AppendString(sigBuf, bufferSize, pos, "i"); break;
  137. case IL2CPP_TYPE_U: AppendString(sigBuf, bufferSize, pos, "u"); break;
  138. case IL2CPP_TYPE_TYPEDBYREF:
  139. {
  140. IL2CPP_ASSERT(sizeof(Il2CppTypedRef) == sizeof(void*) * 3);
  141. AppendString(sigBuf, bufferSize, pos, "typedbyref");
  142. break;
  143. }
  144. case IL2CPP_TYPE_VALUETYPE:
  145. {
  146. const Il2CppTypeDefinition* typeDef = (const Il2CppTypeDefinition*)type->data.typeHandle;
  147. if (hybridclr::metadata::IsEnumType(typeDef))
  148. {
  149. AppendSignature(il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(typeDef->elementTypeIndex), sigBuf, bufferSize, pos);
  150. break;
  151. }
  152. if (hybridclr::metadata::IsInterpreterType(typeDef))
  153. {
  154. AppendSignatureInterpreterValueType(sigBuf, bufferSize, pos);
  155. break;
  156. }
  157. char tempFullName[1024];
  158. size_t fullNamePos = 0;
  159. Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
  160. BuildValueTypeFullName(klass, tempFullName, sizeof(tempFullName) - 1, fullNamePos);
  161. tempFullName[fullNamePos] = 0;
  162. AppendString(sigBuf, bufferSize, pos, convertTypeName2SigName ? InterpreterModule::GetValueTypeSignature(tempFullName) : tempFullName);
  163. break;
  164. }
  165. case IL2CPP_TYPE_GENERICINST:
  166. {
  167. const Il2CppType* underlyingGenericType = type->data.generic_class->type;
  168. if (underlyingGenericType->type == IL2CPP_TYPE_CLASS)
  169. {
  170. AppendSignatureObjOrRefOrPointer(sigBuf, bufferSize, pos);
  171. break;
  172. }
  173. const Il2CppTypeDefinition* underlyingTypeDef = (const Il2CppTypeDefinition*)underlyingGenericType->data.typeHandle;
  174. if (hybridclr::metadata::IsEnumType(underlyingTypeDef))
  175. {
  176. AppendSignature(il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(underlyingTypeDef->elementTypeIndex), sigBuf, bufferSize, pos);
  177. break;
  178. }
  179. IL2CPP_ASSERT(underlyingGenericType->type == IL2CPP_TYPE_VALUETYPE);
  180. if (hybridclr::metadata::IsInterpreterType(underlyingTypeDef))
  181. {
  182. AppendSignatureInterpreterValueType(sigBuf, bufferSize, pos);
  183. break;
  184. }
  185. char tempFullName[1024];
  186. size_t fullNamePos = 0;
  187. BuildGenericValueTypeFullName(type, tempFullName, sizeof(tempFullName) - 1, fullNamePos);
  188. tempFullName[fullNamePos] = 0;
  189. AppendString(sigBuf, bufferSize, pos, convertTypeName2SigName ? InterpreterModule::GetValueTypeSignature(tempFullName) : tempFullName);
  190. break;
  191. }
  192. case IL2CPP_TYPE_VAR:
  193. case IL2CPP_TYPE_MVAR:
  194. {
  195. AppendString(sigBuf, bufferSize, pos, "!");
  196. break;
  197. }
  198. default: AppendSignatureObjOrRefOrPointer(sigBuf, bufferSize, pos); break;
  199. }
  200. }
  201. bool ComputeSignature(const Il2CppType* ret, const Il2CppType* params, uint32_t paramCount, bool instanceCall, char* sigBuf, size_t bufferSize)
  202. {
  203. size_t pos = 0;
  204. AppendSignature(ret, sigBuf, bufferSize, pos);
  205. if (instanceCall)
  206. {
  207. AppendSignatureObjOrRefOrPointer(sigBuf, bufferSize, pos);
  208. }
  209. for (uint32_t i = 0; i < paramCount; i++)
  210. {
  211. AppendSignature(params + i, sigBuf, bufferSize, pos);
  212. }
  213. sigBuf[pos] = 0;
  214. return true;
  215. }
  216. bool ComputeSignature(const Il2CppMethodDefinition* method, bool call, char* sigBuf, size_t bufferSize)
  217. {
  218. size_t pos = 0;
  219. if (method->genericContainerIndex != kGenericContainerIndexInvalid)
  220. {
  221. AppendString(sigBuf, bufferSize, pos, "!");
  222. return true;
  223. }
  224. const Il2CppImage* image = hybridclr::metadata::MetadataModule::GetImage(method)->GetIl2CppImage();
  225. AppendSignature(hybridclr::metadata::MetadataModule::GetIl2CppTypeFromEncodeIndex(method->returnType), sigBuf, bufferSize, pos);
  226. if (call && metadata::IsInstanceMethod(method))
  227. {
  228. AppendSignatureObjOrRefOrPointer(sigBuf, bufferSize, pos);
  229. }
  230. for (uint8_t i = 0; i < method->parameterCount; i++)
  231. {
  232. TypeIndex paramTypeIndex = hybridclr::metadata::MetadataModule::GetParameterDefinitionFromIndex(image, method->parameterStart + i)->typeIndex;
  233. AppendSignature(hybridclr::metadata::MetadataModule::GetIl2CppTypeFromEncodeIndex(paramTypeIndex), sigBuf, bufferSize, pos);
  234. }
  235. sigBuf[pos] = 0;
  236. return true;
  237. }
  238. inline bool ContainsGenericParameters(const MethodInfo* method)
  239. {
  240. IL2CPP_ASSERT(method->is_inflated);
  241. auto& ctx = method->genericMethod->context;
  242. if (ctx.class_inst && il2cpp::metadata::GenericMetadata::ContainsGenericParameters(ctx.class_inst))
  243. {
  244. return true;
  245. }
  246. if (ctx.method_inst && il2cpp::metadata::GenericMetadata::ContainsGenericParameters(ctx.method_inst))
  247. {
  248. return true;
  249. }
  250. return false;
  251. }
  252. bool ComputeSignature(const MethodInfo* method, bool call, char* sigBuf, size_t bufferSize)
  253. {
  254. size_t pos = 0;
  255. if (method->is_generic || (method->is_inflated && ContainsGenericParameters(method)))
  256. {
  257. AppendString(sigBuf, bufferSize, pos, "!");
  258. return true;
  259. }
  260. AppendSignature(method->return_type, sigBuf, bufferSize, pos);
  261. if (call && metadata::IsInstanceMethod(method))
  262. {
  263. AppendSignatureObjOrRefOrPointer(sigBuf, bufferSize, pos);
  264. }
  265. for (uint8_t i = 0; i < method->parameters_count; i++)
  266. {
  267. AppendSignature(GET_METHOD_PARAMETER_TYPE(method->parameters[i]), sigBuf, bufferSize, pos);
  268. }
  269. sigBuf[pos] = 0;
  270. return true;
  271. }
  272. }
  273. }