~mcf/cproc

a71a7975c95b794983c4b83a26981c7b4d7f7c82 — Michael Forney 1 year, 7 months ago 0e9f74c
Use a common member for expression base
6 files changed, 52 insertions(+), 69 deletions(-)

M cc.h
M decl.c
M eval.c
M expr.c
M init.c
M qbe.c
M cc.h => cc.h +3 -14
@@ 306,6 306,7 @@ struct expr {
	/* the type qualifiers of the object this expression refers to (ignored for non-lvalues) */
	enum typequal qual;
	enum tokenkind op;
	struct expr *base;
	struct expr *next;
	union {
		struct {


@@ 320,11 321,10 @@ struct expr {
			size_t size;
		} string;
		struct {
			struct expr *func, *args;
			struct expr *args;
			size_t nargs;
		} call;
		struct {
			struct expr *base;
			struct bitfield bits;
		} bitfield;
		struct {


@@ 332,29 332,18 @@ struct expr {
		} compound;
		struct {
			_Bool post;
			struct expr *base;
		} incdec;
		struct {
			struct expr *base;
		} unary;
		struct {
			struct expr *e;
		} cast;
		struct {
			struct expr *l, *r;
		} binary;
		struct {
			struct expr *e, *t, *f;
			struct expr *t, *f;
		} cond;
		struct {
			struct expr *l, *r;
		} assign;
		struct {
			struct expr *exprs;
		} comma;
		struct {
			enum builtinkind kind;
			struct expr *arg;
		} builtin;
		struct value *temp;
	};

M decl.c => decl.c +1 -1
@@ 348,7 348,7 @@ declspecs(struct scope *s, enum storageclass *sc, enum funcspec *fs, int *align)
			if (!t) {
				e = expr(s);
				if (e->decayed)
					e = e->unary.base;
					e = e->base;
				t = e->type;
				tq |= e->qual;
				delexpr(e);

M eval.c => eval.c +5 -5
@@ 107,23 107,23 @@ eval(struct expr *expr)
		expr->ident.decl = d;
		break;
	case EXPRUNARY:
		l = eval(expr->unary.base);
		l = eval(expr->base);
		if (expr->op != TBAND)
			break;
		switch (l->kind) {
		case EXPRUNARY:
			if (l->op == TMUL)
				expr = eval(l->unary.base);
				expr = eval(l->base);
			break;
		case EXPRSTRING:
			l->ident.decl = stringdecl(l);
			l->kind = EXPRIDENT;
			expr->unary.base = l;
			expr->base = l;
			break;
		}
		break;
	case EXPRCAST:
		l = eval(expr->cast.e);
		l = eval(expr->base);
		if (l->kind == EXPRCONST) {
			expr->kind = EXPRCONST;
			if (l->type->prop & PROPINT && expr->type->prop & PROPFLOAT)


@@ 176,7 176,7 @@ eval(struct expr *expr)
	case EXPRCOND:
		l = expr->cond.t;
		r = expr->cond.f;
		c = eval(expr->cond.e);
		c = eval(expr->base);
		if (c->kind != EXPRCONST)
			break;
		return eval(c->constant.i ? l : r);

M expr.c => expr.c +24 -30
@@ 33,30 33,24 @@ delexpr(struct expr *e)

	switch (e->kind) {
	case EXPRCALL:
		delexpr(e->call.func);
		delexpr(e->base);
		while (sub = e->call.args) {
			e->call.args = sub->next;
			delexpr(sub);
		}
		break;
	case EXPRBITFIELD:
		delexpr(e->bitfield.base);
		break;
	case EXPRINCDEC:
		delexpr(e->incdec.base);
		break;
	case EXPRUNARY:
		delexpr(e->unary.base);
		break;
	case EXPRCAST:
		delexpr(e->cast.e);
		delexpr(e->base);
		break;
	case EXPRBINARY:
		delexpr(e->binary.l);
		delexpr(e->binary.r);
		break;
	case EXPRCOND:
		delexpr(e->cond.e);
		delexpr(e->base);
		delexpr(e->cond.t);
		delexpr(e->cond.f);
		break;


@@ 70,8 64,8 @@ delexpr(struct expr *e)
		break;
	*/
	case EXPRCOMMA:
		while (sub = e->comma.exprs) {
			e->comma.exprs = sub->next;
		while (sub = e->base) {
			e->base = sub->next;
			delexpr(sub);
		}
		break;


@@ 138,7 132,7 @@ mkunaryexpr(enum tokenkind op, struct expr *base)
			error(&tok.loc, "cannot take address of bit-field");
		expr = mkexpr(EXPRUNARY, mkpointertype(base->type, base->qual));
		expr->op = op;
		expr->unary.base = base;
		expr->base = base;
		return expr;
	case TMUL:
		if (base->type->kind != TYPEPOINTER)


@@ 147,7 141,7 @@ mkunaryexpr(enum tokenkind op, struct expr *base)
		expr->qual = base->type->qual;
		expr->lvalue = true;
		expr->op = op;
		expr->unary.base = base;
		expr->base = base;
		return decay(expr);
	}
	/* other unary operators get compiled as equivalent binary ones */


@@ 560,7 554,7 @@ builtinfunc(struct scope *s, enum builtinkind kind)
	case BUILTINALLOCA:
		e = mkexpr(EXPRBUILTIN, mkpointertype(&typevoid, QUALNONE));
		e->builtin.kind = BUILTINALLOCA;
		e->builtin.arg = exprconvert(assignexpr(s), &typeulong);
		e->base = exprconvert(assignexpr(s), &typeulong);
		break;
	case BUILTINCONSTANTP:
		e = mkconstexpr(&typeint, eval(condexpr(s))->kind == EXPRCONST);


@@ 572,7 566,7 @@ builtinfunc(struct scope *s, enum builtinkind kind)
		break;
	case BUILTINNANF:
		e = assignexpr(s);
		if (!e->decayed || e->unary.base->kind != EXPRSTRING || e->unary.base->string.size > 0)
		if (!e->decayed || e->base->kind != EXPRSTRING || e->base->string.size > 0)
			error(&tok.loc, "__builtin_nanf currently only supports empty string literals");
		e = mkexpr(EXPRCONST, &typefloat);
		/* TODO: use NAN here when we can handle musl's math.h */


@@ 600,7 594,7 @@ builtinfunc(struct scope *s, enum builtinkind kind)
	case BUILTINVAARG:
		e = mkexpr(EXPRBUILTIN, NULL);
		e->builtin.kind = BUILTINVAARG;
		e->builtin.arg = exprconvert(assignexpr(s), &typevalistptr);
		e->base = exprconvert(assignexpr(s), &typevalistptr);
		expect(TCOMMA, "after va_list");
		e->type = typename(s, &e->qual);
		break;


@@ 619,7 613,7 @@ builtinfunc(struct scope *s, enum builtinkind kind)
	case BUILTINVASTART:
		e = mkexpr(EXPRBUILTIN, &typevoid);
		e->builtin.kind = BUILTINVASTART;
		e->builtin.arg = exprconvert(assignexpr(s), &typevalistptr);
		e->base = exprconvert(assignexpr(s), &typevalistptr);
		expect(TCOMMA, "after va_list");
		param = assignexpr(s);
		if (param->kind != EXPRIDENT)


@@ 644,7 638,7 @@ mkincdecexpr(enum tokenkind op, struct expr *base, bool post)
		error(&tok.loc, "operand of '%s' operator is const qualified", tokstr[op]);
	e = mkexpr(EXPRINCDEC, base->type);
	e->op = op;
	e->incdec.base = base;
	e->base = base;
	e->incdec.post = post;
	return e;
}


@@ 694,7 688,7 @@ postfixexpr(struct scope *s, struct expr *r)
				error(&tok.loc, "called object is not a function");
			t = r->type->base;
			e = mkexpr(EXPRCALL, t->base);
			e->call.func = r;
			e->base = r;
			e->call.args = NULL;
			e->call.nargs = 0;
			p = t->func.params;


@@ 735,7 729,7 @@ postfixexpr(struct scope *s, struct expr *r)
			next();
			if (tok.kind != TIDENT)
				error(&tok.loc, "expected identifier after '%s' operator", tokstr[op]);
			lvalue = op == TARROW || r->unary.base->lvalue;
			lvalue = op == TARROW || r->base->lvalue;
			r = exprconvert(r, mkpointertype(&typechar, QUALNONE));
			offset = 0;
			m = typemember(t, tok.lit, &offset);


@@ 748,7 742,7 @@ postfixexpr(struct scope *s, struct expr *r)
			if (m->bits.before || m->bits.after) {
				e = mkexpr(EXPRBITFIELD, r->type);
				e->lvalue = lvalue;
				e->bitfield.base = r;
				e->base = r;
				e->bitfield.bits = m->bits;
			} else {
				e = r;


@@ 836,13 830,13 @@ unaryexpr(struct scope *s)
				if (op == TSIZEOF)
					e = postfixexpr(s, e);
				if (e->decayed)
					e = e->unary.base;
					e = e->base;
				t = e->type;
			}
		} else if (op == TSIZEOF) {
			e = unaryexpr(s);
			if (e->decayed)
				e = e->unary.base;
				e = e->base;
			t = e->type;
		} else {
			error(&tok.loc, "expected ')' after '_Alignof'");


@@ 886,7 880,7 @@ castexpr(struct scope *s)
		e = mkexpr(EXPRCAST, t);
		// XXX check types 6.5.4
		*end = e;
		end = &e->cast.e;
		end = &e->base;
	}
	*end = unaryexpr(s);



@@ 962,7 956,7 @@ condexpr(struct scope *s)
	if (!consume(TQUESTION))
		return r;
	e = mkexpr(EXPRCOND, NULL);
	e->cond.e = exprconvert(r, &typebool);
	e->base = exprconvert(r, &typebool);
	e->cond.t = expr(s);
	expect(TCOLON, "in conditional expression");
	e->cond.f = condexpr(s);


@@ 1064,7 1058,7 @@ assignexpr(struct scope *s)
	/* rewrite `E1 OP= E2` as `T = &E1, *T = *T OP E2`, where T is a temporary slot */
	if (l->kind == EXPRBITFIELD) {
		bit = l;
		l = l->bitfield.base;
		l = l->base;
	} else {
		bit = NULL;
	}


@@ 1074,13 1068,13 @@ assignexpr(struct scope *s)
	e = mkassignexpr(tmp, mkunaryexpr(TBAND, l));
	l = mkunaryexpr(TMUL, tmp);
	if (bit) {
		bit->bitfield.base = l;
		bit->base = l;
		l = bit;
	}
	r = mkbinaryexpr(&tok.loc, op, l, r);
	e->next = mkassignexpr(l, r);
	l = mkexpr(EXPRCOMMA, l->type);
	l->comma.exprs = e;
	l->base = e;
	return l;
}



@@ 1101,7 1095,7 @@ expr(struct scope *s)
	if (!r->next)
		return r;
	e = mkexpr(EXPRCOMMA, e->type);
	e->comma.exprs = r;
	e->base = r;

	return e;
}


@@ 1114,7 1108,7 @@ exprconvert(struct expr *e, struct type *t)
	if (typecompatible(e->type, t))
		return e;
	cast = mkexpr(EXPRCAST, t);
	cast->cast.e = e;
	cast->base = e;

	return cast;
}

M init.c => init.c +2 -2
@@ 240,8 240,8 @@ parseinit(struct scope *s, struct type *t)
			t = p.sub->type;
			switch (t->kind) {
			case TYPEARRAY:
				if (expr->decayed && expr->unary.base->kind == EXPRSTRING) {
					expr = expr->unary.base;
				if (expr->decayed && expr->base->kind == EXPRSTRING) {
					expr = expr->base;
					base = t->base;
					/* XXX: wide string literals */
					if (!(base->prop & PROPCHAR))

M qbe.c => qbe.c +17 -17
@@ 493,7 493,7 @@ funclval(struct func *f, struct expr *e)

	if (e->kind == EXPRBITFIELD) {
		lval.bits = e->bitfield.bits;
		e = e->bitfield.base;
		e = e->base;
	}
	switch (e->kind) {
	case EXPRIDENT:


@@ 520,7 520,7 @@ funclval(struct func *f, struct expr *e)
	case EXPRUNARY:
		if (e->op != TMUL)
			break;
		lval.addr = funcexpr(f, e->unary.base);
		lval.addr = funcexpr(f, e->base);
		break;
	default:
		if (e->type->kind != TYPESTRUCT && e->type->kind != TYPEUNION)


@@ 642,8 642,8 @@ funcexpr(struct func *f, struct expr *e)
		lval = funclval(f, e);
		return funcload(f, e->type, lval);
	case EXPRINCDEC:
		lval = funclval(f, e->incdec.base);
		l = funcload(f, e->incdec.base->type, lval);
		lval = funclval(f, e->base);
		l = funcload(f, e->base->type, lval);
		if (e->type->kind == TYPEPOINTER)
			r = mkintconst(e->type->repr, e->type->base->size);
		else if (e->type->prop & PROPINT)


@@ 657,26 657,26 @@ funcexpr(struct func *f, struct expr *e)
		return e->incdec.post ? l : v;
	case EXPRCALL:
		argvals = xreallocarray(NULL, e->call.nargs + 3, sizeof(argvals[0]));
		argvals[0] = funcexpr(f, e->call.func);
		argvals[0] = funcexpr(f, e->base);
		emittype(e->type);
		for (argval = &argvals[1], arg = e->call.args; arg; ++argval, arg = arg->next) {
			emittype(arg->type);
			*argval = funcexpr(f, arg);
		}
		*argval = NULL;
		op = e->call.func->type->base->func.isvararg ? IVACALL : ICALL;
		op = e->base->type->base->func.isvararg ? IVACALL : ICALL;
		v = funcinstn(f, op, e->type == &typevoid ? NULL : e->type->repr, argvals);
		free(argvals);
		//if (e->call.func->type->base->func.isnoreturn)
		//if (e->base->type->base->func.isnoreturn)
		//	funcret(f, NULL);
		return v;
	case EXPRUNARY:
		switch (e->op) {
		case TBAND:
			lval = funclval(f, e->unary.base);
			lval = funclval(f, e->base);
			return lval.addr;
		case TMUL:
			r = funcexpr(f, e->unary.base);
			r = funcexpr(f, e->base);
			return funcload(f, e->type, (struct lvalue){r});
		}
		fatal("internal error; unknown unary expression");


@@ 684,10 684,10 @@ funcexpr(struct func *f, struct expr *e)
	case EXPRCAST: {
		struct type *src, *dst;

		l = funcexpr(f, e->cast.e);
		l = funcexpr(f, e->base);
		r = NULL;

		src = e->cast.e->type;
		src = e->base->type;
		if (src->kind == TYPEPOINTER)
			src = &typeulong;
		dst = e->type;


@@ 847,7 847,7 @@ funcexpr(struct func *f, struct expr *e)
		label[1] = mkblock("cond_false");
		label[2] = mkblock("cond_join");

		v = funcexpr(f, e->cond.e);
		v = funcexpr(f, e->base);
		funcjnz(f, v, label[0], label[1]);

		funclabel(f, label[0]);


@@ 873,23 873,23 @@ funcexpr(struct func *f, struct expr *e)
		}
		return r;
	case EXPRCOMMA:
		for (e = e->comma.exprs; e->next; e = e->next)
		for (e = e->base; e->next; e = e->next)
			funcexpr(f, e);
		return funcexpr(f, e);
	case EXPRBUILTIN:
		switch (e->builtin.kind) {
		case BUILTINVASTART:
			l = funcexpr(f, e->builtin.arg);
			l = funcexpr(f, e->base);
			funcinst(f, IVASTART, NULL, l);
			break;
		case BUILTINVAARG:
			l = funcexpr(f, e->builtin.arg);
			l = funcexpr(f, e->base);
			return funcinst(f, IVAARG, e->type->repr, l);
		case BUILTINVAEND:
			/* no-op */
			break;
		case BUILTINALLOCA:
			l = funcexpr(f, e->builtin.arg);
			l = funcexpr(f, e->base);
			return funcinst(f, IALLOC16, &iptr, l);
		default:
			fatal("internal error: unimplemented builtin");


@@ 1193,7 1193,7 @@ dataitem(struct expr *expr, uint64_t size)
	case EXPRUNARY:
		if (expr->op != TBAND)
			fatal("not a address expr");
		expr = expr->unary.base;
		expr = expr->base;
		if (expr->kind != EXPRIDENT)
			error(&tok.loc, "initializer is not a constant expression");
		decl = expr->ident.decl;