diff --git a/codeGenExperimental/src/prog8/codegen/experimental/BuiltinFuncGen.kt b/codeGenExperimental/src/prog8/codegen/experimental/BuiltinFuncGen.kt index 4394e0a30..a1483a335 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/BuiltinFuncGen.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/BuiltinFuncGen.kt @@ -327,7 +327,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: val align = (call.args[2] as PtNumber).number.toUInt() val label = codeGen.addMemorySlab(name, size, align, call.position) val code = VmCodeChunk() - code += VmCodeInstruction(Opcode.LOAD, VmDataType.WORD, reg1=resultRegister, labelSymbol = label) + code += VmCodeInstruction(Opcode.LOAD, VmDataType.WORD, reg1=resultRegister, labelSymbol = listOf(label)) return code } diff --git a/codeGenExperimental/src/prog8/codegen/experimental/CodeGen.kt b/codeGenExperimental/src/prog8/codegen/experimental/CodeGen.kt index cfd55a82c..3efd8213b 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/CodeGen.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/CodeGen.kt @@ -775,15 +775,13 @@ class CodeGen(internal val program: PtProgram, return code } - private fun translate(block: PtBlock): VmCodeChunk { - val code = VmCodeChunk() - code += VmCodeComment("BLOCK '${block.name}' addr=${block.address} lib=${block.library}") + private fun translate(block: PtBlock): VmBlock { + val vmblock = VmBlock(block.name, block.address, block.alignment) // no use for other attributes yet? for (child in block.children) { if(child !is PtAssignment) // global variable initialization is done elsewhere - code += translateNode(child) + vmblock += translateNode(child) } - code += VmCodeComment("BLOCK-END '${block.name}'") - return code + return vmblock } @@ -813,10 +811,10 @@ class CodeGen(internal val program: PtProgram, internal fun isOne(expression: PtExpression): Boolean = expression is PtNumber && expression.number==1.0 - fun addMemorySlab(name: String, size: UInt, align: UInt, position: Position): List { - val scopedName = "prog8_memoryslabs.$name" - symbolTable.add(StMemorySlab(scopedName, size, align, position)) - return scopedName.split('.', limit=2) + fun addMemorySlab(name: String, size: UInt, align: UInt, position: Position): String { + val scopedName = "prog8_memoryslab_$name" + symbolTable.add(StMemorySlab(scopedName, size, align, null, position)) + return scopedName } } diff --git a/codeGenExperimental/src/prog8/codegen/experimental/IRProgram.kt b/codeGenExperimental/src/prog8/codegen/experimental/IRProgram.kt index a8313bf08..acfb7826f 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/IRProgram.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/IRProgram.kt @@ -1,6 +1,7 @@ package prog8.codegen.experimental import prog8.code.SymbolTable +import prog8.code.ast.PtBlock import prog8.code.core.* import prog8.vm.Instruction import prog8.vm.Opcode @@ -20,28 +21,50 @@ class IRProgram(val name: String, private val st: SymbolTable) { private val globalInits = mutableListOf() - private val blocks = mutableListOf() + private val blocks = mutableListOf() fun writeFile() { val outfile = options.outputDir / ("$name.p8ir") println("Writing intermediate representation to $outfile") outfile.bufferedWriter().use { out -> + out.write("; PROGRAM '$name'\n") + writeOptions(out) writeVariableAllocations(out) - out.write("------PROGRAM------\n") if(!options.dontReinitGlobals) { - out.write("; global var inits\n") + // note: this a block of code that loads values and stores them into the global variables to reset their values. + out.write("\n[INITGLOBALS]\n") globalInits.forEach { out.writeLine(it) } + out.write("[/INITGLOBALS]\n") } - out.write("; actual program code\n") - blocks.asSequence().flatMap { it.lines }.forEach { line->out.writeLine(line) } + out.write("\n[CODE]\n") + blocks.forEach { block -> + out.write("\n[BLOCK NAME=${block.name} ADDRESS=${block.address} ALIGN=${block.alignment}]\n") + block.lines.forEach { out.writeLine(it) } + out.write("[/BLOCK]\n") + } + out.write("[/CODE]\n") } } + private fun writeOptions(out: BufferedWriter) { + out.write("[OPTIONS]\n") + out.write("compTarget = ${options.compTarget.name}\n") + out.write("output = ${options.output}\n") + out.write("launcher = ${options.launcher}\n") + out.write("zeropage = ${options.zeropage}\n") + out.write("zpReserved = ${options.zpReserved}\n") + out.write("loadAddress = ${options.loadAddress}\n") + out.write("dontReinitGlobals = ${options.dontReinitGlobals}\n") + out.write("evalStackBaseAddress = ${options.evalStackBaseAddress}\n") + // other options not yet useful here? + out.write("[/OPTIONS]\n") + } + private fun writeVariableAllocations(out: Writer) { - out.write("; NORMAL VARIABLES\n") + out.write("\n[VARIABLES]\n") for (variable in st.allVariables) { val typeStr = when(variable.dt) { DataType.UBYTE, DataType.ARRAY_UB, DataType.STR -> "ubyte" @@ -77,8 +100,9 @@ class IRProgram(val name: String, // TODO have uninitialized variables? (BSS SECTION) out.write("VAR ${variable.scopedName.joinToString(".")} $typeStr = $value\n") } + out.write("[/VARIABLES]\n") - out.write("; MEMORY MAPPED VARIABLES\n") + out.write("\n[MEMORYMAPPEDVARIABLES]\n") for (variable in st.allMemMappedVariables) { val typeStr = when(variable.dt) { DataType.UBYTE, DataType.ARRAY_UB, DataType.STR -> "ubyte" @@ -90,9 +114,11 @@ class IRProgram(val name: String, } out.write("MAP ${variable.scopedName.joinToString(".")} $typeStr ${variable.address}\n") } + out.write("[/MEMORYMAPPEDVARIABLES]\n") - out.write("; MEMORY SLABS\n") - st.allMemorySlabs.forEach{ slab -> out.write("MEMORYSLAB _${slab.name} ${slab.size} ${slab.align}\n") } + out.write("\n[MEMORYSLABS]\n") + st.allMemorySlabs.forEach{ slab -> out.write("SLAB _${slab.name} ${slab.size} ${slab.align}\n") } + out.write("[/MEMORYSLABS]\n") } private fun BufferedWriter.writeLine(line: VmCodeLine) { @@ -119,8 +145,8 @@ class IRProgram(val name: String, } fun addGlobalInits(chunk: VmCodeChunk) = globalInits.addAll(chunk.lines) - fun addBlock(block: VmCodeChunk) = blocks.add(block) - fun getBlocks(): List = blocks + fun addBlock(block: VmBlock) = blocks.add(block) + fun getBlocks(): List = blocks } sealed class VmCodeLine @@ -167,7 +193,16 @@ class VmCodeInstruction( class VmCodeLabel(val name: List): VmCodeLine() internal class VmCodeComment(val comment: String): VmCodeLine() -class VmCodeChunk(initial: VmCodeLine? = null) { + +class VmBlock( + val name: String, + val address: UInt?, + val alignment: PtBlock.BlockAlignment, + initial: VmCodeLine? = null +): VmCodeChunk(initial) + + +open class VmCodeChunk(initial: VmCodeLine? = null) { val lines = mutableListOf() init { diff --git a/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt b/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt index cf8fe344a..b780823d3 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt @@ -49,6 +49,7 @@ class AssemblyProgram(override val name: String, private val allocations: Variab is VmCodeLabel -> write("_" + line.name.joinToString(".") + ":\n") is VmCodeInlineAsm -> { val asm = line.assembly.replace("""\{[a-zA-Z\d_\.]+\}""".toRegex()) { matchResult -> + // "{ X }" -> address of X val name = matchResult.value.substring(1, matchResult.value.length-1).split('.') allocations.get(name).toString() } write(asm+"\n") diff --git a/examples/test.p8 b/examples/test.p8 index 7e360e155..5202fc1d4 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,4 +1,7 @@ main { + + uword global1 = 1234 + sub start() { ; TODO should generate address @@ -13,5 +16,14 @@ main { qq=4242 ; TODO should generate symbol not allocated address c64.EXTCOL = 42 ; TODO wrong VMASM code generated... should generate mapped memory address + + qq=global1 + qq=other.global2 } } + +other { + + uword global2 = 9999 + +}