cproc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/cproc
Log | Files | Refs | Submodules | README | LICENSE

commit 7d746860bda62c2f382bc0ac82d4d6c8cdf6c7b2
parent 18ad54b003608f3060d4baf2fef00a8a2b6f0a7b
Author: Michael Forney <mforney@mforney.org>
Date:   Sat, 16 Feb 2019 20:47:45 -0800

Extend char/short types before comparing

Thanks to Andrew Chambers for reporting the issue.

Diffstat:
Mqbe.c | 26++++++++++++++++++++++++++
Atests/cast-bool-char.c | 3+++
Atests/cast-bool-char.qbe | 10++++++++++
Atests/compare-char.c | 3+++
Atests/compare-char.qbe | 11+++++++++++
5 files changed, 53 insertions(+), 0 deletions(-)

diff --git 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 @@ -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 @@ -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 @@ -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 @@ -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 +}