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 */
74SymTable* CurrentScope = 0; /* Pointer to current symbol table */
75SymTable* RootScope = 0; /* Root symbol table */
76static SymTable* LastScope = 0; /* Pointer to last scope in list */
77static unsigned ScopeCount = 0; /* Number of scopes */
78
79/* Symbol table variables */
80static unsigned ImportCount = 0; /* Counter for import symbols */
81static unsigned ExportCount = 0; /* Counter for export symbols */
82
83
84
85/*****************************************************************************/
86/* Internally used functions */
87/*****************************************************************************/
88
89
90
91static 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
105static 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
117static 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
199void 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
245void 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
278SymTable* 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
305SymTable* 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
326SymEntry* 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
376SymEntry* 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
428SymEntry* 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
466static 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
566void 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
692void 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
716void 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
751void 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
832void 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
940void 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}
1024