scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

symbol.c (4550B)


      1 #include <ctype.h>
      2 #include <stdio.h>
      3 #include <stdint.h>
      4 #include <string.h>
      5 
      6 #include <scc/scc.h>
      7 #include "as.h"
      8 
      9 #define HASHSIZ 64
     10 #define NALLOC  10
     11 
     12 Section *cursec, *seclist;
     13 Section *sabs, *sbss, *sdata, *stext;
     14 Symbol *linesym, *symlist;
     15 int pass;
     16 
     17 static Symbol *hashtbl[HASHSIZ], *symlast;
     18 static Alloc *tmpalloc;
     19 
     20 
     21 #ifndef NDEBUG
     22 void
     23 dumpstab(char *msg)
     24 {
     25 	Symbol **bp, *sym;
     26 
     27 	fprintf(stderr, "%s\n", msg);
     28 	for (bp = hashtbl; bp < &hashtbl[HASHSIZ]; ++bp) {
     29 		if (*bp == NULL)
     30 			continue;
     31 
     32 		fprintf(stderr, "[%d]", (int) (bp - hashtbl));
     33 		for (sym = *bp; sym; sym = sym->hash) {
     34 			fprintf(stderr, " -> %s:%0X:%0X",
     35 			       sym->name.buf, sym->flags, sym->value);
     36 		}
     37 		putc('\n', stderr);
     38 	}
     39 }
     40 #endif
     41 
     42 Symbol *
     43 lookup(char *name)
     44 {
     45 	unsigned h;
     46 	Symbol *sym, **list;
     47 	int c, symtype;
     48 	char *t;
     49 
     50 	h = genhash(name) & HASHSIZ-1;
     51 
     52 	c = toupper(*name);
     53 	list = &hashtbl[h];
     54 	for (sym = *list; sym; sym = sym->hash) {
     55 		t = sym->name.buf;
     56 		if (c == toupper(*t) && !casecmp(t, name))
     57 			return sym;
     58 	}
     59 
     60 	sym = xmalloc(sizeof(*sym));
     61 	sym->name = newstring(name);
     62 	sym->flags = 0;
     63 	sym->size = sym->value = 0;
     64 	sym->section = cursec;
     65 	sym->hash = *list;
     66 	sym->next = NULL;
     67 
     68 	*list = sym;
     69 	if (symlast)
     70 		symlast->next = sym;
     71 	symlast = sym;
     72 	if (!symlist)
     73 		symlist = sym;
     74 
     75 	return sym;
     76 }
     77 
     78 Symbol *
     79 deflabel(char *name)
     80 {
     81 	static Symbol *cursym;
     82 	Symbol *sym;
     83 	char label[MAXSYM+1];
     84 
     85 	if (*name == '.') {
     86 		int r;
     87 
     88 		if (!cursym) {
     89 			error("local label '%s' without global label", name);
     90 			return NULL;
     91 		}
     92 		r = snprintf(label, sizeof(label),
     93 		             "%s%s",
     94 		             cursym->name.buf, name);
     95 		if (r == sizeof(label)) {
     96 			error("local label '%s' in '%s' produces too long symbol",
     97 			      name, cursym->name.buf);
     98 			return NULL;
     99 		}
    100 		name = label;
    101 	}
    102 
    103 	sym = lookup(name);
    104 	if (pass == 1 && (sym->flags & FDEF))
    105 		error("redefinition of label '%s'", name);
    106 	if (cursec->flags & SABS)
    107 		sym->flags |= FABS;
    108 	sym->flags |= FDEF;
    109 	sym->value = cursec->curpc;
    110 	sym->section = cursec;
    111 
    112 	if (*name != '.')
    113 		cursym = sym;
    114 	return sym;
    115 }
    116 
    117 int
    118 toobig(Node *np, int type)
    119 {
    120 	/* TODO */
    121 	return 0;
    122 }
    123 
    124 static void
    125 incpc(int siz)
    126 {
    127 	TUINT pc, curpc;
    128 
    129 	pc = cursec->pc;
    130 	curpc = cursec->curpc;
    131 
    132 	cursec->curpc += siz;
    133 	cursec->pc += siz;
    134 
    135 	if (pass == 2)
    136 		return;
    137 
    138 	if (cursec->pc > cursec->max)
    139 		cursec->max = cursec->pc;
    140 
    141 	if (pc > cursec->pc ||
    142 	    curpc > cursec->curpc ||
    143 	    cursec->curpc > maxaddr ||
    144 	    cursec->pc > maxaddr) {
    145 		die("as: address overflow in section '%s'");
    146 	}
    147 }
    148 
    149 static int
    150 secflags(char *attr)
    151 {
    152 	int c, flags;
    153 
    154 	if (!attr)
    155 		return 0;
    156 
    157 	for (flags = 0; c = *attr++; ) {
    158 		switch (c) {
    159 		case 'w':
    160 			flags |= SWRITE;
    161 			break;
    162 		case 'r':
    163 			flags |= SREAD;
    164 			break;
    165 		case 'x':
    166 			flags |= SEXEC;
    167 			break;
    168 		case 'f':
    169 			flags |= SFILE;
    170 			break;
    171 		case 'l':
    172 			flags |= SLOAD;
    173 			break;
    174 		case 'a':
    175 			flags |= SABS;
    176 			break;
    177 		}
    178 	}
    179 
    180 	return flags;
    181 }
    182 
    183 Section *
    184 setsec(char *name, char *attr)
    185 {
    186 	Section *sec;
    187 	Symbol *sym;
    188 
    189 	cursec = NULL;
    190 	sym = lookup(name);
    191 	if (sym->flags & ~FSECT)
    192 		error("invalid section name '%s'", name);
    193 
    194 	if ((sec = sym->section) == NULL) {
    195 		sec = xmalloc(sizeof(*sec));
    196 		sec->mem = NULL;
    197 		sec->sym = sym;
    198 		sec->base = sec->max = sec->pc = sec->curpc = 0;
    199 		sec->next = seclist;
    200 		sec->flags = 0;
    201 		sec->fill = 0;
    202 		sec->aligment = 0;
    203 		sec->next = seclist;
    204 		seclist = sec;
    205 
    206 		sym->section = sec;
    207 		sym->flags = FSECT;
    208 	}
    209 	sec->flags |= secflags(attr);
    210 
    211 	return cursec = sec;
    212 }
    213 
    214 void
    215 isecs(void)
    216 {
    217 	sabs = setsec(".abs", "rwx");
    218 	sbss = setsec(".bss", "rwf");
    219 	sdata = setsec(".data", "rw");
    220 	stext = setsec(".text", "rx");
    221 }
    222 
    223 void
    224 cleansecs(void)
    225 {
    226 	Section *sec;
    227 	TUINT siz;
    228 
    229 	for (sec = seclist; sec; sec = sec->next) {
    230 		sec->curpc = sec->pc = sec->base;
    231 		if (pass == 1 || sec->flags & SFILE)
    232 			continue;
    233 
    234 		siz = sec->max - sec->base;
    235 		if (siz > SIZE_MAX)
    236 			die("as: out of memory");
    237 		sec->mem = xmalloc(sec->max - sec->base);
    238 	}
    239 	cursec = stext;
    240 }
    241 
    242 void
    243 emit(char *bytes, int n)
    244 {
    245 	if (cursec->mem) {
    246 		size_t len = cursec->pc - cursec->base;
    247 		memcpy(&cursec->mem[len], bytes, n);
    248 	}
    249 	incpc(n);
    250 }
    251 
    252 Symbol *
    253 tmpsym(TUINT val)
    254 {
    255 	Symbol *sym;
    256 
    257 	if (!tmpalloc)
    258 		tmpalloc = alloc(sizeof(*sym), NALLOC);
    259 	sym = new(tmpalloc);
    260 	sym->value = val;
    261 	sym->section = NULL;
    262 	sym->flags = FABS;
    263 
    264 	return sym;
    265 }
    266 
    267 void
    268 killtmp(void)
    269 {
    270 	if (!tmpalloc)
    271 		return;
    272 	dealloc(tmpalloc);
    273 	tmpalloc = NULL;
    274 }
    275 
    276 String
    277 newstring(char *s)
    278 {
    279 	size_t len = strlen(s) + 1;
    280 	String str;
    281 
    282 	str.offset = 0;
    283 	str.buf = xmalloc(len);
    284 	memcpy(str.buf, s, len);
    285 	return str;
    286 }