summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/pcc/cc/Makefile9
-rw-r--r--usr.bin/pcc/cc/cc.131
-rw-r--r--usr.bin/pcc/cc/cc.c563
-rw-r--r--usr.bin/pcc/ccconfig.h3
-rw-r--r--usr.bin/pcc/ccom/cgram.y461
-rw-r--r--usr.bin/pcc/ccom/gcc_compat.c31
-rw-r--r--usr.bin/pcc/ccom/init.c29
-rw-r--r--usr.bin/pcc/ccom/main.c107
-rw-r--r--usr.bin/pcc/ccom/optim.c5
-rw-r--r--usr.bin/pcc/ccom/pass1.h99
-rw-r--r--usr.bin/pcc/ccom/pftn.c354
-rw-r--r--usr.bin/pcc/ccom/scan.l59
-rw-r--r--usr.bin/pcc/ccom/stabs.c11
-rw-r--r--usr.bin/pcc/ccom/symtabs.c30
-rw-r--r--usr.bin/pcc/ccom/trees.c174
-rw-r--r--usr.bin/pcc/config.h8
-rw-r--r--usr.bin/pcc/cpp/cpp.15
-rw-r--r--usr.bin/pcc/cpp/cpp.c235
-rw-r--r--usr.bin/pcc/cpp/cpp.h12
-rw-r--r--usr.bin/pcc/cpp/cpy.y4
-rw-r--r--usr.bin/pcc/cpp/scanner.l102
-rw-r--r--usr.bin/pcc/i386/code.c85
-rw-r--r--usr.bin/pcc/i386/local.c475
-rw-r--r--usr.bin/pcc/i386/local2.c191
-rw-r--r--usr.bin/pcc/i386/macdefs.h61
-rw-r--r--usr.bin/pcc/i386/table.c8
-rw-r--r--usr.bin/pcc/mip/common.c81
-rw-r--r--usr.bin/pcc/mip/manifest.h16
-rw-r--r--usr.bin/pcc/mip/match.c27
-rw-r--r--usr.bin/pcc/mip/mkext.c31
-rw-r--r--usr.bin/pcc/mip/node.h7
-rw-r--r--usr.bin/pcc/mip/optim2.c27
-rw-r--r--usr.bin/pcc/mip/pass2.h22
-rw-r--r--usr.bin/pcc/mip/protos.h13
-rw-r--r--usr.bin/pcc/mip/reader.c273
-rw-r--r--usr.bin/pcc/mip/regs.c287
-rw-r--r--usr.bin/pcc/vax/local.c6
-rw-r--r--usr.bin/pcc/vax/local2.c11
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;
+}