fixed return values problem and wrong optimization into jump

This commit is contained in:
Irmen de Jong 2018-12-12 00:15:05 +01:00
parent 756930a54f
commit d6cf8bcce0
8 changed files with 58 additions and 48 deletions

View File

@ -48,8 +48,7 @@
; c64.CHROUT('\n')
if guess==secretnumber {
ending(true)
return ; @todo make return ending(true) actually work as well
return ending(true)
} else {
c64scr.print_string("\n\nThat is too ")
if guess<secretnumber
@ -59,12 +58,7 @@
}
}
; return 99 ;@todo error message (no return values)
; return 99,44 ;@todo error message (no return values)
; return ending(false) ; @todo fix this, actuall needs to CALL ending even though no value is returned
ending(false)
return ; @todo make return ending(false) actually work as well
return ending(false)
sub ending(success: ubyte) {
@ -78,10 +72,6 @@
c64scr.print_string("Thanks for playing, ")
c64scr.print_string(name)
c64scr.print_string(".\n")
; return 99 ; @todo error message (no return values)
; return 99,44 ; @todo error message (no return values)
; return 99,44 ; @todo should check number of return values!!
}
}
}

View File

@ -17,7 +17,8 @@
vm_write_str("\nYou have ")
vm_write_num(attempts_left)
vm_write_str(" guess")
if attempts_left>1 vm_write_str("es")
if attempts_left>1
vm_write_str("es")
vm_write_str(" left. What is your next guess? ")
vm_input_str(guess)
ubyte guessednumber = str2ubyte(guess)

View File

@ -1,26 +1,15 @@
%output raw
%launcher none
%import c64utils
~ main {
sub start() {
ending(true)
return ; @todo make return ending(true) actually work as well
return 99 ;@todo error message (no return values)
return 99,44 ;@todo error message (no return values)
return ending(false) ; @todo fix this, actuall needs to CALL ending even though no value is returned
return ending(true) ;; @todo fix argument passing!
sub ending(success: ubyte) {
return 99 ; @todo error message (no return values)
return 99,44 ; @todo error message (no return values)
return 99,44 ; @todo should check number of return values!!
}
sub ending2() -> ubyte {
return
return 1
return 2, 2 ; @todo error message number of return values
c64scr.print_byte_decimal(success)
c64scr.print_byte_decimal(success)
c64scr.print_byte_decimal(success)
c64.CHROUT('\n')
}
}
}

View File

@ -7,7 +7,7 @@ import kotlin.system.exitProcess
fun main(args: Array<String>) {
println("\nProg8 StackVM by Irmen de Jong (irmen@razorvine.net)")
// @todo software license string
// @todo decide on software license
// println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n")
println("**** This is a prerelease version. Please do not distribute! ****\n")

View File

@ -96,9 +96,9 @@ class AstChecker(private val namespace: INameScope,
if(returnStmt.values.size==1 && returnStmt.values[0] is FunctionCall) {
val dt = (returnStmt.values[0] as FunctionCall).resultingDatatype(namespace, heap)
if(dt!=null && expectedReturnValues.isEmpty())
checkResult.add(SyntaxError("number of return values doesn't match subroutine return spec", returnStmt.position))
checkResult.add(SyntaxError("invalid number of return values", returnStmt.position))
} else
checkResult.add(SyntaxError("number of return values doesn't match subroutine return spec", returnStmt.position))
checkResult.add(SyntaxError("invalid number of return values", returnStmt.position))
}
for (rv in expectedReturnValues.withIndex().zip(returnStmt.values)) {

View File

@ -177,6 +177,8 @@ class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
if(returnStmt.values.isNotEmpty()) {
// possibly adjust any literal values returned, into the desired returning data type
val subroutine = returnStmt.definingSubroutine()!!
if(subroutine.returntypes.size!=returnStmt.values.size)
return returnStmt // mismatch in number of return values, error will be printed later.
val newValues = mutableListOf<IExpression>()
for(returnvalue in returnStmt.values.zip(subroutine.returntypes)) {
val lval = returnvalue.first as? LiteralValue

View File

@ -41,13 +41,53 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
optimizeDataConversionAndUselessDiscards()
optimizeVariableCopying()
optimizeMultipleSequentialLineInstrs()
optimizeCallReturnIntoJump()
optimizeRestoreXSaveXIntoRestoreX()
// todo: optimize stackvm code more
// todo: stackvm replace rrestorex+rsavex combo by only rrestorex (note: can have label/comment inbetween)
// todo: stackvm replace call X + return (without values) combo by a jump X
optimizeRemoveNops() // must be done as the last step
optimizeMultipleSequentialLineInstrs() // once more
optimizeRemoveNops() // once more
}
private fun optimizeRemoveNops() {
// remove nops (that are not a label)
for (blk in blocks) {
for (blk in blocks)
blk.instructions.removeIf { it.opcode== Opcode.NOP && it !is LabelInstr }
}
private fun optimizeRestoreXSaveXIntoRestoreX() {
// replace rrestorex+rsavex combo by only rrestorex
for(blk in blocks) {
val instructionsToReplace = mutableMapOf<Int, Instruction>()
blk.instructions.asSequence().withIndex().filter {it.value.opcode!=Opcode.LINE}.windowed(2).toList().forEach {
if(it[0].value.opcode==Opcode.RRESTOREX && it[1].value.opcode==Opcode.RSAVEX) {
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
}
for (rins in instructionsToReplace) {
blk.instructions[rins.key] = rins.value
}
}
}
private fun optimizeCallReturnIntoJump() {
// replaces call X followed by return, by jump X
for(blk in blocks) {
val instructionsToReplace = mutableMapOf<Int, Instruction>()
blk.instructions.asSequence().withIndex().filter {it.value.opcode!=Opcode.LINE}.windowed(2).toList().forEach {
if(it[0].value.opcode==Opcode.CALL && it[1].value.opcode==Opcode.RETURN) {
instructionsToReplace[it[1].index] = Instruction(Opcode.JUMP, callLabel = it[0].value.callLabel)
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
}
}
for (rins in instructionsToReplace) {
blk.instructions[rins.key] = rins.value
}
}
}

View File

@ -67,18 +67,6 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
return super.process(functionCall)
}
override fun process(returnStmt: Return): IStatement {
// if the return value is a subroutine call, replace this with a jump to the subroutine
if(returnStmt.values.size==1 && returnStmt.values[0] is FunctionCall) {
val call = returnStmt.values[0] as FunctionCall
if(call.target.targetStatement(namespace) is Subroutine) {
optimizationsDone++
return Jump(null, call.target, null, call.position)
}
}
return super.process(returnStmt)
}
override fun process(ifStatement: IfStatement): IStatement {
super.process(ifStatement)
val constvalue = ifStatement.condition.constValue(namespace, heap)