-# $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}\"
-.\" $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>
.\"
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
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
.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
-/* $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.
*
#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)
/*
* 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
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 *, ...);
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;
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;
};
struct cppmd cppmds[] = CPPMDADDS;
+#else
+char *cppmdadd[] = CPPMDADD;
+#endif
#ifdef LIBCLIBS
char *libclibs[] = LIBCLIBS;
#else
#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] == '-') {
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) {
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, ','))) {
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;
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++;
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];
outfile = argv[++i];
break;
case 'O':
- Oflag++;
+ if (argv[i][2] == '0')
+ Oflag = 0;
+ else
+ Oflag++;
break;
case 'E':
Eflag++;
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;
}
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");
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++) {
/*
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;
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)
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;
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;
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";
*/
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)
if (dflag)
av[na++] = alist;
av[na++] = 0;
- if (callsys("/bin/as", av)) {
+ if (callsys(as, av)) {
cflag++;
eflag++;
cunlink(tmp4);
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) {
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";
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) {
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);
}
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;
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);
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
{
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) {
exit(8);
}
close(fd);
-
return sfn;
}
+#endif
+
+void *
+ccmalloc(int size)
+{
+ void *rv;
+
+ if ((rv = malloc(size)) == NULL)
+ error("malloc failed");
+ return rv;
+}
-/* $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).
}
#define MAXCPPMDARGS 8
+#define ELFABI
#define STABS
-/* $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).
/*
* 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 */
# 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);
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).
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
| { 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
;
/*
;
function_specifiers:
- C_FUNSPEC {
- if (fun_inline)
- uerror("too many inline");
- fun_inline = 1;
- }
+ C_FUNSPEC { fun_inline = 1; }
;
type_specifier: C_TYPE { $$ = $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;
}
;
-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)); }
;
/*
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));
}
;
*/
parameter_list: parameter_declaration { $$ = $1; }
| parameter_list ',' parameter_declaration {
- $$ = block(CM, $1, $3, 0, 0, 0);
+ $$ = cmop($1, $3);
}
;
*/
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);
}
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);
}
/*
* 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;
}
;
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 {
uerror("designator must be non-negative");
$2 = 0;
}
- $$ = bdty(LB, NULL, $2);
+ $$ = biop(LB, NIL, bcon($2));
}
| C_STROP C_NAME {
if ($1 != DOT)
/* 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: '{' {
bc->next = savctx;
savctx = bc;
bccode();
+ if (sspflag && blevel == 2)
+ sspstart();
}
;
}
| 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);
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 ';'
| 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); }
;
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());
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());
forprefix: C_FOR '(' .e ';' .e ';' {
if ($3)
ecomp($3);
- else if (!reached)
- werror("loop not entered at top");
savebc();
contlab = getlab();
brklab = getlab();
| 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
;
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
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
}
| '(' cast_type ')' clbrace init_list optcomma '}' {
endinit();
- spname = $4;
- $$ = buildtree(NAME, NIL, NIL);
+ $$ = nametree($4);
}
| term '[' e ']' {
$$ = buildtree( UMUL,
| 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 {
}
if (s->sflags & SINLINE)
inline_ref(s);
- spname = s;
- $$ = buildtree(NAME, NIL, NIL);
+ $$ = nametree(s);
}
| term '('
;
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:
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:
return q;
}
+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)
{
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;
return typ->n_sp;
}
+/*
+ * 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.
*/
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 */
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;
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;
branch(int lbl)
{
int r = reached++;
- ecomp(block(GOTO, bcon(lbl), NIL, INT, 0, 0));
+ ecomp(biop(GOTO, bcon(lbl), NIL));
reached = r;
}
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++ == '\\')
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)
{
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);
}
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 *
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)
{
/* 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;
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;
}
{
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);
}
-/* $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.
* 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 },
};
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;
-/* $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).
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--;
}
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 */
}
}
}
}
+#ifdef PCC_DEBUG
if (idebug>1) {
printf("findoff: off %lld\n", off);
prtstk(pstk);
}
+#endif
return off;
}
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;
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 */
(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;
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;
/* 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;
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);
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:
-/* $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.
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
+
#include <unistd.h>
#include <signal.h>
#include <string.h>
#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);
{ "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, },
};
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
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':
#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;
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();
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;
}
#endif
+ if (sspflag)
+ sspinit();
+
(void) yyparse();
yyaccpt();
-/* $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.
*
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);
-/* $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.
*
* 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"
#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
extern int reached;
extern int isinlining;
-/* tunnel to buildtree for name id's */
-
-extern struct symtab *spname;
-
extern int sdebug, idebug, pdebug;
/* various labels */
extern int retlab;
/* pragma globals */
-extern int pragma_packed, pragma_aligned;
+extern int pragma_allpacked, pragma_packed, pragma_aligned;
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),
*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 *);
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 *);
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);
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
*/
#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)
-/* $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.
#include "cgram.h"
-struct symtab *spname;
struct symtab *cftnsp;
int arglistcnt, dimfuncnt; /* statistics */
int symtabcnt, suedefcnt; /* statistics */
int rstr;
struct symtab *rsym;
struct symtab *rb;
+ int flags;
+#define LASTELM 1
} *rpole;
/*
void
defid(NODE *q, int class)
{
+ extern int fun_inline;
struct symtab *p;
TWORD type, qual;
TWORD stp, stq;
p = q->n_sp;
+ if (p->sname == NULL)
+ cerror("defining null identifier");
+
#ifdef PCC_DEBUG
if (ddebug) {
printf("defid(%s (%p), ", p->sname, p);
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;
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;
case REGISTER:
if (blevel == slev)
goto redec;
- ; /* mismatch.. */
+ break; /* mismatch.. */
+ case SNULL:
+ if (fun_inline && ISFTN(type))
+ goto done;
+ break;
}
mismatch:
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
stabs_newsym(p);
#endif
+done:
fixdef(p); /* Leave last word to target */
#ifdef PCC_DEBUG
if (ddebug)
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);
} 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;
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++;
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;
*/
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
soumemb(NODE *n, char *name, int class)
{
struct symtab *sp, *lsp;
+ int incomp;
if (rpole == NULL)
cerror("soumemb");
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
case PTR:
return( SZPOINT(ty) * mult );
case ARY:
+ if (d->ddim == NOOFFSET)
+ return 0;
mult *= d->ddim;
d++;
continue;
}
/*
- * 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)
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 {
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);
/*
* 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;
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++]);
}
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;
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)
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:
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) {
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) {
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
}
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)
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 },
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);
}
*/
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)
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) {
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;
}
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;
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)
}
if (class & FIELD) {
- if (rpole && rpole->rsou != STNAME)
+ if (rpole && rpole->rsou != STNAME && rpole->rsou != UNAME)
uerror("illegal use of field");
return(class);
}
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");
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);
+}
%{
-/* $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.
IS (u|U|l|L)*
%{
+#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#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);
"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); }
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); }
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];
}
/* 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;
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
-/* $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).
void
stabs_newsym(struct symtab *s)
{
+ extern int fun_inline;
char *sname;
char ostr[MAXPSTR];
int suesize;
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);
}
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);
-/* $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.
#include "pass1.h"
+#include <stdint.h>
+
/*
* These definitions are used in the patricia tree that stores
* the strings.
* Returns a struct symtab.
*/
struct symtab *
-lookup(char *key, int ttype)
+lookup(char *key, int stype)
{
struct symtab *sym;
struct tree *w, *new, *last;
int type, uselvl;
intptr_t ix, match, code = (intptr_t)key;
- type = ttype & SMASK;
+ type = stype & SMASK;
uselvl = (blevel > 0 && type != SSTRING);
/*
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];
ix = code ^ match;
if (ix == 0)
return sym;
- else if (ttype & SNOCREAT)
+ else if (stype & SNOCREAT)
return NULL;
#ifdef PCC_DEBUG
* 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;
* 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);
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",
-/* $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.
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;
}
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) */
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);
}
+/*
+ * 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.
*/
t1 = DECREF(t1);
t2 = DECREF(t2);
}
- werror("illegal pointer combination");
+ if (Wpointer_sign)
+ werror("illegal pointer combination");
}
}
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;
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++;
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);
fwalk(p, eprint, 0);
#endif
if (!reached) {
- werror("statement not reached");
+ if (Wunreachable_code)
+ werror("statement not reached");
reached = 1;
}
p = optim(p);
ecode(p);
}
+
#if defined(MULTIPASS)
void
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)
{
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;
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:
else
sz = sizeof(struct interpass);
- ip = isinlining ? permalloc(sz) : tmpalloc(sz);
+ ip = inlalloc(sz);
ip->type = type;
ip->lineno = lineno;
switch (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;
cerror("bad send_passt type %d", type);
}
va_end(ap);
+ pass1_lastchance(ip); /* target-specific info */
if (isinlining)
inline_addarg(ip);
else
-/* $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
-.\" $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>
.\"
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
-/* $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).
#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 {
* 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 */
#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
void line(void);
void flbuf(void);
void usage(void);
+usch *xstrdup(char *str);
+usch *prtprag(usch *opb);
+
int
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++;
Mflag++;
break;
+ case 'P': /* Inhibit generation of line numbers */
+ Pflag++;
+ break;
+
case 'S':
case 'I':
if ((w = calloc(sizeof(struct incs), 1)) == NULL)
thisnl = NULL;
slow = 1;
+ readmac++;
base = osp = stringbuf;
goto found;
thisnl = NULL;
break;
+ case CMNT:
+ getcmnt();
+ break;
+
case STRING:
case '\n':
case NUMBER:
}
if (thisnl == NULL) {
slow = 0;
+ readmac--;
savch(0);
return base;
}
}
- error("preamture EOF");
+ error("premature EOF");
/* NOTREACHED */
return NULL; /* XXX gcc */
}
return c;
}
+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()
{
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;
np = lookup((usch *)yytext, ENTER);
redef = np->value != NULL;
+ readmac = 1;
sbeg = stringbuf;
if ((c = yylex()) == '(') {
narg = 0;
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;
}
/* 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 */
savch(CONC);
if ((c = yylex()) == WSPACE)
c = yylex();
+#ifdef GCC_VARI
+ if (c == '\n')
+ break;
+ wascon = 1;
+ goto loop;
+#endif
}
continue;
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) {
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;
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')
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 */
}
#endif
slow = 0;
+ for (i = 0; i < narg; i++)
+ free(args[i]);
return;
bad: error("bad define");
usch *opb;
int t, plev;
- slow = 1;
- putstr((usch *)"\n#pragma ");
+ slow++;
if ((t = yylex()) == WSPACE)
t = yylex();
if (t != '(')
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");
}
struct symtab *nl;
int c, noexp = 0, orgexp;
usch *och, *stksv;
- extern int yyleng;
#ifdef CPP_DEBUG
if (dflag) {
}
}
#endif
+ readmac++;
while ((c = yylex()) != WARN) {
switch (c) {
case NOEXP: noexp++; break;
unpstr((usch *)yytext);
if (orgexp == -1)
cunput(EXPAND);
+ else if (orgexp == -2)
+ cunput(EXPAND), cunput(EXPAND);
else if (orgexp == 1)
cunput(NOEXP);
unpstr(och);
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 */
unpstr(stksv);
savstr(nl->namep);
}
+ if (stksv)
+ free(stksv);
+ break;
+
+ case CMNT:
+ getcmnt();
break;
case STRING:
}
if (noexp)
error("expmac noexp=%d", noexp);
+ readmac--;
DPRINT(("return from expmac\n"));
}
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.
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'))
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) {
/* scan the input buffer (until WARN) and save result on heap */
expmac(rp);
+ free(args);
}
usch *
putstr(usch *s)
{
for (; *s; s++) {
+ if (*s == PRAGS) {
+ s = prtprag(s);
+ continue;
+ }
outbuf[obufp++] = *s;
if (obufp == CPPBUF || (istty && *s == '\n'))
flbuf();
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;
+}
-/* $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).
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;
int infil;
usch *curptr;
usch *maxread;
+ usch *ostr;
usch *buffer;
usch bbuf[NAMEMAX+CPPBUF+1];
} *ifiles;
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);
-/* $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).
/*
* 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 '?' ':'
%{
-/* $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.
%{
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);
}
#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);
IS (u|U|l|L)*
WS [\t ]
-%s IFR CONTR DEF
+%s IFR CONTR DEF COMMENT
%%
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)
}
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]; }
"//".*$ { /* 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 != '*') {
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;
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]);
+ }
+ }
%%
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");
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;
}
{
#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);
}
}
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++) {
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? */
{
error("invalid operator in preprocessor expression: %s", op);
}
+
+int
+cinput()
+{
+ return input();
+}
-/* $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.
# include "pass1.h"
+int lastloc = -1;
+
/*
* Define everything needed to print out some data (or text).
* This means segment, alignment, visibility, etc.
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;
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);
}
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;
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));
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);
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
}
/*
}
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;
;
r->n_left = block(CM, l, r->n_left, INT, 0, MKSUE(INT));
}
+#endif
return p;
}
-/* $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.
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));
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
+
}
/*
static NODE *
picstatic(NODE *p)
{
+
+#if defined(ELFABI)
+
NODE *q, *r;
struct symtab *sp;
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);
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
tlspic(NODE *p)
{
NODE *q, *r;
- struct symtab *sp;
+ struct symtab *sp, *sp2;
/*
* creates:
/* 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);
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));
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);
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)
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,
static void
fixnames(NODE *p)
{
+#if !defined(PECOFFABI)
+
struct symtab *sp;
struct suedef *sue;
NODE *q;
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;
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)
p->n_left = q;
q->n_sue = sue;
}
+#endif
}
void
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;
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;
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 \"");
NODE *p;
defloc(sp);
- p = bcon(0);
+ p = xbcon(0, NULL, WCHAR_TYPE);
do {
if (*s++ == '\\')
p->n_lval = esccon(&s);
{
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;
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");
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;
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;
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
}
/*
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)
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;
}
/*
if (gottls)
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
}
-/* $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.
# 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;
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++)
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) {
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
}
/*
int addto;
ftype = ipp->ipp_type;
+
#ifdef LANG_F77
if (ipp->ipp_vis)
printf(" .globl %s\n", ipp->ipp_name);
* add to the stack.
*/
addto = offcalc(ipp);
+#if defined(MACHOABI)
+ addto = (addto + 15) & ~15; /* stack alignment */
+#endif
prtprolog(ipp, addto);
}
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
}
/*
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");
}
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;
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 */
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;
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 */
}
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;
+ }
+}
-/* $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.
/* 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 */
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))
#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 */
*/
#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
-/* $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.
/* 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", },
SNAME|SOREG, TLDOUBLE,
SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
0, RDEST,
- " fstt AL\n", },
+ " fst AL\n", },
{ ASSIGN, FOREFF,
SNAME|SOREG, TLDOUBLE,
0, RNOP,
" jmp LL\n", },
-#ifdef GCC_COMPAT
+#if defined(GCC_COMPAT) || defined(LANG_F77)
{ GOTO, FOREFF,
SAREG, TANY,
SANY, TANY,
-/* $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.
static NODE *freelink;
static int usednodes;
+#ifndef LANG_F77
NODE *
talloc()
{
printf("alloc node %p from memory\n", p);
return p;
}
+#endif
/*
* make a fresh copy of p
return(q);
}
+#ifndef LANG_F77
/*
* ensure that all nodes have been freed
*/
if ((usednodes - inlnodecnt) != 0)
cerror("usednodes == %d, inlnodecnt %d", usednodes, inlnodecnt);
}
+#endif
/*
* free the tree p
NODE *
nfree(NODE *p)
{
+#ifndef LANG_F77
extern int inlnodecnt, recovernodes;
+#endif
NODE *l;
#ifdef PCC_DEBUG_NODES
NODE *q;
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
(*f)(t, down, &down1, &down2);
- switch (coptype( t->n_op )) {
+ switch (OPTYPE( t->n_op )) {
case BITYPE:
fwalk( t->n_left, f, down1 );
{
int opty;
- opty = coptype(t->n_op);
+
+ opty = OPTYPE(t->n_op);
if (opty != LTYPE)
walkf( t->n_left, f );
"void",
"signed", /* pass1 */
"bool", /* pass1 */
+ "fcomplex", /* pass1 */
+ "dcomplex", /* pass1 */
+ "lcomplex", /* pass1 */
"?", "?"
};
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()
{
*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;
+}
-/* $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.
*
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);
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
};
/*
void *tmpalloc(int size);
void tmpfree(void);
char *newstring(char *, int len);
+char *tmpstrdup(char *str);
+
/* command-line processing */
void mflags(char *);
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 */
-/* $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.
* 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);
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)
#include <string.h>
+#define FMTdPTR "%td"
+
int chkop[DSIZE];
void mktables(void);
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
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++;
}
}
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++;
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 {
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++;
}
}
-/* $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.
union {
int _label;
int _stalign;
+ int _flags;
struct suedef *_sue;
} n_6;
union {
#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
#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.
*
-/* $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.
l->n_op = REG;
l->n_lval = 0;
l->n_rval = FPREG;
-
}
}
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);
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);
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)
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;
-/* $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.
*
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 *);
#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);
struct labelinfo {
struct basicblock **arr;
- unsigned int size;
+ int size;
unsigned int low;
};
struct bblockinfo {
- unsigned int size;
+ int size;
struct basicblock **arr;
};
-/* $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, ...);
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);
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);
-/* $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.
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);
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);
}
}
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:
* 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;
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.
*/
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++;
va_end(ap);
prfil = stderr;
+#ifdef PCC_DEBUG
if (nodepole && nodepole->n_op != FREE)
fwalk(nodepole, e2print, 0);
+#endif
exit(1);
}
p->n_right = right;
p->n_type = type;
p->n_regw = NULL;
+ p->n_su = 0;
return p;
}
p->n_rval = rval;
p->n_type = type;
p->n_regw = NULL;
+ p->n_su = 0;
return p;
}
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);
+}
-/* $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.
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;
}
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));
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);
return i;
}
-static inline REGW *
+static REGW *
popwlist(REGW *l)
{
REGW *w = DLIST_NEXT(l, link);
worklistMoves, activeMoves;
enum { COAL, CONSTR, FROZEN, WLIST, ACTIVE };
-static inline REGM *
+static REGM *
popmlist(REGM *l)
{
REGM *w = DLIST_NEXT(l, link);
*
* 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
{
struct lives *l;
+#ifdef PCC_DEBUG
RDEBUG(("LIVEDELR: %d\n", x->nodnum));
+#endif
DLIST_FOREACH(l, &lused, link) {
if (l->var != x)
continue;
{
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");
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 */
/* 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"));
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);
addedge_r(p->n_left, 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)
*
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) {
}
}
-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)
{
#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;
}
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;
}
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");
}
/* 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 */
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);
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);
}
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;
}
#ifdef PCC_DEBUG
if (rdebug) {
- int i;
struct AdjSet *w;
ADJL *x;
REGW *y;
{
int wast;
+#ifdef PCC_DEBUG
RRDEBUG(("DecrementDegree: w %d, c %d\n", ASGNUM(w), c));
+#endif
wast = trivially_colorable(w);
NCLASS(w, c)--;
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) {
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;
#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;
ADJL *l;
REGW *t;
+#ifdef PCC_DEBUG
RDEBUG(("Combine (%d,%d)\n", ASGNUM(u), ASGNUM(v)));
+#endif
if (ONLIST(v) == &freezeWorklist) {
DELWLIST(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);
DELWLIST(u);
PUSHWLIST(u, spillWorklist);
}
+#ifdef PCC_DEBUG
if (rdebug) {
ADJL *w;
printf("Combine %d class (%d): ", ASGNUM(u), CLASS(u));
}
printf("\n");
}
+#endif
}
static 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",
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)
*/
u = POPWLIST(freezeWorklist);
PUSHWLIST(u, simplifyWorklist);
+#ifdef PCC_DEBUG
RDEBUG(("Freeze %d\n", ASGNUM(u)));
+#endif
FreezeMoves(u);
}
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) {
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;
}
DLIST_REMOVE(w, link);
PUSHWLIST(w, simplifyWorklist);
+#ifdef PCC_DEBUG
RDEBUG(("Freezing node %d\n", ASGNUM(w)));
+#endif
FreezeMoves(w);
}
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) {
}
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)
static void
longtemp(NODE *p)
{
+ NODE *l, *r;
REGW *w;
if (p->n_op != TEMP)
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;
}
/* 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);
{
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++)
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);
}
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));
/*
* 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])
-/* $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.
*
{
}
+void
+pass1_lastchance(struct interpass *ip)
+{
+}
-/* $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.
*
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;
+}