fixed missing initialization of loop index var

This commit is contained in:
Irmen de Jong 2018-12-29 17:02:48 +01:00
parent 9ddda9fcf7
commit 98b9ddac76
5 changed files with 49 additions and 36 deletions

View File

@ -88,7 +88,6 @@
} }
; draw all edges of the object ; draw all edges of the object
; @todo crashes with array index out of bounds in stackvm
for uword edge in edges { for uword edge in edges {
ubyte e_from = msb(edge) ubyte e_from = msb(edge)
ubyte e_to = lsb(edge) ubyte e_to = lsb(edge)

View File

@ -11,49 +11,60 @@
str text = "hello\n" str text = "hello\n"
sub start() { sub start() {
c64scr.print_ub(X)
c64.CHROUT('\n')
c64scr.print("loop str\n")
rpt:
vm_write_str("\nregular for loop byte\n")
for ubyte x in 10 to 15 {
vm_write_num(x)
vm_write_char(',')
}
vm_write_str("\nregular for loop word\n")
for uword y in 500 to 505 {
vm_write_num(y)
vm_write_char(',')
}
vm_write_str("\nloop str\n")
for ubyte c in text { for ubyte c in text {
c64scr.print_ub(c) vm_write_num(c)
c64.CHROUT(',') vm_write_char(',')
} }
c64scr.print("\nloop ub\n") vm_write_str("\nloop ub\n")
for ubyte ub in ubarray{ for ubyte ub in ubarray{
c64scr.print_ub(ub) vm_write_num(ub)
c64.CHROUT(',') vm_write_char(',')
} }
c64scr.print("\nloop b\n") vm_write_str("\nloop b\n")
for byte b in barray { for byte b in barray {
c64scr.print_b(b) vm_write_num(b)
c64.CHROUT(',') vm_write_char(',')
} }
c64scr.print("\nloop uw\n") vm_write_str("\nloop uw\n")
for uword uw in uwarray { for uword uw in uwarray {
c64scr.print_uw(uw) vm_write_num(uw)
c64.CHROUT(',') vm_write_char(',')
} }
c64scr.print("\nloop w\n") vm_write_str("\nloop w\n")
for word w in warray { for word w in warray {
c64scr.print_w(w) vm_write_num(w)
c64.CHROUT(',') vm_write_char(',')
} }
c64scr.print("\nloop f\n") vm_write_str("\nloop f\n")
for float f in farray { for float f in farray {
c64flt.print_f(f) vm_write_num(f)
c64.CHROUT(',') vm_write_char(',')
} }
goto rpt
ending: ending:
c64scr.print("\nending\n") vm_write_str("\nending\n")
c64scr.print_ub(X)
c64.CHROUT('\n')
} }
} }

View File

