Skip to main content

rust_asm/
insn.rs

1use crate::opcodes;
2
3#[derive(Debug, Clone)]
4pub struct InsnNode {
5    pub opcode: u8,
6}
7
8#[derive(Debug, Clone)]
9pub struct IntInsnNode {
10    pub insn: InsnNode,
11    pub operand: i32,
12}
13
14#[derive(Debug, Clone)]
15pub struct VarInsnNode {
16    pub insn: InsnNode,
17    pub var_index: u16,
18}
19
20#[derive(Debug, Clone)]
21pub struct TypeInsnNode {
22    pub insn: InsnNode,
23    pub type_index: u16,
24}
25
26#[derive(Debug, Clone)]
27pub struct FieldInsnNode {
28    pub insn: InsnNode,
29    pub field_ref: MemberRef,
30}
31
32#[derive(Debug, Clone)]
33pub struct MethodInsnNode {
34    pub insn: InsnNode,
35    pub method_ref: MemberRef,
36}
37
38#[derive(Debug, Clone)]
39pub struct InvokeInterfaceInsnNode {
40    pub insn: InsnNode,
41    pub method_index: u16,
42    pub count: u8,
43}
44
45#[derive(Debug, Clone)]
46pub struct InvokeDynamicInsnNode {
47    pub insn: InsnNode,
48    pub method_index: u16,
49}
50
51#[derive(Debug, Clone)]
52pub struct JumpInsnNode {
53    pub insn: InsnNode,
54    pub offset: i32,
55}
56
57#[derive(Debug, Clone)]
58pub struct LdcInsnNode {
59    pub insn: InsnNode,
60    pub value: LdcValue,
61}
62
63#[derive(Debug, Clone)]
64pub struct IincInsnNode {
65    pub insn: InsnNode,
66    pub var_index: u16,
67    pub increment: i16,
68}
69
70#[derive(Debug, Clone)]
71pub struct TableSwitchInsnNode {
72    pub insn: InsnNode,
73    pub default_offset: i32,
74    pub low: i32,
75    pub high: i32,
76    pub offsets: Vec<i32>,
77}
78
79#[derive(Debug, Clone)]
80pub struct LookupSwitchInsnNode {
81    pub insn: InsnNode,
82    pub default_offset: i32,
83    pub pairs: Vec<(i32, i32)>,
84}
85
86#[derive(Debug, Clone)]
87pub struct MultiANewArrayInsnNode {
88    pub insn: InsnNode,
89    pub type_index: u16,
90    pub dimensions: u8,
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
94pub struct LabelNode {
95    pub id: usize,
96}
97
98#[derive(Debug, Clone)]
99pub struct TryCatchBlockNode {
100    pub start: LabelNode,
101    pub end: LabelNode,
102    pub handler: LabelNode,
103    pub catch_type: Option<String>,
104}
105
106#[derive(Debug, Clone)]
107pub enum AbstractInsnNode {
108    Label(LabelNode),
109    Insn(Insn),
110}
111
112#[derive(Debug, Clone)]
113pub enum Insn {
114    Simple(InsnNode),
115    Int(IntInsnNode),
116    Var(VarInsnNode),
117    Type(TypeInsnNode),
118    Field(FieldInsnNode),
119    Method(MethodInsnNode),
120    InvokeInterface(InvokeInterfaceInsnNode),
121    InvokeDynamic(InvokeDynamicInsnNode),
122    Jump(JumpInsnNode),
123    Ldc(LdcInsnNode),
124    Iinc(IincInsnNode),
125    TableSwitch(TableSwitchInsnNode),
126    LookupSwitch(LookupSwitchInsnNode),
127    MultiANewArray(MultiANewArrayInsnNode),
128}
129
130#[derive(Debug, Clone)]
131pub enum MemberRef {
132    Index(u16),
133    Symbolic {
134        owner: String,
135        name: String,
136        descriptor: String,
137    },
138}
139
140#[derive(Debug, Clone)]
141pub enum LdcValue {
142    Index(u16),
143    String(String),
144}
145
146#[derive(Debug, Clone, Default)]
147pub struct InsnList {
148    insns: Vec<Insn>,
149}
150
151impl InsnList {
152    pub fn new() -> Self {
153        Self { insns: Vec::new() }
154    }
155
156    pub fn add<T: Into<Insn>>(&mut self, insn: T) -> &mut Self {
157        self.insns.push(insn.into());
158        self
159    }
160
161    pub fn insns(&self) -> &[Insn] {
162        &self.insns
163    }
164
165    pub fn into_insns(self) -> Vec<Insn> {
166        self.insns
167    }
168}
169
170#[derive(Debug, Clone, Default)]
171pub struct NodeList {
172    nodes: Vec<AbstractInsnNode>,
173}
174
175impl NodeList {
176    pub fn new() -> Self {
177        Self { nodes: Vec::new() }
178    }
179
180    pub fn add<T: Into<AbstractInsnNode>>(&mut self, node: T) -> &mut Self {
181        self.nodes.push(node.into());
182        self
183    }
184
185    pub fn nodes(&self) -> &[AbstractInsnNode] {
186        &self.nodes
187    }
188
189    pub fn into_nodes(self) -> Vec<AbstractInsnNode> {
190        self.nodes
191    }
192}
193
194impl From<LabelNode> for AbstractInsnNode {
195    fn from(value: LabelNode) -> Self {
196        AbstractInsnNode::Label(value)
197    }
198}
199
200impl From<Insn> for AbstractInsnNode {
201    fn from(value: Insn) -> Self {
202        AbstractInsnNode::Insn(value)
203    }
204}
205
206impl FieldInsnNode {
207    pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
208        Self {
209            insn: InsnNode { opcode },
210            field_ref: MemberRef::Symbolic {
211                owner: owner.to_string(),
212                name: name.to_string(),
213                descriptor: descriptor.to_string(),
214            },
215        }
216    }
217
218    pub fn from_index(opcode: u8, index: u16) -> Self {
219        Self {
220            insn: InsnNode { opcode },
221            field_ref: MemberRef::Index(index),
222        }
223    }
224}
225
226impl MethodInsnNode {
227    pub fn new(opcode: u8, owner: &str, name: &str, descriptor: &str) -> Self {
228        Self {
229            insn: InsnNode { opcode },
230            method_ref: MemberRef::Symbolic {
231                owner: owner.to_string(),
232                name: name.to_string(),
233                descriptor: descriptor.to_string(),
234            },
235        }
236    }
237
238    pub fn from_index(opcode: u8, index: u16) -> Self {
239        Self {
240            insn: InsnNode { opcode },
241            method_ref: MemberRef::Index(index),
242        }
243    }
244}
245
246impl LdcInsnNode {
247    pub fn from_index(opcode: u8, index: u16) -> Self {
248        Self {
249            insn: InsnNode { opcode },
250            value: LdcValue::Index(index),
251        }
252    }
253
254    pub fn string(value: &str) -> Self {
255        Self {
256            insn: InsnNode {
257                opcode: opcodes::LDC,
258            },
259            value: LdcValue::String(value.to_string()),
260        }
261    }
262}
263
264impl From<InsnNode> for Insn {
265    fn from(value: InsnNode) -> Self {
266        Insn::Simple(value)
267    }
268}
269
270impl From<IntInsnNode> for Insn {
271    fn from(value: IntInsnNode) -> Self {
272        Insn::Int(value)
273    }
274}
275
276impl From<VarInsnNode> for Insn {
277    fn from(value: VarInsnNode) -> Self {
278        Insn::Var(value)
279    }
280}
281
282impl From<TypeInsnNode> for Insn {
283    fn from(value: TypeInsnNode) -> Self {
284        Insn::Type(value)
285    }
286}
287
288impl From<FieldInsnNode> for Insn {
289    fn from(value: FieldInsnNode) -> Self {
290        Insn::Field(value)
291    }
292}
293
294impl From<MethodInsnNode> for Insn {
295    fn from(value: MethodInsnNode) -> Self {
296        Insn::Method(value)
297    }
298}
299
300impl From<InvokeInterfaceInsnNode> for Insn {
301    fn from(value: InvokeInterfaceInsnNode) -> Self {
302        Insn::InvokeInterface(value)
303    }
304}
305
306impl From<InvokeDynamicInsnNode> for Insn {
307    fn from(value: InvokeDynamicInsnNode) -> Self {
308        Insn::InvokeDynamic(value)
309    }
310}
311
312impl From<JumpInsnNode> for Insn {
313    fn from(value: JumpInsnNode) -> Self {
314        Insn::Jump(value)
315    }
316}
317
318impl From<LdcInsnNode> for Insn {
319    fn from(value: LdcInsnNode) -> Self {
320        Insn::Ldc(value)
321    }
322}
323
324impl From<IincInsnNode> for Insn {
325    fn from(value: IincInsnNode) -> Self {
326        Insn::Iinc(value)
327    }
328}
329
330impl From<TableSwitchInsnNode> for Insn {
331    fn from(value: TableSwitchInsnNode) -> Self {
332        Insn::TableSwitch(value)
333    }
334}
335
336impl From<LookupSwitchInsnNode> for Insn {
337    fn from(value: LookupSwitchInsnNode) -> Self {
338        Insn::LookupSwitch(value)
339    }
340}
341
342impl From<MultiANewArrayInsnNode> for Insn {
343    fn from(value: MultiANewArrayInsnNode) -> Self {
344        Insn::MultiANewArray(value)
345    }
346}