when using @requirezp in a subroutine that is unused (and is pruned), don't give an error there when using %zeropage dontuse

give warning when a pointer var is declared as @nozp  (very inefficient)
This commit is contained in:
Irmen de Jong
2025-01-04 16:06:46 +01:00
parent a2be42c5ca
commit 823eaa8918
4 changed files with 78 additions and 17 deletions

View File

@@ -912,9 +912,6 @@ internal class AstChecker(private val program: Program,
} }
} }
if(compilerOptions.zeropage==ZeropageType.DONTUSE && decl.zeropage == ZeropageWish.REQUIRE_ZEROPAGE)
err("zeropage usage has been disabled by options")
if(decl.datatype.isSplitWordArray) { if(decl.datatype.isSplitWordArray) {
if (!decl.datatype.isWordArray) { if (!decl.datatype.isWordArray) {
errors.err("split can only be used on word arrays", decl.position) errors.err("split can only be used on word arrays", decl.position)
@@ -1415,6 +1412,15 @@ internal class AstChecker(private val program: Program,
} }
} }
if(functionCallExpr.target.nameInSource.singleOrNull() in listOf("peek", "peekw")) {
val pointervar = functionCallExpr.args[0] as? IdentifierReference
if(pointervar!=null)
checkPointer(pointervar)
val binexpr = functionCallExpr.args[0] as? BinaryExpression
if(binexpr?.left is IdentifierReference && binexpr.right is NumericLiteral)
checkPointer(binexpr.left as IdentifierReference)
}
super.visit(functionCallExpr) super.visit(functionCallExpr)
} }
@@ -1489,6 +1495,15 @@ internal class AstChecker(private val program: Program,
if(error!=null) if(error!=null)
errors.err(error.first, error.second) errors.err(error.first, error.second)
if(functionCallStatement.target.nameInSource.singleOrNull() in listOf("poke", "pokew")) {
val pointervar = functionCallStatement.args[0] as? IdentifierReference
if(pointervar!=null)
checkPointer(pointervar)
val binexpr = functionCallStatement.args[0] as? BinaryExpression
if(binexpr?.left is IdentifierReference && binexpr.right is NumericLiteral)
checkPointer(binexpr.left as IdentifierReference)
}
super.visit(functionCallStatement) super.visit(functionCallStatement)
} }
@@ -1559,6 +1574,12 @@ internal class AstChecker(private val program: Program,
} }
} }
private fun checkPointer(pointervar: IdentifierReference) {
val vardecl = pointervar.targetVarDecl(program)
if(vardecl?.zeropage == ZeropageWish.NOT_IN_ZEROPAGE)
errors.info("pointer variable should preferrably be in zeropage but is marked nozp", vardecl.position)
}
override fun visit(arrayIndexedExpression: ArrayIndexedExpression) { override fun visit(arrayIndexedExpression: ArrayIndexedExpression) {
checkLongType(arrayIndexedExpression) checkLongType(arrayIndexedExpression)
val target = arrayIndexedExpression.arrayvar.targetStatement(program) val target = arrayIndexedExpression.arrayvar.targetStatement(program)
@@ -1687,6 +1708,14 @@ internal class AstChecker(private val program: Program,
errors.err("address for memory access isn't uword", memread.position) errors.err("address for memory access isn't uword", memread.position)
} }
} }
val pointervar = memread.addressExpression as? IdentifierReference
if(pointervar!=null)
checkPointer(pointervar)
val binexpr = memread.addressExpression as? BinaryExpression
if(binexpr?.left is IdentifierReference && binexpr.right is NumericLiteral)
checkPointer(binexpr.left as IdentifierReference)
super.visit(memread) super.visit(memread)
} }
@@ -1700,6 +1729,14 @@ internal class AstChecker(private val program: Program,
errors.err("address for memory access isn't uword", memwrite.position) errors.err("address for memory access isn't uword", memwrite.position)
} }
} }
val pointervar = memwrite.addressExpression as? IdentifierReference
if(pointervar!=null)
checkPointer(pointervar)
val binexpr = memwrite.addressExpression as? BinaryExpression
if(binexpr?.left is IdentifierReference && binexpr.right is NumericLiteral)
checkPointer(binexpr.left as IdentifierReference)
super.visit(memwrite) super.visit(memwrite)
} }

