OpCode.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Runtime.InteropServices;
  6. using ILRuntime.CLR.Method;
  7. namespace ILRuntime.Runtime.Intepreter.OpCodes
  8. {
  9. /// <summary>
  10. /// IL指令
  11. /// </summary>
  12. struct OpCode
  13. {
  14. /// <summary>
  15. /// 当前指令
  16. /// </summary>
  17. public OpCodeEnum Code;
  18. /// <summary>
  19. /// Int32 操作数
  20. /// </summary>
  21. public int TokenInteger;
  22. /// <summary>
  23. /// Int64 操作数
  24. /// </summary>
  25. public long TokenLong;
  26. }
  27. /// <summary>
  28. /// Register machine opcode
  29. /// </summary>
  30. [StructLayout(LayoutKind.Explicit)]
  31. struct OpCodeR
  32. {
  33. [FieldOffset(0)]
  34. public OpCodeREnum Code;
  35. [FieldOffset(4)]
  36. public short Register1;
  37. [FieldOffset(6)]
  38. public short Register2;
  39. [FieldOffset(8)]
  40. public short Register3;
  41. [FieldOffset(10)]
  42. public short Register4;
  43. [FieldOffset(8)]
  44. public int Operand;
  45. [FieldOffset(8)]
  46. public float OperandFloat;
  47. [FieldOffset(12)]
  48. public int Operand2;
  49. [FieldOffset(16)]
  50. public int Operand3;
  51. [FieldOffset(12)]
  52. public long OperandLong;
  53. [FieldOffset(12)]
  54. public double OperandDouble;
  55. [FieldOffset(20)]
  56. public int Operand4;
  57. public override string ToString()
  58. {
  59. return ToString(null);
  60. }
  61. public string ToString(Enviorment.AppDomain domain)
  62. {
  63. string param = null;
  64. switch (Code)
  65. {
  66. case OpCodeREnum.Move:
  67. case OpCodeREnum.Ldind_I:
  68. case OpCodeREnum.Ldind_I1:
  69. case OpCodeREnum.Ldind_I2:
  70. case OpCodeREnum.Ldind_I4:
  71. case OpCodeREnum.Ldind_I8:
  72. case OpCodeREnum.Ldind_R4:
  73. case OpCodeREnum.Ldind_R8:
  74. case OpCodeREnum.Ldind_U1:
  75. case OpCodeREnum.Ldind_U2:
  76. case OpCodeREnum.Ldind_U4:
  77. case OpCodeREnum.Ldind_Ref:
  78. case OpCodeREnum.Ldobj:
  79. case OpCodeREnum.Stind_I:
  80. case OpCodeREnum.Stind_I1:
  81. case OpCodeREnum.Stind_I2:
  82. case OpCodeREnum.Stind_I4:
  83. case OpCodeREnum.Stind_I8:
  84. case OpCodeREnum.Stind_R4:
  85. case OpCodeREnum.Stind_R8:
  86. case OpCodeREnum.Stind_Ref:
  87. case OpCodeREnum.Stobj:
  88. case OpCodeREnum.Ldloca:
  89. case OpCodeREnum.Ldloca_S:
  90. case OpCodeREnum.Ldarga:
  91. case OpCodeREnum.Ldarga_S:
  92. case OpCodeREnum.Conv_I:
  93. case OpCodeREnum.Conv_I1:
  94. case OpCodeREnum.Conv_I2:
  95. case OpCodeREnum.Conv_I4:
  96. case OpCodeREnum.Conv_I8:
  97. case OpCodeREnum.Conv_Ovf_I:
  98. case OpCodeREnum.Conv_Ovf_I1:
  99. case OpCodeREnum.Conv_Ovf_I1_Un:
  100. case OpCodeREnum.Conv_Ovf_I2:
  101. case OpCodeREnum.Conv_Ovf_I2_Un:
  102. case OpCodeREnum.Conv_Ovf_I4:
  103. case OpCodeREnum.Conv_Ovf_I4_Un:
  104. case OpCodeREnum.Conv_Ovf_I8:
  105. case OpCodeREnum.Conv_Ovf_I8_Un:
  106. case OpCodeREnum.Conv_Ovf_I_Un:
  107. case OpCodeREnum.Conv_Ovf_U:
  108. case OpCodeREnum.Conv_Ovf_U1:
  109. case OpCodeREnum.Conv_Ovf_U1_Un:
  110. case OpCodeREnum.Conv_Ovf_U2:
  111. case OpCodeREnum.Conv_Ovf_U2_Un:
  112. case OpCodeREnum.Conv_Ovf_U4:
  113. case OpCodeREnum.Conv_Ovf_U4_Un:
  114. case OpCodeREnum.Conv_Ovf_U8:
  115. case OpCodeREnum.Conv_Ovf_U8_Un:
  116. case OpCodeREnum.Conv_Ovf_U_Un:
  117. case OpCodeREnum.Conv_R4:
  118. case OpCodeREnum.Conv_R8:
  119. case OpCodeREnum.Conv_R_Un:
  120. case OpCodeREnum.Conv_U:
  121. case OpCodeREnum.Conv_U1:
  122. case OpCodeREnum.Conv_U2:
  123. case OpCodeREnum.Conv_U4:
  124. case OpCodeREnum.Conv_U8:
  125. case OpCodeREnum.Not:
  126. case OpCodeREnum.Neg:
  127. param = string.Format("r{0}, r{1}", Register1, Register2);
  128. break;
  129. case OpCodeREnum.Box:
  130. case OpCodeREnum.Unbox:
  131. case OpCodeREnum.Unbox_Any:
  132. case OpCodeREnum.Isinst:
  133. if (domain == null)
  134. param = string.Format("r{0}, r{1}, {2}", Register1, Register2, Operand);
  135. else
  136. {
  137. var type = domain.GetType(Operand);
  138. param = string.Format("r{0}, r{1}, {2}", Register1, Register2, type);
  139. }
  140. break;
  141. case OpCodeREnum.Stfld:
  142. case OpCodeREnum.Ldfld:
  143. param = string.Format("r{0}, r{1}, 0x{2:X8}", Register1, Register2, OperandLong);
  144. break;
  145. case OpCodeREnum.Stsfld:
  146. case OpCodeREnum.Ldsfld:
  147. param = string.Format("r{0}, 0x{1:X8}", Register1, OperandLong);
  148. break;
  149. case OpCodeREnum.Beqi:
  150. case OpCodeREnum.Bgei:
  151. case OpCodeREnum.Bgei_Un:
  152. case OpCodeREnum.Bgti:
  153. case OpCodeREnum.Bgti_Un:
  154. case OpCodeREnum.Bnei_Un:
  155. case OpCodeREnum.Blei:
  156. case OpCodeREnum.Blei_Un:
  157. case OpCodeREnum.Blti:
  158. case OpCodeREnum.Blti_Un:
  159. if (Operand != 0)
  160. {
  161. param = string.Format("r{0},{1},{2}", Register1, Operand, Operand4);
  162. }
  163. else if (OperandLong != 0)
  164. {
  165. param = string.Format("r{0},{1},{2}", Register1, OperandLong, Operand4);
  166. }
  167. else if (OperandFloat != 0)
  168. {
  169. param = string.Format("r{0},{1},{2}", Register1, OperandFloat, Operand4);
  170. }
  171. else if (OperandDouble != 0)
  172. {
  173. param = string.Format("r{0},{1},{2}", Register1, OperandDouble, Operand4);
  174. }
  175. else
  176. {
  177. param = string.Format("r{0},0,{1}", Register1, Operand4);
  178. }
  179. break;
  180. case OpCodeREnum.Ceqi:
  181. case OpCodeREnum.Cgti:
  182. case OpCodeREnum.Cgti_Un:
  183. case OpCodeREnum.Clti:
  184. case OpCodeREnum.Clti_Un:
  185. case OpCodeREnum.Addi:
  186. case OpCodeREnum.Subi:
  187. case OpCodeREnum.Muli:
  188. case OpCodeREnum.Divi:
  189. case OpCodeREnum.Remi:
  190. case OpCodeREnum.Remi_Un:
  191. case OpCodeREnum.Andi:
  192. case OpCodeREnum.Ori:
  193. case OpCodeREnum.Xori:
  194. case OpCodeREnum.Shli:
  195. case OpCodeREnum.Shri:
  196. case OpCodeREnum.Shri_Un:
  197. if (Operand != 0)
  198. {
  199. param = string.Format("r{0},r{1},{2}", Register1, Register2, Operand);
  200. }
  201. else if (OperandLong != 0)
  202. {
  203. param = string.Format("r{0},r{1},{2}", Register1, Register2, OperandLong);
  204. }
  205. else if (OperandFloat != 0)
  206. {
  207. param = string.Format("r{0},r{1},{2}", Register1, Register2, OperandFloat);
  208. }
  209. else if (OperandDouble != 0)
  210. {
  211. param = string.Format("r{0},r{1},{2}", Register1, Register2, OperandDouble);
  212. }
  213. else
  214. {
  215. param = string.Format("r{0},r{1},0", Register1, Register2);
  216. }
  217. break;
  218. case OpCodeREnum.Add:
  219. case OpCodeREnum.Add_Ovf:
  220. case OpCodeREnum.Add_Ovf_Un:
  221. case OpCodeREnum.Sub:
  222. case OpCodeREnum.Sub_Ovf:
  223. case OpCodeREnum.Sub_Ovf_Un:
  224. case OpCodeREnum.Mul:
  225. case OpCodeREnum.Mul_Ovf:
  226. case OpCodeREnum.Mul_Ovf_Un:
  227. case OpCodeREnum.Div:
  228. case OpCodeREnum.Div_Un:
  229. case OpCodeREnum.Rem:
  230. case OpCodeREnum.Rem_Un:
  231. case OpCodeREnum.Xor:
  232. case OpCodeREnum.And:
  233. case OpCodeREnum.Or:
  234. case OpCodeREnum.Shl:
  235. case OpCodeREnum.Shr:
  236. case OpCodeREnum.Shr_Un:
  237. case OpCodeREnum.Clt:
  238. case OpCodeREnum.Clt_Un:
  239. case OpCodeREnum.Cgt:
  240. case OpCodeREnum.Cgt_Un:
  241. case OpCodeREnum.Ceq:
  242. case OpCodeREnum.Stelem_I1:
  243. case OpCodeREnum.Stelem_I2:
  244. case OpCodeREnum.Stelem_I:
  245. case OpCodeREnum.Stelem_I4:
  246. case OpCodeREnum.Stelem_R4:
  247. case OpCodeREnum.Stelem_R8:
  248. case OpCodeREnum.Stelem_Any:
  249. case OpCodeREnum.Stelem_Ref:
  250. case OpCodeREnum.Ldelem_I1:
  251. case OpCodeREnum.Ldelem_I2:
  252. case OpCodeREnum.Ldelem_I:
  253. case OpCodeREnum.Ldelem_I4:
  254. case OpCodeREnum.Ldelem_R4:
  255. case OpCodeREnum.Ldelem_R8:
  256. case OpCodeREnum.Ldelem_Ref:
  257. case OpCodeREnum.Ldelem_Any:
  258. case OpCodeREnum.Ldelema:
  259. param = string.Format("r{0},r{1},r{2}", Register1, Register2, Register3);
  260. break;
  261. case OpCodeREnum.Ldc_I4_0:
  262. case OpCodeREnum.Ldc_I4_1:
  263. case OpCodeREnum.Ldc_I4_2:
  264. case OpCodeREnum.Ldc_I4_3:
  265. case OpCodeREnum.Ldc_I4_4:
  266. case OpCodeREnum.Ldc_I4_5:
  267. case OpCodeREnum.Ldc_I4_6:
  268. case OpCodeREnum.Ldc_I4_7:
  269. case OpCodeREnum.Ldc_I4_8:
  270. case OpCodeREnum.Ldc_I4_M1:
  271. case OpCodeREnum.Ldnull:
  272. case OpCodeREnum.Ret:
  273. case OpCodeREnum.Push:
  274. param = string.Format("r{0}", Register1);
  275. break;
  276. case OpCodeREnum.Brtrue:
  277. case OpCodeREnum.Brtrue_S:
  278. case OpCodeREnum.Brfalse:
  279. case OpCodeREnum.Brfalse_S:
  280. case OpCodeREnum.Switch:
  281. param = string.Format("r{0}, {1}", Register1, Operand);
  282. break;
  283. case OpCodeREnum.Ldftn:
  284. if (domain == null)
  285. {
  286. param = string.Format("r{0}, {1}", Register1, Operand2);
  287. }
  288. else
  289. {
  290. IMethod m = domain.GetMethod(Operand2);
  291. if (m is CLR.Method.CLRMethod)
  292. param = m != null ? string.Format("r{0}, {1}::{2}", Register1, m.DeclearingType.FullName, m) : string.Format("r{0}, {1}", Register1, Operand2);
  293. else
  294. param = m != null ? string.Format("r{0}, {1}", Register1, m) : string.Format("r{0}, {1}", Register1, Operand2);
  295. }
  296. break;
  297. case OpCodeREnum.Ldvirtftn:
  298. if (domain == null)
  299. {
  300. param = string.Format("r{0}, r{1} {2}", Register1, Register2, Operand2);
  301. }
  302. else
  303. {
  304. IMethod m = domain.GetMethod(Operand2);
  305. if (m is CLR.Method.CLRMethod)
  306. param = m != null ? string.Format("r{0}, r{1}, {2}::{3}", Register1, Register2, m.DeclearingType.FullName, m) : string.Format("r{0}, r{1}, {2}", Register1, Register2, Operand2);
  307. else
  308. param = m != null ? string.Format("r{0}, r{1}, {2}", Register1, Register2, m) : string.Format("r{0}, r{1}, {2}", Register1, Register2, Operand2);
  309. }
  310. break;
  311. case OpCodeREnum.Constrained:
  312. {
  313. if (domain == null)
  314. {
  315. param = Operand.ToString();
  316. }
  317. else
  318. {
  319. var m = domain.GetType(Operand);
  320. param = m != null ? m.ToString() : Operand.ToString();
  321. }
  322. }
  323. break;
  324. case OpCodeREnum.Call:
  325. case OpCodeREnum.Callvirt:
  326. case OpCodeREnum.Newobj:
  327. {
  328. string retR = Register1 >= 0 ? "r" + Register1 : "-";
  329. if (Register2 >= 0)
  330. retR += ", r" + Register2;
  331. if (Register3 >= 0)
  332. retR += ", r" + Register3;
  333. if (Register4 >= 0)
  334. retR += ", r" + Register4;
  335. if (domain == null)
  336. {
  337. param = string.Format("{0}, {1}", retR, Operand2);
  338. }
  339. else
  340. {
  341. IMethod m = domain.GetMethod(Operand2);
  342. if (m is CLR.Method.CLRMethod)
  343. param = m != null ? string.Format("{0}, {1}::{2}", retR, m.DeclearingType.FullName, m) : string.Format("{0}, {1}", retR, Operand2);
  344. else
  345. param = m != null ? string.Format("{0}, {1}", retR, m) : string.Format("{0}, {1}", retR, Operand2);
  346. }
  347. }
  348. break;
  349. case OpCodeREnum.Blt:
  350. case OpCodeREnum.Blt_S:
  351. case OpCodeREnum.Blt_Un:
  352. case OpCodeREnum.Blt_Un_S:
  353. case OpCodeREnum.Ble:
  354. case OpCodeREnum.Ble_S:
  355. case OpCodeREnum.Ble_Un:
  356. case OpCodeREnum.Ble_Un_S:
  357. case OpCodeREnum.Bgt:
  358. case OpCodeREnum.Bgt_S:
  359. case OpCodeREnum.Bgt_Un:
  360. case OpCodeREnum.Bgt_Un_S:
  361. case OpCodeREnum.Bge:
  362. case OpCodeREnum.Bge_S:
  363. case OpCodeREnum.Bge_Un:
  364. case OpCodeREnum.Bge_Un_S:
  365. case OpCodeREnum.Beq:
  366. case OpCodeREnum.Beq_S:
  367. case OpCodeREnum.Bne_Un:
  368. case OpCodeREnum.Bne_Un_S:
  369. param = string.Format("r{0}, r{1}, {2}", Register1, Register2, Operand);
  370. break;
  371. case OpCodeREnum.Br:
  372. case OpCodeREnum.Br_S:
  373. case OpCodeREnum.Leave:
  374. case OpCodeREnum.Leave_S:
  375. param = string.Format("{0}", Operand);
  376. break;
  377. case OpCodeREnum.Ldc_I4:
  378. case OpCodeREnum.Ldc_I4_S:
  379. param = string.Format("r{0},{1}", Register1, Operand);
  380. break;
  381. case OpCodeREnum.Ldc_I8:
  382. param = string.Format("r{0},{1}", Register1, OperandLong);
  383. break;
  384. case OpCodeREnum.Ldc_R4:
  385. param = string.Format("r{0},{1}", Register1, OperandFloat);
  386. break;
  387. case OpCodeREnum.Ldc_R8:
  388. param = string.Format("r{0},{1}", Register1, OperandDouble);
  389. break;
  390. case OpCodeREnum.Ldstr:
  391. if (domain == null)
  392. param = string.Format("r{0},0x{1:X}", Register1, OperandLong);
  393. else
  394. param = string.Format("r{0},\"{1}\"", Register1, domain.GetString(OperandLong));
  395. break;
  396. case OpCodeREnum.Ldtoken:
  397. if (domain == null)
  398. param = string.Format("r{0},0x{1:X}", Register1, OperandLong);
  399. else
  400. {
  401. switch (Operand)
  402. {
  403. case 0:
  404. {
  405. var type = domain.GetType((int)(OperandLong >> 32));
  406. int fieldIdx = (int)OperandLong;
  407. param = string.Format("r{0},{1}.{2}", Register1, type.FullName, (type is CLR.TypeSystem.ILType) ? ((CLR.TypeSystem.ILType)type).TypeDefinition.Fields[fieldIdx].Name : ((CLR.TypeSystem.CLRType)type).Fields[fieldIdx].Name);
  408. }
  409. break;
  410. case 1:
  411. {
  412. var type = domain.GetType((int)OperandLong);
  413. param = string.Format("r{0},\"{1}\"", Register1, type);
  414. }
  415. break;
  416. default:
  417. throw new NotImplementedException();
  418. }
  419. }
  420. break;
  421. case OpCodeREnum.Initobj:
  422. if (domain == null)
  423. param = string.Format("r{0}, {1}", Register1, Operand);
  424. else
  425. {
  426. var type = domain.GetType(Operand);
  427. param = string.Format("r{0}, {1}", Register1, type);
  428. }
  429. break;
  430. case OpCodeREnum.Newarr:
  431. if (domain == null)
  432. param = string.Format("r{0}, r{1}", Register1, Register2);
  433. else
  434. {
  435. var type = domain.GetType(Operand);
  436. param = string.Format("r{0}, {2}, r{1}", Register1, Register2, type);
  437. }
  438. break;
  439. }
  440. return string.Format("{0} {1}", Code.ToString().ToLower().Replace('_', '.'), param);
  441. }
  442. }
  443. }