add support for thread-local storage

The apple targets are not done yet.
This commit is contained in:
Quentin Carbonneaux 2022-09-09 17:40:31 +02:00
parent 5cea0c20ee
commit 00a30954ac
12 changed files with 145 additions and 70 deletions

View file

@ -129,14 +129,10 @@ slot(int s, Fn *fn)
static void
emitaddr(Con *c, FILE *f)
{
char off[32], *p;
assert(c->rel == RelDef);
fputs(str(c->label), f);
if (c->bits.i)
sprintf(off, "+%"PRIi64, c->bits.i);
else
off[0] = 0;
p = c->local ? ".L" : "";
fprintf(f, "%s%s%s", p, str(c->label), off);
fprintf(f, "+%"PRIi64, c->bits.i);
}
static void
@ -228,26 +224,45 @@ emitf(char *s, Ins *i, Fn *fn, FILE *f)
}
}
static void
loadaddr(Con *c, char *rn, FILE *f)
{
char off[32];
if (c->rel == RelThr) {
if (c->bits.i)
sprintf(off, "+%"PRIi64, c->bits.i);
else
off[0] = 0;
fprintf(f, "\tlui %s, %%tprel_hi(%s)%s\n",
rn, str(c->label), off);
fprintf(f, "\tadd %s, %s, tp, %%tprel_add(%s)%s\n",
rn, rn, str(c->label), off);
fprintf(f, "\taddi %s, %s, %%tprel_lo(%s)%s\n",
rn, rn, str(c->label), off);
} else {
fprintf(f, "\tla %s, ", rn);
emitaddr(c, f);
fputc('\n', f);
}
}
static void
loadcon(Con *c, int r, int k, FILE *f)
{
char *rn;
int64_t n;
int w;
w = KWIDE(k);
rn = rname[r];
switch (c->type) {
case CAddr:
fprintf(f, "\tla %s, ", rn);
emitaddr(c, f);
fputc('\n', f);
loadaddr(c, rn, f);
break;
case CBits:
n = c->bits.i;
if (!w)
if (!KWIDE(k))
n = (int32_t)n;
fprintf(f, "\tli %s, %"PRIu64"\n", rn, n);
fprintf(f, "\tli %s, %"PRIi64"\n", rn, n);
break;
default:
die("invalid constant");
@ -255,12 +270,20 @@ loadcon(Con *c, int r, int k, FILE *f)
}
static void
fixslot(Ref *pr, Fn *fn, FILE *f)
fixmem(Ref *pr, Fn *fn, FILE *f)
{
Ref r;
int64_t s;
Con *c;
r = *pr;
if (rtype(r) == RCon) {
c = &fn->con[r.val];
if (c->type == CAddr && c->rel == RelThr) {
loadcon(c, T6, Kl, f);
*pr = TMP(T6);
}
}
if (rtype(r) == RSlot) {
s = slot(r.val, fn);
if (s < -2048 || s > 2047) {
@ -282,9 +305,9 @@ emitins(Ins *i, Fn *fn, FILE *f)
switch (i->op) {
default:
if (isload(i->op))
fixslot(&i->arg[0], fn, f);
fixmem(&i->arg[0], fn, f);
else if (isstore(i->op))
fixslot(&i->arg[1], fn, f);
fixmem(&i->arg[1], fn, f);
Table:
/* most instructions are just pulled out of
* the table omap[], some special cases are
@ -321,7 +344,7 @@ emitins(Ins *i, Fn *fn, FILE *f)
case Ks: i->op = Ostores; break;
case Kd: i->op = Ostored; break;
}
fixslot(&i->arg[1], fn, f);
fixmem(&i->arg[1], fn, f);
goto Table;
}
break;
@ -333,7 +356,7 @@ emitins(Ins *i, Fn *fn, FILE *f)
break;
case RSlot:
i->op = Oload;
fixslot(&i->arg[0], fn, f);
fixmem(&i->arg[0], fn, f);
goto Table;
default:
assert(isreg(i->arg[0]));
@ -415,7 +438,7 @@ rv64_emitfn(Fn *fn, FILE *f)
Blk *b, *s;
Ins *i;
emitlnk(fn->name, &fn->lnk, ".text", f);
emitfnlnk(fn->name, &fn->lnk, f);
if (fn->vararg) {
/* TODO: only need space for registers