diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmDataChunk.java b/src/main/java/dk/camelot64/kickc/asm/AsmDataChunk.java index f61386b21..4a00d8d98 100644 --- a/src/main/java/dk/camelot64/kickc/asm/AsmDataChunk.java +++ b/src/main/java/dk/camelot64/kickc/asm/AsmDataChunk.java @@ -44,21 +44,21 @@ public class AsmDataChunk { /** A number of identical numerical data elements. */ public static class AsmDataFilledElement implements AsmDataElement { + /** The ASM specifying how the total size in bytes - in ASM-format. */ + String totalSizeBytesAsm; /** The type of the element */ AsmDataNumeric.Type type; - /** The ASM specifying how many elements to fill. */ - String sizeAsm; /** The literal integer number of elements. */ - int size; + int numElements; /** The fill value. */ String fillValue; /** The string encoding used in any char/string value */ Set encoding; - AsmDataFilledElement(AsmDataNumeric.Type type, String sizeAsm, int size, String fillValue, Set encoding) { + AsmDataFilledElement(AsmDataNumeric.Type type, String totalSizeBytesAsm, int numElements, String fillValue, Set encoding) { this.type = type; - this.sizeAsm = sizeAsm; - this.size = size; + this.totalSizeBytesAsm = totalSizeBytesAsm; + this.numElements = numElements; this.fillValue = fillValue; this.encoding = encoding; } @@ -67,12 +67,12 @@ public class AsmDataChunk { return type; } - String getSizeAsm() { - return sizeAsm; + String getTotalSizeBytesAsm() { + return totalSizeBytesAsm; } - public int getSize() { - return size; + public int getNumElements() { + return numElements; } String getFillValue() { @@ -116,8 +116,8 @@ public class AsmDataChunk { elements.add(new AsmDataNumericElement(type, value, encoding)); } - public void addDataFilled(AsmDataNumeric.Type type, String sizeAsm, int size, String fillValue, Set encoding) { - elements.add(new AsmDataFilledElement(type, sizeAsm, size, fillValue, encoding)); + public void addDataFilled(AsmDataNumeric.Type type, String totalSizeBytesAsm, int numElements, String fillValue, Set encoding) { + elements.add(new AsmDataFilledElement(type, totalSizeBytesAsm, numElements, fillValue, encoding)); } public void addDataString(String string, Set encoding) { @@ -148,7 +148,7 @@ public class AsmDataChunk { } AsmDataFilledElement filledElement = (AsmDataFilledElement) element; asm.ensureEncoding(filledElement.getEncoding()); - asm.addDataFilled(label, filledElement.getType(), filledElement.getSizeAsm(), filledElement.getSize(), filledElement.getFillValue()); + asm.addDataFilled(label, filledElement.getType(), filledElement.getTotalSizeBytesAsm(), filledElement.getNumElements(), filledElement.getFillValue()); label = null; // Only output label once } else if(element instanceof AsmDataStringElement) { if(currentNumericElements!=null && currentNumericElements.size() > 0) { diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmDataFill.java b/src/main/java/dk/camelot64/kickc/asm/AsmDataFill.java index a90f335cd..752cfffc8 100644 --- a/src/main/java/dk/camelot64/kickc/asm/AsmDataFill.java +++ b/src/main/java/dk/camelot64/kickc/asm/AsmDataFill.java @@ -4,18 +4,23 @@ package dk.camelot64.kickc.asm; public class AsmDataFill implements AsmLine { private String label; + /** The calculation of the total number of bytes in ASM-format */ + private String totalByteSizeAsm; + /** The type of value being filled with. */ private AsmDataNumeric.Type type; - private String sizeAsm; - private int size; + /** The number of elements*/ + private int numElements; + /** The value to fill with in ASM-format */ private String fillValue; + private int index; - public AsmDataFill(String label, AsmDataNumeric.Type type, String sizeAsm, int size, String fillValue) { + public AsmDataFill(String label, AsmDataNumeric.Type type, String totalByteSizeAsm, int numElements, String fillValue) { this.label = label; this.type = type; - this.sizeAsm = sizeAsm; - this.size = size; + this.totalByteSizeAsm = totalByteSizeAsm; + this.numElements = numElements; this.fillValue = fillValue; } @@ -25,7 +30,7 @@ public class AsmDataFill implements AsmLine { @Override public int getLineBytes() { - return size * getElementBytes(); + return numElements * getElementBytes(); } @Override @@ -40,7 +45,7 @@ public class AsmDataFill implements AsmLine { asm.append(label + ": "); } asm.append(".fill "); - asm.append(sizeAsm); + asm.append(totalByteSizeAsm); asm.append(", "); asm.append(fillValue); return asm.toString(); diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmProgram.java b/src/main/java/dk/camelot64/kickc/asm/AsmProgram.java index 7a91b3a59..4b39dc6a9 100644 --- a/src/main/java/dk/camelot64/kickc/asm/AsmProgram.java +++ b/src/main/java/dk/camelot64/kickc/asm/AsmProgram.java @@ -139,10 +139,10 @@ public class AsmProgram { * * @param label The label of the data * @param type The type of the data - * @param size The size of data to fill + * @param numElements The size of data to fill */ - public void addDataFilled(String label, AsmDataNumeric.Type type, String sizeAsm, int size, String fillValue) { - addLine(new AsmDataFill(label, type, sizeAsm, size, fillValue)); + public void addDataFilled(String label, AsmDataNumeric.Type type, String totalSizeBytesAsm, int numElements, String fillValue) { + addLine(new AsmDataFill(label, type, totalSizeBytesAsm, numElements, fillValue)); } /** diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index 5a629ab48..91c23a274 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -456,51 +456,9 @@ public class Pass4CodeGeneration { addChunkData(asmDataChunk, constantValue, constantVar.getType(), scopeRef); asmDataChunk.addToAsm(asmName, asm); } else if(constantValue instanceof ConstantArrayFilled) { - ConstantArrayFilled constantArrayFilled = (ConstantArrayFilled) constantValue; - ConstantValue arraySize = constantArrayFilled.getSize(); - // ensure encoding is good - ensureEncoding(asm, arraySize); - ConstantLiteral arraySizeConst = arraySize.calculateLiteral(getScope()); - if(!(arraySizeConst instanceof ConstantInteger)) { - throw new Pass2SsaAssertion.AssertionFailed("Error! Array size is not constant integer " + constantVar.toString(program)); - } - int size = ((ConstantInteger) arraySizeConst).getInteger().intValue(); - if(SymbolType.BYTE.equals(constantArrayFilled.getElementType())) { - String asmSize = AsmFormat.getAsmConstant(program, arraySize, 99, scopeRef); - asm.addDataFilled(AsmFormat.asmFix(asmName), AsmDataNumeric.Type.BYTE, asmSize, size, "0"); - added.add(asmName); - } else if(SymbolType.SBYTE.equals(constantArrayFilled.getElementType())) { - String asmSize = AsmFormat.getAsmConstant(program, arraySize, 99, scopeRef); - asm.addDataFilled(AsmFormat.asmFix(asmName), AsmDataNumeric.Type.BYTE, asmSize, size, "0"); - added.add(asmName); - } else if(SymbolType.WORD.equals(constantArrayFilled.getElementType())) { - String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(2L), Operators.MULTIPLY, arraySize), 99, scopeRef); - asm.addDataFilled(AsmFormat.asmFix(asmName), AsmDataNumeric.Type.WORD, asmSize, size, "0"); - added.add(asmName); - } else if(SymbolType.SWORD.equals(constantArrayFilled.getElementType())) { - String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(2L), Operators.MULTIPLY, arraySize), 99, scopeRef); - asm.addDataFilled(AsmFormat.asmFix(asmName), AsmDataNumeric.Type.WORD, asmSize, size, "0"); - added.add(asmName); - } else if(SymbolType.DWORD.equals(constantArrayFilled.getElementType())) { - String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(4L), Operators.MULTIPLY, arraySize), 99, scopeRef); - asm.addDataFilled(AsmFormat.asmFix(asmName), AsmDataNumeric.Type.DWORD, asmSize, size, "0"); - added.add(asmName); - } else if(SymbolType.SDWORD.equals(constantArrayFilled.getElementType())) { - String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(4L), Operators.MULTIPLY, arraySize), 99, scopeRef); - asm.addDataFilled(AsmFormat.asmFix(asmName), AsmDataNumeric.Type.DWORD, asmSize, size, "0"); - added.add(asmName); - } else if(constantArrayFilled.getElementType() instanceof SymbolTypePointer) { - String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(2L), Operators.MULTIPLY, arraySize), 99, scopeRef); - asm.addDataFilled(AsmFormat.asmFix(asmName), AsmDataNumeric.Type.WORD, asmSize, size, "0"); - added.add(asmName); - } else if(constantArrayFilled.getElementType() instanceof SymbolTypeStruct) { - SymbolTypeStruct structElementType = (SymbolTypeStruct) constantArrayFilled.getElementType(); - String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) structElementType.getSizeBytes()), Operators.MULTIPLY, arraySize), 99, scopeRef); - asm.addDataFilled(AsmFormat.asmFix(asmName), AsmDataNumeric.Type.WORD, asmSize, size, "0"); - added.add(asmName); - } else { - throw new InternalError("Unhandled constant array element type " + constantArrayFilled.toString(program)); - } + AsmDataChunk asmDataChunk = new AsmDataChunk(); + addChunkData(asmDataChunk, constantValue, constantVar.getType(), scopeRef); + asmDataChunk.addToAsm(asmName, asm); } else if(constantValue instanceof ConstantArrayKickAsm) { ConstantArrayKickAsm kickAsm = (ConstantArrayKickAsm) constantValue; SymbolType type = constantVar.getType(); @@ -602,8 +560,31 @@ public class Pass4CodeGeneration { SymbolType elementType = constTypeArray.getElementType(); SymbolType dataType = value.getType(program.getScope()); - int dataSize = 0; - if(dataType.equals(SymbolType.STRING)) { + int dataNumElements = 0; + if(value instanceof ConstantArrayFilled) { + ConstantArrayFilled constantArrayFilled = (ConstantArrayFilled) value; + ConstantValue arraySize = constantArrayFilled.getSize(); + ConstantLiteral arraySizeConst = arraySize.calculateLiteral(getScope()); + if(!(arraySizeConst instanceof ConstantInteger)) { + throw new Pass2SsaAssertion.AssertionFailed("Error! Array size is not constant integer " + arraySize.toString(program)); + } + dataNumElements = ((ConstantInteger) arraySizeConst).getInteger().intValue(); + int elementSizeBytes = elementType.getSizeBytes(); + String totalSizeBytesAsm; + if(elementSizeBytes>1) { + totalSizeBytesAsm = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger((long)elementSizeBytes, SymbolType.NUMBER), Operators.MULTIPLY, arraySize), 99, scopeRef); + } else { + totalSizeBytesAsm = AsmFormat.getAsmConstant(program, arraySize, 99, scopeRef); + } + if(elementType instanceof SymbolTypeIntegerFixed || elementType instanceof SymbolTypePointer) { + // Use an ASM type in the fill that matches the element type + dataChunk.addDataFilled(getNumericType(elementType), totalSizeBytesAsm, dataNumElements, "0", null); + } else { + // Complex fill type - calculate byte size and use that + int totalSizeBytes = elementSizeBytes*dataNumElements; + dataChunk.addDataFilled(AsmDataNumeric.Type.BYTE, totalSizeBytesAsm, totalSizeBytes, "0", null); + } + } else if(dataType.equals(SymbolType.STRING)) { try { ConstantLiteral literal = value.calculateLiteral(getScope()); if(literal instanceof ConstantString) { @@ -613,23 +594,24 @@ public class Pass4CodeGeneration { if(((ConstantString) literal).isZeroTerminated()) { dataChunk.addDataNumeric(AsmDataNumeric.Type.BYTE, "0", null); } - dataSize = ((ConstantString) literal).getStringLength(); + dataNumElements = ((ConstantString) literal).getStringLength(); } } catch(ConstantNotLiteral e) { // can't calculate literal value, so it is not data - just return } - } else { + } else { + // Assume we have a ConstantArrayList ConstantArrayList constantArrayList = (ConstantArrayList) value; // Output each element to the chunk for(ConstantValue element : constantArrayList.getElements()) { addChunkData(dataChunk, element, elementType, scopeRef); } - dataSize = constantArrayList.getElements().size(); + dataNumElements = constantArrayList.getElements().size(); } // Pad output to match declared size (if larger than the data list) Integer declaredSize = getArrayDeclaredSize(valueType); - if(declaredSize != null && declaredSize > dataSize) { - int padding = declaredSize - dataSize; + if(declaredSize != null && declaredSize > dataNumElements) { + int padding = declaredSize - dataNumElements; ConstantValue zeroValue = ZeroConstantValues.zeroValue(elementType, program.getScope()); if(zeroValue instanceof ConstantInteger) { dataChunk.addDataFilled(getNumericType(elementType), AsmFormat.getAsmNumber(padding), padding, AsmFormat.getAsmConstant(program, zeroValue, 99, scopeRef), getEncoding(zeroValue));