diff options
38 files changed, 3133 insertions, 820 deletions
diff --git a/usr.bin/pcc/cc/Makefile b/usr.bin/pcc/cc/Makefile index a2e7d4fe0fd..1dbca15d34f 100644 --- a/usr.bin/pcc/cc/Makefile +++ b/usr.bin/pcc/cc/Makefile @@ -1,15 +1,18 @@ -# $OpenBSD: Makefile,v 1.5 2007/10/22 13:40:08 otto Exp $ +# $OpenBSD: Makefile,v 1.6 2008/08/17 18:40:12 ragge Exp $ # # Makefile for the cc part of pcc. # -PROG= cc +PROG= pcc +SRCS= cc.c +MAN= cc.1 PREFIX= /usr/local BINDIR= ${PREFIX}/bin MANDIR= ${PREFIX}/man/man TARGOS= openbsd TARGMACH= ${MACHINE_ARCH} +#LINKS= ${PREFIX}/bin/pcc ${PREFIX}/bin/cc -CFLAGS+= -DLIBEXECDIR=\"${PREFIX}/libexec\" +CFLAGS+= -DLIBEXECDIR=\"${PREFIX}/libexec/\" CPPFLAGS+= -I${.CURDIR}/.. CPPFLAGS+= -DDEFMACH=\"${TARGMACH}\" diff --git a/usr.bin/pcc/cc/cc.1 b/usr.bin/pcc/cc/cc.1 index 75841c134a2..d37ce5c3748 100644 --- a/usr.bin/pcc/cc/cc.1 +++ b/usr.bin/pcc/cc/cc.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: cc.1,v 1.4 2008/04/11 20:45:52 stefan Exp $ +.\" $OpenBSD: cc.1,v 1.5 2008/08/17 18:40:12 ragge Exp $ .\" .\" Copyright (c) 2007 Jeremy C. Reed <reed@reedmedia.net> .\" @@ -55,22 +55,29 @@ Unrecognized options are all sent directly to Filenames that end with .Sy \&.c are passed via -.Xr cpp 1 -\*[Gt] -.Xr ccom 1 -\*[Gt] -.Xr as 1 -\*[Gt] +.Xr cpp 1 -\*(Gt +.Xr ccom 1 -\*(Gt +.Xr as 1 -\*(Gt .Xr ld 1 . .Pp Filenames that end with .Sy \&.i are passed via -.Xr ccom 1 -\*[Gt] -.Xr as 1 -\*[Gt] +.Xr ccom 1 -\*(Gt +.Xr as 1 -\*(Gt .Xr ld 1 . .Pp Filenames that end with .Sy \&.s are passed via -.Xr as 1 -\*[Gt] +.Xr as 1 -\*(Gt +.Xr ld 1 . +.Pp +Filenames that end with +.Sy \&.S +are passed via +.Xr cpp 1 -\*(Gt +.Xr as 1 -\*(Gt .Xr ld 1 . .Pp Filenames that end with @@ -238,6 +245,9 @@ if multiple files are given. Do not use dynamic linkage. By default, it will link using the dynamic linker options and/or shared objects for the platform. +.It Fl shared +Create a shared object of the result. Tells the linker not to +generate an executable. .It Fl t Passes .Fl t @@ -258,7 +268,12 @@ Options for the linker. .It Fl X Don't remove temporary files on exit. .It Fl x -TODO +May be used to give separate optimization flags to ccom, see +.Fl O +for options. +.It Fl x Ar c +Gcc compatibility option; specify that the language in use is +.Ar c . .El .Ss Predefined Macros A few diff --git a/usr.bin/pcc/cc/cc.c b/usr.bin/pcc/cc/cc.c index 23cf8beb7a8..0bbe81d23f5 100644 --- a/usr.bin/pcc/cc/cc.c +++ b/usr.bin/pcc/cc/cc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cc.c,v 1.13 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: cc.c,v 1.14 2008/08/17 18:40:12 ragge Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -61,8 +61,17 @@ #include <string.h> #include <unistd.h> +#ifdef WIN32 +#include <windows.h> +#include <process.h> +#include <io.h> +#endif + #include "../config.h" #include "ccconfig.h" + +#define MULTITARGET + /* C command */ #define MKS(x) _MKS(x) @@ -71,7 +80,39 @@ /* * Many specific definitions, should be declared elsewhere. */ -#define STDINC "/usr/include" + +#ifndef STDINC +#define STDINC "/usr/include/" +#endif + +#ifndef LIBDIR +#define LIBDIR "/usr/lib/" +#endif + +#ifndef PREPROCESSOR +#define PREPROCESSOR "cpp" +#endif + +#ifndef COMPILER +#define COMPILER "ccom"; +#endif + +#ifndef ASSEMBLER +#define ASSEMBLER "as" +#endif + +#ifndef LINKER +#define LINKER "ld" +#endif + +#define OS MKS(TARGOS) +#define MACH MKS(TARGMACH) +#ifndef PCCINCDIR +#define PCCINCDIR LIBDIR "pcc/" MACH "-" OS "/" PACKAGE_VERSION "/include" +#endif +#ifndef PCCLIBDIR +#define PCCLIBDIR LIBDIR "pcc/" MACH "-" OS "/" PACKAGE_VERSION "/lib" +#endif #define MAXFIL 10000 #define MAXLIB 10000 @@ -80,7 +121,8 @@ char *tmp3; char *tmp4; char *outfile; -char *copy(char *),*setsuf(char *, char); +char *Bprefix(char *); +char *copy(char *, int),*setsuf(char *, char); int getsuf(char *); int main(int, char *[]); void error(char *, ...); @@ -89,16 +131,23 @@ int callsys(char [], char *[]); int cunlink(char *); void dexit(int); void idexit(int); -char *gettmp(); +char *gettmp(void); +void *ccmalloc(int size); char *av[MAXAV]; char *clist[MAXFIL]; char *llist[MAXLIB]; +char *aslist[MAXAV]; char alist[20]; char *xlist[100]; int xnum; char *mlist[100]; +char *flist[100]; +char *wlist[100]; char *idirafter; int nm; +int nf; +int nw; +int sspflag; int Cflag; int dflag; int pflag; @@ -117,21 +166,43 @@ int Mflag; /* dependencies only */ int pgflag; int exfail; int Xflag; -int Werror; -int nostartfiles, Bstatic; +int Wallflag; +int Wflag; +int nostartfiles, Bstatic, shared; int nostdinc, nostdlib; int onlyas; int pthreads; +int xcflag; +int ascpp; -char *pass0; -char *passp = LIBEXECDIR "/cpp"; +char *passp = LIBEXECDIR PREPROCESSOR; +char *pass0 = LIBEXECDIR COMPILER; +char *as = ASSEMBLER; +char *ld = LINKER; char *Bflag; char *cppadd[] = CPPADD; +#ifdef DYNLINKER char *dynlinker[] = DYNLINKER; +#endif +#ifdef CRT0FILE char *crt0file = CRT0FILE; +#endif +#ifdef CRT0FILE_PROFILE char *crt0file_profile = CRT0FILE_PROFILE; +#endif +#ifdef STARTFILES char *startfiles[] = STARTFILES; char *endfiles[] = ENDFILES; +#endif +#ifdef STARTFILES_T +char *startfiles_T[] = STARTFILES_T; +char *endfiles_T[] = ENDFILES_T; +#endif +#ifdef STARTFILES_S +char *startfiles_S[] = STARTFILES_S; +char *endfiles_S[] = ENDFILES_S; +#endif +#ifdef MULTITARGET char *mach = DEFMACH; struct cppmd { char *mach; @@ -139,6 +210,9 @@ struct cppmd { }; struct cppmd cppmds[] = CPPMDADDS; +#else +char *cppmdadd[] = CPPMDADD; +#endif #ifdef LIBCLIBS char *libclibs[] = LIBCLIBS; #else @@ -152,16 +226,45 @@ char *libclibs_profile[] = { "-lc_p", NULL }; #ifndef STARTLABEL #define STARTLABEL "__start" #endif +char *incdir = STDINC; +char *libdir = PCCLIBDIR; + +/* handle gcc warning emulations */ +struct Wflags { + char *name; + int flags; +#define INWALL 1 +#define NEGATIVE 2 +} Wflags[] = { + { "-Werror", 0 }, + { "-Wshadow", 0 }, + { "-Wno-shadow", NEGATIVE }, + { "-Wpointer-sign", INWALL }, + { "-Wno-pointer-sign", NEGATIVE }, + { "-Wsign-compare", 0 }, + { "-Wno-sign-compare", NEGATIVE }, + { "-Wunknown-pragmas", INWALL }, + { "-Wno-unknown-pragmas", NEGATIVE }, + { "-Wunreachable-code", 0 }, + { "-Wno-unreachable-code", NEGATIVE }, + { 0, 0 }, +}; + +#define SZWFL (sizeof(Wflags)/sizeof(Wflags[0])) int main(int argc, char *argv[]) { + struct Wflags *Wf; char *t, *u; char *assource; char **pv, *ptemp[MAXOPT], **pvt; - int nc, nl, i, j, k, c, nxo, na; + int nc, nl, nas, i, j, c, nxo, na; +#ifdef MULTITARGET + int k; +#endif - i = nc = nl = nxo = 0; + i = nc = nl = nas = nxo = 0; pv = ptemp; while(++i < argc) { if (argv[i][0] == '-') { @@ -174,10 +277,20 @@ main(int argc, char *argv[]) break; #endif + case '-': /* double -'s */ + if (strcmp(argv[i], "--version") == 0) + printf("%s\n", VERSSTR); + else if (strcmp(argv[i], "--param") == 0) + /* NOTHING YET */; + else + error("unrecognized option %s", argv[i]); + break; + case 'B': /* other search paths for binaries */ Bflag = &argv[i][2]; break; - + +#ifdef MULTITARGET case 'b': t = &argv[i][2]; if (*t == '\0' && i + 1 < argc) { @@ -200,14 +313,13 @@ main(int argc, char *argv[]) if (cppmds[j].mach == NULL) errorx(1, "unknown target arch %s", t); break; - +#endif + case 'X': Xflag++; break; case 'W': /* Ignore (most of) W-flags */ - if (strncmp(argv[i], "-Werror", 7) == 0) { - Werror = 1; - } else if (strncmp(argv[i], "-Wl,", 4) == 0) { + if (strncmp(argv[i], "-Wl,", 4) == 0) { /* options to the linker */ t = &argv[i][4]; while ((u = strchr(t, ','))) { @@ -216,18 +328,67 @@ main(int argc, char *argv[]) t = u; } llist[nl++] = t; + } else if (strncmp(argv[i], "-Wa,", 4) == 0) { + /* options to the assembler */ + t = &argv[i][4]; + while ((u = strchr(t, ','))) { + *u++ = 0; + aslist[nas++] = t; + t = u; + } + aslist[nas++] = t; } else if (strncmp(argv[i], "-Wp,", 4) == 0) { /* preprocessor */ if (!strncmp(argv[i], "-Wp,-C", 6)) Cflag++; + } else if (strcmp(argv[i], "-Wall") == 0) { + Wallflag = 1; + } else if (strcmp(argv[i], "-WW") == 0) { + Wflag = 1; + } else { + /* check and set if available */ + for (Wf = Wflags; Wf->name; Wf++) { + if (strcmp(argv[i], Wf->name)) + continue; + wlist[nw++] = Wf->name; + } } break; case 'f': /* GCC compatibility flags */ if (strcmp(argv[i], "-fPIC") == 0) kflag = F_PIC; - if (strcmp(argv[i], "-fpic") == 0) + else if (strcmp(argv[i], "-fpic") == 0) kflag = F_pic; + else if (strcmp(argv[i], + "-fsigned-char") == 0) + flist[nf++] = argv[i]; + else if (strcmp(argv[i], + "-fno-signed-char") == 0) + flist[nf++] = argv[i]; + else if (strcmp(argv[i], + "-funsigned-char") == 0) + flist[nf++] = argv[i]; + else if (strcmp(argv[i], + "-fno-unsigned-char") == 0) + flist[nf++] = argv[i]; + else if (strcmp(argv[i], + "-fstack-protector") == 0) { + flist[nf++] = argv[i]; + sspflag++; + } else if (strcmp(argv[i], + "-fstack-protector-all") == 0) { + flist[nf++] = argv[i]; + sspflag++; + } else if (strcmp(argv[i], + "-fno-stack-protector") == 0) { + flist[nf++] = argv[i]; + sspflag = 0; + } else if (strcmp(argv[i], + "-fno-stack-protector-all") == 0) { + flist[nf++] = argv[i]; + sspflag = 0; + } /* silently ignore the rest */ break; @@ -269,7 +430,8 @@ main(int argc, char *argv[]) break; case 'p': - if (strcmp(argv[i], "-pg") == 0) + if (strcmp(argv[i], "-pg") == 0 || + strcmp(argv[i], "-p") == 0) pgflag++; else if (strcmp(argv[i], "-pthread") == 0) pthreads++; @@ -284,10 +446,12 @@ main(int argc, char *argv[]) if (*t == 0) t = argv[++i]; if (strcmp(t, "c") == 0) - ; /* default */ + xcflag = 1; /* default */ + else if (strcmp(t, "assembler-with-cpp") == 0) + ascpp = 1; #ifdef notyet - else if (strcmp(t, "c++")) - cxxflag; + else if (strcmp(t, "c++") == 0) + cxxflag++; #endif else xlist[xnum++] = argv[i]; @@ -305,7 +469,10 @@ main(int argc, char *argv[]) outfile = argv[++i]; break; case 'O': - Oflag++; + if (argv[i][2] == '0') + Oflag = 0; + else + Oflag++; break; case 'E': Eflag++; @@ -357,7 +524,14 @@ main(int argc, char *argv[]) case 's': if (strcmp(argv[i], "-static") == 0) Bstatic = 1; - else + else if (strcmp(argv[i], "-shared") == 0) { + shared = 1; +#ifndef os_win32 + nostdlib = 1; +#endif + } else if (strncmp(argv[i], "-std", 4) == 0) { + /* ignore gcc -std= */; + } else goto passa; break; } @@ -367,7 +541,7 @@ main(int argc, char *argv[]) if (*argv[i] == '-' && argv[i][1] == 'L') ; else if((c=getsuf(t))=='c' || c=='S' || c=='i' || - c=='s'|| Eflag) { + c=='s'|| Eflag || xcflag) { clist[nc++] = t; if (nc>=MAXFIL) { error("Too many source files"); @@ -411,11 +585,17 @@ main(int argc, char *argv[]) tmp3 = gettmp(); tmp4 = gettmp(); } + if (Bflag) { + incdir = Bflag; + libdir = Bflag; + } if (signal(SIGINT, SIG_IGN) != SIG_IGN) /* interrupt */ signal(SIGINT, idexit); if (signal(SIGTERM, SIG_IGN) != SIG_IGN) /* terminate */ signal(SIGTERM, idexit); +#ifdef MULTITARGET asprintf(&pass0, "%s%s%s", LIBEXECDIR, "/ccom_", mach); +#endif pvt = pv; for (i=0; i<nc; i++) { /* @@ -425,15 +605,18 @@ main(int argc, char *argv[]) printf("%s:\n", clist[i]); onlyas = 0; assource = tmp3; + if (getsuf(clist[i])=='S') + ascpp = 1; if (getsuf(clist[i])=='i') { if(Eflag) continue; goto com; + } else if (ascpp) { + onlyas = 1; } else if (getsuf(clist[i])=='s') { assource = clist[i]; goto assemble; - } else if (getsuf(clist[i])=='S') - onlyas = 1; + } if (pflag) tmp4 = setsuf(clist[i], 'i'); na = 0; @@ -443,8 +626,10 @@ main(int argc, char *argv[]) av[na++] = "-D__PCC__=" MKS(PCC_MAJOR); av[na++] = "-D__PCC_MINOR__=" MKS(PCC_MINOR); av[na++] = "-D__PCC_MINORMINOR__=" MKS(PCC_MINORMINOR); - if (getsuf(clist[i])=='S') + if (ascpp) av[na++] = "-D__ASSEMBLER__"; + if (sspflag) + av[na++] = "-D__SSP__=1"; if (pthreads) av[na++] = "-D_PTHREADS"; if (Cflag) @@ -455,6 +640,7 @@ main(int argc, char *argv[]) av[na++] = alist; for (j = 0; cppadd[j]; j++) av[na++] = cppadd[j]; +#ifdef MULTITARGET for (k = 0; cppmds[k].mach; k++) { if (strcmp(cppmds[k].mach, mach) != 0) continue; @@ -462,12 +648,17 @@ main(int argc, char *argv[]) av[na++] = cppmds[k].cppmdadd[j]; break; } +#else + for (j = 0; cppmdadd[j]; j++) + av[na++] = cppmdadd[j]; +#endif if (tflag) av[na++] = "-t"; for(pv=ptemp; pv <pvt; pv++) av[na++] = *pv; if (!nostdinc) - av[na++] = "-S", av[na++] = STDINC; + av[na++] = "-S", av[na++] = incdir; + av[na++] = "-I", av[na++] = PCCINCDIR; if (idirafter) { av[na++] = "-I"; av[na++] = idirafter; @@ -493,16 +684,40 @@ main(int argc, char *argv[]) com: na = 0; av[na++]= "ccom"; + if (Wallflag) { + /* Set only the same flags as gcc */ + for (Wf = Wflags; Wf->name; Wf++) { + if (Wf->flags != INWALL) + continue; + av[na++] = Wf->name; + } + } + if (Wflag) { + /* set all positive flags */ + for (Wf = Wflags; Wf->name; Wf++) { + if (Wf->flags == NEGATIVE) + continue; + av[na++] = Wf->name; + } + } + for (j = 0; j < nw; j++) + av[na++] = wlist[j]; + for (j = 0; j < nf; j++) + av[na++] = flist[j]; if (vflag) av[na++] = "-v"; if (pgflag) av[na++] = "-p"; if (gflag) av[na++] = "-g"; +#ifdef os_darwin + /* darwin always wants PIC compilation */ + if (!Bstatic) + av[na++] = "-k"; +#else if (kflag) av[na++] = "-k"; - if (Werror) - av[na++] = "-Werror"; +#endif if (Oflag) { av[na++] = "-xtemps"; av[na++] = "-xdeljumps"; @@ -548,7 +763,16 @@ main(int argc, char *argv[]) */ assemble: na = 0; - av[na++] = "as"; + av[na++] = as; + for (j = 0; j < nas; j++) + av[na++] = aslist[j]; +#if defined(os_sunos) && defined(mach_sparc64) + av[na++] = "-m64"; +#endif +#if defined(os_darwin) + if (Bstatic) + av[na++] = "-static"; +#endif if (vflag) av[na++] = "-v"; if (kflag) @@ -562,7 +786,7 @@ main(int argc, char *argv[]) if (dflag) av[na++] = alist; av[na++] = 0; - if (callsys("/bin/as", av)) { + if (callsys(as, av)) { cflag++; eflag++; cunlink(tmp4); @@ -580,27 +804,85 @@ main(int argc, char *argv[]) nocom: if (cflag==0 && nl!=0) { j = 0; - av[j++] = "ld"; + av[j++] = ld; +#ifndef MSLINKER if (vflag) av[j++] = "-v"; +#endif +#if !defined(os_sunos) && !defined(os_win32) av[j++] = "-X"; - av[j++] = "-d"; - av[j++] = "-e"; - av[j++] = STARTLABEL; - if (Bstatic == 0) { /* Dynamic linkage */ - for (i = 0; dynlinker[i]; i++) - av[j++] = dynlinker[i]; - } else - av[j++] = "-Bstatic"; +#endif + if (shared) { + av[j++] = "-shared"; +#ifdef os_win32 + av[j++] = "-Bdynamic"; +#endif +#ifndef os_sunos + } else { +#ifndef os_win32 +#ifndef os_darwin + av[j++] = "-d"; +#endif + av[j++] = "-e"; + av[j++] = STARTLABEL; +#endif +#endif + if (Bstatic == 0) { /* Dynamic linkage */ +#ifdef DYNLINKER + for (i = 0; dynlinker[i]; i++) + av[j++] = dynlinker[i]; +#endif + } else { +#ifdef os_darwin + av[j++] = "-static"; +#else + av[j++] = "-Bstatic"; +#endif + } + } if (outfile) { +#ifdef MSLINKER + char *s = copy("/OUT:", strlen(outfile)); + strcat(s, outfile); + av[j++] = s; +#else av[j++] = "-o"; av[j++] = outfile; +#endif } - if (!nostartfiles) { - av[j++] = crt0file; - av[j++] = pgflag ? crt0file_profile : crt0file; - for (i = 0; startfiles[i]; i++) - av[j++] = startfiles[i]; +#ifdef STARTFILES_S + if (shared) { + if (!nostartfiles) { + for (i = 0; startfiles_S[i]; i++) + av[j++] = Bprefix(startfiles_S[i]); + } + } else +#endif + { + if (!nostartfiles) { +#ifdef CRT0FILE_PROFILE + if (pgflag) { + av[j++] = Bprefix(crt0file_profile); + } else +#endif + { +#ifdef CRT0FILE + av[j++] = Bprefix(crt0file); +#endif + } +#ifdef STARTFILES_T + if (Bstatic) { + for (i = 0; startfiles_T[i]; i++) + av[j++] = Bprefix(listartfiles_T[i]); + } else +#endif + { +#ifdef STARTFILES + for (i = 0; startfiles[i]; i++) + av[j++] = Bprefix(startfiles[i]); +#endif + } + } } i = 0; while(i<nl) { @@ -608,8 +890,11 @@ nocom: if (j >= MAXAV) error("Too many ld options"); } +#ifndef MACHOABI + /* darwin assembler doesn't want -g */ if (gflag) av[j++] = "-g"; +#endif #if 0 if (gflag) av[j++] = "-lg"; @@ -617,22 +902,45 @@ nocom: if (pthreads) av[j++] = "-lpthread"; if (!nostdlib) { +#ifdef MSLINKER + char *s = copy("/LIBPATH:", strlen(libdir)); +#else + char *s = copy("-L", strlen(libdir)); +#endif + strcat(s, libdir); + av[j++] = s; if (pgflag) { for (i = 0; libclibs_profile[i]; i++) - av[j++] = libclibs_profile[i]; + av[j++] = Bprefix(libclibs_profile[i]); } else { for (i = 0; libclibs[i]; i++) - av[j++] = libclibs[i]; + av[j++] = Bprefix(libclibs[i]); } - for (i = 0; libclibs[i]; i++) - av[j++] = libclibs[i]; } if (!nostartfiles) { - for (i = 0; endfiles[i]; i++) - av[j++] = endfiles[i]; +#ifdef STARTFILES_S + if (shared) { + for (i = 0; endfiles_S[i]; i++) + av[j++] = Bprefix(endfiles_S[i]); + } else +#endif + { +#ifdef STARTFILES_T + if (Bstatic) { + for (i = 0; endfiles_T[i]; i++) + av[j++] = Bprefix(endfiles_T[i]); + } else +#endif + { +#ifdef STARTFILES + for (i = 0; endfiles[i]; i++) + av[j++] = Bprefix(endfiles[i]); +#endif + } + } } av[j++] = 0; - eflag |= callsys("/bin/ld", av); + eflag |= callsys(ld, av); if (nc==1 && nxo==1 && eflag==0) cunlink(setsuf(clist[0], 'o')); else if (nc > 0 && eflag == 0) { @@ -707,13 +1015,31 @@ errorx(int eval, char *s, ...) dexit(eval); } +char * +Bprefix(char *s) +{ + char *suffix; + char *str; + + if (Bflag == NULL || s[0] != '/') + return s; + + suffix = strrchr(s, '/'); + if (suffix == NULL) + suffix = s; + + str = copy(Bflag, strlen(suffix)); + strcat(str, suffix); + return str; +} + int -getsuf(char *as) +getsuf(char *s) { - register char *s; + register char *p; - if ((s = strrchr(as, '.')) && s[1] != '\0' && s[2] == '\0') - return s[1]; + if ((p = strrchr(s, '.')) && p[1] != '\0' && p[2] == '\0') + return p[1]; return(0); } @@ -723,13 +1049,69 @@ getsuf(char *as) char * setsuf(char *s, char ch) { - s = copy(basename(s)); - s[strlen(s) - 1] = ch; + char *p; + + s = copy(basename(s), 2); + if ((p = strrchr(s, '.')) == NULL) { + p = s + strlen(s); + p[0] = '.'; + } + p[1] = ch; + p[2] = '\0'; return(s); } +#ifdef WIN32 +int +callsys(char *f, char *v[]) +{ + char *s; + int t, status = 0; + char cmd[MAX_PATH]; + int len; + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD exitCode; + BOOL ok; + + len = strlcpy(cmd, f, MAX_PATH); + for (t = 1; v[t] && len < MAX_PATH; t++) { + len = strlcat(cmd, " ", MAX_PATH); + len = strlcat(cmd, v[t], MAX_PATH); + } + + if (vflag) + printf("%s\n", cmd); + + ZeroMemory(&si, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); + + ok = CreateProcess(NULL, // the executable program + cmd, // the command line arguments + NULL, // ignored + NULL, // ignored + TRUE, // inherit handles + HIGH_PRIORITY_CLASS, + NULL, // ignored + NULL, // ignored + &si, + &pi); + + if (!ok) { + printf("Try Again\n"); + return 100; + } + + WaitForSingleObject(pi.hProcess, INFINITE); + GetExitCodeProcess(pi.hProcess, &exitCode); + return (exitCode != 0); +} + +#else + int -callsys(char f[], char *v[]) +callsys(char *f, char *v[]) { int t, status = 0; pid_t p; @@ -756,7 +1138,7 @@ callsys(char f[], char *v[]) execv(a, v); } } - execv(f, v); + execvp(f, v); if ((s = strrchr(f, '/'))) execvp(s+1, v); fprintf(stderr, "Can't find %s\n", f); @@ -772,19 +1154,25 @@ callsys(char f[], char *v[]) if (WIFEXITED(status)) return (WEXITSTATUS(status)); if (WIFSIGNALED(status)) - dexit(eflag); + dexit(eflag ? eflag : 1); errorx(8, "Fatal error in %s", f); + + return 0; } +#endif +/* + * Make a copy of string as, mallocing extra bytes in the string. + */ char * -copy(char *as) +copy(char *s, int extra) { - char *p; - - if ((p = strdup(as)) == NULL) - errorx(8, "no space for file names"); + int len = strlen(s)+1; + char *rv; - return p; + rv = ccmalloc(len+extra); + strlcpy(rv, s, len); + return rv; } int @@ -792,13 +1180,38 @@ cunlink(char *f) { if (f==0 || Xflag) return(0); - return(unlink(f)); + return (unlink(f)); } +#ifdef WIN32 char * gettmp(void) { - char *sfn = copy("/tmp/ctm.XXXXXX"); +#define BUFFSIZE 1000 + DWORD pathSize; + char pathBuffer[BUFFSIZE]; + char tempFilename[MAX_PATH]; + UINT uniqueNum; + + pathSize = GetTempPath(BUFFSIZE, pathBuffer); + if (pathSize < BUFFSIZE) + pathBuffer[pathSize] = 0; + else + pathBuffer[0] = 0; + uniqueNum = GetTempFileName(pathBuffer, "ctm", 0, tempFilename); + if (uniqueNum == 0) { + fprintf(stderr, "%s:\n", pathBuffer); + exit(8); + } + return copy(tempFilename, 0); +} + +#else + +char * +gettmp(void) +{ + char *sfn = copy("/tmp/ctm.XXXXXX", 0); int fd = -1; if ((fd = mkstemp(sfn)) == -1) { @@ -806,6 +1219,16 @@ gettmp(void) exit(8); } close(fd); - return sfn; } +#endif + +void * +ccmalloc(int size) +{ + void *rv; + + if ((rv = malloc(size)) == NULL) + error("malloc failed"); + return rv; +} diff --git a/usr.bin/pcc/ccconfig.h b/usr.bin/pcc/ccconfig.h index c7fe0569ba6..45cda23866f 100644 --- a/usr.bin/pcc/ccconfig.h +++ b/usr.bin/pcc/ccconfig.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ccconfig.h,v 1.4 2008/04/11 20:45:51 stefan Exp $ */ +/* $OpenBSD: ccconfig.h,v 1.5 2008/08/17 18:40:12 ragge Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). @@ -64,4 +64,5 @@ } #define MAXCPPMDARGS 8 +#define ELFABI #define STABS diff --git a/usr.bin/pcc/ccom/cgram.y b/usr.bin/pcc/ccom/cgram.y index 2af2844b3aa..9d9d03b7130 100644 --- a/usr.bin/pcc/ccom/cgram.y +++ b/usr.bin/pcc/ccom/cgram.y @@ -1,4 +1,4 @@ -/* $OpenBSD: cgram.y,v 1.9 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: cgram.y,v 1.10 2008/08/17 18:40:12 ragge Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). @@ -79,7 +79,6 @@ /* * Token used in C lex/yacc communications. */ -%token C_WSTRING /* a wide string constant */ %token C_STRING /* a string constant */ %token C_ICON /* an integer constant */ %token C_FCON /* a floating point constant */ @@ -143,13 +142,14 @@ # include <string.h> # include <stdlib.h> -static int fun_inline; /* Reading an inline function */ +int fun_inline; /* Reading an inline function */ int oldstyle; /* Current function being defined */ -int noretype; static struct symtab *xnf; extern int enummer, tvaloff; extern struct rstack *rpole; -static int ctval; +static int ctval, widestr; + +#define NORETYP SNOCREAT /* no return type, save in unused field in symtab */ static NODE *bdty(int op, ...); static void fend(void); @@ -170,7 +170,10 @@ static NODE *cmop(NODE *l, NODE *r); static NODE *xcmop(NODE *out, NODE *in, NODE *str); static void mkxasm(char *str, NODE *p); static NODE *xasmop(char *str, NODE *p); - +static int maxstlen(char *str); +static char *stradd(char *old, char *new); +static NODE *biop(int op, NODE *l, NODE *r); +static void flend(void); /* * State for saving current switch state (when nested switches). @@ -204,9 +207,9 @@ struct savbc { parameter_type_list parameter_list addrlbl declaration_specifiers pointer direct_abstract_declarator specifier_qualifier_list merge_specifiers nocon_e - identifier_list arg_param_list arg_declaration arg_dcl_list - designator_list designator xasm oplist oper cnstr -%type <strp> string wstring C_STRING C_WSTRING + identifier_list arg_param_list + designator_list designator xasm oplist oper cnstr funtype +%type <strp> string C_STRING %type <rp> str_head %type <symp> xnfdeclarator clbrace enum_head @@ -222,36 +225,22 @@ ext_def_list: ext_def_list external_def | { ftnend(); } ; -external_def: function_definition { blevel = 0; } +external_def: funtype kr_args compoundstmt { fend(); } | declaration { blevel = 0; symclear(0); } | asmstatement ';' | ';' | error { blevel = 0; } ; -function_definition: - /* Ansi (or K&R header without parameter types) */ - declaration_specifiers declarator { - fundef($1, $2); - } compoundstmt { fend(); } - /* Same as above but without declaring function type */ - | declarator { - noretype = 1; - fundef(mkty(INT, 0, MKSUE(INT)), $1); - } compoundstmt { fend(); noretype = 0; } - /* K&R function without type declaration */ - | declarator { - noretype = 1; - if (oldstyle == 0) - uerror("bad declaration in ansi function"); - fundef(mkty(INT, 0, MKSUE(INT)), $1); - } arg_dcl_list compoundstmt { fend(); noretype = 0; } - /* K&R function with type declaration */ - | declaration_specifiers declarator { - if (oldstyle == 0) - uerror("bad declaration in ansi function"); - fundef($1, $2); - } arg_dcl_list compoundstmt { fend(); } +funtype: /* no type given */ declarator { + fundef(mkty(INT, 0, MKSUE(INT)), $1); + cftnsp->sflags |= NORETYP; + } + | declaration_specifiers declarator { fundef($1,$2); } + ; + +kr_args: /* empty */ + | arg_dcl_list ; /* @@ -274,11 +263,7 @@ merge_attribs: C_CLASS { $$ = block(CLASS, NIL, NIL, $1, 0, 0); } ; function_specifiers: - C_FUNSPEC { - if (fun_inline) - uerror("too many inline"); - fun_inline = 1; - } + C_FUNSPEC { fun_inline = 1; } ; type_specifier: C_TYPE { $$ = $1; } @@ -336,26 +321,36 @@ direct_declarator: C_NAME { $$ = bdty(NAME, $1); } | '(' declarator ')' { $$ = $2; } | direct_declarator '[' nocon_e ']' { $3 = optim($3); - if (blevel == 0 && !nncon($3)) + if ((blevel == 0 || rpole != NULL) && !nncon($3)) uerror("array size not constant"); + /* + * Checks according to 6.7.5.2 clause 1: + * "...the expression shall have an integer type." + * "If the expression is a constant expression, + * it shall have a value greater than zero." + */ if (!ISINTEGER($3->n_type)) werror("array size is not an integer"); - else if ($3->n_op == ICON && $3->n_lval < 0) { - uerror("array size must be non-negative"); - $3->n_lval = 1; + else if ($3->n_op == ICON) { + if ($3->n_lval < 0) { + uerror("array size cannot be negative"); + $3->n_lval = 1; + } +#ifdef notyet + if ($3->n_lval == 0 && Wgcc) + werror("gcc extension; zero size"); +#endif } - $$ = block(LB, $1, $3, INT, 0, MKSUE(INT)); - } - | direct_declarator '[' ']' { $$ = bdty(LB, $1, 0); } - | direct_declarator '(' fundcl parameter_type_list ')' { - if (blevel-- > 1) - symclear(blevel); - $$ = bdty(CALL, $1, $4); - } - | direct_declarator '(' fundcl identifier_list ')' { - if (blevel-- > 1) - symclear(blevel); - $$ = bdty(CALL, $1, $4); + $$ = biop(LB, $1, $3); + } + | direct_declarator '[' ']' { + $$ = biop(LB, $1, bcon(NOOFFSET)); + } + | direct_declarator '(' parameter_type_list ')' { + $$ = bdty(CALL, $1, $3); + } + | direct_declarator '(' identifier_list ')' { + $$ = bdty(CALL, $1, $3); if (blevel != 0) uerror("function declaration in bad context"); oldstyle = 1; @@ -366,20 +361,8 @@ direct_declarator: C_NAME { $$ = bdty(NAME, $1); } } ; -fundcl: { if (++blevel == 1) argoff = ARGINIT; ctval = tvaloff; } - ; - -identifier_list: C_NAME { - $$ = mkty(FARG, NULL, MKSUE(INT)); - $$->n_sp = lookup($1, 0); - defid($$, PARAM); - } - | identifier_list ',' C_NAME { - $$ = mkty(FARG, NULL, MKSUE(INT)); - $$->n_sp = lookup($3, 0); - defid($$, PARAM); - $$ = block(CM, $1, $$, 0, 0, 0); - } +identifier_list: C_NAME { $$ = bdty(NAME, $1); } + | identifier_list ',' C_NAME { $$ = cmop($1, bdty(NAME, $3)); } ; /* @@ -388,8 +371,7 @@ identifier_list: C_NAME { parameter_type_list: parameter_list { $$ = $1; } | parameter_list ',' C_ELLIPSIS { - $$ = block(CM, $1, block(ELLIPSIS, NIL, NIL, 0, 0, 0), - 0, 0, 0); + $$ = cmop($1, biop(ELLIPSIS, NIL, NIL)); } ; @@ -400,7 +382,7 @@ parameter_type_list: */ parameter_list: parameter_declaration { $$ = $1; } | parameter_list ',' parameter_declaration { - $$ = block(CM, $1, $3, 0, 0, 0); + $$ = cmop($1, $3); } ; @@ -409,16 +391,9 @@ parameter_list: parameter_declaration { $$ = $1; } */ parameter_declaration: declaration_specifiers declarator { - if ($1->n_lval == AUTO || $1->n_lval == TYPEDEF || - $1->n_lval == EXTERN || $1->n_lval == STATIC) + if ($1->n_lval != SNULL && $1->n_lval != REGISTER) uerror("illegal parameter class"); $$ = tymerge($1, $2); - if (blevel == 1) { - $$->n_sp = lookup((char *)$$->n_sp, 0);/* XXX */ - if (ISFTN($$->n_type)) - $$->n_type = INCREF($$->n_type); - defid($$, PARAM); - } nfree($1); } @@ -442,9 +417,11 @@ abstract_declarator: direct_abstract_declarator: '(' abstract_declarator ')' { $$ = $2; } - | '[' ']' { $$ = bdty(LB, bdty(NAME, NULL), 0); } + | '[' ']' { $$ = biop(LB, bdty(NAME, NULL), bcon(NOOFFSET)); } | '[' con_e ']' { $$ = bdty(LB, bdty(NAME, NULL), $2); } - | direct_abstract_declarator '[' ']' { $$ = bdty(LB, $1, 0); } + | direct_abstract_declarator '[' ']' { + $$ = biop(LB, $1, bcon(NOOFFSET)); + } | direct_abstract_declarator '[' con_e ']' { $$ = bdty(LB, $1, $3); } @@ -497,10 +474,9 @@ block_item: declaration /* * Variables are declared in init_declarator. */ -declaration: declaration_specifiers ';' { nfree($1); goto inl; } +declaration: declaration_specifiers ';' { nfree($1); fun_inline = 0; } | declaration_specifiers init_declarator_list ';' { nfree($1); - inl: fun_inline = 0; } ; @@ -580,8 +556,7 @@ struct_declarator_list: struct_declarator: declarator { tymerge($<nodep>0, $1); - soumemb($1, (char *)$1->n_sp, - $<nodep>0->n_lval); /* XXX */ + soumemb($1, (char *)$1->n_sp, 0); nfree($1); } | ':' con_e { @@ -652,7 +627,7 @@ designator: '[' con_e ']' { uerror("designator must be non-negative"); $2 = 0; } - $$ = bdty(LB, NULL, $2); + $$ = biop(LB, NIL, bcon($2)); } | C_STROP C_NAME { if ($1 != DOT) @@ -670,34 +645,8 @@ ibrace: '{' { ilbrace(); } /* STATEMENTS */ -compoundstmt: begin block_item_list '}' { -#ifdef STABS - if (gflag && blevel > 2) - stabs_rbrac(blevel); -#endif - --blevel; - if( blevel == 1 ) - blevel = 0; - symclear(blevel); /* Clean ut the symbol table */ - if (autooff > maxautooff) - maxautooff = autooff; - autooff = savctx->contlab; - savctx = savctx->next; - } - | begin '}' { -#ifdef STABS - if (gflag && blevel > 2) - stabs_rbrac(blevel); -#endif - --blevel; - if( blevel == 1 ) - blevel = 0; - symclear(blevel); /* Clean ut the symbol table */ - if (autooff > maxautooff) - maxautooff = autooff; - autooff = savctx->contlab; - savctx = savctx->next; - } +compoundstmt: begin block_item_list '}' { flend(); } + | begin '}' { flend(); } ; begin: '{' { @@ -719,6 +668,8 @@ begin: '{' { bc->next = savctx; savctx = bc; bccode(); + if (sspflag && blevel == 2) + sspstart(); } ; @@ -788,19 +739,19 @@ statement: e ';' { ecomp( $1 ); symclear(blevel); } } | C_RETURN ';' { branch(retlab); - if (cftnsp->stype != VOID && noretype && + if (cftnsp->stype != VOID && + (cftnsp->sflags & NORETYP) == 0 && cftnsp->stype != VOID+FTN) uerror("return value required"); rch: - if (!reached) + if (!reached && Wunreachable_code) werror( "statement is not reached"); reached = 0; } | C_RETURN e ';' { register NODE *temp; - spname = cftnsp; - temp = buildtree( NAME, NIL, NIL ); + temp = nametree(cftnsp); temp->n_type = DECREF(temp->n_type); temp = buildtree(RETURN, temp, $2); @@ -814,9 +765,7 @@ statement: e ';' { ecomp( $1 ); symclear(blevel); } reached = 0; } | C_GOTO C_NAME ';' { gotolabel($2); goto rch; } - | C_GOTO '*' e ';' { - ecomp(block(GOTO, $3, NIL, INT, 0, 0)); - } + | C_GOTO '*' e ';' { ecomp(biop(GOTO, $3, NIL)); } | asmstatement ';' | ';' | error ';' @@ -824,8 +773,12 @@ statement: e ';' { ecomp( $1 ); symclear(blevel); } | label statement ; -asmstatement: C_ASM '(' string ')' { send_passt(IP_ASM, mkpstr($3)); } - | C_ASM '(' string xasm ')' { mkxasm($3, $4); } +asmstatement: C_ASM mvol '(' string ')' { send_passt(IP_ASM, mkpstr($4)); } + | C_ASM mvol '(' string xasm ')' { mkxasm($4, $5); } + ; + +mvol: /* empty */ + | C_QUALIFIER { nfree($1); } ; xasm: ':' oplist { $$ = xcmop($2, NIL, NIL); } @@ -846,14 +799,13 @@ cnstr: string { $$ = xasmop($1, bcon(0)); } ; label: C_NAME ':' { deflabel($1); reached = 1; } + | C_TYPENAME ':' { deflabel($1); reached = 1; } | C_CASE e ':' { addcase($2); reached = 1; } | C_DEFAULT ':' { reached = 1; adddef(); flostat |= FDEF; } ; doprefix: C_DO { savebc(); - if (!reached) - werror("loop not entered at top"); brklab = getlab(); contlab = getlab(); plabel( $$ = getlab()); @@ -877,8 +829,6 @@ ifelprefix: ifprefix statement C_ELSE { whprefix: C_WHILE '(' e ')' { savebc(); - if (!reached) - werror("loop not entered at top"); if ($3->n_op == ICON && $3->n_lval != 0) flostat = FLOOP; plabel( contlab = getlab()); @@ -893,8 +843,6 @@ whprefix: C_WHILE '(' e ')' { forprefix: C_FOR '(' .e ';' .e ';' { if ($3) ecomp($3); - else if (!reached) - werror("loop not entered at top"); savebc(); contlab = getlab(); brklab = getlab(); @@ -993,6 +941,7 @@ e: e ',' e { $$ = buildtree(COMOP, $1, $3); } | e C_DIVOP e { $$ = buildtree($2, $1, $3); } | e '*' e { $$ = buildtree(MUL, $1, $3); } | e '=' addrlbl { $$ = buildtree(ASSIGN, $1, $3); } + | '(' begin block_item_list e ';' '}' ')' { $$ = $4; flend(); } | term ; @@ -1001,8 +950,7 @@ addrlbl: C_ANDAND C_NAME { struct symtab *s = lookup($2, SLBLNAME); if (s->soffset == 0) s->soffset = -getlab(); - spname = s; - $$ = buildtree(ADDROF, buildtree(NAME, NIL, NIL), NIL); + $$ = buildtree(ADDROF, nametree(s), NIL); #else uerror("gcc extension"); #endif @@ -1012,7 +960,7 @@ addrlbl: C_ANDAND C_NAME { term: term C_INCOP { $$ = buildtree( $2, $1, bcon(1) ); } | '*' term { $$ = buildtree(UMUL, $2, NIL); } | '&' term { - if( ISFTN($2->n_type) || ISARY($2->n_type) ){ + if( ISFTN($2->n_type)/* || ISARY($2->n_type) */){ #ifdef notdef werror( "& before array or function: ignored" ); #endif @@ -1041,8 +989,7 @@ term: term C_INCOP { $$ = buildtree( $2, $1, bcon(1) ); } } | '(' cast_type ')' clbrace init_list optcomma '}' { endinit(); - spname = $4; - $$ = buildtree(NAME, NIL, NIL); + $$ = nametree($4); } | term '[' e ']' { $$ = buildtree( UMUL, @@ -1053,47 +1000,26 @@ term: term C_INCOP { $$ = buildtree( $2, $1, bcon(1) ); } | term C_STROP C_NAME { $$ = structref($1, $2, $3); } | term C_STROP C_TYPENAME { $$ = structref($1, $2, $3); } | C_NAME { - spname = lookup($1, 0); - if (spname->sflags & SINLINE) - inline_ref(spname); - $$ = buildtree(NAME, NIL, NIL); - if (spname->sflags & SDYNARRAY) + struct symtab *sp; + + sp = lookup($1, 0); + if (sp->sflags & SINLINE) + inline_ref(sp); + $$ = nametree(sp); + if (sp->sflags & SDYNARRAY) $$ = buildtree(UMUL, $$, NIL); } | C_ICON { $$ = $1; } | C_FCON { $$ = $1; } - | string { $$ = strend(0, $1); /* get string contents */ } - | wstring { $$ = strend('L', $1); } + | string { $$ = strend(widestr, $1); } | '(' e ')' { $$=$2; } ; clbrace: '{' { $$ = clbrace($<nodep>-1); } ; -string: C_STRING { - int len = strlen($1) + 1; - $$ = tmpalloc(len); - strlcpy($$, $1, len); - } - | string C_STRING { - int len = strlen($1) + strlen($2) + 1; - $$ = tmpalloc(len); - strlcpy($$, $1, len); - strlcat($$, $2, len); - } - ; - -wstring: C_WSTRING { - int len = strlen($1) + 1; - $$ = tmpalloc(len); - strlcpy($$, $1, len); - } - | string C_WSTRING { - int len = strlen($1) + strlen($2) + 1; - $$ = tmpalloc(len); - strlcpy($$, $1, len); - strlcat($$, $2, len); - } +string: C_STRING { widestr = $1[0] == 'L'; $$ = stradd("", $1); } + | string C_STRING { $$ = stradd($1, $2); } ; cast_type: specifier_qualifier_list { @@ -1117,8 +1043,7 @@ funct_idn: C_NAME '(' { } if (s->sflags & SINLINE) inline_ref(s); - spname = s; - $$ = buildtree(NAME, NIL, NIL); + $$ = nametree(s); } | term '(' ; @@ -1138,7 +1063,7 @@ bdty(int op, ...) register NODE *q; va_start(ap, op); - q = block(op, NIL, NIL, INT, 0, MKSUE(INT)); + q = biop(op, NIL, NIL); switch (op) { case UMUL: @@ -1154,9 +1079,11 @@ bdty(int op, ...) case LB: q->n_left = va_arg(ap, NODE *); - if ((val = va_arg(ap, int)) < 0) - uerror("array size must be non-negative"); - q->n_right = bcon(val < 0 ? 1 : val); + if ((val = va_arg(ap, int)) <= 0) { + uerror("array size must be positive"); + val = 1; + } + q->n_right = bcon(val); break; case NAME: @@ -1172,6 +1099,25 @@ bdty(int op, ...) } static void +flend(void) +{ + if (sspflag && blevel == 2) + sspend(); +#ifdef STABS + if (gflag && blevel > 2) + stabs_rbrac(blevel); +#endif + --blevel; + if( blevel == 1 ) + blevel = 0; + symclear(blevel); /* Clean ut the symbol table */ + if (autooff > maxautooff) + maxautooff = autooff; + autooff = savctx->contlab; + savctx = savctx->next; +} + +static void savebc(void) { struct savbc *bc = tmpalloc(sizeof(struct savbc)); @@ -1221,14 +1167,15 @@ addcase(NODE *p) return; } - val = p->n_lval; - p = makety(p, swpole->type, 0, 0, MKSUE(swpole->type)); - if (p->n_op != ICON) - cerror("could not cast case value to type of switch " - "expression"); - if (p->n_lval != val) - werror("case expression truncated"); - + if (DEUNSIGN(swpole->type) != DEUNSIGN(p->n_type)) { + val = p->n_lval; + p = makety(p, swpole->type, 0, 0, MKSUE(swpole->type)); + if (p->n_op != ICON) + cerror("could not cast case value to type of switch " + "expression"); + if (p->n_lval != val) + werror("case expression truncated"); + } sw->sval = p->n_lval; tfree(p); put = &swpole->ents; @@ -1370,6 +1317,24 @@ init_declarator(NODE *tn, NODE *p, int assign) } /* + * Declare function arguments. + */ +static void +funargs(NODE *p) +{ + if (p->n_op == ELLIPSIS) + return; + if (oldstyle) { + p->n_op = TYPE; + p->n_type = FARG; + } + p->n_sp = lookup((char *)p->n_sp, 0);/* XXX */ + if (ISFTN(p->n_type)) + p->n_type = INCREF(p->n_type); + defid(p, PARAM); +} + +/* * Declare a function. */ static void @@ -1381,17 +1346,25 @@ fundef(NODE *tp, NODE *p) int class = tp->n_lval, oclass; char *c; - while (q->n_op == UMUL) - q = q->n_left; + for (q = p; coptype(q->n_op) != LTYPE && q->n_left->n_op != NAME; + q = q->n_left) + ; if (q->n_op != CALL && q->n_op != UCALL) { uerror("invalid function definition"); p = bdty(UCALL, p); } - /* Save function args before they are clobbered in tymerge() */ - /* Typecheck against prototype will be done in defid(). */ - ftnarg(p); + argoff = ARGINIT; + ctval = tvaloff; + blevel++; + + if (q->n_op == CALL && q->n_right->n_type != VOID) { + /* declare function arguments */ + listf(q->n_right, funargs); + ftnarg(q); + } + blevel--; tymerge(tp, p); s = p->n_sp = lookup((char *)p->n_sp, 0); /* XXX */ @@ -1399,14 +1372,17 @@ fundef(NODE *tp, NODE *p) if (class == STATIC && oclass == EXTERN) werror("%s was first declared extern, then static", s->sname); - if ((oclass == SNULL || oclass == USTATIC) && - class == STATIC && fun_inline) { + if (fun_inline) { + /* special syntax for inline functions */ + if ((oclass == SNULL || oclass == USTATIC) && + (class == STATIC || class == SNULL)) { /* Unreferenced, store it for (eventual) later use */ /* Ignore it if it not declared static */ - s->sflags |= SINLINE; - inline_start(s); - } - if (class == EXTERN) + s->sflags |= SINLINE; + inline_start(s); + } else if (class == EXTERN) + class = EXTDEF; + } else if (class == EXTERN) class = SNULL; /* same result */ cftnsp = s; @@ -1442,7 +1418,7 @@ structref(NODE *p, int f, char *name) if (f == DOT) p = buildtree(ADDROF, p, NIL); - r = block(NAME, NIL, NIL, INT, 0, MKSUE(INT)); + r = biop(NAME, NIL, NIL); r->n_name = name; r = buildtree(STREF, p, r); return r; @@ -1468,7 +1444,7 @@ void branch(int lbl) { int r = reached++; - ecomp(block(GOTO, bcon(lbl), NIL, INT, 0, 0)); + ecomp(biop(GOTO, bcon(lbl), NIL)); reached = r; } @@ -1481,7 +1457,7 @@ mkpstr(char *str) char *s, *os; int v, l = strlen(str)+3; /* \t + \n + \0 */ - os = s = isinlining ? permalloc(l) : tmpalloc(l); + os = s = inlalloc(l); *s++ = '\t'; for (; *str; ) { if (*str++ == '\\') @@ -1495,6 +1471,81 @@ mkpstr(char *str) return os; } +/* + * Estimate the max length a string will have in its internal + * representation based on number of \ characters. + */ +static int +maxstlen(char *str) +{ + int i; + + for (i = 0; *str; str++, i++) + if (*str == '\\' || *str < 32 || *str > 0176) + i += 3; + return i; +} + +static char * +voct(char *d, unsigned int v) +{ + v &= (1 << SZCHAR) - 1; + *d++ = '\\'; + *d++ = v/64 + '0'; v &= 077; + *d++ = v/8 + '0'; v &= 7; + *d++ = v + '0'; + return d; +} + + +/* + * Convert a string to internal format. The resulting string may be no + * more than len characters long. + */ +static void +fixstr(char *d, char *s, int len) +{ + unsigned int v; + + while (*s) { + if (len <= 0) + cerror("fixstr"); + if (*s == '\\') { + s++; + v = esccon(&s); + d = voct(d, v); + len -= 4; + } else if (*s < ' ' || *s > 0176) { + d = voct(d, *s++); + len -= 4; + } else + *d++ = *s++, len--; + } + *d = 0; +} + +/* + * Add "raw" string new to cleaned string old. + */ +static char * +stradd(char *old, char *new) +{ + char *rv; + int len; + + if (*new == 'L' && new[1] == '\"') + widestr = 1, new++; + if (*new == '\"') { + new++; /* remove first " */ + new[strlen(new) - 1] = 0;/* remove last " */ + } + len = strlen(old) + maxstlen(new) + 1; + rv = tmpalloc(len); + strlcpy(rv, old, len); + fixstr(rv + strlen(old), new, maxstlen(new) + 1); + return rv; +} + static struct symtab * clbrace(NODE *p) { @@ -1509,7 +1560,7 @@ clbrace(NODE *p) sp->sdf = p->n_df; sp->ssue = p->n_sue; sp->sclass = blevel ? AUTO : STATIC; - if (!ISARY(sp->stype) || sp->sdf->ddim != 0) { + if (!ISARY(sp->stype) || sp->sdf->ddim != NOOFFSET) { sp->soffset = NOOFFSET; oalloc(sp, &autooff); } @@ -1518,12 +1569,16 @@ clbrace(NODE *p) return sp; } -/* Support for extended assembler a' la' gcc style follows below */ +NODE * +biop(int op, NODE *l, NODE *r) +{ + return block(op, l, r, INT, 0, MKSUE(INT)); +} static NODE * cmop(NODE *l, NODE *r) { - return block(CM, l, r, INT, 0, MKSUE(INT)); + return biop(CM, l, r); } static NODE * @@ -1532,6 +1587,8 @@ voidcon(void) return block(ICON, NIL, NIL, STRTY, 0, MKSUE(VOID)); } +/* Support for extended assembler a' la' gcc style follows below */ + static NODE * xmrg(NODE *out, NODE *in) { @@ -1560,10 +1617,10 @@ xcmop(NODE *out, NODE *in, NODE *str) /* D out-list sanity check */ for (p = out; p->n_op == CM; p = p->n_left) { q = p->n_right; - if (q->n_name[0] != '=') + if (q->n_name[0] != '=' && q->n_name[0] != '+') uerror("output missing ="); } - if (p->n_name[0] != '=') + if (p->n_name[0] != '=' && p->n_name[0] != '+') uerror("output missing ="); if (in == NIL) p = out; @@ -1586,8 +1643,8 @@ static NODE * xasmop(char *str, NODE *p) { - p = block(XARG, p, NIL, INT, 0, MKSUE(INT)); - p->n_name = str; + p = biop(XARG, p, NIL); + p->n_name = isinlining ? newstring(str, strlen(str)+1) : str; return p; } @@ -1599,8 +1656,8 @@ mkxasm(char *str, NODE *p) { NODE *q; - q = block(XASM, p->n_left, p->n_right, INT, 0, MKSUE(INT)); - q->n_name = str; + q = biop(XASM, p->n_left, p->n_right); + q->n_name = isinlining ? newstring(str, strlen(str)+1) : str; nfree(p); ecomp(q); } diff --git a/usr.bin/pcc/ccom/gcc_compat.c b/usr.bin/pcc/ccom/gcc_compat.c index 1f8920623e6..d743f06f313 100644 --- a/usr.bin/pcc/ccom/gcc_compat.c +++ b/usr.bin/pcc/ccom/gcc_compat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gcc_compat.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: gcc_compat.c,v 1.6 2008/08/17 18:40:12 ragge Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -44,13 +44,17 @@ static struct kw { * Do NOT change the order of these entries unless you know * what you're doing! */ - { "__asm", NULL, C_ASM }, - { "__signed", NULL, 0 }, - { "__inline", NULL, C_FUNSPEC }, - { "__const", NULL, 0 }, - { "__asm__", NULL, C_ASM }, - { "__inline__", NULL, C_FUNSPEC }, - { "__thread", NULL, 0 }, +/* 0 */ { "__asm", NULL, C_ASM }, +/* 1 */ { "__signed", NULL, 0 }, +/* 2 */ { "__inline", NULL, C_FUNSPEC }, +/* 3 */ { "__const", NULL, 0 }, +/* 4 */ { "__asm__", NULL, C_ASM }, +/* 5 */ { "__inline__", NULL, C_FUNSPEC }, +/* 6 */ { "__thread", NULL, 0 }, +/* 7 */ { "__FUNCTION__", NULL, 0 }, +/* 8 */ { "__volatile", NULL, 0 }, +/* 9 */ { "__volatile__", NULL, 0 }, +/* 10 */{ "__restrict", NULL, -1 }, { NULL, NULL, 0 }, }; @@ -96,6 +100,17 @@ gcc_keyword(char *str, NODE **n) while (tw > tlbuf) cunput(*--tw); return -1; + case 7: /* __FUNCTION__ */ + if (cftnsp == NULL) { + uerror("__FUNCTION__ outside function"); + yylval.strp = ""; + } else + yylval.strp = cftnsp->sname; /* XXX - not C99 */ + return C_STRING; + case 8: /* __volatile */ + case 9: /* __volatile__ */ + *n = block(QUALIFIER, NIL, NIL, VOL, 0, 0); + return C_QUALIFIER; } cerror("gcc_keyword"); return 0; diff --git a/usr.bin/pcc/ccom/init.c b/usr.bin/pcc/ccom/init.c index f4ced795f23..b6754d56f23 100644 --- a/usr.bin/pcc/ccom/init.c +++ b/usr.bin/pcc/ccom/init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init.c,v 1.7 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: init.c,v 1.8 2008/08/17 18:40:12 ragge Exp $ */ /* * Copyright (c) 2004, 2007 Anders Magnusson (ragge@ludd.ltu.se). @@ -297,7 +297,8 @@ stkpush(void) is->in_lnk = ISSOU(DECREF(t)) ? pstk->in_sym->ssue->sylnk : 0; is->in_t = DECREF(t); is->in_sym = sp; - if (pstk->in_df->ddim && pstk->in_n >= pstk->in_df->ddim) { + if (pstk->in_df->ddim != NOOFFSET && + pstk->in_n >= pstk->in_df->ddim) { werror("excess of initializing elements"); pstk->in_n--; } @@ -340,7 +341,7 @@ stkpop(void) pstk->in_n++; if (pstk->in_fl) break; - if (pstk->in_df->ddim == 0 || + if (pstk->in_df->ddim == NOOFFSET || pstk->in_n < pstk->in_df->ddim) break; /* ger more elements */ } @@ -401,10 +402,12 @@ findoff(void) } } } +#ifdef PCC_DEBUG if (idebug>1) { printf("findoff: off %lld\n", off); prtstk(pstk); } +#endif return off; } @@ -539,9 +542,7 @@ insbf(OFFSZ off, int fsz, int val) else typ = INT; /* Fake a struct reference */ - spname = csym; - p = buildtree(ADDROF, - buildtree(NAME, NIL, NIL), NIL); + p = buildtree(ADDROF, nametree(csym), NIL); sym.stype = typ; sym.squal = 0; sym.sdf = 0; @@ -598,7 +599,7 @@ endinit(void) defloc(csym); /* Calculate total block size */ - if (ISARY(csym->stype) && csym->sdf->ddim == 0) { + if (ISARY(csym->stype) && csym->sdf->ddim == NOOFFSET) { tbit = numents*basesz; /* open-ended arrays */ csym->sdf->ddim = numents; if (csym->sclass == AUTO) { /* Get stack space */ @@ -630,9 +631,7 @@ endinit(void) (ll->begsz + il->off) - lastoff); /* Fake a struct reference */ - spname = csym; - p = buildtree(ADDROF, - buildtree(NAME, NIL, NIL), NIL); + p = buildtree(ADDROF, nametree(csym), NIL); n = il->n; sym.stype = n->n_type; sym.squal = n->n_qual; @@ -642,7 +641,7 @@ endinit(void) sym.sclass = fsz < 0 ? FIELD | -fsz : 0; r = xbcon(0, &sym, INT); p = block(STREF, p, r, INT, 0, MKSUE(INT)); - ecode(buildtree(ASSIGN, stref(p), il->n)); + ecomp(buildtree(ASSIGN, stref(p), il->n)); if (fsz < 0) fsz = -fsz; @@ -917,7 +916,7 @@ simpleinit(struct symtab *sp, NODE *p) /* Handle "aaa" as { 'a', 'a', 'a' } */ beginit(sp); strcvt(p); - if (csym->sdf->ddim == 0) + if (csym->sdf->ddim == NOOFFSET) scalinit(bcon(0)); /* Null-term arrays */ endinit(); return; @@ -926,8 +925,7 @@ simpleinit(struct symtab *sp, NODE *p) switch (sp->sclass) { case STATIC: case EXTDEF: - spname = sp; - p = optim(buildtree(ASSIGN, buildtree(NAME, NIL, NIL), p)); + p = optim(buildtree(ASSIGN, nametree(sp), p)); defloc(sp); ninval(0, p->n_right->n_sue->suesize, p->n_right); tfree(p); @@ -937,8 +935,7 @@ simpleinit(struct symtab *sp, NODE *p) case REGISTER: if (ISARY(sp->stype)) cerror("no array init"); - spname = sp; - ecomp(buildtree(ASSIGN, buildtree(NAME, NIL, NIL), p)); + ecomp(buildtree(ASSIGN, nametree(sp), p)); break; default: diff --git a/usr.bin/pcc/ccom/main.c b/usr.bin/pcc/ccom/main.c index de88379c9e8..f0bc7dfc6f9 100644 --- a/usr.bin/pcc/ccom/main.c +++ b/usr.bin/pcc/ccom/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: main.c,v 1.6 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2002 Anders Magnusson. All rights reserved. @@ -26,6 +26,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "config.h" + #include <unistd.h> #include <signal.h> #include <string.h> @@ -41,12 +43,19 @@ int iTflag, oTflag; #endif int xdebug, sdebug, gflag, c2debug, pdebug; int Wstrict_prototypes, Wmissing_prototypes, Wimplicit_int, - Wimplicit_function_declaration; + Wimplicit_function_declaration, Wpointer_sign, Wshadow, + Wsign_compare, Wunknown_pragmas, Wunreachable_code; +#ifdef CHAR_UNSIGNED +int funsigned_char = 1; +#else +int funsigned_char = 0; +#endif +int sspflag; int xssaflag, xtailcallflag, xtemps, xdeljumps; int e2debug, t2debug, f2debug, b2debug; -struct suedef btdims[24]; +struct suedef btdims[32]; char *prgname; static void prtstats(void); @@ -58,6 +67,11 @@ static struct { { "missing-prototypes", &Wmissing_prototypes, }, { "implicit-int", &Wimplicit_int, }, { "implicit-function-declaration", &Wimplicit_function_declaration, }, + { "shadow", &Wshadow, }, + { "pointer-sign", &Wpointer_sign, }, + { "sign-compare", &Wsign_compare, }, + { "unknown-pragmas", &Wunknown_pragmas, }, + { "unreachable-code", &Wunreachable_code, }, { NULL, NULL, }, }; @@ -86,26 +100,60 @@ segvcatch(int a) static void Wflags(char *str) { - int i, found = 0, all; + int i, flagval = 1, found = 0, all; + + if (strncmp("no-", str, 3) == 0) { + str += 3; + flagval = 0; + } if (strcmp(str, "implicit") == 0) { - Wimplicit_int = Wimplicit_function_declaration = 1; + Wimplicit_int = Wimplicit_function_declaration = flagval; return; } if (strcmp(str, "error") == 0) { - warniserr = 1; + warniserr = flagval; return; } + all = strcmp(str, "W") == 0; - for (i = 0; flagstr[i].n; i++) + for (i = 0; flagstr[i].n; i++) { if (all || strcmp(flagstr[i].n, str) == 0) { - *flagstr[i].f = 1; + *flagstr[i].f = flagval; found++; } - if (found == 0) + } + if (found == 0) { + fprintf(stderr, "unrecognised option '%s'\n", str); usage(); + } } +static void +fflags(char *str) +{ + int flagval = 1; + + if (strncmp("no-", str, 3) == 0) { + str += 3; + flagval = 0; + } + + if (strcmp(str, "signed-char") == 0) + funsigned_char = !flagval; + else if (strcmp(str, "unsigned-char") == 0) + funsigned_char = flagval; + else if (strcmp(str, "stack-protector") == 0) + sspflag = flagval; + else if (strcmp(str, "stack-protector-all") == 0) + sspflag = flagval; + else if (strncmp(str, "pack-struct", 11) == 0) + pragma_allpacked = (strlen(str) > 12 ? atoi(str+12) : 1); + else { + fprintf(stderr, "unrecognised option '%s'\n", str); + usage(); + } +} /* control multiple files */ int @@ -116,7 +164,7 @@ main(int argc, char *argv[]) prgname = argv[0]; - while ((ch = getopt(argc, argv, "OT:VW:X:Z:gklm:psvwx:")) != -1) + while ((ch = getopt(argc, argv, "OT:VW:X:Z:f:gklm:psvwx:")) != -1) switch (ch) { #if !defined(MULTIPASS) || defined(PASS1) case 'X': @@ -190,22 +238,26 @@ main(int argc, char *argv[]) #endif break; + case 'f': /* Language */ + fflags(optarg); + break; + + case 'g': /* Debugging */ + gflag = 1; + break; + case 'k': /* PIC code */ ++kflag; break; - case 'l': /* linenos */ + case 'l': /* Linenos */ ++lflag; break; - case 'm': /* target-specific */ + case 'm': /* Target-specific */ mflags(optarg); break; - case 'g': /* Debugging */ - gflag = 1; - break; - case 'p': /* Profiling */ pflag = 1; break; @@ -241,20 +293,21 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; - if (argc != 0) { + if (argc > 0 && strcmp(argv[0], "-") != 0) { if (freopen(argv[0], "r", stdin) == NULL) { fprintf(stderr, "open input file '%s':", argv[0]); perror(NULL); exit(1); } - if (argc != 1) - if (freopen(argv[1], "w", stdout) == NULL) { - fprintf(stderr, "open output file '%s':", - argv[1]); - perror(NULL); - exit(1); - } + } + if (argc > 1 && strcmp(argv[1], "-") != 0) { + if (freopen(argv[1], "w", stdout) == NULL) { + fprintf(stderr, "open output file '%s':", + argv[1]); + perror(NULL); + exit(1); + } } mkdope(); @@ -282,6 +335,9 @@ main(int argc, char *argv[]) btdims[UNSIGNED].suesize = SZINT; btdims[ULONG].suesize = SZLONG; btdims[ULONGLONG].suesize = SZLONGLONG; + btdims[FCOMPLEX].suesize = SZFLOAT * 2; + btdims[COMPLEX].suesize = SZDOUBLE * 2; + btdims[LCOMPLEX].suesize = SZLDOUBLE * 2; /* starts past any of the above */ reached = 1; @@ -294,6 +350,9 @@ main(int argc, char *argv[]) } #endif + if (sspflag) + sspinit(); + (void) yyparse(); yyaccpt(); diff --git a/usr.bin/pcc/ccom/optim.c b/usr.bin/pcc/ccom/optim.c index 6ae9991a6c4..548912521d5 100644 --- a/usr.bin/pcc/ccom/optim.c +++ b/usr.bin/pcc/ccom/optim.c @@ -1,4 +1,4 @@ -/* $OpenBSD: optim.c,v 1.3 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: optim.c,v 1.4 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -135,7 +135,8 @@ again: o = p->n_op; goto setuleft; case RS: - if (LO(p) == RS && RCON(p->n_left) && RCON(p)) { + if (LO(p) == RS && RCON(p->n_left) && RCON(p) && + (RV(p) + RV(p->n_left)) < p->n_sue->suesize) { /* two right-shift by constants */ RV(p) += RV(p->n_left); p->n_left = zapleft(p->n_left); diff --git a/usr.bin/pcc/ccom/pass1.h b/usr.bin/pcc/ccom/pass1.h index 960e0f40de1..51b00ccda55 100644 --- a/usr.bin/pcc/ccom/pass1.h +++ b/usr.bin/pcc/ccom/pass1.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pass1.h,v 1.9 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: pass1.h,v 1.10 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -33,9 +33,13 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "config.h" + #include <sys/types.h> #include <stdarg.h> +#ifdef HAVE_STDINT_H #include <stdint.h> +#endif #include "manifest.h" @@ -82,14 +86,14 @@ extern char *scnames(int); #define NSTYPES 05 #define SMASK 07 -#define SSET 00010 -#define SREF 00020 -#define SNOCREAT 00040 -#define STEMP 00100 -#define SDYNARRAY 00200 -#define SINLINE 00400 -#define STNODE 01000 -#define SASG 04000 +/* #define SSET 00010 */ +/* #define SREF 00020 */ +#define SNOCREAT 00040 /* don't create a symbol in lookup() */ +#define STEMP 00100 /* Allocate symtab from temp or perm mem */ +#define SDYNARRAY 00200 /* symbol is dynamic array on stack */ +#define SINLINE 00400 /* function is of type inline */ +#define STNODE 01000 /* symbol shall be a temporary node */ +#define SASG 04000 /* symbol is assigned to already */ #define SLOCAL1 010000 #define SLOCAL2 020000 #define SLOCAL3 040000 @@ -192,10 +196,6 @@ extern OFFSZ inoff; extern int reached; extern int isinlining; -/* tunnel to buildtree for name id's */ - -extern struct symtab *spname; - extern int sdebug, idebug, pdebug; /* various labels */ @@ -205,7 +205,7 @@ extern int flostat; extern int retlab; /* pragma globals */ -extern int pragma_packed, pragma_aligned; +extern int pragma_allpacked, pragma_packed, pragma_aligned; extern char *pragma_renamed; /* @@ -222,12 +222,12 @@ extern char *pragma_renamed; /* declarations of various functions */ extern NODE - *buildtree(int, NODE *l, NODE *r), + *buildtree(int, NODE *, NODE *r), *mkty(unsigned, union dimfun *, struct suedef *), *rstruct(char *, int), *dclstruct(struct rstack *), *strend(int gtype, char *), - *tymerge(NODE *typ, NODE *idp), + *tymerge(NODE *, NODE *), *stref(NODE *), *offcon(OFFSZ, TWORD, union dimfun *, struct suedef *), *bcon(int), @@ -239,14 +239,14 @@ extern NODE *ptmatch(NODE *), *tymatch(NODE *), *makety(NODE *, TWORD, TWORD, union dimfun *, struct suedef *), - *block(int, NODE *, NODE *r, TWORD, union dimfun *, struct suedef *), + *block(int, NODE *, NODE *, TWORD, union dimfun *, struct suedef *), *doszof(NODE *), *talloc(void), *optim(NODE *), *clocal(NODE *), *ccopy(NODE *), - *tempnode(int, TWORD type, union dimfun *df, struct suedef *sue), - *doacall(NODE *f, NODE *a); + *tempnode(int, TWORD, union dimfun *, struct suedef *), + *doacall(NODE *, NODE *); NODE *intprom(NODE *); OFFSZ tsize(TWORD, union dimfun *, struct suedef *), psize(NODE *); @@ -255,56 +255,58 @@ void spalloc(NODE *, NODE *, OFFSZ); char *exname(char *); extern struct rstack *rpole; -int oalloc(struct symtab *p, int *poff); +int oalloc(struct symtab *, int *); void deflabel(char *); void gotolabel(char *); -unsigned int esccon(char **sptr); -void inline_start(struct symtab *sp); +unsigned int esccon(char **); +void inline_start(struct symtab *); void inline_end(void); void inline_addarg(struct interpass *); -void inline_ref(struct symtab *sp); +void inline_ref(struct symtab *); void inline_prtout(void); void ftnarg(NODE *); struct rstack *bstruct(char *, int); void moedef(char *); void beginit(struct symtab *); void simpleinit(struct symtab *, NODE *); -struct symtab *lookup(char *name, int s); -struct symtab *getsymtab(char *name, int flags); +struct symtab *lookup(char *, int); +struct symtab *getsymtab(char *, int); char *addstring(char *); char *addname(char *); -char *newstring(char *, int len); -void symclear(int level); -struct symtab *hide(struct symtab *p); +void symclear(int); +struct symtab *hide(struct symtab *); void soumemb(NODE *, char *, int); int talign(unsigned int, struct suedef *); void bfcode(struct symtab **, int); int chkftn(union arglist *, union arglist *); void branch(int); -void cbranch(NODE *p, NODE *q); +void cbranch(NODE *, NODE *); void extdec(struct symtab *); void defzero(struct symtab *); -int falloc(struct symtab *p, int w, int new, NODE *pty); +int falloc(struct symtab *, int, int, NODE *); TWORD ctype(TWORD); -void ninval(CONSZ off, int fsz, NODE *); -void infld(CONSZ off, int fsz, CONSZ); -void zbits(CONSZ off, int fsz); -void instring(struct symtab *sp); -void inwstring(struct symtab *sp); -void plabel(int lab); +void ninval(CONSZ, int, NODE *); +void infld(CONSZ, int, CONSZ); +void zbits(CONSZ, int); +void instring(struct symtab *); +void inwstring(struct symtab *); +void plabel(int); void bjobcode(void); void ejobcode(int); void calldec(NODE *, NODE *); int cisreg(TWORD); -char *tmpsprintf(char *fmt, ...); -char *tmpvsprintf(char *fmt, va_list ap); +char *tmpsprintf(char *, ...); +char *tmpvsprintf(char *, va_list); void asginit(NODE *); void desinit(NODE *); void endinit(void); +void sspinit(void); +void sspstart(void); +void sspend(void); void ilbrace(void); void irbrace(void); -void scalinit(NODE *p); -void p1print(char *fmt, ...); +void scalinit(NODE *); +void p1print(char *, ...); char *copst(int); int cdope(int); void myp2tree(NODE *); @@ -317,12 +319,15 @@ NODE *enumref(char *); CONSZ icons(NODE *); int mypragma(char **); void fixdef(struct symtab *); -int cqual(TWORD t, TWORD q); +int cqual(TWORD, TWORD); void defloc(struct symtab *); -int fldchk(int sz); +int fldchk(int); int nncon(NODE *); -void cunput(char c); - +void cunput(char); +NODE *nametree(struct symtab *sp); +void *inlalloc(int size); +void pass1_lastchance(struct interpass *); +void fldty(struct symtab *p); #ifdef GCC_COMPAT void gcc_init(void); @@ -338,7 +343,7 @@ void stabs_lbrac(int); void stabs_func(struct symtab *); void stabs_newsym(struct symtab *); void stabs_chgsym(struct symtab *); -void stabs_struct(struct symtab *p, struct suedef *sue); +void stabs_struct(struct symtab *, struct suedef *); #endif #ifndef CHARCAST @@ -387,7 +392,9 @@ void stabs_struct(struct symtab *p, struct suedef *sue); */ #define SIGNED (MAXTYPES+1) #define BOOL (MAXTYPES+2) - +#define FCOMPLEX (MAXTYPES+3) +#define COMPLEX (MAXTYPES+4) +#define LCOMPLEX (MAXTYPES+5) #define coptype(o) (cdope(o)&TYFLG) #define clogop(o) (cdope(o)&LOGFLG) diff --git a/usr.bin/pcc/ccom/pftn.c b/usr.bin/pcc/ccom/pftn.c index 55d2925688e..5f946d3c1a1 100644 --- a/usr.bin/pcc/ccom/pftn.c +++ b/usr.bin/pcc/ccom/pftn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pftn.c,v 1.13 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: pftn.c,v 1.14 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -71,7 +71,6 @@ #include "cgram.h" -struct symtab *spname; struct symtab *cftnsp; int arglistcnt, dimfuncnt; /* statistics */ int symtabcnt, suedefcnt; /* statistics */ @@ -101,6 +100,8 @@ struct rstack { int rstr; struct symtab *rsym; struct symtab *rb; + int flags; +#define LASTELM 1 } *rpole; /* @@ -139,6 +140,7 @@ int ddebug = 0; void defid(NODE *q, int class) { + extern int fun_inline; struct symtab *p; TWORD type, qual; TWORD stp, stq; @@ -151,6 +153,9 @@ defid(NODE *q, int class) p = q->n_sp; + if (p->sname == NULL) + cerror("defining null identifier"); + #ifdef PCC_DEBUG if (ddebug) { printf("defid(%s (%p), ", p->sname, p); @@ -215,10 +220,11 @@ defid(NODE *q, int class) changed = 0; for (temp = type; temp & TMASK; temp = DECREF(temp)) { if (ISARY(temp)) { - if (dsym->ddim == 0) { + if (dsym->ddim == NOOFFSET) { dsym->ddim = ddef->ddim; changed = 1; - } else if (ddef->ddim != 0 && dsym->ddim!=ddef->ddim) { + } else if (ddef->ddim != NOOFFSET && + dsym->ddim!=ddef->ddim) { goto mismatch; } ++dsym; @@ -258,59 +264,60 @@ defid(NODE *q, int class) switch( scl ){ case STATIC: case USTATIC: - if( slev==0 ) return; + if( slev==0 ) + goto done; break; case EXTDEF: case EXTERN: case FORTRAN: case UFORTRAN: - return; + goto done; } break; case STATIC: if (scl==USTATIC || (scl==EXTERN && blevel==0)) { p->sclass = STATIC; - return; + goto done; } if (changed || (scl == STATIC && blevel == slev)) - return; /* identical redeclaration */ + goto done; /* identical redeclaration */ break; case USTATIC: if (scl==STATIC || scl==USTATIC) - return; + goto done; break; case TYPEDEF: if (scl == class) - return; + goto done; break; case UFORTRAN: if (scl == UFORTRAN || scl == FORTRAN) - return; + goto done; break; case FORTRAN: if (scl == UFORTRAN) { p->sclass = FORTRAN; - return; + goto done; } break; case MOU: case MOS: - return; + goto done; case EXTDEF: switch (scl) { case EXTERN: p->sclass = EXTDEF; - return; + goto done; case USTATIC: p->sclass = STATIC; - return; + goto done; } break; @@ -318,7 +325,11 @@ defid(NODE *q, int class) case REGISTER: if (blevel == slev) goto redec; - ; /* mismatch.. */ + break; /* mismatch.. */ + case SNULL: + if (fun_inline && ISFTN(type)) + goto done; + break; } mismatch: @@ -396,11 +407,18 @@ redec: uerror("redeclaration of %s", p->sname); break; case MOU: + rpole->rstr = 0; + /* FALLTHROUGH */ case MOS: oalloc(p, &rpole->rstr); if (class == MOU) rpole->rstr = 0; break; + case SNULL: + if (fun_inline) { + p->slevel = 1; + p->soffset = getlab(); + } } #ifdef STABS @@ -408,6 +426,7 @@ redec: uerror("redeclaration of %s", p->sname); stabs_newsym(p); #endif +done: fixdef(p); /* Leave last word to target */ #ifdef PCC_DEBUG if (ddebug) @@ -705,6 +724,12 @@ enumref(char *name) NODE *p; sp = lookup(name, STAGNAME); + /* + * 6.7.2.3 Clause 2: + * "A type specifier of the form 'enum identifier' without an + * enumerator list shall only appear after the type it specifies + * is complete." + */ if (sp->sclass != ENAME) uerror("enum %s undeclared", name); @@ -735,9 +760,8 @@ bstruct(char *name, int soru) } else sp = NULL; - r = tmpalloc(sizeof(struct rstack)); + r = tmpcalloc(sizeof(struct rstack)); r->rsou = soru; - r->rstr = 0; r->rsym = sp; r->rb = NULL; r->rnext = rpole; @@ -758,6 +782,9 @@ dclstruct(struct rstack *r) int al, sa, sz, coff; TWORD temp; + if (pragma_allpacked && !pragma_packed) + pragma_packed = pragma_allpacked; + if (r->rsym == NULL) { sue = permalloc(sizeof(struct suedef)); suedefcnt++; @@ -768,10 +795,6 @@ dclstruct(struct rstack *r) if (sue->suealign == 0) /* suealign == 0 is undeclared struct */ sue->suealign = ALSTRUCT; -#ifdef PCC_DEBUG - if (ddebug) - printf("dclstruct(%s)\n", r->rsym ? r->rsym->sname : "??"); -#endif temp = r->rsou == STNAME ? STRTY : UNIONTY; al = ALSTRUCT; @@ -805,11 +828,21 @@ dclstruct(struct rstack *r) */ SETOFF(al, sa); } - SETOFF(rpole->rstr, al); + + if (!pragma_packed && !pragma_aligned) + SETOFF(rpole->rstr, al); sue->suesize = rpole->rstr; sue->suealign = al; +#ifdef PCC_DEBUG + if (ddebug) { + printf("dclstruct(%s): size=%d, align=%d\n", + r->rsym ? r->rsym->sname : "??", + sue->suesize, sue->suealign); + } +#endif + pragma_packed = pragma_aligned = 0; #ifdef STABS @@ -839,6 +872,7 @@ void soumemb(NODE *n, char *name, int class) { struct symtab *sp, *lsp; + int incomp; if (rpole == NULL) cerror("soumemb"); @@ -854,10 +888,38 @@ soumemb(NODE *n, char *name, int class) else lsp->snext = sp; n->n_sp = sp; + if ((class & FIELD) == 0) + class = rpole->rsou == STNAME ? MOS : MOU; defid(n, class); -} - + /* + * 6.7.2.1 clause 16: + * "...the last member of a structure with more than one + * named member may have incomplete array type;" + */ + if (ISARY(sp->stype) && sp->sdf->ddim == NOOFFSET) + incomp = 1; + else + incomp = 0; + if ((rpole->flags & LASTELM) || (rpole->rb == sp && incomp == 1)) + uerror("incomplete array in struct"); + if (incomp == 1) + rpole->flags |= LASTELM; + + /* + * 6.7.2.1 clause 2: + * "...such a structure shall not be a member of a structure + * or an element of an array." + */ + if (sp->stype == STRTY && sp->ssue->sylnk) { + struct symtab *lnk; + + for (lnk = sp->ssue->sylnk; lnk->snext; lnk = lnk->snext) + ; + if (ISARY(lnk->stype) && lnk->sdf->ddim == NOOFFSET) + uerror("incomplete struct in struct"); + } +} /* * error printing routine in parser @@ -1005,6 +1067,8 @@ tsize(TWORD ty, union dimfun *d, struct suedef *sue) case PTR: return( SZPOINT(ty) * mult ); case ARY: + if (d->ddim == NOOFFSET) + return 0; mult *= d->ddim; d++; continue; @@ -1035,7 +1099,7 @@ tsize(TWORD ty, union dimfun *d, struct suedef *sue) } /* - * Save string (and print it out). If wide == 'L' then wide string. + * Save string (and print it out). If wide then wide string. */ NODE * strend(int wide, char *str) @@ -1044,7 +1108,7 @@ strend(int wide, char *str) NODE *p; /* If an identical string is already emitted, just forget this one */ - if (wide == 'L') { + if (wide) { /* Do not save wide strings, at least not now */ sp = getsymtab(str, SSTRING|STEMP); } else { @@ -1061,24 +1125,24 @@ strend(int wide, char *str) sp->soffset = getlab(); sp->squal = (CON >> TSHIFT); sp->sdf = permalloc(sizeof(union dimfun)); - if (wide == 'L') { + if (wide) { sp->stype = WCHAR_TYPE+ARY; sp->ssue = MKSUE(WCHAR_TYPE); } else { -#ifdef CHAR_UNSIGNED - sp->stype = UCHAR+ARY; - sp->ssue = MKSUE(UCHAR); -#else - sp->stype = CHAR+ARY; - sp->ssue = MKSUE(CHAR); -#endif + if (funsigned_char) { + sp->stype = UCHAR+ARY; + sp->ssue = MKSUE(UCHAR); + } else { + sp->stype = CHAR+ARY; + sp->ssue = MKSUE(CHAR); + } } for (wr = sp->sname, i = 1; *wr; i++) if (*wr++ == '\\') (void)esccon(&wr); sp->sdf->ddim = i; - if (wide == 'L') + if (wide) inwstring(sp); else instring(sp); @@ -1119,12 +1183,11 @@ oalloc(struct symtab *p, int *poff ) /* * Only generate tempnodes if we are optimizing, * and only for integers, floats or pointers, - * and not if the basic type is volatile. + * and not if the type on this level is volatile. */ -/* XXX OLDSTYLE */ if (xtemps && ((p->sclass == AUTO) || (p->sclass == REGISTER)) && (p->stype < STRTY || ISPTR(p->stype)) && - !ISVOL((p->squal << TSHIFT)) && cisreg(p->stype)) { + !(cqual(p->stype, p->squal) & VOL) && cisreg(p->stype)) { NODE *tn = tempnode(0, p->stype, p->sdf, p->ssue); p->soffset = regno(tn); p->sflags |= STNODE; @@ -1209,7 +1272,7 @@ dynalloc(struct symtab *p, int *poff) astkp = 0; if (ISARY(t) && blevel == 1) { /* must take care of side effects of dynamic arg arrays */ - if (p->sdf->ddim < 0) { + if (p->sdf->ddim < 0 && p->sdf->ddim != NOOFFSET) { /* first-level array will be indexed correct */ edelay(arrstk[astkp++]); } @@ -1235,8 +1298,10 @@ dynalloc(struct symtab *p, int *poff) continue; if (df->ddim < 0) { n = arrstk[astkp++]; - nn = tempnode(0, INT, 0, MKSUE(INT)); - no = regno(nn); + do { + nn = tempnode(0, INT, 0, MKSUE(INT)); + no = regno(nn); + } while (no == -NOOFFSET); edelay(buildtree(ASSIGN, nn, n)); df->ddim = -no; @@ -1358,7 +1423,7 @@ nidcl(NODE *p, int class) sp = p->n_sp; /* check if forward decl */ - if (ISARY(sp->stype) && sp->sdf->ddim == 0) + if (ISARY(sp->stype) && sp->sdf->ddim == NOOFFSET) return; if (sp->sflags & SASG) @@ -1459,14 +1524,11 @@ typenode(NODE *p) NODE *q, *saved; TWORD type; int class, qual; - int sig, uns; + int sig, uns, cmplx; - type = class = qual = sig = uns = 0; + cmplx = type = class = qual = sig = uns = 0; saved = NIL; - if (rpole != NULL) - class = rpole->rsou == STNAME ? MOS : MOU; - for (q = p; p; p = p->n_left) { switch (p->n_op) { case CLASS: @@ -1544,11 +1606,32 @@ typenode(NODE *p) goto bad; uns = 1; break; + case COMPLEX: + cmplx = 1; + break; default: cerror("typenode"); } } } + if (cmplx) { + if (sig || uns) + goto bad; + switch (type) { + case FLOAT: + type = FCOMPLEX; + break; + case DOUBLE: + type = COMPLEX; + break; + case LDOUBLE: + type = LCOMPLEX; + break; + default: + goto bad; + } + } + if (saved && type) goto bad; if (sig || uns) { @@ -1559,10 +1642,9 @@ typenode(NODE *p) if (uns) type = ENUNSIGN(type); } -#ifdef CHAR_UNSIGNED - if (type == CHAR && sig == 0) + + if (funsigned_char && type == CHAR && sig == 0) type = UCHAR; -#endif /* free the chain */ while (q) { @@ -1789,7 +1871,7 @@ tyreduce(NODE *p, struct tylnk **tylkp, int *ntdim) nfree(p->n_right); #ifdef notdef /* XXX - check dimensions at usage time */ - if (dim.ddim == 0 && p->n_left->n_op == LB) + if (dim.ddim == NOOFFSET && p->n_left->n_op == LB) uerror("null dimension"); #endif } @@ -1859,6 +1941,22 @@ builtin_alloca(NODE *f, NODE *a) return u; } +/* + * Determine if a value is known to be constant at compile-time and + * hence that PCC can perform constant-folding on expressions involving + * that value. + */ +static NODE * +builtin_constant_p(NODE *f, NODE *a) +{ + int isconst = (a != NULL && a->n_op == ICON); + + tfree(f); + tfree(a); + + return bcon(isconst); +} + #ifndef TARGET_STDARGS static NODE * builtin_stdarg_start(NODE *f, NODE *a) @@ -1966,6 +2064,7 @@ static struct bitable { NODE *(*fun)(NODE *f, NODE *a); } bitable[] = { { "__builtin_alloca", builtin_alloca }, + { "__builtin_constant_p", builtin_constant_p }, #ifndef TARGET_STDARGS { "__builtin_stdarg_start", builtin_stdarg_start }, { "__builtin_va_arg", builtin_va_arg }, @@ -2051,7 +2150,7 @@ doacall(NODE *f, NODE *a) f->n_sp->sname[0] == '_' && f->n_sp->sname[1] == '_') { int i; - for (i = 0; i < sizeof(bitable)/sizeof(bitable[0]); i++) { + for (i = 0; i < (int)(sizeof(bitable)/sizeof(bitable[0])); i++) { if (strcmp(bitable[i].name, f->n_sp->sname) == 0) return (*bitable[i].fun)(f, a); } @@ -2062,11 +2161,14 @@ doacall(NODE *f, NODE *a) */ if (f->n_df == NULL || (al = f->n_df[0].dfun) == NULL) { if (Wimplicit_function_declaration) { - if (f->n_sp != NULL) - werror("no prototype for function '%s()'", - f->n_sp->sname); - else + if (f->n_sp != NULL) { + if (strncmp(f->n_sp->sname, + "__builtin", 9) != 0) + werror("no prototype for function " + "'%s()'", f->n_sp->sname); + } else { werror("no prototype for function pointer"); + } } /* floats must be cast to double */ if (a == NULL) @@ -2144,8 +2246,19 @@ doacall(NODE *f, NODE *a) if ((hasarray = ISARY(arrt))) arrt += (PTR-ARY); #endif - if (ISARY(type)) - type += (PTR-ARY); + /* Taking addresses of arrays are meaningless in expressions */ + /* but people tend to do that and also use in prototypes */ + /* this is mostly a problem with typedefs */ + if (ISARY(type)) { + if (ISPTR(arrt) && ISARY(DECREF(arrt))) + type = INCREF(type); + else + type += (PTR-ARY); + } else if (ISPTR(type) && !ISARY(DECREF(type)) && + ISPTR(arrt) && ISARY(DECREF(arrt))) { + type += (ARY-PTR); + type = INCREF(type); + } /* Check structs */ if (type <= BTMASK && arrt <= BTMASK) { @@ -2190,9 +2303,9 @@ incomp: uerror("incompatible types for arg %d", goto skip; /* Anything assigned a zero */ if ((type & ~BTMASK) == (arrt & ~BTMASK)) { - /* do not complain for intermixed char/uchar */ - if ((BTYPE(type) == CHAR || BTYPE(type) == UCHAR) && - (BTYPE(arrt) == CHAR || BTYPE(arrt) == UCHAR)) + /* do not complain for pointers with signedness */ + if (!Wpointer_sign && + DEUNSIGN(BTYPE(type)) == DEUNSIGN(BTYPE(arrt))) goto skip; } @@ -2238,9 +2351,9 @@ chk2(TWORD type, union dimfun *dsym, union dimfun *ddef) switch (type & TMASK) { case ARY: /* may be declared without dimension */ - if (dsym->ddim == 0) + if (dsym->ddim == NOOFFSET) dsym->ddim = ddef->ddim; - if (ddef->ddim && dsym->ddim != ddef->ddim) + if (ddef->ddim != NOOFFSET && dsym->ddim != ddef->ddim) return 1; dsym++, ddef++; break; @@ -2368,8 +2481,12 @@ uclass(int class) int fixclass(int class, TWORD type) { + extern int fun_inline; + /* first, fix null class */ if (class == SNULL) { + if (fun_inline && ISFTN(type)) + return SNULL; if (rpole) class = rpole->rsou == STNAME ? MOS : MOU; else if (blevel == 0) @@ -2398,7 +2515,7 @@ fixclass(int class, TWORD type) } if (class & FIELD) { - if (rpole && rpole->rsou != STNAME) + if (rpole && rpole->rsou != STNAME && rpole->rsou != UNAME) uerror("illegal use of field"); return(class); } @@ -2508,7 +2625,7 @@ getsymtab(char *name, int flags) int fldchk(int sz) { - if (rpole->rsou != STNAME) + if (rpole->rsou != STNAME && rpole->rsou != UNAME) uerror("field outside of structure"); if (sz < 0 || sz >= FIELD) { uerror("illegal field size"); @@ -2553,3 +2670,108 @@ scnames(int c) return( ccnames[c] ); } #endif + +void +sspinit() +{ + NODE *p; + + p = block(NAME, NIL, NIL, FTN+VOID, 0, MKSUE(VOID)); + p->n_sp = lookup("__stack_chk_fail", SNORMAL); + defid(p, EXTERN); + nfree(p); + + p = block(NAME, NIL, NIL, INT, 0, MKSUE(INT)); + p->n_sp = lookup("__stack_chk_guard", SNORMAL); + defid(p, EXTERN); + nfree(p); +} + +void +sspstart() +{ + NODE *p, *q; + + q = block(NAME, NIL, NIL, INT, 0, MKSUE(INT)); + q->n_sp = lookup("__stack_chk_guard", SNORMAL); + q = clocal(q); + + p = block(REG, NIL, NIL, INT, 0, 0); + p->n_lval = 0; + p->n_rval = FPREG; + q = block(ER, p, q, INT, 0, MKSUE(INT)); + q = clocal(q); + + p = block(NAME, NIL, NIL, INT, 0, MKSUE(INT)); + p->n_sp = lookup("__stack_chk_canary", SNORMAL); + defid(p, AUTO); + p = clocal(p); + + ecomp(buildtree(ASSIGN, p, q)); +} + +void +sspend() +{ + NODE *p, *q; + TWORD t; + int tmpnr = 0; + int lab; + + if (retlab != NOLAB) { + plabel(retlab); + retlab = getlab(); + } + + t = DECREF(cftnsp->stype); + if (t == BOOL) + t = BOOL_TYPE; + + if (t != VOID && !ISSOU(t)) { + p = tempnode(0, t, cftnsp->sdf, cftnsp->ssue); + tmpnr = regno(p); + q = block(REG, NIL, NIL, t, cftnsp->sdf, cftnsp->ssue); + q->n_rval = RETREG(t); + ecomp(buildtree(ASSIGN, p, q)); + } + + p = block(NAME, NIL, NIL, INT, 0, MKSUE(INT)); + p->n_sp = lookup("__stack_chk_canary", SNORMAL); + p = clocal(p); + + q = block(REG, NIL, NIL, INT, 0, 0); + q->n_lval = 0; + q->n_rval = FPREG; + q = block(ER, p, q, INT, 0, MKSUE(INT)); + + p = block(NAME, NIL, NIL, INT, 0, MKSUE(INT)); + p->n_sp = lookup("__stack_chk_guard", SNORMAL); + p = clocal(p); + + lab = getlab(); + cbranch(buildtree(EQ, p, q), bcon(lab)); + + p = block(NAME, NIL, NIL, FTN+VOID, 0, MKSUE(VOID)); + p->n_sp = lookup("__stack_chk_fail", SNORMAL); + p = clocal(p); + + ecomp(buildtree(UCALL, p, NIL)); + + plabel(lab); + + if (t != VOID && !ISSOU(t)) { + p = tempnode(tmpnr, t, cftnsp->sdf, cftnsp->ssue); + q = block(REG, NIL, NIL, t, cftnsp->sdf, cftnsp->ssue); + q->n_rval = RETREG(t); + ecomp(buildtree(ASSIGN, q, p)); + } +} + +/* + * Allocate on the permanent heap for inlines, otherwise temporary heap. + */ +void * +inlalloc(int size) +{ + return isinlining ? permalloc(size) : tmpalloc(size); +} diff --git a/usr.bin/pcc/ccom/scan.l b/usr.bin/pcc/ccom/scan.l index 32dd7857a7e..12feaaabaa7 100644 --- a/usr.bin/pcc/ccom/scan.l +++ b/usr.bin/pcc/ccom/scan.l @@ -1,5 +1,5 @@ %{ -/* $OpenBSD: scan.l,v 1.5 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: scan.l,v 1.6 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2002 Anders Magnusson. All rights reserved. @@ -38,6 +38,7 @@ FS (f|F|l|L) IS (u|U|l|L)* %{ +#include <stdlib.h> #include <errno.h> #include <string.h> #include <stdarg.h> @@ -58,20 +59,20 @@ int notype, parbal; #define CPP_HASH 4 #ifdef STABS -#define STABS_LINE(x) if (gflag && blevel > 1) stabs_line(x) +#define STABS_LINE(x) if (gflag && cftnsp) stabs_line(x) #else #define STABS_LINE(x) #endif #if defined(FLEX_SCANNER) && YY_FLEX_SUBMINOR_VERSION >= 31 -/* Hack to avoid unneccessary warnings */ +/* Hack to avoid unnecessary warnings */ FILE *yyget_in (void); FILE *yyget_out (void); int yyget_leng (void); char *yyget_text (void); -void yyset_in (FILE * in_str ); -void yyset_out (FILE * out_str ); +void yyset_in (FILE *); +void yyset_out (FILE *); int yyget_debug (void); -void yyset_debug (int bdebug ); +void yyset_debug (int); int yylex_destroy (void); extern int yyget_lineno (void); extern void yyset_lineno (int); @@ -95,6 +96,8 @@ extern void yyset_lineno (int); "case" { return(C_CASE); } "char" { yylval.nodep = mkty((TWORD)CHAR, 0, MKSUE(CHAR)); notype=1; return(C_TYPE); } +"_Complex" { yylval.nodep = mkty((TWORD)COMPLEX, 0, MKSUE(DOUBLE)); + notype=1; return(C_TYPE); } "const" { yylval.nodep = block(QUALIFIER, NIL, NIL, CON, 0, 0); return(C_QUALIFIER); } @@ -167,19 +170,8 @@ L?'(\\.|[^\\'])+' { yylval.nodep = charcon(); return(C_ICON); } 0[xX]{H}+"."{P}{FS}? { yylval.nodep = fhexcon(); return(C_FCON); } 0[xX]{H}+{P}{FS}? { yylval.nodep = fhexcon(); return(C_FCON); } -L?\"(\\.|[^\\"])*\" { - char *c = yytext; - int i = yyleng-2, rv; - - if (*c++ == 'L') { - c++, i--; - rv = C_WSTRING; - } else - rv = C_STRING; - c[i] = 0; /* last " */ - yylval.strp = c; - return rv; - } +L?\"(\\.|[^\\"])*\" { yylval.strp = yytext; return C_STRING; } + "..." { return(C_ELLIPSIS); } ">>=" { yylval.intval = RSEQ; return(C_ASOP); } "<<=" { yylval.intval = LSEQ; return(C_ASOP); } @@ -326,9 +318,13 @@ esccon(char **sptr) case '\"': val = '\"'; break; case 'x': val = strtoul(wr, &wr, 16); break; case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - wr--; - val = strtoul(wr, &wr, 8); + case '5': case '6': case '7': + val = wr[-1] - '0'; + if (*wr >= '0' && *wr <= '7') { + val = (val << 3) + (*wr++ - '0'); + if (*wr >= '0' && *wr <= '7') + val = (val << 3) + (*wr++ - '0'); + } break; default: val = wr[-1]; } @@ -478,15 +474,17 @@ splitup(char *str) /* count ws. at least needed array size, add 2 to terminate */ for (i = 2, s = str; *s; s++) - if (*s == ' ' || *s == '\t') + if (*s == ' ' || *s == '\t' || + *s == '(' || *s == ')' || *s == ',') i++; ary = tmpalloc(sizeof(char *)*i); - for (i = 0, s = strtok(str, " \t"); s; s = strtok(NULL, " \t")) + for (i = 0, s = strtok(str, " \t(,)"); s; s = strtok(NULL, " \t(,)")) ary[i++] = s; ary[i] = NULL; return ary; } +int pragma_allpacked; int pragma_packed, pragma_aligned; char *pragma_renamed; @@ -501,16 +499,21 @@ pragma() ary = splitup(yytext); if (ary[1] == NULL) goto bad; - if (strcmp(ary[1], "packed") == 0) { + if (strcmp(ary[1], "pack") == 0) { + pragma_allpacked = ary[2] ? atoi(ary[2]) : 0; + } else if (strcmp(ary[1], "packed") == 0) { pragma_packed = ary[2] ? atoi(ary[2]) : 1; } else if (strcmp(ary[1], "aligned") == 0) { pragma_aligned = ary[2] ? atoi(ary[2]) : 1; } else if (strcmp(ary[1], "rename") == 0) { pragma_renamed = newstring(ary[2], strlen(ary[2])); - } else if (mypragma(ary)) + } else if (mypragma(ary)) { return; - else -bad: werror("unknown pragma"); + } else { +bad: + if (Wunknown_pragmas) + werror("unknown pragma"); + } } void diff --git a/usr.bin/pcc/ccom/stabs.c b/usr.bin/pcc/ccom/stabs.c index 78765545eff..e1e05518a31 100644 --- a/usr.bin/pcc/ccom/stabs.c +++ b/usr.bin/pcc/ccom/stabs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: stabs.c,v 1.7 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: stabs.c,v 1.8 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). @@ -308,6 +308,7 @@ printtype(struct symtab *s, char *ostr, int len) void stabs_newsym(struct symtab *s) { + extern int fun_inline; char *sname; char ostr[MAXPSTR]; int suesize; @@ -358,7 +359,10 @@ stabs_newsym(struct symtab *s) cprint(savestabs, "\t.stabs \"%s:r%s\",%d,0,%d,%d\n", sname, ostr, N_RSYM, 1, s->soffset); break; - + case SNULL: + if (fun_inline) + break; + /* FALLTHROUGH */ default: cerror("fix stab_newsym; class %d", s->sclass); } @@ -389,6 +393,9 @@ cprint(int p2, char *fmt, ...) va_list ap; char *str; + if (isinlining) + return; /* XXX do not save any inline functions currently */ + va_start(ap, fmt); if (p2) { str = tmpvsprintf(fmt, ap); diff --git a/usr.bin/pcc/ccom/symtabs.c b/usr.bin/pcc/ccom/symtabs.c index 9f1b1a04cd0..f66e5b29184 100644 --- a/usr.bin/pcc/ccom/symtabs.c +++ b/usr.bin/pcc/ccom/symtabs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: symtabs.c,v 1.4 2008/01/07 21:04:47 stefan Exp $ */ +/* $OpenBSD: symtabs.c,v 1.5 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -29,6 +29,8 @@ #include "pass1.h" +#include <stdint.h> + /* * These definitions are used in the patricia tree that stores * the strings. @@ -175,7 +177,7 @@ int numsyms[NSTYPES]; * Returns a struct symtab. */ struct symtab * -lookup(char *key, int ttype) +lookup(char *key, int stype) { struct symtab *sym; struct tree *w, *new, *last; @@ -183,7 +185,7 @@ lookup(char *key, int ttype) int type, uselvl; intptr_t ix, match, code = (intptr_t)key; - type = ttype & SMASK; + type = stype & SMASK; uselvl = (blevel > 0 && type != SSTRING); /* @@ -197,15 +199,15 @@ lookup(char *key, int ttype) switch (numsyms[type]) { case 0: - if (ttype & SNOCREAT) + if (stype & SNOCREAT) return NULL; if (uselvl) { - sym = getsymtab(key, ttype|STEMP); + sym = getsymtab(key, stype|STEMP); sym->snext = tmpsyms[type]; tmpsyms[type] = sym; return sym; } - sympole[type] = (struct tree *)getsymtab(key, ttype); + sympole[type] = (struct tree *)getsymtab(key, stype); numsyms[type]++; return (struct symtab *)sympole[type]; @@ -233,7 +235,7 @@ lookup(char *key, int ttype) ix = code ^ match; if (ix == 0) return sym; - else if (ttype & SNOCREAT) + else if (stype & SNOCREAT) return NULL; #ifdef PCC_DEBUG @@ -246,7 +248,7 @@ lookup(char *key, int ttype) * Insert into the linked list, if feasible. */ if (uselvl) { - sym = getsymtab(key, ttype|STEMP); + sym = getsymtab(key, stype|STEMP); sym->snext = tmpsyms[type]; tmpsyms[type] = sym; return sym; @@ -258,17 +260,17 @@ lookup(char *key, int ttype) * This could be optimized by adding a remove routine, but it * may be more trouble than it is worth. */ - if (ttype == (STEMP|SNORMAL)) - ttype = SNORMAL; + if (stype == (STEMP|SNORMAL)) + stype = SNORMAL; for (cix = 0; (ix & 1) == 0; ix >>= 1, cix++) ; - new = ttype & STEMP ? tmpalloc(sizeof(struct tree)) : + new = stype & STEMP ? tmpalloc(sizeof(struct tree)) : permalloc(sizeof(struct tree)); bit = (code >> cix) & 1; new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); - new->lr[bit] = (struct tree *)getsymtab(key, ttype); + new->lr[bit] = (struct tree *)getsymtab(key, stype); if (numsyms[type]++ == 1) { new->lr[!bit] = sympole[type]; new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); @@ -348,6 +350,10 @@ hide(struct symtab *sym) new = getsymtab(sym->sname, typ|STEMP); new->snext = tmpsyms[typ]; tmpsyms[typ] = new; + + if (Wshadow) + werror("declaration of '%s' shadows previous", sym->sname); + #ifdef PCC_DEBUG if (ddebug) printf("\t%s hidden at level %d (%p -> %p)\n", diff --git a/usr.bin/pcc/ccom/trees.c b/usr.bin/pcc/ccom/trees.c index e7bd9a87f8a..bfe42901c18 100644 --- a/usr.bin/pcc/ccom/trees.c +++ b/usr.bin/pcc/ccom/trees.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trees.c,v 1.14 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: trees.c,v 1.15 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -197,9 +197,11 @@ buildtree(int o, NODE *l, NODE *r) case ER: case LS: case RS: - if( conval( l, o, r ) ) { - nfree(r); - return(l); + if (!ISPTR(l->n_type) && !ISPTR(r->n_type)) { + if( conval( l, o, r ) ) { + nfree(r); + return(l); + } } break; } @@ -296,51 +298,7 @@ runtime: switch(o){ case NAME: - sp = spname; - if (sp->sflags & STNODE) { - /* Generated for optimizer */ - p->n_op = TEMP; - p->n_type = sp->stype; - p->n_sue = sp->ssue; - p->n_df = sp->sdf; - p->n_rval = sp->soffset; - break; - } - -#ifdef GCC_COMPAT - /* Get a label name */ - if (sp->sflags == SLBLNAME) { - p->n_type = VOID; - p->n_sue = MKSUE(VOID); - p->n_lval = 0; - p->n_sp = sp; - break; - } else -#endif - if (sp->stype == UNDEF) { - uerror("%s undefined", sp->sname); - /* make p look reasonable */ - p->n_type = INT; - p->n_sue = MKSUE(INT); - p->n_df = NULL; - p->n_sp = sp; - p->n_lval = 0; - defid(p, SNULL); - break; - } - p->n_type = sp->stype; - p->n_qual = sp->squal; - p->n_df = sp->sdf; - p->n_sue = sp->ssue; - p->n_lval = 0; - p->n_sp = sp; - if (sp->sclass == MOE) { - p->n_op = ICON; - p->n_lval = sp->soffset; - p->n_df = NULL; - p->n_sp = NULL; - } - break; + cerror("buildtree NAME"); case STREF: /* p->x turned into *(p+offset) */ @@ -352,16 +310,20 @@ runtime: break; } - if ((sp = l->n_sue->sylnk) == NULL) + if ((sp = l->n_sue->sylnk) == NULL) { uerror("undefined struct or union"); + break; + } name = r->n_name; for (; sp != NULL; sp = sp->snext) { if (sp->sname == name) break; } - if (sp == NULL) + if (sp == NULL) { uerror("member '%s' not declared", name); + break; + } r->n_sp = sp; p = stref(p); @@ -541,6 +503,55 @@ runtime: } /* + * Build a name node based on a symtab entry. + * broken out from buildtree(). + */ +NODE * +nametree(struct symtab *sp) +{ + NODE *p; + + p = block(NAME, NIL, NIL, sp->stype, sp->sdf, sp->ssue); + p->n_qual = sp->squal; + p->n_sp = sp; + +#ifndef NO_C_BUILTINS + if (sp->sname[0] == '_' && strncmp(sp->sname, "__builtin_", 10) == 0) + return p; /* do not touch builtins here */ + +#endif + + if (sp->sflags & STNODE) { + /* Generated for optimizer */ + p->n_op = TEMP; + p->n_rval = sp->soffset; + } + +#ifdef GCC_COMPAT + /* Get a label name */ + if (sp->sflags == SLBLNAME) { + p->n_type = VOID; + p->n_sue = MKSUE(VOID); + } +#endif + if (sp->stype == UNDEF) { + uerror("%s undefined", sp->sname); + /* make p look reasonable */ + p->n_type = INT; + p->n_sue = MKSUE(INT); + p->n_df = NULL; + defid(p, SNULL); + } + if (sp->sclass == MOE) { + p->n_op = ICON; + p->n_lval = sp->soffset; + p->n_df = NULL; + p->n_sp = NULL; + } + return clocal(p); +} + +/* * Do a conditional branch. */ void @@ -797,7 +808,8 @@ chkpun(NODE *p) t1 = DECREF(t1); t2 = DECREF(t2); } - werror("illegal pointer combination"); + if (Wpointer_sign) + werror("illegal pointer combination"); } } @@ -1159,6 +1171,10 @@ tymatch(p) register NODE *p; { t2 = DEUNSIGN(t2); } + if (Wsign_compare && clogop(o) && t1 == t2 && lu != ru && + p->n_left->n_op != ICON && p->n_right->n_op != ICON) + werror("comparison between signed and unsigned"); + #if 0 if ((t1 == CHAR || t1 == SHORT) && o!= RETURN) t1 = INT; @@ -1566,6 +1582,8 @@ doszof(NODE *p) df = p->n_df; ty = p->n_type; while (ISARY(ty)) { + if (df->ddim == NOOFFSET) + uerror("sizeof of incomplete type"); rv = buildtree(MUL, rv, df->ddim >= 0 ? bcon(df->ddim) : tempnode(-df->ddim, INT, 0, MKSUE(INT))); df++; @@ -1933,7 +1951,7 @@ delasgop(NODE *p) if (p->n_op == INCR || p->n_op == DECR) { /* * Rewrite x++ to (x += 1) -1; and deal with it further down. - * Pass2 will remove -1 if unneccessary. + * Pass2 will remove -1 if unnecessary. */ q = ccopy(p); tfree(p->n_left); @@ -1991,7 +2009,8 @@ ecomp(NODE *p) fwalk(p, eprint, 0); #endif if (!reached) { - werror("statement not reached"); + if (Wunreachable_code) + werror("statement not reached"); reached = 1; } p = optim(p); @@ -2003,6 +2022,7 @@ ecomp(NODE *p) ecode(p); } + #if defined(MULTIPASS) void p2tree(NODE *p) @@ -2075,6 +2095,17 @@ p2tree(NODE *p) p2tree(p->n_right); } #else +static char * +sptostr(struct symtab *sp) +{ + char *cp = inlalloc(32); + int n = sp->soffset; + if (n < 0) + n = -n; + snprintf(cp, 32, LABFMT, n); + return cp; +} + void p2tree(NODE *p) { @@ -2095,16 +2126,16 @@ p2tree(NODE *p) q->sflags == SLBLNAME || #endif q->sclass == ILABEL) { - char *cp = (isinlining ? - permalloc(32) : tmpalloc(32)); - int n = q->soffset; - if (n < 0) - n = -n; - snprintf(cp, 32, LABFMT, n); + p->n_name = sptostr(q); + } else if (!kflag) { + char *name = exname(q->soname); + int n = strlen(name) + 1; + char *cp = inlalloc(n); + + strlcpy(cp, name, n); p->n_name = cp; - } else { + } else p->n_name = q->soname; - } } else p->n_name = ""; break; @@ -2130,6 +2161,18 @@ p2tree(NODE *p) p->n_stsize = (tsize(STRTY, p->n_left->n_df, p->n_left->n_sue)+SZCHAR-1)/SZCHAR; p->n_stalign = talign(STRTY,p->n_left->n_sue)/SZCHAR; + /* FALLTHROUGH */ + case CALL: + case UCALL: + if (callop(p->n_op) && p->n_left->n_op == ICON && + (q = p->n_left->n_sp) != NULL && q->sclass == SNULL && + (q->sflags & SINLINE)) { + /* call to inline ftns uses L-style labels */ + p->n_left->n_name = sptostr(q); + if (ty == BITYPE) + p2tree(p->n_right); + return; + } break; case XARG: @@ -2219,7 +2262,7 @@ send_passt(int type, ...) else sz = sizeof(struct interpass); - ip = isinlining ? permalloc(sz) : tmpalloc(sz); + ip = inlalloc(sz); ip->type = type; ip->lineno = lineno; switch (type) { @@ -2249,7 +2292,9 @@ send_passt(int type, ...) break; case IP_ASM: if (blevel == 0) { /* outside function */ - printf("\t%s\n", va_arg(ap, char *)); + printf("\t"); + printf("%s", va_arg(ap, char *)); + printf("\n"); va_end(ap); defloc(NULL); return; @@ -2260,6 +2305,7 @@ send_passt(int type, ...) cerror("bad send_passt type %d", type); } va_end(ap); + pass1_lastchance(ip); /* target-specific info */ if (isinlining) inline_addarg(ip); else diff --git a/usr.bin/pcc/config.h b/usr.bin/pcc/config.h index 47f4ced9ead..c2b9e47d052 100644 --- a/usr.bin/pcc/config.h +++ b/usr.bin/pcc/config.h @@ -1,8 +1,12 @@ -/* $OpenBSD: config.h,v 1.5 2008/04/11 20:45:51 stefan Exp $ */ +/* $OpenBSD: config.h,v 1.6 2008/08/17 18:40:12 ragge Exp $ */ #define PCC_MAJOR 0 #define PCC_MINOR 9 #define PCC_MINORMINOR 9 -#define VERSSTR "pcc 0.9.9" +#define PACKAGE_VERSION "0.9.9" +#define VERSSTR "pcc " PACKAGE_VERSION +#define PACKAGE_STRING VERSSTR +#define TARGOS OpenBSD #define YYTEXT_POINTER 1 +#define HAVE_CPP_VARARG_MACRO_GCC diff --git a/usr.bin/pcc/cpp/cpp.1 b/usr.bin/pcc/cpp/cpp.1 index 0c849dc8989..9d8f9728389 100644 --- a/usr.bin/pcc/cpp/cpp.1 +++ b/usr.bin/pcc/cpp/cpp.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: cpp.1,v 1.5 2008/04/11 20:55:22 stefan Exp $ +.\" $OpenBSD: cpp.1,v 1.6 2008/08/17 18:40:13 ragge Exp $ ."\ .\" Copyright (c) 2007 Jeremy C. Reed <reed@reedmedia.net> .\" @@ -102,6 +102,9 @@ Include a file at the beginning by using Generate dependencies for .Xr make 1 . .\" TODO: explain and show example? +.It Fl P +Inhibit generation of line markers. This is sometimes useful when +running the preprocessor on something other than C code. .It Fl S Ar path Add .Ar path diff --git a/usr.bin/pcc/cpp/cpp.c b/usr.bin/pcc/cpp/cpp.c index 095b75da475..3e435aca41b 100644 --- a/usr.bin/pcc/cpp/cpp.c +++ b/usr.bin/pcc/cpp/cpp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpp.c,v 1.9 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: cpp.c,v 1.10 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). @@ -99,12 +99,15 @@ int dflag; /* debug printouts */ #define DDPRINT(x) #endif +#define GCC_VARI + int ofd; usch outbuf[CPPBUF]; int obufp, istty, inmac; -int Cflag, Mflag, dMflag; +int Cflag, Mflag, dMflag, Pflag; usch *Mfile; struct initar *initar; +int readmac; /* avoid recursion */ struct recur { @@ -145,6 +148,7 @@ usch *stringbuf = sbf; * 1-> - number of args. */ +#define GCCARG 0xfd /* has gcc varargs that may be replaced with 0 */ #define VARG 0xfe /* has varargs */ #define OBJCT 0xff #define WARN 1 /* SOH, not legal char */ @@ -152,6 +156,8 @@ usch *stringbuf = sbf; #define SNUFF 3 /* ETX, not legal char */ #define NOEXP 4 /* EOT, not legal char */ #define EXPAND 5 /* ENQ, not legal char */ +#define PRAGS 6 /* start of converted pragma */ +#define PRAGE 14 /* end of converted pragma */ /* args for lookup() */ #define FIND 0 @@ -164,6 +170,9 @@ void include(void); void line(void); void flbuf(void); void usage(void); +usch *xstrdup(char *str); +usch *prtprag(usch *opb); + int main(int argc, char **argv) @@ -173,7 +182,7 @@ main(int argc, char **argv) struct symtab *nl; register int ch; - while ((ch = getopt(argc, argv, "CD:I:MS:U:d:i:tvV?")) != -1) + while ((ch = getopt(argc, argv, "CD:I:MPS:U:d:i:tvV?")) != -1) switch (ch) { case 'C': /* Do not discard comments */ Cflag++; @@ -195,6 +204,10 @@ main(int argc, char **argv) Mflag++; break; + case 'P': /* Inhibit generation of line numbers */ + Pflag++; + break; + case 'S': case 'I': if ((w = calloc(sizeof(struct incs), 1)) == NULL) @@ -315,6 +328,7 @@ gotident(struct symtab *nl) thisnl = NULL; slow = 1; + readmac++; base = osp = stringbuf; goto found; @@ -377,6 +391,10 @@ found: if (nl == 0 || subst(nl, NULL) == 0) { thisnl = NULL; break; + case CMNT: + getcmnt(); + break; + case STRING: case '\n': case NUMBER: @@ -394,11 +412,12 @@ found: if (nl == 0 || subst(nl, NULL) == 0) { } if (thisnl == NULL) { slow = 0; + readmac--; savch(0); return base; } } - error("preamture EOF"); + error("premature EOF"); /* NOTREACHED */ return NULL; /* XXX gcc */ } @@ -550,6 +569,55 @@ definp(void) } void +getcmnt(void) +{ + int c; + + savstr((usch *)yytext); + for (;;) { + c = cinput(); + if (c == '*') { + c = cinput(); + if (c == '/') { + savstr((usch *)"*/"); + return; + } + cunput(c); + c = '*'; + } + savch(c); + } +} + +/* + * Compare two replacement lists, taking in account comments etc. + */ +static int +cmprepl(usch *o, usch *n) +{ + for (; *o; o--, n--) { + /* comment skip */ + if (*o == '/' && o[-1] == '*') { + while (*o != '*' || o[-1] != '/') + o--; + o -= 2; + } + if (*n == '/' && n[-1] == '*') { + while (*n != '*' || n[-1] != '/') + n--; + n -= 2; + } + while (*o == ' ' || *o == '\t') + o--; + while (*n == ' ' || *n == '\t') + n--; + if (*o != *n) + return 1; + } + return 0; +} + +void define() { struct symtab *np; @@ -557,7 +625,10 @@ define() int c, i, redef; int mkstr = 0, narg = -1; int ellips = 0; - size_t len; +#ifdef GCC_VARI + usch *gccvari = NULL; + int wascon; +#endif if (flslvl) return; @@ -571,6 +642,7 @@ define() np = lookup((usch *)yytext, ENTER); redef = np->value != NULL; + readmac = 1; sbeg = stringbuf; if ((c = yylex()) == '(') { narg = 0; @@ -591,15 +663,20 @@ define() if (!strcmp((char *) args[i], yytext)) error("Duplicate macro " "parameter \"%s\"", yytext); - len = strlen(yytext); - args[narg] = alloca(len+1); - strlcpy((char *)args[narg], yytext, len+1); - narg++; + args[narg++] = xstrdup(yytext); if ((c = definp()) == ',') { if ((c = definp()) == ')') goto bad; continue; } +#ifdef GCC_VARI + if (c == ELLIPS) { + if (definp() != ')') + goto bad; + gccvari = args[--narg]; + break; + } +#endif if (c == ')') break; } @@ -622,6 +699,10 @@ define() /* parse replacement-list, substituting arguments */ savch('\0'); while (c != '\n') { +#ifdef GCC_VARI + wascon = 0; +loop: +#endif switch (c) { case WSPACE: /* remove spaces if it surrounds a ## directive */ @@ -633,6 +714,12 @@ define() savch(CONC); if ((c = yylex()) == WSPACE) c = yylex(); +#ifdef GCC_VARI + if (c == '\n') + break; + wascon = 1; + goto loop; +#endif } continue; @@ -641,7 +728,14 @@ define() savch(CONC); if ((c = yylex()) == WSPACE) c = yylex(); +#ifdef GCC_VARI + if (c == '\n') + break; + wascon = 1; + goto loop; +#else continue; +#endif case MKSTR: if (narg < 0) { @@ -666,6 +760,16 @@ define() if (strcmp(yytext, (char *)args[i]) == 0) break; if (i == narg) { +#ifdef GCC_VARI + if (gccvari && + strcmp(yytext, (char *)gccvari) == 0) { + savch(wascon ? GCCARG : VARG); + savch(WARN); + if (mkstr) + savch(SNUFF), mkstr = 0; + break; + } +#endif if (mkstr) error("not argument"); goto id; @@ -685,12 +789,17 @@ define() savch(SNUFF), mkstr = 0; break; + case CMNT: /* save comments */ + getcmnt(); + break; + default: id: savstr((usch *)yytext); break; } c = yylex(); } + readmac = 0; /* remove trailing whitespace */ while (stringbuf > sbeg) { if (stringbuf[-1] == ' ' || stringbuf[-1] == '\t') @@ -701,18 +810,19 @@ id: savstr((usch *)yytext); else break; } +#ifdef GCC_VARI + if (gccvari) { + savch(narg); + savch(VARG); + } else +#endif if (ellips) { savch(narg); savch(VARG); } else savch(narg < 0 ? OBJCT : narg); if (redef) { - usch *o = np->value, *n = stringbuf-1; - - /* Redefinition to identical replacement-list is allowed */ - while (*o && *o == *n) - o--, n--; - if (*o || *o != *n) + if (cmprepl(np->value, stringbuf-1)) error("%s redefined\nprevious define: %s:%d", np->namep, np->file, np->line); stringbuf = sbeg; /* forget this space */ @@ -740,6 +850,8 @@ id: savstr((usch *)yytext); } #endif slow = 0; + for (i = 0; i < narg; i++) + free(args[i]); return; bad: error("bad define"); @@ -801,8 +913,7 @@ pragoper(void) usch *opb; int t, plev; - slow = 1; - putstr((usch *)"\n#pragma "); + slow++; if ((t = yylex()) == WSPACE) t = yylex(); if (t != '(') @@ -828,23 +939,19 @@ pragoper(void) cunput('\n'); while (stringbuf > opb) cunput(*--stringbuf); + savch(PRAGS); while ((t = yylex()) != '\n') { if (t == WSPACE) continue; if (t != STRING) goto bad; - opb = (usch *)yytext; - if (*opb++ == 'L') - opb++; - while ((t = *opb++) != '\"') { - if (t == '\\' && (*opb == '\"' || *opb == '\\')) - t = *opb++; - putch(t); - } + savstr((usch *)yytext); } - putch('\n'); - prtline(); + savch(PRAGE); + while (stringbuf > opb) + cunput(*--stringbuf); + slow--; return; bad: error("bad pragma operator"); } @@ -946,7 +1053,6 @@ expmac(struct recur *rp) struct symtab *nl; int c, noexp = 0, orgexp; usch *och, *stksv; - extern int yyleng; #ifdef CPP_DEBUG if (dflag) { @@ -958,6 +1064,7 @@ expmac(struct recur *rp) } } #endif + readmac++; while ((c = yylex()) != WARN) { switch (c) { case NOEXP: noexp++; break; @@ -1018,6 +1125,8 @@ expmac(struct recur *rp) unpstr((usch *)yytext); if (orgexp == -1) cunput(EXPAND); + else if (orgexp == -2) + cunput(EXPAND), cunput(EXPAND); else if (orgexp == 1) cunput(NOEXP); unpstr(och); @@ -1048,8 +1157,7 @@ expmac(struct recur *rp) error("bad noexp %d", noexp); stksv = NULL; if ((c = yylex()) == WSPACE) { - stksv = alloca(yyleng+1); - strlcpy((char *)stksv, yytext, yyleng+1); + stksv = xstrdup(yytext); c = yylex(); } /* only valid for expansion if fun macro */ @@ -1066,6 +1174,12 @@ expmac(struct recur *rp) unpstr(stksv); savstr(nl->namep); } + if (stksv) + free(stksv); + break; + + case CMNT: + getcmnt(); break; case STRING: @@ -1087,6 +1201,7 @@ def: default: } if (noexp) error("expmac noexp=%d", noexp); + readmac--; DPRINT(("return from expmac\n")); } @@ -1113,7 +1228,8 @@ expdef(vp, rp, gotwarn) ellips = 1; } else narg = vp[1]; - args = alloca(sizeof(usch *) * (narg+ellips)); + if ((args = malloc(sizeof(usch *) * (narg+ellips))) == NULL) + error("expdef: out of mem"); /* * read arguments and store them on heap. @@ -1142,8 +1258,14 @@ expdef(vp, rp, gotwarn) savstr((usch *)yytext); while ((c = yylex()) == '\n') savch('\n'); + while (c == CMNT) { + getcmnt(); + c = yylex(); + } if (c == EXPAND) instr = 0; + if (c == 0) + error("eof in macro"); } while (args[i] < stringbuf && (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')) @@ -1216,6 +1338,14 @@ expdef(vp, rp, gotwarn) if (sp[-1] == VARG) { bp = ap = args[narg]; sp--; +#ifdef GCC_VARI + } else if (sp[-1] == GCCARG) { + ap = args[narg]; + if (ap[0] == 0) + ap = (usch *)"0"; + bp = ap; + sp--; +#endif } else bp = ap = args[(int)*--sp]; if (sp[2] != CONC && !snuff && sp[-1] != CONC) { @@ -1261,6 +1391,7 @@ expdef(vp, rp, gotwarn) /* scan the input buffer (until WARN) and save result on heap */ expmac(rp); + free(args); } usch * @@ -1324,6 +1455,10 @@ void putstr(usch *s) { for (; *s; s++) { + if (*s == PRAGS) { + s = prtprag(s); + continue; + } outbuf[obufp++] = *s; if (obufp == CPPBUF || (istty && *s == '\n')) flbuf(); @@ -1549,3 +1684,41 @@ lookup(usch *key, int enterf) return (struct symtab *)new->lr[bit]; } +usch * +xstrdup(char *str) +{ + size_t len = strlen(str)+1; + usch *rv; + + if ((rv = malloc(len)) == NULL) + error("xstrdup: out of mem"); + strlcpy((char *)rv, str, len); + return rv; +} + +usch * +prtprag(usch *s) +{ + int ch; + + s++; + putstr((usch *)"\n#pragma "); + while (*s != PRAGE) { + if (*s == 'L') + s++; + if (*s == '\"') { + s++; + while ((ch = *s++) != '\"') { + if (ch == '\\' && (*s == '\"' || *s == '\\')) + ch = *s++; + putch(ch); + } + } else { + s++; + putch(*s); + } + } + putstr((usch *)"\n"); + prtline(); + return ++s; +} diff --git a/usr.bin/pcc/cpp/cpp.h b/usr.bin/pcc/cpp/cpp.h index 8b94abe9ac9..d0a84fb4935 100644 --- a/usr.bin/pcc/cpp/cpp.h +++ b/usr.bin/pcc/cpp/cpp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpp.h,v 1.5 2007/10/21 18:58:02 otto Exp $ */ +/* $OpenBSD: cpp.h,v 1.6 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). @@ -43,7 +43,7 @@ extern int trulvl; extern int flslvl; extern int elflvl; extern int elslvl; -extern int tflag, Cflag; +extern int tflag, Cflag, Pflag; extern int Mflag, dMflag; extern usch *Mfile; extern int ofd; @@ -72,6 +72,7 @@ struct includ { int infil; usch *curptr; usch *maxread; + usch *ostr; usch *buffer; usch bbuf[NAMEMAX+CPPBUF+1]; } *ifiles; @@ -134,6 +135,13 @@ void line(void); usch *sheap(char *fmt, ...); void xwarning(usch *); void xerror(usch *); +#ifdef HAVE_CPP_VARARG_MACRO_GCC #define warning(...) xwarning(sheap(__VA_ARGS__)) #define error(...) xerror(sheap(__VA_ARGS__)) +#else +#define warning printf +#define error printf +#endif void expmac(struct recur *); +int cinput(void); +void getcmnt(void); diff --git a/usr.bin/pcc/cpp/cpy.y b/usr.bin/pcc/cpp/cpy.y index c4ff14092f4..a49a9c8ab3f 100644 --- a/usr.bin/pcc/cpp/cpy.y +++ b/usr.bin/pcc/cpp/cpy.y @@ -1,4 +1,4 @@ -/* $OpenBSD: cpy.y,v 1.4 2007/10/21 18:58:02 otto Exp $ */ +/* $OpenBSD: cpy.y,v 1.5 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). @@ -87,7 +87,7 @@ int setd(int l, int r); /* * The following terminals are not used in the yacc code. */ -%term STRING FPOINT WSPACE VA_ARGS CONCAT MKSTR ELLIPS +%term STRING FPOINT WSPACE VA_ARGS CONCAT MKSTR ELLIPS CMNT %left ',' %right '?' ':' diff --git a/usr.bin/pcc/cpp/scanner.l b/usr.bin/pcc/cpp/scanner.l index e5dca5e9f26..c22e08a54b4 100644 --- a/usr.bin/pcc/cpp/scanner.l +++ b/usr.bin/pcc/cpp/scanner.l @@ -1,5 +1,5 @@ %{ -/* $OpenBSD: scanner.l,v 1.9 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: scanner.l,v 1.10 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2004 Anders Magnusson. All rights reserved. @@ -40,7 +40,7 @@ %{ static void cvtdig(int rad); -static int charcon(void); +static int charcon(usch *); static void elsestmt(void); static void ifdefstmt(void); static void ifndefstmt(void); @@ -83,15 +83,17 @@ yyinput(char *b, int m) } #undef YY_INPUT #undef YY_BUF_SIZE -#define YY_BUF_SIZE 32768 +#define YY_BUF_SIZE (8*65536) #define YY_INPUT(b,r,m) (r = yyinput(b, m)) +#ifdef HAVE_CPP_VARARG_MACRO_GCC #define fprintf(x, ...) error(__VA_ARGS__) +#endif #define ECHO putstr((usch *)yytext) #undef fileno #define fileno(x) 0 #if YY_FLEX_SUBMINOR_VERSION >= 31 -/* Hack to avoid unneccessary warnings */ +/* Hack to avoid unnecessary warnings */ FILE *yyget_in (void); FILE *yyget_out (void); int yyget_leng (void); @@ -122,7 +124,7 @@ FS (f|F|l|L) IS (u|U|l|L)* WS [\t ] -%s IFR CONTR DEF +%s IFR CONTR DEF COMMENT %% @@ -177,7 +179,12 @@ WS [\t ] return NUMBER; } -[1-9][0-9]* { if (slow && !YYSTATE) return IDENT; scale = 10; goto num; } +[0-9][0-9]* { + if (slow && !YYSTATE) + return IDENT; + scale = yytext[0] == '0' ? 8 : 10; + goto num; + } 0[xX]{H}+{IS}? { scale = 16; num: if (YYSTATE == IFR) @@ -186,11 +193,16 @@ WS [\t ] } 0{D}+{IS}? { scale = 8; goto num; } {D}+{IS}? { scale = 10; goto num; } -L?'(\\.|[^\\'])+' { if (YYSTATE) { +'(\\.|[^\\'])+' { + if (YYSTATE || slow) { yylval.node.op = NUMBER; - yylval.node.nd_val = charcon(); + yylval.node.nd_val = charcon((usch *)yytext); + return (NUMBER); } - PRTOUT(NUMBER); + if (tflag) + yyless(1); + if (!flslvl) + putstr((usch *)yytext); } <IFR>. { return yytext[0]; } @@ -225,13 +237,19 @@ L?'(\\.|[^\\'])+' { if (YYSTATE) { "//".*$ { /* if (tflag) yyless(..) */ - if (Cflag && !flslvl) + if (Cflag && !flslvl && !slow) putstr((usch *)yytext); else if (!flslvl) putch(' '); } "/*" { int c, wrn; - if (Cflag && !flslvl) + int prtcm = Cflag && !flslvl && !slow; + extern int readmac; + + if (Cflag && !flslvl && readmac) + return CMNT; + + if (prtcm) putstr((usch *)yytext); wrn = 0; more: while ((c = input()) && c != '*') { @@ -239,20 +257,18 @@ L?'(\\.|[^\\'])+' { if (YYSTATE) { putch(c), ifiles->lineno++; else if (c == 1) /* WARN */ wrn = 1; - else if (Cflag && !flslvl) + else if (prtcm) putch(c); } if (c == 0) return 0; - if (Cflag && !flslvl) + if (prtcm) putch(c); if ((c = input()) && c != '/') { - if (Cflag && !flslvl) - putch('*'); unput(c); goto more; } - if (Cflag && !flslvl) + if (prtcm) putch(c); if (c == 0) return 0; @@ -296,7 +312,22 @@ L?\"(\\.|[^\\"])*\" { PRTOUT(STRING); } xx: ; } -. { PRTOUT(yytext[0]); } +. { + if (YYSTATE || slow) + return yytext[0]; + if (yytext[0] == 6) { /* PRAGS */ + usch *obp = stringbuf; + extern usch *prtprag(usch *); + *stringbuf++ = yytext[0]; + do { + *stringbuf = input(); + } while (*stringbuf++ != 14); + prtprag(obp); + stringbuf = obp; + } else { + PRTOUT(yytext[0]); + } + } %% @@ -424,12 +455,8 @@ pushfile(usch *file) slow = 0; if (file != NULL) { - if ((ic->infil = open((char *)file, O_RDONLY)) < 0) { - if (errno != ENOENT) - error("Cannot open '%s'. %s", file, - strerror(errno)); + if ((ic->infil = open((char *)file, O_RDONLY)) < 0) return -1; - } ic->orgfn = ic->fname = file; if (++inclevel > MAX_INCLEVEL) error("Limit for nested includes exceeded"); @@ -480,7 +507,7 @@ prtline() s = sheap("%s: %s\n", Mfile, ifiles->fname); write(ofd, s, strlen((char *)s)); } - } else + } else if (!Pflag) putstr(sheap("# %d \"%s\"\n", ifiles->lineno, ifiles->fname)); stringbuf = os; } @@ -490,7 +517,7 @@ cunput(int c) { #ifdef CPP_DEBUG extern int dflag; - if (dflag)printf(": '%c'(%d)", c, c); + if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c); #endif unput(c); } @@ -544,14 +571,11 @@ cvtdig(int rad) } static int -charcon(void) +charcon(usch *p) { - usch *p = (usch *)yytext; int val, c; - if (*p == 'L') - p++; - p++; /* first ' */ + p++; /* skip first ' */ val = 0; if (*p++ == '\\') { switch (*p++) { @@ -749,8 +773,20 @@ storepb(void) usch *opb = stringbuf; int c; - while ((c = input()) != '\n') + while ((c = input()) != '\n') { + if (c == '/') { + if ((c = input()) == '*') { + /* ignore comments here whatsoever */ + usch *g = stringbuf; + getcmnt(); + stringbuf = g; + continue; + } + unput(c); + c = '/'; + } savch(c); + } cunput('\n'); savch(0); fixdefined(opb); /* XXX can fail if #line? */ @@ -876,3 +912,9 @@ badop(const char *op) { error("invalid operator in preprocessor expression: %s", op); } + +int +cinput() +{ + return input(); +} diff --git a/usr.bin/pcc/i386/code.c b/usr.bin/pcc/i386/code.c index 11f951ff1f2..249d0411412 100644 --- a/usr.bin/pcc/i386/code.c +++ b/usr.bin/pcc/i386/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.8 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: code.c,v 1.9 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -29,6 +29,8 @@ # include "pass1.h" +int lastloc = -1; + /* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. @@ -37,8 +39,11 @@ void defloc(struct symtab *sp) { extern char *nextsect; +#if defined(ELFABI) || defined(PECOFFABI) static char *loctbl[] = { "text", "data", "section .rodata" }; - static int lastloc = -1; +#elif defined(MACHOABI) + static char *loctbl[] = { "text", "data", "const_data" }; +#endif TWORD t; int s; @@ -67,9 +72,13 @@ defloc(struct symtab *sp) if (t > UCHAR) printf(" .align %d\n", t > USHORT ? 4 : 2); if (sp->sclass == EXTDEF) - printf(" .globl %s\n", sp->soname); + printf(" .globl %s\n", exname(sp->soname)); +#if defined(ELFABI) + if (ISFTN(t)) + printf("\t.type %s,@function\n", exname(sp->soname)); +#endif if (sp->slevel == 0) - printf("%s:\n", sp->soname); + printf("%s:\n", exname(sp->soname)); else printf(LABFMT ":\n", sp->soffset); } @@ -105,6 +114,10 @@ efcode() void bfcode(struct symtab **sp, int cnt) { +#ifdef os_win32 + extern int argstacksize; +#endif + struct symtab *sp2; extern int gotnr; NODE *n, *p; int i; @@ -114,6 +127,26 @@ bfcode(struct symtab **sp, int cnt) for (i = 0; i < cnt; i++) sp[i]->soffset += SZPOINT(INT); } + +#ifdef os_win32 + /* + * Count the arguments and mangle name in symbol table as a callee. + */ + argstacksize = 0; + if (cftnsp->sflags & SSTDCALL) { + char buf[64]; + for (i = 0; i < cnt; i++) { + TWORD t = sp[i]->stype; + if (t == STRTY || t == UNIONTY) + argstacksize += sp[i]->ssue->suesize; + else + argstacksize += szty(t) * SZINT / SZCHAR; + } + snprintf(buf, 64, "%s@%d", cftnsp->soname, argstacksize); + cftnsp->soname = newstring(buf, strlen(buf)); + } +#endif + if (kflag) { /* Put ebx in temporary */ n = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); @@ -130,9 +163,9 @@ bfcode(struct symtab **sp, int cnt) if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY || cisreg(sp[i]->stype) == 0) continue; - spname = sp[i]; + sp2 = sp[i]; n = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->ssue); - n = buildtree(ASSIGN, n, buildtree(NAME, 0, 0)); + n = buildtree(ASSIGN, n, nametree(sp2)); sp[i]->soffset = regno(n->n_left); sp[i]->sflags |= STNODE; ecomp(n); @@ -149,16 +182,54 @@ bccode() SETOFF(autooff, SZINT); } +#if defined(MACHOABI) +struct stub stublist; +struct stub nlplist; +#endif + /* called just before final exit */ /* flag is 1 if errors, 0 if none */ void ejobcode(int flag ) { +#if defined(MACHOABI) + /* + * iterate over the stublist and output the PIC stubs +` */ + if (kflag) { + struct stub *p; + + DLIST_FOREACH(p, &stublist, link) { + printf("\t.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5\n"); + printf("L%s$stub:\n", p->name); + printf("\t.indirect_symbol %s\n", exname(p->name)); + printf("\thlt ; hlt ; hlt ; hlt ; hlt\n"); + printf("\t.subsections_via_symbols\n"); + } + + printf("\t.section __IMPORT,__pointers,non_lazy_symbol_pointers\n"); + DLIST_FOREACH(p, &nlplist, link) { + printf("L%s$non_lazy_ptr:\n", p->name); + printf("\t.indirect_symbol %s\n", exname(p->name)); + printf("\t.long 0\n"); + } + + } +#endif + +#define _MKSTR(x) #x +#define MKSTR(x) _MKSTR(x) +#define OS MKSTR(TARGOS) + printf("\t.ident \"PCC: %s (%s)\"\n", PACKAGE_STRING, OS); } void bjobcode() { +#if defined(MACHOABI) + DLIST_INIT(&stublist, link); + DLIST_INIT(&nlplist, link); +#endif } /* @@ -188,6 +259,7 @@ funcode(NODE *p) } if (kflag == 0) return p; +#if defined(ELFABI) /* Create an ASSIGN node for ebx */ l = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); l->n_rval = EBX; @@ -199,6 +271,7 @@ funcode(NODE *p) ; r->n_left = block(CM, l, r->n_left, INT, 0, MKSUE(INT)); } +#endif return p; } diff --git a/usr.bin/pcc/i386/local.c b/usr.bin/pcc/i386/local.c index 9f3fe41cdd5..33e86e6ae76 100644 --- a/usr.bin/pcc/i386/local.c +++ b/usr.bin/pcc/i386/local.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local.c,v 1.7 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: local.c,v 1.8 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -58,36 +58,69 @@ toolarge(TWORD t, CONSZ con) return 0; } +#if defined(MACHOABI) + +/* + * Keep track of PIC stubs. + */ + +void +addstub(struct stub *list, char *name) +{ + struct stub *s; + + DLIST_FOREACH(s, list, link) { + if (strcmp(s->name, name) == 0) + return; + } + + s = permalloc(sizeof(struct stub)); + s->name = permalloc(strlen(name) + 1); + strcpy(s->name, name); + DLIST_INSERT_BEFORE(list, s, link); +} + +#endif + #define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz)) + +#ifndef os_win32 /* * Make a symtab entry for PIC use. */ static struct symtab * -picsymtab(char *s, char *s2) +picsymtab(char *p, char *s, char *s2) { struct symtab *sp = IALLOC(sizeof(struct symtab)); - size_t len = strlen(s) + strlen(s2) + 1; + size_t len = strlen(p) + strlen(s) + strlen(s2) + 1; sp->sname = sp->soname = IALLOC(len); - strlcpy(sp->soname, s, len); + strlcpy(sp->soname, p, len); + strlcat(sp->soname, s, len); strlcat(sp->soname, s2, len); sp->sclass = EXTERN; sp->sflags = sp->slevel = 0; return sp; } +#endif int gotnr; /* tempnum for GOT register */ +int argstacksize; + /* * Create a reference for an extern variable. */ static NODE * picext(NODE *p) { + +#if defined(ELFABI) + NODE *q, *r; struct symtab *sp; q = tempnode(gotnr, PTR|VOID, 0, MKSUE(VOID)); - sp = picsymtab(p->n_sp->soname, "@GOT"); + sp = picsymtab("", p->n_sp->soname, "@GOT"); r = xbcon(0, sp, INT); q = buildtree(PLUS, q, r); q = block(UMUL, q, 0, PTR|VOID, 0, MKSUE(VOID)); @@ -95,6 +128,38 @@ picext(NODE *p) q->n_sp = p->n_sp; /* for init */ nfree(p); return q; + +#elif defined(MACHOABI) + + NODE *q, *r; + struct symtab *sp; + char buf2[64]; + + if (p->n_sp->sclass == EXTDEF) { + snprintf(buf2, 64, "-L%s$pb", cftnsp->soname); + sp = picsymtab("", exname(p->n_sp->soname), buf2); + } else { + snprintf(buf2, 64, "$non_lazy_ptr-L%s$pb", cftnsp->soname); + sp = picsymtab("L", p->n_sp->soname, buf2); + addstub(&nlplist, p->n_sp->soname); + } + q = tempnode(gotnr, PTR+VOID, 0, MKSUE(VOID)); + r = xbcon(0, sp, INT); + q = buildtree(PLUS, q, r); + + if (p->n_sp->sclass != EXTDEF) + 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; + +#elif defined(PECOFFABI) + + return p; + +#endif + } /* @@ -103,6 +168,9 @@ picext(NODE *p) static NODE * picstatic(NODE *p) { + +#if defined(ELFABI) + NODE *q, *r; struct symtab *sp; @@ -110,9 +178,9 @@ picstatic(NODE *p) if (p->n_sp->slevel > 0 || p->n_sp->sclass == ILABEL) { char buf[32]; snprintf(buf, 32, LABFMT, (int)p->n_sp->soffset); - sp = picsymtab(buf, "@GOTOFF"); + sp = picsymtab("", buf, "@GOTOFF"); } else - sp = picsymtab(p->n_sp->soname, "@GOTOFF"); + sp = picsymtab("", p->n_sp->soname, "@GOTOFF"); sp->sclass = STATIC; sp->stype = p->n_sp->stype; r = xbcon(0, sp, INT); @@ -121,6 +189,39 @@ picstatic(NODE *p) q->n_sp = p->n_sp; /* for init */ nfree(p); return q; + +#elif defined(MACHOABI) + + NODE *q, *r; + struct symtab *sp; + char buf2[64]; + + snprintf(buf2, 64, "-L%s$pb", cftnsp->soname); + + if (p->n_sp->slevel > 0 || p->n_sp->sclass == ILABEL) { + char buf1[64]; + snprintf(buf1, 64, LABFMT, (int)p->n_sp->soffset); + sp = picsymtab("", buf1, buf2); + sp->sflags |= SNOUNDERSCORE; + } else { + sp = picsymtab("", exname(p->n_sp->soname), buf2); + } + sp->sclass = STATIC; + sp->stype = p->n_sp->stype; + q = tempnode(gotnr, PTR+VOID, 0, MKSUE(VOID)); + r = xbcon(0, sp, INT); + 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; + nfree(p); + return q; + +#elif defined(PECOFFABI) + + return p; + +#endif + } #ifdef TLS @@ -131,7 +232,7 @@ static NODE * tlspic(NODE *p) { NODE *q, *r; - struct symtab *sp; + struct symtab *sp, *sp2; /* * creates: @@ -141,7 +242,7 @@ tlspic(NODE *p) /* calc address of var@TLSGD */ q = tempnode(gotnr, PTR|VOID, 0, MKSUE(VOID)); - sp = picsymtab(p->n_sp->soname, "@TLSGD"); + sp = picsymtab("", p->n_sp->soname, "@TLSGD"); r = xbcon(0, sp, INT); q = buildtree(PLUS, q, r); @@ -151,9 +252,9 @@ tlspic(NODE *p) q = buildtree(ASSIGN, r, q); /* call ___tls_get_addr */ - spname = lookup("___tls_get_addr@PLT", 0); - spname->stype = EXTERN|INT|FTN; - r = buildtree(NAME, NIL, NIL); + sp2 = lookup("___tls_get_addr@PLT", 0); + sp2->stype = EXTERN|INT|FTN; + r = nametree(sp2); r = buildtree(ADDROF, r, NIL); r = block(UCALL, r, NIL, INT, 0, MKSUE(INT)); @@ -170,17 +271,18 @@ static NODE * tlsnonpic(NODE *p) { NODE *q, *r; - struct symtab *sp; + struct symtab *sp, *sp2; int ext = p->n_sp->sclass; - sp = picsymtab(p->n_sp->soname, ext == EXTERN ? "@INDNTPOFF" : "@NTPOFF"); + sp = picsymtab("", p->n_sp->soname, + ext == EXTERN ? "@INDNTPOFF" : "@NTPOFF"); q = xbcon(0, sp, INT); if (ext == EXTERN) q = block(UMUL, q, NIL, PTR|VOID, 0, MKSUE(VOID)); - spname = lookup("%gs:0", 0); - spname->stype = EXTERN|INT; - r = buildtree(NAME, NIL, NIL); + sp2 = lookup("%gs:0", 0); + sp2->stype = EXTERN|INT; + r = nametree(sp2); q = buildtree(PLUS, q, r); q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue); @@ -312,19 +414,21 @@ clocal(NODE *p) case USTCALL: if (kflag == 0) break; +#if defined(ELFABI) /* Change to CALL node with ebx as argument */ l = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); l->n_rval = EBX; p->n_right = buildtree(ASSIGN, l, tempnode(gotnr, INT, 0, MKSUE(INT))); p->n_op -= (UCALL-CALL); +#endif break; case CBRANCH: l = p->n_left; /* - * Remove unneccessary conversion ops. + * Remove unnecessary conversion ops. */ if (clogop(l->n_op) && l->n_left->n_op == SCONV) { if (coptype(l->n_op) != BITYPE) @@ -520,8 +624,6 @@ clocal(NODE *p) case RS: /* shift count must be in a char * unless longlong, where it must be int */ - if (p->n_right->n_op == ICON) - break; /* do not do anything */ if (p->n_type == LONGLONG || p->n_type == ULONGLONG) { if (p->n_right->n_type != INT) p->n_right = block(SCONV, p->n_right, NIL, @@ -549,6 +651,8 @@ clocal(NODE *p) static void fixnames(NODE *p) { +#if !defined(PECOFFABI) + struct symtab *sp; struct suedef *sue; NODE *q; @@ -562,6 +666,7 @@ fixnames(NODE *p) 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; @@ -575,12 +680,29 @@ fixnames(NODE *p) sp->sclass != EXTDEF) cerror("fixnames"); +#if defined(ELFABI) + if ((c = strstr(sp->soname, "@GOT")) == NULL) cerror("fixnames2"); if (isu) { memcpy(c, "@PLT", sizeof("@PLT")); } else *c = 0; + +#elif defined(MACHOABI) + + if ((c = strstr(sp->soname, "$non_lazy_ptr")) == NULL && + (c = strstr(sp->soname, "-L")) == NULL) + cerror("fixnames2"); + if (isu) { + *c = 0; + addstub(&stublist, sp->soname+1); + strcpy(c, "$stub"); + } else + *c = 0; + +#endif + nfree(q->n_left); q = q->n_right; if (isu) @@ -589,6 +711,7 @@ fixnames(NODE *p) p->n_left = q; q->n_sue = sue; } +#endif } void @@ -611,6 +734,7 @@ myp2tree(NODE *p) sp = IALLOC(sizeof(struct symtab)); sp->sclass = STATIC; + sp->ssue = MKSUE(p->n_type); sp->slevel = 1; /* fake numeric label */ sp->soffset = getlab(); sp->sflags = 0; @@ -618,7 +742,7 @@ myp2tree(NODE *p) sp->squal = (CON >> TSHIFT); defloc(sp); - ninval(0, btdims[p->n_type].suesize, p); + ninval(0, sp->ssue->suesize, p); p->n_op = NAME; p->n_lval = 0; @@ -711,10 +835,22 @@ spalloc(NODE *t, NODE *p, OFFSZ off) void instring(struct symtab *sp) { - char *s, *str; + char *s, *str = sp->sname; + +#if defined(ELFABI) || defined(PECOFFABI) defloc(sp); - str = sp->sname; + +#elif defined(MACHOABI) + + extern int lastloc; + if (lastloc != STRNG) + printf(" .cstring\n"); + lastloc = STRNG; + printf("\t.p2align 2\n"); + printf(LABFMT ":\n", sp->soffset); + +#endif /* be kind to assemblers and avoid long strings */ printf("\t.ascii \""); @@ -742,7 +878,7 @@ inwstring(struct symtab *sp) NODE *p; defloc(sp); - p = bcon(0); + p = xbcon(0, NULL, WCHAR_TYPE); do { if (*s++ == '\\') p->n_lval = esccon(&s); @@ -821,7 +957,9 @@ ninval(CONSZ off, int fsz, NODE *p) { union { float f; double d; long double l; int i[3]; } u; struct symtab *q; +#if defined(ELFABI) || defined(MACHOABI) char *c; +#endif TWORD t; int i; @@ -840,8 +978,22 @@ ninval(CONSZ off, int fsz, NODE *p) p = p->n_left; p = p->n_right; q = p->n_sp; + +#if defined(ELFABI) + if ((c = strstr(q->soname, "@GOT")) != NULL) *c = 0; /* ignore GOT ref here */ + +#elif defined(MACHOABI) + + if ((c = strstr(q->soname, "$non_lazy_ptr")) != NULL) { + q->soname++; /* skip "L" */ + *c = 0; /* ignore GOT ref here */ + } + else if ((c = strstr(q->soname, "-L")) != NULL) + *c = 0; /* ignore GOT ref here */ + +#endif } if (p->n_op != ICON && p->n_op != FCON) cerror("ninval: init node not constant"); @@ -866,8 +1018,14 @@ ninval(CONSZ off, int fsz, NODE *p) if ((q->sclass == STATIC && q->slevel > 0) || q->sclass == ILABEL) { printf("+" LABFMT, q->soffset); - } else - printf("+%s", exname(q->soname)); + } else { +#if defined(MACHOABI) + if ((q->sflags & SNOUNDERSCORE) != 0) + printf("+%s", q->soname); + else +#endif + printf("+%s", exname(q->soname)); + } } printf("\n"); break; @@ -886,11 +1044,20 @@ ninval(CONSZ off, int fsz, NODE *p) case LDOUBLE: u.i[2] = 0; u.l = (long double)p->n_dcon; +#if defined(HOST_BIG_ENDIAN) + /* XXX probably broken on most hosts */ + printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[2], u.i[1], u.i[0]); +#else printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]); +#endif break; case DOUBLE: u.d = (double)p->n_dcon; +#if defined(HOST_BIG_ENDIAN) + printf("\t.long\t0x%x,0x%x\n", u.i[1], u.i[0]); +#else printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]); +#endif break; case FLOAT: u.f = (float)p->n_dcon; @@ -905,9 +1072,29 @@ ninval(CONSZ off, int fsz, NODE *p) char * exname(char *p) { +#if defined(PECOFFABI) || defined(MACHOABI) + +#define NCHNAM 256 + static char text[NCHNAM+1]; + int i; + if (p == NULL) return ""; - return p; + + text[0] = '_'; + for (i=1; *p && i<NCHNAM; ++i) + text[i] = *p++; + + text[i] = '\0'; + text[NCHNAM] = '\0'; /* truncate */ + + return (text); + +#else + + return (p == NULL ? "" : p); + +#endif } /* @@ -962,12 +1149,40 @@ defzero(struct symtab *sp) printf(LABFMT ",0%o\n", sp->soffset, off); } +static char * +section2string(char *name, int len) +{ +#if defined(ELFABI) + char *s; + int n; + + if (strncmp(name, "link_set", 8) == 0) { + const char *postfix = ",\"aw\",@progbits"; + n = len + strlen(postfix) + 1; + s = IALLOC(n); + strlcpy(s, name, n); + strlcat(s, postfix, n); + return s; + } +#endif + + return newstring(name, len); +} + char *nextsect; #ifdef TLS static int gottls; #endif +#ifdef os_win32 +static int stdcall; +static int dllindirect; +#endif +static char *alias; +static int constructor; +static int destructor; -/* * Give target the opportunity of handling pragmas. +/* + * Give target the opportunity of handling pragmas. */ int mypragma(char **ary) @@ -978,10 +1193,46 @@ mypragma(char **ary) return 1; } #endif - if (strcmp(ary[1], "section") || ary[2] == NULL) - return 0; - nextsect = newstring(ary[2], strlen(ary[2])); - return 1; +#ifdef os_win32 + if (strcmp(ary[1], "stdcall") == 0) { + stdcall = 1; + return 1; + } + if (strcmp(ary[1], "cdecl") == 0) { + stdcall = 0; + return 1; + } + if (strcmp(ary[1], "fastcall") == 0) { + stdcall = 2; + return 1; + } + if (strcmp(ary[1], "dllimport") == 0) { + dllindirect = 1; + return 1; + } + if (strcmp(ary[1], "dllexport") == 0) { + dllindirect = 1; + return 1; + } +#endif + if (strcmp(ary[1], "constructor") == 0 || strcmp(ary[1], "init") == 0) { + constructor = 1; + return 1; + } + if (strcmp(ary[1], "destructor") == 0 || strcmp(ary[1], "fini") == 0) { + destructor = 1; + return 1; + } + if (strcmp(ary[1], "section") == 0 && ary[2] != NULL) { + nextsect = section2string(ary[2], strlen(ary[2])); + return 1; + } + if (strcmp(ary[1], "alias") == 0 && ary[2] != NULL) { + alias = tmpstrdup(ary[2]); + return 1; + } + + return 0; } /* @@ -996,4 +1247,164 @@ fixdef(struct symtab *sp) sp->sflags |= STLS; gottls = 0; #endif + if (alias != NULL && (sp->sclass != PARAM)) { + printf("\t.globl %s\n", exname(sp->soname)); + printf("%s = ", exname(sp->soname)); + printf("%s\n", exname(alias)); + alias = NULL; + } + if ((constructor || destructor) && (sp->sclass != PARAM)) { +#if defined(ELFABI) + printf("\t.section .%ctors,\"aw\",@progbits\n", + constructor ? 'c' : 'd'); +#elif defined(MACHOABI) + if (kflag) { + if (constructor) + printf("\t.mod_init_func\n"); + else + printf("\t.mod_term_func\n"); + } else { + if (constructor) + printf("\t.constructor\n"); + else + printf("\t.destructor\n"); + } +#endif + printf("\t.p2align 2\n"); + printf("\t.long %s\n", exname(sp->sname)); + constructor = destructor = 0; + } +#ifdef os_win32 + if (stdcall && (sp->sclass != PARAM)) { + sp->sflags |= SSTDCALL; + stdcall = 0; + } + if (dllindirect && (sp->sclass != PARAM)) { + sp->sflags |= SDLLINDIRECT; + dllindirect = 0; + } +#endif +} + +NODE * +i386_builtin_return_address(NODE *f, NODE *a) +{ + int nframes; + + if (a == NULL || a->n_op != ICON) + goto bad; + + nframes = a->n_lval; + + tfree(f); + tfree(a); + + f = block(REG, NIL, NIL, PTR+VOID, 0, MKSUE(VOID)); + regno(f) = FPREG; + + while (nframes--) + f = block(UMUL, f, NIL, PTR+VOID, 0, MKSUE(VOID)); + + f = block(PLUS, f, bcon(4), INCREF(PTR+VOID), 0, MKSUE(VOID)); + f = buildtree(UMUL, f, NIL); + + return f; +bad: + uerror("bad argument to __builtin_return_address"); + return bcon(0); +} + +NODE * +i386_builtin_frame_address(NODE *f, NODE *a) +{ + int nframes; + + if (a == NULL || a->n_op != ICON) + goto bad; + + nframes = a->n_lval; + + tfree(f); + tfree(a); + + f = block(REG, NIL, NIL, PTR+VOID, 0, MKSUE(VOID)); + regno(f) = FPREG; + + while (nframes--) + f = block(UMUL, f, NIL, PTR+VOID, 0, MKSUE(VOID)); + + return f; +bad: + uerror("bad argument to __builtin_frame_address"); + return bcon(0); +} + +#ifdef os_win32 +/* + * Postfix external functions with the arguments size. + */ +static void +mangle(NODE *p) +{ + NODE *l, *r; + TWORD t; + int size = 0; + char buf[64]; + + if ((p->n_op == NAME || p->n_op == ICON) && + p->n_sp && (p->n_sp->sflags & SDLLINDIRECT) && p->n_name) { + snprintf(buf, 64, "__imp_%s", p->n_name); + p->n_name = IALLOC(strlen(buf) + 1); + strcpy(p->n_name, buf); + return; + } + + if (p->n_op != CALL && p->n_op != STCALL && + p->n_op != UCALL && p->n_op != USTCALL) + return; + + l = p->n_left; + if (l->n_op == ADDROF) + l = l->n_left; + if (l->n_sp == NULL) + return; + if (l->n_sp->sflags & SSTDCALL) { + if (strchr(l->n_name, '@') == NULL) { + if (p->n_op == CALL || p->n_op == STCALL) { + for (r = p->n_right; + r->n_op == CM; r = r->n_left) { + t = r->n_type; + if (t == STRTY || t == UNIONTY) + size += r->n_sue->suesize; + else + size += szty(t) * SZINT / SZCHAR; + } + t = r->n_type; + if (t == STRTY || t == UNIONTY) + size += r->n_sue->suesize; + else + size += szty(t) * SZINT / SZCHAR; + } + snprintf(buf, 64, "%s@%d", l->n_name, size); + l->n_name = IALLOC(strlen(buf) + 1); + strcpy(l->n_name, buf); + } + + l->n_flags = FSTDCALL; + } +} +#endif + +void +pass1_lastchance(struct interpass *ip) +{ +#ifdef os_win32 + if (ip->type == IP_EPILOG) { + struct interpass_prolog *ipp = (struct interpass_prolog *)ip; + ipp->ipp_argstacksize = argstacksize; + } + + if (ip->type == IP_NODE) + walkf(ip->ip_node, mangle); +#endif } diff --git a/usr.bin/pcc/i386/local2.c b/usr.bin/pcc/i386/local2.c index 70015de2b29..355e2c46337 100644 --- a/usr.bin/pcc/i386/local2.c +++ b/usr.bin/pcc/i386/local2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local2.c,v 1.8 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: local2.c,v 1.9 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -30,8 +30,12 @@ # include <ctype.h> # include <string.h> -void acon(NODE *p); -int argsize(NODE *p); +#if defined(PECOFFABI) || defined(MACHOABI) +#define EXPREFIX "_" +#else +#define EXPREFIX "" +#endif + static int stkpos; @@ -51,11 +55,16 @@ static TWORD ftype; static void prtprolog(struct interpass_prolog *ipp, int addto) { +#if defined(ELFABI) static int lwnr; +#endif int i, j; printf(" pushl %%ebp\n"); printf(" movl %%esp,%%ebp\n"); +#if defined(MACHOABI) + printf(" subl $8,%%esp\n"); /* 16-byte stack alignment */ +#endif if (addto) printf(" subl $%d,%%esp\n", addto); for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++) @@ -64,6 +73,9 @@ prtprolog(struct interpass_prolog *ipp, int addto) rnames[j], regoff[j], rnames[FPREG]); if (kflag == 0) return; + +#if defined(ELFABI) + /* 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) { @@ -89,8 +101,15 @@ prtprolog(struct interpass_prolog *ipp, int addto) printf(" call .LW%d\n", ++lwnr); printf(".LW%d:\n", lwnr); printf(" popl %%ebx\n"); - printf(" addl $_GLOBAL_OFFSET_TABLE_+[.-.LW%d], %%ebx\n", - lwnr); + printf(" addl $_GLOBAL_OFFSET_TABLE_+[.-.LW%d], %%ebx\n", lwnr); + +#elif defined(MACHOABI) + + printf("\tcall L%s$pb\n", ipp->ipp_name); + printf("L%s$pb:\n", ipp->ipp_name); + printf("\tpopl %%ebx\n"); + +#endif } /* @@ -119,6 +138,7 @@ prologue(struct interpass_prolog *ipp) int addto; ftype = ipp->ipp_type; + #ifdef LANG_F77 if (ipp->ipp_vis) printf(" .globl %s\n", ipp->ipp_name); @@ -130,6 +150,9 @@ prologue(struct interpass_prolog *ipp) * add to the stack. */ addto = offcalc(ipp); +#if defined(MACHOABI) + addto = (addto + 15) & ~15; /* stack alignment */ +#endif prtprolog(ipp, addto); } @@ -153,11 +176,25 @@ eoftn(struct interpass_prolog *ipp) if (ftype == STRTY || ftype == UNIONTY) { printf(" movl 8(%%ebp),%%eax\n"); printf(" leave\n"); - printf(" ret $4\n"); +#ifdef os_win32 + printf(" ret $%d\n", 4 + ipp->ipp_argstacksize); +#else + printf(" ret $%d\n", 4); +#endif } else { printf(" leave\n"); - printf(" ret\n"); +#ifdef os_win32 + if (ipp->ipp_argstacksize) + printf(" ret $%d\n", ipp->ipp_argstacksize); + else +#endif + printf(" ret\n"); } + +#if defined(ELFABI) + printf("\t.size " EXPREFIX "%s,.-" EXPREFIX "%s\n", ipp->ipp_name, + ipp->ipp_name); +#endif } /* @@ -348,7 +385,12 @@ starg(NODE *p) expand(p, 0, " pushl AL\n"); expand(p, 0, " leal 8(%esp),A1\n"); expand(p, 0, " pushl A1\n"); - fprintf(fp, " call memcpy\n"); +#if defined(MACHOABI) + fprintf(fp, " call L%s$stub\n", EXPREFIX "memcpy"); + addstub(&stublist, "memcpy"); +#else + fprintf(fp, " call %s\n", EXPREFIX "memcpy"); +#endif fprintf(fp, " addl $12,%%esp\n"); } @@ -456,6 +498,8 @@ zzzcode(NODE *p, int c) break; case 'C': /* remove from stack after subroutine call */ + if (p->n_left->n_flags & FSTDCALL) + break; pr = p->n_qual; if (p->n_op == STCALL || p->n_op == USTCALL) pr += 4; @@ -521,7 +565,8 @@ zzzcode(NODE *p, int c) else if (p->n_op == RS) ch = "ashr"; else if (p->n_op == LS) ch = "ashl"; else ch = 0, comperr("ZO"); - printf("\tcall __%sdi3\n\taddl $%d,%s\n", ch, pr, rnames[ESP]); + printf("\tcall " EXPREFIX "__%sdi3\n\taddl $%d,%s\n", + ch, pr, rnames[ESP]); break; case 'P': /* push hidden argument on stack */ @@ -538,7 +583,12 @@ zzzcode(NODE *p, int c) printf("\tpushl $%d\n", p->n_stsize); expand(p, INAREG, "\tpushl AR\n"); expand(p, INAREG, "\tleal AL,%eax\n\tpushl %eax\n"); - printf("\tcall memcpy\n"); +#if defined(MACHOABI) + printf("\tcall L%s$stub\n", EXPREFIX "memcpy"); + addstub(&stublist, "memcpy"); +#else + printf("\tcall %s\n", EXPREFIX "memcpy"); +#endif printf("\taddl $12,%%esp\n"); break; @@ -1069,8 +1119,10 @@ 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 defined(ELFABI) if (kflag) size -= 4; +#endif op->n_qual = size; /* XXX */ } @@ -1115,3 +1167,122 @@ void mflags(char *str) { } + +/* + * Do something target-dependent for xasm arguments. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + struct interpass *ip2; + NODE *in = 0, *ut = 0; + TWORD t; + char *w; + int reg; + int cw; + + cw = xasmcode(p->n_name); + if (cw & (XASMASG|XASMINOUT)) + ut = p->n_left; + if ((cw & XASMASG) == 0) + in = p->n_left; + + switch (XASMVAL(cw)) { + case 'D': reg = EDI; break; + case 'S': reg = ESI; break; + case 'a': reg = EAX; break; + case 'b': reg = EBX; break; + case 'c': reg = ECX; break; + case 'd': reg = EDX; break; + case 't': reg = 0; break; + case 'u': reg = 1; break; + case 'A': reg = EAXEDX; break; + case 'q': /* XXX let it be CLASSA as for now */ + p->n_name = tmpstrdup(p->n_name); + w = strchr(p->n_name, 'q'); + *w = 'r'; + return 0; + default: + return 0; + } + p->n_name = tmpstrdup(p->n_name); + for (w = p->n_name; *w; w++) + ; + w[-1] = 'r'; /* now reg */ + t = p->n_left->n_type; + if (reg == EAXEDX) { + p->n_label = CLASSC; + } else { + p->n_label = CLASSA; + if (t == CHAR || t == UCHAR) { + p->n_label = CLASSB; + reg = reg * 2 + 8; + } + } + if (t == FLOAT || t == DOUBLE || t == LDOUBLE) { + p->n_label = CLASSD; + reg += 037; + } + + if (in && ut) + in = tcopy(in); + p->n_left = mklnode(REG, 0, reg, t); + if (ut) { + ip2 = ipnode(mkbinode(ASSIGN, ut, tcopy(p->n_left), t)); + DLIST_INSERT_AFTER(ip, ip2, qelem); + } + if (in) { + ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), in, t)); + DLIST_INSERT_BEFORE(ip, ip2, qelem); + } + return 1; +} + +void +targarg(char *w, void *arg) +{ + NODE **ary = arg; + NODE *p, *q; + + p = ary[(int)w[1]-'0']->n_left; + if (optype(p->n_op) != LTYPE) + comperr("bad xarg op %d", p->n_op); + q = tcopy(p); + if (q->n_op == REG) { + if (*w == 'k') { + q->n_type = INT; + } else if (*w != 'w') { + if (q->n_type > UCHAR) { + regno(q) = regno(q)*2+8; + if (*w == 'h') + regno(q)++; + } + q->n_type = INT; + } else + q->n_type = SHORT; + } + adrput(stdout, q); + tfree(q); +} + +/* + * target-specific conversion of numeric arguments. + */ +int +numconv(void *ip, void *p1, void *q1) +{ + NODE *p = p1, *q = q1; + int cw = xasmcode(q->n_name); + + switch (XASMVAL(cw)) { + case 'a': + case 'b': + case 'c': + case 'd': + p->n_name = tmpcalloc(2); + p->n_name[0] = XASMVAL(cw); + return 1; + default: + return 0; + } +} diff --git a/usr.bin/pcc/i386/macdefs.h b/usr.bin/pcc/i386/macdefs.h index 0343b1ffabc..4b5248a6c2a 100644 --- a/usr.bin/pcc/i386/macdefs.h +++ b/usr.bin/pcc/i386/macdefs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: macdefs.h,v 1.4 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: macdefs.h,v 1.5 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -90,7 +90,7 @@ /* Default char is signed */ #undef CHAR_UNSIGNED #define BOOL_TYPE CHAR /* what used to store _Bool */ -#if os_mirbsd +#if defined(os_mirbsd) || defined(os_win32) #define WCHAR_TYPE USHORT /* ISO 10646 16-bit Unicode */ #else #define WCHAR_TYPE INT /* what used to store wchar_t */ @@ -104,8 +104,13 @@ typedef unsigned long long U_CONSZ; typedef long long OFFSZ; #define CONFMT "%lld" /* format for printing constants */ +#if defined(ELFABI) #define LABFMT ".L%d" /* format for printing labels */ #define STABLBL ".LL%d" /* format for stab (debugging) labels */ +#else +#define LABFMT "L%d" /* format for printing labels */ +#define STABLBL "LL%d" /* format for stab (debugging) labels */ +#endif #ifdef LANG_F77 #define BLANKCOMMON "_BLNK_" #define MSKIREG (M(TYSHORT)|M(TYLONG)) @@ -116,6 +121,10 @@ typedef long long OFFSZ; #define ARGOFFSET 8 #endif +#ifdef MACHOABI +#define STAB_LINE_ABSOLUTE /* S_LINE fields use absolute addresses */ +#endif + #define BACKAUTO /* stack grows negatively for automatics */ #define BACKTEMP /* stack grows negatively for temporaries */ @@ -302,3 +311,51 @@ int COLORMAP(int c, int *r); */ #define SSECTION SLOCAL1 #define STLS SLOCAL2 +#define SNOUNDERSCORE SLOCAL3 +#define SSTDCALL SLOCAL2 +#define SDLLINDIRECT SLOCAL3 + +/* + * i386-specific node flags. + */ +#define FSTDCALL 0x01 + +/* + * i386-specific interpass stuff. + */ + +#define TARGET_IPP_MEMBERS \ + int ipp_argstacksize; + +/* + * Extended assembler macros. + */ +void targarg(char *w, void *arg); +#define XASM_TARGARG(w, ary) \ + (w[1] == 'b' || w[1] == 'h' || w[1] == 'w' || w[1] == 'k' ? \ + w++, targarg(w, ary), 1 : 0) +int numconv(void *ip, void *p, void *q); +#define XASM_NUMCONV(ip, p, q) numconv(ip, p, q) + +/* + * builtins. + */ +#define TARGET_BUILTINS \ + { "__builtin_frame_address", i386_builtin_frame_address }, \ + { "__builtin_return_address", i386_builtin_return_address }, + +#define NODE struct node +struct node; +NODE *i386_builtin_frame_address(NODE *f, NODE *a); +NODE *i386_builtin_return_address(NODE *f, NODE *a); +#undef NODE + +#if defined(MACHOABI) +struct stub { + struct { struct stub *q_forw, *q_back; } link; + char *name; +}; +extern struct stub stublist; +extern struct stub nlplist; +void addstub(struct stub *list, char *name); +#endif diff --git a/usr.bin/pcc/i386/table.c b/usr.bin/pcc/i386/table.c index 8370d128171..ef95b6346ca 100644 --- a/usr.bin/pcc/i386/table.c +++ b/usr.bin/pcc/i386/table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table.c,v 1.6 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: table.c,v 1.7 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -229,7 +229,7 @@ struct optab table[] = { /* convert int to char. This is done when register is loaded */ { SCONV, INCH, - SAREG, TWORD, + SAREG, TWORD|TPOINT, SANY, TCHAR|TUCHAR, NSPECIAL|NBREG|NBSL, RESC1, "ZM", }, @@ -976,7 +976,7 @@ struct optab table[] = { SNAME|SOREG, TLDOUBLE, SHFL, TFLOAT|TDOUBLE|TLDOUBLE, 0, RDEST, - " fstt AL\n", }, + " fst AL\n", }, { ASSIGN, FOREFF, SNAME|SOREG, TLDOUBLE, @@ -1316,7 +1316,7 @@ struct optab table[] = { 0, RNOP, " jmp LL\n", }, -#ifdef GCC_COMPAT +#if defined(GCC_COMPAT) || defined(LANG_F77) { GOTO, FOREFF, SAREG, TANY, SANY, TANY, diff --git a/usr.bin/pcc/mip/common.c b/usr.bin/pcc/mip/common.c index 95ee5358394..99635d553e9 100644 --- a/usr.bin/pcc/mip/common.c +++ b/usr.bin/pcc/mip/common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: common.c,v 1.9 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: common.c,v 1.10 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -152,6 +152,7 @@ werror(char *s, ...) static NODE *freelink; static int usednodes; +#ifndef LANG_F77 NODE * talloc() { @@ -178,6 +179,7 @@ talloc() printf("alloc node %p from memory\n", p); return p; } +#endif /* * make a fresh copy of p @@ -200,6 +202,7 @@ tcopy(NODE *p) return(q); } +#ifndef LANG_F77 /* * ensure that all nodes have been freed */ @@ -214,6 +217,7 @@ tcheck() if ((usednodes - inlnodecnt) != 0) cerror("usednodes == %d, inlnodecnt %d", usednodes, inlnodecnt); } +#endif /* * free the tree p @@ -232,7 +236,9 @@ tfree(NODE *p) NODE * nfree(NODE *p) { +#ifndef LANG_F77 extern int inlnodecnt, recovernodes; +#endif NODE *l; #ifdef PCC_DEBUG_NODES NODE *q; @@ -259,12 +265,20 @@ nfree(NODE *p) p->next = freelink; freelink = p; usednodes--; +#ifndef LANG_F77 if (recovernodes) inlnodecnt--; +#endif return l; } #endif +#ifdef LANG_F77 +#define OPTYPE(x) optype(x) +#else +#define OPTYPE(x) coptype(x) +#endif + #ifdef MKEXT #define coptype(o) (dope[o]&TYFLG) #else @@ -283,7 +297,7 @@ fwalk(NODE *t, void (*f)(NODE *, int, int *, int *), int down) (*f)(t, down, &down1, &down2); - switch (coptype( t->n_op )) { + switch (OPTYPE( t->n_op )) { case BITYPE: fwalk( t->n_left, f, down1 ); @@ -304,7 +318,8 @@ walkf(NODE *t, void (*f)(NODE *)) { int opty; - opty = coptype(t->n_op); + + opty = OPTYPE(t->n_op); if (opty != LTYPE) walkf( t->n_left, f ); @@ -419,6 +434,9 @@ tprint(FILE *fp, TWORD t, TWORD q) "void", "signed", /* pass1 */ "bool", /* pass1 */ + "fcomplex", /* pass1 */ + "dcomplex", /* pass1 */ + "lcomplex", /* pass1 */ "?", "?" }; @@ -600,6 +618,18 @@ tmpvsprintf(char *fmt, va_list ap) return tmp; } +/* + * Duplicate a string onto the temporary heap. + */ +char * +tmpstrdup(char *str) +{ + int len; + + len = strlen(str) + 1; + return memcpy(tmpalloc(len), str, len); +} + void tmpfree() { @@ -644,3 +674,48 @@ newstring(char *s, int len) *c++ = *s++; return u; } + +/* + * Do a preorder walk of the CM list p and apply function f on each element. + */ +void +flist(NODE *p, void (*f)(NODE *, void *), void *arg) +{ + if (p->n_op == CM) { + (*f)(p->n_right, arg); + flist(p->n_left, f, arg); + } else + (*f)(p, arg); +} + +/* + * The same as flist but postorder. + */ +void +listf(NODE *p, void (*f)(NODE *)) +{ + if (p->n_op == CM) { + listf(p->n_left, f); + (*f)(p->n_right); + } else + (*f)(p); +} + +/* + * Get list argument number n from list, or NIL if out of list. + */ +NODE * +listarg(NODE *p, int n, int *cnt) +{ + NODE *r; + + if (p->n_op == CM) { + r = listarg(p->n_left, n, cnt); + if (n == ++(*cnt)) + r = p->n_right; + } else { + *cnt = 0; + r = n == 0 ? p : NIL; + } + return r; +} diff --git a/usr.bin/pcc/mip/manifest.h b/usr.bin/pcc/mip/manifest.h index a41278c8f0e..368faced7d2 100644 --- a/usr.bin/pcc/mip/manifest.h +++ b/usr.bin/pcc/mip/manifest.h @@ -1,4 +1,4 @@ -/* $OpenBSD: manifest.h,v 1.10 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: manifest.h,v 1.11 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -180,7 +180,10 @@ extern int ddebug, xdebug, f2debug; extern int iTflag, oTflag, kflag; extern int sflag, nflag, gflag, pflag; extern int Wstrict_prototypes, Wmissing_prototypes, Wimplicit_int, - Wimplicit_function_declaration; + Wimplicit_function_declaration, Wpointer_sign, Wshadow, + Wsign_compare, Wunknown_pragmas, Wunreachable_code; +extern int funsigned_char; +extern int sspflag; extern int xssaflag, xtailcallflag, xtemps, xdeljumps; int yyparse(void); @@ -263,6 +266,9 @@ struct interpass_prolog { int ipp_autos; /* Size on stack needed */ int ip_tmpnum; /* # allocated temp nodes so far */ int ip_lblnum; /* # used labels so far */ +#ifdef TARGET_IPP_MEMBERS + TARGET_IPP_MEMBERS +#endif }; /* @@ -302,6 +308,8 @@ void *tmpcalloc(int size); void *tmpalloc(int size); void tmpfree(void); char *newstring(char *, int len); +char *tmpstrdup(char *str); + /* command-line processing */ void mflags(char *); @@ -318,6 +326,10 @@ void pass2_compile(struct interpass *); NODE *nfree(NODE *); NODE *tcopy(NODE *); void fwalk(NODE *t, void (*f)(NODE *, int, int *, int *), int down); +void flist(NODE *p, void (*f)(NODE *, void *), void *); +void listf(NODE *p, void (*f)(NODE *)); +NODE *listarg(NODE *p, int n, int *cnt); + extern int nerrors; /* number of errors seen so far */ extern int warniserr; /* treat warnings as errors */ diff --git a/usr.bin/pcc/mip/match.c b/usr.bin/pcc/mip/match.c index 3204f429835..6f14573c006 100644 --- a/usr.bin/pcc/mip/match.c +++ b/usr.bin/pcc/mip/match.c @@ -1,4 +1,4 @@ -/* $OpenBSD: match.c,v 1.9 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: match.c,v 1.10 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -60,11 +60,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ -# include "pass2.h" +#include "pass2.h" +#ifdef HAVE_STRINGS_H #include <strings.h> +#endif -void prttype(int t); void setclass(int tmp, int class); int getclass(int tmp); @@ -385,26 +386,6 @@ getlr(NODE *p, int c) return NULL; } -static char *tarr[] = { - "CHAR", "SHORT", "INT", "LONG", "FLOAT", "DOUBLE", "POINT", "UCHAR", - "USHORT", "UINT", "ULONG", "PTRTO", "ANY", "STRUCT", "LONGLONG", - "ULONGLONG", -}; - -void -prttype(int t) -{ - int i, gone = 0; - - for (i = 0; i < 16; i++) - if ((t >> i) & 1) { - if (gone) putchar('|'); - gone++; - printf("%s", tarr[i]); - } -} - - #ifdef PCC_DEBUG #define F2DEBUG(x) if (f2debug) printf x #define F2WALK(x) if (f2debug) fwalk(x, e2print, 0) diff --git a/usr.bin/pcc/mip/mkext.c b/usr.bin/pcc/mip/mkext.c index f0fcdbde8fc..d06aa1b48aa 100644 --- a/usr.bin/pcc/mip/mkext.c +++ b/usr.bin/pcc/mip/mkext.c @@ -6,6 +6,8 @@ #include <string.h> +#define FMTdPTR "%td" + int chkop[DSIZE]; void mktables(void); @@ -73,8 +75,22 @@ compl(struct optab *q, char *str) if (op < OPSIMP) { s = opst[op]; } else - s = "Special op"; - printf("table entry %td, op %s: %s\n", q - table, s, str); + switch (op) { + default: s = "Special op"; break; + case OPSIMP: s = "OPLSIMP"; break; + case OPCOMM: s = "OPCOMM"; break; + case OPMUL: s = "OPMUL"; break; + case OPDIV: s = "OPDIV"; break; + case OPUNARY: s = "OPUNARY"; break; + case OPLEAF: s = "OPLEAF"; break; + case OPANY: s = "OPANY"; break; + case OPLOG: s = "OPLOG"; break; + case OPFLOAT: s = "OPFLOAT"; break; + case OPSHFT: s = "OPSHFT"; break; + case OPLTYPE: s = "OPLTYPE"; break; + } + + printf("table entry " FMTdPTR ", op %s: %s\n", q - table, s, str); } static int @@ -174,7 +190,7 @@ main(int argc, char *argv[]) if ((q->rewrite & (RESC1|RESC2|RESC3)) && !(q->needs & REWRITE)) { if ((q->visit & getrcl(q)) == 0) { - compl(q, "rwong RESCx class"); + compl(q, "wrong RESCx class"); rval++; } } @@ -272,7 +288,7 @@ main(int argc, char *argv[]) if (breg > mx) mx = breg; if (creg > mx) mx = creg; if (dreg > mx) mx = dreg; - if (mx > (sizeof(int)*8)-1) { + if (mx > (int)(sizeof(int)*8)-1) { printf("too many regs in a class, use two classes instead\n"); printf("%d > %zu\n", mx, (sizeof(int)*8)-1); rval++; @@ -342,7 +358,7 @@ mktables() for (op = table; op->op != FREE; op++) { if (op->op < OPSIMP) { if (op->op == i) { - P((fc, "%td, ", op - table)); + P((fc, FMTdPTR ", ", op - table)); curalen++; } } else { @@ -350,11 +366,12 @@ mktables() if ((opmtemp=mamask[op->op - OPSIMP])&SPFLG) { if (i==NAME || i==ICON || i==TEMP || i==OREG || i == REG || i == FCON) { - P((fc, "%td, ", op - table)); + P((fc, FMTdPTR ", ", + op - table)); curalen++; } } else if ((dope[i]&(opmtemp|ASGFLG))==opmtemp){ - P((fc, "%td, ", op - table)); + P((fc, FMTdPTR ", ", op - table)); curalen++; } } diff --git a/usr.bin/pcc/mip/node.h b/usr.bin/pcc/mip/node.h index ba7ce53be37..c02737e5e61 100644 --- a/usr.bin/pcc/mip/node.h +++ b/usr.bin/pcc/mip/node.h @@ -1,4 +1,4 @@ -/* $OpenBSD: node.h,v 1.3 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: node.h,v 1.4 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -63,6 +63,7 @@ typedef struct node { union { int _label; int _stalign; + int _flags; struct suedef *_sue; } n_6; union { @@ -90,6 +91,7 @@ typedef struct node { #define n_label n_6._label #define n_stalign n_6._stalign +#define n_flags n_6._flags #define n_sue n_6._sue #define n_left n_f.n_u.n_l._left @@ -100,6 +102,9 @@ typedef struct node { #define n_sp n_f.n_u.n_r._sp #define n_dcon n_f._dcon +#define NLOCAL1 010000 +#define NLOCAL2 020000 +#define NLOCAL3 040000 /* * Node types. * diff --git a/usr.bin/pcc/mip/optim2.c b/usr.bin/pcc/mip/optim2.c index 393cbbd2302..4164cedfeec 100644 --- a/usr.bin/pcc/mip/optim2.c +++ b/usr.bin/pcc/mip/optim2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: optim2.c,v 1.7 2008/01/12 17:17:28 ragge Exp $ */ +/* $OpenBSD: optim2.c,v 1.8 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -167,7 +167,6 @@ cvtaddrof(NODE *p) l->n_op = REG; l->n_lval = 0; l->n_rval = FPREG; - } } @@ -430,7 +429,7 @@ again: gotone = 0; continue; ip->ip_node->n_right->n_lval = j; i = ip->ip_node->n_left->n_op; - if (i < EQ || i - EQ >= negrelsize) + if (i < EQ || i - EQ >= (int)negrelsize) comperr("deljumps: unexpected op"); ip->ip_node->n_left->n_op = negrel[i - EQ]; tfree(n->ip_node); @@ -473,7 +472,9 @@ optdump(struct interpass *ip) printf("type %s\n", nm[ip->type-1]); switch (ip->type) { case IP_NODE: +#ifdef PCC_DEBUG fwalk(ip->ip_node, e2print, 0); +#endif break; case IP_DEFLAB: printf("label " LABFMT "\n", ip->ip_lbl); @@ -967,7 +968,7 @@ printip(struct interpass *pole) static char *foo[] = { 0, "NODE", "PROLOG", "STKOFF", "EPILOG", "DEFLAB", "DEFNAM", "ASM" }; struct interpass *ip; - struct interpass_prolog *ipp, *epp; + struct interpass_prolog *ipplg, *epplg; DLIST_FOREACH(ip, pole, qelem) { if (ip->type > MAXIP) @@ -976,20 +977,22 @@ printip(struct interpass *pole) printf("%s (%p): ", foo[ip->type], ip); switch (ip->type) { case IP_NODE: printf("\n"); +#ifdef PCC_DEBUG fwalk(ip->ip_node, e2print, 0); break; +#endif case IP_PROLOG: - ipp = (struct interpass_prolog *)ip; + ipplg = (struct interpass_prolog *)ip; printf("%s %s regs %x autos %d mintemp %d minlbl %d\n", - ipp->ipp_name, ipp->ipp_vis ? "(local)" : "", - ipp->ipp_regs, ipp->ipp_autos, ipp->ip_tmpnum, - ipp->ip_lblnum); + ipplg->ipp_name, ipplg->ipp_vis ? "(local)" : "", + ipplg->ipp_regs, ipplg->ipp_autos, ipplg->ip_tmpnum, + ipplg->ip_lblnum); break; case IP_EPILOG: - epp = (struct interpass_prolog *)ip; + epplg = (struct interpass_prolog *)ip; printf("%s %s regs %x autos %d mintemp %d minlbl %d\n", - epp->ipp_name, epp->ipp_vis ? "(local)" : "", - epp->ipp_regs, epp->ipp_autos, epp->ip_tmpnum, - epp->ip_lblnum); + epplg->ipp_name, epplg->ipp_vis ? "(local)" : "", + epplg->ipp_regs, epplg->ipp_autos, epplg->ip_tmpnum, + epplg->ip_lblnum); break; case IP_DEFLAB: printf(LABFMT "\n", ip->ip_lbl); break; case IP_DEFNAM: printf("\n"); break; diff --git a/usr.bin/pcc/mip/pass2.h b/usr.bin/pcc/mip/pass2.h index 4b0c3b23b6a..90082a2f936 100644 --- a/usr.bin/pcc/mip/pass2.h +++ b/usr.bin/pcc/mip/pass2.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pass2.h,v 1.8 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: pass2.h,v 1.9 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -267,6 +267,13 @@ void myormake(NODE *); int *livecall(NODE *); void prtreg(FILE *, NODE *); char *prcook(int); +int myxasm(struct interpass *ip, NODE *p); +int xasmcode(char *s); +int freetemp(int k); +int rewfld(NODE *p); +void canon(NODE *); +void mycanon(NODE *); +void oreg2(NODE *p); void conput(FILE *, NODE *); @@ -284,6 +291,15 @@ extern int regK[]; #define CLASSD 4 #define CLASSE 5 +/* used when parsing xasm codes */ +#define XASMVAL(x) ((x) & 0377) /* get val from codeword */ +#define XASMASG 0x100 /* = */ +#define XASMCONSTR 0x200 /* & */ +#define XASMINOUT 0x400 /* + */ +#define XASMALL (XASMASG|XASMCONSTR|XASMINOUT) +#define XASMISINP(cw) (((cw) & XASMASG) == 0) /* input operand */ +#define XASMISOUT(cw) ((cw) & (XASMASG|XASMINOUT)) /* output operand */ + /* routines to handle double indirection */ #ifdef R2REGS void makeor2(NODE *p, NODE *q, int, int); @@ -383,12 +399,12 @@ struct basicblock { struct labelinfo { struct basicblock **arr; - unsigned int size; + int size; unsigned int low; }; struct bblockinfo { - unsigned int size; + int size; struct basicblock **arr; }; diff --git a/usr.bin/pcc/mip/protos.h b/usr.bin/pcc/mip/protos.h index e266120633e..879c806413e 100644 --- a/usr.bin/pcc/mip/protos.h +++ b/usr.bin/pcc/mip/protos.h @@ -1,8 +1,4 @@ -/* $OpenBSD: protos.h,v 1.7 2008/01/12 17:17:28 ragge Exp $ */ - -struct optab; -struct symtab; -struct sw; +/* $OpenBSD: protos.h,v 1.8 2008/08/17 18:40:13 ragge Exp $ */ void cerror(char *s, ...); void werror(char *s, ...); @@ -13,7 +9,6 @@ void tfree(NODE *); int tshape(NODE *, int); void tcheck(void); void mkdope(void); -int tshape(NODE *p, int shape); int shtemp(NODE *p); int flshape(NODE *p); int shumul(NODE *p); @@ -38,22 +33,16 @@ int fldexpand(NODE *, int, char **); void ecomp(NODE *p); void bccode(void); int upoff(int size, int alignment, int *poff); -void fldty(struct symtab *p); void nidcl(NODE *p, int class); int noinit(void); void eprint(NODE *, int, int *, int *); int uclass(int class); -void mycanon(NODE *); void setregs(void); -void canon(NODE *); int tlen(NODE *p); int setbin(NODE *); -void oreg2(NODE *p); int notoff(TWORD, int, CONSZ, char *); int notlval(NODE *); void ecode(NODE *p); int yylex(void); void yyerror(char *s); void p2tree(NODE *p); -int rewfld(NODE *p); -int freetemp(int k); diff --git a/usr.bin/pcc/mip/reader.c b/usr.bin/pcc/mip/reader.c index 67292997d02..fd192cc7f0d 100644 --- a/usr.bin/pcc/mip/reader.c +++ b/usr.bin/pcc/mip/reader.c @@ -1,4 +1,4 @@ -/* $OpenBSD: reader.c,v 1.14 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: reader.c,v 1.15 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -90,7 +90,7 @@ static struct interpass prepole; void saveip(struct interpass *ip); void deltemp(NODE *p); -void cvtemps(struct interpass *epil); +static void cvtemps(struct interpass *ipole, int op, int off); NODE *store(NODE *); static void fixxasm(struct interpass *ip); @@ -228,15 +228,17 @@ pass2_compile(struct interpass *ip) if (ip->type != IP_NODE) continue; canon(ip->ip_node); +#ifdef PCC_DEBUG walkf(ip->ip_node, cktree); +#endif if ((ip->ip_node = deluseless(ip->ip_node)) == NULL) { DLIST_REMOVE(ip, qelem); } else while (!DLIST_ISEMPTY(&prepole, qelem)) { - struct interpass *ipp; + struct interpass *tipp; - ipp = DLIST_NEXT(&prepole, qelem); - DLIST_REMOVE(ipp, qelem); - DLIST_INSERT_BEFORE(ip, ipp, qelem); + tipp = DLIST_NEXT(&prepole, qelem); + DLIST_REMOVE(tipp, qelem); + DLIST_INSERT_BEFORE(ip, tipp, qelem); } } @@ -484,7 +486,7 @@ again: switch (o = p->n_op) { case XARG: /* generate code for correct class here */ - geninsn(p->n_left, 1 << p->n_label); +// geninsn(p->n_left, 1 << p->n_label); break; default: @@ -544,7 +546,7 @@ ckmove(NODE *p, NODE *q) * Rewrite node to register after instruction emit. */ static void -rewrite(NODE *p, int rewrite, int cookie) +rewrite(NODE *p, int dorewrite, int cookie) { NODE *l, *r; int o; @@ -580,13 +582,17 @@ rewrite(NODE *p, int rewrite, int cookie) tfree(l); if (optype(o) == BITYPE) tfree(r); - if (rewrite == 0) + if (dorewrite == 0) return; CDEBUG(("rewrite: %p, reg %s\n", p, p->n_reg == -1? "<none>" : rnames[DECRA(p->n_reg, 0)])); p->n_rval = DECRA(p->n_reg, 0); } +#ifndef XASM_TARGARG +#define XASM_TARGARG(x,y) 0 +#endif + /* * printout extended assembler. */ @@ -597,26 +603,38 @@ genxasm(NODE *p) int n = 1, o = 0; char *w; - for (q = p->n_left; q->n_op == CM; q = q->n_left) - n++; - nary = tmpalloc(sizeof(NODE *)*n); - o = n; - for (q = p->n_left; q->n_op == CM; q = q->n_left) { - gencode(q->n_right->n_left, INREGS); - nary[--o] = q->n_right; - } - gencode(q->n_left, INREGS); - nary[--o] = q; + if (p->n_left->n_op != ICON || p->n_left->n_type != STRTY) { + for (q = p->n_left; q->n_op == CM; q = q->n_left) + n++; + nary = tmpalloc(sizeof(NODE *)*n); + o = n; + for (q = p->n_left; q->n_op == CM; q = q->n_left) { + gencode(q->n_right->n_left, INREGS); + nary[--o] = q->n_right; + } + gencode(q->n_left, INREGS); + nary[--o] = q; + } else + nary = 0; w = p->n_name; putchar('\t'); while (*w != 0) { if (*w == '%') { - if (w[1] < '1' || w[1] > (n + '0')) - uerror("bad xasm arg number"); + if (w[1] == '%') + putchar('%'); + else if (XASM_TARGARG(w, nary)) + ; /* handled by target */ + else if (w[1] < '0' || w[1] > (n + '0')) + uerror("bad xasm arg number %c", w[1]); else - adrput(stdout, nary[(int)w[1]-'1']->n_left); + adrput(stdout, nary[(int)w[1]-'0']->n_left); w++; + } else if (*w == '\\') { /* Always 3-digit octal */ + int num = *++w - '0'; + num = (num << 3) + *++w - '0'; + num = (num << 3) + *++w - '0'; + putchar(num); } else putchar(*w); w++; @@ -1080,8 +1098,10 @@ comperr(char *str, ...) va_end(ap); prfil = stderr; +#ifdef PCC_DEBUG if (nodepole && nodepole->n_op != FREE) fwalk(nodepole, e2print, 0); +#endif exit(1); } @@ -1146,6 +1166,7 @@ mkbinode(int op, NODE *left, NODE *right, TWORD type) p->n_right = right; p->n_type = type; p->n_regw = NULL; + p->n_su = 0; return p; } @@ -1161,6 +1182,7 @@ mkunode(int op, NODE *left, int rval, TWORD type) p->n_rval = rval; p->n_type = type; p->n_regw = NULL; + p->n_su = 0; return p; } @@ -1187,67 +1209,220 @@ rspecial(struct optab *q, int what) return -1; } +#ifndef XASM_NUMCONV +#define XASM_NUMCONV(x,y,z) 0 +#endif + +/* + * change numeric argument redirections to the correct node type after + * cleaning up the other nodes. + * be careful about input operands that may have different value than output. + */ +static void +delnums(NODE *p, void *arg) +{ + struct interpass *ip = arg, *ip2; + NODE *r = ip->ip_node->n_left; + NODE *q; + TWORD t; + int cnt; + + if (p->n_name[0] < '0' || p->n_name[0] > '9') + return; /* not numeric */ + if ((q = listarg(r, p->n_name[0] - '0', &cnt)) == NIL) + comperr("bad delnums"); + + /* target may have opinions whether to do this conversion */ + if (XASM_NUMCONV(ip, p, q)) + return; + + /* Delete number by adding move-to/from-temp. Later on */ + /* the temps may be rewritten to other LTYPEs */ + t = p->n_left->n_type; + r = mklnode(TEMP, 0, epp->ip_tmpnum++, t); + + /* pre node */ + ip2 = ipnode(mkbinode(ASSIGN, tcopy(r), p->n_left, t)); + DLIST_INSERT_BEFORE(ip, ip2, qelem); + + /* post node */ + ip2 = ipnode(mkbinode(ASSIGN, q->n_left, tcopy(r), t)); + DLIST_INSERT_AFTER(ip, ip2, qelem); + + p->n_left = tcopy(r); + q->n_left = r; + + p->n_name = tmpstrdup(q->n_name); + if (*p->n_name == '=') + p->n_name++; +} + /* * Ensure that a node is correct for the destination. */ static void -ltypify(struct interpass *ip, NODE *p) +ltypify(NODE *p, void *arg) { + struct interpass *ip = arg; struct interpass *ip2; TWORD t = p->n_left->n_type; NODE *q, *r; - char *w; -// int asg = 0, and = 0; + int cw, ooff; + char *c; -#ifdef notyet +again: if (myxasm(ip, p)) return; /* handled by target-specific code */ -#endif - w = p->n_name; -// if (*w == '=') -// w++, asg = 1; - switch (*w) { + + cw = xasmcode(p->n_name); + switch (XASMVAL(cw)) { + case 'p': + /* pointer */ + /* just make register of it */ + p->n_name = tmpstrdup(p->n_name); + c = strchr(p->n_name, XASMVAL(cw)); /* cannot fail */ + *c = 'r'; + /* FALLTHROUGH */ + case 'g': /* general; any operand */ case 'r': /* general reg */ /* set register class */ p->n_label = gclass(p->n_left->n_type); - if (optype(p->n_left->n_op) == LTYPE) + if (p->n_left->n_op == REG || p->n_left->n_op == TEMP) + break; + q = p->n_left; + r = (cw & XASMINOUT ? tcopy(q) : q); + p->n_left = mklnode(TEMP, 0, epp->ip_tmpnum++, t); + if ((cw & XASMASG) == 0) { + ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), r, t)); + DLIST_INSERT_BEFORE(ip, ip2, qelem); + } + if (cw & (XASMASG|XASMINOUT)) { + /* output parameter */ + ip2 = ipnode(mkbinode(ASSIGN, q, tcopy(p->n_left), t)); + DLIST_INSERT_AFTER(ip, ip2, qelem); + } + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + break; + + case 'm': /* memory operand */ + /* store and reload value */ + q = p->n_left; + if (optype(q->n_op) == LTYPE) { + if (q->n_op == TEMP) { + ooff = BITOOR(freetemp(szty(t))); + cvtemps(ip, q->n_rval, ooff); + } else if (q->n_op == REG) + comperr("xasm m and reg"); + } else if (q->n_op == UMUL && + (q->n_left->n_op != TEMP && q->n_left->n_op != REG)) { + t = q->n_left->n_type; + ooff = epp->ip_tmpnum++; + ip2 = ipnode(mkbinode(ASSIGN, + mklnode(TEMP, 0, ooff, t), q->n_left, t)); + q->n_left = mklnode(TEMP, 0, ooff, t); + DLIST_INSERT_BEFORE(ip, ip2, qelem); + } + break; + + case 'i': /* immediate constant */ + case 'n': /* numeric constant */ + if (p->n_left->n_op == ICON) break; - q = mklnode(TEMP, 0, epp->ip_tmpnum++, t); - r = tcopy(q); - ip2 = ipnode(mkbinode(ASSIGN, q, p->n_left, t)); - DLIST_INSERT_BEFORE(ip, ip2, qelem); - p->n_left = r; + p->n_name = tmpstrdup(p->n_name); + c = strchr(p->n_name, XASMVAL(cw)); /* cannot fail */ + if (c[1]) { + c[0] = c[1], c[1] = 0; + goto again; + } else + uerror("constant required"); break; + default: uerror("unsupported xasm option string '%s'", p->n_name); } - - -// fwalk(p, e2print, 0); } /* Extended assembler hacks */ static void -fixxasm(struct interpass *ipole) +fixxasm(struct interpass *pole) { struct interpass *ip; NODE *p; - DLIST_FOREACH(ip, ipole, qelem) { + DLIST_FOREACH(ip, pole, qelem) { if (ip->type != IP_NODE || ip->ip_node->n_op != XASM) continue; - /* Got an assembler node */ + thisline = ip->lineno; p = ip->ip_node->n_left; + if (p->n_op == ICON && p->n_type == STRTY) + continue; + + /* replace numeric redirections with its underlying type */ + flist(p, delnums, ip); + /* * Ensure that the arg nodes can be directly addressable * We decide that everything shall be LTYPE here. */ - for (; p->n_op == CM; p = p->n_left) - ltypify(ip, p->n_right); - ltypify(ip, p); - p = ip->ip_node->n_right; - if (p->n_op != ICON || p->n_type != STRTY) - uerror("xasm constraints not supported"); + flist(p, ltypify, ip); } } + +/* + * Extract codeword from xasm string */ +int +xasmcode(char *s) +{ + int cw = 0; + + while (*s) { + switch ((int)*s) { + case '=': cw |= XASMASG; break; + case '&': cw |= XASMCONSTR; break; + case '+': cw |= XASMINOUT; break; + default: + if ((*s >= 'a' && *s <= 'z') || + (*s >= 'A' && *s <= 'Z') || + (*s >= '0' && *s <= '9')) { + cw |= *s; + return cw; + } + uerror("bad xasm constraint %c", *s); + } + s++; + } + return cw; +} + +static int xasnum, xoffnum; + +static void +xconv(NODE *p) +{ + if (p->n_op != TEMP || p->n_rval != xasnum) + return; + p->n_op = OREG; + p->n_rval = FPREG; + p->n_lval = xoffnum; +} + +/* + * Convert nodes of type TEMP to op with lval off. + */ +static void +cvtemps(struct interpass *ipl, int tnum, int off) +{ + struct interpass *ip; + + xasnum = tnum; + xoffnum = off; + + DLIST_FOREACH(ip, ipl, qelem) + if (ip->type == IP_NODE) + walkf(ip->ip_node, xconv); + walkf(ipl->ip_node, xconv); +} diff --git a/usr.bin/pcc/mip/regs.c b/usr.bin/pcc/mip/regs.c index 55f605a3629..0528bb21b95 100644 --- a/usr.bin/pcc/mip/regs.c +++ b/usr.bin/pcc/mip/regs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: regs.c,v 1.16 2008/04/11 20:45:52 stefan Exp $ */ +/* $OpenBSD: regs.c,v 1.17 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright (c) 2005 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -162,14 +162,18 @@ newblock(NODE *p) REGW *nb = &nblock[regno(p)]; if (nb->link.q_forw == 0) { DLIST_INSERT_AFTER(&initial, nb, link); +#ifdef PCC_DEBUG ASGNUM(nb) = regno(p); RDEBUG(("Adding longtime %d for tmp %d\n", nb->nodnum, regno(p))); +#endif } if (nb->r_class == 0) nb->r_class = gclass(p->n_type); +#ifdef PCC_DEBUG RDEBUG(("newblock: p %p, node %d class %d\n", p, nb->nodnum, nb->r_class)); +#endif return nb; } @@ -280,11 +284,18 @@ nsucomp(NODE *p) return need; } +#ifdef PCC_DEBUG #define ADCL(n, cl) \ for (i = 0; i < n; i++, w++) { w->r_class = cl; \ DLIST_INSERT_BEFORE(&initial, w, link); SETNUM(w); \ UDEBUG(("Adding " #n " %d\n", w->nodnum)); \ } +#else +#define ADCL(n, cl) \ + for (i = 0; i < n; i++, w++) { w->r_class = cl; \ + DLIST_INSERT_BEFORE(&initial, w, link); SETNUM(w); \ + } +#endif UDEBUG(("node %p numregs %d\n", p, nxreg+1)); w = p->n_regw = tmpalloc(sizeof(REGW) * (nxreg+1)); @@ -297,7 +308,9 @@ nsucomp(NODE *p) SETNUM(w); if (w->r_class) DLIST_INSERT_BEFORE(&initial, w, link); +#ifdef PCC_DEBUG UDEBUG(("Adding short %d class %d\n", w->nodnum, w->r_class)); +#endif w++; ADCL(nareg, CLASSA); ADCL(nbreg, CLASSB); @@ -391,7 +404,7 @@ ncnt(int needs) return i; } -static inline REGW * +static REGW * popwlist(REGW *l) { REGW *w = DLIST_NEXT(l, link); @@ -408,7 +421,7 @@ static REGM coalescedMoves, constrainedMoves, frozenMoves, worklistMoves, activeMoves; enum { COAL, CONSTR, FROZEN, WLIST, ACTIVE }; -static inline REGM * +static REGM * popmlist(REGM *l) { REGM *w = DLIST_NEXT(l, link); @@ -426,7 +439,7 @@ popmlist(REGM *l) * * Bitfields are used for liveness. Bit arrays are allocated on the * heap for the "live" variable and on the stack for the in, out, gen - * and kill variables. Therefore, for a temp number, the bit number must + * and killed variables. Therefore, for a temp number, the bit number must * be biased with tempmin. * * There may be an idea to use a different data structure to store @@ -497,7 +510,9 @@ LIVEDELR(REGW *x) { struct lives *l; +#ifdef PCC_DEBUG RDEBUG(("LIVEDELR: %d\n", x->nodnum)); +#endif DLIST_FOREACH(l, &lused, link) { if (l->var != x) continue; @@ -594,9 +609,9 @@ AddEdge(REGW *u, REGW *v) { ADJL *x; +#ifdef PCC_DEBUG RRDEBUG(("AddEdge: u %d v %d\n", ASGNUM(u), ASGNUM(v))); -#ifdef PCC_DEBUG #if 0 if (ASGNUM(u) == 0) comperr("AddEdge 0"); @@ -698,7 +713,9 @@ addalledges(REGW *e) int i, j, k; struct lives *l; +#ifdef PCC_DEBUG RDEBUG(("addalledges for %d\n", e->nodnum)); +#endif if (e->r_class == -1) return; /* unused */ @@ -727,7 +744,9 @@ addalledges(REGW *e) /* short-lived temps */ RDEBUG(("addalledges shortlived ")); DLIST_FOREACH(l, &lused, link) { +#ifdef PCC_DEBUG RRDEBUG(("%d ", ASGNUM(l->var))); +#endif AddEdge(l->var, e); } RDEBUG(("done\n")); @@ -743,7 +762,9 @@ moveadd(REGW *def, REGW *use) if (def == use) return; /* no move to itself XXX - ``shouldn't happen'' */ +#ifdef PCC_DEBUG RDEBUG(("moveadd: def %d use %d\n", ASGNUM(def), ASGNUM(use))); +#endif r = WORKLISTMOVEADD(use, def); MOVELISTADD(def, r); @@ -818,6 +839,50 @@ addedge_r(NODE *p, REGW *w) } /* + * add/del parameter from live set. + */ +static void +setxarg(NODE *p) +{ + int i, ut = 0, in = 0; + int cw; + + if (p->n_op == ICON && p->n_type == STRTY) + return; + + RDEBUG(("setxarg %p %s\n", p, p->n_name)); + cw = xasmcode(p->n_name); + if (XASMISINP(cw)) + in = 1; + if (XASMISOUT(cw)) + ut = 1; + + switch (XASMVAL(cw)) { + case 'g': + if (p->n_left->n_op != REG && p->n_left->n_op != TEMP) + break; + /* FALLTHROUGH */ + case 'r': + i = regno(p->n_left); + if (ut) { + REGW *rw = p->n_left->n_op == REG ? ablock : nblock; + LIVEDEL(i); + addalledges(&rw[i]); + } + if (in) { + LIVEADD(i); + } + break; + case 'i': + case 'm': + case 'n': + break; + default: + comperr("bad ixarg %s", p->n_name); + } +} + +/* * Do the in-tree part of liveness analysis. (the difficult part) * * Walk down the tree in reversed-evaluation order (backwards). @@ -1018,8 +1083,11 @@ insnwalk(NODE *p) case LTYPE: switch (o) { - case TEMP: case REG: + if (!TESTBIT(validregs, regno(p))) + break; /* never add moves */ + /* FALLTHROUGH */ + case TEMP: i = regno(p); rr = (o == TEMP ? &nblock[i] : &ablock[i]); if (rv != rr) { @@ -1039,9 +1107,101 @@ insnwalk(NODE *p) } } -static bittype **gen, **kill, **in, **out; -//static int ntemp, emax; +static bittype **gen, **killed, **in, **out; +#define MAXNSPILL 100 +static int notspill[MAXNSPILL], nspill; + +static int +innotspill(int n) +{ + int i; + for (i = 0; i < nspill; i++) + if (notspill[i] == n) + return 1; + return 0; +} + +/* + * Found an extended assembler node, so growel out gen/killed nodes. + */ +static void +xasmionize(NODE *p, void *arg) +{ + int bb = *(int *)arg; + int cw, b; + + if (p->n_op == ICON && p->n_type == STRTY) + return; /* dummy end marker */ + + cw = xasmcode(p->n_name); + if (XASMVAL(cw) == 'n' || XASMVAL(cw) == 'm') + return; /* no flow analysis */ + p = p->n_left; + + if (XASMVAL(cw) == 'g' && p->n_op != TEMP && p->n_op != REG) + return; /* no flow analysis */ + + b = regno(p); + if (XASMVAL(cw) == 'r' && p->n_op == TEMP) { + if (!innotspill(b)) { + if (nspill < MAXNSPILL) + notspill[nspill++] = b; + else + werror("MAXNSPILL overbooked"); + } + } + if (XASMISOUT(cw)) { + if (p->n_op == TEMP) { + b -= tempmin+MAXREGS; + BITCLEAR(gen[bb], b); + BITSET(killed[bb], b); + } else if (p->n_op == REG) { + BITCLEAR(gen[bb], b); + BITSET(killed[bb], b); + } else + uerror("bad xasm node type"); + } + if (XASMISINP(cw)) { + if (p->n_op == TEMP) { + BITSET(gen[bb], (b - tempmin+MAXREGS)); + } else if (p->n_op == REG) { + BITSET(gen[bb], b); + } else if (optype(p->n_op) != LTYPE) { + if (XASMVAL(cw) == 'r') + uerror("couldn't find available register"); + else + uerror("bad xasm node type2"); + } + } +} + +/* + * Check that given constraints are valid. + */ +static void +xasmconstr(NODE *p, void *arg) +{ + int i; + + if (p->n_op == ICON && p->n_type == STRTY) + return; /* no constraints */ + + if (strcmp(p->n_name, "cc") == 0 || strcmp(p->n_name, "memory") == 0) + return; + + for (i = 0; i < MAXREGS; i++) + if (strcmp(rnames[i], p->n_name) == 0) { + addalledges(&ablock[i]); + return; + } + + comperr("unsupported xasm constraint %s", p->n_name); +} + +/* + * Set/clear long term liveness for regs and temps. + */ static void unionize(NODE *p, int bb) { @@ -1065,19 +1225,19 @@ unionize(NODE *p, int bb) #ifdef notyet for (i = 0; i < szty(p->n_type); i++) { BITCLEAR(gen[bb], (b+i)); - BITSET(kill[bb], (b+i)); + BITSET(killed[bb], (b+i)); } #else i = 0; BITCLEAR(gen[bb], (b+i)); - BITSET(kill[bb], (b+i)); + BITSET(killed[bb], (b+i)); #endif unionize(p->n_right, bb); return; } else if (p->n_left->n_op == REG) { int b = regno(p->n_left); BITCLEAR(gen[bb], b); - BITSET(kill[bb], b); + BITSET(killed[bb], b); unionize(p->n_right, bb); return; } @@ -1104,14 +1264,19 @@ LivenessAnalysis(void) int i, bbnum; /* - * generate the gen-kill sets for all basic blocks. + * generate the gen-killed sets for all basic blocks. */ DLIST_FOREACH(bb, &bblocks, bbelem) { bbnum = bb->bbnum; for (ip = bb->last; ; ip = DLIST_PREV(ip, qelem)) { - /* gen/kill is 'p', this node is 'n' */ - if (ip->type == IP_NODE) - unionize(ip->ip_node, bbnum); + /* gen/killed is 'p', this node is 'n' */ + if (ip->type == IP_NODE) { + if (ip->ip_node->n_op == XASM) + flist(ip->ip_node->n_left, + xasmionize, &bbnum); + else + unionize(ip->ip_node, bbnum); + } if (ip == bb->first) break; } @@ -1123,9 +1288,9 @@ LivenessAnalysis(void) for (i = 0; i < xbits; i++) if (TESTBIT(gen[bbnum], i)) PRTRG(i); - printf("\nkill: "); + printf("\nkilled: "); for (i = 0; i < xbits; i++) - if (TESTBIT(kill[bbnum], i)) + if (TESTBIT(killed[bbnum], i)) PRTRG(i); printf("\n"); } @@ -1172,17 +1337,18 @@ Build(struct interpass *ipole) /* Just fetch space for the temporaries from stack */ gen = alloca(nbblocks*sizeof(bittype*)); - kill = alloca(nbblocks*sizeof(bittype*)); + killed = alloca(nbblocks*sizeof(bittype*)); in = alloca(nbblocks*sizeof(bittype*)); out = alloca(nbblocks*sizeof(bittype*)); for (i = 0; i < nbblocks; i++) { BITALLOC(gen[i],alloca,xbits); - BITALLOC(kill[i],alloca,xbits); + BITALLOC(killed[i],alloca,xbits); BITALLOC(in[i],alloca,xbits); BITALLOC(out[i],alloca,xbits); } BITALLOC(saved,alloca,xbits); + nspill = 0; LivenessAnalysis(); /* register variable temporaries are live */ @@ -1202,7 +1368,7 @@ Build(struct interpass *ipole) again = 0; /* XXX - loop should be in reversed execution-order */ DLIST_FOREACH_REVERSE(bb, &bblocks, bbelem) { - int i = bb->bbnum; + i = bb->bbnum; SETCOPY(saved, out[i], j, xbits); SLIST_FOREACH(cn, &bb->children, cfgelem) { SETSET(out[i], in[cn->bblock->bbnum], j, xbits); @@ -1210,7 +1376,7 @@ Build(struct interpass *ipole) SETCMP(again, saved, out[i], j, xbits); SETCOPY(saved, in[i], j, xbits); SETCOPY(in[i], out[i], j, xbits); - SETCLEAR(in[i], kill[i], j, xbits); + SETCLEAR(in[i], killed[i], j, xbits); SETSET(in[i], gen[i], j, xbits); SETCMP(again, saved, in[i], j, xbits); } @@ -1239,8 +1405,14 @@ Build(struct interpass *ipole) live[j/NUMBITS] = 0; SETCOPY(live, out[i], j, xbits); for (ip = bb->last; ; ip = DLIST_PREV(ip, qelem)) { - if (ip->type == IP_NODE) - insnwalk(ip->ip_node); + if (ip->type == IP_NODE) { + if (ip->ip_node->n_op == XASM) { + flist(ip->ip_node->n_right, + xasmconstr, 0); + listf(ip->ip_node->n_left, setxarg); + } else + insnwalk(ip->ip_node); + } if (ip == bb->first) break; } @@ -1248,7 +1420,6 @@ Build(struct interpass *ipole) #ifdef PCC_DEBUG if (rdebug) { - int i; struct AdjSet *w; ADJL *x; REGW *y; @@ -1329,7 +1500,9 @@ DecrementDegree(REGW *w, int c) { int wast; +#ifdef PCC_DEBUG RRDEBUG(("DecrementDegree: w %d, c %d\n", ASGNUM(w), c)); +#endif wast = trivially_colorable(w); NCLASS(w, c)--; @@ -1354,7 +1527,9 @@ Simplify(void) w = POPWLIST(simplifyWorklist); PUSHWLIST(w, selectStack); +#ifdef PCC_DEBUG RDEBUG(("Simplify: node %d class %d\n", ASGNUM(w), w->r_class)); +#endif l = w->r_adjList; for (; l; l = l->r_next) { @@ -1376,10 +1551,10 @@ GetAlias(REGW *n) static int OK(REGW *t, REGW *r) { +#ifdef PCC_DEBUG RDEBUG(("OK: t %d CLASS(t) %d adjSet(%d,%d)=%d\n", ASGNUM(t), CLASS(t), ASGNUM(t), ASGNUM(r), adjSet(t, r))); -#ifdef PCC_DEBUG if (rdebug > 1) { ADJL *w; int ndeg = 0; @@ -1438,14 +1613,18 @@ Conservative(REGW *u, REGW *v) #ifdef oldcons int i, ncl[NUMCLASS+1]; +#ifdef PCC_DEBUG if (CLASS(u) != CLASS(v)) comperr("Conservative: u(%d = %d), v(%d = %d)", ASGNUM(u), CLASS(u), ASGNUM(v), CLASS(v)); +#endif for (i = 0; i < NUMCLASS+1; i++) ncl[i] = 0; +#ifdef PCC_DEBUG RDEBUG(("Conservative (%d,%d)\n", ASGNUM(u), ASGNUM(v))); +#endif for (w = ADJLIST(u); w; w = w->r_next) { n = w->a_temp; @@ -1540,7 +1719,9 @@ Combine(REGW *u, REGW *v) ADJL *l; REGW *t; +#ifdef PCC_DEBUG RDEBUG(("Combine (%d,%d)\n", ASGNUM(u), ASGNUM(v))); +#endif if (ONLIST(v) == &freezeWorklist) { DELWLIST(v); @@ -1549,12 +1730,14 @@ Combine(REGW *u, REGW *v) } PUSHWLIST(v, coalescedNodes); ALIAS(v) = u; +#ifdef PCC_DEBUG if (rdebug) { printf("adjlist(%d): ", ASGNUM(v)); for (l = ADJLIST(v); l; l = l->r_next) printf("%d ", l->a_temp->nodnum); printf("\n"); } +#endif #if 1 { MOVL *m0 = MOVELIST(v); @@ -1592,6 +1775,7 @@ Combine(REGW *u, REGW *v) DELWLIST(u); PUSHWLIST(u, spillWorklist); } +#ifdef PCC_DEBUG if (rdebug) { ADJL *w; printf("Combine %d class (%d): ", ASGNUM(u), CLASS(u)); @@ -1604,6 +1788,7 @@ if (rdebug) { } printf("\n"); } +#endif } static void @@ -1621,9 +1806,11 @@ Coalesce(void) else u = x, v = y; +#ifdef PCC_DEBUG RDEBUG(("Coalesce: src %d dst %d u %d v %d x %d y %d\n", ASGNUM(m->src), ASGNUM(m->dst), ASGNUM(u), ASGNUM(v), ASGNUM(x), ASGNUM(y))); +#endif if (CLASS(m->src) != CLASS(m->dst)) comperr("Coalesce: src class %d, dst class %d", @@ -1668,8 +1855,10 @@ FreezeMoves(REGW *u) v = GetAlias(x); else v = GetAlias(y); +#ifdef PCC_DEBUG RDEBUG(("FreezeMoves: u %d (%d,%d) v %d\n", ASGNUM(u),ASGNUM(x),ASGNUM(y),ASGNUM(v))); +#endif DLIST_REMOVE(m, link); PUSHMLIST(m, frozenMoves, FROZEN); if (ONLIST(v) != &freezeWorklist) @@ -1697,7 +1886,9 @@ Freeze(void) */ u = POPWLIST(freezeWorklist); PUSHWLIST(u, simplifyWorklist); +#ifdef PCC_DEBUG RDEBUG(("Freeze %d\n", ASGNUM(u))); +#endif FreezeMoves(u); } @@ -1707,9 +1898,11 @@ SelectSpill(void) REGW *w; RDEBUG(("SelectSpill\n")); +#ifdef PCC_DEBUG if (rdebug) DLIST_FOREACH(w, &spillWorklist, link) printf("SelectSpill: %d\n", ASGNUM(w)); +#endif /* First check if we can spill register variables */ DLIST_FOREACH(w, &spillWorklist, link) { @@ -1720,6 +1913,8 @@ SelectSpill(void) if (w == &spillWorklist) { /* try to find another long-range variable */ DLIST_FOREACH(w, &spillWorklist, link) { + if (innotspill(w - nblock)) + continue; if (w >= &nblock[tempmin] && w < &nblock[tempmax]) break; } @@ -1743,7 +1938,9 @@ SelectSpill(void) DLIST_REMOVE(w, link); PUSHWLIST(w, simplifyWorklist); +#ifdef PCC_DEBUG RDEBUG(("Freezing node %d\n", ASGNUM(w))); +#endif FreezeMoves(w); } @@ -1807,13 +2004,17 @@ AssignColors(struct interpass *ip) while (!WLISTEMPTY(selectStack)) { w = POPWLIST(selectStack); okColors = classmask(CLASS(w)); +#ifdef PCC_DEBUG RDEBUG(("classmask av %d, class %d: %x\n", w->nodnum, CLASS(w), okColors)); +#endif for (x = ADJLIST(w); x; x = x->r_next) { o = GetAlias(x->a_temp); +#ifdef PCC_DEBUG RRDEBUG(("Adj(%d): %d (%d)\n", ASGNUM(w), ASGNUM(o), ASGNUM(x->a_temp))); +#endif if (ONLIST(o) == &coloredNodes || ONLIST(o) == &precolored) { @@ -1827,32 +2028,43 @@ AssignColors(struct interpass *ip) } if (okColors == 0) { PUSHWLIST(w, spilledNodes); +#ifdef PCC_DEBUG RDEBUG(("Spilling node %d\n", ASGNUM(w))); +#endif } else { PUSHWLIST(w, coloredNodes); c = ffs(okColors)-1; COLOR(w) = color2reg(c, CLASS(w)); +#ifdef PCC_DEBUG RDEBUG(("Coloring %d with %s, free %x\n", ASGNUM(w), rnames[COLOR(w)], okColors)); +#endif } } DLIST_FOREACH(w, &coalescedNodes, link) { REGW *ww = GetAlias(w); COLOR(w) = COLOR(ww); if (ONLIST(ww) == &spilledNodes) { +#ifdef PCC_DEBUG RDEBUG(("coalesced node %d spilled\n", w->nodnum)); +#endif ww = DLIST_PREV(w, link); DLIST_REMOVE(w, link); PUSHWLIST(w, spilledNodes); w = ww; - } else + } else { +#ifdef PCC_DEBUG RDEBUG(("Giving coalesced node %d color %s\n", w->nodnum, rnames[COLOR(w)])); +#endif + } } +#ifdef PCC_DEBUG if (rdebug) DLIST_FOREACH(w, &coloredNodes, link) printf("%d: color %s\n", ASGNUM(w), rnames[COLOR(w)]); +#endif if (DLIST_ISEMPTY(&spilledNodes, link)) { struct interpass *ip2; DLIST_FOREACH(ip2, ip, qelem) @@ -1869,6 +2081,7 @@ static REGW *spole; static void longtemp(NODE *p) { + NODE *l, *r; REGW *w; if (p->n_op != TEMP) @@ -1881,9 +2094,10 @@ longtemp(NODE *p) w->r_color = BITOOR(freetemp(szty(p->n_type))); w->r_class = 1; } - p->n_op = OREG; - p->n_lval = w->r_color; - p->n_rval = FPREG; + l = mklnode(REG, 0, FPREG, INCREF(p->n_type)); + r = mklnode(ICON, w->r_color, 0, INT); + p->n_left = mkbinode(PLUS, l, r, INCREF(p->n_type)); + p->n_op = UMUL; p->n_regw = NULL; break; } @@ -1910,10 +2124,14 @@ shorttemp(NODE *p) /* XXX - use canaddr() */ if (p->n_op == OREG || p->n_op == NAME) { DLIST_REMOVE(w, link); +#ifdef PCC_DEBUG RDEBUG(("Node %d already in memory\n", ASGNUM(w))); +#endif break; } +#ifdef PCC_DEBUG RDEBUG(("rewriting node %d\n", ASGNUM(w))); +#endif off = BITOOR(freetemp(szty(p->n_type))); l = mklnode(OREG, off, FPREG, p->n_type); @@ -2118,7 +2336,7 @@ prtreg(FILE *fp, NODE *p) { int i, n = p->n_su == -1 ? 0 : ncnt(table[TBLIDX(p->n_su)].needs); - if (use_regw) { + if (use_regw || p->n_reg > 0x40000000 || p->n_reg < 0) { fprintf(fp, "TEMP "); if (p->n_regw != NULL) { for (i = 0; i < n+1; i++) @@ -2246,7 +2464,8 @@ onlyperm: /* XXX - should not have to redo all */ continue; nodepole = ip->ip_node; thisline = ip->lineno; - geninsn(ip->ip_node, FOREFF); + if (ip->ip_node->n_op != XASM) + geninsn(ip->ip_node, FOREFF); nsucomp(ip->ip_node); walkf(ip->ip_node, traclass); } @@ -2254,9 +2473,13 @@ onlyperm: /* XXX - should not have to redo all */ RDEBUG(("nsucomp allocated %d temps (%d,%d)\n", tempmax-tempmin, tempmin, tempmax)); +#ifdef PCC_DEBUG use_regw = 1; +#endif RPRINTIP(ipole); +#ifdef PCC_DEBUG use_regw = 0; +#endif RDEBUG(("ngenregs: numtemps %d (%d, %d)\n", tempmax-tempmin, tempmin, tempmax)); @@ -2322,7 +2545,7 @@ onlyperm: /* XXX - should not have to redo all */ /* * If the original color of this permreg is used for * coloring another register, swap them to avoid - * unneccessary moves. + * unnecessary moves. */ for (j = i+1; j < NPERMREG-1; j++) { if (nblock[j+tempmin].r_color != permregs[i]) diff --git a/usr.bin/pcc/vax/local.c b/usr.bin/pcc/vax/local.c index 28749650e79..60493c8352c 100644 --- a/usr.bin/pcc/vax/local.c +++ b/usr.bin/pcc/vax/local.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local.c,v 1.5 2008/01/12 17:30:42 ragge Exp $ */ +/* $OpenBSD: local.c,v 1.6 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -503,3 +503,7 @@ fixdef(struct symtab *sp) { } +void +pass1_lastchance(struct interpass *ip) +{ +} diff --git a/usr.bin/pcc/vax/local2.c b/usr.bin/pcc/vax/local2.c index 18cc926a886..8d6fdfc5094 100644 --- a/usr.bin/pcc/vax/local2.c +++ b/usr.bin/pcc/vax/local2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local2.c,v 1.6 2007/12/22 22:56:31 stefan Exp $ */ +/* $OpenBSD: local2.c,v 1.7 2008/08/17 18:40:13 ragge Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -1023,3 +1023,12 @@ void mflags(char *str) { } +/* + * Do something target-dependent for xasm arguments. + * Supposed to find target-specific constraints and rewrite them. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + return 0; +} |