[Midnightbsd-cvs] src: usr.bin/pcc: WIP: Update to .99
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Tue Jan 20 16:09:44 EST 2009
Log Message:
-----------
WIP: Update to .99
Modified Files:
--------------
src/usr.bin/pcc:
ccconfig.h (r1.1 -> r1.2)
config.h (r1.3 -> r1.4)
src/usr.bin/pcc/cc:
Makefile (r1.8 -> r1.9)
cc.c (r1.2 -> r1.3)
src/usr.bin/pcc/ccom:
Makefile (r1.2 -> r1.3)
ccom.1 (r1.1 -> r1.2)
cgram.y (r1.1 -> r1.2)
gcc_compat.c (r1.1 -> r1.2)
init.c (r1.1 -> r1.2)
inline.c (r1.1 -> r1.2)
main.c (r1.2 -> r1.3)
optim.c (r1.1 -> r1.2)
pass1.h (r1.1 -> r1.2)
pftn.c (r1.1 -> r1.2)
scan.l (r1.1 -> r1.2)
stabs.c (r1.1 -> r1.2)
symtabs.c (r1.1 -> r1.2)
trees.c (r1.1 -> r1.2)
src/usr.bin/pcc/cpp:
Makefile (r1.6 -> r1.7)
cpp.c (r1.3 -> r1.4)
cpp.h (r1.2 -> r1.3)
cpy.y (r1.1 -> r1.2)
scanner.l (r1.1 -> r1.2)
token.c (r1.1 -> r1.2)
src/usr.bin/pcc/i386:
code.c (r1.1 -> r1.2)
local.c (r1.1 -> r1.2)
local2.c (r1.1 -> r1.2)
macdefs.h (r1.1 -> r1.2)
order.c (r1.1 -> r1.2)
table.c (r1.1 -> r1.2)
src/usr.bin/pcc/mip:
common.c (r1.1 -> r1.2)
compat.c (r1.1 -> r1.2)
manifest.h (r1.1 -> r1.2)
match.c (r1.1 -> r1.2)
mkext.c (r1.1 -> r1.2)
node.h (r1.1 -> r1.2)
optim2.c (r1.1 -> r1.2)
pass2.h (r1.1 -> r1.2)
protos.h (r1.1 -> r1.2)
reader.c (r1.1 -> r1.2)
regs.c (r1.1 -> r1.2)
Added Files:
-----------
src/usr.bin/pcc/amd64:
code.c (r1.1)
local.c (r1.1)
local2.c (r1.1)
macdefs.h (r1.1)
order.c (r1.1)
table.c (r1.1)
src/usr.bin/pcc/cpp:
pcpp.1 (r1.1)
src/usr.bin/pcc/sparc64:
code.c (r1.1)
local.c (r1.1)
local2.c (r1.1)
macdefs.h (r1.1)
order.c (r1.1)
table.c (r1.1)
Removed Files:
-------------
src/usr.bin/pcc/cpp:
cpp.1
-------------- next part --------------
--- /dev/null
+++ usr.bin/pcc/amd64/order.c
@@ -0,0 +1,273 @@
+/* $Id: order.c,v 1.1 2008/11/27 05:25:15 mickey Exp $ */
+/*
+ * Copyright (c) 2008 Michael Shalayeff
+ * Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+# include "pass2.h"
+
+#include <string.h>
+
+int canaddr(NODE *);
+
+/* is it legal to make an OREG or NAME entry which has an
+ * offset of off, (from a register of r), if the
+ * resulting thing had type t */
+int
+notoff(TWORD t, int r, CONSZ off, char *cp)
+{
+ return(0); /* YES */
+}
+
+/*
+ * Turn a UMUL-referenced node into OREG.
+ * Be careful about register classes, this is a place where classes change.
+ */
+void
+offstar(NODE *p, int shape)
+{
+ NODE *r;
+
+ if (x2debug)
+ printf("offstar(%p)\n", p);
+
+ if (isreg(p))
+ return; /* Is already OREG */
+
+ r = p->n_right;
+ if( p->n_op == PLUS || p->n_op == MINUS ){
+ if( r->n_op == ICON ){
+ if (isreg(p->n_left) == 0)
+ (void)geninsn(p->n_left, INAREG);
+ /* Converted in ormake() */
+ return;
+ }
+ if (r->n_op == LS && r->n_right->n_op == ICON &&
+ r->n_right->n_lval == 2 && p->n_op == PLUS) {
+ if (isreg(p->n_left) == 0)
+ (void)geninsn(p->n_left, INAREG);
+ if (isreg(r->n_left) == 0)
+ (void)geninsn(r->n_left, INAREG);
+ return;
+ }
+ }
+ (void)geninsn(p, INAREG);
+}
+
+/*
+ * Do the actual conversion of offstar-found OREGs into real OREGs.
+ */
+void
+myormake(NODE *q)
+{
+ NODE *p, *r;
+
+ if (x2debug)
+ printf("myormake(%p)\n", q);
+
+ p = q->n_left;
+ if (p->n_op == PLUS && (r = p->n_right)->n_op == LS &&
+ r->n_right->n_op == ICON && r->n_right->n_lval == 2 &&
+ p->n_left->n_op == REG && r->n_left->n_op == REG) {
+ q->n_op = OREG;
+ q->n_lval = 0;
+ q->n_rval = R2PACK(p->n_left->n_rval, r->n_left->n_rval, 0);
+ tfree(p);
+ }
+}
+
+/*
+ * Shape matches for UMUL. Cooperates with offstar().
+ */
+int
+shumul(NODE *p, int shape)
+{
+
+ if (x2debug)
+ printf("shumul(%p)\n", p);
+
+ /* Turns currently anything into OREG on x86 */
+ if (shape & SOREG)
+ return SROREG;
+ return SRNOPE;
+}
+
+/*
+ * Rewrite operations on binary operators (like +, -, etc...).
+ * Called as a result of table lookup.
+ */
+int
+setbin(NODE *p)
+{
+
+ if (x2debug)
+ printf("setbin(%p)\n", p);
+ return 0;
+
+}
+
+/* setup for assignment operator */
+int
+setasg(NODE *p, int cookie)
+{
+ if (x2debug)
+ printf("setasg(%p)\n", p);
+ return(0);
+}
+
+/* setup for unary operator */
+int
+setuni(NODE *p, int cookie)
+{
+ return 0;
+}
+
+/*
+ * Special handling of some instruction register allocation.
+ */
+struct rspecial *
+nspecial(struct optab *q)
+{
+ switch (q->op) {
+ case OPLOG:
+ {
+ static struct rspecial s[] = { { NEVER, EAX }, { 0 } };
+ return s;
+ }
+
+ case STASG:
+ case STARG:
+ {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NEVER, ECX }, { 0 } };
+ return s;
+ }
+
+ case DIV:
+ if (q->lshape == SBREG) {
+ static struct rspecial s[] = {
+ { NEVER, AL }, { NEVER, AH },
+ { NLEFT, AL }, { NRES, AL },
+ { NORIGHT, AH }, { NORIGHT, AL }, { 0 } };
+ return s;
+ } else if (q->lshape == SAREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NLEFT, EAX }, { NRES, EAX },
+ { NORIGHT, EDX }, { NORIGHT, EAX }, { 0 } };
+ return s;
+ } else if (q->lshape & SCREG) {
+ static struct rspecial s[] = {
+ { NEVER, RAX }, { NEVER, RDX },
+ { NLEFT, RAX }, { NRES, RAX },
+ { NORIGHT, RDX }, { NORIGHT, RAX }, { 0 } };
+ return s;
+ }
+ break;
+ case MOD:
+ if (q->lshape == SBREG) {
+ static struct rspecial s[] = {
+ { NEVER, AL }, { NEVER, AH },
+ { NLEFT, AL }, { NRES, AH },
+ { NORIGHT, AH }, { NORIGHT, AL }, { 0 } };
+ return s;
+ } else if (q->lshape == SAREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NLEFT, EAX }, { NRES, EDX },
+ { NORIGHT, EDX }, { NORIGHT, EAX }, { 0 } };
+ return s;
+ } else if (q->lshape & SCREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NEVER, ECX }, { NRES, RAX }, { 0 } };
+ return s;
+ }
+ break;
+ case MUL:
+ if (q->lshape == SBREG) {
+ static struct rspecial s[] = {
+ { NEVER, AL }, { NEVER, AH },
+ { NLEFT, AL }, { NRES, AL }, { 0 } };
+ return s;
+ } else if (q->lshape & SCREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NEVER, ECX }, { NRES, RAX }, { 0 } };
+ return s;
+ }
+ break;
+ case LS:
+ case RS:
+ static struct rspecial s[] = {
+ { NRIGHT, CL }, { NOLEFT, RCX }, { 0 } };
+ return s;
+ break;
+
+ default:
+ break;
+ }
+ comperr("nspecial entry %d", q - table);
+ return 0; /* XXX gcc */
+}
+
+/*
+ * Set evaluation order of a binary node if it differs from default.
+ */
+int
+setorder(NODE *p)
+{
+ return 0; /* nothing differs on x86 */
+}
+
+/*
+ * set registers in calling conventions live.
+ */
+int *
+livecall(NODE *p)
+{
+ static int r[] = { EAX, EBX, -1 };
+ int off = 1;
+
+#ifdef TLS
+ if (p->n_left->n_op == ICON &&
+ strcmp(p->n_left->n_name, "___tls_get_addr at PLT") == 0)
+ off--;
+#endif
+
+ return kflag ? &r[off] : &r[2];
+}
+
+/*
+ * Signal whether the instruction is acceptable for this target.
+ */
+int
+acceptable(struct optab *op)
+{
+ return 1;
+}
--- /dev/null
+++ usr.bin/pcc/amd64/macdefs.h
@@ -0,0 +1,337 @@
+/* $Id: macdefs.h,v 1.2 2008/12/10 17:59:30 mickey Exp $ */
+/*
+ * Copyright (c) 2008 Michael Shalayeff
+ * Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Machine-dependent defines for both passes.
+ */
+
+/*
+ * Convert (multi-)character constant to integer.
+ */
+#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24);
+
+#define ARGINIT 64 /* # bits above fp where arguments start */
+#define AUTOINIT 0 /* # bits below fp where automatics start */
+
+/*
+ * Storage space requirements
+ */
+#define SZCHAR 8
+#define SZBOOL 8
+#define SZSHORT 16
+#define SZINT 32
+#define SZLONG 64
+#define SZPOINT(t) 64
+#define SZLONGLONG 64
+#define SZFLOAT 32
+#define SZDOUBLE 64
+#define SZLDOUBLE 128
+
+/*
+ * Alignment constraints
+ */
+#define ALCHAR 8
+#define ALBOOL 8
+#define ALSHORT 16
+#define ALINT 32
+#define ALLONG 64
+#define ALPOINT 64
+#define ALLONGLONG 64
+#define ALFLOAT 32
+#define ALDOUBLE 64
+#define ALLDOUBLE 128
+#define ALSTRUCT 128
+#define ALSTACK 64
+#define ALMAX 128
+
+/*
+ * Min/max values.
+ */
+#define MIN_CHAR -128
+#define MAX_CHAR 127
+#define MAX_UCHAR 255
+#define MIN_SHORT -32768
+#define MAX_SHORT 32767
+#define MAX_USHORT 65535
+#define MIN_INT (-0x7fffffff-1)
+#define MAX_INT 0x7fffffff
+#define MAX_UNSIGNED 0xffffffff
+#define MIN_LONG MIN_LONGLONG
+#define MAX_LONG MAX_LONGLONG
+#define MAX_ULONG MAX_ULONGLONG
+#define MIN_LONGLONG 0x8000000000000000LL
+#define MAX_LONGLONG 0x7fffffffffffffffLL
+#define MAX_ULONGLONG 0xffffffffffffffffULL
+
+/* Default char is signed */
+#undef CHAR_UNSIGNED
+#define BOOL_TYPE CHAR /* what used to store _Bool */
+#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 */
+#endif
+
+/*
+ * Use large-enough types.
+ */
+typedef long long CONSZ;
+typedef unsigned long long U_CONSZ;
+typedef long long OFFSZ;
+
+#define CONFMT "%lld" /* format for printing constants */
+#define LABFMT ".L%d" /* format for printing labels */
+#define STABLBL ".LL%d" /* format for stab (debugging) labels */
+#ifdef LANG_F77
+#define BLANKCOMMON "_BLNK_"
+#define MSKIREG (M(TYSHORT)|M(TYLONG))
+#define TYIREG TYLONG
+#define FSZLENG FSZLONG
+#define AUTOREG EBP
+#define ARGREG EBP
+#define ARGOFFSET 8
+#endif
+
+#define BACKAUTO /* stack grows negatively for automatics */
+#define BACKTEMP /* stack grows negatively for temporaries */
+
+#undef FIELDOPS /* no bit-field instructions */
+#define RTOLBYTES /* bytes are numbered right to left */
+
+#define ENUMSIZE(high,low) INT /* enums are always stored in full int */
+
+#define FINDMOPS /* i386 has instructions that modifies memory */
+
+/* Definitions mostly used in pass2 */
+
+#define BYTEOFF(x) ((x)&03)
+#define wdal(k) (BYTEOFF(k)==0)
+#define BITOOR(x) (x) /* bit offset to oreg offset XXX die! */
+
+#define STOARG(p)
+#define STOFARG(p)
+#define STOSTARG(p)
+#define genfcall(a,b) gencall(a,b)
+
+#define szty(t) (((t) == DOUBLE || (t) == FLOAT || (t) == LONG || \
+ (t) == ULONG || (t) == LONGLONG || (t) == ULONGLONG) ? 2 : \
+ (t) == LDOUBLE ? 4 : 1)
+
+/*
+ * The x86 has a bunch of register classes, most of them interfering
+ * with each other. All registers are given a sequential number to
+ * identify it which must match rnames[] in local2.c.
+ * Class membership and overlaps are defined in the macros RSTATUS
+ * and ROVERLAP below.
+ *
+ * The classes used on x86 are:
+ * A - short and int regs
+ * B - char regs
+ * C - long long regs
+ * D - floating point
+ */
+#define EAX 000 /* Scratch and return register */
+#define EDX 001 /* Scratch and secondary return register */
+#define ECX 002 /* Scratch (and shift count) register */
+#define EBX 003 /* GDT pointer or callee-saved temporary register */
+#define ESI 004 /* Callee-saved temporary register */
+#define EDI 005 /* Callee-saved temporary register */
+#define EBP 006 /* Frame pointer */
+#define ESP 007 /* Stack pointer */
+
+#define AL 010
+#define AH 011
+#define DL 012
+#define DH 013
+#define CL 014
+#define CH 015
+#define BL 016
+#define BH 017
+
+#define RAX 020
+#define RDX 021
+#define RCX 022
+#define RBX 023
+#define RSI 024
+#define RDI 025
+#define RBP 026
+#define RSP 027
+#define R08 030
+#define R09 031
+#define R10 032
+#define R11 033
+#define R12 034
+#define R13 035
+#define R14 036
+#define R15 037
+
+/* The 8 math registers in class D lacks names */
+
+#define MAXREGS 050 /* 40 registers */
+
+#define RSTATUS \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|PERMREG, \
+ SAREG|TEMPREG, SAREG|TEMPREG, 0, 0, \
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, 0, 0, \
+ SCREG|TEMPREG, SCREG|TEMPREG, SCREG|TEMPREG, SCREG|TEMPREG, \
+ SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, \
+ SDREG, SDREG, SDREG, SDREG, SDREG, SDREG, SDREG, SDREG,
+
+#define ROVERLAP \
+ /* 8 basic registers */\
+ { AL, AH, RAX, -1 },\
+ { DL, DH, RDX, -1 },\
+ { CL, CH, RCX, -1 },\
+ { BL, BH, RBX, -1 },\
+ { RSI, -1 },\
+ { RDI, -1 },\
+ { RBP, -1 },\
+ { RSP, -1 },\
+\
+ /* 8 char registers */\
+ { EAX, RAX, -1 },\
+ { EAX, RAX, -1 },\
+ { EDX, RDX, -1 },\
+ { EDX, RDX, -1 },\
+ { ECX, RCX, -1 },\
+ { ECX, RCX, -1 },\
+ { EBX, RBX, -1 },\
+ { EBX, RBX, -1 },\
+\
+ /* 16 long-long-emulating registers */\
+ { EAX, AL, AH, -1 },\
+ { EDX, DL, DH, -1 },\
+ { ECX, CL, CH, -1 },\
+ { EBX, BL, BH, -1 },\
+ { ESI, -1 },\
+ { EDI, -1 },\
+ { EBP, -1 },\
+ { ESP, -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+\
+ /* The fp registers do not overlap with anything */\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },
+
+
+/* Return a register class based on the type of the node */
+#define PCLASS(p) (p->n_type <= UCHAR ? SBREG : \
+ (p->n_type == LONG || p->n_type == ULONG || \
+ p->n_type == LONGLONG || p->n_type == ULONGLONG ? SCREG : \
+ (p->n_type >= FLOAT && p->n_type <= LDOUBLE ? SDREG : SAREG)))
+
+#define NUMCLASS 4 /* highest number of reg classes used */
+
+int COLORMAP(int c, int *r);
+#define GCLASS(x) (x < 8 ? CLASSA : x < 16 ? CLASSB : x < 32 ? CLASSC : CLASSD)
+#define DECRA(x,y) (((x) >> (y*8)) & 255) /* decode encoded regs */
+#define ENCRD(x) (x) /* Encode dest reg in n_reg */
+#define ENCRA1(x) ((x) << 8) /* A1 */
+#define ENCRA2(x) ((x) << 16) /* A2 */
+#define ENCRA(x,y) ((x) << (8+y*8)) /* encode regs in int */
+/* XXX - return char in al? */
+#define RETREG(x) (x == CHAR || x == UCHAR ? AL : \
+ x == LONG || x == ULONG || \
+ x == LONGLONG || x == ULONGLONG ? RAX : \
+ x == FLOAT || x == DOUBLE || x == LDOUBLE ? 32 : EAX)
+
+//#define R2REGS 1 /* permit double indexing */
+
+/* XXX - to die */
+#define FPREG RBP /* frame pointer */
+#define STKREG RSP /* stack pointer */
+
+#define SHSTR (MAXSPECIAL+1) /* short struct */
+#define SFUNCALL (MAXSPECIAL+2) /* struct assign after function call */
+#define SPCON (MAXSPECIAL+3) /* positive nonnamed constant */
+
+/*
+ * Specials that indicate the applicability of machine idioms.
+ */
+#define SMIXOR (MAXSPECIAL+4)
+#define SMILWXOR (MAXSPECIAL+5)
+#define SMIHWXOR (MAXSPECIAL+6)
+
+/*
+ * i386-specific symbol table flags.
+ */
+#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
--- /dev/null
+++ usr.bin/pcc/amd64/table.c
@@ -0,0 +1,1568 @@
+/* $Id: table.c,v 1.1 2008/11/27 05:25:15 mickey Exp $ */
+/*
+ * Copyright (c) 2008 Michael Shalayeff
+ * Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+# include "pass2.h"
+
+# define TLL TLONG|TULONG|TLONGLONG|TULONGLONG
+# define ANYSIGNED TINT|TSHORT|TCHAR
+# define ANYUSIGNED TUNSIGNED|TUSHORT|TUCHAR
+# define ANYFIXED ANYSIGNED|ANYUSIGNED
+# define TUWORD TUNSIGNED
+# define TSWORD TINT
+# define TWORD TUWORD|TSWORD
+#define SHINT SAREG /* short and int */
+#define ININT INAREG
+#define SHCH SBREG /* shape for char */
+#define INCH INBREG
+#define SHLL SCREG /* shape for long long */
+#define INLL INCREG
+#define SHFL SDREG /* shape for float/double */
+#define INFL INDREG /* shape for float/double */
+
+struct optab table[] = {
+/* First entry must be an empty entry */
+{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", },
+
+/* PCONVs are usually not necessary */
+{ PCONV, INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RLEFT,
+ "", },
+
+/*
+ * A bunch conversions of integral<->integral types
+ * There are lots of them, first in table conversions to itself
+ * and then conversions from each type to the others.
+ */
+
+/* itself to itself, including pointers */
+
+/* convert (u)char to (u)char. */
+{ SCONV, INCH,
+ SHCH, TCHAR|TUCHAR,
+ SHCH, TCHAR|TUCHAR,
+ 0, RLEFT,
+ "", },
+
+/* convert pointer to (u)longlong. */
+{ SCONV, INLL,
+ SHLL, TLL|TPOINT,
+ SHLL, TLL,
+ 0, RLEFT,
+ "", },
+
+/* convert double <-> float. nothing to do here */
+{ SCONV, INFL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ "", },
+
+/* convert pointers to pointers and ints. */
+{ SCONV, ININT,
+ SHINT, TPOINT|TWORD,
+ SANY, TPOINT,
+ 0, RLEFT,
+ "", },
+
+/* char to something */
+
+/* convert char to (unsigned) short. */
+{ SCONV, ININT,
+ SBREG|SOREG|SNAME, TCHAR,
+ SAREG, TSHORT|TUSHORT,
+ NASL|NAREG, RESC1,
+ " movsbw AL,A1\n", },
+
+/* convert unsigned char to (u)short. */
+{ SCONV, ININT,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SAREG, TSHORT|TUSHORT,
+ NASL|NAREG, RESC1,
+ " movzbw AL,A1\n", },
+
+/* convert signed char to int (or pointer). */
+{ SCONV, ININT,
+ SHCH|SOREG|SNAME, TCHAR,
+ SAREG, TWORD|TPOINT,
+ NASL|NAREG, RESC1,
+ " movsbl AL,A1\n", },
+
+/* convert unsigned char to (u)int. */
+{ SCONV, ININT,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SAREG, TWORD,
+ NASL|NAREG, RESC1,
+ " movzbl AL,A1\n", },
+
+/* convert char to (u)long long */
+{ SCONV, INLL,
+ SHCH|SOREG|SNAME, TCHAR,
+ SANY, TLL,
+ NCREG|NCSL, RESC1,
+ " movsbq AL,A1\n", },
+
+/* convert unsigned char to (u)long long */
+{ SCONV, INLL,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SANY, TLL,
+ NCREG|NCSL, RESC1,
+ " movzbq AL,A1\n", },
+
+/* convert char (in register) to double XXX - use NTEMP */
+{ SCONV, INFL,
+ SHCH|SOREG|SNAME, TCHAR,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NAREG|NASL|NDREG, RESC2,
+ " movsbl AL,A1\n pushl A1\n" /* XXX fpconv */
+ " fildl (%rsp)\n addl $8,%rsp\n", },
+
+/* convert (u)char (in register) to double XXX - use NTEMP */
+{ SCONV, INFL,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NAREG|NASL|NDREG, RESC2,
+ " movzbl AL,A1\n pushl A1\n" /* XXX fpconv */
+ " fildl (%rsp)\n addl $8,%rsp\n", },
+
+/* short to something */
+
+/* convert short (in memory) to char */
+{ SCONV, INCH,
+ SNAME|SOREG, TSHORT|TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NBREG|NBSL, RESC1,
+ " movb AL,A1\n", },
+
+/* convert short (in reg) to char. */
+{ SCONV, INCH,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL|NBREG|NBSL, RESC1,
+ "ZM", },
+
+/* convert short to (u)int. */
+{ SCONV, ININT,
+ SAREG|SOREG|SNAME, TSHORT,
+ SAREG, TWORD,
+ NASL|NAREG, RESC1,
+ " movswl AL,A1\n", },
+
+/* convert unsigned short to (u)int. */
+{ SCONV, ININT,
+ SAREG|SOREG|SNAME, TUSHORT,
+ SAREG, TWORD,
+ NASL|NAREG, RESC1,
+ " movzwl AL,A1\n", },
+
+/* convert short to (u)long long */
+{ SCONV, INLL,
+ SAREG|SOREG|SNAME, TSHORT,
+ SHLL, TLL,
+ NCREG|NCSL, RESC1,
+ " movswq AL,A1\n", },
+
+/* convert unsigned short to (u)long long */
+{ SCONV, INLL,
+ SAREG|SOREG|SNAME, TUSHORT,
+ SHLL, TLL,
+ NCREG|NCSL, RESC1,
+ " movzwq AL,A1\n", },
+
+/* convert short (in memory) to float/double */
+{ SCONV, INFL,
+ SOREG|SNAME, TSHORT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ " fild AL\n", }, /* XXX fpconv */
+
+/* convert short (in register) to float/double */
+{ SCONV, INFL,
+ SAREG, TSHORT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NTEMP|NDREG, RESC1, /* XXX fpconv */
+ " pushw AL\n fild (%rsp)\n addl $8,%rsp\n", },
+
+/* convert unsigned short to double XXX - use NTEMP */
+{ SCONV, INFL,
+ SAREG|SOREG|SNAME, TUSHORT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NAREG|NASL|NDREG|NTEMP, RESC2,
+ " movzwl AL,A1\n pushl A1\n" /* XXX fpconv */
+ " fildl (%rsp)\n addl $8,%esp\n", },
+
+/* int to something */
+
+/* convert int to char. This is done when register is loaded */
+{ SCONV, INCH,
+ SAREG, TWORD|TPOINT,
+ SANY, TCHAR|TUCHAR,
+ NSPECIAL|NBREG|NBSL, RESC1,
+ "ZM", },
+
+/* convert int to short. Nothing to do */
+{ SCONV, INAREG,
+ SAREG, TWORD,
+ SANY, TSHORT|TUSHORT,
+ 0, RLEFT,
+ "", },
+
+/* convert signed int to (u)long long */
+{ SCONV, INLL,
+ SHINT, TSWORD,
+ SHLL, TLL,
+ NSPECIAL|NCREG|NCSL, RESC1,
+ " cltd\n", },
+
+/* convert unsigned int to (u)long long */
+{ SCONV, INLL,
+ SHINT|SOREG|SNAME, TUWORD|TPOINT,
+ SHLL, TLL,
+ NCSL|NCREG, RESC1,
+ " movzlq AL,A1\n\n", },
+
+/* convert int (in memory) to double */
+{ SCONV, INFL,
+ SOREG|SNAME, TWORD,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ " fildl AL\n", },
+
+/* convert int (in register) to double */
+{ SCONV, INFL,
+ SAREG, TWORD,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NTEMP|NDREG, RESC1, /* XXX fpconv */
+ " pushl AL\n fildl (%esp)\n addl $8,%esp\n", },
+
+/* long long to something */
+
+/* convert (u)long long to (u)char (mem->reg) */
+{ SCONV, INCH,
+ SOREG|SNAME, TLL,
+ SANY, TCHAR|TUCHAR,
+ NBREG|NBSL, RESC1,
+ " movb AL,A1\n", },
+
+/* convert (u)long long to (u)char (reg->reg, hopefully nothing) */
+{ SCONV, INCH,
+ SHLL, TLL,
+ SANY, TCHAR|TUCHAR,
+ NBREG|NBSL, RESC1,
+ "ZS", },
+
+/* convert (u)long long to (u)short (mem->reg) */
+{ SCONV, INAREG,
+ SOREG|SNAME, TLL,
+ SAREG, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " movw AL,A1\n", },
+
+/* convert (u)long long to (u)short (reg->reg, hopefully nothing) */
+{ SCONV, INAREG,
+ SHLL|SOREG|SNAME, TLL,
+ SAREG, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ "ZS", },
+
+/* convert long long to int (mem->reg) */
+{ SCONV, INAREG,
+ SOREG|SNAME, TLL,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ " movl AL,A1\n", },
+
+/* convert long long to int (reg->reg, hopefully nothing) */
+{ SCONV, INAREG,
+ SHLL|SOREG|SNAME, TLL,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ "ZS", },
+
+/* convert long long (in memory) to floating */
+{ SCONV, INFL,
+ SOREG|SNAME, TLONGLONG,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1, /* XXX fpconv */
+ " fildq AL\n", },
+
+/* convert long long (in register) to floating */
+{ SCONV, INFL,
+ SHLL, TLONGLONG,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NTEMP|NDREG, RESC1, /* XXX fpconv */
+ " pushq AL\n\n"
+ " fildq (%esp)\n addl $8,%esp\n", },
+
+/* convert unsigned long long to floating */
+{ SCONV, INFL,
+ SCREG, TULONGLONG,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1, /* XXX fpconv */
+ "ZJ", },
+
+/* float to something */
+
+#if 0 /* go via int by adding an extra sconv in clocal() */
+/* convert float/double to (u) char. XXX should use NTEMP here */
+{ SCONV, INCH,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NBREG, RESC1, /* XXX fpconv */
+ " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
+
+/* convert float/double to (u) int/short/char. XXX should use NTEMP here */
+{ SCONV, INCH,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NCREG, RESC1, /* XXX fpconv */
+ " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
+#endif
+
+/* convert float/double to (u)int. XXX should use NTEMP here */
+{ SCONV, INAREG,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SAREG, TWORD,
+ NAREG, RESC1, /* XXX fpconv */
+#ifdef notdef /* Must round down and nothing else */
+ " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
+#else
+ " subl $12,%esp\n"
+ " fnstcw (%esp)\n"
+ " fnstcw 4(%esp)\n"
+ " movb $12,1(%esp)\n"
+ " fldcw (%esp)\n"
+ " fistpl 8(%esp)\n"
+ " movl 8(%esp),A1\n"
+ " fldcw 4(%esp)\n"
+ " addl $12,%esp\n", },
+#endif
+
+/* convert float/double (in register) to (unsigned) long long */
+/* XXX - unsigned is not handled correct */
+{ SCONV, INLL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHLL, TLONGLONG|TULONGLONG,
+ NCREG, RESC1, /* XXX fpconv */
+#ifdef notdef /* Must round down and nothing else */
+ " subl $8,%esp\n fistpq (%esp)\n"
+ " popl A1\n popl U1\n", },
+#else
+ " subl $16,%esp\n"
+ " fnstcw (%esp)\n"
+ " fnstcw 4(%esp)\n"
+ " movb $12,1(%esp)\n"
+ " fldcw (%esp)\n"
+ " fistpq 8(%esp)\n"
+ " movl 8(%esp),A1\n"
+ " movl 12(%esp),U1\n"
+ " fldcw 4(%esp)\n"
+ " addl $16,%esp\n", },
+#endif
+
+/* slut sconv */
+
+/*
+ * Subroutine calls.
+ */
+
+{ CALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call CL\nZC", },
+
+{ UCALL, FOREFF,
+ SCON, TANY,
+ SAREG, TWORD|TPOINT,
+ 0, 0,
+ " call CL\n", },
+
+{ CALL, INAREG,
+ SCON, TANY,
+ SAREG, TSHORT|TUSHORT|TWORD|TPOINT,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INAREG,
+ SCON, TANY,
+ SAREG, TSHORT|TUSHORT|TWORD|TPOINT,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call CL\n", },
+
+{ CALL, INBREG,
+ SCON, TANY,
+ SBREG, TCHAR|TUCHAR,
+ NBREG, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INBREG,
+ SCON, TANY,
+ SBREG, TCHAR|TUCHAR,
+ NBREG, RESC1, /* should be 0 */
+ " call CL\n", },
+
+{ CALL, INCREG,
+ SCON, TANY,
+ SCREG, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INCREG,
+ SCON, TANY,
+ SCREG, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call CL\n", },
+
+{ CALL, INDREG,
+ SCON, TANY,
+ SDREG, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INDREG,
+ SCON, TANY,
+ SDREG, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ CALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call *AL\nZC", },
+
+{ UCALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call *AL\nZC", },
+
+{ CALL, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ CALL, INBREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NBREG|NBSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INBREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NBREG|NBSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ CALL, INCREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INCREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ CALL, INDREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INDREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+/* struct return */
+{ USTCALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, 0,
+ " call CL\nZC", },
+
+{ USTCALL, INAREG,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ USTCALL, INAREG,
+ SNAME|SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ STCALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, 0,
+ " call CL\nZC", },
+
+{ STCALL, INAREG,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ STCALL, INAREG,
+ SNAME|SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+/*
+ * The next rules handle all binop-style operators.
+ */
+{ PLUS, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " faddl AR\n", },
+
+{ PLUS, INFL|FOREFF,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " faddp\n", },
+
+{ PLUS, INLL|FOREFF,
+ SHLL|SNAME|SOREG, TLL|TPOINT,
+ SONE, TANY,
+ 0, RLEFT,
+ " incq AL\n", },
+
+{ PLUS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TWORD,
+ SONE, TANY,
+ 0, RLEFT,
+ " incl AL\n", },
+
+{ PLUS, INLL,
+ SCREG, TLL|TPOINT,
+ SCON, TWORD,
+ NCREG|NCSL, RESC1,
+ " leaq CR(AL),A1\n", },
+
+{ PLUS, INAREG,
+ SAREG, TWORD,
+ SCON, TANY,
+ NAREG|NASL, RESC1,
+ " leal CR(AL),A1\n", },
+
+{ PLUS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SONE, TANY,
+ 0, RLEFT,
+ " incw AL\n", },
+
+{ PLUS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SONE, TANY,
+ 0, RLEFT,
+ " incb AL\n", },
+
+{ PLUS, INAREG,
+ SAREG, TWORD,
+ SAREG, TWORD,
+ NAREG|NASL|NASR, RESC1,
+ " leal (AL,AR),A1\n", },
+
+{ MINUS, INLL|FOREFF,
+ SCREG|SNAME|SOREG, TLL|TPOINT,
+ SONE, TANY,
+ 0, RLEFT,
+ " decq AL\n", },
+
+{ MINUS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TWORD,
+ SONE, TANY,
+ 0, RLEFT,
+ " decl AL\n", },
+
+{ MINUS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SONE, TANY,
+ 0, RLEFT,
+ " decw AL\n", },
+
+{ MINUS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SONE, TANY,
+ 0, RLEFT,
+ " decb AL\n", },
+
+/* address as register offset, negative */
+{ MINUS, INAREG,
+ SAREG, TWORD|TPOINT,
+ SPCON, TANY,
+ NAREG|NASL, RESC1,
+ " leal -CR(AL),A1\n", },
+
+{ MINUS, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " fsubl AR\n", },
+
+{ MINUS, INFL|FOREFF,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fsubZAp\n", },
+
+/* Simple r/m->reg ops */
+/* m/r |= r */
+{ OPSIMP, INLL|FOREFF|FORCC,
+ SHLL|SNAME|SOREG, TLL|TPOINT,
+ SHLL, TLL|TPOINT,
+ 0, RLEFT|RESCC,
+ " Oq AR,AL\n", },
+
+/* r |= r/m */
+{ OPSIMP, INLL|FOREFF|FORCC,
+ SHLL, TLL|TPOINT,
+ SHLL|SNAME|SOREG, TLL|TPOINT,
+ 0, RLEFT|RESCC,
+ " Oq AR,AL\n", },
+
+/* m/r |= r */
+{ OPSIMP, INAREG|FOREFF|FORCC,
+ SAREG|SNAME|SOREG, TWORD,
+ SAREG, TWORD,
+ 0, RLEFT|RESCC,
+ " Ol AR,AL\n", },
+
+/* r |= r/m */
+{ OPSIMP, INAREG|FOREFF|FORCC,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ 0, RLEFT|RESCC,
+ " Ol AR,AL\n", },
+
+/* m/r |= r */
+{ OPSIMP, INAREG|FOREFF|FORCC,
+ SHINT|SNAME|SOREG, TSHORT|TUSHORT,
+ SHINT, TSHORT|TUSHORT,
+ 0, RLEFT|RESCC,
+ " Ow AR,AL\n", },
+
+/* r |= r/m */
+{ OPSIMP, INAREG|FOREFF|FORCC,
+ SHINT, TSHORT|TUSHORT,
+ SHINT|SNAME|SOREG, TSHORT|TUSHORT,
+ 0, RLEFT|RESCC,
+ " Ow AR,AL\n", },
+
+/* m/r |= r */
+{ OPSIMP, INCH|FOREFF|FORCC,
+ SHCH, TCHAR|TUCHAR,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ 0, RLEFT|RESCC,
+ " Ob AR,AL\n", },
+
+/* r |= r/m */
+{ OPSIMP, INCH|FOREFF|FORCC,
+ SHCH, TCHAR|TUCHAR,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ 0, RLEFT|RESCC,
+ " Ob AR,AL\n", },
+
+/* m/r |= const */
+{ OPSIMP, INLL|FOREFF|FORCC,
+ SCREG|SNAME|SOREG, TLL,
+ SCON, TWORD,
+ 0, RLEFT|RESCC,
+ " Oq AR,AL\n", },
+
+{ OPSIMP, INAREG|FOREFF|FORCC,
+ SAREG|SNAME|SOREG, TWORD,
+ SCON, TWORD,
+ 0, RLEFT|RESCC,
+ " Ol AR,AL\n", },
+
+{ OPSIMP, INAREG|FOREFF|FORCC,
+ SHINT|SNAME|SOREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, RLEFT|RESCC,
+ " Ow AR,AL\n", },
+
+{ OPSIMP, INCH|FOREFF|FORCC,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RLEFT|RESCC,
+ " Ob AR,AL\n", },
+
+/* r |= r/m */
+{ OPSIMP, INLL|FOREFF,
+ SHLL, TLL|TPOINT,
+ SHLL|SNAME|SOREG, TLL|TPOINT,
+ 0, RLEFT,
+ " Oq AR,AL\n", },
+
+/*
+ * The next rules handle all shift operators.
+ */
+/* r/m <<= r */
+{ LS, INLL|FOREFF,
+ SHLL|SNAME|SOREG, TLL,
+ SHLL, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " salq AR,AL\n", },
+
+/* r/m <<= const */
+{ LS, INLL|FOREFF,
+ SHLL|SNAME|SOREG, TLL,
+ SCON, TANY,
+ 0, RLEFT,
+ " salq AR,AL\n", },
+
+/* r/m <<= r */
+{ LS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TWORD,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sall AR,AL\n", },
+
+/* r/m <<= const */
+{ LS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TWORD,
+ SCON, TANY,
+ 0, RLEFT,
+ " sall AR,AL\n", },
+
+/* r/m <<= r */
+{ LS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shlw AR,AL\n", },
+
+/* r/m <<= const */
+{ LS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " shlw AR,AL\n", },
+
+{ LS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " salb AR,AL\n", },
+
+{ LS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " salb AR,AL\n", },
+
+{ RS, INLL|FOREFF,
+ SHLL|SNAME|SOREG, TLONG|TLONGLONG,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sarq AR,AL\n", },
+
+{ RS, INLL|FOREFF,
+ SHLL|SNAME|SOREG, TLONG|TLONGLONG,
+ SCON, TANY,
+ 0, RLEFT,
+ " sarq AR,AL\n", },
+
+{ RS, INLL|FOREFF,
+ SHLL|SNAME|SOREG, TULONG|TULONGLONG,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shrq AR,AL\n", },
+
+{ RS, INLL|FOREFF,
+ SHLL|SNAME|SOREG, TULONG|TULONGLONG,
+ SCON, TANY,
+ 0, RLEFT,
+ " shrq AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSWORD,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sarl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSWORD,
+ SCON, TANY,
+ 0, RLEFT,
+ " sarl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUWORD,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shrl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUWORD,
+ SCON, TANY,
+ 0, RLEFT,
+ " shrl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sarw AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " sarw AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shrw AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " shrw AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sarb AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " sarb AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TUCHAR,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shrb AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TUCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " shrb AR,AL\n", },
+
+/*
+ * The next rules takes care of assignments. "=".
+ */
+{ ASSIGN, FORCC|FOREFF|INLL,
+ SHLL, TLL|TPOINT,
+ SMIXOR, TANY,
+ 0, RDEST,
+ " xorq AL,AL\n\n", },
+
+{ ASSIGN, FOREFF|INLL,
+ SHLL, TLL|TPOINT,
+ SCON, TANY,
+ 0, RDEST,
+ " movabs AR,AL\n", },
+
+{ ASSIGN, FORCC|FOREFF|INAREG,
+ SAREG, TWORD,
+ SMIXOR, TANY,
+ 0, RDEST,
+ " xorl AL,AL\n", },
+
+{ ASSIGN, FOREFF,
+ SAREG|SNAME|SOREG, TWORD,
+ SCON, TANY,
+ 0, 0,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TWORD,
+ SCON, TANY,
+ 0, RDEST,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FORCC|FOREFF|INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SMIXOR, TANY,
+ 0, RDEST,
+ " xorw AL,AL\n", },
+
+{ ASSIGN, FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, 0,
+ " movw AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, RDEST,
+ " movw AR,AL\n", },
+
+{ ASSIGN, FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, 0,
+ " movb AR,AL\n", },
+
+{ ASSIGN, FOREFF|INCH,
+ SHCH, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RDEST,
+ " movb AR,AL\n", },
+
+{ ASSIGN, FOREFF|INLL,
+ SHLL|SNAME|SOREG, TLL,
+ SHLL, TLL,
+ 0, RDEST,
+ " movq AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RDEST,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ 0, RDEST,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ 0, RDEST,
+ " movw AR,AL\n", },
+
+{ ASSIGN, FOREFF|INCH,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SHCH, TCHAR|TUCHAR|TWORD,
+ 0, RDEST,
+ " movb AR,AL\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SFLD, TCHAR|TUCHAR,
+ SBREG|SCON, TCHAR|TUCHAR,
+ NAREG|NBREG, RDEST,
+ " movb AR,A2\n"
+ " movzbl A2,A1\n"
+ " andl $N,AL\n"
+ " sall $H,A1\n"
+ " andl $M,A1\n"
+ " orl A1,AL\n"
+ "F movb AR,AD\n"
+ "FZE", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SFLD, TSHORT|TUSHORT,
+ SAREG|SCON, TSHORT|TUSHORT,
+ NAREG, RDEST,
+ " movw AR,A1\n"
+ " movzwl A1,ZN\n"
+ " andl $N,AL\n"
+ " sall $H,ZN\n"
+ " andl $M,ZN\n"
+ " orl ZN,AL\n"
+ "F movw AR,AD\n"
+ "FZE", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SFLD, TWORD,
+ SAREG|SNAME|SOREG|SCON, TWORD,
+ NAREG, RDEST,
+ " movl AR,A1\n"
+ " andl $N,AL\n"
+ " sall $H,A1\n"
+ " andl $M,A1\n"
+ " orl A1,AL\n"
+ "F movl AR,AD\n"
+ "FZE", },
+
+{ ASSIGN, INDREG|FOREFF,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ "", }, /* This will always be in the correct register */
+
+/* order of table entries is very important here! */
+{ ASSIGN, INFL,
+ SNAME|SOREG, TLDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " fst AL\n", },
+
+{ ASSIGN, FOREFF,
+ SNAME|SOREG, TLDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, 0,
+ " fstpt AL\n", },
+
+{ ASSIGN, INFL,
+ SNAME|SOREG, TDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " fstl AL\n", },
+
+{ ASSIGN, FOREFF,
+ SNAME|SOREG, TDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, 0,
+ " fstpl AL\n", },
+
+{ ASSIGN, INFL,
+ SNAME|SOREG, TFLOAT,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " fsts AL\n", },
+
+{ ASSIGN, FOREFF,
+ SNAME|SOREG, TFLOAT,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, 0,
+ " fstps AL\n", },
+/* end very important order */
+
+{ ASSIGN, INFL|FOREFF,
+ SHFL, TLDOUBLE,
+ SHFL|SOREG|SNAME, TLDOUBLE,
+ 0, RDEST,
+ " fldt AR\n", },
+
+{ ASSIGN, INFL|FOREFF,
+ SHFL, TDOUBLE,
+ SHFL|SOREG|SNAME, TDOUBLE,
+ 0, RDEST,
+ " fldl AR\n", },
+
+{ ASSIGN, INFL|FOREFF,
+ SHFL, TFLOAT,
+ SHFL|SOREG|SNAME, TFLOAT,
+ 0, RDEST,
+ " flds AR\n", },
+
+/* Do not generate memcpy if return from funcall */
+#if 0
+{ STASG, INAREG|FOREFF,
+ SOREG|SNAME|SAREG, TPTRTO|TSTRUCT,
+ SFUNCALL, TPTRTO|TSTRUCT,
+ 0, RRIGHT,
+ "", },
+#endif
+
+{ STASG, INAREG|FOREFF,
+ SOREG|SNAME, TANY,
+ SAREG|SOREG|SNAME, TPTRTO|TANY,
+ NSPECIAL, RRIGHT,
+ "ZQ", },
+
+/*
+ * DIV/MOD/MUL
+ */
+{ DIV, INLL,
+ SCREG, TLONG|TLONGLONG,
+ SCREG|SNAME|SOREG, TLL,
+ NSPECIAL, RDEST,
+ " cltd\n idivq AR\n", },
+
+{ DIV, INAREG,
+ SAREG, TULONG|TULONGLONG|TPOINT,
+ SAREG|SNAME|SOREG, TULONG|TULONGLONG|TPOINT,
+ NSPECIAL, RDEST,
+ " xorq %rdx,%rdx\n divq AR\n", },
+
+{ DIV, INAREG,
+ SAREG, TSWORD,
+ SAREG|SNAME|SOREG, TWORD,
+ NSPECIAL, RDEST,
+ " cltd\n idivl AR\n", },
+
+{ DIV, INAREG,
+ SAREG, TUWORD,
+ SAREG|SNAME|SOREG, TUWORD,
+ NSPECIAL, RDEST,
+ " xorl %edx,%edx\n divl AR\n", },
+
+{ DIV, INAREG,
+ SAREG, TUSHORT,
+ SAREG|SNAME|SOREG, TUSHORT,
+ NSPECIAL, RDEST,
+ " xorl %edx,%edx\n divw AR\n", },
+
+{ DIV, INCH,
+ SHCH, TUCHAR,
+ SHCH|SNAME|SOREG, TUCHAR,
+ NSPECIAL, RDEST,
+ " xorb %ah,%ah\n divb AR\n", },
+
+{ DIV, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " fdivl AR\n", },
+
+{ DIV, INFL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fdivZAp\n", },
+
+{ MOD, INLL,
+ SCREG, TLONG|TLONGLONG,
+ SCREG|SNAME|SOREG, TLONG|TLONGLONG,
+ NCREG|NSPECIAL, RESC1,
+ " cltd\n idivq AR\n", },
+
+{ MOD, INLL,
+ SCREG, TLL|TPOINT,
+ SCREG|SNAME|SOREG, TULONG|TULONGLONG|TPOINT,
+ NCREG|NSPECIAL, RESC1,
+ " xorq %rdx,%rdx\n divq AR\n", },
+
+{ MOD, INAREG,
+ SAREG, TSWORD,
+ SAREG|SNAME|SOREG, TSWORD,
+ NAREG|NSPECIAL, RESC1,
+ " cltd\n idivl AR\n", },
+
+{ MOD, INAREG,
+ SAREG, TWORD,
+ SAREG|SNAME|SOREG, TUWORD,
+ NAREG|NSPECIAL, RESC1,
+ " xorl %edx,%edx\n divl AR\n", },
+
+{ MOD, INAREG,
+ SAREG, TUSHORT,
+ SAREG|SNAME|SOREG, TUSHORT,
+ NAREG|NSPECIAL, RESC1,
+ " xorl %edx,%edx\n divw AR\n", },
+
+{ MOD, INCH,
+ SHCH, TUCHAR,
+ SHCH|SNAME|SOREG, TUCHAR,
+ NBREG|NSPECIAL, RESC1,
+ " xorb %ah,%ah\n divb AR\n", },
+
+{ MUL, INLL,
+ SCREG, TLL|TPOINT,
+ SCREG|SNAME|SOREG|SCON, TLL|TPOINT,
+ 0, RLEFT,
+ " imulq AR,AL\n", },
+
+{ MUL, INAREG,
+ SAREG, TWORD,
+ SAREG|SNAME|SOREG|SCON, TWORD,
+ 0, RLEFT,
+ " imull AR,AL\n", },
+
+{ MUL, INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " imulw AR,AL\n", },
+
+{ MUL, INCH,
+ SHCH, TCHAR|TUCHAR,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ NSPECIAL, RDEST,
+ " imulb AR\n", },
+
+{ MUL, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " fmull AR\n", },
+
+{ MUL, INFL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fmulp\n", },
+
+/*
+ * Indirection operators.
+ */
+{ UMUL, INLL,
+ SANY, TANY,
+ SOREG, TLL|TPOINT,
+ NCREG, RESC1,
+ " movq AL,A1\n", },
+
+{ UMUL, INAREG,
+ SANY, TWORD,
+ SOREG, TWORD,
+ NAREG|NASL, RESC1,
+ " movl AL,A1\n", },
+
+{ UMUL, INCH,
+ SANY, TANY,
+ SOREG, TCHAR|TUCHAR,
+ NBREG|NBSL, RESC1,
+ " movb AL,A1\n", },
+
+{ UMUL, INAREG,
+ SANY, TANY,
+ SOREG, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " movw AL,A1\n", },
+
+{ UMUL, INFL,
+ SANY, TANY,
+ SOREG, TLDOUBLE,
+ NDREG|NDSL, RESC1,
+ " fldt AL\n", },
+
+{ UMUL, INFL,
+ SANY, TANY,
+ SOREG, TDOUBLE,
+ NDREG|NDSL, RESC1,
+ " fldl AL\n", },
+
+{ UMUL, INFL,
+ SANY, TANY,
+ SOREG, TFLOAT,
+ NDREG|NDSL, RESC1,
+ " flds AL\n", },
+
+/*
+ * Logical/branching operators
+ */
+
+/* Comparisions, take care of everything */
+{ OPLOG, FORCC,
+ SCON, TWORD,
+ SHLL|SOREG|SNAME, TLL|TPOINT,
+ 0, RESCC,
+ " cmpq AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SHLL, TLL|TPOINT,
+ SHLL|SOREG|SNAME, TLL|TPOINT,
+ 0, RESCC,
+ " cmpq AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SHLL|SOREG|SNAME, TLL|TPOINT,
+ SHLL, TLL|TPOINT,
+ 0, RESCC,
+ " cmpq AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SAREG|SOREG|SNAME, TWORD,
+ SCON|SAREG, TWORD,
+ 0, RESCC,
+ " cmpl AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SCON|SAREG, TWORD,
+ SAREG|SOREG|SNAME, TWORD,
+ 0, RESCC,
+ " cmpl AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SAREG|SOREG|SNAME, TSHORT|TUSHORT,
+ SCON|SAREG, TANY,
+ 0, RESCC,
+ " cmpw AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SBREG|SOREG|SNAME, TCHAR|TUCHAR,
+ SCON|SBREG, TANY,
+ 0, RESCC,
+ " cmpb AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NSPECIAL, 0,
+ "ZG", },
+
+{ OPLOG, FORCC,
+ SOREG|SNAME, TDOUBLE|TFLOAT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NSPECIAL, 0,
+ "ZG", },
+
+#if 0
+/* Ppro and later only */
+{ OPLOG, FORCC,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RESCC,
+ "ZA fucomip %st,%st(1)\n", },
+#endif
+
+{ OPLOG, FORCC,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "diediedie!", },
+
+/* AND/OR/ER/NOT */
+{ AND, INAREG|FOREFF,
+ SCREG|SOREG|SNAME, TLL,
+ SCON, TWORD,
+ 0, RLEFT,
+ " andq AR,AL\n", },
+
+{ AND, INAREG|FOREFF,
+ SCREG|SOREG|SNAME, TLL,
+ SCREG, TLL,
+ 0, RLEFT,
+ " andq AR,AL\n", },
+
+{ AND, INCREG|FOREFF,
+ SCREG, TLL,
+ SCREG|SOREG|SNAME, TLL,
+ 0, RLEFT,
+ " andq AR,AL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG|SOREG|SNAME, TWORD,
+ SCON|SAREG, TWORD,
+ 0, RLEFT,
+ " andl AR,AL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG, TWORD,
+ SAREG|SOREG|SNAME, TWORD,
+ 0, RLEFT,
+ " andl AR,AL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG|SOREG|SNAME, TSHORT|TUSHORT,
+ SCON|SAREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " andw AR,AL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG, TSHORT|TUSHORT,
+ SAREG|SOREG|SNAME, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " andw AR,AL\n", },
+
+{ AND, INBREG|FOREFF,
+ SBREG|SOREG|SNAME, TCHAR|TUCHAR,
+ SCON|SBREG, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " andb AR,AL\n", },
+
+{ AND, INBREG|FOREFF,
+ SBREG, TCHAR|TUCHAR,
+ SBREG|SOREG|SNAME, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " andb AR,AL\n", },
+/* AND/OR/ER/NOT */
+
+/*
+ * Jumps.
+ */
+{ GOTO, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " jmp LL\n", },
+
+#if defined(GCC_COMPAT) || defined(LANG_F77)
+{ GOTO, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " jmp *AL\n", },
+#endif
+
+/*
+ * Convert LTYPE to reg.
+ */
+{ OPLTYPE, FORCC|INLL,
+ SCREG, TLL|TPOINT,
+ SMIXOR, TANY,
+ NCREG, RESC1,
+ " xorq A1,A1\n", },
+
+{ OPLTYPE, INLL,
+ SANY, TANY,
+ SCREG|SCON|SOREG|SNAME, TLL|TPOINT,
+ NCREG, RESC1,
+ " movq AL,A1\n", },
+
+{ OPLTYPE, FORCC|INAREG,
+ SAREG, TWORD,
+ SMIXOR, TANY,
+ NAREG|NASL, RESC1,
+ " xorl A1,A1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SAREG|SCON|SOREG|SNAME, TWORD,
+ NAREG|NASL, RESC1,
+ " movl AL,A1\n", },
+
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SBREG|SOREG|SNAME|SCON, TCHAR|TUCHAR,
+ NBREG, RESC1,
+ " movb AL,A1\n", },
+
+{ OPLTYPE, FORCC|INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SMIXOR, TANY,
+ NAREG, RESC1,
+ " xorw A1,A1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SAREG|SOREG|SNAME|SCON, TSHORT|TUSHORT,
+ NAREG, RESC1,
+ " movw AL,A1\n", },
+
+{ OPLTYPE, INDREG,
+ SANY, TLDOUBLE,
+ SOREG|SNAME, TLDOUBLE,
+ NDREG, RESC1,
+ " fldt AL\n", },
+
+{ OPLTYPE, INDREG,
+ SANY, TDOUBLE,
+ SOREG|SNAME, TDOUBLE,
+ NDREG, RESC1,
+ " fldl AL\n", },
+
+{ OPLTYPE, INDREG,
+ SANY, TFLOAT,
+ SOREG|SNAME, TFLOAT,
+ NDREG, RESC1,
+ " flds AL\n", },
+
+/* Only used in ?: constructs. The stack already contains correct value */
+{ OPLTYPE, INDREG,
+ SANY, TFLOAT|TDOUBLE|TLDOUBLE,
+ SDREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ NDREG, RESC1,
+ "", },
+
+/*
+ * Negate a word.
+ */
+
+{ UMINUS, INCREG|FOREFF,
+ SCREG, TLL|TPOINT,
+ SCREG, TLL|TPOINT,
+ 0, RLEFT,
+ " negq AL\n", },
+
+{ UMINUS, INAREG|FOREFF,
+ SAREG, TWORD,
+ SAREG, TWORD,
+ 0, RLEFT,
+ " negl AL\n", },
+
+{ UMINUS, INAREG|FOREFF,
+ SAREG, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " negw AL\n", },
+
+{ UMINUS, INBREG|FOREFF,
+ SBREG, TCHAR|TUCHAR,
+ SBREG, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " negb AL\n", },
+
+{ UMINUS, INFL|FOREFF,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fchs\n", },
+
+{ COMPL, INCREG,
+ SCREG, TLL,
+ SANY, TANY,
+ 0, RLEFT,
+ " notq AL\n", },
+
+{ COMPL, INAREG,
+ SAREG, TWORD,
+ SANY, TANY,
+ 0, RLEFT,
+ " notl AL\n", },
+
+{ COMPL, INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SANY, TANY,
+ 0, RLEFT,
+ " notw AL\n", },
+
+{ COMPL, INBREG,
+ SBREG, TCHAR|TUCHAR,
+ SANY, TANY,
+ 0, RLEFT,
+ " notb AL\n", },
+
+# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,""
+
+{ UMUL, DF( UMUL ), },
+
+{ ASSIGN, DF(ASSIGN), },
+
+{ STASG, DF(STASG), },
+
+{ FLD, DF(FLD), },
+
+{ OPLEAF, DF(NAME), },
+
+/* { INIT, DF(INIT), }, */
+
+{ OPUNARY, DF(UMINUS), },
+
+{ OPANY, DF(BITYPE), },
+
+{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" },
+};
+
+int tablesize = sizeof(table)/sizeof(table[0]);
--- /dev/null
+++ usr.bin/pcc/amd64/local2.c
@@ -0,0 +1,1163 @@
+/* $Id: local2.c,v 1.1 2008/11/27 05:25:15 mickey Exp $ */
+/*
+ * Copyright (c) 2008 Michael Shalayeff
+ * Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+# include "pass2.h"
+# include <ctype.h>
+# include <string.h>
+
+static int stkpos;
+
+void
+deflab(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+static int regoff[7];
+static TWORD ftype;
+
+/*
+ * Print out the prolog assembler.
+ * addto and regoff are already calculated.
+ */
+static void
+prtprolog(struct interpass_prolog *ipp, int addto)
+{
+ static int lwnr;
+ int i;
+
+ printf(" pushl %%ebp\n");
+ printf(" movl %%esp,%%ebp\n");
+ if (addto)
+ printf(" subl $%d,%%esp\n", addto);
+ for (i = 0; i < MAXREGS; i++)
+ if (TESTBIT(ipp->ipp_regs, i))
+ fprintf(stdout, " movl %s,-%d(%s)\n",
+ rnames[i], regoff[i], rnames[FPREG]);
+ if (kflag == 0)
+ return;
+
+ /* if ebx are not saved to stack, it must be moved into another reg */
+ /* check and emit the move before GOT stuff */
+ if (!TESTBIT(ipp->ipp_regs, EBX)) {
+ struct interpass *ip = (struct interpass *)ipp;
+
+ ip = DLIST_PREV(ip, qelem);
+ ip = DLIST_PREV(ip, qelem);
+ ip = DLIST_PREV(ip, qelem);
+ if (ip->type != IP_NODE || ip->ip_node->n_op != ASSIGN ||
+ ip->ip_node->n_left->n_op != REG)
+ comperr("prtprolog pic error");
+ ip = (struct interpass *)ipp;
+ ip = DLIST_NEXT(ip, qelem);
+ if (ip->type != IP_NODE || ip->ip_node->n_op != ASSIGN ||
+ ip->ip_node->n_left->n_op != REG)
+ comperr("prtprolog pic error2");
+ printf(" movl %s,%s\n",
+ rnames[ip->ip_node->n_right->n_rval],
+ rnames[ip->ip_node->n_left->n_rval]);
+ tfree(ip->ip_node);
+ DLIST_REMOVE(ip, qelem);
+ }
+ printf(" call .LW%d\n", ++lwnr);
+ printf(".LW%d:\n", lwnr);
+ printf(" popl %%ebx\n");
+ printf(" addl $_GLOBAL_OFFSET_TABLE_+[.-.LW%d], %%ebx\n", lwnr);
+}
+
+/*
+ * calculate stack size and offsets
+ */
+static int
+offcalc(struct interpass_prolog *ipp)
+{
+ int i, addto;
+
+ addto = p2maxautooff;
+ if (addto >= AUTOINIT/SZCHAR)
+ addto -= AUTOINIT/SZCHAR;
+ for (i = 0; i < MAXREGS; i++)
+ if (TESTBIT(ipp->ipp_regs, i)) {
+ addto += SZINT/SZCHAR;
+ regoff[i] = addto;
+ }
+ return addto;
+}
+
+void
+prologue(struct interpass_prolog *ipp)
+{
+ int addto;
+
+ ftype = ipp->ipp_type;
+
+#ifdef LANG_F77
+ if (ipp->ipp_vis)
+ printf(" .globl %s\n", ipp->ipp_name);
+ printf(" .align 4\n");
+ printf("%s:\n", ipp->ipp_name);
+#endif
+ /*
+ * We here know what register to save and how much to
+ * add to the stack.
+ */
+ addto = offcalc(ipp);
+ prtprolog(ipp, addto);
+}
+
+void
+eoftn(struct interpass_prolog *ipp)
+{
+ int i;
+
+ if (ipp->ipp_ip.ip_lbl == 0)
+ return; /* no code needs to be generated */
+
+ /* return from function code */
+ for (i = 0; i < MAXREGS; i++)
+ if (TESTBIT(ipp->ipp_regs, i))
+ fprintf(stdout, " movl -%d(%s),%s\n",
+ regoff[i], rnames[FPREG], rnames[i]);
+
+ /* struct return needs special treatment */
+ if (ftype == STRTY || ftype == UNIONTY) {
+ printf(" movl 8(%%ebp),%%eax\n");
+ printf(" leave\n");
+ printf(" ret $%d\n", 4);
+ } else {
+ printf(" leave\n");
+ }
+ printf("\t.size %s,.-%s\n", ipp->ipp_name,
+ ipp->ipp_name);
+}
+
+/*
+ * add/sub/...
+ *
+ * Param given:
+ */
+void
+hopcode(int f, int o)
+{
+ char *str;
+
+ switch (o) {
+ case PLUS:
+ str = "add";
+ break;
+ case MINUS:
+ str = "sub";
+ break;
+ case AND:
+ str = "and";
+ break;
+ case OR:
+ str = "or";
+ break;
+ case ER:
+ str = "xor";
+ break;
+ default:
+ comperr("hopcode2: %d", o);
+ str = 0; /* XXX gcc */
+ }
+ printf("%s%c", str, f);
+}
+
+/*
+ * Return type size in bytes. Used by R2REGS, arg 2 to offset().
+ */
+int
+tlen(p) NODE *p;
+{
+ switch(p->n_type) {
+ case CHAR:
+ case UCHAR:
+ return(1);
+
+ case SHORT:
+ case USHORT:
+ return(SZSHORT/SZCHAR);
+
+ case DOUBLE:
+ return(SZDOUBLE/SZCHAR);
+
+ case INT:
+ case UNSIGNED:
+ return(SZINT/SZCHAR);
+
+ case LONG:
+ case ULONG:
+ case LONGLONG:
+ case ULONGLONG:
+ return SZLONGLONG/SZCHAR;
+
+ default:
+ if (!ISPTR(p->n_type))
+ comperr("tlen type %d not pointer");
+ return SZPOINT(p->n_type)/SZCHAR;
+ }
+}
+
+/*
+ * Emit code to compare two longlong numbers.
+ */
+static void
+twollcomp(NODE *p)
+{
+ int o = p->n_op;
+ int s = getlab();
+ int e = p->n_label;
+ int cb1, cb2;
+
+ if (o >= ULE)
+ o -= (ULE-LE);
+ switch (o) {
+ case NE:
+ cb1 = 0;
+ cb2 = NE;
+ break;
+ case EQ:
+ cb1 = NE;
+ cb2 = 0;
+ break;
+ case LE:
+ case LT:
+ cb1 = GT;
+ cb2 = LT;
+ break;
+ case GE:
+ case GT:
+ cb1 = LT;
+ cb2 = GT;
+ break;
+
+ default:
+ cb1 = cb2 = 0; /* XXX gcc */
+ }
+ if (p->n_op >= ULE)
+ cb1 += 4, cb2 += 4;
+ expand(p, 0, " cmpl UR,UL\n");
+ if (cb1) cbgen(cb1, s);
+ if (cb2) cbgen(cb2, e);
+ expand(p, 0, " cmpl AR,AL\n");
+ cbgen(p->n_op, e);
+ deflab(s);
+}
+
+int
+fldexpand(NODE *p, int cookie, char **cp)
+{
+ CONSZ val;
+
+ if (p->n_op == ASSIGN)
+ p = p->n_left;
+ switch (**cp) {
+ case 'S':
+ printf("%d", UPKFSZ(p->n_rval));
+ break;
+ case 'H':
+ printf("%d", UPKFOFF(p->n_rval));
+ break;
+ case 'M':
+ case 'N':
+ val = (CONSZ)1 << UPKFSZ(p->n_rval);
+ --val;
+ val <<= UPKFOFF(p->n_rval);
+ printf("0x%llx", (**cp == 'M' ? val : ~val) & 0xffffffff);
+ break;
+ default:
+ comperr("fldexpand");
+ }
+ return 1;
+}
+
+static void
+bfext(NODE *p)
+{
+ int ch = 0, sz = 0;
+
+ if (ISUNSIGNED(p->n_right->n_type))
+ return;
+ switch (p->n_right->n_type) {
+ case CHAR:
+ ch = 'b';
+ sz = 8;
+ break;
+ case SHORT:
+ ch = 'w';
+ sz = 16;
+ break;
+ case INT:
+ ch = 'l';
+ sz = 32;
+ break;
+ case LONG:
+ ch = 'q';
+ sz = 64;
+ break;
+ default:
+ comperr("bfext");
+ }
+
+ sz -= UPKFSZ(p->n_left->n_rval);
+ printf("\tshl%c $%d,", ch, sz);
+ adrput(stdout, getlr(p, 'D'));
+ printf("\n\tsar%c $%d,", ch, sz);
+ adrput(stdout, getlr(p, 'D'));
+ printf("\n");
+}
+
+/*
+ * Push a structure on stack as argument.
+ * the scratch registers are already free here
+ */
+static void
+starg(NODE *p)
+{
+ FILE *fp = stdout;
+
+ fprintf(fp, " subl $%d,%%esp\n", p->n_stsize);
+ fprintf(fp, " pushl $%d\n", p->n_stsize);
+ 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");
+ fprintf(fp, " addl $12,%%esp\n");
+}
+
+/*
+ * Compare two floating point numbers.
+ */
+static void
+fcomp(NODE *p)
+{
+
+ if (p->n_left->n_op == REG) {
+ if (p->n_su & DORIGHT)
+ expand(p, 0, " fxch\n");
+ expand(p, 0, " fucompp\n"); /* emit compare insn */
+ } else if (p->n_left->n_type == DOUBLE)
+ expand(p, 0, " fcompl AL\n"); /* emit compare insn */
+ else if (p->n_left->n_type == FLOAT)
+ expand(p, 0, " fcomp AL\n"); /* emit compare insn */
+ else
+ comperr("bad compare %p\n", p);
+ expand(p, 0, " fnstsw %ax\n"); /* move status reg to ax */
+
+ switch (p->n_op) {
+ case EQ:
+ expand(p, 0, " andb $64,%ah\n jne LC\n");
+ break;
+ case NE:
+ expand(p, 0, " andb $64,%ah\n je LC\n");
+ break;
+ case LE:
+ expand(p, 0, " andb $65,%ah\n cmpb $1,%ah\n jne LC\n");
+ break;
+ case LT:
+ expand(p, 0, " andb $65,%ah\n je LC\n");
+ break;
+ case GT:
+ expand(p, 0, " andb $1,%ah\n jne LC\n");
+ break;
+ case GE:
+ expand(p, 0, " andb $65,%ah\n jne LC\n");
+ break;
+ default:
+ comperr("fcomp op %d\n", p->n_op);
+ }
+}
+
+/*
+ * Convert an unsigned long long to floating point number.
+ */
+static void
+ulltofp(NODE *p)
+{
+ static int loadlab;
+ int jmplab;
+
+ if (loadlab == 0) {
+ loadlab = getlab();
+ expand(p, 0, " .data\n");
+ printf(LABFMT ": .long 0,0x80000000,0x403f\n", loadlab);
+ expand(p, 0, " .text\n");
+ }
+ jmplab = getlab();
+ expand(p, 0, " pushl UL\n pushl AL\n");
+ expand(p, 0, " fildq (%esp)\n");
+ expand(p, 0, " addl $8,%esp\n");
+ expand(p, 0, " cmpl $0,UL\n");
+ printf(" jge " LABFMT "\n", jmplab);
+ printf(" fldt " LABFMT "\n", loadlab);
+ printf(" faddp %%st,%%st(1)\n");
+ printf(LABFMT ":\n", jmplab);
+}
+
+static int
+argsiz(NODE *p)
+{
+ TWORD t = p->n_type;
+
+ if (t < LONG || t == FLOAT || t > BTMASK)
+ return 4;
+ if (t == LONG || t == ULONG || t == LONGLONG || t == ULONGLONG ||
+ t == DOUBLE)
+ return 8;
+ if (t == LDOUBLE)
+ return 16;
+ if (t == STRTY || t == UNIONTY)
+ return p->n_stsize;
+ comperr("argsiz");
+ return 0;
+}
+
+void
+zzzcode(NODE *p, int c)
+{
+ NODE *r, *l;
+ int pr, lr, s;
+ char *ch;
+
+ switch (c) {
+ case 'A': /* swap st0 and st1 if right is evaluated second */
+ if ((p->n_su & DORIGHT) == 0) {
+ if (logop(p->n_op))
+ printf(" fxch\n");
+ else
+ printf("r");
+ }
+ 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;
+ if (p->n_op == UCALL)
+ return; /* XXX remove ZC from UCALL */
+ if (pr)
+ printf(" addl $%d, %s\n", pr, rnames[ESP]);
+ break;
+
+ case 'E': /* Perform bitfield sign-extension */
+ bfext(p);
+ break;
+
+ case 'F': /* Structure argument */
+ if (p->n_stalign != 0) /* already on stack */
+ starg(p);
+ break;
+
+ case 'G': /* Floating point compare */
+ fcomp(p);
+ break;
+
+ case 'J': /* convert unsigned long long to floating point */
+ ulltofp(p);
+ break;
+
+ case 'M': /* Output sconv move, if needed */
+ l = getlr(p, 'L');
+ /* XXX fixneed: regnum */
+ pr = DECRA(p->n_reg, 0);
+ lr = DECRA(l->n_reg, 0);
+ if ((pr == AL && lr == EAX) || (pr == BL && lr == EBX) ||
+ (pr == CL && lr == ECX) || (pr == DL && lr == EDX))
+ ;
+ else
+ printf(" movb %%%cl,%s\n",
+ rnames[lr][2], rnames[pr]);
+ l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */
+ break;
+
+ case 'N': /* output extended reg name */
+ printf("%s", rnames[getlr(p, '1')->n_rval]);
+ break;
+
+ case 'S': /* emit eventual move after cast from longlong */
+ pr = DECRA(p->n_reg, 0);
+ lr = p->n_left->n_rval;
+ switch (p->n_type) {
+ case CHAR:
+ case UCHAR:
+ if (rnames[pr][2] == 'l' && rnames[lr][2] == 'x' &&
+ rnames[pr][1] == rnames[lr][1])
+ break;
+ if (rnames[lr][2] == 'x') {
+ printf("\tmovb %%%cl,%s\n",
+ rnames[lr][1], rnames[pr]);
+ break;
+ }
+ /* Must go via stack */
+ s = BITOOR(freetemp(1));
+ printf("\tmovl %%e%ci,%d(%%rbp)\n", rnames[lr][1], s);
+ printf("\tmovb %d(%%rbp),%s\n", s, rnames[pr]);
+ comperr("SCONV1 %s->%s", rnames[lr], rnames[pr]);
+ break;
+
+ case SHORT:
+ case USHORT:
+ if (rnames[lr][1] == rnames[pr][2] &&
+ rnames[lr][2] == rnames[pr][3])
+ break;
+ printf("\tmovw %%%c%c,%%%s\n",
+ rnames[lr][1], rnames[lr][2], rnames[pr]+2);
+ comperr("SCONV2 %s->%s", rnames[lr], rnames[pr]);
+ break;
+ case INT:
+ case UNSIGNED:
+ if (rnames[lr][1] == rnames[pr][2] &&
+ rnames[lr][2] == rnames[pr][3])
+ break;
+ printf("\tmovl %%e%c%c,%s\n",
+ rnames[lr][1], rnames[lr][2], rnames[pr]);
+ comperr("SCONV3 %s->%s", rnames[lr], rnames[pr]);
+ break;
+
+ default:
+ if (rnames[lr][1] == rnames[pr][2] &&
+ rnames[lr][2] == rnames[pr][3])
+ break;
+ comperr("SCONV4 %s->%s", rnames[lr], rnames[pr]);
+ break;
+ }
+ break;
+
+ default:
+ comperr("zzzcode %c", c);
+ }
+}
+
+/*ARGSUSED*/
+int
+rewfld(NODE *p)
+{
+ return(1);
+}
+
+int canaddr(NODE *);
+int
+canaddr(NODE *p)
+{
+ int o = p->n_op;
+
+ if (o==NAME || o==REG || o==ICON || o==OREG ||
+ (o==UMUL && shumul(p->n_left, SOREG)))
+ return(1);
+ return(0);
+}
+
+/*
+ * Does the bitfield shape match?
+ */
+int
+flshape(NODE *p)
+{
+ int o = p->n_op;
+
+ if (o == OREG || o == REG || o == NAME)
+ return SRDIR; /* Direct match */
+ if (o == UMUL && shumul(p->n_left, SOREG))
+ return SROREG; /* Convert into oreg */
+ return SRREG; /* put it into a register */
+}
+
+/* INTEMP shapes must not contain any temporary registers */
+/* XXX should this go away now? */
+int
+shtemp(NODE *p)
+{
+ return 0;
+#if 0
+ int r;
+
+ if (p->n_op == STARG )
+ p = p->n_left;
+
+ switch (p->n_op) {
+ case REG:
+ return (!istreg(p->n_rval));
+
+ case OREG:
+ r = p->n_rval;
+ if (R2TEST(r)) {
+ if (istreg(R2UPK1(r)))
+ return(0);
+ r = R2UPK2(r);
+ }
+ return (!istreg(r));
+
+ case UMUL:
+ p = p->n_left;
+ return (p->n_op != UMUL && shtemp(p));
+ }
+
+ if (optype(p->n_op) != LTYPE)
+ return(0);
+ return(1);
+#endif
+}
+
+void
+adrcon(CONSZ val)
+{
+ printf("$" CONFMT, val);
+}
+
+void
+conput(FILE *fp, NODE *p)
+{
+ int val = p->n_lval;
+
+ switch (p->n_op) {
+ case ICON:
+ if (p->n_name[0] != '\0') {
+ fprintf(fp, "%s", p->n_name);
+ if (val)
+ fprintf(fp, "+%d", val);
+ } else
+ fprintf(fp, "%d", val);
+ return;
+
+ default:
+ comperr("illegal conput, p %p", p);
+ }
+}
+
+/*ARGSUSED*/
+void
+insput(NODE *p)
+{
+ comperr("insput");
+}
+
+/*
+ * Write out the upper address, like the upper register of a 2-register
+ * reference, or the next memory location.
+ */
+void
+upput(NODE *p, int size)
+{
+
+ size /= SZCHAR;
+ switch (p->n_op) {
+ case REG:
+ fprintf(stdout, "%%%s", &rnames[p->n_rval][3]);
+ break;
+
+ case NAME:
+ case OREG:
+ p->n_lval += size;
+ adrput(stdout, p);
+ p->n_lval -= size;
+ break;
+ case ICON:
+ fprintf(stdout, "$" CONFMT, p->n_lval >> 32);
+ break;
+ default:
+ comperr("upput bad op %d size %d", p->n_op, size);
+ }
+}
+
+void
+adrput(FILE *io, NODE *p)
+{
+ int r;
+ /* output an address, with offsets, from p */
+
+ if (p->n_op == FLD)
+ p = p->n_left;
+
+ switch (p->n_op) {
+
+ case NAME:
+ if (p->n_name[0] != '\0') {
+ fputs(p->n_name, io);
+ if (p->n_lval != 0)
+ fprintf(io, "+" CONFMT, p->n_lval);
+ } else
+ fprintf(io, CONFMT, p->n_lval);
+ return;
+
+ case OREG:
+ r = p->n_rval;
+ if (p->n_name[0])
+ printf("%s%s", p->n_name, p->n_lval ? "+" : "");
+ if (p->n_lval)
+ fprintf(io, "%d", (int)p->n_lval);
+ if (R2TEST(r)) {
+ fprintf(io, "(%s,%s,8)", rnames[R2UPK1(r)],
+ rnames[R2UPK2(r)]);
+ } else
+ fprintf(io, "(%s)", rnames[p->n_rval]);
+ return;
+ case ICON:
+#ifdef PCC_DEBUG
+ /* Sanitycheck for PIC, to catch adressable constants */
+ if (kflag && p->n_name[0]) {
+ static int foo;
+
+ if (foo++ == 0) {
+ printf("\nfailing...\n");
+ fwalk(p, e2print, 0);
+ comperr("pass2 conput");
+ }
+ }
+#endif
+ /* addressable value of the constant */
+ fputc('$', io);
+ conput(io, p);
+ return;
+
+ case REG:
+ switch (p->n_type) {
+ case LONGLONG:
+ case ULONGLONG:
+ fprintf(io, "%%%c%c%c", rnames[p->n_rval][0],
+ rnames[p->n_rval][1], rnames[p->n_rval][2]);
+ break;
+ case SHORT:
+ case USHORT:
+ fprintf(io, "%%%s", &rnames[p->n_rval][2]);
+ break;
+ default:
+ fprintf(io, "%s", rnames[p->n_rval]);
+ }
+ return;
+
+ default:
+ comperr("illegal address, op %d, node %p", p->n_op, p);
+ return;
+
+ }
+}
+
+static char *
+ccbranches[] = {
+ "je", /* jumpe */
+ "jne", /* jumpn */
+ "jle", /* jumple */
+ "jl", /* jumpl */
+ "jge", /* jumpge */
+ "jg", /* jumpg */
+ "jbe", /* jumple (jlequ) */
+ "jb", /* jumpl (jlssu) */
+ "jae", /* jumpge (jgequ) */
+ "ja", /* jumpg (jgtru) */
+};
+
+
+/* printf conditional and unconditional branches */
+void
+cbgen(int o, int lab)
+{
+ if (o < EQ || o > UGT)
+ comperr("bad conditional branch: %s", opst[o]);
+ printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab);
+}
+
+static void
+fixcalls(NODE *p, void *arg)
+{
+ /* Prepare for struct return by allocating bounce space on stack */
+ switch (p->n_op) {
+ case STCALL:
+ case USTCALL:
+ if (p->n_stsize+p2autooff > stkpos)
+ stkpos = p->n_stsize+p2autooff;
+ break;
+ }
+}
+
+/*
+ * Must store floats in memory if there are two function calls involved.
+ */
+static int
+storefloat(struct interpass *ip, NODE *p)
+{
+ int l, r;
+
+ switch (optype(p->n_op)) {
+ case BITYPE:
+ l = storefloat(ip, p->n_left);
+ r = storefloat(ip, p->n_right);
+ if (p->n_op == CM)
+ return 0; /* arguments, don't care */
+ if (callop(p->n_op))
+ return 1; /* found one */
+#define ISF(p) ((p)->n_type == FLOAT || (p)->n_type == DOUBLE || \
+ (p)->n_type == LDOUBLE)
+ if (ISF(p->n_left) && ISF(p->n_right) && l && r) {
+ /* must store one. store left */
+ struct interpass *nip;
+ TWORD t = p->n_left->n_type;
+ NODE *ll;
+ int off;
+
+ off = BITOOR(freetemp(szty(t)));
+ ll = mklnode(OREG, off, FPREG, t);
+ nip = ipnode(mkbinode(ASSIGN, ll, p->n_left, t));
+ p->n_left = mklnode(OREG, off, FPREG, t);
+ DLIST_INSERT_BEFORE(ip, nip, qelem);
+ }
+ return l|r;
+
+ case UTYPE:
+ l = storefloat(ip, p->n_left);
+ if (callop(p->n_op))
+ l = 1;
+ return l;
+ default:
+ return 0;
+ }
+}
+
+void
+myreader(struct interpass *ipole)
+{
+ struct interpass *ip;
+
+ stkpos = p2autooff;
+ DLIST_FOREACH(ip, ipole, qelem) {
+ if (ip->type != IP_NODE)
+ continue;
+ walkf(ip->ip_node, fixcalls, 0);
+ storefloat(ip, ip->ip_node);
+ }
+ if (stkpos > p2autooff)
+ p2autooff = stkpos;
+ if (stkpos > p2maxautooff)
+ p2maxautooff = stkpos;
+ if (x2debug)
+ printip(ipole);
+}
+
+/*
+ * Remove some PCONVs after OREGs are created.
+ */
+static void
+pconv2(NODE *p, void *arg)
+{
+ NODE *q;
+
+ if (p->n_op == PLUS) {
+ if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
+ if (p->n_right->n_op != ICON)
+ return;
+ if (p->n_left->n_op != PCONV)
+ return;
+ if (p->n_left->n_left->n_op != OREG)
+ return;
+ q = p->n_left->n_left;
+ nfree(p->n_left);
+ p->n_left = q;
+ /*
+ * This will be converted to another OREG later.
+ */
+ }
+ }
+}
+
+void
+mycanon(NODE *p)
+{
+ walkf(p, pconv2, 0);
+}
+
+void
+myoptim(struct interpass *ip)
+{
+}
+
+void
+rmove(int s, int d, TWORD t)
+{
+ int sl, sh, dl, dh;
+
+ switch (t) {
+ case LONG:
+ case ULONG:
+ case LONGLONG:
+ case ULONGLONG:
+ printf(" movq %s,%s\n", rnames[s], rnames[d]);
+ break;
+ case CHAR:
+ case UCHAR:
+ printf(" movb %s,%s\n", rnames[s], rnames[d]);
+ break;
+ case FLOAT:
+ case DOUBLE:
+ case LDOUBLE:
+#ifdef notdef
+ /* a=b()*c(); will generate this */
+ comperr("bad float rmove: %d %d", s, d);
+#endif
+ break;
+ default:
+ printf(" movl %s,%s\n", rnames[s], rnames[d]);
+ }
+}
+
+/*
+ * For class c, find worst-case displacement of the number of
+ * registers in the array r[] indexed by class.
+ */
+int
+COLORMAP(int c, int *r)
+{
+ int num;
+
+ switch (c) {
+ case CLASSA:
+ num = r[CLASSB] > 4 ? 4 : r[CLASSB];
+ num += 2*r[CLASSC];
+ num += r[CLASSA];
+ return num < 6;
+ case CLASSB:
+ num = r[CLASSA];
+ num += 2*r[CLASSC];
+ num += r[CLASSB];
+ return num < 4;
+ case CLASSC:
+ num = r[CLASSA];
+ num += r[CLASSB] > 4 ? 4 : r[CLASSB];
+ num += 2*r[CLASSC];
+ return num < 5;
+ case CLASSD:
+ return r[CLASSD] < DREGCNT;
+ }
+ return 0; /* XXX gcc */
+}
+
+char *rnames[] = {
+ "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp",
+ "%al", "%ah", "%dl", "%dh", "%cl", "%ch", "%bl", "%bh",
+ "%rax", "%rdx", "%rcx", "%rbx", "%rsi", "%rdi", "%rbp", "%rsp",
+ "%r08", "%r09", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
+ "%st0", "%st1", "%st2", "%st3", "%st4", "%st5", "%st6", "%st7",
+};
+
+/*
+ * Return a class suitable for a specific type.
+ */
+int
+gclass(TWORD t)
+{
+ if (t == CHAR || t == UCHAR)
+ return CLASSB;
+ if (t == LONG || t == ULONG || t == LONGLONG || t == ULONGLONG)
+ return CLASSC;
+ if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
+ return CLASSD;
+ return CLASSA;
+}
+
+/*
+ * Calculate argument sizes.
+ */
+void
+lastcall(NODE *p)
+{
+ NODE *op = p;
+ int size = 0;
+
+ p->n_qual = 0;
+ if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
+ return;
+ for (p = p->n_right; p->n_op == CM; p = p->n_left)
+ size += argsiz(p->n_right);
+ size += argsiz(p);
+ if (kflag)
+ size -= 4;
+ op->n_qual = size; /* XXX */
+}
+
+/*
+ * Special shapes.
+ */
+int
+special(NODE *p, int shape)
+{
+ int o = p->n_op;
+
+ switch (shape) {
+ case SFUNCALL:
+ if (o == STCALL || o == USTCALL)
+ return SRREG;
+ break;
+ case SPCON:
+ if (o != ICON || p->n_name[0] ||
+ p->n_lval < 0 || p->n_lval > 0x7fffffff)
+ break;
+ return SRDIR;
+ case SMIXOR:
+ return tshape(p, SZERO);
+ case SMILWXOR:
+ if (o != ICON || p->n_name[0] ||
+ p->n_lval == 0 || p->n_lval & 0xffffffff)
+ break;
+ return SRDIR;
+ case SMIHWXOR:
+ if (o != ICON || p->n_name[0] ||
+ p->n_lval == 0 || (p->n_lval >> 32) != 0)
+ break;
+ return SRDIR;
+ }
+ return SRNOPE;
+}
+
+/*
+ * Target-dependent command-line options.
+ */
+void
+mflags(char *str)
+{
+}
+
+/*
+ * Do something target-dependent for xasm arguments.
+ */
+int
+myxasm(struct interpass *ip, NODE *p)
+{
+ struct interpass *ip2;
+ NODE *in = 0, *ut = 0;
+ TWORD t;
+ char *w;
+ int reg;
+ int cw;
+
+ cw = xasmcode(p->n_name);
+ if (cw & (XASMASG|XASMINOUT))
+ ut = p->n_left;
+ if ((cw & XASMASG) == 0)
+ in = p->n_left;
+
+ switch (XASMVAL(cw)) {
+ case 'D': reg = EDI; break;
+ case 'S': reg = ESI; break;
+ case 'a': reg = EAX; break;
+ case 'b': reg = EBX; break;
+ case 'c': reg = ECX; break;
+ case 'd': reg = EDX; break;
+ case 't': reg = 0; break;
+ case 'u': reg = 1; break;
+ case 'A': reg = EAXEDX; break;
+ case 'q': /* XXX let it be CLASSA as for now */
+ p->n_name = tmpstrdup(p->n_name);
+ w = strchr(p->n_name, 'q');
+ *w = 'r';
+ return 0;
+ default:
+ return 0;
+ }
+ p->n_name = tmpstrdup(p->n_name);
+ for (w = p->n_name; *w; w++)
+ ;
+ w[-1] = 'r'; /* now reg */
+ t = p->n_left->n_type;
+ if (reg == EAXEDX) {
+ p->n_label = CLASSC;
+ } else {
+ p->n_label = CLASSA;
+ if (t == CHAR || t == UCHAR) {
+ p->n_label = CLASSB;
+ reg = reg * 2 + 8;
+ }
+ }
+ if (t == FLOAT || t == DOUBLE || t == LDOUBLE) {
+ p->n_label = CLASSD;
+ reg += 037;
+ }
+
+ if (in && ut)
+ in = tcopy(in);
+ p->n_left = mklnode(REG, 0, reg, t);
+ if (ut) {
+ ip2 = ipnode(mkbinode(ASSIGN, ut, tcopy(p->n_left), t));
+ DLIST_INSERT_AFTER(ip, ip2, qelem);
+ }
+ if (in) {
+ ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), in, t));
+ DLIST_INSERT_BEFORE(ip, ip2, qelem);
+ }
+ return 1;
+}
+
+void
+targarg(char *w, void *arg)
+{
+ NODE **ary = arg;
+ NODE *p, *q;
+
+ p = ary[(int)w[1]-'0']->n_left;
+ if (optype(p->n_op) != LTYPE)
+ comperr("bad xarg op %d", p->n_op);
+ q = tcopy(p);
+ if (q->n_op == REG) {
+ if (*w == 'k') {
+ q->n_type = INT;
+ } else if (*w != 'w') {
+ if (q->n_type > UCHAR) {
+ regno(q) = regno(q)*2+8;
+ if (*w == 'h')
+ regno(q)++;
+ }
+ q->n_type = INT;
+ } else
+ q->n_type = SHORT;
+ }
+ adrput(stdout, q);
+ tfree(q);
+}
+
+/*
+ * target-specific conversion of numeric arguments.
+ */
+int
+numconv(void *ip, void *p1, void *q1)
+{
+ NODE *p = p1, *q = q1;
+ int cw = xasmcode(q->n_name);
+
+ switch (XASMVAL(cw)) {
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ p->n_name = tmpcalloc(2);
+ p->n_name[0] = XASMVAL(cw);
+ return 1;
+ default:
+ return 0;
+ }
+}
--- /dev/null
+++ usr.bin/pcc/amd64/code.c
@@ -0,0 +1,290 @@
+/* $Id: code.c,v 1.2 2008/12/10 17:59:30 mickey Exp $ */
+/*
+ * Copyright (c) 2008 Michael Shalayeff
+ * Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+# include "pass1.h"
+
+NODE *funarg(NODE *, int *);
+int argreg(TWORD, int *);
+
+int lastloc = -1;
+
+/*
+ * Define everything needed to print out some data (or text).
+ * This means segment, alignment, visibility, etc.
+ */
+void
+defloc(struct symtab *sp)
+{
+ extern char *nextsect;
+ static char *loctbl[] = { "text", "data", "section .rodata" };
+ TWORD t;
+ int s;
+
+ if (sp == NULL) {
+ lastloc = -1;
+ return;
+ }
+ t = sp->stype;
+ s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA;
+#ifdef TLS
+ if (sp->sflags & STLS) {
+ if (s != DATA)
+ cerror("non-data symbol in tls section");
+ nextsect = ".tdata";
+ }
+#endif
+ if (nextsect) {
+ printf(" .section %s\n", nextsect);
+ nextsect = NULL;
+ s = -1;
+ } else if (s != lastloc)
+ printf(" .%s\n", loctbl[s]);
+ lastloc = s;
+ while (ISARY(t))
+ t = DECREF(t);
+ if (sp->ssue->suealign > ALCHAR)
+ printf(" .align %d\n", sp->ssue->suealign/ALCHAR);
+ if (sp->sclass == EXTDEF)
+ printf(" .globl %s\n", exname(sp->soname));
+ if (ISFTN(t))
+ printf("\t.type %s, at function\n", exname(sp->soname));
+ if (sp->slevel == 0)
+ printf("%s:\n", exname(sp->soname));
+ else
+ printf(LABFMT ":\n", sp->soffset);
+}
+
+/*
+ * code for the end of a function
+ * deals with struct return here
+ */
+void
+efcode()
+{
+ extern int gotnr;
+ NODE *p, *q;
+
+ gotnr = 0; /* new number for next fun */
+ if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
+ return;
+ /* Create struct assignment */
+ q = block(OREG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue);
+ q->n_rval = EBP;
+ q->n_lval = 8; /* return buffer offset */
+ q = buildtree(UMUL, q, NIL);
+ p = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue);
+ p = buildtree(UMUL, p, NIL);
+ p = buildtree(ASSIGN, q, p);
+ ecomp(p);
+}
+
+/*
+ * code for the beginning of a function; a is an array of
+ * indices in symtab for the arguments; n is the number
+ */
+void
+bfcode(struct symtab **a, int cnt)
+{
+ struct symtab *sp2;
+ extern int gotnr;
+ NODE *n, *p;
+ int i;
+
+ if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
+ /* Function returns struct, adjust arg offset */
+ for (i = 0; i < cnt; i++)
+ sp[i]->soffset += SZPOINT(LONG);
+ }
+
+ if (kflag) {
+ /* Put ebx in temporary */
+ n = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ n->n_rval = EBX;
+ p = tempnode(0, INT, 0, MKSUE(INT));
+ gotnr = regno(p);
+ ecomp(buildtree(ASSIGN, p, n));
+ }
+
+ /* recalculate the arg offset and create TEMP moves */
+ for (n = 0, i = 0; i < cnt; i++) {
+ sp = a[i];
+
+ if (n < 6) {
+ p = tempnode(0, sp->stype, sp->sdf, sp->ssue);
+ q = block(REG, NIL, NIL, sp->stype, sp->sdf, sp->ssue);
+ q->n_rval = argreg(sp->stype, &n);
+ p = buildtree(ASSIGN, p, q);
+ sp->soffset = regno(p->n_left);
+ sp->sflags |= STNODE;
+ ecomp(p);
+ } else {
+ sp->soffset += SZLONG * n;
+ if (xtemps) {
+ /* put stack args in temps if optimizing */
+ p = tempnode(0, sp->stype, sp->sdf, sp->ssue);
+ p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0));
+ sp->soffset = regno(p->n_left);
+ sp->sflags |= STNODE;
+ ecomp(p);
+ }
+ }
+ }
+}
+
+
+/*
+ * by now, the automatics and register variables are allocated
+ */
+void
+bccode()
+{
+ SETOFF(autooff, SZINT);
+}
+
+/* called just before final exit */
+/* flag is 1 if errors, 0 if none */
+void
+ejobcode(int flag )
+{
+ if (errors)
+ return;
+
+#define _MKSTR(x) #x
+#define MKSTR(x) _MKSTR(x)
+#define OS MKSTR(TARGOS)
+ printf("\t.ident \"PCC: %s (%s)\"\n\t.end\n", PACKAGE_STRING, OS);
+}
+
+void
+bjobcode()
+{
+}
+
+static const int argregsi[] = { RDI, RSI, RDX, RCX, R09, R08 };
+
+int
+argreg(TWORD t, int *n)
+{
+ switch (t) {
+ case FLOAT:
+ case DOUBLE:
+ case LDOUBLE:
+ return FR6 - *n - 2;
+ case LONGLONG:
+ case ULONGLONG:
+ /* TODO */;
+ default:
+ return argregsi[(*n)++];
+ }
+}
+
+NODE *
+funarg(NODE *p, int *n)
+{
+ NODE *r;
+ int sz;
+
+ if (p->n_op == CM) {
+ p->n_left = funarg(p->n_left, n);
+ p->n_right = funarg(p->n_right, n);
+ return p;
+ }
+
+ if (*n >= 6) {
+ *n++;
+ r = block(OREG, NIL, NIL, p->n_type|PTR, 0,
+ MKSUE(p->n_type|PTR));
+ r->n_rval = RBP;
+ r->n_lval = 16 + (*n - 6) * 8;
+ } else {
+ r = block(REG, NIL, NIL, p->n_type, 0, 0);
+ r->n_lval = 0;
+ r->n_rval = argreg(p->n_type, n);
+ }
+ p = block(ASSIGN, r, p, p->n_type, 0, 0);
+ clocal(p);
+
+ return p;
+}
+
+/*
+ * Called with a function call with arguments as argument.
+ * This is done early in buildtree() and only done once.
+ * Returns p.
+ */
+NODE *
+funcode(NODE *p)
+{
+ extern int gotnr;
+ NODE *r, *l;
+ int n = 0;
+
+ p->n_right = funarg(p->n_right, &n);
+
+ if (kflag == 0)
+ return p;
+ /* Create an ASSIGN node for ebx */
+ l = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ l->n_rval = EBX;
+ l = buildtree(ASSIGN, l, tempnode(gotnr, INT, 0, MKSUE(INT)));
+ if (p->n_right->n_op != CM) {
+ p->n_right = block(CM, l, p->n_right, INT, 0, MKSUE(INT));
+ } else {
+ for (r = p->n_right; r->n_left->n_op == CM; r = r->n_left)
+ ;
+ r->n_left = block(CM, l, r->n_left, INT, 0, MKSUE(INT));
+ }
+ return p;
+}
+
+/*
+ * return the alignment of field of type t
+ */
+int
+fldal(unsigned int t)
+{
+ uerror("illegal field type");
+ return(ALINT);
+}
+
+/* fix up type of field p */
+void
+fldty(struct symtab *p)
+{
+}
+
+/*
+ * XXX - fix genswitch.
+ */
+int
+mygenswitch(int num, TWORD type, struct swents **p, int n)
+{
+ return 0;
+}
--- /dev/null
+++ usr.bin/pcc/amd64/local.c
@@ -0,0 +1,1117 @@
+/* $Id: local.c,v 1.2 2008/12/14 21:16:58 ragge Exp $ */
+/*
+ * Copyright (c) 2008 Michael Shalayeff
+ * Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "pass1.h"
+
+/* this file contains code which is dependent on the target machine */
+
+/*
+ * Check if a constant is too large for a type.
+ */
+static int
+toolarge(TWORD t, CONSZ con)
+{
+ U_CONSZ ucon = con;
+
+ switch (t) {
+ case ULONG:
+ case LONG:
+ case ULONGLONG:
+ case LONGLONG:
+ break; /* cannot be too large */
+#define SCHK(i) case i: if (con > MAX_##i || con < MIN_##i) return 1; break
+#define UCHK(i) case i: if (ucon > MAX_##i) return 1; break
+ SCHK(INT);
+ SCHK(SHORT);
+ case BOOL:
+ SCHK(CHAR);
+ UCHK(UNSIGNED);
+ UCHK(USHORT);
+ UCHK(UCHAR);
+ default:
+ cerror("toolarge");
+ }
+ return 0;
+}
+
+#define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz))
+
+/*
+ * Make a symtab entry for PIC use.
+ */
+static struct symtab *
+picsymtab(char *p, char *s, char *s2)
+{
+ struct symtab *sp = IALLOC(sizeof(struct symtab));
+ size_t len = strlen(p) + strlen(s) + strlen(s2) + 1;
+
+ sp->sname = sp->soname = IALLOC(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;
+}
+
+int gotnr; /* tempnum for GOT register */
+int argstacksize;
+
+/*
+ * Create a reference for an extern variable.
+ */
+static NODE *
+picext(NODE *p)
+{
+ NODE *q, *r;
+ struct symtab *sp;
+
+ q = tempnode(gotnr, PTR|VOID, 0, MKSUE(VOID));
+ 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 = 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;
+}
+
+/*
+ * Create a reference for a static variable.
+ */
+static NODE *
+picstatic(NODE *p)
+{
+ NODE *q, *r;
+ struct symtab *sp;
+
+ q = tempnode(gotnr, PTR|VOID, 0, MKSUE(VOID));
+ if (p->n_sp->slevel > 0) {
+ char buf[32];
+ snprintf(buf, 32, LABFMT, (int)p->n_sp->soffset);
+ sp = picsymtab("", buf, "@GOTOFF");
+ } else
+ sp = picsymtab("", p->n_sp->soname, "@GOTOFF");
+ sp->sclass = STATIC;
+ sp->stype = p->n_sp->stype;
+ 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; /* for init */
+ nfree(p);
+ return q;
+}
+
+#ifdef TLS
+/*
+ * Create a reference for a TLS variable.
+ */
+static NODE *
+tlspic(NODE *p)
+{
+ NODE *q, *r;
+ struct symtab *sp, *sp2;
+
+ /*
+ * creates:
+ * leal var at TLSGD(%ebx),%eax
+ * call ___tls_get_addr at PLT
+ */
+
+ /* calc address of var at TLSGD */
+ q = tempnode(gotnr, PTR|VOID, 0, MKSUE(VOID));
+ sp = picsymtab("", p->n_sp->soname, "@TLSGD");
+ r = xbcon(0, sp, INT);
+ q = buildtree(PLUS, q, r);
+
+ /* assign to %eax */
+ r = block(REG, NIL, NIL, PTR|VOID, 0, MKSUE(VOID));
+ r->n_rval = EAX;
+ q = buildtree(ASSIGN, r, q);
+
+ /* call ___tls_get_addr */
+ sp2 = lookup("___tls_get_addr at PLT", 0);
+ sp2->stype = EXTERN|INT|FTN;
+ r = nametree(sp2);
+ r = buildtree(ADDROF, r, NIL);
+ r = block(UCALL, r, NIL, INT, 0, MKSUE(INT));
+
+ /* fusion both parts together */
+ q = buildtree(COMOP, q, r);
+ q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue);
+ q->n_sp = p->n_sp; /* for init */
+
+ nfree(p);
+ return q;
+}
+
+static NODE *
+tlsnonpic(NODE *p)
+{
+ NODE *q, *r;
+ struct symtab *sp, *sp2;
+ int ext = p->n_sp->sclass;
+
+ 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));
+
+ 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);
+ q->n_sp = p->n_sp; /* for init */
+
+ nfree(p);
+ return q;
+}
+
+static NODE *
+tlsref(NODE *p)
+{
+ if (kflag)
+ return (tlspic(p));
+ else
+ return (tlsnonpic(p));
+}
+#endif
+
+/* clocal() is called to do local transformations on
+ * an expression tree preparitory to its being
+ * written out in intermediate code.
+ *
+ * the major essential job is rewriting the
+ * automatic variables and arguments in terms of
+ * REG and OREG nodes
+ * conversion ops which are not necessary are also clobbered here
+ * in addition, any special features (such as rewriting
+ * exclusive or) are easily handled here as well
+ */
+NODE *
+clocal(NODE *p)
+{
+
+ register struct symtab *q;
+ register NODE *r, *l;
+ register int o;
+ register int m;
+ TWORD t;
+
+#ifdef PCC_DEBUG
+ if (xdebug) {
+ printf("clocal: %p\n", p);
+ fwalk(p, eprint, 0);
+ }
+#endif
+ switch( o = p->n_op ){
+
+ case NAME:
+ if ((q = p->n_sp) == NULL)
+ return p; /* Nothing to care about */
+
+ switch (q->sclass) {
+
+ case PARAM:
+ case AUTO:
+ /* fake up a structure reference */
+ r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
+ r->n_lval = 0;
+ r->n_rval = FPREG;
+ p = stref(block(STREF, r, p, 0, 0, 0));
+ break;
+
+ case USTATIC:
+ if (kflag == 0)
+ break;
+ /* FALLTHROUGH */
+ case STATIC:
+#ifdef TLS
+ if (q->sflags & STLS) {
+ p = tlsref(p);
+ break;
+ }
+#endif
+ if (kflag == 0) {
+ if (q->slevel == 0)
+ break;
+ p->n_lval = 0;
+ } else if (blevel > 0)
+ p = picstatic(p);
+ break;
+
+ case REGISTER:
+ p->n_op = REG;
+ p->n_lval = 0;
+ p->n_rval = q->soffset;
+ break;
+
+ case EXTERN:
+ case EXTDEF:
+#ifdef TLS
+ if (q->sflags & STLS) {
+ p = tlsref(p);
+ break;
+ }
+#endif
+ if (kflag == 0)
+ break;
+ if (blevel > 0)
+ p = picext(p);
+ break;
+ }
+ break;
+
+ case ADDROF:
+ if (kflag == 0 || blevel == 0)
+ break;
+ /* char arrays may end up here */
+ l = p->n_left;
+ if (l->n_op != NAME ||
+ (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE))
+ break;
+ l = p;
+ p = picstatic(p->n_left);
+ nfree(l);
+ if (p->n_op != UMUL)
+ cerror("ADDROF error");
+ l = p;
+ p = p->n_left;
+ nfree(l);
+ break;
+
+ case UCALL:
+ case USTCALL:
+ if (kflag == 0)
+ break;
+ /* 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);
+ break;
+
+ case CBRANCH:
+ l = p->n_left;
+
+ /*
+ * Remove unnecessary conversion ops.
+ */
+ if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
+ if (coptype(l->n_op) != BITYPE)
+ break;
+ if (l->n_right->n_op == ICON) {
+ r = l->n_left->n_left;
+ if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
+ break;
+ if (ISPTR(r->n_type))
+ break; /* no opt for pointers */
+ if (toolarge(r->n_type, l->n_right->n_lval))
+ break;
+ /* Type must be correct */
+ t = r->n_type;
+ nfree(l->n_left);
+ l->n_left = r;
+ l->n_type = t;
+ l->n_right->n_type = t;
+ }
+ }
+ break;
+
+ case PCONV:
+ /* Remove redundant PCONV's. Be careful */
+ l = p->n_left;
+ if (l->n_op == ICON) {
+ l->n_lval = (unsigned)l->n_lval;
+ goto delp;
+ }
+ if (l->n_type < INT || l->n_type == LONGLONG ||
+ l->n_type == ULONGLONG) {
+ /* float etc? */
+ p->n_left = block(SCONV, l, NIL,
+ UNSIGNED, 0, MKSUE(UNSIGNED));
+ break;
+ }
+ /* if left is SCONV, cannot remove */
+ if (l->n_op == SCONV)
+ break;
+
+ /* avoid ADDROF TEMP */
+ if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
+ break;
+
+ /* if conversion to another pointer type, just remove */
+ if (p->n_type > BTMASK && l->n_type > BTMASK)
+ goto delp;
+ break;
+
+ delp: l->n_type = p->n_type;
+ l->n_qual = p->n_qual;
+ l->n_df = p->n_df;
+ l->n_sue = p->n_sue;
+ nfree(p);
+ p = l;
+ break;
+
+ case SCONV:
+ l = p->n_left;
+
+ if (p->n_type == l->n_type) {
+ nfree(p);
+ return l;
+ }
+
+ if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
+ btdims[p->n_type].suesize == btdims[l->n_type].suesize) {
+ if (p->n_type != FLOAT && p->n_type != DOUBLE &&
+ l->n_type != FLOAT && l->n_type != DOUBLE &&
+ l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
+ if (l->n_op == NAME || l->n_op == UMUL ||
+ l->n_op == TEMP) {
+ l->n_type = p->n_type;
+ nfree(p);
+ return l;
+ }
+ }
+ }
+
+ if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
+ coptype(l->n_op) == BITYPE) {
+ l->n_type = p->n_type;
+ nfree(p);
+ return l;
+ }
+
+ o = l->n_op;
+ m = p->n_type;
+
+ if (o == ICON) {
+ CONSZ val = l->n_lval;
+
+ if (!ISPTR(m)) /* Pointers don't need to be conv'd */
+ switch (m) {
+ case BOOL:
+ l->n_lval = l->n_lval != 0;
+ break;
+ case CHAR:
+ l->n_lval = (char)val;
+ break;
+ case UCHAR:
+ l->n_lval = val & 0377;
+ break;
+ case SHORT:
+ l->n_lval = (short)val;
+ break;
+ case USHORT:
+ l->n_lval = val & 0177777;
+ break;
+ case UNSIGNED:
+ l->n_lval = val & 0xffffffff;
+ break;
+ case INT:
+ l->n_lval = (int)val;
+ break;
+ case LONG:
+ case LONGLONG:
+ l->n_lval = (long long)val;
+ break;
+ case ULONG:
+ case ULONGLONG:
+ l->n_lval = val;
+ break;
+ case VOID:
+ break;
+ case LDOUBLE:
+ case DOUBLE:
+ case FLOAT:
+ l->n_op = FCON;
+ l->n_dcon = val;
+ break;
+ default:
+ cerror("unknown type %d", m);
+ }
+ l->n_type = m;
+ l->n_sue = MKSUE(m);
+ nfree(p);
+ return l;
+ } else if (l->n_op == FCON) {
+ l->n_lval = l->n_dcon;
+ l->n_sp = NULL;
+ l->n_op = ICON;
+ l->n_type = m;
+ l->n_sue = MKSUE(m);
+ nfree(p);
+ return clocal(l);
+ }
+ if (DEUNSIGN(p->n_type) == SHORT &&
+ DEUNSIGN(l->n_type) == SHORT) {
+ nfree(p);
+ p = l;
+ }
+ if ((p->n_type == CHAR || p->n_type == UCHAR ||
+ p->n_type == SHORT || p->n_type == USHORT) &&
+ (l->n_type == FLOAT || l->n_type == DOUBLE ||
+ l->n_type == LDOUBLE)) {
+ p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue);
+ p->n_left->n_type = INT;
+ return p;
+ }
+ break;
+
+ case MOD:
+ case DIV:
+ if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
+ break;
+ if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
+ break;
+ /* make it an int division by inserting conversions */
+ p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKSUE(INT));
+ p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKSUE(INT));
+ p = block(SCONV, p, NIL, p->n_type, 0, MKSUE(p->n_type));
+ p->n_left->n_type = INT;
+ break;
+
+ case PMCONV:
+ case PVCONV:
+ r = p;
+ p = buildtree(o == PMCONV ? MUL : DIV, p->n_left, p->n_right);
+ nfree(r);
+ break;
+
+ case FORCE:
+ /* put return value in return reg */
+ p->n_op = ASSIGN;
+ p->n_right = p->n_left;
+ p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
+ p->n_left->n_rval = p->n_left->n_type == BOOL ?
+ RETREG(CHAR) : RETREG(p->n_type);
+ break;
+
+ case LS:
+ case RS:
+ /* shift count must be in a char
+ * unless longlong, where it must be int */
+ 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,
+ INT, 0, MKSUE(INT));
+ break;
+ }
+ if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR)
+ break;
+ p->n_right = block(SCONV, p->n_right, NIL,
+ CHAR, 0, MKSUE(CHAR));
+ break;
+ }
+#ifdef PCC_DEBUG
+ if (xdebug) {
+ printf("clocal end: %p\n", p);
+ fwalk(p, eprint, 0);
+ }
+#endif
+ return(p);
+}
+
+/*
+ * Change CALL references to either direct (static) or PLT.
+ */
+static void
+fixnames(NODE *p, void *arg)
+{
+ struct symtab *sp;
+ struct suedef *sue;
+ NODE *q;
+ char *c;
+ int isu;
+
+ if ((cdope(p->n_op) & CALLFLG) == 0)
+ return;
+ isu = 0;
+ q = p->n_left;
+ sue = q->n_sue;
+ if (q->n_op == UMUL)
+ q = q->n_left, isu = 1;
+
+ if (q->n_op == PLUS && q->n_left->n_op == TEMP &&
+ q->n_right->n_op == ICON) {
+ sp = q->n_right->n_sp;
+
+ if (sp == NULL)
+ return; /* nothing to do */
+ if (sp->sclass == STATIC && !ISFTN(sp->stype))
+ return; /* function pointer */
+
+ if (sp->sclass != STATIC && sp->sclass != EXTERN &&
+ sp->sclass != EXTDEF)
+ cerror("fixnames");
+
+ if ((c = strstr(sp->soname, "@GOT")) == NULL)
+ cerror("fixnames2");
+ if (isu) {
+ memcpy(c, "@PLT", sizeof("@PLT"));
+ } else
+ *c = 0;
+
+ nfree(q->n_left);
+ q = q->n_right;
+ if (isu)
+ nfree(p->n_left->n_left);
+ nfree(p->n_left);
+ p->n_left = q;
+ q->n_sue = sue;
+ }
+}
+
+void
+myp2tree(NODE *p)
+{
+ struct symtab *sp;
+
+ if (kflag)
+ walkf(p, fixnames, 0); /* XXX walkf not needed */
+ if (p->n_op != FCON)
+ return;
+
+#if 0
+ /* put floating constants in memory */
+ setloc1(RDATA);
+ defalign(ALLDOUBLE);
+ deflab1(i = getlab());
+ ninval(0, btdims[p->n_type].suesize, p);
+#endif
+
+ 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->stype = p->n_type;
+ sp->squal = (CON >> TSHIFT);
+
+ defloc(sp);
+ ninval(0, sp->ssue->suesize, p);
+
+ p->n_op = NAME;
+ p->n_lval = 0;
+ p->n_sp = sp;
+}
+
+/*ARGSUSED*/
+int
+andable(NODE *p)
+{
+ return(1); /* all names can have & taken on them */
+}
+
+/*
+ * at the end of the arguments of a ftn, set the automatic offset
+ */
+void
+cendarg()
+{
+ autooff = AUTOINIT;
+}
+
+/*
+ * Return 1 if a variable of type type is OK to put in register.
+ */
+int
+cisreg(TWORD t)
+{
+ if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
+ return 0; /* not yet */
+ return 1;
+}
+
+/*
+ * return a node, for structure references, which is suitable for
+ * being added to a pointer of type t, in order to be off bits offset
+ * into a structure
+ * t, d, and s are the type, dimension offset, and sizeoffset
+ * For pdp10, return the type-specific index number which calculation
+ * is based on its size. For example, short a[3] would return 3.
+ * Be careful about only handling first-level pointers, the following
+ * indirections must be fullword.
+ */
+NODE *
+offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
+{
+ register NODE *p;
+
+ if (xdebug)
+ printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
+ off, t, d, sue->suesize);
+
+ p = bcon(0);
+ p->n_lval = off/SZCHAR; /* Default */
+ return(p);
+}
+
+/*
+ * Allocate off bits on the stack. p is a tree that when evaluated
+ * is the multiply count for off, t is a storeable node where to write
+ * the allocated address.
+ */
+void
+spalloc(NODE *t, NODE *p, OFFSZ off)
+{
+ NODE *sp;
+
+ p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */
+
+ /* sub the size from sp */
+ sp = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
+ sp->n_lval = 0;
+ sp->n_rval = STKREG;
+ ecomp(buildtree(MINUSEQ, sp, p));
+
+ /* save the address of sp */
+ sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue);
+ sp->n_lval = 0;
+ sp->n_rval = STKREG;
+ t->n_type = sp->n_type;
+ ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
+
+}
+
+/*
+ * Print out a string of characters.
+ * Assume that the assembler understands C-style escape
+ * sequences.
+ */
+void
+instring(struct symtab *sp)
+{
+ char *s, *str = sp->sname;
+
+ defloc(sp);
+
+ /* be kind to assemblers and avoid long strings */
+ printf("\t.ascii \"");
+ for (s = str; *s != 0; ) {
+ if (*s++ == '\\') {
+ (void)esccon(&s);
+ }
+ if (s - str > 60) {
+ fwrite(str, 1, s - str, stdout);
+ printf("\"\n\t.ascii \"");
+ str = s;
+ }
+ }
+ fwrite(str, 1, s - str, stdout);
+ printf("\\0\"\n");
+}
+
+/*
+ * Print out a wide string by calling ninval().
+ */
+void
+inwstring(struct symtab *sp)
+{
+ char *s = sp->sname;
+ NODE *p;
+
+ defloc(sp);
+ p = xbcon(0, NULL, WCHAR_TYPE);
+ do {
+ if (*s++ == '\\')
+ p->n_lval = esccon(&s);
+ else
+ p->n_lval = (unsigned char)s[-1];
+ ninval(0, (MKSUE(WCHAR_TYPE))->suesize, p);
+ } while (s[-1] != 0);
+ nfree(p);
+}
+
+
+static int inbits, inval;
+
+/*
+ * set fsz bits in sequence to zero.
+ */
+void
+zbits(OFFSZ off, int fsz)
+{
+ int m;
+
+ if (idebug)
+ printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits);
+ if ((m = (inbits % SZCHAR))) {
+ m = SZCHAR - m;
+ if (fsz < m) {
+ inbits += fsz;
+ return;
+ } else {
+ fsz -= m;
+ printf("\t.byte %d\n", inval);
+ inval = inbits = 0;
+ }
+ }
+ if (fsz >= SZCHAR) {
+ printf("\t.zero %d\n", fsz/SZCHAR);
+ fsz -= (fsz/SZCHAR) * SZCHAR;
+ }
+ if (fsz) {
+ inval = 0;
+ inbits = fsz;
+ }
+}
+
+/*
+ * Initialize a bitfield.
+ */
+void
+infld(CONSZ off, int fsz, CONSZ val)
+{
+ if (idebug)
+ printf("infld off %lld, fsz %d, val %lld inbits %d\n",
+ off, fsz, val, inbits);
+ val &= ((CONSZ)1 << fsz)-1;
+ while (fsz + inbits >= SZCHAR) {
+ inval |= (val << inbits);
+ printf("\t.byte %d\n", inval & 255);
+ fsz -= (SZCHAR - inbits);
+ val >>= (SZCHAR - inbits);
+ inval = inbits = 0;
+ }
+ if (fsz) {
+ inval |= (val << inbits);
+ inbits += fsz;
+ }
+}
+
+/*
+ * print out a constant node, may be associated with a label.
+ * Do not free the node after use.
+ * off is bit offset from the beginning of the aggregate
+ * fsz is the number of bits this is referring to
+ */
+void
+ninval(CONSZ off, int fsz, NODE *p)
+{
+ union { float f; double d; long double l; int i[3]; } u;
+ struct symtab *q;
+ char *c;
+ TWORD t;
+ int i;
+
+ t = p->n_type;
+ if (t > BTMASK)
+ t = INT; /* pointer */
+
+ while (p->n_op == SCONV || p->n_op == PCONV) {
+ NODE *l = p->n_left;
+ l->n_type = p->n_type;
+ p = l;
+ }
+
+ if (kflag && (p->n_op == PLUS || p->n_op == UMUL)) {
+ if (p->n_op == UMUL)
+ p = p->n_left;
+ p = p->n_right;
+ q = p->n_sp;
+
+ if ((c = strstr(q->soname, "@GOT")) != NULL)
+ *c = 0; /* ignore GOT ref here */
+ }
+ if (p->n_op != ICON && p->n_op != FCON)
+ cerror("ninval: init node not constant");
+
+ if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
+ uerror("element not constant");
+
+ switch (t) {
+ case LONGLONG:
+ case ULONGLONG:
+ i = (p->n_lval >> 32);
+ p->n_lval &= 0xffffffff;
+ p->n_type = INT;
+ ninval(off, 32, p);
+ p->n_lval = i;
+ ninval(off+32, 32, p);
+ break;
+ case INT:
+ case UNSIGNED:
+ printf("\t.long 0x%x", (int)p->n_lval);
+ if ((q = p->n_sp) != NULL) {
+ if ((q->sclass == STATIC && q->slevel > 0)) {
+ printf("+" LABFMT, q->soffset);
+ } else {
+ printf("+%s", exname(q->soname));
+ }
+ }
+ printf("\n");
+ break;
+ case SHORT:
+ case USHORT:
+ printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff);
+ break;
+ case BOOL:
+ if (p->n_lval > 1)
+ p->n_lval = p->n_lval != 0;
+ /* FALLTHROUGH */
+ case CHAR:
+ case UCHAR:
+ printf("\t.byte %d\n", (int)p->n_lval & 0xff);
+ 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;
+ printf("\t.long\t0x%x\n", u.i[0]);
+ break;
+ default:
+ cerror("ninval");
+ }
+}
+
+/* make a name look like an external name in the local machine */
+char *
+exname(char *p)
+{
+ return (p == NULL ? "" : p);
+}
+
+/*
+ * map types which are not defined on the local machine
+ */
+TWORD
+ctype(TWORD type)
+{
+ switch (BTYPE(type)) {
+ case LONG:
+ MODTYPE(type,LONG);
+ break;
+
+ case ULONG:
+ MODTYPE(type,ULONG);
+
+ }
+ return (type);
+}
+
+void
+calldec(NODE *p, NODE *q)
+{
+}
+
+void
+extdec(struct symtab *q)
+{
+}
+
+/* make a common declaration for id, if reasonable */
+void
+defzero(struct symtab *sp)
+{
+ int off;
+
+#ifdef TLS
+ if (sp->sflags & STLS) {
+ if (sp->sclass == EXTERN)
+ sp->sclass = EXTDEF;
+ simpleinit(sp, bcon(0));
+ return;
+ }
+#endif
+
+ off = tsize(sp->stype, sp->sdf, sp->ssue);
+ off = (off+(SZCHAR-1))/SZCHAR;
+ printf(" .%scomm ", sp->sclass == STATIC ? "l" : "");
+ if (sp->slevel == 0)
+ printf("%s,0%o\n", exname(sp->soname), off);
+ else
+ printf(LABFMT ",0%o\n", sp->soffset, off);
+}
+
+static char *
+section2string(char *name, int len)
+{
+ char *s;
+ int n;
+
+ if (strncmp(name, "link_set", 8) == 0) {
+ const char *postfix = ",\"aw\", at progbits";
+ n = len + strlen(postfix) + 1;
+ s = IALLOC(n);
+ strlcpy(s, name, n);
+ strlcat(s, postfix, n);
+ return s;
+ }
+
+ return newstring(name, len);
+}
+
+char *nextsect;
+#ifdef TLS
+static int gottls;
+#endif
+static char *alias;
+static int constructor;
+static int destructor;
+
+/*
+ * Give target the opportunity of handling pragmas.
+ */
+int
+mypragma(char **ary)
+{
+#ifdef TLS
+ if (strcmp(ary[1], "tls") == 0 && ary[2] == NULL) {
+ gottls = 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;
+}
+
+/*
+ * Called when a identifier has been declared.
+ */
+void
+fixdef(struct symtab *sp)
+{
+#ifdef TLS
+ /* may have sanity checks here */
+ 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)) {
+ printf("\t.section .%ctors,\"aw\", at progbits\n",
+ constructor ? 'c' : 'd');
+ printf("\t.p2align 2\n");
+ printf("\t.long %s\n", exname(sp->sname));
+ constructor = destructor = 0;
+ }
+}
+
+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);
+}
+
+void
+pass1_lastchance(struct interpass *ip)
+{
+}
Index: cc.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/cc/cc.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L usr.bin/pcc/cc/cc.c -L usr.bin/pcc/cc/cc.c -u -r1.2 -r1.3
--- usr.bin/pcc/cc/cc.c
+++ usr.bin/pcc/cc/cc.c
@@ -1,4 +1,4 @@
-/* $Id: cc.c,v 1.61 2007/09/26 14:48:47 ragge Exp $ */
+/* $Id: cc.c,v 1.136 2008/12/22 02:04:11 gmcgarry Exp $ */
/*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
@@ -47,21 +47,35 @@
*
* This file should be rewritten readable.
*/
+#include "config.h"
+
#include <sys/types.h>
+#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
+#endif
-#include <stdio.h>
#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <libgen.h>
-#include <errno.h>
+#endif
+
+#ifdef WIN32
+#include <windows.h>
+#include <process.h>
+#include <io.h>
+#endif
-#include "../config.h"
+#include "compat.h"
#include "ccconfig.h"
/* C command */
@@ -72,34 +86,79 @@
/*
* Many specific definitions, should be declared elsewhere.
*/
-#define STDINC "/usr/include/"
-#define SBSIZE 10000
-#define MAXINC 100
-#define MAXFIL 100
+#ifndef STDINC
+#define STDINC "/usr/include/"
+#endif
+
+#ifndef LIBDIR
+#define LIBDIR "/usr/lib/"
+#endif
+
+#ifndef PREPROCESSOR
+#define PREPROCESSOR "pcpp"
+#endif
+
+#ifndef COMPILER
+#define COMPILER "pccom";
+#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
#define MAXAV 10000
#define MAXOPT 100
char *tmp3;
char *tmp4;
-char *outfile;
-char *copy(char *as),*setsuf(char *as, char ch);
-int getsuf(char []);
+char *outfile, *ermfile;
+char *Bprefix(char *);
+char *copy(char *, int),*setsuf(char *, char);
+int getsuf(char *);
int main(int, char *[]);
void error(char *, ...);
-void errorx(int eval, char *, ...);
-int nodup(char **, char *);
+void errorx(int, char *, ...);
int callsys(char [], char *[]);
int cunlink(char *);
-void dexit(int eval);
+void dexit(int);
void idexit(int);
-char *gettmp();
+char *gettmp(void);
+void *ccmalloc(int size);
+#ifdef WIN32
+char *win32pathsubst(char *);
+#endif
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 Vflag;
int dflag;
int pflag;
int sflag;
@@ -117,205 +176,416 @@
int pgflag;
int exfail;
int Xflag;
-int nostartfiles, Bstatic;
+int Wallflag;
+int Wflag;
+int nostartfiles, Bstatic, shared;
int nostdinc, nostdlib;
int onlyas;
int pthreads;
+int xcflag;
+int ascpp;
-char *pass0 = LIBEXECDIR "/pccom";
-char *passp = LIBEXECDIR "/pcpp";
+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;
+ char *cppmdadd[MAXCPPMDARGS];
+};
+
+struct cppmd cppmds[] = CPPMDADDS;
+#else
char *cppmdadd[] = CPPMDADD;
+#endif
#ifdef LIBCLIBS
char *libclibs[] = LIBCLIBS;
#else
char *libclibs[] = { "-lc", NULL };
#endif
+#ifdef LIBCLIBS_PROFILE
+char *libclibs_profile[] = LIBCLIBS_PROFILE;
+#else
+char *libclibs_profile[] = { "-lc_p", NULL };
+#endif
#ifndef STARTLABEL
#define STARTLABEL "__start"
#endif
+char *incdir = STDINC;
+char *libdir = LIBDIR;
+char *pccincdir = PCCINCDIR;
+char *pcclibdir = 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, c, nxo, na;
+ int nc, nl, nas, i, j, c, nxo, na;
+#ifdef MULTITARGET
+ int k;
+#endif
- i = nc = nl = nxo = 0;
+#ifdef WIN32
+ /* have to prefix path early. -B may override */
+ incdir = win32pathsubst(incdir);
+ libdir = win32pathsubst(libdir);
+ pccincdir = win32pathsubst(pccincdir);
+ pcclibdir = win32pathsubst(pcclibdir);
+ passp = win32pathsubst(passp);
+ pass0 = win32pathsubst(pass0);
+#endif
+
+ i = nc = nl = nas = nxo = 0;
pv = ptemp;
while(++i < argc) {
- if (argv[i][0] == '-')
- switch (argv[i][1]) {
- default:
- goto passa;
+ if (argv[i][0] == '-') {
+ switch (argv[i][1]) {
+ default:
+ goto passa;
+#ifdef notyet
+ /* must add library options first (-L/-l/...) */
+ error("unrecognized option `-%c'", argv[i][1]);
+ break;
+#endif
- case 'B': /* other search paths for binaries */
- Bflag = &argv[i][2];
- break;
+ case '-': /* double -'s */
+ if (strcmp(argv[i], "--version") == 0) {
+ printf("%s\n", VERSSTR);
+ return 0;
+ } else if (strcmp(argv[i], "--param") == 0)
+ /* NOTHING YET */;
+ else
+ error("unrecognized option %s", argv[i]);
+ break;
- case 'X':
- Xflag++;
- break;
- case 'W': /* Ignore (most of) W-flags */
- if (strncmp(argv[i], "-Wl,", 4) == 0) {
- /* options to the linker */
- t = &argv[i][4];
- while ((u = strchr(t, ','))) {
- *u++ = 0;
+ 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) {
+ t = argv[i+1];
+ i++;
+ }
+ if (strncmp(t, "?", 1) == 0) {
+ /* show machine targets */
+ printf("Available machine targets:");
+ for (j=0; cppmds[j].mach; j++)
+ printf(" %s",cppmds[j].mach);
+ printf("\n");
+ exit(0);
+ }
+ for (j=0; cppmds[j].mach; j++)
+ if (strcmp(t, cppmds[j].mach) == 0) {
+ mach = cppmds[j].mach;
+ break;
+ }
+ 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], "-Wl,", 4) == 0) {
+ /* options to the linker */
+ t = &argv[i][4];
+ while ((u = strchr(t, ','))) {
+ *u++ = 0;
+ llist[nl++] = t;
+ t = u;
+ }
llist[nl++] = t;
- t = u;
+ } 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 (!strncmp(argv[i], "-Wp,-V", 6))
+ Vflag++;
+ } 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;
+ }
}
- llist[nl++] = t;
- }
- break;
+ break;
- case 'f': /* GCC compatibility flags */
- if (strcmp(argv[i], "-fPIC") == 0)
- kflag = F_PIC;
- if (strcmp(argv[i], "-fpic") == 0)
- kflag = F_pic;
- /* silently ignore the rest */
- break;
+ case 'f': /* GCC compatibility flags */
+ if (strcmp(argv[i], "-fPIC") == 0)
+ kflag = F_PIC;
+ 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;
- case 'g': /* create debug output */
- gflag++;
- break;
+ case 'g': /* create debug output */
+ gflag++;
+ break;
- case 'i':
- if (strcmp(argv[i], "-isystem") == 0) {
- *pv++ = "-S";
- *pv++ = argv[++i];
- } else if (strcmp(argv[i], "-include") == 0) {
- *pv++ = "-i";
- *pv++ = argv[++i];
- } else
- goto passa;
- break;
+ case 'i':
+ if (strcmp(argv[i], "-isystem") == 0) {
+ *pv++ = "-S";
+ *pv++ = argv[++i];
+ } else if (strcmp(argv[i], "-include") == 0) {
+ *pv++ = "-i";
+ *pv++ = argv[++i];
+ } else if (strcmp(argv[i], "-idirafter") == 0) {
+ idirafter = argv[++i];
+ } else
+ goto passa;
+ break;
- case 'k': /* generate PIC code */
- kflag = F_pic;
- break;
+ case 'k': /* generate PIC code */
+ kflag = F_pic;
+ break;
- case 'n': /* handle -n flags */
- if (strcmp(argv[i], "-nostdinc") == 0)
- nostdinc++;
- if (strcmp(argv[i], "-nostdlib") == 0) {
- nostdlib++;
- nostartfiles++;
- } else if (strcmp(argv[i], "-nostartfiles") == 0)
- nostartfiles = 1;
- else
- goto passa;
- break;
+ case 'm': /* target-dependent options */
+ mlist[nm++] = argv[i];
+ break;
- case 'p':
- if (strcmp(argv[i], "-pg") == 0)
- pgflag++;
- else if (strcmp(argv[i], "-pthread") == 0)
- pthreads++;
- else
- errorx(1, "unknown option %s", argv[i]);
- break;
+ case 'n': /* handle -n flags */
+ if (strcmp(argv[i], "-nostdinc") == 0)
+ nostdinc++;
+ else if (strcmp(argv[i], "-nostdlib") == 0) {
+ nostdlib++;
+ nostartfiles++;
+ } else if (strcmp(argv[i], "-nostartfiles") == 0)
+ nostartfiles = 1;
+ else
+ goto passa;
+ break;
- case 'x':
- xlist[xnum++] = argv[i];
- break;
- case 't':
- tflag++;
- break;
- case 'S':
- sflag++;
- cflag++;
- break;
- case 'o':
- if (outfile)
- errorx(8, "too many -o");
- outfile = argv[++i];
- break;
- case 'O':
- Oflag++;
- break;
- case 'E':
- Eflag++;
- break;
- case 'P':
- pflag++;
- *pv++ = argv[i];
- case 'c':
- cflag++;
- break;
+ case 'p':
+ if (strcmp(argv[i], "-pg") == 0 ||
+ strcmp(argv[i], "-p") == 0)
+ pgflag++;
+ else if (strcmp(argv[i], "-pthread") == 0)
+ pthreads++;
+ else if (strcmp(argv[i], "-pipe") == 0)
+ /* NOTHING YET */;
+ else
+ errorx(1, "unknown option %s", argv[i]);
+ break;
+
+ case 'x':
+ t = &argv[i][2];
+ if (*t == 0)
+ t = argv[++i];
+ if (strcmp(t, "c") == 0)
+ xcflag = 1; /* default */
+ else if (strcmp(t, "assembler-with-cpp") == 0)
+ ascpp = 1;
+#ifdef notyet
+ else if (strcmp(t, "c++") == 0)
+ cxxflag++;
+#endif
+ else
+ xlist[xnum++] = argv[i];
+ break;
+ case 't':
+ tflag++;
+ break;
+ case 'S':
+ sflag++;
+ cflag++;
+ break;
+ case 'o':
+ if (outfile)
+ errorx(8, "too many -o");
+ outfile = argv[++i];
+ break;
+ case 'O':
+ if (argv[i][2] == '0')
+ Oflag = 0;
+ else
+ Oflag++;
+ break;
+ case 'E':
+ Eflag++;
+ break;
+ case 'P':
+ pflag++;
+ *pv++ = argv[i];
+ case 'c':
+ cflag++;
+ break;
#if 0
- case '2':
- if(argv[i][2] == '\0')
- pref = "/lib/crt2.o";
- else {
- pref = "/lib/crt20.o";
- }
- break;
+ case '2':
+ if(argv[i][2] == '\0')
+ pref = "/lib/crt2.o";
+ else {
+ pref = "/lib/crt20.o";
+ }
+ break;
#endif
- case 'D':
- case 'I':
- case 'U':
- case 'C':
- *pv++ = argv[i];
- if (argv[i][2] == 0)
- *pv++ = argv[++i];
- if (pv >= ptemp+MAXOPT)
- {
- error("Too many DIUC options");
- --pv;
+ case 'C':
+ Cflag = 1;
+ break;
+ case 'D':
+ case 'I':
+ case 'U':
+ *pv++ = argv[i];
+ if (argv[i][2] == 0)
+ *pv++ = argv[++i];
+ if (pv >= ptemp+MAXOPT) {
+ error("Too many DIU options");
+ --pv;
}
- break;
+ break;
- case 'M':
- Mflag++;
- break;
+ case 'M':
+ Mflag++;
+ break;
- case 'd':
- dflag++;
- strncpy(alist, argv[i], 19);
- break;
- case 'v':
- printf("%s\n", VERSSTR);
- vflag++;
- break;
+ case 'd':
+ dflag++;
+ strlcpy(alist, argv[i], sizeof (alist));
+ break;
+ case 'v':
+ printf("%s\n", VERSSTR);
+ vflag++;
+ break;
- case 's':
- if (strcmp(argv[i], "-static") == 0)
- Bstatic = 1;
- else
- goto passa;
- break;
+ case 's':
+ if (strcmp(argv[i], "-static") == 0)
+ Bstatic = 1;
+ 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;
+ }
} else {
passa:
t = argv[i];
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)
- {
+ if (nc>=MAXFIL) {
error("Too many source files");
exit(1);
- }
+ }
t = setsuf(t, 'o');
}
- if (nodup(llist, t)) {
+
+ /* Check for duplicate .o files. */
+ for (j = getsuf(t) == 'o' ? 0 : nl; j < nl; j++) {
+ if (strcmp(llist[j], t) == 0)
+ break;
+ }
+ if (j == nl) {
llist[nl++] = t;
- if (nl >= MAXLIB)
- {
+ if (nl >= MAXLIB) {
error("Too many object/library files");
exit(1);
- }
+ }
if (getsuf(t)=='o')
nxo++;
}
@@ -329,31 +599,30 @@
if (outfile && clist[0] && strcmp(outfile, clist[0]) == 0)
errorx(8, "output file will be clobbered");
#if 0
- for(i=0, j=0; i<nc; i++) {
- if((c=getsuf(clist[i]))=='c' || c=='S') {
- j++;
- break;
- }
- }
- if (j==0 && Eflag)
- errorx(8, "no file to be preprocessed");
-#endif
-
- if (gflag) Oflag = 0;
-#if 0
if (proflag)
pref = "/lib/mcrt0.o";
#endif
if(nc==0)
goto nocom;
if (pflag==0) {
- tmp3 = gettmp();
+ if (!sflag)
+ tmp3 = gettmp();
tmp4 = gettmp();
}
+ if (Bflag) {
+ incdir = Bflag;
+ libdir = Bflag;
+ pccincdir = Bflag;
+ pcclibdir = 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
+ pass0 = copy(LIBEXECDIR "/pccom_", k = strlen(mach));
+ strlcat(pass0, mach, sizeof(LIBEXECDIR "/pccom_") + k);
+#endif
pvt = pv;
for (i=0; i<nc; i++) {
/*
@@ -363,17 +632,17 @@
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];
- onlyas = 1;
goto assemble;
- } else if (getsuf(clist[i])=='S') {
- assource = clist[i];
- onlyas = 1;
}
if (pflag)
tmp4 = setsuf(clist[i], 'i');
@@ -384,36 +653,59 @@
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++] = "-C";
if (Mflag)
av[na++] = "-M";
+ if (Vflag)
+ av[na++] = "-V";
if (dflag)
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;
+ for (j = 0; cppmds[k].cppmdadd[j]; j++)
+ 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;
+ }
av[na++] = clist[i];
if (!Eflag && !Mflag)
av[na++] = tmp4;
if (Eflag && outfile)
- av[na++] = outfile;
+ ermfile = av[na++] = outfile;
av[na++]=0;
if (callsys(passp, av))
{exfail++; eflag++;}
if (Eflag || Mflag)
continue;
- if (onlyas)
+ if (onlyas) {
+ assource = tmp4;
goto assemble;
+ }
/*
* C compiler
@@ -421,18 +713,53 @@
com:
na = 0;
av[na++]= "pccom";
+ 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";
+#endif
if (Oflag) {
av[na++] = "-xtemps";
+ av[na++] = "-xdeljumps";
+ av[na++] = "-xinline";
}
for (j = 0; j < xnum; j++)
av[na++] = xlist[j];
- av[na++] = tmp4;
+ for (j = 0; j < nm; j++)
+ av[na++] = mlist[j];
+ if (getsuf(clist[i])=='i')
+ av[na++] = clist[i];
+ else
+ av[na++] = tmp4; /* created by cpp */
if (pflag || exfail)
{
cflag++;
@@ -440,11 +767,11 @@
}
if(sflag) {
if (outfile)
- assource = tmp3 = outfile;
+ tmp3 = outfile;
else
- assource = tmp3 = setsuf(clist[i], 's');
+ tmp3 = setsuf(clist[i], 's');
}
- av[na++] = tmp3;
+ ermfile = av[na++] = tmp3;
#if 0
if (proflag) {
av[3] = "-XP";
@@ -466,21 +793,30 @@
*/
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)
av[na++] = "-k";
av[na++] = "-o";
if (outfile && cflag)
- av[na++] = outfile;
+ ermfile = av[na++] = outfile;
else
- av[na++] = setsuf(clist[i], 'o');
- av[na++] = onlyas ? tmp4 : assource;
+ ermfile = av[na++] = setsuf(clist[i], 'o');
+ av[na++] = assource;
if (dflag)
av[na++] = alist;
av[na++] = 0;
- if (callsys("/bin/as", av)) {
+ if (callsys(as, av)) {
cflag++;
eflag++;
cunlink(tmp4);
@@ -498,26 +834,86 @@
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) && !defined(os_darwin)
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
+#define OUTSTR "/OUT:"
+ char *s = copy(OUTSTR, i = strlen(outfile));
+ strlcat(s, outfile, sizeof(OUTSTR) + i);
+ av[j++] = s;
+#else
av[j++] = "-o";
av[j++] = outfile;
+#endif
}
- if (!nostartfiles) {
- av[j++] = 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(startfiles_T[i]);
+ } else
+#endif
+ {
+#ifdef STARTFILES
+ for (i = 0; startfiles[i]; i++)
+ av[j++] = Bprefix(startfiles[i]);
+#endif
+ }
+ }
}
i = 0;
while(i<nl) {
@@ -525,21 +921,63 @@
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";
#endif
if (pthreads)
av[j++] = "-lpthread";
- if (!nostdlib)
- for (i = 0; libclibs[i]; i++)
- av[j++] = libclibs[i];
+ if (!nostdlib) {
+#ifdef MSLINKER
+#define DL "/LIBPATH:"
+#else
+#define DL "-L"
+#endif
+ char *s = copy(DL, i = strlen(pcclibdir));
+ strlcat(s, pcclibdir, sizeof(DL) + i);
+ av[j++] = s;
+#ifdef os_win32
+ s = copy(DL, i = strlen(libdir));
+ strlcat(s, libdir, sizeof(DL) + i);
+ av[j++] = s;
+#endif
+ if (pgflag) {
+ for (i = 0; libclibs_profile[i]; i++)
+ av[j++] = Bprefix(libclibs_profile[i]);
+ } else {
+ for (i = 0; libclibs[i]; i++)
+ av[j++] = Bprefix(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) {
@@ -572,6 +1010,10 @@
cunlink(tmp3);
cunlink(tmp4);
}
+ if (exfail || eflag)
+ cunlink(ermfile);
+ if (eval == 100)
+ _exit(eval);
exit(eval);
}
@@ -612,14 +1054,47 @@
dexit(eval);
}
+char *
+Bprefix(char *s)
+{
+ char *suffix;
+ char *str;
+ int i;
+
+#ifdef os_win32
+
+ /* put here to save sprinkling it ~everywhere */
+ s = win32pathsubst(s);
+
+ if (Bflag == NULL)
+ return s;
+ suffix = strrchr(s, '/');
+ if (suffix == NULL)
+ suffix = strrchr(s, '\\');
+
+#else
+
+ if (Bflag == NULL || s[0] != '/')
+ return s;
+ suffix = strrchr(s, '/');
+
+#endif
+
+ if (suffix == NULL)
+ suffix = s;
+
+ str = copy(Bflag, i = strlen(suffix));
+ strlcat(str, suffix, strlen(Bflag) + i + 1);
+ return str;
+}
+
int
-getsuf(as)
-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);
}
@@ -629,16 +1104,71 @@
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[])
+callsys(char *f, char *v[])
{
- int status;
- pid_t t;
+ int t;
+ 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) {
+ fprintf(stderr, "Can't find %s\n", f);
+ return 100;
+ }
+
+ WaitForSingleObject(pi.hProcess, INFINITE);
+ GetExitCodeProcess(pi.hProcess, &exitCode);
+ return (exitCode != 0);
+}
+
+#else
+
+int
+callsys(char *f, char *v[])
+{
+ int t, status = 0;
+ pid_t p;
char *s;
if (vflag) {
@@ -648,82 +1178,94 @@
fprintf(stderr, "\n");
}
- if ((t=fork())==0) {
+ if ((p = fork()) == 0) {
if (Bflag) {
size_t len = strlen(Bflag) + 8;
char *a = malloc(len);
- if (a == NULL)
- errorx(1, "callsys: malloc failed\n");
+ if (a == NULL) {
+ error("callsys: malloc failed");
+ exit(1);
+ }
if ((s = strrchr(f, '/'))) {
strlcpy(a, Bflag, len);
strlcat(a, s, len);
execv(a, v);
}
}
- execv(f, v);
+ execvp(f, v);
if ((s = strrchr(f, '/')))
execvp(s+1, v);
- printf("Can't find %s\n", f);
- exit(100);
- } else
- if (t == -1) {
+ fprintf(stderr, "Can't find %s\n", f);
+ _exit(100);
+ } else {
+ if (p == -1) {
printf("Try again\n");
return(100);
}
- while(t!=wait(&status));
- if ((t=(status&0377)) != 0 && t!=14) {
- if (t!=2) /* interrupt */
- errorx(8, "Fatal error in %s", f);
- dexit(eflag);
}
- return((status>>8) & 0377);
+ while (waitpid(p, &status, 0) == -1 && errno == EINTR)
+ ;
+ if (WIFEXITED(status))
+ return (WEXITSTATUS(status));
+ if (WIFSIGNALED(status))
+ 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
-nodup(l, os)
-char **l, *os;
+cunlink(char *f)
{
- register char *t, *s;
- register int c;
-
- s = os;
- if (getsuf(s) != 'o')
- return(1);
- while((t = *l++)) {
- while((c = *s++))
- if (c != *t++)
- break;
- if (*t=='\0' && c=='\0')
- return(0);
- s = os;
- }
- return(1);
+ if (f==0 || Xflag)
+ return(0);
+ return (unlink(f));
}
-int
-cunlink(f)
-char *f;
+#ifdef WIN32
+char *
+gettmp(void)
{
- if (f==0 || Xflag)
- return(0);
- return(unlink(f));
+#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()
+gettmp(void)
{
- char *sfn = strdup("/tmp/ctm.XXXXXX");
+ char *sfn = copy("/tmp/ctm.XXXXXX", 0);
int fd = -1;
if ((fd = mkstemp(sfn)) == -1) {
@@ -731,6 +1273,43 @@
exit(8);
}
close(fd);
-
return sfn;
}
+#endif
+
+void *
+ccmalloc(int size)
+{
+ void *rv;
+
+ if ((rv = malloc(size)) == NULL)
+ error("malloc failed");
+ return rv;
+}
+
+#ifdef WIN32
+
+char *
+win32pathsubst(char *s)
+{
+ char env[1024];
+ char *rv;
+ int len;
+
+ len = ExpandEnvironmentStrings(s, env, sizeof(env));
+ if (len <= 0)
+ return s;
+
+ while (env[len-1] == '/' || env[len-1] == '\\' || env[len-1] == '\0')
+ env[--len] = 0;
+
+ len += 3;
+ rv = ccmalloc(len);
+ strlcpy(rv, "\"", len);
+ strlcat(rv, env, len);
+ strlcat(rv, "\"", len);
+
+ return rv;
+}
+
+#endif
Index: Makefile
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/cc/Makefile,v
retrieving revision 1.8
retrieving revision 1.9
diff -L usr.bin/pcc/cc/Makefile -L usr.bin/pcc/cc/Makefile -u -r1.8 -r1.9
--- usr.bin/pcc/cc/Makefile
+++ usr.bin/pcc/cc/Makefile
@@ -5,8 +5,8 @@
TARGOS= midnightbsd
TARGMACH= ${MACHINE_ARCH}
-CFLAGS+= -DLIBEXECDIR=\"/usr/libexec\"
-CFLAGS+= -I${.CURDIR}/..
+CFLAGS+= -DLIBEXECDIR=\"/usr/libexec/\"
+CFLAGS+= -I${.CURDIR}/.. -I${.CURDIR}/../mip/
CFLAGS+= -Dmach_${TARGMACH} -Dos_${TARGOS}
BINDIR= /usr/bin
Index: inline.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/inline.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/ccom/inline.c -L usr.bin/pcc/ccom/inline.c -u -r1.1 -r1.2
--- usr.bin/pcc/ccom/inline.c
+++ usr.bin/pcc/ccom/inline.c
@@ -1,6 +1,6 @@
-/* $Id: inline.c,v 1.17 2007/09/09 10:01:01 ragge Exp $ */
+/* $Id: inline.c,v 1.25 2008/11/28 15:23:57 ragge Exp $ */
/*
- * Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
+ * Copyright (c) 2003, 2008 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,104 +32,135 @@
#include <stdarg.h>
/*
+ * Simple description of how the inlining works:
+ * A function found with the keyword "inline" is always saved.
+ * If it also has the keyword "extern" it is written out thereafter.
+ * If it has the keyword "static" it will be written out if it is referenced.
+ * inlining will only be done if -xinline is given, and only if it is
+ * possible to inline the function.
+ */
+static void printip(struct interpass *pole);
+
+/*
* ilink from ipole points to the next struct in the list of functions.
*/
static struct istat {
- struct istat *ilink;
- char *name;
- int type;
-#define NOTYETR 0 /* saved but not yet referenced */
-#define NOTYETW 1 /* saved and referenced but not yet written out */
-#define WRITTEN 2 /* is written out */
-#define NOTYETD 3 /* referenced but not yet saved */
+ SLIST_ENTRY(istat) link;
+ struct symtab *sp;
+ int flags;
+#define CANINL 1 /* function is possible to inline */
+#define WRITTEN 2 /* function is written out */
+#define REFD 4 /* Referenced but not yet written out */
+ int *args; /* Array of arg temp numbers */
+ int nargs; /* number of args in array */
+ int retval; /* number of return temporary, if any */
struct interpass shead;
-} *ipole, *cifun;
+} *cifun;
+
+static SLIST_HEAD(, istat) ipole = { NULL, &ipole.q_forw };
+static int nlabs;
#define IP_REF (MAXIP+1)
+#ifdef PCC_DEBUG
+#define SDEBUG(x) if (sdebug) printf x
+#else
+#define SDEBUG(x)
+#endif
-int isinlining, recovernodes;
+int isinlining;
int inlnodecnt, inlstatcnt;
-#define ialloc() permalloc(sizeof(struct istat)); inlstatcnt++
-#define nalloc() permalloc(sizeof(NODE))
+#define SZSI sizeof(struct istat)
+#define ialloc() memset(permalloc(SZSI), 0, SZSI); inlstatcnt++
static void
-tcnt(NODE *p)
+tcnt(NODE *p, void *arg)
{
inlnodecnt++;
+ if (nlabs > 1 && (p->n_op == REG || p->n_op == OREG) &&
+ regno(p) == FPREG)
+ SLIST_FIRST(&ipole)->flags &= ~CANINL; /* no stack refs */
+ if (nflag)
+ printf("locking node %p\n", p);
}
static struct istat *
-findfun(char *name)
+findfun(struct symtab *sp)
{
- struct istat *is = ipole;
- while (is) {
- if (is->name == name)
+ struct istat *is;
+
+ SLIST_FOREACH(is, &ipole, link)
+ if (is->sp == sp)
return is;
- is = is->ilink;
- }
return NULL;
}
static void
-refnode(char *str)
+refnode(struct symtab *sp)
{
struct interpass *ip;
- if (sdebug)
- printf("refnode(%s)\n", str);
+ SDEBUG(("refnode(%s)\n", sp->sname));
ip = permalloc(sizeof(*ip));
ip->type = IP_REF;
- ip->ip_name = str;
+ ip->ip_name = (char *)sp;
inline_addarg(ip);
}
void
inline_addarg(struct interpass *ip)
{
+ extern NODE *cftnod;
+
+// SDEBUG(("inline_addarg(%p)\n", ip));
DLIST_INSERT_BEFORE(&cifun->shead, ip, qelem);
+ if (ip->type == IP_DEFLAB)
+ nlabs++;
if (ip->type == IP_NODE)
- walkf(ip->ip_node, tcnt); /* Count as saved */
+ walkf(ip->ip_node, tcnt, 0); /* Count as saved */
+ if (cftnod)
+ cifun->retval = regno(cftnod);
}
/*
* Called to setup for inlining of a new function.
*/
void
-inline_start(char *name)
+inline_start(struct symtab *sp)
{
struct istat *is;
- if (sdebug)
- printf("inline_start(\"%s\")\n", name);
+ SDEBUG(("inline_start(\"%s\")\n", sp->sname));
if (isinlining)
cerror("already inlining function");
- if ((is = findfun(name)) == 0) {
- is = ialloc();
- is->ilink = ipole;
- ipole = is;
- is->name = name;
- is->type = NOTYETR;
+ if ((is = findfun(sp)) != 0) {
+ if (!DLIST_ISEMPTY(&is->shead, qelem))
+ uerror("inline function already defined");
} else {
- if (is->type != NOTYETD)
- cerror("inline function already defined");
- is->type = NOTYETW;
+ is = ialloc();
+ is->sp = sp;
+ SLIST_INSERT_FIRST(&ipole, is, link);
+ DLIST_INIT(&is->shead, qelem);
}
- DLIST_INIT(&is->shead, qelem);
cifun = is;
+ nlabs = 0;
isinlining++;
}
void
inline_end()
{
- if (sdebug)
- printf("inline_end()\n");
+ SDEBUG(("inline_end()\n"));
+ if (sdebug)printip(&cifun->shead);
isinlining = 0;
+ if (cifun->sp->sclass == EXTDEF) {
+ cifun->flags |= REFD;
+ inline_prtout();
+ }
}
/*
@@ -138,49 +169,85 @@
* The function may not be defined when inline_ref() is called.
*/
void
-inline_ref(char *name)
+inline_ref(struct symtab *sp)
{
- struct istat *w = ipole;
+ struct istat *w;
- if (sdebug)
- printf("inline_ref(\"%s\")\n", name);
+ SDEBUG(("inline_ref(\"%s\")\n", sp->sname));
+ if (sp->sclass == SNULL)
+ return; /* only inline, no references */
if (isinlining) {
- refnode(name);
+ refnode(sp);
} else {
- while (w != NULL) {
- if (w->name == name) {
- if (w->type == NOTYETR)
- w->type = NOTYETW;
- return; /* setup for writeout */
- }
- w = w->ilink;
+ SLIST_FOREACH(w,&ipole, link) {
+ if (w->sp != sp)
+ continue;
+ w->flags |= REFD;
+ return;
}
/* function not yet defined, print out when found */
w = ialloc();
- w->ilink = ipole;
- ipole = w;
- w->name = name;
- w->type = NOTYETD;
+ w->sp = sp;
+ w->flags |= REFD;
+ SLIST_INSERT_FIRST(&ipole, w, link);
+ DLIST_INIT(&w->shead, qelem);
}
}
static void
puto(struct istat *w)
{
+ struct interpass_prolog *ipp, *epp, *pp;
struct interpass *ip, *nip;
+ extern int crslab;
+ int lbloff = 0;
- /* if -O, list will be saved again so foreach cannot be used */
- ip = DLIST_NEXT(&w->shead, qelem);
- while (ip != (&w->shead)) {
- nip = DLIST_NEXT(ip, qelem);
- DLIST_REMOVE(ip, qelem);
- if (ip->type == IP_REF)
- inline_ref(ip->ip_name);
- else
- pass2_compile(ip);
- ip = nip;
+ /* Copy the saved function and print it out */
+ ipp = 0; /* XXX data flow analysis */
+ DLIST_FOREACH(ip, &w->shead, qelem) {
+ switch (ip->type) {
+ case IP_EPILOG:
+ case IP_PROLOG:
+ if (ip->type == IP_PROLOG) {
+ ipp = (struct interpass_prolog *)ip;
+ /* fix label offsets */
+ lbloff = crslab - ipp->ip_lblnum;
+ } else {
+ epp = (struct interpass_prolog *)ip;
+ crslab += (epp->ip_lblnum - ipp->ip_lblnum);
+ }
+ pp = tmpalloc(sizeof(struct interpass_prolog));
+ memcpy(pp, ip, sizeof(struct interpass_prolog));
+ pp->ip_lblnum += lbloff;
+#ifdef PCC_DEBUG
+ if (ip->type == IP_EPILOG && crslab != pp->ip_lblnum)
+ cerror("puto: %d != %d", crslab, pp->ip_lblnum);
+#endif
+ pass2_compile((struct interpass *)pp);
+ break;
+
+ case IP_REF:
+ inline_ref((struct symtab *)ip->ip_name);
+ break;
+
+ default:
+ nip = tmpalloc(sizeof(struct interpass));
+ *nip = *ip;
+ if (nip->type == IP_NODE) {
+ NODE *p;
+
+ p = nip->ip_node = tcopy(nip->ip_node);
+ if (p->n_op == GOTO)
+ p->n_left->n_lval += lbloff;
+ else if (p->n_op == CBRANCH)
+ p->n_right->n_lval += lbloff;
+ } else if (nip->type == IP_DEFLAB)
+ nip->ip_lbl += lbloff;
+ pass2_compile(nip);
+ break;
+ }
}
- DLIST_INIT(&w->shead, qelem);
+ w->flags |= WRITTEN;
}
/*
@@ -189,21 +256,246 @@
void
inline_prtout()
{
- struct istat *w = ipole;
+ struct istat *w;
int gotone = 0;
- if (w == NULL)
- return;
- recovernodes++;
- while (w != NULL) {
- if (w->type == NOTYETW) {
+ SLIST_FOREACH(w, &ipole, link) {
+ if ((w->flags & (REFD|WRITTEN)) == REFD &&
+ !DLIST_ISEMPTY(&w->shead, qelem)) {
+ defloc(w->sp);
puto(w);
- w->type = WRITTEN;
+ w->flags |= WRITTEN;
gotone++;
}
- w = w->ilink;
}
if (gotone)
inline_prtout();
- recovernodes--;
+}
+
+#if 1
+static void
+printip(struct interpass *pole)
+{
+ static char *foo[] = {
+ 0, "NODE", "PROLOG", "STKOFF", "EPILOG", "DEFLAB", "DEFNAM", "ASM" };
+ struct interpass *ip;
+ struct interpass_prolog *ipplg, *epplg;
+
+ DLIST_FOREACH(ip, pole, qelem) {
+ if (ip->type > MAXIP)
+ printf("IP(%d) (%p): ", ip->type, ip);
+ else
+ printf("%s (%p): ", foo[ip->type], ip);
+ switch (ip->type) {
+ case IP_NODE: printf("\n");
+#ifdef PCC_DEBUG
+ fwalk(ip->ip_node, eprint, 0); break;
+#endif
+ case IP_PROLOG:
+ ipplg = (struct interpass_prolog *)ip;
+ printf("%s %s regs %x autos %d mintemp %d minlbl %d\n",
+ ipplg->ipp_name, ipplg->ipp_vis ? "(local)" : "",
+ ipplg->ipp_regs[0], ipplg->ipp_autos, ipplg->ip_tmpnum,
+ ipplg->ip_lblnum);
+ break;
+ case IP_EPILOG:
+ epplg = (struct interpass_prolog *)ip;
+ printf("%s %s regs %x autos %d mintemp %d minlbl %d\n",
+ epplg->ipp_name, epplg->ipp_vis ? "(local)" : "",
+ epplg->ipp_regs[0], 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;
+ case IP_ASM: printf("%s\n", ip->ip_asm); break;
+ default:
+ break;
+ }
+ }
+}
+#endif
+
+static int toff;
+
+static NODE *
+mnode(int *n, NODE *p)
+{
+ NODE *q;
+ int num = *n + toff;
+
+ if (p->n_op == CM) {
+ q = p->n_right;
+ q = tempnode(num, q->n_type, q->n_df, q->n_sue);
+ n--;
+ p->n_right = buildtree(ASSIGN, q, p->n_right);
+ p->n_left = mnode(n, p->n_left);
+ p->n_op = COMOP;
+ } else {
+ p = pconvert(p);
+ q = tempnode(num, p->n_type, p->n_df, p->n_sue);
+ p = buildtree(ASSIGN, q, p);
+ }
+ return p;
+}
+
+static void
+rtmps(NODE *p, void *arg)
+{
+ if (p->n_op == TEMP)
+ regno(p) += toff;
+}
+
+/*
+ * Inline a function. Returns the return value.
+ * There are two major things that must be converted when
+ * inlining a function:
+ * - Label numbers must be updated with an offset.
+ * - The stack block must be relocated (add to REG or OREG).
+ * - Temporaries should be updated (but no must)
+ */
+NODE *
+inlinetree(struct symtab *sp, NODE *f, NODE *ap)
+{
+ extern int crslab, tvaloff;
+ struct istat *is = findfun(sp);
+ struct interpass *ip, *ipf, *ipl;
+ int lmin, stksz, L0, L1, L2;
+ OFFSZ stkoff;
+ NODE *p, *rp;
+
+ if (is == NULL) {
+ inline_ref(sp); /* prototype of not yet declared inline ftn */
+ return NIL;
+ }
+
+ SDEBUG(("inlinetree(%p,%p) OK %d\n", f, ap, is->flags & CANINL));
+
+ if ((is->flags & CANINL) == 0 || xinline == 0) {
+ if (is->sp->sclass == STATIC || is->sp->sclass == USTATIC)
+ is->flags |= REFD; /* if static inline, emit */
+ return NIL;
+ }
+
+#ifdef mach_i386
+ if (kflag) {
+ is->flags |= REFD; /* if static inline, emit */
+ return NIL; /* XXX cannot handle hidden ebx arg */
+ }
+#endif
+
+ stksz = stkoff = 0;
+ /* emit jumps to surround inline function */
+ branch(L0 = getlab());
+ plabel(L1 = getlab());
+ L2 = getlab();
+ SDEBUG(("branch labels %d,%d,%d\n", L0, L1, L2));
+
+ ipf = DLIST_NEXT(&is->shead, qelem); /* prolog */
+ ipl = DLIST_PREV(&is->shead, qelem); /* epilog */
+
+ /* Fix label & temp offsets */
+#define IPP(x) ((struct interpass_prolog *)x)
+ SDEBUG(("pre-offsets crslab %d tvaloff %d\n", crslab, tvaloff));
+ lmin = crslab - IPP(ipf)->ip_lblnum;
+ crslab += (IPP(ipl)->ip_lblnum - IPP(ipf)->ip_lblnum) + 1;
+ toff = tvaloff - IPP(ipf)->ip_tmpnum;
+ tvaloff += (IPP(ipl)->ip_tmpnum - IPP(ipf)->ip_tmpnum) + 1;
+ SDEBUG(("offsets crslab %d lmin %d tvaloff %d toff %d\n",
+ crslab, lmin, tvaloff, toff));
+
+ /* traverse until first real label */
+ ipf = DLIST_NEXT(ipf, qelem);
+ do
+ ipf = DLIST_NEXT(ipf, qelem);
+ while (ipf->type != IP_DEFLAB);
+
+ /* traverse backwards to last label */
+ do
+ ipl = DLIST_PREV(ipl, qelem);
+ while (ipl->type != IP_DEFLAB);
+
+ /* So, walk over all statements and emit them */
+ for (ip = ipf; ip != ipl; ip = DLIST_NEXT(ip, qelem)) {
+ switch (ip->type) {
+ case IP_NODE:
+ p = tcopy(ip->ip_node);
+ if (p->n_op == GOTO)
+ p->n_left->n_lval += lmin;
+ else if (p->n_op == CBRANCH)
+ p->n_right->n_lval += lmin;
+ walkf(p, rtmps, 0);
+#ifdef PCC_DEBUG
+ if (sdebug) {
+ printf("converted node\n");
+ fwalk(ip->ip_node, eprint, 0);
+ fwalk(p, eprint, 0);
+ }
+#endif
+ send_passt(IP_NODE, p);
+ break;
+
+ case IP_DEFLAB:
+ SDEBUG(("converted label %d to %d\n",
+ ip->ip_lbl, ip->ip_lbl + lmin));
+ send_passt(IP_DEFLAB, ip->ip_lbl + lmin);
+ break;
+
+ case IP_ASM:
+ send_passt(IP_ASM, ip->ip_asm);
+ break;
+
+ case IP_REF:
+ inline_ref((struct symtab *)ip->ip_name);
+ break;
+
+ default:
+ cerror("bad inline stmt %d", ip->type);
+ }
+ }
+ SDEBUG(("last label %d to %d\n", ip->ip_lbl, ip->ip_lbl + lmin));
+ send_passt(IP_DEFLAB, ip->ip_lbl + lmin);
+
+ branch(L2);
+ plabel(L0);
+
+ rp = block(GOTO, bcon(L1), NIL, INT, 0, MKSUE(INT));
+ if (is->retval)
+ p = tempnode(is->retval + toff, DECREF(sp->stype),
+ sp->sdf, sp->ssue);
+ else
+ p = bcon(0);
+ rp = buildtree(COMOP, rp, p);
+
+ if (is->nargs) {
+ p = mnode(&is->args[is->nargs-1], ap);
+ rp = buildtree(COMOP, p, rp);
+ }
+
+ tfree(f);
+ return rp;
+}
+
+void
+inline_args(struct symtab **sp, int nargs)
+{
+ struct istat *cf;
+ int i;
+
+ SDEBUG(("inline_args\n"));
+ cf = cifun;
+ /*
+ * First handle arguments. We currently do not inline anything if:
+ * - function has varargs
+ * - function args are volatile, checked if no temp node is asg'd.
+ */
+ if (nargs) {
+ for (i = 0; i < nargs; i++)
+ if ((sp[i]->sflags & STNODE) == 0)
+ return; /* not temporary */
+ cf->args = permalloc(sizeof(int)*nargs);
+ for (i = 0; i < nargs; i++)
+ cf->args[i] = sp[i]->soffset;
+ }
+ cf->nargs = nargs;
+ cf->flags |= CANINL;
}
Index: scan.l
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/scan.l,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/ccom/scan.l -L usr.bin/pcc/ccom/scan.l -u -r1.1 -r1.2
--- usr.bin/pcc/ccom/scan.l
+++ usr.bin/pcc/ccom/scan.l
@@ -1,5 +1,5 @@
%{
-/* $Id: scan.l,v 1.61 2007/09/19 17:20:26 ragge Exp $ */
+/* $Id: scan.l,v 1.81 2008/12/20 14:15:27 ragge Exp $ */
/*
* Copyright (c) 2002 Anders Magnusson. All rights reserved.
@@ -38,6 +38,7 @@
IS (u|U|l|L)*
%{
+#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
@@ -48,30 +49,29 @@
static NODE *cvtdig(int radix);
static NODE *charcon(void);
static void control(int);
-static NODE *floatcon(void);
-static NODE *fhexcon(void);
-int notype, parbal;
+static void pragma(void);
+int notype, parbal, inattr, parlvl;
+static int resw(TWORD, int);
-#define CPP_PRAGMA 1
#define CPP_IDENT 2
#define CPP_LINE 3
#define CPP_HASH 4
#ifdef STABS
-#define STABS_LINE(x) if (gflag && blevel) stabs_line(x)
+#define STABS_LINE(x) if (gflag && cftnsp) stabs_line(x)
#else
#define STABS_LINE(x)
#endif
#if defined(FLEX_SCANNER) && YY_FLEX_SUBMINOR_VERSION >= 31
-/* Hack to avoid unneccessary warnings */
+/* Hack to avoid unnecessary warnings */
FILE *yyget_in (void);
FILE *yyget_out (void);
int yyget_leng (void);
char *yyget_text (void);
-void yyset_in (FILE * in_str );
-void yyset_out (FILE * out_str );
+void yyset_in (FILE *);
+void yyset_out (FILE *);
int yyget_debug (void);
-void yyset_debug (int bdebug );
+void yyset_debug (int);
int yylex_destroy (void);
extern int yyget_lineno (void);
extern void yyset_lineno (int);
@@ -95,9 +95,9 @@
"case" { return(C_CASE); }
"char" { yylval.nodep = mkty((TWORD)CHAR, 0, MKSUE(CHAR));
notype=1; return(C_TYPE); }
-"const" { yylval.nodep =
- block(QUALIFIER, NIL, NIL, CON, 0, 0);
- return(C_QUALIFIER); }
+"_Complex" { yylval.nodep = mkty((TWORD)COMPLEX, 0, MKSUE(DOUBLE));
+ notype=1; return(C_TYPE); }
+"const" { return resw(CON, C_QUALIFIER); }
"continue" { return(C_CONTINUE); }
"default" { return(C_DEFAULT); }
"do" { return(C_DO); }
@@ -125,60 +125,48 @@
notype=1; return(C_TYPE); }
"sizeof" { return(C_SIZEOF); }
"static" { yylval.intval = STATIC; return(C_CLASS); }
-"struct" { yylval.intval = INSTRUCT; notype=1; return(C_STRUCT); }
+"struct" { yylval.intval = STNAME; notype=1; return(C_STRUCT); }
"switch" { return(C_SWITCH); }
"typedef" { yylval.intval = TYPEDEF; return(C_CLASS); }
-"union" { yylval.intval = INUNION; notype=1; return(C_STRUCT); }
+"union" { yylval.intval = UNAME; notype=1; return(C_STRUCT); }
"unsigned" { yylval.nodep = mkty((TWORD)UNSIGNED, 0, MKSUE(UNSIGNED));
notype=1; return(C_TYPE); }
"void" { yylval.nodep = mkty((TWORD)VOID, 0, MKSUE(VOID));
notype=1; return(C_TYPE); }
-"volatile" { yylval.nodep =
- block(QUALIFIER, NIL, NIL, VOL, 0, 0);
- return(C_QUALIFIER); }
+"volatile" { return resw(VOL, C_QUALIFIER); }
"while" { return(C_WHILE); }
-{L}({L}|{D})* { struct symtab *s;
- int i;
+{L}({L}|{D})* { struct symtab *s;
+ int i = 0;
- yylval.strp = addname(yytext);
- if ((i = gcc_keyword(yylval.strp,
- &yylval.nodep)) != 0)
- return i;
-// printf("str: %s notype %d parbal %d\n", yytext, notype, parbal);
- if (!notype) {
- s = lookup(yylval.strp, SNOCREAT);
- if (s && s->sclass == TYPEDEF)
- return notype=1, C_TYPENAME;
- }
- return(C_NAME);
+ yylval.strp = addname(yytext);
+#ifdef GCC_COMPAT
+ if ((i = gcc_keyword(yylval.strp, &yylval.nodep)) > 0)
+ return i;
+#endif
+ if (i == 0) {
+ if (notype)
+ return(C_NAME);
+ s = lookup(yylval.strp, SNOCREAT);
+ return s && s->sclass == TYPEDEF ?
+ notype=1, C_TYPENAME : C_NAME;
}
+ }
0[xX]{H}+{IS}? { yylval.nodep = cvtdig(16); return(C_ICON); }
0{D}+{IS}? { yylval.nodep = cvtdig(8); return(C_ICON); }
{D}+{IS}? { yylval.nodep = cvtdig(10); return(C_ICON); }
L?'(\\.|[^\\'])+' { yylval.nodep = charcon(); return(C_ICON); }
-{D}+{E}{FS}? { yylval.nodep = floatcon(); return(C_FCON); }
-{D}*"."{D}+({E})?{FS}? { yylval.nodep = floatcon(); return(C_FCON); }
-{D}+"."{D}*({E})?{FS}? { yylval.nodep = floatcon(); return(C_FCON); }
-0[xX]{H}*"."{H}+{P}{FS}? { yylval.nodep = fhexcon(); return(C_FCON); }
-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;
- }
+{D}+{E}{FS}? { yylval.nodep = floatcon(yytext); return(C_FCON); }
+{D}*"."{D}+({E})?{FS}? { yylval.nodep = floatcon(yytext); return(C_FCON); }
+{D}+"."{D}*({E})?{FS}? { yylval.nodep = floatcon(yytext); return(C_FCON); }
+0[xX]{H}*"."{H}+{P}{FS}? { yylval.nodep = fhexcon(yytext); return(C_FCON); }
+0[xX]{H}+"."{P}{FS}? { yylval.nodep = fhexcon(yytext); return(C_FCON); }
+0[xX]{H}+{P}{FS}? { yylval.nodep = fhexcon(yytext); return(C_FCON); }
+
+L?\"(\\.|[^\\"])*\" { yylval.strp = yytext; return C_STRING; }
+
"..." { return(C_ELLIPSIS); }
">>=" { yylval.intval = RSEQ; return(C_ASOP); }
"<<=" { yylval.intval = LSEQ; return(C_ASOP); }
@@ -203,12 +191,16 @@
"!=" { yylval.intval = NE; return(C_EQUOP); }
";" { notype = 0; return(';'); }
("{"|"<%") { notype = 0; return('{'); }
-("}"|"%>") { return('}'); }
+("}"|"%>") { if (rpole) notype = 1; return('}'); }
"," { if (parbal) notype = 0; return(','); }
":" { return(':'); }
"=" { return('='); }
"(" { parbal++; notype = 0; return('('); }
-")" { parbal--; if (parbal==0) { notype = 0; } return(')'); }
+")" { parbal--;
+ if (parbal==0) { notype = 0; }
+ if (inattr && parlvl == parbal)
+ inattr = 0;
+ return(')'); }
("["|"<:") { return('['); }
("]"|":>") { return(']'); }
"." { yylval.intval = DOT; return(C_STROP); }
@@ -225,7 +217,7 @@
"^" { return('^'); }
"|" { return('|'); }
"?" { return('?'); }
-^#pragma[ \t].* { control(CPP_PRAGMA); }
+^#pragma[ \t].* { pragma(); }
^#ident[ \t].* { control(CPP_IDENT); }
^#line[ \t].* { control(CPP_LINE); }
^#.* { control(CPP_HASH); }
@@ -246,6 +238,25 @@
return(1);
}
+int
+resw(TWORD t, int rv)
+{
+ if (inattr) {
+ yylval.strp = addname(yytext);
+ return C_NAME;
+ }
+
+ switch (rv) {
+ case C_QUALIFIER:
+ yylval.nodep = block(QUALIFIER, NIL, NIL, t, 0, 0);
+ return C_QUALIFIER;
+ default:
+ cerror("resw");
+ }
+ return 0;
+}
+
+#ifndef SOFTFLOAT
/*
* XXX floatcon() and fhexcon() should be in support libraries for
* the target floating point.
@@ -266,9 +277,9 @@
}
NODE *
-floatcon(void)
+floatcon(char *s)
{
- return f2(yytext);
+ return f2(s);
}
static int
@@ -283,10 +294,9 @@
}
NODE *
-fhexcon(void)
+fhexcon(char *c)
{
char buf[500];
- char *c = yytext;
unsigned long long num1, num2;
/* XXX - convert it to a decimal float number and use strtod */
@@ -307,6 +317,7 @@
snprintf(buf, sizeof(buf), "%llu.%lluE%s", num1, num2, c);
return f2(buf);
}
+#endif
unsigned int
esccon(char **sptr)
@@ -325,9 +336,13 @@
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];
}
@@ -387,8 +402,7 @@
ntype = UNSIGNED;
}
ntype = ctype(ntype);
- p = block(ICON, NIL, NIL, ntype, 0, MKSUE(ntype));
- p->n_lval = v;
+ p = xbcon(v, NULL, ntype);
ASGLVAL(p->n_slval, v);
return p;
@@ -432,7 +446,6 @@
wr++; /* Skip initial '#' */
switch (t) {
- case CPP_PRAGMA:
case CPP_IDENT:
return; /* Just skip these for now. */
@@ -447,6 +460,8 @@
lineno = val - 1;
while (*wr && *wr != '\"')
wr++;
+ if (*wr == 0)
+ return;
if (*wr++ != '\"')
goto bad;
eptr = wr;
@@ -465,3 +480,62 @@
bad:
werror("%s: illegal control", yytext);
}
+
+/*
+ * split a pragma string in parts.
+ */
+static char **
+splitup(char *str)
+{
+ char *s, **ary;
+ int i;
+
+ /* count ws. at least needed array size, add 2 to terminate */
+ for (i = 2, s = str; *s; s++)
+ 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(,)"))
+ ary[i++] = s;
+ ary[i] = NULL;
+ return ary;
+}
+
+int pragma_allpacked;
+int pragma_packed, pragma_aligned;
+char *pragma_renamed;
+
+/*
+ * got a full pragma line. Split it up here.
+ */
+static void
+pragma()
+{
+ char **ary;
+
+ ary = splitup(yytext);
+ if (ary[1] == NULL)
+ goto bad;
+ 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)) {
+ return;
+ } else {
+bad:
+ if (Wunknown_pragmas)
+ werror("unknown pragma");
+ }
+}
+
+void
+cunput(char c)
+{
+ unput(c);
+}
Index: pftn.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/pftn.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/ccom/pftn.c -L usr.bin/pcc/ccom/pftn.c -u -r1.1 -r1.2
--- usr.bin/pcc/ccom/pftn.c
+++ usr.bin/pcc/ccom/pftn.c
@@ -1,4 +1,4 @@
-/* $Id: pftn.c,v 1.171 2007/09/23 20:00:22 ragge Exp $ */
+/* $Id: pftn.c,v 1.241 2008/12/14 17:19:50 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -69,49 +69,41 @@
#include <string.h> /* XXX - for strcmp */
-struct symtab *spname;
+#include "cgram.h"
+
struct symtab *cftnsp;
-static int strunem; /* currently parsed member type */
int arglistcnt, dimfuncnt; /* statistics */
int symtabcnt, suedefcnt; /* statistics */
int autooff, /* the next unused automatic offset */
maxautooff, /* highest used automatic offset in function */
- argoff, /* the next unused argument offset */
- strucoff; /* the next structure offset position */
+ argoff; /* the next unused argument offset */
int retlab = NOLAB; /* return label for subroutine */
int brklab;
int contlab;
int flostat;
-int instruct, blevel;
+int blevel;
int reached, prolab;
struct params;
-#define ISSTR(ty) (ty == STRTY || ty == UNIONTY || ty == ENUMTY)
+#define ISSTR(ty) (ty == STRTY || ty == UNIONTY)
#define ISSOU(ty) (ty == STRTY || ty == UNIONTY)
#define MKTY(p, t, d, s) r = talloc(); *r = *p; \
r = argcast(r, t, d, s); *p = *r; nfree(r);
/*
- * Info stored for delaying string printouts.
- */
-struct strsched {
- struct strsched *next;
- int locctr;
- struct symtab *sym;
-} *strpole;
-
-/*
* Linked list stack while reading in structs.
*/
struct rstack {
struct rstack *rnext;
- int rinstruct;
- int rclass;
- int rstrucoff;
- struct params *rlparam;
+ int rsou;
+ int rstr;
struct symtab *rsym;
-};
+ struct symtab *rb;
+ struct suedef *rsue;
+ int flags;
+#define LASTELM 1
+} *rpole;
/*
* Linked list for parameter (and struct elements) declaration.
@@ -127,6 +119,7 @@
static NODE *arrstk[10];
static int arrstkp;
static int intcompare;
+static NODE *parlink;
void fixtype(NODE *p, int class);
int fixclass(int class, TWORD type);
@@ -135,9 +128,9 @@
void inforce(OFFSZ n);
void vfdalign(int n);
static void ssave(struct symtab *);
-static void strprint(void);
static void alprint(union arglist *al, int in);
static void lcommadd(struct symtab *sp);
+extern int fun_inline;
int ddebug = 0;
@@ -161,6 +154,9 @@
p = q->n_sp;
+ if (p->sname == NULL)
+ cerror("defining null identifier");
+
#ifdef PCC_DEBUG
if (ddebug) {
printf("defid(%s (%p), ", p->sname, p);
@@ -195,16 +191,13 @@
if (blevel == 1) {
switch (class) {
default:
- if (!(class&FIELD))
+ if (!(class&FIELD) && !ISFTN(type))
uerror("declared argument %s missing",
p->sname );
case MOS:
- case STNAME:
case MOU:
- case UNAME:
- case MOE:
- case ENAME:
case TYPEDEF:
+ case PARAM:
;
}
}
@@ -228,10 +221,11 @@
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;
@@ -252,9 +246,7 @@
#endif
/* check that redeclarations are to the same structure */
- if ((temp == STRTY || temp == UNIONTY || temp == ENUMTY) &&
- p->ssue != q->n_sue &&
- class != STNAME && class != UNAME && class != ENAME) {
+ if ((temp == STRTY || temp == UNIONTY) && p->ssue != q->n_sue) {
goto mismatch;
}
@@ -265,99 +257,87 @@
printf(" previous class: %s\n", scnames(scl));
#endif
- if (class&FIELD) {
- /* redefinition */
- if (!falloc(p, class&FLDSIZ, 1, NIL)) {
- /* successful allocation */
- ssave(p);
- return;
- }
- /* blew it: resume at end of switch... */
- } else switch(class) {
+ if (class & FIELD)
+ return;
+ switch(class) {
case EXTERN:
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;
+ case SNULL:
+ if (p->sflags & SINLINE) {
+ p->sclass = EXTDEF;
+ inline_ref(p);
+ goto done;
}
+ break;
+ }
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:
- if (scl == class) {
- if (oalloc(p, &strucoff))
- break;
- if (class == MOU)
- strucoff = 0;
- ssave(p);
- return;
- }
- break;
-
- case MOE:
- break;
+ goto done;
case EXTDEF:
switch (scl) {
case EXTERN:
p->sclass = EXTDEF;
- return;
+ goto done;
case USTATIC:
p->sclass = STATIC;
- return;
+ goto done;
}
break;
- case STNAME:
- case UNAME:
- case ENAME:
- if (scl != class)
- break;
- if (p->ssue->suesize == 0)
- return; /* previous entry just a mention */
- break;
-
case AUTO:
case REGISTER:
- ; /* mismatch.. */
+ if (blevel == slev)
+ goto redec;
+ break; /* mismatch.. */
+ case SNULL:
+ if (fun_inline && ISFTN(type))
+ goto done;
+ break;
}
mismatch:
@@ -368,12 +348,12 @@
if (blevel == slev || class == EXTERN || class == FORTRAN ||
class == UFORTRAN) {
if (ISSTR(class) && !ISSTR(p->sclass)) {
- uerror("redeclaration of %s", p->sname);
+redec: uerror("redeclaration of %s", p->sname);
return;
}
}
if (blevel == 0)
- uerror("redeclaration of %s", p->sname);
+ goto redec;
q->n_sp = p = hide(p);
enter: /* make a new entry */
@@ -387,24 +367,9 @@
p->sclass = class;
p->slevel = blevel;
p->soffset = NOOFFSET;
- p->suse = lineno;
- if (class == STNAME || class == UNAME || class == ENAME) {
- p->ssue = permalloc(sizeof(struct suedef));
- suedefcnt++;
- p->ssue->suesize = 0;
- p->ssue->suelem = NULL;
- p->ssue->suealign = ALSTRUCT;
- } else {
- switch (BTYPE(type)) {
- case STRTY:
- case UNIONTY:
- case ENUMTY:
- p->ssue = q->n_sue;
- break;
- default:
- p->ssue = MKSUE(BTYPE(type));
- }
- }
+ if (q->n_sue == NULL)
+ cerror("q->n_sue == NULL");
+ p->ssue = q->n_sue;
/* copy dimensions */
p->sdf = q->n_df;
@@ -415,7 +380,6 @@
/* allocate offsets */
if (class&FIELD) {
(void) falloc(p, class&FLDSIZ, 0, NIL); /* new entry */
- ssave(p);
} else switch (class) {
case REGISTER:
@@ -427,47 +391,45 @@
else
oalloc(p, &autooff);
break;
- case STATIC:
- case EXTDEF:
- p->soffset = getlab();
-#ifdef GCC_COMPAT
- { extern char *renname;
- if (renname)
- gcc_rename(p, renname);
- renname = NULL;
+ case PARAM:
+ if (ISARY(p->stype)) {
+ /* remove array type on parameters before oalloc */
+ p->stype += (PTR-ARY);
+ p->sdf++;
}
-#endif
+ if (arrstkp)
+ dynalloc(p, &argoff);
+ else
+ oalloc(p, &argoff);
break;
-
+
+ case STATIC:
+ case EXTDEF:
case EXTERN:
case UFORTRAN:
case FORTRAN:
p->soffset = getlab();
-#ifdef notdef
- /* Cannot reset level here. What does the standard say??? */
- p->slevel = 0;
-#endif
-#ifdef GCC_COMPAT
- { extern char *renname;
- if (renname)
- gcc_rename(p, renname);
- renname = NULL;
- }
-#endif
+ if (pragma_renamed)
+ p->soname = pragma_renamed;
+ pragma_renamed = NULL;
break;
+
case MOU:
+ rpole->rstr = 0;
+ /* FALLTHROUGH */
case MOS:
- oalloc(p, &strucoff);
+ oalloc(p, &rpole->rstr);
if (class == MOU)
- strucoff = 0;
- ssave(p);
+ rpole->rstr = 0;
break;
-
- case MOE:
- p->soffset = strucoff++;
- ssave(p);
+ case SNULL:
+#ifdef notdef
+ if (fun_inline) {
+ p->slevel = 1;
+ p->soffset = getlab();
+ }
+#endif
break;
-
}
#ifdef STABS
@@ -475,12 +437,13 @@
stabs_newsym(p);
#endif
+done:
+ fixdef(p); /* Leave last word to target */
#ifdef PCC_DEBUG
if (ddebug)
printf( " sdf, ssue, offset: %p, %p, %d\n",
p->sdf, p->ssue, p->soffset);
#endif
-
}
void
@@ -492,13 +455,10 @@
p->next = NULL;
p->sym = sym;
- if (lparam == NULL) {
- p->prev = (struct params *)&lpole;
+ if ((p->prev = lparam) == NULL)
lpole = p;
- } else {
+ else
lparam->next = p;
- p->prev = lparam;
- }
lparam = p;
}
@@ -508,22 +468,24 @@
void
ftnend()
{
+ extern NODE *cftnod;
extern struct savbc *savbc;
extern struct swdef *swpole;
+ extern int tvaloff;
char *c;
if (retlab != NOLAB && nerrors == 0) { /* inside a real function */
plabel(retlab);
+ if (cftnod)
+ ecomp(buildtree(FORCE, cftnod, NIL));
efcode(); /* struct return handled here */
- c = cftnsp->sname;
-#ifdef GCC_COMPAT
- c = gcc_findname(cftnsp);
-#endif
+ c = cftnsp->soname;
SETOFF(maxautooff, ALCHAR);
- send_passt(IP_EPILOG, 0, maxautooff/SZCHAR, c,
- cftnsp->stype, cftnsp->sclass == EXTDEF, retlab);
+ send_passt(IP_EPILOG, maxautooff/SZCHAR, c,
+ cftnsp->stype, cftnsp->sclass == EXTDEF, retlab, tvaloff);
}
+ cftnod = NIL;
tcheck();
brklab = contlab = retlab = NOLAB;
flostat = 0;
@@ -537,6 +499,7 @@
}
savbc = NULL;
lparam = NULL;
+ cftnsp = NULL;
maxautooff = autooff = AUTOINIT;
reached = 1;
@@ -544,11 +507,13 @@
inline_end();
inline_prtout();
- strprint();
-
tmpfree(); /* Release memory resources */
}
+static struct symtab nulsym = {
+ NULL, 0, 0, 0, 0, "null", "null", INT, 0, NULL, NULL
+};
+
void
dclargs()
{
@@ -556,15 +521,12 @@
union arglist *al, *al2, *alb;
struct params *a;
struct symtab *p, **parr = NULL; /* XXX gcc */
- char *c;
int i;
- argoff = ARGINIT;
-
/*
* Deal with fun(void) properly.
*/
- if (nparams == 1 && lparam->sym->stype == VOID)
+ if (nparams == 1 && lparam->sym && lparam->sym->stype == VOID)
goto done;
/*
@@ -575,11 +537,13 @@
parr = tmpalloc(sizeof(struct symtab *) * nparams);
if (nparams)
- for (a = lparam, i = 0; a != NULL && a != (struct params *)&lpole;
- a = a->prev) {
-
+ for (a = lparam, i = 0; a != NULL; a = a->prev) {
p = a->sym;
parr[i++] = p;
+ if (p == NULL) {
+ uerror("parameter %d name missing", i);
+ p = &nulsym; /* empty symtab */
+ }
if (p->stype == FARG) {
p->stype = INT;
p->ssue = MKSUE(INT);
@@ -591,8 +555,6 @@
werror("function declared as argument");
p->stype = INCREF(p->stype);
}
- /* always set aside space, even for register arguments */
- oalloc(p, &argoff);
#ifdef STABS
if (gflag)
stabs_newsym(p);
@@ -618,41 +580,66 @@
if (chkftn(al, alb))
uerror("function doesn't match prototype");
intcompare = 0;
+
}
+
+ if (oldstyle && nparams) {
+ /* Must recalculate offset for oldstyle args here */
+ argoff = ARGINIT;
+ for (i = 0; i < nparams; i++) {
+ parr[i]->soffset = NOOFFSET;
+ oalloc(parr[i], &argoff);
+ }
+ }
+
done: cendarg();
- c = cftnsp->sname;
-#ifdef GCC_COMPAT
- c = gcc_findname(cftnsp);
-#endif
-#if 0
- prolab = getlab();
- send_passt(IP_PROLOG, -1, -1, c, cftnsp->stype,
- cftnsp->sclass == EXTDEF, prolab);
-#endif
+
plabel(prolab); /* after prolog, used in optimization */
retlab = getlab();
bfcode(parr, nparams);
- if (xtemps) {
- /* put arguments in temporaries */
- for (i = 0; i < nparams; i++) {
- NODE *q, *r, *s;
-
- p = parr[i];
- if (p->stype == STRTY || p->stype == UNIONTY ||
- cisreg(p->stype) == 0)
- continue;
- spname = p;
- q = buildtree(NAME, 0, 0);
- r = tempnode(0, p->stype, p->sdf, p->ssue);
- s = buildtree(ASSIGN, r, q);
- p->soffset = r->n_lval;
- p->sflags |= STNODE;
- ecomp(s);
- }
- plabel(getlab()); /* used when spilling */
- }
+ if (fun_inline && xinline)
+ inline_args(parr, nparams);
+ plabel(getlab()); /* used when spilling */
+ if (parlink)
+ ecomp(parlink);
+ parlink = NIL;
lparam = NULL;
nparams = 0;
+ symclear(1); /* In case of function pointer args */
+}
+
+/*
+ * Struct/union/enum symtab construction.
+ */
+static void
+defstr(struct symtab *sp, int class)
+{
+ sp->ssue = permalloc(sizeof(struct suedef));
+ memset(sp->ssue, 0, sizeof(struct suedef));
+ sp->sclass = class;
+ if (class == STNAME)
+ sp->stype = STRTY;
+ else if (class == UNAME)
+ sp->stype = UNIONTY;
+ else if (class == ENAME)
+ sp->stype = ENUMTY;
+}
+
+/*
+ * Declare a struct/union/enum tag.
+ * If not found, create a new tag with UNDEF type.
+ */
+static struct symtab *
+deftag(char *name, int class)
+{
+ struct symtab *sp;
+
+ if ((sp = lookup(name, STAGNAME))->ssue == NULL) {
+ /* New tag */
+ defstr(sp, class);
+ } else if (sp->sclass != class)
+ uerror("tag %s redeclared", name);
+ return sp;
}
/*
@@ -661,194 +648,246 @@
NODE *
rstruct(char *tag, int soru)
{
- struct symtab *p;
- NODE *q;
+ struct symtab *sp;
- p = (struct symtab *)lookup(tag, STAGNAME);
- switch (p->stype) {
+ sp = deftag(tag, soru);
+ return mkty(sp->stype, 0, sp->ssue);
+}
- case UNDEF:
- def:
- q = block(NAME, NIL, NIL, 0, 0, 0);
- q->n_sp = p;
- q->n_type = (soru&INSTRUCT) ? STRTY :
- ((soru&INUNION) ? UNIONTY : ENUMTY);
- defid(q, (soru&INSTRUCT) ? STNAME :
- ((soru&INUNION) ? UNAME : ENAME));
- nfree(q);
- break;
+static int enumlow, enumhigh;
+int enummer;
- case STRTY:
- if (soru & INSTRUCT)
- break;
- goto def;
+/*
+ * Declare a member of enum.
+ */
+void
+moedef(char *name)
+{
+ struct symtab *sp;
- case UNIONTY:
- if (soru & INUNION)
- break;
- goto def;
+ sp = lookup(name, SNORMAL);
+ if (sp->stype == UNDEF || (sp->slevel < blevel)) {
+ if (sp->stype != UNDEF)
+ sp = hide(sp);
+ sp->stype = INT; /* always */
+ sp->ssue = MKSUE(INT);
+ sp->sclass = MOE;
+ sp->soffset = enummer;
+ } else
+ uerror("%s redeclared", name);
+ if (enummer < enumlow)
+ enumlow = enummer;
+ if (enummer > enumhigh)
+ enumhigh = enummer;
+ enummer++;
+}
- case ENUMTY:
- if (!(soru&(INUNION|INSTRUCT)))
- break;
- goto def;
+/*
+ * Declare an enum tag. Complain if already defined.
+ */
+struct symtab *
+enumhd(char *name)
+{
+ struct symtab *sp;
+
+ enummer = enumlow = enumhigh = 0;
+ if (name == NULL)
+ return NULL;
+ sp = deftag(name, ENAME);
+ if (sp->stype != ENUMTY) {
+ if (sp->slevel == blevel)
+ uerror("%s redeclared", name);
+ sp = hide(sp);
+ defstr(sp, ENAME);
}
- q = mkty(p->stype, 0, p->ssue);
- q->n_sue = p->ssue;
- return q;
+ sp->ssue->sylnk = sp; /* ourselves */
+ return sp;
}
-void
-moedef(char *name)
+/*
+ * finish declaration of an enum
+ */
+NODE *
+enumdcl(struct symtab *sp)
{
- NODE *q;
+ NODE *p;
+ TWORD t;
- q = block(NAME, NIL, NIL, MOETY, 0, 0);
- q->n_sp = lookup(name, 0);
- defid(q, MOE);
- nfree(q);
+#ifdef ENUMSIZE
+ t = ENUMSIZE(enumhigh, enumlow);
+#else
+ if (enumhigh <= MAX_CHAR && enumlow >= MIN_CHAR)
+ t = ctype(CHAR);
+ else if (enumhigh <= MAX_SHORT && enumlow >= MIN_SHORT)
+ t = ctype(SHORT);
+ else
+ t = ctype(INT);
+#endif
+ if (sp) {
+ sp->stype = t;
+ sp->ssue = MKSUE(t);
+ }
+ p = mkty(t, 0, MKSUE(t));
+ p->n_sp = sp;
+ return p;
+}
+
+/*
+ * Handle reference to an enum
+ */
+NODE *
+enumref(char *name)
+{
+ struct symtab *sp;
+ NODE *p;
+
+ sp = lookup(name, STAGNAME);
+
+#ifdef notdef
+ /*
+ * 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);
+#endif
+ if (sp->sclass == SNULL) {
+ /* declare existence of enum */
+ sp = enumhd(name);
+ sp->stype = ENUMTY;
+ }
+
+ p = mkty(sp->stype, 0, sp->ssue);
+ p->n_sp = sp;
+ return p;
}
/*
* begining of structure or union declaration
*/
struct rstack *
-bstruct(char *name, int soru)
+bstruct(char *name, int soru, struct suedef *sue)
{
struct rstack *r;
- struct symtab *s;
- NODE *q;
+ struct symtab *sp;
- if (name != NULL)
- s = lookup(name, STAGNAME);
- else
- s = NULL;
+ if (name != NULL) {
+ sp = deftag(name, soru);
+ if (sp->ssue->suealign != 0) {
+ if (sp->slevel < blevel) {
+ sp = hide(sp);
+ defstr(sp, soru);
+ } else
+ uerror("%s redeclared", name);
+ }
+ } else
+ sp = NULL;
- r = tmpalloc(sizeof(struct rstack));
- r->rinstruct = instruct;
- r->rclass = strunem;
- r->rstrucoff = strucoff;
-
- strucoff = 0;
- instruct = soru;
- q = block(NAME, NIL, NIL, 0, 0, 0);
- q->n_sp = s;
- if (instruct==INSTRUCT) {
- strunem = MOS;
- q->n_type = STRTY;
- if (s != NULL)
- defid(q, STNAME);
- } else if(instruct == INUNION) {
- strunem = MOU;
- q->n_type = UNIONTY;
- if (s != NULL)
- defid(q, UNAME);
- } else { /* enum */
- strunem = MOE;
- q->n_type = ENUMTY;
- if (s != NULL)
- defid(q, ENAME);
- }
- r->rsym = q->n_sp;
- r->rlparam = lparam;
- nfree(q);
+ r = tmpcalloc(sizeof(struct rstack));
+ r->rsou = soru;
+ r->rsym = sp;
+ r->rb = NULL;
+ r->rsue = sue;
+ r->rnext = rpole;
+ rpole = r;
return r;
}
/*
* Called after a struct is declared to restore the environment.
+ * Alignment and packing are handled here.
+ * - If ALSTRUCT is defined, this will be the struct alignment and the
+ * struct size will be a multiple of ALSTRUCT, otherwise it will use
+ * the alignment of the largest struct member.
+ * - If suep->suealigned is set, then it will specify the alignment.
+ * - If suep->suepacked is set, it will pack all struct members.
*/
NODE *
-dclstruct(struct rstack *r)
+dclstruct(struct rstack *r, struct suedef *suep)
{
NODE *n;
- struct params *l, *m;
struct suedef *sue;
- struct symtab *p;
- int al, sa, sz;
- TWORD temp;
- int i, high, low;
+ struct symtab *sp;
+ int al, sa, sz, coff;
+ struct suedef sues;
+
+ if (suep && r->rsue) { /* merge */
+ if (suep->suealigned == 0)
+ suep->suealigned = r->rsue->suealigned;
+ if (suep->suepacked == 0)
+ suep->suepacked = r->rsue->suepacked;
+ } else if (suep == NULL)
+ suep = r->rsue;
+ if (suep == NULL)
+ suep = memset(&sues, 0, sizeof sues);
+
+ if (pragma_allpacked && !suep->suepacked)
+ suep->suepacked = pragma_allpacked;
if (r->rsym == NULL) {
sue = permalloc(sizeof(struct suedef));
+ memset(sue, 0, sizeof(struct suedef));
suedefcnt++;
- sue->suesize = 0;
- sue->suealign = ALSTRUCT;
} else
sue = r->rsym->ssue;
-#ifdef PCC_DEBUG
- if (ddebug)
- printf("dclstruct(%s)\n", r->rsym ? r->rsym->sname : "??");
-#endif
- temp = (instruct&INSTRUCT)?STRTY:((instruct&INUNION)?UNIONTY:ENUMTY);
- instruct = r->rinstruct;
- strunem = r->rclass;
+#ifdef ALSTRUCT
al = ALSTRUCT;
+#else
+ al = ALCHAR;
+#endif
- high = low = 0;
-
- if ((l = r->rlparam) == NULL)
- l = lpole;
- else
- l = l->next;
-
- /* memory for the element array must be allocated first */
- for (m = l, i = 1; m != NULL; m = m->next)
- i++;
- sue->suelem = permalloc(sizeof(struct symtab *) * i);
-
- for (i = 0; l != NULL; l = l->next) {
- sue->suelem[i++] = p = l->sym;
-
- if (p == NULL)
- cerror("gummy structure member");
- if (temp == ENUMTY) {
- if (p->soffset < low)
- low = p->soffset;
- if (p->soffset > high)
- high = p->soffset;
- p->ssue = sue;
- continue;
- }
- sa = talign(p->stype, p->ssue);
- if (p->sclass & FIELD) {
- sz = p->sclass&FLDSIZ;
- } else {
- sz = tsize(p->stype, p->sdf, p->ssue);
+ /*
+ * extract size and alignment, recalculate offsets
+ * if struct should be packed.
+ */
+ coff = 0;
+ sue->sylnk = r->rb;
+ for (sp = r->rb; sp; sp = sp->snext) {
+ sa = talign(sp->stype, sp->ssue);
+ if (sp->sclass & FIELD)
+ sz = sp->sclass&FLDSIZ;
+ else
+ sz = tsize(sp->stype, sp->sdf, sp->ssue);
+ if (suep->suepacked && r->rsou == STNAME) {
+ sp->soffset = coff;
+ coff += sz;
+ rpole->rstr = coff;
}
- if (sz > strucoff)
- strucoff = sz; /* for use with unions */
+ if (sz > rpole->rstr)
+ rpole->rstr = sz; /* for use with unions */
/*
* set al, the alignment, to the lcm of the alignments
* of the members.
*/
- SETOFF(al, sa);
+ if (suep->suepacked == 0)
+ SETOFF(al, sa);
}
- sue->suelem[i] = NULL;
- SETOFF(strucoff, al);
- if (temp == ENUMTY) {
- TWORD ty;
+ /* If alignment given is larger that calculated, expand */
+ if (suep->suealigned)
+ SETOFF(al, suep->suealigned);
-#ifdef ENUMSIZE
- ty = ENUMSIZE(high,low);
-#else
- if ((char)high == high && (char)low == low)
- ty = ctype(CHAR);
- else if ((short)high == high && (short)low == low)
- ty = ctype(SHORT);
- else
- ty = ctype(INT);
-#endif
- strucoff = tsize(ty, 0, MKSUE(ty));
- sue->suealign = al = talign(ty, MKSUE(ty));
- }
+ SETOFF(rpole->rstr, al);
- sue->suesize = strucoff;
+ sue->suesize = rpole->rstr;
sue->suealign = al;
+ sue->suealigned = suep->suealigned;
+ sue->suepacked = suep->suepacked;
+
+#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
if (gflag)
@@ -857,25 +896,77 @@
#ifdef PCC_DEBUG
if (ddebug>1) {
- int i;
-
- printf("\tsize %d align %d elem %p\n",
- sue->suesize, sue->suealign, sue->suelem);
- for (i = 0; sue->suelem[i] != NULL; ++i) {
- printf("\tmember %s(%p)\n",
- sue->suelem[i]->sname, sue->suelem[i]);
+ printf("\tsize %d align %d link %p\n",
+ sue->suesize, sue->suealign, sue->sylnk);
+ for (sp = sue->sylnk; sp != NULL; sp = sp->snext) {
+ printf("\tmember %s(%p)\n", sp->sname, sp);
}
}
#endif
- strucoff = r->rstrucoff;
- if ((lparam = r->rlparam) != NULL)
- lparam->next = NULL;
- n = mkty(temp, 0, sue);
+ rpole = r->rnext;
+ n = mkty(r->rsou == STNAME ? STRTY : UNIONTY, 0, sue);
return n;
}
/*
+ * Add a new member to the current struct or union being declared.
+ */
+void
+soumemb(NODE *n, char *name, int class)
+{
+ struct symtab *sp, *lsp;
+ int incomp;
+
+ if (rpole == NULL)
+ cerror("soumemb");
+
+ /* check if tag name exists */
+ lsp = NULL;
+ for (sp = rpole->rb; sp != NULL; lsp = sp, sp = sp->snext)
+ if (*name != '*' && sp->sname == name)
+ uerror("redeclaration of %s", name);
+
+ sp = getsymtab(name, SMOSNAME);
+ if (rpole->rb == NULL)
+ rpole->rb = sp;
+ 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 (rpole->rsou == STNAME && 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
*/
void yyerror(char *s);
@@ -900,74 +991,44 @@
ftnarg(NODE *p)
{
NODE *q;
- struct symtab *s;
#ifdef PCC_DEBUG
if (ddebug > 2)
printf("ftnarg(%p)\n", p);
#endif
/*
- * Enter argument onto param stack.
- * Do not declare parameters until later (in dclargs);
- * the function must be declared first.
- * put it on the param stack in reverse order, due to the
- * nature of the stack it will be reclaimed correct.
+ * Push argument symtab entries onto param stack in reverse order,
+ * due to the nature of the stack it will be reclaimed correct.
*/
for (; p->n_op != NAME; p = p->n_left) {
- if (p->n_op == (UCALL) && p->n_left->n_op == NAME)
+ if (p->n_op == UCALL && p->n_left->n_op == NAME)
return; /* Nothing to enter */
if (p->n_op == CALL && p->n_left->n_op == NAME)
break;
}
p = p->n_right;
- blevel = 1;
-
while (p->n_op == CM) {
q = p->n_right;
if (q->n_op != ELLIPSIS) {
- s = lookup((char *)q->n_sp, 0);
- if (s->stype != UNDEF) {
- if (s->slevel > 0)
- uerror("parameter '%s' redefined",
- s->sname);
- s = hide(s);
- }
- s->soffset = NOOFFSET;
- s->sclass = PARAM;
- s->stype = q->n_type;
- s->sdf = q->n_df;
- s->ssue = q->n_sue;
- ssave(s);
+ ssave(q->n_sp);
nparams++;
#ifdef PCC_DEBUG
if (ddebug > 2)
printf(" saving sym %s (%p) from (%p)\n",
- s->sname, s, q);
+ q->n_sp->sname, q->n_sp, q);
#endif
}
p = p->n_left;
}
- s = lookup((char *)p->n_sp, 0);
- if (s->stype != UNDEF) {
- if (s->slevel > 0)
- uerror("parameter '%s' redefined", s->sname);
- s = hide(s);
- }
- s->soffset = NOOFFSET;
- s->sclass = PARAM;
- s->stype = p->n_type;
- s->sdf = p->n_df;
- s->ssue = p->n_sue;
- ssave(s);
+ ssave(p->n_sp);
if (p->n_type != VOID)
nparams++;
- blevel = 0;
#ifdef PCC_DEBUG
if (ddebug > 2)
printf(" saving sym %s (%p) from (%p)\n",
- s->sname, s, p);
+ nparams ? p->n_sp->sname : "<noname>", p->n_sp, p);
#endif
}
@@ -1001,35 +1062,9 @@
}
}
- switch( BTYPE(ty) ){
-
- case UNIONTY:
- case ENUMTY:
- case STRTY:
- return((unsigned int)sue->suealign);
- case BOOL:
- return (ALBOOL);
- case CHAR:
- case UCHAR:
- return (ALCHAR);
- case FLOAT:
- return (ALFLOAT);
- case LDOUBLE:
- return (ALLDOUBLE);
- case DOUBLE:
- return (ALDOUBLE);
- case LONGLONG:
- case ULONGLONG:
- return (ALLONGLONG);
- case LONG:
- case ULONG:
- return (ALLONG);
- case SHORT:
- case USHORT:
- return (ALSHORT);
- default:
- return (ALINT);
- }
+ if (sue->suealign == 0)
+ uerror("no alignment");
+ return sue->suealign;
}
/* compute the size associated with type ty,
@@ -1052,6 +1087,8 @@
case PTR:
return( SZPOINT(ty) * mult );
case ARY:
+ if (d->ddim == NOOFFSET)
+ return 0;
mult *= d->ddim;
d++;
continue;
@@ -1074,7 +1111,7 @@
return(SZINT);
}
} else {
- if (sue->suelem == NULL)
+ if (sue->suealign == 0)
uerror("unknown structure/union/enum");
}
@@ -1082,146 +1119,59 @@
}
/*
- * Write last part of wide string.
- * Do not bother to save wide strings.
+ * Save string (and print it out). If wide then wide string.
*/
NODE *
-wstrend(char *str)
+strend(int wide, char *str)
{
- struct symtab *sp = getsymtab(str, SSTRING|STEMP);
- struct strsched *sc = tmpalloc(sizeof(struct strsched));
- NODE *p = block(NAME, NIL, NIL, WCHAR_TYPE+ARY,
- tmpalloc(sizeof(union dimfun)), MKSUE(WCHAR_TYPE));
- int i;
- char *c;
-
- sp->sclass = ILABEL;
- sp->soffset = getlab();
- sp->stype = WCHAR_TYPE+ARY;
-
- sc = tmpalloc(sizeof(struct strsched));
- sc->locctr = STRNG;
- sc->sym = sp;
- sc->next = strpole;
- strpole = sc;
-
- /* length calculation, used only for sizeof */
- for (i = 0, c = str; *c; ) {
- if (*c++ == '\\')
- (void)esccon(&c);
- i++;
- }
- p->n_df->ddim = (i+1) * ((MKSUE(WCHAR_TYPE))->suesize/SZCHAR);
- p->n_sp = sp;
- return(p);
-}
-
-/*
- * Write last part of string.
- */
-NODE *
-strend(char *str)
-{
-// extern int maystr;
- struct symtab *s;
+ struct symtab *sp;
NODE *p;
- int i;
- char *c;
/* If an identical string is already emitted, just forget this one */
- str = addstring(str); /* enter string in string table */
- s = lookup(str, SSTRING); /* check for existance */
-
- if (s->soffset == 0 /* && maystr == 0 */) { /* No string */
- struct strsched *sc;
- s->sclass = ILABEL;
-
- /*
- * Delay printout of this string until after the current
- * function, or the end of the statement.
- */
- sc = tmpalloc(sizeof(struct strsched));
- sc->locctr = STRNG;
- sc->sym = s;
- sc->next = strpole;
- strpole = sc;
- s->soffset = getlab();
+ if (wide) {
+ /* Do not save wide strings, at least not now */
+ sp = getsymtab(str, SSTRING|STEMP);
+ } else {
+ str = addstring(str); /* enter string in string table */
+ sp = lookup(str, SSTRING); /* check for existance */
}
- p = block(NAME, NIL, NIL, CHAR+ARY,
- tmpalloc(sizeof(union dimfun)), MKSUE(CHAR));
-#ifdef CHAR_UNSIGNED
- p->n_type = UCHAR+ARY;
-#endif
- /* length calculation, used only for sizeof */
- for (i = 0, c = str; *c; ) {
- if (*c++ == '\\')
- (void)esccon(&c);
- i++;
- }
- p->n_df->ddim = i+1;
- p->n_sp = s;
- return(p);
-}
+ if (sp->soffset == 0) { /* No string */
+ char *wr;
+ int i;
-/*
- * Print out new strings, before temp memory is cleared.
- */
-void
-strprint()
-{
- char *wr;
- int i, val, isw;
- NODE *p = bcon(0);
-
- while (strpole != NULL) {
- setloc1(STRNG);
- deflab1(strpole->sym->soffset);
- isw = strpole->sym->stype == WCHAR_TYPE+ARY;
-
- i = 0;
- wr = strpole->sym->sname;
- while (*wr != 0) {
- if (*wr++ == '\\')
- val = esccon(&wr);
- else
- val = (unsigned char)wr[-1];
- if (isw) {
- p->n_lval = val;
- p->n_type = WCHAR_TYPE;
- ninval(i*(WCHAR_TYPE/SZCHAR),
- (MKSUE(WCHAR_TYPE))->suesize, p);
- } else
- bycode(val, i);
- i++;
- }
- if (isw) {
- p->n_lval = 0;
- ninval(i*(WCHAR_TYPE/SZCHAR),
- (MKSUE(WCHAR_TYPE))->suesize, p);
+ sp->sclass = STATIC;
+ sp->slevel = 1;
+ sp->soffset = getlab();
+ sp->squal = (CON >> TSHIFT);
+ sp->sdf = permalloc(sizeof(union dimfun));
+ if (wide) {
+ sp->stype = WCHAR_TYPE+ARY;
+ sp->ssue = MKSUE(WCHAR_TYPE);
} else {
- bycode(0, i++);
- bycode(-1, i);
+ if (funsigned_char) {
+ sp->stype = UCHAR+ARY;
+ sp->ssue = MKSUE(UCHAR);
+ } else {
+ sp->stype = CHAR+ARY;
+ sp->ssue = MKSUE(CHAR);
+ }
}
- strpole = strpole->next;
+ for (wr = sp->sname, i = 1; *wr; i++)
+ if (*wr++ == '\\')
+ (void)esccon(&wr);
+
+ sp->sdf->ddim = i;
+ if (wide)
+ inwstring(sp);
+ else
+ instring(sp);
}
- nfree(p);
-}
-#if 0
-/*
- * simulate byte v appearing in a list of integer values
- */
-void
-putbyte(int v)
-{
- NODE *p;
- p = bcon(v);
- incode( p, SZCHAR );
- tfree( p );
-// gotscal();
+ p = block(NAME, NIL, NIL, sp->stype, sp->sdf, sp->ssue);
+ p->n_sp = sp;
+ return(clocal(p));
}
-#endif
/*
* update the offset pointed to by poff; return the
@@ -1253,14 +1203,13 @@
/*
* 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 = tn->n_lval;
+ p->soffset = regno(tn);
p->sflags |= STNODE;
nfree(tn);
return 0;
@@ -1279,7 +1228,7 @@
} else
#endif
if (p->sclass == PARAM && (p->stype == CHAR || p->stype == UCHAR ||
- p->stype == SHORT || p->stype == USHORT)) {
+ p->stype == SHORT || p->stype == USHORT || p->stype == BOOL)) {
off = upoff(SZINT, ALINT, &noff);
#ifndef RTOLBYTES
off = noff - tsz;
@@ -1301,7 +1250,24 @@
}
/*
- * Allocate space on the stack for dynamic arrays.
+ * Delay emission of code generated in argument headers.
+ */
+static void
+edelay(NODE *p)
+{
+ if (blevel == 1) {
+ /* Delay until after declarations */
+ if (parlink == NULL)
+ parlink = p;
+ else
+ parlink = block(COMOP, parlink, p, 0, 0, 0);
+ } else
+ ecomp(p);
+}
+
+/*
+ * Allocate space on the stack for dynamic arrays (or at least keep track
+ * of the index).
* Strategy is as follows:
* - first entry is a pointer to the dynamic datatype.
* - if it's a one-dimensional array this will be the only entry used.
@@ -1316,41 +1282,68 @@
union dimfun *df;
NODE *n, *nn, *tn, *pol;
TWORD t;
- int i, no;
+ int astkp, no;
/*
- * The pointer to the array is stored in a TEMP node, which number
- * is in the soffset field;
+ * The pointer to the array is not necessarily stored in a
+ * TEMP node, but if it is, its number is in the soffset field;
*/
t = p->stype;
- p->sflags |= (STNODE|SDYNARRAY);
- p->stype = INCREF(p->stype); /* Make this an indirect pointer */
- tn = tempnode(0, p->stype, p->sdf, p->ssue);
- p->soffset = tn->n_lval;
+ astkp = 0;
+ if (ISARY(t) && blevel == 1) {
+ /* must take care of side effects of dynamic arg arrays */
+ if (p->sdf->ddim < 0 && p->sdf->ddim != NOOFFSET) {
+ /* first-level array will be indexed correct */
+ edelay(arrstk[astkp++]);
+ }
+ p->sdf++;
+ p->stype += (PTR-ARY);
+ t = p->stype;
+ }
+ if (ISARY(t)) {
+ p->sflags |= (STNODE|SDYNARRAY);
+ p->stype = INCREF(p->stype); /* Make this an indirect pointer */
+ tn = tempnode(0, p->stype, p->sdf, p->ssue);
+ p->soffset = regno(tn);
+ } else {
+ oalloc(p, poff);
+ tn = NIL;
+ }
df = p->sdf;
pol = NIL;
- for (i = 0; ISARY(t); t = DECREF(t), df++) {
- if (df->ddim >= 0)
+ for (; t > BTMASK; t = DECREF(t)) {
+ if (!ISARY(t))
continue;
- n = arrstk[i++];
- nn = tempnode(0, INT, 0, MKSUE(INT));
- no = nn->n_lval;
- ecomp(buildtree(ASSIGN, nn, n)); /* Save size */
+ if (df->ddim < 0) {
+ n = arrstk[astkp++];
+ do {
+ nn = tempnode(0, INT, 0, MKSUE(INT));
+ no = regno(nn);
+ } while (no == -NOOFFSET);
+ edelay(buildtree(ASSIGN, nn, n));
- df->ddim = -no;
- n = tempnode(no, INT, 0, MKSUE(INT));
- if (pol == NIL)
- pol = n;
- else
- pol = buildtree(MUL, pol, n);
+ df->ddim = -no;
+ n = tempnode(no, INT, 0, MKSUE(INT));
+ } else
+ n = bcon(df->ddim);
+
+ pol = (pol == NIL ? n : buildtree(MUL, pol, n));
+ df++;
}
/* Create stack gap */
- if (pol == NIL)
- uerror("aggregate dynamic array not allowed");
- else
- spalloc(tn, pol, tsize(t, 0, p->ssue));
+ if (blevel == 1) {
+ if (tn)
+ tfree(tn);
+ if (pol)
+ tfree(pol);
+ } else {
+ if (pol == NIL)
+ uerror("aggregate dynamic array not allowed");
+ if (tn)
+ spalloc(tn, pol, tsize(t, 0, p->ssue));
+ }
arrstkp = 0;
}
@@ -1368,14 +1361,6 @@
/* this must be fixed to use the current type in alignments */
switch( new<0?pty->n_type:p->stype ){
- case ENUMTY: {
- struct suedef *sue;
- sue = new < 0 ? pty->n_sue : p->ssue;
- al = sue->suealign;
- sz = sue->suesize;
- break;
- }
-
case CHAR:
case UCHAR:
al = ALCHAR;
@@ -1409,24 +1394,24 @@
}
if( w == 0 ){ /* align only */
- SETOFF( strucoff, al );
+ SETOFF( rpole->rstr, al );
if( new >= 0 ) uerror( "zero size field");
return(0);
}
- if( strucoff%al + w > sz ) SETOFF( strucoff, al );
+ if( rpole->rstr%al + w > sz ) SETOFF( rpole->rstr, al );
if( new < 0 ) {
- strucoff += w; /* we know it will fit */
+ rpole->rstr += w; /* we know it will fit */
return(0);
}
/* establish the field */
if( new == 1 ) { /* previous definition */
- if( p->soffset != strucoff || p->sclass != (FIELD|w) ) return(1);
+ if( p->soffset != rpole->rstr || p->sclass != (FIELD|w) ) return(1);
}
- p->soffset = strucoff;
- strucoff += w;
+ p->soffset = rpole->rstr;
+ rpole->rstr += w;
p->stype = type;
fldty( p );
return(0);
@@ -1448,7 +1433,7 @@
if (class == SNULL) {
if (blevel > 1)
class = AUTO;
- else if (blevel != 0 || instruct)
+ else if (blevel != 0 || rpole)
cerror( "nidcl error" );
else /* blevel = 0 */
commflag = 1, class = EXTERN;
@@ -1458,7 +1443,7 @@
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)
@@ -1479,7 +1464,7 @@
if (blevel == 0)
lcommadd(p->n_sp);
else
- lcommdec(p->n_sp);
+ defzero(p->n_sp);
break;
}
}
@@ -1539,173 +1524,161 @@
struct lcd *lc;
SLIST_FOREACH(lc, &lhead, next) {
- if (lc->sp != NULL) {
- if (lc->sp->sclass == STATIC)
- lcommdec(lc->sp);
- else
- commdec(lc->sp);
- }
+ if (lc->sp != NULL)
+ defzero(lc->sp);
}
}
/*
- * Merges a type tree into one type. Returns one type node with merged types
- * and class stored in the su field. Frees all other nodes.
- * XXX - classes in typedefs?
+ * Merge given types to a single node.
+ * Any type can end up here.
+ * p is the old node, q is the old (if any).
+ * CLASS is AUTO, EXTERN, REGISTER, STATIC or TYPEDEF.
+ * QUALIFIER is VOL or CON
+ * TYPE is CHAR, SHORT, INT, LONG, SIGNED, UNSIGNED, VOID, BOOL, FLOAT,
+ * DOUBLE, STRTY, UNIONTY.
*/
NODE *
typenode(NODE *p)
{
- NODE *l, *sp = NULL;
- int class = 0, adj, noun, sign;
- TWORD qual = 0;
-
- adj = INT; /* INT, LONG or SHORT */
- noun = UNDEF; /* INT, CHAR or FLOAT */
- sign = 0; /* 0, SIGNED or UNSIGNED */
-
- /* Remove initial QUALIFIERs */
- if (p && p->n_op == QUALIFIER) {
- qual = p->n_type;
- l = p->n_left;
- nfree(p);
- p = l;
- }
-
- /* Handle initial classes special */
- if (p && p->n_op == CLASS) {
- class = p->n_type;
- l = p->n_left;
- nfree(p);
- p = l;
- }
-
- /* Remove more QUALIFIERs */
- if (p && p->n_op == QUALIFIER) {
- qual |= p->n_type;
- l = p->n_left;
- nfree(p);
- p = l;
- }
-
-ag: if (p && p->n_op == TYPE) {
- if (p->n_left == NIL) {
-#ifdef CHAR_UNSIGNED
- if (p->n_type == CHAR)
- p->n_type = UCHAR;
-#endif
- if (p->n_type == SIGNED)
- p->n_type = INT;
-uni: p->n_lval = class;
- p->n_qual = qual >> TSHIFT;
- return p;
- } else if (p->n_left->n_op == QUALIFIER) {
- qual |= p->n_left->n_type;
- l = p->n_left;
- p->n_left = l->n_left;
- nfree(l);
- goto ag;
- } else if (ISSTR(p->n_type)) {
- /* Save node; needed for return */
- sp = p;
- p = p->n_left;
- }
- }
-
- while (p != NIL) {
- if (p->n_op == QUALIFIER) {
- qual |= p->n_type;
- goto next;
- }
- if (p->n_op == CLASS) {
- if (class != 0)
- uerror("too many storage classes");
+ NODE *q, *saved;
+ TWORD type;
+ int class, qual;
+ int sig, uns, cmplx;
+
+ cmplx = type = class = qual = sig = uns = 0;
+ saved = NIL;
+
+ for (q = p; p; p = p->n_left) {
+ switch (p->n_op) {
+ case CLASS:
+ if (class)
+ goto bad; /* max 1 class */
class = p->n_type;
- goto next;
- }
- if (p->n_op != TYPE)
- cerror("typenode got notype %d", p->n_op);
- switch (p->n_type) {
- case UCHAR:
- case USHORT: /* may come from typedef */
- if (sign != 0 || adj != INT)
- goto bad;
- noun = p->n_type;
break;
- case SIGNED:
- case UNSIGNED:
- if (sign != 0)
- goto bad;
- sign = p->n_type;
+
+ case QUALIFIER:
+ qual |= p->n_type >> TSHIFT;
break;
- case LONG:
- if (adj == LONG) {
- adj = LONGLONG;
+
+ case TYPE:
+ if (p->n_sp != NULL || ISSOU(p->n_type)) {
+ /* typedef, enum or struct/union */
+ if (saved || type)
+ goto bad;
+ saved = p;
break;
- }
- /* FALLTHROUGH */
- case SHORT:
- if (adj != INT)
+ } else if ((p->n_type == SIGNED && uns) ||
+ (p->n_type == UNSIGNED && sig))
goto bad;
- adj = p->n_type;
- break;
- case INT:
- case CHAR:
+
+ switch (p->n_type) {
+ case BOOL:
+ case CHAR:
+ case FLOAT:
+ case VOID:
+ if (type)
+ goto bad;
+ type = p->n_type;
+ break;
+ case DOUBLE:
+ if (type == 0)
+ type = DOUBLE;
+ else if (type == LONG)
+ type = LDOUBLE;
+ else
+ goto bad;
+ break;
+ case SHORT:
+ if (type == 0 || type == INT)
+ type = SHORT;
+ else
+ goto bad;
+ break;
+ case INT:
+ if (type == SHORT || type == LONG ||
+ type == LONGLONG)
+ break;
+ else if (type == 0)
+ type = INT;
+ else
+ goto bad;
+ break;
+ case LONG:
+ if (type == 0)
+ type = LONG;
+ else if (type == INT)
+ break;
+ else if (type == LONG)
+ type = LONGLONG;
+ else if (type == DOUBLE)
+ type = LDOUBLE;
+ else
+ goto bad;
+ break;
+ case SIGNED:
+ if (sig || uns)
+ goto bad;
+ sig = 1;
+ break;
+ case UNSIGNED:
+ if (sig || uns)
+ goto bad;
+ uns = 1;
+ break;
+ case COMPLEX:
+ cmplx = 1;
+ break;
+ default:
+ cerror("typenode");
+ }
+ }
+ }
+ if (cmplx) {
+ if (sig || uns)
+ goto bad;
+ switch (type) {
case FLOAT:
- case DOUBLE:
- if (noun != UNDEF)
- goto bad;
- noun = p->n_type;
+ type = FCOMPLEX;
break;
- case VOID:
- if (noun != UNDEF || adj != INT)
- goto bad;
- adj = noun = VOID;
+ case DOUBLE:
+ type = COMPLEX;
break;
- case STRTY:
- case UNIONTY:
+ case LDOUBLE:
+ type = LCOMPLEX;
break;
default:
goto bad;
}
- next:
- l = p->n_left;
- nfree(p);
- p = l;
}
- if (sp) {
- p = sp;
- goto uni;
+ if (saved && type)
+ goto bad;
+ if (sig || uns) {
+ if (type == 0)
+ type = sig ? INT : UNSIGNED;
+ if (type > ULONGLONG)
+ goto bad;
+ if (uns)
+ type = ENUNSIGN(type);
}
-#ifdef CHAR_UNSIGNED
- if (noun == CHAR && sign == 0)
- sign = UNSIGNED;
-#endif
- if (noun == UNDEF) {
- noun = INT;
- } else if (noun == FLOAT) {
- if (sign != 0 || adj == SHORT)
- goto bad;
- noun = (adj == LONG ? DOUBLE : FLOAT);
- } else if (noun == DOUBLE) {
- if (sign != 0 || adj == SHORT)
- goto bad;
- noun = (adj == LONG ? LDOUBLE : DOUBLE);
- } else if (noun == CHAR && adj != INT)
- goto bad;
+ if (funsigned_char && type == CHAR && sig == 0)
+ type = UCHAR;
+
+ /* free the chain */
+ while (q) {
+ p = q->n_left;
+ if (q != saved)
+ nfree(q);
+ q = p;
+ }
- if (adj != INT && (noun != DOUBLE && noun != LDOUBLE))
- noun = adj;
- if (sign == UNSIGNED)
- noun += (UNSIGNED-INT);
-
- p = block(TYPE, NIL, NIL, noun, 0, 0);
- p->n_qual = qual >> TSHIFT;
- if (strunem != 0)
- class = strunem;
+ p = (saved ? saved : block(TYPE, NIL, NIL, type, 0, 0));
+ p->n_qual = qual;
p->n_lval = class;
+ if (BTYPE(p->n_type) == UNDEF)
+ MODTYPE(p->n_type, INT);
return p;
bad: uerror("illegal type combination");
@@ -1729,13 +1702,18 @@
(*ntdim)++;
}
-/* merge type typ with identifier idp */
+/*
+ * merge type typ with identifier idp.
+ * idp is returned as a NAME node with correct types.
+ * typ is untouched.
+ */
NODE *
tymerge(NODE *typ, NODE *idp)
{
NODE *p;
union dimfun *j;
struct tylnk *base, tylnk, *tylkp;
+ struct suedef *sue;
unsigned int t;
int ntdim, i;
@@ -1750,8 +1728,10 @@
}
#endif
+ sue = idp->n_sue;
+
idp->n_type = typ->n_type;
- idp->n_qual = (typ->n_qual << TSHIFT) | idp->n_qual; /* XXX ??? */
+ idp->n_qual |= typ->n_qual;
tylkp = &tylnk;
tylkp->next = NULL;
@@ -1776,12 +1756,29 @@
/* now idp is a single node: fix up type */
idp->n_type = ctype(idp->n_type);
- idp->n_qual = DECQAL(idp->n_qual);
/* in case ctype has rewritten things */
if ((t = BTYPE(idp->n_type)) != STRTY && t != UNIONTY && t != ENUMTY)
idp->n_sue = MKSUE(t);
+#if 1
+ if (sue) {
+ struct suedef *s = permalloc(sizeof(struct suedef));
+ *s = *idp->n_sue;
+ idp->n_sue = s;
+ if (sue->suealigned > s->suealign)
+ s->suealign = sue->suealigned;
+ s->suepacked = sue->suepacked;
+ s->suesection = sue->suesection;
+ }
+#else
+ if (sue) {
+ if (sue->suealigned > idp->n_sue->suealign)
+ idp->n_sue->suealign = sue->suealigned;
+ idp->n_sue->suepacked = sue->suepacked;
+ }
+#endif
+
if (idp->n_op != NAME) {
for (p = idp->n_left; p->n_op != NAME; p = p->n_left)
nfree(p);
@@ -1818,8 +1815,7 @@
if (w->n_right->n_op == ELLIPSIS)
continue;
ty = w->n_right->n_type;
- if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY ||
- BTYPE(ty) == ENUMTY)
+ if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY)
num++;
while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
ty = DECREF(ty);
@@ -1828,8 +1824,7 @@
}
cnt++;
ty = w->n_type;
- if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY ||
- BTYPE(ty) == ENUMTY)
+ if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY)
num++;
while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
ty = DECREF(ty);
@@ -1863,8 +1858,7 @@
ap[j]->n_type = INCREF(ap[j]->n_type);
ty = ap[j]->n_type;
al[k++].type = ty;
- if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY ||
- BTYPE(ty) == ENUMTY)
+ if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY)
al[k++].sue = ap[j]->n_sue;
while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
ty = DECREF(ty);
@@ -1875,8 +1869,10 @@
if (k > num)
cerror("arglist: k%d > num%d", k, num);
tfree(n);
+#ifdef PCC_DEBUG
if (pdebug)
alprint(al, 0);
+#endif
return al;
}
@@ -1894,8 +1890,10 @@
TWORD t, q;
o = p->n_op;
- if (o == NAME)
+ if (o == NAME) {
+ p->n_qual = DECQAL(p->n_qual);
return;
+ }
t = INCREF(p->n_type);
q = p->n_qual;
@@ -1918,7 +1916,7 @@
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
}
@@ -1975,25 +1973,153 @@
if (xnobuiltins)
return NULL;
#endif
-
- if (f->n_op != NAME)
- return NULL; /* not direct call */
sp = f->n_sp;
- /* XXX - strcmp is bad, use pointer comparision, redo someday */
- if (strcmp(sp->sname, "__builtin_alloca")) /* use GCC name */
- return NULL; /* not alloca */
-
if (a == NULL || a->n_op == CM) {
uerror("wrong arg count for alloca");
- return NULL;
+ return bcon(0);
}
t = tempnode(0, VOID|PTR, 0, MKSUE(INT) /* XXX */);
- u = tempnode(t->n_lval, VOID|PTR, 0, MKSUE(INT) /* XXX */);
+ u = tempnode(regno(t), VOID|PTR, 0, MKSUE(INT) /* XXX */);
spalloc(t, a, SZCHAR);
tfree(f);
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 *p, *q;
+ int sz;
+
+ /* check num args and type */
+ if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
+ !ISPTR(a->n_left->n_type))
+ goto bad;
+
+ /* must first deal with argument size; use int size */
+ p = a->n_right;
+ if (p->n_type < INT) {
+ sz = SZINT/tsize(p->n_type, p->n_df, p->n_sue);
+ } else
+ sz = 1;
+
+ /* do the real job */
+ p = buildtree(ADDROF, p, NIL); /* address of last arg */
+#ifdef BACKAUTO
+ p = optim(buildtree(PLUS, p, bcon(sz))); /* add one to it (next arg) */
+#else
+ p = optim(buildtree(MINUS, p, bcon(sz))); /* add one to it (next arg) */
+#endif
+ q = block(NAME, NIL, NIL, PTR+VOID, 0, 0); /* create cast node */
+ q = buildtree(CAST, q, p); /* cast to void * (for assignment) */
+ p = q->n_right;
+ nfree(q->n_left);
+ nfree(q);
+ p = buildtree(ASSIGN, a->n_left, p); /* assign to ap */
+ tfree(f);
+ nfree(a);
+ return p;
+bad:
+ uerror("bad argument to __builtin_stdarg_start");
+ return bcon(0);
+}
+
+static NODE *
+builtin_va_arg(NODE *f, NODE *a)
+{
+ NODE *p, *q, *r, *rv;
+ int sz, nodnum;
+
+ /* check num args and type */
+ if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
+ !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE)
+ goto bad;
+
+ /* create a copy to a temp node of current ap */
+ p = tcopy(a->n_left);
+ q = tempnode(0, p->n_type, p->n_df, p->n_sue);
+ nodnum = regno(q);
+ rv = buildtree(ASSIGN, q, p);
+
+ r = a->n_right;
+ sz = tsize(r->n_type, r->n_df, r->n_sue)/SZCHAR;
+ /* add one to ap */
+#ifdef BACKAUTO
+ rv = buildtree(COMOP, rv , buildtree(PLUSEQ, a->n_left, bcon(sz)));
+#else
+#error fix wrong eval order in builtin_va_arg
+ ecomp(buildtree(MINUSEQ, a->n_left, bcon(sz)));
+#endif
+
+ nfree(a->n_right);
+ nfree(a);
+ nfree(f);
+ r = tempnode(nodnum, INCREF(r->n_type), r->n_df, r->n_sue);
+ return buildtree(COMOP, rv, buildtree(UMUL, r, NIL));
+bad:
+ uerror("bad argument to __builtin_va_arg");
+ return bcon(0);
+
+}
+
+static NODE *
+builtin_va_end(NODE *f, NODE *a)
+{
+ tfree(f);
+ tfree(a);
+ return bcon(0); /* nothing */
+}
+
+static NODE *
+builtin_va_copy(NODE *f, NODE *a)
+{
+ if (a == NULL || a->n_op != CM || a->n_left->n_op == CM)
+ goto bad;
+ tfree(f);
+ f = buildtree(ASSIGN, a->n_left, a->n_right);
+ nfree(a);
+ return f;
+
+bad:
+ uerror("bad argument to __builtin_va_copy");
+ return bcon(0);
+}
+#endif /* TARGET_STDARGS */
+
+static struct bitable {
+ char *name;
+ 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 },
+ { "__builtin_va_end", builtin_va_end },
+ { "__builtin_va_copy", builtin_va_copy },
+#endif
+#ifdef TARGET_BUILTINS
+ TARGET_BUILTINS
+#endif
+};
#endif
#ifdef PCC_DEBUG
@@ -2010,16 +2136,18 @@
printf(" ");
printf("arg %d: ", i++);
tprint(stdout, al->type, 0);
- if (BTYPE(al->type) == STRTY ||
- BTYPE(al->type) == UNIONTY || BTYPE(al->type) == ENUMTY) {
+ if (ISARY(al->type)) {
+ printf(" dim %d\n", al->df->ddim);
+ } else if (BTYPE(al->type) == STRTY ||
+ BTYPE(al->type) == UNIONTY) {
al++;
- printf("dim %d\n", al->df->ddim);
- }
- printf("\n");
- if (ISFTN(DECREF(al->type))) {
+ printf(" (size %d align %d)", al->sue->suesize,
+ al->sue->suealign);
+ } else if (ISFTN(DECREF(al->type))) {
al++;
alprint(al->df->dfun, in+1);
}
+ printf("\n");
}
if (in == 0)
printf("end arglist\n");
@@ -2031,7 +2159,7 @@
* Returns a merged node (via buildtree() of function and arguments.
*/
NODE *
-doacall(NODE *f, NODE *a)
+doacall(struct symtab *sp, NODE *f, NODE *a)
{
NODE *w, *r;
union arglist *al;
@@ -2054,7 +2182,7 @@
/* First let MD code do something */
calldec(f, a);
/* XXX XXX hack */
- if ((f->n_op == CALL || f->n_op == CALL) &&
+ if ((f->n_op == CALL) &&
f->n_left->n_op == ADDROF &&
f->n_left->n_left->n_op == NAME &&
(f->n_left->n_left->n_type & 0x7e0) == 0x4c0)
@@ -2062,30 +2190,54 @@
/* XXX XXX hack */
#ifndef NO_C_BUILTINS
- /* check for alloca */
- if ((w = builtin_alloca(f, a)))
- return w;
+ /* check for builtins. function pointers are not allowed */
+ if (f->n_op == NAME &&
+ f->n_sp->sname[0] == '_' && f->n_sp->sname[1] == '_') {
+ int 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);
+ }
+ }
#endif
+
+ /* Check for undefined or late defined enums */
+ if (BTYPE(f->n_type) == ENUMTY) {
+ /* not-yet check if declared enum */
+ if (f->n_sue->sylnk->stype != ENUMTY)
+ MODTYPE(f->n_type, f->n_sue->sylnk->stype);
+ if (BTYPE(f->n_type) == ENUMTY)
+ uerror("enum %s not declared", f->n_sue->sylnk->sname);
+ }
+
/*
* Do some basic checks.
*/
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)
goto build;
for (w = a; w->n_op == CM; w = w->n_left) {
+ if (w->n_right->n_op == TYPE)
+ uerror("type is not an argument");
if (w->n_right->n_type != FLOAT)
continue;
w->n_right = argcast(w->n_right, DOUBLE,
NULL, MKSUE(DOUBLE));
}
+ if (a->n_op == TYPE)
+ uerror("type is not an argument");
if (a->n_type == FLOAT) {
MKTY(a, DOUBLE, 0, 0);
}
@@ -2103,7 +2255,7 @@
}
#ifdef PCC_DEBUG
if (pdebug) {
- printf("arglist for %p\n",
+ printf("arglist for %s\n",
f->n_sp != NULL ? f->n_sp->sname : "function pointer");
alprint(al, 0);
}
@@ -2149,8 +2301,19 @@
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) {
@@ -2162,12 +2325,17 @@
MKTY(apole->node, arrt, 0, 0)
}
} else if (ISSOU(BTYPE(type))) {
- if (apole->node->n_sue != al[1].sue)
+ if (apole->node->n_sue->sylnk != al[1].sue->sylnk)
goto incomp;
}
goto out;
}
+ /* XXX should (recusively) check return type and arg list of
+ func ptr arg XXX */
+ if (ISFTN(DECREF(arrt)) && ISFTN(type))
+ type = INCREF(type);
+
/* Hereafter its only pointers (or arrays) left */
/* Check for struct/union intermixing with other types */
if (((type <= BTMASK) && ISSOU(BTYPE(type))) ||
@@ -2177,14 +2345,11 @@
/* Check for struct/union compatibility */
if (type == arrt) {
if (ISSOU(BTYPE(type))) {
- if (apole->node->n_sue == al[1].sue)
+ if (apole->node->n_sue->sylnk == al[1].sue->sylnk)
goto out;
} else
goto out;
}
- if (BTYPE(arrt) == ENUMTY && BTYPE(type) == INT &&
- (arrt & ~BTMASK) == (type & ~BTMASK))
- goto skip; /* XXX enumty destroyed in optim() */
if (BTYPE(arrt) == VOID && type > BTMASK)
goto skip; /* void *f = some pointer */
if (arrt > BTMASK && BTYPE(type) == VOID)
@@ -2193,9 +2358,9 @@
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;
}
@@ -2231,7 +2396,9 @@
if (apole != NULL)
uerror("too many arguments to function");
-build: return buildtree(a == NIL ? UCALL : CALL, f, a);
+build: if (sp != NULL && (sp->sflags & SINLINE) && (w = inlinetree(sp, f, a)))
+ return w;
+ return buildtree(a == NIL ? UCALL : CALL, f, a);
}
static int
@@ -2241,9 +2408,9 @@
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;
@@ -2303,7 +2470,7 @@
t2 = usym->type;
if (ISSTR(ty)) {
usym++, udef++;
- if (usym->sue != udef->sue)
+ if (usym->sue->sylnk != udef->sue->sylnk)
return 1;
}
@@ -2345,7 +2512,7 @@
}
/* detect function arguments, watching out for structure declarations */
- if (instruct && ISFTN(type)) {
+ if (rpole && ISFTN(type)) {
uerror("function illegal in structure or union");
type = INCREF(type);
}
@@ -2371,12 +2538,14 @@
int
fixclass(int class, TWORD type)
{
+ extern int fun_inline;
+
/* first, fix null class */
if (class == SNULL) {
- if (instruct&INSTRUCT)
- class = MOS;
- else if (instruct&INUNION)
- class = MOU;
+ if (fun_inline && ISFTN(type))
+ return SNULL;
+ if (rpole)
+ class = rpole->rsou == STNAME ? MOS : MOU;
else if (blevel == 0)
class = EXTDEF;
else
@@ -2402,28 +2571,23 @@
}
}
- if( class&FIELD ){
- if( !(instruct&INSTRUCT) ) uerror( "illegal use of field" );
- return( class );
- }
-
- switch( class ){
+ if (class & FIELD) {
+ if (rpole && rpole->rsou != STNAME && rpole->rsou != UNAME)
+ uerror("illegal use of field");
+ return(class);
+ }
- case MOU:
- if( !(instruct&INUNION) ) uerror( "illegal MOU class" );
- return( class );
+ switch (class) {
case MOS:
- if( !(instruct&INSTRUCT) ) uerror( "illegal MOS class" );
- return( class );
-
- case MOE:
- if( instruct & (INSTRUCT|INUNION) ) uerror( "illegal MOE class" );
- return( class );
+ case MOU:
+ if (rpole == NULL)
+ uerror("illegal member class");
+ return(class);
case REGISTER:
if (blevel == 0)
- uerror( "illegal register declaration" );
+ uerror("illegal register declaration");
if (blevel == 1)
return(PARAM);
else
@@ -2445,14 +2609,12 @@
uerror( "fortran function has wrong type" );
}
}
- case STNAME:
- case UNAME:
- case ENAME:
case EXTERN:
case STATIC:
case EXTDEF:
case TYPEDEF:
case USTATIC:
+ case PARAM:
return( class );
default:
@@ -2504,7 +2666,7 @@
s = permalloc(sizeof(struct symtab));
symtabcnt++;
}
- s->sname = name;
+ s->sname = s->soname = name;
s->snext = NULL;
s->stype = UNDEF;
s->squal = 0;
@@ -2512,9 +2674,23 @@
s->sflags = flags & SMASK;
s->soffset = 0;
s->slevel = blevel;
+ s->sdf = NULL;
+ s->ssue = NULL;
return s;
}
+int
+fldchk(int sz)
+{
+ if (rpole->rsou != STNAME && rpole->rsou != UNAME)
+ uerror("field outside of structure");
+ if (sz < 0 || sz >= FIELD) {
+ uerror("illegal field size");
+ return 1;
+ }
+ return 0;
+}
+
#ifdef PCC_DEBUG
static char *
ccnames[] = { /* names of storage classes */
@@ -2551,3 +2727,108 @@
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);
+}
Index: init.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/init.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/ccom/init.c -L usr.bin/pcc/ccom/init.c -u -r1.1 -r1.2
--- usr.bin/pcc/ccom/init.c
+++ usr.bin/pcc/ccom/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.30 2007/09/24 20:34:03 ragge Exp $ */
+/* $Id: init.c,v 1.47 2008/12/20 14:15:27 ragge Exp $ */
/*
* Copyright (c) 2004, 2007 Anders Magnusson (ragge at ludd.ltu.se).
@@ -65,13 +65,13 @@
#include <string.h>
/*
- * Four machine-dependent routines may be called during initialization:
+ * The following machine-dependent routines may be called during
+ * initialization:
*
- * instring(char *str) - Print out a string.
* zbits(OFFSZ, int) - sets int bits of zero at position OFFSZ.
* infld(CONSZ off, int fsz, CONSZ val)
* - sets the bitfield val starting at off and size fsz.
- * inval(CONSZ off, int fsz, NODE *)
+ * ninval(CONSZ off, int fsz, NODE *)
* - prints an integer constant which may have
* a label associated with it, located at off and
* size fsz.
@@ -118,8 +118,8 @@
*/
static struct instk {
struct instk *in_prev; /* linked list */
- struct symtab **in_xp; /* member in structure initializations */
- struct symtab *in_sym; /* stab index */
+ struct symtab *in_lnk; /* member in structure initializations */
+ struct symtab *in_sym; /* symtab index */
union dimfun *in_df; /* dimenston of array */
TWORD in_t; /* type for this level */
int in_n; /* number of arrays seen so far */
@@ -148,11 +148,20 @@
SLIST_ENTRY(llist) next;
CONSZ begsz; /* bit offset of this entry */
struct ilist *il;
-} *curll;
-static SLIST_HEAD(, llist) lpole;
+};
+static SLIST_HEAD(llh, llist) lpole;
static CONSZ basesz;
static int numents; /* # of array entries allocated */
+static struct initctx {
+ struct initctx *prev;
+ struct instk *pstk;
+ struct symtab *psym;
+ struct llh lpole;
+ CONSZ basesz;
+ int numents;
+} *inilnk;
+
static struct ilist *
getil(struct ilist *next, CONSZ b, int sz, NODE *n)
{
@@ -185,16 +194,19 @@
/*
* Return structure containing off bitnumber.
* Allocate more entries, if needed.
- * This is not bright implemented.
*/
static struct llist *
setll(OFFSZ off)
{
- struct llist *ll;
+ struct llist *ll = NULL;
/* Ensure that we have enough entries */
while (off >= basesz * numents)
- (void)getll();
+ ll = getll();
+
+ if (ll != NULL && ll->begsz <= off && ll->begsz + basesz > off)
+ return ll;
+
SLIST_FOREACH(ll, &lpole, next)
if (ll->begsz <= off && ll->begsz + basesz > off)
break;
@@ -209,14 +221,30 @@
void
beginit(struct symtab *sp)
{
+ struct initctx *ict;
struct instk *is = &pbase;
- struct llist *ll;
#ifdef PCC_DEBUG
if (idebug)
printf("beginit(), sclass %s\n", scnames(sp->sclass));
#endif
+ if (pstk) {
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("beginit: saving ctx pstk %p\n", pstk);
+#endif
+ /* save old context */
+ ict = tmpalloc(sizeof(struct initctx));
+ ict->prev = inilnk;
+ inilnk = ict;
+ ict->pstk = pstk;
+ ict->psym = csym;
+ ict->lpole = lpole;
+ ict->basesz = basesz;
+ ict->numents = numents;
+ is = tmpalloc(sizeof(struct instk));
+ }
csym = sp;
numents = 0; /* no entries in array list */
@@ -225,10 +253,9 @@
else
basesz = tsize(DECREF(sp->stype), sp->sdf, sp->ssue);
SLIST_INIT(&lpole);
- curll = ll = getll(); /* at least first entry in list */
/* first element */
- is->in_xp = ISSOU(sp->stype) ? sp->ssue->suelem : NULL;
+ is->in_lnk = ISSOU(sp->stype) ? sp->ssue->sylnk : NULL;
is->in_n = 0;
is->in_t = sp->stype;
is->in_sym = sp;
@@ -276,25 +303,26 @@
is->in_n = 0;
if (pstk == NULL) {
/* stack empty */
- is->in_xp = ISSOU(sp->stype) ? sp->ssue->suelem : NULL;
+ is->in_lnk = ISSOU(sp->stype) ? sp->ssue->sylnk : NULL;
is->in_t = sp->stype;
is->in_sym = sp;
is->in_df = sp->sdf;
} else if (ISSOU(t)) {
- sq = *pstk->in_xp;
+ sq = pstk->in_lnk;
if (sq == NULL) {
uerror("excess of initializing elements");
} else {
- is->in_xp = ISSOU(sq->stype) ? sq->ssue->suelem : 0;
+ is->in_lnk = ISSOU(sq->stype) ? sq->ssue->sylnk : 0;
is->in_t = sq->stype;
is->in_sym = sq;
is->in_df = sq->sdf;
}
} else if (ISARY(t)) {
- is->in_xp = ISSOU(DECREF(t)) ? pstk->in_sym->ssue->suelem : 0;
+ 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--;
}
@@ -326,9 +354,9 @@
printf("stkpop\n");
#endif
for (; pstk; pstk = pstk->in_prev) {
- if (pstk->in_t == STRTY) {
- pstk->in_xp++;
- if (*pstk->in_xp != NULL)
+ if (pstk->in_t == STRTY && pstk->in_lnk != NULL) {
+ pstk->in_lnk = pstk->in_lnk->snext;
+ if (pstk->in_lnk != NULL)
break;
}
if (ISSOU(pstk->in_t) && pstk->in_fl)
@@ -337,7 +365,7 @@
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 */
}
@@ -398,10 +426,12 @@
}
}
}
+#ifdef PCC_DEBUG
if (idebug>1) {
printf("findoff: off %lld\n", off);
prtstk(pstk);
}
+#endif
return off;
}
@@ -445,24 +475,6 @@
}
/*
- * Align data and set correct location.
- */
-static void
-setscl(struct symtab *sp)
-{
- setloc1((sp->squal << TSHIFT) & CON ? RDATA : DATA);
- defalign(talign(sp->stype, sp->ssue));
- if (sp->sclass == EXTDEF ||
- (sp->sclass == STATIC && sp->slevel == 0)) {
- defnam(sp);
- } else {
- if (sp->soffset == NOOFFSET)
- cerror("setscl");
- deflab1(sp->soffset);
- }
-}
-
-/*
* take care of generating a value for the initializer p
* inoff has the current offset (last bit written)
* in the current word being generated
@@ -487,9 +499,11 @@
p = optim(p);
+#ifdef notdef /* leave to the target to decide if useable */
if (csym->sclass != AUTO && p->n_op != ICON &&
p->n_op != FCON && p->n_op != NAME)
cerror("scalinit not leaf");
+#endif
/* Out of elements? */
if (pstk == NULL) {
@@ -552,17 +566,14 @@
else
typ = INT;
/* Fake a struct reference */
- spname = csym;
- p = buildtree(ADDROF,
- buildtree(NAME, NIL, NIL), NIL);
- r = block(ICON, NIL, NIL, typ, 0, MKSUE(typ));
+ p = buildtree(ADDROF, nametree(csym), NIL);
sym.stype = typ;
sym.squal = 0;
sym.sdf = 0;
sym.ssue = MKSUE(typ);
sym.soffset = off;
sym.sclass = typ == INT ? FIELD | fsz : MOU;
- r->n_sp = &sym;
+ r = xbcon(0, &sym, typ);
p = block(STREF, p, r, INT, 0, MKSUE(INT));
ecode(buildtree(ASSIGN, stref(p), bcon(val)));
}
@@ -609,10 +620,10 @@
#endif
if (csym->sclass != AUTO)
- setscl(csym);
+ 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 */
@@ -644,20 +655,17 @@
(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;
- r = block(ICON, NIL, NIL, INT, 0, MKSUE(INT));
sym.stype = n->n_type;
sym.squal = n->n_qual;
sym.sdf = n->n_df;
sym.ssue = n->n_sue;
sym.soffset = ll->begsz + il->off;
sym.sclass = fsz < 0 ? FIELD | -fsz : 0;
- r->n_sp = &sym;
+ 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;
@@ -670,7 +678,7 @@
infld(il->off, fsz, il->n->n_lval);
} else
ninval(il->off, fsz, il->n);
- nfree(il->n);
+ tfree(il->n);
}
lastoff = ll->begsz + il->off + fsz;
}
@@ -679,6 +687,19 @@
clearbf(lastoff, tbit-lastoff);
} else
zbits(lastoff, tbit-lastoff);
+ if (inilnk) {
+ struct initctx *ict = inilnk;
+ pstk = ict->pstk;
+ csym = ict->psym;
+ lpole = ict->lpole;
+ basesz = ict->basesz;
+ numents = ict->numents;
+ inilnk = inilnk->prev;
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("endinit: restoring ctx pstk %p\n", pstk);
+#endif
+ }
}
/*
@@ -731,8 +752,9 @@
if (ISARY(pstk->in_t))
pstk->in_n = pstk->in_df->ddim;
else if (pstk->in_t == STRTY) {
- while (pstk->in_xp[1] != NULL)
- pstk->in_xp++;
+ while (pstk->in_lnk != NULL &&
+ pstk->in_lnk->snext != NULL)
+ pstk->in_lnk = pstk->in_lnk->snext;
}
stkpop();
return;
@@ -766,11 +788,11 @@
break;
case NAME:
- if (pstk->in_xp) {
- for (; pstk->in_xp[0]; pstk->in_xp++)
- if (pstk->in_xp[0]->sname == (char *)p->n_sp)
+ if (pstk->in_lnk) {
+ for (; pstk->in_lnk; pstk->in_lnk = pstk->in_lnk->snext)
+ if (pstk->in_lnk->sname == (char *)p->n_sp)
break;
- if (pstk->in_xp[0] == NULL)
+ if (pstk->in_lnk == NULL)
uerror("member missing");
} else {
uerror("not a struct/union");
@@ -798,12 +820,12 @@
pstk = pstk->in_prev; /* Empty stack */
if (ISSOU(pstk->in_t))
- pstk->in_xp = pstk->in_sym->ssue->suelem;
+ pstk->in_lnk = pstk->in_sym->ssue->sylnk;
mkstack(p); /* Setup for assignment */
/* pop one step if SOU, ilbrace will push */
- if (op == NAME)
+ if (op == NAME || op == LB)
pstk = pstk->in_prev;
#ifdef PCC_DEBUG
@@ -830,7 +852,7 @@
i = (unsigned char)s[-1];
asginit(bcon(i));
}
- nfree(p);
+ tfree(p);
}
/*
@@ -904,8 +926,8 @@
if (in->in_fl) printf("{ ");
printf("soff=%d ", in->in_sym->soffset);
if (in->in_t == STRTY) {
- if (in->in_xp && in->in_xp[0])
- printf("curel %s ", in->in_xp[0]->sname);
+ if (in->in_lnk)
+ printf("curel %s ", in->in_lnk->sname);
else
printf("END struct");
}
@@ -931,7 +953,7 @@
/* 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;
@@ -940,9 +962,8 @@
switch (sp->sclass) {
case STATIC:
case EXTDEF:
- spname = sp;
- p = optim(buildtree(ASSIGN, buildtree(NAME, NIL, NIL), p));
- setscl(sp);
+ p = optim(buildtree(ASSIGN, nametree(sp), p));
+ defloc(sp);
ninval(0, p->n_right->n_sue->suesize, p->n_right);
tfree(p);
break;
@@ -951,8 +972,7 @@
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:
Index: gcc_compat.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/gcc_compat.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/ccom/gcc_compat.c -L usr.bin/pcc/ccom/gcc_compat.c -u -r1.1 -r1.2
--- usr.bin/pcc/ccom/gcc_compat.c
+++ usr.bin/pcc/ccom/gcc_compat.c
@@ -1,4 +1,4 @@
-/* $Id: gcc_compat.c,v 1.7 2006/05/13 06:35:36 ragge Exp $ */
+/* $Id: gcc_compat.c,v 1.22 2008/12/20 14:15:27 ragge Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -36,15 +36,46 @@
#include <string.h>
+/* Remove heading and trailing __ */
+static char *
+decap(char *s)
+{
+ if (s[0] == '_' && s[1] == '_') {
+ int len = strlen(s);
+
+ if (s[len-1] == '_' && s[len-2] == '_') {
+ s = tmpstrdup(s); /* will trash */
+ s[len-2] = 0;
+ }
+ s += 2;
+ }
+ return s;
+}
+
static struct kw {
char *name, *ptr;
int rv;
} kw[] = {
- { "__asm", NULL, C_ASM },
- { "__signed", NULL, 0 },
- { "__inline", NULL, C_FUNSPEC },
- { "__const", NULL, 0 },
- { "__asm__", NULL, C_ASM },
+/*
+ * Do NOT change the order of these entries unless you know
+ * what you're doing!
+ */
+/* 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 },
+/* 11 */{ "__typeof__", NULL, C_TYPEOF },
+/* 12 */{ "typeof", NULL, C_TYPEOF },
+/* 13 */{ "__extension__", NULL, -1 },
+/* 14 */{ "__signed__", NULL, 0 },
+/* 15 */{ "__attribute__", NULL, 0 },
{ NULL, NULL, 0 },
};
@@ -58,12 +89,16 @@
}
+#define TS "\n#pragma tls\n# %d\n"
+#define TLLEN sizeof(TS)+10
/*
* See if a string matches a gcc keyword.
*/
int
gcc_keyword(char *str, NODE **n)
{
+ extern int inattr, parlvl, parbal;
+ char tlbuf[TLLEN], *tw;
struct kw *kwp;
int i;
@@ -75,52 +110,174 @@
if (kwp->rv)
return kwp->rv;
switch (i) {
- case 1: /* __signed */
+ case 1: /* __signed */
+ case 14: /* __signed__ */
*n = mkty((TWORD)SIGNED, 0, MKSUE(SIGNED));
return C_TYPE;
case 3: /* __const */
*n = block(QUALIFIER, NIL, NIL, CON, 0, 0);
return C_QUALIFIER;
+ case 6: /* __thread */
+ snprintf(tlbuf, TLLEN, TS, lineno);
+ tw = &tlbuf[strlen(tlbuf)];
+ 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;
+ case 15: /* __attribute__ */
+ inattr = 1;
+ parlvl = parbal;
+ return C_ATTRIBUTE;
}
cerror("gcc_keyword");
return 0;
}
-static struct ren {
- struct ren *next;
- char *old, *new;
-} *renp;
+#ifndef TARGET_TYPE_ATTR
+#define TARGET_TYPE_ATTR(p, sue) 1
+#endif
+#ifndef TARGET_VAR_ATTR
+#define TARGET_VAR_ATTR(p, sue) 1
+#endif
+#ifndef ALMAX
+#define ALMAX (ALLDOUBLE > ALLONGLONG ? ALLDOUBLE : ALLONGLONG)
+#endif
+
/*
- * Save a name for later renaming of a variable.
+ * Get type attributes from an argument list.
*/
-void
-gcc_rename(struct symtab *sp, char *newname)
+static void
+gcc_ta(NODE *p, void *arg)
{
- struct ren *ren = permalloc(sizeof(struct ren));
+ struct suedef *sue = arg;
+ char *n2, *name = NULL;
- sp->sflags |= SRENAME;
- ren->old = sp->sname;
- ren->new = newstring(newname, strlen(newname)+1);
- ren->next = renp;
- renp = ren;
+ if (p->n_op == NAME) {
+ name = (char *)p->n_sp;
+ } else if (p->n_op == CALL || p->n_op == UCALL) {
+ name = (char *)p->n_left->n_sp;
+ } else
+ cerror("bad type attribute");
+
+ n2 = name;
+ name = decap(name);
+ if (strcmp(name, "aligned") == 0) {
+ /* Align the type to a given max alignment */
+ if (p->n_op == CALL) {
+ sue->suealigned = icons(eve(p->n_right)) * SZCHAR;
+ p->n_op = UCALL;
+ } else
+ sue->suealigned = ALMAX;
+ } else if (strcmp(name, "packed") == 0) {
+ /* pack members of a struct */
+ if (p->n_op != NAME)
+ uerror("packed takes no args");
+ sue->suepacked = SZCHAR; /* specify pack size? */
+ } else if (TARGET_TYPE_ATTR(p, sue) == 0)
+ werror("unsupported attribute %s", n2);
}
/*
- * Get a renamed variable.
+ * Get variable attributes from an argument list.
*/
-char *
-gcc_findname(struct symtab *sp)
+static void
+gcc_va(NODE *p, void *arg)
{
- struct ren *w;
+ struct suedef *sue = arg;
+ char *n2, *name = NULL;
- if ((sp->sflags & SRENAME) == 0)
- return exname(sp->sname);
+ if (p->n_op == NAME) {
+ name = (char *)p->n_sp;
+ } else if (p->n_op == CALL || p->n_op == UCALL) {
+ name = (char *)p->n_left->n_sp;
+ } else
+ cerror("bad variable attribute");
+
+ n2 = name;
+ name = decap(name);
+ if (strcmp(name, "aligned") == 0) {
+ /* Align the variable to a given max alignment */
+ if (p->n_op == CALL) {
+ sue->suealigned = icons(eve(p->n_right)) * SZCHAR;
+ p->n_op = UCALL;
+ } else
+ sue->suealigned = ALMAX;
+ } else if (strcmp(name, "section") == 0) {
+ if (p->n_right->n_op != STRING)
+ uerror("bad section");
+ sue->suesection = p->n_right->n_name;
+#ifdef notyet
+ } else if (strcmp(name, "packed") == 0) {
+ /* pack members of a struct */
+ if (p->n_op != NAME)
+ uerror("packed takes no args");
+ sue->suepacked = SZCHAR; /* specify pack size? */
+#endif
+ } else if (TARGET_VAR_ATTR(p, sue) == 0)
+ werror("unsupported attribute %s", n2);
+}
- for (w = renp; w; w = w->next) {
- if (w->old == sp->sname)
- return exname(w->new);
- }
- cerror("gcc_findname %s", sp->sname);
- return NULL;
+/*
+ * Extract type attributes from a node tree and setup a suedef
+ * struct based on its contents.
+ */
+struct suedef *
+gcc_type_attrib(NODE *p)
+{
+ struct suedef *sue = tmpcalloc(sizeof(struct suedef));
+
+ flist(p, gcc_ta, sue);
+ tfree(p);
+ return sue;
+}
+
+struct suedef *
+gcc_var_attrib(NODE *p)
+{
+ struct suedef *sue = permalloc(sizeof(struct suedef)); /* XXX ??? */
+
+ memset(sue, 0, sizeof(struct suedef));
+ flist(p, gcc_va, sue);
+ tfree(p);
+ return sue;
+}
+
+
+#ifdef notyet
+struct gcc_attrib {
+ int atype;
+ union {
+ int iarg; char *sarg;
+ } a1;
+ union {
+ int iarg; char *sarg;
+ } a2;
+ union {
+ int iarg; char *sarg;
+ } a3;
+};
+
+typedef struct gcc_attrib g_attr_t;
+
+/*
+ * Parse an attribute tree and create a attribute struct.
+ * If failed, return NULL>
+ */
+g_attr_t *
+gcc_attrib_parse(NODE *p)
+{
}
+
+#endif
+
#endif
Index: pass1.h
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/pass1.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/ccom/pass1.h -L usr.bin/pcc/ccom/pass1.h -u -r1.1 -r1.2
--- usr.bin/pcc/ccom/pass1.h
+++ usr.bin/pcc/ccom/pass1.h
@@ -1,4 +1,4 @@
-/* $Id: pass1.h,v 1.125 2007/09/09 10:01:01 ragge Exp $ */
+/* $Id: pass1.h,v 1.166 2008/12/14 21:15:24 ragge Exp $ */
/*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
@@ -33,9 +33,20 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
+
#include <sys/types.h>
#include <stdarg.h>
+#include <string.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifndef MKEXT
+#include "external.h"
+#else
+typedef unsigned int bittype; /* XXX - for basicblock */
+#endif
#include "manifest.h"
#include "protos.h"
@@ -63,7 +74,6 @@
#define MOE 16
#define UFORTRAN 17
#define USTATIC 18
-#define ILABEL 19
/* field size is ORed in */
#define FIELD 0100
@@ -81,21 +91,17 @@
#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
-#ifdef GCC_COMPAT
-#define SRENAME 02000 /* Node is renamed */
-#endif
-#define SASG 04000
-
-#ifndef FIXDEF
-#define FIXDEF(p)
-#endif
+/* #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
/* alignment of initialized quantities */
#ifndef AL_INIT
@@ -122,8 +128,11 @@
*/
struct suedef {
int suesize; /* Size of the struct */
- struct symtab **suelem;/* points to the list of elements */
+ struct symtab *sylnk; /* the list of elements */
int suealign; /* Alignment of this struct */
+ int suealigned; /* Larger alignment requested */
+ int suepacked; /* Smaller alignment requested */
+ char * suesection; /* Section requested for this var/fun */
};
/*
@@ -134,38 +143,26 @@
union dimfun *df;
struct suedef *sue;
};
-#define TNULL INCREF(MOETY) /* pointer to MOETY -- impossible type */
-#define TELLIPSIS INCREF(INCREF(MOETY))
+#define TNULL INCREF(FARG) /* pointer to FARG -- impossible type */
+#define TELLIPSIS INCREF(INCREF(FARG))
/*
* Symbol table definition.
- *
- * The symtab_hdr struct is used to save label info in NAME and ICON nodes.
*/
-struct symtab_hdr {
- struct symtab *h_next; /* link to other symbols in the same scope */
- int h_offset; /* offset or value */
- char h_sclass; /* storage class */
- char h_slevel; /* scope level */
- short h_sflags; /* flags, see below */
-};
-
struct symtab {
- struct symtab_hdr hdr;
- char *sname;
+ struct symtab *snext; /* link to other symbols in the same scope */
+ int soffset; /* offset or value */
+ char sclass; /* storage class */
+ char slevel; /* scope level */
+ short sflags; /* flags, see below */
+ char *sname; /* Symbol name */
+ char *soname; /* Written-out name */
TWORD stype; /* type word */
TWORD squal; /* qualifier word */
union dimfun *sdf; /* ptr to the dimension/prototype array */
struct suedef *ssue; /* ptr to the definition table */
- int suse; /* line number of last use of the variable */
};
-#define snext hdr.h_next
-#define soffset hdr.h_offset
-#define sclass hdr.h_sclass
-#define slevel hdr.h_slevel
-#define sflags hdr.h_sflags
-
#define MKSUE(type) &btdims[type]
extern struct suedef btdims[];
@@ -177,7 +174,7 @@
CONSZ sval; /* case value */
int slab; /* associated label */
};
-void genswitch(int, struct swents **, int);
+int mygenswitch(int, TWORD, struct swents **, int);
extern int blevel;
extern int instruct, got_type;
@@ -189,16 +186,12 @@
extern struct symtab *cftnsp;
extern int autooff, maxautooff, argoff, strucoff;
extern int brkflag;
-extern int lastloc;
extern OFFSZ inoff;
extern int reached;
extern int isinlining;
-
-/* tunnel to buildtree for name id's */
-
-extern struct symtab *spname;
+extern int xinline;
extern int sdebug, idebug, pdebug;
@@ -208,11 +201,9 @@
extern int flostat;
extern int retlab;
-/*
- * Flags used in structures/unions
- */
-#define INSTRUCT 02
-#define INUNION 04
+/* pragma globals */
+extern int pragma_allpacked, pragma_packed, pragma_aligned;
+extern char *pragma_renamed;
/*
* Flags used in the (elementary) flow analysis ...
@@ -228,16 +219,16 @@
/* 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(char *),
- *wstrend(char *),
- *tymerge(NODE *typ, NODE *idp),
+ *dclstruct(struct rstack *, struct suedef *),
+ *strend(int gtype, char *),
+ *tymerge(NODE *, NODE *),
*stref(NODE *),
*offcon(OFFSZ, TWORD, union dimfun *, struct suedef *),
*bcon(int),
+ *xbcon(CONSZ, struct symtab *, TWORD),
*bpsize(NODE *),
*convert(NODE *, int),
*pconvert(NODE *),
@@ -245,99 +236,150 @@
*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 *),
- *btsize(TWORD, union dimfun *, struct suedef *),
- *tempnode(int, TWORD type, union dimfun *df, struct suedef *sue),
- *doacall(NODE *f, NODE *a);
+ *tempnode(int, TWORD, union dimfun *, struct suedef *),
+ *eve(NODE *),
+ *doacall(struct symtab *, NODE *, NODE *);
+NODE *intprom(NODE *);
OFFSZ tsize(TWORD, union dimfun *, struct suedef *),
psize(NODE *);
NODE * typenode(NODE *new);
void spalloc(NODE *, NODE *, OFFSZ);
char *exname(char *);
+NODE *floatcon(char *);
+NODE *fhexcon(char *);
+extern struct rstack *rpole;
-int oalloc(struct symtab *p, int *poff);
+int oalloc(struct symtab *, int *);
void deflabel(char *);
-void deflab1(int);
-void setloc1(int);
void gotolabel(char *);
-unsigned int esccon(char **sptr);
-void inline_start(char *name);
+unsigned int esccon(char **);
+void inline_start(struct symtab *);
void inline_end(void);
void inline_addarg(struct interpass *);
-void inline_ref(char *);
+void inline_ref(struct symtab *);
void inline_prtout(void);
+void inline_args(struct symtab **, int);
+NODE *inlinetree(struct symtab *, NODE *, NODE *);
void ftnarg(NODE *);
-struct rstack *bstruct(char *, int);
+struct rstack *bstruct(char *, int, struct suedef *);
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);
-void schedremove(struct symtab *p);
-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 commdec(struct symtab *);
-void lcommdec(struct symtab *);
-int falloc(struct symtab *p, int w, int new, NODE *pty);
+void defzero(struct symtab *);
+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 indata(CONSZ, int);
-void instring(char *);
-void defnam(struct symtab *);
-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);
-int ftoint(NODE *, CONSZ **);
-void p1print(char *fmt, ...);
+void scalinit(NODE *);
+void p1print(char *, ...);
char *copst(int);
int cdope(int);
void myp2tree(NODE *);
void lcommprint(void);
void lcommdel(struct symtab *);
+NODE *funcode(NODE *);
+struct symtab *enumhd(char *);
+NODE *enumdcl(struct symtab *);
+NODE *enumref(char *);
+CONSZ icons(NODE *);
+int mypragma(char **);
+void fixdef(struct symtab *);
+int cqual(TWORD, TWORD);
+void defloc(struct symtab *);
+int fldchk(int);
+int nncon(NODE *);
+void cunput(char);
+NODE *nametree(struct symtab *sp);
+void *inlalloc(int size);
+void pass1_lastchance(struct interpass *);
+void fldty(struct symtab *p);
+int getlab(void);
+
+#ifdef SOFTFLOAT
+typedef struct softfloat SF;
+SF soft_neg(SF);
+SF soft_cast(CONSZ v, TWORD);
+SF soft_plus(SF, SF);
+SF soft_minus(SF, SF);
+SF soft_mul(SF, SF);
+SF soft_div(SF, SF);
+int soft_isz(SF);
+CONSZ soft_val(SF);
+#define FLOAT_NEG(sf) soft_neg(sf)
+#define FLOAT_CAST(v,t) soft_cast(v, t)
+#define FLOAT_PLUS(x1,x2) soft_plus(x1, x2)
+#define FLOAT_MINUS(x1,x2) soft_minus(x1, x2)
+#define FLOAT_MUL(x1,x2) soft_mul(x1, x2)
+#define FLOAT_DIV(x1,x2) soft_div(x1, x2)
+#define FLOAT_ISZERO(sf) soft_isz(sf)
+#define FLOAT_VAL(sf) soft_val(sf)
+#else
+#define FLOAT_NEG(p) -(p)
+#define FLOAT_CAST(p,v) (ISUNSIGNED(v) ? \
+ (long double)(U_CONSZ)(p) : (long double)(CONSZ)(p))
+#define FLOAT_PLUS(x1,x2) (x1) + (x2)
+#define FLOAT_MINUS(x1,x2) (x1) - (x2)
+#define FLOAT_MUL(x1,x2) (x1) * (x2)
+#define FLOAT_DIV(x1,x2) (x1) / (x2)
+#define FLOAT_ISZERO(p) (p) == 0.0
+#define FLOAT_VAL(p) (CONSZ)(p)
+#endif
#ifdef GCC_COMPAT
void gcc_init(void);
int gcc_keyword(char *, NODE **);
-void gcc_rename(struct symtab *sp, char *newname);
-char *gcc_findname(struct symtab *sp);
+struct suedef *gcc_type_attrib(NODE *);
+struct suedef *gcc_var_attrib(NODE *);
#endif
#ifdef STABS
void stabs_init(void);
void stabs_file(char *);
+void stabs_efile(char *);
void stabs_line(int);
void stabs_rbrac(int);
void stabs_lbrac(int);
void stabs_func(struct symtab *);
void stabs_newsym(struct symtab *);
void stabs_chgsym(struct symtab *);
-void stabs_struct(struct symtab *p, struct suedef *sue);
+void stabs_struct(struct symtab *, struct suedef *);
#endif
#ifndef CHARCAST
@@ -363,7 +405,7 @@
#define OROR (MAXOP+12)
#define NOT (MAXOP+13)
#define CAST (MAXOP+14)
-/* #define STRING (MAXOP+15) */
+#define STRING (MAXOP+15)
/* The following must be in the same order as their NOASG counterparts */
#define PLUSEQ (MAXOP+16)
@@ -381,12 +423,18 @@
#define INCR (MAXOP+26)
#define DECR (MAXOP+27)
+#define SZOF (MAXOP+28)
+
+
/*
* The following types are only used in pass1.
*/
#define SIGNED (MAXTYPES+1)
#define BOOL (MAXTYPES+2)
-
+#define FCOMPLEX (MAXTYPES+3)
+#define COMPLEX (MAXTYPES+4)
+#define LCOMPLEX (MAXTYPES+5)
+#define ENUMTY (MAXTYPES+6)
#define coptype(o) (cdope(o)&TYFLG)
#define clogop(o) (cdope(o)&LOGFLG)
Index: main.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/main.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L usr.bin/pcc/ccom/main.c -L usr.bin/pcc/ccom/main.c -u -r1.2 -r1.3
--- usr.bin/pcc/ccom/main.c
+++ usr.bin/pcc/ccom/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.72 2007/09/25 06:43:06 ragge Exp $ */
+/* $Id: main.c,v 1.95 2008/12/17 15:59:24 ragge Exp $ */
/*
* Copyright (c) 2002 Anders Magnusson. All rights reserved.
@@ -26,7 +26,11 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
+
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <signal.h>
#include <string.h>
#include <stdlib.h>
@@ -34,19 +38,44 @@
#include "pass1.h"
#include "pass2.h"
-int sflag, nflag, oflag, kflag;
-int lflag, odebug, rdebug, radebug, vdebug, s2debug, udebug, x2debug;
+int sflag, nflag, oflag, kflag, pflag;
+int lflag, odebug, rdebug, s2debug, udebug, x2debug;
#if !defined(MULTIPASS) || defined(PASST)
int iTflag, oTflag;
#endif
-int xdebug, mdebug, sdebug, gflag, c2debug, pdebug;
+int xdebug, sdebug, gflag, c2debug, pdebug;
int Wstrict_prototypes, Wmissing_prototypes, Wimplicit_int,
- Wimplicit_function_declaration;
-int xssaflag, xtailcallflag, xtemps, xdeljumps;
+ 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, xdce, xinline;
int e2debug, t2debug, f2debug, b2debug;
-struct suedef btdims[24];
+struct suedef btdims[32] = {
+ [BOOL] = { .suesize = SZBOOL, .suealign = ALBOOL },
+ [CHAR] = { .suesize = SZCHAR, .suealign = ALCHAR },
+ [INT] = { .suesize = SZINT, .suealign = ALINT },
+ [FLOAT] = { .suesize = SZFLOAT, .suealign = ALFLOAT },
+ [DOUBLE] = { .suesize = SZDOUBLE, .suealign = ALDOUBLE },
+ [LDOUBLE] = { .suesize = SZLDOUBLE, .suealign = ALLDOUBLE },
+ [LONG] = { .suesize = SZLONG, .suealign = ALLONG },
+ [LONGLONG] = { .suesize = SZLONGLONG, .suealign = ALLONGLONG },
+ [SHORT] = { .suesize = SZSHORT, .suealign = ALSHORT },
+ [UCHAR] = { .suesize = SZCHAR, .suealign = ALCHAR },
+ [USHORT] = { .suesize = SZSHORT, .suealign = ALSHORT },
+ [UNSIGNED] = { .suesize = SZINT, .suealign = ALINT },
+ [ULONG] = { .suesize = SZLONG, .suealign = ALLONG },
+ [ULONGLONG] = { .suesize = SZLONGLONG, .suealign = ALLONGLONG },
+ [FCOMPLEX] = { .suesize = SZFLOAT * 2, .suealign = ALFLOAT },
+ [COMPLEX] = { .suesize = SZDOUBLE * 2, .suealign = ALDOUBLE },
+ [LCOMPLEX] = { .suesize = SZLDOUBLE * 2, .suealign = ALLDOUBLE },
+};
char *prgname;
static void prtstats(void);
@@ -58,6 +87,11 @@
{ "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, },
};
@@ -72,10 +106,12 @@
static void
segvcatch(int a)
{
- fprintf(stderr, "%sinternal compiler error: %s, line %d\n",
+ char buf[1024];
+
+ snprintf(buf, sizeof buf, "%sinternal compiler error: %s, line %d\n",
nerrors ? "" : "major ", ftitle, lineno);
- fflush(stderr);
- exit(1);
+ write(STDERR_FILENO, buf, strlen(buf));
+ _exit(1);
}
/*
@@ -84,22 +120,60 @@
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 = 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
@@ -108,9 +182,15 @@
int ch;
+#ifdef TIMING
+ struct timeval t1, t2;
+
+ (void)gettimeofday(&t1, NULL);
+#endif
+
prgname = argv[0];
- while ((ch = getopt(argc, argv, "VlwX:Z:W:sOT:gx:kv")) != -1)
+ while ((ch = getopt(argc, argv, "OT:VW:X:Z:f:gklm:psvwx:")) != -1)
switch (ch) {
#if !defined(MULTIPASS) || defined(PASS1)
case 'X':
@@ -118,13 +198,13 @@
switch (*optarg++) {
case 'd': ++ddebug; break; /* declarations */
case 'i': ++idebug; break; /* initializations */
- case 'b': ++bdebug; break;
- case 't': ++tdebug; break;
+ case 'b': ++bdebug; break; /* buildtree */
+ case 't': ++tdebug; break; /* type match */
case 'e': ++edebug; break; /* pass1 exit */
case 'x': ++xdebug; break; /* MD code */
- case 's': ++sdebug; break;
- case 'n': ++nflag; break;
- case 'o': ++oflag; break;
+ case 's': ++sdebug; break; /* inline */
+ case 'n': ++nflag; break; /* node alloc */
+ case 'o': ++oflag; break; /* optim */
case 'p': ++pdebug; break; /* prototype */
default:
fprintf(stderr, "unknown X flag '%c'\n",
@@ -161,15 +241,12 @@
case 'r': /* register alloc/graph coloring */
++rdebug;
break;
- case 'a': ++radebug; break;
case 'b': /* basic block and SSA building */
++b2debug;
break;
case 'c': /* code printout */
++c2debug;
break;
- case 'm': ++mdebug; break;
- case 'v': ++vdebug; break;
case 't': ++t2debug; break;
case 's': /* shape matching */
++s2debug;
@@ -187,16 +264,28 @@
#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 'g': /* Debugging */
- gflag = 1;
+ case 'm': /* Target-specific */
+ mflags(optarg);
+ break;
+
+ case 'p': /* Profiling */
+ pflag = 1;
break;
case 's': /* Statistics */
@@ -216,6 +305,10 @@
xtemps++;
else if (strcmp(optarg, "deljumps") == 0)
xdeljumps++;
+ else if (strcmp(optarg, "dce") == 0)
+ xdce++;
+ else if (strcmp(optarg, "inline") == 0)
+ xinline++;
else
usage();
break;
@@ -230,20 +323,21 @@
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();
@@ -254,27 +348,18 @@
gcc_init();
#endif
- /* dimension table initialization */
-
- btdims[VOID].suesize = 0;
- btdims[BOOL].suesize = SZBOOL;
- btdims[CHAR].suesize = SZCHAR;
- btdims[INT].suesize = SZINT;
- btdims[FLOAT].suesize = SZFLOAT;
- btdims[DOUBLE].suesize = SZDOUBLE;
- btdims[LDOUBLE].suesize = SZLDOUBLE;
- btdims[LONG].suesize = SZLONG;
- btdims[LONGLONG].suesize = SZLONGLONG;
- btdims[SHORT].suesize = SZSHORT;
- btdims[UCHAR].suesize = SZCHAR;
- btdims[USHORT].suesize = SZSHORT;
- btdims[UNSIGNED].suesize = SZINT;
- btdims[ULONG].suesize = SZLONG;
- btdims[ULONGLONG].suesize = SZLONGLONG;
- /* starts past any of the above */
reached = 1;
bjobcode();
+#ifndef TARGET_STDARGS
+ {
+ NODE *p = block(NAME, NIL, NIL, PTR|CHAR, NULL, MKSUE(CHAR));
+ struct symtab *sp = lookup(addname("__builtin_va_list"), 0);
+ p->n_sp = sp;
+ defid(p, TYPEDEF);
+ nfree(p);
+ }
+#endif
#ifdef STABS
if (gflag) {
@@ -283,13 +368,34 @@
}
#endif
+ if (sspflag)
+ sspinit();
+
(void) yyparse();
yyaccpt();
- ejobcode( nerrors ? 1 : 0 );
if (!nerrors)
lcommprint();
+#ifdef STABS
+ if (gflag)
+ stabs_efile(argc ? argv[0] : "");
+#endif
+
+ ejobcode( nerrors ? 1 : 0 );
+
+#ifdef TIMING
+ (void)gettimeofday(&t2, NULL);
+ t2.tv_sec -= t1.tv_sec;
+ t2.tv_usec -= t1.tv_usec;
+ if (t2.tv_usec < 0) {
+ t2.tv_usec += 1000000;
+ t2.tv_sec -= 1;
+ }
+ fprintf(stderr, "pccom total time: %ld s %ld us\n",
+ t2.tv_sec, t2.tv_usec);
+#endif
+
if (sflag)
prtstats();
return(nerrors?1:0);
Index: cgram.y
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/cgram.y,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/ccom/cgram.y -L usr.bin/pcc/ccom/cgram.y -u -r1.1 -r1.2
--- usr.bin/pcc/ccom/cgram.y
+++ usr.bin/pcc/ccom/cgram.y
@@ -1,4 +1,4 @@
-/* $Id: cgram.y,v 1.170 2007/09/16 19:25:33 ragge Exp $ */
+/* $Id: cgram.y,v 1.241 2008/12/20 14:15:27 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
@@ -79,7 +79,6 @@
/*
* Token used in C lex/yacc communications.
*/
-%token C_WSTRING /* a wide string constant */
%token C_STRING /* a string constant */
%token C_ICON /* an integer constant */
%token C_FCON /* a floating point constant */
@@ -116,6 +115,9 @@
%token C_QUALIFIER
%token C_FUNSPEC
%token C_ASM
+%token NOMATCH
+%token C_TYPEOF /* COMPAT_GCC */
+%token C_ATTRIBUTE /* COMPAT_GCC */
/*
* Precedence
@@ -142,14 +144,15 @@
# 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;
-#ifdef GCC_COMPAT
-char *renname; /* for renaming of variables */
-#endif
+extern int enummer, tvaloff;
+extern struct rstack *rpole;
+static int ctval, widestr;
+NODE *cftnod;
+#define NORETYP SNOCREAT /* no return type, save in unused field in symtab */
static NODE *bdty(int op, ...);
static void fend(void);
@@ -159,12 +162,29 @@
static void resetbc(int mask);
static void swend(void);
static void addcase(NODE *p);
+#ifdef GCC_COMPAT
+static void gcccase(NODE *p, NODE *);
+#endif
static void adddef(void);
static void savebc(void);
-static void swstart(int);
-static NODE * structref(NODE *p, int f, char *name);
+static void swstart(int, TWORD);
+static void genswitch(int, TWORD, struct swents **, int);
+static NODE *structref(NODE *p, int f, char *name);
static char *mkpstr(char *str);
static struct symtab *clbrace(NODE *);
+static NODE *cmop(NODE *l, NODE *r);
+static NODE *xcmop(NODE *out, NODE *in, NODE *str);
+static void mkxasm(char *str, NODE *p);
+static NODE *xasmop(char *str, NODE *p);
+static int maxstlen(char *str);
+static char *stradd(char *old, char *new);
+static NODE *biop(int op, NODE *l, NODE *r);
+static void flend(void);
+static char * simname(char *s);
+#ifdef GCC_COMPAT
+static NODE *tyof(NODE *); /* COMPAT_GCC */
+static NODE *voidcon(void); /* COMPAT_GCC */
+#endif
/*
* State for saving current switch state (when nested switches).
@@ -184,6 +204,7 @@
NODE *nodep;
struct symtab *symp;
struct rstack *rp;
+ struct suedef *suep;
char *strp;
}
@@ -191,60 +212,49 @@
%start ext_def_list
%type <intval> con_e ifelprefix ifprefix whprefix forprefix doprefix switchpart
- type_qualifier_list
-%type <nodep> e .e term enum_dcl struct_dcl cast_type funct_idn declarator
+ type_qualifier_list xbegin
+%type <nodep> e .e term enum_dcl struct_dcl cast_type declarator
direct_declarator elist type_specifier merge_attribs
parameter_declaration abstract_declarator initializer
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
-%type <strp> string wstring C_STRING C_WSTRING
-%type <rp> enum_head str_head
-%type <symp> xnfdeclarator clbrace
+ identifier_list arg_param_list
+ designator_list designator xasm oplist oper cnstr funtype
+ typeof attribute attribute_specifier /* COMPAT_GCC */
+ attribute_list attr_spec_list /* COMPAT_GCC */
+%type <strp> string C_STRING
+%type <rp> str_head
+%type <symp> xnfdeclarator clbrace enum_head
%type <intval> C_CLASS C_STRUCT C_RELOP C_DIVOP C_SHIFTOP
C_ANDAND C_OROR C_STROP C_INCOP C_UNOP C_ASOP C_EQUOP
+
%type <nodep> C_TYPE C_QUALIFIER C_ICON C_FCON
%type <strp> C_NAME C_TYPENAME
-
+%type <suep> attr_var
%%
ext_def_list: ext_def_list external_def
| { ftnend(); }
;
-external_def: function_definition { blevel = 0; }
+external_def: funtype kr_args compoundstmt { fend(); }
| declaration { blevel = 0; symclear(0); }
| asmstatement ';'
| ';'
| error { blevel = 0; }
;
-function_definition:
- /* Ansi (or K&R header without parameter types) */
- declaration_specifiers declarator {
- fundef($1, $2);
- } compoundstmt { fend(); }
- /* Same as above but without declaring function type */
- | declarator {
- noretype = 1;
- fundef(mkty(INT, 0, MKSUE(INT)), $1);
- } compoundstmt { fend(); noretype = 0; }
- /* K&R function without type declaration */
- | declarator {
- noretype = 1;
- if (oldstyle == 0)
- uerror("bad declaration in ansi function");
- fundef(mkty(INT, 0, MKSUE(INT)), $1);
- } arg_dcl_list compoundstmt { fend(); noretype = 0; }
- /* K&R function with type declaration */
- | declaration_specifiers declarator {
- if (oldstyle == 0)
- uerror("bad declaration in ansi function");
- fundef($1, $2);
- } arg_dcl_list compoundstmt { fend(); }
+funtype: /* no type given */ declarator {
+ fundef(mkty(INT, 0, MKSUE(INT)), $1);
+ cftnsp->sflags |= NORETYP;
+ }
+ | declaration_specifiers declarator { fundef($1,$2); }
+ ;
+
+kr_args: /* empty */
+ | arg_dcl_list
;
/*
@@ -264,14 +274,12 @@
| C_QUALIFIER merge_attribs { $1->n_left = $2; $$ = $1; }
| function_specifiers { $$ = NIL; }
| function_specifiers merge_attribs { $$ = $2; }
+ /*COMPAT_GCC*/ | typeof { $$ = $1; }
+ /*COMPAT_GCC*/ | typeof merge_attribs { $1->n_left = $2; $$ = $1; }
;
function_specifiers:
- C_FUNSPEC {
- if (fun_inline)
- uerror("too many inline");
- fun_inline = 1;
- }
+ C_FUNSPEC { fun_inline = 1; }
;
type_specifier: C_TYPE { $$ = $1; }
@@ -282,16 +290,40 @@
}
| struct_dcl { $$ = $1; }
| enum_dcl { $$ = $1; }
+ | attribute_specifier { tfree($1); $$ = biop(FLD, 0, 0); }
+ ;
+
+typeof: C_TYPEOF '(' term ')' { $$ = tyof($3); } /* COMPAT_GCC */
+ /*COMPAT_GCC*/ | C_TYPEOF '(' cast_type ')' { $$ = tyof($3); }
+ /*COMPAT_GCC*/ ;
+
+attribute_specifier :
+ C_ATTRIBUTE '(' '(' attribute_list ')' ')' { $$ = $4; }
+ /*COMPAT_GCC*/ ;
+
+attribute_list: attribute
+ | attribute ',' attribute_list { $$ = cmop($3, $1); }
+ ;
+
+attribute: { $$ = voidcon(); }
+ | C_NAME { $$ = bdty(NAME, $1); }
+ | C_NAME '(' elist ')' {
+ $$ = bdty($3 == NIL ? UCALL : CALL, bdty(NAME, $1), $3);
+ }
;
/*
* Adds a pointer list to front of the declarators.
* Note the UMUL right node pointer usage.
*/
-declarator: pointer direct_declarator {
- $$ = $1; $1->n_right->n_left = $2;
+declarator: pointer direct_declarator attr_var {
+ $$ = $1; $1->n_right->n_left = $2; $$->n_sue = 0;
}
- | direct_declarator { $$ = $1; }
+ | pointer attr_spec_list direct_declarator attr_var {
+ $$ = $1; $1->n_right->n_left = $3; $$->n_sue = 0;
+ tfree($2);
+ }
+ | direct_declarator attr_var { $$ = $1; $$->n_sue = 0; }
;
/*
@@ -328,41 +360,58 @@
direct_declarator: C_NAME { $$ = bdty(NAME, $1); }
| '(' declarator ')' { $$ = $2; }
| direct_declarator '[' nocon_e ']' {
- $$ = block(LB, $1, $3, INT, 0, MKSUE(INT));
+ $3 = optim($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) {
+ 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
+ }
+ $$ = biop(LB, $1, $3);
+ }
+ | direct_declarator '[' ']' {
+ $$ = biop(LB, $1, bcon(NOOFFSET));
}
- | direct_declarator '[' ']' { $$ = bdty(LB, $1, 0); }
- | direct_declarator '(' notype parameter_type_list ')' {
- $$ = bdty(CALL, $1, $4);
+ | direct_declarator '(' parameter_type_list ')' {
+ $$ = bdty(CALL, $1, $3);
}
- | direct_declarator '(' notype identifier_list ')' {
- $$ = bdty(CALL, $1, $4);
+ | direct_declarator '(' identifier_list ')' {
+ $$ = bdty(CALL, $1, $3);
if (blevel != 0)
uerror("function declaration in bad context");
oldstyle = 1;
}
- | direct_declarator '(' ')' { $$ = bdty(UCALL, $1); }
- ;
-
-notype: { /* extern int notype, doproto; notype = 0; doproto=1; printf("notype\n"); */ }
+ | direct_declarator '(' ')' {
+ ctval = tvaloff;
+ $$ = bdty(UCALL, $1);
+ }
;
-identifier_list: C_NAME { $$ = bdty(NAME, $1); $$->n_type = FARG; }
- | identifier_list ',' C_NAME {
- $$ = bdty(NAME, $3);
- $$->n_type = FARG;
- $$ = block(CM, $1, $$, 0, 0, 0);
- }
+identifier_list: C_NAME { $$ = bdty(NAME, $1); }
+ | identifier_list ',' C_NAME { $$ = cmop($1, bdty(NAME, $3)); }
;
/*
* Returns as parameter_list, but can add an additional ELLIPSIS node.
- * Calls revert() to get the parameter list in the forward order.
*/
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));
}
;
@@ -373,7 +422,7 @@
*/
parameter_list: parameter_declaration { $$ = $1; }
| parameter_list ',' parameter_declaration {
- $$ = block(CM, $1, $3, 0, 0, 0);
+ $$ = cmop($1, $3);
}
;
@@ -382,15 +431,22 @@
*/
parameter_declaration:
declaration_specifiers declarator {
+ if ($1->n_lval != SNULL && $1->n_lval != REGISTER)
+ uerror("illegal parameter class");
+ $2->n_sue = NULL; /* no attributes */
$$ = tymerge($1, $2);
nfree($1);
+
}
| declaration_specifiers abstract_declarator {
+ $2->n_sue = NULL; /* no attributes */
$$ = tymerge($1, $2);
nfree($1);
}
| declaration_specifiers {
- $$ = tymerge($1, bdty(NAME, NULL));
+ $$ = bdty(NAME, NULL);
+ $$->n_sue = NULL; /* no attributes */
+ $$ = tymerge($1, $$);
nfree($1);
}
;
@@ -398,28 +454,30 @@
abstract_declarator:
pointer { $$ = $1; $1->n_right->n_left = bdty(NAME, NULL); }
| direct_abstract_declarator { $$ = $1; }
- | pointer direct_abstract_declarator {
+ | pointer direct_abstract_declarator attr_var {
$$ = $1; $1->n_right->n_left = $2;
}
;
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);
}
| '(' ')' { $$ = bdty(UCALL, bdty(NAME, NULL)); }
- | '(' notype parameter_type_list ')' {
- $$ = bdty(CALL, bdty(NAME, NULL), $3);
+ | '(' parameter_type_list ')' {
+ $$ = bdty(CALL, bdty(NAME, NULL), $2);
}
| direct_abstract_declarator '(' ')' {
$$ = bdty(UCALL, $1);
}
- | direct_abstract_declarator '(' notype parameter_type_list ')' {
- $$ = bdty(CALL, $1, $4);
+ | direct_abstract_declarator '(' parameter_type_list ')' {
+ $$ = bdty(CALL, $1, $3);
}
;
@@ -445,25 +503,24 @@
/*
* Declarations in beginning of blocks.
*/
-declaration_list: declaration
- | declaration_list declaration
+block_item_list: block_item
+ | block_item_list block_item
+ ;
+
+block_item: declaration
+ | statement
;
/*
* Here starts the old YACC code.
*/
-stmt_list: stmt_list statement
- | { bccode(); }
- ;
-
/*
* 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;
}
;
@@ -474,41 +531,51 @@
*/
init_declarator_list:
init_declarator
- | init_declarator_list ',' { $<nodep>$ = $<nodep>0; } init_declarator
+ | init_declarator_list ',' attr_var { $<nodep>$ = $<nodep>0; } init_declarator attr_var
;
-enum_dcl: enum_head '{' moe_list optcomma '}' { $$ = dclstruct($1); }
- | C_ENUM C_NAME { $$ = rstruct($2,0); }
- | C_ENUM C_TYPENAME { $$ = rstruct($2,0); }
+enum_dcl: enum_head '{' moe_list optcomma '}' { $$ = enumdcl($1); }
+ | C_ENUM C_NAME { $$ = enumref($2); }
;
-enum_head: C_ENUM { $$ = bstruct(NULL,0); }
- | C_ENUM C_NAME { $$ = bstruct($2,0); }
- | C_ENUM C_TYPENAME { $$ = bstruct($2,0); }
+enum_head: C_ENUM { $$ = enumhd(NULL); }
+ | C_ENUM C_NAME { $$ = enumhd($2); }
;
moe_list: moe
| moe_list ',' moe
;
-moe: C_NAME { moedef( $1 ); }
- | C_NAME '=' con_e { strucoff = $3; moedef( $1 ); }
+moe: C_NAME { moedef($1); }
+ | C_TYPENAME { moedef($1); }
+ | C_NAME '=' con_e { enummer = $3; moedef($1); }
+ | C_TYPENAME '=' con_e { enummer = $3; moedef($1); }
;
-struct_dcl: str_head '{' struct_dcl_list '}' { $$ = dclstruct($1); }
- | C_STRUCT C_NAME { $$ = rstruct($2,$1); }
- | C_STRUCT C_TYPENAME { $$ = rstruct($2,$1); }
- | str_head '{' '}' {
-#ifndef GCC_COMPAT
- werror("gcc extension");
-#endif
- $$ = dclstruct($1);
+struct_dcl: str_head '{' struct_dcl_list '}' {
+ $$ = dclstruct($1, NULL);
}
+ | C_STRUCT attr_var C_NAME { $$ = rstruct($3,$1); }
+ /*COMPAT_GCC*/ | str_head '{' '}' { $$ = dclstruct($1, NULL); }
;
-str_head: C_STRUCT { $$ = bstruct(NULL, $1); }
- | C_STRUCT C_NAME { $$ = bstruct($2,$1); }
- | C_STRUCT C_TYPENAME { $$ = bstruct($2,$1); }
+attr_var: {
+ if (pragma_aligned || pragma_packed) {
+ $$ = tmpcalloc(sizeof(struct suedef));
+ $$->suealigned = pragma_aligned;
+ $$->suepacked = pragma_packed;
+ } else
+ $$ = NULL;
+ }
+ /*COMPAT_GCC*/ | attr_spec_list { $$ = gcc_type_attrib($1); }
+ ;
+
+attr_spec_list: attribute_specifier
+ | attr_spec_list attribute_specifier { tfree($2); /* XXX */ }
+ ;
+
+str_head: C_STRUCT attr_var { $$ = bstruct(NULL, $1, $2); }
+ | C_STRUCT attr_var C_NAME { $$ = bstruct($3,$1, $2); }
;
struct_dcl_list: struct_declaration
@@ -539,30 +606,33 @@
struct_declarator: declarator {
tymerge($<nodep>0, $1);
- $1->n_sp = getsymtab((char *)$1->n_sp, SMOSNAME); /* XXX */
- defid($1, $<nodep>0->n_lval);
+ soumemb($1, (char *)$1->n_sp, 0);
nfree($1);
}
| ':' con_e {
- if (!(instruct&INSTRUCT))
- uerror( "field outside of structure" );
+ if (fldchk($2))
+ $2 = 1;
falloc(NULL, $2, -1, $<nodep>0);
}
| declarator ':' con_e {
- if (!(instruct&INSTRUCT))
- uerror( "field outside of structure" );
- if( $3<0 || $3 >= FIELD ){
- uerror( "illegal field size" );
+ if (fldchk($3))
$3 = 1;
- }
if ($1->n_op == NAME) {
tymerge($<nodep>0, $1);
- $1->n_sp = getsymtab((char *)$1->n_sp,SMOSNAME);
- defid($1, FIELD|$3);
+ soumemb($1, (char *)$1->n_sp, FIELD | $3);
nfree($1);
} else
uerror("illegal declarator");
}
+ | /* unnamed member */ {
+ NODE *p = $<nodep>0;
+ char *c = permalloc(10);
+
+ if (p->n_type != STRTY && p->n_type != UNIONTY)
+ uerror("bad unnamed member type");
+ snprintf(c, 10, "*%dFAKE", getlab());
+ soumemb(p, c, 0);
+ }
;
/* always preceeded by attributes */
@@ -576,27 +646,29 @@
init_declarator: declarator { init_declarator($<nodep>0, $1, 0); }
| declarator C_ASM '(' string ')' {
#ifdef GCC_COMPAT
- renname = $4;
+ pragma_renamed = newstring($4, strlen($4));
init_declarator($<nodep>0, $1, 0);
#else
werror("gcc extension");
init_declarator($<nodep>0, $1, 0);
#endif
}
- | xnfdeclarator '=' e { simpleinit($1, $3); xnf = NULL; }
+ | xnfdeclarator '=' e { simpleinit($1, eve($3)); xnf = NULL; }
| xnfdeclarator '=' begbr init_list optcomma '}' {
endinit();
xnf = NULL;
}
+ /*COMPAT_GCC*/ | xnfdeclarator '=' begbr '}' { endinit(); xnf = NULL; }
| xnfdeclarator '=' addrlbl { simpleinit($1, $3); xnf = NULL; }
;
begbr: '{' { beginit($<symp>-1); }
;
-initializer: e %prec ',' { $$ = $1; }
+initializer: e %prec ',' { $$ = eve($1); }
| addrlbl { $$ = $1; }
| ibrace init_list optcomma '}' { $$ = NULL; }
+ | ibrace '}' { asginit(bcon(0)); $$ = NULL; }
;
init_list: designation initializer { asginit($2); }
@@ -611,8 +683,18 @@
| designator_list designator { $$ = $2; $$->n_left = $1; }
;
-designator: '[' con_e ']' { $$ = bdty(LB, NULL, $2); }
- | C_STROP C_NAME { $$ = bdty(NAME, $2); }
+designator: '[' con_e ']' {
+ if ($2 < 0) {
+ uerror("designator must be non-negative");
+ $2 = 0;
+ }
+ $$ = biop(LB, NIL, bcon($2));
+ }
+ | C_STROP C_NAME {
+ if ($1 != DOT)
+ uerror("invalid designator");
+ $$ = bdty(NAME, $2);
+ }
;
optcomma : /* VOID */
@@ -624,34 +706,8 @@
/* STATEMENTS */
-compoundstmt: begin declaration_list stmt_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 stmt_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;
- }
+compoundstmt: begin block_item_list '}' { flend(); }
+ | begin '}' { flend(); }
;
begin: '{' {
@@ -672,10 +728,13 @@
bc->contlab = autooff;
bc->next = savctx;
savctx = bc;
+ bccode();
+ if (sspflag && blevel == 2)
+ sspstart();
}
;
-statement: e ';' { ecomp( $1 ); }
+statement: e ';' { ecomp(eve($1)); symclear(blevel); }
| compoundstmt
| ifprefix statement { plabel($1); reached = 1; }
| ifelprefix statement {
@@ -698,9 +757,9 @@
if (flostat & FCONT)
reached = 1;
if (reached)
- cbranch($5, bcon($1));
+ cbranch(eve($5), bcon($1));
else
- tfree($5);
+ tfree(eve($5));
plabel( brklab);
reached = 1;
resetbc(0);
@@ -741,35 +800,37 @@
}
| 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->n_type = DECREF(temp->n_type);
- temp = buildtree(RETURN, temp, $2);
+ NODE *p;
- if (temp->n_type == VOID)
- ecomp(temp->n_right);
- else
- ecomp(buildtree(FORCE, temp->n_right, NIL));
- nfree(temp->n_left);
- nfree(temp);
+ p = nametree(cftnsp);
+ p->n_type = DECREF(p->n_type);
+ p = buildtree(RETURN, p, eve($2));
+ if (p->n_type == VOID) {
+ ecomp(p->n_right);
+ } else {
+ if (cftnod == NIL)
+ cftnod = tempnode(0, p->n_type,
+ p->n_df, p->n_sue);
+ ecomp(buildtree(ASSIGN,
+ tcopy(cftnod), p->n_right));
+ }
+ tfree(p->n_left);
+ nfree(p);
branch(retlab);
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, eve($3), NIL)); }
| asmstatement ';'
| ';'
| error ';'
@@ -777,18 +838,44 @@
| label statement
;
-asmstatement: C_ASM '(' string ')' { send_passt(IP_ASM, mkpstr($3)); }
+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); }
+ | ':' oplist ':' oplist { $$ = xcmop($2, $4, NIL); }
+ | ':' oplist ':' oplist ':' cnstr { $$ = xcmop($2, $4, $6); }
+ ;
+
+oplist: /* nothing */ { $$ = NIL; }
+ | oper { $$ = $1; }
;
+oper: string '(' e ')' { $$ = xasmop($1, eve($3)); }
+ | oper ',' string '(' e ')' {
+ $$ = cmop($1, xasmop($3, eve($5)));
+ }
+ ;
+
+cnstr: string { $$ = xasmop($1, bcon(0)); }
+ | cnstr ',' string { $$ = cmop($1, xasmop($3, bcon(0))); }
+ ;
+
label: C_NAME ':' { deflabel($1); reached = 1; }
- | C_CASE e ':' { addcase($2); reached = 1; }
+ | C_TYPENAME ':' { deflabel($1); reached = 1; }
+ | C_CASE e ':' { addcase(eve($2)); reached = 1; }
+/* COMPAT_GCC */| C_CASE e C_ELLIPSIS e ':' {
+ gcccase(eve($2), eve($4)); 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());
@@ -796,7 +883,7 @@
}
;
ifprefix: C_IF '(' e ')' {
- cbranch(buildtree(NOT, $3, NIL), bcon($$ = getlab()));
+ cbranch(buildtree(NOT, eve($3), NIL), bcon($$ = getlab()));
reached = 1;
}
;
@@ -812,8 +899,7 @@
whprefix: C_WHILE '(' e ')' {
savebc();
- if (!reached)
- werror("loop not entered at top");
+ $3 = eve($3);
if ($3->n_op == ICON && $3->n_lval != 0)
flostat = FLOOP;
plabel( contlab = getlab());
@@ -828,8 +914,18 @@
forprefix: C_FOR '(' .e ';' .e ';' {
if ($3)
ecomp($3);
- else if (!reached)
- werror("loop not entered at top");
+ savebc();
+ contlab = getlab();
+ brklab = getlab();
+ plabel( $$ = getlab());
+ reached = 1;
+ if ($5)
+ cbranch(buildtree(NOT, $5, NIL), bcon(brklab));
+ else
+ flostat |= FLOOP;
+ }
+ | C_FOR '(' incblev declaration .e ';' {
+ blevel--;
savebc();
contlab = getlab();
brklab = getlab();
@@ -841,182 +937,152 @@
flostat |= FLOOP;
}
;
-switchpart: C_SWITCH '(' e ')' {
+
+incblev: { blevel++; }
+ ;
+
+switchpart: C_SWITCH '(' e ')' {
NODE *p;
int num;
+ TWORD t;
savebc();
brklab = getlab();
- if ($3->n_type != INT) {
- /* must cast to integer */
- p = block(NAME, NIL, NIL, INT, 0, MKSUE(INT));
- p = buildtree(CAST, p, $3);
- $3 = p->n_right;
- nfree(p->n_left);
- nfree(p);
+ $3 = eve($3);
+ if (($3->n_type != BOOL && $3->n_type > ULONGLONG) ||
+ $3->n_type < CHAR) {
+ uerror("switch expression must have integer "
+ "type");
+ t = INT;
+ } else {
+ $3 = intprom($3);
+ t = $3->n_type;
}
-// ecomp( buildtree( FORCE, $3, NIL ) );
- p = tempnode(0, INT, 0, MKSUE(INT));
- num = p->n_lval;
+ p = tempnode(0, t, 0, MKSUE(t));
+ num = regno(p);
ecomp(buildtree(ASSIGN, p, $3));
branch( $$ = getlab());
- swstart(num);
+ swstart(num, t);
reached = 0;
}
;
/* EXPRESSIONS */
-con_e: { $<intval>$=instruct; instruct=0; } e %prec ',' {
- $$ = icons( $2 );
- instruct=$<intval>1;
+con_e: { $<rp>$ = rpole; rpole = NULL; } e %prec ',' {
+ $$ = icons(eve($2));
+ rpole = $<rp>1;
}
;
-nocon_e: { $<intval>$=instruct; instruct=0; } e %prec ',' {
- instruct=$<intval>1;
- $$ = $2;
+nocon_e: { $<rp>$ = rpole; rpole = NULL; } e %prec ',' {
+ rpole = $<rp>1;
+ $$ = eve($2);
}
;
-.e: e
+.e: e { $$ = eve($1); }
| { $$=0; }
;
-elist: e %prec ','
- | elist ',' e { $$ = buildtree(CM, $1, $3); }
+elist: { $$ = NIL; }
+ | e %prec ','
+ | elist ',' e { $$ = biop(CM, $1, $3); }
+ | elist ',' cast_type { /* hack for stdarg */
+ $3->n_op = TYPE;
+ $$ = biop(CM, $1, $3);
+ }
;
/*
* Precedence order of operators.
*/
-e: e ',' e { $$ = buildtree(COMOP, $1, $3); }
- | e '=' e { $$ = buildtree(ASSIGN, $1, $3); }
- | e C_ASOP e { $$ = buildtree($2, $1, $3); }
+e: e ',' e { $$ = biop(COMOP, $1, $3); }
+ | e '=' e { $$ = biop(ASSIGN, $1, $3); }
+ | e C_ASOP e { $$ = biop($2, $1, $3); }
| e '?' e ':' e {
- $$=buildtree(QUEST, $1, buildtree(COLON, $3, $5));
+ $$=biop(QUEST, $1, biop(COLON, $3, $5));
}
- | e C_OROR e { $$ = buildtree($2, $1, $3); }
- | e C_ANDAND e { $$ = buildtree($2, $1, $3); }
- | e '|' e { $$ = buildtree(OR, $1, $3); }
- | e '^' e { $$ = buildtree(ER, $1, $3); }
- | e '&' e { $$ = buildtree(AND, $1, $3); }
- | e C_EQUOP e { $$ = buildtree($2, $1, $3); }
- | e C_RELOP e { $$ = buildtree($2, $1, $3); }
- | e C_SHIFTOP e { $$ = buildtree($2, $1, $3); }
- | e '+' e { $$ = buildtree(PLUS, $1, $3); }
- | e '-' e { $$ = buildtree(MINUS, $1, $3); }
- | e C_DIVOP e { $$ = buildtree($2, $1, $3); }
- | e '*' e { $$ = buildtree(MUL, $1, $3); }
- | e '=' addrlbl { $$ = buildtree(ASSIGN, $1, $3); }
+ | e C_OROR e { $$ = biop($2, $1, $3); }
+ | e C_ANDAND e { $$ = biop($2, $1, $3); }
+ | e '|' e { $$ = biop(OR, $1, $3); }
+ | e '^' e { $$ = biop(ER, $1, $3); }
+ | e '&' e { $$ = biop(AND, $1, $3); }
+ | e C_EQUOP e { $$ = biop($2, $1, $3); }
+ | e C_RELOP e { $$ = biop($2, $1, $3); }
+ | e C_SHIFTOP e { $$ = biop($2, $1, $3); }
+ | e '+' e { $$ = biop(PLUS, $1, $3); }
+ | e '-' e { $$ = biop(MINUS, $1, $3); }
+ | e C_DIVOP e { $$ = biop($2, $1, $3); }
+ | e '*' e { $$ = biop(MUL, $1, $3); }
+ | e '=' addrlbl { $$ = biop(ASSIGN, $1, $3); }
| term
;
+xbegin: begin {
+ $$ = getlab(); getlab(); getlab();
+ branch($$); plabel(($$)+1); }
+ ;
+
addrlbl: C_ANDAND C_NAME {
#ifdef GCC_COMPAT
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) ){
-#ifdef notdef
- werror( "& before array or function: ignored" );
-#endif
- $$ = $2;
- } else
- $$ = buildtree(ADDROF, $2, NIL);
- }
- | '-' term { $$ = buildtree(UMINUS, $2, NIL ); }
+term: term C_INCOP { $$ = biop($2, $1, bcon(1)); }
+ | '*' term { $$ = biop(UMUL, $2, NIL); }
+ | '&' term { $$ = biop(ADDROF, $2, NIL); }
+ | '-' term { $$ = biop(UMINUS, $2, NIL ); }
| '+' term { $$ = $2; }
- | C_UNOP term { $$ = buildtree( $1, $2, NIL ); }
+ | C_UNOP term { $$ = biop($1, $2, NIL); }
| C_INCOP term {
- $$ = buildtree($1 == INCR ? PLUSEQ : MINUSEQ,
- $2, bcon(1));
+ $$ = biop($1 == INCR ? PLUSEQ : MINUSEQ, $2, bcon(1));
}
- | C_SIZEOF term { $$ = doszof($2); }
+ | C_SIZEOF term { $$ = biop(SZOF, $2, bcon(0)); }
| '(' cast_type ')' term %prec C_INCOP {
- $$ = buildtree(CAST, $2, $4);
- nfree($$->n_left);
- nfree($$);
- $$ = $$->n_right;
+ $$ = biop(CAST, $2, $4);
}
| C_SIZEOF '(' cast_type ')' %prec C_SIZEOF {
- $$ = doszof($3);
+ $$ = biop(SZOF, $3, bcon(1));
}
- | '(' cast_type ')' clbrace init_list '}' {
+ | '(' cast_type ')' clbrace init_list optcomma '}' {
+ uerror("compound literals");
endinit();
- spname = $4;
- $$ = buildtree(NAME, NIL, NIL);
- }
- | term '[' e ']' {
- $$ = buildtree( UMUL,
- buildtree( PLUS, $1, $3 ), NIL );
- }
- | funct_idn ')' { $$ = doacall($1, NIL); }
- | funct_idn elist ')' { $$ = doacall($1, $2); }
- | term C_STROP C_NAME { $$ = structref($1, $2, $3); }
- | term C_STROP C_TYPENAME { $$ = structref($1, $2, $3); }
- | C_NAME {
- spname = lookup($1, 0);
- /* recognize identifiers in initializations */
- if (blevel==0 && spname->stype == UNDEF) {
- register NODE *q;
- werror("undeclared initializer name %s",
- spname->sname);
- q = block(NAME, NIL, NIL, INT, 0, MKSUE(INT));
- q->n_sp = spname;
- defid(q, EXTERN);
- nfree(q);
- }
- if (spname->sflags & SINLINE)
- inline_ref($1);
- $$ = buildtree(NAME, NIL, NIL);
- spname->suse = -lineno;
- if (spname->sflags & SDYNARRAY)
- $$ = buildtree(UMUL, $$, NIL);
+ $$ = nametree($4);
}
+ | term '[' e ']' { $$ = biop(LB, $1, $3); }
+ | C_NAME '(' elist ')' {
+ $$ = biop($3 ? CALL : UCALL, bdty(NAME, $1), $3);
+ }
+ | term '(' elist ')' { $$ = biop($3 ? CALL : UCALL, $1, $3); }
+ | term C_STROP C_NAME { $$ = biop($2, $1, bdty(NAME, $3)); }
+ | term C_STROP C_TYPENAME { $$ = biop($2, $1, bdty(NAME, $3));}
+ | C_NAME %prec C_SIZEOF /* below ( */{ $$ = bdty(NAME, $1); }
| C_ICON { $$ = $1; }
| C_FCON { $$ = $1; }
- | string { $$ = strend($1); /* get string contents */ }
- | wstring { $$ = wstrend($1); }
+ | string { $$ = bdty(STRING, $1, widestr); }
| '(' e ')' { $$=$2; }
+ | '(' xbegin block_item_list e ';' '}' ')' {
+ branch(($2)+2);
+ plabel($2);
+ $$ = biop(COMOP, biop(GOTO, bcon(($2)+1), NIL), $4);
+ $$->n_type = $4->n_type; /* XXX type checking ? */
+ $$->n_sue = $4->n_sue; /* XXX type checking ? */
+ $$->n_df = $4->n_df; /* XXX type checking ? */
+ flend();
+ }
;
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 {
@@ -1027,25 +1093,9 @@
$$ = tymerge($1, $2);
nfree($1);
}
+ /*COMPAT_GCC*/ | typeof { $$ = $1; $$->n_op = NAME; }
;
-funct_idn: C_NAME '(' {
- struct symtab *s = lookup($1, 0);
- if (s->stype == UNDEF) {
- register NODE *q;
- q = block(NAME, NIL, NIL, FTN|INT, 0, MKSUE(INT));
- q->n_sp = s;
- defid(q, EXTERN);
- nfree(q);
- }
- if (s->sflags & SINLINE)
- inline_ref($1);
- spname = s;
- $$ = buildtree(NAME, NIL, NIL);
- s->suse = -lineno;
- }
- | term '('
- ;
%%
NODE *
@@ -1058,10 +1108,11 @@
bdty(int op, ...)
{
va_list ap;
+ int val;
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:
@@ -1077,13 +1128,22 @@
case LB:
q->n_left = va_arg(ap, NODE *);
- q->n_right = bcon(va_arg(ap, int));
+ if ((val = va_arg(ap, int)) <= 0) {
+ uerror("array size must be positive");
+ val = 1;
+ }
+ q->n_right = bcon(val);
break;
case NAME:
q->n_sp = va_arg(ap, struct symtab *); /* XXX survive tymerge */
break;
+ case STRING:
+ q->n_name = va_arg(ap, char *);
+ q->n_lval = va_arg(ap, int);
+ break;
+
default:
cerror("bad bdty");
}
@@ -1093,6 +1153,25 @@
}
static void
+flend(void)
+{
+ if (sspflag && blevel == 2)
+ sspend();
+#ifdef STABS
+ if (gflag && blevel > 2)
+ stabs_rbrac(blevel);
+#endif
+ --blevel;
+ if( blevel == 1 )
+ blevel = 0;
+ symclear(blevel); /* Clean ut the symbol table */
+ if (autooff > maxautooff)
+ maxautooff = autooff;
+ autooff = savctx->contlab;
+ savctx = savctx->next;
+}
+
+static void
savebc(void)
{
struct savbc *bc = tmpalloc(sizeof(struct savbc));
@@ -1120,6 +1199,7 @@
struct swents *ents; /* Linked sorted list of case entries */
int nents; /* # of entries in list */
int num; /* Node value will end up in */
+ TWORD type; /* Type of switch expression */
} *swpole;
/*
@@ -1128,7 +1208,8 @@
static void
addcase(NODE *p)
{
- struct swents *w, *sw = tmpalloc(sizeof(struct swents));
+ struct swents **put, *w, *sw = tmpalloc(sizeof(struct swents));
+ CONSZ val;
p = optim(p); /* change enum to ints */
if (p->n_op != ICON || p->n_sp != NULL) {
@@ -1140,40 +1221,55 @@
return;
}
+ 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;
- plabel( sw->slab = getlab());
- w = swpole->ents;
- if (swpole->ents == NULL) {
- sw->next = NULL;
- swpole->ents = sw;
- } else if (swpole->ents->next == NULL) {
- if (swpole->ents->sval == sw->sval) {
- uerror("duplicate case in switch");
- } else if (swpole->ents->sval < sw->sval) {
- sw->next = NULL;
- swpole->ents->next = sw;
- } else {
- sw->next = swpole->ents;
- swpole->ents = sw;
- }
+ tfree(p);
+ put = &swpole->ents;
+ if (ISUNSIGNED(swpole->type)) {
+ for (w = swpole->ents;
+ w != NULL && (U_CONSZ)w->sval < (U_CONSZ)sw->sval;
+ w = w->next)
+ put = &w->next;
} else {
- while (w->next->next != NULL && w->next->sval < sw->sval) {
- w = w->next;
- }
- if (w->next->sval == sw->sval) {
- uerror("duplicate case in switch");
- } else if (w->next->sval > sw->sval) {
- sw->next = w->next;
- w->next = sw;
- } else {
- sw->next = NULL;
- w->next->next = sw;
- }
+ for (w = swpole->ents; w != NULL && w->sval < sw->sval;
+ w = w->next)
+ put = &w->next;
}
+ if (w != NULL && w->sval == sw->sval) {
+ uerror("duplicate case in switch");
+ return;
+ }
+ plabel(sw->slab = getlab());
+ *put = sw;
+ sw->next = w;
swpole->nents++;
- tfree(p);
}
+#ifdef GCC_COMPAT
+void
+gcccase(NODE *ln, NODE *hn)
+{
+ CONSZ i, l, h;
+
+ l = icons(optim(ln));
+ h = icons(optim(hn));
+
+ if (h < l)
+ i = l, l = h, h = i;
+
+ for (i = l; i <= h; i++)
+ addcase(xbcon(i, NULL, hn->n_type));
+}
+#endif
+
/*
* add default case to switch
*/
@@ -1189,7 +1285,7 @@
}
static void
-swstart(int num)
+swstart(int num, TWORD type)
{
struct swdef *sw = tmpalloc(sizeof(struct swdef));
@@ -1197,6 +1293,7 @@
sw->ents = NULL;
sw->next = swpole;
sw->num = num;
+ sw->type = type;
swpole = sw;
}
@@ -1219,12 +1316,44 @@
swp[i] = swpole->ents;
swpole->ents = swpole->ents->next;
}
- genswitch(swpole->num, swp, swpole->nents);
+ genswitch(swpole->num, swpole->type, swp, swpole->nents);
swpole = swpole->next;
}
/*
+ * num: tempnode the value of the switch expression is in
+ * type: type of the switch expression
+ *
+ * p points to an array of structures, each consisting
+ * of a constant value and a label.
+ * The first is >=0 if there is a default label;
+ * its value is the label number
+ * The entries p[1] to p[n] are the nontrivial cases
+ * n is the number of case statements (length of list)
+ */
+static void
+genswitch(int num, TWORD type, struct swents **p, int n)
+{
+ NODE *r, *q;
+ int i;
+
+ if (mygenswitch(num, type, p, n))
+ return;
+
+ /* simple switch code */
+ for (i = 1; i <= n; ++i) {
+ /* already in 1 */
+ r = tempnode(num, type, 0, MKSUE(type));
+ q = xbcon(p[i]->sval, NULL, type);
+ r = buildtree(NE, r, clocal(q));
+ cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab));
+ }
+ if (p[0]->slab > 0)
+ branch(p[0]->slab);
+}
+
+/*
* Declare a variable or prototype.
*/
static struct symtab *
@@ -1240,10 +1369,11 @@
typ->n_sp->sflags |= SINLINE;
if (ISFTN(typ->n_type) == 0) {
- setloc1(DATA);
if (assign) {
defid(typ, class);
typ->n_sp->sflags |= SASG;
+ if (typ->n_sp->sflags & SDYNARRAY)
+ uerror("can't initialize dynamic arrays");
lcommdel(typ->n_sp);
} else {
nidcl(typ, class);
@@ -1258,6 +1388,24 @@
}
/*
+ * Declare function arguments.
+ */
+static void
+funargs(NODE *p)
+{
+ if (p->n_op == ELLIPSIS)
+ return;
+ if (oldstyle) {
+ p->n_op = TYPE;
+ p->n_type = FARG;
+ }
+ p->n_sp = lookup((char *)p->n_sp, 0);/* XXX */
+ if (ISFTN(p->n_type))
+ p->n_type = INCREF(p->n_type);
+ defid(p, PARAM);
+}
+
+/*
* Declare a function.
*/
static void
@@ -1265,14 +1413,29 @@
{
extern int prolab;
struct symtab *s;
+ NODE *q = p;
int class = tp->n_lval, oclass;
char *c;
- setloc1(PROG);
- /* Enter function args before they are clobbered in tymerge() */
- /* Typecheck against prototype will be done in defid(). */
- ftnarg(p);
+ 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);
+ }
+
+ 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 */
@@ -1280,26 +1443,22 @@
if (class == STATIC && oclass == EXTERN)
werror("%s was first declared extern, then static", s->sname);
- if ((oclass == SNULL || oclass == USTATIC) &&
- class == STATIC && fun_inline) {
- /* Unreferenced, store it for (eventual) later use */
- /* Ignore it if it not declared static */
+ if (fun_inline) {
+ /* special syntax for inline functions */
s->sflags |= SINLINE;
- inline_start(s->sname);
- }
- if (class == EXTERN)
+ inline_start(s);
+ if (class == EXTERN)
+ class = EXTDEF;
+ } else if (class == EXTERN)
class = SNULL; /* same result */
cftnsp = s;
defid(p, class);
prolab = getlab();
- c = cftnsp->sname;
-#ifdef GCC_COMPAT
- c = gcc_findname(cftnsp);
-#endif
- send_passt(IP_PROLOG, -1, -1, c, cftnsp->stype,
- cftnsp->sclass == EXTDEF, prolab);
- blevel = 1;
+ c = cftnsp->soname;
+ send_passt(IP_PROLOG, -1, c, cftnsp->stype,
+ cftnsp->sclass == EXTDEF, prolab, ctval);
+ blevel++;
#ifdef STABS
if (gflag)
stabs_func(s);
@@ -1326,9 +1485,10 @@
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;
- return buildtree(STREF, p, r);
+ r = buildtree(STREF, p, r);
+ return r;
}
static void
@@ -1351,7 +1511,7 @@
branch(int lbl)
{
int r = reached++;
- ecomp(block(GOTO, bcon(lbl), NIL, INT, 0, 0));
+ ecomp(biop(GOTO, bcon(lbl), NIL));
reached = r;
}
@@ -1362,9 +1522,10 @@
mkpstr(char *str)
{
char *s, *os;
- int v, l = strlen(str)+1;
+ 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++ == '\\')
v = esccon(&str);
@@ -1372,29 +1533,365 @@
v = str[-1];
*s++ = v;
}
+ *s++ = '\n';
*s = 0;
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)
{
struct symtab *sp;
- if (blevel == 0 && xnf != NULL)
- cerror("no level0 compound literals");
-
- sp = getsymtab("cl", STEMP);
+ sp = getsymtab(simname("cl"), STEMP);
+ if (blevel == 0 && xnf != NULL) {
+ sp->sclass = STATIC;
+ sp->slevel = 2;
+ sp->soffset = getlab();
+ } else {
+ sp->sclass = blevel ? AUTO : STATIC;
+ if (!ISARY(sp->stype) || sp->sdf->ddim != NOOFFSET) {
+ sp->soffset = NOOFFSET;
+ oalloc(sp, &autooff);
+ }
+ }
sp->stype = p->n_type;
sp->squal = p->n_qual;
sp->sdf = p->n_df;
sp->ssue = p->n_sue;
- sp->sclass = blevel ? AUTO : STATIC;
- if (!ISARY(sp->stype) || sp->sdf->ddim != 0) {
- sp->soffset = NOOFFSET;
- oalloc(sp, &autooff);
- }
tfree(p);
beginit(sp);
return sp;
}
+
+char *
+simname(char *s)
+{
+ int len = strlen(s) + 10 + 1;
+ char *w = tmpalloc(len);
+
+ snprintf(w, len, "%s%d", s, getlab());
+ return w;
+}
+
+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 biop(CM, l, r);
+}
+
+static NODE *
+voidcon(void)
+{
+ return block(ICON, NIL, NIL, STRTY, 0, MKSUE(VOID));
+}
+
+/* Support for extended assembler a' la' gcc style follows below */
+
+static NODE *
+xmrg(NODE *out, NODE *in)
+{
+ NODE *p = in;
+
+ if (p->n_op == XARG) {
+ in = cmop(out, p);
+ } else {
+ while (p->n_left->n_op == CM)
+ p = p->n_left;
+ p->n_left = cmop(out, p->n_left);
+ }
+ return in;
+}
+
+/*
+ * Put together in and out node lists in one list, and balance it with
+ * the constraints on the right side of a CM node.
+ */
+static NODE *
+xcmop(NODE *out, NODE *in, NODE *str)
+{
+ NODE *p, *q;
+
+ if (out) {
+ /* 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] != '=' && q->n_name[0] != '+')
+ uerror("output missing =");
+ }
+ if (p->n_name[0] != '=' && p->n_name[0] != '+')
+ uerror("output missing =");
+ if (in == NIL)
+ p = out;
+ else
+ p = xmrg(out, in);
+ } else if (in) {
+ p = in;
+ } else
+ p = voidcon();
+
+ if (str == NIL)
+ str = voidcon();
+ return cmop(p, str);
+}
+
+/*
+ * Generate a XARG node based on a string and an expression.
+ */
+static NODE *
+xasmop(char *str, NODE *p)
+{
+
+ p = biop(XARG, p, NIL);
+ p->n_name = isinlining ? newstring(str, strlen(str)+1) : str;
+ return p;
+}
+
+/*
+ * Generate a XASM node based on a string and an expression.
+ */
+static void
+mkxasm(char *str, NODE *p)
+{
+ NODE *q;
+
+ q = biop(XASM, p->n_left, p->n_right);
+ q->n_name = isinlining ? newstring(str, strlen(str)+1) : str;
+ nfree(p);
+ ecomp(q);
+}
+
+#ifdef GCC_COMPAT
+static NODE *
+tyof(NODE *p)
+{
+ static struct symtab spp;
+ NODE *q = block(TYPE, NIL, NIL, p->n_type, 0, 0);
+ q->n_qual = p->n_qual;
+ q->n_sp = &spp; /* for typenode */
+ tfree(p);
+ return q;
+}
+#endif
+
+/*
+ * Traverse an unhandled expression tree bottom-up and call buildtree()
+ * or equivalent as needed.
+ */
+NODE *
+eve(NODE *p)
+{
+ struct symtab *sp;
+ NODE *r, *p1, *p2;
+ r = NULL;
+
+ p1 = p->n_left;
+ p2 = p->n_right;
+ switch (p->n_op) {
+ case NAME:
+ sp = lookup((char *)p->n_sp, 0);
+ if (sp->sflags & SINLINE)
+ inline_ref(sp);
+ r = nametree(sp);
+ if (sp->sflags & SDYNARRAY)
+ r = buildtree(UMUL, r, NIL);
+ break;
+
+ case DOT:
+ case STREF:
+ r = structref(eve(p1), p->n_op, (char *)p2->n_sp);
+ nfree(p2);
+ break;
+
+ case CAST:
+ p1 = buildtree(CAST, p1, eve(p2));
+ nfree(p1->n_left);
+ r = p1->n_right;
+ nfree(p1);
+ break;
+
+
+ case SZOF:
+ if (p2->n_lval == 0)
+ p1 = eve(p1);
+ nfree(p2);
+ r = doszof(p1);
+ break;
+
+ case LB:
+ p1 = eve(p->n_left);
+ r = buildtree(UMUL, buildtree(PLUS, p1, eve(p2)), NIL);
+ break;
+
+ case COMPL:
+ case UMINUS:
+ case NOT:
+ case UMUL:
+ r = buildtree(p->n_op, eve(p->n_left), NIL);
+ break;
+
+ case ADDROF:
+ r = eve(p1);
+ if (ISFTN(p->n_type)/* || ISARY(p->n_type) */){
+#ifdef notdef
+ werror( "& before array or function: ignored" );
+#endif
+ } else
+ r = buildtree(ADDROF, r, NIL);
+ break;
+
+ case CALL:
+ p2 = eve(p2);
+ /* FALLTHROUGH */
+ case UCALL:
+ if (p1->n_op == NAME) {
+ sp = lookup((char *)p1->n_sp, 0);
+ if (sp->stype == UNDEF) {
+ p1->n_type = FTN|INT;
+ p1->n_sp = sp;
+ defid(p1, EXTERN);
+ }
+ nfree(p1);
+ r = doacall(sp, nametree(sp), p2);
+ } else
+ r = doacall(NULL, eve(p1), p2);
+ break;
+
+ case INCR:
+ case DECR:
+ case CM:
+ case GT:
+ case GE:
+ case LT:
+ case LE:
+ case EQ:
+ case NE:
+ case RS:
+ case LS:
+ case RSEQ:
+ case LSEQ:
+ case AND:
+ case OR:
+ case ER:
+ case MUL:
+ case DIV:
+ case MOD:
+ case PLUS:
+ case MINUS:
+ case OROR:
+ case ANDAND:
+ case EREQ:
+ case OREQ:
+ case ANDEQ:
+ case MINUSEQ:
+ case PLUSEQ:
+ case MULEQ:
+ case DIVEQ:
+ case MODEQ:
+ case COMOP:
+ case QUEST:
+ case COLON:
+ case ASSIGN:
+ p1 = eve(p1);
+ r = buildtree(p->n_op, p1, eve(p2));
+ break;
+
+ case STRING:
+ r = strend(p->n_lval, p->n_name);
+ break;
+
+ case TYPE:
+ case ICON:
+ case FCON:
+ return p;
+
+ default:
+#ifdef PCC_DEBUG
+ fwalk(p, eprint, 0);
+#endif
+ cerror("eve");
+ }
+ nfree(p);
+ return r;
+}
Index: ccom.1
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/ccom.1,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/ccom/ccom.1 -L usr.bin/pcc/ccom/ccom.1 -u -r1.1 -r1.2
--- usr.bin/pcc/ccom/ccom.1
+++ usr.bin/pcc/ccom/ccom.1
@@ -1,39 +1,43 @@
-.\" $Id: ccom.1,v 1.2 2007/09/26 14:48:49 ragge Exp $
.\" $NetBSD$
-.\" $OpenBSD$
+.\" $Id: ccom.1,v 1.8 2008/02/20 01:31:26 gmcgarry Exp $
."\
.\" Copyright (c) 2007 Jeremy C. Reed <reed at reedmedia.net>
-.\" Permission to use, copy, modify, and/or distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
+.\" Permission to use, copy, modify, and/or distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM
-.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
-.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND
-.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM
+.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND
+.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
.\" THIS SOFTWARE.
.Dd September 14, 2007
-.Dt ccom 1
+.Dt CCOM 1
.Os
.Sh NAME
.Nm ccom
.Nd C compiler
.Sh SYNOPSIS
.Nm
+.Op Fl gs
+.Op Fl W Ar flags
.Op Fl X Ar flags
+.Op Fl x Ar optimizations
+.Op Fl Z Ar flags
.Op infile
.Op outfile
-.Pp
.Sh DESCRIPTION
The
.Nm
utility provides a C compiler.
The frontend is usually
.Xr pcc 1 .
-It is \fBnot\fR intended to be run directly.
+It is
+.Em not
+intended to be run directly.
.Pp
.Nm
reads the C source from
@@ -48,6 +52,8 @@
.It Fl g
Enable debugging.
.\" built into binary, explain stabs?
+.It Fl k
+Generate PIC code.
.It Fl s
Print statistics to standard error when complete.
This includes:
@@ -56,81 +62,112 @@
dimension/function unions, struct/union/enum blocks, inline node count,
inline control blocks, and permanent symtab entries.
.\" TODO: explain units for above?
+.It Fl v
+Display version.
.It Fl W Ar flags
Report warnings.
(Do some basic checks.)
-NOTE! These are subject to change RSN!
-.Ar Flags
+.Em NOTE!
+.Em These are subject to change RSN!
+.Ar flags
is one or more of the following:
.Bl -tag -width Ds
+.It Sy error
+Report all warnings as errors.
.It Sy implicit
Implies
-.Sy implicit-int
+.Sy implicit-function-declaration
and
-.Sy implicit-function-declaration .
+.Sy implicit-int .
+.It Sy implicit-function-declaration
+Report if no prototype was declared for a function.
.It Sy implicit-int
TODO
-.It Sy implicit-function-declaration
-Report if no prototype for function.
.It Sy missing-prototypes
TODO
.It Sy strict-prototypes
TODO
+.It Sy W
+Enable all warnings.
+.El
+.\"
+.It Fl X Ar flags
+C specific debugging where
+.Ar flags
+is one or more of the following:
+.Bl -tag -width Ds
+.It Sy b
+Building of parse trees
+.It Sy d
+Declarations (using multiple
+.Sy d
+flags gives more output)
+.It Sy e
+Pass1 trees at exit
+.It Sy i
+Initializations
+.It Sy n
+Memory allocations
+.It Sy o
+Turn off optimisations
+.It Sy p
+Prototypes
+.It Sy s
+Inlining
+.It Sy t
+Type conversions
+.It Sy x
+Target-specific flag, used in machine-dependent code
.El
.\"
.It Fl x Ar optimizations
.Ar optimizations
-is one or more of the following:
+is one of the following:
+.\" TODO: reword this, since multiple terms don't go with one -x switch??
.Bl -tag -width deljumps
.It Sy deljumps
Delete redundant jumps and dead code.
.It Sy ssa
-Convert statements into SSA form for optimization. Not yet finished.
+Convert statements into SSA form for optimization.
+Not yet finished.
.It Sy tailcall
Currently not implemented.
.It Sy temps
-Setting this flag allow variables to be put into registers, for further
+Setting this flag allows variables to be put into registers, for further
optimization by the register allocator.
.El
+The
+.Fl x
+flag can be passed multiple times to set different options.
.\"
-.It Fl X Ar C specific debugging flags
-.Ar Flags
+.It Fl Z Ar flags
+Code generator (pass2) specific debugging where
+.Ar flags
is one or more of the following:
.Bl -tag -width Ds
.It Sy b
-Building of parse trees
-.It Sy d
-Declarations, more d gives more output
-.It Sy t
-Type conversions
-.It Sy i
-Initializations
-.It Sy e
-Pass1 trees at exit
-.It Sy x
-Target-specific flag, used in machine-dependent code
-.El
-.\"
-.It Fl Z Ar Code generator (pass2) specific debugging flags
-.Ar Flags
-is one or more of the following:
-.Bl -tag -width Ds
+Basic block and SSA building
+.It Sy c
+Code printout
.It Sy e
Trees when entering pass2
-.It Sy o
-Instruction generator
.It Sy f
Instruction matcher, may provide much output
+.It Sy n
+Memory allocation
+.It Sy o
+Instruction generator
.It Sy r
Register allocator
-.It Sy t
-Type matching in instruction generator
.It Sy s
Shape matching in instruction generator
+.It Sy t
+Type matching in instruction generator
.It Sy u
Sethi-Ullman computations
.It Sy x
-Target-specific flag, used in machine-dependent code
+Target-specific flag, used in machine-dependent code
+.El
.El
.Sh SEE ALSO
.Xr as 1 ,
@@ -139,8 +176,8 @@
.Sh HISTORY
The
.Nm
-compiler is based on the original Portable C Compiler by S. C.
-Johnson, written in the late 70's.
+compiler is based on the original Portable C Compiler by S. C. Johnson,
+written in the late 70's.
Even though much of the compiler has been rewritten, some of the
basics still remain.
About 50% of the frontend code and 80% of the backend code has been
@@ -148,5 +185,8 @@
Most is written by Anders Magnusson, with the exception of
the data-flow analysis part and the SSA conversion code which is
written by Peter A Jonsson, and the Mips port that were written as
-part of a project by undergraduate students at Lulea University of
+part of a project by undergraduate students at Lulea University of
Technology.
+.Pp
+This product includes software developed or owned by Caldera
+International, Inc.
Index: trees.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/trees.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/ccom/trees.c -L usr.bin/pcc/ccom/trees.c -u -r1.1 -r1.2
--- usr.bin/pcc/ccom/trees.c
+++ usr.bin/pcc/ccom/trees.c
@@ -1,4 +1,4 @@
-/* $Id: trees.c,v 1.163 2007/09/16 08:26:39 ragge Exp $ */
+/* $Id: trees.c,v 1.223 2008/12/14 21:15:24 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -70,14 +70,16 @@
# include "pass2.h"
# include <stdarg.h>
+# include <string.h>
static void chkpun(NODE *p);
static int opact(NODE *p);
static int moditype(TWORD);
static NODE *strargs(NODE *);
static void rmcops(NODE *p);
-
-int lastloc = -1;
+static void putjops(NODE *, void *);
+static struct symtab *findmember(struct symtab *, char *);
+int inftn; /* currently between epilog/prolog */
/* some special actions, used in finding the type of nodes */
# define NCVT 01
@@ -107,6 +109,8 @@
*/
int bdebug = 0;
+extern int negrel[];
+
NODE *
buildtree(int o, NODE *l, NODE *r)
@@ -116,8 +120,6 @@
int opty;
struct symtab *sp = NULL; /* XXX gcc */
NODE *lr, *ll;
- char *name;
- struct symtab **elem;
#ifdef PCC_DEBUG
if (bdebug) {
@@ -143,23 +145,23 @@
} else if (o == NOT && l->n_op == FCON) {
l = clocal(block(SCONV, l, NIL, INT, 0, MKSUE(INT)));
} else if( o == UMINUS && l->n_op == FCON ){
- l->n_dcon = -l->n_dcon;
+ l->n_dcon = FLOAT_NEG(l->n_dcon);
return(l);
} else if( o==QUEST && l->n_op==ICON ) {
CONSZ c = l->n_lval;
nfree(l);
if (c) {
+ walkf(r->n_right, putjops, 0);
tfree(r->n_right);
l = r->n_left;
- nfree(r);
- return(l);
} else {
+ walkf(r->n_left, putjops, 0);
tfree(r->n_left);
l = r->n_right;
- nfree(r);
- return(l);
}
+ nfree(r);
+ return(l);
} else if( opty == BITYPE && l->n_op == ICON && r->n_op == ICON ){
switch( o ){
@@ -199,9 +201,11 @@
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;
}
@@ -214,21 +218,24 @@
case MUL:
case DIV:
if (l->n_op == ICON)
- l->n_dcon = l->n_lval;
+ l->n_dcon = FLOAT_CAST(l->n_lval, l->n_type);
if (r->n_op == ICON)
- r->n_dcon = r->n_lval;
+ r->n_dcon = FLOAT_CAST(r->n_lval, r->n_type);
switch (o) {
case PLUS:
- l->n_dcon += r->n_dcon; break;
+ l->n_dcon = FLOAT_PLUS(l->n_dcon, r->n_dcon);
+ break;
case MINUS:
- l->n_dcon -= r->n_dcon; break;
+ l->n_dcon = FLOAT_MINUS(l->n_dcon, r->n_dcon);
+ break;
case MUL:
- l->n_dcon *= r->n_dcon; break;
+ l->n_dcon = FLOAT_MUL(l->n_dcon, r->n_dcon);
+ break;
case DIV:
- if (r->n_dcon == 0)
- uerror("division by 0.");
- else
- l->n_dcon /= r->n_dcon;
+ if (FLOAT_ISZERO(r->n_dcon))
+ goto runtime;
+ l->n_dcon = FLOAT_DIV(l->n_dcon, r->n_dcon);
+ break;
}
l->n_op = FCON;
l->n_type = DOUBLE;
@@ -237,7 +244,7 @@
return(l);
}
}
-
+runtime:
/* its real; we must make a new node */
p = block(o, l, r, INT, 0, MKSUE(INT));
@@ -247,6 +254,8 @@
if (actions & LVAL) { /* check left descendent */
if (notlval(p->n_left)) {
uerror("lvalue required");
+ nfree(p);
+ return l;
#ifdef notyet
} else {
if ((l->n_type > BTMASK && ISCON(l->n_qual)) ||
@@ -296,53 +305,7 @@
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_lval = 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;
- /* special case: MOETY is really an ICON... */
- if (p->n_type == MOETY) {
- p->n_sp = NULL;
- p->n_lval = sp->soffset;
- p->n_df = NULL;
- p->n_type = ENUMTY;
- p->n_op = ICON;
- }
- break;
+ cerror("buildtree NAME");
case STREF:
/* p->x turned into *(p+offset) */
@@ -354,17 +317,23 @@
break;
}
- if ((elem = l->n_sue->suelem) == NULL)
+ if ((sp = l->n_sue->sylnk) == NULL) {
uerror("undefined struct or union");
+ break;
+ }
+ sp = findmember(sp, r->n_name);
+#ifdef notdef
name = r->n_name;
- for (; *elem != NULL; elem++) {
- sp = *elem;
+ for (; sp != NULL; sp = sp->snext) {
if (sp->sname == name)
break;
}
- if (*elem == NULL)
- uerror("member '%s' not declared", name);
+#endif
+ if (sp == NULL) {
+ uerror("member '%s' not declared", r->n_name);
+ break;
+ }
r->n_sp = sp;
p = stref(p);
@@ -453,7 +422,7 @@
TWORD t;
union dimfun *d;
- if (l->n_sue != r->n_sue)
+ if (l->n_sue->sylnk != r->n_sue->sylnk)
uerror("assignment of different structures");
r = buildtree(ADDROF, r, NIL);
@@ -462,6 +431,7 @@
sue = r->n_sue;
l = block(STASG, l, r, t, d, sue);
+ l = clocal(l);
if( o == RETURN ){
nfree(p);
@@ -483,6 +453,8 @@
case CALL:
p->n_right = r = strargs(p->n_right);
+ p = funcode(p);
+ /* FALLTHROUGH */
case UCALL:
if (!ISPTR(l->n_type))
uerror("illegal function");
@@ -540,6 +512,88 @@
}
+/* Find a member in a struct or union. May be an unnamed member */
+static struct symtab *
+findmember(struct symtab *sp, char *s)
+{
+ struct symtab *sp2, *sp3;
+
+ for (; sp != NULL; sp = sp->snext) {
+ if (sp->sname[0] == '*') {
+ /* unnamed member, recurse down */
+ if ((sp2 = findmember(sp->ssue->sylnk, s))) {
+ sp3 = tmpalloc(sizeof (struct symtab));
+ *sp3 = *sp2;
+ sp3->soffset += sp->soffset;
+ return sp3;
+ }
+ } else if (sp->sname == s)
+ return sp;
+ }
+ return NULL;
+}
+
+
+/*
+ * Check if there will be a lost label destination inside of a ?:
+ * It cannot be reached so just print it out.
+ */
+static void
+putjops(NODE *p, void *arg)
+{
+ if (p->n_op == COMOP && p->n_left->n_op == GOTO)
+ plabel(p->n_left->n_left->n_lval+1);
+}
+
+/*
+ * 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.
*/
@@ -548,8 +602,10 @@
{
p = buildtree(CBRANCH, p, q);
if (p->n_left->n_op == ICON) {
- if (p->n_left->n_lval != 0)
+ if (p->n_left->n_lval != 0) {
branch(q->n_lval); /* branch always */
+ reached = 0;
+ }
tfree(p);
tfree(q);
return;
@@ -714,6 +770,7 @@
* we check that this integer is in fact a constant zero...
* in the case of ASSIGN, any assignment of pointer to integer is illegal
* this falls out, because the LHS is never 0.
+ * XXX - check for COMOPs in assignment RHS?
*/
void
chkpun(NODE *p)
@@ -743,8 +800,10 @@
return;
break;
default:
- if ((t1 == VOID && t2 != VOID) || (t1 != VOID && t2 == VOID))
- return uerror("value of void expression used");
+ if ((t1 == VOID && t2 != VOID) || (t1 != VOID && t2 == VOID)) {
+ uerror("value of void expression used");
+ return;
+ }
break;
}
@@ -754,26 +813,6 @@
if (BTYPE(t2) == VOID && (t1 & TMASK))
return;
-#ifdef notdef
- /* C99 says that enums always should be handled as ints */
- /* check for enumerations */
- if (t1==ENUMTY || t2==ENUMTY) {
- if( clogop( p->n_op ) && p->n_op != EQ && p->n_op != NE ) {
- werror( "comparison of enums" );
- return;
- }
- if (t1==ENUMTY && t2==ENUMTY) {
- if (p->n_left->n_sue!=p->n_right->n_sue)
- werror("enumeration type clash, "
- "operator %s", copst(p->n_op));
- return;
- }
- if ((t1 == ENUMTY && t2 <= BTMASK) ||
- (t2 == ENUMTY && t1 <= BTMASK))
- return;
- }
-#endif
-
if (ISPTR(t1) || ISARY(t1))
q = p->n_right;
else
@@ -786,7 +825,7 @@
d1 = p->n_left->n_df;
d2 = p->n_right->n_df;
if (t1 == t2) {
- if (p->n_left->n_sue != p->n_right->n_sue)
+ if (p->n_left->n_sue->sylnk != p->n_right->n_sue->sylnk)
werror("illegal structure pointer combination");
return;
}
@@ -815,7 +854,8 @@
t1 = DECREF(t1);
t2 = DECREF(t2);
}
- werror("illegal pointer combination");
+ if (Wpointer_sign)
+ werror("illegal pointer combination");
}
}
@@ -856,6 +896,21 @@
off = s->soffset;
dsc = s->sclass;
+#ifndef CAN_UNALIGN
+ /*
+ * If its a packed struct, and the target cannot do unaligned
+ * accesses, then split it up in two bitfield operations.
+ * LHS and RHS accesses are different, so must delay
+ * it until we know. Do the bitfield construct here though.
+ */
+ if ((dsc & FIELD) == 0 && (off % talign(s->stype, s->ssue))) {
+// int sz = tsize(s->stype, s->sdf, s->ssue);
+// int al = talign(s->stype, s->ssue);
+// int sz1 = al - (off % al);
+
+ }
+#endif
+
if (dsc & FIELD) { /* make fields look like ints */
off = (off/ALINT)*ALINT;
sue = MKSUE(INT);
@@ -911,12 +966,18 @@
NODE *
bcon(int i)
{
- register NODE *p;
+ return xbcon(i, NULL, INT);
+}
- p = block(ICON, NIL, NIL, INT, 0, MKSUE(INT));
- p->n_lval = i;
- p->n_sp = NULL;
- return(clocal(p));
+NODE *
+xbcon(CONSZ val, struct symtab *sp, TWORD type)
+{
+ NODE *p;
+
+ p = block(ICON, NIL, NIL, type, 0, MKSUE(type));
+ p->n_lval = val;
+ p->n_sp = sp;
+ return clocal(p);
}
NODE *
@@ -995,34 +1056,6 @@
return(p);
}
-/*
- * change enums to ints, or appropriate types
- */
-void
-econvert( p ) register NODE *p; {
-
-
- register TWORD ty;
-
- if( (ty=BTYPE(p->n_type)) == ENUMTY || ty == MOETY ) {
- if (p->n_sue->suesize == SZCHAR)
- ty = INT;
- else if (p->n_sue->suesize == SZINT)
- ty = INT;
- else if (p->n_sue->suesize == SZSHORT)
- ty = INT;
- else if (p->n_sue->suesize == SZLONGLONG)
- ty = LONGLONG;
- else
- ty = LONG;
- ty = ctype(ty);
- p->n_sue = MKSUE(ty);
- MODTYPE(p->n_type,ty);
- if (p->n_op == ICON && ty != LONG && ty != LONGLONG)
- p->n_type = INT, p->n_sue = MKSUE(INT);
- }
-}
-
NODE *
pconvert( p ) register NODE *p; {
@@ -1049,7 +1082,12 @@
case LT:
case GE:
case GT:
- if( ISUNSIGNED(p->n_left->n_type) || ISUNSIGNED(p->n_right->n_type) ) p->n_op += (ULE-LE);
+ if(ISUNSIGNED(p->n_left->n_type) ||
+ ISUNSIGNED(p->n_right->n_type) ||
+ ISPTR(p->n_left->n_type) ||
+ ISPTR(p->n_right->n_type))
+ p->n_op += (ULE-LE);
+ /* FALLTHROUGH */
case EQ:
case NE:
return( p );
@@ -1184,10 +1222,10 @@
t2 = DEUNSIGN(t2);
}
- if (t1 == ENUMTY || t1 == MOETY)
- t1 = INT; /* XXX */
- if (t2 == ENUMTY || t2 == MOETY)
- t2 = INT; /* XXX */
+ 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;
@@ -1266,8 +1304,6 @@
makety(NODE *p, TWORD t, TWORD q, union dimfun *d, struct suedef *sue)
{
- if (p->n_type == ENUMTY && p->n_op == ICON)
- econvert(p);
if (t == p->n_type) {
p->n_df = d;
p->n_sue = sue;
@@ -1294,10 +1330,7 @@
if (p->n_op == ICON) {
if (t == DOUBLE || t == FLOAT) {
p->n_op = FCON;
- if (ISUNSIGNED(p->n_type))
- p->n_dcon = (U_CONSZ) p->n_lval;
- else
- p->n_dcon = p->n_lval;
+ p->n_dcon = FLOAT_CAST(p->n_lval, p->n_type);
p->n_type = t;
p->n_qual = q;
p->n_sue = MKSUE(t);
@@ -1332,20 +1365,21 @@
return(p);
}
-int
-icons(p) register NODE *p; {
+/*
+ * Return the constant value from an ICON.
+ */
+CONSZ
+icons(NODE *p)
+{
/* if p is an integer constant, return its value */
- int val;
+ CONSZ val;
- if( p->n_op != ICON ){
+ if (p->n_op != ICON || p->n_sp != NULL) {
uerror( "constant expected");
val = 1;
- }
- else {
+ } else
val = p->n_lval;
- if( val != p->n_lval ) uerror( "constant too big for cross-compiler" );
- }
- tfree( p );
+ tfree(p);
return(val);
}
@@ -1382,7 +1416,6 @@
# define MSTR 04 /* structure */
# define MPTR 010 /* pointer */
# define MPTI 020 /* pointer or integer */
-# define MENU 040 /* enumeration variable or member */
int
opact(NODE *p)
@@ -1428,8 +1461,6 @@
case MUL:
case DIV:
- if ((mt1&MDBI) && (mt2&MENU)) return( TYMATCH );
- if ((mt2&MDBI) && (mt1&MENU)) return( TYMATCH );
if( mt12 & MDBI ) return( TYMATCH );
break;
@@ -1452,13 +1483,12 @@
case GT:
case GE:
if( mt12 & MDBI ) return( TYMATCH+CVTO );
- else if( mt12 & MPTR ) return( PTMATCH+PUN );
+ else if( mt12 & MPTR ) return( PTMATCH+PUN+CVTO );
else if( mt12 & MPTI ) return( PTMATCH+PUN );
else break;
case QUEST:
case COMOP:
- if( mt2&MENU ) return( TYPR+NCVTR );
return( TYPR );
case STREF:
@@ -1480,12 +1510,6 @@
if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
case CAST:
if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
-#if 0
- else if(mt1&MENU && mt2&MDBI) return( TYPL+LVAL+TYMATCH );
- else if(mt2&MENU && mt1&MDBI) return( TYPL+LVAL+TYMATCH );
- else if( (mt1&MENU)||(mt2&MENU) )
- return( LVAL+NCVT+TYPL+PTMATCH+PUN );
-#endif
else if( mt1 & MPTR) return( LVAL+PTMATCH+PUN );
else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
break;
@@ -1542,10 +1566,6 @@
{
switch (ty) {
- case ENUMTY:
- case MOETY:
- return( MENU|MINT|MDBI|MPTI );
-
case STRTY:
case UNIONTY:
return( MSTR );
@@ -1572,7 +1592,7 @@
}
}
-int tvaloff = 100;
+int tvaloff = MAXREGS+NPERMREG > 100 ? MAXREGS+NPERMREG + 100 : 100;
/*
* Returns a TEMP node with temp number nr.
@@ -1584,7 +1604,7 @@
NODE *r;
r = block(TEMP, NIL, NIL, type, df, sue);
- r->n_lval = nr ? nr : tvaloff;
+ regno(r) = nr ? nr : tvaloff;
tvaloff += szty(type);
return r;
}
@@ -1599,6 +1619,9 @@
TWORD ty;
NODE *rv;
+ if (p->n_op == FLD)
+ uerror("can't apply sizeof to bit-field");
+
/*
* Arrays may be dynamic, may need to make computations.
*/
@@ -1607,6 +1630,8 @@
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++;
@@ -1633,40 +1658,51 @@
ty = coptype( p->n_op );
printf("%p) %s, ", p, copst(p->n_op));
+ if (p->n_op == XARG || p->n_op == XASM)
+ printf("id '%s', ", p->n_name);
if (ty == LTYPE) {
printf(CONFMT, p->n_lval);
- printf(", %d, ", p->n_rval);
+ printf(", %d, ", (p->n_op != NAME && p->n_op != ICON) ?
+ p->n_rval : 0);
}
tprint(stdout, p->n_type, p->n_qual);
printf( ", %p, %p\n", p->n_df, p->n_sue );
}
# endif
-void
-prtdcon(NODE *p)
+/*
+ * Emit everything that should be emitted on the left side
+ * of a comma operator, and remove the operator.
+ * Do not traverse through QUEST, ANDAND and OROR.
+ * Enable this for all targets when stable enough.
+ */
+static void
+comops(NODE *p)
{
- int o = p->n_op, i;
-
- if (o != FCON)
- return;
-
- /* Write float constants to memory */
- /* Should be volontary per architecture */
+ int o;
+ NODE *q;
- setloc1(RDATA);
- defalign(p->n_type == FLOAT ? ALFLOAT : p->n_type == DOUBLE ?
- ALDOUBLE : ALLDOUBLE );
- deflab1(i = getlab());
- ninval(0, btdims[p->n_type].suesize, p);
- p->n_op = NAME;
- p->n_lval = 0;
- p->n_sp = tmpalloc(sizeof(struct symtab_hdr));
- p->n_sp->sclass = ILABEL;
- p->n_sp->soffset = i;
+ while (p->n_op == COMOP) {
+ /* XXX hack for GCC ({ }) ops */
+ if (p->n_left->n_op == GOTO) {
+ int v = p->n_left->n_left->n_lval;
+ ecomp(p->n_left);
+ plabel(v+1);
+ } else
+ ecomp(p->n_left); /* will recurse if more COMOPs */
+ q = p->n_right;
+ *p = *q;
+ nfree(q);
+ }
+ o = coptype(p->n_op);
+ if (p->n_op == QUEST || p->n_op == ANDAND || p->n_op == OROR)
+ o = UTYPE;
+ if (o != LTYPE)
+ comops(p->n_left);
+ if (o == BITYPE)
+ comops(p->n_right);
}
-extern int negrel[];
-
/*
* Walk up through the tree from the leaves,
* removing constant operators.
@@ -1815,6 +1851,7 @@
case ANDAND:
lab = false<0 ? getlab() : false ;
andorbr(p->n_left, -1, lab);
+ comops(p->n_right);
andorbr(p->n_right, true, false);
if (false < 0)
plabel( lab);
@@ -1824,6 +1861,7 @@
case OROR:
lab = true<0 ? getlab() : true;
andorbr(p->n_left, lab, -1);
+ comops(p->n_right);
andorbr(p->n_right, true, false);
if (true < 0)
plabel( lab);
@@ -1862,9 +1900,18 @@
NODE *q, *r;
int o, ty, lbl, lbl2, tval = 0;
-again:
o = p->n_op;
ty = coptype(o);
+ if (BTYPE(p->n_type) == ENUMTY) { /* fixup enum */
+ MODTYPE(p->n_type, p->n_sue->sylnk->stype);
+ /*
+ * XXX may fail if these are true:
+ * - variable-sized enums
+ * - non-byte-addressed targets.
+ */
+ if (BTYPE(p->n_type) == ENUMTY && ISPTR(p->n_type))
+ MODTYPE(p->n_type, INT); /* INT ok? */
+ }
switch (o) {
case QUEST:
@@ -1878,9 +1925,10 @@
/* Make ASSIGN node */
/* Only if type is not void */
q = p->n_right->n_left;
+ comops(q);
if (type != VOID) {
r = tempnode(0, q->n_type, q->n_df, q->n_sue);
- tval = r->n_lval;
+ tval = regno(r);
q = buildtree(ASSIGN, r, q);
}
rmcops(q);
@@ -1889,6 +1937,7 @@
plabel( lbl);
q = p->n_right->n_right;
+ comops(q);
if (type != VOID) {
r = tempnode(tval, q->n_type, q->n_df, q->n_sue);
q = buildtree(ASSIGN, r, q);
@@ -1927,7 +1976,7 @@
*r = *p;
andorbr(r, -1, lbl = getlab());
q = tempnode(0, p->n_type, p->n_df, p->n_sue);
- tval = q->n_lval;
+ tval = regno(q);
r = tempnode(tval, p->n_type, p->n_df, p->n_sue);
ecode(buildtree(ASSIGN, q, bcon(1)));
branch(lbl2 = getlab());
@@ -1945,13 +1994,7 @@
p->n_op = ICON; p->n_type = VOID;
break;
case COMOP:
- rmcops(p->n_left);
- ecode(p->n_left);
- /* Now when left tree is dealt with, rm COMOP */
- q = p->n_right;
- *p = *p->n_right;
- nfree(q);
- goto again;
+ cerror("COMOP error");
default:
if (ty == LTYPE)
@@ -1994,7 +2037,7 @@
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);
@@ -2009,7 +2052,7 @@
if (has_se(l)) {
q = tempnode(0, ll->n_type, ll->n_df, ll->n_sue);
- tval = q->n_lval;
+ tval = regno(q);
r = tempnode(tval, ll->n_type, ll->n_df,ll->n_sue);
l->n_left = q;
/* Now the left side of node p has no side effects. */
@@ -2052,19 +2095,21 @@
fwalk(p, eprint, 0);
#endif
if (!reached) {
- werror("statement not reached");
+ if (Wunreachable_code)
+ werror("statement not reached");
reached = 1;
}
p = optim(p);
+ comops(p);
rmcops(p);
p = delasgop(p);
- setloc1(PROG);
if (p->n_op == ICON && p->n_type == VOID)
tfree(p);
else
ecode(p);
}
+
#if defined(MULTIPASS)
void
p2tree(NODE *p)
@@ -2072,9 +2117,7 @@
struct symtab *q;
int ty;
-# ifdef MYP2TREE
- MYP2TREE(p); /* local action can be taken here; then return... */
-# endif
+ myp2tree(p); /* local action can be taken here */
ty = coptype(p->n_op);
@@ -2101,11 +2144,10 @@
case ICON:
/* print external name */
if ((q = p->n_sp) != NULL) {
- if ((q->sclass == STATIC && q->slevel > 0) ||
- q->sclass == ILABEL) {
+ if ((q->sclass == STATIC && q->slevel > 0)) {
printf(LABFMT, q->soffset);
} else
- printf("%s\n", exname(q->sname));
+ printf("%s\n", exname(q->soname));
} else
printf("\n");
break;
@@ -2125,6 +2167,10 @@
printf("\t%d\t\n", talign(STRTY, p->n_left->n_sue));
break;
+ case XARG:
+ case XASM:
+ break;
+
default:
printf( "\n" );
}
@@ -2135,15 +2181,24 @@
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)
{
struct symtab *q;
int ty;
-# ifdef MYP2TREE
- MYP2TREE(p); /* local action can be taken here; then return... */
-# endif
+ myp2tree(p); /* local action can be taken here */
ty = coptype(p->n_op);
@@ -2154,23 +2209,19 @@
if ((q = p->n_sp) != NULL) {
if ((q->sclass == STATIC && q->slevel > 0) ||
#ifdef GCC_COMPAT
- q->sflags == SLBLNAME ||
+ 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 {
-#ifdef GCC_COMPAT
- p->n_name = gcc_findname(q);
-#else
- p->n_name = exname(q->sname);
-#endif
- }
+ } else
+ p->n_name = q->soname;
} else
p->n_name = "";
break;
@@ -2198,6 +2249,10 @@
p->n_stalign = talign(STRTY,p->n_left->n_sue)/SZCHAR;
break;
+ case XARG:
+ case XASM:
+ break;
+
default:
p->n_name = "";
}
@@ -2212,7 +2267,7 @@
* Change void data types into char.
*/
static void
-delvoid(NODE *p)
+delvoid(NODE *p, void *arg)
{
/* Convert "PTR undef" (void *) to "PTR uchar" */
if (BTYPE(p->n_type) == VOID)
@@ -2227,7 +2282,7 @@
*q = *p;
q->n_type = BOOL_TYPE;
r = tempnode(0, BOOL_TYPE, NULL, MKSUE(BOOL_TYPE));
- val = r->n_lval;
+ val = regno(r);
s = tempnode(val, BOOL_TYPE, NULL, MKSUE(BOOL_TYPE));
*p = *s;
q = buildtree(ASSIGN, r, q);
@@ -2250,8 +2305,7 @@
p = optim(p);
p = delasgop(p);
- walkf(p, prtdcon);
- walkf(p, delvoid);
+ walkf(p, delvoid, 0);
#ifdef PCC_DEBUG
if (xdebug) {
printf("Fulltree:\n");
@@ -2282,26 +2336,28 @@
else
sz = sizeof(struct interpass);
- ip = isinlining ? permalloc(sz) : tmpalloc(sz);
+ ip = inlalloc(sz);
ip->type = type;
ip->lineno = lineno;
switch (type) {
case IP_NODE:
- if (lastloc != PROG)
- setloc1(PROG);
ip->ip_node = va_arg(ap, NODE *);
break;
case IP_EPILOG:
+ if (!isinlining)
+ defloc(cftnsp);
+ /* FALLTHROUGH */
case IP_PROLOG:
- setloc1(PROG);
+ inftn = type == IP_PROLOG ? 1 : 0;
ipp = (struct interpass_prolog *)ip;
- ipp->ipp_regs = va_arg(ap, int);
+ memset(ipp->ipp_regs, (type == IP_PROLOG)? -1 : 0,
+ sizeof(ipp->ipp_regs));
ipp->ipp_autos = va_arg(ap, int);
ipp->ipp_name = va_arg(ap, char *);
ipp->ipp_type = va_arg(ap, TWORD);
ipp->ipp_vis = va_arg(ap, int);
ip->ip_lbl = va_arg(ap, int);
- ipp->ip_tmpnum = tvaloff;
+ ipp->ip_tmpnum = va_arg(ap, int);
ipp->ip_lblnum = crslab;
if (type == IP_PROLOG)
ipp->ip_lblnum--;
@@ -2311,9 +2367,11 @@
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);
- lastloc = -1;
+ defloc(NULL);
return;
}
ip->ip_asm = va_arg(ap, char *);
@@ -2322,12 +2380,11 @@
cerror("bad send_passt type %d", type);
}
va_end(ap);
+ pass1_lastchance(ip); /* target-specific info */
if (isinlining)
inline_addarg(ip);
else
pass2_compile(ip);
- if (type == IP_EPILOG)
- lastloc = PROG;
}
char *
@@ -2363,6 +2420,8 @@
SNAM(RSEQ,>>=)
SNAM(INCR,++)
SNAM(DECR,--)
+ SNAM(STRING,STRING)
+ SNAM(SZOF,SIZEOF)
default:
cerror("bad copst %d", op);
}
@@ -2375,6 +2434,7 @@
if (op <= MAXOP)
return dope[op];
switch (op) {
+ case STRING:
case QUALIFIER:
case CLASS:
case RB:
@@ -2415,6 +2475,7 @@
case DECR:
return BITYPE|ASGFLG;
}
+ cerror("cdope missing op %d", op);
return 0; /* XXX gcc */
}
@@ -2445,7 +2506,45 @@
void
plabel(int label)
{
- setloc1(PROG);
reached = 1; /* Will this always be correct? */
send_passt(IP_DEFLAB, label);
}
+
+/*
+ * Perform integer promotion on node n.
+ */
+NODE *
+intprom(NODE *n)
+{
+ if ((n->n_type >= CHAR && n->n_type < INT) || n->n_type == BOOL) {
+ if ((n->n_type == UCHAR && MAX_UCHAR > MAX_INT) ||
+ (n->n_type == USHORT && MAX_USHORT > MAX_INT))
+ return makety(n, UNSIGNED, 0, 0, MKSUE(UNSIGNED));
+ return makety(n, INT, 0, 0, MKSUE(INT));
+ }
+ return n;
+}
+
+/*
+ * Return CON/VOL/0, whichever are active for the current type.
+ */
+int
+cqual(TWORD t, TWORD q)
+{
+ while (ISARY(t))
+ t = DECREF(t), q = DECQAL(q);
+ if (t <= BTMASK)
+ q <<= TSHIFT;
+ return q & (CON|VOL);
+}
+
+int crslab = 10;
+/*
+ * Return a number for internal labels.
+ */
+int
+getlab(void)
+{
+ return crslab++;
+}
+
Index: stabs.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/stabs.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/ccom/stabs.c -L usr.bin/pcc/ccom/stabs.c -u -r1.1 -r1.2
--- usr.bin/pcc/ccom/stabs.c
+++ usr.bin/pcc/ccom/stabs.c
@@ -1,4 +1,4 @@
-/* $Id: stabs.c,v 1.15 2007/09/15 07:37:44 ragge Exp $ */
+/* $Id: stabs.c,v 1.27 2008/12/08 21:39:50 gmcgarry Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson (ragge at ludd.luth.se).
@@ -39,18 +39,31 @@
#ifdef STABS
#include <sys/types.h>
-#include <stab.h>
#include <stdarg.h>
#include <string.h>
#define STABHASH 256
#define INTNUM 1 /* internal number of type "int" */
+#undef BIT2BYTE /* from external.h */
#define BIT2BYTE(x) ((x)/SZCHAR)
#ifndef STABLBL
#error macdefs.h must define STABLBL
#endif
+/* defines taken from BSD <stab.h> */
+#define N_GSYM 0x20 /* global symbol */
+#define N_FUN 0x24 /* procedure name */
+#define N_LCSYM 0x28 /* bss segment variable */
+#define N_RSYM 0x40 /* register variable */
+#define N_SLINE 0x44 /* text segment line number */
+#define N_SO 0x64 /* main source file name */
+#define N_LSYM 0x80 /* stack variable */
+#define N_SOL 0x84 /* included source file name */
+#define N_PSYM 0xa0 /* parameter variable */
+#define N_LBRAC 0xc0 /* left bracket */
+#define N_RBRAC 0xe0 /* right bracket */
+
/*
* Local type mapping
* Types are defined as a typeword, a dimension pointer (in the case
@@ -67,6 +80,7 @@
static int ntypes;
static char *curfun;
static int stablbl = 10;
+extern int inftn;
void ptype(char *name, int num, int inhnum, long long min, long long max);
struct stabtype *addtype(TWORD, union dimfun *, struct suedef *);
@@ -77,7 +91,6 @@
#define MAXPSTR 100
extern int isinlining;
-#define savestabs isinlining
/*
* Output type definitions for the stab debugging format.
@@ -109,7 +122,7 @@
ptype("double", ADDTYPE(DOUBLE)->num, INTNUM, 8, 0);
ptype("long double", ADDTYPE(LDOUBLE)->num, INTNUM, 12, 0);
st = ADDTYPE(VOID);
- cprint(savestabs, ".stabs \"void:t%d=r%d\",%d,0,0,0\n",
+ cprint(0, "\t.stabs \"void:t%d=r%d\",%d,0,0,0\n",
st->num, st->num, N_LSYM);
}
@@ -120,7 +133,7 @@
void
ptype(char *name, int num, int inhnum, long long min, long long max)
{
- cprint(savestabs, ".stabs \"%s:t%d=r%d;%lld;%lld;\",%d,0,0,0",
+ cprint(0, "\t.stabs \"%s:t%d=r%d;%lld;%lld;\",%d,0,0,0\n",
name, num, inhnum, min, max, N_LSYM);
}
@@ -183,8 +196,16 @@
void
stabs_line(int line)
{
- cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s", N_SLINE, line, stablbl, curfun);
- cprint(1, STABLBL ":", stablbl++);
+ if (inftn == 0)
+ return; /* ignore */
+#ifdef STAB_LINE_ABSOLUTE
+ cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n",
+ N_SLINE, line, stablbl, stablbl);
+#else
+ cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n",
+ N_SLINE, line, stablbl, exname(curfun), stablbl);
+#endif
+ stablbl++;
}
/*
@@ -193,9 +214,14 @@
void
stabs_lbrac(int blklvl)
{
- cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s",
- N_LBRAC, blklvl, stablbl, curfun);
- cprint(1, STABLBL ":", stablbl++);
+#ifdef STAB_LINE_ABSOLUTE
+ cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n",
+ N_LBRAC, blklvl, stablbl, stablbl);
+#else
+ cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n",
+ N_LBRAC, blklvl, stablbl, exname(curfun), stablbl);
+#endif
+ stablbl++;
}
/*
@@ -204,24 +230,40 @@
void
stabs_rbrac(int blklvl)
{
- cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s\n",
- N_RBRAC, blklvl, stablbl, curfun);
- cprint(1, STABLBL ":", stablbl++);
+#ifdef STAB_LINE_ABSOLUTE
+ cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n",
+ N_RBRAC, blklvl, stablbl, stablbl);
+#else
+ cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n",
+ N_RBRAC, blklvl, stablbl, exname(curfun), stablbl);
+#endif
+ stablbl++;
}
+static char *mainfile;
+
/*
* Print current file and set mark.
*/
void
stabs_file(char *fname)
{
- static char *mainfile;
-
if (mainfile == NULL)
mainfile = fname; /* first call */
- cprint(savestabs, ".stabs \"%s\",%d,0,0," STABLBL,
- fname, fname == mainfile ? N_SO : N_SOL, stablbl);
- cprint(savestabs, STABLBL ":", stablbl++);
+ cprint(inftn, "\t.stabs \"%s\",%d,0,0," STABLBL "\n" STABLBL ":\n",
+ fname, fname == mainfile ? N_SO : N_SOL, stablbl, stablbl);
+ stablbl++;
+}
+
+/*
+ * Print end mark
+ */
+void
+stabs_efile(char *fname)
+{
+ cprint(inftn, "\t.stabs \"\",%d,0,0," STABLBL "\n" STABLBL ":\n",
+ fname == mainfile ? N_SO : N_SOL, stablbl, stablbl);
+ stablbl++;
}
/*
@@ -232,12 +274,9 @@
{
char str[MAXPSTR];
- curfun = s->sname;
-#ifdef GCC_COMPAT
- curfun = gcc_findname(cftnsp);
-#endif
+ curfun = s->soname;
printtype(s, str, sizeof(str));
- cprint(savestabs, ".stabs \"%s:%c%s\",%d,0,%d,%s",
+ cprint(1, "\t.stabs \"%s:%c%s\",%d,0,%d,%s\n",
curfun, s->sclass == STATIC ? 'f' : 'F', str,
N_FUN, BIT2BYTE(s->ssue->suesize), exname(curfun));
}
@@ -286,8 +325,10 @@
void
stabs_newsym(struct symtab *s)
{
+ extern int fun_inline;
char *sname;
char ostr[MAXPSTR];
+ int suesize;
if (ISFTN(s->stype))
return; /* functions are handled separate */
@@ -297,43 +338,48 @@
s->sclass == TYPEDEF || (s->sclass & FIELD))
return; /* XXX - fix structs */
- sname = s->sname;
-#ifdef GCC_COMPAT
- sname = gcc_findname(s);
-#endif
+ sname = s->soname;
+ suesize = BIT2BYTE(s->ssue->suesize);
+ if (suesize > 32767)
+ suesize = 32767;
+ else if (suesize < -32768)
+ suesize = -32768;
printtype(s, ostr, sizeof(ostr));
switch (s->sclass) {
case PARAM:
- cprint(savestabs, ".stabs \"%s:p%s\",%d,0,%d,%d", sname, ostr,
- N_PSYM, BIT2BYTE(s->ssue->suesize), BIT2BYTE(s->soffset));
+ cprint(0, "\t.stabs \"%s:p%s\",%d,0,%d,%d\n", sname, ostr,
+ N_PSYM, suesize, BIT2BYTE(s->soffset));
break;
case AUTO:
- cprint(savestabs, ".stabs \"%s:%s\",%d,0,%d,%d", sname, ostr,
- N_LSYM, BIT2BYTE(s->ssue->suesize), BIT2BYTE(s->soffset));
+ cprint(0, "\t.stabs \"%s:%s\",%d,0,%d,%d\n", sname, ostr,
+ N_LSYM, suesize, BIT2BYTE(s->soffset));
break;
case STATIC:
if (blevel)
- cprint(savestabs, ".stabs \"%s:V%s\",%d,0,%d," LABFMT, sname, ostr,
- N_LCSYM, BIT2BYTE(s->ssue->suesize), s->soffset);
+ cprint(0, "\t.stabs \"%s:V%s\",%d,0,%d," LABFMT "\n", sname, ostr,
+ N_LCSYM, suesize, s->soffset);
else
- cprint(savestabs, ".stabs \"%s:S%s\",%d,0,%d,%s", sname, ostr,
- N_LCSYM, BIT2BYTE(s->ssue->suesize), exname(sname));
+ cprint(0, "\t.stabs \"%s:S%s\",%d,0,%d,%s\n", sname, ostr,
+ N_LCSYM, suesize, exname(sname));
break;
case EXTERN:
case EXTDEF:
- cprint(savestabs, ".stabs \"%s:G%s\",%d,0,%d,0", sname, ostr,
- N_GSYM, BIT2BYTE(s->ssue->suesize));
+ cprint(0, "\t.stabs \"%s:G%s\",%d,0,%d,0\n", sname, ostr,
+ N_GSYM, suesize);
break;
case REGISTER:
- cprint(savestabs, ".stabs \"%s:r%s\",%d,0,%d,%d", sname, ostr,
+ cprint(0, "\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);
}
@@ -352,22 +398,54 @@
{
}
-void
+struct stabsv {
+ SLIST_ENTRY(stabsv) next;
+ char *str;
+} ;
+static SLIST_HEAD(, stabsv) stpole = { NULL, &stpole.q_forw };
+
+/*
+ * Global variable debug info is printed out directly.
+ * For functions and their declarations, both the labels and
+ * the debug info is put into ASM nodes and follows their statements
+ * into pass2.
+ * Due to the possible unsync between pass1 and 2 and where the
+ * stabs info for text is sent over the following syncing is used:
+ * curfun == 0
+ * print out everything; only data will be.
+ * curfun != 0 && inftn == 0
+ * save in linked list
+ * curfun != 0 && inftn != 0
+ * print linked list first, empty it, then arg.
+ */
+void
cprint(int p2, char *fmt, ...)
{
- va_list ap;
+ struct stabsv *w;
+ 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);
- str = newstring(str, strlen(str)); /* XXX - for inlines */
- send_passt(IP_ASM, str);
- } else {
- putchar('\t');
+ if (inftn == 0) {
+ w = tmpalloc(sizeof(struct stabsv));
+ w->str = str;
+ SLIST_INSERT_LAST(&stpole, w, next);
+ } else {
+ if (stpole.q_last != &stpole.q_forw) {
+ SLIST_FOREACH(w, &stpole, next) {
+ send_passt(IP_ASM, w->str);
+ }
+ SLIST_INIT(&stpole);
+ }
+ send_passt(IP_ASM, str);
+ }
+ } else
vprintf(fmt, ap);
- putchar('\n');
- }
va_end(ap);
}
Index: symtabs.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/symtabs.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/ccom/symtabs.c -L usr.bin/pcc/ccom/symtabs.c -u -r1.1 -r1.2
--- usr.bin/pcc/ccom/symtabs.c
+++ usr.bin/pcc/ccom/symtabs.c
@@ -1,4 +1,4 @@
-/* $Id: symtabs.c,v 1.14 2006/06/16 09:30:32 ragge Exp $ */
+/* $Id: symtabs.c,v 1.18 2008/06/19 08:05:00 gmcgarry Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -175,15 +175,15 @@
* 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 cix, bit, fbit, svbit, ix, bitno, match;
+ int cix, bit, fbit, svbit, bitno;
int type, uselvl;
+ intptr_t ix, match, code = (intptr_t)key;
- long code = (long)key;
- type = ttype & SMASK;
+ type = stype & SMASK;
uselvl = (blevel > 0 && type != SSTRING);
/*
@@ -197,15 +197,15 @@
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];
@@ -228,12 +228,12 @@
}
sym = (struct symtab *)w;
- match = (long)sym->sname;
+ match = (intptr_t)sym->sname;
ix = code ^ match;
if (ix == 0)
return sym;
- else if (ttype & SNOCREAT)
+ else if (stype & SNOCREAT)
return NULL;
#ifdef PCC_DEBUG
@@ -246,7 +246,7 @@
* Insert into the linked list, if feasible.
*/
if (uselvl) {
- sym = getsymtab(key, ttype|STEMP);
+ sym = getsymtab(key, stype|STEMP);
sym->snext = tmpsyms[type];
tmpsyms[type] = sym;
return sym;
@@ -258,17 +258,17 @@
* 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);
@@ -343,10 +343,15 @@
hide(struct symtab *sym)
{
struct symtab *new;
+ int typ = sym->sflags & SMASK;
+
+ new = getsymtab(sym->sname, typ|STEMP);
+ new->snext = tmpsyms[typ];
+ tmpsyms[typ] = new;
+
+ if (Wshadow)
+ werror("declaration of '%s' shadows previous", sym->sname);
- new = getsymtab(sym->sname, SNORMAL|STEMP);
- new->snext = tmpsyms[SNORMAL];
- tmpsyms[SNORMAL] = new;
#ifdef PCC_DEBUG
if (ddebug)
printf("\t%s hidden at level %d (%p -> %p)\n",
Index: optim.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/optim.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/ccom/optim.c -L usr.bin/pcc/ccom/optim.c -u -r1.1 -r1.2
--- usr.bin/pcc/ccom/optim.c
+++ usr.bin/pcc/ccom/optim.c
@@ -1,4 +1,4 @@
-/* $Id: optim.c,v 1.28 2006/07/11 07:54:29 ragge Exp $ */
+/* $Id: optim.c,v 1.32 2008/10/27 21:13:20 ragge Exp $ */
/*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
@@ -43,8 +43,6 @@
# define LO(p) p->n_left->n_op
# define LV(p) p->n_left->n_lval
-static int nncon(NODE *);
-
int oflag = 0;
/* remove left node */
@@ -92,7 +90,7 @@
int i;
TWORD t;
- if( (t=BTYPE(p->n_type))==ENUMTY || t==MOETY ) econvert(p);
+ t = BTYPE(p->n_type);
if( oflag ) return(p);
ty = coptype(p->n_op);
@@ -137,7 +135,8 @@
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);
@@ -334,7 +333,21 @@
p->n_op = revrel[p->n_op - EQ ];
break;
+#ifdef notyet
+ case ASSIGN:
+ /* Simple test to avoid two branches */
+ if (RO(p) != NE)
+ break;
+ q = p->n_right;
+ if (RCON(q) && RV(q) == 0 && LO(q) == AND &&
+ RCON(q->n_left) && (i = ispow2(RV(q->n_left))) &&
+ q->n_left->n_type == INT) {
+ q->n_op = RS;
+ RV(q) = i;
}
+ break;
+#endif
+ }
return(p);
}
Index: Makefile
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccom/Makefile,v
retrieving revision 1.2
retrieving revision 1.3
diff -L usr.bin/pcc/ccom/Makefile -L usr.bin/pcc/ccom/Makefile -u -r1.2 -r1.3
--- usr.bin/pcc/ccom/Makefile
+++ usr.bin/pcc/ccom/Makefile
@@ -14,8 +14,8 @@
CFLAGS+= -Dmach_${TARGMACH}
CFLAGS+= -DPCC_DEBUG -DGCC_COMPAT
CFLAGS+= -Wall -Wmissing-prototypes -Wstrict-prototypes -Werror
-CFLAGS+= -I. -I${.CURDIR}/.. -I${.CURDIR} -I${.CURDIR}/../mip
-CFLAGS+= -I${.CURDIR}/../${TARGMACH}
+CFLAGS+= -I. -I${.CURDIR}/.. -I${.CURDIR}
+CFLAGS+= -I${.CURDIR}/../${TARGMACH} -I${.CURDIR}/../mip
.PATH: ${.CURDIR}/../${TARGMACH}
.PATH: ${.CURDIR}/../mip
Index: scanner.l
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/cpp/scanner.l,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/cpp/scanner.l -L usr.bin/pcc/cpp/scanner.l -u -r1.1 -r1.2
--- usr.bin/pcc/cpp/scanner.l
+++ usr.bin/pcc/cpp/scanner.l
@@ -1,5 +1,5 @@
%{
-/* $Id: scanner.l,v 1.20 2007/09/25 20:41:07 ragge Exp $ */
+/* $Id: scanner.l,v 1.48 2008/08/21 16:32:40 ragge Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson. All rights reserved.
@@ -27,19 +27,25 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
+
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <fcntl.h>
+#include <errno.h>
+#include "compat.h"
#include "cpp.h"
#include "y.tab.h"
%}
%{
-static long long cvtdig(int rad);
-static int charcon(void);
+static void cvtdig(int rad);
+static int charcon(usch *);
static void elsestmt(void);
static void ifdefstmt(void);
static void ifndefstmt(void);
@@ -50,8 +56,8 @@
static void undefstmt(void);
static void cpperror(void);
static void elifstmt(void);
-//static void linestmt(void);
static void storepb(void);
+static void badop(const char *);
void include(void);
void define(void);
@@ -82,15 +88,17 @@
}
#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);
@@ -108,6 +116,9 @@
#define unput(ch) unch(ch)
#endif
#define PRTOUT(x) if (YYSTATE || slow) return x; if (!flslvl) putstr((usch *)yytext);
+/* protection against recursion in #include */
+#define MAX_INCLEVEL 100
+static int inclevel;
%}
D [0-9]
@@ -118,7 +129,7 @@
IS (u|U|l|L)*
WS [\t ]
-%s IFR CONTR DEF
+%s IFR CONTR DEF COMMENT
%%
@@ -139,6 +150,8 @@
"\r" { ; /* Ignore CR's */ }
+<IFR>"++" { badop("++"); }
+<IFR>"--" { badop("--"); }
<IFR>"==" { return EQ; }
<IFR>"!=" { return NE; }
<IFR>"<=" { return LE; }
@@ -160,28 +173,41 @@
<IFR>{WS}+ { ; }
<IFR>{L}({L}|{D})* {
+ yylval.node.op = NUMBER;
if (gotdef) {
- yylval.val =
- lookup((usch *)yytext, FIND) != 0;
+ yylval.node.nd_val
+ = lookup((usch *)yytext, FIND) != 0;
gotdef = 0;
return IDENT;
}
- yylval.val = 0;
+ yylval.node.nd_val = 0;
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)
- yylval.val = cvtdig(scale);
+ num: if (YYSTATE == IFR)
+ cvtdig(scale);
PRTOUT(NUMBER);
}
0{D}+{IS}? { scale = 8; goto num; }
{D}+{IS}? { scale = 10; goto num; }
-L?'(\\.|[^\\'])+' { if (YYSTATE)
- yylval.val = charcon();
- PRTOUT(NUMBER);
+'(\\.|[^\\'])+' {
+ if (YYSTATE || slow) {
+ yylval.node.op = NUMBER;
+ yylval.node.nd_val = charcon((usch *)yytext);
+ return (NUMBER);
+ }
+ if (tflag)
+ yyless(1);
+ if (!flslvl)
+ putstr((usch *)yytext);
}
<IFR>. { return yytext[0]; }
@@ -190,7 +216,14 @@
{D}*"."{D}+({E})?{FS}? { PRTOUT(FPOINT); }
{D}+"."{D}*({E})?{FS}? { PRTOUT(FPOINT); }
-^{WS}*#{WS}* { contr = 1; BEGIN CONTR; }
+^{WS}*#{WS}* { extern int inmac;
+
+ if (inmac)
+ error("preprocessor directive found "
+ "while expanding macro");
+ contr = 1;
+ BEGIN CONTR;
+ }
{WS}+ { PRTOUT(WSPACE); }
<CONTR>"ifndef" { contr = 0; ifndefstmt(); }
@@ -203,19 +236,25 @@
<CONTR>"define" { contr = 0; BEGIN DEF; define(); BEGIN 0; }
<CONTR>"undef" { contr = 0; if (slow) return IDENT; undefstmt(); }
<CONTR>"line" { contr = 0; storepb(); BEGIN 0; line(); }
-<CONTR>"pragma" { contr = 0; pragmastmt(); }
+<CONTR>"pragma" { contr = 0; pragmastmt(); BEGIN 0; }
<CONTR>"elif" { contr = 0; storepb(); BEGIN IFR; elifstmt(); BEGIN 0; }
"//".*$ { /* if (tflag) yyless(..) */
- if (Cflag)
+ if (Cflag && !flslvl && !slow)
putstr((usch *)yytext);
else if (!flslvl)
putch(' ');
}
"/*" { int c, wrn;
- if (Cflag)
+ 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 != '*') {
@@ -223,20 +262,18 @@
putch(c), ifiles->lineno++;
else if (c == 1) /* WARN */
wrn = 1;
- else if (Cflag)
+ else if (prtcm)
putch(c);
}
if (c == 0)
return 0;
- if (Cflag)
+ if (prtcm)
putch(c);
if ((c = input()) && c != '/') {
- if (Cflag)
- putch('*');
unput(c);
goto more;
}
- if (Cflag)
+ if (prtcm)
putch(c);
if (c == 0)
return 0;
@@ -280,7 +317,31 @@
xx: ;
}
-. { PRTOUT(yytext[0]); }
+. {
+ if (contr) {
+ while (input() != '\n')
+ ;
+ unput('\n');
+ BEGIN 0;
+ contr = 0;
+ goto yy;
+ }
+ 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]);
+ }
+ yy:;
+ }
%%
@@ -393,25 +454,26 @@
/*
* A new file included.
* If ifiles == NULL, this is the first file and already opened (stdin).
- * Return 0 on success, -1 on failure to open file.
+ * Return 0 on success, -1 if file to be included is not found.
*/
int
pushfile(usch *file)
{
extern struct initar *initar;
struct includ ibuf;
- struct includ *old;
struct includ *ic;
int c, otrulvl;
ic = &ibuf;
- old = ifiles;
+ ic->next = ifiles;
slow = 0;
if (file != NULL) {
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");
} else {
ic->infil = 0;
ic->orgfn = ic->fname = (usch *)"<stdin>";
@@ -438,8 +500,9 @@
if (otrulvl != trulvl || flslvl)
error("unterminated conditional");
- ifiles = old;
+ ifiles = ic->next;
close(ic->infil);
+ inclevel--;
return 0;
}
@@ -458,7 +521,7 @@
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;
}
@@ -468,7 +531,7 @@
{
#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);
}
@@ -488,13 +551,13 @@
}
/*
- * Convert some string numbers to long long.
- * Do not care about UL trailers, should we?
+ * Convert string numbers to unsigned long long and check overflow.
*/
-static long long
+static void
cvtdig(int rad)
{
- long long rv = 0;
+ unsigned long long rv = 0;
+ unsigned long long rv2 = 0;
char *y = yytext;
int c;
@@ -503,20 +566,30 @@
y++;
while (isxdigit(c)) {
rv = rv * rad + dig2num(c);
+ /* check overflow */
+ if (rv / rad < rv2)
+ error("Constant \"%s\" is out of range", yytext);
+ rv2 = rv;
c = *y++;
}
- return rv;
+ y--;
+ while (*y == 'l' || *y == 'L')
+ y++;
+ yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
+ yylval.node.nd_uval = rv;
+ if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
+ yylval.node.op = UNUMBER;
+ if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
+ /* too large for signed */
+ error("Constant \"%s\" is out of range", yytext);
}
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++) {
@@ -553,14 +626,24 @@
}
static void
-chknl(void)
+chknl(int ignore)
{
int t;
+ slow = 1;
while ((t = yylex()) == WSPACE)
;
- if (t != '\n')
- error("newline expected, got %d", t);
+ if (t != '\n') {
+ if (ignore) {
+ warning("newline expected, got \"%s\"", yytext);
+ /* ignore rest of line */
+ while ((t = yylex()) && t != '\n')
+ ;
+ }
+ else
+ error("newline expected, got \"%s\"", yytext);
+ }
+ slow = 0;
}
static void
@@ -583,12 +666,14 @@
if (elslvl==trulvl+flslvl)
error("Too many else");
elslvl=trulvl+flslvl;
- chknl();
+ chknl(1);
}
static void
ifdefstmt(void)
{
+ int t;
+
if (flslvl) {
/* just ignore the rest of the line */
while (input() != '\n')
@@ -599,28 +684,36 @@
return;
}
slow = 1;
- if (yylex() != WSPACE || yylex() != IDENT)
+ do
+ t = yylex();
+ while (t == WSPACE);
+ if (t != IDENT)
error("bad ifdef");
slow = 0;
if (flslvl == 0 && lookup((usch *)yytext, FIND) != 0)
trulvl++;
else
flslvl++;
- chknl();
+ chknl(0);
}
static void
ifndefstmt(void)
{
+ int t;
+
slow = 1;
- if (yylex() != WSPACE || yylex() != IDENT)
+ do
+ t = yylex();
+ while (t == WSPACE);
+ if (t != IDENT)
error("bad ifndef");
slow = 0;
if (flslvl == 0 && lookup((usch *)yytext, FIND) == 0)
trulvl++;
else
flslvl++;
- chknl();
+ chknl(0);
}
static void
@@ -637,7 +730,7 @@
if (flslvl == 0)
elflvl = 0;
elslvl = 0;
- chknl();
+ chknl(1);
}
/*
@@ -694,8 +787,24 @@
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;
+ } else if (c == '/') {
+ while ((c = input()) && c != '\n')
+ ;
+ break;
+ }
+ unput(c);
+ c = '/';
+ }
savch(c);
+ }
cunput('\n');
savch(0);
fixdefined(opb); /* XXX can fail if #line? */
@@ -779,7 +888,7 @@
if (flslvl)
stringbuf = cp;
else
- error("error: %s", cp);
+ error("%s", cp);
}
static void
@@ -793,7 +902,7 @@
if (flslvl == 0 && (np = lookup((usch *)yytext, FIND)))
np->value = 0;
slow = 0;
- chknl();
+ chknl(0);
}
static void
@@ -804,11 +913,26 @@
slow = 1;
if (yylex() != WSPACE)
error("bad pragma");
- putstr((usch *)"#pragma ");
+ if (!flslvl)
+ putstr((usch *)"#pragma ");
do {
- putch(c = input()); /* Do arg expansion instead? */
+ c = input();
+ if (!flslvl)
+ putch(c); /* Do arg expansion instead? */
} while (c && c != '\n');
ifiles->lineno++;
prtline();
slow = 0;
}
+
+static void
+badop(const char *op)
+{
+ error("invalid operator in preprocessor expression: %s", op);
+}
+
+int
+cinput()
+{
+ return input();
+}
Index: token.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/cpp/token.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/cpp/token.c -L usr.bin/pcc/cpp/token.c -u -r1.1 -r1.2
--- usr.bin/pcc/cpp/token.c
+++ usr.bin/pcc/cpp/token.c
@@ -1,4 +1,4 @@
-/* $Id: token.c,v 1.11 2006/09/28 11:10:08 ragge Exp $ */
+/* $Id: token.c,v 1.12 2008/04/15 09:54:23 gmcgarry Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson. All rights reserved.
@@ -35,17 +35,7 @@
#include "cpp.h"
/* definition for include file info */
-struct includ {
- struct includ *next;
- char *fname;
- int lineno;
- int infil;
- usch *curptr;
- usch *maxread;
- usch *ostr;
- usch *buffer;
- usch bbuf[NAMEMAX+CPPBUF+1];
-} *ifiles;
+struct includ *ifiles;
usch *yyp, *yystr, yybuf[CPPBUF];
Index: cpp.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/cpp/cpp.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L usr.bin/pcc/cpp/cpp.c -L usr.bin/pcc/cpp/cpp.c -u -r1.3 -r1.4
--- usr.bin/pcc/cpp/cpp.c
+++ usr.bin/pcc/cpp/cpp.c
@@ -1,4 +1,4 @@
-/* $Id: cpp.c,v 1.65 2007/09/25 20:41:08 ragge Exp $ */
+/* $Id: cpp.c,v 1.95 2008/12/07 20:12:05 gmcgarry Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson (ragge at ludd.luth.se).
@@ -66,24 +66,24 @@
* from V7 cpp, and at last ansi/c99 support.
*/
-#include "../config.h"
+#include "config.h"
+#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
+#endif
#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
-#include <unistd.h>
#include <ctype.h>
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
-
+#include "compat.h"
#include "cpp.h"
#include "y.tab.h"
@@ -103,12 +103,15 @@
#define DDPRINT(x)
#endif
+#define GCC_VARI
+
int ofd;
usch outbuf[CPPBUF];
-int obufp, istty;
-int Cflag, Mflag, dMflag;
+int obufp, istty, inmac;
+int Cflag, Mflag, dMflag, Pflag;
usch *Mfile;
struct initar *initar;
+int readmac;
/* avoid recursion */
struct recur {
@@ -149,6 +152,7 @@
* 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 */
@@ -156,6 +160,8 @@
#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
@@ -168,6 +174,9 @@
void line(void);
void flbuf(void);
void usage(void);
+usch *xstrdup(char *str);
+usch *prtprag(usch *opb);
+
int
main(int argc, char **argv)
@@ -177,7 +186,13 @@
struct symtab *nl;
register int ch;
- while ((ch = getopt(argc, argv, "CD:I:MS:U:d:i:tvV?")) != -1)
+#ifdef TIMING
+ struct timeval t1, t2;
+
+ (void)gettimeofday(&t1, NULL);
+#endif
+
+ while ((ch = getopt(argc, argv, "CD:I:MPS:U:d:i:tvV?")) != -1)
switch (ch) {
case 'C': /* Do not discard comments */
Cflag++;
@@ -199,6 +214,10 @@
Mflag++;
break;
+ case 'P': /* Inhibit generation of line numbers */
+ Pflag++;
+ break;
+
case 'S':
case 'I':
if ((w = calloc(sizeof(struct incs), 1)) == NULL)
@@ -219,7 +238,7 @@
break;
#endif
case 'v':
- printf("pcpp: %s\n", VERSSTR);
+ printf("cpp: %s\n", VERSSTR);
break;
case 'd':
if (optarg[0] == 'M') {
@@ -267,6 +286,10 @@
nl = lookup((usch *)"__STDC__", ENTER);
savch(0); savch('1'); savch(OBJCT);
nl->value = stringbuf-1;
+
+ nl = lookup((usch *)"__STDC_VERSION__", ENTER);
+ savch(0); savstr((usch *)"199901L"); savch(OBJCT);
+ nl->value = stringbuf-1;
}
if (Mflag && !dMflag) {
@@ -298,6 +321,17 @@
flbuf();
close(ofd);
+#ifdef TIMING
+ (void)gettimeofday(&t2, NULL);
+ t2.tv_sec -= t1.tv_sec;
+ t2.tv_usec -= t1.tv_usec;
+ if (t2.tv_usec < 0) {
+ t2.tv_usec += 1000000;
+ t2.tv_sec -= 1;
+ }
+ fprintf(stderr, "cpp total time: %ld s %ld us\n",
+ t2.tv_sec, t2.tv_usec);
+#endif
return 0;
}
@@ -315,6 +349,7 @@
thisnl = NULL;
slow = 1;
+ readmac++;
base = osp = stringbuf;
goto found;
@@ -377,6 +412,10 @@
thisnl = NULL;
break;
+ case CMNT:
+ getcmnt();
+ break;
+
case STRING:
case '\n':
case NUMBER:
@@ -394,11 +433,12 @@
}
if (thisnl == NULL) {
slow = 0;
+ readmac--;
savch(0);
return base;
}
}
- error("preamture EOF");
+ error("premature EOF");
/* NOTREACHED */
return NULL; /* XXX gcc */
}
@@ -423,7 +463,7 @@
slow = 0;
return;
}
- if (yylex() != STRING)
+ if (yylex() != STRING || yytext[0] == 'L')
goto bad;
c = strlen((char *)yytext);
if (llen < c) {
@@ -550,6 +590,55 @@
}
void
+getcmnt(void)
+{
+ int c;
+
+ savstr((usch *)yytext);
+ for (;;) {
+ c = cinput();
+ if (c == '*') {
+ c = cinput();
+ if (c == '/') {
+ savstr((usch *)"*/");
+ return;
+ }
+ cunput(c);
+ c = '*';
+ }
+ savch(c);
+ }
+}
+
+/*
+ * Compare two replacement lists, taking in account comments etc.
+ */
+static int
+cmprepl(usch *o, usch *n)
+{
+ for (; *o; o--, n--) {
+ /* comment skip */
+ if (*o == '/' && o[-1] == '*') {
+ while (*o != '*' || o[-1] != '/')
+ o--;
+ o -= 2;
+ }
+ if (*n == '/' && n[-1] == '*') {
+ while (*n != '*' || n[-1] != '/')
+ n--;
+ n -= 2;
+ }
+ while (*o == ' ' || *o == '\t')
+ o--;
+ while (*n == ' ' || *n == '\t')
+ n--;
+ if (*o != *n)
+ return 1;
+ }
+ return 0;
+}
+
+void
define()
{
struct symtab *np;
@@ -557,7 +646,10 @@
int c, i, redef;
int mkstr = 0, narg = -1;
int ellips = 0;
- int len;
+#ifdef GCC_VARI
+ usch *gccvari = NULL;
+ int wascon;
+#endif
if (flslvl)
return;
@@ -571,12 +663,13 @@
np = lookup((usch *)yytext, ENTER);
redef = np->value != NULL;
+ readmac = 1;
sbeg = stringbuf;
if ((c = yylex()) == '(') {
narg = 0;
/* function-like macros, deal with identifiers */
+ c = definp();
for (;;) {
- c = definp();
if (c == ')')
break;
if (c == ELLIPS) {
@@ -586,15 +679,27 @@
break;
}
if (c == IDENT) {
- len = strlen(yytext);
- args[narg] = alloca(len+1);
- strlcpy((char *)args[narg], yytext, len+1);
- narg++;
- if ((c = definp()) == ',')
+ /* make sure there is no arg of same name */
+ for (i = 0; i < narg; i++)
+ if (!strcmp((char *) args[i], yytext))
+ error("Duplicate macro "
+ "parameter \"%s\"", yytext);
+ 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;
- goto bad;
}
goto bad;
}
@@ -608,9 +713,17 @@
while (c == WSPACE)
c = yylex();
+ /* replacement list cannot start with ## operator */
+ if (c == CONCAT)
+ goto bad;
+
/* 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 */
@@ -622,6 +735,12 @@
savch(CONC);
if ((c = yylex()) == WSPACE)
c = yylex();
+#ifdef GCC_VARI
+ if (c == '\n')
+ break;
+ wascon = 1;
+ goto loop;
+#endif
}
continue;
@@ -630,7 +749,14 @@
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) {
@@ -655,6 +781,16 @@
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;
@@ -674,31 +810,40 @@
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')
stringbuf--;
+ /* replacement list cannot end with ## operator */
+ else if (stringbuf[-1] == CONC)
+ goto bad;
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 */
@@ -726,12 +871,31 @@
}
#endif
slow = 0;
+ for (i = 0; i < narg; i++)
+ free(args[i]);
return;
bad: error("bad define");
}
void
+xwarning(usch *s)
+{
+ usch *t;
+ usch *sb = stringbuf;
+
+ flbuf();
+ savch(0);
+ if (ifiles != NULL) {
+ t = sheap("%s:%d: warning: ", ifiles->fname, ifiles->lineno);
+ write (2, t, strlen((char *)t));
+ }
+ write (2, s, strlen((char *)s));
+ write (2, "\n", 1);
+ stringbuf = sb;
+}
+
+void
xerror(usch *s)
{
usch *t;
@@ -739,7 +903,7 @@
flbuf();
savch(0);
if (ifiles != NULL) {
- t = sheap("%s:%d: ", ifiles->fname, ifiles->lineno);
+ t = sheap("%s:%d: error: ", ifiles->fname, ifiles->lineno);
write (2, t, strlen((char *)t));
}
write (2, s, strlen((char *)s));
@@ -751,7 +915,7 @@
* store a character into the "define" buffer.
*/
void
-savch(c)
+savch(int c)
{
if (stringbuf-sbf < SBSIZE) {
*stringbuf++ = c;
@@ -768,10 +932,9 @@
pragoper(void)
{
usch *opb;
- int t;
+ int t, plev;
- slow = 1;
- putstr((usch *)"\n#pragma ");
+ slow++;
if ((t = yylex()) == WSPACE)
t = yylex();
if (t != '(')
@@ -779,29 +942,37 @@
if ((t = yylex()) == WSPACE)
t = yylex();
opb = stringbuf;
- while (t != ')') {
+ for (plev = 0; ; t = yylex()) {
+ if (t == '(')
+ plev++;
+ if (t == ')')
+ plev--;
+ if (plev < 0)
+ break;
savstr((usch *)yytext);
- t = yylex();
}
+
savch(0);
cunput(WARN);
unpstr(opb);
stringbuf = opb;
expmac(NULL);
+ cunput('\n');
while (stringbuf > opb)
cunput(*--stringbuf);
- if ((t = yylex()) != STRING)
- goto bad;
- opb = (usch *)yytext;
- if (*opb++ == 'L')
- opb++;
- while ((t = *opb++) != '\"') {
- if (t == '\\' && (*opb == '\"' || *opb == '\\'))
- t = *opb++;
- putch(t);
+ savch(PRAGS);
+ while ((t = yylex()) != '\n') {
+ if (t == WSPACE)
+ continue;
+ if (t != STRING)
+ goto bad;
+ savstr((usch *)yytext);
}
- putch('\n');
- prtline();
+
+ savch(PRAGE);
+ while (stringbuf > opb)
+ cunput(*--stringbuf);
+ slow--;
return;
bad: error("bad pragma operator");
}
@@ -815,8 +986,8 @@
struct recur *rp;
{
struct recur rp2;
- register usch *vp, *cp;
- int c, rv = 0, ws;
+ register usch *vp, *cp, *obp;
+ int c, nl;
DPRINT(("subst: %s\n", sp->namep));
/*
@@ -842,40 +1013,36 @@
/* should we be here at all? */
/* check if identifier is followed by parentheses */
- rv = 1;
- ws = 0;
+
+ obp = stringbuf;
+ nl = 0;
do {
- c = yylex();
+ c = cinput();
+ *stringbuf++ = c;
if (c == WARN) {
gotwarn++;
if (rp == NULL)
- goto noid;
- } else if (c == WSPACE || c == '\n')
- ws = 1;
- } while (c == WSPACE || c == '\n' || c == WARN);
-
- cp = (usch *)yytext;
- while (*cp)
- cp++;
- while (cp > (usch *)yytext)
- cunput(*--cp);
+ break;
+ }
+ if (c == '\n')
+ nl++;
+ } while (c == ' ' || c == '\t' || c == '\n' ||
+ c == '\r' || c == WARN);
+
DPRINT(("c %d\n", c));
if (c == '(' ) {
+ cunput(c);
+ stringbuf = obp;
+ ifiles->lineno += nl;
expdef(vp, &rp2, gotwarn);
- return rv;
+ return 1;
} else {
- /* restore identifier */
-noid: while (gotwarn--)
- cunput(WARN);
- if (ws)
- cunput(' ');
- cp = sp->namep;
- while (*cp)
- cp++;
- while (cp > sp->namep)
- cunput(*--cp);
+ *stringbuf = 0;
+ unpstr(obp);
+ unpstr(sp->namep);
if ((c = yylex()) != IDENT)
error("internal sync error");
+ stringbuf = obp;
return 0;
}
} else {
@@ -903,18 +1070,18 @@
struct symtab *nl;
int c, noexp = 0, orgexp;
usch *och, *stksv;
- extern int yyleng;
#ifdef CPP_DEBUG
if (dflag) {
struct recur *rp2 = rp;
printf("\nexpmac\n");
while (rp2) {
- printf("do not expand %s\n", rp->sp->namep);
+ printf("do not expand %s\n", rp2->sp->namep);
rp2 = rp2->next;
}
}
#endif
+ readmac++;
while ((c = yylex()) != WARN) {
switch (c) {
case NOEXP: noexp++; break;
@@ -940,7 +1107,8 @@
else
orgexp++;
- DDPRINT(("id1: noexp %d orgexp %d\n", noexp, orgexp));
+ DDPRINT(("id1: typ %d noexp %d orgexp %d\n",
+ c, noexp, orgexp));
if (c == IDENT) { /* XXX numbers? */
DDPRINT(("id2: str %s\n", yytext));
/* OK to always expand here? */
@@ -974,6 +1142,8 @@
unpstr((usch *)yytext);
if (orgexp == -1)
cunput(EXPAND);
+ else if (orgexp == -2)
+ cunput(EXPAND), cunput(EXPAND);
else if (orgexp == 1)
cunput(NOEXP);
unpstr(och);
@@ -1004,8 +1174,7 @@
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 */
@@ -1022,6 +1191,12 @@
unpstr(stksv);
savstr(nl->namep);
}
+ if (stksv)
+ free(stksv);
+ break;
+
+ case CMNT:
+ getcmnt();
break;
case STRING:
@@ -1043,6 +1218,7 @@
}
if (noexp)
error("expmac noexp=%d", noexp);
+ readmac--;
DPRINT(("return from expmac\n"));
}
@@ -1053,34 +1229,40 @@
* result is written on top of heap
*/
void
-expdef(vp, rp, gotwarn)
- usch *vp;
- struct recur *rp;
+expdef(usch *vp, struct recur *rp, int gotwarn)
{
usch **args, *sptr, *ap, *bp, *sp;
int narg, c, i, plev, snuff, instr;
int ellips = 0;
- DPRINT(("expdef %s rp %s\n", vp, (rp ? (char *)rp->sp->namep : "")));
+ DPRINT(("expdef rp %s\n", (rp ? (char *)rp->sp->namep : "")));
if ((c = yylex()) != '(')
- error("got %c, expected )", c);
+ error("got %c, expected (", c);
if (vp[1] == VARG) {
narg = *vp--;
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.
* will be removed just before return from this function.
*/
+ inmac = 1;
sptr = stringbuf;
+ instr = 0;
for (i = 0; i < narg && c != ')'; i++) {
args[i] = stringbuf;
plev = 0;
while ((c = yylex()) == WSPACE || c == '\n')
;
+ DDPRINT((":AAA (%d)", c));
+ if (instr == -1)
+ savch(NOEXP), instr = 1;
+ if (c == NOEXP)
+ instr = 1;
for (;;) {
if (plev == 0 && (c == ')' || c == ','))
break;
@@ -1091,10 +1273,20 @@
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'))
stringbuf--;
+ if (instr == 1)
+ savch(EXPAND), instr = -1;
savch('\0');
}
if (ellips)
@@ -1102,8 +1294,12 @@
if (ellips && c != ')') {
args[i] = stringbuf;
plev = 0;
+ instr = 0;
while ((c = yylex()) == WSPACE)
;
+ if (c == NOEXP)
+ instr++;
+ DDPRINT((":AAY (%d)", c));
for (;;) {
if (plev == 0 && c == ')')
break;
@@ -1111,9 +1307,16 @@
plev++;
if (c == ')')
plev--;
- savstr((usch *)yytext);
+ if (plev == 0 && c == ',' && instr) {
+ savch(EXPAND);
+ savch(',');
+ savch(NOEXP);
+ } else
+ savstr((usch *)yytext);
while ((c = yylex()) == '\n')
savch('\n');
+ if (c == EXPAND)
+ instr--;
}
while (args[i] < stringbuf &&
(stringbuf[-1] == ' ' || stringbuf[-1] == '\t'))
@@ -1122,10 +1325,13 @@
}
if (narg == 0 && ellips == 0)
- c = yylex();
+ while ((c = yylex()) == WSPACE || c == '\n')
+ ;
+
if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1))
error("wrong arg count");
+ inmac = 0;
while (gotwarn--)
cunput(WARN);
@@ -1147,6 +1353,14 @@
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) {
@@ -1192,6 +1406,7 @@
/* scan the input buffer (until WARN) and save result on heap */
expmac(rp);
+ free(args);
}
usch *
@@ -1255,6 +1470,10 @@
putstr(usch *s)
{
for (; *s; s++) {
+ if (*s == PRAGS) {
+ s = prtprag(s);
+ continue;
+ }
outbuf[obufp++] = *s;
if (obufp == CPPBUF || (istty && *s == '\n'))
flbuf();
@@ -1480,3 +1699,41 @@
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;
+}
Index: cpy.y
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/cpp/cpy.y,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/cpp/cpy.y -L usr.bin/pcc/cpp/cpy.y -u -r1.1 -r1.2
--- usr.bin/pcc/cpp/cpy.y
+++ usr.bin/pcc/cpp/cpy.y
@@ -1,4 +1,4 @@
-/* $Id: cpy.y,v 1.12 2006/10/08 13:41:39 ragge Exp $ */
+/* $Id: cpy.y,v 1.16 2008/04/12 17:14:27 ragge Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson (ragge at ludd.luth.se).
@@ -62,23 +62,34 @@
*/
%{
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
+
+#include "cpp.h"
+
void yyerror(char *);
int yylex(void);
+int setd(int l, int r);
+
+#define EVALUNARY(tok, l, r) l.nd_val = tok r.nd_val; l.op = r.op
+#define EVALBIN(tok, d, l, r) \
+ d.op = setd(l.op, r.op); d.nd_val = l.nd_val tok r.nd_val
+#define EVALUBIN(tok, d, l, r, t) \
+ d.op = setd(l.op, r.op); \
+ if (d.op == NUMBER) d.nd_val = l.nd_val tok r.nd_val; \
+ else d.nd_uval = l.nd_uval tok r.nd_uval; \
+ if (t && d.op) d.op = NUMBER
+#define XEVALUBIN(tok, d, l, r) \
+ if (r.nd_val) { EVALUBIN(tok, d, l, r, 0); } else d.op = 0
%}
%term stop
%term EQ NE LE GE LS RS
-%term ANDAND OROR IDENT NUMBER
+%term ANDAND OROR IDENT NUMBER UNUMBER
/*
* 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 '='
%right '?' ':'
%left OROR
%left ANDAND
@@ -90,77 +101,117 @@
%left '+' '-'
%left '*' '/' '%'
%right '!' '~' UMINUS
-%left '(' '.'
+%left '('
%union {
- long long val;
+ struct nd node;
}
-%type <val> term NUMBER e
+%type <node> term e NUMBER UNUMBER
%%
-S: e '\n' { return($1 != 0);}
-
+S: e '\n' {
+ if ($1.op == 0)
+ error("division by zero");
+ return $1.nd_val;
+ }
e: e '*' e
- {$$ = $1 * $3;}
+ { EVALUBIN(*, $$, $1, $3, 0); }
| e '/' e
- {$$ = $1 / $3;}
+ { XEVALUBIN(/, $$, $1, $3); }
| e '%' e
- {$$ = $1 % $3;}
+ { XEVALUBIN(%, $$, $1, $3); }
| e '+' e
- {$$ = $1 + $3;}
+ { EVALBIN(+, $$, $1, $3); }
| e '-' e
- {$$ = $1 - $3;}
+ { EVALBIN(-, $$, $1, $3); }
| e LS e
- {$$ = $1 << $3;}
+ { EVALBIN(<<, $$, $1, $3); }
| e RS e
- {$$ = $1 >> $3;}
+ { EVALUBIN(>>, $$, $1, $3, 0); }
| e '<' e
- {$$ = $1 < $3;}
+ { EVALUBIN(<, $$, $1, $3, 1); }
| e '>' e
- {$$ = $1 > $3;}
+ { EVALUBIN(>, $$, $1, $3, 1); }
| e LE e
- {$$ = $1 <= $3;}
+ { EVALUBIN(<=, $$, $1, $3, 1); }
| e GE e
- {$$ = $1 >= $3;}
+ { EVALUBIN(>=, $$, $1, $3, 1); }
| e EQ e
- {$$ = $1 == $3;}
+ { EVALUBIN(==, $$, $1, $3, 1); }
| e NE e
- {$$ = $1 != $3;}
+ { EVALUBIN(!=, $$, $1, $3, 1); }
| e '&' e
- {$$ = $1 & $3;}
+ { EVALBIN(&, $$, $1, $3); }
| e '^' e
- {$$ = $1 ^ $3;}
+ { EVALBIN(^, $$, $1, $3); }
| e '|' e
- {$$ = $1 | $3;}
- | e ANDAND e
- {$$ = $1 && $3;}
- | e OROR e
- {$$ = $1 || $3;}
- | e '?' e ':' e
- {$$ = $1 ? $3 : $5;}
- | e ',' e
- {$$ = $3;}
+ { EVALBIN(|, $$, $1, $3); }
+ | e ANDAND e {
+ $$ = $1;
+ if ($1.nd_val) {
+ $$.op = setd($1.op, $3.op);
+ $$.nd_val = ($3.nd_val != 0);
+ }
+ if ($$.op == UNUMBER) $$.op = NUMBER;
+ }
+ | e OROR e {
+ if ($1.nd_val != 0) {
+ $$.nd_val = ($1.nd_val != 0);
+ $$.op = $1.op;
+ } else {
+ $$.nd_val = ($3.nd_val != 0);
+ $$.op = setd($1.op, $3.op);
+ }
+ if ($$.op == UNUMBER) $$.op = NUMBER;
+ }
+ | e '?' e ':' e {
+ if ($1.op == 0)
+ $$ = $1;
+ else if ($1.nd_val)
+ $$ = $3;
+ else
+ $$ = $5;
+ }
+ | e ',' e {
+ $$.op = setd($1.op, $3.op);
+ $$.nd_val = $3.nd_val;
+ if ($$.op) $$.op = $3.op;
+ }
| term
{$$ = $1;}
term:
'-' term %prec UMINUS
- {$$ = -$2;}
+ { EVALUNARY(-, $$, $2); }
+ | '+' term %prec UMINUS
+ {$$ = $2;}
| '!' term
- {$$ = !$2;}
+ { $$.nd_val = ! $2.nd_val; $$.op = $2.op ? NUMBER : 0; }
| '~' term
- {$$ = ~$2;}
+ { EVALUNARY(~, $$, $2); }
| '(' e ')'
{$$ = $2;}
| NUMBER
- {$$= $1;}
+ {$$ = $1;}
%%
-#include "cpp.h"
-
void
yyerror(char *err)
{
error(err);
}
+
+/*
+ * Set return type of an expression.
+ */
+int
+setd(int l, int r)
+{
+ if (!l || !r)
+ return 0; /* div by zero involved */
+ if (l == UNUMBER || r == UNUMBER)
+ return UNUMBER;
+ return NUMBER;
+}
+
Index: cpp.h
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/cpp/cpp.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L usr.bin/pcc/cpp/cpp.h -L usr.bin/pcc/cpp/cpp.h -u -r1.2 -r1.3
--- usr.bin/pcc/cpp/cpp.h
+++ usr.bin/pcc/cpp/cpp.h
@@ -1,4 +1,4 @@
-/* $Id: cpp.h,v 1.27 2007/09/17 18:16:14 ragge Exp $ */
+/* $Id: cpp.h,v 1.37 2008/07/02 01:12:41 gmcgarry Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson (ragge at ludd.luth.se).
@@ -28,8 +28,9 @@
*/
#include <stdio.h> /* for obuf */
+#include <stdlib.h>
-#include "../config.h"
+#include "config.h"
typedef unsigned char usch;
#ifdef YYTEXT_POINTER
@@ -43,7 +44,7 @@
extern int flslvl;
extern int elflvl;
extern int elslvl;
-extern int tflag, Cflag;
+extern int tflag, Cflag, Pflag;
extern int Mflag, dMflag;
extern usch *Mfile;
extern int ofd;
@@ -72,6 +73,7 @@
int infil;
usch *curptr;
usch *maxread;
+ usch *ostr;
usch *buffer;
usch bbuf[NAMEMAX+CPPBUF+1];
} *ifiles;
@@ -90,6 +92,23 @@
char *str;
};
+/*
+ * Struct used in parse tree evaluation.
+ * op is one of:
+ * - number type (NUMBER, UNUMBER)
+ * - zero (0) if divided by zero.
+ */
+struct nd {
+ int op;
+ union {
+ long long val;
+ unsigned long long uval;
+ } n;
+};
+
+#define nd_val n.val
+#define nd_uval n.uval
+
struct recur; /* not used outside cpp.c */
int subst(struct symtab *, struct recur *);
struct symtab *lookup(usch *namep, int enterf);
@@ -115,6 +134,15 @@
void putstr(usch *s);
void line(void);
usch *sheap(char *fmt, ...);
+void xwarning(usch *);
void xerror(usch *);
+#ifdef HAVE_CPP_VARARG_MACRO_GCC
+#define warning(...) xwarning(sheap(__VA_ARGS__))
#define error(...) xerror(sheap(__VA_ARGS__))
+#else
+#define warning printf
+#define error printf
+#endif
void expmac(struct recur *);
+int cinput(void);
+void getcmnt(void);
--- /dev/null
+++ usr.bin/pcc/cpp/pcpp.1
@@ -0,0 +1,210 @@
+.\" $Id: cpp.1,v 1.10 2008/07/02 01:12:41 gmcgarry Exp $
+.\" $NetBSD$
+.\" $OpenBSD$
+."\
+.\" Copyright (c) 2007 Jeremy C. Reed <reed at reedmedia.net>
+.\"
+.\" Permission to use, copy, modify, and/or distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM
+.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND
+.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+.\" THIS SOFTWARE.
+.\"
+.Dd September 17, 2007
+.Dt CPP 1
+.Os
+.Sh NAME
+.Nm cpp
+.Nd C preprocessor
+.Sh SYNOPSIS
+.Nm
+.\" TODO also document -Dvar and below without spaces?
+.Op Fl CdMtVv
+.Op Fl D Ar macro[=value]
+.Op Fl I Ar path
+.Op Fl i Ar file
+.Op Fl S Ar path
+.Op Fl U Ar macro
+.Op Ar infile | -
+.Op Ar outfile
+.Sh DESCRIPTION
+The
+.Nm
+utility is a macro preprocessor used by the
+.Xr pcc 1
+compiler.
+It is used to include header files,
+expand macro definitions,
+and perform conditional compilation.
+.Pp
+The
+.Ar infile
+input file is optional.
+If not provided or the file name is
+.Qq -
+(dash),
+.Nm
+reads its initial file from standard input.
+The
+.Ar outfile
+output file is also optional.
+It writes by default to standard output.
+.Pp
+.\" TODO: document MAXARG 250 args to a macro, limited by char value
+.\" TODO: Include order:
+.\" For "..." files, first search "current" dir, then as <...> files.
+.\" For <...> files, first search -I directories, then system directories.
+.\"
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl ?
+Show command line usage for
+.Nm .
+.It Fl C
+Do not discard comments.
+.It Fl D Ar macro[=value]
+Fake a definition at the beginning by using
+.Do #define
+.Ar macro=value Dc .
+If
+.Ar value
+is not set on command-line, then define it as 1.
+.\" TODO: show example
+.It Fl dM
+Print list of
+.Dq #define
+statements to standard output for all defined macros other than
+builtin macros (see below).
+The normal results of preprocessing are not output.
+.\" TODO this doesn't show predefined macros
+.\" other -d options are ignored
+.It Fl I Ar path
+Add
+.Ar path
+to the list of directories containing needed header files.
+This may be used to override system include directories
+(see
+.Fl S
+option).
+.Fl I
+may be specified multiple times.
+.It Fl i Ar file
+Include a file at the beginning by using
+.Do #include
+.Ar file Dc .
+.\" Note: I did not use the .In macro above
+.It Fl M
+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
+to the list of system directories containing needed header files.
+The
+.Fl S
+option may be specified multiple times.
+Note:
+.Nm
+does not have a default include directory defined.
+.\" TODO: explain difference between -I and -S
+.\" The directories listed by -I are searched first?
+.It Fl t
+Traditional cpp syntax.
+Do not define the
+.Dv __TIME__ ,
+.Dv __DATE__ ,
+.Dv __STDC__ ,
+and
+.Dv __STDC_VERSION__
+macros.
+.\"
+.It Fl U Ar macro
+Undefine a macro at the beginning by using
+.Do #undef
+.Ar macro Dc .
+.It Fl V
+Verbose debugging output.
+.Fl V
+can be repeated for further details.
+.\" -V only available if cpp source built with CPP_DEBUG, which is the default.
+.It Fl v
+Display version.
+.El
+.Ss Builtin Macros
+A few macros are interpreted inside the
+.Nm cpp
+program:
+.Bl -diag
+.It __DATE__
+Expands to the date in abbreviated month, day, and year format from
+.Xr ctime 3
+in quotes.
+.\" TODO: is that ctime(3) format output change according to locale?
+.It __FILE__
+Expands to the name of the current input file in quotes.
+When read from standard input, it expands to
+.Qq Aq stdin .
+.It __LINE__
+Expands to the line number of the current line containing the macro.
+.It __STDC__
+Expands to the constant 1.
+This means the compiler conforms to
+.St -isoC
+.Po also known as
+.Do C90 Dc Pc .
+.It __STDC_VERSION__
+Expands to
+.Dq 199901L
+which indicates that
+.Nm
+supports
+.St -isoC-99
+.Po commonly referred to as
+.Do C99 Dc Pc .
+.It __TIME__
+Expands to the time in hour, minutes, and seconds from
+.Xr ctime 3
+in quotes.
+.El
+.Pp
+Also see the
+.Fl t
+option.
+.Sh EXIT STATUS
+The
+.Nm
+utility exits with one of the following values:
+.Bl -tag -width Ds
+.It 0
+Successfully finished.
+.It 1
+An error occurred.
+.El
+.Sh SEE ALSO
+.Xr as 1 ,
+.Xr ccom 1 ,
+.Xr pcc 1
+.\"
+.Sh HISTORY
+The
+.Nm
+command comes from the original Portable C Compiler by S. C. Johnson,
+written in the late 70's.
+The code originates from the V6 preprocessor with some additions
+from V7 cpp and ansi/c99 support.
+.Pp
+A lot of the PCC code was rewritten by Anders Magnusson.
+.Pp
+This product includes software developed or owned by Caldera
+International, Inc.
Index: Makefile
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/cpp/Makefile,v
retrieving revision 1.6
retrieving revision 1.7
diff -L usr.bin/pcc/cpp/Makefile -L usr.bin/pcc/cpp/Makefile -u -r1.6 -r1.7
--- usr.bin/pcc/cpp/Makefile
+++ usr.bin/pcc/cpp/Makefile
@@ -5,13 +5,11 @@
PROG= pcpp
TARGOS= midnightbsd
BINDIR= ${libexecdir}
-NO_MAN=
-#MAN= cpp.1
-#MANDIR= /usr/local/man/man
+MAN= pcpp.1
CFLAGS+= -DCPP_DEBUG -Wall -Wmissing-prototypes -Wstrict-prototypes -Werror
CFLAGS+= -DLIBEXECDIR=\"${libexecdir}\"
-CFLAGS+= -I. -I${.CURDIR}
+CFLAGS+= -I. -I${.CURDIR} -I${.CURDIR}/.. -I${.CURDIR}/../mip/
SRCS= cpy.y scanner.l cpp.c
CLEANFILES+= y.tab.c y.tab.h
--- usr.bin/pcc/cpp/cpp.1
+++ /dev/null
@@ -1,191 +0,0 @@
-.\" $Id: cpp.1,v 1.4 2007/09/26 14:48:51 ragge Exp $
-.\" $NetBSD$
-.\" $OpenBSD$
-."\
-.\" Copyright (c) 2007 Jeremy C. Reed <reed at reedmedia.net>
-.\"
-.\" Permission to use, copy, modify, and/or distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM
-.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
-.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND
-.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-.\" THIS SOFTWARE.
-.\"
-.Dd September 17, 2007
-.Dt cpp 1
-.Os
-.Sh NAME
-.Nm cpp
-.Nd C preprocessor
-.Sh SYNOPSIS
-.Nm
-.\" TODO also document -Dvar and below without spaces?
-.Op Fl Cdt
-.Op Fl D Ar var=val
-.Op Fl U Ar var
-.Op Fl I Ar path
-.Op Fl S Ar path
-.Op Ar infile | -
-.Op Ar outfile
-.Pp
-.Sh DESCRIPTION
-The
-.Nm
-utility is a macro preprocessor used by the
-.Xr pcc 1
-compiler.
-It is used to include header files,
-expand macro definitions,
-and perform conditional compilation.
-.Pp
-The
-.Ar infile
-input file is optional.
-If not provided or the file name is
-.Qq -
-(dash),
-.Nm
-reads its initial file from standard input.
-The
-.Ar outfile
-output file is also optional.
-It writes by default to standard output.
-.Pp
-.\" TODO: document MAXARG 250 args to a macro, limited by char value
-.\" TODO: Include order:
-.\" For "..." files, first search "current" dir, then as <...> files.
-.\" For <...> files, first search -I directories, then system directories.
-.\"
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl C
-Do not discard comments.
-.It Fl dM
-Print list of
-.Dq #define
-statements to standard output for all defined macros other than
-builtin macros (see below).
-The normal results of preprocessing are not outputted.
-.\" TODO this doesn't show predefined macros
-.\" other -d options are ignored
-.It Fl D Ar macro[=value]
-Fake a definition at the beginning by using
-.Do #define
-.Ar macro=value Dc .
-If
-.Ar value
-is not set on command-line, then defines as 1.
-.\" TODO: show example
-.It Fl i Ar file
-Include a file at the beginning by using
-.Do #include
-.Ar file Dc .
-.\" Note: I did not use the .In macro above
-.It Fl I Ar directory
-Add
-.Ar directory
-to the list of system directories containing needed header files.
-This may be used to override system include directories
-(see
-.Fl S
-option).
-.Fl I
-may be specified multiple times.
-.It Fl M
-Generate dependencies for
-.Xr make 1 .
-.\" TODO: explain and show example?
-.It Fl S Ar directory
-Add
-.Ar directory
-to the list of system directories containing needed header files.
-.Fl S
-may be specified multiple times.
-Note:
-.Nm
-does not have a default include directory defined.
-.\" TODO: explain difference between -I and -S
-.\" The directories listed by -I are searched first?
-.It Fl t
-Traditional cpp syntax.
-Do not define the
-.Dv __TIME__ ,
-.Dv __DATE__ ,
-and
-.Dv __STDC__
-macros.
-.\"
-.It Fl U Ar macro
-Undefine a macro at the beginning by using
-.Do #undef
-.Ar macro Dc .
-.It Fl v
-Verbose debugging output.
-.Fl v
-can be repeated for further details.
-.\" -v only available if cpp source built with CPP_DEBUG, which is the default.
-.It Fl ?
-Show command line usage for
-.Nm .
-.El
-.Sh Builtin Macros
-A few macros are interpreted inside the
-.Nm cpp
-program:
-.Bl -diag
-.It __DATE__
-Expands to the date in abbreviated month, day, and year format from
-.Xr ctime 3
-in quotes.
-.\" TODO: is that ctime(3) format output change according to locale?
-.It __FILE__
-Expands to the name of the current input file in quotes.
-When read from standard input, it expands to
-.Qq Ao stdin Ac .
-.It __LINE__
-Expands to the line number of the current line containing the macro.
-.It __STDC__
-Expands to the constant 1.
-This means the compiler conforms to ISO Standard C.
-.It __TIME__
-Expands to the time in hour, minutes, and seconds from
-.Xr ctime 3
-in quotes.
-.El
-.Pp
-Also see the
-.Fl t
-option.
-.Sh EXIT STATUS
-The
-.Nm
-utility exits with one of the following values:
-.Bl -tag -width Ds
-.It 0
-Successfully finished.
-.It 1
-An error occurred.
-.El
-.Sh SEE ALSO
-.Xr as 1 ,
-.Xr ccom 1 ,
-.Xr pcc 1
-.\"
-.Sh HISTORY
-The
-.Nm
-command comes from the original Portable C Compiler by S. C.
-Johnson, written in the late 70's.
-The code originates from the V6 preprocessor with some additions
-from V7 cpp and ansi/c99 support.
-.Pp
-A lot of the PCC code was rewritten by Anders Magnusson.
-.Pp
-This product includes software developed or owned by Caldera
-International, Inc.
Index: order.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/i386/order.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/i386/order.c -L usr.bin/pcc/i386/order.c -u -r1.1 -r1.2
--- usr.bin/pcc/i386/order.c
+++ usr.bin/pcc/i386/order.c
@@ -1,4 +1,4 @@
-/* $Id: order.c,v 1.49 2007/08/01 04:53:58 ragge Exp $ */
+/* $Id: order.c,v 1.54 2008/09/27 07:35:22 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -103,26 +103,16 @@
* Shape matches for UMUL. Cooperates with offstar().
*/
int
-shumul(NODE *p)
+shumul(NODE *p, int shape)
{
if (x2debug)
printf("shumul(%p)\n", p);
/* Turns currently anything into OREG on x86 */
- return SOREG;
-}
-
-/*
- * Rewrite increment/decrement operation.
- */
-int
-setincr(NODE *p)
-{
- if (x2debug)
- printf("setincr(%p)\n", p);
-
- return(0);
+ if (shape & SOREG)
+ return SROREG;
+ return SRNOPE;
}
/*
@@ -183,8 +173,8 @@
static struct rspecial s[] = {
{ NOLEFT, ESI }, { NOLEFT, EDI }, { 0 } };
return s;
- } else if ((q->ltype & (TINT|TUNSIGNED)) &&
- q->rtype == TLONGLONG) {
+ } else if ((q->ltype & TINT) &&
+ q->rtype == (TLONGLONG|TULONGLONG)) {
static struct rspecial s[] = {
{ NLEFT, EAX }, { NRES, EAXEDX },
{ NEVER, EAX }, { NEVER, EDX }, { 0 } };
@@ -285,3 +275,30 @@
{
return 0; /* nothing differs on x86 */
}
+
+/*
+ * set registers in calling conventions live.
+ */
+int *
+livecall(NODE *p)
+{
+ static int r[] = { EAX, EBX, -1 };
+ int off = 1;
+
+#ifdef TLS
+ if (p->n_left->n_op == ICON &&
+ strcmp(p->n_left->n_name, "___tls_get_addr at PLT") == 0)
+ off--;
+#endif
+
+ return kflag ? &r[off] : &r[2];
+}
+
+/*
+ * Signal whether the instruction is acceptable for this target.
+ */
+int
+acceptable(struct optab *op)
+{
+ return 1;
+}
Index: macdefs.h
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/i386/macdefs.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/i386/macdefs.h -L usr.bin/pcc/i386/macdefs.h -u -r1.1 -r1.2
--- usr.bin/pcc/i386/macdefs.h
+++ usr.bin/pcc/i386/macdefs.h
@@ -1,4 +1,4 @@
-/* $Id: macdefs.h,v 1.46 2007/08/19 19:25:22 ragge Exp $ */
+/* $Id: macdefs.h,v 1.67 2008/12/14 18:26:43 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -65,8 +65,9 @@
#define ALLONGLONG 32
#define ALSHORT 16
#define ALPOINT 32
-#define ALSTRUCT 32
+#undef ALSTRUCT /* Not defined if ELF ABI */
#define ALSTACK 32
+#define ALMAX 128 /* not yet supported type */
/*
* Min/max values.
@@ -77,7 +78,7 @@
#define MIN_SHORT -32768
#define MAX_SHORT 32767
#define MAX_USHORT 65535
-#define MIN_INT -1
+#define MIN_INT (-0x7fffffff-1)
#define MAX_INT 0x7fffffff
#define MAX_UNSIGNED 0xffffffff
#define MIN_LONG MIN_INT
@@ -90,7 +91,11 @@
/* Default char is signed */
#undef CHAR_UNSIGNED
#define BOOL_TYPE CHAR /* what used to store _Bool */
+#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 */
+#endif
/*
* Use large-enough types.
@@ -100,36 +105,37 @@
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 */
-#ifdef FORTRAN
-#define XL 8
-#define FLABELFMT "%s:\n"
-#define USETEXT ".text"
-#define USECONST ".data\t0" /* XXX - fix */
-#define USEBSS ".data\t1" /* XXX - fix */
-#define USEINIT ".data\t2" /* XXX - fix */
-#define MAXREGVAR 3 /* XXX - fix */
+#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 TYIREG TYLONG
#define FSZLENG FSZLONG
-#define FUDGEOFFSET 1
#define AUTOREG EBP
#define ARGREG EBP
-#define ARGOFFSET 4
+#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 MYP2TREE(p) myp2tree(p);
-
#undef FIELDOPS /* no bit-field instructions */
#define RTOLBYTES /* bytes are numbered right to left */
#define ENUMSIZE(high,low) INT /* enums are always stored in full int */
+#define FINDMOPS /* i386 has instructions that modifies memory */
+
/* Definitions mostly used in pass2 */
#define BYTEOFF(x) ((x)&03)
@@ -292,10 +298,69 @@
#define FPREG EBP /* frame pointer */
#define STKREG ESP /* stack pointer */
-#define MYREADER(p) myreader(p)
-#define MYCANON(p) mycanon(p)
-#define MYOPTIM
-
#define SHSTR (MAXSPECIAL+1) /* short struct */
#define SFUNCALL (MAXSPECIAL+2) /* struct assign after function call */
#define SPCON (MAXSPECIAL+3) /* positive nonnamed constant */
+
+/*
+ * Specials that indicate the applicability of machine idioms.
+ */
+#define SMIXOR (MAXSPECIAL+4)
+#define SMILWXOR (MAXSPECIAL+5)
+#define SMIHWXOR (MAXSPECIAL+6)
+
+/*
+ * i386-specific symbol table flags.
+ */
+#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)
+int xasmconstregs(char *);
+#define XASMCONSTREGS(x) xasmconstregs(x)
+
+/*
+ * 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
Index: table.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/i386/table.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/i386/table.c -L usr.bin/pcc/i386/table.c -u -r1.1 -r1.2
--- usr.bin/pcc/i386/table.c
+++ usr.bin/pcc/i386/table.c
@@ -1,4 +1,4 @@
-/* $Id: table.c,v 1.96 2007/09/20 14:52:13 ragge Exp $ */
+/* $Id: table.c,v 1.110 2008/11/24 14:52:02 mickey Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -133,7 +133,7 @@
{ SCONV, INLL,
SHCH|SOREG|SNAME, TCHAR,
SANY, TLL,
- NSPECIAL|NAREG|NASL, RESC1,
+ NSPECIAL|NCREG|NCSL, RESC1,
" movsbl AL,%eax\n cltd\n", },
/* convert unsigned char to (u)long long */
@@ -229,7 +229,7 @@
/* 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", },
@@ -241,17 +241,17 @@
0, RLEFT,
"", },
-/* convert int to long long */
+/* convert signed int to (u)long long */
{ SCONV, INLL,
- SAREG, TWORD|TPOINT,
- SCREG, TLONGLONG,
+ SHINT, TSWORD,
+ SHLL, TLL,
NSPECIAL|NCREG|NCSL, RESC1,
" cltd\n", },
-/* convert int to unsigned long long */
+/* convert unsigned int to (u)long long */
{ SCONV, INLL,
- SAREG|SOREG|SNAME, TWORD|TPOINT,
- SHLL, TULONGLONG,
+ SHINT|SOREG|SNAME, TUWORD|TPOINT,
+ SHLL, TLL,
NCSL|NCREG, RESC1,
" movl AL,A1\n xorl U1,U1\n", },
@@ -275,14 +275,14 @@
{ SCONV, INCH,
SOREG|SNAME, TLL,
SANY, TCHAR|TUCHAR,
- NAREG|NASL, RESC1,
+ NBREG|NBSL, RESC1,
" movb AL,A1\n", },
/* convert (u)long long to (u)char (reg->reg, hopefully nothing) */
{ SCONV, INCH,
SHLL, TLL,
SANY, TCHAR|TUCHAR,
- NAREG|NASL, RESC1,
+ NBREG|NBSL, RESC1,
"ZS", },
/* convert (u)long long to (u)short (mem->reg) */
@@ -358,7 +358,19 @@
SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
SAREG, TWORD,
NAREG, RESC1,
+#ifdef notdef /* Must round down and nothing else */
" subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
+#else
+ " subl $12,%esp\n"
+ " fnstcw (%esp)\n"
+ " fnstcw 4(%esp)\n"
+ " movb $12,1(%esp)\n"
+ " fldcw (%esp)\n"
+ " fistpl 8(%esp)\n"
+ " movl 8(%esp),A1\n"
+ " fldcw 4(%esp)\n"
+ " addl $12,%esp\n", },
+#endif
/* convert float/double (in register) to (unsigned) long long */
/* XXX - unsigned is not handled correct */
@@ -366,8 +378,21 @@
SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
SHLL, TLONGLONG|TULONGLONG,
NCREG, RESC1,
+#ifdef notdef /* Must round down and nothing else */
" subl $8,%esp\n fistpq (%esp)\n"
" popl A1\n popl U1\n", },
+#else
+ " subl $16,%esp\n"
+ " fnstcw (%esp)\n"
+ " fnstcw 4(%esp)\n"
+ " movb $12,1(%esp)\n"
+ " fldcw (%esp)\n"
+ " fistpq 8(%esp)\n"
+ " movl 8(%esp),A1\n"
+ " movl 12(%esp),U1\n"
+ " fldcw 4(%esp)\n"
+ " addl $16,%esp\n", },
+#endif
/* slut sconv */
@@ -389,13 +414,13 @@
{ CALL, INAREG,
SCON, TANY,
- SAREG, TWORD|TPOINT,
+ SAREG, TSHORT|TUSHORT|TWORD|TPOINT,
NAREG|NASL, RESC1, /* should be 0 */
" call CL\nZC", },
{ UCALL, INAREG,
SCON, TANY,
- SAREG, TWORD|TPOINT,
+ SAREG, TSHORT|TUSHORT|TWORD|TPOINT,
NAREG|NASL, RESC1, /* should be 0 */
" call CL\n", },
@@ -573,6 +598,12 @@
NAREG|NASL, RESC1,
" leal CR(AL),A1\n", },
+{ PLUS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SONE, TANY,
+ 0, RLEFT,
+ " incw AL\n", },
+
{ PLUS, INCH|FOREFF,
SHCH|SNAME|SOREG, TCHAR|TUCHAR,
SONE, TANY,
@@ -591,6 +622,12 @@
0, RLEFT,
" decl AL\n", },
+{ MINUS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SONE, TANY,
+ 0, RLEFT,
+ " decw AL\n", },
+
{ MINUS, INCH|FOREFF,
SHCH|SNAME|SOREG, TCHAR|TUCHAR,
SONE, TANY,
@@ -623,48 +660,81 @@
" fsubZAp\n", },
/* Simple r/m->reg ops */
-{ OPSIMP, INAREG|FOREFF,
+/* m/r |= r */
+{ OPSIMP, INAREG|FOREFF|FORCC,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RLEFT|RESCC,
+ " Ol AR,AL\n", },
+
+/* r |= r/m */
+{ OPSIMP, INAREG|FOREFF|FORCC,
SAREG, TWORD|TPOINT,
SAREG|SNAME|SOREG, TWORD|TPOINT,
- 0, RLEFT,
+ 0, RLEFT|RESCC,
" Ol AR,AL\n", },
-{ OPSIMP, INAREG|FOREFF,
+/* m/r |= r */
+{ OPSIMP, INAREG|FOREFF|FORCC,
+ SHINT|SNAME|SOREG, TSHORT|TUSHORT,
+ SHINT, TSHORT|TUSHORT,
+ 0, RLEFT|RESCC,
+ " Ow AR,AL\n", },
+
+/* r |= r/m */
+{ OPSIMP, INAREG|FOREFF|FORCC,
SHINT, TSHORT|TUSHORT,
SHINT|SNAME|SOREG, TSHORT|TUSHORT,
- 0, RLEFT,
+ 0, RLEFT|RESCC,
" Ow AR,AL\n", },
-{ OPSIMP, INCH|FOREFF,
+/* m/r |= r */
+{ OPSIMP, INCH|FOREFF|FORCC,
SHCH, TCHAR|TUCHAR,
SHCH|SNAME|SOREG, TCHAR|TUCHAR,
- 0, RLEFT,
+ 0, RLEFT|RESCC,
" Ob AR,AL\n", },
-{ OPSIMP, INAREG|FOREFF,
- SAREG, TWORD|TPOINT,
+/* r |= r/m */
+{ OPSIMP, INCH|FOREFF|FORCC,
+ SHCH, TCHAR|TUCHAR,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ 0, RLEFT|RESCC,
+ " Ob AR,AL\n", },
+
+/* m/r |= const */
+{ OPSIMP, INAREG|FOREFF|FORCC,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
SCON, TWORD|TPOINT,
- 0, RLEFT,
+ 0, RLEFT|RESCC,
" Ol AR,AL\n", },
-{ OPSIMP, INAREG|FOREFF,
+{ OPSIMP, INAREG|FOREFF|FORCC,
SHINT|SNAME|SOREG, TSHORT|TUSHORT,
SCON, TANY,
- 0, RLEFT,
+ 0, RLEFT|RESCC,
" Ow AR,AL\n", },
-{ OPSIMP, INCH|FOREFF,
+{ OPSIMP, INCH|FOREFF|FORCC,
SHCH|SNAME|SOREG, TCHAR|TUCHAR,
SCON, TANY,
- 0, RLEFT,
+ 0, RLEFT|RESCC,
" Ob AR,AL\n", },
+/* r |= r/m */
{ OPSIMP, INLL|FOREFF,
SHLL, TLL,
SHLL|SNAME|SOREG, TLL,
0, RLEFT,
" Ol AR,AL\n Ol UR,UL\n", },
+/* m/r |= r/const */
+{ OPSIMP, INLL|FOREFF,
+ SHLL|SNAME|SOREG, TLL,
+ SHLL|SCON, TLL,
+ 0, RLEFT,
+ " Ol AR,AL\n Ol UR,UL\n", },
+
/*
* The next rules handle all shift operators.
@@ -676,24 +746,28 @@
NSPECIAL|NCREG|NCSL|NCSR, RESC1,
"ZO", },
+/* r/m <<= r */
{ LS, INAREG|FOREFF,
SAREG|SNAME|SOREG, TWORD,
SHCH, TCHAR|TUCHAR,
NSPECIAL, RLEFT,
" sall AR,AL\n", },
+/* r/m <<= const */
{ LS, INAREG|FOREFF,
- SAREG, TWORD,
+ SAREG|SNAME|SOREG, TWORD,
SCON, TANY,
0, RLEFT,
" sall AR,AL\n", },
+/* r/m <<= r */
{ LS, INAREG|FOREFF,
SAREG|SNAME|SOREG, TSHORT|TUSHORT,
SHCH, TCHAR|TUCHAR,
NSPECIAL, RLEFT,
" shlw AR,AL\n", },
+/* r/m <<= const */
{ LS, INAREG|FOREFF,
SAREG|SNAME|SOREG, TSHORT|TUSHORT,
SCON, TANY,
@@ -727,7 +801,7 @@
{ RS, INAREG|FOREFF,
SAREG|SNAME|SOREG, TSWORD,
- SCON, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SCON, TANY,
0, RLEFT,
" sarl AR,AL\n", },
@@ -739,7 +813,7 @@
{ RS, INAREG|FOREFF,
SAREG|SNAME|SOREG, TUWORD,
- SCON, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SCON, TANY,
0, RLEFT,
" shrl AR,AL\n", },
@@ -794,17 +868,41 @@
/*
* The next rules takes care of assignments. "=".
*/
+{ ASSIGN, FORCC|FOREFF|INLL,
+ SHLL, TLL,
+ SMIXOR, TANY,
+ 0, RDEST,
+ " xorl AL,AL\n xorl UL,UL\n", },
+
+{ ASSIGN, FORCC|FOREFF|INLL,
+ SHLL, TLL,
+ SMILWXOR, TANY,
+ 0, RDEST,
+ " xorl AL,AL\n movl UR,UL\n", },
+
+{ ASSIGN, FORCC|FOREFF|INLL,
+ SHLL, TLL,
+ SMIHWXOR, TANY,
+ 0, RDEST,
+ " movl AR,AL\n xorl UL,UL\n", },
+
+{ ASSIGN, FOREFF|INLL,
+ SHLL, TLL,
+ SCON, TANY,
+ 0, RDEST,
+ " movl AR,AL\n movl UR,UL\n", },
+
{ ASSIGN, FOREFF,
SHLL|SNAME|SOREG, TLL,
SCON, TANY,
0, 0,
" movl AR,AL\n movl UR,UL\n", },
-{ ASSIGN, FOREFF|INLL,
- SHLL, TLL,
- SCON, TANY,
+{ ASSIGN, FORCC|FOREFF|INAREG,
+ SAREG, TWORD|TPOINT,
+ SMIXOR, TANY,
0, RDEST,
- " movl AR,AL\n movl UR,UL\n", },
+ " xorl AL,AL\n", },
{ ASSIGN, FOREFF,
SAREG|SNAME|SOREG, TWORD|TPOINT,
@@ -818,6 +916,12 @@
0, RDEST,
" movl AR,AL\n", },
+{ ASSIGN, FORCC|FOREFF|INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SMIXOR, TANY,
+ 0, RDEST,
+ " xorw AL,AL\n", },
+
{ ASSIGN, FOREFF,
SAREG|SNAME|SOREG, TSHORT|TUSHORT,
SCON, TANY,
@@ -875,20 +979,40 @@
{ ASSIGN, FOREFF|INBREG,
SFLD, TCHAR|TUCHAR,
SBREG|SCON, TCHAR|TUCHAR,
- NBREG, RDEST,
- "ZE", },
+ NAREG|NBREG, RDEST,
+ " movb AR,A2\n"
+ " movzbl A2,A1\n"
+ " andl $N,AL\n"
+ " sall $H,A1\n"
+ " andl $M,A1\n"
+ " orl A1,AL\n"
+ "F movb AR,AD\n"
+ "FZE", },
{ ASSIGN, FOREFF|INAREG,
- SFLD, TANY,
- SAREG, TANY,
+ SFLD, TSHORT|TUSHORT,
+ SAREG|SCON, TSHORT|TUSHORT,
NAREG, RDEST,
- "ZE", },
+ " movw AR,A1\n"
+ " movzwl A1,ZN\n"
+ " andl $N,AL\n"
+ " sall $H,ZN\n"
+ " andl $M,ZN\n"
+ " orl ZN,AL\n"
+ "F movw AR,AD\n"
+ "FZE", },
-{ ASSIGN, FOREFF,
- SFLD, TANY,
- SAREG|SNAME|SOREG|SCON, TANY,
- NAREG, 0,
- "ZE", },
+{ ASSIGN, FOREFF|INAREG,
+ SFLD, TWORD,
+ SAREG|SNAME|SOREG|SCON, TWORD,
+ NAREG, RDEST,
+ " movl AR,A1\n"
+ " andl $N,AL\n"
+ " sall $H,A1\n"
+ " andl $M,A1\n"
+ " orl A1,AL\n"
+ "F movl AR,AD\n"
+ "FZE", },
{ ASSIGN, INDREG|FOREFF,
SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
@@ -901,7 +1025,7 @@
SNAME|SOREG, TLDOUBLE,
SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
0, RDEST,
- " fstt AL\n", },
+ " fst AL\n", },
{ ASSIGN, FOREFF,
SNAME|SOREG, TLDOUBLE,
@@ -1087,7 +1211,7 @@
{ UMUL, INLL,
SANY, TANY,
SOREG, TLL,
- NCREG|NCSL, RESC1,
+ NCREG, RESC1,
" movl UL,U1\n movl AL,A1\n", },
{ UMUL, INAREG,
@@ -1241,7 +1365,7 @@
0, RNOP,
" jmp LL\n", },
-#ifdef GCC_COMPAT
+#if defined(GCC_COMPAT) || defined(LANG_F77)
{ GOTO, FOREFF,
SAREG, TANY,
SANY, TANY,
@@ -1252,12 +1376,36 @@
/*
* Convert LTYPE to reg.
*/
+{ OPLTYPE, FORCC|INLL,
+ SCREG, TLL,
+ SMIXOR, TANY,
+ NCREG, RESC1,
+ " xorl U1,U1\n xorl A1,A1\n", },
+
+{ OPLTYPE, FORCC|INLL,
+ SCREG, TLL,
+ SMILWXOR, TANY,
+ NCREG, RESC1,
+ " movl UL,U1\n xorl A1,A1\n", },
+
+{ OPLTYPE, FORCC|INLL,
+ SCREG, TLL,
+ SMIHWXOR, TANY,
+ NCREG, RESC1,
+ " xorl U1,U1\n movl AL,A1\n", },
+
{ OPLTYPE, INLL,
SANY, TANY,
SCREG|SCON|SOREG|SNAME, TLL,
NCREG, RESC1,
" movl UL,U1\n movl AL,A1\n", },
+{ OPLTYPE, FORCC|INAREG,
+ SAREG, TWORD|TPOINT,
+ SMIXOR, TANY,
+ NAREG|NASL, RESC1,
+ " xorl A1,A1\n", },
+
{ OPLTYPE, INAREG,
SANY, TANY,
SAREG|SCON|SOREG|SNAME, TWORD|TPOINT,
@@ -1270,6 +1418,12 @@
NBREG, RESC1,
" movb AL,A1\n", },
+{ OPLTYPE, FORCC|INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SMIXOR, TANY,
+ NAREG, RESC1,
+ " xorw A1,A1\n", },
+
{ OPLTYPE, INAREG,
SANY, TANY,
SAREG|SOREG|SNAME|SCON, TSHORT|TUSHORT,
Index: local2.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/i386/local2.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/i386/local2.c -L usr.bin/pcc/i386/local2.c -u -r1.1 -r1.2
--- usr.bin/pcc/i386/local2.c
+++ usr.bin/pcc/i386/local2.c
@@ -1,4 +1,4 @@
-/* $Id: local2.c,v 1.89 2007/09/16 19:08:16 ragge Exp $ */
+/* $Id: local2.c,v 1.120 2008/12/14 18:26:43 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -26,22 +26,18 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
# include "pass2.h"
# 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;
-void
-lineid(int l, char *fn)
-{
- /* identify line l and file fn */
- printf("# line %d, file %s\n", l, fn);
-}
+static int stkpos;
void
deflab(int label)
@@ -59,16 +55,19 @@
static void
prtprolog(struct interpass_prolog *ipp, int addto)
{
- int i, j;
+ int i;
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++)
- if (i & 1)
+ for (i = 0; i < MAXREGS; i++)
+ if (TESTBIT(ipp->ipp_regs, i))
fprintf(stdout, " movl %s,-%d(%s)\n",
- rnames[j], regoff[j], rnames[FPREG]);
+ rnames[i], regoff[i], rnames[FPREG]);
}
/*
@@ -77,17 +76,16 @@
static int
offcalc(struct interpass_prolog *ipp)
{
- int i, j, addto;
+ int i, addto;
addto = p2maxautooff;
if (addto >= AUTOINIT/SZCHAR)
addto -= AUTOINIT/SZCHAR;
- for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
- if (i & 1) {
+ for (i = 0; i < MAXREGS; i++)
+ if (TESTBIT(ipp->ipp_regs, i)) {
addto += SZINT/SZCHAR;
- regoff[j] = addto;
+ regoff[i] = addto;
}
- }
return addto;
}
@@ -97,43 +95,61 @@
int addto;
ftype = ipp->ipp_type;
+
+#ifdef LANG_F77
if (ipp->ipp_vis)
printf(" .globl %s\n", ipp->ipp_name);
printf(" .align 4\n");
printf("%s:\n", ipp->ipp_name);
+#endif
/*
* We here know what register to save and how much to
* add to the stack.
*/
addto = offcalc(ipp);
+#if defined(MACHOABI)
+ addto = (addto + 15) & ~15; /* stack alignment */
+#endif
prtprolog(ipp, addto);
}
void
eoftn(struct interpass_prolog *ipp)
{
- int i, j;
+ int i;
if (ipp->ipp_ip.ip_lbl == 0)
return; /* no code needs to be generated */
/* return from function code */
- for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
- if (i & 1)
+ for (i = 0; i < MAXREGS; i++)
+ if (TESTBIT(ipp->ipp_regs, i))
fprintf(stdout, " movl -%d(%s),%s\n",
- regoff[j], rnames[FPREG], rnames[j]);
-
- }
+ regoff[i], rnames[FPREG], rnames[i]);
/* struct return needs special treatment */
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
}
/*
@@ -211,7 +227,7 @@
twollcomp(NODE *p)
{
int o = p->n_op;
- int s = getlab();
+ int s = getlab2();
int e = p->n_label;
int cb1, cb2;
@@ -250,58 +266,64 @@
deflab(s);
}
-/*
- * Assign to a bitfield.
- * Clumsy at least, but what to do?
- */
+int
+fldexpand(NODE *p, int cookie, char **cp)
+{
+ CONSZ val;
+
+ if (p->n_op == ASSIGN)
+ p = p->n_left;
+ switch (**cp) {
+ case 'S':
+ printf("%d", UPKFSZ(p->n_rval));
+ break;
+ case 'H':
+ printf("%d", UPKFOFF(p->n_rval));
+ break;
+ case 'M':
+ case 'N':
+ val = (CONSZ)1 << UPKFSZ(p->n_rval);
+ --val;
+ val <<= UPKFOFF(p->n_rval);
+ printf("0x%llx", (**cp == 'M' ? val : ~val) & 0xffffffff);
+ break;
+ default:
+ comperr("fldexpand");
+ }
+ return 1;
+}
+
static void
-bfasg(NODE *p)
+bfext(NODE *p)
{
- NODE *fn = p->n_left;
- int shift = UPKFOFF(fn->n_rval);
- int fsz = UPKFSZ(fn->n_rval);
- int andval, tch = 0;
-
- /* get instruction size */
- switch (p->n_type) {
- case CHAR: case UCHAR: tch = 'b'; break;
- case SHORT: case USHORT: tch = 'w'; break;
- case INT: case UNSIGNED: tch = 'l'; break;
- default: comperr("bfasg");
- }
-
- /* put src into a temporary reg */
- fprintf(stdout, " mov%c ", tch);
- adrput(stdout, getlr(p, 'R'));
- fprintf(stdout, ",");
- adrput(stdout, getlr(p, '1'));
- fprintf(stdout, "\n");
-
- /* AND away the bits from dest */
- andval = ~(((1 << fsz) - 1) << shift);
- fprintf(stdout, " and%c $%d,", tch, andval);
- adrput(stdout, fn->n_left);
- fprintf(stdout, "\n");
-
- /* AND away unwanted bits from src */
- andval = ((1 << fsz) - 1);
- fprintf(stdout, " and%c $%d,", tch, andval);
- adrput(stdout, getlr(p, '1'));
- fprintf(stdout, "\n");
-
- /* SHIFT left src number of bits */
- if (shift) {
- fprintf(stdout, " sal%c $%d,", tch, shift);
- adrput(stdout, getlr(p, '1'));
- fprintf(stdout, "\n");
+ int ch = 0, sz = 0;
+
+ if (ISUNSIGNED(p->n_right->n_type))
+ return;
+ switch (p->n_right->n_type) {
+ case CHAR:
+ ch = 'b';
+ sz = 8;
+ break;
+ case SHORT:
+ ch = 'w';
+ sz = 16;
+ break;
+ case INT:
+ case LONG:
+ ch = 'l';
+ sz = 32;
+ break;
+ default:
+ comperr("bfext");
}
- /* OR in src to dest */
- fprintf(stdout, " or%c ", tch);
- adrput(stdout, getlr(p, '1'));
- fprintf(stdout, ",");
- adrput(stdout, fn->n_left);
- fprintf(stdout, "\n");
+ sz -= UPKFSZ(p->n_left->n_rval);
+ printf("\tshl%c $%d,", ch, sz);
+ adrput(stdout, getlr(p, 'D'));
+ printf("\n\tsar%c $%d,", ch, sz);
+ adrput(stdout, getlr(p, 'D'));
+ printf("\n");
}
/*
@@ -318,7 +340,12 @@
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");
}
@@ -375,12 +402,12 @@
int jmplab;
if (loadlab == 0) {
- loadlab = getlab();
+ loadlab = getlab2();
expand(p, 0, " .data\n");
printf(LABFMT ": .long 0,0x80000000,0x403f\n", loadlab);
expand(p, 0, " .text\n");
}
- jmplab = getlab();
+ jmplab = getlab2();
expand(p, 0, " pushl UL\n pushl AL\n");
expand(p, 0, " fildq (%esp)\n");
expand(p, 0, " addl $8,%esp\n");
@@ -426,6 +453,8 @@
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;
@@ -439,8 +468,8 @@
twollcomp(p);
break;
- case 'E': /* Assign to bitfield */
- bfasg(p);
+ case 'E': /* Perform bitfield sign-extension */
+ bfext(p);
break;
case 'F': /* Structure argument */
@@ -491,7 +520,8 @@
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 */
@@ -508,7 +538,12 @@
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;
@@ -578,7 +613,7 @@
int o = p->n_op;
if (o==NAME || o==REG || o==ICON || o==OREG ||
- (o==UMUL && shumul(p->n_left)))
+ (o==UMUL && shumul(p->n_left, SOREG)))
return(1);
return(0);
}
@@ -593,7 +628,7 @@
if (o == OREG || o == REG || o == NAME)
return SRDIR; /* Direct match */
- if (o == UMUL && shumul(p->n_left))
+ if (o == UMUL && shumul(p->n_left, SOREG))
return SROREG; /* Convert into oreg */
return SRREG; /* put it into a register */
}
@@ -717,6 +752,8 @@
case OREG:
r = p->n_rval;
+ if (p->n_name[0])
+ printf("%s%s", p->n_name, p->n_lval ? "+" : "");
if (p->n_lval)
fprintf(io, "%d", (int)p->n_lval);
if (R2TEST(r)) {
@@ -726,12 +763,23 @@
fprintf(io, "(%s)", rnames[p->n_rval]);
return;
case ICON:
+#ifdef PCC_DEBUG
+ /* Sanitycheck for PIC, to catch adressable constants */
+ if (kflag && p->n_name[0] && 0) {
+ static int foo;
+
+ if (foo++ == 0) {
+ printf("\nfailing...\n");
+ fwalk(p, e2print, 0);
+ comperr("pass2 conput");
+ }
+ }
+#endif
/* addressable value of the constant */
fputc('$', io);
conput(io, p);
return;
- case MOVE:
case REG:
switch (p->n_type) {
case LONGLONG:
@@ -780,7 +828,7 @@
}
static void
-fixcalls(NODE *p)
+fixcalls(NODE *p, void *arg)
{
/* Prepare for struct return by allocating bounce space on stack */
switch (p->n_op) {
@@ -844,7 +892,7 @@
DLIST_FOREACH(ip, ipole, qelem) {
if (ip->type != IP_NODE)
continue;
- walkf(ip->ip_node, fixcalls);
+ walkf(ip->ip_node, fixcalls, 0);
storefloat(ip, ip->ip_node);
}
if (stkpos > p2autooff)
@@ -859,7 +907,7 @@
* Remove some PCONVs after OREGs are created.
*/
static void
-pconv2(NODE *p)
+pconv2(NODE *p, void *arg)
{
NODE *q;
@@ -884,7 +932,7 @@
void
mycanon(NODE *p)
{
- walkf(p, pconv2);
+ walkf(p, pconv2, 0);
}
void
@@ -1026,6 +1074,22 @@
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
+
+
+#if defined(MACHOABI)
+ int newsize = (size + 15) & ~15; /* stack alignment */
+ int align = newsize-size;
+
+ if (align != 0)
+ printf(" subl $%d,%%esp\n", align);
+
+ size=newsize;
+#endif
+
op->n_qual = size; /* XXX */
}
@@ -1047,6 +1111,177 @@
p->n_lval < 0 || p->n_lval > 0x7fffffff)
break;
return SRDIR;
+ case SMIXOR:
+ return tshape(p, SZERO);
+ case SMILWXOR:
+ if (o != ICON || p->n_name[0] ||
+ p->n_lval == 0 || p->n_lval & 0xffffffff)
+ break;
+ return SRDIR;
+ case SMIHWXOR:
+ if (o != ICON || p->n_name[0] ||
+ p->n_lval == 0 || (p->n_lval >> 32) != 0)
+ break;
+ return SRDIR;
}
return SRNOPE;
}
+
+/*
+ * Target-dependent command-line options.
+ */
+void
+mflags(char *str)
+{
+}
+
+/*
+ * Do something target-dependent for xasm arguments.
+ */
+int
+myxasm(struct interpass *ip, NODE *p)
+{
+ struct interpass *ip2;
+ NODE *in = 0, *ut = 0;
+ TWORD t;
+ char *w;
+ int reg;
+ int cw;
+
+ cw = xasmcode(p->n_name);
+ if (cw & (XASMASG|XASMINOUT))
+ ut = p->n_left;
+ if ((cw & XASMASG) == 0)
+ in = p->n_left;
+
+ switch (XASMVAL(cw)) {
+ case 'D': reg = EDI; break;
+ case 'S': reg = ESI; break;
+ case 'a': reg = EAX; break;
+ case 'b': reg = EBX; break;
+ case 'c': reg = ECX; break;
+ case 'd': reg = EDX; break;
+ case 't': reg = 0; break;
+ case 'u': reg = 1; break;
+ case 'A': reg = EAXEDX; break;
+ case 'q': /* XXX let it be CLASSA as for now */
+ p->n_name = tmpstrdup(p->n_name);
+ w = strchr(p->n_name, 'q');
+ *w = 'r';
+ return 0;
+ default:
+ return 0;
+ }
+ p->n_name = tmpstrdup(p->n_name);
+ for (w = p->n_name; *w; w++)
+ ;
+ w[-1] = 'r'; /* now reg */
+ t = p->n_left->n_type;
+ if (reg == EAXEDX) {
+ p->n_label = CLASSC;
+ } else {
+ p->n_label = CLASSA;
+ if (t == CHAR || t == UCHAR) {
+ p->n_label = CLASSB;
+ reg = reg * 2 + 8;
+ }
+ }
+ if (t == FLOAT || t == DOUBLE || t == LDOUBLE) {
+ p->n_label = CLASSD;
+ reg += 037;
+ }
+
+ if (in && ut)
+ in = tcopy(in);
+ p->n_left = mklnode(REG, 0, reg, t);
+ if (ut) {
+ ip2 = ipnode(mkbinode(ASSIGN, ut, tcopy(p->n_left), t));
+ DLIST_INSERT_AFTER(ip, ip2, qelem);
+ }
+ if (in) {
+ ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), in, t));
+ DLIST_INSERT_BEFORE(ip, ip2, qelem);
+ }
+ return 1;
+}
+
+void
+targarg(char *w, void *arg)
+{
+ NODE **ary = arg;
+ NODE *p, *q;
+
+ p = ary[(int)w[1]-'0']->n_left;
+ if (optype(p->n_op) != LTYPE)
+ comperr("bad xarg op %d", p->n_op);
+ q = tcopy(p);
+ if (q->n_op == REG) {
+ if (*w == 'k') {
+ q->n_type = INT;
+ } else if (*w != 'w') {
+ if (q->n_type > UCHAR) {
+ regno(q) = regno(q)*2+8;
+ if (*w == 'h')
+ regno(q)++;
+ }
+ q->n_type = INT;
+ } else
+ q->n_type = SHORT;
+ }
+ adrput(stdout, q);
+ tfree(q);
+}
+
+/*
+ * target-specific conversion of numeric arguments.
+ */
+int
+numconv(void *ip, void *p1, void *q1)
+{
+ NODE *p = p1, *q = q1;
+ int cw = xasmcode(q->n_name);
+
+ switch (XASMVAL(cw)) {
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ p->n_name = tmpcalloc(2);
+ p->n_name[0] = XASMVAL(cw);
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static struct {
+ char *name; int num;
+} xcr[] = {
+ { "eax", EAX },
+ { "ebx", EBX },
+ { "ecx", ECX },
+ { "edx", EDX },
+ { "ax", EAX },
+ { "bx", EBX },
+ { "cx", ECX },
+ { "dx", EDX },
+ { NULL, 0 },
+};
+
+/*
+ * Check for other names of the xasm constraints registers.
+ */
+
+/*
+ * Check for other names of the xasm constraints registers.
+ */
+int xasmconstregs(char *s)
+{
+ int i;
+
+ for (i = 0; xcr[i].name; i++)
+ if (strcmp(xcr[i].name, s) == 0)
+ return xcr[i].num;
+ return -1;
+}
+
Index: code.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/i386/code.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/i386/code.c -L usr.bin/pcc/i386/code.c -u -r1.1 -r1.2
--- usr.bin/pcc/i386/code.c
+++ usr.bin/pcc/i386/code.c
@@ -1,4 +1,4 @@
-/* $Id: code.c,v 1.15 2007/07/06 17:02:27 ragge Exp $ */
+/* $Id: code.c,v 1.38 2008/12/14 17:20:58 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -29,37 +29,62 @@
# include "pass1.h"
-/*
- * cause the alignment to become a multiple of n
- * never called for text segment.
- */
-void
-defalign(int n)
-{
- n /= SZCHAR;
- if (n == 1)
- return;
- printf(" .align %d\n", n);
-}
+int lastloc = -1;
/*
- * define the current location as the name p->sname
- * never called for text segment.
+ * Define everything needed to print out some data (or text).
+ * This means segment, alignment, visibility, etc.
*/
void
-defnam(struct symtab *p)
+defloc(struct symtab *sp)
{
- char *c = p->sname;
+ extern char *nextsect;
+#if defined(ELFABI) || defined(PECOFFABI)
+ static char *loctbl[] = { "text", "data", "section .rodata" };
+#elif defined(MACHOABI)
+ static char *loctbl[] = { "text", "data", "const_data" };
+#endif
+ TWORD t;
+ int s;
-#ifdef GCC_COMPAT
- c = gcc_findname(p);
+ if (sp == NULL) {
+ lastloc = -1;
+ return;
+ }
+ t = sp->stype;
+ s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA;
+#ifdef TLS
+ if (sp->sflags & STLS) {
+ if (s != DATA)
+ cerror("non-data symbol in tls section");
+ nextsect = ".tdata";
+ }
+#endif
+ if (sp->ssue->suesection)
+ nextsect = sp->ssue->suesection;
+ if (nextsect) {
+ printf(" .section %s\n", nextsect);
+ nextsect = NULL;
+ s = -1;
+ } else if (s != lastloc)
+ printf(" .%s\n", loctbl[s]);
+ lastloc = s;
+ while (ISARY(t))
+ t = DECREF(t);
+ if (sp->ssue->suealign > ALCHAR)
+ printf(" .align %d\n", sp->ssue->suealign/ALCHAR);
+ if (sp->sclass == EXTDEF)
+ printf(" .globl %s\n", exname(sp->soname));
+#if defined(ELFABI)
+ if (ISFTN(t))
+ printf("\t.type %s, at function\n", exname(sp->soname));
#endif
- if (p->sclass == EXTDEF)
- printf(" .globl %s\n", c);
- printf("%s:\n", c);
+ if (sp->slevel == 0)
+ printf("%s:\n", exname(sp->soname));
+ else
+ printf(LABFMT ":\n", sp->soffset);
}
-
/*
* code for the end of a function
* deals with struct return here
@@ -67,27 +92,21 @@
void
efcode()
{
+ extern int gotnr;
NODE *p, *q;
- int sz;
+ gotnr = 0; /* new number for next fun */
if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
return;
- /* address of return struct is in eax */
- /* create a call to memcpy() */
- /* will get the result in eax */
- p = block(REG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
- p->n_rval = EAX;
- q = block(OREG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
+ /* Create struct assignment */
+ q = block(OREG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue);
q->n_rval = EBP;
q->n_lval = 8; /* return buffer offset */
- p = block(CM, q, p, INT, 0, MKSUE(INT));
- sz = (tsize(STRTY, cftnsp->sdf, cftnsp->ssue)+SZCHAR-1)/SZCHAR;
- p = block(CM, p, bcon(sz), INT, 0, MKSUE(INT));
- p->n_right->n_name = "";
- p = block(CALL, bcon(0), p, CHAR+PTR, 0, MKSUE(CHAR+PTR));
- p->n_left->n_name = "memcpy";
- p = clocal(p);
- send_passt(IP_NODE, p);
+ q = buildtree(UMUL, q, NIL);
+ p = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue);
+ p = buildtree(UMUL, p, NIL);
+ p = buildtree(ASSIGN, q, p);
+ ecomp(p);
}
/*
@@ -95,15 +114,86 @@
* indices in symtab for the arguments; n is the number
*/
void
-bfcode(struct symtab **a, int n)
+bfcode(struct symtab **sp, int cnt)
{
+#ifdef os_win32
+ extern int argstacksize;
+#endif
+ struct symtab *sp2;
+ extern int gotnr;
+ NODE *n, *p;
int i;
- if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
+ if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
+ /* Function returns struct, adjust arg offset */
+ 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) {
+#define STL 100
+ char *str = inlalloc(STL);
+#if !defined(MACHOABI)
+ int l = getlab();
+#endif
+
+ /* Generate extended assembler for PIC prolog */
+ p = tempnode(0, INT, 0, MKSUE(INT));
+ gotnr = regno(p);
+ p = block(XARG, p, NIL, INT, 0, MKSUE(INT));
+ p->n_name = "=g";
+ p = block(XASM, p, bcon(0), INT, 0, MKSUE(INT));
+#if defined(MACHOABI)
+ if (snprintf(str, STL, "call L%s$pb\nL%s$pb:\n\tpopl %%0\n",
+ cftnsp->sname, cftnsp->sname) >= STL)
+ cerror("bfcode");
+#else
+ if (snprintf(str, STL,
+ "call " LABFMT "\n" LABFMT ":\n popl %%0\n"
+ " addl $_GLOBAL_OFFSET_TABLE_+[.-" LABFMT "], %%0\n",
+ l, l, l) >= STL)
+ cerror("bfcode");
+#endif
+ p->n_name = str;
+ p->n_right->n_type = STRTY;
+ ecomp(p);
+ }
+ if (xtemps == 0)
return;
- /* Function returns struct, adjust arg offset */
- for (i = 0; i < n; i++)
- a[i]->soffset += SZPOINT(INT);
+
+ /* put arguments in temporaries */
+ for (i = 0; i < cnt; i++) {
+ if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY ||
+ cisreg(sp[i]->stype) == 0)
+ continue;
+ if (cqual(sp[i]->stype, sp[i]->squal) & VOL)
+ continue;
+ sp2 = sp[i];
+ n = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->ssue);
+ n = buildtree(ASSIGN, n, nametree(sp2));
+ sp[i]->soffset = regno(n->n_left);
+ sp[i]->sflags |= STNODE;
+ ecomp(n);
+ }
}
@@ -116,60 +206,97 @@
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
}
/*
- * Print character t at position i in one string, until t == -1.
- * Locctr & label is already defined.
+ * Called with a function call with arguments as argument.
+ * This is done early in buildtree() and only done once.
+ * Returns p.
*/
-void
-bycode(int t, int i)
+NODE *
+funcode(NODE *p)
{
- static int lastoctal = 0;
-
- /* put byte i+1 in a string */
+ extern int gotnr;
+ NODE *r, *l;
- if (t < 0) {
- if (i != 0)
- puts("\"");
+ /* Fix function call arguments. On x86, just add funarg */
+ for (r = p->n_right; r->n_op == CM; r = r->n_left) {
+ if (r->n_right->n_op != STARG)
+ r->n_right = block(FUNARG, r->n_right, NIL,
+ r->n_right->n_type, r->n_right->n_df,
+ r->n_right->n_sue);
+ }
+ if (r->n_op != STARG) {
+ l = talloc();
+ *l = *r;
+ r->n_op = FUNARG;
+ r->n_left = l;
+ r->n_type = l->n_type;
+ }
+ 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;
+ l = buildtree(ASSIGN, l, tempnode(gotnr, INT, 0, MKSUE(INT)));
+ if (p->n_right->n_op != CM) {
+ p->n_right = block(CM, l, p->n_right, INT, 0, MKSUE(INT));
} else {
- if (i == 0)
- printf("\t.ascii \"");
- if (t == '\\' || t == '"') {
- lastoctal = 0;
- putchar('\\');
- putchar(t);
- } else if (t < 040 || t >= 0177) {
- lastoctal++;
- printf("\\%o",t);
- } else if (lastoctal && '0' <= t && t <= '9') {
- lastoctal = 0;
- printf("\"\n\t.ascii \"%c", t);
- } else {
- lastoctal = 0;
- putchar(t);
- }
+ for (r = p->n_right; r->n_left->n_op == CM; r = r->n_left)
+ ;
+ r->n_left = block(CM, l, r->n_left, INT, 0, MKSUE(INT));
}
-}
-
-/*
- * n integer words of zeros
- */
-void
-zecode(int n)
-{
- printf(" .zero %d\n", n * (SZINT/SZCHAR));
-// inoff += n * SZINT;
+#endif
+ return p;
}
/*
@@ -188,26 +315,11 @@
{
}
-/* p points to an array of structures, each consisting
- * of a constant value and a label.
- * The first is >=0 if there is a default label;
- * its value is the label number
- * The entries p[1] to p[n] are the nontrivial cases
+/*
* XXX - fix genswitch.
*/
-void
-genswitch(int num, struct swents **p, int n)
+int
+mygenswitch(int num, TWORD type, struct swents **p, int n)
{
- NODE *r;
- int i;
-
- /* simple switch code */
- for (i = 1; i <= n; ++i) {
- /* already in 1 */
- r = tempnode(num, INT, 0, MKSUE(INT));
- r = buildtree(NE, r, bcon(p[i]->sval));
- cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab));
- }
- if (p[0]->slab > 0)
- branch(p[0]->slab);
+ return 0;
}
Index: local.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/i386/local.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/i386/local.c -L usr.bin/pcc/i386/local.c -u -r1.1 -r1.2
--- usr.bin/pcc/i386/local.c
+++ usr.bin/pcc/i386/local.c
@@ -1,4 +1,4 @@
-/* $Id: local.c,v 1.56 2007/09/24 16:23:36 ragge Exp $ */
+/* $Id: local.c,v 1.95 2008/12/23 06:51:21 gmcgarry Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -31,6 +31,277 @@
/* this file contains code which is dependent on the target machine */
+/*
+ * Check if a constant is too large for a type.
+ */
+static int
+toolarge(TWORD t, CONSZ con)
+{
+ U_CONSZ ucon = con;
+
+ switch (t) {
+ case ULONGLONG:
+ case LONGLONG:
+ break; /* cannot be too large */
+#define SCHK(i) case i: if (con > MAX_##i || con < MIN_##i) return 1; break
+#define UCHK(i) case i: if (ucon > MAX_##i) return 1; break
+ SCHK(INT);
+ SCHK(SHORT);
+ case BOOL:
+ SCHK(CHAR);
+ UCHK(UNSIGNED);
+ UCHK(USHORT);
+ UCHK(UCHAR);
+ default:
+ cerror("toolarge");
+ }
+ 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 *p, char *s, char *s2)
+{
+ struct symtab *sp = IALLOC(sizeof(struct symtab));
+ size_t len = strlen(p) + strlen(s) + strlen(s2) + 1;
+
+ sp->sname = sp->soname = IALLOC(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");
+ r = xbcon(0, sp, INT);
+ q = buildtree(PLUS, q, r);
+ q = block(UMUL, q, 0, PTR|VOID, 0, MKSUE(VOID));
+ q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue);
+ q->n_sp = p->n_sp; /* for init */
+ nfree(p);
+ return q;
+
+#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
+
+}
+
+/*
+ * Create a reference for a static variable.
+ */
+static NODE *
+picstatic(NODE *p)
+{
+
+#if defined(ELFABI)
+
+ NODE *q, *r;
+ struct symtab *sp;
+
+ q = tempnode(gotnr, PTR|VOID, 0, MKSUE(VOID));
+ if (p->n_sp->slevel > 0) {
+ char buf[32];
+ snprintf(buf, 32, LABFMT, (int)p->n_sp->soffset);
+ sp = picsymtab("", buf, "@GOTOFF");
+ } else
+ sp = picsymtab("", p->n_sp->soname, "@GOTOFF");
+ sp->sclass = STATIC;
+ sp->stype = p->n_sp->stype;
+ 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; /* 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) {
+ 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
+/*
+ * Create a reference for a TLS variable.
+ */
+static NODE *
+tlspic(NODE *p)
+{
+ NODE *q, *r;
+ struct symtab *sp, *sp2;
+
+ /*
+ * creates:
+ * leal var at TLSGD(%ebx),%eax
+ * call ___tls_get_addr at PLT
+ */
+
+ /* calc address of var at TLSGD */
+ q = tempnode(gotnr, PTR|VOID, 0, MKSUE(VOID));
+ sp = picsymtab("", p->n_sp->soname, "@TLSGD");
+ r = xbcon(0, sp, INT);
+ q = buildtree(PLUS, q, r);
+
+ /* assign to %eax */
+ r = block(REG, NIL, NIL, PTR|VOID, 0, MKSUE(VOID));
+ r->n_rval = EAX;
+ q = buildtree(ASSIGN, r, q);
+
+ /* call ___tls_get_addr */
+ sp2 = lookup("___tls_get_addr at PLT", 0);
+ sp2->stype = EXTERN|INT|FTN;
+ r = nametree(sp2);
+ r = buildtree(ADDROF, r, NIL);
+ r = block(UCALL, r, NIL, INT, 0, MKSUE(INT));
+
+ /* fusion both parts together */
+ q = buildtree(COMOP, q, r);
+ q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue);
+ q->n_sp = p->n_sp; /* for init */
+
+ nfree(p);
+ return q;
+}
+
+static NODE *
+tlsnonpic(NODE *p)
+{
+ NODE *q, *r;
+ struct symtab *sp, *sp2;
+ int ext = p->n_sp->sclass;
+
+ 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));
+
+ 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);
+ q->n_sp = p->n_sp; /* for init */
+
+ nfree(p);
+ return q;
+}
+
+static NODE *
+tlsref(NODE *p)
+{
+ if (kflag)
+ return (tlspic(p));
+ else
+ return (tlsnonpic(p));
+}
+#endif
+
/* clocal() is called to do local transformations on
* an expression tree preparitory to its being
* written out in intermediate code.
@@ -75,11 +346,23 @@
p = stref(block(STREF, r, p, 0, 0, 0));
break;
+ case USTATIC:
+ if (kflag == 0)
+ break;
+ /* FALLTHROUGH */
case STATIC:
- if (q->slevel == 0)
+#ifdef TLS
+ if (q->sflags & STLS) {
+ p = tlsref(p);
break;
- p->n_lval = 0;
- p->n_sp = q;
+ }
+#endif
+ if (kflag == 0) {
+ if (q->slevel == 0)
+ break;
+ p->n_lval = 0;
+ } else if (blevel > 0)
+ p = picstatic(p);
break;
case REGISTER:
@@ -88,31 +371,72 @@
p->n_rval = q->soffset;
break;
+ case EXTERN:
+ case EXTDEF:
+#ifdef TLS
+ if (q->sflags & STLS) {
+ p = tlsref(p);
+ break;
}
+#endif
+ if (kflag == 0)
+ break;
+ if (blevel > 0)
+ p = picext(p);
+ break;
+ }
break;
- case STCALL:
+ case ADDROF:
+ if (kflag == 0 || blevel == 0)
+ break;
+ /* char arrays may end up here */
+ l = p->n_left;
+ if (l->n_op != NAME ||
+ (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE))
+ break;
+ l = p;
+ p = picstatic(p->n_left);
+ nfree(l);
+ if (p->n_op != UMUL)
+ cerror("ADDROF error");
+ l = p;
+ p = p->n_left;
+ nfree(l);
+ break;
+
+ case UCALL:
+ case USTCALL:
+ if (kflag == 0)
+ 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
+
+ /* FALLTHROUGH */
+#if defined(MACHOABI)
case CALL:
- /* Fix function call arguments. On x86, just add funarg */
- for (r = p->n_right; r->n_op == CM; r = r->n_left) {
- if (r->n_right->n_op != STARG &&
- r->n_right->n_op != FUNARG)
- r->n_right = block(FUNARG, r->n_right, NIL,
- r->n_right->n_type, r->n_right->n_df,
- r->n_right->n_sue);
- }
- if (r->n_op != STARG && r->n_op != FUNARG) {
- l = talloc();
- *l = *r;
- r->n_op = FUNARG; r->n_left = l; r->n_type = l->n_type;
- }
+ case STCALL:
+ if (p->n_type == VOID)
+ break;
+
+ r = tempnode(0, p->n_type, p->n_df, p->n_sue);
+ l = tcopy(r);
+ p = buildtree(COMOP, buildtree(ASSIGN, r, p), l);
+#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)
@@ -121,6 +445,10 @@
r = l->n_left->n_left;
if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
break;
+ if (ISPTR(r->n_type))
+ break; /* no opt for pointers */
+ if (toolarge(r->n_type, l->n_right->n_lval))
+ break;
/* Type must be correct */
t = r->n_type;
nfree(l->n_left);
@@ -222,8 +550,6 @@
case UNSIGNED:
l->n_lval = val & 0xffffffff;
break;
- case ENUMTY:
- case MOETY:
case LONG:
case INT:
l->n_lval = (int)val;
@@ -249,6 +575,14 @@
l->n_sue = MKSUE(m);
nfree(p);
return l;
+ } else if (l->n_op == FCON) {
+ l->n_lval = l->n_dcon;
+ l->n_sp = NULL;
+ l->n_op = ICON;
+ l->n_type = m;
+ l->n_sue = MKSUE(m);
+ nfree(p);
+ return clocal(l);
}
if (DEUNSIGN(p->n_type) == SHORT &&
DEUNSIGN(l->n_type) == SHORT) {
@@ -280,9 +614,10 @@
case PMCONV:
case PVCONV:
- if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0);
- nfree(p);
- return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right));
+ r = p;
+ p = buildtree(o == PMCONV ? MUL : DIV, p->n_left, p->n_right);
+ nfree(r);
+ break;
case FORCE:
/* put return value in return reg */
@@ -297,8 +632,6 @@
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,
@@ -320,16 +653,115 @@
return(p);
}
+/*
+ * Change CALL references to either direct (static) or PLT.
+ */
+static void
+fixnames(NODE *p, void *arg)
+{
+#if !defined(PECOFFABI)
+
+ struct symtab *sp;
+ struct suedef *sue;
+ NODE *q;
+ char *c;
+ int isu;
+
+ if ((cdope(p->n_op) & CALLFLG) == 0)
+ return;
+ isu = 0;
+ q = p->n_left;
+ sue = q->n_sue;
+ if (q->n_op == UMUL)
+ q = q->n_left, isu = 1;
+
+ if (q->n_op == PLUS && q->n_left->n_op == TEMP &&
+ q->n_right->n_op == ICON) {
+ sp = q->n_right->n_sp;
+
+ if (sp == NULL)
+ return; /* nothing to do */
+ if (sp->sclass == STATIC && !ISFTN(sp->stype))
+ return; /* function pointer */
+
+ if (sp->sclass != STATIC && sp->sclass != EXTERN &&
+ sp->sclass != EXTDEF)
+ cerror("fixnames");
+
+#if 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)
+ nfree(p->n_left->n_left);
+ nfree(p->n_left);
+ p->n_left = q;
+ q->n_sue = sue;
+ }
+#endif
+}
+
void
myp2tree(NODE *p)
{
+ struct symtab *sp;
+
+ if (kflag)
+ walkf(p, fixnames, 0); /* XXX walkf not needed */
+ if (p->n_op != FCON)
+ return;
+
+#if 0
+ /* put floating constants in memory */
+ setloc1(RDATA);
+ defalign(ALLDOUBLE);
+ deflab1(i = getlab());
+ ninval(0, btdims[p->n_type].suesize, p);
+#endif
+
+ 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->stype = p->n_type;
+ sp->squal = (CON >> TSHIFT);
+
+ defloc(sp);
+ ninval(0, sp->ssue->suesize, p);
+
+ p->n_op = NAME;
+ p->n_lval = 0;
+ p->n_sp = sp;
}
/*ARGSUSED*/
int
andable(NODE *p)
{
- return(1); /* all names can have & taken on them */
+ return(1); /* all names can have & taken on them */
}
/*
@@ -403,47 +835,38 @@
}
-#if 0
-/*
- * Print out an integer constant of size size.
- * can only be sizes <= SZINT.
- */
-void
-indata(CONSZ val, int size)
-{
- switch (size) {
- case SZCHAR:
- printf("\t.byte %d\n", (int)val & 0xff);
- break;
- case SZSHORT:
- printf("\t.word %d\n", (int)val & 0xffff);
- break;
- case SZINT:
- printf("\t.long %d\n", (int)val & 0xffffffff);
- break;
- default:
- cerror("indata");
- }
-}
-#endif
-
/*
* Print out a string of characters.
* Assume that the assembler understands C-style escape
- * sequences. Location is already set.
+ * sequences.
*/
void
-instring(char *str)
+instring(struct symtab *sp)
{
- char *s;
+ char *s, *str = sp->sname;
+
+#if defined(ELFABI) || defined(PECOFFABI)
+
+ defloc(sp);
+
+#elif defined(MACHOABI)
+
+ extern int lastloc;
+ if (lastloc != STRNG)
+ printf(" .cstring\n");
+ lastloc = STRNG;
+ printf("\t.p2align 2\n");
+ printf(LABFMT ":\n", sp->soffset);
- /* be kind to assemblers and avoid long strings */
+#endif
+
+ /* be kind to assemblers and avoid long strings */
printf("\t.ascii \"");
for (s = str; *s != 0; ) {
if (*s++ == '\\') {
(void)esccon(&s);
}
- if (s - str > 64) {
+ if (s - str > 60) {
fwrite(str, 1, s - str, stdout);
printf("\"\n\t.ascii \"");
str = s;
@@ -453,6 +876,28 @@
printf("\\0\"\n");
}
+/*
+ * Print out a wide string by calling ninval().
+ */
+void
+inwstring(struct symtab *sp)
+{
+ char *s = sp->sname;
+ NODE *p;
+
+ defloc(sp);
+ p = xbcon(0, NULL, WCHAR_TYPE);
+ do {
+ if (*s++ == '\\')
+ p->n_lval = esccon(&s);
+ else
+ p->n_lval = (unsigned char)s[-1];
+ ninval(0, (MKSUE(WCHAR_TYPE))->suesize, p);
+ } while (s[-1] != 0);
+ nfree(p);
+}
+
+
static int inbits, inval;
/*
@@ -520,6 +965,9 @@
{
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;
@@ -527,6 +975,34 @@
if (t > BTMASK)
t = INT; /* pointer */
+ while (p->n_op == SCONV || p->n_op == PCONV) {
+ NODE *l = p->n_left;
+ l->n_type = p->n_type;
+ p = l;
+ }
+
+ if (kflag && (p->n_op == PLUS || p->n_op == UMUL)) {
+ if (p->n_op == UMUL)
+ p = p->n_left;
+ p = p->n_right;
+ q = p->n_sp;
+
+#if 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");
@@ -547,17 +1023,26 @@
case UNSIGNED:
printf("\t.long 0x%x", (int)p->n_lval);
if ((q = p->n_sp) != NULL) {
- if ((q->sclass == STATIC && q->slevel > 0) ||
- q->sclass == ILABEL) {
+ if ((q->sclass == STATIC && q->slevel > 0)) {
printf("+" LABFMT, q->soffset);
- } else
- printf("+%s", exname(q->sname));
+ } else {
+#if defined(MACHOABI)
+ if ((q->sflags & SNOUNDERSCORE) != 0)
+ printf("+%s", q->soname);
+ else
+#endif
+ printf("+%s", exname(q->soname));
+ }
}
printf("\n");
break;
case SHORT:
case USHORT:
+#ifdef os_sunos
+ printf("\t.2byte 0x%x\n", (int)p->n_lval & 0xffff);
+#else
printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff);
+#endif
break;
case BOOL:
if (p->n_lval > 1)
@@ -570,11 +1055,20 @@
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;
@@ -585,49 +1079,33 @@
}
}
-#if 0
-/*
- * print out an integer.
- */
-void
-inval(CONSZ word)
-{
- word &= 0xffffffff;
- printf(" .long 0x%llx\n", word);
-}
-
-/* output code to initialize a floating point value */
-/* the proper alignment has been obtained */
-void
-finval(NODE *p)
-{
- union { float f; double d; long double l; int i[3]; } u;
-
- switch (p->n_type) {
- case LDOUBLE:
- u.i[2] = 0;
- u.l = (long double)p->n_dcon;
- printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]);
- break;
- case DOUBLE:
- u.d = (double)p->n_dcon;
- printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]);
- break;
- case FLOAT:
- u.f = (float)p->n_dcon;
- printf("\t.long\t0x%x\n", u.i[0]);
- break;
- }
-}
-#endif
-
/* make a name look like an external name in the local machine */
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
}
/*
@@ -660,84 +1138,294 @@
/* make a common declaration for id, if reasonable */
void
-commdec(struct symtab *q)
+defzero(struct symtab *sp)
{
int off;
+ int al;
- off = tsize(q->stype, q->sdf, q->ssue);
- off = (off+(SZCHAR-1))/SZCHAR;
-#ifdef GCC_COMPAT
- printf(" .comm %s,0%o\n", gcc_findname(q), off);
-#else
- printf(" .comm %s,0%o\n", exname(q->sname), off);
+#ifdef TLS
+ if (sp->sflags & STLS) {
+ if (sp->sclass == EXTERN)
+ sp->sclass = EXTDEF;
+ simpleinit(sp, bcon(0));
+ return;
+ }
#endif
+
+ al = talign(sp->stype, sp->ssue)/SZCHAR;
+ off = tsize(sp->stype, sp->sdf, sp->ssue);
+ off = (off+(SZCHAR-1))/SZCHAR;
+ printf(" .%scomm ", sp->sclass == STATIC ? "l" : "");
+ if (sp->slevel == 0)
+ printf("%s,0%o", exname(sp->soname), off);
+ else
+ printf(LABFMT ",0%o", sp->soffset, off);
+ if (sp->sclass != STATIC)
+ printf(",%d", al);
+ printf("\n");
}
-/* make a local common declaration for id, if reasonable */
-void
-lcommdec(struct symtab *q)
+static char *
+section2string(char *name, int len)
{
- int off;
+#if defined(ELFABI)
+ char *s;
+ int n;
- off = tsize(q->stype, q->sdf, q->ssue);
- off = (off+(SZCHAR-1))/SZCHAR;
- if (q->slevel == 0)
-#ifdef GCC_COMPAT
- printf(" .lcomm %s,0%o\n", gcc_findname(q), off);
-#else
- printf(" .lcomm %s,0%o\n", exname(q->sname), off);
+ if (strncmp(name, "link_set", 8) == 0) {
+ const char *postfix = ",\"aw\", at progbits";
+ n = len + strlen(postfix) + 1;
+ s = IALLOC(n);
+ strlcpy(s, name, n);
+ strlcat(s, postfix, n);
+ return s;
+ }
#endif
- else
- printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off);
+
+ 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;
+
/*
- * print a (non-prog) label.
+ * Give target the opportunity of handling pragmas.
+ */
+int
+mypragma(char **ary)
+{
+#ifdef TLS
+ if (strcmp(ary[1], "tls") == 0 && ary[2] == NULL) {
+ gottls = 1;
+ return 1;
+ }
+#endif
+#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;
+ }
+ if (strcmp(ary[1], "ident") == 0)
+ return 1; /* Just ignore */
+
+ return 0;
+}
+
+/*
+ * Called when a identifier has been declared.
*/
void
-deflab1(int label)
+fixdef(struct symtab *sp)
{
- printf(LABFMT ":\n", label);
+#ifdef TLS
+ /* may have sanity checks here */
+ 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\", at progbits\n",
+ constructor ? 'c' : 'd');
+#elif defined(PECOFFABI)
+ printf("\t.section .%ctors,\"w\"\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
}
-static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" };
+NODE *
+i386_builtin_return_address(NODE *f, NODE *a)
+{
+ int nframes;
+
+ if (a == NULL || a->n_op != ICON)
+ goto bad;
-void
-setloc1(int locc)
+ 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)
{
- if (locc == lastloc)
- return;
- lastloc = locc;
- printf(" .%s\n", loctbl[locc]);
+ 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);
}
-#if 0
-int
-ftoint(NODE *p, CONSZ **c)
+#ifdef os_win32
+/*
+ * Postfix external functions with the arguments size.
+ */
+static void
+mangle(NODE *p, void *arg)
{
- static CONSZ cc[3];
- union { float f; double d; long double l; int i[3]; } u;
- int n;
+ NODE *l, *r;
+ TWORD t;
+ int size = 0;
+ char buf[64];
- switch (p->n_type) {
- case LDOUBLE:
- u.i[2] = 0;
- u.l = (long double)p->n_dcon;
- n = SZLDOUBLE;
- break;
- case DOUBLE:
- u.d = (double)p->n_dcon;
- n = SZDOUBLE;
- break;
- case FLOAT:
- u.f = (float)p->n_dcon;
- n = SZFLOAT;
- break;
+ 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;
}
- cc[0] = u.i[0];
- cc[1] = u.i[1];
- cc[2] = u.i[2];
- *c = cc;
- return n;
}
#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, 0);
+#endif
+}
Index: reader.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/mip/reader.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/mip/reader.c -L usr.bin/pcc/mip/reader.c -u -r1.1 -r1.2
--- usr.bin/pcc/mip/reader.c
+++ usr.bin/pcc/mip/reader.c
@@ -1,4 +1,4 @@
-/* $Id: reader.c,v 1.203 2007/09/24 17:49:54 ragge Exp $ */
+/* $Id: reader.c,v 1.248 2008/12/03 07:08:40 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -61,12 +61,8 @@
*/
/*
- * Everything is entered via pass2_compile(). Three functions are
- * allowed to recurse into pass2_compile(), so be careful:
- * - deluseless()
- * - myreader()
- * Especially in myreader note that trees may be rewritten twice if
- * things are not carefully handled.
+ * Everything is entered via pass2_compile(). No functions are
+ * allowed to recurse back into pass2_compile().
*/
# include "pass2.h"
@@ -86,59 +82,185 @@
NODE *nodepole;
FILE *prfil;
-static struct interpass prepole;
+struct interpass prepole;
void saveip(struct interpass *ip);
-void deljumps(void);
-void deltemp(NODE *p);
-void mkhardops(NODE *p);
-void optdump(struct interpass *ip);
-void cvtemps(struct interpass *epil);
+void deltemp(NODE *p, void *);
+static void cvtemps(struct interpass *ipole, int op, int off);
NODE *store(NODE *);
-void rcount(void);
-void compile2(struct interpass *ip);
-void compile3(struct interpass *ip);
-void compile4(struct interpass *ip);
+static void fixxasm(struct p2env *);
static void gencode(NODE *p, int cookie);
+static void genxasm(NODE *p);
-char *ltyp[] = { "", "LREG", "LOREG", "LTEMP" };
-char *rtyp[] = { "", "RREG", "ROREG", "RTEMP" };
+struct p2env p2env;
-/* used when removing nodes */
-struct tmpsave {
- struct tmpsave *next;
- CONSZ tempaddr;
- int tempno;
-} *tmpsave;
+int
+getlab2(void)
+{
+ extern int getlab(void);
+ int rv = getlab();
+#ifdef PCC_DEBUG
+ if (p2env.epp->ip_lblnum != rv)
+ comperr("getlab2 error: %d != %d", p2env.epp->ip_lblnum, rv);
+#endif
+ p2env.epp->ip_lblnum++;
+ return rv;
+}
#ifdef PCC_DEBUG
+static int *lbldef, *lbluse;
static void
-cktree(NODE *p)
+cktree(NODE *p, void *arg)
{
+ int i;
+
if (p->n_op > MAXOP)
- cerror("op %d slipped through", p->n_op);
+ cerror("%p) op %d slipped through", p, p->n_op);
if (BTYPE(p->n_type) > MAXTYPES)
- cerror("type %x slipped through", p->n_type);
- if (p->n_op == CBRANCH && !logop(p->n_left->n_op))
- cerror("not logop branch");
+ cerror("%p) type %x slipped through", p, p->n_type);
+ if (p->n_op == CBRANCH) {
+ if (!logop(p->n_left->n_op))
+ cerror("%p) not logop branch", p);
+ i = p->n_right->n_lval;
+ if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum)
+ cerror("%p) label %d outside boundaries %d-%d",
+ p, i, p2env.ipp->ip_lblnum, p2env.epp->ip_lblnum);
+ lbluse[i-p2env.ipp->ip_lblnum] = 1;
+ }
if ((dope[p->n_op] & ASGOPFLG) && p->n_op != RETURN)
- cerror("asgop %d slipped through", p->n_op);
+ cerror("%p) asgop %d slipped through", p, p->n_op);
+ if (p->n_op == TEMP &&
+ (regno(p) < p2env.ipp->ip_tmpnum || regno(p) >= p2env.epp->ip_tmpnum))
+ cerror("%p) temporary %d outside boundaries %d-%d",
+ p, regno(p), p2env.ipp->ip_tmpnum, p2env.epp->ip_tmpnum);
+ if (p->n_op == GOTO) {
+ i = p->n_left->n_lval;
+ if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum)
+ cerror("%p) label %d outside boundaries %d-%d",
+ p, i, p2env.ipp->ip_lblnum, p2env.epp->ip_lblnum);
+ lbluse[i-p2env.ipp->ip_lblnum] = 1;
+ }
+}
+
+/*
+ * Check that the trees are in a suitable state for pass2.
+ */
+static void
+sanitychecks(struct p2env *p2e)
+{
+ struct interpass *ip;
+ int i;
+#ifdef notyet
+ TMPMARK();
+#endif
+ lbldef = tmpcalloc(sizeof(int) * (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum));
+ lbluse = tmpcalloc(sizeof(int) * (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum));
+
+ DLIST_FOREACH(ip, &p2env.ipole, qelem) {
+ if (ip->type == IP_DEFLAB) {
+ i = ip->ip_lbl;
+ if (i < p2e->ipp->ip_lblnum || i >= p2e->epp->ip_lblnum)
+ cerror("label %d outside boundaries %d-%d",
+ i, p2e->ipp->ip_lblnum, p2e->epp->ip_lblnum);
+ lbldef[i-p2e->ipp->ip_lblnum] = 1;
+ }
+ if (ip->type == IP_NODE)
+ walkf(ip->ip_node, cktree, 0);
+ }
+ for (i = 0; i < (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum); i++)
+ if (lbluse[i] != 0 && lbldef[i] == 0)
+ cerror("internal label %d not defined",
+ i + p2e->ipp->ip_lblnum);
+
+#ifdef notyet
+ TMPFREE();
+#endif
}
#endif
/*
+ * Look if a temporary comes from a on-stack argument, in that case
+ * use the already existing stack position instead of moving it to
+ * a new place, and remove the move-to-temp statement.
+ */
+static int
+stkarg(int tnr, int *soff)
+{
+ struct p2env *p2e = &p2env;
+ struct interpass *ip;
+ NODE *p;
+
+ ip = DLIST_NEXT((struct interpass *)p2e->ipp, qelem);
+ while (ip->type != IP_DEFLAB) /* search for first DEFLAB */
+ ip = DLIST_NEXT(ip, qelem);
+
+ ip = DLIST_NEXT(ip, qelem); /* first NODE */
+
+ for (; ip->type != IP_DEFLAB; ip = DLIST_NEXT(ip, qelem)) {
+ if (ip->type != IP_NODE)
+ continue;
+
+ p = ip->ip_node;
+ if (p->n_op == XASM)
+ continue; /* XXX - hack for x86 PIC */
+#ifdef PCC_DEBUG
+ if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
+ comperr("temparg");
+#endif
+ if (p->n_right->n_op != OREG && p->n_right->n_op != UMUL)
+ continue; /* arg in register */
+ if (tnr != regno(p->n_left))
+ continue; /* wrong assign */
+ p = p->n_right;
+ if (p->n_op == UMUL &&
+ p->n_left->n_op == PLUS &&
+ p->n_left->n_left->n_op == REG &&
+ p->n_left->n_right->n_op == ICON)
+ *soff = p->n_left->n_right->n_lval;
+ else if (p->n_op == OREG)
+ *soff = p->n_lval;
+ else
+ comperr("stkarg: bad arg");
+ tfree(ip->ip_node);
+ DLIST_REMOVE(ip, qelem);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * See if an ADDROF is somewhere inside the expression tree.
+ * If so, fill in the offset table.
+ */
+static void
+findaof(NODE *p, void *arg)
+{
+ int *aof = arg;
+ int tnr;
+
+ if (p->n_op != ADDROF)
+ return;
+ tnr = regno(p->n_left);
+ if (aof[tnr])
+ return; /* already gotten stack address */
+ if (stkarg(tnr, &aof[tnr]))
+ return; /* argument was on stack */
+ aof[tnr] = BITOOR(freetemp(szty(p->n_left->n_type)));
+}
+
+/*
* Check if a node has side effects.
*/
static int
isuseless(NODE *n)
{
switch (n->n_op) {
+ case XASM:
case FUNARG:
case UCALL:
case UFORTCALL:
case FORCE:
-/* case INIT: */
case ASSIGN:
case CALL:
case FORTCALL:
@@ -158,7 +280,7 @@
/*
* Delete statements with no meaning (like a+b; or 513.4;)
*/
-static NODE *
+NODE *
deluseless(NODE *p)
{
struct interpass *ip;
@@ -192,70 +314,111 @@
return NULL;
}
-static struct interpass ipole;
-struct interpass_prolog *ipp, *epp;
-
/*
* Receives interpass structs from pass1.
*/
void
pass2_compile(struct interpass *ip)
{
+ struct p2env *p2e = &p2env;
+ int *addrp;
+ MARK mark;
+
if (ip->type == IP_PROLOG) {
- tmpsave = NULL;
- ipp = (struct interpass_prolog *)ip;
- DLIST_INIT(&ipole, qelem);
+ memset(p2e, 0, sizeof(struct p2env));
+ p2e->ipp = (struct interpass_prolog *)ip;
+ DLIST_INIT(&p2e->ipole, qelem);
}
- DLIST_INSERT_BEFORE(&ipole, ip, qelem);
+ DLIST_INSERT_BEFORE(&p2e->ipole, ip, qelem);
if (ip->type != IP_EPILOG)
return;
#ifdef PCC_DEBUG
if (e2debug) {
printf("Entering pass2\n");
- printip(&ipole);
+ printip(&p2e->ipole);
}
#endif
- epp = (struct interpass_prolog *)DLIST_PREV(&ipole, qelem);
- p2maxautooff = p2autooff = epp->ipp_autos;
+ p2e->epp = (struct interpass_prolog *)DLIST_PREV(&p2e->ipole, qelem);
+ p2maxautooff = p2autooff = p2e->epp->ipp_autos;
- myreader(&ipole); /* local massage of input */
+#ifdef PCC_DEBUG
+ sanitychecks(p2e);
+#endif
+ myreader(&p2e->ipole); /* local massage of input */
+
+ /*
+ * Do initial modification of the trees. Two loops;
+ * - first, search for ADDROF of TEMPs, these must be
+ * converterd to OREGs on stack.
+ * - second, do the actual conversions, in case of not xtemps
+ * convert all temporaries to stack references.
+ */
+ markset(&mark);
+ if (p2e->epp->ip_tmpnum != p2e->ipp->ip_tmpnum) {
+ addrp = tmpcalloc(sizeof(int) *
+ (p2e->epp->ip_tmpnum - p2e->ipp->ip_tmpnum));
+ addrp -= p2e->ipp->ip_tmpnum;
+ } else
+ addrp = NULL;
+ if (xtemps) {
+ DLIST_FOREACH(ip, &p2e->ipole, qelem) {
+ if (ip->type == IP_NODE)
+ walkf(ip->ip_node, findaof, addrp);
+ }
+ }
+ DLIST_FOREACH(ip, &p2e->ipole, qelem)
+ if (ip->type == IP_NODE)
+ walkf(ip->ip_node, deltemp, addrp);
+ markfree(&mark);
+
+#ifdef PCC_DEBUG
+ if (e2debug) {
+ printf("Efter ADDROF/TEMP\n");
+ printip(&p2e->ipole);
+ }
+#endif
- DLIST_FOREACH(ip, &ipole, qelem) {
+#if 0
+ DLIST_FOREACH(ip, &p2e->ipole, qelem) {
if (ip->type != IP_NODE)
continue;
if (xtemps == 0)
- walkf(ip->ip_node, deltemp);
+ walkf(ip->ip_node, deltemp, 0);
}
+#endif
+
DLIST_INIT(&prepole, qelem);
- DLIST_FOREACH(ip, &ipole, qelem) {
+ DLIST_FOREACH(ip, &p2e->ipole, qelem) {
if (ip->type != IP_NODE)
continue;
canon(ip->ip_node);
- walkf(ip->ip_node, cktree);
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);
}
}
- optimize(&ipole);
- ngenregs(&ipole);
+ fixxasm(p2e); /* setup for extended asm */
- DLIST_FOREACH(ip, &ipole, qelem)
+ optimize(p2e);
+ ngenregs(p2e);
+
+ DLIST_FOREACH(ip, &p2e->ipole, qelem)
emit(ip);
}
void
emit(struct interpass *ip)
{
- NODE *p;
+ NODE *p, *r;
+ struct optab *op;
int o;
switch (ip->type) {
@@ -263,23 +426,36 @@
p = ip->ip_node;
nodepole = p;
-//printf("bu:\n");
-//fwalk(p, e2print, 0);
canon(p); /* may convert stuff after genregs */
-//fwalk(p, e2print, 0);
+ if (c2debug > 1) {
+ printf("emit IP_NODE:\n");
+ fwalk(p, e2print, 0);
+ }
switch (p->n_op) {
case CBRANCH:
/* Only emit branch insn if RESCC */
- if (table[TBLIDX(p->n_left->n_su)].rewrite & RESCC) {
+ /* careful when an OPLOG has been elided */
+ if (p->n_left->n_su == 0 && p->n_left->n_left != NULL) {
+ op = &table[TBLIDX(p->n_left->n_left->n_su)];
+ r = p->n_left;
+ } else {
+ op = &table[TBLIDX(p->n_left->n_su)];
+ r = p;
+ }
+ if (op->rewrite & RESCC) {
o = p->n_left->n_op;
- gencode(p, FORCC);
+ gencode(r, FORCC);
cbgen(o, p->n_right->n_lval);
- } else
- gencode(p, FORCC);
+ } else {
+ gencode(r, FORCC);
+ }
break;
case FORCE:
gencode(p->n_left, INREGS);
break;
+ case XASM:
+ genxasm(p);
+ break;
default:
if (p->n_op != REG || p->n_type != VOID) /* XXX */
gencode(p, FOREFF); /* Emit instructions */
@@ -292,17 +468,16 @@
break;
case IP_EPILOG:
eoftn((struct interpass_prolog *)ip);
- tmpsave = NULL; /* Always forget old nodes */
p2maxautooff = p2autooff = AUTOINIT/SZCHAR;
break;
case IP_DEFLAB:
deflab(ip->ip_lbl);
break;
case IP_ASM:
- printf("\t%s\n", ip->ip_asm);
+ printf("%s", ip->ip_asm);
break;
default:
- cerror("compile4 %d", ip->type);
+ cerror("emit %d", ip->type);
}
}
@@ -370,7 +545,7 @@
geninsn(NODE *p, int cookie)
{
NODE *p1, *p2;
- int o, rv = 0;
+ int q, o, rv = 0;
#ifdef PCC_DEBUG
if (odebug) {
@@ -379,6 +554,9 @@
}
#endif
+ q = cookie & QUIET;
+ cookie &= ~QUIET; /* XXX - should not be necessary */
+
again: switch (o = p->n_op) {
case EQ:
case NE:
@@ -390,6 +568,18 @@
case ULT:
case UGE:
case UGT:
+ p1 = p->n_left;
+ p2 = p->n_right;
+ if (p2->n_op == ICON && p2->n_lval == 0 &&
+ optype(p1->n_op) == BITYPE) {
+#ifdef mach_pdp11 /* XXX all targets? */
+ if ((rv = geninsn(p1, FORCC|QUIET)) != FFAIL)
+ break;
+#else
+ if (findops(p1, FORCC) > 0)
+ break;
+#endif
+ }
rv = relops(p);
break;
@@ -407,6 +597,11 @@
break;
case ASSIGN:
+#ifdef FINDMOPS
+ if ((rv = findmops(p, cookie)) != FFAIL)
+ break;
+ /* FALLTHROUGH */
+#endif
case STASG:
rv = findasg(p, cookie);
break;
@@ -419,6 +614,7 @@
case TEMP:
case NAME:
case ICON:
+ case FCON:
case OREG:
rv = findleaf(p, cookie);
break;
@@ -427,9 +623,10 @@
case CALL:
/* CALL arguments are handled special */
for (p1 = p->n_right; p1->n_op == CM; p1 = p1->n_left)
- geninsn(p1->n_right, FOREFF);
- geninsn(p1, FOREFF);
+ (void)geninsn(p1->n_right, FOREFF);
+ (void)geninsn(p1, FOREFF);
/* FALLTHROUGH */
+ case FLD:
case COMPL:
case UMINUS:
case PCONV:
@@ -440,6 +637,7 @@
case STARG:
case UCALL:
case USTCALL:
+ case ADDROF:
rv = finduni(p, cookie);
break;
@@ -447,23 +645,39 @@
p1 = p->n_left;
p2 = p->n_right;
p1->n_label = p2->n_lval;
- o = p1->n_op;
- geninsn(p1, FORCC);
+ (void)geninsn(p1, FORCC);
p->n_su = 0;
break;
case FORCE: /* XXX needed? */
- geninsn(p->n_left, INREGS);
+ (void)geninsn(p->n_left, INREGS);
p->n_su = 0; /* su calculations traverse left */
break;
+ case XASM:
+ for (p1 = p->n_left; p1->n_op == CM; p1 = p1->n_left)
+ (void)geninsn(p1->n_right, FOREFF);
+ (void)geninsn(p1, FOREFF);
+ break; /* all stuff already done? */
+
+ case XARG:
+ /* generate code for correct class here */
+// geninsn(p->n_left, 1 << p->n_label);
+ break;
+
default:
comperr("geninsn: bad op %s, node %p", opst[o], p);
}
- if (rv == FFAIL)
+ if (rv == FFAIL && !q)
comperr("Cannot generate code, node %p op %s", p,opst[p->n_op]);
if (rv == FRETRY)
goto again;
+#ifdef PCC_DEBUG
+ if (odebug) {
+ printf("geninsn(%p, %s) rv %d\n", p, prcook(cookie), rv);
+ fwalk(p, e2print, 0);
+ }
+#endif
return rv;
}
@@ -514,7 +728,7 @@
* 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;
@@ -550,18 +764,75 @@
tfree(l);
if (optype(o) == BITYPE)
tfree(r);
- if (rewrite == 0)
+ if (dorewrite == 0)
return;
- CDEBUG(("rewrite: %p, reg %s\n", p, rnames[DECRA(p->n_reg, 0)]));
+ 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.
+ */
+void
+genxasm(NODE *p)
+{
+ NODE *q, **nary;
+ int n = 1, o = 0;
+ char *w;
+
+ 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] == '%')
+ 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]-'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++;
+ }
+ putchar('\n');
+}
+
void
gencode(NODE *p, int cookie)
{
struct optab *q = &table[TBLIDX(p->n_su)];
NODE *p1, *l, *r;
int o = optype(p->n_op);
+#ifdef FINDMOPS
+ int ismops = (p->n_op == ASSIGN && (p->n_flags & 1));
+#endif
l = p->n_left;
r = p->n_right;
@@ -598,7 +869,12 @@
}
if (o != LTYPE) {
gencode(l, INREGS);
- if (q->rewrite & RLEFT)
+#ifdef FINDMOPS
+ if (ismops)
+ ;
+ else
+#endif
+ if (q->rewrite & RLEFT)
ckmove(p, l);
}
if (o == BITYPE && !(p->n_su & DORIGHT)) {
@@ -607,6 +883,18 @@
ckmove(p, r);
}
+#ifdef FINDMOPS
+ if (ismops) {
+ /* reduce right tree to make expand() work */
+ if (optype(r->n_op) != LTYPE) {
+ p->n_op = r->n_op;
+ r = tcopy(r->n_right);
+ tfree(p->n_right);
+ p->n_right = r;
+ }
+ }
+#endif
+
canon(p);
if (q->needs & NSPECIAL) {
@@ -614,6 +902,10 @@
int lr = rspecial(q, NLEFT);
if (rr >= 0) {
+#ifdef PCC_DEBUG
+ if (optype(p->n_op) != BITYPE)
+ comperr("gencode: rspecial borked");
+#endif
if (r->n_op != REG)
comperr("gencode: rop != REG");
if (rr != r->n_rval)
@@ -633,7 +925,8 @@
if (p->n_op == ASSIGN &&
p->n_left->n_op == REG && p->n_right->n_op == REG &&
- p->n_left->n_rval == p->n_right->n_rval){
+ p->n_left->n_rval == p->n_right->n_rval &&
+ (p->n_su & RVCC) == 0) { /* XXX should check if necessary */
/* do not emit anything */
CDEBUG(("gencode(%p) assign nothing\n", p));
rewrite(p, q->rewrite, cookie);
@@ -645,6 +938,12 @@
return;
expand(p, cookie, q->cstring);
+#ifdef FINDMOPS
+ if (ismops && DECRA(p->n_reg, 0) != regno(l) && cookie != FOREFF) {
+ CDEBUG(("gencode(%p) rmove\n", p));
+ rmove(regno(l), DECRA(p->n_reg, 0), p->n_type);
+ } else
+#endif
if (callop(p->n_op) && cookie != FOREFF &&
DECRA(p->n_reg, 0) != RETREG(p->n_type)) {
CDEBUG(("gencode(%p) retreg\n", p));
@@ -681,6 +980,7 @@
}
int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ; /* negatives of relationals */
+size_t negrelsize = sizeof negrel / sizeof negrel[0];
#ifdef PCC_DEBUG
#undef PRTABLE
@@ -708,7 +1008,12 @@
break;
case TEMP:
- fprintf(prfil, " " CONFMT, p->n_lval);
+ fprintf(prfil, " %d", regno(p));
+ break;
+
+ case XASM:
+ case XARG:
+ fprintf(prfil, " '%s'", p->n_name);
break;
case ICON:
@@ -730,16 +1035,9 @@
fprintf(prfil, ", " );
tprint(prfil, p->n_type, p->n_qual);
fprintf(prfil, ", " );
- {
- int gregn(struct regw *);
- if (p->n_reg == -1)
- fprintf(prfil, "REG <undef>");
- else if (p->n_reg < 100000) /* XXX */
- fprintf(prfil, "REG %s", rnames[DECRA(p->n_reg, 0)]);
- else
- fprintf(prfil, "TEMP %d", gregn(p->n_regw));
- }
- fprintf(prfil, ", SU= %d(%cREG,%s,%s,%s,%s)\n",
+
+ prtreg(prfil, p);
+ fprintf(prfil, ", SU= %d(%cREG,%s,%s,%s,%s,%s,%s)\n",
TBLIDX(p->n_su),
TCLASS(p->n_su)+'@',
#ifdef PRTABLE
@@ -748,8 +1046,9 @@
#else
"",
#endif
- ltyp[LMASK&p->n_su],
- rtyp[(p->n_su&RMASK) >> 2], p->n_su & DORIGHT ? "DORIGHT" : "");
+ p->n_su & LREG ? "LREG" : "", p->n_su & RREG ? "RREG" : "",
+ p->n_su & RVEFF ? "RVEFF" : "", p->n_su & RVCC ? "RVCC" : "",
+ p->n_su & DORIGHT ? "DORIGHT" : "");
}
#endif
@@ -815,35 +1114,32 @@
* change left TEMPs into OREGs
*/
void
-deltemp(NODE *p)
+deltemp(NODE *p, void *arg)
{
- struct tmpsave *w;
- NODE *l;
+ int *aor = arg;
+ NODE *l, *r;
if (p->n_op == TEMP) {
- /* Check if already existing */
- for (w = tmpsave; w; w = w->next)
- if (w->tempno == p->n_lval)
- break;
- if (w == NULL) {
- /* new on stack */
- w = tmpalloc(sizeof(struct tmpsave));
- w->tempno = p->n_lval;
- w->tempaddr = BITOOR(freetemp(szty(p->n_type)));
- w->next = tmpsave;
- tmpsave = w;
- }
- p->n_op = OREG;
- p->n_rval = FPREG;
- p->n_lval = w->tempaddr;
- } else if (p->n_op == ADDROF) {
- /* TEMPs are already converted to OREGs */
- if ((l = p->n_left)->n_op != OREG)
- comperr("bad U&");
+ if (aor[regno(p)] == 0) {
+ if (xtemps)
+ return;
+ aor[regno(p)] = BITOOR(freetemp(szty(p->n_type)));
+ }
+ l = mklnode(REG, 0, FPREG, INCREF(p->n_type));
+ r = mklnode(ICON, aor[regno(p)], 0, INT);
+ p->n_left = mkbinode(PLUS, l, r, INCREF(p->n_type));
+ p->n_op = UMUL;
+ } else if (p->n_op == ADDROF && p->n_left->n_op == OREG) {
p->n_op = PLUS;
+ l = p->n_left;
l->n_op = REG;
l->n_type = INCREF(l->n_type);
p->n_right = mklnode(ICON, l->n_lval, 0, INT);
+ } else if (p->n_op == ADDROF && p->n_left->n_op == UMUL) {
+ l = p->n_left;
+ *p = *p->n_left->n_left;
+ nfree(l->n_left);
+ nfree(l);
}
}
@@ -851,7 +1147,7 @@
* for pointer/integer arithmetic, set pointer at left node
*/
static void
-setleft(NODE *p)
+setleft(NODE *p, void *arg)
{
NODE *q;
@@ -909,10 +1205,10 @@
int i;
if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) {
makeor2(p, ql, r, i);
- return;
+ return 1;
} else if((r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) {
makeor2(p, qr, r, i);
- return;
+ return 1;
}
}
@@ -966,7 +1262,7 @@
* look for situations where we can turn * into OREG
*/
void
-oreg2(NODE *p)
+oreg2(NODE *p, void *arg)
{
if (p->n_op != UMUL)
return;
@@ -980,14 +1276,12 @@
canon(p) NODE *p; {
/* put p in canonical form */
- walkf(p, setleft); /* ptrs at left node for arithmetic */
- walkf(p, oreg2); /* look for and create OREG nodes */
+ walkf(p, setleft, 0); /* ptrs at left node for arithmetic */
+ walkf(p, oreg2, 0); /* look for and create OREG nodes */
#ifndef FIELDOPS
fwalk(p, ffld, 0); /* look for field operators */
# endif
-#ifdef MYCANON
- MYCANON(p); /* your own canonicalization routine(s) */
-#endif
+ mycanon(p); /* your own canonicalization routine(s) */
}
@@ -997,6 +1291,12 @@
extern char *ftitle;
va_list ap;
+ if (nerrors) {
+ fprintf(stderr,
+ "cannot recover from earlier errors: goodbye!\n");
+ exit(1);
+ }
+
va_start(ap, str);
fprintf(stderr, "%s, line %d: compiler error: ", ftitle, thisline);
vfprintf(stderr, str, ap);
@@ -1004,8 +1304,10 @@
va_end(ap);
prfil = stderr;
+#ifdef PCC_DEBUG
if (nodepole && nodepole->n_op != FREE)
fwalk(nodepole, e2print, 0);
+#endif
exit(1);
}
@@ -1050,6 +1352,7 @@
p->n_name = "";
p->n_qual = 0;
p->n_op = op;
+ p->n_label = 0;
p->n_lval = lval;
p->n_rval = rval;
p->n_type = type;
@@ -1066,10 +1369,12 @@
p->n_name = "";
p->n_qual = 0;
p->n_op = op;
+ p->n_label = 0;
p->n_left = left;
p->n_right = right;
p->n_type = type;
p->n_regw = NULL;
+ p->n_su = 0;
return p;
}
@@ -1081,10 +1386,12 @@
p->n_name = "";
p->n_qual = 0;
p->n_op = op;
+ p->n_label = 0;
p->n_left = left;
p->n_rval = rval;
p->n_type = type;
p->n_regw = NULL;
+ p->n_su = 0;
return p;
}
@@ -1110,3 +1417,222 @@
}
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, p2env.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(NODE *p, void *arg)
+{
+ struct interpass *ip = arg;
+ struct interpass *ip2;
+ TWORD t = p->n_left->n_type;
+ NODE *q, *r;
+ int cw, ooff;
+ char *c;
+
+again:
+ if (myxasm(ip, p))
+ return; /* handled by target-specific code */
+
+ 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 (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, p2env.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 = p2env.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;
+ 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);
+ }
+}
+
+/* Extended assembler hacks */
+static void
+fixxasm(struct p2env *p2e)
+{
+ struct interpass *pole = &p2e->ipole;
+ struct interpass *ip;
+ NODE *p;
+
+ DLIST_FOREACH(ip, pole, qelem) {
+ if (ip->type != IP_NODE || ip->ip_node->n_op != XASM)
+ continue;
+ 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.
+ */
+ 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, void *arg)
+{
+ 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, 0);
+ walkf(ipl->ip_node, xconv, 0);
+}
Index: node.h
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/mip/node.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/mip/node.h -L usr.bin/pcc/mip/node.h -u -r1.1 -r1.2
--- usr.bin/pcc/mip/node.h
+++ usr.bin/pcc/mip/node.h
@@ -1,4 +1,4 @@
-/* $Id: node.h,v 1.31 2007/07/22 12:50:56 ragge Exp $ */
+/* $Id: node.h,v 1.35 2008/09/04 08:00:11 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -26,6 +26,9 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef NODE_H
+#define NODE_H
+
/*
* The node structure is the basic element in the compiler.
* Depending on the operator, it may be one of several types.
@@ -60,6 +63,7 @@
union {
int _label;
int _stalign;
+ int _flags;
struct suedef *_sue;
} n_6;
union {
@@ -77,7 +81,18 @@
struct symtab *_sp;
} n_r;
} n_u;
+#ifdef SOFTFLOAT
+#ifdef FDFLOAT
+ /* To store F- or D-floats */
+ struct softfloat {
+ unsigned short fd1, fd2, fd3, fd4;
+ } _dcon;
+#else
+#error missing softfloat structure definition
+#endif
+#else
long double _dcon;
+#endif
} n_f;
} NODE;
@@ -87,6 +102,7 @@
#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
@@ -97,6 +113,9 @@
#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.
*
@@ -113,7 +132,7 @@
#define REG 6
#define OREG 7
#define TEMP 8
-#define MOVE 9 /* Special reg-reg move node */
+#define XARG 9
/*
* Arithmetic nodes.
@@ -184,7 +203,7 @@
#define STASG 50
#define STARG 51
#define FORCE 52
-/* #define INIT 53 */
+#define XASM 53
#define GOTO 54
#define RETURN 55
#define STREF 56
@@ -192,3 +211,5 @@
#define ADDROF 58
#define MAXOP 58
+
+#endif
Index: match.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/mip/match.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/mip/match.c -L usr.bin/pcc/mip/match.c -u -r1.1 -r1.2
--- usr.bin/pcc/mip/match.c
+++ usr.bin/pcc/mip/match.c
@@ -1,4 +1,4 @@
-/* $Id: match.c,v 1.72 2006/07/30 09:32:15 ragge Exp $ */
+/* $Id: match.c,v 1.89 2008/11/26 17:31:40 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -60,16 +60,15 @@
* 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);
-int fldsz, fldshf;
-
int s2debug = 0;
extern char *ltyp[], *rtyp[];
@@ -149,27 +148,14 @@
break;
case ICON:
+ case FCON:
if (shape & SCON)
return SRDIR;
break;
case FLD:
- if (shape & SFLD) {
- int sh;
-
- if ((sh = flshape(p->n_left)) == SRNOPE)
- return sh;
- /* it is a FIELD shape; make side-effects */
- /* XXX - this will not work for multi-matches */
- o = p->n_rval;
- fldsz = UPKFSZ(o);
-# ifdef RTOLBYTES
- fldshf = UPKFOFF(o);
-# else
- fldshf = SZINT - fldsz - UPKFOFF(o);
-# endif
- return sh;
- }
+ if (shape & SFLD)
+ return flshape(p->n_left);
break;
case CCODES:
@@ -190,9 +176,13 @@
break;
case UMUL:
+#if 0
if (shumul(p->n_left) & shape)
return SROREG; /* Calls offstar to traverse down */
break;
+#else
+ return shumul(p->n_left, shape);
+#endif
}
return SRNOPE;
@@ -264,6 +254,13 @@
return(0);
}
+#define FLDSZ(x) UPKFSZ(x)
+#ifdef RTOLBYTES
+#define FLDSHF(x) UPKFOFF(x)
+#else
+#define FLDSHF(x) (SZINT - FLDSZ(x) - UPKFOFF(x))
+#endif
+
/*
* generate code by interpreting table entry
*/
@@ -272,6 +269,9 @@
{
CONSZ val;
+//printf("expand\n");
+//fwalk(p, e2print, 0);
+
for( ; *cp; ++cp ){
switch( *cp ){
@@ -284,23 +284,34 @@
continue;
case 'F': /* this line deleted if FOREFF is active */
- if( cookie & FOREFF ) while( *++cp != '\n' ) ; /* VOID */
+ if (cookie & FOREFF) {
+ while (*cp && *cp != '\n')
+ cp++;
+ if (*cp == 0)
+ return;
+ }
continue;
case 'S': /* field size */
- printf( "%d", fldsz );
+ if (fldexpand(p, cookie, &cp))
+ continue;
+ printf("%d", FLDSZ(p->n_rval));
continue;
case 'H': /* field shift */
- printf( "%d", fldshf );
+ if (fldexpand(p, cookie, &cp))
+ continue;
+ printf("%d", FLDSHF(p->n_rval));
continue;
case 'M': /* field mask */
case 'N': /* complement of field mask */
+ if (fldexpand(p, cookie, &cp))
+ continue;
val = 1;
- val <<= fldsz;
+ val <<= FLDSZ(p->n_rval);
--val;
- val <<= fldshf;
+ val <<= FLDSHF(p->n_rval);
adrcon( *cp=='M' ? val : ~val );
continue;
@@ -312,6 +323,11 @@
continue;
case 'O': /* opcode string */
+#ifdef FINDMOPS
+ if (p->n_op == ASSIGN)
+ hopcode(*++cp, p->n_right->n_op);
+ else
+#endif
hopcode( *++cp, p->n_op );
continue;
@@ -382,26 +398,6 @@
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)
@@ -415,8 +411,8 @@
* Shape is register class where we want the result.
* Returns register class if register nodes.
* If w is: (should be shapes)
- * - LREG - result in register, call geninsn().
- * - LOREG - create OREG; call offstar().
+ * - SRREG - result in register, call geninsn().
+ * - SROREG - create OREG; call offstar().
* - 0 - clear su, walk down.
*/
static int
@@ -424,12 +420,14 @@
{
int rv = 0;
+ F2DEBUG(("swmatch: p=%p, shape=%s, w=%s\n", p, prcook(shape), srtyp[w]));
+
switch (w) {
- case LREG:
+ case SRREG:
rv = geninsn(p, shape);
break;
- case LOREG:
+ case SROREG:
/* should be here only if op == UMUL */
if (p->n_op != UMUL && p->n_op != FLD)
comperr("swmatch %p", p);
@@ -493,7 +491,8 @@
* p - node (for this leg)
* shape - given shape for this leg
* cookie - cookie given for parent node
- * rv - switch key for traversing down
+ * rew -
+ * go - switch key for traversing down
* returns register class.
*/
static int
@@ -501,20 +500,23 @@
{
int lsh;
+ F2DEBUG(("shswitch: p=%p, shape=%s, ", p, prcook(shape)));
+ F2DEBUG(("cookie=%s, rew=0x%x, go=%s\n", prcook(cookie), rew, srtyp[go]));
+
switch (go) {
case SRDIR: /* direct match, just clear su */
(void)swmatch(p, 0, 0);
break;
case SROREG: /* call offstar to prepare for OREG conversion */
- (void)swmatch(p, shape, LOREG);
+ (void)swmatch(p, shape, SROREG);
break;
case SRREG: /* call geninsn() to get value into register */
- lsh = shape & INREGS;
+ lsh = shape & (FORCC | INREGS);
if (rew && cookie != FOREFF)
- lsh &= (cookie & INREGS);
- lsh = swmatch(p, lsh, LREG);
+ lsh &= (cookie & (FORCC | INREGS));
+ lsh = swmatch(p, lsh, SRREG);
if (rew)
sh = lsh;
break;
@@ -549,7 +551,10 @@
for (i = 0; ixp[i] >= 0; i++) {
q = &table[ixp[i]];
- F2DEBUG(("findop: ixp %d\n", ixp[i]));
+ F2DEBUG(("findop: ixp %d str %s\n", ixp[i], q->cstring));
+ if (!acceptable(q)) /* target-dependent filter */
+ continue;
+
if (ttype(l->n_type, q->ltype) == 0 ||
ttype(r->n_type, q->rtype) == 0)
continue; /* Types must be correct */
@@ -565,7 +570,8 @@
F2DEBUG(("findop lshape %d\n", shl));
F2WALK(l);
- if ((shr = chcheck(r, q->rshape, q->rewrite & RRIGHT))== SRNOPE) continue;
+ if ((shr = chcheck(r, q->rshape, q->rewrite & RRIGHT)) == SRNOPE)
+ continue;
F2DEBUG(("findop rshape %d\n", shr));
F2WALK(r);
@@ -592,18 +598,26 @@
sh = -1;
+#ifdef mach_pdp11
+ if (cookie == FORCC && p->n_op != AND) /* XXX - fix */
+ cookie = INREGS;
+#else
+ if (cookie == FORCC)
+ cookie = INREGS;
+#endif
+
sh = shswitch(sh, p->n_left, qq->lshape, cookie,
qq->rewrite & RLEFT, gol);
sh = shswitch(sh, p->n_right, qq->rshape, cookie,
qq->rewrite & RRIGHT, gor);
if (sh == -1) {
- if (cookie == FOREFF)
+ if (cookie == FOREFF || cookie == FORCC)
sh = 0;
else
sh = ffs(cookie & qq->visit & INREGS)-1;
}
- F2DEBUG(("findops: node %p (%s)\n", p, prcook(1 << sh)));
+ F2DEBUG(("findops: node %p sh %d (%s)\n", p, sh, prcook(1 << sh)));
p->n_su = MKIDX(idx, 0);
SCLASS(p->n_su, sh);
return sh;
@@ -647,6 +661,9 @@
q = &table[ixp[i]];
F2DEBUG(("relops: ixp %d\n", ixp[i]));
+ if (!acceptable(q)) /* target-dependent filter */
+ continue;
+
if (ttype(l->n_type, q->ltype) == 0 ||
ttype(r->n_type, q->rtype) == 0)
continue; /* Types must be correct */
@@ -686,7 +703,7 @@
(void)shswitch(-1, p->n_right, q->rshape, FORCC,
q->rewrite & RRIGHT, gor);
- F2DEBUG(("findops: node %p\n", p));
+ F2DEBUG(("relops: node %p\n", p));
p->n_su = MKIDX(idx, 0);
SCLASS(p->n_su, CLASSA); /* XXX */
return 0;
@@ -727,7 +744,10 @@
for (i = 0; ixp[i] >= 0; i++) {
q = &table[ixp[i]];
- F2DEBUG(("asgop: ixp %d\n", ixp[i]));
+ F2DEBUG(("findasg: ixp %d\n", ixp[i]));
+ if (!acceptable(q)) /* target-dependent filter */
+ continue;
+
if (ttype(l->n_type, q->ltype) == 0 ||
ttype(r->n_type, q->rtype) == 0)
continue; /* Types must be correct */
@@ -735,20 +755,30 @@
if ((cookie & q->visit) == 0)
continue; /* must get a result */
- F2DEBUG(("asgop got types\n"));
- if ((shl = tshape(l, q->lshape)) == SRNOPE)
- continue;
-
- if (shl == SRREG)
- continue;
+ F2DEBUG(("findasg got types\n"));
+#ifdef mach_pdp11 /* XXX - check for other targets too */
+ if (p->n_op == STASG && ISPTR(l->n_type)) {
+ /* Accept lvalue to be in register */
+ /* if struct assignment is given a pointer */
+ if ((shl = chcheck(l, q->lshape,
+ q->rewrite & RLEFT)) == SRNOPE)
+ continue;
+ } else
+#endif
+ {
+ if ((shl = tshape(l, q->lshape)) == SRNOPE)
+ continue;
+ if (shl == SRREG)
+ continue;
+ }
- F2DEBUG(("asgop lshape %d\n", shl));
+ F2DEBUG(("findasg lshape %d\n", shl));
F2WALK(l);
- if ((shr = chcheck(r, q->rshape, q->rewrite & RRIGHT))== SRNOPE)
+ if ((shr = chcheck(r, q->rshape, q->rewrite & RRIGHT)) == SRNOPE)
continue;
- F2DEBUG(("asgop rshape %d\n", shr));
+ F2DEBUG(("findasg rshape %d\n", shr));
F2WALK(r);
if (q->needs & REWRITE)
break; /* Done here */
@@ -778,6 +808,23 @@
sh = shswitch(sh, p->n_right, qq->rshape, cookie,
qq->rewrite & RRIGHT, gor);
+#ifdef mach_pdp11 /* XXX all targets? */
+ lvl = 0;
+ if (cookie == FOREFF)
+ lvl = RVEFF, sh = 0;
+ else if (cookie == FORCC)
+ lvl = RVCC, sh = 0;
+ else if (sh == -1) {
+ sh = ffs(cookie & qq->visit & INREGS)-1;
+#ifdef PCC_DEBUG
+ if (sh == -1)
+ comperr("findasg bad shape");
+#endif
+ SCLASS(lvl,sh);
+ } else
+ SCLASS(lvl,sh);
+ p->n_su = MKIDX(idx, lvl);
+#else
if (sh == -1) {
if (cookie == FOREFF)
sh = 0;
@@ -788,7 +835,10 @@
p->n_su = MKIDX(idx, 0);
SCLASS(p->n_su, sh);
-
+#endif /* mach_pdp11 */
+#ifdef FINDMOPS
+ p->n_flags &= ~1;
+#endif
return sh;
}
@@ -812,6 +862,9 @@
q = &table[ixp[i]];
F2DEBUG(("findumul: ixp %d\n", ixp[i]));
+ if (!acceptable(q)) /* target-dependent filter */
+ continue;
+
if ((q->visit & cookie) == 0)
continue; /* wrong registers */
@@ -874,6 +927,8 @@
q = &table[ixp[i]];
F2DEBUG(("findleaf: ixp %d\n", ixp[i]));
+ if (!acceptable(q)) /* target-dependent filter */
+ continue;
if ((q->visit & cookie) == 0)
continue; /* wrong registers */
@@ -935,6 +990,9 @@
q = &table[ixp[i]];
F2DEBUG(("finduni: ixp %d\n", ixp[i]));
+ if (!acceptable(q)) /* target-dependent filter */
+ continue;
+
if (ttype(l->n_type, q->ltype) == 0)
continue; /* Type must be correct */
@@ -993,3 +1051,192 @@
SCLASS(p->n_su, sh);
return sh;
}
+
+#ifdef FINDMOPS
+/*
+ * Try to find constructs like "a = a + 1;" and match them together
+ * with instructions like "incl a" or "addl $1,a".
+ *
+ * Level assignment for priority:
+ * left right prio
+ * - - -
+ * direct direct 1
+ * direct REG 2
+ * direct OREG 3
+ * OREG direct 4
+ * OREG REG 5
+ * OREG OREG 6
+ */
+int
+findmops(NODE *p, int cookie)
+{
+ extern int *qtable[];
+ struct optab *q;
+ int i, sh, shl, shr, lvl = 10;
+ NODE *l, *r;
+ int *ixp;
+ struct optab *qq = NULL; /* XXX gcc */
+ int idx = 0, gol = 0, gor = 0;
+
+ shl = shr = 0;
+
+ F2DEBUG(("findmops tree: %s\n", prcook(cookie)));
+ F2WALK(p);
+
+ l = getlr(p, 'L');
+ r = getlr(p, 'R');
+ /* See if this is a usable tree to work with */
+ /* Currently only check for leaves */
+ if (optype(r->n_op) != BITYPE || treecmp(l, r->n_left) == 0)
+ return FFAIL;
+
+ F2DEBUG(("findmops is useable\n"));
+
+ /* We can try to find a match. Use right op */
+ ixp = qtable[r->n_op];
+ l = getlr(r, 'L');
+ r = getlr(r, 'R');
+
+ for (i = 0; ixp[i] >= 0; i++) {
+ q = &table[ixp[i]];
+
+ F2DEBUG(("findmops: ixp %d\n", ixp[i]));
+ if (!acceptable(q)) /* target-dependent filter */
+ continue;
+
+ if (ttype(l->n_type, q->ltype) == 0 ||
+ ttype(r->n_type, q->rtype) == 0)
+ continue; /* Types must be correct */
+
+ F2DEBUG(("findmops got types\n"));
+
+ switch (cookie) {
+ case FOREFF:
+ if ((q->visit & FOREFF) == 0)
+ continue; /* Not only for side effects */
+ break;
+ case FORCC:
+ if ((q->visit & FORCC) == 0)
+ continue; /* Not only for side effects */
+ break;
+ default:
+ if ((cookie & q->visit) == 0)
+ continue; /* Won't match requested shape */
+ if (((cookie & INREGS & q->lshape) == 0) || !isreg(l))
+ continue; /* Bad return register */
+ break;
+ }
+ F2DEBUG(("findmops cookie\n"));
+
+ /*
+ * left shape must match left node.
+ */
+ if ((shl = tshape(l, q->lshape)) != SRDIR && (shl != SROREG))
+ continue;
+
+ F2DEBUG(("findmops lshape %d\n", shl));
+ F2WALK(l);
+
+ if ((shr = chcheck(r, q->rshape, 0)) == SRNOPE)
+ continue;
+
+ F2DEBUG(("findmops rshape %d\n", shr));
+
+ /*
+ * Only allow RLEFT. XXX
+ */
+ if ((q->rewrite & (RLEFT|RRIGHT)) != RLEFT)
+ continue;
+
+ F2DEBUG(("rewrite OK\n"));
+
+ F2WALK(r);
+ if (q->needs & REWRITE)
+ break; /* Done here */
+
+ if (lvl <= (shl + shr))
+ continue;
+
+ lvl = shl + shr;
+ qq = q;
+ idx = ixp[i];
+ gol = shl;
+ gor = shr;
+ }
+
+ if (lvl == 10)
+ return FFAIL;
+ F2DEBUG(("findmops entry %d(%s,%s)\n", idx, srtyp[gol], srtyp[gor]));
+
+ /*
+ * Now we're here and have a match. left is semi-direct and
+ * right may be anything.
+ */
+
+ sh = -1;
+ sh = shswitch(sh, p->n_left, qq->lshape, cookie,
+ qq->rewrite & RLEFT, gol);
+ sh = shswitch(sh, r, qq->rshape, cookie, 0, gor);
+
+ if (sh == -1) {
+ if (cookie & (FOREFF|FORCC))
+ sh = 0;
+ else
+ sh = ffs(cookie & qq->visit & INREGS)-1;
+ }
+ F2DEBUG(("findmops done: node %p class %d\n", p, sh));
+
+ /* Trickery: Set table index on assign to op instead */
+ /* gencode() will remove useless nodes */
+ p->n_su = MKIDX(idx, 0);
+ p->n_flags |= 1; /* XXX tell gencode to reduce the right tree */
+ SCLASS(p->n_su, sh);
+
+ return sh;
+}
+
+/*
+ * Compare two trees; return 1 if equal and 0 if not.
+ */
+int
+treecmp(NODE *p1, NODE *p2)
+{
+ if (p1->n_op != p2->n_op)
+ return 0;
+
+ switch (p1->n_op) {
+ case UMUL:
+ return treecmp(p1->n_left, p2->n_left);
+
+ case OREG:
+ if (p1->n_lval != p2->n_lval || p1->n_rval != p2->n_rval)
+ return 0;
+ break;
+
+ case NAME:
+ case ICON:
+ if (strcmp(p1->n_name, p2->n_name))
+ return 0;
+ /* FALLTHROUGH */
+ if (p1->n_lval != p2->n_lval)
+ return 0;
+ break;
+
+ case REG:
+ case TEMP:
+ if (p1->n_rval != p2->n_rval)
+ return 0;
+ break;
+ case PLUS:
+ case MINUS:
+ if (treecmp(p1->n_left, p2->n_left) == 0 ||
+ treecmp(p1->n_right, p2->n_right) == 0)
+ return 0;
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+#endif
Index: pass2.h
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/mip/pass2.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/mip/pass2.h -L usr.bin/pcc/mip/pass2.h -u -r1.1 -r1.2
--- usr.bin/pcc/mip/pass2.h
+++ usr.bin/pcc/mip/pass2.h
@@ -1,4 +1,4 @@
-/* $Id: pass2.h,v 1.98 2006/12/22 06:23:09 ragge Exp $ */
+/* $Id: pass2.h,v 1.119 2008/11/22 20:13:50 pantzer Exp $ */
/*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
@@ -34,13 +34,14 @@
*/
#include <sys/types.h>
-#include "manifest.h"
-#include "protos.h"
#ifndef MKEXT
#include "external.h"
#else
-typedef int bittype; /* XXX - for basicblock */
+typedef unsigned int bittype; /* XXX - for basicblock */
+#define BIT2BYTE(a) (((a) + 31) / 32)
#endif
+#include "manifest.h"
+#include "protos.h"
/* cookies, used as arguments to codgen */
#define FOREFF 01 /* compute for effects only */
@@ -50,8 +51,12 @@
#define INDREG 020 /* compute into a register */
#define INREGS (INAREG|INBREG|INCREG|INDREG)
#define FORCC 040 /* compute for condition codes only */
+#define QUIET 0100 /* tell geninsn() to not complain if fail */
#define INTEMP 010000 /* compute into a temporary location */
#define FORREW 040000 /* search the table for a rewrite rule */
+#define INEREG 0x10000 /* compute into a register, > 16 bits */
+#define INFREG 0x20000 /* compute into a register, > 16 bits */
+#define INGREG 0x40000 /* compute into a register, > 16 bits */
/*
* OP descriptors,
@@ -91,10 +96,13 @@
#define SSCON (SPECIAL|4) /* -32768 <= constant < 32768 */
#define SSOREG (SPECIAL|5) /* non-indexed OREG */
#define MAXSPECIAL (SPECIAL|5)
+#define SEREG 0x10000 /* same as INEREG */
+#define SFREG 0x20000 /* same as INFREG */
+#define SGREG 0x40000 /* same as INGREG */
/* These are used in rstatus[] in conjunction with SxREG */
-#define TEMPREG 0100
-#define PERMREG 0200
+#define TEMPREG 01000
+#define PERMREG 02000
/* tshape() return values */
#define SRNOPE 0 /* Cannot match any shape */
@@ -140,28 +148,38 @@
#define RNOP 010000 /* DANGER: can cause loops.. */
/* needs */
-#define NAREG 0000001
-#define NACOUNT 0000003
-#define NAMASK 0000017
-#define NASL 0000004 /* may share left register */
-#define NASR 0000010 /* may share right register */
-#define NBREG 0000020
-#define NBCOUNT 0000060
-#define NBMASK 0000360
-#define NBSL 0000100
-#define NBSR 0000200
-#define NTEMP 0000400
-#define NTMASK 0001400
-#define NSPECIAL 0040000 /* need special register treatment */
-#define REWRITE 0100000
-#define NCSL 0x10000 /* Above 16 bit */
-#define NCSR 0x20000 /* Above 16 bit */
-#define NCREG 0x40000 /* Above 16 bit */
-#define NCCOUNT 0xc0000
-#define NDSL 0x100000 /* Above 16 bit */
-#define NDSR 0x200000 /* Above 16 bit */
-#define NDREG 0x400000 /* Above 16 bit */
-#define NDCOUNT 0xc00000
+#define NASL 0x0001 /* may share left register */
+#define NASR 0x0002 /* may share right register */
+#define NAREG 0x0004
+#define NACOUNT 0x000c
+#define NBSL 0x0010
+#define NBSR 0x0020
+#define NBREG 0x0040
+#define NBCOUNT 0x00c0
+#define NCSL 0x0100
+#define NCSR 0x0200
+#define NCREG 0x0400
+#define NCCOUNT 0x0c00
+#define NTEMP 0x1000
+#define NTMASK 0x3000
+#define NSPECIAL 0x4000 /* need special register treatment */
+#define REWRITE 0x8000
+#define NDSL 0x00010000 /* Above 16 bit */
+#define NDSR 0x00020000 /* Above 16 bit */
+#define NDREG 0x00040000 /* Above 16 bit */
+#define NDCOUNT 0x000c0000
+#define NESL 0x00100000 /* Above 16 bit */
+#define NESR 0x00200000 /* Above 16 bit */
+#define NEREG 0x00400000 /* Above 16 bit */
+#define NECOUNT 0x00c00000
+#define NFSL 0x01000000 /* Above 16 bit */
+#define NFSR 0x02000000 /* Above 16 bit */
+#define NFREG 0x04000000 /* Above 16 bit */
+#define NFCOUNT 0x0c000000
+#define NGSL 0x10000000 /* Above 16 bit */
+#define NGSR 0x20000000 /* Above 16 bit */
+#define NGREG 0x40000000 /* Above 16 bit */
+#define NGCOUNT 0xc0000000
/* special treatment */
#define NLEFT (0001) /* left leg register (moveadd) */
@@ -178,14 +196,6 @@
#define isreg(p) (p->n_op == REG || p->n_op == TEMP)
-#define TBUSY 01000
-
-#define SETSTO(x,y) (stotree = (x), stocook = (y))
-extern int stocook;
-
-extern NODE *stotree;
-extern int callflag;
-
extern int fregs;
/* code tables */
@@ -215,14 +225,13 @@
#endif
};
+struct p2env;
extern NODE resc[];
-
extern int p2autooff, p2maxautooff;
extern NODE
*talloc(void),
*eread(void),
- *tcopy(NODE *),
*mklnode(int, CONSZ, int, TWORD),
*mkbinode(int, NODE *, NODE *, TWORD),
*mkunode(int, NODE *, int, TWORD),
@@ -230,17 +239,12 @@
void eoftn(struct interpass_prolog *);
void prologue(struct interpass_prolog *);
-void setlocc(int locctr);
void e2print(NODE *p, int down, int *a, int *b);
void myoptim(struct interpass *);
void cbgen(int op, int label);
-struct optab *nxtmatch(struct optab *);
-int chkmatch(NODE *, int, int, int);
int match(NODE *p, int cookie);
-int nmatch(NODE *p, int what);
-#ifndef special
+int acceptable(struct optab *);
int special(NODE *, int);
-#endif
int setasg(NODE *, int);
int setuni(NODE *, int);
int sucomp(NODE *);
@@ -250,9 +254,8 @@
void adrput(FILE *, NODE *);
void comperr(char *str, ...);
void genregs(NODE *p);
-void ngenregs(struct interpass *);
+void ngenregs(struct p2env *);
NODE *store(NODE *);
-void gencall(NODE *, NODE *prev);
struct interpass *ipnode(NODE *);
void deflab(int);
void rmove(int, int, TWORD);
@@ -265,14 +268,29 @@
int findumul(NODE *p, int);
int findleaf(NODE *p, int);
int relops(NODE *p);
+#ifdef FINDMOPS
+int findmops(NODE *p, int);
+int treecmp(NODE *p1, NODE *p2);
+#endif
void offstar(NODE *p, int shape);
int gclass(TWORD);
void lastcall(NODE *);
void myreader(struct interpass *pole);
int oregok(NODE *p, int sharp);
void myormake(NODE *);
-
+int *livecall(NODE *);
+void prtreg(FILE *, NODE *);
char *prcook(int);
+int myxasm(struct interpass *ip, NODE *p);
+int xasmcode(char *s);
+int freetemp(int k);
+int rewfld(NODE *p);
+void canon(NODE *);
+void mycanon(NODE *);
+void oreg2(NODE *p, void *);
+int shumul(NODE *p, int);
+NODE *deluseless(NODE *p);
+int getlab2(void);
void conput(FILE *, NODE *);
@@ -289,6 +307,17 @@
#define CLASSC 3
#define CLASSD 4
#define CLASSE 5
+#define CLASSF 6
+#define CLASSG 7
+
+/* 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
@@ -299,8 +328,8 @@
extern int lineno;
extern int fldshf, fldsz;
-extern int lflag, x2debug, udebug, e2debug, odebug, mdebug;
-extern int rdebug, radebug, t2debug, s2debug, b2debug, c2debug;
+extern int lflag, x2debug, udebug, e2debug, odebug;
+extern int rdebug, t2debug, s2debug, b2debug, c2debug;
extern int kflag;
#ifdef FORT
extern int Oflag;
@@ -330,24 +359,17 @@
/*
* Layout of findops() return value:
- * bit 0-1 where to store left node.
- * bit 2-3 where to store right node.
- * bit 4 set if right leg should be evaluated first
- * bit 5- table index
+ * bit 0 whether left shall go into a register.
+ * bit 1 whether right shall go into a register.
+ * bit 2 entry is only used for side effects.
+ * bit 3 if condition codes are used.
*
- * LOREG means: walk down left node, after code emission call canon() to
- * convert the tree to an OREG.
+ * These values should be synced with FOREFF/FORCC.
*/
#define LREG 001
-#define LOREG 002
-#define LTEMP 003
-#define LDIR 003
-#define LMASK 003
-#define RREG 004
-#define ROREG 010
-#define RTEMP 014
-#define RDIR 014
-#define RMASK 014
+#define RREG 002
+#define RVEFF 004
+#define RVCC 010
#define DORIGHT 020
#define SCLASS(v,x) ((v) |= ((x) << 5))
#define TCLASS(x) (((x) >> 5) & 7)
@@ -360,9 +382,12 @@
#define TBREGS 0
#endif
#define REGBIT(x) (1 << (x))
+#ifndef PERMTYPE
+#define PERMTYPE(a) (INT)
+#endif
void emit(struct interpass *);
-void optimize(struct interpass *);
+void optimize(struct p2env *);
struct basicblock {
DLIST_ENTRY(basicblock) bbelem;
@@ -380,23 +405,25 @@
bittype *dfchildren;
bittype *Aorig;
bittype *Aphi;
+ SLIST_HEAD(, phiinfo) phi;
struct interpass *first; /* first element of basic block */
struct interpass *last; /* last element of basic block */
};
struct labelinfo {
struct basicblock **arr;
- unsigned int size;
+ int size;
unsigned int low;
};
struct bblockinfo {
- unsigned int size;
+ int size;
struct basicblock **arr;
};
struct varinfo {
struct pvarinfo **arr;
+ SLIST_HEAD(, varstack) *stack;
int size;
int low;
};
@@ -404,14 +431,44 @@
struct pvarinfo {
struct pvarinfo *next;
struct basicblock *bb;
- NODE *top, *n;
+ TWORD n_type;
+};
+
+struct varstack {
+ SLIST_ENTRY(varstack) varstackelem;
+ int tmpregno;
};
+
struct cfgnode {
SLIST_ENTRY(cfgnode) cfgelem;
struct basicblock *bblock;
};
+struct phiinfo {
+ SLIST_ENTRY(phiinfo) phielem;
+ int tmpregno;
+ int newtmpregno;
+ TWORD n_type;
+ int size;
+ int *intmpregno;
+};
+
+/*
+ * Description of the pass2 environment.
+ * There will be only one of these structs. It is used to keep
+ * all state descriptions during the compilation of a function
+ * in one place.
+ */
+struct p2env {
+ struct interpass ipole; /* all statements */
+ struct interpass_prolog *ipp, *epp; /* quick references */
+ struct basicblock bblocks;
+ int nbblocks;
+};
+
+extern struct p2env p2env;
+
/*
* C compiler second pass extra defines.
*/
Index: regs.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/mip/regs.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/mip/regs.c -L usr.bin/pcc/mip/regs.c -u -r1.1 -r1.2
--- usr.bin/pcc/mip/regs.c
+++ usr.bin/pcc/mip/regs.c
@@ -1,4 +1,4 @@
-/* $Id: regs.c,v 1.155 2007/09/22 17:15:00 ragge Exp $ */
+/* $Id: regs.c,v 1.198 2008/12/14 18:26:02 ragge Exp $ */
/*
* Copyright (c) 2005 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -28,11 +28,22 @@
#include "pass2.h"
#include <string.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
#include <stdlib.h>
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
#define MAXLOOP 20 /* Max number of allocation loops XXX 3 should be enough */
+#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
/*
* New-style register allocator using graph coloring.
@@ -40,9 +51,8 @@
* "Iterated Register Coalescing", ACM Transactions, No 3, May 1996.
*/
-#define BIT2BYTE(bits) ((((bits)+NUMBITS-1)/NUMBITS)*(NUMBITS/8))
#define BITALLOC(ptr,all,sz) { \
- int __s = BIT2BYTE(sz); ptr = all(__s); memset(ptr, 0, __s); }
+ int sz__s = BIT2BYTE(sz); ptr = all(sz__s); memset(ptr, 0, sz__s); }
#undef COMPERR_PERM_MOVE
#define RDEBUG(x) if (rdebug) printf x
@@ -50,6 +60,9 @@
#define RPRINTIP(x) if (rdebug) printip(x)
#define RDX(x) x
#define UDEBUG(x) if (udebug) printf x
+#define BDEBUG(x) if (b2debug) printf x
+
+#define VALIDREG(p) (p->n_op == REG && TESTBIT(validregs, regno(p)))
/*
* Data structure overview for this implementation of graph coloring:
@@ -124,6 +137,7 @@
static REGW initial, *nblock;
static void insnwalk(NODE *p);
#ifdef PCC_DEBUG
+int use_regw;
int nodnum = 100;
#define SETNUM(x) (x)->nodnum = nodnum++
#define ASGNUM(x) (x)->nodnum
@@ -132,7 +146,7 @@
#define ASGNUM(x)
#endif
-#define ALLNEEDS (NACOUNT|NBCOUNT|NCCOUNT|NDCOUNT)
+#define ALLNEEDS (NACOUNT|NBCOUNT|NCCOUNT|NDCOUNT|NECOUNT|NFCOUNT|NGCOUNT)
/* XXX */
REGW *ablock;
@@ -157,17 +171,21 @@
static REGW *
newblock(NODE *p)
{
- REGW *nb = &nblock[(int)p->n_lval];
+ REGW *nb = &nblock[regno(p)];
if (nb->link.q_forw == 0) {
DLIST_INSERT_AFTER(&initial, nb, link);
- ASGNUM(nb) = p->n_lval;
+#ifdef PCC_DEBUG
+ ASGNUM(nb) = regno(p);
RDEBUG(("Adding longtime %d for tmp %d\n",
- nb->nodnum, (int)p->n_lval));
+ 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;
}
@@ -191,7 +209,7 @@
struct optab *q;
int left, right;
int nreg, need, i, nxreg, o;
- int nareg, nbreg, ncreg, ndreg;
+ int nareg, nbreg, ncreg, ndreg, nereg, nfreg, ngreg;
REGW *w;
o = optype(p->n_op);
@@ -205,6 +223,8 @@
if (o == LTYPE ) {
if (p->n_op == TEMP)
p->n_regw = newblock(p);
+ else if (p->n_op == REG)
+ p->n_regw = &ablock[regno(p)];
} else
a = nsucomp(p->n_left);
if (o == BITYPE) {
@@ -217,16 +237,23 @@
}
q = &table[TBLIDX(p->n_su)];
- nareg = (q->needs & NACOUNT);
+ for (i = (q->needs & NACOUNT), nareg = 0; i; i -= NAREG)
+ nareg++;
for (i = (q->needs & NBCOUNT), nbreg = 0; i; i -= NBREG)
nbreg++;
for (i = (q->needs & NCCOUNT), ncreg = 0; i; i -= NCREG)
ncreg++;
for (i = (q->needs & NDCOUNT), ndreg = 0; i; i -= NDREG)
ndreg++;
+ for (i = (q->needs & NECOUNT), nereg = 0; i; i -= NEREG)
+ nereg++;
+ for (i = (q->needs & NFCOUNT), nfreg = 0; i; i -= NFREG)
+ nfreg++;
+ for (i = (q->needs & NGCOUNT), ngreg = 0; i; i -= NGREG)
+ ngreg++;
- nxreg = nareg + nbreg + ncreg + ndreg;
+ nxreg = nareg + nbreg + ncreg + ndreg + nereg + nfreg + ngreg;
nreg = nxreg;
if (callop(p->n_op))
nreg = MAX(fregs, nreg);
@@ -276,11 +303,18 @@
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));
@@ -293,12 +327,17 @@
SETNUM(w);
if (w->r_class)
DLIST_INSERT_BEFORE(&initial, w, link);
- UDEBUG(("Adding short %d calss %d\n", w->nodnum, w->r_class));
+#ifdef PCC_DEBUG
+ UDEBUG(("Adding short %d class %d\n", w->nodnum, w->r_class));
+#endif
w++;
ADCL(nareg, CLASSA);
ADCL(nbreg, CLASSB);
ADCL(ncreg, CLASSC);
ADCL(ndreg, CLASSD);
+ ADCL(nereg, CLASSE);
+ ADCL(nfreg, CLASSF);
+ ADCL(ngreg, CLASSG);
if (q->rewrite & RESC1) {
w = p->n_regw + 1;
@@ -361,9 +400,13 @@
#endif
i = COLORMAP(c, r);
-if (i < 0 || i > 1)
- comperr("trivially_colorable_p");
-//printf("trivially_colorable_p: n[1] %d n[2] %d n[3] %d n[4] %d class %d, triv %d\n", n[1], n[2], n[3], n[4], c, i);
+ if (i < 0 || i > 1)
+ comperr("trivially_colorable_p");
+#ifdef PCC_DEBUG
+ if (rdebug > 1)
+ printf("trivially_colorable_p: n[1] %d n[2] %d n[3] %d n[4] "
+ "%d for class %d, triv %d\n", n[1], n[2], n[3], n[4], c, i);
+#endif
return i;
}
@@ -380,10 +423,16 @@
needs -= NCREG, i++;
while (needs & NDCOUNT)
needs -= NDREG, i++;
+ while (needs & NECOUNT)
+ needs -= NEREG, i++;
+ while (needs & NFCOUNT)
+ needs -= NFREG, i++;
+ while (needs & NGCOUNT)
+ needs -= NGREG, i++;
return i;
}
-static inline REGW *
+static REGW *
popwlist(REGW *l)
{
REGW *w = DLIST_NEXT(l, link);
@@ -400,7 +449,7 @@
worklistMoves, activeMoves;
enum { COAL, CONSTR, FROZEN, WLIST, ACTIVE };
-static inline REGM *
+static REGM *
popmlist(REGM *l)
{
REGM *w = DLIST_NEXT(l, link);
@@ -418,7 +467,7 @@
*
* 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
@@ -430,21 +479,31 @@
LIVEADD(int x)
{
RDEBUG(("Liveadd: %d\n", x));
- if (x < tempmin || x >= tempmax)
+ if (x >= MAXREGS && (x < tempmin || x >= tempmax))
comperr("LIVEADD: out of range");
- BITSET(live, (x-tempmin));
+ if (x < MAXREGS) {
+ BITSET(live, x);
+ } else
+ BITSET(live, (x-tempmin+MAXREGS));
}
+
static void
LIVEDEL(int x)
{
RDEBUG(("Livedel: %d\n", x));
- if (x < tempmin || x >= tempmax)
+
+ if (x >= MAXREGS && (x < tempmin || x >= tempmax))
comperr("LIVEDEL: out of range");
- BITCLEAR(live, (x-tempmin));
+ if (x < MAXREGS) {
+ BITCLEAR(live, x);
+ } else
+ BITCLEAR(live, (x-tempmin+MAXREGS));
}
#else
-#define LIVEADD(x) BITSET(live, (x-tempmin))
-#define LIVEDEL(x) BITCLEAR(live, (x-tempmin))
+#define LIVEADD(x) \
+ (x >= MAXREGS ? BITSET(live, (x-tempmin+MAXREGS)) : BITSET(live, x))
+#define LIVEDEL(x) \
+ (x >= MAXREGS ? BITCLEAR(live, (x-tempmin+MAXREGS)) : BITCLEAR(live, x))
#endif
static struct lives {
@@ -479,7 +538,9 @@
{
struct lives *l;
+#ifdef PCC_DEBUG
RDEBUG(("LIVEDELR: %d\n", x->nodnum));
+#endif
DLIST_FOREACH(l, &lused, link) {
if (l->var != x)
continue;
@@ -515,10 +576,11 @@
return w;
}
+#define HASHSZ 16384
struct AdjSet {
struct AdjSet *next;
REGW *u, *v;
-} *edgehash[256];
+} *edgehash[HASHSZ];
/* Check if a node pair is adjacent */
static int
@@ -543,7 +605,7 @@
}
if (u > v)
t = v, v = u, u = t;
- w = edgehash[((long)u+(long)v) & 255];
+ w = edgehash[((intptr_t)u+(intptr_t)v) & (HASHSZ-1)];
for (; w; w = w->next) {
if (u == w->u && v == w->v)
return 1;
@@ -561,7 +623,7 @@
if (u > v)
t = v, v = u, u = t;
- x = ((long)u+(long)v) & 255;
+ x = ((intptr_t)u+(intptr_t)v) & (HASHSZ-1);
w = tmpalloc(sizeof(struct AdjSet));
w->u = u, w->v = v;
w->next = edgehash[x];
@@ -576,9 +638,9 @@
{
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");
@@ -678,10 +740,11 @@
addalledges(REGW *e)
{
int i, j, k;
- int nbits = xbits;
struct lives *l;
+#ifdef PCC_DEBUG
RDEBUG(("addalledges for %d\n", e->nodnum));
+#endif
if (e->r_class == -1)
return; /* unused */
@@ -691,14 +754,17 @@
AddEdge(e, &ablock[ndontregs[i]]);
}
- /* First add to long-lived temps */
+ /* First add to long-lived temps and hard regs */
RDEBUG(("addalledges longlived "));
- for (i = 0; i < nbits; i += NUMBITS) {
+ for (i = 0; i < xbits; i += NUMBITS) {
if ((k = live[i/NUMBITS]) == 0)
continue;
while (k) {
j = ffs(k)-1;
- AddEdge(&nblock[i+j+tempmin], e);
+ if (i+j < MAXREGS)
+ AddEdge(&ablock[i+j], e);
+ else
+ AddEdge(&nblock[i+j+tempmin-MAXREGS], e);
RRDEBUG(("%d ", i+j+tempmin));
k &= ~(1 << j);
}
@@ -707,7 +773,9 @@
/* 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"));
@@ -723,7 +791,9 @@
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);
@@ -754,23 +824,25 @@
setlive(NODE *p, int set, REGW *rv)
{
if (rv != NULL) {
+ if (rv->nodnum < MAXREGS &&
+ TESTBIT(validregs, rv->nodnum) == 0)
+ return;
set ? LIVEADDR(rv) : LIVEDELR(rv);
return;
}
if (p->n_regw != NULL) {
+ if (p->n_regw->nodnum < MAXREGS &&
+ TESTBIT(validregs, p->n_regw->nodnum) == 0)
+ return;
set ? LIVEADDR(p->n_regw) : LIVEDELR(p->n_regw);
return;
}
switch (optype(p->n_op)) {
case LTYPE:
- if (p->n_op == TEMP)
- set ? LIVEADD((int)p->n_lval) : LIVEDEL((int)p->n_lval);
-#ifdef notyet
- else if (p->n_op == REG)
- ...
-#endif
+ if (p->n_op == TEMP || VALIDREG(p))
+ set ? LIVEADD(regno(p)) : LIVEDEL(regno(p));
break;
case BITYPE:
setlive(p->n_right, set, rv);
@@ -788,7 +860,12 @@
static void
addedge_r(NODE *p, REGW *w)
{
+ RRDEBUG(("addedge_r: node %p regw %p\n", p, w));
+
if (p->n_regw != NULL) {
+ if (p->n_regw->nodnum < MAXREGS &&
+ TESTBIT(validregs, p->n_regw->nodnum) == 0)
+ return;
AddEdge(p->n_regw, w);
return;
}
@@ -800,6 +877,50 @@
}
/*
+ * add/del parameter from live set.
+ */
+static void
+setxarg(NODE *p)
+{
+ int i, ut = 0, in = 0;
+ int cw;
+
+ if (p->n_op == ICON && p->n_type == STRTY)
+ return;
+
+ RDEBUG(("setxarg %p %s\n", p, p->n_name));
+ cw = xasmcode(p->n_name);
+ if (XASMISINP(cw))
+ in = 1;
+ if (XASMISOUT(cw))
+ ut = 1;
+
+ switch (XASMVAL(cw)) {
+ case 'g':
+ if (p->n_left->n_op != REG && p->n_left->n_op != TEMP)
+ break;
+ /* FALLTHROUGH */
+ case 'r':
+ i = regno(p->n_left);
+ if (ut) {
+ REGW *rw = p->n_left->n_op == REG ? ablock : nblock;
+ LIVEDEL(i);
+ addalledges(&rw[i]);
+ }
+ if (in) {
+ LIVEADD(i);
+ }
+ break;
+ case 'i':
+ case 'm':
+ case 'n':
+ break;
+ default:
+ comperr("bad ixarg %s", p->n_name);
+ }
+}
+
+/*
* Do the in-tree part of liveness analysis. (the difficult part)
*
* Walk down the tree in reversed-evaluation order (backwards).
@@ -825,14 +946,13 @@
* Moves to special regs are scheduled after the evaluation of both legs.
*/
-#define ASGLEFT(p) (p->n_op == ASSIGN && p->n_left->n_op == TEMP)
-
static void
insnwalk(NODE *p)
{
int o = p->n_op;
struct optab *q = &table[TBLIDX(p->n_su)];
REGW *lr, *rr, *rv, *r, *rrv, *lrv;
+ NODE *lp, *rp;
int i, n;
RDEBUG(("insnwalk %p\n", p));
@@ -840,14 +960,16 @@
rv = p->n_regw;
rrv = lrv = NULL;
- if (ASGLEFT(p)) {
- int v = p->n_left->n_lval;
- LIVEDEL(v); /* remove assigned temp from live set */
- addalledges(&nblock[v]);
+ if (p->n_op == ASSIGN &&
+ (p->n_left->n_op == TEMP || VALIDREG(p->n_left))) {
+ lr = p->n_left->n_op == TEMP ? nblock : ablock;
+ i = regno(p->n_left);
+ LIVEDEL(i); /* remove assigned temp from live set */
+ addalledges(&lr[i]);
}
/* Add edges for the result of this node */
- if (rv && (q->visit & INREGS || o == TEMP))
+ if (rv && (q->visit & INREGS || o == TEMP || VALIDREG(p)))
addalledges(rv);
/* special handling of CALL operators */
@@ -866,24 +988,36 @@
/* Check leaves for results in registers */
lr = optype(o) != LTYPE ? p->n_left->n_regw : NULL;
+ lp = optype(o) != LTYPE ? p->n_left : NULL;
rr = optype(o) == BITYPE ? p->n_right->n_regw : NULL;
+ rp = optype(o) == BITYPE ? p->n_right : NULL;
/* simple needs */
n = ncnt(q->needs);
for (i = 0; i < n; i++) {
#if 1
- static int ncl[] = { 0, NASL, NBSL, NCSL, NDSL };
- static int ncr[] = { 0, NASR, NBSR, NCSR, NDSR };
-
+ static int ncl[] =
+ { 0, NASL, NBSL, NCSL, NDSL, NESL, NFSL, NGSL };
+ static int ncr[] =
+ { 0, NASR, NBSR, NCSR, NDSR, NESR, NFSR, NGSR };
+ int j;
+
/* edges are already added */
- if ((r = &p->n_regw[1+i])->r_class == -1)
+ if ((r = &p->n_regw[1+i])->r_class == -1) {
r = p->n_regw;
- else
+ } else {
+ AddEdge(r, p->n_regw);
addalledges(r);
+ }
if (optype(o) != LTYPE && (q->needs & ncl[CLASS(r)]) == 0)
addedge_r(p->n_left, r);
if (optype(o) == BITYPE && (q->needs & ncr[CLASS(r)]) == 0)
addedge_r(p->n_right, r);
+ for (j = i + 1; j < n; j++) {
+ if (p->n_regw[j+1].r_class == -1)
+ continue;
+ AddEdge(r, &p->n_regw[j+1]);
+ }
#else
if ((r = &p->n_regw[1+i])->r_class == -1)
continue;
@@ -924,6 +1058,13 @@
}
if (o == ASSIGN) {
+ /* avoid use of unhandled registers */
+ if (p->n_left->n_op == REG &&
+ !TESTBIT(validregs, regno(p->n_left)))
+ lr = NULL;
+ if (p->n_right->n_op == REG &&
+ !TESTBIT(validregs, regno(p->n_right)))
+ rr = NULL;
/* needs special treatment */
if (lr && rr)
moveadd(lr, rr);
@@ -932,33 +1073,31 @@
if (rr && rv)
moveadd(rr, rv);
} else if (callop(o)) {
-#ifdef notdef
- /* calls needs special treatment */
- for (i = 0; tempregs[i] >= 0; i++)
- addalledges(&ablock[i]);
- if (rv)
- moveadd(rv, &ablock[RETREG(p->n_type)]);
-#endif
- /* XXX - here must all live arg registers be added
- * for archs with arguments in registers */
+ int *c;
+
+ for (c = livecall(p); *c != -1; c++) {
+ addalledges(ablock + *c);
+ LIVEADD(*c);
+ }
} else if (q->rewrite & (RESC1|RESC2|RESC3)) {
if (lr && rr)
AddEdge(lr, rr);
} else if (q->rewrite & RLEFT) {
if (lr && rv)
moveadd(rv, lr), lrv = rv;
- if (rr && rv)
- AddEdge(rr, rv);
+ if (rv && rp)
+ addedge_r(rp, rv);
} else if (q->rewrite & RRIGHT) {
if (rr && rv)
moveadd(rv, rr), rrv = rv;
- if (lr && rv)
- AddEdge(lr, rv);
+ if (rv && lp)
+ addedge_r(lp, rv);
}
switch (optype(o)) {
case BITYPE:
- if (ASGLEFT(p)) {
+ if (p->n_op == ASSIGN &&
+ (p->n_left->n_op == TEMP || p->n_left->n_op == REG)) {
/* only go down right node */
insnwalk(p->n_right);
} else if (callop(o)) {
@@ -984,18 +1123,23 @@
case LTYPE:
switch (o) {
+ case REG:
+ if (!TESTBIT(validregs, regno(p)))
+ break; /* never add moves */
+ /* FALLTHROUGH */
case TEMP:
- rr = &nblock[(int)p->n_lval];
+ i = regno(p);
+ rr = (o == TEMP ? &nblock[i] : &ablock[i]);
if (rv != rr) {
addalledges(rr);
moveadd(rv, rr);
}
- LIVEADD((int)p->n_lval);
- break;
- case REG:
- case OREG:
- /* Liveness for regs??? */
+ LIVEADD(i);
break;
+
+ case OREG: /* XXX - not yet */
+ break;
+
default:
break;
}
@@ -1003,8 +1147,218 @@
}
}
-static bittype **gen, **kill, **in, **out;
+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");
+ }
+ }
+}
+
+#ifndef XASMCONSTREGS
+#define XASMCONSTREGS(x) (-1)
+#endif
+
+/*
+ * 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;
+ }
+ if ((i = XASMCONSTREGS(p->n_name)) < 0)
+ comperr("unsupported xasm constraint %s", p->n_name);
+ addalledges(&ablock[i]);
+}
+
+#define RUP(x) (((x)+NUMBITS-1)/NUMBITS)
+#define SETCOPY(t,f,i,n) for (i = 0; i < RUP(n); i++) t[i] = f[i]
+#define SETSET(t,f,i,n) for (i = 0; i < RUP(n); i++) t[i] |= f[i]
+#define SETCLEAR(t,f,i,n) for (i = 0; i < RUP(n); i++) t[i] &= ~f[i]
+#define SETCMP(v,t,f,i,n) for (i = 0; i < RUP(n); i++) \
+ if (t[i] != f[i]) v = 1
+#define SETEMPTY(t,sz) memset(t, 0, BIT2BYTE(sz))
+
+static int
+deldead(NODE *p, bittype *lvar)
+{
+ NODE *q;
+ int ty, rv = 0;
+
+#define BNO(p) (regno(p) - tempmin+MAXREGS)
+ if (p->n_op == TEMP)
+ BITSET(lvar, BNO(p));
+ if (asgop(p->n_op) && p->n_left->n_op == TEMP &&
+ TESTBIT(lvar, BNO(p->n_left)) == 0) {
+ /*
+ * Not live, must delete the right tree at least
+ * down to next statement with side effects.
+ */
+ BDEBUG(("DCE deleting temp %d\n", regno(p->n_left)));
+ nfree(p->n_left);
+ q = p->n_right;
+ *p = *q;
+ nfree(q);
+ rv = 1;
+ }
+ ty = optype(p->n_op);
+ if (ty != LTYPE)
+ rv |= deldead(p->n_left, lvar);
+ if (ty == BITYPE)
+ rv |= deldead(p->n_right, lvar);
+ return rv;
+}
+
+/*
+ * Do dead code elimination.
+ */
+static int
+dce(struct p2env *p2e)
+{
+ extern struct interpass prepole;
+ struct basicblock *bb;
+ struct interpass *ip;
+ NODE *p;
+ bittype *lvar;
+ int i, bbnum, fix = 0;
+
+ BDEBUG(("Entering DCE\n"));
+ /*
+ * Traverse over the basic blocks.
+ * if an assignment is found that writes to a temporary
+ * that is not live out, remove that assignment and its legs.
+ */
+ DLIST_INIT(&prepole, qelem);
+ BITALLOC(lvar, alloca, xbits);
+ DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
+ bbnum = bb->bbnum;
+ BDEBUG(("DCE bblock %d, start %p last %p\n",
+ bbnum, bb->first, bb->last));
+ SETCOPY(lvar, out[bbnum], i, xbits);
+ for (ip = bb->last; ; ip = DLIST_PREV(ip, qelem)) {
+ if (ip->type == IP_NODE && deldead(ip->ip_node, lvar)) {
+ if ((p = deluseless(ip->ip_node)) == NULL) {
+#ifdef notyet
+ if (ip == bb->last) {
+ bb->last =
+ DLIST_PREV(ip, qelem);
+ } else if (ip == bb->first) {
+ bb->first =
+ DLIST_NEXT(ip, qelem);
+ }
+ DLIST_REMOVE(ip, qelem);
+#else
+ ip->type = IP_ASM;
+ ip->ip_asm = "";
+#endif
+ fix++;
+ BDEBUG(("DCE ip %p deleted\n", ip));
+ } else while (!DLIST_ISEMPTY(&prepole, qelem)) {
+ BDEBUG(("DCE doing ip prepend\n"));
+#ifdef notyet
+ struct interpass *tipp;
+ tipp = DLIST_NEXT(&prepole, qelem);
+ DLIST_REMOVE(tipp, qelem);
+ DLIST_INSERT_BEFORE(ip, tipp, qelem);
+ if (ip == bb->first)
+ bb->first = tipp;
+ fix++;
+#else
+ comperr("dce needs bb fixup");
+#endif
+ BDEBUG(("DCE ip prepended\n"));
+ }
+ if (ip->type == IP_NODE) {
+ geninsn(p, FOREFF);
+ nsucomp(p);
+ ip->ip_node = p;
+ }
+ }
+ if (ip == bb->first)
+ break;
+ }
+ }
+ BDEBUG(("DCE fix %d\n", fix));
+ return fix;
+}
+
+/*
+ * Set/clear long term liveness for regs and temps.
+ */
static void
unionize(NODE *p, int bb)
{
@@ -1013,27 +1367,37 @@
if ((o = p->n_op) == TEMP) {
#ifdef notyet
for (i = 0; i < szty(p->n_type); i++) {
- BITSET(gen[bb], ((int)p->n_lval - tempmin+i));
+ BITSET(gen[bb], (regno(p) - tempmin+i+MAXREGS));
}
#else
i = 0;
- BITSET(gen[bb], ((int)p->n_lval - tempmin+i));
+ BITSET(gen[bb], (regno(p) - tempmin+i+MAXREGS));
#endif
+ } else if (VALIDREG(p)) {
+ BITSET(gen[bb], regno(p));
}
- if (asgop(o) && p->n_left->n_op == TEMP) {
- int b = p->n_left->n_lval - tempmin;
+ if (asgop(o)) {
+ if (p->n_left->n_op == TEMP) {
+ int b = regno(p->n_left) - tempmin+MAXREGS;
#ifdef notyet
- for (i = 0; i < szty(p->n_type); i++) {
- BITCLEAR(gen[bb], (b+i));
- BITSET(kill[bb], (b+i));
- }
+ for (i = 0; i < szty(p->n_type); i++) {
+ BITCLEAR(gen[bb], (b+i));
+ BITSET(killed[bb], (b+i));
+ }
#else
- i = 0;
- BITCLEAR(gen[bb], (b+i));
- BITSET(kill[bb], (b+i));
+ i = 0;
+ BITCLEAR(gen[bb], (b+i));
+ BITSET(killed[bb], (b+i));
#endif
- unionize(p->n_right, bb);
- return;
+ unionize(p->n_right, bb);
+ return;
+ } else if (VALIDREG(p->n_left)) {
+ int b = regno(p->n_left);
+ BITCLEAR(gen[bb], b);
+ BITSET(killed[bb], b);
+ unionize(p->n_right, bb);
+ return;
+ }
}
ty = optype(o);
if (ty != LTYPE)
@@ -1049,62 +1413,60 @@
* when doing short-range liveness analysis in Build().
*/
static void
-LivenessAnalysis(void)
+LivenessAnalysis(struct p2env *p2e)
{
- extern struct basicblock bblocks;
struct basicblock *bb;
struct interpass *ip;
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) {
+ DLIST_FOREACH(bb, &p2e->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;
}
- memcpy(in[bbnum], gen[bbnum], BIT2BYTE(tempmax-tempmin));
+ memcpy(in[bbnum], gen[bbnum], BIT2BYTE(xbits));
#ifdef PCC_DEBUG
+#define PRTRG(x) printf("%d ", i < MAXREGS ? i : i + tempmin-MAXREGS)
if (rdebug) {
printf("basic block %d\ngen: ", bbnum);
- for (i = 0; i < tempmax-tempmin; i++)
+ for (i = 0; i < xbits; i++)
if (TESTBIT(gen[bbnum], i))
- printf("%d ", i+tempmin);
- printf("\nkill: ");
- for (i = 0; i < tempmax-tempmin; i++)
- if (TESTBIT(kill[bbnum], i))
- printf("%d ", i+tempmin);
+ PRTRG(i);
+ printf("\nkilled: ");
+ for (i = 0; i < xbits; i++)
+ if (TESTBIT(killed[bbnum], i))
+ PRTRG(i);
printf("\n");
}
#endif
}
}
-#define SETCOPY(t,f,i,n) for (i = 0; i < n/NUMBITS; i++) t[i] = f[i]
-#define SETSET(t,f,i,n) for (i = 0; i < n/NUMBITS; i++) t[i] |= f[i]
-#define SETCLEAR(t,f,i,n) for (i = 0; i < n/NUMBITS; i++) t[i] &= ~f[i]
-#define SETCMP(v,t,f,i,n) for (i = 0; i < n/NUMBITS; i++) \
- if (t[i] != f[i]) v = 1
-
/*
* Build the set of interference edges and adjacency list.
*/
static void
-Build(struct interpass *ipole)
+Build(struct p2env *p2e)
{
- extern struct basicblock bblocks;
+ struct interpass *ipole = &p2e->ipole;
struct basicblock bbfake;
struct interpass *ip;
struct basicblock *bb;
struct cfgnode *cn;
- extern int nbblocks;
bittype *saved;
- int i, j, again, nbits;
+ int i, j, again;
if (xtemps == 0) {
/*
@@ -1112,35 +1474,37 @@
* so fake one basic block to keep the liveness analysis
* happy.
*/
- nbblocks = 1;
+ p2e->nbblocks = 1;
bbfake.bbnum = 0;
bbfake.last = DLIST_PREV(ipole, qelem);
bbfake.first = DLIST_NEXT(ipole, qelem);
- DLIST_INIT(&bblocks, bbelem);
- DLIST_INSERT_AFTER(&bblocks, &bbfake, bbelem);
+ DLIST_INIT(&p2e->bblocks, bbelem);
+ DLIST_INSERT_AFTER(&p2e->bblocks, &bbfake, bbelem);
SLIST_INIT(&bbfake.children);
}
/* Just fetch space for the temporaries from stack */
- nbits = xbits+(NUMBITS-1);
- gen = alloca(nbblocks*sizeof(bittype*));
- kill = alloca(nbblocks*sizeof(bittype*));
- in = alloca(nbblocks*sizeof(bittype*));
- out = alloca(nbblocks*sizeof(bittype*));
- for (i = 0; i < nbblocks; i++) {
- BITALLOC(gen[i],alloca,nbits);
- BITALLOC(kill[i],alloca,nbits);
- BITALLOC(in[i],alloca,nbits);
- BITALLOC(out[i],alloca,nbits);
- }
- BITALLOC(saved,alloca,nbits);
- LivenessAnalysis();
+ gen = alloca(p2e->nbblocks*sizeof(bittype*));
+ killed = alloca(p2e->nbblocks*sizeof(bittype*));
+ in = alloca(p2e->nbblocks*sizeof(bittype*));
+ out = alloca(p2e->nbblocks*sizeof(bittype*));
+ for (i = 0; i < p2e->nbblocks; i++) {
+ BITALLOC(gen[i],alloca,xbits);
+ BITALLOC(killed[i],alloca,xbits);
+ BITALLOC(in[i],alloca,xbits);
+ BITALLOC(out[i],alloca,xbits);
+ }
+ BITALLOC(saved,alloca,xbits);
+
+ nspill = 0;
+livagain:
+ LivenessAnalysis(p2e);
/* register variable temporaries are live */
for (i = 0; i < NPERMREG-1; i++) {
if (nsavregs[i])
continue;
- BITSET(out[nbblocks-1], i);
+ BITSET(out[p2e->nbblocks-1], (i+MAXREGS));
for (j = i+1; j < NPERMREG-1; j++) {
if (nsavregs[j])
continue;
@@ -1152,47 +1516,73 @@
do {
again = 0;
/* XXX - loop should be in reversed execution-order */
- DLIST_FOREACH_REVERSE(bb, &bblocks, bbelem) {
- int i = bb->bbnum;
- SETCOPY(saved, out[i], j, nbits);
+ DLIST_FOREACH_REVERSE(bb, &p2e->bblocks, bbelem) {
+ i = bb->bbnum;
+ SETCOPY(saved, out[i], j, xbits);
SLIST_FOREACH(cn, &bb->children, cfgelem) {
- SETSET(out[i], in[cn->bblock->bbnum],
- j, nbits);
+ SETSET(out[i], in[cn->bblock->bbnum], j, xbits);
}
- SETCMP(again, saved, out[i], j, nbits);
- SETCOPY(saved, in[i], j, nbits);
- SETCOPY(in[i], out[i], j, nbits);
- SETCLEAR(in[i], kill[i], j, nbits);
- SETSET(in[i], gen[i], j, nbits);
- SETCMP(again, saved, in[i], j, nbits);
+ SETCMP(again, saved, out[i], j, xbits);
+ SETCOPY(saved, in[i], j, xbits);
+ SETCOPY(in[i], out[i], j, xbits);
+ SETCLEAR(in[i], killed[i], j, xbits);
+ SETSET(in[i], gen[i], j, xbits);
+ SETCMP(again, saved, in[i], j, xbits);
}
} while (again);
#ifdef PCC_DEBUG
if (rdebug) {
- DLIST_FOREACH(bb, &bblocks, bbelem) {
+ DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
printf("basic block %d\nin: ", bb->bbnum);
- for (i = 0; i < tempmax-tempmin; i++)
+ for (i = 0; i < xbits; i++)
if (TESTBIT(in[bb->bbnum], i))
- printf("%d ", i+tempmin);
+ PRTRG(i);
printf("\nout: ");
- for (i = 0; i < tempmax-tempmin; i++)
+ for (i = 0; i < xbits; i++)
if (TESTBIT(out[bb->bbnum], i))
- printf("%d ", i+tempmin);
+ PRTRG(i);
printf("\n");
}
}
#endif
+ if (xtemps && xdce) {
+ /*
+ * Do dead code elimination by using live out.
+ * Ignores if any variable read from is marked volatile,
+ * but what it should do is unspecified anyway.
+ * Liveness Analysis should be done in optim2 instead.
+ *
+ * This should recalculate the basic block structure.
+ */
+ if (dce(p2e)) {
+ /* Clear bitfields */
+ for (i = 0; i < p2e->nbblocks; i++) {
+ SETEMPTY(gen[i],xbits);
+ SETEMPTY(killed[i],xbits);
+ SETEMPTY(in[i],xbits);
+ SETEMPTY(out[i],xbits);
+ }
+ SETEMPTY(saved,xbits);
+ goto livagain;
+ }
+ }
- DLIST_FOREACH(bb, &bblocks, bbelem) {
+ DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
RDEBUG(("liveadd bb %d\n", bb->bbnum));
i = bb->bbnum;
- for (j = 0; j < (tempmax-tempmin); j += NUMBITS)
+ for (j = 0; j < xbits; j += NUMBITS)
live[j/NUMBITS] = 0;
- SETCOPY(live, out[i], j, nbits);
+ 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;
}
@@ -1200,14 +1590,13 @@
#ifdef PCC_DEBUG
if (rdebug) {
- int i;
struct AdjSet *w;
ADJL *x;
REGW *y;
MOVL *m;
printf("Interference edges\n");
- for (i = 0; i < 256; i++) {
+ for (i = 0; i < HASHSZ; i++) {
if ((w = edgehash[i]) == NULL)
continue;
for (; w; w = w->next)
@@ -1217,14 +1606,16 @@
DLIST_FOREACH(y, &initial, link) {
printf("%d (%c): trivial [%d] ", ASGNUM(y),
CLASS(y)+'@', trivially_colorable(y));
+ i = 0;
for (x = ADJLIST(y); x; x = x->r_next) {
if (ONLIST(x->a_temp) != &selectStack &&
ONLIST(x->a_temp) != &coalescedNodes)
printf("%d ", ASGNUM(x->a_temp));
else
printf("(%d) ", ASGNUM(x->a_temp));
+ i++;
}
- printf("\n");
+ printf(": n=%d\n", i);
}
printf("Move nodes\n");
DLIST_FOREACH(y, &initial, link) {
@@ -1281,7 +1672,9 @@
{
int wast;
+#ifdef PCC_DEBUG
RRDEBUG(("DecrementDegree: w %d, c %d\n", ASGNUM(w), c));
+#endif
wast = trivially_colorable(w);
NCLASS(w, c)--;
@@ -1306,7 +1699,9 @@
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) {
@@ -1328,10 +1723,10 @@
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;
@@ -1376,7 +1771,6 @@
return 1;
}
-#define oldcons /* check some more */
/*
* Do a conservative estimation of whether two temporaries can
* be coalesced. This is "Briggs-style" check.
@@ -1387,41 +1781,8 @@
{
ADJL *w, *ww;
REGW *n;
-#ifdef oldcons
- int i, ncl[NUMCLASS+1];
-
- if (CLASS(u) != CLASS(v))
- comperr("Conservative: u(%d = %d), v(%d = %d)",
- ASGNUM(u), CLASS(u), ASGNUM(v), CLASS(v));
-
- for (i = 0; i < NUMCLASS+1; i++)
- ncl[i] = 0;
-
- RDEBUG(("Conservative (%d,%d)\n", ASGNUM(u), ASGNUM(v)));
-
- for (w = ADJLIST(u); w; w = w->r_next) {
- n = w->a_temp;
- if (ONLIST(n) == &selectStack || ONLIST(n) == &coalescedNodes)
- continue;
- for (ww = ADJLIST(v); ww; ww = ww->r_next)
- if (ww->a_temp == n)
- break;
- if (ww)
- continue;
- if (!trivially_colorable(n))
- ncl[CLASS(n)]++;
- }
- for (w = ADJLIST(v); w; w = w->r_next) {
- n = w->a_temp;
- if (ONLIST(n) == &selectStack || ONLIST(n) == &coalescedNodes)
- continue;
- if (!trivially_colorable(n))
- ncl[CLASS(n)]++;
- }
- i = trivially_colorable_p(CLASS(u), ncl);
-#endif
-{
int xncl[NUMCLASS+1], mcl = 0, j;
+
for (j = 0; j < NUMCLASS+1; j++)
xncl[j] = 0;
/*
@@ -1461,17 +1822,7 @@
break;
}
out: j = trivially_colorable_p(CLASS(u), xncl);
-#ifdef oldcons
- if (j != i)
- comperr("Conservative: j %d i %d", j, i);
-#else
return j;
-#endif
-}
-#ifdef oldcons
- RDEBUG(("Conservative i=%d\n", i));
- return i;
-#endif
}
static void
@@ -1492,7 +1843,9 @@
ADJL *l;
REGW *t;
+#ifdef PCC_DEBUG
RDEBUG(("Combine (%d,%d)\n", ASGNUM(u), ASGNUM(v)));
+#endif
if (ONLIST(v) == &freezeWorklist) {
DELWLIST(v);
@@ -1501,12 +1854,14 @@
}
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);
@@ -1544,6 +1899,7 @@
DELWLIST(u);
PUSHWLIST(u, spillWorklist);
}
+#ifdef PCC_DEBUG
if (rdebug) {
ADJL *w;
printf("Combine %d class (%d): ", ASGNUM(u), CLASS(u));
@@ -1556,6 +1912,7 @@
}
printf("\n");
}
+#endif
}
static void
@@ -1573,9 +1930,11 @@
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",
@@ -1620,8 +1979,10 @@
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)
@@ -1649,7 +2010,9 @@
*/
u = POPWLIST(freezeWorklist);
PUSHWLIST(u, simplifyWorklist);
+#ifdef PCC_DEBUG
RDEBUG(("Freeze %d\n", ASGNUM(u)));
+#endif
FreezeMoves(u);
}
@@ -1659,9 +2022,11 @@
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) {
@@ -1672,6 +2037,8 @@
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;
}
@@ -1695,41 +2062,42 @@
DLIST_REMOVE(w, link);
PUSHWLIST(w, simplifyWorklist);
+#ifdef PCC_DEBUG
RDEBUG(("Freezing node %d\n", ASGNUM(w)));
+#endif
FreezeMoves(w);
}
-int gregn(REGW *);
-
-int
-gregn(REGW *w)
-{
- return w->nodnum;
-}
-
/*
* Set class on long-lived temporaries based on its type.
*/
static void
-traclass(NODE *p)
+traclass(NODE *p, void *arg)
{
REGW *nb;
if (p->n_op != TEMP)
return;
- nb = &nblock[(int)p->n_lval];
+ nb = &nblock[regno(p)];
if (CLASS(nb) == 0)
CLASS(nb) = gclass(p->n_type);
}
static void
-paint(NODE *p)
+paint(NODE *p, void *arg)
{
struct optab *q;
REGW *w, *ww;
int i;
+#ifdef notyet
+ /* XXX - trashes rewrite of trees (short) */
+ if (!DLIST_ISEMPTY(&spilledNodes, link)) {
+ p->n_reg = 0;
+ return;
+ }
+#endif
if (p->n_regw != NULL) {
/* Must color all allocated regs also */
ww = w = p->n_regw;
@@ -1747,8 +2115,8 @@
} else
p->n_reg = -1;
if (p->n_op == TEMP) {
- REGW *nb = &nblock[(int)p->n_lval];
- p->n_rval = COLOR(nb);
+ REGW *nb = &nblock[regno(p)];
+ regno(p) = COLOR(nb);
if (TCLASS(p->n_su) == 0)
SCLASS(p->n_su, CLASS(nb));
p->n_op = REG;
@@ -1759,6 +2127,7 @@
static void
AssignColors(struct interpass *ip)
{
+ struct interpass *ip2;
int okColors, c;
REGW *o, *w;
ADJL *x;
@@ -1767,13 +2136,17 @@
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) {
@@ -1787,37 +2160,47 @@
}
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)
if (ip2->type == IP_NODE)
- walkf(ip2->ip_node, paint);
+ walkf(ip2->ip_node, paint, 0);
}
}
@@ -1827,23 +2210,25 @@
* Will never end up here if not optimizing.
*/
static void
-longtemp(NODE *p)
+longtemp(NODE *p, void *arg)
{
+ NODE *l, *r;
REGW *w;
if (p->n_op != TEMP)
return;
/* XXX - should have a bitmask to find temps to convert */
DLIST_FOREACH(w, spole, link) {
- if (w != &nblock[(int)p->n_lval])
+ if (w != &nblock[regno(p)])
continue;
if (w->r_class == 0) {
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;
}
@@ -1855,7 +2240,7 @@
* XXX - must check if basic block structure is destroyed!
*/
static void
-shorttemp(NODE *p)
+shorttemp(NODE *p, void *arg)
{
struct interpass *nip;
struct optab *q;
@@ -1870,10 +2255,14 @@
/* 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);
@@ -1923,7 +2312,7 @@
if (ip->type != IP_NODE)
continue;
cip = ip;
- walkf(ip->ip_node, shorttemp); /* convert temps to oregs */
+ walkf(ip->ip_node, shorttemp, 0); /* convert temps to oregs */
}
if (!DLIST_ISEMPTY(spole, link))
comperr("treerewrite not empty");
@@ -1945,7 +2334,7 @@
continue;
nodepole = ip->ip_node;
thisline = ip->lineno;
- walkf(ip->ip_node, longtemp); /* convert temps to oregs */
+ walkf(ip->ip_node, longtemp, 0); /* convert temps to oregs */
}
nodepole = NIL;
}
@@ -1960,19 +2349,21 @@
NODE *p;
ip = DLIST_NEXT(ipole, qelem); /* PROLOG */
- ip = DLIST_NEXT(ip, qelem); /* first DEFLAB */
+ while (ip->type != IP_DEFLAB)
+ ip = DLIST_NEXT(ip, qelem);
ip = DLIST_NEXT(ip, qelem); /* first NODE */
for (; ip->type != IP_DEFLAB; ip = DLIST_NEXT(ip, qelem)) {
if (ip->type == IP_ASM)
continue;
p = ip->ip_node;
-#ifdef PCC_DEBUG
+#ifdef notdef
+ /* register args may already have been put on stack */
if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
comperr("temparg");
#endif
if (p->n_right->n_op != OREG)
continue; /* arg in register */
- if (w != &nblock[(int)p->n_left->n_lval])
+ if (w != &nblock[regno(p->n_left)])
continue;
w->r_color = p->n_right->n_lval;
tfree(p);
@@ -2068,6 +2459,33 @@
return rwtyp;
}
+#ifdef PCC_DEBUG
+/*
+ * Print TEMP/REG contents in a node.
+ */
+void
+prtreg(FILE *fp, NODE *p)
+{
+ int i, n = p->n_su == -1 ? 0 : ncnt(table[TBLIDX(p->n_su)].needs);
+if (p->n_reg == -1) goto foo;
+ 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++)
+ fprintf(fp, "%d ", p->n_regw[i].nodnum);
+ } else
+ fprintf(fp, "<undef>");
+ } else {
+foo: fprintf(fp, "REG ");
+ if (p->n_reg != -1) {
+ for (i = 0; i < n+1; i++)
+ fprintf(fp, "%s ", rnames[DECRA(p->n_reg, i)]);
+ } else
+ fprintf(fp, "<undef>");
+ }
+}
+#endif
+
#ifdef notyet
/*
* Assign instructions, calculate evaluation order and
@@ -2087,15 +2505,16 @@
* Do register allocation for trees by graph-coloring.
*/
void
-ngenregs(struct interpass *ipole)
+ngenregs(struct p2env *p2e)
{
+ struct interpass *ipole = &p2e->ipole;
extern NODE *nodepole;
- struct interpass_prolog *ipp, *epp;
struct interpass *ip;
- int i, j, nbits = 0;
+ int i, j, tbits;
int uu[NPERMREG] = { -1 };
int xnsavregs[NPERMREG];
int beenhere = 0;
+ TWORD type;
DLIST_INIT(&lunused, link);
DLIST_INIT(&lused, link);
@@ -2103,11 +2522,8 @@
/*
* Do some setup before doing the real thing.
*/
- ipp = (struct interpass_prolog *)DLIST_NEXT(ipole, qelem);
- epp = (struct interpass_prolog *)DLIST_PREV(ipole, qelem);
-
- tempmin = ipp->ip_tmpnum;
- tempmax = epp->ip_tmpnum;
+ tempmin = p2e->ipp->ip_tmpnum;
+ tempmax = p2e->epp->ip_tmpnum;
/*
* Allocate space for the permanent registers in the
@@ -2130,16 +2546,16 @@
#ifdef PCC_DEBUG
nodnum = tempmax;
#endif
- nbits = xbits = tempmax - tempmin;
- if (nbits) {
- nblock = tmpalloc(nbits * sizeof(REGW));
+ tbits = tempmax - tempmin; /* # of temporaries */
+ xbits = tbits + MAXREGS; /* total size of live array */
+ if (tbits) {
+ nblock = tmpalloc(tbits * sizeof(REGW));
nblock -= tempmin;
- live = tmpalloc(BIT2BYTE(nbits));
- RDEBUG(("nblock %p num %d size %zd\n",
- nblock, nbits, (int)(nbits * sizeof(REGW))));
+ RDEBUG(("nblock %p num %d size %zu\n",
+ nblock, tbits, (size_t)(tbits * sizeof(REGW))));
}
-
+ live = tmpalloc(BIT2BYTE(xbits));
/* Block for precolored nodes */
ablock = tmpalloc(sizeof(REGW)*MAXREGS);
@@ -2159,16 +2575,16 @@
recalc:
onlyperm: /* XXX - should not have to redo all */
+ memset(edgehash, 0, sizeof(edgehash));
- if (nbits) {
- memset(nblock+tempmin, 0, nbits * sizeof(REGW));
- memset(live, 0, BIT2BYTE(nbits));
- memset(edgehash, 0, sizeof(edgehash));
+ if (tbits) {
+ memset(nblock+tempmin, 0, tbits * sizeof(REGW));
#ifdef PCC_DEBUG
for (i = tempmin; i < tempmax; i++)
nblock[i].nodnum = i;
#endif
}
+ memset(live, 0, BIT2BYTE(xbits));
RPRINTIP(ipole);
DLIST_INIT(&initial, link);
DLIST_FOREACH(ip, ipole, qelem) {
@@ -2177,15 +2593,20 @@
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);
+ walkf(ip->ip_node, traclass, 0);
}
nodepole = NIL;
RDEBUG(("nsucomp allocated %d temps (%d,%d)\n",
tempmax-tempmin, tempmin, tempmax));
+#ifdef PCC_DEBUG
+ use_regw = 1;
RPRINTIP(ipole);
+ use_regw = 0;
+#endif
RDEBUG(("ngenregs: numtemps %d (%d, %d)\n", tempmax-tempmin,
tempmin, tempmax));
@@ -2205,7 +2626,7 @@
addalledges(&nblock[i+tempmin]);
}
- Build(ipole);
+ Build(p2e);
RDEBUG(("Build done\n"));
MkWorklist();
RDEBUG(("MkWorklist done\n"));
@@ -2230,20 +2651,20 @@
case ONLYPERM:
goto onlyperm;
case SMALL:
- optimize(ipole);
+ optimize(p2e);
if (beenhere++ == MAXLOOP)
- comperr("beenhere");
+ comperr("cannot color graph - COLORMAP() bug?");
goto recalc;
}
}
- /* fill in regs to save */
- ipp->ipp_regs = 0;
+ /* fill in regs to save */
+ memset(p2e->ipp->ipp_regs, 0, sizeof(p2e->ipp->ipp_regs));
for (i = 0; i < NPERMREG-1; i++) {
NODE *p;
if (nsavregs[i]) {
- ipp->ipp_regs |= (1 << permregs[i]);
+ BITSET(p2e->ipp->ipp_regs, permregs[i]);
continue; /* Spilled */
}
if (nblock[i+tempmin].r_color == permregs[i])
@@ -2251,7 +2672,7 @@
/*
* 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])
@@ -2263,23 +2684,27 @@
continue;
/* Generate reg-reg move nodes for save */
+ type = PERMTYPE(permregs[i]);
+#ifdef PCC_DEBUG
+ if (PERMTYPE(nblock[i+tempmin].r_color) != type)
+ comperr("permreg botch");
+#endif
p = mkbinode(ASSIGN,
- mklnode(REG, 0, nblock[i+tempmin].r_color, INT),
- mklnode(REG, 0, permregs[i], INT), INT);
+ mklnode(REG, 0, nblock[i+tempmin].r_color, type),
+ mklnode(REG, 0, permregs[i], type), type);
p->n_reg = p->n_left->n_reg = p->n_right->n_reg = -1;
p->n_left->n_su = p->n_right->n_su = 0;
geninsn(p, FOREFF);
ip = ipnode(p);
DLIST_INSERT_AFTER(ipole->qelem.q_forw, ip, qelem);
- /* XXX not int */
- p = mkbinode(ASSIGN, mklnode(REG, 0, permregs[i], INT),
- mklnode(REG, 0, nblock[i+tempmin].r_color, INT), INT);
+ p = mkbinode(ASSIGN, mklnode(REG, 0, permregs[i], type),
+ mklnode(REG, 0, nblock[i+tempmin].r_color, type), type);
p->n_reg = p->n_left->n_reg = p->n_right->n_reg = -1;
p->n_left->n_su = p->n_right->n_su = 0;
geninsn(p, FOREFF);
ip = ipnode(p);
DLIST_INSERT_BEFORE(ipole->qelem.q_back, ip, qelem);
}
- epp->ipp_regs = ipp->ipp_regs;
- /* Done! */
+ memcpy(p2e->epp->ipp_regs, p2e->ipp->ipp_regs, sizeof(p2e->epp->ipp_regs));
+ /* Done! */
}
Index: common.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/mip/common.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/mip/common.c -L usr.bin/pcc/mip/common.c -u -r1.1 -r1.2
--- usr.bin/pcc/mip/common.c
+++ usr.bin/pcc/mip/common.c
@@ -1,4 +1,4 @@
-/* $Id: common.c,v 1.73 2007/09/22 17:15:00 ragge Exp $ */
+/* $Id: common.c,v 1.87 2008/12/03 07:10:04 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -11,8 +11,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -75,10 +73,19 @@
char *ftitle;
int lineno;
+int warniserr = 0;
+
#ifndef WHERE
#define WHERE(ch) fprintf(stderr, "%s, line %d: ", ftitle, lineno);
#endif
+static void
+incerr(void)
+{
+ if (++nerrors > 30)
+ cerror("too many errors");
+}
+
/*
* nonfatal error message
* the routine where is different for pass 1 and pass 2;
@@ -90,13 +97,11 @@
va_list ap;
va_start(ap, s);
- ++nerrors;
WHERE('u');
vfprintf(stderr, s, ap);
fprintf(stderr, "\n");
- if (nerrors > 30)
- cerror("too many errors");
va_end(ap);
+ incerr();
}
/*
@@ -137,22 +142,22 @@
vfprintf(stderr, s, ap);
fprintf(stderr, "\n");
va_end(ap);
+ if (warniserr)
+ incerr();
}
#ifndef MKEXT
static NODE *freelink;
static int usednodes;
+#ifndef LANG_F77
NODE *
talloc()
{
- extern int inlnodecnt, recovernodes;
register NODE *p;
usednodes++;
- if (recovernodes)
- inlnodecnt++;
if (freelink != NULL) {
p = freelink;
freelink = p->next;
@@ -169,6 +174,7 @@
printf("alloc node %p from memory\n", p);
return p;
}
+#endif
/*
* make a fresh copy of p
@@ -191,7 +197,7 @@
return(q);
}
-
+#ifndef LANG_F77
/*
* ensure that all nodes have been freed
*/
@@ -206,6 +212,7 @@
if ((usednodes - inlnodecnt) != 0)
cerror("usednodes == %d, inlnodecnt %d", usednodes, inlnodecnt);
}
+#endif
/*
* free the tree p
@@ -214,7 +221,7 @@
tfree(NODE *p)
{
if (p->n_op != FREE)
- walkf(p, (void (*)(NODE *))nfree);
+ walkf(p, (void (*)(NODE *, void *))nfree, 0);
}
/*
@@ -224,7 +231,6 @@
NODE *
nfree(NODE *p)
{
- extern int inlnodecnt, recovernodes;
NODE *l;
#ifdef PCC_DEBUG_NODES
NODE *q;
@@ -251,12 +257,16 @@
p->next = freelink;
freelink = p;
usednodes--;
- if (recovernodes)
- inlnodecnt--;
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
@@ -275,7 +285,7 @@
(*f)(t, down, &down1, &down2);
- switch (coptype( t->n_op )) {
+ switch (OPTYPE( t->n_op )) {
case BITYPE:
fwalk( t->n_left, f, down1 );
@@ -292,17 +302,18 @@
}
void
-walkf(NODE *t, void (*f)(NODE *))
+walkf(NODE *t, void (*f)(NODE *, void *), void *arg)
{
int opty;
- opty = coptype(t->n_op);
+
+ opty = OPTYPE(t->n_op);
if (opty != LTYPE)
- walkf( t->n_left, f );
+ walkf( t->n_left, f, arg );
if (opty == BITYPE)
- walkf( t->n_right, f );
- (*f)(t);
+ walkf( t->n_right, f, arg );
+ (*f)(t, arg);
}
int dope[DSIZE];
@@ -317,7 +328,6 @@
{ REG, "REG", LTYPE, },
{ OREG, "OREG", LTYPE, },
{ TEMP, "TEMP", LTYPE, },
- { MOVE, "MOVE", UTYPE, },
{ ICON, "ICON", LTYPE, },
{ FCON, "FCON", LTYPE, },
{ CCODES, "CCODES", LTYPE, },
@@ -328,7 +338,8 @@
{ UFORTCALL, "UFCALL", UTYPE|CALLFLG, },
{ COMPL, "~", UTYPE, },
{ FORCE, "FORCE", UTYPE, },
-/* { INIT, "INIT", UTYPE, }, */
+ { XARG, "XARG", UTYPE, },
+ { XASM, "XASM", BITYPE, },
{ SCONV, "SCONV", UTYPE, },
{ PCONV, "PCONV", UTYPE, },
{ PLUS, "+", BITYPE|FLOFLG|SIMPFLG|COMMFLG, },
@@ -411,6 +422,9 @@
"void",
"signed", /* pass1 */
"bool", /* pass1 */
+ "fcomplex", /* pass1 */
+ "dcomplex", /* pass1 */
+ "lcomplex", /* pass1 */
"?", "?"
};
@@ -434,16 +448,6 @@
}
}
-int crslab = 10;
-/*
- * Return a number for internal labels.
- */
-int
-getlab()
-{
- return crslab++;
-}
-
/*
* Memory allocation routines.
* Memory are allocated from the system in MEMCHUNKSZ blocks.
@@ -453,7 +457,7 @@
*/
#define MEMCHUNKSZ 8192 /* 8k per allocation */
-struct b {
+struct balloc {
char a1;
union {
long long l;
@@ -461,13 +465,11 @@
} a2;
};
-#define ALIGNMENT ((long)&((struct b *)0)->a2)
+#define ALIGNMENT ((long)&((struct balloc *)0)->a2)
#define ROUNDUP(x) (((x) + ((ALIGNMENT)-1)) & ~((ALIGNMENT)-1))
static char *allocpole;
static int allocleft;
-static char *tmppole;
-static int tmpleft;
int permallocsize, tmpallocsize, lostmem;
void *
@@ -475,29 +477,27 @@
{
void *rv;
-//printf("permalloc: allocpole %p allocleft %d size %d ", allocpole, allocleft, size);
- if (size > MEMCHUNKSZ)
- cerror("permalloc");
+ if (size > MEMCHUNKSZ) {
+ if ((rv = malloc(size)) == NULL)
+ cerror("permalloc: missing %d bytes", size);
+ return rv;
+ }
if (size <= 0)
cerror("permalloc2");
if (allocleft < size) {
/* looses unused bytes */
lostmem += allocleft;
-//fprintf(stderr, "allocating perm\n");
if ((allocpole = malloc(MEMCHUNKSZ)) == NULL)
cerror("permalloc: out of memory");
allocleft = MEMCHUNKSZ;
}
size = ROUNDUP(size);
rv = &allocpole[MEMCHUNKSZ-allocleft];
-//printf("rv %p\n", rv);
allocleft -= size;
permallocsize += size;
return rv;
}
-static char *tmplink;
-
void *
tmpcalloc(int size)
{
@@ -508,66 +508,96 @@
return rv;
}
-#define TMPOLE &tmppole[MEMCHUNKSZ-tmpleft]
+/*
+ * Duplicate a string onto the temporary heap.
+ */
+char *
+tmpstrdup(char *str)
+{
+ int len;
+
+ len = strlen(str) + 1;
+ return memcpy(tmpalloc(len), str, len);
+}
+
+/*
+ * Allocation routines for temporary memory.
+ */
+#if 0
+#define ALLDEBUG(x) printf x
+#else
+#define ALLDEBUG(x)
+#endif
+
+#define NELEM ((MEMCHUNKSZ-ROUNDUP(sizeof(struct xalloc *)))/ALIGNMENT)
+#define ELEMSZ (ALIGNMENT)
+#define MAXSZ (NELEM*ELEMSZ)
+struct xalloc {
+ struct xalloc *next;
+ union {
+ struct balloc b; /* for initial alignment */
+ char elm[MAXSZ];
+ } u;
+} *tapole, *tmpole;
+int uselem = NELEM; /* next unused element */
+
void *
tmpalloc(int size)
{
+ struct xalloc *xp;
void *rv;
+ size_t nelem;
- if (size > MEMCHUNKSZ/2) {
- size += ROUNDUP(sizeof(char *));
- if ((rv = malloc(size)) == NULL)
- cerror("tmpalloc: out of memory");
- /* link in before current chunk XXX */
- *(char **)rv = *(char **)tmppole;
- *(char **)tmppole = rv;
- tmpallocsize += size;
- return (char *)rv + ROUNDUP(sizeof(char *));
- }
- if (size <= 0)
- cerror("tmpalloc2");
-//printf("tmpalloc: tmppole %p tmpleft %d size %d ", tmppole, tmpleft, size);
- size = ROUNDUP(size);
- if (tmpleft < size) {
- if ((tmppole = malloc(MEMCHUNKSZ)) == NULL)
- cerror("tmpalloc: out of memory");
-//fprintf(stderr, "allocating tmp\n");
- tmpleft = MEMCHUNKSZ - ROUNDUP(sizeof(char *));
- *(char **)tmppole = tmplink;
- tmplink = tmppole;
- }
- rv = TMPOLE;
-//printf("rv %p\n", rv);
- tmpleft -= size;
- tmpallocsize += size;
+ nelem = ROUNDUP(size)/ELEMSZ;
+ ALLDEBUG(("tmpalloc(%ld,%ld) %d (%zd) ", ELEMSZ, NELEM, size, nelem));
+ if (nelem > NELEM/2) {
+ xp = malloc(size + ROUNDUP(sizeof(struct xalloc *)));
+ if (xp == NULL)
+ cerror("out of memory");
+ ALLDEBUG(("XMEM! (%ld,%p) ",
+ size + ROUNDUP(sizeof(struct xalloc *)), xp));
+ xp->next = tmpole;
+ tmpole = xp;
+ ALLDEBUG(("rv %p\n", &xp->u.elm[0]));
+ return &xp->u.elm[0];
+ }
+ if (nelem + uselem >= NELEM) {
+ ALLDEBUG(("MOREMEM! "));
+ /* alloc more */
+ if ((xp = malloc(sizeof(struct xalloc))) == NULL)
+ cerror("out of memory");
+ xp->next = tapole;
+ tapole = xp;
+ uselem = 0;
+ } else
+ xp = tapole;
+ rv = &xp->u.elm[uselem * ELEMSZ];
+ ALLDEBUG(("elemno %d ", uselem));
+ uselem += nelem;
+ ALLDEBUG(("new %d rv %p\n", uselem, rv));
return rv;
}
-#if 0
-/*
- * Print and pack strings on heap.
- */
-char *tmpsprintf(char *fmt, ...);
-char *
-tmpsprintf(char *fmt, ...)
+void
+tmpfree()
{
- va_list ap;
- int len;
- char *tmp;
+ struct xalloc *x1;
- tmp = TMPOLE;
- va_start(ap, fmt);
- if ((len = vsnprintf(tmp, tmpleft, fmt, ap)) >= tmpleft) {
- (void)tmpalloc(tmpleft); /* ugly */
- tmp = TMPOLE;
- if ((len = vsnprintf(tmp, tmpleft, fmt, ap)) >= tmpleft)
- cerror("bad tmpsprintf len");
+ while (tmpole) {
+ x1 = tmpole;
+ tmpole = tmpole->next;
+ ALLDEBUG(("XMEM! free %p\n", x1));
+ free(x1);
+ }
+ while (tapole && tapole->next) {
+ x1 = tapole;
+ tapole = tapole->next;
+ ALLDEBUG(("MOREMEM! free %p\n", x1));
+ free(x1);
}
- va_end(ap);
- tmpleft += len;
- return tmp;
+ if (tapole)
+ uselem = 0;
}
-#endif
/*
* Print and pack vararg string on heap.
@@ -576,43 +606,58 @@
char *
tmpvsprintf(char *fmt, va_list ap)
{
- int len;
+ int len, asz;
char *tmp;
- if (tmpleft == 0)
+ if (uselem == NELEM)
(void)tmpalloc(1); /* XXX ugly */
- tmp = TMPOLE;
- if ((len = vsnprintf(tmp, tmpleft, fmt, ap)) >= tmpleft) {
- (void)tmpalloc(tmpleft+1); /* ugly */
- tmp = TMPOLE;
- if ((len = vsnprintf(tmp, tmpleft, fmt, ap)) >= tmpleft)
+ tmp = &tapole->u.elm[uselem * ELEMSZ];
+ asz = (NELEM-uselem) * ELEMSZ;
+//printf("tmpvsprintf: uselem %d asz %d ", uselem, asz);
+ if ((len = vsnprintf(tmp, asz, fmt, ap)) >= asz) {
+ (void)tmpalloc(asz+1); /* ugly */
+ tmp = &tapole->u.elm[uselem * ELEMSZ];
+ asz = (NELEM-uselem) * ELEMSZ;
+//printf("len %d uselem %d \n", len, uselem);
+ if ((len = vsnprintf(tmp, asz, fmt, ap)) >= asz)
cerror("bad tmpsprintf len");
}
- tmpleft -= len+1;
+//else printf("\n");
+ uselem += (ROUNDUP(len+1)/ELEMSZ);
+//printf("len %d asz %d strlen(tmp) %ld\n", len, asz, strlen(tmp));
return tmp;
}
+/*
+ * Set a mark for later removal from the temp heap.
+ */
void
-tmpfree()
+markset(struct mark *m)
{
- char *f, *of;
+ m->tmsav = tmpole;
+ m->tasav = tapole;
+ m->elem = uselem;
+}
- f = tmplink;
- if (f == NULL)
- return;
- if (*(char **)f == NULL) {
- tmpleft = MEMCHUNKSZ - ROUNDUP(sizeof(char *));
- return;
+/*
+ * Remove everything on tmp heap from a mark.
+ */
+void
+markfree(struct mark *m)
+{
+ struct xalloc *x1;
+
+ while (tmpole != m->tmsav) {
+ x1 = tmpole;
+ tmpole = tmpole->next;
+ free(x1);
}
- while (f != NULL) {
- of = f;
- f = *(char **)f;
- free(of);
- }
- tmplink = tmppole = NULL;
- tmpleft = 0;
-//fprintf(stderr, "freeing tmp\n");
- /* XXX - nothing right now */
+ while (tapole != m->tasav) {
+ x1 = tapole;
+ tapole = tapole->next;
+ free(x1);
+ }
+ uselem = m->elem;
}
/*
@@ -636,3 +681,48 @@
*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;
+}
Index: compat.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/mip/compat.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/mip/compat.c -L usr.bin/pcc/mip/compat.c -u -r1.1 -r1.2
--- usr.bin/pcc/mip/compat.c
+++ usr.bin/pcc/mip/compat.c
@@ -24,12 +24,83 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: compat.c,v 1.1 2007/09/20 12:52:15 ragge Exp $
+ * $Id: compat.c,v 1.8 2008/11/01 08:29:38 mickey Exp $
+ */
+
+/*-
+ * Copyright (c) 1997, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein and Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $NetBSD: basename.c,v 1.5 2002/10/17 02:06:04 thorpej Exp $
+ */
+
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $NetBSD: gettemp.c,v 1.13 2003/12/05 00:57:36 uebayasi Exp $
*/
#include <string.h>
+#include <fcntl.h>
-#include "../config.h"
+#include "config.h"
+#define MKEXT /* XXX */
#include "manifest.h"
#ifndef HAVE_STRLCAT
@@ -102,3 +173,754 @@
return(s - src - 1); /* count does not include NUL */
}
#endif
+
+#ifndef HAVE_GETOPT
+char *optarg;
+int optind = 1;
+int
+getopt(int argc, char **argv, char *args)
+{
+ int n;
+ int nlen = strlen(args);
+ char cmd;
+ char rv;
+
+ if (argv[optind] && *argv[optind] == '-') {
+ cmd = *(argv[optind] + 1);
+
+ for (n = 0; n < nlen; n++) {
+ if (args[n] == ':')
+ continue;
+ if (args[n] == cmd) {
+ rv = *(argv[optind] + 1);
+ if (args[n+1] == ':') {
+ if (*(argv[optind] + 2) != '\0') {
+ optarg = argv[optind] + 2;
+ optind += 1;
+ } else {
+ optarg = argv[optind + 1];
+ optind += 2;
+ }
+ if (!optarg)
+ optarg="";
+ return rv;
+ } else {
+ optarg = NULL;
+ optind += 1;
+ return rv;
+ }
+ }
+ }
+ }
+
+ return -1;
+}
+#endif
+
+#ifdef WIN32
+#define ISPATHSEPARATOR(x) ((x == '/') || (x == '\\'))
+#else
+#define ISPATHSEPARATOR(x) (x == '/')
+#endif
+
+#ifndef HAVE_BASENAME
+#ifndef PATH_MAX
+#define PATH_MAX 5000
+#endif
+
+char *
+basename(char *path)
+{
+ static char singledot[] = ".";
+ static char result[PATH_MAX];
+ char *p, *lastp;
+ size_t len;
+
+ /*
+ * If `path' is a null pointer or points to an empty string,
+ * return a pointer to the string ".".
+ */
+ if ((path == NULL) || (*path == '\0'))
+ return (singledot);
+
+ /* Strip trailing slashes, if any. */
+ lastp = path + strlen(path) - 1;
+ while (lastp != path && ISPATHSEPARATOR(*lastp))
+ lastp--;
+
+ /* Now find the beginning of this (final) component. */
+ p = lastp;
+ while (p != path && !ISPATHSEPARATOR(*(p - 1)))
+ p--;
+
+ /* ...and copy the result into the result buffer. */
+ len = (lastp - p) + 1 /* last char */;
+ if (len > (PATH_MAX - 1))
+ len = PATH_MAX - 1;
+
+ memcpy(result, p, len);
+ result[len] = '\0';
+
+ return (result);
+}
+#endif
+
+#if !defined(HAVE_MKSTEMP) && !defined(WIN32)
+int
+mkstemp(char *path)
+{
+ char *start, *trv;
+ unsigned int pid;
+
+ /* To guarantee multiple calls generate unique names even if
+ the file is not created. 676 different possibilities with 7
+ or more X's, 26 with 6 or less. */
+ static char xtra[2] = "aa";
+ int xcnt = 0;
+
+ pid = getpid();
+
+ /* Move to end of path and count trailing X's. */
+ for (trv = path; *trv; ++trv)
+ if (*trv == 'X')
+ xcnt++;
+ else
+ xcnt = 0;
+
+ /* Use at least one from xtra. Use 2 if more than 6 X's. */
+ if (*(trv - 1) == 'X')
+ *--trv = xtra[0];
+ if (xcnt > 6 && *(trv - 1) == 'X')
+ *--trv = xtra[1];
+
+ /* Set remaining X's to pid digits with 0's to the left. */
+ while (*--trv == 'X') {
+ *trv = (pid % 10) + '0';
+ pid /= 10;
+ }
+
+ /* update xtra for next call. */
+ if (xtra[0] != 'z')
+ xtra[0]++;
+ else {
+ xtra[0] = 'a';
+ if (xtra[1] != 'z')
+ xtra[1]++;
+ else
+ xtra[1] = 'a';
+ }
+
+ return open(path, O_CREAT | O_EXCL | O_RDWR, 0600);
+}
+#endif
+
+#ifndef HAVE_FFS
+int
+ffs(int x)
+{
+ int r = 1;
+ if (!x) return 0;
+ if (!(x & 0xffff)) { x >>= 16; r += 16; }
+ if (!(x & 0xff)) { x >>= 8; r += 8; }
+ if (!(x & 0xf)) { x >>= 4; r += 4; }
+ if (!(x & 3)) { x >>= 2; r += 2; }
+ if (!(x & 1)) { x >>= 1; r += 1; }
+
+ return r;
+}
+#endif
+
+/*
+ * Copyright Patrick Powell 1995
+ * This code is based on code written by Patrick Powell (papowell at astart.com)
+ * It may be used for any purpose as long as this notice remains intact
+ * on all source code distributions
+ */
+
+#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
+
+static void
+dopr(char *buffer, size_t maxlen, const char *format, va_list args);
+
+static void
+fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags,
+ int min, int max);
+
+static void
+fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base,
+ int min, int max, int flags);
+
+static void
+fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,
+ int min, int max, int flags);
+
+static void
+dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
+
+/*
+ * dopr(): poor man's version of doprintf
+ */
+
+/* format read states */
+#define DP_S_DEFAULT 0
+#define DP_S_FLAGS 1
+#define DP_S_MIN 2
+#define DP_S_DOT 3
+#define DP_S_MAX 4
+#define DP_S_MOD 5
+#define DP_S_CONV 6
+#define DP_S_DONE 7
+
+/* format flags - Bits */
+#define DP_F_MINUS (1 << 0)
+#define DP_F_PLUS (1 << 1)
+#define DP_F_SPACE (1 << 2)
+#define DP_F_NUM (1 << 3)
+#define DP_F_ZERO (1 << 4)
+#define DP_F_UP (1 << 5)
+#define DP_F_UNSIGNED (1 << 6)
+
+/* Conversion Flags */
+#define DP_C_SHORT 1
+#define DP_C_LONG 2
+#define DP_C_LDOUBLE 3
+#define DP_C_LONG_LONG 4
+
+#define char_to_int(p) (p - '0')
+#define abs_val(p) (p < 0 ? -p : p)
+
+
+static void
+dopr(char *buffer, size_t maxlen, const char *format, va_list args)
+{
+ char *strvalue, ch;
+ long value;
+ long double fvalue;
+ int min = 0, max = -1, state = DP_S_DEFAULT, flags = 0, cflags = 0;
+ size_t currlen = 0;
+
+ ch = *format++;
+
+ while (state != DP_S_DONE) {
+ if ((ch == '\0') || (currlen >= maxlen))
+ state = DP_S_DONE;
+
+ switch(state) {
+ case DP_S_DEFAULT:
+ if (ch == '%')
+ state = DP_S_FLAGS;
+ else
+ dopr_outch(buffer, &currlen, maxlen, ch);
+ ch = *format++;
+ break;
+ case DP_S_FLAGS:
+ switch (ch) {
+ case '-':
+ flags |= DP_F_MINUS;
+ ch = *format++;
+ break;
+ case '+':
+ flags |= DP_F_PLUS;
+ ch = *format++;
+ break;
+ case ' ':
+ flags |= DP_F_SPACE;
+ ch = *format++;
+ break;
+ case '#':
+ flags |= DP_F_NUM;
+ ch = *format++;
+ break;
+ case '0':
+ flags |= DP_F_ZERO;
+ ch = *format++;
+ break;
+ default:
+ state = DP_S_MIN;
+ break;
+ }
+ break;
+ case DP_S_MIN:
+ if (isdigit((unsigned char)ch)) {
+ min = 10 * min + char_to_int (ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ min = va_arg (args, int);
+ ch = *format++;
+ state = DP_S_DOT;
+ } else
+ state = DP_S_DOT;
+ break;
+ case DP_S_DOT:
+ if (ch == '.') {
+ state = DP_S_MAX;
+ ch = *format++;
+ } else
+ state = DP_S_MOD;
+ break;
+ case DP_S_MAX:
+ if (isdigit((unsigned char)ch)) {
+ if (max < 0)
+ max = 0;
+ max = 10 * max + char_to_int(ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ max = va_arg (args, int);
+ ch = *format++;
+ state = DP_S_MOD;
+ } else
+ state = DP_S_MOD;
+ break;
+ case DP_S_MOD:
+ switch (ch) {
+ case 'h':
+ cflags = DP_C_SHORT;
+ ch = *format++;
+ break;
+ case 'l':
+ cflags = DP_C_LONG;
+ ch = *format++;
+ if (ch == 'l') {
+ cflags = DP_C_LONG_LONG;
+ ch = *format++;
+ }
+ break;
+ case 'q':
+ cflags = DP_C_LONG_LONG;
+ ch = *format++;
+ break;
+ case 'L':
+ cflags = DP_C_LDOUBLE;
+ ch = *format++;
+ break;
+ default:
+ break;
+ }
+ state = DP_S_CONV;
+ break;
+ case DP_S_CONV:
+ switch (ch) {
+ case 'd':
+ case 'i':
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg (args, long long);
+ else
+ value = va_arg (args, int);
+ fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags);
+ break;
+ case 'o':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg(args, unsigned long long);
+ else
+ value = va_arg(args, unsigned int);
+ fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags);
+ break;
+ case 'u':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg(args, unsigned long long);
+ else
+ value = va_arg(args, unsigned int);
+ fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
+ break;
+ case 'X':
+ flags |= DP_F_UP;
+ case 'x':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg(args, unsigned long long);
+ else
+ value = va_arg(args, unsigned int);
+ fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags);
+ break;
+ case 'f':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, long double);
+ else
+ fvalue = va_arg(args, double);
+ /* um, floating point? */
+ fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags);
+ break;
+ case 'E':
+ flags |= DP_F_UP;
+ case 'e':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, long double);
+ else
+ fvalue = va_arg(args, double);
+ break;
+ case 'G':
+ flags |= DP_F_UP;
+ case 'g':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, long double);
+ else
+ fvalue = va_arg(args, double);
+ break;
+ case 'c':
+ dopr_outch(buffer, &currlen, maxlen, va_arg(args, int));
+ break;
+ case 's':
+ strvalue = va_arg(args, char *);
+ if (max < 0)
+ max = maxlen; /* ie, no max */
+ fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max);
+ break;
+ case 'p':
+ strvalue = va_arg(args, void *);
+ fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
+ break;
+ case 'n':
+ if (cflags == DP_C_SHORT) {
+ short int *num;
+ num = va_arg(args, short int *);
+ *num = currlen;
+ } else if (cflags == DP_C_LONG) {
+ long int *num;
+ num = va_arg(args, long int *);
+ *num = currlen;
+ } else if (cflags == DP_C_LONG_LONG) {
+ long long *num;
+ num = va_arg(args, long long *);
+ *num = currlen;
+ } else {
+ int *num;
+ num = va_arg(args, int *);
+ *num = currlen;
+ }
+ break;
+ case '%':
+ dopr_outch(buffer, &currlen, maxlen, ch);
+ break;
+ case 'w': /* not supported yet, treat as next char */
+ ch = *format++;
+ break;
+ default: /* Unknown, skip */
+ break;
+ }
+ ch = *format++;
+ state = DP_S_DEFAULT;
+ flags = cflags = min = 0;
+ max = -1;
+ break;
+ case DP_S_DONE:
+ break;
+ default: /* hmm? */
+ break; /* some picky compilers need this */
+ }
+ }
+ if (currlen < maxlen - 1)
+ buffer[currlen] = '\0';
+ else
+ buffer[maxlen - 1] = '\0';
+}
+
+static void
+fmtstr(char *buffer, size_t *currlen, size_t maxlen,
+ char *value, int flags, int min, int max)
+{
+ int cnt = 0, padlen, strln; /* amount to pad */
+
+ if (value == 0)
+ value = "<NULL>";
+
+ for (strln = 0; value[strln]; ++strln); /* strlen */
+ padlen = min - strln;
+ if (padlen < 0)
+ padlen = 0;
+ if (flags & DP_F_MINUS)
+ padlen = -padlen; /* Left Justify */
+
+ while ((padlen > 0) && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --padlen;
+ ++cnt;
+ }
+ while (*value && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, *value++);
+ ++cnt;
+ }
+ while ((padlen < 0) && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ ++padlen;
+ ++cnt;
+ }
+}
+
+/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
+
+static void
+fmtint(char *buffer, size_t *currlen, size_t maxlen,
+ long value, int base, int min, int max, int flags)
+{
+ unsigned long uvalue;
+ char convert[20];
+ int signvalue = 0, place = 0, caps = 0;
+ int spadlen = 0; /* amount to space pad */
+ int zpadlen = 0; /* amount to zero pad */
+
+#define PADMAX(x,y) ((x) > (y) ? (x) : (y))
+
+ if (max < 0)
+ max = 0;
+
+ uvalue = value;
+
+ if (!(flags & DP_F_UNSIGNED)) {
+ if (value < 0) {
+ signvalue = '-';
+ uvalue = -value;
+ } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
+ signvalue = '+';
+ else if (flags & DP_F_SPACE)
+ signvalue = ' ';
+ }
+
+ if (flags & DP_F_UP)
+ caps = 1; /* Should characters be upper case? */
+ do {
+ convert[place++] =
+ (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [uvalue % (unsigned)base];
+ uvalue = (uvalue / (unsigned)base );
+ } while (uvalue && (place < 20));
+ if (place == 20)
+ place--;
+ convert[place] = 0;
+
+ zpadlen = max - place;
+ spadlen = min - PADMAX(max, place) - (signvalue ? 1 : 0);
+ if (zpadlen < 0)
+ zpadlen = 0;
+ if (spadlen < 0)
+ spadlen = 0;
+ if (flags & DP_F_ZERO) {
+ zpadlen = PADMAX(zpadlen, spadlen);
+ spadlen = 0;
+ }
+ if (flags & DP_F_MINUS)
+ spadlen = -spadlen; /* Left Justifty */
+
+ /* Spaces */
+ while (spadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --spadlen;
+ }
+
+ /* Sign */
+ if (signvalue)
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+
+ /* Zeros */
+ if (zpadlen > 0) {
+ while (zpadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --zpadlen;
+ }
+ }
+
+ /* Digits */
+ while (place > 0)
+ dopr_outch(buffer, currlen, maxlen, convert[--place]);
+
+ /* Left Justified spaces */
+ while (spadlen < 0) {
+ dopr_outch (buffer, currlen, maxlen, ' ');
+ ++spadlen;
+ }
+}
+
+static long double
+pow10(int exp)
+{
+ long double result = 1;
+
+ while (exp) {
+ result *= 10;
+ exp--;
+ }
+
+ return result;
+}
+
+static long
+round(long double value)
+{
+ long intpart = value;
+
+ value -= intpart;
+ if (value >= 0.5)
+ intpart++;
+
+ return intpart;
+}
+
+static void
+fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,
+ int min, int max, int flags)
+{
+ char iconvert[20], fconvert[20];
+ int signvalue = 0, iplace = 0, fplace = 0;
+ int padlen = 0; /* amount to pad */
+ int zpadlen = 0, caps = 0;
+ long intpart, fracpart;
+ long double ufvalue;
+
+ /*
+ * AIX manpage says the default is 0, but Solaris says the default
+ * is 6, and sprintf on AIX defaults to 6
+ */
+ if (max < 0)
+ max = 6;
+
+ ufvalue = abs_val(fvalue);
+
+ if (fvalue < 0)
+ signvalue = '-';
+ else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
+ signvalue = '+';
+ else if (flags & DP_F_SPACE)
+ signvalue = ' ';
+
+ intpart = ufvalue;
+
+ /*
+ * Sorry, we only support 9 digits past the decimal because of our
+ * conversion method
+ */
+ if (max > 9)
+ max = 9;
+
+ /* We "cheat" by converting the fractional part to integer by
+ * multiplying by a factor of 10
+ */
+ fracpart = round((pow10 (max)) * (ufvalue - intpart));
+
+ if (fracpart >= pow10 (max)) {
+ intpart++;
+ fracpart -= pow10 (max);
+ }
+
+ /* Convert integer part */
+ do {
+ iconvert[iplace++] =
+ (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [intpart % 10];
+ intpart = (intpart / 10);
+ } while(intpart && (iplace < 20));
+ if (iplace == 20)
+ iplace--;
+ iconvert[iplace] = 0;
+
+ /* Convert fractional part */
+ do {
+ fconvert[fplace++] =
+ (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [fracpart % 10];
+ fracpart = (fracpart / 10);
+ } while(fracpart && (fplace < 20));
+ if (fplace == 20)
+ fplace--;
+ fconvert[fplace] = 0;
+
+ /* -1 for decimal point, another -1 if we are printing a sign */
+ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
+ zpadlen = max - fplace;
+ if (zpadlen < 0)
+ zpadlen = 0;
+ if (padlen < 0)
+ padlen = 0;
+ if (flags & DP_F_MINUS)
+ padlen = -padlen; /* Left Justifty */
+
+ if ((flags & DP_F_ZERO) && (padlen > 0)) {
+ if (signvalue) {
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+ --padlen;
+ signvalue = 0;
+ }
+ while (padlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --padlen;
+ }
+ }
+ while (padlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --padlen;
+ }
+ if (signvalue)
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+
+ while (iplace > 0)
+ dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]);
+
+ /*
+ * Decimal point. This should probably use locale to find the
+ * correct char to print out.
+ */
+ dopr_outch(buffer, currlen, maxlen, '.');
+
+ while (fplace > 0)
+ dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]);
+
+ while (zpadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --zpadlen;
+ }
+
+ while (padlen < 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ ++padlen;
+ }
+}
+
+static void
+dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
+{
+ if (*currlen < maxlen)
+ buffer[(*currlen)++] = c;
+}
+#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
+
+#ifndef HAVE_VSNPRINTF
+int
+vsnprintf(char *str, size_t count, const char *fmt, va_list args)
+{
+ str[0] = 0;
+ dopr(str, count, fmt, args);
+
+ return(strlen(str));
+}
+#endif /* !HAVE_VSNPRINTF */
+
+#ifndef HAVE_SNPRINTF
+int
+snprintf(char *str,size_t count,const char *fmt,...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void) vsnprintf(str, count, fmt, ap);
+ va_end(ap);
+
+ return(strlen(str));
+}
+
+#endif /* !HAVE_SNPRINTF */
Index: manifest.h
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/mip/manifest.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/mip/manifest.h -L usr.bin/pcc/mip/manifest.h -u -r1.1 -r1.2
--- usr.bin/pcc/mip/manifest.h
+++ usr.bin/pcc/mip/manifest.h
@@ -1,4 +1,4 @@
-/* $Id: manifest.h,v 1.59 2007/09/20 12:02:54 ragge Exp $ */
+/* $Id: manifest.h,v 1.87 2008/12/04 07:28:55 ragge Exp $ */
/*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
@@ -37,9 +37,11 @@
#define MANIFEST
#include <stdio.h>
-#include "../config.h"
+#include <string.h>
+#include "config.h"
#include "macdefs.h"
#include "node.h"
+#include "compat.h"
/*
* Node types
@@ -75,8 +77,8 @@
#define LDOUBLE 14
#define STRTY 15
#define UNIONTY 16
-#define ENUMTY 17
-#define MOETY 18 /* member of enum */
+/* #define ENUMTY 17 */
+/* #define MOETY 18 */ /* member of enum */
#define VOID 19
#define MAXTYPES 19 /* highest type+1 to be used by lang code */
@@ -114,6 +116,7 @@
#define UNSIGNABLE(x) (((x)<=ULONGLONG&&(x)>=CHAR) && !ISUNSIGNED(x))
#define ENUNSIGN(x) ((x)|1)
#define DEUNSIGN(x) ((x)&~1)
+#define ISINTEGER(x) (((x) >= CHAR && (x) <= ULONGLONG) || (x) == BOOL)
#define ISPTR(x) (((x)&TMASK)==PTR)
#define ISFTN(x) (((x)&TMASK)==FTN) /* is x a function type? */
#define ISARY(x) (((x)&TMASK)==ARY) /* is x an array type? */
@@ -165,18 +168,24 @@
#define DATA 1 /* (rw) data segment */
#define RDATA 2 /* (ro) data segment */
#define STRNG 3 /* (ro) string segment */
+#define UDATA 4 /* (rw) uninitialized data */
+#define regno(p) ((p)->n_rval) /* register number */
+
/*
*
*/
extern int bdebug, tdebug, edebug;
extern int ddebug, xdebug, f2debug;
-extern int iTflag, oTflag;
-extern int vdebug, sflag, nflag, gflag;
+extern int iTflag, oTflag, kflag;
+extern int sflag, nflag, gflag, pflag;
extern int Wstrict_prototypes, Wmissing_prototypes, Wimplicit_int,
- Wimplicit_function_declaration;
-extern int xssaflag, xtailcallflag, xtemps, xdeljumps;
+ 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, xdce;
int yyparse(void);
void yyaccpt(void);
@@ -191,6 +200,7 @@
#define DLIST_NEXT(h,f) (h)->f.q_forw
#define DLIST_PREV(h,f) (h)->f.q_back
#define DLIST_ISEMPTY(h,f) ((h)->f.q_forw == (h))
+#define DLIST_ENDMARK(h) (h)
#define DLIST_FOREACH(v,h,f) \
for ((v) = (h)->f.q_forw; (v) != (h); (v) = (v)->f.q_forw)
#define DLIST_FOREACH_REVERSE(v,h,f) \
@@ -215,17 +225,26 @@
/* Single-linked list */
#define SLIST_INIT(h) \
{ (h)->q_forw = NULL; (h)->q_last = &(h)->q_forw; }
+#define SLIST_SETUP(h) { NULL, &(h)->q_forw }
#define SLIST_ENTRY(t) struct { struct t *q_forw; }
#define SLIST_HEAD(n,t) struct n { struct t *q_forw, **q_last; }
+#define SLIST_ISEMPTY(h) ((h)->q_last == &(h)->q_forw)
#define SLIST_FIRST(h) ((h)->q_forw)
#define SLIST_FOREACH(v,h,f) \
for ((v) = (h)->q_forw; (v) != NULL; (v) = (v)->f.q_forw)
+#define SLIST_INSERT_FIRST(h,e,f) { \
+ if ((h)->q_last == &(h)->q_forw) \
+ (h)->q_last = &(e)->f.q_forw; \
+ (e)->f.q_forw = (h)->q_forw; \
+ (h)->q_forw = (e); \
+}
#define SLIST_INSERT_LAST(h,e,f) { \
(e)->f.q_forw = NULL; \
*(h)->q_last = (e); \
(h)->q_last = &(e)->f.q_forw; \
}
+#ifndef MKEXT
/*
* Functions for inter-pass communication.
*
@@ -253,11 +272,20 @@
char *ipp_name; /* Function name */
int ipp_vis; /* Function visibility */
TWORD ipp_type; /* Function type */
- int ipp_regs; /* Bitmask of registers to save */
+#define NIPPREGS BIT2BYTE(MAXREGS)/sizeof(bittype)
+ bittype ipp_regs[NIPPREGS];
+ /* Bitmask of registers to save */
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
};
+#else
+struct interpass { int dummy; };
+struct interpass_prolog;
+#endif /* !MKEXT */
/*
* Epilog/prolog takes following arguments (in order):
@@ -289,17 +317,13 @@
/*
* External declarations, typedefs and the like
*/
-char *hash(char *s);
-char *savestr(char *cp);
-char *tstr(char *cp);
-
-#ifndef HAVE_STRLCPY
-size_t strlcpy(char *dst, const char *src, size_t siz);
-#endif
-#ifndef HAVE_STRLCAT
-size_t strlcat(char *dst, const char *src, size_t siz);
-#endif
+/* used for memory allocation */
+typedef struct mark {
+ void *tmsav;
+ void *tasav;
+ int elem;
+} MARK;
/* memory management stuff */
void *permalloc(int size);
@@ -307,6 +331,12 @@
void *tmpalloc(int size);
void tmpfree(void);
char *newstring(char *, int len);
+char *tmpstrdup(char *str);
+void markset(struct mark *m);
+void markfree(struct mark *m);
+
+/* command-line processing */
+void mflags(char *);
void tprint(FILE *, TWORD, TWORD);
@@ -318,7 +348,18 @@
/* node routines */
NODE *nfree(NODE *);
+void tfree(NODE *);
+NODE *tcopy(NODE *);
+void walkf(NODE *, void (*f)(NODE *, void *), void *);
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);
+void cerror(char *s, ...);
+void werror(char *s, ...);
+void uerror(char *s, ...);
+
extern int nerrors; /* number of errors seen so far */
+extern int warniserr; /* treat warnings as errors */
#endif
Index: mkext.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/mip/mkext.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/mip/mkext.c -L usr.bin/pcc/mip/mkext.c -u -r1.1 -r1.2
--- usr.bin/pcc/mip/mkext.c
+++ usr.bin/pcc/mip/mkext.c
@@ -3,8 +3,21 @@
* Generate defines for the needed hardops.
*/
#include "pass2.h"
+#include <stdlib.h>
+#ifdef HAVE_STRING_H
#include <string.h>
+#endif
+
+#ifdef HAVE_C99_FORMAT
+#define FMTdPTR "%td"
+#else
+#if defined(_WIN64) || defined(LP64)
+#define FMTdPTR "%ld"
+#else
+#define FMTdPTR "%d"
+#endif
+#endif
int chkop[DSIZE];
@@ -62,12 +75,53 @@
int rstatus[] = { RSTATUS };
int roverlay[MAXREGS][MAXREGS] = { ROVERLAP };
-int regclassmap[NUMCLASS][MAXREGS];
+int regclassmap[CLASSG][MAXREGS]; /* CLASSG is highest class */
static void
compl(struct optab *q, char *str)
{
- printf("table entry %td, op %s: %s\n", q - table, opst[q->op], str);
+ int op = q->op;
+ char *s;
+
+ if (op < OPSIMP) {
+ s = opst[op];
+ } else
+ 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
+getrcl(struct optab *q)
+{
+ int v = q->needs &
+ (NACOUNT|NBCOUNT|NCCOUNT|NDCOUNT|NECOUNT|NFCOUNT|NGCOUNT);
+ int r = q->rewrite & RESC1 ? 1 : q->rewrite & RESC2 ? 2 : 3;
+ int i = 0;
+
+#define INCK(c) while (v & c##COUNT) { \
+ v -= c##REG, i++; if (i == r) return I##c##REG; }
+ INCK(NA)
+ INCK(NB)
+ INCK(NC)
+ INCK(ND)
+ INCK(NE)
+ INCK(NF)
+ INCK(NG)
+ return 0;
}
int
@@ -75,10 +129,16 @@
{
struct optab *q;
struct checks *ch;
- int i, j, areg, breg, creg, dreg, mx;
+ int i, j, areg, breg, creg, dreg, mx, ereg, freg, greg;
char *bitary;
int bitsz, rval, nelem;
+ if (argc == 2) {
+ i = atoi(argv[1]);
+ printf("Entry %d:\n%s\n", i, table[i].cstring);
+ return 0;
+ }
+
mkdope();
for (q = table; q->op != FREE; q++) {
@@ -99,6 +159,8 @@
perror("open hfile");
return(1);
}
+ fprintf(fh, "#ifndef _EXTERNAL_H_\n#define _EXTERNAL_H_\n");
+
for (ch = checks; ch->op != 0; ch++) {
if ((chkop[ch->op] & ch->type) == 0)
fprintf(fh, "#define NEED_%s\n", ch->name);
@@ -117,12 +179,17 @@
bitsz = sizeof(int) == 4 ? 32 : 16;
}
fprintf(fh, "#define NUMBITS %d\n", bitsz);
+ fprintf(fh, "#define BIT2BYTE(bits) "
+ "((((bits)+NUMBITS-1)/NUMBITS)*(NUMBITS/8))\n");
fprintf(fh, "#define BITSET(arr, bit) "
- "(arr[bit/NUMBITS] |= (1 << (bit & (NUMBITS-1))))\n");
+ "(arr[bit/NUMBITS] |= ((%s)1 << (bit & (NUMBITS-1))))\n",
+ bitary);
fprintf(fh, "#define BITCLEAR(arr, bit) "
- "(arr[bit/NUMBITS] &= ~(1 << (bit & (NUMBITS-1))))\n");
+ "(arr[bit/NUMBITS] &= ~((%s)1 << (bit & (NUMBITS-1))))\n",
+ bitary);
fprintf(fh, "#define TESTBIT(arr, bit) "
- "(arr[bit/NUMBITS] & (1 << (bit & (NUMBITS-1))))\n");
+ "(arr[bit/NUMBITS] & ((%s)1 << (bit & (NUMBITS-1))))\n",
+ bitary);
fprintf(fh, "typedef %s bittype;\n", bitary);
/* register class definitions, used by graph-coloring */
@@ -134,16 +201,25 @@
if (q->op == ASSIGN) {
#define F(x) (q->visit & x && q->rewrite & (RLEFT|RRIGHT) && \
q->lshape & ~x && q->rshape & ~x)
- if (F(INAREG) || F(INBREG) || F(INCREG) || F(INDREG)) {
+ if (F(INAREG) || F(INBREG) || F(INCREG) || F(INDREG) ||
+ F(INEREG) || F(INFREG) || F(INGREG)) {
compl(q, "may match without result register");
rval++;
}
#undef F
- if ((q->visit & INREGS) && q->rewrite != RDEST) {
+ if ((q->visit & INREGS) && !(q->rewrite & RDEST)) {
compl(q, "ASSIGN reclaim must be RDEST");
rval++;
}
}
+ /* check that reclaim is not the wrong class */
+ if ((q->rewrite & (RESC1|RESC2|RESC3)) &&
+ !(q->needs & REWRITE)) {
+ if ((q->visit & getrcl(q)) == 0) {
+ compl(q, "wrong RESCx class");
+ rval++;
+ }
+ }
if (q->rewrite & (RESC1|RESC2|RESC3) && q->visit & FOREFF)
compl(q, "FOREFF may cause reclaim of wrong class");
}
@@ -163,23 +239,42 @@
fprintf(fc, "%d, ", i), j++;
fprintf(fc, "-1 };\n");
fprintf(fh, "#define NPERMREG %d\n", j+1);
+ fprintf(fc, "bittype validregs[] = {\n");
+ for (j = 0; j < MAXREGS; j += bitsz) {
+ int cbit = 0;
+ for (i = 0; i < bitsz; i++) {
+ if (i+j == MAXREGS)
+ break;
+ if (rstatus[i+j] & INREGS)
+ cbit |= (1 << i);
+ }
+ fprintf(fc, "\t0x%08x,\n", cbit);
+ }
+ fprintf(fc, "};\n");
+ fprintf(fh, "extern bittype validregs[];\n");
/*
* The register allocator uses bitmasks of registers for each class.
*/
- areg = breg = creg = dreg = 0;
+ areg = breg = creg = dreg = ereg = freg = greg = 0;
for (i = 0; i < MAXREGS; i++) {
- regclassmap[0][i] = regclassmap[1][i] = regclassmap[2][i] =
- regclassmap[3][i] = -1;
+ for (j = 0; j < NUMCLASS; j++)
+ regclassmap[j][i] = -1;
if (rstatus[i] & SAREG) regclassmap[0][i] = areg++;
if (rstatus[i] & SBREG) regclassmap[1][i] = breg++;
if (rstatus[i] & SCREG) regclassmap[2][i] = creg++;
if (rstatus[i] & SDREG) regclassmap[3][i] = dreg++;
+ if (rstatus[i] & SEREG) regclassmap[4][i] = ereg++;
+ if (rstatus[i] & SFREG) regclassmap[5][i] = freg++;
+ if (rstatus[i] & SGREG) regclassmap[6][i] = greg++;
}
fprintf(fh, "#define AREGCNT %d\n", areg);
fprintf(fh, "#define BREGCNT %d\n", breg);
fprintf(fh, "#define CREGCNT %d\n", creg);
fprintf(fh, "#define DREGCNT %d\n", dreg);
+ fprintf(fh, "#define EREGCNT %d\n", ereg);
+ fprintf(fh, "#define FREGCNT %d\n", freg);
+ fprintf(fh, "#define GREGCNT %d\n", greg);
if (areg > bitsz)
printf("%d regs in class A (max %d)\n", areg, bitsz), rval++;
if (breg > bitsz)
@@ -188,15 +283,24 @@
printf("%d regs in class C (max %d)\n", creg, bitsz), rval++;
if (dreg > bitsz)
printf("%d regs in class D (max %d)\n", dreg, bitsz), rval++;
+ if (ereg > bitsz)
+ printf("%d regs in class E (max %d)\n", ereg, bitsz), rval++;
+ if (freg > bitsz)
+ printf("%d regs in class F (max %d)\n", freg, bitsz), rval++;
+ if (greg > bitsz)
+ printf("%d regs in class G (max %d)\n", greg, bitsz), rval++;
fprintf(fc, "static int amap[MAXREGS][NUMCLASS] = {\n");
for (i = 0; i < MAXREGS; i++) {
- int ba, bb, bc, bd, r;
- ba = bb = bc = bd = 0;
+ int ba, bb, bc, bd, r, be, bf, bg;
+ ba = bb = bc = bd = be = bf = bg = 0;
if (rstatus[i] & SAREG) ba = (1 << regclassmap[0][i]);
if (rstatus[i] & SBREG) bb = (1 << regclassmap[1][i]);
if (rstatus[i] & SCREG) bc = (1 << regclassmap[2][i]);
if (rstatus[i] & SDREG) bd = (1 << regclassmap[3][i]);
+ if (rstatus[i] & SEREG) be = (1 << regclassmap[4][i]);
+ if (rstatus[i] & SFREG) bf = (1 << regclassmap[5][i]);
+ if (rstatus[i] & SGREG) bg = (1 << regclassmap[6][i]);
for (j = 0; roverlay[i][j] >= 0; j++) {
r = roverlay[i][j];
if (rstatus[r] & SAREG)
@@ -207,8 +311,21 @@
bc |= (1 << regclassmap[2][r]);
if (rstatus[r] & SDREG)
bd |= (1 << regclassmap[3][r]);
+ if (rstatus[r] & SEREG)
+ be |= (1 << regclassmap[4][r]);
+ if (rstatus[r] & SFREG)
+ bf |= (1 << regclassmap[5][r]);
+ if (rstatus[r] & SGREG)
+ bg |= (1 << regclassmap[6][r]);
}
- fprintf(fc, "\t{ 0x%x,0x%x,0x%x,0x%x },\n", ba, bb, bc, bd);
+ fprintf(fc, "\t/* %d */{ 0x%x", i, ba);
+ if (NUMCLASS > 1) fprintf(fc, ",0x%x", bb);
+ if (NUMCLASS > 2) fprintf(fc, ",0x%x", bc);
+ if (NUMCLASS > 3) fprintf(fc, ",0x%x", bd);
+ if (NUMCLASS > 4) fprintf(fc, ",0x%x", be);
+ if (NUMCLASS > 5) fprintf(fc, ",0x%x", bf);
+ if (NUMCLASS > 6) fprintf(fc, ",0x%x", bg);
+ fprintf(fc, " },\n");
}
fprintf(fc, "};\n");
@@ -221,9 +338,12 @@
if (breg > mx) mx = breg;
if (creg > mx) mx = creg;
if (dreg > mx) mx = dreg;
- if (mx > (sizeof(int)*8)-1) {
- printf("too many regs in a calss, use two classes instead\n");
- printf("%d > %d\n", mx, (sizeof(int)*8)-1);
+ if (ereg > mx) mx = ereg;
+ if (freg > mx) mx = freg;
+ if (greg > mx) mx = greg;
+ 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++;
}
fprintf(fc, "static int rmap[NUMCLASS][%d] = {\n", mx);
@@ -241,13 +361,16 @@
fprintf(fc, " return rmap[class-1][color];\n}\n");
/* used by register allocator */
- fprintf(fc, "int regK[] = { 0, %d, %d, %d, %d };\n",
- areg, breg, creg, dreg);
+ fprintf(fc, "int regK[] = { 0, %d, %d, %d, %d, %d, %d, %d };\n",
+ areg, breg, creg, dreg, ereg, freg, greg);
fprintf(fc, "int\nclassmask(int class)\n{\n");
fprintf(fc, "\tif(class == CLASSA) return 0x%x;\n", (1 << areg)-1);
fprintf(fc, "\tif(class == CLASSB) return 0x%x;\n", (1 << breg)-1);
fprintf(fc, "\tif(class == CLASSC) return 0x%x;\n", (1 << creg)-1);
- fprintf(fc, "\treturn 0x%x;\n}\n", (1 << dreg)-1);
+ fprintf(fc, "\tif(class == CLASSD) return 0x%x;\n", (1 << dreg)-1);
+ fprintf(fc, "\tif(class == CLASSE) return 0x%x;\n", (1 << ereg)-1);
+ fprintf(fc, "\tif(class == CLASSF) return 0x%x;\n", (1 << freg)-1);
+ fprintf(fc, "\treturn 0x%x;\n}\n", (1 << greg)-1);
fprintf(fh, "int interferes(int reg1, int reg2);\n");
nelem = (MAXREGS+bitsz-1)/bitsz;
@@ -270,6 +393,7 @@
fprintf(fc, "int\ninterferes(int reg1, int reg2)\n{\n");
fprintf(fc, "return TESTBIT(ovlarr[reg1], reg2);\n}\n");
fclose(fc);
+ fprintf(fh, "#endif /* _EXTERNAL_H_ */\n");
fclose(fh);
return rval;
}
@@ -291,19 +415,20 @@
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 {
int opmtemp;
if ((opmtemp=mamask[op->op - OPSIMP])&SPFLG) {
if (i==NAME || i==ICON || i==TEMP ||
- i==OREG || i == REG) {
- P((fc, "%td, ", op - table));
+ i==OREG || i == REG || i == FCON) {
+ P((fc, FMTdPTR ", ",
+ op - table));
curalen++;
}
} else if ((dope[i]&(opmtemp|ASGFLG))==opmtemp){
- P((fc, "%td, ", op - table));
+ P((fc, FMTdPTR ", ", op - table));
curalen++;
}
}
Index: optim2.c
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/mip/optim2.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/mip/optim2.c -L usr.bin/pcc/mip/optim2.c -u -r1.1 -r1.2
--- usr.bin/pcc/mip/optim2.c
+++ usr.bin/pcc/mip/optim2.c
@@ -1,4 +1,4 @@
-/* $Id: optim2.c,v 1.44 2006/06/20 06:02:44 ragge Exp $ */
+/* $Id: optim2.c,v 1.62 2008/12/11 21:23:28 pantzer Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson (ragge at ludd.luth.se).
* All rights reserved.
@@ -41,169 +41,48 @@
#define BDEBUG(x) if (b2debug) printf x
+#define mktemp(n, t) mklnode(TEMP, 0, n, t)
+
static int dfsnum;
void saveip(struct interpass *ip);
-void deljumps(struct interpass *);
+void deljumps(struct p2env *);
void optdump(struct interpass *ip);
void printip(struct interpass *pole);
static struct varinfo defsites;
struct interpass *storesave;
-static struct interpass_prolog *ipp, *epp; /* prolog/epilog */
-void bblocks_build(struct interpass *, struct labelinfo *, struct bblockinfo *);
-void cfg_build(struct labelinfo *labinfo);
+void bblocks_build(struct p2env *, struct labelinfo *, struct bblockinfo *);
+void cfg_build(struct p2env *, struct labelinfo *labinfo);
void cfg_dfs(struct basicblock *bb, unsigned int parent,
struct bblockinfo *bbinfo);
-void dominators(struct bblockinfo *bbinfo);
+void dominators(struct p2env *, struct bblockinfo *bbinfo);
struct basicblock *
ancestorwithlowestsemi(struct basicblock *bblock, struct bblockinfo *bbinfo);
void link(struct basicblock *parent, struct basicblock *child);
void computeDF(struct basicblock *bblock, struct bblockinfo *bbinfo);
+void printDF(struct p2env *p2e, struct bblockinfo *bbinfo);
void findTemps(struct interpass *ip);
-void placePhiFunctions(struct bblockinfo *bbinfo);
-void remunreach(void);
-
-struct basicblock bblocks;
-int nbblocks;
-static struct interpass *cvpole;
-
-struct addrof {
- struct addrof *next;
- int tempnum;
- int oregoff;
-} *otlink;
-
-static int
-getoff(int num)
-{
- struct addrof *w;
-
- for (w = otlink; w; w = w->next)
- if (w->tempnum == num)
- return w->oregoff;
- return 0;
-}
-
-/*
- * Use stack argument addresses instead of copying if & is used on a var.
- */
-static int
-setargs(int tval, struct addrof *w)
-{
- struct interpass *ip;
- NODE *p;
-
- ip = DLIST_NEXT(cvpole, qelem); /* PROLOG */
- ip = DLIST_NEXT(ip, qelem); /* first DEFLAB */
- ip = DLIST_NEXT(ip, qelem); /* first NODE */
- for (; ip->type != IP_DEFLAB; ip = DLIST_NEXT(ip, qelem)) {
- p = ip->ip_node;
-#ifdef PCC_DEBUG
- if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
- comperr("temparg");
-#endif
- if (p->n_right->n_op != OREG)
- continue; /* arg in register */
- if (tval != p->n_left->n_lval)
- continue; /* wrong assign */
- w->oregoff = p->n_right->n_lval;
- tfree(p);
- DLIST_REMOVE(ip, qelem);
- return 1;
- }
- return 0;
-}
-
-/*
- * Search for ADDROF elements and, if found, record them.
- */
-static void
-findaddrof(NODE *p)
-{
- struct addrof *w;
-
- if (p->n_op != ADDROF)
- return;
- if (getoff(p->n_left->n_lval))
- return;
- w = tmpalloc(sizeof(struct addrof));
- w->tempnum = p->n_left->n_lval;
- if (setargs(p->n_left->n_lval, w) == 0)
- w->oregoff = BITOOR(freetemp(szty(p->n_left->n_type)));
- w->next = otlink;
- otlink = w;
-}
-
-
-/*
- * Convert address-taken temps to OREGs.
- */
-static void
-cvtaddrof(NODE *p)
-{
- NODE *l;
- int n;
-
- if (p->n_op != ADDROF && p->n_op != TEMP)
- return;
- if (p->n_op == TEMP) {
- n = getoff(p->n_lval);
- if (n == 0)
- return;
- p->n_op = OREG;
- p->n_lval = n;
- p->n_rval = FPREG;
- } else {
- l = p->n_left;
- l->n_type = p->n_type;
- p->n_right = mklnode(ICON, l->n_lval, 0, l->n_type);
- p->n_op = PLUS;
- l->n_op = REG;
- l->n_lval = 0;
- l->n_rval = FPREG;
-
- }
-}
+void placePhiFunctions(struct p2env *, struct bblockinfo *bbinfo);
+void renamevar(struct p2env *p2e,struct basicblock *bblock, struct bblockinfo *bbinfo);
+void removephi(struct p2env *p2e, struct labelinfo *,struct bblockinfo *bbinfo);
+void remunreach(struct p2env *);
void
-optimize(struct interpass *ipole)
+optimize(struct p2env *p2e)
{
- struct interpass *ip;
+ struct interpass *ipole = &p2e->ipole;
struct labelinfo labinfo;
struct bblockinfo bbinfo;
- ipp = (struct interpass_prolog *)DLIST_NEXT(ipole, qelem);
- epp = (struct interpass_prolog *)DLIST_PREV(ipole, qelem);
-
if (b2debug) {
printf("initial links\n");
printip(ipole);
}
- /*
- * Convert ADDROF TEMP to OREGs.
- */
- if (xtemps) {
- otlink = NULL;
- cvpole = ipole;
- DLIST_FOREACH(ip, ipole, qelem) {
- if (ip->type != IP_NODE)
- continue;
- walkf(ip->ip_node, findaddrof);
- }
- if (otlink) {
- DLIST_FOREACH(ip, ipole, qelem) {
- if (ip->type != IP_NODE)
- continue;
- walkf(ip->ip_node, cvtaddrof);
- }
- }
- }
-
if (xdeljumps)
- deljumps(ipole); /* Delete redundant jumps and dead code */
+ deljumps(p2e); /* Delete redundant jumps and dead code */
#ifdef PCC_DEBUG
if (b2debug) {
@@ -212,32 +91,64 @@
}
#endif
if (xssaflag || xtemps) {
- DLIST_INIT(&bblocks, bbelem);
- bblocks_build(ipole, &labinfo, &bbinfo);
+ DLIST_INIT(&p2e->bblocks, bbelem);
+ bblocks_build(p2e, &labinfo, &bbinfo);
BDEBUG(("Calling cfg_build\n"));
- cfg_build(&labinfo);
+ cfg_build(p2e, &labinfo);
}
if (xssaflag) {
BDEBUG(("Calling dominators\n"));
- dominators(&bbinfo);
+ dominators(p2e, &bbinfo);
BDEBUG(("Calling computeDF\n"));
- computeDF(DLIST_NEXT(&bblocks, bbelem), &bbinfo);
+ computeDF(DLIST_NEXT(&p2e->bblocks, bbelem), &bbinfo);
+
+ if (b2debug) {
+ printDF(p2e,&bbinfo);
+ }
+
+ BDEBUG(("Calling placePhiFunctions\n"));
+
+ placePhiFunctions(p2e, &bbinfo);
+
+ BDEBUG(("Calling renamevar\n"));
+
+ renamevar(p2e,DLIST_NEXT(&p2e->bblocks, bbelem), &bbinfo);
+
+ BDEBUG(("Calling removephi\n"));
+
+ removephi(p2e,&labinfo,&bbinfo);
+
BDEBUG(("Calling remunreach\n"));
- remunreach();
-#if 0
- dfg = dfg_build(cfg);
- ssa = ssa_build(cfg, dfg);
+ remunreach(p2e);
+
+ /*
+ Recalculate basic blocks and cfg that was destroyed
+ by removephi
+ */
+
+ DLIST_INIT(&p2e->bblocks, bbelem);
+ bblocks_build(p2e, &labinfo, &bbinfo);
+ BDEBUG(("Calling cfg_build\n"));
+ cfg_build(p2e, &labinfo);
+
+#ifdef PCC_DEBUG
+ if (b2debug) {
+ printf("new tree\n");
+ printip(ipole);
+ }
#endif
}
#ifdef PCC_DEBUG
- if (epp->ipp_regs != 0)
- comperr("register error");
+ {
+ int i;
+ for (i = NIPPREGS; i--; )
+ if (p2e->epp->ipp_regs[i] != 0)
+ comperr("register error");
+ }
#endif
-#ifdef MYOPTIM
- myoptim((struct interpass *)ipp);
-#endif
+ myoptim(ipole);
}
/*
@@ -245,14 +156,18 @@
* This routine can be made much more efficient.
*/
void
-deljumps(struct interpass *ipole)
+deljumps(struct p2env *p2e)
{
- struct interpass *ip, *n, *ip2;
+ struct interpass *ipole = &p2e->ipole;
+ struct interpass *ip, *n, *ip2, *start;
int gotone,low, high;
- int *lblary, sz, o, i;
+ int *lblary, *jmpary, sz, o, i, j, lab1, lab2;
+ int del;
+ extern int negrel[];
+ extern size_t negrelsize;
- low = ipp->ip_lblnum;
- high = epp->ip_lblnum;
+ low = p2e->ipp->ip_lblnum;
+ high = p2e->epp->ip_lblnum;
#ifdef notyet
mark = tmpmark(); /* temporary used memory */
@@ -260,18 +175,64 @@
sz = (high-low) * sizeof(int);
lblary = tmpalloc(sz);
+ jmpary = tmpalloc(sz);
+
+ /*
+ * XXX: Find the first two labels. They may not be deleted,
+ * because the register allocator expects them to be there.
+ * These will not be coalesced with any other label.
+ */
+ lab1 = lab2 = -1;
+ start = NULL;
+ DLIST_FOREACH(ip, ipole, qelem) {
+ if (ip->type != IP_DEFLAB)
+ continue;
+ if (lab1 < 0)
+ lab1 = ip->ip_lbl;
+ else if (lab2 < 0) {
+ lab2 = ip->ip_lbl;
+ start = ip;
+ } else /* lab1 >= 0 && lab2 >= 0, we're done. */
+ break;
+ }
+ if (lab1 < 0 || lab2 < 0)
+ comperr("deljumps");
again: gotone = 0;
memset(lblary, 0, sz);
+ lblary[lab1 - low] = lblary[lab2 - low] = 1;
+ memset(jmpary, 0, sz);
/* refcount and coalesce all labels */
DLIST_FOREACH(ip, ipole, qelem) {
- if (ip->type == IP_DEFLAB) {
+ if (ip->type == IP_DEFLAB && ip->ip_lbl != lab1 &&
+ ip->ip_lbl != lab2) {
n = DLIST_NEXT(ip, qelem);
+
+ /*
+ * Find unconditional jumps directly following a
+ * label. Jumps jumping to themselves are not
+ * taken into account.
+ */
+ if (n->type == IP_NODE && n->ip_node->n_op == GOTO) {
+ i = n->ip_node->n_left->n_lval;
+ if (i != ip->ip_lbl)
+ jmpary[ip->ip_lbl - low] = i;
+ }
+
while (n->type == IP_DEFLAB) {
- if (n->type == IP_DEFLAB &&
- lblary[n->ip_lbl-low] >= 0)
- lblary[n->ip_lbl-low] = -ip->ip_lbl;
+ if (n->ip_lbl != lab1 && n->ip_lbl != lab2 &&
+ lblary[n->ip_lbl-low] >= 0) {
+ /*
+ * If the label is used, mark the
+ * label to be coalesced with as
+ * used, too.
+ */
+ if (lblary[n->ip_lbl - low] > 0 &&
+ lblary[ip->ip_lbl - low] == 0)
+ lblary[ip->ip_lbl - low] = 1;
+ lblary[n->ip_lbl - low] = -ip->ip_lbl;
+ }
n = DLIST_NEXT(n, qelem);
}
}
@@ -284,7 +245,15 @@
i = ip->ip_node->n_right->n_lval;
else
continue;
- lblary[i-low] |= 1;
+
+ /*
+ * Mark destination label i as used, if it is not already.
+ * If i is to be merged with label j, mark j as used, too.
+ */
+ if (lblary[i - low] == 0)
+ lblary[i-low] = 1;
+ else if ((j = lblary[i - low]) < 0 && lblary[-j - low] == 0)
+ lblary[-j - low] = 1;
}
/* delete coalesced/unused labels and rename gotos */
@@ -295,22 +264,33 @@
DLIST_REMOVE(n, qelem);
gotone = 1;
}
- continue;
}
- if (n->type != IP_NODE)
+ if (ip->type != IP_NODE)
continue;
- o = n->ip_node->n_op;
+ o = ip->ip_node->n_op;
if (o == GOTO)
- i = n->ip_node->n_left->n_lval;
+ i = ip->ip_node->n_left->n_lval;
else if (o == CBRANCH)
- i = n->ip_node->n_right->n_lval;
+ i = ip->ip_node->n_right->n_lval;
else
continue;
+
+ /* Simplify (un-)conditional jumps to unconditional jumps. */
+ if (jmpary[i - low] > 0) {
+ gotone = 1;
+ i = jmpary[i - low];
+ if (o == GOTO)
+ ip->ip_node->n_left->n_lval = i;
+ else
+ ip->ip_node->n_right->n_lval = i;
+ }
+
+ /* Fixup for coalesced labels. */
if (lblary[i-low] < 0) {
if (o == GOTO)
- n->ip_node->n_left->n_lval = -lblary[i-low];
+ ip->ip_node->n_left->n_lval = -lblary[i-low];
else
- n->ip_node->n_right->n_lval = -lblary[i-low];
+ ip->ip_node->n_right->n_lval = -lblary[i-low];
}
}
@@ -332,13 +312,61 @@
if (ip2->type != IP_DEFLAB)
continue;
- if (ip2->ip_lbl == i) {
+ if (ip2->ip_lbl == i && i != lab1 && i != lab2) {
tfree(n->ip_node);
DLIST_REMOVE(n, qelem);
gotone = 1;
}
}
+ /*
+ * Transform cbranch cond, 1; goto 2; 1: ... into
+ * cbranch !cond, 2; 1: ...
+ */
+ DLIST_FOREACH(ip, ipole, qelem) {
+ n = DLIST_NEXT(ip, qelem);
+ ip2 = DLIST_NEXT(n, qelem);
+ if (ip->type != IP_NODE || ip->ip_node->n_op != CBRANCH)
+ continue;
+ if (n->type != IP_NODE || n->ip_node->n_op != GOTO)
+ continue;
+ if (ip2->type != IP_DEFLAB)
+ continue;
+ i = ip->ip_node->n_right->n_lval;
+ j = n->ip_node->n_left->n_lval;
+ if (j == lab1 || j == lab2)
+ continue;
+ if (i != ip2->ip_lbl || i == lab1 || i == lab2)
+ continue;
+ ip->ip_node->n_right->n_lval = j;
+ i = ip->ip_node->n_left->n_op;
+ 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);
+ DLIST_REMOVE(n, qelem);
+ gotone = 1;
+ }
+
+ /* Delete everything after a goto up to the next label. */
+ for (ip = start, del = 0; ip != DLIST_ENDMARK(ipole);
+ ip = DLIST_NEXT(ip, qelem)) {
+loop:
+ if ((n = DLIST_NEXT(ip, qelem)) == DLIST_ENDMARK(ipole))
+ break;
+ if (n->type != IP_NODE) {
+ del = 0;
+ continue;
+ }
+ if (del) {
+ tfree(n->ip_node);
+ DLIST_REMOVE(n, qelem);
+ gotone = 1;
+ goto loop;
+ } else if (n->ip_node->n_op == GOTO)
+ del = 1;
+ }
+
if (gotone)
goto again;
@@ -355,7 +383,9 @@
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);
@@ -374,9 +404,10 @@
*/
void
-bblocks_build(struct interpass *ipole, struct labelinfo *labinfo,
+bblocks_build(struct p2env *p2e, struct labelinfo *labinfo,
struct bblockinfo *bbinfo)
{
+ struct interpass *ipole = &p2e->ipole;
struct interpass *ip;
struct basicblock *bb = NULL;
int low, high;
@@ -384,8 +415,8 @@
int i;
BDEBUG(("bblocks_build (%p, %p)\n", labinfo, bbinfo));
- low = ipp->ip_lblnum;
- high = epp->ip_lblnum;
+ low = p2e->ipp->ip_lblnum;
+ high = p2e->epp->ip_lblnum;
/*
* First statement is a leader.
@@ -410,8 +441,9 @@
bb->dfchildren = NULL;
bb->Aorig = NULL;
bb->Aphi = NULL;
+ SLIST_INIT(&bb->phi);
bb->bbnum = count;
- DLIST_INSERT_BEFORE(&bblocks, bb, bbelem);
+ DLIST_INSERT_BEFORE(&p2e->bblocks, bb, bbelem);
count++;
}
bb->last = ip;
@@ -421,12 +453,12 @@
if (ip->type == IP_PROLOG)
bb = NULL;
}
- nbblocks = count;
+ p2e->nbblocks = count;
if (b2debug) {
printf("Basic blocks in func: %d, low %d, high %d\n",
count, low, high);
- DLIST_FOREACH(bb, &bblocks, bbelem) {
+ DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
printf("bb %p: first %p last %p\n", bb,
bb->first, bb->last);
}
@@ -446,7 +478,7 @@
}
/* Build the label table */
- DLIST_FOREACH(bb, &bblocks, bbelem) {
+ DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
if (bb->first->type == IP_DEFLAB)
labinfo->arr[bb->first->ip_lbl - low] = bb;
}
@@ -465,14 +497,14 @@
*/
void
-cfg_build(struct labelinfo *labinfo)
+cfg_build(struct p2env *p2e, struct labelinfo *labinfo)
{
/* Child and parent nodes */
struct cfgnode *cnode;
struct cfgnode *pnode;
struct basicblock *bb;
- DLIST_FOREACH(bb, &bblocks, bbelem) {
+ DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
if (bb->first->type == IP_EPILOG) {
break;
@@ -483,7 +515,8 @@
pnode->bblock = bb;
if ((bb->last->type == IP_NODE) &&
- (bb->last->ip_node->n_op == GOTO)) {
+ (bb->last->ip_node->n_op == GOTO) &&
+ (bb->last->ip_node->n_left->n_op == ICON)) {
if (bb->last->ip_node->n_left->n_lval - labinfo->low >
labinfo->size) {
comperr("Label out of range: %d, base %d",
@@ -550,27 +583,27 @@
*/
void
-dominators(struct bblockinfo *bbinfo)
+dominators(struct p2env *p2e, struct bblockinfo *bbinfo)
{
struct cfgnode *cnode;
struct basicblock *bb, *y, *v;
struct basicblock *s, *sprime, *p;
int h, i;
- DLIST_FOREACH(bb, &bblocks, bbelem) {
+ DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
bb->bucket = setalloc(bbinfo->size);
bb->df = setalloc(bbinfo->size);
bb->dfchildren = setalloc(bbinfo->size);
}
dfsnum = 0;
- cfg_dfs(DLIST_NEXT(&bblocks, bbelem), 0, bbinfo);
+ cfg_dfs(DLIST_NEXT(&p2e->bblocks, bbelem), 0, bbinfo);
if (b2debug) {
struct basicblock *bbb;
struct cfgnode *ccnode;
- DLIST_FOREACH(bbb, &bblocks, bbelem) {
+ DLIST_FOREACH(bbb, &p2e->bblocks, bbelem) {
printf("Basic block %d, parents: ", bbb->dfnum);
SLIST_FOREACH(ccnode, &bbb->parents, cfgelem) {
printf("%d, ", ccnode->bblock->dfnum);
@@ -587,6 +620,9 @@
bb = bbinfo->arr[h];
p = s = bbinfo->arr[bb->dfparent];
SLIST_FOREACH(cnode, &bb->parents, cfgelem) {
+ if (cnode->bblock->dfnum ==0)
+ continue; /* Ignore unreachable code */
+
if (cnode->bblock->dfnum <= bb->dfnum)
sprime = cnode->bblock;
else
@@ -613,7 +649,7 @@
if (b2debug) {
printf("Num\tSemi\tAncest\tidom\n");
- DLIST_FOREACH(bb, &bblocks, bbelem) {
+ DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
printf("%d\t%d\t%d\t%d\n", bb->dfnum, bb->semi,
bb->ancestor, bb->idom);
}
@@ -625,7 +661,7 @@
bb->idom = bbinfo->arr[bb->samedom]->idom;
}
}
- DLIST_FOREACH(bb, &bblocks, bbelem) {
+ DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
if (bb->idom != 0 && bb->idom != bb->dfnum) {
BDEBUG(("Setting child %d of %d\n",
bb->dfnum, bbinfo->arr[bb->idom]->dfnum));
@@ -672,36 +708,70 @@
computeDF(bbinfo->arr[h], bbinfo);
for (i = 1; i < bbinfo->size; i++) {
if (TESTBIT(bbinfo->arr[h]->df, i) &&
- (bbinfo->arr[h] == bblock ||
- (bblock->idom != bbinfo->arr[h]->dfnum)))
+ (bbinfo->arr[i] == bblock ||
+ (bblock->dfnum != bbinfo->arr[i]->idom)))
BITSET(bblock->df, i);
}
}
}
+void printDF(struct p2env *p2e, struct bblockinfo *bbinfo)
+{
+ struct basicblock *bb;
+ int i;
+
+ printf("Dominance frontiers:\n");
+
+ DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
+ printf("bb %d : ", bb->dfnum);
+
+ for (i=1; i < bbinfo->size;i++) {
+ if (TESTBIT(bb->df,i)) {
+ printf("%d ",i);
+ }
+ }
+
+ printf("\n");
+ }
+
+}
+
+
+
static struct basicblock *currbb;
static struct interpass *currip;
/* Helper function for findTemps, Find assignment nodes. */
static void
-searchasg(NODE *p)
+searchasg(NODE *p, void *arg)
{
struct pvarinfo *pv;
-
+ int tempnr;
+ struct varstack *stacke;
+
if (p->n_op != ASSIGN)
return;
if (p->n_left->n_op != TEMP)
return;
+ tempnr=regno(p->n_left)-defsites.low;
+
+ BITSET(currbb->Aorig, tempnr);
+
pv = tmpcalloc(sizeof(struct pvarinfo));
- pv->next = defsites.arr[p->n_left->n_lval];
+ pv->next = defsites.arr[tempnr];
pv->bb = currbb;
- pv->top = currip->ip_node;
- pv->n = p->n_left;
- BITSET(currbb->Aorig, p->n_left->n_lval);
-
- defsites.arr[p->n_left->n_lval] = pv;
+ pv->n_type = p->n_left->n_type;
+
+ defsites.arr[tempnr] = pv;
+
+
+ if (SLIST_FIRST(&defsites.stack[tempnr])==NULL) {
+ stacke=tmpcalloc(sizeof (struct varstack));
+ stacke->tmpregno=0;
+ SLIST_INSERT_FIRST(&defsites.stack[tempnr],stacke,varstackelem);
+ }
}
/* Walk the interpass looking for assignment nodes. */
@@ -712,7 +782,7 @@
currip = ip;
- walkf(ip->ip_node, searchasg);
+ walkf(ip->ip_node, searchasg, 0);
}
/*
@@ -720,32 +790,37 @@
*/
void
-placePhiFunctions(struct bblockinfo *bbinfo)
+placePhiFunctions(struct p2env *p2e, struct bblockinfo *bbinfo)
{
struct basicblock *bb;
+ struct basicblock *y;
struct interpass *ip;
- int maxtmp, i, j, k, l;
+ int maxtmp, i, j, k;
struct pvarinfo *n;
struct cfgnode *cnode;
TWORD ntype;
- NODE *p;
struct pvarinfo *pv;
+ struct phiinfo *phi;
+ int phifound;
- bb = DLIST_NEXT(&bblocks, bbelem);
+ bb = DLIST_NEXT(&p2e->bblocks, bbelem);
defsites.low = ((struct interpass_prolog *)bb->first)->ip_tmpnum;
- bb = DLIST_PREV(&bblocks, bbelem);
+ bb = DLIST_PREV(&p2e->bblocks, bbelem);
maxtmp = ((struct interpass_prolog *)bb->first)->ip_tmpnum;
defsites.size = maxtmp - defsites.low + 1;
defsites.arr = tmpcalloc(defsites.size*sizeof(struct pvarinfo *));
-
+ defsites.stack = tmpcalloc(defsites.size*sizeof(SLIST_HEAD(, varstack)));
+
+ for (i=0;i<defsites.size;i++)
+ SLIST_INIT(&defsites.stack[i]);
+
/* Find all defsites */
- DLIST_FOREACH(bb, &bblocks, bbelem) {
+ DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
currbb = bb;
ip = bb->first;
bb->Aorig = setalloc(defsites.size);
bb->Aphi = setalloc(defsites.size);
-
while (ip != bb->last) {
findTemps(ip);
ip = DLIST_NEXT(ip, qelem);
@@ -753,8 +828,9 @@
/* Make sure we get the last statement in the bblock */
findTemps(ip);
}
+
/* For each variable */
- for (i = defsites.low; i < defsites.size; i++) {
+ for (i = 0; i < defsites.size; i++) {
/* While W not empty */
while (defsites.arr[i] != NULL) {
/* Remove some node n from W */
@@ -768,27 +844,45 @@
if (TESTBIT(bbinfo->arr[j]->Aphi, i))
continue;
- ntype = n->n->n_type;
+ y=bbinfo->arr[j];
+ ntype = n->n_type;
k = 0;
/* Amount of predecessors for y */
- SLIST_FOREACH(cnode, &n->bb->parents, cfgelem)
+ SLIST_FOREACH(cnode, &y->parents, cfgelem)
k++;
- /* Construct phi(...) */
- p = mklnode(TEMP, i, 0, ntype);
- for (l = 0; l < k-1; l++)
- p = mkbinode(PHI, p,
- mklnode(TEMP, i, 0, ntype), ntype);
- ip = ipnode(mkbinode(ASSIGN,
- mklnode(TEMP, i, 0, ntype), p, ntype));
- /* Insert phi at top of basic block */
- DLIST_INSERT_BEFORE(((struct interpass*)&n->bb->first), ip, qelem);
- n->bb->first = ip;
+ /* Construct phi(...)
+ */
+
+ phifound=0;
+
+ SLIST_FOREACH(phi, &y->phi, phielem) {
+ if (phi->tmpregno==i+defsites.low)
+ phifound++;
+ }
+
+ if (phifound==0) {
+ if (b2debug)
+ printf("Phi in %d (%p) for %d\n",y->dfnum,y,i+defsites.low);
+
+ phi = tmpcalloc(sizeof(struct phiinfo));
+
+ phi->tmpregno=i+defsites.low;
+ phi->size=k;
+ phi->n_type=ntype;
+ phi->intmpregno=tmpcalloc(k*sizeof(int));
+
+ SLIST_INSERT_LAST(&y->phi,phi,phielem);
+ } else {
+ if (b2debug)
+ printf("Phi already in %d for %d\n",y->dfnum,i+defsites.low);
+ }
+
BITSET(bbinfo->arr[j]->Aphi, i);
if (!TESTBIT(bbinfo->arr[j]->Aorig, i)) {
pv = tmpalloc(sizeof(struct pvarinfo));
- // XXXpj Ej fullständig information.
- pv->bb = bbinfo->arr[j];
- pv->next = defsites.arr[i]->next;
+ pv->bb = y;
+ pv->n_type=ntype;
+ pv->next = defsites.arr[i];
defsites.arr[i] = pv;
}
@@ -798,18 +892,232 @@
}
}
+/* Helper function for renamevar. */
+static void
+renamevarhelper(struct p2env *p2e,NODE *t,void *poplistarg)
+{
+ SLIST_HEAD(, varstack) *poplist=poplistarg;
+ int opty;
+ int tempnr;
+ int newtempnr;
+ int x;
+ struct varstack *stacke;
+
+ if (t->n_op == ASSIGN && t->n_left->n_op == TEMP) {
+ renamevarhelper(p2e,t->n_right,poplist);
+
+ tempnr=regno(t->n_left)-defsites.low;
+
+ newtempnr=p2e->epp->ip_tmpnum++;
+ regno(t->n_left)=newtempnr;
+
+ stacke=tmpcalloc(sizeof (struct varstack));
+ stacke->tmpregno=newtempnr;
+ SLIST_INSERT_FIRST(&defsites.stack[tempnr],stacke,varstackelem);
+
+ stacke=tmpcalloc(sizeof (struct varstack));
+ stacke->tmpregno=tempnr;
+ SLIST_INSERT_FIRST(poplist,stacke,varstackelem);
+ } else {
+ if (t->n_op == TEMP) {
+ tempnr=regno(t)-defsites.low;
+
+ x=SLIST_FIRST(&defsites.stack[tempnr])->tmpregno;
+ regno(t)=x;
+ }
+
+ opty = optype(t->n_op);
+
+ if (opty != LTYPE)
+ renamevarhelper(p2e, t->n_left,poplist);
+ if (opty == BITYPE)
+ renamevarhelper(p2e, t->n_right,poplist);
+ }
+}
+
+
+void
+renamevar(struct p2env *p2e,struct basicblock *bb, struct bblockinfo *bbinfo)
+{
+ struct interpass *ip;
+ int h,j;
+ SLIST_HEAD(, varstack) poplist;
+ struct varstack *stacke;
+ struct cfgnode *cfgn;
+ struct cfgnode *cfgn2;
+ int tmpregno,newtmpregno;
+ struct phiinfo *phi;
+
+ SLIST_INIT(&poplist);
+
+ SLIST_FOREACH(phi,&bb->phi,phielem) {
+ tmpregno=phi->tmpregno-defsites.low;
+
+ newtmpregno=p2e->epp->ip_tmpnum++;
+ phi->newtmpregno=newtmpregno;
+
+ stacke=tmpcalloc(sizeof (struct varstack));
+ stacke->tmpregno=newtmpregno;
+ SLIST_INSERT_FIRST(&defsites.stack[tmpregno],stacke,varstackelem);
+
+ stacke=tmpcalloc(sizeof (struct varstack));
+ stacke->tmpregno=tmpregno;
+ SLIST_INSERT_FIRST(&poplist,stacke,varstackelem);
+ }
+
+
+ ip=bb->first;
+
+ while (1) {
+ if ( ip->type == IP_NODE) {
+ renamevarhelper(p2e,ip->ip_node,&poplist);
+ }
+
+ if (ip==bb->last)
+ break;
+
+ ip = DLIST_NEXT(ip, qelem);
+ }
+
+ SLIST_FOREACH(cfgn,&bb->children,cfgelem) {
+ j=0;
+
+ SLIST_FOREACH(cfgn2, &cfgn->bblock->parents, cfgelem) {
+ if (cfgn2->bblock->dfnum==bb->dfnum)
+ break;
+
+ j++;
+ }
+
+ SLIST_FOREACH(phi,&cfgn->bblock->phi,phielem) {
+ phi->intmpregno[j]=SLIST_FIRST(&defsites.stack[phi->tmpregno-defsites.low])->tmpregno;
+ }
+
+ }
+
+ for (h = 1; h < bbinfo->size; h++) {
+ if (!TESTBIT(bb->dfchildren, h))
+ continue;
+
+ renamevar(p2e,bbinfo->arr[h], bbinfo);
+ }
+
+ SLIST_FOREACH(stacke,&poplist,varstackelem) {
+ tmpregno=stacke->tmpregno;
+
+ defsites.stack[tmpregno].q_forw=defsites.stack[tmpregno].q_forw->varstackelem.q_forw;
+ }
+}
+
+void
+removephi(struct p2env *p2e, struct labelinfo *labinfo,struct bblockinfo *bbinfo)
+{
+ struct basicblock *bb,*bbparent;
+ struct cfgnode *cfgn;
+ struct phiinfo *phi;
+ int i;
+ struct interpass *ip;
+ struct interpass *pip;
+ TWORD n_type;
+ int complex;
+ int label=0;
+ int newlabel;
+
+ DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
+ SLIST_FOREACH(phi,&bb->phi,phielem) { // Look at only one, notice break at end
+ i=0;
+
+ SLIST_FOREACH(cfgn, &bb->parents, cfgelem) {
+ bbparent=cfgn->bblock;
+
+ pip=bbparent->last;
+
+ complex = 0;
+
+ BDEBUG(("removephi: %p in %d",pip,bb->dfnum));
+ if (pip->type == IP_NODE && pip->ip_node->n_op == GOTO) {
+ BDEBUG((" GOTO "));
+ label=pip->ip_node->n_left->n_lval;
+ complex=1;
+ } else if (pip->type == IP_NODE && pip->ip_node->n_op == CBRANCH) {
+ BDEBUG((" CBRANCH "));
+ label=pip->ip_node->n_right->n_lval;
+
+ if (bb==labinfo->arr[label - p2e->ipp->ip_lblnum])
+ complex=2;
+ }
+
+ BDEBUG((" Complex: %d\n",complex));
+
+ if (complex > 0) {
+ /*
+ This destroys basic block calculations.
+ Maybe it shoud not
+ */
+ ip = ipnode(mkunode(GOTO, mklnode(ICON, label, 0, INT), 0, INT));
+ DLIST_INSERT_BEFORE((bb->first), ip, qelem);
+
+ newlabel=getlab2();
+
+ ip = tmpalloc(sizeof(struct interpass));
+ ip->type = IP_DEFLAB;
+ // Line number?? ip->lineno;
+ ip->ip_lbl = newlabel;
+ DLIST_INSERT_BEFORE((bb->first), ip, qelem);
+
+ SLIST_FOREACH(phi,&bb->phi,phielem) {
+ if (phi->intmpregno[i]>0) {
+ n_type=phi->n_type;
+ ip = ipnode(mkbinode(ASSIGN,
+ mktemp(phi->newtmpregno, n_type),
+ mktemp(phi->intmpregno[i],n_type),
+ n_type));
+
+ DLIST_INSERT_BEFORE((bb->first), ip, qelem);
+ }
+ }
+
+ if (complex==1)
+ pip->ip_node->n_left->n_lval=newlabel;
+
+ if (complex==2)
+ pip->ip_node->n_right->n_lval=newlabel;
+
+ } else {
+ /* Construct move */
+ SLIST_FOREACH(phi,&bb->phi,phielem) {
+ if (phi->intmpregno[i]>0) {
+ n_type=phi->n_type;
+ ip = ipnode(mkbinode(ASSIGN,
+ mktemp(phi->newtmpregno, n_type),
+ mktemp(phi->intmpregno[i],n_type),
+ n_type));
+
+ /* Insert move at bottom of parent basic block */
+ DLIST_INSERT_AFTER((bbparent->last), ip, qelem);
+ }
+ }
+ }
+ i++;
+ }
+ break;
+ }
+ }
+}
+
+
/*
* Remove unreachable nodes in the CFG.
*/
void
-remunreach(void)
+remunreach(struct p2env *p2e)
{
struct basicblock *bb, *nbb;
struct interpass *next, *ctree;
- bb = DLIST_NEXT(&bblocks, bbelem);
- while (bb != &bblocks) {
+ bb = DLIST_NEXT(&p2e->bblocks, bbelem);
+ while (bb != &p2e->bblocks) {
nbb = DLIST_NEXT(bb, bbelem);
/* Code with dfnum 0 is unreachable */
@@ -848,7 +1156,8 @@
static char *foo[] = {
0, "NODE", "PROLOG", "STKOFF", "EPILOG", "DEFLAB", "DEFNAM", "ASM" };
struct interpass *ip;
- struct interpass_prolog *ipp, *epp;
+ struct interpass_prolog *ipplg, *epplg;
+ unsigned i;
DLIST_FOREACH(ip, pole, qelem) {
if (ip->type > MAXIP)
@@ -857,20 +1166,28 @@
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;
- 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 = (struct interpass_prolog *)ip;
+ printf("%s %s regs",
+ ipplg->ipp_name, ipplg->ipp_vis ? "(local)" : "");
+ for (i = 0; i < NIPPREGS; i++)
+ printf("%s0x%x", i? ":" : " ",
+ ipplg->ipp_regs[i]);
+ printf(" autos %d mintemp %d minlbl %d\n",
+ ipplg->ipp_autos, ipplg->ip_tmpnum, ipplg->ip_lblnum);
break;
case IP_EPILOG:
- epp = (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 = (struct interpass_prolog *)ip;
+ printf("%s %s regs",
+ epplg->ipp_name, epplg->ipp_vis ? "(local)" : "");
+ for (i = 0; i < NIPPREGS; i++)
+ printf("%s0x%x", i? ":" : " ",
+ epplg->ipp_regs[i]);
+ printf(" autos %d mintemp %d minlbl %d\n",
+ 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;
Index: protos.h
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/mip/protos.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/mip/protos.h -L usr.bin/pcc/mip/protos.h -u -r1.1 -r1.2
--- usr.bin/pcc/mip/protos.h
+++ usr.bin/pcc/mip/protos.h
@@ -1,24 +1,9 @@
-struct optab;
-struct symtab;
-struct sw;
-
-void cerror(char *s, ...);
-void werror(char *s, ...);
-void uerror(char *s, ...);
-void reclaim(NODE *p, int, int);
-void walkf(NODE *, void (*f)(NODE *));
-void allchk(void);
-void tfree(NODE *);
int tshape(NODE *, int);
-void prtdcon(NODE *p);
-void tinit(void);
void tcheck(void);
void mkdope(void);
-int tshape(NODE *p, int shape);
int shtemp(NODE *p);
int flshape(NODE *p);
-int shumul(NODE *p);
int ttype(TWORD t, int tword);
void expand(NODE *, int, char *);
void hopcode(int, int);
@@ -26,58 +11,29 @@
void zzzcode(NODE *, int);
void insput(NODE *);
void upput(NODE *, int);
-void econvert(NODE *);
int andable(NODE *);
int conval(NODE *, int, NODE *);
int ispow2(CONSZ);
void defid(NODE *q, int class);
-int getlab(void);
void ftnend(void);
void efcode(void);
void dclargs(void);
-void fixarg(struct symtab *);
void cendarg(void);
-void defalign(int);
int fldal(unsigned int);
-void vfdzero(int);
-void zecode(int);
-void putbyte(int v);
+int fldexpand(NODE *, int, char **);
void ecomp(NODE *p);
-void cinit(NODE *, int);
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);
-int fixclass(int, TWORD type);
-void lineid(int, char *);
-void mycanon(NODE *);
-void delay(NODE *);
-int delay1(NODE *);
-void delay2(NODE *);
void setregs(void);
-int autoincr(NODE *);
-int deltest(NODE *);
-void canon(NODE *);
-void order(NODE *, int);
int tlen(NODE *p);
-int setincr(NODE *);
int setbin(NODE *);
-void stoarg(NODE *p, int);
-void constore(NODE *);
-void markcall(NODE *);
-void oreg2(NODE *p);
int notoff(TWORD, int, CONSZ, char *);
-void bycode(int, int);
-void pstab(char *, int);
-void psline(void);
int notlval(NODE *);
-int icons(NODE *);
void ecode(NODE *p);
int yylex(void);
void yyerror(char *s);
void p2tree(NODE *p);
-int rewfld(NODE *p);
-int freetemp(int k);
Index: ccconfig.h
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/ccconfig.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/ccconfig.h -L usr.bin/pcc/ccconfig.h -u -r1.1 -r1.2
--- usr.bin/pcc/ccconfig.h
+++ usr.bin/pcc/ccconfig.h
@@ -1,43 +1,129 @@
+/* $Id: ccconfig.h,v 1.4 2008/07/18 06:53:48 gmcgarry Exp $ */
/*-
- * Copyright (c) 2007 Lucas Holt <luke at midnightbsd.org>
- * Copyright (c) 2007 David O'Brien <obrien at FreeBSD.org>
- * Copyright (c) 2007 Ed Schouten <ed at fxq.nl>
- * All rights reserved.
+ * Copyright (c) 2007, 2008
+ * Thorsten Glaser <tg at mirbsd.de>
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
+ * Provided that these terms and disclaimer and all copyright notices
+ * are retained or reproduced in an accompanying document, permission
+ * is granted to deal in this work without restriction, including un-
+ * limited rights to use, publicly perform, distribute, sell, modify,
+ * merge, give away, or sublicence.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
+ * the utmost extent permitted by applicable law, neither express nor
+ * implied; without malicious intent or gross negligence. In no event
+ * may a licensor, author or contributor be held liable for indirect,
+ * direct, other damage, loss, or other issues arising in any way out
+ * of dealing in the work, even if advised of the possibility of such
+ * damage or existence of a defect, except proven that it results out
+ * of said person's immediate fault when using the work as intended.
*/
-#define CPPADD { "-D__MidnightBSD__", "-D__ELF__", "-D__unix__=1", "-D__unix=1", "-D__STDC__=1", NULL, }
-#define DYNLINKER { "-dynamic-linker", "/libexec/ld-elf.so.1", NULL }
-#define CRT0FILE "/usr/lib/crt1.o"
-#define STARTFILES { "/usr/lib/crti.o", "/usr/lib/crtbegin.o", NULL }
-#define ENDFILES { "/usr/lib/crtend.o", "/usr/lib/crtn.o", NULL }
-#define STARTLABEL "_start"
+/**
+ * Configuration for pcc on a MidnightBSD (amd64, i386 or sparc64) target
+ */
-#if defined(mach_i386) || defined(mach_x86)
-#define CPPMDADD { "-D__i386__", "-D__i386", NULL, }
-#else
-#error defines for arch missing
+/* === mi part === */
+
+#ifndef LIBDIR
+#define LIBDIR "/usr/lib/"
#endif
+/* cpp MI defines */
+#define CPPADD { \
+ "-D__MidnightBSD__", \
+ "-D__FreeBSD__", \
+ "-D__unix__", \
+ "-D__unix", \
+ "-Dunix", \
+ "-D__ELF__", \
+ "-D_LONGLONG", \
+ NULL \
+}
+
+/* for dynamically linked binaries */
+#define DYNLINKER { \
+ "-dynamic-linker", \
+ "/libexec/ld-elf.so.1", \
+ NULL \
+}
+#define STARTFILES { \
+ LIBDIR "crti.o", \
+ LIBDIR "crtbegin.o", \
+ NULL \
+}
+#define ENDFILES { \
+ LIBDIR "crtend.o", \
+ LIBDIR "crtn.o", \
+ NULL \
+}
+
+/* for shared libraries */
+#define STARTFILES_S { \
+ LIBDIR "crti.o", \
+ LIBDIR "crtbeginS.o", \
+ NULL \
+}
+#define ENDFILES_S { \
+ LIBDIR "crtendS.o", \
+ LIBDIR "crtn.o", \
+ NULL \
+}
+
+/* for statically linked binaries */
+#define STARTFILES_T { \
+ LIBDIR "crti.o", \
+ LIBDIR "crtbeginT.o", \
+ NULL \
+}
+#define ENDFILES_T { \
+ LIBDIR "crtend.o", \
+ LIBDIR "crtn.o", \
+ NULL \
+}
+
+#define LIBCLIBS { \
+ "-lc", \
+ NULL \
+}
+#define LIBCLIBS_PROFILE { \
+ "-lc_p", \
+ NULL \
+}
+
+
+/* C run-time startup */
+#define CRT0FILE LIBDIR "crt1.o"
+#define CRT0FILE_PROFILE LIBDIR "gcrt1.o"
+#define STARTLABEL "_start"
+
+/* debugging info */
#define STABS
+/* === md part === */
+
+#if defined(mach_i386)
+#define CPPMDADD { \
+ "-D__i386__", \
+ "-D__i386", \
+ "-Di386", \
+ NULL, \
+}
+#elif defined(mach_sparc64)
+#define CPPMDADD { \
+ "-D__sparc64__", \
+ "-D__sparc_v9__", \
+ "-D__sparcv9", \
+ "-D__sparc__", \
+ "-D__sparc", \
+ "-Dsparc", \
+ "-D__arch64__", \
+ "-D__LP64__", \
+ "-D_LP64", \
+ NULL, \
+}
+#elif defined(mach_amd64)
+#error pcc does not support amd64 yet
+#else
+#error this architecture is not supported by MidnightBSD
+#endif
Index: config.h
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/config.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -L usr.bin/pcc/config.h -L usr.bin/pcc/config.h -u -r1.3 -r1.4
--- usr.bin/pcc/config.h
+++ usr.bin/pcc/config.h
@@ -1,6 +1,21 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
+/* Using a.out ABI */
+/* #undef AOUTABI */
+
+/* Define path to alternate assembler */
+/* #undef ASSEMBLER */
+
+/* Using Classic 68k ABI */
+/* #undef CLASSIC68K */
+
+/* Using COFF ABI */
+/* #undef COFFABI */
+
+/* Define path to alternate preprocessor */
+/* #undef COMPILER */
+
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
@@ -9,6 +24,12 @@
/* Define to 1 if using `alloca.c'. */
/* #undef C_ALLOCA */
+/* Using ECOFF ABI */
+/* #undef ECOFFABI */
+
+/* Using ELF ABI */
+#define ELFABI
+
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
@@ -16,30 +37,38 @@
*/
/* #undef HAVE_ALLOCA_H */
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-/* #undef HAVE_DOPRNT */
+/* Define to 1 if you have the `basename' function. */
+#define HAVE_BASENAME 1
+
+/* Define to 1 if printf supports C99 size specifiers */
+#define HAVE_C99_FORMAT 1
+
+/* Define to 1 if your compiler supports C99 variadic macros */
+#define HAVE_CPP_VARARG_MACRO_GCC 1
-/* Define to 1 if you have the <fcntl.h> header file. */
-/* #undef HAVE_FCNTL_H */
+/* Define to 1 if you have the `ffs' function. */
+#define HAVE_FFS 1
-/* Define to 1 if you have the `fork' function. */
-/* #undef HAVE_FORK */
+/* Define to 1 if you have the `getopt' function. */
+#define HAVE_GETOPT 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
-/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
- to 0 otherwise. */
-/* #undef HAVE_MALLOC */
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
-/* Define to 1 if you have the `memset' function. */
-/* #undef HAVE_MEMSET */
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
-/* Define to 1 if stdbool.h conforms to C99. */
-/* #undef HAVE_STDBOOL_H */
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
@@ -47,27 +76,17 @@
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
-/* Define to 1 if you have the `strchr' function. */
-/* #undef HAVE_STRCHR */
-#define HAVE_STRCHR 1
-
-/* Define to 1 if you have the `strdup' function. */
-/* #undef HAVE_STRDUP */
-#define HAVE_STRDUP 1
-
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
-/* Define to 1 if you have the `strrchr' function. */
-/* #undef HAVE_STRRCHR */
-#define HAVE_STRRCHR 1
-
-/* Define to 1 if you have the `strtol' function. */
-/* #undef HAVE_STRTOL */
-#define HAVE_STRTOL 1
+/* Define to 1 if you have the `strlcat' function. */
+#define HAVE_STRLCAT 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+#define HAVE_STRLCPY 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
@@ -76,51 +95,61 @@
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
-/* #undef HAVE_SYS_WAIT_H */
+#define HAVE_SYS_WAIT_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
-/* Define to 1 if you have the `vfork' function. */
-/* #undef HAVE_VFORK */
-#define HAVE_VFORK 1
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
-/* Define to 1 if you have the <vfork.h> header file. */
-/* #undef HAVE_VFORK_H */
+/* Define if host is BIG endian */
+/* #undef HOST_BIG_ENDIAN */
-/* Define to 1 if you have the `vprintf' function. */
-/* #undef HAVE_VPRINTF */
-#define HAVE_VPRINTF 1
+/* Define if host is LITTLE endian */
+#define HOST_LITTLE_ENDIAN
-/* Define to 1 if `fork' works. */
-/* #undef HAVE_WORKING_FORK */
+/* lex is flex */
+#define ISFLEX 1
-/* Define to 1 if `vfork' works. */
-/* #undef HAVE_WORKING_VFORK */
+/* Define alternate standard lib directory */
+/* #undef LIBDIR */
-/* Define to 1 if the system has the type `_Bool'. */
-/* #undef HAVE__BOOL */
+/* Define path to alternate linker */
+/* #undef LINKER */
-/* Name of package */
-/* #undef PACKAGE */
+/* Using Mach-O ABI */
+/* #undef MACHOABI */
/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "BUG-REPORT-ADDRESS"
+#define PACKAGE_BUGREPORT "<pcc-list at ludd.ltu.se>"
/* Define to the full name of this package. */
#define PACKAGE_NAME "pcc"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "pcc 0.9.8"
+#define PACKAGE_STRING "pcc 0.9.9"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pcc"
/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.9.8"
+#define PACKAGE_VERSION "0.9.9"
+
+/* Major version no */
+#define PCC_MAJOR 0
-/* Define as the return type of signal handlers (`int' or `void'). */
-/* #undef RETSIGTYPE */
+/* Minor version no */
+#define PCC_MINOR 9
+
+/* Minor minor version no */
+#define PCC_MINORMINOR 9
+
+/* Using PE/COFF ABI */
+/* #undef PECOFFABI */
+
+/* Define path to alternate preprocessor */
+/* #undef PREPROCESSOR */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
@@ -133,30 +162,24 @@
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
-/* Version number of package */
-#define PCC_MAJOR 0
-#define PCC_MINOR 9
-#define PCC_MINORMINOR 8
-#define VERSSTR "pcc 0.9.8 for i386-unknown-midnightbsd0.2, laffer1 at m5.midnightbsd.org Wed Sep 26 15:13:33 EDT 2007"
-
-/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
- `char[]'. */
-#define YYTEXT_POINTER 1
-
-/* Define to rpl_malloc if the replacement function should be used. */
-/* #undef malloc */
+/* Define alternate standard include directory */
+/* #undef STDINC */
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef pid_t */
+/* Define if target defaults to BIG endian */
+/* #undef TARGET_BIG_ENDIAN */
-/* Define as `fork' if `vfork' does not work. */
-/* #undef vfork */
+/* Define if target defaults to LITTLE endian */
+#define TARGET_LITTLE_ENDIAN 1
-/* target operating system */
+/* Target OS */
#define TARGOS midnightbsd
-/* mkstemp() */
-#define HAVE_MKSTEMP 1
+/* Enable thread-local storage (TLS). */
+/* #undef TLS */
-/* which lex is used */
-#define ISFLEX 1
+/* Version string */
+#define VERSSTR "pcc 0.9.9 for i386-unknown-midnightbsd0.3, root at defiant.midnightbsd.org Tue Jan 20 15:33:42 EST 2009"
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#define YYTEXT_POINTER 1
--- /dev/null
+++ usr.bin/pcc/sparc64/order.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2008 David Crawshaw <david at zentus.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "pass2.h"
+
+int
+notoff(TWORD t, int r, CONSZ off, char *cp)
+{
+ return 0;
+}
+
+/*
+ * Turn a UMUL-referenced node into OREG.
+ */
+void
+offstar(NODE *p, int shape)
+{
+ if (x2debug)
+ printf("offstar(%p)\n", p);
+
+ if (p->n_op == PLUS || p->n_op == MINUS) {
+ if (p->n_right->n_op == ICON) {
+ if (isreg(p->n_left) == 0)
+ (void)geninsn(p->n_left, INAREG);
+ /* Converted in ormake() */
+ return;
+ }
+ }
+ (void)geninsn(p, INAREG);
+}
+
+void
+myormake(NODE *q)
+{
+}
+
+int
+shumul(NODE *p, int shape)
+{
+ if (shape & SOREG)
+ return SROREG;
+ return SRNOPE;
+}
+
+int
+setbin(NODE *p)
+{
+ return 0;
+}
+
+int
+setasg(NODE *p, int cookie)
+{
+ return 0;
+}
+
+int
+setuni(NODE *p, int cookie)
+{
+ return 0;
+}
+
+struct rspecial *
+nspecial(struct optab *q)
+{
+ switch (q->op) {
+ case STASG: {
+ static struct rspecial s[] = {
+ { NEVER, O0 },
+ { NRIGHT, O1 },
+ { NEVER, O2 },
+ { 0 }
+ };
+ return s;
+ }
+ }
+
+ comperr("unknown nspecial %d: %s", q - table, q->cstring);
+ return 0; /* XXX */
+}
+
+int
+setorder(NODE *p)
+{
+ return 0;
+}
+
+int *
+livecall(NODE *p)
+{
+ static int ret[] = { O0, O1, O2, O3, O4, O5, O6, O7, -1 };
+ return ret;
+}
+
+int
+acceptable(struct optab *op)
+{
+ return 1;
+}
--- /dev/null
+++ usr.bin/pcc/sparc64/macdefs.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2008 David Crawshaw <david at zentus.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+/*
+ * Many arithmetic instructions take 'reg_or_imm' in SPARCv9, where imm
+ * means we can use a signed 13-bit constant (simm13). This gives us a
+ * shortcut for small constants, instead of loading them into a register.
+ * Special handling is required because 13 bits lies between SSCON and SCON.
+ */
+#define SIMM13(val) (val < 4096 && val > -4097)
+
+/*
+ * The SPARCv9 ABI specifies a stack bias of 2047 bits. This means that the
+ * end of our call space is %fp+V9BIAS, working back towards %sp+V9BIAS+176.
+ */
+#define V9BIAS 2047
+
+/*
+ * The ABI requires that every frame reserve 176 bits for saving registers
+ * in the case of a spill. The stack size must be 16-bit aligned.
+ */
+#define V9RESERVE 176
+#define V9STEP(x) ALIGN(x, 0xf)
+#define ALIGN(x, y) ((x & y) ? (x + y) & ~y : x)
+
+
+#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24);
+
+#define ARGINIT (7*8) /* XXX */
+#define AUTOINIT (0)
+
+/* Type sizes */
+#define SZCHAR 8
+#define SZBOOL 32
+#define SZINT 32
+#define SZFLOAT 32
+#define SZDOUBLE 64
+#define SZLDOUBLE 64
+#define SZLONG 64
+#define SZSHORT 16
+#define SZLONGLONG 64
+#define SZPOINT(t) 64
+
+/* Type alignments */
+#define ALCHAR 8
+#define ALBOOL 32
+#define ALINT 32
+#define ALFLOAT 32
+#define ALDOUBLE 64
+#define ALLDOUBLE 64
+#define ALLONG 64
+#define ALLONGLONG 64
+#define ALSHORT 16
+#define ALPOINT 64
+#define ALSTRUCT 32
+#define ALSTACK 64
+
+/* Min/max values. */
+#define MIN_CHAR -128
+#define MAX_CHAR 127
+#define MAX_UCHAR 255
+#define MIN_SHORT -32768
+#define MAX_SHORT 32767
+#define MAX_USHORT 65535
+#define MIN_INT -1
+#define MAX_INT 0x7fffffff
+#define MAX_UNSIGNED 0xffffffff
+#define MIN_LONGLONG 0x8000000000000000LL
+#define MAX_LONGLONG 0x7fffffffffffffffLL
+#define MAX_ULONGLONG 0xffffffffffffffffULL
+#define MIN_LONG MIN_LONGLONG
+#define MAX_LONG MAX_LONGLONG
+#define MAX_ULONG MAX_ULONGLONG
+
+#define BOOL_TYPE INT
+#define WCHAR_TYPE INT
+
+typedef long long CONSZ;
+typedef unsigned long long U_CONSZ;
+typedef long long OFFSZ;
+
+#define CONFMT "%lld"
+#define LABFMT "L%d"
+#define STABLBL "LL%d"
+
+#define BACKAUTO /* Stack grows negatively for automatics. */
+#define BACKTEMP /* Stack grows negatively for temporaries. */
+
+#undef FIELDOPS
+#define RTOLBYTES
+
+#define ENUMSIZE(high,low) INT
+#define BYTEOFF(x) ((x)&03)
+#define BITOOR(x) (x)
+
+#define szty(t) ((ISPTR(t) || (t) == DOUBLE || \
+ (t) == LONG || (t) == ULONG || \
+ (t) == LONGLONG || (t) == ULONGLONG) ? 2 : 1)
+
+
+/* Register names. */
+
+#define MAXREGS (31 + 31 + 16 + 2)
+#define NUMCLASS 4
+
+//define G0 -1
+#define G1 0
+#define G2 1
+#define G3 2
+#define G4 3
+#define G5 4
+#define G6 5
+#define G7 6
+#define O0 7
+#define O1 8
+#define O2 9
+#define O3 10
+#define O4 11
+#define O5 12
+#define O6 13
+#define O7 14
+#define L0 15
+#define L1 16
+#define L2 17
+#define L3 18
+#define L4 19
+#define L5 20
+#define L6 21
+#define L7 22
+#define I0 23
+#define I1 24
+#define I2 25
+#define I3 26
+#define I4 27
+#define I5 28
+#define I6 29
+#define I7 30
+
+#define F0 31
+#define F1 32
+#define F2 33
+#define F3 34
+#define F4 35
+#define F5 36
+#define F6 37
+#define F7 38
+#define F8 39
+#define F9 40
+#define F10 41
+#define F11 42
+#define F12 43
+#define F13 44
+#define F14 45
+#define F15 46
+#define F16 47
+#define F17 48
+#define F18 49
+#define F19 50
+#define F20 51
+#define F21 52
+#define F22 53
+#define F23 54
+#define F24 55
+#define F25 56
+#define F26 57
+#define F27 58
+#define F28 59
+#define F29 60
+#define F30 61
+//define F31 XXX
+#define D0 62
+#define D1 63
+#define D2 64
+#define D3 65
+#define D4 66
+#define D5 67
+#define D6 68
+#define D7 69
+#define D8 70
+#define D9 71
+#define D10 72
+#define D11 73
+#define D12 74
+#define D13 75
+#define D14 76
+#define D15 77
+
+#define SP 78
+#define FP 79
+
+#define FPREG FP
+
+#define RETREG(x) ((x)==DOUBLE ? D0 : (x)==FLOAT ? F1 : O0)
+#define RETREG_PRE(x) ((x)==DOUBLE ? D0 : (x)==FLOAT ? F1 : I0)
+
+#define RSTATUS \
+ /* global */ \
+ SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \
+ SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \
+ /* out */ \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ /* local */ \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ /* in */ \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ /* 32-bit floating point */ \
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, /*, SBREG */ \
+ /* 64-bit floating point */ \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
+ /* sp */ SDREG, \
+ /* fp */ SDREG
+
+#define ROVERLAP \
+ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
+/* 32-bit floating point */ \
+ { D0, -1 }, { D0, -1 }, { D1, -1 }, { D1, -1 }, \
+ { D2, -1 }, { D2, -1 }, { D3, -1 }, { D3, -1 }, \
+ { D4, -1 }, { D4, -1 }, { D5, -1 }, { D5, -1 }, \
+ { D6, -1 }, { D6, -1 }, { D7, -1 }, { D7, -1 }, \
+ { D8, -1 }, { D8, -1 }, { D9, -1 }, { D9, -1 }, \
+ { D10, -1 }, { D10, -1 }, { D11, -1 }, { D11, -1 }, \
+ { D12, -1 }, { D12, -1 }, { D13, -1 }, { D13, -1 }, \
+ { D14, -1 }, { D14, -1 }, { D15, -1 }, /* { D15, -1 }, */ \
+/* 64-bit floating point */ \
+ { F0, F1, -1 }, { F2, F3, -1 }, { F4, F5, -1 }, \
+ { F6, F7, -1 }, { F8, F9, -1 }, { F10, F11, -1 }, \
+ { F12, F13, -1 }, { F14, F15, -1 }, { F16, F17, -1 }, \
+ { F18, F19, -1 }, { F20, F21, -1 }, { F22, F23, -1 }, \
+ { F24, F25, -1 }, { F26, F27, -1 }, { F28, F29, -1 }, \
+ { F30, /* F31, */ -1 }, \
+ { -1 }, \
+ { -1 }
+
+#define GCLASS(x) (x <= I7 ? CLASSA : \
+ (x <= F30 ? CLASSB : \
+ (x <= D15 ? CLASSC : \
+ (x == SP || x == FP ? CLASSD : 0))))
+#define PCLASS(p) (1 << gclass((p)->n_type))
+#define DECRA(x,y) (((x) >> (y*7)) & 127)
+#define ENCRA(x,y) ((x) << (7+y*7))
+#define ENCRD(x) (x)
+
+int COLORMAP(int c, int *r);
--- /dev/null
+++ usr.bin/pcc/sparc64/table.c
@@ -0,0 +1,963 @@
+/*
+ * Copyright (c) 2008 David Crawshaw <david at zentus.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "pass2.h"
+
+#define TS64 TLONG|TLONGLONG
+#define TU64 TULONG|TULONGLONG|TPOINT
+#define T64 TS64|TU64
+
+struct optab table[] = {
+
+{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, /* empty */
+
+{ PCONV, INAREG,
+ SAREG, T64|TINT,
+ SAREG, T64,
+ 0, RLEFT,
+ " ! convert between word and pointer\n", },
+
+/* Conversions. */
+
+{ SCONV, INAREG,
+ SAREG, T64|TUNSIGNED,
+ SAREG, TINT,
+ NAREG|NASL, RESC1,
+ " sra AL,0,A1 \t\t! (u)int64/32 -> (u)int32\n", },
+
+{ SCONV, INAREG,
+ SAREG, T64|TINT|TUNSIGNED,
+ SAREG, TSHORT,
+ NAREG|NASL, RESC1,
+ " sll AL,16,A1 \t\t! (u)int64/32 -> int16\n"
+ " sra AL,16,A1\n"
+ " sra AL, 0,A1\n", },
+
+{ SCONV, INAREG,
+ SAREG, T64|TINT|TUNSIGNED,
+ SAREG, TUSHORT,
+ NAREG|NASL, RESC1,
+ " sll AL,16,A1 \t\t! (u)int64/32 -> uint16\n"
+ " srl AL,16,A1\n", },
+
+{ SCONV, INAREG,
+ SAREG, T64|TINT|TUNSIGNED|TSHORT|TUSHORT,
+ SAREG, TCHAR,
+ NAREG|NASL, RESC1,
+ " sll AL,24,A1 \t\t! (u)int64/32/16 -> int8\n"
+ " sra AL,24,A1\n"
+ " sra AL, 0,A1\n", },
+
+{ SCONV, INAREG,
+ SAREG, T64|TINT|TUNSIGNED|TSHORT|TUSHORT,
+ SAREG, TUCHAR,
+ NAREG|NASL, RESC1,
+ " and AL,0xff,A1 \t\t! (u)int64/32/16 -> uint8\n", },
+
+{ SCONV, INAREG,
+ SAREG, T64|TINT|TUNSIGNED|TSHORT|TUSHORT,
+ SAREG, T64,
+ 0, RLEFT,
+ " \t\t! (u)int64...8 -> (u)int64\n", },
+
+{ SCONV, INAREG,
+ SAREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TINT,
+ 0, RLEFT,
+ " \t\t! (u)int16/8 -> int32\n", },
+
+{ SCONV, INAREG,
+ SAREG, T64|TINT|TSHORT|TCHAR,
+ SAREG, TUNSIGNED,
+ 0, RLEFT,
+ " srl AL, 0,A1 \t\t! int32/16/8 -> uint32\n", },
+
+{ SCONV, INAREG,
+ SAREG, TUSHORT|TUCHAR,
+ SAREG, TUNSIGNED,
+ 0, RLEFT,
+ " \t\t! uint16/8 -> uint32\n", },
+
+{ SCONV, INBREG,
+ SBREG, TINT|TUNSIGNED,
+ SBREG, TFLOAT,
+ NBREG|NASL, RESC1,
+ " fitos AL,A1 \t\t! (u)int32 -> float\n", },
+
+{ SCONV, INBREG,
+ SBREG, T64,
+ SBREG, TFLOAT,
+ NBREG|NASL, RESC1,
+ " fxtos AL,A1 \t\t! (u)int64 -> float\n", },
+
+{ SCONV, INCREG,
+ SCREG, TINT|TUNSIGNED,
+ SCREG, TDOUBLE,
+ NCREG|NASL, RESC1,
+ " fitod AL,A1 \t\t! (u)int32 -> double\n", },
+
+{ SCONV, INCREG,
+ SCREG, T64,
+ SCREG, TDOUBLE,
+ NCREG|NASL, RESC1,
+ " fxtod AL,A1 \t\t! (u)int64 -> double\n", },
+
+
+/* Floating-point conversions must be stored and loaded. */
+
+{ SCONV, INAREG,
+ SOREG, TFLOAT,
+ SAREG, TINT,
+ NAREG|(2*NBREG), RESC1,
+ " ld [AL],A2 \t\t! float -> int32\n"
+ " nop\n"
+ " fmovs A2,A3\n"
+ " fstoi A2,A2\n"
+ " st A2,[AL]\n"
+ " nop\n"
+ " ld [AL],A1\n"
+ " nop\n"
+ " st A3,[AL]\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TDOUBLE,
+ SAREG, TINT,
+ NAREG|(2*NCREG), RESC1,
+ " ld [AL],A2 \t\t! double -> int32\n"
+ " nop\n"
+ " fmovd A2,A3\n"
+ " fdtoi A2,A2\n"
+ " std A2,[AL]\n"
+ " nop\n"
+ " ldd [AL],A1\n"
+ " nop\n"
+ " std A3,[AL]\n"
+ " nop\n", },
+
+{ SCONV, INBREG,
+ SOREG, T64|TUNSIGNED,
+ SBREG, TFLOAT,
+ NBREG, RESC1,
+ " ld [AL],A1 \t\t! int64 -> float\n"
+ " fxtos A1,A1\n", },
+
+{ SCONV, INBREG,
+ SOREG, TINT|TSHORT|TCHAR,
+ SBREG, TFLOAT,
+ NBREG, RESC1,
+ " ld [AL],A1 \t\t! int32/16/8 -> float\n"
+ " fitos A1,A1\n", }, // XXX need 'lds', 'ldh', etc
+
+{ SCONV, INCREG,
+ SOREG, T64|TUNSIGNED,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
+ " ldd [AL],A1 \t\t! (u)int64 -> double\n"
+ " fxtod A1,A1\n", },
+
+{ SCONV, INCREG,
+ SOREG, TINT|TSHORT|TCHAR,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
+ " ld [AL],A1 \t\t! int32/16/8 -> double\n"
+ " fitod A1,A1\n", }, // XXX need 'lds' 'ldh' 'ld', etc.
+
+{ SCONV, INBREG,
+ SCREG, TDOUBLE,
+ SBREG, TFLOAT,
+ NBREG, RESC1,
+ " fdtos AL,A1 \t\t! double -> float\n",},
+
+{ SCONV, INCREG,
+ SBREG, TFLOAT,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
+ " fstod AL,A1 \t\t! float -> double\n",},
+
+{ SCONV, INAREG,
+ SBREG, TFLOAT,
+ SAREG, TINT,
+ NAREG|NBREG, RESC1,
+ " fstoi AL,A2 \t\t! float -> int\n"
+ " st A2,[%fp+2047]\n"
+ " nop\n"
+ " ld [%fp+2047],A1\n"
+ " nop\n",},
+
+{ SCONV, INAREG,
+ SCREG, TDOUBLE,
+ SAREG, TINT,
+ NAREG|NCREG, RESC1,
+ " fdtoi AL,A2 \t\t! double -> int\n"
+ " st A2,[%fp+2047]\n"
+ " nop\n"
+ " ld [%fp+2047],A1\n"
+ " nop\n",},
+
+
+/* Multiplication and division */
+
+{ MUL, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASR|NASL, RESC1,
+ " mulx AL,AR,A1 ! multiply\n", },
+
+{ MUL, INBREG,
+ SBREG, TFLOAT,
+ SBREG, TFLOAT,
+ NBREG|NBSR|NBSL, RESC1,
+ " fmuls AL,AR,A1 ! multiply float\n", },
+
+{ MUL, INCREG,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG|NCSR|NCSL, RESC1,
+ " fmuld AL,AR,A1 ! multiply double\n", },
+
+{ DIV, INAREG,
+ SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64,
+ SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64,
+ NAREG|NASR|NASL, RESC1,
+ " udivx AL,AR,A1 ! unsigned division\n", },
+
+{ DIV, INAREG,
+ SAREG, TINT|TSHORT|TCHAR|TS64,
+ SAREG, TINT|TSHORT|TCHAR|TS64,
+ NAREG|NASR|NASL, RESC1,
+ " sdivx AL,AR,A1 ! signed division\n", },
+
+{ DIV, INBREG,
+ SBREG, TFLOAT,
+ SBREG, TFLOAT,
+ NBREG|NBSR|NBSL, RESC1,
+ " fdivs AL,AR,A1 ! divide float\n", },
+
+{ DIV, INCREG,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG|NCSR|NCSL, RESC1,
+ " fdivd AL,AR,A1 ! divide double\n", },
+
+{ MOD, INAREG,
+ SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64,
+ SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64,
+ NAREG, RESC1,
+ " udivx AL,AR,A1 ! unsigned modulo\n"
+ " mulx A1,AR,A1\n"
+ " sub AL,A1,A1\n", },
+
+{ MOD, INAREG,
+ SAREG, TINT|TSHORT|TCHAR|TS64,
+ SAREG, TINT|TSHORT|TCHAR|TS64,
+ NAREG, RESC1,
+ " sdivx AL,AR,A1 ! signed modulo\n"
+ " mulx A1,AR,A1\n"
+ " sub AL,A1,A1\n", },
+
+{ PLUS, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASL, RESC1,
+ " add AL,AR,A1\n", },
+
+{ PLUS, INBREG,
+ SBREG, TFLOAT,
+ SBREG, TFLOAT,
+ NBREG|NBSL, RESC1,
+ " fadds AL,AR,A1\n", },
+
+{ PLUS, INCREG,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG|NCSL, RESC1,
+ " faddd AL,AR,A1\n", },
+
+{ PLUS, INAREG,
+ SAREG, TANY,
+ SCON, TANY,
+ (3*NAREG)|NASL, RESC1,
+ "ZA", },
+
+{ MINUS, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASL, RESC1,
+ " sub AL,AR,A1\n", },
+
+{ MINUS, INBREG,
+ SBREG, TANY,
+ SBREG, TANY,
+ NBREG|NBSL|NBSR, RESC1,
+ " fsubs AL,AR,A1\n", },
+
+{ MINUS, INCREG,
+ SCREG, TANY,
+ SCREG, TANY,
+ NCREG|NCSL|NBSR, RESC1,
+ " fsubd AL,AR,A1\n", },
+
+{ MINUS, INAREG,
+ SAREG, TANY,
+ SCON, TANY,
+ (3*NAREG)|NASL, RESC1,
+ "ZB", },
+
+{ UMINUS, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " sub %g0,AL,A1\n", },
+
+{ UMINUS, INBREG,
+ SBREG, TANY,
+ SANY, TANY,
+ NBREG|NBSL, RESC1,
+ " fsubs %g0,AL,A1\n", },
+
+{ UMINUS, INCREG,
+ SCREG, TANY,
+ SANY, TANY,
+ NCREG|NCSL, RESC1,
+ " fsubd %g0,AL,A1\n", },
+
+/* Shifts */
+
+{ RS, INAREG,
+ SAREG, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG|SCON, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " sra AL,AR,A1 ! shift right\n", },
+
+{ RS, INAREG,
+ SAREG, T64,
+ SAREG|SCON, T64|TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " srax AL,AR,A1 ! shift right\n", },
+
+{ LS, INAREG,
+ SAREG, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG|SCON, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " sll AL,AR,A1 ! shift left\n", },
+
+{ LS, INAREG,
+ SAREG, T64,
+ SAREG|SCON, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " sllx AL,AR,A1 ! shift left\n", },
+
+{ COMPL, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " orn AL,%g0,A1 ! complement\n", },
+
+/* Assignments */
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG, TINT|TUNSIGNED,
+ SAREG, TINT|TUNSIGNED,
+ 0, RDEST,
+ " stw AR,[AL] ! store (u)int32\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ 0, RDEST,
+ " sth AR,[AL] ! store (u)int16\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG, TCHAR|TUCHAR,
+ SAREG, TCHAR|TUCHAR,
+ 0, RDEST,
+ " stb AR,[AL] ! store (u)int8\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG, T64,
+ SAREG, T64,
+ 0, RDEST,
+ " stx AR,[AL] ! store (u)int64\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SOREG, TFLOAT,
+ SBREG, TFLOAT,
+ 0, RDEST,
+ " st AR,[AL] ! store float\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SOREG, TINT,
+ SBREG, TINT,
+ 0, RDEST,
+ " st AR,[AL] ! store int from fp address\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INCREG,
+ SOREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ 0, RDEST,
+ " std AR,[AL] ! store double\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INCREG,
+ SOREG, TINT,
+ SCREG, TINT,
+ 0, RDEST,
+ " st AR,[AL] ! store int from fp address\n"
+ " nop\n", },
+
+
+{ ASSIGN, FOREFF|INAREG,
+ SNAME, TINT|TUNSIGNED,
+ SAREG, TINT|TUNSIGNED,
+ NAREG, RDEST,
+ " sethi %h44(AL),A1 \t! store (u)int32 into sname\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " stw AR,[A1+%l44(AL)]\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SNAME, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ NAREG, RDEST,
+ " sethi %h44(AL),A1 \t! store (u)int16 into sname\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " sth AR,[A1+%l44(AL)]\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SNAME, TCHAR|TUCHAR,
+ SAREG, TCHAR|TUCHAR,
+ NAREG, RDEST,
+ " sethi %h44(AL),A1 \t! store (u)int8 into sname\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " stb AR,[A1+%l44(AL)]\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SNAME, T64,
+ SAREG, T64,
+ NAREG, RDEST,
+ " sethi %h44(AL),A1 \t! store (u)int64 into sname\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " stx AR,[A1+%l44(AL)]\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SNAME, TFLOAT|TINT,
+ SBREG, TFLOAT|TINT,
+ NAREG, RDEST,
+ " sethi %h44(AL),A1 \t! store float into sname\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " st AR,[A1+%l44(AL)]\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INCREG,
+ SNAME, TDOUBLE,
+ SCREG, TDOUBLE,
+ NAREG, RDEST,
+ " sethi %h44(AL),A1 \t! store double into sname\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " std AR,[A1+%l44(AL)]\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INCREG,
+ SNAME, TINT,
+ SCREG, TINT,
+ NAREG, RDEST,
+ " sethi %h44(AL),A1 \t! store int into sname\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " st AR,[A1+%l44(AL)]\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ 0, RDEST,
+ " mov AR,AL ! register move\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SBREG, TANY,
+ SBREG, TANY,
+ 0, RDEST,
+ " fmovs AR,AL ! move float\n", },
+
+{ ASSIGN, FOREFF|INCREG,
+ SCREG, TANY,
+ SCREG, TANY,
+ 0, RDEST,
+ " fmovd AR,AL ! move double\n", },
+
+/* Structure assignment. */
+
+{ STASG, INAREG|FOREFF,
+ SOREG|SNAME, TANY,
+ SAREG, TPTRTO|TANY,
+ NSPECIAL, RRIGHT,
+ "ZQ", },
+
+/* Comparisons. */
+
+{ EQ, FORCC,
+ SAREG, TANY,
+ SAREG, TANY,
+ 0, RESCC,
+ " cmp AL,AR\n"
+ " be LC\n"
+ " nop\n", },
+
+{ NE, FORCC,
+ SAREG, TANY,
+ SAREG, TANY,
+ 0, RESCC,
+ " cmp AL,AR\n"
+ " bne LC\n"
+ " nop\n", },
+
+{ OPLOG, FORCC,
+ SAREG, TANY,
+ SZERO, TANY,
+ 0, RESCC,
+ " O AL,LC\n"
+ " nop\n", },
+
+{ OPLOG, FORCC,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASL, RESCC,
+ " sub AL,AR,A1 ! oplog\n"
+ " O A1,LC\n"
+ " nop\n", },
+
+{ OPLOG, FORCC,
+ SAREG, TANY,
+ SCCON, TANY,
+ NAREG|NASL, RESCC,
+ " sub AL,AR,A1 ! oplog sccon\n"
+ " O A1,LC\n"
+ " nop\n", },
+
+{ OPLOG, FORCC,
+ SBREG, TFLOAT,
+ SBREG, TFLOAT,
+ NBREG, RESCC,
+ " fcmps AL,AR ! oplog float\n"
+ " ZF LC\n", },
+
+{ OPLOG, FORCC,
+ SOREG, TFLOAT,
+ SBREG, TFLOAT,
+ NBREG, RESCC,
+ " ld [AL], A1 ! oplog float oreg\n"
+ " nop\n"
+ " fcmps A1,AR\n"
+ " ZF LC\n", },
+
+{ OPLOG, FORCC,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG, RESCC,
+ " fcmpd AL,AR ! oplog double\n"
+ " ZF LC\n", },
+
+{ OPLOG, FORCC,
+ SOREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG, RESCC,
+ " ldd [AL], A1 ! oplog double oreg\n"
+ " nop\n"
+ " fcmpd A1,AR\n"
+ " ZF LC\n", },
+
+
+/* Load constants to register. */
+
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, T64,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t ! load const (u)int64 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ldx [A1+%l44(AL)],A1\n"
+ " nop\n", },
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, TINT,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t ! load const int32 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ldsw [A1+%l44(AL)],A1\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, TUNSIGNED,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t! load const uint32 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " lduw [A1+%l44(AL)],A1\n"
+ " nop\n", },
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, TSHORT,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t! load const int16 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ldsh [A1+%l44(AL)],A1\n"
+ " nop\n", },
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, TUSHORT,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t ! load const uint16 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " lduh [A1+%l44(AL)],A1\n"
+ " nop\n", },
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, TCHAR,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t\t! load const int8 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ldsb [A1+%l44(AL)],A1\n"
+ " nop\n", },
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, TUCHAR,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t! load const uint8 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ldub [A1+%l44(AL)],A1\n"
+ " nop\n", },
+
+{ OPLTYPE, INBREG,
+ SBREG, TANY,
+ SNAME, TANY,
+ NAREG|NBREG, RESC2,
+ " sethi %h44(AL),A1\t\t! load const to fp reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ld [A1+%l44(AL)],A2\n"
+ " nop\n", },
+
+{ OPLTYPE, INCREG,
+ SCREG, TANY,
+ SNAME, TANY,
+ NAREG|NCREG, RESC2,
+ " sethi %h44(AL),A1\t\t! load const to fp reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ldd [A1+%l44(AL)],A2\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SCON, TANY,
+ (2*NAREG), RESC1,
+ "ZC" },
+
+/* Convert LTYPE to reg. */
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, TCHAR,
+ NAREG, RESC1,
+ " ldsb [AL],A1 ! load int8 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, TUCHAR,
+ NAREG, RESC1,
+ " ldub [AL],A1 ! load uint8 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, TSHORT,
+ NAREG, RESC1,
+ " ldsh [AL],A1 ! load int16 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, TUSHORT,
+ NAREG, RESC1,
+ " lduh [AL],A1 ! load uint16 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, TINT,
+ NAREG, RESC1,
+ " ldsw [AL],A1 ! load int32 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, TUNSIGNED,
+ NAREG, RESC1,
+ " lduw [AL],A1 ! load uint32 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, T64,
+ NAREG, RESC1,
+ " ldx [AL],A1 ! load (u)int64 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SZERO, TANY,
+ NAREG, RESC1,
+ " mov \%g0,A1\t ! load 0 to reg\n", },
+
+{ OPLTYPE, INBREG,
+ SBREG, TFLOAT,
+ SOREG, TFLOAT,
+ NBREG, RESC1,
+ " ld [AL],A1 ! load float to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INCREG,
+ SCREG, TDOUBLE,
+ SOREG, TDOUBLE,
+ NCREG, RESC1,
+ " ldd [AL],A1 ! load double to reg\n"
+ " nop\n", },
+
+/* Jumps. */
+
+{ GOTO, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " call LL ! goto LL\n"
+ " nop\n", },
+
+{ UCALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call CL ! void CL()\n"
+ " nop\n", },
+
+{ UCALL, INAREG,
+ SCON, TANY,
+ SAREG, TANY,
+ NAREG, RESC1,
+ " call CL ! = CL()\n"
+ " nop\n", },
+
+{ CALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call CL ! void CL(constant)\n"
+ " nop\n", },
+
+{ CALL, INAREG,
+ SCON, TANY,
+ SAREG, TANY,
+ NAREG, RESC1,
+ " call CL ! = CL(constant)\n"
+ " nop\n", },
+
+{ CALL, INBREG,
+ SCON, TANY,
+ SBREG, TFLOAT,
+ NBREG, RESC1,
+ " call CL ! = CL(constant)\n"
+ " nop\n", },
+
+{ CALL, INCREG,
+ SCON, TANY,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
+ " call CL ! = CL(constant)\n"
+ " nop\n", },
+
+{ CALL, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG, RESC1,
+ " call AL ! = AL(args)\n"
+ " nop\n", },
+
+{ CALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call AL ! void AL(args)\n"
+ " nop\n", },
+
+{ UCALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call AL ! (*AL)()\n"
+ " nop\n", },
+
+{ UCALL, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG, RESC1,
+ " call AL ! = (*AL)()\n"
+ " nop\n", },
+
+{ CALL, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG, RESC1,
+ " call AL ! = (*AL)(args)\n"
+ " nop\n", },
+
+/* Function arguments. */
+
+{ FUNARG, FOREFF,
+ SAREG, T64,
+ SANY, TANY,
+ 0, 0,
+ " stx AL,[%sp+AR] \t! save func arg to stack\n"
+ " nop\n", },
+
+{ FUNARG, FOREFF,
+ SAREG, TINT|TUNSIGNED,
+ SANY, TANY,
+ 0, 0,
+ " stw AL,[%sp+AR] \t! save func arg to stack\n"
+ " nop\n", },
+
+{ FUNARG, FOREFF,
+ SAREG, TSHORT|TUSHORT,
+ SANY, TANY,
+ 0, 0,
+ " sth AL,[%sp+AR] \t! save func arg to stack\n"
+ " nop\n", },
+
+{ FUNARG, FOREFF,
+ SAREG, TCHAR|TUCHAR,
+ SANY, TANY,
+ 0, 0,
+ " stb AL,[%sp+AR] \t! save func arg to stack\n"
+ " nop\n", },
+
+{ FUNARG, FOREFF,
+ SBREG, TFLOAT,
+ SANY, TANY,
+ 0, 0,
+ " st AL,[%sp+AR] \t! save func arg to stack\n"
+ " nop\n", },
+
+{ FUNARG, FOREFF,
+ SCREG, TDOUBLE,
+ SANY, TANY,
+ 0, 0,
+ " std AL,[%sp+AR] \t! save func arg to stack\n"
+ " nop\n", },
+
+
+/* Indirection. */
+
+{ OPSIMP, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASR|NASL, RESC1,
+ " O AL,AR,A1\n", },
+
+{ UMUL, INAREG,
+ SANY, T64,
+ SOREG, T64,
+ NAREG, RESC1,
+ " ldx [AL],A1 ! (u)int64 load\n"
+ " nop\n", },
+{ UMUL, INAREG,
+ SANY, TINT,
+ SOREG, TINT,
+ NAREG, RESC1,
+ " ldsw [AL],A1 ! int32 load\n"
+ " nop\n", },
+{ UMUL, INAREG,
+ SANY, TUNSIGNED,
+ SOREG, TUNSIGNED,
+ NAREG, RESC1,
+ " lduw [AL],A1 ! uint32 load\n"
+ " nop\n", },
+{ UMUL, INAREG,
+ SANY, TCHAR,
+ SOREG, TCHAR,
+ NAREG, RESC1,
+ " ldsb [AL],A1 ! int8 load\n"
+ " nop\n", },
+{ UMUL, INAREG,
+ SANY, TUCHAR,
+ SOREG, TUCHAR,
+ NAREG, RESC1,
+ " ldub [AL],A1 ! uint8 load\n"
+ " nop\n", },
+{ UMUL, INAREG,
+ SANY, TSHORT,
+ SOREG, TSHORT,
+ NAREG, RESC1,
+ " ldsh [AL],A1 ! int16 load\n"
+ " nop\n", },
+{ UMUL, INAREG,
+ SANY, TUSHORT,
+ SOREG, TUSHORT,
+ NAREG, RESC1,
+ " lduh [AL],A1 ! uint16 load\n"
+ " nop\n", },
+
+{ UMUL, INBREG,
+ SANY, TFLOAT,
+ SOREG, TFLOAT,
+ NBREG, RESC1,
+ " ld [AL],A1 ! load float\n"
+ " nop\n", },
+
+{ UMUL, INCREG,
+ SANY, TDOUBLE,
+ SOREG, TDOUBLE,
+ NCREG, RESC1,
+ " ldd [AL],A1 ! load double\n"
+ " nop\n", },
+
+{ FREE,FREE,FREE,FREE,FREE,FREE,FREE,FREE, "ERR: printing free op\n" },
+
+};
+
+int tablesize = sizeof(table)/sizeof(table[0]);
--- /dev/null
+++ usr.bin/pcc/sparc64/local2.c
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2008 David Crawshaw <david at zentus.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "pass1.h"
+#include "pass2.h"
+
+
+char *
+rnames[] = {
+ /* "\%g0", always zero, removed due to 31-element class limit */
+ "\%g1", "\%g2", "\%g3", "\%g4", "\%g5", "\%g6", "\%g7",
+ "\%o0", "\%o1", "\%o2", "\%o3", "\%o4", "\%o5", "\%o6", "\%o7",
+ "\%l0", "\%l1", "\%l2", "\%l3", "\%l4", "\%l5", "\%l6", "\%l7",
+ "\%i0", "\%i1", "\%i2", "\%i3", "\%i4", "\%i5", "\%i6", "\%i7",
+
+ "\%f0", "\%f1", "\%f2", "\%f3", "\%f4", "\%f5", "\%f6", "\%f7",
+ "\%f8", "\%f9", "\%f10", "\%f11", "\%f12", "\%f13", "\%f14", "\%f15",
+ "\%f16", "\%f17", "\%f18", "\%f19", "\%f20", "\%f21", "\%f22", "\%f23",
+ "\%f24", "\%f25", "\%f26", "\%f27", "\%f28", "\%f29", "\%f30",
+ /*, "\%f31" XXX removed due to 31-element class limit */
+
+ "\%f0", "\%f2", "\%f4", "\%f6", "\%f8", "\%f10", "\%f12", "\%f14",
+ "\%f16", "\%f18", "\%f20", "\%f22", "\%f24", "\%f26", "\%f28", "\%f30",
+
+ "\%sp", "\%fp",
+};
+
+void
+deflab(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+void
+prologue(struct interpass_prolog *ipp)
+{
+ int i, stack;
+
+ stack = V9RESERVE + V9STEP(p2maxautooff);
+
+ for (i = ipp->ipp_regs[0]; i; i >>= 1)
+ if (i & 1)
+ stack += 16;
+
+ /* TODO printf("\t.proc %d\n"); */
+ printf("\t.global %s\n", ipp->ipp_name);
+ printf("\t.align 4\n");
+ printf("%s:\n", ipp->ipp_name);
+ if (SIMM13(stack))
+ printf("\tsave %%sp,-%d,%%sp\n", stack);
+ else {
+ printf("\tsetx -%d,%%g4,%%g1\n", stack);
+ printf("\tsave %%sp,%%g1,%%sp\n");
+ }
+}
+
+void
+eoftn(struct interpass_prolog *ipp)
+{
+ printf("\tret\n");
+ printf("\trestore\n");
+ printf("\t.type %s,#function\n", ipp->ipp_name);
+ printf("\t.size %s,(.-%s)\n", ipp->ipp_name, ipp->ipp_name);
+}
+
+void
+hopcode(int f, int o)
+{
+ char *str;
+
+ switch (o) {
+ case EQ: str = "brz"; break;
+ case NE: str = "brnz"; break;
+ case ULE:
+ case LE: str = "brlez"; break;
+ case ULT:
+ case LT: str = "brlz"; break;
+ case UGE:
+ case GE: str = "brgez"; break;
+ case UGT:
+ case GT: str = "brgz"; break;
+ case PLUS: str = "add"; break;
+ case MINUS: str = "sub"; break;
+ case AND: str = "and"; break;
+ case OR: str = "or"; break;
+ case ER: str = "xor"; break;
+ default:
+ comperr("unknown hopcode: %d (with %c)", o, f);
+ return;
+ }
+
+ printf("%s%c", str, f);
+}
+
+int
+tlen(NODE *p)
+{
+ switch (p->n_type) {
+ case CHAR:
+ case UCHAR:
+ return 1;
+ case SHORT:
+ case USHORT:
+ return (SZSHORT / SZCHAR);
+ case FLOAT:
+ return (SZFLOAT / SZCHAR);
+ case DOUBLE:
+ return (SZDOUBLE / SZCHAR);
+ case INT:
+ case UNSIGNED:
+ return (SZINT / SZCHAR);
+ case LONG:
+ case ULONG:
+ case LONGLONG:
+ case ULONGLONG:
+ return SZLONGLONG / SZCHAR;
+ default:
+ if (!ISPTR(p->n_type))
+ comperr("tlen type unknown: %d");
+ return SZPOINT(p->n_type) / SZCHAR;
+ }
+}
+
+void
+zzzcode(NODE * p, int c)
+{
+ char *str;
+ NODE *l, *r;
+ l = p->n_left;
+ r = p->n_right;
+
+ switch (c) {
+
+ case 'A': /* Add const. */
+ if (ISPTR(l->n_type) && l->n_rval == FP)
+ r->n_lval += V9BIAS;
+
+ if (SIMM13(r->n_lval))
+ expand(p, 0, "\tadd AL,AR,A1\t\t! add const\n");
+ else
+ expand(p, 0, "\tsetx AR,A3,A2\t\t! add const\n"
+ "\tadd AL,A2,A1\n");
+ break;
+ case 'B': /* Subtract const. */
+ if (ISPTR(l->n_type) && l->n_rval == FP)
+ r->n_lval -= V9BIAS;
+
+ if (SIMM13(r->n_lval))
+ expand(p, 0, "\tsub AL,AR,A1\t\t! subtract const\n");
+ else
+ expand(p, 0, "\tsetx AR,A3,A2\t\t! subtract const\n"
+ "\tsub AL,A2,A1\n");
+ break;
+ case 'C': /* Load constant to register. */
+ if (ISPTR(p->n_type))
+ expand(p, 0,
+ "\tsethi %h44(AL),A1\t\t! load label\n"
+ "\tor A1,%m44(AL),A1\n"
+ "\tsllx A1,12,A1\n"
+ "\tor A1,%l44(AL),A1\n");
+ else if (SIMM13(p->n_lval))
+ expand(p, 0, "\tor %g0,AL,A1\t\t\t! load const\n");
+ else
+ expand(p, 0, "\tsetx AL,A2,A1\t\t! load const\n");
+ break;
+ case 'F': /* Floating-point comparison, cf. hopcode(). */
+ switch (p->n_op) {
+ case EQ: str = "fbe"; break;
+ case NE: str = "fbne"; break;
+ case ULE:
+ case LE: str = "fbule"; break;
+ case ULT:
+ case LT: str = "fbul"; break;
+ case UGE:
+ case GE: str = "fbuge"; break;
+ case UGT:
+ case GT: str = "fbug"; break;
+ /* XXX
+ case PLUS: str = "add"; break;
+ case MINUS: str = "sub"; break;
+ case AND: str = "and"; break;
+ case OR: str = "or"; break;
+ case ER: str = "xor"; break;*/
+ default:
+ comperr("unknown float code: %d", p->n_op);
+ return;
+ }
+ printf(str);
+ break;
+
+ case 'Q': /* Structure assignment. */
+ /* TODO Check if p->n_stsize is small and use a few ldx's
+ to move the struct instead of memcpy. The equiv.
+ could be done on all the architectures. */
+ if (l->n_rval != O0)
+ printf("\tmov %s,%s\n", rnames[l->n_rval], rnames[O0]);
+ if (SIMM13(p->n_stsize))
+ printf("\tor %%g0,%d,%%o2\n", p->n_stsize);
+ else
+ printf("\tsetx %d,%%g1,%%o2\n", p->n_stsize);
+ printf("\tcall memcpy\t\t\t! struct assign (dest, src, len)\n");
+ printf("\tnop\n");
+ break;
+ default:
+ cerror("unknown zzzcode call: %c", c);
+ }
+}
+
+int
+rewfld(NODE * p)
+{
+ return (1);
+}
+
+int
+fldexpand(NODE *p, int cookie, char **cp)
+{
+ printf("XXX fldexpand called\n"); /* XXX */
+ return 1;
+}
+
+int
+flshape(NODE * p)
+{
+ return SRREG;
+}
+
+int
+shtemp(NODE * p)
+{
+ return 0;
+}
+
+
+void
+adrcon(CONSZ val)
+{
+}
+
+void
+conput(FILE * fp, NODE * p)
+{
+ if (p->n_op != ICON) {
+ comperr("conput got bad op: %s", copst(p->n_op));
+ return;
+ }
+
+ if (p->n_name[0] != '\0') {
+ fprintf(fp, "%s", p->n_name);
+ if (p->n_lval > 0)
+ fprintf(fp, "+");
+ if (p->n_lval)
+ fprintf(fp, "%lld", p->n_lval);
+ } else
+ fprintf(fp, CONFMT, p->n_lval);
+}
+
+void
+insput(NODE * p)
+{
+ comperr("insput");
+}
+
+void
+upput(NODE *p, int size)
+{
+ comperr("upput");
+}
+
+void
+adrput(FILE * io, NODE * p)
+{
+ int64_t off;
+
+ if (p->n_op == FLD) {
+ printf("adrput a FLD\n");
+ p = p->n_left;
+ }
+
+ if (p->n_op == UMUL && p->n_right == 0)
+ p = p->n_left;
+
+ off = p->n_lval;
+
+ switch (p->n_op) {
+ case NAME:
+ if (p->n_name[0] != '\0')
+ fputs(p->n_name, io);
+ if (off > 0)
+ fprintf(io, "+");
+ if (off != 0)
+ fprintf(io, CONFMT, off);
+ return;
+ case OREG:
+ fprintf(io, "%s", rnames[p->n_rval]);
+ if (p->n_rval == FP)
+ off += V9BIAS;
+ if (p->n_rval == SP)
+ off += V9BIAS + V9RESERVE;
+ if (off > 0)
+ fprintf(io, "+");
+ if (off)
+ fprintf(io, "%lld", off);
+ return;
+ case ICON:
+ /* addressable value of the constant */
+ conput(io, p);
+ return;
+ case REG:
+ fputs(rnames[p->n_rval], io);
+ return;
+ case FUNARG:
+ /* We do something odd and store the stack offset in n_rval. */
+ fprintf(io, "%d", V9BIAS + V9RESERVE + p->n_rval);
+ return;
+ default:
+ comperr("bad address, %s, node %p", copst(p->n_op), p);
+ return;
+ }
+}
+
+void
+cbgen(int o, int lab)
+{
+}
+
+void
+myreader(struct interpass * ipole)
+{
+}
+
+void
+mycanon(NODE * p)
+{
+}
+
+void
+myoptim(struct interpass * ipole)
+{
+}
+
+void
+rmove(int s, int d, TWORD t)
+{
+ printf("\t");
+
+ if (t == FLOAT) printf("fmovs");
+ else if (t == DOUBLE) printf("fmovd");
+ else printf("mov");
+
+ printf(" %s,%s\t\t\t! rmove()\n", rnames[s], rnames[d]);
+}
+
+int
+gclass(TWORD t)
+{
+ if (t == FLOAT)
+ return CLASSB;
+ if (t == DOUBLE)
+ return CLASSC;
+ return CLASSA;
+}
+
+void
+lastcall(NODE *p)
+{
+}
+
+int
+special(NODE *p, int shape)
+{
+ return SRNOPE;
+}
+
+void mflags(char *str)
+{
+}
+
+int
+COLORMAP(int c, int *r)
+{
+ int num=0;
+
+ switch (c) {
+ case CLASSA:
+ num += r[CLASSA];
+ return num < 32;
+ case CLASSB:
+ num += r[CLASSB];
+ num += 2*r[CLASSC];
+ return num < 32;;
+ case CLASSC:
+ num += r[CLASSC];
+ num += 2*r[CLASSB];
+ return num < 17;
+ case CLASSD:
+ return 0;
+ default:
+ comperr("COLORMAP: unknown class: %d", c);
+ return 0;
+ }
+}
+/*
+ * 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;
+}
--- /dev/null
+++ usr.bin/pcc/sparc64/code.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2008 David Crawshaw <david at zentus.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "pass1.h"
+
+void
+defloc(struct symtab *sp)
+{
+ static char *loctbl[] = { "text", "data", "rodata" };
+ static int lastloc = -1;
+ TWORD t;
+ int s;
+
+ t = sp->stype;
+ s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA;
+ if (s != lastloc)
+ printf("\n\t.section \".%s\"\n", loctbl[s]);
+ lastloc = s;
+ if (s == PROG)
+ return;
+
+ switch (DEUNSIGN(sp->stype)) {
+ case CHAR: s = 1;
+ case SHORT: s = 2;
+ case INT:
+ case UNSIGNED: s = 4;
+ default: s = 8;
+ }
+ printf("\t.align %d\n", s);
+
+ if (sp->sclass == EXTDEF)
+ printf("\t.global %s\n", sp->soname);
+ if (sp->slevel == 0) {
+ printf("\t.type %s,#object\n", sp->soname);
+ printf("\t.size %s," CONFMT "\n", sp->soname,
+ tsize(sp->stype, sp->sdf, sp->ssue) / SZCHAR);
+ printf("%s:\n", sp->soname);
+ } else
+ printf(LABFMT ":\n", sp->soffset);
+}
+
+void
+efcode()
+{
+ /* XXX */
+}
+
+void
+bfcode(struct symtab **sp, int cnt)
+{
+ int i, off;
+ NODE *p, *q;
+ struct symtab *sym;
+
+ /* Process the first six arguments. */
+ for (i=0; i < cnt && i < 6; i++) {
+ sym = sp[i];
+ q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue);
+ q->n_rval = RETREG_PRE(sym->stype) + i;
+ p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
+ sym->soffset = regno(p);
+ sym->sflags |= STNODE;
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+ }
+
+ /* Process the remaining arguments. */
+ for (off = V9RESERVE; i < cnt; i++) {
+ sym = sp[i];
+ p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
+ off = ALIGN(off, (tlen(p) - 1));
+ sym->soffset = off * SZCHAR;
+ off += tlen(p);
+ p = buildtree(ASSIGN, p, nametree(sym));
+ sym->soffset = regno(p->n_left);
+ sym->sflags |= STNODE;
+ ecomp(p);
+ }
+}
+
+void
+bccode()
+{
+ SETOFF(autooff, SZINT);
+}
+
+void
+ejobcode(int flag)
+{
+}
+
+void
+bjobcode()
+{
+}
+
+/*
+ * The first six 64-bit arguments are saved in the registers O0 to O5,
+ * which become I0 to I5 after the "save" instruction moves the register
+ * window. Arguments 7 and up must be saved on the stack to %sp+BIAS+176.
+ *
+ * For a pretty picture, see Figure 3-16 in the SPARC Compliance Def 2.4.
+ */
+static NODE *
+moveargs(NODE *p, int *regp, int *stacksize)
+{
+ NODE *r, *q;
+
+ if (p->n_op == CM) {
+ p->n_left = moveargs(p->n_left, regp, stacksize);
+ r = p->n_right;
+ } else {
+ r = p;
+ }
+
+ /* XXX more than six FP args can and should be passed in registers. */
+ if (*regp > 5 && r->n_op != STARG) {
+ /* We are storing the stack offset in n_rval. */
+ r = block(FUNARG, r, NIL, r->n_type, r->n_df, r->n_sue);
+ /* Make sure we are appropriately aligned. */
+ *stacksize = ALIGN(*stacksize, (tlen(r) - 1));
+ r->n_rval = *stacksize;
+ *stacksize += tlen(r);
+ } else if (r->n_op == STARG)
+ cerror("op STARG in moveargs");
+ else {
+ q = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_sue);
+
+ /*
+ * The first six non-FP arguments go in the registers O0 - O5.
+ * Float arguments are stored in %fp1, %fp3, ..., %fp29, %fp31.
+ * Double arguments are stored in %fp0, %fp2, ..., %fp28, %fp30.
+ * A non-fp argument still increments register, eg.
+ * test(int a, int b, float b)
+ * takes %o0, %o1, %fp5.
+ */
+ if (q->n_type == FLOAT)
+ q->n_rval = F0 + (*regp++ * 2) + 1;
+ else if (q->n_type == DOUBLE)
+ q->n_rval = D0 + *regp++;
+ else if (q->n_type == LDOUBLE)
+ cerror("long double support incomplete");
+ else
+ q->n_rval = O0 + (*regp)++;
+
+ r = buildtree(ASSIGN, q, r);
+ }
+
+ if (p->n_op == CM) {
+ p->n_right = r;
+ return p;
+ }
+
+ return r;
+}
+
+NODE *
+funcode(NODE *p)
+{
+ NODE *r, *l;
+ int reg = 0, stacksize = 0;
+
+ r = l = 0;
+
+ p->n_right = moveargs(p->n_right, ®, &stacksize);
+
+ /*
+ * This is a particularly gross and inefficient way to handle
+ * argument overflows. First, we calculate how much stack space
+ * we need in moveargs(). Then we assign it by moving %sp, make
+ * the function call, and then move %sp back.
+ *
+ * What we should be doing is getting the maximum of all the needed
+ * stacksize values to the prologue and doing it all in the "save"
+ * instruction.
+ */
+ if (stacksize != 0) {
+ stacksize = V9STEP(stacksize); /* 16-bit alignment. */
+
+ r = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ r->n_lval = 0;
+ r->n_rval = SP;
+ r = block(MINUS, r, bcon(stacksize), INT, 0, MKSUE(INT));
+
+ l = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ l->n_lval = 0;
+ l->n_rval = SP;
+ r = buildtree(ASSIGN, l, r);
+
+ p = buildtree(COMOP, r, p);
+
+ r = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ r->n_lval = 0;
+ r->n_rval = SP;
+ r = block(PLUS, r, bcon(stacksize), INT, 0, MKSUE(INT));
+
+ l = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ l->n_lval = 0;
+ l->n_rval = SP;
+ r = buildtree(ASSIGN, l, r);
+
+ p = buildtree(COMOP, p, r);
+
+ }
+ return p;
+}
+
+int
+fldal(unsigned int t)
+{
+ uerror("illegal field type");
+ return ALINT;
+}
+
+void
+fldty(struct symtab *p)
+{
+}
+
+int
+mygenswitch(int num, TWORD type, struct swents **p, int n)
+{
+ return 0;
+}
--- /dev/null
+++ usr.bin/pcc/sparc64/local.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2008 David Crawshaw <david at zentus.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "pass1.h"
+
+NODE *
+clocal(NODE *p)
+{
+ struct symtab *sp;
+ int op;
+ NODE *r, *l;
+
+ op = p->n_op;
+ sp = p->n_sp;
+ l = p->n_left;
+ r = p->n_right;
+
+#ifdef PCC_DEBUG
+ if (xdebug) {
+ printf("clocal in: %p, %s\n", p, copst(op));
+ fwalk(p, eprint, 0);
+ }
+#endif
+
+ switch (op) {
+
+ case NAME:
+ if (sp->sclass == PARAM || sp->sclass == AUTO) {
+ /*
+ * Use a fake structure reference to
+ * write out frame pointer offsets.
+ */
+ l = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
+ l->n_lval = 0;
+ l->n_rval = FP;
+ r = p;
+ p = stref(block(STREF, l, r, 0, 0, 0));
+ }
+ break;
+ case PCONV: /* Remove what PCONVs we can. */
+ if (l->n_op == SCONV)
+ break;
+
+ if (l->n_op == ICON || (ISPTR(p->n_type) && ISPTR(l->n_type))) {
+ l->n_type = p->n_type;
+ l->n_qual = p->n_qual;
+ l->n_df = p->n_df;
+ l->n_sue = p->n_sue;
+ nfree(p);
+ p = l;
+ }
+ break;
+
+ case SCONV:
+ /* Remove redundant conversions. */
+ if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
+ btdims[p->n_type].suesize == btdims[l->n_type].suesize &&
+ p->n_type != FLOAT && p->n_type != DOUBLE &&
+ l->n_type != FLOAT && l->n_type != DOUBLE &&
+ l->n_type != DOUBLE && p->n_type != LDOUBLE) {
+ if (l->n_op == NAME || l->n_op == UMUL ||
+ l->n_op == TEMP) {
+ l->n_type = p->n_type;
+ nfree(p);
+ p = l;
+ break;
+ }
+ }
+
+ /* Convert floating point to int before to char or short. */
+ if ((l->n_type == FLOAT || l->n_type == DOUBLE || l->n_type == LDOUBLE)
+ && (DEUNSIGN(p->n_type) == CHAR || DEUNSIGN(p->n_type) == SHORT)) {
+ p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue);
+ p->n_left->n_type = INT;
+ break;
+ }
+
+ /* Transform constants now. */
+ if (l->n_op != ICON)
+ break;
+
+ if (ISPTR(p->n_type)) {
+ l->n_type = p->n_type;
+ nfree(p);
+ p = l;
+ break;
+ }
+
+ switch (p->n_type) {
+ case BOOL: l->n_lval = (l->n_lval != 0); break;
+ case CHAR: l->n_lval = (char)l->n_lval; break;
+ case UCHAR: l->n_lval = l->n_lval & 0377; break;
+ case SHORT: l->n_lval = (short)l->n_lval; break;
+ case USHORT: l->n_lval = l->n_lval & 0177777; break;
+ case UNSIGNED: l->n_lval = l->n_lval & 0xffffffff; break;
+ case INT: l->n_lval = (int)l->n_lval; break;
+ case ULONG:
+ case ULONGLONG: l->n_lval = l->n_lval; break;
+ case LONG:
+ case LONGLONG: l->n_lval = (long long)l->n_lval; break;
+ case FLOAT:
+ case DOUBLE:
+ case LDOUBLE:
+ l->n_op = FCON;
+ l->n_dcon = l->n_lval;
+ break;
+ case VOID:
+ break;
+ default:
+ cerror("sconv type unknown %d", p->n_type);
+ }
+
+ l->n_type = p->n_type;
+ nfree(p);
+ p = l;
+ break;
+
+ case PMCONV:
+ case PVCONV:
+ if (r->n_op != ICON)
+ cerror("converting bad type");
+ nfree(p);
+ p = buildtree(op == PMCONV ? MUL : DIV, l, r);
+ break;
+
+ case FORCE:
+ /* Put attached value into the return register. */
+ p->n_op = ASSIGN;
+ p->n_right = p->n_left;
+ p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
+ p->n_left->n_rval = RETREG_PRE(p->n_type);
+ break;
+ }
+
+#ifdef PCC_DEBUG
+ if (xdebug) {
+ printf("clocal out: %p, %s\n", p, copst(op));
+ fwalk(p, eprint, 0);
+ }
+#endif
+
+ return p;
+}
+
+void
+myp2tree(NODE *p)
+{
+ struct symtab *sp;
+
+ if (p->n_op != FCON)
+ return;
+
+ sp = tmpalloc(sizeof(struct symtab));
+ sp->sclass = STATIC;
+ sp->slevel = 1;
+ sp->soffset = getlab();
+ sp->sflags = 0;
+ sp->stype = p->n_type;
+ sp->squal = (CON >> TSHIFT);
+
+ defloc(sp);
+ ninval(0, btdims[p->n_type].suesize, p);
+
+ p->n_op = NAME;
+ p->n_lval = 0;
+ p->n_sp = sp;
+}
+
+int
+andable(NODE *p)
+{
+ return 1;
+}
+
+void
+cendarg()
+{
+ autooff = AUTOINIT;
+}
+
+int
+cisreg(TWORD t)
+{
+ /* SPARCv9 registers are all 64-bits wide. */
+ return 1;
+}
+
+NODE *
+offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
+{
+ return bcon(off / SZCHAR);
+}
+
+void
+spalloc(NODE *t, NODE *p, OFFSZ off)
+{
+}
+
+void
+inwstring(struct symtab *sp)
+{
+}
+
+void
+instring(struct symtab *sp)
+{
+ char *s, *str;
+
+ defloc(sp);
+ str = sp->sname;
+
+ printf("\t.ascii \"");
+ for (s = str; *s != 0; *s++) {
+ if (*s++ == '\\')
+ esccon(&s);
+ if (s - str > 60) {
+ fwrite(str, 1, s - str, stdout);
+ printf("\"\n\t.ascii \"");
+ str = s;
+ }
+ }
+ fwrite(str, 1, s - str, stdout);
+ printf("\\0\"\n");
+}
+
+void
+zbits(OFFSZ off, int fsz)
+{
+}
+
+void
+infld(CONSZ off, int fsz, CONSZ val)
+{
+}
+
+void
+ninval(CONSZ off, int fsz, NODE *p)
+{
+ TWORD t;
+ struct symtab *sp;
+ union { float f; double d; int i; long long l; } u;
+
+ t = p->n_type;
+ sp = p->n_sp;
+
+ if (ISPTR(t))
+ t = LONGLONG;
+
+ if (p->n_op != ICON && p->n_op != FCON)
+ cerror("ninval: not a constant");
+ if (p->n_op == ICON && sp != NULL && DEUNSIGN(t) != LONGLONG)
+ cerror("ninval: not constant");
+
+ switch (t) {
+ case CHAR:
+ case UCHAR:
+ printf("\t.byte %d\n", (int)p->n_lval & 0xff);
+ break;
+ case SHORT:
+ case USHORT:
+ printf("\t.half %d\n", (int)p->n_lval &0xffff);
+ break;
+ case BOOL:
+ p->n_lval = (p->n_lval != 0); /* FALLTHROUGH */
+ case INT:
+ case UNSIGNED:
+ printf("\t.long " CONFMT "\n", p->n_lval);
+ break;
+ case LONG:
+ case ULONG:
+ case LONGLONG:
+ case ULONGLONG:
+ printf("\t.xword %lld", p->n_lval);
+ if (sp != 0) {
+ if (sp->sclass == STATIC && sp->slevel > 0)
+ printf("+" LABFMT, sp->soffset);
+ else
+ printf("+%s", exname(sp->soname));
+ }
+ printf("\n");
+ break;
+ case FLOAT:
+ u.f = (float)p->n_dcon;
+ printf("\t.long %d\n", u.i);
+ break;
+ case DOUBLE:
+ u.d = (double)p->n_dcon;
+ printf("\t.xword %lld\n", u.l);
+ break;
+ }
+}
+
+char *
+exname(char *p)
+{
+ return p ? p : "";
+}
+
+TWORD
+ctype(TWORD type)
+{
+ return type;
+}
+
+void
+calldec(NODE *p, NODE *q)
+{
+}
+
+void
+extdec(struct symtab *q)
+{
+}
+
+void
+defzero(struct symtab *sp)
+{
+ int off = (tsize(sp->stype, sp->sdf, sp->ssue) + SZCHAR - 1) / SZCHAR;
+ printf("\t.comm ");
+ if (sp->slevel == 0)
+ printf("%s,%d\n", exname(sp->soname), off);
+ else
+ printf(LABFMT ",%d\n", sp->soffset, off);
+}
+
+int
+mypragma(char **ary)
+{
+ return 0;
+}
+
+void
+fixdef(struct symtab *sp)
+{
+}
+
+void
+pass1_lastchance(struct interpass *ip)
+{
+}
+
More information about the Midnightbsd-cvs
mailing list