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