1 /*****************************************************************************/
5 /* Symbol table for the ca65 macroassembler */
9 /* (C) 1998-2011, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
43 #include "scopedefs.h"
57 #include "studyexpr.h"
62 /*****************************************************************************/
64 /*****************************************************************************/
68 /* Combined symbol entry flags used within this module */
69 #define SF_UNDEFMASK (SF_REFERENCED | SF_DEFINED | SF_IMPORT)
70 #define SF_UNDEFVAL (SF_REFERENCED)
73 SymTable* CurrentScope = 0; /* Pointer to current symbol table */
74 SymTable* RootScope = 0; /* Root symbol table */
75 static SymTable* LastScope = 0; /* Pointer to last scope in list */
76 static unsigned ScopeCount = 0; /* Number of scopes */
78 /* Symbol table variables */
79 static unsigned ImportCount = 0; /* Counter for import symbols */
80 static unsigned ExportCount = 0; /* Counter for export symbols */
84 /*****************************************************************************/
85 /* Internally used functions */
86 /*****************************************************************************/
90 static int IsDbgSym (const SymEntry* S)
91 /* Return true if this is a debug symbol */
93 if ((S->Flags & (SF_DEFINED | SF_UNUSED)) == SF_DEFINED) {
94 /* Defined symbols are debug symbols if they aren't sizes */
95 return !IsSizeOfSymbol (S);
97 /* Others are debug symbols if they're referenced imports */
98 return ((S->Flags & SF_REFIMP) == SF_REFIMP);
104 static unsigned ScopeTableSize (unsigned Level)
105 /* Get the size of a table for the given lexical level */
116 static SymTable* NewSymTable (SymTable* Parent, const StrBuf* Name)
117 /* Allocate a symbol table on the heap and return it */
119 /* Determine the lexical level and the number of table slots */
120 unsigned Level = Parent? Parent->Level + 1 : 0;
121 unsigned Slots = ScopeTableSize (Level);
123 /* Allocate memory */
124 SymTable* S = xmalloc (sizeof (SymTable) + (Slots-1) * sizeof (SymEntry*));
126 /* Set variables and clear hash table entries */
132 S->Spans = AUTO_COLLECTION_INITIALIZER;
133 S->Id = ScopeCount++;
135 S->AddrSize = ADDR_SIZE_DEFAULT;
136 S->Type = SCOPE_UNDEF;
138 S->TableSlots = Slots;
141 S->Name = GetStrBufId (Name);
146 /* Insert the symbol table into the list of all symbol tables */
147 if (RootScope == 0) {
154 /* Insert the symbol table into the child tree of the parent */
156 SymTable* T = Parent->Childs;
162 /* Choose next entry */
163 int Cmp = SB_Compare (Name, GetStrBuf (T->Name));
171 } else if (Cmp > 0) {
179 /* Duplicate scope name */
180 Internal ("Duplicate scope name: `%m%p'", Name);
186 /* Return the prepared struct */
192 /*****************************************************************************/
194 /*****************************************************************************/
198 void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
199 unsigned char AddrSize, SymEntry* ScopeLabel)
200 /* Enter a new lexical level */
202 /* Map a default address size to something real */
203 if (AddrSize == ADDR_SIZE_DEFAULT) {
204 /* Use the segment address size */
205 AddrSize = GetCurrentSegAddrSize ();
208 /* If we have a current scope, search for the given name and create a
209 * new one if it doesn't exist. If this is the root scope, just create it.
213 /* Search for the scope, create a new one */
214 CurrentScope = SymFindScope (CurrentScope, ScopeName, SYM_ALLOC_NEW);
216 /* Check if the scope has been defined before */
217 if (CurrentScope->Flags & ST_DEFINED) {
218 Error ("Duplicate scope `%m%p'", ScopeName);
222 CurrentScope = RootScope = NewSymTable (0, ScopeName);
225 /* Mark the scope as defined and set type, address size and owner symbol */
226 CurrentScope->Flags |= ST_DEFINED;
227 CurrentScope->AddrSize = AddrSize;
228 CurrentScope->Type = Type;
229 CurrentScope->Label = ScopeLabel;
231 /* If this is a scope that allows to emit data into segments, add spans
232 * for all currently existing segments. Doing this for just a few scope
233 * types is not really necessary but an optimization, because it does not
234 * allocate memory for useless data (unhandled types here don't occupy
235 * space in any segment).
237 if (CurrentScope->Type <= SCOPE_HAS_DATA) {
238 OpenSpanList (&CurrentScope->Spans);
244 void SymLeaveLevel (void)
245 /* Leave the current lexical level */
247 /* If this is a scope that allows to emit data into segments, close the
250 if (CurrentScope->Type <= SCOPE_HAS_DATA) {
251 CloseSpanList (&CurrentScope->Spans);
254 /* If we have spans, the first one is the segment that was active, when the
255 * scope was opened. Set the size of the scope to the number of data bytes
256 * emitted into this segment. If we have an owner symbol set the size of
259 if (CollCount (&CurrentScope->Spans) > 0) {
260 const Span* S = CollAtUnchecked (&CurrentScope->Spans, 0);
261 unsigned long Size = GetSpanSize (S);
262 DefSizeOfScope (CurrentScope, Size);
263 if (CurrentScope->Label) {
264 DefSizeOfSymbol (CurrentScope->Label, Size);
268 /* Leave the scope */
269 CurrentScope = CurrentScope->Parent;
274 SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, int AllocNew)
275 /* Find a scope in the given enclosing scope */
277 SymTable** T = &Parent->Childs;
279 int Cmp = SB_Compare (Name, GetStrBuf ((*T)->Name));
282 } else if (Cmp > 0) {
285 /* Found the scope */
290 /* Create a new scope if requested and we didn't find one */
291 if (*T == 0 && AllocNew) {
292 *T = NewSymTable (Parent, Name);
295 /* Return the scope */
301 SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name)
302 /* Find a scope in the given or any of its parent scopes. The function will
303 * never create a new symbol, since this can only be done in one specific
309 /* Search in the current table */
310 Scope = SymFindScope (Parent, Name, SYM_FIND_EXISTING);
312 /* Not found, search in the parent scope, if we have one */
313 Parent = Parent->Parent;
315 } while (Scope == 0 && Parent != 0);
322 SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, int AllocNew)
323 /* Find a cheap local symbol. If AllocNew is given and the entry is not
324 * found, create a new one. Return the entry found, or the new entry created,
325 * or - in case AllocNew is zero - return 0.
331 /* Local symbol, get the table */
333 /* No last global, so there's no local table */
334 Error ("No preceeding global symbol");
336 return NewSymEntry (Name, SF_LOCAL);
342 /* Search for the symbol if we have a table */
343 Cmp = SymSearchTree (Parent->Locals, Name, &S);
345 /* If we found an entry, return it */
352 /* Otherwise create a new entry, insert and return it */
353 SymEntry* N = NewSymEntry (Name, SF_LOCAL);
354 N->Sym.Entry = Parent;
357 } else if (Cmp < 0) {
365 /* We did not find the entry and AllocNew is false. */
371 SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, int AllocNew)
372 /* Find a new symbol table entry in the given table. If AllocNew is given and
373 * the entry is not found, create a new one. Return the entry found, or the
374 * new entry created, or - in case AllocNew is zero - return 0.
379 /* Global symbol: Get the hash value for the name */
380 unsigned Hash = HashBuf (Name) % Scope->TableSlots;
382 /* Search for the entry */
383 int Cmp = SymSearchTree (Scope->Table[Hash], Name, &S);
385 /* If we found an entry, return it */
392 /* Otherwise create a new entry, insert and return it */
393 SymEntry* N = NewSymEntry (Name, SF_NONE);
396 Scope->Table[Hash] = N;
397 } else if (Cmp < 0) {
402 ++Scope->TableEntries;
407 /* We did not find the entry and AllocNew is false. */
413 SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name)
414 /* Find a symbol in the given or any of its parent scopes. The function will
415 * never create a new symbol, since this can only be done in one specific
421 /* Search in the current table */
422 Sym = SymFind (Scope, Name, SYM_FIND_EXISTING);
424 /* Found, return it */
428 /* Not found, search in the parent scope, if we have one */
429 Scope = Scope->Parent;
431 } while (Sym == 0 && Scope != 0);
433 /* Return the result */
439 static void SymCheckUndefined (SymEntry* S)
440 /* Handle an undefined symbol */
442 /* Undefined symbol. It may be...
444 * - An undefined symbol in a nested lexical level. In this
445 * case, search for the symbol in the higher levels and
446 * make the entry a trampoline entry if we find one.
448 * - If the symbol is not found, it is a real undefined symbol.
449 * If the AutoImport flag is set, make it an import. If the
450 * AutoImport flag is not set, it's an error.
453 SymTable* Tab = GetSymParentScope (S);
455 Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING);
456 if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) {
457 /* We've found a symbol in a higher level that is
458 * either defined in the source, or an import.
462 /* No matching symbol found in this level. Look further */
468 /* We found the symbol in a higher level. Transfer the flags and
469 * address size from the local symbol to that in the higher level
470 * and check for problems.
472 if (S->Flags & SF_EXPORT) {
473 if (Sym->Flags & SF_IMPORT) {
474 /* The symbol is already marked as import */
475 LIError (&S->RefLines,
476 "Symbol `%s' is already an import",
477 GetString (Sym->Name));
479 if (Sym->Flags & SF_EXPORT) {
480 /* The symbol is already marked as an export. */
481 if (Sym->AddrSize > S->ExportSize) {
482 /* We're exporting a symbol smaller than it actually is */
483 LIWarning (&S->DefLines, 1,
484 "Symbol `%m%p' is %s but exported %s",
486 AddrSizeToStr (Sym->AddrSize),
487 AddrSizeToStr (S->ExportSize));
490 /* Mark the symbol as an export */
491 Sym->Flags |= SF_EXPORT;
492 Sym->ExportSize = S->ExportSize;
493 if (Sym->ExportSize == ADDR_SIZE_DEFAULT) {
494 /* Use the actual size of the symbol */
495 Sym->ExportSize = Sym->AddrSize;
497 if (Sym->AddrSize > Sym->ExportSize) {
498 /* We're exporting a symbol smaller than it actually is */
499 LIWarning (&S->DefLines, 1,
500 "Symbol `%m%p' is %s but exported %s",
502 AddrSizeToStr (Sym->AddrSize),
503 AddrSizeToStr (Sym->ExportSize));
507 if (S->Flags & SF_REFERENCED) {
508 /* Mark as referenced and move the line info */
509 Sym->Flags |= SF_REFERENCED;
510 CollTransfer (&Sym->RefLines, &S->RefLines);
511 CollDeleteAll (&S->RefLines);
514 /* Transfer all expression references */
515 SymTransferExprRefs (S, Sym);
517 /* Mark the symbol as unused removing all other flags */
518 S->Flags = SF_UNUSED;
521 /* The symbol is definitely undefined */
522 if (S->Flags & SF_EXPORT) {
523 /* We will not auto-import an export */
524 LIError (&S->RefLines,
525 "Exported symbol `%m%p' was never defined",
529 /* Mark as import, will be indexed later */
530 S->Flags |= SF_IMPORT;
531 /* Use the address size for code */
532 S->AddrSize = CodeAddrSize;
533 /* Mark point of import */
534 GetFullLineInfo (&S->DefLines);
537 LIError (&S->RefLines,
538 "Symbol `%m%p' is undefined",
548 /* Run through all symbols and check for anomalies and errors */
552 /* Check for open scopes */
553 if (CurrentScope->Parent != 0) {
554 Error ("Local scope was not closed");
557 /* First pass: Walk through all symbols, checking for undefined's and
558 * changing them to trampoline symbols or make them imports.
562 /* If the symbol is marked as global, mark it as export, if it is
563 * already defined, otherwise mark it as import.
565 if (S->Flags & SF_GLOBAL) {
566 if (S->Flags & SF_DEFINED) {
567 SymExportFromGlobal (S);
569 SymImportFromGlobal (S);
573 /* Handle undefined symbols */
574 if ((S->Flags & SF_UNDEFMASK) == SF_UNDEFVAL) {
575 /* This is an undefined symbol. Handle it. */
576 SymCheckUndefined (S);
583 /* Second pass: Walk again through the symbols. Count exports and imports
584 * and set address sizes where this has not happened before. Ignore
585 * undefined's, since we handled them in the last pass, and ignore unused
586 * symbols, since we handled them in the last pass, too.
590 if ((S->Flags & SF_UNUSED) == 0 &&
591 (S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) {
593 /* Check for defined symbols that were never referenced */
594 if (IsSizeOfSymbol (S)) {
595 /* Remove line infos, we don't need them any longer */
596 ReleaseFullLineInfo (&S->DefLines);
597 ReleaseFullLineInfo (&S->RefLines);
598 } else if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
599 LIWarning (&S->DefLines, 2,
600 "Symbol `%m%p' is defined but never used",
604 /* Assign an index to all imports */
605 if (S->Flags & SF_IMPORT) {
606 if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
607 /* Imported symbol is not referenced */
608 LIWarning (&S->DefLines, 2,
609 "Symbol `%m%p' is imported but never used",
612 /* Give the import an id, count imports */
613 S->ImportId = ImportCount++;
617 /* Count exports, assign the export ID */
618 if (S->Flags & SF_EXPORT) {
619 S->ExportId = ExportCount++;
622 /* If the symbol is defined but has an unknown address size,
625 if (SymHasExpr (S) && S->AddrSize == ADDR_SIZE_DEFAULT) {
628 StudyExpr (S->Expr, &ED);
629 S->AddrSize = ED.AddrSize;
630 if (SymIsExport (S)) {
631 if (S->ExportSize == ADDR_SIZE_DEFAULT) {
632 /* Use the real export size */
633 S->ExportSize = S->AddrSize;
634 } else if (S->AddrSize > S->ExportSize) {
635 /* We're exporting a symbol smaller than it actually is */
636 LIWarning (&S->DefLines, 1,
637 "Symbol `%m%p' is %s but exported %s",
639 AddrSizeToStr (S->AddrSize),
640 AddrSizeToStr (S->ExportSize));
646 /* If the address size of the symbol was guessed, check the guess
647 * against the actual address size and print a warning if the two
650 if (S->AddrSize != ADDR_SIZE_DEFAULT) {
651 /* Do we have data for this address size? */
652 if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) {
653 /* Get the file position where the symbol was used */
654 const FilePos* P = S->GuessedUse[S->AddrSize - 1];
657 "Didn't use %s addressing for `%m%p'",
658 AddrSizeToStr (S->AddrSize),
673 void SymDump (FILE* F)
674 /* Dump the symbol table */
676 SymEntry* S = SymList;
679 /* Ignore unused symbols */
680 if ((S->Flags & SF_UNUSED) != 0) {
682 "%m%-24p %s %s %s %s %s\n",
684 (S->Flags & SF_DEFINED)? "DEF" : "---",
685 (S->Flags & SF_REFERENCED)? "REF" : "---",
686 (S->Flags & SF_IMPORT)? "IMP" : "---",
687 (S->Flags & SF_EXPORT)? "EXP" : "---",
688 AddrSizeToStr (S->AddrSize));
697 void WriteImports (void)
698 /* Write the imports list to the object file */
702 /* Tell the object file module that we're about to start the imports */
705 /* Write the import count to the list */
706 ObjWriteVar (ImportCount);
708 /* Walk throught list and write all valid imports to the file. An import
709 * is considered valid, if it is either referenced, or the forced bit is
710 * set. Otherwise, the import is ignored (no need to link in something
715 if ((S->Flags & (SF_UNUSED | SF_IMPORT)) == SF_IMPORT &&
716 (S->Flags & (SF_REFERENCED | SF_FORCED)) != 0) {
718 ObjWrite8 (S->AddrSize);
719 ObjWriteVar (S->Name);
720 WriteLineInfo (&S->DefLines);
721 WriteLineInfo (&S->RefLines);
726 /* Done writing imports */
732 void WriteExports (void)
733 /* Write the exports list to the object file */
738 /* Tell the object file module that we're about to start the exports */
741 /* Write the export count to the list */
742 ObjWriteVar (ExportCount);
744 /* Walk throught list and write all exports to the file */
747 if ((S->Flags & (SF_UNUSED | SF_EXPORT)) == SF_EXPORT) {
749 /* Get the expression bits and the value */
751 unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
753 /* Check if this symbol has a size. If so, remember it in the
757 SymEntry* SizeSym = FindSizeOfSymbol (S);
758 if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
759 SymFlags |= SYM_SIZE;
762 /* Count the number of ConDes types */
763 for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
764 if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
765 SYM_INC_CONDES_COUNT (SymFlags);
769 /* Write the type and the export size */
770 ObjWriteVar (SymFlags);
771 ObjWrite8 (S->ExportSize);
773 /* Write any ConDes declarations */
774 if (SYM_GET_CONDES_COUNT (SymFlags) > 0) {
775 for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
776 unsigned char Prio = S->ConDesPrio[Type];
777 if (Prio != CD_PRIO_NONE) {
778 ObjWrite8 (CD_BUILD (Type, Prio));
784 ObjWriteVar (S->Name);
786 /* Write the value */
787 if (SYM_IS_CONST (SymFlags)) {
789 ObjWrite32 (ConstVal);
791 /* Expression involved */
795 /* If the symbol has a size, write it to the file */
796 if (SYM_HAS_SIZE (SymFlags)) {
800 /* Write the line infos */
801 WriteLineInfo (&S->DefLines);
802 WriteLineInfo (&S->RefLines);
807 /* Done writing exports */
813 void WriteDbgSyms (void)
814 /* Write a list of all symbols to the object file */
819 /* Tell the object file module that we're about to start the debug info */
822 /* Check if debug info is requested */
825 /* Walk through the list, give each symbol an id and count them */
830 S->DebugSymId = Count++;
835 /* Write the symbol count to the list */
838 /* Walk through list and write all symbols to the file. Ignore size
845 /* Get the expression bits and the value */
847 unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
849 /* Check if this symbol has a size. If so, remember it in the
853 SymEntry* SizeSym = FindSizeOfSymbol (S);
854 if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
855 SymFlags |= SYM_SIZE;
859 ObjWriteVar (SymFlags);
861 /* Write the address size */
862 ObjWrite8 (S->AddrSize);
864 /* Write the id of the parent. For normal symbols, this is a
865 * scope (symbol table), for cheap locals, it's a symbol.
867 if (SYM_IS_STD (SymFlags)) {
868 ObjWriteVar (S->Sym.Tab->Id);
870 ObjWriteVar (S->Sym.Entry->DebugSymId);
874 ObjWriteVar (S->Name);
876 /* Write the value */
877 if (SYM_IS_CONST (SymFlags)) {
879 ObjWrite32 (ConstVal);
881 /* Expression involved */
885 /* If the symbol has a size, write it to the file */
886 if (SYM_HAS_SIZE (SymFlags)) {
890 /* If the symbol is an im- or export, write out the ids */
891 if (SYM_IS_IMPORT (SymFlags)) {
892 ObjWriteVar (GetSymImportId (S));
894 if (SYM_IS_EXPORT (SymFlags)) {
895 ObjWriteVar (GetSymExportId (S));
898 /* Write the line infos */
899 WriteLineInfo (&S->DefLines);
900 WriteLineInfo (&S->RefLines);
907 /* No debug symbols */
912 /* Done writing debug symbols */
918 void WriteScopes (void)
919 /* Write the scope table to the object file */
921 /* Tell the object file module that we're about to start the scopes */
924 /* We will write scopes only if debug symbols are requested */
927 /* Get head of list */
928 SymTable* S = RootScope;
930 /* Write the scope count to the file */
931 ObjWriteVar (ScopeCount);
933 /* Walk through all scopes and write them to the file */
936 /* Flags for this scope */
939 /* Check if this scope has a size. If so, remember it in the
943 SymEntry* SizeSym = FindSizeOfScope (S);
944 if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
948 /* Check if the scope has a label */
950 Flags |= SCOPE_LABELED;
953 /* Scope must be defined */
954 CHECK (S->Type != SCOPE_UNDEF);
956 /* Id of parent scope */
958 ObjWriteVar (S->Parent->Id);
964 ObjWriteVar (S->Level);
970 ObjWriteVar (S->Type);
972 /* Name of the scope */
973 ObjWriteVar (S->Name);
975 /* If the scope has a size, write it to the file */
976 if (SCOPE_HAS_SIZE (Flags)) {
980 /* If the scope has a label, write its id to the file */
981 if (SCOPE_HAS_LABEL (Flags)) {
982 ObjWriteVar (S->Label->DebugSymId);
985 /* Spans for this scope */
986 WriteSpanList (&S->Spans);
994 /* No debug info requested */
999 /* Done writing the scopes */