Skip to main content

rust_asm/
insn.rs

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