Over/Underflow in closed vector limits
fsantanna opened this issue · 3 comments
The runtime decrements the starting limit 0[
:
var int ret = 1;
var u8 i;
loop i in [0->0[ do
ret = ret + 1;
end
escape ret;
This bug is not specific to u8, u16 or even u32 or restricted to unsigned types. The current logic is utterly flawed, e.g. try [0->253[, 50 or step 250 for fun.
Here is how Céu could generate a different kind of loop expansion. I'm making use of the excellent overflow detection API introduced with GCC version 5. LLVM supports it too.
int main() {
unsigned int ret = 0;
unsigned char start = 0, stop = 0, step = 1;
assert(step > 0); // says the Céu manual
for ( ; start < stop // Use either < with [a -> b[ or <= with [a -> b]
; ({if (__builtin_add_overflow(start,step,&start)) goto end;})) {
// for() supports both break; and continue; statements.
printf(" ..%u", start);
ret = ret + 1;
}
end: // gensym this label, of course
printf(" ->%u\n", ret);
return 0;
}
Conversely, a descending loop [ <- ] would use __builtin_sub_overflow().
I'm using another GCC extension, namely ({ statements as expressions }) so that the complete step fits for(;;step) syntax. That allows to support continue;
statements within the loop. Céu actually doesn't need that because it compiles Céu break and continue statements to C goto expressions; but well, I thought: "What if the user writes { continue; }
as a C escape inside one Céu loop?".
thanks
It's good that ceu-maker 0.40 updated the embedded Arduino package from 1.8.3 to 1.8.8. The old one contains avr-gcc version 4.9.2; however GCC did not support __builtin_add_overflow
until GCC 5.x. The new package contains GCC 5.4.0.
Overflow detection could be written without these helper functions, but it's touch to get right (avoiding undefined behaviour in C with signed overflow) and there are many different cases to consider (unsigned vs. s8/s16/s32, addition and substraction).