From a9e0c7805f826e6376cf7004f7c0e2cab4e82284 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Thu, 25 Jul 2019 17:26:43 +0200 Subject: [PATCH] Added error when exhausting zeropage space for variables. Closes #233 --- .../java/dk/camelot64/kickc/Compiler.java | 2 +- .../passes/Pass4AssertZeropageAllocation.java | 35 +++++++++++++++++++ .../dk/camelot64/kickc/test/TestPrograms.java | 6 +++- src/test/kc/zeropage-exhausted.kc | 11 ++++++ src/test/ref/euclid-3.asm | 2 +- src/test/ref/euclid-3.log | 6 ++-- 6 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass4AssertZeropageAllocation.java create mode 100644 src/test/kc/zeropage-exhausted.kc diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 89809e3f9..ec2f887a6 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -521,7 +521,7 @@ public class Compiler { new Pass4ZeroPageCoalesce(program).coalesce(); } new Pass4RegistersFinalize(program).allocate(true); - + new Pass4AssertZeropageAllocation(program).check(); } private void pass5GenerateAndOptimizeAsm() { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4AssertZeropageAllocation.java b/src/main/java/dk/camelot64/kickc/passes/Pass4AssertZeropageAllocation.java new file mode 100644 index 000000000..f5b61620c --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4AssertZeropageAllocation.java @@ -0,0 +1,35 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.Registers; +import dk.camelot64.kickc.model.symbols.Variable; + +import java.util.Collection; + +/*** Ensures that the variables fit on zeropage. */ +public class Pass4AssertZeropageAllocation extends Pass2Base { + + public Pass4AssertZeropageAllocation(Program program) { + super(program); + } + + /** + * Check that all variables fit onto zeropage + */ + public void check() { + Collection allVariables = getSymbols().getAllVariables(true); + for(Variable variable : allVariables) { + Registers.Register allocation = variable.getAllocation(); + if(allocation!=null && allocation.isZp()) { + int zp = ((Registers.RegisterZp) allocation).getZp(); + int sizeBytes = variable.getType().getSizeBytes(); + if(zp+sizeBytes>0x100) { + // Allocation is outside ZP! + throw new CompileError("Error! Variables used in program do not fit on zeropage. Maybe try compiling with -Ocoalesce to optimize ZP usage."); + } + } + } + } + +} diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index ec85f4c8e..05a1e3a81 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -35,12 +35,16 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testZeropageExhausted() throws IOException, URISyntaxException { + assertError("zeropage-exhausted", "Variables used in program do not fit on zeropage", false); + } + @Test public void testPlatformAsm6502() throws IOException, URISyntaxException { compileAndCompare("platform-asm6502"); } - @Test public void testEuclid2() throws IOException, URISyntaxException { compileAndCompare("euclid-3"); diff --git a/src/test/kc/zeropage-exhausted.kc b/src/test/kc/zeropage-exhausted.kc new file mode 100644 index 000000000..53c6500ef --- /dev/null +++ b/src/test/kc/zeropage-exhausted.kc @@ -0,0 +1,11 @@ +// Tests warning when running out of zeropage-addresses for variables + +// Start by reserving most of zeropage (254 bytes) +#reserve(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254) + +// And then allocate a 2-byte-variable +void main() { + const int* SCREEN = 0x0400; + for(int i=0;i<10;i++) + SCREEN[(char)i] = i; +} diff --git a/src/test/ref/euclid-3.asm b/src/test/ref/euclid-3.asm index cf60e97a3..132b35c4a 100644 --- a/src/test/ref/euclid-3.asm +++ b/src/test/ref/euclid-3.asm @@ -1,5 +1,5 @@ /* - * Find least common denominator using subtraction-based Euclidian algorithm + * Find greatest common denominator using subtraction-based Euclidian algorithm * See https://en.wikipedia.org/wiki/Euclidean_algorithm * Based on facebook post from */ diff --git a/src/test/ref/euclid-3.log b/src/test/ref/euclid-3.log index 512febf42..8c1ef7a66 100644 --- a/src/test/ref/euclid-3.log +++ b/src/test/ref/euclid-3.log @@ -1230,7 +1230,7 @@ INITIAL ASM Target platform is c64basic // File Comments /* - * Find least common denominator using subtraction-based Euclidian algorithm + * Find greatest common denominator using subtraction-based Euclidian algorithm * See https://en.wikipedia.org/wiki/Euclidean_algorithm * Based on facebook post from */ @@ -1782,7 +1782,7 @@ Allocated (was zp ZP_WORD:12) zp ZP_WORD:8 [ memset::dst#2 memset::dst#1 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments /* - * Find least common denominator using subtraction-based Euclidian algorithm + * Find greatest common denominator using subtraction-based Euclidian algorithm * See https://en.wikipedia.org/wiki/Euclidean_algorithm * Based on facebook post from */ @@ -2443,7 +2443,7 @@ Score: 1577 // File Comments /* - * Find least common denominator using subtraction-based Euclidian algorithm + * Find greatest common denominator using subtraction-based Euclidian algorithm * See https://en.wikipedia.org/wiki/Euclidean_algorithm * Based on facebook post from */