From c13e1ec500a8a7ce6d41f0610ee1e71da50bb3b7 Mon Sep 17 00:00:00 2001 From: lemon Date: Sun, 22 Feb 2026 19:05:52 +0100 Subject: driver: recognize shared libraries; & backend: misc fixes for PIC isel edgecases --- main.c | 13 ++++++++----- x86_64/emit.c | 2 +- x86_64/isel.c | 10 ++++++---- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/main.c b/main.c index 12374af..3eb56ea 100644 --- a/main.c +++ b/main.c @@ -52,7 +52,7 @@ fileext(const char *path) return dot ? dot+1 : ""; } -enum inft { IFTauto, IFTc, IFTasm, IFTobj, IFTar }; +enum inft { IFTauto, IFTc, IFTasm, IFTobj, IFTar, IFTdll }; static enum inft ftdetect(const char *s) @@ -62,6 +62,7 @@ ftdetect(const char *s) if (!strcmp(ext, "o")) return IFTobj; if (!strcmp(ext, "a")) return IFTar; if (!strcmp(ext, "s")) return IFTasm; + if (!strcmp(ext, "so")) return IFTdll; warn(NULL, "assuming %'s is C source file", s); return IFTc; } @@ -198,7 +199,7 @@ optparse(char **args) const char *s = *++args; if (!s) fatal(NULL, "missing target name"); task.targ = s; - } else if (*arg == 'l' || *arg == 'L' || *arg == 'B') { + } else if (*arg == 'l' || *arg == 'L' || *arg == 'B' || !strcmp(arg, "shared")) { vpush(&task.linkargs, arg-1); } else if (!strcmp(arg, "v") || !strcmp(arg, "-verbose")) { task.verbose = 1; @@ -359,7 +360,8 @@ compileobjs(void) if (!ccopt.dbg.any && !task.syntaxonly) mktemps(); for (int i = 0; i < task.inf.n; ++i) { - if (task.inf.p[i].ft == IFTc) { + enum inft ft = task.inf.p[i].ft; + if (ft == IFTc) { if ((p = fork()) < 0) { error(NULL, "fork(): %s\n", strerror(errno)); exit(1); @@ -372,7 +374,8 @@ compileobjs(void) cleantemps(); exit(WEXITSTATUS(wstat)); } - } else if (task.inf.p[i].ft == IFTobj || task.inf.p[i].ft == IFTar) { + } else if (ft == IFTobj || ft == IFTar || ft == IFTdll) { + // passthru } else assert(!"not obj"); } if (!ccopt.dbg.any && !task.syntaxonly) { @@ -474,7 +477,7 @@ dolink(void) const char *o; switch (task.inf.p[i].ft) { case IFTc: o = task.inf.p[i].temp; break; - case IFTobj: case IFTar: + case IFTobj: case IFTar: case IFTdll: o = task.inf.p[i].path; break; default: assert(!"link obj?"); } diff --git a/x86_64/emit.c b/x86_64/emit.c index 0d7b77a..e54b7dd 100644 --- a/x86_64/emit.c +++ b/x86_64/emit.c @@ -880,7 +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 || (contab.p[val.i].flag & SFUNC)) && !(contab.p[val.i].flag & SLOCAL)) { + if ((ccopt.pic || (contab.p[val.i].flag & SFUNC)) && (contab.p[val.i].flag & (SLOCAL|SFUNC)) != (SLOCAL|SFUNC)) { 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 7f82984..c3857c7 100644 --- a/x86_64/isel.c +++ b/x86_64/isel.c @@ -90,8 +90,8 @@ fixarg(union ref *r, struct instr *ins, struct block *blk, int *curi) } if (docopy) *r = insertinstr(blk, (*curi)++, mkinstr(Ocopy, con->cls, *r)); - } else if (op != Omove && con->issym && ins && r == &ins->r) { - *r = insertinstr(blk, (*curi)++, mkinstr(Ocopy, KPTR, mkaddr((struct addr){*r}))); + } else if (op != Omove && (con->issym || (con->isdat && !con->deref)) && ins && r == &ins->r) { + *r = insertinstr(blk, (*curi)++, mkinstr(Ocopy, KPTR, *r)); } else if (in_range(op, Odiv, Ourem) && kisint(ins->cls)) goto DivImm; } else if (r->t == RICON && in_range(op, Odiv, Ourem) && kisint(ins->cls) && r == &ins->r) { @@ -107,6 +107,8 @@ fixarg(union ref *r, struct instr *ins, struct block *blk, int *curi) *ins = adr; else *r = insertinstr(blk, (*curi)++, adr); + } else if (r->bits == UNDREF.bits && ins->op != Ocopy) { + *r = insertinstr(blk, (*curi)++, mkinstr(Ocopy, ins->cls, *r)); } picfixsym(r, blk, curi); } @@ -387,7 +389,7 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi) case Ointrin: break; case Oshl: case Osar: case Oslr: - if (!iscon(ins->r)) { + if (!isintcon(ins->r)) { /* shift amount register is always CL */ insertinstr(blk, (*curi)++, mkinstr(Omove, KI32, mkref(RREG, RCX), ins->r)); ins->r = mkref(RREG, RCX); @@ -396,7 +398,7 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi) case Oequ: case Oneq: case Olth: case Ogth: case Olte: case Ogte: case Oulth: case Ougth: case Oulte: case Ougte: - if (iscon(ins->l)) { + if (iscon(ins->l) && !iscon(ins->r)) { /* lth imm, x -> gth x, imm */ if (!in_range(ins->op, Oequ, Oneq)) ins->op = ((op - Olth) ^ 1) + Olth; -- cgit v1.2.3