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 let index = self.add_string(symbol.clone());
108 bytecode.push(0x14); bytecode.push((index >> 8) as u8);
110 bytecode.push((index & 0xFF) as u8);
111 }
112
113 JvmInstruction::Iload { index } => {
114 if *index <= 3 {
115 bytecode.push(0x1A + *index as u8);
116 }
117 else if *index <= 255 {
118 bytecode.push(0x15);
119 bytecode.push(*index as u8);
120 }
121 else {
122 bytecode.push(0xC4); bytecode.push(0x15);
124 bytecode.push((*index >> 8) as u8);
125 bytecode.push((*index & 0xFF) as u8);
126 }
127 }
128 JvmInstruction::Iload0 => bytecode.push(0x1A),
129 JvmInstruction::Iload1 => bytecode.push(0x1B),
130 JvmInstruction::Iload2 => bytecode.push(0x1C),
131 JvmInstruction::Iload3 => bytecode.push(0x1D),
132
133 JvmInstruction::Lload { index } => {
134 if *index <= 3 {
135 bytecode.push(0x1E + *index as u8);
136 }
137 else if *index <= 255 {
138 bytecode.push(0x16);
139 bytecode.push(*index as u8);
140 }
141 else {
142 bytecode.push(0xC4); bytecode.push(0x16);
144 bytecode.push((*index >> 8) as u8);
145 bytecode.push((*index & 0xFF) as u8);
146 }
147 }
148 JvmInstruction::Lload0 => bytecode.push(0x1E),
149 JvmInstruction::Lload1 => bytecode.push(0x1F),
150 JvmInstruction::Lload2 => bytecode.push(0x20),
151 JvmInstruction::Lload3 => bytecode.push(0x21),
152
153 JvmInstruction::Fload { index } => {
154 if *index <= 3 {
155 bytecode.push(0x22 + *index as u8);
156 }
157 else if *index <= 255 {
158 bytecode.push(0x17);
159 bytecode.push(*index as u8);
160 }
161 else {
162 bytecode.push(0xC4); bytecode.push(0x17);
164 bytecode.push((*index >> 8) as u8);
165 bytecode.push((*index & 0xFF) as u8);
166 }
167 }
168 JvmInstruction::Fload0 => bytecode.push(0x22),
169 JvmInstruction::Fload1 => bytecode.push(0x23),
170 JvmInstruction::Fload2 => bytecode.push(0x24),
171 JvmInstruction::Fload3 => bytecode.push(0x25),
172
173 JvmInstruction::Dload { index } => {
174 if *index <= 3 {
175 bytecode.push(0x26 + *index as u8);
176 }
177 else if *index <= 255 {
178 bytecode.push(0x18);
179 bytecode.push(*index as u8);
180 }
181 else {
182 bytecode.push(0xC4); bytecode.push(0x18);
184 bytecode.push((*index >> 8) as u8);
185 bytecode.push((*index & 0xFF) as u8);
186 }
187 }
188 JvmInstruction::Dload0 => bytecode.push(0x26),
189 JvmInstruction::Dload1 => bytecode.push(0x27),
190 JvmInstruction::Dload2 => bytecode.push(0x28),
191 JvmInstruction::Dload3 => bytecode.push(0x29),
192
193 JvmInstruction::Aload { index } => {
194 if *index <= 3 {
195 bytecode.push(0x2A + *index as u8);
196 }
197 else if *index <= 255 {
198 bytecode.push(0x19);
199 bytecode.push(*index as u8);
200 }
201 else {
202 bytecode.push(0xC4); bytecode.push(0x19);
204 bytecode.push((*index >> 8) as u8);
205 bytecode.push((*index & 0xFF) as u8);
206 }
207 }
208 JvmInstruction::Aload0 => bytecode.push(0x2A),
209 JvmInstruction::Aload1 => bytecode.push(0x2B),
210 JvmInstruction::Aload2 => bytecode.push(0x2C),
211 JvmInstruction::Aload3 => bytecode.push(0x2D),
212
213 JvmInstruction::Istore { index } => {
214 if *index <= 3 {
215 bytecode.push(0x3B + *index as u8);
216 }
217 else if *index <= 255 {
218 bytecode.push(0x36);
219 bytecode.push(*index as u8);
220 }
221 else {
222 bytecode.push(0xC4); bytecode.push(0x36);
224 bytecode.push((*index >> 8) as u8);
225 bytecode.push((*index & 0xFF) as u8);
226 }
227 }
228 JvmInstruction::Istore0 => bytecode.push(0x3B),
229 JvmInstruction::Istore1 => bytecode.push(0x3C),
230 JvmInstruction::Istore2 => bytecode.push(0x3D),
231 JvmInstruction::Istore3 => bytecode.push(0x3E),
232
233 JvmInstruction::Lstore { index } => {
234 if *index <= 3 {
235 bytecode.push(0x3F + *index as u8);
236 }
237 else if *index <= 255 {
238 bytecode.push(0x37);
239 bytecode.push(*index as u8);
240 }
241 else {
242 bytecode.push(0xC4); bytecode.push(0x37);
244 bytecode.push((*index >> 8) as u8);
245 bytecode.push((*index & 0xFF) as u8);
246 }
247 }
248 JvmInstruction::Lstore0 => bytecode.push(0x3F),
249 JvmInstruction::Lstore1 => bytecode.push(0x40),
250 JvmInstruction::Lstore2 => bytecode.push(0x41),
251 JvmInstruction::Lstore3 => bytecode.push(0x42),
252
253 JvmInstruction::Fstore { index } => {
254 if *index <= 3 {
255 bytecode.push(0x43 + *index as u8);
256 }
257 else if *index <= 255 {
258 bytecode.push(0x38);
259 bytecode.push(*index as u8);
260 }
261 else {
262 bytecode.push(0xC4); bytecode.push(0x38);
264 bytecode.push((*index >> 8) as u8);
265 bytecode.push((*index & 0xFF) as u8);
266 }
267 }
268 JvmInstruction::Fstore0 => bytecode.push(0x43),
269 JvmInstruction::Fstore1 => bytecode.push(0x44),
270 JvmInstruction::Fstore2 => bytecode.push(0x45),
271 JvmInstruction::Fstore3 => bytecode.push(0x46),
272
273 JvmInstruction::Dstore { index } => {
274 if *index <= 3 {
275 bytecode.push(0x47 + *index as u8);
276 }
277 else if *index <= 255 {
278 bytecode.push(0x39);
279 bytecode.push(*index as u8);
280 }
281 else {
282 bytecode.push(0xC4); bytecode.push(0x39);
284 bytecode.push((*index >> 8) as u8);
285 bytecode.push((*index & 0xFF) as u8);
286 }
287 }
288 JvmInstruction::Dstore0 => bytecode.push(0x47),
289 JvmInstruction::Dstore1 => bytecode.push(0x48),
290 JvmInstruction::Dstore2 => bytecode.push(0x49),
291 JvmInstruction::Dstore3 => bytecode.push(0x4A),
292
293 JvmInstruction::Astore { index } => {
294 if *index <= 3 {
295 bytecode.push(0x4B + *index as u8);
296 }
297 else if *index <= 255 {
298 bytecode.push(0x3A);
299 bytecode.push(*index as u8);
300 }
301 else {
302 bytecode.push(0xC4); bytecode.push(0x3A);
304 bytecode.push((*index >> 8) as u8);
305 bytecode.push((*index & 0xFF) as u8);
306 }
307 }
308 JvmInstruction::Astore0 => bytecode.push(0x4B),
309 JvmInstruction::Astore1 => bytecode.push(0x4C),
310 JvmInstruction::Astore2 => bytecode.push(0x4D),
311 JvmInstruction::Astore3 => bytecode.push(0x4E),
312
313 JvmInstruction::Pop => bytecode.push(0x57),
314 JvmInstruction::Pop2 => bytecode.push(0x58),
315 JvmInstruction::Dup => bytecode.push(0x59),
316 JvmInstruction::DupX1 => bytecode.push(0x5A),
317 JvmInstruction::DupX2 => bytecode.push(0x5B),
318 JvmInstruction::Dup2 => bytecode.push(0x5C),
319 JvmInstruction::Dup2X1 => bytecode.push(0x5D),
320 JvmInstruction::Dup2X2 => bytecode.push(0x5E),
321 JvmInstruction::Swap => bytecode.push(0x5F),
322
323 JvmInstruction::Iadd => bytecode.push(0x60),
324 JvmInstruction::Ladd => bytecode.push(0x61),
325 JvmInstruction::Fadd => bytecode.push(0x62),
326 JvmInstruction::Dadd => bytecode.push(0x63),
327 JvmInstruction::Isub => bytecode.push(0x64),
328 JvmInstruction::Lsub => bytecode.push(0x65),
329 JvmInstruction::Fsub => bytecode.push(0x66),
330 JvmInstruction::Dsub => bytecode.push(0x67),
331 JvmInstruction::Imul => bytecode.push(0x68),
332 JvmInstruction::Lmul => bytecode.push(0x69),
333 JvmInstruction::Fmul => bytecode.push(0x6A),
334 JvmInstruction::Dmul => bytecode.push(0x6B),
335 JvmInstruction::Idiv => bytecode.push(0x6C),
336 JvmInstruction::Ldiv => bytecode.push(0x6D),
337 JvmInstruction::Fdiv => bytecode.push(0x6E),
338 JvmInstruction::Ddiv => bytecode.push(0x6F),
339 JvmInstruction::Irem => bytecode.push(0x70),
340 JvmInstruction::Lrem => bytecode.push(0x71),
341 JvmInstruction::Frem => bytecode.push(0x72),
342 JvmInstruction::Drem => bytecode.push(0x73),
343 JvmInstruction::Ineg => bytecode.push(0x74),
344 JvmInstruction::Lneg => bytecode.push(0x75),
345 JvmInstruction::Fneg => bytecode.push(0x76),
346 JvmInstruction::Dneg => bytecode.push(0x77),
347
348 JvmInstruction::Ishl => bytecode.push(0x78),
349 JvmInstruction::Lshl => bytecode.push(0x79),
350 JvmInstruction::Ishr => bytecode.push(0x7A),
351 JvmInstruction::Lshr => bytecode.push(0x7B),
352 JvmInstruction::Iushr => bytecode.push(0x7C),
353 JvmInstruction::Lushr => bytecode.push(0x7D),
354 JvmInstruction::Iand => bytecode.push(0x7E),
355 JvmInstruction::Land => bytecode.push(0x7F),
356 JvmInstruction::Ior => bytecode.push(0x80),
357 JvmInstruction::Lor => bytecode.push(0x81),
358 JvmInstruction::Ixor => bytecode.push(0x82),
359 JvmInstruction::Lxor => bytecode.push(0x83),
360
361 JvmInstruction::Lcmp => bytecode.push(0x94),
362 JvmInstruction::Fcmpl => bytecode.push(0x95),
363 JvmInstruction::Fcmpg => bytecode.push(0x96),
364 JvmInstruction::Dcmpl => bytecode.push(0x97),
365 JvmInstruction::Dcmpg => bytecode.push(0x98),
366
367 JvmInstruction::Ifeq { target } => {
368 jump_patches.push((pos, pos + 1, target.clone(), false));
369 bytecode.push(0x99);
370 bytecode.push(0);
371 bytecode.push(0);
372 }
373 JvmInstruction::Ifne { target } => {
374 jump_patches.push((pos, pos + 1, target.clone(), false));
375 bytecode.push(0x9A);
376 bytecode.push(0);
377 bytecode.push(0);
378 }
379 JvmInstruction::Iflt { target } => {
380 jump_patches.push((pos, pos + 1, target.clone(), false));
381 bytecode.push(0x9B);
382 bytecode.push(0);
383 bytecode.push(0);
384 }
385 JvmInstruction::Ifge { target } => {
386 jump_patches.push((pos, pos + 1, target.clone(), false));
387 bytecode.push(0x9C);
388 bytecode.push(0);
389 bytecode.push(0);
390 }
391 JvmInstruction::Ifgt { target } => {
392 jump_patches.push((pos, pos + 1, target.clone(), false));
393 bytecode.push(0x9D);
394 bytecode.push(0);
395 bytecode.push(0);
396 }
397 JvmInstruction::Ifle { target } => {
398 jump_patches.push((pos, pos + 1, target.clone(), false));
399 bytecode.push(0x9E);
400 bytecode.push(0);
401 bytecode.push(0);
402 }
403 JvmInstruction::IfIcmpeq { target } => {
404 jump_patches.push((pos, pos + 1, target.clone(), false));
405 bytecode.push(0x9F);
406 bytecode.push(0);
407 bytecode.push(0);
408 }
409 JvmInstruction::IfIcmpne { target } => {
410 jump_patches.push((pos, pos + 1, target.clone(), false));
411 bytecode.push(0xA0);
412 bytecode.push(0);
413 bytecode.push(0);
414 }
415 JvmInstruction::IfIcmplt { target } => {
416 jump_patches.push((pos, pos + 1, target.clone(), false));
417 bytecode.push(0xA1);
418 bytecode.push(0);
419 bytecode.push(0);
420 }
421 JvmInstruction::IfIcmpge { target } => {
422 jump_patches.push((pos, pos + 1, target.clone(), false));
423 bytecode.push(0xA2);
424 bytecode.push(0);
425 bytecode.push(0);
426 }
427 JvmInstruction::IfIcmpgt { target } => {
428 jump_patches.push((pos, pos + 1, target.clone(), false));
429 bytecode.push(0xA3);
430 bytecode.push(0);
431 bytecode.push(0);
432 }
433 JvmInstruction::IfIcmple { target } => {
434 jump_patches.push((pos, pos + 1, target.clone(), false));
435 bytecode.push(0xA4);
436 bytecode.push(0);
437 bytecode.push(0);
438 }
439 JvmInstruction::IfAcmpeq { target } => {
440 jump_patches.push((pos, pos + 1, target.clone(), false));
441 bytecode.push(0xA5);
442 bytecode.push(0);
443 bytecode.push(0);
444 }
445 JvmInstruction::IfAcmpne { target } => {
446 jump_patches.push((pos, pos + 1, target.clone(), false));
447 bytecode.push(0xA6);
448 bytecode.push(0);
449 bytecode.push(0);
450 }
451 JvmInstruction::Ifnull { target } => {
452 jump_patches.push((pos, pos + 1, target.clone(), false));
453 bytecode.push(0xC6);
454 bytecode.push(0);
455 bytecode.push(0);
456 }
457 JvmInstruction::Ifnonnull { target } => {
458 jump_patches.push((pos, pos + 1, target.clone(), false));
459 bytecode.push(0xC7);
460 bytecode.push(0);
461 bytecode.push(0);
462 }
463 JvmInstruction::Goto { target } => {
464 jump_patches.push((pos, pos + 1, target.clone(), false));
465 bytecode.push(0xA7);
466 bytecode.push(0);
467 bytecode.push(0);
468 }
469 JvmInstruction::GotoW { target } => {
470 jump_patches.push((pos, pos + 1, target.clone(), true));
471 bytecode.push(0xC8);
472 bytecode.push(0);
473 bytecode.push(0);
474 bytecode.push(0);
475 bytecode.push(0);
476 }
477
478 JvmInstruction::Return => bytecode.push(0xB1),
479 JvmInstruction::Ireturn => bytecode.push(0xAC),
480 JvmInstruction::Lreturn => bytecode.push(0xAD),
481 JvmInstruction::Freturn => bytecode.push(0xAE),
482 JvmInstruction::Dreturn => bytecode.push(0xAF),
483 JvmInstruction::Areturn => bytecode.push(0xB0),
484
485 JvmInstruction::Arraylength => bytecode.push(0xBE),
486 JvmInstruction::Athrow => bytecode.push(0xBF),
487 JvmInstruction::Monitorenter => bytecode.push(0xC2),
488 JvmInstruction::Monitorexit => bytecode.push(0xC3),
489
490 JvmInstruction::Iaload => bytecode.push(0x2E),
491 JvmInstruction::Laload => bytecode.push(0x2F),
492 JvmInstruction::Faload => bytecode.push(0x30),
493 JvmInstruction::Daload => bytecode.push(0x31),
494 JvmInstruction::Aaload => bytecode.push(0x32),
495 JvmInstruction::Baload => bytecode.push(0x33),
496 JvmInstruction::Saload => bytecode.push(0x34),
497 JvmInstruction::Caload => bytecode.push(0x35),
498
499 JvmInstruction::Iastore => bytecode.push(0x4F),
500 JvmInstruction::Lastore => bytecode.push(0x50),
501 JvmInstruction::Fastore => bytecode.push(0x51),
502 JvmInstruction::Dastore => bytecode.push(0x52),
503 JvmInstruction::Aastore => bytecode.push(0x53),
504 JvmInstruction::Bastore => bytecode.push(0x54),
505 JvmInstruction::Sastore => bytecode.push(0x55),
506 JvmInstruction::Castore => bytecode.push(0x56),
507
508 JvmInstruction::Getstatic { class_name, field_name, descriptor } => {
509 let index = self.add_field_ref(class_name.clone(), field_name.clone(), descriptor.clone());
510 bytecode.push(0xB2); bytecode.push((index >> 8) as u8);
512 bytecode.push((index & 0xFF) as u8);
513 }
514 JvmInstruction::Putstatic { class_name, field_name, descriptor } => {
515 let index = self.add_field_ref(class_name.clone(), field_name.clone(), descriptor.clone());
516 bytecode.push(0xB3); bytecode.push((index >> 8) as u8);
518 bytecode.push((index & 0xFF) as u8);
519 }
520 JvmInstruction::Getfield { class_name, field_name, descriptor } => {
521 let index = self.add_field_ref(class_name.clone(), field_name.clone(), descriptor.clone());
522 bytecode.push(0xB4); bytecode.push((index >> 8) as u8);
524 bytecode.push((index & 0xFF) as u8);
525 }
526 JvmInstruction::Putfield { class_name, field_name, descriptor } => {
527 let index = self.add_field_ref(class_name.clone(), field_name.clone(), descriptor.clone());
528 bytecode.push(0xB5); bytecode.push((index >> 8) as u8);
530 bytecode.push((index & 0xFF) as u8);
531 }
532 JvmInstruction::Invokevirtual { class_name, method_name, descriptor } => {
533 let index = self.add_method_ref(class_name.clone(), method_name.clone(), descriptor.clone());
534 bytecode.push(0xB6); bytecode.push((index >> 8) as u8);
536 bytecode.push((index & 0xFF) as u8);
537 }
538 JvmInstruction::Invokespecial { class_name, method_name, descriptor } => {
539 let index = self.add_method_ref(class_name.clone(), method_name.clone(), descriptor.clone());
540 bytecode.push(0xB7); bytecode.push((index >> 8) as u8);
542 bytecode.push((index & 0xFF) as u8);
543 }
544 JvmInstruction::Invokestatic { class_name, method_name, descriptor } => {
545 let index = self.add_method_ref(class_name.clone(), method_name.clone(), descriptor.clone());
546 bytecode.push(0xB8); bytecode.push((index >> 8) as u8);
548 bytecode.push((index & 0xFF) as u8);
549 }
550 JvmInstruction::Invokeinterface { class_name, method_name, descriptor } => {
551 let index = self.add_interface_method_ref(class_name.clone(), method_name.clone(), descriptor.clone());
552 bytecode.push(0xB9); bytecode.push((index >> 8) as u8);
554 bytecode.push((index & 0xFF) as u8);
555
556 let count = calculate_parameter_count(descriptor) + 1;
558 bytecode.push(count as u8);
559 bytecode.push(0);
560 }
561 JvmInstruction::Invokedynamic { class_name, method_name, descriptor } => {
562 let index = self.add_method_ref(class_name.clone(), method_name.clone(), descriptor.clone());
563 bytecode.push(0xBA); bytecode.push((index >> 8) as u8);
565 bytecode.push((index & 0xFF) as u8);
566 bytecode.push(0);
567 bytecode.push(0);
568 }
569 JvmInstruction::New { class_name } => {
570 let index = self.add_class(class_name.clone());
571 bytecode.push(0xBB); bytecode.push((index >> 8) as u8);
573 bytecode.push((index & 0xFF) as u8);
574 }
575 JvmInstruction::Newarray { type_code } => {
576 bytecode.push(0xBC); bytecode.push(*type_code);
578 }
579 JvmInstruction::Anewarray { class_name } => {
580 let index = self.add_class(class_name.clone());
581 bytecode.push(0xBD); bytecode.push((index >> 8) as u8);
583 bytecode.push((index & 0xFF) as u8);
584 }
585 JvmInstruction::Multianewarray { class_name, dimensions } => {
586 let index = self.add_class(class_name.clone());
587 bytecode.push(0xC5); bytecode.push((index >> 8) as u8);
589 bytecode.push((index & 0xFF) as u8);
590 bytecode.push(*dimensions);
591 }
592 JvmInstruction::Checkcast { class_name } => {
593 let index = self.add_class(class_name.clone());
594 bytecode.push(0xC0); bytecode.push((index >> 8) as u8);
596 bytecode.push((index & 0xFF) as u8);
597 }
598 JvmInstruction::Instanceof { class_name } => {
599 let index = self.add_class(class_name.clone());
600 bytecode.push(0xC1); bytecode.push((index >> 8) as u8);
602 bytecode.push((index & 0xFF) as u8);
603 }
604 JvmInstruction::Jsr { target } => {
605 jump_patches.push((pos, pos + 1, target.clone(), false));
606 bytecode.push(0xA8); bytecode.push(0);
608 bytecode.push(0);
609 }
610 JvmInstruction::Ret { index } => {
611 if *index <= 255 {
612 bytecode.push(0xA9); bytecode.push(*index as u8);
614 }
615 else {
616 bytecode.push(0xC4); bytecode.push(0xA9);
618 bytecode.push((*index >> 8) as u8);
619 bytecode.push((*index & 0xFF) as u8);
620 }
621 }
622 JvmInstruction::Iinc { index, value } => {
623 if *index <= 255 && *value >= -128 && *value <= 127 {
624 bytecode.push(0x84); bytecode.push(*index as u8);
626 bytecode.push(*value as u8);
627 }
628 else {
629 bytecode.push(0xC4); bytecode.push(0x84);
631 bytecode.push((*index >> 8) as u8);
632 bytecode.push((*index & 0xFF) as u8);
633 bytecode.push((*value >> 8) as u8);
634 bytecode.push((*value & 0xFF) as u8);
635 }
636 }
637
638 JvmInstruction::I2l => bytecode.push(0x85),
639 JvmInstruction::I2f => bytecode.push(0x86),
640 JvmInstruction::I2d => bytecode.push(0x87),
641 JvmInstruction::L2i => bytecode.push(0x88),
642 JvmInstruction::L2f => bytecode.push(0x89),
643 JvmInstruction::L2d => bytecode.push(0x8A),
644 JvmInstruction::F2i => bytecode.push(0x8B),
645 JvmInstruction::F2l => bytecode.push(0x8C),
646 JvmInstruction::F2d => bytecode.push(0x8D),
647 JvmInstruction::D2i => bytecode.push(0x8E),
648 JvmInstruction::D2l => bytecode.push(0x8F),
649 JvmInstruction::D2f => bytecode.push(0x90),
650 JvmInstruction::I2b => bytecode.push(0x91),
651 JvmInstruction::I2c => bytecode.push(0x92),
652 JvmInstruction::I2s => bytecode.push(0x93),
653
654 JvmInstruction::JsrW { target } => {
655 jump_patches.push((pos, pos + 1, target.clone(), true));
656 bytecode.push(0xC9); bytecode.push(0);
658 bytecode.push(0);
659 bytecode.push(0);
660 bytecode.push(0);
661 }
662
663 JvmInstruction::Lookupswitch { default, npairs, match_offsets } => {
664 bytecode.push(0xAB); let padding = (4 - (bytecode.len() % 4)) % 4;
668 for _ in 0..padding {
669 bytecode.push(0);
670 }
671
672 let default_patch_pos = bytecode.len();
674 jump_patches.push((pos, default_patch_pos, default.clone(), true));
675 bytecode.push(0);
676 bytecode.push(0);
677 bytecode.push(0);
678 bytecode.push(0);
679
680 bytecode.push((*npairs >> 24) as u8);
682 bytecode.push((*npairs >> 16) as u8);
683 bytecode.push((*npairs >> 8) as u8);
684 bytecode.push(*npairs as u8);
685
686 for (val, target) in match_offsets {
688 bytecode.push((val >> 24) as u8);
690 bytecode.push((val >> 16) as u8);
691 bytecode.push((val >> 8) as u8);
692 bytecode.push(*val as u8);
693
694 let patch_pos = bytecode.len();
696 jump_patches.push((pos, patch_pos, target.clone(), true));
697 bytecode.push(0);
698 bytecode.push(0);
699 bytecode.push(0);
700 bytecode.push(0);
701 }
702 }
703 JvmInstruction::Tableswitch { default, low, high, offsets } => {
704 bytecode.push(0xAA); let padding = (4 - (bytecode.len() % 4)) % 4;
708 for _ in 0..padding {
709 bytecode.push(0);
710 }
711
712 let default_patch_pos = bytecode.len();
714 jump_patches.push((pos, default_patch_pos, default.clone(), true));
715 bytecode.push(0);
716 bytecode.push(0);
717 bytecode.push(0);
718 bytecode.push(0);
719
720 bytecode.push((*low >> 24) as u8);
722 bytecode.push((*low >> 16) as u8);
723 bytecode.push((*low >> 8) as u8);
724 bytecode.push(*low as u8);
725
726 bytecode.push((*high >> 24) as u8);
728 bytecode.push((*high >> 16) as u8);
729 bytecode.push((*high >> 8) as u8);
730 bytecode.push(*high as u8);
731
732 for target in offsets {
734 let patch_pos = bytecode.len();
735 jump_patches.push((pos, patch_pos, target.clone(), true));
736 bytecode.push(0);
737 bytecode.push(0);
738 bytecode.push(0);
739 bytecode.push(0);
740 }
741 }
742 JvmInstruction::Wide => {
743 bytecode.push(0xC4);
747 }
748 JvmInstruction::Label { .. } => {
749 }
751 }
752 }
753}