aboutsummaryrefslogtreecommitdiff
path: root/qbe.c
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2024-04-20 01:45:41 -0700
committerMichael Forney <mforney@mforney.org>2024-04-20 01:53:14 -0700
commite0b5d82377932c6fc72a9eb567bc53eec0d9866d (patch)
tree8a895922ef6f17ce9aa45cfa1b5c062255d9836e /qbe.c
parent92e397469d49e5d6dd053b061ec2a138a3dd1ef0 (diff)
qbe: Track 'thread' prefix in value kind
Adding a bool field increases the size of struct value by 8 due to alignment. In the future, maybe we just use something like VALUE_DECL instead.
Diffstat (limited to 'qbe.c')
-rw-r--r--qbe.c72
1 files changed, 42 insertions, 30 deletions
diff --git a/qbe.c b/qbe.c
index a360d03..c930972 100644
--- a/qbe.c
+++ b/qbe.c
@@ -18,9 +18,10 @@ struct value {
VALUE_TEMP,
VALUE_TYPE,
VALUE_LABEL,
+
+ VALUE_THREAD = 1<<4,
} kind;
unsigned id;
- bool threadlocal;
union {
char *name;
unsigned long long i;
@@ -136,6 +137,8 @@ mkglobal(struct decl *d)
v = xmalloc(sizeof(*v));
v->kind = VALUE_GLOBAL;
+ if (d->kind == DECLOBJECT && d->u.obj.storage == SDTHREAD)
+ v->kind |= VALUE_THREAD;
if (d->asmname) {
v->u.name = d->asmname;
v->id = 0;
@@ -143,7 +146,6 @@ mkglobal(struct decl *d)
v->u.name = d->name;
v->id = d->linkage == LINKNONE ? ++id : 0;
}
- v->threadlocal = d->kind == DECLOBJECT && d->u.obj.storage == SDTHREAD;
return v;
}
@@ -210,6 +212,7 @@ qbetype(struct type *t)
/* functions */
static void emittype(struct type *);
+static void emitname(struct value *);
static void emitvalue(struct value *);
static void
@@ -631,7 +634,7 @@ funclval(struct func *f, struct expr *e)
error(&tok.loc, "identifier is not an object or function"); /* XXX: fix location, var name */
if (d == f->namedecl) {
fputs("data ", stdout);
- emitvalue(d->value);
+ emitname(d->value);
printf(" = { b \"%s\", b 0 }\n", f->name);
f->namedecl = NULL;
}
@@ -1017,7 +1020,7 @@ funcswitch(struct func *f, struct value *v, struct switchcases *c, struct block
/* emit */
static void
-emitvalue(struct value *v)
+emitname(struct value *v)
{
static const char sigil[] = {
[VALUE_TEMP] = '%',
@@ -1025,8 +1028,24 @@ emitvalue(struct value *v)
[VALUE_TYPE] = ':',
[VALUE_LABEL] = '@',
};
+ int kind;
+
+ kind = v->kind & 0xf;
+ if (kind >= LEN(sigil) || !sigil[kind])
+ fatal("invalid value");
+ putchar(sigil[kind]);
+ if (kind == VALUE_GLOBAL && v->id)
+ fputs(".L", stdout);
+ if (v->u.name)
+ fputs(v->u.name, stdout);
+ if (v->id)
+ printf(".%u", v->id);
+}
- switch (v->kind) {
+static void
+emitvalue(struct value *v)
+{
+ switch (v->kind & 0xf) {
case VALUE_INTCONST:
printf("%llu", v->u.i);
break;
@@ -1036,16 +1055,13 @@ emitvalue(struct value *v)
case VALUE_DBLCONST:
printf("d_%.17g", v->u.f);
break;
+ case VALUE_GLOBAL:
+ if (v->kind & VALUE_THREAD)
+ fputs("thread ", stdout);
+ /* fallthrough */
default:
- if (v->kind >= LEN(sigil) || !sigil[v->kind])
- fatal("invalid value");
- putchar(sigil[v->kind]);
- if (v->kind == VALUE_GLOBAL && v->id)
- fputs(".L", stdout);
- if (v->u.name)
- fputs(v->u.name, stdout);
- if (v->id)
- printf(".%u", v->id);
+ emitname(v);
+ break;
}
}
@@ -1053,7 +1069,7 @@ static void
emitclass(int class, struct value *v)
{
if (v && v->kind == VALUE_TYPE)
- emitvalue(v);
+ emitname(v);
else if (class)
putchar(class);
else
@@ -1081,7 +1097,7 @@ emittype(struct type *t)
emittype(sub);
}
fputs("type ", stdout);
- emitvalue(t->value);
+ emitname(t->value);
if (t == targ->typevalist) {
printf(" = align %d { %llu }\n", t->align, t->size);
return;
@@ -1134,8 +1150,6 @@ emitinst(struct inst **instp, struct inst **instend)
}
fputs(instname[inst->kind], stdout);
putchar(' ');
- if (inst->arg[0]->kind == VALUE_GLOBAL && inst->arg[0]->threadlocal)
- fputs("thread ", stdout);
emitvalue(inst->arg[0]);
++instp;
op = inst->kind;
@@ -1163,8 +1177,6 @@ emitinst(struct inst **instp, struct inst **instend)
default:
if (inst->arg[1]) {
fputs(", ", stdout);
- if (inst->arg[1]->kind == VALUE_GLOBAL && inst->arg[1]->threadlocal)
- fputs("thread ", stdout);
emitvalue(inst->arg[1]);
}
}
@@ -1186,16 +1198,16 @@ emitjump(struct jump *j)
break;
case JUMP_JMP:
fputs("\tjmp ", stdout);
- emitvalue(&j->blk[0]->label);
+ emitname(&j->blk[0]->label);
putchar('\n');
break;
case JUMP_JNZ:
fputs("\tjnz ", stdout);
emitvalue(j->arg);
fputs(", ", stdout);
- emitvalue(&j->blk[0]->label);
+ emitname(&j->blk[0]->label);
fputs(", ", stdout);
- emitvalue(&j->blk[1]->label);
+ emitname(&j->blk[1]->label);
putchar('\n');
break;
}
@@ -1223,14 +1235,14 @@ emitfunc(struct func *f, bool global)
emitclass(qbetype(f->type->base).base, f->type->base->value);
putchar(' ');
}
- emitvalue(f->decl->value);
+ emitname(f->decl->value);
putchar('(');
for (p = f->type->u.func.params, v = f->paramtemps; p; p = p->next, ++v) {
if (p != f->type->u.func.params)
fputs(", ", stdout);
emitclass(qbetype(p->type).base, p->type->value);
putchar(' ');
- emitvalue(v);
+ emitname(v);
}
if (f->type->u.func.isvararg) {
if (f->type->u.func.params)
@@ -1239,17 +1251,17 @@ emitfunc(struct func *f, bool global)
}
puts(") {");
for (b = f->start; b; b = b->next) {
- emitvalue(&b->label);
+ emitname(&b->label);
putchar('\n');
if (b->phi.res.kind) {
putchar('\t');
emitvalue(&b->phi.res);
printf(" =%c phi ", b->phi.class);
- emitvalue(&b->phi.blk[0]->label);
+ emitname(&b->phi.blk[0]->label);
putchar(' ');
emitvalue(b->phi.val[0]);
fputs(", ", stdout);
- emitvalue(&b->phi.blk[1]->label);
+ emitname(&b->phi.blk[1]->label);
putchar(' ');
emitvalue(b->phi.val[1]);
putchar('\n');
@@ -1279,7 +1291,7 @@ dataitem(struct expr *expr, unsigned long long size)
decl = expr->u.ident.decl;
if (decl->kind == DECLOBJECT && decl->u.obj.storage != SDSTATIC)
error(&tok.loc, "initializer is not a constant expression");
- emitvalue(decl->value);
+ emitname(decl->value);
break;
case EXPRBINARY:
if (expr->op != TADD || expr->u.binary.l->kind != EXPRUNARY || expr->u.binary.r->kind != EXPRCONST)
@@ -1340,7 +1352,7 @@ emitdata(struct decl *d, struct init *init)
if (d->linkage == LINKEXTERN)
fputs("export ", stdout);
fputs("data ", stdout);
- emitvalue(d->value);
+ emitname(d->value);
printf(" = align %d { ", align);
while (init) {