aboutsummaryrefslogtreecommitdiff
path: root/qbe.c
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2019-02-16 20:47:45 -0800
committerMichael Forney <mforney@mforney.org>2019-02-16 20:51:11 -0800
commit7d746860bda62c2f382bc0ac82d4d6c8cdf6c7b2 (patch)
tree3b57414a9a175c04d529e43a4be672ee22c1f88d /qbe.c
parent18ad54b003608f3060d4baf2fef00a8a2b6f0a7b (diff)
Extend char/short types before comparing
Thanks to Andrew Chambers for reporting the issue.
Diffstat (limited to 'qbe.c')
-rw-r--r--qbe.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/qbe.c b/qbe.c
index 3d68495..6107bf8 100644
--- a/qbe.c
+++ b/qbe.c
@@ -527,6 +527,19 @@ ftou(struct function *f, struct representation *r, struct value *v)
return funcinst(f, IPHI, r, phi);
}
+static struct value *
+extend(struct function *f, struct type *t, struct value *v)
+{
+ enum instructionkind op;
+
+ switch (t->size) {
+ case 1: op = t->basic.issigned ? IEXTSB : IEXTUB; break;
+ case 2: op = t->basic.issigned ? IEXTSH : IEXTUH; break;
+ default: return v;
+ }
+ return funcinst(f, op, &i32, (struct value *[]){v});
+}
+
struct value *
funcexpr(struct function *f, struct expression *e)
{
@@ -612,6 +625,7 @@ funcexpr(struct function *f, struct expression *e)
srcprop = typeprop(src);
dstprop = typeprop(dst);
if (dst->basic.kind == BASICBOOL) {
+ l = extend(f, src, l);
r = mkintconst(src->repr, 0);
if (srcprop & PROPINT)
op = src->size == 8 ? ICNEL : ICNEW;
@@ -704,36 +718,48 @@ funcexpr(struct function *f, struct expression *e)
op = IXOR;
break;
case TLESS:
+ l = extend(f, t, l);
+ r = extend(f, t, r);
if (t->size <= 4)
op = typeprop(t) & PROPFLOAT ? ICLTS : t->basic.issigned ? ICSLTW : ICULTW;
else
op = typeprop(t) & PROPFLOAT ? ICLTD : t->basic.issigned ? ICSLTL : ICULTL;
break;
case TGREATER:
+ l = extend(f, t, l);
+ r = extend(f, t, r);
if (t->size <= 4)
op = typeprop(t) & PROPFLOAT ? ICGTS : t->basic.issigned ? ICSGTW : ICUGTW;
else
op = typeprop(t) & PROPFLOAT ? ICGTD : t->basic.issigned ? ICSGTL : ICUGTL;
break;
case TLEQ:
+ l = extend(f, t, l);
+ r = extend(f, t, r);
if (t->size <= 4)
op = typeprop(t) & PROPFLOAT ? ICLES : t->basic.issigned ? ICSLEW : ICULEW;
else
op = typeprop(t) & PROPFLOAT ? ICLED : t->basic.issigned ? ICSLEL : ICULEL;
break;
case TGEQ:
+ l = extend(f, t, l);
+ r = extend(f, t, r);
if (t->size <= 4)
op = typeprop(t) & PROPFLOAT ? ICGES : t->basic.issigned ? ICSGEW : ICUGEW;
else
op = typeprop(t) & PROPFLOAT ? ICGED : t->basic.issigned ? ICSGEL : ICUGEL;
break;
case TEQL:
+ l = extend(f, t, l);
+ r = extend(f, t, r);
if (t->size <= 4)
op = typeprop(t) & PROPFLOAT ? ICEQS : ICEQW;
else
op = typeprop(t) & PROPFLOAT ? ICEQD : ICEQL;
break;
case TNEQ:
+ l = extend(f, t, l);
+ r = extend(f, t, r);
if (t->size <= 4)
op = typeprop(t) & PROPFLOAT ? ICNES : ICNEW;
else