Merge branch 'optimize-st'

# Conflicts:
#	examples/test.p8
This commit is contained in:
Irmen de Jong 2023-12-17 02:11:01 +01:00
commit eba0bde6f3
14 changed files with 330 additions and 250 deletions

View File

@ -1,6 +1,7 @@
package prog8.codegen.cpu6502 package prog8.codegen.cpu6502
import com.github.michaelbull.result.fold import com.github.michaelbull.result.fold
import prog8.code.StNode
import prog8.code.StNodeType import prog8.code.StNodeType
import prog8.code.SymbolTable import prog8.code.SymbolTable
import prog8.code.SymbolTableMaker import prog8.code.SymbolTableMaker
@ -282,6 +283,18 @@ class AsmGen6502Internal (
name name
} }
fun asmVariableName(st: StNode, scope: PtSub?): String {
val name = asmVariableName(st.scopedName)
if(scope==null)
return name
// remove the whole prefix and just make the variable name locally scoped (64tass scopes it to the proper .proc block)
val subName = scope.scopedName
return if (name.length>subName.length && name.startsWith(subName) && name[subName.length] == '.')
name.drop(subName.length+1)
else
name
}
internal fun getTempVarName(dt: DataType): String { internal fun getTempVarName(dt: DataType): String {
return when(dt) { return when(dt) {
DataType.UBYTE -> "cx16.r9L" DataType.UBYTE -> "cx16.r9L"

View File

@ -1,5 +1,6 @@
package prog8.codegen.cpu6502 package prog8.codegen.cpu6502
import prog8.code.StMemVar
import prog8.code.StStaticVariable import prog8.code.StStaticVariable
import prog8.code.ast.* import prog8.code.ast.*
import prog8.code.core.* import prog8.code.core.*
@ -311,106 +312,97 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
} }
private fun funcReverse(fcall: PtBuiltinFunctionCall) { private fun funcReverse(fcall: PtBuiltinFunctionCall) {
val variable = fcall.args.single() val variable = fcall.args.single() as PtIdentifier
if (variable is PtIdentifier) { val symbol = asmgen.symbolTable.lookup(variable.name)
val symbol = asmgen.symbolTable.lookup(variable.name) val (dt, numElements) = when(symbol) {
val decl = symbol!!.astNode as IPtVariable is StStaticVariable -> symbol.dt to symbol.length!!
val numElements = when(decl) { is StMemVar -> symbol.dt to symbol.length!!
is PtConstant -> throw AssemblyError("cannot reverse a constant") else -> DataType.UNDEFINED to 0
is PtMemMapped -> decl.arraySize }
is PtVariable -> decl.arraySize val varName = asmgen.asmVariableName(variable)
when (dt) {
DataType.ARRAY_UB, DataType.ARRAY_B -> {
asmgen.out("""
lda #<$varName
ldy #>$varName
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #$numElements
jsr prog8_lib.func_reverse_b""")
} }
val varName = asmgen.asmVariableName(variable) DataType.ARRAY_UW, DataType.ARRAY_W -> {
when (decl.type) { asmgen.out("""
DataType.ARRAY_UB, DataType.ARRAY_B -> { lda #<$varName
asmgen.out(""" ldy #>$varName
lda #<$varName sta P8ZP_SCRATCH_W1
ldy #>$varName sty P8ZP_SCRATCH_W1+1
sta P8ZP_SCRATCH_W1 lda #$numElements
sty P8ZP_SCRATCH_W1+1 jsr prog8_lib.func_reverse_w""")
lda #$numElements
jsr prog8_lib.func_reverse_b""")
}
DataType.ARRAY_UW, DataType.ARRAY_W -> {
asmgen.out("""
lda #<$varName
ldy #>$varName
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #$numElements
jsr prog8_lib.func_reverse_w""")
}
DataType.STR -> {
val stringLength = (symbol as StStaticVariable).length!!-1
asmgen.out("""
lda #<$varName
ldy #>$varName
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #$stringLength
jsr prog8_lib.func_reverse_b""")
}
DataType.ARRAY_F -> {
asmgen.out("""
lda #<$varName
ldy #>$varName
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #$numElements
jsr floats.func_reverse_f""")
}
in SplitWordArrayTypes -> TODO("split word reverse")
else -> throw AssemblyError("weird type")
} }
DataType.STR -> {
asmgen.out("""
lda #<$varName
ldy #>$varName
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #${numElements-1}
jsr prog8_lib.func_reverse_b""")
}
DataType.ARRAY_F -> {
asmgen.out("""
lda #<$varName
ldy #>$varName
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #$numElements
jsr floats.func_reverse_f""")
}
in SplitWordArrayTypes -> TODO("split word reverse")
else -> throw AssemblyError("weird type")
} }
} }
private fun funcSort(fcall: PtBuiltinFunctionCall) { private fun funcSort(fcall: PtBuiltinFunctionCall) {
val variable = fcall.args.single() val variable = fcall.args.single() as PtIdentifier
if (variable is PtIdentifier) { val symbol = asmgen.symbolTable.lookup(variable.name)
val symbol = asmgen.symbolTable.lookup(variable.name) val varName = asmgen.asmVariableName(variable)
val decl = symbol!!.astNode as IPtVariable val (dt, numElements) = when(symbol) {
val varName = asmgen.asmVariableName(variable) is StStaticVariable -> symbol.dt to symbol.length!!
val numElements = when(decl) { is StMemVar -> symbol.dt to symbol.length!!
is PtConstant -> throw AssemblyError("cannot sort a constant") else -> DataType.UNDEFINED to 0
is PtMemMapped -> decl.arraySize }
is PtVariable -> decl.arraySize when (dt) {
DataType.ARRAY_UB, DataType.ARRAY_B -> {
asmgen.out("""
lda #<$varName
ldy #>$varName
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #$numElements""")
asmgen.out(if (dt == DataType.ARRAY_UB) " jsr prog8_lib.func_sort_ub" else " jsr prog8_lib.func_sort_b")
} }
when (decl.type) { DataType.ARRAY_UW, DataType.ARRAY_W -> {
DataType.ARRAY_UB, DataType.ARRAY_B -> { asmgen.out("""
asmgen.out(""" lda #<$varName
lda #<$varName ldy #>$varName
ldy #>$varName sta P8ZP_SCRATCH_W1
sta P8ZP_SCRATCH_W1 sty P8ZP_SCRATCH_W1+1
sty P8ZP_SCRATCH_W1+1 lda #$numElements""")
lda #$numElements""") asmgen.out(if (dt == DataType.ARRAY_UW) " jsr prog8_lib.func_sort_uw" else " jsr prog8_lib.func_sort_w")
asmgen.out(if (decl.type == DataType.ARRAY_UB) " jsr prog8_lib.func_sort_ub" else " jsr prog8_lib.func_sort_b")
}
DataType.ARRAY_UW, DataType.ARRAY_W -> {
asmgen.out("""
lda #<$varName
ldy #>$varName
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #$numElements""")
asmgen.out(if (decl.type == DataType.ARRAY_UW) " jsr prog8_lib.func_sort_uw" else " jsr prog8_lib.func_sort_w")
}
DataType.STR -> {
val stringLength = (symbol as StStaticVariable).length!!-1
asmgen.out("""
lda #<$varName
ldy #>$varName
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #$stringLength
jsr prog8_lib.func_sort_ub""")
}
DataType.ARRAY_F -> throw AssemblyError("sorting of floating point array is not supported")
in SplitWordArrayTypes -> TODO("split word sort")
else -> throw AssemblyError("weird type")
} }
} else DataType.STR -> {
throw AssemblyError("weird type") asmgen.out("""
lda #<$varName
ldy #>$varName
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #${numElements-1}
jsr prog8_lib.func_sort_ub""")
}
DataType.ARRAY_F -> throw AssemblyError("sorting of floating point array is not supported")
in SplitWordArrayTypes -> TODO("split word sort")
else -> throw AssemblyError("weird type")
}
} }
private fun funcRor2(fcall: PtBuiltinFunctionCall) { private fun funcRor2(fcall: PtBuiltinFunctionCall) {
@ -1245,12 +1237,11 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
// address in P8ZP_SCRATCH_W1, number of elements in A // address in P8ZP_SCRATCH_W1, number of elements in A
arg as PtIdentifier arg as PtIdentifier
val symbol = asmgen.symbolTable.lookup(arg.name) val symbol = asmgen.symbolTable.lookup(arg.name)
val arrayVar = symbol!!.astNode as IPtVariable val numElements = when(symbol) {
val numElements = when(arrayVar) { is StStaticVariable -> symbol.length!!
is PtConstant -> null is StMemVar -> symbol.length!!
is PtMemMapped -> arrayVar.arraySize else -> 0
is PtVariable -> arrayVar.arraySize }
} ?: throw AssemblyError("length of non-array requested")
val identifierName = asmgen.asmVariableName(arg) val identifierName = asmgen.asmVariableName(arg)
asmgen.out(""" asmgen.out("""
lda #<$identifierName lda #<$identifierName

View File

@ -1,7 +1,11 @@
package prog8.codegen.cpu6502 package prog8.codegen.cpu6502
import com.github.michaelbull.result.fold import com.github.michaelbull.result.fold
import prog8.code.ast.* import prog8.code.StMemVar
import prog8.code.StStaticVariable
import prog8.code.ast.PtForLoop
import prog8.code.ast.PtIdentifier
import prog8.code.ast.PtRange
import prog8.code.core.* import prog8.code.core.*
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
@ -332,11 +336,10 @@ $endLabel""")
asmgen.loopEndLabels.push(endLabel) asmgen.loopEndLabels.push(endLabel)
val iterableName = asmgen.asmVariableName(ident) val iterableName = asmgen.asmVariableName(ident)
val symbol = asmgen.symbolTable.lookup(ident.name) val symbol = asmgen.symbolTable.lookup(ident.name)
val decl = symbol!!.astNode as IPtVariable val numElements = when(symbol) {
val numElements = when(decl) { is StStaticVariable -> symbol.length!!
is PtConstant -> throw AssemblyError("length of non-array requested") is StMemVar -> symbol.length!!
is PtMemMapped -> decl.arraySize else -> 0
is PtVariable -> decl.arraySize
} }
when(iterableDt) { when(iterableDt) {
DataType.STR -> { DataType.STR -> {
@ -364,7 +367,7 @@ $loopLabel sty $indexVar
lda $iterableName,y lda $iterableName,y
sta ${asmgen.asmVariableName(stmt.variable)}""") sta ${asmgen.asmVariableName(stmt.variable)}""")
asmgen.translate(stmt.statements) asmgen.translate(stmt.statements)
if(numElements!!<=255u) { if(numElements<=255) {
asmgen.out(""" asmgen.out("""
ldy $indexVar ldy $indexVar
iny iny
@ -379,7 +382,7 @@ $loopLabel sty $indexVar
bne $loopLabel bne $loopLabel
beq $endLabel""") beq $endLabel""")
} }
if(numElements>=16u) { if(numElements>=16) {
// allocate index var on ZP if possible // allocate index var on ZP if possible
val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors) val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors)
result.fold( result.fold(
@ -392,7 +395,7 @@ $loopLabel sty $indexVar
asmgen.out(endLabel) asmgen.out(endLabel)
} }
DataType.ARRAY_W, DataType.ARRAY_UW -> { DataType.ARRAY_W, DataType.ARRAY_UW -> {
val length = numElements!! * 2u val length = numElements * 2
val indexVar = asmgen.makeLabel("for_index") val indexVar = asmgen.makeLabel("for_index")
val loopvarName = asmgen.asmVariableName(stmt.variable) val loopvarName = asmgen.asmVariableName(stmt.variable)
asmgen.out(""" asmgen.out("""
@ -403,7 +406,7 @@ $loopLabel sty $indexVar
lda $iterableName+1,y lda $iterableName+1,y
sta $loopvarName+1""") sta $loopvarName+1""")
asmgen.translate(stmt.statements) asmgen.translate(stmt.statements)
if(length<=127u) { if(length<=127) {
asmgen.out(""" asmgen.out("""
ldy $indexVar ldy $indexVar
iny iny
@ -420,7 +423,7 @@ $loopLabel sty $indexVar
bne $loopLabel bne $loopLabel
beq $endLabel""") beq $endLabel""")
} }
if(length>=16u) { if(length>=16) {
// allocate index var on ZP if possible // allocate index var on ZP if possible
val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors) val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors)
result.fold( result.fold(
@ -444,7 +447,7 @@ $loopLabel sty $indexVar
lda ${iterableName}_msb,y lda ${iterableName}_msb,y
sta $loopvarName+1""") sta $loopvarName+1""")
asmgen.translate(stmt.statements) asmgen.translate(stmt.statements)
if(numElements<=255u) { if(numElements<=255) {
asmgen.out(""" asmgen.out("""
ldy $indexVar ldy $indexVar
iny iny
@ -459,7 +462,7 @@ $loopLabel sty $indexVar
bne $loopLabel bne $loopLabel
beq $endLabel""") beq $endLabel""")
} }
if(numElements>=16u) { if(numElements>=16) {
// allocate index var on ZP if possible // allocate index var on ZP if possible
val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors) val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors)
result.fold( result.fold(

View File

@ -1,5 +1,7 @@
package prog8.codegen.cpu6502.assignment package prog8.codegen.cpu6502.assignment
import prog8.code.StMemVar
import prog8.code.StStaticVariable
import prog8.code.ast.* import prog8.code.ast.*
import prog8.code.core.* import prog8.code.core.*
import prog8.codegen.cpu6502.AsmGen6502Internal import prog8.codegen.cpu6502.AsmGen6502Internal
@ -1814,23 +1816,21 @@ internal class AssignmentAsmGen(private val program: PtProgram,
private fun containmentCheckIntoA(containment: PtContainmentCheck) { private fun containmentCheckIntoA(containment: PtContainmentCheck) {
val elementDt = containment.element.type val elementDt = containment.element.type
val symbol = asmgen.symbolTable.lookup(containment.iterable.name) val symbol = asmgen.symbolTable.lookup(containment.iterable.name)!!
val variable = symbol!!.astNode as IPtVariable val symbolName = asmgen.asmVariableName(symbol, containment.definingSub())
val varname = asmgen.asmVariableName(containment.iterable) val (dt, numElements) = when(symbol) {
val numElements = when(variable) { is StStaticVariable -> symbol.dt to symbol.length!!
is PtConstant -> null is StMemVar -> symbol.dt to symbol.length!!
is PtMemMapped -> variable.arraySize else -> DataType.UNDEFINED to 0
is PtVariable -> variable.arraySize
} }
when(variable.type) { when(dt) {
DataType.STR -> { DataType.STR -> {
// use subroutine // use subroutine
assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt == DataType.BYTE) assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt == DataType.BYTE)
asmgen.saveRegisterStack(CpuRegister.A, true) asmgen.saveRegisterStack(CpuRegister.A, true)
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), symbol.astNode.position,"P8ZP_SCRATCH_W1"), varname, null, null) assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), containment.position,"P8ZP_SCRATCH_W1"), symbolName, null, null)
asmgen.restoreRegisterStack(CpuRegister.A, false) asmgen.restoreRegisterStack(CpuRegister.A, false)
val stringVal = (variable as PtVariable).value as PtString asmgen.out(" ldy #${numElements-1}")
asmgen.out(" ldy #${stringVal.value.length}")
asmgen.out(" jsr prog8_lib.containment_bytearray") asmgen.out(" jsr prog8_lib.containment_bytearray")
return return
} }
@ -1840,7 +1840,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
DataType.ARRAY_B, DataType.ARRAY_UB -> { DataType.ARRAY_B, DataType.ARRAY_UB -> {
assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt == DataType.BYTE) assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt == DataType.BYTE)
asmgen.saveRegisterStack(CpuRegister.A, true) asmgen.saveRegisterStack(CpuRegister.A, true)
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), symbol.astNode.position, "P8ZP_SCRATCH_W1"), varname, null, null) assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), containment.position, "P8ZP_SCRATCH_W1"), symbolName, null, null)
asmgen.restoreRegisterStack(CpuRegister.A, false) asmgen.restoreRegisterStack(CpuRegister.A, false)
asmgen.out(" ldy #$numElements") asmgen.out(" ldy #$numElements")
asmgen.out(" jsr prog8_lib.containment_bytearray") asmgen.out(" jsr prog8_lib.containment_bytearray")
@ -1848,7 +1848,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
} }
DataType.ARRAY_W, DataType.ARRAY_UW -> { DataType.ARRAY_W, DataType.ARRAY_UW -> {
assignExpressionToVariable(containment.element, "P8ZP_SCRATCH_W1", elementDt) assignExpressionToVariable(containment.element, "P8ZP_SCRATCH_W1", elementDt)
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), symbol.astNode.position, "P8ZP_SCRATCH_W2"), varname, null, null) assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, containment.definingISub(), containment.position, "P8ZP_SCRATCH_W2"), symbolName, null, null)
asmgen.out(" ldy #$numElements") asmgen.out(" ldy #$numElements")
asmgen.out(" jsr prog8_lib.containment_wordarray") asmgen.out(" jsr prog8_lib.containment_wordarray")
return return

View File

@ -18,7 +18,6 @@ class IRCodeGen(
private val expressionEval = ExpressionGen(this) private val expressionEval = ExpressionGen(this)
private val builtinFuncGen = BuiltinFuncGen(this, expressionEval) private val builtinFuncGen = BuiltinFuncGen(this, expressionEval)
private val assignmentGen = AssignmentGen(this, expressionEval) private val assignmentGen = AssignmentGen(this, expressionEval)
private var irSymbolTable: IRSymbolTable = IRSymbolTable(null)
internal val registers = RegisterPool() internal val registers = RegisterPool()
fun generate(): IRProgram { fun generate(): IRProgram {
@ -26,7 +25,7 @@ class IRCodeGen(
moveAllNestedSubroutinesToBlockScope() moveAllNestedSubroutinesToBlockScope()
verifyNameScoping(program, symbolTable) verifyNameScoping(program, symbolTable)
irSymbolTable = IRSymbolTable(symbolTable) val irSymbolTable = IRSymbolTable.fromStDuringCodegen(symbolTable)
val irProg = IRProgram(program.name, irSymbolTable, options, program.encoding) val irProg = IRProgram(program.name, irSymbolTable, options, program.encoding)
// collect global variables initializers // collect global variables initializers

View File

@ -24,7 +24,7 @@ class TestIRPeepholeOpt: FunSpec({
compTarget = target, compTarget = target,
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS loadAddress = target.machine.PROGRAM_LOAD_ADDRESS
) )
val prog = IRProgram("test", IRSymbolTable(null), options, target) val prog = IRProgram("test", IRSymbolTable(), options, target)
prog.addBlock(block) prog.addBlock(block)
prog.linkChunks() prog.linkChunks()
prog.validate() prog.validate()

View File

@ -5,11 +5,11 @@ package prog8.buildversion
*/ */
const val MAVEN_GROUP = "prog8" const val MAVEN_GROUP = "prog8"
const val MAVEN_NAME = "compiler" const val MAVEN_NAME = "compiler"
const val VERSION = "9.7" const val VERSION = "9.8-SNAPSHOT"
const val GIT_REVISION = 4286 const val GIT_REVISION = 4287
const val GIT_SHA = "cfc9c15f1e9fe96940e170fb14ad3a957109977c" const val GIT_SHA = "08a079a96e67c26298b81de2d35919be51a3dfd0"
const val GIT_DATE = "2023-12-10T15:22:00Z" const val GIT_DATE = "2023-12-11T20:15:48Z"
const val GIT_BRANCH = "master" const val GIT_BRANCH = "no-vardecls"
const val BUILD_DATE = "2023-12-10T15:44:19Z" const val BUILD_DATE = "2023-12-11T21:48:14Z"
const val BUILD_UNIX_TIME = 1702223059842L const val BUILD_UNIX_TIME = 1702331294381L
const val DIRTY = 1 const val DIRTY = 1

View File

@ -56,7 +56,7 @@ class IRFileReader {
val initGlobals = parseInitGlobals(reader) val initGlobals = parseInitGlobals(reader)
val blocks = parseBlocksUntilProgramEnd(reader) val blocks = parseBlocksUntilProgramEnd(reader)
val st = IRSymbolTable(null) val st = IRSymbolTable()
asmsymbols.forEach { (name, value) -> st.addAsmSymbol(name, value)} asmsymbols.forEach { (name, value) -> st.addAsmSymbol(name, value)}
varsWithoutInit.forEach { st.add(it) } varsWithoutInit.forEach { st.add(it) }
variables.forEach { st.add(it) } variables.forEach { st.add(it) }

View File

@ -142,7 +142,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
if(irProgram.options.includeSourcelines) { if(irProgram.options.includeSourcelines) {
if(code.sourceLinesPositions.any {it !== Position.DUMMY}) { if(code.sourceLinesPositions.any {it !== Position.DUMMY}) {
xml.writeStartElement("P8SRC") xml.writeStartElement("P8SRC")
var sourceTxt = StringBuilder("\n") val sourceTxt = StringBuilder("\n")
code.sourceLinesPositions.forEach { pos -> code.sourceLinesPositions.forEach { pos ->
val line = SourceLineCache.retrieveLine(pos) val line = SourceLineCache.retrieveLine(pos)
if(line!=null) { if(line!=null) {
@ -210,8 +210,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_lsb zp=${variable.zpwish}\n") xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_lsb zp=${variable.zpwish}\n")
xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_msb zp=${variable.zpwish}\n") xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_msb zp=${variable.zpwish}\n")
} else { } else {
val typeStr = getTypeString(variable) xml.writeCharacters("${variable.typeString} ${variable.name} zp=${variable.zpwish}\n")
xml.writeCharacters("$typeStr ${variable.name} zp=${variable.zpwish}\n")
} }
} }
@ -228,15 +227,15 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
lsbValue = "" lsbValue = ""
msbValue = "" msbValue = ""
} else { } else {
lsbValue = variable.onetimeInitializationArrayValue!!.joinToString(",") { lsbValue = variable.onetimeInitializationArrayValue.joinToString(",") {
if(it.number!=null) if(it.number!=null)
(it.number!!.toInt() and 255).toHex() (it.number.toInt() and 255).toHex()
else else
"@<${it.addressOfSymbol}" "@<${it.addressOfSymbol}"
} }
msbValue = variable.onetimeInitializationArrayValue!!.joinToString(",") { msbValue = variable.onetimeInitializationArrayValue.joinToString(",") {
if(it.number!=null) if(it.number!=null)
(it.number!!.toInt() shr 8).toHex() (it.number.toInt() shr 8).toHex()
else else
"@>${it.addressOfSymbol}" "@>${it.addressOfSymbol}"
} }
@ -244,26 +243,25 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_lsb=$lsbValue zp=${variable.zpwish}\n") xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_lsb=$lsbValue zp=${variable.zpwish}\n")
xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_msb=$msbValue zp=${variable.zpwish}\n") xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_msb=$msbValue zp=${variable.zpwish}\n")
} else { } else {
val typeStr = getTypeString(variable)
val value: String = when(variable.dt) { val value: String = when(variable.dt) {
DataType.FLOAT -> (variable.onetimeInitializationNumericValue ?: "").toString() DataType.FLOAT -> (variable.onetimeInitializationNumericValue ?: "").toString()
in NumericDatatypes -> (variable.onetimeInitializationNumericValue?.toInt()?.toHex() ?: "").toString() in NumericDatatypes -> (variable.onetimeInitializationNumericValue?.toInt()?.toHex() ?: "").toString()
DataType.STR -> { DataType.STR -> {
val encoded = irProgram.encoding.encodeString(variable.onetimeInitializationStringValue!!.first, variable.onetimeInitializationStringValue!!.second) + listOf(0u) val encoded = irProgram.encoding.encodeString(variable.onetimeInitializationStringValue!!.first, variable.onetimeInitializationStringValue.second) + listOf(0u)
encoded.joinToString(",") { it.toInt().toString() } encoded.joinToString(",") { it.toInt().toString() }
} }
DataType.ARRAY_F -> { DataType.ARRAY_F -> {
if(variable.onetimeInitializationArrayValue!=null) { if(variable.onetimeInitializationArrayValue!=null) {
variable.onetimeInitializationArrayValue!!.joinToString(",") { it.number!!.toString() } variable.onetimeInitializationArrayValue.joinToString(",") { it.number!!.toString() }
} else { } else {
"" // array will be zero'd out at program start "" // array will be zero'd out at program start
} }
} }
in ArrayDatatypes -> { in ArrayDatatypes -> {
if(variable.onetimeInitializationArrayValue!==null) { if(variable.onetimeInitializationArrayValue!==null) {
variable.onetimeInitializationArrayValue!!.joinToString(",") { variable.onetimeInitializationArrayValue.joinToString(",") {
if(it.number!=null) if(it.number!=null)
it.number!!.toInt().toHex() it.number.toInt().toHex()
else else
"@${it.addressOfSymbol}" "@${it.addressOfSymbol}"
} }
@ -273,7 +271,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
} }
else -> throw InternalCompilerException("weird dt") else -> throw InternalCompilerException("weird dt")
} }
xml.writeCharacters("$typeStr ${variable.name}=$value zp=${variable.zpwish}\n") xml.writeCharacters("${variable.typeString} ${variable.name}=$value zp=${variable.zpwish}\n")
} }
} }
xml.writeEndElement() xml.writeEndElement()
@ -282,8 +280,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
xml.writeStartElement("MEMORYMAPPEDVARIABLES") xml.writeStartElement("MEMORYMAPPEDVARIABLES")
xml.writeCharacters("\n") xml.writeCharacters("\n")
for (variable in irProgram.st.allMemMappedVariables()) { for (variable in irProgram.st.allMemMappedVariables()) {
val typeStr = getTypeString(variable) xml.writeCharacters("@${variable.typeString} ${variable.name}=${variable.address.toHex()}\n")
xml.writeCharacters("@$typeStr ${variable.name}=${variable.address.toHex()}\n")
} }
xml.writeEndElement() xml.writeEndElement()
xml.writeCharacters("\n") xml.writeCharacters("\n")

View File

@ -1,88 +1,88 @@
package prog8.intermediate package prog8.intermediate
import prog8.code.* import prog8.code.*
import prog8.code.ast.PtVariable import prog8.code.core.*
import prog8.code.core.DataType
import prog8.code.core.ZeropageWish
import prog8.code.core.internedStringsModuleName
// In the Intermediate Representation, all nesting has been removed. // In the Intermediate Representation, all nesting has been removed.
// So the symbol table is just a big flat mapping of (scoped)name to node. // So the symbol table is just a big flat mapping of (scoped)name to node.
// We define a stripped down symbol table for use in the IR phase only, rather than reuse the codegen symboltable
class IRSymbolTable(sourceSt: SymbolTable?) { class IRSymbolTable {
private val table = mutableMapOf<String, StNode>() private val table = mutableMapOf<String, IRStNode>()
private val asmSymbols = mutableMapOf<String, String>() private val asmSymbols = mutableMapOf<String, String>()
init { companion object {
if(sourceSt!=null) { fun fromStDuringCodegen(sourceSt: SymbolTable?): IRSymbolTable {
sourceSt.allVariables.forEach { val st = IRSymbolTable()
add(it) if (sourceSt != null) {
} sourceSt.allVariables.forEach {
sourceSt.allMemMappedVariables.forEach { st.add(it)
add(it) }
} sourceSt.allMemMappedVariables.forEach {
sourceSt.allMemorySlabs.forEach { st.add(it)
add(it) }
} sourceSt.allMemorySlabs.forEach {
st.add(it)
}
require(table.all { it.key==it.value.name }) require(st.table.all { it.key == it.value.name })
allVariables().forEach {variable -> st.allVariables().forEach { variable ->
variable.onetimeInitializationArrayValue?.let { variable.onetimeInitializationArrayValue?.let {
it.forEach { arrayElt -> it.forEach { arrayElt ->
if(arrayElt.addressOfSymbol!=null) { if (arrayElt.addressOfSymbol != null) {
require(arrayElt.addressOfSymbol!!.contains('.')) { require(arrayElt.addressOfSymbol.contains('.')) {
"pointer var in array should be properly scoped: ${arrayElt.addressOfSymbol} in ${variable.name}" "pointer var in array should be properly scoped: ${arrayElt.addressOfSymbol} in ${variable.name}"
}
} }
} }
} }
} }
} }
return st
} }
} }
fun allVariables(): Sequence<StStaticVariable> = fun allVariables(): Sequence<IRStStaticVariable> =
table.asSequence().map { it.value }.filterIsInstance<StStaticVariable>() table.asSequence().map { it.value }.filterIsInstance<IRStStaticVariable>()
fun allMemMappedVariables(): Sequence<StMemVar> = fun allMemMappedVariables(): Sequence<IRStMemVar> =
table.asSequence().map { it.value }.filterIsInstance<StMemVar>() table.asSequence().map { it.value }.filterIsInstance<IRStMemVar>()
fun allMemorySlabs(): Sequence<StMemorySlab> = fun allMemorySlabs(): Sequence<IRStMemorySlab> =
table.asSequence().map { it.value }.filterIsInstance<StMemorySlab>() table.asSequence().map { it.value }.filterIsInstance<IRStMemorySlab>()
fun lookup(name: String) = table[name] fun lookup(name: String) = table[name]
fun add(variable: StStaticVariable) { fun add(variable: StStaticVariable) {
val scopedName: String val scopedName: String
val varToadd: StStaticVariable val varToadd: IRStStaticVariable
if('.' in variable.name) { if('.' in variable.name) {
scopedName = variable.name scopedName = variable.name
varToadd = variable varToadd = IRStStaticVariable.from(variable)
} else { } else {
fun fixupAddressOfInArray(array: List<StArrayElement>?): List<StArrayElement>? { fun fixupAddressOfInArray(array: List<StArrayElement>?): List<IRStArrayElement>? {
if(array==null) if(array==null)
return null return null
val newArray = mutableListOf<StArrayElement>() val newArray = mutableListOf<IRStArrayElement>()
array.forEach { array.forEach {
if(it.addressOfSymbol!=null) { if(it.addressOfSymbol!=null) {
val target = variable.lookup(it.addressOfSymbol!!)!! val target = variable.lookup(it.addressOfSymbol!!)!!
newArray.add(StArrayElement(null, target.scopedName)) newArray.add(IRStArrayElement(null, target.scopedName))
} else { } else {
newArray.add(it) newArray.add(IRStArrayElement.from(it))
} }
} }
return newArray return newArray
} }
scopedName = variable.scopedName scopedName = variable.scopedName
val dummyNode = PtVariable(scopedName, variable.dt, variable.zpwish, null, null, variable.astNode.position) varToadd = IRStStaticVariable(scopedName, variable.dt,
varToadd = StStaticVariable(scopedName, variable.dt,
variable.onetimeInitializationNumericValue, variable.onetimeInitializationNumericValue,
variable.onetimeInitializationStringValue, variable.onetimeInitializationStringValue,
fixupAddressOfInArray(variable.onetimeInitializationArrayValue), fixupAddressOfInArray(variable.onetimeInitializationArrayValue),
variable.length, variable.length,
variable.zpwish, variable.zpwish
dummyNode
) )
} }
table[scopedName] = varToadd table[scopedName] = varToadd
@ -91,27 +91,26 @@ class IRSymbolTable(sourceSt: SymbolTable?) {
fun add(variable: StMemVar) { fun add(variable: StMemVar) {
val scopedName: String val scopedName: String
val varToadd: StMemVar val varToadd: IRStMemVar
if('.' in variable.name) { if('.' in variable.name) {
scopedName = variable.name scopedName = variable.name
varToadd = variable varToadd = IRStMemVar.from(variable)
} else { } else {
scopedName = try { scopedName = try {
variable.scopedName variable.scopedName
} catch (ux: UninitializedPropertyAccessException) { } catch (ux: UninitializedPropertyAccessException) {
variable.name variable.name
} }
varToadd = StMemVar(scopedName, variable.dt, variable.address, variable.length, variable.astNode) varToadd = IRStMemVar(scopedName, variable.dt, variable.address, variable.length)
} }
table[scopedName] = varToadd table[scopedName] = varToadd
} }
fun add(variable: StMemorySlab) { fun add(variable: StMemorySlab) {
val varToadd = if('.' in variable.name) val varToadd = if('.' in variable.name)
variable IRStMemorySlab.from(variable)
else { else {
val dummyNode = PtVariable(variable.name, DataType.ARRAY_UB, ZeropageWish.NOT_IN_ZEROPAGE, null, null, variable.astNode.position) IRStMemorySlab("prog8_slabs.${variable.name}", variable.size, variable.align)
StMemorySlab("prog8_slabs.${variable.name}", variable.size, variable.align, dummyNode)
} }
table[varToadd.name] = varToadd table[varToadd.name] = varToadd
} }
@ -133,3 +132,118 @@ class IRSymbolTable(sourceSt: SymbolTable?) {
} }
} }
} }
enum class IRStNodeType {
STATICVAR,
MEMVAR,
MEMORYSLAB
// the other StNodeType types aren't used here anymore.
// this symbol table only contains variables.
}
open class IRStNode(val name: String,
val type: IRStNodeType,
val children: MutableMap<String, StNode> = mutableMapOf()
)
class IRStMemVar(name: String,
val dt: DataType,
val address: UInt,
val length: Int? // for arrays: the number of elements, for strings: number of characters *including* the terminating 0-byte
) : IRStNode(name, IRStNodeType.MEMVAR) {
companion object {
fun from(variable: StMemVar): IRStMemVar {
return IRStMemVar(
variable.name,
variable.dt,
variable.address,
variable.length
)
}
}
val typeString: String
get() = when (dt) {
DataType.UBYTE -> "ubyte"
DataType.BYTE -> "byte"
DataType.UWORD -> "uword"
DataType.WORD -> "word"
DataType.FLOAT -> "float"
DataType.BOOL, DataType.ARRAY_BOOL -> throw InternalCompilerException("bool should have been converted to ubyte")
DataType.ARRAY_UB, DataType.STR -> "ubyte[${length}]"
DataType.ARRAY_B -> "byte[${length}]"
DataType.ARRAY_UW -> "uword[${length}]"
DataType.ARRAY_W -> "word[${length}]"
DataType.ARRAY_F -> "float[${length}]"
in SplitWordArrayTypes -> throw InternalCompilerException("@split can't be used on memory mapped arrays")
else -> throw InternalCompilerException("weird dt")
}
}
class IRStMemorySlab(
name: String,
val size: UInt,
val align: UInt
): IRStNode(name, IRStNodeType.MEMORYSLAB) {
companion object {
fun from(variable: StMemorySlab): IRStMemorySlab {
return IRStMemorySlab(
variable.name,
variable.size,
variable.align
)
}
}
}
class IRStStaticVariable(name: String,
val dt: DataType,
val onetimeInitializationNumericValue: Double?, // regular (every-run-time) initialization is done via regular assignments
val onetimeInitializationStringValue: IRStString?,
val onetimeInitializationArrayValue: IRStArray?,
val length: Int?, // for arrays: the number of elements, for strings: number of characters *including* the terminating 0-byte
val zpwish: ZeropageWish // used in the variable allocator
) : IRStNode(name, IRStNodeType.STATICVAR) {
companion object {
fun from(variable: StStaticVariable): IRStStaticVariable {
return IRStStaticVariable(variable.name,
variable.dt,
variable.onetimeInitializationNumericValue,
variable.onetimeInitializationStringValue,
variable.onetimeInitializationArrayValue?.map { IRStArrayElement.from(it) },
variable.length,
variable.zpwish)
}
}
val uninitialized = onetimeInitializationArrayValue==null && onetimeInitializationStringValue==null && onetimeInitializationNumericValue==null
val typeString: String
get() = when (dt) {
DataType.UBYTE -> "ubyte"
DataType.BYTE -> "byte"
DataType.UWORD -> "uword"
DataType.WORD -> "word"
DataType.FLOAT -> "float"
DataType.BOOL, DataType.ARRAY_BOOL -> throw InternalCompilerException("bool should have been converted to ubyte")
DataType.ARRAY_UB, DataType.STR -> "ubyte[${length}]"
DataType.ARRAY_B -> "byte[${length}]"
DataType.ARRAY_UW -> "uword[${length}]"
DataType.ARRAY_W -> "word[${length}]"
DataType.ARRAY_F -> "float[${length}]"
in SplitWordArrayTypes -> throw InternalCompilerException("split array should have been converted to 2 ubyte arrays")
else -> throw InternalCompilerException("weird dt")
}
}
class IRStArrayElement(val number: Double?, val addressOfSymbol: String?) {
companion object {
fun from(elt: StArrayElement): IRStArrayElement {
return IRStArrayElement(elt.number, elt.addressOfSymbol)
}
}
}
typealias IRStArray = List<IRStArrayElement>
typealias IRStString = Pair<String, Encoding>

View File

@ -1,7 +1,9 @@
package prog8.intermediate package prog8.intermediate
import prog8.code.* import prog8.code.Either
import prog8.code.core.* import prog8.code.core.*
import prog8.code.left
import prog8.code.right
fun getTypeString(dt : DataType): String = when(dt) { fun getTypeString(dt : DataType): String = when(dt) {
@ -20,38 +22,6 @@ fun getTypeString(dt : DataType): String = when(dt) {
else -> throw InternalCompilerException("weird dt") else -> throw InternalCompilerException("weird dt")
} }
fun getTypeString(memvar: StMemVar): String = when(memvar.dt) {
DataType.UBYTE -> "ubyte"
DataType.BYTE -> "byte"
DataType.UWORD -> "uword"
DataType.WORD -> "word"
DataType.FLOAT -> "float"
DataType.BOOL, DataType.ARRAY_BOOL -> throw InternalCompilerException("bool should have been converted to ubyte")
DataType.ARRAY_UB, DataType.STR -> "ubyte[${memvar.length}]"
DataType.ARRAY_B -> "byte[${memvar.length}]"
DataType.ARRAY_UW -> "uword[${memvar.length}]"
DataType.ARRAY_W -> "word[${memvar.length}]"
DataType.ARRAY_F -> "float[${memvar.length}]"
in SplitWordArrayTypes -> throw InternalCompilerException("@split can't be used on memory mapped arrays")
else -> throw InternalCompilerException("weird dt")
}
fun getTypeString(variable : StStaticVariable): String = when(variable.dt) {
DataType.UBYTE -> "ubyte"
DataType.BYTE -> "byte"
DataType.UWORD -> "uword"
DataType.WORD -> "word"
DataType.FLOAT -> "float"
DataType.BOOL, DataType.ARRAY_BOOL -> throw InternalCompilerException("bool should have been converted to ubyte")
DataType.ARRAY_UB, DataType.STR -> "ubyte[${variable.length}]"
DataType.ARRAY_B -> "byte[${variable.length}]"
DataType.ARRAY_UW -> "uword[${variable.length}]"
DataType.ARRAY_W -> "word[${variable.length}]"
DataType.ARRAY_F -> "float[${variable.length}]"
in SplitWordArrayTypes -> throw InternalCompilerException("split array should have been converted to 2 ubyte arrays")
else -> throw InternalCompilerException("weird dt")
}
fun convertIRType(typestr: String): IRDataType? { fun convertIRType(typestr: String): IRDataType? {
return when(typestr.lowercase()) { return when(typestr.lowercase()) {
"" -> null "" -> null

View File

@ -1,16 +1,12 @@
import io.kotest.core.spec.style.FunSpec import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.ints.shouldBeGreaterThan import io.kotest.matchers.ints.shouldBeGreaterThan
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import prog8.code.StStaticVariable
import prog8.code.core.CbmPrgLauncherType import prog8.code.core.CbmPrgLauncherType
import prog8.code.core.CompilationOptions import prog8.code.core.CompilationOptions
import prog8.code.core.OutputType import prog8.code.core.OutputType
import prog8.code.core.ZeropageType import prog8.code.core.ZeropageType
import prog8.code.target.Cx16Target import prog8.code.target.Cx16Target
import prog8.intermediate.IRFileReader import prog8.intermediate.*
import prog8.intermediate.IRFileWriter
import prog8.intermediate.IRProgram
import prog8.intermediate.IRSymbolTable
import kotlin.io.path.* import kotlin.io.path.*
class TestIRFileInOut: FunSpec({ class TestIRFileInOut: FunSpec({
@ -29,7 +25,7 @@ class TestIRFileInOut: FunSpec({
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS, loadAddress = target.machine.PROGRAM_LOAD_ADDRESS,
outputDir = tempdir outputDir = tempdir
) )
val program = IRProgram("unittest-irwriter", IRSymbolTable(null), options, target) val program = IRProgram("unittest-irwriter", IRSymbolTable(), options, target)
val writer = IRFileWriter(program, null) val writer = IRFileWriter(program, null)
val generatedFile = writer.write() val generatedFile = writer.write()
val lines = generatedFile.readLines() val lines = generatedFile.readLines()
@ -107,9 +103,9 @@ return
program.name shouldBe "test-ir-reader" program.name shouldBe "test-ir-reader"
program.blocks.size shouldBe 2 program.blocks.size shouldBe 2
program.st.allVariables().count() shouldBe 3 program.st.allVariables().count() shouldBe 3
val var1 = program.st.lookup("sys.wait.jiffies") as StStaticVariable val var1 = program.st.lookup("sys.wait.jiffies") as IRStStaticVariable
val var2 = program.st.lookup("sys.bssvar") as StStaticVariable val var2 = program.st.lookup("sys.bssvar") as IRStStaticVariable
val var3 = program.st.lookup("sys.emptystring") as StStaticVariable val var3 = program.st.lookup("sys.emptystring") as IRStStaticVariable
var1.uninitialized shouldBe false var1.uninitialized shouldBe false
var2.uninitialized shouldBe true var2.uninitialized shouldBe true
var3.uninitialized shouldBe true var3.uninitialized shouldBe true

View File

@ -1,8 +1,5 @@
package prog8.vm package prog8.vm
import prog8.code.StArray
import prog8.code.StArrayElement
import prog8.code.StStaticVariable
import prog8.code.core.ArrayDatatypes import prog8.code.core.ArrayDatatypes
import prog8.code.core.AssemblyError import prog8.code.core.AssemblyError
import prog8.code.core.DataType import prog8.code.core.DataType
@ -247,7 +244,7 @@ class VmProgramLoader {
if(iElts.isEmpty() || iElts.size==1) { if(iElts.isEmpty() || iElts.size==1) {
val iElt = if(iElts.isEmpty()) { val iElt = if(iElts.isEmpty()) {
require(variable.uninitialized) require(variable.uninitialized)
StArrayElement(0.0, null) IRStArrayElement(0.0, null)
} else { } else {
require(!variable.uninitialized) require(!variable.uninitialized)
iElts[0] iElts[0]
@ -262,8 +259,8 @@ class VmProgramLoader {
} }
private fun initializeWithValues( private fun initializeWithValues(
variable: StStaticVariable, variable: IRStStaticVariable,
iElts: StArray, iElts: IRStArray,
startAddress: Int, startAddress: Int,
symbolAddresses: MutableMap<String, Int>, symbolAddresses: MutableMap<String, Int>,
memory: Memory, memory: Memory,
@ -325,8 +322,8 @@ class VmProgramLoader {
} }
private fun initializeWithOneValue( private fun initializeWithOneValue(
variable: StStaticVariable, variable: IRStStaticVariable,
iElt: StArrayElement, iElt: IRStArrayElement,
startAddress: Int, startAddress: Int,
symbolAddresses: MutableMap<String, Int>, symbolAddresses: MutableMap<String, Int>,
memory: Memory, memory: Memory,
@ -389,7 +386,7 @@ class VmProgramLoader {
} }
} }
private fun getInitializerValue(arrayDt: DataType, elt: StArrayElement, symbolAddresses: MutableMap<String, Int>): Double { private fun getInitializerValue(arrayDt: DataType, elt: IRStArrayElement, symbolAddresses: MutableMap<String, Int>): Double {
if(elt.addressOfSymbol!=null) { if(elt.addressOfSymbol!=null) {
when(arrayDt) { when(arrayDt) {
DataType.ARRAY_UB, DataType.STR, DataType.ARRAY_B, DataType.ARRAY_BOOL -> { DataType.ARRAY_UB, DataType.STR, DataType.ARRAY_B, DataType.ARRAY_BOOL -> {

View File

@ -29,7 +29,7 @@ class TestVm: FunSpec( {
} }
test("vm execution: empty program") { test("vm execution: empty program") {
val program = IRProgram("test", IRSymbolTable(null), getTestOptions(), VMTarget()) val program = IRProgram("test", IRSymbolTable(), getTestOptions(), VMTarget())
val vm = VirtualMachine(program) val vm = VirtualMachine(program)
vm.callStack.shouldBeEmpty() vm.callStack.shouldBeEmpty()
vm.valueStack.shouldBeEmpty() vm.valueStack.shouldBeEmpty()
@ -43,7 +43,7 @@ class TestVm: FunSpec( {
} }
test("vm execution: modify memory") { test("vm execution: modify memory") {
val program = IRProgram("test", IRSymbolTable(null), getTestOptions(), VMTarget()) val program = IRProgram("test", IRSymbolTable(), getTestOptions(), VMTarget())
val block = IRBlock("testmain", null, false, false, IRBlock.BlockAlignment.NONE, Position.DUMMY) val block = IRBlock("testmain", null, false, false, IRBlock.BlockAlignment.NONE, Position.DUMMY)
val startSub = IRSubroutine("testmain.testsub", emptyList(), null, Position.DUMMY) val startSub = IRSubroutine("testmain.testsub", emptyList(), null, Position.DUMMY)
val code = IRCodeChunk(startSub.label, null) val code = IRCodeChunk(startSub.label, null)
@ -72,7 +72,7 @@ class TestVm: FunSpec( {
} }
test("asmsub not supported in vm even with IR") { test("asmsub not supported in vm even with IR") {
val program = IRProgram("test", IRSymbolTable(null), getTestOptions(), VMTarget()) val program = IRProgram("test", IRSymbolTable(), getTestOptions(), VMTarget())
val block = IRBlock("main", null, false, false, IRBlock.BlockAlignment.NONE, Position.DUMMY) val block = IRBlock("main", null, false, false, IRBlock.BlockAlignment.NONE, Position.DUMMY)
val startSub = IRAsmSubroutine( val startSub = IRAsmSubroutine(
"main.asmstart", "main.asmstart",