Skip to main content

clr_assembler/program/
instructions.rs

1use super::types::ClrTypeReference;
2
3/// CLR opcode enumeration representing all Common Language Runtime instructions.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub enum ClrOpcode {
6    /// No operation.
7    Nop,
8    /// Load constant integer -1 onto the stack.
9    LdcI4M1,
10    /// Load constant integer 0 onto the stack.
11    LdcI40,
12    /// Load constant integer 1 onto the stack.
13    LdcI41,
14    /// Load constant integer 2 onto the stack.
15    LdcI42,
16    /// Load constant integer 3 onto the stack.
17    LdcI43,
18    /// Load constant integer 4 onto the stack.
19    LdcI44,
20    /// Load constant integer 5 onto the stack.
21    LdcI45,
22    /// Load constant integer 6 onto the stack.
23    LdcI46,
24    /// Load constant integer 7 onto the stack.
25    LdcI47,
26    /// Load constant integer 8 onto the stack.
27    LdcI48,
28    /// Load constant integer (signed byte) onto the stack.
29    LdcI4S,
30    /// Load constant int32 onto the stack.
31    LdcI4,
32    /// Load constant int64 onto the stack.
33    LdcI8,
34    /// Load constant float32 onto the stack.
35    LdcR4,
36    /// Load constant float64 onto the stack.
37    LdcR8,
38    /// Load null reference onto the stack.
39    Ldnull,
40    /// Load a string literal onto the stack.
41    Ldstr,
42    /// Load argument 0 onto the stack.
43    Ldarg0,
44    /// Load argument 1 onto the stack.
45    Ldarg1,
46    /// Load argument 2 onto the stack.
47    Ldarg2,
48    /// Load argument 3 onto the stack.
49    Ldarg3,
50    /// Load local variable 0 onto the stack.
51    Ldloc0,
52    /// Load local variable 1 onto the stack.
53    Ldloc1,
54    /// Load local variable 2
55    Ldloc2,
56    /// Load local variable 3
57    Ldloc3,
58    /// Store local variable 0
59    Stloc0,
60    /// Store local variable 1
61    Stloc1,
62    /// Store local variable 2
63    Stloc2,
64    /// Store local variable 3
65    Stloc3,
66    /// Call method
67    Call,
68    /// Call virtual method
69    Callvirt,
70    /// Return
71    Ret,
72    /// Create new object
73    Newobj,
74    /// Pop from stack
75    Pop,
76    /// Duplicate top of stack
77    Dup,
78    /// Add
79    Add,
80    /// Subtract
81    Sub,
82    /// Multiply
83    Mul,
84    /// Divide
85    Div,
86    /// Compare equal
87    Ceq,
88    /// Compare greater than
89    Cgt,
90    /// Compare less than
91    Clt,
92    /// Logical AND
93    And,
94    /// Logical OR
95    Or,
96    /// Branch
97    Br,
98    /// Branch if true
99    Brtrue,
100    /// Branch if false
101    Brfalse,
102    /// Load local variable
103    Ldloc,
104    /// Store local variable
105    Stloc,
106    /// Load argument
107    Ldarg,
108    /// Store argument
109    Starg,
110    /// Load local address
111    Ldloca,
112    /// Load field
113    Ldfld,
114    /// Store field
115    Stfld,
116    /// Load element
117    Ldelem,
118    /// Store element
119    Stelem,
120    /// Load array length
121    Ldlen,
122    /// Create new array
123    Newarr,
124    /// Box value type
125    Box,
126    /// Unbox value type
127    Unbox,
128    /// Convert to int32
129    ConvI4,
130    /// Convert to int64
131    ConvI8,
132    /// Convert to float32
133    ConvR4,
134    /// Convert to float64
135    ConvR8,
136    /// Load indirect int32
137    LdindI4,
138    /// Load indirect int64
139    LdindI8,
140    /// Load indirect float32
141    LdindR4,
142    /// Load indirect float64
143    LdindR8,
144    /// Load indirect reference
145    LdindRef,
146    /// Store indirect int32
147    StindI4,
148    /// Store indirect int64
149    StindI8,
150    /// Store indirect float32
151    StindR4,
152    /// Store indirect float64
153    StindR8,
154    /// Store indirect reference
155    StindRef,
156    /// Throw exception
157    Throw,
158}
159
160impl ClrOpcode {
161    /// 将操作码转换为字节
162    pub fn to_byte(&self) -> u8 {
163        match self {
164            ClrOpcode::Nop => 0x00,
165            ClrOpcode::LdcI4M1 => 0x15,
166            ClrOpcode::LdcI40 => 0x16,
167            ClrOpcode::LdcI41 => 0x17,
168            ClrOpcode::LdcI42 => 0x18,
169            ClrOpcode::LdcI43 => 0x19,
170            ClrOpcode::LdcI44 => 0x1A,
171            ClrOpcode::LdcI45 => 0x1B,
172            ClrOpcode::LdcI46 => 0x1C,
173            ClrOpcode::LdcI47 => 0x1D,
174            ClrOpcode::LdcI48 => 0x1E,
175            ClrOpcode::LdcI4S => 0x1F,
176            ClrOpcode::LdcI4 => 0x20,
177            ClrOpcode::LdcI8 => 0x21,
178            ClrOpcode::LdcR4 => 0x22,
179            ClrOpcode::LdcR8 => 0x23,
180            ClrOpcode::Ldnull => 0x14,
181            ClrOpcode::Ldstr => 0x72,
182            ClrOpcode::Ldarg0 => 0x02,
183            ClrOpcode::Ldarg1 => 0x03,
184            ClrOpcode::Ldarg2 => 0x04,
185            ClrOpcode::Ldarg3 => 0x05,
186            ClrOpcode::Ldloc0 => 0x06,
187            ClrOpcode::Ldloc1 => 0x07,
188            ClrOpcode::Ldloc2 => 0x08,
189            ClrOpcode::Ldloc3 => 0x09,
190            ClrOpcode::Stloc0 => 0x0A,
191            ClrOpcode::Stloc1 => 0x0B,
192            ClrOpcode::Stloc2 => 0x0C,
193            ClrOpcode::Stloc3 => 0x0D,
194            ClrOpcode::Call => 0x28,
195            ClrOpcode::Callvirt => 0x6F,
196            ClrOpcode::Ret => 0x2A,
197            ClrOpcode::Newobj => 0x73,
198            ClrOpcode::Pop => 0x25,
199            ClrOpcode::Dup => 0x25,
200            ClrOpcode::Add => 0x58,
201            ClrOpcode::Sub => 0x59,
202            ClrOpcode::Mul => 0x5A,
203            ClrOpcode::Div => 0x5B,
204            ClrOpcode::Ceq => 0xFE, // 实际上是 0xFE 0x01
205            ClrOpcode::Cgt => 0xFE, // 实际上是 0xFE 0x02
206            ClrOpcode::Clt => 0xFE, // 实际上是 0xFE 0x03
207            ClrOpcode::And => 0x5F,
208            ClrOpcode::Or => 0x60,
209            ClrOpcode::Br => 0x38,
210            ClrOpcode::Brtrue => 0x3A,
211            ClrOpcode::Brfalse => 0x3B,
212            ClrOpcode::Ldloc => 0xFE,  // 实际上是 0xFE 0x0C
213            ClrOpcode::Stloc => 0xFE,  // 实际上是 0xFE 0x0E
214            ClrOpcode::Ldarg => 0xFE,  // 实际上是 0xFE 0x09
215            ClrOpcode::Starg => 0xFE,  // 实际上是 0xFE 0x0B
216            ClrOpcode::Ldloca => 0xFE, // 实际上是 0xFE 0x0D
217            ClrOpcode::Ldfld => 0x7B,
218            ClrOpcode::Stfld => 0x7C,
219            ClrOpcode::Ldelem => 0xA3,
220            ClrOpcode::Stelem => 0xA4,
221            ClrOpcode::Ldlen => 0x8E,
222            ClrOpcode::Newarr => 0x8D,
223            ClrOpcode::Box => 0x8C,
224            ClrOpcode::Unbox => 0x79,
225            ClrOpcode::ConvI4 => 0x67,
226            ClrOpcode::ConvI8 => 0x68,
227            ClrOpcode::ConvR4 => 0x69,
228            ClrOpcode::ConvR8 => 0x6A,
229            ClrOpcode::LdindI4 => 0x4A,
230            ClrOpcode::LdindI8 => 0x4B,
231            ClrOpcode::LdindR4 => 0x4C,
232            ClrOpcode::LdindR8 => 0x4D,
233            ClrOpcode::LdindRef => 0x50,
234            ClrOpcode::StindI4 => 0x54,
235            ClrOpcode::StindI8 => 0x55,
236            ClrOpcode::StindR4 => 0x56,
237            ClrOpcode::StindR8 => 0x57,
238            ClrOpcode::StindRef => 0x51,
239            ClrOpcode::Throw => 0x7A,
240        }
241    }
242
243    /// 从字符串解析操作码
244    pub fn from_str(s: &str) -> Option<Self> {
245        match s.to_lowercase().as_str() {
246            "nop" => Some(ClrOpcode::Nop),
247            "ldc.i4.m1" => Some(ClrOpcode::LdcI4M1),
248            "ldc.i4.0" => Some(ClrOpcode::LdcI40),
249            "ldc.i4.1" => Some(ClrOpcode::LdcI41),
250            "ldc.i4.2" => Some(ClrOpcode::LdcI42),
251            "ldc.i4.3" => Some(ClrOpcode::LdcI43),
252            "ldc.i4.4" => Some(ClrOpcode::LdcI44),
253            "ldc.i4.5" => Some(ClrOpcode::LdcI45),
254            "ldc.i4.6" => Some(ClrOpcode::LdcI46),
255            "ldc.i4.7" => Some(ClrOpcode::LdcI47),
256            "ldc.i4.8" => Some(ClrOpcode::LdcI48),
257            "ldc.i4.s" => Some(ClrOpcode::LdcI4S),
258            "ldc.i4" => Some(ClrOpcode::LdcI4),
259            "ldc.i8" => Some(ClrOpcode::LdcI8),
260            "ldc.r4" => Some(ClrOpcode::LdcR4),
261            "ldc.r8" => Some(ClrOpcode::LdcR8),
262            "ldnull" => Some(ClrOpcode::Ldnull),
263            "ldstr" => Some(ClrOpcode::Ldstr),
264            "ldarg.0" => Some(ClrOpcode::Ldarg0),
265            "ldarg.1" => Some(ClrOpcode::Ldarg1),
266            "ldarg.2" => Some(ClrOpcode::Ldarg2),
267            "ldarg.3" => Some(ClrOpcode::Ldarg3),
268            "ldloc.0" => Some(ClrOpcode::Ldloc0),
269            "ldloc.1" => Some(ClrOpcode::Ldloc1),
270            "ldloc.2" => Some(ClrOpcode::Ldloc2),
271            "ldloc.3" => Some(ClrOpcode::Ldloc3),
272            "stloc.0" => Some(ClrOpcode::Stloc0),
273            "stloc.1" => Some(ClrOpcode::Stloc1),
274            "stloc.2" => Some(ClrOpcode::Stloc2),
275            "stloc.3" => Some(ClrOpcode::Stloc3),
276            "call" => Some(ClrOpcode::Call),
277            "callvirt" => Some(ClrOpcode::Callvirt),
278            "ret" => Some(ClrOpcode::Ret),
279            "newobj" => Some(ClrOpcode::Newobj),
280            "pop" => Some(ClrOpcode::Pop),
281            "dup" => Some(ClrOpcode::Dup),
282            "add" => Some(ClrOpcode::Add),
283            "sub" => Some(ClrOpcode::Sub),
284            "mul" => Some(ClrOpcode::Mul),
285            "div" => Some(ClrOpcode::Div),
286            "ceq" => Some(ClrOpcode::Ceq),
287            "cgt" => Some(ClrOpcode::Cgt),
288            "clt" => Some(ClrOpcode::Clt),
289            "and" => Some(ClrOpcode::And),
290            "or" => Some(ClrOpcode::Or),
291            "br" => Some(ClrOpcode::Br),
292            "brtrue" => Some(ClrOpcode::Brtrue),
293            "brfalse" => Some(ClrOpcode::Brfalse),
294            "ldloc" => Some(ClrOpcode::Ldloc),
295            "stloc" => Some(ClrOpcode::Stloc),
296            "ldarg" => Some(ClrOpcode::Ldarg),
297            "starg" => Some(ClrOpcode::Starg),
298            "ldloca" => Some(ClrOpcode::Ldloca),
299            "ldfld" => Some(ClrOpcode::Ldfld),
300            "stfld" => Some(ClrOpcode::Stfld),
301            "ldelem" => Some(ClrOpcode::Ldelem),
302            "stelem" => Some(ClrOpcode::Stelem),
303            "ldlen" => Some(ClrOpcode::Ldlen),
304            "newarr" => Some(ClrOpcode::Newarr),
305            "box" => Some(ClrOpcode::Box),
306            "unbox" => Some(ClrOpcode::Unbox),
307            "conv.i4" => Some(ClrOpcode::ConvI4),
308            "conv.i8" => Some(ClrOpcode::ConvI8),
309            "conv.r4" => Some(ClrOpcode::ConvR4),
310            "conv.r8" => Some(ClrOpcode::ConvR8),
311            "ldind.i4" => Some(ClrOpcode::LdindI4),
312            "ldind.i8" => Some(ClrOpcode::LdindI8),
313            "ldind.r4" => Some(ClrOpcode::LdindR4),
314            "ldind.r8" => Some(ClrOpcode::LdindR8),
315            "ldind.ref" => Some(ClrOpcode::LdindRef),
316            "stind.i4" => Some(ClrOpcode::StindI4),
317            "stind.i8" => Some(ClrOpcode::StindI8),
318            "stind.r4" => Some(ClrOpcode::StindR4),
319            "stind.r8" => Some(ClrOpcode::StindR8),
320            "stind.ref" => Some(ClrOpcode::StindRef),
321            "throw" => Some(ClrOpcode::Throw),
322            _ => None,
323        }
324    }
325
326    /// 将操作码转换为字符串
327    pub fn as_str(&self) -> &'static str {
328        match self {
329            ClrOpcode::Nop => "nop",
330            ClrOpcode::LdcI4M1 => "ldc.i4.m1",
331            ClrOpcode::LdcI40 => "ldc.i4.0",
332            ClrOpcode::LdcI41 => "ldc.i4.1",
333            ClrOpcode::LdcI42 => "ldc.i4.2",
334            ClrOpcode::LdcI43 => "ldc.i4.3",
335            ClrOpcode::LdcI44 => "ldc.i4.4",
336            ClrOpcode::LdcI45 => "ldc.i4.5",
337            ClrOpcode::LdcI46 => "ldc.i4.6",
338            ClrOpcode::LdcI47 => "ldc.i4.7",
339            ClrOpcode::LdcI48 => "ldc.i4.8",
340            ClrOpcode::LdcI4S => "ldc.i4.s",
341            ClrOpcode::LdcI4 => "ldc.i4",
342            ClrOpcode::LdcI8 => "ldc.i8",
343            ClrOpcode::LdcR4 => "ldc.r4",
344            ClrOpcode::LdcR8 => "ldc.r8",
345            ClrOpcode::Ldnull => "ldnull",
346            ClrOpcode::Ldstr => "ldstr",
347            ClrOpcode::Ldarg0 => "ldarg.0",
348            ClrOpcode::Ldarg1 => "ldarg.1",
349            ClrOpcode::Ldarg2 => "ldarg.2",
350            ClrOpcode::Ldarg3 => "ldarg.3",
351            ClrOpcode::Ldloc0 => "ldloc.0",
352            ClrOpcode::Ldloc1 => "ldloc.1",
353            ClrOpcode::Ldloc2 => "ldloc.2",
354            ClrOpcode::Ldloc3 => "ldloc.3",
355            ClrOpcode::Stloc0 => "stloc.0",
356            ClrOpcode::Stloc1 => "stloc.1",
357            ClrOpcode::Stloc2 => "stloc.2",
358            ClrOpcode::Stloc3 => "stloc.3",
359            ClrOpcode::Call => "call",
360            ClrOpcode::Callvirt => "callvirt",
361            ClrOpcode::Ret => "ret",
362            ClrOpcode::Newobj => "newobj",
363            ClrOpcode::Pop => "pop",
364            ClrOpcode::Dup => "dup",
365            ClrOpcode::Add => "add",
366            ClrOpcode::Sub => "sub",
367            ClrOpcode::Mul => "mul",
368            ClrOpcode::Div => "div",
369            ClrOpcode::Ceq => "ceq",
370            ClrOpcode::Cgt => "cgt",
371            ClrOpcode::Clt => "clt",
372            ClrOpcode::And => "and",
373            ClrOpcode::Or => "or",
374            ClrOpcode::Br => "br",
375            ClrOpcode::Brtrue => "brtrue",
376            ClrOpcode::Brfalse => "brfalse",
377            ClrOpcode::Ldloc => "ldloc",
378            ClrOpcode::Stloc => "stloc",
379            ClrOpcode::Ldarg => "ldarg",
380            ClrOpcode::Starg => "starg",
381            ClrOpcode::Ldloca => "ldloca",
382            ClrOpcode::Ldfld => "ldfld",
383            ClrOpcode::Stfld => "stfld",
384            ClrOpcode::Ldelem => "ldelem",
385            ClrOpcode::Stelem => "stelem",
386            ClrOpcode::Ldlen => "ldlen",
387            ClrOpcode::Newarr => "newarr",
388            ClrOpcode::Box => "box",
389            ClrOpcode::Unbox => "unbox",
390            ClrOpcode::ConvI4 => "conv.i4",
391            ClrOpcode::ConvI8 => "conv.i8",
392            ClrOpcode::ConvR4 => "conv.r4",
393            ClrOpcode::ConvR8 => "conv.r8",
394            ClrOpcode::LdindI4 => "ldind.i4",
395            ClrOpcode::LdindI8 => "ldind.i8",
396            ClrOpcode::LdindR4 => "ldind.r4",
397            ClrOpcode::LdindR8 => "ldind.r8",
398            ClrOpcode::LdindRef => "ldind.ref",
399            ClrOpcode::StindI4 => "stind.i4",
400            ClrOpcode::StindI8 => "stind.i8",
401            ClrOpcode::StindR4 => "stind.r4",
402            ClrOpcode::StindR8 => "stind.r8",
403            ClrOpcode::StindRef => "stind.ref",
404            ClrOpcode::Throw => "throw",
405        }
406    }
407}
408
409/// CLR instruction
410#[derive(Debug, Clone, PartialEq)]
411pub struct ClrInstruction {
412    /// Instruction opcode
413    pub opcode: ClrOpcode,
414    /// Instruction operand
415    pub operand: Option<ClrInstructionOperand>,
416    /// Offset in the instruction stream
417    pub offset: u32,
418}
419
420/// CLR instruction operand
421#[derive(Debug, Clone, PartialEq)]
422pub enum ClrInstructionOperand {
423    /// 32-bit integer
424    Int32(i32),
425    /// 64-bit integer
426    Int64(i64),
427    /// 32-bit floating point
428    Float32(f32),
429    /// 64-bit floating point
430    Float64(f64),
431    /// String value
432    String(String),
433    /// Type reference
434    Type(ClrTypeReference),
435    /// Method reference (name, class, params, return)
436    Method(String, Option<String>, Vec<ClrTypeReference>, Box<ClrTypeReference>),
437    /// Field reference (name, class, type)
438    Field(String, Option<String>, Box<ClrTypeReference>),
439    /// Branch offset
440    Branch(i32),
441    /// Multiple branch offsets
442    Switch(Vec<i32>),
443}