]> git.sur5r.net Git - cc65/blob - src/cc65/symtab.c
Stack adjustment code optimizations.
[cc65] / src / cc65 / symtab.c
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     SPAdjustTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
230 }
231
232
233
234 void LeaveGlobalLevel (void)
235 /* Leave the program global lexical level */
236 {
237     /* Safety */
238     PRECONDITION (LexicalLevel-- == LEX_LEVEL_GLOBAL);
239
240     /* Check the tables */
241     CheckSymTable (SymTab0);
242
243     /* Dump the tables if requested */
244     if (Debug) {
245         PrintSymTable (SymTab0, stdout, "Global symbol table");
246         PrintSymTable (TagTab0, stdout, "Global tag table");
247     }
248
249     /* Don't delete the symbol and struct tables! */
250     SymTab = 0;
251     TagTab = 0;
252 }
253
254
255
256 void EnterFunctionLevel (void)
257 /* Enter function lexical level */
258 {
259     SymTable* S;
260
261     /* New lexical level */
262     ++LexicalLevel;
263
264     /* Get a new symbol table and make it current */
265     S = NewSymTable (SYMTAB_SIZE_FUNCTION);
266     S->PrevTab = SymTab;
267     SymTab     = S;
268
269     /* Get a new tag table and make it current */
270     S = NewSymTable (SYMTAB_SIZE_FUNCTION);
271     S->PrevTab = TagTab;
272     TagTab  = S;
273
274     /* Create and assign a new label table */
275     S = NewSymTable (SYMTAB_SIZE_LABEL);
276     S->PrevTab = LabelTab;
277     LabelTab = S;
278 }
279
280
281
282 void RememberFunctionLevel (struct FuncDesc* F)
283 /* Remember the symbol tables for the level and leave the level without checks */
284 {
285     /* Leave the lexical level */
286     --LexicalLevel;
287
288     /* Remember the tables */
289     F->SymTab = SymTab;
290     F->TagTab = TagTab;
291
292     /* Don't delete the tables */
293     SymTab = SymTab->PrevTab;
294     TagTab = TagTab->PrevTab;
295     LabelTab = LabelTab->PrevTab;
296 }
297
298
299
300 void ReenterFunctionLevel (struct FuncDesc* F)
301 /* Reenter the function lexical level using the existing tables from F */
302 {
303     /* New lexical level */
304     ++LexicalLevel;
305
306     /* Make the tables current again */
307     F->SymTab->PrevTab = SymTab;
308     SymTab = F->SymTab;
309
310     F->TagTab->PrevTab = TagTab;
311     TagTab = F->TagTab;
312
313     /* Create and assign a new label table */
314     LabelTab = NewSymTable (SYMTAB_SIZE_LABEL);
315 }
316
317
318
319 void LeaveFunctionLevel (void)
320 /* Leave function lexical level */
321 {
322     /* Leave the lexical level */
323     --LexicalLevel;
324
325     /* Check the tables */
326     CheckSymTable (SymTab);
327     CheckSymTable (LabelTab);
328
329     /* Drop the label table if it is empty */
330     if (LabelTab->SymCount == 0) {
331         FreeSymTable (LabelTab);
332     }
333
334     /* Don't delete the tables */
335     SymTab = SymTab->PrevTab;
336     TagTab = TagTab->PrevTab;
337     LabelTab  = 0;
338 }
339
340
341
342 void EnterBlockLevel (void)
343 /* Enter a nested block in a function */
344 {
345     SymTable* S;
346
347     /* New lexical level */
348     ++LexicalLevel;
349
350     /* Get a new symbol table and make it current */
351     S = NewSymTable (SYMTAB_SIZE_BLOCK);
352     S->PrevTab  = SymTab;
353     SymTab      = S;
354
355     /* Get a new tag table and make it current */
356     S = NewSymTable (SYMTAB_SIZE_BLOCK);
357     S->PrevTab = TagTab;
358     TagTab     = S;
359 }
360
361
362
363 void LeaveBlockLevel (void)
364 /* Leave a nested block in a function */
365 {
366     /* Leave the lexical level */
367     --LexicalLevel;
368
369     /* Check the tables */
370     CheckSymTable (SymTab);
371
372     /* Don't delete the tables */
373     SymTab = SymTab->PrevTab;
374     TagTab = TagTab->PrevTab;
375 }
376
377
378
379 void EnterStructLevel (void)
380 /* Enter a nested block for a struct definition */
381 {
382     SymTable* S;
383
384     /* Get a new symbol table and make it current. Note: Structs and enums
385     ** nested in struct scope are NOT local to the struct but visible in the
386     ** outside scope. So we will NOT create a new struct or enum table.
387     */
388     S = NewSymTable (SYMTAB_SIZE_BLOCK);
389     S->PrevTab  = SymTab;
390     SymTab      = S;
391 }
392
393
394
395 void LeaveStructLevel (void)
396 /* Leave a nested block for a struct definition */
397 {
398     /* Don't delete the table */
399     SymTab = SymTab->PrevTab;
400 }
401
402
403
404 /*****************************************************************************/
405 /*                              Find functions                               */
406 /*****************************************************************************/
407
408
409
410 SymEntry* FindSymInTable (const SymTable* T, const char* Name, unsigned Hash)
411 /* Search for an entry in one table */
412 {
413     /* Get the start of the hash chain */
414     SymEntry* E = T->Tab [Hash % T->Size];
415     while (E) {
416         /* Compare the name */
417         if (strcmp (E->Name, Name) == 0) {
418             /* Found */
419             return E;
420         }
421         /* Not found, next entry in hash chain */
422         E = E->NextHash;
423     }
424
425     /* Not found */
426     return 0;
427 }
428
429
430
431 static SymEntry* FindSymInTree (const SymTable* Tab, const char* Name)
432 /* Find the symbol with the given name in the table tree that starts with T */
433 {
434     /* Get the hash over the name */
435     unsigned Hash = HashStr (Name);
436
437     /* Check all symbol tables for the symbol */
438     while (Tab) {
439         /* Try to find the symbol in this table */
440         SymEntry* E = FindSymInTable (Tab, Name, Hash);
441
442         /* Bail out if we found it */
443         if (E != 0) {
444             return E;
445         }
446
447         /* Repeat the search in the next higher lexical level */
448         Tab = Tab->PrevTab;
449     }
450
451     /* Not found */
452     return 0;
453 }
454
455
456
457 SymEntry* FindSym (const char* Name)
458 /* Find the symbol with the given name */
459 {
460     return FindSymInTree (SymTab, Name);
461 }
462
463
464
465 SymEntry* FindGlobalSym (const char* Name)
466 /* Find the symbol with the given name in the global symbol table only */
467 {
468     return FindSymInTable (SymTab0, Name, HashStr (Name));
469 }
470
471
472
473 SymEntry* FindLocalSym (const char* Name)
474 /* Find the symbol with the given name in the current symbol table only */
475 {
476     return FindSymInTable (SymTab, Name, HashStr (Name));
477 }
478
479
480
481 SymEntry* FindTagSym (const char* Name)
482 /* Find the symbol with the given name in the tag table */
483 {
484     return FindSymInTree (TagTab, Name);
485 }
486
487
488
489 SymEntry* FindStructField (const Type* T, const char* Name)
490 /* Find a struct field in the fields list */
491 {
492     SymEntry* Field = 0;
493
494     /* The given type may actually be a pointer to struct */
495     if (IsTypePtr (T)) {
496         ++T;
497     }
498
499     /* Non-structs do not have any struct fields... */
500     if (IsClassStruct (T)) {
501
502         /* Get a pointer to the struct/union type */
503         const SymEntry* Struct = GetSymEntry (T);
504         CHECK (Struct != 0);
505
506         /* Now search in the struct symbol table. Beware: The table may not
507         ** exist.
508         */
509         if (Struct->V.S.SymTab) {
510             Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name));
511         }
512     }
513
514     return Field;
515 }
516
517
518
519 /*****************************************************************************/
520 /*                       Add stuff to the symbol table                       */
521 /*****************************************************************************/
522
523
524
525 static void AddSymEntry (SymTable* T, SymEntry* S)
526 /* Add a symbol to a symbol table */
527 {
528     /* Get the hash value for the name */
529     unsigned Hash = HashStr (S->Name) % T->Size;
530
531     /* Insert the symbol into the list of all symbols in this level */
532     if (T->SymTail) {
533         T->SymTail->NextSym = S;
534     }
535     S->PrevSym = T->SymTail;
536     T->SymTail = S;
537     if (T->SymHead == 0) {
538         /* First symbol */
539         T->SymHead = S;
540     }
541     ++T->SymCount;
542
543     /* Insert the symbol into the hash chain */
544     S->NextHash  = T->Tab[Hash];
545     T->Tab[Hash] = S;
546
547     /* Tell the symbol in which table it is */
548     S->Owner = T;
549 }
550
551
552
553 SymEntry* AddStructSym (const char* Name, unsigned Type, unsigned Size, SymTable* Tab)
554 /* Add a struct/union entry and return it */
555 {
556     SymEntry* Entry;
557
558     /* Type must be struct or union */
559     PRECONDITION (Type == SC_STRUCT || Type == SC_UNION);
560
561     /* Do we have an entry with this name already? */
562     Entry = FindSymInTable (TagTab, Name, HashStr (Name));
563     if (Entry) {
564
565         /* We do have an entry. This may be a forward, so check it. */
566         if ((Entry->Flags & SC_TYPEMASK) != Type) {
567             /* Existing symbol is not a struct */
568             Error ("Symbol `%s' is already different kind", Name);
569         } else if (Size > 0 && Entry->V.S.Size > 0) {
570             /* Both structs are definitions. */
571             Error ("Multiple definition for `%s'", Name);
572         } else {
573             /* Define the struct size if it is given */
574             if (Size > 0) {
575                 Entry->V.S.SymTab = Tab;
576                 Entry->V.S.Size   = Size;
577             }
578         }
579
580     } else {
581
582         /* Create a new entry */
583         Entry = NewSymEntry (Name, Type);
584
585         /* Set the struct data */
586         Entry->V.S.SymTab = Tab;
587         Entry->V.S.Size   = Size;
588
589         /* Add it to the current table */
590         AddSymEntry (TagTab, Entry);
591     }
592
593     /* Return the entry */
594     return Entry;
595 }
596
597
598
599 SymEntry* AddBitField (const char* Name, unsigned Offs, unsigned BitOffs, unsigned Width)
600 /* Add a bit field to the local symbol table and return the symbol entry */
601 {
602     /* Do we have an entry with this name already? */
603     SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
604     if (Entry) {
605
606         /* We have a symbol with this name already */
607         Error ("Multiple definition for `%s'", Name);
608
609     } else {
610
611         /* Create a new entry */
612         Entry = NewSymEntry (Name, SC_BITFIELD);
613
614         /* Set the symbol attributes. Bit-fields are always of type unsigned */
615         Entry->Type         = type_uint;
616         Entry->V.B.Offs     = Offs;
617         Entry->V.B.BitOffs  = BitOffs;
618         Entry->V.B.BitWidth = Width;
619
620         /* Add the entry to the symbol table */
621         AddSymEntry (SymTab, Entry);
622
623     }
624
625     /* Return the entry */
626     return Entry;
627 }
628
629
630
631 SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val)
632 /* Add an constant symbol to the symbol table and return it */
633 {
634     /* Enums must be inserted in the global symbol table */
635     SymTable* Tab = ((Flags & SC_ENUM) == SC_ENUM)? SymTab0 : SymTab;
636
637     /* Do we have an entry with this name already? */
638     SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
639     if (Entry) {
640         if ((Entry->Flags & SC_CONST) != SC_CONST) {
641             Error ("Symbol `%s' is already different kind", Name);
642         } else {
643             Error ("Multiple definition for `%s'", Name);
644         }
645         return Entry;
646     }
647
648     /* Create a new entry */
649     Entry = NewSymEntry (Name, Flags);
650
651     /* Enum values are ints */
652     Entry->Type = TypeDup (T);
653
654     /* Set the enum data */
655     Entry->V.ConstVal = Val;
656
657     /* Add the entry to the symbol table */
658     AddSymEntry (Tab, Entry);
659
660     /* Return the entry */
661     return Entry;
662 }
663
664
665 DefOrRef* AddDefOrRef (SymEntry* E, unsigned Flags)
666 /* Add definition or reference to the SymEntry and preserve its attributes */
667 {
668     DefOrRef *DOR;
669
670     DOR = xmalloc (sizeof (DefOrRef));
671     CollAppend (E->V.L.DefsOrRefs, DOR);
672     DOR->Line = GetCurrentLine ();
673     DOR->LocalsBlockId = (long)CollLast (&CurrentFunc->LocalsBlockStack);
674     DOR->Flags = Flags;
675     DOR->StackPtr = StackPtr;
676     DOR->Depth = CollCount (&CurrentFunc->LocalsBlockStack);
677     DOR->LateSP_Label = GetLocalLabel ();
678
679     return DOR;
680 }
681
682 unsigned short FindSPAdjustment (const char* Name)
683 {
684     SymEntry* Entry = FindSymInTable (SPAdjustTab, Name, HashStr (Name));
685
686     if (Entry) {
687             printf("L: %s sa: %d\n", Name, Entry->V.G.SPAdjustment);
688             return Entry->V.G.SPAdjustment;
689     }
690
691     Fatal("ICE: No label entry found");
692
693     return 0;
694 }
695
696 SymEntry* AddLabelSym (const char* Name, unsigned Flags)
697 /* Add a goto label to the label table */
698 {
699     unsigned i;
700     DefOrRef *DOR, *NewDOR;
701     /* We juggle it so much that a shortcut will help with clarity */
702     Collection *AIC = &CurrentFunc->LocalsBlockStack;
703
704     /* Do we have an entry with this name already? */
705     SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name));
706     if (Entry) {
707
708         if (SymIsDef (Entry) && (Flags & SC_DEF) != 0) {
709             /* Trying to define the label more than once */
710             Error ("Label `%s' is defined more than once", Name);
711         }
712
713         NewDOR = AddDefOrRef (Entry, Flags);
714
715         /* Walk through all occurrences of the label so far and evaluate
716         ** their relationship with the one passed to the function.
717         */
718         for (i = 0; i < CollCount (Entry->V.L.DefsOrRefs); i++) {
719             DOR = CollAt (Entry->V.L.DefsOrRefs, i);
720
721             if ((DOR->Flags & SC_DEF) && (Flags & SC_REF) && (Flags & SC_GOTO)) {
722                 /* We're processing a goto and here is its destination label.
723                 ** This means the difference between SP values is already known,
724                 ** so we simply emit the SP adjustment code.
725                 */
726                 if (StackPtr != DOR->StackPtr) {
727                     g_space (StackPtr - DOR->StackPtr);
728                 }
729
730                 /* Are we jumping into a block with initalization of an object that
731                 ** has automatic storage duration? Let's emit a warning.
732                 */
733                 if ((long)CollLast (AIC) != DOR->LocalsBlockId &&
734                     (CollCount (AIC) < DOR->Depth ||
735                     (long)CollAt (AIC, DOR->Depth - 1) != DOR->LocalsBlockId)) {
736                     Warning ("Goto at line %d to label %s jumps into a block with "
737                     "initialization of an object that has automatic storage duration",
738                     GetCurrentLine (), Name);
739                 }
740             }
741
742
743             if ((DOR->Flags & SC_REF) && (DOR->Flags & SC_GOTO) && (Flags & SC_DEF)) {
744                 /* We're processing a label, let's update all gotos encountered
745                 ** so far
746                 */
747                 SymEntry *E;
748                 g_userodata();
749                 g_defdatalabel (DOR->LateSP_Label);
750                 g_defdata (CF_CONST | CF_INT, StackPtr - DOR->StackPtr, 0);
751                 E = NewSymEntry (LocalLabelName(DOR->LateSP_Label), SC_SPADJUSTMENT);
752                 E->V.G.SPAdjustment = StackPtr - DOR->StackPtr;
753                 AddSymEntry (SPAdjustTab, E);
754
755
756                 /* Are we jumping into a block with initalization of an object that
757                 ** has automatic storage duration? Let's emit a warning.
758                 */
759                 if ((long)CollLast (AIC) != DOR->LocalsBlockId &&
760                     (CollCount (AIC) >= DOR->Depth ||
761                     (long)CollLast (AIC) >= (long)DOR->Line))
762                     Warning ("Goto at line %d to label %s jumps into a block with "
763                     "initialization of an object that has automatic storage duration",
764                     DOR->Line, Name);
765              }
766
767         }
768
769         Entry->Flags |= Flags;
770
771     } else {
772
773         /* Create a new entry */
774         Entry = NewSymEntry (Name, SC_LABEL | Flags);
775
776         /* Set a new label number */
777         Entry->V.L.Label = GetLocalLabel ();
778
779         /* Create Collection for label definition and references */
780         Entry->V.L.DefsOrRefs = NewCollection ();
781         NewDOR = AddDefOrRef (Entry, Flags);
782
783         /* Generate the assembler name of the label */
784         Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label));
785
786         /* Add the entry to the label table */
787         AddSymEntry (LabelTab, Entry);
788
789     }
790
791     /* We are processing a goto, but the label has not yet been defined */
792     if (!SymIsDef (Entry) && (Flags & SC_REF) && (Flags & SC_GOTO)) {
793         g_lateadjustSP (NewDOR->LateSP_Label);
794     }
795
796     /* Return the entry */
797     return Entry;
798 }
799
800
801
802 SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs)
803 /* Add a local symbol and return the symbol entry */
804 {
805     /* Do we have an entry with this name already? */
806     SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
807     if (Entry) {
808
809         /* We have a symbol with this name already */
810         Error ("Multiple definition for `%s'", Name);
811
812     } else {
813
814         /* Create a new entry */
815         Entry = NewSymEntry (Name, Flags);
816
817         /* Set the symbol attributes */
818         Entry->Type = TypeDup (T);
819         if ((Flags & SC_AUTO) == SC_AUTO) {
820             Entry->V.Offs = Offs;
821         } else if ((Flags & SC_REGISTER) == SC_REGISTER) {
822             Entry->V.R.RegOffs  = Offs;
823             Entry->V.R.SaveOffs = StackPtr;
824         } else if ((Flags & SC_EXTERN) == SC_EXTERN) {
825             Entry->V.L.Label = Offs;
826             SymSetAsmName (Entry);
827         } else if ((Flags & SC_STATIC) == SC_STATIC) {
828             /* Generate the assembler name from the label number */
829             Entry->V.L.Label = Offs;
830             Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label));
831         } else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) {
832             Entry->V.Offs = Offs;
833         } else {
834             Internal ("Invalid flags in AddLocalSym: %04X", Flags);
835         }
836
837         /* Add the entry to the symbol table */
838         AddSymEntry (SymTab, Entry);
839
840     }
841
842     /* Return the entry */
843     return Entry;
844 }
845
846
847
848 SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
849 /* Add an external or global symbol to the symbol table and return the entry */
850 {
851     /* There is some special handling for functions, so check if it is one */
852     int IsFunc = IsTypeFunc (T);
853
854     /* Functions must be inserted in the global symbol table */
855     SymTable* Tab = IsFunc? SymTab0 : SymTab;
856
857     /* Do we have an entry with this name already? */
858     SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
859     if (Entry) {
860         Type* EType;
861
862         /* If the existing symbol is an enumerated constant,
863         ** then avoid a compiler crash.  See GitHub issue #728.
864         */
865         if (Entry->Flags & SC_ENUM) {
866             Fatal ("Can't redeclare enum constant `%s' as global variable", Name);
867         }
868
869         /* We have a symbol with this name already */
870         if (Entry->Flags & SC_TYPE) {
871             Error ("Multiple definition for `%s'", Name);
872             return Entry;
873         }
874
875         /* Get the type string of the existing symbol */
876         EType = Entry->Type;
877
878         /* If we are handling arrays, the old entry or the new entry may be an
879         ** incomplete declaration. Accept this, and if the exsting entry is
880         ** incomplete, complete it.
881         */
882         if (IsTypeArray (T) && IsTypeArray (EType)) {
883
884             /* Get the array sizes */
885             long Size  = GetElementCount (T);
886             long ESize = GetElementCount (EType);
887
888             if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) ||
889                 TypeCmp (T + 1, EType + 1) < TC_EQUAL) {
890                 /* Types not identical: Conflicting types */
891                 Error ("Conflicting types for `%s'", Name);
892                 return Entry;
893             } else {
894                 /* Check if we have a size in the existing definition */
895                 if (ESize == UNSPECIFIED) {
896                     /* Existing, size not given, use size from new def */
897                     SetElementCount (EType, Size);
898                 }
899             }
900
901         } else {
902             /* New type must be identical */
903             if (TypeCmp (EType, T) < TC_EQUAL) {
904                 Error ("Conflicting types for `%s'", Name);
905                 return Entry;
906             }
907
908             /* In case of a function, use the new type descriptor, since it
909             ** contains pointers to the new symbol tables that are needed if
910             ** an actual function definition follows. Be sure not to use the
911             ** new descriptor if it contains a function declaration with an
912             ** empty parameter list.
913             */
914             if (IsFunc) {
915                 /* Get the function descriptor from the new type */
916                 FuncDesc* F = GetFuncDesc (T);
917                 /* Use this new function descriptor if it doesn't contain
918                 ** an empty parameter list.
919                 */
920                 if ((F->Flags & FD_EMPTY) == 0) {
921                     Entry->V.F.Func = F;
922                     SetFuncDesc (EType, F);
923                 }
924             }
925         }
926
927         /* If a static declaration follows a non-static declaration, then
928         ** warn about the conflict.  (It will compile a public declaration.)
929         */
930         if ((Flags & SC_EXTERN) == 0 && (Entry->Flags & SC_EXTERN) != 0) {
931             Warning ("static declaration follows non-static declaration of `%s'.", Name);
932         }
933
934         /* An extern declaration must not change the current linkage. */
935         if (IsFunc || (Flags & (SC_EXTERN | SC_STORAGE)) == SC_EXTERN) {
936             Flags &= ~SC_EXTERN;
937         }
938
939         /* If a public declaration follows a static declaration, then
940         ** warn about the conflict.  (It will compile a public declaration.)
941         */
942         if ((Flags & SC_EXTERN) != 0 && (Entry->Flags & SC_EXTERN) == 0) {
943             Warning ("public declaration follows static declaration of `%s'.", Name);
944         }
945
946         /* Add the new flags */
947         Entry->Flags |= Flags;
948
949     } else {
950
951         /* Create a new entry */
952         Entry = NewSymEntry (Name, Flags);
953
954         /* Set the symbol attributes */
955         Entry->Type = TypeDup (T);
956
957         /* If this is a function, set the function descriptor and clear
958         ** additional fields.
959         */
960         if (IsFunc) {
961             Entry->V.F.Func = GetFuncDesc (Entry->Type);
962             Entry->V.F.Seg  = 0;
963         }
964
965         /* Add the assembler name of the symbol */
966         SymSetAsmName (Entry);
967
968         /* Add the entry to the symbol table */
969         AddSymEntry (Tab, Entry);
970     }
971
972     /* Return the entry */
973     return Entry;
974 }
975
976
977
978 /*****************************************************************************/
979 /*                                   Code                                    */
980 /*****************************************************************************/
981
982
983
984 SymTable* GetSymTab (void)
985 /* Return the current symbol table */
986 {
987     return SymTab;
988 }
989
990
991
992 SymTable* GetGlobalSymTab (void)
993 /* Return the global symbol table */
994 {
995     return SymTab0;
996 }
997
998
999
1000 int SymIsLocal (SymEntry* Sym)
1001 /* Return true if the symbol is defined in the highest lexical level */
1002 {
1003     return (Sym->Owner == SymTab || Sym->Owner == TagTab);
1004 }
1005
1006
1007
1008 void MakeZPSym (const char* Name)
1009 /* Mark the given symbol as zero page symbol */
1010 {
1011     /* Get the symbol table entry */
1012     SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
1013
1014     /* Mark the symbol as zeropage */
1015     if (Entry) {
1016         Entry->Flags |= SC_ZEROPAGE;
1017     } else {
1018         Error ("Undefined symbol: `%s'", Name);
1019     }
1020 }
1021
1022
1023
1024 void PrintSymTable (const SymTable* Tab, FILE* F, const char* Header, ...)
1025 /* Write the symbol table to the given file */
1026 {
1027     unsigned Len;
1028     const SymEntry* Entry;
1029
1030     /* Print the header */
1031     va_list ap;
1032     va_start (ap, Header);
1033     fputc ('\n', F);
1034     Len = vfprintf (F, Header, ap);
1035     va_end (ap);
1036     fputc ('\n', F);
1037
1038     /* Underline the header */
1039     while (Len--) {
1040         fputc ('=', F);
1041     }
1042     fputc ('\n', F);
1043
1044     /* Dump the table */
1045     Entry = Tab->SymHead;
1046     if (Entry == 0) {
1047         fprintf (F, "(empty)\n");
1048     } else {
1049         while (Entry) {
1050             DumpSymEntry (F, Entry);
1051             Entry = Entry->NextSym;
1052         }
1053     }
1054     fprintf (F, "\n\n\n");
1055 }
1056
1057
1058
1059 void EmitExternals (void)
1060 /* Write import/export statements for external symbols */
1061 {
1062     SymEntry* Entry;
1063
1064     Entry = SymTab->SymHead;
1065     while (Entry) {
1066         unsigned Flags = Entry->Flags;
1067         if (Flags & SC_EXTERN) {
1068             /* Only defined or referenced externs */
1069             if (SymIsRef (Entry) && !SymIsDef (Entry)) {
1070                 /* An import */
1071                 g_defimport (Entry->Name, Flags & SC_ZEROPAGE);
1072             } else if (SymIsDef (Entry)) {
1073                 /* An export */
1074                 g_defexport (Entry->Name, Flags & SC_ZEROPAGE);
1075             }
1076         }
1077         Entry = Entry->NextSym;
1078     }
1079 }
1080
1081
1082
1083 void EmitDebugInfo (void)
1084 /* Emit debug infos for the locals of the current scope */
1085 {
1086     const char* Head;
1087     const SymEntry* Sym;
1088
1089     /* Output info for locals if enabled */
1090     if (DebugInfo) {
1091         /* For cosmetic reasons in the output file, we will insert two tabs
1092         ** on global level and just one on local level.
1093         */
1094         if (LexicalLevel == LEX_LEVEL_GLOBAL) {
1095             Head = "\t.dbg\t\tsym";
1096         } else {
1097             Head = "\t.dbg\tsym";
1098         }
1099         Sym = SymTab->SymHead;
1100         while (Sym) {
1101             if ((Sym->Flags & (SC_CONST|SC_TYPE)) == 0) {
1102                 if (Sym->Flags & SC_AUTO) {
1103                     AddTextLine ("%s, \"%s\", \"00\", auto, %d",
1104                                  Head, Sym->Name, Sym->V.Offs);
1105                 } else if (Sym->Flags & SC_REGISTER) {
1106                     AddTextLine ("%s, \"%s\", \"00\", register, \"regbank\", %d",
1107                                  Head, Sym->Name, Sym->V.R.RegOffs);
1108
1109                 } else if (SymIsRef (Sym) && !SymIsDef (Sym)) {
1110                     AddTextLine ("%s, \"%s\", \"00\", %s, \"%s\"",
1111                                  Head, Sym->Name,
1112                                  (Sym->Flags & SC_EXTERN)? "extern" : "static",
1113                                  Sym->AsmName);
1114                 }
1115             }
1116             Sym = Sym->NextSym;
1117         }
1118     }
1119 }