mirror of
https://github.com/irmen/prog8.git
synced 2025-08-14 07:26:05 +00:00
retain constants in IR
some IR related cleanups
This commit is contained in:
@@ -42,6 +42,7 @@ class SymbolTable(astProgram: PtProgram) : StNode(astProgram.name, StNodeType.GL
|
|||||||
}
|
}
|
||||||
|
|
||||||
val allVariables: Collection<StStaticVariable> by lazy {
|
val allVariables: Collection<StStaticVariable> by lazy {
|
||||||
|
// can't be done with a generic function because those don't support local recursive functions yet
|
||||||
val vars = mutableListOf<StStaticVariable>()
|
val vars = mutableListOf<StStaticVariable>()
|
||||||
fun collect(node: StNode) {
|
fun collect(node: StNode) {
|
||||||
for(child in node.children) {
|
for(child in node.children) {
|
||||||
@@ -56,6 +57,7 @@ class SymbolTable(astProgram: PtProgram) : StNode(astProgram.name, StNodeType.GL
|
|||||||
}
|
}
|
||||||
|
|
||||||
val allMemMappedVariables: Collection<StMemVar> by lazy {
|
val allMemMappedVariables: Collection<StMemVar> by lazy {
|
||||||
|
// can't be done with a generic function because those don't support local recursive functions yet
|
||||||
val vars = mutableListOf<StMemVar>()
|
val vars = mutableListOf<StMemVar>()
|
||||||
fun collect(node: StNode) {
|
fun collect(node: StNode) {
|
||||||
for(child in node.children) {
|
for(child in node.children) {
|
||||||
@@ -70,6 +72,7 @@ class SymbolTable(astProgram: PtProgram) : StNode(astProgram.name, StNodeType.GL
|
|||||||
}
|
}
|
||||||
|
|
||||||
val allMemorySlabs: Collection<StMemorySlab> by lazy {
|
val allMemorySlabs: Collection<StMemorySlab> by lazy {
|
||||||
|
// can't be done with a generic function because those don't support local recursive functions yet
|
||||||
val vars = mutableListOf<StMemorySlab>()
|
val vars = mutableListOf<StMemorySlab>()
|
||||||
fun collect(node: StNode) {
|
fun collect(node: StNode) {
|
||||||
for(child in node.children) {
|
for(child in node.children) {
|
||||||
@@ -113,7 +116,7 @@ enum class StNodeType {
|
|||||||
|
|
||||||
open class StNode(val name: String,
|
open class StNode(val name: String,
|
||||||
val type: StNodeType,
|
val type: StNodeType,
|
||||||
val astNode: PtNode,
|
val astNode: PtNode?,
|
||||||
val children: MutableMap<String, StNode> = mutableMapOf()
|
val children: MutableMap<String, StNode> = mutableMapOf()
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@@ -187,7 +190,7 @@ class StStaticVariable(name: String,
|
|||||||
val length: Int?, // for arrays: the number of elements, for strings: number of characters *including* the terminating 0-byte
|
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
|
val zpwish: ZeropageWish, // used in the variable allocator
|
||||||
val align: Int,
|
val align: Int,
|
||||||
astNode: PtNode) : StNode(name, StNodeType.STATICVAR, astNode) {
|
astNode: PtNode?) : StNode(name, StNodeType.STATICVAR, astNode) {
|
||||||
|
|
||||||
var initializationNumericValue: Double? = null
|
var initializationNumericValue: Double? = null
|
||||||
private set
|
private set
|
||||||
@@ -229,7 +232,7 @@ class StStaticVariable(name: String,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class StConstant(name: String, val dt: BaseDataType, val value: Double, astNode: PtNode) :
|
class StConstant(name: String, val dt: BaseDataType, val value: Double, astNode: PtNode?) :
|
||||||
StNode(name, StNodeType.CONSTANT, astNode)
|
StNode(name, StNodeType.CONSTANT, astNode)
|
||||||
|
|
||||||
|
|
||||||
@@ -237,7 +240,7 @@ class StMemVar(name: String,
|
|||||||
val dt: DataType,
|
val dt: DataType,
|
||||||
val address: UInt,
|
val address: UInt,
|
||||||
val length: Int?, // for arrays: the number of elements, for strings: number of characters *including* the terminating 0-byte
|
val length: Int?, // for arrays: the number of elements, for strings: number of characters *including* the terminating 0-byte
|
||||||
astNode: PtNode) :
|
astNode: PtNode?) :
|
||||||
StNode(name, StNodeType.MEMVAR, astNode) {
|
StNode(name, StNodeType.MEMVAR, astNode) {
|
||||||
|
|
||||||
init{
|
init{
|
||||||
@@ -251,7 +254,7 @@ class StMemorySlab(
|
|||||||
name: String,
|
name: String,
|
||||||
val size: UInt,
|
val size: UInt,
|
||||||
val align: UInt,
|
val align: UInt,
|
||||||
astNode: PtNode
|
astNode: PtNode?
|
||||||
):
|
):
|
||||||
StNode(name, StNodeType.MEMORYSLAB, astNode)
|
StNode(name, StNodeType.MEMORYSLAB, astNode)
|
||||||
|
|
||||||
|
@@ -59,7 +59,7 @@ class AsmGen6502(val prefixSymbols: Boolean, private val lastGeneratedLabelSeque
|
|||||||
}
|
}
|
||||||
is PtFunctionCall -> {
|
is PtFunctionCall -> {
|
||||||
val stNode = st.lookup(node.name)!!
|
val stNode = st.lookup(node.name)!!
|
||||||
if(stNode.astNode.definingBlock()?.options?.noSymbolPrefixing!=true) {
|
if(stNode.astNode!!.definingBlock()?.options?.noSymbolPrefixing!=true) {
|
||||||
val index = node.parent.children.indexOf(node)
|
val index = node.parent.children.indexOf(node)
|
||||||
functionCallsToPrefix += node.parent to index
|
functionCallsToPrefix += node.parent to index
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ class AsmGen6502(val prefixSymbols: Boolean, private val lastGeneratedLabelSeque
|
|||||||
lookupName = lookupName.dropLast(4)
|
lookupName = lookupName.dropLast(4)
|
||||||
}
|
}
|
||||||
val stNode = st.lookup(lookupName) ?: throw AssemblyError("unknown identifier $node")
|
val stNode = st.lookup(lookupName) ?: throw AssemblyError("unknown identifier $node")
|
||||||
if(stNode.astNode.definingBlock()?.options?.noSymbolPrefixing!=true) {
|
if(stNode.astNode!!.definingBlock()?.options?.noSymbolPrefixing!=true) {
|
||||||
val index = node.parent.children.indexOf(node)
|
val index = node.parent.children.indexOf(node)
|
||||||
nodesToPrefix += node.parent to index
|
nodesToPrefix += node.parent to index
|
||||||
}
|
}
|
||||||
@@ -1268,7 +1268,7 @@ $repeatLabel""")
|
|||||||
val node = stScope.astNode
|
val node = stScope.astNode
|
||||||
if(node is PtSubroutineParameter)
|
if(node is PtSubroutineParameter)
|
||||||
return node
|
return node
|
||||||
return node.definingSub()?.parameters?.singleOrNull { it.name===name }
|
return node!!.definingSub()?.parameters?.singleOrNull { it.name===name }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignByteOperandsToAAndVar(left: PtExpression, right: PtExpression, rightVarName: String) {
|
internal fun assignByteOperandsToAAndVar(left: PtExpression, right: PtExpression, rightVarName: String) {
|
||||||
|
@@ -60,7 +60,7 @@ internal class VariableAllocator(private val symboltable: SymbolTable,
|
|||||||
variable.scopedName,
|
variable.scopedName,
|
||||||
variable.dt,
|
variable.dt,
|
||||||
variable.length,
|
variable.length,
|
||||||
variable.astNode.position,
|
variable.astNode?.position ?: Position.DUMMY,
|
||||||
errors
|
errors
|
||||||
)
|
)
|
||||||
result.fold(
|
result.fold(
|
||||||
@@ -68,7 +68,7 @@ internal class VariableAllocator(private val symboltable: SymbolTable,
|
|||||||
numVariablesAllocatedInZP++
|
numVariablesAllocatedInZP++
|
||||||
},
|
},
|
||||||
failure = {
|
failure = {
|
||||||
errors.err(it.message!!, variable.astNode.position)
|
errors.err(it.message!!, variable.astNode?.position ?: Position.DUMMY)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ internal class VariableAllocator(private val symboltable: SymbolTable,
|
|||||||
variable.scopedName,
|
variable.scopedName,
|
||||||
variable.dt,
|
variable.dt,
|
||||||
variable.length,
|
variable.length,
|
||||||
variable.astNode.position,
|
variable.astNode?.position ?: Position.DUMMY,
|
||||||
errors
|
errors
|
||||||
)
|
)
|
||||||
result.onSuccess { numVariablesAllocatedInZP++ }
|
result.onSuccess { numVariablesAllocatedInZP++ }
|
||||||
@@ -99,7 +99,7 @@ internal class VariableAllocator(private val symboltable: SymbolTable,
|
|||||||
variable.scopedName,
|
variable.scopedName,
|
||||||
variable.dt,
|
variable.dt,
|
||||||
variable.length,
|
variable.length,
|
||||||
variable.astNode.position,
|
variable.astNode?.position ?: Position.DUMMY,
|
||||||
errors
|
errors
|
||||||
)
|
)
|
||||||
result.onSuccess { numVariablesAllocatedInZP++ }
|
result.onSuccess { numVariablesAllocatedInZP++ }
|
||||||
|
@@ -25,7 +25,7 @@ class IRCodeGen(
|
|||||||
verifyNameScoping(program, symbolTable)
|
verifyNameScoping(program, symbolTable)
|
||||||
changeGlobalVarInits(symbolTable)
|
changeGlobalVarInits(symbolTable)
|
||||||
|
|
||||||
val irSymbolTable = IRSymbolTable.fromStDuringCodegen(symbolTable)
|
val irSymbolTable = IRSymbolTable.fromAstSymboltable(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
|
||||||
@@ -486,7 +486,7 @@ class IRCodeGen(
|
|||||||
it += IRInstruction(Opcode.STOREM, irType(DataType.forDt(elementDt)), reg1=tmpReg, labelSymbol = loopvarSymbol)
|
it += IRInstruction(Opcode.STOREM, irType(DataType.forDt(elementDt)), reg1=tmpReg, labelSymbol = loopvarSymbol)
|
||||||
}
|
}
|
||||||
result += translateNode(forLoop.statements)
|
result += translateNode(forLoop.statements)
|
||||||
result += addConstReg(IRDataType.BYTE, indexReg, elementSize)
|
result += addConstIntToReg(IRDataType.BYTE, indexReg, elementSize)
|
||||||
result += IRCodeChunk(null, null).also {
|
result += IRCodeChunk(null, null).also {
|
||||||
if(lengthBytes!=256) {
|
if(lengthBytes!=256) {
|
||||||
// for length 256, the compare is actually against 0, which doesn't require a separate CMP instruction
|
// for length 256, the compare is actually against 0, which doesn't require a separate CMP instruction
|
||||||
@@ -639,7 +639,7 @@ class IRCodeGen(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addConstReg(dt: IRDataType, reg: Int, value: Int): IRCodeChunk {
|
private fun addConstIntToReg(dt: IRDataType, reg: Int, value: Int): IRCodeChunk {
|
||||||
val code = IRCodeChunk(null, null)
|
val code = IRCodeChunk(null, null)
|
||||||
when(value) {
|
when(value) {
|
||||||
0 -> { /* do nothing */ }
|
0 -> { /* do nothing */ }
|
||||||
|
@@ -94,7 +94,7 @@ private fun integrateDefers(subdefers: Map<PtSub, List<PtDefer>>, program: PtPro
|
|||||||
val identifier = node.target as? PtIdentifier
|
val identifier = node.target as? PtIdentifier
|
||||||
if (identifier != null) {
|
if (identifier != null) {
|
||||||
val stNode = st.lookup(identifier.name)!!
|
val stNode = st.lookup(identifier.name)!!
|
||||||
val targetSub = stNode.astNode.definingSub()
|
val targetSub = stNode.astNode!!.definingSub()
|
||||||
if (targetSub != node.definingSub())
|
if (targetSub != node.definingSub())
|
||||||
jumpsAndCallsToAugment.add(node)
|
jumpsAndCallsToAugment.add(node)
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,8 @@ class TestLaunchEmu: FunSpec({
|
|||||||
</VARIABLESNOINIT>
|
</VARIABLESNOINIT>
|
||||||
<VARIABLESWITHINIT>
|
<VARIABLESWITHINIT>
|
||||||
</VARIABLESWITHINIT>
|
</VARIABLESWITHINIT>
|
||||||
|
<CONSTANTS>
|
||||||
|
</CONSTANTS>
|
||||||
|
|
||||||
<MEMORYMAPPEDVARIABLES>
|
<MEMORYMAPPEDVARIABLES>
|
||||||
</MEMORYMAPPEDVARIABLES>
|
</MEMORYMAPPEDVARIABLES>
|
||||||
|
@@ -21,7 +21,7 @@ class TestSymbolTable: FunSpec({
|
|||||||
st.type shouldBe StNodeType.GLOBAL
|
st.type shouldBe StNodeType.GLOBAL
|
||||||
st.children shouldBe mutableMapOf()
|
st.children shouldBe mutableMapOf()
|
||||||
st.astNode shouldBeSameInstanceAs astNode
|
st.astNode shouldBeSameInstanceAs astNode
|
||||||
st.astNode.position shouldBe Position.DUMMY
|
st.astNode!!.position shouldBe Position.DUMMY
|
||||||
}
|
}
|
||||||
|
|
||||||
test("symboltable flatten") {
|
test("symboltable flatten") {
|
||||||
|
@@ -46,8 +46,9 @@ Future Things and Ideas
|
|||||||
|
|
||||||
IR/VM
|
IR/VM
|
||||||
-----
|
-----
|
||||||
|
- cx16.r0-r15 should not be translated to their (fake) addresses but remain symbolical, so they can be translated to what the actual target system specifies for them.
|
||||||
|
- prefix immediate values with '#' for readability reasons (no technical reason)
|
||||||
- ExpressionCodeResult: get rid of the separation between single result register and multiple result registers?
|
- ExpressionCodeResult: get rid of the separation between single result register and multiple result registers?
|
||||||
- constants are not retained in the IR file, they should. (need to be able to make asm labels from them eventually)
|
|
||||||
- implement missing operators in AssignmentGen (array shifts etc)
|
- implement missing operators in AssignmentGen (array shifts etc)
|
||||||
- support %align on code chunks
|
- support %align on code chunks
|
||||||
- fix call() return value handling
|
- fix call() return value handling
|
||||||
|
@@ -1,40 +1,14 @@
|
|||||||
%import sprites
|
|
||||||
%import palette
|
|
||||||
%import math
|
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
%option no_sysinit
|
%option no_sysinit
|
||||||
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
word[128] xpos
|
const ubyte CVALUE = 123
|
||||||
word[128] ypos
|
const long CLONG = 555555
|
||||||
|
ubyte @shared vvalue = 99
|
||||||
|
|
||||||
for cx16.r2L in 0 to 127 {
|
cx16.r0L = CVALUE + 100
|
||||||
sprites.init(cx16.r2L, 0, 0, sprites.SIZE_8, sprites.SIZE_8, sprites.COLORS_16, 0)
|
cx16.r1L = vvalue + 100
|
||||||
xpos[cx16.r2L] = math.rndw() & 511 as word + 64
|
|
||||||
ypos[cx16.r2L] = math.rnd()
|
|
||||||
}
|
|
||||||
|
|
||||||
repeat {
|
|
||||||
sys.waitvsync()
|
|
||||||
palette.set_color(6, $f00)
|
|
||||||
|
|
||||||
sprites.pos_batch(0, 128, &xpos, &ypos)
|
|
||||||
|
|
||||||
palette.set_color(6, $0f0)
|
|
||||||
for cx16.r2L in 0 to 127 {
|
|
||||||
if cx16.r2L & 1 == 0 {
|
|
||||||
xpos[cx16.r2L] ++
|
|
||||||
if xpos[cx16.r2L] > 640
|
|
||||||
xpos[cx16.r2L] = 0
|
|
||||||
} else {
|
|
||||||
ypos[cx16.r2L] ++
|
|
||||||
if ypos[cx16.r2L] > 480
|
|
||||||
ypos[cx16.r2L] = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
palette.set_color(6, $00f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package prog8.intermediate
|
package prog8.intermediate
|
||||||
|
|
||||||
import prog8.code.*
|
import prog8.code.*
|
||||||
|
import prog8.code.ast.PtConstant
|
||||||
import prog8.code.ast.PtVariable
|
import prog8.code.ast.PtVariable
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import prog8.code.target.VMTarget
|
import prog8.code.target.VMTarget
|
||||||
@@ -52,6 +53,7 @@ class IRFileReader {
|
|||||||
val asmsymbols = parseAsmSymbols(reader)
|
val asmsymbols = parseAsmSymbols(reader)
|
||||||
val varsWithoutInit = parseVarsWithoutInit(reader)
|
val varsWithoutInit = parseVarsWithoutInit(reader)
|
||||||
val variables = parseVariables(reader)
|
val variables = parseVariables(reader)
|
||||||
|
val constants = parseConstants(reader)
|
||||||
val memorymapped = parseMemMapped(reader)
|
val memorymapped = parseMemMapped(reader)
|
||||||
val slabs = parseSlabs(reader)
|
val slabs = parseSlabs(reader)
|
||||||
val initGlobals = parseInitGlobals(reader)
|
val initGlobals = parseInitGlobals(reader)
|
||||||
@@ -61,6 +63,7 @@ class IRFileReader {
|
|||||||
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) }
|
||||||
|
constants.forEach { st.add(it) }
|
||||||
memorymapped.forEach { st.add(it) }
|
memorymapped.forEach { st.add(it) }
|
||||||
slabs.forEach { st.add(it) }
|
slabs.forEach { st.add(it) }
|
||||||
|
|
||||||
@@ -165,19 +168,45 @@ class IRFileReader {
|
|||||||
val match = varPattern.matchEntire(line) ?: throw IRParseException("invalid VARIABLESNOINIT $line")
|
val match = varPattern.matchEntire(line) ?: throw IRParseException("invalid VARIABLESNOINIT $line")
|
||||||
val (type, arrayspec, name, zpwish, alignment) = match.destructured
|
val (type, arrayspec, name, zpwish, alignment) = match.destructured
|
||||||
if('.' !in name)
|
if('.' !in name)
|
||||||
throw IRParseException("unscoped varname: $name")
|
throw IRParseException("unscoped name: $name")
|
||||||
val arraysize = if(arrayspec.isNotBlank()) arrayspec.substring(1, arrayspec.length-1).toInt() else null
|
val arraysize = if(arrayspec.isNotBlank()) arrayspec.substring(1, arrayspec.length-1).toInt() else null
|
||||||
val dt = parseDatatype(type, arraysize!=null)
|
val dt = parseDatatype(type, arraysize!=null)
|
||||||
val zp = if(zpwish.isBlank()) ZeropageWish.DONTCARE else ZeropageWish.valueOf(zpwish)
|
val zp = if(zpwish.isBlank()) ZeropageWish.DONTCARE else ZeropageWish.valueOf(zpwish)
|
||||||
val align = if(alignment.isBlank()) 0u else alignment.toUInt()
|
val align = if(alignment.isBlank()) 0u else alignment.toUInt()
|
||||||
val dummyNode = PtVariable(name, dt, zp, align, null, null, Position.DUMMY)
|
val newVar = StStaticVariable(name, dt, null, null, arraysize, zp, align.toInt(), null)
|
||||||
val newVar = StStaticVariable(name, dt, null, null, arraysize, zp, align.toInt(), dummyNode)
|
|
||||||
variables.add(newVar)
|
variables.add(newVar)
|
||||||
}
|
}
|
||||||
return variables
|
return variables
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun parseConstants(reader: XMLEventReader): List<StConstant> {
|
||||||
|
skipText(reader)
|
||||||
|
val start = reader.nextEvent().asStartElement()
|
||||||
|
require(start.name.localPart=="CONSTANTS") { "missing CONSTANTS" }
|
||||||
|
val text = readText(reader).trim()
|
||||||
|
require(reader.nextEvent().isEndElement)
|
||||||
|
|
||||||
|
return if(text.isBlank())
|
||||||
|
emptyList()
|
||||||
|
else {
|
||||||
|
val constantPattern = Regex("(.+?) (.+)=(.*?)")
|
||||||
|
val constants = mutableListOf<StConstant>()
|
||||||
|
text.lineSequence().forEach { line ->
|
||||||
|
// examples:
|
||||||
|
// uword main.start.qq2=0
|
||||||
|
val match = constantPattern.matchEntire(line) ?: throw IRParseException("invalid CONSTANT $line")
|
||||||
|
val (type, name, valueStr) = match.destructured
|
||||||
|
if('.' !in name)
|
||||||
|
throw IRParseException("unscoped name: $name")
|
||||||
|
val dt = parseDatatype(type, false)
|
||||||
|
val value = parseIRValue(valueStr)
|
||||||
|
constants.add(StConstant(name, dt.base, value, null))
|
||||||
|
}
|
||||||
|
return constants
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun parseVariables(reader: XMLEventReader): List<StStaticVariable> {
|
private fun parseVariables(reader: XMLEventReader): List<StStaticVariable> {
|
||||||
skipText(reader)
|
skipText(reader)
|
||||||
val start = reader.nextEvent().asStartElement()
|
val start = reader.nextEvent().asStartElement()
|
||||||
@@ -223,11 +252,10 @@ class IRFileReader {
|
|||||||
dt.isString -> throw IRParseException("STR should have been converted to byte array")
|
dt.isString -> throw IRParseException("STR should have been converted to byte array")
|
||||||
else -> throw IRParseException("weird dt")
|
else -> throw IRParseException("weird dt")
|
||||||
}
|
}
|
||||||
val dummyNode = PtVariable(name, dt, zp, align, null, null, Position.DUMMY)
|
|
||||||
if(arraysize!=null && initArray!=null && initArray.all { it.number==0.0 }) {
|
if(arraysize!=null && initArray!=null && initArray.all { it.number==0.0 }) {
|
||||||
initArray=null // arrays with just zeros can be left uninitialized
|
initArray=null // arrays with just zeros can be left uninitialized
|
||||||
}
|
}
|
||||||
val stVar = StStaticVariable(name, dt, null, initArray, arraysize, zp, align.toInt(), dummyNode)
|
val stVar = StStaticVariable(name, dt, null, initArray, arraysize, zp, align.toInt(), null)
|
||||||
if(initNumeric!=null)
|
if(initNumeric!=null)
|
||||||
stVar.setOnetimeInitNumeric(initNumeric)
|
stVar.setOnetimeInitNumeric(initNumeric)
|
||||||
variables.add(stVar)
|
variables.add(stVar)
|
||||||
@@ -256,16 +284,7 @@ class IRFileReader {
|
|||||||
val (type, arrayspec, name, address) = match.destructured
|
val (type, arrayspec, name, address) = match.destructured
|
||||||
val arraysize = if(arrayspec.isNotBlank()) arrayspec.substring(1, arrayspec.length-1).toInt() else null
|
val arraysize = if(arrayspec.isNotBlank()) arrayspec.substring(1, arrayspec.length-1).toInt() else null
|
||||||
val dt = parseDatatype(type, arraysize!=null)
|
val dt = parseDatatype(type, arraysize!=null)
|
||||||
val dummyNode = PtVariable(
|
memvars.add(StMemVar(name, dt, parseIRValue(address).toUInt(), arraysize, null))
|
||||||
name,
|
|
||||||
dt,
|
|
||||||
ZeropageWish.NOT_IN_ZEROPAGE,
|
|
||||||
0u,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
Position.DUMMY
|
|
||||||
)
|
|
||||||
memvars.add(StMemVar(name, dt, parseIRValue(address).toUInt(), arraysize, dummyNode))
|
|
||||||
}
|
}
|
||||||
memvars
|
memvars
|
||||||
}
|
}
|
||||||
@@ -287,16 +306,7 @@ class IRFileReader {
|
|||||||
// example: "slabname 4096 0"
|
// example: "slabname 4096 0"
|
||||||
val match = slabPattern.matchEntire(line) ?: throw IRParseException("invalid slab $line")
|
val match = slabPattern.matchEntire(line) ?: throw IRParseException("invalid slab $line")
|
||||||
val (name, size, align) = match.destructured
|
val (name, size, align) = match.destructured
|
||||||
val dummyNode = PtVariable(
|
slabs.add(StMemorySlab(name, size.toUInt(), align.toUInt(), null))
|
||||||
name,
|
|
||||||
DataType.arrayFor(BaseDataType.UBYTE, false),
|
|
||||||
ZeropageWish.NOT_IN_ZEROPAGE,
|
|
||||||
0u,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
Position.DUMMY
|
|
||||||
)
|
|
||||||
slabs.add(StMemorySlab(name, size.toUInt(), align.toUInt(), dummyNode))
|
|
||||||
}
|
}
|
||||||
slabs
|
slabs
|
||||||
}
|
}
|
||||||
@@ -520,6 +530,7 @@ class IRFileReader {
|
|||||||
"word" -> DataType.arrayFor(BaseDataType.WORD, false)
|
"word" -> DataType.arrayFor(BaseDataType.WORD, false)
|
||||||
"uword" -> DataType.arrayFor(BaseDataType.UWORD, false)
|
"uword" -> DataType.arrayFor(BaseDataType.UWORD, false)
|
||||||
"float" -> DataType.arrayFor(BaseDataType.FLOAT, false)
|
"float" -> DataType.arrayFor(BaseDataType.FLOAT, false)
|
||||||
|
"long" -> DataType.arrayFor(BaseDataType.LONG, false)
|
||||||
else -> throw IRParseException("invalid dt $type")
|
else -> throw IRParseException("invalid dt $type")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -530,6 +541,7 @@ class IRFileReader {
|
|||||||
"word" -> DataType.forDt(BaseDataType.WORD)
|
"word" -> DataType.forDt(BaseDataType.WORD)
|
||||||
"uword" -> DataType.forDt(BaseDataType.UWORD)
|
"uword" -> DataType.forDt(BaseDataType.UWORD)
|
||||||
"float" -> DataType.forDt(BaseDataType.FLOAT)
|
"float" -> DataType.forDt(BaseDataType.FLOAT)
|
||||||
|
"long" -> DataType.forDt(BaseDataType.LONG)
|
||||||
// note: 'str' should not occur anymore in IR. Should be 'uword'
|
// note: 'str' should not occur anymore in IR. Should be 'uword'
|
||||||
else -> throw IRParseException("invalid dt $type")
|
else -> throw IRParseException("invalid dt $type")
|
||||||
}
|
}
|
||||||
|
@@ -148,10 +148,13 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
if(code.sourceLinesPositions.any {it !== Position.DUMMY}) {
|
if(code.sourceLinesPositions.any {it !== Position.DUMMY}) {
|
||||||
xml.writeStartElement("P8SRC")
|
xml.writeStartElement("P8SRC")
|
||||||
val sourceTxt = StringBuilder("\n")
|
val sourceTxt = StringBuilder("\n")
|
||||||
code.sourceLinesPositions.filter{ pos -> pos.line>0 }.forEach { pos ->
|
code.sourceLinesPositions
|
||||||
val line = ImportFileSystem.retrieveSourceLine(pos)
|
.filter{ pos -> pos.line > 0 }
|
||||||
sourceTxt.append("$pos $line\n")
|
.sortedBy { it.line }
|
||||||
}
|
.forEach { pos ->
|
||||||
|
val line = ImportFileSystem.retrieveSourceLine(pos)
|
||||||
|
sourceTxt.append("$pos $line\n")
|
||||||
|
}
|
||||||
xml.writeCData(sourceTxt.toString())
|
xml.writeCData(sourceTxt.toString())
|
||||||
xml.writeEndElement()
|
xml.writeEndElement()
|
||||||
}
|
}
|
||||||
@@ -212,6 +215,17 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun writeConstant(constant: IRStConstant) {
|
||||||
|
val dt = constant.dt
|
||||||
|
val value: String = when {
|
||||||
|
dt.isBool -> constant.value.toInt().toString()
|
||||||
|
dt.isFloat -> constant.value.toString()
|
||||||
|
dt.isInteger -> constant.value.toInt().toHex()
|
||||||
|
else -> throw InternalCompilerException("weird dt")
|
||||||
|
}
|
||||||
|
xml.writeCharacters("${constant.typeString} ${constant.name}=$value\n")
|
||||||
|
}
|
||||||
|
|
||||||
fun writeVarWithInit(variable: IRStStaticVariable) {
|
fun writeVarWithInit(variable: IRStStaticVariable) {
|
||||||
if(variable.dt.isSplitWordArray) {
|
if(variable.dt.isSplitWordArray) {
|
||||||
val lsbValue: String
|
val lsbValue: String
|
||||||
@@ -240,7 +254,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
val value: String = when {
|
val value: String = when {
|
||||||
dt.isBool -> variable.onetimeInitializationNumericValue?.toInt()?.toString() ?: ""
|
dt.isBool -> variable.onetimeInitializationNumericValue?.toInt()?.toString() ?: ""
|
||||||
dt.isFloat -> (variable.onetimeInitializationNumericValue ?: "").toString()
|
dt.isFloat -> (variable.onetimeInitializationNumericValue ?: "").toString()
|
||||||
dt.isNumeric -> variable.onetimeInitializationNumericValue?.toInt()?.toHex() ?: ""
|
dt.isInteger -> variable.onetimeInitializationNumericValue?.toInt()?.toHex() ?: ""
|
||||||
dt.isString -> {
|
dt.isString -> {
|
||||||
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() }
|
||||||
@@ -285,12 +299,11 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
for (variable in noinitAligned.sortedBy { it.align }) {
|
for (variable in noinitAligned.sortedBy { it.align }) {
|
||||||
writeNoInitVar(variable)
|
writeNoInitVar(variable)
|
||||||
}
|
}
|
||||||
|
|
||||||
xml.writeEndElement()
|
xml.writeEndElement()
|
||||||
xml.writeCharacters("\n")
|
xml.writeCharacters("\n")
|
||||||
|
|
||||||
xml.writeStartElement("VARIABLESWITHINIT")
|
xml.writeStartElement("VARIABLESWITHINIT")
|
||||||
xml.writeCharacters("\n")
|
xml.writeCharacters("\n")
|
||||||
|
|
||||||
val (initNotAligned, initAligned) = variablesWithInit.partition { it.align==0 || it.align==1 }
|
val (initNotAligned, initAligned) = variablesWithInit.partition { it.align==0 || it.align==1 }
|
||||||
for (variable in initNotAligned) {
|
for (variable in initNotAligned) {
|
||||||
writeVarWithInit(variable)
|
writeVarWithInit(variable)
|
||||||
@@ -301,6 +314,14 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
xml.writeEndElement()
|
xml.writeEndElement()
|
||||||
xml.writeCharacters("\n")
|
xml.writeCharacters("\n")
|
||||||
|
|
||||||
|
xml.writeStartElement("CONSTANTS")
|
||||||
|
xml.writeCharacters("\n")
|
||||||
|
for (constant in irProgram.st.allConstants()) {
|
||||||
|
writeConstant(constant)
|
||||||
|
}
|
||||||
|
xml.writeEndElement()
|
||||||
|
xml.writeCharacters("\n")
|
||||||
|
|
||||||
xml.writeStartElement("MEMORYMAPPEDVARIABLES")
|
xml.writeStartElement("MEMORYMAPPEDVARIABLES")
|
||||||
xml.writeCharacters("\n")
|
xml.writeCharacters("\n")
|
||||||
for (variable in irProgram.st.allMemMappedVariables()) {
|
for (variable in irProgram.st.allMemMappedVariables()) {
|
||||||
|
@@ -11,6 +11,7 @@ PROGRAM:
|
|||||||
OPTIONS (from CompilationOptions)
|
OPTIONS (from CompilationOptions)
|
||||||
ASMSYMBOLS (from command line defined symbols)
|
ASMSYMBOLS (from command line defined symbols)
|
||||||
VARIABLES (from Symboltable)
|
VARIABLES (from Symboltable)
|
||||||
|
CONSTANTS (form Symboltable)
|
||||||
MEMORYMAPPEDVARIABLES (from Symboltable)
|
MEMORYMAPPEDVARIABLES (from Symboltable)
|
||||||
MEMORYSLABS (from Symboltable)
|
MEMORYSLABS (from Symboltable)
|
||||||
INITGLOBALS
|
INITGLOBALS
|
||||||
|
@@ -13,17 +13,17 @@ class IRSymbolTable {
|
|||||||
private val asmSymbols = mutableMapOf<String, String>()
|
private val asmSymbols = mutableMapOf<String, String>()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun fromStDuringCodegen(sourceSt: SymbolTable?): IRSymbolTable {
|
fun fromAstSymboltable(sourceSt: SymbolTable?): IRSymbolTable {
|
||||||
val st = IRSymbolTable()
|
val st = IRSymbolTable()
|
||||||
if (sourceSt != null) {
|
if (sourceSt != null) {
|
||||||
sourceSt.allVariables.forEach {
|
sourceSt.flat.forEach {
|
||||||
st.add(it)
|
when(it.value.type) {
|
||||||
}
|
StNodeType.STATICVAR -> st.add(it.value as StStaticVariable)
|
||||||
sourceSt.allMemMappedVariables.forEach {
|
StNodeType.MEMVAR -> st.add(it.value as StMemVar)
|
||||||
st.add(it)
|
StNodeType.CONSTANT -> st.add(it.value as StConstant)
|
||||||
}
|
StNodeType.MEMORYSLAB -> st.add(it.value as StMemorySlab)
|
||||||
sourceSt.allMemorySlabs.forEach {
|
else -> { }
|
||||||
st.add(it)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
require(st.table.all { it.key == it.value.name })
|
require(st.table.all { it.key == it.value.name })
|
||||||
@@ -44,6 +44,9 @@ class IRSymbolTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun allConstants(): Sequence<IRStConstant> =
|
||||||
|
table.asSequence().map { it.value }.filterIsInstance<IRStConstant>()
|
||||||
|
|
||||||
fun allVariables(): Sequence<IRStStaticVariable> =
|
fun allVariables(): Sequence<IRStStaticVariable> =
|
||||||
table.asSequence().map { it.value }.filterIsInstance<IRStStaticVariable>()
|
table.asSequence().map { it.value }.filterIsInstance<IRStStaticVariable>()
|
||||||
|
|
||||||
@@ -60,7 +63,14 @@ class IRSymbolTable {
|
|||||||
val varToadd: IRStStaticVariable
|
val varToadd: IRStStaticVariable
|
||||||
if('.' in variable.name) {
|
if('.' in variable.name) {
|
||||||
scopedName = variable.name
|
scopedName = variable.name
|
||||||
varToadd = IRStStaticVariable.from(variable)
|
varToadd = IRStStaticVariable(variable.name,
|
||||||
|
variable.dt,
|
||||||
|
variable.initializationNumericValue,
|
||||||
|
variable.initializationStringValue,
|
||||||
|
variable.initializationArrayValue?.map { convertArrayElt(it) },
|
||||||
|
variable.length,
|
||||||
|
variable.zpwish,
|
||||||
|
variable.align)
|
||||||
} else {
|
} else {
|
||||||
fun fixupAddressOfInArray(array: List<StArrayElement>?): List<IRStArrayElement>? {
|
fun fixupAddressOfInArray(array: List<StArrayElement>?): List<IRStArrayElement>? {
|
||||||
if(array==null)
|
if(array==null)
|
||||||
@@ -71,7 +81,7 @@ class IRSymbolTable {
|
|||||||
val target = variable.lookup(it.addressOfSymbol!!) ?: throw NoSuchElementException("can't find variable ${it.addressOfSymbol}")
|
val target = variable.lookup(it.addressOfSymbol!!) ?: throw NoSuchElementException("can't find variable ${it.addressOfSymbol}")
|
||||||
newArray.add(IRStArrayElement(null, null, target.scopedName))
|
newArray.add(IRStArrayElement(null, null, target.scopedName))
|
||||||
} else {
|
} else {
|
||||||
newArray.add(IRStArrayElement.from(it))
|
newArray.add(convertArrayElt(it))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newArray
|
return newArray
|
||||||
@@ -90,13 +100,17 @@ class IRSymbolTable {
|
|||||||
table[scopedName] = varToadd
|
table[scopedName] = varToadd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun add(variable: StMemVar) {
|
fun add(variable: StMemVar) {
|
||||||
val scopedName: String
|
val scopedName: String
|
||||||
val varToadd: IRStMemVar
|
val varToadd: IRStMemVar
|
||||||
if('.' in variable.name) {
|
if('.' in variable.name) {
|
||||||
scopedName = variable.name
|
scopedName = variable.name
|
||||||
varToadd = IRStMemVar.from(variable)
|
varToadd = IRStMemVar(
|
||||||
|
variable.name,
|
||||||
|
variable.dt,
|
||||||
|
variable.address,
|
||||||
|
variable.length
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
scopedName = try {
|
scopedName = try {
|
||||||
variable.scopedName
|
variable.scopedName
|
||||||
@@ -110,13 +124,28 @@ class IRSymbolTable {
|
|||||||
|
|
||||||
fun add(variable: StMemorySlab) {
|
fun add(variable: StMemorySlab) {
|
||||||
val varToadd = if('.' in variable.name)
|
val varToadd = if('.' in variable.name)
|
||||||
IRStMemorySlab.from(variable)
|
IRStMemorySlab(variable.name, variable.size, variable.align)
|
||||||
else {
|
else {
|
||||||
IRStMemorySlab("prog8_slabs.${variable.name}", variable.size, variable.align)
|
IRStMemorySlab("prog8_slabs.${variable.name}", variable.size, variable.align)
|
||||||
}
|
}
|
||||||
table[varToadd.name] = varToadd
|
table[varToadd.name] = varToadd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun add(constant: StConstant) {
|
||||||
|
val scopedName: String
|
||||||
|
val dt = DataType.forDt(constant.dt)
|
||||||
|
if('.' in constant.name) {
|
||||||
|
scopedName = constant.name
|
||||||
|
} else {
|
||||||
|
scopedName = try {
|
||||||
|
constant.scopedName
|
||||||
|
} catch (_: UninitializedPropertyAccessException) {
|
||||||
|
constant.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table[scopedName] = IRStConstant(scopedName, dt, constant.value)
|
||||||
|
}
|
||||||
|
|
||||||
fun addAsmSymbol(name: String, value: String) {
|
fun addAsmSymbol(name: String, value: String) {
|
||||||
asmSymbols[name] = value
|
asmSymbols[name] = value
|
||||||
}
|
}
|
||||||
@@ -133,15 +162,20 @@ class IRSymbolTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun convertArrayElt(elt: StArrayElement): IRStArrayElement = if(elt.boolean!=null)
|
||||||
|
IRStArrayElement(elt.boolean, null, elt.addressOfSymbol)
|
||||||
|
else
|
||||||
|
IRStArrayElement(null, elt.number, elt.addressOfSymbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum class IRStNodeType {
|
enum class IRStNodeType {
|
||||||
STATICVAR,
|
STATICVAR,
|
||||||
MEMVAR,
|
MEMVAR,
|
||||||
MEMORYSLAB
|
MEMORYSLAB,
|
||||||
// the other StNodeType types aren't used here anymore.
|
CONST
|
||||||
// this symbol table only contains variables.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open class IRStNode(val name: String,
|
open class IRStNode(val name: String,
|
||||||
@@ -154,17 +188,6 @@ class IRStMemVar(name: String,
|
|||||||
val address: UInt,
|
val address: UInt,
|
||||||
val length: Int? // for arrays: the number of elements, for strings: number of characters *including* the terminating 0-byte
|
val length: Int? // for arrays: the number of elements, for strings: number of characters *including* the terminating 0-byte
|
||||||
) : IRStNode(name, IRStNodeType.MEMVAR) {
|
) : IRStNode(name, IRStNodeType.MEMVAR) {
|
||||||
companion object {
|
|
||||||
fun from(variable: StMemVar): IRStMemVar {
|
|
||||||
return IRStMemVar(
|
|
||||||
variable.name,
|
|
||||||
variable.dt,
|
|
||||||
variable.address,
|
|
||||||
variable.length
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
require(!dt.isString)
|
require(!dt.isString)
|
||||||
}
|
}
|
||||||
@@ -176,18 +199,14 @@ class IRStMemorySlab(
|
|||||||
name: String,
|
name: String,
|
||||||
val size: UInt,
|
val size: UInt,
|
||||||
val align: UInt
|
val align: UInt
|
||||||
): IRStNode(name, IRStNodeType.MEMORYSLAB) {
|
): IRStNode(name, IRStNodeType.MEMORYSLAB)
|
||||||
companion object {
|
|
||||||
fun from(variable: StMemorySlab): IRStMemorySlab {
|
|
||||||
return IRStMemorySlab(
|
class IRStConstant(name: String, val dt: DataType, val value: Double) : IRStNode(name, IRStNodeType.CONST) {
|
||||||
variable.name,
|
val typeString: String = dt.irTypeString(null)
|
||||||
variable.size,
|
|
||||||
variable.align
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class IRStStaticVariable(name: String,
|
class IRStStaticVariable(name: String,
|
||||||
val dt: DataType,
|
val dt: DataType,
|
||||||
val onetimeInitializationNumericValue: Double?, // regular (every-run-time) initialization is done via regular assignments
|
val onetimeInitializationNumericValue: Double?, // regular (every-run-time) initialization is done via regular assignments
|
||||||
@@ -197,19 +216,6 @@ class IRStStaticVariable(name: String,
|
|||||||
val zpwish: ZeropageWish, // used in the variable allocator
|
val zpwish: ZeropageWish, // used in the variable allocator
|
||||||
val align: Int
|
val align: Int
|
||||||
) : IRStNode(name, IRStNodeType.STATICVAR) {
|
) : IRStNode(name, IRStNodeType.STATICVAR) {
|
||||||
companion object {
|
|
||||||
fun from(variable: StStaticVariable): IRStStaticVariable {
|
|
||||||
return IRStStaticVariable(variable.name,
|
|
||||||
variable.dt,
|
|
||||||
variable.initializationNumericValue,
|
|
||||||
variable.initializationStringValue,
|
|
||||||
variable.initializationArrayValue?.map { IRStArrayElement.from(it) },
|
|
||||||
variable.length,
|
|
||||||
variable.zpwish,
|
|
||||||
variable.align)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if(align > 0) {
|
if(align > 0) {
|
||||||
require(dt.isString || dt.isArray)
|
require(dt.isString || dt.isArray)
|
||||||
@@ -223,15 +229,6 @@ class IRStStaticVariable(name: String,
|
|||||||
}
|
}
|
||||||
|
|
||||||
class IRStArrayElement(val bool: Boolean?, val number: Double?, val addressOfSymbol: String?) {
|
class IRStArrayElement(val bool: Boolean?, val number: Double?, val addressOfSymbol: String?) {
|
||||||
companion object {
|
|
||||||
fun from(elt: StArrayElement): IRStArrayElement {
|
|
||||||
return if(elt.boolean!=null)
|
|
||||||
IRStArrayElement(elt.boolean, null, elt.addressOfSymbol)
|
|
||||||
else
|
|
||||||
IRStArrayElement(null, elt.number, elt.addressOfSymbol)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if(bool!=null) require(number==null && addressOfSymbol==null)
|
if(bool!=null) require(number==null && addressOfSymbol==null)
|
||||||
if(number!=null) require(bool==null && addressOfSymbol==null)
|
if(number!=null) require(bool==null && addressOfSymbol==null)
|
||||||
|
@@ -58,6 +58,9 @@ uword sys.bssvar zp=DONTCARE align=0
|
|||||||
uword sys.wait.jiffies=10 zp=DONTCARE align=0
|
uword sys.wait.jiffies=10 zp=DONTCARE align=0
|
||||||
ubyte[3] sys.emptystring=0,0,0 zp=DONTCARE align=0
|
ubyte[3] sys.emptystring=0,0,0 zp=DONTCARE align=0
|
||||||
</VARIABLESWITHINIT>
|
</VARIABLESWITHINIT>
|
||||||
|
<CONSTANTS>
|
||||||
|
ubyte main.thing=42
|
||||||
|
</CONSTANTS>
|
||||||
|
|
||||||
<MEMORYMAPPEDVARIABLES>
|
<MEMORYMAPPEDVARIABLES>
|
||||||
@uword cx16.r0=65282
|
@uword cx16.r0=65282
|
||||||
@@ -104,6 +107,7 @@ 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
|
||||||
|
program.st.allConstants().count() shouldBe 1
|
||||||
val var1 = program.st.lookup("sys.wait.jiffies") as IRStStaticVariable
|
val var1 = program.st.lookup("sys.wait.jiffies") as IRStStaticVariable
|
||||||
val var2 = program.st.lookup("sys.bssvar") as IRStStaticVariable
|
val var2 = program.st.lookup("sys.bssvar") as IRStStaticVariable
|
||||||
val var3 = program.st.lookup("sys.emptystring") as IRStStaticVariable
|
val var3 = program.st.lookup("sys.emptystring") as IRStStaticVariable
|
||||||
|
@@ -105,6 +105,8 @@ class TestVm: FunSpec( {
|
|||||||
</VARIABLESNOINIT>
|
</VARIABLESNOINIT>
|
||||||
<VARIABLESWITHINIT>
|
<VARIABLESWITHINIT>
|
||||||
</VARIABLESWITHINIT>
|
</VARIABLESWITHINIT>
|
||||||
|
<CONSTANTS>
|
||||||
|
</CONSTANTS>
|
||||||
|
|
||||||
<MEMORYMAPPEDVARIABLES>
|
<MEMORYMAPPEDVARIABLES>
|
||||||
</MEMORYMAPPEDVARIABLES>
|
</MEMORYMAPPEDVARIABLES>
|
||||||
|
Reference in New Issue
Block a user