fix array processing and ASM code gen of arrays with addressOf in them

This commit is contained in:
Irmen de Jong 2019-04-12 00:04:15 +02:00
parent 9f302cc640
commit 3f93b87745
11 changed files with 92 additions and 31 deletions

View File

@ -210,6 +210,7 @@ interface IAstProcessor {
}
fun process(literalValue: LiteralValue): LiteralValue {
literalValue.arrayvalue?.forEach { it.process(this) }
return literalValue
}
@ -290,6 +291,7 @@ interface IAstProcessor {
}
fun process(addressOf: AddressOf): IExpression {
process(addressOf.identifier)
return addressOf
}
}
@ -1018,6 +1020,7 @@ data class AddressOf(val identifier: IdentifierReference, override val position:
identifier.parent=this
}
var scopedname: String? = null // will be set in a later state by the compiler
override fun isIterable(namespace: INameScope, heap: HeapValues) = false
override fun constValue(namespace: INameScope, heap: HeapValues): LiteralValue? = null
override fun referencesIdentifier(name: String) = false

View File

@ -464,7 +464,9 @@ private class AstChecker(private val namespace: INameScope,
if(variable.datatype !in ArrayDatatypes && variable.datatype !in StringDatatypes)
checkResult.add(ExpressionError("pointer-of operand must be the name of a string or array heap variable", addressOf.position))
}
return addressOf
if(addressOf.scopedname==null)
throw FatalAstException("the scopedname of AddressOf should have been set by now $addressOf")
return super.process(addressOf)
}
/**

View File

@ -20,7 +20,7 @@ fun Module.checkIdentifiers(namespace: INameScope) {
val parent = variable.first.parent
when {
parent is Assignment && parent.value === variable.first -> {
val idref = IdentifierReference(listOf("$${variable.first.heapId}"), variable.first.position)
val idref = IdentifierReference(listOf("$autoHeapValuePrefix${variable.first.heapId}"), variable.first.position)
idref.linkParents(parent)
parent.value = idref
}
@ -229,6 +229,14 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
}
return super.process(literalValue)
}
override fun process(addressOf: AddressOf): IExpression {
// register the scoped name of the referenced identifier
val variable= addressOf.identifier.targetStatement(namespace) as? VarDecl ?: return addressOf
addressOf.scopedname = variable.scopedname
return super.process(addressOf)
}
}
internal const val autoHeapValuePrefix = "auto_heap_value_"

View File

@ -279,6 +279,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
val variable = idref.targetStatement(namespace) as? VarDecl
if(variable!=null && (variable.datatype in StringDatatypes || variable.datatype in ArrayDatatypes)) {
val pointerExpr = AddressOf(idref, idref.position)
pointerExpr.scopedname = (idref.parent as IStatement).makeScopedName(idref.nameInSource.single())
pointerExpr.linkParents(arglist[argparam.first.index].parent)
arglist[argparam.first.index] = pointerExpr
}
@ -289,6 +290,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
val autoVarName = "$autoHeapValuePrefix${strvalue.heapId}"
val autoHeapvarRef = IdentifierReference(listOf(autoVarName), strvalue.position)
val pointerExpr = AddressOf(autoHeapvarRef, strvalue.position)
pointerExpr.scopedname = (strvalue.parent as IStatement).makeScopedName(autoVarName)
pointerExpr.linkParents(arglist[argparam.first.index].parent)
arglist[argparam.first.index] = pointerExpr
// add a vardecl so that the autovar can be resolved in later lookups
@ -296,7 +298,6 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
addVarDecl(strvalue.definingScope(), variable)
}
}
else throw FatalAstException("expected either an identifier or a literal as argument to $subroutine")
}
}
}

View File

@ -13,6 +13,7 @@ import prog8.stackvm.Syscall
import java.io.File
import java.nio.file.Path
import java.util.*
import javax.lang.model.type.ArrayType
import kotlin.math.abs
@ -81,15 +82,17 @@ class HeapValues {
fun addIntegerArray(type: DataType, array: Array<IntegerOrAddressOf>): Int {
// arrays are never shared, don't check for existing
if(type !in ArrayDatatypes)
throw CompilerException("wrong array type")
val newId = heapId++
heap[newId] = HeapValue(type, null, array, null)
return newId
}
fun addDoublesArray(type: DataType, darray: DoubleArray): Int {
fun addDoublesArray(darray: DoubleArray): Int {
// arrays are never shared, don't check for existing
val newId = heapId++
heap[newId] = HeapValue(type, null, null, darray)
heap[newId] = HeapValue(DataType.ARRAY_F, null, null, darray)
return newId
}
@ -2134,16 +2137,16 @@ internal class Compiler(private val rootModule: Module,
}
}
private fun translate(ptrof: AddressOf) {
val target = ptrof.identifier.targetStatement(namespace) as VarDecl
private fun translate(addrof: AddressOf) {
val target = addrof.identifier.targetStatement(namespace) as VarDecl
if(target.datatype in ArrayDatatypes || target.datatype in StringDatatypes|| target.datatype==DataType.FLOAT) {
pushHeapVarAddress(ptrof.identifier, false)
pushHeapVarAddress(addrof.identifier, false)
}
else if(target.datatype==DataType.FLOAT) {
pushFloatAddress(ptrof.identifier)
pushFloatAddress(addrof.identifier)
}
else
throw CompilerException("cannot take memory pointer $ptrof")
throw CompilerException("cannot take memory pointer $addrof")
}
private fun translateAsmInclude(args: List<DirectiveArg>, importedFrom: Path) {

View File

@ -14,9 +14,9 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
class ProgramBlock(val name: String,
var address: Int?,
val instructions: MutableList<Instruction> = mutableListOf(),
val variables: MutableMap<String, Value> = mutableMapOf(),
val variables: MutableMap<String, Value> = mutableMapOf(), // names are fully scoped
val memoryPointers: MutableMap<String, Pair<Int, DataType>> = mutableMapOf(),
val labels: MutableMap<String, Instruction> = mutableMapOf(),
val labels: MutableMap<String, Instruction> = mutableMapOf(), // names are fully scoped
val force_output: Boolean)
{
val numVariables: Int
@ -468,7 +468,12 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
val arrayvalues = it.value.array!!.map { av ->
when {
av.integer!=null -> av.integer.toString()
av.addressOf!=null -> "&${av.addressOf.identifier}"
av.addressOf!=null -> {
if(av.addressOf.scopedname==null)
throw CompilerException("AddressOf scopedname should have been set")
else
"&${av.addressOf.scopedname}"
}
else -> throw CompilerException("weird array value")
}
}

View File

@ -364,10 +364,11 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// byte array can never contain pointer-to types, so treat values as all integers
array.map { "$"+it.integer!!.toString(16).padStart(2, '0') }
value.type==DataType.ARRAY_UW -> array.map {
if(it.integer!=null)
"$"+it.integer.toString(16).padStart(2, '0')
else
TODO("deal with addressOf")
when {
it.integer!=null -> "$"+it.integer.toString(16).padStart(2, '0')
it.addressOf!=null -> symname(it.addressOf.scopedname!!, block)
else -> throw AssemblyError("weird type in array")
}
}
else -> throw AssemblyError("invalid arrayspec type")
}

View File

@ -82,8 +82,8 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
if(fillvalue< FLOAT_MAX_NEGATIVE || fillvalue> FLOAT_MAX_POSITIVE)
errors.add(ExpressionError("float value overflow", litval?.position ?: decl.position))
else {
val heapId = heap.addDoublesArray(decl.datatype, DoubleArray(size) { fillvalue })
decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval?.position ?: decl.position)
val heapId = heap.addDoublesArray(DoubleArray(size) { fillvalue })
decl.value = LiteralValue(DataType.ARRAY_F, heapId = heapId, position = litval?.position ?: decl.position)
}
}
}
@ -551,10 +551,15 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
addError(ExpressionError("array literal can only consist of constant primitive numerical values or memory pointers", arraylit.position))
return arraylit
} else if(array.any {it is AddressOf}) {
val arrayDt = DataType.UWORD
val intArrayWithAddressOfs = mutableListOf<IntegerOrAddressOf>()
// TODO AddressOf: FILL THIS ARRAY
val heapId = heap.addIntegerArray(DataType.UWORD, intArrayWithAddressOfs.toTypedArray())
val arrayDt = DataType.ARRAY_UW
val intArrayWithAddressOfs = array.map {
when (it) {
is AddressOf -> IntegerOrAddressOf(null, it)
is LiteralValue -> IntegerOrAddressOf(it.asIntegerValue, null)
else -> throw CompilerException("invalid datatype in array")
}
}
val heapId = heap.addIntegerArray(arrayDt, intArrayWithAddressOfs.toTypedArray())
return LiteralValue(arrayDt, heapId = heapId, position = arraylit.position)
} else {
// array is only constant numerical values
@ -594,7 +599,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
DataType.ARRAY_B,
DataType.ARRAY_UW,
DataType.ARRAY_W -> heap.addIntegerArray(arrayDt, integerArray.map { IntegerOrAddressOf(it, null) }.toTypedArray())
DataType.ARRAY_F -> heap.addDoublesArray(arrayDt, doubleArray)
DataType.ARRAY_F -> heap.addDoublesArray(doubleArray)
else -> throw CompilerException("invalid arrayspec type")
}
return LiteralValue(arrayDt, heapId = heapId, position = arraylit.position)

View File

@ -92,13 +92,25 @@ class Program (val name: String,
DataType.ARRAY_UB, DataType.ARRAY_B,
DataType.ARRAY_UW, DataType.ARRAY_W -> {
val numbers = it.third.substring(1, it.third.length-1).split(',')
val intarray = numbers.map{number->IntegerOrAddressOf(number.trim().toInt(), null)}.toTypedArray()
val intarray = numbers.map{number->
val num=number.trim()
if(num.startsWith("&")) {
// it's AddressOf
val scopedname = num.substring(1)
val iref = IdentifierReference(scopedname.split('.'), Position("<intermediate>", 0,0,0))
val addrOf = AddressOf(iref, Position("<intermediate>", 0,0,0))
addrOf.scopedname=scopedname
IntegerOrAddressOf(null, addrOf)
} else {
IntegerOrAddressOf(num.toInt(), null)
}
}.toTypedArray()
heap.addIntegerArray(it.second, intarray)
}
DataType.ARRAY_F -> {
val numbers = it.third.substring(1, it.third.length-1).split(',')
val doublearray = numbers.map{number->number.trim().toDouble()}.toDoubleArray()
heap.addDoublesArray(it.second, doublearray)
heap.addDoublesArray(doublearray)
}
in NumericDatatypes -> throw VmExecutionException("invalid heap value type ${it.second}")
else -> throw VmExecutionException("weird datatype")

View File

@ -1659,10 +1659,16 @@ class StackVm(private var traceOutputFile: String?) {
when(array.type){
DataType.ARRAY_UW -> {
val value = array.array!![index]
if(value.integer!=null)
Value(DataType.UWORD, value.integer)
else
TODO("deal with addressOf $value")
when {
value.integer!=null -> Value(DataType.UWORD, value.integer)
value.addressOf!=null -> {
val heapId = variables.getValue(value.addressOf.scopedname!!).heapId
if(heapId<0)
throw VmExecutionException("expected variable on heap")
evalstack.push(Value(DataType.UWORD, heapId)) // push the "address" of the string or array variable (this is taken care of properly in the assembly code generator)
}
else -> throw VmExecutionException("strange array value")
}
}
DataType.ARRAY_W -> Value(DataType.WORD, array.array!![index].integer!!)
else -> throw VmExecutionException("not a proper arrayspec var with word elements")
@ -2287,6 +2293,13 @@ class StackVm(private var traceOutputFile: String?) {
val number = lo+256*hi
canvas?.printText(number.toString(), 1, true)
}
Syscall.SYSASM_c64scr_print_uwhex -> {
val prefix = if(this.P_carry) "$" else ""
val lo = variables.getValue("A").integerValue()
val hi = variables.getValue("Y").integerValue()
val number = lo+256*hi
canvas?.printText("$prefix${number.toString(16).padStart(4, '0')}", 1, true)
}
Syscall.SYSASM_c64scr_print_w -> {
val lo = variables.getValue("A").integerValue()
val hi = variables.getValue("Y").integerValue()

View File

@ -23,7 +23,7 @@
pointer2 = &array2
pointer3 = &string1
; uword[4] pointers = [&array1, &array2, &string1, &string2] ; @todo make it possible to initialize array with pointers
uword[4] pointers = [&array1, &array2, &string1, &string2] ; @todo make it possible to initialize array with pointers
ptrsubasm("moet werken")
@ -72,3 +72,11 @@
}
}
~ test {
sub testsub() {
uword[4] pointers = [&main.start.array1, &main.start.array2, &main.start.string1, &main.start.string2] ; @todo make it possible to initialize array with pointers
}
}