shithub: scc

Download patch

ref: d0763d72e63709ffc8af883c5dd2db4be98f6b77
parent: e41e68626c04ea501561eb6eb4bf93e6dda9c6e8
author: Roberto E. Vargas Caballero <[email protected]>
date: Wed Aug 6 08:38:17 EDT 2014

Split identifiers between local and global

This separation allows to use only the needed memory for a function
definition. If there is no difference between local and global,
we have to allocate memory for all the variables in the source,
because we don't know when they are not going to be used anymore.

--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -186,60 +186,6 @@
 	return STRING;
 }
 
-void
-init_keywords(void)
-{
-	static struct {
-		char *str;
-		uint8_t token, value;
-	} *bp, buff[] = {
-		{"auto", SCLASS, AUTO},
-		{"break", BREAK, BREAK},
-		{"_Bool", TYPE, BOOL},
-		{"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},
-		{"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},
-	};
-	register Symbol *sym;
-	extern short symid;
-
-	for (bp = buff; bp->str; ++bp) {
-		sym = install(bp->str, NS_IDEN);
-		sym->token = bp->token;
-		sym->u.token = bp->value;
-	}
-	symid = 0;
-}
-
 static uint8_t
 iden(void)
 {
--- a/cc1/symbol.c
+++ b/cc1/symbol.c
@@ -10,7 +10,8 @@
 #define NR_SYM_HASH 32
 
 uint8_t curctx;
-short symid;
+short localcnt;
+short globalcnt;
 
 static struct symtab {
 	Symbol *head;
@@ -66,8 +67,10 @@
 	--curctx;
 	freesyms(NS_IDEN);
 	freesyms(NS_TAG);
-	if (curctx == 0)
+	if (curctx == 0) {
+		localcnt = 0;
 		freesyms(NS_LABEL);
+	}
 }
 
 Symbol *
@@ -95,7 +98,7 @@
 	sym->name = xstrdup(s);
 	sym->ctx = curctx;
 	sym->token = IDEN;
-	sym->id = symid++;
+	sym->id = (curctx) ? ++localcnt : ++globalcnt;
 	sym->s.isdefined = 1;
 	tbl = &symtab[ns];
 	sym->next = tbl->head;
@@ -104,4 +107,57 @@
 	t = &tbl->htab[hash(s)];
 	sym->hash = *t;
 	return *t = sym;
+}
+
+void
+init_keywords(void)
+{
+	static struct {
+		char *str;
+		uint8_t token, value;
+	} *bp, buff[] = {
+		{"auto", SCLASS, AUTO},
+		{"break", BREAK, BREAK},
+		{"_Bool", TYPE, BOOL},
+		{"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},
+		{"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},
+	};
+	register Symbol *sym;
+
+	for (bp = buff; bp->str; ++bp) {
+		sym = install(bp->str, NS_IDEN);
+		sym->token = bp->token;
+		sym->u.token = bp->value;
+	}
+	globalcnt = 0;
 }
--- a/cc2/cc2.h
+++ b/cc2/cc2.h
@@ -17,9 +17,12 @@
 	int8_t sethi;
 	int8_t addrtype;
 	union {
-		short id;
+		Symbol *sym;
 		int imm;
 	} u;
 	struct node *left, *right;
 } Node;
 
+#define AUTO     'A'
+#define REGISTER 'R'
+#define STATIC   'S'
--- a/cc2/parser.c
+++ b/cc2/parser.c
@@ -21,19 +21,39 @@
 static Node nodepool[NR_NODEPOOL], *newp = nodepool;
 static Symbol symtbl[NR_SYMBOLS];
 
+static Symbol *localtbl;
+static Symbol *globaltbl;
+
 extern void esyntax(void);
 
-static short
-getid(void)
+static Symbol *
+local(void)
 {
-	int i;
+	unsigned i;
+	static unsigned nr;
 
-	scanf("%d", &i);
-	if (i < 0 || i >= NR_SYMBOLS)
+	scanf("%u", &i);
+	if (i >= NR_INT_IDENT)
 		esyntax();
-	return i;
+	if (i >= nr)
+		localtbl = xrealloc(localtbl, i+1);
+	return &localtbl[i];
 }
 
+static Symbol *
+global(void)
+{
+	unsigned i;
+	static unsigned nr;
+
+	scanf("%u", &i);
+	if (i >= NR_EXT_IDENT)
+		esyntax();
+	if (i >= nr)
+		globaltbl = xrealloc(globaltbl, i+1);
+	return &globaltbl[i];
+}
+
 static Node *
 newnode(void)
 {
@@ -82,12 +102,31 @@
 static void
 variable(char op)
 {
+	Symbol *sym;
 	Node *np = newnode();
-	short id = getid();
 
+	switch (op) {
+	case 'A':
+		sym = local();
+		op = AUTO;
+		break;
+	case 'R':
+		sym = local();
+		op = REGISTER;
+		break;
+	case 'T':
+		sym = local();
+		op = STATIC;
+		break;
+	case 'G':
+		sym = global();
+		op = STATIC;
+		break;
+	}
+
+	np->u.sym = sym;
 	np->op = op;
-	np->u.id = id;
-	np->type = symtbl[id].u.v.type;
+	np->type = sym->u.v.type;
 	np->left = np->right = NULL;
 	push(np);
 }
@@ -168,9 +207,9 @@
 }
 
 static void
-declaration(char sclass)
+declaration(char sclass, char islocal)
 {
-	Symbol *sym = &symtbl[getid()];
+	Symbol *sym = (islocal) ? local() : global();
 
 	getchar(); /* skip tab */
 	sym->u.v.storage = sclass;
@@ -191,7 +230,7 @@
 static void
 deflabel(void)
 {
-	Symbol *sym = &symtbl[getid()];
+	Symbol *sym = local();
 
 	sym->u.l.addr = listp - listexp;
 	chop();
@@ -217,7 +256,7 @@
 			/* struct */
 			break;
 		case 'T': case 'A': case 'R':
-			declaration(c);
+			declaration(c, 1);
 			break;
 		case '}':
 			chop();
@@ -238,7 +277,7 @@
 	for (;;) {
 		switch (c = getchar()) {
 		case 'G':
-			declaration(c);
+			declaration(c, 0);
 			break;
 		case 'X':
 			function();