remove the -dontsplitarrays compiler option

it was still there for backward compatibility reasons with really old prog8 code. If you need a word array to be not split, just use @nosplit on the array.
This commit is contained in:
Irmen de Jong
2025-10-05 14:44:17 +02:00
parent 4195e3968a
commit 3e1386a987
12 changed files with 13 additions and 51 deletions

View File

@@ -29,7 +29,6 @@ class CompilationOptions(val output: OutputType,
var varsGolden: Boolean = false, var varsGolden: Boolean = false,
var slabsHighBank: Int? = null, var slabsHighBank: Int? = null,
var slabsGolden: Boolean = false, var slabsGolden: Boolean = false,
var dontSplitWordArrays: Boolean = false,
var breakpointCpuInstruction: String? = null, var breakpointCpuInstruction: String? = null,
var ignoreFootguns: Boolean = false, var ignoreFootguns: Boolean = false,
var outputDir: Path = Path(""), var outputDir: Path = Path(""),

View File

@@ -62,7 +62,6 @@ private fun compileMain(args: Array<String>): Boolean {
val slabsGolden by cli.option(ArgType.Boolean, fullName = "slabsgolden", description = "put memory() slabs in 'golden ram' memory area instead of at the end of the program. On the cx16 target this is $0400-07ff. This is unavailable on other systems.") val slabsGolden by cli.option(ArgType.Boolean, fullName = "slabsgolden", description = "put memory() slabs in 'golden ram' memory area instead of at the end of the program. On the cx16 target this is $0400-07ff. This is unavailable on other systems.")
val slabsHighBank by cli.option(ArgType.Int, fullName = "slabshigh", description = "put memory() slabs in high memory area instead of at the end of the program. On the cx16 target the value specifies the HiRAM bank to use, on other systems this value is ignored.") val slabsHighBank by cli.option(ArgType.Int, fullName = "slabshigh", description = "put memory() slabs in high memory area instead of at the end of the program. On the cx16 target the value specifies the HiRAM bank to use, on other systems this value is ignored.")
val dontIncludeSourcelines by cli.option(ArgType.Boolean, fullName = "nosourcelines", description = "do not include original Prog8 source lines in generated asm code") val dontIncludeSourcelines by cli.option(ArgType.Boolean, fullName = "nosourcelines", description = "do not include original Prog8 source lines in generated asm code")
val dontSplitWordArrays by cli.option(ArgType.Boolean, fullName = "dontsplitarrays", description = "don't store any word array as split lsb/msb in memory, as if all of those have @nosplit")
val sourceDirs by cli.option(ArgType.String, fullName="srcdirs", description = "list of extra paths, separated with ${File.pathSeparator}, to search in for imported modules").multiple().delimiter(File.pathSeparator) val sourceDirs by cli.option(ArgType.String, fullName="srcdirs", description = "list of extra paths, separated with ${File.pathSeparator}, to search in for imported modules").multiple().delimiter(File.pathSeparator)
val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of ${CompilationTargets.joinToString(",")} or a custom target properties file) (required)") val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of ${CompilationTargets.joinToString(",")} or a custom target properties file) (required)")
val showTimings by cli.option(ArgType.Boolean, fullName = "timings", description = "show internal compiler timings (for performance analysis)") val showTimings by cli.option(ArgType.Boolean, fullName = "timings", description = "show internal compiler timings (for performance analysis)")
@@ -193,7 +192,6 @@ private fun compileMain(args: Array<String>): Boolean {
slabsHighBank, slabsHighBank,
slabsGolden == true, slabsGolden == true,
compilationTarget!!, compilationTarget!!,
dontSplitWordArrays == true,
breakpointCpuInstruction, breakpointCpuInstruction,
printAst1 == true, printAst1 == true,
printAst2 == true, printAst2 == true,
@@ -278,7 +276,6 @@ private fun compileMain(args: Array<String>): Boolean {
slabsHighBank, slabsHighBank,
slabsGolden == true, slabsGolden == true,
compilationTarget!!, compilationTarget!!,
dontSplitWordArrays == true,
breakpointCpuInstruction, breakpointCpuInstruction,
printAst1 == true, printAst1 == true,
printAst2 == true, printAst2 == true,

View File

@@ -55,7 +55,6 @@ class CompilerArguments(val filepath: Path,
val slabsHighBank: Int?, val slabsHighBank: Int?,
val slabsGolden: Boolean, val slabsGolden: Boolean,
val compilationTarget: String, val compilationTarget: String,
val dontSplitWordArrays: Boolean,
val breakpointCpuInstruction: String?, val breakpointCpuInstruction: String?,
val printAst1: Boolean, val printAst1: Boolean,
val printAst2: Boolean, val printAst2: Boolean,
@@ -120,7 +119,6 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
varsGolden = args.varsGolden varsGolden = args.varsGolden
slabsHighBank = args.slabsHighBank slabsHighBank = args.slabsHighBank
slabsGolden = args.slabsGolden slabsGolden = args.slabsGolden
dontSplitWordArrays = args.dontSplitWordArrays
outputDir = args.outputDir.normalize() outputDir = args.outputDir.normalize()
symbolDefs = args.symbolDefs symbolDefs = args.symbolDefs
} }

View File

@@ -113,8 +113,6 @@ class AstPreprocessor(val program: Program,
val replacements = mutableListOf<IAstModification>() val replacements = mutableListOf<IAstModification>()
for(decl in vars) { for(decl in vars) {
if(shouldUnSplitArray(decl))
continue // unsplitting must be done first
if(decl.type != VarDeclType.VAR) { if(decl.type != VarDeclType.VAR) {
movements.add(IAstModification.InsertFirst(decl, parentscope)) movements.add(IAstModification.InsertFirst(decl, parentscope))
replacements.add(IAstModification.Remove(decl, scope)) replacements.add(IAstModification.Remove(decl, scope))
@@ -198,10 +196,6 @@ class AstPreprocessor(val program: Program,
} }
} }
if(shouldUnSplitArray(decl)) {
return makeUnSplitArray(decl)
}
// convert all antlr names to structs // convert all antlr names to structs
val antlrTypeName = decl.datatype.subTypeFromAntlr val antlrTypeName = decl.datatype.subTypeFromAntlr
if(antlrTypeName!=null) { if(antlrTypeName!=null) {
@@ -232,18 +226,6 @@ class AstPreprocessor(val program: Program,
return noModifications return noModifications
} }
private fun shouldUnSplitArray(decl: VarDecl): Boolean =
options.dontSplitWordArrays && decl.datatype.isSplitWordArray
private fun makeUnSplitArray(decl: VarDecl): Iterable<IAstModification> {
val splitDt = DataType.arrayFor(decl.datatype.sub!!, false)
val newDecl = VarDecl(
decl.type, decl.origin, splitDt, decl.zeropage, decl.splitwordarray, decl.arraysize, decl.name, emptyList(),
decl.value?.copy(), decl.sharedWithAsm, decl.alignment, false, decl.position
)
return listOf(IAstModification.ReplaceNode(decl, newDecl, decl.parent))
}
override fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> { override fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> {
// For non-kernal subroutines and non-asm parameters: // For non-kernal subroutines and non-asm parameters:
// inject subroutine params as local variables (if they're not there yet). // inject subroutine params as local variables (if they're not there yet).

View File

@@ -79,20 +79,14 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
var changeSplit: SplitWish = decl.splitwordarray var changeSplit: SplitWish = decl.splitwordarray
when(decl.splitwordarray) { when(decl.splitwordarray) {
SplitWish.DONTCARE -> { SplitWish.DONTCARE -> {
if(options.dontSplitWordArrays) { changeDataType = if(decl.datatype.isSplitWordArray) null else {
changeDataType = if(decl.datatype.isSplitWordArray) DataType.arrayFor(decl.datatype.elementType().base, false) else null val eltDt = decl.datatype.elementType()
changeSplit = SplitWish.NOSPLIT if(eltDt.isPointer)
} TODO("convert array of pointers to split words array type")
else { else
changeDataType = if(decl.datatype.isSplitWordArray) null else { DataType.arrayFor(eltDt.base)
val eltDt = decl.datatype.elementType()
if(eltDt.isPointer)
TODO("convert array of pointers to split words array type")
else
DataType.arrayFor(eltDt.base)
}
changeSplit = SplitWish.SPLIT
} }
changeSplit = SplitWish.SPLIT
} }
SplitWish.SPLIT -> { SplitWish.SPLIT -> {
changeDataType = if(decl.datatype.isSplitWordArray) null else { changeDataType = if(decl.datatype.isSplitWordArray) null else {

View File

@@ -47,7 +47,6 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat
slabsHighBank = null, slabsHighBank = null,
slabsGolden = false, slabsGolden = false,
compilationTarget = target.name, compilationTarget = target.name,
dontSplitWordArrays = false,
breakpointCpuInstruction = null, breakpointCpuInstruction = null,
printAst1 = false, printAst1 = false,
printAst2 = false, printAst2 = false,

View File

@@ -39,7 +39,6 @@ class TestCompilerOptionSourcedirs: FunSpec({
slabsHighBank = null, slabsHighBank = null,
slabsGolden = false, slabsGolden = false,
compilationTarget = Cx16Target.NAME, compilationTarget = Cx16Target.NAME,
dontSplitWordArrays = false,
breakpointCpuInstruction = null, breakpointCpuInstruction = null,
printAst1 = false, printAst1 = false,
printAst2 = false, printAst2 = false,

View File

@@ -43,7 +43,6 @@ internal fun compileFile(
symbolDefs = emptyMap(), symbolDefs = emptyMap(),
outputDir = outputDir, outputDir = outputDir,
errors = errors ?: ErrorReporterForTests(), errors = errors ?: ErrorReporterForTests(),
dontSplitWordArrays = false,
breakpointCpuInstruction = null, breakpointCpuInstruction = null,
printAst1 = false, printAst1 = false,
printAst2 = false, printAst2 = false,

View File

@@ -162,10 +162,6 @@ One or more .p8 module files
Add this user-defined symbol directly to the beginning of the generated assembly file. Add this user-defined symbol directly to the beginning of the generated assembly file.
Can be repeated to define multiple symbols. Can be repeated to define multiple symbols.
``-dontsplitarrays``
Treat all word arrays as tagged with @nosplit so they are all stored linearly in memory,
instead of splitting them in separate lsb and msb arrays.
``-dumpsymbols`` ``-dumpsymbols``
print a dump of the variable declarations and subroutine signatures print a dump of the variable declarations and subroutine signatures

View File

@@ -73,7 +73,7 @@ So the syntax for declaring typed pointers looks like this:
``^^type[size]``: array with size size containing pointers to a type. ``^^type[size]``: array with size size containing pointers to a type.
So for example; ``^^word[100] values`` declares values to be an array of 100 pointers to words. So for example; ``^^word[100] values`` declares values to be an array of 100 pointers to words.
Note that an array of pointers (regardless of the type they point to) is always a @split word array at this time. Note that an array of pointers (regardless of the type they point to) is always a split word array.
(this is the most efficient way to access the pointers, and they need to be copied to zeropage first to (this is the most efficient way to access the pointers, and they need to be copied to zeropage first to
be able to use them anyway. It also allows for arrays of up to 256 pointers instead of 128.) be able to use them anyway. It also allows for arrays of up to 256 pointers instead of 128.)

View File

@@ -1,6 +1,10 @@
TODO TODO
==== ====
remove "@split" tag SplitWish.NOSPLIT
LONG TYPE LONG TYPE
--------- ---------
- implement the other comparison operators (<,>,<=,>=) on longs - implement the other comparison operators (<,>,<=,>=) on longs
@@ -94,7 +98,7 @@ IR/VM
- 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) - 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. global initialization values are simply a list of LOAD instructions.
Variables replaced include all subroutine parameters? Or not? So the only variables that remain as variables are arrays and strings. Variables replaced include all subroutine parameters? Or not? So the only variables that remain as variables are arrays and strings.
- the @split arrays are currently also split in _lsb/_msb arrays in the IR, and operations take multiple (byte) instructions that may lead to verbose and slow operation and machine code generation down the line. - the split word arrays are currently also split in _lsb/_msb arrays in the IR, and operations take multiple (byte) instructions that may lead to verbose and slow operation and machine code generation down the line.
maybe another representation is needed once actual codegeneration is done from the IR...? Should array operations be encoded in a more high level form in the IR? maybe another representation is needed once actual codegeneration is done from the IR...? Should array operations be encoded in a more high level form in the IR?
- ExpressionCodeResult: get rid of the separation between single result register and multiple result registers? maybe not, this requires hundreds of lines to change.. :( - ExpressionCodeResult: get rid of the separation between single result register and multiple result registers? maybe not, this requires hundreds of lines to change.. :(
- sometimes source lines end up missing in the output p8ir, for example the first assignment is gone in: - sometimes source lines end up missing in the output p8ir, for example the first assignment is gone in:

View File

@@ -366,14 +366,9 @@ For normal prog8 array indexing, the compiler takes care of the distiction for y
*But for assembly code, or code that otherwise accesses the array elements directly, you have to be aware of the distinction from 'normal' arrays.* *But for assembly code, or code that otherwise accesses the array elements directly, you have to be aware of the distinction from 'normal' arrays.*
In the assembly code, the array is generated as two byte arrays namely ``name_lsb`` and ``name_msb``, immediately following eachother in memory. In the assembly code, the array is generated as two byte arrays namely ``name_lsb`` and ``name_msb``, immediately following eachother in memory.
The ``@split`` tag can be added to the variable declaration to *always* split the array even when the command line option -dontsplitarrays is set
The ``@nosplit`` tag can be added to the variable declaration to *never* split the array. This is useful for compatibility with The ``@nosplit`` tag can be added to the variable declaration to *never* split the array. This is useful for compatibility with
code that expects the words to be sequentially in memory (such as the cx16.FB_set_palette routine). code that expects the words to be sequentially in memory (such as the cx16.FB_set_palette routine).
There is a command line option ``-dontsplitarrays`` that avoids splitting word arrays by default,
so every word array is layed out sequentially in memory (this is what older versions of Prog8 used to do).immediately
It reduces the maximum word array length to 128. You can still override this by adding ``@split`` explicitly.
.. note:: .. note::
Most but not all array operations are supported yet on "split word arrays". Most but not all array operations are supported yet on "split word arrays".
If you get a compiler error message, simply revert to a regular sequential word array using ``@nosplit``, If you get a compiler error message, simply revert to a regular sequential word array using ``@nosplit``,