ConstructorBindingGenerator.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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. namespace ILRuntime.Runtime.CLRBinding
  8. {
  9. static class ConstructorBindingGenerator
  10. {
  11. internal static string GenerateConstructorRegisterCode(this Type type, ConstructorInfo[] methods, HashSet<MethodBase> excludes)
  12. {
  13. StringBuilder sb = new StringBuilder();
  14. int idx = 0;
  15. foreach (var i in methods)
  16. {
  17. if (excludes != null && excludes.Contains(i))
  18. continue;
  19. if (type.ShouldSkipMethod(i))
  20. continue;
  21. var param = i.GetParameters();
  22. StringBuilder sb2 = new StringBuilder();
  23. sb2.Append("{");
  24. bool first = true;
  25. foreach (var j in param)
  26. {
  27. if (first)
  28. first = false;
  29. else
  30. sb2.Append(", ");
  31. sb2.Append("typeof(");
  32. string clsName, realClsName;
  33. bool isByRef;
  34. j.ParameterType.GetClassName(out clsName, out realClsName, out isByRef);
  35. sb2.Append(realClsName);
  36. sb2.Append(")");
  37. if (isByRef)
  38. sb2.Append(".MakeByRefType()");
  39. }
  40. sb2.Append("}");
  41. sb.AppendLine(string.Format(" args = new Type[]{0};", sb2));
  42. sb.AppendLine(" method = type.GetConstructor(flag, null, args, null);");
  43. sb.AppendLine(string.Format(" app.RegisterCLRMethodRedirection(method, Ctor_{0});",idx));
  44. idx++;
  45. }
  46. return sb.ToString();
  47. }
  48. internal static string GenerateConstructorWraperCode(this Type type, ConstructorInfo[] methods, string typeClsName, HashSet<MethodBase> excludes, List<Type> valueTypeBinders)
  49. {
  50. StringBuilder sb = new StringBuilder();
  51. int idx = 0;
  52. bool isMultiArr = type.IsArray && type.GetArrayRank() > 1;
  53. foreach (var i in methods)
  54. {
  55. if (excludes != null && excludes.Contains(i))
  56. continue;
  57. if (type.ShouldSkipMethod(i) || i.IsStatic)
  58. continue;
  59. var param = i.GetParameters();
  60. int paramCnt = param.Length;
  61. sb.AppendLine(string.Format(" static StackObject* Ctor_{0}(ILIntepreter __intp, StackObject* __esp, IList<object> __mStack, CLRMethod __method, bool isNewObj)", idx));
  62. sb.AppendLine(" {");
  63. sb.AppendLine(" ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;");
  64. if (param.Length != 0)
  65. sb.AppendLine(" StackObject* ptr_of_this_method;");
  66. sb.AppendLine(string.Format(" StackObject* __ret = ILIntepreter.Minus(__esp, {0});", paramCnt));
  67. bool hasByRef = param.HasByRefParam();
  68. string shouldFreeParam = hasByRef ? "false" : "true";
  69. for (int j = param.Length; j > 0; j--)
  70. {
  71. var p = param[j - 1];
  72. sb.AppendLine(string.Format(" ptr_of_this_method = ILIntepreter.Minus(__esp, {0});", param.Length - j + 1));
  73. string clsName, realClsName;
  74. bool isByRef;
  75. p.ParameterType.GetClassName(out clsName, out realClsName, out isByRef);
  76. var pt = p.ParameterType.IsByRef ? p.ParameterType.GetElementType() : p.ParameterType;
  77. if (pt.IsValueType && !pt.IsPrimitive && valueTypeBinders != null && valueTypeBinders.Contains(pt))
  78. {
  79. if (isMultiArr)
  80. sb.AppendLine(string.Format(" {0} a{1} = new {0}();", realClsName, j));
  81. else
  82. sb.AppendLine(string.Format(" {0} @{1} = new {0}();", realClsName, p.Name));
  83. sb.AppendLine(string.Format(" if (ILRuntime.Runtime.Generated.CLRBindings.s_{0}_Binder != null) {{", clsName));
  84. if (isMultiArr)
  85. sb.AppendLine(string.Format(" ILRuntime.Runtime.Generated.CLRBindings.s_{1}_Binder.ParseValue(ref a{0}, __intp, ptr_of_this_method, __mStack, {2});", j, clsName, shouldFreeParam));
  86. else
  87. sb.AppendLine(string.Format(" ILRuntime.Runtime.Generated.CLRBindings.s_{1}_Binder.ParseValue(ref @{0}, __intp, ptr_of_this_method, __mStack, {2});", p.Name, clsName, shouldFreeParam));
  88. sb.AppendLine(" } else {");
  89. if (isByRef)
  90. sb.AppendLine(" ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method);");
  91. if (isMultiArr)
  92. sb.AppendLine(string.Format(" a{0} = {1};", j, p.ParameterType.GetRetrieveValueCode(realClsName)));
  93. else
  94. sb.AppendLine(string.Format(" @{0} = {1};", p.Name, p.ParameterType.GetRetrieveValueCode(realClsName)));
  95. if (!hasByRef)
  96. sb.AppendLine(" __intp.Free(ptr_of_this_method);");
  97. sb.AppendLine(" }");
  98. }
  99. else
  100. {
  101. if (isByRef)
  102. {
  103. if (p.ParameterType.GetElementType().IsPrimitive)
  104. {
  105. if (pt == typeof(int) || pt == typeof(uint) || pt == typeof(short) || pt == typeof(ushort) || pt == typeof(byte) || pt == typeof(sbyte) || pt == typeof(char))
  106. {
  107. if (pt == typeof(int))
  108. sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveInt32(ptr_of_this_method, __mStack);", realClsName, p.Name));
  109. else
  110. sb.AppendLine(string.Format(" {0} @{1} = ({0})__intp.RetriveInt32(ptr_of_this_method, __mStack);", realClsName, p.Name));
  111. }
  112. else if (pt == typeof(long) || pt == typeof(ulong))
  113. {
  114. if (pt == typeof(long))
  115. sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveInt64(ptr_of_this_method, __mStack);", realClsName, p.Name));
  116. else
  117. sb.AppendLine(string.Format(" {0} @{1} = ({0})__intp.RetriveInt64(ptr_of_this_method, __mStack);", realClsName, p.Name));
  118. }
  119. else if (pt == typeof(float))
  120. {
  121. sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveFloat(ptr_of_this_method, __mStack);", realClsName, p.Name));
  122. }
  123. else if (pt == typeof(double))
  124. {
  125. sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveDouble(ptr_of_this_method, __mStack);", realClsName, p.Name));
  126. }
  127. else if (pt == typeof(bool))
  128. {
  129. sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveInt32(ptr_of_this_method, __mStack) == 1;", realClsName, p.Name));
  130. }
  131. else
  132. throw new NotSupportedException();
  133. }
  134. else
  135. {
  136. sb.AppendLine(string.Format(" {0} @{1} = ({0})typeof({0}).CheckCLRTypes(__intp.RetriveObject(ptr_of_this_method, __mStack));", realClsName, p.Name));
  137. }
  138. }
  139. else
  140. {
  141. if (isMultiArr)
  142. sb.AppendLine(string.Format(" {0} a{1} = {2};", realClsName, j, p.ParameterType.GetRetrieveValueCode(realClsName)));
  143. else
  144. sb.AppendLine(string.Format(" {0} @{1} = {2};", realClsName, p.Name, p.ParameterType.GetRetrieveValueCode(realClsName)));
  145. if (!hasByRef && !p.ParameterType.IsPrimitive)
  146. sb.AppendLine(" __intp.Free(ptr_of_this_method);");
  147. }
  148. }
  149. sb.AppendLine();
  150. }
  151. sb.AppendLine();
  152. sb.Append(" var result_of_this_method = ");
  153. {
  154. string clsName, realClsName;
  155. bool isByRef;
  156. if (isMultiArr)
  157. {
  158. type.GetElementType().GetClassName(out clsName, out realClsName, out isByRef);
  159. sb.Append(string.Format("new {0}[", realClsName));
  160. param.AppendParameters(sb, isMultiArr);
  161. sb.AppendLine("];");
  162. }
  163. else
  164. {
  165. type.GetClassName(out clsName, out realClsName, out isByRef);
  166. sb.Append(string.Format("new {0}(", realClsName));
  167. param.AppendParameters(sb, isMultiArr);
  168. sb.AppendLine(");");
  169. }
  170. }
  171. sb.AppendLine();
  172. //Ref/Out
  173. for (int j = param.Length; j > 0; j--)
  174. {
  175. var p = param[j - 1];
  176. if (!p.ParameterType.IsByRef && !hasByRef)
  177. {
  178. continue;
  179. }
  180. string clsName, realClsName;
  181. bool isByRef;
  182. var pt = p.ParameterType.IsByRef ? p.ParameterType.GetElementType() : p.ParameterType;
  183. pt.GetClassName(out clsName, out realClsName, out isByRef);
  184. sb.AppendLine(string.Format(" ptr_of_this_method = ILIntepreter.Minus(__esp, {0});", param.Length - j + 1));
  185. if (p.ParameterType.IsByRef)
  186. {
  187. sb.AppendLine(@" switch(ptr_of_this_method->ObjectType)
  188. {
  189. case ObjectTypes.StackObjectReference:
  190. {
  191. var ___dst = ILIntepreter.ResolveReference(ptr_of_this_method);");
  192. if (p.ParameterType.IsValueType && !p.ParameterType.IsPrimitive && valueTypeBinders != null && valueTypeBinders.Contains(p.ParameterType))
  193. {
  194. sb.AppendLine(string.Format(" if (ILRuntime.Runtime.Generated.CLRBindings.s_{0}_Binder != null) {{", clsName));
  195. sb.AppendLine(string.Format(" ILRuntime.Runtime.Generated.CLRBindings.s_{0}_Binder.WriteBackValue(__domain, ptr_of_this_method, __mStack, ref {1});", realClsName, p.Name));
  196. sb.AppendLine(" } else {");
  197. p.ParameterType.GetElementType().GetRefWriteBackValueCode(sb, p.Name);
  198. sb.AppendLine(" }");
  199. }
  200. else
  201. {
  202. p.ParameterType.GetElementType().GetRefWriteBackValueCode(sb, p.Name);
  203. }
  204. sb.Append(@" }
  205. break;
  206. case ObjectTypes.FieldReference:
  207. {
  208. var ___obj = __mStack[ptr_of_this_method->Value];
  209. if(___obj is ILTypeInstance)
  210. {
  211. ((ILTypeInstance)___obj)[ptr_of_this_method->ValueLow] = ");
  212. sb.Append(p.Name);
  213. sb.Append(@";
  214. }
  215. else
  216. {
  217. var t = __domain.GetType(___obj.GetType()) as CLRType;
  218. t.SetFieldValue(ptr_of_this_method->ValueLow, ref ___obj, ");
  219. sb.Append(p.Name);
  220. sb.Append(@");
  221. }
  222. }
  223. break;
  224. case ObjectTypes.StaticFieldReference:
  225. {
  226. var t = __domain.GetType(ptr_of_this_method->Value);
  227. if(t is ILType)
  228. {
  229. ((ILType)t).StaticInstance[ptr_of_this_method->ValueLow] = ");
  230. sb.Append(p.Name);
  231. sb.Append(@";
  232. }
  233. else
  234. {
  235. ((CLRType)t).SetStaticFieldValue(ptr_of_this_method->ValueLow, ");
  236. sb.Append(p.Name);
  237. sb.Append(@");
  238. }
  239. }
  240. break;
  241. case ObjectTypes.ArrayReference:
  242. {
  243. var instance_of_arrayReference = __mStack[ptr_of_this_method->Value] as ");
  244. sb.Append(realClsName);
  245. sb.Append(@"[];
  246. instance_of_arrayReference[ptr_of_this_method->ValueLow] = ");
  247. sb.Append(p.Name);
  248. sb.AppendLine(@";
  249. }
  250. break;
  251. }");
  252. sb.AppendLine();
  253. }
  254. else if (pt.IsValueType && !pt.IsPrimitive)
  255. {
  256. sb.AppendLine(" __intp.FreeStackValueType(ptr_of_this_method);");
  257. }
  258. sb.AppendLine(" __intp.Free(ptr_of_this_method);");
  259. }
  260. if (type.IsValueType)
  261. {
  262. if (valueTypeBinders != null && valueTypeBinders.Contains(type))
  263. {
  264. string clsName, realClsName;
  265. bool isByRef;
  266. type.GetClassName(out clsName, out realClsName, out isByRef);
  267. sb.AppendLine(@" if(!isNewObj)
  268. {
  269. __ret--;");
  270. sb.AppendLine(string.Format(" if (ILRuntime.Runtime.Generated.CLRBindings.s_{0}_Binder != null) {{", clsName));
  271. sb.AppendLine(string.Format(" ILRuntime.Runtime.Generated.CLRBindings.s_{0}_Binder.WriteBackValue(__domain, __ret, __mStack, ref result_of_this_method);", clsName));
  272. sb.AppendLine(" } else {");
  273. sb.AppendLine(" WriteBackInstance(__domain, __ret, __mStack, ref result_of_this_method);");
  274. sb.AppendLine(" }");
  275. sb.AppendLine(@" return __ret;
  276. }");
  277. }
  278. else
  279. {
  280. sb.AppendLine(@" if(!isNewObj)
  281. {
  282. __ret--;
  283. WriteBackInstance(__domain, __ret, __mStack, ref result_of_this_method);
  284. return __ret;
  285. }");
  286. }
  287. sb.AppendLine();
  288. }
  289. if (type.IsValueType && valueTypeBinders != null && valueTypeBinders.Contains(type))
  290. {
  291. string clsName, realClsName;
  292. bool isByRef;
  293. type.GetClassName(out clsName, out realClsName, out isByRef);
  294. sb.AppendLine(string.Format(" if (ILRuntime.Runtime.Generated.CLRBindings.s_{0}_Binder != null) {{", clsName));
  295. sb.AppendLine(string.Format(" ILRuntime.Runtime.Generated.CLRBindings.s_{0}_Binder.PushValue(ref result_of_this_method, __intp, __ret, __mStack);", clsName));
  296. sb.AppendLine(" return __ret + 1;");
  297. sb.AppendLine(" } else {");
  298. sb.AppendLine(" return ILIntepreter.PushObject(__ret, __mStack, result_of_this_method);");
  299. sb.AppendLine(" }");
  300. }
  301. else
  302. {
  303. sb.AppendLine(" return ILIntepreter.PushObject(__ret, __mStack, result_of_this_method);");
  304. }
  305. sb.AppendLine(" }");
  306. sb.AppendLine();
  307. idx++;
  308. }
  309. return sb.ToString();
  310. }
  311. }
  312. }