shithub: scc

Download patch

ref: 3a11ea050c4cec90cb4827042e4d13a4de6ef20c
parent: 9c9021c8001fd168ccaf6f9085ecc46f04975be5
parent: 92f9a64740292aba5d19f9562ab63d3f7645e491
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue May 29 11:19:37 EDT 2018

Merge branch 'master' of ssh://simple-cc.org:/var/gitrepos/scc

--- a/README
+++ b/README
@@ -1,6 +1,6 @@
 Derivations from standard C
 ===========================
-This compiler is aimed to be being fully compatible with the C99 standard, but
+This compiler aims to be fully compatible with the C99 standard, but
 it will have some differences:
 
 - Type qualifiers are accepted but ignored.
--- a/as/target/x86/ins.c
+++ b/as/target/x86/ins.c
@@ -32,6 +32,16 @@
 	case AREG_DH:
 		return R8CLASS;
 
+	case AREG_AX:
+	case AREG_BX:
+	case AREG_CX:
+	case AREG_DX:
+	case AREG_DI:
+	case AREG_SI:
+	case AREG_SP:
+	case AREG_BP:
+		return R16CLASS;
+
 	case AREG_CS:
 	case AREG_DS:
 	case AREG_SS:
@@ -58,37 +68,29 @@
 	case AREG_VIP:
 	case AREG_ID:
 
-	case AREG_AX:
 	case AREG_EAX:
 	case AREG_RAX:
 
-	case AREG_BX:
 	case AREG_EBX:
 	case AREG_RBX:
 
-	case AREG_CX:
 	case AREG_ECX:
 	case AREG_RCX:
 
-	case AREG_DX:
 	case AREG_EDX:
 	case AREG_RDX:
 
-	case AREG_SI:
 	case AREG_SIL:
 	case AREG_ESI:
 	case AREG_RSI:
-	case AREG_DI:
 	case AREG_DIL:
 	case AREG_EDI:
 	case AREG_RDI:
 
-	case AREG_SP:
 	case AREG_SPL:
 	case AREG_ESP:
 	case AREG_RSP:
 
-	case AREG_BP:
 	case AREG_BPL:
 	case AREG_EBP:
 	case AREG_RBP:
@@ -202,6 +204,9 @@
 			break;
 		case AREG_R8CLASS:
 			class = R8CLASS;
+			goto check_class;
+		case AREG_R16CLASS:
+			class = R16CLASS;
 		check_class:
 			if ((getclass(np) & class) == 0)
 				return 0;
@@ -261,6 +266,35 @@
 
 	src = reg8toint(args[0]);
 	dst = reg8toint(args[1]);
+	buf[0] = op->bytes[0];
+	buf[1] = addrbyte(REG_MODE, src, dst);
+	emit(buf, 2);
+}
+
+static int
+reg16toint(Node *np)
+{
+	switch (np->sym->value) {
+	case AREG_AX: return 0;
+	case AREG_CX: return 1;
+	case AREG_DX: return 2;
+	case AREG_BX: return 3;
+	case AREG_SP: return 4;
+	case AREG_BP: return 5;
+	case AREG_SI: return 6;
+	case AREG_DI: return 7;
+	default:	abort();
+	}
+}
+
+void
+reg16_reg16(Op *op, Node **args)
+{
+	int src, dst;
+	char buf[2];
+
+	src = reg16toint(args[0]);
+	dst = reg16toint(args[1]);
 	buf[0] = op->bytes[0];
 	buf[1] = addrbyte(REG_MODE, src, dst);
 	emit(buf, 2);
--- a/as/target/x86/proc.h
+++ b/as/target/x86/proc.h
@@ -148,8 +148,10 @@
 	AREG_MXCSR,
 
 	AREG_R8CLASS,   /* register class for 8 bit registers in i286 */
+	AREG_R16CLASS,   /* register class for 16 bit registers in i286 */
 };
 
