Skip to main content

rust_asm/
insn.rs

1use crate::opcodes;
2use std::sync::atomic::{AtomicUsize, Ordering};
3
4#[derive(Debug, Clone)]
5pub struct InsnNode {
6    pub opcode: u8,
7}
8
9impl From<u8> for InsnNode {
10    fn from(value: u8) -> Self {
11        Self { opcode: value }
12    }
13}
14
15#[derive(Debug, Clone)]
16pub struct IntInsnNode {
17    pub insn: InsnNode,
18    pub operand: i32,
19}
20
21#[derive(Debug, Clone)]
22pub struct VarInsnNode {
23    pub insn: InsnNode,
24    pub var_index: u16,
25}
26
27#[derive(Debug, Clone)]
28pub struct TypeInsnNode {
29    pub insn: InsnNode,
30    pub type_index: u16,
31}
32
33#[derive(Debug, Clone)]
34pub struct FieldInsnNode {
35    pub insn: InsnNode,
36    pub field_ref: MemberRef,
37}
38
39#[derive(Debug, Clone)]
40pub struct MethodInsnNode {
41    pub insn: InsnNode,
42    pub method_ref: MemberRef,
43}
44
45#[derive(Debug, Clone)]
46pub struct InvokeInterfaceInsnNode {
47    pub insn: InsnNode,
48    pub method_index: u16,
49    pub count: u8,
50}
51
52#[derive(Debug, Clone)]
53pub struct InvokeDynamicInsnNode {
54    pub insn: InsnNode,
55    pub method_index: u16,
56}
57
58#[derive(Debug, Clone)]
59pub struct JumpInsnNode {
60    pub insn: InsnNode,
61    pub offset: i32,
62}
63
64#[derive(Debug, Clone)]
65pub struct JumpLabelInsnNode {
66    pub insn: InsnNode,
67    pub target: LabelNode,
68}
69
70#[derive(Debug, Clone)]
71pub struct LdcInsnNode {
72    pub insn: InsnNode,
73    pub value: LdcValue,
74}
75
76#[derive(Debug, Clone)]
77pub struct IincInsnNode {
78    pub insn: InsnNode,
79    pub var_index: u16,
80    pub increment: i16,
81}
82
83#[derive(Debug, Clone)]
84pub struct TableSwitchInsnNode {
85    pub insn: InsnNode,
86    pub default_offset: i32,
87    pub low: i32,
88    pub high: i32,
89    pub offsets: Vec<i32>,
90}
91
92#[derive(Debug, Clone)]
93pub struct LookupSwitchInsnNode {
94    pub insn: InsnNode,
95    pub default_offset: i32,
96    pub pairs: Vec<(i32, i32)>,
97}
98
99#[derive(Debug, Clone)]
100pub struct MultiANewArrayInsnNode {
101    pub insn: InsnNode,
102    pub type_index: u16,
103    pub dimensions: u8,
104}
105
106static NEXT_LABEL_ID: AtomicUsize = AtomicUsize::new(0);
107
108fn next_label_id() -> usize {
109    NEXT_LABEL_ID.fetch_add(1, Ordering::Relaxed)
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
113pub struct Label {
114    pub id: usize,
115}
116
117impl Label {
118    pub fn new() -> Self {
119        Self { id: next_label_id() }
120    }
121}
122
123#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
124pub struct LabelNode {
125    pub id: usize,
126}
127
128impl LabelNode {
129    pub fn new() -> Self {
130        Self { id: next_label_id() }
131    }
132
133    pub fn from_label(label: Label) -> Self {
134        Self { id: label.id }
135    }
136}
137
138#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
139pub struct LineNumberInsnNode {
140    pub line: u16,
141    pub start: LabelNode,
142}
143impl LineNumberInsnNode{
144    pub(crate) fn new(line: u16, start: LabelNode) -> Self {
145        Self { line, start }
146    }
147}
148
149#[derive(Debug, Clone)]
150pub struct TryCatchBlockNode {
151    pub start: LabelNode,
152    pub end: LabelNode,
153    pub handler: LabelNode,
154    pub catch_type: Option<String>,
155}
156
157#[derive(Debug, Clone)]
158pub enum AbstractInsnNode {
159    Label(LabelNode),
160    LineNumber(LineNumberInsnNode),
161    Insn(Insn),
162    JumpLabel(JumpLabelInsnNode),
163}
164
165#[derive(Debug, Clone)]
166pub enum Insn {
167    Simple(InsnNode),
168    Int(IntInsnNode),
169    Var(VarInsnNode),
170    Type(TypeInsnNode),
171    Field(FieldInsnNode),
172    Method(MethodInsnNode),
173    InvokeInterface(InvokeInterfaceInsnNode),
174    InvokeDynamic(InvokeDynamicInsnNode),
175    Jump(JumpInsnNode),
176    Ldc(LdcInsnNode),
177    Iinc(IincInsnNode),
178    TableSwitch(TableSwitchInsnNode),
179    LookupSwitch(LookupSwitchInsnNode),
180    MultiANewArray(MultiANewArrayInsnNode),
181}
182
183#[derive(Debug, Clone)]
184pub enum MemberRef {
185    Index(u16),
186    Symbolic {
187        owner: String,
188        name: String,
189        descriptor: String,
190    },
191}
192
193#[derive(Debug, Clone)]
194pub enum LdcValue {
195    Index(u16),
196    String(String),
197    Int(i32),
198    Float(f32),
199    Long(i64),
200    Double(f64),
201}
202
203#[derive(Debug, Clone, Default)]
204pub struct InsnList {
205    insns: Vec<Insn>,
206}
207
208impl InsnList {
209    pub fn new() -> Self {
210        Self { insns: Vec::new() }
211    }
212
213    pub fn add<T: Into<Insn>>(&mut self, insn: T) -> &mut Self {
214        self.insns.push(insn.into());
215        self
216    }
217
218    pub fn insns(&self) -> &[Insn] {
219        &self.insns
220    }
221
222    pub fn into_insns(self) -> Vec<Insn> {
223        self.insns
224    }
225}
226
227
228
229#[derive(Debug, Clone, Default)]
230pub struct NodeList {
231    nodes: Vec<AbstractInsnNode>,
232}
233
234impl NodeList {
235    pub fn new() -> Self {
236        Self { nodes: Vec::new() }
237    }
238
239    pub fn add<T: Into<AbstractInsnNode>>(&mut self, node: T) -> &mut Self {
240        self.nodes.push(node.into());
241        self
242    }
243
244    pub fn nodes(&self) -> &[AbstractInsnNode] {
245        &self.nodes
246    }
247
248    pub fn into_nodes(self) -> Vec<AbstractInsnNode> {
249        self.nodes
250    }
251}
252
253impl From<LabelNode> for AbstractInsnNode {
254    fn from(value: LabelNode) -> Self {
255        AbstractInsnNode::Label(value)
256    }
257}
258
259impl From<LineNumberInsnNode> for AbstractInsnNode {
260    fn from(value: LineNumberInsnNode) -> Self {
261        AbstractInsnNode::LineNumber(value)
262    }
263}
264
265impl From<Insn> for AbstractInsnNode {
266    fn from(value: Insn) -> Self {
267        AbstractInsnNode::Insn(value)
268    }
269}
270
271impl From<JumpLabelInsnNode> for AbstractInsnNode {
272    fn from(value: JumpLabelInsnNode) -> Self {
273        AbstractInsnNode::JumpLabel(value)
274    }
275}
276
277impl FieldInsnNode {
278    pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
279        Self {
280            insn: opcode.into(),
281            field_ref: MemberRef::Symbolic {
282                owner: owner.to_string(),
283                name: name.to_string(),
284                descriptor: descriptor.to_string(),
285            },
286        }
287    }
288
289    pub fn from_index(opcode: u8, index: u16) -> Self {
290        Self {
291            insn: opcode.into(),
292            field_ref: MemberRef::Index(index),
293        }
294    }
295}
296
297impl MethodInsnNode {
298    pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
299        Self {
300            insn: opcode.into(),
301            method_ref: MemberRef::Symbolic {
302                owner: owner.to_string(),
303                name: name.to_string(),
304                descriptor: descriptor.to_string(),
305            },
306        }
307    }
308
309    pub fn from_index(opcode: u8, index: u16) -> Self {
310        Self {
311            insn: opcode.into(),
312            method_ref: MemberRef::Index(index),
313        }
314    }
315}
316
317impl LdcInsnNode {
318    pub fn from_index(opcode: u8, index: u16) -> Self {
319        Self {
320            insn: opcode.into(),
321            value: LdcValue::Index(index),
322        }
323    }
324
325    pub fn int(value: i32) -> Self {
326        Self {
327            insn: opcodes::LDC.into(),
328            value: LdcValue::Int(value),
329        }
330    }
331
332    pub fn long(value: i64) -> Self {
333        Self {
334            insn: opcodes::LDC2_W.into(),
335            value: LdcValue::Long(value),
336        }
337    }
338
339    pub fn float(value: f32) -> Self {
340        Self {
341            insn: opcodes::LDC.into(),
342            value: LdcValue::Float(value),
343        }
344    }
345
346    pub fn double(value: f64) -> Self {
347        Self {
348            insn: opcodes::LDC2_W.into(),
349            value: LdcValue::Double(value),
350        }
351    }
352
353    pub fn short(value: i16) -> Self {
354        Self::int(value as i32)
355    }
356
357    pub fn char(value: u16) -> Self {
358        Self::int(value as i32)
359    }
360
361    pub fn byte(value: i8) -> Self {
362        Self::int(value as i32)
363    }
364
365    pub fn boolean(value: bool) -> Self {
366        Self::int(if value { 1 } else { 0 })
367    }
368
369    pub fn string(value: &str) -> Self {
370        Self {
371            insn: opcodes::LDC.into(),
372            value: LdcValue::String(value.to_string()),
373        }
374    }
375
376}
377
378impl From<InsnNode> for Insn {
379    fn from(value: InsnNode) -> Self {
380        Insn::Simple(value)
381    }
382}
383
384impl From<IntInsnNode> for Insn {
385    fn from(value: IntInsnNode) -> Self {
386        Insn::Int(value)
387    }
388}
389
390impl From<VarInsnNode> for Insn {
391    fn from(value: VarInsnNode) -> Self {
392        Insn::Var(value)
393    }
394}
395
396impl From<TypeInsnNode> for Insn {
397    fn from(value: TypeInsnNode) -> Self {
398        Insn::Type(value)
399    }
400}
401
402impl From<FieldInsnNode> for Insn {
403    fn from(value: FieldInsnNode) -> Self {
404        Insn::Field(value)
405    }
406}
407
408impl From<MethodInsnNode> for Insn {
409    fn from(value: MethodInsnNode) -> Self {
410        Insn::Method(value)
411    }
412}
413
414impl From<InvokeInterfaceInsnNode> for Insn {
415    fn from(value: InvokeInterfaceInsnNode) -> Self {
416        Insn::InvokeInterface(value)
417    }
418}
419
420impl From<InvokeDynamicInsnNode> for Insn {
421    fn from(value: InvokeDynamicInsnNode) -> Self {
422        Insn::InvokeDynamic(value)
423    }
424}
425
426impl From<JumpInsnNode> for Insn {
427    fn from(value: JumpInsnNode) -> Self {
428        Insn::Jump(value)
429    }
430}
431
432impl From<LdcInsnNode> for Insn {
433    fn from(value: LdcInsnNode) -> Self {
434        Insn::Ldc(value)
435    }
436}
437
438impl From<IincInsnNode> for Insn {
439    fn from(value: IincInsnNode) -> Self {
440        Insn::Iinc(value)
441    }
442}
443
444impl From<TableSwitchInsnNode> for Insn {
445    fn from(value: TableSwitchInsnNode) -> Self {
446        Insn::TableSwitch(value)
447    }
448}
449
450impl From<LookupSwitchInsnNode> for Insn {
451    fn from(value: LookupSwitchInsnNode) -> Self {
452        Insn::LookupSwitch(value)
453    }
454}
455
456impl From<MultiANewArrayInsnNode> for Insn {
457    fn from(value: MultiANewArrayInsnNode) -> Self {
458        Insn::MultiANewArray(value)
459    }
460}