/*****************************************************************************/
/* */
-/* symentry.c */
+/* symentry.c */
/* */
/* Symbol table entry for the ca65 macroassembler */
/* */
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
SymEntry* S = xmalloc (sizeof (SymEntry));
/* Initialize the entry */
- S->Left = 0;
- S->Right = 0;
- S->Locals = 0;
+ S->Left = 0;
+ S->Right = 0;
+ S->Locals = 0;
S->Sym.Tab = 0;
- S->LineInfos = EmptyCollection;
- GetFullLineInfo (&S->LineInfos);
+ S->DefLines = EmptyCollection;
+ S->RefLines = EmptyCollection;
for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) {
S->GuessedUse[I] = 0;
}
- S->Flags = Flags;
+ S->HLLSym = 0;
+ S->Flags = Flags;
S->DebugSymId = ~0U;
S->ImportId = ~0U;
+ S->ExportId = ~0U;
S->Expr = 0;
S->ExprRefs = AUTO_COLLECTION_INITIALIZER;
S->ExportSize = ADDR_SIZE_DEFAULT;
{
/* Is there a tree? */
if (T == 0) {
- *E = 0;
- return 1;
+ *E = 0;
+ return 1;
}
/* We have a table, search it */
/* Get the symbol name */
const StrBuf* SymName = GetStrBuf (T->Name);
- /* Choose next entry */
+ /* Choose next entry */
int Cmp = SB_Compare (Name, SymName);
- if (Cmp < 0 && T->Left) {
- T = T->Left;
- } else if (Cmp > 0&& T->Right) {
- T = T->Right;
- } else {
- /* Found or end of search, return the result */
+ if (Cmp < 0 && T->Left) {
+ T = T->Left;
+ } else if (Cmp > 0 && T->Right) {
+ T = T->Right;
+ } else {
+ /* Found or end of search, return the result */
*E = T;
return Cmp;
- }
+ }
}
}
-void SymRef (SymEntry* S)
-/* Mark the given symbol as referenced */
-{
- /* Mark the symbol as referenced */
- S->Flags |= SF_REFERENCED;
-}
-
-
-
void SymTransferExprRefs (SymEntry* From, SymEntry* To)
/* Transfer all expression references from one symbol to another. */
{
/* Define a new symbol */
{
if (S->Flags & SF_IMPORT) {
- /* Defined symbol is marked as imported external symbol */
- Error ("Symbol `%m%p' is already an import", GetSymName (S));
- return;
+ /* Defined symbol is marked as imported external symbol */
+ Error ("Symbol `%m%p' is already an import", GetSymName (S));
+ return;
}
if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) {
/* Variable symbols cannot be exports or globals */
return;
}
if (S->Flags & SF_DEFINED) {
- /* Multiple definition. In case of a variable, this is legal. */
+ /* Multiple definition. In case of a variable, this is legal. */
if ((S->Flags & SF_VAR) == 0) {
Error ("Symbol `%m%p' is already defined", GetSymName (S));
S->Flags |= SF_MULTDEF;
*/
if (S->Flags & SF_GLOBAL) {
S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
+ ReleaseFullLineInfo (&S->DefLines);
}
/* Mark the symbol as defined and use the given address size */
S->Flags |= (SF_DEFINED | Flags);
S->AddrSize = AddrSize;
+ /* Remember the line info of the symbol definition */
+ GetFullLineInfo (&S->DefLines);
+
/* If the symbol is exported, check the address sizes */
if (S->Flags & SF_EXPORT) {
if (S->ExportSize == ADDR_SIZE_DEFAULT) {
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
- PWarning (GetSymPos (S), 1, "Symbol `%m%p' is %s but exported %s",
- GetSymName (S), AddrSizeToStr (S->AddrSize),
- AddrSizeToStr (S->ExportSize));
+ Warning (1, "Symbol `%m%p' is %s but exported %s",
+ GetSymName (S), AddrSizeToStr (S->AddrSize),
+ AddrSizeToStr (S->ExportSize));
}
}
/* If this is not a local symbol, remember it as the last global one */
if ((S->Flags & SF_LOCAL) == 0) {
- SymLast = S;
+ SymLast = S;
}
}
+void SymRef (SymEntry* S)
+/* Mark the given symbol as referenced */
+{
+ /* Mark the symbol as referenced */
+ S->Flags |= SF_REFERENCED;
+
+ /* Remember the current location */
+ CollAppend (&S->RefLines, GetAsmLineInfo ());
+}
+
+
+
void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as an imported symbol */
{
if (S->Flags & SF_DEFINED) {
- Error ("Symbol `%m%p' is already defined", GetSymName (S));
- S->Flags |= SF_MULTDEF;
- return;
+ Error ("Symbol `%m%p' is already defined", GetSymName (S));
+ S->Flags |= SF_MULTDEF;
+ return;
}
if (S->Flags & SF_EXPORT) {
- /* The symbol is already marked as exported symbol */
- Error ("Cannot import exported symbol `%m%p'", GetSymName (S));
- return;
+ /* The symbol is already marked as exported symbol */
+ Error ("Cannot import exported symbol `%m%p'", GetSymName (S));
+ return;
}
/* If no address size is given, use the address size of the enclosing
* then do silently remove the global flag.
*/
if (S->Flags & SF_IMPORT) {
- if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) {
- Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
- }
+ if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) {
+ Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
+ }
if (AddrSize != S->AddrSize) {
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
S->Flags &= ~SF_GLOBAL;
if (AddrSize != S->AddrSize) {
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
- }
+ }
}
/* Set the symbol data */
S->Flags |= (SF_IMPORT | Flags);
S->AddrSize = AddrSize;
+
+ /* Mark the position of the import as the position of the definition.
+ * Please note: In case of multiple .global or .import statements, the line
+ * infos add up.
+ */
+ GetFullLineInfo (&S->DefLines);
}
{
/* Check if it's ok to export the symbol */
if (S->Flags & SF_IMPORT) {
- /* The symbol is already marked as imported external symbol */
- Error ("Symbol `%m%p' is already an import", GetSymName (S));
- return;
+ /* The symbol is already marked as imported external symbol */
+ Error ("Symbol `%m%p' is already an import", GetSymName (S));
+ return;
}
if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported */
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
S->Flags &= ~SF_GLOBAL;
+
+ /* .GLOBAL remembers line infos in case an .IMPORT follows. We have
+ * to remove these here.
+ */
+ ReleaseFullLineInfo (&S->DefLines);
}
/* If the symbol was already marked as an export, but wasn't defined
/* Set the symbol data */
S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags);
+
+ /* Remember line info for this reference */
+ CollAppend (&S->RefLines, GetAsmLineInfo ());
}
}
S->ExportSize = AddrSize;
S->Flags |= (SF_GLOBAL | Flags);
+
+ /* Remember the current location as location of definition in case
+ * an .IMPORT follows later.
+ */
+ GetFullLineInfo (&S->DefLines);
}
}
/* Check for errors */
if (S->Flags & SF_IMPORT) {
- /* The symbol is already marked as imported external symbol */
- Error ("Symbol `%m%p' is already an import", GetSymName (S));
- return;
+ /* The symbol is already marked as imported external symbol */
+ Error ("Symbol `%m%p' is already an import", GetSymName (S));
+ return;
}
if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported or imported */
* priority value is the same as the old one.
*/
if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
- if (S->ConDesPrio[Type] != Prio) {
- Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
- }
+ if (S->ConDesPrio[Type] != Prio) {
+ Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
+ }
}
S->ConDesPrio[Type] = Prio;
/* Set the symbol data */
S->Flags |= (SF_EXPORT | SF_REFERENCED);
+
+ /* In case we have no line info for the definition, record it now */
+ if (CollCount (&S->DefLines) == 0) {
+ GetFullLineInfo (&S->DefLines);
+ }
}
if ((S->Flags & SF_LOCAL) != 0) {
/* This is a cheap local symbol */
return 0;
+ } else if (S->Sym.Tab == 0) {
+ /* Symbol not in a table. This may happen if there have been errors
+ * before. Return NULL in this case to avoid further errors.
+ */
+ return 0;
} else {
/* This is a global symbol */
return S->Sym.Tab->Parent;
+unsigned GetSymExportId (const SymEntry* S)
+/* Return the export id for the given symbol */
+{
+ PRECONDITION (S != 0 && (S->Flags & SF_EXPORT) && S->ExportId != ~0U);
+ return S->ExportId;
+}
+
+
+
unsigned GetSymInfoFlags (const SymEntry* S, long* ConstVal)
/* Return a set of flags used when writing symbol information into a file.
* If the SYM_CONST bit is set, ConstVal will contain the constant value
Flags |= SymIsConst (S, ConstVal)? SYM_CONST : SYM_EXPR;
Flags |= (S->Flags & SF_LABEL)? SYM_LABEL : SYM_EQUATE;
Flags |= (S->Flags & SF_LOCAL)? SYM_CHEAP_LOCAL : SYM_STD;
+ if (S->Flags & SF_EXPORT) {
+ Flags |= SYM_EXPORT;
+ }
+ if (S->Flags & SF_IMPORT) {
+ Flags |= SYM_IMPORT;
+ }
/* Return the result */
return Flags;
-const FilePos* GetSymPos (const SymEntry* S)
-/* Return the position of first occurence in the source for the given symbol */
-{
- /* The actual source entry is in slot zero */
- return &((const LineInfo*) CollConstAt (&S->LineInfos, 0))->Pos;
-}
-
-
-