scc

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

symbol.c (4596B)


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