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}
198
199#[derive(Debug, Clone, Default)]
200pub struct InsnList {
201    insns: Vec<Insn>,
202}
203
204impl InsnList {
205    pub fn new() -> Self {
206        Self { insns: Vec::new() }
207    }
208
209    pub fn add<T: Into<Insn>>(&mut self, insn: T) -> &mut Self {
210        self.insns.push(insn.into());
211        self
212    }
213
214    pub fn insns(&self) -> &[Insn] {
215        &self.insns
216    }
217
218    pub fn into_insns(self) -> Vec<Insn> {
219        self.insns
220    }
221}
222
223
224
225#[derive(Debug, Clone, Default)]
226pub struct NodeList {
227    nodes: Vec<AbstractInsnNode>,
228}
229
230impl NodeList {
231    pub fn new() -> Self {
232        Self { nodes: Vec::new() }
233    }
234
235    pub fn add<T: Into<AbstractInsnNode>>(&mut self, node: T) -> &mut Self {
236        self.nodes.push(node.into());
237        self
238    }
239
240    pub fn nodes(&self) -> &[AbstractInsnNode] {
241        &self.nodes
242    }
243
244    pub fn into_nodes(self) -> Vec<AbstractInsnNode> {
245        self.nodes
246    }
247}
248
249impl From<LabelNode> for AbstractInsnNode {
250    fn from(value: LabelNode) -> Self {
251        AbstractInsnNode::Label(value)
252    }
253}
254
255impl From<LineNumberInsnNode> for AbstractInsnNode {
256    fn from(value: LineNumberInsnNode) -> Self {
257        AbstractInsnNode::LineNumber(value)
258    }
259}
260
261impl From<Insn> for AbstractInsnNode {
262    fn from(value: Insn) -> Self {
263        AbstractInsnNode::Insn(value)
264    }
265}
266
267impl From<JumpLabelInsnNode> for AbstractInsnNode {
268    fn from(value: JumpLabelInsnNode) -> Self {
269        AbstractInsnNode::JumpLabel(value)
270    }
271}
272
273impl FieldInsnNode {
274    pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
275        Self {
276            insn: opcode.into(),
277            field_ref: MemberRef::Symbolic {
278                owner: owner.to_string(),
279                name: name.to_string(),
280                descriptor: descriptor.to_string(),
281            },
282        }
283    }
284
285    pub fn from_index(opcode: u8, index: u16) -> Self {
286        Self {
287            insn: opcode.into(),
288            field_ref: MemberRef::Index(index),
289        }
290    }
291}
292
293impl MethodInsnNode {
294    pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
295        Self {
296            insn: opcode.into(),
297            method_ref: MemberRef::Symbolic {
298                owner: owner.to_string(),
299                name: name.to_string(),
300                descriptor: descriptor.to_string(),
301            },
302        }
303    }
304
305    pub fn from_index(opcode: u8, index: u16) -> Self {
306        Self {
307            insn: opcode.into(),
308            method_ref: MemberRef::Index(index),
309        }
310    }
311}
312
313impl LdcInsnNode {
314    pub fn from_index(opcode: u8, index: u16) -> Self {
315        Self {
316            insn: opcode.into(),
317            value: LdcValue::Index(index),
318        }
319    }
320
321    pub fn string(value: &str) -> Self {
322        Self {
323            insn: opcodes::LDC.into(),
324            value: LdcValue::String(value.to_string()),
325        }
326    }
327}
328
329impl From<InsnNode> for Insn {
330    fn from(value: InsnNode) -> Self {
331        Insn::Simple(value)
332    }
333}
334
335impl From<IntInsnNode> for Insn {
336    fn from(value: IntInsnNode) -> Self {
337        Insn::Int(value)
338    }
339}
340
341impl From<VarInsnNode> for Insn {
342    fn from(value: VarInsnNode) -> Self {
343        Insn::Var(value)
344    }
345}
346
347impl From<TypeInsnNode> for Insn {
348    fn from(value: TypeInsnNode) -> Self {
349        Insn::Type(value)
350    }
351}
352
353impl From<FieldInsnNode> for Insn {
354    fn from(value: FieldInsnNode) -> Self {
355        Insn::Field(value)
356    }
357}
358
359impl From<MethodInsnNode> for Insn {
360    fn from(value: MethodInsnNode) -> Self {
361        Insn::Method(value)
362    }
363}
364
365impl From<InvokeInterfaceInsnNode> for Insn {
366    fn from(value: InvokeInterfaceInsnNode) -> Self {
367        Insn::InvokeInterface(value)
368    }
369}
370
371impl From<InvokeDynamicInsnNode> for Insn {
372    fn from(value: InvokeDynamicInsnNode) -> Self {
373        Insn::InvokeDynamic(value)
374    }
375}
376
377impl From<JumpInsnNode> for Insn {
378    fn from(value: JumpInsnNode) -> Self {
379        Insn::Jump(value)
380    }
381}
382
383impl From<LdcInsnNode> for Insn {
384    fn from(value: LdcInsnNode) -> Self {
385        Insn::Ldc(value)
386    }
387}
388
389impl From<IincInsnNode> for Insn {
390    fn from(value: IincInsnNode) -> Self {
391        Insn::Iinc(value)
392    }
393}
394
395impl From<TableSwitchInsnNode> for Insn {
396    fn from(value: TableSwitchInsnNode) -> Self {
397        Insn::TableSwitch(value)
398    }
399}
400
401impl From<LookupSwitchInsnNode> for Insn {
402    fn from(value: LookupSwitchInsnNode) -> Self {
403        Insn::LookupSwitch(value)
404    }
405}
406
407impl From<MultiANewArrayInsnNode> for Insn {
408    fn from(value: MultiANewArrayInsnNode) -> Self {
409        Insn::MultiANewArray(value)
410    }
411}