IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
OpCode.cs
Go to the documentation of this file.
1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3
4#nullable enable
5
6using System.Threading;
7using System.Diagnostics.CodeAnalysis;
8using System;
9
11{
12 internal readonly struct OpCode : IEquatable<OpCode>
13 {
14 //
15 // Use packed bitfield for flags to avoid code bloat
16 //
17
18 internal const int OperandTypeMask = 0x1F; // 000000000000000000000000000XXXXX
19
20 internal const int FlowControlShift = 5; // 00000000000000000000000XXXX00000
21 internal const int FlowControlMask = 0x0F;
22
23 internal const int OpCodeTypeShift = 9; // 00000000000000000000XXX000000000
24 internal const int OpCodeTypeMask = 0x07;
25
26 internal const int StackBehaviourPopShift = 12; // 000000000000000XXXXX000000000000
27 internal const int StackBehaviourPushShift = 17; // 0000000000XXXXX00000000000000000
28 internal const int StackBehaviourMask = 0x1F;
29
30 internal const int SizeShift = 22; // 00000000XX0000000000000000000000
31 internal const int SizeMask = 0x03;
32
33 internal const int EndsUncondJmpBlkFlag = 0x01000000; // 0000000X000000000000000000000000
34
35 // unused // 0000XXX0000000000000000000000000
36
37 internal const int StackChangeShift = 28; // XXXX0000000000000000000000000000
38
39 private readonly OpCodeValues m_value;
40 private readonly int m_flags;
41
42 internal OpCode(OpCodeValues value, int flags)
43 {
44 m_value = value;
45 m_flags = flags;
46 }
47
48 internal bool EndsUncondJmpBlk() =>
49 (m_flags & EndsUncondJmpBlkFlag) != 0;
50
51 internal int StackChange() =>
52 m_flags >> StackChangeShift;
53
54 public OperandType OperandType => (OperandType)(m_flags & OperandTypeMask);
55
56 public FlowControl FlowControl => (FlowControl)((m_flags >> FlowControlShift) & FlowControlMask);
57
58 public OpCodeType OpCodeType => (OpCodeType)((m_flags >> OpCodeTypeShift) & OpCodeTypeMask);
59
60 public StackBehaviour StackBehaviourPop => (StackBehaviour)((m_flags >> StackBehaviourPopShift) & StackBehaviourMask);
61
62 public StackBehaviour StackBehaviourPush => (StackBehaviour)((m_flags >> StackBehaviourPushShift) & StackBehaviourMask);
63
64 public int Size => (m_flags >> SizeShift) & SizeMask;
65
66 public short Value => (short)m_value;
67
68 private static volatile string[]? g_nameCache;
69
70 public string? Name
71 {
72 get
73 {
74 if (Size == 0)
75 return null;
76
77 // Create and cache the opcode names lazily. They should be rarely used (only for logging, etc.)
78 // Note that we do not any locks here because of we always get the same names. The last one wins.
79 string[]? nameCache = g_nameCache;
80 if (nameCache == null)
81 {
82 nameCache = new string[0x11f];
83 g_nameCache = nameCache;
84 }
85
86 OpCodeValues opCodeValue = (OpCodeValues)(ushort)Value;
87
88 int idx = (int)opCodeValue;
89 if (idx > 0xFF)
90 {
91 if (idx >= 0xfe00 && idx <= 0xfe1e)
92 {
93 // Transform two byte opcode value to lower range that's suitable
94 // for array index
95 idx = 0x100 + (idx - 0xfe00);
96 }
97 else
98 {
99 // Unknown opcode
100 return null;
101 }
102 }
103
104 string name = Volatile.Read(ref nameCache[idx]);
105 if (name != null)
106 return name;
107
108 // Create ilasm style name from the enum value name.
109 name = GetEnumName(opCodeValue)!.ToLowerInvariant().Replace('_', '.');
110 Volatile.Write(ref nameCache[idx], name);
111 return name;
112 }
113 }
114
115 string? GetEnumName<T>(T value) where T : struct, Enum
116 {
117#if NETFRAMEWORK
118 return Enum.GetName(typeof(T), value);
119#else
120 return Enum.GetName(value);
121#endif
122 }
123
124 public override bool Equals(object? obj) =>
125 obj is OpCode other && Equals(other);
126
127 public bool Equals(OpCode obj) => obj.Value == Value;
128
129 public static bool operator ==(OpCode a, OpCode b) => a.Equals(b);
130
131 public static bool operator !=(OpCode a, OpCode b) => !(a == b);
132
133 public override int GetHashCode() => Value;
134
135 public override string? ToString() => Name;
136 }
137}
138
139#nullable restore
global::java.lang.invoke.LambdaForm.Name Name