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