Compare commits

..

No commits in common. "7ab2fbe07cef2da2ac4c7756aafe7fcdd59b21e7" and "4f9b94a9b32a694ba58f99a49d5ceec2656c06ca" have entirely different histories.

12 changed files with 28 additions and 156 deletions

11
all.h
View File

@ -292,16 +292,9 @@ struct Use {
};
struct Sym {
/* SGlo = 0 (direct access)
* SThr = 1 (local-exec TLS)
* SExt = 2 (GOT/PLT access)
* SExt|SThr = 3 (initial-exec TLS)
*/
enum {
SGlo = 0,
SThr = 1,
SExt = 2,
SExtThr = SExt|SThr,
SGlo,
SThr,
} type;
uint32_t id;
};

View File

@ -195,7 +195,7 @@ emitcon(Con *con, E *e)
case CAddr:
l = str(con->sym.id);
p = l[0] == '"' ? "" : T.assym;
if (con->sym.type & SThr) {
if (con->sym.type == SThr) {
if (T.apple)
fprintf(e->f, "%s%s@TLVP", p, l);
else
@ -551,48 +551,14 @@ emitins(Ins i, E *e)
regtoa(i.to.val, SLong));
break;
}
if (rtype(i.arg[0]) == RCon
&& e->fn->con[i.arg[0].val].sym.type == SExt) {
/* load address from the GOT */
assert(isreg(i.to));
con = &e->fn->con[i.arg[0].val];
sym = str(con->sym.id);
assert(!con->bits.i);
fprintf(e->f,
"\tmovq %s%s@GOTPCREL(%%rip), %%%s\n",
sym[0] == '"' ? "" : T.assym, sym,
regtoa(i.to.val, SLong));
break;
}
if (!T.apple
&& rtype(i.arg[0]) == RCon
&& e->fn->con[i.arg[0].val].sym.type == SExtThr) {
/* initial-exec TLS: load offset from
* GOT, add to thread-base register */
assert(isreg(i.to));
con = &e->fn->con[i.arg[0].val];
sym = str(con->sym.id);
assert(!con->bits.i);
emitf("movq %%fs:0, %L=", &i, e);
fprintf(e->f,
"\taddq %s%s@gottpoff(%%rip), %%%s\n",
sym[0] == '"' ? "" : T.assym, sym,
regtoa(i.to.val, SLong));
break;
}
goto Table;
case Ocall:
/* calls simply have a weird syntax in AT&T
* assembly... */
switch (rtype(i.arg[0])) {
case RCon:
con = &e->fn->con[i.arg[0].val];
fprintf(e->f, "\tcallq ");
emitcon(con, e);
if (con->type == CAddr
&& (con->sym.type & SExt)
&& !T.apple)
fprintf(e->f, "@PLT");
emitcon(&e->fn->con[i.arg[0].val], e);
fprintf(e->f, "\n");
break;
case RTmp:

View File

@ -120,34 +120,8 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn)
r1 = newtmp("isel", Kl, fn);
emit(Oaddr, Kl, r1, SLOT(s), R);
}
else if (op != Ocall && hascon(r0, &c, fn)
&& c->type == CAddr && (c->sym.type & SExt)
&& (!T.apple || c->sym.type == SExt)) {
/* extern symbols need indirection
* through the GOT
*/
r1 = newtmp("isel", Kl, fn);
if (c->bits.i) {
r2 = newtmp("isel", Kl, fn);
cc = (Con){.type = CBits};
cc.bits.i = c->bits.i;
r3 = newcon(&cc, fn);
emit(Oadd, Kl, r1, r2, r3);
} else
r2 = r1;
cc = *c;
cc.bits.i = 0;
r3 = newcon(&cc, fn);
emit(Oaddr, Kl, r2, r3, R);
if (rtype(r0) == RMem) {
m = &fn->mem[r0.val];
m->offset.type = CUndef;
m->base = r1;
r1 = r0;
}
}
else if (T.apple && hascon(r0, &c, fn)
&& c->type == CAddr && (c->sym.type & SThr)) {
&& c->type == CAddr && c->sym.type == SThr) {
r1 = newtmp("isel", Kl, fn);
if (c->bits.i) {
r2 = newtmp("isel", Kl, fn);

View File

@ -287,17 +287,6 @@ loadaddr(Con *c, char *rn, E *e)
"\tadd\tR, R, #:tprel_hi12:SO, lsl #12\n"
"\tadd\tR, R, #:tprel_lo12_nc:SO\n";
break;
case SExt:
if (T.apple)
s = "\tadrp\tR, S@gotpageO\n"
"\tldr\tR, [R, S@gotpageoffO]\n";
else
s = "\tadrp\tR, :got:SO\n"
"\tldr\tR, [R, #:got_lo12:SO]\n";
break;
case SExtThr:
die("extern thread not yet implemented on arm64");
break;
}
l = str(c->sym.id);
@ -479,7 +468,7 @@ emitins(Ins *i, E *e)
goto Table;
c = &e->fn->con[i->arg[0].val];
if (c->type != CAddr
|| (c->sym.type & SThr)
|| c->sym.type != SGlo
|| c->bits.i)
die("invalid call argument");
l = str(c->sym.id);

27
copy.c
View File

@ -41,8 +41,9 @@ bitwidth(uint64_t v)
return n+v;
}
/* no more than w bits are used */
static int
uwl(Fn *fn, Ref r, int w)
usewidthle(Fn *fn, Ref r, int w)
{
Ext e;
Tmp *t;
@ -51,6 +52,7 @@ uwl(Fn *fn, Ref r, int w)
Ins *i;
Ref rc;
int64_t v;
int b;
assert(rtype(r) == RTmp);
t = &fn->tmp[r.val];
@ -67,19 +69,21 @@ uwl(Fn *fn, Ref r, int w)
if (p->visit || req(p->to, R))
continue;
p->visit = 1;
if (uwl(fn, p->to, w))
b = usewidthle(fn, p->to, w);
p->visit = 0;
if (b)
continue;
break;
case UIns:
i = u->u.ins;
assert(i != 0);
if (i->op == Ocopy)
if (uwl(fn, i->to, w))
if (usewidthle(fn, i->to, w))
continue;
if (ext(i, &e)) {
if (e.usew <= w)
continue;
if (uwl(fn, i->to, w))
if (usewidthle(fn, i->to, w))
continue;
}
if (i->op == Oand) {
@ -103,21 +107,6 @@ uwl(Fn *fn, Ref r, int w)
return 1;
}
/* no more than w bits are used */
static int
usewidthle(Fn *fn, Ref r, int w)
{
Blk *b;
Phi *p;
int ret;
ret = uwl(fn, r, w);
for (b=fn->start; b; b=b->link)
for (p=b->phi; p; p=p->link)
p->visit = 0;
return ret;
}
static int
min(int v1, int v2)
{

View File

@ -181,8 +181,6 @@ by zero-extension, or by sign-extension.
DYNCONST :=
CONST
| 'thread' $IDENT # Thread-local symbol
| 'extern' $IDENT # Extern symbol (GOT)
| 'extern' 'thread' $IDENT # Extern thread-local (initial-exec)
VAL :=
DYNCONST
@ -227,16 +225,6 @@ When the `thread` keyword prefixes a symbol name, the
symbol's numeric value is resolved at runtime in the
thread-local storage.
When the `extern` keyword prefixes a symbol name, the
symbol is accessed indirectly through the Global Offset
Table (GOT). Function calls to extern symbols use the
Procedure Linkage Table (PLT). This enables PIE and
PIC code generation for symbols that are not part of
the main executable. When `extern` is combined with
`thread`, the symbol is accessed using the initial-exec
TLS model, suitable for thread-local variables defined
in shared libraries.
Vals are used as arguments in regular, phi, and jump
instructions within function definitions. They are
either constants or function-scope temporaries.

2
emit.c
View File

@ -221,7 +221,7 @@ macho_emitfin(FILE *f)
static char *sec[3] = {
"__TEXT,__literal4,4byte_literals",
"__TEXT,__literal8,8byte_literals",
"__TEXT,__literal16,16byte_literals",
".abort \"unreachable\"",
};
emitfin(f, sec);

4
gvn.c
View File

@ -43,11 +43,11 @@ static uint gvntbln;
static Ins *
gvndup(Ins *i, int insert)
{
uint idx;
uint idx, n;
Ins *ii;
idx = ihash(i) % gvntbln;
for (;;) {
for (n=1;; n++) {
ii = gvntbl[idx];
if (!ii)
break;

2
main.c
View File

@ -10,7 +10,7 @@ char debug['Z'+1] = {
['M'] = 0, /* memory optimization */
['N'] = 0, /* ssa construction */
['C'] = 0, /* copy elimination */
['G'] = 0, /* gvn/gcm */
['F'] = 0, /* constant folding */
['K'] = 0, /* if-conversion */
['A'] = 0, /* abi lowering */
['I'] = 0, /* instruction selection */

22
parse.c
View File

@ -57,7 +57,6 @@ enum Token {
Thlt,
Texport,
Tthread,
Textern,
Tcommon,
Tfunc,
Ttype,
@ -117,7 +116,6 @@ static char *kwmap[Ntok] = {
[Thlt] = "hlt",
[Texport] = "export",
[Tthread] = "thread",
[Textern] = "extern",
[Tcommon] = "common",
[Tfunc] = "function",
[Ttype] = "type",
@ -217,15 +215,12 @@ getint()
n = 0;
c = fgetc(inf);
m = (c == '-');
if (m) {
if (m)
c = fgetc(inf);
if (!isdigit(c))
err("integer expected");
}
do {
n = 10*n + (c - '0');
c = fgetc(inf);
} while (isdigit(c));
} while ('0' <= c && c <= '9');
ungetc(c, inf);
if (m)
n = 1 + ~n;
@ -450,20 +445,11 @@ parseref()
c.bits.d = tokval.fltd;
c.flt = 2;
break;
case Textern:
c.sym.type = SExt;
if (peek() == Tthread) {
next();
c.sym.type |= SThr;
}
expect(Tglo);
goto Glo;
case Tthread:
c.sym.type = SThr;
expect(Tglo);
/* fall through */
case Tglo:
Glo:
c.type = CAddr;
c.sym.id = intern(tokval.str);
break;
@ -1266,9 +1252,7 @@ printcon(Con *c, FILE *f)
case CUndef:
break;
case CAddr:
if (c->sym.type & SExt)
fprintf(f, "extern ");
if (c->sym.type & SThr)
if (c->sym.type == SThr)
fprintf(f, "thread ");
fprintf(f, "$%s", str(c->sym.id));
if (c->bits.i)

View File

@ -131,7 +131,7 @@ slot(Ref r, Fn *fn)
static void
emitaddr(Con *c, FILE *f)
{
assert(c->sym.type == SGlo || c->sym.type == SExt);
assert(c->sym.type == SGlo);
fputs(str(c->sym.id), f);
if (c->bits.i)
fprintf(f, "+%"PRIi64, c->bits.i);
@ -231,8 +231,7 @@ loadaddr(Con *c, char *rn, FILE *f)
{
char off[32];
switch (c->sym.type) {
case SThr:
if (c->sym.type == SThr) {
if (c->bits.i)
sprintf(off, "+%"PRIi64, c->bits.i);
else
@ -243,20 +242,10 @@ loadaddr(Con *c, char *rn, FILE *f)
rn, rn, str(c->sym.id), off);
fprintf(f, "\taddi %s, %s, %%tprel_lo(%s)%s\n",
rn, rn, str(c->sym.id), off);
break;
case SExt:
} else {
fprintf(f, "\tla %s, ", rn);
emitaddr(c, f);
fputc('\n', f);
break;
case SExtThr:
die("extern thread not yet implemented on rv64");
break;
default:
fprintf(f, "\tla %s, ", rn);
emitaddr(c, f);
fputc('\n', f);
break;
}
}
@ -293,7 +282,7 @@ fixmem(Ref *pr, Fn *fn, FILE *f)
if (rtype(r) == RCon) {
c = &fn->con[r.val];
if (c->type == CAddr)
if (c->sym.type != SGlo) {
if (c->sym.type == SThr) {
loadcon(c, T6, Kl, f);
*pr = TMP(T6);
}
@ -398,7 +387,7 @@ emitins(Ins *i, Fn *fn, FILE *f)
case RCon:
con = &fn->con[i->arg[0].val];
if (con->type != CAddr
|| (con->sym.type & SThr)
|| con->sym.type != SGlo
|| con->bits.i)
goto Invalid;
fprintf(f, "\tcall %s\n", str(con->sym.id));

View File

@ -29,7 +29,7 @@ char *tok[] = {
"function", "type", "data", "section", "align", "dbgfile",
"blit", "l", "w", "sh", "uh", "h", "sb", "ub", "b",
"d", "s", "z", "loadw", "loadl", "loads", "loadd",
"alloc1", "alloc2", "thread", "extern", "common",
"alloc1", "alloc2", "thread", "common",
};
enum {