From f071c07dd90f3768d96507714623e432b6c507a4 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 6 Jan 2025 02:50:54 +0100 Subject: [PATCH] IR: only put align on lsb array of split word array. tag split word arrays with split. (but this isn't actually used yet) --- docs/source/todo.rst | 2 +- examples/test.p8 | 9 ++++---- .../src/prog8/intermediate/IRFileReader.kt | 21 ++++++++++++++---- .../src/prog8/intermediate/IRFileWriter.kt | 22 ++++++++++++++----- 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index afec5ec5d..0525709bc 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -45,7 +45,6 @@ Future Things and Ideas IR/VM ----- - getting it in shape for code generation...: the IR file should be able to encode every detail about a prog8 program (the VM doesn't have to actually be able to run all of it though!) -- split word arrays, both _msb and _lsb arrays are tagged with an alignment. This is not what's intended; only the one put in memory first should be aligned (the other one should follow straight after it) - fix call() return value handling - proper code gen for the CALLI instruction and that it (optionally) returns a word value that needs to be assigned to a reg - implement fast code paths for TODO("inplace split.... @@ -54,6 +53,7 @@ IR/VM sub start() { cx16.r0L = cx16.r1 as ubyte cx16.r0sL = cx16.r1s as byte } +- do something with the 'split' tag on split word arrays - add more optimizations in IRPeepholeOptimizer - idea: (but LLVM IR simply keeps the variables, so not a good idea then?...): replace all scalar variables by an allocated register. Keep a table of the variable to register mapping (including the datatype) global initialization values are simply a list of LOAD instructions. diff --git a/examples/test.p8 b/examples/test.p8 index 0547829c9..73fe3e352 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,9 +4,10 @@ main { sub start() { - str foo = "foo" - str bar = "bar" - bool flag = true - uword @shared foobar = if flag foo else bar + uword[10] @align64 @nosplit array1 + uword[10] @align64 @split array2 + + array1[2]++ + array2[2]++ } } diff --git a/intermediate/src/prog8/intermediate/IRFileReader.kt b/intermediate/src/prog8/intermediate/IRFileReader.kt index f6c0849a3..a454a2734 100644 --- a/intermediate/src/prog8/intermediate/IRFileReader.kt +++ b/intermediate/src/prog8/intermediate/IRFileReader.kt @@ -159,17 +159,23 @@ class IRFileReader { return if(text.isBlank()) emptyList() else { - val varPattern = Regex("(.+?)(\\[.+?\\])? (.+) zp=(.+) align=(.+)") + val varPattern = Regex("(?.+?)(?\\[.+?\\])? (?.+) zp=(?.+?)\\s?(split=(?.+?))?\\s?(align=(?.+?))?") val variables = mutableListOf() text.lineSequence().forEach { line -> // example: uword main.start.qq2 zp=DONTCARE val match = varPattern.matchEntire(line) ?: throw IRParseException("invalid VARIABLESNOINIT $line") - val (type, arrayspec, name, zpwish, alignment) = match.destructured + val type = match.groups["type"]!!.value + val arrayspec = match.groups["arrayspec"]?.value ?: "" + val name = match.groups["name"]!!.value + val zpwish = match.groups["zp"]!!.value + val split = match.groups["split"]?.value ?: "" + val alignment = match.groups["align"]?.value ?: "" if('.' !in name) throw IRParseException("unscoped name: $name") val arraysize = if(arrayspec.isNotBlank()) arrayspec.substring(1, arrayspec.length-1).toInt() else null val dt = parseDatatype(type, arraysize!=null) val zp = if(zpwish.isBlank()) ZeropageWish.DONTCARE else ZeropageWish.valueOf(zpwish) + val isSplit = if(split.isBlank()) false else split.toBoolean() val align = if(alignment.isBlank()) 0u else alignment.toUInt() val newVar = StStaticVariable(name, dt, null, null, arraysize, zp, align.toInt(), null) variables.add(newVar) @@ -215,19 +221,26 @@ class IRFileReader { return if(text.isBlank()) emptyList() else { - val varPattern = Regex("(.+?)(\\[.+?\\])? (.+)=(.*?) zp=(.+) align=(.+)") + val varPattern = Regex("(?.+?)(?\\[.+?\\])? (?.+)=(?.*?) zp=(?.+?)\\s?(split=(?.+?))?\\s?(align=(?.+?))?") val variables = mutableListOf() text.lineSequence().forEach { line -> // examples: // uword main.start.qq2=0 zp=REQUIRE_ZP // ubyte[6] main.start.namestring=105,114,109,101,110,0 val match = varPattern.matchEntire(line) ?: throw IRParseException("invalid VARIABLE $line") - val (type, arrayspec, name, value, zpwish, alignment) = match.destructured + val type = match.groups["type"]!!.value + val arrayspec = match.groups["arrayspec"]?.value ?: "" + val name = match.groups["name"]!!.value + val value = match.groups["value"]!!.value + val zpwish = match.groups["zp"]!!.value + val split = match.groups["split"]?.value ?: "" + val alignment = match.groups["align"]?.value ?: "" if('.' !in name) throw IRParseException("unscoped varname: $name") val arraysize = if(arrayspec.isNotBlank()) arrayspec.substring(1, arrayspec.length-1).toInt() else null val dt = parseDatatype(type, arraysize!=null) val zp = if(zpwish.isBlank()) ZeropageWish.DONTCARE else ZeropageWish.valueOf(zpwish) + val isSplit = if(split.isBlank()) false else split.toBoolean() val align = if(alignment.isBlank()) 0u else alignment.toUInt() var initNumeric: Double? = null var initArray: StArray? = null diff --git a/intermediate/src/prog8/intermediate/IRFileWriter.kt b/intermediate/src/prog8/intermediate/IRFileWriter.kt index b8fd1aa92..51b04724b 100644 --- a/intermediate/src/prog8/intermediate/IRFileWriter.kt +++ b/intermediate/src/prog8/intermediate/IRFileWriter.kt @@ -233,10 +233,15 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) { fun writeNoInitVar(variable: IRStStaticVariable) { if(variable.dt.isSplitWordArray) { // split into 2 ubyte arrays lsb+msb - xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_lsb zp=${variable.zpwish} align=${variable.align}\n") - xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_msb zp=${variable.zpwish} align=${variable.align}\n") + xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_lsb zp=${variable.zpwish} split=true") + if(variable.align!=0) + xml.writeCharacters(" align=${variable.align}") + xml.writeCharacters("\nubyte[${variable.length}] ${variable.name}_msb zp=${variable.zpwish} split=true\n") } else { - xml.writeCharacters("${variable.typeString} ${variable.name} zp=${variable.zpwish} align=${variable.align}\n") + xml.writeCharacters("${variable.typeString} ${variable.name} zp=${variable.zpwish}") + if(variable.align!=0) + xml.writeCharacters(" align=${variable.align}") + xml.writeCharacters("\n") } } @@ -272,8 +277,10 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) { "@>${it.addressOfSymbol}" } } - xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_lsb=$lsbValue zp=${variable.zpwish} align=${variable.align}\n") - xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_msb=$msbValue zp=${variable.zpwish} align=${variable.align}\n") + xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_lsb=$lsbValue zp=${variable.zpwish} split=true") + if(variable.align!=0) + xml.writeCharacters(" align=${variable.align}") + xml.writeCharacters("\nubyte[${variable.length}] ${variable.name}_msb=$msbValue zp=${variable.zpwish} split=true\n") } else { val dt = variable.dt val value: String = when { @@ -309,7 +316,10 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) { } else -> throw InternalCompilerException("weird dt") } - xml.writeCharacters("${variable.typeString} ${variable.name}=$value zp=${variable.zpwish} align=${variable.align}\n") + xml.writeCharacters("${variable.typeString} ${variable.name}=$value zp=${variable.zpwish}") + if(variable.align!=0) + xml.writeCharacters(" align=${variable.align}") + xml.writeCharacters("\n") } }