symbol.c (8587B)
1 #include <assert.h> 2 #include <limits.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 7 #include <scc/cstd.h> 8 #include <scc/scc.h> 9 #include "cc1.h" 10 11 #define NR_SYM_HASH 64 12 #define NR_CPP_HASH 32 13 #define NR_LBL_HASH 16 14 15 struct keyword { 16 char *str; 17 unsigned char token, value; 18 }; 19 20 unsigned curctx; 21 static unsigned short counterid; 22 23 static Symbol *head, *labels; 24 static Symbol *htab[NR_SYM_HASH]; 25 static Symbol *htabcpp[NR_CPP_HASH]; 26 static Symbol *htablbl[NR_LBL_HASH]; 27 28 #ifndef NDEBUG 29 void 30 dumpstab(Symbol **tbl, char *msg) 31 { 32 Symbol **bp, *sym; 33 unsigned size; 34 35 fprintf(stderr, "Symbol Table dump at ctx=%u\n%s\n", curctx, msg); 36 if (tbl == htab) 37 size = NR_SYM_HASH; 38 else if (tbl == htabcpp) 39 size = NR_CPP_HASH; 40 else if (tbl == htablbl) 41 size = NR_LBL_HASH; 42 else 43 abort(); 44 45 for (bp = tbl; bp < &tbl[size]; ++bp) { 46 if (*bp == NULL) 47 continue; 48 fprintf(stderr, "%d", (int) (bp - htab)); 49 for (sym = *bp; sym; sym = sym->hash) 50 fprintf(stderr, "->[%d,%d:'%s'=%p]", 51 sym->ns, sym->ctx, sym->name, (void *) sym); 52 putc('\n', stderr); 53 } 54 fputs("head:", stderr); 55 for (sym = head; sym; sym = sym->next) { 56 fprintf(stderr, "->[%d,%d:'%s'=%p]", 57 sym->ns, sym->ctx, 58 (sym->name) ? sym->name : "", (void *) sym); 59 } 60 fputs("\nlabels:", stderr); 61 for (sym = labels; sym; sym = sym->next) { 62 fprintf(stderr, "->[%d,%d:'%s'=%p]", 63 sym->ns, sym->ctx, 64 (sym->name) ? sym->name : "", (void *) sym); 65 } 66 putc('\n', stderr); 67 } 68 #endif 69 70 static Symbol ** 71 hash(char *s, int ns) 72 { 73 unsigned h, size; 74 Symbol **tab; 75 76 h = genhash(s); 77 78 switch (ns) { 79 case NS_CPP: 80 tab = htabcpp; 81 size = NR_CPP_HASH-1; 82 break; 83 case NS_LABEL: 84 tab = htablbl; 85 size = NR_LBL_HASH-1; 86 break; 87 default: 88 tab = htab; 89 size = NR_SYM_HASH-1; 90 break; 91 } 92 return &tab[h & size]; 93 } 94 95 static void 96 unlinkhash(Symbol *sym) 97 { 98 Symbol **h; 99 100 if ((sym->flags & SDECLARED) == 0) 101 return; 102 h = hash(sym->name, sym->ns); 103 assert(sym->ns == NS_CPP || *h == sym); 104 while (*h != sym) 105 h = &(*h)->hash; 106 *h = sym->hash; 107 } 108 109 void 110 pushctx(void) 111 { 112 DBG("SYM: pushed context %d", curctx+1); 113 if (++curctx == NR_BLOCK+1) 114 error("too many nested blocks"); 115 } 116 117 void 118 killsym(Symbol *sym) 119 { 120 short f; 121 char *name; 122 123 if (!sym) 124 return; 125 f = sym->flags; 126 if (f & SSTRING) 127 free(sym->u.s); 128 if (sym->ns == NS_TAG) 129 sym->type->prop &= ~TDEFINED; 130 unlinkhash(sym); 131 if ((name = sym->name) != NULL) { 132 switch (sym->ns) { 133 case NS_LABEL: 134 if ((f & SDEFINED) == 0) 135 errorp("label '%s' is not defined", name); 136 case NS_IDEN: 137 if ((f & (SUSED|SGLOBAL|SDECLARED)) == SDECLARED) 138 warn("'%s' defined but not used", name); 139 break; 140 } 141 } 142 free(name); 143 free(sym); 144 } 145 146 void 147 popctx(void) 148 { 149 Symbol *next, *sym; 150 int ns, dangling = 0; 151 152 DBG("SYM: popped context %d", curctx); 153 /* 154 * we have to be careful before popping the current 155 * context, because since the parser is one token 156 * ahead it may already have read an identifier at 157 * this point, and yylval.sym is a pointer to 158 * the symbol associated to such token. If that 159 * symbol is from the context that we are popping 160 * then we are going to generate a dangling pointer. 161 * We can detect this situation and call again to 162 * lookup. 163 */ 164 if ((yytoken == IDEN || yytoken == TYPEIDEN) && 165 yylval.sym->ctx == curctx) { 166 ns = yylval.sym->ns; 167 dangling = 1; 168 } 169 170 for (sym = head; sym && sym->ctx == curctx; sym = next) { 171 /* 172 * Since we are unlinking them in the inverse order 173 * we do know that sym is always the head of the 174 * collision list 175 */ 176 next = sym->next; 177 killsym(sym); 178 } 179 head = sym; 180 181 if (--curctx == GLOBALCTX) { 182 for (sym = labels; sym; sym = next) { 183 next = sym->next; 184 killsym(sym); 185 } 186 labels = NULL; 187 } 188 189 if (dangling) { 190 yylval.sym = lookup(ns, yytext, ALLOC); 191 yytoken = yylval.sym->token; 192 } 193 } 194 195 unsigned 196 newid(void) 197 { 198 unsigned short id; 199 200 if (lexmode == CPPMODE) 201 return 0; 202 id = ++counterid; 203 if (id == 0) { 204 die("cc1: overflow in %s identifiers", 205 (curctx) ? "internal" : "external"); 206 } 207 return id; 208 } 209 210 Symbol * 211 newsym(int ns, char *name) 212 { 213 Symbol *sym; 214 215 sym = xmalloc(sizeof(*sym)); 216 if (name) 217 name = xstrdup(name); 218 sym->name = name; 219 sym->id = 0; 220 sym->hide = 0; 221 sym->ns = ns; 222 sym->ctx = curctx; 223 sym->token = IDEN; 224 sym->flags = 0; 225 sym->u.s = NULL; 226 sym->type = NULL; 227 sym->hash = NULL; 228 229 if (ns == NS_LABEL) { 230 sym->next = labels; 231 labels = sym; 232 } else if (ns != NS_CPP) { 233 sym->next = head; 234 head = sym; 235 } 236 return sym; 237 } 238 239 static Symbol * 240 linkhash(Symbol *sym) 241 { 242 Symbol **h; 243 244 h = hash(sym->name, sym->ns); 245 sym->hash = *h; 246 *h = sym; 247 248 if (sym->ns != NS_CPP) 249 sym->id = newid(); 250 sym->flags |= SDECLARED; 251 return sym; 252 } 253 254 Symbol * 255 newrstring(Rune *rs, size_t len) 256 { 257 Symbol *sym = newsym(NS_IDEN, NULL); 258 259 if (lexmode != CPPMODE) 260 sym->type = mktype(wchartype, ARY, len, NULL); 261 sym->id = newid(); 262 sym->flags |= SRSTRING | SCONSTANT | SPRIVATE; 263 sym->u.rs = xcalloc(len, sizeof(Rune)); 264 if (rs) 265 memcpy(sym->u.rs, rs, len * sizeof(Rune)); 266 267 return sym; 268 } 269 270 Symbol * 271 newstring(char *s, size_t len) 272 { 273 Symbol *sym = newsym(NS_IDEN, NULL); 274 275 if (lexmode != CPPMODE) 276 sym->type = mktype(chartype, ARY, len, NULL); 277 sym->id = newid(); 278 sym->flags |= SSTRING | SCONSTANT | SPRIVATE; 279 sym->u.s = xmalloc(len); 280 if (s) 281 memcpy(sym->u.s, s, len); 282 283 return sym; 284 } 285 286 Symbol * 287 newlabel(void) 288 { 289 Symbol *sym = newsym(NS_LABEL, NULL); 290 sym->id = newid(); 291 return sym; 292 } 293 294 Symbol * 295 lookup(int ns, char *name, int alloc) 296 { 297 Symbol *sym; 298 int sns, c; 299 char *t; 300 301 c = *name; 302 for (sym = *hash(name, ns); sym; sym = sym->hash) { 303 t = sym->name; 304 if (*t != c || strcmp(t, name)) 305 continue; 306 sns = sym->ns; 307 if (sns == ns) 308 return sym; 309 /* 310 * When a lookup is done in a namespace associated 311 * to a struct we also want symbols of NS_IDEN which 312 * are typedef, because in other case we cannot declare 313 * fields of such types. 314 */ 315 if (sns == NS_KEYWORD && ns != NS_MACROPAR && ns != NS_CPP || 316 (sym->flags & STYPEDEF) && ns >= NS_STRUCTS) { 317 return sym; 318 } 319 } 320 return (alloc == ALLOC) ? newsym(ns, name) : NULL; 321 } 322 323 Symbol * 324 install(int ns, Symbol *sym) 325 { 326 if (sym->flags & SDECLARED || sym->ctx != curctx) { 327 if (sym->ctx == curctx && ns == sym->ns) 328 return NULL; 329 sym = newsym(ns, sym->name); 330 } 331 return linkhash(sym); 332 } 333 334 void 335 keywords(struct keyword *key, int ns) 336 { 337 Symbol *sym; 338 339 for ( ; key->str; ++key) { 340 sym = linkhash(newsym(ns, key->str)); 341 sym->token = key->token; 342 sym->u.token = key->value; 343 } 344 } 345 346 void 347 builtins(struct builtin *built) 348 { 349 Symbol *sym; 350 struct builtin *bp; 351 352 for (bp = built; bp->str; ++bp) { 353 sym = linkhash(newsym(NS_KEYWORD, bp->str)); 354 sym->token = BUILTIN; 355 sym->u.fun = bp->fun; 356 } 357 } 358 359 void 360 isyms(void) 361 { 362 static struct keyword cppoper[] = { 363 {"defined", DEFINED, DEFINED}, 364 {NULL, 0, 0} 365 }; 366 static struct keyword cppkeys[] = { 367 {"define", DEFINE, DEFINE}, 368 {"include", INCLUDE, INCLUDE}, 369 {"line", LINE, LINE}, 370 {"ifdef", IFDEF, IFDEF}, 371 {"if", IF, IF}, 372 {"elif", ELIF, ELIF}, 373 {"else", ELSE, ELSE}, 374 {"ifndef", IFNDEF, IFNDEF}, 375 {"endif", ENDIF, ENDIF}, 376 {"undef", UNDEF, UNDEF}, 377 {"pragma", PRAGMA, PRAGMA}, 378 {"error", ERROR, ERROR}, 379 {NULL, 0, 0} 380 }; 381 static struct keyword lexkeys[] = { 382 {"auto", SCLASS, AUTO}, 383 {"break", BREAK, BREAK}, 384 {"_Bool", TYPE, BOOL}, 385 {"__builtin_va_list", TYPE, VA_LIST}, 386 {"case", CASE, CASE}, 387 {"char", TYPE, CHAR}, 388 {"const", TQUALIFIER, CONST}, 389 {"continue", CONTINUE, CONTINUE}, 390 {"default", DEFAULT, DEFAULT}, 391 {"do", DO, DO}, 392 {"double", TYPE, DOUBLE}, 393 {"else", ELSE, ELSE}, 394 {"enum", TYPE, ENUM}, 395 {"extern", SCLASS, EXTERN}, 396 {"float", TYPE, FLOAT}, 397 {"for", FOR, FOR}, 398 {"goto", GOTO, GOTO}, 399 {"if", IF, IF}, 400 {"inline", TQUALIFIER, INLINE}, 401 {"int", TYPE, INT}, 402 {"long", TYPE, LONG}, 403 {"register", SCLASS, REGISTER}, 404 {"restrict", TQUALIFIER, RESTRICT}, 405 {"return", RETURN, RETURN}, 406 {"short", TYPE, SHORT}, 407 {"signed", TYPE, SIGNED}, 408 {"sizeof", SIZEOF, SIZEOF}, 409 {"static", SCLASS, STATIC}, 410 {"struct", TYPE, STRUCT}, 411 {"switch", SWITCH, SWITCH}, 412 {"typedef", SCLASS, TYPEDEF}, 413 {"union", TYPE, UNION}, 414 {"unsigned", TYPE, UNSIGNED}, 415 {"void", TYPE, VOID}, 416 {"volatile", TQUALIFIER, VOLATILE}, 417 {"while", WHILE, WHILE}, 418 {NULL, 0, 0}, 419 }; 420 421 keywords(lexkeys, NS_KEYWORD); 422 keywords(cppkeys, NS_CPPCLAUSES); 423 keywords(cppoper, NS_CPP); 424 ibuilts(); 425 426 /* 427 * Remove all the predefined symbols from * the symbol list. It 428 * will make faster some operations. There is no problem of memory 429 * leakeage because this memory is not ever freed 430 */ 431 counterid = 0; 432 head = NULL; 433 }