cleanup 6502 pointer usage checks

This commit is contained in:
Irmen de Jong
2025-05-16 21:44:28 +02:00
parent 1a69a2f1bc
commit 05dad5ab5f
7 changed files with 41 additions and 37 deletions

View File

@@ -154,11 +154,11 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
println("*********** COMPILER AST END *************\n") println("*********** COMPILER AST END *************\n")
} }
val intermediateAst = SimplifiedAstMaker(program, args.errors).transform() val intermediateAst = SimplifiedAstMaker(program, options.compTarget, args.errors).transform()
val stMaker = SymbolTableMaker(intermediateAst, compilationOptions) val stMaker = SymbolTableMaker(intermediateAst, compilationOptions)
val symbolTable = stMaker.make() val symbolTable = stMaker.make()
postprocessSimplifiedAst(intermediateAst, symbolTable, args.errors) postprocessSimplifiedAst(intermediateAst, symbolTable, compilationOptions, args.errors)
args.errors.report() args.errors.report()
if(compilationOptions.optimize) { if(compilationOptions.optimize) {

View File

@@ -1403,17 +1403,9 @@ internal class AstChecker(private val program: Program,
val rightDt = rightIDt.getOrUndef() val rightDt = rightIDt.getOrUndef()
// gate off nonsensical pointer arithmetic // gate off nonsensical pointer arithmetic
if(compilerOptions.compTarget.name == VMTarget.NAME) { if (expr.operator !in arrayOf("+", "-") + ComparisonOperators) {
if (expr.operator !in arrayOf("+", "-") + ComparisonOperators) {
if (leftDt.isPointer || leftDt.isPointerArray || rightDt.isPointer || rightDt.isPointerArray) {
errors.err("pointer arithmetic only supported for + and - operators", expr.right.position)
}
}
}
else if(expr.operator !in emptyArray<String>()) { // TODO add + and - operators support for pointer arithmetic
if (leftDt.isPointer || leftDt.isPointerArray || rightDt.isPointer || rightDt.isPointerArray) { if (leftDt.isPointer || leftDt.isPointerArray || rightDt.isPointer || rightDt.isPointerArray) {
errors.err("pointer arithmetic not yet supported for this target (will be fixed later)", expr.right.position) errors.err("pointer arithmetic only supported for + and - operators", expr.right.position)
// TODO final error should be different: pointer arithmetic only supported for + and - operators
} }
} }
@@ -2018,10 +2010,6 @@ internal class AstChecker(private val program: Program,
} }
override fun visit(struct: StructDecl) { override fun visit(struct: StructDecl) {
if(compilerOptions.compTarget.name != VMTarget.NAME)
TODO("struct types are not yet supported in the 6502 compilation targets (only virtual) ${struct.position}")
val uniqueFields = struct.fields.map { it.second }.toSet() val uniqueFields = struct.fields.map { it.second }.toSet()
if(uniqueFields.size!=struct.fields.size) if(uniqueFields.size!=struct.fields.size)
errors.err("duplicate field names in struct", struct.position) errors.err("duplicate field names in struct", struct.position)
@@ -2039,22 +2027,11 @@ internal class AstChecker(private val program: Program,
} }
override fun visit(deref: PtrDereference) { override fun visit(deref: PtrDereference) {
if(compilerOptions.compTarget.name != VMTarget.NAME)
TODO("typed pointers are not yet supported in the 6502 compilation targets (only virtual) ${deref.position}")
// unfortunately the AST regarding pointer dereferencing is a bit of a mess, and we cannot do precise type checking on elements inside such expressions yet. // unfortunately the AST regarding pointer dereferencing is a bit of a mess, and we cannot do precise type checking on elements inside such expressions yet.
if(deref.inferType(program).isUnknown) if(deref.inferType(program).isUnknown)
errors.err("unable to determine type of dereferenced pointer expression", deref.position) errors.err("unable to determine type of dereferenced pointer expression", deref.position)
} }
override fun visit(idxderef: PtrIndexedDereference) {
if(compilerOptions.compTarget.name != VMTarget.NAME)
TODO("typed pointers are not yet supported in the 6502 compilation targets (only virtual) ${idxderef.position}")
// TODO ast checks for this one?
}
private fun checkLongType(expression: Expression) { private fun checkLongType(expression: Expression) {
if(expression.inferType(program) issimpletype BaseDataType.LONG) { if(expression.inferType(program) issimpletype BaseDataType.LONG) {
if((expression.parent as? VarDecl)?.type!=VarDeclType.CONST) { if((expression.parent as? VarDecl)?.type!=VarDeclType.CONST) {

View File

@@ -22,7 +22,7 @@ import kotlin.io.path.isRegularFile
/** /**
* Convert 'old' compiler-AST into the 'new' simplified AST with baked types. * Convert 'old' compiler-AST into the 'new' simplified AST with baked types.
*/ */
class SimplifiedAstMaker(private val program: Program, private val errors: IErrorReporter) { class SimplifiedAstMaker(private val program: Program, private val target: ICompilationTarget, private val errors: IErrorReporter) {
fun transform(): PtProgram { fun transform(): PtProgram {
val ptProgram = PtProgram( val ptProgram = PtProgram(
program.name, program.name,

View File

@@ -7,9 +7,38 @@ import prog8.code.ast.*
import prog8.code.core.* import prog8.code.core.*
internal fun postprocessSimplifiedAst(program: PtProgram, st: SymbolTable, errors: IErrorReporter) { internal fun postprocessSimplifiedAst(
program: PtProgram,
st: SymbolTable,
option: CompilationOptions,
errors: IErrorReporter
) {
processDefers(program, st, errors) processDefers(program, st, errors)
processSubtypesIntoStReferences(program, st) processSubtypesIntoStReferences(program, st)
if(option.compTarget.cpu!=CpuType.VIRTUAL)
checkForPointerTypesOn6502(program, errors) // TODO remove this once the 6502 codegen can deal with pointer types and structs
}
private fun checkForPointerTypesOn6502(program: PtProgram, errors: IErrorReporter) {
fun check(node: PtNode) {
when(node) {
//is PtAddressOf -> if(node.type.isPointer) errors.err("cannot use pointer type yet on 6502 target $node", node.position)
is PtAssignTarget -> if(!node.void && node.type.isPointer) errors.err("cannot use pointer type yet on 6502 target $node", node.position)
is PtBinaryExpression -> if(node.left.type.isPointer || node.right.type.isPointer) errors.err("cannot do pointer arithmetic yet on 6502 target $node", node.position)
is PtIdentifier -> if(node.type.isPointer) errors.err("cannot use pointer type yet on 6502 target $node", node.position)
is PtPointerDeref -> errors.err("cannot use pointer type yet on 6502 target $node", node.position)
is PtPointerIndexedDeref -> errors.err("cannot use pointer type yet on 6502 target $node", node.position)
is PtPrefix -> if(node.type.isPointer) errors.err("cannot use pointer type yet on 6502 target $node", node.position)
is PtTypeCast -> if(node.type.isPointer) errors.err("cannot use pointer type yet on 6502 target $node", node.position)
is PtStructDecl -> errors.err("cannot use struct type yet on 6502 target $node", node.position)
is PtSubroutineParameter -> if(node.type.isPointer) errors.err("cannot use pointer type yet on 6502 target $node", node.position)
is PtVariable -> if(node.type.isPointer) errors.err("cannot use pointer type yet on 6502 target $node", node.position)
is PtSubSignature -> if(node.returns.any{it.isPointer}) errors.err("cannot use pointer type yet on 6502 target $node", node.position)
else -> {}
}
}
walkAst(program) { node, _ -> check(node) }
} }

View File

@@ -92,7 +92,7 @@ class TestAsmGenSymbols: StringSpec({
val astchecker = AstChecker(program, errors, options) val astchecker = AstChecker(program, errors, options)
astchecker.visit(program) astchecker.visit(program)
errors.report() errors.report()
val ptProgram = SimplifiedAstMaker(program, errors).transform() val ptProgram = SimplifiedAstMaker(program, options.compTarget, errors).transform()
val st = SymbolTableMaker(ptProgram, options).make() val st = SymbolTableMaker(ptProgram, options).make()
return AsmGen6502Internal(ptProgram, st, options, errors, 0) return AsmGen6502Internal(ptProgram, st, options, errors, 0)
} }

View File

@@ -50,13 +50,14 @@ STRUCTS and TYPED POINTERS
- DONE: replace ^^str by ^^ubyte - DONE: replace ^^str by ^^ubyte
- DONE: allow return ubyte/uword when pointer type is expected as return value type - DONE: allow return ubyte/uword when pointer type is expected as return value type
- DONE: fix _msb/_lsb storage of the split-words pointer-arrays - DONE: fix _msb/_lsb storage of the split-words pointer-arrays
- make typeForAddressOf() be even more specific about the typed pointers it returns for the address-of operator. + unit test. Needs fixes in 6502 codegen too though... (also recheck passing STR and ARRAY types to subroutines) - DONE: what about static initialization of an array of struct pointers? -> impossible right now because the pointer values are not constants.
- fixing the pointer dereferencing issues (cursed hybrid beween IdentifierReference, PtrDereferece and PtrIndexedDereference) may require getting rid of scoped identifiers altogether and treat '.' as a "scope or pointer following operator"
- (later, nasty parser problem:) support chaining pointer dereference on function calls that return a pointer. (type checking now fails on stuff like func().field and func().next.field)
- add unit tests for all changes (pointers and structs) - add unit tests for all changes (pointers and structs)
- make typeForAddressOf() be even more specific about the typed pointers it returns for the address-of operator. + unit test. Needs fixes in 6502 codegen too though... (also recheck passing STR and ARRAY types to subroutines)
- 6502 codegen: remove checks in checkForPointerTypesOn6502()
- 6502 codegen should warn about writing to initialized struct instances when using romable code, like with arrays "can only be used as read-only in ROMable code" - 6502 codegen should warn about writing to initialized struct instances when using romable code, like with arrays "can only be used as read-only in ROMable code"
- 6502 asm symbol name prefixing should work for dereferences too. - 6502 asm symbol name prefixing should work for dereferences too.
- What about static initialization of an array of struct pointers? -> impossible right now because the pointer values are not constants - fixing the pointer dereferencing issues (cursed hybrid beween IdentifierReference, PtrDereferece and PtrIndexedDereference) may require getting rid of scoped identifiers altogether and treat '.' as a "scope or pointer following operator"
- (later, nasty parser problem:) support chaining pointer dereference on function calls that return a pointer. (type checking now fails on stuff like func().field and func().next.field)
- update syntax highlighting files - update syntax highlighting files

View File

@@ -37,9 +37,6 @@ main {
arrayinfo(values) arrayinfo(values)
arrayinfo(&values[2]) arrayinfo(&values[2])
arrayinfo2(values)
bptr = name bptr = name
ubptr = name ubptr = name
txt.print_uw(&name) txt.print_uw(&name)