scc

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

symbol.c (3024B)


      1 #include <assert.h>
      2 #include <errno.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 
      7 #include <scc/mach.h>
      8 #include <scc/scc.h>
      9 
     10 #include "ld.h"
     11 
     12 #define NR_SYMBOL 128
     13 
     14 /*
     15  * struct symtab has a Symbol as first field because
     16  * the code is going to cast from the symbols to the tab.
     17  */
     18 struct symtab {
     19 	Symbol sym;
     20 	Obj *where;
     21 	struct symtab *hash;
     22 	struct symtab *next, *prev;
     23 };
     24 
     25 static struct symtab *symtab[NR_SYMBOL];
     26 static struct symtab undef = {.next = &undef, .prev = &undef};
     27 static struct symtab def = {.next = &def, .prev = &def};
     28 static struct symtab common = {.next = &common, .prev = &common};
     29 
     30 static Symbol *
     31 unlinksym(Symbol *sym)
     32 {
     33 	struct symtab *sp = (struct symtab *) sym;
     34 
     35 	sp->next->prev = sp->prev;
     36 	sp->prev->next = sp->next;
     37 
     38 	return sym;
     39 }
     40 
     41 static Symbol *
     42 linksym(struct symtab *lst, Symbol *sym)
     43 {
     44 	struct symtab *sp = (struct symtab *) sym;
     45 
     46 	sp->next = lst;
     47 	sp->prev = lst->prev;
     48 	lst->prev->next = sp;
     49 	lst->prev = sp;
     50 
     51 	return sym;
     52 }
     53 
     54 int
     55 hasref(char *name)
     56 {
     57 	unsigned h;
     58 	struct symtab *sp;
     59 
     60 	h = genhash(name) % NR_SYMBOL;
     61 	for (sp = symtab[h]; sp; sp = sp->hash) {
     62 		if (!strcmp(name, sp->sym.name))
     63 			return sp->sym.type == 'U';
     64 	}
     65 	return 0;
     66 }
     67 
     68 Symbol *
     69 lookupsym(char *name)
     70 {
     71 	unsigned h;
     72 	size_t len;
     73 	char *s;
     74 	Symbol *sym;
     75 	struct symtab *sp;
     76 
     77 	h = genhash(name) % NR_SYMBOL;
     78 	for (sp = symtab[h]; sp; sp = sp->hash) {
     79 		if (!strcmp(name, sp->sym.name))
     80 			return &sp->sym;
     81 	}
     82 
     83 	len = strlen(name) + 1;
     84 	s = malloc(len);
     85 	sp = malloc(sizeof(*sp));
     86 	if (!s  || !sp) {
     87 		error(strerror(errno));
     88 		exit(EXIT_FAILURE);
     89 	}
     90 
     91 	sym = &sp->sym;
     92 	sym->name = memcpy(s, name, len);
     93 	sym->value = 0;
     94 	sym->size = 0;
     95 	sym->index = 0;
     96 	sym->type = 'U';
     97 	sp->where = NULL;
     98 	sp->hash = symtab[h];
     99 	symtab[h] = sp;
    100 
    101 	return linksym(&undef, sym);;
    102 }
    103 
    104 
    105 int
    106 moreundef(void)
    107 {
    108 	return undef.next != &undef;
    109 }
    110 
    111 void
    112 listundef(void)
    113 {
    114 	struct symtab *sp;
    115 
    116 	for (sp = undef.next; sp != &undef; sp = sp->next)
    117 		error("ld: symbol '%s' not defined", sp->sym.name);
    118 }
    119 
    120 Symbol *
    121 define(Symbol *osym, Obj *obj)
    122 {
    123 	struct symtab *lst;
    124 	Symbol *sym = lookupsym(osym->name);
    125 	struct symtab *sp = (struct symtab *) sym;
    126 
    127 	assert(osym->type != 'U');
    128 	sp->where = obj;
    129 
    130 	switch (sym->type) {
    131 	case 'U':
    132 		sym->value = osym->value;
    133 		sym->size = osym->size;
    134 		lst = (osym->type == 'C') ? &common : &def;
    135 		linksym(lst, unlinksym(sym));
    136 		break;
    137 	case 'C':
    138 		if (osym->type != 'C') {
    139 			sym->size = osym->size;
    140 			sym->value = osym->size;
    141 			linksym(&def, unlinksym(sym));
    142 		} else  if (sym->size < osym->size) {
    143 			sym->value = osym->value;
    144 			sym->size = osym->size;
    145 		}
    146 		break;
    147 	defaul:
    148 		error("%s: symbol redefined", sym->name);
    149 		break;
    150 	}
    151 
    152 	return sym;
    153 }
    154 
    155 #ifndef NDEBUG
    156 void
    157 debugsym(void)
    158 {
    159 	struct symtab **spp, *sp;
    160 	Symbol*sym;
    161 
    162 	fputs("Symbols:\n", stderr);
    163 	for (spp = symtab; spp < &symtab[NR_SYMBOL]; spp++) {
    164 		for (sp = *spp; sp; sp = sp->hash) {
    165 			sym = &sp->sym;
    166 			fprintf(stderr,
    167 			        "sym: %s (%#llx)\n",
    168 			        sym->name,
    169 			        sym->value);
    170 		}
    171 	}
    172 }
    173 #endif