BindingGeneratorExtensions.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using System.Linq;
  5. using System.Text;
  6. using ILRuntime.Runtime.Enviorment;
  7. using ILRuntime.CLR.Utils;
  8. namespace ILRuntime.Runtime.CLRBinding
  9. {
  10. static class BindingGeneratorExtensions
  11. {
  12. internal static bool ShouldSkipField(this Type type, FieldInfo i)
  13. {
  14. if (i.IsPrivate)
  15. return true;
  16. //EventHandler is currently not supported
  17. if (i.IsSpecialName)
  18. {
  19. return true;
  20. }
  21. if (i.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0)
  22. return true;
  23. return false;
  24. }
  25. internal static bool ShouldSkipMethod(this Type type, MethodBase i)
  26. {
  27. if (i.IsPrivate)
  28. return true;
  29. if (i.IsGenericMethodDefinition)
  30. return true;
  31. if (i.IsConstructor && type.IsAbstract)
  32. return true;
  33. if (i is MethodInfo && ((MethodInfo)i).ReturnType.IsByRef)
  34. return true;
  35. //EventHandler is currently not supported
  36. var param = i.GetParameters();
  37. if (i.IsSpecialName)
  38. {
  39. string[] t = i.Name.Split('_');
  40. //if (t[0] == "add" || t[0] == "remove")
  41. // return true;
  42. if (t[0] == "get" || t[0] == "set")
  43. {
  44. Type[] ts;
  45. var cnt = t[0] == "set" ? param.Length - 1 : param.Length;
  46. if (cnt > 0)
  47. {
  48. ts = new Type[cnt];
  49. for (int j = 0; j < cnt; j++)
  50. {
  51. ts[j] = param[j].ParameterType;
  52. }
  53. }
  54. else
  55. ts = new Type[0];
  56. var prop = type.GetProperty(t[1], ts);
  57. if (prop == null)
  58. {
  59. return true;
  60. }
  61. if (prop.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0)
  62. return true;
  63. }
  64. }
  65. if (i.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0)
  66. return true;
  67. foreach (var j in param)
  68. {
  69. if (j.ParameterType.IsPointer)
  70. return true;
  71. }
  72. return false;
  73. }
  74. internal static void AppendParameters(this ParameterInfo[] param, StringBuilder sb, bool isMultiArr = false, int skipLast = 0)
  75. {
  76. bool first = true;
  77. for (int i = 0; i < param.Length - skipLast; i++)
  78. {
  79. if (first)
  80. first = false;
  81. else
  82. sb.Append(", ");
  83. var j = param[i];
  84. if (j.IsOut && j.ParameterType.IsByRef)
  85. sb.Append("out ");
  86. else if (j.IsIn && j.ParameterType.IsByRef)
  87. sb.Append("in ");
  88. else if (j.ParameterType.IsByRef)
  89. sb.Append("ref ");
  90. if (isMultiArr)
  91. {
  92. sb.Append("a");
  93. sb.Append(i + 1);
  94. }
  95. else
  96. {
  97. sb.Append("@");
  98. sb.Append(j.Name);
  99. }
  100. }
  101. }
  102. internal static void AppendArgumentCode(this Type p, StringBuilder sb, int idx, string name, List<Type> valueTypeBinders, bool isMultiArr, bool hasByRef, bool needFree)
  103. {
  104. string clsName, realClsName;
  105. bool isByRef;
  106. p.GetClassName(out clsName, out realClsName, out isByRef);
  107. var pt = p.IsByRef ? p.GetElementType() : p;
  108. string shouldFreeParam = hasByRef ? "false" : "true";
  109. if (pt.IsValueType && !pt.IsPrimitive && valueTypeBinders != null && valueTypeBinders.Contains(pt))
  110. {
  111. if (isMultiArr)
  112. sb.AppendLine(string.Format(" {0} a{1} = new {0}();", realClsName, idx));
  113. else
  114. sb.AppendLine(string.Format(" {0} @{1} = new {0}();", realClsName, name));
  115. sb.AppendLine(string.Format(" if (ILRuntime.Runtime.Generated.CLRBindings.s_{0}_Binder != null) {{", clsName));
  116. if (isMultiArr)
  117. sb.AppendLine(string.Format(" ILRuntime.Runtime.Generated.CLRBindings.s_{1}_Binder.ParseValue(ref a{0}, __intp, ptr_of_this_method, __mStack, {2});", idx, clsName, shouldFreeParam));
  118. else
  119. sb.AppendLine(string.Format(" ILRuntime.Runtime.Generated.CLRBindings.s_{1}_Binder.ParseValue(ref @{0}, __intp, ptr_of_this_method, __mStack, {2});", name, clsName, shouldFreeParam));
  120. sb.AppendLine(" } else {");
  121. if (isByRef)
  122. sb.AppendLine(" ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method);");
  123. if (isMultiArr)
  124. sb.AppendLine(string.Format(" a{0} = {1};", idx, p.GetRetrieveValueCode(realClsName)));
  125. else
  126. sb.AppendLine(string.Format(" @{0} = {1};", name, p.GetRetrieveValueCode(realClsName)));
  127. if (!hasByRef && needFree)
  128. sb.AppendLine(" __intp.Free(ptr_of_this_method);");
  129. sb.AppendLine(" }");
  130. }
  131. else
  132. {
  133. if (isByRef)
  134. {
  135. if (p.GetElementType().IsPrimitive)
  136. {
  137. if (pt == typeof(int) || pt == typeof(uint) || pt == typeof(short) || pt == typeof(ushort) || pt == typeof(byte) || pt == typeof(sbyte) || pt == typeof(char))
  138. {
  139. if (pt == typeof(int))
  140. sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveInt32(ptr_of_this_method, __mStack);", realClsName, name));
  141. else
  142. sb.AppendLine(string.Format(" {0} @{1} = ({0})__intp.RetriveInt32(ptr_of_this_method, __mStack);", realClsName, name));
  143. }
  144. else if (pt == typeof(long) || pt == typeof(ulong))
  145. {
  146. if (pt == typeof(long))
  147. sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveInt64(ptr_of_this_method, __mStack);", realClsName, name));
  148. else
  149. sb.AppendLine(string.Format(" {0} @{1} = ({0})__intp.RetriveInt64(ptr_of_this_method, __mStack);", realClsName, name));
  150. }
  151. else if (pt == typeof(float))
  152. {
  153. sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveFloat(ptr_of_this_method, __mStack);", realClsName, name));
  154. }
  155. else if (pt == typeof(double))
  156. {
  157. sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveDouble(ptr_of_this_method, __mStack);", realClsName, name));
  158. }
  159. else if (pt == typeof(bool))
  160. {
  161. sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveInt32(ptr_of_this_method, __mStack) == 1;", realClsName, name));
  162. }
  163. else
  164. throw new NotSupportedException();
  165. }
  166. else if (p.GetElementType().IsEnum)
  167. {
  168. sb.AppendLine(string.Format(" {0} @{1} = ({0})__intp.RetriveInt32(ptr_of_this_method, __mStack);", realClsName, name));
  169. }
  170. else
  171. {
  172. sb.AppendLine(string.Format(" {0} @{1} = ({0})typeof({0}).CheckCLRTypes(__intp.RetriveObject(ptr_of_this_method, __mStack), (CLR.Utils.Extensions.TypeFlags){2});", realClsName, name, (int)p.GetTypeFlagsRecursive()));
  173. }
  174. }
  175. else
  176. {
  177. if (isMultiArr)
  178. sb.AppendLine(string.Format(" {0} a{1} = {2};", realClsName, idx, p.GetRetrieveValueCode(realClsName)));
  179. else
  180. sb.AppendLine(string.Format(" {0} @{1} = {2};", realClsName, name, p.GetRetrieveValueCode(realClsName)));
  181. if (!hasByRef && !p.IsPrimitive && needFree)
  182. sb.AppendLine(" __intp.Free(ptr_of_this_method);");
  183. }
  184. }
  185. }
  186. internal static string GetRetrieveValueCode(this Type type, string realClsName)
  187. {
  188. if (type.IsByRef)
  189. type = type.GetElementType();
  190. if (type.IsPrimitive)
  191. {
  192. if (type == typeof(int))
  193. {
  194. return "ptr_of_this_method->Value";
  195. }
  196. else if (type == typeof(long))
  197. {
  198. return "*(long*)&ptr_of_this_method->Value";
  199. }
  200. else if (type == typeof(short))
  201. {
  202. return "(short)ptr_of_this_method->Value";
  203. }
  204. else if (type == typeof(bool))
  205. {
  206. return "ptr_of_this_method->Value == 1";
  207. }
  208. else if (type == typeof(ushort))
  209. {
  210. return "(ushort)ptr_of_this_method->Value";
  211. }
  212. else if (type == typeof(float))
  213. {
  214. return "*(float*)&ptr_of_this_method->Value";
  215. }
  216. else if (type == typeof(double))
  217. {
  218. return "*(double*)&ptr_of_this_method->Value";
  219. }
  220. else if (type == typeof(byte))
  221. {
  222. return "(byte)ptr_of_this_method->Value";
  223. }
  224. else if (type == typeof(sbyte))
  225. {
  226. return "(sbyte)ptr_of_this_method->Value";
  227. }
  228. else if (type == typeof(uint))
  229. {
  230. return "(uint)ptr_of_this_method->Value";
  231. }
  232. else if (type == typeof(char))
  233. {
  234. return "(char)ptr_of_this_method->Value";
  235. }
  236. else if (type == typeof(ulong))
  237. {
  238. return "*(ulong*)&ptr_of_this_method->Value";
  239. }
  240. else
  241. throw new NotImplementedException();
  242. }
  243. else
  244. {
  245. return string.Format("({0})typeof({0}).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack), (CLR.Utils.Extensions.TypeFlags){1})", realClsName, (int)type.GetTypeFlagsRecursive());
  246. }
  247. }
  248. internal static void GetRefWriteBackValueCode(this Type type, StringBuilder sb, string paramName)
  249. {
  250. if (type.IsPrimitive)
  251. {
  252. if (type == typeof(int))
  253. {
  254. sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;");
  255. sb.Append(" ___dst->Value = @" + paramName);
  256. sb.AppendLine(";");
  257. }
  258. else if (type == typeof(long))
  259. {
  260. sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Long;");
  261. sb.Append(" *(long*)&___dst->Value = @" + paramName);
  262. sb.AppendLine(";");
  263. }
  264. else if (type == typeof(short))
  265. {
  266. sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;");
  267. sb.Append(" ___dst->Value = @" + paramName);
  268. sb.AppendLine(";");
  269. }
  270. else if (type == typeof(bool))
  271. {
  272. sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;");
  273. sb.Append(" ___dst->Value = @" + paramName + " ? 1 : 0;");
  274. sb.AppendLine(";");
  275. }
  276. else if (type == typeof(ushort))
  277. {
  278. sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;");
  279. sb.Append(" ___dst->Value = @" + paramName);
  280. sb.AppendLine(";");
  281. }
  282. else if (type == typeof(float))
  283. {
  284. sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Float;");
  285. sb.Append(" *(float*)&___dst->Value = @" + paramName);
  286. sb.AppendLine(";");
  287. }
  288. else if (type == typeof(double))
  289. {
  290. sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Double;");
  291. sb.Append(" *(double*)&___dst->Value = @" + paramName);
  292. sb.AppendLine(";");
  293. }
  294. else if (type == typeof(byte))
  295. {
  296. sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;");
  297. sb.Append(" ___dst->Value = @" + paramName);
  298. sb.AppendLine(";");
  299. }
  300. else if (type == typeof(sbyte))
  301. {
  302. sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;");
  303. sb.Append(" ___dst->Value = @" + paramName);
  304. sb.AppendLine(";");
  305. }
  306. else if (type == typeof(uint))
  307. {
  308. sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;");
  309. sb.Append(" ___dst->Value = (int)@" + paramName);
  310. sb.AppendLine(";");
  311. }
  312. else if (type == typeof(char))
  313. {
  314. sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;");
  315. sb.Append(" ___dst->Value = (int)@" + paramName);
  316. sb.AppendLine(";");
  317. }
  318. else if (type == typeof(ulong))
  319. {
  320. sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Long;");
  321. sb.Append(" *(ulong*)&___dst->Value = @" + paramName);
  322. sb.AppendLine(";");
  323. }
  324. else
  325. throw new NotImplementedException();
  326. }
  327. else if(type.IsEnum)
  328. {
  329. sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;");
  330. sb.Append(" ___dst->Value = (int)@" + paramName);
  331. sb.AppendLine(";");
  332. }
  333. else
  334. {
  335. sb.Append(@" object ___obj = @");
  336. sb.Append(paramName);
  337. sb.AppendLine(";");
  338. sb.AppendLine(@" if (___dst->ObjectType >= ObjectTypes.Object)
  339. {
  340. if (___obj is CrossBindingAdaptorType)
  341. ___obj = ((CrossBindingAdaptorType)___obj).ILInstance;
  342. __mStack[___dst->Value] = ___obj;
  343. }
  344. else
  345. {
  346. ILIntepreter.UnboxObject(___dst, ___obj, __mStack, __domain);
  347. }");
  348. /*if (!type.IsValueType)
  349. {
  350. sb.Append(@" object ___obj = ");
  351. sb.Append(paramName);
  352. sb.AppendLine(";");
  353. sb.AppendLine(@" if (___obj is CrossBindingAdaptorType)
  354. ___obj = ((CrossBindingAdaptorType)___obj).ILInstance;
  355. __mStack[___dst->Value] = ___obj; ");
  356. }
  357. else
  358. {
  359. sb.Append(" __mStack[___dst->Value] = ");
  360. sb.Append(paramName);
  361. sb.AppendLine(";");
  362. }*/
  363. }
  364. }
  365. internal static void GetReturnValueCode(this Type type, StringBuilder sb, Enviorment.AppDomain domain)
  366. {
  367. if (type.IsPrimitive)
  368. {
  369. if (type == typeof(int))
  370. {
  371. sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;");
  372. sb.AppendLine(" __ret->Value = result_of_this_method;");
  373. }
  374. else if (type == typeof(long))
  375. {
  376. sb.AppendLine(" __ret->ObjectType = ObjectTypes.Long;");
  377. sb.AppendLine(" *(long*)&__ret->Value = result_of_this_method;");
  378. }
  379. else if (type == typeof(short))
  380. {
  381. sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;");
  382. sb.AppendLine(" __ret->Value = result_of_this_method;");
  383. }
  384. else if (type == typeof(bool))
  385. {
  386. sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;");
  387. sb.AppendLine(" __ret->Value = result_of_this_method ? 1 : 0;");
  388. }
  389. else if (type == typeof(ushort))
  390. {
  391. sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;");
  392. sb.AppendLine(" __ret->Value = result_of_this_method;");
  393. }
  394. else if (type == typeof(float))
  395. {
  396. sb.AppendLine(" __ret->ObjectType = ObjectTypes.Float;");
  397. sb.AppendLine(" *(float*)&__ret->Value = result_of_this_method;");
  398. }
  399. else if (type == typeof(double))
  400. {
  401. sb.AppendLine(" __ret->ObjectType = ObjectTypes.Double;");
  402. sb.AppendLine(" *(double*)&__ret->Value = result_of_this_method;");
  403. }
  404. else if (type == typeof(byte))
  405. {
  406. sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;");
  407. sb.AppendLine(" __ret->Value = result_of_this_method;");
  408. }
  409. else if (type == typeof(sbyte))
  410. {
  411. sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;");
  412. sb.AppendLine(" __ret->Value = result_of_this_method;");
  413. }
  414. else if (type == typeof(uint))
  415. {
  416. sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;");
  417. sb.AppendLine(" __ret->Value = (int)result_of_this_method;");
  418. }
  419. else if (type == typeof(char))
  420. {
  421. sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;");
  422. sb.AppendLine(" __ret->Value = (int)result_of_this_method;");
  423. }
  424. else if (type == typeof(ulong))
  425. {
  426. sb.AppendLine(" __ret->ObjectType = ObjectTypes.Long;");
  427. sb.AppendLine(" *(ulong*)&__ret->Value = result_of_this_method;");
  428. }
  429. else
  430. throw new NotImplementedException();
  431. sb.AppendLine(" return __ret + 1;");
  432. }
  433. else
  434. {
  435. string isBox;
  436. if (type == typeof(object))
  437. isBox = ", true";
  438. else
  439. isBox = "";
  440. if (!type.IsSealed && type != typeof(ILRuntime.Runtime.Intepreter.ILTypeInstance))
  441. {
  442. if(domain == null || CheckAssignableToCrossBindingAdapters(domain, type))
  443. {
  444. sb.Append(@" object obj_result_of_this_method = result_of_this_method;
  445. if(obj_result_of_this_method is CrossBindingAdaptorType)
  446. {
  447. return ILIntepreter.PushObject(__ret, __mStack, ((CrossBindingAdaptorType)obj_result_of_this_method).ILInstance");
  448. sb.Append(isBox);
  449. sb.AppendLine(@");
  450. }");
  451. }
  452. else if (typeof(CrossBindingAdaptorType).IsAssignableFrom(type))
  453. {
  454. sb.AppendLine(string.Format(" return ILIntepreter.PushObject(__ret, __mStack, result_of_this_method.ILInstance{0});", isBox));
  455. return;
  456. }
  457. }
  458. sb.AppendLine(string.Format(" return ILIntepreter.PushObject(__ret, __mStack, result_of_this_method{0});", isBox));
  459. }
  460. }
  461. static bool CheckAssignableToCrossBindingAdapters(Enviorment.AppDomain domain, Type type)
  462. {
  463. if (type == typeof(object))
  464. return true;
  465. bool res = domain.CrossBindingAdaptors.ContainsKey(type);
  466. if (!res)
  467. {
  468. var baseType = type.BaseType;
  469. if (baseType != null && baseType != typeof(object))
  470. {
  471. res = CheckAssignableToCrossBindingAdapters(domain, baseType);
  472. }
  473. }
  474. if (!res)
  475. {
  476. var interfaces = type.GetInterfaces();
  477. foreach(var i in interfaces)
  478. {
  479. res = CheckAssignableToCrossBindingAdapters(domain, i);
  480. if (res)
  481. break;
  482. }
  483. }
  484. return res;
  485. }
  486. internal static bool HasByRefParam(this ParameterInfo[] param)
  487. {
  488. for (int j = param.Length; j > 0; j--)
  489. {
  490. var p = param[j - 1];
  491. if (p.ParameterType.IsByRef)
  492. return true;
  493. }
  494. return false;
  495. }
  496. }
  497. }