fix auto-insertion of AddressOf expression in function call arguments

This commit is contained in:
Irmen de Jong 2019-04-11 21:32:23 +02:00
parent 7780441524
commit 0a73125606
6 changed files with 29 additions and 20 deletions

View File

@ -334,6 +334,7 @@ private class AstChecker(private val namespace: INameScope,
err("a return register is also in the clobber list")
} else {
// TODO: non-asm subroutines can only take numeric arguments for now. (not strings and arrays)
// TODO: AddressOf: can this be improved now that we have '&' ?
// the way string params are treated is almost okay (their address is passed) but the receiving subroutine treats it as an integer rather than referring back to the original string.
// the way array params are treated is buggy; it thinks the subroutine needs a byte parameter in place of a byte[] ...
// This is not easy to fix because strings and arrays are treated a bit simplistic (a "virtual" pointer to the value on the heap)

View File

@ -214,7 +214,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
// Also takes care to insert AddressOf (&) expression where required (string params to a UWORD function param etc).
private val vardeclsToAdd = mutableMapOf<INameScope, MutableList<VarDecl>>()
private val vardeclsToAdd = mutableMapOf<INameScope, MutableMap<String, VarDecl>>()
override fun process(module: Module) {
super.process(module)
@ -222,8 +222,8 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
// add any new vardecls to the various scopes
for(decl in vardeclsToAdd)
for(d in decl.value) {
d.linkParents(decl.key as Node)
decl.key.statements.add(0, d)
d.value.linkParents(decl.key as Node)
decl.key.statements.add(0, d.value)
}
}
@ -234,9 +234,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
if(decl.datatype in NumericDatatypes) {
val scope = decl.definingScope()
if(scope !in vardeclsToAdd)
vardeclsToAdd[scope] = mutableListOf()
vardeclsToAdd.getValue(scope).add(decl.asDefaultValueDecl(null))
addVarDecl(scope, decl.asDefaultValueDecl(null))
val declvalue = decl.value!!
val value =
if(declvalue is LiteralValue) {
@ -269,7 +267,6 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
return functionCallStatement
}
// TODO move this to StatementReorderer instead?
private fun addAddressOfExprIfNeeded(subroutine: Subroutine, arglist: MutableList<IExpression>, parent: Node) {
// functions that accept UWORD and are given an array type, or string, will receive the AddressOf (memory location) of that value instead.
for(argparam in subroutine.parameters.withIndex().zip(arglist)) {
@ -288,13 +285,15 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
}
else if(strvalue!=null) {
if(strvalue.isString) {
println("WANTING TO INSERT & for $strvalue") // TODO
// TODO why does this result later in "pointer-of operand must be the name of a heap variable"
// --> because the AstChecker runs before AstIdentifiersChecker which inserts the actual VarDecl?
val autoHeapvarRef = IdentifierReference(listOf("$autoHeapValuePrefix${strvalue.heapId}"), strvalue.position)
// replace the argument with &autovar
val autoVarName = "$autoHeapValuePrefix${strvalue.heapId}"
val autoHeapvarRef = IdentifierReference(listOf(autoVarName), strvalue.position)
val pointerExpr = AddressOf(autoHeapvarRef, strvalue.position)
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
val variable = VarDecl(VarDeclType.VAR, strvalue.type, false, null, autoVarName, strvalue, strvalue.position)
addVarDecl(strvalue.definingScope(), variable)
}
}
else throw FatalAstException("expected either an identifier or a literal as argument to $subroutine")
@ -302,4 +301,10 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
}
}
private fun addVarDecl(scope: INameScope, variable: VarDecl) {
if(scope !in vardeclsToAdd)
vardeclsToAdd[scope] = mutableMapOf()
vardeclsToAdd.getValue(scope)[variable.name]=variable
}
}

View File

@ -553,7 +553,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
} else if(array.any {it is AddressOf}) {
val arrayDt = DataType.UWORD
val intArrayWithAddressOfs = mutableListOf<IntegerOrAddressOf>()
// TODO FILL THIS ARRAY
// TODO AddressOf: FILL THIS ARRAY
val heapId = heap.addIntegerArray(DataType.UWORD, intArrayWithAddressOfs.toTypedArray())
return LiteralValue(arrayDt, heapId = heapId, position = arraylit.position)
} else {

View File

@ -17,7 +17,8 @@ import kotlin.math.floor
todo remove unused subroutines
todo remove unused strings and arrays from the heap
todo inline subroutines that are called exactly once (regardless of their size)
todo inline subroutines that are only called a few times (3?) and that are "sufficiently small" (0-3 statements)
todo inline subroutines that are only called a few times (max 3?)
todo inline subroutines that are "sufficiently small" (0-3 statements)
todo analyse for unreachable code and remove that (f.i. code after goto or return that has no label so can never be jumped to)
*/

View File

@ -16,23 +16,25 @@
str string2="bye"
uword pointer = &array1
uword pointer2
uword pointer3
byte bt
pointer = &array2
pointer = &string1
pointer2 = &array2
pointer3 = &string1
; uword[4] pointers = [&array1, &array2, &string1, &string2] ; @todo make it possible to initialize array with pointers
;ptrsubasm("moet werken") ; @todo rewrite ast into pointer-of expression (and remove special cases from Compiler)
;pointersub("moet werken") ; @todo rewrite ast into pointer-of expression (and remove special cases from Compiler)
ptrsubasm("moet werken")
pointersub("moet werken")
myprintasm(string1)
myprintasm(string2)
myprintasm("moet werken3")
myprintasm("moet werken3")
myprintasm("moet werken4")
c64scr.print("this print must work\n")
c64.CHROUT('\n')
ptrsubasm(&array1)

View File

@ -109,7 +109,7 @@ varinitializer : vardecl '=' expression ;
constdecl: 'const' varinitializer ;
memoryvardecl: 'memory' varinitializer;
memoryvardecl: 'memory' varinitializer; // TODO replace 'memory' by '&'
datatype: 'ubyte' | 'byte' | 'uword' | 'word' | 'float' | 'str' | 'str_s' ;