History

add support for thread-local storage

The apple targets are not done yet.

Quentin Carbonneaux committed 4 years ago

Commit 00a30951 parent 5cea0c212 files · +145 −70Browse files

Unified · Split

12 files
  1. all.h +6 −2
  2. amd64/emit.c +7 −4
  3. amd64/isel.c +1 −2
  4. arm64/emit.c +28 −13
  5. arm64/isel.c +2 −2
  6. emit.c +27 −8
  7. fold.c +7 −2
  8. load.c +1 −1
  9. parse.c +19 −12
  10. rv64/emit.c +43 −20
  11. rv64/isel.c +2 −2
  12. util.c +2 −2
all.h+6−2
@@ -324,8 +324,11 @@ struct Con { · 323 unmodified lines
324324 double d;
325325 float s;
326326 } bits;
327+ enum {
328+ RelDef,
329+ RelThr,
330+ } rel;
327331 char flt; /* 1 to print as s, 2 to print as d */
328− char local;
329332 };
330333
331334 typedef struct Addr Addr;
@@ -339,6 +342,7 @@ struct Addr { /* amd64 addressing */ · 7 unmodified lines
339342
340343 struct Lnk {
341344 char export;
345+ char thread;
342346 char align;
343347 char *sec;
344348 char *secf;
@@ -536,7 +540,7 @@ void spill(Fn *); · 191 unmodified lines
536540 void rega(Fn *);
537541
538542 /* emit.c */
539−void emitlnk(char *, Lnk *, char *, FILE *);
543+void emitfnlnk(char *, Lnk *, FILE *);
540544 void emitdat(Dat *, FILE *);
541545 int stashbits(void *, int);
542546 void elf_emitfnfin(char *, FILE *);
amd64/emit.c+7−4
@@ -166,8 +166,11 @@ emitcon(Con *con, FILE *f) · 165 unmodified lines
166166 switch (con->type) {
167167 case CAddr:
168168 l = str(con->label);
169− p = con->local ? T.asloc : l[0] == '"' ? "" : T.assym;
170− fprintf(f, "%s%s", p, l);
169+ p = l[0] == '"' ? "" : T.assym;
170+ if (con->rel == RelThr)
171+ fprintf(f, "%%fs:%s%s@tpoff", p, l);
172+ else
173+ fprintf(f, "%s%s", p, l);
171174 if (con->bits.i)
172175 fprintf(f, "%+"PRId64, con->bits.i);
173176 break;
@@ -337,7 +340,7 @@ Next: · 163 unmodified lines
337340 case RCon:
338341 off = fn->con[ref.val];
339342 emitcon(&off, f);
340− if (off.type == CAddr)
343+ if (off.type == CAddr && off.rel != RelThr)
341344 fprintf(f, "(%%rip)");
342345 break;
343346 case RTmp:
@@ -549,7 +552,7 @@ emitfn(Fn *fn, FILE *f) · 205 unmodified lines
549552 int *r, c, o, n, lbl;
550553 uint64_t fs;
551554
552− emitlnk(fn->name, &fn->lnk, ".text", f);
555+ emitfnlnk(fn->name, &fn->lnk, f);
553556 fputs("\tpushq %rbp\n\tmovq %rsp, %rbp\n", f);
554557 fs = framesz(fn);
555558 if (fs)
amd64/isel.c+1−2
@@ -78,9 +78,8 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn) · 77 unmodified lines
7878 vgrow(&fn->mem, ++fn->nmem);
7979 memset(&a, 0, sizeof a);
8080 a.offset.type = CAddr;
81− a.offset.local = 1;
8281 n = stashbits(&fn->con[r0.val].bits, KWIDE(k) ? 8 : 4);
83− sprintf(buf, "fp%d", n);
82+ sprintf(buf, "\"%sfp%d\"", T.asloc, n);
8483 a.offset.label = intern(buf);
8584 fn->mem[fn->nmem-1] = a;
8685 }
arm64/emit.c+28−13
@@ -244,7 +244,7 @@ emitf(char *s, Ins *i, E *e) · 243 unmodified lines
244244 }
245245
246246 static void
247−loadcon(Con *c, int r, int k, E *e)
247+loadaddr(Con *c, char *rn, E *e)
248248 {
249249 static char *ldsym[][2] = {
250250 /* arm64 */
@@ -254,7 +254,31 @@ loadcon(Con *c, int r, int k, E *e) · 3 unmodified lines
254254 [1][0] = "\tadrp\t%s, %s%s@page%s\n",
255255 [1][1] = "\tadd\t%s, %s, %s%s@pageoff%s\n",
256256 };
257− char *rn, *l, *p, off[32];
257+ char *p, *l, off[32];
258+
259+ if (c->bits.i)
260+ /* todo, handle large offsets */
261+ sprintf(off, "+%"PRIi64, c->bits.i);
262+ else
263+ off[0] = 0;
264+ l = str(c->label);
265+ p = l[0] == '"' ? "" : T.assym;
266+ if (c->rel == RelThr) {
267+ fprintf(e->f, "\tmrs\t%s, tpidr_el0\n", rn);
268+ fprintf(e->f, "\tadd\t%s, %s, #:tprel_hi12:%s%s%s, lsl #12\n",
269+ rn, rn, p, l, off);
270+ fprintf(e->f, "\tadd\t%s, %s, #:tprel_lo12_nc:%s%s%s\n",
271+ rn, rn, p, l, off);
272+ } else {
273+ fprintf(e->f, ldsym[e->apple][0], rn, p, l, off);
274+ fprintf(e->f, ldsym[e->apple][1], rn, rn, p, l, off);
275+ }
276+}
277+
278+static void
279+loadcon(Con *c, int r, int k, E *e)
280+{
281+ char *rn;
258282 int64_t n;
259283 int w, sh;
260284
@@ -262,16 +286,7 @@ loadcon(Con *c, int r, int k, E *e) · 1 unmodified line
262286 rn = rname(r, k);
263287 n = c->bits.i;
264288 if (c->type == CAddr) {
265− rn = rname(r, Kl);
266− if (n)
267− /* todo, handle large offsets */
268− sprintf(off, "+%"PRIi64, n);
269− else
270− off[0] = 0;
271− l = str(c->label);
272− p = c->local ? T.asloc : l[0] == '"' ? "" : T.assym;
273− fprintf(e->f, ldsym[e->apple][0], rn, p, l, off);
274− fprintf(e->f, ldsym[e->apple][1], rn, rn, p, l, off);
289+ loadaddr(c, rn, e);
275290 return;
276291 }
277292 assert(c->type == CBits);
@@ -471,7 +486,7 @@ emitfn(E *e) · 193 unmodified lines
471486 Blk *b, *t;
472487 Ins *i;
473488
474− emitlnk(e->fn->name, &e->fn->lnk, ".text", e->f);
489+ emitfnlnk(e->fn->name, &e->fn->lnk, e->f);
475490 framelayout(e);
476491
477492 if (e->fn->vararg && !e->apple) {
arm64/isel.c+2−2
@@ -87,8 +87,8 @@ fixarg(Ref *pr, int k, int phi, Fn *fn) · 86 unmodified lines
8787 n = stashbits(&c->bits, KWIDE(k) ? 8 : 4);
8888 vgrow(&fn->con, ++fn->ncon);
8989 c = &fn->con[fn->ncon-1];
90− sprintf(buf, "fp%d", n);
91− *c = (Con){.type = CAddr, .local = 1};
90+ sprintf(buf, "\"%sfp%d\"", T.asloc, n);
91+ *c = (Con){.type = CAddr};
9292 c->label = intern(buf);
9393 r2 = newtmp("isel", Kl, fn);
9494 emit(Oload, k, r1, r2, R);
emit.c+27−8
@@ -1,17 +1,30 @@
11 #include "all.h"
22
3+enum {
4+ SecText,
5+ SecData,
6+ SecBss,
7+};
8+
39 void
4−emitlnk(char *n, Lnk *l, char *s, FILE *f)
10+emitlnk(char *n, Lnk *l, int s, FILE *f)
511 {
12+ static char *sec[2][3] = {
13+ [0][SecText] = ".text",
14+ [0][SecData] = ".data",
15+ [0][SecBss] = ".bss",
16+ [1][SecText] = ".abort \"unreachable\"",
17+ [1][SecData] = ".section .tdata,\"awT\"",
18+ [1][SecBss] = ".section .tbss,\"awT\"",
19+ };
620 char *p;
721
822 if (l->sec) {
923 fprintf(f, ".section %s", l->sec);
1024 if (l->secf)
11− fprintf(f, ", %s", l->secf);
12− } else {
13− fputs(s, f);
14− }
25+ fprintf(f, ",%s", l->secf);
26+ } else
27+ fputs(sec[l->thread != 0][s], f);
1528 fputc('\n', f);
1629 if (l->align)
1730 fprintf(f, ".balign %d\n", l->align);
@@ -21,6 +34,12 @@ emitlnk(char *n, Lnk *l, char *s, FILE *f) · 3 unmodified lines
2134 fprintf(f, "%s%s:\n", p, n);
2235 }
2336
37+void
38+emitfnlnk(char *n, Lnk *l, FILE *f)
39+{
40+ emitlnk(n, l, SecText, f);
41+}
42+
2443 void
2544 emitdat(Dat *d, FILE *f)
2645 {
@@ -39,7 +58,7 @@ emitdat(Dat *d, FILE *f) · 12 unmodified lines
3958 break;
4059 case DEnd:
4160 if (zero != -1) {
42− emitlnk(d->name, d->lnk, ".bss", f);
61+ emitlnk(d->name, d->lnk, SecBss, f);
4362 fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
4463 }
4564 break;
@@ -51,7 +70,7 @@ emitdat(Dat *d, FILE *f) · 5 unmodified lines
5170 break;
5271 default:
5372 if (zero != -1) {
54− emitlnk(d->name, d->lnk, ".data", f);
73+ emitlnk(d->name, d->lnk, SecData, f);
5574 if (zero > 0)
5675 fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
5776 zero = -1;
@@ -165,7 +184,7 @@ macho_emitfin(FILE *f) · 107 unmodified lines
165184 static char *sec[3] = {
166185 "__TEXT,__literal4,4byte_literals",
167186 "__TEXT,__literal8,8byte_literals",
168− ".rodata", /* should not happen */
187+ ".abort \"unreachable\"",
169188 };
170189
171190 emitfin(f, sec);
fold.c+7−2
@@ -334,9 +334,10 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr) · 333 unmodified lines
334334 } l, r;
335335 uint64_t x;
336336 uint32_t lab;
337− int typ;
337+ int typ, rel;
338338
339339 typ = CBits;
340+ rel = RelDef;
340341 lab = 0;
341342 l.s = cl->bits.i;
342343 r.s = cr->bits.i;
@@ -345,10 +346,12 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr) · 2 unmodified lines
345346 if (cr->type == CAddr)
346347 return 1;
347348 lab = cl->label;
349+ rel = cl->rel;
348350 typ = CAddr;
349351 }
350352 else if (cr->type == CAddr) {
351353 lab = cr->label;
354+ rel = cr->rel;
352355 typ = CAddr;
353356 }
354357 }
@@ -356,6 +359,7 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr) · 1 unmodified line
356359 if (cl->type == CAddr) {
357360 if (cr->type != CAddr) {
358361 lab = cl->label;
362+ rel = cl->rel;
359363 typ = CAddr;
360364 } else if (cl->label != cr->label)
361365 return 1;
@@ -404,6 +408,7 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr) · 42 unmodified lines
404408 x = l.u;
405409 if (cl->type == CAddr) {
406410 lab = cl->label;
411+ rel = cl->rel;
407412 typ = CAddr;
408413 }
409414 break;
@@ -457,7 +462,7 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr) · 47 unmodified lines
457462 else
458463 die("unreachable");
459464 }
460− *res = (Con){.type=typ, .label=lab, .bits={.i=x}};
465+ *res = (Con){.type=typ, .label=lab, .rel=rel, .bits={.i=x}};
461466 return 0;
462467 }
463468
load.c+1−1
@@ -155,7 +155,7 @@ load(Slice sl, bits msk, Loc *l) · 154 unmodified lines
155155 c.type = CAddr;
156156 c.label = a->label;
157157 c.bits.i = a->offset;
158− c.local = 0;
158+ c.rel = RelDef;
159159 r = newcon(&c, curf);
160160 break;
161161 }
parse.c+19−12
@@ -45,6 +45,7 @@ enum { · 44 unmodified lines
4545 Tjnz,
4646 Tret,
4747 Texport,
48+ Tthread,
4849 Tfunc,
4950 Ttype,
5051 Tdata,
@@ -99,6 +100,7 @@ static char *kwmap[Ntok] = { · 48 unmodified lines
99100 [Tjnz] = "jnz",
100101 [Tret] = "ret",
101102 [Texport] = "export",
103+ [Tthread] = "thread",
102104 [Tfunc] = "function",
103105 [Ttype] = "type",
104106 [Tdata] = "data",
@@ -399,30 +401,34 @@ parseref() · 294 unmodified lines
399401
400402 memset(&c, 0, sizeof c);
401403 switch (next()) {
404+ default:
405+ return R;
402406 case Ttmp:
403407 return tmpref(tokval.str);
404408 case Tint:
405409 c.type = CBits;
406410 c.bits.i = tokval.num;
407− goto Look;
411+ break;
408412 case Tflts:
409413 c.type = CBits;
410414 c.bits.s = tokval.flts;
411415 c.flt = 1;
412− goto Look;
416+ break;
413417 case Tfltd:
414418 c.type = CBits;
415419 c.bits.d = tokval.fltd;
416420 c.flt = 2;
417− goto Look;
421+ break;
422+ case Tthread:
423+ c.rel = RelThr;
424+ expect(Tglo);
425+ /* fall through */
418426 case Tglo:
419427 c.type = CAddr;
420428 c.label = intern(tokval.str);
421− Look:
422− return newcon(&c, curf);
423− default:
424− return R;
429+ break;
425430 }
431+ return newcon(&c, curf);
426432 }
427433
428434 static int
@@ -1101,6 +1107,9 @@ parselnk(Lnk *lnk) · 672 unmodified lines
11011107 case Texport:
11021108 lnk->export = 1;
11031109 break;
1110+ case Tthread:
1111+ lnk->thread = 1;
1112+ break;
11041113 case Tsection:
11051114 if (lnk->sec)
11061115 err("only one section allowed");
@@ -1113,9 +1122,9 @@ parselnk(Lnk *lnk) · 6 unmodified lines
11131122 }
11141123 break;
11151124 default:
1116− if (haslnk)
1117− if (t != Tdata)
1118− if (t != Tfunc)
1125+ if (t == Tfunc && lnk->thread)
1126+ err("only data may have thread linkage");
1127+ if (haslnk && t != Tdata && t != Tfunc)
11191128 err("only data and function have linkage");
11201129 return t;
11211130 }
@@ -1244,8 +1253,6 @@ printfn(Fn *fn, FILE *f) · 122 unmodified lines
12441253 Ins *i;
12451254 uint n;
12461255
1247− if (fn->lnk.export)
1248− fprintf(f, "export ");
12491256 fprintf(f, "function $%s() {\n", fn->name);
12501257 for (b=fn->start; b; b=b->link) {
12511258 fprintf(f, "@%s\n", b->name);
rv64/emit.c+43−20
@@ -129,14 +129,10 @@ slot(int s, Fn *fn) · 128 unmodified lines
129129 static void
130130 emitaddr(Con *c, FILE *f)
131131 {
132− char off[32], *p;
133−
132+ assert(c->rel == RelDef);
133+ fputs(str(c->label), f);
134134 if (c->bits.i)
135− sprintf(off, "+%"PRIi64, c->bits.i);
136− else
137− off[0] = 0;
138− p = c->local ? ".L" : "";
139− fprintf(f, "%s%s%s", p, str(c->label), off);
135+ fprintf(f, "+%"PRIi64, c->bits.i);
140136 }
141137
142138 static void
@@ -228,26 +224,45 @@ emitf(char *s, Ins *i, Fn *fn, FILE *f) · 85 unmodified lines
228224 }
229225 }
230226
227+static void
228+loadaddr(Con *c, char *rn, FILE *f)
229+{
230+ char off[32];
231+
232+ if (c->rel == RelThr) {
233+ if (c->bits.i)
234+ sprintf(off, "+%"PRIi64, c->bits.i);
235+ else
236+ off[0] = 0;
237+ fprintf(f, "\tlui %s, %%tprel_hi(%s)%s\n",
238+ rn, str(c->label), off);
239+ fprintf(f, "\tadd %s, %s, tp, %%tprel_add(%s)%s\n",
240+ rn, rn, str(c->label), off);
241+ fprintf(f, "\taddi %s, %s, %%tprel_lo(%s)%s\n",
242+ rn, rn, str(c->label), off);
243+ } else {
244+ fprintf(f, "\tla %s, ", rn);
245+ emitaddr(c, f);
246+ fputc('\n', f);
247+ }
248+}
249+
231250 static void
232251 loadcon(Con *c, int r, int k, FILE *f)
233252 {
234253 char *rn;
235254 int64_t n;
236− int w;
237255
238− w = KWIDE(k);
239256 rn = rname[r];
240257 switch (c->type) {
241258 case CAddr:
242− fprintf(f, "\tla %s, ", rn);
243− emitaddr(c, f);
244− fputc('\n', f);
259+ loadaddr(c, rn, f);
245260 break;
246261 case CBits:
247262 n = c->bits.i;
248− if (!w)
263+ if (!KWIDE(k))
249264 n = (int32_t)n;
250− fprintf(f, "\tli %s, %"PRIu64"\n", rn, n);
265+ fprintf(f, "\tli %s, %"PRIi64"\n", rn, n);
251266 break;
252267 default:
253268 die("invalid constant");
@@ -255,12 +270,20 @@ loadcon(Con *c, int r, int k, FILE *f) · 1 unmodified line
255270 }
256271
257272 static void
258−fixslot(Ref *pr, Fn *fn, FILE *f)
273+fixmem(Ref *pr, Fn *fn, FILE *f)
259274 {
260275 Ref r;
261276 int64_t s;
277+ Con *c;
262278
263279 r = *pr;
280+ if (rtype(r) == RCon) {
281+ c = &fn->con[r.val];
282+ if (c->type == CAddr && c->rel == RelThr) {
283+ loadcon(c, T6, Kl, f);
284+ *pr = TMP(T6);
285+ }
286+ }
264287 if (rtype(r) == RSlot) {
265288 s = slot(r.val, fn);
266289 if (s < -2048 || s > 2047) {
@@ -282,9 +305,9 @@ emitins(Ins *i, Fn *fn, FILE *f) · 15 unmodified lines
282305 switch (i->op) {
283306 default:
284307 if (isload(i->op))
285− fixslot(&i->arg[0], fn, f);
308+ fixmem(&i->arg[0], fn, f);
286309 else if (isstore(i->op))
287− fixslot(&i->arg[1], fn, f);
310+ fixmem(&i->arg[1], fn, f);
288311 Table:
289312 /* most instructions are just pulled out of
290313 * the table omap[], some special cases are
@@ -321,7 +344,7 @@ emitins(Ins *i, Fn *fn, FILE *f) · 30 unmodified lines
321344 case Ks: i->op = Ostores; break;
322345 case Kd: i->op = Ostored; break;
323346 }
324− fixslot(&i->arg[1], fn, f);
347+ fixmem(&i->arg[1], fn, f);
325348 goto Table;
326349 }
327350 break;
@@ -333,7 +356,7 @@ emitins(Ins *i, Fn *fn, FILE *f) · 5 unmodified lines
333356 break;
334357 case RSlot:
335358 i->op = Oload;
336− fixslot(&i->arg[0], fn, f);
359+ fixmem(&i->arg[0], fn, f);
337360 goto Table;
338361 default:
339362 assert(isreg(i->arg[0]));
@@ -415,7 +438,7 @@ rv64_emitfn(Fn *fn, FILE *f) · 75 unmodified lines
415438 Blk *b, *s;
416439 Ins *i;
417440
418− emitlnk(fn->name, &fn->lnk, ".text", f);
441+ emitfnlnk(fn->name, &fn->lnk, f);
419442
420443 if (fn->vararg) {
421444 /* TODO: only need space for registers
rv64/isel.c+2−2
@@ -44,8 +44,8 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn) · 43 unmodified lines
4444 n = stashbits(&c->bits, KWIDE(k) ? 8 : 4);
4545 vgrow(&fn->con, ++fn->ncon);
4646 c = &fn->con[fn->ncon-1];
47− sprintf(buf, "fp%d", n);
48− *c = (Con){.type = CAddr, .local = 1};
47+ sprintf(buf, "\"%sfp%d\"", T.asloc, n);
48+ *c = (Con){.type = CAddr};
4949 c->label = intern(buf);
5050 emit(Oload, k, r1, CON(c-fn->con), R);
5151 break;
util.c+2−2
@@ -358,9 +358,9 @@ newcon(Con *c0, Fn *fn) · 357 unmodified lines
358358 for (i=0; i<fn->ncon; i++) {
359359 c1 = &fn->con[i];
360360 if (c0->type == c1->type
361− && c0->bits.i == c1->bits.i
362361 && c0->label == c1->label
363− && c0->local == c1->local)
362+ && c0->bits.i == c1->bits.i
363+ && c0->rel == c1->rel)
364364 return CON(i);
365365 }
366366 vgrow(&fn->con, ++fn->ncon);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t