-enum {
-	R8CLASS = 1 << 0,
+enum class {
+	R8CLASS  = 1 << 0,
+	R16CLASS = 1 << 1,
 };
--- a/as/target/x86/x86.dat
+++ b/as/target/x86/x86.dat
@@ -25,3 +25,4 @@
 
 # 8 bit arithmetic operations
 ADDB	reg8,reg8	2	0x00	reg8_reg8	I286,I386,AMD64
+ADDW	reg16,reg16	2 	0x01	reg16_reg16	I286,I386,AMD64
--- a/ld/Makefile
+++ b/ld/Makefile
@@ -26,6 +26,7 @@
 coff32.o: ./../inc/coff32/syms.h
 coff32.o: ./../inc/scc.h
 coff32.o: ./ld.h
+formats.o: ./../inc/scc.h
 formats.o: ./ld.h
 main.o: ./../inc/ar.h
 main.o: ./../inc/scc.h
--- a/ld/coff32.c
+++ b/ld/coff32.c
@@ -1,7 +1,9 @@
 static char sccsid[] = "@(#) ./ld/coff32.c";
 
 #include <assert.h>
+#include <ctype.h>
 #include <errno.h>
+#include <limits.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -14,6 +16,7 @@
 #include "ld.h"
 
 static int (*unpack)(unsigned char *, char *, ...);
+static int align;
 
 static FILHDR *
 getfhdr(unsigned char *buff, FILHDR *hdr)
@@ -48,6 +51,13 @@
 
 	(*unpack)(buff, "l", &siz);
 
+	siz -= 4;
+	if (siz == 0) {
+		obj->strtbl = NULL;
+		obj->strsiz = 0;
+		return 0;
+	}
+
 	if (siz > SIZE_MAX || (str = malloc(siz)) == NULL)
 		outmem();
 
@@ -55,6 +65,8 @@
 		return -1;
 
 	obj->strtbl = str;
+	obj->strsiz = siz;
+
 	return 0;
 }
 
