]> git.sur5r.net Git - cc65/blob - src/ca65/symtab.c
Normalized code.
[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, SymFindAction Action)
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 && (Action & SYM_ALLOC_NEW) != 0) {
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, SymFindAction Action)
327 /* Find a cheap local symbol. If Action contains SYM_ALLOC_NEW and the entry is
328  * not found, create a new one. Return the entry found, or the new entry
329  * created, or - in case Action is SYM_FIND_EXISTING - return 0.
330  */
331
332 {
333     SymEntry* S;
334     int Cmp;
335
336     /* Local symbol, get the table */
337     if (!Parent) {
338         /* No last global, so there's no local table */
339         Error ("No preceeding global symbol");
340         if (Action & SYM_ALLOC_NEW) {
341             return NewSymEntry (Name, SF_LOCAL);
342         } else {
343             return 0;
344         }
345     }
346
347     /* Search for the symbol if we have a table */
348     Cmp = SymSearchTree (Parent->Locals, Name, &S);
349
350     /* If we found an entry, return it */
351     if (Cmp == 0) {
352         return S;
353     }
354
355     if (Action & SYM_ALLOC_NEW) {
356
357         /* Otherwise create a new entry, insert and return it */
358         SymEntry* N = NewSymEntry (Name, SF_LOCAL);
359         N->Sym.Entry = Parent;
360         if (S == 0) {
361             Parent->Locals = N;
362         } else if (Cmp < 0) {
363             S->Left = N;
364         } else {
365             S->Right = N;
366         }
367         return N;
368     }
369
370     /* We did not find the entry and AllocNew is false. */
371     return 0;
372 }
373
374
375
376 SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action)
377 /* Find a new symbol table entry in the given table. If Action contains
378  * SYM_ALLOC_NEW and the entry is not found, create a new one. Return the
379  * entry found, or the new entry created, or - in case Action is
380  * SYM_FIND_EXISTING - return 0.
381  */
382 {
383     SymEntry* S;
384
385     /* Global symbol: Get the hash value for the name */
386     unsigned Hash = HashBuf (Name) % Scope->TableSlots;
387
388     /* Search for the entry */
389     int Cmp = SymSearchTree (Scope->Table[Hash], Name, &S);
390
391     /* If we found an entry, return it */
392     if (Cmp == 0) {
393         if ((Action & SYM_CHECK_ONLY) == 0 && SymTabIsClosed (Scope)) {
394             S->Flags |= SF_FIXED;
395         }
396         return S;
397     }
398
399     if (Action & SYM_ALLOC_NEW) {
400
401         /* Otherwise create a new entry, insert and return it. If the scope is
402          * already closed, mark the symbol as fixed so it won't be resolved
403          * by a symbol in the enclosing scopes later.
404          */
405         SymEntry* N = NewSymEntry (Name, SF_NONE);
406         if (SymTabIsClosed (Scope)) {
407             N->Flags |= SF_FIXED;
408         }
409         N->Sym.Tab = Scope;
410         if (S == 0) {
411             Scope->Table[Hash] = N;
412         } else if (Cmp < 0) {
413             S->Left = N;
414         } else {
415             S->Right = N;
416         }
417         ++Scope->TableEntries;
418         return N;
419
420     }
421
422     /* We did not find the entry and AllocNew is false. */
423     return 0;
424 }
425
426
427
428 SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name)
429 /* Find a symbol in the given or any of its parent scopes. The function will
430  * never create a new symbol, since this can only be done in one specific
431  * scope.
432  */
433 {
434     /* Generate the name hash */
435     unsigned Hash = HashBuf (Name);
436
437     /* Search for the symbol */
438     SymEntry* Sym;
439     do {
440         /* Search in the current table. Ignore entries flagged with SF_UNUSED,
441          * because for such symbols there is a real entry in one of the parent
442          * scopes.
443          */
444         if (SymSearchTree (Scope->Table[Hash % Scope->TableSlots], Name, &Sym) == 0) {
445             if (Sym->Flags & SF_UNUSED) {
446                 Sym = 0;
447             } else {
448                 /* Found, return it */
449                 break;
450             }
451         } else {
452             Sym = 0;
453         }
454
455         /* Not found, search in the parent scope, if we have one */
456         Scope = Scope->Parent;
457
458     } while (Sym == 0 && Scope != 0);
459
460     /* Return the result */
461     return Sym;
462 }
463
464
465
466 static void SymCheckUndefined (SymEntry* S)
467 /* Handle an undefined symbol */
468 {
469     /* Undefined symbol. It may be...
470      *
471      *   - An undefined symbol in a nested lexical level. If the symbol is not
472      *     fixed to this level, search for the symbol in the higher levels and
473      *     make the entry a trampoline entry if we find one.
474      *
475      *   - If the symbol is not found, it is a real undefined symbol. If the
476      *     AutoImport flag is set, make it an import. If the AutoImport flag is
477      *     not set, it's an error.
478      */
479     SymEntry* Sym = 0;
480     if ((S->Flags & SF_FIXED) == 0) {
481         SymTable* Tab = GetSymParentScope (S);
482         while (Tab) {
483             Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING | SYM_CHECK_ONLY);
484             if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) {
485                 /* We've found a symbol in a higher level that is
486                  * either defined in the source, or an import.
487                  */
488                  break;
489             }
490             /* No matching symbol found in this level. Look further */
491             Tab = Tab->Parent;
492         }
493     }
494
495     if (Sym) {
496
497         /* We found the symbol in a higher level. Transfer the flags and
498          * address size from the local symbol to that in the higher level
499          * and check for problems.
500          */
501         if (S->Flags & SF_EXPORT) {
502             if (Sym->Flags & SF_IMPORT) {
503                 /* The symbol is already marked as import */
504                 LIError (&S->RefLines,
505                          "Symbol `%s' is already an import",
506                          GetString (Sym->Name));
507             }
508             if (Sym->Flags & SF_EXPORT) {
509                 /* The symbol is already marked as an export. */
510                 if (Sym->AddrSize > S->ExportSize) {
511                     /* We're exporting a symbol smaller than it actually is */
512                     LIWarning (&S->DefLines, 1,
513                                "Symbol `%m%p' is %s but exported %s",
514                               GetSymName (Sym),
515                               AddrSizeToStr (Sym->AddrSize),
516                               AddrSizeToStr (S->ExportSize));
517                 }
518             } else {
519                 /* Mark the symbol as an export */
520                 Sym->Flags |= SF_EXPORT;
521                 Sym->ExportSize = S->ExportSize;
522                 if (Sym->ExportSize == ADDR_SIZE_DEFAULT) {
523                     /* Use the actual size of the symbol */
524                     Sym->ExportSize = Sym->AddrSize;
525                 }
526                 if (Sym->AddrSize > Sym->ExportSize) {
527                     /* We're exporting a symbol smaller than it actually is */
528                     LIWarning (&S->DefLines, 1,
529                                "Symbol `%m%p' is %s but exported %s",
530                                GetSymName (Sym),
531                                AddrSizeToStr (Sym->AddrSize),
532                                AddrSizeToStr (Sym->ExportSize));
533                 }
534             }
535         }
536         if (S->Flags & SF_REFERENCED) {
537             /* Mark as referenced and move the line info */
538             Sym->Flags |= SF_REFERENCED;
539             CollTransfer (&Sym->RefLines, &S->RefLines);
540             CollDeleteAll (&S->RefLines);
541         }
542
543         /* Transfer all expression references */
544         SymTransferExprRefs (S, Sym);
545
546         /* Mark the symbol as unused removing all other flags */
547         S->Flags = SF_UNUSED;
548
549     } else {
550         /* The symbol is definitely undefined */
551         if (S->Flags & SF_EXPORT) {
552             /* We will not auto-import an export */
553             LIError (&S->RefLines,
554                      "Exported symbol `%m%p' was never defined",
555                      GetSymName (S));
556         } else {
557             if (AutoImport) {
558                 /* Mark as import, will be indexed later */
559                 S->Flags |= SF_IMPORT;
560                 /* Use the address size for code */
561                 S->AddrSize = CodeAddrSize;
562                 /* Mark point of import */
563                 GetFullLineInfo (&S->DefLines);
564             } else {
565                 /* Error */
566                 LIError (&S->RefLines,
567                          "Symbol `%m%p' is undefined",
568                          GetSymName (S));
569             }
570         }
571     }
572 }
573
574
575
576 void SymCheck (void)
577 /* Run through all symbols and check for anomalies and errors */
578 {
579     SymEntry* S;
580
581     /* Check for open scopes */
582     if (CurrentScope->Parent != 0) {
583         Error ("Local scope was not closed");
584     }
585
586     /* First pass: Walk through all symbols, checking for undefined's and
587      * changing them to trampoline symbols or make them imports.
588      */
589     S = SymList;
590     while (S) {
591         /* If the symbol is marked as global, mark it as export, if it is
592          * already defined, otherwise mark it as import.
593          */
594         if (S->Flags & SF_GLOBAL) {
595             if (S->Flags & SF_DEFINED) {
596                 SymExportFromGlobal (S);
597             } else {
598                 SymImportFromGlobal (S);
599             }
600         }
601
602         /* Handle undefined symbols */
603         if ((S->Flags & SF_UNDEFMASK) == SF_UNDEFVAL) {
604             /* This is an undefined symbol. Handle it. */
605             SymCheckUndefined (S);
606         }
607
608         /* Next symbol */
609         S = S->List;
610     }
611
612     /* Second pass: Walk again through the symbols. Count exports and imports
613      * and set address sizes where this has not happened before. Ignore
614      * undefined's, since we handled them in the last pass, and ignore unused
615      * symbols, since we handled them in the last pass, too.
616      */
617     S = SymList;
618     while (S) {
619         if ((S->Flags & SF_UNUSED) == 0 &&
620             (S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) {
621
622             /* Check for defined symbols that were never referenced */
623             if (IsSizeOfSymbol (S)) {
624                 /* Remove line infos, we don't need them any longer */
625                 ReleaseFullLineInfo (&S->DefLines);
626                 ReleaseFullLineInfo (&S->RefLines);
627             } else if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
628                 LIWarning (&S->DefLines, 2,
629                            "Symbol `%m%p' is defined but never used",
630                            GetSymName (S));
631             }
632
633             /* Assign an index to all imports */
634             if (S->Flags & SF_IMPORT) {
635                 if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
636                     /* Imported symbol is not referenced */
637                     LIWarning (&S->DefLines, 2,
638                                "Symbol `%m%p' is imported but never used",
639                                GetSymName (S));
640                 } else {
641                     /* Give the import an id, count imports */
642                     S->ImportId = ImportCount++;
643                 }
644             }
645
646             /* Count exports, assign the export ID */
647             if (S->Flags & SF_EXPORT) {
648                 S->ExportId = ExportCount++;
649             }
650
651             /* If the symbol is defined but has an unknown address size,
652              * recalculate it.
653              */
654             if (SymHasExpr (S) && S->AddrSize == ADDR_SIZE_DEFAULT) {
655                 ExprDesc ED;
656                 ED_Init (&ED);
657                 StudyExpr (S->Expr, &ED);
658                 S->AddrSize = ED.AddrSize;
659                 if (SymIsExport (S)) {
660                     if (S->ExportSize == ADDR_SIZE_DEFAULT) {
661                         /* Use the real export size */
662                         S->ExportSize = S->AddrSize;
663                     } else if (S->AddrSize > S->ExportSize) {
664                         /* We're exporting a symbol smaller than it actually is */
665                         LIWarning (&S->DefLines, 1,
666                                    "Symbol `%m%p' is %s but exported %s",
667                                    GetSymName (S),
668                                    AddrSizeToStr (S->AddrSize),
669                                    AddrSizeToStr (S->ExportSize));
670                     }
671                 }
672                 ED_Done (&ED);
673             }
674
675             /* If the address size of the symbol was guessed, check the guess
676              * against the actual address size and print a warning if the two
677              * differ.
678              */
679             if (S->AddrSize != ADDR_SIZE_DEFAULT) {
680                 /* Do we have data for this address size? */
681                 if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) {
682                     /* Get the file position where the symbol was used */
683                     const FilePos* P = S->GuessedUse[S->AddrSize - 1];
684                     if (P) {
685                         PWarning (P, 0,
686                                   "Didn't use %s addressing for `%m%p'",
687                                   AddrSizeToStr (S->AddrSize),
688                                   GetSymName (S));
689                     }
690                 }
691             }
692
693         }
694
695         /* Next symbol */
696         S = S->List;
697     }
698 }
699
700
701
702 void SymDump (FILE* F)
703 /* Dump the symbol table */
704 {
705     SymEntry* S = SymList;
706
707     while (S) {
708         /* Ignore unused symbols */
709         if ((S->Flags & SF_UNUSED) != 0) {
710             fprintf (F,
711                      "%m%-24p %s %s %s %s %s\n",
712                      GetSymName (S),
713                      (S->Flags & SF_DEFINED)? "DEF" : "---",
714                      (S->Flags & SF_REFERENCED)? "REF" : "---",
715                      (S->Flags & SF_IMPORT)? "IMP" : "---",
716                      (S->Flags & SF_EXPORT)? "EXP" : "---",
717                      AddrSizeToStr (S->AddrSize));
718         }
719         /* Next symbol */
720         S = S->List;
721     }
722 }
723
724
725
726 void WriteImports (void)
727 /* Write the imports list to the object file */
728 {
729     SymEntry* S;
730
731     /* Tell the object file module that we're about to start the imports */
732     ObjStartImports ();
733
734     /* Write the import count to the list */
735     ObjWriteVar (ImportCount);
736
737     /* Walk throught list and write all valid imports to the file. An import
738      * is considered valid, if it is either referenced, or the forced bit is
739      * set. Otherwise, the import is ignored (no need to link in something
740      * that isn't used).
741      */
742     S = SymList;
743     while (S) {
744         if ((S->Flags & (SF_UNUSED | SF_IMPORT)) == SF_IMPORT &&
745             (S->Flags & (SF_REFERENCED | SF_FORCED)) != 0) {
746
747             ObjWrite8 (S->AddrSize);
748             ObjWriteVar (S->Name);
749             WriteLineInfo (&S->DefLines);
750             WriteLineInfo (&S->RefLines);
751         }
752         S = S->List;
753     }
754
755     /* Done writing imports */
756     ObjEndImports ();
757 }
758
759
760
761 void WriteExports (void)
762 /* Write the exports list to the object file */
763 {
764     SymEntry* S;
765     unsigned Type;
766
767     /* Tell the object file module that we're about to start the exports */
768     ObjStartExports ();
769
770     /* Write the export count to the list */
771     ObjWriteVar (ExportCount);
772
773     /* Walk throught list and write all exports to the file */
774     S = SymList;
775     while (S) {
776         if ((S->Flags & (SF_UNUSED | SF_EXPORT)) == SF_EXPORT) {
777
778             /* Get the expression bits and the value */
779             long ConstVal;
780             unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
781
782             /* Check if this symbol has a size. If so, remember it in the
783              * flags.
784              */
785             long Size;
786             SymEntry* SizeSym = FindSizeOfSymbol (S);
787             if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
788                 SymFlags |= SYM_SIZE;
789             }
790
791             /* Count the number of ConDes types */
792             for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
793                 if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
794                     SYM_INC_CONDES_COUNT (SymFlags);
795                 }
796             }
797
798             /* Write the type and the export size */
799             ObjWriteVar (SymFlags);
800             ObjWrite8 (S->ExportSize);
801
802             /* Write any ConDes declarations */
803             if (SYM_GET_CONDES_COUNT (SymFlags) > 0) {
804                 for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
805                     unsigned char Prio = S->ConDesPrio[Type];
806                     if (Prio != CD_PRIO_NONE) {
807                         ObjWrite8 (CD_BUILD (Type, Prio));
808                     }
809                 }
810             }
811
812             /* Write the name */
813             ObjWriteVar (S->Name);
814
815             /* Write the value */
816             if (SYM_IS_CONST (SymFlags)) {
817                 /* Constant value */
818                 ObjWrite32 (ConstVal);
819             } else {
820                 /* Expression involved */
821                 WriteExpr (S->Expr);
822             }
823
824             /* If the symbol has a size, write it to the file */
825             if (SYM_HAS_SIZE (SymFlags)) {
826                 ObjWriteVar (Size);
827             }
828
829             /* Write the line infos */
830             WriteLineInfo (&S->DefLines);
831             WriteLineInfo (&S->RefLines);
832         }
833         S = S->List;
834     }
835
836     /* Done writing exports */
837     ObjEndExports ();
838 }
839
840
841
842 void WriteDbgSyms (void)
843 /* Write a list of all symbols to the object file */
844 {
845     unsigned Count;
846     SymEntry* S;
847
848     /* Tell the object file module that we're about to start the debug info */
849     ObjStartDbgSyms ();
850
851     /* Check if debug info is requested */
852     if (DbgSyms) {
853
854         /* Walk through the list, give each symbol an id and count them */
855         Count = 0;
856         S = SymList;
857         while (S) {
858             if (IsDbgSym (S)) {
859                 S->DebugSymId = Count++;
860             }
861             S = S->List;
862         }
863
864         /* Write the symbol count to the list */
865         ObjWriteVar (Count);
866
867         /* Walk through list and write all symbols to the file. Ignore size
868          * symbols.
869          */
870         S = SymList;
871         while (S) {
872             if (IsDbgSym (S)) {
873
874                 /* Get the expression bits and the value */
875                 long ConstVal;
876                 unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
877
878                 /* Check if this symbol has a size. If so, remember it in the
879                  * flags.
880                  */
881                 long Size;
882                 SymEntry* SizeSym = FindSizeOfSymbol (S);
883                 if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
884                     SymFlags |= SYM_SIZE;
885                 }
886
887                 /* Write the type */
888                 ObjWriteVar (SymFlags);
889
890                 /* Write the address size */
891                 ObjWrite8 (S->AddrSize);
892
893                 /* Write the id of the parent. For normal symbols, this is a
894                  * scope (symbol table), for cheap locals, it's a symbol.
895                  */
896                 if (SYM_IS_STD (SymFlags)) {
897                     ObjWriteVar (S->Sym.Tab->Id);
898                 } else {
899                     ObjWriteVar (S->Sym.Entry->DebugSymId);
900                 }
901
902                 /* Write the name */
903                 ObjWriteVar (S->Name);
904
905                 /* Write the value */
906                 if (SYM_IS_CONST (SymFlags)) {
907                     /* Constant value */
908                     ObjWrite32 (ConstVal);
909                 } else {
910                     /* Expression involved */
911                     WriteExpr (S->Expr);
912                 }
913
914                 /* If the symbol has a size, write it to the file */
915                 if (SYM_HAS_SIZE (SymFlags)) {
916                     ObjWriteVar (Size);
917                 }
918
919                 /* If the symbol is an im- or export, write out the ids */
920                 if (SYM_IS_IMPORT (SymFlags)) {
921                     ObjWriteVar (GetSymImportId (S));
922                 }
923                 if (SYM_IS_EXPORT (SymFlags)) {
924                     ObjWriteVar (GetSymExportId (S));
925                 }
926
927                 /* Write the line infos */
928                 WriteLineInfo (&S->DefLines);
929                 WriteLineInfo (&S->RefLines);
930             }
931             S = S->List;
932         }
933
934     } else {
935
936         /* No debug symbols */
937         ObjWriteVar (0);
938
939     }
940
941     /* Write the high level symbols */
942     WriteHLLDbgSyms ();
943
944     /* Done writing debug symbols */
945     ObjEndDbgSyms ();
946 }
947
948
949
950 void WriteScopes (void)
951 /* Write the scope table to the object file */
952 {
953     /* Tell the object file module that we're about to start the scopes */
954     ObjStartScopes ();
955
956     /* We will write scopes only if debug symbols are requested */
957     if (DbgSyms) {
958
959         /* Get head of list */
960         SymTable* S = RootScope;
961
962         /* Write the scope count to the file */
963         ObjWriteVar (ScopeCount);
964
965         /* Walk through all scopes and write them to the file */
966         while (S) {
967
968             /* Flags for this scope */
969             unsigned Flags = 0;
970
971             /* Check if this scope has a size. If so, remember it in the
972              * flags.
973              */
974             long Size;
975             SymEntry* SizeSym = FindSizeOfScope (S);
976             if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
977                 Flags |= SCOPE_SIZE;
978             }
979
980             /* Check if the scope has a label */
981             if (S->Label) {
982                 Flags |= SCOPE_LABELED;
983             }
984
985             /* Scope must be defined */
986             CHECK (S->Type != SCOPE_UNDEF);
987
988             /* Id of parent scope */
989             if (S->Parent) {
990                 ObjWriteVar (S->Parent->Id);
991             } else {
992                 ObjWriteVar (0);
993             }
994
995             /* Lexical level */
996             ObjWriteVar (S->Level);
997
998             /* Scope flags */
999             ObjWriteVar (Flags);
1000
1001             /* Type of scope */
1002             ObjWriteVar (S->Type);
1003
1004             /* Name of the scope */
1005             ObjWriteVar (S->Name);
1006
1007             /* If the scope has a size, write it to the file */
1008             if (SCOPE_HAS_SIZE (Flags)) {
1009                 ObjWriteVar (Size);
1010             }
1011
1012             /* If the scope has a label, write its id to the file */
1013             if (SCOPE_HAS_LABEL (Flags)) {
1014                 ObjWriteVar (S->Label->DebugSymId);
1015             }
1016
1017             /* Spans for this scope */
1018             WriteSpanList (&S->Spans);
1019
1020             /* Next scope */
1021             S = S->Next;
1022         }
1023
1024     } else {
1025
1026         /* No debug info requested */
1027         ObjWriteVar (0);
1028
1029     }
1030
1031     /* Done writing the scopes */
1032     ObjEndScopes ();
1033 }