summaryrefslogtreecommitdiff
path: root/usr.bin/pcc/i386
diff options
context:
space:
mode:
authorAnders Magnusson <ragge@cvs.openbsd.org>2007-12-09 18:54:40 +0000
committerAnders Magnusson <ragge@cvs.openbsd.org>2007-12-09 18:54:40 +0000
commitd0ef6a00182cf3073f66ef501893e6b93016bee2 (patch)
tree4ca736e43fc2a37e940d93ed073f8066420b6e40 /usr.bin/pcc/i386
parenteb5cd1326c57b80460c264cca6fde959e0ec9766 (diff)
Updates from master repo:
- Add support for PIC code.
Diffstat (limited to 'usr.bin/pcc/i386')
-rw-r--r--usr.bin/pcc/i386/code.c14
-rw-r--r--usr.bin/pcc/i386/local.c116
-rw-r--r--usr.bin/pcc/i386/local2.c46
-rw-r--r--usr.bin/pcc/i386/table.c6
4 files changed, 155 insertions, 27 deletions
diff --git a/usr.bin/pcc/i386/code.c b/usr.bin/pcc/i386/code.c
index 6e51e853f84..e2225f63a99 100644
--- a/usr.bin/pcc/i386/code.c
+++ b/usr.bin/pcc/i386/code.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: code.c,v 1.5 2007/11/22 15:06:43 stefan Exp $ */
+/* $OpenBSD: code.c,v 1.6 2007/12/09 18:54:39 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -183,7 +183,7 @@ funcode(NODE *p)
} else {
for (r = p->n_right; r->n_left->n_op == CM; r = r->n_left)
;
- r->n_left = block(CM, l, p->n_left, INT, 0, MKSUE(INT));
+ r->n_left = block(CM, l, r->n_left, INT, 0, MKSUE(INT));
}
return p;
}
@@ -223,16 +223,6 @@ bycode(int t, int i)
}
/*
- * n integer words of zeros
- */
-void
-zecode(int n)
-{
- printf(" .zero %d\n", n * (SZINT/SZCHAR));
-// inoff += n * SZINT;
-}
-
-/*
* return the alignment of field of type t
*/
int
diff --git a/usr.bin/pcc/i386/local.c b/usr.bin/pcc/i386/local.c
index 1f4d3f41462..cb35c3bd679 100644
--- a/usr.bin/pcc/i386/local.c
+++ b/usr.bin/pcc/i386/local.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local.c,v 1.4 2007/11/18 17:39:55 ragge Exp $ */
+/* $OpenBSD: local.c,v 1.5 2007/12/09 18:54:39 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -72,7 +72,7 @@ picsymtab(char *s, char *s2)
strlcpy(sp->sname, s, len);
strlcat(sp->sname, s2, len);
sp->sclass = EXTERN;
- sp->slevel = 0;
+ sp->sflags = sp->slevel = 0;
return sp;
}
@@ -87,10 +87,11 @@ picext(NODE *p)
q = tempnode(gotnr, PTR|VOID, 0, MKSUE(VOID));
r = bcon(0);
- r->n_sp = picsymtab(p->n_sp->sname, "@GOT");
+ r->n_sp = picsymtab(gcc_findname(p->n_sp), "@GOT");
q = buildtree(PLUS, q, r);
q = block(UMUL, q, 0, PTR|VOID, 0, MKSUE(VOID));
q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue);
+ q->n_sp = p->n_sp; /* for init */
nfree(p);
return q;
}
@@ -105,14 +106,17 @@ picstatic(NODE *p)
q = tempnode(gotnr, PTR|VOID, 0, MKSUE(VOID));
r = bcon(0);
- if (p->n_sp->slevel > 0) {
+ if (p->n_sp->slevel > 0 || p->n_sp->sclass == ILABEL) {
char buf[32];
snprintf(buf, 32, LABFMT, (int)p->n_sp->soffset);
r->n_sp = picsymtab(buf, "@GOTOFF");
} else
- r->n_sp = picsymtab(p->n_sp->sname, "@GOTOFF");
+ r->n_sp = picsymtab(gcc_findname(p->n_sp), "@GOTOFF");
+ r->n_sp->sclass = STATIC;
+ r->n_sp->stype = p->n_sp->stype;
q = buildtree(PLUS, q, r);
q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue);
+ q->n_sp = p->n_sp; /* for init */
nfree(p);
return q;
}
@@ -161,12 +165,16 @@ clocal(NODE *p)
p = stref(block(STREF, r, p, 0, 0, 0));
break;
+ case USTATIC:
+ if (kflag == 0)
+ break;
+ /* FALLTHROUGH */
case STATIC:
if (kflag == 0) {
if (q->slevel == 0)
break;
p->n_lval = 0;
- } else
+ } else if (blevel > 0)
p = picstatic(p);
break;
@@ -180,14 +188,35 @@ clocal(NODE *p)
case EXTDEF:
if (kflag == 0)
break;
- if ((p->n_type & TMASK2) == FTN) {
- p->n_sp = picsymtab(q->sname, "@PLT");
- } else
+ if (blevel > 0)
p = picext(p);
break;
+
+ case ILABEL:
+ if (kflag && blevel)
+ p = picstatic(p);
+ break;
}
break;
+ case ADDROF:
+ if (kflag == 0 || blevel == 0)
+ break;
+ /* char arrays may end up here */
+ l = p->n_left;
+ if (l->n_op != NAME ||
+ (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE))
+ break;
+ l = p;
+ p = picstatic(p->n_left);
+ nfree(l);
+ if (p->n_op != UMUL)
+ cerror("ADDROF error");
+ l = p;
+ p = p->n_left;
+ nfree(l);
+ break;
+
case UCALL:
case USTCALL:
if (kflag == 0)
@@ -199,7 +228,7 @@ clocal(NODE *p)
tempnode(gotnr, INT, 0, MKSUE(INT)));
p->n_op -= (UCALL-CALL);
break;
-
+
case CBRANCH:
l = p->n_left;
@@ -414,16 +443,66 @@ clocal(NODE *p)
return(p);
}
+/*
+ * Change CALL references to either direct (static) or PLT.
+ */
+static void
+fixnames(NODE *p)
+{
+ struct symtab *sp;
+ struct suedef *sue;
+ NODE *q;
+ char *c;
+ int isu;
+
+ if ((cdope(p->n_op) & CALLFLG) == 0)
+ return;
+ isu = 0;
+ q = p->n_left;
+ sue = q->n_sue;
+ if (q->n_op == UMUL)
+ q = q->n_left, isu = 1;
+ if (q->n_op == PLUS && q->n_left->n_op == TEMP &&
+ q->n_right->n_op == ICON) {
+ sp = q->n_right->n_sp;
+
+ if (sp == NULL)
+ return; /* nothing to do */
+ if (sp->sclass == STATIC && !ISFTN(sp->stype))
+ return; /* function pointer */
+
+ if (sp->sclass != STATIC && sp->sclass != EXTERN &&
+ sp->sclass != EXTDEF)
+ cerror("fixnames");
+
+ if ((c = strstr(sp->sname, "@GOT")) == NULL)
+ cerror("fixnames2");
+ if (isu) {
+ memcpy(c, "@PLT", sizeof("@PLT"));
+ } else
+ *c = 0;
+ nfree(q->n_left);
+ q = q->n_right;
+ if (isu)
+ nfree(p->n_left->n_left);
+ nfree(p->n_left);
+ p->n_left = q;
+ q->n_sue = sue;
+ }
+}
+
void
myp2tree(NODE *p)
{
+ if (kflag)
+ walkf(p, fixnames);
}
/*ARGSUSED*/
int
andable(NODE *p)
{
- return(1); /* all names can have & taken on them */
+ return(1); /* all names can have & taken on them */
}
/*
@@ -614,6 +693,7 @@ ninval(CONSZ off, int fsz, NODE *p)
{
union { float f; double d; long double l; int i[3]; } u;
struct symtab *q;
+ char *c;
TWORD t;
int i;
@@ -621,6 +701,20 @@ ninval(CONSZ off, int fsz, NODE *p)
if (t > BTMASK)
t = INT; /* pointer */
+ while (p->n_op == SCONV || p->n_op == PCONV) {
+ NODE *l = p->n_left;
+ l->n_type = p->n_type;
+ p = l;
+ }
+
+ if (kflag && (p->n_op == PLUS || p->n_op == UMUL)) {
+ if (p->n_op == UMUL)
+ p = p->n_left;
+ p = p->n_right;
+ q = p->n_sp;
+ if ((c = strstr(q->sname, "@GOT")) != NULL)
+ *c = 0; /* ignore GOT ref here */
+ }
if (p->n_op != ICON && p->n_op != FCON)
cerror("ninval: init node not constant");
diff --git a/usr.bin/pcc/i386/local2.c b/usr.bin/pcc/i386/local2.c
index c02cd4904a3..4c8b0637fef 100644
--- a/usr.bin/pcc/i386/local2.c
+++ b/usr.bin/pcc/i386/local2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local2.c,v 1.4 2007/11/16 09:00:12 otto Exp $ */
+/* $OpenBSD: local2.c,v 1.5 2007/12/09 18:54:39 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -64,6 +64,28 @@ prtprolog(struct interpass_prolog *ipp, int addto)
rnames[j], regoff[j], rnames[FPREG]);
if (kflag == 0)
return;
+ /* if ebx are not saved to stack, it must be moved into another reg */
+ /* check and emit the move before GOT stuff */
+ if ((ipp->ipp_regs & (1 << EBX)) == 0) {
+ struct interpass *ip = (struct interpass *)ipp;
+
+ ip = DLIST_PREV(ip, qelem);
+ ip = DLIST_PREV(ip, qelem);
+ ip = DLIST_PREV(ip, qelem);
+ if (ip->type != IP_NODE || ip->ip_node->n_op != ASSIGN ||
+ ip->ip_node->n_left->n_op != REG)
+ comperr("prtprolog pic error");
+ ip = (struct interpass *)ipp;
+ ip = DLIST_NEXT(ip, qelem);
+ if (ip->type != IP_NODE || ip->ip_node->n_op != ASSIGN ||
+ ip->ip_node->n_left->n_op != REG)
+ comperr("prtprolog pic error2");
+ printf(" movl %s,%s\n",
+ rnames[ip->ip_node->n_right->n_rval],
+ rnames[ip->ip_node->n_left->n_rval]);
+ tfree(ip->ip_node);
+ DLIST_REMOVE(ip, qelem);
+ }
printf(" call .LW%d\n", ++lwnr);
printf(".LW%d:\n", lwnr);
printf(" popl %%ebx\n");
@@ -728,6 +750,18 @@ adrput(FILE *io, NODE *p)
fprintf(io, "(%s)", rnames[p->n_rval]);
return;
case ICON:
+#ifdef PCC_DEBUG
+ /* Sanitycheck for PIC, to catch adressable constants */
+ if (kflag && p->n_name[0]) {
+ static int foo;
+
+ if (foo++ == 0) {
+ printf("\nfailing...\n");
+ fwalk(p, e2print, 0);
+ comperr("pass2 conput");
+ }
+ }
+#endif
/* addressable value of the constant */
fputc('$', io);
conput(io, p);
@@ -1028,6 +1062,8 @@ lastcall(NODE *p)
for (p = p->n_right; p->n_op == CM; p = p->n_left)
size += argsiz(p->n_right);
size += argsiz(p);
+ if (kflag)
+ size -= 4;
op->n_qual = size; /* XXX */
}
@@ -1064,3 +1100,11 @@ special(NODE *p, int shape)
}
return SRNOPE;
}
+
+/*
+ * Target-dependent command-line options.
+ */
+void
+mflags(char *str)
+{
+}
diff --git a/usr.bin/pcc/i386/table.c b/usr.bin/pcc/i386/table.c
index cad725ad629..7f27036bb03 100644
--- a/usr.bin/pcc/i386/table.c
+++ b/usr.bin/pcc/i386/table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: table.c,v 1.2 2007/10/23 14:48:36 ragge Exp $ */
+/* $OpenBSD: table.c,v 1.3 2007/12/09 18:54:39 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -389,13 +389,13 @@ struct optab table[] = {
{ CALL, INAREG,
SCON, TANY,
- SAREG, TWORD|TPOINT,
+ SAREG, TSHORT|TUSHORT|TWORD|TPOINT,
NAREG|NASL, RESC1, /* should be 0 */
" call CL\nZC", },
{ UCALL, INAREG,
SCON, TANY,
- SAREG, TWORD|TPOINT,
+ SAREG, TSHORT|TUSHORT|TWORD|TPOINT,
NAREG|NASL, RESC1, /* should be 0 */
" call CL\n", },