diff --git a/codeCore/src/prog8/code/core/CompilationOptions.kt b/codeCore/src/prog8/code/core/CompilationOptions.kt index 3c33ab677..31617dcca 100644 --- a/codeCore/src/prog8/code/core/CompilationOptions.kt +++ b/codeCore/src/prog8/code/core/CompilationOptions.kt @@ -21,6 +21,7 @@ class CompilationOptions(val output: OutputType, var experimentalCodegen: Boolean = false, var varsHigh: Boolean = false, var useNewExprCode: Boolean = false, + var splitWordArrays: Boolean = false, var evalStackBaseAddress: UInt? = null, var outputDir: Path = Path(""), var symbolDefs: Map = emptyMap() diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index bbfcadcab..fe53384b4 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -5,6 +5,7 @@ import prog8.code.ast.* import prog8.code.core.AssemblyError import prog8.code.core.DataType import prog8.code.core.SignedDatatypes +import prog8.code.core.SplitWordArrayTypes import prog8.intermediate.* @@ -280,6 +281,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe DataType.ARRAY_UB, DataType.ARRAY_B, DataType.STR -> IMSyscall.REVERSE_BYTES DataType.ARRAY_UW, DataType.ARRAY_W -> IMSyscall.REVERSE_WORDS DataType.ARRAY_F -> IMSyscall.REVERSE_FLOATS + in SplitWordArrayTypes -> TODO("split word reverse") else -> throw IllegalArgumentException("weird type to reverse") } val result = mutableListOf() @@ -302,6 +304,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe DataType.ARRAY_W -> IMSyscall.SORT_WORD DataType.STR -> IMSyscall.SORT_UBYTE DataType.ARRAY_F -> throw IllegalArgumentException("sorting a floating point array is not supported") + in SplitWordArrayTypes -> TODO("split word sort") else -> throw IllegalArgumentException("weird type to sort") } val result = mutableListOf() diff --git a/compiler/src/prog8/CompilerMain.kt b/compiler/src/prog8/CompilerMain.kt index 1c85e32d4..371c07ea8 100644 --- a/compiler/src/prog8/CompilerMain.kt +++ b/compiler/src/prog8/CompilerMain.kt @@ -53,6 +53,7 @@ private fun compileMain(args: Array): Boolean { val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watch for file changes)") val varsHigh by cli.option(ArgType.Boolean, fullName = "varshigh", description = "put uninitialized variables in high memory area instead of at the end of the program") val useNewExprCode by cli.option(ArgType.Boolean, fullName = "newexpr", description = "use new expression code-gen (experimental)") + val splitWordArrays by cli.option(ArgType.Boolean, fullName = "splitarrays", description = "treat all word arrays as tagged with @split to make them lsb/msb split in memory") val moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999) try { @@ -130,6 +131,7 @@ private fun compileMain(args: Array): Boolean { useNewExprCode == true, compilationTarget, evalStackAddr, + splitWordArrays == true, processedSymbols, srcdirs, outputPath @@ -195,6 +197,7 @@ private fun compileMain(args: Array): Boolean { useNewExprCode == true, compilationTarget, evalStackAddr, + splitWordArrays == true, processedSymbols, srcdirs, outputPath diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 5a651268a..1be1aa229 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -40,6 +40,7 @@ class CompilerArguments(val filepath: Path, val useNewExprCode: Boolean, val compilationTarget: String, val evalStackBaseAddress: UInt?, + val splitWordArrays: Boolean, val symbolDefs: Map, val sourceDirs: List = emptyList(), val outputDir: Path = Path(""), @@ -80,6 +81,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? { varsHigh = args.varsHigh useNewExprCode = args.useNewExprCode evalStackBaseAddress = args.evalStackBaseAddress + splitWordArrays = args.splitWordArrays outputDir = args.outputDir.normalize() symbolDefs = args.symbolDefs } diff --git a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt index df907eb04..8d3e784dc 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt @@ -162,6 +162,19 @@ class AstPreprocessor(val program: Program, nextAssignment.origin = AssignmentOrigin.VARINIT } } + + if(options.splitWordArrays && (decl.datatype==DataType.ARRAY_W || decl.datatype==DataType.ARRAY_UW)) { + // make all word arrays automatically be tagged as split arrays + if(!decl.definingBlock.isInLibrary) { + val splitDt = ArrayToElementTypes.getValue(decl.datatype) + val newDecl = VarDecl( + decl.type, decl.origin, splitDt, decl.zeropage, decl.arraysize, decl.name, + decl.value, true, decl.sharedWithAsm, true, decl.position + ) + return listOf(IAstModification.ReplaceNode(decl, newDecl, parent)) + } + } + return noModifications } diff --git a/compiler/test/TestCompilerOnExamples.kt b/compiler/test/TestCompilerOnExamples.kt index 5fc22c4c3..7456f520e 100644 --- a/compiler/test/TestCompilerOnExamples.kt +++ b/compiler/test/TestCompilerOnExamples.kt @@ -36,6 +36,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat useNewExprCode = false, compilationTarget = target.name, evalStackBaseAddress = null, + splitWordArrays = false, symbolDefs = emptyMap(), outputDir = outputDir ) diff --git a/compiler/test/TestCompilerOptionLibdirs.kt b/compiler/test/TestCompilerOptionLibdirs.kt index bcdafab38..0e4cb452e 100644 --- a/compiler/test/TestCompilerOptionLibdirs.kt +++ b/compiler/test/TestCompilerOptionLibdirs.kt @@ -53,6 +53,7 @@ class TestCompilerOptionSourcedirs: FunSpec({ useNewExprCode = false, compilationTarget = Cx16Target.NAME, evalStackBaseAddress = null, + splitWordArrays = false, symbolDefs = emptyMap(), sourceDirs, outputDir diff --git a/compiler/test/helpers/compileXyz.kt b/compiler/test/helpers/compileXyz.kt index ceefdde25..63b3477da 100644 --- a/compiler/test/helpers/compileXyz.kt +++ b/compiler/test/helpers/compileXyz.kt @@ -37,7 +37,8 @@ internal fun compileFile( evalStackBaseAddress = null, symbolDefs = emptyMap(), outputDir = outputDir, - errors = errors ?: ErrorReporterForTests() + errors = errors ?: ErrorReporterForTests(), + splitWordArrays = false ) return compileProgram(args) } diff --git a/docs/source/building.rst b/docs/source/building.rst index 14beafff8..9f35c0773 100644 --- a/docs/source/building.rst +++ b/docs/source/building.rst @@ -162,6 +162,11 @@ One or more .p8 module files ``-expericodegen`` Use experimental code generation backend (*incomplete*). +``-splitarrays`` + Treat all word arrays as tagged with @split so they are all lsb/msb split into memory. + This removes the need to add @split yourself but some programs may fail to compile with + this option as not all array operations are implemented yet on split arrays. + ``-vm`` load and run a p8-virt or p8-ir listing in the internal VirtualMachine instead of compiling a prog8 program file.. diff --git a/examples/test.p8 b/examples/test.p8 index 24ee6b1fb..5ae6f9cd6 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,109 +6,29 @@ main { sub start() { - uword[] @split split_uwords = [12345, 60000, 4096] - txt.print_ub(len(split_uwords)) - txt.nl() - } - - sub start22() { - uword[] @split split_uwords = [12345, 60000, 4096] - word[] @split split_words = [-12345, -2222, 22222] - uword[256] @split @shared split2 - word[256] @split @shared split3 - ubyte[200] @shared dummy - uword[256] @split split_large = 1000 to 1255 - - print_arrays() - txt.nl() + uword[] split_uwords = [12345, 60000, 4096] + word[] split_words = [12345, -6000, 4096] + float[] floats = [1.1,2.2,3.3] + reverse(split_uwords) + reverse(split_words) + reverse(floats) uword ww - for ww in split_large { + for ww in split_uwords { txt.print_uw(ww) txt.spc() } txt.nl() - txt.nl() - - - ubyte xx=1 - split_uwords[1] = 0 - txt.print_uw(split_uwords[1]) - txt.spc() - txt.print_w(split_words[1]) - txt.spc() - split_words[1] = -9999 - txt.print_w(split_words[1]) - txt.spc() - txt.print_uw(split_uwords[xx]) - txt.spc() - txt.print_w(split_words[xx]) - txt.spc() - split_words[1]=-1111 - txt.print_w(split_words[xx]) - txt.nl() - txt.nl() - - sub print_arrays() { - ubyte[200] @shared dummy2 = 22 - for cx16.r0 in split_uwords { - txt.print_uw(cx16.r0) - txt.spc() - } - txt.nl() - - for cx16.r0s in split_words { - txt.print_w(cx16.r0s) - txt.spc() - } - txt.nl() - } - - ubyte idx - for idx in 0 to len(split_uwords)-1 { - cx16.r0 = split_uwords[idx] - cx16.r1s = split_words[idx] - txt.print_uw(cx16.r0) + word sw + for sw in split_words { + txt.print_w(sw) txt.spc() - txt.print_w(cx16.r1s) - txt.nl() } txt.nl() - - split_uwords[1] = 9999 - split_words[1] = -9999 - - print_arrays() - txt.nl() - - split_uwords[1]++ - split_words[1]++ - - print_arrays() - txt.nl() -; split_uwords[1] |= 4095 ; TODO fix this in 6502 codegen -; split_words[1] |= 127 ; TODO fix this in 6502 codegen -; -; print_arrays() -; txt.nl() -; txt.nl() - - cx16.r0 = split_uwords[1] - cx16.r1s = split_words[1] - ww = 6655 - split_uwords[1] = xx - split_words[1] = xx as word - txt.print_uw(split_uwords[1]) - txt.spc() - txt.print_w(split_words[1]) - txt.nl() - ww=7788 - split_uwords[xx] = ww - split_words[xx] = ww as word - txt.print_uw(split_uwords[1]) - txt.spc() - txt.print_w(split_words[1]) - txt.nl() - + ubyte ix + for ix in 0 to len(floats)-1 { + floats.print_f(floats[ix]) + txt.spc() + } } } diff --git a/httpCompilerService/src/prog8/http/TestHttp.kt b/httpCompilerService/src/prog8/http/TestHttp.kt index 2395ac548..1b17991ea 100644 --- a/httpCompilerService/src/prog8/http/TestHttp.kt +++ b/httpCompilerService/src/prog8/http/TestHttp.kt @@ -42,6 +42,7 @@ class RequestParser : Take { quietAssembler = false, asmListfile = false, experimentalCodegen = false, + splitWordArrays = false, varsHigh = false, useNewExprCode = false )