From 17a9e90f2bddc321901e83360abb3e45553228bb Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Mon, 16 Dec 2019 22:51:59 +0100 Subject: [PATCH] Working on new VariableBuilder. --- .../kickc/fragment/AsmFragmentInstance.java | 4 +- .../kickc/model/VariableBuilder.java | 233 ++++++++++++++++++ ...ntext.java => VariableBuilderContext.java} | 61 +---- .../kickc/model/iterator/ProgramValue.java | 9 +- .../model/iterator/ProgramValueIterator.java | 4 +- .../camelot64/kickc/model/symbols/Scope.java | 4 +- .../kickc/model/symbols/Variable.java | 64 ++--- .../kickc/model/values/ConstantRef.java | 2 +- .../Pass0GenerateStatementSequence.java | 8 +- .../passes/Pass2ArrayInStructInlining.java | 2 +- ...ass2ConstantCallPointerIdentification.java | 2 +- .../passes/Pass2ConstantIdentification.java | 2 +- .../kickc/passes/Pass2ConstantInlining.java | 16 +- .../Pass2ConstantStringConsolidation.java | 4 +- .../kickc/passes/Pass3AssertArrayLengths.java | 2 +- .../kickc/passes/Pass4CodeGeneration.java | 8 +- .../kickc/passes/Pass4RegistersFinalize.java | 2 +- .../passes/PassNSizeOfSimplification.java | 6 +- 18 files changed, 296 insertions(+), 137 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/model/VariableBuilder.java rename src/main/java/dk/camelot64/kickc/model/{DirectiveParserContext.java => VariableBuilderContext.java} (76%) diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java index a09df4d7a..5d2f8ea28 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java @@ -90,7 +90,7 @@ public class AsmFragmentInstance { String constantValueAsm = AsmFormat.getAsmConstant(program, constantVar.getConstantRef(), 99, codeScopeRef); boolean constantValueZp = SymbolType.BYTE.equals(constantVar.getType()); if(!constantValueZp) { - constantValueZp = isConstantValueZp(constantVar.getConstantValue()); + constantValueZp = isConstantValueZp(constantVar.getInitValue()); } return new AsmParameter(constantValueAsm, constantValueZp); } else if(boundValue instanceof ConstantValue) { @@ -127,7 +127,7 @@ public class AsmFragmentInstance { } if(boundConst instanceof ConstantRef) { Variable reffedConstant = program.getScope().getConstant((ConstantRef) boundConst); - return isConstantValueZp(reffedConstant.getConstantValue()); + return isConstantValueZp(reffedConstant.getInitValue()); } if(boundConst instanceof ConstantCastValue) { SymbolType toType = ((ConstantCastValue) boundConst).getToType(); diff --git a/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java b/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java new file mode 100644 index 000000000..cf7445917 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java @@ -0,0 +1,233 @@ +package dk.camelot64.kickc.model; + +import dk.camelot64.kickc.model.statements.StatementSource; +import dk.camelot64.kickc.model.symbols.*; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypePointer; +import dk.camelot64.kickc.model.types.SymbolTypeStruct; +import dk.camelot64.kickc.model.values.ScopeRef; +import dk.camelot64.kickc.model.values.VariableRef; + +import java.util.List; + +/** + * Used for creating a {@link Variable} with the right properties based on the declaration incl. all directives and configuration. + * + * Holds information about the variable while it is being built. + */ +public class VariableBuilder { + + /** The scope of the variable. */ + private Scope scope; + + /** The variable is a function parameter declaration. */ + private boolean isParameter; + + /** The type of the variable. */ + private SymbolType type; + + /** Tye variable is an array. */ + private boolean isArray; + + /** A compile-time constant (const keyword and no volatile keyword and initValue is a compile-time constant) */ + private boolean isConstant; + + /** Declared as global private (static keyword and global variable) */ + private boolean isPrivate; + + /** Declared as local permanent (static keyword and local variable) */ + private boolean isPermanent; + + /** Declared as volatile (volatile keyword) */ + private boolean isVolatile; + + /** Declared as no-modify (const keyword) */ + private boolean isNoModify; + + /** Declared as optimize (register keyword) */ + private boolean isOptimize; + + /** Declared as pointer to volatile (volatile* keyword) */ + private boolean isToVolatile; + + /** Declared as pointer to no-modify (const* keyword) */ + private boolean isToNoModify; + + /** + * Is the type is a simple integer type. + * @return True if the type is a simple integer type. + */ + boolean isTypeInteger() { + return SymbolType.isInteger(type) || SymbolType.BOOLEAN.equals(type); + } + + /** + * Is the type is a pointer type. + * @return True if the type is a pointer type. + */ + boolean isTypePointer() { + return type instanceof SymbolTypePointer; + } + + /** + * Is the type is a struct type. + * @return True if the type is a struct type. + */ + boolean isTypeStruct() { + return type instanceof SymbolTypeStruct; + } + + /** The different scopes deciding directive defaults. */ + public enum DirectiveScope { + GLOBAL, LOCAL, PARAMETER, MEMBER; + + private static DirectiveScope getFor(Scope scope, boolean isParameter) { + if(isParameter) { + return PARAMETER; + } + if(ScopeRef.ROOT.equals(scope.getRef())) { + return GLOBAL; + } else if(scope instanceof Procedure) { + return LOCAL; + } else if(scope instanceof StructDefinition) { + return MEMBER; + } else if(scope instanceof BlockScope) { + return getFor(scope.getScope(), false); + } else { + throw new InternalError("Scope type not handled " + scope); + } + } + } + + public VariableBuilder() { + } + + /** + * Find the variable kind for a declared variable (not used for intermediates or PHI-versions) + * + * @param type The type of the variable + * @param scope The scope + * @param isParameter true if the variable is a procedure parameter + * @param sourceDirectives The directives in the source code + * @param source The source line (for exceptions) + * @return The variable kind + */ + public Variable.Kind getKind(SymbolType type, Scope scope, boolean isParameter, boolean isArray, List sourceDirectives, StatementSource source) { + // Look for const without volatile + if(hasDirective(Directive.Const.class, sourceDirectives)) + if(!hasDirective(Directive.Volatile.class, sourceDirectives)) + return Variable.Kind.CONSTANT; + // Look for array (which is implicitly const + //DirectiveType directiveType = DirectiveType.getFor(type); + if(isArray) + return Variable.Kind.CONSTANT; + // It is not a constant - determine PHI_MASTER vs LOAD_STORE + if(hasDirective(Directive.FormSsa.class, sourceDirectives)) + return Variable.Kind.PHI_MASTER; + if(hasDirective(Directive.FormMa.class, sourceDirectives)) + return Variable.Kind.LOAD_STORE; + if(hasDirective(Directive.Register.class, sourceDirectives)) + return Variable.Kind.PHI_MASTER; + if(hasDirective(Directive.NamedRegister.class, sourceDirectives)) + return Variable.Kind.PHI_MASTER; + // TODO: Add strategy for selecting LOAD_STORE for global vars + return Variable.Kind.PHI_MASTER; + } + + /** + * Applies directives to a variable. + * + * @param variable The variable to apply directives to + * @param sourceDirectives The directives found in the source code + * @param source The source line (for exceptions) + */ + public void applyDirectives(Variable variable, boolean isParameter, boolean isArray, List sourceDirectives, StatementSource source) { + if(hasDirective(Directive.Const.class, sourceDirectives)) + variable.setDeclaredConst(true); + if(isArray) + variable.setDeclaredConst(true); + if(hasDirective(Directive.Volatile.class, sourceDirectives)) + variable.setDeclaredVolatile(true); + if(hasDirective(Directive.Export.class, sourceDirectives)) + variable.setDeclaredExport(true); + if(hasDirective(Directive.Register.class, sourceDirectives)) { + variable.setMemoryArea(Variable.MemoryArea.ZEROPAGE_MEMORY); + variable.setDeclaredAsRegister(true); + } + if(isArray) + variable.setMemoryArea(Variable.MemoryArea.MAIN_MEMORY); + if(hasDirective(Directive.MemZp.class, sourceDirectives)) + variable.setMemoryArea(Variable.MemoryArea.ZEROPAGE_MEMORY); + if(hasDirective(Directive.MemMain.class, sourceDirectives)) + variable.setMemoryArea(Variable.MemoryArea.MAIN_MEMORY); + Directive.Address addressDirective = findDirective(Directive.Address.class, sourceDirectives); + if(addressDirective != null) { + Variable.MemoryArea memoryArea = (addressDirective.address < 0x100) ? Variable.MemoryArea.ZEROPAGE_MEMORY : Variable.MemoryArea.MAIN_MEMORY; + if(Variable.MemoryArea.ZEROPAGE_MEMORY.equals(memoryArea)) { + variable.setMemoryArea(Variable.MemoryArea.ZEROPAGE_MEMORY); + Registers.Register register = new Registers.RegisterZpMem(addressDirective.address.intValue(), -1, true); + variable.setDeclaredRegister(register); + } else { + variable.setMemoryArea(Variable.MemoryArea.MAIN_MEMORY); + Registers.Register register = new Registers.RegisterMainMem((VariableRef) variable.getRef(), -1, addressDirective.address); + variable.setDeclaredRegister(register); + } + } + + Directive.NamedRegister registerDirective = findDirective(Directive.NamedRegister.class, sourceDirectives); + if(registerDirective != null) { + variable.setDeclaredAsRegister(true); + Registers.Register register = Registers.getRegister(registerDirective.name); + if(register == null) { + throw new CompileError("Error! Unknown register " + registerDirective.name, source); + } + variable.setDeclaredRegister(register); + } + + Directive.Align alignDirective = findDirective(Directive.Align.class, sourceDirectives); + if(alignDirective != null) { + if(isArray) { + variable.setDeclaredAlignment(alignDirective.alignment); + } else { + throw new CompileError("Error! Cannot align variable that is not a string or an array " + variable.toString(), source); + } + } + + // TODO: Add strategy for selecting main memory for non-pointer local variables + //DirectiveScope directiveScope = DirectiveScope.getFor(lValue.getScope(), isParameter); + + } + + /** + * Examines whether a specific directive is present in the source + * + * @param directiveClass The class of the type to look for + * @param directives The list of directives to search + * @param The class of the type to look for + * @return true if the directive if found. false otherwise. + */ + private boolean hasDirective(Class directiveClass, List directives) { + return findDirective(directiveClass, directives) != null; + } + + + /** + * Look for a specific directive type in a list of directives + * + * @param directiveClass The class of the type to look for + * @param directives The list of directives to search + * @param The class of the type to look for + * @return The directive if found. null if not found. + */ + private DirectiveClass findDirective(Class directiveClass, List directives) { + if(directives == null) return null; + for(Directive directive : directives) { + if(directiveClass.isInstance(directive)) { + return (DirectiveClass) directive; + } + } + // Not found! + return null; + } + +} diff --git a/src/main/java/dk/camelot64/kickc/model/DirectiveParserContext.java b/src/main/java/dk/camelot64/kickc/model/VariableBuilderContext.java similarity index 76% rename from src/main/java/dk/camelot64/kickc/model/DirectiveParserContext.java rename to src/main/java/dk/camelot64/kickc/model/VariableBuilderContext.java index 9c9418ff7..90747abfc 100644 --- a/src/main/java/dk/camelot64/kickc/model/DirectiveParserContext.java +++ b/src/main/java/dk/camelot64/kickc/model/VariableBuilderContext.java @@ -11,61 +11,11 @@ import dk.camelot64.kickc.model.values.VariableRef; import java.util.List; /** - * The parser directive context is used for determining which directives to apply to a variable. + * Used for creating {@link Variable}s with the right properties based on all their directives */ -public class DirectiveParserContext { +public class VariableBuilderContext { - /** The different scopes deciding directive defaults. */ - public enum DirectiveScope { - GLOBAL, LOCAL, PARAMETER, MEMBER; - - private static DirectiveScope getFor(Scope scope, boolean isParameter) { - if(isParameter) { - return PARAMETER; - } - if(ScopeRef.ROOT.equals(scope.getRef())) { - return GLOBAL; - } else if(scope instanceof Procedure) { - return LOCAL; - } else if(scope instanceof StructDefinition) { - return MEMBER; - } else if(scope instanceof BlockScope) { - return getFor(scope.getScope(), false); - } else { - throw new InternalError("Scope type not handled " + scope); - } - } - } - - /** The different types deciding directive defaults. */ - public enum DirectiveType { - INTEGER, POINTER, ARRAY, STRUCT; - - /** - * Get a directive type from a variable type. - * - * @param type The variable type - * @return The directive type - */ - public static DirectiveType getFor(SymbolType type) { - if(SymbolType.isInteger(type)) { - return INTEGER; - } else if(SymbolType.BOOLEAN.equals(type)) { - return INTEGER; - } else if(SymbolType.STRING.equals(type)) { - return ARRAY; - } else if(type instanceof SymbolTypePointer) { - return POINTER; - } else if(type instanceof SymbolTypeStruct) { - return STRUCT; - } else { - throw new InternalError("Variable type not handled " + type); - } - } - } - - - public DirectiveParserContext() { + public VariableBuilderContext() { } /** @@ -84,7 +34,6 @@ public class DirectiveParserContext { if(!hasDirective(Directive.Volatile.class, sourceDirectives)) return Variable.Kind.CONSTANT; // Look for array (which is implicitly const - DirectiveType directiveType = DirectiveType.getFor(type); if(isArray) return Variable.Kind.CONSTANT; // It is not a constant - determine PHI_MASTER vs LOAD_STORE @@ -108,7 +57,6 @@ public class DirectiveParserContext { * @param source The source line (for exceptions) */ public void applyDirectives(Variable lValue, boolean isParameter, boolean isArray, List sourceDirectives, StatementSource source) { - DirectiveType directiveType = DirectiveType.getFor(lValue.getType()); if(hasDirective(Directive.Const.class, sourceDirectives)) lValue.setDeclaredConst(true); if(isArray) @@ -159,10 +107,7 @@ public class DirectiveParserContext { throw new CompileError("Error! Cannot align variable that is not a string or an array " + lValue.toString(), source); } } - // TODO: Add strategy for selecting main memory for non-pointer local variables - //DirectiveScope directiveScope = DirectiveScope.getFor(lValue.getScope(), isParameter); - } /** diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java index f805b2fd9..c7152b24f 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java @@ -608,21 +608,22 @@ public interface ProgramValue { } - class ProgramValueConstantVar implements ProgramValue { + /** The initial value of a variable. */ + class ProgramValueInitValue implements ProgramValue { private final Variable constantVar; - ProgramValueConstantVar(Variable constantVar) { + ProgramValueInitValue(Variable constantVar) { this.constantVar = constantVar; } @Override public Value get() { - return constantVar.getConstantValue(); + return constantVar.getInitValue(); } @Override public void set(Value val) { - constantVar.setConstantValue((ConstantValue) val); + constantVar.setInitValue((ConstantValue) val); } } diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java index ef31b102c..23d832fb3 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java @@ -48,8 +48,8 @@ public class ProgramValueIterator { * @param programValueHandler The programValueHandler to execute */ public static void execute(Variable variable, ProgramValueHandler programValueHandler) { - if(variable.isKindConstant()) { - execute(new ProgramValue.ProgramValueConstantVar(variable), programValueHandler, null, null, null); + if(variable.getInitValue()!=null) { + execute(new ProgramValue.ProgramValueInitValue(variable), programValueHandler, null, null, null); } if(variable.isArray()) { execute(new ProgramValue.ProgramValueArraySize(variable), programValueHandler, null, null, null); 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 4d03840bf..d2f1a056c 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java @@ -394,8 +394,8 @@ public abstract class Scope implements Symbol, Serializable { } } } - if(symVar.isKindConstant() && symVar.getConstantValue()!=null) { - res.append(" = " + symVar.getConstantValue().toString(program)); + if(symVar.getInitValue()!=null) { + res.append(" = " + symVar.getInitValue().toString(program)); } res.append("\n"); } 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 a6c8165fc..8f9069746 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java @@ -18,8 +18,8 @@ import java.util.Objects; /** A Variable symbol (can either be a runtime variable or a compile-time constant). *

- * Array values are implemented as {@link Kind#CONSTANT}s with the array data in {@link #getConstantValue()} and the declared size in {@link #getArraySpec()}. - * Struct values are implemented as {@link Kind#LOAD_STORE}s with the initial data in {@link #getConstantValue()} and the strategy for accessing it in {@link #getStructStrategy()}. + * Array values are implemented as {@link Kind#CONSTANT}s with the array data in {@link #getInitValue()} and the declared size in {@link #getArraySpec()}. + * Struct values are implemented as {@link Kind#LOAD_STORE}s with the initial data in {@link #getInitValue()} or as {@link Kind#PHI_MASTER}s that will be unwound to member variables during compilation. *

**/ public class Variable implements Symbol { @@ -93,23 +93,12 @@ public class Variable implements Symbol { /** The data segment to put the variable into (if it is allocated in memory). [Only variables stored in memory and arrays] */ private String dataSegment; - /** The constant value if the variable is a constant. Null otherwise. [Only constants] */ - private ConstantValue constantValue; + /** The initial compiletime-value of the variable. Null if no initial value present. [Constants, Arrays, global/local-static loadstore-variables ] */ + private ConstantValue initValue; /** Non-null if the variable is an array. [Only constants that are arrays] */ private ArraySpec arraySpec; - /** Strategy for handling a struct variable during compilation. */ - public enum StructStrategy { - /** The struct is stored in memory and accessed using OFFSET's */ - CSTANDARD, - /** The struct is unwound and handled as if each member was a separate variable. */ - UNWINDING - } - - /** Non-null if the variable is a struct value. Strategy for how to handle the struct value. [Only constants that are structs] */ - private StructStrategy structStrategy; - /** The number of the next version (only used for PHI masters) [Only PHI masters] */ private Integer nextPhiVersionNumber; @@ -126,9 +115,9 @@ public class Variable implements Symbol { * @param memoryArea The memory area (zeropage/main memory) * @param dataSegment The data segment (in main memory) * @param arraySpec The array specification of the variable (if it is an array) - * @param constantValue The constant value of the variable (if it is constant) + * @param initValue The constant value of the variable (if it is constant) */ - private Variable(String name, Kind kind, SymbolType type, Scope scope, MemoryArea memoryArea, String dataSegment, ArraySpec arraySpec, StructStrategy structStrategy, ConstantValue constantValue) { + private Variable(String name, Kind kind, SymbolType type, Scope scope, MemoryArea memoryArea, String dataSegment, ArraySpec arraySpec, ConstantValue initValue) { this.name = name; this.kind = kind; if(Kind.PHI_MASTER.equals(kind)) @@ -136,8 +125,7 @@ public class Variable implements Symbol { this.type = type; this.scope = scope; this.arraySpec = arraySpec; - this.structStrategy = structStrategy; - this.constantValue = constantValue; + this.initValue = initValue; this.dataSegment = dataSegment; this.memoryArea = memoryArea; this.comments = new ArrayList<>(); @@ -153,7 +141,7 @@ public class Variable implements Symbol { * @return The new intermediate variable */ public static Variable createIntermediate(String name, Scope scope, String dataSegment) { - return new Variable(name, Kind.INTERMEDIATE, SymbolType.VAR, scope, MemoryArea.ZEROPAGE_MEMORY, dataSegment, null, null, null); + return new Variable(name, Kind.INTERMEDIATE, SymbolType.VAR, scope, MemoryArea.ZEROPAGE_MEMORY, dataSegment, null, null); } /** @@ -167,7 +155,7 @@ public class Variable implements Symbol { * @return The new PHI-master variable */ public static Variable createLoadStore(String name, SymbolType type, Scope scope, Variable.MemoryArea memoryArea, String dataSegment) { - return new Variable(name, Kind.LOAD_STORE, type, scope, memoryArea, dataSegment, null, null, null); + return new Variable(name, Kind.LOAD_STORE, type, scope, memoryArea, dataSegment, null, null); } /** @@ -181,7 +169,7 @@ public class Variable implements Symbol { * @return The new PHI-master variable */ public static Variable createPhiMaster(String name, SymbolType type, Scope scope, Variable.MemoryArea memoryArea, String dataSegment) { - return new Variable(name, Kind.PHI_MASTER, type, scope, memoryArea, dataSegment, null, null, null); + return new Variable(name, Kind.PHI_MASTER, type, scope, memoryArea, dataSegment, null, null); } /** @@ -193,7 +181,7 @@ public class Variable implements Symbol { public static Variable createPhiVersion(Variable phiMaster, int versionNum) { if(!phiMaster.isKindPhiMaster()) throw new InternalError("Cannot version non-PHI variable " + phiMaster.toString()); - Variable version = new Variable(phiMaster.getName() + "#" + versionNum, Kind.PHI_VERSION, phiMaster.getType(), phiMaster.getScope(), phiMaster.getMemoryArea(), phiMaster.getDataSegment(), phiMaster.getArraySpec(), phiMaster.getStructStrategy(), null); + Variable version = new Variable(phiMaster.getName() + "#" + versionNum, Kind.PHI_VERSION, phiMaster.getType(), phiMaster.getScope(), phiMaster.getMemoryArea(), phiMaster.getDataSegment(), phiMaster.getArraySpec(), null); version.setDeclaredAlignment(phiMaster.getDeclaredAlignment()); version.setDeclaredAsRegister(phiMaster.isDeclaredAsRegister()); version.setDeclaredConst(phiMaster.isDeclaredConst()); @@ -227,7 +215,7 @@ public class Variable implements Symbol { * @param dataSegment The data segment (in main memory) */ public static Variable createConstant(String name, SymbolType type, Scope scope, ArraySpec arraySpec, ConstantValue constantValue, String dataSegment) { - return new Variable(name, Kind.CONSTANT, type, scope, MemoryArea.MAIN_MEMORY, dataSegment, arraySpec, null, constantValue); + return new Variable(name, Kind.CONSTANT, type, scope, MemoryArea.MAIN_MEMORY, dataSegment, arraySpec, constantValue); } /** @@ -257,7 +245,7 @@ public class Variable implements Symbol { * @param original The original variable */ public static Variable createCopy(String name, Scope scope, Variable original) { - Variable copy = new Variable(name, original.getKind(), original.getType(), scope, original.getMemoryArea(), original.getDataSegment(), original.getArraySpec(), original.getStructStrategy(), original.getConstantValue()); + Variable copy = new Variable(name, original.getKind(), original.getType(), scope, original.getMemoryArea(), original.getDataSegment(), original.getArraySpec(), original.getInitValue()); copy.setDeclaredAlignment(original.getDeclaredAlignment()); copy.setDeclaredAsRegister(original.isDeclaredAsRegister()); copy.setDeclaredConst(original.isDeclaredConst()); @@ -283,13 +271,13 @@ public class Variable implements Symbol { Variable memberVariable; if(isParameter && memberDefinition.isArray()) { // Array struct members are converted to pointers when unwound (use same kind as the struct variable) - memberVariable = new Variable(name, structVar.getKind(), memberDefinition.getType(), structVar.getScope(), memoryArea, structVar.getDataSegment(), null, null, null); + memberVariable = new Variable(name, structVar.getKind(), memberDefinition.getType(), structVar.getScope(), memoryArea, structVar.getDataSegment(), null, null); } else if(memberDefinition.isKindConstant()) { // Constant members are unwound as constants - memberVariable = new Variable(name, Kind.CONSTANT, memberDefinition.getType(), structVar.getScope(), memoryArea, structVar.getDataSegment(), memberDefinition.getArraySpec(), memberDefinition.getStructStrategy(), memberDefinition.getConstantValue()); + memberVariable = new Variable(name, Kind.CONSTANT, memberDefinition.getType(), structVar.getScope(), memoryArea, structVar.getDataSegment(), memberDefinition.getArraySpec(), memberDefinition.getInitValue()); } else { // For others the kind is preserved from the member definition - memberVariable = new Variable(name, structVar.getKind(), memberDefinition.getType(), structVar.getScope(), memoryArea, structVar.getDataSegment(), memberDefinition.getArraySpec(), memberDefinition.getStructStrategy(), memberDefinition.getConstantValue()); + memberVariable = new Variable(name, structVar.getKind(), memberDefinition.getType(), structVar.getScope(), memoryArea, structVar.getDataSegment(), memberDefinition.getArraySpec(), memberDefinition.getInitValue()); } memberVariable.setDeclaredVolatile(structVar.isDeclaredVolatile()); memberVariable.setInferredVolatile(structVar.isInferredVolatile()); @@ -395,14 +383,6 @@ public class Variable implements Symbol { return type instanceof SymbolTypeStruct; } - public StructStrategy getStructStrategy() { - return structStrategy; - } - - public void setStructStrategy(StructStrategy structStrategy) { - this.structStrategy = structStrategy; - } - public Registers.Register getAllocation() { return allocation; } @@ -411,12 +391,12 @@ public class Variable implements Symbol { this.allocation = allocation; } - public ConstantValue getConstantValue() { - return constantValue; + public ConstantValue getInitValue() { + return initValue; } - public void setConstantValue(ConstantValue value) { - this.constantValue = value; + public void setInitValue(ConstantValue value) { + this.initValue = value; } public String getDataSegment() { @@ -573,9 +553,9 @@ public class Variable implements Symbol { public String toString(Program program) { return new StringBuilder() .append("(") - .append((constantValue != null) ? "const " : "") + .append((initValue != null) ? "const " : "") .append(getType().getTypeName()) - .append((constantValue == null && isKindIntermediate()) ? "~" : "") + .append((initValue == null && isKindIntermediate()) ? "~" : "") .append(") ") .append(getFullName()).toString(); } diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantRef.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantRef.java index 993dbafab..aacb87cc2 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantRef.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantRef.java @@ -23,7 +23,7 @@ public class ConstantRef extends SymbolVariableRef implements ConstantValue { @Override public ConstantLiteral calculateLiteral(ProgramScope scope) { Variable constantVar = scope.getConstant(this); - ConstantValue constantVarValue = constantVar.getConstantValue(); + ConstantValue constantVarValue = constantVar.getInitValue(); return constantVarValue.calculateLiteral(scope); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index abd0ec520..7efb115c3 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -48,7 +48,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor(); this.defaultMemoryArea = Variable.MemoryArea.ZEROPAGE_MEMORY; - this.directiveContext = new DirectiveParserContext(); + this.directiveContext = new VariableBuilderContext(); scopeStack.push(program.getScope()); } @@ -1551,7 +1551,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor> constantStringMap = new LinkedHashMap<>(); for(Variable constVar : getScope().getAllConstants(true)) { - ConstantValue constVal = constVar.getConstantValue(); + ConstantValue constVal = constVar.getInitValue(); if(constVal instanceof ConstantString) { ConstantString constString = (ConstantString) constVal; List constantVars = constantStringMap.computeIfAbsent(constString, k -> new ArrayList<>()); @@ -101,7 +101,7 @@ public class Pass2ConstantStringConsolidation extends Pass2SsaOptimization { // Modify all other constants to be references to the root constant for(Variable constantVar : constantVars) { if(!constantVar.equals(rootConstant)) { - constantVar.setConstantValue(new ConstantRef(rootConstant)); + constantVar.setInitValue(new ConstantRef(rootConstant)); modified = true; } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertArrayLengths.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertArrayLengths.java index b3bcb2f35..98e9b19f9 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertArrayLengths.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertArrayLengths.java @@ -30,7 +30,7 @@ public class Pass3AssertArrayLengths extends Pass2SsaAssertion { } Integer declaredSizeInt = ((ConstantInteger) declaredSizeVal).getInteger().intValue(); // A constant size was found - Check that a value with the same size is present - ConstantValue constantValue = constantVar.getConstantValue(); + ConstantValue constantValue = constantVar.getInitValue(); if(constantValue == null) { throw new CompileError("Error! Array with a size not initialized " + constantVar.toString(getProgram())); } else if(constantValue instanceof ConstantArrayFilled) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index 0e6d5a247..fed51da0e 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -300,7 +300,7 @@ public class Pass4CodeGeneration { } private boolean hasData(Variable constantVar) { - ConstantValue constantValue = constantVar.getConstantValue(); + ConstantValue constantValue = constantVar.getInitValue(); if(constantValue instanceof ConstantArray) { return true; } else { @@ -400,9 +400,9 @@ public class Pass4CodeGeneration { // Add any comments generateComments(asm, constantVar.getComments()); // Ensure encoding is good - ensureEncoding(asm, constantVar.getConstantValue()); + ensureEncoding(asm, constantVar.getInitValue()); // Find the constant value calculation - String asmConstant = AsmFormat.getAsmConstant(program, constantVar.getConstantValue(), 99, scopeRef); + String asmConstant = AsmFormat.getAsmConstant(program, constantVar.getInitValue(), 99, scopeRef); if(constantVar.getType() instanceof SymbolTypePointer) { // Must use a label for pointers asm.addLabelDecl(AsmFormat.asmFix(asmName), asmConstant); @@ -482,7 +482,7 @@ public class Pass4CodeGeneration { String alignment = AsmFormat.getAsmNumber(declaredAlignment); asm.addDataAlignment(alignment); } - ConstantValue constantValue = constantVar.getConstantValue(); + ConstantValue constantValue = constantVar.getInitValue(); if(constantValue instanceof ConstantArray || constantValue instanceof ConstantString) { AsmDataChunk asmDataChunk = new AsmDataChunk(); addChunkData(asmDataChunk, constantValue, constantVar.getType(), constantVar.getArraySpec(), scopeRef); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java index cfb38692e..743cdd3fd 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java @@ -116,7 +116,7 @@ public class Pass4RegistersFinalize extends Pass2Base { } } for(Variable constantVar : scope.getAllConstants(false)) { - Registers.Register allocation = new Registers.RegisterConstant(constantVar.getConstantValue()); + Registers.Register allocation = new Registers.RegisterConstant(constantVar.getInitValue()); shortenAsmName(shortNames, constantVar, allocation); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNSizeOfSimplification.java b/src/main/java/dk/camelot64/kickc/passes/PassNSizeOfSimplification.java index 8474065ae..19925349f 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNSizeOfSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNSizeOfSimplification.java @@ -78,9 +78,9 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization { ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), arrayType.getElementType()); programValue.set(new ConstantBinary((ConstantValue) arraySize, Operators.MULTIPLY, sizeOfConstantVar)); modified.set(true); - } else if(constant.getConstantValue() instanceof ConstantArrayList) { + } else if(constant.getInitValue() instanceof ConstantArrayList) { getLog().append("Resolving array sizeof() " + unary.toString(getProgram())); - int size = ((ConstantArrayList) constant.getConstantValue()).getElements().size(); + int size = ((ConstantArrayList) constant.getInitValue()).getElements().size(); ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), arrayType.getElementType()); programValue.set(new ConstantBinary(new ConstantInteger((long) size), Operators.MULTIPLY, sizeOfConstantVar)); modified.set(true); @@ -88,7 +88,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization { // Try to calculate the literal to check if it is a string ConstantLiteral stringLiteral = null; try { - stringLiteral = constant.getConstantValue().calculateLiteral(getProgram().getScope()); + stringLiteral = constant.getInitValue().calculateLiteral(getProgram().getScope()); } catch(ConstantNotLiteral e) { // Ignore }