add support for thread-local storage
The apple targets are not done yet.
This commit is contained in:
parent
5cea0c20ee
commit
00a30954ac
12 changed files with 145 additions and 70 deletions
8
all.h
8
all.h
|
@ -324,8 +324,11 @@ struct Con {
|
||||||
double d;
|
double d;
|
||||||
float s;
|
float s;
|
||||||
} bits;
|
} bits;
|
||||||
|
enum {
|
||||||
|
RelDef,
|
||||||
|
RelThr,
|
||||||
|
} rel;
|
||||||
char flt; /* 1 to print as s, 2 to print as d */
|
char flt; /* 1 to print as s, 2 to print as d */
|
||||||
char local;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Addr Addr;
|
typedef struct Addr Addr;
|
||||||
|
@ -339,6 +342,7 @@ struct Addr { /* amd64 addressing */
|
||||||
|
|
||||||
struct Lnk {
|
struct Lnk {
|
||||||
char export;
|
char export;
|
||||||
|
char thread;
|
||||||
char align;
|
char align;
|
||||||
char *sec;
|
char *sec;
|
||||||
char *secf;
|
char *secf;
|
||||||
|
@ -536,7 +540,7 @@ void spill(Fn *);
|
||||||
void rega(Fn *);
|
void rega(Fn *);
|
||||||
|
|
||||||
/* emit.c */
|
/* emit.c */
|
||||||
void emitlnk(char *, Lnk *, char *, FILE *);
|
void emitfnlnk(char *, Lnk *, FILE *);
|
||||||
void emitdat(Dat *, FILE *);
|
void emitdat(Dat *, FILE *);
|
||||||
int stashbits(void *, int);
|
int stashbits(void *, int);
|
||||||
void elf_emitfnfin(char *, FILE *);
|
void elf_emitfnfin(char *, FILE *);
|
||||||
|
|
11
amd64/emit.c
11
amd64/emit.c
|
@ -166,8 +166,11 @@ emitcon(Con *con, FILE *f)
|
||||||
switch (con->type) {
|
switch (con->type) {
|
||||||
case CAddr:
|
case CAddr:
|
||||||
l = str(con->label);
|
l = str(con->label);
|
||||||
p = con->local ? T.asloc : l[0] == '"' ? "" : T.assym;
|
p = l[0] == '"' ? "" : T.assym;
|
||||||
fprintf(f, "%s%s", p, l);
|
if (con->rel == RelThr)
|
||||||
|
fprintf(f, "%%fs:%s%s@tpoff", p, l);
|
||||||
|
else
|
||||||
|
fprintf(f, "%s%s", p, l);
|
||||||
if (con->bits.i)
|
if (con->bits.i)
|
||||||
fprintf(f, "%+"PRId64, con->bits.i);
|
fprintf(f, "%+"PRId64, con->bits.i);
|
||||||
break;
|
break;
|
||||||
|
@ -337,7 +340,7 @@ Next:
|
||||||
case RCon:
|
case RCon:
|
||||||
off = fn->con[ref.val];
|
off = fn->con[ref.val];
|
||||||
emitcon(&off, f);
|
emitcon(&off, f);
|
||||||
if (off.type == CAddr)
|
if (off.type == CAddr && off.rel != RelThr)
|
||||||
fprintf(f, "(%%rip)");
|
fprintf(f, "(%%rip)");
|
||||||
break;
|
break;
|
||||||
case RTmp:
|
case RTmp:
|
||||||
|
@ -549,7 +552,7 @@ emitfn(Fn *fn, FILE *f)
|
||||||
int *r, c, o, n, lbl;
|
int *r, c, o, n, lbl;
|
||||||
uint64_t fs;
|
uint64_t fs;
|
||||||
|
|
||||||
emitlnk(fn->name, &fn->lnk, ".text", f);
|
emitfnlnk(fn->name, &fn->lnk, f);
|
||||||
fputs("\tpushq %rbp\n\tmovq %rsp, %rbp\n", f);
|
fputs("\tpushq %rbp\n\tmovq %rsp, %rbp\n", f);
|
||||||
fs = framesz(fn);
|
fs = framesz(fn);
|
||||||
if (fs)
|
if (fs)
|
||||||
|
|
|
@ -78,9 +78,8 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn)
|
||||||
vgrow(&fn->mem, ++fn->nmem);
|
vgrow(&fn->mem, ++fn->nmem);
|
||||||
memset(&a, 0, sizeof a);
|
memset(&a, 0, sizeof a);
|
||||||
a.offset.type = CAddr;
|
a.offset.type = CAddr;
|
||||||
a.offset.local = 1;
|
|
||||||
n = stashbits(&fn->con[r0.val].bits, KWIDE(k) ? 8 : 4);
|
n = stashbits(&fn->con[r0.val].bits, KWIDE(k) ? 8 : 4);
|
||||||
sprintf(buf, "fp%d", n);
|
sprintf(buf, "\"%sfp%d\"", T.asloc, n);
|
||||||
a.offset.label = intern(buf);
|
a.offset.label = intern(buf);
|
||||||
fn->mem[fn->nmem-1] = a;
|
fn->mem[fn->nmem-1] = a;
|
||||||
}
|
}
|
||||||
|
|
41
arm64/emit.c
41
arm64/emit.c
|
@ -244,7 +244,7 @@ emitf(char *s, Ins *i, E *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
loadcon(Con *c, int r, int k, E *e)
|
loadaddr(Con *c, char *rn, E *e)
|
||||||
{
|
{
|
||||||
static char *ldsym[][2] = {
|
static char *ldsym[][2] = {
|
||||||
/* arm64 */
|
/* arm64 */
|
||||||
|
@ -254,7 +254,31 @@ loadcon(Con *c, int r, int k, E *e)
|
||||||
[1][0] = "\tadrp\t%s, %s%s@page%s\n",
|
[1][0] = "\tadrp\t%s, %s%s@page%s\n",
|
||||||
[1][1] = "\tadd\t%s, %s, %s%s@pageoff%s\n",
|
[1][1] = "\tadd\t%s, %s, %s%s@pageoff%s\n",
|
||||||
};
|
};
|
||||||
char *rn, *l, *p, off[32];
|
char *p, *l, off[32];
|
||||||
|
|
||||||
|
if (c->bits.i)
|
||||||
|
/* todo, handle large offsets */
|
||||||
|
sprintf(off, "+%"PRIi64, c->bits.i);
|
||||||
|
else
|
||||||
|
off[0] = 0;
|
||||||
|
l = str(c->label);
|
||||||
|
p = l[0] == '"' ? "" : T.assym;
|
||||||
|
if (c->rel == RelThr) {
|
||||||
|
fprintf(e->f, "\tmrs\t%s, tpidr_el0\n", rn);
|
||||||
|
fprintf(e->f, "\tadd\t%s, %s, #:tprel_hi12:%s%s%s, lsl #12\n",
|
||||||
|
rn, rn, p, l, off);
|
||||||
|
fprintf(e->f, "\tadd\t%s, %s, #:tprel_lo12_nc:%s%s%s\n",
|
||||||
|
rn, rn, p, l, off);
|
||||||
|
} else {
|
||||||
|
fprintf(e->f, ldsym[e->apple][0], rn, p, l, off);
|
||||||
|
fprintf(e->f, ldsym[e->apple][1], rn, rn, p, l, off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
loadcon(Con *c, int r, int k, E *e)
|
||||||
|
{
|
||||||
|
char *rn;
|
||||||
int64_t n;
|
int64_t n;
|
||||||
int w, sh;
|
int w, sh;
|
||||||
|
|
||||||
|
@ -262,16 +286,7 @@ loadcon(Con *c, int r, int k, E *e)
|
||||||
rn = rname(r, k);
|
rn = rname(r, k);
|
||||||
n = c->bits.i;
|
n = c->bits.i;
|
||||||
if (c->type == CAddr) {
|
if (c->type == CAddr) {
|
||||||
rn = rname(r, Kl);
|
loadaddr(c, rn, e);
|
||||||
if (n)
|
|
||||||
/* todo, handle large offsets */
|
|
||||||
sprintf(off, "+%"PRIi64, n);
|
|
||||||
else
|
|
||||||
off[0] = 0;
|
|
||||||
l = str(c->label);
|
|
||||||
p = c->local ? T.asloc : l[0] == '"' ? "" : T.assym;
|
|
||||||
fprintf(e->f, ldsym[e->apple][0], rn, p, l, off);
|
|
||||||
fprintf(e->f, ldsym[e->apple][1], rn, rn, p, l, off);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(c->type == CBits);
|
assert(c->type == CBits);
|
||||||
|
@ -471,7 +486,7 @@ emitfn(E *e)
|
||||||
Blk *b, *t;
|
Blk *b, *t;
|
||||||
Ins *i;
|
Ins *i;
|
||||||
|
|
||||||
emitlnk(e->fn->name, &e->fn->lnk, ".text", e->f);
|
emitfnlnk(e->fn->name, &e->fn->lnk, e->f);
|
||||||
framelayout(e);
|
framelayout(e);
|
||||||
|
|
||||||
if (e->fn->vararg && !e->apple) {
|
if (e->fn->vararg && !e->apple) {
|
||||||
|
|
|
@ -87,8 +87,8 @@ fixarg(Ref *pr, int k, int phi, Fn *fn)
|
||||||
n = stashbits(&c->bits, KWIDE(k) ? 8 : 4);
|
n = stashbits(&c->bits, KWIDE(k) ? 8 : 4);
|
||||||
vgrow(&fn->con, ++fn->ncon);
|
vgrow(&fn->con, ++fn->ncon);
|
||||||
c = &fn->con[fn->ncon-1];
|
c = &fn->con[fn->ncon-1];
|
||||||
sprintf(buf, "fp%d", n);
|
sprintf(buf, "\"%sfp%d\"", T.asloc, n);
|
||||||
*c = (Con){.type = CAddr, .local = 1};
|
*c = (Con){.type = CAddr};
|
||||||
c->label = intern(buf);
|
c->label = intern(buf);
|
||||||
r2 = newtmp("isel", Kl, fn);
|
r2 = newtmp("isel", Kl, fn);
|
||||||
emit(Oload, k, r1, r2, R);
|
emit(Oload, k, r1, r2, R);
|
||||||
|
|
35
emit.c
35
emit.c
|
@ -1,17 +1,30 @@
|
||||||
#include "all.h"
|
#include "all.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SecText,
|
||||||
|
SecData,
|
||||||
|
SecBss,
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
emitlnk(char *n, Lnk *l, char *s, FILE *f)
|
emitlnk(char *n, Lnk *l, int s, FILE *f)
|
||||||
{
|
{
|
||||||
|
static char *sec[2][3] = {
|
||||||
|
[0][SecText] = ".text",
|
||||||
|
[0][SecData] = ".data",
|
||||||
|
[0][SecBss] = ".bss",
|
||||||
|
[1][SecText] = ".abort \"unreachable\"",
|
||||||
|
[1][SecData] = ".section .tdata,\"awT\"",
|
||||||
|
[1][SecBss] = ".section .tbss,\"awT\"",
|
||||||
|
};
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if (l->sec) {
|
if (l->sec) {
|
||||||
fprintf(f, ".section %s", l->sec);
|
fprintf(f, ".section %s", l->sec);
|
||||||
if (l->secf)
|
if (l->secf)
|
||||||
fprintf(f, ", %s", l->secf);
|
fprintf(f, ",%s", l->secf);
|
||||||
} else {
|
} else
|
||||||
fputs(s, f);
|
fputs(sec[l->thread != 0][s], f);
|
||||||
}
|
|
||||||
fputc('\n', f);
|
fputc('\n', f);
|
||||||
if (l->align)
|
if (l->align)
|
||||||
fprintf(f, ".balign %d\n", l->align);
|
fprintf(f, ".balign %d\n", l->align);
|
||||||
|
@ -21,6 +34,12 @@ emitlnk(char *n, Lnk *l, char *s, FILE *f)
|
||||||
fprintf(f, "%s%s:\n", p, n);
|
fprintf(f, "%s%s:\n", p, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
emitfnlnk(char *n, Lnk *l, FILE *f)
|
||||||
|
{
|
||||||
|
emitlnk(n, l, SecText, f);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
emitdat(Dat *d, FILE *f)
|
emitdat(Dat *d, FILE *f)
|
||||||
{
|
{
|
||||||
|
@ -39,7 +58,7 @@ emitdat(Dat *d, FILE *f)
|
||||||
break;
|
break;
|
||||||
case DEnd:
|
case DEnd:
|
||||||
if (zero != -1) {
|
if (zero != -1) {
|
||||||
emitlnk(d->name, d->lnk, ".bss", f);
|
emitlnk(d->name, d->lnk, SecBss, f);
|
||||||
fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
|
fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -51,7 +70,7 @@ emitdat(Dat *d, FILE *f)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (zero != -1) {
|
if (zero != -1) {
|
||||||
emitlnk(d->name, d->lnk, ".data", f);
|
emitlnk(d->name, d->lnk, SecData, f);
|
||||||
if (zero > 0)
|
if (zero > 0)
|
||||||
fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
|
fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
|
||||||
zero = -1;
|
zero = -1;
|
||||||
|
@ -165,7 +184,7 @@ macho_emitfin(FILE *f)
|
||||||
static char *sec[3] = {
|
static char *sec[3] = {
|
||||||
"__TEXT,__literal4,4byte_literals",
|
"__TEXT,__literal4,4byte_literals",
|
||||||
"__TEXT,__literal8,8byte_literals",
|
"__TEXT,__literal8,8byte_literals",
|
||||||
".rodata", /* should not happen */
|
".abort \"unreachable\"",
|
||||||
};
|
};
|
||||||
|
|
||||||
emitfin(f, sec);
|
emitfin(f, sec);
|
||||||
|
|
9
fold.c
9
fold.c
|
@ -334,9 +334,10 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr)
|
||||||
} l, r;
|
} l, r;
|
||||||
uint64_t x;
|
uint64_t x;
|
||||||
uint32_t lab;
|
uint32_t lab;
|
||||||
int typ;
|
int typ, rel;
|
||||||
|
|
||||||
typ = CBits;
|
typ = CBits;
|
||||||
|
rel = RelDef;
|
||||||
lab = 0;
|
lab = 0;
|
||||||
l.s = cl->bits.i;
|
l.s = cl->bits.i;
|
||||||
r.s = cr->bits.i;
|
r.s = cr->bits.i;
|
||||||
|
@ -345,10 +346,12 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr)
|
||||||
if (cr->type == CAddr)
|
if (cr->type == CAddr)
|
||||||
return 1;
|
return 1;
|
||||||
lab = cl->label;
|
lab = cl->label;
|
||||||
|
rel = cl->rel;
|
||||||
typ = CAddr;
|
typ = CAddr;
|
||||||
}
|
}
|
||||||
else if (cr->type == CAddr) {
|
else if (cr->type == CAddr) {
|
||||||
lab = cr->label;
|
lab = cr->label;
|
||||||
|
rel = cr->rel;
|
||||||
typ = CAddr;
|
typ = CAddr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -356,6 +359,7 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr)
|
||||||
if (cl->type == CAddr) {
|
if (cl->type == CAddr) {
|
||||||
if (cr->type != CAddr) {
|
if (cr->type != CAddr) {
|
||||||
lab = cl->label;
|
lab = cl->label;
|
||||||
|
rel = cl->rel;
|
||||||
typ = CAddr;
|
typ = CAddr;
|
||||||
} else if (cl->label != cr->label)
|
} else if (cl->label != cr->label)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -404,6 +408,7 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr)
|
||||||
x = l.u;
|
x = l.u;
|
||||||
if (cl->type == CAddr) {
|
if (cl->type == CAddr) {
|
||||||
lab = cl->label;
|
lab = cl->label;
|
||||||
|
rel = cl->rel;
|
||||||
typ = CAddr;
|
typ = CAddr;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -457,7 +462,7 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr)
|
||||||
else
|
else
|
||||||
die("unreachable");
|
die("unreachable");
|
||||||
}
|
}
|
||||||
*res = (Con){.type=typ, .label=lab, .bits={.i=x}};
|
*res = (Con){.type=typ, .label=lab, .rel=rel, .bits={.i=x}};
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
load.c
2
load.c
|
@ -155,7 +155,7 @@ load(Slice sl, bits msk, Loc *l)
|
||||||
c.type = CAddr;
|
c.type = CAddr;
|
||||||
c.label = a->label;
|
c.label = a->label;
|
||||||
c.bits.i = a->offset;
|
c.bits.i = a->offset;
|
||||||
c.local = 0;
|
c.rel = RelDef;
|
||||||
r = newcon(&c, curf);
|
r = newcon(&c, curf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
31
parse.c
31
parse.c
|
@ -45,6 +45,7 @@ enum {
|
||||||
Tjnz,
|
Tjnz,
|
||||||
Tret,
|
Tret,
|
||||||
Texport,
|
Texport,
|
||||||
|
Tthread,
|
||||||
Tfunc,
|
Tfunc,
|
||||||
Ttype,
|
Ttype,
|
||||||
Tdata,
|
Tdata,
|
||||||
|
@ -99,6 +100,7 @@ static char *kwmap[Ntok] = {
|
||||||
[Tjnz] = "jnz",
|
[Tjnz] = "jnz",
|
||||||
[Tret] = "ret",
|
[Tret] = "ret",
|
||||||
[Texport] = "export",
|
[Texport] = "export",
|
||||||
|
[Tthread] = "thread",
|
||||||
[Tfunc] = "function",
|
[Tfunc] = "function",
|
||||||
[Ttype] = "type",
|
[Ttype] = "type",
|
||||||
[Tdata] = "data",
|
[Tdata] = "data",
|
||||||
|
@ -399,30 +401,34 @@ parseref()
|
||||||
|
|
||||||
memset(&c, 0, sizeof c);
|
memset(&c, 0, sizeof c);
|
||||||
switch (next()) {
|
switch (next()) {
|
||||||
|
default:
|
||||||
|
return R;
|
||||||
case Ttmp:
|
case Ttmp:
|
||||||
return tmpref(tokval.str);
|
return tmpref(tokval.str);
|
||||||
case Tint:
|
case Tint:
|
||||||
c.type = CBits;
|
c.type = CBits;
|
||||||
c.bits.i = tokval.num;
|
c.bits.i = tokval.num;
|
||||||
goto Look;
|
break;
|
||||||
case Tflts:
|
case Tflts:
|
||||||
c.type = CBits;
|
c.type = CBits;
|
||||||
c.bits.s = tokval.flts;
|
c.bits.s = tokval.flts;
|
||||||
c.flt = 1;
|
c.flt = 1;
|
||||||
goto Look;
|
break;
|
||||||
case Tfltd:
|
case Tfltd:
|
||||||
c.type = CBits;
|
c.type = CBits;
|
||||||
c.bits.d = tokval.fltd;
|
c.bits.d = tokval.fltd;
|
||||||
c.flt = 2;
|
c.flt = 2;
|
||||||
goto Look;
|
break;
|
||||||
|
case Tthread:
|
||||||
|
c.rel = RelThr;
|
||||||
|
expect(Tglo);
|
||||||
|
/* fall through */
|
||||||
case Tglo:
|
case Tglo:
|
||||||
c.type = CAddr;
|
c.type = CAddr;
|
||||||
c.label = intern(tokval.str);
|
c.label = intern(tokval.str);
|
||||||
Look:
|
break;
|
||||||
return newcon(&c, curf);
|
|
||||||
default:
|
|
||||||
return R;
|
|
||||||
}
|
}
|
||||||
|
return newcon(&c, curf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1101,6 +1107,9 @@ parselnk(Lnk *lnk)
|
||||||
case Texport:
|
case Texport:
|
||||||
lnk->export = 1;
|
lnk->export = 1;
|
||||||
break;
|
break;
|
||||||
|
case Tthread:
|
||||||
|
lnk->thread = 1;
|
||||||
|
break;
|
||||||
case Tsection:
|
case Tsection:
|
||||||
if (lnk->sec)
|
if (lnk->sec)
|
||||||
err("only one section allowed");
|
err("only one section allowed");
|
||||||
|
@ -1113,9 +1122,9 @@ parselnk(Lnk *lnk)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (haslnk)
|
if (t == Tfunc && lnk->thread)
|
||||||
if (t != Tdata)
|
err("only data may have thread linkage");
|
||||||
if (t != Tfunc)
|
if (haslnk && t != Tdata && t != Tfunc)
|
||||||
err("only data and function have linkage");
|
err("only data and function have linkage");
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
@ -1244,8 +1253,6 @@ printfn(Fn *fn, FILE *f)
|
||||||
Ins *i;
|
Ins *i;
|
||||||
uint n;
|
uint n;
|
||||||
|
|
||||||
if (fn->lnk.export)
|
|
||||||
fprintf(f, "export ");
|
|
||||||
fprintf(f, "function $%s() {\n", fn->name);
|
fprintf(f, "function $%s() {\n", fn->name);
|
||||||
for (b=fn->start; b; b=b->link) {
|
for (b=fn->start; b; b=b->link) {
|
||||||
fprintf(f, "@%s\n", b->name);
|
fprintf(f, "@%s\n", b->name);
|
||||||
|
|
63
rv64/emit.c
63
rv64/emit.c
|
@ -129,14 +129,10 @@ slot(int s, Fn *fn)
|
||||||
static void
|
static void
|
||||||
emitaddr(Con *c, FILE *f)
|
emitaddr(Con *c, FILE *f)
|
||||||
{
|
{
|
||||||
char off[32], *p;
|
assert(c->rel == RelDef);
|
||||||
|
fputs(str(c->label), f);
|
||||||
if (c->bits.i)
|
if (c->bits.i)
|
||||||
sprintf(off, "+%"PRIi64, c->bits.i);
|
fprintf(f, "+%"PRIi64, c->bits.i);
|
||||||
else
|
|
||||||
off[0] = 0;
|
|
||||||
p = c->local ? ".L" : "";
|
|
||||||
fprintf(f, "%s%s%s", p, str(c->label), off);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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
|
static void
|
||||||
loadcon(Con *c, int r, int k, FILE *f)
|
loadcon(Con *c, int r, int k, FILE *f)
|
||||||
{
|
{
|
||||||
char *rn;
|
char *rn;
|
||||||
int64_t n;
|
int64_t n;
|
||||||
int w;
|
|
||||||
|
|
||||||
w = KWIDE(k);
|
|
||||||
rn = rname[r];
|
rn = rname[r];
|
||||||
switch (c->type) {
|
switch (c->type) {
|
||||||
case CAddr:
|
case CAddr:
|
||||||
fprintf(f, "\tla %s, ", rn);
|
loadaddr(c, rn, f);
|
||||||
emitaddr(c, f);
|
|
||||||
fputc('\n', f);
|
|
||||||
break;
|
break;
|
||||||
case CBits:
|
case CBits:
|
||||||
n = c->bits.i;
|
n = c->bits.i;
|
||||||
if (!w)
|
if (!KWIDE(k))
|
||||||
n = (int32_t)n;
|
n = (int32_t)n;
|
||||||
fprintf(f, "\tli %s, %"PRIu64"\n", rn, n);
|
fprintf(f, "\tli %s, %"PRIi64"\n", rn, n);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
die("invalid constant");
|
die("invalid constant");
|
||||||
|
@ -255,12 +270,20 @@ loadcon(Con *c, int r, int k, FILE *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fixslot(Ref *pr, Fn *fn, FILE *f)
|
fixmem(Ref *pr, Fn *fn, FILE *f)
|
||||||
{
|
{
|
||||||
Ref r;
|
Ref r;
|
||||||
int64_t s;
|
int64_t s;
|
||||||
|
Con *c;
|
||||||
|
|
||||||
r = *pr;
|
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) {
|
if (rtype(r) == RSlot) {
|
||||||
s = slot(r.val, fn);
|
s = slot(r.val, fn);
|
||||||
if (s < -2048 || s > 2047) {
|
if (s < -2048 || s > 2047) {
|
||||||
|
@ -282,9 +305,9 @@ emitins(Ins *i, Fn *fn, FILE *f)
|
||||||
switch (i->op) {
|
switch (i->op) {
|
||||||
default:
|
default:
|
||||||
if (isload(i->op))
|
if (isload(i->op))
|
||||||
fixslot(&i->arg[0], fn, f);
|
fixmem(&i->arg[0], fn, f);
|
||||||
else if (isstore(i->op))
|
else if (isstore(i->op))
|
||||||
fixslot(&i->arg[1], fn, f);
|
fixmem(&i->arg[1], fn, f);
|
||||||
Table:
|
Table:
|
||||||
/* most instructions are just pulled out of
|
/* most instructions are just pulled out of
|
||||||
* the table omap[], some special cases are
|
* 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 Ks: i->op = Ostores; break;
|
||||||
case Kd: i->op = Ostored; break;
|
case Kd: i->op = Ostored; break;
|
||||||
}
|
}
|
||||||
fixslot(&i->arg[1], fn, f);
|
fixmem(&i->arg[1], fn, f);
|
||||||
goto Table;
|
goto Table;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -333,7 +356,7 @@ emitins(Ins *i, Fn *fn, FILE *f)
|
||||||
break;
|
break;
|
||||||
case RSlot:
|
case RSlot:
|
||||||
i->op = Oload;
|
i->op = Oload;
|
||||||
fixslot(&i->arg[0], fn, f);
|
fixmem(&i->arg[0], fn, f);
|
||||||
goto Table;
|
goto Table;
|
||||||
default:
|
default:
|
||||||
assert(isreg(i->arg[0]));
|
assert(isreg(i->arg[0]));
|
||||||
|
@ -415,7 +438,7 @@ rv64_emitfn(Fn *fn, FILE *f)
|
||||||
Blk *b, *s;
|
Blk *b, *s;
|
||||||
Ins *i;
|
Ins *i;
|
||||||
|
|
||||||
emitlnk(fn->name, &fn->lnk, ".text", f);
|
emitfnlnk(fn->name, &fn->lnk, f);
|
||||||
|
|
||||||
if (fn->vararg) {
|
if (fn->vararg) {
|
||||||
/* TODO: only need space for registers
|
/* TODO: only need space for registers
|
||||||
|
|
|
@ -44,8 +44,8 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn)
|
||||||
n = stashbits(&c->bits, KWIDE(k) ? 8 : 4);
|
n = stashbits(&c->bits, KWIDE(k) ? 8 : 4);
|
||||||
vgrow(&fn->con, ++fn->ncon);
|
vgrow(&fn->con, ++fn->ncon);
|
||||||
c = &fn->con[fn->ncon-1];
|
c = &fn->con[fn->ncon-1];
|
||||||
sprintf(buf, "fp%d", n);
|
sprintf(buf, "\"%sfp%d\"", T.asloc, n);
|
||||||
*c = (Con){.type = CAddr, .local = 1};
|
*c = (Con){.type = CAddr};
|
||||||
c->label = intern(buf);
|
c->label = intern(buf);
|
||||||
emit(Oload, k, r1, CON(c-fn->con), R);
|
emit(Oload, k, r1, CON(c-fn->con), R);
|
||||||
break;
|
break;
|
||||||
|
|
4
util.c
4
util.c
|
@ -358,9 +358,9 @@ newcon(Con *c0, Fn *fn)
|
||||||
for (i=0; i<fn->ncon; i++) {
|
for (i=0; i<fn->ncon; i++) {
|
||||||
c1 = &fn->con[i];
|
c1 = &fn->con[i];
|
||||||
if (c0->type == c1->type
|
if (c0->type == c1->type
|
||||||
&& c0->bits.i == c1->bits.i
|
|
||||||
&& c0->label == c1->label
|
&& c0->label == c1->label
|
||||||
&& c0->local == c1->local)
|
&& c0->bits.i == c1->bits.i
|
||||||
|
&& c0->rel == c1->rel)
|
||||||
return CON(i);
|
return CON(i);
|
||||||
}
|
}
|
||||||
vgrow(&fn->con, ++fn->ncon);
|
vgrow(&fn->con, ++fn->ncon);
|
||||||
|
|
Loading…
Add table
Reference in a new issue