mirror of
https://github.com/irmen/prog8.git
synced 2025-11-01 22:16:16 +00:00
fix code size regressions
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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*
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user