aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--c/eval.c3
-rw-r--r--ir/fold.c8
2 files changed, 9 insertions, 2 deletions
diff --git a/c/eval.c b/c/eval.c
index 721401b..8f458da 100644
--- a/c/eval.c
+++ b/c/eval.c
@@ -1,5 +1,6 @@
#include "c.h"
#include "../ir/ir.h"
+#include <limits.h>
static int
targ2hosttype(enum typetag t)
@@ -303,6 +304,7 @@ binop(struct expr *ex, enum evalmode mode)
lhs->u /= rhs->u;
break;
case EDIV|S: if (!rhs->i) return 0;
+ if (lhs->i == LLONG_MIN && rhs->i == -1) break;
lhs->i /= rhs->i;
break;
case EDIV|F: lhs->f /= rhs->f; break;
@@ -311,6 +313,7 @@ binop(struct expr *ex, enum evalmode mode)
lhs->u %= rhs->u;
break;
case EREM|S: if (!rhs->i) return 0;
+ if (lhs->i == LLONG_MIN && rhs->i == -1) lhs->i = 0;
lhs->i %= rhs->i;
break;
diff --git a/ir/fold.c b/ir/fold.c
index 92d17fa..4c9861e 100644
--- a/ir/fold.c
+++ b/ir/fold.c
@@ -41,9 +41,13 @@ foldint(enum op op, enum irclass k, union ref lr, union ref rr)
case Oadd: x = l.u + r.u; break;
case Osub: x = l.u - r.u; break;
case Omul: x = l.u * r.u; break;
- case Odiv: x = w ? l.s / r.s : (int)l.s / (int)r.s; break;
+ case Odiv: if (r.s == -1 && (w ? l.s == LLONG_MIN : (int)l.s == INT_MIN)) x = l.s;
+ else x = w ? l.s / r.s : (int)l.s / (int)r.s;
+ break;
case Oudiv: x = w ? l.u / r.u : (uint)l.u / (uint)r.u; break;
- case Orem: x = w ? l.s % r.s : (int)l.s % (int)r.s; break;
+ case Orem: if (r.s == -1 && (w ? l.s == LLONG_MIN : (int)l.s == INT_MIN)) x = 0;
+ else x = w ? l.s % r.s : (int)l.s % (int)r.s;
+ break;
case Ourem: x = w ? l.u % r.u : (uint)l.u % (uint)r.u; break;
case Oand: x = l.u & r.u; break;
case Oior: x = l.u | r.u; break;