diff --git a/src/dk/camelot64/kickc/TODO.txt b/src/dk/camelot64/kickc/TODO.txt new file mode 100644 index 000000000..eec7aecff --- /dev/null +++ b/src/dk/camelot64/kickc/TODO.txt @@ -0,0 +1,40 @@ +Features +- Move the main code into a main() function, and disallow code outside functions. The main function per default has no parameters and exits with RTS. +- Implement Register Allocation (that utilize real registers - and non-zeropage memory) +- Add Fixed Point number types +- Create a proper main function for the compiler +- Add for loop +- Add imports +- Add structs +- Add preprocessing / find a way to allow some functions to run at compile time +- Implement inline compilation of functions (and a mechanism for choosing which methods / calls to inline) +- 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?) + +Process/Code Structure Improvement +- Make each phase return a separate object graph (allowing for keeping the history in memory & performing rollbacks) +- Implemenent Assertions for the output of different phases (ensuring that the result of the phase is consistent) +- Refactor Expression Operator Implementation & Evaluation into one class per operator + +Testing +- Test that the parse tree for specific KC syntax is as expected. Use a print function for the parse tree to generate output for comparison. +- Test the ICL result of a specific phase on a specific ICL input. Create an ICL syntax for parsing directly to ICL and a printer for the syntax. +- Test the ASM program output resulting from compiling specific KC program input. +- Emulate/Run the ASM for a specific KC program compiled. Compare the emulated ASM output to output calculated by executing directly on the KC tree. +- Add assert statements to the language. Create KC programs that test the compiler by compiling, running and testing assertions. + +Optimizations +- Optimize register allocation by combining with knowledge of ASM program cost (bytes/cycles) and different ASM fragments with different clobbering. +- Optimize by finding optimal sequence for multiple phi assignments in entry-segments. +- Optimize by allowing resequencing of statements and phi assignemtns in a final phase. Perhaps by converting phi statements to "normal" statements and using some optimization step. + +Usages +- Implement library for memory allocation in main memory +- Implement library for output on the screen (using basic functions) + +Real Usage +- Implement library for fast multiply (mul.asm) +- Implement spline library (spline.asm) +- Implement polygon filler for complex polygons. +- Implement true type font renderer. \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/AsmFragment.java b/src/dk/camelot64/kickc/asm/AsmFragment.java index 59c6c4302..3e9ccb35f 100644 --- a/src/dk/camelot64/kickc/asm/AsmFragment.java +++ b/src/dk/camelot64/kickc/asm/AsmFragment.java @@ -127,7 +127,10 @@ public class AsmFragment { } if (conditionalJump.getRValue2() instanceof ConstantInteger && ((ConstantInteger) conditionalJump.getRValue2()).getNumber() == 0) { signature.append("0"); - } else { + } else if (conditionalJump.getRValue2() instanceof ConstantBool) { + ConstantBool boolValue = (ConstantBool) conditionalJump.getRValue2(); + signature.append(boolValue.toString()); + } else{ signature.append(bind(conditionalJump.getRValue2())); } signature.append("_then_"); @@ -135,7 +138,7 @@ public class AsmFragment { ControlFlowBlock destinationBlock = graph.getBlock(destination); String destinationLabel = destination.getFullName(); if (destinationBlock.hasPhiStatements()) { - destinationLabel = destination.getFullName() + "_from_" + block.getLabel().getFullName(); + destinationLabel = (destinationBlock.getLabel().getLocalName() + "_from_" + block.getLabel().getLocalName()).replace('@', 'B').replace(':','_'); } signature.append(bind(new Label(destinationLabel, destination.getScope(),false))); return signature.toString(); @@ -348,7 +351,7 @@ public class AsmFragment { bound = Integer.toString(boundInt.getNumber()); } } else if (boundValue instanceof Label) { - bound = ((Label) boundValue).getFullName().replace('@', 'B'); + bound = ((Label) boundValue).getFullName().replace('@', 'B').replace(':','_'); } else { throw new RuntimeException("Bound Value Type not implemented " + boundValue); } diff --git a/src/dk/camelot64/kickc/asm/fragment/coptr1=zpby1.asm b/src/dk/camelot64/kickc/asm/fragment/coptr1=zpby1.asm new file mode 100644 index 000000000..94df8a017 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/coptr1=zpby1.asm @@ -0,0 +1,2 @@ +lda {zpby1} +sta {coptr1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_xby=xby.asm b/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_xby=xby.asm new file mode 100644 index 000000000..e6ad0e51a --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_xby=xby.asm @@ -0,0 +1,2 @@ +txa +sta {cowo1},x \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_yby=aby.asm b/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_yby=aby.asm new file mode 100644 index 000000000..59a445cd9 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_yby=aby.asm @@ -0,0 +1 @@ +sta {cowo1},y \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_zpby1=zpby1.asm b/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_zpby1=zpby1.asm new file mode 100644 index 000000000..aee9ef73a --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_zpby1=zpby1.asm @@ -0,0 +1,3 @@ +ldy {zpby1} +tya +sta {cowo1},y \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/ptr_zpptrby1_yby=aby.asm b/src/dk/camelot64/kickc/asm/fragment/ptr_zpptrby1_yby=aby.asm new file mode 100644 index 000000000..40c3ae3d9 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/ptr_zpptrby1_yby=aby.asm @@ -0,0 +1 @@ +sta ({zpptrby1}),y \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/ptr_zpptrby1_zpby1=zpby2.asm b/src/dk/camelot64/kickc/asm/fragment/ptr_zpptrby1_zpby1=zpby2.asm new file mode 100644 index 000000000..1e0ab1b7f --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/ptr_zpptrby1_zpby1=zpby2.asm @@ -0,0 +1,3 @@ +lda {zpby2} +ldy {zpby1} +sta ({zpptrby1}),y \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/true_then_la1.asm b/src/dk/camelot64/kickc/asm/fragment/true_then_la1.asm new file mode 100644 index 000000000..3a49f26fb --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/true_then_la1.asm @@ -0,0 +1 @@ +jmp {la1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/yby=yby_plus_1.asm b/src/dk/camelot64/kickc/asm/fragment/yby=yby_plus_1.asm new file mode 100644 index 000000000..ee2cffde5 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/yby=yby_plus_1.asm @@ -0,0 +1 @@ +iny \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/yby_lt_coby1_then_la1.asm b/src/dk/camelot64/kickc/asm/fragment/yby_lt_coby1_then_la1.asm new file mode 100644 index 000000000..21d350ba9 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/yby_lt_coby1_then_la1.asm @@ -0,0 +1,2 @@ +cpy #{coby1} +bcc {la1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpby1=cowo1_staridx_zpby2.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=cowo1_staridx_zpby2.asm new file mode 100644 index 000000000..4f29a06d2 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1=cowo1_staridx_zpby2.asm @@ -0,0 +1,3 @@ +ldy {zpby2} +lda {cowo1},y +sta {zpby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpby1=xby.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=xby.asm new file mode 100644 index 000000000..ab3a202f5 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1=xby.asm @@ -0,0 +1 @@ +stx {zpby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpby1_neq_0_then_la1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1_neq_0_then_la1.asm new file mode 100644 index 000000000..aa3881fa0 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1_neq_0_then_la1.asm @@ -0,0 +1,2 @@ +lda {zpby1} +bne {la1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java b/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java index c7623eb75..d0307275b 100644 --- a/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java +++ b/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java @@ -151,7 +151,9 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { } procedure.setParameters(parameterList); sequence.addStatement(new StatementProcedureBegin(procedure)); - this.visit(ctx.stmtSeq()); + if(ctx.stmtSeq()!=null) { + this.visit(ctx.stmtSeq()); + } sequence.addStatement(new StatementLabel(procExit)); if(returnVar!=null) { sequence.addStatement(new StatementAssignment(returnVar, returnVar)); @@ -285,7 +287,13 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public Object visitExprCall(KickCParser.ExprCallContext ctx) { - List parameters = (List) this.visit(ctx.parameterList()); + List parameters; + KickCParser.ParameterListContext parameterList = ctx.parameterList(); + if(parameterList!=null) { + parameters = (List) this.visit(parameterList); + } else { + parameters = new ArrayList<>(); + } VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); sequence.addStatement(new StatementCall(tmpVar, ctx.NAME().getText(), parameters)); return tmpVar; diff --git a/src/dk/camelot64/kickc/icl/Pass1ProcedureCallParameters.java b/src/dk/camelot64/kickc/icl/Pass1ProcedureCallParameters.java index 9074331c1..713add442 100644 --- a/src/dk/camelot64/kickc/icl/Pass1ProcedureCallParameters.java +++ b/src/dk/camelot64/kickc/icl/Pass1ProcedureCallParameters.java @@ -38,7 +38,9 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor { addStatementToCurrentBlock(copyCall); getCurrentBlock().setCallSuccessor(procedure.getLabel()); splitCurrentBlock(scope.addLabelIntermediate()); - addStatementToCurrentBlock(new StatementAssignment(origCall.getLValue(), procReturnVar)); + if(!SymbolTypeBasic.VOID.equals(procedure.getReturnType())) { + addStatementToCurrentBlock(new StatementAssignment(origCall.getLValue(), procReturnVar)); + } return null; } diff --git a/src/dk/camelot64/kickc/icl/Pass1ProcedureCallsReturnValue.java b/src/dk/camelot64/kickc/icl/Pass1ProcedureCallsReturnValue.java index b00149f6d..ee665282b 100644 --- a/src/dk/camelot64/kickc/icl/Pass1ProcedureCallsReturnValue.java +++ b/src/dk/camelot64/kickc/icl/Pass1ProcedureCallsReturnValue.java @@ -28,25 +28,26 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor copyCall.setProcedure(procedure); addStatementToCurrentBlock(copyCall); getCurrentBlock().setCallSuccessor(procedure.getLabel()); - - // Find return variable final version - Label returnBlockLabel = procedure.getLabel("@return"); - ControlFlowBlock returnBlock = graph.getBlock(returnBlockLabel); - VariableVersion returnVarFinal = null; - for (Statement statement : returnBlock.getStatements()) { - if (statement instanceof StatementReturn) { - StatementReturn statementReturn = (StatementReturn) statement; - RValue returnValue = statementReturn.getValue(); - if (returnValue instanceof VariableVersion) { - returnVarFinal = (VariableVersion) returnValue; + if(!SymbolTypeBasic.VOID.equals(procedure.getReturnType())) { + // Find return variable final version + Label returnBlockLabel = procedure.getLabel("@return"); + ControlFlowBlock returnBlock = graph.getBlock(returnBlockLabel); + VariableVersion returnVarFinal = null; + for (Statement statement : returnBlock.getStatements()) { + if (statement instanceof StatementReturn) { + StatementReturn statementReturn = (StatementReturn) statement; + RValue returnValue = statementReturn.getValue(); + if (returnValue instanceof VariableVersion) { + returnVarFinal = (VariableVersion) returnValue; + } } } + if (returnVarFinal == null) { + throw new RuntimeException("Error! Cannot find final return variable for " + procedure.getFullName()); + } + StatementAssignment returnAssignment = new StatementAssignment(origCall.getLValue(), returnVarFinal); + addStatementToCurrentBlock(returnAssignment); } - if (returnVarFinal == null) { - throw new RuntimeException("Error! Cannot find final return variable for " + procedure.getFullName()); - } - StatementAssignment returnAssignment = new StatementAssignment(origCall.getLValue(), returnVarFinal); - addStatementToCurrentBlock(returnAssignment); return null; } diff --git a/src/dk/camelot64/kickc/icl/Pass2ConstantAdditionElimination.java b/src/dk/camelot64/kickc/icl/Pass2ConstantAdditionElimination.java index 0576b1223..ed9a760bd 100644 --- a/src/dk/camelot64/kickc/icl/Pass2ConstantAdditionElimination.java +++ b/src/dk/camelot64/kickc/icl/Pass2ConstantAdditionElimination.java @@ -59,6 +59,14 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { private boolean optimizePointerDereferenceIndexed(StatementAssignment assignment) { PointerDereferenceIndexed pointerDereferenceIndexed = (PointerDereferenceIndexed) assignment.getLValue(); + if(pointerDereferenceIndexed.getPointer() instanceof ConstantInteger && pointerDereferenceIndexed.getIndex() instanceof Constant) { + ConstantInteger ptrConstant = (ConstantInteger) pointerDereferenceIndexed.getPointer(); + ConstantInteger idxConstant = (ConstantInteger) pointerDereferenceIndexed.getIndex(); + int newPtr = ptrConstant.getNumber() + idxConstant.getNumber(); + assignment.setLValue(new PointerDereferenceSimple(new ConstantInteger(newPtr))); + System.out.println("Consolidated assigned array index constant in assignment " + assignment.getLValue()); + return true; + } if(pointerDereferenceIndexed.getPointer() instanceof ConstantInteger && pointerDereferenceIndexed.getIndex() instanceof Variable) { Variable variable = (Variable) pointerDereferenceIndexed.getIndex(); ConstantInteger consolidated = consolidateSubConstants(variable); @@ -74,13 +82,23 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { } private boolean optimizeArrayDeref(StatementAssignment assignment) { + if (assignment.getRValue1() instanceof ConstantInteger && assignment.getRValue2() instanceof ConstantInteger) { + ConstantInteger ptrConstant = (ConstantInteger) assignment.getRValue1(); + ConstantInteger idxConstant = (ConstantInteger) assignment.getRValue2(); + int newPtr = ptrConstant.getNumber() + idxConstant.getNumber(); + assignment.setRValue1(null); + assignment.setOperator(new Operator("*")); + assignment.setRValue2(new ConstantInteger(newPtr)); + System.out.println("Consolidated referenced array index constant in assignment " + assignment.getLValue()); + return true; + } if (assignment.getRValue1() instanceof ConstantInteger && assignment.getRValue2() instanceof Variable) { Variable variable = (Variable) assignment.getRValue2(); ConstantInteger consolidated = consolidateSubConstants(variable); if (consolidated != null) { ConstantInteger ptrConstant = (ConstantInteger) assignment.getRValue1(); int newPtr = ptrConstant.getNumber() + consolidated.getNumber(); - assignment.setRValue1(new ConstantInteger(newPtr)); + assignment.setRValue1(new ConstantInteger(newPtr)); System.out.println("Consolidated referenced array index constant in assignment " + assignment.getLValue()); return true; } @@ -124,7 +142,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { * @return The consolidated constant. Null if no sub-constants were found. */ private ConstantInteger consolidateSubConstants(Variable variable) { - if(usages.get(variable)>1) { + if(getUsages(variable) >1) { System.out.println("Multiple usages for variable. Not optimizing sub-constant "+variable); return null; } @@ -197,4 +215,10 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { return null; } + private Integer getUsages(Variable variable) { + Integer useCount = usages.get(variable); + if(useCount==null) useCount = 0; + return useCount; + } + } diff --git a/src/dk/camelot64/kickc/icl/Pass2ConstantPropagation.java b/src/dk/camelot64/kickc/icl/Pass2ConstantPropagation.java index e854ba073..3ad267470 100644 --- a/src/dk/camelot64/kickc/icl/Pass2ConstantPropagation.java +++ b/src/dk/camelot64/kickc/icl/Pass2ConstantPropagation.java @@ -56,7 +56,9 @@ public class Pass2ConstantPropagation extends Pass2SsaOptimization { assignment.getOperator(), (Constant) assignment.getRValue1(), (Constant) assignment.getRValue2()); - constants.put(variable, constant); + if(constant!=null) { + constants.put(variable, constant); + } } } return null; @@ -110,6 +112,10 @@ public class Pass2ConstantPropagation extends Pass2SsaOptimization { return new ConstantDouble(getDouble(c1) / getDouble(c2)); } } + case "*idx": { + // Cannot be directly propagated + return null; + } default: throw new RuntimeException("Unhandled Binary Operator " + operator.getOperator()); } diff --git a/src/dk/camelot64/kickc/icl/Pass3BlockSequencePlanner.java b/src/dk/camelot64/kickc/icl/Pass3BlockSequencePlanner.java index 6f6656934..f52ce6698 100644 --- a/src/dk/camelot64/kickc/icl/Pass3BlockSequencePlanner.java +++ b/src/dk/camelot64/kickc/icl/Pass3BlockSequencePlanner.java @@ -26,7 +26,7 @@ public class Pass3BlockSequencePlanner { } if(sequence.contains(block)) { // already handled - move on - break; + continue; } sequence.add(block); if(block.getCallSuccessor()!=null) { diff --git a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java index 46bc2e8f0..2b065109b 100644 --- a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java +++ b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java @@ -17,34 +17,40 @@ public class Pass3RegisterAllocation { public void allocate() { RegisterAllocation allocation = new RegisterAllocation(); performAllocation(symbols, allocation); - allocation.allocate(symbols.getVariable("i#0"), RegisterAllocation.getRegisterX()); - allocation.allocate(symbols.getVariable("i#1"), RegisterAllocation.getRegisterX()); - allocation.allocate(symbols.getVariable("i#2"), RegisterAllocation.getRegisterX()); - allocation.allocate(symbols.getVariable("i#3"), RegisterAllocation.getRegisterX()); - allocation.allocate(symbols.getVariable("i#4"), RegisterAllocation.getRegisterX()); - allocation.allocate(symbols.getVariable("i#5"), RegisterAllocation.getRegisterX()); - allocation.allocate(symbols.getVariable("n1#1"), RegisterAllocation.getRegisterY()); - allocation.allocate(symbols.getVariable("n1#2"), RegisterAllocation.getRegisterY()); - allocation.allocate(symbols.getVariable("e#2"), new RegisterAllocation.RegisterZpByte(128)); - allocation.allocate(symbols.getVariable("e#3"), new RegisterAllocation.RegisterZpByte(128)); - allocation.allocate(symbols.getVariable("e#4"), new RegisterAllocation.RegisterZpByte(128)); - allocation.allocate(symbols.getVariable("e#5"), new RegisterAllocation.RegisterZpByte(128)); - allocation.allocate(symbols.getVariable("idx#2"), new RegisterAllocation.RegisterZpWord(129)); - allocation.allocate(symbols.getVariable("idx#3"), new RegisterAllocation.RegisterZpWord(129)); - allocation.allocate(symbols.getVariable("idx#4"), new RegisterAllocation.RegisterZpWord(129)); - allocation.allocate(symbols.getVariable("idx#5"), new RegisterAllocation.RegisterZpWord(129)); - allocation.allocate(symbols.getVariable("x#2"), new RegisterAllocation.RegisterZpByte(131)); - allocation.allocate(symbols.getVariable("x#5"), new RegisterAllocation.RegisterZpByte(131)); - allocation.allocate(symbols.getVariable("y#1"), new RegisterAllocation.RegisterZpByte(132)); - allocation.allocate(symbols.getVariable("y#2"), new RegisterAllocation.RegisterZpByte(132)); - allocation.allocate(symbols.getVariable("y#5"), new RegisterAllocation.RegisterZpByte(132)); - allocation.allocate(symbols.getVariable("cursor#2"), new RegisterAllocation.RegisterZpPointerByte(133)); - allocation.allocate(symbols.getVariable("cursor#3"), new RegisterAllocation.RegisterZpPointerByte(133)); - allocation.allocate(symbols.getVariable("cursor#4"), new RegisterAllocation.RegisterZpPointerByte(133)); - allocation.allocate(symbols.getVariable("cursor#5"), new RegisterAllocation.RegisterZpPointerByte(133)); - allocation.allocate(symbols.getVariable("ptr#1"), new RegisterAllocation.RegisterZpPointerByte(135)); - allocation.allocate(symbols.getVariable("ptr#2"), new RegisterAllocation.RegisterZpPointerByte(135)); - allocation.allocate(symbols.getVariable("ptr#3"), new RegisterAllocation.RegisterZpPointerByte(135)); + + //allocation.allocate(symbols.getVariable("i#0"), RegisterAllocation.getRegisterX()); + //allocation.allocate(symbols.getVariable("i#1"), RegisterAllocation.getRegisterX()); + //allocation.allocate(symbols.getVariable("i#2"), RegisterAllocation.getRegisterX()); + //allocation.allocate(symbols.getVariable("i#3"), RegisterAllocation.getRegisterX()); + //allocation.allocate(symbols.getVariable("i#4"), RegisterAllocation.getRegisterX()); + //allocation.allocate(symbols.getVariable("i#5"), RegisterAllocation.getRegisterX()); + //allocation.allocate(symbols.getVariable("i#6"), RegisterAllocation.getRegisterX()); + //allocation.allocate(symbols.getVariable("i#7"), RegisterAllocation.getRegisterX()); + //allocation.allocate(symbols.getVariable("n1#1"), RegisterAllocation.getRegisterY()); + //allocation.allocate(symbols.getVariable("n1#2"), RegisterAllocation.getRegisterY()); + //allocation.allocate(symbols.getVariable("e#2"), new RegisterAllocation.RegisterZpByte(128)); + //allocation.allocate(symbols.getVariable("e#3"), new RegisterAllocation.RegisterZpByte(128)); + //allocation.allocate(symbols.getVariable("e#4"), new RegisterAllocation.RegisterZpByte(128)); + //allocation.allocate(symbols.getVariable("e#5"), new RegisterAllocation.RegisterZpByte(128)); + //allocation.allocate(symbols.getVariable("idx#2"), new RegisterAllocation.RegisterZpWord(129)); + //allocation.allocate(symbols.getVariable("idx#3"), new RegisterAllocation.RegisterZpWord(129)); + //allocation.allocate(symbols.getVariable("idx#4"), new RegisterAllocation.RegisterZpWord(129)); + //allocation.allocate(symbols.getVariable("idx#5"), new RegisterAllocation.RegisterZpWord(129)); + //allocation.allocate(symbols.getVariable("x#0"), new RegisterAllocation.RegisterYByte()); + //allocation.allocate(symbols.getVariable("x#1"), new RegisterAllocation.RegisterYByte()); + //allocation.allocate(symbols.getVariable("x#2"), new RegisterAllocation.RegisterYByte()); + //allocation.allocate(symbols.getVariable("x#5"), new RegisterAllocation.RegisterZpByte(131)); + //allocation.allocate(symbols.getVariable("y#0"), new RegisterAllocation.RegisterZpByte(132)); + //allocation.allocate(symbols.getVariable("y#1"), new RegisterAllocation.RegisterZpByte(132)); + //allocation.allocate(symbols.getVariable("y#2"), new RegisterAllocation.RegisterZpByte(132)); + //allocation.allocate(symbols.getVariable("y#5"), new RegisterAllocation.RegisterZpByte(132)); + //allocation.allocate(symbols.getVariable("cursor#2"), new RegisterAllocation.RegisterZpPointerByte(133)); + //allocation.allocate(symbols.getVariable("cursor#3"), new RegisterAllocation.RegisterZpPointerByte(133)); + //allocation.allocate(symbols.getVariable("cursor#4"), new RegisterAllocation.RegisterZpPointerByte(133)); + //allocation.allocate(symbols.getVariable("cursor#5"), new RegisterAllocation.RegisterZpPointerByte(133)); + //allocation.allocate(symbols.getVariable("ptr#1"), new RegisterAllocation.RegisterZpPointerByte(135)); + //allocation.allocate(symbols.getVariable("ptr#2"), new RegisterAllocation.RegisterZpPointerByte(135)); + //allocation.allocate(symbols.getVariable("ptr#3"), new RegisterAllocation.RegisterZpPointerByte(135)); //allocation.allocate(symbols.getVariable("v#1"), new RegisterAllocation.RegisterAByte()); //allocation.allocate(symbols.getVariable("v#2"), new RegisterAllocation.RegisterAByte()); //allocation.allocate(symbols.getVariable("v#3"), new RegisterAllocation.RegisterAByte()); @@ -56,14 +62,39 @@ public class Pass3RegisterAllocation { //allocation.allocate(symbols.getVariable("$1"), new RegisterAllocation.RegisterAByte()); //allocation.allocate(symbols.getVariable("$3"), new RegisterAllocation.RegisterALUByte()); //allocation.allocate(symbols.getVariable("$4"), new RegisterAllocation.RegisterAByte()); + //allocation.allocate(symbols.getVariable("$5"), new RegisterAllocation.RegisterAByte()); //allocation.allocate(symbols.getVariable("$6"), new RegisterAllocation.RegisterALUByte()); //allocation.allocate(symbols.getVariable("$7"), new RegisterAllocation.RegisterAByte()); //allocation.allocate(symbols.getVariable("inc::a#2"), new RegisterAllocation.RegisterAByte()); //allocation.allocate(symbols.getVariable("bv#0"), new RegisterAllocation.RegisterAByte()); - allocation.allocate(symbols.getVariable("sum::b#0"), new RegisterAllocation.RegisterAByte()); - allocation.allocate(symbols.getVariable("inc::b#1"), new RegisterAllocation.RegisterAByte()); + //allocation.allocate(symbols.getVariable("sum::b#0"), new RegisterAllocation.RegisterAByte()); + //allocation.allocate(symbols.getVariable("inc::b#1"), new RegisterAllocation.RegisterAByte()); //allocation.allocate(symbols.getVariable("a#1"), new RegisterAllocation.RegisterAByte()); //allocation.allocate(symbols.getVariable("a#0"), new RegisterAllocation.RegisterAByte()); + + 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()); + allocation.allocate(symbols.getVariable("plot::i#3"), RegisterAllocation.getRegisterX()); + allocation.allocate(symbols.getVariable("plot::i#4"), RegisterAllocation.getRegisterX()); + allocation.allocate(symbols.getVariable("plot::x#0"), RegisterAllocation.getRegisterY()); + allocation.allocate(symbols.getVariable("plot::x#1"), RegisterAllocation.getRegisterY()); + allocation.allocate(symbols.getVariable("plot::x#2"), RegisterAllocation.getRegisterY()); + allocation.allocate(symbols.getVariable("plot::y#0"), new RegisterAllocation.RegisterZpByte(100)); + allocation.allocate(symbols.getVariable("plot::y#1"), new RegisterAllocation.RegisterZpByte(100)); + allocation.allocate(symbols.getVariable("plot::y#2"), new RegisterAllocation.RegisterZpByte(100)); + allocation.allocate(symbols.getVariable("plot::y#3"), new RegisterAllocation.RegisterZpByte(100)); + allocation.allocate(symbols.getVariable("plot::y#4"), new RegisterAllocation.RegisterZpByte(100)); + allocation.allocate(symbols.getVariable("plot::line#0"), new RegisterAllocation.RegisterZpPointerByte(101)); + allocation.allocate(symbols.getVariable("plot::line#1"), new RegisterAllocation.RegisterZpPointerByte(101)); + allocation.allocate(symbols.getVariable("plot::line#2"), new RegisterAllocation.RegisterZpPointerByte(101)); + allocation.allocate(symbols.getVariable("plot::line#3"), new RegisterAllocation.RegisterZpPointerByte(101)); + allocation.allocate(symbols.getVariable("plot::line#4"), new RegisterAllocation.RegisterZpPointerByte(101)); + allocation.allocate(symbols.getVariable("plot::$3"), RegisterAllocation.getRegisterA()); + allocation.allocate(symbols.getVariable("prepare::i#0"), RegisterAllocation.getRegisterX()); + allocation.allocate(symbols.getVariable("prepare::i#1"), RegisterAllocation.getRegisterX()); + allocation.allocate(symbols.getVariable("prepare::i#2"), RegisterAllocation.getRegisterX()); + symbols.setAllocation(allocation); } diff --git a/src/dk/camelot64/kickc/icl/PointerDereferenceSimple.java b/src/dk/camelot64/kickc/icl/PointerDereferenceSimple.java index 3e933a9aa..fe71cc504 100644 --- a/src/dk/camelot64/kickc/icl/PointerDereferenceSimple.java +++ b/src/dk/camelot64/kickc/icl/PointerDereferenceSimple.java @@ -5,7 +5,7 @@ public class PointerDereferenceSimple implements PointerDereference { private RValue pointer; - public PointerDereferenceSimple(Variable pointer) { + public PointerDereferenceSimple(RValue pointer) { this.pointer = pointer; } diff --git a/src/dk/camelot64/kickc/icl/SymbolTypeBasic.java b/src/dk/camelot64/kickc/icl/SymbolTypeBasic.java index 2c583fd0a..5399954cb 100644 --- a/src/dk/camelot64/kickc/icl/SymbolTypeBasic.java +++ b/src/dk/camelot64/kickc/icl/SymbolTypeBasic.java @@ -29,6 +29,7 @@ public enum SymbolTypeBasic implements SymbolType { case "word": return WORD; case "string": return STRING; case "boolean": return BOOLEAN; + case "void": return VOID; } return null; } diff --git a/src/dk/camelot64/kickc/test/Main.java b/src/dk/camelot64/kickc/test/Main.java index e9837db69..bcd4a1adc 100644 --- a/src/dk/camelot64/kickc/test/Main.java +++ b/src/dk/camelot64/kickc/test/Main.java @@ -13,7 +13,7 @@ import java.util.List; /** Test my KickC Grammar */ public class Main { public static void main(String[] args) throws IOException { - final String fileName = "src/dk/camelot64/kickc/test/callsum.kc"; + final String fileName = "src/dk/camelot64/kickc/test/flipper-rex2.kc"; final CharStream input = CharStreams.fromFileName(fileName); System.out.println(input.toString()); KickCLexer lexer = new KickCLexer(input); diff --git a/src/dk/camelot64/kickc/test/flipper-rex2.kc b/src/dk/camelot64/kickc/test/flipper-rex2.kc new file mode 100644 index 000000000..b334a462a --- /dev/null +++ b/src/dk/camelot64/kickc/test/flipper-rex2.kc @@ -0,0 +1,39 @@ +byte[1000] SCREEN = $0400; +byte[16*16] buffer = $1000; +byte[16*16] buffer2 = $1100; + +prepare(); +do { + plot(); + flip(); +} while(true) + +void prepare() { + // Prepare buffer + byte i=0; + do { + buffer[i] = i; + i=i+1; + } while (i!=0) +} + +void flip() { + // Flip buffer +} + +// Plot buffer on screen +void plot() { + byte* line = SCREEN+5*40+12; + byte y=0; + byte i=0; + do { + byte x=0; + do { + line[x] = buffer[i]; + x=x+1; + i=i+1; + } while(x<16) + line = line+40; + y=y+1; + } while(y<16) +} \ No newline at end of file