From de8e5139cc2842ef425246b0d67d67f47afc6a9b Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard Date: Thu, 13 Jul 2017 22:03:52 +0200 Subject: [PATCH] Added a phase 2 block assertion checking that the program always contains all referenced blocks. --- src/dk/camelot64/kickc/TODO.txt | 1 + .../asm/fragment/ptr_cowo1_zpby1=zpby2.asm | 3 + .../asm/fragment/zpby1_neq_coby1_then_la1.asm | 3 + .../icl/Pass1ProcedureCallParameters.java | 2 +- .../kickc/icl/Pass2AssertBlocks.java | 73 +++++++++++++++++++ .../kickc/icl/Pass3RegisterAllocation.java | 2 +- src/dk/camelot64/kickc/test/Main.java | 1 + 7 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_zpby1=zpby2.asm create mode 100644 src/dk/camelot64/kickc/asm/fragment/zpby1_neq_coby1_then_la1.asm create mode 100644 src/dk/camelot64/kickc/icl/Pass2AssertBlocks.java diff --git a/src/dk/camelot64/kickc/TODO.txt b/src/dk/camelot64/kickc/TODO.txt index 801206b66..36b7a83ed 100644 --- a/src/dk/camelot64/kickc/TODO.txt +++ b/src/dk/camelot64/kickc/TODO.txt @@ -13,6 +13,7 @@ Features - Add ability to call ASM code from KC. - Add ability to call KC code from ASM. (maybe declare some functions external to ensure their interface is well defined. Maybe generate ASM call stubs.) - Add inline ASM (maybe?) +- Handle long branches Process/Code Structure Improvement - Make each phase return a separate object graph (allowing for keeeping the history in memory & performing rollbacks) diff --git a/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_zpby1=zpby2.asm b/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_zpby1=zpby2.asm new file mode 100644 index 000000000..50741f8a0 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_zpby1=zpby2.asm @@ -0,0 +1,3 @@ +lda {zpby2} +ldy {zpby1} +sta {cowo1},y \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpby1_neq_coby1_then_la1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1_neq_coby1_then_la1.asm new file mode 100644 index 000000000..0a7d86b7f --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1_neq_coby1_then_la1.asm @@ -0,0 +1,3 @@ +lda {zpby1} +cmp #{coby1} +bne {la1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/icl/Pass1ProcedureCallParameters.java b/src/dk/camelot64/kickc/icl/Pass1ProcedureCallParameters.java index 89952d6a0..2eed78f3b 100644 --- a/src/dk/camelot64/kickc/icl/Pass1ProcedureCallParameters.java +++ b/src/dk/camelot64/kickc/icl/Pass1ProcedureCallParameters.java @@ -40,7 +40,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor { splitCurrentBlock(scope.addLabelIntermediate()); if(!SymbolTypeBasic.VOID.equals(procedure.getReturnType())) { addStatementToCurrentBlock(new StatementAssignment(origCall.getLValue(), procReturnVar)); - } { + } else { // No return type. Remove variable receiving the result. LValue lValue = origCall.getLValue(); if(lValue instanceof Variable) { diff --git a/src/dk/camelot64/kickc/icl/Pass2AssertBlocks.java b/src/dk/camelot64/kickc/icl/Pass2AssertBlocks.java new file mode 100644 index 000000000..c53fb1742 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/Pass2AssertBlocks.java @@ -0,0 +1,73 @@ +package dk.camelot64.kickc.icl; + +/** Assert that all referenced blocks exist in the program */ +public class Pass2AssertBlocks extends Pass2SsaAssertion { + + public Pass2AssertBlocks(ControlFlowGraph graph, Scope scope) { + super(graph, scope); + } + + @Override + public void check() throws AssertionFailed { + ControlFlowGraphBaseVisitor blockReferenceFinder = new BlockReferenceChecker(getGraph()); + blockReferenceFinder.visitGraph(getGraph()); + } + + private static class BlockReferenceChecker extends ControlFlowGraphBaseVisitor { + + private ControlFlowGraph graph; + + public BlockReferenceChecker(ControlFlowGraph graph) { + this.graph = graph; + } + + private void assertBlock(Label blockLabel) throws AssertionFailed { + if (blockLabel == null) { + return; + } + if (blockLabel.getFullName().equals("@RETURN")) { + return; + } + ControlFlowBlock block = graph.getBlock(blockLabel); + if (block == null) { + throw new AssertionFailed("Compilation Process Error! Block referenced, but not found in program. " + blockLabel); + } + } + + @Override + public Void visitBlock(ControlFlowBlock block) { + assertBlock(block.getDefaultSuccessor()); + assertBlock(block.getCallSuccessor()); + assertBlock(block.getConditionalSuccessor()); + return super.visitBlock(block); + } + + + @Override + public Void visitConditionalJump(StatementConditionalJump conditionalJump) { + assertBlock(conditionalJump.getDestination()); + return super.visitConditionalJump(conditionalJump); + } + + @Override + public Void visitCall(StatementCall callLValue) { + assertBlock(callLValue.getProcedure().getLabel()); + return super.visitCall(callLValue); + } + + @Override + public Void visitPhi(StatementPhi phi) { + for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) { + assertBlock(previousSymbol.getBlock()); + } + return super.visitPhi(phi); + } + + @Override + public Void visitJump(StatementJump jump) { + assertBlock(jump.getDestination()); + return super.visitJump(jump); + } + } + +} diff --git a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java index 91103339a..2ac441d2f 100644 --- a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java +++ b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java @@ -72,6 +72,7 @@ public class Pass3RegisterAllocation { //allocation.allocate(symbols.getVariable("a#1"), new RegisterAllocation.RegisterAByte()); //allocation.allocate(symbols.getVariable("a#0"), new RegisterAllocation.RegisterAByte()); + // Optimal Registers for flipper-rex2.kc allocation.allocate(symbols.getVariable("plot::i#0"), RegisterAllocation.getRegisterX()); allocation.allocate(symbols.getVariable("plot::i#1"), RegisterAllocation.getRegisterX()); allocation.allocate(symbols.getVariable("plot::i#2"), RegisterAllocation.getRegisterX()); @@ -126,7 +127,6 @@ public class Pass3RegisterAllocation { allocation.allocate(symbols.getVariable("c#2"), RegisterAllocation.getRegisterX()); allocation.allocate(symbols.getVariable("c#3"), RegisterAllocation.getRegisterX()); allocation.allocate(symbols.getVariable("c#4"), RegisterAllocation.getRegisterX()); - symbols.setAllocation(allocation); } diff --git a/src/dk/camelot64/kickc/test/Main.java b/src/dk/camelot64/kickc/test/Main.java index add0ec106..e263fae20 100644 --- a/src/dk/camelot64/kickc/test/Main.java +++ b/src/dk/camelot64/kickc/test/Main.java @@ -73,6 +73,7 @@ public class Main { List assertions = new ArrayList<>(); assertions.add(new Pass2AssertSymbols(controlFlowGraph, programScope)); + assertions.add(new Pass2AssertBlocks(controlFlowGraph, programScope)); boolean ssaOptimized = true; while (ssaOptimized) {