| NHIRInstruction.java |
1 // Copyright 2012- Bill Campbell, Swami Iyer and Bahar Akbal-Delibas
2
3 package jminusminus;
4
5 import java.util.ArrayList;
6
7 import static jminusminus.CLConstants.*;
8 import static jminusminus.NPhysicalRegister.*;
9
10 /**
11 * This abstract base class provides a high-level intermediate representation (HIR) of a JVM
12 * instruction.
13 */
14 abstract class NHIRInstruction {
15 /**
16 * Maps JVM opcode to a string mnemonic for HIR instructions. For example, the opcode imul is
17 * mapped to the string "*".
18 */
19 protected static String[] hirMnemonic;
20
21 static {
22 hirMnemonic = new String[256];
23 hirMnemonic[IADD] = "+";
24 hirMnemonic[ISUB] = "-";
25 hirMnemonic[IMUL] = "*";
26 hirMnemonic[MULTIANEWARRAY] = "multianewarray";
27 hirMnemonic[AALOAD] = "aaload";
28 hirMnemonic[IALOAD] = "iaload";
29 hirMnemonic[IASTORE] = "iastore";
30 hirMnemonic[IF_ICMPNE] = "!=";
31 hirMnemonic[IF_ICMPGT] = ">";
32 hirMnemonic[IF_ICMPLE] = "<=";
33 hirMnemonic[GETSTATIC] = "getstatic";
34 hirMnemonic[PUTSTATIC] = "putstatic";
35 hirMnemonic[INVOKESPECIAL] = "invokespecial";
36 hirMnemonic[INVOKESTATIC] = "invokestatic";
37 hirMnemonic[ARETURN] = "areturn";
38 hirMnemonic[RETURN] = "return";
39 hirMnemonic[IRETURN] = "ireturn";
40 }
41
42 /**
43 * The block containing this instruction.
44 */
45 public NBasicBlock block;
46
47 /**
48 * Unique identifier of this instruction.
49 */
50 public int id;
51
52 /**
53 * Short type name for this instruction.
54 */
55 public String sType;
56
57 /**
58 * Long type name for this instruction.
59 */
60 public String lType;
61
62 /**
63 * The LIR instruction corresponding to this HIR instruction.
64 */
65 public NLIRInstruction lir;
66
67 /**
68 * Constructs a NHIRInstruction object.
69 *
70 * @param block enclosing block.
71 * @param id identifier of the instruction.
72 */
73 protected NHIRInstruction(NBasicBlock block, int id) {
74 this(block, id, "", "");
75 }
76
77 /**
78 * Constructs a NHIRInstruction object.
79 *
80 * @param block enclosing block.
81 * @param id identifier of the instruction.
82 * @param sType short type name of the instruction.
83 * @param lType long type name of the instruction.
84 */
85 protected NHIRInstruction(NBasicBlock block, int id, String sType, String lType) {
86 this.block = block;
87 this.id = id;
88 this.sType = sType;
89 this.lType = lType;
90 }
91
92 /**
93 * Returns true if this instruction is the same as the other, and false otherwise.
94 *
95 * @param other the instruction to compare to.
96 * @return true if this instruction is the same as the other, and false otherwise.
97 */
98 public boolean equals(NHIRInstruction other) {
99 return this.id == other.id;
100 }
101
102 /**
103 * Converts and returns a low-level representation (LIR) of this HIR instruction. Also adds
104 * the returned LIR instruction to the list of LIR instructions for the block containing this
105 * instruction, along with any other intermediate LIR instructions needed.
106 *
107 * @return the LIR instruction corresponding to this HIR instruction.
108 */
109 public NLIRInstruction toLir() {
110 return null;
111 }
112
113 /**
114 * Returns the identifier of this instruction with the short type name prefix.
115 *
116 * @return the identifier of this instruction with the short type name prefix.
117 */
118 public String id() {
119 return sType + id;
120 }
121
122 /**
123 * Returns a string representation of this instruction.
124 *
125 * @return a string representation of this instruction.
126 */
127 public String toString() {
128 return sType + id;
129 }
130 }
131
132 /**
133 * HIR instruction corresponding to the JVM arithmetic instructions.
134 */
135 class NHIRArithmetic extends NHIRInstruction {
136 // Opcode for the arithmetic operator.
137 private int opcode;
138
139 // Lhs HIR id.
140 private int lhs;
141
142 // Rhs HIR id.
143 private int rhs;
144
145 /**
146 * Constructs an NHIRArithmetic object.
147 *
148 * @param block enclosing block.
149 * @param id identifier of the instruction.
150 * @param opcode opcode for the arithmetic operator.
151 * @param lhs lhs HIR id.
152 * @param rhs rhs HIR id.
153 */
154 public NHIRArithmetic(NBasicBlock block, int id, int opcode, int lhs, int rhs) {
155 super(block, id, "I", "I");
156 this.opcode = opcode;
157 this.lhs = lhs;
158 this.rhs = rhs;
159 }
160
161 /**
162 * {@inheritDoc}
163 */
164 public NLIRInstruction toLir() {
165 if (lir != null) {
166 return lir;
167 }
168 NLIRInstruction ins1 = block.cfg.hirMap.get(lhs).toLir();
169 NLIRInstruction ins2 = block.cfg.hirMap.get(rhs).toLir();
170 lir = new NLIRArithmetic(block, NControlFlowGraph.lirId++, opcode, ins1, ins2);
171 block.lir.add(lir);
172 return lir;
173 }
174
175 /**
176 * {@inheritDoc}
177 */
178 public String toString() {
179 return id() + ": " + block.cfg.hirMap.get(lhs).id() + " " + hirMnemonic[opcode] + " " +
180 block.cfg.hirMap.get(rhs).id();
181 }
182 }
183
184 /**
185 * HIR instruction corresponding to the JVM instructions representing integer constants.
186 */
187 class NHIRIntConstant extends NHIRInstruction {
188 // The constant int value.
189 private int value;
190
191 /**
192 * Constructs an NHIRIntConstant object.
193 *
194 * @param block enclosing block.
195 * @param id identifier of the instruction.
196 * @param value the constant int value.
197 */
198 public NHIRIntConstant(NBasicBlock block, int id, int value) {
199 super(block, id, "I", "I");
200 this.value = value;
201 }
202
203 /**
204 * {@inheritDoc}
205 */
206 public NLIRInstruction toLir() {
207 if (lir != null) {
208 return lir;
209 }
210 lir = new NLIRIntConstant(block, NControlFlowGraph.lirId++, value);
211 block.lir.add(lir);
212 return lir;
213 }
214
215 /**
216 * {@inheritDoc}
217 */
218 public String toString() {
219 return id() + ": " + value;
220 }
221 }
222
223 /**
224 * HIR instruction corresponding to the JVM instructions representing string
225 * constants.
226 */
227
228 class NHIRStringConstant extends NHIRInstruction {
229 // The constant string value.
230 private String value;
231
232 /**
233 * Constructs an NHIRStringConstant object.
234 *
235 * @param block enclosing block.
236 * @param id identifier for the instruction.
237 * @param value the constant string value.
238 */
239 public NHIRStringConstant(NBasicBlock block, int id, String value) {
240 super(block, id, "L", "Ljava/lang/String;");
241 this.value = value;
242 }
243
244 /**
245 * {@inheritDoc}
246 */
247 public NLIRInstruction toLir() {
248 if (lir != null) {
249 return lir;
250 }
251 lir = new NLIRStringConstant(block, NControlFlowGraph.lirId++, value);
252 block.lir.add(lir);
253 return lir;
254 }
255
256 /**
257 * {@inheritDoc}
258 */
259 public String toString() {
260 return id() + ": \"" + value + "\"";
261 }
262 }
263
264 /**
265 * HIR instruction representing an conditional jump instructions in JVM.
266 */
267 class NHIRConditionalJump extends NHIRInstruction {
268 // Lhs HIR id.
269 private int lhs;
270
271 // Rhs HIR id.
272 private int rhs;
273
274 // Test expression opcode.
275 private int opcode;
276
277 // Block to jump to on true.
278 private NBasicBlock onTrueDestination;
279
280 // Block to jump to on false.
281 private NBasicBlock onFalseDestination;
282
283 /**
284 * Constructs an NHIRConditionalJump object.
285 *
286 * @param block enclosing block.
287 * @param id identifier of the instruction.
288 * @param lhs Lhs HIR id.
289 * @param rhs Rhs HIR id.
290 * @param opcode opcode in the test.
291 * @param onTrueDestination block to jump to on true.
292 * @param onFalseDestination block to jump to on false.
293 */
294 public NHIRConditionalJump(NBasicBlock block, int id, int lhs, int rhs, int opcode,
295 NBasicBlock onTrueDestination, NBasicBlock onFalseDestination) {
296 super(block, id, "", "");
297 this.lhs = lhs;
298 this.rhs = rhs;
299 this.opcode = opcode;
300 this.onTrueDestination = onTrueDestination;
301 this.onFalseDestination = onFalseDestination;
302 }
303
304 /**
305 * {@inheritDoc}
306 */
307 public NLIRInstruction toLir() {
308 if (lir != null) {
309 return lir;
310 }
311 NLIRInstruction ins1 = block.cfg.hirMap.get(lhs).toLir();
312 NLIRInstruction ins2 = block.cfg.hirMap.get(rhs).toLir();
313 lir = new NLIRConditionalJump(block, NControlFlowGraph.lirId++, ins1, ins2, opcode,
314 onTrueDestination, onFalseDestination);
315 block.lir.add(lir);
316 return lir;
317 }
318
319 /**
320 * {@inheritDoc}
321 */
322 public String toString() {
323 return id() + ": if " + block.cfg.hirMap.get(lhs).id() + " " + hirMnemonic[opcode] + " " +
324 block.cfg.hirMap.get(rhs).id() + " then " + onTrueDestination.id() + " else " +
325 onFalseDestination.id();
326 }
327 }
328
329 /**
330 * HIR instruction representing an unconditional jump instruction in JVM.
331 */
332 class NHIRGoto extends NHIRInstruction {
333 // The destination block to unconditionally jump to.
334 private NBasicBlock destination;
335
336 /**
337 * Constructs an NHIRGoto object.
338 *
339 * @param block enclosing block.
340 * @param id identifier of the instruction.
341 * @param destination the block to jump to.
342 */
343 public NHIRGoto(NBasicBlock block, int id, NBasicBlock destination) {
344 super(block, id, "", "");
345 this.destination = destination;
346 }
347
348 /**
349 * {@inheritDoc}
350 */
351 public NLIRInstruction toLir() {
352 if (lir != null) {
353 return lir;
354 }
355 lir = new NLIRGoto(block, NControlFlowGraph.lirId++, destination);
356 block.lir.add(lir);
357 return lir;
358 }
359
360 /**
361 * {@inheritDoc}
362 */
363 public String toString() {
364 return id() + ": goto " + destination.id();
365 }
366 }
367
368 /**
369 * HIR instruction representing method invocation instructions in JVM.
370 */
371 class NHIRInvoke extends NHIRInstruction {
372 // Opcode of the JVM instruction.
373 private int opcode;
374
375 // Target for the method.
376 private String target;
377
378 // Name of the method being invoked.
379 private String name;
380
381 // List of HIR ids of arguments for the method.
382 private ArrayList<Integer> arguments;
383
384 /**
385 * Constructs an NHIRInvoke object.
386 *
387 * @param block enclosing block.
388 * @param id identifier of the instruction.
389 * @param opcode opcode of the JVM instruction.
390 * @param target target of the method.
391 * @param name name of the method.
392 * @param arguments list of HIR ids of arguments for the method.
393 * @param sType return type (short name) of the method.
394 * @param lType return type (long name) of the method.
395 */
396 public NHIRInvoke(NBasicBlock block, int id, int opcode, String target, String name,
397 ArrayList<Integer> arguments, String sType, String lType) {
398 super(block, id, sType, lType);
399 this.opcode = opcode;
400 this.target = target;
401 this.name = name;
402 this.arguments = arguments;
403 }
404
405 /**
406 * {@inheritDoc}
407 */
408 public NLIRInstruction toLir() {
409 if (lir != null) {
410 return lir;
411 }
412
413 // First four arguments are stored in physical registers (a0, ..., a3) and the rest are
414 // on the stack. Allocate space on stack for arguments fourth or above; [0, block.cfg
415 // .offset - 1].
416 if (this.arguments.size() - 4 > block.cfg.offset) {
417 block.cfg.offset = this.arguments.size() - 4;
418 }
419
420 ArrayList<NRegister> arguments = new ArrayList<NRegister>();
421 ArrayList<NPhysicalRegister> froms = new ArrayList<NPhysicalRegister>();
422 ArrayList<NVirtualRegister> tos = new ArrayList<NVirtualRegister>();
423 for (int i = 0; i < this.arguments.size(); i++) {
424 int arg = this.arguments.get(i);
425 NLIRInstruction ins = block.cfg.hirMap.get(arg).toLir();
426 if (i < 4) {
427 // Generate an LIR move instruction (move1) to save away the physical register a0
428 // + i into a virtual register, and another LIR move instruction (move2) to copy
429 // the argument from the virtual register it's in to the physical register a0 + i.
430 String sType = block.cfg.hirMap.get(arg).sType;
431 String lType = block.cfg.hirMap.get(arg).lType;
432 NPhysicalRegister from = NPhysicalRegister.regInfo[A0 + i];
433 block.cfg.registers.set(A0 + i, from);
434 NVirtualRegister to = new NVirtualRegister(NControlFlowGraph.regId++, sType, lType);
435 block.cfg.registers.add(to);
436 NLIRMove move1 = new NLIRMove(block, NControlFlowGraph.lirId++, from, to);
437 block.lir.add(move1);
438 NLIRMove move2 = new NLIRMove(block, NControlFlowGraph.lirId++, ins.write, from);
439 block.lir.add(move2);
440 arguments.add(NPhysicalRegister.regInfo[A0 + i]);
441
442 // Remember the froms and the tos so we can restore the values of a0 + i registers.
443 froms.add(from);
444 tos.add(to);
445 } else {
446 NLIRStore store = new NLIRStore(block, NControlFlowGraph.lirId++, i - 4,
447 OffsetFrom.SP, ins.write);
448 block.lir.add(store);
449 arguments.add(ins.write);
450 }
451 }
452 lir = new NLIRInvoke(block, NControlFlowGraph.lirId++, opcode, target, name, arguments,
453 sType, lType);
454 block.lir.add(lir);
455
456 // If the function returns a value, generate an LIR move instruction to save away the
457 // value in the physical register v0 into a virtual register.
458 if (lir.write != null) {
459 NVirtualRegister to = new NVirtualRegister(NControlFlowGraph.regId++, sType, lType);
460 NLIRMove move = new NLIRMove(block, NControlFlowGraph.lirId++,
461 NPhysicalRegister.regInfo[V0], to);
462 block.cfg.registers.add(to);
463 block.lir.add(move);
464 lir = move;
465 }
466
467 // Generate LIR move instructions to restore the a0, ..., a3 instructions.
468 for (int i = 0; i < tos.size(); i++) {
469 NLIRMove move = new NLIRMove(block, NControlFlowGraph.lirId++, tos.get(i),
470 froms.get(i));
471 block.lir.add(move);
472 }
473 return lir;
474 }
475
476 /**
477 * {@inheritDoc}
478 */
479 public String toString() {
480 String s = id() + ": " + hirMnemonic[opcode] + " " + target + "." + name + "( ";
481 for (int arg : arguments) {
482 s += block.cfg.hirMap.get(arg).id() + " ";
483 }
484 s += ")";
485 return s;
486 }
487 }
488
489 /**
490 * HIR instruction representing a JVM return instruction.
491 */
492 class NHIRReturn extends NHIRInstruction {
493 // JVM opcode for the return instruction.
494 private int opcode;
495
496 // Return value HIR id.
497 private int value;
498
499 /**
500 * Constructs an NHIRReturn object.
501 *
502 * @param block enclosing block.
503 * @param id identifier of the instruction.
504 * @param opcode JVM opcode for the return instruction.
505 * @param value return value HIR id.
506 */
507 public NHIRReturn(NBasicBlock block, int id, int opcode, int value) {
508 super(block, id, value == -1 ? "" : block.cfg.hirMap.get(value).sType,
509 value == -1 ? "" : block.cfg.hirMap.get(value).lType);
510 this.opcode = opcode;
511 this.value = value;
512 }
513
514 /**
515 * {@inheritDoc}
516 */
517 public NLIRInstruction toLir() {
518 if (lir != null) {
519 return lir;
520 }
521 NLIRInstruction result = null;
522 if (value != -1) {
523 result = block.cfg.hirMap.get(value).toLir();
524 NLIRMove move = new NLIRMove(block, NControlFlowGraph.lirId++, result.write,
525 NPhysicalRegister.regInfo[V0]);
526 block.lir.add(move);
527 block.cfg.registers.set(V0, NPhysicalRegister.regInfo[V0]);
528 }
529 lir = new NLIRReturn(block, NControlFlowGraph.lirId++, opcode, result == null ? null :
530 NPhysicalRegister.regInfo[V0]);
531 block.lir.add(lir);
532 return lir;
533 }
534
535 /**
536 * {@inheritDoc}
537 */
538 public String toString() {
539 if (value == -1) {
540 return id() + ": " + hirMnemonic[opcode];
541 }
542 return id() + ": " + hirMnemonic[opcode] + " " + block.cfg.hirMap.get(value).id();
543 }
544 }
545
546 /**
547 * HIR instruction representing JVM (put) field instructions.
548 */
549 class NHIRPutField extends NHIRInstruction {
550 // Opcode of the JVM instruction.
551 private int opcode;
552
553 // Target for the field.
554 private String target;
555
556 // Name of the field being accessed.
557 private String name;
558
559 // HIR id of the value of the field.
560 private int value;
561
562 /**
563 * Constructs an NHIRPutField object.
564 *
565 * @param block enclosing block.
566 * @param id identifier of the instruction.
567 * @param opcode JVM opcode for the instruction.
568 * @param target target for the field.
569 * @param name name of the field.
570 * @param sType type (short name) of the field.
571 * @param lType type (long name) of the field.
572 * @param value HIR id of the value of the field.
573 */
574 public NHIRPutField(NBasicBlock block, int id, int opcode, String target, String name,
575 String sType, String lType, int value) {
576 super(block, id, sType, lType);
577 this.opcode = opcode;
578 this.target = target;
579 this.name = name;
580 this.value = value;
581 }
582
583 /**
584 * {@inheritDoc}
585 */
586 public NLIRInstruction toLir() {
587 if (lir != null) {
588 return lir;
589 }
590 NLIRInstruction result = block.cfg.hirMap.get(value).toLir();
591 lir = new NLIRPutField(block, NControlFlowGraph.lirId++, opcode, target, name, sType,
592 lType, result);
593 block.lir.add(lir);
594 return lir;
595 }
596
597 /**
598 * {@inheritDoc}
599 */
600 public String toString() {
601 return id() + ": " + hirMnemonic[opcode] + " " + target + "." + name + " = " +
602 block.cfg.hirMap.get(value).id();
603 }
604 }
605
606 /**
607 * HIR instruction representing JVM (get) field instructions.
608 */
609 class NHIRGetField extends NHIRInstruction {
610 // Opcode of the JVM instruction.
611 private int opcode;
612
613 // Target for the field.
614 private String target;
615
616 // Name of the field being accessed.
617 private String name;
618
619 /**
620 * Constructs an NHIRGetField object.
621 *
622 * @param block enclosing block.
623 * @param id identifier of the instruction.
624 * @param opcode JVM opcode for the instruction.
625 * @param target target for the field.
626 * @param name name of the field.
627 * @param sType type (short name) of the field.
628 * @param lType type (long name) of the field.
629 */
630 public NHIRGetField(NBasicBlock block, int id, int opcode, String target, String name,
631 String sType, String lType) {
632 super(block, id, sType, lType);
633 this.opcode = opcode;
634 this.target = target;
635 this.name = name;
636 }
637
638 /**
639 * {@inheritDoc}
640 */
641 public NLIRInstruction toLir() {
642 if (lir != null) {
643 return lir;
644 }
645 lir = new NLIRGetField(block, NControlFlowGraph.lirId++, opcode, target, name, sType,
646 lType);
647 block.lir.add(lir);
648 return lir;
649 }
650
651 /**
652 * {@inheritDoc}
653 */
654 public String toString() {
655 return id() + ": " + hirMnemonic[opcode] + " " + target + "." + name;
656 }
657 }
658
659 /**
660 * HIR instruction representing JVM array creation instructions.
661 */
662 class NHIRNewArray extends NHIRInstruction {
663 // Opcode of the JVM instruction.
664 private int opcode;
665
666 // Dimension of the array.
667 private int dim;
668
669 /**
670 * Constructs an NHIRNewArray object.
671 *
672 * @param block enclosing block.
673 * @param id identifier of the instruction.
674 * @param opcode JVM opcode for the instruction.
675 * @param dim dimension of the array.
676 * @param sType type (short name) of the array.
677 * @param lType type (long name) of the array.
678 */
679 public NHIRNewArray(NBasicBlock block, int id, int opcode, int dim, String sType,
680 String lType) {
681 super(block, id, lType, sType);
682 this.opcode = opcode;
683 this.dim = dim;
684 }
685
686 /**
687 * {@inheritDoc}
688 */
689 public NLIRInstruction toLir() {
690 if (lir != null) {
691 return lir;
692 }
693 lir = new NLIRNewArray(block, NControlFlowGraph.lirId++, opcode, dim, sType, lType);
694 block.lir.add(lir);
695 return lir;
696 }
697
698 /**
699 * {@inheritDoc}
700 */
701 public String toString() {
702 return id() + ": " + hirMnemonic[opcode] + " " + lType + " [" + dim + "]";
703 }
704 }
705
706 /**
707 * HIR instruction representing JVM array load instructions.
708 */
709 class NHIRALoad extends NHIRInstruction {
710 // Opcode of the JVM instruction.
711 private int opcode;
712
713 // HIR id of the array reference.
714 private int arrayRef;
715
716 // HIR id of the array index.
717 private int index;
718
719 /**
720 * Constructs an NHIRALoad object.
721 *
722 * @param block enclosing block.
723 * @param id identifier of the instruction.
724 * @param opcode JVM opcode for the instruction.
725 * @param arrayRef HIR id of the array reference.
726 * @param index HIR id of the the array index.
727 * @param sType type (short name) of the array.
728 * @param lType type (long name) of the array.
729 */
730 public NHIRALoad(NBasicBlock block, int id, int opcode, int arrayRef, int index,
731 String sType, String lType) {
732 super(block, id, sType, lType);
733 this.opcode = opcode;
734 this.arrayRef = arrayRef;
735 this.index = index;
736 }
737
738 /**
739 * {@inheritDoc}
740 */
741 public NLIRInstruction toLir() {
742 if (lir != null) {
743 return lir;
744 }
745 NLIRInstruction arrayRef = block.cfg.hirMap.get(this.arrayRef).toLir();
746 NLIRInstruction index = block.cfg.hirMap.get(this.index).toLir();
747 lir = new NLIRALoad(block, NControlFlowGraph.lirId++, opcode, arrayRef, index, sType,
748 lType);
749 block.lir.add(lir);
750 return lir;
751 }
752
753 /**
754 * {@inheritDoc}
755 */
756 public String toString() {
757 return id() + ": " + hirMnemonic[opcode] + " " + block.cfg.hirMap.get(arrayRef).id() +
758 "[" + block.cfg.hirMap.get(index).id() + "]";
759 }
760 }
761
762 /**
763 * HIR instruction representing JVM array store instructions.
764 */
765 class NHIRAStore extends NHIRInstruction {
766 // Opcode of the JVM instruction.
767 private int opcode;
768
769 // HIR id of the array reference.
770 private int arrayRef;
771
772 // HIR id of the array index.
773 private int index;
774
775 // HIR id of the value to store.
776 private int value;
777
778 /**
779 * Constructs an NHIRAStore object.
780 *
781 * @param block enclosing block.
782 * @param id identifier of the instruction.
783 * @param opcode JVM opcode for the instruction.
784 * @param arrayRef HIR id of the array reference.
785 * @param index HIR id of the array index.
786 * @param value HIR id of the value to store.
787 * @param sType type (short name) of the array.
788 * @param lType type (long name) of the array.
789 */
790 public NHIRAStore(NBasicBlock block, int id, int opcode, int arrayRef, int index, int value,
791 String sType, String lType) {
792 super(block, id, sType, lType);
793 this.opcode = opcode;
794 this.arrayRef = arrayRef;
795 this.index = index;
796 this.value = value;
797 }
798
799 /**
800 * {@inheritDoc}
801 */
802 public NLIRInstruction toLir() {
803 if (lir != null) {
804 return lir;
805 }
806 NLIRInstruction arrayRef = block.cfg.hirMap.get(this.arrayRef).toLir();
807 NLIRInstruction index = block.cfg.hirMap.get(this.index).toLir();
808 NLIRInstruction value = block.cfg.hirMap.get(this.value).toLir();
809 lir = new NLIRAStore(block, NControlFlowGraph.lirId++, opcode, arrayRef, index, value,
810 sType, lType);
811 block.lir.add(lir);
812 return lir;
813 }
814
815 /**
816 * {@inheritDoc}
817 */
818 public String toString() {
819 return id() + ": " + hirMnemonic[opcode] + " " + block.cfg.hirMap.get(arrayRef).id() +
820 "[" + block.cfg.hirMap.get(index).id() + "] = " + block.cfg.hirMap.get(value).id();
821 }
822 }
823
824 /**
825 * HIR instruction representing phi functions.
826 */
827 class NHIRPhiFunction extends NHIRInstruction {
828
829 // List of HIR ids of arguments for the phi function.
830 private ArrayList<Integer> arguments;
831
832 // Local variable index.
833 private int local;
834
835 /**
836 * Constructs an NHIRPhiFunction object.
837 *
838 * @param block enclosing block.
839 * @param id identifier of the instruction.
840 * @param arguments list of HIR ids of arguments for the phi function.
841 * @param local local variable index.
842 */
843 public NHIRPhiFunction(NBasicBlock block, int id, ArrayList<Integer> arguments, int local) {
844 super(block, id, "", "");
845 this.arguments = arguments;
846 this.local = local;
847 }
848
849 /**
850 * Returns a list containing the ids of arguments for this phi function.
851 *
852 * @return a list containing the ids of arguments for this phi function.
853 */
854 public ArrayList<Integer> getArguments() {
855 return arguments;
856 }
857
858 /**
859 * Returns the local variable index for this phi function.
860 *
861 * @return the local variable index for this phi function.
862 */
863 public int getLocal() {
864 return local;
865 }
866
867 /**
868 * Infers type for this phi function, which is essentially the type of the arguments.
869 */
870 public void inferType() {
871 for (int arg : arguments) {
872 if (!block.cfg.hirMap.get(arguments.get(0)).sType.equals("")) {
873 sType = block.cfg.hirMap.get(arguments.get(0)).sType;
874 lType = block.cfg.hirMap.get(arguments.get(0)).lType;
875 break;
876 }
877 }
878 }
879
880 /**
881 * {@inheritDoc}
882 */
883 public NLIRInstruction toLir() {
884 if (lir != null) {
885 return lir;
886 }
887 lir = new NLIRPhiFunction(block, NControlFlowGraph.lirId++, sType, lType);
888 return lir;
889 }
890
891 /**
892 * {@inheritDoc}
893 */
894 public String toString() {
895 String s = "[ ";
896 for (int ins : arguments) {
897 if (block.cfg.hirMap.get(ins) != null)
898 s += block.cfg.hirMap.get(ins).sType + ins + " ";
899 }
900 s += "]";
901 return s;
902 }
903 }
904
905 /**
906 * HIR instruction representing a formal parameter.
907 */
908 class NHIRLoadLocal extends NHIRInstruction {
909 // Local variable index.
910 private int local;
911
912 /**
913 * Constructs an NHIRLoadLocal object.
914 *
915 * @param block enclosing block.
916 * @param id identifier of the instruction.
917 * @param local local variable index.
918 * @param sType short type name of the instruction.
919 * @param lType long type name of the instruction.
920 */
921 public NHIRLoadLocal(NBasicBlock block, int id, int local, String sType, String lType) {
922 super(block, id, sType, lType);
923 this.local = local;
924 }
925
926 /**
927 * {@inheritDoc}
928 */
929 public NLIRInstruction toLir() {
930 if (lir != null) {
931 return lir;
932 }
933 lir = new NLIRLoadLocal(block, NControlFlowGraph.lirId++, local, sType, lType);
934 block.lir.add(lir);
935 return lir;
936 }
937
938 /**
939 * {@inheritDoc}
940 */
941 public String toString() {
942 return id() + ": LDLOC " + local;
943 }
944 }
945
946 /**
947 * HIR instruction representing a local (not formal) variable.
948 */
949 class NHIRLocal extends NHIRInstruction {
950 // Local variable index.
951 private int local;
952
953 /**
954 * Constructs an NHIRLocal object.
955 *
956 * @param block enclosing block.
957 * @param id identifier of the instruction.
958 * @param local local variable index.
959 * @param sType short type name of the instruction.
960 * @param lType long type name of the instruction.
961 */
962 public NHIRLocal(NBasicBlock block, int id, int local, String sType, String lType) {
963 super(block, id, sType, lType);
964 this.local = local;
965 }
966
967 /**
968 * {@inheritDoc}
969 */
970 public String toString() {
971 return id() + ": LOC " + lType;
972 }
973 }
974