for loop generates working code for the most often occurring loop scenarios

This commit is contained in:
Irmen de Jong 2018-09-22 02:38:53 +02:00
parent f84e06bdeb
commit 4174d49fb3
2 changed files with 111 additions and 59 deletions

View File

@ -8,38 +8,62 @@ sub start() -> () {
byte from = 0 byte from = 0
byte last = 5 byte last = 5
if (i>last) { word iw
_vm_write_num(100)
word fromw = 0
word lastw = 5
for i in 10 to 1 step -1 {
_vm_write_num(i)
_vm_write_char($8d) _vm_write_char($8d)
} }
_vm_write_char($8d)
_vm_write_char($8d)
for i in 10 to 0 step -1 {
_vm_write_num(i)
_vm_write_char($8d)
}
_vm_write_char($8d)
_vm_write_char($8d)
for i in from to last {
_vm_write_num(i)
_vm_write_char($8d)
}
_vm_write_char($8d)
_vm_write_char($8d)
from=250
last=255
for i in from to last {
_vm_write_num(i)
_vm_write_char($8d)
}
_vm_write_char($8d)
_vm_write_char($8d)
fromw=65530
lastw=65535
for iw in fromw to lastw {
_vm_write_num(iw)
_vm_write_char($8d)
}
_vm_write_char($8d)
_vm_write_char($8d)
; for i in from to last { from = 5
; _vm_write_num(i) last = 1
; _vm_write_char($8d)
; }
; _vm_write_char($8d)
; _vm_write_char($8d)
; from=250 fromw = 1
; last=255 lastw = 5
; for i in from to last {
; _vm_write_num(i)
; _vm_write_char($8d)
; }
; _vm_write_char($8d)
; _vm_write_char($8d)
;
;
; from = 8
; last = 0
;
; for i in from to last step -1 {
; _vm_write_num(i)
; _vm_write_char($8d)
; }
; _vm_write_char($8d)
; _vm_write_char($8d)
for iw in fromw to lastw step 1 { ;@todo last 0
_vm_write_num(iw)
_vm_write_char($8d)
}
_vm_write_char($8d)
_vm_write_char($8d)
} }
} }

View File

