fix code size regressions

This commit is contained in:
Irmen de Jong
2025-08-14 23:37:59 +02:00
parent 4ea8b4d445
commit 729efb04e1
7 changed files with 30 additions and 16 deletions

View File

@@ -1223,11 +1223,11 @@ $repeatLabel""")
return null
val leftDt = left.type
val rightDt = right.type
if(leftDt.isUnsignedWord && rightDt.isUnsignedByte)
if((leftDt.isUnsignedWord || leftDt.isPointer) && rightDt.isUnsignedByte)
return Pair(left, right)
if(leftDt.isUnsignedByte && rightDt.isUnsignedWord)
return Pair(right, left)
if(leftDt.isUnsignedWord && rightDt.isUnsignedWord) {
if((leftDt.isUnsignedWord || leftDt.isPointer) && rightDt.isUnsignedWord) {
// could be that the index was a constant numeric byte but converted to word, check that
val constIdx = right as? PtNumber
if(constIdx!=null && constIdx.number.toInt()>=0 && constIdx.number.toInt()<=255) {

View File

@@ -21,7 +21,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
// we consider them NOT to be optimized into (possibly different) CPU registers.
// Just load them in whatever the register spec says.
return when (params.size) {
1 -> params[0].type.isIntegerOrBool && params[0].register == null
1 -> params[0].register == null && (params[0].type.isIntegerOrBool || params[0].type.isPointer)
2 -> params[0].type.isByteOrBool && params[1].type.isByteOrBool && params[0].register == null && params[1].register == null
else -> false
}

View File

@@ -53,6 +53,11 @@ internal class BeforeAsmTypecastCleaner(val program: Program,
}
}
if(typecast.type.isUnsignedWord && sourceDt.isPointer) {
// remove all typecasts of pointers to unsigned words.
return listOf(IAstModification.ReplaceNode(typecast, typecast.expression, parent))
}
return noModifications
}

View File

@@ -1637,7 +1637,9 @@ class IfExpression(var condition: Expression, var truevalue: Expression, var fal
override fun inferType(program: Program): InferredTypes.InferredType {
val t1 = truevalue.inferType(program)
val t2 = falsevalue.inferType(program)
return if(t1==t2) t1 else InferredTypes.unknown()
if(t1==t2) return t1
if(t1.isPointer && t2.isUnsignedWord || t1.isUnsignedWord && t2.isPointer) return InferredTypes.knownFor(BaseDataType.UWORD)
return InferredTypes.unknown()
}
override fun copy(): Expression = IfExpression(condition.copy(), truevalue.copy(), falsevalue.copy(), position)

View File

@@ -153,7 +153,7 @@ Regular subroutines
- A byte value will be put in ``A`` .
- A boolean value will be put in ``A`` too, as 0 or 1.
- A word value will be put in ``A`` + ``Y`` register pair (lsb in A, msb in Y).
- A word or pointer value will be put in ``A`` + ``Y`` register pair (lsb in A, msb in Y).
- A float value will be put in the ``FAC1`` float 'register'.
- In case of *multiple* return values:
@@ -171,7 +171,7 @@ Regular subroutines
some builtin functions are special and won't exactly follow these rules.
**Some arguments will be passed in registers:**
For single byte and word arguments, the values are simply loaded in cpu registers by the caller before calling the subroutine.
For single byte, word, and pointer arguments, the values are simply loaded in cpu registers by the caller before calling the subroutine.
*The subroutine itself will take care of putting the values into the parameter variables.* This saves on code size because
otherwise all callers would have to store the values in those variables themselves.
Note that his convention is also still used for subroutines that specify parameters to be put into
@@ -187,6 +187,9 @@ Two byte parameters: ``sub foo(ubyte bar, ubyte baz) { ... }``
Single word parameter: ``sub foo(uword bar) { ... }``
gets bar in the register pair A + Y (lsb in A, msb in Y), *subroutine* stores it into parameter variable
Single pointer parameter: ``sub foo(^^ubyte bar) { ... }``
gets bar in the register pair A + Y (lsb in A, msb in Y), *subroutine* stores it into parameter variable
Floating point parameter: ``sub foo(float bar) { ... }``
value for bar gets copied into the parameter variable *by the caller*

View File

@@ -5,8 +5,6 @@ TODO
STRUCTS and TYPED POINTERS (6502 codegen specific)
--------------------------------------------------
- fix code size regression. (for instance rockrunner is 200 bytes larger than before)
- fix struct allocations/inits.
- prefixSymbols(): what to do with prefixing struct fields? Should they be prefixed with something or no?
@@ -17,4 +15,4 @@ STRUCTS and TYPED POINTERS (6502 codegen specific)
- update structpointers.rst docs with 6502 specific things?
- scan through 6502 library modules to change untyped uword pointers to typed pointers
- scan through 6502 examples to change untyped uword pointers to typed pointers
- fix code size regressions (if any)

View File

@@ -1,11 +1,17 @@
main {
sub start() {
struct Node {
ubyte weight
void derp("a")
}
^^Node nodes
nodes^^.zzz1 = 99
cx16.r0L = nodes^^.zzz2
cx16.r0L = nodes[2].zzz3
sub derp(str arg) -> ubyte {
if arg==0
return 42
if arg==4444
return 42
if arg!=0
return 42
if arg!=4444
return 42
return 1
}
}