]> git.sur5r.net Git - cc65/blob - src/ca65/symtab.c
atari: split color.s into bordercolor.s and bgcolor.s
[cc65] / src / ca65 / symtab.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 symtab.c                                  */
4 /*                                                                           */
5 /*                 Symbol table for the ca65 macroassembler                  */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2014, 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) == 0) {
509                 /* Mark the symbol as an export */
510                 Sym->Flags |= SF_EXPORT;
511                 Sym->ExportSize = S->ExportSize;
512                 if (Sym->ExportSize == ADDR_SIZE_DEFAULT) {
513                     /* Use the actual size of the symbol */
514                     Sym->ExportSize = Sym->AddrSize;
515                 }
516                 if (Sym->AddrSize > Sym->ExportSize) {
517                     /* We're exporting a symbol smaller than it actually is */
518                     LIWarning (&Sym->DefLines, 1,
519                                "Symbol '%m%p' is %s but exported %s",
520                                GetSymName (Sym),
521                                AddrSizeToStr (Sym->AddrSize),
522                                AddrSizeToStr (Sym->ExportSize));
523                 }
524             }
525         }
526         if (S->Flags & SF_REFERENCED) {
527             /* Mark as referenced and move the line info */
528             Sym->Flags |= SF_REFERENCED;
529             CollTransfer (&Sym->RefLines, &S->RefLines);
530             CollDeleteAll (&S->RefLines);
531         }
532
533         /* Transfer all expression references */
534         SymTransferExprRefs (S, Sym);
535
536         /* Mark the symbol as unused removing all other flags */
537         S->Flags = SF_UNUSED;
538
539     } else {
540         /* The symbol is definitely undefined */
541         if (S->Flags & SF_EXPORT) {
542             /* We will not auto-import an export */
543             LIError (&S->RefLines,
544                      "Exported symbol '%m%p' was never defined",
545                      GetSymName (S));
546         } else {
547             if (AutoImport) {
548                 /* Mark as import, will be indexed later */
549                 S->Flags |= SF_IMPORT;
550                 /* Use the address size for code */
551                 S->AddrSize = CodeAddrSize;
552                 /* Mark point of import */
553                 GetFullLineInfo (&S->DefLines);
554             } else {
555                 /* Error */
556                 LIError (&S->RefLines,
557                          "Symbol '%m%p' is undefined",
558                          GetSymName (S));
559             }
560         }
561     }
562 }
563
564
565
566 void SymCheck (void)
567 /* Run through all symbols and check for anomalies and errors */
568 {
569     SymEntry* S;
570
571     /* Check for open scopes */
572     if (CurrentScope->Parent != 0) {
573         Error ("Local scope was not closed");
574     }
575
576     /* First pass: Walk through all symbols, checking for undefined's and
577     ** changing them to trampoline symbols or make them imports.
578     */
579     S = SymList;
580     while (S) {
581         /* If the symbol is marked as global, mark it as export, if it is
582         ** already defined, otherwise mark it as import.
583         */
584         if (S->Flags & SF_GLOBAL) {
585             if (S->Flags & SF_DEFINED) {
586                 SymExportFromGlobal (S);
587             } else {
588                 SymImportFromGlobal (S);
589             }
590         }
591
592         /* Handle undefined symbols */
593         if ((S->Flags & SF_UNDEFMASK) == SF_UNDEFVAL) {
594             /* This is an undefined symbol. Handle it. */
595             SymCheckUndefined (S);
596         }
597
598         /* Next symbol */
599         S = S->List;
600     }
601
602     /* Second pass: Walk again through the symbols. Count exports and imports
603     ** and set address sizes where this has not happened before. Ignore
604     ** undefined's, since we handled them in the last pass, and ignore unused
605     ** symbols, since we handled them in the last pass, too.
606     */
607     S = SymList;
608     while (S) {
609         if ((S->Flags & SF_UNUSED) == 0 &&
610             (S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) {
611
612             /* Check for defined symbols that were never referenced */
613             if (IsSizeOfSymbol (S)) {
614                 /* Remove line infos, we don't need them any longer */
615                 ReleaseFullLineInfo (&S->DefLines);
616                 ReleaseFullLineInfo (&S->RefLines);
617             } else if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
618                 LIWarning (&S->DefLines, 2,
619                            "Symbol '%m%p' is defined but never used",
620                            GetSymName (S));
621             }
622
623             /* Assign an index to all imports */
624             if (S->Flags & SF_IMPORT) {
625                 if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
626                     /* Imported symbol is not referenced */
627                     LIWarning (&S->DefLines, 2,
628                                "Symbol '%m%p' is imported but never used",
629                                GetSymName (S));
630                 } else {
631                     /* Give the import an id, count imports */
632                     S->ImportId = ImportCount++;
633                 }
634             }
635
636             /* Count exports, assign the export ID */
637             if (S->Flags & SF_EXPORT) {
638                 S->ExportId = ExportCount++;
639             }
640
641             /* If the symbol is defined but has an unknown address size,
642             ** recalculate it.
643             */
644             if (SymHasExpr (S) && S->AddrSize == ADDR_SIZE_DEFAULT) {
645                 ExprDesc ED;
646                 ED_Init (&ED);
647                 StudyExpr (S->Expr, &ED);
648                 S->AddrSize = ED.AddrSize;
649                 if (SymIsExport (S)) {
650                     if (S->ExportSize == ADDR_SIZE_DEFAULT) {
651                         /* Use the real export size */
652                         S->ExportSize = S->AddrSize;
653                     } else if (S->AddrSize > S->ExportSize) {
654                         /* We're exporting a symbol smaller than it actually is */
655                         LIWarning (&S->DefLines, 1,
656                                    "Symbol '%m%p' is %s but exported %s",
657                                    GetSymName (S),
658                                    AddrSizeToStr (S->AddrSize),
659                                    AddrSizeToStr (S->ExportSize));
660                     }
661                 }
662                 ED_Done (&ED);
663             }
664
665             /* If the address size of the symbol was guessed, check the guess
666             ** against the actual address size and print a warning if the two
667             ** differ.
668             */
669             if (S->AddrSize != ADDR_SIZE_DEFAULT) {
670                 /* Do we have data for this address size? */
671                 if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) {
672                     /* Get the file position where the symbol was used */
673                     const FilePos* P = S->GuessedUse[S->AddrSize - 1];
674                     if (P) {
675                         PWarning (P, 0,
676                                   "Didn't use %s addressing for '%m%p'",
677                                   AddrSizeToStr (S->AddrSize),
678                                   GetSymName (S));
679                     }
680                 }
681             }
682
683         }
684
685         /* Next symbol */
686         S = S->List;
687     }
688 }
689
690
691
692 void SymDump (FILE* F)
693 /* Dump the symbol table */
694 {
695     SymEntry* S = SymList;
696
697     while (S) {
698         /* Ignore unused symbols */
699         if ((S->Flags & SF_UNUSED) == 0) {
700             fprintf (F,
701                      "%-24s %s %s %s %s %s\n",
702                      SB_GetConstBuf (GetSymName (S)),
703                      (S->Flags & SF_DEFINED)? "DEF" : "---",
704                      (S->Flags & SF_REFERENCED)? "REF" : "---",
705                      (S->Flags & SF_IMPORT)? "IMP" : "---",
706                      (S->Flags & SF_EXPORT)? "EXP" : "---",
707                      AddrSizeToStr (S->AddrSize));
708         }
709         /* Next symbol */
710         S = S->List;
711     }
712 }
713
714
715
716 void WriteImports (void)
717 /* Write the imports list to the object file */
718 {
719     SymEntry* S;
720
721     /* Tell the object file module that we're about to start the imports */
722     ObjStartImports ();
723
724     /* Write the import count to the list */
725     ObjWriteVar (ImportCount);
726
727     /* Walk throught list and write all valid imports to the file. An import
728     ** is considered valid, if it is either referenced, or the forced bit is
729     ** set. Otherwise, the import is ignored (no need to link in something
730     ** that isn't used).
731     */
732     S = SymList;
733     while (S) {
734         if ((S->Flags & (SF_UNUSED | SF_IMPORT)) == SF_IMPORT &&
735             (S->Flags & (SF_REFERENCED | SF_FORCED)) != 0) {
736
737             ObjWrite8 (S->AddrSize);
738             ObjWriteVar (S->Name);
739             WriteLineInfo (&S->DefLines);
740             WriteLineInfo (&S->RefLines);
741         }
742         S = S->List;
743     }
744
745     /* Done writing imports */
746     ObjEndImports ();
747 }
748
749
750
751 void WriteExports (void)
752 /* Write the exports list to the object file */
753 {
754     SymEntry* S;
755     unsigned Type;
756
757     /* Tell the object file module that we're about to start the exports */
758     ObjStartExports ();
759
760     /* Write the export count to the list */
761     ObjWriteVar (ExportCount);
762
763     /* Walk throught list and write all exports to the file */
764     S = SymList;
765     while (S) {
766         if ((S->Flags & (SF_UNUSED | SF_EXPORT)) == SF_EXPORT) {
767
768             /* Get the expression bits and the value */
769             long ConstVal;
770             unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
771
772             /* Check if this symbol has a size. If so, remember it in the
773             ** flags.
774             */
775             long Size;
776             SymEntry* SizeSym = FindSizeOfSymbol (S);
777             if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
778                 SymFlags |= SYM_SIZE;
779             }
780
781             /* Count the number of ConDes types */
782             for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
783                 if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
784                     SYM_INC_CONDES_COUNT (SymFlags);
785                 }
786             }
787
788             /* Write the type and the export size */
789             ObjWriteVar (SymFlags);
790             ObjWrite8 (S->ExportSize);
791
792             /* Write any ConDes declarations */
793             if (SYM_GET_CONDES_COUNT (SymFlags) > 0) {
794                 for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
795                     unsigned char Prio = S->ConDesPrio[Type];
796                     if (Prio != CD_PRIO_NONE) {
797                         ObjWrite8 (CD_BUILD (Type, Prio));
798                     }
799                 }
800             }
801
802             /* Write the name */
803             ObjWriteVar (S->Name);
804
805             /* Write the value */
806             if (SYM_IS_CONST (SymFlags)) {
807                 /* Constant value */
808                 ObjWrite32 (ConstVal);
809             } else {
810                 /* Expression involved */
811                 WriteExpr (S->Expr);
812             }
813
814             /* If the symbol has a size, write it to the file */
815             if (SYM_HAS_SIZE (SymFlags)) {
816                 ObjWriteVar (Size);
817             }
818
819             /* Write the line infos */
820             WriteLineInfo (&S->DefLines);
821             WriteLineInfo (&S->RefLines);
822         }
823         S = S->List;
824     }
825
826     /* Done writing exports */
827     ObjEndExports ();
828 }
829
830
831
832 void WriteDbgSyms (void)
833 /* Write a list of all symbols to the object file */
834 {
835     unsigned Count;
836     SymEntry* S;
837
838     /* Tell the object file module that we're about to start the debug info */
839     ObjStartDbgSyms ();
840
841     /* Check if debug info is requested */
842     if (DbgSyms) {
843
844         /* Walk through the list, give each symbol an id and count them */
845         Count = 0;
846         S = SymList;
847         while (S) {
848             if (IsDbgSym (S)) {
849                 S->DebugSymId = Count++;
850             }
851             S = S->List;
852         }
853
854         /* Write the symbol count to the list */
855         ObjWriteVar (Count);
856
857         /* Walk through list and write all symbols to the file. Ignore size
858         ** symbols.
859         */
860         S = SymList;
861         while (S) {
862             if (IsDbgSym (S)) {
863
864                 /* Get the expression bits and the value */
865                 long ConstVal;
866                 unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
867
868                 /* Check if this symbol has a size. If so, remember it in the
869                 ** flags.
870                 */
871                 long Size;
872                 SymEntry* SizeSym = FindSizeOfSymbol (S);
873                 if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
874                     SymFlags |= SYM_SIZE;
875                 }
876
877                 /* Write the type */
878                 ObjWriteVar (SymFlags);
879
880                 /* Write the address size */
881                 ObjWrite8 (S->AddrSize);
882
883                 /* Write the id of the parent. For normal symbols, this is a
884                 ** scope (symbol table), for cheap locals, it's a symbol.
885                 */
886                 if (SYM_IS_STD (SymFlags)) {
887                     ObjWriteVar (S->Sym.Tab->Id);
888                 } else {
889                     ObjWriteVar (S->Sym.Entry->DebugSymId);
890                 }
891
892                 /* Write the name */
893                 ObjWriteVar (S->Name);
894
895                 /* Write the value */
896                 if (SYM_IS_CONST (SymFlags)) {
897                     /* Constant value */
898                     ObjWrite32 (ConstVal);
899                 } else {
900                     /* Expression involved */
901                     WriteExpr (S->Expr);
902                 }
903
904                 /* If the symbol has a size, write it to the file */
905                 if (SYM_HAS_SIZE (SymFlags)) {
906                     ObjWriteVar (Size);
907                 }
908
909                 /* If the symbol is an im- or export, write out the ids */
910                 if (SYM_IS_IMPORT (SymFlags)) {
911                     ObjWriteVar (GetSymImportId (S));
912                 }
913                 if (SYM_IS_EXPORT (SymFlags)) {
914                     ObjWriteVar (GetSymExportId (S));
915                 }
916
917                 /* Write the line infos */
918                 WriteLineInfo (&S->DefLines);
919                 WriteLineInfo (&S->RefLines);
920             }
921             S = S->List;
922         }
923
924     } else {
925
926         /* No debug symbols */
927         ObjWriteVar (0);
928
929     }
930
931     /* Write the high level symbols */
932     WriteHLLDbgSyms ();
933
934     /* Done writing debug symbols */
935     ObjEndDbgSyms ();
936 }
937
938
939
940 void WriteScopes (void)
941 /* Write the scope table to the object file */
942 {
943     /* Tell the object file module that we're about to start the scopes */
944     ObjStartScopes ();
945
946     /* We will write scopes only if debug symbols are requested */
947     if (DbgSyms) {
948
949         /* Get head of list */
950         SymTable* S = RootScope;
951
952         /* Write the scope count to the file */
953         ObjWriteVar (ScopeCount);
954
955         /* Walk through all scopes and write them to the file */
956         while (S) {
957
958             /* Flags for this scope */
959             unsigned Flags = 0;
960
961             /* Check if this scope has a size. If so, remember it in the
962             ** flags.
963             */
964             long Size;
965             SymEntry* SizeSym = FindSizeOfScope (S);
966             if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
967                 Flags |= SCOPE_SIZE;
968             }
969
970             /* Check if the scope has a label */
971             if (S->Label) {
972                 Flags |= SCOPE_LABELED;
973             }
974
975             /* Scope must be defined */
976             CHECK (S->Type != SCOPE_UNDEF);
977
978             /* Id of parent scope */
979             if (S->Parent) {
980                 ObjWriteVar (S->Parent->Id);
981             } else {
982                 ObjWriteVar (0);
983             }
984
985             /* Lexical level */
986             ObjWriteVar (S->Level);
987
988             /* Scope flags */
989             ObjWriteVar (Flags);
990
991             /* Type of scope */
992             ObjWriteVar (S->Type);
993
994             /* Name of the scope */
995             ObjWriteVar (S->Name);
996
997             /* If the scope has a size, write it to the file */
998             if (SCOPE_HAS_SIZE (Flags)) {
999                 ObjWriteVar (Size);
1000             }
1001
1002             /* If the scope has a label, write its id to the file */
1003             if (SCOPE_HAS_LABEL (Flags)) {
1004                 ObjWriteVar (S->Label->DebugSymId);
1005             }
1006
1007             /* Spans for this scope */
1008             WriteSpanList (&S->Spans);
1009
1010             /* Next scope */
1011             S = S->Next;
1012         }
1013
1014     } else {
1015
1016         /* No debug info requested */
1017         ObjWriteVar (0);
1018
1019     }
1020
1021     /* Done writing the scopes */
1022     ObjEndScopes ();
1023 }