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 // See the LICENSE file in the project root for more information.
4 
5 namespace System.Reflection.Metadata
6 {
7     public static partial class ILOpCodeExtensions
8     {
9         /// <summary>
10         /// Returns true of the specified op-code is a branch to a label.
11         /// </summary>
IsBranch(this ILOpCode opCode)12         public static bool IsBranch(this ILOpCode opCode)
13         {
14             switch (opCode)
15             {
16                 case ILOpCode.Br:
17                 case ILOpCode.Br_s:
18                 case ILOpCode.Brtrue:
19                 case ILOpCode.Brtrue_s:
20                 case ILOpCode.Brfalse:
21                 case ILOpCode.Brfalse_s:
22                 case ILOpCode.Beq:
23                 case ILOpCode.Beq_s:
24                 case ILOpCode.Bne_un:
25                 case ILOpCode.Bne_un_s:
26                 case ILOpCode.Bge:
27                 case ILOpCode.Bge_s:
28                 case ILOpCode.Bge_un:
29                 case ILOpCode.Bge_un_s:
30                 case ILOpCode.Bgt:
31                 case ILOpCode.Bgt_s:
32                 case ILOpCode.Bgt_un:
33                 case ILOpCode.Bgt_un_s:
34                 case ILOpCode.Ble:
35                 case ILOpCode.Ble_s:
36                 case ILOpCode.Ble_un:
37                 case ILOpCode.Ble_un_s:
38                 case ILOpCode.Blt:
39                 case ILOpCode.Blt_s:
40                 case ILOpCode.Blt_un:
41                 case ILOpCode.Blt_un_s:
42                 case ILOpCode.Leave:
43                 case ILOpCode.Leave_s:
44                     return true;
45             }
46 
47             return false;
48         }
49 
50         /// <summary>
51         /// Calculate the size of the specified branch instruction operand.
52         /// </summary>
53         /// <param name="opCode">Branch op-code.</param>
54         /// <returns>1 if <paramref name="opCode"/> is a short branch or 4 if it is a long branch.</returns>
55         /// <exception cref="ArgumentException">Specified <paramref name="opCode"/> is not a branch op-code.</exception>
GetBranchOperandSize(this ILOpCode opCode)56         public static int GetBranchOperandSize(this ILOpCode opCode)
57         {
58             switch (opCode)
59             {
60                 case ILOpCode.Br_s:
61                 case ILOpCode.Brfalse_s:
62                 case ILOpCode.Brtrue_s:
63                 case ILOpCode.Beq_s:
64                 case ILOpCode.Bge_s:
65                 case ILOpCode.Bgt_s:
66                 case ILOpCode.Ble_s:
67                 case ILOpCode.Blt_s:
68                 case ILOpCode.Bne_un_s:
69                 case ILOpCode.Bge_un_s:
70                 case ILOpCode.Bgt_un_s:
71                 case ILOpCode.Ble_un_s:
72                 case ILOpCode.Blt_un_s:
73                 case ILOpCode.Leave_s:
74                     return 1;
75 
76                 case ILOpCode.Br:
77                 case ILOpCode.Brfalse:
78                 case ILOpCode.Brtrue:
79                 case ILOpCode.Beq:
80                 case ILOpCode.Bge:
81                 case ILOpCode.Bgt:
82                 case ILOpCode.Ble:
83                 case ILOpCode.Blt:
84                 case ILOpCode.Bne_un:
85                 case ILOpCode.Bge_un:
86                 case ILOpCode.Bgt_un:
87                 case ILOpCode.Ble_un:
88                 case ILOpCode.Blt_un:
89                 case ILOpCode.Leave:
90                     return 4;
91             }
92 
93             throw new ArgumentException(SR.Format(SR.UnexpectedOpCode, opCode), nameof(opCode));
94         }
95 
96         /// <summary>
97         /// Get a short form of the specified branch op-code.
98         /// </summary>
99         /// <param name="opCode">Branch op-code.</param>
100         /// <returns>Short form of the branch op-code.</returns>
101         /// <exception cref="ArgumentException">Specified <paramref name="opCode"/> is not a branch op-code.</exception>
GetShortBranch(this ILOpCode opCode)102         public static ILOpCode GetShortBranch(this ILOpCode opCode)
103         {
104             switch (opCode)
105             {
106                 case ILOpCode.Br_s:
107                 case ILOpCode.Brfalse_s:
108                 case ILOpCode.Brtrue_s:
109                 case ILOpCode.Beq_s:
110                 case ILOpCode.Bge_s:
111                 case ILOpCode.Bgt_s:
112                 case ILOpCode.Ble_s:
113                 case ILOpCode.Blt_s:
114                 case ILOpCode.Bne_un_s:
115                 case ILOpCode.Bge_un_s:
116                 case ILOpCode.Bgt_un_s:
117                 case ILOpCode.Ble_un_s:
118                 case ILOpCode.Blt_un_s:
119                 case ILOpCode.Leave_s:
120                     return opCode;
121 
122                 case ILOpCode.Br:
123                     return ILOpCode.Br_s;
124 
125                 case ILOpCode.Brfalse:
126                     return ILOpCode.Brfalse_s;
127 
128                 case ILOpCode.Brtrue:
129                     return ILOpCode.Brtrue_s;
130 
131                 case ILOpCode.Beq:
132                     return ILOpCode.Beq_s;
133 
134                 case ILOpCode.Bge:
135                     return ILOpCode.Bge_s;
136 
137                 case ILOpCode.Bgt:
138                     return ILOpCode.Bgt_s;
139 
140                 case ILOpCode.Ble:
141                     return ILOpCode.Ble_s;
142 
143                 case ILOpCode.Blt:
144                     return ILOpCode.Blt_s;
145 
146                 case ILOpCode.Bne_un:
147                     return ILOpCode.Bne_un_s;
148 
149                 case ILOpCode.Bge_un:
150                     return ILOpCode.Bge_un_s;
151 
152                 case ILOpCode.Bgt_un:
153                     return ILOpCode.Bgt_un_s;
154 
155                 case ILOpCode.Ble_un:
156                     return ILOpCode.Ble_un_s;
157 
158                 case ILOpCode.Blt_un:
159                     return ILOpCode.Blt_un_s;
160 
161                 case ILOpCode.Leave:
162                     return ILOpCode.Leave_s;
163             }
164 
165             throw new ArgumentException(SR.Format(SR.UnexpectedOpCode, opCode), nameof(opCode));
166         }
167 
168         /// <summary>
169         /// Get a long form of the specified branch op-code.
170         /// </summary>
171         /// <param name="opCode">Branch op-code.</param>
172         /// <returns>Long form of the branch op-code.</returns>
173         /// <exception cref="ArgumentException">Specified <paramref name="opCode"/> is not a branch op-code.</exception>
GetLongBranch(this ILOpCode opCode)174         public static ILOpCode GetLongBranch(this ILOpCode opCode)
175         {
176             switch (opCode)
177             {
178                 case ILOpCode.Br:
179                 case ILOpCode.Brfalse:
180                 case ILOpCode.Brtrue:
181                 case ILOpCode.Beq:
182                 case ILOpCode.Bge:
183                 case ILOpCode.Bgt:
184                 case ILOpCode.Ble:
185                 case ILOpCode.Blt:
186                 case ILOpCode.Bne_un:
187                 case ILOpCode.Bge_un:
188                 case ILOpCode.Bgt_un:
189                 case ILOpCode.Ble_un:
190                 case ILOpCode.Blt_un:
191                 case ILOpCode.Leave:
192                     return opCode;
193 
194                 case ILOpCode.Br_s:
195                     return ILOpCode.Br;
196 
197                 case ILOpCode.Brfalse_s:
198                     return ILOpCode.Brfalse;
199 
200                 case ILOpCode.Brtrue_s:
201                     return ILOpCode.Brtrue;
202 
203                 case ILOpCode.Beq_s:
204                     return ILOpCode.Beq;
205 
206                 case ILOpCode.Bge_s:
207                     return ILOpCode.Bge;
208 
209                 case ILOpCode.Bgt_s:
210                     return ILOpCode.Bgt;
211 
212                 case ILOpCode.Ble_s:
213                     return ILOpCode.Ble;
214 
215                 case ILOpCode.Blt_s:
216                     return ILOpCode.Blt;
217 
218                 case ILOpCode.Bne_un_s:
219                     return ILOpCode.Bne_un;
220 
221                 case ILOpCode.Bge_un_s:
222                     return ILOpCode.Bge_un;
223 
224                 case ILOpCode.Bgt_un_s:
225                     return ILOpCode.Bgt_un;
226 
227                 case ILOpCode.Ble_un_s:
228                     return ILOpCode.Ble_un;
229 
230                 case ILOpCode.Blt_un_s:
231                     return ILOpCode.Blt_un;
232 
233                 case ILOpCode.Leave_s:
234                     return ILOpCode.Leave;
235             }
236 
237             throw new ArgumentException(SR.Format(SR.UnexpectedOpCode, opCode), nameof(opCode));
238         }
239     }
240 }
241