shithub: scc

Download patch

ref: 9fbc6a472de910787bc0ba27ceac576392b46045
parent: 8de2cd4ed1cc4193a4db1c7aad83133dea693f96
author: Roberto E. Vargas Caballero <[email protected]>
date: Fri Dec 15 16:59:18 EST 2017

[as] Rework section layer

There were several problems with the section layer
and this patch unifies sections and symbols, making
easier to handle them.

--- a/as/as.h
+++ b/as/as.h
@@ -9,6 +9,8 @@
 	FUNDEF  = 1 << 3,
 	FDEDUP  = 1 << 4,
 	FRELOC  = 1 << 5,
+	FSECT   = 1 << 6,
+	FNTYPE  = 1 << 7, 
 };
 
 enum secflags {
@@ -99,7 +101,7 @@
 };
 
 struct section {
-	String name;
+	Symbol *sym;
 	char *mem;
 	unsigned char flags;
 	unsigned char fill;
@@ -132,9 +134,10 @@
 };
 
 /* symbol.c */
-extern void isections(void);
+extern void cleansecs(void);
+extern void isecs(void);
 extern void emit(char *bytes, int nbytes);
-extern Section *setsection(char *name);
+extern Section *setsec(char *name, char *attr);
 extern Symbol *tmpsym(TUINT val);
 extern void killtmp(void);
 extern int toobig(Node *np, int type);
@@ -142,7 +145,7 @@
 extern String newstring(char *s);
 
 /* main.c */
-extern Symbol *lookup(char *name, int type);
+extern Symbol *lookup(char *name);
 extern Symbol *deflabel(char *name);
 
 /* parser.c */
--- a/as/expr.c
+++ b/as/expr.c
@@ -200,7 +200,7 @@
 	}
 
 	tok2str();
-	yylval.sym = lookup(yytext, FUNDEF);
+	yylval.sym = lookup(yytext);
 
 	return IDEN;
 }
@@ -267,9 +267,9 @@
 	while (isalnum(c = *endp))
 		++endp;
 	tok2str();
-	yylval.sym = lookup(yytext, FREG);
-	if (!yylval.sym->argtype)
-		error("incorrect register name");
+	yylval.sym = lookup(yytext);
+	if ((yylval.sym->flags & FREG) == 0)
+		error("incorrect register name '%s'", yytext);
 	return REG;
 }
 
--- a/as/ins.c
+++ b/as/ins.c
@@ -3,6 +3,8 @@
 #include "../inc/scc.h"
 #include "as.h"
 
+extern Section *sabs, *sbss, *sdata, *stext;
+
 char *
 tobytes(TUINT v, int nbytes, int inc)
 {
@@ -79,23 +81,23 @@
 {
 	Symbol *sym = args[0]->sym;
 
-	setsection(sym->name.buf);
+	setsec(sym->name.buf, NULL);
 }
 
 void
 text(Op *op, Node **args)
 {
-	setsection("text");
+	cursec = stext;
 }
 
 void
 data(Op *op, Node **args)
 {
-	setsection("data");
+	cursec = sdata;
 }
 
 void
 bss(Op *op, Node **args)
 {
-	setsection("bss");
+	cursec = sbss;
 }
--- a/as/main.c
+++ b/as/main.c
@@ -75,7 +75,7 @@
 
 	if ((fp = fopen(fname, "r")) == NULL)
 		die("as: error opening '%s'", fname);
-	isections();
+	cleansecs();
 
 	setjmp(recover);
 	while (nextline(fp, &line)) {
@@ -128,6 +128,7 @@
 
 	atexit(cleanup);
 	iarch();
+	isecs();
 	for (pass = 1; pass <= 2; pass++) {
 		if (!dopass(infile))
 			return 1;
--- a/as/myro.c
+++ b/as/myro.c
@@ -35,14 +35,6 @@
 		off += len;
 	}
 
-	for (sp = seclist; sp; sp = sp->next) {
-		str = &sp->name;
-		len = strlen(str->buf) + 1;
-		fwrite(str->buf, len, 1, fp);
-		str->offset = off;
-		off += len;
-	}
-
 	return off;
 }
 
@@ -78,7 +70,7 @@
 		if (id == MYROMAXSEC)
 			die("too many sections for a myro file");
 		sp->id = id++;
-		sect.name = sp->name.offset;
+		sect.name = sp->sym->name.offset;
 		sect.flags = getsecflags(sp);
 		sect.fill = sp->fill;
 		sect.aligment = sp->aligment;
@@ -114,7 +106,7 @@
 	struct myrosym symbol;
 
 	for (sym = symlist; sym; sym = sym->next) {
-		if (sym->flags & FREG)
+		if (sym->flags & (FREG|FSECT))
 			continue;
 		symbol.name = sym->name.offset;
 		symbol.type = -1;
--- a/as/symbol.c
+++ b/as/symbol.c
@@ -11,37 +11,14 @@
 #define HASHSIZ 64
 #define NALLOC  10
 
-static Section abss = {
-	.name  = (String) {"abs"},
-	.flags = SABS|SREAD|SWRITE|SFILE|SLOAD,
-};
-
-static Section bss = {
-	.name  = (String) {"bss"},
-	.flags = SREAD|SWRITE|SLOAD,
-	.next  = &abss,
-};
-
-static Section data = {
-	.name  = (String) {"data"},
-	.flags = SREAD|SWRITE|SFILE|SLOAD,
-	.next  = &bss,
-};
-
-static Section text = {
-	.name  = (String) {"text"},
-	.flags = SREAD|SEXEC|SLOAD|SFILE,
-	.next  = &data,
-};
-
-Section *cursec = &text, *seclist = &text;
-
+Section *cursec, *seclist;
+Section *sabs, *sbss, *sdata, *stext;
+Symbol *linesym, *symlist;
 int pass;
 
-static Symbol *hashtbl[HASHSIZ];
+static Symbol *hashtbl[HASHSIZ], *symlast;
 static Alloc *tmpalloc;
 
-Symbol *linesym, *symlist, *symlast;
 
 #ifndef NDEBUG
 void
@@ -65,7 +42,7 @@
 #endif
 
 Symbol *
-lookup(char *name, int type)
+lookup(char *name)
 {
 	unsigned h;
 	Symbol *sym, **list;
@@ -81,17 +58,13 @@
 	list = &hashtbl[h];
 	for (sym = *list; sym; sym = sym->hash) {
 		t = sym->name.buf;
-		if (c != toupper(*t) || casecmp(t, name))
-			continue;
-		symtype = sym->flags;
-		if (((symtype | type) & FUNDEF) == 0 && symtype != type)
-			continue;
-		return sym;
+		if (c == toupper(*t) && !casecmp(t, name))
+			return sym;
 	}
 
 	sym = xmalloc(sizeof(*sym));
 	sym->name = newstring(name);
-	sym->flags = FRELOC | FUNDEF | type;
+	sym->flags = FRELOC | FUNDEF | FNTYPE;
 	sym->value = 0;
 	sym->section = cursec;
 	sym->hash = *list;
@@ -132,7 +105,7 @@
 		name = label;
 	}
 
-	sym = lookup(name, FUNDEF);
+	sym = lookup(name);
 	if (pass == 1 && (sym->flags & FUNDEF) == 0)
 		error("redefinition of label '%s'", name);
 	if (cursec->flags & SABS)
@@ -139,6 +112,7 @@
 		sym->flags &= ~FRELOC;
 	sym->flags &= ~FUNDEF;
 	sym->value = cursec->curpc;
+	sym->section = cursec;
 
 	if (*name != '.')
 		cursym = sym;
@@ -177,50 +151,97 @@
 	}
 }
 
