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