dice_rust/jvm/
jvm_types.rs

1/// JVM bytecode instructions and data type definitions
2/// JVM bytecode instructions
3#[derive(Debug, Clone)]
4pub enum JvmInstruction {
5    // Constant pool operations
6    Ldc(u16),    // Load constant from pool
7    Ldc2W(u16),  // Load 2-word constant from pool (long/double)
8    IconstM1,    // Load -1
9    Iconst0,     // Load 0
10    Iconst1,     // Load 1
11    Iconst2,     // Load 2
12    Iconst3,     // Load 3
13    Iconst4,     // Load 4
14    Iconst5,     // Load 5
15    Lconst0,     // Load long 0
16    Lconst1,     // Load long 1
17    Bipush(i8),  // Push byte value
18    Sipush(i16), // Push short value
19
20    // Stack operations
21    Pop,  // Pop top value
22    Dup,  // Duplicate top value
23    Swap, // Swap top two values
24
25    // Arithmetic operations
26    Iadd, // Add two ints
27    Isub, // Subtract two ints
28    Imul, // Multiply two ints
29    Idiv, // Divide two ints
30    Irem, // Remainder of two ints
31
32    // Floating-point operations
33    Dadd, // Add two doubles
34    Dsub, // Subtract two doubles
35    Dmul, // Multiply two doubles
36    Ddiv, // Divide two doubles
37
38    // Type conversion
39    I2d, // Convert int to double
40    D2i, // Convert double to int
41
42    // Control flow
43    Ifeq(u16), // Branch if int equals zero
44    Ifne(u16), // Branch if int not equals zero
45    Iflt(u16), // Branch if int less than zero
46    Ifge(u16), // Branch if int greater or equal zero
47    Ifgt(u16), // Branch if int greater than zero
48    Ifle(u16), // Branch if int less or equal zero
49    Goto(u16), // Unconditional branch
50
51    // Local variable operations
52    Iload(u8),  // Load int from local variable
53    Iload0,     // Load int from local variable 0
54    Iload1,     // Load int from local variable 1
55    Iload2,     // Load int from local variable 2
56    Iload3,     // Load int from local variable 3
57    Istore(u8), // Store int to local variable
58    Istore0,    // Store int to local variable 0
59    Istore1,    // Store int to local variable 1
60    Istore2,    // Store int to local variable 2
61    Istore3,    // Store int to local variable 3
62
63    Aload(u8),  // Load reference from local variable
64    Aload0,     // Load reference from local variable 0
65    Aload1,     // Load reference from local variable 1
66    Aload2,     // Load reference from local variable 2
67    Aload3,     // Load reference from local variable 3
68    Astore(u8), // Store reference to local variable
69    Astore0,    // Store reference to local variable 0
70    Astore1,    // Store reference to local variable 1
71    Astore2,    // Store reference to local variable 2
72    Astore3,    // Store reference to local variable 3
73
74    Dload(u8),  // Load double from local variable
75    Dload0,     // Load double from local variable 0
76    Dload1,     // Load double from local variable 1
77    Dload2,     // Load double from local variable 2
78    Dload3,     // Load double from local variable 3
79    Dstore(u8), // Store double to local variable
80    Dstore0,    // Store double to local variable 0
81    Dstore1,    // Store double to local variable 1
82    Dstore2,    // Store double to local variable 2
83    Dstore3,    // Store double to local variable 3
84
85    Lload(u8),  // Load long from local variable
86    Lload0,     // Load long from local variable 0
87    Lload1,     // Load long from local variable 1
88    Lload2,     // Load long from local variable 2
89    Lload3,     // Load long from local variable 3
90    Lstore(u8), // Store long to local variable
91    Lstore0,    // Store long to local variable 0
92    Lstore1,    // Store long to local variable 1
93    Lstore2,    // Store long to local variable 2
94    Lstore3,    // Store long to local variable 3
95
96    // Method invocation
97    Invokevirtual(u16), // Invoke virtual method
98    Invokestatic(u16),  // Invoke static method
99    Invokespecial(u16), // Invoke special method (constructors, private methods)
100    Invokedynamic(u16), // Invoke dynamic method (for lambda and string concatenation)
101
102    // Object operations
103    New(u16), // Create new object
104
105    // Return instructions
106    Return,  // Return void
107    Ireturn, // Return int
108
109    // Field access
110    Getstatic(u16), // Get static field
111
112    // Constants
113    Dconst0, // Push double 0.0
114    Dconst1, // Push double 1.0
115
116    // Miscellaneous
117    Nop, // No operation
118}
119
120/// Constant pool entry
121#[derive(Debug, Clone)]
122pub enum ConstantPoolEntry {
123    Utf8(String),
124    Class(u16),
125    String(u16),
126    Fieldref(u16, u16),
127    Methodref(u16, u16),
128    NameAndType(u16, u16),
129    Integer(i32),
130    Float(f32),
131    Long(i64),
132    Double(f64),
133    Placeholder, // Used for the second slot of 8-byte constants
134}
135
136/// Constant pool error
137#[derive(Debug, Clone)]
138pub enum ConstantPoolError {
139    SizeLimitExceeded(u16),
140}
141
142/// Constant pool
143#[derive(Debug, Clone)]
144pub struct ConstantPool {
145    entries: Vec<ConstantPoolEntry>,
146}
147
148impl Default for ConstantPool {
149    fn default() -> Self {
150        Self::new()
151    }
152}
153
154impl ConstantPool {
155    pub fn new() -> Self {
156        Self {
157            entries: Vec::new(),
158        }
159    }
160
161    pub fn add_utf8(&mut self, value: String) -> Result<u16, String> {
162        let index = self.entries.len();
163        if index >= u16::MAX as usize {
164            return Err(format!(
165                "Constant pool size exceeds the maximum limit of {}",
166                u16::MAX
167            ));
168        }
169        self.entries.push(ConstantPoolEntry::Utf8(value));
170        Ok(index as u16 + 1)
171    }
172
173    pub fn add_class(&mut self, name_index: u16) -> Result<u16, String> {
174        let index = self.entries.len();
175        if index >= u16::MAX as usize {
176            return Err(format!(
177                "Constant pool size exceeds the maximum limit of {}",
178                u16::MAX
179            ));
180        }
181        self.entries.push(ConstantPoolEntry::Class(name_index));
182        Ok(index as u16 + 1)
183    }
184
185    pub fn add_string(&mut self, utf8_index: u16) -> Result<u16, String> {
186        let index = self.entries.len();
187        if index >= u16::MAX as usize {
188            return Err(format!(
189                "Constant pool size exceeds the maximum limit of {}",
190                u16::MAX
191            ));
192        }
193        self.entries.push(ConstantPoolEntry::String(utf8_index));
194        Ok(index as u16 + 1)
195    }
196
197    pub fn add_fieldref(
198        &mut self,
199        class_index: u16,
200        name_and_type_index: u16,
201    ) -> Result<u16, String> {
202        let index = self.entries.len();
203        if index >= u16::MAX as usize {
204            return Err(format!(
205                "Constant pool size exceeds the maximum limit of {}",
206                u16::MAX
207            ));
208        }
209        self.entries.push(ConstantPoolEntry::Fieldref(
210            class_index,
211            name_and_type_index,
212        ));
213        Ok(index as u16 + 1)
214    }
215
216    pub fn add_methodref(
217        &mut self,
218        class_index: u16,
219        name_and_type_index: u16,
220    ) -> Result<u16, String> {
221        let index = self.entries.len();
222        if index >= u16::MAX as usize {
223            return Err(format!(
224                "Constant pool size exceeds the maximum limit of {}",
225                u16::MAX
226            ));
227        }
228        self.entries.push(ConstantPoolEntry::Methodref(
229            class_index,
230            name_and_type_index,
231        ));
232        Ok(index as u16 + 1)
233    }
234
235    pub fn add_name_and_type(
236        &mut self,
237        name_index: u16,
238        descriptor_index: u16,
239    ) -> Result<u16, String> {
240        let index = self.entries.len();
241        if index >= u16::MAX as usize {
242            return Err(format!(
243                "Constant pool size exceeds the maximum limit of {}",
244                u16::MAX
245            ));
246        }
247        self.entries
248            .push(ConstantPoolEntry::NameAndType(name_index, descriptor_index));
249        Ok(index as u16 + 1)
250    }
251
252    pub fn add_integer(&mut self, value: i32) -> Result<u16, String> {
253        let index = self.entries.len();
254        if index >= u16::MAX as usize {
255            return Err(format!(
256                "Constant pool size exceeds the maximum limit of {}",
257                u16::MAX
258            ));
259        }
260        self.entries.push(ConstantPoolEntry::Integer(value));
261        Ok(index as u16 + 1)
262    }
263
264    pub fn add_float(&mut self, value: f32) -> Result<u16, String> {
265        let index = self.entries.len();
266        if index >= u16::MAX as usize {
267            return Err(format!(
268                "Constant pool size exceeds the maximum limit of {}",
269                u16::MAX
270            ));
271        }
272        self.entries.push(ConstantPoolEntry::Float(value));
273        Ok(index as u16 + 1)
274    }
275
276    pub fn add_long(&mut self, value: i64) -> Result<u16, String> {
277        let index = self.entries.len();
278        if index + 1 >= u16::MAX as usize {
279            return Err(format!(
280                "Constant pool size exceeds the maximum limit of {} (long requires 2 slots)",
281                u16::MAX
282            ));
283        }
284        self.entries.push(ConstantPoolEntry::Long(value));
285        // Long takes 2 slots in the constant pool, add placeholder for the second slot
286        self.entries.push(ConstantPoolEntry::Placeholder);
287        Ok(index as u16 + 1)
288    }
289
290    pub fn add_double(&mut self, value: f64) -> Result<u16, String> {
291        let index = self.entries.len();
292        if index + 1 >= u16::MAX as usize {
293            return Err(format!(
294                "Constant pool size exceeds the maximum limit of {} (double requires 2 slots)",
295                u16::MAX
296            ));
297        }
298        self.entries.push(ConstantPoolEntry::Double(value));
299        // Double takes 2 slots in the constant pool, add placeholder for the second slot
300        self.entries.push(ConstantPoolEntry::Placeholder);
301        Ok(index as u16 + 1)
302    }
303
304    pub fn add_placeholder(&mut self) -> Result<u16, String> {
305        let index = self.entries.len();
306        if index >= u16::MAX as usize {
307            return Err(format!(
308                "Constant pool size exceeds the maximum limit of {}",
309                u16::MAX
310            ));
311        }
312        self.entries.push(ConstantPoolEntry::Placeholder);
313        Ok(index as u16 + 1)
314    }
315
316    pub fn entries(&self) -> &Vec<ConstantPoolEntry> {
317        &self.entries
318    }
319}