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 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);
@ -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));
LOG("+LOOP, i=%d, step %d, limit %d", fh->loop_i, val, limit);
index0 = fh->loop_i;
fh->loop_i += val;
LOG("after add: %d", fh->loop_i);
// FIXME this is probably wrong
// FIXME yes it actually is wrong
if (((int32_t)index0 < (int32_t)limit) == ((int32_t)fh->loop_i < (int32_t)limit) && fh->loop_i != limit) { // boundary not crossed, continue
fh->execptr = instr->data; // go to beginning
} else {
const int32_t vi = (int32_t)val;
const int32_t bdr = (int32_t)limit - (int32_t)1;
const int32_t i0 = (int32_t)fh->loop_i;
fh->loop_i += val; // this can overflow
const int32_t i1 = (int32_t)fh->loop_i;
// TODO this can probably be optimized
if (
(vi > 0 && i0 <= bdr && i1 > bdr)
|| (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
TRY(rs_pop(fh, &limit));
TRY(fh_loop_unnest(fh));
} else {
//LOGE("continue loop");
// continue the loop
fh->execptr = instr->data;
}
goto instr;

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