]> git.sur5r.net Git - cc65/commitdiff
More stringpool use / memory savings
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 5 Jun 2003 16:50:01 +0000 (16:50 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 5 Jun 2003 16:50:01 +0000 (16:50 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@2199 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/ld65/exports.c
src/ld65/exports.h
src/ld65/library.c
src/ld65/mapfile.c
src/ld65/objdata.c
src/ld65/objdata.h
src/ld65/objfile.c

index 7520a1c9b3a636642648df0a6dfec5e4d7a0e66f..7aafb72b3113008fd831b8d2bc6d8e182004e722 100644 (file)
@@ -75,8 +75,12 @@ static unsigned              ImpOpen  = 0;           /* Count of open imports */
 static unsigned                ExpCount = 0;           /* Export count */
 static Export**                ExpPool  = 0;           /* Exports array */
 
+/* Defines for the flags in Import */
+#define IMP_INLIST      0x0001U                 /* Import is in exports list */
+
 /* Defines for the flags in Export */
-#define EXP_USERMARK           0x0001
+#define EXP_INLIST      0x0001U                 /* Export is in exports list */
+#define EXP_USERMARK           0x0002U                 /* User setable flag */
 
 
 
@@ -102,6 +106,7 @@ static Import* NewImport (unsigned char Type, ObjData* Obj)
     I->Obj     = Obj;
     I->Exp      = 0;
     I->Name     = INVALID_STRING_ID;
+    I->Flags    = 0;
     I->Type    = Type;
 
     /* Return the new structure */
@@ -157,6 +162,24 @@ void InsertImport (Import* I)
                /* This is a dummy export */
        ++ImpOpen;
     }
+
+    /* Mark the import so we know it's in the list */
+    I->Flags |= IMP_INLIST;
+}
+
+
+
+void FreeImport (Import* I)
+/* Free an import. NOTE: This won't remove the import from the exports table,
+ * so it may only be called for unused imports (imports from modules that
+ * aren't referenced).
+ */
+{
+    /* Safety */
+    PRECONDITION ((I->Flags & IMP_INLIST) == 0);
+
+    /* Free the struct */
+    xfree (I);
 }
 
 
@@ -217,6 +240,24 @@ static Export* NewExport (unsigned char Type, unsigned Name, ObjData* Obj)
 
 
 
