mirror of
https://github.com/irmen/prog8.git
synced 2025-11-03 04:17:16 +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,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) {
|
||||||
|
|||||||
@@ -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