aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qbe.c26
-rw-r--r--tests/cast-bool-char.c3
-rw-r--r--tests/cast-bool-char.qbe10
-rw-r--r--tests/compare-char.c3
-rw-r--r--tests/compare-char.qbe11
5 files changed, 53 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
diff --git a/tests/cast-bool-char.c b/tests/cast-bool-char.c
new file mode 100644
index 0000000..d05f575
--- /dev/null
+++ b/tests/cast-bool-char.c
@@ -0,0 +1,3 @@
+int main(void) {
+ return (_Bool)(unsigned char)256;
+}
diff --git a/tests/cast-bool-char.qbe b/tests/cast-bool-char.qbe
new file mode 100644
index 0000000..81d4eba
--- /dev/null
+++ b/tests/cast-bool-char.qbe
@@ -0,0 +1,10 @@
+export
+function w $main() {
+@start.1
+@body.2
+ %.1 =w copy 256
+ %.2 =w extub %.1
+ %.3 =w cnew %.2, 0
+ %.4 =w extub %.3
+ ret %.4
+}
diff --git a/tests/compare-char.c b/tests/compare-char.c
new file mode 100644
index 0000000..5219647
--- /dev/null
+++ b/tests/compare-char.c
@@ -0,0 +1,3 @@
+int main(void) {
+ return (unsigned char)0 < (unsigned char)256;
+}
diff --git a/tests/compare-char.qbe b/tests/compare-char.qbe
new file mode 100644
index 0000000..a0a1c03
--- /dev/null
+++ b/tests/compare-char.qbe
@@ -0,0 +1,11 @@
+export
+function w $main() {
+@start.1
+@body.2
+ %.1 =w copy 0
+ %.2 =w copy 256
+ %.3 =w extub %.1
+ %.4 =w extub %.2
+ %.5 =w cultw %.3, %.4
+ ret %.5
+}