~mcf/cproc

a98385a607aafe373c14d2a6fb2778d21a600c30 — Michael Forney 1 year, 7 months ago e0b772b
Fix integer promotion on bit-fields

Fixes #47.
M cc.h => cc.h +3 -3
@@ 400,9 400,8 @@ _Bool typecompatible(struct type *, struct type *);
_Bool typesame(struct type *, struct type *);
struct type *typecomposite(struct type *, struct type *);
struct type *typeunqual(struct type *, enum typequal *);
struct type *typecommonreal(struct type *, struct type *);
struct type *typeargpromote(struct type *);
struct type *typeintpromote(struct type *);
struct type *typecommonreal(struct type *, unsigned, struct type *, unsigned);
struct type *typepromote(struct type *, unsigned);
enum typeprop typeprop(struct type *);
struct member *typemember(struct type *, const char *, uint64_t *);



@@ 451,6 450,7 @@ uint64_t intconstexpr(struct scope *, _Bool);
void delexpr(struct expr *);

struct expr *exprconvert(struct expr *, struct type *);
struct expr *exprpromote(struct expr *);

/* eval */


M expr.c => expr.c +26 -7
@@ 107,12 107,29 @@ mkunaryexpr(enum tokenkind op, struct expr *base)
	fatal("internal error: unknown unary operator %d", op);
}

static unsigned
bitfieldwidth(struct expr *e)
{
	if (e->kind != EXPRBITFIELD)
		return -1;
	return e->type->size * 8 - e->bitfield.bits.before - e->bitfield.bits.after;
}

struct expr *
exprpromote(struct expr *e)
{
	struct type *t;

	t = typepromote(e->type, bitfieldwidth(e));
	return exprconvert(e, t);
}

