aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--c/c.c2
-rw-r--r--ir/intrin.c2
-rw-r--r--ir/ir.c8
-rw-r--r--ir/ir.h9
-rw-r--r--x86_64/emit.c12
-rw-r--r--x86_64/isel.c2
6 files changed, 19 insertions, 16 deletions
diff --git a/c/c.c b/c/c.c
index e070924..8a06272 100644
--- a/c/c.c
+++ b/c/c.c
@@ -2867,7 +2867,7 @@ expraddr(struct function *fn, const struct expr *ex)
uchar *p = objout.code ? objout.textbegin + off : objout.rodata.p + off;
memcpy(p, fn->name, typearrlen(decl->ty)-1);
}
- return mksymref(decl->sym, decl->ty.t == TYFUNC);
+ return mksymref(decl->sym, (SFUNC & -(decl->ty.t == TYFUNC)) | (SLOCAL & -(decl->scls == SCSTATIC || decl->isdef)));
default:
assert(0);
}
diff --git a/ir/intrin.c b/ir/intrin.c
index d31f9bb..dcd05a5 100644
--- a/ir/intrin.c
+++ b/ir/intrin.c
@@ -24,7 +24,7 @@ intrin(struct block *blk, int *curi, enum intrin in, struct arg *args, int narg,
/* memcpy */
*args[1].ty = *args[0].ty = mktyperef(cls2type(KPTR));
insertinstr(blk, (*curi)++, mkarginstr(cls2type(cls), mkintcon(cls, td->siz)));
- *this = mkinstr(Ocall, 0, mksymref(intern("memcpy"), 1), this->r);
+ *this = mkinstr(Ocall, 0, mksymref(intern("memcpy"), SFUNC), this->r);
calltab.p[this->r.i].narg = 3;
calltab.p[this->r.i].ret = cls2type(0);
return 0;
diff --git a/ir/ir.c b/ir/ir.c
index 1f1c9bc..29d52d4 100644
--- a/ir/ir.c
+++ b/ir/ir.c
@@ -101,7 +101,7 @@ newcon(const struct xcon *con)
{
uint h = hashb(0, con, sizeof *con);
uint i = h, n = countof(conht);
- assert((con->issym ^ con->isdat && !(con->isdat && con->isfunc)) || con->cls);
+ assert((con->issym ^ con->isdat) || con->cls);
for (;; ++i) {
i &= countof(conht) - 1;
if (!conht[i].issym && !conht[i].isdat && !conht[i].cls) {
@@ -145,9 +145,9 @@ mkfltcon(enum irclass k, double f)
}
union ref
-mksymref(internstr s, bool isfunc)
+mksymref(internstr s, enum symflags symflags)
{
- struct xcon con = { .issym = 1, .sym = s, .isfunc = isfunc };
+ struct xcon con = { .issym = 1, .sym = s, .flag = symflags };
return mkref(RXCON, newcon(&con));
}
@@ -172,7 +172,7 @@ mkdatref(internstr name, union type ctype, uint siz, uint align, const void *byt
if (n) memcpy(p, bytes, n);
if (dat.section != Stext) memset(p+n, 0, siz - n);
vpush(&dattab, dat);
- return mkref(RXCON, newcon(&(struct xcon){.isdat = 1, .deref = deref, .dat = dattab.n - 1}));
+ return mkref(RXCON, newcon(&(struct xcon){.isdat = 1, .deref = deref, .dat = dattab.n - 1, .flag = SLOCAL}));
}
internstr
diff --git a/ir/ir.h b/ir/ir.h
index 8e18e1f..8402864 100644
--- a/ir/ir.h
+++ b/ir/ir.h
@@ -25,9 +25,14 @@ struct irdat {
internstr name;
};
+enum symflags {
+ SLOCAL = 1,
+ SFUNC = 2,
+};
struct xcon {
- bool issym, isdat, isfunc, deref;
+ bool issym, isdat, deref;
uchar cls;
+ uchar flag;
union {
internstr sym;
int dat;
@@ -255,7 +260,7 @@ union ref mkfltcon(enum irclass, double);
#define isaddrcon(r,derefok) ((r).t == RXCON && !conht[(r).i].cls && (derefok || !conht[(r).i].deref))
#define intconval(r) ((r).t == RICON ? (r).i : conht[(r).i].i)
#define fltconval(r) ((r).t == RICON ? (r).i : conht[(r).i].f)
-union ref mksymref(internstr, bool isfunc);
+union ref mksymref(internstr, enum symflags);
union ref mkdatref(internstr name, union type ctype, uint siz, uint align, const void *, uint n, bool deref);
internstr xcon2sym(int ref);
struct instr mkalloca(uint siz, uint align);
diff --git a/x86_64/emit.c b/x86_64/emit.c
index 6f989f6..6e48965 100644
--- a/x86_64/emit.c
+++ b/x86_64/emit.c
@@ -336,12 +336,11 @@ encode(uchar **pcode, const struct desc *tab, int ntab, enum irclass k, struct o
int disp = mem.disp - 4 - offs[en->operenc];
internstr sym = xcon2sym(mem.con);
B(/*mod 0*/ (reg & 7) << 3 | RBP);
- if (objhassym(sym, &addr) == Stext) {
+ if (objhassym(sym, &addr) == Stext && mem.t != OSYMGOT) {
I32(addr - (*pcode - objout.textbegin) + disp);
} else {
enum relockind r = REL_PCREL32;
- if (mem.t == OSYMGOT)
- r = (rex ? REL_GOTPCRELX_REX : REL_GOTPCRELX);
+ if (mem.t == OSYMGOT) r = rex ? REL_GOTPCRELX_REX : REL_GOTPCRELX;
objreloc(xcon2sym(mem.con), r, Stext, *pcode - objout.textbegin, disp);
I32(0);
}
@@ -870,8 +869,8 @@ gencopy(uchar **pcode, enum irclass cls, struct block *blk, int curi, struct ope
}
/* normal (not 2-address) case */
Lea:
- if (isaddrcon(addr->base,0) && (ccopt.pic || conht[addr->base.i].isfunc)
- && !objhassym(xcon2sym(addr->base.i), NULL)) {
+ if (isaddrcon(addr->base,0) && (ccopt.pic || (conht[addr->base.i].flag & SFUNC))
+ && !(conht[addr->base.i].flag & SLOCAL)) {
assert(!addr->disp && !addr->index.bits);
val = addr->base;
goto GOTLoad;
@@ -881,8 +880,7 @@ gencopy(uchar **pcode, enum irclass cls, struct block *blk, int curi, struct ope
/* dst = 0 -> xor dst, dst; but only if it is ok to clobber flags */
Xxor(pcode, kisint(cls) ? KI32 : cls, dst, dst);
} else if (isaddrcon(val,0)) {
- if ((ccopt.pic || conht[val.i].isfunc)
- && !objhassym(xcon2sym(val.i), NULL)) {
+ if ((ccopt.pic || (conht[val.i].flag & SFUNC)) && !(conht[val.i].flag & SLOCAL)) {
GOTLoad:
/* for mov reg, [rip(sym@GOTPCREL)] */
Xmov(pcode, cls, dst, mkoper(OSYMGOT, .con = val.i, .cindex = NOINDEX));
diff --git a/x86_64/isel.c b/x86_64/isel.c
index 9c99608..40d8db4 100644
--- a/x86_64/isel.c
+++ b/x86_64/isel.c
@@ -305,7 +305,7 @@ fuseaddr(union ref *r, struct block *blk, int *curi)
if (r->t != RSTACK && r->t != RTMP) return 0;
if (!aadd(&addr, blk, curi, *r)) return 0;
- if (isaddrcon(addr.base,0) && (ccopt.pic || (ccopt.pie && addr.index.bits) || conht[addr.base.i].isfunc)) {
+ if (isaddrcon(addr.base,0) && (ccopt.pic || (ccopt.pie && addr.index.bits) || (conht[addr.base.i].flag & SFUNC))) {
/* pic needs to load from GOT */
/* pie cannot encode RIP-relative address with index register */
/* first load symbol address into a temp register */