@ -180,7 +180,7 @@ class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
if(forLoop.iterable !is RangeExpr) { if(forLoop.iterable !is RangeExpr) {
val existing = if(forLoop.body.isEmpty()) null else forLoop.body.lookup(listOf(ForLoop.iteratorLoopcounterVarname), forLoop.body.statements.first()) val existing = if(forLoop.body.isEmpty()) null else forLoop.body.lookup(listOf(ForLoop.iteratorLoopcounterVarname), forLoop.body.statements.first())
if(existing==null) { if(existing==null) {
// create loop iteration counter variable // create loop iteration counter variable (without value, to avoid an assignment)
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, null, ForLoop.iteratorLoopcounterVarname, null, forLoop.loopVar.position) val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, null, ForLoop.iteratorLoopcounterVarname, null, forLoop.loopVar.position)
vardecl.linkParents(forLoop.body) vardecl.linkParents(forLoop.body)
forLoop.body.statements.add(0, vardecl) forLoop.body.statements.add(0, vardecl)

View File

@ -105,7 +105,7 @@ class StatementReorderer(private val namespace: INameScope, private val heap: He
if(decl.type!=VarDeclType.VAR || decl.value==null) if(decl.type!=VarDeclType.VAR || decl.value==null)
return decl return decl
// for variables that are not on the heap (so: byte, word, float), // regarding variables that are not on the heap (so: byte, word, float),
// replace the var decl with an assignment and add a new vardecl with the default constant value. // replace the var decl with an assignment and add a new vardecl with the default constant value.
if(decl.datatype in NumericDatatypes) { if(decl.datatype in NumericDatatypes) {
val scope = decl.definingScope() val scope = decl.definingScope()

View File

@ -1667,13 +1667,17 @@ private class StatementTranslator(private val prog: IntermediateProgram,
val loopLabel = makeLabel("loop") val loopLabel = makeLabel("loop")
val continueLabel = makeLabel("continue") val continueLabel = makeLabel("continue")
val breakLabel = makeLabel("break") val breakLabel = makeLabel("break")
val indexVarType = if (numElements <= 255) DataType.UBYTE else DataType.UWORD
val indexVar = loop.body.getLabelOrVariable(ForLoop.iteratorLoopcounterVarname) as VarDecl
continueStmtLabelStack.push(continueLabel) continueStmtLabelStack.push(continueLabel)
breakStmtLabelStack.push(breakLabel) breakStmtLabelStack.push(breakLabel)
val zero = Value(if (numElements <= 255) DataType.UBYTE else DataType.UWORD, 0) // set the index var to zero before the loop
prog.instr(opcodePush(zero.type), zero) prog.instr(opcodePush(indexVarType), Value(indexVarType, 0))
prog.instr(opcodePopvar(zero.type), callLabel = "Y") prog.instr(opcodePopvar(indexVarType), callLabel = indexVar.scopedname)
// loop starts here
prog.label(loopLabel) prog.label(loopLabel)
val assignTarget = if(loop.loopRegister!=null) val assignTarget = if(loop.loopRegister!=null)
AssignTarget(loop.loopRegister, null, null, loop.position) AssignTarget(loop.loopRegister, null, null, loop.position)
@ -1689,14 +1693,13 @@ private class StatementTranslator(private val prog: IntermediateProgram,
translate(loop.body) translate(loop.body)
prog.label(continueLabel) prog.label(continueLabel)
val loopCounterVar = loop.body.getLabelOrVariable(ForLoop.iteratorLoopcounterVarname) as VarDecl prog.instr(opcodeIncvar(indexVarType), callLabel = indexVar.scopedname)
prog.instr(opcodeIncvar(zero.type), callLabel = loopCounterVar.scopedname)
// TODO: optimize edge cases if last value = 255 or 0 (for bytes) etc. to avoid PUSH_BYTE / SUB opcodes and make use of the wrapping around of the value. // TODO: optimize edge cases if last value = 255 or 0 (for bytes) etc. to avoid PUSH_BYTE / SUB opcodes and make use of the wrapping around of the value.
prog.instr(opcodePush(zero.type), Value(zero.type, numElements)) prog.instr(opcodePush(indexVarType), Value(indexVarType, numElements))
prog.instr(opcodePushvar(zero.type), callLabel = loopCounterVar.scopedname) prog.instr(opcodePushvar(indexVarType), callLabel = indexVar.scopedname)
prog.instr(opcodeSub(zero.type)) prog.instr(opcodeSub(indexVarType))
if(zero.type==DataType.UWORD) if(indexVarType==DataType.UWORD)
prog.instr(Opcode.JNZW, callLabel = loopLabel) prog.instr(Opcode.JNZW, callLabel = loopLabel)
else else
prog.instr(Opcode.JNZ, callLabel = loopLabel) prog.instr(Opcode.JNZ, callLabel = loopLabel)
@ -1735,7 +1738,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
continueStmtLabelStack.push(continueLabel) continueStmtLabelStack.push(continueLabel)
breakStmtLabelStack.push(breakLabel) breakStmtLabelStack.push(breakLabel)
prog.instr(opcodePush(varDt), Value(varDt, range.first)) prog.instr(opcodePush(varDt), Value(varDt, range.first)) // @todo use VariableInitializationStatement instead?? (like other for loop)
prog.instr(opcodePopvar(varDt), callLabel = varname) prog.instr(opcodePopvar(varDt), callLabel = varname)
prog.label(loopLabel) prog.label(loopLabel)
translate(body) translate(body)