fix loop end checking

master
Ondřej Hruška 3 years ago
parent f23c8260c9
commit 090cbd1fc5
  1. 32
      src/fh_runtime.c
  2. 3
      testfiles/ovfloop.f

@ -133,7 +133,7 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
uint32_t strl; uint32_t strl;
uint32_t val; uint32_t val;
uint32_t limit, index, index0; uint32_t limit, index;
LOG("0x%08x: Instr %s, 0x%08x", fh->execptr, instr_name(instr->kind), instr->data); LOG("0x%08x: Instr %s, 0x%08x", fh->execptr, instr_name(instr->kind), instr->data);
@ -271,20 +271,28 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
TRY(rs_peek(fh, &limit)); TRY(rs_peek(fh, &limit));
LOG("+LOOP, i=%d, step %d, limit %d", fh->loop_i, val, limit); LOG("+LOOP, i=%d, step %d, limit %d", fh->loop_i, val, limit);
index0 = fh->loop_i; const int32_t vi = (int32_t)val;
fh->loop_i += val; const int32_t bdr = (int32_t)limit - (int32_t)1;
const int32_t i0 = (int32_t)fh->loop_i;
LOG("after add: %d", fh->loop_i); fh->loop_i += val; // this can overflow
const int32_t i1 = (int32_t)fh->loop_i;
// FIXME this is probably wrong
// FIXME yes it actually is wrong // TODO this can probably be optimized
if (((int32_t)index0 < (int32_t)limit) == ((int32_t)fh->loop_i < (int32_t)limit) && fh->loop_i != limit) { // boundary not crossed, continue if (
fh->execptr = instr->data; // go to beginning (vi > 0 && i0 <= bdr && i1 > bdr)
} else { || (vi > 0 && i0 > 0 && i1 < 0 && (bdr >= i0 || bdr <= i1))
|| (vi < 0 && i0 > bdr && i1 <= bdr)
|| (vi < 0 && i0 < 0 && i1 > 0 && (bdr <= i0 || bdr >= i1))
) {
//LOGE("end of loop");
// end of loop // end of loop
TRY(rs_pop(fh, &limit)); TRY(rs_pop(fh, &limit));
TRY(fh_loop_unnest(fh)); TRY(fh_loop_unnest(fh));
} else {
//LOGE("continue loop");
// continue the loop
fh->execptr = instr->data;
} }
goto instr; goto instr;

@ -0,0 +1,3 @@
: x 2147483647 -2147483648 DO I . -1 +LOOP ;
x
Loading…
Cancel
Save