1
0
mirror of https://github.com/cc65/cc65.git synced 2024-10-02 06:56:39 +00:00

More stringpool use / memory savings

git-svn-id: svn://svn.cc65.org/cc65/trunk@2199 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2003-06-05 16:50:01 +00:00
parent cea9aff3ef
commit eb5637b6e4
7 changed files with 233 additions and 136 deletions

View 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);
}

View 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 */

View File

@ -49,9 +49,10 @@
#include "error.h"
#include "exports.h"
#include "fileio.h"
#include "library.h"
#include "objdata.h"
#include "objfile.h"
#include "library.h"
#include "spool.h"
@ -63,19 +64,18 @@
/* 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);
/* All references to strings are now resolved, so we can delete
* the module string pool.
*/
FreeObjStrings (O);
/* Add a pointer to the library name */
O->LibName = LibName;
/* Insert the object into the list of all used object files */
InsertObjData (O);
} else {
/* Unreferenced object file, remove it */
FreeObjData (O);
}
}
/* Done. Close the file, release allocated memory */
fclose (F);
xfree (Index);
Lib = 0;
LibName = 0;
ModuleCount = 0;
Index = 0;
}

View 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) {
}
O = O->Next;
/* Get the object file */
ObjData* O = CollAtUnchecked (&ObjDataList, I);
/* 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);
for (I = 0; I < CollCount (&ObjDataList); ++I) {
}
O = O->Next;
/* Get the object file */
ObjData* O = CollAtUnchecked (&ObjDataList, I);
/* Output debug info */
PrintDbgInfo (O, F);
}
/* Close the file */

View File

@ -41,6 +41,7 @@
/* ld65 */
#include "error.h"
#include "exports.h"
#include "fileinfo.h"
#include "objdata.h"
#include "spool.h"
@ -53,11 +54,8 @@
/* 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]";
}

View File

@ -39,6 +39,7 @@
/* common */
#include "coll.h"
#include "objdefs.h"
@ -51,16 +52,14 @@
/* 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.

View 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"
@ -62,15 +63,15 @@
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);
}