added subroutine params to IRSubroutine

This commit is contained in:
Irmen de Jong 2022-09-11 22:34:36 +02:00
parent 30a42ec1bd
commit 6428ced157
7 changed files with 105 additions and 30 deletions

View File

@ -8,7 +8,7 @@ class PtAsmSub(
val address: UInt?,
val clobbers: Set<CpuRegister>,
val parameters: List<Pair<PtSubroutineParameter, RegisterOrStatusflag>>,
val returnTypes: List<DataType>,
val returnTypes: List<DataType>, // TODO join with register as Pairs ?
val retvalRegisters: List<RegisterOrStatusflag>,
val inline: Boolean,
position: Position

View File

@ -863,14 +863,14 @@ class CodeGen(internal val program: PtProgram,
}
private fun translate(block: PtBlock): IRBlock {
val vmblock = IRBlock(block.name, block.address, block.alignment, block.position) // no use for other attributes yet?
val vmblock = IRBlock(block.name, block.address, translate(block.alignment), block.position) // no use for other attributes yet?
for (child in block.children) {
when(child) {
is PtNop -> { /* nothing */ }
is PtAssignment -> { /* global variable initialization is done elsewhere */ }
is PtScopeVarsDecls -> { /* vars should be looked up via symbol table */ }
is PtSub -> {
val vmsub = IRSubroutine(child.name, child.returntype, child.position)
val vmsub = IRSubroutine(child.name, translate(child.parameters), child.returntype, child.position)
for (subchild in child.children) {
val translated = translateNode(subchild)
if(translated.isNotEmpty())
@ -880,7 +880,11 @@ class CodeGen(internal val program: PtProgram,
}
is PtAsmSub -> {
val assembly = if(child.children.isEmpty()) "" else (child.children.single() as PtInlineAssembly).assembly
vmblock += IRAsmSubroutine(child.name, child.position, child.address, assembly)
vmblock += IRAsmSubroutine(child.name, child.position, child.address,
child.clobbers,
child.parameters.map { IRAsmSubroutine.IRAsmSubParam(it.first.name, it.first.type, it.second) },
child.returnTypes.zip(child.retvalRegisters),
assembly)
}
is PtInlineAssembly -> {
vmblock += IRInlineAsmChunk(child.assembly, child.position)
@ -891,6 +895,20 @@ class CodeGen(internal val program: PtProgram,
return vmblock
}
private fun translate(parameters: List<PtSubroutineParameter>) =
parameters.map {
val flattenedName = (it.definingSub()!!.scopedName + it.name)
symbolTable.flat.getValue(flattenedName) as StStaticVariable
}
private fun translate(alignment: PtBlock.BlockAlignment): IRBlock.BlockAlignment {
return when(alignment) {
PtBlock.BlockAlignment.NONE -> IRBlock.BlockAlignment.NONE
PtBlock.BlockAlignment.WORD -> IRBlock.BlockAlignment.WORD
PtBlock.BlockAlignment.PAGE -> IRBlock.BlockAlignment.PAGE
}
}
internal fun vmType(type: DataType): VmDataType {
return when(type) {

View File

@ -302,6 +302,8 @@ class IntermediateAstMaker(val program: Program) {
srcSub.asmReturnvaluesRegisters,
srcSub.inline,
srcSub.position)
sub.parameters.forEach { it.first.parent=sub }
if(srcSub.asmAddress==null) {
var combinedAsm = ""
for (asm in srcSub.statements)
@ -322,6 +324,7 @@ class IntermediateAstMaker(val program: Program) {
srcSub.returntypes.singleOrNull(),
srcSub.inline,
srcSub.position)
sub.parameters.forEach { it.parent=sub }
if(vardecls.isNotEmpty()) sub.add(makeScopeVarsDecls(vardecls, sub.position))
for (statement in statements)

View File

@ -55,10 +55,10 @@ a_label:
qq=global1
qq=other.global2
nested()
nested(11,22)
main.start.nested.nested2()
sub nested() {
sub nested(ubyte a1, ubyte a2) {
qq++
txt.print("zzz")
nested2()

View File

@ -1,7 +1,6 @@
package prog8.intermediate
import prog8.code.*
import prog8.code.ast.PtBlock
import prog8.code.core.*
import prog8.code.target.*
import java.nio.file.Path
@ -30,7 +29,7 @@ class IRFileReader(outputDir: Path, programName: String) {
val memorymapped = parseMemMapped(lines)
val slabs = parseSlabs(lines)
val initGlobals = parseInitGlobals(lines)
val blocks = parseBlocksUntilProgramEnd(lines)
val blocks = parseBlocksUntilProgramEnd(lines, variables)
val st = SymbolTable()
variables.forEach { st.add(it) }
@ -226,7 +225,7 @@ class IRFileReader(outputDir: Path, programName: String) {
return chunk
}
private fun parseBlocksUntilProgramEnd(lines: Iterator<String>): List<IRBlock> {
private fun parseBlocksUntilProgramEnd(lines: Iterator<String>, variables: List<StStaticVariable>): List<IRBlock> {
val blocks = mutableListOf<IRBlock>()
while(true) {
var line = lines.next()
@ -234,27 +233,27 @@ class IRFileReader(outputDir: Path, programName: String) {
line = lines.next()
if (line == "</PROGRAM>")
break
blocks.add(parseBlock(line, lines))
blocks.add(parseBlock(line, lines, variables))
}
return blocks
}
private val blockPattern = Regex("<BLOCK NAME=(.+) ADDRESS=(.+) ALIGN=(.+) POS=(.+)>")
private val inlineAsmPattern = Regex("<INLINEASM POS=(.+)>")
private val asmsubPattern = Regex("<ASMSUB NAME=(.+) ADDRESS=(.+) POS=(.+)>")
private val asmsubPattern = Regex("<ASMSUB NAME=(.+) ADDRESS=(.+) CLOBBERS=(.+) POS=(.+)>")
private val subPattern = Regex("<SUB NAME=(.+) RETURNTYPE=(.+) POS=(.+)>")
private val posPattern = Regex("\\[(.+): line (.+) col (.+)-(.+)\\]")
private val instructionPattern = Regex("""([a-z]+)(\.b|\.w|\.f)?(.*)""", RegexOption.IGNORE_CASE)
private val labelPattern = Regex("""_([a-zA-Z\d\._]+):""")
private fun parseBlock(startline: String, lines: Iterator<String>): IRBlock {
private fun parseBlock(startline: String, lines: Iterator<String>, variables: List<StStaticVariable>): IRBlock {
var line = startline
if(!line.startsWith("<BLOCK "))
throw IRParseException("invalid BLOCK")
val match = blockPattern.matchEntire(line) ?: throw IRParseException("invalid BLOCK")
val (name, address, align, position) = match.destructured
val addressNum = if(address=="null") null else address.toUInt()
val block = IRBlock(name, addressNum, PtBlock.BlockAlignment.valueOf(align), parsePosition(position))
val block = IRBlock(name, addressNum, IRBlock.BlockAlignment.valueOf(align), parsePosition(position))
while(true) {
line = lines.next()
if(line.isBlank())
@ -262,7 +261,7 @@ class IRFileReader(outputDir: Path, programName: String) {
if(line=="</BLOCK>")
return block
if(line.startsWith("<SUB ")) {
val sub = parseSubroutine(line, lines)
val sub = parseSubroutine(line, lines, variables)
block += sub
} else if(line.startsWith("<ASMSUB ")) {
val sub = parseAsmSubroutine(line, lines)
@ -289,23 +288,33 @@ class IRFileReader(outputDir: Path, programName: String) {
}
private fun parseAsmSubroutine(startline: String, lines: Iterator<String>): IRAsmSubroutine {
// <ASMSUB NAME=main.testasmsub ADDRESS=null POS=[examples/test.p8: line 14 col 6-11]>
// TODO parse more signature stuff once it's there.
// <ASMSUB NAME=main.testasmsub ADDRESS=null CLOBBERS=A,Y POS=[examples/test.p8: line 14 col 6-11]>
val match = asmsubPattern.matchEntire(startline) ?: throw IRParseException("invalid ASMSUB")
val (scopedname, address, pos) = match.destructured
val (scopedname, address, clobbers, pos) = match.destructured
var line = lines.next()
val asm = parseInlineAssembly(line, lines)
while(line!="</ASMSUB>")
line = lines.next()
return IRAsmSubroutine(scopedname, parsePosition(pos), if(address=="null") null else address.toUInt(), asm.asm)
val clobberRegs = clobbers.split(',').map { CpuRegister.valueOf(it) }
// TODO parse this additional signature stuff once it's there.
val parameters = mutableListOf<IRAsmSubroutine.IRAsmSubParam>()
val returns = mutableListOf<Pair<DataType, RegisterOrStatusflag>>()
return IRAsmSubroutine(scopedname,
parsePosition(pos), if(address=="null") null else address.toUInt(),
clobberRegs.toSet(),
parameters,
returns,
asm.asm)
}
private fun parseSubroutine(startline: String, lines: Iterator<String>): IRSubroutine {
private fun parseSubroutine(startline: String, lines: Iterator<String>, variables: List<StStaticVariable>): IRSubroutine {
// <SUB NAME=main.start.nested.nested2 RETURNTYPE=null POS=[examples/test.p8: line 54 col 14-16]>
// TODO parse more signature stuff once it's there.
val match = subPattern.matchEntire(startline) ?: throw IRParseException("invalid SUB")
val (name, returntype, pos) = match.destructured
val sub = IRSubroutine(name, if(returntype=="null") null else parseDatatype(returntype, false), parsePosition(pos))
val sub = IRSubroutine(name,
parseParameters(lines, variables),
if(returntype=="null") null else parseDatatype(returntype, false),
parsePosition(pos))
while(true) {
val line = lines.next()
if(line=="</SUB>")
@ -328,6 +337,21 @@ class IRFileReader(outputDir: Path, programName: String) {
return sub
}
private fun parseParameters(lines: Iterator<String>, variables: List<StStaticVariable>): List<StStaticVariable> {
var line = lines.next()
if(line!="<PARAMS>")
throw IRParseException("missing PARAMS")
val params = mutableListOf<StStaticVariable>()
while(true) {
line = lines.next()
if(line=="</PARAMS>")
return params
val (datatype, name) = line.split(' ')
val dt = parseDatatype(datatype, datatype.contains('['))
params.add(variables.single { it.dt==dt && it.name==name})
}
}
private fun parseCodeChunk(firstline: String, lines: Iterator<String>): IRCodeChunk? {
if(firstline!="<C>") {
if(firstline=="</SUB>")

View File

@ -39,7 +39,9 @@ class IRFileWriter(private val irProgram: IRProgram) {
}
block.subroutines.forEach {
out.write("<SUB NAME=${it.name} RETURNTYPE=${it.returnType.toString().lowercase()} POS=${it.position}>\n")
// TODO rest of the signature
out.write("<PARAMS>\n")
it.parameters.forEach { param -> out.write("${getTypeString(param)} ${param.scopedName.joinToString(".")}\n") }
out.write("</PARAMS>\n")
it.chunks.forEach { chunk ->
if(chunk is IRInlineAsmChunk) {
writeInlineAsm(chunk)
@ -54,8 +56,9 @@ class IRFileWriter(private val irProgram: IRProgram) {
out.write("</SUB>\n")
}
block.asmSubroutines.forEach {
out.write("<ASMSUB NAME=${it.name} ADDRESS=${it.address} POS=${it.position}>\n")
// TODO rest of the signature
val clobbers = it.clobbers.joinToString(",")
out.write("<ASMSUB NAME=${it.name} ADDRESS=${it.address} CLOBBERS=$clobbers POS=${it.position}>\n")
// TODO rest of the signature: RETURNS = it.returns
out.write("<INLINEASM POS=${it.position}>\n")
out.write(it.assembly.trimStart('\n').trimEnd(' ', '\n'))
out.write("\n</INLINEASM>\n</ASMSUB>\n")
@ -130,6 +133,22 @@ class IRFileWriter(private val irProgram: IRProgram) {
out.write("</MEMORYSLABS>\n")
}
private fun getTypeString(dt : DataType): String {
return when(dt) {
DataType.UBYTE -> "ubyte"
DataType.BYTE -> "byte"
DataType.UWORD -> "uword"
DataType.WORD -> "word"
DataType.FLOAT -> "float"
DataType.ARRAY_UB, DataType.STR -> "ubyte[]"
DataType.ARRAY_B -> "byte[]"
DataType.ARRAY_UW -> "uword[]"
DataType.ARRAY_W -> "word[]"
DataType.ARRAY_F -> "float[]"
else -> throw InternalCompilerException("weird dt")
}
}
private fun getTypeString(memvar: StMemVar): String {
return when(memvar.dt) {
DataType.UBYTE -> "ubyte"

View File

@ -1,11 +1,8 @@
package prog8.intermediate
import prog8.code.StStaticVariable
import prog8.code.SymbolTable
import prog8.code.ast.PtBlock
import prog8.code.core.CompilationOptions
import prog8.code.core.DataType
import prog8.code.core.IStringEncoding
import prog8.code.core.Position
import prog8.code.core.*
/*
@ -25,6 +22,7 @@ PROGRAM:
INLINEASM
INLINEASM
SUB
PARAMS
INLINEASM
INLINEASM
C (CODE)
@ -65,13 +63,19 @@ class IRProgram(val name: String,
class IRBlock(
val name: String,
val address: UInt?,
val alignment: PtBlock.BlockAlignment,
val alignment: BlockAlignment,
val position: Position
) {
val subroutines = mutableListOf<IRSubroutine>()
val asmSubroutines = mutableListOf<IRAsmSubroutine>()
val inlineAssembly = mutableListOf<IRInlineAsmChunk>()
enum class BlockAlignment {
NONE,
WORD,
PAGE
}
operator fun plusAssign(sub: IRSubroutine) {
subroutines += sub
}
@ -80,8 +84,10 @@ class IRBlock(
}
class IRSubroutine(val name: String,
val parameters: List<StStaticVariable>, // NOTE: these are the same objects as their occurrences as variables in the symbol table
val returnType: DataType?,
val position: Position) {
val chunks = mutableListOf<IRCodeChunkBase>()
init {
@ -97,6 +103,9 @@ class IRSubroutine(val name: String,
class IRAsmSubroutine(val name: String,
val position: Position,
val address: UInt?,
val clobbers: Set<CpuRegister>,
val parameters: List<IRAsmSubParam>,
val returns: List<Pair<DataType, RegisterOrStatusflag>>,
val assembly: String) {
val lines = mutableListOf<IRCodeLine>()
@ -106,6 +115,8 @@ class IRAsmSubroutine(val name: String,
if(name.startsWith("main.main."))
throw IllegalArgumentException("subroutine name invalid main prefix: $name")
}
class IRAsmSubParam(val name: String, val dt: DataType, val reg: RegisterOrStatusflag)
}
sealed class IRCodeLine