diff options
author | Anders Magnusson <ragge@cvs.openbsd.org> | 2007-12-09 18:54:40 +0000 |
---|---|---|
committer | Anders Magnusson <ragge@cvs.openbsd.org> | 2007-12-09 18:54:40 +0000 |
commit | d0ef6a00182cf3073f66ef501893e6b93016bee2 (patch) | |
tree | 4ca736e43fc2a37e940d93ed073f8066420b6e40 /usr.bin/pcc/i386 | |
parent | eb5cd1326c57b80460c264cca6fde959e0ec9766 (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.c | 14 | ||||
-rw-r--r-- | usr.bin/pcc/i386/local.c | 116 | ||||
-rw-r--r-- | usr.bin/pcc/i386/local2.c | 46 | ||||
-rw-r--r-- | usr.bin/pcc/i386/table.c | 6 |
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", }, |