Skip to content

Commit b5623ae

Browse files
Fix bug in EnterSSA caused by mutable operands shared across instructions, replacing the phi register cause other instructions to change inadvertantly.
Fix bug in EnterSSA caused by mutable operands shared across instructions, replacing the phi register cause other instructions to change inadvertantly. Fix bug in EnterSSA caused by mutable operands shared across instructions, replacing the phi register cause other instructions to change inadvertantly.
1 parent 2fd6186 commit b5623ae

File tree

8 files changed

+239
-23
lines changed

8 files changed

+239
-23
lines changed

optvm/src/main/java/com/compilerprogramming/ezlang/compiler/CompiledFunction.java

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.compilerprogramming.ezlang.types.Scope;
66
import com.compilerprogramming.ezlang.types.Symbol;
77
import com.compilerprogramming.ezlang.types.Type;
8+
import com.compilerprogramming.ezlang.types.TypeDictionary;
89

910
import java.util.ArrayList;
1011
import java.util.BitSet;
@@ -20,6 +21,7 @@ public class CompiledFunction {
2021
private BasicBlock currentContinueTarget;
2122
private Type.TypeFunction functionType;
2223
public final RegisterPool registerPool;
24+
private final TypeDictionary typeDictionary;
2325

2426
private int frameSlots;
2527

@@ -36,7 +38,7 @@ public class CompiledFunction {
3638
*/
3739
private List<Operand> virtualStack = new ArrayList<>();
3840

39-
public CompiledFunction(Symbol.FunctionTypeSymbol functionSymbol) {
41+
public CompiledFunction(Symbol.FunctionTypeSymbol functionSymbol, TypeDictionary typeDictionary) {
4042
AST.FuncDecl funcDecl = (AST.FuncDecl) functionSymbol.functionDecl;
4143
this.functionType = (Type.TypeFunction) functionSymbol.type;
4244
this.registerPool = new RegisterPool();
@@ -46,20 +48,22 @@ public CompiledFunction(Symbol.FunctionTypeSymbol functionSymbol) {
4648
this.exit = createBlock();
4749
this.currentBreakTarget = null;
4850
this.currentContinueTarget = null;
51+
this.typeDictionary = typeDictionary;
4952
generateArgInstructions(funcDecl.scope);
5053
compileStatement(funcDecl.block);
5154
exitBlockIfNeeded();
5255
this.frameSlots = registerPool.numRegisters();
5356
}
5457

55-
public CompiledFunction(Type.TypeFunction functionType) {
58+
public CompiledFunction(Type.TypeFunction functionType, TypeDictionary typeDictionary) {
5659
this.functionType = (Type.TypeFunction) functionType;
5760
this.registerPool = new RegisterPool();
5861
this.BID = 0;
5962
this.entry = this.currentBlock = createBlock();
6063
this.exit = createBlock();
6164
this.currentBreakTarget = null;
6265
this.currentContinueTarget = null;
66+
this.typeDictionary = typeDictionary;
6367
this.frameSlots = registerPool.numRegisters();
6468
}
6569

@@ -437,8 +441,42 @@ private boolean compileSymbolExpr(AST.NameExpr symbolExpr) {
437441
return false;
438442
}
439443

444+
private boolean codeBoolean(AST.BinaryExpr binaryExpr) {
445+
boolean isAnd = binaryExpr.op.str.equals("&&");
446+
BasicBlock l1 = createBlock();
447+
BasicBlock l2 = createBlock();
448+
BasicBlock l3 = createBlock();
449+
boolean indexed = compileExpr(binaryExpr.expr1);
450+
if (indexed)
451+
codeIndexedLoad();
452+
if (isAnd) {
453+
code(new Instruction.ConditionalBranch(currentBlock, pop(), l1, l2));
454+
} else {
455+
code(new Instruction.ConditionalBranch(currentBlock, pop(), l2, l1));
456+
}
457+
startBlock(l1);
458+
compileExpr(binaryExpr.expr2);
459+
var temp = ensureTemp();
460+
jumpTo(l3);
461+
startBlock(l2);
462+
// Below we must write to the same temp
463+
//code(new Instruction.Move(new Operand.ConstantOperand(isAnd ? 0 : 1, typeDictionary.INT), new Operand.TempRegisterOperand(temp.reg)));
464+
code(new Instruction.Move(new Operand.ConstantOperand(isAnd ? 0 : 1, typeDictionary.INT), temp));
465+
jumpTo(l3);
466+
startBlock(l3);
467+
// leave temp on virtual stack
468+
// var temp2 = (Operand.TempRegisterOperand) pop();
469+
// pushOperand(new Operand.TempRegisterOperand(temp2.reg));
470+
return false;
471+
}
472+
473+
440474
private boolean compileBinaryExpr(AST.BinaryExpr binaryExpr) {
441-
String opCode = null;
475+
String opCode = binaryExpr.op.str;
476+
if (opCode.equals("&&") ||
477+
opCode.equals("||")) {
478+
return codeBoolean(binaryExpr);
479+
}
442480
boolean indexed = compileExpr(binaryExpr.expr1);
443481
if (indexed)
444482
codeIndexedLoad();
@@ -511,6 +549,36 @@ private Operand.TempRegisterOperand createTemp(Type type) {
511549
return tempRegister;
512550
}
513551

552+
Type typeOfOperand(Operand operand) {
553+
if (operand instanceof Operand.ConstantOperand constant)
554+
return constant.type;
555+
// else if (operand instanceof Operand.NullConstantOperand nullConstantOperand)
556+
// return nullConstantOperand.type;
557+
else if (operand instanceof Operand.RegisterOperand registerOperand)
558+
return registerOperand.type;
559+
else throw new CompilerException("Invalid operand");
560+
}
561+
562+
private Operand.TempRegisterOperand createTempAndMove(Operand src) {
563+
Type type = typeOfOperand(src);
564+
var temp = createTemp(type);
565+
code(new Instruction.Move(src, temp));
566+
return temp;
567+
}
568+
569+
private Operand.RegisterOperand ensureTemp() {
570+
Operand top = top();
571+
if (top instanceof Operand.ConstantOperand
572+
//|| top instanceof Operand.NullConstantOperand
573+
|| top instanceof Operand.LocalRegisterOperand) {
574+
return createTempAndMove(pop());
575+
} else if (top instanceof Operand.IndexedOperand) {
576+
return codeIndexedLoad();
577+
} else if (top instanceof Operand.TempRegisterOperand tempRegisterOperand) {
578+
return tempRegisterOperand;
579+
} else throw new CompilerException("Cannot convert to temporary register");
580+
}
581+
514582
private void pushLocal(Register reg) {
515583
pushOperand(new Operand.LocalRegisterOperand(reg));
516584
}
@@ -527,7 +595,7 @@ private Operand top() {
527595
return virtualStack.getLast();
528596
}
529597

530-
private void codeIndexedLoad() {
598+
private Operand.TempRegisterOperand codeIndexedLoad() {
531599
Operand indexed = pop();
532600
var temp = createTemp(indexed.type);
533601
if (indexed instanceof Operand.LoadIndexedOperand loadIndexedOperand) {
@@ -538,6 +606,7 @@ else if (indexed instanceof Operand.LoadFieldOperand loadFieldOperand) {
538606
}
539607
else
540608
code(new Instruction.Move(indexed, temp));
609+
return temp;
541610
}
542611

543612
private void codeIndexedStore() {

optvm/src/main/java/com/compilerprogramming/ezlang/compiler/Compiler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ private void compile(TypeDictionary typeDictionary, EnumSet<Options> options) {
1616
for (Symbol symbol: typeDictionary.getLocalSymbols()) {
1717
if (symbol instanceof Symbol.FunctionTypeSymbol functionSymbol) {
1818
Type.TypeFunction functionType = (Type.TypeFunction) functionSymbol.type;
19-
var function = new CompiledFunction(functionSymbol);
19+
var function = new CompiledFunction(functionSymbol, typeDictionary);
2020
if (options.contains(Options.DUMP_INITIAL_IR))
2121
function.dumpIR(false, "Initial IR");
2222
functionType.code = function;

optvm/src/main/java/com/compilerprogramming/ezlang/compiler/Instruction.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,14 @@ public List<Register> uses() {
6767
}
6868
public void replaceDef(Register newReg) {
6969
if (def == null) throw new IllegalStateException();
70-
def.replaceRegister(newReg);
70+
def = def.copy(newReg);
7171
}
7272
public void replaceUses(Register[] newUses) {
7373
int j = 0;
7474
for (int i = 0; i < uses.length; i++) {
7575
Operand use = uses[i];
7676
if (use != null && use instanceof Operand.RegisterOperand registerOperand) {
77-
registerOperand.replaceRegister(newUses[j++]);
77+
uses[i] = registerOperand.copy(newUses[j++]);
7878
}
7979
}
8080
}
@@ -83,7 +83,7 @@ public boolean replaceUse(Register source, Register target) {
8383
for (int i = 0; i < uses.length; i++) {
8484
Operand operand = uses[i];
8585
if (operand != null && operand instanceof Operand.RegisterOperand registerOperand && registerOperand.reg.id == source.id) {
86-
registerOperand.replaceRegister(target);
86+
uses[i] = registerOperand.copy(target);
8787
replaced = true;
8888
}
8989
}
@@ -362,7 +362,7 @@ public Phi(Register value, List<Register> inputs) {
362362
}
363363
}
364364
public void replaceInput(int i, Register newReg) {
365-
uses[i].replaceRegister(newReg);
365+
uses[i] = new Operand.RegisterOperand(newReg);
366366
}
367367
/**
368368
* This will fail in input was replaced by a constant

optvm/src/main/java/com/compilerprogramming/ezlang/compiler/Operand.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ public class Operand {
66

77
Type type;
88

9-
public void replaceRegister(Register register) {}
10-
119
public static class ConstantOperand extends Operand {
1210
public final long value;
1311
public ConstantOperand(long value, Type type) {
@@ -21,17 +19,16 @@ public String toString() {
2119
}
2220

2321
public static class RegisterOperand extends Operand {
24-
Register reg;
25-
public RegisterOperand(Register reg) {
22+
final Register reg;
23+
protected RegisterOperand(Register reg) {
2624
this.reg = reg;
2725
if (reg == null)
2826
throw new NullPointerException();
2927
}
3028
public int frameSlot() { return reg.nonSSAId(); }
3129

32-
@Override
33-
public void replaceRegister(Register register) {
34-
this.reg = register;
30+
public RegisterOperand copy(Register register) {
31+
return new RegisterOperand(register);
3532
}
3633

3734
@Override
@@ -44,6 +41,10 @@ public static class LocalRegisterOperand extends RegisterOperand {
4441
public LocalRegisterOperand(Register reg) {
4542
super(reg);
4643
}
44+
@Override
45+
public RegisterOperand copy(Register register) {
46+
return new LocalRegisterOperand(register);
47+
}
4748
}
4849

4950
public static class LocalFunctionOperand extends Operand {
@@ -66,6 +67,10 @@ public static class TempRegisterOperand extends RegisterOperand {
6667
public TempRegisterOperand(Register reg) {
6768
super(reg);
6869
}
70+
@Override
71+
public RegisterOperand copy(Register register) {
72+
return new TempRegisterOperand(register);
73+
}
6974
}
7075

7176
public static class IndexedOperand extends Operand {}

optvm/src/test/java/com/compilerprogramming/ezlang/compiler/TestInterferenceGraph.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ private CompiledFunction buildTest1() {
1313
Type.TypeFunction functionType = new Type.TypeFunction("foo");
1414
functionType.addArg(new Symbol.ParameterSymbol("a", typeDictionary.INT));
1515
functionType.setReturnType(typeDictionary.INT);
16-
CompiledFunction function = new CompiledFunction(functionType);
16+
CompiledFunction function = new CompiledFunction(functionType, typeDictionary);
1717
RegisterPool regPool = function.registerPool;
1818
Register a = regPool.newReg("a", typeDictionary.INT);
1919
Register b = regPool.newReg("b", typeDictionary.INT);
@@ -82,7 +82,7 @@ private CompiledFunction buildTest2() {
8282
TypeDictionary typeDictionary = new TypeDictionary();
8383
Type.TypeFunction functionType = new Type.TypeFunction("foo");
8484
functionType.setReturnType(typeDictionary.VOID);
85-
CompiledFunction function = new CompiledFunction(functionType);
85+
CompiledFunction function = new CompiledFunction(functionType, typeDictionary);
8686
RegisterPool regPool = function.registerPool;
8787
Register a = regPool.newReg("a", typeDictionary.INT);
8888
Register b = regPool.newReg("b", typeDictionary.INT);
@@ -158,7 +158,7 @@ public static CompiledFunction buildTest4() {
158158
TypeDictionary typeDictionary = new TypeDictionary();
159159
Type.TypeFunction functionType = new Type.TypeFunction("foo");
160160
functionType.setReturnType(typeDictionary.VOID);
161-
CompiledFunction function = new CompiledFunction(functionType);
161+
CompiledFunction function = new CompiledFunction(functionType, typeDictionary);
162162
RegisterPool regPool = function.registerPool;
163163
Register a = regPool.newReg("a", typeDictionary.INT);
164164
Register b = regPool.newReg("b", typeDictionary.INT);

optvm/src/test/java/com/compilerprogramming/ezlang/compiler/TestLiveness.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ static CompiledFunction buildTest3() {
247247
TypeDictionary typeDictionary = new TypeDictionary();
248248
Type.TypeFunction functionType = new Type.TypeFunction("foo");
249249
functionType.setReturnType(typeDictionary.INT);
250-
CompiledFunction function = new CompiledFunction(functionType);
250+
CompiledFunction function = new CompiledFunction(functionType, typeDictionary);
251251
RegisterPool regPool = function.registerPool;
252252
Register i = regPool.newReg("i", typeDictionary.INT);
253253
Register s = regPool.newReg("s", typeDictionary.INT);

optvm/src/test/java/com/compilerprogramming/ezlang/compiler/TestSSATransform.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ static CompiledFunction buildLostCopyTest() {
640640
Type.TypeFunction functionType = new Type.TypeFunction("foo");
641641
functionType.addArg(new Symbol.ParameterSymbol("p", typeDictionary.INT));
642642
functionType.setReturnType(typeDictionary.INT);
643-
CompiledFunction function = new CompiledFunction(functionType);
643+
CompiledFunction function = new CompiledFunction(functionType, typeDictionary);
644644
RegisterPool regPool = function.registerPool;
645645
Register p = regPool.newReg("p", typeDictionary.INT);
646646
Register x1 = regPool.newReg("x1", typeDictionary.INT);
@@ -708,7 +708,7 @@ static CompiledFunction buildSwapTest() {
708708
Type.TypeFunction functionType = new Type.TypeFunction("foo");
709709
functionType.addArg(new Symbol.ParameterSymbol("p", typeDictionary.INT));
710710
functionType.setReturnType(typeDictionary.VOID);
711-
CompiledFunction function = new CompiledFunction(functionType);
711+
CompiledFunction function = new CompiledFunction(functionType, typeDictionary);
712712
RegisterPool regPool = function.registerPool;
713713
Register p = regPool.newReg("p", typeDictionary.INT);
714714
Register a1 = regPool.newReg("a1", typeDictionary.INT);
@@ -2469,7 +2469,6 @@ func main()->Int {
24692469
""", result);
24702470
}
24712471

2472-
@Ignore
24732472
@Test
24742473
public void testSSA14() {
24752474
String src = """

0 commit comments

Comments
 (0)