fix the missing cases in certain expressions that need the address of a split word array

This commit is contained in:
Irmen de Jong
2024-12-25 16:07:09 +01:00
parent 0653d430a7
commit fe011de934
8 changed files with 70 additions and 76 deletions

View File

@@ -644,32 +644,6 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
val varname = asmgen.asmVariableName(fcall.args[0] as PtIdentifier) + if(msb) "+1" else ""
target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UBYTE), fcall.definingSub(), fcall.position, variableAsmName = varname)
}
is PtNumber -> {
val num = (fcall.args[0] as PtNumber).number + if(msb) 1 else 0
val mem = PtMemoryByte(fcall.position)
mem.add(PtNumber(BaseDataType.UBYTE, num, fcall.position))
target = AsmAssignTarget(TargetStorageKind.MEMORY, asmgen, DataType.forDt(BaseDataType.UBYTE), fcall.definingSub(), fcall.position, memory = mem)
}
is PtAddressOf -> {
val addrof = fcall.args[0] as PtAddressOf
if(addrof.identifier.type.isSplitWordArray) {
TODO("address of split word array")
} else {
val mem = PtMemoryByte(fcall.position)
if(addrof.isFromArrayElement)
TODO("address-of arrayelement")
if(msb) {
val address = PtBinaryExpression("+", DataType.forDt(BaseDataType.UWORD), addrof.position)
address.add(addrof)
address.add(PtNumber(address.type.base, 1.0, addrof.position))
mem.add(address)
} else {
mem.add(addrof)
}
target = AsmAssignTarget(TargetStorageKind.MEMORY, asmgen, DataType.forDt(BaseDataType.UBYTE), fcall.definingSub(), fcall.position, memory = mem)
}
}
is PtArrayIndexer -> {
val indexer = fcall.args[0] as PtArrayIndexer
val elementSize: Int

View File

@@ -808,11 +808,11 @@ _jump jmp (${target.asmLabel})
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY, true)
asmgen.out(" cpy #0")
} else {
var varname = asmgen.asmVariableName(value.identifier)
if(value.identifier.type.isSplitWordArray) {
TODO("address of split word array")
} else {
asmgen.out(" lda #>${asmgen.asmVariableName(value.identifier)}")
varname += if(value.isMsbForSplitArray) "_msb" else "_lsb"
}
asmgen.out(" lda #>$varname")
}
}
else -> {
@@ -1607,13 +1607,13 @@ _jump jmp (${target.asmLabel})
if(left.isFromArrayElement)
fallbackTranslateForSimpleCondition(stmt)
else {
if(left.identifier.type.isSplitWordArray) {
TODO("address of split word array")
val varname = if(left.identifier.type.isSplitWordArray) {
if(left.isMsbForSplitArray) left.identifier.name+"_msb" else left.identifier.name+"_lsb"
} else {
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
val varname = left.identifier.name
translateAYNotEquals("#<$varname", "#>$varname")
left.identifier.name
}
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
translateAYNotEquals("#<$varname", "#>$varname")
}
}
else -> {
@@ -1659,13 +1659,13 @@ _jump jmp (${target.asmLabel})
if(left.isFromArrayElement)
fallbackTranslateForSimpleCondition(stmt)
else {
if(left.identifier.type.isSplitWordArray) {
TODO("address of split word array")
val varname = if(left.identifier.type.isSplitWordArray) {
if(left.isMsbForSplitArray) left.identifier.name+"_msb" else left.identifier.name+"_lsb"
} else {
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
val varname = left.identifier.name
translateAYEquals("#<$varname", "#>$varname")
left.identifier.name
}
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
translateAYEquals("#<$varname", "#>$varname")
}
}
else -> {

View File

@@ -1341,13 +1341,12 @@ internal class AssignmentAsmGen(
when (right) {
is PtAddressOf -> {
val symbol = asmgen.asmVariableName(right.identifier)
var symbol = asmgen.asmVariableName(right.identifier)
if(right.isFromArrayElement) {
TODO("address-of array element $symbol at ${right.position}")
} else {
if(right.identifier.type.isSplitWordArray) {
TODO("address of split word array")
return true
symbol = if(right.isMsbForSplitArray) symbol+"_msb" else symbol+"_lsb"
}
assignExpressionToRegister(left, RegisterOrPair.AY, dt.isSigned)
if(expr.operator=="+")
@@ -2579,7 +2578,8 @@ $endLabel""")
private fun assignAddressOf(target: AsmAssignTarget, sourceName: String, arrayDt: DataType?, arrayIndexExpr: PtExpression?) {
if(arrayIndexExpr!=null) {
require(arrayDt?.isSplitWordArray!=true)
if(arrayDt?.isSplitWordArray==true)
TODO("address of element of a split word array")
val constIndex = arrayIndexExpr.asConstInteger()
if(constIndex!=null) {
if (arrayDt?.isUnsignedWord==true) {
@@ -2930,14 +2930,12 @@ $endLabel""")
storeRegisterAInMemoryAddress(target.memory!!)
}
TargetStorageKind.ARRAY -> {
if(target.array!!.splitWords)
TODO("assign into split words ${target.position}")
if (target.constArrayIndexValue!=null) {
val scaledIdx = program.memsizer.memorySize(target.datatype, target.constArrayIndexValue!!.toInt())
asmgen.out(" lda $sourceName | sta ${target.asmVarname}+$scaledIdx")
}
else {
asmgen.loadScaledArrayIndexIntoRegister(target.array, CpuRegister.Y)
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, CpuRegister.Y)
asmgen.out(" lda $sourceName | sta ${target.asmVarname},y")
}
}
@@ -2979,19 +2977,33 @@ $endLabel""")
""")
}
TargetStorageKind.ARRAY -> {
if(wordtarget.array!!.splitWords)
TODO("assign byte into split words ${wordtarget.position}")
if (wordtarget.constArrayIndexValue!=null) {
val scaledIdx = wordtarget.constArrayIndexValue!! * 2u
asmgen.out(" lda $sourceName")
asmgen.signExtendAYlsb(BaseDataType.BYTE)
asmgen.out(" sta ${wordtarget.asmVarname}+$scaledIdx | sty ${wordtarget.asmVarname}+$scaledIdx+1")
if(wordtarget.array!!.splitWords) {
// signed byte, we must sign-extend
if (wordtarget.constArrayIndexValue!=null) {
val scaledIdx = wordtarget.constArrayIndexValue!!
asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname}_lsb+$scaledIdx")
asmgen.signExtendAYlsb(BaseDataType.BYTE)
asmgen.out(" sty ${wordtarget.asmVarname}_msb+$scaledIdx")
}
else {
asmgen.loadScaledArrayIndexIntoRegister(wordtarget.array, CpuRegister.X)
asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname}_msb,x")
asmgen.signExtendAYlsb(BaseDataType.BYTE)
asmgen.out(" tya | sta ${wordtarget.asmVarname}_msb,x")
}
}
else {
asmgen.loadScaledArrayIndexIntoRegister(wordtarget.array, CpuRegister.X)
asmgen.out(" lda $sourceName")
asmgen.signExtendAYlsb(BaseDataType.BYTE)
asmgen.out(" sta ${wordtarget.asmVarname},x | inx | tya | sta ${wordtarget.asmVarname},x")
if (wordtarget.constArrayIndexValue != null) {
val scaledIdx = wordtarget.constArrayIndexValue!! * 2u
asmgen.out(" lda $sourceName")
asmgen.signExtendAYlsb(BaseDataType.BYTE)
asmgen.out(" sta ${wordtarget.asmVarname}+$scaledIdx | sty ${wordtarget.asmVarname}+$scaledIdx+1")
} else {
asmgen.loadScaledArrayIndexIntoRegister(wordtarget.array, CpuRegister.X)
asmgen.out(" lda $sourceName")
asmgen.signExtendAYlsb(BaseDataType.BYTE)
asmgen.out(" sta ${wordtarget.asmVarname},x | inx | tya | sta ${wordtarget.asmVarname},x")
}
}
}
TargetStorageKind.REGISTER -> {
@@ -3700,8 +3712,7 @@ $endLabel""")
storeRegisterAInMemoryAddress(target.memory!!)
}
TargetStorageKind.ARRAY -> {
if(target.array!!.splitWords)
TODO("assign into split words ${target.position}")
require(!target.array!!.splitWords)
if (target.constArrayIndexValue!=null) {
val indexValue = target.constArrayIndexValue!!
asmgen.out(" lda #${byte.toHex()} | sta ${target.asmVarname}+$indexValue")

View File

@@ -904,10 +904,10 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
}
return result
} else {
return null // TODO("inplace split word array +")
return null // TODO("inplace split word array -")
}
}
return null // TODO("inplace split word array +")
return null // TODO("inplace split word array -")
}
private fun operatorPlusInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks? {

View File

@@ -133,7 +133,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val result = mutableListOf<IRCodeChunkBase>()
val resultRegister = codeGen.registers.nextFree()
if(expr.isFromArrayElement) {
require(!expr.identifier.type.isSplitWordArray)
if(expr.identifier.type.isSplitWordArray)
TODO("address of element of a split word array")
addInstr(result, IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = symbol), null)
val indexTr2 = translateExpression(expr.arrayIndexExpr!!)
addToResult(result, indexTr2, indexTr2.resultReg, -1)

View File

@@ -703,7 +703,12 @@ internal class AstChecker(private val program: Program,
if (variable!=null) {
if (variable.type == VarDeclType.CONST && addressOf.arrayIndex == null)
errors.err("invalid pointer-of operand type",addressOf.position)
if(addressOf.arrayIndex!=null && variable.datatype.isSplitWordArray) {
errors.err("cannot take the adress of a word element that is in a split-word array", addressOf.position)
}
}
super.visit(addressOf)
}
@@ -1467,18 +1472,18 @@ internal class AstChecker(private val program: Program,
}
if(funcName[0] in InplaceModifyingBuiltinFunctions) {
// in-place modification, can't be done on literals
// in-place modification, can be done on specific types of arguments only (variables, array elements)
if(funcName[0]=="setlsb" || funcName[0]=="setmsb") {
val firstArg = functionCallStatement.args[0]
if(firstArg !is IdentifierReference && firstArg !is ArrayIndexedExpression)
errors.err("invalid argument to a in-place modifying function", firstArg.position)
errors.err("this function can only act on an identifier or array element", firstArg.position)
} else if(funcName[0]=="divmod" || funcName[0].startsWith("divmod__")) {
val thirdArg = functionCallStatement.args[2]
val fourthArg = functionCallStatement.args[3]
if(thirdArg !is IdentifierReference && thirdArg !is ArrayIndexedExpression)
errors.err("invalid argument to a in-place modifying function", thirdArg.position)
errors.err("this function can only act on an identifier or array element", thirdArg.position)
if(fourthArg !is IdentifierReference && fourthArg !is ArrayIndexedExpression)
errors.err("invalid argument to a in-place modifying function", fourthArg.position)
errors.err("this function can only act on an identifier or array element", fourthArg.position)
} else {
if(functionCallStatement.args.any { it !is IdentifierReference && it !is ArrayIndexedExpression && it !is DirectMemoryRead })
errors.err("invalid argument to a in-place modifying function", functionCallStatement.args.first().position)

View File

@@ -10,6 +10,9 @@ TODO
Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^
- support &, &< and &> on array elements from split word arrays too not just the array as a whole (to get rid of the error "&< is only valid on array variables"
and "cannot take the adress of a word element that is in a split-word array" and the TODOS "address of element of a split word array")
- fix leftover asmgen split word array todo's
- Kotlin: can we use inline value classes in certain spots?
- Improve the SublimeText syntax file for prog8, you can also install this for 'bat': https://github.com/sharkdp/bat?tab=readme-ov-file#adding-new-syntaxes--language-definitions
@@ -28,7 +31,6 @@ Future Things and Ideas
- Allow normal subroutines to return multiple values as well (just as asmsubs already can)
- Change scoping rules for qualified symbols so that they don't always start from the root but behave like other programming languages (look in local scope first)
- Fix missing cases where regular & has to return the start of the split array in memory whatever byte comes first. Search TODO("address of split word array")
- something to reduce the need to use fully qualified names all the time. 'with' ? Or 'using <prefix>'?
- Improve register load order in subroutine call args assignments:
in certain situations (need examples!), the "wrong" order of evaluation of function call arguments is done which results
@@ -47,6 +49,8 @@ Future Things and Ideas
IR/VM
-----
- fix TODO("IR rol/ror on split words array")
- fix "<< in array" / ">> in array"
- implement missing operators in AssignmentGen (array shifts etc)
- support %align on code chunks
- fix call() return value handling

View File

@@ -5,18 +5,17 @@
main {
sub start() {
&ubyte mmvar = $2000
uword[2] array1
txt.print_ub(@($2000))
array1[1] = $0122
txt.print_uwhex(array1[1], true)
txt.nl()
@($2000) = 123
txt.print_ub(@($2000))
rol(array1[1])
txt.print_uwhex(array1[1], true)
txt.nl()
mmvar = 42
txt.print_ub(@($2000))
sys.set_carry()
ror(array1[1])
txt.print_uwhex(array1[1], true)
txt.nl()
cx16.r0 = 123
}
}