X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fca65%2Fsymentry.c;h=a47fde9a64237f25ff6c35cc7ce616894a496368;hb=5ef1f65c9bd9f83ecbb8c66c6d8f8da0dec85e47;hp=35e60b5efad61779d737a1bed820c9257535fc17;hpb=1e624c5e91a66ac1706fe2cf1a1e0fa55ceca61a;p=cc65 diff --git a/src/ca65/symentry.c b/src/ca65/symentry.c index 35e60b5ef..a47fde9a6 100644 --- a/src/ca65/symentry.c +++ b/src/ca65/symentry.c @@ -44,6 +44,7 @@ #include "expr.h" #include "global.h" #include "scanner.h" +#include "segment.h" #include "spool.h" #include "symentry.h" #include "symtab.h" @@ -94,8 +95,8 @@ static unsigned SymAddrSize (const SymEntry* S) return ADDR_SIZE_ABS; } - /* Return the address size of the enclosing scope */ - return S->SymTab->AddrSize; + /* Return the address size of the segment */ + return GetCurrentSegAddrSize (); } @@ -130,6 +131,43 @@ SymEntry* NewSymEntry (const char* Name) +int SymSearchTree (SymEntry* T, const char* Name, SymEntry** E) +/* Search in the given tree for a name. If we find the symbol, the function + * will return 0 and put the entry pointer into E. If we did not find the + * symbol, and the tree is empty, E is set to NULL. If the tree is not empty, + * E will be set to the last entry, and the result of the function is <0 if + * the entry should be inserted on the left side, and >0 if it should get + * inserted on the right side. + */ +{ + /* Is there a tree? */ + if (T == 0) { + *E = 0; + return 1; + } + + /* We have a table, search it */ + while (1) { + + /* Get the symbol name */ + const char* SymName = GetString (T->Name); + + /* Choose next entry */ + int Cmp = strcmp (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 */ + *E = T; + return Cmp; + } + } +} + + + void SymRef (SymEntry* S) /* Mark the given symbol as referenced */ { @@ -139,7 +177,7 @@ void SymRef (SymEntry* S) -void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags) +void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags) /* Define a new symbol */ { if (S->Flags & SF_IMPORT) { @@ -156,11 +194,16 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags) /* Map a default address size to a real value */ if (AddrSize == ADDR_SIZE_DEFAULT) { - AddrSize = SymAddrSize (S); + long Val; + if (IsConstExpr (Expr, &Val) && IsByteRange (Val)) { + AddrSize = ADDR_SIZE_ZP; + } else { + AddrSize = SymAddrSize (S); + } } /* Set the symbol value */ - S->V.Expr = Expr; + S->V.Expr = Expr; /* If the symbol is marked as global, export it */ if (S->Flags & SF_GLOBAL) { @@ -178,7 +221,9 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags) /* Use the real size of the symbol */ S->ExportSize = S->AddrSize; } else if (S->AddrSize > S->ExportSize) { - Warning (1, "Address size mismatch for symbol `%s'", GetSymName (S)); + PWarning (GetSymPos (S), 1, "Symbol `%s' is %s but exported as %s", + GetSymName (S), AddrSizeToStr (S->AddrSize), + AddrSizeToStr (S->ExportSize)); } } @@ -198,7 +243,7 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags) -void SymImport (SymEntry* S, unsigned AddrSize, unsigned Flags) +void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags) /* Mark the given symbol as an imported symbol */ { /* Don't accept local symbols */ @@ -226,11 +271,18 @@ void SymImport (SymEntry* S, unsigned AddrSize, unsigned Flags) /* If the symbol is marked as import or global, check the symbol flags, * then do silently remove the global flag */ - if (S->Flags & (SF_IMPORT | SF_GLOBAL)) { - if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED) || - AddrSize != S->AddrSize) { + if (S->Flags & SF_IMPORT) { + if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) { Error ("Redeclaration mismatch for symbol `%s'", GetSymName (S)); } + if (AddrSize != S->AddrSize) { + Error ("Address size mismatch for symbol `%s'", GetSymName (S)); + } + } + if (S->Flags & SF_GLOBAL) { + if (S->AddrSize != ADDR_SIZE_DEFAULT && S->AddrSize != AddrSize) { + Error ("Address size mismatch for symbol `%s'", GetSymName (S)); + } S->Flags &= ~SF_GLOBAL; } @@ -241,7 +293,7 @@ void SymImport (SymEntry* S, unsigned AddrSize, unsigned Flags) -void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags) +void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags) /* Mark the given symbol as an exported symbol */ { /* Don't accept local symbols */ @@ -257,15 +309,25 @@ void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags) return; } - /* If the symbol was already marked as an export or global, check if - * this was done specifiying the same address size. In case of a global - * declaration, silently remove the global flag. + /* If the symbol was marked as global before, make it an export */ + if (S->Flags & SF_GLOBAL) { + S->ExportSize = S->AddrSize; + S->Flags &= ~SF_GLOBAL; + } + + /* If the symbol was already marked as an export, check if this was done + * specifiying the same address size. If the old spec had no explicit + * address size, use the new one. */ - if (S->Flags & (SF_EXPORT | SF_GLOBAL)) { - if (S->ExportSize != AddrSize) { + if (S->Flags & SF_EXPORT) { + if (S->ExportSize == ADDR_SIZE_DEFAULT) { + S->ExportSize = AddrSize; + } else if (AddrSize == ADDR_SIZE_DEFAULT) { + AddrSize = S->ExportSize; + } + if (S->ExportSize != ADDR_SIZE_DEFAULT && S->ExportSize != AddrSize) { Error ("Address size mismatch for symbol `%s'", GetSymName (S)); } - S->Flags &= ~SF_GLOBAL; } S->ExportSize = AddrSize; @@ -274,10 +336,12 @@ void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags) */ if (S->Flags & SF_DEFINED) { if (S->ExportSize == ADDR_SIZE_DEFAULT) { - /* Use the real size of the symbol */ + /* No export size given, use the real size of the symbol */ S->ExportSize = S->AddrSize; } else if (S->AddrSize > S->ExportSize) { - Warning (1, "Address size mismatch for symbol `%s'", GetSymName (S)); + Warning (1, "Symbol `%s' is %s but exported as %s", + GetSymName (S), AddrSizeToStr (S->AddrSize), + AddrSizeToStr (S->ExportSize)); } } @@ -287,7 +351,7 @@ void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags) -void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags) +void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags) /* Mark the given symbol as a global symbol, that is, as a symbol that is * either imported or exported. */ @@ -298,21 +362,22 @@ void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags) return; } - /* Map a default address size to a real value */ - if (AddrSize == ADDR_SIZE_DEFAULT) { - AddrSize = SymAddrSize (S); - } - /* If the symbol is already marked as import or export, check the * size of the definition, then bail out. */ if (S->Flags & SF_IMPORT) { - if (AddrSize != S->AddrSize) { + if (AddrSize != ADDR_SIZE_DEFAULT && AddrSize != S->AddrSize) { Error ("Address size mismatch for symbol `%s'", GetSymName (S)); } return; } if (S->Flags & SF_EXPORT) { + /* If the old symbol had no explicit address size spec, use the + * new one. + */ + if (S->ExportSize == ADDR_SIZE_DEFAULT) { + S->ExportSize = AddrSize; + } if (AddrSize != S->ExportSize) { Error ("Address size mismatch for symbol `%s'", GetSymName (S)); } @@ -324,8 +389,14 @@ void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags) */ if (S->Flags & SF_DEFINED) { /* The symbol is defined, export it */ - if (S->ExportSize != AddrSize) { - Error ("Address size mismatch for symbol `%s'", GetSymName (S)); + S->ExportSize = AddrSize; + if (S->ExportSize == ADDR_SIZE_DEFAULT) { + /* No export size given, use the real size of the symbol */ + S->ExportSize = S->AddrSize; + } else if (S->AddrSize > S->ExportSize) { + Warning (1, "Symbol `%s' is %s but exported as %s", + GetSymName (S), AddrSizeToStr (S->AddrSize), + AddrSizeToStr (S->ExportSize)); } S->Flags |= (SF_EXPORT | Flags); S->ExportSize = AddrSize; @@ -337,6 +408,72 @@ void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags) +void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Prio) +/* Mark the given symbol as a module constructor/destructor. This will also + * mark the symbol as an export. Initializers may never be zero page symbols. + */ +{ + /* Check the parameters */ +#if (CD_TYPE_MIN != 0) + CHECK (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX); +#else + CHECK (Type <= CD_TYPE_MAX); +#endif + CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX); + + /* Don't accept local symbols */ + if (IsLocalNameId (S->Name)) { + Error ("Illegal use of a local symbol"); + return; + } + + /* Check for errors */ + if (S->Flags & SF_IMPORT) { + /* The symbol is already marked as imported external symbol */ + Error ("Symbol `%s' is already an import", GetSymName (S)); + return; + } + + /* If the symbol was already marked as an export or global, check if + * this was done specifiying the same address size. In case of a global + * declaration, silently remove the global flag. + */ + if (S->Flags & (SF_EXPORT | SF_GLOBAL)) { + if (S->ExportSize != AddrSize) { + Error ("Address size mismatch for symbol `%s'", GetSymName (S)); + } + S->Flags &= ~SF_GLOBAL; + } + S->ExportSize = AddrSize; + + /* If the symbol is already defined, check symbol size against the + * exported size. + */ + if (S->Flags & SF_DEFINED) { + if (S->ExportSize == ADDR_SIZE_DEFAULT) { + /* Use the real size of the symbol */ + S->ExportSize = S->AddrSize; + } else if (S->AddrSize != S->ExportSize) { + Error ("Address size mismatch for symbol `%s'", GetSymName (S)); + } + } + + /* If the symbol was already declared as a condes, check if the new + * 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 `%s'", GetSymName (S)); + } + } + S->ConDesPrio[Type] = Prio; + + /* Set the symbol data */ + S->Flags |= (SF_EXPORT | SF_REFERENCED); +} + + + int SymIsDef (const SymEntry* S) /* Return true if the given symbol is already defined */ { @@ -480,7 +617,7 @@ const char* GetSymName (const SymEntry* S) -unsigned GetSymAddrSize (const SymEntry* S) +unsigned char GetSymAddrSize (const SymEntry* S) /* Return the address size of the symbol. Beware: This function will just * return the AddrSize member, it will not look at the expression! */ @@ -493,6 +630,18 @@ unsigned GetSymAddrSize (const SymEntry* S) +long GetSymVal (SymEntry* S) +/* Return the value of a symbol assuming it's constant. FAIL will be called + * in case the symbol is undefined or not constant. + */ +{ + long Val; + CHECK (S != 0 && SymHasExpr (S) && IsConstExpr (GetSymExpr (S), &Val)); + return Val; +} + + + unsigned GetSymIndex (const SymEntry* S) /* Return the symbol index for the given symbol */ {