1
3 package jminusminus;
4
5 import java.util.ArrayList;
6
7 import static jminusminus.CLConstants.*;
8 import static jminusminus.NPhysicalRegister.*;
9
10
14 abstract class NHIRInstruction {
15
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
45 public NBasicBlock block;
46
47
50 public int id;
51
52
55 public String sType;
56
57
60 public String lType;
61
62
65 public NLIRInstruction lir;
66
67
73 protected NHIRInstruction(NBasicBlock block, int id) {
74 this(block, id, "", "");
75 }
76
77
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
98 public boolean equals(NHIRInstruction other) {
99 return this.id == other.id;
100 }
101
102
109 public NLIRInstruction toLir() {
110 return null;
111 }
112
113
118 public String id() {
119 return sType + id;
120 }
121
122
127 public String toString() {
128 return sType + id;
129 }
130 }
131
132
135 class NHIRArithmetic extends NHIRInstruction {
136 private int opcode;
138
139 private int lhs;
141
142 private int rhs;
144
145
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
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
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
187 class NHIRIntConstant extends NHIRInstruction {
188 private int value;
190
191
198 public NHIRIntConstant(NBasicBlock block, int id, int value) {
199 super(block, id, "I", "I");
200 this.value = value;
201 }
202
203
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
218 public String toString() {
219 return id() + ": " + value;
220 }
221 }
222
223
227
228 class NHIRStringConstant extends NHIRInstruction {
229 private String value;
231
232
239 public NHIRStringConstant(NBasicBlock block, int id, String value) {
240 super(block, id, "L", "Ljava/lang/String;");
241 this.value = value;
242 }
243
244
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
259 public String toString() {
260 return id() + ": \"" + value + "\"";
261 }
262 }
263
264
267 class NHIRConditionalJump extends NHIRInstruction {
268 private int lhs;
270
271 private int rhs;
273
274 private int opcode;
276
277 private NBasicBlock onTrueDestination;
279
280 private NBasicBlock onFalseDestination;
282
283
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
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
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
332 class NHIRGoto extends NHIRInstruction {
333 private NBasicBlock destination;
335
336
343 public NHIRGoto(NBasicBlock block, int id, NBasicBlock destination) {
344 super(block, id, "", "");
345 this.destination = destination;
346 }
347
348
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
363 public String toString() {
364 return id() + ": goto " + destination.id();
365 }
366 }
367
368
371 class NHIRInvoke extends NHIRInstruction {
372 private int opcode;
374
375 private String target;
377
378 private String name;
380
381 private ArrayList<Integer> arguments;
383
384
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
408 public NLIRInstruction toLir() {
409 if (lir != null) {
410 return lir;
411 }
412
413 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 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 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 (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 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
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
492 class NHIRReturn extends NHIRInstruction {
493 private int opcode;
495
496 private int value;
498
499
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
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
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
549 class NHIRPutField extends NHIRInstruction {
550 private int opcode;
552
553 private String target;
555
556 private String name;
558
559 private int value;
561
562
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
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
600 public String toString() {
601 return id() + ": " + hirMnemonic[opcode] + " " + target + "." + name + " = " +
602 block.cfg.hirMap.get(value).id();
603 }
604 }
605
606
609 class NHIRGetField extends NHIRInstruction {
610 private int opcode;
612
613 private String target;
615
616 private String name;
618
619
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
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
654 public String toString() {
655 return id() + ": " + hirMnemonic[opcode] + " " + target + "." + name;
656 }
657 }
658
659
662 class NHIRNewArray extends NHIRInstruction {
663 private int opcode;
665
666 private int dim;
668
669
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
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
701 public String toString() {
702 return id() + ": " + hirMnemonic[opcode] + " " + lType + " [" + dim + "]";
703 }
704 }
705
706
709 class NHIRALoad extends NHIRInstruction {
710 private int opcode;
712
713 private int arrayRef;
715
716 private int index;
718
719
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
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
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
765 class NHIRAStore extends NHIRInstruction {
766 private int opcode;
768
769 private int arrayRef;
771
772 private int index;
774
775 private int value;
777
778
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
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
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
827 class NHIRPhiFunction extends NHIRInstruction {
828
829 private ArrayList<Integer> arguments;
831
832 private int local;
834
835
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
854 public ArrayList<Integer> getArguments() {
855 return arguments;
856 }
857
858
863 public int getLocal() {
864 return local;
865 }
866
867
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
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
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
908 class NHIRLoadLocal extends NHIRInstruction {
909 private int local;
911
912
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
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
941 public String toString() {
942 return id() + ": LDLOC " + local;
943 }
944 }
945
946
949 class NHIRLocal extends NHIRInstruction {
950 private int local;
952
953
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
970 public String toString() {
971 return id() + ": LOC " + lType;
972 }
973 }
974