/* */
/* */
/* */
-/* (C) 1998-2004 Ullrich von Bassewitz */
-/* Römerstraße 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2011, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#define SF_DBGINFOVAL (SF_DEFINED)
/* Symbol tables */
-SymTable* CurrentScope = 0; /* Pointer to current symbol table */
-SymTable* RootScope = 0; /* Root symbol table */
+SymTable* CurrentScope = 0; /* Pointer to current symbol table */
+SymTable* RootScope = 0; /* Root symbol table */
+static SymTable* LastScope = 0; /* Pointer to last scope in list */
/* Symbol table variables */
-static unsigned ImportCount = 0; /* Counter for import symbols */
-static unsigned ExportCount = 0; /* Counter for export symbols */
+static unsigned ImportCount = 0; /* Counter for import symbols */
+static unsigned ExportCount = 0; /* Counter for export symbols */
-static SymTable* NewSymTable (SymTable* Parent, const char* Name)
+static SymTable* NewSymTable (SymTable* Parent, const StrBuf* Name)
/* Allocate a symbol table on the heap and return it */
{
/* Determine the lexical level and the number of table slots */
S->Left = 0;
S->Right = 0;
S->Childs = 0;
+ S->OwnerSym = 0;
S->SegRanges = AUTO_COLLECTION_INITIALIZER;
S->Flags = ST_NONE;
S->AddrSize = ADDR_SIZE_DEFAULT;
S->TableSlots = Slots;
S->TableEntries = 0;
S->Parent = Parent;
- S->Name = GetStringId (Name);
+ S->Name = GetStrBufId (Name);
while (Slots--) {
S->Table[Slots] = 0;
}
+ /* Insert the symbol table into the list of all symbol tables and maintain
+ * a unqiue id for each scope.
+ */
+ S->Next = LastScope;
+ if (RootScope == 0) {
+ S->Id = 0;
+ RootScope = S;
+ } else {
+ S->Id = LastScope->Id + 1;
+ }
+ LastScope = S;
+
/* Insert the symbol table into the child tree of the parent */
if (Parent) {
SymTable* T = Parent->Childs;
} else {
while (1) {
/* Choose next entry */
- int Cmp = strcmp (Name, GetString (T->Name));
+ int Cmp = SB_Compare (Name, GetStrBuf (T->Name));
if (Cmp < 0) {
if (T->Left) {
T = T->Left;
} else {
T->Right = S;
break;
- }
+ }
} else {
/* Duplicate scope name */
- Internal ("Duplicate scope name: `%s'", Name);
+ Internal ("Duplicate scope name: `%m%p'", Name);
}
}
}
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
-void SymEnterLevel (const char* ScopeName, unsigned char Type, unsigned char AddrSize)
+void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
+ unsigned char AddrSize, SymEntry* OwnerSym)
/* Enter a new lexical level */
{
/* Map a default address size to something real */
/* Check if the scope has been defined before */
if (CurrentScope->Flags & ST_DEFINED) {
- Error ("Duplicate scope `%s'", ScopeName);
+ Error ("Duplicate scope `%m%p'", ScopeName);
}
} else {
CurrentScope = RootScope = NewSymTable (0, ScopeName);
}
- /* Mark the scope as defined and set type and address size */
+ /* Mark the scope as defined and set type, address size and owner symbol */
CurrentScope->Flags |= ST_DEFINED;
CurrentScope->AddrSize = AddrSize;
CurrentScope->Type = Type;
+ CurrentScope->OwnerSym = OwnerSym;
/* If this is a scope that allows to emit data into segments, add segment
* ranges for all currently existing segments. Doing this for just a few
/* If we have segment ranges, the first one is the segment that was
* active, when the scope was opened. Set the size of the scope to the
- * number of data bytes emitted into this segment.
+ * number of data bytes emitted into this segment. If we have an owner
+ * symbol set the size of this symbol, too.
*/
if (CollCount (&CurrentScope->SegRanges) > 0) {
const SegRange* R = CollAtUnchecked (&CurrentScope->SegRanges, 0);
- DefSizeOfScope (CurrentScope, GetSegRangeSize (R));
+ unsigned long Size = GetSegRangeSize (R);
+ DefSizeOfScope (CurrentScope, Size);
+ if (CurrentScope->OwnerSym) {
+ DefSizeOfSymbol (CurrentScope->OwnerSym, Size);
+ }
}
/* Leave the scope */
-SymTable* SymFindScope (SymTable* Parent, const char* Name, int AllocNew)
+SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, int AllocNew)
/* Find a scope in the given enclosing scope */
{
SymTable** T = &Parent->Childs;
while (*T) {
- int Cmp = strcmp (Name, GetString ((*T)->Name));
+ int Cmp = SB_Compare (Name, GetStrBuf ((*T)->Name));
if (Cmp < 0) {
T = &(*T)->Left;
} else if (Cmp > 0) {
-SymTable* SymFindAnyScope (SymTable* Parent, const char* Name)
+SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name)
/* Find a scope in the given or any of its parent scopes. The function will
* never create a new symbol, since this can only be done in one specific
* scope.
-SymEntry* SymFindLocal (SymEntry* Parent, const char* Name, int AllocNew)
+SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, int AllocNew)
/* Find a cheap local symbol. If AllocNew is given and the entry is not
* found, create a new one. Return the entry found, or the new entry created,
* or - in case AllocNew is zero - return 0.
/* Otherwise create a new entry, insert and return it */
SymEntry* N = NewSymEntry (Name, SF_LOCAL);
+ N->Sym.Entry = Parent;
if (S == 0) {
Parent->Locals = N;
} else if (Cmp < 0) {
-SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
+SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, int AllocNew)
/* Find a new symbol table entry in the given table. If AllocNew is given and
* the entry is not found, create a new one. Return the entry found, or the
* new entry created, or - in case AllocNew is zero - return 0.
SymEntry* S;
/* Global symbol: Get the hash value for the name */
- unsigned Hash = HashStr (Name) % Scope->TableSlots;
+ unsigned Hash = HashBuf (Name) % Scope->TableSlots;
/* Search for the entry */
int Cmp = SymSearchTree (Scope->Table[Hash], Name, &S);
/* Otherwise create a new entry, insert and return it */
SymEntry* N = NewSymEntry (Name, SF_NONE);
+ N->Sym.Tab = Scope;
if (S == 0) {
Scope->Table[Hash] = N;
} else if (Cmp < 0) {
} else {
S->Right = N;
}
- N->SymTab = Scope;
++Scope->TableEntries;
return N;
-SymEntry* SymFindAny (SymTable* Scope, const char* Name)
+SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name)
/* Find a symbol in the given or any of its parent scopes. The function will
* never create a new symbol, since this can only be done in one specific
* scope.
SymEntry* Sym = 0;
SymTable* Tab = GetSymParentScope (S);
while (Tab) {
- Sym = SymFind (Tab, GetString (S->Name), SYM_FIND_EXISTING);
+ Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING);
if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) {
/* We've found a symbol in a higher level that is
* either defined in the source, or an import.
if (S->Flags & SF_EXPORT) {
if (Sym->Flags & SF_IMPORT) {
/* The symbol is already marked as import */
- PError (&S->Pos, "Symbol `%s' is already an import",
- GetString (Sym->Name));
+ LIError (&S->LineInfos,
+ "Symbol `%s' is already an import",
+ GetString (Sym->Name));
}
if (Sym->Flags & SF_EXPORT) {
/* The symbol is already marked as an export. */
if (Sym->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
- PWarning (&S->Pos, 1, "Symbol `%s' is %s but exported %s",
- GetSymName (Sym), AddrSizeToStr (Sym->AddrSize),
+ LIWarning (&S->LineInfos, 1,
+ "Symbol `%m%p' is %s but exported %s",
+ GetSymName (Sym),
+ AddrSizeToStr (Sym->AddrSize),
AddrSizeToStr (S->ExportSize));
}
} else {
}
if (Sym->AddrSize > Sym->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
- PWarning (&S->Pos, 1, "Symbol `%s' is %s but exported %s",
- GetSymName (Sym), AddrSizeToStr (Sym->AddrSize),
- AddrSizeToStr (Sym->ExportSize));
+ LIWarning (&S->LineInfos, 1,
+ "Symbol `%m%p' is %s but exported %s",
+ GetSymName (Sym),
+ AddrSizeToStr (Sym->AddrSize),
+ AddrSizeToStr (Sym->ExportSize));
}
}
}
/* The symbol is definitely undefined */
if (S->Flags & SF_EXPORT) {
/* We will not auto-import an export */
- PError (&S->Pos, "Exported symbol `%s' was never defined",
- GetString (S->Name));
+ LIError (&S->LineInfos,
+ "Exported symbol `%m%p' was never defined",
+ GetSymName (S));
} else {
if (AutoImport) {
/* Mark as import, will be indexed later */
S->AddrSize = CodeAddrSize;
} else {
/* Error */
- PError (&S->Pos, "Symbol `%s' is undefined", GetString (S->Name));
+ LIError (&S->LineInfos,
+ "Symbol `%m%p' is undefined",
+ GetSymName (S));
}
}
}
/* Check for defined symbols that were never referenced */
if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
- const char* Name = GetString (S->Name);
- if (Name[0] != '.') { /* Ignore internals */
- PWarning (&S->Pos, 2,
- "Symbol `%s' is defined but never used",
- GetString (S->Name));
+ const StrBuf* Name = GetStrBuf (S->Name);
+ if (SB_At (Name, 0) != '.') { /* Ignore internals */
+ LIWarning (&S->LineInfos, 2,
+ "Symbol `%m%p' is defined but never used",
+ GetSymName (S));
}
}
if (S->Flags & SF_IMPORT) {
if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
/* Imported symbol is not referenced */
- PWarning (&S->Pos, 2,
- "Symbol `%s' is imported but never used",
- GetString (S->Name));
+ LIWarning (&S->LineInfos, 2,
+ "Symbol `%m%p' is imported but never used",
+ GetSymName (S));
} else {
- /* Give the import an index, count imports */
- S->Index = ImportCount++;
- S->Flags |= SF_INDEXED;
+ /* Give the import an id, count imports */
+ S->ImportId = ImportCount++;
}
}
- /* Assign an index to all exports */
+ /* Count exports */
if (S->Flags & SF_EXPORT) {
- /* Give the export an index, count exports */
- S->Index = ExportCount++;
- S->Flags |= SF_INDEXED;
+ ++ExportCount;
}
/* If the symbol is defined but has an unknown address size,
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
- PWarning (&S->Pos, 1,
- "Symbol `%s' is %s but exported %s",
- GetSymName (S), AddrSizeToStr (S->AddrSize),
- AddrSizeToStr (S->ExportSize));
+ LIWarning (&S->LineInfos, 1,
+ "Symbol `%m%p' is %s but exported %s",
+ GetSymName (S),
+ AddrSizeToStr (S->AddrSize),
+ AddrSizeToStr (S->ExportSize));
}
}
ED_Done (&ED);
}
+
+ /* If the address size of the symbol was guessed, check the guess
+ * against the actual address size and print a warning if the two
+ * differ.
+ */
+ if (S->AddrSize != ADDR_SIZE_DEFAULT) {
+ /* Do we have data for this address size? */
+ if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) {
+ /* Get the file position where the symbol was used */
+ const FilePos* P = S->GuessedUse[S->AddrSize - 1];
+ if (P) {
+ PWarning (P, 0,
+ "Didn't use %s addressing for `%m%p'",
+ AddrSizeToStr (S->AddrSize),
+ GetSymName (S));
+ }
+ }
+ }
+
}
/* Next symbol */
/* Ignore unused symbols */
if ((S->Flags & SF_UNUSED) != 0) {
fprintf (F,
- "%-24s %s %s %s %s %s\n",
- GetString (S->Name),
+ "%m%-24p %s %s %s %s %s\n",
+ GetSymName (S),
(S->Flags & SF_DEFINED)? "DEF" : "---",
(S->Flags & SF_REFERENCED)? "REF" : "---",
(S->Flags & SF_IMPORT)? "IMP" : "---",
ObjWrite8 (S->AddrSize);
ObjWriteVar (S->Name);
- ObjWritePos (&S->Pos);
+ WriteLineInfo (&S->LineInfos);
}
S = S->List;
}
while (S) {
if ((S->Flags & (SF_UNUSED | SF_EXPORT)) == SF_EXPORT) {
+ /* Get the expression bits and the value */
long ConstVal;
+ unsigned ExprMask = GetSymInfoFlags (S, &ConstVal);
- /* Get the expression bits */
- unsigned char ExprMask = SymIsConst (S, &ConstVal)? EXP_CONST : EXP_EXPR;
- ExprMask |= (S->Flags & SF_LABEL)? EXP_LABEL : EXP_EQUATE;
+ /* Check if this symbol has a size. If so, remember it in the
+ * flags.
+ */
+ long Size;
+ SymEntry* SizeSym = FindSizeOfSymbol (S);
+ if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
+ ExprMask |= SYM_SIZE;
+ }
/* Count the number of ConDes types */
for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
- if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
- INC_EXP_CONDES_COUNT (ExprMask);
- }
+ if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
+ SYM_INC_CONDES_COUNT (ExprMask);
+ }
}
/* Write the type and the export size */
- ObjWrite8 (ExprMask);
+ ObjWriteVar (ExprMask);
ObjWrite8 (S->ExportSize);
/* Write any ConDes declarations */
- if (GET_EXP_CONDES_COUNT (ExprMask) > 0) {
- for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
- unsigned char Prio = S->ConDesPrio[Type];
- if (Prio != CD_PRIO_NONE) {
- ObjWrite8 (CD_BUILD (Type, Prio));
- }
- }
+ if (SYM_GET_CONDES_COUNT (ExprMask) > 0) {
+ for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
+ unsigned char Prio = S->ConDesPrio[Type];
+ if (Prio != CD_PRIO_NONE) {
+ ObjWrite8 (CD_BUILD (Type, Prio));
+ }
+ }
}
/* Write the name */
ObjWriteVar (S->Name);
/* Write the value */
- if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
+ if (SYM_IS_CONST (ExprMask)) {
/* Constant value */
ObjWrite32 (ConstVal);
} else {
WriteExpr (S->Expr);
}
- /* Write the source file position */
- ObjWritePos (&S->Pos);
+ /* If the symbol has a size, write it to the file */
+ if (SYM_HAS_SIZE (ExprMask)) {
+ ObjWriteVar (Size);
+ }
+
+ /* Write the line infos */
+ WriteLineInfo (&S->LineInfos);
}
S = S->List;
}
/* Check if debug info is requested */
if (DbgSyms) {
- /* Walk through the list and count the symbols */
+ /* Walk through the list, give each symbol an id and count them */
Count = 0;
S = SymList;
while (S) {
- if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
- ++Count;
+ if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL &&
+ !IsSizeOfSymbol (S)) {
+ S->DebugSymId = Count++;
}
S = S->List;
}
/* Write the symbol count to the list */
ObjWriteVar (Count);
- /* Walk through list and write all symbols to the file */
+ /* Walk through list and write all symbols to the file. Ignore size
+ * symbols.
+ */
S = SymList;
while (S) {
- if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
+ if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL &&
+ !IsSizeOfSymbol (S)) {
+ /* Get the expression bits and the value */
long ConstVal;
-
- /* Get the expression bits */
- unsigned char ExprMask = (SymIsConst (S, &ConstVal))? EXP_CONST : EXP_EXPR;
- ExprMask |= (S->Flags & SF_LABEL)? EXP_LABEL : EXP_EQUATE;
+ unsigned ExprMask = GetSymInfoFlags (S, &ConstVal);
+
+ /* Check if this symbol has a size. If so, remember it in the
+ * flags.
+ */
+ long Size;
+ SymEntry* SizeSym = FindSizeOfSymbol (S);
+ if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
+ ExprMask |= SYM_SIZE;
+ }
/* Write the type */
- ObjWrite8 (ExprMask);
+ ObjWriteVar (ExprMask);
/* Write the address size */
ObjWrite8 (S->AddrSize);
ObjWriteVar (S->Name);
/* Write the value */
- if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
+ if (SYM_IS_CONST (ExprMask)) {
/* Constant value */
ObjWrite32 (ConstVal);
} else {
WriteExpr (S->Expr);
}
- /* Write the source file position */
- ObjWritePos (&S->Pos);
+ /* If the symbol has a size, write it to the file */
+ if (SYM_HAS_SIZE (ExprMask)) {
+ ObjWriteVar (Size);
+ }
+
+ /* Write the line infos */
+ WriteLineInfo (&S->LineInfos);
}
S = S->List;
}
/* Tell the object file module that we're about to start the scopes */
ObjStartScopes ();
- /* For now ...*/
+ /* No debug info requested */
ObjWriteVar (0);
/* Done writing the scopes */