X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fca65%2Fsymtab.c;h=c54445faec0de0fecbb96804284abb55891ca74a;hb=46209118b1a77d2e57f28026b1e5916c2c074778;hp=f43b4c7b1178b2d790834564a1044e3908ace7f8;hpb=9977ddd973057db1cfa520b859d8b19e6000d704;p=cc65 diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index f43b4c7b1..c54445fae 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -36,6 +36,7 @@ #include /* common */ +#include "cddefs.h" #include "check.h" #include "hashstr.h" #include "symdefs.h" @@ -63,9 +64,9 @@ #define SF_EXPORT 0x0004 /* Export this symbol */ #define SF_IMPORT 0x0008 /* Import this symbol */ #define SF_GLOBAL 0x0010 /* Global symbol */ -#define SF_INITIALIZER 0x0020 /* Exported initializer */ -#define SF_ZP 0x0040 /* Declared as zeropage symbol */ -#define SF_ABS 0x0080 /* Declared as absolute symbol */ +#define SF_ZP 0x0020 /* Declared as zeropage symbol */ +#define SF_ABS 0x0040 /* Declared as absolute symbol */ +#define SF_LABEL 0x0080 /* Used as a label */ #define SF_INDEXED 0x0800 /* Index is valid */ #define SF_CONST 0x1000 /* The symbol has a constant value */ #define SF_MULTDEF 0x2000 /* Multiply defined symbol */ @@ -83,34 +84,36 @@ #define SF_DBGINFOVAL (SF_DEFINED) /* Structure of a symbol table entry */ -struct SymEntry_ { +struct SymEntry { SymEntry* Left; /* Lexically smaller entry */ - SymEntry* Right; /* Lexically larger entry */ - SymEntry* List; /* List of all entries */ + SymEntry* Right; /* Lexically larger entry */ + SymEntry* List; /* List of all entries */ SymEntry* Locals; /* Root of subtree for local symbols */ - struct SymTable_* SymTab; /* Table this symbol is in, 0 for locals */ + struct SymTable* SymTab; /* Table this symbol is in, 0 for locals */ FilePos Pos; /* File position for this symbol */ unsigned Flags; /* Symbol flags */ unsigned Index; /* Index of import/export entries */ union { - struct ExprNode_* Expr; /* Expression if CONST not set */ + struct ExprNode* Expr; /* Expression if CONST not set */ long Val; /* Value (if CONST set) */ - SymEntry* Sym; /* Symbol (if trampoline entry) */ + SymEntry* Sym; /* Symbol (if trampoline entry) */ } V; + unsigned char ConDesPrio[CD_TYPE_COUNT]; /* ConDes priorities... */ + /* ...actually value+1 (used as flag) */ char Name [1]; /* Dynamic allocation */ }; /* Definitions for the hash table */ -#define MAIN_HASHTAB_SIZE 213 -#define SUB_HASHTAB_SIZE 53 -typedef struct SymTable_ SymTable; -struct SymTable_ { - unsigned TableSlots; /* Number of hash table slots */ - unsigned TableEntries; /* Number of entries in the table */ +#define MAIN_HASHTAB_SIZE 213 +#define SUB_HASHTAB_SIZE 53 +typedef struct SymTable SymTable; +struct SymTable { + unsigned TableSlots; /* Number of hash table slots */ + unsigned TableEntries; /* Number of entries in the table */ SymTable* BackLink; /* Link to enclosing scope if any */ - SymEntry* Table [1]; /* Dynamic allocation */ + SymEntry* Table [1]; /* Dynamic allocation */ }; @@ -158,13 +161,14 @@ static SymEntry* NewSymEntry (const char* Name) S = xmalloc (sizeof (SymEntry) + Len); /* Initialize the entry */ - S->Left = 0; - S->Right = 0; - S->Locals = 0; - S->SymTab = 0; - S->Flags = 0; - S->V.Expr = 0; - S->Pos = CurPos; + S->Left = 0; + S->Right = 0; + S->Locals = 0; + S->SymTab = 0; + S->Pos = CurPos; + S->Flags = 0; + S->V.Expr = 0; + memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio)); memcpy (S->Name, Name, Len+1); /* Insert it into the list of all entries */ @@ -396,14 +400,14 @@ void SymLeaveLevel (void) -void SymDef (const char* Name, ExprNode* Expr, int ZP) +void SymDef (const char* Name, ExprNode* Expr, int ZP, int Label) /* Define a new symbol */ { /* Do we have such a symbol? */ SymEntry* S = SymFind (SymTab, Name, SF_ALLOC_NEW); if (S->Flags & SF_IMPORT) { /* Defined symbol is marked as imported external symbol */ - Error (ERR_SYM_ALREADY_IMPORT); + Error (ERR_SYM_ALREADY_IMPORT, Name); return; } if (S->Flags & SF_DEFINED) { @@ -427,6 +431,9 @@ void SymDef (const char* Name, ExprNode* Expr, int ZP) if (ZP) { S->Flags |= SF_ZP; } + if (Label) { + S->Flags |= SF_LABEL; + } /* If the symbol is a ZP symbol, check if the value is in correct range */ if (S->Flags & SF_ZP) { @@ -482,7 +489,7 @@ void SymImport (const char* Name, int ZP) } if (S->Flags & SF_EXPORT) { /* The symbol is already marked as exported symbol */ - Error (ERR_SYM_ALREADY_EXPORT); + Error (ERR_SYM_ALREADY_EXPORT, Name); return; } @@ -520,7 +527,7 @@ void SymExport (const char* Name, int ZP) S = SymFind (SymTab, Name, SF_ALLOC_NEW); if (S->Flags & SF_IMPORT) { /* The symbol is already marked as imported external symbol */ - Error (ERR_SYM_ALREADY_IMPORT); + Error (ERR_SYM_ALREADY_IMPORT, Name); return; } @@ -577,18 +584,20 @@ void SymGlobal (const char* Name, int ZP) -void SymInitializer (const char* Name, int ZP) -/* Mark the given symbol as an initializer. This will also mark the symbol as - * an export. Initializers may never be zero page symbols, the ZP parameter - * is supplied to make the prototype the same as the other functions (this - * is used in pseudo.c). Passing something else but zero as ZP argument will - * trigger an internal error. +void SymConDes (const char* Name, 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. */ { SymEntry* S; - /* Check the ZP parameter */ - CHECK (ZP == 0); + /* 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 (IsLocal (Name)) { @@ -600,22 +609,32 @@ void SymInitializer (const char* Name, int ZP) S = SymFind (SymTab, Name, SF_ALLOC_NEW); if (S->Flags & SF_IMPORT) { /* The symbol is already marked as imported external symbol */ - Error (ERR_SYM_ALREADY_IMPORT); + Error (ERR_SYM_ALREADY_IMPORT, Name); return; } - /* If the symbol is marked as global, check the symbol size, then do - * silently remove the global flag - */ + /* If the symbol is marked as global, silently remove the global flag */ if (S->Flags & SF_GLOBAL) { - if ((S->Flags & SF_ZP) != 0) { - Error (ERR_SYM_REDECL_MISMATCH); - } S->Flags &= ~SF_GLOBAL; } + /* Check if the symbol was not already defined as ZP symbol */ + if ((S->Flags & SF_ZP) != 0) { + Error (ERR_SYM_REDECL_MISMATCH); + } + + /* 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 (ERR_SYM_REDECL_MISMATCH); + } + } + S->ConDesPrio[Type] = Prio; + /* Set the symbol data */ - S->Flags |= SF_EXPORT | SF_INITIALIZER | SF_REFERENCED; + S->Flags |= SF_EXPORT | SF_REFERENCED; } @@ -624,7 +643,7 @@ int SymIsDef (const char* Name) /* Return true if the given symbol is already defined */ { SymEntry* S = SymFindAny (SymTab, Name); - return S != 0 && (S->Flags & (SF_DEFINED | SF_IMPORT)) != 0; + return S != 0 && (S->Flags & SF_DEFINED) != 0; } @@ -896,7 +915,7 @@ static void SymCheckUndefined (SymEntry* S) if (S->Flags & SF_EXPORT) { if (Sym->Flags & SF_IMPORT) { /* The symbol is already marked as imported external symbol */ - PError (&S->Pos, ERR_SYM_ALREADY_IMPORT); + PError (&S->Pos, ERR_SYM_ALREADY_IMPORT, S->Name); } Sym->Flags |= S->Flags & (SF_EXPORT | SF_ZP); } @@ -1004,13 +1023,14 @@ void SymDump (FILE* F) while (S) { /* Ignore trampoline symbols */ if ((S->Flags & SF_TRAMPOLINE) != 0) { - printf ("%-24s %s %s %s %s %s\n", - S->Name, - (S->Flags & SF_DEFINED)? "DEF" : "---", - (S->Flags & SF_REFERENCED)? "REF" : "---", - (S->Flags & SF_IMPORT)? "IMP" : "---", - (S->Flags & SF_EXPORT)? "EXP" : "---", - (S->Flags & SF_ZP)? "ZP" : "--"); + fprintf (F, + "%-24s %s %s %s %s %s\n", + S->Name, + (S->Flags & SF_DEFINED)? "DEF" : "---", + (S->Flags & SF_REFERENCED)? "REF" : "---", + (S->Flags & SF_IMPORT)? "IMP" : "---", + (S->Flags & SF_EXPORT)? "EXP" : "---", + (S->Flags & SF_ZP)? "ZP" : "--"); } /* Next symbol */ S = S->List; @@ -1051,10 +1071,31 @@ void WriteImports (void) +static unsigned char GetExprMask (SymEntry* S) +/* Return the expression bits for the given symbol table entry */ +{ + unsigned char ExprMask; + + /* Check if the symbol is const */ + ExprMask = (SymIsConst (S))? EXP_CONST : EXP_EXPR; + + /* Add zeropage/abs bits */ + ExprMask |= (S->Flags & SF_ZP)? EXP_ZP : EXP_ABS; + + /* Add the label/equate bits */ + ExprMask |= (S->Flags & SF_LABEL)? EXP_LABEL : EXP_EQUATE; + + /* Return the mask */ + return ExprMask; +} + + + void WriteExports (void) /* Write the exports list to the object file */ { SymEntry* S; + unsigned Type; /* Tell the object file module that we're about to start the exports */ ObjStartExports (); @@ -1071,20 +1112,29 @@ void WriteExports (void) /* Finalize an associated expression if we have one */ SymFinalize (S); - /* Check if the symbol is const */ - ExprMask = (SymIsConst (S))? EXP_CONST : EXP_EXPR; + /* Get the expression bits */ + ExprMask = GetExprMask (S); - /* Add zeropage/abs bits */ - ExprMask |= (S->Flags & SF_ZP)? EXP_ZP : EXP_ABS; - - /* Add the initializer bits */ - if (S->Flags & SF_INITIALIZER) { - ExprMask |= EXP_INITIALIZER; + /* 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); + } } /* Write the type */ ObjWrite8 (ExprMask); + /* 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)); + } + } + } + /* Write the name */ ObjWriteStr (S->Name); @@ -1143,23 +1193,25 @@ void WriteDbgSyms (void) /* Finalize an associated expression if we have one */ SymFinalize (S); - /* Check if the symbol is const */ - ExprMask = (SymIsConst (S))? EXP_CONST : EXP_EXPR; + /* Get the expression bits */ + ExprMask = GetExprMask (S); /* Write the type */ - if (S->Flags & SF_ZP) { - ObjWrite8 (EXP_ZP | ExprMask); - } else { - ObjWrite8 (EXP_ABS | ExprMask); - } + ObjWrite8 (ExprMask); + + /* Write the name */ ObjWriteStr (S->Name); - if (ExprMask == EXP_CONST) { + + /* Write the value */ + if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) { /* Constant value */ ObjWrite32 (S->V.Val); } else { /* Expression involved */ WriteExpr (S->V.Expr); } + + /* Write the source file position */ ObjWritePos (&S->Pos); } S = S->List;