diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplate.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplate.java index 596107827..1b8c76263 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplate.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplate.java @@ -80,12 +80,12 @@ public class AsmFragmentTemplate { ProgramScope scope = new ProgramScope(); LinkedHashMap bindings = new LinkedHashMap<>(); { - Variable v1 = new Variable("z1", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION); - Variable v2 = new Variable("z2", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION); - Variable v3 = new Variable("z3", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION); - Variable v4 = new Variable("z4", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION); - Variable v5 = new Variable("z5", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION); - Variable v6 = new Variable("z6", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION); + Variable v1 = new Variable("z1", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION, SymbolVariable.MemoryArea.ZEROPAGE); + Variable v2 = new Variable("z2", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION, SymbolVariable.MemoryArea.ZEROPAGE); + Variable v3 = new Variable("z3", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION, SymbolVariable.MemoryArea.ZEROPAGE); + Variable v4 = new Variable("z4", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION, SymbolVariable.MemoryArea.ZEROPAGE); + Variable v5 = new Variable("z5", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION, SymbolVariable.MemoryArea.ZEROPAGE); + Variable v6 = new Variable("z6", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION, SymbolVariable.MemoryArea.ZEROPAGE); v1.setAllocation(new Registers.RegisterZpMem(2, 1)); v2.setAllocation(new Registers.RegisterZpMem(4, 1)); v3.setAllocation(new Registers.RegisterZpMem(6, 1)); @@ -100,12 +100,12 @@ public class AsmFragmentTemplate { if(signature.contains("z6")) bindings.put("z6", v6); } { - Variable v1 = new Variable("m1", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY); - Variable v2 = new Variable("m2", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY); - Variable v3 = new Variable("m3", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY); - Variable v4 = new Variable("m4", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY); - Variable v5 = new Variable("m5", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY); - Variable v6 = new Variable("m6", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY); + Variable v1 = new Variable("m1", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY, SymbolVariable.MemoryArea.MAIN_MEMORY); + Variable v2 = new Variable("m2", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY, SymbolVariable.MemoryArea.MAIN_MEMORY); + Variable v3 = new Variable("m3", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY, SymbolVariable.MemoryArea.MAIN_MEMORY); + Variable v4 = new Variable("m4", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY, SymbolVariable.MemoryArea.MAIN_MEMORY); + Variable v5 = new Variable("m5", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY, SymbolVariable.MemoryArea.MAIN_MEMORY); + Variable v6 = new Variable("m6", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY, SymbolVariable.MemoryArea.MAIN_MEMORY); v1.setAllocation(new Registers.RegisterMainMem(v1.getRef(), 1)); v2.setAllocation(new Registers.RegisterMainMem(v2.getRef(), 1)); v3.setAllocation(new Registers.RegisterMainMem(v3.getRef(), 1)); diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/ConstantVar.java b/src/main/java/dk/camelot64/kickc/model/symbols/ConstantVar.java index b187f93b7..0af6b0adc 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/ConstantVar.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/ConstantVar.java @@ -12,7 +12,7 @@ public class ConstantVar extends SymbolVariable { private ConstantValue value; public ConstantVar(String name, Scope scope, SymbolType type, ConstantValue value, String dataSegment) { - super(name, scope, type, StorageStrategy.CONSTANT, dataSegment); + super(name, scope, type, StorageStrategy.CONSTANT, MemoryArea.NONE, dataSegment); this.value = value; } diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java index e5158502f..64b23823d 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java @@ -99,13 +99,13 @@ public abstract class Scope implements Symbol, Serializable { symbols.remove(symbol.getLocalName()); } - public Variable addVariablePhiMaster(String name, SymbolType type, String dataSegment) { - return add(new Variable(name, this, type, dataSegment, SymbolVariable.StorageStrategy.PHI_MASTER)); + public Variable addVariablePhiMaster(String name, SymbolType type, SymbolVariable.MemoryArea memoryArea, String dataSegment) { + return add(new Variable(name, this, type, dataSegment, SymbolVariable.StorageStrategy.PHI_MASTER, memoryArea)); } public Variable addVariableIntermediate() { String name = allocateIntermediateVariableName(); - return add(new Variable(name, this, SymbolType.VAR, getSegmentData(), SymbolVariable.StorageStrategy.INTERMEDIATE)); + return add(new Variable(name, this, SymbolType.VAR, getSegmentData(), SymbolVariable.StorageStrategy.INTERMEDIATE, SymbolVariable.MemoryArea.ZEROPAGE)); } /** diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/SymbolVariable.java b/src/main/java/dk/camelot64/kickc/model/symbols/SymbolVariable.java index dd0584148..fd3b2e318 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/SymbolVariable.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/SymbolVariable.java @@ -55,16 +55,23 @@ public abstract class SymbolVariable implements Symbol { /** Strategy being used for storing and accessing the variable. The value depends on the directives memory/register/volatile/const - and on the compilers optimization decisions. * **/ - public enum StorageStrategy {PHI_MASTER, PHI_VERSION, INTERMEDIATE, MEMORY, CONSTANT } + public enum StorageStrategy { PHI_MASTER, PHI_VERSION, INTERMEDIATE, MEMORY, CONSTANT } /** The storage strategy for the variable. */ private StorageStrategy storageStrategy; + /** Memory area used for storing the variable (if is is stored in memory). */ + public enum MemoryArea { ZEROPAGE, MAIN_MEMORY } + + /** The memory area where the variable lives (if stored in memory). */ + private MemoryArea memoryArea; + /** Comments preceding the procedure in the source code. */ private List comments; @@ -75,7 +82,7 @@ public abstract class SymbolVariable implements Symbol { private String dataSegment; - public SymbolVariable(String name, Scope scope, SymbolType type, StorageStrategy storageStrategy, String dataSegment) { + public SymbolVariable(String name, Scope scope, SymbolType type, StorageStrategy storageStrategy, MemoryArea memoryArea, String dataSegment) { this.name = name; this.scope = scope; this.type = type; @@ -83,6 +90,7 @@ public abstract class SymbolVariable implements Symbol { this.comments = new ArrayList<>(); this.dataSegment = dataSegment; this.storageStrategy = storageStrategy; + this.memoryArea = memoryArea; setFullName(); } @@ -265,6 +273,22 @@ public abstract class SymbolVariable implements Symbol { return StorageStrategy.INTERMEDIATE.equals(getStorageStrategy()); } + public MemoryArea getMemoryArea() { + return memoryArea; + } + + public void setMemoryArea(MemoryArea memoryArea) { + this.memoryArea = memoryArea; + } + + public boolean isMemoryAreaZp() { + return MemoryArea.ZEROPAGE.equals(getMemoryArea()); + } + + public boolean isMemoryAreaMain() { + return MemoryArea.MAIN_MEMORY.equals(getMemoryArea()); + } + public List getComments() { return comments; } diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java b/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java index 07950db4b..b8b65b419 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java @@ -25,8 +25,8 @@ public class Variable extends SymbolVariable { /** If the variable is assigned to a specific "register", this contains the register. If null the variable has no allocation (yet). Constants are never assigned to registers. */ private Registers.Register allocation; - public Variable(String name, Scope scope, SymbolType type, String dataSegment, StorageStrategy storageStrategy) { - super(name, scope, type, storageStrategy, dataSegment); + public Variable(String name, Scope scope, SymbolType type, String dataSegment, StorageStrategy storageStrategy, MemoryArea memoryArea) { + super(name, scope, type, storageStrategy, memoryArea, dataSegment); if(isStoragePhiMaster()) this.nextPhiVersionNumber = 0; } @@ -38,7 +38,7 @@ public class Variable extends SymbolVariable { * @param version The version number */ public Variable(Variable phiMaster, int version) { - super(phiMaster.getName() + "#" + version, phiMaster.getScope(), phiMaster.getType(), StorageStrategy.PHI_VERSION, phiMaster.getDataSegment()); + super(phiMaster.getName() + "#" + version, phiMaster.getScope(), phiMaster.getType(), StorageStrategy.PHI_VERSION, phiMaster.getMemoryArea(), phiMaster.getDataSegment()); this.setDeclaredAlignment(phiMaster.getDeclaredAlignment()); this.setDeclaredAsRegister(phiMaster.isDeclaredAsRegister()); this.setDeclaredAsMemory(phiMaster.isDeclaredAsMemory()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 135076744..0b8d677e2 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -43,6 +43,8 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor scopeStack; + /** The memory area used by default for variables. */ + private SymbolVariable.MemoryArea defaultMemoryArea; public Pass0GenerateStatementSequence(CParser cParser, KickCParser.FileContext fileCtx, Program program) { this.cParser = cParser; @@ -50,6 +52,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor(); + this.defaultMemoryArea = SymbolVariable.MemoryArea.ZEROPAGE; scopeStack.push(program.getScope()); } @@ -201,7 +204,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor parameterList = new ArrayList<>(); if(ctx.parameterListDecl() != null) { @@ -260,7 +263,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor directives = declVarDirectives; - Variable param = new Variable(ctx.NAME().getText(), getCurrentScope(), type, currentDataSegment, SymbolVariable.StorageStrategy.PHI_MASTER); + Variable param = new Variable(ctx.NAME().getText(), getCurrentScope(), type, currentDataSegment, SymbolVariable.StorageStrategy.PHI_MASTER, defaultMemoryArea); // Add directives addDirectives(param, type, directives, new StatementSource(ctx)); exitDeclTypes(); @@ -613,7 +616,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor scopeVariables = scope.getAllVariables(false); for(Variable variable : scopeVariables) { - if(variable.isStorageMemory()) { + if(variable.isMemoryAreaMain()) { // Skip if already added String asmName = variable.getAsmName() == null ? variable.getLocalName() : variable.getAsmName(); if(added.contains(asmName)) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java index bcc0574c6..f47e98ac1 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java @@ -181,7 +181,7 @@ public class Pass4RegistersFinalize extends Pass2Base { String before = register == null ? null : register.toString(); VariableRef variableRef = equivalenceClass.getVariables().get(0); Variable variable = getProgram().getSymbolInfos().getVariable(variableRef); - if(variable.isStorageMemory()) { + if(variable.isMemoryAreaMain()) { register = new Registers.RegisterMainMem(variableRef, variable.getType().getSizeBytes()); } else { register = allocateNewRegisterZp(variable); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java index e7f55803c..c094d4547 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java @@ -137,9 +137,11 @@ public class PassNTypeInference extends Pass2SsaOptimization { if(symbol.getType() instanceof SymbolTypeArray) { symbol.setDeclaredConstant(true); symbol.setStorageStrategy(SymbolVariable.StorageStrategy.CONSTANT); + symbol.setMemoryArea(SymbolVariable.MemoryArea.NONE); } else if(SymbolType.STRING.equals(symbol.getType())) { symbol.setDeclaredConstant(true); symbol.setStorageStrategy(SymbolVariable.StorageStrategy.CONSTANT); + symbol.setMemoryArea(SymbolVariable.MemoryArea.NONE); } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/utils/Unroller.java b/src/main/java/dk/camelot64/kickc/passes/utils/Unroller.java index 3e066b880..a7327ec43 100644 --- a/src/main/java/dk/camelot64/kickc/passes/utils/Unroller.java +++ b/src/main/java/dk/camelot64/kickc/passes/utils/Unroller.java @@ -236,6 +236,7 @@ public class Unroller { newVar.setDeclaredAsMemory(definedVar.isDeclaredAsMemory()); newVar.setDeclaredMemoryAddress(definedVar.getDeclaredMemoryAddress()); newVar.setStorageStrategy(definedVar.getStorageStrategy()); + newVar.setMemoryArea(definedVar.getMemoryArea()); newVar.setDeclaredVolatile(definedVar.isDeclaredVolatile()); newVar.setInferedVolatile(definedVar.isInferedVolatile()); newVar.setDeclaredExport(definedVar.isDeclaredExport());