@ -212,6 +212,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
* other_stuff ;; optional * other_stuff ;; optional
* _stmt_999_end: * _stmt_999_end:
* nop * nop
*
* @todo generate more efficient bytecode for the form with just jumps: if_xx goto .. [else goto ..] ?
* -> this should translate into just a single branch opcode per goto
*/ */
stackvmProg.line(branch.position) stackvmProg.line(branch.position)
val labelElse = makeLabel("else") val labelElse = makeLabel("else")
@ -258,17 +261,18 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
* *
* or when there is no else block: * or when there is no else block:
* <condition-expression evaluation> * <condition-expression evaluation>
* BNZ _stmt_999_end * BZ _stmt_999_end
* stuff * stuff
* _stmt_999_end: * _stmt_999_end:
* nop * nop
* *
* @todo generate more efficient bytecode for the form with just jumps: if(..) goto .. [else goto ..]
*/ */
stackvmProg.line(stmt.position) stackvmProg.line(stmt.position)
translate(stmt.condition) translate(stmt.condition)
val labelEnd = makeLabel("end") val labelEnd = makeLabel("end")
if(stmt.elsepart.isEmpty()) { if(stmt.elsepart.isEmpty()) {
stackvmProg.instr(Opcode.BNZ, callLabel = labelEnd) stackvmProg.instr(Opcode.BZ, callLabel = labelEnd)
translate(stmt.statements) translate(stmt.statements)
stackvmProg.label(labelEnd) stackvmProg.label(labelEnd)
} else { } else {
@ -319,7 +323,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
} }
} }
is RangeExpr -> { is RangeExpr -> {
TODO("TRANSLATE range $expr") // todo TODO("TRANSLATE range $expr")
} }
else -> { else -> {
val lv = expr.constValue(namespace) ?: throw CompilerException("constant expression required, not $expr") val lv = expr.constValue(namespace) ?: throw CompilerException("constant expression required, not $expr")
@ -540,7 +544,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
else if (range.count()==1) else if (range.count()==1)
throw CompilerException("loop over just 1 value should have been optimized away") throw CompilerException("loop over just 1 value should have been optimized away")
if((range.last-range.first) % range.step != 0) if((range.last-range.first) % range.step != 0)
throw CompilerException("range first and last must be inclusive") throw CompilerException("range first and last must be exactly inclusive")
when (loopVarDt) { when (loopVarDt) {
DataType.BYTE -> { DataType.BYTE -> {
if (range.first < 0 || range.first > 255 || range.last < 0 || range.last > 255) if (range.first < 0 || range.first > 255 || range.last < 0 || range.last > 255)
@ -660,9 +664,17 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
* ..continue statement: goto continue * ..continue statement: goto continue
* .. * ..
* continue: * continue:
* LV ++ / LV-- (if step =1 or step=-1) *
* LV += step (otherwise) * (if we know step is a constant:)
* goto loop * step == 1 ->
* LV++
* if_nz goto loop ;; acts as overflow check
* step == -1 ->
* LV--
* @todo some condition to check for not overflow , jump to loop
* (not constant or other step:
* LV += step ; @todo implement overflow on the appropriate arithmetic operations
* if_vc goto loop ;; not overflowed
* break: * break:
* nop * nop
*/ */
@ -687,6 +699,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
stackvmProg.label(loopLabel) stackvmProg.label(loopLabel)
if(literalStepValue!=null) { if(literalStepValue!=null) {
// Step is a constant. We can optimize some stuff!
val loopVar = val loopVar =
if(varname!=null) if(varname!=null)
IdentifierReference(varname, range.position) IdentifierReference(varname, range.position)
@ -708,34 +721,49 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
ifstmt.linkParents(range.parent) ifstmt.linkParents(range.parent)
translate(ifstmt) translate(ifstmt)
} else { } else {
// generate code for the whole if statement // Step is a variable. We can't optimize anything...
TODO("code for non-constant step comparison") TODO("code for non-constant step comparison of LV")
} }
stackvmProg.label("body_goes_here") // todo weg translate(body)
stackvmProg.label(continueLabel)
val lvTarget = makeAssignmentTarget()
lvTarget.linkParents(range.parent)
val targetStatement: VarDecl? =
if(lvTarget.identifier!=null) {
lvTarget.identifier.targetStatement(namespace) as VarDecl
} else {
null
}
// translate(body) when (literalStepValue) {
// stackvmProg.label(continueLabel) 1 -> {
// when (literalStepValue) { // LV++
// 1 -> { val postIncr = PostIncrDecr(lvTarget, "++", range.position)
// // LV++ postIncr.linkParents(range.parent)
// val postIncr = PostIncrDecr(makeAssignmentTarget(), "++", range.position) translate(postIncr)
// postIncr.linkParents(range.parent) if(lvTarget.register!=null)
// translate(postIncr) stackvmProg.instr(Opcode.PUSH_VAR, Value(DataType.STR, null, stringvalue=lvTarget.register.toString()))
// } else
// -1 -> { stackvmProg.instr(Opcode.PUSH_VAR, Value(DataType.STR, null, stringvalue=targetStatement!!.scopedname))
// // LV-- val branch = BranchStatement(
// val postIncr = PostIncrDecr(makeAssignmentTarget(), "--", range.position) BranchCondition.NZ,
// postIncr.linkParents(range.parent) listOf(Jump(null, null, loopLabel, range.position)),
// translate(postIncr) emptyList(), range.position)
// } branch.linkParents(range.parent)
// else -> { translate(branch)
// // LV += step }
// val addAssignment = Assignment(makeAssignmentTarget(), "+=", range.step, range.position) -1 -> {
// addAssignment.linkParents(range.parent) // LV--
// translate(addAssignment) val postIncr = PostIncrDecr(makeAssignmentTarget(), "--", range.position)
// } postIncr.linkParents(range.parent)
// } translate(postIncr)
TODO("signed numbers and/or special condition still needed for decreasing for loop. Try increasing loop and/or constant loop values instead? At: ${range.position}")
}
else -> {
TODO("non-literal-const or other-than-one step increment code At: ${range.position}")
}
}
stackvmProg.label(breakLabel) stackvmProg.label(breakLabel)
stackvmProg.instr(Opcode.NOP) stackvmProg.instr(Opcode.NOP)