-
-static void
-isect(Section *sec)
+static int
+secflags(char *attr)
 {
-	TUINT siz;
+	int c, flags;
 
-	sec->curpc = sec->pc = sec->base;
-	if (pass == 1 || !(sec->flags & SFILE))
-		return;
+	if (!attr)
+		return 0;
 
-	siz = sec->max - sec->base;
-	if (siz > SIZE_MAX)
-		die("out of memory");
-	sec->mem = xmalloc(sec->max - sec->base);
+	for (flags = 0; c = *attr++; ) {
+		switch (c) {
+		case 'w':
+			flags |= SWRITE;
+			break;
+		case 'r':
+			flags |= SREAD;
+			break;
+		case 'x':
+			flags |= SEXEC;
+			break;
+		case 'f':
+			flags |= SFILE;
+			break;
+		case 'l':
+			flags |= SLOAD;
+			break;
+		case 'a':
+			flags |= SABS;
+			break;
+		}
+	}
+
+	return flags;
 }
 
 Section *
-setsection(char *name)
+setsec(char *name, char *attr)
 {
 	Section *sec;
+	Symbol *sym;
+	int flags;
 
-	for (sec = seclist; sec; sec = sec->next) {
-		if (!strcmp(sec->name.buf, name))
-			break;
-	}
-	if (!sec) {
+	cursec = NULL;
+	sym = lookup(name);
+	if ((sym->flags & (FNTYPE | FSECT)) == 0)
+		error("invalid section name '%s'", name);
+
+	if ((sec = sym->section) == NULL) {
 		sec = xmalloc(sizeof(*sec));
-		sec->name = newstring(name);
+		sec->sym = sym;
 		sec->base = sec->max = sec->pc = sec->curpc = 0;
 		sec->next = seclist;
 		sec->flags = 0;
 		sec->fill = 0;
 		sec->aligment = 0;
+		sec->next = seclist;
+		seclist = sec;
+
+		sym->section = sec;
+		sym->flags = FSECT;
 	}
+	sec->flags |= secflags(attr);
+
 	return cursec = sec;
 }
 
 void
-isections(void)
+isecs(void)
 {
+	sabs = setsec(".abs", "rwxafl");
+	sbss = setsec(".bss", "rwl");
+	sdata = setsec(".data", "rwfl");
+	stext = setsec(".text", "rxfl");
+}
+
+void
+cleansecs(void)
+{
 	Section *sec;
+	TUINT siz;
 
-	for (sec = seclist; sec; sec = sec->next)
-		isect(sec);
+	for (sec = seclist; sec; sec = sec->next) {
+		sec->curpc = sec->pc = sec->base;
+		if (pass == 1 || !(sec->flags & SFILE))
+			continue;
+
+		siz = sec->max - sec->base;
+		if (siz > SIZE_MAX)
+			die("out of memory");
+		sec->mem = xmalloc(sec->max - sec->base);
+	}
+	cursec = stext;
 }
 
 void
--- a/as/target/i386/proc.c
+++ b/as/target/i386/proc.c
@@ -92,7 +92,8 @@
 	}, *bp;
 
 	for (bp = regs; bp->name; ++bp) {
-		Symbol *sym = lookup(bp->name, FREG);
+		Symbol *sym = lookup(bp->name);
+		sym->flags = FREG;
 		sym->argtype = bp->type;
 	}
 }
--- a/as/target/z80/proc.c
+++ b/as/target/z80/proc.c
@@ -45,7 +45,8 @@
 	}, *bp;
 
 	for (bp = regs; bp->name; ++bp) {
-		Symbol *sym = lookup(bp->name, FREG);
+		Symbol *sym = lookup(bp->name);
+		sym->flags = FREG;
 		sym->argtype = bp->type;
 	}
 }