~mcf/cproc

38d906288b70102cf869a9cbb433ddc1fbf23efb — Nihal Jere 5 months ago 4e9690b
qbe, init: Handle prefixed string literals
3 files changed, 50 insertions(+), 23 deletions(-)

M cc.h
M init.c
M qbe.c
M cc.h => cc.h +5 -1
@@ 331,7 331,11 @@ struct expr {
			double f;
		} constant;
		struct {
			unsigned char *data;
			union {
				unsigned char *data;
				uint_least16_t *data16;
				uint_least32_t *data32;
			};
			size_t size;
		} string;
		struct {

M init.c => init.c +3 -4
@@ 243,13 243,12 @@ parseinit(struct scope *s, struct type *t)
			t = p.sub->type;
			switch (t->kind) {
			case TYPEARRAY:
				if (!expr->decayed || expr->base->kind != EXPRSTRING)
				if (!expr->decayed || expr->base->kind != EXPRSTRING || !(t->base->prop & PROPINT))
					break;
				base = t->base;
				/* XXX: wide string literals */
				if (!(base->prop & PROPCHAR))
					break;
				expr = expr->base;
				if (!(base->prop & PROPCHAR && expr->type->base->prop & PROPCHAR) && !typecompatible(base, expr->type->base))
					error(&tok.loc, "cannot initialize array with string literal of different width");
				if (t->incomplete)
					updatearray(t, expr->string.size - 1);
				goto add;

M qbe.c => qbe.c +42 -18
@@ 969,9 969,9 @@ void
funcinit(struct func *func, struct decl *d, struct init *init)
{
	struct lvalue dst;
	struct value *src;
	struct value *src, *v;
	uint64_t offset = 0, max = 0;
	size_t i;
	size_t i, w;

	funcalloc(func, d);
	if (!init)


@@ 980,11 980,18 @@ funcinit(struct func *func, struct decl *d, struct init *init)
		zero(func, d->value, d->type->align, offset, init->start);
		dst.bits = init->bits;
		if (init->expr->kind == EXPRSTRING) {
			for (i = 0; i < init->expr->string.size && i < init->end - init->start; ++i) {
				dst.addr = funcinst(func, IADD, ptrclass, d->value, mkintconst(init->start + i));
				funcstore(func, &typechar, QUALNONE, dst, mkintconst(init->expr->string.data[i]));
			w = init->expr->type->base->size;
			for (i = 0; i < init->expr->string.size && i * w < init->end - init->start; ++i) {
				v = mkintconst(init->start + i * w);
				dst.addr = funcinst(func, IADD, ptrclass, d->value, v);
				switch (w) {
				case 1: v = mkintconst(init->expr->string.data[i]); break;
				case 2: v = mkintconst(init->expr->string.data16[i]); break;
				case 4: v = mkintconst(init->expr->string.data32[i]); break;
				}
				funcstore(func, init->expr->type->base, QUALNONE, dst, v);
			}
			offset = init->start + i;
			offset = init->start + i * w;
		} else {
			if (offset < init->end && (dst.bits.before || dst.bits.after))
				zero(func, d->value, d->type->align, offset, init->end);


@@ 1274,7 1281,7 @@ static void
dataitem(struct expr *expr, uint64_t size)
{
	struct decl *decl;
	size_t i;
	size_t i, w;
	unsigned c;

	switch (expr->kind) {


@@ 1303,17 1310,28 @@ dataitem(struct expr *expr, uint64_t size)
			printf("%" PRIu64, expr->constant.i);
		break;
	case EXPRSTRING:
		fputc('"', stdout);
		for (i = 0; i < expr->string.size && i < size; ++i) {
			c = expr->string.data[i];
			if (isprint(c) && c != '"' && c != '\\')
				putchar(c);
			else
				printf("\\%03o", c);
		w = expr->type->base->size;
		if (w == 1) {
			fputc('"', stdout);
			for (i = 0; i < expr->string.size && i < size; ++i) {
				c = expr->string.data[i];
				if (isprint(c) && c != '"' && c != '\\')
					putchar(c);
				else
					printf("\\%03o", c);
			}
			fputc('"', stdout);
		} else {
			for (i = 0; i < expr->string.size && i * w < size; ++i) {
				switch (w) {
				case 2: printf("%hu ", expr->string.data16[i]); break;
				case 4: printf("%u ", expr->string.data32[i]);  break;
				default: assert(0);
				}
			}
		}
		fputc('"', stdout);
		if (i < size)
			printf(", z %" PRIu64, size - i);
		if (i * w < size)
			printf(", z %" PRIu64, size - i * w);
		break;
	default:
		error(&tok.loc, "initializer is not a constant expression");


@@ 1326,6 1344,7 @@ emitdata(struct decl *d, struct init *init)
	struct init *cur;
	struct type *t;
	uint64_t offset = 0, start, end, bits = 0;
	size_t i;

	if (!d->align)
		d->align = d->type->align;


@@ 1349,7 1368,12 @@ emitdata(struct decl *d, struct init *init)
			*/
			assert(cur->expr->kind == EXPRSTRING);
			assert(init->expr->kind == EXPRCONST);
			cur->expr->string.data[init->start - cur->start] = init->expr->constant.i;
			i = (init->start - cur->start) / cur->expr->type->base->size;
			switch (cur->expr->type->base->size) {
			case 1: cur->expr->string.data[i]   = init->expr->constant.i; break;
			case 2: cur->expr->string.data16[i] = init->expr->constant.i; break;
			case 4: cur->expr->string.data32[i] = init->expr->constant.i; break;
			}
		}
		start = cur->start + cur->bits.before / 8;
		end = cur->end - (cur->bits.after + 7) / 8;