diff options
| author | 2026-03-08 18:38:33 +0100 | |
|---|---|---|
| committer | 2026-03-08 19:03:56 +0100 | |
| commit | 429bb2eaaa1f2dd62b7cab8eaaf7d1f20b738a93 (patch) | |
| tree | 20dd7439f77211b9d437c755724e579353e8c9aa /ir | |
| parent | 18304d695eb69e6e8776e82c305c6798d42ca1f7 (diff) | |
ir/fold: fix float conversion overflows
Diffstat (limited to 'ir')
| -rw-r--r-- | ir/fold.c | 18 |
1 files changed, 14 insertions, 4 deletions
@@ -1,6 +1,10 @@ #include "ir.h" #include "../endian.h" +#include <limits.h> +#ifdef __clang__ +__attribute__((no_sanitize("float-cast-overflow"))) /* silence UBsan for float->int overflow */ +#endif static union ref foldint(enum op op, enum irclass k, union ref lr, union ref rr) { @@ -15,10 +19,16 @@ foldint(enum op op, enum irclass k, union ref lr, union ref rr) case Ocopy: x = l.s; break; case Oneg: x = -l.s; break; case Onot: x = ~l.s; break; - case Ocvtf32s: x = (int)(float)fltconval(lr); break; - case Ocvtf32u: x = (uint)(float)fltconval(lr); break; - case Ocvtf64s: x = (vlong)fltconval(lr); break; - case Ocvtf64u: x = (uvlong)fltconval(lr); break; +#define CVTF2I(TF, TI) do { \ + TF f = fltconval(lr); \ + if (f != f) x = 0; \ + else x = (TI)f; \ +} while (0) + case Ocvtf32s: if (w) CVTF2I(float, vlong); else CVTF2I(float, int); break; + case Ocvtf32u: if (w) CVTF2I(float, uvlong); else CVTF2I(float, uint); break; + case Ocvtf64s: if (w) CVTF2I(double, vlong); else CVTF2I(double, int); break; + case Ocvtf64u: if (w) CVTF2I(double, uvlong); else CVTF2I(double, uint); break; +#undef CVTF2I case Oexts8: x = (schar)l.s; break; case Oextu8: x = (uchar)l.s; break; case Oexts16: x = (short)l.s; break; |