ILMethodBuilder.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. using ChocolArm64.State;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Reflection.Emit;
  5. using System.Runtime.Intrinsics;
  6. namespace ChocolArm64.Translation
  7. {
  8. class ILMethodBuilder
  9. {
  10. private const int RegsCount = 32;
  11. private const int RegsMask = RegsCount - 1;
  12. public RegisterUsage RegUsage { get; private set; }
  13. public ILGenerator Generator { get; private set; }
  14. private Dictionary<Register, int> _locals;
  15. private ILBlock[] _ilBlocks;
  16. private string _subName;
  17. public bool IsAarch64 { get; }
  18. public bool IsSubComplete { get; }
  19. private int _localsCount;
  20. public ILMethodBuilder(
  21. ILBlock[] ilBlocks,
  22. string subName,
  23. bool isAarch64,
  24. bool isSubComplete = false)
  25. {
  26. _ilBlocks = ilBlocks;
  27. _subName = subName;
  28. IsAarch64 = isAarch64;
  29. IsSubComplete = isSubComplete;
  30. }
  31. public TranslatedSub GetSubroutine(TranslationTier tier, bool isWorthOptimizing)
  32. {
  33. RegUsage = new RegisterUsage();
  34. RegUsage.BuildUses(_ilBlocks[0]);
  35. DynamicMethod method = new DynamicMethod(_subName, typeof(long), TranslatedSub.FixedArgTypes);
  36. long intNiRegsMask = RegUsage.GetIntNotInputs(_ilBlocks[0]);
  37. long vecNiRegsMask = RegUsage.GetVecNotInputs(_ilBlocks[0]);
  38. TranslatedSub subroutine = new TranslatedSub(
  39. method,
  40. intNiRegsMask,
  41. vecNiRegsMask,
  42. tier,
  43. isWorthOptimizing);
  44. _locals = new Dictionary<Register, int>();
  45. _localsCount = 0;
  46. Generator = method.GetILGenerator();
  47. foreach (ILBlock ilBlock in _ilBlocks)
  48. {
  49. ilBlock.Emit(this);
  50. }
  51. subroutine.PrepareMethod();
  52. return subroutine;
  53. }
  54. public int GetLocalIndex(Register reg)
  55. {
  56. if (!_locals.TryGetValue(reg, out int index))
  57. {
  58. Generator.DeclareLocal(GetFieldType(reg.Type));
  59. index = _localsCount++;
  60. _locals.Add(reg, index);
  61. }
  62. return index;
  63. }
  64. private static Type GetFieldType(RegisterType regType)
  65. {
  66. switch (regType)
  67. {
  68. case RegisterType.Flag: return typeof(bool);
  69. case RegisterType.Int: return typeof(ulong);
  70. case RegisterType.Vector: return typeof(Vector128<float>);
  71. }
  72. throw new ArgumentException(nameof(regType));
  73. }
  74. public static Register GetRegFromBit(int bit, RegisterType baseType)
  75. {
  76. if (bit < RegsCount)
  77. {
  78. return new Register(bit, baseType);
  79. }
  80. else if (baseType == RegisterType.Int)
  81. {
  82. return new Register(bit & RegsMask, RegisterType.Flag);
  83. }
  84. else
  85. {
  86. throw new ArgumentOutOfRangeException(nameof(bit));
  87. }
  88. }
  89. public static bool IsRegIndex(int index)
  90. {
  91. return (uint)index < RegsCount;
  92. }
  93. }
  94. }