main block element order now remains the same as in source

This commit is contained in:
Irmen de Jong 2022-11-15 18:51:52 +01:00
parent df1793efbf
commit 922033c1b2
8 changed files with 40 additions and 43 deletions

View File

@ -202,16 +202,10 @@ internal class ProgramAndVarsGen(
asmsubs2asm(block.statements) asmsubs2asm(block.statements)
asmgen.out("") 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 initializers = blockVariableInitializers.getValue(block)
val statements = block.statements.filterNot { it in initializers } val notInitializers = block.statements.filterNot { it in initializers }
val (subroutine, stmts) = statements.partition { it is Subroutine } notInitializers.forEach { asmgen.translate(it) }
stmts.forEach { asmgen.translate(it) }
subroutine.forEach { asmgen.translate(it) }
if(!options.dontReinitGlobals) { if(!options.dontReinitGlobals) {
// generate subroutine to initialize block-level (global) variables // generate subroutine to initialize block-level (global) variables

View File

@ -1122,7 +1122,7 @@ class IRCodeGen(
irBlock += IRInlineBinaryChunk(null, readBinaryData(child), null) irBlock += IRInlineBinaryChunk(null, readBinaryData(child), null)
} }
is PtLabel -> { is PtLabel -> {
TODO("allow label inside block scope ${child.name}") irBlock += IRCodeChunk(child.name, null)
} }
else -> TODO("weird child node $child") else -> TODO("weird child node $child")
} }

View File

@ -382,7 +382,7 @@ private fun postprocessAst(program: Program, errors: IErrorReporter, compilerOpt
callGraph.checkRecursiveCalls(errors) callGraph.checkRecursiveCalls(errors)
program.verifyFunctionArgTypes(errors) program.verifyFunctionArgTypes(errors)
errors.report() errors.report()
program.moveMainAndStartToFirst() program.moveMainBlockAsFirst()
program.checkValid(errors, compilerOptions) // check if final tree is still valid program.checkValid(errors, compilerOptions) // check if final tree is still valid
errors.report() errors.report()
} }

View File

@ -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 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, // 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.
// sortModules() val module = this.entrypoint.definingModule
val directives = modules[0].statements.filterIsInstance<Directive>() val block = this.entrypoint.definingBlock
val start = this.entrypoint moveModuleToFront(module)
val mod = start.definingModule module.remove(block)
val block = start.definingBlock val afterDirective = module.statements.indexOfFirst { it !is Directive }
moveModuleToFront(mod)
mod.remove(block)
var afterDirective = mod.statements.indexOfFirst { it !is Directive }
if(afterDirective<0) if(afterDirective<0)
mod.statements.add(block) module.statements.add(block)
else else
mod.statements.add(afterDirective, block) module.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)
}
} }
internal fun IdentifierReference.isSubroutineParameter(program: Program): Boolean { internal fun IdentifierReference.isSubroutineParameter(program: Program): Boolean {

View File

@ -37,11 +37,6 @@ internal class BeforeAsmAstChanger(val program: Program,
} }
override fun before(block: Block, parent: Node): Iterable<IAstModification> { override fun before(block: Block, parent: Node): Iterable<IAstModification> {
// move all subroutines to the bottom of the block
val subs = block.statements.filterIsInstance<Subroutine>()
block.statements.removeAll(subs)
block.statements.addAll(subs)
// adjust global variables initialization // adjust global variables initialization
if(options.dontReinitGlobals) { if(options.dontReinitGlobals) {
block.statements.asSequence().filterIsInstance<VarDecl>().forEach { block.statements.asSequence().filterIsInstance<VarDecl>().forEach {

View File

@ -3,6 +3,7 @@ TODO
For next release For next release
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
- make it so that uword xx = <byte constant> <op> expr is treated as <word constant> <op> <expr> instead (or inverse order)
- ir/vm: allow label in block scope - ir/vm: allow label in block scope
- regression test the various projects - 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) - 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)

View File

@ -1,8 +1,25 @@
%import textio
%zeropage basicsafe
main { main {
alsostart:
sub start() { sub start() {
uword xx = 100
uword yy = xx / 256 ; TODO hangs in optimizer for 6502 internalstart:
yy++ 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:
} }

View File

@ -222,6 +222,11 @@ class IRBlock(
operator fun plusAssign(sub: IRAsmSubroutine) { asmSubroutines += sub } operator fun plusAssign(sub: IRAsmSubroutine) { asmSubroutines += sub }
operator fun plusAssign(asm: IRInlineAsmChunk) { inlineAssemblies += asm } operator fun plusAssign(asm: IRInlineAsmChunk) { inlineAssemblies += asm }
operator fun plusAssign(binary: IRInlineBinaryChunk) { inlineBinaries += binary } 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 { fun isEmpty(): Boolean {
val noAsm = inlineAssemblies.isEmpty() || inlineAssemblies.all { it.isEmpty() } val noAsm = inlineAssemblies.isEmpty() || inlineAssemblies.all { it.isEmpty() }
@ -230,6 +235,7 @@ class IRBlock(
val noBins = inlineBinaries.isEmpty() || inlineBinaries.all { it.isEmpty() } val noBins = inlineBinaries.isEmpty() || inlineBinaries.all { it.isEmpty() }
return noAsm && noSubs && noAsmSubs && noBins return noAsm && noSubs && noAsmSubs && noBins
} }
} }
class IRSubroutine(val name: String, class IRSubroutine(val name: String,