static struct type *
commonreal(struct expr **e1, struct expr **e2)
{
	struct type *t;

	t = typecommonreal((*e1)->type, (*e2)->type);
	t = typecommonreal((*e1)->type, bitfieldwidth(*e1), (*e2)->type, bitfieldwidth(*e2));
	*e1 = exprconvert(*e1, t);
	*e2 = exprconvert(*e2, t);



@@ 208,8 225,8 @@ mkbinaryexpr(struct location *loc, enum tokenkind op, struct expr *l, struct exp
	case TSHR:
		if (!(lp & PROPINT) || !(rp & PROPINT))
			error(loc, "operands to '%s' operator must be integer", tokstr[op]);
		l = exprconvert(l, typeintpromote(l->type));
		r = exprconvert(r, typeintpromote(r->type));
		l = exprpromote(l);
		r = exprpromote(r);
		t = l->type;
		break;
	default:


@@ 597,7 614,7 @@ postfixexpr(struct scope *s, struct expr *r)
					error(&tok.loc, "too many arguments for function call");
				*end = assignexpr(s);
				if (!t->func.isprototype || (t->func.isvararg && !p))
					*end = exprconvert(*end, typeargpromote((*end)->type));
					*end = exprpromote(*end);
				else
					*end = exprconvert(*end, p->type);
				end = &(*end)->next;


@@ 682,14 699,16 @@ unaryexpr(struct scope *s)
		e = castexpr(s);
		if (!(e->type->prop & PROPARITH))
			error(&tok.loc, "operand of unary '+' operator must have arithmetic type");
		e = exprconvert(e, typeintpromote(e->type));
		if (e->type->prop & PROPINT)
			e = exprpromote(e);
		break;
	case TSUB:
		next();
		e = castexpr(s);
		if (!(e->type->prop & PROPARITH))
			error(&tok.loc, "operand of unary '-' operator must have arithmetic type");
		e = exprconvert(e, typeintpromote(e->type));
		if (e->type->prop & PROPINT)
			e = exprpromote(e);
		e = mkbinaryexpr(&tok.loc, TSUB, mkconstexpr(&typeint, 0), e);
		break;
	case TBNOT:


@@ 697,7 716,7 @@ unaryexpr(struct scope *s)
		e = castexpr(s);
		if (!(e->type->prop & PROPINT))
			error(&tok.loc, "operand of '~' operator must have integer type");
		e = exprconvert(e, typeintpromote(e->type));
		e = exprpromote(e);
		e = mkbinaryexpr(&tok.loc, TXOR, e, mkconstexpr(e->type, -1));
		break;
	case TLNOT:

M qbe.c => qbe.c +1 -1
@@ 382,7 382,7 @@ mkfunc(char *name, struct type *t, struct scope *s)
	for (p = t->func.params; p; p = p->next) {
		if (!p->name)
			error(&tok.loc, "parameter name omitted in function definition");
		if (!t->func.isprototype && !typecompatible(p->type, typeargpromote(p->type)))
		if (!t->func.isprototype && !typecompatible(p->type, typepromote(p->type, -1)))
			error(&tok.loc, "old-style function definition with parameter type incompatible with promoted type is not yet supported");
		emittype(p->type);
		d = mkdecl(DECLOBJECT, p->type, p->qual, LINKNONE);

M stmt.c => stmt.c +1 -1
@@ 127,7 127,7 @@ stmt(struct func *f, struct scope *s)

		if (!(e->type->prop & PROPINT))
			error(&tok.loc, "controlling expression of switch statement must have integer type");
		e = exprconvert(e, typeintpromote(e->type));
		e = exprpromote(e);

		label[0] = mkblock("switch_cond");
		label[1] = mkblock("switch_join");

A test/bitfield-integer-promotion-long.c => test/bitfield-integer-promotion-long.c +6 -0
@@ 0,0 1,6 @@
struct {unsigned long x:31;} s1;
struct {unsigned long x:32;} s2;
struct {unsigned long x:33;} s3;
int c1 = __builtin_types_compatible_p(__typeof__(+s1.x), int);
int c2 = __builtin_types_compatible_p(__typeof__(+s2.x), unsigned);
int c3 = __builtin_types_compatible_p(__typeof__(+s3.x), unsigned long);

A test/bitfield-integer-promotion-long.qbe => test/bitfield-integer-promotion-long.qbe +6 -0
@@ 0,0 1,6 @@
export data $c1 = align 4 { w 1, }
export data $c2 = align 4 { w 1, }
export data $c3 = align 4 { w 1, }
export data $s1 = align 8 { z 8 }
export data $s2 = align 8 { z 8 }
export data $s3 = align 8 { z 8 }

A test/bitfield-integer-promotion.c => test/bitfield-integer-promotion.c +7 -0
@@ 0,0 1,7 @@
struct {
	unsigned a : 2;
} s;

int main(void) {
	return -1 > s.a;
}

A test/bitfield-integer-promotion.qbe => test/bitfield-integer-promotion.qbe +17 -0
@@ 0,0 1,17 @@
export
function w $main() {
@start.1
@body.2
	%.1 =w sub 0, 1
	%.2 =l copy $s
	%.3 =l mul 0, 1
	%.4 =l add %.2, %.3
	%.5 =l copy %.4
	%.6 =w loaduw %.5
	%.7 =w shl %.6, 30
	%.8 =w shr %.7, 30
	%.9 =w copy %.8
	%.10 =w csgtw %.1, %.9
	ret %.10
}
export data $s = align 4 { z 4 }

M type.c => type.c +12 -15
@@ 149,7 149,7 @@ typecompatible(struct type *t1, struct type *t2)
			return false;
		if (!t2->func.paraminfo) {
			for (p1 = t1->func.params; p1; p1 = p1->next) {
				if (!typecompatible(p1->type, typeargpromote(p1->type)))
				if (!typecompatible(p1->type, typepromote(p1->type, -1)))
					return false;
			}
			return true;


@@ 157,7 157,7 @@ typecompatible(struct type *t1, struct type *t2)
		for (p1 = t1->func.params, p2 = t2->func.params; p1 && p2; p1 = p1->next, p2 = p2->next) {
			if (p1->qual != p2->qual)
				return false;
			tmp = t2->func.isprototype ? p2->type : typeargpromote(p2->type);
			tmp = t2->func.isprototype ? p2->type : typepromote(p2->type, -1);
			if (!typecompatible(p1->type, tmp))
				return false;
		}


@@ 186,23 186,20 @@ typecomposite(struct type *t1, struct type *t2)
}

struct type *
typeintpromote(struct type *t)
{
	if (t->prop & PROPINT && typerank(t) <= typerank(&typeint))
		return t->size < typeint.size || t->basic.issigned ? &typeint : &typeuint;
	return t;
}

struct type *
typeargpromote(struct type *t)
typepromote(struct type *t, unsigned width)
{
	if (t == &typefloat)
		return &typedouble;
	return typeintpromote(t);
	if (t->prop & PROPINT && (typerank(t) <= typerank(&typeint) || width <= typeint.size * 8)) {
		if (width == -1)
			width = t->size * 8;
		return width - t->basic.issigned < typeint.size * 8 ? &typeint : &typeuint;
	}
	return t;
}

struct type *
typecommonreal(struct type *t1, struct type *t2)
typecommonreal(struct type *t1, unsigned w1, struct type *t2, unsigned w2)
{
	struct type *tmp;



@@ 215,8 212,8 @@ typecommonreal(struct type *t1, struct type *t2)
		return &typedouble;
	if (t1 == &typefloat || t2 == &typefloat)
		return &typefloat;
	t1 = typeintpromote(t1);
	t2 = typeintpromote(t2);
	t1 = typepromote(t1, w1);
	t2 = typepromote(t2, w2);
	if (t1 == t2)
		return t1;
	if (t1->basic.issigned == t2->basic.issigned)