mirror of
https://github.com/irmen/prog8.git
synced 2025-04-07 01:38:09 +00:00
comments
This commit is contained in:
parent
101b33c381
commit
12ed07a607
@ -47,6 +47,9 @@ class CodeGen(internal val program: PtProgram,
|
||||
internal val vmRegisters = VmRegisterPool()
|
||||
|
||||
override fun compileToAssembly(): IAssemblyProgram? {
|
||||
|
||||
flattenNestedSubroutines()
|
||||
|
||||
val irProg = IRProgram(program.name, symbolTable, options, program.encoding)
|
||||
|
||||
if(!options.dontReinitGlobals) {
|
||||
@ -80,6 +83,56 @@ class CodeGen(internal val program: PtProgram,
|
||||
return DummyAssemblyProgram(irProg.name)
|
||||
}
|
||||
|
||||
private fun flattenNestedSubroutines() {
|
||||
// this moves all nested subroutines up to the block scope.
|
||||
val flattenedSubs = mutableListOf<Pair<PtBlock, PtSub>>()
|
||||
val flattenedAsmSubs = mutableListOf<Pair<PtBlock, PtAsmSub>>()
|
||||
val removalsSubs = mutableListOf<Pair<PtSub, PtSub>>()
|
||||
val removalsAsmSubs = mutableListOf<Pair<PtSub, PtAsmSub>>()
|
||||
|
||||
fun flattenNestedAsm(block: PtBlock, parentSub: PtSub, asmsub: PtAsmSub) {
|
||||
val flattened = PtAsmSub(asmsub.scopedName.joinToString("."),
|
||||
asmsub.address,
|
||||
asmsub.clobbers,
|
||||
asmsub.parameters,
|
||||
asmsub.returnTypes,
|
||||
asmsub.retvalRegisters,
|
||||
asmsub.inline,
|
||||
asmsub.position)
|
||||
asmsub.children.forEach { flattened.add(it) }
|
||||
flattenedAsmSubs += Pair(block, flattened)
|
||||
removalsAsmSubs += Pair(parentSub, asmsub)
|
||||
}
|
||||
|
||||
fun flattenNested(block: PtBlock, parentSub: PtSub, sub: PtSub) {
|
||||
sub.children.filterIsInstance<PtSub>().forEach { subsub->flattenNested(block, sub, subsub) }
|
||||
sub.children.filterIsInstance<PtAsmSub>().forEach { asmsubsub->flattenNestedAsm(block, sub, asmsubsub) }
|
||||
val flattened = PtSub(sub.scopedName.joinToString("."),
|
||||
sub.parameters,
|
||||
sub.returntype,
|
||||
sub.inline,
|
||||
sub.position)
|
||||
sub.children.forEach { if(it !is PtSub) flattened.add(it) }
|
||||
flattenedSubs += Pair(block, flattened)
|
||||
removalsSubs += Pair(parentSub, sub)
|
||||
}
|
||||
|
||||
program.allBlocks().forEach { block ->
|
||||
block.children.forEach {
|
||||
if(it is PtSub) {
|
||||
// Only regular subroutines can have nested subroutines.
|
||||
it.children.filterIsInstance<PtSub>().forEach { subsub->flattenNested(block, it, subsub)}
|
||||
it.children.filterIsInstance<PtAsmSub>().forEach { asmsubsub->flattenNestedAsm(block, it, asmsubsub)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removalsSubs.forEach { (parent, sub) -> parent.children.remove(sub) }
|
||||
removalsAsmSubs.forEach { (parent, asmsub) -> parent.children.remove(asmsub) }
|
||||
flattenedSubs.forEach { (block, sub) -> block.add(sub) }
|
||||
flattenedAsmSubs.forEach { (block, asmsub) -> block.add(asmsub) }
|
||||
}
|
||||
|
||||
|
||||
internal fun translateNode(node: PtNode): IRCodeChunk {
|
||||
val code = when(node) {
|
||||
@ -651,7 +704,6 @@ class CodeGen(internal val program: PtProgram,
|
||||
translateNonZeroComparison()
|
||||
}
|
||||
|
||||
|
||||
private fun translate(postIncrDecr: PtPostIncrDecr): IRCodeChunk {
|
||||
val code = IRCodeChunk(postIncrDecr.position)
|
||||
val operationMem: Opcode
|
||||
@ -771,7 +823,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
is PtAssignment -> { /* global variable initialization is done elsewhere */ }
|
||||
is PtScopeVarsDecls -> { /* vars should be looked up via symbol table */ }
|
||||
is PtSub -> {
|
||||
val vmsub = IRSubroutine(child.scopedName, child.returntype, child.position)
|
||||
val vmsub = IRSubroutine(child.name, child.returntype, child.position)
|
||||
for (line in child.children) {
|
||||
vmsub += translateNode(line)
|
||||
}
|
||||
@ -823,4 +875,3 @@ class CodeGen(internal val program: PtProgram,
|
||||
return scopedName
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,11 +20,19 @@ main {
|
||||
|
||||
qq=global1
|
||||
qq=other.global2
|
||||
; nested()
|
||||
nested()
|
||||
main.start.nested.nested2()
|
||||
|
||||
; TODO flatten nested subroutines in codegen
|
||||
sub nested() {
|
||||
qq++
|
||||
txt.print("zzz")
|
||||
nested2()
|
||||
|
||||
sub nested2() {
|
||||
txt.print("zzz2")
|
||||
qq++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
@ -37,7 +37,7 @@ class IRFileWriter(private val irProgram: IRProgram) {
|
||||
out.write("</INLINEASM>\n")
|
||||
}
|
||||
block.subroutines.forEach {
|
||||
out.write("<SUB SCOPEDNAME=${it.scopedName.joinToString(".")} RETURNTYPE=${it.returnType} POS=${it.position}>\n")
|
||||
out.write("<SUB NAME=${it.name} RETURNTYPE=${it.returnType} POS=${it.position}>\n")
|
||||
it.lines.forEach { line -> out.writeLine(line) }
|
||||
out.write("</SUB>\n")
|
||||
}
|
||||
|
@ -8,7 +8,33 @@ import prog8.code.core.IStringEncoding
|
||||
import prog8.code.core.Position
|
||||
import java.nio.file.Path
|
||||
|
||||
// TODO: move this Intermedate Representation into the actual compiler core, code gen modules can receive it as input rather than an Ast.
|
||||
/*
|
||||
PROGRAM:
|
||||
OPTIONS (from CompilationOptions)
|
||||
VARIABLES (from Symboltable)
|
||||
MEMORYMAPPEDVARIABLES (from Symboltable)
|
||||
MEMORYSLABS (from Symboltable)
|
||||
GLOBALINITS
|
||||
CODE-LINE (assignment to initialize a variable)
|
||||
CODE-LINE (assignment to initialize a variable)
|
||||
...
|
||||
BLOCK
|
||||
INLINEASM
|
||||
INLINEASM
|
||||
SUB
|
||||
CODE-LINE (label, instruction, comment, inlinebinary)
|
||||
CODE-LINE
|
||||
CODE-LINE
|
||||
...
|
||||
SUB
|
||||
SUB
|
||||
ASMSUB
|
||||
ASMSUB
|
||||
...
|
||||
BLOCK
|
||||
BLOCK
|
||||
...
|
||||
*/
|
||||
|
||||
class IRProgram(val name: String,
|
||||
val st: SymbolTable,
|
||||
@ -35,22 +61,16 @@ class IRBlock(
|
||||
operator fun plusAssign(sub: IRSubroutine) {
|
||||
subroutines += sub
|
||||
}
|
||||
operator fun plusAssign(sub: IRAsmSubroutine) {
|
||||
asmSubroutines += sub
|
||||
}
|
||||
operator fun plusAssign(asm: IRInlineAsmChunk) {
|
||||
inlineAssembly += asm
|
||||
}
|
||||
operator fun plusAssign(sub: IRAsmSubroutine) { asmSubroutines += sub }
|
||||
operator fun plusAssign(asm: IRInlineAsmChunk) { inlineAssembly += asm }
|
||||
}
|
||||
|
||||
class IRSubroutine(val scopedName: List<String>,
|
||||
class IRSubroutine(val name: String,
|
||||
val returnType: DataType?,
|
||||
val position: Position) {
|
||||
val lines = mutableListOf<IRCodeLine>()
|
||||
|
||||
operator fun plusAssign(chunk: IRCodeChunk) {
|
||||
lines += chunk.lines
|
||||
}
|
||||
operator fun plusAssign(chunk: IRCodeChunk) { lines += chunk.lines }
|
||||
}
|
||||
|
||||
class IRAsmSubroutine(val scopedName: List<String>,
|
||||
|
@ -2,15 +2,18 @@ package prog8.intermediate
|
||||
|
||||
/*
|
||||
|
||||
Virtual machine:
|
||||
Intermediate Representation instructions for the IR Virtual machine.
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Specs of the virtual machine this will run on:
|
||||
Program to execute is not stored in the system memory, it's just a separate list of instructions.
|
||||
65536 virtual registers, 16 bits wide, can also be used as 8 bits. r0-r65535
|
||||
65536 virtual floating point registers (32 bits single precision floats) fr0-fr65535
|
||||
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
|
||||
Value stack, max 128 entries of 1 byte each.
|
||||
Status flags: Carry, Zero, Negative. NOTE: status flags are only affected by the CMP instruction or explicit CLC/SEC!!!
|
||||
logical or arithmetic operations DO NOT AFFECT THE STATUS FLAGS UNLESS EXPLICITLY NOTED!
|
||||
Program to execute is not stored in this memory, it's just a separate list of instructions.
|
||||
|
||||
Most instructions have an associated data type 'b','w','f'. (omitting it means 'b'/byte).
|
||||
Currently NO support for 24 or 32 bits integers.
|
||||
Floating point operations are just 'f' typed regular instructions, and additionally there are a few fp conversion instructions
|
||||
|
@ -10,6 +10,19 @@ import java.util.*
|
||||
import kotlin.math.*
|
||||
import kotlin.random.Random
|
||||
|
||||
/*
|
||||
|
||||
Virtual machine specs:
|
||||
|
||||
Program to execute is not stored in the system memory, it's just a separate list of instructions.
|
||||
65536 virtual registers, 16 bits wide, can also be used as 8 bits. r0-r65535
|
||||
65536 virtual floating point registers (32 bits single precision floats) fr0-fr65535
|
||||
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
|
||||
Value stack, max 128 entries of 1 byte each.
|
||||
Status flags: Carry, Zero, Negative. NOTE: status flags are only affected by the CMP instruction or explicit CLC/SEC!!!
|
||||
logical or arithmetic operations DO NOT AFFECT THE STATUS FLAGS UNLESS EXPLICITLY NOTED!
|
||||
|
||||
*/
|
||||
|
||||
class ProgramExitException(val status: Int): Exception()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user