scc

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

commit 3a7f44ab39f632bf2fe8b6c7ea1b56822f78d0d1
parent ffc846e846ca027ab5ac3a710b2a4269680c5bcb
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed,  3 Jul 2013 23:19:34 +0200

Add intermediate code for symbol definition

We need some intermediate code for the symbol definitions, because
symbol definitions can have initializators, and the initializators
of extern symbols can't be attatched to the current function.

Diffstat:
Mdecl.c | 38+++++++++++++++++++++++---------------
Mflow.c | 21++++++++++++---------
Mmain.c | 8+++++---
Msyntax.h | 6+++---
Mtree.c | 3++-
5 files changed, 45 insertions(+), 31 deletions(-)

diff --git a/decl.c b/decl.c @@ -150,49 +150,57 @@ initializer(register struct ctype *tp) return np; } -static void -listdcl(register struct ctype *tp) +static struct node * +listdcl(struct ctype *tp) { + struct node *lp = nodecomp(); + do { + register struct node *sp, *np; + declarator(); tp = decl_type(tp); if (!tp->type) { warning_error(options.implicit, "type defaults to 'int' in declaration of '%s'", yytext); - } else if (tp->type == FTN && yytoken == '{') { - function(cursym); - return; } - if (accept('=')) - initializer(tp); + sp = nodesym(cursym); + if (tp->type == FTN && yytoken == '{') { + np = node2(ODEF, sp, function(cursym)); + return addstmt(lp, np); + } + np = node2(ODEF, sp, accept('=') ? initializer(tp) : NULL); + lp = addstmt(lp, np); } while (accept(',')); expect(';'); + + return lp; } -unsigned char +struct node * decl(void) { register struct ctype *tp; + register struct node *np = NULL; - if (accept(';')) - return 1; - + while (accept(';')) + /* nothing */; tp = newctype(); if (!spec(tp)) { if (curctx != CTX_OUTER) - return 0; + goto end; warning("data definition has no type or storage class"); } if (accept(';')) { warning_error(options.useless, "useless type name in empty declaration"); } else { - listdcl(tp); + np = listdcl(tp); } - delctype(tp); - return 1; +end: delctype(tp); + return np; } void diff --git a/flow.c b/flow.c @@ -233,17 +233,17 @@ _default(void) static struct node * compound(void) { - register struct node *np = nodecomp(); + register struct node *lp = nodecomp(), *np; expect('{'); new_ctx(); - while (decl()) - /* nothing */; + while (np = decl()) + addstmt(lp, np); while (!accept('}')) - addstmt(np, stmt()); + addstmt(lp, stmt()); del_ctx(); - return np; + return lp; } static struct node * @@ -271,13 +271,16 @@ stmt(void) return np; } -void +struct node * function(register struct symbol *sym) { - register struct node *np; - curfun = sym; - np = node2(OFTN, nodesym(sym), compound()); + return node1(OFTN, compound()); +} + +void +run(register struct node *np) +{ prtree(np); putchar('\n'); freesyms(); diff --git a/main.c b/main.c @@ -6,18 +6,20 @@ #include "syntax.h" extern void open_file(const char *file); +extern void run(struct node *np); struct user_opt options; - int main(int argc, char *argv[]) { + struct node *np; + init_keywords(); open_file(NULL); - for (next(); yytoken != EOFTOK; decl()) - /* nothing */; + for (next(); yytoken != EOFTOK; run(np)) + np = decl(); return 0; } diff --git a/syntax.h b/syntax.h @@ -12,16 +12,16 @@ enum opcode { OA_MOD, OA_ADD, OA_SUB, OA_SHL, OA_SHR, OA_AND, OA_XOR, OA_OR, OSYM, OCOMP, OSWITCH, OIF, OFOR, OFEXP, ODO, OWHILE, OLABEL, OGOTO, OBREAK, OCONT, - ORETURN, OCASE, ODEFAULT, OFTN + ORETURN, OCASE, ODEFAULT, OFTN, ODEF }; struct node; struct symbol; extern struct node *expr(void); -extern unsigned char decl(void); +extern struct node *decl(void); extern void type_name(void); -extern void function(struct symbol *sym); +extern struct node *function(struct symbol *sym); extern struct node *node3(unsigned char op, struct node *l, struct node *i, struct node *r); diff --git a/tree.c b/tree.c @@ -190,7 +190,8 @@ prtree_helper(register struct node *np) [ORETURN] = {1, "return"}, [OCASE] = {1, "case"}, [ODEFAULT] = {1, "default"}, - [OFTN] = {2, "function"} + [OFTN] = {1, "function"}, + [ODEF] = {2, "def"} }; if (!np) { fputs(" nil", stdout);