diff --git a/src/main/java/dk/camelot64/kickc/model/CallingConventionStack.java b/src/main/java/dk/camelot64/kickc/model/CallingConventionStack.java index 76769ceb8..d992896d5 100644 --- a/src/main/java/dk/camelot64/kickc/model/CallingConventionStack.java +++ b/src/main/java/dk/camelot64/kickc/model/CallingConventionStack.java @@ -23,7 +23,7 @@ public class CallingConventionStack { if(returnOffsetConstant == null) { // Constant not found - create it long returnByteOffset = getReturnByteOffset(procedure); - returnOffsetConstant = new Variable(returnOffsetConstantName, procedure, SymbolType.BYTE, false, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(returnByteOffset & 0xff, SymbolType.BYTE)); + returnOffsetConstant = new Variable(returnOffsetConstantName, procedure, SymbolType.BYTE, null, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(returnByteOffset & 0xff, SymbolType.BYTE)); procedure.add(returnOffsetConstant); } return returnOffsetConstant.getConstantRef(); @@ -42,7 +42,7 @@ public class CallingConventionStack { if(paramOffsetConstant == null) { // Constant not found - create it long paramByteOffset = getParameterByteOffset(procedure, parameter); - paramOffsetConstant = new Variable(paramOffsetConstantName, procedure, SymbolType.BYTE, false, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(paramByteOffset & 0xff, SymbolType.BYTE)); + paramOffsetConstant = new Variable(paramOffsetConstantName, procedure, SymbolType.BYTE, null, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(paramByteOffset & 0xff, SymbolType.BYTE)); procedure.add(paramOffsetConstant); } return paramOffsetConstant.getConstantRef(); @@ -123,7 +123,7 @@ public class CallingConventionStack { */ public static ConstantRef getStackBaseConstant(ProgramScope programScope) { long STACK_BASE_ADDRESS = 0x103L; - Variable stackBase = new Variable("STACK_BASE", programScope, SymbolType.WORD, false, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(STACK_BASE_ADDRESS, SymbolType.WORD)); + Variable stackBase = new Variable("STACK_BASE", programScope, SymbolType.WORD, null, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(STACK_BASE_ADDRESS, SymbolType.WORD)); programScope.add(stackBase); return stackBase.getConstantRef(); } 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 6a5188021..857ea35c6 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java @@ -936,12 +936,12 @@ public interface ProgramValue { @Override public Value get() { - return variable.getArraySize(); + return variable.getArraySpec().getArraySize(); } @Override public void set(Value val) { - variable.setArraySize((ConstantValue) val); + variable.getArraySpec().setArraySize((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 3bed2d832..a39f700bb 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java @@ -51,7 +51,7 @@ public class ProgramValueIterator { if(variable.isConstant()) { execute(new ProgramValue.ProgramValueConstantVar(variable), programValueHandler, null, null, null); } - if(variable.getArraySize()!=null) { + if(variable.isArray()) { execute(new ProgramValue.ProgramValueArraySize(variable), programValueHandler, null, null, null); } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java index f91bc139b..68bc3e59f 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java @@ -42,7 +42,7 @@ public class OperatorSizeOf extends OperatorUnary { if(typeSizeConstant == null) { // Constant not found - create it long typeSize = type.getSizeBytes(); - typeSizeConstant = new Variable(typeConstName, programScope, SymbolType.BYTE, false, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(typeSize&0xff, SymbolType.BYTE)); + typeSizeConstant = new Variable(typeConstName, programScope, SymbolType.BYTE, null, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(typeSize&0xff, SymbolType.BYTE)); programScope.add(typeSizeConstant); } return typeSizeConstant.getConstantRef(); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java index 9b1d1c8c0..77b729649 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java @@ -47,7 +47,7 @@ public class OperatorTypeId extends OperatorUnary { if(typeIdConstant == null) { // Constant not found - create it long typeSize = getTypeId(type); - typeIdConstant = new Variable(typeConstName, programScope, SymbolType.BYTE, false, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(typeSize)); + typeIdConstant = new Variable(typeConstName, programScope, SymbolType.BYTE, null, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(typeSize)); programScope.add(typeIdConstant); } return typeIdConstant.getConstantRef(); diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/ArraySpec.java b/src/main/java/dk/camelot64/kickc/model/symbols/ArraySpec.java new file mode 100644 index 000000000..9607e17bf --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/symbols/ArraySpec.java @@ -0,0 +1,28 @@ +package dk.camelot64.kickc.model.symbols; + +import dk.camelot64.kickc.model.values.ConstantValue; + +/** Specification of array properties of a variable. + * The presence of this means the variable is an array. + * If the size of the array is fixed this will contain the size. + * */ +public class ArraySpec { + + /** If the variable is a fixed size array this is the fixed size of the array. */ + private ConstantValue arraySize; + + public ArraySpec() { + } + + public ArraySpec(ConstantValue arraySize) { + this.arraySize = arraySize; + } + + public ConstantValue getArraySize() { + return arraySize; + } + + public void setArraySize(ConstantValue arraySize) { + this.arraySize = arraySize; + } +} diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java b/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java index 4702a3282..4a061a685 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java @@ -43,7 +43,7 @@ public class StructDefinition extends Scope { if(structMember.equals(member)) { break; } else { - byteOffset += SymbolTypeStruct.getMemberSizeBytes(structMember.getType(), structMember.isArray(), structMember.getArraySize(), programScope); + byteOffset += SymbolTypeStruct.getMemberSizeBytes(structMember.getType(), structMember.getArraySpec(), programScope); } } return byteOffset; 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 6a56a4de0..ea8ea4924 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java @@ -39,11 +39,8 @@ public class Variable implements Symbol { /** True of the variable is a compile-time constant (previously ConstantVar) [ALL] TODO: Eliminate (use Kind.CONSTANT) */ private boolean isConstant; - /** True if the variable is an array. */ - private boolean isArray; - - /** If the variable is a fixed size array this is the fixed size of the array. */ - private ConstantValue arraySize; + /** Non-null if teh variable is an array. */ + private ArraySpec arraySpec; /** The local name of the variable. [ALL] */ private String name; @@ -112,12 +109,12 @@ public class Variable implements Symbol { * @param dataSegment The data segment (in main memory) * @param value The constant value */ - public Variable(String name, Scope scope, SymbolType type, boolean isArray, String dataSegment, ConstantValue value) { + public Variable(String name, Scope scope, SymbolType type, ArraySpec arraySpec, String dataSegment, ConstantValue value) { this.isConstant = true; this.name = name; this.scope = scope; this.type = type; - this.isArray = isArray; + this.arraySpec = arraySpec; this.dataSegment = dataSegment; this.kind = Kind.CONSTANT; this.memoryArea = MemoryArea.MAIN_MEMORY; @@ -158,8 +155,7 @@ public class Variable implements Symbol { */ public Variable(Variable phiMaster, int version) { this(false, phiMaster.getName() + "#" + version, phiMaster.getScope(), phiMaster.getType(), Kind.PHI_VERSION, phiMaster.getMemoryArea(), phiMaster.getDataSegment()); - this.setArray(phiMaster.isArray()); - this.setArraySize(phiMaster.getArraySize()); + this.setArraySpec(phiMaster.getArraySpec()); this.setDeclaredAlignment(phiMaster.getDeclaredAlignment()); this.setDeclaredAsRegister(phiMaster.isDeclaredAsRegister()); this.setDeclaredConst(phiMaster.isDeclaredConst()); @@ -179,8 +175,7 @@ public class Variable implements Symbol { */ public Variable(String name, Scope scope, Variable original) { this(original.isConstant(), name, scope, original.getType(), original.getKind(), original.getMemoryArea(), original.getDataSegment()); - this.setArray(original.isArray()); - this.setArraySize(original.getArraySize()); + this.setArraySpec(original.getArraySpec()); this.setDeclaredAlignment(original.getDeclaredAlignment()); this.setDeclaredAsRegister(original.isDeclaredAsRegister()); this.setDeclaredConst(original.isDeclaredConst()); @@ -285,19 +280,15 @@ public class Variable implements Symbol { } public boolean isArray() { - return isArray; + return arraySpec!=null; } - public void setArray(boolean array) { - isArray = array; + public ArraySpec getArraySpec() { + return arraySpec; } - public ConstantValue getArraySize() { - return arraySize; - } - - public void setArraySize(ConstantValue arraySize) { - this.arraySize = arraySize; + public void setArraySpec(ArraySpec arraySpec) { + this.arraySpec = arraySpec; } public Registers.Register getAllocation() { diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java index de822865e..622bcca99 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java @@ -1,11 +1,11 @@ package dk.camelot64.kickc.model.types; +import dk.camelot64.kickc.model.symbols.ArraySpec; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.symbols.StructDefinition; import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; -import dk.camelot64.kickc.model.values.ConstantValue; import java.util.Objects; @@ -55,16 +55,16 @@ public class SymbolTypeStruct implements SymbolType { int sizeBytes = 0; for(Variable member : structDefinition.getAllVariables(false)) { SymbolType memberType = member.getType(); - int memberSize = getMemberSizeBytes(memberType, member.isArray(), member.getArraySize(), programScope); + int memberSize = getMemberSizeBytes(memberType, member.getArraySpec(), programScope); sizeBytes += memberSize; } return sizeBytes; } - public static int getMemberSizeBytes(SymbolType memberType, boolean isArray, ConstantValue memberArraySize, ProgramScope programScope) { - if(isArray && memberArraySize != null) { + public static int getMemberSizeBytes(SymbolType memberType, ArraySpec arraySpec, ProgramScope programScope) { + if(arraySpec!=null && arraySpec.getArraySize() != null) { if(programScope != null) { - ConstantLiteral sizeLiteral = memberArraySize.calculateLiteral(programScope); + ConstantLiteral sizeLiteral = arraySpec.getArraySize().calculateLiteral(programScope); if(sizeLiteral instanceof ConstantInteger) { return ((ConstantInteger) sizeLiteral).getInteger().intValue(); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 09e939d3f..f775da0ce 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -582,7 +582,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor allConstants = getScope().getAllConstants(true); for(Variable constantVar : allConstants) { SymbolType constantType = constantVar.getType(); - if(constantVar.isArray() && constantVar.getArraySize() != null) { - ConstantValue declaredSize = constantVar.getArraySize(); + if(constantVar.isArray() && constantVar.getArraySpec().getArraySize() != null) { + ConstantValue declaredSize = constantVar.getArraySpec().getArraySize(); ConstantLiteral declaredSizeVal = declaredSize.calculateLiteral(getScope()); if(!(declaredSizeVal instanceof ConstantInteger)) { throw new CompileError("Error! Array declared size is not integer " + constantType.toString()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index 184fa6966..1926bc504 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -9,10 +9,7 @@ import dk.camelot64.kickc.model.iterator.ProgramValueHandler; import dk.camelot64.kickc.model.iterator.ProgramValueIterator; import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.*; -import dk.camelot64.kickc.model.symbols.Procedure; -import dk.camelot64.kickc.model.symbols.ProgramScope; -import dk.camelot64.kickc.model.symbols.Scope; -import dk.camelot64.kickc.model.symbols.Variable; +import dk.camelot64.kickc.model.symbols.*; import dk.camelot64.kickc.model.types.*; import dk.camelot64.kickc.model.values.*; import dk.camelot64.kickc.passes.calcs.PassNCalcVariableReferenceInfos; @@ -488,7 +485,7 @@ public class Pass4CodeGeneration { ConstantValue constantValue = constantVar.getConstantValue(); if(constantValue instanceof ConstantArray || constantValue instanceof ConstantString) { AsmDataChunk asmDataChunk = new AsmDataChunk(); - addChunkData(asmDataChunk, constantValue, constantVar.getType(), constantVar.isArray(), constantVar.getArraySize(), scopeRef); + addChunkData(asmDataChunk, constantValue, constantVar.getType(), constantVar.getArraySpec(), scopeRef); asmDataChunk.addToAsm(AsmFormat.asmFix(asmName), asm); } else { throw new InternalError("Constant Variable not handled " + constantVar.toString(program)); @@ -531,7 +528,7 @@ public class Pass4CodeGeneration { asm.addDataAlignment(alignment); } AsmDataChunk asmDataChunk = new AsmDataChunk(); - addChunkData(asmDataChunk, ZeroConstantValues.zeroValue(variable.getType(), getScope()), variable.getType(), variable.isArray(), variable.getArraySize(), scopeRef); + addChunkData(asmDataChunk, ZeroConstantValues.zeroValue(variable.getType(), getScope()), variable.getType(), variable.getArraySpec(), scopeRef); asmDataChunk.addToAsm(AsmFormat.asmFix(variable.getAsmName()), asm); added.add(variable.getAsmName()); } @@ -566,20 +563,19 @@ public class Pass4CodeGeneration { * @param dataChunk The data chunk * @param value The constant value * @param valueType The declared type of the value - * @param valueArray true if the value is declared as an array - * @param valueArraySize the decalred size of the array value (if array with a declared size) + * @param valueArraySpec The array properties of the value * @param scopeRef The scope containing the data chunk */ - private void addChunkData(AsmDataChunk dataChunk, ConstantValue value, SymbolType valueType, boolean valueArray, ConstantValue valueArraySize, ScopeRef scopeRef) { + private void addChunkData(AsmDataChunk dataChunk, ConstantValue value, SymbolType valueType, ArraySpec valueArraySpec, ScopeRef scopeRef) { if(valueType instanceof SymbolTypeStruct) { // Add each struct member recursively ConstantStructValue structValue = (ConstantStructValue) value; for(SymbolVariableRef memberRef : structValue.getMembers()) { ConstantValue memberValue = structValue.getValue(memberRef); Variable memberVariable = getScope().getVariable(memberRef); - addChunkData(dataChunk, memberValue, memberVariable.getType(), memberVariable.isArray(), memberVariable.getArraySize(), scopeRef); + addChunkData(dataChunk, memberValue, memberVariable.getType(), memberVariable.getArraySpec(), scopeRef); } - } else if(valueType instanceof SymbolTypePointer && valueArray) { + } else if(valueType instanceof SymbolTypePointer && valueArraySpec!=null) { SymbolTypePointer constTypeArray = (SymbolTypePointer) valueType; SymbolType elementType = constTypeArray.getElementType(); @@ -612,7 +608,7 @@ public class Pass4CodeGeneration { ConstantArrayKickAsm kickAsm = (ConstantArrayKickAsm) value; // default - larger then 256 int bytes = 1023; - Integer declaredSize = getArrayDeclaredSize(valueArraySize); + Integer declaredSize = getArrayDeclaredSize(valueArraySpec.getArraySize()); if(declaredSize!=null) { bytes = declaredSize * elementType.getSizeBytes(); } @@ -638,13 +634,13 @@ public class Pass4CodeGeneration { ConstantArrayList constantArrayList = (ConstantArrayList) value; // Output each element to the chunk for(ConstantValue element : constantArrayList.getElements()) { - addChunkData(dataChunk, element, elementType, false, null, scopeRef); + addChunkData(dataChunk, element, elementType, null, scopeRef); } dataNumElements = constantArrayList.getElements().size(); } // Pad output to match declared size (if larger than the data list) if(!(value instanceof ConstantArrayKickAsm)) { - Integer declaredSize = getArrayDeclaredSize(valueArraySize); + Integer declaredSize = getArrayDeclaredSize(valueArraySpec.getArraySize()); if(declaredSize != null && declaredSize > dataNumElements) { int padding = declaredSize - dataNumElements; ConstantValue zeroValue = ZeroConstantValues.zeroValue(elementType, program.getScope()); @@ -652,7 +648,7 @@ public class Pass4CodeGeneration { dataChunk.addDataFilled(getNumericType(elementType), AsmFormat.getAsmNumber(padding), padding, AsmFormat.getAsmConstant(program, zeroValue, 99, scopeRef), getEncoding(zeroValue)); } else { for(int i = 0; i < padding; i++) { - addChunkData(dataChunk, zeroValue, elementType, false, null, scopeRef); + addChunkData(dataChunk, zeroValue, elementType, null, scopeRef); } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNSizeOfSimplification.java b/src/main/java/dk/camelot64/kickc/passes/PassNSizeOfSimplification.java index c447c1a57..00240ff07 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNSizeOfSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNSizeOfSimplification.java @@ -72,7 +72,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization { SymbolType symbolType = constant.getType(); if(constant.isArray() && symbolType instanceof SymbolTypePointer) { SymbolTypePointer arrayType = (SymbolTypePointer) symbolType; - RValue arraySize = constant.getArraySize(); + ConstantValue arraySize = constant.getArraySpec().getArraySize(); if(arraySize instanceof ConstantValue) { getLog().append("Resolving array sizeof() " + unary.toString(getProgram())); ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), arrayType.getElementType()); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNStructPointerRewriting.java b/src/main/java/dk/camelot64/kickc/passes/PassNStructPointerRewriting.java index 10b31925a..727521281 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNStructPointerRewriting.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNStructPointerRewriting.java @@ -40,7 +40,7 @@ public class PassNStructPointerRewriting extends Pass2SsaOptimization { SymbolType memberType = SymbolTypeInference.inferType(getScope(), structMemberRef); Variable memberVar = structDefinition.getMember(structMemberRef.getMemberName()); getLog().append("Rewriting struct pointer member access " + programValue.get().toString(getProgram())); - if(memberVar.isArray() && memberVar.getArraySize()!=null) { + if(memberVar.isArray() && memberVar.getArraySpec().getArraySize()!=null) { // Cast struct pointer to the type of the member CastValue structTypedPointer = new CastValue(memberType, structPointer); // Create temporary variable to hold pointer to member ($1) @@ -80,7 +80,7 @@ public class PassNStructPointerRewriting extends Pass2SsaOptimization { SymbolType memberType = SymbolTypeInference.inferType(getScope(), structMemberRef); Variable memberVar = structDefinition.getMember(structMemberRef.getMemberName()); getLog().append("Rewriting struct pointer member access " + programValue.get().toString(getProgram())); - if(memberVar.isArray() && memberVar.getArraySize()!=null) { + if(memberVar.isArray() && memberVar.getArraySpec().getArraySize()!=null) { // Cast struct pointer to the type of the member CastValue structTypedPointer = new CastValue(memberType, structPointer); // Create temporary variable to hold pointer to member ($1) @@ -133,7 +133,7 @@ public class PassNStructPointerRewriting extends Pass2SsaOptimization { // Constant not found - create it Variable memberDef = structDefinition.getMember(memberName); long memberByteOffset = structDefinition.getMemberByteOffset(memberDef, programScope); - memberOffsetConstant = new Variable(typeConstName, programScope, SymbolType.BYTE, false, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(memberByteOffset & 0xff, SymbolType.BYTE)); + memberOffsetConstant = new Variable(typeConstName, programScope, SymbolType.BYTE, null, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(memberByteOffset & 0xff, SymbolType.BYTE)); programScope.add(memberOffsetConstant); } return memberOffsetConstant.getConstantRef(); diff --git a/src/test/kc/unary-plus.kc b/src/test/kc/unary-plus.kc index bd86441a8..d4042c5a4 100644 --- a/src/test/kc/unary-plus.kc +++ b/src/test/kc/unary-plus.kc @@ -13,5 +13,4 @@ void main() { SCREEN2[0] = j; SCREEN2[1] = +3; - } \ No newline at end of file