scc

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

symbol.c (4865B)


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