From 922033c1b2d4cc6573115206b28e09c0206c361c Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 15 Nov 2022 18:51:52 +0100 Subject: [PATCH] main block element order now remains the same as in source --- .../codegen/cpu6502/ProgramAndVarsGen.kt | 10 ++---- .../prog8/codegen/intermediate/IRCodeGen.kt | 2 +- compiler/src/prog8/compiler/Compiler.kt | 2 +- .../compiler/astprocessing/AstExtensions.kt | 34 +++++-------------- .../astprocessing/BeforeAsmAstChanger.kt | 5 --- docs/source/todo.rst | 1 + examples/test.p8 | 23 +++++++++++-- .../src/prog8/intermediate/IRProgram.kt | 6 ++++ 8 files changed, 40 insertions(+), 43 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt index 9c533bcbb..4b4b45693 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt @@ -202,16 +202,10 @@ internal class ProgramAndVarsGen( asmsubs2asm(block.statements) asmgen.out("") - asmgen.out("; subroutines in this block") - // First translate regular statements, and then put the subroutines at the end. - // (regular statements = everything except the initialization assignments; - // these will be part of the prog8_init_vars init routine generated below) val initializers = blockVariableInitializers.getValue(block) - val statements = block.statements.filterNot { it in initializers } - val (subroutine, stmts) = statements.partition { it is Subroutine } - stmts.forEach { asmgen.translate(it) } - subroutine.forEach { asmgen.translate(it) } + val notInitializers = block.statements.filterNot { it in initializers } + notInitializers.forEach { asmgen.translate(it) } if(!options.dontReinitGlobals) { // generate subroutine to initialize block-level (global) variables diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index 57f563571..14e64b743 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -1122,7 +1122,7 @@ class IRCodeGen( irBlock += IRInlineBinaryChunk(null, readBinaryData(child), null) } is PtLabel -> { - TODO("allow label inside block scope ${child.name}") + irBlock += IRCodeChunk(child.name, null) } else -> TODO("weird child node $child") } diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index bf2531d9f..8ee71d49d 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -382,7 +382,7 @@ private fun postprocessAst(program: Program, errors: IErrorReporter, compilerOpt callGraph.checkRecursiveCalls(errors) program.verifyFunctionArgTypes(errors) errors.report() - program.moveMainAndStartToFirst() + program.moveMainBlockAsFirst() program.checkValid(errors, compilerOptions) // check if final tree is still valid errors.report() } diff --git a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt index e9d77f945..2b1ddf676 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt @@ -129,35 +129,19 @@ internal fun Program.variousCleanups(errors: IErrorReporter, options: Compilatio } } -internal fun Program.moveMainAndStartToFirst() { +internal fun Program.moveMainBlockAsFirst() { // The module containing the program entrypoint is moved to the first in the sequence. - // the "main" block containing the entrypoint is moved to the top in there, - // and finally the entrypoint subroutine "start" itself is moved to the top in that block. + // the "main" block containing the entrypoint is moved to the top in there. - // sortModules() - val directives = modules[0].statements.filterIsInstance() - val start = this.entrypoint - val mod = start.definingModule - val block = start.definingBlock - moveModuleToFront(mod) - mod.remove(block) - var afterDirective = mod.statements.indexOfFirst { it !is Directive } + val module = this.entrypoint.definingModule + val block = this.entrypoint.definingBlock + moveModuleToFront(module) + module.remove(block) + val afterDirective = module.statements.indexOfFirst { it !is Directive } if(afterDirective<0) - mod.statements.add(block) + module.statements.add(block) else - mod.statements.add(afterDirective, block) - block.remove(start) - afterDirective = block.statements.indexOfFirst { it !is Directive } - if(afterDirective<0) - block.statements.add(start) - else - block.statements.add(afterDirective, start) - - // overwrite the directives in the module containing the entrypoint - for(directive in directives) { - modules[0].statements.removeAll { it is Directive && it.directive == directive.directive } - modules[0].statements.add(0, directive) - } + module.statements.add(afterDirective, block) } internal fun IdentifierReference.isSubroutineParameter(program: Program): Boolean { diff --git a/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt b/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt index de0c246b4..12f9df98a 100644 --- a/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt +++ b/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt @@ -37,11 +37,6 @@ internal class BeforeAsmAstChanger(val program: Program, } override fun before(block: Block, parent: Node): Iterable { - // move all subroutines to the bottom of the block - val subs = block.statements.filterIsInstance() - block.statements.removeAll(subs) - block.statements.addAll(subs) - // adjust global variables initialization if(options.dontReinitGlobals) { block.statements.asSequence().filterIsInstance().forEach { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index be9a59dea..6619b46e8 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,6 +3,7 @@ TODO For next release ^^^^^^^^^^^^^^^^ +- make it so that uword xx = expr is treated as instead (or inverse order) - ir/vm: allow label in block scope - regression test the various projects - 6502 codegen: make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``p8v_``? Or not worth it (most 3 letter opcodes as variables are nonsensical anyway) diff --git a/examples/test.p8 b/examples/test.p8 index d292b9919..b3989902e 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,8 +1,25 @@ +%import textio +%zeropage basicsafe + main { +alsostart: sub start() { - uword xx = 100 - uword yy = xx / 256 ; TODO hangs in optimizer for 6502 - yy++ + + internalstart: + txt.print_uwhex(start, true) + txt.nl() + txt.print_uwhex(alsostart, true) + txt.nl() + txt.print_uwhex(internalstart, true) + txt.nl() + txt.print_uwhex(startend, true) + txt.nl() + txt.print_uwhex(internalend, true) + txt.nl() + internalend: } + +startend: + } diff --git a/intermediate/src/prog8/intermediate/IRProgram.kt b/intermediate/src/prog8/intermediate/IRProgram.kt index 3a07388fb..4378b2762 100644 --- a/intermediate/src/prog8/intermediate/IRProgram.kt +++ b/intermediate/src/prog8/intermediate/IRProgram.kt @@ -222,6 +222,11 @@ class IRBlock( operator fun plusAssign(sub: IRAsmSubroutine) { asmSubroutines += sub } operator fun plusAssign(asm: IRInlineAsmChunk) { inlineAssemblies += asm } operator fun plusAssign(binary: IRInlineBinaryChunk) { inlineBinaries += binary } + operator fun plusAssign(irCodeChunk: IRCodeChunk) { + // this is for a separate label in the block scope. (random code statements are not allowed) + require(irCodeChunk.isEmpty() && irCodeChunk.label!=null) + TODO("allow labels in block scope, ${irCodeChunk.label}") + } fun isEmpty(): Boolean { val noAsm = inlineAssemblies.isEmpty() || inlineAssemblies.all { it.isEmpty() } @@ -230,6 +235,7 @@ class IRBlock( val noBins = inlineBinaries.isEmpty() || inlineBinaries.all { it.isEmpty() } return noAsm && noSubs && noAsmSubs && noBins } + } class IRSubroutine(val name: String,