+void FreeExport (Export* E)
+/* Free an export. NOTE: This won't remove the export from the exports table,
+ * so it may only be called for unused exports (exports from modules that
+ * aren't referenced).
+ */
+{
+    /* Safety */
+    PRECONDITION ((E->Flags & EXP_INLIST) == 0);
+
+    /* Free the export expression */
+    FreeExpr (E->Expr);
+
+    /* Free the struct */
+    xfree (E);
+}
+
+
+
 void InsertExport (Export* E)
 /* Insert an exported identifier and check if it's already in the list */
 {
@@ -225,6 +266,9 @@ void InsertExport (Export* E)
     Import* Imp;
     unsigned Hash;
 
+    /* Mark the export as inserted */
+    E->Flags |= EXP_INLIST;
+
     /* Insert the export into any condes tables if needed */
     if (IS_EXP_CONDES (E->Type)) {
                ConDesAddExport (E);
@@ -243,35 +287,37 @@ void InsertExport (Export* E)
        Last = 0;
        L = HashTab[Hash];
        do {
-           if (L->Name == E->Name) {
+                   if (L->Name == E->Name) {
                /* This may be an unresolved external */
                if (L->Expr == 0) {
 
-                   /* This *is* an unresolved external */
+                   /* This *is* an unresolved external. Use the actual export
+                     * in E instead of the dummy one in L.
+                     */
                    E->Next     = L->Next;
                    E->ImpCount = L->ImpCount;
                    E->ImpList  = L->ImpList;
-                   if (Last) {
-                       Last->Next = E;
-                   } else {
+                   if (Last) {
+                       Last->Next = E;
+                   } else {
                        HashTab[Hash] = E;
-                   }
+                   }
                            ImpOpen -= E->ImpCount;     /* Decrease open imports now */
-                   xfree (L);
-                   /* We must run through the import list and change the
+                   xfree (L);
+                   /* We must run through the import list and change the
                     * export pointer now.
-                    */
-                   Imp = E->ImpList;
-                   while (Imp) {
-                       Imp->Exp = E;
-                       Imp = Imp->Next;
-                   }
-               } else {
-                   /* Duplicate entry, ignore it */
-                           Warning ("Duplicate external identifier: `%s'", 
+                    */
+                   Imp = E->ImpList;
+                   while (Imp) {
+                       Imp->Exp = E;
+                       Imp = Imp->Next;
+                   }
+               } else {
+                   /* Duplicate entry, ignore it */
+                           Warning ("Duplicate external identifier: `%s'",
                              GetString (L->Name));
-               }
-               return;
+               }
+               return;
            }
            Last = L;
            L = L->Next;
@@ -491,15 +537,15 @@ static void CheckSymType (const Export* E)
                /* User defined export */
                Warning ("Type mismatch for `%s', export in "
                         "%s(%lu), import in %s(%lu)",
-                        GetString (E->Name), 
+                        GetString (E->Name),
                          GetSourceFileName (E->Obj, Imp->Pos.Name),
-                        E->Pos.Line, 
+                        E->Pos.Line,
                          GetSourceFileName (Imp->Obj, Imp->Pos.Name),
                         Imp->Pos.Line);
            } else {
                /* Export created by the linker */
                Warning ("Type mismatch for `%s', imported from %s(%lu)",
-                        GetString (E->Name), 
+                        GetString (E->Name),
                          GetSourceFileName (Imp->Obj, Imp->Pos.Name),
                         Imp->Pos.Line);
            }
@@ -557,7 +603,7 @@ static void PrintUnresolved (ExpCheckFunc F, void* Data)
 static int CmpExpName (const void* K1, const void* K2)
 /* Compare function for qsort */
 {
-    return strcmp (GetString ((*(Export**)K1)->Name), 
+    return strcmp (GetString ((*(Export**)K1)->Name),
                    GetString ((*(Export**)K2)->Name));
 }
 
@@ -728,11 +774,11 @@ void CircularRefError (const Export* E)
 /* Print an error about a circular reference using to define the given export */
 {
     Error ("Circular reference for symbol `%s', %s(%lu)",
-          GetString (E->Name), 
+          GetString (E->Name),
            GetSourceFileName (E->Obj, E->Pos.Name),
            E->Pos.Line);
 }
 
 
 
-           
+
index c28d49ed4018954cc4bc0a9da13ed7d8e59d5803..97a6eea6325b16be56c2803f65bde83649667f86 100644 (file)
@@ -65,6 +65,7 @@ struct Import {
     FilePos            Pos;            /* File position of reference */
     struct Export*     Exp;            /* Matching export for this import */
     unsigned            Name;          /* Name if not in table */
+    unsigned char       Flags;          /* Generic flags */
     unsigned char      Type;           /* Type of import */
 };
 
@@ -103,12 +104,24 @@ typedef int (*ExpCheckFunc) (unsigned Name, void* Data);
 
 
 
+void FreeImport (Import* I);
+/* Free an import. NOTE: This won't remove the import from the exports table,
+ * so it may only be called for unused imports (imports from modules that
+ * aren't referenced).
+ */
+
 Import* ReadImport (FILE* F, ObjData* Obj);
 /* Read an import from a file and insert it into the table */
 
 void InsertImport (Import* I);
 /* Insert an import into the table */
 
+void FreeExport (Export* E);
+/* Free an export. NOTE: This won't remove the export from the exports table,
+ * so it may only be called for unused exports (exports from modules that
+ * aren't referenced).
+ */
+
 Export* ReadExport (FILE* F, ObjData* Obj);
 /* Read an export from a file */
 
index 8b3c868a56355881458b4b503004d3b9b7bc4e4a..327c142d98da824c65a44aed0c8d5f4b29691f52 100644 (file)
 #include "error.h"
 #include "exports.h"
 #include "fileio.h"
+#include "library.h"
 #include "objdata.h"
 #include "objfile.h"
-#include "library.h"
+#include "spool.h"
 
 
 
 
 /* Library data */
 static FILE*           Lib             = 0;
-static char*           LibName         = 0;
 static unsigned                ModuleCount     = 0;
 static ObjData**       Index           = 0;
 
 
 
 /*****************************************************************************/
-/*                      Reading file data structures                        */
+/*                      Reading file data structures                        */
 /*****************************************************************************/
 
 
 
-static void LibReadObjHeader (ObjData* O)
+static void LibReadObjHeader (ObjData* O, const char* LibName)
 /* Read the header of the object file checking the signature */
 {
     O->Header.Magic = Read32 (Lib);
@@ -117,10 +117,14 @@ static ObjData* ReadIndexEntry (void)
     /* Create a new entry and insert it into the list */
     ObjData* O = NewObjData ();
 
-    /* Module name/flags/MTime/Start/Size */
-    O->Name            = ReadStr (Lib);
+    /* Module name */
+    char* Name = ReadStr (Lib);
+    O->Name = GetStringId (Name);
+    xfree (Name);
+
+    /* Module flags/MTime/Start/Size */
     O->Flags   = Read16 (Lib);
-    Read32 (Lib);                      /* Skip MTime */
+    O->MTime    = Read32 (Lib);      
     O->Start   = Read32 (Lib);
     Read32 (Lib);                      /* Skip Size */
 
@@ -208,13 +212,14 @@ void LibAdd (FILE* F, const char* Name)
  * be satisfied.
  */
 {
-    int Add;
+    unsigned LibName;
+    int HaveAdditions;
     unsigned I;
     LibHeader Header;
 
     /* Store the parameters, so they're visible for other routines */
     Lib     = F;
-    LibName = xstrdup (Name);
+    LibName = GetStringId (Name);
 
     /* Read the remaining header fields (magic is already read) */
     Header.Magic   = LIB_MAGIC;
@@ -235,27 +240,31 @@ void LibAdd (FILE* F, const char* Name)
      * were added.
      */
     do {
-       Add = 0;
-       for (I = 0; I < ModuleCount; ++I) {
-           ObjData* O = Index [I];
-           if ((O->Flags & OBJ_REF) == 0) {
-               LibCheckExports (O);
-               if (O->Flags & OBJ_REF) {
-                   /* The routine added the file */
-                   Add = 1;
-               }
-           }
-       }
-    } while (Add);
+       HaveAdditions = 0;
+       for (I = 0; I < ModuleCount; ++I) {
+           ObjData* O = Index [I];
+           if ((O->Flags & OBJ_REF) == 0) {
+               LibCheckExports (O);
+               if (O->Flags & OBJ_REF) {
+                   /* The routine added the file */
+                   HaveAdditions = 1;
+               }
+           }
+       }
+    } while (HaveAdditions);
 
     /* Add the files list and sections for all requested modules */
     for (I = 0; I < ModuleCount; ++I) {
+
+        /* Get the object data */
        ObjData* O = Index [I];
+
+        /* Is this object file referenced? */
        if (O->Flags & OBJ_REF) {
 
            /* Seek to the start of the object file and read the header */
            fseek (Lib, O->Start, SEEK_SET);
-           LibReadObjHeader (O);
+           LibReadObjHeader (O, Name);
 
            /* Seek to the start of the files list and read the files list */
            fseek (Lib, O->Start + O->Header.FileOffs, SEEK_SET);
@@ -276,24 +285,29 @@ void LibAdd (FILE* F, const char* Name)
            fseek (Lib, O->Start + O->Header.SegOffs, SEEK_SET);
            ObjReadSections (Lib, O);
 
-           /* We have the data now */
-           O->Flags |= OBJ_HAVEDATA;
-       }
+            /* Add a pointer to the library name */
+            O->LibName = LibName;
+
+            /* All references to strings are now resolved, so we can delete
+             * the module string pool.
+             */
+            FreeObjStrings (O);
+
+            /* Insert the object into the list of all used object files */
+            InsertObjData (O);
+
+        } else {
 
-        /* All references to strings are now resolved, so we can delete
-         * the module string pool.
-         */
-        FreeObjStrings (O);
+            /* Unreferenced object file, remove it */
+            FreeObjData (O);
 
-       /* Add a pointer to the library name */
-       O->LibName = LibName;
+        }
     }
 
     /* Done. Close the file, release allocated memory */
     fclose (F);
     xfree (Index);
     Lib                = 0;
-    LibName    = 0;
     ModuleCount = 0;
     Index      = 0;
 }
index 7a8eab44ed0ea11021d12f9a040e23fb78457dff..af4ad219182bbc1525150bad8eacc56e471a165e 100644 (file)
@@ -60,7 +60,6 @@
 void CreateMapFile (void)
 /* Create a map file */
 {
-    ObjData* O;
     unsigned I;
 
     /* Open the map file */
@@ -72,28 +71,30 @@ void CreateMapFile (void)
     /* Write a modules list */
     fprintf (F, "Modules list:\n"
                "-------------\n");
-    O = ObjRoot;
-    while (O) {
-       if (O->Flags & OBJ_HAVEDATA) {
-           /* We've linked this module */
-           if (O->LibName) {
-               /* The file is from a library */
-               fprintf (F, "%s(%s):\n", O->LibName, GetObjFileName (O));
-           } else {
-               fprintf (F, "%s:\n", GetObjFileName (O));
-           }
-           for (I = 0; I < O->SectionCount; ++I) {
-               const Section* S = O->Sections [I];
-               /* Don't include zero sized sections if not explicitly
-                * requested
-                */
-               if (VerboseMap || S->Size > 0) {
-                           fprintf (F, "    %-15s   Offs = %06lX   Size = %06lX\n",
-                            GetString (S->Seg->Name), S->Offs, S->Size);
-               }
-           }
-       }
-       O = O->Next;
+    for (I = 0; I < CollCount (&ObjDataList); ++I) {
+
+        unsigned J;
+
+        /* Get the object file */
+        const ObjData* O = CollConstAt (&ObjDataList, I);
+
+        /* Output the data */
+        if (O->LibName != INVALID_STRING_ID) {
+            /* The file is from a library */
+            fprintf (F, "%s(%s):\n", GetString (O->LibName), GetObjFileName (O));
+        } else {
+            fprintf (F, "%s:\n", GetObjFileName (O));
+        }
+        for (J = 0; J < O->SectionCount; ++J) {
+            const Section* S = O->Sections [J];
+            /* Don't include zero sized sections if not explicitly
+             * requested
+             */
+            if (VerboseMap || S->Size > 0) {
+                fprintf (F, "    %-15s   Offs = %06lX   Size = %06lX\n",
+                         GetString (S->Seg->Name), S->Offs, S->Size);
+            }
+        }
     }
 
     /* Write the segment list */
@@ -125,7 +126,7 @@ void CreateMapFile (void)
 void CreateLabelFile (void)
 /* Create a label file */
 {
-    ObjData* O;
+    unsigned I;
 
     /* Open the label file */
     FILE* F = fopen (LabelFileName, "w");
@@ -136,15 +137,14 @@ void CreateLabelFile (void)
     /* Print the labels for the export symbols */
     PrintExportLabels (F);
 
-    /* Print debug symbols from all modules we have linked into the output file */
-    O = ObjRoot;
-    while (O) {
-       if (O->Flags & OBJ_HAVEDATA) {
-           /* We've linked this module */
-           PrintDbgSymLabels (O, F);
+    /* Create labels from all modules we have linked into the output file */
+    for (I = 0; I < CollCount (&ObjDataList); ++I) {
+
+        /* Get the object file */
+        ObjData* O = CollAtUnchecked (&ObjDataList, I);
 
-       }
-       O = O->Next;
+        /* Output the labels */
+       PrintDbgSymLabels (O, F);
     }
 
     /* If we should mark write protected areas as such, do it */
@@ -174,7 +174,7 @@ void CreateLabelFile (void)
 void CreateDbgFile (void)
 /* Create a debug info file */
 {
-    ObjData* O;
+    unsigned I;
 
     /* Open the debug info file */
     FILE* F = fopen (DbgFileName, "w");
@@ -183,14 +183,13 @@ void CreateDbgFile (void)
     }
 
     /* Print line infos from all modules we have linked into the output file */
-    O = ObjRoot;
-    while (O) {
-       if (O->Flags & OBJ_HAVEDATA) {
-           /* We've linked this module */
-           PrintDbgInfo (O, F);
-
-       }
-       O = O->Next;
+    for (I = 0; I < CollCount (&ObjDataList); ++I) {
+
+        /* Get the object file */
+        ObjData* O = CollAtUnchecked (&ObjDataList, I);
+
+        /* Output debug info */
+       PrintDbgInfo (O, F);
     }
 
     /* Close the file */
index 484c5431f7676f77f12113282298bfbeb3008c1c..6da81965c01d83f7691f976514534e27a09b0f4b 100644 (file)
@@ -41,6 +41,7 @@
 
 /* ld65 */
 #include "error.h"
+#include "exports.h"
 #include "fileinfo.h"
 #include "objdata.h"
 #include "spool.h"
 
 
 
-/* Object data list management */
-unsigned       ObjCount = 0;   /* Count of object files in the list */
-ObjData*       ObjRoot  = 0;   /* List of object files */
-ObjData*       ObjLast  = 0;   /* Last entry in list */
-ObjData**              ObjPool  = 0;   /* Object files as array */
+/* Collection containing used ObjData objects */
+Collection       ObjDataList = STATIC_COLLECTION_INITIALIZER;
 
 
 
@@ -75,8 +73,9 @@ ObjData* NewObjData (void)
 
     /* Initialize the data */
     O->Next            = 0;
-    O->Name            = 0;
-    O->LibName         = 0;
+    O->Name            = INVALID_STRING_ID;
+    O->LibName         = INVALID_STRING_ID;
+    O->MTime            = 0;
     O->Flags                   = 0;
     O->Start           = 0;
     O->ExportCount     = 0;
@@ -90,24 +89,33 @@ ObjData* NewObjData (void)
     O->StringCount      = 0;
     O->Strings          = 0;
 
-    /* Link it into the list */
-    if (ObjLast) {
-       ObjLast->Next = O;
-       ObjLast       = O;
-    } else {
-       /* First entry */
-       ObjRoot = ObjLast = O;
-    }
-
-    /* One object file more now */
-    ++ObjCount;
-
     /* Return the new entry */
     return O;
 }
 
 
 
+void FreeObjData (ObjData* O)
+/* Free an ObjData object. NOTE: This function works only for unused object
+ * data, that is, ObjData objects that aren't used because they aren't
+ * referenced.
+ */
+{
+    /* Unused ObjData do only have the string pool, Exports and Imports. */
+    while (O->ExportCount) {
+        FreeExport (O->Exports[--O->ExportCount]);
+    }
+    xfree (O->Exports);
+    while (O->ImportCount) {
+        FreeImport (O->Imports[--O->ImportCount]);
+    }
+    xfree (O->Imports);
+    FreeObjStrings (O);
+    xfree (O);
+}
+
+
+
 void FreeObjStrings (ObjData* O)
 /* Free the module string data. Used once the object file is loaded completely
  * when all strings are converted to global strings.
@@ -122,6 +130,14 @@ void FreeObjStrings (ObjData* O)
 
 
 
+void InsertObjData (ObjData* O)
+/* Insert the ObjData object into the collection of used ObjData objects. */
+{
+    CollAppend (&ObjDataList, O);
+}
+
+
+
 const char* GetObjString (const ObjData* O, unsigned Index)
 /* Get a string from the object file string table. Abort if the string index
  * is invalid.
@@ -153,7 +169,7 @@ const char* GetObjFileName (const ObjData* O)
  * file is NULL.
  */
 {
-    return O? O->Name : "[linker generated]";
+    return O? GetString (O->Name) : "[linker generated]";
 }
 
 
index 8da6fc080dd179b9f020bb5c5bb5db8c93fcc244..0174b733d7c3ba699b711c1ffb5a0a64fc1174ce 100644 (file)
@@ -39,6 +39,7 @@
 
 
 /* common */
+#include "coll.h"
 #include "objdefs.h"
 
 
 
 /* Values for the Flags field */
 #define        OBJ_REF         0x0001          /* We have a reference to this file */
-#define OBJ_HAVEDATA   0x0002          /* We have this object file already */
-#define OBJ_MARKED             0x0004          /* Generic marker bit */
-
 
 /* Internal structure holding object file data */
 typedef struct ObjData ObjData;
 struct ObjData {
-    ObjData*           Next;           /* Linked list of all objects */
-    char*              Name;           /* Module name */
-    char*                      LibName;        /* Name of library */
+    ObjData*           Next;           /* Linked list of all objects */
+    unsigned            Name;                  /* Module name */
+    unsigned            LibName;       /* Name of library */
+    unsigned long       MTime;          /* Time of last modification */
     ObjHeader          Header;         /* Header of file */
     unsigned long      Start;          /* Start offset of data in library */
     unsigned           Flags;
@@ -82,15 +81,13 @@ struct ObjData {
 
 
 
-/* Object data list management */
-extern unsigned                ObjCount;       /* Count of files in the list */
-extern ObjData*                ObjRoot;        /* List of object files */
-extern ObjData*                ObjLast;        /* Last entry in list */
+/* Collection containing used ObjData objects */
+extern Collection       ObjDataList;
 
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                          Code                                    */
 /*****************************************************************************/
 
 
@@ -98,11 +95,20 @@ extern ObjData*             ObjLast;        /* Last entry in list */
 ObjData* NewObjData (void);
 /* Allocate a new structure on the heap, insert it into the list, return it */
 
+void FreeObjData (ObjData* O);
+/* Free an ObjData object. NOTE: This function works only for unused object
+ * data, that is, ObjData objects that aren't used because they aren't
+ * referenced.
+ */
+
 void FreeObjStrings (ObjData* O);
 /* Free the module string data. Used once the object file is loaded completely
  * when all strings are converted to global strings.
  */
 
+void InsertObjData (ObjData* O);
+/* Insert the ObjData object into the collection of used ObjData objects. */
+
 const char* GetObjString (const ObjData* O, unsigned Index);
 /* Get a string from the object file string table. Abort if the string index
  * is invalid.
index ff9a14b57315bf44b54807470a7c8a5f82e27888..7404b2cacb7fc296e6cdeda12724462efec079d1 100644 (file)
@@ -51,8 +51,9 @@
 #include "fileio.h"
 #include "lineinfo.h"
 #include "objdata.h"
-#include "segments.h"
 #include "objfile.h"
+#include "segments.h"
+#include "spool.h"
 
 
 
 
 
 
-static const char* GetModule (const char* Name)
-/* Get a module name from the file name */
+static unsigned GetModule (const char* Name)
+/* Get a module name index from the file name */
 {
     /* Make a module name from the file name */
     const char* Module = FindName (Name);
     if (*Module == 0) {
        Error ("Cannot make module name from `%s'", Name);
     }
-    return Module;
+    return GetStringId (Module);
 }
 
 
@@ -216,8 +217,7 @@ void ObjAdd (FILE* Obj, const char* Name)
     ObjReadHeader (Obj, &O->Header, Name);
 
     /* Initialize the object module data structure */
-    O->Name  = xstrdup (GetModule (Name));
-    O->Flags = OBJ_HAVEDATA;
+    O->Name  = GetModule (Name);
 
     /* Read the string pool from the object file */
     fseek (Obj, O->Header.StrPoolOffs, SEEK_SET);
@@ -251,7 +251,7 @@ void ObjAdd (FILE* Obj, const char* Name)
     ObjReadSections (Obj, O);
 
     /* Mark this object file as needed */
-    O->Flags |= OBJ_REF | OBJ_HAVEDATA;
+    O->Flags |= OBJ_REF;
 
     /* Done, close the file (we read it only, so no error check) */
     fclose (Obj);
@@ -260,6 +260,9 @@ void ObjAdd (FILE* Obj, const char* Name)
      * string pool.
      */
     FreeObjStrings (O);
+
+    /* Insert the object into the list of all used object files */
+    InsertObjData (O);
 }