/ src / Spv.Generator / LiteralInteger.cs
LiteralInteger.cs
  1  using System;
  2  using System.IO;
  3  
  4  namespace Spv.Generator
  5  {
  6      public class LiteralInteger : IOperand, IEquatable<LiteralInteger>
  7      {
  8          [ThreadStatic]
  9          private static GeneratorPool<LiteralInteger> _pool;
 10  
 11          internal static void RegisterPool(GeneratorPool<LiteralInteger> pool)
 12          {
 13              _pool = pool;
 14          }
 15  
 16          internal static void UnregisterPool()
 17          {
 18              _pool = null;
 19          }
 20  
 21          public OperandType Type => OperandType.Number;
 22  
 23          private enum IntegerType
 24          {
 25              UInt32,
 26              Int32,
 27              UInt64,
 28              Int64,
 29              Float32,
 30              Float64,
 31          }
 32  
 33          private IntegerType _integerType;
 34          private ulong _data;
 35  
 36          public ushort WordCount { get; private set; }
 37  
 38          public LiteralInteger() { }
 39  
 40          private static LiteralInteger New()
 41          {
 42              return _pool.Allocate();
 43          }
 44  
 45          private LiteralInteger Set(ulong data, IntegerType integerType, ushort wordCount)
 46          {
 47              _data = data;
 48              _integerType = integerType;
 49  
 50              WordCount = wordCount;
 51  
 52              return this;
 53          }
 54  
 55          public static implicit operator LiteralInteger(int value) => New().Set((ulong)value, IntegerType.Int32, 1);
 56          public static implicit operator LiteralInteger(uint value) => New().Set(value, IntegerType.UInt32, 1);
 57          public static implicit operator LiteralInteger(long value) => New().Set((ulong)value, IntegerType.Int64, 2);
 58          public static implicit operator LiteralInteger(ulong value) => New().Set(value, IntegerType.UInt64, 2);
 59          public static implicit operator LiteralInteger(float value) => New().Set(BitConverter.SingleToUInt32Bits(value), IntegerType.Float32, 1);
 60          public static implicit operator LiteralInteger(double value) => New().Set(BitConverter.DoubleToUInt64Bits(value), IntegerType.Float64, 2);
 61          public static implicit operator LiteralInteger(Enum value) => New().Set((ulong)(int)(object)value, IntegerType.Int32, 1);
 62  
 63          // NOTE: this is not in the standard, but this is some syntax sugar useful in some instructions (TypeInt ect)
 64          public static implicit operator LiteralInteger(bool value) => New().Set(Convert.ToUInt64(value), IntegerType.Int32, 1);
 65  
 66          public static LiteralInteger CreateForEnum<T>(T value) where T : Enum
 67          {
 68              return value;
 69          }
 70  
 71          public void WriteOperand(BinaryWriter writer)
 72          {
 73              if (WordCount == 1)
 74              {
 75                  writer.Write((uint)_data);
 76              }
 77              else
 78              {
 79                  writer.Write(_data);
 80              }
 81          }
 82  
 83          public override bool Equals(object obj)
 84          {
 85              return obj is LiteralInteger literalInteger && Equals(literalInteger);
 86          }
 87  
 88          public bool Equals(LiteralInteger cmpObj)
 89          {
 90              return Type == cmpObj.Type && _integerType == cmpObj._integerType && _data == cmpObj._data;
 91          }
 92  
 93          public override int GetHashCode()
 94          {
 95              return DeterministicHashCode.Combine(Type, _data);
 96          }
 97  
 98          public bool Equals(IOperand obj)
 99          {
100              return obj is LiteralInteger literalInteger && Equals(literalInteger);
101          }
102  
103          public override string ToString() => $"{_integerType} {_data}";
104      }
105  }