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 Default for Label {
118    fn default() -> Self {
119        Self::new()
120    }
121}
122
123impl Label {
124    pub fn new() -> Self {
125        Self {
126            id: next_label_id(),
127        }
128    }
129}
130
131#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
132pub struct LabelNode {
133    pub id: usize,
134}
135
136impl Default for LabelNode {
137    fn default() -> Self {
138        Self::new()
139    }
140}
141
142impl LabelNode {
143    pub fn new() -> Self {
144        Self {
145            id: next_label_id(),
146        }
147    }
148
149    pub fn from_label(label: Label) -> Self {
150        Self { id: label.id }
151    }
152}
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
155pub struct LineNumberInsnNode {
156    pub line: u16,
157    pub start: LabelNode,
158}
159impl LineNumberInsnNode {
160    pub(crate) fn new(line: u16, start: LabelNode) -> Self {
161        Self { line, start }
162    }
163}
164
165#[derive(Debug, Clone)]
166pub struct TryCatchBlockNode {
167    pub start: LabelNode,
168    pub end: LabelNode,
169    pub handler: LabelNode,
170    pub catch_type: Option<String>,
171}
172
173#[derive(Debug, Clone)]
174pub enum AbstractInsnNode {
175    Label(LabelNode),
176    LineNumber(LineNumberInsnNode),
177    Insn(Insn),
178    JumpLabel(JumpLabelInsnNode),
179}
180
181#[derive(Debug, Clone)]
182pub enum Insn {
183    Simple(InsnNode),
184    Int(IntInsnNode),
185    Var(VarInsnNode),
186    Type(TypeInsnNode),
187    Field(FieldInsnNode),
188    Method(MethodInsnNode),
189    InvokeInterface(InvokeInterfaceInsnNode),
190    InvokeDynamic(InvokeDynamicInsnNode),
191    Jump(JumpInsnNode),
192    Ldc(LdcInsnNode),
193    Iinc(IincInsnNode),
194    TableSwitch(TableSwitchInsnNode),
195    LookupSwitch(LookupSwitchInsnNode),
196    MultiANewArray(MultiANewArrayInsnNode),
197}
198
199#[derive(Debug, Clone)]
200pub enum MemberRef {
201    Index(u16),
202    Symbolic {
203        owner: String,
204        name: String,
205        descriptor: String,
206    },
207}
208
209#[derive(Debug, Clone)]
210pub enum LdcValue {
211    Index(u16),
212    String(String),
213    Int(i32),
214    Float(f32),
215    Long(i64),
216    Double(f64),
217}
218
219#[derive(Debug, Clone, Default)]
220pub struct InsnList {
221    insns: Vec<Insn>,
222}
223
224impl InsnList {
225    pub fn new() -> Self {
226        Self { insns: Vec::new() }
227    }
228
229    pub fn add<T: Into<Insn>>(&mut self, insn: T) -> &mut Self {
230        self.insns.push(insn.into());
231        self
232    }
233
234    pub fn insns(&self) -> &[Insn] {
235        &self.insns
236    }
237
238    pub fn into_insns(self) -> Vec<Insn> {
239        self.insns
240    }
241}
242
243#[derive(Debug, Clone, Default)]
244pub struct NodeList {
245    nodes: Vec<AbstractInsnNode>,
246}
247
248impl NodeList {
249    pub fn new() -> Self {
250        Self { nodes: Vec::new() }
251    }
252
253    pub fn add<T: Into<AbstractInsnNode>>(&mut self, node: T) -> &mut Self {
254        self.nodes.push(node.into());
255        self
256    }
257
258    pub fn nodes(&self) -> &[AbstractInsnNode] {
259        &self.nodes
260    }
261
262    pub fn into_nodes(self) -> Vec<AbstractInsnNode> {
263        self.nodes
264    }
265}
266
267impl From<LabelNode> for AbstractInsnNode {
268    fn from(value: LabelNode) -> Self {
269        AbstractInsnNode::Label(value)
270    }
271}
272
273impl From<LineNumberInsnNode> for AbstractInsnNode {
274    fn from(value: LineNumberInsnNode) -> Self {
275        AbstractInsnNode::LineNumber(value)
276    }
277}
278
279impl From<Insn> for AbstractInsnNode {
280    fn from(value: Insn) -> Self {
281        AbstractInsnNode::Insn(value)
282    }
283}
284
285impl From<JumpLabelInsnNode> for AbstractInsnNode {
286    fn from(value: JumpLabelInsnNode) -> Self {
287        AbstractInsnNode::JumpLabel(value)
288    }
289}
290
291impl FieldInsnNode {
292    pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
293        Self {
294            insn: opcode.into(),
295            field_ref: MemberRef::Symbolic {
296                owner: owner.to_string(),
297                name: name.to_string(),
298                descriptor: descriptor.to_string(),
299            },
300        }
301    }
302
303    pub fn from_index(opcode: u8, index: u16) -> Self {
304        Self {
305            insn: opcode.into(),
306            field_ref: MemberRef::Index(index),
307        }
308    }
309}
310
311impl MethodInsnNode {
312    pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
313        Self {
314            insn: opcode.into(),
315            method_ref: MemberRef::Symbolic {
316                owner: owner.to_string(),
317                name: name.to_string(),
318                descriptor: descriptor.to_string(),
319            },
320        }
321    }
322
323    pub fn from_index(opcode: u8, index: u16) -> Self {
324        Self {
325            insn: opcode.into(),
326            method_ref: MemberRef::Index(index),
327        }
328    }
329}
330
331impl LdcInsnNode {
332    pub fn from_index(opcode: u8, index: u16) -> Self {
333        Self {
334            insn: opcode.into(),
335            value: LdcValue::Index(index),
336        }
337    }
338
339    pub fn int(value: i32) -> Self {
340        Self {
341            insn: opcodes::LDC.into(),
342            value: LdcValue::Int(value),
343        }
344    }
345
346    pub fn long(value: i64) -> Self {
347        Self {
348            insn: opcodes::LDC2_W.into(),
349            value: LdcValue::Long(value),
350        }
351    }
352
353    pub fn float(value: f32) -> Self {
354        Self {
355            insn: opcodes::LDC.into(),
356            value: LdcValue::Float(value),
357        }
358    }
359
360    pub fn double(value: f64) -> Self {
361        Self {
362            insn: opcodes::LDC2_W.into(),
363            value: LdcValue::Double(value),
364        }
365    }
366
367    pub fn short(value: i16) -> Self {
368        Self::int(value as i32)
369    }
370
371    pub fn char(value: u16) -> Self {
372        Self::int(value as i32)
373    }
374
375    pub fn byte(value: i8) -> Self {
376        Self::int(value as i32)
377    }
378
379    pub fn boolean(value: bool) -> Self {
380        Self::int(if value { 1 } else { 0 })
381    }
382
383    pub fn string(value: &str) -> Self {
384        Self {
385            insn: opcodes::LDC.into(),
386            value: LdcValue::String(value.to_string()),
387        }
388    }
389}
390
391impl From<InsnNode> for Insn {
392    fn from(value: InsnNode) -> Self {
393        Insn::Simple(value)
394    }
395}
396
397impl From<IntInsnNode> for Insn {
398    fn from(value: IntInsnNode) -> Self {
399        Insn::Int(value)
400    }
401}
402
403impl From<VarInsnNode> for Insn {
404    fn from(value: VarInsnNode) -> Self {
405        Insn::Var(value)
406    }
407}
408
409impl From<TypeInsnNode> for Insn {
410    fn from(value: TypeInsnNode) -> Self {
411        Insn::Type(value)
412    }
413}
414
415impl From<FieldInsnNode> for Insn {
416    fn from(value: FieldInsnNode) -> Self {
417        Insn::Field(value)
418    }
419}
420
421impl From<MethodInsnNode> for Insn {
422    fn from(value: MethodInsnNode) -> Self {
423        Insn::Method(value)
424    }
425}
426
427impl From<InvokeInterfaceInsnNode> for Insn {
428    fn from(value: InvokeInterfaceInsnNode) -> Self {
429        Insn::InvokeInterface(value)
430    }
431}
432
433impl From<InvokeDynamicInsnNode> for Insn {
434    fn from(value: InvokeDynamicInsnNode) -> Self {
435        Insn::InvokeDynamic(value)
436    }
437}
438
439impl From<JumpInsnNode> for Insn {
440    fn from(value: JumpInsnNode) -> Self {
441        Insn::Jump(value)
442    }
443}
444
445impl From<LdcInsnNode> for Insn {
446    fn from(value: LdcInsnNode) -> Self {
447        Insn::Ldc(value)
448    }
449}
450
451impl From<IincInsnNode> for Insn {
452    fn from(value: IincInsnNode) -> Self {
453        Insn::Iinc(value)
454    }
455}
456
457impl From<TableSwitchInsnNode> for Insn {
458    fn from(value: TableSwitchInsnNode) -> Self {
459        Insn::TableSwitch(value)
460    }
461}
462
463impl From<LookupSwitchInsnNode> for Insn {
464    fn from(value: LookupSwitchInsnNode) -> Self {
465        Insn::LookupSwitch(value)
466    }
467}
468
469impl From<MultiANewArrayInsnNode> for Insn {
470    fn from(value: MultiANewArrayInsnNode) -> Self {
471        Insn::MultiANewArray(value)
472    }
473}