View File

@@ -70,6 +70,13 @@ internal class VerifyFunctionArgTypes(val program: Program, val options: Compila
super.visit(functionCallStatement) super.visit(functionCallStatement)
} }
override fun visit(decl: VarDecl) {
if(options.zeropage==ZeropageType.DONTUSE && decl.zeropage == ZeropageWish.REQUIRE_ZEROPAGE)
errors.err("zeropage usage has been disabled by options", decl.position)
super.visit(decl)
}
companion object { companion object {
private fun argTypeCompatible(argDt: DataType, paramDt: DataType): Boolean { private fun argTypeCompatible(argDt: DataType, paramDt: DataType): Boolean {

View File

@@ -78,6 +78,25 @@ Libraries
Optimizations Optimizations
------------- -------------
- optimize word*$0080 (also *$0040); don't shift 7 times, but swap lsb/msb (rockrunner)
- if abs(dx) < cave.VISIBLE_CELLS_H looks like it treats abs(dx) as signed word still in codegen? (rockrunner)
- word offset = (row as uword) * 128 + col*2 inefficient code for col*2 (rockrunner)
- is @(cells+offset) same code as cells[offset] ?
- if magicwall_enabled and (jiffy_counter & 3 == 1) sounds.magicwall() -> generates shortcut jump to another jump, why not immediately after the if
- explode(x, y+1) pushes x on the stack and pops it, could simply load it in reverse order and not use the stack.normal
- return mkword(attrs[cx16.r2L], object[cx16.r2L]) same as the explode() above
- @(cell_ptr-1) = objects.amoeba uses temp zp pointer, also when cell_ptr is zp already?
- x = y + z more efficient if rewritten to x=y; x+=z ?
- return peekw(table+64+pos*2) .... or rather .. return <complex expression> -> can this be optimized by using a temporary variable and chop up the expression?
likewise cx16.r0 = (gfx_lores.WIDTH-bmx.width)/2 + (gfx_lores.HEIGHT-bmx.height)/2*gfx_lores.WIDTH a lot of register juggling
- is there a trick to make @(pointer-1) = v more efficient? (like @(pointer+1)=v using Y indexed)
- if sv=="aa" else if sv=="bb" else if sv=="cc" -> needs much code, allow when(stringvar) too to avoid reloading both strings for every case (rockrunner bdcff.p8)
- if cx16.r0L>=97 and cx16.r0L<=122 {...} -> treats the boolean condition as a byte 0/1 result , can't it somehow just act on the carry bit alone?
same with if x1!=x2 or y1!=y2..... but it's because of the way boolean expressions are handled... can this be optimized?
- min(x1,x2) lots of code in a temp word, can just use the existing variables x1 and x2
- Optimize the IfExpression code generation to be more like regular if-else code. (both 6502 and IR) search for "TODO don't store condition as expression" - Optimize the IfExpression code generation to be more like regular if-else code. (both 6502 and IR) search for "TODO don't store condition as expression"
- VariableAllocator: can we think of a smarter strategy for allocating variables into zeropage, rather than first-come-first-served? - VariableAllocator: can we think of a smarter strategy for allocating variables into zeropage, rather than first-come-first-served?
for instance, vars used inside loops first, then loopvars, then uwords used as pointers (or these first??), then the rest for instance, vars used inside loops first, then loopvars, then uwords used as pointers (or these first??), then the rest

View File

@@ -1,22 +1,20 @@
%import textio %import textio
%option no_sysinit %option no_sysinit
%zeropage basicsafe %zeropage dontuse
main { main {
sub start() { sub start() {
txt.print("\n\n\n\n\n\n !") uword @nozp pointer
pointer++
ubyte column, row cx16.r0L = @(pointer)
cx16.r1L = @(pointer+100)
column, row = txt.get_cursor() cx16.r1 = peekw(pointer)
txt.nl() cx16.r2 = peekw(pointer+100)
txt.print_ub(column) cx16.r3L = peek(pointer+100)
txt.spc() @(pointer) = 99
txt.print_ub(row) @(pointer+100) = 99
txt.nl() poke(pointer, 99)
pokew(pointer, 99)
repeat {
}
} }
} }