This commit is contained in:
Irmen de Jong
2024-12-19 21:05:49 +01:00
parent b01555d75e
commit ef4efcb112
13 changed files with 25 additions and 142 deletions

View File

@@ -99,7 +99,7 @@ class PtInlineAssembly(val assembly: String, val isIR: Boolean, position: Positi
class PtLabel(name: String, position: Position) : PtNamedNode(name, position) { class PtLabel(name: String, position: Position) : PtNamedNode(name, position) {
companion object { companion object {
// all automatically generated labels everywhere need to have the same label name prefix: // all automatically generated labels everywhere need to have the same label name prefix:
const val GeneratedLabelPrefix = "p8_label_gen_" const val GENERATED_LABEL_PREFIX = "p8_label_gen_"
} }
} }

View File

@@ -36,7 +36,7 @@ class AsmGen6502(val prefixSymbols: Boolean, private val lastGeneratedLabelSeque
when(node) { when(node) {
is PtAsmSub, is PtSub -> node.name = "p8s_${node.name}" is PtAsmSub, is PtSub -> node.name = "p8s_${node.name}"
is PtBlock -> node.name = "p8b_${node.name}" is PtBlock -> node.name = "p8b_${node.name}"
is PtLabel -> if(!node.name.startsWith(PtLabel.GeneratedLabelPrefix)) node.name = "p8l_${node.name}" // don't prefix autogenerated labels is PtLabel -> if(!node.name.startsWith(PtLabel.GENERATED_LABEL_PREFIX)) node.name = "p8l_${node.name}" // don't prefix autogenerated labels
is PtConstant -> node.name = "p8c_${node.name}" is PtConstant -> node.name = "p8c_${node.name}"
is PtVariable, is PtMemMapped, is PtSubroutineParameter -> node.name = "p8v_${node.name}" is PtVariable, is PtMemMapped, is PtSubroutineParameter -> node.name = "p8v_${node.name}"
} }
@@ -118,14 +118,14 @@ class AsmGen6502(val prefixSymbols: Boolean, private val lastGeneratedLabelSeque
private fun prefixScopedName(name: String, type: Char): String { private fun prefixScopedName(name: String, type: Char): String {
if('.' !in name) { if('.' !in name) {
if(name.startsWith(PtLabel.GeneratedLabelPrefix)) if(name.startsWith(PtLabel.GENERATED_LABEL_PREFIX))
return name return name
return "p8${type}_$name" return "p8${type}_$name"
} }
val parts = name.split('.') val parts = name.split('.')
val firstPrefixed = "p8b_${parts[0]}" val firstPrefixed = "p8b_${parts[0]}"
val lastPart = parts.last() val lastPart = parts.last()
val lastPrefixed = if(lastPart.startsWith(PtLabel.GeneratedLabelPrefix)) lastPart else "p8${type}_$lastPart" val lastPrefixed = if(lastPart.startsWith(PtLabel.GENERATED_LABEL_PREFIX)) lastPart else "p8${type}_$lastPart"
// the parts in between are assumed to be subroutine scopes. // the parts in between are assumed to be subroutine scopes.
val inbetweenPrefixed = parts.drop(1).dropLast(1).map{ "p8s_$it" } val inbetweenPrefixed = parts.drop(1).dropLast(1).map{ "p8s_$it" }
val prefixed = listOf(firstPrefixed) + inbetweenPrefixed + listOf(lastPrefixed) val prefixed = listOf(firstPrefixed) + inbetweenPrefixed + listOf(lastPrefixed)
@@ -1369,7 +1369,7 @@ $repeatLabel""")
internal fun makeLabel(postfix: String): String { internal fun makeLabel(postfix: String): String {
generatedLabelSequenceNumber++ generatedLabelSequenceNumber++
return "${PtLabel.GeneratedLabelPrefix}${generatedLabelSequenceNumber}_$postfix" return "${PtLabel.GENERATED_LABEL_PREFIX}${generatedLabelSequenceNumber}_$postfix"
} }
internal fun assignConstFloatToPointerAY(number: PtNumber) { internal fun assignConstFloatToPointerAY(number: PtNumber) {

View File

@@ -362,7 +362,7 @@ or *_afterif labels.
This gets generated after certain if conditions, and only the branch instruction is needed in these cases. This gets generated after certain if conditions, and only the branch instruction is needed in these cases.
*/ */
val autoLabelPrefix = PtLabel.GeneratedLabelPrefix val autoLabelPrefix = PtLabel.GENERATED_LABEL_PREFIX
if(first=="beq +" && second=="lda #1" && third=="+") { if(first=="beq +" && second=="lda #1" && third=="+") {
if((fourth.startsWith("beq $autoLabelPrefix") || fourth.startsWith("bne $autoLabelPrefix")) && if((fourth.startsWith("beq $autoLabelPrefix") || fourth.startsWith("bne $autoLabelPrefix")) &&
(fourth.endsWith("_shortcut") || fourth.endsWith("_afterif") || fourth.endsWith("_shortcut:") || fourth.endsWith("_afterif:"))) { (fourth.endsWith("_shortcut") || fourth.endsWith("_afterif") || fourth.endsWith("_shortcut:") || fourth.endsWith("_afterif:"))) {

View File

@@ -148,7 +148,7 @@ internal class AssemblyProgram(
} }
private fun removeGeneratedLabelsFromMonlist() { private fun removeGeneratedLabelsFromMonlist() {
val pattern = Regex("""al (\w+) \S+${PtLabel.GeneratedLabelPrefix}.+?""") val pattern = Regex("""al (\w+) \S+${PtLabel.GENERATED_LABEL_PREFIX}.+?""")
val lines = viceMonListFile.toFile().readLines() val lines = viceMonListFile.toFile().readLines()
viceMonListFile.toFile().outputStream().bufferedWriter().use { viceMonListFile.toFile().outputStream().bufferedWriter().use {
for (line in lines) { for (line in lines) {

View File

@@ -1799,7 +1799,7 @@ class IRCodeGen(
private var labelSequenceNumber = 0 private var labelSequenceNumber = 0
internal fun createLabelName(): String { internal fun createLabelName(): String {
labelSequenceNumber++ labelSequenceNumber++
return "${PtLabel.GeneratedLabelPrefix}$labelSequenceNumber" return "${PtLabel.GENERATED_LABEL_PREFIX}$labelSequenceNumber"
} }
internal fun translateBuiltinFunc(call: PtBuiltinFunctionCall): ExpressionCodeResult internal fun translateBuiltinFunc(call: PtBuiltinFunctionCall): ExpressionCodeResult

View File

@@ -317,23 +317,6 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
return noModifications return noModifications
} }
fun checkArray(variable: VarDecl): Iterable<IAstModification> {
return when (variable.value) {
null -> {
val arraySpec = variable.arraysize!!
val size = arraySpec.indexExpr.constValue(program)?.number?.toInt() ?: throw FatalAstException("no array size")
return if(size==0)
replaceWithFalse()
else
noModifications
}
is ArrayLiteral -> {
checkArray((variable.value as ArrayLiteral).value)
}
else -> noModifications
}
}
fun checkString(stringVal: StringLiteral): Iterable<IAstModification> { fun checkString(stringVal: StringLiteral): Iterable<IAstModification> {
if(stringVal.value.isEmpty()) if(stringVal.value.isEmpty())
return replaceWithFalse() return replaceWithFalse()

View File

@@ -151,7 +151,7 @@ class Program(val name: String,
fun makeLabel(postfix: String): String { fun makeLabel(postfix: String): String {
generatedLabelSequenceNumber++ generatedLabelSequenceNumber++
return "${PtLabel.GeneratedLabelPrefix}${generatedLabelSequenceNumber}_$postfix" return "${PtLabel.GENERATED_LABEL_PREFIX}${generatedLabelSequenceNumber}_$postfix"
} }
fun makeLabel(postfix: String, position: Position): Label { fun makeLabel(postfix: String, position: Position): Label {

View File

@@ -594,13 +594,13 @@ private fun ExpressionContext.toAst(insideParentheses: Boolean=false) : Expressi
val identifier = addressOf.scoped_identifier() val identifier = addressOf.scoped_identifier()
if(addressOf.ADDRESS_OF_LSB()!=null && identifier==null) if(addressOf.ADDRESS_OF_LSB()!=null && identifier==null)
throw SyntaxError("&< is only valid on array variables", toPosition()) throw SyntaxError("&< is only valid on array variables", toPosition())
if(addressOf.ADDRESS_OF_MSB()!=null) { return if(addressOf.ADDRESS_OF_MSB()!=null) {
return if (identifier != null) if (identifier != null)
AddressOfMsb(addressof().scoped_identifier().toAst(), toPosition()) AddressOfMsb(addressof().scoped_identifier().toAst(), toPosition())
else else
throw SyntaxError("&> is only valid on array variables", toPosition()) throw SyntaxError("&> is only valid on array variables", toPosition())
} else { } else {
return if (identifier != null) if (identifier != null)
AddressOf(addressof().scoped_identifier().toAst(), null, toPosition()) AddressOf(addressof().scoped_identifier().toAst(), null, toPosition())
else { else {
val array = addressOf.arrayindexed() val array = addressOf.arrayindexed()

View File

@@ -106,11 +106,11 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid
constval.type == BaseDataType.FLOAT -> NumericLiteral(BaseDataType.FLOAT, -constval.number, constval.position) constval.type == BaseDataType.FLOAT -> NumericLiteral(BaseDataType.FLOAT, -constval.number, constval.position)
else -> throw ExpressionError("can only take negative of int or float", constval.position) else -> throw ExpressionError("can only take negative of int or float", constval.position)
} }
"~" -> when { "~" -> when (constval.type) {
constval.type == BaseDataType.BYTE -> NumericLiteral(BaseDataType.BYTE, constval.number.toInt().inv().toDouble(), constval.position) BaseDataType.BYTE -> NumericLiteral(BaseDataType.BYTE, constval.number.toInt().inv().toDouble(), constval.position)
constval.type == BaseDataType.UBYTE -> NumericLiteral(BaseDataType.UBYTE, (constval.number.toInt().inv() and 255).toDouble(), constval.position) BaseDataType.UBYTE -> NumericLiteral(BaseDataType.UBYTE, (constval.number.toInt().inv() and 255).toDouble(), constval.position)
constval.type == BaseDataType.WORD -> NumericLiteral(BaseDataType.WORD, constval.number.toInt().inv().toDouble(), constval.position) BaseDataType.WORD -> NumericLiteral(BaseDataType.WORD, constval.number.toInt().inv().toDouble(), constval.position)
constval.type == BaseDataType.UWORD -> NumericLiteral(BaseDataType.UWORD, (constval.number.toInt().inv() and 65535).toDouble(), constval.position) BaseDataType.UWORD -> NumericLiteral(BaseDataType.UWORD, (constval.number.toInt().inv() and 65535).toDouble(), constval.position)
else -> throw ExpressionError("can only take bitwise inversion of int", constval.position) else -> throw ExpressionError("can only take bitwise inversion of int", constval.position)
} }
"not" -> NumericLiteral.fromBoolean(constval.number==0.0, constval.position) "not" -> NumericLiteral.fromBoolean(constval.number==0.0, constval.position)

View File

@@ -24,9 +24,6 @@ Future Things and Ideas
Need to add some way to generate a stable jump table at a given address. Need to add some way to generate a stable jump table at a given address.
Need library to not call init_system AND init_system_phase2 not either. Need library to not call init_system AND init_system_phase2 not either.
Library must not include prog8_program_start stuff either. Library must not include prog8_program_start stuff either.
- Add a LZSA decompressor to the compression library to be able to decompress lzsa when you don't have it in ROM or when the ROM is banked out or unavailable
Problem is: on the X16, it should replicate the Kernal's behavior with decompressing to Vram / not incrementing the output address
- Add TSCrunch or ZX0 decruncher to compression lib. Same requirement on X16 again to be able to decompress into vram.
- 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") - 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")
- Add a syntax to access specific bits in a variable, to avoid manually shifts&ands, something like variable[4:8] ? (or something else this may be too similar to regular array indexing) - Add a syntax to access specific bits in a variable, to avoid manually shifts&ands, something like variable[4:8] ? (or something else this may be too similar to regular array indexing)
- something to reduce the need to use fully qualified names all the time. 'with' ? Or 'using <prefix>'? - something to reduce the need to use fully qualified names all the time. 'with' ? Or 'using <prefix>'?
@@ -75,6 +72,9 @@ IR/VM
Libraries Libraries
--------- ---------
- monogfx: flood fill should be able to fill stippled - monogfx: flood fill should be able to fill stippled
- Add a LZSA decompressor to the compression library to be able to decompress lzsa when you don't have it in ROM or when the ROM is banked out or unavailable
Problem is: on the X16, it should replicate the Kernal's behavior with decompressing to Vram / not incrementing the output address
- Add TSCrunch or ZX0 decruncher to compression lib. Same requirement on X16 again to be able to decompress into vram.
- pet32 target: make syslib more complete (missing kernal routines)? - pet32 target: make syslib more complete (missing kernal routines)?
- need help with: PET disk routines (OPEN, SETLFS etc are not exposed as kernal calls) - need help with: PET disk routines (OPEN, SETLFS etc are not exposed as kernal calls)
- fix the problems in atari target, and flesh out its libraries. - fix the problems in atari target, and flesh out its libraries.

View File

@@ -423,7 +423,7 @@ object SysCalls {
returnValue(callspec.returns.single(), result, vm) returnValue(callspec.returns.single(), result, vm)
} }
Syscall.MUL16_LAST_UPPER -> { Syscall.MUL16_LAST_UPPER -> {
returnValue(callspec.returns.single(), vm.mul16_last_upper, vm) returnValue(callspec.returns.single(), vm.mul16LastUpper, vm)
} }
Syscall.FLOAT_TO_STR -> { Syscall.FLOAT_TO_STR -> {
val (buffer, number) = getArgValues(callspec.arguments, vm) val (buffer, number) = getArgValues(callspec.arguments, vm)

View File

@@ -58,7 +58,7 @@ class VirtualMachine(irProgram: IRProgram) {
var statusNegative = false var statusNegative = false
internal var randomGenerator = Random(0xa55a7653) internal var randomGenerator = Random(0xa55a7653)
internal var randomGeneratorFloats = Random(0xc0d3dbad) internal var randomGeneratorFloats = Random(0xc0d3dbad)
internal var mul16_last_upper = 0u internal var mul16LastUpper = 0u
init { init {
val (prg, labelAddr) = VmProgramLoader().load(irProgram, memory) val (prg, labelAddr) = VmProgramLoader().load(irProgram, memory)
@@ -1593,7 +1593,7 @@ class VirtualMachine(irProgram: IRProgram) {
"-" -> result = left - right "-" -> result = left - right
"*" -> { "*" -> {
result = left.toUInt() * right result = left.toUInt() * right
mul16_last_upper = result shr 16 mul16LastUpper = result shr 16
} }
else -> throw IllegalArgumentException("operator word $operator") else -> throw IllegalArgumentException("operator word $operator")
} }
@@ -1608,7 +1608,7 @@ class VirtualMachine(irProgram: IRProgram) {
"-" -> result = left - value "-" -> result = left - value
"*" -> { "*" -> {
result = left.toUInt() * value result = left.toUInt() * value
mul16_last_upper = result shr 16 mul16LastUpper = result shr 16
} }
else -> throw IllegalArgumentException("operator word $operator") else -> throw IllegalArgumentException("operator word $operator")
} }
@@ -1624,7 +1624,7 @@ class VirtualMachine(irProgram: IRProgram) {
"-" -> result = memvalue - operand "-" -> result = memvalue - operand
"*" -> { "*" -> {
result = memvalue.toUInt() * operand result = memvalue.toUInt() * operand
mul16_last_upper = result shr 16 mul16LastUpper = result shr 16
} }
else -> throw IllegalArgumentException("operator word $operator") else -> throw IllegalArgumentException("operator word $operator")
} }

View File

@@ -338,106 +338,6 @@ class VmProgramLoader {
} }
} }
private fun initializeWithOneValue(
variable: IRStStaticVariable,
iElt: IRStArrayElement,
startAddress: Int,
symbolAddresses: MutableMap<String, Int>,
memory: Memory,
program: IRProgram
) {
var address = startAddress
when {
variable.dt.isString || variable.dt.isUnsignedByteArray -> {
val value = getInitializerValue(variable.dt, iElt, symbolAddresses)
value.fold(
{
val integer = it.toInt().toUByte()
repeat(variable.length!!) {
memory.setUB(address, integer)
address++
}
},
{ throw IRParseException("didn't expect bool") }
)
}
variable.dt.isSignedByteArray -> {
val value = getInitializerValue(variable.dt, iElt, symbolAddresses)
value.fold(
{
val integer = it.toInt().toByte()
repeat(variable.length!!) {
memory.setSB(address, integer)
address++
}
},
{ throw IRParseException("didn't expect bool") },
)
}
variable.dt.isSplitWordArray -> {
val value = getInitializerValue(variable.dt, iElt, symbolAddresses)
value.fold(
{
val integer = it.toUInt()
val lsb = (integer and 255u).toUByte()
val msb = (integer shr 8).toUByte()
repeat(variable.length!!) {
memory.setUB(address, lsb)
memory.setUB(address + variable.length!!, msb)
address++
}
},
{ throw IRParseException("didn't expect bool") }
)
}
variable.dt.isUnsignedWordArray -> {
val value = getInitializerValue(variable.dt, iElt, symbolAddresses)
value.fold(
{
val integer = it.toInt().toUShort()
repeat(variable.length!!) {
memory.setUW(address, integer)
address += 2
}
},
{ throw IRParseException("didn't expect bool") }
)
}
variable.dt.isSignedWordArray -> {
val value = getInitializerValue(variable.dt, iElt, symbolAddresses)
value.fold(
{
val integer = it.toInt().toShort()
repeat(variable.length!!) {
memory.setSW(address, integer)
address += 2
}
},
{ throw IRParseException("didn't expect bool") }
)
}
variable.dt.isFloatArray -> {
val value = getInitializerValue(variable.dt, iElt, symbolAddresses)
value.fold(
{ d ->
repeat(variable.length!!) {
memory.setFloat(address, d)
address += program.options.compTarget.machine.FLOAT_MEM_SIZE
}
},
{ throw IRParseException("didn't expect bool") }
)
}
else -> throw IRParseException("invalid dt")
}
}
private fun getInitializerValue(arrayDt: DataType, elt: IRStArrayElement, symbolAddresses: MutableMap<String, Int>): Either<Double, Boolean> { private fun getInitializerValue(arrayDt: DataType, elt: IRStArrayElement, symbolAddresses: MutableMap<String, Int>): Either<Double, Boolean> {
if(elt.addressOfSymbol!=null) { if(elt.addressOfSymbol!=null) {
when { when {