mirror of
				https://github.com/irmen/prog8.git
				synced 2025-11-03 19:16:13 +00:00 
			
		
		
		
	cleanup 6502 pointer usage checks
This commit is contained in:
		@@ -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) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1403,19 +1403,11 @@ 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) {
 | 
					            if (leftDt.isPointer || leftDt.isPointerArray || rightDt.isPointer || rightDt.isPointerArray) {
 | 
				
			||||||
                errors.err("pointer arithmetic only supported for + and - operators", expr.right.position)
 | 
					                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) {
 | 
					 | 
				
			||||||
                errors.err("pointer arithmetic not yet supported for this target (will be fixed later)", expr.right.position)
 | 
					 | 
				
			||||||
                // TODO final error should be different:  pointer arithmetic only supported for + and - operators
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(expr.operator=="+" || expr.operator=="-") {
 | 
					        if(expr.operator=="+" || expr.operator=="-") {
 | 
				
			||||||
            if(leftDt.isString || rightDt.isString || leftDt.isArray || rightDt.isArray) {
 | 
					            if(leftDt.isString || rightDt.isString || leftDt.isArray || rightDt.isArray) {
 | 
				
			||||||
@@ -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) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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) }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user