aboutsummaryrefslogtreecommitdiffhomepage
path: root/ir
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2026-03-08 18:38:33 +0100
committerlemon <lsof@mailbox.org>2026-03-08 19:03:56 +0100
commit429bb2eaaa1f2dd62b7cab8eaaf7d1f20b738a93 (patch)
tree20dd7439f77211b9d437c755724e579353e8c9aa /ir
parent18304d695eb69e6e8776e82c305c6798d42ca1f7 (diff)
ir/fold: fix float conversion overflows
Diffstat (limited to 'ir')
-rw-r--r--ir/fold.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/ir/fold.c b/ir/fold.c
index ba50e40..92d17fa 100644
--- a/ir/fold.c
+++ b/ir/fold.c
@@ -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;