diff --git a/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java b/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java index 2509b55a2..07e0ef5f4 100644 --- a/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java +++ b/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java @@ -38,7 +38,10 @@ public class VariableBuilder { /** The data segment. */ private String dataSegment; - public VariableBuilder(String varName, Scope scope, boolean isParameter, SymbolType type, ArraySpec arraySpec, List directives, String dataSegment) { + /** Configuration of how to setup optimization/memory area for variables. */ + private VariableBuilderConfig config; + + public VariableBuilder(String varName, Scope scope, boolean isParameter, SymbolType type, ArraySpec arraySpec, List directives, String dataSegment, VariableBuilderConfig config) { this.varName = varName; this.scope = scope; this.isParameter = isParameter; @@ -46,14 +49,13 @@ public class VariableBuilder { this.arraySpec = arraySpec; this.directives = directives; this.dataSegment = dataSegment; + this.config = config; } public static VariableBuilderConfig getDefaultConfig(CompileLog log) { VariableBuilderConfig config = new VariableBuilderConfig(); config.addSetting("ssa_zp", log, null); config.addSetting("array_ma_mem", log, null); - config.addSetting("global_ma_mem", log, null); - config.addSetting("local_struct_ssa_zp", log, null); config.addSetting("global_struct_ma_mem", log, null); return config; } @@ -247,12 +249,15 @@ public class VariableBuilder { else if(isVolatile()) // volatile variables must be load/store return false; - else if(isTypeStruct() && isScopeGlobal()) - // global struct variables must be load/store - return false; - else - // All others are single-static-assignment (by default) - return true; + else { + VariableBuilderConfig.Scope scope = VariableBuilderConfig.getScope(isScopeGlobal(), isScopeLocal(), isScopeParameter(), isScopeMember()); + VariableBuilderConfig.Type type = VariableBuilderConfig.getType(isTypeInteger(), isArray(), isTypePointer(), isTypeStruct()); + VariableBuilderConfig.Setting setting = config.getSetting(scope, type); + if(setting!=null && VariableBuilderConfig.Optimization.MA.equals(setting.optimization)) + return false; + else + return true; + } } /** diff --git a/src/main/java/dk/camelot64/kickc/model/VariableBuilderConfig.java b/src/main/java/dk/camelot64/kickc/model/VariableBuilderConfig.java index 7b9ba3d55..ce803d9cf 100644 --- a/src/main/java/dk/camelot64/kickc/model/VariableBuilderConfig.java +++ b/src/main/java/dk/camelot64/kickc/model/VariableBuilderConfig.java @@ -4,9 +4,7 @@ import dk.camelot64.kickc.CompileLog; import dk.camelot64.kickc.model.operators.Operator; import dk.camelot64.kickc.model.statements.StatementSource; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; /** * Configuration for the {@link VariableBuilder} specifying how different variables should be compiled. @@ -62,13 +60,38 @@ public class VariableBuilderConfig { } } + /** Key of the settings map containing scope & type. */ + public static class ScopeType { + public Scope scope; + public Type type; + + public ScopeType(Scope scope, Type type) { + this.scope = scope; + this.type = type; + } + + @Override + public boolean equals(Object o) { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + ScopeType scopeType = (ScopeType) o; + return scope == scopeType.scope && + type == scopeType.type; + } + + @Override + public int hashCode() { + return Objects.hash(scope, type); + } + } + /** * The settings */ - private List settings; + private Map settings; VariableBuilderConfig() { - this.settings = new ArrayList<>(); + this.settings = new HashMap<>(); } public void addSetting(String pragmaParam, CompileLog log, StatementSource statementSource) { @@ -81,7 +104,7 @@ public class VariableBuilderConfig { throw new CompileError("Warning: Malformed var_model parameter "+pragmaParam, statementSource); for(Scope scope : scopes) { for(Type type : types) { - settings.add(new Setting(scope, type, memoryArea, optimization)); + settings.put(new ScopeType(scope, type), new Setting(scope, type, memoryArea, optimization)); } } } @@ -182,13 +205,31 @@ public class VariableBuilderConfig { * @return The memory area to use */ public Setting getSetting(Scope scope, Type type) { - for(Setting setting : settings) { - if(setting.scope.equals(scope) && setting.type.equals(type)) { - // Found perfect match - return it - return setting; - } - } - return null; + return settings.get(new ScopeType(scope, type)); + } + + public static Scope getScope(boolean isScopeGlobal, boolean isScopeLocal, boolean isScopeParameter, boolean isScopeMember) { + if(isScopeGlobal) + return Scope.GLOBAL; + if(isScopeLocal) + return Scope.LOCAL; + if(isScopeParameter) + return Scope.PARAMETER; + if(isScopeMember) + return Scope.MEMBER; + throw new InternalError("Unknown scope!"); + } + + public static Type getType(boolean isTypeInteger, boolean isTypeArray, boolean isTypePointer, boolean isTypeStruct) { + if(isTypeInteger) + return Type.INTEGER; + if(isTypeArray) + return Type.ARRAY; + if(isTypePointer) + return Type.POINTER; + if(isTypeStruct) + return Type.STRUCT; + throw new InternalError("Unknown type!"); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index abf99fe64..e43de29cf 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -276,7 +276,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor