mirror of
https://github.com/irmen/prog8.git
synced 2025-08-14 22:27:48 +00:00
optimize symbol table for IR
This commit is contained in:
@@ -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
|
||||||
@@ -296,6 +297,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"
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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()
|
||||||
|
@@ -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
|
||||||
|
@@ -2,6 +2,10 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
|
- [on branch: no-vardecls]
|
||||||
|
remove IPtVariable and the 3 derived types (var, constant, memmapped) in the codegen ast
|
||||||
|
remove VarDecls in compiler ast?
|
||||||
|
|
||||||
- [on branch: call-pointers] allow calling a subroutine via a pointer variable (indirect JSR, optimized form of callfar())
|
- [on branch: call-pointers] allow calling a subroutine via a pointer variable (indirect JSR, optimized form of callfar())
|
||||||
modify programs (shell, paint) that now use callfar
|
modify programs (shell, paint) that now use callfar
|
||||||
|
|
||||||
@@ -28,11 +32,6 @@ Compiler:
|
|||||||
- OR.... make all this more generic and use some %segment option to create real segments for 64tass?
|
- OR.... make all this more generic and use some %segment option to create real segments for 64tass?
|
||||||
- (need separate step in codegen and IR to write the "golden" variables)
|
- (need separate step in codegen and IR to write the "golden" variables)
|
||||||
|
|
||||||
- [on branch: no-vardecls]
|
|
||||||
remove astNode from StNode in the symboltable
|
|
||||||
remove IPtVariable and the 3 derived types (var, constant, memmapped) in the codegen ast
|
|
||||||
remove VarDecls in compiler ast
|
|
||||||
|
|
||||||
- do we need (array)variable alignment tag instead of block alignment tag? You want to align the data, not the code in the block?
|
- do we need (array)variable alignment tag instead of block alignment tag? You want to align the data, not the code in the block?
|
||||||
- ir: getting it in shape for code generation
|
- ir: getting it in shape for code generation
|
||||||
- ir: related to the one above: block alignment doesn't translate well to variables in the block (the actual stuff that needs to be aligned in memory) but: need variable alignment tag instead of block alignment tag, really
|
- ir: related to the one above: block alignment doesn't translate well to variables in the block (the actual stuff that needs to be aligned in memory) but: need variable alignment tag instead of block alignment tag, really
|
||||||
|
@@ -4,21 +4,13 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte x,y,z = math.rnd()
|
str name = "irmen"
|
||||||
|
ubyte[] bytes = [1,2,3]
|
||||||
txt.print_ub(x)
|
uword[] words = [1,2,3,4,5]
|
||||||
txt.nl()
|
txt.print_ub('z' in name)
|
||||||
txt.print_ub(y)
|
txt.print_ub('r' in name)
|
||||||
txt.nl()
|
txt.print_ub('r' in "derp")
|
||||||
txt.print_ub(z)
|
txt.print_ub(4 in bytes)
|
||||||
txt.nl()
|
txt.print_ub($0004 in words)
|
||||||
|
|
||||||
x=y=z=math.rnd()
|
|
||||||
txt.print_ub(x)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_ub(y)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_ub(z)
|
|
||||||
txt.nl()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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) }
|
||||||
|
@@ -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")
|
||||||
|
@@ -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>
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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 -> {
|
||||||
|
@@ -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",
|
||||||
|
Reference in New Issue
Block a user