]> git.sur5r.net Git - cc65/blob - src/ca65/symtab.c
e0d6f830987ee6ce19e2404302b4265a5316e224
[cc65] / src / ca65 / symtab.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 symtab.c                                  */
4 /*                                                                           */
5 /*                 Symbol table for the ca65 macroassembler                  */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2011, 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 <string.h>
37
38 /* common */
39 #include "addrsize.h"
40 #include "check.h"
41 #include "hashfunc.h"
42 #include "mmodel.h"
43 #include "scopedefs.h"
44 #include "symdefs.h"
45 #include "xmalloc.h"
46
47 /* ca65 */
48 #include "global.h"
49 #include "error.h"
50 #include "expr.h"
51 #include "objfile.h"
52 #include "scanner.h"
53 #include "segment.h"
54 #include "sizeof.h"
55 #include "span.h"
56 #include "spool.h"
57 #include "studyexpr.h"
58 #include "symtab.h"
59
60
61
62 /*****************************************************************************/
63 /*                                   Data                                    */
64 /*****************************************************************************/
65
66
67
68 /* Combined symbol entry flags used within this module */
69 #define SF_UNDEFMASK    (SF_REFERENCED | SF_DEFINED | SF_IMPORT)
70 #define SF_UNDEFVAL     (SF_REFERENCED)
71
72 /* Symbol tables */
73 SymTable*           CurrentScope = 0;   /* Pointer to current symbol table */
74 SymTable*           RootScope    = 0;   /* Root symbol table */
75 static SymTable*    LastScope    = 0;   /* Pointer to last scope in list */
76 static unsigned     ScopeCount   = 0;   /* Number of scopes */
77
78 /* Symbol table variables */
79 static unsigned     ImportCount = 0;    /* Counter for import symbols */
80 static unsigned     ExportCount = 0;    /* Counter for export symbols */
81
82
83
84 /*****************************************************************************/
85 /*                         Internally used functions                         */
86 /*****************************************************************************/
87
88
89
90 static int IsDbgSym (const SymEntry* S)
91 /* Return true if this is a debug symbol */
92 {
93     if ((S->Flags & (SF_DEFINED | SF_UNUSED)) == SF_DEFINED) {
94         /* Defined symbols are debug symbols if they aren't sizes */
95         return !IsSizeOfSymbol (S);
96     } else {
97         /* Others are debug symbols if they're referenced imports */
98         return ((S->Flags & SF_REFIMP) == SF_REFIMP);
99     }
100 }
101
102
103
104 static unsigned ScopeTableSize (unsigned Level)
105 /* Get the size of a table for the given lexical level */
106 {
107     switch (Level) {
108         case 0:         return 213;
109         case 1:         return  53;
110         default:        return  29;
111     }
112 }
113
114
115
116 static SymTable* NewSymTable (SymTable* Parent, const StrBuf* Name)
117 /* Allocate a symbol table on the heap and return it */
118 {
119     /* Determine the lexical level and the number of table slots */
120     unsigned Level = Parent? Parent->Level + 1 : 0;
121     unsigned Slots = ScopeTableSize (Level);
122
123     /* Allocate memory */
124     SymTable* S = xmalloc (sizeof (SymTable) + (Slots-1) * sizeof (SymEntry*));
125
126     /* Set variables and clear hash table entries */
127     S->Next         = 0;
128     S->Left         = 0;
129     S->Right        = 0;
130     S->Childs       = 0;
131     S->Label        = 0;
132     S->Spans        = AUTO_COLLECTION_INITIALIZER;
133     S->Id           = ScopeCount++;
134     S->Flags        = ST_NONE;
135     S->AddrSize     = ADDR_SIZE_DEFAULT;
136     S->Type         = SCOPE_UNDEF;
137     S->Level        = Level;
138     S->TableSlots   = Slots;
139     S->TableEntries = 0;
140     S->Parent       = Parent;
141     S->Name         = GetStrBufId (Name);
142     while (Slots--) {
143         S->Table[Slots] = 0;
144     }
145
146     /* Insert the symbol table into the list of all symbol tables */
147     if (RootScope == 0) {
148         RootScope = S;
149     } else {
150         LastScope->Next = S;
151     }
152     LastScope = S;
153
154     /* Insert the symbol table into the child tree of the parent */
155     if (Parent) {
156         SymTable* T = Parent->Childs;
157         if (T == 0) {
158             /* First entry */
159             Parent->Childs = S;
160         } else {
161             while (1) {
162                 /* Choose next entry */
163                 int Cmp = SB_Compare (Name, GetStrBuf (T->Name));
164                 if (Cmp < 0) {
165                     if (T->Left) {
166                         T = T->Left;
167                     } else {
168                         T->Left = S;
169                         break;
170                     }
171                 } else if (Cmp > 0) {
172                     if (T->Right) {
173                         T = T->Right;
174                     } else {
175                         T->Right = S;
176                         break;
177                     }
178                 } else {
179                     /* Duplicate scope name */
180                     Internal ("Duplicate scope name: `%m%p'", Name);
181                 }
182             }
183         }
184     }
185
186     /* Return the prepared struct */
187     return S;
188 }
189
190
191
192 /*****************************************************************************/
193 /*                                   Code                                    */
194 /*****************************************************************************/
195
196
197
198 void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
199                     unsigned char AddrSize, SymEntry* ScopeLabel)
200 /* Enter a new lexical level */
201 {
202     /* Map a default address size to something real */
203     if (AddrSize == ADDR_SIZE_DEFAULT) {
204         /* Use the segment address size */
205         AddrSize = GetCurrentSegAddrSize ();
206     }
207
208     /* If we have a current scope, search for the given name and create a
209      * new one if it doesn't exist. If this is the root scope, just create it.
210      */
211     if (CurrentScope) {
212
213         /* Search for the scope, create a new one */
214         CurrentScope = SymFindScope (CurrentScope, ScopeName, SYM_ALLOC_NEW);
215
216         /* Check if the scope has been defined before */
217         if (CurrentScope->Flags & ST_DEFINED) {
218             Error ("Duplicate scope `%m%p'", ScopeName);
219         }
220
221     } else {
222         CurrentScope = RootScope = NewSymTable (0, ScopeName);
223     }
224
225     /* Mark the scope as defined and set type, address size and owner symbol */
226     CurrentScope->Flags    |= ST_DEFINED;
227     CurrentScope->AddrSize = AddrSize;
228     CurrentScope->Type     = Type;
229     CurrentScope->Label    = ScopeLabel;
230
231     /* If this is a scope that allows to emit data into segments, add spans
232      * for all currently existing segments. Doing this for just a few scope
233      * types is not really necessary but an optimization, because it does not
234      * allocate memory for useless data (unhandled types here don't occupy
235      * space in any segment).
236      */
237     if (CurrentScope->Type <= SCOPE_HAS_DATA) {
238         OpenSpanList (&CurrentScope->Spans);
239     }
240 }
241
242
243
244 void SymLeaveLevel (void)
245 /* Leave the current lexical level */
246 {
247     /* If this is a scope that allows to emit data into segments, close the
248      * open the spans.
249      */
250     if (CurrentScope->Type <= SCOPE_HAS_DATA) {
251         CloseSpanList (&CurrentScope->Spans);
252     }
253
254     /* If we have spans, the first one is the segment that was active, when the
255      * scope was opened. Set the size of the scope to the number of data bytes
256      * emitted into this segment. If we have an owner symbol set the size of
257      * this symbol, too.
258      */
259     if (CollCount (&CurrentScope->Spans) > 0) {
260         const Span* S = CollAtUnchecked (&CurrentScope->Spans, 0);
261         unsigned long Size = GetSpanSize (S);
262         DefSizeOfScope (CurrentScope, Size);
263         if (CurrentScope->Label) {
264             DefSizeOfSymbol (CurrentScope->Label, Size);
265         }
266     }
267
268     /* Leave the scope */
269     CurrentScope = CurrentScope->Parent;
270 }
271
272
273
274 SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, int AllocNew)
275 /* Find a scope in the given enclosing scope */
276 {
277     SymTable** T = &Parent->Childs;
278     while (*T) {
279         int Cmp = SB_Compare (Name, GetStrBuf ((*T)->Name));
280         if (Cmp < 0) {
281             T = &(*T)->Left;
282         } else if (Cmp > 0) {
283             T = &(*T)->Right;
284         } else {
285             /* Found the scope */
286             return *T;
287         }
288     }
289
290     /* Create a new scope if requested and we didn't find one */
291     if (*T == 0 && AllocNew) {
292         *T = NewSymTable (Parent, Name);
293     }
294
295     /* Return the scope */
296     return *T;
297 }
298
299
300
301 SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name)
302 /* Find a scope in the given or any of its parent scopes. The function will
303  * never create a new symbol, since this can only be done in one specific
304  * scope.
305  */
306 {
307     SymTable* Scope;
308     do {
309         /* Search in the current table */
310         Scope = SymFindScope (Parent, Name, SYM_FIND_EXISTING);
311         if (Scope == 0) {
312             /* Not found, search in the parent scope, if we have one */
313             Parent = Parent->Parent;
314         }
315     } while (Scope == 0 && Parent != 0);
316
317     return Scope;
318 }
319
320
321
322 SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, int AllocNew)
323 /* Find a cheap local symbol. If AllocNew is given and the entry is not
324  * found, create a new one. Return the entry found, or the new entry created,
325  * or - in case AllocNew is zero - return 0.
326  */
327 {
328     SymEntry* S;
329     int Cmp;
330
331     /* Local symbol, get the table */
332     if (!Parent) {
333         /* No last global, so there's no local table */
334         Error ("No preceeding global symbol");
335         if (AllocNew) {
336             return NewSymEntry (Name, SF_LOCAL);
337         } else {
338             return 0;
339         }
340     }
341
342     /* Search for the symbol if we have a table */
343     Cmp = SymSearchTree (Parent->Locals, Name, &S);
344
345     /* If we found an entry, return it */
346     if (Cmp == 0) {
347         return S;
348     }
349
350     if (AllocNew) {
351
352         /* Otherwise create a new entry, insert and return it */
353         SymEntry* N = NewSymEntry (Name, SF_LOCAL);
354         N->Sym.Entry = Parent;
355         if (S == 0) {
356             Parent->Locals = N;
357         } else if (Cmp < 0) {
358             S->Left = N;
359         } else {
360             S->Right = N;
361         }
362         return N;
363     }
364
365     /* We did not find the entry and AllocNew is false. */
366     return 0;
367 }
368
369
370
371 SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, int AllocNew)
372 /* Find a new symbol table entry in the given table. If AllocNew is given and
373  * the entry is not found, create a new one. Return the entry found, or the
374  * new entry created, or - in case AllocNew is zero - return 0.
375  */
376 {
377     SymEntry* S;
378
379     /* Global symbol: Get the hash value for the name */
380     unsigned Hash = HashBuf (Name) % Scope->TableSlots;
381
382     /* Search for the entry */
383     int Cmp = SymSearchTree (Scope->Table[Hash], Name, &S);
384
385     /* If we found an entry, return it */
386     if (Cmp == 0) {
387         return S;
388     }
389
390     if (AllocNew) {
391
392         /* Otherwise create a new entry, insert and return it */
393         SymEntry* N = NewSymEntry (Name, SF_NONE);
394         N->Sym.Tab = Scope;
395         if (S == 0) {
396             Scope->Table[Hash] = N;
397         } else if (Cmp < 0) {
398             S->Left = N;
399         } else {
400             S->Right = N;
401         }
402         ++Scope->TableEntries;
403         return N;
404
405     }
406
407     /* We did not find the entry and AllocNew is false. */
408     return 0;
409 }
410
411
412
413 SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name)
414 /* Find a symbol in the given or any of its parent scopes. The function will
415  * never create a new symbol, since this can only be done in one specific
416  * scope.
417  */
418 {
419     SymEntry* Sym;
420     do {
421         /* Search in the current table */
422         Sym = SymFind (Scope, Name, SYM_FIND_EXISTING);
423         if (Sym) {
424             /* Found, return it */
425             break;
426         }
427
428         /* Not found, search in the parent scope, if we have one */
429         Scope = Scope->Parent;
430
431     } while (Sym == 0 && Scope != 0);
432
433     /* Return the result */
434     return Sym;
435 }
436
437
438
439 static void SymCheckUndefined (SymEntry* S)
440 /* Handle an undefined symbol */
441 {
442     /* Undefined symbol. It may be...
443      *
444      *   - An undefined symbol in a nested lexical level. In this
445      *     case, search for the symbol in the higher levels and
446      *     make the entry a trampoline entry if we find one.
447      *
448      *   - If the symbol is not found, it is a real undefined symbol.
449      *     If the AutoImport flag is set, make it an import. If the
450      *     AutoImport flag is not set, it's an error.
451      */
452     SymEntry* Sym = 0;
453     SymTable* Tab = GetSymParentScope (S);
454     while (Tab) {
455         Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING);
456         if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) {
457             /* We've found a symbol in a higher level that is
458              * either defined in the source, or an import.
459              */
460              break;
461         }
462         /* No matching symbol found in this level. Look further */
463         Tab = Tab->Parent;
464     }
465
466     if (Sym) {
467
468         /* We found the symbol in a higher level. Transfer the flags and
469          * address size from the local symbol to that in the higher level
470          * and check for problems.
471          */
472         if (S->Flags & SF_EXPORT) {
473             if (Sym->Flags & SF_IMPORT) {
474                 /* The symbol is already marked as import */
475                 LIError (&S->RefLines,
476                          "Symbol `%s' is already an import",
477                          GetString (Sym->Name));
478             }
479             if (Sym->Flags & SF_EXPORT) {
480                 /* The symbol is already marked as an export. */
481                 if (Sym->AddrSize > S->ExportSize) {
482                     /* We're exporting a symbol smaller than it actually is */
483                     LIWarning (&S->DefLines, 1,
484                                "Symbol `%m%p' is %s but exported %s",
485                               GetSymName (Sym),
486                               AddrSizeToStr (Sym->AddrSize),
487                               AddrSizeToStr (S->ExportSize));
488                 }
489             } else {
490                 /* Mark the symbol as an export */
491                 Sym->Flags |= SF_EXPORT;
492                 Sym->ExportSize = S->ExportSize;
493                 if (Sym->ExportSize == ADDR_SIZE_DEFAULT) {
494                     /* Use the actual size of the symbol */
495                     Sym->ExportSize = Sym->AddrSize;
496                 }
497                 if (Sym->AddrSize > Sym->ExportSize) {
498                     /* We're exporting a symbol smaller than it actually is */
499                     LIWarning (&S->DefLines, 1,
500                                "Symbol `%m%p' is %s but exported %s",
501                                GetSymName (Sym),
502                                AddrSizeToStr (Sym->AddrSize),
503                                AddrSizeToStr (Sym->ExportSize));
504                 }
505             }
506         }
507         if (S->Flags & SF_REFERENCED) {
508             /* Mark as referenced and move the line info */
509             Sym->Flags |= SF_REFERENCED;
510             CollTransfer (&Sym->RefLines, &S->RefLines);
511             CollDeleteAll (&S->RefLines);
512         }
513
514         /* Transfer all expression references */
515         SymTransferExprRefs (S, Sym);
516
517         /* Mark the symbol as unused removing all other flags */
518         S->Flags = SF_UNUSED;
519
520     } else {
521         /* The symbol is definitely undefined */
522         if (S->Flags & SF_EXPORT) {
523             /* We will not auto-import an export */
524             LIError (&S->RefLines,
525                      "Exported symbol `%m%p' was never defined",
526                      GetSymName (S));
527         } else {
528             if (AutoImport) {
529                 /* Mark as import, will be indexed later */
530                 S->Flags |= SF_IMPORT;
531                 /* Use the address size for code */
532                 S->AddrSize = CodeAddrSize;
533                 /* Mark point of import */
534                 GetFullLineInfo (&S->DefLines);
535             } else {
536                 /* Error */
537                 LIError (&S->RefLines,
538                          "Symbol `%m%p' is undefined",
539                          GetSymName (S));
540             }
541         }
542     }
543 }
544
545
546
547 void SymCheck (void)
548 /* Run through all symbols and check for anomalies and errors */
549 {
550     SymEntry* S;
551
552     /* Check for open scopes */
553     if (CurrentScope->Parent != 0) {
554         Error ("Local scope was not closed");
555     }
556
557     /* First pass: Walk through all symbols, checking for undefined's and
558      * changing them to trampoline symbols or make them imports.
559      */
560     S = SymList;
561     while (S) {
562         /* If the symbol is marked as global, mark it as export, if it is
563          * already defined, otherwise mark it as import.
564          */
565         if (S->Flags & SF_GLOBAL) {
566             if (S->Flags & SF_DEFINED) {
567                 SymExportFromGlobal (S);
568             } else {
569                 SymImportFromGlobal (S);
570             }
571         }
572
573         /* Handle undefined symbols */
574         if ((S->Flags & SF_UNDEFMASK) == SF_UNDEFVAL) {
575             /* This is an undefined symbol. Handle it. */
576             SymCheckUndefined (S);
577         }
578
579         /* Next symbol */
580         S = S->List;
581     }
582
583     /* Second pass: Walk again through the symbols. Count exports and imports
584      * and set address sizes where this has not happened before. Ignore
585      * undefined's, since we handled them in the last pass, and ignore unused
586      * symbols, since we handled them in the last pass, too.
587      */
588     S = SymList;
589     while (S) {
590         if ((S->Flags & SF_UNUSED) == 0 &&
591             (S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) {
592
593             /* Check for defined symbols that were never referenced */
594             if (IsSizeOfSymbol (S)) {
595                 /* Remove line infos, we don't need them any longer */
596                 ReleaseFullLineInfo (&S->DefLines);
597                 ReleaseFullLineInfo (&S->RefLines);
598             } else if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
599                 LIWarning (&S->DefLines, 2,
600                            "Symbol `%m%p' is defined but never used",
601                            GetSymName (S));
602             }
603
604             /* Assign an index to all imports */
605             if (S->Flags & SF_IMPORT) {
606                 if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
607                     /* Imported symbol is not referenced */
608                     LIWarning (&S->DefLines, 2,
609                                "Symbol `%m%p' is imported but never used",
610                                GetSymName (S));
611                 } else {
612                     /* Give the import an id, count imports */
613                     S->ImportId = ImportCount++;
614                 }
615             }
616
617             /* Count exports, assign the export ID */
618             if (S->Flags & SF_EXPORT) {
619                 S->ExportId = ExportCount++;
620             }
621
622             /* If the symbol is defined but has an unknown address size,
623              * recalculate it.
624              */
625             if (SymHasExpr (S) && S->AddrSize == ADDR_SIZE_DEFAULT) {
626                 ExprDesc ED;
627                 ED_Init (&ED);
628                 StudyExpr (S->Expr, &ED);
629                 S->AddrSize = ED.AddrSize;
630                 if (SymIsExport (S)) {
631                     if (S->ExportSize == ADDR_SIZE_DEFAULT) {
632                         /* Use the real export size */
633                         S->ExportSize = S->AddrSize;
634                     } else if (S->AddrSize > S->ExportSize) {
635                         /* We're exporting a symbol smaller than it actually is */
636                         LIWarning (&S->DefLines, 1,
637                                    "Symbol `%m%p' is %s but exported %s",
638                                    GetSymName (S),
639                                    AddrSizeToStr (S->AddrSize),
640                                    AddrSizeToStr (S->ExportSize));
641                     }
642                 }
643                 ED_Done (&ED);
644             }
645
646             /* If the address size of the symbol was guessed, check the guess
647              * against the actual address size and print a warning if the two
648              * differ.
649              */
650             if (S->AddrSize != ADDR_SIZE_DEFAULT) {
651                 /* Do we have data for this address size? */
652                 if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) {
653                     /* Get the file position where the symbol was used */
654                     const FilePos* P = S->GuessedUse[S->AddrSize - 1];
655                     if (P) {
656                         PWarning (P, 0,
657                                   "Didn't use %s addressing for `%m%p'",
658                                   AddrSizeToStr (S->AddrSize),
659                                   GetSymName (S));
660                     }
661                 }
662             }
663
664         }
665
666         /* Next symbol */
667         S = S->List;
668     }
669 }
670
671
672
673 void SymDump (FILE* F)
674 /* Dump the symbol table */
675 {
676     SymEntry* S = SymList;
677
678     while (S) {
679         /* Ignore unused symbols */
680         if ((S->Flags & SF_UNUSED) != 0) {
681             fprintf (F,
682                      "%m%-24p %s %s %s %s %s\n",
683                      GetSymName (S),
684                      (S->Flags & SF_DEFINED)? "DEF" : "---",
685                      (S->Flags & SF_REFERENCED)? "REF" : "---",
686                      (S->Flags & SF_IMPORT)? "IMP" : "---",
687                      (S->Flags & SF_EXPORT)? "EXP" : "---",
688                      AddrSizeToStr (S->AddrSize));
689         }
690         /* Next symbol */
691         S = S->List;
692     }
693 }
694
695
696
697 void WriteImports (void)
698 /* Write the imports list to the object file */
699 {
700     SymEntry* S;
701
702     /* Tell the object file module that we're about to start the imports */
703     ObjStartImports ();
704
705     /* Write the import count to the list */
706     ObjWriteVar (ImportCount);
707
708     /* Walk throught list and write all valid imports to the file. An import
709      * is considered valid, if it is either referenced, or the forced bit is
710      * set. Otherwise, the import is ignored (no need to link in something
711      * that isn't used).
712      */
713     S = SymList;
714     while (S) {
715         if ((S->Flags & (SF_UNUSED | SF_IMPORT)) == SF_IMPORT &&
716             (S->Flags & (SF_REFERENCED | SF_FORCED)) != 0) {
717
718             ObjWrite8 (S->AddrSize);
719             ObjWriteVar (S->Name);
720             WriteLineInfo (&S->DefLines);
721             WriteLineInfo (&S->RefLines);
722         }
723         S = S->List;
724     }
725
726     /* Done writing imports */
727     ObjEndImports ();
728 }
729
730
731
732 void WriteExports (void)
733 /* Write the exports list to the object file */
734 {
735     SymEntry* S;
736     unsigned Type;
737
738     /* Tell the object file module that we're about to start the exports */
739     ObjStartExports ();
740
741     /* Write the export count to the list */
742     ObjWriteVar (ExportCount);
743
744     /* Walk throught list and write all exports to the file */
745     S = SymList;
746     while (S) {
747         if ((S->Flags & (SF_UNUSED | SF_EXPORT)) == SF_EXPORT) {
748
749             /* Get the expression bits and the value */
750             long ConstVal;
751             unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
752
753             /* Check if this symbol has a size. If so, remember it in the
754              * flags.
755              */
756             long Size;
757             SymEntry* SizeSym = FindSizeOfSymbol (S);
758             if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
759                 SymFlags |= SYM_SIZE;
760             }
761
762             /* Count the number of ConDes types */
763             for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
764                 if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
765                     SYM_INC_CONDES_COUNT (SymFlags);
766                 }
767             }
768
769             /* Write the type and the export size */
770             ObjWriteVar (SymFlags);
771             ObjWrite8 (S->ExportSize);
772
773             /* Write any ConDes declarations */
774             if (SYM_GET_CONDES_COUNT (SymFlags) > 0) {
775                 for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
776                     unsigned char Prio = S->ConDesPrio[Type];
777                     if (Prio != CD_PRIO_NONE) {
778                         ObjWrite8 (CD_BUILD (Type, Prio));
779                     }
780                 }
781             }
782
783             /* Write the name */
784             ObjWriteVar (S->Name);
785
786             /* Write the value */
787             if (SYM_IS_CONST (SymFlags)) {
788                 /* Constant value */
789                 ObjWrite32 (ConstVal);
790             } else {
791                 /* Expression involved */
792                 WriteExpr (S->Expr);
793             }
794
795             /* If the symbol has a size, write it to the file */
796             if (SYM_HAS_SIZE (SymFlags)) {
797                 ObjWriteVar (Size);
798             }
799
800             /* Write the line infos */
801             WriteLineInfo (&S->DefLines);
802             WriteLineInfo (&S->RefLines);
803         }
804         S = S->List;
805     }
806
807     /* Done writing exports */
808     ObjEndExports ();
809 }
810
811
812
813 void WriteDbgSyms (void)
814 /* Write a list of all symbols to the object file */
815 {
816     unsigned Count;
817     SymEntry* S;
818
819     /* Tell the object file module that we're about to start the debug info */
820     ObjStartDbgSyms ();
821
822     /* Check if debug info is requested */
823     if (DbgSyms) {
824
825         /* Walk through the list, give each symbol an id and count them */
826         Count = 0;
827         S = SymList;
828         while (S) {
829             if (IsDbgSym (S)) {
830                 S->DebugSymId = Count++;
831             }
832             S = S->List;
833         }
834
835         /* Write the symbol count to the list */
836         ObjWriteVar (Count);
837
838         /* Walk through list and write all symbols to the file. Ignore size
839          * symbols.
840          */
841         S = SymList;
842         while (S) {
843             if (IsDbgSym (S)) {
844
845                 /* Get the expression bits and the value */
846                 long ConstVal;
847                 unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
848
849                 /* Check if this symbol has a size. If so, remember it in the
850                  * flags.
851                  */
852                 long Size;
853                 SymEntry* SizeSym = FindSizeOfSymbol (S);
854                 if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
855                     SymFlags |= SYM_SIZE;
856                 }
857
858                 /* Write the type */
859                 ObjWriteVar (SymFlags);
860
861                 /* Write the address size */
862                 ObjWrite8 (S->AddrSize);
863
864                 /* Write the id of the parent. For normal symbols, this is a
865                  * scope (symbol table), for cheap locals, it's a symbol.
866                  */
867                 if (SYM_IS_STD (SymFlags)) {
868                     ObjWriteVar (S->Sym.Tab->Id);
869                 } else {
870                     ObjWriteVar (S->Sym.Entry->DebugSymId);
871                 }
872
873                 /* Write the name */
874                 ObjWriteVar (S->Name);
875
876                 /* Write the value */
877                 if (SYM_IS_CONST (SymFlags)) {
878                     /* Constant value */
879                     ObjWrite32 (ConstVal);
880                 } else {
881                     /* Expression involved */
882                     WriteExpr (S->Expr);
883                 }
884
885                 /* If the symbol has a size, write it to the file */
886                 if (SYM_HAS_SIZE (SymFlags)) {
887                     ObjWriteVar (Size);
888                 }
889
890                 /* If the symbol is an im- or export, write out the ids */
891                 if (SYM_IS_IMPORT (SymFlags)) {
892                     ObjWriteVar (GetSymImportId (S));
893                 }
894                 if (SYM_IS_EXPORT (SymFlags)) {
895                     ObjWriteVar (GetSymExportId (S));
896                 }
897
898                 /* Write the line infos */
899                 WriteLineInfo (&S->DefLines);
900                 WriteLineInfo (&S->RefLines);
901             }
902             S = S->List;
903         }
904
905     } else {
906
907         /* No debug symbols */
908         ObjWriteVar (0);
909
910     }
911
912     /* Done writing debug symbols */
913     ObjEndDbgSyms ();
914 }
915
916
917
918 void WriteScopes (void)
919 /* Write the scope table to the object file */
920 {
921     /* Tell the object file module that we're about to start the scopes */
922     ObjStartScopes ();
923
924     /* We will write scopes only if debug symbols are requested */
925     if (DbgSyms) {
926
927         /* Get head of list */
928         SymTable* S = RootScope;
929
930         /* Write the scope count to the file */
931         ObjWriteVar (ScopeCount);
932
933         /* Walk through all scopes and write them to the file */
934         while (S) {
935
936             /* Flags for this scope */
937             unsigned Flags = 0;
938
939             /* Check if this scope has a size. If so, remember it in the
940              * flags.
941              */
942             long Size;
943             SymEntry* SizeSym = FindSizeOfScope (S);
944             if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
945                 Flags |= SCOPE_SIZE;
946             }
947
948             /* Check if the scope has a label */
949             if (S->Label) {
950                 Flags |= SCOPE_LABELED;
951             }
952
953             /* Scope must be defined */
954             CHECK (S->Type != SCOPE_UNDEF);
955
956             /* Id of parent scope */
957             if (S->Parent) {
958                 ObjWriteVar (S->Parent->Id);
959             } else {
960                 ObjWriteVar (0);
961             }
962
963             /* Lexical level */
964             ObjWriteVar (S->Level);
965
966             /* Scope flags */
967             ObjWriteVar (Flags);
968
969             /* Type of scope */
970             ObjWriteVar (S->Type);
971
972             /* Name of the scope */
973             ObjWriteVar (S->Name);
974
975             /* If the scope has a size, write it to the file */
976             if (SCOPE_HAS_SIZE (Flags)) {
977                 ObjWriteVar (Size);
978             }
979
980             /* If the scope has a label, write its id to the file */
981             if (SCOPE_HAS_LABEL (Flags)) {
982                 ObjWriteVar (S->Label->DebugSymId);
983             }
984
985             /* Spans for this scope */
986             WriteSpanList (&S->Spans);
987
988             /* Next scope */
989             S = S->Next;
990         }
991
992     } else {
993
994         /* No debug info requested */
995         ObjWriteVar (0);
996
997     }
998
999     /* Done writing the scopes */
1000     ObjEndScopes ();
1001 }
1002
1003
1004