symbol.c (8616B)
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 * TODO: Remove this trick 315 */ 316 if (sns == NS_KEYWORD && ns != NS_MACROPAR && ns != NS_CPP || 317 (sym->flags & STYPEDEF) && ns >= NS_STRUCTS) { 318 return sym; 319 } 320 } 321 return (alloc == ALLOC) ? newsym(ns, name) : NULL; 322 } 323 324 Symbol * 325 install(int ns, Symbol *sym) 326 { 327 if (sym->flags & SDECLARED || sym->ctx != curctx) { 328 if (sym->ctx == curctx && ns == sym->ns) 329 return NULL; 330 sym = newsym(ns, sym->name); 331 } 332 return linkhash(sym); 333 } 334 335 void 336 keywords(struct keyword *key, int ns) 337 { 338 Symbol *sym; 339 340 for ( ; key->str; ++key) { 341 sym = linkhash(newsym(ns, key->str)); 342 sym->token = key->token; 343 sym->u.token = key->value; 344 } 345 } 346 347 void 348 builtins(struct builtin *built) 349 { 350 Symbol *sym; 351 struct builtin *bp; 352 353 for (bp = built; bp->str; ++bp) { 354 sym = linkhash(newsym(NS_KEYWORD, bp->str)); 355 sym->token = BUILTIN; 356 sym->u.fun = bp->fun; 357 } 358 } 359 360 void 361 isyms(void) 362 { 363 static struct keyword cppoper[] = { 364 {"defined", DEFINED, DEFINED}, 365 {NULL, 0, 0} 366 }; 367 static struct keyword cppkeys[] = { 368 {"define", DEFINE, DEFINE}, 369 {"include", INCLUDE, INCLUDE}, 370 {"line", LINE, LINE}, 371 {"ifdef", IFDEF, IFDEF}, 372 {"if", IF, IF}, 373 {"elif", ELIF, ELIF}, 374 {"else", ELSE, ELSE}, 375 {"ifndef", IFNDEF, IFNDEF}, 376 {"endif", ENDIF, ENDIF}, 377 {"undef", UNDEF, UNDEF}, 378 {"pragma", PRAGMA, PRAGMA}, 379 {"error", ERROR, ERROR}, 380 {NULL, 0, 0} 381 }; 382 static struct keyword lexkeys[] = { 383 {"auto", SCLASS, AUTO}, 384 {"break", BREAK, BREAK}, 385 {"_Bool", TYPE, BOOL}, 386 {"__builtin_va_list", TYPE, VA_LIST}, 387 {"case", CASE, CASE}, 388 {"char", TYPE, CHAR}, 389 {"const", TQUALIFIER, CONST}, 390 {"continue", CONTINUE, CONTINUE}, 391 {"default", DEFAULT, DEFAULT}, 392 {"do", DO, DO}, 393 {"double", TYPE, DOUBLE}, 394 {"else", ELSE, ELSE}, 395 {"enum", TYPE, ENUM}, 396 {"extern", SCLASS, EXTERN}, 397 {"float", TYPE, FLOAT}, 398 {"for", FOR, FOR}, 399 {"goto", GOTO, GOTO}, 400 {"if", IF, IF}, 401 {"inline", TQUALIFIER, INLINE}, 402 {"int", TYPE, INT}, 403 {"long", TYPE, LONG}, 404 {"register", SCLASS, REGISTER}, 405 {"restrict", TQUALIFIER, RESTRICT}, 406 {"return", RETURN, RETURN}, 407 {"short", TYPE, SHORT}, 408 {"signed", TYPE, SIGNED}, 409 {"sizeof", SIZEOF, SIZEOF}, 410 {"static", SCLASS, STATIC}, 411 {"struct", TYPE, STRUCT}, 412 {"switch", SWITCH, SWITCH}, 413 {"typedef", SCLASS, TYPEDEF}, 414 {"union", TYPE, UNION}, 415 {"unsigned", TYPE, UNSIGNED}, 416 {"void", TYPE, VOID}, 417 {"volatile", TQUALIFIER, VOLATILE}, 418 {"while", WHILE, WHILE}, 419 {NULL, 0, 0}, 420 }; 421 422 keywords(lexkeys, NS_KEYWORD); 423 keywords(cppkeys, NS_CPPCLAUSES); 424 keywords(cppoper, NS_CPP); 425 ibuilts(); 426 427 /* 428 * Remove all the predefined symbols from * the symbol list. It 429 * will make faster some operations. There is no problem of memory 430 * leakeage because this memory is not ever freed 431 */ 432 counterid = 0; 433 head = NULL; 434 }