ref: 8c20e677d7728c5120feb182e4d4195a7571fa71
parent: 1ce079ecedd0b95c5c367572b5872a78d2a309ba
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sun Oct 6 09:54:31 EDT 2019
[scc] Rename scc directory to cc This makes the directory layout more orthogonal and similar to classical unix layout.
--- a/src/cmd/Makefile
+++ b/src/cmd/Makefile
@@ -13,7 +13,7 @@
$(BINDIR)/objcopy\
$(BINDIR)/addr2line\
-DIRS = ld as scc
+DIRS = ld as cc
LIBMACH = $(LIBDIR)/libmach.a
LIBSCC = $(LIBDIR)/libscc.a
--- /dev/null
+++ b/src/cmd/cc/Makefile
@@ -1,0 +1,14 @@
+.POSIX:
+
+PROJECTDIR = ../../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+DIRS = cc1 cc2 $(DRIVER)
+
+all: $(DIRS)
+
+$(DIRS): FORCE
+ +@cd $@ && $(MAKE)
+
+dep clean:
+ $(FORALL)
--- /dev/null
+++ b/src/cmd/cc/cc1/Makefile
@@ -1,0 +1,38 @@
+.POSIX:
+
+PROJECTDIR = ../../../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+OBJS = types.o \
+ decl.o \
+ lex.o \
+ error.o \
+ symbol.o \
+ main.o \
+ expr.o \
+ code.o \
+ stmt.o \
+ cpp.o \
+ fold.o \
+ init.o \
+ builtin.o \
+
+TARGET = $(LIBEXEC)/cc1-amd64-sysv \
+ $(LIBEXEC)/cc1-arm64-sysv \
+ $(LIBEXEC)/cc1-i386-sysv \
+ $(LIBEXEC)/cc1-z80-scc \
+
+all: $(TARGET)
+
+$(TARGET): $(LIBDIR)/libscc.a
+
+dep: inc-dep
+
+clean:
+ rm -f target/*/*.o
+
+include target/amd64-sysv/arch.mk
+include target/arm64-sysv/arch.mk
+include target/i386-sysv/arch.mk
+include target/z80-scc/arch.mk
+include deps.mk
--- /dev/null
+++ b/src/cmd/cc/cc1/TODO
@@ -1,0 +1,14 @@
+* Implement bitfields
+* Rewrite error recovery code, and ensure correct state after recovery
+* Parse correctly all integer and float constants
+* Add C99 features (almost all the new features of C99 are missed)
+* Add correct emit for any kind of constant
+* Add warning when some ANSI limit is violated.
+* Free memory in emit after some error happened.
+* Rewrite initializers to deal with the idea of "current object"
+* Add some test about pointer airthmetic.
+* Merge all the definitions of the same string
+* Do not assign identifierss until symbols are emitted. This change will
+ avoid identifiers that are not emitted.
+* Fix assignation abbreviations. They fail whe lhs type is smaller than
+ the type in rhs
--- /dev/null
+++ b/src/cmd/cc/cc1/builtin.c
@@ -1,0 +1,119 @@
+#include <stdio.h>
+
+#include <scc/scc.h>
+#include "cc1.h"
+
+static Node *
+builtin_va_arg(Symbol *sym)
+{
+ Node *np, *ap;
+ Type *tp;
+
+ ap = assign();
+ expect(',');
+ tp = typename();
+
+ if (!valid_va_list(ap->type)) {
+ errorp("incorrect parameters for va_arg");
+ goto error;
+ }
+ if (tp == booltype ||
+ tp == chartype || tp == uchartype || tp == schartype ||
+ tp == shortype || tp == ushortype) {
+ warn("bool, char and short are promoted to int when passed through '...'");
+ tp = (tp->prop & TSIGNED) ? inttype : uinttype;
+ }
+
+ np = node(OBUILTIN, tp, ap, NULL);
+ np->sym = sym;
+ return np;
+
+error:
+ return constnode(zero);
+}
+
+static Node *
+builtin_va_copy(Symbol *sym)
+{
+ Node *np, *src, *dst;
+
+ dst = assign();
+ expect(',');
+ src = assign();
+
+ if (!valid_va_list(dst->type) || !valid_va_list(src->type)) {
+ errorp("incorrect parameters for va_copy");
+ return constnode(zero);
+ }
+
+ np = node(OBUILTIN, voidtype, dst, src);
+ np->sym = sym;
+ return np;
+}
+
+static Node *
+builtin_va_start(Symbol *sym)
+{
+ Node *np, *ap, *last;
+ Symbol **p;
+ Type *tp;
+
+ ap = assign();
+ expect(',');
+ last = assign();
+ if (last->op != OSYM)
+ goto error;
+
+ if (!valid_va_list(ap->type) || !(last->sym->flags&SDECLARED))
+ goto error;
+
+ for (p = curfun->u.pars; p && *p != last->sym; ++p)
+ ;
+ if (!p || *p == NULL || p[1] == NULL || p[1]->type != ellipsistype)
+ warn("second parameter of 'va_start' not last named argument");
+
+ tp = last->type;
+ if (tp == booltype ||
+ tp == chartype || tp == uchartype || tp == schartype ||
+ tp == shortype || tp == ushortype) {
+ warn("last parameter before '...' must not be bool, char or short");
+ }
+
+ np = node(OBUILTIN, voidtype, ap, last);
+ np->sym = sym;
+ return np;
+
+error:
+ errorp("incorrect parameters for va_start");
+ return constnode(zero);
+}
+
+static Node *
+builtin_va_end(Symbol *sym)
+{
+ Node *ap, *np;
+
+ ap = assign();
+
+ if (!valid_va_list(ap->type)) {
+ errorp("incorrect parameters for va_end");
+ return constnode(zero);
+ }
+
+ np = node(OBUILTIN, voidtype, ap, NULL);
+ np->sym = sym;
+ return np;
+}
+
+void
+ibuilts(void)
+{
+ struct builtin built[] = {
+ {"__builtin_va_arg", builtin_va_arg},
+ {"__builtin_va_copy", builtin_va_copy},
+ {"__builtin_va_start", builtin_va_start},
+ {"__builtin_va_end", builtin_va_end},
+ {NULL}
+ };
+ builtins(built);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/cc1.h
@@ -1,0 +1,496 @@
+#define INPUTSIZ LINESIZ
+
+#define GLOBALCTX 0
+#define PARAMCTX 1
+
+#define NR_USWITCHES 20
+
+/*
+ * Definition of enumerations
+ */
+enum {
+ NOALLOC,
+ ALLOC
+};
+
+enum typeprops {
+ TDEFINED = 1 << 0, /* type defined */
+ TSIGNED = 1 << 1, /* signedness of the type */
+ TINTEGER = 1 << 2, /* the type is INT of enum */
+ TARITH = 1 << 3, /* the type is INT, ENUM or FLOAT */
+ TAGGREG = 1 << 4, /* the type is struct or union */
+ TK_R = 1 << 5, /* this is a K&R-function */
+ TELLIPSIS= 1 << 6, /* this function has an ellipsis par */
+ TFUNDEF = 1 << 7, /* function definition */
+};
+
+enum inputtype {
+ IMACRO = 1 << 0, /* macro expansion type */
+ IFILE = 1 << 1, /* input file type */
+ ISTDIN = 1 << 2, /* stdin type */
+ IEOF = 1 << 3, /* EOF mark */
+ ITYPE = IMACRO | IFILE | ISTDIN,
+};
+
+/* data type letters */
+enum ns {
+ L_INT8 = 'C',
+ L_INT16 = 'I',
+ L_INT32 = 'W',
+ L_INT64 = 'Q',
+ L_UINT8 = 'K',
+ L_UINT16 = 'N',
+ L_UINT32 = 'Z',
+ L_UINT64 = 'O',
+ L_BOOL = 'B',
+
+ L_FLOAT = 'J',
+ L_DOUBLE = 'D',
+ L_LDOUBLE = 'H',
+
+ L_ELLIPSIS = 'E',
+ L_VOID = '0',
+ L_POINTER = 'P',
+ L_FUNCTION = 'F',
+ L_ARRAY = 'V',
+ L_UNION = 'U',
+ L_STRUCT = 'S',
+ L_VA_ARG = '1',
+};
+
+/* recovery points */
+enum {
+ END_DECL,
+ END_LDECL,
+ END_COMP,
+ END_COND
+};
+
+/* type constructors */
+enum typeop {
+ FTN = 1,
+ PTR,
+ ARY,
+ KRFTN
+};
+
+/* namespaces */
+enum namespaces {
+ NS_DUMMY,
+ NS_IDEN,
+ NS_TAG,
+ NS_LABEL,
+ NS_CPP,
+ NS_KEYWORD,
+ NS_CPPCLAUSES,
+ NS_STRUCTS
+};
+
+/* symbol flags */
+enum {
+ SAUTO = 1 << 0,
+ SREGISTER = 1 << 1,
+ SDECLARED = 1 << 2,
+ SFIELD = 1 << 3,
+ SEXTERN = 1 << 4,
+ SUSED = 1 << 5,
+ SCONSTANT = 1 << 6,
+ SGLOBAL = 1 << 7,
+ SPRIVATE = 1 << 8,
+ SLOCAL = 1 << 9,
+ SEMITTED = 1 << 10,
+ SDEFINED = 1 << 11,
+ SSTRING = 1 << 12,
+ STYPEDEF = 1 << 13,
+ SINITLST = 1 << 14,
+ SHASINIT = 1 << 15
+};
+
+/* node flags */
+enum {
+ NLVAL = 1 << 0,
+ NCONST = 1 << 1,
+ NEFFECT = 1 << 2
+};
+
+/* lexer mode, compiler or preprocessor directive */
+enum {
+ CCMODE,
+ CPPMODE
+};
+
+/* input tokens */
+enum tokens {
+ CONST = 1 << 0, /* type qualifier tokens are used as flags */
+ RESTRICT = 1 << 1,
+ VOLATILE = 1 << 2,
+ INLINE = 1 << 3,
+ TQUALIFIER = 1 << 7, /* this value is picked outside of ASCII range */
+ TYPE,
+ IDEN,
+ SCLASS,
+ CONSTANT,
+ STRING,
+ SIZEOF,
+ INDIR,
+ INC,
+ DEC,
+ SHL,
+ SHR,
+ LE,
+ GE,
+ EQ,
+ NE,
+ AND,
+ OR,
+ MUL_EQ,
+ DIV_EQ,
+ MOD_EQ,
+ ADD_EQ,
+ SUB_EQ,
+ AND_EQ,
+ XOR_EQ,
+ OR_EQ,
+ SHL_EQ,
+ SHR_EQ,
+ ELLIPSIS,
+ CASE,
+ DEFAULT,
+ IF,
+ ELSE,
+ SWITCH,
+ WHILE,
+ DO,
+ FOR,
+ GOTO,
+ VOID,
+ FLOAT,
+ INT,
+ BOOL,
+ VA_LIST,
+ STRUCT,
+ UNION,
+ CHAR,
+ DOUBLE,
+ SHORT,
+ LONG,
+ LLONG,
+ COMPLEX,
+ TYPEDEF,
+ EXTERN,
+ STATIC,
+ AUTO,
+ REGISTER,
+ ENUM,
+ TYPEIDEN,
+ UNSIGNED,
+ SIGNED,
+ CONTINUE,
+ BREAK,
+ RETURN,
+ DEFINE,
+ INCLUDE,
+ LINE,
+ PRAGMA,
+ ERROR,
+ IFDEF,
+ ELIF,
+ IFNDEF,
+ UNDEF,
+ ENDIF,
+ BUILTIN,
+ EOFTOK
+};
+
+/* operations */
+enum op {
+ OADD,
+ OMUL,
+ OSUB,
+ OINC,
+ ODEC,
+ ODIV,
+ OMOD,
+ OSHL,
+ OSHR,
+ OBAND,
+ OBXOR,
+ OBOR,
+ OSNEG,
+ ONEG,
+ OCPL,
+ OAND,
+ OOR,
+ OEQ,
+ ONE,
+ OLT,
+ OGE,
+ OLE,
+ OGT,
+ OASSIGN,
+ OA_MUL,
+ OA_DIV,
+ OA_MOD,
+ OA_ADD,
+ OA_SUB,
+ OA_SHL,
+ OA_SHR,
+ OA_AND,
+ OA_XOR,
+ OA_OR,
+ OADDR,
+ OCOMMA,
+ OCAST,
+ OPTR,
+ OSYM,
+ OASK,
+ OCOLON,
+ OFIELD,
+ OLABEL,
+ ODEFAULT,
+ OCASE,
+ OJUMP,
+ OBRANCH,
+ OEXPR,
+ OEFUN,
+ OELOOP,
+ OBLOOP,
+ OFUN,
+ OPAR,
+ OCALL,
+ OCALLE,
+ ORET,
+ ODECL,
+ OBSWITCH,
+ OESWITCH,
+ OINIT,
+ OBUILTIN,
+ OTYP,
+};
+
+/*
+ * Definition of structures
+ */
+typedef struct type Type;
+typedef struct symbol Symbol;
+typedef struct swtch Switch;
+typedef struct node Node;
+typedef struct input Input;
+
+struct limits {
+ union {
+ TUINT i;
+ TFLOAT f;
+ } max;
+ union {
+ TUINT i;
+ TFLOAT f;
+ } min;
+};
+
+struct builtin {
+ char *str;
+ Node *(*fun)(Symbol *);
+};
+
+struct keyword {
+ char *str;
+ unsigned char token, value;
+};
+
+struct type {
+ unsigned char op; /* type builder operator */
+ unsigned char ns; /* namespace for struct members */
+ short id; /* type id, used in dcls */
+ char letter; /* letter of the type */
+ unsigned char prop; /* type properties */
+ unsigned char align; /* align of the type */
+ unsigned long size; /* sizeof the type */
+ Type *type; /* base type */
+ Symbol *tag; /* symbol of the strug tag */
+ union {
+ Type **pars; /* Function type parameters */
+ Symbol **fields; /* fields of aggregate type */
+ } p;
+ union {
+ unsigned char rank; /* convertion rank */
+ TINT elem; /* number of type parameters */
+ } n;
+ Type *next; /* local list pointer */
+ Type *h_next; /* hash collision list */
+};
+
+struct symbol {
+ unsigned char ctx;
+ unsigned char hide;
+ char ns;
+ unsigned short id;
+ unsigned short flags;
+ char *name;
+ Type *type;
+ unsigned char token;
+ union {
+ TINT i;
+ TUINT u;
+ TFLOAT f;
+ char *s;
+ unsigned char token;
+ Node **init;
+ Symbol **pars;
+ Node *(*fun)(Symbol *);
+ } u;
+ struct symbol *next;
+ struct symbol *hash;
+};
+
+struct node {
+ unsigned char op;
+ unsigned char flags;
+ Type *type;
+ Symbol *sym;
+ struct node *left, *right;
+};
+
+struct swtch {
+ short nr;
+ char hasdef;
+};
+
+struct yystype {
+ Symbol *sym;
+ unsigned char token;
+};
+
+#ifdef stdin
+struct input {
+ char flags;
+ unsigned lineno;
+ char *filenam;
+ FILE *fp;
+ Symbol *hide;
+ char *line, *begin, *p;
+ struct input *next;
+};
+#endif
+
+/* error.c */
+extern void error(char *fmt, ...);
+extern void warn(char *fmt, ...);
+extern void unexpected(void);
+extern void errorp(char *fmt, ...);
+extern void cpperror(char *fmt, ...);
+extern Type *deftype(Type *tp);
+
+/* types.c */
+extern int eqtype(Type *tp1, Type *tp2, int eqflag);
+extern Type *ctype(int type, int sign, int size);
+extern Type *mktype(Type *tp, int op, TINT nelem, Type *data[]);
+extern Type *duptype(Type *base);
+extern struct limits *getlimits(Type *tp);
+extern void typesize(Type *tp);
+extern void flushtypes(void);
+
+/* symbol.c */
+extern void dumpstab(Symbol **tbl, char *msg);
+extern Symbol *lookup(int ns, char *name, int alloc);
+extern Symbol *nextsym(Symbol *sym, int ns);
+extern Symbol *install(int ns, Symbol *sym);
+extern Symbol *newsym(int ns, char *name);
+extern void pushctx(void), popctx(void);
+extern void killsym(Symbol *sym);
+extern Symbol *newlabel(void);
+extern void keywords(struct keyword *key, int ns);
+extern void builtins(struct builtin *builts);
+extern Symbol *newstring(char *s, size_t len);
+extern unsigned newid(void);
+
+/* stmt.c */
+extern void compound(Symbol *lbreak, Symbol *lcont, Switch *sw);
+
+/* decl.c */
+extern Type *typename(void);
+extern void decl(void);
+
+/* lex.c */
+extern int ahead(void);
+extern int next(void);
+extern void expect(int tok);
+extern void discard(void);
+extern void addinput(char *fname, Symbol *hide, char *buffer);
+extern void delinput(void);
+extern void setsafe(int type);
+extern void ilex(void);
+extern void setloc(char *fname, unsigned line);
+#define accept(t) ((yytoken == (t)) ? next() : 0)
+
+/* code.c */
+extern void prtree(Node *np);
+extern void emit(int, void *);
+extern Node *node(int op, Type *tp, Node *left, Node *rigth);
+extern Node *varnode(Symbol *sym);
+extern Node *constnode(Symbol *sym);
+extern Node *sizeofnode(Type *tp);
+extern void freetree(Node *np);
+extern void icode(void);
+#define BTYPE(np) ((np)->type->op)
+
+/* fold.c */
+extern Node *simplify(Node *np);
+extern TUINT ones(int nbytes);
+
+/* expr.c */
+extern Node *decay(Node *), *negate(Node *np), *assign(void);
+extern Node *convert(Node *np, Type *tp1, int iscast);
+extern Node *constexpr(void), *condexpr(int neg), *expr(void);
+extern int isnodecmp(int op);
+extern int negop(int op);
+extern int cmpnode(Node *np, TUINT val);
+
+/* init.c */
+extern void initializer(Symbol *sym, Type *tp);
+extern Node *initlist(Type *tp);
+
+/* cpp.c */
+extern void icpp(void);
+extern int cpp(void);
+extern int expand(char *begin, Symbol *sym);
+extern void incdir(char *dir);
+extern void outcpp(void);
+extern void defdefine(char *macro, char *val, char *source);
+extern void undefmacro(char *s);
+extern void ppragmaln(void);
+
+/* builtin.c */
+extern void ibuilts(void);
+
+/* arch.c */
+extern void iarch(void);
+extern int valid_va_list(Type *tp);
+
+/*
+ * Definition of global variables
+ */
+extern struct yystype yylval;
+extern char yytext[];
+extern int yytoken;
+extern unsigned short yylen;
+extern int disexpand;
+extern unsigned cppctx;
+extern Input *input;
+extern int lexmode, namespace;
+extern int onlycpp, onlyheader;
+extern unsigned curctx;
+extern Symbol *curfun, *zero, *one;
+extern char *infile;
+extern unsigned lineno;
+extern char filenam[];
+
+extern Type *voidtype, *pvoidtype, *booltype,
+ *uchartype, *chartype, *schartype,
+ *uinttype, *inttype,
+ *sizettype, *pdifftype,
+ *ushortype, *shortype,
+ *longtype, *ulongtype,
+ *ullongtype, *llongtype,
+ *floattype, *doubletype, *ldoubletype,
+ *ellipsistype, *va_list_type, *va_type;
--- /dev/null
+++ b/src/cmd/cc/cc1/code.c
@@ -1,0 +1,549 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <scc/scc.h>
+#include "cc1.h"
+
+static void emitbin(int, void *),
+ emitcast(int, void *),
+ emitsym(int, void *),
+ emitexp(int, void *),
+ emitsymid(int, void *),
+ emittext(int, void *),
+ emitfun(int, void *),
+ emitdcl(int, void *),
+ emitinit(int, void *),
+ emittype(int, void *),
+ emitbuilt(int, void *);
+
+char *optxt[] = {
+ [OADD] = "+",
+ [OSUB] = "-",
+ [OMUL] = "*",
+ [OINC] = ":i",
+ [ODEC] = ":d",
+ [OPTR] = "@",
+ [OMOD] = "%",
+ [ODIV] = "/",
+ [OSHL] = "l",
+ [OSHR] = "r",
+ [OLT] = "<",
+ [OGT] = ">",
+ [OGE] = "]",
+ [OLE] = "[",
+ [OEQ] = "=",
+ [ONE] = "!",
+ [OBAND] = "&",
+ [OBXOR] = "^",
+ [OBOR] = "|",
+ [OASSIGN] = ":",
+ [OA_MUL] = ":*",
+ [OA_DIV] = ":/",
+ [OA_MOD] = ":%",
+ [OA_ADD] = ":+",
+ [OA_SUB] = ":-",
+ [OA_SHL] = ":l",
+ [OA_SHR] = ":r",
+ [OA_AND] = ":&",
+ [OA_XOR] = ":^",
+ [OA_OR] = ":|",
+ [OADDR] = "'",
+ [OSNEG] = "_",
+ [ONEG] = "n",
+ [OCPL] = "~",
+ [OAND] = "a",
+ [OOR] = "o",
+ [OASK] = "?",
+ [OCOMMA] = ",",
+ [OLABEL] = "L%d\n",
+ [ODEFAULT] = "\tf\tL%d\n",
+ [OBSWITCH] = "\ts",
+ [OESWITCH] = "\tt\tL%d\n",
+ [OCASE] = "\tv\tL%d",
+ [OJUMP] = "\tj\tL%d\n",
+ [OBRANCH] = "\ty\tL%d",
+ [OEFUN] = "}\n",
+ [OELOOP] = "\tb\n",
+ [OBLOOP] = "\te\n",
+ [ORET] = "\th",
+ [OPAR] = "p",
+ [OCALL] = "c",
+ [OCALLE] = "z",
+ [OFIELD] = "."
+};
+
+void (*opcode[])(int, void *) = {
+ [OADD] = emitbin,
+ [OSUB] = emitbin,
+ [OMUL] = emitbin,
+ [OINC] = emitbin,
+ [ODEC] = emitbin,
+ [OPTR] = emitbin,
+ [OMOD] = emitbin,
+ [ODIV] = emitbin,
+ [OSHL] = emitbin,
+ [OSHR] = emitbin,
+ [OLT] = emitbin,
+ [OGT] = emitbin,
+ [OGE] = emitbin,
+ [OLE] = emitbin,
+ [OEQ] = emitbin,
+ [ONE] = emitbin,
+ [OBAND] = emitbin,
+ [OBXOR] = emitbin,
+ [OBOR] = emitbin,
+ [OASSIGN] = emitbin,
+ [OA_MUL] = emitbin,
+ [OA_DIV] = emitbin,
+ [OA_MOD] = emitbin,
+ [OA_ADD] = emitbin,
+ [OA_SUB] = emitbin,
+ [OA_SHL] = emitbin,
+ [OA_SHR] = emitbin,
+ [OA_AND] = emitbin,
+ [OA_XOR] = emitbin,
+ [OA_OR] = emitbin,
+ [OADDR] = emitbin,
+ [OSNEG] = emitbin,
+ [ONEG] = emitbin,
+ [OCPL] = emitbin,
+ [OAND] = emitbin,
+ [OOR] = emitbin,
+ [OCOMMA] = emitbin,
+ [OCAST] = emitcast,
+ [OSYM] = emitsym,
+ [OASK] = emitbin,
+ [OCOLON] = emitbin,
+ [OFIELD]= emitbin,
+ [OEXPR] = emitexp,
+ [OLABEL] = emitsymid,
+ [ODEFAULT] = emitsymid,
+ [OCASE] = emitsymid,
+ [OJUMP] = emitsymid,
+ [OBRANCH] = emitsymid,
+ [OEFUN] = emittext,
+ [OELOOP] = emittext,
+ [OBLOOP] = emittext,
+ [OFUN] = emitfun,
+ [ORET] = emittext,
+ [ODECL] = emitdcl,
+ [OBSWITCH] = emittext,
+ [OESWITCH] = emitsymid,
+ [OPAR] = emitbin,
+ [OCALL] = emitbin,
+ [OCALLE] = emitbin,
+ [OINIT] = emitinit,
+ [OBUILTIN] = emitbuilt,
+ [OTYP] = emittype,
+};
+
+static FILE *outfp;
+
+void
+icode(void)
+{
+ outfp = stdout;
+}
+
+void
+freetree(Node *np)
+{
+ if (!np)
+ return;
+ freetree(np->left);
+ freetree(np->right);
+ free(np);
+}
+
+static void
+emitnode(Node *np)
+{
+ if (np)
+ (*opcode[np->op])(np->op, np);
+}
+
+void
+prtree(Node *np)
+{
+ outfp = stderr;
+ fputs("DBG prtree", outfp);
+ emitnode(np);
+ putc('\n', outfp);
+ outfp = stdout;
+}
+
+void
+emit(int op, void *arg)
+{
+ extern int failure;
+
+ if (failure || onlycpp || onlyheader)
+ return;
+ (*opcode[op])(op, arg);
+}
+
+static void
+emitvar(Symbol *sym)
+{
+ int c;
+ short flags = sym->flags;
+
+ if (flags & SLOCAL)
+ c = 'T';
+ else if (flags & SPRIVATE)
+ c = 'Y';
+ else if (flags & SGLOBAL)
+ c = 'G';
+ else if (flags & SREGISTER)
+ c = 'R';
+ else if (flags & SFIELD)
+ c = 'M';
+ else if (flags & SEXTERN)
+ c = 'X';
+ else
+ c = 'A';
+ fprintf(outfp, "%c%u", c, sym->id);
+}
+
+static void
+emitconst(Node *np)
+{
+ Symbol *sym = np->sym;
+ Type *tp = np->type;
+ TUINT u;
+
+ switch (tp->op) {
+ case PTR:
+ case INT:
+ case ENUM:
+ u = (tp->prop & TSIGNED) ? (TUINT) sym->u.i : sym->u.u;
+ fprintf(outfp,
+ "#%c%llX",
+ np->type->letter,
+ (long long) u & ones(tp->size));
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+emitsym(int op, void *arg)
+{
+ Node *np = arg;
+
+ if ((np->sym->flags & SINITLST) == 0) {
+ /*
+ * When we have a compound literal we are going
+ * to call to emitnode for every element of it,
+ * and it means that we will have two '\t'
+ * for the first element
+ */
+ putc('\t', outfp);
+ }
+ (np->flags & NCONST) ? emitconst(np) : emitvar(np->sym);
+}
+
+static void
+emitletter(Type *tp)
+{
+ int letter;
+
+ letter = (tp->prop&TELLIPSIS) ? 'E' : tp->letter;
+ putc(letter, outfp);
+ switch (tp->op) {
+ case ARY:
+ case STRUCT:
+ case UNION:
+ fprintf(outfp, "%u", tp->id);
+ }
+}
+
+static void
+emittype(int op, void *arg)
+{
+ TINT n;
+ Symbol **sp;
+ char *tag;
+ Type *tp = arg;
+
+ if (!(tp->prop & TDEFINED))
+ return;
+
+ switch (tp->op) {
+ case ARY:
+ emitletter(tp);
+ putc('\t', outfp);
+ emitletter(tp->type);
+ fprintf(outfp,
+ "\t#%c%llX\n",
+ sizettype->letter, (long long) tp->n.elem);
+ return;
+ case UNION:
+ case STRUCT:
+ emitletter(tp);
+ tag = tp->tag->name;
+ fprintf(outfp,
+ "\t\"%s\t#%c%lX\t#%c%X\n",
+ (tag) ? tag : "",
+ sizettype->letter,
+ tp->size,
+ sizettype->letter,
+ tp->align);
+ n = tp->n.elem;
+ for (sp = tp->p.fields; n-- > 0; ++sp)
+ emit(ODECL, *sp);
+ break;
+ case PTR:
+ case FTN:
+ case ENUM:
+ return;
+ default:
+ abort();
+ }
+}
+
+static void
+emitstring(Symbol *sym, Type *tp)
+{
+ char *bp, *s, *lim;
+ int n;
+
+ bp = sym->u.s;
+ lim = &sym->u.s[tp->n.elem];
+ while (bp < lim) {
+ s = bp;
+ while (bp < lim && isprint(*bp))
+ ++bp;
+ if ((n = bp - s) > 1)
+ fprintf(outfp, "\t#\"%.*s\n", n, s);
+ else
+ bp = s;
+ if (bp == lim)
+ break;
+ do {
+ fprintf(outfp,
+ "\t#%c%02X\n",
+ chartype->letter, (*bp++) & 0xFF);
+ } while (bp < lim && !isprint(*bp));
+ }
+}
+
+static void
+emitdesig(Node *np, Type *tp)
+{
+ Symbol *sym;
+ size_t n; /* TODO: This should be SIZET */
+ Node *aux;
+ Type *p;
+
+ if (!np) {
+ sym = NULL;
+ } else {
+ if (!np->sym)
+ goto emit_expression;
+ sym = np->sym;
+ if (sym->flags & SSTRING) {
+ emitstring(sym, tp);
+ return;
+ }
+ if ((sym->flags & SINITLST) == 0)
+ goto emit_expression;
+ }
+
+ switch (tp->op) {
+ case PTR:
+ case INT:
+ case ENUM:
+ aux = (sym) ? *sym->u.init : convert(constnode(zero), tp, 0);
+ emitexp(OEXPR, aux);
+ break;
+ case UNION:
+ n = tp->n.elem-1;
+ aux = (sym) ? sym->u.init[0] : NULL;
+ emitdesig(aux, aux->type);
+ break;
+ case STRUCT:
+ case ARY:
+ for (n = 0; n < tp->n.elem; ++n) {
+ aux = (sym) ? sym->u.init[n] : NULL;
+ p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type;
+ emitdesig(aux, p);
+ }
+ break;
+ default:
+ abort();
+ }
+
+ if (sym) {
+ free(sym->u.init);
+ sym->u.init = NULL;
+ }
+ freetree(np);
+ return;
+
+emit_expression:
+ emitexp(OEXPR, np);
+}
+
+static void
+emitinit(int op, void *arg)
+{
+ Node *np = arg;
+
+ fputs("\t(\n", outfp);
+ emitdesig(np, np->type);
+ fputs(")\n", outfp);
+}
+
+static void
+emitdcl(int op, void *arg)
+{
+ Symbol *sym = arg;
+
+ if (sym->flags & SEMITTED)
+ return;
+ emitvar(sym);
+ putc('\t', outfp);
+ if (sym->type->op == FTN) {
+ emitletter(sym->type->type);
+ putc('\t', outfp);
+ }
+ emitletter(sym->type);
+ fprintf(outfp, "\t\"%s", (sym->name) ? sym->name : "");
+ if (sym->flags & SFIELD)
+ fprintf(outfp, "\t#%c%llX", sizettype->letter, sym->u.i);
+ sym->flags |= SEMITTED;
+ if ((sym->flags & SHASINIT) == 0)
+ putc('\n', outfp);
+}
+
+static void
+emitcast(int op, void *arg)
+{
+ Node *np = arg, *lp = np->left;
+
+ emitnode(lp);
+ if (np->type != voidtype)
+ fprintf(outfp, "\tg%c", np->type->letter);
+}
+
+static void
+emitbin(int op, void *arg)
+{
+ Node *np = arg;
+ char *s;
+
+ emitnode(np->left);
+ emitnode(np->right);
+ if ((s = optxt[op]) != NULL) { /* do not print in OCOLON case */
+ fprintf(outfp, "\t%s", s);
+ emitletter(np->type);
+ }
+}
+
+static void
+emitbuilt(int op, void *arg)
+{
+ Node *np = arg;
+
+ emitnode(np->left);
+ emitnode(np->right);
+ fprintf(outfp, "\t\"%s\tm", np->sym->name);
+ emitletter(np->type);
+}
+
+
+static void
+emitexp(int op, void *arg)
+{
+ Node *np = arg;
+
+ emitnode(np);
+ putc('\n', outfp);
+ freetree(np);
+}
+
+static void
+emitfun(int op, void *arg)
+{
+ Symbol *sym = arg, **sp;
+
+ emitdcl(op, arg);
+ fputs("{\n", outfp);
+
+ for (sp = sym->u.pars; sp && *sp; ++sp)
+ emit(ODECL, *sp);
+ fputs("\\\n", outfp);
+}
+
+static void
+emittext(int op, void *arg)
+{
+ fputs(optxt[op], outfp);
+}
+
+static void
+emitsymid(int op, void *arg)
+{
+ Symbol *sym = arg;
+ fprintf(outfp, optxt[op], sym->id);
+}
+
+Node *
+node(int op, Type *tp, Node *lp, Node *rp)
+{
+ Node *np;
+
+ np = xmalloc(sizeof(*np));
+ np->op = op;
+ np->type = tp;
+ np->sym = NULL;
+ np->flags = 0;
+ np->left = lp;
+ np->right = rp;
+
+ if (lp)
+ np->flags |= lp->flags & NEFFECT;
+ if (rp)
+ np->flags |= rp->flags & NEFFECT;
+ return np;
+}
+
+Node *
+varnode(Symbol *sym)
+{
+ Node *np;
+ Type *tp = sym->type;
+
+ np = node(OSYM, sym->type, NULL, NULL);
+ np->type = sym->type;
+ np->flags = (tp->op != FTN && tp->op != ARY) ? NLVAL : 0;
+ np->sym = sym;
+ return np;
+}
+
+Node *
+constnode(Symbol *sym)
+{
+ Node *np;
+
+ np = node(OSYM, sym->type, NULL, NULL);
+ np->type = sym->type;
+ np->flags = NCONST;
+ np->sym = sym;
+ return np;
+}
+
+Node *
+sizeofnode(Type *tp)
+{
+ Symbol *sym;
+
+ sym = newsym(NS_IDEN, NULL);
+ sym->type = sizettype;
+ sym->u.i = tp->size;
+ return constnode(sym);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/cpp.c
@@ -1,0 +1,838 @@
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+static char *argp, *macroname;
+static unsigned arglen;
+static unsigned ncmdlines;
+static Symbol *symline, *symfile;
+static unsigned char ifstatus[NR_COND];
+static int cppoff;
+static struct items dirinclude;
+
+unsigned cppctx;
+int disexpand;
+
+void
+defdefine(char *macro, char *val, char *source)
+{
+ char *def, *fmt = "#define %s %s\n";
+ Symbol dummy = {.flags = SDECLARED};
+
+ if (!val)
+ val = "";
+ def = xmalloc(strlen(fmt) + strlen(macro) + strlen(val));
+
+ sprintf(def, fmt, macro, val);
+ lineno = ++ncmdlines;
+ addinput(source, &dummy, def);
+ cpp();
+ delinput();
+}
+
+void
+undefmacro(char *s)
+{
+ killsym(lookup(NS_CPP, s, NOALLOC));
+}
+
+void
+icpp(void)
+{
+ static char sdate[14], stime[11];
+ struct tm *tm;
+ time_t t;
+ static char **bp, *list[] = {
+ "__STDC__",
+ "__STDC_HOSTED__",
+ "__SCC__",
+ NULL
+ };
+ static struct keyword keys[] = {
+ {"define", DEFINE, DEFINE},
+ {"include", INCLUDE, INCLUDE},
+ {"line", LINE, LINE},
+ {"ifdef", IFDEF, IFDEF},
+ {"if", IF, IF},
+ {"elif", ELIF, ELIF},
+ {"else", ELSE, ELSE},
+ {"ifndef", IFNDEF, IFNDEF},
+ {"endif", ENDIF, ENDIF},
+ {"undef", UNDEF, UNDEF},
+ {"pragma", PRAGMA, PRAGMA},
+ {"error", ERROR, ERROR},
+ {NULL, 0, 0}
+ };
+
+ keywords(keys, NS_CPPCLAUSES);
+
+ t = time(NULL);
+ tm = localtime(&t);
+ strftime(sdate, sizeof(sdate), "\"%b %d %Y\"", tm);
+ strftime(stime, sizeof(stime), "\"%H:%M:%S\"", tm);
+ defdefine("__DATE__", sdate, "built-in");
+ defdefine("__TIME__", stime, "built-in");
+ defdefine("__STDC_VERSION__", STDC_VERSION, "built-in");
+ defdefine("__LINE__", NULL, "built-in");
+ defdefine("__FILE__", NULL, "built-in");
+
+ symline = lookup(NS_CPP, "__LINE__", ALLOC);
+ symfile = lookup(NS_CPP, "__FILE__", ALLOC);
+
+ for (bp = list; *bp; ++bp)
+ defdefine(*bp, "1", "built-in");
+
+ ncmdlines = 0;
+}
+
+static void
+nextcpp(void)
+{
+ next();
+ if (yytoken == EOFTOK)
+ error("unterminated argument list invoking macro \"%s\"",
+ macroname);
+ if (yylen + 1 > arglen)
+ error("argument overflow invoking macro \"%s\"",
+ macroname);
+ if (yytoken == IDEN)
+ yylval.sym->flags |= SUSED;
+ memcpy(argp, yytext, yylen);
+ argp += yylen;
+ *argp++ = ' ';
+ arglen -= yylen + 1;
+}
+
+static void
+paren(void)
+{
+ for (;;) {
+ nextcpp();
+ switch (yytoken) {
+ case ')':
+ return;
+ case '(':
+ paren();
+ break;
+ }
+ }
+}
+
+static void
+parameter(void)
+{
+ for (;;) {
+ nextcpp();
+ switch (yytoken) {
+ case ')':
+ case ',':
+ argp -= 3; /* remove " , " or " ) "*/
+ *argp++ = '\0';
+ return;
+ case '(':
+ paren();
+ break;
+ }
+ }
+}
+
+static int
+parsepars(char *buffer, char **listp, int nargs)
+{
+ int n;
+
+ if (nargs == -1)
+ return -1;
+ if (ahead() != '(' && nargs > 0)
+ return 0;
+
+ disexpand = 1;
+ next();
+ n = 0;
+ argp = buffer;
+ arglen = INPUTSIZ;
+ if (ahead() == ')') {
+ next();
+ } else {
+ do {
+ *listp++ = argp;
+ parameter();
+ } while (++n < NR_MACROARG && yytoken == ',');
+ }
+ if (yytoken != ')')
+ error("incorrect macro function-alike invocation");
+ disexpand = 0;
+
+ if (n == NR_MACROARG)
+ error("too many parameters in macro \"%s\"", macroname);
+ if (n != nargs) {
+ error("macro \"%s\" received %d arguments, but it takes %d",
+ macroname, n, nargs);
+ }
+
+ return 1;
+}
+
+static size_t
+copymacro(char *buffer, char *s, size_t bufsiz, char *arglist[])
+{
+ int delim, prevc, c;
+ char *p, *arg, *bp = buffer;
+ size_t size;
+
+ for (prevc = '\0'; c = *s; prevc = c, ++s) {
+ switch (c) {
+ case '$':
+ while (bp[-1] == ' ')
+ --bp, ++bufsiz;
+ while (s[1] == ' ')
+ ++s;
+ case '#':
+ break;
+ case '\'':
+ delim = '\'';
+ goto search_delim;
+ case '\"':
+ delim = '"';
+ search_delim:
+ for (p = s; *++s != delim; )
+ ;
+ size = s - p + 1;
+ if (size > bufsiz)
+ goto expansion_too_long;
+ memcpy(bp, p, size);
+ bufsiz -= size;
+ bp += size;
+ break;
+ case '@':
+ if (prevc == '#')
+ bufsiz -= 2;
+ arg = arglist[atoi(++s)];
+ size = strlen(arg);
+ if (size > bufsiz)
+ goto expansion_too_long;
+ if (prevc == '#')
+ *bp++ = '"';
+ memcpy(bp, arg, size);
+ bp += size;
+ if (prevc == '#')
+ *bp++ = '"';
+ bufsiz -= size;
+ s += 2;
+ break;
+ default:
+ if (bufsiz-- == 0)
+ goto expansion_too_long;
+ *bp++ = c;
+ break;
+ }
+ }
+ *bp = '\0';
+
+ return bp - buffer;
+
+expansion_too_long:
+ error("macro expansion of \"%s\" too long", macroname);
+}
+
+int
+expand(char *begin, Symbol *sym)
+{
+ size_t elen;
+ int n, i;
+ char *s = sym->u.s;
+ char *arglist[NR_MACROARG], arguments[INPUTSIZ], buffer[INPUTSIZ];
+
+ macroname = sym->name;
+ if (sym == symfile) {
+ elen = sprintf(buffer, "\"%s\" ", filenam);
+ goto substitute;
+ }
+ if (sym == symline) {
+ elen = sprintf(buffer, "%d ", lineno);
+ goto substitute;
+ }
+ if (!s)
+ return 1;
+
+ n = atoi(s);
+ if (!parsepars(arguments, arglist, n))
+ return 0;
+ for (i = 0; i < n; ++i)
+ DBG("MACRO par%d:%s", i, arglist[i]);
+
+ elen = copymacro(buffer, s+3, INPUTSIZ-1, arglist);
+
+substitute:
+ DBG("MACRO '%s' expanded to :'%s'", macroname, buffer);
+ buffer[elen] = '\0';
+ addinput(filenam, sym, xstrdup(buffer));
+
+ return 1;
+}
+
+static int
+getpars(Symbol *args[NR_MACROARG])
+{
+ int n, c;
+ Symbol *sym;
+
+ c = *input->p;
+ next();
+ if (c != '(')
+ return -1;
+ next(); /* skip the '(' */
+ if (accept(')'))
+ return 0;
+
+ n = 0;
+ do {
+ if (n == NR_MACROARG) {
+ cpperror("too many parameters in macro");
+ return NR_MACROARG;
+ }
+ if (accept(ELLIPSIS)) {
+ args[n++] = NULL;
+ break;
+ }
+ if (yytoken != IDEN) {
+ cpperror("macro arguments must be identifiers");
+ return NR_MACROARG;
+ }
+ sym = install(NS_IDEN, yylval.sym);
+ sym->flags |= SUSED;
+ args[n++] = sym;
+ next();
+ } while (accept(','));
+ expect(')');
+
+ return n;
+}
+
+static int
+getdefs(Symbol *args[NR_MACROARG], int nargs, char *bp, size_t bufsiz)
+{
+ Symbol **argp;
+ size_t len;
+ int prevc = 0, ispar;
+
+ if (yytoken == '$') {
+ cpperror("'##' cannot appear at either ends of a macro expansion");
+ return 0;
+ }
+
+ for (;;) {
+ ispar = 0;
+ if (yytoken == IDEN && nargs >= 0) {
+ for (argp = args; argp < &args[nargs]; ++argp) {
+ if (*argp == yylval.sym)
+ break;
+ }
+ if (argp != &args[nargs]) {
+ sprintf(yytext, "@%02d@", (int) (argp - args));
+ ispar = 1;
+ }
+ }
+ if (prevc == '#' && !ispar) {
+ cpperror("'#' is not followed by a macro parameter");
+ return 0;
+ }
+ if (yytoken == '\n')
+ break;
+
+ if ((len = strlen(yytext)) >= bufsiz) {
+ cpperror("macro too long");
+ return 0;
+ }
+ if (yytoken == '$') {
+ *bp++ = '$';
+ --bufsiz;
+ } else {
+ memcpy(bp, yytext, len);
+ bp += len;
+ bufsiz -= len;
+ }
+ if ((prevc = yytoken) != '#') {
+ *bp++ = ' ';
+ --bufsiz;
+ }
+ next();
+ }
+ *bp = '\0';
+ return 1;
+}
+
+static void
+define(void)
+{
+ Symbol *sym,*args[NR_MACROARG];
+ char buff[LINESIZ+1];
+ int n;
+
+ if (cppoff)
+ return;
+
+ namespace = NS_CPP;
+ next();
+
+ if (yytoken != IDEN) {
+ cpperror("macro names must be identifiers");
+ return;
+ }
+ sym = yylval.sym;
+ if (sym->flags & SDECLARED) {
+ warn("'%s' redefined", yytext);
+ free(sym->u.s);
+ } else {
+ sym = install(NS_CPP, sym);
+ sym->flags |= SDECLARED|SSTRING;
+ }
+
+ namespace = NS_IDEN; /* Avoid polution in NS_CPP */
+ if ((n = getpars(args)) == NR_MACROARG)
+ goto delete;
+ if (n > 0 && !args[n-1]) /* it is a variadic function */
+ --n;
+ sprintf(buff, "%02d#", n);
+ if (!getdefs(args, n, buff+3, LINESIZ-3))
+ goto delete;
+ sym->u.s = xstrdup(buff);
+ DBG("MACRO '%s' defined as '%s'", sym->name, buff);
+ return;
+
+delete:
+ killsym(sym);
+}
+
+void
+incdir(char *dir)
+{
+ if (!dir || *dir == '\0')
+ die("cc1: incorrect -I flag");
+ newitem(&dirinclude, dir);
+}
+
+static int
+includefile(char *dir, char *file, size_t filelen)
+{
+ size_t dirlen;
+ char path[FILENAME_MAX];
+
+ if (!dir) {
+ dirlen = 0;
+ if (filelen > FILENAME_MAX-1)
+ return 0;
+ } else {
+ dirlen = strlen(dir);
+ if (dirlen + filelen > FILENAME_MAX-2)
+ return 0;
+ memcpy(path, dir, dirlen);
+ if (dir[dirlen-1] != '/')
+ path[dirlen++] = '/';
+ }
+ memcpy(path+dirlen, file, filelen);
+ path[dirlen + filelen] = '\0';
+
+ addinput(path, NULL, NULL);
+ return 1;
+}
+
+static char *
+cwd(char *buf)
+{
+ char *p, *s = filenam;
+ size_t len;
+
+ if ((p = strrchr(s, '/')) == NULL)
+ return NULL;
+ if ((len = p - s) >= FILENAME_MAX)
+ die("cc1: current work directory too long");
+ memcpy(buf, s, len);
+ buf[len] = '\0';
+ return buf;
+}
+
+static void
+include(void)
+{
+ char dir[FILENAME_MAX], file[FILENAME_MAX], *p, **bp;
+ size_t filelen;
+ int n;
+
+ if (cppoff)
+ return;
+
+ namespace = NS_IDEN;
+ next();
+
+ switch (*yytext) {
+ case '<':
+ if ((p = strchr(input->begin, '>')) == NULL || p[-1] == '<')
+ goto bad_include;
+ filelen = p - input->begin;
+ if (filelen >= FILENAME_MAX)
+ goto too_long;
+ memcpy(file, input->begin, filelen);
+ file[filelen] = '\0';
+
+ input->begin = input->p = p+1;
+ if (next() != '\n')
+ goto trailing_characters;
+
+ break;
+ case '"':
+ if (yylen < 3)
+ goto bad_include;
+ filelen = yylen-2;
+ if (filelen >= FILENAME_MAX)
+ goto too_long;
+ memcpy(file, yytext+1, filelen);
+ file[filelen] = '\0';
+
+ if (next() != '\n')
+ goto trailing_characters;
+
+ if (includefile(cwd(dir), file, filelen))
+ goto its_done;
+ break;
+ default:
+ goto bad_include;
+ }
+
+ n = dirinclude.n;
+ for (bp = dirinclude.s; n--; ++bp) {
+ if (includefile(*bp, file, filelen))
+ goto its_done;
+ }
+ cpperror("included file '%s' not found", file);
+
+its_done:
+ return;
+
+trailing_characters:
+ cpperror("trailing characters after preprocessor directive");
+ return;
+
+too_long:
+ cpperror("too long file name in #include");
+ return;
+
+bad_include:
+ cpperror("#include expects \"FILENAME\" or <FILENAME>");
+ return;
+}
+
+static void
+line(void)
+{
+ long n;
+ char *endp, *fname;
+
+ if (cppoff)
+ return;
+
+ disexpand = 0;
+ next();
+ n = strtol(yytext, &endp, 10);
+ if (n <= 0 || n > USHRT_MAX || *endp != '\0') {
+ cpperror("first parameter of #line is not a positive integer");
+ return;
+ }
+
+ next();
+ if (yytoken == '\n') {
+ fname = NULL;
+ } else {
+ if (*yytext != '\"' || yylen == 1) {
+ cpperror("second parameter of #line is not a valid filename");
+ return;
+ }
+ fname = yylval.sym->u.s;
+ }
+ setloc(fname, n - 1);
+ if (yytoken != '\n')
+ next();
+}
+
+static void
+pragma(void)
+{
+ if (cppoff)
+ return;
+ next();
+ warn("ignoring pragma '%s'", yytext);
+ *input->p = '\0';
+ next();
+}
+
+static void
+usererr(void)
+{
+ if (cppoff)
+ return;
+ cpperror("#error %s", input->p);
+ *input->p = '\0';
+ next();
+}
+
+static void
+ifclause(int negate, int isifdef)
+{
+ Symbol *sym;
+ unsigned n;
+ int status;
+ Node *expr;
+
+ if (cppctx == NR_COND-1)
+ error("too many nesting levels of conditional inclusion");
+
+ n = cppctx++;
+ namespace = NS_CPP;
+ next();
+
+ if (isifdef) {
+ if (yytoken != IDEN) {
+ cpperror("no macro name given in #%s directive",
+ (negate) ? "ifndef" : "ifdef");
+ return;
+ }
+ sym = yylval.sym;
+ next();
+ status = (sym->flags & SDECLARED) != 0;
+ if (!status)
+ killsym(sym);
+ } else {
+ /* TODO: catch recovery here */
+ if ((expr = constexpr()) == NULL) {
+ cpperror("parameter of #if is not an integer constant expression");
+ return;
+ }
+ status = expr->sym->u.i != 0;
+ freetree(expr);
+ }
+
+ if (negate)
+ status = !status;
+ if ((ifstatus[n] = status) == 0)
+ ++cppoff;
+}
+
+static void
+cppif(void)
+{
+ disexpand = 0;
+ ifclause(0, 0);
+}
+
+static void
+ifdef(void)
+{
+ ifclause(0, 1);
+}
+
+static void
+ifndef(void)
+{
+ ifclause(1, 1);
+}
+
+static void
+elseclause(void)
+{
+ int status;
+
+ if (cppctx == 0) {
+ cpperror("#else without #ifdef/ifndef");
+ return;
+ }
+
+ status = ifstatus[cppctx-1];
+ ifstatus[cppctx-1] = !status;
+ cppoff += (status) ? 1 : -1;
+}
+
+static void
+cppelse(void)
+{
+ elseclause();
+ next();
+}
+
+static void
+elif(void)
+{
+ elseclause();
+ if (ifstatus[cppctx-1]) {
+ --cppctx;
+ cppif();
+ }
+}
+
+static void
+endif(void)
+{
+ if (cppctx == 0)
+ error("#endif without #if");
+ if (!ifstatus[--cppctx])
+ --cppoff;
+ next();
+}
+
+static void
+undef(void)
+{
+ if (cppoff)
+ return;
+
+ namespace = NS_CPP;
+ next();
+ if (yytoken != IDEN) {
+ error("no macro name given in #undef directive");
+ return;
+ }
+ killsym(yylval.sym);
+ next();
+}
+
+int
+cpp(void)
+{
+ static struct {
+ unsigned char token;
+ void (*fun)(void);
+ } *bp, clauses [] = {
+ {DEFINE, define},
+ {INCLUDE, include},
+ {LINE, line},
+ {IFDEF, ifdef},
+ {IF, cppif},
+ {ELIF, elif},
+ {IFNDEF, ifndef},
+ {ELSE, cppelse},
+ {ENDIF, endif},
+ {UNDEF, undef},
+ {PRAGMA, pragma},
+ {ERROR, usererr},
+ {0, NULL}
+ };
+ int ns;
+ char *p;
+
+ for (p = input->p; isspace(*p); ++p)
+ ;
+
+ if (*p != '#')
+ return cppoff;
+ input->p = p+1;
+
+ disexpand = 1;
+ lexmode = CPPMODE;
+ ns = namespace;
+ namespace = NS_CPPCLAUSES;
+ next();
+ namespace = NS_IDEN;
+
+ for (bp = clauses; bp->token && bp->token != yytoken; ++bp)
+ ;
+ if (!bp->token) {
+ errorp("incorrect preprocessor directive '%s'", yytext);
+ goto error;
+ }
+
+ DBG("CPP %s", yytext);
+
+ pushctx(); /* create a new context to avoid polish */
+ (*bp->fun)(); /* the current context, and to get all */
+ popctx(); /* the symbols freed at the end */
+
+ /*
+ * #include changes the content of input->line, so the correctness
+ * of the line must be checked in the own include(), and we have
+ * to skip this tests. For the same reason include() is the only
+ * function which does not prepare the next token
+ */
+ if (yytoken != '\n' && !cppoff && bp->token != INCLUDE)
+ errorp("trailing characters after preprocessor directive");
+
+error:
+ disexpand = 0;
+ lexmode = CCMODE;
+ namespace = ns;
+
+ return 1;
+}
+
+void
+ppragmaln(void)
+{
+ static char file[FILENAME_MAX];
+ static unsigned nline;
+ char *s;
+
+ putchar('\n');
+ if (strcmp(file, filenam)) {
+ strcpy(file, filenam);
+ s = "#line %u \"%s\"\n";
+ } else if (nline+1 != lineno) {
+ s = "#line %u\n";
+ } else {
+ s = "";
+ }
+ nline = lineno;
+ printf(s, nline, file);
+}
+
+void
+outcpp(void)
+{
+ int c;
+ char *s, *t;
+
+ for (next(); yytoken != EOFTOK; next()) {
+ if (onlyheader)
+ continue;
+ if (yytoken != STRING) {
+ printf("%s ", yytext);
+ continue;
+ }
+ for (s = yytext; c = *s; ++s) {
+ switch (c) {
+ case '\n':
+ t = "\\n";
+ goto print_str;
+ case '\v':
+ t = "\\v";
+ goto print_str;
+ case '\b':
+ t = "\\b";
+ goto print_str;
+ case '\t':
+ t = "\\t";
+ goto print_str;
+ case '\a':
+ t = "\\a";
+ print_str:
+ fputs(t, stdout);
+ break;
+ case '\\':
+ putchar('\\');
+ default:
+ if (!isprint(c))
+ printf("\\x%x", c);
+ else
+ putchar(c);
+ break;
+ }
+ }
+ putchar(' ');
+ }
+ putchar('\n');
+}
+
--- /dev/null
+++ b/src/cmd/cc/cc1/decl.c
@@ -1,0 +1,966 @@
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+#define NOSCLASS 0
+
+#define NOREP 0
+#define REP 1
+#define QUIET 1
+#define NOQUIET 0
+
+#define NR_DCL_TYP (NR_DECLARATORS+NR_FUNPARAM)
+#define NR_DCL_SYM (NR_DECLARATORS+NR_FUNPARAM+1)
+
+struct declarators {
+ unsigned nr;
+ unsigned ns;
+ struct decl *dcl;
+ unsigned nr_types;
+ Type **tpars;
+ Symbol **pars;
+ struct declarator {
+ unsigned char op;
+ TINT nelem;
+ Symbol *sym;
+ Type **tpars;
+ Symbol **pars;
+ } d [NR_DECLARATORS];
+};
+
+struct decl {
+ unsigned ns;
+ int sclass;
+ int qualifier;
+ Symbol *sym;
+ Type *type;
+ Type *parent;
+ Symbol **pars;
+ Symbol *bufpars[NR_DCL_SYM];
+ Type *buftpars[NR_DCL_TYP];
+};
+
+
+static void
+endfundcl(Type *tp, Symbol **pars)
+{
+ if (tp->prop&TK_R && *pars)
+ warn("parameter names (without types) in function declaration");
+ /*
+ * avoid non used warnings in prototypes
+ */
+ while (*pars)
+ (*pars++)->flags |= SUSED;
+ popctx();
+}
+
+static void
+push(struct declarators *dp, int op, ...)
+{
+ va_list va;
+ unsigned n;
+ struct declarator *p;
+
+ va_start(va, op);
+ if ((n = dp->nr++) == NR_DECLARATORS)
+ error("too many declarators");
+
+ p = &dp->d[n];
+ p->op = op;
+ p->tpars = NULL;
+
+ switch (op) {
+ case ARY:
+ p->nelem = va_arg(va, TINT);
+ break;
+ case KRFTN:
+ case FTN:
+ p->nelem = va_arg(va, unsigned);
+ p->tpars = va_arg(va, Type **);
+ p->pars = va_arg(va, Symbol **);
+ break;
+ case IDEN:
+ p->sym = va_arg(va, Symbol *);
+ break;
+ }
+ va_end(va);
+}
+
+static int
+pop(struct declarators *dp, struct decl *dcl)
+{
+ struct declarator *p;
+
+ if (dp->nr == 0)
+ return 0;
+
+ p = &dp->d[--dp->nr];
+ if (p->op == IDEN) {
+ dcl->sym = p->sym;
+ return 1;
+ }
+
+ if (dcl->type->op == FTN)
+ endfundcl(dcl->type, dcl->pars);
+ dcl->pars = p->pars;
+
+ dcl->type = mktype(dcl->type, p->op, p->nelem, p->tpars);
+ return 1;
+}
+
+static void
+arydcl(struct declarators *dp)
+{
+ Node *np = NULL;
+ TINT n = 0;
+
+ expect('[');
+ if (yytoken != ']') {
+ if ((np = constexpr()) == NULL) {
+ errorp("invalid storage size");
+ } else {
+ if ((n = np->sym->u.i) <= 0) {
+ errorp("array size is not a positive number");
+ n = 1;
+ }
+ freetree(np);
+ }
+ }
+ expect(']');
+
+ push(dp, ARY, n);
+}
+
+static int
+empty(Symbol *sym, Type *tp, int param)
+{
+ if (!sym->name) {
+ sym->type = tp;
+ switch (tp->op) {
+ default:
+ /* warn if it is not a parameter */
+ if (!param)
+ warn("empty declaration");
+ case STRUCT:
+ case UNION:
+ case ENUM:
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void
+bad_storage(Type *tp, char *name)
+{
+ if (tp->op != FTN)
+ errorp("incorrect storage class for file-scope declaration");
+ else
+ errorp("invalid storage class for function '%s'", name);
+}
+
+static Symbol *
+redcl(Symbol *sym, Type *tp, int sclass)
+{
+ int flags;
+ char *name = sym->name;
+
+ if (!eqtype(sym->type, tp, 1)) {
+ errorp("conflicting types for '%s'", name);
+ return sym;
+ }
+
+ if (sym->token == TYPEIDEN && sclass != TYPEDEF ||
+ sym->token != TYPEIDEN && sclass == TYPEDEF) {
+ goto redeclaration;
+ }
+ if (curctx != GLOBALCTX && tp->op != FTN) {
+ /* is it the redeclaration of a local variable? */
+ if ((sym->flags & SEXTERN) && sclass == EXTERN)
+ return sym;
+ goto redeclaration;
+ }
+
+ flags = sym->flags;
+ switch (sclass) {
+ case REGISTER:
+ case AUTO:
+ bad_storage(tp, name);
+ break;
+ case NOSCLASS:
+ if ((flags & SPRIVATE) == 0) {
+ if (flags & SEXTERN)
+ flags &= ~(SEXTERN|SEMITTED);
+ flags |= SGLOBAL;
+ break;
+ }
+ errorp("non-static declaration of '%s' follows static declaration",
+ name);
+ break;
+ case TYPEDEF:
+ /* Only C11 allows multiple definitions of a typedef. */
+ goto redeclaration;
+ case EXTERN:
+ break;
+ case STATIC:
+ if ((flags & (SGLOBAL|SEXTERN)) == 0) {
+ flags |= SPRIVATE;
+ break;
+ }
+ errorp("static declaration of '%s' follows non-static declaration",
+ name);
+ break;
+ }
+ sym->flags = flags;
+
+ return sym;
+
+redeclaration:
+ errorp("redeclaration of '%s'", name);
+ return sym;
+}
+
+static Symbol *
+identifier(struct decl *dcl)
+{
+ Symbol *sym = dcl->sym;
+ Type *tp = dcl->type;
+ int sclass = dcl->sclass;
+ char *name = sym->name;
+
+ if (empty(sym, tp, 0))
+ return sym;
+
+ /* TODO: Add warning about ANSI limits */
+ if (!(tp->prop & TDEFINED) &&
+ sclass != EXTERN && sclass != TYPEDEF &&
+ !(tp->op == ARY && yytoken == '=')) {
+ errorp("declared variable '%s' of incomplete type", name);
+ }
+
+ if (tp->op == FTN) {
+ if (sclass == NOSCLASS)
+ sclass = EXTERN;
+ if (!strcmp(name, "main") && tp->type != inttype) {
+ errorp("main shall be defined with a return type of int");
+ errorp("please contact __20h__ on irc.freenode.net (#bitreich-en) via IRC");
+ }
+ }
+
+ if (sym->flags & SDECLARED) {
+ sym = redcl(dcl->sym, tp, sclass);
+ } else {
+ int flags = sym->flags | SDECLARED;
+
+ sym->type = tp;
+
+ switch (sclass) {
+ case REGISTER:
+ case AUTO:
+ if (curctx != GLOBALCTX && tp->op != FTN) {
+ flags |= (sclass == REGISTER) ? SREGISTER : SAUTO;
+ break;
+ }
+ bad_storage(tp, name);
+ case NOSCLASS:
+ if (tp->op == FTN)
+ flags |= SEXTERN;
+ else
+ flags |= (curctx == GLOBALCTX) ? SGLOBAL : SAUTO;
+ break;
+ case EXTERN:
+ flags |= SEXTERN;
+ break;
+ case STATIC:
+ flags |= (curctx == GLOBALCTX) ? SPRIVATE : SLOCAL;
+ break;
+ case TYPEDEF:
+ flags |= STYPEDEF;
+ sym->u.token = sym->token = TYPEIDEN;
+ break;
+ }
+ sym->flags = flags;
+ }
+
+ if (accept('='))
+ initializer(sym, sym->type);
+ if (!(sym->flags & (SGLOBAL|SEXTERN)) && tp->op != FTN)
+ sym->flags |= SDEFINED;
+ if (sym->token == IDEN && tp->op != FTN)
+ emit(ODECL, sym);
+ return sym;
+}
+
+static Symbol *
+parameter(struct decl *dcl)
+{
+ Symbol *sym = dcl->sym;
+ Type *funtp = dcl->parent, *tp = dcl->type;
+ char *name = sym->name;
+ int flags;
+
+ flags = 0;
+ switch (dcl->sclass) {
+ case STATIC:
+ case EXTERN:
+ case AUTO:
+ errorp("bad storage class in function parameter");
+ break;
+ case REGISTER:
+ flags |= SREGISTER;
+ break;
+ case NOSCLASS:
+ flags |= SAUTO;
+ break;
+ }
+
+ switch (tp->op) {
+ case VOID:
+ funtp->n.elem = 1;
+ if (dcl->sclass)
+ errorp("void as unique parameter may not be qualified");
+ return NULL;
+ case ARY:
+ tp = mktype(tp->type, PTR, 0, NULL);
+ break;
+ case FTN:
+ errorp("incorrect function type for a function parameter");
+ return NULL;
+ }
+ if (!empty(sym, tp, 1)) {
+ int isdcl = sym->flags&SDECLARED, isk_r = funtp->prop & TK_R;
+ if (isdcl && !isk_r) {
+ errorp("redefinition of parameter '%s'", name);
+ return NULL;
+ }
+ if (!isdcl && isk_r) {
+ errorp("declaration for parameter '%s' but no such parameter",
+ sym->name);
+ return NULL;
+ }
+ sym->flags |= SDECLARED;
+ }
+
+ sym->type = tp;
+ sym->flags &= ~(SAUTO|SREGISTER);
+ sym->flags |= flags;
+ return sym;
+}
+
+static Symbol *dodcl(int rep,
+ Symbol *(*fun)(struct decl *),
+ unsigned ns,
+ Type *type);
+
+static int
+krpars(struct declarators *dp)
+{
+ Symbol *sym;
+ int toomany = 0;
+ unsigned npars = 0;
+
+ do {
+ sym = yylval.sym;
+ expect(IDEN);
+ sym->flags |= SAUTO;
+ if ((sym = install(NS_IDEN, sym)) == NULL) {
+ errorp("redefinition of parameter '%s'",
+ yylval.sym->name);
+ continue;
+ }
+ if (npars < NR_FUNPARAM) {
+ ++npars;
+ *dp->pars++ = sym;
+ continue;
+ }
+ if (!toomany)
+ toomany = 1;
+ } while (accept(','));
+
+ return toomany;
+}
+
+static unsigned
+krfun(struct declarators *dp)
+{
+ int toomany = 0;
+
+
+ if (yytoken != ')')
+ toomany = krpars(dp);
+
+ if (dp->nr_types == NR_DCL_TYP) {
+ toomany = 1;
+ } else {
+ ++dp->nr_types;
+ *dp->tpars++ = ellipsistype;
+ }
+
+ if (toomany)
+ errorp("too many parameters in function definition");
+ return 1;
+}
+
+static unsigned
+ansifun(struct declarators *dp)
+{
+ Symbol *sym;
+ unsigned npars, ntype, toomany, distoomany, voidpar;
+ Type type, *tp;
+
+ type.n.elem = 0;
+ type.prop = 0;
+ npars = ntype = toomany = distoomany = voidpar = 0;
+
+ do {
+ if (accept(ELLIPSIS)) {
+ if (ntype < 1)
+ errorp("a named argument is requiered before '...'");
+ if (yytoken != ')')
+ errorp("... must be the last parameter");
+ sym = NULL;
+ tp = ellipsistype;
+ } else if ((sym = dodcl(NOREP, parameter, NS_IDEN, &type)) == NULL) {
+ if (type.n.elem == 1 && ntype > 1)
+ voidpar = 1;
+ sym = NULL;
+ tp = NULL;
+ } else {
+ tp = sym->type;
+ }
+
+ if (sym) {
+ if (npars == NR_FUNPARAM) {
+ toomany = 1;
+ } else {
+ npars++;
+ *dp->pars++ = sym;
+ }
+ }
+
+ if (tp) {
+ if (dp->nr_types == NR_DCL_TYP) {
+ toomany = 1;
+ } else {
+ ntype++;
+ dp->nr_types++;
+ *dp->tpars++ = tp;
+ }
+ }
+
+ } while (accept(','));
+
+ if (toomany == 1)
+ errorp("too many parameters in function definition");
+ if (voidpar && ntype > 1)
+ errorp("'void' must be the only parameter");
+ return ntype;
+}
+
+static int
+funbody(Symbol *sym, Symbol *pars[])
+{
+ Type *tp;
+ Symbol **bp, *p;
+
+ if (!sym)
+ return 0;
+ tp = sym->type;
+ if (tp->op != FTN)
+ return 0;
+
+ switch (yytoken) {
+ case '{':
+ case TYPE:
+ case TYPEIDEN:
+ if (curctx != PARAMCTX)
+ errorp("nested function declaration");
+ if (sym && sym->ns == NS_IDEN)
+ break;
+ default:
+ emit(ODECL, sym);
+ endfundcl(tp, pars);
+ return 0;
+ }
+
+ tp->prop |= TFUNDEF;
+ curfun = sym;
+ if (sym->type->prop & TK_R) {
+ while (yytoken != '{') {
+ dodcl(REP, parameter, NS_IDEN, sym->type);
+ expect(';');
+ }
+ for (bp = pars; p = *bp; ++bp) {
+ if (p->type == NULL) {
+ warn("type of '%s' defaults to int", p->name);
+ p->type = inttype;
+ }
+ }
+ }
+ if (sym->flags & STYPEDEF)
+ errorp("function definition declared 'typedef'");
+ if (sym->flags & SDEFINED)
+ errorp("redefinition of '%s'", sym->name);
+ if (sym->flags & SEXTERN) {
+ sym->flags &= ~SEXTERN;
+ sym->flags |= SGLOBAL;
+ }
+ sym->flags |= SDEFINED;
+ sym->flags &= ~SEMITTED;
+ sym->u.pars = pars;
+ emit(OFUN, sym);
+ compound(NULL, NULL, NULL);
+ emit(OEFUN, NULL);
+ popctx();
+ flushtypes();
+ curfun = NULL;
+ return 1;
+}
+
+static void
+fundcl(struct declarators *dp)
+{
+ Type **types = dp->tpars;
+ unsigned ntypes, typefun;
+ Symbol **pars = dp->pars;
+ unsigned (*fun)(struct declarators *);
+
+ pushctx();
+ expect('(');
+ if (yytoken == ')' || yytoken == IDEN) {
+ typefun = KRFTN;
+ fun = krfun;
+ } else {
+ typefun = FTN;
+ fun = ansifun;
+ }
+ ntypes = (*fun)(dp);
+ *dp->pars++= NULL;
+ expect(')');
+
+ push(dp, typefun, ntypes, types, pars);
+}
+
+static void declarator(struct declarators *dp);
+
+static void
+directdcl(struct declarators *dp)
+{
+ Symbol *p, *sym;
+ static int nested;
+
+ if (accept('(')) {
+ if (nested == NR_SUBTYPE)
+ error("too many declarators nested by parentheses");
+ ++nested;
+ declarator(dp);
+ --nested;
+ expect(')');
+ } else {
+ if (yytoken == IDEN || yytoken == TYPEIDEN) {
+ sym = yylval.sym;
+ if (p = install(dp->ns, sym)) {
+ sym = p;
+ sym->flags &= ~SDECLARED;
+ }
+ next();
+ } else {
+ sym = newsym(dp->ns, NULL);
+ }
+ push(dp, IDEN, sym);
+ }
+
+ for (;;) {
+ switch (yytoken) {
+ case '(': fundcl(dp); break;
+ case '[': arydcl(dp); break;
+ default: return;
+ }
+ }
+}
+
+static void
+declarator(struct declarators *dp)
+{
+ unsigned n;
+
+ for (n = 0; accept('*'); ++n) {
+ while (accept(TQUALIFIER))
+ ;
+ }
+
+ directdcl(dp);
+
+ while (n--)
+ push(dp, PTR);
+}
+
+static Type *structdcl(void), *enumdcl(void);
+
+static Type *
+specifier(int *sclass, int *qualifier)
+{
+ Type *tp = NULL;
+ unsigned spec, qlf, sign, type, cls, size;
+
+ spec = qlf = sign = type = cls = size = 0;
+
+ for (;;) {
+ unsigned *p = NULL;
+ Type *(*dcl)(void) = NULL;
+
+ switch (yytoken) {
+ case SCLASS:
+ p = &cls;
+ break;
+ case TQUALIFIER:
+ qlf |= yylval.token;
+ next();
+ continue;
+ case TYPEIDEN:
+ if (type)
+ goto return_type;
+ tp = yylval.sym->type;
+ p = &type;
+ break;
+ case TYPE:
+ switch (yylval.token) {
+ case ENUM:
+ dcl = enumdcl;
+ p = &type;
+ break;
+ case STRUCT:
+ case UNION:
+ dcl = structdcl;
+ p = &type;
+ break;
+ case VA_LIST:
+ case VOID:
+ case BOOL:
+ case CHAR:
+ case INT:
+ case FLOAT:
+ case DOUBLE:
+ p = &type;
+ break;
+ case SIGNED:
+ case UNSIGNED:
+ p = &sign;
+ break;
+ case LONG:
+ if (size == LONG) {
+ yylval.token = LLONG;
+ size = 0;
+ }
+ case SHORT:
+ p = &size;
+ break;
+ }
+ break;
+ default:
+ goto return_type;
+ }
+ if (*p)
+ errorp("invalid type specification");
+ *p = yylval.token;
+ if (dcl) {
+ if (size || sign)
+ errorp("invalid type specification");
+ tp = (*dcl)();
+ goto return_type;
+ } else {
+ next();
+ }
+ spec = 1;
+ }
+
+return_type:
+ *sclass = cls;
+ *qualifier = qlf;
+ if (!tp) {
+ if (spec) {
+ tp = ctype(type, sign, size);
+ } else {
+ if (curctx != GLOBALCTX)
+ unexpected();
+ warn("type defaults to 'int' in declaration");
+ tp = inttype;
+ }
+ }
+ return tp;
+}
+
+static Symbol *
+newtag(void)
+{
+ Symbol *sym;
+ int ns, op, tag = yylval.token;
+ static unsigned tpns = NS_STRUCTS;
+
+ ns = namespace;
+ namespace = NS_TAG;
+ next();
+ namespace = ns;
+
+ switch (yytoken) {
+ case IDEN:
+ case TYPEIDEN:
+ sym = yylval.sym;
+ if ((sym->flags & SDECLARED) == 0)
+ install(NS_TAG, yylval.sym);
+ next();
+ break;
+ default:
+ sym = newsym(NS_TAG, NULL);
+ break;
+ }
+ if (!sym->type) {
+ Type *tp;
+
+ if (tpns == NS_STRUCTS + NR_MAXSTRUCTS)
+ error("too many tags declared");
+ tp = mktype(NULL, tag, 0, NULL);
+ tp->ns = tpns++;
+ sym->type = tp;
+ tp->tag = sym;
+ DBG("declared tag '%s' with ns = %d\n",
+ (sym->name) ? sym->name : "anonymous", tp->ns);
+ }
+
+ if ((op = sym->type->op) != tag && op != INT)
+ error("'%s' defined as wrong kind of tag", sym->name);
+ return sym;
+}
+
+static void fieldlist(Type *tp);
+
+static Type *
+structdcl(void)
+{
+ Symbol *sym;
+ Type *tp;
+ static int nested;
+ int ns;
+
+ sym = newtag();
+ tp = sym->type;
+
+ if (!accept('{'))
+ return tp;
+
+ ns = namespace;
+ namespace = tp->ns;
+
+ if (tp->prop & TDEFINED && sym->ctx == curctx)
+ error("redefinition of struct/union '%s'", sym->name);
+
+ if (nested == NR_STRUCT_LEVEL)
+ error("too many levels of nested structure or union definitions");
+
+ ++nested;
+ while (yytoken != '}') {
+ fieldlist(tp);
+ }
+ --nested;
+
+ deftype(tp);
+ namespace = ns;
+ expect('}');
+ return tp;
+}
+
+static Type *
+enumdcl(void)
+{
+ Type *tp;
+ Symbol *sym, *tagsym;
+ int ns, val, toomany;
+ unsigned nctes;
+
+ ns = namespace;
+ tagsym = newtag();
+ tp = tagsym->type;
+
+ if (!accept('{'))
+ goto restore_name;
+ if (tp->prop & TDEFINED)
+ errorp("redefinition of enumeration '%s'", tagsym->name);
+ deftype(tp);
+ namespace = NS_IDEN;
+
+ /* TODO: check incorrect values in val */
+ for (nctes = val = 0; yytoken != '}'; ++nctes, ++val) {
+ if (yytoken != IDEN)
+ unexpected();
+ sym = yylval.sym;
+ next();
+ if (nctes == NR_ENUM_CTES && !toomany) {
+ errorp("too many enum constants in a single enum");
+ toomany = 1;
+ }
+ if (accept('=')) {
+ Node *np = constexpr();
+
+ if (np == NULL)
+ errorp("invalid enumeration value");
+ else
+ val = np->sym->u.i;
+ freetree(np);
+ }
+ if ((sym = install(NS_IDEN, sym)) == NULL) {
+ errorp("'%s' redeclared as different kind of symbol",
+ yytext);
+ } else {
+ sym->u.i = val;
+ sym->flags |= SCONSTANT;
+ sym->type = inttype;
+ }
+ if (!accept(','))
+ break;
+ }
+ expect('}');
+
+restore_name:
+ namespace = ns;
+ return tp;
+}
+
+static Symbol *
+type(struct decl *dcl)
+{
+ Symbol *sym = dcl->sym;
+
+ if (dcl->sclass)
+ error("class storage in type name");
+ if (sym->name)
+ error("unexpected identifier in type name");
+ sym->type = dcl->type;
+
+ return sym;
+}
+
+static Symbol *
+field(struct decl *dcl)
+{
+ static char *anon = "<anonymous>";
+ Symbol *sym = dcl->sym;
+ char *name = (sym->name) ? sym->name : anon;
+ Type *structp = dcl->parent, *tp = dcl->type;
+ TINT n = structp->n.elem;
+ int err = 0;
+
+ if (accept(':')) {
+ Node *np;
+ TINT n;
+
+ if ((np = constexpr()) == NULL) {
+ unexpected();
+ n = 0;
+ } else {
+ n = np->sym->u.i;
+ freetree(np);
+ }
+ if (n == 0 && name != anon)
+ errorp("zero width for bit-field '%s'", name);
+ if (tp != booltype && tp != inttype && tp != uinttype)
+ errorp("bit-field '%s' has invalid type", name);
+ if (n < 0)
+ errorp("negative width in bit-field '%s'", name);
+ else if (n > tp->size*8)
+ errorp("width of '%s' exceeds its type", name);
+ } else if (empty(sym, tp, 0)) {
+ return sym;
+ }
+
+ if (tp->op == FTN) {
+ errorp("invalid type '%s' in struct/union", name);
+ err = 1;
+ }
+ if (dcl->sclass) {
+ errorp("storage class in struct/union field '%s'", name);
+ err = 1;
+ }
+ if (!(tp->prop & TDEFINED)) {
+ error("field '%s' has incomplete type", name);
+ err = 1;
+ }
+ if (err)
+ return sym;
+
+ if (sym->flags & SDECLARED)
+ error("duplicated member '%s'", name);
+ sym->flags |= SFIELD|SDECLARED;
+ sym->type = tp;
+
+ if (n == NR_FIELDS)
+ error("too many fields in struct/union");
+ DBG("New field '%s' in namespace %d\n", name, structp->ns);
+ structp->p.fields = xrealloc(structp->p.fields, ++n * sizeof(*sym));
+ structp->p.fields[n-1] = sym;
+ structp->n.elem = n;
+
+ return sym;
+}
+
+static Symbol *
+dodcl(int rep, Symbol *(*fun)(struct decl *), unsigned ns, Type *parent)
+{
+ Symbol *sym;
+ Type *base;
+ struct decl dcl;
+ struct declarators stack;
+
+ dcl.ns = ns;
+ dcl.parent = parent;
+ base = specifier(&dcl.sclass, &dcl.qualifier);
+
+ do {
+ dcl.type = base;
+ stack.nr_types = stack.nr = 0;
+ stack.tpars = dcl.buftpars;
+ stack.pars = dcl.bufpars;
+ stack.dcl = &dcl;
+ stack.ns = ns;
+
+ declarator(&stack);
+
+ while (pop(&stack, &dcl))
+ ;
+ sym = (*fun)(&dcl);
+ if (funbody(sym, dcl.pars))
+ return sym;
+ } while (rep && accept(','));
+
+ return sym;
+}
+
+void
+decl(void)
+{
+ Symbol *sym;
+
+ if (accept(';'))
+ return;
+ sym = dodcl(REP, identifier, NS_IDEN, NULL);
+ if (sym->type->prop & TFUNDEF)
+ return;
+ expect(';');
+}
+
+static void
+fieldlist(Type *tp)
+{
+ if (yytoken != ';')
+ dodcl(REP, field, tp->ns, tp);
+ expect(';');
+}
+
+Type *
+typename(void)
+{
+ return dodcl(NOREP, type, NS_DUMMY, NULL)->type;
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/deps.mk
@@ -1,0 +1,44 @@
+#deps
+./builtin.o: $(INCDIR)/scc/scc/scc.h
+./builtin.o: ./cc1.h
+./code.o: $(INCDIR)/scc/scc/scc.h
+./code.o: ./cc1.h
+./cpp.o: $(INCDIR)/scc/scc/cstd.h
+./cpp.o: $(INCDIR)/scc/scc/scc.h
+./cpp.o: ./cc1.h
+./decl.o: $(INCDIR)/scc/scc/cstd.h
+./decl.o: $(INCDIR)/scc/scc/scc.h
+./decl.o: ./cc1.h
+./error.o: $(INCDIR)/scc/scc/scc.h
+./error.o: ./cc1.h
+./expr.o: $(INCDIR)/scc/scc/cstd.h
+./expr.o: $(INCDIR)/scc/scc/scc.h
+./expr.o: ./cc1.h
+./fold.o: $(INCDIR)/scc/scc/scc.h
+./fold.o: ./cc1.h
+./init.o: $(INCDIR)/scc/scc/cstd.h
+./init.o: $(INCDIR)/scc/scc/scc.h
+./init.o: ./cc1.h
+./lex.o: $(INCDIR)/scc/scc/cstd.h
+./lex.o: $(INCDIR)/scc/scc/scc.h
+./lex.o: ./cc1.h
+./main.o: $(INCDIR)/scc/scc/arg.h
+./main.o: $(INCDIR)/scc/scc/scc.h
+./main.o: ./cc1.h
+./stmt.o: $(INCDIR)/scc/scc/cstd.h
+./stmt.o: $(INCDIR)/scc/scc/scc.h
+./stmt.o: ./cc1.h
+./symbol.o: $(INCDIR)/scc/scc/cstd.h
+./symbol.o: $(INCDIR)/scc/scc/scc.h
+./symbol.o: ./cc1.h
+./target/amd64-sysv/arch.o: $(INCDIR)/scc/scc/scc.h
+./target/amd64-sysv/arch.o: ./target/amd64-sysv/../../cc1.h
+./target/arm64-sysv/arch.o: $(INCDIR)/scc/scc/scc.h
+./target/arm64-sysv/arch.o: ./target/arm64-sysv/../../cc1.h
+./target/i386-sysv/arch.o: $(INCDIR)/scc/scc/scc.h
+./target/i386-sysv/arch.o: ./target/i386-sysv/../../cc1.h
+./target/z80-scc/arch.o: $(INCDIR)/scc/scc/scc.h
+./target/z80-scc/arch.o: ./target/z80-scc/../../cc1.h
+./types.o: $(INCDIR)/scc/scc/cstd.h
+./types.o: $(INCDIR)/scc/scc/scc.h
+./types.o: ./cc1.h
--- /dev/null
+++ b/src/cmd/cc/cc1/error.c
@@ -1,0 +1,84 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/scc.h>
+#include "cc1.h"
+
+#define MAXERRNUM 10
+
+extern int failure;
+static unsigned nerrors;
+
+static void
+warn_error(int flag, char *fmt, va_list va)
+{
+ if (flag == 0)
+ return;
+ fprintf(stderr, "%s:%u: %s: ",
+ filenam, lineno,
+ (flag < 0) ? "error" : "warning");
+ vfprintf(stderr, fmt, va);
+ putc('\n', stderr);
+
+ if (flag < 0) {
+ if (!failure)
+ fclose(stdout);
+ failure = 1;
+ if (++nerrors == MAXERRNUM) {
+ fputs("too many errors\n", stderr);
+ exit(1);
+ }
+ }
+}
+
+void
+warn(char *fmt, ...)
+{
+ extern int warnings;
+
+ va_list va;
+ va_start(va, fmt);
+ warn_error(warnings, fmt, va);
+ va_end(va);
+}
+
+void
+error(char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ warn_error(-1, fmt, va);
+ va_end(va);
+ exit(1);
+ discard();
+}
+
+void
+errorp(char *fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ warn_error(-1, fmt, va);
+ va_end(va);
+}
+
+void
+cpperror(char *fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ warn_error(-1, fmt, va);
+ va_end(va);
+
+ /* discard input until the end of the line */
+ *input->p = '\0';
+ next();
+}
+
+void
+unexpected(void)
+{
+ error("unexpected '%s'", yytext);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/expr.c
@@ -1,0 +1,1184 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+#define XCHG(lp, rp, np) (np = lp, lp = rp, rp = np)
+
+static Node *xexpr(void), *xassign(void);
+
+int
+cmpnode(Node *np, TUINT val)
+{
+ Symbol *sym;
+ Type *tp;
+ TUINT mask, nodeval;
+
+ if (!np || !(np->flags & NCONST) || !np->sym)
+ return 0;
+ sym = np->sym;
+ tp = sym->type;
+
+ switch (tp->op) {
+ case PTR:
+ case INT:
+ mask = (val > 1) ? ones(np->type->size) : -1;
+ nodeval = (tp->prop & TSIGNED) ? sym->u.i : sym->u.u;
+ return (nodeval & mask) == (val & mask);
+ case FLOAT:
+ return sym->u.f == val;
+ }
+ return 0;
+}
+
+static Node *
+promote(Node *np)
+{
+ Type *tp;
+ Node *new;
+ struct limits *lim, *ilim;
+
+ tp = np->type;
+
+ switch (tp->op) {
+ case ENUM:
+ case INT:
+ if (tp->n.rank >= inttype->n.rank)
+ return np;
+ lim = getlimits(tp);
+ ilim = getlimits(inttype);
+ tp = (lim->max.i <= ilim->max.i) ? inttype : uinttype;
+ break;
+ case FLOAT:
+ /* TODO: Add support for C99 float math */
+ tp = doubletype;
+ break;
+ default:
+ abort();
+ }
+ if ((new = convert(np, tp, 1)) != NULL)
+ return new;
+ return np;
+}
+
+static void
+arithconv(Node **p1, Node **p2)
+{
+ int to = 0, s1, s2;
+ unsigned r1, r2;
+ Type *tp1, *tp2;
+ Node *np1, *np2;
+ struct limits *lp1, *lp2;
+
+ np1 = promote(*p1);
+ np2 = promote(*p2);
+
+ tp1 = np1->type;
+ tp2 = np2->type;
+
+ if (tp1 == tp2)
+ goto set_p1_p2;
+
+ s1 = (tp1->prop & TSIGNED) != 0;
+ r1 = tp1->n.rank;
+ lp1 = getlimits(tp1);
+
+ s2 = (tp2->prop & TSIGNED) != 0;
+ r2 = tp2->n.rank;
+ lp2 = getlimits(tp2);
+
+ if (s1 == s2 || tp1->op == FLOAT || tp2->op == FLOAT) {
+ to = r1 - r2;
+ } else if (!s1) {
+ if (r1 >= r2 || lp1->max.i >= lp2->max.i)
+ to = 1;
+ else
+ to = -1;
+ } else {
+ if (r2 >= r1 || lp2->max.i >= lp1->max.i)
+ to = -1;
+ else
+ to = 1;
+ }
+
+ if (to > 0)
+ np2 = convert(np2, tp1, 1);
+ else if (to < 0)
+ np1 = convert(np1, tp2, 1);
+
+set_p1_p2:
+ *p1 = np1;
+ *p2 = np2;
+}
+
+static int
+null(Node *np)
+{
+ if (np->type != pvoidtype || np->op != OCAST)
+ return 0;
+
+ np = np->left;
+ if (np->type != inttype)
+ return 0;
+
+ return cmpnode(np, 0);
+}
+
+static Node *
+chkternary(Node *yes, Node *no)
+{
+ /*
+ * FIXME:
+ * We are ignoring type qualifiers here,
+ * but the standard has strong rules about this.
+ * take a look to 6.5.15
+ */
+
+ if (!eqtype(yes->type, no->type, 1)) {
+ if ((yes->type->prop & TARITH) && (no->type->prop & TARITH)) {
+ arithconv(&yes, &no);
+ } else if (yes->type->op != PTR && no->type->op != PTR) {
+ goto wrong_type;
+ } else {
+ /* convert integer 0 to NULL */
+ if ((yes->type->prop & TINTEGER) && cmpnode(yes, 0))
+ yes = convert(yes, pvoidtype, 0);
+ if ((no->type->prop & TINTEGER) && cmpnode(no, 0))
+ no = convert(no, pvoidtype, 0);
+ /*
+ * At this point the type of both should be
+ * a pointer to something, or we have don't
+ * compatible types
+ */
+ if (yes->type->op != PTR || no->type->op != PTR)
+ goto wrong_type;
+ /*
+ * If we have a null pointer constant then
+ * convert to the another type
+ */
+ if (null(yes))
+ yes = convert(yes, no->type, 0);
+ if (null(no))
+ no = convert(no, yes->type, 0);
+
+ if (!eqtype(yes->type, no->type, 1))
+ goto wrong_type;
+ }
+ }
+ return node(OCOLON, yes->type, yes, no);
+
+wrong_type:
+ errorp("type mismatch in conditional expression");
+ freetree(yes);
+ freetree(no);
+ return constnode(zero);
+}
+
+static void
+chklvalue(Node *np)
+{
+ if (!(np->flags & NLVAL))
+ errorp("lvalue required in operation");
+ if (np->type == voidtype)
+ errorp("invalid use of void expression");
+}
+
+Node *
+decay(Node *np)
+{
+ Node *new;
+ Type *tp = np->type;
+
+ switch (tp->op) {
+ case ARY:
+ tp = tp->type;
+ if (np->op == OPTR) {
+ new = np->left;
+ free(np);
+ new->type = mktype(tp, PTR, 0, NULL);
+ return new;
+ }
+ case FTN:
+ new = node(OADDR, mktype(tp, PTR, 0, NULL), np, NULL);
+ if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE))
+ new->flags |= NCONST;
+ return new;
+ default:
+ return np;
+ }
+}
+
+static Node *
+integerop(int op, Node *lp, Node *rp)
+{
+ if (!(lp->type->prop & TINTEGER) || !(rp->type->prop & TINTEGER))
+ error("operator requires integer operands");
+ arithconv(&lp, &rp);
+ return node(op, lp->type, lp, rp);
+}
+
+static Node *
+integeruop(int op, Node *np)
+{
+ if (!(np->type->prop & TINTEGER))
+ error("unary operator requires integer operand");
+ np = promote(np);
+ return node(op, np->type, np, NULL);
+}
+
+static Node *
+numericaluop(int op, Node *np)
+{
+ if (!(np->type->prop & TARITH))
+ error("unary operator requires numerical operand");
+ np = promote(np);
+ return node(op, np->type, np, NULL);
+}
+
+Node *
+convert(Node *np, Type *newtp, int iscast)
+{
+ Type *oldtp = np->type;
+
+ if (eqtype(newtp, oldtp, 0))
+ return np;
+
+ switch (oldtp->op) {
+ case ENUM:
+ case INT:
+ case FLOAT:
+ switch (newtp->op) {
+ case PTR:
+ if (oldtp->op == FLOAT || !cmpnode(np, 0) && !iscast)
+ return NULL;
+ case INT:
+ case FLOAT:
+ case ENUM:
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ case PTR:
+ switch (newtp->op) {
+ case ENUM:
+ case INT:
+ case VOID:
+ if (!iscast)
+ return NULL;
+ break;
+ case PTR:
+ if (eqtype(newtp, oldtp, 1) ||
+ iscast ||
+ newtp == pvoidtype || oldtp == pvoidtype) {
+ np->type = newtp;
+ return np;
+ }
+ default:
+ return NULL;
+ }
+ break;
+ default:
+ return NULL;
+ }
+ return node(OCAST, newtp, np, NULL);
+}
+
+static Node *
+parithmetic(int op, Node *lp, Node *rp)
+{
+ Type *tp;
+ Node *size, *np;
+
+ if (lp->type->op != PTR)
+ XCHG(lp, rp, np);
+
+ tp = rp->type;
+ if (tp->op == PTR && !(tp->type->prop & TDEFINED))
+ goto incomplete;
+ tp = lp->type;
+ if (!(tp->type->prop & TDEFINED))
+ goto incomplete;
+ size = sizeofnode(tp->type);
+
+ if (op == OSUB && BTYPE(rp) == PTR) {
+ if ((rp = convert(rp, lp->type, 0)) == NULL)
+ goto incorrect;
+ lp = node(OSUB, pdifftype, lp, rp);
+ return node(ODIV, inttype, lp, size);
+ }
+ if (!(rp->type->prop & TINTEGER))
+ goto incorrect;
+
+ rp = convert(promote(rp), sizettype, 0);
+ rp = node(OMUL, sizettype, rp, size);
+ rp = convert(rp, tp, 1);
+
+ return node(op, tp, lp, rp);
+
+incomplete:
+ errorp("invalid use of undefined type");
+ return lp;
+incorrect:
+ errorp("incorrect arithmetic operands");
+ return lp;
+
+}
+
+static Node *
+arithmetic(int op, Node *lp, Node *rp)
+{
+ Type *ltp = lp->type, *rtp = rp->type;
+
+ if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) {
+ arithconv(&lp, &rp);
+ return node(op, lp->type, lp, rp);
+ } else if ((ltp->op == PTR || rtp->op == PTR)) {
+ switch (op) {
+ case OADD:
+ case OSUB:
+ case OA_ADD:
+ case OA_SUB:
+ case OINC:
+ case ODEC:
+ return parithmetic(op, lp, rp);
+ }
+ }
+ errorp("incorrect arithmetic operands");
+}
+
+static Node *
+pcompare(int op, Node *lp, Node *rp)
+{
+ Node *np;
+
+ if (lp->type->prop & TINTEGER)
+ XCHG(lp, rp, np);
+ else if (eqtype(lp->type, pvoidtype, 1))
+ XCHG(lp, rp, np);
+
+ if ((np = convert(rp, lp->type, 0)) != NULL)
+ rp = np;
+ else
+ errorp("incompatible types in comparison");
+ return convert(node(op, pvoidtype, lp, rp), inttype, 1);
+}
+
+static Node *
+compare(int op, Node *lp, Node *rp)
+{
+ Type *ltp, *rtp;
+
+ ltp = lp->type;
+ rtp = rp->type;
+
+ if (ltp->op == PTR || rtp->op == PTR) {
+ return pcompare(op, rp, lp);
+ } else if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) {
+ arithconv(&lp, &rp);
+ return convert(node(op, lp->type, lp, rp), inttype, 1);;
+ } else {
+ errorp("incompatible types in comparison");
+ freetree(lp);
+ freetree(rp);
+ return constnode(zero);
+ }
+}
+
+int
+negop(int op)
+{
+ switch (op) {
+ case OEQ: return ONE;
+ case ONE: return OEQ;
+ case OLT: return OGE;
+ case OGE: return OLT;
+ case OLE: return OGT;
+ case OGT: return OLE;
+ default: abort();
+ }
+ return op;
+}
+
+static Node *
+exp2cond(Node *np, int neg)
+{
+ if (np->type->prop & TAGGREG) {
+ errorp("used struct/union type value where scalar is required");
+ return constnode(zero);
+ }
+ switch (np->op) {
+ case ONEG:
+ case OOR:
+ case OAND:
+ return (neg) ? node(ONEG, inttype, np, NULL) : np;
+ case OEQ:
+ case ONE:
+ case OLT:
+ case OGE:
+ case OLE:
+ case OGT:
+ if (neg)
+ np->op = negop(np->op);
+ return np;
+ default:
+ return compare((neg) ? OEQ : ONE, np, constnode(zero));
+ }
+}
+
+static Node *
+logic(int op, Node *lp, Node *rp)
+{
+ lp = exp2cond(lp, 0);
+ rp = exp2cond(rp, 0);
+ return node(op, inttype, lp, rp);
+}
+
+static Node *
+field(Node *np)
+{
+ Symbol *sym;
+
+ namespace = np->type->ns;
+ next();
+ namespace = NS_IDEN;
+
+ sym = yylval.sym;
+ if (yytoken != IDEN)
+ unexpected();
+ next();
+
+ if (!(np->type->prop & TAGGREG)) {
+ errorp("request for member '%s' in something not a structure or union",
+ yylval.sym->name);
+ goto free_np;
+ }
+ if ((sym->flags & SDECLARED) == 0) {
+ errorp("incorrect field in struct/union");
+ goto free_np;
+ }
+ np = node(OFIELD, sym->type, np, varnode(sym));
+ np->flags |= NLVAL;
+ return np;
+
+free_np:
+ freetree(np);
+ return constnode(zero);
+}
+
+static Node *
+content(int op, Node *np)
+{
+ if (BTYPE(np) != PTR) {
+ errorp("invalid argument of memory indirection");
+ } else {
+ if (np->op == OADDR) {
+ Node *new = np->left;
+ new->type = np->type->type;
+ free(np);
+ np = new;
+ } else {
+ np = node(op, np->type->type, np, NULL);
+ }
+ np->flags |= NLVAL;
+ }
+ return np;
+}
+
+static Node *
+array(Node *lp, Node *rp)
+{
+ Type *tp;
+ Node *np;
+
+ if (!(lp->type->prop & TINTEGER) && !(rp->type->prop & TINTEGER))
+ error("array subscript is not an integer");
+ np = arithmetic(OADD, lp, rp);
+ tp = np->type;
+ if (tp->op != PTR)
+ errorp("subscripted value is neither array nor pointer");
+ return content(OPTR, np);
+}
+
+static Node *
+assignop(int op, Node *lp, Node *rp)
+{
+ if ((rp = convert(rp, lp->type, 0)) == NULL) {
+ errorp("incompatible types when assigning");
+ return lp;
+ }
+
+ return node(op, lp->type, lp, rp);
+}
+
+static Node *
+incdec(Node *np, int op)
+{
+ Type *tp = np->type;
+ Node *inc;
+
+ chklvalue(np);
+ np->flags |= NEFFECT;
+
+ if (!(tp->prop & TDEFINED)) {
+ errorp("invalid use of undefined type");
+ return np;
+ } else if (tp->op == PTR && !(tp->type->prop & TDEFINED)) {
+ errorp("%s of pointer to an incomplete type",
+ (op == OINC || op == OA_ADD) ? "increment" : "decrement");
+ return np;
+ } else if (tp->op == PTR || (tp->prop & TARITH)) {
+ inc = constnode(one);
+ } else {
+ errorp("wrong type argument to increment or decrement");
+ return np;
+ }
+ return arithmetic(op, np, inc);
+}
+
+static Node *
+address(int op, Node *np)
+{
+ Node *new;
+
+ /*
+ * ansi c accepts & applied to a function name, and it generates
+ * a function pointer
+ */
+ if (np->op == OSYM) {
+ if (np->type->op == FTN)
+ return decay(np);
+ if (np->type->op == ARY)
+ goto dont_check_lvalue;
+ }
+ chklvalue(np);
+
+dont_check_lvalue:
+ if (np->sym && (np->sym->flags & SREGISTER))
+ errorp("address of register variable '%s' requested", yytext);
+ new = node(op, mktype(np->type, PTR, 0, NULL), np, NULL);
+ if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE))
+ new->flags |= NCONST;
+ return new;
+}
+
+static Node *
+negation(int op, Node *np)
+{
+ if (!(np->type->prop & TARITH) && np->type->op != PTR) {
+ errorp("invalid argument of unary '!'");
+ return constnode(zero);
+ }
+ return exp2cond(np, 1);
+}
+
+static Symbol *
+notdefined(Symbol *sym)
+{
+ int isdef;
+
+ if (namespace == NS_CPP && !strcmp(sym->name, "defined")) {
+ disexpand = 1;
+ next();
+ expect('(');
+ sym = yylval.sym;
+ expect(IDEN);
+ expect(')');
+
+ isdef = (sym->flags & SDECLARED) != 0;
+ sym = newsym(NS_IDEN, NULL);
+ sym->type = inttype;
+ sym->flags |= SCONSTANT;
+ sym->u.i = isdef;
+ disexpand = 0;
+ return sym;
+ }
+ errorp("'%s' undeclared", yytext);
+ sym->type = inttype;
+ return install(sym->ns, yylval.sym);
+}
+
+static Symbol *
+adjstrings(Symbol *sym)
+{
+ char *s, *t;
+ size_t len, n;
+ Type *tp;
+
+ tp = sym->type;
+ s = sym->u.s;
+ for (len = strlen(s);; len += n) {
+ next();
+ if (yytoken != STRING)
+ break;
+ t = yylval.sym->u.s;
+ n = strlen(t);
+ s = xrealloc(s, len + n + 1);
+ memcpy(s+len, t, n);
+ s[len + n] = '\0';
+ killsym(yylval.sym);
+ }
+ ++len;
+ if (tp->n.elem != len) {
+ sym->type = mktype(chartype, ARY, len, NULL);
+ sym->u.s = s;
+ }
+ return sym;
+}
+
+/*************************************************************
+ * grammar functions *
+ *************************************************************/
+static Node *
+primary(void)
+{
+ Node *np;
+ Symbol *sym;
+ Node *(*fun)(Symbol *);
+
+ sym = yylval.sym;
+ switch (yytoken) {
+ case STRING:
+ np = constnode(adjstrings(sym));
+ sym->flags |= SHASINIT;
+ emit(ODECL, sym);
+ emit(OINIT, np);
+ return varnode(sym);
+ case BUILTIN:
+ fun = sym->u.fun;
+ next();
+ expect('(');
+ np = (*fun)(sym);
+ expect(')');
+
+ /* do not call to next */
+ return np;
+ case CONSTANT:
+ np = constnode(sym);
+ break;
+ case IDEN:
+ assert((sym->flags & SCONSTANT) == 0);
+ if ((sym->flags & SDECLARED) == 0) {
+ if (namespace == NS_CPP) {
+ np = constnode(zero);
+ break;
+ }
+ sym = notdefined(sym);
+ }
+ sym->flags |= SUSED;
+ np = varnode(sym);
+ break;
+ default:
+ unexpected();
+ }
+ next();
+
+ return np;
+}
+
+static Node *
+arguments(Node *np)
+{
+ int toomany, n, op;
+ Node *par = NULL, *arg;
+ Type *argtype, **targs, *tp = np->type, *rettype;
+
+ if (tp->op == PTR && tp->type->op == FTN) {
+ np = content(OPTR, np);
+ tp = np->type;
+ }
+ if (tp->op != FTN) {
+ targs = (Type *[]) {ellipsistype};
+ n = 1;
+ rettype = inttype;
+ errorp("function or function pointer expected");
+ } else {
+ targs = tp->p.pars;
+ n = tp->n.elem;
+ rettype = tp->type;
+ }
+
+ expect('(');
+ if (yytoken == ')')
+ goto no_pars;
+ toomany = 0;
+
+ do {
+ arg = xassign();
+ argtype = *targs;
+ if (argtype == ellipsistype) {
+ n = 0;
+ switch (arg->type->op) {
+ case INT:
+ arg = promote(arg);
+ break;
+ case FLOAT:
+ if (arg->type == floattype)
+ arg = convert(arg, doubletype, 1);
+ break;
+ }
+ par = node(OPAR, arg->type, par, arg);
+ continue;
+ }
+ if (--n < 0) {
+ if (!toomany)
+ errorp("too many arguments in function call");
+ toomany = 1;
+ continue;
+ }
+ ++targs;
+ if ((arg = convert(arg, argtype, 0)) != NULL) {
+ par = node(OPAR, arg->type, par, arg);
+ continue;
+ }
+ errorp("incompatible type for argument %d in function call",
+ tp->n.elem - n + 1);
+ } while (accept(','));
+
+no_pars:
+ expect(')');
+ if (n > 0 && *targs != ellipsistype)
+ errorp("too few arguments in function call");
+
+ op = (tp->prop&TELLIPSIS) ? OCALLE : OCALL;
+ return node(op, rettype, np, par);
+}
+
+static Node *unary(int);
+
+static Type *
+typeof(Node *np)
+{
+ Type *tp;
+
+ if (np == NULL)
+ unexpected();
+ tp = np->type;
+ freetree(np);
+ return tp;
+}
+
+static Type *
+sizeexp(void)
+{
+ Type *tp;
+
+ expect('(');
+ switch (yytoken) {
+ case TYPE:
+ case TYPEIDEN:
+ tp = typename();
+ break;
+ default:
+ tp = typeof(unary(0));
+ break;
+ }
+ expect(')');
+ return tp;
+}
+
+static Node *
+postfix(Node *lp)
+{
+ Node *rp;
+
+ for (;;) {
+ switch (yytoken) {
+ case '[':
+ case DEC:
+ case INC:
+ case INDIR:
+ case '.':
+ case '(':
+ lp = decay(lp);
+ switch (yytoken) {
+ case '[':
+ next();
+ rp = xexpr();
+ expect(']');
+ lp = array(lp, rp);
+ break;
+ case DEC:
+ case INC:
+ lp = incdec(lp, (yytoken == INC) ? OINC : ODEC);
+ next();
+ break;
+ case INDIR:
+ lp = content(OPTR, lp);
+ case '.':
+ lp = field(lp);
+ break;
+ case '(':
+ lp = arguments(lp);
+ lp->flags |= NEFFECT;
+ break;
+ }
+ break;
+ default:
+ return lp;
+ }
+ }
+}
+
+static Node *
+defined(void)
+{
+ Symbol *sym;
+ int paren;
+
+ disexpand = 1;
+ next();
+ paren = accept('(');
+ if (yytoken != IDEN && yytoken != TYPEIDEN)
+ cpperror("operator 'defined' requires an identifier");
+ if (yytoken == TYPEIDEN || !(yylval.sym->flags & SDECLARED))
+ sym = zero;
+ else
+ sym = one;
+ disexpand = 0;
+ next();
+ if (paren)
+ expect(')');
+ return constnode(sym);
+}
+
+static Node *cast(int);
+
+static Node *
+unary(int needdecay)
+{
+ Node *(*fun)(int, Node *), *np;
+ int op;
+ Type *tp;
+
+ switch (yytoken) {
+ case '!': op = 0; fun = negation; break;
+ case '+': op = OADD; fun = numericaluop; break;
+ case '-': op = OSNEG; fun = numericaluop; break;
+ case '~': op = OCPL; fun = integeruop; break;
+ case '&': op = OADDR; fun = address; break;
+ case '*': op = OPTR; fun = content; break;
+ case SIZEOF:
+ next();
+ tp = (yytoken == '(') ? sizeexp() : typeof(unary(0));
+ if (!(tp->prop & TDEFINED))
+ errorp("sizeof applied to an incomplete type");
+ return sizeofnode(tp);
+ case INC:
+ case DEC:
+ op = (yytoken == INC) ? OA_ADD : OA_SUB;
+ next();
+ np = incdec(unary(1), op);
+ goto chk_decay;
+ case IDEN:
+ case TYPEIDEN:
+ if (lexmode == CPPMODE && !strcmp(yylval.sym->name, "defined"))
+ return defined();
+ default:
+ np = postfix(primary());
+ goto chk_decay;
+ }
+
+ next();
+ np = (*fun)(op, cast(op != OADDR));
+
+chk_decay:
+ if (needdecay)
+ np = decay(np);
+ return np;
+}
+
+static Node *
+cast(int needdecay)
+{
+ Node *lp, *rp;
+ Type *tp;
+ static int nested;
+
+ if (!accept('('))
+ return unary(needdecay);
+
+ switch (yytoken) {
+ case TQUALIFIER:
+ case TYPE:
+ case TYPEIDEN:
+ tp = typename();
+ expect(')');
+
+ if (yytoken == '{')
+ return initlist(tp);
+
+ switch (tp->op) {
+ case ARY:
+ error("cast specifies an array type");
+ default:
+ lp = cast(needdecay);
+ if ((rp = convert(lp, tp, 1)) == NULL)
+ error("bad type conversion requested");
+ rp->flags &= ~NLVAL;
+ rp->flags |= lp->flags & NLVAL;
+ }
+ break;
+ default:
+ if (nested == NR_SUBEXPR)
+ error("too many expressions nested by parentheses");
+ ++nested;
+ rp = xexpr();
+ --nested;
+ expect(')');
+ rp = postfix(rp);
+ break;
+ }
+
+ return rp;
+}
+
+static Node *
+mul(void)
+{
+ Node *np, *(*fun)(int, Node *, Node *);
+ int op;
+
+ np = cast(1);
+ for (;;) {
+ switch (yytoken) {
+ case '*': op = OMUL; fun = arithmetic; break;
+ case '/': op = ODIV; fun = arithmetic; break;
+ case '%': op = OMOD; fun = integerop; break;
+ default: return np;
+ }
+ next();
+ np = (*fun)(op, np, cast(1));
+ }
+}
+
+static Node *
+add(void)
+{
+ int op;
+ Node *np;
+
+ np = mul();
+ for (;;) {
+ switch (yytoken) {
+ case '+': op = OADD; break;
+ case '-': op = OSUB; break;
+ default: return np;
+ }
+ next();
+ np = arithmetic(op, np, mul());
+ }
+}
+
+static Node *
+shift(void)
+{
+ int op;
+ Node *np;
+
+ np = add();
+ for (;;) {
+ switch (yytoken) {
+ case SHL: op = OSHL; break;
+ case SHR: op = OSHR; break;
+ default: return np;
+ }
+ next();
+ np = integerop(op, np, add());
+ }
+}
+
+static Node *
+relational(void)
+{
+ int op;
+ Node *np;
+
+ np = shift();
+ for (;;) {
+ switch (yytoken) {
+ case '<': op = OLT; break;
+ case '>': op = OGT; break;
+ case GE: op = OGE; break;
+ case LE: op = OLE; break;
+ default: return np;
+ }
+ next();
+ np = compare(op, np, shift());
+ }
+}
+
+static Node *
+eq(void)
+{
+ int op;
+ Node *np;
+
+ np = relational();
+ for (;;) {
+ switch (yytoken) {
+ case EQ: op = OEQ; break;
+ case NE: op = ONE; break;
+ default: return np;
+ }
+ next();
+ np = compare(op, np, relational());
+ }
+}
+
+static Node *
+bit_and(void)
+{
+ Node *np;
+
+ np = eq();
+ while (accept('&'))
+ np = integerop(OBAND, np, eq());
+ return np;
+}
+
+static Node *
+bit_xor(void)
+{
+ Node *np;
+
+ np = bit_and();
+ while (accept('^'))
+ np = integerop(OBXOR, np, bit_and());
+ return np;
+}
+
+static Node *
+bit_or(void)
+{
+ Node *np;
+
+ np = bit_xor();
+ while (accept('|'))
+ np = integerop(OBOR, np, bit_xor());
+ return np;
+}
+
+static Node *
+and(void)
+{
+ Node *np;
+
+ np = bit_or();
+ while (accept(AND))
+ np = logic(OAND, np, bit_or());
+ return np;
+}
+
+static Node *
+or(void)
+{
+ Node *np;
+
+ np = and();
+ while (accept(OR))
+ np = logic(OOR, np, and());
+ return np;
+}
+
+static Node *
+ternary(void)
+{
+ Node *cond;
+
+ cond = or();
+ while (accept('?')) {
+ Node *ifyes, *ifno, *np;
+
+ cond = exp2cond(cond, 0);
+ ifyes = xexpr();
+ expect(':');
+ ifno = ternary();
+ np = chkternary(ifyes, ifno);
+ cond = node(OASK, np->type, cond, np);
+ }
+ return cond;
+}
+
+static Node *
+xassign(void)
+{
+ Node *np, *(*fun)(int , Node *, Node *);
+ int op;
+
+ np = ternary();
+ for (;;) {
+ switch (yytoken) {
+ case '=': op = OASSIGN; fun = assignop; break;
+ case MUL_EQ: op = OA_MUL; fun = arithmetic; break;
+ case DIV_EQ: op = OA_DIV; fun = arithmetic; break;
+ case MOD_EQ: op = OA_MOD; fun = integerop; break;
+ case ADD_EQ: op = OA_ADD; fun = arithmetic; break;
+ case SUB_EQ: op = OA_SUB; fun = arithmetic; break;
+ case SHL_EQ: op = OA_SHL; fun = integerop; break;
+ case SHR_EQ: op = OA_SHR; fun = integerop; break;
+ case AND_EQ: op = OA_AND; fun = integerop; break;
+ case XOR_EQ: op = OA_XOR; fun = integerop; break;
+ case OR_EQ: op = OA_OR; fun = integerop; break;
+ default: return np;
+ }
+ chklvalue(np);
+ np->flags |= NEFFECT;
+ next();
+ np = (fun)(op, np, assign());
+ }
+}
+
+static Node *
+xexpr(void)
+{
+ Node *lp, *rp;
+
+ lp = xassign();
+ while (accept(',')) {
+ rp = xassign();
+ lp = node(OCOMMA, rp->type, lp, rp);
+ }
+ return lp;
+}
+
+Node *
+assign(void)
+{
+ return simplify(xassign());
+}
+
+Node *
+constexpr(void)
+{
+ Node *np;
+
+ np = ternary();
+ if (np && np->type->op == INT) {
+ np = simplify(convert(np, inttype, 0));
+ if (np->flags & NCONST)
+ return np;
+ }
+ freetree(np);
+ return NULL;
+}
+
+Node *
+expr(void)
+{
+ return simplify(xexpr());
+}
+
+Node *
+condexpr(int neg)
+{
+ Node *np;
+
+ np = exp2cond(xexpr(), neg);
+ if (np->flags & NCONST)
+ warn("conditional expression is constant");
+ return simplify(np);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/fold.c
@@ -1,0 +1,684 @@
+#include <assert.h>
+#include <stdlib.h>
+
+#include <scc/scc.h>
+#include "cc1.h"
+
+
+TUINT
+ones(int nbytes)
+{
+ return (nbytes == 8) ? -1 : ~(-1ull << nbytes * 8);
+}
+
+static int
+addi(TINT l, TINT r, Type *tp)
+{
+ struct limits *lim = getlimits(tp);
+ TINT max = lim->max.i, min = -lim->min.i;
+
+ if (l < 0 && r < 0 && l >= min - r ||
+ l == 0 ||
+ r == 0 ||
+ l < 0 && r > 0 ||
+ l > 0 && r < 0 ||
+ l > 0 && r > 0 && l <= max - r) {
+ return 1;
+ }
+ warn("overflow in constant expression");
+ return 0;
+}
+
+static int
+addf(TFLOAT l, TFLOAT r, Type *tp)
+{
+ struct limits *lim = getlimits(tp);
+ TFLOAT max = lim->max.f, min = lim->min.f;
+
+ if (l < 0 && r < 0 && l >= min - r ||
+ l == 0 ||
+ r == 0 ||
+ l < 0 && r > 0 ||
+ l > 0 && r < 0 ||
+ l > 0 && r > 0 && l <= max - r) {
+ return 1;
+ }
+ warn("overflow in constant expression");
+ return 0;
+}
+
+static int
+subi(TINT l, TINT r, Type *tp)
+{
+ return addi(l, -r, tp);
+}
+
+static int
+subf(TFLOAT l, TFLOAT r, Type *tp)
+{
+ return addf(l, -r, tp);
+}
+
+static int
+muli(TINT l, TINT r, Type *tp)
+{
+ struct limits *lim = getlimits(tp);
+ TINT max = lim->max.i, min = -lim->min.i;
+
+ if (l > -1 && l <= 1 ||
+ r > -1 && r <= 1 ||
+ l < 0 && r < 0 && -l <= max/-r ||
+ l < 0 && r > 0 && l >= min/r ||
+ l > 0 && r < 0 && r >= min/l ||
+ l > 0 && r > 0 && l <= max/r) {
+ return 1;
+ }
+ warn("overflow in constant expression");
+ return 0;
+}
+
+static int
+mulf(TFLOAT l, TFLOAT r, Type *tp)
+{
+ struct limits *lim = getlimits(tp);
+ TFLOAT max = lim->max.f, min = lim->min.f;
+
+ if (l > -1 && l <= 1 ||
+ r > -1 && r <= 1 ||
+ l < 0 && r < 0 && -l <= max/-r ||
+ l < 0 && r > 0 && l >= min/r ||
+ l > 0 && r < 0 && r >= min/l ||
+ l > 0 && r > 0 && l <= max/r) {
+ return 1;
+ }
+ warn("overflow in constant expression");
+ return 0;
+}
+
+static int
+divi(TINT l, TINT r, Type *tp)
+{
+ struct limits *lim = getlimits(tp);
+
+ if (r == 0 || l == -lim->min.i && r == -1) {
+ warn("overflow in constant expression");
+ return 0;
+ }
+ return 1;
+}
+
+static int
+divf(TFLOAT l, TFLOAT r, Type *tp)
+{
+ struct limits *lim = getlimits(tp);
+
+ if (l < 0) l = -l;
+ if (r < 0) r = -r;
+
+ if (r == 0.0 || r < 1.0 && l > lim->max.f * r) {
+ warn("overflow in constant expression");
+ return 0;
+ }
+ return 1;
+}
+
+static int
+lshi(TINT l, TINT r, Type *tp)
+{
+ if (r < 0 || r >= tp->size * 8) {
+ warn("shifting %d bits is undefined", r);
+ return 0;
+ }
+ return muli(l, 1 << r, tp);
+}
+
+static int
+rshi(TINT l, TINT r, Type *tp)
+{
+ if (r < 0 || r >= tp->size * 8) {
+ warn("shifting %d bits is undefined", r);
+ return 0;
+ }
+ return 1;
+}
+
+static int
+foldint(int op, Symbol *res, TINT l, TINT r)
+{
+ TINT i;
+ Type *tp = res->type;
+ int (*validate)(TINT, TINT, Type *tp);
+
+ switch (op) {
+ case OADD: validate = addi; break;
+ case OSUB: validate = subi; break;
+ case OMUL: validate = muli; break;
+ case ODIV: validate = divi; break;
+ case OSHL: validate = lshi; break;
+ case OSHR: validate = rshi; break;
+ case OMOD: validate = divi; break;
+ default: validate = NULL; break;
+ }
+
+ if (validate && !(*validate)(l, r, tp))
+ return 0;
+
+ switch (op) {
+ case OADD: i = l + r; break;
+ case OSUB: i = l - r; break;
+ case OMUL: i = l * r; break;
+ case ODIV: i = l / r; break;
+ case OMOD: i = l % r; break;
+ case OSHL: i = l << r; break;
+ case OSHR: i = l >> r; break;
+ case OBAND: i = l & r; break;
+ case OBXOR: i = l ^ r; break;
+ case OBOR: i = l | r; break;
+ case OAND: i = l && r; break;
+ case OOR: i = l || r; break;
+ case OLT: i = l < r; break;
+ case OGT: i = l > r; break;
+ case OGE: i = l >= r; break;
+ case OLE: i = l <= r; break;
+ case OEQ: i = l == r; break;
+ case ONE: i = l != r; break;
+ case ONEG: i = !l; break;
+ case OSNEG: i = -l; break;
+ case OCPL: i = ~l; break;
+ default: return 0;
+ }
+ res->u.i = i;
+
+ DBG("FOLD i l=%lld %d r=%lld = %lld", l, op, r, i);
+ return 1;
+}
+
+static int
+folduint(int op, Symbol *res, TUINT l, TUINT r)
+{
+ TINT i;
+ TUINT u;
+
+ switch (op) {
+ case OADD: u = l + r; break;
+ case OSUB: u = l - r; break;
+ case OMUL: u = l * r; break;
+ case ODIV: u = l / r; break;
+ case OMOD: u = l % r; break;
+ case OSHL: u = l << r; break;
+ case OSHR: u = l >> r; break;
+ case OBAND: u = l & r; break;
+ case OBXOR: u = l ^ r; break;
+ case OBOR: u = l | r; break;
+ case ONEG: u = !l; break;
+ case OSNEG: u = -l; break;
+ case OCPL: u = ~l; break;
+ case OAND: i = l && r; goto sign;
+ case OOR: i = l || r; goto sign;
+ case OLT: i = l < r; goto sign;
+ case OGT: i = l > r; goto sign;
+ case OGE: i = l >= r; goto sign;
+ case OLE: i = l <= r; goto sign;
+ case OEQ: i = l == r; goto sign;
+ case ONE: i = l != r; goto sign;
+ default: return 0;
+ }
+ res->u.u = u & ones(res->type->size);
+
+ DBG("FOLD ui l=%llu %d r=%llu = %llu", l, op, r, u);
+ return 1;
+
+sign:
+ res->u.i = i;
+
+ DBG("FOLD sui %llu %d %llu = %llu", l, op, r, i);
+ return 1;
+}
+
+static int
+foldfloat(int op, Symbol *res, TFLOAT l, TFLOAT r)
+{
+ TFLOAT f;
+ TINT i;
+ int (*validate)(TFLOAT, TFLOAT, Type *tp);
+
+ switch (op) {
+ case OADD: validate = addf; break;
+ case OSUB: validate = subf; break;
+ case OMUL: validate = mulf; break;
+ case ODIV: validate = divf; break;
+ default: validate = NULL; break;
+ }
+
+ if (validate && !(*validate)(l, r, res->type))
+ return 0;
+
+ switch (op) {
+ case OADD: f = l + r; break;
+ case OSUB: f = l - r; break;
+ case OMUL: f = l * r; break;
+ case ODIV: f = l / r; break;
+ case OLT: i = l < r; goto comparison;
+ case OGT: i = l > r; goto comparison;
+ case OGE: i = l >= r; goto comparison;
+ case OLE: i = l <= r; goto comparison;
+ case OEQ: i = l == r; goto comparison;
+ case ONE: i = l != r; goto comparison;
+ default: return 0;
+ }
+ res->u.f = f;
+
+ DBG("FOLD f l=%lf %d r=%lf = %lf", l, op, r, f);
+ return 1;
+
+comparison:
+ res->u.i = i;
+
+ DBG("FOLD if l=%lf %d r=%lf = %lld", l, op, r, i);
+ return 1;
+}
+
+static Node *
+foldconst(int type, int op, Type *tp, Symbol *ls, Symbol *rs)
+{
+ Symbol *sym, aux;
+ TINT i;
+ TUINT u;
+ TFLOAT f;
+
+ aux.type = tp;
+ switch (type) {
+ case INT:
+ i = (rs) ? rs->u.i : 0;
+ if (!foldint(op, &aux, ls->u.i, i))
+ return NULL;
+ break;
+ case UNSIGNED:
+ u = (rs) ? rs->u.u : 0u;
+ if (!folduint(op, &aux, ls->u.u, u))
+ return NULL;
+ break;
+ case FLOAT:
+ f = (rs) ? rs->u.f : 0.0;
+ if (!foldfloat(op, &aux, ls->u.f, f))
+ return NULL;
+ break;
+ }
+ sym = newsym(NS_IDEN, NULL);
+ sym->flags |= SCONSTANT;
+ sym->type = tp;
+ sym->u = aux.u;
+ return constnode(sym);
+}
+
+static Node *
+foldcast(Node *np, Node *l)
+{
+ TUINT negmask, mask, u;
+ Type *newtp = np->type, *oldtp = l->type;
+ Symbol aux, *sym, *osym = l->sym;
+
+ if (!(l->flags & NCONST))
+ return np;
+
+ switch (newtp->op) {
+ case PTR:
+ case INT:
+ case ENUM:
+ switch (oldtp->op) {
+ case PTR:
+ case INT:
+ case ENUM:
+ u = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
+ break;
+ case FLOAT:
+ oldtp = newtp;
+ u = osym->u.f;
+ break;
+ default:
+ return np;
+ }
+ mask = ones(newtp->size);
+ if (newtp->prop & TSIGNED) {
+ negmask = ~mask;
+ if (u & (negmask >> 1) & mask)
+ u |= negmask;
+ aux.u.i = u;
+ } else {
+ aux.u.u = u & mask;
+ }
+ break;
+ case FLOAT:
+ /* FIXME: The cast can be from another float type */
+ aux.u.f = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
+ break;
+ default:
+ return np;
+ }
+ DBG("FOLD cast %c->%c", oldtp->letter, newtp->letter);
+ freetree(np);
+ sym = newsym(NS_IDEN, NULL);
+ sym->flags |= SCONSTANT;
+ sym->type = newtp;
+ sym->u = aux.u;
+ return constnode(sym);
+}
+
+static Node *
+foldunary(Node *np, Node *l)
+{
+ int op = l->op;
+ Node *aux;
+
+ switch (np->op) {
+ case ONEG:
+ if (l->op == ONEG)
+ break;
+ return NULL;
+ case OADD:
+ DBG("FOLD unary delete %d", np->op);
+ np->left = NULL;
+ freetree(np);
+ return l;
+ case OCAST:
+ if (op != OCAST)
+ return foldcast(np, l);
+ /* TODO: This is wrong: (float)(int) 7.2 */
+ DBG("FOLD unary collapse %d", np->op);
+ np->left = l->left;
+ l->left = NULL;
+ freetree(l);
+ return np;
+ case OSNEG:
+ case OCPL:
+ if (op != np->op)
+ return NULL;
+ break;
+ case OPTR:
+ if (op != OADDR || np->type != l->left->type)
+ return NULL;
+ break;
+ case OADDR:
+ if (op != OPTR)
+ return NULL;
+ break;
+ default:
+ return NULL;
+ }
+ DBG("FOLD unary cancel %d", np->op);
+ aux = l->left;
+ l->left = NULL;
+ freetree(np);
+ return aux;
+}
+
+static Node *
+fold(Node *np)
+{
+ Symbol *rs, *ls;
+ Type *optype;
+ int type;
+ int op = np->op;
+ Node *p, *lp = np->left, *rp = np->right;
+ Type *tp = np->type;
+
+ assert(lp && rp);
+ if ((op == ODIV || op == OMOD) && cmpnode(rp, 0)) {
+ warn("division by 0");
+ return NULL;
+ }
+ /*
+ * Return if any of the children is no constant,
+ * or it is a constant generated when
+ * the address of a static variable is taken
+ * (when we don't know the physical address so
+ * we cannot fold it)
+ */
+ if (!rp) {
+ rs = NULL;
+ } else {
+ if (!(rp->flags & NCONST) || !rp->sym)
+ return NULL;
+ rs = rp->sym;
+ }
+
+ if (!(lp->flags & NCONST) || !lp->sym)
+ return NULL;
+ optype = lp->type;
+ ls = lp->sym;
+
+ switch (type = optype->op) {
+ case ENUM:
+ case INT:
+ if (!(optype->prop & TSIGNED))
+ type = UNSIGNED;
+ case PTR:
+ case FLOAT:
+ if ((p = foldconst(type, op, tp, ls, rs)) == NULL)
+ return NULL;
+ freetree(np);
+ return p;
+ default:
+ return NULL;
+ }
+}
+
+static void
+commutative(Node *np, Node *l, Node *r)
+{
+ int op = np->op;
+
+ if (r == NULL || r->flags&NCONST || !(l->flags&NCONST))
+ return;
+
+ switch (op) {
+ case OLT:
+ case OGT:
+ case OGE:
+ case OLE:
+ DBG("FOLD neg commutative %d", np->op);
+ np->op = negop(op);
+ case OEQ:
+ case ONE:
+ case OADD:
+ case OMUL:
+ case OBAND:
+ case OBXOR:
+ case OBOR:
+ DBG("FOLD commutative %d", np->op);
+ np->left = r;
+ np->right = l;
+ break;
+ }
+}
+
+static Node *
+identity(Node *np)
+{
+ int iszeror, isoner;
+ int iszerol, isonel;
+ Node *lp = np->left, *rp = np->right;
+
+ if (!rp)
+ return NULL;
+
+ iszeror = cmpnode(rp, 0);
+ isoner = cmpnode(rp, 1),
+ iszerol = cmpnode(lp, 0);
+ isonel = cmpnode(lp, 1);
+
+ switch (np->op) {
+ case OOR:
+ /*
+ * 1 || i => 1 (free right)
+ * i || 0 => i (free right)
+ * 0 || i => i (free left)
+ * i || 1 => i,1 (comma)
+ */
+ if (isonel | iszeror)
+ goto free_right;
+ if (iszerol)
+ goto free_left;
+ if (isoner)
+ goto change_to_comma;
+ return NULL;
+ case OAND:
+ /*
+ * 0 && i => 0 (free right)
+ * i && 1 => i (free right)
+ * 1 && i => i (free left)
+ * i && 0 => i,0 (comma)
+ */
+ if (iszerol | isoner)
+ goto free_right;
+ if (isonel)
+ goto free_left;
+ if (iszeror)
+ goto change_to_comma;
+ return NULL;
+ case OSHL:
+ case OSHR:
+ /*
+ * i >> 0 => i (free right)
+ * i << 0 => i (free right)
+ * 0 >> i => 0 (free right)
+ * 0 << i => 0 (free right)
+ */
+ if (iszeror | iszerol)
+ goto free_right;
+ return NULL;
+ case OBXOR:
+ case OADD:
+ case OBOR:
+ case OSUB:
+ /*
+ * i + 0 => i
+ * i - 0 => i
+ * i | 0 => i
+ * i ^ 0 => i
+ */
+ if (iszeror)
+ goto free_right;
+ return NULL;
+ case OMUL:
+ /*
+ * i * 0 => i,0
+ * i * 1 => i
+ */
+ if (iszeror)
+ goto change_to_comma;
+ if (isoner)
+ goto free_right;
+ return NULL;
+ case ODIV:
+ /* i / 1 => i */
+ if (isoner)
+ goto free_right;
+ return NULL;
+ case OBAND:
+ /* i & ~0 => i */
+ if (cmpnode(rp, -1))
+ goto free_right;
+ return NULL;
+ case OMOD:
+ /* i % 1 => i,1 */
+ /* TODO: i % 2^n => i & n-1 */
+ if (isoner)
+ goto change_to_comma;
+ default:
+ return NULL;
+ }
+
+free_right:
+ DBG("FOLD identity %d", np->op);
+ np->left = NULL;
+ freetree(np);
+ return lp;
+
+free_left:
+ DBG("FOLD identity %d", np->op);
+ np->right = NULL;
+ freetree(np);
+ return rp;
+
+change_to_comma:
+ DBG("FOLD identity %d", np->op);
+ np->op = OCOMMA;
+ return np;
+}
+
+static Node *
+foldternary(Node *np, Node *cond, Node *body)
+{
+ if (!(cond->flags & NCONST))
+ return np;
+ if (cmpnode(cond, 0)) {
+ np = body->right;
+ freetree(body->left);
+ } else {
+ np = body->left;
+ freetree(body->right);
+ }
+
+ DBG("FOLD ternary");
+ body->left = NULL;
+ body->right = NULL;
+ freetree(cond);
+ free(body);
+ return np;
+}
+
+/* TODO: fold OCOMMA */
+
+Node *
+simplify(Node *np)
+{
+ Node *p, *l, *r;
+
+ if (!np)
+ return NULL;
+ if (enadebug)
+ prtree(np);
+
+ l = np->left = simplify(np->left);
+ r = np->right = simplify(np->right);
+
+ switch (np->op) {
+ case OASK:
+ return foldternary(np, l, r);
+ case OCALL:
+ case OPAR:
+ case OSYM:
+ case OASSIGN:
+ case OA_MUL:
+ case OA_DIV:
+ case OA_MOD:
+ case OA_ADD:
+ case OA_SUB:
+ case OA_SHL:
+ case OA_SHR:
+ case OA_AND:
+ case OA_XOR:
+ case OA_OR:
+ return np;
+ case OSNEG:
+ case OCPL:
+ case OADDR:
+ case OPTR:
+ case INC:
+ case DEC:
+ case OCAST:
+ case ONEG:
+ assert(!r);
+ if ((p = foldunary(np, l)) != NULL)
+ return p;
+ return np;
+ default:
+ commutative(np, l, r);
+ if ((p = fold(np)) != NULL)
+ return p;
+ if ((p = identity(np)) != NULL)
+ return p;
+ return np;
+ }
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/init.c
@@ -1,0 +1,377 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+
+typedef struct init Init;
+
+struct designator {
+ TINT pos;
+ Node *expr;
+ struct designator *next;
+};
+
+struct init {
+ TUINT pos;
+ TUINT max;
+ struct designator *tail;
+ struct designator *head;
+};
+
+static TINT
+arydesig(Type *tp, Init *ip)
+{
+ TINT npos;
+ Node *np;
+
+ if (tp->op != ARY)
+ errorp("array index in non-array initializer");
+ next();
+ np = constexpr();
+ npos = np->sym->u.i;
+ if (npos < 0 || (tp->prop & TDEFINED) && npos >= tp->n.elem) {
+ errorp("array index in initializer exceeds array bounds");
+ npos = 0;
+ }
+ freetree(np);
+ expect(']');
+ return npos;
+}
+
+static TINT
+fielddesig(Type *tp, Init *ip)
+{
+ int ons;
+ Symbol *sym, **p;
+
+ if (!(tp->prop & TAGGREG))
+ errorp("field name not in record or union initializer");
+ ons = namespace;
+ namespace = tp->ns;
+ next();
+ namespace = ons;
+ if (yytoken != IDEN)
+ unexpected();
+ sym = yylval.sym;
+ next();
+ if ((sym->flags & SDECLARED) == 0) {
+ errorp("unknown field '%s' specified in initializer",
+ sym->name);
+ return 0;
+ }
+ for (p = tp->p.fields; *p != sym; ++p)
+ ;
+ return p - tp->p.fields;
+}
+
+static Init *
+init(Init *ip)
+{
+ ip->tail = ip->head = NULL;
+ ip->pos = ip->max = 0;
+ return ip;
+}
+
+static Node *
+str2ary(Type *tp)
+{
+ Node *np;
+ Type *btp = tp->type;;
+ Symbol *sym;
+ size_t len;
+ char *s;
+
+ np = assign();
+ sym = np->left->sym;
+ if (btp != chartype && btp != uchartype && btp != schartype) {
+ errorp("array of inappropriate type initialized from string constant");
+ return constnode(zero);
+ }
+
+ len = sym->type->n.elem-1;
+ if (!(tp->prop & TDEFINED)) {
+ tp->n.elem = len+1;
+ deftype(tp);
+ } else if (tp->n.elem < len) {
+ warn("initializer-string for array of chars is too long");
+ }
+
+ len = tp->n.elem;
+ s = sym->u.s;
+ sym = newstring(NULL, len);
+ strncpy(sym->u.s, s, len);
+ np->sym = sym;
+ np->type = sym->type;
+
+ return np;
+}
+
+static Node *
+initialize(Type *tp)
+{
+ Node *np;
+ Symbol *sym;
+
+ if (tp->op == ARY && yytoken == STRING)
+ return str2ary(tp);
+
+ if (yytoken == '{' || tp->op == STRUCT || tp->op == ARY)
+ return initlist(tp);
+
+ np = assign();
+ if (eqtype(tp, np->type, 1))
+ return np;
+
+ np = convert(decay(np), tp, 0);
+ if (!np) {
+ errorp("incorrect initializer");
+ return constnode(zero);
+ }
+
+ return simplify(np);
+}
+
+static Node *
+mkcompound(Init *ip, Type *tp)
+{
+ Node **v, **p;
+ size_t n;
+ struct designator *dp, *next;
+ Symbol *sym;
+
+ if (tp->op == UNION) {
+ Node *np = NULL;
+
+ v = xmalloc(sizeof(*v));
+ for (dp = ip->head; dp; dp = next) {
+ freetree(np);
+ np = dp->expr;
+ next = dp->next;
+ free(dp);
+ }
+ *v = np;
+ } else {
+ n = (tp->prop&TDEFINED) ? tp->n.elem : ip->max;
+ if (n == 0) {
+ v = NULL;
+ } else if (n > SIZE_MAX / sizeof(*v)) {
+ errorp("compound literal too big");
+ return constnode(zero);
+ } else {
+ n *= sizeof(*v);
+ v = memset(xmalloc(n), 0, n);
+
+ for (dp = ip->head; dp; dp = next) {
+ p = &v[dp->pos];
+ freetree(*p);
+ *p = dp->expr;
+ next = dp->next;
+ free(dp);
+ }
+ }
+ }
+
+ sym = newsym(NS_IDEN, NULL);
+ sym->u.init = v;
+ sym->type = tp;
+ sym->flags |= SINITLST;
+
+ return constnode(sym);
+}
+
+static void
+newdesig(Init *ip, Node *np)
+{
+ struct designator *dp;
+
+ dp = xmalloc(sizeof(*dp));
+ dp->pos = ip->pos;
+ dp->expr = np;
+ dp->next = NULL;
+
+ if (ip->head == NULL) {
+ ip->head = ip->tail = dp;
+ } else {
+ ip->tail->next = dp;
+ ip->tail = dp;
+ }
+
+ if (ip->pos+1 > ip->max)
+ ip->max = ip->pos+1;
+}
+
+Node *
+initlist(Type *tp)
+{
+ Init in;
+ Node *np;
+ Type *curtp;
+ int braces, scalar, toomany, outbound;
+ TINT nelem = tp->n.elem;
+ static int depth;
+
+ if (depth == NR_SUBTYPE)
+ error("too many nested initializers");
+ ++depth;
+ init(&in);
+ braces = scalar = toomany = 0;
+
+ if (accept('{'))
+ braces = 1;
+
+ do {
+ curtp = inttype;
+ switch (yytoken) {
+ case '[':
+ in.pos = arydesig(tp, &in);
+ curtp = tp->type;
+ goto desig_list;
+ case '.':
+ in.pos = fielddesig(tp, &in);
+ if (in.pos < nelem)
+ curtp = tp->p.fields[in.pos]->type;
+ desig_list:
+ if (yytoken == '[' || yytoken == '.') {
+ np = initlist(curtp);
+ goto new_desig;
+ }
+ expect('=');
+ default:
+ outbound = 0;
+
+ switch (tp->op) {
+ case ARY:
+ curtp = tp->type;
+ if (!(tp->prop & TDEFINED) || in.pos < tp->n.elem)
+ break;
+ if (!toomany)
+ warn("excess elements in array initializer");
+ toomany = 1;
+ outbound = 1;
+ break;
+ case UNION:
+ case STRUCT:
+ if (in.pos < nelem) {
+ curtp = tp->p.fields[in.pos]->type;
+ break;
+ }
+ if (!toomany)
+ warn("excess elements in struct initializer");
+ toomany = 1;
+ outbound = 1;
+ break;
+ default:
+ curtp = tp;
+ if (!scalar)
+ warn("braces around scalar initializer");
+ scalar = 1;
+ if (in.pos == 0)
+ break;
+ if (!toomany)
+ warn("excess elements in scalar initializer");
+ toomany = 1;
+ outbound = 1;
+ break;
+ }
+ np = initialize(curtp);
+ if (outbound) {
+ freetree(np);
+ np = NULL;
+ }
+ }
+
+new_desig:
+ if (np)
+ newdesig(&in, np);
+ if (++in.pos == 0)
+ errorp("compound literal too big");
+ if (nelem == in.pos && !braces)
+ break;
+ } while (accept(','));
+
+ if (braces)
+ expect('}');
+
+
+ if (tp->op == ARY && !(tp->prop & TDEFINED)) {
+ tp->n.elem = in.max;
+ deftype(tp);
+ }
+ if (in.max == 0) {
+ errorp("empty braced initializer");
+ return constnode(zero);
+ }
+
+ return mkcompound(&in, tp);
+}
+
+static void
+autoinit(Symbol *sym, Node *np)
+{
+ Symbol *hidden;
+ Type *tp = sym->type;
+ size_t n; /* FIXME: It should be SIZET */
+
+repeat:
+ switch (tp->op) {
+ case UNION:
+ np = np->sym->u.init[0];
+ tp = np->type;
+ goto repeat;
+ case ARY:
+ case STRUCT:
+ if (!(np->flags & NCONST))
+ abort(); /* TODO */
+ hidden = newsym(NS_IDEN, NULL);
+ hidden->type = sym->type;
+ hidden->flags |= SLOCAL | SHASINIT;
+ emit(ODECL, hidden);
+ emit(OINIT, np);
+ emit(ODECL, sym);
+ emit(OEXPR,
+ node(OASSIGN, tp, varnode(sym), varnode(hidden)));
+ break;
+ default:
+ emit(ODECL, sym);
+ np = node(OASSIGN, tp, varnode(sym), np);
+ emit(OEXPR, np);
+ break;
+ }
+}
+
+void
+initializer(Symbol *sym, Type *tp)
+{
+ Node *np;
+ int flags = sym->flags;
+
+ if (tp->op == FTN) {
+ errorp("function '%s' initialized like a variable",
+ sym->name);
+ tp = inttype;
+ }
+ np = initialize(tp);
+
+ if (flags & SDEFINED) {
+ errorp("redeclaration of '%s'", sym->name);
+ } else if ((flags & (SGLOBAL|SLOCAL|SPRIVATE)) != 0) {
+ if (!(np->flags & NCONST)) {
+ errorp("initializer element is not constant");
+ return;
+ }
+ sym->flags |= SHASINIT;
+ sym->flags &= ~SEMITTED;
+ emit(ODECL, sym);
+ emit(OINIT, np);
+ sym->flags |= SDEFINED;
+ } else if ((flags & (SEXTERN|STYPEDEF)) != 0) {
+ errorp("'%s' has both '%s' and initializer",
+ sym->name, (flags&SEXTERN) ? "extern" : "typedef");
+ } else {
+ autoinit(sym, np);
+ }
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/ir.md
@@ -1,0 +1,443 @@
+# scc intermediate representation #
+
+The scc IR tries to be be a simple and easily parseable intermediate
+representation, and it makes it a bit terse and cryptic. The main
+characteristic of the IR is that all the types and operations are
+represented with only one letter, so parsing tables can be used
+to parse it.
+
+The language is composed of lines, representing statements.
+Each statement is composed of tab-separated fields.
+Declaration statements begin in column 0, expressions and
+control flow begin with a tabulator.
+When the frontend detects an error, it closes the output stream.
+
+## Types ##
+
+Types are represented with uppercase letters:
+
+* C -- signed 8-Bit integer
+* I -- signed 16-Bit integer
+* W -- signed 32-Bit integer
+* Q -- signed 64-Bit integer
+* K -- unsigned 8-Bit integer
+* N -- unsigned 16-Bit integer
+* Z -- unsigned 32-Bit integer
+* O -- unsigned 64-Bit integer
+* 0 -- void
+* P -- pointer
+* F -- function
+* V -- vector
+* U -- union
+* S -- struct
+* B -- bool
+* J -- float
+* D -- double
+* H -- long double
+
+This list has been built for the original Z80 backend, where 'int'
+has the same size as 'short'. Several types (S, F, V, U and others) need
+an identifier after the type letter for better differentiation
+between multiple structs, functions, vectors and unions (S1, V12 ...)
+naturally occuring in a C-program.
+
+## Storage classes ##
+
+The storage classes are represented using uppercase letters:
+
+* A -- automatic
+* R -- register
+* G -- public (global variable declared in the module)
+* X -- extern (global variable declared in another module)
+* Y -- private (variable in file-scope)
+* T -- local (static variable in function-scope)
+* M -- member (struct/union member)
+* L -- label
+
+## Declarations/definitions ##
+
+Variable names are composed of a storage class and an identifier
+(e.g. A1, R2, T3).
+Declarations and definitions are composed of a variable
+name, a type and the name of the variable:
+
+ A1 I maxweight
+ R2 C flag
+ A3 S4 statstruct
+
+### Type declarations ###
+
+Some declarations (e.g. structs) involve the declaration of member
+variables.
+Struct members are declared normally after the type declaration in
+parentheses.
+
+For example the struct declaration
+
+ struct foo {
+ int i;
+ long c;
+ } var1;
+
+generates
+
+ S2 foo (
+ M3 I i
+ M4 W c
+ )
+ G5 S2 var1
+
+## Functions ##
+
+A function prototype
+
+ int printf(char *cmd, int flag, void *data);
+
+will generate a type declaration and a variable declaration
+
+ F5 P I P
+ X1 F5 printf
+
+The first line gives the function-type specification 'F' with
+an identifier '5' and subsequently lists the types of the
+function parameters.
+The second line declares the 'printf' function as a publicly
+scoped variable.
+
+Analogously, a statically declared function in file scope
+
+ static int printf(char *cmd, int flag, void *data);
+
+generates
+
+ F5 P I P
+ T1 F5 printf
+
+Thus, the 'printf' variable went into local scope ('T').
+
+A '{' in the first column starts the body of the previously
+declared function:
+
+ int printf(char *cmd, int flag, void *data) {}
+
+generates
+
+ F5 P I P
+ G1 F5 printf
+ {
+ A2 P cmd
+ A3 I flag
+ A4 P data
+ -
+ }
+
+Again, the frontend must ensure that '{' appears only after the
+declaration of a function. The character '-' marks the separation
+between parameters and local variables:
+
+ int printf(register char *cmd, int flag, void *data) {int i;};
+
+generates
+
+ F5 P I P
+ G1 F5 printf
+ {
+ R2 P cmd
+ A3 I flag
+ A4 P data
+ -
+ A6 I i
+ }
+
+### Expressions ###
+
+Expressions are emitted in reverse polish notation, simplifying
+parsing and converting into a tree representation.
+
+#### Operators ####
+
+Operators allowed in expressions are:
+
+* \+ -- addition
+* \- -- substraction
+* \* -- multiplication
+* % -- modulo
+* / -- division
+* l -- left shift
+* r -- right shift
+* < -- less than
+* > -- greather than
+* ] -- greather or equal than
+* [ -- less or equal than
+* = -- equal than
+* ! -- different than
+* & -- bitwise and
+* | -- bitwise or
+* ^ -- bitwise xor
+* ~ -- bitwise complement
+* : -- asignation
+* _ -- unary negation
+* c -- function call
+* p -- parameter
+* . -- field
+* , -- comma operator
+* ? -- ternary operator
+* ' -- take address
+* a -- logical shortcut and
+* o -- logical shortcut or
+* @ -- content of pointer
+
+Assignation has some suboperators:
+
+* :/ -- divide and assign
+* :% -- modulo and assign
+* :+ -- addition and assign
+* :- -- substraction and assign
+* :l -- left shift and assign
+* :r -- right shift and assign
+* :& -- bitwise and and assign
+* :^ -- bitwise xor and assign
+* :| -- bitwise or and assign
+* :i -- post increment
+* :d -- post decrement
+
+Every operator in an expression has a type descriptor.
+
+#### Constants ####
+
+Constants are introduced with the character '#'. For instance, 10 is
+translated to #IA (all constants are emitted in hexadecimal),
+where I indicates that it is an integer constant.
+Strings are a special case because they are represented with
+the " character.
+The constant "hello" is emitted as "68656C6C6F. For example
+
+ int
+ main(void)
+ {
+ int i, j;
+
+ i = j+2*3;
+ }
+
+generates
+
+ F1
+ G1 F1 main
+ {
+ -
+ A2 I i
+ A3 I j
+ A2 A3 #I6 +I :I
+ }
+
+Type casts are expressed with a tuple denoting the
+type conversion
+
+ int
+ main(void)
+ {
+ int i;
+ long j;
+
+ j = (long)i;
+ }
+
+generates
+
+ F1
+ G1 F1 main
+ {
+ -
+ A2 I i
+ A3 W j
+ A2 A3 WI :I
+ }
+
+### Statements ###
+#### Jumps #####
+
+Jumps have the following form:
+
+ j L# [expression]
+
+the optional expression field indicates some condition which
+must be satisfied to jump. Example:
+
+ int
+ main(void)
+ {
+ int i;
+
+ goto label;
+ label:
+ i -= i;
+ }
+
+generates
+
+ F1
+ G1 F1 main
+ {
+ -
+ A2 I i
+ j L3
+ L3
+ A2 A2 :-I
+ }
+
+Another form of jump is the return statement, which uses the
+letter 'y' followed by a type identifier.
+Depending on the type, an optional expression follows.
+
+ int
+ main(void)
+ {
+ return 16;
+ }
+
+generates
+
+ F1
+ G1 F1 main
+ {
+ -
+ yI #I10
+ }
+
+
+#### Loops ####
+
+There are two special characters that are used to indicate
+to the backend that the following statements are part of
+a loop body.
+
+* b -- beginning of loop
+* e -- end of loop
+
+#### Switch statement ####
+
+Switches are represented using a table, in which the labels
+where to jump for each case are indicated. Common cases are
+represented with 'v' and default with 'f'.
+The switch statement itself is represented with 's' followed
+by the label where the jump table is located, and the
+expression of the switch:
+
+ int
+ func(int n)
+ {
+ switch (n+1) {
+ case 1:
+ case 2:
+ case 3:
+ default:
+ ++n;
+ }
+ }
+
+generates
+
+ F2 I
+ G1 F2 func
+ {
+ A1 I n
+ -
+ s L4 A1 #I1 +I
+ L5
+ L6
+ L7
+ L8
+ A1 #I1 :+I
+ j L3
+ L4
+ t #4
+ v L7 #I3
+ v L6 #I2
+ v L5 #I1
+ f L8
+ L3
+ }
+
+The beginning of the jump table is indicated by the the letter 't',
+followed by the number of cases (including default case) of the
+switch.
+
+## Resumen ##
+
+* C -- signed 8-Bit integer
+* I -- signed 16-Bit integer
+* W -- signed 32-Bit integer
+* O -- signed 64-Bit integer
+* M -- unsigned 8-Bit integer
+* N -- unsigned 16-Bit integer
+* Z -- unsigned 32-Bit integer
+* Q -- unsigned 64-Bit integer
+* 0 -- void
+* P -- pointer
+* F -- function
+* V -- vector
+* U -- union
+* S -- struct
+* B -- bool
+* J -- float
+* D -- double
+* H -- long double
+* A -- automatic
+* R -- register
+* G -- public (global variable declared in the module)
+* X -- extern (global variable declared in another module)
+* Y -- private (variable in file-scope)
+* T -- local (static variable in function-scope)
+* M -- member (struct/union member)
+* L -- label
+* { -- beginning of function body
+* } -- end of function body
+* \\ -- end of function parameters
+* \+ -- addition
+* \- -- substraction
+* \* -- multiplication
+* % -- modulo
+* / -- division
+* l -- left shift
+* r -- right shift
+* < -- less than
+* > -- greather than
+* ] -- greather or equal than
+* [ -- less or equal than
+* = -- equal than
+* ! -- different than
+* & -- bitwise and
+* | -- bitwise or
+* ^ -- bitwise xor
+* ~ -- bitwise complement
+* : -- asignation
+* _ -- unary negation
+* c -- function call
+* p -- parameter
+* . -- field
+* , -- comma operator
+* ? -- ternary operator
+* ' -- take address
+* a -- logical shortcut and
+* o -- logical shortcut or
+* @ -- content of pointer
+* :/ -- divide and assign
+* :% -- modulo and assign
+* :+ -- addition and assign
+* :- -- substraction and assign
+* :l -- left shift and assign
+* :r -- right shift and assign
+* :& -- bitwise and and assign
+* :^ -- bitwise xor and assign
+* :| -- bitwise or and assign
+* ;+ -- post increment
+* ;- -- post decrement
+* j -- jump
+* y -- return
+* b -- begin of loop
+* d -- end of loop
+* s -- switch statement
+* t -- switch table
+* v -- case entry in switch table
+* f -- default entry in switch table
--- /dev/null
+++ b/src/cmd/cc/cc1/lex.c
@@ -1,0 +1,800 @@
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+int yytoken;
+struct yystype yylval;
+char yytext[STRINGSIZ+3];
+unsigned short yylen;
+int lexmode = CCMODE;
+unsigned lineno;
+char filenam[FILENAME_MAX];
+
+int namespace = NS_IDEN;
+static int safe;
+Input *input;
+
+void
+ilex(void)
+{
+ static struct keyword keys[] = {
+ {"auto", SCLASS, AUTO},
+ {"break", BREAK, BREAK},
+ {"_Bool", TYPE, BOOL},
+ {"__builtin_va_list", TYPE, VA_LIST},
+ {"case", CASE, CASE},
+ {"char", TYPE, CHAR},
+ {"const", TQUALIFIER, CONST},
+ {"continue", CONTINUE, CONTINUE},
+ {"default", DEFAULT, DEFAULT},
+ {"do", DO, DO},
+ {"double", TYPE, DOUBLE},
+ {"else", ELSE, ELSE},
+ {"enum", TYPE, ENUM},
+ {"extern", SCLASS, EXTERN},
+ {"float", TYPE, FLOAT},
+ {"for", FOR, FOR},
+ {"goto", GOTO, GOTO},
+ {"if", IF, IF},
+ {"inline", TQUALIFIER, INLINE},
+ {"int", TYPE, INT},
+ {"long", TYPE, LONG},
+ {"register", SCLASS, REGISTER},
+ {"restrict", TQUALIFIER, RESTRICT},
+ {"return", RETURN, RETURN},
+ {"short", TYPE, SHORT},
+ {"signed", TYPE, SIGNED},
+ {"sizeof", SIZEOF, SIZEOF},
+ {"static", SCLASS, STATIC},
+ {"struct", TYPE, STRUCT},
+ {"switch", SWITCH, SWITCH},
+ {"typedef", SCLASS, TYPEDEF},
+ {"union", TYPE, UNION},
+ {"unsigned", TYPE, UNSIGNED},
+ {"void", TYPE, VOID},
+ {"volatile", TQUALIFIER, VOLATILE},
+ {"while", WHILE, WHILE},
+ {NULL, 0, 0},
+ };
+ keywords(keys, NS_KEYWORD);
+}
+
+void
+setloc(char *fname, unsigned line)
+{
+ size_t len;
+
+ if ((len = strlen(fname)) >= FILENAME_MAX)
+ die("cc1: %s: file name too long", fname);
+ memmove(filenam, fname, len);
+ filenam[len] = '\0';
+
+ free(input->filenam);
+ input->filenam = xstrdup(fname);
+ lineno = input->lineno = line;
+}
+
+void
+addinput(char *fname, Symbol *hide, char *buffer)
+{
+ FILE *fp;
+ char *extp;
+ unsigned flags;
+ int infileln;
+ Input *newip, *curip = input;
+
+ if (hide) {
+ /* this is a macro expansion */
+ fp = NULL;
+ if (hide->hide == UCHAR_MAX)
+ die("cc1: too many macro expansions");
+ ++hide->hide;
+ flags = IMACRO;
+ } else if (fname) {
+ /* a new file */
+ if ((fp = fopen(fname, "r")) == NULL)
+ die("cc1: %s: %s", fname, strerror(errno));
+ flags = IFILE;
+ if (curip && onlyheader) {
+ infileln = strlen(infile);
+ if (extp = strrchr(infile, '.'))
+ infileln -= strlen(extp);
+ printf("%.*s.o: %s %s\n",
+ infileln, infile, infile, fname);
+ }
+ } else {
+ /* reading from stdin */
+ fp = stdin;
+ fname = "<stdin>";
+ flags = ISTDIN;
+ }
+
+ newip = xmalloc(sizeof(*newip));
+
+ if (!buffer) {
+ buffer = xmalloc(INPUTSIZ);
+ buffer[0] = '\0';
+ }
+
+ if (curip)
+ curip->lineno = lineno;
+
+ newip->p = newip->begin = newip->line = buffer;
+ newip->filenam = NULL;
+ newip->lineno = 0;
+ newip->next = curip;
+ newip->fp = fp;
+ newip->hide = hide;
+ newip->flags = flags;
+ input = newip;
+
+ setloc(fname, (curip) ? curip->lineno : newip->lineno);
+}
+
+void
+delinput(void)
+{
+ Input *ip = input;
+ Symbol *hide = ip->hide;
+
+ switch (ip->flags & ITYPE) {
+ case IFILE:
+ if (fclose(ip->fp))
+ die("cc1: %s: %s", ip->filenam, strerror(errno));
+ break;
+ case IMACRO:
+ assert(hide->hide == 1);
+ --hide->hide;
+ break;
+ }
+ input = ip->next;
+ free(ip->filenam);
+ free(ip->line);
+ if (input) {
+ lineno = input->lineno;
+ strcpy(filenam, input->filenam);
+ }
+}
+
+static void
+newline(void)
+{
+ if (++lineno == 0)
+ die("cc1: %s: file too long", filenam);
+}
+
+/*
+ * Read the next character from the input file, counting number of lines
+ * and joining lines escaped with \
+ */
+static int
+readchar(void)
+{
+ FILE *fp = input->fp;
+ int c;
+
+repeat:
+ switch (c = getc(fp)) {
+ case '\\':
+ if ((c = getc(fp)) == '\n') {
+ newline();
+ goto repeat;
+ }
+ ungetc(c, fp);
+ c = '\\';
+ break;
+ case '\n':
+ newline();
+ break;
+ default:
+ if (!isprint(c) && !ispunct(c) && !isspace(c))
+ warn("invalid input character. The shame of UB is yours");
+ break;
+ }
+
+ return c;
+}
+
+/*
+ * discard a C comment. This function is only called from readline
+ * because it is impossible to have a comment in a macro, because
+ * comments are always discarded before processing any cpp directive
+ */
+static void
+comment(int type)
+{
+ int c;
+
+repeat:
+ while ((c = readchar()) != EOF && c != type)
+ ;
+
+ if (c == EOF) {
+ errorp("unterminated comment");
+ return;
+ }
+
+ if (type == '*' && (c = readchar()) != '/')
+ goto repeat;
+}
+
+/*
+ * readline is used to read a full logic line from a file.
+ * It discards comments and check that the line fits in
+ * the input buffer
+ */
+static int
+readline(void)
+{
+ char *bp, *lim;
+ int c, peekc = 0;
+
+ if (feof(input->fp)) {
+ input->flags |= IEOF;
+ return 0;
+ }
+
+ *input->line = '\0';
+ lim = &input->line[INPUTSIZ-1];
+ for (bp = input->line; bp < lim-1; *bp++ = c) {
+ c = (peekc) ? peekc : readchar();
+ peekc = 0;
+ if (c == '\n' || c == EOF)
+ break;
+ if (c != '/')
+ continue;
+
+ /* check for /* or // */
+ peekc = readchar();
+ if (peekc != '*' && peekc != '/')
+ continue;
+ comment((peekc == '/') ? '\n' : '*');
+ peekc = 0;
+ c = ' ';
+ }
+
+ input->begin = input->p = input->line;
+ if (bp == lim-1) {
+ errorp("line too long");
+ --bp;
+ }
+ *bp++ = '\n';
+ *bp = '\0';
+
+ return 1;
+}
+
+/*
+ * moreinput gets more bytes to be passed to the lexer.
+ * It can take more bytes from macro expansions or
+ * directly reading from files. When a cpp directive
+ * is processed the line is discarded because it must not
+ * be passed to the lexer
+ */
+static int
+moreinput(void)
+{
+ int wasexpand = 0;
+
+repeat:
+ if (!input)
+ return 0;
+
+ if (*input->p == '\0') {
+ if ((input->flags&ITYPE) == IMACRO) {
+ wasexpand = 1;
+ input->flags |= IEOF;
+ }
+ if (input->flags & IEOF) {
+ delinput();
+ goto repeat;
+ }
+ if (!readline() || cpp()) {
+ *input->p = '\0';
+ goto repeat;
+ }
+ }
+
+ if (onlycpp && !wasexpand)
+ ppragmaln();
+ return 1;
+}
+
+static void
+tok2str(void)
+{
+ if ((yylen = input->p - input->begin) > INTIDENTSIZ)
+ error("token too big");
+ memcpy(yytext, input->begin, yylen);
+ yytext[yylen] = '\0';
+ input->begin = input->p;
+}
+
+static Symbol *
+readint(char *s, int base, int sign, Symbol *sym)
+{
+ Type *tp = sym->type;
+ struct limits *lim;
+ TUINT u, val, max;
+ int c;
+
+ lim = getlimits(tp);
+ max = lim->max.i;
+ if (*s == '0')
+ ++s;
+ if (toupper(*s) == 'X')
+ ++s;
+
+ for (u = 0; isxdigit(c = *s++); u = u*base + val) {
+ static char letters[] = "0123456789ABCDEF";
+ val = strchr(letters, toupper(c)) - letters;
+ repeat:
+ if (u <= max/base && u*base <= max - val)
+ continue;
+ if (tp->prop & TSIGNED) {
+ if (tp == inttype)
+ tp = (base==10) ? longtype : uinttype;
+ else if (tp == longtype)
+ tp = (base==10) ? llongtype : ulongtype;
+ else
+ goto overflow;
+ } else {
+ if (tp == uinttype)
+ tp = (sign==UNSIGNED) ? ulongtype : longtype;
+ else if (tp == ulongtype)
+ tp = (sign==UNSIGNED) ? ullongtype : llongtype;
+ else
+ goto overflow;
+ }
+ sym->type = tp;
+ lim = getlimits(tp);
+ max = lim->max.i;
+ goto repeat;
+ }
+
+ if (tp->prop & TSIGNED)
+ sym->u.i = u;
+ else
+ sym->u.u = u;
+
+ return sym;
+
+overflow:
+ errorp("overflow in integer constant");
+ return sym;
+}
+
+static int
+integer(char *s, int base)
+{
+ Type *tp;
+ Symbol *sym;
+ unsigned size, sign;
+
+ for (size = sign = 0; ; ++input->p) {
+ switch (toupper(*input->p)) {
+ case 'L':
+ if (size == LLONG)
+ goto wrong_type;
+ size = (size == LONG) ? LLONG : LONG;
+ continue;
+ case 'U':
+ if (sign == UNSIGNED)
+ goto wrong_type;
+ sign = UNSIGNED;
+ continue;
+ default:
+ goto convert;
+ wrong_type:
+ error("invalid suffix in integer constant");
+ }
+ }
+
+convert:
+ tp = ctype(INT, sign, size);
+ sym = newsym(NS_IDEN, NULL);
+ sym->type = tp;
+ sym->flags |= SCONSTANT;
+ yylval.sym = readint(s, base, sign, sym);
+ return CONSTANT;
+}
+
+static char *
+digits(int base)
+{
+ char *p;
+ int c;
+
+ for (p = input->p; c = *p; ++p) {
+ switch (base) {
+ case 8:
+ if (!strchr("01234567", c))
+ goto end;
+ break;
+ case 10:
+ if (!isdigit(c))
+ goto end;
+ break;
+ case 16:
+ if (!isxdigit(c))
+ goto end;
+ break;
+ }
+ }
+end:
+ input->p = p;
+ tok2str();
+ return yytext;
+}
+
+static int
+number(void)
+{
+ int base;
+
+ if (*input->p != '0') {
+ base = 10;
+ } else {
+ if (toupper(*++input->p) == 'X') {
+ ++input->p;
+ base = 16;
+ } else {
+ base = 8;
+ }
+ }
+
+ return integer(digits(base), base);
+}
+
+static int
+escape(void)
+{
+ int c, base;
+
+ switch (*++input->p) {
+ case 'a': return '\a';
+ case 'f': return '\f';
+ case 'n': return '\n';
+ case 'r': return '\r';
+ case 't': return '\t';
+ case 'v': return '\v';
+ case '"': return '"';
+ case '\'': return '\'';
+ case '\\': return '\\';
+ case '\?': return '\?';
+ case 'u':
+ /*
+ * FIXME: universal constants are not correctly handled
+ */
+ if (!isdigit(*++input->p))
+ warn("incorrect digit for numerical character constant");
+ base = 10;
+ break;
+ case 'x':
+ if (!isxdigit(*++input->p))
+ warn("\\x used with no following hex digits");
+ base = 16;
+ break;
+ case '0':
+ if (!strchr("01234567", *++input->p))
+ warn("\\0 used with no following octal digits");
+ base = 8;
+ break;
+ default:
+ warn("unknown escape sequence");
+ return ' ';
+ }
+ errno = 0;
+ c = strtoul(input->p, &input->p, base);
+ if (errno || c > 255)
+ warn("character constant out of range");
+ --input->p;
+ return c;
+}
+
+static int
+character(void)
+{
+ int c;
+ Symbol *sym;
+
+ if ((c = *++input->p) == '\\')
+ c = escape();
+ else
+ c = *input->p;
+ ++input->p;
+ if (*input->p != '\'')
+ errorp("invalid character constant");
+ else
+ ++input->p;
+
+ sym = newsym(NS_IDEN, NULL);
+ sym->u.i = c;
+ sym->type = inttype;
+ yylval.sym = sym;
+ tok2str();
+ return CONSTANT;
+}
+
+static int
+string(void)
+{
+ char *bp = yytext;
+ int c;
+
+ *bp++ = '"';
+ for (++input->p; (c = *input->p) != '"'; ++input->p) {
+ if (c == '\0') {
+ errorp("missing terminating '\"' character");
+ break;
+ }
+ if (c == '\\')
+ c = escape();
+ if (bp == &yytext[STRINGSIZ+1]) {
+ /* TODO: proper error handling here */
+ error("string too long");
+ }
+ *bp++ = c;
+ }
+
+ input->begin = ++input->p;
+ *bp = '\0';
+
+ yylen = bp - yytext + 1;
+ yylval.sym = newstring(yytext+1, yylen-1);
+ *bp++ = '"';
+ *bp = '\0';
+ return STRING;
+}
+
+static int
+iden(void)
+{
+ Symbol *sym;
+ char *p, *begin;
+
+ begin = input->p;
+ for (p = begin; isalnum(*p) || *p == '_'; ++p)
+ ;
+ input->p = p;
+ tok2str();
+ if ((sym = lookup(NS_CPP, yytext, NOALLOC)) != NULL) {
+ if (!disexpand && !sym->hide && expand(begin, sym))
+ return next();
+ }
+ sym = lookup(namespace, yytext, ALLOC);
+ yylval.sym = sym;
+ if (sym->flags & SCONSTANT)
+ return CONSTANT;
+ if (sym->token != IDEN)
+ yylval.token = sym->u.token;
+ return sym->token;
+}
+
+static int
+follow(int expect, int ifyes, int ifno)
+{
+ if (*input->p++ == expect)
+ return ifyes;
+ --input->p;
+ return ifno;
+}
+
+static int
+minus(void)
+{
+ switch (*input->p++) {
+ case '-': return DEC;
+ case '>': return INDIR;
+ case '=': return SUB_EQ;
+ default: --input->p; return '-';
+ }
+}
+
+static int
+plus(void)
+{
+ switch (*input->p++) {
+ case '+': return INC;
+ case '=': return ADD_EQ;
+ default: --input->p; return '+';
+ }
+}
+
+static int
+relational(int op, int equal, int shift, int assig)
+{
+ int c;
+
+ if ((c = *input->p++) == '=')
+ return equal;
+ if (c == op)
+ return follow('=', assig, shift);
+ --input->p;
+ return op;
+}
+
+static int
+logic(int op, int equal, int logic)
+{
+ int c;
+
+ if ((c = *input->p++) == '=')
+ return equal;
+ if (c == op)
+ return logic;
+ --input->p;
+ return op;
+}
+
+static int
+dot(void)
+{
+ int c;
+
+ if ((c = *input->p) != '.')
+ return '.';
+ if ((c = *++input->p) != '.')
+ error("incorrect token '..'");
+ ++input->p;
+ return ELLIPSIS;
+}
+
+static int
+operator(void)
+{
+ int t;
+
+ switch (t = *input->p++) {
+ case '<': t = relational('<', LE, SHL, SHL_EQ); break;
+ case '>': t = relational('>', GE, SHR, SHR_EQ); break;
+ case '&': t = logic('&', AND_EQ, AND); break;
+ case '|': t = logic('|', OR_EQ, OR); break;
+ case '=': t = follow('=', EQ, '='); break;
+ case '^': t = follow('=', XOR_EQ, '^'); break;
+ case '*': t = follow('=', MUL_EQ, '*'); break;
+ case '/': t = follow('=', DIV_EQ, '/'); break;
+ case '!': t = follow('=', NE, '!'); break;
+ case '#': t = follow('#', '$', '#'); break;
+ case '-': t = minus(); break;
+ case '+': t = plus(); break;
+ case '.': t = dot(); break;
+ }
+ tok2str();
+ return t;
+}
+
+/* TODO: Ensure that namespace is NS_IDEN after a recovery */
+
+/*
+ * skip all the spaces until the next token. When we are in
+ * CPPMODE \n is not considered a whitespace
+ */
+static int
+skipspaces(void)
+{
+ int c;
+
+ for (;;) {
+ switch (c = *input->p) {
+ case '\n':
+ if (lexmode == CPPMODE)
+ goto return_byte;
+ ++input->p;
+ case '\0':
+ if (!moreinput())
+ return EOF;
+ break;
+ case ' ':
+ case '\t':
+ case '\v':
+ case '\r':
+ case '\f':
+ ++input->p;
+ break;
+ default:
+ goto return_byte;
+ }
+ }
+
+return_byte:
+ input->begin = input->p;
+ return c;
+}
+
+int
+next(void)
+{
+ int c;
+
+ if ((c = skipspaces()) == EOF)
+ yytoken = EOFTOK;
+ else if (isalpha(c) || c == '_')
+ yytoken = iden();
+ else if (isdigit(c))
+ yytoken = number();
+ else if (c == '"')
+ yytoken = string();
+ else if (c == '\'')
+ yytoken = character();
+ else
+ yytoken = operator();
+
+ if (yytoken == EOF) {
+ strcpy(yytext, "<EOF>");
+ if (cppctx)
+ errorp("#endif expected");
+ }
+
+ DBG("TOKEN %s", yytext);
+ return yytoken;
+}
+
+void
+expect(int tok)
+{
+ if (yytoken != tok) {
+ if (isgraph(tok))
+ errorp("expected '%c' before '%s'", tok, yytext);
+ else
+ errorp("unexpected '%s'", yytext);
+ } else {
+ next();
+ }
+}
+
+int
+ahead(void)
+{
+ skipspaces();
+ return *input->begin;
+}
+
+void
+setsafe(int type)
+{
+ safe = type;
+}
+
+void
+discard(void)
+{
+ extern jmp_buf recover;
+ int c;
+
+ input->begin = input->p;
+ for (c = yytoken; ; c = *input->begin++) {
+ switch (safe) {
+ case END_COMP:
+ if (c == '}')
+ goto jump;
+ goto semicolon;
+ case END_COND:
+ if (c == ')')
+ goto jump;
+ break;
+ case END_LDECL:
+ if (c == ',')
+ goto jump;
+ case END_DECL:
+ semicolon:
+ if (c == ';')
+ goto jump;
+ break;
+ }
+ if (c == '\0' && !moreinput())
+ exit(1);
+ }
+jump:
+ yytoken = c;
+ longjmp(recover, 1);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/main.c
@@ -1,0 +1,101 @@
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <scc/arg.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+char *argv0, *infile;
+
+int warnings;
+jmp_buf recover;
+
+static struct items uflags;
+int onlycpp, onlyheader;
+
+
+extern int failure;
+
+static void
+defmacro(char *macro)
+{
+ char *p = strchr(macro, '=');
+
+ if (p)
+ *p++ = '\0';
+ else
+ p = "1";
+
+ defdefine(macro, p, "command-line");
+}
+
+static void
+usage(void)
+{
+ fputs("usage: cc1 [-Ewd] [-D def[=val]]... [-U def]... "
+ "[-I dir]... [-o output] [input]\n", stderr);
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+
+ ilex();
+ icpp();
+ icode();
+ ibuilts();
+
+ ARGBEGIN {
+ case 'D':
+ defmacro(EARGF(usage()));
+ break;
+ case 'M':
+ onlyheader = 1;
+ break;
+ case 'E':
+ onlycpp = 1;
+ break;
+ case 'I':
+ incdir(EARGF(usage()));
+ break;
+ case 'U':
+ newitem(&uflags, EARGF(usage()));
+ break;
+ case 'd':
+ DBGON();
+ break;
+ case 'w':
+ warnings = 1;
+ break;
+ default:
+ usage();
+ } ARGEND
+
+ if (argc > 1)
+ usage();
+
+ for (i = 0; i < uflags.n; ++i)
+ undefmacro(uflags.s[i]);
+
+ infile = (*argv) ? *argv : "<stdin>";
+ addinput(*argv, NULL, NULL);
+
+ /*
+ * we cannot initialize arch until we have an
+ * output stream, because we maybe want to emit new types
+ */
+ iarch();
+ if (onlycpp || onlyheader) {
+ outcpp();
+ } else {
+ for (next(); yytoken != EOFTOK; decl())
+ ;
+ }
+
+ return failure;
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/stmt.c
@@ -1,0 +1,385 @@
+#include <stddef.h>
+#include <setjmp.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+#define NEGATE 1
+#define NONEGATE 0
+
+Symbol *curfun;
+
+static void stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch);
+
+static void
+label(void)
+{
+ Symbol *sym;
+
+ switch (yytoken) {
+ case IDEN:
+ case TYPEIDEN:
+ sym = lookup(NS_LABEL, yytext, ALLOC);
+ if (sym->flags & SDEFINED)
+ error("label '%s' already defined", yytext);
+ if ((sym->flags & SDECLARED) == 0)
+ sym = install(NS_LABEL, sym);
+ sym->flags |= SDEFINED;
+ emit(OLABEL, sym);
+ next();
+ expect(':');
+ break;
+ default:
+ unexpected();
+ }
+}
+
+static void
+stmtexp(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+ Node *np;
+
+ if (accept(';'))
+ return;
+ if (yytoken == IDEN && ahead() == ':') {
+ label();
+ stmt(lbreak, lcont, lswitch);
+ return;
+ }
+ np = expr();
+ if ((np->flags & NEFFECT) == 0)
+ warn("expression without side effects");
+ emit(OEXPR, np);
+ expect(';');
+}
+
+static Node *
+condition(int neg)
+{
+ Node *np;
+
+ expect('(');
+ np = condexpr(neg);
+ expect(')');
+
+ return np;
+}
+
+static void
+While(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+ Symbol *begin;
+ Node *np;
+
+ begin = newlabel();
+ lcont = newlabel();
+ lbreak = newlabel();
+
+ expect(WHILE);
+ np = condition(NONEGATE);
+
+ emit(OJUMP, lcont);
+
+ emit(OBLOOP, NULL);
+ emit(OLABEL, begin);
+ stmt(lbreak, lcont, lswitch);
+ emit(OLABEL, lcont);
+ emit(OBRANCH, begin);
+ emit(OEXPR, np);
+ emit(OELOOP, NULL);
+
+ emit(OLABEL, lbreak);
+}
+
+static void
+For(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+ Symbol *begin, *cond;
+ Node *econd, *einc;
+
+ begin = newlabel();
+ lcont = newlabel();
+ cond = newlabel();
+ lbreak = newlabel();
+
+ pushctx();
+
+ expect(FOR);
+ expect('(');
+ switch (yytoken) {
+ case TYPE:
+ case TYPEIDEN:
+ case TQUALIFIER:
+ case SCLASS:
+ decl();
+ break;
+ default:
+ emit(OEXPR, expr());
+ case ';':
+ expect(';');
+ break;
+ }
+ econd = (yytoken != ';') ? condexpr(NONEGATE) : NULL;
+ expect(';');
+ einc = (yytoken != ')') ? expr() : NULL;
+ expect(')');
+
+ emit(OJUMP, cond);
+
+ emit(OBLOOP, NULL);
+ emit(OLABEL, begin);
+ stmt(lbreak, lcont, lswitch);
+ emit(OLABEL, lcont);
+ emit(OEXPR, einc);
+ emit(OLABEL, cond);
+ emit((econd) ? OBRANCH : OJUMP, begin);
+ emit(OEXPR, econd);
+ emit(OELOOP, NULL);
+
+ emit(OLABEL, lbreak);
+
+ popctx();
+}
+
+static void
+Dowhile(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+ Symbol *begin;
+ Node *np;
+
+ begin = newlabel();
+ lcont = newlabel();
+ lbreak = newlabel();
+
+ expect(DO);
+
+ emit(OBLOOP, NULL);
+ emit(OLABEL, begin);
+ stmt(lbreak, lcont, lswitch);
+ expect(WHILE);
+ np = condition(NONEGATE);
+ emit(OLABEL, lcont);
+ emit(OBRANCH, begin);
+ emit(OEXPR, np);
+ emit(OELOOP, NULL);
+
+ emit(OLABEL, lbreak);
+}
+
+static void
+Return(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+ Node *np;
+ Type *tp = curfun->type->type;
+
+ expect(RETURN);
+ np = (yytoken != ';') ? decay(expr()) : NULL;
+ expect(';');
+ if (!np) {
+ if (tp != voidtype)
+ warn("function returning non void returns no value");
+ tp = voidtype;
+ } else if (np->type != tp) {
+ if (tp == voidtype)
+ warn("function returning void returns a value");
+ else if ((np = convert(np, tp, 0)) == NULL)
+ errorp("incorrect type in return");
+ }
+ emit(ORET, NULL);
+ emit(OEXPR, np);
+}
+
+static void
+Break(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+ expect(BREAK);
+ if (!lbreak) {
+ errorp("break statement not within loop or switch");
+ } else {
+ emit(OJUMP, lbreak);
+ expect(';');
+ }
+}
+
+static void
+Continue(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+ expect(CONTINUE);
+ if (!lcont) {
+ errorp("continue statement not within loop");
+ } else {
+ emit(OJUMP, lcont);
+ expect(';');
+ }
+}
+
+static void
+Goto(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+ Symbol *sym;
+
+ namespace = NS_LABEL;
+ next();
+ namespace = NS_IDEN;
+
+ if (yytoken != IDEN)
+ unexpected();
+ sym = yylval.sym;
+ if ((sym->flags & SDECLARED) == 0)
+ sym = install(NS_LABEL, sym);
+ sym->flags |= SUSED;
+ emit(OJUMP, sym);
+ next();
+ expect(';');
+}
+
+static void
+Swtch(Symbol *obr, Symbol *lcont, Switch *osw)
+{
+ Switch sw = {0};
+ Node *cond;
+ Symbol *lbreak;
+
+ expect(SWITCH);
+
+ expect ('(');
+ if ((cond = convert(expr(), inttype, 0)) == NULL) {
+ errorp("incorrect type in switch statement");
+ cond = constnode(zero);
+ }
+ expect (')');
+
+ lbreak = newlabel();
+ emit(OBSWITCH, NULL);
+ emit(OEXPR, cond);
+ stmt(lbreak, lcont, &sw);
+ emit(OESWITCH, lbreak);
+ emit(OLABEL, lbreak);
+}
+
+static void
+Case(Symbol *lbreak, Symbol *lcont, Switch *sw)
+{
+ Node *np;
+ Symbol *label;
+
+ expect(CASE);
+ if ((np = constexpr()) == NULL)
+ errorp("case label does not reduce to an integer constant");
+ if (!sw) {
+ errorp("case label not within a switch statement");
+ } else if (sw->nr >= 0 && ++sw->nr == NR_SWITCH) {
+ errorp("too many case labels for a switch statement");
+ sw->nr = -1;
+ }
+ expect(':');
+
+ label = newlabel();
+ emit(OCASE, label);
+ emit(OEXPR, np);
+ emit(OLABEL, label);
+ stmt(lbreak, lcont, sw);
+}
+
+static void
+Default(Symbol *lbreak, Symbol *lcont, Switch *sw)
+{
+ Symbol *label = newlabel();
+
+ if (sw->hasdef)
+ errorp("multiple default labels in one switch");
+ sw->hasdef = 1;
+ expect(DEFAULT);
+ expect(':');
+ emit(ODEFAULT, label);
+ emit(OLABEL, label);
+ stmt(lbreak, lcont, sw);
+}
+
+static void
+If(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+ Symbol *end, *lelse;
+ Node *np;
+
+ lelse = newlabel();
+ expect(IF);
+ np = condition(NEGATE);
+ emit(OBRANCH, lelse);
+ emit(OEXPR, np);
+ stmt(lbreak, lcont, lswitch);
+ if (accept(ELSE)) {
+ end = newlabel();
+ emit(OJUMP, end);
+ emit(OLABEL, lelse);
+ stmt(lbreak, lcont, lswitch);
+ emit(OLABEL, end);
+ } else {
+ emit(OLABEL, lelse);
+ }
+}
+
+static void
+blockit(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+ switch (yytoken) {
+ case TYPEIDEN:
+ if (ahead() == ':')
+ goto parse_stmt;
+ case TYPE:
+ case TQUALIFIER:
+ case SCLASS:
+ decl();
+ return;
+ default:
+ parse_stmt:
+ stmt(lbreak, lcont, lswitch);
+ }
+}
+
+void
+compound(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+ static int nested;
+
+ pushctx();
+ expect('{');
+
+ if (nested == NR_BLOCK)
+ error("too many nesting levels of compound statements");
+
+ ++nested;
+ for (;;) {
+ if (yytoken == '}')
+ break;
+ blockit(lbreak, lcont, lswitch);
+ }
+ --nested;
+
+ popctx();
+ expect('}');
+}
+
+static void
+stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+ void (*fun)(Symbol *, Symbol *, Switch *);
+
+ switch (yytoken) {
+ case '{': fun = compound; break;
+ case RETURN: fun = Return; break;
+ case WHILE: fun = While; break;
+ case FOR: fun = For; break;
+ case DO: fun = Dowhile; break;
+ case IF: fun = If; break;
+ case BREAK: fun = Break; break;
+ case CONTINUE: fun = Continue; break;
+ case GOTO: fun = Goto; break;
+ case SWITCH: fun = Swtch; break;
+ case CASE: fun = Case; break;
+ case DEFAULT: fun = Default; break;
+ default: fun = stmtexp; break;
+ }
+ (*fun)(lbreak, lcont, lswitch);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/symbol.c
@@ -1,0 +1,351 @@
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+#define NR_SYM_HASH 64
+#define NR_CPP_HASH 32
+#define NR_LBL_HASH 16
+
+unsigned curctx;
+static unsigned short counterid;
+
+static Symbol *head, *labels;
+static Symbol *htab[NR_SYM_HASH];
+static Symbol *htabcpp[NR_CPP_HASH];
+static Symbol *htablbl[NR_LBL_HASH];
+
+#ifndef NDEBUG
+void
+dumpstab(Symbol **tbl, char *msg)
+{
+ Symbol **bp, *sym;
+ unsigned size;
+
+ fprintf(stderr, "Symbol Table dump at ctx=%u\n%s\n", curctx, msg);
+ if (tbl == htab)
+ size = NR_SYM_HASH;
+ else if (tbl == htabcpp)
+ size = NR_CPP_HASH;
+ else if (tbl == htablbl)
+ size = NR_LBL_HASH;
+ else
+ abort();
+
+ for (bp = tbl; bp < &tbl[size]; ++bp) {
+ if (*bp == NULL)
+ continue;
+ fprintf(stderr, "%d", (int) (bp - htab));
+ for (sym = *bp; sym; sym = sym->hash)
+ fprintf(stderr, "->[%d,%d:'%s'=%p]",
+ sym->ns, sym->ctx, sym->name, (void *) sym);
+ putc('\n', stderr);
+ }
+ fputs("head:", stderr);
+ for (sym = head; sym; sym = sym->next) {
+ fprintf(stderr, "->[%d,%d:'%s'=%p]",
+ sym->ns, sym->ctx,
+ (sym->name) ? sym->name : "", (void *) sym);
+ }
+ fputs("\nlabels:", stderr);
+ for (sym = labels; sym; sym = sym->next) {
+ fprintf(stderr, "->[%d,%d:'%s'=%p]",
+ sym->ns, sym->ctx,
+ (sym->name) ? sym->name : "", (void *) sym);
+ }
+ putc('\n', stderr);
+}
+#endif
+
+static Symbol **
+hash(char *s, int ns)
+{
+ unsigned h, size;
+ Symbol **tab;
+
+ h = genhash(s);
+
+ switch (ns) {
+ case NS_CPP:
+ tab = htabcpp;
+ size = NR_CPP_HASH-1;
+ break;
+ case NS_LABEL:
+ tab = htablbl;
+ size = NR_LBL_HASH-1;
+ break;
+ default:
+ tab = htab;
+ size = NR_SYM_HASH-1;
+ break;
+ }
+ return &tab[h & size];
+}
+
+static void
+unlinkhash(Symbol *sym)
+{
+ Symbol **h;
+
+ if ((sym->flags & SDECLARED) == 0)
+ return;
+ h = hash(sym->name, sym->ns);
+ assert(sym->ns == NS_CPP || *h == sym);
+ while (*h != sym)
+ h = &(*h)->hash;
+ *h = sym->hash;
+}
+
+void
+pushctx(void)
+{
+ DBG("SYM: pushed context %d", curctx+1);
+ if (++curctx == NR_BLOCK+1)
+ error("too many nested blocks");
+}
+
+void
+killsym(Symbol *sym)
+{
+ short f;
+ char *name;
+
+ if (!sym)
+ return;
+ f = sym->flags;
+ if (f & SSTRING)
+ free(sym->u.s);
+ if (sym->ns == NS_TAG)
+ sym->type->prop &= ~TDEFINED;
+ unlinkhash(sym);
+ if ((name = sym->name) != NULL) {
+ switch (sym->ns) {
+ case NS_LABEL:
+ if ((f & SDEFINED) == 0)
+ errorp("label '%s' is not defined", name);
+ case NS_IDEN:
+ if ((f & (SUSED|SGLOBAL|SDECLARED)) == SDECLARED)
+ warn("'%s' defined but not used", name);
+ break;
+ }
+ }
+ free(name);
+ free(sym);
+}
+
+void
+popctx(void)
+{
+ Symbol *next, *sym;
+ int ns, dangling = 0;
+
+ DBG("SYM: poped context %d", curctx);
+ /*
+ * we have to be careful before popping the current
+ * context, because since the parser is one token
+ * ahead it may already have read an identifier at
+ * this point, and yylval.sym is a pointer to
+ * the symbol associated to such token. If that
+ * symbol is from the context that we are popping
+ * then we are going to generate a dangling pointer.
+ * We can detect this situation and call again to
+ * lookup.
+ */
+ if ((yytoken == IDEN || yytoken == TYPEIDEN) &&
+ yylval.sym->ctx == curctx) {
+ ns = yylval.sym->ns;
+ dangling = 1;
+ }
+
+ for (sym = head; sym && sym->ctx == curctx; sym = next) {
+ /*
+ * Since we are unlinking them in the inverse order
+ * we do know that sym is always the head of the
+ * collision list
+ */
+ next = sym->next;
+ killsym(sym);
+ }
+ head = sym;
+
+ if (--curctx == GLOBALCTX) {
+ for (sym = labels; sym; sym = next) {
+ next = sym->next;
+ killsym(sym);
+ }
+ labels = NULL;
+ }
+
+ if (dangling) {
+ yylval.sym = lookup(ns, yytext, ALLOC);
+ yytoken = yylval.sym->token;
+ }
+}
+
+unsigned
+newid(void)
+{
+ unsigned short id;
+
+ if (lexmode == CPPMODE)
+ return 0;
+ id = ++counterid;
+ if (id == 0) {
+ die("cc1: overflow in %s identifiers",
+ (curctx) ? "internal" : "external");
+ }
+ return id;
+}
+
+Symbol *
+newsym(int ns, char *name)
+{
+ Symbol *sym;
+
+ sym = xmalloc(sizeof(*sym));
+ if (name)
+ name = xstrdup(name);
+ sym->name = name;
+ sym->id = 0;
+ sym->hide = 0;
+ sym->ns = ns;
+ sym->ctx = curctx;
+ sym->token = IDEN;
+ sym->flags = 0;
+ sym->u.s = NULL;
+ sym->type = NULL;
+ sym->hash = NULL;
+
+ if (ns == NS_LABEL) {
+ sym->next = labels;
+ labels = sym;
+ } else if (ns != NS_CPP) {
+ sym->next = head;
+ head = sym;
+ }
+ return sym;
+}
+
+static Symbol *
+linkhash(Symbol *sym)
+{
+ Symbol **h;
+
+ h = hash(sym->name, sym->ns);
+ sym->hash = *h;
+ *h = sym;
+
+ if (sym->ns != NS_CPP)
+ sym->id = newid();
+ sym->flags |= SDECLARED;
+ return sym;
+}
+
+Symbol *
+newstring(char *s, size_t len)
+{
+ Symbol *sym = newsym(NS_IDEN, NULL);
+
+ if (lexmode != CPPMODE)
+ sym->type = mktype(chartype, ARY, len, NULL);
+ sym->id = newid();
+ sym->flags |= SSTRING | SCONSTANT | SPRIVATE;
+ sym->u.s = xmalloc(len);
+ if (s)
+ memcpy(sym->u.s, s, len);
+
+ return sym;
+}
+
+Symbol *
+newlabel(void)
+{
+ Symbol *sym = newsym(NS_LABEL, NULL);
+ sym->id = newid();
+ return sym;
+}
+
+Symbol *
+lookup(int ns, char *name, int alloc)
+{
+ Symbol *sym;
+ int sns, c;
+ char *t;
+
+ c = *name;
+ for (sym = *hash(name, ns); sym; sym = sym->hash) {
+ t = sym->name;
+ if (*t != c || strcmp(t, name))
+ continue;
+ sns = sym->ns;
+ if (sns == ns)
+ return sym;
+ /*
+ * When a lookup is done in a namespace associated
+ * to a struct we also want symbols of NS_IDEN which
+ * are typedef, because in other case we cannot declare
+ * fields of such types.
+ * TODO: Remove this trick
+ */
+ if (sns == NS_KEYWORD ||
+ (sym->flags & STYPEDEF) && ns >= NS_STRUCTS) {
+ return sym;
+ }
+ }
+ return (alloc == ALLOC) ? newsym(ns, name) : NULL;
+}
+
+Symbol *
+install(int ns, Symbol *sym)
+{
+ if (sym->flags & SDECLARED || sym->ctx != curctx) {
+ if (sym->ctx == curctx && ns == sym->ns)
+ return NULL;
+ sym = newsym(ns, sym->name);
+ }
+ return linkhash(sym);
+}
+
+void
+keywords(struct keyword *key, int ns)
+{
+ Symbol *sym;
+
+ for ( ; key->str; ++key) {
+ sym = linkhash(newsym(ns, key->str));
+ sym->token = key->token;
+ sym->u.token = key->value;
+ }
+ /*
+ * Remove all the predefined symbols from * the symbol list. It
+ * will make faster some operations. There is no problem of memory
+ * leakeage because this memory is not ever freed
+ */
+ counterid = 0;
+ head = NULL;
+}
+
+void
+builtins(struct builtin *built)
+{
+ Symbol *sym;
+ struct builtin *bp;
+
+ for (bp = built; bp->str; ++bp) {
+ sym = linkhash(newsym(NS_KEYWORD, bp->str));
+ sym->token = BUILTIN;
+ sym->u.fun = bp->fun;
+ }
+ /*
+ * Remove all the predefined symbols from * the symbol list. It
+ * will make faster some operations. There is no problem of memory
+ * leakeage because this memory is not ever freed
+ */
+ counterid = 0;
+ head = NULL;
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/target/amd64-sysv/arch.c
@@ -1,0 +1,218 @@
+#include <scc/scc.h>
+#include "../../cc1.h"
+
+#define RANK_BOOL 0
+#define RANK_SCHAR 1
+#define RANK_UCHAR 1
+#define RANK_CHAR 1
+#define RANK_SHORT 2
+#define RANK_USHORT 2
+#define RANK_INT 3
+#define RANK_UINT 3
+#define RANK_LONG 4
+#define RANK_ULONG 4
+#define RANK_LLONG 5
+#define RANK_ULLONG 5
+#define RANK_FLOAT 6
+#define RANK_DOUBLE 7
+#define RANK_LDOUBLE 8
+
+/*
+ * Initializaion of type pointers were done with
+ * a C99 initilizator '... = &(Type) {...', but
+ * c compiler in Plan9 gives error with this
+ * syntax, so I have switched it to this ugly form
+ * I hope I will change it again in the future
+ */
+
+static Type types[] = {
+ { /* 0 = voidtype */
+ .op = VOID,
+ .letter = L_VOID,
+ },
+ { /* 1 = pvoidtype */
+ .op = PTR,
+ .letter = L_POINTER,
+ .prop = TDEFINED,
+ .type = &types[5], /* chartype */
+ .size = 8,
+ .align = 8,
+ },
+ { /* 2 = booltype */
+ .op = INT,
+ .letter = L_BOOL,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_BOOL,
+ },
+ { /* 3 = schartype */
+ .op = INT,
+ .letter = L_INT8,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_SCHAR,
+ },
+ { /* 4 = uchartype */
+ .op = INT,
+ .letter = L_UINT8,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_UCHAR,
+ },
+ { /* 5 = chartype */
+ .op = INT,
+ .letter = L_INT8,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_CHAR,
+ },
+ { /* 6 = ushortype */
+ .op = INT,
+ .letter = L_UINT16,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 2,
+ .align = 2,
+ .n.rank = RANK_USHORT,
+ },
+ { /* 7 = shortype */
+ .op = INT,
+ .letter = L_INT16,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 2,
+ .align = 2,
+ .n.rank = RANK_SHORT,
+ },
+ { /* 8 = uinttype */
+ .op = INT,
+ .letter = L_UINT32,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 4,
+ .align = 4,
+ .n.rank = RANK_UINT,
+ },
+ { /* 9 = inttype */
+ .op = INT,
+ .letter = L_INT32,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 4,
+ .align = 4,
+ .n.rank = RANK_INT,
+ },
+ { /* 10 = longtype */
+ .op = INT,
+ .letter = L_INT64,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_LONG,
+ },
+ { /* 11 = ulongtype */
+ .op = INT,
+ .letter = L_UINT64,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_ULONG,
+ },
+ { /* 12 = ullongtype */
+ .op = INT,
+ .letter = L_UINT64,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_ULLONG,
+ },
+ { /* 13 = llongtype */
+ .op = INT,
+ .letter = L_INT64,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_LLONG,
+ },
+ { /* 14 = floattype */
+ .op = FLOAT,
+ .letter = L_FLOAT,
+ .prop = TDEFINED | TARITH,
+ .size = 4,
+ .align = 4,
+ .n.rank = RANK_FLOAT,
+ },
+ { /* 15 = doubletype */
+ .op = FLOAT,
+ .letter = L_DOUBLE,
+ .prop = TDEFINED | TARITH,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_DOUBLE,
+ },
+ { /* 16 = ldoubletype */
+ .op = FLOAT,
+ .letter = L_LDOUBLE,
+ .prop = TDEFINED | TARITH,
+ .size = 16,
+ .align = 16,
+ .n.rank = RANK_LDOUBLE,
+ },
+ { /* 17 = sizettype */
+ .op = INT,
+ .letter = L_UINT64,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_UINT,
+ },
+ { /* 18 = ellipsis */
+ .op = ELLIPSIS,
+ .letter = L_ELLIPSIS,
+ .prop = TDEFINED,
+ },
+ { /* 19 = pdifftype */
+ .op = INT,
+ .letter = L_INT64,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_LONG,
+ },
+ { /* 20 = va_type */
+ .op = STRUCT,
+ .letter = L_VA_ARG,
+ .prop = TDEFINED,
+ .size = 24,
+ .align = 8,
+ },
+};
+
+Type *voidtype = &types[0], *pvoidtype = &types[1],
+ *booltype = &types[2], *schartype = &types[3],
+ *uchartype = &types[4], *chartype = &types[5],
+ *ushortype = &types[6], *shortype = &types[7],
+ *uinttype = &types[8], *inttype = &types[9],
+ *longtype = &types[10], *ulongtype = &types[11],
+ *ullongtype = &types[12], *llongtype = &types[13],
+ *floattype = &types[14], *doubletype = &types[15],
+ *ldoubletype = &types[16],
+ *sizettype = &types[17], *pdifftype = &types[19],
+ *ellipsistype = &types[18], *va_type = &types[20],
+ *va_list_type;
+
+static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
+ dummy1 = {.u.i = 1, .type = &types[9]};
+Symbol *zero = &dummy0, *one = &dummy1;
+
+void
+iarch(void)
+{
+ va_list_type = mktype(va_type, ARY, 1, NULL);
+}
+
+int
+valid_va_list(Type *tp)
+{
+ return tp->op == PTR && eqtype(tp->type, va_type, 1);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/target/amd64-sysv/arch.mk
@@ -1,0 +1,4 @@
+OBJ-amd64-sysv= $(OBJS) target/amd64-sysv/arch.o
+
+$(LIBEXEC)/cc1-amd64-sysv: $(OBJ-amd64-sysv)
+ $(CC) $(SCC_LDFLAGS) $(OBJ-amd64-sysv) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc1/target/arm64-sysv/arch.c
@@ -1,0 +1,218 @@
+#include <scc/scc.h>
+#include "../../cc1.h"
+
+#define RANK_BOOL 0
+#define RANK_SCHAR 1
+#define RANK_UCHAR 1
+#define RANK_CHAR 1
+#define RANK_SHORT 2
+#define RANK_USHORT 2
+#define RANK_INT 3
+#define RANK_UINT 3
+#define RANK_LONG 4
+#define RANK_ULONG 4
+#define RANK_LLONG 5
+#define RANK_ULLONG 5
+#define RANK_FLOAT 6
+#define RANK_DOUBLE 7
+#define RANK_LDOUBLE 8
+
+/*
+ * Initializaion of type pointers were done with
+ * a C99 initilizator '... = &(Type) {...', but
+ * c compiler in Plan9 gives error with this
+ * syntax, so I have switched it to this ugly form
+ * I hope I will change it again in the future
+ */
+
+static Type types[] = {
+ { /* 0 = voidtype */
+ .op = VOID,
+ .letter = L_VOID,
+ },
+ { /* 1 = pvoidtype */
+ .op = PTR,
+ .letter = L_POINTER,
+ .prop = TDEFINED,
+ .type = &types[5], /* chartype */
+ .size = 8,
+ .align = 8,
+ },
+ { /* 2 = booltype */
+ .op = INT,
+ .letter = L_BOOL,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_BOOL,
+ },
+ { /* 3 = schartype */
+ .op = INT,
+ .letter = L_INT8,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_SCHAR,
+ },
+ { /* 4 = uchartype */
+ .op = INT,
+ .letter = L_UINT8,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_UCHAR,
+ },
+ { /* 5 = chartype */
+ .op = INT,
+ .letter = L_INT8,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_CHAR,
+ },
+ { /* 6 = ushortype */
+ .op = INT,
+ .letter = L_UINT16,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 2,
+ .align = 2,
+ .n.rank = RANK_USHORT,
+ },
+ { /* 7 = shortype */
+ .op = INT,
+ .letter = L_INT16,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 2,
+ .align = 2,
+ .n.rank = RANK_SHORT,
+ },
+ { /* 8 = uinttype */
+ .op = INT,
+ .letter = L_UINT32,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 4,
+ .align = 4,
+ .n.rank = RANK_UINT,
+ },
+ { /* 9 = inttype */
+ .op = INT,
+ .letter = L_INT32,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 4,
+ .align = 4,
+ .n.rank = RANK_INT,
+ },
+ { /* 10 = longtype */
+ .op = INT,
+ .letter = L_INT64,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_LONG,
+ },
+ { /* 11 = ulongtype */
+ .op = INT,
+ .letter = L_UINT64,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_ULONG,
+ },
+ { /* 12 = ullongtype */
+ .op = INT,
+ .letter = L_UINT64,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_ULLONG,
+ },
+ { /* 13 = llongtype */
+ .op = INT,
+ .letter = L_INT64,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_LLONG,
+ },
+ { /* 14 = floattype */
+ .op = FLOAT,
+ .letter = L_FLOAT,
+ .prop = TDEFINED | TARITH,
+ .size = 4,
+ .align = 4,
+ .n.rank = RANK_FLOAT,
+ },
+ { /* 15 = doubletype */
+ .op = FLOAT,
+ .letter = L_DOUBLE,
+ .prop = TDEFINED | TARITH,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_DOUBLE,
+ },
+ { /* 16 = ldoubletype */
+ .op = FLOAT,
+ .letter = L_LDOUBLE,
+ .prop = TDEFINED | TARITH,
+ .size = 16,
+ .align = 16,
+ .n.rank = RANK_LDOUBLE,
+ },
+ { /* 17 = sizettype */
+ .op = INT,
+ .letter = L_UINT64,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_UINT,
+ },
+ { /* 18 = ellipsis */
+ .op = ELLIPSIS,
+ .letter = L_ELLIPSIS,
+ .prop = TDEFINED,
+ },
+ { /* 19 = pdifftype */
+ .op = INT,
+ .letter = L_INT64,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 8,
+ .align = 8,
+ .n.rank = RANK_LONG,
+ },
+ { /* 20 = va_type */
+ .op = STRUCT,
+ .letter = L_VA_ARG,
+ .prop = TDEFINED,
+ .size = 24,
+ .align = 8,
+ },
+};
+
+Type *voidtype = &types[0], *pvoidtype = &types[1],
+ *booltype = &types[2], *schartype = &types[3],
+ *uchartype = &types[4], *chartype = &types[5],
+ *ushortype = &types[6], *shortype = &types[7],
+ *uinttype = &types[8], *inttype = &types[9],
+ *longtype = &types[10], *ulongtype = &types[11],
+ *ullongtype = &types[12], *llongtype = &types[13],
+ *floattype = &types[14], *doubletype = &types[15],
+ *ldoubletype = &types[16],
+ *sizettype = &types[17], *pdifftype = &types[19],
+ *ellipsistype = &types[18], *va_type = &types[20],
+ *va_list_type;
+
+static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
+ dummy1 = {.u.i = 1, .type = &types[9]};
+Symbol *zero = &dummy0, *one = &dummy1;
+
+void
+iarch(void)
+{
+ va_list_type = mktype(va_type, ARY, 1, NULL);
+}
+
+int
+valid_va_list(Type *tp)
+{
+ return tp->op == PTR && eqtype(tp->type, va_type, 1);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/target/arm64-sysv/arch.mk
@@ -1,0 +1,4 @@
+OBJ-arm64-sysv= $(OBJS) target/arm64-sysv/arch.o
+
+$(LIBEXEC)/cc1-arm64-sysv: $(OBJ-arm64-sysv)
+ $(CC) $(SCC_LDFLAGS) $(OBJ-arm64-sysv) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc1/target/i386-sysv/arch.c
@@ -1,0 +1,219 @@
+#include <scc/scc.h>
+#include "../../cc1.h"
+
+#define RANK_BOOL 0
+#define RANK_SCHAR 1
+#define RANK_UCHAR 1
+#define RANK_CHAR 1
+#define RANK_SHORT 2
+#define RANK_USHORT 2
+#define RANK_INT 3
+#define RANK_UINT 3
+#define RANK_LONG 4
+#define RANK_ULONG 4
+#define RANK_LLONG 5
+#define RANK_ULLONG 5
+#define RANK_FLOAT 6
+#define RANK_DOUBLE 7
+#define RANK_LDOUBLE 8
+
+/*
+ * Initializaion of type pointers were done with
+ * a C99 initilizator '... = &(Type) {...', but
+ * c compiler in Plan9 gives error with this
+ * syntax, so I have switched it to this ugly form
+ * I hope I will change it again in the future
+ */
+
+static Type types[] = {
+ { /* 0 = voidtype */
+ .op = VOID,
+ .letter = L_VOID,
+ },
+ { /* 1 = pvoidtype */
+ .op = PTR,
+ .letter = L_POINTER,
+ .prop = TDEFINED,
+ .type = &types[5], /* chartype */
+ .size = 4,
+ .align = 4,
+ },
+ { /* 2 = booltype */
+ .op = INT,
+ .letter = L_BOOL,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_BOOL,
+ },
+ { /* 3 = schartype */
+ .op = INT,
+ .letter = L_INT8,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_SCHAR,
+ },
+ { /* 4 = uchartype */
+ .op = INT,
+ .letter = L_UINT8,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_UCHAR,
+ },
+ { /* 5 = chartype */
+ .op = INT,
+ .letter = L_INT8,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_CHAR,
+ },
+ { /* 6 = ushortype */
+ .op = INT,
+ .letter = L_UINT16,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 2,
+ .align = 2,
+ .n.rank = RANK_USHORT,
+ },
+ { /* 7 = shortype */
+ .op = INT,
+ .letter = L_INT16,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 2,
+ .align = 2,
+ .n.rank = RANK_SHORT,
+ },
+ { /* 8 = uinttype */
+ .op = INT,
+ .letter = L_UINT32,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 4,
+ .align = 4,
+ .n.rank = RANK_UINT,
+ },
+ { /* 9 = inttype */
+ .op = INT,
+ .letter = L_INT32,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 4,
+ .align = 4,
+ .n.rank = RANK_INT,
+ },
+ { /* 10 = longtype */
+ .op = INT,
+ .letter = L_INT32,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 4,
+ .align = 4,
+ .n.rank = RANK_LONG,
+ },
+ { /* 11 = ulongtype */
+ .op = INT,
+ .letter = L_UINT32,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 4,
+ .align = 4,
+ .n.rank = RANK_ULONG,
+ },
+ { /* 12 = ullongtype */
+ .op = INT,
+ .letter = L_UINT64,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 8,
+ .align = 4,
+ .n.rank = RANK_ULLONG,
+ },
+ { /* 13 = llongtype */
+ .op = INT,
+ .letter = L_INT64,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 8,
+ .align = 4,
+ .n.rank = RANK_LLONG,
+ },
+ { /* 14 = floattype */
+ .op = FLOAT,
+ .letter = L_FLOAT,
+ .prop = TDEFINED | TARITH,
+ .size = 4,
+ .align = 4,
+ .n.rank = RANK_FLOAT,
+ },
+ { /* 15 = doubletype */
+ .op = FLOAT,
+ .letter = L_DOUBLE,
+ .prop = TDEFINED | TARITH,
+ .size = 8,
+ .align = 4,
+ .n.rank = RANK_DOUBLE,
+ },
+ { /* 16 = ldoubletype */
+ .op = FLOAT,
+ .letter = L_LDOUBLE,
+ .prop = TDEFINED | TARITH,
+ .size = 12,
+ .align = 4,
+ .n.rank = RANK_LDOUBLE,
+ },
+ { /* 17 = sizettype */
+ .op = INT,
+ .letter = L_UINT32,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 4,
+ .align = 4,
+ .n.rank = RANK_UINT,
+ },
+ { /* 18 = ellipsis */
+ .op = ELLIPSIS,
+ .letter = L_ELLIPSIS,
+ .prop = TDEFINED,
+ },
+ { /* 19 = pdifftype */
+ .op = INT,
+ .letter = L_INT32,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 4,
+ .align = 4,
+ .n.rank = RANK_INT,
+ },
+ { /* 20 = va_list_type */
+ .op = PTR,
+ .letter = L_POINTER,
+ .prop = TDEFINED,
+ .size = 4,
+ .align = 4,
+ },
+};
+
+
+Type *voidtype = &types[0], *pvoidtype = &types[1],
+ *booltype = &types[2], *schartype = &types[3],
+ *uchartype = &types[4], *chartype = &types[5],
+ *ushortype = &types[6], *shortype = &types[7],
+ *uinttype = &types[8], *inttype = &types[9],
+ *longtype = &types[10], *ulongtype = &types[11],
+ *ullongtype = &types[12], *llongtype = &types[13],
+ *floattype = &types[14], *doubletype = &types[15],
+ *ldoubletype = &types[16],
+ *sizettype = &types[17], *pdifftype = &types[19],
+ *ellipsistype = &types[18], *va_list_type = &types[20];
+
+
+
+static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
+ dummy1 = {.u.i = 1, .type = &types[9]};
+Symbol *zero = &dummy0, *one = &dummy1;
+
+void
+iarch(void)
+{
+}
+
+int
+valid_va_list(Type *tp)
+{
+ return eqtype(tp, va_list_type, 1);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/target/i386-sysv/arch.mk
@@ -1,0 +1,4 @@
+OBJ-i386-sysv= $(OBJS) target/i386-sysv/arch.o
+
+$(LIBEXEC)/cc1-i386-sysv: $(OBJ-i386-sysv)
+ $(CC) $(SCC_LDFLAGS) $(OBJ-i386-sysv) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc1/target/z80-scc/arch.c
@@ -1,0 +1,217 @@
+#include <scc/scc.h>
+#include "../../cc1.h"
+
+#define RANK_BOOL 0
+#define RANK_SCHAR 1
+#define RANK_UCHAR 1
+#define RANK_CHAR 1
+#define RANK_SHORT 2
+#define RANK_USHORT 2
+#define RANK_INT 3
+#define RANK_UINT 3
+#define RANK_LONG 4
+#define RANK_ULONG 4
+#define RANK_LLONG 5
+#define RANK_ULLONG 5
+#define RANK_FLOAT 6
+#define RANK_DOUBLE 7
+#define RANK_LDOUBLE 8
+
+/*
+ * Initializaion of type pointers were done with
+ * a C99 initilizator '... = &(Type) {...', but
+ * c compiler in Plan9 gives error with this
+ * syntax, so I have switched it to this ugly form
+ * I hope I will change it again in the future
+ */
+
+static Type types[] = {
+ { /* 0 = voidtype */
+ .op = VOID,
+ .letter = L_VOID,
+ },
+ { /* 1 = pvoidtype */
+ .op = PTR,
+ .letter = L_POINTER,
+ .prop = TDEFINED,
+ .type = &types[5], /* char type */
+ .size = 2,
+ .align = 2,
+ },
+ { /* 2 = booltype */
+ .op = INT,
+ .letter = L_BOOL,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_BOOL,
+ },
+ { /* 3 = schartype */
+ .op = INT,
+ .letter = L_INT8,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_SCHAR,
+ },
+ { /* 4 = uchartype */
+ .op = INT,
+ .letter = L_UINT8,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_UCHAR,
+ },
+ { /* 5 = chartype */
+ .op = INT,
+ .letter = L_UINT8,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 1,
+ .align = 1,
+ .n.rank = RANK_CHAR,
+ },
+ { /* 6 = ushortype */
+ .op = INT,
+ .letter = L_UINT16,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 2,
+ .align = 1,
+ .n.rank = RANK_USHORT,
+ },
+ { /* 7 = shortype */
+ .op = INT,
+ .letter = L_INT16,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 2,
+ .align = 1,
+ .n.rank = RANK_SHORT,
+ },
+ { /* 8 = uinttype */
+ .op = INT,
+ .letter = L_UINT16,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 2,
+ .align = 1,
+ .n.rank = RANK_UINT,
+ },
+ { /* 9 = inttype */
+ .op = INT,
+ .letter = L_INT16,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 2,
+ .align = 1,
+ .n.rank = RANK_INT,
+ },
+ { /* 10 = longtype */
+ .op = INT,
+ .letter = L_INT32,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 4,
+ .align = 1,
+ .n.rank = RANK_LONG,
+ },
+ { /* 11 = ulongtype */
+ .op = INT,
+ .letter = L_UINT32,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 4,
+ .align = 1,
+ .n.rank = RANK_ULONG,
+ },
+ { /* 12 = ullongtype */
+ .op = INT,
+ .letter = L_UINT64,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 8,
+ .align = 1,
+ .n.rank = RANK_ULLONG,
+ },
+ { /* 13 = llongtype */
+ .op = INT,
+ .letter = L_INT64,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 8,
+ .align = 1,
+ .n.rank = RANK_LLONG,
+ },
+ { /* 14 = floattype */
+ .op = FLOAT,
+ .letter = L_FLOAT,
+ .prop = TDEFINED | TARITH,
+ .size = 4,
+ .align = 1,
+ .n.rank = RANK_FLOAT,
+ },
+ { /* 15 = doubletype */
+ .op = FLOAT,
+ .letter = L_DOUBLE,
+ .prop = TDEFINED | TARITH,
+ .size = 8,
+ .align = 1,
+ .n.rank = RANK_DOUBLE,
+ },
+ { /* 16 = ldoubletype */
+ .op = FLOAT,
+ .letter = L_LDOUBLE,
+ .prop = TDEFINED | TARITH,
+ .size = 16,
+ .align = 1,
+ .n.rank = RANK_LDOUBLE,
+ },
+ { /* 17 = sizettype */
+ .op = INT,
+ .letter = L_UINT16,
+ .prop = TDEFINED | TINTEGER | TARITH,
+ .size = 2,
+ .align = 1,
+ .n.rank = RANK_UINT,
+ },
+ { /* 18 = ellipsis */
+ .op = ELLIPSIS,
+ .letter = L_ELLIPSIS,
+ .prop = TDEFINED,
+ },
+ { /* 7 = pdifftype */
+ .op = INT,
+ .letter = L_INT16,
+ .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+ .size = 2,
+ .align = 1,
+ .n.rank = RANK_SHORT,
+ },
+ { /* 20 = va_list_type */
+ .op = PTR,
+ .letter = L_POINTER,
+ .prop = TDEFINED,
+ .size = 2,
+ .align = 1,
+ }
+};
+
+Type *voidtype = &types[0], *pvoidtype = &types[1],
+ *booltype = &types[2], *schartype = &types[3],
+ *uchartype = &types[4], *chartype = &types[5],
+ *ushortype = &types[6], *shortype = &types[7],
+ *uinttype = &types[8], *inttype = &types[9],
+ *longtype = &types[10], *ulongtype = &types[11],
+ *ullongtype = &types[12], *llongtype = &types[13],
+ *floattype = &types[14], *doubletype = &types[15],
+ *ldoubletype = &types[16],
+ *sizettype = &types[17], *pdifftype = &types[19],
+ *ellipsistype = &types[18], *va_list_type = &types[20];
+
+
+static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
+ dummy1 = {.u.i = 1, .type = &types[9]};
+Symbol *zero = &dummy0, *one = &dummy1;
+
+void
+iarch(void)
+{
+}
+
+int
+valid_va_list(Type *tp)
+{
+ return eqtype(tp, va_list_type, 1);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/target/z80-scc/arch.mk
@@ -1,0 +1,4 @@
+OBJ-z80-scc= $(OBJS) target/z80-scc/arch.o
+
+$(LIBEXEC)/cc1-z80-scc: $(OBJ-z80-scc)
+ $(CC) $(SCC_LDFLAGS) $(OBJ-z80-scc) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc1/types.c
@@ -1,0 +1,437 @@
+#include <assert.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+#define NR_TYPE_HASH 16
+#define HASH(t) (((t)->op ^ (uintptr_t) (t)->type>>3) & NR_TYPE_HASH-1)
+
+static Type *typetab[NR_TYPE_HASH], *localtypes;
+
+/* FIXME:
+ * Compiler can generate warnings here if the ranges of TINT,
+ * TUINT and TFLOAT are smaller than any of the constants in this
+ * array. Ignore them if you know that the target types are correct
+ */
+static struct limits limits[][4] = {
+ {
+ { /* 0 = unsigned 1 byte */
+ .min.i = 0,
+ .max.i = 0xff
+ },
+ { /* 1 = unsigned 2 bytes */
+ .min.i = 0,
+ .max.i = 0xffff
+ },
+ { /* 2 = unsigned 4 bytes */
+ .min.i = 0,
+ .max.i = 0xffffffff
+ },
+ { /* 3 = unsigned 8 bytes */
+ .min.i = 0,
+ .max.i = 0xffffffffffffffff
+ }
+ },
+ {
+ { /* 0 = signed 1 byte */
+ .min.i = -0x7f-1,
+ .max.i = 0x7f
+ },
+ { /* 1 = signed 2 byte */
+ .min.i = -0x7fff-1,
+ .max.i = 0x7fff
+ },
+ { /* 2 = signed 4 byte */
+ .min.i = -0x7fffffff-1,
+ .max.i = 0x7fffffff
+ },
+ { /* 3 = signed 8 byte */
+ .min.i = -0x7fffffffffffffff-1,
+ .max.i = 0x7fffffffffffffff,
+ }
+ },
+ {
+ {
+ /* 0 = float 4 bytes */
+ .min.f = -1,
+ .max.f = 2
+ },
+ {
+ /* 1 = float 8 bytes */
+ .min.f = -1,
+ .max.f = 2,
+ },
+ {
+ /* 2 = float 16 bytes */
+ .min.f = -1,
+ .max.f = 2,
+ }
+ }
+};
+
+struct limits *
+getlimits(Type *tp)
+{
+ int ntable, ntype;
+
+ switch (tp->op) {
+ case ENUM:
+ case INT:
+ ntable = ((tp->prop & TSIGNED) != 0);
+ switch (tp->size) {
+ case 1: ntype = 0; break;
+ case 2: ntype = 1; break;
+ case 4: ntype = 2; break;
+ case 8: ntype = 3; break;
+ }
+ break;
+ case FLOAT:
+ ntable = 2;
+ switch (tp->size) {
+ case 4: ntype = 0; break;
+ case 8: ntype = 1; break;
+ case 16: ntype = 2; break;
+ }
+ break;
+ default:
+ abort();
+ }
+
+ return &limits[ntable][ntype];
+}
+
+Type *
+ctype(int type, int sign, int size)
+{
+ switch (type) {
+ case CHAR:
+ if (size)
+ goto invalid_type;
+ switch (sign) {
+ case 0:
+ return chartype;
+ case SIGNED:
+ return schartype;
+ case UNSIGNED:
+ return uchartype;
+ }
+ break;
+ case VA_LIST:
+ if (size || sign)
+ goto invalid_type;
+ return va_list_type;
+ case VOID:
+ if (size || sign)
+ goto invalid_type;
+ return voidtype;
+ case BOOL:
+ if (size || sign)
+ goto invalid_type;
+ return booltype;
+ case 0:
+ case INT:
+ switch (size) {
+ case 0:
+ return (sign == UNSIGNED) ? uinttype : inttype;
+ case SHORT:
+ return (sign == UNSIGNED) ? ushortype : shortype;
+ case LONG:
+ return (sign == UNSIGNED) ? ulongtype : longtype;
+ case LLONG:
+ return (sign == UNSIGNED) ? ullongtype : llongtype;
+ }
+ break;
+ case DOUBLE:
+ if (size == LLONG)
+ goto invalid_type;
+ if (size == LONG)
+ size = LLONG;
+ else
+ size = LONG;
+ goto floating;
+ case FLOAT:
+ if (size == LLONG)
+ goto invalid_type;
+ floating:
+ if (sign)
+ goto invalid_type;
+ switch (size) {
+ case 0:
+ return floattype;
+ case LONG:
+ return doubletype;
+ case LLONG:
+ return ldoubletype;
+ }
+ break;
+ }
+
+invalid_type:
+ error("invalid type specification");
+}
+
+void
+typesize(Type *tp)
+{
+ Symbol **sp;
+ Type *type;
+ unsigned long size, offset;
+ int align, a;
+ TINT n;
+
+ switch (tp->op) {
+ case ARY:
+ /* FIXME: Control overflow */
+ tp->size = tp->n.elem * tp->type->size;
+ tp->align = tp->type->align;
+ return;
+ case PTR:
+ tp->size = pvoidtype->size;
+ tp->align = pvoidtype->align;
+ return;
+ case STRUCT:
+ case UNION:
+ /* FIXME: Control overflow */
+ /*
+ * The alignment of the struct/union is
+ * he alignment of the largest included type.
+ * The size of an union is the size of the largest
+ * field, and the size of a struct is the sum
+ * of the size of every field plus padding bits.
+ */
+ offset = align = size = 0;
+ n = tp->n.elem;
+ for (sp = tp->p.fields; n--; ++sp) {
+ (*sp)->u.i = offset;
+ type = (*sp)->type;
+ a = type->align;
+ if (a > align)
+ align = a;
+ if (tp->op == STRUCT) {
+ if (--a != 0)
+ size = (size + a) & ~a;
+ size += type->size;
+ offset = size;
+ } else {
+ if (type->size > size)
+ size = type->size;
+ }
+ }
+
+ tp->align = align;
+ /*
+ * We have to add the padding bits to
+ * ensure next struct in an array is well
+ * alignment.
+ */
+ if (tp->op == STRUCT && align-- > 1)
+ size += size+align & ~align;
+ tp->size = size;
+ return;
+ case ENUM:
+ tp->size = inttype->size;
+ tp->align = inttype->align;
+ return;
+ case FTN:
+ return;
+ default:
+ abort();
+ }
+}
+
+Type *
+deftype(Type *tp)
+{
+ tp->prop |= TDEFINED;
+ typesize(tp);
+ emit(OTYP, tp);
+ return tp;
+}
+
+static Type *
+newtype(Type *base)
+{
+ Type *tp;
+ size_t siz;
+
+ tp = xmalloc(sizeof(*tp));
+ *tp = *base;
+ tp->id = newid();
+
+ if (tp->op == FTN) {
+ siz = tp->n.elem * sizeof(Type *);
+ tp->p.pars = memcpy(xmalloc(siz), tp->p.pars, siz);
+ }
+
+ if (curfun) {
+ /* it is a type defined in the body of a function */
+ tp->next = localtypes;
+ localtypes = tp;
+ }
+ if (tp->prop & TDEFINED)
+ deftype(tp);
+ return tp;
+}
+
+Type *
+mktype(Type *tp, int op, TINT nelem, Type *pars[])
+{
+ Type **tbl, type;
+ Type *bp;
+
+ if (op == PTR && tp == voidtype)
+ return pvoidtype;
+
+ memset(&type, 0, sizeof(type));
+ type.type = tp;
+ type.op = op;
+ type.p.pars = pars;
+ type.n.elem = nelem;
+
+ switch (op) {
+ case ARY:
+ if (tp == voidtype) {
+ errorp("declaration of array of voids type");
+ tp = inttype;
+ }
+ type.letter = L_ARRAY;
+ if (nelem != 0)
+ type.prop |= TDEFINED;
+ break;
+ case KRFTN:
+ type.prop |= TDEFINED | TK_R;
+ type.op = FTN;
+ type.letter = L_FUNCTION;
+ break;
+ case FTN:
+ if (nelem > 0 && pars[nelem-1] == ellipsistype)
+ type.prop |= TELLIPSIS;
+ type.letter = L_FUNCTION;
+ type.prop |= TDEFINED;
+ break;
+ case PTR:
+ type.letter = L_POINTER;
+ type.prop |= TDEFINED;
+ break;
+ case ENUM:
+ type.letter = inttype->letter;
+ type.prop |= TINTEGER | TARITH;
+ type.n.rank = inttype->n.rank;
+ goto create_type;
+ case STRUCT:
+ type.letter = L_STRUCT;
+ type.prop |= TAGGREG;
+ goto create_type;
+ case UNION:
+ type.letter = L_UNION;
+ type.prop |= TAGGREG;
+ create_type:
+ return newtype(&type);
+ default:
+ abort();
+ }
+
+ tbl = &typetab[HASH(&type)];
+ for (bp = *tbl; bp; bp = bp->h_next) {
+ if (eqtype(bp, &type, 0))
+ return bp;
+ }
+
+ bp = newtype(&type);
+ bp->h_next = *tbl;
+ *tbl = bp;
+
+ return bp;
+}
+
+int
+eqtype(Type *tp1, Type *tp2, int equiv)
+{
+ TINT n;
+ Type **p1, **p2;
+ Symbol **s1, **s2;
+
+ if (tp1 == tp2)
+ return 1;
+ if (!tp1 || !tp2)
+ return 0;
+ if (tp1->op != tp2->op)
+ return 0;
+
+ switch (tp1->op) {
+ case UNION:
+ case STRUCT:
+ if (tp1->letter != tp2->letter)
+ return 0;
+ if (tp1->tag->name || tp2->tag->name)
+ return tp1->tag == tp2->tag;
+ if (tp1->n.elem != tp2->n.elem)
+ return 0;
+ s1 = tp1->p.fields, s2 = tp2->p.fields;
+ for (n = tp1->n.elem; n > 0; --n, ++s1, ++s2) {
+ if (strcmp((*s1)->name, (*s2)->name))
+ return 0;
+ if (!eqtype((*s1)->type, (*s2)->type, equiv))
+ return 0;
+ }
+ return 1;
+ case FTN:
+ if (tp1->n.elem != tp2->n.elem)
+ return 0;
+ p1 = tp1->p.pars, p2 = tp2->p.pars;
+ for (n = tp1->n.elem; n > 0; --n) {
+ if (!eqtype(*p1++, *p2++, equiv))
+ return 0;
+ }
+ goto check_base;
+ case ARY:
+ if (equiv && (tp1->n.elem == 0 || tp2->n.elem == 0))
+ goto check_base;
+ if (tp1->n.elem != tp2->n.elem)
+ return 0;
+ case PTR:
+ check_base:
+ return eqtype(tp1->type, tp2->type, equiv);
+ case VOID:
+ case ENUM:
+ return 0;
+ case INT:
+ case FLOAT:
+ return tp1->letter == tp2->letter;
+ default:
+ abort();
+ }
+}
+
+void
+flushtypes(void)
+{
+ Type *tp, *next, **h;
+
+ for (tp = localtypes; tp; tp = next) {
+ next = tp->next;
+ switch (tp->op) {
+ default:
+ /*
+ * All the local types are linked after
+ * global types, and since we are
+ * unlinking them in the inverse order
+ * we do know that tp is always the head
+ * of the collision list
+ */
+ h = &typetab[HASH(tp)];
+ assert(*h == tp);
+ *h = tp->h_next;
+ case STRUCT:
+ case UNION:
+ case ENUM:
+ free(tp);
+ break;
+ }
+ }
+ localtypes = NULL;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/.gitignore
@@ -1,0 +1,1 @@
+error.h
--- /dev/null
+++ b/src/cmd/cc/cc2/Makefile
@@ -1,0 +1,40 @@
+.POSIX:
+
+PROJECTDIR = ../../../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+MORECFLAGS = -I$(INCDIR)/$(STD)
+
+OBJS = main.o \
+ parser.o \
+ peep.o \
+ symbol.o \
+ node.o \
+ code.o \
+ optm.o \
+
+TARGET = $(LIBEXEC)/cc2-amd64-sysv \
+ $(LIBEXEC)/cc2-i386-sysv \
+ $(LIBEXEC)/cc2-qbe_amd64-sysv \
+ $(LIBEXEC)/cc2-z80-scc \
+
+all: $(TARGET)
+
+$(TARGET): error.h
+
+error.h: cc2.h
+ rm -f $@;\
+ trap 'r=$?;rm -f $$$$.h;exit $r' EXIT INT QUIT ;\
+ awk -f generror.awk cc2.h > $$$$.h && mv $$$$.h $@
+
+dep: inc-dep
+
+clean:
+ rm -f target/*/*.o error.h
+
+include target/amd64-sysv/target.mk
+include target/i386-sysv/target.mk
+include target/qbe_amd64-sysv/target.mk
+include target/qbe_arm64-sysv/target.mk
+include target/z80-scc/target.mk
+include deps.mk
--- /dev/null
+++ b/src/cmd/cc/cc2/cc2.h
@@ -1,0 +1,256 @@
+enum iflags {
+ BBENTRY = 1, /* basic block entry */
+};
+
+enum tflags {
+ SIGNF = 1 << 0, /* Signed type */
+ INTF = 1 << 1, /* integer type */
+ FLOATF = 1 << 2, /* float type */
+ STRF = 1 << 3, /* string */
+ AGGRF = 1 << 4, /* aggregate */
+ FUNF = 1 << 5, /* function */
+ PARF = 1 << 6, /* parameter */
+ INITF = 1 << 7, /* initializer flag */
+ ELLIPS = 1 << 8, /* vararg function */
+};
+
+enum sclass {
+ SAUTO = 'A',
+ SREG = 'R',
+ SLABEL = 'L',
+ SINDEX = 'I',
+ STMP = 'N',
+ SGLOB = 'G',
+ SEXTRN = 'X',
+ SPRIV = 'Y',
+ SLOCAL = 'T',
+ SMEMB = 'M',
+ SCONST = '#',
+ STRING = '"',
+ SNONE = 0 /* cc2 relies on SNONE being 0 in nextpc() */
+};
+
+enum types {
+ ELLIPSIS = 'E',
+ INT8 = 'C',
+ INT16 = 'I',
+ INT32 = 'W',
+ INT64 = 'Q',
+ UINT8 = 'K',
+ UINT16 = 'N',
+ UINT32 = 'Z',
+ UINT64 = 'O',
+ POINTER = 'P',
+ FUNCTION = 'F',
+ VECTOR = 'V',
+ UNION = 'U',
+ STRUCT = 'S',
+ BOOL = 'B',
+ FLOAT = 'J',
+ DOUBLE = 'D',
+ LDOUBLE = 'H',
+ VOID = '0'
+};
+
+enum op {
+ /* kind of operand */
+ /* operands */
+ OMEM = 'M',
+ OTMP = 'N',
+ OAUTO = 'A',
+ OREG = 'R',
+ OCONST = '#',
+ OSTRING = '"',
+ OLOAD = 'D',
+ OLABEL = 'L',
+ OADD = '+',
+ OSUB = '-',
+ OMUL = '*',
+ OMOD = '%',
+ ODIV = '/',
+ OSHL = 'l',
+ OSHR = 'r',
+ OLT = '<',
+ OGT = '>',
+ OLE = '[',
+ OGE = ']',
+ OEQ = '=',
+ ONE = '!',
+ OBAND = '&',
+ OBOR = '|',
+ OBXOR = '^',
+ OCPL = '~',
+ OASSIG = ':',
+ OSNEG = '_',
+ OCALL = 'c',
+ OCALLE = 'z',
+ OPAR = 'p',
+ OFIELD = '.',
+ OCOMMA = ',',
+ OASK = '?',
+ OCOLON = ' ',
+ OADDR = '\'',
+ OAND = 'a',
+ OOR = 'o',
+ ONEG = 'n',
+ OPTR = '@',
+ OCAST = 'g',
+ OINC = 'i',
+ ODEC = 'd',
+ OBUILTIN = 'm',
+ /*statements */
+ ONOP = 'q',
+ OJMP = 'j',
+ OBRANCH = 'y',
+ ORET = 'h',
+ OBLOOP = 'b',
+ OELOOP = 'e',
+ OCASE = 'v',
+ ODEFAULT = 'f',
+ OBSWITCH = 's',
+ OESWITCH = 't',
+ OBFUN = 'x',
+ OEFUN = 'k',
+};
+
+enum builtins {
+ BVA_START = 's',
+ BVA_END = 'e',
+ BVA_ARG = 'a',
+ BVA_COPY = 'c',
+};
+
+enum nerrors {
+ EEOFFUN, /* EOF while parsing function */
+ ENLABEL, /* label without statement */
+ EIDOVER, /* identifier overflow */
+ EOUTPAR, /* out pf params */
+ ESYNTAX, /* syntax error */
+ ESTACKA, /* stack unaligned */
+ ESTACKO, /* stack overflow */
+ ESTACKU, /* stack underflow */
+ ELNLINE, /* line too long */
+ ELNBLNE, /* line without new line */
+ EFERROR, /* error reading from file:%s */
+ EBADID, /* incorrect symbol id */
+ EWTACKO, /* switch stack overflow */
+ EWTACKU, /* switch stack underflow */
+ ENOSWTC, /* Out of switch statement */
+ EBBUILT, /* Unknown builtin */
+ ENUMERR
+};
+
+typedef struct node Node;
+typedef struct type Type;
+typedef struct symbol Symbol;
+typedef struct addr Addr;
+typedef struct inst Inst;
+
+struct type {
+ unsigned long size;
+ unsigned long align;
+ short flags;
+};
+
+struct symbol {
+ Type type;
+ Type rtype;
+ unsigned short id;
+ unsigned short numid;
+ char *name;
+ char kind;
+ union {
+ unsigned long off;
+ Node *stmt;
+ Inst *inst;
+ } u;
+ Symbol *next;
+ Symbol *h_next;
+};
+
+struct node {
+ char op;
+ Type type;
+ char complex;
+ char address;
+ unsigned char flags;
+ union {
+ TUINT i;
+ TFLOAT f;
+ char reg;
+ char *s;
+ Symbol *sym;
+ char subop;
+ } u;
+ Symbol *label;
+ Node *left, *right;
+ Node *next, *prev;
+};
+
+struct addr {
+ char kind;
+ union {
+ char reg;
+ TUINT i;
+ Symbol *sym;
+ } u;
+};
+
+struct inst {
+ unsigned char op;
+ unsigned char flags;
+ Symbol *label;
+ Inst *next, *prev;
+ Addr from1, from2, to;
+};
+
+/* main.c */
+extern void error(unsigned nerror, ...);
+
+/* parse.c */
+extern void parse(void);
+
+/* optm.c */
+extern Node *optm_dep(Node *np), *optm_ind(Node *np);
+
+/* cgen.c */
+extern Node *sethi(Node *np);
+extern Node *cgen(Node *np);
+
+/* peep.c */
+extern void peephole(void);
+
+/* code.c */
+extern void data(Node *np);
+extern void writeout(void), endinit(void), newfun(void);
+extern void code(int op, Node *to, Node *from1, Node *from2);
+extern void defvar(Symbol *), defpar(Symbol *), defglobal(Symbol *);
+extern void setlabel(Symbol *sym), getbblocks(void);
+extern Node *label2node(Node *np, Symbol *sym);
+extern Node *constnode(Node *np, TUINT n, Type *tp);
+extern Symbol *newlabel(void);
+
+/* node.c */
+#define SETCUR 1
+#define KEEPCUR 0
+extern void apply(Node *(*fun)(Node *));
+extern void cleannodes(void);
+extern void delnode(Node *np);
+extern void deltree(Node *np);
+extern void prtree(Node *np), prforest(char *msg);
+extern Node *node(int op);
+extern Node *addstmt(Node *np, int flags);
+extern Node *delstmt(void);
+extern Node *nextstmt(void);
+
+/* symbol.c */
+#define TMPSYM 0
+extern Symbol *getsym(unsigned id);
+extern void popctx(void);
+extern void pushctx(void);
+extern void freesym(Symbol *sym);
+
+/* globals */
+extern Symbol *curfun;
+extern Symbol *locals;
+extern Inst *pc, *prog;
--- /dev/null
+++ b/src/cmd/cc/cc2/code.c
@@ -1,0 +1,132 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/scc.h>
+#include "cc2.h"
+
+Inst *pc, *prog;
+
+static void
+nextpc(void)
+{
+ Inst *new;
+
+ new = xcalloc(1, sizeof(*new)); /* TODO: create an arena */
+
+ if (!pc) {
+ prog = new;
+ } else {
+ new->next = pc->next;
+ pc->next = new;
+ }
+
+ /* SNONE being 0, calloc initialized {from1,from2,to}.kind for us */
+ new->prev = pc;
+ pc = new;
+}
+
+static void
+addr(Node *np, Addr *addr)
+{
+ Symbol *sym;
+
+ switch (np->op) {
+ case OREG:
+ /* TODO:
+ * At this moment this op is used also for register variables
+ */
+ addr->kind = SREG;
+ addr->u.reg = np->u.reg;
+ break;
+ case OCONST:
+ addr->kind = SCONST;
+ /* TODO: Add support for more type of constants */
+ addr->u.i = np->u.i;
+ break;
+ case OTMP:
+ case OLABEL:
+ case OAUTO:
+ case OMEM:
+ sym = np->u.sym;
+ addr->kind = sym->kind;
+ addr->u.sym = sym;
+ break;
+ default:
+ abort();
+ }
+}
+
+Symbol *
+newlabel(void)
+{
+ Symbol *sym = getsym(TMPSYM);
+
+ sym->kind = SLABEL;
+ return sym;
+}
+
+Node *
+label2node(Node *np, Symbol *sym)
+{
+ if(!sym)
+ sym = newlabel();
+ if (!np)
+ np = node(OLABEL);
+ np->op = OLABEL;
+ np->u.sym = sym;
+
+ return np;
+}
+
+Node *
+constnode(Node *np, TUINT n, Type *tp)
+{
+ if (!np)
+ np = node(OCONST);
+ np->op = OCONST;
+ np->left = NULL;
+ np->right = NULL;
+ np->type = *tp;
+ np->u.i = n;
+ return np;
+}
+
+void
+setlabel(Symbol *sym)
+{
+ if (!sym)
+ return;
+ code(0, NULL, NULL, NULL);
+ pc->label = sym;
+ sym->u.inst = pc;
+}
+
+void
+code(int op, Node *to, Node *from1, Node *from2)
+{
+ nextpc();
+ if (from1)
+ addr(from1, &pc->from1);
+ if (from2)
+ addr(from2, &pc->from2);
+ if (to)
+ addr(to, &pc->to);
+ pc->op = op;
+}
+
+void
+delcode(void)
+{
+ Inst *prev = pc->prev, *next = pc->next;
+
+ free(pc);
+ if (!prev) {
+ pc = next;
+ prog = NULL;
+ } else {
+ pc = prev;
+ prev->next = next;
+ if (next)
+ next->prev = prev;
+ }
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/deps.mk
@@ -1,0 +1,61 @@
+#deps
+./code.o: $(INCDIR)/scc/scc/scc.h
+./code.o: ./cc2.h
+./main.o: $(INCDIR)/scc/scc/arg.h
+./main.o: $(INCDIR)/scc/scc/scc.h
+./main.o: ./cc2.h
+./main.o: ./error.h
+./node.o: $(INCDIR)/scc/scc/scc.h
+./node.o: ./cc2.h
+./optm.o: $(INCDIR)/scc/scc/scc.h
+./optm.o: ./cc2.h
+./parser.o: $(INCDIR)/scc/scc/cstd.h
+./parser.o: $(INCDIR)/scc/scc/scc.h
+./parser.o: ./cc2.h
+./peep.o: $(INCDIR)/scc/scc/scc.h
+./peep.o: ./cc2.h
+./symbol.o: $(INCDIR)/scc/scc/scc.h
+./symbol.o: ./cc2.h
+./target/amd64-sysv/cgen.o: $(INCDIR)/scc/scc/scc.h
+./target/amd64-sysv/cgen.o: ./target/amd64-sysv/../../cc2.h
+./target/amd64-sysv/cgen.o: ./target/amd64-sysv/arch.h
+./target/amd64-sysv/code.o: $(INCDIR)/scc/scc/cstd.h
+./target/amd64-sysv/code.o: $(INCDIR)/scc/scc/scc.h
+./target/amd64-sysv/code.o: ./target/amd64-sysv/../../cc2.h
+./target/amd64-sysv/code.o: ./target/amd64-sysv/arch.h
+./target/amd64-sysv/optm.o: $(INCDIR)/scc/scc/scc.h
+./target/amd64-sysv/optm.o: ./target/amd64-sysv/../../cc2.h
+./target/amd64-sysv/types.o: $(INCDIR)/scc/scc/scc.h
+./target/amd64-sysv/types.o: ./target/amd64-sysv/../../cc2.h
+./target/i386-sysv/cgen.o: $(INCDIR)/scc/scc/scc.h
+./target/i386-sysv/cgen.o: ./target/i386-sysv/../../cc2.h
+./target/i386-sysv/cgen.o: ./target/i386-sysv/arch.h
+./target/i386-sysv/code.o: $(INCDIR)/scc/scc/cstd.h
+./target/i386-sysv/code.o: $(INCDIR)/scc/scc/scc.h
+./target/i386-sysv/code.o: ./target/i386-sysv/../../cc2.h
+./target/i386-sysv/code.o: ./target/i386-sysv/arch.h
+./target/i386-sysv/optm.o: $(INCDIR)/scc/scc/scc.h
+./target/i386-sysv/optm.o: ./target/i386-sysv/../../cc2.h
+./target/i386-sysv/types.o: $(INCDIR)/scc/scc/scc.h
+./target/i386-sysv/types.o: ./target/i386-sysv/../../cc2.h
+./target/qbe/cgen.o: $(INCDIR)/scc/scc/cstd.h
+./target/qbe/cgen.o: $(INCDIR)/scc/scc/scc.h
+./target/qbe/cgen.o: ./target/qbe/../../cc2.h
+./target/qbe/cgen.o: ./target/qbe/arch.h
+./target/qbe/code.o: $(INCDIR)/scc/scc/cstd.h
+./target/qbe/code.o: $(INCDIR)/scc/scc/scc.h
+./target/qbe/code.o: ./target/qbe/../../cc2.h
+./target/qbe/code.o: ./target/qbe/arch.h
+./target/qbe/optm.o: $(INCDIR)/scc/scc/scc.h
+./target/qbe/optm.o: ./target/qbe/../../cc2.h
+./target/z80-scc/cgen.o: $(INCDIR)/scc/scc/scc.h
+./target/z80-scc/cgen.o: ./target/z80-scc/../../cc2.h
+./target/z80-scc/cgen.o: ./target/z80-scc/arch.h
+./target/z80-scc/code.o: $(INCDIR)/scc/scc/cstd.h
+./target/z80-scc/code.o: $(INCDIR)/scc/scc/scc.h
+./target/z80-scc/code.o: ./target/z80-scc/../../cc2.h
+./target/z80-scc/code.o: ./target/z80-scc/arch.h
+./target/z80-scc/optm.o: $(INCDIR)/scc/scc/scc.h
+./target/z80-scc/optm.o: ./target/z80-scc/../../cc2.h
+./target/z80-scc/types.o: $(INCDIR)/scc/scc/scc.h
+./target/z80-scc/types.o: ./target/z80-scc/../../cc2.h
--- /dev/null
+++ b/src/cmd/cc/cc2/generror.awk
@@ -1,0 +1,9 @@
+/^enum nerrors \{/ {print "char *errlist[] = {"; inhome = 1}
+
+inhome && /E[A-Z]*, / {sub(/,/, "", $1)
+ printf("\t[%s] = \"", $1)
+ for (i = 3; i <= NF-1; ++i)
+ printf("%s%s", $i, (i == NF-1) ? "\"" : " ")
+ print ","}
+
+inhome && /^}/ {print "};" ; inhome = 0}
--- /dev/null
+++ b/src/cmd/cc/cc2/main.c
@@ -1,0 +1,68 @@
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/arg.h>
+#include <scc/scc.h>
+#include "cc2.h"
+#include "error.h"
+
+char *argv0;
+
+void
+error(unsigned nerror, ...)
+{
+ va_list va;
+ va_start(va, nerror);
+ vfprintf(stderr, errlist[nerror], va);
+ va_end(va);
+ putc('\n', stderr);
+ exit(1);
+}
+
+static int
+moreinput(void)
+{
+ int c;
+
+repeat:
+ if (feof(stdin))
+ return 0;
+ if ((c = getchar()) == '\n' || c == EOF)
+ goto repeat;
+ ungetc(c, stdin);
+ return 1;
+}
+
+static void
+usage(void)
+{
+ fputs("usage: cc2 [irfile]\n", stderr);
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ ARGBEGIN {
+ default:
+ usage();
+ } ARGEND
+
+ if (argv[0] && !freopen(argv[0], "r", stdin))
+ die("cc2: %s: %s", argv[0], strerror(errno));
+
+ while (moreinput()) {
+ parse();
+ apply(optm_ind);
+ apply(optm_dep);
+ apply(sethi);
+ apply(cgen);
+ getbblocks(); /* TODO: run apply over asm ins too */
+ peephole();
+ writeout();
+ }
+ return 0;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/node.c
@@ -1,0 +1,141 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/scc.h>
+
+#include "cc2.h"
+
+#define NNODES 32
+
+Node *curstmt;
+Symbol *curfun;
+
+static Alloc *arena;
+
+
+Node *
+node(int op)
+{
+ struct arena *ap;
+ Node *np;
+
+ if (!arena)
+ arena = alloc(sizeof(Node), NNODES);
+ np = memset(new(arena), 0, sizeof(*np));
+ np->op = op;
+
+ return np;
+}
+
+#ifndef NDEBUG
+#include <stdio.h>
+
+static void
+prnode(Node *np)
+{
+ if (np->left)
+ prnode(np->left);
+ if (np->right)
+ prnode(np->right);
+ fprintf(stderr, "\t%c%lu", np->op, np->type.size);
+}
+
+void
+prtree(Node *np)
+{
+ prnode(np);
+ putc('\n', stderr);
+}
+
+void
+prforest(char *msg)
+{
+ Node *np;
+
+ if (!curfun)
+ return;
+
+ fprintf(stderr, "%s {\n", msg);
+ for (np = curfun->u.stmt; np; np = np->next)
+ prtree(np);
+ fputs("}\n", stderr);
+}
+#endif
+
+Node *
+addstmt(Node *np, int flag)
+{
+ if (curstmt)
+ np->next = curstmt->next;
+ np->prev = curstmt;
+
+ if (!curfun->u.stmt)
+ curfun->u.stmt = np;
+ else
+ curstmt->next = np;
+
+ if (flag == SETCUR)
+ curstmt = np;
+
+ return np;
+}
+
+Node *
+delstmt(void)
+{
+ Node *next, *prev;
+
+ next = curstmt->next;
+ prev = curstmt->prev;
+ if (next)
+ next->prev = prev;
+ if (prev)
+ prev->next = next;
+ else
+ curfun->u.stmt = next;
+ deltree(curstmt);
+
+ return curstmt = next;
+}
+
+Node *
+nextstmt(void)
+{
+ return curstmt = curstmt->next;
+}
+
+void
+delnode(Node *np)
+{
+ delete(arena, np);
+}
+
+void
+deltree(Node *np)
+{
+ if (!np)
+ return;
+ deltree(np->left);
+ deltree(np->right);
+ delnode(np);
+}
+
+void
+cleannodes(void)
+{
+ if (arena) {
+ dealloc(arena);
+ arena = NULL;
+ }
+ curstmt = NULL;
+}
+
+void
+apply(Node *(*fun)(Node *))
+{
+ if (!curfun)
+ return;
+ curstmt = curfun->u.stmt;
+ while (curstmt)
+ (*fun)(curstmt) ? nextstmt() : delstmt();
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/optm.c
@@ -1,0 +1,9 @@
+#include <scc/scc.h>
+#include "cc2.h"
+
+Node *
+optm_ind(Node *np)
+{
+ return np;
+}
+
--- /dev/null
+++ b/src/cmd/cc/cc2/parser.c
@@ -1,0 +1,721 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "cc2.h"
+
+#define STACKSIZ 50
+
+extern Type int8type, int16type, int32type, int64type,
+ uint8type, uint16type, uint32type, uint64type,
+ float32type, float64type, float80type,
+ booltype,
+ ptrtype,
+ voidtype,
+ arg_type;
+
+Type funetype = {
+ .flags = FUNF | ELLIPS
+};
+
+Type funtype = {
+ .flags = FUNF
+};
+
+union tokenop {
+ void *arg;
+ unsigned op;
+};
+
+struct swtch {
+ int nr;
+ Node *first;
+ Node *last;
+};
+
+static struct swtch swtbl[NR_BLOCK], *swp = swtbl;
+static Symbol *lastfun;
+
+typedef void parsefun(char *, union tokenop);
+static parsefun type, symbol, getname, unary, binary, ternary, call,
+ constant, composed, binit, einit,
+ jump, oreturn, loop, assign,
+ ocase, bswitch, eswitch, builtin;
+
+typedef void evalfun(void);
+static evalfun vardecl, beginfun, endfun, endpars, stmt,
+ array, aggregate, flddecl, labeldcl;
+
+static struct decoc {
+ void (*eval)(void);
+ void (*parse)(char *token, union tokenop);
+ union tokenop u;
+} optbl[] = { /* eval parse args */
+ ['A'] = { vardecl, symbol, .u.op = SAUTO<<8 | OAUTO},
+ ['R'] = { vardecl, symbol, .u.op = SREG<<8 | OREG},
+ ['G'] = { vardecl, symbol, .u.op = SGLOB<<8 | OMEM},
+ ['X'] = { vardecl, symbol, .u.op = SEXTRN<<8 | OMEM},
+ ['Y'] = { vardecl, symbol, .u.op = SPRIV<<8 | OMEM},
+ ['T'] = { vardecl, symbol, .u.op = SLOCAL<<8 | OMEM},
+ ['M'] = { flddecl, symbol, .u.op = SMEMB<<8 | OMEM},
+ ['L'] = { labeldcl, symbol, .u.op = SLABEL<<8 | OLABEL},
+
+ ['C'] = { NULL, type, .u.arg = &int8type},
+ ['I'] = { NULL, type, .u.arg = &int16type},
+ ['W'] = { NULL, type, .u.arg = &int32type},
+ ['Q'] = { NULL, type, .u.arg = &int64type},
+ ['K'] = { NULL, type, .u.arg = &uint8type},
+ ['N'] = { NULL, type, .u.arg = &uint16type},
+ ['Z'] = { NULL, type, .u.arg = &uint32type},
+ ['O'] = { NULL, type, .u.arg = &uint64type},
+ ['J'] = { NULL, type, .u.arg = &float32type},
+ ['D'] = { NULL, type, .u.arg = &float64type},
+ ['H'] = { NULL, type, .u.arg = &float80type},
+ ['0'] = { NULL, type, .u.arg = &voidtype},
+ ['B'] = { NULL, type, .u.arg = &booltype},
+ ['P'] = { NULL, type, .u.arg = &ptrtype},
+ ['E'] = { NULL, type, .u.arg = &funetype},
+ ['1'] = { NULL, type, .u.arg = &arg_type},
+
+ ['F'] = { NULL, type, .u.arg = &funtype},
+ ['V'] = { array,composed, 0},
+ ['U'] = {aggregate,composed, 0},
+ ['S'] = {aggregate,composed, 0},
+
+ ['"'] = { NULL, getname, 0},
+ ['{'] = { beginfun, NULL, 0},
+ ['}'] = { endfun, NULL, 0},
+ ['('] = { NULL, binit, 0},
+ [')'] = { NULL, einit, 0},
+ ['\\'] = { endpars, NULL, 0},
+ ['\t'] = { stmt, NULL, 0},
+
+ ['~'] = { NULL, unary, .u.op = OCPL},
+ ['_'] = { NULL, unary, .u.op = OSNEG},
+ ['\''] = { NULL, unary, .u.op = OADDR},
+ ['@'] = { NULL, unary, .u.op = OPTR},
+ ['g'] = { NULL, unary, .u.op = OCAST},
+ ['p'] = { NULL, unary, .u.op = OPAR},
+ ['n'] = { NULL, unary, .u.op = ONEG},
+
+ ['a'] = { NULL, binary, .u.op = OAND},
+ ['o'] = { NULL, binary, .u.op = OOR},
+ ['.'] = { NULL, binary, .u.op = OFIELD},
+ ['+'] = { NULL, binary, .u.op = OADD},
+ ['-'] = { NULL, binary, .u.op = OSUB},
+ ['*'] = { NULL, binary, .u.op = OMUL},
+ ['%'] = { NULL, binary, .u.op = OMOD},
+ ['/'] = { NULL, binary, .u.op = ODIV},
+ ['l'] = { NULL, binary, .u.op = OSHL},
+ ['r'] = { NULL, binary, .u.op = OSHR},
+ ['<'] = { NULL, binary, .u.op = OLT},
+ ['>'] = { NULL, binary, .u.op = OGT},
+ ['['] = { NULL, binary, .u.op = OLE},
+ [']'] = { NULL, binary, .u.op = OGE},
+ ['='] = { NULL, binary, .u.op = OEQ},
+ ['!'] = { NULL, binary, .u.op = ONE},
+ ['&'] = { NULL, binary, .u.op = OBAND},
+ ['|'] = { NULL, binary, .u.op = OBOR},
+ ['^'] = { NULL, binary, .u.op = OBXOR},
+ [','] = { NULL, binary, .u.op = OCOMMA},
+ ['m'] = { NULL, builtin,.u.op = OBUILTIN},
+
+ [':'] = { NULL, assign, .u.op = OASSIG},
+ ['?'] = { NULL, ternary, .u.op = OASK},
+ ['c'] = { NULL, call, .u.op = OCALL},
+ ['z'] = { NULL, call, .u.op = OCALLE},
+
+ ['#'] = { NULL,constant, .u.op = OCONST},
+
+ ['j'] = { NULL, jump, .u.op = OJMP},
+ ['y'] = { NULL, jump, .u.op = OBRANCH},
+ ['h'] = { NULL, oreturn, .u.op = ORET},
+ ['i'] = { NULL, NULL, .u.op = OINC},
+ ['d'] = { NULL, NULL, .u.op = ODEC},
+
+ ['b'] = { NULL, loop, .u.op = OBLOOP},
+ ['e'] = { NULL, loop, .u.op = OELOOP},
+
+ ['v'] = { NULL, ocase, .u.op = OCASE},
+ ['f'] = { NULL, ocase, .u.op = ODEFAULT},
+ ['t'] = { NULL, eswitch, .u.op = OESWITCH},
+ ['s'] = { NULL, bswitch, .u.op = OBSWITCH},
+};
+
+static int sclass, inpars, ininit, endf, lineno;
+static void *stack[STACKSIZ], **sp = stack;
+
+static Node *
+push(void *elem)
+{
+ if (sp == &stack[STACKSIZ])
+ error(ESTACKO);
+ return *sp++ = elem;
+}
+
+static void *
+pop(void)
+{
+ if (sp == stack)
+ error(ESTACKU);
+ return *--sp;
+}
+
+static int
+empty(void)
+{
+ return sp == stack;
+}
+
+static void
+type(char *token, union tokenop u)
+{
+ push(u.arg);
+}
+
+static void
+composed(char *token, union tokenop u)
+{
+ Symbol *sym;
+
+ sym = getsym(atoi(token+1));
+ push(&sym->type);
+}
+
+static void
+getname(char *t, union tokenop u)
+{
+ push((*++t) ? xstrdup(t) : NULL);
+}
+
+static void
+symbol(char *token, union tokenop u)
+{
+ Node *np = node(u.op & 0xFF);
+ Symbol *sym = getsym(atoi(token+1));
+
+ sclass = u.op >> 8;
+ np->u.sym = sym;
+ np->type = sym->type;
+ push(np);
+}
+
+static Type *
+gettype(char *token)
+{
+ struct decoc *dp;
+
+ dp = &optbl[*token];
+ if (!dp->parse)
+ error(ESYNTAX);
+ (*dp->parse)(token, dp->u);
+ return pop();
+}
+
+static void
+constant(char *token, union tokenop u)
+{
+ static char letters[] = "0123456789ABCDEF";
+ Node *np;
+ TUINT v;
+ unsigned c;
+
+ ++token;
+ if (*token == '"') {
+ ++token;
+ np = node(OSTRING);
+ np->type.flags = STRF;
+ np->type.size = strlen(token);
+ np->type.align = int8type.align;
+ np->u.s = xstrdup(token);
+ } else {
+ np = node(OCONST);
+ np->type = *gettype(token++);
+ for (v = 0; c = *token++; v += c) {
+ v <<= 4;
+ c = strchr(letters, c) - letters;
+ }
+ np->u.i = v;
+ }
+ push(np);
+}
+
+static void
+assign(char *token, union tokenop u)
+{
+ int subop;
+ Node *np = node(u.op);
+
+ switch (subop = *++token) {
+ case '+':
+ case '-':
+ case '*':
+ case '%':
+ case '/':
+ case 'l':
+ case 'r':
+ case '&':
+ case '|':
+ case '^':
+ case 'i':
+ case 'd':
+ ++token;
+ subop = optbl[subop].u.op;
+ break;
+ default:
+ subop = 0;
+ break;
+ }
+
+ np->u.subop = subop;
+ np->type = *gettype(token);
+ np->right = pop();
+ np->left = pop();
+ push(np);
+}
+
+static void
+ternary(char *token, union tokenop u)
+{
+ Node *ask = node(OASK), *colon = node(OCOLON);
+ Type *tp = gettype(token+1);
+
+ colon->right = pop();
+ colon->left = pop();
+
+ ask->type = *tp;
+ ask->left = pop();
+ ask->right = colon;
+ push(ask);
+}
+
+static void
+eval(char *tok)
+{
+ struct decoc *dp;
+
+ do {
+ dp = &optbl[*tok];
+ if (!dp->parse)
+ break;
+ (*dp->parse)(tok, dp->u);
+ } while (tok = strtok(NULL, "\t\n"));
+}
+
+static int
+nextline(void)
+{
+ static char line[LINESIZ];
+ size_t len;
+ int c;
+ void (*fun)(void);
+
+repeat:
+ ++lineno;
+ if (!fgets(line, sizeof(line), stdin))
+ return 0;
+ if ((len = strlen(line)) == 0 || line[0] == '\n')
+ goto repeat;
+ if (line[len-1] != '\n')
+ error(len < sizeof(line)-1 ? ELNBLNE : ELNLINE);
+ line[len-1] = '\0';
+
+ c = *line;
+ eval(strtok(line, "\t\n"));
+ if ((fun = *optbl[c].eval) != NULL)
+ (*fun)();
+ if (sp != stack)
+ error(ESTACKA);
+ return 1;
+}
+
+static void
+oreturn(char *token, union tokenop u)
+{
+ Node *np = node(u.op);
+
+ if (token = strtok(NULL, "\t\n"))
+ eval(token);
+ if (!empty())
+ np->left = pop();
+ push(np);
+}
+
+/*
+ * Move np (which is a OCASE/ODEFAULT/OESWITCH) to be contigous with
+ * the last switch table. It is a bit ugly to touch directly curstmt
+ * here, but moving this function to node.c is worse, because we are
+ * putting knowledge of how the text is parsed into the node
+ * represtation module.
+ */
+static void
+waft(Node *np)
+{
+ Node *lastcase, *next;;
+ struct swtch *cur;
+ extern Node *curstmt;
+
+ if (swp == swtbl)
+ error(EWTACKU);
+
+ cur = swp - 1;
+ lastcase = cur->last;
+ next = lastcase->next;
+
+ np->next = next;
+ np->prev = lastcase;
+
+ if (next)
+ next->prev = np;
+ lastcase->next = np;
+
+ if (curstmt == cur->last)
+ curstmt = np;
+ cur->last = np;
+ cur->nr++;
+}
+
+static void
+bswitch(char *token, union tokenop u)
+{
+ struct swtch *cur;
+ Node *np = node(u.op);
+
+ if (swp == &swtbl[NR_BLOCK])
+ error(EWTACKO);
+ cur = swp++;
+ cur->nr = 0;
+
+ eval(strtok(NULL, "\t\n"));
+ np->left = pop();
+
+ push(cur->first = cur->last = np);
+}
+
+static void
+eswitch(char *token, union tokenop u)
+{
+ struct swtch *cur;
+
+ if (swp == swtbl)
+ error(EWTACKU);
+ jump(token, u);
+ waft(pop());
+ cur = --swp;
+ cur->first->u.i = cur->nr;
+}
+
+static void
+ocase(char *token, union tokenop u)
+{
+ jump(token, u);
+ waft(pop());
+}
+
+static void
+jump(char *token, union tokenop u)
+{
+ Node *aux, *np = node(u.op);
+
+ eval(strtok(NULL, "\t\n"));
+
+ if (u.op == OBRANCH || u.op == OCASE)
+ np->left = pop();
+ aux = pop();
+ np->u.sym = aux->u.sym;
+ delnode(aux);
+ push(np);
+}
+
+static void
+loop(char *token, union tokenop u)
+{
+ push(node(u.op));
+}
+
+static void
+unary(char *token, union tokenop u)
+{
+ Node *np = node(u.op);
+
+ np->type = *gettype(token+1);
+ np->left = pop();
+ np->right = NULL;
+ push(np);
+}
+
+static void
+call(char *token, union tokenop u)
+{
+ Node *np, *par, *fun = node(u.op);
+
+ for (par = NULL;; par = np) {
+ np = pop();
+ if (np->op != OPAR)
+ break;
+ np->right = par;
+ }
+
+ fun->type = *gettype(token+1);
+ fun->left = np;
+ fun->right = par;
+ push(fun);
+}
+
+static void
+builtin(char *token, union tokenop u)
+{
+ Node *np = node(u.op);
+ char *name;
+ unsigned subop, nchilds;
+
+ np->type = *gettype(token+1);
+ name = pop();
+
+ if (!strcmp("__builtin_va_arg", name)) {
+ nchilds = 1;
+ subop = BVA_ARG;
+ } else if (!strcmp("__builtin_va_start", name)) {
+ nchilds = 2;
+ subop = BVA_START;
+ } else if (!strcmp("__builtin_va_end", name)) {
+ nchilds = 1;
+ subop = BVA_END;
+ } else if (!strcmp("__builtin_va_copy", name)) {
+ nchilds = 2;
+ subop = BVA_COPY;
+ } else {
+ error(EBBUILT);;
+ }
+
+ np->u.subop = subop;
+ np->right = (nchilds == 2) ? pop() : NULL;
+ np->left = (nchilds != 0) ? pop() : NULL;
+
+ free(name);
+ push(np);
+}
+
+static void
+binary(char *token, union tokenop u)
+{
+ Node *np = node(u.op);
+
+ np->type = *gettype(token+1);
+ np->right = pop();
+ np->left = pop();
+ push(np);
+}
+
+static void
+binit(char *token, union tokenop u)
+{
+ ininit = 1;
+}
+
+static void
+einit(char *token, union tokenop u)
+{
+ ininit = 0;
+ endinit();
+}
+
+static void
+endpars(void)
+{
+ if (!curfun || !inpars)
+ error(ESYNTAX);
+ inpars = 0;
+}
+
+static void
+aggregate(void)
+{
+ Node *align, *size;
+ char *name;
+ Type *tp;
+ Symbol *sym;
+
+ align = pop();
+ size = pop();
+ name = pop();
+ tp = pop();
+
+ tp->size = size->u.i;
+ tp->align = align->u.i;
+ tp->flags = AGGRF;
+ /*
+ * type is the first field of Symbol so we can obtain the
+ * address of the symbol from the address of the type.
+ * We have to do this because composed returns the pointer
+ * to the type, but in this function we also need the
+ * symbol to store the name.
+ */
+ sym = (Symbol *) tp;
+ sym->name = name;
+
+ delnode(align);
+ delnode(size);
+}
+
+static void
+array(void)
+{
+ Type *tp, *base;
+ Node *size;
+
+ size = pop();
+ base = pop();
+ tp = pop();
+ tp->size = size->u.i * base->size; /* FIXME check for overflow */
+ tp->align = base->align;
+
+ delnode(size);
+}
+
+static void
+decl(Symbol *sym)
+{
+ Type *tp = &sym->type;
+
+ if (tp->flags & FUNF) {
+ lastfun = sym;
+ } else {
+ switch (sym->kind) {
+ case SEXTRN:
+ case SGLOB:
+ case SPRIV:
+ case SLOCAL:
+ defglobal(sym);
+ break;
+ case SAUTO:
+ case SREG:
+ if (!curfun)
+ error(ESYNTAX);
+ ((inpars) ? defpar : defvar)(sym);
+ break;
+ default:
+ abort();
+ }
+ }
+}
+
+static void
+vardecl(void)
+{
+ Type *tp, *rp;
+ Node *np;
+ Symbol *sym;
+ char *name;
+
+ name = pop();
+ tp = pop();
+ if (tp->flags & FUNF)
+ rp = pop();
+ np = pop();
+
+ sym = np->u.sym;
+ /*
+ * We have to free sym->name because in tentative declarations
+ * we can have multiple declarations of the same symbol, and in
+ * this case our parser will allocate twice the memory
+ */
+ free(sym->name);
+ sym->name = name;
+ sym->type = *tp;
+ if (tp->flags & FUNF)
+ sym->rtype = *rp;
+ sym->kind = sclass;
+
+ if (ininit)
+ sym->type.flags |= INITF;
+ decl(sym);
+ delnode(np);
+}
+
+static void
+flddecl(void)
+{
+ Node *off, *np;
+ char *name;
+ Type *tp;
+ Symbol *sym;
+
+ off = pop();
+ name = pop();
+ tp = pop();
+ np = pop();
+
+ sym = np->u.sym;
+ sym->u.off = off->u.i;
+ sym->name = name;
+ sym->type = *tp;
+
+ delnode(np);
+ delnode(off);
+}
+
+static void
+labeldcl(void)
+{
+ Node *np;
+ Symbol *sym;
+
+ np = pop();
+ np->op = ONOP;
+ sym = np->u.sym;
+ sym->kind = SLABEL;
+ sym->u.stmt = np;
+ np->label = sym;
+ addstmt(np, SETCUR);
+}
+
+static void
+stmt(void)
+{
+ Node *np;
+
+ if (empty())
+ return;
+ np = pop();
+ if (ininit) {
+ data(np);
+ deltree(np);
+ return;
+ }
+ addstmt(np, SETCUR);
+}
+
+static void
+beginfun(void)
+{
+ curfun = lastfun;
+ inpars = 1;
+ pushctx();
+ addstmt(node(OBFUN), SETCUR);
+}
+
+static void
+endfun(void)
+{
+ endf = 1;
+ addstmt(node(OEFUN), SETCUR);
+}
+
+void
+parse(void)
+{
+ cleannodes(); /* remove code of previous function */
+ popctx(); /* remove context of previous function */
+ curfun = NULL;
+ endf = 0;
+
+ while (!endf && nextline())
+ ;
+ if (ferror(stdin))
+ error(EFERROR, strerror(errno));
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/peep.c
@@ -1,0 +1,7 @@
+#include <scc/scc.h>
+#include "cc2.h"
+
+void
+peephole(void)
+{
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/symbol.c
@@ -1,0 +1,91 @@
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/scc.h>
+
+#include "cc2.h"
+
+#define NR_SYMHASH 64
+
+Symbol *locals;
+
+static Symbol *symtab[NR_SYMHASH], *curlocal;
+static int infunction;
+
+
+void
+freesym(Symbol *sym)
+{
+ free(sym->name);
+ free(sym);
+}
+
+void
+pushctx(void)
+{
+ infunction = 1;
+}
+
+void
+popctx(void)
+{
+ Symbol *sym, *next;
+
+ infunction = 0;
+ for (sym = locals; sym; sym = next) {
+ next = sym->next;
+ /*
+ * Symbols are inserted in the hash in the inverted
+ * order they are found in locals and it is impossible
+ * to have a global over a local, because a local is
+ * any symbol defined in the body of a function,
+ * even if it has extern linkage.
+ * For this reason when we reach a symbol in the
+ * locals list we know that it is the head of it
+ * collision list and we can remove it assigning
+ * it h_next to the hash table position
+ */
+ if (sym->id != TMPSYM)
+ symtab[sym->id & NR_SYMHASH-1] = sym->h_next;
+ freesym(sym);
+ }
+ curlocal = locals = NULL;
+}
+
+Symbol *
+getsym(unsigned id)
+{
+ Symbol **htab, *sym;
+ static unsigned short num;
+
+ if (id >= USHRT_MAX)
+ error(EBADID);
+
+ if (id != TMPSYM) {
+ htab = &symtab[id & NR_SYMHASH-1];
+ for (sym = *htab; sym; sym = sym->h_next) {
+ if (sym->id == id)
+ return sym;
+ }
+ }
+
+ sym = xcalloc(1, sizeof(*sym));
+ sym->id = id;
+ if (infunction) {
+ if (!locals)
+ locals = sym;
+ if (curlocal)
+ curlocal->next = sym;
+ curlocal = sym;
+ }
+ if (id != TMPSYM) {
+ sym->h_next = *htab;
+ *htab = sym;
+ }
+ if ((sym->numid = ++num) == 0)
+ error(EIDOVER);
+
+ return sym;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/amd64-sysv/cgen.c
@@ -1,0 +1,13 @@
+#include "arch.h"
+#include <scc/scc.h>
+#include "../../cc2.h"
+
+Node *
+cgen(Node *np)
+{
+}
+
+Node *
+sethi(Node *np)
+{
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/amd64-sysv/code.c
@@ -1,0 +1,209 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+enum segment {
+ CODESEG,
+ DATASEG,
+ BSSSEG,
+ NOSEG
+};
+
+static int curseg = NOSEG;
+
+static void
+segment(int seg)
+{
+ static char *txt[] = {
+ [CODESEG] = "\t.text\n",
+ [DATASEG] = "\t.data\n",
+ [BSSSEG] = "\t.bss\n",
+ };
+
+ if (seg == curseg)
+ return;
+ fputs(txt[seg], stdout);
+ curseg = seg;
+}
+
+static char *
+symname(Symbol *sym)
+{
+ static char name[INTIDENTSIZ+1];
+
+ if (sym->name) {
+ switch (sym->kind) {
+ case SEXTRN:
+ case SGLOB:
+ case SPRIV:
+ return sym->name;
+ }
+ }
+
+ sprintf(name, ".L%d", sym->numid);
+
+ return name;
+}
+
+static void
+emitconst(Node *np)
+{
+ switch (np->type.size) {
+ case 1:
+ printf("%d", (int) np->u.i & 0xFF);
+ break;
+ case 2:
+ printf("%d", (int) np->u.i & 0xFFFF);
+ break;
+ case 4:
+ printf("%ld", (long) np->u.i & 0xFFFFFFFF);
+ break;
+ case 8:
+ printf("%lld", (long long) np->u.i & 0xFFFFFFFF);
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+emittree(Node *np)
+{
+ if (!np)
+ return;
+
+ switch (np->op) {
+ case OSTRING:
+ printf("\"%s\"", np->u.s);
+ free(np->u.s);
+ np->u.s = NULL;
+ break;
+ case OCONST:
+ emitconst(np);
+ break;
+ case OADDR:
+ emittree(np->left);
+ break;
+ case OMEM:
+ fputs(symname(np->u.sym), stdout);
+ break;
+ default:
+ emittree(np->left);
+ printf(" %c ", np->op);
+ emittree(np->right);
+ break;
+ }
+}
+static void
+size2asm(Type *tp)
+{
+ char *s;
+
+ if (tp->flags & STRF) {
+ s = "\t.ascii\t";
+ } else {
+ switch (tp->size) {
+ case 1:
+ s = "\t.byte\t";
+ break;
+ case 2:
+ s = "\t.short\t";
+ break;
+ case 4:
+ s = "\t.long\t";
+ break;
+ case 8:
+ s = "\t.quad\t";
+ break;
+ default:
+ s = "\t.space\t%lu,";
+ break;
+ }
+ }
+ printf(s, tp->size);
+}
+
+
+void
+data(Node *np)
+{
+ size2asm(&np->type);
+ emittree(np);
+ putchar('\n');
+}
+
+static void
+label(Symbol *sym)
+{
+ int seg;
+ char *name = symname(sym);
+ Type *tp = &sym->type;
+
+ if (sym->type.flags & FUNF)
+ seg = CODESEG;
+ else if (sym->type.flags & INITF)
+ seg = DATASEG;
+ else
+ seg = BSSSEG;
+ segment(seg);
+
+ switch (sym->kind) {
+ case SEXTRN:
+ printf("\t.extern\t%s\n", name);
+ case SLOCAL:
+ return;
+ case SGLOB:
+ printf("\t.global\t%s\n", name);
+ if (seg == BSSSEG)
+ printf("\t.comm\t%s,%lu\n", name, tp->size);
+ break;
+ }
+ if (sym->type.align != 1)
+ printf("\t.align\t%lu\n", sym->type.align );
+ printf("%s:\n", name);
+}
+
+void
+defglobal(Symbol *sym)
+{
+ label(sym);
+ if (sym->kind == SEXTRN || (sym->type.flags & INITF))
+ return;
+ size2asm(&sym->type);
+ puts("0");
+}
+
+void
+defvar(Symbol *sym)
+{
+}
+
+void
+defpar(Symbol *sym)
+{
+}
+
+void
+newfun(void)
+{
+}
+
+void
+writeout(void)
+{
+}
+
+void
+endinit(void)
+{
+}
+
+void
+getbblocks(void)
+{
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/amd64-sysv/optm.c
@@ -1,0 +1,9 @@
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+Node *
+optm_dep(Node *np)
+{
+ return np;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/amd64-sysv/target.mk
@@ -1,0 +1,8 @@
+OBJ-amd64-sysv = $(OBJS) \
+ target/amd64-sysv/cgen.o \
+ target/amd64-sysv/optm.o \
+ target/amd64-sysv/code.o \
+ target/amd64-sysv/types.o
+
+$(LIBEXEC)/cc2-amd64-sysv: $(OBJ-amd64-sysv)
+ $(CC) $(SCC_LDFLAGS) $(OBJ-amd64-sysv) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc2/target/amd64-sysv/types.c
@@ -1,0 +1,92 @@
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+
+Type int8type = {
+ .flags = SIGNF | INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type int16type = {
+ .flags = SIGNF | INTF,
+ .size = 2,
+ .align = 2
+};
+
+Type int32type = {
+ .flags = SIGNF | INTF,
+ .size = 4,
+ .align = 4
+};
+
+Type int64type = {
+ .flags = SIGNF | INTF,
+ .size = 8,
+ .align = 8
+};
+
+Type uint8type = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type uint16type = {
+ .flags = INTF,
+ .size = 2,
+ .align = 2
+};
+
+Type uint32type = {
+ .flags = INTF,
+ .size = 4,
+ .align = 4
+};
+
+Type uint64type = {
+ .flags = INTF,
+ .size = 8,
+ .align = 2
+};
+
+Type ptrtype = {
+ .flags = INTF,
+ .size = 8,
+ .align = 8
+};
+
+Type booltype = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type float32type = {
+ .flags = FLOATF,
+ .size = 4,
+ .align = 4
+};
+
+Type float64type = {
+ .flags = FLOATF,
+ .size = 8,
+ .align = 8
+};
+
+Type float80type = {
+ .flags = FLOATF,
+ .size = 16,
+ .align = 16
+};
+
+Type voidtype = {
+ .size = 0,
+ .align = 0
+};
+
+Type arg_type = {
+ .size = 24,
+ .align = 8
+};
--- /dev/null
+++ b/src/cmd/cc/cc2/target/i386-sysv/cgen.c
@@ -1,0 +1,14 @@
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+Node *
+cgen(Node *np)
+{
+}
+
+Node *
+sethi(Node *np)
+{
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/i386-sysv/code.c
@@ -1,0 +1,208 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+enum segment {
+ CODESEG,
+ DATASEG,
+ BSSSEG,
+ NOSEG
+};
+
+static int curseg = NOSEG;
+
+static void
+segment(int seg)
+{
+ static char *txt[] = {
+ [CODESEG] = "\t.text\n",
+ [DATASEG] = "\t.data\n",
+ [BSSSEG] = "\t.bss\n",
+ };
+
+ if (seg == curseg)
+ return;
+ fputs(txt[seg], stdout);
+ curseg = seg;
+}
+
+static char *
+symname(Symbol *sym)
+{
+ static char name[INTIDENTSIZ+1];
+
+ if (sym->name) {
+ switch (sym->kind) {
+ case SEXTRN:
+ case SGLOB:
+ case SPRIV:
+ return sym->name;
+ }
+ }
+
+ sprintf(name, ".L%d", sym->numid);
+
+ return name;
+}
+
+static void
+emitconst(Node *np)
+{
+ switch (np->type.size) {
+ case 1:
+ printf("%d", (int) np->u.i & 0xFF);
+ break;
+ case 2:
+ printf("%d", (int) np->u.i & 0xFFFF);
+ break;
+ case 4:
+ printf("%ld", (long) np->u.i & 0xFFFFFFFF);
+ break;
+ case 8:
+ printf("%lld", (long long) np->u.i & 0xFFFFFFFF);
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+emittree(Node *np)
+{
+ if (!np)
+ return;
+
+ switch (np->op) {
+ case OSTRING:
+ printf("\"%s\"", np->u.s);
+ free(np->u.s);
+ np->u.s = NULL;
+ break;
+ case OCONST:
+ emitconst(np);
+ break;
+ case OADDR:
+ emittree(np->left);
+ break;
+ case OMEM:
+ fputs(symname(np->u.sym), stdout);
+ break;
+ default:
+ emittree(np->left);
+ printf(" %c ", np->op);
+ emittree(np->right);
+ break;
+ }
+}
+static void
+size2asm(Type *tp)
+{
+ char *s;
+
+ if (tp->flags & STRF) {
+ s = "\t.ascii\t";
+ } else {
+ switch (tp->size) {
+ case 1:
+ s = "\t.byte\t";
+ break;
+ case 2:
+ s = "\t.short\t";
+ break;
+ case 4:
+ s = "\t.long\t";
+ break;
+ case 8:
+ s = "\t.quad\t";
+ break;
+ default:
+ s = "\t.space\t%lu,";
+ break;
+ }
+ }
+ printf(s, tp->size);
+}
+
+void
+data(Node *np)
+{
+ size2asm(&np->type);
+ emittree(np);
+ putchar('\n');
+}
+
+static void
+label(Symbol *sym)
+{
+ int seg;
+ char *name = symname(sym);
+ Type *tp = &sym->type;
+
+ if (sym->type.flags & FUNF)
+ seg = CODESEG;
+ else if (sym->type.flags & INITF)
+ seg = DATASEG;
+ else
+ seg = BSSSEG;
+ segment(seg);
+
+ switch (sym->kind) {
+ case SEXTRN:
+ printf("\t.extern\t%s\n", name);
+ case SLOCAL:
+ return;
+ case SGLOB:
+ printf("\t.global\t%s\n", name);
+ if (seg == BSSSEG)
+ printf("\t.comm\t%s,%lu\n", name, tp->size);
+ break;
+ }
+ if (sym->type.align != 1)
+ printf("\t.align\t%lu\n", sym->type.align );
+ printf("%s:\n", name);
+}
+
+void
+defglobal(Symbol *sym)
+{
+ label(sym);
+ if (sym->kind == SEXTRN || (sym->type.flags & INITF))
+ return;
+ size2asm(&sym->type);
+ puts("0");
+}
+
+void
+defpar(Symbol *sym)
+{
+}
+
+void
+defvar(Symbol *sym)
+{
+}
+
+void
+newfun(void)
+{
+}
+
+void
+writeout(void)
+{
+}
+
+void
+endinit(void)
+{
+}
+
+void
+getbblocks(void)
+{
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/i386-sysv/optm.c
@@ -1,0 +1,9 @@
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+Node *
+optm_dep(Node *np)
+{
+ return np;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/i386-sysv/target.mk
@@ -1,0 +1,8 @@
+OBJ-i386-sysv = $(OBJS) \
+ target/i386-sysv/cgen.o \
+ target/i386-sysv/optm.o \
+ target/i386-sysv/code.o \
+ target/i386-sysv/types.o
+
+$(LIBEXEC)/cc2-i386-sysv: $(OBJ-i386-sysv)
+ $(CC) $(SCC_LDFLAGS) $(OBJ-i386-sysv) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc2/target/i386-sysv/types.c
@@ -1,0 +1,93 @@
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+
+Type int8type = {
+ .flags = SIGNF | INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type int16type = {
+ .flags = SIGNF | INTF,
+ .size = 2,
+ .align = 2
+};
+
+Type int32type = {
+ .flags = SIGNF | INTF,
+ .size = 4,
+ .align = 4
+};
+
+Type int64type = {
+ .flags = SIGNF | INTF,
+ .size = 8,
+ .align = 4
+};
+
+Type uint8type = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type uint16type = {
+ .flags = INTF,
+ .size = 2,
+ .align = 2
+};
+
+Type uint32type = {
+ .flags = INTF,
+ .size = 4,
+ .align = 2
+};
+
+Type uint64type = {
+ .flags = INTF,
+ .size = 8,
+ .align = 4
+};
+
+Type ptrtype = {
+ .flags = INTF,
+ .size = 4,
+ .align = 4
+};
+
+Type booltype = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type float32type = {
+ .flags = FLOATF,
+ .size = 4,
+ .align = 4
+};
+
+Type float64type = {
+ .flags = FLOATF,
+ .size = 8,
+ .align = 4
+};
+
+Type float80type = {
+ .flags = FLOATF,
+ .size = 12,
+ .align = 4
+};
+
+Type voidtype = {
+ .size = 0,
+ .align = 0
+};
+
+/* this type is not used in this architecture */
+Type arg_type = {
+ .size = 0,
+ .align = 0
+};
--- /dev/null
+++ b/src/cmd/cc/cc2/target/qbe/arch.h
@@ -1,0 +1,135 @@
+enum asmop {
+ ASNOP = 0,
+ ASSTB,
+ ASSTH,
+ ASSTW,
+ ASSTL,
+ ASSTM,
+ ASSTS,
+ ASSTD,
+
+ ASLDSB,
+ ASLDUB,
+ ASLDSH,
+ ASLDUH,
+ ASLDSW,
+ ASLDUW,
+ ASLDL,
+ ASLDS,
+ ASLDD,
+
+ ASADDW,
+ ASSUBW,
+ ASMULW,
+ ASMODW,
+ ASUMODW,
+ ASDIVW,
+ ASUDIVW,
+ ASSHLW,
+ ASSHRW,
+ ASUSHRW,
+ ASLTW,
+ ASULTW,
+ ASGTW,
+ ASUGTW,
+ ASLEW,
+ ASULEW,
+ ASGEW,
+ ASUGEW,
+ ASEQW,
+ ASNEW,
+ ASBANDW,
+ ASBORW,
+ ASBXORW,
+
+ ASADDL,
+ ASSUBL,
+ ASMULL,
+ ASMODL,
+ ASUMODL,
+ ASDIVL,
+ ASUDIVL,
+ ASSHLL,
+ ASSHRL,
+ ASUSHRL,
+ ASLTL,
+ ASULTL,
+ ASGTL,
+ ASUGTL,
+ ASLEL,
+ ASULEL,
+ ASGEL,
+ ASUGEL,
+ ASEQL,
+ ASNEL,
+ ASBANDL,
+ ASBORL,
+ ASBXORL,
+
+ ASADDS,
+ ASSUBS,
+ ASMULS,
+ ASDIVS,
+ ASLTS,
+ ASGTS,
+ ASLES,
+ ASGES,
+ ASEQS,
+ ASNES,
+
+ ASADDD,
+ ASSUBD,
+ ASMULD,
+ ASDIVD,
+ ASLTD,
+ ASGTD,
+ ASLED,
+ ASGED,
+ ASEQD,
+ ASNED,
+
+ ASEXTBW,
+ ASUEXTBW,
+ ASEXTBL,
+ ASUEXTBL,
+ ASEXTHW,
+ ASUEXTHW,
+ ASEXTHL,
+ ASUEXTHL,
+ ASEXTWL,
+ ASUEXTWL,
+
+ ASSTOL,
+ ASSTOW,
+ ASDTOL,
+ ASDTOW,
+
+ ASSWTOD,
+ ASSWTOS,
+ ASSLTOD,
+ ASSLTOS,
+
+ ASEXTS,
+ ASTRUNCD,
+
+ ASJMP,
+ ASBRANCH,
+ ASRET,
+ ASCALL,
+ ASCALLE,
+ ASCALLEX,
+ ASPAR,
+ ASPARE,
+ ASALLOC,
+ ASFORM,
+
+ ASCOPYB,
+ ASCOPYH,
+ ASCOPYW,
+ ASCOPYL,
+ ASCOPYS,
+ ASCOPYD,
+
+ ASVSTAR,
+ ASVARG,
+};
--- /dev/null
+++ b/src/cmd/cc/cc2/target/qbe/cgen.c
@@ -1,0 +1,727 @@
+#include <assert.h>
+#include <stdlib.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+enum sflags {
+ ISTMP = 1,
+ ISCONS = 2
+};
+
+static char opasmw[] = {
+ [OADD] = ASADDW,
+ [OSUB] = ASSUBW,
+ [OMUL] = ASMULW,
+ [OMOD] = ASMODW,
+ [ODIV] = ASDIVW,
+ [OSHL] = ASSHLW,
+ [OSHR] = ASSHRW,
+ [OLT] = ASLTW,
+ [OGT] = ASGTW,
+ [OLE] = ASLEW,
+ [OGE] = ASGEW,
+ [OEQ] = ASEQW,
+ [ONE] = ASNEW,
+ [OBAND] = ASBANDW,
+ [OBOR] = ASBORW,
+ [OBXOR] = ASBXORW,
+};
+
+static char opasml[] = {
+ [OADD] = ASADDL,
+ [OSUB] = ASSUBL,
+ [OMUL] = ASMULL,
+ [OMOD] = ASMODL,
+ [ODIV] = ASDIVL,
+ [OSHL] = ASSHLL,
+ [OSHR] = ASSHRL,
+ [OLT] = ASLTL,
+ [OGT] = ASGTL,
+ [OLE] = ASLEL,
+ [OGE] = ASGEL,
+ [OEQ] = ASEQL,
+ [ONE] = ASNEL,
+ [OBAND] = ASBANDL,
+ [OBOR] = ASBORL,
+ [OBXOR] = ASBXORL,
+};
+
+static char opasms[] = {
+ [OADD] = ASADDS,
+ [OSUB] = ASSUBS,
+ [OMUL] = ASMULS,
+ [ODIV] = ASDIVS,
+ [OLT] = ASLTS,
+ [OGT] = ASGTS,
+ [OLE] = ASLES,
+ [OGE] = ASGES,
+ [OEQ] = ASEQS,
+ [ONE] = ASNES,
+};
+static char opasmd[] = {
+ [OADD] = ASADDD,
+ [OSUB] = ASSUBD,
+ [OMUL] = ASMULD,
+ [ODIV] = ASDIVD,
+ [OLT] = ASLTD,
+ [OGT] = ASGTD,
+ [OLE] = ASLED,
+ [OGE] = ASGED,
+ [OEQ] = ASEQD,
+ [ONE] = ASNED,
+};
+
+extern Type int32type, uint32type, ptrtype;
+
+static Node *
+tmpnode(Node *np, Type *tp)
+{
+ char flags;
+ Symbol *sym;
+
+ if (!np)
+ np = node(OTMP);
+ sym = getsym(TMPSYM);
+ sym->type = np->type = *tp;
+ flags = tp->flags & ~(PARF|INITF);
+ sym->type.flags = np->type.flags = flags;
+ sym->kind = STMP;
+ np->left = np->right = NULL;
+ np->u.sym = sym;
+ np->op = OTMP;
+ np->flags |= ISTMP;
+ return np;
+}
+
+static Node *
+load(Type *tp, Node *np, Node *new)
+{
+ int op;
+ int flags = tp->flags;
+
+ if (flags & (AGGRF|FUNF)) {
+ *new = *np;
+ return new;
+ }
+ switch (tp->size) {
+ case 1:
+ op = ASLDSB;
+ break;
+ case 2:
+ op = ASLDSH;
+ break;
+ case 4:
+ op = (flags & FLOATF) ? ASLDS : ASLDSW;
+ break;
+ case 8:
+ op = (flags & FLOATF) ? ASLDD : ASLDL;
+ break;
+ default:
+ abort();
+ }
+ /*
+ * unsigned version of operations are always +1 the
+ * signed version
+ */
+ if ((flags & (INTF|SIGNF)) == INTF && tp->size < 8)
+ ++op;
+
+ code(op, tmpnode(new, tp), np, NULL);
+
+ return new;
+}
+
+static Node *rhs(Node *np, Node *new);
+
+static Node *
+cast(Type *td, Node *ns, Node *nd)
+{
+ Type *ts;
+ Node aux1, aux2;
+ int op, d_isint, s_isint;
+
+ ts = &ns->type;
+ d_isint = (td->flags & INTF) != 0;
+ s_isint = (ts->flags & INTF) != 0;
+
+ if (d_isint && s_isint) {
+ if (td->size <= ts->size) {
+ *nd = *ns;
+ return nd;
+ }
+ assert(td->size == 4 || td->size == 8);
+ switch (ts->size) {
+ case 1:
+ op = (td->size == 4) ? ASEXTBW : ASEXTBL;
+ break;
+ case 2:
+ op = (td->size == 4) ? ASEXTHW : ASEXTHL;
+ break;
+ case 4:
+ op = ASEXTWL;
+ break;
+ default:
+ abort();
+ }
+ /*
+ * unsigned version of operations are always +1 the
+ * signed version
+ */
+ op += (ts->flags & SIGNF) == 0;
+ } else if (d_isint) {
+ /* conversion from float to int */
+ switch (ts->size) {
+ case 4:
+ op = (td->size == 8) ? ASSTOL : ASSTOW;
+ break;
+ case 8:
+ op = (td->size == 8) ? ASDTOL : ASDTOW;
+ break;
+ default:
+ abort();
+ }
+ /* TODO: Add signess */
+ } else if (s_isint) {
+ /* conversion from int to float */
+ switch (ts->size) {
+ case 1:
+ case 2:
+ ts = (ts->flags&SIGNF) ? &int32type : &uint32type;
+ ns = cast(ts, ns, tmpnode(&aux2, ts));
+ case 4:
+ op = (td->size == 8) ? ASSWTOD : ASSWTOS;
+ break;
+ case 8:
+ op = (td->size == 8) ? ASSLTOD : ASSLTOS;
+ break;
+ default:
+ abort();
+ }
+ /* TODO: Add signess */
+ } else {
+ /* conversion from float to float */
+ op = (td->size == 4) ? ASEXTS : ASTRUNCD;
+ }
+
+ code(op, tmpnode(nd, td), ns, NULL);
+ return nd;
+}
+
+static Node *
+call(Node *np, Node *fun, Node *ret)
+{
+ int n, op;
+ Type *tp;
+ Node aux, **q, *p, *pars[NR_FUNPARAM];
+
+ for (n = 0, p = np->right; p; p = p->right)
+ pars[n++] = rhs(p->left, node(OTMP));
+
+ tp = &np->type;
+ code(ASCALL, tmpnode(ret, tp), fun, NULL);
+
+ for (q = pars; q < &pars[n]; ++q) {
+ op = (q == &pars[n-1]) ? ASPARE : ASPAR;
+ tmpnode(&aux, &(*q)->type);
+ code(op, NULL, *q, &aux);
+ }
+ code((np->op == OCALL) ? ASCALLE : ASCALLEX, NULL, NULL, NULL);
+
+ return ret;
+}
+
+static Node *
+assign(Type *tp, Node *to, Node *from)
+{
+ int op;
+
+ switch (tp->size) {
+ case 1:
+ op = ASSTB;
+ break;
+ case 2:
+ op = ASSTH;
+ break;
+ case 4:
+ op = (tp->flags & FLOATF) ? ASSTS : ASSTW;
+ break;
+ case 8:
+ op = (tp->flags & FLOATF) ? ASSTD : ASSTL;
+ break;
+ default:
+ op = ASSTM;
+ break;
+ }
+ code(op, to, from, NULL);
+ return from;
+}
+
+static Node *
+copy(Type *tp, Node *to, Node *from)
+{
+ int op;
+
+ switch (tp->size) {
+ case 1:
+ op = ASCOPYB;
+ break;
+ case 2:
+ op = ASCOPYH;
+ break;
+ case 4:
+ op = (tp->flags & FLOATF) ? ASCOPYS : ASCOPYW;
+ break;
+ case 8:
+ op = (tp->flags & FLOATF) ? ASCOPYD : ASCOPYL;
+ break;
+ default:
+ /* TODO: Need to handle the general case */
+ abort();
+ }
+ code(op, to, from, NULL);
+ return from;
+}
+
+/* TODO: Do field() transformation in sethi */
+
+static Node *
+field(Node *np, Node *ret, int islhs)
+{
+ Node base, node, off, add, *addr;
+ TUINT offset = np->right->u.sym->u.off;
+
+ addr = rhs(np->left, &base);
+
+ if (offset != 0) {
+ node.op = OADD;
+ node.type = ptrtype;
+ node.left = addr;
+ node.right = constnode(&off, offset, &ptrtype);
+ addr = rhs(&node, &add);
+ }
+
+ if (islhs)
+ *ret = *addr;
+ else
+ load(&np->type, addr, ret);
+
+ return ret;
+}
+
+static Node *
+lhs(Node *np, Node *new)
+{
+ switch (np->op) {
+ case OMEM:
+ case OAUTO:
+ *new = *np;
+ return new;
+ case OPTR:
+ return rhs(np->left, new);
+ case OFIELD:
+ return field(np, new, 1);
+ default:
+ abort();
+ }
+}
+
+static void
+bool(Node *np, Symbol *true, Symbol *false)
+{
+ Node *l = np->left, *r = np->right;
+ Node ret, ifyes, ifno;
+ Symbol *label;
+
+ switch (np->op) {
+ case ONEG:
+ bool(l, false, true);
+ break;
+ case OAND:
+ label = newlabel();
+ bool(l, label, false);
+ setlabel(label);
+ bool(r, true, false);
+ break;
+ case OOR:
+ label = newlabel();
+ bool(l, true, label);
+ setlabel(label);
+ bool(r, true, false);
+ break;
+ default:
+ label2node(&ifyes, true);
+ label2node(&ifno, false);
+ code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno);
+ break;
+ }
+}
+
+static Node *
+ternary(Node *np, Node *ret)
+{
+ Node ifyes, ifno, phi, *colon, aux1, aux2, aux3;
+
+ tmpnode(ret, &np->type);
+ label2node(&ifyes, NULL);
+ label2node(&ifno, NULL);
+ label2node(&phi, NULL);
+
+ colon = np->right;
+ code(ASBRANCH, rhs(np->left, &aux1), &ifyes, &ifno);
+
+ setlabel(ifyes.u.sym);
+ copy(&ret->type, ret, rhs(colon->left, &aux2));
+ code(ASJMP, NULL, &phi, NULL);
+
+ setlabel(ifno.u.sym);
+ copy(&ret->type, ret, rhs(colon->right, &aux3));
+ setlabel(phi.u.sym);
+
+ return ret;
+}
+
+static Node *
+function(void)
+{
+ Node aux;
+ Symbol *p;
+
+ /* allocate stack space for parameters */
+ for (p = locals; p && (p->type.flags & PARF) != 0; p = p->next)
+ code(ASALLOC, label2node(&aux, p), NULL, NULL);
+
+ /* allocate stack space for local variables) */
+ for ( ; p && p->id != TMPSYM; p = p->next) {
+ if (p->kind != SAUTO)
+ continue;
+ code(ASALLOC, label2node(&aux, p), NULL, NULL);
+ }
+ /* store formal parameters in parameters */
+ for (p = locals; p; p = p->next) {
+ if ((p->type.flags & PARF) == 0)
+ break;
+ code(ASFORM, label2node(&aux, p), NULL, NULL);
+ }
+ return NULL;
+}
+
+static void
+swtch_if(Node *idx)
+{
+ Node aux1, aux2, *np;
+ Symbol *deflabel = NULL;
+
+ for (;;) {
+ np = delstmt();
+ setlabel(np->label);
+
+ switch (np->op) {
+ case OESWITCH:
+ if (!deflabel)
+ deflabel = np->u.sym;
+ aux1.op = OJMP;
+ aux1.label = NULL;
+ aux1.u.sym = deflabel;
+ cgen(&aux1);
+ return;
+ case OCASE:
+ aux1 = *np;
+ aux1.op = OBRANCH;
+ aux1.label = NULL;
+ aux1.left = &aux2;
+
+ aux2.op = OEQ;
+ aux2.type = idx->type;
+ aux2.left = np->left;
+ aux2.right = idx;
+
+ cgen(&aux1);
+ break;
+ case ODEFAULT:
+ deflabel = np->u.sym;
+ break;
+ default:
+ abort();
+ }
+ }
+}
+
+static Node *
+rhs(Node *np, Node *ret)
+{
+ Node aux1, aux2, *phi, *l = np->left, *r = np->right;
+ Type *tp;
+ int off, op;
+ char *tbl;
+ Symbol *true, *false;
+
+ tp = &np->type;
+
+ switch (np->op) {
+ case OBFUN:
+ return function();
+ case ONOP:
+ case OBLOOP:
+ case OELOOP:
+ case OEFUN:
+ return NULL;
+ case OTMP:
+ case OCONST:
+ *ret = *np;
+ return np;
+ case OMEM:
+ case OAUTO:
+ return load(tp, np, ret);
+ case ONEG:
+ case OAND:
+ case OOR:
+ true = newlabel();
+ false = newlabel();
+ phi = label2node(&aux1, NULL);
+ tmpnode(ret, &int32type);
+
+ bool(np, true, false);
+
+ setlabel(true);
+ code(ASCOPYW, ret, constnode(&aux2, 1, &int32type), NULL);
+ code(ASJMP, NULL, phi, NULL);
+
+ setlabel(false);
+ code(ASCOPYW, ret, constnode(&aux2, 0, &int32type), NULL);
+
+ setlabel(phi->u.sym);
+ return ret;
+ case OMOD:
+ case OSHR:
+ assert(tp->flags & INTF);
+ case ODIV:
+ case OLT:
+ case OGT:
+ case OLE:
+ case OGE:
+ /*
+ * unsigned version of operations are always +1 the
+ * signed version
+ */
+ off = (tp->flags & SIGNF) == 0;
+ goto binary;
+ case OSHL:
+ case OBAND:
+ case OBOR:
+ case OBXOR:
+ assert(tp->flags & INTF);
+ case OADD:
+ case OSUB:
+ case OMUL:
+ case OEQ:
+ case ONE:
+ off = 0;
+ binary:
+ if (l->complex >= r->complex) {
+ rhs(l, &aux1);
+ rhs(r, &aux2);
+ } else {
+ rhs(r, &aux2);
+ rhs(l, &aux1);
+ }
+ switch (tp->size) {
+ case 4:
+ tbl = (tp->flags & FLOATF) ? opasms : opasmw;
+ break;
+ case 8:
+ tbl = (tp->flags & FLOATF) ? opasmd : opasml;
+ break;
+ default:
+ abort();
+ }
+ op = tbl[np->op] + off;
+ tmpnode(ret, tp);
+ code(op, ret, &aux1, &aux2);
+ return ret;
+ case OCALL:
+ case OCALLE:
+ if (l->op == OPTR)
+ l = rhs(l, &aux1);
+ return call(np, l, ret);
+ case OCAST:
+ return cast(tp, rhs(l, &aux1), ret);
+ case OASSIG:
+ /* TODO: Do this transformations in sethi */
+ switch (np->u.subop) {
+ case OINC:
+ op = OADD;
+ goto post_oper;
+ case ODEC:
+ op = OSUB;
+ post_oper:
+ aux1.op = op;
+ aux1.left = rhs(l, ret);
+ aux1.right = r;
+ aux1.type = np->type;
+ rhs(&aux1, &aux2);
+ lhs(l, &aux1);
+ assign(tp, &aux1, &aux2);
+ break;
+ default:
+ aux2.type = np->type;
+ aux2.op = np->u.subop;
+ aux2.right = np->right;
+ aux2.left = np->left;
+ r = rhs(&aux2, &aux1);
+ Node aux3;
+ if (l->op == OCAST) {
+ aux3.type = l->left->type;
+ aux3.op = OCAST;
+ aux3.left = r;
+ aux3.right = NULL;
+ r = &aux3;
+ l = l->left;
+ }
+ case 0:
+ /* TODO: see what is the most difficult */
+ lhs(l, &aux2);
+ rhs(r, ret);
+ return assign(tp, &aux2, ret);
+ }
+ return ret;
+ case OASK:
+ return ternary(np, ret);
+ case OCOMMA:
+ rhs(l, &aux1);
+ return rhs(r, ret);
+ case OPTR:
+ return load(tp, rhs(l, &aux1), ret);
+ case OADDR:
+ lhs(l, ret);
+ ret->type = *tp;
+ return ret;
+ case OFIELD:
+ return field(np, ret, 0);
+ case OBUILTIN:
+ switch (np->u.subop) {
+ case BVA_START:
+ l = rhs(l, &aux1);
+ code(ASVSTAR, NULL, l, NULL);
+ return NULL;
+ case BVA_END:
+ return NULL;
+ case BVA_ARG:
+ l = rhs(l, &aux1);
+ code(ASVARG, tmpnode(ret, tp), l, NULL);
+ return ret;
+ case BVA_COPY:
+ /* TODO */
+ default:
+ abort();
+ }
+ default:
+ abort();
+ }
+ abort();
+}
+
+Node *
+cgen(Node *np)
+{
+ Node aux, *p, *next;
+
+ setlabel(np->label);
+ switch (np->op) {
+ case OJMP:
+ label2node(&aux, np->u.sym);
+ code(ASJMP, NULL, &aux, NULL);
+ break;
+ case OBRANCH:
+ next = np->next;
+ if (!next->label)
+ next->label = newlabel();
+ bool(np->left, np->u.sym, next->label);
+ break;
+ case ORET:
+ p = (np->left) ? rhs(np->left, &aux) : NULL;
+ code(ASRET, NULL, p, NULL);
+ break;
+ case OBSWITCH:
+ p = rhs(np->left, &aux);
+ swtch_if(p);
+ break;
+ default:
+ rhs(np, &aux);
+ break;
+ }
+ return NULL;
+}
+
+/*
+ * This is strongly influenced by
+ * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
+ * calculate addresability as follows
+ * AUTO => 11 value+fp
+ * REG => 11 reg
+ * STATIC => 11 (value)
+ * CONST => 11 $value
+ * These values of addressability are not used in the code generation.
+ * They are only used to calculate the Sethi-Ullman numbers. Since
+ * QBE is AMD64 targered we could do a better job there, and try to
+ * detect some of the complex addressing modes of these processors.
+ */
+Node *
+sethi(Node *np)
+{
+ Node *lp, *rp;
+
+ if (!np)
+ return np;
+
+ np->complex = 0;
+ np->address = 0;
+ lp = np->left;
+ rp = np->right;
+
+ switch (np->op) {
+ case OAUTO:
+ case OREG:
+ case OMEM:
+ case OCONST:
+ np->address = 11;
+ break;
+ case OCPL:
+ assert(np->type.flags & INTF);
+ np->op = OBXOR;
+ rp = constnode(NULL, ~(TUINT) 0, &np->type);
+ goto binary;
+ case OSNEG:
+ np->op = OSUB;
+ rp = lp;
+ lp = constnode(NULL, 0, &np->type);
+ if ((np->type.flags & INTF) == 0)
+ lp->u.f = 0.0;
+ default:
+ binary:
+ lp = sethi(lp);
+ rp = sethi(rp);
+ break;
+ }
+ np->left = lp;
+ np->right = rp;
+
+ if (np->address > 10)
+ return np;
+ if (lp)
+ np->complex = lp->complex;
+ if (rp) {
+ int d = np->complex - rp->complex;
+
+ if (d == 0)
+ ++np->complex;
+ else if (d < 0)
+ np->complex = rp->complex;
+ }
+ if (np->complex == 0)
+ ++np->complex;
+ return np;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/qbe/code.c
@@ -1,0 +1,567 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+#define ADDR_LEN (INTIDENTSIZ+64)
+
+static void binary(void), unary(void), store(void), jmp(void), ret(void),
+ branch(void), call(void), ecall(void), param(void),
+ asalloc(void), form2local(void), ldir(void), vastart(void),
+ vaarg(void);
+
+static struct opdata {
+ void (*fun)(void);
+ char *txt;
+ char letter;
+} optbl [] = {
+ [ASLDSB] = {.fun = unary, .txt = "loadsb", .letter = 'w'},
+ [ASLDUB] = {.fun = unary, .txt = "loadub", .letter = 'w'},
+ [ASLDSH] = {.fun = unary, .txt = "loadsh", .letter = 'w'},
+ [ASLDUH] = {.fun = unary, .txt = "loaduh", .letter = 'w'},
+ [ASLDSW] = {.fun = unary, .txt = "loadsw", .letter = 'w'},
+ [ASLDUW] = {.fun = unary, .txt = "loaduw", .letter = 'w'},
+ [ASLDL] = {.fun = unary, .txt = "loadl", .letter = 'l'},
+ [ASLDS] = {.fun = unary, .txt = "loads", .letter = 's'},
+ [ASLDD] = {.fun = unary, .txt = "loadd", .letter = 'd'},
+
+ [ASCOPYB] = {.fun = unary, .txt = "copy", .letter = 'b'},
+ [ASCOPYH] = {.fun = unary, .txt = "copy", .letter = 'h'},
+ [ASCOPYW] = {.fun = unary, .txt = "copy", .letter = 'w'},
+ [ASCOPYL] = {.fun = unary, .txt = "copy", .letter = 'l'},
+ [ASCOPYS] = {.fun = unary, .txt = "copy", .letter = 's'},
+ [ASCOPYD] = {.fun = unary, .txt = "copy", .letter = 'd'},
+
+ [ASSTB] = {.fun = store, .txt = "store", .letter = 'b'},
+ [ASSTH] = {.fun = store, .txt = "store", .letter = 'h'},
+ [ASSTW] = {.fun = store, .txt = "store", .letter = 'w'},
+ [ASSTL] = {.fun = store, .txt = "store", .letter = 'l'},
+ [ASSTM] = {.fun = ldir},
+ [ASSTS] = {.fun = store, .txt = "store", .letter = 's'},
+ [ASSTD] = {.fun = store, .txt = "store", .letter = 'd'},
+
+ [ASADDW] = {.fun = binary, .txt = "add", .letter = 'w'},
+ [ASSUBW] = {.fun = binary, .txt = "sub", .letter = 'w'},
+ [ASMULW] = {.fun = binary, .txt = "mul", .letter = 'w'},
+ [ASMODW] = {.fun = binary, .txt = "rem", .letter = 'w'},
+ [ASUMODW] = {.fun = binary, .txt = "urem", .letter = 'w'},
+ [ASDIVW] = {.fun = binary, .txt = "div", .letter = 'w'},
+ [ASUDIVW] = {.fun = binary, .txt = "udiv", .letter = 'w'},
+ [ASSHLW] = {.fun = binary, .txt = "shl", .letter = 'w'},
+ [ASSHRW] = {.fun = binary, .txt = "sar", .letter = 'w'},
+ [ASUSHRW] = {.fun = binary, .txt = "shr", .letter = 'w'},
+ [ASLTW] = {.fun = binary, .txt = "csltw", .letter = 'w'},
+ [ASULTW] = {.fun = binary, .txt = "cultw", .letter = 'w'},
+ [ASGTW] = {.fun = binary, .txt = "csgtw", .letter = 'w'},
+ [ASUGTW] = {.fun = binary, .txt = "cugtw", .letter = 'w'},
+ [ASLEW] = {.fun = binary, .txt = "cslew", .letter = 'w'},
+ [ASULEW] = {.fun = binary, .txt = "culew", .letter = 'w'},
+ [ASGEW] = {.fun = binary, .txt = "csgew", .letter = 'w'},
+ [ASUGEW] = {.fun = binary, .txt = "cugew", .letter = 'w'},
+ [ASEQW] = {.fun = binary, .txt = "ceqw", .letter = 'w'},
+ [ASNEW] = {.fun = binary, .txt = "cnew", .letter = 'w'},
+ [ASBANDW] = {.fun = binary, .txt = "and", .letter = 'w'},
+ [ASBORW] = {.fun = binary, .txt = "or", .letter = 'w'},
+ [ASBXORW] = {.fun = binary, .txt = "xor", .letter = 'w'},
+
+ [ASADDL] = {.fun = binary, .txt = "add", .letter = 'l'},
+ [ASSUBL] = {.fun = binary, .txt = "sub", .letter = 'l'},
+ [ASMULL] = {.fun = binary, .txt = "mul", .letter = 'l'},
+ [ASMODL] = {.fun = binary, .txt = "rem", .letter = 'l'},
+ [ASUMODL] = {.fun = binary, .txt = "urem", .letter = 'l'},
+ [ASDIVL] = {.fun = binary, .txt = "div", .letter = 'l'},
+ [ASUDIVL] = {.fun = binary, .txt = "udiv", .letter = 'l'},
+ [ASSHLL] = {.fun = binary, .txt = "shl", .letter = 'l'},
+ [ASSHRL] = {.fun = binary, .txt = "sar", .letter = 'l'},
+ [ASUSHRL] = {.fun = binary, .txt = "shr", .letter = 'l'},
+ [ASLTL] = {.fun = binary, .txt = "csltl", .letter = 'w'},
+ [ASULTL] = {.fun = binary, .txt = "cultl", .letter = 'w'},
+ [ASGTL] = {.fun = binary, .txt = "csgtl", .letter = 'w'},
+ [ASUGTL] = {.fun = binary, .txt = "cugtl", .letter = 'w'},
+ [ASLEL] = {.fun = binary, .txt = "cslel", .letter = 'w'},
+ [ASULEL] = {.fun = binary, .txt = "culel", .letter = 'w'},
+ [ASGEL] = {.fun = binary, .txt = "csgel", .letter = 'w'},
+ [ASUGEL] = {.fun = binary, .txt = "cugel", .letter = 'w'},
+ [ASEQL] = {.fun = binary, .txt = "ceql", .letter = 'w'},
+ [ASNEL] = {.fun = binary, .txt = "cnel", .letter = 'w'},
+ [ASBANDL] = {.fun = binary, .txt = "and", .letter = 'l'},
+ [ASBORL] = {.fun = binary, .txt = "or", .letter = 'l'},
+ [ASBXORL] = {.fun = binary, .txt = "xor", .letter = 'l'},
+
+ [ASADDS] = {.fun = binary, .txt = "add", .letter = 's'},
+ [ASSUBS] = {.fun = binary, .txt = "sub", .letter = 's'},
+ [ASMULS] = {.fun = binary, .txt = "mul", .letter = 's'},
+ [ASDIVS] = {.fun = binary, .txt = "div", .letter = 's'},
+ [ASLTS] = {.fun = binary, .txt = "clts", .letter = 'w'},
+ [ASGTS] = {.fun = binary, .txt = "cgts", .letter = 'w'},
+ [ASLES] = {.fun = binary, .txt = "cles", .letter = 'w'},
+ [ASGES] = {.fun = binary, .txt = "cges", .letter = 'w'},
+ [ASEQS] = {.fun = binary, .txt = "ceqs", .letter = 'w'},
+ [ASNES] = {.fun = binary, .txt = "cnes", .letter = 'w'},
+
+ [ASADDD] = {.fun = binary, .txt = "add", .letter = 'd'},
+ [ASSUBD] = {.fun = binary, .txt = "sub", .letter = 'd'},
+ [ASMULD] = {.fun = binary, .txt = "mul", .letter = 'd'},
+ [ASDIVD] = {.fun = binary, .txt = "div", .letter = 'd'},
+ [ASLTD] = {.fun = binary, .txt = "cltd", .letter = 'w'},
+ [ASGTD] = {.fun = binary, .txt = "cgtd", .letter = 'w'},
+ [ASLED] = {.fun = binary, .txt = "cled", .letter = 'w'},
+ [ASGED] = {.fun = binary, .txt = "cged", .letter = 'w'},
+ [ASEQD] = {.fun = binary, .txt = "ceqd", .letter = 'w'},
+ [ASNED] = {.fun = binary, .txt = "cned", .letter = 'w'},
+
+ [ASEXTBW] = {.fun = unary, .txt = "extsb", .letter = 'w'},
+ [ASUEXTBW]= {.fun = unary, .txt = "extub", .letter = 'w'},
+ [ASEXTBL] = {.fun = unary, .txt = "extsb", .letter = 'l'},
+ [ASUEXTBL]= {.fun = unary, .txt = "extub", .letter = 'l'},
+ [ASEXTHW] = {.fun = unary, .txt = "extsh", .letter = 'w'},
+ [ASUEXTHW]= {.fun = unary, .txt = "extuh", .letter = 'w'},
+ [ASEXTWL] = {.fun = unary, .txt = "extsw", .letter = 'l'},
+ [ASUEXTWL]= {.fun = unary, .txt = "extuw", .letter = 'l'},
+
+ [ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'},
+ [ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'},
+ [ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'},
+ [ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'},
+
+ [ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'},
+ [ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'},
+ [ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'},
+ [ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'},
+
+ [ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'},
+ [ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'},
+
+ [ASBRANCH] = {.fun = branch},
+ [ASJMP] = {.fun = jmp},
+ [ASRET] = {.fun = ret},
+ [ASCALL] = {.fun = call},
+ [ASCALLE] = {.fun = ecall, .txt = ")"},
+ [ASCALLEX] = {.fun = ecall, .txt = ", ...)"},
+ [ASPAR] = {.fun = param, .txt = "%s %s, "},
+ [ASPARE] = {.fun = param, .txt = "%s %s"},
+ [ASALLOC] = {.fun = asalloc},
+ [ASFORM] = {.fun = form2local},
+
+ [ASVSTAR] = {.fun = vastart},
+ [ASVARG] = {.fun = vaarg},
+};
+
+static char buff[ADDR_LEN];
+/*
+ * : is for user-defined Aggregate Types
+ * $ is for globals (represented by a pointer)
+ * % is for function-scope temporaries
+ * @ is for block labels
+ */
+static char
+sigil(Symbol *sym)
+{
+ switch (sym->kind) {
+ case SEXTRN:
+ case SGLOB:
+ case SPRIV:
+ case SLOCAL:
+ return '$';
+ case SAUTO:
+ case STMP:
+ return '%';
+ case SLABEL:
+ return '@';
+ default:
+ abort();
+ }
+}
+
+static char *
+symname(Symbol *sym)
+{
+ char c = sigil(sym);
+
+ if (sym->name) {
+ switch (sym->kind) {
+ case SEXTRN:
+ case SGLOB:
+ sprintf(buff, "%c%s", c, sym->name);
+ return buff;
+ case SLOCAL:
+ case SPRIV:
+ case SAUTO:
+ sprintf(buff, "%c%s.%u", c, sym->name, sym->id);
+ return buff;
+ default:
+ abort();
+ }
+ }
+ sprintf(buff, "%c.%u", c, sym->numid);
+
+ return buff;
+}
+
+static void
+emitconst(Node *np)
+{
+ switch (np->type.size) {
+ case 1:
+ printf("%d", (int) np->u.i & 0xFF);
+ break;
+ case 2:
+ printf("%d", (int) np->u.i & 0xFFFF);
+ break;
+ case 4:
+ printf("%ld", (long) np->u.i & 0xFFFFFFFF);
+ break;
+ case 8:
+ printf("%lld", (long long) np->u.i);
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+emittree(Node *np)
+{
+ if (!np)
+ return;
+
+ switch (np->op) {
+ case OSTRING:
+ printf("\"%s\"", np->u.s);
+ free(np->u.s);
+ np->u.s = NULL;
+ break;
+ case OCONST:
+ emitconst(np);
+ break;
+ case OADDR:
+ emittree(np->left);
+ break;
+ case OMEM:
+ fputs(symname(np->u.sym), stdout);
+ break;
+ default:
+ emittree(np->left);
+ printf(" %c ", np->op);
+ emittree(np->right);
+ break;
+ }
+}
+
+static char *
+size2asm(Type *tp)
+{
+ if (tp->flags & STRF) {
+ return "b";
+ } else if (tp->flags & INTF) {
+ switch (tp->size) {
+ case 1:
+ return "b";
+ case 2:
+ return "h";
+ case 4:
+ return "w";
+ case 8:
+ return "l";
+ }
+ } else if (tp->flags & FLOATF) {
+ if (tp->size == 4)
+ return "s";
+ else if (tp->size == 8)
+ return "d";
+ }
+ abort();
+}
+
+void
+defglobal(Symbol *sym)
+{
+ if (sym->kind == SEXTRN)
+ return;
+ if (sym->kind == SGLOB)
+ fputs("export ", stdout);
+ printf("data %s = {\n", symname(sym));
+ if (sym->type.flags & INITF)
+ return;
+ printf("\tz\t%lu\n}\n", sym->type.size);
+}
+
+void
+defpar(Symbol *sym)
+{
+ sym->type.flags |= PARF;
+}
+
+void
+defvar(Symbol *sym)
+{
+ if (sym->kind == SREG)
+ sym->kind = SAUTO;
+}
+
+void
+data(Node *np)
+{
+ printf("\t%s\t", size2asm(&np->type));
+ emittree(np);
+ putchar(',');
+ putchar('\n');
+}
+
+static char *
+size2stack(Type *tp)
+{
+ if (tp->flags & INTF) {
+ switch (tp->size) {
+ case 1:
+ case 2:
+ case 4:
+ return "w";
+ case 8:
+ return "l";
+ }
+ } else if (tp->flags & FLOATF) {
+ if (tp->size == 4)
+ return "s";
+ else if (tp->size == 8)
+ return "d";
+ } else if (tp->size == 0) {
+ return "w";
+ }
+ abort();
+}
+
+void
+writeout(void)
+{
+ Symbol *p;
+ Type *tp;
+ char *sep, *name;
+ int haslabel = 0;
+
+ if (!curfun)
+ return;
+ if (curfun->kind == SGLOB)
+ fputs("export ", stdout);
+ printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun));
+
+ /* declare formal parameters */
+ for (sep = "", p = locals; p; p = p->next, sep = ",") {
+ if ((p->type.flags & PARF) == 0)
+ break;
+ printf("%s%s %s.val", sep, size2stack(&p->type), symname(p));
+ }
+ printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : "");
+
+ /* emit assembler instructions */
+ for (pc = prog; pc; pc = pc->next) {
+ if (pc->label) {
+ haslabel = 1;
+ printf("%s\n", symname(pc->label));
+ }
+ if (!pc->op)
+ continue;
+ if (pc->flags&BBENTRY && !haslabel)
+ printf("%s\n", symname(newlabel()));
+ (*optbl[pc->op].fun)();
+ if (!pc->label)
+ haslabel = 0;
+ }
+
+ puts("}");
+}
+
+static char *
+addr2txt(Addr *a)
+{
+ switch (a->kind) {
+ case SCONST:
+ sprintf(buff, "%llu", (unsigned long long) a->u.i);
+ return buff;
+ case SAUTO:
+ case SLABEL:
+ case STMP:
+ case SGLOB:
+ case SEXTRN:
+ case SPRIV:
+ case SLOCAL:
+ return symname(a->u.sym);
+ default:
+ abort();
+ }
+}
+
+static void
+binary(void)
+{
+ struct opdata *p = &optbl[pc->op];
+ char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from1, addr2txt(&pc->from1));
+ strcpy(from2, addr2txt(&pc->from2));
+ printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2);
+}
+
+static void
+ldir(void)
+{
+ struct opdata *p = &optbl[pc->op];
+ char to[ADDR_LEN], from[ADDR_LEN];
+ /* TODO: what type do we use for the size? */
+
+ /* TODO: it is pending */
+}
+
+static void
+store(void)
+{
+ struct opdata *p = &optbl[pc->op];
+ char to[ADDR_LEN], from[ADDR_LEN];
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from, addr2txt(&pc->from1));
+ printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to);
+}
+
+static void
+unary(void)
+{
+ struct opdata *p = &optbl[pc->op];
+ char to[ADDR_LEN], from[ADDR_LEN];
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from, addr2txt(&pc->from1));
+ printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from);
+}
+
+static void
+call(void)
+{
+ struct opdata *p = &optbl[pc->op];
+ char to[ADDR_LEN], from[ADDR_LEN];
+ Symbol *sym = pc->to.u.sym;
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from, addr2txt(&pc->from1));
+ printf("\t%s =%s\tcall\t%s(",
+ to, size2stack(&sym->type), from);
+}
+
+static void
+param(void)
+{
+ Symbol *sym = pc->from2.u.sym;
+
+ printf(optbl[pc->op].txt,
+ size2stack(&sym->type), addr2txt(&pc->from1));
+}
+
+static void
+ecall(void)
+{
+ struct opdata *p = &optbl[pc->op];
+
+ puts(p->txt);
+}
+
+static void
+ret(void)
+{
+ if (pc->from1.kind == SNONE)
+ puts("\t\tret");
+ else
+ printf("\t\tret\t%s\n", addr2txt(&pc->from1));
+}
+
+static void
+jmp(void)
+{
+ printf("\t\tjmp\t%s\n", addr2txt(&pc->from1));
+}
+
+static void
+branch(void)
+{
+ char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from1, addr2txt(&pc->from1));
+ strcpy(from2, addr2txt(&pc->from2));
+ printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2);
+}
+
+static void
+vastart(void)
+{
+ printf("\t\tvastart %s\n", addr2txt(&pc->from1));
+}
+
+static void
+vaarg(void)
+{
+ Symbol *sym = pc->to.u.sym;
+ Type *tp = &sym->type;
+ char to[ADDR_LEN], from[ADDR_LEN];
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from, addr2txt(&pc->from1));
+ printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from);
+}
+
+static void
+asalloc(void)
+{
+ Symbol *sym = pc->to.u.sym;
+ Type *tp = &sym->type;
+ extern Type ptrtype;
+
+ printf("\t%s =%s\talloc%lu\t%lu\n",
+ symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size);
+}
+
+static void
+form2local(void)
+{
+ Symbol *sym = pc->to.u.sym;
+ Type *tp = &sym->type;
+ char *name = symname(sym);
+
+ printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name);
+}
+
+void
+endinit(void)
+{
+ puts("}");
+}
+
+void
+getbblocks(void)
+{
+ Inst *i;
+
+ if (!prog)
+ return;
+
+ prog->flags |= BBENTRY;
+ for (pc = prog; pc; pc = pc->next) {
+ switch (pc->op) {
+ case ASBRANCH:
+ i = pc->from2.u.sym->u.inst;
+ i->flags |= BBENTRY;
+ case ASJMP:
+ i = pc->from1.u.sym->u.inst;
+ i->flags |= BBENTRY;
+ case ASRET:
+ if (pc->next)
+ pc->next->flags |= BBENTRY;
+ break;
+ }
+ }
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/qbe/optm.c
@@ -1,0 +1,56 @@
+#include <stddef.h>
+
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+Node *
+optm_dep(Node *np)
+{
+ int op = np->op;
+ Node *p, *dst, *next = np->next;
+ Symbol *sym, *osym;
+
+ switch (op) {
+ case OEFUN:
+ /*
+ * In QBE we need at the end of a basic block
+ * a jump, so we have to ensure that the last
+ * statement of the function is a ret, a jmp
+ * or a branch. In the same way, QBE does
+ * not accept labels at the end of a function
+ * (ONOP is used for labels) so we have to add
+ * a ret there, and in the case of branches
+ * we need a label for the next statement
+ */
+ op = (np->prev) ? np->prev->op : 0;
+ if (!op || op == ONOP || op == OBRANCH || (op != ORET && op != OJMP))
+ addstmt(node(ORET), KEEPCUR);
+ break;
+ case OBRANCH:
+ if (!next->label) {
+ sym = getsym(TMPSYM);
+ sym->kind = SLABEL;
+ next->label = sym;
+ }
+ case OJMP:
+ for (;;) {
+ dst = np->u.sym->u.stmt;
+ if (dst->op != OJMP)
+ break;
+ np->u.sym = dst->u.sym;
+ }
+ for (p = np->next; p; p = p->next) {
+ if (p == dst)
+ return NULL;
+ if (p->op == ONOP ||
+ p->op == OBLOOP ||
+ p->op == OELOOP) {
+ continue;
+ }
+ break;
+ }
+ break;
+ }
+ return np;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/qbe_amd64-sysv/target.mk
@@ -1,0 +1,8 @@
+OBJ-qbe_amd64-sysv = $(OBJS) \
+ target/qbe/cgen.o \
+ target/qbe/optm.o \
+ target/qbe/code.o \
+ target/amd64-sysv/types.o
+
+$(LIBEXEC)/cc2-qbe_amd64-sysv: $(OBJ-qbe_amd64-sysv)
+ $(CC) $(SCC_LDFLAGS) $(OBJ-qbe_amd64-sysv) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc2/target/qbe_arm64-sysv/target.mk
@@ -1,0 +1,5 @@
+OBJ-qbe_arm64-sysv = $(OBJS) \
+ target/qbe/cgen.o \
+ target/qbe/optm.o \
+ target/qbe/code.o \
+ target/arm64-sysv/types.o \
--- /dev/null
+++ b/src/cmd/cc/cc2/target/z80-scc/arch.h
@@ -1,0 +1,5 @@
+enum asmop {
+ ASJMP = 0,
+ ASRET,
+ ASBRANCH,
+};
--- /dev/null
+++ b/src/cmd/cc/cc2/target/z80-scc/cgen.c
@@ -1,0 +1,159 @@
+#include <stdlib.h>
+
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+static void
+swtch(Node *idx)
+{
+}
+
+static Node *
+rhs(Node *np, Node *ret)
+{
+}
+
+static Node *
+field(Node *np, Node *ret, int islhs)
+{
+}
+
+static Node *
+lhs(Node *np, Node *new)
+{
+ switch (np->op) {
+ case OMEM:
+ case OAUTO:
+ *new = *np;
+ return new;
+ case OPTR:
+ return rhs(np->left, new);
+ case OFIELD:
+ return field(np, new, 1);
+ default:
+ abort();
+ }
+}
+
+static void
+bool(Node *np, Symbol *true, Symbol *false)
+{
+ Node *l = np->left, *r = np->right;
+ Node ret, ifyes, ifno;
+ Symbol *label;
+
+ switch (np->op) {
+ case ONEG:
+ bool(l, false, true);
+ break;
+ case OAND:
+ label = newlabel();
+ bool(l, label, false);
+ setlabel(label);
+ bool(r, true, false);
+ break;
+ case OOR:
+ label = newlabel();
+ bool(l, true, label);
+ setlabel(label);
+ bool(r, true, false);
+ break;
+ default:
+ label2node(&ifyes, true);
+ label2node(&ifno, false);
+ code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno);
+ break;
+ }
+}
+
+Node *
+cgen(Node *np)
+{
+ Node aux, *p, *next;
+
+ setlabel(np->label);
+ switch (np->op) {
+ case OJMP:
+ label2node(&aux, np->u.sym);
+ code(ASJMP, NULL, &aux, NULL);
+ break;
+ case OBRANCH:
+ next = np->next;
+ if (!next->label)
+ next->label = newlabel();
+ bool(np->left, np->u.sym, next->label);
+ break;
+ case ORET:
+ p = np->left;
+ if (p)
+ p = rhs(np->left, &aux);
+ code(ASRET, NULL, p, NULL);
+ break;
+ case OBSWITCH:
+ swtch(rhs(np->left, &aux));
+ break;
+ default:
+ rhs(np, &aux);
+ break;
+ }
+ return NULL;
+}
+
+/*
+ * This is strongly influenced by
+ * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
+ * calculate addresability as follows
+ * AUTO => 11 value+fp
+ * REG => 13 reg
+ * STATIC => 12 (value)
+ * CONST => 20 $value
+ */
+Node *
+sethi(Node *np)
+{
+ Node *lp, *rp;
+
+ if (!np)
+ return np;
+
+ np->complex = 0;
+ np->address = 0;
+ lp = np->left;
+ rp = np->right;
+ switch (np->op) {
+ case OAUTO:
+ np->address = 11;
+ break;
+ case OREG:
+ np->address = 13;
+ break;
+ case OMEM:
+ np->address = 12;
+ break;
+ case OCONST:
+ np->address = 20;
+ break;
+ default:
+ sethi(lp);
+ sethi(rp);
+ break;
+ }
+
+ if (np->address > 10)
+ return np;
+ if (lp)
+ np->complex = lp->complex;
+ if (rp) {
+ int d = np->complex - rp->complex;
+
+ if (d == 0)
+ ++np->complex;
+ else if (d < 0)
+ np->complex = rp->complex;
+ }
+ if (np->complex == 0)
+ ++np->complex;
+ return np;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/z80-scc/code.c
@@ -1,0 +1,227 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+enum segment {
+ CODESEG,
+ DATASEG,
+ BSSSEG,
+ NOSEG
+};
+
+static int curseg = NOSEG;
+static unsigned long offpar, offvar;
+
+static void
+segment(int seg)
+{
+ static char *txt[] = {
+ [CODESEG] = "\tCSEG\n",
+ [DATASEG] = "\tDSEG\n",
+ [BSSSEG] = "\tASEG\n",
+ };
+
+ if (seg == curseg)
+ return;
+ fputs(txt[seg], stdout);
+ curseg = seg;
+}
+
+static char *
+symname(Symbol *sym)
+{
+ static char name[INTIDENTSIZ+1];
+
+ if (sym->name) {
+ switch (sym->kind) {
+ case SGLOB:
+ case SEXTRN:
+ snprintf(name, sizeof(name), "_%s", sym->name);
+ return name;
+ case SPRIV:
+ return sym->name;
+ }
+ }
+
+ sprintf(name, ".%d", sym->numid);
+
+ return name;
+}
+
+static void
+label(Symbol *sym)
+{
+ int seg;
+ char *name = symname(sym);
+
+ if (sym->type.flags & FUNF)
+ seg = CODESEG;
+ else if (sym->type.flags & INITF)
+ seg = DATASEG;
+ else
+ seg = BSSSEG;
+ segment(seg);
+
+ switch (sym->kind) {
+ case SEXTRN:
+ printf("\tEXTRN\t%s\n", name);
+ return;
+ case SGLOB:
+ printf("\tPUBLIC\t%s\n", name);
+ break;
+ }
+
+ printf("%s:\n", name);
+}
+
+static void
+emitconst(Node *np)
+{
+ switch (np->type.size) {
+ case 1:
+ printf("%d", (int) np->u.i & 0xFF);
+ break;
+ case 2:
+ printf("%d", (int) np->u.i & 0xFFFF);
+ break;
+ case 4:
+ printf("%ld", (long) np->u.i & 0xFFFFFFFF);
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+emittree(Node *np)
+{
+ if (!np)
+ return;
+
+ switch (np->op) {
+ case OSTRING:
+ printf("\"%s\"", np->u.s);
+ free(np->u.s);
+ np->u.s = NULL;
+ break;
+ case OCONST:
+ emitconst(np);
+ break;
+ case OADDR:
+ emittree(np->left);
+ break;
+ case OMEM:
+ fputs(symname(np->u.sym), stdout);
+ break;
+ default:
+ emittree(np->left);
+ printf(" %c ", np->op);
+ emittree(np->right);
+ break;
+ }
+}
+
+static void
+size2asm(Type *tp)
+{
+ char *s;
+
+ /*
+ * In z80 we can ignore the alignment
+ */
+ if (tp->flags & STRF) {
+ s = "\tDB\t";
+ } else {
+ switch (tp->size) {
+ case 1:
+ s = "\tDB\t";
+ break;
+ case 2:
+ s = "\tDW\t";
+ break;
+ case 4:
+ s = "\tDD\t";
+ break;
+ default:
+ s = "\tDS\t%lu,";
+ break;
+ }
+ }
+ printf(s, tp->size);
+}
+
+void
+newfun()
+{
+ offpar = offvar = 0;
+}
+
+void
+defpar(Symbol *sym)
+{
+ unsigned long align, size;
+
+ if (sym->kind != SREG && sym->kind != SAUTO)
+ return;
+ align = sym->type.align;
+ size = sym->type.size;
+
+ offpar -= align-1 & ~align;
+ sym->u.off = offpar;
+ offpar -= size;
+ sym->kind = SAUTO;
+}
+
+void
+defvar(Symbol *sym)
+{
+ unsigned long align, size;
+
+ if (sym->kind != SREG && sym->kind != SAUTO)
+ return;
+ align = sym->type.align;
+ size = sym->type.size;
+
+ offvar += align-1 & ~align;
+ sym->u.off = offvar;
+ offvar += size;
+ sym->kind = SAUTO;
+}
+
+void
+defglobal(Symbol *sym)
+{
+ label(sym);
+ if (sym->kind == SEXTRN || (sym->type.flags & INITF))
+ return;
+ size2asm(&sym->type);
+ puts("0");
+}
+
+void
+data(Node *np)
+{
+ size2asm(&np->type);
+ emittree(np);
+ putchar('\n');
+}
+
+void
+writeout(void)
+{
+}
+
+void
+endinit(void)
+{
+}
+
+void
+getbblocks(void)
+{
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/z80-scc/optm.c
@@ -1,0 +1,9 @@
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+Node *
+optm_dep(Node *np)
+{
+ return np;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/z80-scc/target.mk
@@ -1,0 +1,8 @@
+OBJ-z80-scc = $(OBJS) \
+ target/z80-scc/cgen.o \
+ target/z80-scc/optm.o \
+ target/z80-scc/code.o \
+ target/z80-scc/types.o \
+
+$(LIBEXEC)/cc2-z80-scc: $(OBJ-z80-scc)
+ $(CC) $(SCC_LDFLAGS) $(OBJ-z80-scc) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc2/target/z80-scc/types.c
@@ -1,0 +1,93 @@
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+
+Type int8type = {
+ .flags = SIGNF | INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type int16type = {
+ .flags = SIGNF | INTF,
+ .size = 2,
+ .align = 1
+};
+
+Type int32type = {
+ .flags = SIGNF | INTF,
+ .size = 4,
+ .align = 1
+};
+
+Type int64type = {
+ .flags = SIGNF | INTF,
+ .size = 8,
+ .align = 1
+};
+
+Type uint8type = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type uint16type = {
+ .flags = INTF,
+ .size = 2,
+ .align = 1
+};
+
+Type uint32type = {
+ .flags = INTF,
+ .size = 4,
+ .align = 1
+};
+
+Type uint64type = {
+ .flags = INTF,
+ .size = 8,
+ .align = 1
+};
+
+Type ptrtype = {
+ .flags = INTF,
+ .size = 2,
+ .align = 1
+};
+
+Type booltype = {
+ .flags = INTF,
+ .size = 1,
+ .align = 1
+};
+
+Type float32type = {
+ .flags = FLOATF,
+ .size = 4,
+ .align = 1
+};
+
+Type float64type = {
+ .flags = FLOATF,
+ .size = 4,
+ .align = 1
+};
+
+Type float80type = {
+ .flags = FLOATF,
+ .size = 4,
+ .align = 1
+};
+
+Type voidtype = {
+ .size = 0,
+ .align = 0
+};
+
+/* this types is not going to be used in this arch */
+Type arg_type = {
+ .size = 0,
+ .align = 0
+};
--- /dev/null
+++ b/src/cmd/cc/posix/.gitignore
@@ -1,0 +1,1 @@
+config.h
--- /dev/null
+++ b/src/cmd/cc/posix/Makefile
@@ -1,0 +1,38 @@
+.POSIX:
+
+PROJECTDIR = ../../../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+# SYSLST is a list of backend-arch-abi-sys. First
+# element of the list becomes the default target
+
+SYSLST = amd64-sysv-linux-elf z80-scc-none-none \
+ i386-sysv-linux-elf amd64-sysv-openbsd-elf
+
+STDCFLAGS =
+
+TARGETS = $(BINDIR)/scc $(BINDIR)/scpp
+
+all: $(TARGETS)
+
+$(BINDIR)/scc: scc.o
+ $(CC) $(SCC_LDFLAGS) scc.o -lscc -o $@
+
+$(BINDIR)/scpp: cpp.sh
+ trap "rm -f $$$$.sh" 0 2 3;\
+ rm -f $@ ;\
+ sed "s%@PREFIX@%$(PREFIX)%" < cpp.sh > $$$$.sh && \
+ chmod +x $$$$.sh && \
+ mv $$$$.sh $@
+
+config.h:
+ PREFIX=$(PREFIX) mkconf $(SYSLST)
+
+dep: inc-dep
+
+clean:
+ rm -f scc scpp *.o
+ rm -f $(TARGETS)
+ rm -f config.h
+
+include deps.mk
--- /dev/null
+++ b/src/cmd/cc/posix/cpp.sh
@@ -1,0 +1,4 @@
+#!/bin/sh
+
+SCCPREFIX=${SCCPREFIX:-@PREFIX@}
+${SCCPREFIX}/bin/scc -E $@
--- /dev/null
+++ b/src/cmd/cc/posix/deps.mk
@@ -1,0 +1,8 @@
+#deps
+./scc.o: $(INCDIR)/scc/scc/arg.h
+./scc.o: $(INCDIR)/scc/scc/ldflags.h
+./scc.o: $(INCDIR)/scc/scc/scc.h
+./scc.o: $(INCDIR)/scc/scc/syscrts.h
+./scc.o: $(INCDIR)/scc/scc/sysincludes.h
+./scc.o: $(INCDIR)/scc/scc/syslibs.h
+./scc.o: ./config.h
--- /dev/null
+++ b/src/cmd/cc/posix/mkconf
@@ -1,0 +1,16 @@
+#!/bin/sh
+
+set -e
+
+rm -f config.h
+trap "rm -f $$.h" 0 2 3
+
+PREFIX=${PREFIX-$HOME}
+
+echo $@ |
+(IFS='- ' read arch abi sys format r
+echo \#define PREFIX \"$PREFIX\"
+echo \#define ARCH \"$arch\"
+echo \#define SYS \"$sys\"
+echo \#define ABI \"$abi\"
+echo \#define FORMAT \"$format\") > $$.h && mv $$.h config.h
--- /dev/null
+++ b/src/cmd/cc/posix/scc.c
@@ -1,0 +1,620 @@
+#define _POSIX_SOURCE
+#define _XOPEN_SOURCE 500
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include <scc/arg.h>
+#include <scc/scc.h>
+#include <scc/syscrts.h>
+#include <scc/sysincludes.h>
+#include <scc/syslibs.h>
+#include <scc/ldflags.h>
+
+enum {
+ CC1,
+ TEEIR,
+ CC2,
+ TEEQBE,
+ QBE,
+ TEEAS,
+ AS,
+ LD,
+ STRIP,
+ LAST_TOOL,
+};
+
+static struct tool {
+ char cmd[PATH_MAX];
+ char bin[32];
+ char *outfile;
+ struct items args;
+ unsigned nparams;
+ int in, out, init;
+ pid_t pid;
+} tools[] = {
+ [CC1] = { .cmd = "cc1" },
+ [TEEIR] = { .bin = "tee", .cmd = "tee", },
+ [CC2] = { .cmd = "cc2" },
+ [TEEQBE] = { .bin = "tee", .cmd = "tee", },
+ [QBE] = { .bin = "qbe", .cmd = "qbe", },
+ [TEEAS] = { .bin = "tee", .cmd = "tee", },
+ [AS] = { .bin = "as", .cmd = "as", },
+ [LD] = { .bin = "ld", .cmd = "ld", },
+ [STRIP] = { .bin = "strip", .cmd = "strip", },
+};
+
+char *argv0;
+static char *arch, *sys, *abi, *format;
+static char *prefix, *objfile, *outfile;
+static char *tmpdir;
+static size_t tmpdirln;
+static struct items objtmp, objout;
+static int Mflag, Eflag, Sflag, Wflag,
+ cflag, dflag, kflag, sflag, Qflag = 1; /* TODO: Remove Qflag */
+static int devnullfd = -1;
+
+extern int failure;
+
+static void
+terminate(void)
+{
+ unsigned i;
+
+ if (!kflag) {
+ for (i = 0; i < objtmp.n; ++i)
+ unlink(objtmp.s[i]);
+ }
+}
+
+static void
+addarg(int tool, char *arg)
+{
+ struct tool *t = &tools[tool];
+
+ if (t->args.n < 1)
+ t->args.n = 1;
+
+ newitem(&t->args, arg);
+}
+
+static void
+setargv0(int tool, char *arg)
+{
+ struct tool *t = &tools[tool];
+
+ if (t->args.n > 0)
+ t->args.s[0] = arg;
+ else
+ newitem(&t->args, arg);
+}
+
+static int
+qbe(int tool)
+{
+ if (tool != CC2 || !Qflag)
+ return 0;
+ if (!strcmp(arch, "amd64") && !strcmp(abi, "sysv"))
+ return 1;
+ return 0;
+}
+
+static int
+inittool(int tool)
+{
+ struct tool *t = &tools[tool];
+ char *crt, *fmt;
+ int n;
+
+ if (t->init)
+ return tool;
+
+ switch (tool) {
+ case CC1:
+ if (Wflag)
+ addarg(tool, "-w");
+ for (n = 0; sysincludes[n]; ++n) {
+ addarg(tool, "-I");
+ addarg(tool, sysincludes[n]);
+ }
+ case CC2:
+ fmt = (qbe(tool)) ? "%s-qbe_%s-%s" : "%s-%s-%s";
+ n = snprintf(t->bin, sizeof(t->bin), fmt, t->cmd, arch, abi);
+ if (n < 0 || n >= sizeof(t->bin))
+ die("scc: target tool name too long");
+
+ n = snprintf(t->cmd, sizeof(t->cmd),
+ "%s/libexec/scc/%s", prefix, t->bin);
+ if (n < 0 || n >= sizeof(t->cmd))
+ die("scc: target tool path too long");
+ break;
+ case LD:
+ for (n = 0; ldflags[n]; ++n)
+ addarg(tool, ldflags[n]);
+ addarg(tool, "-o");
+ t->outfile = outfile ? outfile : xstrdup("a.out");
+ addarg(tool, t->outfile);
+ for (n = 0; syslibs[n]; ++n) {
+ addarg(tool, "-L");
+ addarg(tool, syslibs[n]);
+ }
+ if (syscrts[0]) {
+ for (n = 0; syscrts[n]; ++n)
+ addarg(tool, syscrts[n]);
+ break;
+ }
+ n = snprintf(NULL, 0,
+ "%s/lib/scc/%s-%s-%s/crt.o",
+ prefix, arch, abi, sys);
+ if (n < 0)
+ die("scc: wrong crt file name");
+ crt = xmalloc(++n);
+ sprintf(crt,
+ "%s/lib/scc/%s-%s-%s/crt.o",
+ prefix, arch, abi, sys);
+ addarg(tool, crt);
+ break;
+ case AS:
+ addarg(tool, "-o");
+ break;
+ default:
+ break;
+ }
+
+ setargv0(tool, t->bin);
+ t->nparams = t->args.n;
+ t->init = 1;
+
+ return tool;
+}
+
+static char *
+outfname(char *path, char *type)
+{
+ char *new, sep, *p;
+ size_t newsz, pathln;
+ int tmpfd, n;
+
+ if (path) {
+ sep = '.';
+ if (p = strrchr(path, '/'))
+ path = p + 1;
+ pathln = strlen(path);
+ if (p = strrchr(path, '.'))
+ pathln -= strlen(p);
+ } else {
+ sep = '/';
+ type = "scc-XXXXXX";
+ path = tmpdir;
+ pathln = tmpdirln;
+ }
+
+ newsz = pathln + 1 + strlen(type) + 1;
+ new = xmalloc(newsz);
+ n = snprintf(new, newsz, "%.*s%c%s", (int)pathln, path, sep, type);
+ if (n < 0 || n >= newsz)
+ die("scc: wrong output filename");
+ if (sep == '/') {
+ if ((tmpfd = mkstemp(new)) < 0)
+ die("scc: could not create output file '%s': %s",
+ new, strerror(errno));
+ close(tmpfd);
+ }
+
+ return new;
+}
+
+static int
+settool(int tool, char *infile, int nexttool)
+{
+ struct tool *t = &tools[tool];
+ unsigned i;
+ int fds[2];
+ static int fdin = -1;
+
+ switch (tool) {
+ case TEEIR:
+ t->outfile = outfname(infile, "ir");
+ addarg(tool, t->outfile);
+ break;
+ case TEEQBE:
+ t->outfile = outfname(infile, "qbe");
+ addarg(tool, t->outfile);
+ break;
+ case TEEAS:
+ t->outfile = outfname(infile, "s");
+ addarg(tool, t->outfile);
+ break;
+ case AS:
+ if (cflag && outfile) {
+ objfile = outfile;
+ } else {
+ objfile = (cflag || kflag) ? infile : NULL;
+ objfile = outfname(objfile, "o");
+ }
+ t->outfile = xstrdup(objfile);
+ addarg(tool, t->outfile);
+ break;
+ case STRIP:
+ if (cflag || kflag) {
+ for (i = 0; i < objout.n; ++i)
+ addarg(tool, xstrdup(objout.s[i]));
+ }
+ if (!cflag && tools[LD].outfile)
+ addarg(tool, tools[LD].outfile);
+ break;
+ default:
+ break;
+ }
+
+ if (fdin > -1) {
+ t->in = fdin;
+ fdin = -1;
+ } else {
+ t->in = -1;
+ if (infile)
+ addarg(tool, xstrdup(infile));
+ }
+
+ if (nexttool < LAST_TOOL) {
+ if (pipe(fds))
+ die("scc: pipe: %s", strerror(errno));
+ t->out = fds[1];
+ fdin = fds[0];
+ } else {
+ t->out = -1;
+ }
+
+ addarg(tool, NULL);
+
+ return tool;
+}
+
+static void
+spawn(int tool)
+{
+ struct tool *t = &tools[tool];
+
+ switch (t->pid = fork()) {
+ case -1:
+ die("scc: %s: %s", t->bin, strerror(errno));
+ case 0:
+ if (t->out > -1)
+ dup2(t->out, 1);
+ if (t->in > -1)
+ dup2(t->in, 0);
+ if (!dflag && tool != CC1 && tool != LD)
+ dup2(devnullfd, 2);
+ execvp(t->cmd, t->args.s);
+ if (dflag) {
+ fprintf(stderr,
+ "scc: execvp %s: %s\n",
+ t->cmd,
+ strerror(errno));
+ }
+ abort();
+ default:
+ if (t->in > -1)
+ close(t->in);
+ if (t->out > -1)
+ close(t->out);
+ break;
+ }
+}
+
+static int
+toolfor(char *file)
+{
+ char *dot = strrchr(file, '.');
+
+ if (dot) {
+ if (!strcmp(dot, ".c"))
+ return CC1;
+ if (!strcmp(dot, ".ir"))
+ return CC2;
+ if (!strcmp(dot, ".qbe"))
+ return QBE;
+ if (!strcmp(dot, ".s"))
+ return AS;
+ if (!strcmp(dot, ".o"))
+ return LD;
+ if (!strcmp(dot, ".a"))
+ return LD;
+ } else if (!strcmp(file, "-")) {
+ return CC1;
+ }
+
+ die("scc: do not recognize filetype of %s", file);
+}
+
+static int
+valid(int tool, struct tool *t)
+{
+ int st;
+
+ if (waitpid(t->pid, &st, 0) == -1 || WIFSIGNALED(st))
+ goto internal;
+ if (WIFEXITED(st) && WEXITSTATUS(st) == 0)
+ return 1;
+ if (!failure && (tool == CC1 || tool == LD))
+ goto fail;
+
+internal:
+ fprintf(stderr, "scc:%s: internal error\n", t->bin);
+fail:
+ failure = 1;
+ return 0;
+}
+
+static int
+validatetools(void)
+{
+ struct tool *t;
+ unsigned i;
+ int tool, st, failed = LAST_TOOL;
+
+ for (tool = 0; tool < LAST_TOOL; ++tool) {
+ t = &tools[tool];
+ if (!t->pid)
+ continue;
+ if (!valid(tool, t))
+ failed = tool;
+ if (tool >= failed && t->outfile)
+ unlink(t->outfile);
+ for (i = t->nparams; i < t->args.n; ++i)
+ free(t->args.s[i]);
+ t->args.n = t->nparams;
+ t->pid = 0;
+ }
+ if (failed < LAST_TOOL) {
+ unlink(objfile);
+ free(objfile);
+ objfile = NULL;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+buildfile(char *file, int tool)
+{
+ int nexttool;
+
+ for (; tool < LAST_TOOL; tool = nexttool) {
+ switch (tool) {
+ case CC1:
+ if (Eflag || Mflag)
+ nexttool = LAST_TOOL;
+ else
+ nexttool = kflag ? TEEIR : CC2;
+ break;
+ case TEEIR:
+ nexttool = CC2;
+ break;
+ case CC2:
+ if (Qflag)
+ nexttool = kflag ? TEEQBE : QBE;
+ else
+ nexttool = (Sflag || kflag) ? TEEAS : AS;
+ break;
+ case TEEQBE:
+ nexttool = QBE;
+ break;
+ case QBE:
+ nexttool = (Sflag || kflag) ? TEEAS : AS;
+ break;
+ case TEEAS:
+ nexttool = Sflag ? LAST_TOOL : AS;
+ break;
+ case AS:
+ nexttool = LAST_TOOL;
+ break;
+ default:
+ nexttool = LAST_TOOL;
+ continue;
+ }
+
+ spawn(settool(inittool(tool), file, nexttool));
+ }
+
+ return validatetools();
+}
+
+static void
+build(struct items *chain, int link)
+{
+ int i, tool;
+
+ if (link)
+ inittool(LD);
+
+ for (i = 0; i < chain->n; ++i) {
+ if (!strcmp(chain->s[i], "-l")) {
+ if (link) {
+ addarg(LD, xstrdup(chain->s[i++]));
+ addarg(LD, xstrdup(chain->s[i]));
+ } else {
+ ++i;
+ }
+ continue;
+ }
+ tool = toolfor(chain->s[i]);
+ if (tool == LD) {
+ if (link)
+ addarg(LD, xstrdup(chain->s[i]));
+ continue;
+ }
+ if (buildfile(chain->s[i], tool)) {
+ if (link)
+ addarg(LD, xstrdup(objfile));
+ newitem((!link || kflag) ? &objout : &objtmp, objfile);
+ }
+ }
+}
+
+static void
+usage(void)
+{
+ fputs("usage: scc [-D def[=val]]... [-U def]... [-I dir]... "
+ "[-L dir]... [-l dir]...\n"
+ " [-dgksw] [-m arch] [-M|-E|-S] [-o outfile] file...\n"
+ " scc [-D def[=val]]... [-U def]... [-I dir]... "
+ "[-L dir]... [-l dir]...\n"
+ " [-dgksw] [-m arch] [-M|-E|-S] -c file...\n"
+ " scc [-D def[=val]]... [-U def]... [-I dir]... "
+ "[-L dir]... [-l dir]...\n"
+ " [-dgksw] [-m arch] -c -o outfile file\n", stderr);
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct items linkchain = { .n = 0, };
+ int link;
+
+ atexit(terminate);
+
+ if (!(arch = getenv("ARCH")))
+ arch = ARCH;
+ if (!(sys = getenv("SYS")))
+ sys = SYS;
+ if (!(abi = getenv("ABI")))
+ abi = ABI;
+ if (!(format = getenv("FORMAT")))
+ format = FORMAT;
+ if (!(prefix = getenv("SCCPREFIX")))
+ prefix = PREFIX;
+
+ ARGBEGIN {
+ case 'D':
+ addarg(CC1, "-D");
+ addarg(CC1, EARGF(usage()));
+ break;
+ case 'M':
+ Mflag = 1;
+ addarg(CC1, "-M");
+ break;
+ case 'E':
+ Eflag = 1;
+ addarg(CC1, "-E");
+ break;
+ case 'I':
+ addarg(CC1, "-I");
+ addarg(CC1, EARGF(usage()));
+ break;
+ case 'L':
+ addarg(LD, "-L");
+ addarg(LD, EARGF(usage()));
+ break;
+ case 'O':
+ EARGF(usage());
+ break;
+ case 'S':
+ Sflag = 1;
+ break;
+ case 'U':
+ addarg(CC1, "-U");
+ addarg(CC1, EARGF(usage()));
+ break;
+ case 'c':
+ cflag = 1;
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'g':
+ addarg(AS, "-g");
+ addarg(LD, "-g");
+ break;
+ case 'k':
+ kflag = 1;
+ break;
+ case 'l':
+ newitem(&linkchain, "-l");
+ newitem(&linkchain, EARGF(usage()));
+ break;
+ case 'm':
+ arch = EARGF(usage());
+ break;
+ case 'o':
+ outfile = xstrdup(EARGF(usage()));
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case 't':
+ sys = EARGF(usage());
+ break;
+ case 'w':
+ Wflag = 0;
+ break;
+ case 'W':
+ Wflag = 1;
+ break;
+ case 'q':
+ Qflag = 0;
+ break;
+ case 'Q':
+ Qflag = 1;
+ break;
+ case '-':
+ fprintf(stderr,
+ "scc: ignored parameter --%s\n", EARGF(usage()));
+ break;
+ default:
+ usage();
+ } ARGOPERAND {
+operand:
+ newitem(&linkchain, ARGOP());
+ } ARGEND
+
+ for (; *argv; --argc, ++argv)
+ goto operand;
+
+ if (Eflag && linkchain.n == 0)
+ newitem(&linkchain, "-");
+
+ if (Eflag && Mflag ||
+ (Eflag || Mflag) && (Sflag || kflag) ||
+ linkchain.n == 0 ||
+ linkchain.n > 1 && cflag && outfile)
+ usage();
+
+ if (!dflag) {
+ if ((devnullfd = open("/dev/null", O_WRONLY)) < 0)
+ fputs("scc: could not open /dev/null\n", stderr);
+ }
+
+ if (!(tmpdir = getenv("TMPDIR")) || !tmpdir[0])
+ tmpdir = ".";
+ tmpdirln = strlen(tmpdir);
+
+ build(&linkchain, (link = !(Mflag || Eflag || Sflag || cflag)));
+
+ if (!(link || cflag))
+ return failure;
+
+ if (link && !failure) {
+ addarg(LD, xstrdup("-lc"));
+ spawn(settool(LD, NULL, LAST_TOOL));
+ validatetools();
+ }
+
+ if (sflag) {
+ spawn(settool(inittool(STRIP), NULL, LAST_TOOL));
+ validatetools();
+ }
+
+ return failure;
+}
--- a/src/cmd/scc/Makefile
+++ /dev/null
@@ -1,14 +1,0 @@
-.POSIX:
-
-PROJECTDIR = ../../..
-include $(PROJECTDIR)/scripts/rules.mk
-
-DIRS = cc1 cc2 $(DRIVER)
-
-all: $(DIRS)
-
-$(DIRS): FORCE
- +@cd $@ && $(MAKE)
-
-dep clean:
- $(FORALL)
--- a/src/cmd/scc/cc1/Makefile
+++ /dev/null
@@ -1,38 +1,0 @@
-.POSIX:
-
-PROJECTDIR = ../../../..
-include $(PROJECTDIR)/scripts/rules.mk
-
-OBJS = types.o \
- decl.o \
- lex.o \
- error.o \
- symbol.o \
- main.o \
- expr.o \
- code.o \
- stmt.o \
- cpp.o \
- fold.o \
- init.o \
- builtin.o \
-
-TARGET = $(LIBEXEC)/cc1-amd64-sysv \
- $(LIBEXEC)/cc1-arm64-sysv \
- $(LIBEXEC)/cc1-i386-sysv \
- $(LIBEXEC)/cc1-z80-scc \
-
-all: $(TARGET)
-
-$(TARGET): $(LIBDIR)/libscc.a
-
-dep: inc-dep
-
-clean:
- rm -f target/*/*.o
-
-include target/amd64-sysv/arch.mk
-include target/arm64-sysv/arch.mk
-include target/i386-sysv/arch.mk
-include target/z80-scc/arch.mk
-include deps.mk
--- a/src/cmd/scc/cc1/TODO
+++ /dev/null
@@ -1,14 +1,0 @@
-* Implement bitfields
-* Rewrite error recovery code, and ensure correct state after recovery
-* Parse correctly all integer and float constants
-* Add C99 features (almost all the new features of C99 are missed)
-* Add correct emit for any kind of constant
-* Add warning when some ANSI limit is violated.
-* Free memory in emit after some error happened.
-* Rewrite initializers to deal with the idea of "current object"
-* Add some test about pointer airthmetic.
-* Merge all the definitions of the same string
-* Do not assign identifierss until symbols are emitted. This change will
- avoid identifiers that are not emitted.
-* Fix assignation abbreviations. They fail whe lhs type is smaller than
- the type in rhs
--- a/src/cmd/scc/cc1/builtin.c
+++ /dev/null
@@ -1,119 +1,0 @@
-#include <stdio.h>
-
-#include <scc/scc.h>
-#include "cc1.h"
-
-static Node *
-builtin_va_arg(Symbol *sym)
-{
- Node *np, *ap;
- Type *tp;
-
- ap = assign();
- expect(',');
- tp = typename();
-
- if (!valid_va_list(ap->type)) {
- errorp("incorrect parameters for va_arg");
- goto error;
- }
- if (tp == booltype ||
- tp == chartype || tp == uchartype || tp == schartype ||
- tp == shortype || tp == ushortype) {
- warn("bool, char and short are promoted to int when passed through '...'");
- tp = (tp->prop & TSIGNED) ? inttype : uinttype;
- }
-
- np = node(OBUILTIN, tp, ap, NULL);
- np->sym = sym;
- return np;
-
-error:
- return constnode(zero);
-}
-
-static Node *
-builtin_va_copy(Symbol *sym)
-{
- Node *np, *src, *dst;
-
- dst = assign();
- expect(',');
- src = assign();
-
- if (!valid_va_list(dst->type) || !valid_va_list(src->type)) {
- errorp("incorrect parameters for va_copy");
- return constnode(zero);
- }
-
- np = node(OBUILTIN, voidtype, dst, src);
- np->sym = sym;
- return np;
-}
-
-static Node *
-builtin_va_start(Symbol *sym)
-{
- Node *np, *ap, *last;
- Symbol **p;
- Type *tp;
-
- ap = assign();
- expect(',');
- last = assign();
- if (last->op != OSYM)
- goto error;
-
- if (!valid_va_list(ap->type) || !(last->sym->flags&SDECLARED))
- goto error;
-
- for (p = curfun->u.pars; p && *p != last->sym; ++p)
- ;
- if (!p || *p == NULL || p[1] == NULL || p[1]->type != ellipsistype)
- warn("second parameter of 'va_start' not last named argument");
-
- tp = last->type;
- if (tp == booltype ||
- tp == chartype || tp == uchartype || tp == schartype ||
- tp == shortype || tp == ushortype) {
- warn("last parameter before '...' must not be bool, char or short");
- }
-
- np = node(OBUILTIN, voidtype, ap, last);
- np->sym = sym;
- return np;
-
-error:
- errorp("incorrect parameters for va_start");
- return constnode(zero);
-}
-
-static Node *
-builtin_va_end(Symbol *sym)
-{
- Node *ap, *np;
-
- ap = assign();
-
- if (!valid_va_list(ap->type)) {
- errorp("incorrect parameters for va_end");
- return constnode(zero);
- }
-
- np = node(OBUILTIN, voidtype, ap, NULL);
- np->sym = sym;
- return np;
-}
-
-void
-ibuilts(void)
-{
- struct builtin built[] = {
- {"__builtin_va_arg", builtin_va_arg},
- {"__builtin_va_copy", builtin_va_copy},
- {"__builtin_va_start", builtin_va_start},
- {"__builtin_va_end", builtin_va_end},
- {NULL}
- };
- builtins(built);
-}
--- a/src/cmd/scc/cc1/cc1.h
+++ /dev/null
@@ -1,496 +1,0 @@
-#define INPUTSIZ LINESIZ
-
-#define GLOBALCTX 0
-#define PARAMCTX 1
-
-#define NR_USWITCHES 20
-
-/*
- * Definition of enumerations
- */
-enum {
- NOALLOC,
- ALLOC
-};
-
-enum typeprops {
- TDEFINED = 1 << 0, /* type defined */
- TSIGNED = 1 << 1, /* signedness of the type */
- TINTEGER = 1 << 2, /* the type is INT of enum */
- TARITH = 1 << 3, /* the type is INT, ENUM or FLOAT */
- TAGGREG = 1 << 4, /* the type is struct or union */
- TK_R = 1 << 5, /* this is a K&R-function */
- TELLIPSIS= 1 << 6, /* this function has an ellipsis par */
- TFUNDEF = 1 << 7, /* function definition */
-};
-
-enum inputtype {
- IMACRO = 1 << 0, /* macro expansion type */
- IFILE = 1 << 1, /* input file type */
- ISTDIN = 1 << 2, /* stdin type */
- IEOF = 1 << 3, /* EOF mark */
- ITYPE = IMACRO | IFILE | ISTDIN,
-};
-
-/* data type letters */
-enum ns {
- L_INT8 = 'C',
- L_INT16 = 'I',
- L_INT32 = 'W',
- L_INT64 = 'Q',
- L_UINT8 = 'K',
- L_UINT16 = 'N',
- L_UINT32 = 'Z',
- L_UINT64 = 'O',
- L_BOOL = 'B',
-
- L_FLOAT = 'J',
- L_DOUBLE = 'D',
- L_LDOUBLE = 'H',
-
- L_ELLIPSIS = 'E',
- L_VOID = '0',
- L_POINTER = 'P',
- L_FUNCTION = 'F',
- L_ARRAY = 'V',
- L_UNION = 'U',
- L_STRUCT = 'S',
- L_VA_ARG = '1',
-};
-
-/* recovery points */
-enum {
- END_DECL,
- END_LDECL,
- END_COMP,
- END_COND
-};
-
-/* type constructors */
-enum typeop {
- FTN = 1,
- PTR,
- ARY,
- KRFTN
-};
-
-/* namespaces */
-enum namespaces {
- NS_DUMMY,
- NS_IDEN,
- NS_TAG,
- NS_LABEL,
- NS_CPP,
- NS_KEYWORD,
- NS_CPPCLAUSES,
- NS_STRUCTS
-};
-
-/* symbol flags */
-enum {
- SAUTO = 1 << 0,
- SREGISTER = 1 << 1,
- SDECLARED = 1 << 2,
- SFIELD = 1 << 3,
- SEXTERN = 1 << 4,
- SUSED = 1 << 5,
- SCONSTANT = 1 << 6,
- SGLOBAL = 1 << 7,
- SPRIVATE = 1 << 8,
- SLOCAL = 1 << 9,
- SEMITTED = 1 << 10,
- SDEFINED = 1 << 11,
- SSTRING = 1 << 12,
- STYPEDEF = 1 << 13,
- SINITLST = 1 << 14,
- SHASINIT = 1 << 15
-};
-
-/* node flags */
-enum {
- NLVAL = 1 << 0,
- NCONST = 1 << 1,
- NEFFECT = 1 << 2
-};
-
-/* lexer mode, compiler or preprocessor directive */
-enum {
- CCMODE,
- CPPMODE
-};
-
-/* input tokens */
-enum tokens {
- CONST = 1 << 0, /* type qualifier tokens are used as flags */
- RESTRICT = 1 << 1,
- VOLATILE = 1 << 2,
- INLINE = 1 << 3,
- TQUALIFIER = 1 << 7, /* this value is picked outside of ASCII range */
- TYPE,
- IDEN,
- SCLASS,
- CONSTANT,
- STRING,
- SIZEOF,
- INDIR,
- INC,
- DEC,
- SHL,
- SHR,
- LE,
- GE,
- EQ,
- NE,
- AND,
- OR,
- MUL_EQ,
- DIV_EQ,
- MOD_EQ,
- ADD_EQ,
- SUB_EQ,
- AND_EQ,
- XOR_EQ,
- OR_EQ,
- SHL_EQ,
- SHR_EQ,
- ELLIPSIS,
- CASE,
- DEFAULT,
- IF,
- ELSE,
- SWITCH,
- WHILE,
- DO,
- FOR,
- GOTO,
- VOID,
- FLOAT,
- INT,
- BOOL,
- VA_LIST,
- STRUCT,
- UNION,
- CHAR,
- DOUBLE,
- SHORT,
- LONG,
- LLONG,
- COMPLEX,
- TYPEDEF,
- EXTERN,
- STATIC,
- AUTO,
- REGISTER,
- ENUM,
- TYPEIDEN,
- UNSIGNED,
- SIGNED,
- CONTINUE,
- BREAK,
- RETURN,
- DEFINE,
- INCLUDE,
- LINE,
- PRAGMA,
- ERROR,
- IFDEF,
- ELIF,
- IFNDEF,
- UNDEF,
- ENDIF,
- BUILTIN,
- EOFTOK
-};
-
-/* operations */
-enum op {
- OADD,
- OMUL,
- OSUB,
- OINC,
- ODEC,
- ODIV,
- OMOD,
- OSHL,
- OSHR,
- OBAND,
- OBXOR,
- OBOR,
- OSNEG,
- ONEG,
- OCPL,
- OAND,
- OOR,
- OEQ,
- ONE,
- OLT,
- OGE,
- OLE,
- OGT,
- OASSIGN,
- OA_MUL,
- OA_DIV,
- OA_MOD,
- OA_ADD,
- OA_SUB,
- OA_SHL,
- OA_SHR,
- OA_AND,
- OA_XOR,
- OA_OR,
- OADDR,
- OCOMMA,
- OCAST,
- OPTR,
- OSYM,
- OASK,
- OCOLON,
- OFIELD,
- OLABEL,
- ODEFAULT,
- OCASE,
- OJUMP,
- OBRANCH,
- OEXPR,
- OEFUN,
- OELOOP,
- OBLOOP,
- OFUN,
- OPAR,
- OCALL,
- OCALLE,
- ORET,
- ODECL,
- OBSWITCH,
- OESWITCH,
- OINIT,
- OBUILTIN,
- OTYP,
-};
-
-/*
- * Definition of structures
- */
-typedef struct type Type;
-typedef struct symbol Symbol;
-typedef struct swtch Switch;
-typedef struct node Node;
-typedef struct input Input;
-
-struct limits {
- union {
- TUINT i;
- TFLOAT f;
- } max;
- union {
- TUINT i;
- TFLOAT f;
- } min;
-};
-
-struct builtin {
- char *str;
- Node *(*fun)(Symbol *);
-};
-
-struct keyword {
- char *str;
- unsigned char token, value;
-};
-
-struct type {
- unsigned char op; /* type builder operator */
- unsigned char ns; /* namespace for struct members */
- short id; /* type id, used in dcls */
- char letter; /* letter of the type */
- unsigned char prop; /* type properties */
- unsigned char align; /* align of the type */
- unsigned long size; /* sizeof the type */
- Type *type; /* base type */
- Symbol *tag; /* symbol of the strug tag */
- union {
- Type **pars; /* Function type parameters */
- Symbol **fields; /* fields of aggregate type */
- } p;
- union {
- unsigned char rank; /* convertion rank */
- TINT elem; /* number of type parameters */
- } n;
- Type *next; /* local list pointer */
- Type *h_next; /* hash collision list */
-};
-
-struct symbol {
- unsigned char ctx;
- unsigned char hide;
- char ns;
- unsigned short id;
- unsigned short flags;
- char *name;
- Type *type;
- unsigned char token;
- union {
- TINT i;
- TUINT u;
- TFLOAT f;
- char *s;
- unsigned char token;
- Node **init;
- Symbol **pars;
- Node *(*fun)(Symbol *);
- } u;
- struct symbol *next;
- struct symbol *hash;
-};
-
-struct node {
- unsigned char op;
- unsigned char flags;
- Type *type;
- Symbol *sym;
- struct node *left, *right;
-};
-
-struct swtch {
- short nr;
- char hasdef;
-};
-
-struct yystype {
- Symbol *sym;
- unsigned char token;
-};
-
-#ifdef stdin
-struct input {
- char flags;
- unsigned lineno;
- char *filenam;
- FILE *fp;
- Symbol *hide;
- char *line, *begin, *p;
- struct input *next;
-};
-#endif
-
-/* error.c */
-extern void error(char *fmt, ...);
-extern void warn(char *fmt, ...);
-extern void unexpected(void);
-extern void errorp(char *fmt, ...);
-extern void cpperror(char *fmt, ...);
-extern Type *deftype(Type *tp);
-
-/* types.c */
-extern int eqtype(Type *tp1, Type *tp2, int eqflag);
-extern Type *ctype(int type, int sign, int size);
-extern Type *mktype(Type *tp, int op, TINT nelem, Type *data[]);
-extern Type *duptype(Type *base);
-extern struct limits *getlimits(Type *tp);
-extern void typesize(Type *tp);
-extern void flushtypes(void);
-
-/* symbol.c */
-extern void dumpstab(Symbol **tbl, char *msg);
-extern Symbol *lookup(int ns, char *name, int alloc);
-extern Symbol *nextsym(Symbol *sym, int ns);
-extern Symbol *install(int ns, Symbol *sym);
-extern Symbol *newsym(int ns, char *name);
-extern void pushctx(void), popctx(void);
-extern void killsym(Symbol *sym);
-extern Symbol *newlabel(void);
-extern void keywords(struct keyword *key, int ns);
-extern void builtins(struct builtin *builts);
-extern Symbol *newstring(char *s, size_t len);
-extern unsigned newid(void);
-
-/* stmt.c */
-extern void compound(Symbol *lbreak, Symbol *lcont, Switch *sw);
-
-/* decl.c */
-extern Type *typename(void);
-extern void decl(void);
-
-/* lex.c */
-extern int ahead(void);
-extern int next(void);
-extern void expect(int tok);
-extern void discard(void);
-extern void addinput(char *fname, Symbol *hide, char *buffer);
-extern void delinput(void);
-extern void setsafe(int type);
-extern void ilex(void);
-extern void setloc(char *fname, unsigned line);
-#define accept(t) ((yytoken == (t)) ? next() : 0)
-
-/* code.c */
-extern void prtree(Node *np);
-extern void emit(int, void *);
-extern Node *node(int op, Type *tp, Node *left, Node *rigth);
-extern Node *varnode(Symbol *sym);
-extern Node *constnode(Symbol *sym);
-extern Node *sizeofnode(Type *tp);
-extern void freetree(Node *np);
-extern void icode(void);
-#define BTYPE(np) ((np)->type->op)
-
-/* fold.c */
-extern Node *simplify(Node *np);
-extern TUINT ones(int nbytes);
-
-/* expr.c */
-extern Node *decay(Node *), *negate(Node *np), *assign(void);
-extern Node *convert(Node *np, Type *tp1, int iscast);
-extern Node *constexpr(void), *condexpr(int neg), *expr(void);
-extern int isnodecmp(int op);
-extern int negop(int op);
-extern int cmpnode(Node *np, TUINT val);
-
-/* init.c */
-extern void initializer(Symbol *sym, Type *tp);
-extern Node *initlist(Type *tp);
-
-/* cpp.c */
-extern void icpp(void);
-extern int cpp(void);
-extern int expand(char *begin, Symbol *sym);
-extern void incdir(char *dir);
-extern void outcpp(void);
-extern void defdefine(char *macro, char *val, char *source);
-extern void undefmacro(char *s);
-extern void ppragmaln(void);
-
-/* builtin.c */
-extern void ibuilts(void);
-
-/* arch.c */
-extern void iarch(void);
-extern int valid_va_list(Type *tp);
-
-/*
- * Definition of global variables
- */
-extern struct yystype yylval;
-extern char yytext[];
-extern int yytoken;
-extern unsigned short yylen;
-extern int disexpand;
-extern unsigned cppctx;
-extern Input *input;
-extern int lexmode, namespace;
-extern int onlycpp, onlyheader;
-extern unsigned curctx;
-extern Symbol *curfun, *zero, *one;
-extern char *infile;
-extern unsigned lineno;
-extern char filenam[];
-
-extern Type *voidtype, *pvoidtype, *booltype,
- *uchartype, *chartype, *schartype,
- *uinttype, *inttype,
- *sizettype, *pdifftype,
- *ushortype, *shortype,
- *longtype, *ulongtype,
- *ullongtype, *llongtype,
- *floattype, *doubletype, *ldoubletype,
- *ellipsistype, *va_list_type, *va_type;
--- a/src/cmd/scc/cc1/code.c
+++ /dev/null
@@ -1,549 +1,0 @@
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include <scc/scc.h>
-#include "cc1.h"
-
-static void emitbin(int, void *),
- emitcast(int, void *),
- emitsym(int, void *),
- emitexp(int, void *),
- emitsymid(int, void *),
- emittext(int, void *),
- emitfun(int, void *),
- emitdcl(int, void *),
- emitinit(int, void *),
- emittype(int, void *),
- emitbuilt(int, void *);
-
-char *optxt[] = {
- [OADD] = "+",
- [OSUB] = "-",
- [OMUL] = "*",
- [OINC] = ":i",
- [ODEC] = ":d",
- [OPTR] = "@",
- [OMOD] = "%",
- [ODIV] = "/",
- [OSHL] = "l",
- [OSHR] = "r",
- [OLT] = "<",
- [OGT] = ">",
- [OGE] = "]",
- [OLE] = "[",
- [OEQ] = "=",
- [ONE] = "!",
- [OBAND] = "&",
- [OBXOR] = "^",
- [OBOR] = "|",
- [OASSIGN] = ":",
- [OA_MUL] = ":*",
- [OA_DIV] = ":/",
- [OA_MOD] = ":%",
- [OA_ADD] = ":+",
- [OA_SUB] = ":-",
- [OA_SHL] = ":l",
- [OA_SHR] = ":r",
- [OA_AND] = ":&",
- [OA_XOR] = ":^",
- [OA_OR] = ":|",
- [OADDR] = "'",
- [OSNEG] = "_",
- [ONEG] = "n",
- [OCPL] = "~",
- [OAND] = "a",
- [OOR] = "o",
- [OASK] = "?",
- [OCOMMA] = ",",
- [OLABEL] = "L%d\n",
- [ODEFAULT] = "\tf\tL%d\n",
- [OBSWITCH] = "\ts",
- [OESWITCH] = "\tt\tL%d\n",
- [OCASE] = "\tv\tL%d",
- [OJUMP] = "\tj\tL%d\n",
- [OBRANCH] = "\ty\tL%d",
- [OEFUN] = "}\n",
- [OELOOP] = "\tb\n",
- [OBLOOP] = "\te\n",
- [ORET] = "\th",
- [OPAR] = "p",
- [OCALL] = "c",
- [OCALLE] = "z",
- [OFIELD] = "."
-};
-
-void (*opcode[])(int, void *) = {
- [OADD] = emitbin,
- [OSUB] = emitbin,
- [OMUL] = emitbin,
- [OINC] = emitbin,
- [ODEC] = emitbin,
- [OPTR] = emitbin,
- [OMOD] = emitbin,
- [ODIV] = emitbin,
- [OSHL] = emitbin,
- [OSHR] = emitbin,
- [OLT] = emitbin,
- [OGT] = emitbin,
- [OGE] = emitbin,
- [OLE] = emitbin,
- [OEQ] = emitbin,
- [ONE] = emitbin,
- [OBAND] = emitbin,
- [OBXOR] = emitbin,
- [OBOR] = emitbin,
- [OASSIGN] = emitbin,
- [OA_MUL] = emitbin,
- [OA_DIV] = emitbin,
- [OA_MOD] = emitbin,
- [OA_ADD] = emitbin,
- [OA_SUB] = emitbin,
- [OA_SHL] = emitbin,
- [OA_SHR] = emitbin,
- [OA_AND] = emitbin,
- [OA_XOR] = emitbin,
- [OA_OR] = emitbin,
- [OADDR] = emitbin,
- [OSNEG] = emitbin,
- [ONEG] = emitbin,
- [OCPL] = emitbin,
- [OAND] = emitbin,
- [OOR] = emitbin,
- [OCOMMA] = emitbin,
- [OCAST] = emitcast,
- [OSYM] = emitsym,
- [OASK] = emitbin,
- [OCOLON] = emitbin,
- [OFIELD]= emitbin,
- [OEXPR] = emitexp,
- [OLABEL] = emitsymid,
- [ODEFAULT] = emitsymid,
- [OCASE] = emitsymid,
- [OJUMP] = emitsymid,
- [OBRANCH] = emitsymid,
- [OEFUN] = emittext,
- [OELOOP] = emittext,
- [OBLOOP] = emittext,
- [OFUN] = emitfun,
- [ORET] = emittext,
- [ODECL] = emitdcl,
- [OBSWITCH] = emittext,
- [OESWITCH] = emitsymid,
- [OPAR] = emitbin,
- [OCALL] = emitbin,
- [OCALLE] = emitbin,
- [OINIT] = emitinit,
- [OBUILTIN] = emitbuilt,
- [OTYP] = emittype,
-};
-
-static FILE *outfp;
-
-void
-icode(void)
-{
- outfp = stdout;
-}
-
-void
-freetree(Node *np)
-{
- if (!np)
- return;
- freetree(np->left);
- freetree(np->right);
- free(np);
-}
-
-static void
-emitnode(Node *np)
-{
- if (np)
- (*opcode[np->op])(np->op, np);
-}
-
-void
-prtree(Node *np)
-{
- outfp = stderr;
- fputs("DBG prtree", outfp);
- emitnode(np);
- putc('\n', outfp);
- outfp = stdout;
-}
-
-void
-emit(int op, void *arg)
-{
- extern int failure;
-
- if (failure || onlycpp || onlyheader)
- return;
- (*opcode[op])(op, arg);
-}
-
-static void
-emitvar(Symbol *sym)
-{
- int c;
- short flags = sym->flags;
-
- if (flags & SLOCAL)
- c = 'T';
- else if (flags & SPRIVATE)
- c = 'Y';
- else if (flags & SGLOBAL)
- c = 'G';
- else if (flags & SREGISTER)
- c = 'R';
- else if (flags & SFIELD)
- c = 'M';
- else if (flags & SEXTERN)
- c = 'X';
- else
- c = 'A';
- fprintf(outfp, "%c%u", c, sym->id);
-}
-
-static void
-emitconst(Node *np)
-{
- Symbol *sym = np->sym;
- Type *tp = np->type;
- TUINT u;
-
- switch (tp->op) {
- case PTR:
- case INT:
- case ENUM:
- u = (tp->prop & TSIGNED) ? (TUINT) sym->u.i : sym->u.u;
- fprintf(outfp,
- "#%c%llX",
- np->type->letter,
- (long long) u & ones(tp->size));
- break;
- default:
- abort();
- }
-}
-
-static void
-emitsym(int op, void *arg)
-{
- Node *np = arg;
-
- if ((np->sym->flags & SINITLST) == 0) {
- /*
- * When we have a compound literal we are going
- * to call to emitnode for every element of it,
- * and it means that we will have two '\t'
- * for the first element
- */
- putc('\t', outfp);
- }
- (np->flags & NCONST) ? emitconst(np) : emitvar(np->sym);
-}
-
-static void
-emitletter(Type *tp)
-{
- int letter;
-
- letter = (tp->prop&TELLIPSIS) ? 'E' : tp->letter;
- putc(letter, outfp);
- switch (tp->op) {
- case ARY:
- case STRUCT:
- case UNION:
- fprintf(outfp, "%u", tp->id);
- }
-}
-
-static void
-emittype(int op, void *arg)
-{
- TINT n;
- Symbol **sp;
- char *tag;
- Type *tp = arg;
-
- if (!(tp->prop & TDEFINED))
- return;
-
- switch (tp->op) {
- case ARY:
- emitletter(tp);
- putc('\t', outfp);
- emitletter(tp->type);
- fprintf(outfp,
- "\t#%c%llX\n",
- sizettype->letter, (long long) tp->n.elem);
- return;
- case UNION:
- case STRUCT:
- emitletter(tp);
- tag = tp->tag->name;
- fprintf(outfp,
- "\t\"%s\t#%c%lX\t#%c%X\n",
- (tag) ? tag : "",
- sizettype->letter,
- tp->size,
- sizettype->letter,
- tp->align);
- n = tp->n.elem;
- for (sp = tp->p.fields; n-- > 0; ++sp)
- emit(ODECL, *sp);
- break;
- case PTR:
- case FTN:
- case ENUM:
- return;
- default:
- abort();
- }
-}
-
-static void
-emitstring(Symbol *sym, Type *tp)
-{
- char *bp, *s, *lim;
- int n;
-
- bp = sym->u.s;
- lim = &sym->u.s[tp->n.elem];
- while (bp < lim) {
- s = bp;
- while (bp < lim && isprint(*bp))
- ++bp;
- if ((n = bp - s) > 1)
- fprintf(outfp, "\t#\"%.*s\n", n, s);
- else
- bp = s;
- if (bp == lim)
- break;
- do {
- fprintf(outfp,
- "\t#%c%02X\n",
- chartype->letter, (*bp++) & 0xFF);
- } while (bp < lim && !isprint(*bp));
- }
-}
-
-static void
-emitdesig(Node *np, Type *tp)
-{
- Symbol *sym;
- size_t n; /* TODO: This should be SIZET */
- Node *aux;
- Type *p;
-
- if (!np) {
- sym = NULL;
- } else {
- if (!np->sym)
- goto emit_expression;
- sym = np->sym;
- if (sym->flags & SSTRING) {
- emitstring(sym, tp);
- return;
- }
- if ((sym->flags & SINITLST) == 0)
- goto emit_expression;
- }
-
- switch (tp->op) {
- case PTR:
- case INT:
- case ENUM:
- aux = (sym) ? *sym->u.init : convert(constnode(zero), tp, 0);
- emitexp(OEXPR, aux);
- break;
- case UNION:
- n = tp->n.elem-1;
- aux = (sym) ? sym->u.init[0] : NULL;
- emitdesig(aux, aux->type);
- break;
- case STRUCT:
- case ARY:
- for (n = 0; n < tp->n.elem; ++n) {
- aux = (sym) ? sym->u.init[n] : NULL;
- p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type;
- emitdesig(aux, p);
- }
- break;
- default:
- abort();
- }
-
- if (sym) {
- free(sym->u.init);
- sym->u.init = NULL;
- }
- freetree(np);
- return;
-
-emit_expression:
- emitexp(OEXPR, np);
-}
-
-static void
-emitinit(int op, void *arg)
-{
- Node *np = arg;
-
- fputs("\t(\n", outfp);
- emitdesig(np, np->type);
- fputs(")\n", outfp);
-}
-
-static void
-emitdcl(int op, void *arg)
-{
- Symbol *sym = arg;
-
- if (sym->flags & SEMITTED)
- return;
- emitvar(sym);
- putc('\t', outfp);
- if (sym->type->op == FTN) {
- emitletter(sym->type->type);
- putc('\t', outfp);
- }
- emitletter(sym->type);
- fprintf(outfp, "\t\"%s", (sym->name) ? sym->name : "");
- if (sym->flags & SFIELD)
- fprintf(outfp, "\t#%c%llX", sizettype->letter, sym->u.i);
- sym->flags |= SEMITTED;
- if ((sym->flags & SHASINIT) == 0)
- putc('\n', outfp);
-}
-
-static void
-emitcast(int op, void *arg)
-{
- Node *np = arg, *lp = np->left;
-
- emitnode(lp);
- if (np->type != voidtype)
- fprintf(outfp, "\tg%c", np->type->letter);
-}
-
-static void
-emitbin(int op, void *arg)
-{
- Node *np = arg;
- char *s;
-
- emitnode(np->left);
- emitnode(np->right);
- if ((s = optxt[op]) != NULL) { /* do not print in OCOLON case */
- fprintf(outfp, "\t%s", s);
- emitletter(np->type);
- }
-}
-
-static void
-emitbuilt(int op, void *arg)
-{
- Node *np = arg;
-
- emitnode(np->left);
- emitnode(np->right);
- fprintf(outfp, "\t\"%s\tm", np->sym->name);
- emitletter(np->type);
-}
-
-
-static void
-emitexp(int op, void *arg)
-{
- Node *np = arg;
-
- emitnode(np);
- putc('\n', outfp);
- freetree(np);
-}
-
-static void
-emitfun(int op, void *arg)
-{
- Symbol *sym = arg, **sp;
-
- emitdcl(op, arg);
- fputs("{\n", outfp);
-
- for (sp = sym->u.pars; sp && *sp; ++sp)
- emit(ODECL, *sp);
- fputs("\\\n", outfp);
-}
-
-static void
-emittext(int op, void *arg)
-{
- fputs(optxt[op], outfp);
-}
-
-static void
-emitsymid(int op, void *arg)
-{
- Symbol *sym = arg;
- fprintf(outfp, optxt[op], sym->id);
-}
-
-Node *
-node(int op, Type *tp, Node *lp, Node *rp)
-{
- Node *np;
-
- np = xmalloc(sizeof(*np));
- np->op = op;
- np->type = tp;
- np->sym = NULL;
- np->flags = 0;
- np->left = lp;
- np->right = rp;
-
- if (lp)
- np->flags |= lp->flags & NEFFECT;
- if (rp)
- np->flags |= rp->flags & NEFFECT;
- return np;
-}
-
-Node *
-varnode(Symbol *sym)
-{
- Node *np;
- Type *tp = sym->type;
-
- np = node(OSYM, sym->type, NULL, NULL);
- np->type = sym->type;
- np->flags = (tp->op != FTN && tp->op != ARY) ? NLVAL : 0;
- np->sym = sym;
- return np;
-}
-
-Node *
-constnode(Symbol *sym)
-{
- Node *np;
-
- np = node(OSYM, sym->type, NULL, NULL);
- np->type = sym->type;
- np->flags = NCONST;
- np->sym = sym;
- return np;
-}
-
-Node *
-sizeofnode(Type *tp)
-{
- Symbol *sym;
-
- sym = newsym(NS_IDEN, NULL);
- sym->type = sizettype;
- sym->u.i = tp->size;
- return constnode(sym);
-}
--- a/src/cmd/scc/cc1/cpp.c
+++ /dev/null
@@ -1,838 +1,0 @@
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-static char *argp, *macroname;
-static unsigned arglen;
-static unsigned ncmdlines;
-static Symbol *symline, *symfile;
-static unsigned char ifstatus[NR_COND];
-static int cppoff;
-static struct items dirinclude;
-
-unsigned cppctx;
-int disexpand;
-
-void
-defdefine(char *macro, char *val, char *source)
-{
- char *def, *fmt = "#define %s %s\n";
- Symbol dummy = {.flags = SDECLARED};
-
- if (!val)
- val = "";
- def = xmalloc(strlen(fmt) + strlen(macro) + strlen(val));
-
- sprintf(def, fmt, macro, val);
- lineno = ++ncmdlines;
- addinput(source, &dummy, def);
- cpp();
- delinput();
-}
-
-void
-undefmacro(char *s)
-{
- killsym(lookup(NS_CPP, s, NOALLOC));
-}
-
-void
-icpp(void)
-{
- static char sdate[14], stime[11];
- struct tm *tm;
- time_t t;
- static char **bp, *list[] = {
- "__STDC__",
- "__STDC_HOSTED__",
- "__SCC__",
- NULL
- };
- static struct keyword keys[] = {
- {"define", DEFINE, DEFINE},
- {"include", INCLUDE, INCLUDE},
- {"line", LINE, LINE},
- {"ifdef", IFDEF, IFDEF},
- {"if", IF, IF},
- {"elif", ELIF, ELIF},
- {"else", ELSE, ELSE},
- {"ifndef", IFNDEF, IFNDEF},
- {"endif", ENDIF, ENDIF},
- {"undef", UNDEF, UNDEF},
- {"pragma", PRAGMA, PRAGMA},
- {"error", ERROR, ERROR},
- {NULL, 0, 0}
- };
-
- keywords(keys, NS_CPPCLAUSES);
-
- t = time(NULL);
- tm = localtime(&t);
- strftime(sdate, sizeof(sdate), "\"%b %d %Y\"", tm);
- strftime(stime, sizeof(stime), "\"%H:%M:%S\"", tm);
- defdefine("__DATE__", sdate, "built-in");
- defdefine("__TIME__", stime, "built-in");
- defdefine("__STDC_VERSION__", STDC_VERSION, "built-in");
- defdefine("__LINE__", NULL, "built-in");
- defdefine("__FILE__", NULL, "built-in");
-
- symline = lookup(NS_CPP, "__LINE__", ALLOC);
- symfile = lookup(NS_CPP, "__FILE__", ALLOC);
-
- for (bp = list; *bp; ++bp)
- defdefine(*bp, "1", "built-in");
-
- ncmdlines = 0;
-}
-
-static void
-nextcpp(void)
-{
- next();
- if (yytoken == EOFTOK)
- error("unterminated argument list invoking macro \"%s\"",
- macroname);
- if (yylen + 1 > arglen)
- error("argument overflow invoking macro \"%s\"",
- macroname);
- if (yytoken == IDEN)
- yylval.sym->flags |= SUSED;
- memcpy(argp, yytext, yylen);
- argp += yylen;
- *argp++ = ' ';
- arglen -= yylen + 1;
-}
-
-static void
-paren(void)
-{
- for (;;) {
- nextcpp();
- switch (yytoken) {
- case ')':
- return;
- case '(':
- paren();
- break;
- }
- }
-}
-
-static void
-parameter(void)
-{
- for (;;) {
- nextcpp();
- switch (yytoken) {
- case ')':
- case ',':
- argp -= 3; /* remove " , " or " ) "*/
- *argp++ = '\0';
- return;
- case '(':
- paren();
- break;
- }
- }
-}
-
-static int
-parsepars(char *buffer, char **listp, int nargs)
-{
- int n;
-
- if (nargs == -1)
- return -1;
- if (ahead() != '(' && nargs > 0)
- return 0;
-
- disexpand = 1;
- next();
- n = 0;
- argp = buffer;
- arglen = INPUTSIZ;
- if (ahead() == ')') {
- next();
- } else {
- do {
- *listp++ = argp;
- parameter();
- } while (++n < NR_MACROARG && yytoken == ',');
- }
- if (yytoken != ')')
- error("incorrect macro function-alike invocation");
- disexpand = 0;
-
- if (n == NR_MACROARG)
- error("too many parameters in macro \"%s\"", macroname);
- if (n != nargs) {
- error("macro \"%s\" received %d arguments, but it takes %d",
- macroname, n, nargs);
- }
-
- return 1;
-}
-
-static size_t
-copymacro(char *buffer, char *s, size_t bufsiz, char *arglist[])
-{
- int delim, prevc, c;
- char *p, *arg, *bp = buffer;
- size_t size;
-
- for (prevc = '\0'; c = *s; prevc = c, ++s) {
- switch (c) {
- case '$':
- while (bp[-1] == ' ')
- --bp, ++bufsiz;
- while (s[1] == ' ')
- ++s;
- case '#':
- break;
- case '\'':
- delim = '\'';
- goto search_delim;
- case '\"':
- delim = '"';
- search_delim:
- for (p = s; *++s != delim; )
- ;
- size = s - p + 1;
- if (size > bufsiz)
- goto expansion_too_long;
- memcpy(bp, p, size);
- bufsiz -= size;
- bp += size;
- break;
- case '@':
- if (prevc == '#')
- bufsiz -= 2;
- arg = arglist[atoi(++s)];
- size = strlen(arg);
- if (size > bufsiz)
- goto expansion_too_long;
- if (prevc == '#')
- *bp++ = '"';
- memcpy(bp, arg, size);
- bp += size;
- if (prevc == '#')
- *bp++ = '"';
- bufsiz -= size;
- s += 2;
- break;
- default:
- if (bufsiz-- == 0)
- goto expansion_too_long;
- *bp++ = c;
- break;
- }
- }
- *bp = '\0';
-
- return bp - buffer;
-
-expansion_too_long:
- error("macro expansion of \"%s\" too long", macroname);
-}
-
-int
-expand(char *begin, Symbol *sym)
-{
- size_t elen;
- int n, i;
- char *s = sym->u.s;
- char *arglist[NR_MACROARG], arguments[INPUTSIZ], buffer[INPUTSIZ];
-
- macroname = sym->name;
- if (sym == symfile) {
- elen = sprintf(buffer, "\"%s\" ", filenam);
- goto substitute;
- }
- if (sym == symline) {
- elen = sprintf(buffer, "%d ", lineno);
- goto substitute;
- }
- if (!s)
- return 1;
-
- n = atoi(s);
- if (!parsepars(arguments, arglist, n))
- return 0;
- for (i = 0; i < n; ++i)
- DBG("MACRO par%d:%s", i, arglist[i]);
-
- elen = copymacro(buffer, s+3, INPUTSIZ-1, arglist);
-
-substitute:
- DBG("MACRO '%s' expanded to :'%s'", macroname, buffer);
- buffer[elen] = '\0';
- addinput(filenam, sym, xstrdup(buffer));
-
- return 1;
-}
-
-static int
-getpars(Symbol *args[NR_MACROARG])
-{
- int n, c;
- Symbol *sym;
-
- c = *input->p;
- next();
- if (c != '(')
- return -1;
- next(); /* skip the '(' */
- if (accept(')'))
- return 0;
-
- n = 0;
- do {
- if (n == NR_MACROARG) {
- cpperror("too many parameters in macro");
- return NR_MACROARG;
- }
- if (accept(ELLIPSIS)) {
- args[n++] = NULL;
- break;
- }
- if (yytoken != IDEN) {
- cpperror("macro arguments must be identifiers");
- return NR_MACROARG;
- }
- sym = install(NS_IDEN, yylval.sym);
- sym->flags |= SUSED;
- args[n++] = sym;
- next();
- } while (accept(','));
- expect(')');
-
- return n;
-}
-
-static int
-getdefs(Symbol *args[NR_MACROARG], int nargs, char *bp, size_t bufsiz)
-{
- Symbol **argp;
- size_t len;
- int prevc = 0, ispar;
-
- if (yytoken == '$') {
- cpperror("'##' cannot appear at either ends of a macro expansion");
- return 0;
- }
-
- for (;;) {
- ispar = 0;
- if (yytoken == IDEN && nargs >= 0) {
- for (argp = args; argp < &args[nargs]; ++argp) {
- if (*argp == yylval.sym)
- break;
- }
- if (argp != &args[nargs]) {
- sprintf(yytext, "@%02d@", (int) (argp - args));
- ispar = 1;
- }
- }
- if (prevc == '#' && !ispar) {
- cpperror("'#' is not followed by a macro parameter");
- return 0;
- }
- if (yytoken == '\n')
- break;
-
- if ((len = strlen(yytext)) >= bufsiz) {
- cpperror("macro too long");
- return 0;
- }
- if (yytoken == '$') {
- *bp++ = '$';
- --bufsiz;
- } else {
- memcpy(bp, yytext, len);
- bp += len;
- bufsiz -= len;
- }
- if ((prevc = yytoken) != '#') {
- *bp++ = ' ';
- --bufsiz;
- }
- next();
- }
- *bp = '\0';
- return 1;
-}
-
-static void
-define(void)
-{
- Symbol *sym,*args[NR_MACROARG];
- char buff[LINESIZ+1];
- int n;
-
- if (cppoff)
- return;
-
- namespace = NS_CPP;
- next();
-
- if (yytoken != IDEN) {
- cpperror("macro names must be identifiers");
- return;
- }
- sym = yylval.sym;
- if (sym->flags & SDECLARED) {
- warn("'%s' redefined", yytext);
- free(sym->u.s);
- } else {
- sym = install(NS_CPP, sym);
- sym->flags |= SDECLARED|SSTRING;
- }
-
- namespace = NS_IDEN; /* Avoid polution in NS_CPP */
- if ((n = getpars(args)) == NR_MACROARG)
- goto delete;
- if (n > 0 && !args[n-1]) /* it is a variadic function */
- --n;
- sprintf(buff, "%02d#", n);
- if (!getdefs(args, n, buff+3, LINESIZ-3))
- goto delete;
- sym->u.s = xstrdup(buff);
- DBG("MACRO '%s' defined as '%s'", sym->name, buff);
- return;
-
-delete:
- killsym(sym);
-}
-
-void
-incdir(char *dir)
-{
- if (!dir || *dir == '\0')
- die("cc1: incorrect -I flag");
- newitem(&dirinclude, dir);
-}
-
-static int
-includefile(char *dir, char *file, size_t filelen)
-{
- size_t dirlen;
- char path[FILENAME_MAX];
-
- if (!dir) {
- dirlen = 0;
- if (filelen > FILENAME_MAX-1)
- return 0;
- } else {
- dirlen = strlen(dir);
- if (dirlen + filelen > FILENAME_MAX-2)
- return 0;
- memcpy(path, dir, dirlen);
- if (dir[dirlen-1] != '/')
- path[dirlen++] = '/';
- }
- memcpy(path+dirlen, file, filelen);
- path[dirlen + filelen] = '\0';
-
- addinput(path, NULL, NULL);
- return 1;
-}
-
-static char *
-cwd(char *buf)
-{
- char *p, *s = filenam;
- size_t len;
-
- if ((p = strrchr(s, '/')) == NULL)
- return NULL;
- if ((len = p - s) >= FILENAME_MAX)
- die("cc1: current work directory too long");
- memcpy(buf, s, len);
- buf[len] = '\0';
- return buf;
-}
-
-static void
-include(void)
-{
- char dir[FILENAME_MAX], file[FILENAME_MAX], *p, **bp;
- size_t filelen;
- int n;
-
- if (cppoff)
- return;
-
- namespace = NS_IDEN;
- next();
-
- switch (*yytext) {
- case '<':
- if ((p = strchr(input->begin, '>')) == NULL || p[-1] == '<')
- goto bad_include;
- filelen = p - input->begin;
- if (filelen >= FILENAME_MAX)
- goto too_long;
- memcpy(file, input->begin, filelen);
- file[filelen] = '\0';
-
- input->begin = input->p = p+1;
- if (next() != '\n')
- goto trailing_characters;
-
- break;
- case '"':
- if (yylen < 3)
- goto bad_include;
- filelen = yylen-2;
- if (filelen >= FILENAME_MAX)
- goto too_long;
- memcpy(file, yytext+1, filelen);
- file[filelen] = '\0';
-
- if (next() != '\n')
- goto trailing_characters;
-
- if (includefile(cwd(dir), file, filelen))
- goto its_done;
- break;
- default:
- goto bad_include;
- }
-
- n = dirinclude.n;
- for (bp = dirinclude.s; n--; ++bp) {
- if (includefile(*bp, file, filelen))
- goto its_done;
- }
- cpperror("included file '%s' not found", file);
-
-its_done:
- return;
-
-trailing_characters:
- cpperror("trailing characters after preprocessor directive");
- return;
-
-too_long:
- cpperror("too long file name in #include");
- return;
-
-bad_include:
- cpperror("#include expects \"FILENAME\" or <FILENAME>");
- return;
-}
-
-static void
-line(void)
-{
- long n;
- char *endp, *fname;
-
- if (cppoff)
- return;
-
- disexpand = 0;
- next();
- n = strtol(yytext, &endp, 10);
- if (n <= 0 || n > USHRT_MAX || *endp != '\0') {
- cpperror("first parameter of #line is not a positive integer");
- return;
- }
-
- next();
- if (yytoken == '\n') {
- fname = NULL;
- } else {
- if (*yytext != '\"' || yylen == 1) {
- cpperror("second parameter of #line is not a valid filename");
- return;
- }
- fname = yylval.sym->u.s;
- }
- setloc(fname, n - 1);
- if (yytoken != '\n')
- next();
-}
-
-static void
-pragma(void)
-{
- if (cppoff)
- return;
- next();
- warn("ignoring pragma '%s'", yytext);
- *input->p = '\0';
- next();
-}
-
-static void
-usererr(void)
-{
- if (cppoff)
- return;
- cpperror("#error %s", input->p);
- *input->p = '\0';
- next();
-}
-
-static void
-ifclause(int negate, int isifdef)
-{
- Symbol *sym;
- unsigned n;
- int status;
- Node *expr;
-
- if (cppctx == NR_COND-1)
- error("too many nesting levels of conditional inclusion");
-
- n = cppctx++;
- namespace = NS_CPP;
- next();
-
- if (isifdef) {
- if (yytoken != IDEN) {
- cpperror("no macro name given in #%s directive",
- (negate) ? "ifndef" : "ifdef");
- return;
- }
- sym = yylval.sym;
- next();
- status = (sym->flags & SDECLARED) != 0;
- if (!status)
- killsym(sym);
- } else {
- /* TODO: catch recovery here */
- if ((expr = constexpr()) == NULL) {
- cpperror("parameter of #if is not an integer constant expression");
- return;
- }
- status = expr->sym->u.i != 0;
- freetree(expr);
- }
-
- if (negate)
- status = !status;
- if ((ifstatus[n] = status) == 0)
- ++cppoff;
-}
-
-static void
-cppif(void)
-{
- disexpand = 0;
- ifclause(0, 0);
-}
-
-static void
-ifdef(void)
-{
- ifclause(0, 1);
-}
-
-static void
-ifndef(void)
-{
- ifclause(1, 1);
-}
-
-static void
-elseclause(void)
-{
- int status;
-
- if (cppctx == 0) {
- cpperror("#else without #ifdef/ifndef");
- return;
- }
-
- status = ifstatus[cppctx-1];
- ifstatus[cppctx-1] = !status;
- cppoff += (status) ? 1 : -1;
-}
-
-static void
-cppelse(void)
-{
- elseclause();
- next();
-}
-
-static void
-elif(void)
-{
- elseclause();
- if (ifstatus[cppctx-1]) {
- --cppctx;
- cppif();
- }
-}
-
-static void
-endif(void)
-{
- if (cppctx == 0)
- error("#endif without #if");
- if (!ifstatus[--cppctx])
- --cppoff;
- next();
-}
-
-static void
-undef(void)
-{
- if (cppoff)
- return;
-
- namespace = NS_CPP;
- next();
- if (yytoken != IDEN) {
- error("no macro name given in #undef directive");
- return;
- }
- killsym(yylval.sym);
- next();
-}
-
-int
-cpp(void)
-{
- static struct {
- unsigned char token;
- void (*fun)(void);
- } *bp, clauses [] = {
- {DEFINE, define},
- {INCLUDE, include},
- {LINE, line},
- {IFDEF, ifdef},
- {IF, cppif},
- {ELIF, elif},
- {IFNDEF, ifndef},
- {ELSE, cppelse},
- {ENDIF, endif},
- {UNDEF, undef},
- {PRAGMA, pragma},
- {ERROR, usererr},
- {0, NULL}
- };
- int ns;
- char *p;
-
- for (p = input->p; isspace(*p); ++p)
- ;
-
- if (*p != '#')
- return cppoff;
- input->p = p+1;
-
- disexpand = 1;
- lexmode = CPPMODE;
- ns = namespace;
- namespace = NS_CPPCLAUSES;
- next();
- namespace = NS_IDEN;
-
- for (bp = clauses; bp->token && bp->token != yytoken; ++bp)
- ;
- if (!bp->token) {
- errorp("incorrect preprocessor directive '%s'", yytext);
- goto error;
- }
-
- DBG("CPP %s", yytext);
-
- pushctx(); /* create a new context to avoid polish */
- (*bp->fun)(); /* the current context, and to get all */
- popctx(); /* the symbols freed at the end */
-
- /*
- * #include changes the content of input->line, so the correctness
- * of the line must be checked in the own include(), and we have
- * to skip this tests. For the same reason include() is the only
- * function which does not prepare the next token
- */
- if (yytoken != '\n' && !cppoff && bp->token != INCLUDE)
- errorp("trailing characters after preprocessor directive");
-
-error:
- disexpand = 0;
- lexmode = CCMODE;
- namespace = ns;
-
- return 1;
-}
-
-void
-ppragmaln(void)
-{
- static char file[FILENAME_MAX];
- static unsigned nline;
- char *s;
-
- putchar('\n');
- if (strcmp(file, filenam)) {
- strcpy(file, filenam);
- s = "#line %u \"%s\"\n";
- } else if (nline+1 != lineno) {
- s = "#line %u\n";
- } else {
- s = "";
- }
- nline = lineno;
- printf(s, nline, file);
-}
-
-void
-outcpp(void)
-{
- int c;
- char *s, *t;
-
- for (next(); yytoken != EOFTOK; next()) {
- if (onlyheader)
- continue;
- if (yytoken != STRING) {
- printf("%s ", yytext);
- continue;
- }
- for (s = yytext; c = *s; ++s) {
- switch (c) {
- case '\n':
- t = "\\n";
- goto print_str;
- case '\v':
- t = "\\v";
- goto print_str;
- case '\b':
- t = "\\b";
- goto print_str;
- case '\t':
- t = "\\t";
- goto print_str;
- case '\a':
- t = "\\a";
- print_str:
- fputs(t, stdout);
- break;
- case '\\':
- putchar('\\');
- default:
- if (!isprint(c))
- printf("\\x%x", c);
- else
- putchar(c);
- break;
- }
- }
- putchar(' ');
- }
- putchar('\n');
-}
-
--- a/src/cmd/scc/cc1/decl.c
+++ /dev/null
@@ -1,966 +1,0 @@
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-#define NOSCLASS 0
-
-#define NOREP 0
-#define REP 1
-#define QUIET 1
-#define NOQUIET 0
-
-#define NR_DCL_TYP (NR_DECLARATORS+NR_FUNPARAM)
-#define NR_DCL_SYM (NR_DECLARATORS+NR_FUNPARAM+1)
-
-struct declarators {
- unsigned nr;
- unsigned ns;
- struct decl *dcl;
- unsigned nr_types;
- Type **tpars;
- Symbol **pars;
- struct declarator {
- unsigned char op;
- TINT nelem;
- Symbol *sym;
- Type **tpars;
- Symbol **pars;
- } d [NR_DECLARATORS];
-};
-
-struct decl {
- unsigned ns;
- int sclass;
- int qualifier;
- Symbol *sym;
- Type *type;
- Type *parent;
- Symbol **pars;
- Symbol *bufpars[NR_DCL_SYM];
- Type *buftpars[NR_DCL_TYP];
-};
-
-
-static void
-endfundcl(Type *tp, Symbol **pars)
-{
- if (tp->prop&TK_R && *pars)
- warn("parameter names (without types) in function declaration");
- /*
- * avoid non used warnings in prototypes
- */
- while (*pars)
- (*pars++)->flags |= SUSED;
- popctx();
-}
-
-static void
-push(struct declarators *dp, int op, ...)
-{
- va_list va;
- unsigned n;
- struct declarator *p;
-
- va_start(va, op);
- if ((n = dp->nr++) == NR_DECLARATORS)
- error("too many declarators");
-
- p = &dp->d[n];
- p->op = op;
- p->tpars = NULL;
-
- switch (op) {
- case ARY:
- p->nelem = va_arg(va, TINT);
- break;
- case KRFTN:
- case FTN:
- p->nelem = va_arg(va, unsigned);
- p->tpars = va_arg(va, Type **);
- p->pars = va_arg(va, Symbol **);
- break;
- case IDEN:
- p->sym = va_arg(va, Symbol *);
- break;
- }
- va_end(va);
-}
-
-static int
-pop(struct declarators *dp, struct decl *dcl)
-{
- struct declarator *p;
-
- if (dp->nr == 0)
- return 0;
-
- p = &dp->d[--dp->nr];
- if (p->op == IDEN) {
- dcl->sym = p->sym;
- return 1;
- }
-
- if (dcl->type->op == FTN)
- endfundcl(dcl->type, dcl->pars);
- dcl->pars = p->pars;
-
- dcl->type = mktype(dcl->type, p->op, p->nelem, p->tpars);
- return 1;
-}
-
-static void
-arydcl(struct declarators *dp)
-{
- Node *np = NULL;
- TINT n = 0;
-
- expect('[');
- if (yytoken != ']') {
- if ((np = constexpr()) == NULL) {
- errorp("invalid storage size");
- } else {
- if ((n = np->sym->u.i) <= 0) {
- errorp("array size is not a positive number");
- n = 1;
- }
- freetree(np);
- }
- }
- expect(']');
-
- push(dp, ARY, n);
-}
-
-static int
-empty(Symbol *sym, Type *tp, int param)
-{
- if (!sym->name) {
- sym->type = tp;
- switch (tp->op) {
- default:
- /* warn if it is not a parameter */
- if (!param)
- warn("empty declaration");
- case STRUCT:
- case UNION:
- case ENUM:
- return 1;
- }
- }
- return 0;
-}
-
-static void
-bad_storage(Type *tp, char *name)
-{
- if (tp->op != FTN)
- errorp("incorrect storage class for file-scope declaration");
- else
- errorp("invalid storage class for function '%s'", name);
-}
-
-static Symbol *
-redcl(Symbol *sym, Type *tp, int sclass)
-{
- int flags;
- char *name = sym->name;
-
- if (!eqtype(sym->type, tp, 1)) {
- errorp("conflicting types for '%s'", name);
- return sym;
- }
-
- if (sym->token == TYPEIDEN && sclass != TYPEDEF ||
- sym->token != TYPEIDEN && sclass == TYPEDEF) {
- goto redeclaration;
- }
- if (curctx != GLOBALCTX && tp->op != FTN) {
- /* is it the redeclaration of a local variable? */
- if ((sym->flags & SEXTERN) && sclass == EXTERN)
- return sym;
- goto redeclaration;
- }
-
- flags = sym->flags;
- switch (sclass) {
- case REGISTER:
- case AUTO:
- bad_storage(tp, name);
- break;
- case NOSCLASS:
- if ((flags & SPRIVATE) == 0) {
- if (flags & SEXTERN)
- flags &= ~(SEXTERN|SEMITTED);
- flags |= SGLOBAL;
- break;
- }
- errorp("non-static declaration of '%s' follows static declaration",
- name);
- break;
- case TYPEDEF:
- /* Only C11 allows multiple definitions of a typedef. */
- goto redeclaration;
- case EXTERN:
- break;
- case STATIC:
- if ((flags & (SGLOBAL|SEXTERN)) == 0) {
- flags |= SPRIVATE;
- break;
- }
- errorp("static declaration of '%s' follows non-static declaration",
- name);
- break;
- }
- sym->flags = flags;
-
- return sym;
-
-redeclaration:
- errorp("redeclaration of '%s'", name);
- return sym;
-}
-
-static Symbol *
-identifier(struct decl *dcl)
-{
- Symbol *sym = dcl->sym;
- Type *tp = dcl->type;
- int sclass = dcl->sclass;
- char *name = sym->name;
-
- if (empty(sym, tp, 0))
- return sym;
-
- /* TODO: Add warning about ANSI limits */
- if (!(tp->prop & TDEFINED) &&
- sclass != EXTERN && sclass != TYPEDEF &&
- !(tp->op == ARY && yytoken == '=')) {
- errorp("declared variable '%s' of incomplete type", name);
- }
-
- if (tp->op == FTN) {
- if (sclass == NOSCLASS)
- sclass = EXTERN;
- if (!strcmp(name, "main") && tp->type != inttype) {
- errorp("main shall be defined with a return type of int");
- errorp("please contact __20h__ on irc.freenode.net (#bitreich-en) via IRC");
- }
- }
-
- if (sym->flags & SDECLARED) {
- sym = redcl(dcl->sym, tp, sclass);
- } else {
- int flags = sym->flags | SDECLARED;
-
- sym->type = tp;
-
- switch (sclass) {
- case REGISTER:
- case AUTO:
- if (curctx != GLOBALCTX && tp->op != FTN) {
- flags |= (sclass == REGISTER) ? SREGISTER : SAUTO;
- break;
- }
- bad_storage(tp, name);
- case NOSCLASS:
- if (tp->op == FTN)
- flags |= SEXTERN;
- else
- flags |= (curctx == GLOBALCTX) ? SGLOBAL : SAUTO;
- break;
- case EXTERN:
- flags |= SEXTERN;
- break;
- case STATIC:
- flags |= (curctx == GLOBALCTX) ? SPRIVATE : SLOCAL;
- break;
- case TYPEDEF:
- flags |= STYPEDEF;
- sym->u.token = sym->token = TYPEIDEN;
- break;
- }
- sym->flags = flags;
- }
-
- if (accept('='))
- initializer(sym, sym->type);
- if (!(sym->flags & (SGLOBAL|SEXTERN)) && tp->op != FTN)
- sym->flags |= SDEFINED;
- if (sym->token == IDEN && tp->op != FTN)
- emit(ODECL, sym);
- return sym;
-}
-
-static Symbol *
-parameter(struct decl *dcl)
-{
- Symbol *sym = dcl->sym;
- Type *funtp = dcl->parent, *tp = dcl->type;
- char *name = sym->name;
- int flags;
-
- flags = 0;
- switch (dcl->sclass) {
- case STATIC:
- case EXTERN:
- case AUTO:
- errorp("bad storage class in function parameter");
- break;
- case REGISTER:
- flags |= SREGISTER;
- break;
- case NOSCLASS:
- flags |= SAUTO;
- break;
- }
-
- switch (tp->op) {
- case VOID:
- funtp->n.elem = 1;
- if (dcl->sclass)
- errorp("void as unique parameter may not be qualified");
- return NULL;
- case ARY:
- tp = mktype(tp->type, PTR, 0, NULL);
- break;
- case FTN:
- errorp("incorrect function type for a function parameter");
- return NULL;
- }
- if (!empty(sym, tp, 1)) {
- int isdcl = sym->flags&SDECLARED, isk_r = funtp->prop & TK_R;
- if (isdcl && !isk_r) {
- errorp("redefinition of parameter '%s'", name);
- return NULL;
- }
- if (!isdcl && isk_r) {
- errorp("declaration for parameter '%s' but no such parameter",
- sym->name);
- return NULL;
- }
- sym->flags |= SDECLARED;
- }
-
- sym->type = tp;
- sym->flags &= ~(SAUTO|SREGISTER);
- sym->flags |= flags;
- return sym;
-}
-
-static Symbol *dodcl(int rep,
- Symbol *(*fun)(struct decl *),
- unsigned ns,
- Type *type);
-
-static int
-krpars(struct declarators *dp)
-{
- Symbol *sym;
- int toomany = 0;
- unsigned npars = 0;
-
- do {
- sym = yylval.sym;
- expect(IDEN);
- sym->flags |= SAUTO;
- if ((sym = install(NS_IDEN, sym)) == NULL) {
- errorp("redefinition of parameter '%s'",
- yylval.sym->name);
- continue;
- }
- if (npars < NR_FUNPARAM) {
- ++npars;
- *dp->pars++ = sym;
- continue;
- }
- if (!toomany)
- toomany = 1;
- } while (accept(','));
-
- return toomany;
-}
-
-static unsigned
-krfun(struct declarators *dp)
-{
- int toomany = 0;
-
-
- if (yytoken != ')')
- toomany = krpars(dp);
-
- if (dp->nr_types == NR_DCL_TYP) {
- toomany = 1;
- } else {
- ++dp->nr_types;
- *dp->tpars++ = ellipsistype;
- }
-
- if (toomany)
- errorp("too many parameters in function definition");
- return 1;
-}
-
-static unsigned
-ansifun(struct declarators *dp)
-{
- Symbol *sym;
- unsigned npars, ntype, toomany, distoomany, voidpar;
- Type type, *tp;
-
- type.n.elem = 0;
- type.prop = 0;
- npars = ntype = toomany = distoomany = voidpar = 0;
-
- do {
- if (accept(ELLIPSIS)) {
- if (ntype < 1)
- errorp("a named argument is requiered before '...'");
- if (yytoken != ')')
- errorp("... must be the last parameter");
- sym = NULL;
- tp = ellipsistype;
- } else if ((sym = dodcl(NOREP, parameter, NS_IDEN, &type)) == NULL) {
- if (type.n.elem == 1 && ntype > 1)
- voidpar = 1;
- sym = NULL;
- tp = NULL;
- } else {
- tp = sym->type;
- }
-
- if (sym) {
- if (npars == NR_FUNPARAM) {
- toomany = 1;
- } else {
- npars++;
- *dp->pars++ = sym;
- }
- }
-
- if (tp) {
- if (dp->nr_types == NR_DCL_TYP) {
- toomany = 1;
- } else {
- ntype++;
- dp->nr_types++;
- *dp->tpars++ = tp;
- }
- }
-
- } while (accept(','));
-
- if (toomany == 1)
- errorp("too many parameters in function definition");
- if (voidpar && ntype > 1)
- errorp("'void' must be the only parameter");
- return ntype;
-}
-
-static int
-funbody(Symbol *sym, Symbol *pars[])
-{
- Type *tp;
- Symbol **bp, *p;
-
- if (!sym)
- return 0;
- tp = sym->type;
- if (tp->op != FTN)
- return 0;
-
- switch (yytoken) {
- case '{':
- case TYPE:
- case TYPEIDEN:
- if (curctx != PARAMCTX)
- errorp("nested function declaration");
- if (sym && sym->ns == NS_IDEN)
- break;
- default:
- emit(ODECL, sym);
- endfundcl(tp, pars);
- return 0;
- }
-
- tp->prop |= TFUNDEF;
- curfun = sym;
- if (sym->type->prop & TK_R) {
- while (yytoken != '{') {
- dodcl(REP, parameter, NS_IDEN, sym->type);
- expect(';');
- }
- for (bp = pars; p = *bp; ++bp) {
- if (p->type == NULL) {
- warn("type of '%s' defaults to int", p->name);
- p->type = inttype;
- }
- }
- }
- if (sym->flags & STYPEDEF)
- errorp("function definition declared 'typedef'");
- if (sym->flags & SDEFINED)
- errorp("redefinition of '%s'", sym->name);
- if (sym->flags & SEXTERN) {
- sym->flags &= ~SEXTERN;
- sym->flags |= SGLOBAL;
- }
- sym->flags |= SDEFINED;
- sym->flags &= ~SEMITTED;
- sym->u.pars = pars;
- emit(OFUN, sym);
- compound(NULL, NULL, NULL);
- emit(OEFUN, NULL);
- popctx();
- flushtypes();
- curfun = NULL;
- return 1;
-}
-
-static void
-fundcl(struct declarators *dp)
-{
- Type **types = dp->tpars;
- unsigned ntypes, typefun;
- Symbol **pars = dp->pars;
- unsigned (*fun)(struct declarators *);
-
- pushctx();
- expect('(');
- if (yytoken == ')' || yytoken == IDEN) {
- typefun = KRFTN;
- fun = krfun;
- } else {
- typefun = FTN;
- fun = ansifun;
- }
- ntypes = (*fun)(dp);
- *dp->pars++= NULL;
- expect(')');
-
- push(dp, typefun, ntypes, types, pars);
-}
-
-static void declarator(struct declarators *dp);
-
-static void
-directdcl(struct declarators *dp)
-{
- Symbol *p, *sym;
- static int nested;
-
- if (accept('(')) {
- if (nested == NR_SUBTYPE)
- error("too many declarators nested by parentheses");
- ++nested;
- declarator(dp);
- --nested;
- expect(')');
- } else {
- if (yytoken == IDEN || yytoken == TYPEIDEN) {
- sym = yylval.sym;
- if (p = install(dp->ns, sym)) {
- sym = p;
- sym->flags &= ~SDECLARED;
- }
- next();
- } else {
- sym = newsym(dp->ns, NULL);
- }
- push(dp, IDEN, sym);
- }
-
- for (;;) {
- switch (yytoken) {
- case '(': fundcl(dp); break;
- case '[': arydcl(dp); break;
- default: return;
- }
- }
-}
-
-static void
-declarator(struct declarators *dp)
-{
- unsigned n;
-
- for (n = 0; accept('*'); ++n) {
- while (accept(TQUALIFIER))
- ;
- }
-
- directdcl(dp);
-
- while (n--)
- push(dp, PTR);
-}
-
-static Type *structdcl(void), *enumdcl(void);
-
-static Type *
-specifier(int *sclass, int *qualifier)
-{
- Type *tp = NULL;
- unsigned spec, qlf, sign, type, cls, size;
-
- spec = qlf = sign = type = cls = size = 0;
-
- for (;;) {
- unsigned *p = NULL;
- Type *(*dcl)(void) = NULL;
-
- switch (yytoken) {
- case SCLASS:
- p = &cls;
- break;
- case TQUALIFIER:
- qlf |= yylval.token;
- next();
- continue;
- case TYPEIDEN:
- if (type)
- goto return_type;
- tp = yylval.sym->type;
- p = &type;
- break;
- case TYPE:
- switch (yylval.token) {
- case ENUM:
- dcl = enumdcl;
- p = &type;
- break;
- case STRUCT:
- case UNION:
- dcl = structdcl;
- p = &type;
- break;
- case VA_LIST:
- case VOID:
- case BOOL:
- case CHAR:
- case INT:
- case FLOAT:
- case DOUBLE:
- p = &type;
- break;
- case SIGNED:
- case UNSIGNED:
- p = &sign;
- break;
- case LONG:
- if (size == LONG) {
- yylval.token = LLONG;
- size = 0;
- }
- case SHORT:
- p = &size;
- break;
- }
- break;
- default:
- goto return_type;
- }
- if (*p)
- errorp("invalid type specification");
- *p = yylval.token;
- if (dcl) {
- if (size || sign)
- errorp("invalid type specification");
- tp = (*dcl)();
- goto return_type;
- } else {
- next();
- }
- spec = 1;
- }
-
-return_type:
- *sclass = cls;
- *qualifier = qlf;
- if (!tp) {
- if (spec) {
- tp = ctype(type, sign, size);
- } else {
- if (curctx != GLOBALCTX)
- unexpected();
- warn("type defaults to 'int' in declaration");
- tp = inttype;
- }
- }
- return tp;
-}
-
-static Symbol *
-newtag(void)
-{
- Symbol *sym;
- int ns, op, tag = yylval.token;
- static unsigned tpns = NS_STRUCTS;
-
- ns = namespace;
- namespace = NS_TAG;
- next();
- namespace = ns;
-
- switch (yytoken) {
- case IDEN:
- case TYPEIDEN:
- sym = yylval.sym;
- if ((sym->flags & SDECLARED) == 0)
- install(NS_TAG, yylval.sym);
- next();
- break;
- default:
- sym = newsym(NS_TAG, NULL);
- break;
- }
- if (!sym->type) {
- Type *tp;
-
- if (tpns == NS_STRUCTS + NR_MAXSTRUCTS)
- error("too many tags declared");
- tp = mktype(NULL, tag, 0, NULL);
- tp->ns = tpns++;
- sym->type = tp;
- tp->tag = sym;
- DBG("declared tag '%s' with ns = %d\n",
- (sym->name) ? sym->name : "anonymous", tp->ns);
- }
-
- if ((op = sym->type->op) != tag && op != INT)
- error("'%s' defined as wrong kind of tag", sym->name);
- return sym;
-}
-
-static void fieldlist(Type *tp);
-
-static Type *
-structdcl(void)
-{
- Symbol *sym;
- Type *tp;
- static int nested;
- int ns;
-
- sym = newtag();
- tp = sym->type;
-
- if (!accept('{'))
- return tp;
-
- ns = namespace;
- namespace = tp->ns;
-
- if (tp->prop & TDEFINED && sym->ctx == curctx)
- error("redefinition of struct/union '%s'", sym->name);
-
- if (nested == NR_STRUCT_LEVEL)
- error("too many levels of nested structure or union definitions");
-
- ++nested;
- while (yytoken != '}') {
- fieldlist(tp);
- }
- --nested;
-
- deftype(tp);
- namespace = ns;
- expect('}');
- return tp;
-}
-
-static Type *
-enumdcl(void)
-{
- Type *tp;
- Symbol *sym, *tagsym;
- int ns, val, toomany;
- unsigned nctes;
-
- ns = namespace;
- tagsym = newtag();
- tp = tagsym->type;
-
- if (!accept('{'))
- goto restore_name;
- if (tp->prop & TDEFINED)
- errorp("redefinition of enumeration '%s'", tagsym->name);
- deftype(tp);
- namespace = NS_IDEN;
-
- /* TODO: check incorrect values in val */
- for (nctes = val = 0; yytoken != '}'; ++nctes, ++val) {
- if (yytoken != IDEN)
- unexpected();
- sym = yylval.sym;
- next();
- if (nctes == NR_ENUM_CTES && !toomany) {
- errorp("too many enum constants in a single enum");
- toomany = 1;
- }
- if (accept('=')) {
- Node *np = constexpr();
-
- if (np == NULL)
- errorp("invalid enumeration value");
- else
- val = np->sym->u.i;
- freetree(np);
- }
- if ((sym = install(NS_IDEN, sym)) == NULL) {
- errorp("'%s' redeclared as different kind of symbol",
- yytext);
- } else {
- sym->u.i = val;
- sym->flags |= SCONSTANT;
- sym->type = inttype;
- }
- if (!accept(','))
- break;
- }
- expect('}');
-
-restore_name:
- namespace = ns;
- return tp;
-}
-
-static Symbol *
-type(struct decl *dcl)
-{
- Symbol *sym = dcl->sym;
-
- if (dcl->sclass)
- error("class storage in type name");
- if (sym->name)
- error("unexpected identifier in type name");
- sym->type = dcl->type;
-
- return sym;
-}
-
-static Symbol *
-field(struct decl *dcl)
-{
- static char *anon = "<anonymous>";
- Symbol *sym = dcl->sym;
- char *name = (sym->name) ? sym->name : anon;
- Type *structp = dcl->parent, *tp = dcl->type;
- TINT n = structp->n.elem;
- int err = 0;
-
- if (accept(':')) {
- Node *np;
- TINT n;
-
- if ((np = constexpr()) == NULL) {
- unexpected();
- n = 0;
- } else {
- n = np->sym->u.i;
- freetree(np);
- }
- if (n == 0 && name != anon)
- errorp("zero width for bit-field '%s'", name);
- if (tp != booltype && tp != inttype && tp != uinttype)
- errorp("bit-field '%s' has invalid type", name);
- if (n < 0)
- errorp("negative width in bit-field '%s'", name);
- else if (n > tp->size*8)
- errorp("width of '%s' exceeds its type", name);
- } else if (empty(sym, tp, 0)) {
- return sym;
- }
-
- if (tp->op == FTN) {
- errorp("invalid type '%s' in struct/union", name);
- err = 1;
- }
- if (dcl->sclass) {
- errorp("storage class in struct/union field '%s'", name);
- err = 1;
- }
- if (!(tp->prop & TDEFINED)) {
- error("field '%s' has incomplete type", name);
- err = 1;
- }
- if (err)
- return sym;
-
- if (sym->flags & SDECLARED)
- error("duplicated member '%s'", name);
- sym->flags |= SFIELD|SDECLARED;
- sym->type = tp;
-
- if (n == NR_FIELDS)
- error("too many fields in struct/union");
- DBG("New field '%s' in namespace %d\n", name, structp->ns);
- structp->p.fields = xrealloc(structp->p.fields, ++n * sizeof(*sym));
- structp->p.fields[n-1] = sym;
- structp->n.elem = n;
-
- return sym;
-}
-
-static Symbol *
-dodcl(int rep, Symbol *(*fun)(struct decl *), unsigned ns, Type *parent)
-{
- Symbol *sym;
- Type *base;
- struct decl dcl;
- struct declarators stack;
-
- dcl.ns = ns;
- dcl.parent = parent;
- base = specifier(&dcl.sclass, &dcl.qualifier);
-
- do {
- dcl.type = base;
- stack.nr_types = stack.nr = 0;
- stack.tpars = dcl.buftpars;
- stack.pars = dcl.bufpars;
- stack.dcl = &dcl;
- stack.ns = ns;
-
- declarator(&stack);
-
- while (pop(&stack, &dcl))
- ;
- sym = (*fun)(&dcl);
- if (funbody(sym, dcl.pars))
- return sym;
- } while (rep && accept(','));
-
- return sym;
-}
-
-void
-decl(void)
-{
- Symbol *sym;
-
- if (accept(';'))
- return;
- sym = dodcl(REP, identifier, NS_IDEN, NULL);
- if (sym->type->prop & TFUNDEF)
- return;
- expect(';');
-}
-
-static void
-fieldlist(Type *tp)
-{
- if (yytoken != ';')
- dodcl(REP, field, tp->ns, tp);
- expect(';');
-}
-
-Type *
-typename(void)
-{
- return dodcl(NOREP, type, NS_DUMMY, NULL)->type;
-}
--- a/src/cmd/scc/cc1/deps.mk
+++ /dev/null
@@ -1,44 +1,0 @@
-#deps
-./builtin.o: $(INCDIR)/scc/scc/scc.h
-./builtin.o: ./cc1.h
-./code.o: $(INCDIR)/scc/scc/scc.h
-./code.o: ./cc1.h
-./cpp.o: $(INCDIR)/scc/scc/cstd.h
-./cpp.o: $(INCDIR)/scc/scc/scc.h
-./cpp.o: ./cc1.h
-./decl.o: $(INCDIR)/scc/scc/cstd.h
-./decl.o: $(INCDIR)/scc/scc/scc.h
-./decl.o: ./cc1.h
-./error.o: $(INCDIR)/scc/scc/scc.h
-./error.o: ./cc1.h
-./expr.o: $(INCDIR)/scc/scc/cstd.h
-./expr.o: $(INCDIR)/scc/scc/scc.h
-./expr.o: ./cc1.h
-./fold.o: $(INCDIR)/scc/scc/scc.h
-./fold.o: ./cc1.h
-./init.o: $(INCDIR)/scc/scc/cstd.h
-./init.o: $(INCDIR)/scc/scc/scc.h
-./init.o: ./cc1.h
-./lex.o: $(INCDIR)/scc/scc/cstd.h
-./lex.o: $(INCDIR)/scc/scc/scc.h
-./lex.o: ./cc1.h
-./main.o: $(INCDIR)/scc/scc/arg.h
-./main.o: $(INCDIR)/scc/scc/scc.h
-./main.o: ./cc1.h
-./stmt.o: $(INCDIR)/scc/scc/cstd.h
-./stmt.o: $(INCDIR)/scc/scc/scc.h
-./stmt.o: ./cc1.h
-./symbol.o: $(INCDIR)/scc/scc/cstd.h
-./symbol.o: $(INCDIR)/scc/scc/scc.h
-./symbol.o: ./cc1.h
-./target/amd64-sysv/arch.o: $(INCDIR)/scc/scc/scc.h
-./target/amd64-sysv/arch.o: ./target/amd64-sysv/../../cc1.h
-./target/arm64-sysv/arch.o: $(INCDIR)/scc/scc/scc.h
-./target/arm64-sysv/arch.o: ./target/arm64-sysv/../../cc1.h
-./target/i386-sysv/arch.o: $(INCDIR)/scc/scc/scc.h
-./target/i386-sysv/arch.o: ./target/i386-sysv/../../cc1.h
-./target/z80-scc/arch.o: $(INCDIR)/scc/scc/scc.h
-./target/z80-scc/arch.o: ./target/z80-scc/../../cc1.h
-./types.o: $(INCDIR)/scc/scc/cstd.h
-./types.o: $(INCDIR)/scc/scc/scc.h
-./types.o: ./cc1.h
--- a/src/cmd/scc/cc1/error.c
+++ /dev/null
@@ -1,84 +1,0 @@
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <scc/scc.h>
-#include "cc1.h"
-
-#define MAXERRNUM 10
-
-extern int failure;
-static unsigned nerrors;
-
-static void
-warn_error(int flag, char *fmt, va_list va)
-{
- if (flag == 0)
- return;
- fprintf(stderr, "%s:%u: %s: ",
- filenam, lineno,
- (flag < 0) ? "error" : "warning");
- vfprintf(stderr, fmt, va);
- putc('\n', stderr);
-
- if (flag < 0) {
- if (!failure)
- fclose(stdout);
- failure = 1;
- if (++nerrors == MAXERRNUM) {
- fputs("too many errors\n", stderr);
- exit(1);
- }
- }
-}
-
-void
-warn(char *fmt, ...)
-{
- extern int warnings;
-
- va_list va;
- va_start(va, fmt);
- warn_error(warnings, fmt, va);
- va_end(va);
-}
-
-void
-error(char *fmt, ...)
-{
- va_list va;
-
- va_start(va, fmt);
- warn_error(-1, fmt, va);
- va_end(va);
- exit(1);
- discard();
-}
-
-void
-errorp(char *fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
- warn_error(-1, fmt, va);
- va_end(va);
-}
-
-void
-cpperror(char *fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
- warn_error(-1, fmt, va);
- va_end(va);
-
- /* discard input until the end of the line */
- *input->p = '\0';
- next();
-}
-
-void
-unexpected(void)
-{
- error("unexpected '%s'", yytext);
-}
--- a/src/cmd/scc/cc1/expr.c
+++ /dev/null
@@ -1,1184 +1,0 @@
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-#define XCHG(lp, rp, np) (np = lp, lp = rp, rp = np)
-
-static Node *xexpr(void), *xassign(void);
-
-int
-cmpnode(Node *np, TUINT val)
-{
- Symbol *sym;
- Type *tp;
- TUINT mask, nodeval;
-
- if (!np || !(np->flags & NCONST) || !np->sym)
- return 0;
- sym = np->sym;
- tp = sym->type;
-
- switch (tp->op) {
- case PTR:
- case INT:
- mask = (val > 1) ? ones(np->type->size) : -1;
- nodeval = (tp->prop & TSIGNED) ? sym->u.i : sym->u.u;
- return (nodeval & mask) == (val & mask);
- case FLOAT:
- return sym->u.f == val;
- }
- return 0;
-}
-
-static Node *
-promote(Node *np)
-{
- Type *tp;
- Node *new;
- struct limits *lim, *ilim;
-
- tp = np->type;
-
- switch (tp->op) {
- case ENUM:
- case INT:
- if (tp->n.rank >= inttype->n.rank)
- return np;
- lim = getlimits(tp);
- ilim = getlimits(inttype);
- tp = (lim->max.i <= ilim->max.i) ? inttype : uinttype;
- break;
- case FLOAT:
- /* TODO: Add support for C99 float math */
- tp = doubletype;
- break;
- default:
- abort();
- }
- if ((new = convert(np, tp, 1)) != NULL)
- return new;
- return np;
-}
-
-static void
-arithconv(Node **p1, Node **p2)
-{
- int to = 0, s1, s2;
- unsigned r1, r2;
- Type *tp1, *tp2;
- Node *np1, *np2;
- struct limits *lp1, *lp2;
-
- np1 = promote(*p1);
- np2 = promote(*p2);
-
- tp1 = np1->type;
- tp2 = np2->type;
-
- if (tp1 == tp2)
- goto set_p1_p2;
-
- s1 = (tp1->prop & TSIGNED) != 0;
- r1 = tp1->n.rank;
- lp1 = getlimits(tp1);
-
- s2 = (tp2->prop & TSIGNED) != 0;
- r2 = tp2->n.rank;
- lp2 = getlimits(tp2);
-
- if (s1 == s2 || tp1->op == FLOAT || tp2->op == FLOAT) {
- to = r1 - r2;
- } else if (!s1) {
- if (r1 >= r2 || lp1->max.i >= lp2->max.i)
- to = 1;
- else
- to = -1;
- } else {
- if (r2 >= r1 || lp2->max.i >= lp1->max.i)
- to = -1;
- else
- to = 1;
- }
-
- if (to > 0)
- np2 = convert(np2, tp1, 1);
- else if (to < 0)
- np1 = convert(np1, tp2, 1);
-
-set_p1_p2:
- *p1 = np1;
- *p2 = np2;
-}
-
-static int
-null(Node *np)
-{
- if (np->type != pvoidtype || np->op != OCAST)
- return 0;
-
- np = np->left;
- if (np->type != inttype)
- return 0;
-
- return cmpnode(np, 0);
-}
-
-static Node *
-chkternary(Node *yes, Node *no)
-{
- /*
- * FIXME:
- * We are ignoring type qualifiers here,
- * but the standard has strong rules about this.
- * take a look to 6.5.15
- */
-
- if (!eqtype(yes->type, no->type, 1)) {
- if ((yes->type->prop & TARITH) && (no->type->prop & TARITH)) {
- arithconv(&yes, &no);
- } else if (yes->type->op != PTR && no->type->op != PTR) {
- goto wrong_type;
- } else {
- /* convert integer 0 to NULL */
- if ((yes->type->prop & TINTEGER) && cmpnode(yes, 0))
- yes = convert(yes, pvoidtype, 0);
- if ((no->type->prop & TINTEGER) && cmpnode(no, 0))
- no = convert(no, pvoidtype, 0);
- /*
- * At this point the type of both should be
- * a pointer to something, or we have don't
- * compatible types
- */
- if (yes->type->op != PTR || no->type->op != PTR)
- goto wrong_type;
- /*
- * If we have a null pointer constant then
- * convert to the another type
- */
- if (null(yes))
- yes = convert(yes, no->type, 0);
- if (null(no))
- no = convert(no, yes->type, 0);
-
- if (!eqtype(yes->type, no->type, 1))
- goto wrong_type;
- }
- }
- return node(OCOLON, yes->type, yes, no);
-
-wrong_type:
- errorp("type mismatch in conditional expression");
- freetree(yes);
- freetree(no);
- return constnode(zero);
-}
-
-static void
-chklvalue(Node *np)
-{
- if (!(np->flags & NLVAL))
- errorp("lvalue required in operation");
- if (np->type == voidtype)
- errorp("invalid use of void expression");
-}
-
-Node *
-decay(Node *np)
-{
- Node *new;
- Type *tp = np->type;
-
- switch (tp->op) {
- case ARY:
- tp = tp->type;
- if (np->op == OPTR) {
- new = np->left;
- free(np);
- new->type = mktype(tp, PTR, 0, NULL);
- return new;
- }
- case FTN:
- new = node(OADDR, mktype(tp, PTR, 0, NULL), np, NULL);
- if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE))
- new->flags |= NCONST;
- return new;
- default:
- return np;
- }
-}
-
-static Node *
-integerop(int op, Node *lp, Node *rp)
-{
- if (!(lp->type->prop & TINTEGER) || !(rp->type->prop & TINTEGER))
- error("operator requires integer operands");
- arithconv(&lp, &rp);
- return node(op, lp->type, lp, rp);
-}
-
-static Node *
-integeruop(int op, Node *np)
-{
- if (!(np->type->prop & TINTEGER))
- error("unary operator requires integer operand");
- np = promote(np);
- return node(op, np->type, np, NULL);
-}
-
-static Node *
-numericaluop(int op, Node *np)
-{
- if (!(np->type->prop & TARITH))
- error("unary operator requires numerical operand");
- np = promote(np);
- return node(op, np->type, np, NULL);
-}
-
-Node *
-convert(Node *np, Type *newtp, int iscast)
-{
- Type *oldtp = np->type;
-
- if (eqtype(newtp, oldtp, 0))
- return np;
-
- switch (oldtp->op) {
- case ENUM:
- case INT:
- case FLOAT:
- switch (newtp->op) {
- case PTR:
- if (oldtp->op == FLOAT || !cmpnode(np, 0) && !iscast)
- return NULL;
- case INT:
- case FLOAT:
- case ENUM:
- break;
- default:
- return NULL;
- }
- break;
- case PTR:
- switch (newtp->op) {
- case ENUM:
- case INT:
- case VOID:
- if (!iscast)
- return NULL;
- break;
- case PTR:
- if (eqtype(newtp, oldtp, 1) ||
- iscast ||
- newtp == pvoidtype || oldtp == pvoidtype) {
- np->type = newtp;
- return np;
- }
- default:
- return NULL;
- }
- break;
- default:
- return NULL;
- }
- return node(OCAST, newtp, np, NULL);
-}
-
-static Node *
-parithmetic(int op, Node *lp, Node *rp)
-{
- Type *tp;
- Node *size, *np;
-
- if (lp->type->op != PTR)
- XCHG(lp, rp, np);
-
- tp = rp->type;
- if (tp->op == PTR && !(tp->type->prop & TDEFINED))
- goto incomplete;
- tp = lp->type;
- if (!(tp->type->prop & TDEFINED))
- goto incomplete;
- size = sizeofnode(tp->type);
-
- if (op == OSUB && BTYPE(rp) == PTR) {
- if ((rp = convert(rp, lp->type, 0)) == NULL)
- goto incorrect;
- lp = node(OSUB, pdifftype, lp, rp);
- return node(ODIV, inttype, lp, size);
- }
- if (!(rp->type->prop & TINTEGER))
- goto incorrect;
-
- rp = convert(promote(rp), sizettype, 0);
- rp = node(OMUL, sizettype, rp, size);
- rp = convert(rp, tp, 1);
-
- return node(op, tp, lp, rp);
-
-incomplete:
- errorp("invalid use of undefined type");
- return lp;
-incorrect:
- errorp("incorrect arithmetic operands");
- return lp;
-
-}
-
-static Node *
-arithmetic(int op, Node *lp, Node *rp)
-{
- Type *ltp = lp->type, *rtp = rp->type;
-
- if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) {
- arithconv(&lp, &rp);
- return node(op, lp->type, lp, rp);
- } else if ((ltp->op == PTR || rtp->op == PTR)) {
- switch (op) {
- case OADD:
- case OSUB:
- case OA_ADD:
- case OA_SUB:
- case OINC:
- case ODEC:
- return parithmetic(op, lp, rp);
- }
- }
- errorp("incorrect arithmetic operands");
-}
-
-static Node *
-pcompare(int op, Node *lp, Node *rp)
-{
- Node *np;
-
- if (lp->type->prop & TINTEGER)
- XCHG(lp, rp, np);
- else if (eqtype(lp->type, pvoidtype, 1))
- XCHG(lp, rp, np);
-
- if ((np = convert(rp, lp->type, 0)) != NULL)
- rp = np;
- else
- errorp("incompatible types in comparison");
- return convert(node(op, pvoidtype, lp, rp), inttype, 1);
-}
-
-static Node *
-compare(int op, Node *lp, Node *rp)
-{
- Type *ltp, *rtp;
-
- ltp = lp->type;
- rtp = rp->type;
-
- if (ltp->op == PTR || rtp->op == PTR) {
- return pcompare(op, rp, lp);
- } else if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) {
- arithconv(&lp, &rp);
- return convert(node(op, lp->type, lp, rp), inttype, 1);;
- } else {
- errorp("incompatible types in comparison");
- freetree(lp);
- freetree(rp);
- return constnode(zero);
- }
-}
-
-int
-negop(int op)
-{
- switch (op) {
- case OEQ: return ONE;
- case ONE: return OEQ;
- case OLT: return OGE;
- case OGE: return OLT;
- case OLE: return OGT;
- case OGT: return OLE;
- default: abort();
- }
- return op;
-}
-
-static Node *
-exp2cond(Node *np, int neg)
-{
- if (np->type->prop & TAGGREG) {
- errorp("used struct/union type value where scalar is required");
- return constnode(zero);
- }
- switch (np->op) {
- case ONEG:
- case OOR:
- case OAND:
- return (neg) ? node(ONEG, inttype, np, NULL) : np;
- case OEQ:
- case ONE:
- case OLT:
- case OGE:
- case OLE:
- case OGT:
- if (neg)
- np->op = negop(np->op);
- return np;
- default:
- return compare((neg) ? OEQ : ONE, np, constnode(zero));
- }
-}
-
-static Node *
-logic(int op, Node *lp, Node *rp)
-{
- lp = exp2cond(lp, 0);
- rp = exp2cond(rp, 0);
- return node(op, inttype, lp, rp);
-}
-
-static Node *
-field(Node *np)
-{
- Symbol *sym;
-
- namespace = np->type->ns;
- next();
- namespace = NS_IDEN;
-
- sym = yylval.sym;
- if (yytoken != IDEN)
- unexpected();
- next();
-
- if (!(np->type->prop & TAGGREG)) {
- errorp("request for member '%s' in something not a structure or union",
- yylval.sym->name);
- goto free_np;
- }
- if ((sym->flags & SDECLARED) == 0) {
- errorp("incorrect field in struct/union");
- goto free_np;
- }
- np = node(OFIELD, sym->type, np, varnode(sym));
- np->flags |= NLVAL;
- return np;
-
-free_np:
- freetree(np);
- return constnode(zero);
-}
-
-static Node *
-content(int op, Node *np)
-{
- if (BTYPE(np) != PTR) {
- errorp("invalid argument of memory indirection");
- } else {
- if (np->op == OADDR) {
- Node *new = np->left;
- new->type = np->type->type;
- free(np);
- np = new;
- } else {
- np = node(op, np->type->type, np, NULL);
- }
- np->flags |= NLVAL;
- }
- return np;
-}
-
-static Node *
-array(Node *lp, Node *rp)
-{
- Type *tp;
- Node *np;
-
- if (!(lp->type->prop & TINTEGER) && !(rp->type->prop & TINTEGER))
- error("array subscript is not an integer");
- np = arithmetic(OADD, lp, rp);
- tp = np->type;
- if (tp->op != PTR)
- errorp("subscripted value is neither array nor pointer");
- return content(OPTR, np);
-}
-
-static Node *
-assignop(int op, Node *lp, Node *rp)
-{
- if ((rp = convert(rp, lp->type, 0)) == NULL) {
- errorp("incompatible types when assigning");
- return lp;
- }
-
- return node(op, lp->type, lp, rp);
-}
-
-static Node *
-incdec(Node *np, int op)
-{
- Type *tp = np->type;
- Node *inc;
-
- chklvalue(np);
- np->flags |= NEFFECT;
-
- if (!(tp->prop & TDEFINED)) {
- errorp("invalid use of undefined type");
- return np;
- } else if (tp->op == PTR && !(tp->type->prop & TDEFINED)) {
- errorp("%s of pointer to an incomplete type",
- (op == OINC || op == OA_ADD) ? "increment" : "decrement");
- return np;
- } else if (tp->op == PTR || (tp->prop & TARITH)) {
- inc = constnode(one);
- } else {
- errorp("wrong type argument to increment or decrement");
- return np;
- }
- return arithmetic(op, np, inc);
-}
-
-static Node *
-address(int op, Node *np)
-{
- Node *new;
-
- /*
- * ansi c accepts & applied to a function name, and it generates
- * a function pointer
- */
- if (np->op == OSYM) {
- if (np->type->op == FTN)
- return decay(np);
- if (np->type->op == ARY)
- goto dont_check_lvalue;
- }
- chklvalue(np);
-
-dont_check_lvalue:
- if (np->sym && (np->sym->flags & SREGISTER))
- errorp("address of register variable '%s' requested", yytext);
- new = node(op, mktype(np->type, PTR, 0, NULL), np, NULL);
- if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE))
- new->flags |= NCONST;
- return new;
-}
-
-static Node *
-negation(int op, Node *np)
-{
- if (!(np->type->prop & TARITH) && np->type->op != PTR) {
- errorp("invalid argument of unary '!'");
- return constnode(zero);
- }
- return exp2cond(np, 1);
-}
-
-static Symbol *
-notdefined(Symbol *sym)
-{
- int isdef;
-
- if (namespace == NS_CPP && !strcmp(sym->name, "defined")) {
- disexpand = 1;
- next();
- expect('(');
- sym = yylval.sym;
- expect(IDEN);
- expect(')');
-
- isdef = (sym->flags & SDECLARED) != 0;
- sym = newsym(NS_IDEN, NULL);
- sym->type = inttype;
- sym->flags |= SCONSTANT;
- sym->u.i = isdef;
- disexpand = 0;
- return sym;
- }
- errorp("'%s' undeclared", yytext);
- sym->type = inttype;
- return install(sym->ns, yylval.sym);
-}
-
-static Symbol *
-adjstrings(Symbol *sym)
-{
- char *s, *t;
- size_t len, n;
- Type *tp;
-
- tp = sym->type;
- s = sym->u.s;
- for (len = strlen(s);; len += n) {
- next();
- if (yytoken != STRING)
- break;
- t = yylval.sym->u.s;
- n = strlen(t);
- s = xrealloc(s, len + n + 1);
- memcpy(s+len, t, n);
- s[len + n] = '\0';
- killsym(yylval.sym);
- }
- ++len;
- if (tp->n.elem != len) {
- sym->type = mktype(chartype, ARY, len, NULL);
- sym->u.s = s;
- }
- return sym;
-}
-
-/*************************************************************
- * grammar functions *
- *************************************************************/
-static Node *
-primary(void)
-{
- Node *np;
- Symbol *sym;
- Node *(*fun)(Symbol *);
-
- sym = yylval.sym;
- switch (yytoken) {
- case STRING:
- np = constnode(adjstrings(sym));
- sym->flags |= SHASINIT;
- emit(ODECL, sym);
- emit(OINIT, np);
- return varnode(sym);
- case BUILTIN:
- fun = sym->u.fun;
- next();
- expect('(');
- np = (*fun)(sym);
- expect(')');
-
- /* do not call to next */
- return np;
- case CONSTANT:
- np = constnode(sym);
- break;
- case IDEN:
- assert((sym->flags & SCONSTANT) == 0);
- if ((sym->flags & SDECLARED) == 0) {
- if (namespace == NS_CPP) {
- np = constnode(zero);
- break;
- }
- sym = notdefined(sym);
- }
- sym->flags |= SUSED;
- np = varnode(sym);
- break;
- default:
- unexpected();
- }
- next();
-
- return np;
-}
-
-static Node *
-arguments(Node *np)
-{
- int toomany, n, op;
- Node *par = NULL, *arg;
- Type *argtype, **targs, *tp = np->type, *rettype;
-
- if (tp->op == PTR && tp->type->op == FTN) {
- np = content(OPTR, np);
- tp = np->type;
- }
- if (tp->op != FTN) {
- targs = (Type *[]) {ellipsistype};
- n = 1;
- rettype = inttype;
- errorp("function or function pointer expected");
- } else {
- targs = tp->p.pars;
- n = tp->n.elem;
- rettype = tp->type;
- }
-
- expect('(');
- if (yytoken == ')')
- goto no_pars;
- toomany = 0;
-
- do {
- arg = xassign();
- argtype = *targs;
- if (argtype == ellipsistype) {
- n = 0;
- switch (arg->type->op) {
- case INT:
- arg = promote(arg);
- break;
- case FLOAT:
- if (arg->type == floattype)
- arg = convert(arg, doubletype, 1);
- break;
- }
- par = node(OPAR, arg->type, par, arg);
- continue;
- }
- if (--n < 0) {
- if (!toomany)
- errorp("too many arguments in function call");
- toomany = 1;
- continue;
- }
- ++targs;
- if ((arg = convert(arg, argtype, 0)) != NULL) {
- par = node(OPAR, arg->type, par, arg);
- continue;
- }
- errorp("incompatible type for argument %d in function call",
- tp->n.elem - n + 1);
- } while (accept(','));
-
-no_pars:
- expect(')');
- if (n > 0 && *targs != ellipsistype)
- errorp("too few arguments in function call");
-
- op = (tp->prop&TELLIPSIS) ? OCALLE : OCALL;
- return node(op, rettype, np, par);
-}
-
-static Node *unary(int);
-
-static Type *
-typeof(Node *np)
-{
- Type *tp;
-
- if (np == NULL)
- unexpected();
- tp = np->type;
- freetree(np);
- return tp;
-}
-
-static Type *
-sizeexp(void)
-{
- Type *tp;
-
- expect('(');
- switch (yytoken) {
- case TYPE:
- case TYPEIDEN:
- tp = typename();
- break;
- default:
- tp = typeof(unary(0));
- break;
- }
- expect(')');
- return tp;
-}
-
-static Node *
-postfix(Node *lp)
-{
- Node *rp;
-
- for (;;) {
- switch (yytoken) {
- case '[':
- case DEC:
- case INC:
- case INDIR:
- case '.':
- case '(':
- lp = decay(lp);
- switch (yytoken) {
- case '[':
- next();
- rp = xexpr();
- expect(']');
- lp = array(lp, rp);
- break;
- case DEC:
- case INC:
- lp = incdec(lp, (yytoken == INC) ? OINC : ODEC);
- next();
- break;
- case INDIR:
- lp = content(OPTR, lp);
- case '.':
- lp = field(lp);
- break;
- case '(':
- lp = arguments(lp);
- lp->flags |= NEFFECT;
- break;
- }
- break;
- default:
- return lp;
- }
- }
-}
-
-static Node *
-defined(void)
-{
- Symbol *sym;
- int paren;
-
- disexpand = 1;
- next();
- paren = accept('(');
- if (yytoken != IDEN && yytoken != TYPEIDEN)
- cpperror("operator 'defined' requires an identifier");
- if (yytoken == TYPEIDEN || !(yylval.sym->flags & SDECLARED))
- sym = zero;
- else
- sym = one;
- disexpand = 0;
- next();
- if (paren)
- expect(')');
- return constnode(sym);
-}
-
-static Node *cast(int);
-
-static Node *
-unary(int needdecay)
-{
- Node *(*fun)(int, Node *), *np;
- int op;
- Type *tp;
-
- switch (yytoken) {
- case '!': op = 0; fun = negation; break;
- case '+': op = OADD; fun = numericaluop; break;
- case '-': op = OSNEG; fun = numericaluop; break;
- case '~': op = OCPL; fun = integeruop; break;
- case '&': op = OADDR; fun = address; break;
- case '*': op = OPTR; fun = content; break;
- case SIZEOF:
- next();
- tp = (yytoken == '(') ? sizeexp() : typeof(unary(0));
- if (!(tp->prop & TDEFINED))
- errorp("sizeof applied to an incomplete type");
- return sizeofnode(tp);
- case INC:
- case DEC:
- op = (yytoken == INC) ? OA_ADD : OA_SUB;
- next();
- np = incdec(unary(1), op);
- goto chk_decay;
- case IDEN:
- case TYPEIDEN:
- if (lexmode == CPPMODE && !strcmp(yylval.sym->name, "defined"))
- return defined();
- default:
- np = postfix(primary());
- goto chk_decay;
- }
-
- next();
- np = (*fun)(op, cast(op != OADDR));
-
-chk_decay:
- if (needdecay)
- np = decay(np);
- return np;
-}
-
-static Node *
-cast(int needdecay)
-{
- Node *lp, *rp;
- Type *tp;
- static int nested;
-
- if (!accept('('))
- return unary(needdecay);
-
- switch (yytoken) {
- case TQUALIFIER:
- case TYPE:
- case TYPEIDEN:
- tp = typename();
- expect(')');
-
- if (yytoken == '{')
- return initlist(tp);
-
- switch (tp->op) {
- case ARY:
- error("cast specifies an array type");
- default:
- lp = cast(needdecay);
- if ((rp = convert(lp, tp, 1)) == NULL)
- error("bad type conversion requested");
- rp->flags &= ~NLVAL;
- rp->flags |= lp->flags & NLVAL;
- }
- break;
- default:
- if (nested == NR_SUBEXPR)
- error("too many expressions nested by parentheses");
- ++nested;
- rp = xexpr();
- --nested;
- expect(')');
- rp = postfix(rp);
- break;
- }
-
- return rp;
-}
-
-static Node *
-mul(void)
-{
- Node *np, *(*fun)(int, Node *, Node *);
- int op;
-
- np = cast(1);
- for (;;) {
- switch (yytoken) {
- case '*': op = OMUL; fun = arithmetic; break;
- case '/': op = ODIV; fun = arithmetic; break;
- case '%': op = OMOD; fun = integerop; break;
- default: return np;
- }
- next();
- np = (*fun)(op, np, cast(1));
- }
-}
-
-static Node *
-add(void)
-{
- int op;
- Node *np;
-
- np = mul();
- for (;;) {
- switch (yytoken) {
- case '+': op = OADD; break;
- case '-': op = OSUB; break;
- default: return np;
- }
- next();
- np = arithmetic(op, np, mul());
- }
-}
-
-static Node *
-shift(void)
-{
- int op;
- Node *np;
-
- np = add();
- for (;;) {
- switch (yytoken) {
- case SHL: op = OSHL; break;
- case SHR: op = OSHR; break;
- default: return np;
- }
- next();
- np = integerop(op, np, add());
- }
-}
-
-static Node *
-relational(void)
-{
- int op;
- Node *np;
-
- np = shift();
- for (;;) {
- switch (yytoken) {
- case '<': op = OLT; break;
- case '>': op = OGT; break;
- case GE: op = OGE; break;
- case LE: op = OLE; break;
- default: return np;
- }
- next();
- np = compare(op, np, shift());
- }
-}
-
-static Node *
-eq(void)
-{
- int op;
- Node *np;
-
- np = relational();
- for (;;) {
- switch (yytoken) {
- case EQ: op = OEQ; break;
- case NE: op = ONE; break;
- default: return np;
- }
- next();
- np = compare(op, np, relational());
- }
-}
-
-static Node *
-bit_and(void)
-{
- Node *np;
-
- np = eq();
- while (accept('&'))
- np = integerop(OBAND, np, eq());
- return np;
-}
-
-static Node *
-bit_xor(void)
-{
- Node *np;
-
- np = bit_and();
- while (accept('^'))
- np = integerop(OBXOR, np, bit_and());
- return np;
-}
-
-static Node *
-bit_or(void)
-{
- Node *np;
-
- np = bit_xor();
- while (accept('|'))
- np = integerop(OBOR, np, bit_xor());
- return np;
-}
-
-static Node *
-and(void)
-{
- Node *np;
-
- np = bit_or();
- while (accept(AND))
- np = logic(OAND, np, bit_or());
- return np;
-}
-
-static Node *
-or(void)
-{
- Node *np;
-
- np = and();
- while (accept(OR))
- np = logic(OOR, np, and());
- return np;
-}
-
-static Node *
-ternary(void)
-{
- Node *cond;
-
- cond = or();
- while (accept('?')) {
- Node *ifyes, *ifno, *np;
-
- cond = exp2cond(cond, 0);
- ifyes = xexpr();
- expect(':');
- ifno = ternary();
- np = chkternary(ifyes, ifno);
- cond = node(OASK, np->type, cond, np);
- }
- return cond;
-}
-
-static Node *
-xassign(void)
-{
- Node *np, *(*fun)(int , Node *, Node *);
- int op;
-
- np = ternary();
- for (;;) {
- switch (yytoken) {
- case '=': op = OASSIGN; fun = assignop; break;
- case MUL_EQ: op = OA_MUL; fun = arithmetic; break;
- case DIV_EQ: op = OA_DIV; fun = arithmetic; break;
- case MOD_EQ: op = OA_MOD; fun = integerop; break;
- case ADD_EQ: op = OA_ADD; fun = arithmetic; break;
- case SUB_EQ: op = OA_SUB; fun = arithmetic; break;
- case SHL_EQ: op = OA_SHL; fun = integerop; break;
- case SHR_EQ: op = OA_SHR; fun = integerop; break;
- case AND_EQ: op = OA_AND; fun = integerop; break;
- case XOR_EQ: op = OA_XOR; fun = integerop; break;
- case OR_EQ: op = OA_OR; fun = integerop; break;
- default: return np;
- }
- chklvalue(np);
- np->flags |= NEFFECT;
- next();
- np = (fun)(op, np, assign());
- }
-}
-
-static Node *
-xexpr(void)
-{
- Node *lp, *rp;
-
- lp = xassign();
- while (accept(',')) {
- rp = xassign();
- lp = node(OCOMMA, rp->type, lp, rp);
- }
- return lp;
-}
-
-Node *
-assign(void)
-{
- return simplify(xassign());
-}
-
-Node *
-constexpr(void)
-{
- Node *np;
-
- np = ternary();
- if (np && np->type->op == INT) {
- np = simplify(convert(np, inttype, 0));
- if (np->flags & NCONST)
- return np;
- }
- freetree(np);
- return NULL;
-}
-
-Node *
-expr(void)
-{
- return simplify(xexpr());
-}
-
-Node *
-condexpr(int neg)
-{
- Node *np;
-
- np = exp2cond(xexpr(), neg);
- if (np->flags & NCONST)
- warn("conditional expression is constant");
- return simplify(np);
-}
--- a/src/cmd/scc/cc1/fold.c
+++ /dev/null
@@ -1,684 +1,0 @@
-#include <assert.h>
-#include <stdlib.h>
-
-#include <scc/scc.h>
-#include "cc1.h"
-
-
-TUINT
-ones(int nbytes)
-{
- return (nbytes == 8) ? -1 : ~(-1ull << nbytes * 8);
-}
-
-static int
-addi(TINT l, TINT r, Type *tp)
-{
- struct limits *lim = getlimits(tp);
- TINT max = lim->max.i, min = -lim->min.i;
-
- if (l < 0 && r < 0 && l >= min - r ||
- l == 0 ||
- r == 0 ||
- l < 0 && r > 0 ||
- l > 0 && r < 0 ||
- l > 0 && r > 0 && l <= max - r) {
- return 1;
- }
- warn("overflow in constant expression");
- return 0;
-}
-
-static int
-addf(TFLOAT l, TFLOAT r, Type *tp)
-{
- struct limits *lim = getlimits(tp);
- TFLOAT max = lim->max.f, min = lim->min.f;
-
- if (l < 0 && r < 0 && l >= min - r ||
- l == 0 ||
- r == 0 ||
- l < 0 && r > 0 ||
- l > 0 && r < 0 ||
- l > 0 && r > 0 && l <= max - r) {
- return 1;
- }
- warn("overflow in constant expression");
- return 0;
-}
-
-static int
-subi(TINT l, TINT r, Type *tp)
-{
- return addi(l, -r, tp);
-}
-
-static int
-subf(TFLOAT l, TFLOAT r, Type *tp)
-{
- return addf(l, -r, tp);
-}
-
-static int
-muli(TINT l, TINT r, Type *tp)
-{
- struct limits *lim = getlimits(tp);
- TINT max = lim->max.i, min = -lim->min.i;
-
- if (l > -1 && l <= 1 ||
- r > -1 && r <= 1 ||
- l < 0 && r < 0 && -l <= max/-r ||
- l < 0 && r > 0 && l >= min/r ||
- l > 0 && r < 0 && r >= min/l ||
- l > 0 && r > 0 && l <= max/r) {
- return 1;
- }
- warn("overflow in constant expression");
- return 0;
-}
-
-static int
-mulf(TFLOAT l, TFLOAT r, Type *tp)
-{
- struct limits *lim = getlimits(tp);
- TFLOAT max = lim->max.f, min = lim->min.f;
-
- if (l > -1 && l <= 1 ||
- r > -1 && r <= 1 ||
- l < 0 && r < 0 && -l <= max/-r ||
- l < 0 && r > 0 && l >= min/r ||
- l > 0 && r < 0 && r >= min/l ||
- l > 0 && r > 0 && l <= max/r) {
- return 1;
- }
- warn("overflow in constant expression");
- return 0;
-}
-
-static int
-divi(TINT l, TINT r, Type *tp)
-{
- struct limits *lim = getlimits(tp);
-
- if (r == 0 || l == -lim->min.i && r == -1) {
- warn("overflow in constant expression");
- return 0;
- }
- return 1;
-}
-
-static int
-divf(TFLOAT l, TFLOAT r, Type *tp)
-{
- struct limits *lim = getlimits(tp);
-
- if (l < 0) l = -l;
- if (r < 0) r = -r;
-
- if (r == 0.0 || r < 1.0 && l > lim->max.f * r) {
- warn("overflow in constant expression");
- return 0;
- }
- return 1;
-}
-
-static int
-lshi(TINT l, TINT r, Type *tp)
-{
- if (r < 0 || r >= tp->size * 8) {
- warn("shifting %d bits is undefined", r);
- return 0;
- }
- return muli(l, 1 << r, tp);
-}
-
-static int
-rshi(TINT l, TINT r, Type *tp)
-{
- if (r < 0 || r >= tp->size * 8) {
- warn("shifting %d bits is undefined", r);
- return 0;
- }
- return 1;
-}
-
-static int
-foldint(int op, Symbol *res, TINT l, TINT r)
-{
- TINT i;
- Type *tp = res->type;
- int (*validate)(TINT, TINT, Type *tp);
-
- switch (op) {
- case OADD: validate = addi; break;
- case OSUB: validate = subi; break;
- case OMUL: validate = muli; break;
- case ODIV: validate = divi; break;
- case OSHL: validate = lshi; break;
- case OSHR: validate = rshi; break;
- case OMOD: validate = divi; break;
- default: validate = NULL; break;
- }
-
- if (validate && !(*validate)(l, r, tp))
- return 0;
-
- switch (op) {
- case OADD: i = l + r; break;
- case OSUB: i = l - r; break;
- case OMUL: i = l * r; break;
- case ODIV: i = l / r; break;
- case OMOD: i = l % r; break;
- case OSHL: i = l << r; break;
- case OSHR: i = l >> r; break;
- case OBAND: i = l & r; break;
- case OBXOR: i = l ^ r; break;
- case OBOR: i = l | r; break;
- case OAND: i = l && r; break;
- case OOR: i = l || r; break;
- case OLT: i = l < r; break;
- case OGT: i = l > r; break;
- case OGE: i = l >= r; break;
- case OLE: i = l <= r; break;
- case OEQ: i = l == r; break;
- case ONE: i = l != r; break;
- case ONEG: i = !l; break;
- case OSNEG: i = -l; break;
- case OCPL: i = ~l; break;
- default: return 0;
- }
- res->u.i = i;
-
- DBG("FOLD i l=%lld %d r=%lld = %lld", l, op, r, i);
- return 1;
-}
-
-static int
-folduint(int op, Symbol *res, TUINT l, TUINT r)
-{
- TINT i;
- TUINT u;
-
- switch (op) {
- case OADD: u = l + r; break;
- case OSUB: u = l - r; break;
- case OMUL: u = l * r; break;
- case ODIV: u = l / r; break;
- case OMOD: u = l % r; break;
- case OSHL: u = l << r; break;
- case OSHR: u = l >> r; break;
- case OBAND: u = l & r; break;
- case OBXOR: u = l ^ r; break;
- case OBOR: u = l | r; break;
- case ONEG: u = !l; break;
- case OSNEG: u = -l; break;
- case OCPL: u = ~l; break;
- case OAND: i = l && r; goto sign;
- case OOR: i = l || r; goto sign;
- case OLT: i = l < r; goto sign;
- case OGT: i = l > r; goto sign;
- case OGE: i = l >= r; goto sign;
- case OLE: i = l <= r; goto sign;
- case OEQ: i = l == r; goto sign;
- case ONE: i = l != r; goto sign;
- default: return 0;
- }
- res->u.u = u & ones(res->type->size);
-
- DBG("FOLD ui l=%llu %d r=%llu = %llu", l, op, r, u);
- return 1;
-
-sign:
- res->u.i = i;
-
- DBG("FOLD sui %llu %d %llu = %llu", l, op, r, i);
- return 1;
-}
-
-static int
-foldfloat(int op, Symbol *res, TFLOAT l, TFLOAT r)
-{
- TFLOAT f;
- TINT i;
- int (*validate)(TFLOAT, TFLOAT, Type *tp);
-
- switch (op) {
- case OADD: validate = addf; break;
- case OSUB: validate = subf; break;
- case OMUL: validate = mulf; break;
- case ODIV: validate = divf; break;
- default: validate = NULL; break;
- }
-
- if (validate && !(*validate)(l, r, res->type))
- return 0;
-
- switch (op) {
- case OADD: f = l + r; break;
- case OSUB: f = l - r; break;
- case OMUL: f = l * r; break;
- case ODIV: f = l / r; break;
- case OLT: i = l < r; goto comparison;
- case OGT: i = l > r; goto comparison;
- case OGE: i = l >= r; goto comparison;
- case OLE: i = l <= r; goto comparison;
- case OEQ: i = l == r; goto comparison;
- case ONE: i = l != r; goto comparison;
- default: return 0;
- }
- res->u.f = f;
-
- DBG("FOLD f l=%lf %d r=%lf = %lf", l, op, r, f);
- return 1;
-
-comparison:
- res->u.i = i;
-
- DBG("FOLD if l=%lf %d r=%lf = %lld", l, op, r, i);
- return 1;
-}
-
-static Node *
-foldconst(int type, int op, Type *tp, Symbol *ls, Symbol *rs)
-{
- Symbol *sym, aux;
- TINT i;
- TUINT u;
- TFLOAT f;
-
- aux.type = tp;
- switch (type) {
- case INT:
- i = (rs) ? rs->u.i : 0;
- if (!foldint(op, &aux, ls->u.i, i))
- return NULL;
- break;
- case UNSIGNED:
- u = (rs) ? rs->u.u : 0u;
- if (!folduint(op, &aux, ls->u.u, u))
- return NULL;
- break;
- case FLOAT:
- f = (rs) ? rs->u.f : 0.0;
- if (!foldfloat(op, &aux, ls->u.f, f))
- return NULL;
- break;
- }
- sym = newsym(NS_IDEN, NULL);
- sym->flags |= SCONSTANT;
- sym->type = tp;
- sym->u = aux.u;
- return constnode(sym);
-}
-
-static Node *
-foldcast(Node *np, Node *l)
-{
- TUINT negmask, mask, u;
- Type *newtp = np->type, *oldtp = l->type;
- Symbol aux, *sym, *osym = l->sym;
-
- if (!(l->flags & NCONST))
- return np;
-
- switch (newtp->op) {
- case PTR:
- case INT:
- case ENUM:
- switch (oldtp->op) {
- case PTR:
- case INT:
- case ENUM:
- u = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
- break;
- case FLOAT:
- oldtp = newtp;
- u = osym->u.f;
- break;
- default:
- return np;
- }
- mask = ones(newtp->size);
- if (newtp->prop & TSIGNED) {
- negmask = ~mask;
- if (u & (negmask >> 1) & mask)
- u |= negmask;
- aux.u.i = u;
- } else {
- aux.u.u = u & mask;
- }
- break;
- case FLOAT:
- /* FIXME: The cast can be from another float type */
- aux.u.f = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
- break;
- default:
- return np;
- }
- DBG("FOLD cast %c->%c", oldtp->letter, newtp->letter);
- freetree(np);
- sym = newsym(NS_IDEN, NULL);
- sym->flags |= SCONSTANT;
- sym->type = newtp;
- sym->u = aux.u;
- return constnode(sym);
-}
-
-static Node *
-foldunary(Node *np, Node *l)
-{
- int op = l->op;
- Node *aux;
-
- switch (np->op) {
- case ONEG:
- if (l->op == ONEG)
- break;
- return NULL;
- case OADD:
- DBG("FOLD unary delete %d", np->op);
- np->left = NULL;
- freetree(np);
- return l;
- case OCAST:
- if (op != OCAST)
- return foldcast(np, l);
- /* TODO: This is wrong: (float)(int) 7.2 */
- DBG("FOLD unary collapse %d", np->op);
- np->left = l->left;
- l->left = NULL;
- freetree(l);
- return np;
- case OSNEG:
- case OCPL:
- if (op != np->op)
- return NULL;
- break;
- case OPTR:
- if (op != OADDR || np->type != l->left->type)
- return NULL;
- break;
- case OADDR:
- if (op != OPTR)
- return NULL;
- break;
- default:
- return NULL;
- }
- DBG("FOLD unary cancel %d", np->op);
- aux = l->left;
- l->left = NULL;
- freetree(np);
- return aux;
-}
-
-static Node *
-fold(Node *np)
-{
- Symbol *rs, *ls;
- Type *optype;
- int type;
- int op = np->op;
- Node *p, *lp = np->left, *rp = np->right;
- Type *tp = np->type;
-
- assert(lp && rp);
- if ((op == ODIV || op == OMOD) && cmpnode(rp, 0)) {
- warn("division by 0");
- return NULL;
- }
- /*
- * Return if any of the children is no constant,
- * or it is a constant generated when
- * the address of a static variable is taken
- * (when we don't know the physical address so
- * we cannot fold it)
- */
- if (!rp) {
- rs = NULL;
- } else {
- if (!(rp->flags & NCONST) || !rp->sym)
- return NULL;
- rs = rp->sym;
- }
-
- if (!(lp->flags & NCONST) || !lp->sym)
- return NULL;
- optype = lp->type;
- ls = lp->sym;
-
- switch (type = optype->op) {
- case ENUM:
- case INT:
- if (!(optype->prop & TSIGNED))
- type = UNSIGNED;
- case PTR:
- case FLOAT:
- if ((p = foldconst(type, op, tp, ls, rs)) == NULL)
- return NULL;
- freetree(np);
- return p;
- default:
- return NULL;
- }
-}
-
-static void
-commutative(Node *np, Node *l, Node *r)
-{
- int op = np->op;
-
- if (r == NULL || r->flags&NCONST || !(l->flags&NCONST))
- return;
-
- switch (op) {
- case OLT:
- case OGT:
- case OGE:
- case OLE:
- DBG("FOLD neg commutative %d", np->op);
- np->op = negop(op);
- case OEQ:
- case ONE:
- case OADD:
- case OMUL:
- case OBAND:
- case OBXOR:
- case OBOR:
- DBG("FOLD commutative %d", np->op);
- np->left = r;
- np->right = l;
- break;
- }
-}
-
-static Node *
-identity(Node *np)
-{
- int iszeror, isoner;
- int iszerol, isonel;
- Node *lp = np->left, *rp = np->right;
-
- if (!rp)
- return NULL;
-
- iszeror = cmpnode(rp, 0);
- isoner = cmpnode(rp, 1),
- iszerol = cmpnode(lp, 0);
- isonel = cmpnode(lp, 1);
-
- switch (np->op) {
- case OOR:
- /*
- * 1 || i => 1 (free right)
- * i || 0 => i (free right)
- * 0 || i => i (free left)
- * i || 1 => i,1 (comma)
- */
- if (isonel | iszeror)
- goto free_right;
- if (iszerol)
- goto free_left;
- if (isoner)
- goto change_to_comma;
- return NULL;
- case OAND:
- /*
- * 0 && i => 0 (free right)
- * i && 1 => i (free right)
- * 1 && i => i (free left)
- * i && 0 => i,0 (comma)
- */
- if (iszerol | isoner)
- goto free_right;
- if (isonel)
- goto free_left;
- if (iszeror)
- goto change_to_comma;
- return NULL;
- case OSHL:
- case OSHR:
- /*
- * i >> 0 => i (free right)
- * i << 0 => i (free right)
- * 0 >> i => 0 (free right)
- * 0 << i => 0 (free right)
- */
- if (iszeror | iszerol)
- goto free_right;
- return NULL;
- case OBXOR:
- case OADD:
- case OBOR:
- case OSUB:
- /*
- * i + 0 => i
- * i - 0 => i
- * i | 0 => i
- * i ^ 0 => i
- */
- if (iszeror)
- goto free_right;
- return NULL;
- case OMUL:
- /*
- * i * 0 => i,0
- * i * 1 => i
- */
- if (iszeror)
- goto change_to_comma;
- if (isoner)
- goto free_right;
- return NULL;
- case ODIV:
- /* i / 1 => i */
- if (isoner)
- goto free_right;
- return NULL;
- case OBAND:
- /* i & ~0 => i */
- if (cmpnode(rp, -1))
- goto free_right;
- return NULL;
- case OMOD:
- /* i % 1 => i,1 */
- /* TODO: i % 2^n => i & n-1 */
- if (isoner)
- goto change_to_comma;
- default:
- return NULL;
- }
-
-free_right:
- DBG("FOLD identity %d", np->op);
- np->left = NULL;
- freetree(np);
- return lp;
-
-free_left:
- DBG("FOLD identity %d", np->op);
- np->right = NULL;
- freetree(np);
- return rp;
-
-change_to_comma:
- DBG("FOLD identity %d", np->op);
- np->op = OCOMMA;
- return np;
-}
-
-static Node *
-foldternary(Node *np, Node *cond, Node *body)
-{
- if (!(cond->flags & NCONST))
- return np;
- if (cmpnode(cond, 0)) {
- np = body->right;
- freetree(body->left);
- } else {
- np = body->left;
- freetree(body->right);
- }
-
- DBG("FOLD ternary");
- body->left = NULL;
- body->right = NULL;
- freetree(cond);
- free(body);
- return np;
-}
-
-/* TODO: fold OCOMMA */
-
-Node *
-simplify(Node *np)
-{
- Node *p, *l, *r;
-
- if (!np)
- return NULL;
- if (enadebug)
- prtree(np);
-
- l = np->left = simplify(np->left);
- r = np->right = simplify(np->right);
-
- switch (np->op) {
- case OASK:
- return foldternary(np, l, r);
- case OCALL:
- case OPAR:
- case OSYM:
- case OASSIGN:
- case OA_MUL:
- case OA_DIV:
- case OA_MOD:
- case OA_ADD:
- case OA_SUB:
- case OA_SHL:
- case OA_SHR:
- case OA_AND:
- case OA_XOR:
- case OA_OR:
- return np;
- case OSNEG:
- case OCPL:
- case OADDR:
- case OPTR:
- case INC:
- case DEC:
- case OCAST:
- case ONEG:
- assert(!r);
- if ((p = foldunary(np, l)) != NULL)
- return p;
- return np;
- default:
- commutative(np, l, r);
- if ((p = fold(np)) != NULL)
- return p;
- if ((p = identity(np)) != NULL)
- return p;
- return np;
- }
-}
--- a/src/cmd/scc/cc1/init.c
+++ /dev/null
@@ -1,377 +1,0 @@
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-
-typedef struct init Init;
-
-struct designator {
- TINT pos;
- Node *expr;
- struct designator *next;
-};
-
-struct init {
- TUINT pos;
- TUINT max;
- struct designator *tail;
- struct designator *head;
-};
-
-static TINT
-arydesig(Type *tp, Init *ip)
-{
- TINT npos;
- Node *np;
-
- if (tp->op != ARY)
- errorp("array index in non-array initializer");
- next();
- np = constexpr();
- npos = np->sym->u.i;
- if (npos < 0 || (tp->prop & TDEFINED) && npos >= tp->n.elem) {
- errorp("array index in initializer exceeds array bounds");
- npos = 0;
- }
- freetree(np);
- expect(']');
- return npos;
-}
-
-static TINT
-fielddesig(Type *tp, Init *ip)
-{
- int ons;
- Symbol *sym, **p;
-
- if (!(tp->prop & TAGGREG))
- errorp("field name not in record or union initializer");
- ons = namespace;
- namespace = tp->ns;
- next();
- namespace = ons;
- if (yytoken != IDEN)
- unexpected();
- sym = yylval.sym;
- next();
- if ((sym->flags & SDECLARED) == 0) {
- errorp("unknown field '%s' specified in initializer",
- sym->name);
- return 0;
- }
- for (p = tp->p.fields; *p != sym; ++p)
- ;
- return p - tp->p.fields;
-}
-
-static Init *
-init(Init *ip)
-{
- ip->tail = ip->head = NULL;
- ip->pos = ip->max = 0;
- return ip;
-}
-
-static Node *
-str2ary(Type *tp)
-{
- Node *np;
- Type *btp = tp->type;;
- Symbol *sym;
- size_t len;
- char *s;
-
- np = assign();
- sym = np->left->sym;
- if (btp != chartype && btp != uchartype && btp != schartype) {
- errorp("array of inappropriate type initialized from string constant");
- return constnode(zero);
- }
-
- len = sym->type->n.elem-1;
- if (!(tp->prop & TDEFINED)) {
- tp->n.elem = len+1;
- deftype(tp);
- } else if (tp->n.elem < len) {
- warn("initializer-string for array of chars is too long");
- }
-
- len = tp->n.elem;
- s = sym->u.s;
- sym = newstring(NULL, len);
- strncpy(sym->u.s, s, len);
- np->sym = sym;
- np->type = sym->type;
-
- return np;
-}
-
-static Node *
-initialize(Type *tp)
-{
- Node *np;
- Symbol *sym;
-
- if (tp->op == ARY && yytoken == STRING)
- return str2ary(tp);
-
- if (yytoken == '{' || tp->op == STRUCT || tp->op == ARY)
- return initlist(tp);
-
- np = assign();
- if (eqtype(tp, np->type, 1))
- return np;
-
- np = convert(decay(np), tp, 0);
- if (!np) {
- errorp("incorrect initializer");
- return constnode(zero);
- }
-
- return simplify(np);
-}
-
-static Node *
-mkcompound(Init *ip, Type *tp)
-{
- Node **v, **p;
- size_t n;
- struct designator *dp, *next;
- Symbol *sym;
-
- if (tp->op == UNION) {
- Node *np = NULL;
-
- v = xmalloc(sizeof(*v));
- for (dp = ip->head; dp; dp = next) {
- freetree(np);
- np = dp->expr;
- next = dp->next;
- free(dp);
- }
- *v = np;
- } else {
- n = (tp->prop&TDEFINED) ? tp->n.elem : ip->max;
- if (n == 0) {
- v = NULL;
- } else if (n > SIZE_MAX / sizeof(*v)) {
- errorp("compound literal too big");
- return constnode(zero);
- } else {
- n *= sizeof(*v);
- v = memset(xmalloc(n), 0, n);
-
- for (dp = ip->head; dp; dp = next) {
- p = &v[dp->pos];
- freetree(*p);
- *p = dp->expr;
- next = dp->next;
- free(dp);
- }
- }
- }
-
- sym = newsym(NS_IDEN, NULL);
- sym->u.init = v;
- sym->type = tp;
- sym->flags |= SINITLST;
-
- return constnode(sym);
-}
-
-static void
-newdesig(Init *ip, Node *np)
-{
- struct designator *dp;
-
- dp = xmalloc(sizeof(*dp));
- dp->pos = ip->pos;
- dp->expr = np;
- dp->next = NULL;
-
- if (ip->head == NULL) {
- ip->head = ip->tail = dp;
- } else {
- ip->tail->next = dp;
- ip->tail = dp;
- }
-
- if (ip->pos+1 > ip->max)
- ip->max = ip->pos+1;
-}
-
-Node *
-initlist(Type *tp)
-{
- Init in;
- Node *np;
- Type *curtp;
- int braces, scalar, toomany, outbound;
- TINT nelem = tp->n.elem;
- static int depth;
-
- if (depth == NR_SUBTYPE)
- error("too many nested initializers");
- ++depth;
- init(&in);
- braces = scalar = toomany = 0;
-
- if (accept('{'))
- braces = 1;
-
- do {
- curtp = inttype;
- switch (yytoken) {
- case '[':
- in.pos = arydesig(tp, &in);
- curtp = tp->type;
- goto desig_list;
- case '.':
- in.pos = fielddesig(tp, &in);
- if (in.pos < nelem)
- curtp = tp->p.fields[in.pos]->type;
- desig_list:
- if (yytoken == '[' || yytoken == '.') {
- np = initlist(curtp);
- goto new_desig;
- }
- expect('=');
- default:
- outbound = 0;
-
- switch (tp->op) {
- case ARY:
- curtp = tp->type;
- if (!(tp->prop & TDEFINED) || in.pos < tp->n.elem)
- break;
- if (!toomany)
- warn("excess elements in array initializer");
- toomany = 1;
- outbound = 1;
- break;
- case UNION:
- case STRUCT:
- if (in.pos < nelem) {
- curtp = tp->p.fields[in.pos]->type;
- break;
- }
- if (!toomany)
- warn("excess elements in struct initializer");
- toomany = 1;
- outbound = 1;
- break;
- default:
- curtp = tp;
- if (!scalar)
- warn("braces around scalar initializer");
- scalar = 1;
- if (in.pos == 0)
- break;
- if (!toomany)
- warn("excess elements in scalar initializer");
- toomany = 1;
- outbound = 1;
- break;
- }
- np = initialize(curtp);
- if (outbound) {
- freetree(np);
- np = NULL;
- }
- }
-
-new_desig:
- if (np)
- newdesig(&in, np);
- if (++in.pos == 0)
- errorp("compound literal too big");
- if (nelem == in.pos && !braces)
- break;
- } while (accept(','));
-
- if (braces)
- expect('}');
-
-
- if (tp->op == ARY && !(tp->prop & TDEFINED)) {
- tp->n.elem = in.max;
- deftype(tp);
- }
- if (in.max == 0) {
- errorp("empty braced initializer");
- return constnode(zero);
- }
-
- return mkcompound(&in, tp);
-}
-
-static void
-autoinit(Symbol *sym, Node *np)
-{
- Symbol *hidden;
- Type *tp = sym->type;
- size_t n; /* FIXME: It should be SIZET */
-
-repeat:
- switch (tp->op) {
- case UNION:
- np = np->sym->u.init[0];
- tp = np->type;
- goto repeat;
- case ARY:
- case STRUCT:
- if (!(np->flags & NCONST))
- abort(); /* TODO */
- hidden = newsym(NS_IDEN, NULL);
- hidden->type = sym->type;
- hidden->flags |= SLOCAL | SHASINIT;
- emit(ODECL, hidden);
- emit(OINIT, np);
- emit(ODECL, sym);
- emit(OEXPR,
- node(OASSIGN, tp, varnode(sym), varnode(hidden)));
- break;
- default:
- emit(ODECL, sym);
- np = node(OASSIGN, tp, varnode(sym), np);
- emit(OEXPR, np);
- break;
- }
-}
-
-void
-initializer(Symbol *sym, Type *tp)
-{
- Node *np;
- int flags = sym->flags;
-
- if (tp->op == FTN) {
- errorp("function '%s' initialized like a variable",
- sym->name);
- tp = inttype;
- }
- np = initialize(tp);
-
- if (flags & SDEFINED) {
- errorp("redeclaration of '%s'", sym->name);
- } else if ((flags & (SGLOBAL|SLOCAL|SPRIVATE)) != 0) {
- if (!(np->flags & NCONST)) {
- errorp("initializer element is not constant");
- return;
- }
- sym->flags |= SHASINIT;
- sym->flags &= ~SEMITTED;
- emit(ODECL, sym);
- emit(OINIT, np);
- sym->flags |= SDEFINED;
- } else if ((flags & (SEXTERN|STYPEDEF)) != 0) {
- errorp("'%s' has both '%s' and initializer",
- sym->name, (flags&SEXTERN) ? "extern" : "typedef");
- } else {
- autoinit(sym, np);
- }
-}
--- a/src/cmd/scc/cc1/ir.md
+++ /dev/null
@@ -1,443 +1,0 @@
-# scc intermediate representation #
-
-The scc IR tries to be be a simple and easily parseable intermediate
-representation, and it makes it a bit terse and cryptic. The main
-characteristic of the IR is that all the types and operations are
-represented with only one letter, so parsing tables can be used
-to parse it.
-
-The language is composed of lines, representing statements.
-Each statement is composed of tab-separated fields.
-Declaration statements begin in column 0, expressions and
-control flow begin with a tabulator.
-When the frontend detects an error, it closes the output stream.
-
-## Types ##
-
-Types are represented with uppercase letters:
-
-* C -- signed 8-Bit integer
-* I -- signed 16-Bit integer
-* W -- signed 32-Bit integer
-* Q -- signed 64-Bit integer
-* K -- unsigned 8-Bit integer
-* N -- unsigned 16-Bit integer
-* Z -- unsigned 32-Bit integer
-* O -- unsigned 64-Bit integer
-* 0 -- void
-* P -- pointer
-* F -- function
-* V -- vector
-* U -- union
-* S -- struct
-* B -- bool
-* J -- float
-* D -- double
-* H -- long double
-
-This list has been built for the original Z80 backend, where 'int'
-has the same size as 'short'. Several types (S, F, V, U and others) need
-an identifier after the type letter for better differentiation
-between multiple structs, functions, vectors and unions (S1, V12 ...)
-naturally occuring in a C-program.
-
-## Storage classes ##
-
-The storage classes are represented using uppercase letters:
-
-* A -- automatic
-* R -- register
-* G -- public (global variable declared in the module)
-* X -- extern (global variable declared in another module)
-* Y -- private (variable in file-scope)
-* T -- local (static variable in function-scope)
-* M -- member (struct/union member)
-* L -- label
-
-## Declarations/definitions ##
-
-Variable names are composed of a storage class and an identifier
-(e.g. A1, R2, T3).
-Declarations and definitions are composed of a variable
-name, a type and the name of the variable:
-
- A1 I maxweight
- R2 C flag
- A3 S4 statstruct
-
-### Type declarations ###
-
-Some declarations (e.g. structs) involve the declaration of member
-variables.
-Struct members are declared normally after the type declaration in
-parentheses.
-
-For example the struct declaration
-
- struct foo {
- int i;
- long c;
- } var1;
-
-generates
-
- S2 foo (
- M3 I i
- M4 W c
- )
- G5 S2 var1
-
-## Functions ##
-
-A function prototype
-
- int printf(char *cmd, int flag, void *data);
-
-will generate a type declaration and a variable declaration
-
- F5 P I P
- X1 F5 printf
-
-The first line gives the function-type specification 'F' with
-an identifier '5' and subsequently lists the types of the
-function parameters.
-The second line declares the 'printf' function as a publicly
-scoped variable.
-
-Analogously, a statically declared function in file scope
-
- static int printf(char *cmd, int flag, void *data);
-
-generates
-
- F5 P I P
- T1 F5 printf
-
-Thus, the 'printf' variable went into local scope ('T').
-
-A '{' in the first column starts the body of the previously
-declared function:
-
- int printf(char *cmd, int flag, void *data) {}
-
-generates
-
- F5 P I P
- G1 F5 printf
- {
- A2 P cmd
- A3 I flag
- A4 P data
- -
- }
-
-Again, the frontend must ensure that '{' appears only after the
-declaration of a function. The character '-' marks the separation
-between parameters and local variables:
-
- int printf(register char *cmd, int flag, void *data) {int i;};
-
-generates
-
- F5 P I P
- G1 F5 printf
- {
- R2 P cmd
- A3 I flag
- A4 P data
- -
- A6 I i
- }
-
-### Expressions ###
-
-Expressions are emitted in reverse polish notation, simplifying
-parsing and converting into a tree representation.
-
-#### Operators ####
-
-Operators allowed in expressions are:
-
-* \+ -- addition
-* \- -- substraction
-* \* -- multiplication
-* % -- modulo
-* / -- division
-* l -- left shift
-* r -- right shift
-* < -- less than
-* > -- greather than
-* ] -- greather or equal than
-* [ -- less or equal than
-* = -- equal than
-* ! -- different than
-* & -- bitwise and
-* | -- bitwise or
-* ^ -- bitwise xor
-* ~ -- bitwise complement
-* : -- asignation
-* _ -- unary negation
-* c -- function call
-* p -- parameter
-* . -- field
-* , -- comma operator
-* ? -- ternary operator
-* ' -- take address
-* a -- logical shortcut and
-* o -- logical shortcut or
-* @ -- content of pointer
-
-Assignation has some suboperators:
-
-* :/ -- divide and assign
-* :% -- modulo and assign
-* :+ -- addition and assign
-* :- -- substraction and assign
-* :l -- left shift and assign
-* :r -- right shift and assign
-* :& -- bitwise and and assign
-* :^ -- bitwise xor and assign
-* :| -- bitwise or and assign
-* :i -- post increment
-* :d -- post decrement
-
-Every operator in an expression has a type descriptor.
-
-#### Constants ####
-
-Constants are introduced with the character '#'. For instance, 10 is
-translated to #IA (all constants are emitted in hexadecimal),
-where I indicates that it is an integer constant.
-Strings are a special case because they are represented with
-the " character.
-The constant "hello" is emitted as "68656C6C6F. For example
-
- int
- main(void)
- {
- int i, j;
-
- i = j+2*3;
- }
-
-generates
-
- F1
- G1 F1 main
- {
- -
- A2 I i
- A3 I j
- A2 A3 #I6 +I :I
- }
-
-Type casts are expressed with a tuple denoting the
-type conversion
-
- int
- main(void)
- {
- int i;
- long j;
-
- j = (long)i;
- }
-
-generates
-
- F1
- G1 F1 main
- {
- -
- A2 I i
- A3 W j
- A2 A3 WI :I
- }
-
-### Statements ###
-#### Jumps #####
-
-Jumps have the following form:
-
- j L# [expression]
-
-the optional expression field indicates some condition which
-must be satisfied to jump. Example:
-
- int
- main(void)
- {
- int i;
-
- goto label;
- label:
- i -= i;
- }
-
-generates
-
- F1
- G1 F1 main
- {
- -
- A2 I i
- j L3
- L3
- A2 A2 :-I
- }
-
-Another form of jump is the return statement, which uses the
-letter 'y' followed by a type identifier.
-Depending on the type, an optional expression follows.
-
- int
- main(void)
- {
- return 16;
- }
-
-generates
-
- F1
- G1 F1 main
- {
- -
- yI #I10
- }
-
-
-#### Loops ####
-
-There are two special characters that are used to indicate
-to the backend that the following statements are part of
-a loop body.
-
-* b -- beginning of loop
-* e -- end of loop
-
-#### Switch statement ####
-
-Switches are represented using a table, in which the labels
-where to jump for each case are indicated. Common cases are
-represented with 'v' and default with 'f'.
-The switch statement itself is represented with 's' followed
-by the label where the jump table is located, and the
-expression of the switch:
-
- int
- func(int n)
- {
- switch (n+1) {
- case 1:
- case 2:
- case 3:
- default:
- ++n;
- }
- }
-
-generates
-
- F2 I
- G1 F2 func
- {
- A1 I n
- -
- s L4 A1 #I1 +I
- L5
- L6
- L7
- L8
- A1 #I1 :+I
- j L3
- L4
- t #4
- v L7 #I3
- v L6 #I2
- v L5 #I1
- f L8
- L3
- }
-
-The beginning of the jump table is indicated by the the letter 't',
-followed by the number of cases (including default case) of the
-switch.
-
-## Resumen ##
-
-* C -- signed 8-Bit integer
-* I -- signed 16-Bit integer
-* W -- signed 32-Bit integer
-* O -- signed 64-Bit integer
-* M -- unsigned 8-Bit integer
-* N -- unsigned 16-Bit integer
-* Z -- unsigned 32-Bit integer
-* Q -- unsigned 64-Bit integer
-* 0 -- void
-* P -- pointer
-* F -- function
-* V -- vector
-* U -- union
-* S -- struct
-* B -- bool
-* J -- float
-* D -- double
-* H -- long double
-* A -- automatic
-* R -- register
-* G -- public (global variable declared in the module)
-* X -- extern (global variable declared in another module)
-* Y -- private (variable in file-scope)
-* T -- local (static variable in function-scope)
-* M -- member (struct/union member)
-* L -- label
-* { -- beginning of function body
-* } -- end of function body
-* \\ -- end of function parameters
-* \+ -- addition
-* \- -- substraction
-* \* -- multiplication
-* % -- modulo
-* / -- division
-* l -- left shift
-* r -- right shift
-* < -- less than
-* > -- greather than
-* ] -- greather or equal than
-* [ -- less or equal than
-* = -- equal than
-* ! -- different than
-* & -- bitwise and
-* | -- bitwise or
-* ^ -- bitwise xor
-* ~ -- bitwise complement
-* : -- asignation
-* _ -- unary negation
-* c -- function call
-* p -- parameter
-* . -- field
-* , -- comma operator
-* ? -- ternary operator
-* ' -- take address
-* a -- logical shortcut and
-* o -- logical shortcut or
-* @ -- content of pointer
-* :/ -- divide and assign
-* :% -- modulo and assign
-* :+ -- addition and assign
-* :- -- substraction and assign
-* :l -- left shift and assign
-* :r -- right shift and assign
-* :& -- bitwise and and assign
-* :^ -- bitwise xor and assign
-* :| -- bitwise or and assign
-* ;+ -- post increment
-* ;- -- post decrement
-* j -- jump
-* y -- return
-* b -- begin of loop
-* d -- end of loop
-* s -- switch statement
-* t -- switch table
-* v -- case entry in switch table
-* f -- default entry in switch table
--- a/src/cmd/scc/cc1/lex.c
+++ /dev/null
@@ -1,800 +1,0 @@
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-int yytoken;
-struct yystype yylval;
-char yytext[STRINGSIZ+3];
-unsigned short yylen;
-int lexmode = CCMODE;
-unsigned lineno;
-char filenam[FILENAME_MAX];
-
-int namespace = NS_IDEN;
-static int safe;
-Input *input;
-
-void
-ilex(void)
-{
- static struct keyword keys[] = {
- {"auto", SCLASS, AUTO},
- {"break", BREAK, BREAK},
- {"_Bool", TYPE, BOOL},
- {"__builtin_va_list", TYPE, VA_LIST},
- {"case", CASE, CASE},
- {"char", TYPE, CHAR},
- {"const", TQUALIFIER, CONST},
- {"continue", CONTINUE, CONTINUE},
- {"default", DEFAULT, DEFAULT},
- {"do", DO, DO},
- {"double", TYPE, DOUBLE},
- {"else", ELSE, ELSE},
- {"enum", TYPE, ENUM},
- {"extern", SCLASS, EXTERN},
- {"float", TYPE, FLOAT},
- {"for", FOR, FOR},
- {"goto", GOTO, GOTO},
- {"if", IF, IF},
- {"inline", TQUALIFIER, INLINE},
- {"int", TYPE, INT},
- {"long", TYPE, LONG},
- {"register", SCLASS, REGISTER},
- {"restrict", TQUALIFIER, RESTRICT},
- {"return", RETURN, RETURN},
- {"short", TYPE, SHORT},
- {"signed", TYPE, SIGNED},
- {"sizeof", SIZEOF, SIZEOF},
- {"static", SCLASS, STATIC},
- {"struct", TYPE, STRUCT},
- {"switch", SWITCH, SWITCH},
- {"typedef", SCLASS, TYPEDEF},
- {"union", TYPE, UNION},
- {"unsigned", TYPE, UNSIGNED},
- {"void", TYPE, VOID},
- {"volatile", TQUALIFIER, VOLATILE},
- {"while", WHILE, WHILE},
- {NULL, 0, 0},
- };
- keywords(keys, NS_KEYWORD);
-}
-
-void
-setloc(char *fname, unsigned line)
-{
- size_t len;
-
- if ((len = strlen(fname)) >= FILENAME_MAX)
- die("cc1: %s: file name too long", fname);
- memmove(filenam, fname, len);
- filenam[len] = '\0';
-
- free(input->filenam);
- input->filenam = xstrdup(fname);
- lineno = input->lineno = line;
-}
-
-void
-addinput(char *fname, Symbol *hide, char *buffer)
-{
- FILE *fp;
- char *extp;
- unsigned flags;
- int infileln;
- Input *newip, *curip = input;
-
- if (hide) {
- /* this is a macro expansion */
- fp = NULL;
- if (hide->hide == UCHAR_MAX)
- die("cc1: too many macro expansions");
- ++hide->hide;
- flags = IMACRO;
- } else if (fname) {
- /* a new file */
- if ((fp = fopen(fname, "r")) == NULL)
- die("cc1: %s: %s", fname, strerror(errno));
- flags = IFILE;
- if (curip && onlyheader) {
- infileln = strlen(infile);
- if (extp = strrchr(infile, '.'))
- infileln -= strlen(extp);
- printf("%.*s.o: %s %s\n",
- infileln, infile, infile, fname);
- }
- } else {
- /* reading from stdin */
- fp = stdin;
- fname = "<stdin>";
- flags = ISTDIN;
- }
-
- newip = xmalloc(sizeof(*newip));
-
- if (!buffer) {
- buffer = xmalloc(INPUTSIZ);
- buffer[0] = '\0';
- }
-
- if (curip)
- curip->lineno = lineno;
-
- newip->p = newip->begin = newip->line = buffer;
- newip->filenam = NULL;
- newip->lineno = 0;
- newip->next = curip;
- newip->fp = fp;
- newip->hide = hide;
- newip->flags = flags;
- input = newip;
-
- setloc(fname, (curip) ? curip->lineno : newip->lineno);
-}
-
-void
-delinput(void)
-{
- Input *ip = input;
- Symbol *hide = ip->hide;
-
- switch (ip->flags & ITYPE) {
- case IFILE:
- if (fclose(ip->fp))
- die("cc1: %s: %s", ip->filenam, strerror(errno));
- break;
- case IMACRO:
- assert(hide->hide == 1);
- --hide->hide;
- break;
- }
- input = ip->next;
- free(ip->filenam);
- free(ip->line);
- if (input) {
- lineno = input->lineno;
- strcpy(filenam, input->filenam);
- }
-}
-
-static void
-newline(void)
-{
- if (++lineno == 0)
- die("cc1: %s: file too long", filenam);
-}
-
-/*
- * Read the next character from the input file, counting number of lines
- * and joining lines escaped with \
- */
-static int
-readchar(void)
-{
- FILE *fp = input->fp;
- int c;
-
-repeat:
- switch (c = getc(fp)) {
- case '\\':
- if ((c = getc(fp)) == '\n') {
- newline();
- goto repeat;
- }
- ungetc(c, fp);
- c = '\\';
- break;
- case '\n':
- newline();
- break;
- default:
- if (!isprint(c) && !ispunct(c) && !isspace(c))
- warn("invalid input character. The shame of UB is yours");
- break;
- }
-
- return c;
-}
-
-/*
- * discard a C comment. This function is only called from readline
- * because it is impossible to have a comment in a macro, because
- * comments are always discarded before processing any cpp directive
- */
-static void
-comment(int type)
-{
- int c;
-
-repeat:
- while ((c = readchar()) != EOF && c != type)
- ;
-
- if (c == EOF) {
- errorp("unterminated comment");
- return;
- }
-
- if (type == '*' && (c = readchar()) != '/')
- goto repeat;
-}
-
-/*
- * readline is used to read a full logic line from a file.
- * It discards comments and check that the line fits in
- * the input buffer
- */
-static int
-readline(void)
-{
- char *bp, *lim;
- int c, peekc = 0;
-
- if (feof(input->fp)) {
- input->flags |= IEOF;
- return 0;
- }
-
- *input->line = '\0';
- lim = &input->line[INPUTSIZ-1];
- for (bp = input->line; bp < lim-1; *bp++ = c) {
- c = (peekc) ? peekc : readchar();
- peekc = 0;
- if (c == '\n' || c == EOF)
- break;
- if (c != '/')
- continue;
-
- /* check for /* or // */
- peekc = readchar();
- if (peekc != '*' && peekc != '/')
- continue;
- comment((peekc == '/') ? '\n' : '*');
- peekc = 0;
- c = ' ';
- }
-
- input->begin = input->p = input->line;
- if (bp == lim-1) {
- errorp("line too long");
- --bp;
- }
- *bp++ = '\n';
- *bp = '\0';
-
- return 1;
-}
-
-/*
- * moreinput gets more bytes to be passed to the lexer.
- * It can take more bytes from macro expansions or
- * directly reading from files. When a cpp directive
- * is processed the line is discarded because it must not
- * be passed to the lexer
- */
-static int
-moreinput(void)
-{
- int wasexpand = 0;
-
-repeat:
- if (!input)
- return 0;
-
- if (*input->p == '\0') {
- if ((input->flags&ITYPE) == IMACRO) {
- wasexpand = 1;
- input->flags |= IEOF;
- }
- if (input->flags & IEOF) {
- delinput();
- goto repeat;
- }
- if (!readline() || cpp()) {
- *input->p = '\0';
- goto repeat;
- }
- }
-
- if (onlycpp && !wasexpand)
- ppragmaln();
- return 1;
-}
-
-static void
-tok2str(void)
-{
- if ((yylen = input->p - input->begin) > INTIDENTSIZ)
- error("token too big");
- memcpy(yytext, input->begin, yylen);
- yytext[yylen] = '\0';
- input->begin = input->p;
-}
-
-static Symbol *
-readint(char *s, int base, int sign, Symbol *sym)
-{
- Type *tp = sym->type;
- struct limits *lim;
- TUINT u, val, max;
- int c;
-
- lim = getlimits(tp);
- max = lim->max.i;
- if (*s == '0')
- ++s;
- if (toupper(*s) == 'X')
- ++s;
-
- for (u = 0; isxdigit(c = *s++); u = u*base + val) {
- static char letters[] = "0123456789ABCDEF";
- val = strchr(letters, toupper(c)) - letters;
- repeat:
- if (u <= max/base && u*base <= max - val)
- continue;
- if (tp->prop & TSIGNED) {
- if (tp == inttype)
- tp = (base==10) ? longtype : uinttype;
- else if (tp == longtype)
- tp = (base==10) ? llongtype : ulongtype;
- else
- goto overflow;
- } else {
- if (tp == uinttype)
- tp = (sign==UNSIGNED) ? ulongtype : longtype;
- else if (tp == ulongtype)
- tp = (sign==UNSIGNED) ? ullongtype : llongtype;
- else
- goto overflow;
- }
- sym->type = tp;
- lim = getlimits(tp);
- max = lim->max.i;
- goto repeat;
- }
-
- if (tp->prop & TSIGNED)
- sym->u.i = u;
- else
- sym->u.u = u;
-
- return sym;
-
-overflow:
- errorp("overflow in integer constant");
- return sym;
-}
-
-static int
-integer(char *s, int base)
-{
- Type *tp;
- Symbol *sym;
- unsigned size, sign;
-
- for (size = sign = 0; ; ++input->p) {
- switch (toupper(*input->p)) {
- case 'L':
- if (size == LLONG)
- goto wrong_type;
- size = (size == LONG) ? LLONG : LONG;
- continue;
- case 'U':
- if (sign == UNSIGNED)
- goto wrong_type;
- sign = UNSIGNED;
- continue;
- default:
- goto convert;
- wrong_type:
- error("invalid suffix in integer constant");
- }
- }
-
-convert:
- tp = ctype(INT, sign, size);
- sym = newsym(NS_IDEN, NULL);
- sym->type = tp;
- sym->flags |= SCONSTANT;
- yylval.sym = readint(s, base, sign, sym);
- return CONSTANT;
-}
-
-static char *
-digits(int base)
-{
- char *p;
- int c;
-
- for (p = input->p; c = *p; ++p) {
- switch (base) {
- case 8:
- if (!strchr("01234567", c))
- goto end;
- break;
- case 10:
- if (!isdigit(c))
- goto end;
- break;
- case 16:
- if (!isxdigit(c))
- goto end;
- break;
- }
- }
-end:
- input->p = p;
- tok2str();
- return yytext;
-}
-
-static int
-number(void)
-{
- int base;
-
- if (*input->p != '0') {
- base = 10;
- } else {
- if (toupper(*++input->p) == 'X') {
- ++input->p;
- base = 16;
- } else {
- base = 8;
- }
- }
-
- return integer(digits(base), base);
-}
-
-static int
-escape(void)
-{
- int c, base;
-
- switch (*++input->p) {
- case 'a': return '\a';
- case 'f': return '\f';
- case 'n': return '\n';
- case 'r': return '\r';
- case 't': return '\t';
- case 'v': return '\v';
- case '"': return '"';
- case '\'': return '\'';
- case '\\': return '\\';
- case '\?': return '\?';
- case 'u':
- /*
- * FIXME: universal constants are not correctly handled
- */
- if (!isdigit(*++input->p))
- warn("incorrect digit for numerical character constant");
- base = 10;
- break;
- case 'x':
- if (!isxdigit(*++input->p))
- warn("\\x used with no following hex digits");
- base = 16;
- break;
- case '0':
- if (!strchr("01234567", *++input->p))
- warn("\\0 used with no following octal digits");
- base = 8;
- break;
- default:
- warn("unknown escape sequence");
- return ' ';
- }
- errno = 0;
- c = strtoul(input->p, &input->p, base);
- if (errno || c > 255)
- warn("character constant out of range");
- --input->p;
- return c;
-}
-
-static int
-character(void)
-{
- int c;
- Symbol *sym;
-
- if ((c = *++input->p) == '\\')
- c = escape();
- else
- c = *input->p;
- ++input->p;
- if (*input->p != '\'')
- errorp("invalid character constant");
- else
- ++input->p;
-
- sym = newsym(NS_IDEN, NULL);
- sym->u.i = c;
- sym->type = inttype;
- yylval.sym = sym;
- tok2str();
- return CONSTANT;
-}
-
-static int
-string(void)
-{
- char *bp = yytext;
- int c;
-
- *bp++ = '"';
- for (++input->p; (c = *input->p) != '"'; ++input->p) {
- if (c == '\0') {
- errorp("missing terminating '\"' character");
- break;
- }
- if (c == '\\')
- c = escape();
- if (bp == &yytext[STRINGSIZ+1]) {
- /* TODO: proper error handling here */
- error("string too long");
- }
- *bp++ = c;
- }
-
- input->begin = ++input->p;
- *bp = '\0';
-
- yylen = bp - yytext + 1;
- yylval.sym = newstring(yytext+1, yylen-1);
- *bp++ = '"';
- *bp = '\0';
- return STRING;
-}
-
-static int
-iden(void)
-{
- Symbol *sym;
- char *p, *begin;
-
- begin = input->p;
- for (p = begin; isalnum(*p) || *p == '_'; ++p)
- ;
- input->p = p;
- tok2str();
- if ((sym = lookup(NS_CPP, yytext, NOALLOC)) != NULL) {
- if (!disexpand && !sym->hide && expand(begin, sym))
- return next();
- }
- sym = lookup(namespace, yytext, ALLOC);
- yylval.sym = sym;
- if (sym->flags & SCONSTANT)
- return CONSTANT;
- if (sym->token != IDEN)
- yylval.token = sym->u.token;
- return sym->token;
-}
-
-static int
-follow(int expect, int ifyes, int ifno)
-{
- if (*input->p++ == expect)
- return ifyes;
- --input->p;
- return ifno;
-}
-
-static int
-minus(void)
-{
- switch (*input->p++) {
- case '-': return DEC;
- case '>': return INDIR;
- case '=': return SUB_EQ;
- default: --input->p; return '-';
- }
-}
-
-static int
-plus(void)
-{
- switch (*input->p++) {
- case '+': return INC;
- case '=': return ADD_EQ;
- default: --input->p; return '+';
- }
-}
-
-static int
-relational(int op, int equal, int shift, int assig)
-{
- int c;
-
- if ((c = *input->p++) == '=')
- return equal;
- if (c == op)
- return follow('=', assig, shift);
- --input->p;
- return op;
-}
-
-static int
-logic(int op, int equal, int logic)
-{
- int c;
-
- if ((c = *input->p++) == '=')
- return equal;
- if (c == op)
- return logic;
- --input->p;
- return op;
-}
-
-static int
-dot(void)
-{
- int c;
-
- if ((c = *input->p) != '.')
- return '.';
- if ((c = *++input->p) != '.')
- error("incorrect token '..'");
- ++input->p;
- return ELLIPSIS;
-}
-
-static int
-operator(void)
-{
- int t;
-
- switch (t = *input->p++) {
- case '<': t = relational('<', LE, SHL, SHL_EQ); break;
- case '>': t = relational('>', GE, SHR, SHR_EQ); break;
- case '&': t = logic('&', AND_EQ, AND); break;
- case '|': t = logic('|', OR_EQ, OR); break;
- case '=': t = follow('=', EQ, '='); break;
- case '^': t = follow('=', XOR_EQ, '^'); break;
- case '*': t = follow('=', MUL_EQ, '*'); break;
- case '/': t = follow('=', DIV_EQ, '/'); break;
- case '!': t = follow('=', NE, '!'); break;
- case '#': t = follow('#', '$', '#'); break;
- case '-': t = minus(); break;
- case '+': t = plus(); break;
- case '.': t = dot(); break;
- }
- tok2str();
- return t;
-}
-
-/* TODO: Ensure that namespace is NS_IDEN after a recovery */
-
-/*
- * skip all the spaces until the next token. When we are in
- * CPPMODE \n is not considered a whitespace
- */
-static int
-skipspaces(void)
-{
- int c;
-
- for (;;) {
- switch (c = *input->p) {
- case '\n':
- if (lexmode == CPPMODE)
- goto return_byte;
- ++input->p;
- case '\0':
- if (!moreinput())
- return EOF;
- break;
- case ' ':
- case '\t':
- case '\v':
- case '\r':
- case '\f':
- ++input->p;
- break;
- default:
- goto return_byte;
- }
- }
-
-return_byte:
- input->begin = input->p;
- return c;
-}
-
-int
-next(void)
-{
- int c;
-
- if ((c = skipspaces()) == EOF)
- yytoken = EOFTOK;
- else if (isalpha(c) || c == '_')
- yytoken = iden();
- else if (isdigit(c))
- yytoken = number();
- else if (c == '"')
- yytoken = string();
- else if (c == '\'')
- yytoken = character();
- else
- yytoken = operator();
-
- if (yytoken == EOF) {
- strcpy(yytext, "<EOF>");
- if (cppctx)
- errorp("#endif expected");
- }
-
- DBG("TOKEN %s", yytext);
- return yytoken;
-}
-
-void
-expect(int tok)
-{
- if (yytoken != tok) {
- if (isgraph(tok))
- errorp("expected '%c' before '%s'", tok, yytext);
- else
- errorp("unexpected '%s'", yytext);
- } else {
- next();
- }
-}
-
-int
-ahead(void)
-{
- skipspaces();
- return *input->begin;
-}
-
-void
-setsafe(int type)
-{
- safe = type;
-}
-
-void
-discard(void)
-{
- extern jmp_buf recover;
- int c;
-
- input->begin = input->p;
- for (c = yytoken; ; c = *input->begin++) {
- switch (safe) {
- case END_COMP:
- if (c == '}')
- goto jump;
- goto semicolon;
- case END_COND:
- if (c == ')')
- goto jump;
- break;
- case END_LDECL:
- if (c == ',')
- goto jump;
- case END_DECL:
- semicolon:
- if (c == ';')
- goto jump;
- break;
- }
- if (c == '\0' && !moreinput())
- exit(1);
- }
-jump:
- yytoken = c;
- longjmp(recover, 1);
-}
--- a/src/cmd/scc/cc1/main.c
+++ /dev/null
@@ -1,101 +1,0 @@
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <scc/arg.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-char *argv0, *infile;
-
-int warnings;
-jmp_buf recover;
-
-static struct items uflags;
-int onlycpp, onlyheader;
-
-
-extern int failure;
-
-static void
-defmacro(char *macro)
-{
- char *p = strchr(macro, '=');
-
- if (p)
- *p++ = '\0';
- else
- p = "1";
-
- defdefine(macro, p, "command-line");
-}
-
-static void
-usage(void)
-{
- fputs("usage: cc1 [-Ewd] [-D def[=val]]... [-U def]... "
- "[-I dir]... [-o output] [input]\n", stderr);
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- int i;
-
- ilex();
- icpp();
- icode();
- ibuilts();
-
- ARGBEGIN {
- case 'D':
- defmacro(EARGF(usage()));
- break;
- case 'M':
- onlyheader = 1;
- break;
- case 'E':
- onlycpp = 1;
- break;
- case 'I':
- incdir(EARGF(usage()));
- break;
- case 'U':
- newitem(&uflags, EARGF(usage()));
- break;
- case 'd':
- DBGON();
- break;
- case 'w':
- warnings = 1;
- break;
- default:
- usage();
- } ARGEND
-
- if (argc > 1)
- usage();
-
- for (i = 0; i < uflags.n; ++i)
- undefmacro(uflags.s[i]);
-
- infile = (*argv) ? *argv : "<stdin>";
- addinput(*argv, NULL, NULL);
-
- /*
- * we cannot initialize arch until we have an
- * output stream, because we maybe want to emit new types
- */
- iarch();
- if (onlycpp || onlyheader) {
- outcpp();
- } else {
- for (next(); yytoken != EOFTOK; decl())
- ;
- }
-
- return failure;
-}
--- a/src/cmd/scc/cc1/stmt.c
+++ /dev/null
@@ -1,385 +1,0 @@
-#include <stddef.h>
-#include <setjmp.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-#define NEGATE 1
-#define NONEGATE 0
-
-Symbol *curfun;
-
-static void stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch);
-
-static void
-label(void)
-{
- Symbol *sym;
-
- switch (yytoken) {
- case IDEN:
- case TYPEIDEN:
- sym = lookup(NS_LABEL, yytext, ALLOC);
- if (sym->flags & SDEFINED)
- error("label '%s' already defined", yytext);
- if ((sym->flags & SDECLARED) == 0)
- sym = install(NS_LABEL, sym);
- sym->flags |= SDEFINED;
- emit(OLABEL, sym);
- next();
- expect(':');
- break;
- default:
- unexpected();
- }
-}
-
-static void
-stmtexp(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
- Node *np;
-
- if (accept(';'))
- return;
- if (yytoken == IDEN && ahead() == ':') {
- label();
- stmt(lbreak, lcont, lswitch);
- return;
- }
- np = expr();
- if ((np->flags & NEFFECT) == 0)
- warn("expression without side effects");
- emit(OEXPR, np);
- expect(';');
-}
-
-static Node *
-condition(int neg)
-{
- Node *np;
-
- expect('(');
- np = condexpr(neg);
- expect(')');
-
- return np;
-}
-
-static void
-While(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
- Symbol *begin;
- Node *np;
-
- begin = newlabel();
- lcont = newlabel();
- lbreak = newlabel();
-
- expect(WHILE);
- np = condition(NONEGATE);
-
- emit(OJUMP, lcont);
-
- emit(OBLOOP, NULL);
- emit(OLABEL, begin);
- stmt(lbreak, lcont, lswitch);
- emit(OLABEL, lcont);
- emit(OBRANCH, begin);
- emit(OEXPR, np);
- emit(OELOOP, NULL);
-
- emit(OLABEL, lbreak);
-}
-
-static void
-For(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
- Symbol *begin, *cond;
- Node *econd, *einc;
-
- begin = newlabel();
- lcont = newlabel();
- cond = newlabel();
- lbreak = newlabel();
-
- pushctx();
-
- expect(FOR);
- expect('(');
- switch (yytoken) {
- case TYPE:
- case TYPEIDEN:
- case TQUALIFIER:
- case SCLASS:
- decl();
- break;
- default:
- emit(OEXPR, expr());
- case ';':
- expect(';');
- break;
- }
- econd = (yytoken != ';') ? condexpr(NONEGATE) : NULL;
- expect(';');
- einc = (yytoken != ')') ? expr() : NULL;
- expect(')');
-
- emit(OJUMP, cond);
-
- emit(OBLOOP, NULL);
- emit(OLABEL, begin);
- stmt(lbreak, lcont, lswitch);
- emit(OLABEL, lcont);
- emit(OEXPR, einc);
- emit(OLABEL, cond);
- emit((econd) ? OBRANCH : OJUMP, begin);
- emit(OEXPR, econd);
- emit(OELOOP, NULL);
-
- emit(OLABEL, lbreak);
-
- popctx();
-}
-
-static void
-Dowhile(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
- Symbol *begin;
- Node *np;
-
- begin = newlabel();
- lcont = newlabel();
- lbreak = newlabel();
-
- expect(DO);
-
- emit(OBLOOP, NULL);
- emit(OLABEL, begin);
- stmt(lbreak, lcont, lswitch);
- expect(WHILE);
- np = condition(NONEGATE);
- emit(OLABEL, lcont);
- emit(OBRANCH, begin);
- emit(OEXPR, np);
- emit(OELOOP, NULL);
-
- emit(OLABEL, lbreak);
-}
-
-static void
-Return(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
- Node *np;
- Type *tp = curfun->type->type;
-
- expect(RETURN);
- np = (yytoken != ';') ? decay(expr()) : NULL;
- expect(';');
- if (!np) {
- if (tp != voidtype)
- warn("function returning non void returns no value");
- tp = voidtype;
- } else if (np->type != tp) {
- if (tp == voidtype)
- warn("function returning void returns a value");
- else if ((np = convert(np, tp, 0)) == NULL)
- errorp("incorrect type in return");
- }
- emit(ORET, NULL);
- emit(OEXPR, np);
-}
-
-static void
-Break(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
- expect(BREAK);
- if (!lbreak) {
- errorp("break statement not within loop or switch");
- } else {
- emit(OJUMP, lbreak);
- expect(';');
- }
-}
-
-static void
-Continue(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
- expect(CONTINUE);
- if (!lcont) {
- errorp("continue statement not within loop");
- } else {
- emit(OJUMP, lcont);
- expect(';');
- }
-}
-
-static void
-Goto(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
- Symbol *sym;
-
- namespace = NS_LABEL;
- next();
- namespace = NS_IDEN;
-
- if (yytoken != IDEN)
- unexpected();
- sym = yylval.sym;
- if ((sym->flags & SDECLARED) == 0)
- sym = install(NS_LABEL, sym);
- sym->flags |= SUSED;
- emit(OJUMP, sym);
- next();
- expect(';');
-}
-
-static void
-Swtch(Symbol *obr, Symbol *lcont, Switch *osw)
-{
- Switch sw = {0};
- Node *cond;
- Symbol *lbreak;
-
- expect(SWITCH);
-
- expect ('(');
- if ((cond = convert(expr(), inttype, 0)) == NULL) {
- errorp("incorrect type in switch statement");
- cond = constnode(zero);
- }
- expect (')');
-
- lbreak = newlabel();
- emit(OBSWITCH, NULL);
- emit(OEXPR, cond);
- stmt(lbreak, lcont, &sw);
- emit(OESWITCH, lbreak);
- emit(OLABEL, lbreak);
-}
-
-static void
-Case(Symbol *lbreak, Symbol *lcont, Switch *sw)
-{
- Node *np;
- Symbol *label;
-
- expect(CASE);
- if ((np = constexpr()) == NULL)
- errorp("case label does not reduce to an integer constant");
- if (!sw) {
- errorp("case label not within a switch statement");
- } else if (sw->nr >= 0 && ++sw->nr == NR_SWITCH) {
- errorp("too many case labels for a switch statement");
- sw->nr = -1;
- }
- expect(':');
-
- label = newlabel();
- emit(OCASE, label);
- emit(OEXPR, np);
- emit(OLABEL, label);
- stmt(lbreak, lcont, sw);
-}
-
-static void
-Default(Symbol *lbreak, Symbol *lcont, Switch *sw)
-{
- Symbol *label = newlabel();
-
- if (sw->hasdef)
- errorp("multiple default labels in one switch");
- sw->hasdef = 1;
- expect(DEFAULT);
- expect(':');
- emit(ODEFAULT, label);
- emit(OLABEL, label);
- stmt(lbreak, lcont, sw);
-}
-
-static void
-If(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
- Symbol *end, *lelse;
- Node *np;
-
- lelse = newlabel();
- expect(IF);
- np = condition(NEGATE);
- emit(OBRANCH, lelse);
- emit(OEXPR, np);
- stmt(lbreak, lcont, lswitch);
- if (accept(ELSE)) {
- end = newlabel();
- emit(OJUMP, end);
- emit(OLABEL, lelse);
- stmt(lbreak, lcont, lswitch);
- emit(OLABEL, end);
- } else {
- emit(OLABEL, lelse);
- }
-}
-
-static void
-blockit(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
- switch (yytoken) {
- case TYPEIDEN:
- if (ahead() == ':')
- goto parse_stmt;
- case TYPE:
- case TQUALIFIER:
- case SCLASS:
- decl();
- return;
- default:
- parse_stmt:
- stmt(lbreak, lcont, lswitch);
- }
-}
-
-void
-compound(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
- static int nested;
-
- pushctx();
- expect('{');
-
- if (nested == NR_BLOCK)
- error("too many nesting levels of compound statements");
-
- ++nested;
- for (;;) {
- if (yytoken == '}')
- break;
- blockit(lbreak, lcont, lswitch);
- }
- --nested;
-
- popctx();
- expect('}');
-}
-
-static void
-stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
- void (*fun)(Symbol *, Symbol *, Switch *);
-
- switch (yytoken) {
- case '{': fun = compound; break;
- case RETURN: fun = Return; break;
- case WHILE: fun = While; break;
- case FOR: fun = For; break;
- case DO: fun = Dowhile; break;
- case IF: fun = If; break;
- case BREAK: fun = Break; break;
- case CONTINUE: fun = Continue; break;
- case GOTO: fun = Goto; break;
- case SWITCH: fun = Swtch; break;
- case CASE: fun = Case; break;
- case DEFAULT: fun = Default; break;
- default: fun = stmtexp; break;
- }
- (*fun)(lbreak, lcont, lswitch);
-}
--- a/src/cmd/scc/cc1/symbol.c
+++ /dev/null
@@ -1,351 +1,0 @@
-#include <assert.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-#define NR_SYM_HASH 64
-#define NR_CPP_HASH 32
-#define NR_LBL_HASH 16
-
-unsigned curctx;
-static unsigned short counterid;
-
-static Symbol *head, *labels;
-static Symbol *htab[NR_SYM_HASH];
-static Symbol *htabcpp[NR_CPP_HASH];
-static Symbol *htablbl[NR_LBL_HASH];
-
-#ifndef NDEBUG
-void
-dumpstab(Symbol **tbl, char *msg)
-{
- Symbol **bp, *sym;
- unsigned size;
-
- fprintf(stderr, "Symbol Table dump at ctx=%u\n%s\n", curctx, msg);
- if (tbl == htab)
- size = NR_SYM_HASH;
- else if (tbl == htabcpp)
- size = NR_CPP_HASH;
- else if (tbl == htablbl)
- size = NR_LBL_HASH;
- else
- abort();
-
- for (bp = tbl; bp < &tbl[size]; ++bp) {
- if (*bp == NULL)
- continue;
- fprintf(stderr, "%d", (int) (bp - htab));
- for (sym = *bp; sym; sym = sym->hash)
- fprintf(stderr, "->[%d,%d:'%s'=%p]",
- sym->ns, sym->ctx, sym->name, (void *) sym);
- putc('\n', stderr);
- }
- fputs("head:", stderr);
- for (sym = head; sym; sym = sym->next) {
- fprintf(stderr, "->[%d,%d:'%s'=%p]",
- sym->ns, sym->ctx,
- (sym->name) ? sym->name : "", (void *) sym);
- }
- fputs("\nlabels:", stderr);
- for (sym = labels; sym; sym = sym->next) {
- fprintf(stderr, "->[%d,%d:'%s'=%p]",
- sym->ns, sym->ctx,
- (sym->name) ? sym->name : "", (void *) sym);
- }
- putc('\n', stderr);
-}
-#endif
-
-static Symbol **
-hash(char *s, int ns)
-{
- unsigned h, size;
- Symbol **tab;
-
- h = genhash(s);
-
- switch (ns) {
- case NS_CPP:
- tab = htabcpp;
- size = NR_CPP_HASH-1;
- break;
- case NS_LABEL:
- tab = htablbl;
- size = NR_LBL_HASH-1;
- break;
- default:
- tab = htab;
- size = NR_SYM_HASH-1;
- break;
- }
- return &tab[h & size];
-}
-
-static void
-unlinkhash(Symbol *sym)
-{
- Symbol **h;
-
- if ((sym->flags & SDECLARED) == 0)
- return;
- h = hash(sym->name, sym->ns);
- assert(sym->ns == NS_CPP || *h == sym);
- while (*h != sym)
- h = &(*h)->hash;
- *h = sym->hash;
-}
-
-void
-pushctx(void)
-{
- DBG("SYM: pushed context %d", curctx+1);
- if (++curctx == NR_BLOCK+1)
- error("too many nested blocks");
-}
-
-void
-killsym(Symbol *sym)
-{
- short f;
- char *name;
-
- if (!sym)
- return;
- f = sym->flags;
- if (f & SSTRING)
- free(sym->u.s);
- if (sym->ns == NS_TAG)
- sym->type->prop &= ~TDEFINED;
- unlinkhash(sym);
- if ((name = sym->name) != NULL) {
- switch (sym->ns) {
- case NS_LABEL:
- if ((f & SDEFINED) == 0)
- errorp("label '%s' is not defined", name);
- case NS_IDEN:
- if ((f & (SUSED|SGLOBAL|SDECLARED)) == SDECLARED)
- warn("'%s' defined but not used", name);
- break;
- }
- }
- free(name);
- free(sym);
-}
-
-void
-popctx(void)
-{
- Symbol *next, *sym;
- int ns, dangling = 0;
-
- DBG("SYM: poped context %d", curctx);
- /*
- * we have to be careful before popping the current
- * context, because since the parser is one token
- * ahead it may already have read an identifier at
- * this point, and yylval.sym is a pointer to
- * the symbol associated to such token. If that
- * symbol is from the context that we are popping
- * then we are going to generate a dangling pointer.
- * We can detect this situation and call again to
- * lookup.
- */
- if ((yytoken == IDEN || yytoken == TYPEIDEN) &&
- yylval.sym->ctx == curctx) {
- ns = yylval.sym->ns;
- dangling = 1;
- }
-
- for (sym = head; sym && sym->ctx == curctx; sym = next) {
- /*
- * Since we are unlinking them in the inverse order
- * we do know that sym is always the head of the
- * collision list
- */
- next = sym->next;
- killsym(sym);
- }
- head = sym;
-
- if (--curctx == GLOBALCTX) {
- for (sym = labels; sym; sym = next) {
- next = sym->next;
- killsym(sym);
- }
- labels = NULL;
- }
-
- if (dangling) {
- yylval.sym = lookup(ns, yytext, ALLOC);
- yytoken = yylval.sym->token;
- }
-}
-
-unsigned
-newid(void)
-{
- unsigned short id;
-
- if (lexmode == CPPMODE)
- return 0;
- id = ++counterid;
- if (id == 0) {
- die("cc1: overflow in %s identifiers",
- (curctx) ? "internal" : "external");
- }
- return id;
-}
-
-Symbol *
-newsym(int ns, char *name)
-{
- Symbol *sym;
-
- sym = xmalloc(sizeof(*sym));
- if (name)
- name = xstrdup(name);
- sym->name = name;
- sym->id = 0;
- sym->hide = 0;
- sym->ns = ns;
- sym->ctx = curctx;
- sym->token = IDEN;
- sym->flags = 0;
- sym->u.s = NULL;
- sym->type = NULL;
- sym->hash = NULL;
-
- if (ns == NS_LABEL) {
- sym->next = labels;
- labels = sym;
- } else if (ns != NS_CPP) {
- sym->next = head;
- head = sym;
- }
- return sym;
-}
-
-static Symbol *
-linkhash(Symbol *sym)
-{
- Symbol **h;
-
- h = hash(sym->name, sym->ns);
- sym->hash = *h;
- *h = sym;
-
- if (sym->ns != NS_CPP)
- sym->id = newid();
- sym->flags |= SDECLARED;
- return sym;
-}
-
-Symbol *
-newstring(char *s, size_t len)
-{
- Symbol *sym = newsym(NS_IDEN, NULL);
-
- if (lexmode != CPPMODE)
- sym->type = mktype(chartype, ARY, len, NULL);
- sym->id = newid();
- sym->flags |= SSTRING | SCONSTANT | SPRIVATE;
- sym->u.s = xmalloc(len);
- if (s)
- memcpy(sym->u.s, s, len);
-
- return sym;
-}
-
-Symbol *
-newlabel(void)
-{
- Symbol *sym = newsym(NS_LABEL, NULL);
- sym->id = newid();
- return sym;
-}
-
-Symbol *
-lookup(int ns, char *name, int alloc)
-{
- Symbol *sym;
- int sns, c;
- char *t;
-
- c = *name;
- for (sym = *hash(name, ns); sym; sym = sym->hash) {
- t = sym->name;
- if (*t != c || strcmp(t, name))
- continue;
- sns = sym->ns;
- if (sns == ns)
- return sym;
- /*
- * When a lookup is done in a namespace associated
- * to a struct we also want symbols of NS_IDEN which
- * are typedef, because in other case we cannot declare
- * fields of such types.
- * TODO: Remove this trick
- */
- if (sns == NS_KEYWORD ||
- (sym->flags & STYPEDEF) && ns >= NS_STRUCTS) {
- return sym;
- }
- }
- return (alloc == ALLOC) ? newsym(ns, name) : NULL;
-}
-
-Symbol *
-install(int ns, Symbol *sym)
-{
- if (sym->flags & SDECLARED || sym->ctx != curctx) {
- if (sym->ctx == curctx && ns == sym->ns)
- return NULL;
- sym = newsym(ns, sym->name);
- }
- return linkhash(sym);
-}
-
-void
-keywords(struct keyword *key, int ns)
-{
- Symbol *sym;
-
- for ( ; key->str; ++key) {
- sym = linkhash(newsym(ns, key->str));
- sym->token = key->token;
- sym->u.token = key->value;
- }
- /*
- * Remove all the predefined symbols from * the symbol list. It
- * will make faster some operations. There is no problem of memory
- * leakeage because this memory is not ever freed
- */
- counterid = 0;
- head = NULL;
-}
-
-void
-builtins(struct builtin *built)
-{
- Symbol *sym;
- struct builtin *bp;
-
- for (bp = built; bp->str; ++bp) {
- sym = linkhash(newsym(NS_KEYWORD, bp->str));
- sym->token = BUILTIN;
- sym->u.fun = bp->fun;
- }
- /*
- * Remove all the predefined symbols from * the symbol list. It
- * will make faster some operations. There is no problem of memory
- * leakeage because this memory is not ever freed
- */
- counterid = 0;
- head = NULL;
-}
--- a/src/cmd/scc/cc1/target/amd64-sysv/arch.c
+++ /dev/null
@@ -1,218 +1,0 @@
-#include <scc/scc.h>
-#include "../../cc1.h"
-
-#define RANK_BOOL 0
-#define RANK_SCHAR 1
-#define RANK_UCHAR 1
-#define RANK_CHAR 1
-#define RANK_SHORT 2
-#define RANK_USHORT 2
-#define RANK_INT 3
-#define RANK_UINT 3
-#define RANK_LONG 4
-#define RANK_ULONG 4
-#define RANK_LLONG 5
-#define RANK_ULLONG 5
-#define RANK_FLOAT 6
-#define RANK_DOUBLE 7
-#define RANK_LDOUBLE 8
-
-/*
- * Initializaion of type pointers were done with
- * a C99 initilizator '... = &(Type) {...', but
- * c compiler in Plan9 gives error with this
- * syntax, so I have switched it to this ugly form
- * I hope I will change it again in the future
- */
-
-static Type types[] = {
- { /* 0 = voidtype */
- .op = VOID,
- .letter = L_VOID,
- },
- { /* 1 = pvoidtype */
- .op = PTR,
- .letter = L_POINTER,
- .prop = TDEFINED,
- .type = &types[5], /* chartype */
- .size = 8,
- .align = 8,
- },
- { /* 2 = booltype */
- .op = INT,
- .letter = L_BOOL,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 1,
- .align = 1,
- .n.rank = RANK_BOOL,
- },
- { /* 3 = schartype */
- .op = INT,
- .letter = L_INT8,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 1,
- .align = 1,
- .n.rank = RANK_SCHAR,
- },
- { /* 4 = uchartype */
- .op = INT,
- .letter = L_UINT8,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 1,
- .align = 1,
- .n.rank = RANK_UCHAR,
- },
- { /* 5 = chartype */
- .op = INT,
- .letter = L_INT8,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 1,
- .align = 1,
- .n.rank = RANK_CHAR,
- },
- { /* 6 = ushortype */
- .op = INT,
- .letter = L_UINT16,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 2,
- .align = 2,
- .n.rank = RANK_USHORT,
- },
- { /* 7 = shortype */
- .op = INT,
- .letter = L_INT16,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 2,
- .align = 2,
- .n.rank = RANK_SHORT,
- },
- { /* 8 = uinttype */
- .op = INT,
- .letter = L_UINT32,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 4,
- .align = 4,
- .n.rank = RANK_UINT,
- },
- { /* 9 = inttype */
- .op = INT,
- .letter = L_INT32,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 4,
- .align = 4,
- .n.rank = RANK_INT,
- },
- { /* 10 = longtype */
- .op = INT,
- .letter = L_INT64,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 8,
- .align = 8,
- .n.rank = RANK_LONG,
- },
- { /* 11 = ulongtype */
- .op = INT,
- .letter = L_UINT64,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 8,
- .align = 8,
- .n.rank = RANK_ULONG,
- },
- { /* 12 = ullongtype */
- .op = INT,
- .letter = L_UINT64,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 8,
- .align = 8,
- .n.rank = RANK_ULLONG,
- },
- { /* 13 = llongtype */
- .op = INT,
- .letter = L_INT64,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 8,
- .align = 8,
- .n.rank = RANK_LLONG,
- },
- { /* 14 = floattype */
- .op = FLOAT,
- .letter = L_FLOAT,
- .prop = TDEFINED | TARITH,
- .size = 4,
- .align = 4,
- .n.rank = RANK_FLOAT,
- },
- { /* 15 = doubletype */
- .op = FLOAT,
- .letter = L_DOUBLE,
- .prop = TDEFINED | TARITH,
- .size = 8,
- .align = 8,
- .n.rank = RANK_DOUBLE,
- },
- { /* 16 = ldoubletype */
- .op = FLOAT,
- .letter = L_LDOUBLE,
- .prop = TDEFINED | TARITH,
- .size = 16,
- .align = 16,
- .n.rank = RANK_LDOUBLE,
- },
- { /* 17 = sizettype */
- .op = INT,
- .letter = L_UINT64,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 8,
- .align = 8,
- .n.rank = RANK_UINT,
- },
- { /* 18 = ellipsis */
- .op = ELLIPSIS,
- .letter = L_ELLIPSIS,
- .prop = TDEFINED,
- },
- { /* 19 = pdifftype */
- .op = INT,
- .letter = L_INT64,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 8,
- .align = 8,
- .n.rank = RANK_LONG,
- },
- { /* 20 = va_type */
- .op = STRUCT,
- .letter = L_VA_ARG,
- .prop = TDEFINED,
- .size = 24,
- .align = 8,
- },
-};
-
-Type *voidtype = &types[0], *pvoidtype = &types[1],
- *booltype = &types[2], *schartype = &types[3],
- *uchartype = &types[4], *chartype = &types[5],
- *ushortype = &types[6], *shortype = &types[7],
- *uinttype = &types[8], *inttype = &types[9],
- *longtype = &types[10], *ulongtype = &types[11],
- *ullongtype = &types[12], *llongtype = &types[13],
- *floattype = &types[14], *doubletype = &types[15],
- *ldoubletype = &types[16],
- *sizettype = &types[17], *pdifftype = &types[19],
- *ellipsistype = &types[18], *va_type = &types[20],
- *va_list_type;
-
-static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
- dummy1 = {.u.i = 1, .type = &types[9]};
-Symbol *zero = &dummy0, *one = &dummy1;
-
-void
-iarch(void)
-{
- va_list_type = mktype(va_type, ARY, 1, NULL);
-}
-
-int
-valid_va_list(Type *tp)
-{
- return tp->op == PTR && eqtype(tp->type, va_type, 1);
-}
--- a/src/cmd/scc/cc1/target/amd64-sysv/arch.mk
+++ /dev/null
@@ -1,4 +1,0 @@
-OBJ-amd64-sysv= $(OBJS) target/amd64-sysv/arch.o
-
-$(LIBEXEC)/cc1-amd64-sysv: $(OBJ-amd64-sysv)
- $(CC) $(SCC_LDFLAGS) $(OBJ-amd64-sysv) -lscc -o $@
--- a/src/cmd/scc/cc1/target/arm64-sysv/arch.c
+++ /dev/null
@@ -1,218 +1,0 @@
-#include <scc/scc.h>
-#include "../../cc1.h"
-
-#define RANK_BOOL 0
-#define RANK_SCHAR 1
-#define RANK_UCHAR 1
-#define RANK_CHAR 1
-#define RANK_SHORT 2
-#define RANK_USHORT 2
-#define RANK_INT 3
-#define RANK_UINT 3
-#define RANK_LONG 4
-#define RANK_ULONG 4
-#define RANK_LLONG 5
-#define RANK_ULLONG 5
-#define RANK_FLOAT 6
-#define RANK_DOUBLE 7
-#define RANK_LDOUBLE 8
-
-/*
- * Initializaion of type pointers were done with
- * a C99 initilizator '... = &(Type) {...', but
- * c compiler in Plan9 gives error with this
- * syntax, so I have switched it to this ugly form
- * I hope I will change it again in the future
- */
-
-static Type types[] = {
- { /* 0 = voidtype */
- .op = VOID,
- .letter = L_VOID,
- },
- { /* 1 = pvoidtype */
- .op = PTR,
- .letter = L_POINTER,
- .prop = TDEFINED,
- .type = &types[5], /* chartype */
- .size = 8,
- .align = 8,
- },
- { /* 2 = booltype */
- .op = INT,
- .letter = L_BOOL,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 1,
- .align = 1,
- .n.rank = RANK_BOOL,
- },
- { /* 3 = schartype */
- .op = INT,
- .letter = L_INT8,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 1,
- .align = 1,
- .n.rank = RANK_SCHAR,
- },
- { /* 4 = uchartype */
- .op = INT,
- .letter = L_UINT8,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 1,
- .align = 1,
- .n.rank = RANK_UCHAR,
- },
- { /* 5 = chartype */
- .op = INT,
- .letter = L_INT8,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 1,
- .align = 1,
- .n.rank = RANK_CHAR,
- },
- { /* 6 = ushortype */
- .op = INT,
- .letter = L_UINT16,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 2,
- .align = 2,
- .n.rank = RANK_USHORT,
- },
- { /* 7 = shortype */
- .op = INT,
- .letter = L_INT16,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 2,
- .align = 2,
- .n.rank = RANK_SHORT,
- },
- { /* 8 = uinttype */
- .op = INT,
- .letter = L_UINT32,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 4,
- .align = 4,
- .n.rank = RANK_UINT,
- },
- { /* 9 = inttype */
- .op = INT,
- .letter = L_INT32,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 4,
- .align = 4,
- .n.rank = RANK_INT,
- },
- { /* 10 = longtype */
- .op = INT,
- .letter = L_INT64,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 8,
- .align = 8,
- .n.rank = RANK_LONG,
- },
- { /* 11 = ulongtype */
- .op = INT,
- .letter = L_UINT64,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 8,
- .align = 8,
- .n.rank = RANK_ULONG,
- },
- { /* 12 = ullongtype */
- .op = INT,
- .letter = L_UINT64,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 8,
- .align = 8,
- .n.rank = RANK_ULLONG,
- },
- { /* 13 = llongtype */
- .op = INT,
- .letter = L_INT64,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 8,
- .align = 8,
- .n.rank = RANK_LLONG,
- },
- { /* 14 = floattype */
- .op = FLOAT,
- .letter = L_FLOAT,
- .prop = TDEFINED | TARITH,
- .size = 4,
- .align = 4,
- .n.rank = RANK_FLOAT,
- },
- { /* 15 = doubletype */
- .op = FLOAT,
- .letter = L_DOUBLE,
- .prop = TDEFINED | TARITH,
- .size = 8,
- .align = 8,
- .n.rank = RANK_DOUBLE,
- },
- { /* 16 = ldoubletype */
- .op = FLOAT,
- .letter = L_LDOUBLE,
- .prop = TDEFINED | TARITH,
- .size = 16,
- .align = 16,
- .n.rank = RANK_LDOUBLE,
- },
- { /* 17 = sizettype */
- .op = INT,
- .letter = L_UINT64,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 8,
- .align = 8,
- .n.rank = RANK_UINT,
- },
- { /* 18 = ellipsis */
- .op = ELLIPSIS,
- .letter = L_ELLIPSIS,
- .prop = TDEFINED,
- },
- { /* 19 = pdifftype */
- .op = INT,
- .letter = L_INT64,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 8,
- .align = 8,
- .n.rank = RANK_LONG,
- },
- { /* 20 = va_type */
- .op = STRUCT,
- .letter = L_VA_ARG,
- .prop = TDEFINED,
- .size = 24,
- .align = 8,
- },
-};
-
-Type *voidtype = &types[0], *pvoidtype = &types[1],
- *booltype = &types[2], *schartype = &types[3],
- *uchartype = &types[4], *chartype = &types[5],
- *ushortype = &types[6], *shortype = &types[7],
- *uinttype = &types[8], *inttype = &types[9],
- *longtype = &types[10], *ulongtype = &types[11],
- *ullongtype = &types[12], *llongtype = &types[13],
- *floattype = &types[14], *doubletype = &types[15],
- *ldoubletype = &types[16],
- *sizettype = &types[17], *pdifftype = &types[19],
- *ellipsistype = &types[18], *va_type = &types[20],
- *va_list_type;
-
-static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
- dummy1 = {.u.i = 1, .type = &types[9]};
-Symbol *zero = &dummy0, *one = &dummy1;
-
-void
-iarch(void)
-{
- va_list_type = mktype(va_type, ARY, 1, NULL);
-}
-
-int
-valid_va_list(Type *tp)
-{
- return tp->op == PTR && eqtype(tp->type, va_type, 1);
-}
--- a/src/cmd/scc/cc1/target/arm64-sysv/arch.mk
+++ /dev/null
@@ -1,4 +1,0 @@
-OBJ-arm64-sysv= $(OBJS) target/arm64-sysv/arch.o
-
-$(LIBEXEC)/cc1-arm64-sysv: $(OBJ-arm64-sysv)
- $(CC) $(SCC_LDFLAGS) $(OBJ-arm64-sysv) -lscc -o $@
--- a/src/cmd/scc/cc1/target/i386-sysv/arch.c
+++ /dev/null
@@ -1,219 +1,0 @@
-#include <scc/scc.h>
-#include "../../cc1.h"
-
-#define RANK_BOOL 0
-#define RANK_SCHAR 1
-#define RANK_UCHAR 1
-#define RANK_CHAR 1
-#define RANK_SHORT 2
-#define RANK_USHORT 2
-#define RANK_INT 3
-#define RANK_UINT 3
-#define RANK_LONG 4
-#define RANK_ULONG 4
-#define RANK_LLONG 5
-#define RANK_ULLONG 5
-#define RANK_FLOAT 6
-#define RANK_DOUBLE 7
-#define RANK_LDOUBLE 8
-
-/*
- * Initializaion of type pointers were done with
- * a C99 initilizator '... = &(Type) {...', but
- * c compiler in Plan9 gives error with this
- * syntax, so I have switched it to this ugly form
- * I hope I will change it again in the future
- */
-
-static Type types[] = {
- { /* 0 = voidtype */
- .op = VOID,
- .letter = L_VOID,
- },
- { /* 1 = pvoidtype */
- .op = PTR,
- .letter = L_POINTER,
- .prop = TDEFINED,
- .type = &types[5], /* chartype */
- .size = 4,
- .align = 4,
- },
- { /* 2 = booltype */
- .op = INT,
- .letter = L_BOOL,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 1,
- .align = 1,
- .n.rank = RANK_BOOL,
- },
- { /* 3 = schartype */
- .op = INT,
- .letter = L_INT8,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 1,
- .align = 1,
- .n.rank = RANK_SCHAR,
- },
- { /* 4 = uchartype */
- .op = INT,
- .letter = L_UINT8,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 1,
- .align = 1,
- .n.rank = RANK_UCHAR,
- },
- { /* 5 = chartype */
- .op = INT,
- .letter = L_INT8,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 1,
- .align = 1,
- .n.rank = RANK_CHAR,
- },
- { /* 6 = ushortype */
- .op = INT,
- .letter = L_UINT16,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 2,
- .align = 2,
- .n.rank = RANK_USHORT,
- },
- { /* 7 = shortype */
- .op = INT,
- .letter = L_INT16,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 2,
- .align = 2,
- .n.rank = RANK_SHORT,
- },
- { /* 8 = uinttype */
- .op = INT,
- .letter = L_UINT32,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 4,
- .align = 4,
- .n.rank = RANK_UINT,
- },
- { /* 9 = inttype */
- .op = INT,
- .letter = L_INT32,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 4,
- .align = 4,
- .n.rank = RANK_INT,
- },
- { /* 10 = longtype */
- .op = INT,
- .letter = L_INT32,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 4,
- .align = 4,
- .n.rank = RANK_LONG,
- },
- { /* 11 = ulongtype */
- .op = INT,
- .letter = L_UINT32,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 4,
- .align = 4,
- .n.rank = RANK_ULONG,
- },
- { /* 12 = ullongtype */
- .op = INT,
- .letter = L_UINT64,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 8,
- .align = 4,
- .n.rank = RANK_ULLONG,
- },
- { /* 13 = llongtype */
- .op = INT,
- .letter = L_INT64,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 8,
- .align = 4,
- .n.rank = RANK_LLONG,
- },
- { /* 14 = floattype */
- .op = FLOAT,
- .letter = L_FLOAT,
- .prop = TDEFINED | TARITH,
- .size = 4,
- .align = 4,
- .n.rank = RANK_FLOAT,
- },
- { /* 15 = doubletype */
- .op = FLOAT,
- .letter = L_DOUBLE,
- .prop = TDEFINED | TARITH,
- .size = 8,
- .align = 4,
- .n.rank = RANK_DOUBLE,
- },
- { /* 16 = ldoubletype */
- .op = FLOAT,
- .letter = L_LDOUBLE,
- .prop = TDEFINED | TARITH,
- .size = 12,
- .align = 4,
- .n.rank = RANK_LDOUBLE,
- },
- { /* 17 = sizettype */
- .op = INT,
- .letter = L_UINT32,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 4,
- .align = 4,
- .n.rank = RANK_UINT,
- },
- { /* 18 = ellipsis */
- .op = ELLIPSIS,
- .letter = L_ELLIPSIS,
- .prop = TDEFINED,
- },
- { /* 19 = pdifftype */
- .op = INT,
- .letter = L_INT32,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 4,
- .align = 4,
- .n.rank = RANK_INT,
- },
- { /* 20 = va_list_type */
- .op = PTR,
- .letter = L_POINTER,
- .prop = TDEFINED,
- .size = 4,
- .align = 4,
- },
-};
-
-
-Type *voidtype = &types[0], *pvoidtype = &types[1],
- *booltype = &types[2], *schartype = &types[3],
- *uchartype = &types[4], *chartype = &types[5],
- *ushortype = &types[6], *shortype = &types[7],
- *uinttype = &types[8], *inttype = &types[9],
- *longtype = &types[10], *ulongtype = &types[11],
- *ullongtype = &types[12], *llongtype = &types[13],
- *floattype = &types[14], *doubletype = &types[15],
- *ldoubletype = &types[16],
- *sizettype = &types[17], *pdifftype = &types[19],
- *ellipsistype = &types[18], *va_list_type = &types[20];
-
-
-
-static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
- dummy1 = {.u.i = 1, .type = &types[9]};
-Symbol *zero = &dummy0, *one = &dummy1;
-
-void
-iarch(void)
-{
-}
-
-int
-valid_va_list(Type *tp)
-{
- return eqtype(tp, va_list_type, 1);
-}
--- a/src/cmd/scc/cc1/target/i386-sysv/arch.mk
+++ /dev/null
@@ -1,4 +1,0 @@
-OBJ-i386-sysv= $(OBJS) target/i386-sysv/arch.o
-
-$(LIBEXEC)/cc1-i386-sysv: $(OBJ-i386-sysv)
- $(CC) $(SCC_LDFLAGS) $(OBJ-i386-sysv) -lscc -o $@
--- a/src/cmd/scc/cc1/target/z80-scc/arch.c
+++ /dev/null
@@ -1,217 +1,0 @@
-#include <scc/scc.h>
-#include "../../cc1.h"
-
-#define RANK_BOOL 0
-#define RANK_SCHAR 1
-#define RANK_UCHAR 1
-#define RANK_CHAR 1
-#define RANK_SHORT 2
-#define RANK_USHORT 2
-#define RANK_INT 3
-#define RANK_UINT 3
-#define RANK_LONG 4
-#define RANK_ULONG 4
-#define RANK_LLONG 5
-#define RANK_ULLONG 5
-#define RANK_FLOAT 6
-#define RANK_DOUBLE 7
-#define RANK_LDOUBLE 8
-
-/*
- * Initializaion of type pointers were done with
- * a C99 initilizator '... = &(Type) {...', but
- * c compiler in Plan9 gives error with this
- * syntax, so I have switched it to this ugly form
- * I hope I will change it again in the future
- */
-
-static Type types[] = {
- { /* 0 = voidtype */
- .op = VOID,
- .letter = L_VOID,
- },
- { /* 1 = pvoidtype */
- .op = PTR,
- .letter = L_POINTER,
- .prop = TDEFINED,
- .type = &types[5], /* char type */
- .size = 2,
- .align = 2,
- },
- { /* 2 = booltype */
- .op = INT,
- .letter = L_BOOL,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 1,
- .align = 1,
- .n.rank = RANK_BOOL,
- },
- { /* 3 = schartype */
- .op = INT,
- .letter = L_INT8,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 1,
- .align = 1,
- .n.rank = RANK_SCHAR,
- },
- { /* 4 = uchartype */
- .op = INT,
- .letter = L_UINT8,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 1,
- .align = 1,
- .n.rank = RANK_UCHAR,
- },
- { /* 5 = chartype */
- .op = INT,
- .letter = L_UINT8,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 1,
- .align = 1,
- .n.rank = RANK_CHAR,
- },
- { /* 6 = ushortype */
- .op = INT,
- .letter = L_UINT16,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 2,
- .align = 1,
- .n.rank = RANK_USHORT,
- },
- { /* 7 = shortype */
- .op = INT,
- .letter = L_INT16,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 2,
- .align = 1,
- .n.rank = RANK_SHORT,
- },
- { /* 8 = uinttype */
- .op = INT,
- .letter = L_UINT16,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 2,
- .align = 1,
- .n.rank = RANK_UINT,
- },
- { /* 9 = inttype */
- .op = INT,
- .letter = L_INT16,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 2,
- .align = 1,
- .n.rank = RANK_INT,
- },
- { /* 10 = longtype */
- .op = INT,
- .letter = L_INT32,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 4,
- .align = 1,
- .n.rank = RANK_LONG,
- },
- { /* 11 = ulongtype */
- .op = INT,
- .letter = L_UINT32,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 4,
- .align = 1,
- .n.rank = RANK_ULONG,
- },
- { /* 12 = ullongtype */
- .op = INT,
- .letter = L_UINT64,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 8,
- .align = 1,
- .n.rank = RANK_ULLONG,
- },
- { /* 13 = llongtype */
- .op = INT,
- .letter = L_INT64,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 8,
- .align = 1,
- .n.rank = RANK_LLONG,
- },
- { /* 14 = floattype */
- .op = FLOAT,
- .letter = L_FLOAT,
- .prop = TDEFINED | TARITH,
- .size = 4,
- .align = 1,
- .n.rank = RANK_FLOAT,
- },
- { /* 15 = doubletype */
- .op = FLOAT,
- .letter = L_DOUBLE,
- .prop = TDEFINED | TARITH,
- .size = 8,
- .align = 1,
- .n.rank = RANK_DOUBLE,
- },
- { /* 16 = ldoubletype */
- .op = FLOAT,
- .letter = L_LDOUBLE,
- .prop = TDEFINED | TARITH,
- .size = 16,
- .align = 1,
- .n.rank = RANK_LDOUBLE,
- },
- { /* 17 = sizettype */
- .op = INT,
- .letter = L_UINT16,
- .prop = TDEFINED | TINTEGER | TARITH,
- .size = 2,
- .align = 1,
- .n.rank = RANK_UINT,
- },
- { /* 18 = ellipsis */
- .op = ELLIPSIS,
- .letter = L_ELLIPSIS,
- .prop = TDEFINED,
- },
- { /* 7 = pdifftype */
- .op = INT,
- .letter = L_INT16,
- .prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
- .size = 2,
- .align = 1,
- .n.rank = RANK_SHORT,
- },
- { /* 20 = va_list_type */
- .op = PTR,
- .letter = L_POINTER,
- .prop = TDEFINED,
- .size = 2,
- .align = 1,
- }
-};
-
-Type *voidtype = &types[0], *pvoidtype = &types[1],
- *booltype = &types[2], *schartype = &types[3],
- *uchartype = &types[4], *chartype = &types[5],
- *ushortype = &types[6], *shortype = &types[7],
- *uinttype = &types[8], *inttype = &types[9],
- *longtype = &types[10], *ulongtype = &types[11],
- *ullongtype = &types[12], *llongtype = &types[13],
- *floattype = &types[14], *doubletype = &types[15],
- *ldoubletype = &types[16],
- *sizettype = &types[17], *pdifftype = &types[19],
- *ellipsistype = &types[18], *va_list_type = &types[20];
-
-
-static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
- dummy1 = {.u.i = 1, .type = &types[9]};
-Symbol *zero = &dummy0, *one = &dummy1;
-
-void
-iarch(void)
-{
-}
-
-int
-valid_va_list(Type *tp)
-{
- return eqtype(tp, va_list_type, 1);
-}
--- a/src/cmd/scc/cc1/target/z80-scc/arch.mk
+++ /dev/null
@@ -1,4 +1,0 @@
-OBJ-z80-scc= $(OBJS) target/z80-scc/arch.o
-
-$(LIBEXEC)/cc1-z80-scc: $(OBJ-z80-scc)
- $(CC) $(SCC_LDFLAGS) $(OBJ-z80-scc) -lscc -o $@
--- a/src/cmd/scc/cc1/types.c
+++ /dev/null
@@ -1,437 +1,0 @@
-#include <assert.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-#define NR_TYPE_HASH 16
-#define HASH(t) (((t)->op ^ (uintptr_t) (t)->type>>3) & NR_TYPE_HASH-1)
-
-static Type *typetab[NR_TYPE_HASH], *localtypes;
-
-/* FIXME:
- * Compiler can generate warnings here if the ranges of TINT,
- * TUINT and TFLOAT are smaller than any of the constants in this
- * array. Ignore them if you know that the target types are correct
- */
-static struct limits limits[][4] = {
- {
- { /* 0 = unsigned 1 byte */
- .min.i = 0,
- .max.i = 0xff
- },
- { /* 1 = unsigned 2 bytes */
- .min.i = 0,
- .max.i = 0xffff
- },
- { /* 2 = unsigned 4 bytes */
- .min.i = 0,
- .max.i = 0xffffffff
- },
- { /* 3 = unsigned 8 bytes */
- .min.i = 0,
- .max.i = 0xffffffffffffffff
- }
- },
- {
- { /* 0 = signed 1 byte */
- .min.i = -0x7f-1,
- .max.i = 0x7f
- },
- { /* 1 = signed 2 byte */
- .min.i = -0x7fff-1,
- .max.i = 0x7fff
- },
- { /* 2 = signed 4 byte */
- .min.i = -0x7fffffff-1,
- .max.i = 0x7fffffff
- },
- { /* 3 = signed 8 byte */
- .min.i = -0x7fffffffffffffff-1,
- .max.i = 0x7fffffffffffffff,
- }
- },
- {
- {
- /* 0 = float 4 bytes */
- .min.f = -1,
- .max.f = 2
- },
- {
- /* 1 = float 8 bytes */
- .min.f = -1,
- .max.f = 2,
- },
- {
- /* 2 = float 16 bytes */
- .min.f = -1,
- .max.f = 2,
- }
- }
-};
-
-struct limits *
-getlimits(Type *tp)
-{
- int ntable, ntype;
-
- switch (tp->op) {
- case ENUM:
- case INT:
- ntable = ((tp->prop & TSIGNED) != 0);
- switch (tp->size) {
- case 1: ntype = 0; break;
- case 2: ntype = 1; break;
- case 4: ntype = 2; break;
- case 8: ntype = 3; break;
- }
- break;
- case FLOAT:
- ntable = 2;
- switch (tp->size) {
- case 4: ntype = 0; break;
- case 8: ntype = 1; break;
- case 16: ntype = 2; break;
- }
- break;
- default:
- abort();
- }
-
- return &limits[ntable][ntype];
-}
-
-Type *
-ctype(int type, int sign, int size)
-{
- switch (type) {
- case CHAR:
- if (size)
- goto invalid_type;
- switch (sign) {
- case 0:
- return chartype;
- case SIGNED:
- return schartype;
- case UNSIGNED:
- return uchartype;
- }
- break;
- case VA_LIST:
- if (size || sign)
- goto invalid_type;
- return va_list_type;
- case VOID:
- if (size || sign)
- goto invalid_type;
- return voidtype;
- case BOOL:
- if (size || sign)
- goto invalid_type;
- return booltype;
- case 0:
- case INT:
- switch (size) {
- case 0:
- return (sign == UNSIGNED) ? uinttype : inttype;
- case SHORT:
- return (sign == UNSIGNED) ? ushortype : shortype;
- case LONG:
- return (sign == UNSIGNED) ? ulongtype : longtype;
- case LLONG:
- return (sign == UNSIGNED) ? ullongtype : llongtype;
- }
- break;
- case DOUBLE:
- if (size == LLONG)
- goto invalid_type;
- if (size == LONG)
- size = LLONG;
- else
- size = LONG;
- goto floating;
- case FLOAT:
- if (size == LLONG)
- goto invalid_type;
- floating:
- if (sign)
- goto invalid_type;
- switch (size) {
- case 0:
- return floattype;
- case LONG:
- return doubletype;
- case LLONG:
- return ldoubletype;
- }
- break;
- }
-
-invalid_type:
- error("invalid type specification");
-}
-
-void
-typesize(Type *tp)
-{
- Symbol **sp;
- Type *type;
- unsigned long size, offset;
- int align, a;
- TINT n;
-
- switch (tp->op) {
- case ARY:
- /* FIXME: Control overflow */
- tp->size = tp->n.elem * tp->type->size;
- tp->align = tp->type->align;
- return;
- case PTR:
- tp->size = pvoidtype->size;
- tp->align = pvoidtype->align;
- return;
- case STRUCT:
- case UNION:
- /* FIXME: Control overflow */
- /*
- * The alignment of the struct/union is
- * he alignment of the largest included type.
- * The size of an union is the size of the largest
- * field, and the size of a struct is the sum
- * of the size of every field plus padding bits.
- */
- offset = align = size = 0;
- n = tp->n.elem;
- for (sp = tp->p.fields; n--; ++sp) {
- (*sp)->u.i = offset;
- type = (*sp)->type;
- a = type->align;
- if (a > align)
- align = a;
- if (tp->op == STRUCT) {
- if (--a != 0)
- size = (size + a) & ~a;
- size += type->size;
- offset = size;
- } else {
- if (type->size > size)
- size = type->size;
- }
- }
-
- tp->align = align;
- /*
- * We have to add the padding bits to
- * ensure next struct in an array is well
- * alignment.
- */
- if (tp->op == STRUCT && align-- > 1)
- size += size+align & ~align;
- tp->size = size;
- return;
- case ENUM:
- tp->size = inttype->size;
- tp->align = inttype->align;
- return;
- case FTN:
- return;
- default:
- abort();
- }
-}
-
-Type *
-deftype(Type *tp)
-{
- tp->prop |= TDEFINED;
- typesize(tp);
- emit(OTYP, tp);
- return tp;
-}
-
-static Type *
-newtype(Type *base)
-{
- Type *tp;
- size_t siz;
-
- tp = xmalloc(sizeof(*tp));
- *tp = *base;
- tp->id = newid();
-
- if (tp->op == FTN) {
- siz = tp->n.elem * sizeof(Type *);
- tp->p.pars = memcpy(xmalloc(siz), tp->p.pars, siz);
- }
-
- if (curfun) {
- /* it is a type defined in the body of a function */
- tp->next = localtypes;
- localtypes = tp;
- }
- if (tp->prop & TDEFINED)
- deftype(tp);
- return tp;
-}
-
-Type *
-mktype(Type *tp, int op, TINT nelem, Type *pars[])
-{
- Type **tbl, type;
- Type *bp;
-
- if (op == PTR && tp == voidtype)
- return pvoidtype;
-
- memset(&type, 0, sizeof(type));
- type.type = tp;
- type.op = op;
- type.p.pars = pars;
- type.n.elem = nelem;
-
- switch (op) {
- case ARY:
- if (tp == voidtype) {
- errorp("declaration of array of voids type");
- tp = inttype;
- }
- type.letter = L_ARRAY;
- if (nelem != 0)
- type.prop |= TDEFINED;
- break;
- case KRFTN:
- type.prop |= TDEFINED | TK_R;
- type.op = FTN;
- type.letter = L_FUNCTION;
- break;
- case FTN:
- if (nelem > 0 && pars[nelem-1] == ellipsistype)
- type.prop |= TELLIPSIS;
- type.letter = L_FUNCTION;
- type.prop |= TDEFINED;
- break;
- case PTR:
- type.letter = L_POINTER;
- type.prop |= TDEFINED;
- break;
- case ENUM:
- type.letter = inttype->letter;
- type.prop |= TINTEGER | TARITH;
- type.n.rank = inttype->n.rank;
- goto create_type;
- case STRUCT:
- type.letter = L_STRUCT;
- type.prop |= TAGGREG;
- goto create_type;
- case UNION:
- type.letter = L_UNION;
- type.prop |= TAGGREG;
- create_type:
- return newtype(&type);
- default:
- abort();
- }
-
- tbl = &typetab[HASH(&type)];
- for (bp = *tbl; bp; bp = bp->h_next) {
- if (eqtype(bp, &type, 0))
- return bp;
- }
-
- bp = newtype(&type);
- bp->h_next = *tbl;
- *tbl = bp;
-
- return bp;
-}
-
-int
-eqtype(Type *tp1, Type *tp2, int equiv)
-{
- TINT n;
- Type **p1, **p2;
- Symbol **s1, **s2;
-
- if (tp1 == tp2)
- return 1;
- if (!tp1 || !tp2)
- return 0;
- if (tp1->op != tp2->op)
- return 0;
-
- switch (tp1->op) {
- case UNION:
- case STRUCT:
- if (tp1->letter != tp2->letter)
- return 0;
- if (tp1->tag->name || tp2->tag->name)
- return tp1->tag == tp2->tag;
- if (tp1->n.elem != tp2->n.elem)
- return 0;
- s1 = tp1->p.fields, s2 = tp2->p.fields;
- for (n = tp1->n.elem; n > 0; --n, ++s1, ++s2) {
- if (strcmp((*s1)->name, (*s2)->name))
- return 0;
- if (!eqtype((*s1)->type, (*s2)->type, equiv))
- return 0;
- }
- return 1;
- case FTN:
- if (tp1->n.elem != tp2->n.elem)
- return 0;
- p1 = tp1->p.pars, p2 = tp2->p.pars;
- for (n = tp1->n.elem; n > 0; --n) {
- if (!eqtype(*p1++, *p2++, equiv))
- return 0;
- }
- goto check_base;
- case ARY:
- if (equiv && (tp1->n.elem == 0 || tp2->n.elem == 0))
- goto check_base;
- if (tp1->n.elem != tp2->n.elem)
- return 0;
- case PTR:
- check_base:
- return eqtype(tp1->type, tp2->type, equiv);
- case VOID:
- case ENUM:
- return 0;
- case INT:
- case FLOAT:
- return tp1->letter == tp2->letter;
- default:
- abort();
- }
-}
-
-void
-flushtypes(void)
-{
- Type *tp, *next, **h;
-
- for (tp = localtypes; tp; tp = next) {
- next = tp->next;
- switch (tp->op) {
- default:
- /*
- * All the local types are linked after
- * global types, and since we are
- * unlinking them in the inverse order
- * we do know that tp is always the head
- * of the collision list
- */
- h = &typetab[HASH(tp)];
- assert(*h == tp);
- *h = tp->h_next;
- case STRUCT:
- case UNION:
- case ENUM:
- free(tp);
- break;
- }
- }
- localtypes = NULL;
-}
--- a/src/cmd/scc/cc2/.gitignore
+++ /dev/null
@@ -1,1 +1,0 @@
-error.h
--- a/src/cmd/scc/cc2/Makefile
+++ /dev/null
@@ -1,40 +1,0 @@
-.POSIX:
-
-PROJECTDIR = ../../../..
-include $(PROJECTDIR)/scripts/rules.mk
-
-MORECFLAGS = -I$(INCDIR)/$(STD)
-
-OBJS = main.o \
- parser.o \
- peep.o \
- symbol.o \
- node.o \
- code.o \
- optm.o \
-
-TARGET = $(LIBEXEC)/cc2-amd64-sysv \
- $(LIBEXEC)/cc2-i386-sysv \
- $(LIBEXEC)/cc2-qbe_amd64-sysv \
- $(LIBEXEC)/cc2-z80-scc \
-
-all: $(TARGET)
-
-$(TARGET): error.h
-
-error.h: cc2.h
- rm -f $@;\
- trap 'r=$?;rm -f $$$$.h;exit $r' EXIT INT QUIT ;\
- awk -f generror.awk cc2.h > $$$$.h && mv $$$$.h $@
-
-dep: inc-dep
-
-clean:
- rm -f target/*/*.o error.h
-
-include target/amd64-sysv/target.mk
-include target/i386-sysv/target.mk
-include target/qbe_amd64-sysv/target.mk
-include target/qbe_arm64-sysv/target.mk
-include target/z80-scc/target.mk
-include deps.mk
--- a/src/cmd/scc/cc2/cc2.h
+++ /dev/null
@@ -1,256 +1,0 @@
-enum iflags {
- BBENTRY = 1, /* basic block entry */
-};
-
-enum tflags {
- SIGNF = 1 << 0, /* Signed type */
- INTF = 1 << 1, /* integer type */
- FLOATF = 1 << 2, /* float type */
- STRF = 1 << 3, /* string */
- AGGRF = 1 << 4, /* aggregate */
- FUNF = 1 << 5, /* function */
- PARF = 1 << 6, /* parameter */
- INITF = 1 << 7, /* initializer flag */
- ELLIPS = 1 << 8, /* vararg function */
-};
-
-enum sclass {
- SAUTO = 'A',
- SREG = 'R',
- SLABEL = 'L',
- SINDEX = 'I',
- STMP = 'N',
- SGLOB = 'G',
- SEXTRN = 'X',
- SPRIV = 'Y',
- SLOCAL = 'T',
- SMEMB = 'M',
- SCONST = '#',
- STRING = '"',
- SNONE = 0 /* cc2 relies on SNONE being 0 in nextpc() */
-};
-
-enum types {
- ELLIPSIS = 'E',
- INT8 = 'C',
- INT16 = 'I',
- INT32 = 'W',
- INT64 = 'Q',
- UINT8 = 'K',
- UINT16 = 'N',
- UINT32 = 'Z',
- UINT64 = 'O',
- POINTER = 'P',
- FUNCTION = 'F',
- VECTOR = 'V',
- UNION = 'U',
- STRUCT = 'S',
- BOOL = 'B',
- FLOAT = 'J',
- DOUBLE = 'D',
- LDOUBLE = 'H',
- VOID = '0'
-};
-
-enum op {
- /* kind of operand */
- /* operands */
- OMEM = 'M',
- OTMP = 'N',
- OAUTO = 'A',
- OREG = 'R',
- OCONST = '#',
- OSTRING = '"',
- OLOAD = 'D',
- OLABEL = 'L',
- OADD = '+',
- OSUB = '-',
- OMUL = '*',
- OMOD = '%',
- ODIV = '/',
- OSHL = 'l',
- OSHR = 'r',
- OLT = '<',
- OGT = '>',
- OLE = '[',
- OGE = ']',
- OEQ = '=',
- ONE = '!',
- OBAND = '&',
- OBOR = '|',
- OBXOR = '^',
- OCPL = '~',
- OASSIG = ':',
- OSNEG = '_',
- OCALL = 'c',
- OCALLE = 'z',
- OPAR = 'p',
- OFIELD = '.',
- OCOMMA = ',',
- OASK = '?',
- OCOLON = ' ',
- OADDR = '\'',
- OAND = 'a',
- OOR = 'o',
- ONEG = 'n',
- OPTR = '@',
- OCAST = 'g',
- OINC = 'i',
- ODEC = 'd',
- OBUILTIN = 'm',
- /*statements */
- ONOP = 'q',
- OJMP = 'j',
- OBRANCH = 'y',
- ORET = 'h',
- OBLOOP = 'b',
- OELOOP = 'e',
- OCASE = 'v',
- ODEFAULT = 'f',
- OBSWITCH = 's',
- OESWITCH = 't',
- OBFUN = 'x',
- OEFUN = 'k',
-};
-
-enum builtins {
- BVA_START = 's',
- BVA_END = 'e',
- BVA_ARG = 'a',
- BVA_COPY = 'c',
-};
-
-enum nerrors {
- EEOFFUN, /* EOF while parsing function */
- ENLABEL, /* label without statement */
- EIDOVER, /* identifier overflow */
- EOUTPAR, /* out pf params */
- ESYNTAX, /* syntax error */
- ESTACKA, /* stack unaligned */
- ESTACKO, /* stack overflow */
- ESTACKU, /* stack underflow */
- ELNLINE, /* line too long */
- ELNBLNE, /* line without new line */
- EFERROR, /* error reading from file:%s */
- EBADID, /* incorrect symbol id */
- EWTACKO, /* switch stack overflow */
- EWTACKU, /* switch stack underflow */
- ENOSWTC, /* Out of switch statement */
- EBBUILT, /* Unknown builtin */
- ENUMERR
-};
-
-typedef struct node Node;
-typedef struct type Type;
-typedef struct symbol Symbol;
-typedef struct addr Addr;
-typedef struct inst Inst;
-
-struct type {
- unsigned long size;
- unsigned long align;
- short flags;
-};
-
-struct symbol {
- Type type;
- Type rtype;
- unsigned short id;
- unsigned short numid;
- char *name;
- char kind;
- union {
- unsigned long off;
- Node *stmt;
- Inst *inst;
- } u;
- Symbol *next;
- Symbol *h_next;
-};
-
-struct node {
- char op;
- Type type;
- char complex;
- char address;
- unsigned char flags;
- union {
- TUINT i;
- TFLOAT f;
- char reg;
- char *s;
- Symbol *sym;
- char subop;
- } u;
- Symbol *label;
- Node *left, *right;
- Node *next, *prev;
-};
-
-struct addr {
- char kind;
- union {
- char reg;
- TUINT i;
- Symbol *sym;
- } u;
-};
-
-struct inst {
- unsigned char op;
- unsigned char flags;
- Symbol *label;
- Inst *next, *prev;
- Addr from1, from2, to;
-};
-
-/* main.c */
-extern void error(unsigned nerror, ...);
-
-/* parse.c */
-extern void parse(void);
-
-/* optm.c */
-extern Node *optm_dep(Node *np), *optm_ind(Node *np);
-
-/* cgen.c */
-extern Node *sethi(Node *np);
-extern Node *cgen(Node *np);
-
-/* peep.c */
-extern void peephole(void);
-
-/* code.c */
-extern void data(Node *np);
-extern void writeout(void), endinit(void), newfun(void);
-extern void code(int op, Node *to, Node *from1, Node *from2);
-extern void defvar(Symbol *), defpar(Symbol *), defglobal(Symbol *);
-extern void setlabel(Symbol *sym), getbblocks(void);
-extern Node *label2node(Node *np, Symbol *sym);
-extern Node *constnode(Node *np, TUINT n, Type *tp);
-extern Symbol *newlabel(void);
-
-/* node.c */
-#define SETCUR 1
-#define KEEPCUR 0
-extern void apply(Node *(*fun)(Node *));
-extern void cleannodes(void);
-extern void delnode(Node *np);
-extern void deltree(Node *np);
-extern void prtree(Node *np), prforest(char *msg);
-extern Node *node(int op);
-extern Node *addstmt(Node *np, int flags);
-extern Node *delstmt(void);
-extern Node *nextstmt(void);
-
-/* symbol.c */
-#define TMPSYM 0
-extern Symbol *getsym(unsigned id);
-extern void popctx(void);
-extern void pushctx(void);
-extern void freesym(Symbol *sym);
-
-/* globals */
-extern Symbol *curfun;
-extern Symbol *locals;
-extern Inst *pc, *prog;
--- a/src/cmd/scc/cc2/code.c
+++ /dev/null
@@ -1,132 +1,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/scc.h>
-#include "cc2.h"
-
-Inst *pc, *prog;
-
-static void
-nextpc(void)
-{
- Inst *new;
-
- new = xcalloc(1, sizeof(*new)); /* TODO: create an arena */
-
- if (!pc) {
- prog = new;
- } else {
- new->next = pc->next;
- pc->next = new;
- }
-
- /* SNONE being 0, calloc initialized {from1,from2,to}.kind for us */
- new->prev = pc;
- pc = new;
-}
-
-static void
-addr(Node *np, Addr *addr)
-{
- Symbol *sym;
-
- switch (np->op) {
- case OREG:
- /* TODO:
- * At this moment this op is used also for register variables
- */
- addr->kind = SREG;
- addr->u.reg = np->u.reg;
- break;
- case OCONST:
- addr->kind = SCONST;
- /* TODO: Add support for more type of constants */
- addr->u.i = np->u.i;
- break;
- case OTMP:
- case OLABEL:
- case OAUTO:
- case OMEM:
- sym = np->u.sym;
- addr->kind = sym->kind;
- addr->u.sym = sym;
- break;
- default:
- abort();
- }
-}
-
-Symbol *
-newlabel(void)
-{
- Symbol *sym = getsym(TMPSYM);
-
- sym->kind = SLABEL;
- return sym;
-}
-
-Node *
-label2node(Node *np, Symbol *sym)
-{
- if(!sym)
- sym = newlabel();
- if (!np)
- np = node(OLABEL);
- np->op = OLABEL;
- np->u.sym = sym;
-
- return np;
-}
-
-Node *
-constnode(Node *np, TUINT n, Type *tp)
-{
- if (!np)
- np = node(OCONST);
- np->op = OCONST;
- np->left = NULL;
- np->right = NULL;
- np->type = *tp;
- np->u.i = n;
- return np;
-}
-
-void
-setlabel(Symbol *sym)
-{
- if (!sym)
- return;
- code(0, NULL, NULL, NULL);
- pc->label = sym;
- sym->u.inst = pc;
-}
-
-void
-code(int op, Node *to, Node *from1, Node *from2)
-{
- nextpc();
- if (from1)
- addr(from1, &pc->from1);
- if (from2)
- addr(from2, &pc->from2);
- if (to)
- addr(to, &pc->to);
- pc->op = op;
-}
-
-void
-delcode(void)
-{
- Inst *prev = pc->prev, *next = pc->next;
-
- free(pc);
- if (!prev) {
- pc = next;
- prog = NULL;
- } else {
- pc = prev;
- prev->next = next;
- if (next)
- next->prev = prev;
- }
-}
--- a/src/cmd/scc/cc2/deps.mk
+++ /dev/null
@@ -1,61 +1,0 @@
-#deps
-./code.o: $(INCDIR)/scc/scc/scc.h
-./code.o: ./cc2.h
-./main.o: $(INCDIR)/scc/scc/arg.h
-./main.o: $(INCDIR)/scc/scc/scc.h
-./main.o: ./cc2.h
-./main.o: ./error.h
-./node.o: $(INCDIR)/scc/scc/scc.h
-./node.o: ./cc2.h
-./optm.o: $(INCDIR)/scc/scc/scc.h
-./optm.o: ./cc2.h
-./parser.o: $(INCDIR)/scc/scc/cstd.h
-./parser.o: $(INCDIR)/scc/scc/scc.h
-./parser.o: ./cc2.h
-./peep.o: $(INCDIR)/scc/scc/scc.h
-./peep.o: ./cc2.h
-./symbol.o: $(INCDIR)/scc/scc/scc.h
-./symbol.o: ./cc2.h
-./target/amd64-sysv/cgen.o: $(INCDIR)/scc/scc/scc.h
-./target/amd64-sysv/cgen.o: ./target/amd64-sysv/../../cc2.h
-./target/amd64-sysv/cgen.o: ./target/amd64-sysv/arch.h
-./target/amd64-sysv/code.o: $(INCDIR)/scc/scc/cstd.h
-./target/amd64-sysv/code.o: $(INCDIR)/scc/scc/scc.h
-./target/amd64-sysv/code.o: ./target/amd64-sysv/../../cc2.h
-./target/amd64-sysv/code.o: ./target/amd64-sysv/arch.h
-./target/amd64-sysv/optm.o: $(INCDIR)/scc/scc/scc.h
-./target/amd64-sysv/optm.o: ./target/amd64-sysv/../../cc2.h
-./target/amd64-sysv/types.o: $(INCDIR)/scc/scc/scc.h
-./target/amd64-sysv/types.o: ./target/amd64-sysv/../../cc2.h
-./target/i386-sysv/cgen.o: $(INCDIR)/scc/scc/scc.h
-./target/i386-sysv/cgen.o: ./target/i386-sysv/../../cc2.h
-./target/i386-sysv/cgen.o: ./target/i386-sysv/arch.h
-./target/i386-sysv/code.o: $(INCDIR)/scc/scc/cstd.h
-./target/i386-sysv/code.o: $(INCDIR)/scc/scc/scc.h
-./target/i386-sysv/code.o: ./target/i386-sysv/../../cc2.h
-./target/i386-sysv/code.o: ./target/i386-sysv/arch.h
-./target/i386-sysv/optm.o: $(INCDIR)/scc/scc/scc.h
-./target/i386-sysv/optm.o: ./target/i386-sysv/../../cc2.h
-./target/i386-sysv/types.o: $(INCDIR)/scc/scc/scc.h
-./target/i386-sysv/types.o: ./target/i386-sysv/../../cc2.h
-./target/qbe/cgen.o: $(INCDIR)/scc/scc/cstd.h
-./target/qbe/cgen.o: $(INCDIR)/scc/scc/scc.h
-./target/qbe/cgen.o: ./target/qbe/../../cc2.h
-./target/qbe/cgen.o: ./target/qbe/arch.h
-./target/qbe/code.o: $(INCDIR)/scc/scc/cstd.h
-./target/qbe/code.o: $(INCDIR)/scc/scc/scc.h
-./target/qbe/code.o: ./target/qbe/../../cc2.h
-./target/qbe/code.o: ./target/qbe/arch.h
-./target/qbe/optm.o: $(INCDIR)/scc/scc/scc.h
-./target/qbe/optm.o: ./target/qbe/../../cc2.h
-./target/z80-scc/cgen.o: $(INCDIR)/scc/scc/scc.h
-./target/z80-scc/cgen.o: ./target/z80-scc/../../cc2.h
-./target/z80-scc/cgen.o: ./target/z80-scc/arch.h
-./target/z80-scc/code.o: $(INCDIR)/scc/scc/cstd.h
-./target/z80-scc/code.o: $(INCDIR)/scc/scc/scc.h
-./target/z80-scc/code.o: ./target/z80-scc/../../cc2.h
-./target/z80-scc/code.o: ./target/z80-scc/arch.h
-./target/z80-scc/optm.o: $(INCDIR)/scc/scc/scc.h
-./target/z80-scc/optm.o: ./target/z80-scc/../../cc2.h
-./target/z80-scc/types.o: $(INCDIR)/scc/scc/scc.h
-./target/z80-scc/types.o: ./target/z80-scc/../../cc2.h
--- a/src/cmd/scc/cc2/generror.awk
+++ /dev/null
@@ -1,9 +1,0 @@
-/^enum nerrors \{/ {print "char *errlist[] = {"; inhome = 1}
-
-inhome && /E[A-Z]*, / {sub(/,/, "", $1)
- printf("\t[%s] = \"", $1)
- for (i = 3; i <= NF-1; ++i)
- printf("%s%s", $i, (i == NF-1) ? "\"" : " ")
- print ","}
-
-inhome && /^}/ {print "};" ; inhome = 0}
--- a/src/cmd/scc/cc2/main.c
+++ /dev/null
@@ -1,68 +1,0 @@
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/arg.h>
-#include <scc/scc.h>
-#include "cc2.h"
-#include "error.h"
-
-char *argv0;
-
-void
-error(unsigned nerror, ...)
-{
- va_list va;
- va_start(va, nerror);
- vfprintf(stderr, errlist[nerror], va);
- va_end(va);
- putc('\n', stderr);
- exit(1);
-}
-
-static int
-moreinput(void)
-{
- int c;
-
-repeat:
- if (feof(stdin))
- return 0;
- if ((c = getchar()) == '\n' || c == EOF)
- goto repeat;
- ungetc(c, stdin);
- return 1;
-}
-
-static void
-usage(void)
-{
- fputs("usage: cc2 [irfile]\n", stderr);
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- ARGBEGIN {
- default:
- usage();
- } ARGEND
-
- if (argv[0] && !freopen(argv[0], "r", stdin))
- die("cc2: %s: %s", argv[0], strerror(errno));
-
- while (moreinput()) {
- parse();
- apply(optm_ind);
- apply(optm_dep);
- apply(sethi);
- apply(cgen);
- getbblocks(); /* TODO: run apply over asm ins too */
- peephole();
- writeout();
- }
- return 0;
-}
--- a/src/cmd/scc/cc2/node.c
+++ /dev/null
@@ -1,141 +1,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/scc.h>
-
-#include "cc2.h"
-
-#define NNODES 32
-
-Node *curstmt;
-Symbol *curfun;
-
-static Alloc *arena;
-
-
-Node *
-node(int op)
-{
- struct arena *ap;
- Node *np;
-
- if (!arena)
- arena = alloc(sizeof(Node), NNODES);
- np = memset(new(arena), 0, sizeof(*np));
- np->op = op;
-
- return np;
-}
-
-#ifndef NDEBUG
-#include <stdio.h>
-
-static void
-prnode(Node *np)
-{
- if (np->left)
- prnode(np->left);
- if (np->right)
- prnode(np->right);
- fprintf(stderr, "\t%c%lu", np->op, np->type.size);
-}
-
-void
-prtree(Node *np)
-{
- prnode(np);
- putc('\n', stderr);
-}
-
-void
-prforest(char *msg)
-{
- Node *np;
-
- if (!curfun)
- return;
-
- fprintf(stderr, "%s {\n", msg);
- for (np = curfun->u.stmt; np; np = np->next)
- prtree(np);
- fputs("}\n", stderr);
-}
-#endif
-
-Node *
-addstmt(Node *np, int flag)
-{
- if (curstmt)
- np->next = curstmt->next;
- np->prev = curstmt;
-
- if (!curfun->u.stmt)
- curfun->u.stmt = np;
- else
- curstmt->next = np;
-
- if (flag == SETCUR)
- curstmt = np;
-
- return np;
-}
-
-Node *
-delstmt(void)
-{
- Node *next, *prev;
-
- next = curstmt->next;
- prev = curstmt->prev;
- if (next)
- next->prev = prev;
- if (prev)
- prev->next = next;
- else
- curfun->u.stmt = next;
- deltree(curstmt);
-
- return curstmt = next;
-}
-
-Node *
-nextstmt(void)
-{
- return curstmt = curstmt->next;
-}
-
-void
-delnode(Node *np)
-{
- delete(arena, np);
-}
-
-void
-deltree(Node *np)
-{
- if (!np)
- return;
- deltree(np->left);
- deltree(np->right);
- delnode(np);
-}
-
-void
-cleannodes(void)
-{
- if (arena) {
- dealloc(arena);
- arena = NULL;
- }
- curstmt = NULL;
-}
-
-void
-apply(Node *(*fun)(Node *))
-{
- if (!curfun)
- return;
- curstmt = curfun->u.stmt;
- while (curstmt)
- (*fun)(curstmt) ? nextstmt() : delstmt();
-}
--- a/src/cmd/scc/cc2/optm.c
+++ /dev/null
@@ -1,9 +1,0 @@
-#include <scc/scc.h>
-#include "cc2.h"
-
-Node *
-optm_ind(Node *np)
-{
- return np;
-}
-
--- a/src/cmd/scc/cc2/parser.c
+++ /dev/null
@@ -1,721 +1,0 @@
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "cc2.h"
-
-#define STACKSIZ 50
-
-extern Type int8type, int16type, int32type, int64type,
- uint8type, uint16type, uint32type, uint64type,
- float32type, float64type, float80type,
- booltype,
- ptrtype,
- voidtype,
- arg_type;
-
-Type funetype = {
- .flags = FUNF | ELLIPS
-};
-
-Type funtype = {
- .flags = FUNF
-};
-
-union tokenop {
- void *arg;
- unsigned op;
-};
-
-struct swtch {
- int nr;
- Node *first;
- Node *last;
-};
-
-static struct swtch swtbl[NR_BLOCK], *swp = swtbl;
-static Symbol *lastfun;
-
-typedef void parsefun(char *, union tokenop);
-static parsefun type, symbol, getname, unary, binary, ternary, call,
- constant, composed, binit, einit,
- jump, oreturn, loop, assign,
- ocase, bswitch, eswitch, builtin;
-
-typedef void evalfun(void);
-static evalfun vardecl, beginfun, endfun, endpars, stmt,
- array, aggregate, flddecl, labeldcl;
-
-static struct decoc {
- void (*eval)(void);
- void (*parse)(char *token, union tokenop);
- union tokenop u;
-} optbl[] = { /* eval parse args */
- ['A'] = { vardecl, symbol, .u.op = SAUTO<<8 | OAUTO},
- ['R'] = { vardecl, symbol, .u.op = SREG<<8 | OREG},
- ['G'] = { vardecl, symbol, .u.op = SGLOB<<8 | OMEM},
- ['X'] = { vardecl, symbol, .u.op = SEXTRN<<8 | OMEM},
- ['Y'] = { vardecl, symbol, .u.op = SPRIV<<8 | OMEM},
- ['T'] = { vardecl, symbol, .u.op = SLOCAL<<8 | OMEM},
- ['M'] = { flddecl, symbol, .u.op = SMEMB<<8 | OMEM},
- ['L'] = { labeldcl, symbol, .u.op = SLABEL<<8 | OLABEL},
-
- ['C'] = { NULL, type, .u.arg = &int8type},
- ['I'] = { NULL, type, .u.arg = &int16type},
- ['W'] = { NULL, type, .u.arg = &int32type},
- ['Q'] = { NULL, type, .u.arg = &int64type},
- ['K'] = { NULL, type, .u.arg = &uint8type},
- ['N'] = { NULL, type, .u.arg = &uint16type},
- ['Z'] = { NULL, type, .u.arg = &uint32type},
- ['O'] = { NULL, type, .u.arg = &uint64type},
- ['J'] = { NULL, type, .u.arg = &float32type},
- ['D'] = { NULL, type, .u.arg = &float64type},
- ['H'] = { NULL, type, .u.arg = &float80type},
- ['0'] = { NULL, type, .u.arg = &voidtype},
- ['B'] = { NULL, type, .u.arg = &booltype},
- ['P'] = { NULL, type, .u.arg = &ptrtype},
- ['E'] = { NULL, type, .u.arg = &funetype},
- ['1'] = { NULL, type, .u.arg = &arg_type},
-
- ['F'] = { NULL, type, .u.arg = &funtype},
- ['V'] = { array,composed, 0},
- ['U'] = {aggregate,composed, 0},
- ['S'] = {aggregate,composed, 0},
-
- ['"'] = { NULL, getname, 0},
- ['{'] = { beginfun, NULL, 0},
- ['}'] = { endfun, NULL, 0},
- ['('] = { NULL, binit, 0},
- [')'] = { NULL, einit, 0},
- ['\\'] = { endpars, NULL, 0},
- ['\t'] = { stmt, NULL, 0},
-
- ['~'] = { NULL, unary, .u.op = OCPL},
- ['_'] = { NULL, unary, .u.op = OSNEG},
- ['\''] = { NULL, unary, .u.op = OADDR},
- ['@'] = { NULL, unary, .u.op = OPTR},
- ['g'] = { NULL, unary, .u.op = OCAST},
- ['p'] = { NULL, unary, .u.op = OPAR},
- ['n'] = { NULL, unary, .u.op = ONEG},
-
- ['a'] = { NULL, binary, .u.op = OAND},
- ['o'] = { NULL, binary, .u.op = OOR},
- ['.'] = { NULL, binary, .u.op = OFIELD},
- ['+'] = { NULL, binary, .u.op = OADD},
- ['-'] = { NULL, binary, .u.op = OSUB},
- ['*'] = { NULL, binary, .u.op = OMUL},
- ['%'] = { NULL, binary, .u.op = OMOD},
- ['/'] = { NULL, binary, .u.op = ODIV},
- ['l'] = { NULL, binary, .u.op = OSHL},
- ['r'] = { NULL, binary, .u.op = OSHR},
- ['<'] = { NULL, binary, .u.op = OLT},
- ['>'] = { NULL, binary, .u.op = OGT},
- ['['] = { NULL, binary, .u.op = OLE},
- [']'] = { NULL, binary, .u.op = OGE},
- ['='] = { NULL, binary, .u.op = OEQ},
- ['!'] = { NULL, binary, .u.op = ONE},
- ['&'] = { NULL, binary, .u.op = OBAND},
- ['|'] = { NULL, binary, .u.op = OBOR},
- ['^'] = { NULL, binary, .u.op = OBXOR},
- [','] = { NULL, binary, .u.op = OCOMMA},
- ['m'] = { NULL, builtin,.u.op = OBUILTIN},
-
- [':'] = { NULL, assign, .u.op = OASSIG},
- ['?'] = { NULL, ternary, .u.op = OASK},
- ['c'] = { NULL, call, .u.op = OCALL},
- ['z'] = { NULL, call, .u.op = OCALLE},
-
- ['#'] = { NULL,constant, .u.op = OCONST},
-
- ['j'] = { NULL, jump, .u.op = OJMP},
- ['y'] = { NULL, jump, .u.op = OBRANCH},
- ['h'] = { NULL, oreturn, .u.op = ORET},
- ['i'] = { NULL, NULL, .u.op = OINC},
- ['d'] = { NULL, NULL, .u.op = ODEC},
-
- ['b'] = { NULL, loop, .u.op = OBLOOP},
- ['e'] = { NULL, loop, .u.op = OELOOP},
-
- ['v'] = { NULL, ocase, .u.op = OCASE},
- ['f'] = { NULL, ocase, .u.op = ODEFAULT},
- ['t'] = { NULL, eswitch, .u.op = OESWITCH},
- ['s'] = { NULL, bswitch, .u.op = OBSWITCH},
-};
-
-static int sclass, inpars, ininit, endf, lineno;
-static void *stack[STACKSIZ], **sp = stack;
-
-static Node *
-push(void *elem)
-{
- if (sp == &stack[STACKSIZ])
- error(ESTACKO);
- return *sp++ = elem;
-}
-
-static void *
-pop(void)
-{
- if (sp == stack)
- error(ESTACKU);
- return *--sp;
-}
-
-static int
-empty(void)
-{
- return sp == stack;
-}
-
-static void
-type(char *token, union tokenop u)
-{
- push(u.arg);
-}
-
-static void
-composed(char *token, union tokenop u)
-{
- Symbol *sym;
-
- sym = getsym(atoi(token+1));
- push(&sym->type);
-}
-
-static void
-getname(char *t, union tokenop u)
-{
- push((*++t) ? xstrdup(t) : NULL);
-}
-
-static void
-symbol(char *token, union tokenop u)
-{
- Node *np = node(u.op & 0xFF);
- Symbol *sym = getsym(atoi(token+1));
-
- sclass = u.op >> 8;
- np->u.sym = sym;
- np->type = sym->type;
- push(np);
-}
-
-static Type *
-gettype(char *token)
-{
- struct decoc *dp;
-
- dp = &optbl[*token];
- if (!dp->parse)
- error(ESYNTAX);
- (*dp->parse)(token, dp->u);
- return pop();
-}
-
-static void
-constant(char *token, union tokenop u)
-{
- static char letters[] = "0123456789ABCDEF";
- Node *np;
- TUINT v;
- unsigned c;
-
- ++token;
- if (*token == '"') {
- ++token;
- np = node(OSTRING);
- np->type.flags = STRF;
- np->type.size = strlen(token);
- np->type.align = int8type.align;
- np->u.s = xstrdup(token);
- } else {
- np = node(OCONST);
- np->type = *gettype(token++);
- for (v = 0; c = *token++; v += c) {
- v <<= 4;
- c = strchr(letters, c) - letters;
- }
- np->u.i = v;
- }
- push(np);
-}
-
-static void
-assign(char *token, union tokenop u)
-{
- int subop;
- Node *np = node(u.op);
-
- switch (subop = *++token) {
- case '+':
- case '-':
- case '*':
- case '%':
- case '/':
- case 'l':
- case 'r':
- case '&':
- case '|':
- case '^':
- case 'i':
- case 'd':
- ++token;
- subop = optbl[subop].u.op;
- break;
- default:
- subop = 0;
- break;
- }
-
- np->u.subop = subop;
- np->type = *gettype(token);
- np->right = pop();
- np->left = pop();
- push(np);
-}
-
-static void
-ternary(char *token, union tokenop u)
-{
- Node *ask = node(OASK), *colon = node(OCOLON);
- Type *tp = gettype(token+1);
-
- colon->right = pop();
- colon->left = pop();
-
- ask->type = *tp;
- ask->left = pop();
- ask->right = colon;
- push(ask);
-}
-
-static void
-eval(char *tok)
-{
- struct decoc *dp;
-
- do {
- dp = &optbl[*tok];
- if (!dp->parse)
- break;
- (*dp->parse)(tok, dp->u);
- } while (tok = strtok(NULL, "\t\n"));
-}
-
-static int
-nextline(void)
-{
- static char line[LINESIZ];
- size_t len;
- int c;
- void (*fun)(void);
-
-repeat:
- ++lineno;
- if (!fgets(line, sizeof(line), stdin))
- return 0;
- if ((len = strlen(line)) == 0 || line[0] == '\n')
- goto repeat;
- if (line[len-1] != '\n')
- error(len < sizeof(line)-1 ? ELNBLNE : ELNLINE);
- line[len-1] = '\0';
-
- c = *line;
- eval(strtok(line, "\t\n"));
- if ((fun = *optbl[c].eval) != NULL)
- (*fun)();
- if (sp != stack)
- error(ESTACKA);
- return 1;
-}
-
-static void
-oreturn(char *token, union tokenop u)
-{
- Node *np = node(u.op);
-
- if (token = strtok(NULL, "\t\n"))
- eval(token);
- if (!empty())
- np->left = pop();
- push(np);
-}
-
-/*
- * Move np (which is a OCASE/ODEFAULT/OESWITCH) to be contigous with
- * the last switch table. It is a bit ugly to touch directly curstmt
- * here, but moving this function to node.c is worse, because we are
- * putting knowledge of how the text is parsed into the node
- * represtation module.
- */
-static void
-waft(Node *np)
-{
- Node *lastcase, *next;;
- struct swtch *cur;
- extern Node *curstmt;
-
- if (swp == swtbl)
- error(EWTACKU);
-
- cur = swp - 1;
- lastcase = cur->last;
- next = lastcase->next;
-
- np->next = next;
- np->prev = lastcase;
-
- if (next)
- next->prev = np;
- lastcase->next = np;
-
- if (curstmt == cur->last)
- curstmt = np;
- cur->last = np;
- cur->nr++;
-}
-
-static void
-bswitch(char *token, union tokenop u)
-{
- struct swtch *cur;
- Node *np = node(u.op);
-
- if (swp == &swtbl[NR_BLOCK])
- error(EWTACKO);
- cur = swp++;
- cur->nr = 0;
-
- eval(strtok(NULL, "\t\n"));
- np->left = pop();
-
- push(cur->first = cur->last = np);
-}
-
-static void
-eswitch(char *token, union tokenop u)
-{
- struct swtch *cur;
-
- if (swp == swtbl)
- error(EWTACKU);
- jump(token, u);
- waft(pop());
- cur = --swp;
- cur->first->u.i = cur->nr;
-}
-
-static void
-ocase(char *token, union tokenop u)
-{
- jump(token, u);
- waft(pop());
-}
-
-static void
-jump(char *token, union tokenop u)
-{
- Node *aux, *np = node(u.op);
-
- eval(strtok(NULL, "\t\n"));
-
- if (u.op == OBRANCH || u.op == OCASE)
- np->left = pop();
- aux = pop();
- np->u.sym = aux->u.sym;
- delnode(aux);
- push(np);
-}
-
-static void
-loop(char *token, union tokenop u)
-{
- push(node(u.op));
-}
-
-static void
-unary(char *token, union tokenop u)
-{
- Node *np = node(u.op);
-
- np->type = *gettype(token+1);
- np->left = pop();
- np->right = NULL;
- push(np);
-}
-
-static void
-call(char *token, union tokenop u)
-{
- Node *np, *par, *fun = node(u.op);
-
- for (par = NULL;; par = np) {
- np = pop();
- if (np->op != OPAR)
- break;
- np->right = par;
- }
-
- fun->type = *gettype(token+1);
- fun->left = np;
- fun->right = par;
- push(fun);
-}
-
-static void
-builtin(char *token, union tokenop u)
-{
- Node *np = node(u.op);
- char *name;
- unsigned subop, nchilds;
-
- np->type = *gettype(token+1);
- name = pop();
-
- if (!strcmp("__builtin_va_arg", name)) {
- nchilds = 1;
- subop = BVA_ARG;
- } else if (!strcmp("__builtin_va_start", name)) {
- nchilds = 2;
- subop = BVA_START;
- } else if (!strcmp("__builtin_va_end", name)) {
- nchilds = 1;
- subop = BVA_END;
- } else if (!strcmp("__builtin_va_copy", name)) {
- nchilds = 2;
- subop = BVA_COPY;
- } else {
- error(EBBUILT);;
- }
-
- np->u.subop = subop;
- np->right = (nchilds == 2) ? pop() : NULL;
- np->left = (nchilds != 0) ? pop() : NULL;
-
- free(name);
- push(np);
-}
-
-static void
-binary(char *token, union tokenop u)
-{
- Node *np = node(u.op);
-
- np->type = *gettype(token+1);
- np->right = pop();
- np->left = pop();
- push(np);
-}
-
-static void
-binit(char *token, union tokenop u)
-{
- ininit = 1;
-}
-
-static void
-einit(char *token, union tokenop u)
-{
- ininit = 0;
- endinit();
-}
-
-static void
-endpars(void)
-{
- if (!curfun || !inpars)
- error(ESYNTAX);
- inpars = 0;
-}
-
-static void
-aggregate(void)
-{
- Node *align, *size;
- char *name;
- Type *tp;
- Symbol *sym;
-
- align = pop();
- size = pop();
- name = pop();
- tp = pop();
-
- tp->size = size->u.i;
- tp->align = align->u.i;
- tp->flags = AGGRF;
- /*
- * type is the first field of Symbol so we can obtain the
- * address of the symbol from the address of the type.
- * We have to do this because composed returns the pointer
- * to the type, but in this function we also need the
- * symbol to store the name.
- */
- sym = (Symbol *) tp;
- sym->name = name;
-
- delnode(align);
- delnode(size);
-}
-
-static void
-array(void)
-{
- Type *tp, *base;
- Node *size;
-
- size = pop();
- base = pop();
- tp = pop();
- tp->size = size->u.i * base->size; /* FIXME check for overflow */
- tp->align = base->align;
-
- delnode(size);
-}
-
-static void
-decl(Symbol *sym)
-{
- Type *tp = &sym->type;
-
- if (tp->flags & FUNF) {
- lastfun = sym;
- } else {
- switch (sym->kind) {
- case SEXTRN:
- case SGLOB:
- case SPRIV:
- case SLOCAL:
- defglobal(sym);
- break;
- case SAUTO:
- case SREG:
- if (!curfun)
- error(ESYNTAX);
- ((inpars) ? defpar : defvar)(sym);
- break;
- default:
- abort();
- }
- }
-}
-
-static void
-vardecl(void)
-{
- Type *tp, *rp;
- Node *np;
- Symbol *sym;
- char *name;
-
- name = pop();
- tp = pop();
- if (tp->flags & FUNF)
- rp = pop();
- np = pop();
-
- sym = np->u.sym;
- /*
- * We have to free sym->name because in tentative declarations
- * we can have multiple declarations of the same symbol, and in
- * this case our parser will allocate twice the memory
- */
- free(sym->name);
- sym->name = name;
- sym->type = *tp;
- if (tp->flags & FUNF)
- sym->rtype = *rp;
- sym->kind = sclass;
-
- if (ininit)
- sym->type.flags |= INITF;
- decl(sym);
- delnode(np);
-}
-
-static void
-flddecl(void)
-{
- Node *off, *np;
- char *name;
- Type *tp;
- Symbol *sym;
-
- off = pop();
- name = pop();
- tp = pop();
- np = pop();
-
- sym = np->u.sym;
- sym->u.off = off->u.i;
- sym->name = name;
- sym->type = *tp;
-
- delnode(np);
- delnode(off);
-}
-
-static void
-labeldcl(void)
-{
- Node *np;
- Symbol *sym;
-
- np = pop();
- np->op = ONOP;
- sym = np->u.sym;
- sym->kind = SLABEL;
- sym->u.stmt = np;
- np->label = sym;
- addstmt(np, SETCUR);
-}
-
-static void
-stmt(void)
-{
- Node *np;
-
- if (empty())
- return;
- np = pop();
- if (ininit) {
- data(np);
- deltree(np);
- return;
- }
- addstmt(np, SETCUR);
-}
-
-static void
-beginfun(void)
-{
- curfun = lastfun;
- inpars = 1;
- pushctx();
- addstmt(node(OBFUN), SETCUR);
-}
-
-static void
-endfun(void)
-{
- endf = 1;
- addstmt(node(OEFUN), SETCUR);
-}
-
-void
-parse(void)
-{
- cleannodes(); /* remove code of previous function */
- popctx(); /* remove context of previous function */
- curfun = NULL;
- endf = 0;
-
- while (!endf && nextline())
- ;
- if (ferror(stdin))
- error(EFERROR, strerror(errno));
-}
--- a/src/cmd/scc/cc2/peep.c
+++ /dev/null
@@ -1,7 +1,0 @@
-#include <scc/scc.h>
-#include "cc2.h"
-
-void
-peephole(void)
-{
-}
--- a/src/cmd/scc/cc2/symbol.c
+++ /dev/null
@@ -1,91 +1,0 @@
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/scc.h>
-
-#include "cc2.h"
-
-#define NR_SYMHASH 64
-
-Symbol *locals;
-
-static Symbol *symtab[NR_SYMHASH], *curlocal;
-static int infunction;
-
-
-void
-freesym(Symbol *sym)
-{
- free(sym->name);
- free(sym);
-}
-
-void
-pushctx(void)
-{
- infunction = 1;
-}
-
-void
-popctx(void)
-{
- Symbol *sym, *next;
-
- infunction = 0;
- for (sym = locals; sym; sym = next) {
- next = sym->next;
- /*
- * Symbols are inserted in the hash in the inverted
- * order they are found in locals and it is impossible
- * to have a global over a local, because a local is
- * any symbol defined in the body of a function,
- * even if it has extern linkage.
- * For this reason when we reach a symbol in the
- * locals list we know that it is the head of it
- * collision list and we can remove it assigning
- * it h_next to the hash table position
- */
- if (sym->id != TMPSYM)
- symtab[sym->id & NR_SYMHASH-1] = sym->h_next;
- freesym(sym);
- }
- curlocal = locals = NULL;
-}
-
-Symbol *
-getsym(unsigned id)
-{
- Symbol **htab, *sym;
- static unsigned short num;
-
- if (id >= USHRT_MAX)
- error(EBADID);
-
- if (id != TMPSYM) {
- htab = &symtab[id & NR_SYMHASH-1];
- for (sym = *htab; sym; sym = sym->h_next) {
- if (sym->id == id)
- return sym;
- }
- }
-
- sym = xcalloc(1, sizeof(*sym));
- sym->id = id;
- if (infunction) {
- if (!locals)
- locals = sym;
- if (curlocal)
- curlocal->next = sym;
- curlocal = sym;
- }
- if (id != TMPSYM) {
- sym->h_next = *htab;
- *htab = sym;
- }
- if ((sym->numid = ++num) == 0)
- error(EIDOVER);
-
- return sym;
-}
--- a/src/cmd/scc/cc2/target/amd64-sysv/cgen.c
+++ /dev/null
@@ -1,13 +1,0 @@
-#include "arch.h"
-#include <scc/scc.h>
-#include "../../cc2.h"
-
-Node *
-cgen(Node *np)
-{
-}
-
-Node *
-sethi(Node *np)
-{
-}
--- a/src/cmd/scc/cc2/target/amd64-sysv/code.c
+++ /dev/null
@@ -1,209 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-enum segment {
- CODESEG,
- DATASEG,
- BSSSEG,
- NOSEG
-};
-
-static int curseg = NOSEG;
-
-static void
-segment(int seg)
-{
- static char *txt[] = {
- [CODESEG] = "\t.text\n",
- [DATASEG] = "\t.data\n",
- [BSSSEG] = "\t.bss\n",
- };
-
- if (seg == curseg)
- return;
- fputs(txt[seg], stdout);
- curseg = seg;
-}
-
-static char *
-symname(Symbol *sym)
-{
- static char name[INTIDENTSIZ+1];
-
- if (sym->name) {
- switch (sym->kind) {
- case SEXTRN:
- case SGLOB:
- case SPRIV:
- return sym->name;
- }
- }
-
- sprintf(name, ".L%d", sym->numid);
-
- return name;
-}
-
-static void
-emitconst(Node *np)
-{
- switch (np->type.size) {
- case 1:
- printf("%d", (int) np->u.i & 0xFF);
- break;
- case 2:
- printf("%d", (int) np->u.i & 0xFFFF);
- break;
- case 4:
- printf("%ld", (long) np->u.i & 0xFFFFFFFF);
- break;
- case 8:
- printf("%lld", (long long) np->u.i & 0xFFFFFFFF);
- break;
- default:
- abort();
- }
-}
-
-static void
-emittree(Node *np)
-{
- if (!np)
- return;
-
- switch (np->op) {
- case OSTRING:
- printf("\"%s\"", np->u.s);
- free(np->u.s);
- np->u.s = NULL;
- break;
- case OCONST:
- emitconst(np);
- break;
- case OADDR:
- emittree(np->left);
- break;
- case OMEM:
- fputs(symname(np->u.sym), stdout);
- break;
- default:
- emittree(np->left);
- printf(" %c ", np->op);
- emittree(np->right);
- break;
- }
-}
-static void
-size2asm(Type *tp)
-{
- char *s;
-
- if (tp->flags & STRF) {
- s = "\t.ascii\t";
- } else {
- switch (tp->size) {
- case 1:
- s = "\t.byte\t";
- break;
- case 2:
- s = "\t.short\t";
- break;
- case 4:
- s = "\t.long\t";
- break;
- case 8:
- s = "\t.quad\t";
- break;
- default:
- s = "\t.space\t%lu,";
- break;
- }
- }
- printf(s, tp->size);
-}
-
-
-void
-data(Node *np)
-{
- size2asm(&np->type);
- emittree(np);
- putchar('\n');
-}
-
-static void
-label(Symbol *sym)
-{
- int seg;
- char *name = symname(sym);
- Type *tp = &sym->type;
-
- if (sym->type.flags & FUNF)
- seg = CODESEG;
- else if (sym->type.flags & INITF)
- seg = DATASEG;
- else
- seg = BSSSEG;
- segment(seg);
-
- switch (sym->kind) {
- case SEXTRN:
- printf("\t.extern\t%s\n", name);
- case SLOCAL:
- return;
- case SGLOB:
- printf("\t.global\t%s\n", name);
- if (seg == BSSSEG)
- printf("\t.comm\t%s,%lu\n", name, tp->size);
- break;
- }
- if (sym->type.align != 1)
- printf("\t.align\t%lu\n", sym->type.align );
- printf("%s:\n", name);
-}
-
-void
-defglobal(Symbol *sym)
-{
- label(sym);
- if (sym->kind == SEXTRN || (sym->type.flags & INITF))
- return;
- size2asm(&sym->type);
- puts("0");
-}
-
-void
-defvar(Symbol *sym)
-{
-}
-
-void
-defpar(Symbol *sym)
-{
-}
-
-void
-newfun(void)
-{
-}
-
-void
-writeout(void)
-{
-}
-
-void
-endinit(void)
-{
-}
-
-void
-getbblocks(void)
-{
-}
--- a/src/cmd/scc/cc2/target/amd64-sysv/optm.c
+++ /dev/null
@@ -1,9 +1,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-Node *
-optm_dep(Node *np)
-{
- return np;
-}
--- a/src/cmd/scc/cc2/target/amd64-sysv/target.mk
+++ /dev/null
@@ -1,8 +1,0 @@
-OBJ-amd64-sysv = $(OBJS) \
- target/amd64-sysv/cgen.o \
- target/amd64-sysv/optm.o \
- target/amd64-sysv/code.o \
- target/amd64-sysv/types.o
-
-$(LIBEXEC)/cc2-amd64-sysv: $(OBJ-amd64-sysv)
- $(CC) $(SCC_LDFLAGS) $(OBJ-amd64-sysv) -lscc -o $@
--- a/src/cmd/scc/cc2/target/amd64-sysv/types.c
+++ /dev/null
@@ -1,92 +1,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-
-Type int8type = {
- .flags = SIGNF | INTF,
- .size = 1,
- .align = 1
-};
-
-Type int16type = {
- .flags = SIGNF | INTF,
- .size = 2,
- .align = 2
-};
-
-Type int32type = {
- .flags = SIGNF | INTF,
- .size = 4,
- .align = 4
-};
-
-Type int64type = {
- .flags = SIGNF | INTF,
- .size = 8,
- .align = 8
-};
-
-Type uint8type = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type uint16type = {
- .flags = INTF,
- .size = 2,
- .align = 2
-};
-
-Type uint32type = {
- .flags = INTF,
- .size = 4,
- .align = 4
-};
-
-Type uint64type = {
- .flags = INTF,
- .size = 8,
- .align = 2
-};
-
-Type ptrtype = {
- .flags = INTF,
- .size = 8,
- .align = 8
-};
-
-Type booltype = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type float32type = {
- .flags = FLOATF,
- .size = 4,
- .align = 4
-};
-
-Type float64type = {
- .flags = FLOATF,
- .size = 8,
- .align = 8
-};
-
-Type float80type = {
- .flags = FLOATF,
- .size = 16,
- .align = 16
-};
-
-Type voidtype = {
- .size = 0,
- .align = 0
-};
-
-Type arg_type = {
- .size = 24,
- .align = 8
-};
--- a/src/cmd/scc/cc2/target/i386-sysv/cgen.c
+++ /dev/null
@@ -1,14 +1,0 @@
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-Node *
-cgen(Node *np)
-{
-}
-
-Node *
-sethi(Node *np)
-{
-}
--- a/src/cmd/scc/cc2/target/i386-sysv/code.c
+++ /dev/null
@@ -1,208 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-enum segment {
- CODESEG,
- DATASEG,
- BSSSEG,
- NOSEG
-};
-
-static int curseg = NOSEG;
-
-static void
-segment(int seg)
-{
- static char *txt[] = {
- [CODESEG] = "\t.text\n",
- [DATASEG] = "\t.data\n",
- [BSSSEG] = "\t.bss\n",
- };
-
- if (seg == curseg)
- return;
- fputs(txt[seg], stdout);
- curseg = seg;
-}
-
-static char *
-symname(Symbol *sym)
-{
- static char name[INTIDENTSIZ+1];
-
- if (sym->name) {
- switch (sym->kind) {
- case SEXTRN:
- case SGLOB:
- case SPRIV:
- return sym->name;
- }
- }
-
- sprintf(name, ".L%d", sym->numid);
-
- return name;
-}
-
-static void
-emitconst(Node *np)
-{
- switch (np->type.size) {
- case 1:
- printf("%d", (int) np->u.i & 0xFF);
- break;
- case 2:
- printf("%d", (int) np->u.i & 0xFFFF);
- break;
- case 4:
- printf("%ld", (long) np->u.i & 0xFFFFFFFF);
- break;
- case 8:
- printf("%lld", (long long) np->u.i & 0xFFFFFFFF);
- break;
- default:
- abort();
- }
-}
-
-static void
-emittree(Node *np)
-{
- if (!np)
- return;
-
- switch (np->op) {
- case OSTRING:
- printf("\"%s\"", np->u.s);
- free(np->u.s);
- np->u.s = NULL;
- break;
- case OCONST:
- emitconst(np);
- break;
- case OADDR:
- emittree(np->left);
- break;
- case OMEM:
- fputs(symname(np->u.sym), stdout);
- break;
- default:
- emittree(np->left);
- printf(" %c ", np->op);
- emittree(np->right);
- break;
- }
-}
-static void
-size2asm(Type *tp)
-{
- char *s;
-
- if (tp->flags & STRF) {
- s = "\t.ascii\t";
- } else {
- switch (tp->size) {
- case 1:
- s = "\t.byte\t";
- break;
- case 2:
- s = "\t.short\t";
- break;
- case 4:
- s = "\t.long\t";
- break;
- case 8:
- s = "\t.quad\t";
- break;
- default:
- s = "\t.space\t%lu,";
- break;
- }
- }
- printf(s, tp->size);
-}
-
-void
-data(Node *np)
-{
- size2asm(&np->type);
- emittree(np);
- putchar('\n');
-}
-
-static void
-label(Symbol *sym)
-{
- int seg;
- char *name = symname(sym);
- Type *tp = &sym->type;
-
- if (sym->type.flags & FUNF)
- seg = CODESEG;
- else if (sym->type.flags & INITF)
- seg = DATASEG;
- else
- seg = BSSSEG;
- segment(seg);
-
- switch (sym->kind) {
- case SEXTRN:
- printf("\t.extern\t%s\n", name);
- case SLOCAL:
- return;
- case SGLOB:
- printf("\t.global\t%s\n", name);
- if (seg == BSSSEG)
- printf("\t.comm\t%s,%lu\n", name, tp->size);
- break;
- }
- if (sym->type.align != 1)
- printf("\t.align\t%lu\n", sym->type.align );
- printf("%s:\n", name);
-}
-
-void
-defglobal(Symbol *sym)
-{
- label(sym);
- if (sym->kind == SEXTRN || (sym->type.flags & INITF))
- return;
- size2asm(&sym->type);
- puts("0");
-}
-
-void
-defpar(Symbol *sym)
-{
-}
-
-void
-defvar(Symbol *sym)
-{
-}
-
-void
-newfun(void)
-{
-}
-
-void
-writeout(void)
-{
-}
-
-void
-endinit(void)
-{
-}
-
-void
-getbblocks(void)
-{
-}
--- a/src/cmd/scc/cc2/target/i386-sysv/optm.c
+++ /dev/null
@@ -1,9 +1,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-Node *
-optm_dep(Node *np)
-{
- return np;
-}
--- a/src/cmd/scc/cc2/target/i386-sysv/target.mk
+++ /dev/null
@@ -1,8 +1,0 @@
-OBJ-i386-sysv = $(OBJS) \
- target/i386-sysv/cgen.o \
- target/i386-sysv/optm.o \
- target/i386-sysv/code.o \
- target/i386-sysv/types.o
-
-$(LIBEXEC)/cc2-i386-sysv: $(OBJ-i386-sysv)
- $(CC) $(SCC_LDFLAGS) $(OBJ-i386-sysv) -lscc -o $@
--- a/src/cmd/scc/cc2/target/i386-sysv/types.c
+++ /dev/null
@@ -1,93 +1,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-
-Type int8type = {
- .flags = SIGNF | INTF,
- .size = 1,
- .align = 1
-};
-
-Type int16type = {
- .flags = SIGNF | INTF,
- .size = 2,
- .align = 2
-};
-
-Type int32type = {
- .flags = SIGNF | INTF,
- .size = 4,
- .align = 4
-};
-
-Type int64type = {
- .flags = SIGNF | INTF,
- .size = 8,
- .align = 4
-};
-
-Type uint8type = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type uint16type = {
- .flags = INTF,
- .size = 2,
- .align = 2
-};
-
-Type uint32type = {
- .flags = INTF,
- .size = 4,
- .align = 2
-};
-
-Type uint64type = {
- .flags = INTF,
- .size = 8,
- .align = 4
-};
-
-Type ptrtype = {
- .flags = INTF,
- .size = 4,
- .align = 4
-};
-
-Type booltype = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type float32type = {
- .flags = FLOATF,
- .size = 4,
- .align = 4
-};
-
-Type float64type = {
- .flags = FLOATF,
- .size = 8,
- .align = 4
-};
-
-Type float80type = {
- .flags = FLOATF,
- .size = 12,
- .align = 4
-};
-
-Type voidtype = {
- .size = 0,
- .align = 0
-};
-
-/* this type is not used in this architecture */
-Type arg_type = {
- .size = 0,
- .align = 0
-};
--- a/src/cmd/scc/cc2/target/qbe/arch.h
+++ /dev/null
@@ -1,135 +1,0 @@
-enum asmop {
- ASNOP = 0,
- ASSTB,
- ASSTH,
- ASSTW,
- ASSTL,
- ASSTM,
- ASSTS,
- ASSTD,
-
- ASLDSB,
- ASLDUB,
- ASLDSH,
- ASLDUH,
- ASLDSW,
- ASLDUW,
- ASLDL,
- ASLDS,
- ASLDD,
-
- ASADDW,
- ASSUBW,
- ASMULW,
- ASMODW,
- ASUMODW,
- ASDIVW,
- ASUDIVW,
- ASSHLW,
- ASSHRW,
- ASUSHRW,
- ASLTW,
- ASULTW,
- ASGTW,
- ASUGTW,
- ASLEW,
- ASULEW,
- ASGEW,
- ASUGEW,
- ASEQW,
- ASNEW,
- ASBANDW,
- ASBORW,
- ASBXORW,
-
- ASADDL,
- ASSUBL,
- ASMULL,
- ASMODL,
- ASUMODL,
- ASDIVL,
- ASUDIVL,
- ASSHLL,
- ASSHRL,
- ASUSHRL,
- ASLTL,
- ASULTL,
- ASGTL,
- ASUGTL,
- ASLEL,
- ASULEL,
- ASGEL,
- ASUGEL,
- ASEQL,
- ASNEL,
- ASBANDL,
- ASBORL,
- ASBXORL,
-
- ASADDS,
- ASSUBS,
- ASMULS,
- ASDIVS,
- ASLTS,
- ASGTS,
- ASLES,
- ASGES,
- ASEQS,
- ASNES,
-
- ASADDD,
- ASSUBD,
- ASMULD,
- ASDIVD,
- ASLTD,
- ASGTD,
- ASLED,
- ASGED,
- ASEQD,
- ASNED,
-
- ASEXTBW,
- ASUEXTBW,
- ASEXTBL,
- ASUEXTBL,
- ASEXTHW,
- ASUEXTHW,
- ASEXTHL,
- ASUEXTHL,
- ASEXTWL,
- ASUEXTWL,
-
- ASSTOL,
- ASSTOW,
- ASDTOL,
- ASDTOW,
-
- ASSWTOD,
- ASSWTOS,
- ASSLTOD,
- ASSLTOS,
-
- ASEXTS,
- ASTRUNCD,
-
- ASJMP,
- ASBRANCH,
- ASRET,
- ASCALL,
- ASCALLE,
- ASCALLEX,
- ASPAR,
- ASPARE,
- ASALLOC,
- ASFORM,
-
- ASCOPYB,
- ASCOPYH,
- ASCOPYW,
- ASCOPYL,
- ASCOPYS,
- ASCOPYD,
-
- ASVSTAR,
- ASVARG,
-};
--- a/src/cmd/scc/cc2/target/qbe/cgen.c
+++ /dev/null
@@ -1,727 +1,0 @@
-#include <assert.h>
-#include <stdlib.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-enum sflags {
- ISTMP = 1,
- ISCONS = 2
-};
-
-static char opasmw[] = {
- [OADD] = ASADDW,
- [OSUB] = ASSUBW,
- [OMUL] = ASMULW,
- [OMOD] = ASMODW,
- [ODIV] = ASDIVW,
- [OSHL] = ASSHLW,
- [OSHR] = ASSHRW,
- [OLT] = ASLTW,
- [OGT] = ASGTW,
- [OLE] = ASLEW,
- [OGE] = ASGEW,
- [OEQ] = ASEQW,
- [ONE] = ASNEW,
- [OBAND] = ASBANDW,
- [OBOR] = ASBORW,
- [OBXOR] = ASBXORW,
-};
-
-static char opasml[] = {
- [OADD] = ASADDL,
- [OSUB] = ASSUBL,
- [OMUL] = ASMULL,
- [OMOD] = ASMODL,
- [ODIV] = ASDIVL,
- [OSHL] = ASSHLL,
- [OSHR] = ASSHRL,
- [OLT] = ASLTL,
- [OGT] = ASGTL,
- [OLE] = ASLEL,
- [OGE] = ASGEL,
- [OEQ] = ASEQL,
- [ONE] = ASNEL,
- [OBAND] = ASBANDL,
- [OBOR] = ASBORL,
- [OBXOR] = ASBXORL,
-};
-
-static char opasms[] = {
- [OADD] = ASADDS,
- [OSUB] = ASSUBS,
- [OMUL] = ASMULS,
- [ODIV] = ASDIVS,
- [OLT] = ASLTS,
- [OGT] = ASGTS,
- [OLE] = ASLES,
- [OGE] = ASGES,
- [OEQ] = ASEQS,
- [ONE] = ASNES,
-};
-static char opasmd[] = {
- [OADD] = ASADDD,
- [OSUB] = ASSUBD,
- [OMUL] = ASMULD,
- [ODIV] = ASDIVD,
- [OLT] = ASLTD,
- [OGT] = ASGTD,
- [OLE] = ASLED,
- [OGE] = ASGED,
- [OEQ] = ASEQD,
- [ONE] = ASNED,
-};
-
-extern Type int32type, uint32type, ptrtype;
-
-static Node *
-tmpnode(Node *np, Type *tp)
-{
- char flags;
- Symbol *sym;
-
- if (!np)
- np = node(OTMP);
- sym = getsym(TMPSYM);
- sym->type = np->type = *tp;
- flags = tp->flags & ~(PARF|INITF);
- sym->type.flags = np->type.flags = flags;
- sym->kind = STMP;
- np->left = np->right = NULL;
- np->u.sym = sym;
- np->op = OTMP;
- np->flags |= ISTMP;
- return np;
-}
-
-static Node *
-load(Type *tp, Node *np, Node *new)
-{
- int op;
- int flags = tp->flags;
-
- if (flags & (AGGRF|FUNF)) {
- *new = *np;
- return new;
- }
- switch (tp->size) {
- case 1:
- op = ASLDSB;
- break;
- case 2:
- op = ASLDSH;
- break;
- case 4:
- op = (flags & FLOATF) ? ASLDS : ASLDSW;
- break;
- case 8:
- op = (flags & FLOATF) ? ASLDD : ASLDL;
- break;
- default:
- abort();
- }
- /*
- * unsigned version of operations are always +1 the
- * signed version
- */
- if ((flags & (INTF|SIGNF)) == INTF && tp->size < 8)
- ++op;
-
- code(op, tmpnode(new, tp), np, NULL);
-
- return new;
-}
-
-static Node *rhs(Node *np, Node *new);
-
-static Node *
-cast(Type *td, Node *ns, Node *nd)
-{
- Type *ts;
- Node aux1, aux2;
- int op, d_isint, s_isint;
-
- ts = &ns->type;
- d_isint = (td->flags & INTF) != 0;
- s_isint = (ts->flags & INTF) != 0;
-
- if (d_isint && s_isint) {
- if (td->size <= ts->size) {
- *nd = *ns;
- return nd;
- }
- assert(td->size == 4 || td->size == 8);
- switch (ts->size) {
- case 1:
- op = (td->size == 4) ? ASEXTBW : ASEXTBL;
- break;
- case 2:
- op = (td->size == 4) ? ASEXTHW : ASEXTHL;
- break;
- case 4:
- op = ASEXTWL;
- break;
- default:
- abort();
- }
- /*
- * unsigned version of operations are always +1 the
- * signed version
- */
- op += (ts->flags & SIGNF) == 0;
- } else if (d_isint) {
- /* conversion from float to int */
- switch (ts->size) {
- case 4:
- op = (td->size == 8) ? ASSTOL : ASSTOW;
- break;
- case 8:
- op = (td->size == 8) ? ASDTOL : ASDTOW;
- break;
- default:
- abort();
- }
- /* TODO: Add signess */
- } else if (s_isint) {
- /* conversion from int to float */
- switch (ts->size) {
- case 1:
- case 2:
- ts = (ts->flags&SIGNF) ? &int32type : &uint32type;
- ns = cast(ts, ns, tmpnode(&aux2, ts));
- case 4:
- op = (td->size == 8) ? ASSWTOD : ASSWTOS;
- break;
- case 8:
- op = (td->size == 8) ? ASSLTOD : ASSLTOS;
- break;
- default:
- abort();
- }
- /* TODO: Add signess */
- } else {
- /* conversion from float to float */
- op = (td->size == 4) ? ASEXTS : ASTRUNCD;
- }
-
- code(op, tmpnode(nd, td), ns, NULL);
- return nd;
-}
-
-static Node *
-call(Node *np, Node *fun, Node *ret)
-{
- int n, op;
- Type *tp;
- Node aux, **q, *p, *pars[NR_FUNPARAM];
-
- for (n = 0, p = np->right; p; p = p->right)
- pars[n++] = rhs(p->left, node(OTMP));
-
- tp = &np->type;
- code(ASCALL, tmpnode(ret, tp), fun, NULL);
-
- for (q = pars; q < &pars[n]; ++q) {
- op = (q == &pars[n-1]) ? ASPARE : ASPAR;
- tmpnode(&aux, &(*q)->type);
- code(op, NULL, *q, &aux);
- }
- code((np->op == OCALL) ? ASCALLE : ASCALLEX, NULL, NULL, NULL);
-
- return ret;
-}
-
-static Node *
-assign(Type *tp, Node *to, Node *from)
-{
- int op;
-
- switch (tp->size) {
- case 1:
- op = ASSTB;
- break;
- case 2:
- op = ASSTH;
- break;
- case 4:
- op = (tp->flags & FLOATF) ? ASSTS : ASSTW;
- break;
- case 8:
- op = (tp->flags & FLOATF) ? ASSTD : ASSTL;
- break;
- default:
- op = ASSTM;
- break;
- }
- code(op, to, from, NULL);
- return from;
-}
-
-static Node *
-copy(Type *tp, Node *to, Node *from)
-{
- int op;
-
- switch (tp->size) {
- case 1:
- op = ASCOPYB;
- break;
- case 2:
- op = ASCOPYH;
- break;
- case 4:
- op = (tp->flags & FLOATF) ? ASCOPYS : ASCOPYW;
- break;
- case 8:
- op = (tp->flags & FLOATF) ? ASCOPYD : ASCOPYL;
- break;
- default:
- /* TODO: Need to handle the general case */
- abort();
- }
- code(op, to, from, NULL);
- return from;
-}
-
-/* TODO: Do field() transformation in sethi */
-
-static Node *
-field(Node *np, Node *ret, int islhs)
-{
- Node base, node, off, add, *addr;
- TUINT offset = np->right->u.sym->u.off;
-
- addr = rhs(np->left, &base);
-
- if (offset != 0) {
- node.op = OADD;
- node.type = ptrtype;
- node.left = addr;
- node.right = constnode(&off, offset, &ptrtype);
- addr = rhs(&node, &add);
- }
-
- if (islhs)
- *ret = *addr;
- else
- load(&np->type, addr, ret);
-
- return ret;
-}
-
-static Node *
-lhs(Node *np, Node *new)
-{
- switch (np->op) {
- case OMEM:
- case OAUTO:
- *new = *np;
- return new;
- case OPTR:
- return rhs(np->left, new);
- case OFIELD:
- return field(np, new, 1);
- default:
- abort();
- }
-}
-
-static void
-bool(Node *np, Symbol *true, Symbol *false)
-{
- Node *l = np->left, *r = np->right;
- Node ret, ifyes, ifno;
- Symbol *label;
-
- switch (np->op) {
- case ONEG:
- bool(l, false, true);
- break;
- case OAND:
- label = newlabel();
- bool(l, label, false);
- setlabel(label);
- bool(r, true, false);
- break;
- case OOR:
- label = newlabel();
- bool(l, true, label);
- setlabel(label);
- bool(r, true, false);
- break;
- default:
- label2node(&ifyes, true);
- label2node(&ifno, false);
- code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno);
- break;
- }
-}
-
-static Node *
-ternary(Node *np, Node *ret)
-{
- Node ifyes, ifno, phi, *colon, aux1, aux2, aux3;
-
- tmpnode(ret, &np->type);
- label2node(&ifyes, NULL);
- label2node(&ifno, NULL);
- label2node(&phi, NULL);
-
- colon = np->right;
- code(ASBRANCH, rhs(np->left, &aux1), &ifyes, &ifno);
-
- setlabel(ifyes.u.sym);
- copy(&ret->type, ret, rhs(colon->left, &aux2));
- code(ASJMP, NULL, &phi, NULL);
-
- setlabel(ifno.u.sym);
- copy(&ret->type, ret, rhs(colon->right, &aux3));
- setlabel(phi.u.sym);
-
- return ret;
-}
-
-static Node *
-function(void)
-{
- Node aux;
- Symbol *p;
-
- /* allocate stack space for parameters */
- for (p = locals; p && (p->type.flags & PARF) != 0; p = p->next)
- code(ASALLOC, label2node(&aux, p), NULL, NULL);
-
- /* allocate stack space for local variables) */
- for ( ; p && p->id != TMPSYM; p = p->next) {
- if (p->kind != SAUTO)
- continue;
- code(ASALLOC, label2node(&aux, p), NULL, NULL);
- }
- /* store formal parameters in parameters */
- for (p = locals; p; p = p->next) {
- if ((p->type.flags & PARF) == 0)
- break;
- code(ASFORM, label2node(&aux, p), NULL, NULL);
- }
- return NULL;
-}
-
-static void
-swtch_if(Node *idx)
-{
- Node aux1, aux2, *np;
- Symbol *deflabel = NULL;
-
- for (;;) {
- np = delstmt();
- setlabel(np->label);
-
- switch (np->op) {
- case OESWITCH:
- if (!deflabel)
- deflabel = np->u.sym;
- aux1.op = OJMP;
- aux1.label = NULL;
- aux1.u.sym = deflabel;
- cgen(&aux1);
- return;
- case OCASE:
- aux1 = *np;
- aux1.op = OBRANCH;
- aux1.label = NULL;
- aux1.left = &aux2;
-
- aux2.op = OEQ;
- aux2.type = idx->type;
- aux2.left = np->left;
- aux2.right = idx;
-
- cgen(&aux1);
- break;
- case ODEFAULT:
- deflabel = np->u.sym;
- break;
- default:
- abort();
- }
- }
-}
-
-static Node *
-rhs(Node *np, Node *ret)
-{
- Node aux1, aux2, *phi, *l = np->left, *r = np->right;
- Type *tp;
- int off, op;
- char *tbl;
- Symbol *true, *false;
-
- tp = &np->type;
-
- switch (np->op) {
- case OBFUN:
- return function();
- case ONOP:
- case OBLOOP:
- case OELOOP:
- case OEFUN:
- return NULL;
- case OTMP:
- case OCONST:
- *ret = *np;
- return np;
- case OMEM:
- case OAUTO:
- return load(tp, np, ret);
- case ONEG:
- case OAND:
- case OOR:
- true = newlabel();
- false = newlabel();
- phi = label2node(&aux1, NULL);
- tmpnode(ret, &int32type);
-
- bool(np, true, false);
-
- setlabel(true);
- code(ASCOPYW, ret, constnode(&aux2, 1, &int32type), NULL);
- code(ASJMP, NULL, phi, NULL);
-
- setlabel(false);
- code(ASCOPYW, ret, constnode(&aux2, 0, &int32type), NULL);
-
- setlabel(phi->u.sym);
- return ret;
- case OMOD:
- case OSHR:
- assert(tp->flags & INTF);
- case ODIV:
- case OLT:
- case OGT:
- case OLE:
- case OGE:
- /*
- * unsigned version of operations are always +1 the
- * signed version
- */
- off = (tp->flags & SIGNF) == 0;
- goto binary;
- case OSHL:
- case OBAND:
- case OBOR:
- case OBXOR:
- assert(tp->flags & INTF);
- case OADD:
- case OSUB:
- case OMUL:
- case OEQ:
- case ONE:
- off = 0;
- binary:
- if (l->complex >= r->complex) {
- rhs(l, &aux1);
- rhs(r, &aux2);
- } else {
- rhs(r, &aux2);
- rhs(l, &aux1);
- }
- switch (tp->size) {
- case 4:
- tbl = (tp->flags & FLOATF) ? opasms : opasmw;
- break;
- case 8:
- tbl = (tp->flags & FLOATF) ? opasmd : opasml;
- break;
- default:
- abort();
- }
- op = tbl[np->op] + off;
- tmpnode(ret, tp);
- code(op, ret, &aux1, &aux2);
- return ret;
- case OCALL:
- case OCALLE:
- if (l->op == OPTR)
- l = rhs(l, &aux1);
- return call(np, l, ret);
- case OCAST:
- return cast(tp, rhs(l, &aux1), ret);
- case OASSIG:
- /* TODO: Do this transformations in sethi */
- switch (np->u.subop) {
- case OINC:
- op = OADD;
- goto post_oper;
- case ODEC:
- op = OSUB;
- post_oper:
- aux1.op = op;
- aux1.left = rhs(l, ret);
- aux1.right = r;
- aux1.type = np->type;
- rhs(&aux1, &aux2);
- lhs(l, &aux1);
- assign(tp, &aux1, &aux2);
- break;
- default:
- aux2.type = np->type;
- aux2.op = np->u.subop;
- aux2.right = np->right;
- aux2.left = np->left;
- r = rhs(&aux2, &aux1);
- Node aux3;
- if (l->op == OCAST) {
- aux3.type = l->left->type;
- aux3.op = OCAST;
- aux3.left = r;
- aux3.right = NULL;
- r = &aux3;
- l = l->left;
- }
- case 0:
- /* TODO: see what is the most difficult */
- lhs(l, &aux2);
- rhs(r, ret);
- return assign(tp, &aux2, ret);
- }
- return ret;
- case OASK:
- return ternary(np, ret);
- case OCOMMA:
- rhs(l, &aux1);
- return rhs(r, ret);
- case OPTR:
- return load(tp, rhs(l, &aux1), ret);
- case OADDR:
- lhs(l, ret);
- ret->type = *tp;
- return ret;
- case OFIELD:
- return field(np, ret, 0);
- case OBUILTIN:
- switch (np->u.subop) {
- case BVA_START:
- l = rhs(l, &aux1);
- code(ASVSTAR, NULL, l, NULL);
- return NULL;
- case BVA_END:
- return NULL;
- case BVA_ARG:
- l = rhs(l, &aux1);
- code(ASVARG, tmpnode(ret, tp), l, NULL);
- return ret;
- case BVA_COPY:
- /* TODO */
- default:
- abort();
- }
- default:
- abort();
- }
- abort();
-}
-
-Node *
-cgen(Node *np)
-{
- Node aux, *p, *next;
-
- setlabel(np->label);
- switch (np->op) {
- case OJMP:
- label2node(&aux, np->u.sym);
- code(ASJMP, NULL, &aux, NULL);
- break;
- case OBRANCH:
- next = np->next;
- if (!next->label)
- next->label = newlabel();
- bool(np->left, np->u.sym, next->label);
- break;
- case ORET:
- p = (np->left) ? rhs(np->left, &aux) : NULL;
- code(ASRET, NULL, p, NULL);
- break;
- case OBSWITCH:
- p = rhs(np->left, &aux);
- swtch_if(p);
- break;
- default:
- rhs(np, &aux);
- break;
- }
- return NULL;
-}
-
-/*
- * This is strongly influenced by
- * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
- * calculate addresability as follows
- * AUTO => 11 value+fp
- * REG => 11 reg
- * STATIC => 11 (value)
- * CONST => 11 $value
- * These values of addressability are not used in the code generation.
- * They are only used to calculate the Sethi-Ullman numbers. Since
- * QBE is AMD64 targered we could do a better job there, and try to
- * detect some of the complex addressing modes of these processors.
- */
-Node *
-sethi(Node *np)
-{
- Node *lp, *rp;
-
- if (!np)
- return np;
-
- np->complex = 0;
- np->address = 0;
- lp = np->left;
- rp = np->right;
-
- switch (np->op) {
- case OAUTO:
- case OREG:
- case OMEM:
- case OCONST:
- np->address = 11;
- break;
- case OCPL:
- assert(np->type.flags & INTF);
- np->op = OBXOR;
- rp = constnode(NULL, ~(TUINT) 0, &np->type);
- goto binary;
- case OSNEG:
- np->op = OSUB;
- rp = lp;
- lp = constnode(NULL, 0, &np->type);
- if ((np->type.flags & INTF) == 0)
- lp->u.f = 0.0;
- default:
- binary:
- lp = sethi(lp);
- rp = sethi(rp);
- break;
- }
- np->left = lp;
- np->right = rp;
-
- if (np->address > 10)
- return np;
- if (lp)
- np->complex = lp->complex;
- if (rp) {
- int d = np->complex - rp->complex;
-
- if (d == 0)
- ++np->complex;
- else if (d < 0)
- np->complex = rp->complex;
- }
- if (np->complex == 0)
- ++np->complex;
- return np;
-}
--- a/src/cmd/scc/cc2/target/qbe/code.c
+++ /dev/null
@@ -1,567 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-#define ADDR_LEN (INTIDENTSIZ+64)
-
-static void binary(void), unary(void), store(void), jmp(void), ret(void),
- branch(void), call(void), ecall(void), param(void),
- asalloc(void), form2local(void), ldir(void), vastart(void),
- vaarg(void);
-
-static struct opdata {
- void (*fun)(void);
- char *txt;
- char letter;
-} optbl [] = {
- [ASLDSB] = {.fun = unary, .txt = "loadsb", .letter = 'w'},
- [ASLDUB] = {.fun = unary, .txt = "loadub", .letter = 'w'},
- [ASLDSH] = {.fun = unary, .txt = "loadsh", .letter = 'w'},
- [ASLDUH] = {.fun = unary, .txt = "loaduh", .letter = 'w'},
- [ASLDSW] = {.fun = unary, .txt = "loadsw", .letter = 'w'},
- [ASLDUW] = {.fun = unary, .txt = "loaduw", .letter = 'w'},
- [ASLDL] = {.fun = unary, .txt = "loadl", .letter = 'l'},
- [ASLDS] = {.fun = unary, .txt = "loads", .letter = 's'},
- [ASLDD] = {.fun = unary, .txt = "loadd", .letter = 'd'},
-
- [ASCOPYB] = {.fun = unary, .txt = "copy", .letter = 'b'},
- [ASCOPYH] = {.fun = unary, .txt = "copy", .letter = 'h'},
- [ASCOPYW] = {.fun = unary, .txt = "copy", .letter = 'w'},
- [ASCOPYL] = {.fun = unary, .txt = "copy", .letter = 'l'},
- [ASCOPYS] = {.fun = unary, .txt = "copy", .letter = 's'},
- [ASCOPYD] = {.fun = unary, .txt = "copy", .letter = 'd'},
-
- [ASSTB] = {.fun = store, .txt = "store", .letter = 'b'},
- [ASSTH] = {.fun = store, .txt = "store", .letter = 'h'},
- [ASSTW] = {.fun = store, .txt = "store", .letter = 'w'},
- [ASSTL] = {.fun = store, .txt = "store", .letter = 'l'},
- [ASSTM] = {.fun = ldir},
- [ASSTS] = {.fun = store, .txt = "store", .letter = 's'},
- [ASSTD] = {.fun = store, .txt = "store", .letter = 'd'},
-
- [ASADDW] = {.fun = binary, .txt = "add", .letter = 'w'},
- [ASSUBW] = {.fun = binary, .txt = "sub", .letter = 'w'},
- [ASMULW] = {.fun = binary, .txt = "mul", .letter = 'w'},
- [ASMODW] = {.fun = binary, .txt = "rem", .letter = 'w'},
- [ASUMODW] = {.fun = binary, .txt = "urem", .letter = 'w'},
- [ASDIVW] = {.fun = binary, .txt = "div", .letter = 'w'},
- [ASUDIVW] = {.fun = binary, .txt = "udiv", .letter = 'w'},
- [ASSHLW] = {.fun = binary, .txt = "shl", .letter = 'w'},
- [ASSHRW] = {.fun = binary, .txt = "sar", .letter = 'w'},
- [ASUSHRW] = {.fun = binary, .txt = "shr", .letter = 'w'},
- [ASLTW] = {.fun = binary, .txt = "csltw", .letter = 'w'},
- [ASULTW] = {.fun = binary, .txt = "cultw", .letter = 'w'},
- [ASGTW] = {.fun = binary, .txt = "csgtw", .letter = 'w'},
- [ASUGTW] = {.fun = binary, .txt = "cugtw", .letter = 'w'},
- [ASLEW] = {.fun = binary, .txt = "cslew", .letter = 'w'},
- [ASULEW] = {.fun = binary, .txt = "culew", .letter = 'w'},
- [ASGEW] = {.fun = binary, .txt = "csgew", .letter = 'w'},
- [ASUGEW] = {.fun = binary, .txt = "cugew", .letter = 'w'},
- [ASEQW] = {.fun = binary, .txt = "ceqw", .letter = 'w'},
- [ASNEW] = {.fun = binary, .txt = "cnew", .letter = 'w'},
- [ASBANDW] = {.fun = binary, .txt = "and", .letter = 'w'},
- [ASBORW] = {.fun = binary, .txt = "or", .letter = 'w'},
- [ASBXORW] = {.fun = binary, .txt = "xor", .letter = 'w'},
-
- [ASADDL] = {.fun = binary, .txt = "add", .letter = 'l'},
- [ASSUBL] = {.fun = binary, .txt = "sub", .letter = 'l'},
- [ASMULL] = {.fun = binary, .txt = "mul", .letter = 'l'},
- [ASMODL] = {.fun = binary, .txt = "rem", .letter = 'l'},
- [ASUMODL] = {.fun = binary, .txt = "urem", .letter = 'l'},
- [ASDIVL] = {.fun = binary, .txt = "div", .letter = 'l'},
- [ASUDIVL] = {.fun = binary, .txt = "udiv", .letter = 'l'},
- [ASSHLL] = {.fun = binary, .txt = "shl", .letter = 'l'},
- [ASSHRL] = {.fun = binary, .txt = "sar", .letter = 'l'},
- [ASUSHRL] = {.fun = binary, .txt = "shr", .letter = 'l'},
- [ASLTL] = {.fun = binary, .txt = "csltl", .letter = 'w'},
- [ASULTL] = {.fun = binary, .txt = "cultl", .letter = 'w'},
- [ASGTL] = {.fun = binary, .txt = "csgtl", .letter = 'w'},
- [ASUGTL] = {.fun = binary, .txt = "cugtl", .letter = 'w'},
- [ASLEL] = {.fun = binary, .txt = "cslel", .letter = 'w'},
- [ASULEL] = {.fun = binary, .txt = "culel", .letter = 'w'},
- [ASGEL] = {.fun = binary, .txt = "csgel", .letter = 'w'},
- [ASUGEL] = {.fun = binary, .txt = "cugel", .letter = 'w'},
- [ASEQL] = {.fun = binary, .txt = "ceql", .letter = 'w'},
- [ASNEL] = {.fun = binary, .txt = "cnel", .letter = 'w'},
- [ASBANDL] = {.fun = binary, .txt = "and", .letter = 'l'},
- [ASBORL] = {.fun = binary, .txt = "or", .letter = 'l'},
- [ASBXORL] = {.fun = binary, .txt = "xor", .letter = 'l'},
-
- [ASADDS] = {.fun = binary, .txt = "add", .letter = 's'},
- [ASSUBS] = {.fun = binary, .txt = "sub", .letter = 's'},
- [ASMULS] = {.fun = binary, .txt = "mul", .letter = 's'},
- [ASDIVS] = {.fun = binary, .txt = "div", .letter = 's'},
- [ASLTS] = {.fun = binary, .txt = "clts", .letter = 'w'},
- [ASGTS] = {.fun = binary, .txt = "cgts", .letter = 'w'},
- [ASLES] = {.fun = binary, .txt = "cles", .letter = 'w'},
- [ASGES] = {.fun = binary, .txt = "cges", .letter = 'w'},
- [ASEQS] = {.fun = binary, .txt = "ceqs", .letter = 'w'},
- [ASNES] = {.fun = binary, .txt = "cnes", .letter = 'w'},
-
- [ASADDD] = {.fun = binary, .txt = "add", .letter = 'd'},
- [ASSUBD] = {.fun = binary, .txt = "sub", .letter = 'd'},
- [ASMULD] = {.fun = binary, .txt = "mul", .letter = 'd'},
- [ASDIVD] = {.fun = binary, .txt = "div", .letter = 'd'},
- [ASLTD] = {.fun = binary, .txt = "cltd", .letter = 'w'},
- [ASGTD] = {.fun = binary, .txt = "cgtd", .letter = 'w'},
- [ASLED] = {.fun = binary, .txt = "cled", .letter = 'w'},
- [ASGED] = {.fun = binary, .txt = "cged", .letter = 'w'},
- [ASEQD] = {.fun = binary, .txt = "ceqd", .letter = 'w'},
- [ASNED] = {.fun = binary, .txt = "cned", .letter = 'w'},
-
- [ASEXTBW] = {.fun = unary, .txt = "extsb", .letter = 'w'},
- [ASUEXTBW]= {.fun = unary, .txt = "extub", .letter = 'w'},
- [ASEXTBL] = {.fun = unary, .txt = "extsb", .letter = 'l'},
- [ASUEXTBL]= {.fun = unary, .txt = "extub", .letter = 'l'},
- [ASEXTHW] = {.fun = unary, .txt = "extsh", .letter = 'w'},
- [ASUEXTHW]= {.fun = unary, .txt = "extuh", .letter = 'w'},
- [ASEXTWL] = {.fun = unary, .txt = "extsw", .letter = 'l'},
- [ASUEXTWL]= {.fun = unary, .txt = "extuw", .letter = 'l'},
-
- [ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'},
- [ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'},
- [ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'},
- [ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'},
-
- [ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'},
- [ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'},
- [ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'},
- [ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'},
-
- [ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'},
- [ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'},
-
- [ASBRANCH] = {.fun = branch},
- [ASJMP] = {.fun = jmp},
- [ASRET] = {.fun = ret},
- [ASCALL] = {.fun = call},
- [ASCALLE] = {.fun = ecall, .txt = ")"},
- [ASCALLEX] = {.fun = ecall, .txt = ", ...)"},
- [ASPAR] = {.fun = param, .txt = "%s %s, "},
- [ASPARE] = {.fun = param, .txt = "%s %s"},
- [ASALLOC] = {.fun = asalloc},
- [ASFORM] = {.fun = form2local},
-
- [ASVSTAR] = {.fun = vastart},
- [ASVARG] = {.fun = vaarg},
-};
-
-static char buff[ADDR_LEN];
-/*
- * : is for user-defined Aggregate Types
- * $ is for globals (represented by a pointer)
- * % is for function-scope temporaries
- * @ is for block labels
- */
-static char
-sigil(Symbol *sym)
-{
- switch (sym->kind) {
- case SEXTRN:
- case SGLOB:
- case SPRIV:
- case SLOCAL:
- return '$';
- case SAUTO:
- case STMP:
- return '%';
- case SLABEL:
- return '@';
- default:
- abort();
- }
-}
-
-static char *
-symname(Symbol *sym)
-{
- char c = sigil(sym);
-
- if (sym->name) {
- switch (sym->kind) {
- case SEXTRN:
- case SGLOB:
- sprintf(buff, "%c%s", c, sym->name);
- return buff;
- case SLOCAL:
- case SPRIV:
- case SAUTO:
- sprintf(buff, "%c%s.%u", c, sym->name, sym->id);
- return buff;
- default:
- abort();
- }
- }
- sprintf(buff, "%c.%u", c, sym->numid);
-
- return buff;
-}
-
-static void
-emitconst(Node *np)
-{
- switch (np->type.size) {
- case 1:
- printf("%d", (int) np->u.i & 0xFF);
- break;
- case 2:
- printf("%d", (int) np->u.i & 0xFFFF);
- break;
- case 4:
- printf("%ld", (long) np->u.i & 0xFFFFFFFF);
- break;
- case 8:
- printf("%lld", (long long) np->u.i);
- break;
- default:
- abort();
- }
-}
-
-static void
-emittree(Node *np)
-{
- if (!np)
- return;
-
- switch (np->op) {
- case OSTRING:
- printf("\"%s\"", np->u.s);
- free(np->u.s);
- np->u.s = NULL;
- break;
- case OCONST:
- emitconst(np);
- break;
- case OADDR:
- emittree(np->left);
- break;
- case OMEM:
- fputs(symname(np->u.sym), stdout);
- break;
- default:
- emittree(np->left);
- printf(" %c ", np->op);
- emittree(np->right);
- break;
- }
-}
-
-static char *
-size2asm(Type *tp)
-{
- if (tp->flags & STRF) {
- return "b";
- } else if (tp->flags & INTF) {
- switch (tp->size) {
- case 1:
- return "b";
- case 2:
- return "h";
- case 4:
- return "w";
- case 8:
- return "l";
- }
- } else if (tp->flags & FLOATF) {
- if (tp->size == 4)
- return "s";
- else if (tp->size == 8)
- return "d";
- }
- abort();
-}
-
-void
-defglobal(Symbol *sym)
-{
- if (sym->kind == SEXTRN)
- return;
- if (sym->kind == SGLOB)
- fputs("export ", stdout);
- printf("data %s = {\n", symname(sym));
- if (sym->type.flags & INITF)
- return;
- printf("\tz\t%lu\n}\n", sym->type.size);
-}
-
-void
-defpar(Symbol *sym)
-{
- sym->type.flags |= PARF;
-}
-
-void
-defvar(Symbol *sym)
-{
- if (sym->kind == SREG)
- sym->kind = SAUTO;
-}
-
-void
-data(Node *np)
-{
- printf("\t%s\t", size2asm(&np->type));
- emittree(np);
- putchar(',');
- putchar('\n');
-}
-
-static char *
-size2stack(Type *tp)
-{
- if (tp->flags & INTF) {
- switch (tp->size) {
- case 1:
- case 2:
- case 4:
- return "w";
- case 8:
- return "l";
- }
- } else if (tp->flags & FLOATF) {
- if (tp->size == 4)
- return "s";
- else if (tp->size == 8)
- return "d";
- } else if (tp->size == 0) {
- return "w";
- }
- abort();
-}
-
-void
-writeout(void)
-{
- Symbol *p;
- Type *tp;
- char *sep, *name;
- int haslabel = 0;
-
- if (!curfun)
- return;
- if (curfun->kind == SGLOB)
- fputs("export ", stdout);
- printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun));
-
- /* declare formal parameters */
- for (sep = "", p = locals; p; p = p->next, sep = ",") {
- if ((p->type.flags & PARF) == 0)
- break;
- printf("%s%s %s.val", sep, size2stack(&p->type), symname(p));
- }
- printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : "");
-
- /* emit assembler instructions */
- for (pc = prog; pc; pc = pc->next) {
- if (pc->label) {
- haslabel = 1;
- printf("%s\n", symname(pc->label));
- }
- if (!pc->op)
- continue;
- if (pc->flags&BBENTRY && !haslabel)
- printf("%s\n", symname(newlabel()));
- (*optbl[pc->op].fun)();
- if (!pc->label)
- haslabel = 0;
- }
-
- puts("}");
-}
-
-static char *
-addr2txt(Addr *a)
-{
- switch (a->kind) {
- case SCONST:
- sprintf(buff, "%llu", (unsigned long long) a->u.i);
- return buff;
- case SAUTO:
- case SLABEL:
- case STMP:
- case SGLOB:
- case SEXTRN:
- case SPRIV:
- case SLOCAL:
- return symname(a->u.sym);
- default:
- abort();
- }
-}
-
-static void
-binary(void)
-{
- struct opdata *p = &optbl[pc->op];
- char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
-
- strcpy(to, addr2txt(&pc->to));
- strcpy(from1, addr2txt(&pc->from1));
- strcpy(from2, addr2txt(&pc->from2));
- printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2);
-}
-
-static void
-ldir(void)
-{
- struct opdata *p = &optbl[pc->op];
- char to[ADDR_LEN], from[ADDR_LEN];
- /* TODO: what type do we use for the size? */
-
- /* TODO: it is pending */
-}
-
-static void
-store(void)
-{
- struct opdata *p = &optbl[pc->op];
- char to[ADDR_LEN], from[ADDR_LEN];
-
- strcpy(to, addr2txt(&pc->to));
- strcpy(from, addr2txt(&pc->from1));
- printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to);
-}
-
-static void
-unary(void)
-{
- struct opdata *p = &optbl[pc->op];
- char to[ADDR_LEN], from[ADDR_LEN];
-
- strcpy(to, addr2txt(&pc->to));
- strcpy(from, addr2txt(&pc->from1));
- printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from);
-}
-
-static void
-call(void)
-{
- struct opdata *p = &optbl[pc->op];
- char to[ADDR_LEN], from[ADDR_LEN];
- Symbol *sym = pc->to.u.sym;
-
- strcpy(to, addr2txt(&pc->to));
- strcpy(from, addr2txt(&pc->from1));
- printf("\t%s =%s\tcall\t%s(",
- to, size2stack(&sym->type), from);
-}
-
-static void
-param(void)
-{
- Symbol *sym = pc->from2.u.sym;
-
- printf(optbl[pc->op].txt,
- size2stack(&sym->type), addr2txt(&pc->from1));
-}
-
-static void
-ecall(void)
-{
- struct opdata *p = &optbl[pc->op];
-
- puts(p->txt);
-}
-
-static void
-ret(void)
-{
- if (pc->from1.kind == SNONE)
- puts("\t\tret");
- else
- printf("\t\tret\t%s\n", addr2txt(&pc->from1));
-}
-
-static void
-jmp(void)
-{
- printf("\t\tjmp\t%s\n", addr2txt(&pc->from1));
-}
-
-static void
-branch(void)
-{
- char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
-
- strcpy(to, addr2txt(&pc->to));
- strcpy(from1, addr2txt(&pc->from1));
- strcpy(from2, addr2txt(&pc->from2));
- printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2);
-}
-
-static void
-vastart(void)
-{
- printf("\t\tvastart %s\n", addr2txt(&pc->from1));
-}
-
-static void
-vaarg(void)
-{
- Symbol *sym = pc->to.u.sym;
- Type *tp = &sym->type;
- char to[ADDR_LEN], from[ADDR_LEN];
-
- strcpy(to, addr2txt(&pc->to));
- strcpy(from, addr2txt(&pc->from1));
- printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from);
-}
-
-static void
-asalloc(void)
-{
- Symbol *sym = pc->to.u.sym;
- Type *tp = &sym->type;
- extern Type ptrtype;
-
- printf("\t%s =%s\talloc%lu\t%lu\n",
- symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size);
-}
-
-static void
-form2local(void)
-{
- Symbol *sym = pc->to.u.sym;
- Type *tp = &sym->type;
- char *name = symname(sym);
-
- printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name);
-}
-
-void
-endinit(void)
-{
- puts("}");
-}
-
-void
-getbblocks(void)
-{
- Inst *i;
-
- if (!prog)
- return;
-
- prog->flags |= BBENTRY;
- for (pc = prog; pc; pc = pc->next) {
- switch (pc->op) {
- case ASBRANCH:
- i = pc->from2.u.sym->u.inst;
- i->flags |= BBENTRY;
- case ASJMP:
- i = pc->from1.u.sym->u.inst;
- i->flags |= BBENTRY;
- case ASRET:
- if (pc->next)
- pc->next->flags |= BBENTRY;
- break;
- }
- }
-}
--- a/src/cmd/scc/cc2/target/qbe/optm.c
+++ /dev/null
@@ -1,56 +1,0 @@
-#include <stddef.h>
-
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-Node *
-optm_dep(Node *np)
-{
- int op = np->op;
- Node *p, *dst, *next = np->next;
- Symbol *sym, *osym;
-
- switch (op) {
- case OEFUN:
- /*
- * In QBE we need at the end of a basic block
- * a jump, so we have to ensure that the last
- * statement of the function is a ret, a jmp
- * or a branch. In the same way, QBE does
- * not accept labels at the end of a function
- * (ONOP is used for labels) so we have to add
- * a ret there, and in the case of branches
- * we need a label for the next statement
- */
- op = (np->prev) ? np->prev->op : 0;
- if (!op || op == ONOP || op == OBRANCH || (op != ORET && op != OJMP))
- addstmt(node(ORET), KEEPCUR);
- break;
- case OBRANCH:
- if (!next->label) {
- sym = getsym(TMPSYM);
- sym->kind = SLABEL;
- next->label = sym;
- }
- case OJMP:
- for (;;) {
- dst = np->u.sym->u.stmt;
- if (dst->op != OJMP)
- break;
- np->u.sym = dst->u.sym;
- }
- for (p = np->next; p; p = p->next) {
- if (p == dst)
- return NULL;
- if (p->op == ONOP ||
- p->op == OBLOOP ||
- p->op == OELOOP) {
- continue;
- }
- break;
- }
- break;
- }
- return np;
-}
--- a/src/cmd/scc/cc2/target/qbe_amd64-sysv/target.mk
+++ /dev/null
@@ -1,8 +1,0 @@
-OBJ-qbe_amd64-sysv = $(OBJS) \
- target/qbe/cgen.o \
- target/qbe/optm.o \
- target/qbe/code.o \
- target/amd64-sysv/types.o
-
-$(LIBEXEC)/cc2-qbe_amd64-sysv: $(OBJ-qbe_amd64-sysv)
- $(CC) $(SCC_LDFLAGS) $(OBJ-qbe_amd64-sysv) -lscc -o $@
--- a/src/cmd/scc/cc2/target/qbe_arm64-sysv/target.mk
+++ /dev/null
@@ -1,5 +1,0 @@
-OBJ-qbe_arm64-sysv = $(OBJS) \
- target/qbe/cgen.o \
- target/qbe/optm.o \
- target/qbe/code.o \
- target/arm64-sysv/types.o \
--- a/src/cmd/scc/cc2/target/z80-scc/arch.h
+++ /dev/null
@@ -1,5 +1,0 @@
-enum asmop {
- ASJMP = 0,
- ASRET,
- ASBRANCH,
-};
--- a/src/cmd/scc/cc2/target/z80-scc/cgen.c
+++ /dev/null
@@ -1,159 +1,0 @@
-#include <stdlib.h>
-
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-static void
-swtch(Node *idx)
-{
-}
-
-static Node *
-rhs(Node *np, Node *ret)
-{
-}
-
-static Node *
-field(Node *np, Node *ret, int islhs)
-{
-}
-
-static Node *
-lhs(Node *np, Node *new)
-{
- switch (np->op) {
- case OMEM:
- case OAUTO:
- *new = *np;
- return new;
- case OPTR:
- return rhs(np->left, new);
- case OFIELD:
- return field(np, new, 1);
- default:
- abort();
- }
-}
-
-static void
-bool(Node *np, Symbol *true, Symbol *false)
-{
- Node *l = np->left, *r = np->right;
- Node ret, ifyes, ifno;
- Symbol *label;
-
- switch (np->op) {
- case ONEG:
- bool(l, false, true);
- break;
- case OAND:
- label = newlabel();
- bool(l, label, false);
- setlabel(label);
- bool(r, true, false);
- break;
- case OOR:
- label = newlabel();
- bool(l, true, label);
- setlabel(label);
- bool(r, true, false);
- break;
- default:
- label2node(&ifyes, true);
- label2node(&ifno, false);
- code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno);
- break;
- }
-}
-
-Node *
-cgen(Node *np)
-{
- Node aux, *p, *next;
-
- setlabel(np->label);
- switch (np->op) {
- case OJMP:
- label2node(&aux, np->u.sym);
- code(ASJMP, NULL, &aux, NULL);
- break;
- case OBRANCH:
- next = np->next;
- if (!next->label)
- next->label = newlabel();
- bool(np->left, np->u.sym, next->label);
- break;
- case ORET:
- p = np->left;
- if (p)
- p = rhs(np->left, &aux);
- code(ASRET, NULL, p, NULL);
- break;
- case OBSWITCH:
- swtch(rhs(np->left, &aux));
- break;
- default:
- rhs(np, &aux);
- break;
- }
- return NULL;
-}
-
-/*
- * This is strongly influenced by
- * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
- * calculate addresability as follows
- * AUTO => 11 value+fp
- * REG => 13 reg
- * STATIC => 12 (value)
- * CONST => 20 $value
- */
-Node *
-sethi(Node *np)
-{
- Node *lp, *rp;
-
- if (!np)
- return np;
-
- np->complex = 0;
- np->address = 0;
- lp = np->left;
- rp = np->right;
- switch (np->op) {
- case OAUTO:
- np->address = 11;
- break;
- case OREG:
- np->address = 13;
- break;
- case OMEM:
- np->address = 12;
- break;
- case OCONST:
- np->address = 20;
- break;
- default:
- sethi(lp);
- sethi(rp);
- break;
- }
-
- if (np->address > 10)
- return np;
- if (lp)
- np->complex = lp->complex;
- if (rp) {
- int d = np->complex - rp->complex;
-
- if (d == 0)
- ++np->complex;
- else if (d < 0)
- np->complex = rp->complex;
- }
- if (np->complex == 0)
- ++np->complex;
- return np;
-}
--- a/src/cmd/scc/cc2/target/z80-scc/code.c
+++ /dev/null
@@ -1,227 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-enum segment {
- CODESEG,
- DATASEG,
- BSSSEG,
- NOSEG
-};
-
-static int curseg = NOSEG;
-static unsigned long offpar, offvar;
-
-static void
-segment(int seg)
-{
- static char *txt[] = {
- [CODESEG] = "\tCSEG\n",
- [DATASEG] = "\tDSEG\n",
- [BSSSEG] = "\tASEG\n",
- };
-
- if (seg == curseg)
- return;
- fputs(txt[seg], stdout);
- curseg = seg;
-}
-
-static char *
-symname(Symbol *sym)
-{
- static char name[INTIDENTSIZ+1];
-
- if (sym->name) {
- switch (sym->kind) {
- case SGLOB:
- case SEXTRN:
- snprintf(name, sizeof(name), "_%s", sym->name);
- return name;
- case SPRIV:
- return sym->name;
- }
- }
-
- sprintf(name, ".%d", sym->numid);
-
- return name;
-}
-
-static void
-label(Symbol *sym)
-{
- int seg;
- char *name = symname(sym);
-
- if (sym->type.flags & FUNF)
- seg = CODESEG;
- else if (sym->type.flags & INITF)
- seg = DATASEG;
- else
- seg = BSSSEG;
- segment(seg);
-
- switch (sym->kind) {
- case SEXTRN:
- printf("\tEXTRN\t%s\n", name);
- return;
- case SGLOB:
- printf("\tPUBLIC\t%s\n", name);
- break;
- }
-
- printf("%s:\n", name);
-}
-
-static void
-emitconst(Node *np)
-{
- switch (np->type.size) {
- case 1:
- printf("%d", (int) np->u.i & 0xFF);
- break;
- case 2:
- printf("%d", (int) np->u.i & 0xFFFF);
- break;
- case 4:
- printf("%ld", (long) np->u.i & 0xFFFFFFFF);
- break;
- default:
- abort();
- }
-}
-
-static void
-emittree(Node *np)
-{
- if (!np)
- return;
-
- switch (np->op) {
- case OSTRING:
- printf("\"%s\"", np->u.s);
- free(np->u.s);
- np->u.s = NULL;
- break;
- case OCONST:
- emitconst(np);
- break;
- case OADDR:
- emittree(np->left);
- break;
- case OMEM:
- fputs(symname(np->u.sym), stdout);
- break;
- default:
- emittree(np->left);
- printf(" %c ", np->op);
- emittree(np->right);
- break;
- }
-}
-
-static void
-size2asm(Type *tp)
-{
- char *s;
-
- /*
- * In z80 we can ignore the alignment
- */
- if (tp->flags & STRF) {
- s = "\tDB\t";
- } else {
- switch (tp->size) {
- case 1:
- s = "\tDB\t";
- break;
- case 2:
- s = "\tDW\t";
- break;
- case 4:
- s = "\tDD\t";
- break;
- default:
- s = "\tDS\t%lu,";
- break;
- }
- }
- printf(s, tp->size);
-}
-
-void
-newfun()
-{
- offpar = offvar = 0;
-}
-
-void
-defpar(Symbol *sym)
-{
- unsigned long align, size;
-
- if (sym->kind != SREG && sym->kind != SAUTO)
- return;
- align = sym->type.align;
- size = sym->type.size;
-
- offpar -= align-1 & ~align;
- sym->u.off = offpar;
- offpar -= size;
- sym->kind = SAUTO;
-}
-
-void
-defvar(Symbol *sym)
-{
- unsigned long align, size;
-
- if (sym->kind != SREG && sym->kind != SAUTO)
- return;
- align = sym->type.align;
- size = sym->type.size;
-
- offvar += align-1 & ~align;
- sym->u.off = offvar;
- offvar += size;
- sym->kind = SAUTO;
-}
-
-void
-defglobal(Symbol *sym)
-{
- label(sym);
- if (sym->kind == SEXTRN || (sym->type.flags & INITF))
- return;
- size2asm(&sym->type);
- puts("0");
-}
-
-void
-data(Node *np)
-{
- size2asm(&np->type);
- emittree(np);
- putchar('\n');
-}
-
-void
-writeout(void)
-{
-}
-
-void
-endinit(void)
-{
-}
-
-void
-getbblocks(void)
-{
-}
--- a/src/cmd/scc/cc2/target/z80-scc/optm.c
+++ /dev/null
@@ -1,9 +1,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-Node *
-optm_dep(Node *np)
-{
- return np;
-}
--- a/src/cmd/scc/cc2/target/z80-scc/target.mk
+++ /dev/null
@@ -1,8 +1,0 @@
-OBJ-z80-scc = $(OBJS) \
- target/z80-scc/cgen.o \
- target/z80-scc/optm.o \
- target/z80-scc/code.o \
- target/z80-scc/types.o \
-
-$(LIBEXEC)/cc2-z80-scc: $(OBJ-z80-scc)
- $(CC) $(SCC_LDFLAGS) $(OBJ-z80-scc) -lscc -o $@
--- a/src/cmd/scc/cc2/target/z80-scc/types.c
+++ /dev/null
@@ -1,93 +1,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-
-Type int8type = {
- .flags = SIGNF | INTF,
- .size = 1,
- .align = 1
-};
-
-Type int16type = {
- .flags = SIGNF | INTF,
- .size = 2,
- .align = 1
-};
-
-Type int32type = {
- .flags = SIGNF | INTF,
- .size = 4,
- .align = 1
-};
-
-Type int64type = {
- .flags = SIGNF | INTF,
- .size = 8,
- .align = 1
-};
-
-Type uint8type = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type uint16type = {
- .flags = INTF,
- .size = 2,
- .align = 1
-};
-
-Type uint32type = {
- .flags = INTF,
- .size = 4,
- .align = 1
-};
-
-Type uint64type = {
- .flags = INTF,
- .size = 8,
- .align = 1
-};
-
-Type ptrtype = {
- .flags = INTF,
- .size = 2,
- .align = 1
-};
-
-Type booltype = {
- .flags = INTF,
- .size = 1,
- .align = 1
-};
-
-Type float32type = {
- .flags = FLOATF,
- .size = 4,
- .align = 1
-};
-
-Type float64type = {
- .flags = FLOATF,
- .size = 4,
- .align = 1
-};
-
-Type float80type = {
- .flags = FLOATF,
- .size = 4,
- .align = 1
-};
-
-Type voidtype = {
- .size = 0,
- .align = 0
-};
-
-/* this types is not going to be used in this arch */
-Type arg_type = {
- .size = 0,
- .align = 0
-};
--- a/src/cmd/scc/posix/.gitignore
+++ /dev/null
@@ -1,1 +1,0 @@
-config.h
--- a/src/cmd/scc/posix/Makefile
+++ /dev/null
@@ -1,38 +1,0 @@
-.POSIX:
-
-PROJECTDIR = ../../../..
-include $(PROJECTDIR)/scripts/rules.mk
-
-# SYSLST is a list of backend-arch-abi-sys. First
-# element of the list becomes the default target
-
-SYSLST = amd64-sysv-linux-elf z80-scc-none-none \
- i386-sysv-linux-elf amd64-sysv-openbsd-elf
-
-STDCFLAGS =
-
-TARGETS = $(BINDIR)/scc $(BINDIR)/scpp
-
-all: $(TARGETS)
-
-$(BINDIR)/scc: scc.o
- $(CC) $(SCC_LDFLAGS) scc.o -lscc -o $@
-
-$(BINDIR)/scpp: cpp.sh
- trap "rm -f $$$$.sh" 0 2 3;\
- rm -f $@ ;\
- sed "s%@PREFIX@%$(PREFIX)%" < cpp.sh > $$$$.sh && \
- chmod +x $$$$.sh && \
- mv $$$$.sh $@
-
-config.h:
- PREFIX=$(PREFIX) mkconf $(SYSLST)
-
-dep: inc-dep
-
-clean:
- rm -f scc scpp *.o
- rm -f $(TARGETS)
- rm -f config.h
-
-include deps.mk
--- a/src/cmd/scc/posix/cpp.sh
+++ /dev/null
@@ -1,4 +1,0 @@
-#!/bin/sh
-
-SCCPREFIX=${SCCPREFIX:-@PREFIX@}
-${SCCPREFIX}/bin/scc -E $@
--- a/src/cmd/scc/posix/deps.mk
+++ /dev/null
@@ -1,8 +1,0 @@
-#deps
-./scc.o: $(INCDIR)/scc/scc/arg.h
-./scc.o: $(INCDIR)/scc/scc/ldflags.h
-./scc.o: $(INCDIR)/scc/scc/scc.h
-./scc.o: $(INCDIR)/scc/scc/syscrts.h
-./scc.o: $(INCDIR)/scc/scc/sysincludes.h
-./scc.o: $(INCDIR)/scc/scc/syslibs.h
-./scc.o: ./config.h
--- a/src/cmd/scc/posix/mkconf
+++ /dev/null
@@ -1,16 +1,0 @@
-#!/bin/sh
-
-set -e
-
-rm -f config.h
-trap "rm -f $$.h" 0 2 3
-
-PREFIX=${PREFIX-$HOME}
-
-echo $@ |
-(IFS='- ' read arch abi sys format r
-echo \#define PREFIX \"$PREFIX\"
-echo \#define ARCH \"$arch\"
-echo \#define SYS \"$sys\"
-echo \#define ABI \"$abi\"
-echo \#define FORMAT \"$format\") > $$.h && mv $$.h config.h
--- a/src/cmd/scc/posix/scc.c
+++ /dev/null
@@ -1,620 +1,0 @@
-#define _POSIX_SOURCE
-#define _XOPEN_SOURCE 500
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include <scc/arg.h>
-#include <scc/scc.h>
-#include <scc/syscrts.h>
-#include <scc/sysincludes.h>
-#include <scc/syslibs.h>
-#include <scc/ldflags.h>
-
-enum {
- CC1,
- TEEIR,
- CC2,
- TEEQBE,
- QBE,
- TEEAS,
- AS,
- LD,
- STRIP,
- LAST_TOOL,
-};
-
-static struct tool {
- char cmd[PATH_MAX];
- char bin[32];
- char *outfile;
- struct items args;
- unsigned nparams;
- int in, out, init;
- pid_t pid;
-} tools[] = {
- [CC1] = { .cmd = "cc1" },
- [TEEIR] = { .bin = "tee", .cmd = "tee", },
- [CC2] = { .cmd = "cc2" },
- [TEEQBE] = { .bin = "tee", .cmd = "tee", },
- [QBE] = { .bin = "qbe", .cmd = "qbe", },
- [TEEAS] = { .bin = "tee", .cmd = "tee", },
- [AS] = { .bin = "as", .cmd = "as", },
- [LD] = { .bin = "ld", .cmd = "ld", },
- [STRIP] = { .bin = "strip", .cmd = "strip", },
-};
-
-char *argv0;
-static char *arch, *sys, *abi, *format;
-static char *prefix, *objfile, *outfile;
-static char *tmpdir;
-static size_t tmpdirln;
-static struct items objtmp, objout;
-static int Mflag, Eflag, Sflag, Wflag,
- cflag, dflag, kflag, sflag, Qflag = 1; /* TODO: Remove Qflag */
-static int devnullfd = -1;
-
-extern int failure;
-
-static void
-terminate(void)
-{
- unsigned i;
-
- if (!kflag) {
- for (i = 0; i < objtmp.n; ++i)
- unlink(objtmp.s[i]);
- }
-}
-
-static void
-addarg(int tool, char *arg)
-{
- struct tool *t = &tools[tool];
-
- if (t->args.n < 1)
- t->args.n = 1;
-
- newitem(&t->args, arg);
-}
-
-static void
-setargv0(int tool, char *arg)
-{
- struct tool *t = &tools[tool];
-
- if (t->args.n > 0)
- t->args.s[0] = arg;
- else
- newitem(&t->args, arg);
-}
-
-static int
-qbe(int tool)
-{
- if (tool != CC2 || !Qflag)
- return 0;
- if (!strcmp(arch, "amd64") && !strcmp(abi, "sysv"))
- return 1;
- return 0;
-}
-
-static int
-inittool(int tool)
-{
- struct tool *t = &tools[tool];
- char *crt, *fmt;
- int n;
-
- if (t->init)
- return tool;
-
- switch (tool) {
- case CC1:
- if (Wflag)
- addarg(tool, "-w");
- for (n = 0; sysincludes[n]; ++n) {
- addarg(tool, "-I");
- addarg(tool, sysincludes[n]);
- }
- case CC2:
- fmt = (qbe(tool)) ? "%s-qbe_%s-%s" : "%s-%s-%s";
- n = snprintf(t->bin, sizeof(t->bin), fmt, t->cmd, arch, abi);
- if (n < 0 || n >= sizeof(t->bin))
- die("scc: target tool name too long");
-
- n = snprintf(t->cmd, sizeof(t->cmd),
- "%s/libexec/scc/%s", prefix, t->bin);
- if (n < 0 || n >= sizeof(t->cmd))
- die("scc: target tool path too long");
- break;
- case LD:
- for (n = 0; ldflags[n]; ++n)
- addarg(tool, ldflags[n]);
- addarg(tool, "-o");
- t->outfile = outfile ? outfile : xstrdup("a.out");
- addarg(tool, t->outfile);
- for (n = 0; syslibs[n]; ++n) {
- addarg(tool, "-L");
- addarg(tool, syslibs[n]);
- }
- if (syscrts[0]) {
- for (n = 0; syscrts[n]; ++n)
- addarg(tool, syscrts[n]);
- break;
- }
- n = snprintf(NULL, 0,
- "%s/lib/scc/%s-%s-%s/crt.o",
- prefix, arch, abi, sys);
- if (n < 0)
- die("scc: wrong crt file name");
- crt = xmalloc(++n);
- sprintf(crt,
- "%s/lib/scc/%s-%s-%s/crt.o",
- prefix, arch, abi, sys);
- addarg(tool, crt);
- break;
- case AS:
- addarg(tool, "-o");
- break;
- default:
- break;
- }
-
- setargv0(tool, t->bin);
- t->nparams = t->args.n;
- t->init = 1;
-
- return tool;
-}
-
-static char *
-outfname(char *path, char *type)
-{
- char *new, sep, *p;
- size_t newsz, pathln;
- int tmpfd, n;
-
- if (path) {
- sep = '.';
- if (p = strrchr(path, '/'))
- path = p + 1;
- pathln = strlen(path);
- if (p = strrchr(path, '.'))
- pathln -= strlen(p);
- } else {
- sep = '/';
- type = "scc-XXXXXX";
- path = tmpdir;
- pathln = tmpdirln;
- }
-
- newsz = pathln + 1 + strlen(type) + 1;
- new = xmalloc(newsz);
- n = snprintf(new, newsz, "%.*s%c%s", (int)pathln, path, sep, type);
- if (n < 0 || n >= newsz)
- die("scc: wrong output filename");
- if (sep == '/') {
- if ((tmpfd = mkstemp(new)) < 0)
- die("scc: could not create output file '%s': %s",
- new, strerror(errno));
- close(tmpfd);
- }
-
- return new;
-}
-
-static int
-settool(int tool, char *infile, int nexttool)
-{
- struct tool *t = &tools[tool];
- unsigned i;
- int fds[2];
- static int fdin = -1;
-
- switch (tool) {
- case TEEIR:
- t->outfile = outfname(infile, "ir");
- addarg(tool, t->outfile);
- break;
- case TEEQBE:
- t->outfile = outfname(infile, "qbe");
- addarg(tool, t->outfile);
- break;
- case TEEAS:
- t->outfile = outfname(infile, "s");
- addarg(tool, t->outfile);
- break;
- case AS:
- if (cflag && outfile) {
- objfile = outfile;
- } else {
- objfile = (cflag || kflag) ? infile : NULL;
- objfile = outfname(objfile, "o");
- }
- t->outfile = xstrdup(objfile);
- addarg(tool, t->outfile);
- break;
- case STRIP:
- if (cflag || kflag) {
- for (i = 0; i < objout.n; ++i)
- addarg(tool, xstrdup(objout.s[i]));
- }
- if (!cflag && tools[LD].outfile)
- addarg(tool, tools[LD].outfile);
- break;
- default:
- break;
- }
-
- if (fdin > -1) {
- t->in = fdin;
- fdin = -1;
- } else {
- t->in = -1;
- if (infile)
- addarg(tool, xstrdup(infile));
- }
-
- if (nexttool < LAST_TOOL) {
- if (pipe(fds))
- die("scc: pipe: %s", strerror(errno));
- t->out = fds[1];
- fdin = fds[0];
- } else {
- t->out = -1;
- }
-
- addarg(tool, NULL);
-
- return tool;
-}
-
-static void
-spawn(int tool)
-{
- struct tool *t = &tools[tool];
-
- switch (t->pid = fork()) {
- case -1:
- die("scc: %s: %s", t->bin, strerror(errno));
- case 0:
- if (t->out > -1)
- dup2(t->out, 1);
- if (t->in > -1)
- dup2(t->in, 0);
- if (!dflag && tool != CC1 && tool != LD)
- dup2(devnullfd, 2);
- execvp(t->cmd, t->args.s);
- if (dflag) {
- fprintf(stderr,
- "scc: execvp %s: %s\n",
- t->cmd,
- strerror(errno));
- }
- abort();
- default:
- if (t->in > -1)
- close(t->in);
- if (t->out > -1)
- close(t->out);
- break;
- }
-}
-
-static int
-toolfor(char *file)
-{
- char *dot = strrchr(file, '.');
-
- if (dot) {
- if (!strcmp(dot, ".c"))
- return CC1;
- if (!strcmp(dot, ".ir"))
- return CC2;
- if (!strcmp(dot, ".qbe"))
- return QBE;
- if (!strcmp(dot, ".s"))
- return AS;
- if (!strcmp(dot, ".o"))
- return LD;
- if (!strcmp(dot, ".a"))
- return LD;
- } else if (!strcmp(file, "-")) {
- return CC1;
- }
-
- die("scc: do not recognize filetype of %s", file);
-}
-
-static int
-valid(int tool, struct tool *t)
-{
- int st;
-
- if (waitpid(t->pid, &st, 0) == -1 || WIFSIGNALED(st))
- goto internal;
- if (WIFEXITED(st) && WEXITSTATUS(st) == 0)
- return 1;
- if (!failure && (tool == CC1 || tool == LD))
- goto fail;
-
-internal:
- fprintf(stderr, "scc:%s: internal error\n", t->bin);
-fail:
- failure = 1;
- return 0;
-}
-
-static int
-validatetools(void)
-{
- struct tool *t;
- unsigned i;
- int tool, st, failed = LAST_TOOL;
-
- for (tool = 0; tool < LAST_TOOL; ++tool) {
- t = &tools[tool];
- if (!t->pid)
- continue;
- if (!valid(tool, t))
- failed = tool;
- if (tool >= failed && t->outfile)
- unlink(t->outfile);
- for (i = t->nparams; i < t->args.n; ++i)
- free(t->args.s[i]);
- t->args.n = t->nparams;
- t->pid = 0;
- }
- if (failed < LAST_TOOL) {
- unlink(objfile);
- free(objfile);
- objfile = NULL;
- return 0;
- }
-
- return 1;
-}
-
-static int
-buildfile(char *file, int tool)
-{
- int nexttool;
-
- for (; tool < LAST_TOOL; tool = nexttool) {
- switch (tool) {
- case CC1:
- if (Eflag || Mflag)
- nexttool = LAST_TOOL;
- else
- nexttool = kflag ? TEEIR : CC2;
- break;
- case TEEIR:
- nexttool = CC2;
- break;
- case CC2:
- if (Qflag)
- nexttool = kflag ? TEEQBE : QBE;
- else
- nexttool = (Sflag || kflag) ? TEEAS : AS;
- break;
- case TEEQBE:
- nexttool = QBE;
- break;
- case QBE:
- nexttool = (Sflag || kflag) ? TEEAS : AS;
- break;
- case TEEAS:
- nexttool = Sflag ? LAST_TOOL : AS;
- break;
- case AS:
- nexttool = LAST_TOOL;
- break;
- default:
- nexttool = LAST_TOOL;
- continue;
- }
-
- spawn(settool(inittool(tool), file, nexttool));
- }
-
- return validatetools();
-}
-
-static void
-build(struct items *chain, int link)
-{
- int i, tool;
-
- if (link)
- inittool(LD);
-
- for (i = 0; i < chain->n; ++i) {
- if (!strcmp(chain->s[i], "-l")) {
- if (link) {
- addarg(LD, xstrdup(chain->s[i++]));
- addarg(LD, xstrdup(chain->s[i]));
- } else {
- ++i;
- }
- continue;
- }
- tool = toolfor(chain->s[i]);
- if (tool == LD) {
- if (link)
- addarg(LD, xstrdup(chain->s[i]));
- continue;
- }
- if (buildfile(chain->s[i], tool)) {
- if (link)
- addarg(LD, xstrdup(objfile));
- newitem((!link || kflag) ? &objout : &objtmp, objfile);
- }
- }
-}
-
-static void
-usage(void)
-{
- fputs("usage: scc [-D def[=val]]... [-U def]... [-I dir]... "
- "[-L dir]... [-l dir]...\n"
- " [-dgksw] [-m arch] [-M|-E|-S] [-o outfile] file...\n"
- " scc [-D def[=val]]... [-U def]... [-I dir]... "
- "[-L dir]... [-l dir]...\n"
- " [-dgksw] [-m arch] [-M|-E|-S] -c file...\n"
- " scc [-D def[=val]]... [-U def]... [-I dir]... "
- "[-L dir]... [-l dir]...\n"
- " [-dgksw] [-m arch] -c -o outfile file\n", stderr);
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- struct items linkchain = { .n = 0, };
- int link;
-
- atexit(terminate);
-
- if (!(arch = getenv("ARCH")))
- arch = ARCH;
- if (!(sys = getenv("SYS")))
- sys = SYS;
- if (!(abi = getenv("ABI")))
- abi = ABI;
- if (!(format = getenv("FORMAT")))
- format = FORMAT;
- if (!(prefix = getenv("SCCPREFIX")))
- prefix = PREFIX;
-
- ARGBEGIN {
- case 'D':
- addarg(CC1, "-D");
- addarg(CC1, EARGF(usage()));
- break;
- case 'M':
- Mflag = 1;
- addarg(CC1, "-M");
- break;
- case 'E':
- Eflag = 1;
- addarg(CC1, "-E");
- break;
- case 'I':
- addarg(CC1, "-I");
- addarg(CC1, EARGF(usage()));
- break;
- case 'L':
- addarg(LD, "-L");
- addarg(LD, EARGF(usage()));
- break;
- case 'O':
- EARGF(usage());
- break;
- case 'S':
- Sflag = 1;
- break;
- case 'U':
- addarg(CC1, "-U");
- addarg(CC1, EARGF(usage()));
- break;
- case 'c':
- cflag = 1;
- break;
- case 'd':
- dflag = 1;
- break;
- case 'g':
- addarg(AS, "-g");
- addarg(LD, "-g");
- break;
- case 'k':
- kflag = 1;
- break;
- case 'l':
- newitem(&linkchain, "-l");
- newitem(&linkchain, EARGF(usage()));
- break;
- case 'm':
- arch = EARGF(usage());
- break;
- case 'o':
- outfile = xstrdup(EARGF(usage()));
- break;
- case 's':
- sflag = 1;
- break;
- case 't':
- sys = EARGF(usage());
- break;
- case 'w':
- Wflag = 0;
- break;
- case 'W':
- Wflag = 1;
- break;
- case 'q':
- Qflag = 0;
- break;
- case 'Q':
- Qflag = 1;
- break;
- case '-':
- fprintf(stderr,
- "scc: ignored parameter --%s\n", EARGF(usage()));
- break;
- default:
- usage();
- } ARGOPERAND {
-operand:
- newitem(&linkchain, ARGOP());
- } ARGEND
-
- for (; *argv; --argc, ++argv)
- goto operand;
-
- if (Eflag && linkchain.n == 0)
- newitem(&linkchain, "-");
-
- if (Eflag && Mflag ||
- (Eflag || Mflag) && (Sflag || kflag) ||
- linkchain.n == 0 ||
- linkchain.n > 1 && cflag && outfile)
- usage();
-
- if (!dflag) {
- if ((devnullfd = open("/dev/null", O_WRONLY)) < 0)
- fputs("scc: could not open /dev/null\n", stderr);
- }
-
- if (!(tmpdir = getenv("TMPDIR")) || !tmpdir[0])
- tmpdir = ".";
- tmpdirln = strlen(tmpdir);
-
- build(&linkchain, (link = !(Mflag || Eflag || Sflag || cflag)));
-
- if (!(link || cflag))
- return failure;
-
- if (link && !failure) {
- addarg(LD, xstrdup("-lc"));
- spawn(settool(LD, NULL, LAST_TOOL));
- validatetools();
- }
-
- if (sflag) {
- spawn(settool(inittool(STRIP), NULL, LAST_TOOL));
- validatetools();
- }
-
- return failure;
-}