]> git.sur5r.net Git - cc65/blobdiff - src/ca65/symtab.c
The longbranch macros did not work with numeric addresses
[cc65] / src / ca65 / symtab.c
index 4963d2c3a5e8ea37e03367ae660352ed491c8e5c..c54445faec0de0fecbb96804284abb55891ca74a 100644 (file)
@@ -36,6 +36,7 @@
 #include <string.h>
 
 /* 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 */
 #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,16 +1193,8 @@ 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;
-
-               /* 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;
-               }
+               /* Get the expression bits */
+                       ExprMask = GetExprMask (S);
 
                /* Write the type */
                ObjWrite8 (ExprMask);