1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* symtab.c */ |
4 | /* */ |
5 | /* Symbol table management for the cc65 C compiler */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 2000-2013, Ullrich von Bassewitz */ |
10 | /* Roemerstrasse 52 */ |
11 | /* D-70794 Filderstadt */ |
12 | /* EMail: uz@cc65.org */ |
13 | /* */ |
14 | /* */ |
15 | /* This software is provided 'as-is', without any expressed or implied */ |
16 | /* warranty. In no event will the authors be held liable for any damages */ |
17 | /* arising from the use of this software. */ |
18 | /* */ |
19 | /* Permission is granted to anyone to use this software for any purpose, */ |
20 | /* including commercial applications, and to alter it and redistribute it */ |
21 | /* freely, subject to the following restrictions: */ |
22 | /* */ |
23 | /* 1. The origin of this software must not be misrepresented; you must not */ |
24 | /* claim that you wrote the original software. If you use this software */ |
25 | /* in a product, an acknowledgment in the product documentation would be */ |
26 | /* appreciated but is not required. */ |
27 | /* 2. Altered source versions must be plainly marked as such, and must not */ |
28 | /* be misrepresented as being the original software. */ |
29 | /* 3. This notice may not be removed or altered from any source */ |
30 | /* distribution. */ |
31 | /* */ |
32 | /*****************************************************************************/ |
33 | |
34 | |
35 | |
36 | #include <stdio.h> |
37 | #include <stdlib.h> |
38 | #include <stdarg.h> |
39 | #include <string.h> |
40 | |
41 | /* common */ |
42 | #include "check.h" |
43 | #include "debugflag.h" |
44 | #include "hashfunc.h" |
45 | #include "xmalloc.h" |
46 | |
47 | /* cc65 */ |
48 | #include "asmcode.h" |
49 | #include "asmlabel.h" |
50 | #include "codegen.h" |
51 | #include "datatype.h" |
52 | #include "declare.h" |
53 | #include "error.h" |
54 | #include "funcdesc.h" |
55 | #include "global.h" |
56 | #include "stackptr.h" |
57 | #include "symentry.h" |
58 | #include "typecmp.h" |
59 | #include "symtab.h" |
60 | #include "function.h" |
61 | #include "input.h" |
62 | |
63 | |
64 | |
65 | /*****************************************************************************/ |
66 | /* Data */ |
67 | /*****************************************************************************/ |
68 | |
69 | |
70 | |
71 | /* An empty symbol table */ |
72 | SymTable EmptySymTab = { |
73 | 0, /* PrevTab */ |
74 | 0, /* SymHead */ |
75 | 0, /* SymTail */ |
76 | 0, /* SymCount */ |
77 | 1, /* Size */ |
78 | { 0 } /* Tab[1] */ |
79 | }; |
80 | |
81 | /* Symbol table sizes */ |
82 | #define SYMTAB_SIZE_GLOBAL 211U |
83 | #define SYMTAB_SIZE_FUNCTION 29U |
84 | #define SYMTAB_SIZE_BLOCK 13U |
85 | #define SYMTAB_SIZE_STRUCT 19U |
86 | #define SYMTAB_SIZE_LABEL 7U |
87 | |
88 | /* The current and root symbol tables */ |
89 | static unsigned LexicalLevel = 0; /* For safety checks */ |
90 | static SymTable* SymTab0 = 0; |
91 | static SymTable* SymTab = 0; |
92 | static SymTable* TagTab0 = 0; |
93 | static SymTable* TagTab = 0; |
94 | static SymTable* LabelTab = 0; |
95 | static SymTable* SPAdjustTab = 0; |
96 | |
97 | |
98 | /*****************************************************************************/ |
99 | /* struct SymTable */ |
100 | /*****************************************************************************/ |
101 | |
102 | |
103 | |
104 | static SymTable* NewSymTable (unsigned Size) |
105 | /* Create and return a symbol table for the given lexical level */ |
106 | { |
107 | unsigned I; |
108 | |
109 | /* Allocate memory for the table */ |
110 | SymTable* S = xmalloc (sizeof (SymTable) + (Size-1) * sizeof (SymEntry*)); |
111 | |
112 | /* Initialize the symbol table structure */ |
113 | S->PrevTab = 0; |
114 | S->SymHead = 0; |
115 | S->SymTail = 0; |
116 | S->SymCount = 0; |
117 | S->Size = Size; |
118 | for (I = 0; I < Size; ++I) { |
119 | S->Tab[I] = 0; |
120 | } |
121 | |
122 | /* Return the symbol table */ |
123 | return S; |
124 | } |
125 | |
126 | |
127 | |
128 | static void FreeSymTable (SymTable* S) |
129 | /* Free the given symbo table including all symbols */ |
130 | { |
131 | /* Free all symbols */ |
132 | SymEntry* Sym = S->SymHead; |
133 | while (Sym) { |
134 | SymEntry* NextSym = Sym->NextSym; |
135 | FreeSymEntry (Sym); |
136 | Sym = NextSym; |
137 | } |
138 | |
139 | /* Free the table itself */ |
140 | xfree (S); |
141 | } |
142 | |
143 | |
144 | |
145 | /*****************************************************************************/ |
146 | /* Check symbols in a table */ |
147 | /*****************************************************************************/ |
148 | |
149 | |
150 | |
151 | static void CheckSymTable (SymTable* Tab) |
152 | /* Check a symbol table for open references, unused symbols ... */ |
153 | { |
154 | SymEntry* Entry = Tab->SymHead; |
155 | while (Entry) { |
156 | |
157 | /* Get the storage flags for tne entry */ |
158 | unsigned Flags = Entry->Flags; |
159 | |
160 | /* Ignore typedef entries */ |
161 | if (!SymIsTypeDef (Entry)) { |
162 | |
163 | /* Check if the symbol is one with storage, and it if it was |
164 | ** defined but not used. |
165 | */ |
166 | if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) { |
167 | if (SymIsDef (Entry) && !SymIsRef (Entry) && |
168 | !SymHasAttr (Entry, atUnused)) { |
169 | if (Flags & SC_PARAM) { |
170 | if (IS_Get (&WarnUnusedParam)) { |
171 | Warning ("Parameter '%s' is never used" , Entry->Name); |
172 | } |
173 | } else { |
174 | if (IS_Get (&WarnUnusedVar)) { |
175 | Warning ("'%s' is defined but never used" , Entry->Name); |
176 | } |
177 | } |
178 | } |
179 | } |
180 | |
181 | /* If the entry is a label, check if it was defined in the function */ |
182 | if (Flags & SC_LABEL) { |
183 | if (!SymIsDef (Entry)) { |
184 | /* Undefined label */ |
185 | Error ("Undefined label: '%s'" , Entry->Name); |
186 | } else if (!SymIsRef (Entry)) { |
187 | /* Defined but not used */ |
188 | if (IS_Get (&WarnUnusedLabel)) { |
189 | Warning ("'%s' is defined but never used" , Entry->Name); |
190 | } |
191 | } |
192 | } |
193 | |
194 | } |
195 | |
196 | /* Next entry */ |
197 | Entry = Entry->NextSym; |
198 | } |
199 | } |
200 | |
201 | |
202 | |
203 | /*****************************************************************************/ |
204 | /* Handling of lexical levels */ |
205 | /*****************************************************************************/ |
206 | |
207 | |
208 | |
209 | unsigned GetLexicalLevel (void) |
210 | /* Return the current lexical level */ |
211 | { |
212 | return LexicalLevel; |
213 | } |
214 | |
215 | |
216 | |
217 | void EnterGlobalLevel (void) |
218 | /* Enter the program global lexical level */ |
219 | { |
220 | /* Safety */ |
221 | PRECONDITION (++LexicalLevel == LEX_LEVEL_GLOBAL); |
222 | |
223 | /* Create and assign the symbol table */ |
224 | SymTab0 = SymTab = NewSymTable (SYMTAB_SIZE_GLOBAL); |
225 | |
226 | /* Create and assign the tag table */ |
227 | TagTab0 = TagTab = NewSymTable (SYMTAB_SIZE_GLOBAL); |
228 | |
229 | /* Create and assign the table of SP adjustment symbols */ |
230 | SPAdjustTab = NewSymTable (SYMTAB_SIZE_GLOBAL); |
231 | } |
232 | |
233 | |
234 | |
235 | void LeaveGlobalLevel (void) |
236 | /* Leave the program global lexical level */ |
237 | { |
238 | /* Safety */ |
239 | PRECONDITION (LexicalLevel-- == LEX_LEVEL_GLOBAL); |
240 | |
241 | /* Check the tables */ |
242 | CheckSymTable (SymTab0); |
243 | |
244 | /* Dump the tables if requested */ |
245 | if (Debug) { |
246 | PrintSymTable (SymTab0, stdout, "Global symbol table" ); |
247 | PrintSymTable (TagTab0, stdout, "Global tag table" ); |
248 | } |
249 | |
250 | /* Don't delete the symbol and struct tables! */ |
251 | SymTab = 0; |
252 | TagTab = 0; |
253 | } |
254 | |
255 | |
256 | |
257 | void EnterFunctionLevel (void) |
258 | /* Enter function lexical level */ |
259 | { |
260 | SymTable* S; |
261 | |
262 | /* New lexical level */ |
263 | ++LexicalLevel; |
264 | |
265 | /* Get a new symbol table and make it current */ |
266 | S = NewSymTable (SYMTAB_SIZE_FUNCTION); |
267 | S->PrevTab = SymTab; |
268 | SymTab = S; |
269 | |
270 | /* Get a new tag table and make it current */ |
271 | S = NewSymTable (SYMTAB_SIZE_FUNCTION); |
272 | S->PrevTab = TagTab; |
273 | TagTab = S; |
274 | |
275 | /* Create and assign a new label table */ |
276 | S = NewSymTable (SYMTAB_SIZE_LABEL); |
277 | S->PrevTab = LabelTab; |
278 | LabelTab = S; |
279 | } |
280 | |
281 | |
282 | |
283 | void RememberFunctionLevel (struct FuncDesc* F) |
284 | /* Remember the symbol tables for the level and leave the level without checks */ |
285 | { |
286 | /* Leave the lexical level */ |
287 | --LexicalLevel; |
288 | |
289 | /* Remember the tables */ |
290 | F->SymTab = SymTab; |
291 | F->TagTab = TagTab; |
292 | |
293 | /* Don't delete the tables */ |
294 | SymTab = SymTab->PrevTab; |
295 | TagTab = TagTab->PrevTab; |
296 | LabelTab = LabelTab->PrevTab; |
297 | } |
298 | |
299 | |
300 | |
301 | void ReenterFunctionLevel (struct FuncDesc* F) |
302 | /* Reenter the function lexical level using the existing tables from F */ |
303 | { |
304 | /* New lexical level */ |
305 | ++LexicalLevel; |
306 | |
307 | /* Make the tables current again */ |
308 | F->SymTab->PrevTab = SymTab; |
309 | SymTab = F->SymTab; |
310 | |
311 | F->TagTab->PrevTab = TagTab; |
312 | TagTab = F->TagTab; |
313 | |
314 | /* Create and assign a new label table */ |
315 | LabelTab = NewSymTable (SYMTAB_SIZE_LABEL); |
316 | } |
317 | |
318 | |
319 | |
320 | void LeaveFunctionLevel (void) |
321 | /* Leave function lexical level */ |
322 | { |
323 | /* Leave the lexical level */ |
324 | --LexicalLevel; |
325 | |
326 | /* Check the tables */ |
327 | CheckSymTable (SymTab); |
328 | CheckSymTable (LabelTab); |
329 | |
330 | /* Drop the label table if it is empty */ |
331 | if (LabelTab->SymCount == 0) { |
332 | FreeSymTable (LabelTab); |
333 | } |
334 | |
335 | /* Don't delete the tables */ |
336 | SymTab = SymTab->PrevTab; |
337 | TagTab = TagTab->PrevTab; |
338 | LabelTab = 0; |
339 | } |
340 | |
341 | |
342 | |
343 | void EnterBlockLevel (void) |
344 | /* Enter a nested block in a function */ |
345 | { |
346 | SymTable* S; |
347 | |
348 | /* New lexical level */ |
349 | ++LexicalLevel; |
350 | |
351 | /* Get a new symbol table and make it current */ |
352 | S = NewSymTable (SYMTAB_SIZE_BLOCK); |
353 | S->PrevTab = SymTab; |
354 | SymTab = S; |
355 | |
356 | /* Get a new tag table and make it current */ |
357 | S = NewSymTable (SYMTAB_SIZE_BLOCK); |
358 | S->PrevTab = TagTab; |
359 | TagTab = S; |
360 | } |
361 | |
362 | |
363 | |
364 | void LeaveBlockLevel (void) |
365 | /* Leave a nested block in a function */ |
366 | { |
367 | /* Leave the lexical level */ |
368 | --LexicalLevel; |
369 | |
370 | /* Check the tables */ |
371 | CheckSymTable (SymTab); |
372 | |
373 | /* Don't delete the tables */ |
374 | SymTab = SymTab->PrevTab; |
375 | TagTab = TagTab->PrevTab; |
376 | } |
377 | |
378 | |
379 | |
380 | void EnterStructLevel (void) |
381 | /* Enter a nested block for a struct definition */ |
382 | { |
383 | SymTable* S; |
384 | |
385 | /* Get a new symbol table and make it current. Note: Structs and enums |
386 | ** nested in struct scope are NOT local to the struct but visible in the |
387 | ** outside scope. So we will NOT create a new struct or enum table. |
388 | */ |
389 | S = NewSymTable (SYMTAB_SIZE_BLOCK); |
390 | S->PrevTab = SymTab; |
391 | SymTab = S; |
392 | } |
393 | |
394 | |
395 | |
396 | void LeaveStructLevel (void) |
397 | /* Leave a nested block for a struct definition */ |
398 | { |
399 | /* Don't delete the table */ |
400 | SymTab = SymTab->PrevTab; |
401 | } |
402 | |
403 | |
404 | |
405 | /*****************************************************************************/ |
406 | /* Find functions */ |
407 | /*****************************************************************************/ |
408 | |
409 | |
410 | |
411 | static SymEntry* FindSymInTable (const SymTable* T, const char* Name, unsigned Hash) |
412 | /* Search for an entry in one table */ |
413 | { |
414 | /* Get the start of the hash chain */ |
415 | SymEntry* E = T->Tab [Hash % T->Size]; |
416 | while (E) { |
417 | /* Compare the name */ |
418 | if (strcmp (E->Name, Name) == 0) { |
419 | /* Found */ |
420 | return E; |
421 | } |
422 | /* Not found, next entry in hash chain */ |
423 | E = E->NextHash; |
424 | } |
425 | |
426 | /* Not found */ |
427 | return 0; |
428 | } |
429 | |
430 | |
431 | |
432 | static SymEntry* FindSymInTree (const SymTable* Tab, const char* Name) |
433 | /* Find the symbol with the given name in the table tree that starts with T */ |
434 | { |
435 | /* Get the hash over the name */ |
436 | unsigned Hash = HashStr (Name); |
437 | |
438 | /* Check all symbol tables for the symbol */ |
439 | while (Tab) { |
440 | /* Try to find the symbol in this table */ |
441 | SymEntry* E = FindSymInTable (Tab, Name, Hash); |
442 | |
443 | /* Bail out if we found it */ |
444 | if (E != 0) { |
445 | return E; |
446 | } |
447 | |
448 | /* Repeat the search in the next higher lexical level */ |
449 | Tab = Tab->PrevTab; |
450 | } |
451 | |
452 | /* Not found */ |
453 | return 0; |
454 | } |
455 | |
456 | |
457 | |
458 | SymEntry* FindSym (const char* Name) |
459 | /* Find the symbol with the given name */ |
460 | { |
461 | return FindSymInTree (SymTab, Name); |
462 | } |
463 | |
464 | |
465 | |
466 | SymEntry* FindGlobalSym (const char* Name) |
467 | /* Find the symbol with the given name in the global symbol table only */ |
468 | { |
469 | return FindSymInTable (SymTab0, Name, HashStr (Name)); |
470 | } |
471 | |
472 | |
473 | |
474 | SymEntry* FindLocalSym (const char* Name) |
475 | /* Find the symbol with the given name in the current symbol table only */ |
476 | { |
477 | return FindSymInTable (SymTab, Name, HashStr (Name)); |
478 | } |
479 | |
480 | |
481 | |
482 | SymEntry* FindTagSym (const char* Name) |
483 | /* Find the symbol with the given name in the tag table */ |
484 | { |
485 | return FindSymInTree (TagTab, Name); |
486 | } |
487 | |
488 | |
489 | |
490 | SymEntry* FindStructField (const Type* T, const char* Name) |
491 | /* Find a struct field in the fields list */ |
492 | { |
493 | SymEntry* Field = 0; |
494 | |
495 | /* The given type may actually be a pointer to struct */ |
496 | if (IsTypePtr (T)) { |
497 | ++T; |
498 | } |
499 | |
500 | /* Non-structs do not have any struct fields... */ |
501 | if (IsClassStruct (T)) { |
502 | |
503 | /* Get a pointer to the struct/union type */ |
504 | const SymEntry* Struct = GetSymEntry (T); |
505 | CHECK (Struct != 0); |
506 | |
507 | /* Now search in the struct symbol table. Beware: The table may not |
508 | ** exist. |
509 | */ |
510 | if (Struct->V.S.SymTab) { |
511 | Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name)); |
512 | } |
513 | } |
514 | |
515 | return Field; |
516 | } |
517 | |
518 | |
519 | |
520 | /*****************************************************************************/ |
521 | /* Add stuff to the symbol table */ |
522 | /*****************************************************************************/ |
523 | |
524 | |
525 | |
526 | static void AddSymEntry (SymTable* T, SymEntry* S) |
527 | /* Add a symbol to a symbol table */ |
528 | { |
529 | /* Get the hash value for the name */ |
530 | unsigned Hash = HashStr (S->Name) % T->Size; |
531 | |
532 | /* Insert the symbol into the list of all symbols in this level */ |
533 | if (T->SymTail) { |
534 | T->SymTail->NextSym = S; |
535 | } |
536 | S->PrevSym = T->SymTail; |
537 | T->SymTail = S; |
538 | if (T->SymHead == 0) { |
539 | /* First symbol */ |
540 | T->SymHead = S; |
541 | } |
542 | ++T->SymCount; |
543 | |
544 | /* Insert the symbol into the hash chain */ |
545 | S->NextHash = T->Tab[Hash]; |
546 | T->Tab[Hash] = S; |
547 | |
548 | /* Tell the symbol in which table it is */ |
549 | S->Owner = T; |
550 | } |
551 | |
552 | |
553 | |
554 | SymEntry* AddStructSym (const char* Name, unsigned Type, unsigned Size, SymTable* Tab) |
555 | /* Add a struct/union entry and return it */ |
556 | { |
557 | SymEntry* Entry; |
558 | |
559 | /* Type must be struct or union */ |
560 | PRECONDITION (Type == SC_STRUCT || Type == SC_UNION); |
561 | |
562 | /* Do we have an entry with this name already? */ |
563 | Entry = FindSymInTable (TagTab, Name, HashStr (Name)); |
564 | if (Entry) { |
565 | |
566 | /* We do have an entry. This may be a forward, so check it. */ |
567 | if ((Entry->Flags & SC_TYPEMASK) != Type) { |
568 | /* Existing symbol is not a struct */ |
569 | Error ("Symbol '%s' is already different kind" , Name); |
570 | } else if (Size > 0 && Entry->V.S.Size > 0) { |
571 | /* Both structs are definitions. */ |
572 | Error ("Multiple definition for '%s'" , Name); |
573 | } else { |
574 | /* Define the struct size if it is given */ |
575 | if (Size > 0) { |
576 | Entry->V.S.SymTab = Tab; |
577 | Entry->V.S.Size = Size; |
578 | } |
579 | } |
580 | |
581 | } else { |
582 | |
583 | /* Create a new entry */ |
584 | Entry = NewSymEntry (Name, Type); |
585 | |
586 | /* Set the struct data */ |
587 | Entry->V.S.SymTab = Tab; |
588 | Entry->V.S.Size = Size; |
589 | |
590 | /* Add it to the current table */ |
591 | AddSymEntry (TagTab, Entry); |
592 | } |
593 | |
594 | /* Return the entry */ |
595 | return Entry; |
596 | } |
597 | |
598 | |
599 | |
600 | SymEntry* AddBitField (const char* Name, unsigned Offs, unsigned BitOffs, unsigned Width) |
601 | /* Add a bit field to the local symbol table and return the symbol entry */ |
602 | { |
603 | /* Do we have an entry with this name already? */ |
604 | SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name)); |
605 | if (Entry) { |
606 | |
607 | /* We have a symbol with this name already */ |
608 | Error ("Multiple definition for '%s'" , Name); |
609 | |
610 | } else { |
611 | |
612 | /* Create a new entry */ |
613 | Entry = NewSymEntry (Name, SC_BITFIELD); |
614 | |
615 | /* Set the symbol attributes. Bit-fields are always of type unsigned */ |
616 | Entry->Type = type_uint; |
617 | Entry->V.B.Offs = Offs; |
618 | Entry->V.B.BitOffs = BitOffs; |
619 | Entry->V.B.BitWidth = Width; |
620 | |
621 | /* Add the entry to the symbol table */ |
622 | AddSymEntry (SymTab, Entry); |
623 | |
624 | } |
625 | |
626 | /* Return the entry */ |
627 | return Entry; |
628 | } |
629 | |
630 | |
631 | |
632 | SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val) |
633 | /* Add an constant symbol to the symbol table and return it */ |
634 | { |
635 | /* Enums must be inserted in the global symbol table */ |
636 | SymTable* Tab = ((Flags & SC_ENUM) == SC_ENUM)? SymTab0 : SymTab; |
637 | |
638 | /* Do we have an entry with this name already? */ |
639 | SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name)); |
640 | if (Entry) { |
641 | if ((Entry->Flags & SC_CONST) != SC_CONST) { |
642 | Error ("Symbol '%s' is already different kind" , Name); |
643 | } else { |
644 | Error ("Multiple definition for '%s'" , Name); |
645 | } |
646 | return Entry; |
647 | } |
648 | |
649 | /* Create a new entry */ |
650 | Entry = NewSymEntry (Name, Flags); |
651 | |
652 | /* Enum values are ints */ |
653 | Entry->Type = TypeDup (T); |
654 | |
655 | /* Set the enum data */ |
656 | Entry->V.ConstVal = Val; |
657 | |
658 | /* Add the entry to the symbol table */ |
659 | AddSymEntry (Tab, Entry); |
660 | |
661 | /* Return the entry */ |
662 | return Entry; |
663 | } |
664 | |
665 | |
666 | DefOrRef* AddDefOrRef (SymEntry* E, unsigned Flags) |
667 | /* Add definition or reference to the SymEntry and preserve its attributes */ |
668 | { |
669 | DefOrRef *DOR; |
670 | |
671 | DOR = xmalloc (sizeof (DefOrRef)); |
672 | CollAppend (E->V.L.DefsOrRefs, DOR); |
673 | DOR->Line = GetCurrentLine (); |
674 | DOR->LocalsBlockId = (long)CollLast (&CurrentFunc->LocalsBlockStack); |
675 | DOR->Flags = Flags; |
676 | DOR->StackPtr = StackPtr; |
677 | DOR->Depth = CollCount (&CurrentFunc->LocalsBlockStack); |
678 | DOR->LateSP_Label = GetLocalLabel (); |
679 | |
680 | return DOR; |
681 | } |
682 | |
683 | unsigned short FindSPAdjustment (const char* Name) |
684 | /* Search for an entry in the table of SP adjustments */ |
685 | { |
686 | SymEntry* Entry = FindSymInTable (SPAdjustTab, Name, HashStr (Name)); |
687 | |
688 | if (!Entry) { |
689 | Internal ("No SP adjustment label entry found" ); |
690 | } |
691 | |
692 | return Entry->V.SPAdjustment; |
693 | } |
694 | |
695 | SymEntry* AddLabelSym (const char* Name, unsigned Flags) |
696 | /* Add a goto label to the label table */ |
697 | { |
698 | unsigned i; |
699 | DefOrRef *DOR, *NewDOR; |
700 | /* We juggle it so much that a shortcut will help with clarity */ |
701 | Collection *AIC = &CurrentFunc->LocalsBlockStack; |
702 | |
703 | /* Do we have an entry with this name already? */ |
704 | SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name)); |
705 | if (Entry) { |
706 | |
707 | if (SymIsDef (Entry) && (Flags & SC_DEF) != 0) { |
708 | /* Trying to define the label more than once */ |
709 | Error ("Label '%s' is defined more than once" , Name); |
710 | } |
711 | |
712 | NewDOR = AddDefOrRef (Entry, Flags); |
713 | |
714 | /* Walk through all occurrences of the label so far and evaluate |
715 | ** their relationship with the one passed to the function. |
716 | */ |
717 | for (i = 0; i < CollCount (Entry->V.L.DefsOrRefs); i++) { |
718 | DOR = CollAt (Entry->V.L.DefsOrRefs, i); |
719 | |
720 | if ((DOR->Flags & SC_DEF) && (Flags & SC_REF) && (Flags & (SC_GOTO|SC_GOTO_IND))) { |
721 | /* We're processing a goto and here is its destination label. |
722 | ** This means the difference between SP values is already known, |
723 | ** so we simply emit the SP adjustment code. |
724 | */ |
725 | if (StackPtr != DOR->StackPtr) { |
726 | g_space (StackPtr - DOR->StackPtr); |
727 | } |
728 | |
729 | /* Are we jumping into a block with initalization of an object that |
730 | ** has automatic storage duration? Let's emit a warning. |
731 | */ |
732 | if ((long)CollLast (AIC) != DOR->LocalsBlockId && |
733 | (CollCount (AIC) < DOR->Depth || |
734 | (long)CollAt (AIC, DOR->Depth - 1) != DOR->LocalsBlockId)) { |
735 | Warning ("Goto at line %d to label %s jumps into a block with " |
736 | "initialization of an object that has automatic storage duration" , |
737 | GetCurrentLine (), Name); |
738 | } |
739 | } |
740 | |
741 | |
742 | if ((DOR->Flags & SC_REF) && (DOR->Flags & (SC_GOTO|SC_GOTO_IND)) && (Flags & SC_DEF)) { |
743 | /* We're processing a label, let's update all gotos encountered |
744 | ** so far |
745 | */ |
746 | if (DOR->Flags & SC_GOTO) { |
747 | SymEntry *E; |
748 | g_userodata (); |
749 | g_defdatalabel (DOR->LateSP_Label); |
750 | g_defdata (CF_CONST | CF_INT, StackPtr - DOR->StackPtr, 0); |
751 | |
752 | /* Optimizer will need the information about the value of SP adjustment |
753 | ** later, so let's preserve it. |
754 | */ |
755 | E = NewSymEntry (LocalLabelName (DOR->LateSP_Label), SC_SPADJUSTMENT); |
756 | E->V.SPAdjustment = StackPtr - DOR->StackPtr; |
757 | AddSymEntry (SPAdjustTab, E); |
758 | } |
759 | |
760 | /* Are we jumping into a block with initalization of an object that |
761 | ** has automatic storage duration? Let's emit a warning. |
762 | */ |
763 | if ((long)CollLast (AIC) != DOR->LocalsBlockId && |
764 | (CollCount (AIC) >= DOR->Depth || |
765 | (long)CollLast (AIC) >= (long)DOR->Line)) |
766 | Warning ("Goto at line %d to label %s jumps into a block with " |
767 | "initialization of an object that has automatic storage duration" , |
768 | DOR->Line, Name); |
769 | } |
770 | |
771 | } |
772 | |
773 | Entry->Flags |= Flags; |
774 | |
775 | } else { |
776 | |
777 | /* Create a new entry */ |
778 | Entry = NewSymEntry (Name, SC_LABEL | Flags); |
779 | |
780 | /* Set a new label number */ |
781 | Entry->V.L.Label = GetLocalLabel (); |
782 | Entry->V.L.IndJumpFrom = NULL; |
783 | |
784 | /* Create Collection for label definition and references */ |
785 | Entry->V.L.DefsOrRefs = NewCollection (); |
786 | NewDOR = AddDefOrRef (Entry, Flags); |
787 | |
788 | /* Generate the assembler name of the label */ |
789 | Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label)); |
790 | |
791 | /* Add the entry to the label table */ |
792 | AddSymEntry (LabelTab, Entry); |
793 | |
794 | } |
795 | |
796 | /* We are processing a goto, but the label has not yet been defined */ |
797 | if (!SymIsDef (Entry) && (Flags & SC_REF) && (Flags & SC_GOTO)) { |
798 | g_lateadjustSP (NewDOR->LateSP_Label); |
799 | } |
800 | |
801 | /* Return the entry */ |
802 | return Entry; |
803 | } |
804 | |
805 | |
806 | |
807 | SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs) |
808 | /* Add a local symbol and return the symbol entry */ |
809 | { |
810 | /* Do we have an entry with this name already? */ |
811 | SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name)); |
812 | if (Entry) { |
813 | |
814 | /* We have a symbol with this name already */ |
815 | Error ("Multiple definition for '%s'" , Name); |
816 | |
817 | } else { |
818 | |
819 | /* Create a new entry */ |
820 | Entry = NewSymEntry (Name, Flags); |
821 | |
822 | /* Set the symbol attributes */ |
823 | Entry->Type = TypeDup (T); |
824 | if ((Flags & SC_AUTO) == SC_AUTO) { |
825 | Entry->V.Offs = Offs; |
826 | } else if ((Flags & SC_REGISTER) == SC_REGISTER) { |
827 | Entry->V.R.RegOffs = Offs; |
828 | Entry->V.R.SaveOffs = StackPtr; |
829 | } else if ((Flags & SC_EXTERN) == SC_EXTERN) { |
830 | Entry->V.L.Label = Offs; |
831 | SymSetAsmName (Entry); |
832 | } else if ((Flags & SC_STATIC) == SC_STATIC) { |
833 | /* Generate the assembler name from the label number */ |
834 | Entry->V.L.Label = Offs; |
835 | Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label)); |
836 | } else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) { |
837 | Entry->V.Offs = Offs; |
838 | } else { |
839 | Internal ("Invalid flags in AddLocalSym: %04X" , Flags); |
840 | } |
841 | |
842 | /* Add the entry to the symbol table */ |
843 | AddSymEntry (SymTab, Entry); |
844 | |
845 | } |
846 | |
847 | /* Return the entry */ |
848 | return Entry; |
849 | } |
850 | |
851 | |
852 | |
853 | SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) |
854 | /* Add an external or global symbol to the symbol table and return the entry */ |
855 | { |
856 | /* There is some special handling for functions, so check if it is one */ |
857 | int IsFunc = IsTypeFunc (T); |
858 | |
859 | /* Functions must be inserted in the global symbol table */ |
860 | SymTable* Tab = IsFunc? SymTab0 : SymTab; |
861 | |
862 | /* Do we have an entry with this name already? */ |
863 | SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name)); |
864 | if (Entry) { |
865 | Type* EType; |
866 | |
867 | /* If the existing symbol is an enumerated constant, |
868 | ** then avoid a compiler crash. See GitHub issue #728. |
869 | */ |
870 | if (Entry->Flags & SC_ENUM) { |
871 | Fatal ("Can't redeclare enum constant '%s' as global variable" , Name); |
872 | } |
873 | |
874 | /* We have a symbol with this name already */ |
875 | if (Entry->Flags & SC_TYPE) { |
876 | Error ("Multiple definition for '%s'" , Name); |
877 | return Entry; |
878 | } |
879 | |
880 | /* Get the type string of the existing symbol */ |
881 | EType = Entry->Type; |
882 | |
883 | /* If we are handling arrays, the old entry or the new entry may be an |
884 | ** incomplete declaration. Accept this, and if the exsting entry is |
885 | ** incomplete, complete it. |
886 | */ |
887 | if (IsTypeArray (T) && IsTypeArray (EType)) { |
888 | |
889 | /* Get the array sizes */ |
890 | long Size = GetElementCount (T); |
891 | long ESize = GetElementCount (EType); |
892 | |
893 | if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) || |
894 | TypeCmp (T + 1, EType + 1) < TC_EQUAL) { |
895 | /* Types not identical: Conflicting types */ |
896 | Error ("Conflicting types for '%s'" , Name); |
897 | return Entry; |
898 | } else { |
899 | /* Check if we have a size in the existing definition */ |
900 | if (ESize == UNSPECIFIED) { |
901 | /* Existing, size not given, use size from new def */ |
902 | SetElementCount (EType, Size); |
903 | } |
904 | } |
905 | |
906 | } else { |
907 | /* New type must be identical */ |
908 | if (TypeCmp (EType, T) < TC_EQUAL) { |
909 | Error ("Conflicting types for '%s'" , Name); |
910 | return Entry; |
911 | } |
912 | |
913 | /* In case of a function, use the new type descriptor, since it |
914 | ** contains pointers to the new symbol tables that are needed if |
915 | ** an actual function definition follows. Be sure not to use the |
916 | ** new descriptor if it contains a function declaration with an |
917 | ** empty parameter list. |
918 | */ |
919 | if (IsFunc) { |
920 | /* Get the function descriptor from the new type */ |
921 | FuncDesc* F = GetFuncDesc (T); |
922 | /* Use this new function descriptor if it doesn't contain |
923 | ** an empty parameter list. |
924 | */ |
925 | if ((F->Flags & FD_EMPTY) == 0) { |
926 | Entry->V.F.Func = F; |
927 | SetFuncDesc (EType, F); |
928 | } |
929 | } |
930 | } |
931 | |
932 | /* If a static declaration follows a non-static declaration, then |
933 | ** warn about the conflict. (It will compile a public declaration.) |
934 | */ |
935 | if ((Flags & SC_EXTERN) == 0 && (Entry->Flags & SC_EXTERN) != 0) { |
936 | Warning ("static declaration follows non-static declaration of '%s'." , Name); |
937 | } |
938 | |
939 | /* An extern declaration must not change the current linkage. */ |
940 | if (IsFunc || (Flags & (SC_EXTERN | SC_STORAGE)) == SC_EXTERN) { |
941 | Flags &= ~SC_EXTERN; |
942 | } |
943 | |
944 | /* If a public declaration follows a static declaration, then |
945 | ** warn about the conflict. (It will compile a public declaration.) |
946 | */ |
947 | if ((Flags & SC_EXTERN) != 0 && (Entry->Flags & SC_EXTERN) == 0) { |
948 | Warning ("public declaration follows static declaration of '%s'." , Name); |
949 | } |
950 | |
951 | /* Add the new flags */ |
952 | Entry->Flags |= Flags; |
953 | |
954 | } else { |
955 | |
956 | /* Create a new entry */ |
957 | Entry = NewSymEntry (Name, Flags); |
958 | |
959 | /* Set the symbol attributes */ |
960 | Entry->Type = TypeDup (T); |
961 | |
962 | /* If this is a function, set the function descriptor and clear |
963 | ** additional fields. |
964 | */ |
965 | if (IsFunc) { |
966 | Entry->V.F.Func = GetFuncDesc (Entry->Type); |
967 | Entry->V.F.Seg = 0; |
968 | } |
969 | |
970 | /* Add the assembler name of the symbol */ |
971 | SymSetAsmName (Entry); |
972 | |
973 | /* Add the entry to the symbol table */ |
974 | AddSymEntry (Tab, Entry); |
975 | } |
976 | |
977 | /* Return the entry */ |
978 | return Entry; |
979 | } |
980 | |
981 | |
982 | |
983 | /*****************************************************************************/ |
984 | /* Code */ |
985 | /*****************************************************************************/ |
986 | |
987 | |
988 | |
989 | SymTable* GetSymTab (void) |
990 | /* Return the current symbol table */ |
991 | { |
992 | return SymTab; |
993 | } |
994 | |
995 | |
996 | |
997 | SymTable* GetGlobalSymTab (void) |
998 | /* Return the global symbol table */ |
999 | { |
1000 | return SymTab0; |
1001 | } |
1002 | |
1003 | SymTable* GetLabelSymTab (void) |
1004 | /* Return the global symbol table */ |
1005 | { |
1006 | return LabelTab; |
1007 | } |
1008 | |
1009 | |
1010 | |
1011 | int SymIsLocal (SymEntry* Sym) |
1012 | /* Return true if the symbol is defined in the highest lexical level */ |
1013 | { |
1014 | return (Sym->Owner == SymTab || Sym->Owner == TagTab); |
1015 | } |
1016 | |
1017 | |
1018 | |
1019 | void MakeZPSym (const char* Name) |
1020 | /* Mark the given symbol as zero page symbol */ |
1021 | { |
1022 | /* Get the symbol table entry */ |
1023 | SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name)); |
1024 | |
1025 | /* Mark the symbol as zeropage */ |
1026 | if (Entry) { |
1027 | Entry->Flags |= SC_ZEROPAGE; |
1028 | } else { |
1029 | Error ("Undefined symbol: '%s'" , Name); |
1030 | } |
1031 | } |
1032 | |
1033 | |
1034 | |
1035 | void PrintSymTable (const SymTable* Tab, FILE* F, const char* , ...) |
1036 | /* Write the symbol table to the given file */ |
1037 | { |
1038 | unsigned Len; |
1039 | const SymEntry* Entry; |
1040 | |
1041 | /* Print the header */ |
1042 | va_list ap; |
1043 | va_start (ap, Header); |
1044 | fputc ('\n', F); |
1045 | Len = vfprintf (F, Header, ap); |
1046 | va_end (ap); |
1047 | fputc ('\n', F); |
1048 | |
1049 | /* Underline the header */ |
1050 | while (Len--) { |
1051 | fputc ('=', F); |
1052 | } |
1053 | fputc ('\n', F); |
1054 | |
1055 | /* Dump the table */ |
1056 | Entry = Tab->SymHead; |
1057 | if (Entry == 0) { |
1058 | fprintf (F, "(empty)\n" ); |
1059 | } else { |
1060 | while (Entry) { |
1061 | DumpSymEntry (F, Entry); |
1062 | Entry = Entry->NextSym; |
1063 | } |
1064 | } |
1065 | fprintf (F, "\n\n\n" ); |
1066 | } |
1067 | |
1068 | |
1069 | |
1070 | void EmitExternals (void) |
1071 | /* Write import/export statements for external symbols */ |
1072 | { |
1073 | SymEntry* Entry; |
1074 | |
1075 | Entry = SymTab->SymHead; |
1076 | while (Entry) { |
1077 | unsigned Flags = Entry->Flags; |
1078 | if (Flags & SC_EXTERN) { |
1079 | /* Only defined or referenced externs */ |
1080 | if (SymIsRef (Entry) && !SymIsDef (Entry)) { |
1081 | /* An import */ |
1082 | g_defimport (Entry->Name, Flags & SC_ZEROPAGE); |
1083 | } else if (SymIsDef (Entry)) { |
1084 | /* An export */ |
1085 | g_defexport (Entry->Name, Flags & SC_ZEROPAGE); |
1086 | } |
1087 | } |
1088 | Entry = Entry->NextSym; |
1089 | } |
1090 | } |
1091 | |
1092 | |
1093 | |
1094 | void EmitDebugInfo (void) |
1095 | /* Emit debug infos for the locals of the current scope */ |
1096 | { |
1097 | const char* Head; |
1098 | const SymEntry* Sym; |
1099 | |
1100 | /* Output info for locals if enabled */ |
1101 | if (DebugInfo) { |
1102 | /* For cosmetic reasons in the output file, we will insert two tabs |
1103 | ** on global level and just one on local level. |
1104 | */ |
1105 | if (LexicalLevel == LEX_LEVEL_GLOBAL) { |
1106 | Head = "\t.dbg\t\tsym" ; |
1107 | } else { |
1108 | Head = "\t.dbg\tsym" ; |
1109 | } |
1110 | Sym = SymTab->SymHead; |
1111 | while (Sym) { |
1112 | if ((Sym->Flags & (SC_CONST|SC_TYPE)) == 0) { |
1113 | if (Sym->Flags & SC_AUTO) { |
1114 | AddTextLine ("%s, \"%s\", \"00\", auto, %d" , |
1115 | Head, Sym->Name, Sym->V.Offs); |
1116 | } else if (Sym->Flags & SC_REGISTER) { |
1117 | AddTextLine ("%s, \"%s\", \"00\", register, \"regbank\", %d" , |
1118 | Head, Sym->Name, Sym->V.R.RegOffs); |
1119 | |
1120 | } else if (SymIsRef (Sym) && !SymIsDef (Sym)) { |
1121 | AddTextLine ("%s, \"%s\", \"00\", %s, \"%s\"" , |
1122 | Head, Sym->Name, |
1123 | (Sym->Flags & SC_EXTERN)? "extern" : "static" , |
1124 | Sym->AsmName); |
1125 | } |
1126 | } |
1127 | Sym = Sym->NextSym; |
1128 | } |
1129 | } |
1130 | } |
1131 | |