aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2026-02-22 19:05:52 +0100
committerlemon <lsof@mailbox.org>2026-02-22 19:05:52 +0100
commitc13e1ec500a8a7ce6d41f0610ee1e71da50bb3b7 (patch)
tree2a7050320918656c5d9521f258d8e1703039a35d
parent975d76cfc99fcf797ebe0ac254dd3252405bd778 (diff)
driver: recognize shared libraries; & backend: misc fixes for PIC isel edgecases
-rw-r--r--main.c13
-rw-r--r--x86_64/emit.c2
-rw-r--r--x86_64/isel.c10
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;