@@ -84,8 +96,9 @@
 {
 	unsigned nsec, i;
 	unsigned char buff[SCNHSZ];
-	SCNHDR *scn;
+	SCNHDR *scn, *p;
 	FILHDR *hdr;
+	Symbol *sym;
 
 	hdr = obj->filhdr;
 	nsec = hdr->f_nscns;
@@ -98,10 +111,20 @@
 	if (fseek(obj->fp, off, SEEK_SET) == EOF)
 		return -1;
 
-	for (i = 0; i < nsec; i++) {
+	for (p = scn; p < &scn[nsec]; ++p) {
 		if (fread(buff, SCNHSZ, 1, obj->fp) != 1)
 			return -1;
-		getscn(buff, &scn[i]);
+		getscn(buff, p);
+		sym = lookup(p->s_name);
+
+		sym->size = (sym->size + align-1) & align-1;
+		if (sym->size > ULLONG_MAX - p->s_size) {
+			fprintf(stderr,
+			        "ld: %s: overflow in section '%s'\n",
+			        obj->fname, p->s_name);
+			exit(EXIT_FAILURE);
+		}
+		sym->size += p->s_size;
 	}
 	obj->scnhdr = scn;
 
@@ -130,31 +153,156 @@
 		(*unpack)(buff, "ll", &ent->n_zeroes, &ent->n_offset);
 }
 
+static char *
+symname(Obj *obj, SYMENT *ent)
+{
+	long off;
+
+	if (ent->n_zeroes != 0)
+		return ent->n_name;
+
+	off = ent->n_offset;
+	if (off >= obj->strsiz) {
+		fprintf(stderr,
+		        "ld: invalid offset in symbol table: %zd\n", off);
+		return "";
+	}
+
+	return &obj->strtbl[off];
+}
+
+static char
+typeof(Obj *obj, SYMENT *ent)
+{
+	SCNHDR *sec;
+	FILHDR *hdr;
+	int c, n;
+	long flags;
+
+	switch (ent->n_scnum) {
+	case N_DEBUG:
+		c = 'n';
+		break;
+	case N_ABS:
+		c = 'a';
+		break;
+	case N_UNDEF:
+		c = (ent->n_value != 0) ? 'C' : 'U';
+		break;
+	default:
+		sec = obj->scnhdr;
+		hdr = obj->filhdr;
+		n = ent->n_scnum;
+		if (n > hdr->f_nscns)
+			return '?';
+		sec = &sec[n-1];
+		flags = sec->s_flags;
+		if (flags & STYP_TEXT)
+			c = 't';
+		else if (flags & STYP_DATA)
+			c = 'd';
+		else if (flags & STYP_BSS)
+			c = 'b';
+		else
+			c = '?';
+		break;
+	}
+
+	if (ent->n_sclass == C_EXT)
+		c = toupper(c);
+
+	return c;
+}
+
+static TUINT
+getval(Obj *obj, SYMENT *ent)
+{
+	FILHDR *hdr = obj->filhdr;;
+	SCNHDR *scn = obj->scnhdr;
+
+	if (ent->n_scnum > hdr->f_nscns) {
+		fprintf(stderr,
+		        "ld: %s: incorrect section number\n",
+		        obj->fname,
+		        ent->n_scnum);
+		exit(EXIT_FAILURE);
+	}
+
+	scn = &scn[ent->n_scnum-1];
+
+	/*
+	 * TODO: We have to add the composed size of the segment minus
+	 * the size of the fragment
+	 */
+	return ent->n_value - scn->s_size;
+}
+
 static int
 readsyms(Obj *obj, long off)
 {
-	unsigned i, nsym;
-	unsigned char buff[SYMESZ];
-	SYMENT *ent;
-	FILHDR *hdr;
+	int type;
+	unsigned i;
+	FILHDR *hdr = obj->filhdr;;
 
-	hdr = obj->filhdr;
-	nsym = hdr->f_nsyms;
-	if (nsym > SIZE_MAX / sizeof(*ent))
+	if (fseek(obj->fp, off, SEEK_SET) == EOF)
 		return -1;
 
-	if ((ent = malloc(nsym * sizeof(*ent))) == NULL)
+	if (hdr->f_nsyms > SIZE_MAX / sizeof(Symbol *)) {
+		fprintf(stderr,
+		        "ld: %s: overflow in size of symbol redirection\n",
+		        obj->fname);
+		exit(EXIT_FAILURE);
+	}
+	obj->symbols = malloc(sizeof(Symbol *) * sizeof(Symbol *));
+	if (!obj->symbols)
 		outmem();
 
-	if (fseek(obj->fp, off, SEEK_SET) == EOF)
-		return -1;
+	hdr = obj->filhdr;
+	for (i = 0; i < hdr->f_nsyms; i++) {
+		Symbol *sym;
+		TUINT value;
+		SYMENT ent;
+		unsigned char buff[SYMESZ];
+		char *name;
 
-	for (i = 0; i < nsym; i++) {
 		if (fread(buff, SYMESZ, 1, obj->fp) != 1)
 			return -1;
-		getsym(buff, &ent[i]);
+		getsym(buff, &ent);
+		name = symname(obj, &ent);
+		type = typeof(obj, &ent);
+		sym = lookup(name);
+
+		switch (sym->type) {
+		case 'U':
+			sym->type = type;
+			sym->value = ent.n_value;
+			if (type == 'C')
+				sym->size = ent.n_value;
+			break;
+		case 'C':
+			switch (type) {
+			case 'U':
+			case 'C':
+				if (ent.n_value > sym->size)
+					sym->size = ent.n_value;
+				break;
+			default:
+				sym->type = type;
+				sym->value = ent.n_value;
+				break;
+			}
+			break;
+		default:
+			if (type != 'U') {
+				fprintf(stderr,
+				        "ld: %s: redifinition of symbol '%s'\n",
+				        obj->fname, sym->name);
+			}
+			break;
+		}
+
+		obj->symbols[i] = sym;
 	}
-	obj->enthdr = ent;
 
 	return 0;
 }
@@ -183,10 +331,10 @@
 
 	if (readstr(obj, stroff) < 0)
 		goto bad_file;
-	if (readsyms(obj, symoff) < 0)
-		goto bad_file;
 	if (readsects(obj, secoff) < 0)
 		goto bad_file;
+	if (readsyms(obj, symoff) < 0)
+		goto bad_file;
 	return;
 
 bad_file:
@@ -199,10 +347,17 @@
 pass1(char *fname, char *member, FILE *fp)
 {
 	Obj *obj;
+	SYMENT *ent;
+	FILHDR *hdr;
+	unsigned n, nsyms;
+	int islib = member != NULL;
 
 	obj = newobj(fname, member);
 	obj->fp = fp;
 	readobj(obj);
+
+	hdr = obj->filhdr;
+	nsyms = hdr->f_nsyms;
 }
 
 static void
@@ -232,6 +387,8 @@
 
 	switch (magic) {
 	case COFF_Z80MAGIC:
+		unpack = lunpack;
+		align = 2;
 		return 1;
 	default:
 		return 0;
--- a/ld/formats.c
+++ b/ld/formats.c
@@ -2,6 +2,7 @@
 
 #include <stdio.h>
 
+#include "../inc/scc.h"
 #include "ld.h"
 
 /* TODO: Autogenerate this file */
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -8,13 +8,19 @@
 	FILE *fp;
 	void *filhdr;
 	void *scnhdr;
-	void *enthdr;
+	Symbol **symbols;
 	char *strtbl;
+	size_t strsiz;
 	struct obj *next;
 };
 
 struct symbol {
 	char *name;
+	char type;
+	short flags;
+	long size;
+	TUINT base;
+	TUINT value;
 	struct symbol *hash;
 };
 
@@ -30,3 +36,14 @@
 
 /* main.c */
 extern void outmem(void);
+
+/*
+ * Definition of globals variables
+ */
+extern int pass;
+extern int sflag;
+extern int xflag;
+extern int Xflag;
+extern int rflag;
+extern int dflag;
+extern int gflag;
--- a/ld/main.c
+++ b/ld/main.c
@@ -19,6 +19,7 @@
 int Xflag;		/* discard locals starting with 'L' */
 int rflag;		/* preserve relocation bits */
 int dflag;		/* define common even with rflag */
+int gflag;              /* preserve debug symbols */
 
 void
 outmem(void)
--- a/ld/obj.c
+++ b/ld/obj.c
@@ -46,18 +46,25 @@
 	return obj;
 }
 
+static unsigned
+hash(char *s)
+{
+	unsigned h, c;
+
+	for (h = 0; c = *s; ++s)
+		h = h*33 ^ c;
+	return h & NR_SYM_HASH-1;
+}
+
 Symbol *
 lookup(char *name)
 {
-	unsigned h, c;
+	unsigned h;
 	char *s;
 	size_t len;
 	Symbol *sym;
 
-	for (h = 0; c = *name; ++s)
-		h = h*33 ^ c;
-	h &= NR_SYM_HASH-1;
-
+	h = hash(name);
 	for (sym = symtbl[h]; sym; sym = sym->hash) {
 		s = sym->name;
 		if (*name == *s && !strcmp(name, s))
@@ -69,11 +76,13 @@
 	s = malloc(len);
 	if (!sym || !s)
 		outmem();
+	memset(sym, 0, sizeof(*sym));
+	memcpy(s, name, len);
+
 	sym->hash = symtbl[h];
 	symtbl[h] = sym;
 	sym->name = s;
-	memset(sym, 0, sizeof(*sym));
-	memcpy(sym->name, name, len);
+	sym->type = 'U';
 
 	return sym;
 }
--- a/lib/c/calloc.c
+++ b/lib/c/calloc.c
@@ -1,5 +1,6 @@
 #include <stdlib.h>
 #include <string.h>
+#undef calloc
 
 void *
 calloc(size_t nmemb, size_t size)
--- a/lib/c/ctype.c
+++ b/lib/c/ctype.c
@@ -1,6 +1,5 @@
 #define __USE_MACROS
 #include <ctype.h>
-#undef ctype
 
 int __ctmp;
 
--- a/lib/c/fclose.c
+++ b/lib/c/fclose.c
@@ -1,5 +1,6 @@
 
 #include <stdio.h>
+#include "syscall.h"
 #undef fclose
 
 extern int _flsbuf(FILE *fp);
@@ -14,7 +15,7 @@
 		r = 0;
 		if (_flsbuf(fp) == EOF)
 			r = EOF;
-		if (close(fp->fd) < 0)
+		if (_close(fp->fd) < 0)
 			r = EOF;
 	}
 
--- a/lib/c/fputs.c
+++ b/lib/c/fputs.c
@@ -1,5 +1,6 @@
 
 #include <stdio.h>
+#undef fputs
 
 int
 fputs(const char * restrict bp, FILE * restrict fp)
--- a/lib/c/isascii.c
+++ b/lib/c/isascii.c
@@ -1,4 +1,3 @@
-#define __USE_MACROS
 #include <ctype.h>
 #undef isascii
 
--- a/lib/c/isblank.c
+++ b/lib/c/isblank.c
@@ -1,3 +1,6 @@
+
+#include <ctype.h>
+
 int
 isblank(int c)
 {
--- a/lib/c/puts.c
+++ b/lib/c/puts.c
@@ -1,5 +1,6 @@
 
 #include <stdio.h>
+#undef puts
 
 int
 puts(const char *str)
--- a/lib/c/realloc.c
+++ b/lib/c/realloc.c
@@ -2,6 +2,7 @@
 #include <string.h>
 
 #include "malloc.h"
+#undef realloc
 
 void *
 realloc(void *ptr, size_t nbytes)