1use super::ClassWriter;
2use crate::{formats::class::writer::utils::calculate_parameter_count, program::*};
3use std::io::Write;
4
5impl<W: Write> ClassWriter<W> {
6 pub fn generate_method_bytecode(&mut self, method: &JvmMethod) -> (Vec<u8>, std::collections::HashMap<String, i32>) {
8 let mut bytecode = Vec::new();
9 let mut label_positions = std::collections::HashMap::new();
10 let mut jump_patches = Vec::new(); for instruction in &method.instructions {
14 match instruction {
15 JvmInstruction::Label { name } => {
16 label_positions.insert(name.clone(), bytecode.len() as i32);
17 }
18 _ => {
19 let pos = bytecode.len();
20 self.emit_instruction(instruction, &mut bytecode, &mut jump_patches, pos);
21 }
22 }
23 }
24
25 for (instr_pos, patch_pos, target_name, is_wide) in jump_patches {
27 if let Some(&target_pos) = label_positions.get(&target_name) {
28 let offset = target_pos - instr_pos as i32;
29 if is_wide {
30 bytecode[patch_pos] = ((offset >> 24) & 0xFF) as u8;
32 bytecode[patch_pos + 1] = ((offset >> 16) & 0xFF) as u8;
33 bytecode[patch_pos + 2] = ((offset >> 8) & 0xFF) as u8;
34 bytecode[patch_pos + 3] = (offset & 0xFF) as u8;
35 }
36 else {
37 bytecode[patch_pos] = ((offset >> 8) & 0xFF) as u8;
39 bytecode[patch_pos + 1] = (offset & 0xFF) as u8;
40 }
41 }
42 }
43
44 if bytecode.is_empty() {
46 bytecode.push(0xB1); }
48
49 (bytecode, label_positions)
50 }
51
52 pub fn emit_instruction(
54 &mut self,
55 instruction: &JvmInstruction,
56 bytecode: &mut Vec<u8>,
57 jump_patches: &mut Vec<(usize, usize, String, bool)>,
58 pos: usize,
59 ) {
60 match instruction {
61 JvmInstruction::Nop => bytecode.push(0x00),
62 JvmInstruction::AconstNull => bytecode.push(0x01),
63 JvmInstruction::IconstM1 => bytecode.push(0x02),
64 JvmInstruction::Iconst0 => bytecode.push(0x03),
65 JvmInstruction::Iconst1 => bytecode.push(0x04),
66 JvmInstruction::Iconst2 => bytecode.push(0x05),
67 JvmInstruction::Iconst3 => bytecode.push(0x06),
68 JvmInstruction::Iconst4 => bytecode.push(0x07),
69 JvmInstruction::Iconst5 => bytecode.push(0x08),
70 JvmInstruction::Lconst0 => bytecode.push(0x09),
71 JvmInstruction::Lconst1 => bytecode.push(0x0A),
72 JvmInstruction::Fconst0 => bytecode.push(0x0B),
73 JvmInstruction::Fconst1 => bytecode.push(0x0C),
74 JvmInstruction::Fconst2 => bytecode.push(0x0D),
75 JvmInstruction::Dconst0 => bytecode.push(0x0E),
76 JvmInstruction::Dconst1 => bytecode.push(0x0F),
77
78 JvmInstruction::Bipush { value } => {
79 bytecode.push(0x10);
80 bytecode.push(*value as u8);
81 }
82 JvmInstruction::Sipush { value } => {
83 bytecode.push(0x11);
84 bytecode.push((*value >> 8) as u8);
85 bytecode.push((*value & 0xFF) as u8);
86 }
87
88 JvmInstruction::Ldc { symbol } => {
89 let index = self.add_string(symbol.clone());
90 if index < 256 {
91 bytecode.push(0x12); bytecode.push(index as u8);
93 }
94 else {
95 bytecode.push(0x13); bytecode.push((index >> 8) as u8);
97 bytecode.push((index & 0xFF) as u8);
98 }
99 }
100 JvmInstruction::LdcW { symbol } => {
101 let index = self.add_string(symbol.clone());
102 bytecode.push(0x13); bytecode.push((index >> 8) as u8);
104 bytecode.push((index & 0xFF) as u8);
105 }
106 JvmInstruction::Ldc2W { symbol } => {
107 if let Ok(long_val) = symbol.parse::<i64>() {
109 let index = self.add_long(long_val);
110 bytecode.push(0x14); bytecode.push((index >> 8) as u8);
112 bytecode.push((index & 0xFF) as u8);
113 }
114 else if let Ok(double_val) = symbol.parse::<f64>() {
116 let index = self.add_double(double_val);
117 bytecode.push(0x14); bytecode.push((index >> 8) as u8);
119 bytecode.push((index & 0xFF) as u8);
120 }
121 else {
123 let index = self.add_string(symbol.clone());
124 bytecode.push(0x14); bytecode.push((index >> 8) as u8);
126 bytecode.push((index & 0xFF) as u8);
127 }
128 }
129
130 JvmInstruction::Iload { index } => {
131 if *index <= 3 {
132 bytecode.push(0x1A + *index as u8);
133 }
134 else if *index <= 255 {
135 bytecode.push(0x15);
136 bytecode.push(*index as u8);
137 }
138 else {
139 bytecode.push(0xC4); bytecode.push(0x15);
141 bytecode.push((*index >> 8) as u8);
142 bytecode.push((*index & 0xFF) as u8);
143 }
144 }
145 JvmInstruction::Iload0 => bytecode.push(0x1A),
146 JvmInstruction::Iload1 => bytecode.push(0x1B),
147 JvmInstruction::Iload2 => bytecode.push(0x1C),
148 JvmInstruction::Iload3 => bytecode.push(0x1D),
149
150 JvmInstruction::Lload { index } => {
151 if *index <= 3 {
152 bytecode.push(0x1E + *index as u8);
153 }
154 else if *index <= 255 {
155 bytecode.push(0x16);
156 bytecode.push(*index as u8);
157 }
158 else {
159 bytecode.push(0xC4); bytecode.push(0x16);
161 bytecode.push((*index >> 8) as u8);
162 bytecode.push((*index & 0xFF) as u8);
163 }
164 }
165 JvmInstruction::Lload0 => bytecode.push(0x1E),
166 JvmInstruction::Lload1 => bytecode.push(0x1F),
167 JvmInstruction::Lload2 => bytecode.push(0x20),
168 JvmInstruction::Lload3 => bytecode.push(0x21),
169
170 JvmInstruction::Fload { index } => {
171 if *index <= 3 {
172 bytecode.push(0x22 + *index as u8);
173 }
174 else if *index <= 255 {
175 bytecode.push(0x17);
176 bytecode.push(*index as u8);
177 }
178 else {
179 bytecode.push(0xC4); bytecode.push(0x17);
181 bytecode.push((*index >> 8) as u8);
182 bytecode.push((*index & 0xFF) as u8);
183 }
184 }
185 JvmInstruction::Fload0 => bytecode.push(0x22),
186 JvmInstruction::Fload1 => bytecode.push(0x23),
187 JvmInstruction::Fload2 => bytecode.push(0x24),
188 JvmInstruction::Fload3 => bytecode.push(0x25),
189
190 JvmInstruction::Dload { index } => {
191 if *index <= 3 {
192 bytecode.push(0x26 + *index as u8);
193 }
194 else if *index <= 255 {
195 bytecode.push(0x18);
196 bytecode.push(*index as u8);
197 }
198 else {
199 bytecode.push(0xC4); bytecode.push(0x18);
201 bytecode.push((*index >> 8) as u8);
202 bytecode.push((*index & 0xFF) as u8);
203 }
204 }
205 JvmInstruction::Dload0 => bytecode.push(0x26),
206 JvmInstruction::Dload1 => bytecode.push(0x27),
207 JvmInstruction::Dload2 => bytecode.push(0x28),
208 JvmInstruction::Dload3 => bytecode.push(0x29),
209
210 JvmInstruction::Aload { index } => {
211 if *index <= 3 {
212 bytecode.push(0x2A + *index as u8);
213 }
214 else if *index <= 255 {
215 bytecode.push(0x19);
216 bytecode.push(*index as u8);
217 }
218 else {
219 bytecode.push(0xC4); bytecode.push(0x19);
221 bytecode.push((*index >> 8) as u8);
222 bytecode.push((*index & 0xFF) as u8);
223 }
224 }
225 JvmInstruction::Aload0 => bytecode.push(0x2A),
226 JvmInstruction::Aload1 => bytecode.push(0x2B),
227 JvmInstruction::Aload2 => bytecode.push(0x2C),
228 JvmInstruction::Aload3 => bytecode.push(0x2D),
229
230 JvmInstruction::Istore { index } => {
231 if *index <= 3 {
232 bytecode.push(0x3B + *index as u8);
233 }
234 else if *index <= 255 {
235 bytecode.push(0x36);
236 bytecode.push(*index as u8);
237 }
238 else {
239 bytecode.push(0xC4); bytecode.push(0x36);
241 bytecode.push((*index >> 8) as u8);
242 bytecode.push((*index & 0xFF) as u8);
243 }
244 }
245 JvmInstruction::Istore0 => bytecode.push(0x3B),
246 JvmInstruction::Istore1 => bytecode.push(0x3C),
247 JvmInstruction::Istore2 => bytecode.push(0x3D),
248 JvmInstruction::Istore3 => bytecode.push(0x3E),
249
250 JvmInstruction::Lstore { index } => {
251 if *index <= 3 {
252 bytecode.push(0x3F + *index as u8);
253 }
254 else if *index <= 255 {
255 bytecode.push(0x37);
256 bytecode.push(*index as u8);
257 }
258 else {
259 bytecode.push(0xC4); bytecode.push(0x37);
261 bytecode.push((*index >> 8) as u8);
262 bytecode.push((*index & 0xFF) as u8);
263 }
264 }
265 JvmInstruction::Lstore0 => bytecode.push(0x3F),
266 JvmInstruction::Lstore1 => bytecode.push(0x40),
267 JvmInstruction::Lstore2 => bytecode.push(0x41),
268 JvmInstruction::Lstore3 => bytecode.push(0x42),
269
270 JvmInstruction::Fstore { index } => {
271 if *index <= 3 {
272 bytecode.push(0x43 + *index as u8);
273 }
274 else if *index <= 255 {
275 bytecode.push(0x38);
276 bytecode.push(*index as u8);
277 }
278 else {
279 bytecode.push(0xC4); bytecode.push(0x38);
281 bytecode.push((*index >> 8) as u8);
282 bytecode.push((*index & 0xFF) as u8);
283 }
284 }
285 JvmInstruction::Fstore0 => bytecode.push(0x43),
286 JvmInstruction::Fstore1 => bytecode.push(0x44),
287 JvmInstruction::Fstore2 => bytecode.push(0x45),
288 JvmInstruction::Fstore3 => bytecode.push(0x46),
289
290 JvmInstruction::Dstore { index } => {
291 if *index <= 3 {
292 bytecode.push(0x47 + *index as u8);
293 }
294 else if *index <= 255 {
295 bytecode.push(0x39);
296 bytecode.push(*index as u8);
297 }
298 else {
299 bytecode.push(0xC4); bytecode.push(0x39);
301 bytecode.push((*index >> 8) as u8);
302 bytecode.push((*index & 0xFF) as u8);
303 }
304 }
305 JvmInstruction::Dstore0 => bytecode.push(0x47),
306 JvmInstruction::Dstore1 => bytecode.push(0x48),
307 JvmInstruction::Dstore2 => bytecode.push(0x49),
308 JvmInstruction::Dstore3 => bytecode.push(0x4A),
309
310 JvmInstruction::Astore { index } => {
311 if *index <= 3 {
312 bytecode.push(0x4B + *index as u8);
313 }
314 else if *index <= 255 {
315 bytecode.push(0x3A);
316 bytecode.push(*index as u8);
317 }
318 else {
319 bytecode.push(0xC4); bytecode.push(0x3A);
321 bytecode.push((*index >> 8) as u8);
322 bytecode.push((*index & 0xFF) as u8);
323 }
324 }
325 JvmInstruction::Astore0 => bytecode.push(0x4B),
326 JvmInstruction::Astore1 => bytecode.push(0x4C),
327 JvmInstruction::Astore2 => bytecode.push(0x4D),
328 JvmInstruction::Astore3 => bytecode.push(0x4E),
329
330 JvmInstruction::Pop => bytecode.push(0x57),
331 JvmInstruction::Pop2 => bytecode.push(0x58),
332 JvmInstruction::Dup => bytecode.push(0x59),
333 JvmInstruction::DupX1 => bytecode.push(0x5A),
334 JvmInstruction::DupX2 => bytecode.push(0x5B),
335 JvmInstruction::Dup2 => bytecode.push(0x5C),
336 JvmInstruction::Dup2X1 => bytecode.push(0x5D),
337 JvmInstruction::Dup2X2 => bytecode.push(0x5E),
338 JvmInstruction::Swap => bytecode.push(0x5F),
339
340 JvmInstruction::Iadd => bytecode.push(0x60),
341 JvmInstruction::Ladd => bytecode.push(0x61),
342 JvmInstruction::Fadd => bytecode.push(0x62),
343 JvmInstruction::Dadd => bytecode.push(0x63),
344 JvmInstruction::Isub => bytecode.push(0x64),
345 JvmInstruction::Lsub => bytecode.push(0x65),
346 JvmInstruction::Fsub => bytecode.push(0x66),
347 JvmInstruction::Dsub => bytecode.push(0x67),
348 JvmInstruction::Imul => bytecode.push(0x68),
349 JvmInstruction::Lmul => bytecode.push(0x69),
350 JvmInstruction::Fmul => bytecode.push(0x6A),
351 JvmInstruction::Dmul => bytecode.push(0x6B),
352 JvmInstruction::Idiv => bytecode.push(0x6C),
353 JvmInstruction::Ldiv => bytecode.push(0x6D),
354 JvmInstruction::Fdiv => bytecode.push(0x6E),
355 JvmInstruction::Ddiv => bytecode.push(0x6F),
356 JvmInstruction::Irem => bytecode.push(0x70),
357 JvmInstruction::Lrem => bytecode.push(0x71),
358 JvmInstruction::Frem => bytecode.push(0x72),
359 JvmInstruction::Drem => bytecode.push(0x73),
360 JvmInstruction::Ineg => bytecode.push(0x74),
361 JvmInstruction::Lneg => bytecode.push(0x75),
362 JvmInstruction::Fneg => bytecode.push(0x76),
363 JvmInstruction::Dneg => bytecode.push(0x77),
364
365 JvmInstruction::Ishl => bytecode.push(0x78),
366 JvmInstruction::Lshl => bytecode.push(0x79),
367 JvmInstruction::Ishr => bytecode.push(0x7A),
368 JvmInstruction::Lshr => bytecode.push(0x7B),
369 JvmInstruction::Iushr => bytecode.push(0x7C),
370 JvmInstruction::Lushr => bytecode.push(0x7D),
371 JvmInstruction::Iand => bytecode.push(0x7E),
372 JvmInstruction::Land => bytecode.push(0x7F),
373 JvmInstruction::Ior => bytecode.push(0x80),
374 JvmInstruction::Lor => bytecode.push(0x81),
375 JvmInstruction::Ixor => bytecode.push(0x82),
376 JvmInstruction::Lxor => bytecode.push(0x83),
377
378 JvmInstruction::Lcmp => bytecode.push(0x94),
379 JvmInstruction::Fcmpl => bytecode.push(0x95),
380 JvmInstruction::Fcmpg => bytecode.push(0x96),
381 JvmInstruction::Dcmpl => bytecode.push(0x97),
382 JvmInstruction::Dcmpg => bytecode.push(0x98),
383
384 JvmInstruction::Ifeq { target } => {
385 jump_patches.push((pos, pos + 1, target.clone(), false));
386 bytecode.push(0x99);
387 bytecode.push(0);
388 bytecode.push(0);
389 }
390 JvmInstruction::Ifne { target } => {
391 jump_patches.push((pos, pos + 1, target.clone(), false));
392 bytecode.push(0x9A);
393 bytecode.push(0);
394 bytecode.push(0);
395 }
396 JvmInstruction::Iflt { target } => {
397 jump_patches.push((pos, pos + 1, target.clone(), false));
398 bytecode.push(0x9B);
399 bytecode.push(0);
400 bytecode.push(0);
401 }
402 JvmInstruction::Ifge { target } => {
403 jump_patches.push((pos, pos + 1, target.clone(), false));
404 bytecode.push(0x9C);
405 bytecode.push(0);
406 bytecode.push(0);
407 }
408 JvmInstruction::Ifgt { target } => {
409 jump_patches.push((pos, pos + 1, target.clone(), false));
410 bytecode.push(0x9D);
411 bytecode.push(0);
412 bytecode.push(0);
413 }
414 JvmInstruction::Ifle { target } => {
415 jump_patches.push((pos, pos + 1, target.clone(), false));
416 bytecode.push(0x9E);
417 bytecode.push(0);
418 bytecode.push(0);
419 }
420 JvmInstruction::IfIcmpeq { target } => {
421 jump_patches.push((pos, pos + 1, target.clone(), false));
422 bytecode.push(0x9F);
423 bytecode.push(0);
424 bytecode.push(0);
425 }
426 JvmInstruction::IfIcmpne { target } => {
427 jump_patches.push((pos, pos + 1, target.clone(), false));
428 bytecode.push(0xA0);
429 bytecode.push(0);
430 bytecode.push(0);
431 }
432 JvmInstruction::IfIcmplt { target } => {
433 jump_patches.push((pos, pos + 1, target.clone(), false));
434 bytecode.push(0xA1);
435 bytecode.push(0);
436 bytecode.push(0);
437 }
438 JvmInstruction::IfIcmpge { target } => {
439 jump_patches.push((pos, pos + 1, target.clone(), false));
440 bytecode.push(0xA2);
441 bytecode.push(0);
442 bytecode.push(0);
443 }
444 JvmInstruction::IfIcmpgt { target } => {
445 jump_patches.push((pos, pos + 1, target.clone(), false));
446 bytecode.push(0xA3);
447 bytecode.push(0);
448 bytecode.push(0);
449 }
450 JvmInstruction::IfIcmple { target } => {
451 jump_patches.push((pos, pos + 1, target.clone(), false));
452 bytecode.push(0xA4);
453 bytecode.push(0);
454 bytecode.push(0);
455 }
456 JvmInstruction::IfAcmpeq { target } => {
457 jump_patches.push((pos, pos + 1, target.clone(), false));
458 bytecode.push(0xA5);
459 bytecode.push(0);
460 bytecode.push(0);
461 }
462 JvmInstruction::IfAcmpne { target } => {
463 jump_patches.push((pos, pos + 1, target.clone(), false));
464 bytecode.push(0xA6);
465 bytecode.push(0);
466 bytecode.push(0);
467 }
468 JvmInstruction::Ifnull { target } => {
469 jump_patches.push((pos, pos + 1, target.clone(), false));
470 bytecode.push(0xC6);
471 bytecode.push(0);
472 bytecode.push(0);
473 }
474 JvmInstruction::Ifnonnull { target } => {
475 jump_patches.push((pos, pos + 1, target.clone(), false));
476 bytecode.push(0xC7);
477 bytecode.push(0);
478 bytecode.push(0);
479 }
480 JvmInstruction::Goto { target } => {
481 jump_patches.push((pos, pos + 1, target.clone(), false));
482 bytecode.push(0xA7);
483 bytecode.push(0);
484 bytecode.push(0);
485 }
486 JvmInstruction::GotoW { target } => {
487 jump_patches.push((pos, pos + 1, target.clone(), true));
488 bytecode.push(0xC8);
489 bytecode.push(0);
490 bytecode.push(0);
491 bytecode.push(0);
492 bytecode.push(0);
493 }
494
495 JvmInstruction::Return => bytecode.push(0xB1),
496 JvmInstruction::Ireturn => bytecode.push(0xAC),
497 JvmInstruction::Lreturn => bytecode.push(0xAD),
498 JvmInstruction::Freturn => bytecode.push(0xAE),
499 JvmInstruction::Dreturn => bytecode.push(0xAF),
500 JvmInstruction::Areturn => bytecode.push(0xB0),
501
502 JvmInstruction::Arraylength => bytecode.push(0xBE),
503 JvmInstruction::Athrow => bytecode.push(0xBF),
504 JvmInstruction::Monitorenter => bytecode.push(0xC2),
505 JvmInstruction::Monitorexit => bytecode.push(0xC3),
506
507 JvmInstruction::Iaload => bytecode.push(0x2E),
508 JvmInstruction::Laload => bytecode.push(0x2F),
509 JvmInstruction::Faload => bytecode.push(0x30),
510 JvmInstruction::Daload => bytecode.push(0x31),
511 JvmInstruction::Aaload => bytecode.push(0x32),
512 JvmInstruction::Baload => bytecode.push(0x33),
513 JvmInstruction::Saload => bytecode.push(0x34),
514 JvmInstruction::Caload => bytecode.push(0x35),
515
516 JvmInstruction::Iastore => bytecode.push(0x4F),
517 JvmInstruction::Lastore => bytecode.push(0x50),
518 JvmInstruction::Fastore => bytecode.push(0x51),
519 JvmInstruction::Dastore => bytecode.push(0x52),
520 JvmInstruction::Aastore => bytecode.push(0x53),
521 JvmInstruction::Bastore => bytecode.push(0x54),
522 JvmInstruction::Sastore => bytecode.push(0x55),
523 JvmInstruction::Castore => bytecode.push(0x56),
524
525 JvmInstruction::Getstatic { class_name, field_name, descriptor } => {
526 let index = self.add_field_ref(class_name.clone(), field_name.clone(), descriptor.clone());
527 bytecode.push(0xB2); bytecode.push((index >> 8) as u8);
529 bytecode.push((index & 0xFF) as u8);
530 }
531 JvmInstruction::Putstatic { class_name, field_name, descriptor } => {
532 let index = self.add_field_ref(class_name.clone(), field_name.clone(), descriptor.clone());
533 bytecode.push(0xB3); bytecode.push((index >> 8) as u8);
535 bytecode.push((index & 0xFF) as u8);
536 }
537 JvmInstruction::Getfield { class_name, field_name, descriptor } => {
538 let index = self.add_field_ref(class_name.clone(), field_name.clone(), descriptor.clone());
539 bytecode.push(0xB4); bytecode.push((index >> 8) as u8);
541 bytecode.push((index & 0xFF) as u8);
542 }
543 JvmInstruction::Putfield { class_name, field_name, descriptor } => {
544 let index = self.add_field_ref(class_name.clone(), field_name.clone(), descriptor.clone());
545 bytecode.push(0xB5); bytecode.push((index >> 8) as u8);
547 bytecode.push((index & 0xFF) as u8);
548 }
549 JvmInstruction::Invokevirtual { class_name, method_name, descriptor } => {
550 let index = self.add_method_ref(class_name.clone(), method_name.clone(), descriptor.clone());
551 bytecode.push(0xB6); bytecode.push((index >> 8) as u8);
553 bytecode.push((index & 0xFF) as u8);
554 }
555 JvmInstruction::Invokespecial { class_name, method_name, descriptor } => {
556 let index = self.add_method_ref(class_name.clone(), method_name.clone(), descriptor.clone());
557 bytecode.push(0xB7); bytecode.push((index >> 8) as u8);
559 bytecode.push((index & 0xFF) as u8);
560 }
561 JvmInstruction::Invokestatic { class_name, method_name, descriptor } => {
562 let index = self.add_method_ref(class_name.clone(), method_name.clone(), descriptor.clone());
563 bytecode.push(0xB8); bytecode.push((index >> 8) as u8);
565 bytecode.push((index & 0xFF) as u8);
566 }
567 JvmInstruction::Invokeinterface { class_name, method_name, descriptor } => {
568 let index = self.add_interface_method_ref(class_name.clone(), method_name.clone(), descriptor.clone());
569 bytecode.push(0xB9); bytecode.push((index >> 8) as u8);
571 bytecode.push((index & 0xFF) as u8);
572
573 let count = calculate_parameter_count(descriptor) + 1;
575 bytecode.push(count as u8);
576 bytecode.push(0);
577 }
578 JvmInstruction::Invokedynamic { class_name, method_name, descriptor } => {
579 let index = self.add_method_ref(class_name.clone(), method_name.clone(), descriptor.clone());
580 bytecode.push(0xBA); bytecode.push((index >> 8) as u8);
582 bytecode.push((index & 0xFF) as u8);
583 bytecode.push(0);
584 bytecode.push(0);
585 }
586 JvmInstruction::New { class_name } => {
587 let index = self.add_class(class_name.clone());
588 bytecode.push(0xBB); bytecode.push((index >> 8) as u8);
590 bytecode.push((index & 0xFF) as u8);
591 }
592 JvmInstruction::Newarray { type_code } => {
593 bytecode.push(0xBC); bytecode.push(*type_code);
595 }
596 JvmInstruction::Anewarray { class_name } => {
597 let index = self.add_class(class_name.clone());
598 bytecode.push(0xBD); bytecode.push((index >> 8) as u8);
600 bytecode.push((index & 0xFF) as u8);
601 }
602 JvmInstruction::Multianewarray { class_name, dimensions } => {
603 let index = self.add_class(class_name.clone());
604 bytecode.push(0xC5); bytecode.push((index >> 8) as u8);
606 bytecode.push((index & 0xFF) as u8);
607 bytecode.push(*dimensions);
608 }
609 JvmInstruction::Checkcast { class_name } => {
610 let index = self.add_class(class_name.clone());
611 bytecode.push(0xC0); bytecode.push((index >> 8) as u8);
613 bytecode.push((index & 0xFF) as u8);
614 }
615 JvmInstruction::Instanceof { class_name } => {
616 let index = self.add_class(class_name.clone());
617 bytecode.push(0xC1); bytecode.push((index >> 8) as u8);
619 bytecode.push((index & 0xFF) as u8);
620 }
621 JvmInstruction::Jsr { target } => {
622 jump_patches.push((pos, pos + 1, target.clone(), false));
623 bytecode.push(0xA8); bytecode.push(0);
625 bytecode.push(0);
626 }
627 JvmInstruction::Ret { index } => {
628 if *index <= 255 {
629 bytecode.push(0xA9); bytecode.push(*index as u8);
631 }
632 else {
633 bytecode.push(0xC4); bytecode.push(0xA9);
635 bytecode.push((*index >> 8) as u8);
636 bytecode.push((*index & 0xFF) as u8);
637 }
638 }
639 JvmInstruction::Iinc { index, value } => {
640 if *index <= 255 && *value >= -128 && *value <= 127 {
641 bytecode.push(0x84); bytecode.push(*index as u8);
643 bytecode.push(*value as u8);
644 }
645 else {
646 bytecode.push(0xC4); bytecode.push(0x84);
648 bytecode.push((*index >> 8) as u8);
649 bytecode.push((*index & 0xFF) as u8);
650 bytecode.push((*value >> 8) as u8);
651 bytecode.push((*value & 0xFF) as u8);
652 }
653 }
654
655 JvmInstruction::I2l => bytecode.push(0x85),
656 JvmInstruction::I2f => bytecode.push(0x86),
657 JvmInstruction::I2d => bytecode.push(0x87),
658 JvmInstruction::L2i => bytecode.push(0x88),
659 JvmInstruction::L2f => bytecode.push(0x89),
660 JvmInstruction::L2d => bytecode.push(0x8A),
661 JvmInstruction::F2i => bytecode.push(0x8B),
662 JvmInstruction::F2l => bytecode.push(0x8C),
663 JvmInstruction::F2d => bytecode.push(0x8D),
664 JvmInstruction::D2i => bytecode.push(0x8E),
665 JvmInstruction::D2l => bytecode.push(0x8F),
666 JvmInstruction::D2f => bytecode.push(0x90),
667 JvmInstruction::I2b => bytecode.push(0x91),
668 JvmInstruction::I2c => bytecode.push(0x92),
669 JvmInstruction::I2s => bytecode.push(0x93),
670
671 JvmInstruction::JsrW { target } => {
672 jump_patches.push((pos, pos + 1, target.clone(), true));
673 bytecode.push(0xC9); bytecode.push(0);
675 bytecode.push(0);
676 bytecode.push(0);
677 bytecode.push(0);
678 }
679
680 JvmInstruction::Lookupswitch { default, npairs, match_offsets } => {
681 bytecode.push(0xAB); let padding = (4 - (bytecode.len() % 4)) % 4;
685 for _ in 0..padding {
686 bytecode.push(0);
687 }
688
689 let default_patch_pos = bytecode.len();
691 jump_patches.push((pos, default_patch_pos, default.clone(), true));
692 bytecode.push(0);
693 bytecode.push(0);
694 bytecode.push(0);
695 bytecode.push(0);
696
697 bytecode.push((*npairs >> 24) as u8);
699 bytecode.push((*npairs >> 16) as u8);
700 bytecode.push((*npairs >> 8) as u8);
701 bytecode.push(*npairs as u8);
702
703 for (val, target) in match_offsets {
705 bytecode.push((val >> 24) as u8);
707 bytecode.push((val >> 16) as u8);
708 bytecode.push((val >> 8) as u8);
709 bytecode.push(*val as u8);
710
711 let patch_pos = bytecode.len();
713 jump_patches.push((pos, patch_pos, target.clone(), true));
714 bytecode.push(0);
715 bytecode.push(0);
716 bytecode.push(0);
717 bytecode.push(0);
718 }
719 }
720 JvmInstruction::Tableswitch { default, low, high, offsets } => {
721 bytecode.push(0xAA); let padding = (4 - (bytecode.len() % 4)) % 4;
725 for _ in 0..padding {
726 bytecode.push(0);
727 }
728
729 let default_patch_pos = bytecode.len();
731 jump_patches.push((pos, default_patch_pos, default.clone(), true));
732 bytecode.push(0);
733 bytecode.push(0);
734 bytecode.push(0);
735 bytecode.push(0);
736
737 bytecode.push((*low >> 24) as u8);
739 bytecode.push((*low >> 16) as u8);
740 bytecode.push((*low >> 8) as u8);
741 bytecode.push(*low as u8);
742
743 bytecode.push((*high >> 24) as u8);
745 bytecode.push((*high >> 16) as u8);
746 bytecode.push((*high >> 8) as u8);
747 bytecode.push(*high as u8);
748
749 for target in offsets {
751 let patch_pos = bytecode.len();
752 jump_patches.push((pos, patch_pos, target.clone(), true));
753 bytecode.push(0);
754 bytecode.push(0);
755 bytecode.push(0);
756 bytecode.push(0);
757 }
758 }
759 JvmInstruction::Wide => {
760 bytecode.push(0xC4);
764 }
765 JvmInstruction::Label { .. } => {
766 }
768 }
769 }
770}