Skip to content

Commit 3e63d04

Browse files
committed
Working on code generator / instruction scheduler logic
1 parent b519814 commit 3e63d04

5 files changed

Lines changed: 176 additions & 24 deletions

File tree

src/main/java/de/mirkosertic/metair/ir/CheckCast.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
public class CheckCast extends Node {
44

5+
public final Value arg0;
6+
public final Value arg1;
7+
58
CheckCast(final Value arg1, final Value arg2) {
6-
use(arg1, new ArgumentUse(0));
7-
use(arg2, new ArgumentUse(1));
9+
this.arg0 = use(arg1, new ArgumentUse(0));
10+
this.arg1 = use(arg2, new ArgumentUse(1));
811
}
912

1013
@Override

src/main/java/de/mirkosertic/metair/ir/Sequencer.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,12 @@ private void visitDominationTreeOf(final Node startNode, final Deque<Block> acti
7272
break;
7373
}
7474
case final LabelNode labelNode: {
75-
// TODO
75+
codegenerator.write(labelNode);
7676
current = followUpProcessor.apply(current);
7777
break;
7878
}
7979
case final MergeNode mergeNode: {
80-
// TODO
80+
codegenerator.write(mergeNode);
8181
current = followUpProcessor.apply(current);
8282
break;
8383
}
@@ -87,12 +87,12 @@ private void visitDominationTreeOf(final Node startNode, final Deque<Block> acti
8787
break;
8888
}
8989
case final ArrayLoad arrayLoad: {
90-
// TODO
90+
codegenerator.write(arrayLoad);
9191
current = followUpProcessor.apply(current);
9292
break;
9393
}
9494
case final ClassInitialization classInitialization: {
95-
// TODO
95+
codegenerator.write(classInitialization);
9696
current = followUpProcessor.apply(current);
9797
break;
9898
}
@@ -107,37 +107,37 @@ private void visitDominationTreeOf(final Node startNode, final Deque<Block> acti
107107
break;
108108
}
109109
case final Div div: {
110-
// TODO
110+
codegenerator.write(div);
111111
current = followUpProcessor.apply(current);
112112
break;
113113
}
114114
case final Rem rem: {
115-
// TODO
115+
codegenerator.write(rem);
116116
current = followUpProcessor.apply(current);
117117
break;
118118
}
119119
case final InvokeSpecial invokeSpecial: {
120-
// TODO
120+
codegenerator.write(invokeSpecial);
121121
current = followUpProcessor.apply(current);
122122
break;
123123
}
124124
case final InvokeStatic invokeStatic: {
125-
// TODO
125+
codegenerator.write(invokeStatic);
126126
current = followUpProcessor.apply(current);
127127
break;
128128
}
129129
case final InvokeInterface invokeInterface: {
130-
// TODO
130+
codegenerator.write(invokeInterface);
131131
current = followUpProcessor.apply(current);
132132
break;
133133
}
134134
case final InvokeVirtual invokeVirtual: {
135-
// TODO
135+
codegenerator.write(invokeVirtual);
136136
current = followUpProcessor.apply(current);
137137
break;
138138
}
139139
case final InvokeDynamic invokeDynamic: {
140-
// TODO
140+
codegenerator.write(invokeDynamic);
141141
current = followUpProcessor.apply(current);
142142
break;
143143
}
@@ -152,7 +152,7 @@ private void visitDominationTreeOf(final Node startNode, final Deque<Block> acti
152152
break;
153153
}
154154
case final CheckCast checkCast: {
155-
// TODO
155+
codegenerator.write(checkCast);
156156
current = followUpProcessor.apply(current);
157157
break;
158158
}
@@ -162,7 +162,7 @@ private void visitDominationTreeOf(final Node startNode, final Deque<Block> acti
162162
break;
163163
}
164164
case final ExtractControlFlowProjection extractControlFlowProjection: {
165-
// TODO
165+
// Do nothing here
166166
current = followUpProcessor.apply(current);
167167
break;
168168
}

src/main/java/de/mirkosertic/metair/ir/StructuredControlflowCodeGenerator.java

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,30 @@ public StructuredControlflowCodeGenerator() {
4646

4747
public abstract void write(final MonitorExit node);
4848

49+
public abstract void write(final ClassInitialization node);
50+
51+
public abstract void write(final Div node);
52+
53+
public abstract void write(final Rem node);
54+
55+
public abstract void write(final ArrayLoad node);
56+
57+
public abstract void write(final InvokeSpecial node);
58+
59+
public abstract void write(final InvokeInterface node);
60+
61+
public abstract void write(final InvokeVirtual node);
62+
63+
public abstract void write(final InvokeStatic node);
64+
65+
public abstract void write(final InvokeDynamic node);
66+
67+
public abstract void write(final LabelNode node);
68+
69+
public abstract void write(final MergeNode node);
70+
71+
public abstract void write(final CheckCast node);
72+
4973
public abstract void startIfWithTrueBlock(final If node);
5074

5175
public abstract void startIfElseBlock(final If node);
@@ -254,21 +278,25 @@ private T visit(final Node node, final Deque<Node> expressionStack, final Deque<
254278

255279
public abstract T emitTemporaryVariable(final T value);
256280

281+
protected final void emitWithTemporary(final Node node, final T value, final Deque<T> evaluationStack) {
282+
final T committed = committedToTemporary.get(node);
283+
if (committed == null) {
284+
final T temporary = emitTemporaryVariable(value);
285+
committedToTemporary.put(node, temporary);
286+
evaluationStack.push(temporary);
287+
} else {
288+
evaluationStack.push(committed);
289+
}
290+
}
291+
257292
protected final void emit(final Node node, final Deque<Node> expressionStack, final Deque<T> evaluationStack) {
258293
try {
259294
expressionStack.push(node);
260295

261296
final T result = visit(node, expressionStack, evaluationStack);
262297

263298
if (!node.isConstant() && node.isDataUsedMultipleTimes()) {
264-
final T committed = committedToTemporary.get(node);
265-
if (committed == null) {
266-
final T temporary = emitTemporaryVariable(result);
267-
committedToTemporary.put(node, temporary);
268-
evaluationStack.push(temporary);
269-
} else {
270-
evaluationStack.push(committed);
271-
}
299+
emitWithTemporary(node, result, evaluationStack);
272300
} else {
273301
evaluationStack.push(result);
274302
}

src/main/java/de/mirkosertic/metair/ir/test/DebugStructuredControlflowCodeGenerator.java

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import de.mirkosertic.metair.ir.ArrayLoad;
66
import de.mirkosertic.metair.ir.ArrayStore;
77
import de.mirkosertic.metair.ir.BitOperation;
8+
import de.mirkosertic.metair.ir.CheckCast;
89
import de.mirkosertic.metair.ir.ClassInitialization;
910
import de.mirkosertic.metair.ir.Convert;
1011
import de.mirkosertic.metair.ir.Div;
@@ -22,7 +23,9 @@
2223
import de.mirkosertic.metair.ir.InvokeSpecial;
2324
import de.mirkosertic.metair.ir.InvokeStatic;
2425
import de.mirkosertic.metair.ir.InvokeVirtual;
26+
import de.mirkosertic.metair.ir.LabelNode;
2527
import de.mirkosertic.metair.ir.LookupSwitch;
28+
import de.mirkosertic.metair.ir.MergeNode;
2629
import de.mirkosertic.metair.ir.Method;
2730
import de.mirkosertic.metair.ir.MonitorEnter;
2831
import de.mirkosertic.metair.ir.MonitorExit;
@@ -551,6 +554,122 @@ public GeneratedCode visit_PHI(final PHI node, final Deque<Node> expressionStack
551554
return new GeneratedCode(node.type, "TODO");
552555
}
553556

557+
@Override
558+
public void write(final ClassInitialization node) {
559+
final Deque<GeneratedCode> evaluationStack = new ArrayDeque<>();
560+
561+
final GeneratedCode generatedCode = visit_ClassInitialization(node, new ArrayDeque<>(), evaluationStack);
562+
563+
emitWithTemporary(node, generatedCode, evaluationStack);
564+
}
565+
566+
@Override
567+
public void write(final Div node) {
568+
final Deque<GeneratedCode> evaluationStack = new ArrayDeque<>();
569+
570+
final GeneratedCode generatedCode = visit_Div(node, new ArrayDeque<>(), evaluationStack);
571+
572+
emitWithTemporary(node, generatedCode, evaluationStack);
573+
}
574+
575+
@Override
576+
public void write(final Rem node) {
577+
final Deque<GeneratedCode> evaluationStack = new ArrayDeque<>();
578+
579+
final GeneratedCode generatedCode = visit_Rem(node, new ArrayDeque<>(), evaluationStack);
580+
581+
emitWithTemporary(node, generatedCode, evaluationStack);
582+
}
583+
584+
@Override
585+
public void write(final ArrayLoad node) {
586+
final Deque<GeneratedCode> evaluationStack = new ArrayDeque<>();
587+
588+
final GeneratedCode generatedCode = visit_ArrayLoad(node, new ArrayDeque<>(), evaluationStack);
589+
590+
emitWithTemporary(node, generatedCode, evaluationStack);
591+
}
592+
593+
@Override
594+
public void write(final InvokeSpecial node) {
595+
final Deque<GeneratedCode> evaluationStack = new ArrayDeque<>();
596+
597+
final GeneratedCode generatedCode = visit_InvokeSpecial(node, new ArrayDeque<>(), evaluationStack);
598+
599+
emitWithTemporary(node, generatedCode, evaluationStack);
600+
}
601+
602+
@Override
603+
public void write(final InvokeInterface node) {
604+
final Deque<GeneratedCode> evaluationStack = new ArrayDeque<>();
605+
606+
final GeneratedCode generatedCode = visit_InvokeInterface(node, new ArrayDeque<>(), evaluationStack);
607+
608+
emitWithTemporary(node, generatedCode, evaluationStack);
609+
}
610+
611+
@Override
612+
public void write(final InvokeVirtual node) {
613+
final Deque<GeneratedCode> evaluationStack = new ArrayDeque<>();
614+
615+
final GeneratedCode generatedCode = visit_InvokeVirtual(node, new ArrayDeque<>(), evaluationStack);
616+
617+
emitWithTemporary(node, generatedCode, evaluationStack);
618+
}
619+
620+
@Override
621+
public void write(final InvokeStatic node) {
622+
final Deque<GeneratedCode> evaluationStack = new ArrayDeque<>();
623+
624+
final GeneratedCode generatedCode = visit_InvokeStatic(node, new ArrayDeque<>(), evaluationStack);
625+
626+
emitWithTemporary(node, generatedCode, evaluationStack);
627+
}
628+
629+
@Override
630+
public void write(final InvokeDynamic node) {
631+
final Deque<GeneratedCode> evaluationStack = new ArrayDeque<>();
632+
633+
final GeneratedCode generatedCode = visit_InvokeDynamic(node, new ArrayDeque<>(), evaluationStack);
634+
635+
emitWithTemporary(node, generatedCode, evaluationStack);
636+
}
637+
638+
@Override
639+
public void write(final LabelNode node) {
640+
writeIndentation();
641+
pw.print("// Label ");
642+
pw.println(node.label);
643+
}
644+
645+
@Override
646+
public void write(final MergeNode node) {
647+
writeIndentation();
648+
pw.print("// Merge ");
649+
pw.println(node.label);
650+
}
651+
652+
@Override
653+
public void write(final CheckCast node) {
654+
final Deque<GeneratedCode> evaluationStack = new ArrayDeque<>();
655+
656+
emit(node.arg0, new ArrayDeque<>(), evaluationStack);
657+
emit(node.arg1, new ArrayDeque<>(), evaluationStack);
658+
659+
if (evaluationStack.size() != 2) {
660+
throw new IllegalStateException("Expected exactly two values on the stack, but got " + evaluationStack.size());
661+
}
662+
663+
final GeneratedCode arg1 = evaluationStack.pop();
664+
final GeneratedCode arg0 = evaluationStack.pop();
665+
666+
writeIndentation();
667+
pw.print("typecheck ");
668+
pw.print(arg0);
669+
pw.print(" is instance of ");
670+
pw.println(arg1);
671+
}
672+
554673
@Override
555674
public GeneratedCode emitTemporaryVariable(final GeneratedCode value) {
556675
final String varname = "var" + temporaryVariablesCounter++;
@@ -582,7 +701,6 @@ public String toString() {
582701

583702
// CFG - Generation
584703

585-
586704
@Override
587705
public void begin(final Method method) {
588706
writeIndentation();

src/test/java/de/mirkosertic/metair/ir/CheckCastTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ public void testUsage() {
1212
final PrimitiveInt b = new PrimitiveInt(20);
1313
final CheckCast cc = new CheckCast(a, b);
1414

15+
assertThat(cc.arg0).isSameAs(a);
16+
assertThat(cc.arg1).isSameAs(b);
17+
1518
assertThat(cc.debugDescription()).isEqualTo("CheckCast");
1619

1720
assertThat(a.usedBy).containsExactly(cc);

0 commit comments

Comments
 (0)