scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit dd604299ecdeb25d1c7d0f4cb77e2478777272ad
parent b6d551944bd495bb30ba7345f5ab77ccca14c295
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue,  1 Apr 2014 21:42:12 +0200

Merge branch 'bsc'

Diffstat:
Mcc.h | 215+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mcode.c | 112++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Dcode.h | 10----------
Mdecl.c | 91+++++++++++++++++++++++++++++++-------------------------------------------------
Merror.c | 6++++--
Mexpr.c | 223+++++++++++++++++++++++++++++++++++++------------------------------------------
Mlex.c | 8+++-----
Mmain.c | 1-
Mstmt.c | 12+++++-------
Msymbol.c | 18++++++++----------
Dsymbol.h | 112-------------------------------------------------------------------------------
Dtokens.h | 79-------------------------------------------------------------------------------
Mtypes.c | 206+++++++++++++++++++++----------------------------------------------------------
Mwrapper.c | 2++
14 files changed, 533 insertions(+), 562 deletions(-)

diff --git a/cc.h b/cc.h @@ -1,12 +1,11 @@ #ifndef CC_H #define CC_H -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) - -extern unsigned linenum; -extern unsigned columnum; -extern const char *filename; +#ifndef __bool_true_and_false_defined +#include <stdbool.h> +#endif +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) struct user_opt { unsigned char implicit; @@ -26,4 +25,210 @@ extern void *xmalloc(size_t size); extern void *xcalloc(size_t nmemb, size_t size); extern char *xstrdup(const char *s); extern void *xrealloc(void *buff, register size_t size); + +/* definitions of types */ + +#define CTX_OUTER 0 +#define CTX_FUNC 1 + +enum { + NS_IDEN = 0, + NS_LABEL, + NS_TAG, + NR_NAMESPACES, + NS_KEYWORD, + NS_FREE +}; + +struct funpars; +struct symbol; + +struct ctype { + uint8_t op; /* type builder operator */ + char letter; /* letter of the type */ + short nelem; /* number of elements in arrays */ + unsigned defined : 1; /* type defined (is not a forward reference) */ + unsigned sign : 1; /* sign type */ + struct symbol *sym; /* symbol of the tag identifier */ + struct ctype *type; /* base type */ + struct ctype *next; /* next element in the hash */ + union { + struct funpar *pars; /* function parameters */ + struct field *fields; /* aggregate fields */ + } u; +}; + +typedef struct ctype Type; + +struct field { + struct symbol *sym; + struct field *next; +}; + +struct funpar { + Type *type; + struct funpar *next; +}; + +/* definition of symbols */ + +union value { + char c; + int i; + struct symbol *sym; + uint8_t ns, token; +}; + +struct symbol { + char *name; + Type *type; + short id; + uint8_t ctx; + uint8_t token; + uint8_t ns; + struct { + bool isglobal : 1; + bool isstatic : 1; + bool isauto : 1; + bool isregister : 1; + } s; + union value u; + struct symbol *next; + struct symbol *hash; +}; + +typedef struct symbol Symbol; + +extern void freesyms(uint8_t ns); + +extern Type *qualifier(Type *tp, uint8_t qlf), + *ctype(int8_t type, int8_t sign, int8_t size), + *mktype(Type *tp, + uint8_t op, Symbol *tag, uint16_t nelem); + +extern Symbol + *lookup(char *s, unsigned char ns), + *install(char *s, unsigned char ns); + +extern void context(void (*fun)(void)); + +extern Type *voidtype, + *uchartype, *chartype, + *uinttype, *inttype, + *ushortype, *shortype, + *longtype, *ulongtype, + *ullongtype, *llongtype, + *floattype, *doubletype, *ldoubletype; + +#define ISQUAL(t) (isqual((t)->op)) +#define UNQUAL(t) (ISQUAL(t) ? (t)->type : (t)) +#define BTYPE(t) (UNQUAL(t)->op) +#define isarith(op) ((op) & ARITH) +#define isaddr(op) ((op) & POINTER) +#define isrecord(op) ((op) & RECORD) +#define isqual(op) ((op) & TQUALIFIER) + + +#define ARITH 8 +#define RECORD 16 +#define POINTER 32 +#define ATYPE(x) (ARITH | (x)) +#define RTYPE(x) (RECORD | (x)) +#define PTYPE(x) (POINTER| (x)) + +#define FTN 1 +#define ENUM 2 +#define TYPENAME 3 +#define VOID 4 + +#define FLOAT ATYPE(1) +#define INT ATYPE(2) +#define BOOL ATYPE(3) + +#define STRUCT RTYPE(1) +#define UNION RTYPE(2) + +#define PTR PTYPE(1) +#define ARY PTYPE(2) + +#define CHAR (ARY+1) +#define DOUBLE (ARY+2) +#define SHORT (ARY+3) +#define LONG (ARY+4) + +#define COMPLEX (ARY+5) +#define IMAGINARY (ARY+6) +#define UNSIGNED (ARY+7) +#define SIGNED (ARY+8) + +#define CONST (1<<0) +#define VOLATILE (1<<1) +#define RESTRICT (1<<2) + +#define TYPEDEF 1 +#define EXTERN 2 +#define STATIC 3 +#define AUTO 4 +#define REGISTER 5 + +#define accept(t) ((yytoken == (t)) ? next() : 0) +#define ahead() yyntoken + +enum tokens { + TQUALIFIER = 128, TYPE, IDEN, SCLASS, + CONSTANT, 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, + CONTINUE, BREAK, RETURN, EOFTOK, NOTOK +}; + +union yystype { + Symbol *sym; + uint8_t token; +}; + +extern union yystype yylval; +extern char yytext[]; +extern uint8_t yytoken, yyntoken; + +extern uint8_t next(void); +extern void expect(uint8_t tok); + + +typedef struct node { + void (*code)(struct node *); + Type *type; + union unode { + Symbol *sym; + Type *type; + char op; + } u; + struct node *childs[]; +} Node; + +typedef void (*Inst)(Node *); + +enum { + OCAST, OPTR, OADD, OARY, OSIZE, OMUL +}; + +extern void + emitsym(Node *), emitunary(Node *), + emitbin(Node *), emitexp(Node *); + +extern Node + *node(Inst code, Type *tp, union unode u, uint8_t nchilds), + *unarycode(char op, Type *tp, Node *child), + *bincode(char op, Type *tp, Node *np1, Node *np2), + *castcode(Node *child, Type *tp), + *sizeofcode(Type *tp); + +#define SYM(s) ((union unode) {.sym = s}) +#define OP(s) ((union unode) {.op = s}) +#define TYP(s) ((union unode) {.type = s}) + #endif diff --git a/code.c b/code.c @@ -2,11 +2,32 @@ #include <stdint.h> #include <stdio.h> -#include "symbol.h" +#include "cc.h" + +char *opcodes[] = { + [OADD] = "+", + [OMUL] = "*", + [OARY] = "'", + [OSIZE] = "#", + [OPTR] = "@" +}; + +Node * +node(Inst code, Type *tp, union unode u, uint8_t nchilds) +{ + Node *np = xmalloc(sizeof(*np) + nchilds * sizeof(np)); + + np->code = code; + np->type = tp; + np->u = u; + + return np; +} void -emitsym(struct symbol *sym) +emitsym(Node *np) { + Symbol *sym = np->u.sym; char c; if (sym->s.isglobal) @@ -14,26 +35,104 @@ emitsym(struct symbol *sym) else if (sym->s.isstatic) c = 'T'; else if (sym->s.isregister) - c = 'R'; + c = 'Q'; else c = 'A'; printf("\t%c%d", c, sym->id); } void -emitfun(struct symbol *sym) +emitcast(Node *np) +{ + Node *child = np->childs[0]; + + (*child->code)(child); + printf("\t%c%c", np->u.type->letter, np->type->letter); +} + +void +emitunary(Node *np) +{ + Node *child; + char op, letter; + + letter = np->type->letter; + child = np->childs[0]; + (*child->code)(child); + printf("\t%s%c", opcodes[np->u.op], letter); +} + +void +emitbin(Node *np) +{ + Node *child1, *child2; + + child1 = np->childs[0]; + child2 = np->childs[1]; + (*child1->code)(child1); + (*child2->code)(child2); + printf("\t%s%c", opcodes[np->u.op], np->type->letter); +} + +void +emitsizeof(Node *np) +{ + printf("\t#%c", np->u.type->letter); +} + +void +emitexp(Node *np) +{ + (*np->code)(np); + putchar('\n'); +} + +void +emitfun(Symbol *sym) { printf("X%s\n", sym->name); } void -emitframe(struct symbol *sym) +emitframe(Symbol *sym) { puts("{"); } void -emitret(struct symbol *sym) +emitret(Symbol *sym) { puts("}"); } + +Node * +castcode(Node *child, Type *tp) +{ + Node *np = node(emitcast, tp, TYP(child->type), 1); + + np->childs[0] = child; + return np; +} + +Node * +unarycode(char op, Type *tp, Node *child) +{ + Node *np = node(emitunary, tp, OP(op), 1); + np->childs[0] = child; + return np; +} + +Node * +bincode(char op, Type *tp, Node *np1, Node *np2) +{ + Node *np = node(emitbin, tp, OP(op), 2); + np->childs[0] = np1; + np->childs[1] = np2; + return np; +} + +Node * +sizeofcode(Type *tp) +{ + return node(emitsizeof, inttype, TYP(tp), 0); +} +\ No newline at end of file diff --git a/code.h b/code.h @@ -1,10 +0,0 @@ - -#ifndef CODE_H_ -#define CODE_H_ - -struct symbol; - -extern void emitsym(struct symbol *sym), emitfun(struct symbol *sym), - emitframe(struct symbol *sym), emitret(struct symbol *sym); - -#endif diff --git a/decl.c b/decl.c @@ -5,8 +5,6 @@ #include "sizes.h" #include "cc.h" -#include "tokens.h" -#include "symbol.h" #include "machine.h" #define ID_EXPECTED 1 @@ -18,7 +16,7 @@ struct dcldata { uint8_t op; union { unsigned short nelem; - struct symbol *sym; + Symbol *sym; struct funpars *pars; uint8_t qlf; } u; @@ -51,10 +49,10 @@ fundcl(struct dcldata *dp) return dp + 1; } -static struct symbol * +static Symbol * newiden(uint8_t ns) { - struct symbol *sym; + Symbol *sym; extern uint8_t curctx; if (yylval.sym && yylval.sym->ctx == curctx) @@ -67,7 +65,7 @@ newiden(uint8_t ns) static struct dcldata * directdcl(struct dcldata *dp, uint8_t ns, int8_t flags) { - register struct symbol *sym; + register Symbol *sym; char *err; if (accept('(')) { @@ -133,12 +131,12 @@ too_much_declarators: error("too much declarators"); } -static struct symbol * -declarator(struct ctype *tp, uint8_t ns, int8_t flags) +static Symbol * +declarator(Type *tp, uint8_t ns, int8_t flags) { struct dcldata data[NR_DECLARATORS+1]; register struct dcldata *bp; - struct symbol *sym; + Symbol *sym; memset(data, 0, sizeof(data)); data[NR_DECLARATORS].op = 255; @@ -162,19 +160,19 @@ declarator(struct ctype *tp, uint8_t ns, int8_t flags) return sym; } -static struct ctype *structdcl(void), *enumdcl(void); +static Type *structdcl(void), *enumdcl(void); -static struct ctype * +static Type * specifier(int8_t *sclass) { - struct ctype *tp = NULL; - int8_t qlf, sign, type, cls, cplex, size, t; + Type *tp = NULL; + int8_t qlf, sign, type, cls, size, t; - qlf = sign = type = cls = size = cplex = 0; + qlf = sign = type = cls = size = 0; for (;;) { register uint8_t *p; - struct ctype *(*dcl)(void) = NULL; + Type *(*dcl)(void) = NULL; switch (yytoken) { case SCLASS: p = &cls; break; @@ -203,8 +201,6 @@ specifier(int8_t *sclass) } case SHORT: p = &size; break; - case COMPLEX: case IMAGINARY: - p = &cplex; break; } break; default: @@ -228,7 +224,6 @@ check_types: type = INT; } if (sign && type != INT && type != CHAR || - cplex && type != FLOAT && type != DOUBLE || size == SHORT && type != INT || size == LONG && type != INT && type != DOUBLE || size == LONG+LONG && type != INT) { @@ -237,7 +232,7 @@ check_types: if (sclass) *sclass = cls; if (!tp) - tp = ctype(type, sign, size, cplex); + tp = ctype(type, sign, size); return (qlf) ? qualifier(tp, qlf) : tp; invalid_type: @@ -245,7 +240,7 @@ invalid_type: } static struct node * -initializer(register struct ctype *tp) +initializer(register Type *tp) { if (accept('{')) { initializer(tp); @@ -260,11 +255,10 @@ initializer(register struct ctype *tp) /* TODO: bitfields */ static void -newfield(struct ctype *tp, struct symbol *sym) +newfield(Type *tp, Symbol *sym) { register struct field *p, *q; register char *s, *t; - static short size, offset; static uint8_t op; static char *err; @@ -281,25 +275,10 @@ newfield(struct ctype *tp, struct symbol *sym) p = xmalloc(sizeof(*p)); p->next = NULL; p->sym = sym; - size = sym->type->size; - if (!q) { + if (!q) tp->u.fields = p; - if (op != ENUM) { - tp->size = size; - sym->u.offset = 0; - } - } else { + else q->next = p; - if (tp->op == STRUCT) { - offset = ALIGN(size, tp->size); - sym->u.offset = offset; - tp->size = offset + size; - } else if (op == UNION) { - sym->u.offset = 0; - if (tp->size < size) - tp->size = size; - } - } return; @@ -313,10 +292,10 @@ error: } static void -fielddcl(struct ctype *base, uint8_t ns) +fielddcl(Type *base, uint8_t ns) { - struct ctype *tp; - struct symbol *sym; + Type *tp; + Symbol *sym; char *err; switch (yytoken) { @@ -349,11 +328,11 @@ error: error(err, yytext); } -static struct ctype * +static Type * newtag(uint8_t tag) { - register struct symbol *sym; - struct ctype *tp; + register Symbol *sym; + Type *tp; extern uint8_t namespace; if (yytoken == IDEN) { @@ -377,10 +356,10 @@ bad_tag: error("'%s' defined as wrong kind of tag", yytext); } -static struct ctype * +static Type * structdcl(void) { - struct ctype *tp; + Type *tp; uint8_t ns, tag; tag = yylval.token; @@ -403,11 +382,11 @@ redefined: error("redefinition of struct/union '%s'", yytext); } -static struct ctype * +static Type * enumdcl(void) { - register struct ctype *tp; - struct symbol *sym; + register Type *tp; + Symbol *sym; int val = 0; char *err; @@ -447,8 +426,8 @@ error: void decl(void) { - struct ctype *tp; - struct symbol *sym; + Type *tp; + Symbol *sym; int8_t sclass; tp = specifier(&sclass); @@ -472,9 +451,9 @@ typename(void) void extdecl(void) { - struct ctype *base; + Type *base; int8_t sclass; - struct symbol *sym; + Symbol *sym; char *err; extern void compound(void); @@ -493,14 +472,14 @@ extdecl(void) if (yytoken != ';') { do { - struct ctype *tp; + Type *tp; sym = declarator(base, NS_IDEN, ID_EXPECTED); tp = sym->type; if (!(sclass & STATIC)) sym->s.isglobal = 1; - if (isfun(BTYPE(tp))) { + if (BTYPE(tp) == FTN) { emitfun(sym); if (yytoken == '{') { emitframe(sym); diff --git a/error.c b/error.c @@ -1,12 +1,14 @@ #include <stdarg.h> #include <stdlib.h> +#include <stdint.h> #include <stdio.h> #include "cc.h" - - +extern unsigned linenum; +extern unsigned columnum; +extern const char *filename; static void warn_helper(char flag, const char *fmt, va_list va) diff --git a/expr.c b/expr.c @@ -2,50 +2,22 @@ #include <stdio.h> #include "cc.h" -#include "code.h" -#include "tokens.h" -#include "symbol.h" - -struct node *expr(void); - -enum { - OSYM = 1, OARY, OPTR, OADD, -}; - -struct node { - uint8_t op; - struct ctype *type; - - struct { - bool constant : 1; - } f; - union { - struct symbol *sym; - } u; - struct node *left, *right; -}; - -struct node * -newnode(uint8_t op, struct ctype *tp) -{ - struct node *np = xcalloc(1, sizeof(*np)); - np->op = op; - np->type = tp; - return np; -} +#define SWAP(x1, x2, t) (t = x1, x1 = x2, x2 = t) + +Node *expr(void); -static struct node * +static Node * primary(void) { - register struct node *np; + Node *np; + Symbol *sym; switch (yytoken) { case IDEN: - if (yylval.sym == NULL) + if ((sym = yylval.sym) == NULL) error("'%s' undeclared", yytext); - np = newnode(OSYM, yylval.sym->type); - np->u.sym = yylval.sym; + np = node(emitsym, sym->type, SYM(sym), 0); next(); break; case CONSTANT: @@ -58,117 +30,133 @@ primary(void) expect(')'); break; default: - np = NULL; + ; } return np; } -static struct node * -int2ptr(struct node *np) +void +intconv(Node **np1, Node **np2) { } -static struct node * -ptr2vec(struct node *np) +void +floatconv(Node **np1, Node **np2) { - struct ctype *tp = np->type; - struct node *p; - - tp = mktype(UNQUAL(tp)->type, ARY, NULL, 0); - p = newnode(OPTR, tp); - p->left = np; - return p; } -static struct node * -ary(struct node *np1) +static Node * +add(Node *np1, Node *np2) { - struct node *np2, *naux; - struct ctype *tp; + Node *naux; + Type *tp1, *tp2; uint8_t t1, t2, taux; - /* should be for arrays: A2 A1 RI #1 *R ` */ - /* should be for pointers: A2 @ A1 RI #1 *R ` */ - np2 = expr(); - expect(']'); + tp1 = UNQUAL(np1->type), tp2 = UNQUAL(np2->type); + t1 = tp1->op, t2 = tp2->op; + + switch (t1) { + case INT: + switch (t2) { + case INT: + if (tp1 != tp2) + intconv(&np1, &np2); + break; + case FLOAT: + SWAP(np1, np2, naux); + goto int_float; + case PTR: case FTN: case ARY: + SWAP(np1, np2, naux); + SWAP(t1, t2, taux); + goto pointer; + default: + goto incorrect; + } + break; + case FLOAT: + switch (t2) { + case FLOAT: + if (tp1 != tp2) + floatconv(&np1, &np2); + break; + case INT: +int_float: np2 = castcode(np2, np1->type); + break; + default: + goto incorrect; + } + break; + case PTR: case FTN: case ARY: +pointer: tp3 = tp1->type; + if (t1 == ARY) + tp1 = mktype(tp1->type, PTR, NULL, 0); + if (t2 != INT) + goto incorrect; + np2 = bincode(OMUL, tp1, + castcode(np2, tp1), + sizeofcode(tp3)); + break; + default: + goto incorrect; + } + + return bincode(OADD, tp1, np1, np2); + +incorrect: + error("incorrect arithmetic operands"); /*TODO: print type names */ +} + +static Node * +array(Node *np1, Node *np2) +{ + Type *tp; + uint8_t t1, t2; + char *err; + t1 = BTYPE(np1->type); t2 = BTYPE(np2->type); - - if (!isaddr(t1)) { - taux = t1, t1 = t2, t2 = taux; - naux = np1, np1 = np2, np2 = naux; - } - if (!isaddr(t1)) - error("expected array or pointer"); - if (isptr(t1)) - np1 = ptr2vec(np1); - if (!isarith(t2)) - error("array subscript is not an integer"); - - tp = np1->type; - tp = UNQUAL(tp); - naux = newnode(OADD, tp); - naux->left = np1; - naux->right = int2ptr(np2); - return naux; + if (!isaddr(t1) && !isaddr(t2)) + goto bad_vector; + if (t1 != INT && t2 != INT) + goto bad_subs; + np1 = add(np1, np2); + return unarycode(OARY, np1->type->type , np1); + +bad_vector: + err = "subscripted value is neither array nor pointer nor vector"; + goto error; +bad_subs: + err = "array subscript is not an integer"; +error: error(err); } -static struct node * +static Node * postfix(void) { - struct node *np; + Node *np1, *np2; - np = primary(); + np1 = primary(); for (;;) { switch (yytoken) { - case '[': next(); np = ary(np); break; - default: return np; + case '[': + next(); + np2 = expr(); + np1 = array(np1, np2); + expect(']'); + break; + default: + return np1; } - } + } } -struct node * +Node * expr(void) { - register struct node *np; + Node *np; do np = postfix(); while (yytoken == ','); - return np; } - -static void -evalnode(struct node *np) -{ - if (!np) - return; - - switch (np->op) { - case OSYM: - emitsym(np->u.sym); - break; - case OARY: - evalnode(np->left); - evalnode(np->right); - fputs("\t'", stdout); - break; - case OPTR: - evalnode(np->left); - fputs("\t@", stdout); - break; - case OADD: - evalnode(np->left); - evalnode(np->right); - fputs("\t+", stdout); - break; - } -} - -void -eval(struct node *np) -{ - evalnode(np); - putchar('\n'); -} -\ No newline at end of file diff --git a/lex.c b/lex.c @@ -6,8 +6,6 @@ #include <ctype.h> #include "cc.h" -#include "tokens.h" -#include "symbol.h" #include "sizes.h" static FILE *yyin; @@ -25,7 +23,7 @@ static char yybuf[IDENTSIZ + 1]; static uint8_t integer(char *s, char base) { - static struct ctype *tp; + static Type *tp; static char ch; /* TODO: implement again */ @@ -128,7 +126,7 @@ init_keywords(void) {"while", WHILE, WHILE}, {NULL, 0, 0}, }; - register struct symbol *sym; + register Symbol *sym; for (bp = buff; bp->str; ++bp) { sym = install(bp->str, NS_KEYWORD); @@ -142,7 +140,7 @@ iden(void) { register char *bp; register int c; - struct symbol *sym; + Symbol *sym; for (bp = yybuf; bp < &yybuf[IDENTSIZ]; *bp++ = c) { if (!isalnum(c = getc(yyin)) && c != '_') diff --git a/main.c b/main.c @@ -3,7 +3,6 @@ #include <stdint.h> #include "cc.h" -#include "tokens.h" extern void extdecl(void), init_keywords(void), open_file(const char *file); diff --git a/stmt.c b/stmt.c @@ -1,15 +1,14 @@ +#include <stddef.h> #include <stdint.h> -#include "symbol.h" -#include "tokens.h" - +#include "cc.h" void compound(void) { - extern struct node *expr(void); extern void decl(void); + extern Node *expr(void); expect('{'); while (!accept('}')) { @@ -18,8 +17,8 @@ compound(void) decl(); break; default: - eval(expr()); + emitexp(expr()); } expect(';'); } -} -\ No newline at end of file +} diff --git a/symbol.c b/symbol.c @@ -5,8 +5,6 @@ #include <string.h> #include "cc.h" -#include "symbol.h" -#include "tokens.h" #define NR_SYM_HASH 32 @@ -14,8 +12,8 @@ uint8_t curctx; uint8_t namespace = NS_KEYWORD + 1 ; static struct symtab { - struct symbol *head; - struct symbol *htab[NR_SYM_HASH]; + Symbol *head; + Symbol *htab[NR_SYM_HASH]; } symtab [NR_NAMESPACES]; static inline uint8_t @@ -32,7 +30,7 @@ void freesyms(uint8_t ns) { static struct symtab *tbl; - register struct symbol *sym; + register Symbol *sym; tbl = &symtab[ns]; for (sym = tbl->head; sym; sym = sym->next) { @@ -59,12 +57,12 @@ context(void (*fun)(void)) freesyms(NS_TAG); } -struct symbol * +Symbol * lookup(register char *s, uint8_t ns) { extern union yystype yylval; static struct symtab *tbl; - register struct symbol *sym; + register Symbol *sym; tbl = &symtab[(ns >= NR_NAMESPACES) ? NS_IDEN : ns]; for (sym = tbl->htab[hash(s)]; sym; sym = sym->hash) { @@ -76,11 +74,11 @@ lookup(register char *s, uint8_t ns) return NULL; } -struct symbol * +Symbol * install(char *s, uint8_t ns) { - register struct symbol *sym; - register struct symbol **t; + register Symbol *sym; + register Symbol **t; struct symtab *tbl; static short id; diff --git a/symbol.h b/symbol.h @@ -1,112 +0,0 @@ - -#ifndef SYMBOL_H -#define SYMBOL_H - -#if ! __bool_true_and_false_are_defined -#include <stdbool.h> -#endif - -#define CTX_OUTER 0 -#define CTX_FUNC 1 - -enum { - NS_IDEN = 0, - NS_LABEL, - NS_TAG, - NR_NAMESPACES, - NS_KEYWORD, - NS_FREE -}; - -struct funpars; -struct symbol; - -struct ctype { - uint8_t op; /* type builder operator */ - short size; /* size of variables */ - short nelem; /* number of elements in arrays */ - unsigned defined : 1; /* type defined (is not a forward reference) */ - unsigned cplex : 1; /* complex specifier */ - unsigned imag : 1; - unsigned sign : 1; /* sign type */ - struct symbol *sym; /* symbol of the tag identifier */ - struct ctype *type; /* base type */ - struct ctype *next; /* next element in the hash */ - union { - struct funpar *pars; /* function parameters */ - struct field *fields; /* aggregate fields */ - } u; -}; - -struct field { - struct symbol *sym; - struct field *next; -}; - -struct funpar { - struct ctype *type; - struct funpar *next; -}; - -union value { - char c; - int i; - struct symbol *sym; - uint8_t ns, token; - short offset; -}; - -struct symbol { - char *name; - struct ctype *type; - short id; - uint8_t ctx; - uint8_t token; - uint8_t ns; - struct { - bool isglobal : 1; - bool isstatic : 1; - bool isauto : 1; - bool isregister : 1; - } s; - union value u; - struct symbol *next; - struct symbol *hash; -}; - -extern void freesyms(uint8_t ns); - -extern struct ctype *qualifier(struct ctype *tp, uint8_t qlf), - *ctype(int8_t type, int8_t sign, int8_t size, int8_t cplex), - *mktype(struct ctype *tp, - uint8_t op, struct symbol *tag, uint16_t nelem); - -extern struct symbol - *lookup(char *s, unsigned char ns), - *install(char *s, unsigned char ns); - -extern void context(void (*fun)(void)); - -extern struct ctype *voidtype, - *uchartype, *chartype, - *uinttype, *inttype, - *ushortype, *shortype, - *longtype, *ulongtype, - *ullongtype, *llongtype, - *floattype, *cfloattype, *ifloattype, - *doubletype, *cdoubletype, *idoubletype, - *ldoubletype, *cldoubletype,*ildoubletype; - -#define ISQUAL(t) (isqual((t)->op)) -#define UNQUAL(t) (ISQUAL(t) ? (t)->type : (t)) -#define BTYPE(t) (UNQUAL(t)->op) -#define isfun(op) ((op) == FTN) -#define isptr(op) ((op) == PTR) -#define isary(op) ((op) == ARY) -#define isarith(op) ((op) & ARITH) -#define isaddr(op) ((op) & POINTER) -#define isrecord(op) ((op) & RECORD) -#define isqual(op) ((op) & TQUALIFIER) - - -#endif diff --git a/tokens.h b/tokens.h @@ -1,79 +0,0 @@ -#ifndef TOKENS_H -#define TOKENS_H - -#if ! __bool_true_false_are_defined -# include <stdbool.h> -#endif - -#define ARITH 8 -#define RECORD 16 -#define POINTER 32 -#define ATYPE(x) (ARITH | (x)) -#define RTYPE(x) (RECORD | (x)) -#define PTYPE(x) (POINTER| (x)) - -#define FTN 1 -#define ENUM 2 -#define TYPENAME 3 -#define VOID 4 - -#define FLOAT ATYPE(1) -#define INT ATYPE(2) -#define BOOL ATYPE(3) - -#define STRUCT RTYPE(1) -#define UNION RTYPE(2) - -#define PTR PTYPE(1) -#define ARY PTYPE(2) - -#define CHAR (ARY+1) -#define DOUBLE (ARY+2) -#define SHORT (ARY+3) -#define LONG (ARY+4) - -#define COMPLEX (ARY+5) -#define IMAGINARY (ARY+6) -#define UNSIGNED (ARY+7) -#define SIGNED (ARY+8) - -#define CONST (1<<0) -#define VOLATILE (1<<1) -#define RESTRICT (1<<2) - -#define TYPEDEF 1 -#define EXTERN 2 -#define STATIC 3 -#define AUTO 4 -#define REGISTER 5 - -#define accept(t) ((bool) (yytoken == (t) ? next() : 0)) -#define ahead() yyntoken - -enum tokens { - TQUALIFIER = 128, TYPE, IDEN, SCLASS, - CONSTANT, 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, - CONTINUE, BREAK, RETURN, EOFTOK, NOTOK -}; - -struct symbol; -union yystype { - struct symbol *sym; - uint8_t token; -}; - -extern union yystype yylval; -extern char yytext[]; -extern uint8_t yytoken, yyntoken; - - -extern uint8_t next(void); -extern void expect(uint8_t tok); - -#endif diff --git a/types.c b/types.c @@ -5,106 +5,78 @@ #include "sizes.h" #include "cc.h" -#include "tokens.h" -#include "symbol.h" #include "machine.h" #define NR_TYPE_HASH 16 -struct ctype - *voidtype = &(struct ctype) { - .op = VOID +Type + *voidtype = &(Type) { + .op = VOID, + .letter = 'W' }, - *uchartype = &(struct ctype) { + *booltype = &(Type) { .op = INT, - .size = CHARSIZE, + .letter = 'B' + }, + *uchartype = &(Type) { + .op = INT, + .letter = 'M', .sign = 1 }, - *chartype = &(struct ctype) { + *chartype = &(Type) { .op = INT, - .size = CHARSIZE, + .letter = 'C', }, - *uinttype = &(struct ctype) { + *uinttype = &(Type) { .op = INT, - .size = INTSIZE, + .letter = 'U', .sign = 1 }, - *inttype = &(struct ctype) { + *inttype = &(Type) { .op = INT, - .size = INTSIZE, - .sign = 1 + .letter = 'I', }, - *ushortype = &(struct ctype) { + *ushortype = &(Type) { .op = INT, - .size = SHORTSIZE, + .letter = 'E' }, - *shortype = &(struct ctype) { + *shortype = &(Type) { .op = INT, - .size = INTSIZE, + .letter = 'K', }, - *longtype = &(struct ctype) { + *longtype = &(Type) { .op = INT, - .size = LONGSIZE, + .letter = 'L' }, - *ulongtype = &(struct ctype) { + *ulongtype = &(Type) { .op = INT, - .size = LONGSIZE, + .letter = 'Z', .sign = 1 }, - *ullongtype = &(struct ctype) { + *ullongtype = &(Type) { .op = INT, - .size = LLONGSIZE, + .letter = 'O', .sign = 1 }, - *llongtype = &(struct ctype) { + *llongtype = &(Type) { .op = INT, - .size = LLONGSIZE, - }, - *floattype = &(struct ctype) { - .op = FLOAT, - .size = FLOATSIZE - }, - *cfloattype = &(struct ctype) { - .op = FLOAT, - .size = FLOATSIZE, - .cplex = 1 - }, - *ifloattype = &(struct ctype) { - .op = FLOAT, - .size = FLOATSIZE, - .imag = 1 - }, - *doubletype = &(struct ctype) { - .op = FLOAT, - .size = FLOATSIZE - }, - *cdoubletype = &(struct ctype) { - .op = FLOAT, - .size = 0, - .cplex = 1 - }, - *idoubletype = &(struct ctype) { - .op = FLOAT, - .size = 0, - .imag = 1 + .letter = 'G', }, - *ldoubletype = &(struct ctype) { + *floattype = &(Type) { .op = FLOAT, - .size = LLFLOATSIZE + .letter = 'F' }, - *cldoubletype = &(struct ctype) { + *doubletype = &(Type) { .op = FLOAT, - .size = 0, - .cplex = 1 + .letter = 'D' }, - *ildoubletype = &(struct ctype) { + *ldoubletype = &(Type) { .op = FLOAT, - .size = 0, - .imag = 1 + .letter = 'H' }; -struct ctype * -ctype(int8_t type, int8_t sign, int8_t size, int8_t cplex) +Type * +ctype(int8_t type, int8_t sign, int8_t size) { if (type == CHAR && !sign) sign = options.charsign; @@ -115,6 +87,7 @@ ctype(int8_t type, int8_t sign, int8_t size, int8_t cplex) switch (type) { case VOID: return voidtype; + case BOOL: return booltype; case CHAR: return (sign) ? uchartype : chartype; case INT: switch (size) { case 0: return (sign) ? uinttype : inttype; @@ -123,33 +96,21 @@ ctype(int8_t type, int8_t sign, int8_t size, int8_t cplex) case LONG+LONG: return (sign) ? ullongtype : llongtype; } case FLOAT: switch (size) { - case 0: switch (cplex) { - case 0: return floattype; - case COMPLEX: return cfloattype; - case IMAGINARY: return ifloattype; - } - case LONG: switch (cplex) { - case 0: return doubletype; - case COMPLEX: return cdoubletype; - case IMAGINARY: return ifloattype; - } - case LONG+LONG: switch (cplex) { - case 0: return ldoubletype; - case COMPLEX: return cldoubletype; - case IMAGINARY: return ildoubletype; - } + case 0: return floattype; + case LONG: return doubletype; + case LONG+LONG: return ldoubletype; } } } -struct ctype * -mktype(struct ctype *tp, uint8_t op, - struct symbol *sym, uint16_t nelem) +Type * +mktype(Type *tp, uint8_t op, + Symbol *sym, uint16_t nelem) { - static struct ctype *typetab[NR_TYPE_HASH], **tbl; + static Type *typetab[NR_TYPE_HASH], **tbl; static uint8_t t; - static unsigned short size; - register struct ctype *bp; + register Type *bp; + char letter; t = (op ^ (uint8_t) ((unsigned short) tp >> 3)) & NR_TYPE_HASH-1; @@ -164,12 +125,12 @@ mktype(struct ctype *tp, uint8_t op, } switch (op) { - case PTR: size = PTRSIZE; break; - case FTN: size = 0; break; - case ARY: size = tp->size * nelem; break; - case ENUM: size = INTSIZE; - case STRUCT: size = 0; break; - default: size = tp->size; break; + case PTR: letter = 'R'; break; + case FTN: letter = 'F'; break; + case ARY: letter = 'V'; break; + case ENUM: letter = 'E'; break; + case STRUCT: letter = 'S'; break; + default: abort(); } bp = xmalloc(sizeof(*bp)); bp->next = *tbl; @@ -177,12 +138,12 @@ mktype(struct ctype *tp, uint8_t op, bp->op = op; bp->nelem = nelem; bp->sym = sym; - bp->size = size; + bp->letter = letter; return *tbl = bp; } -struct ctype * -qualifier(struct ctype *tp, uint8_t qlf) +Type * +qualifier(Type *tp, uint8_t qlf) { uint8_t q = tp->op; @@ -195,60 +156,3 @@ qualifier(struct ctype *tp, uint8_t qlf) return mktype(tp, qlf|TQUALIFIER, NULL, 0); } -#include <stdio.h> - -static void -ptype(struct ctype *tp) -{ - uint8_t op; - struct funpar *fp; - - if (!tp) - return; - op = tp->op; - if (op & TQUALIFIER) { - if (op & CONST) - fputs("const ", stdout); - if (op & VOLATILE) - fputs("volatile ", stdout); - if (op & RESTRICT) - fputs("restrict ", stdout); - } else { - switch (op) { - case PTR: fputs("pointer ", stdout); break; - case ARY: fputs("array ", stdout); break; - case STRUCT: fputs("struct", stdout); break; - case UNION: fputs("union", stdout); break; - case ENUM: fputs("enum", stdout); break; - case BOOL: fputs("bool", stdout); break; - case INT: - printf("int size=%u sign=%u", tp->size, tp->sign); - break; - case FLOAT: - printf("float size=%u cplex=%u", tp->size, tp->cplex); - break; - case TYPENAME: - printf("typename %s type ", tp->sym->name); - break; - case FTN: - fputs("function(", stdout); - for (fp = tp->u.pars; fp; fp = fp->next) { - ptype(tp); - if (fp->next) - fputs(", ", stdout); - } - fputs(") ", stdout); - break; - } - } - ptype(tp->type); -} - -void -printtype(struct ctype *tp) -{ - printf("type = %p ", tp); - ptype(tp); - putchar('\n'); -} - diff --git a/wrapper.c b/wrapper.c @@ -2,6 +2,8 @@ #include <stdlib.h> #include <string.h> +#include <stdint.h> + #include "cc.h"