From 77bd3169f6df69b8f62ca52008fb4a999b5b035e Mon Sep 17 00:00:00 2001 From: uz Date: Sat, 3 Nov 2012 21:37:19 +0000 Subject: [PATCH] Added a new attribute IMPORT to the CONDES definition of the FEATURES section. If this attribute is defined, an import for the given symbol is added to the module that contains the condes declaraction. Using this feature, it is possible to force linkage of a module that contains an export for the symbol. git-svn-id: svn://svn.cc65.org/cc65/trunk@5900 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ld65/condes.c | 105 ++++++++++++++++++++++++++++++++++++------ src/ld65/condes.h | 29 ++++++++++-- src/ld65/config.c | 109 +++++++++++++++++++++++++------------------- src/ld65/exports.c | 60 ++++++++++++++++-------- src/ld65/lineinfo.c | 21 ++++++++- src/ld65/lineinfo.h | 3 ++ src/ld65/span.c | 17 +++++++ src/ld65/span.h | 3 ++ 8 files changed, 263 insertions(+), 84 deletions(-) diff --git a/src/ld65/condes.c b/src/ld65/condes.c index 836c9a58a..ebf1bdecb 100644 --- a/src/ld65/condes.c +++ b/src/ld65/condes.c @@ -1,15 +1,15 @@ /*****************************************************************************/ /* */ -/* condes.h */ +/* condes.c */ /* */ /* Module constructor/destructor support */ /* */ /* */ /* */ -/* (C) 2000-2008 Ullrich von Bassewitz */ -/* Roemerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2000-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -39,6 +39,7 @@ #include "addrsize.h" #include "check.h" #include "coll.h" +#include "filepos.h" #include "fragdefs.h" #include "xmalloc.h" @@ -62,20 +63,64 @@ typedef struct ConDesDesc ConDesDesc; struct ConDesDesc { Collection ExpList; /* List of exported symbols */ unsigned SegName; /* Name of segment the table is in */ - unsigned Label; /* Name of table label */ + unsigned Label; /* Name of table label */ unsigned CountSym; /* Name of symbol for entry count */ - unsigned char Order; /* Table order (increasing/decreasing) */ + unsigned char Order; /* Table order (increasing/decreasing) */ + ConDesImport Import; /* Forced import if any */ }; /* Array for all types */ static ConDesDesc ConDes[CD_TYPE_COUNT] = { - { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing }, - { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing }, - { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing }, - { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing }, - { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing }, - { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing }, - { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing }, + { + STATIC_COLLECTION_INITIALIZER, + INVALID_STRING_ID, + INVALID_STRING_ID, + INVALID_STRING_ID, + cdIncreasing, + { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, + },{ + STATIC_COLLECTION_INITIALIZER, + INVALID_STRING_ID, + INVALID_STRING_ID, + INVALID_STRING_ID, + cdIncreasing, + { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, + },{ + STATIC_COLLECTION_INITIALIZER, + INVALID_STRING_ID, + INVALID_STRING_ID, + INVALID_STRING_ID, + cdIncreasing, + { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, + },{ + STATIC_COLLECTION_INITIALIZER, + INVALID_STRING_ID, + INVALID_STRING_ID, + INVALID_STRING_ID, + cdIncreasing, + { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, + },{ + STATIC_COLLECTION_INITIALIZER, + INVALID_STRING_ID, + INVALID_STRING_ID, + INVALID_STRING_ID, + cdIncreasing, + { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, + },{ + STATIC_COLLECTION_INITIALIZER, + INVALID_STRING_ID, + INVALID_STRING_ID, + INVALID_STRING_ID, + cdIncreasing, + { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, + },{ + STATIC_COLLECTION_INITIALIZER, + INVALID_STRING_ID, + INVALID_STRING_ID, + INVALID_STRING_ID, + cdIncreasing, + { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, + }, }; @@ -226,6 +271,38 @@ void ConDesSetSegName (unsigned Type, unsigned SegName) +const ConDesImport* ConDesGetImport (unsigned Type) +/* Get the forced import for the given ConDes type. Returns NULL if there is + * no forced import for this type. + */ +{ + const ConDesImport* Import; + + /* Check the parameters */ + PRECONDITION (Type <= CD_TYPE_MAX); + + /* Return the import */ + Import = &ConDes[Type].Import; + return (Import->Name != INVALID_STRING_ID)? Import : 0; +} + + + +void ConDesSetImport (unsigned Type, const ConDesImport* Import) +/* Set the forced import for the given ConDes type */ +{ + /* Check the parameters */ + PRECONDITION (Type <= CD_TYPE_MAX && Import != 0); + + /* Setting the import twice is bad */ + CHECK (ConDes[Type].Import.Name == INVALID_STRING_ID); + + /* Set the import and its position */ + ConDes[Type].Import = *Import; +} + + + void ConDesSetLabel (unsigned Type, unsigned Name) /* Set the label for the given ConDes type */ { diff --git a/src/ld65/condes.h b/src/ld65/condes.h index d99608176..8ff2687f3 100644 --- a/src/ld65/condes.h +++ b/src/ld65/condes.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2000-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2000-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -38,6 +38,11 @@ +/* common */ +#include "filepos.h" + + + /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ @@ -60,6 +65,14 @@ typedef enum { cdDecreasing /* Decreasing priority */ } ConDesOrder; +/* Data for a forced condes import */ +typedef struct ConDesImport ConDesImport; +struct ConDesImport { + unsigned Name; /* Name of the import */ + FilePos Pos; /* Position of import in the config file */ + unsigned AddrSize; /* Address size of the symbol */ +}; + /*****************************************************************************/ @@ -74,6 +87,14 @@ void ConDesAddExport (struct Export* E); void ConDesSetSegName (unsigned Type, unsigned SegName); /* Set the segment name where the table should go */ +const ConDesImport* ConDesGetImport (unsigned Type); +/* Get the forced import for the given ConDes type. Returns NULL if there is + * no forced import for this type. + */ + +void ConDesSetImport (unsigned Type, const ConDesImport* Import); +/* Set the forced import for the given ConDes type */ + void ConDesSetLabel (unsigned Type, unsigned Name); /* Set the label for the given ConDes type */ diff --git a/src/ld65/config.c b/src/ld65/config.c index 12d875321..4aaa7d99d 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -1042,11 +1042,12 @@ static void ParseConDes (void) /* Parse the CONDES feature */ { static const IdentTok Attributes [] = { - { "SEGMENT", CFGTOK_SEGMENT }, - { "LABEL", CFGTOK_LABEL }, { "COUNT", CFGTOK_COUNT }, - { "TYPE", CFGTOK_TYPE }, + { "IMPORT", CFGTOK_IMPORT }, + { "LABEL", CFGTOK_LABEL }, { "ORDER", CFGTOK_ORDER }, + { "SEGMENT", CFGTOK_SEGMENT }, + { "TYPE", CFGTOK_TYPE }, }; static const IdentTok Types [] = { @@ -1061,9 +1062,10 @@ static void ParseConDes (void) }; /* Attribute values. */ - unsigned SegName = INVALID_STRING_ID; - unsigned Label = INVALID_STRING_ID; unsigned Count = INVALID_STRING_ID; + unsigned Label = INVALID_STRING_ID; + unsigned SegName = INVALID_STRING_ID; + ConDesImport Import; /* Initialize to avoid gcc warnings: */ int Type = -1; ConDesOrder Order = cdIncreasing; @@ -1071,11 +1073,12 @@ static void ParseConDes (void) /* Bitmask to remember the attributes we got already */ enum { atNone = 0x0000, - atSegName = 0x0001, - atLabel = 0x0002, - atCount = 0x0004, - atType = 0x0008, - atOrder = 0x0010 + atCount = 0x0001, + atImport = 0x0002, + atLabel = 0x0004, + atOrder = 0x0008, + atSegName = 0x0010, + atType = 0x0020, }; unsigned AttrFlags = atNone; @@ -1094,50 +1097,34 @@ static void ParseConDes (void) /* Check which attribute was given */ switch (AttrTok) { - case CFGTOK_SEGMENT: - /* Don't allow this twice */ - FlagAttr (&AttrFlags, atSegName, "SEGMENT"); + case CFGTOK_COUNT: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atCount, "COUNT"); /* We expect an identifier */ - CfgAssureIdent (); - /* Remember the value for later */ - SegName = GetStrBufId (&CfgSVal); + CfgAssureIdent (); + /* Remember the value for later */ + Count = GetStrBufId (&CfgSVal); break; - case CFGTOK_LABEL: + case CFGTOK_IMPORT: /* Don't allow this twice */ - FlagAttr (&AttrFlags, atLabel, "LABEL"); + FlagAttr (&AttrFlags, atImport, "IMPORT"); /* We expect an identifier */ - CfgAssureIdent (); - /* Remember the value for later */ - Label = GetStrBufId (&CfgSVal); - break; + CfgAssureIdent (); + /* Remember value and position for later */ + Import.Name = GetStrBufId (&CfgSVal); + Import.Pos = CfgErrorPos; + Import.AddrSize = ADDR_SIZE_ABS; + break; - case CFGTOK_COUNT: + case CFGTOK_LABEL: /* Don't allow this twice */ - FlagAttr (&AttrFlags, atCount, "COUNT"); + FlagAttr (&AttrFlags, atLabel, "LABEL"); /* We expect an identifier */ - CfgAssureIdent (); - /* Remember the value for later */ - Count = GetStrBufId (&CfgSVal); - break; - - case CFGTOK_TYPE: - /* Don't allow this twice */ - FlagAttr (&AttrFlags, atType, "TYPE"); - /* The type may be given as id or numerical */ - if (CfgTok == CFGTOK_INTCON) { - CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX); - Type = (int) CfgIVal; - } else { - CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); - switch (CfgTok) { - case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break; - case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break; - case CFGTOK_INTERRUPTOR: Type = CD_TYPE_INT; break; - default: FAIL ("Unexpected type token"); - } - } - break; + CfgAssureIdent (); + /* Remember the value for later */ + Label = GetStrBufId (&CfgSVal); + break; case CFGTOK_ORDER: /* Don't allow this twice */ @@ -1150,6 +1137,33 @@ static void ParseConDes (void) } break; + case CFGTOK_SEGMENT: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atSegName, "SEGMENT"); + /* We expect an identifier */ + CfgAssureIdent (); + /* Remember the value for later */ + SegName = GetStrBufId (&CfgSVal); + break; + + case CFGTOK_TYPE: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atType, "TYPE"); + /* The type may be given as id or numerical */ + if (CfgTok == CFGTOK_INTCON) { + CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX); + Type = (int) CfgIVal; + } else { + CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); + switch (CfgTok) { + case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break; + case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break; + case CFGTOK_INTERRUPTOR: Type = CD_TYPE_INT; break; + default: FAIL ("Unexpected type token"); + } + } + break; + default: FAIL ("Unexpected attribute token"); @@ -1184,6 +1198,9 @@ static void ParseConDes (void) if (AttrFlags & atCount) { ConDesSetCountSym (Type, Count); } + if (AttrFlags & atImport) { + ConDesSetImport (Type, &Import); + } if (AttrFlags & atOrder) { ConDesSetOrder (Type, Order); } diff --git a/src/ld65/exports.c b/src/ld65/exports.c index fe95721f5..a25d26af0 100644 --- a/src/ld65/exports.c +++ b/src/ld65/exports.c @@ -301,6 +301,8 @@ static Export* NewExport (unsigned Type, unsigned char AddrSize, unsigned Name, ObjData* Obj) /* Create a new export and initialize it */ { + unsigned I; + /* Allocate memory */ Export* E = xmalloc (sizeof (Export)); @@ -318,7 +320,9 @@ static Export* NewExport (unsigned Type, unsigned char AddrSize, E->DbgSymId = ~0U; E->Type = Type | SYM_EXPORT; E->AddrSize = AddrSize; - memset (E->ConDes, 0, sizeof (E->ConDes)); + for (I = 0; I < sizeof (E->ConDes) / sizeof (E->ConDes[0]); ++I) { + E->ConDes[I] = CD_PRIO_NONE; + } /* Return the new entry */ return E; @@ -351,8 +355,9 @@ void FreeExport (Export* E) Export* ReadExport (FILE* F, ObjData* O) /* Read an export from a file */ { - unsigned ConDesCount; - Export* E; + unsigned ConDesCount; + unsigned I; + Export* E; /* Read the type */ unsigned Type = ReadVar (F); @@ -367,23 +372,18 @@ Export* ReadExport (FILE* F, ObjData* O) ConDesCount = SYM_GET_CONDES_COUNT (Type); if (ConDesCount > 0) { - unsigned char ConDes[CD_TYPE_COUNT]; - unsigned I; + unsigned char ConDes[CD_TYPE_COUNT]; - /* Read the data into temp storage */ - ReadData (F, ConDes, ConDesCount); + /* Read the data into temp storage */ + ReadData (F, ConDes, ConDesCount); - /* Re-order the data. In the file, each decl is encoded into a byte - * which contains the type and the priority. In memory, we will use - * an array of types which contain the priority. This array was - * cleared by the constructor (NewExport), so we must only set the - * fields that contain values. - */ - for (I = 0; I < ConDesCount; ++I) { - unsigned ConDesType = CD_GET_TYPE (ConDes[I]); - unsigned ConDesPrio = CD_GET_PRIO (ConDes[I]); - E->ConDes[ConDesType] = ConDesPrio; - } + /* Re-order the data. In the file, each decl is encoded into a byte + * which contains the type and the priority. In memory, we will use + * an array of types which contain the priority. + */ + for (I = 0; I < ConDesCount; ++I) { + E->ConDes[CD_GET_TYPE (ConDes[I])] = CD_GET_PRIO (ConDes[I]); + } } /* Read the name */ @@ -393,7 +393,7 @@ Export* ReadExport (FILE* F, ObjData* O) if (SYM_IS_EXPR (Type)) { E->Expr = ReadExpr (F, O); } else { - E->Expr = LiteralExpr (Read32 (F), O); + E->Expr = LiteralExpr (Read32 (F), O); } /* Read the size */ @@ -405,6 +405,28 @@ Export* ReadExport (FILE* F, ObjData* O) ReadLineInfoList (F, O, &E->DefLines); ReadLineInfoList (F, O, &E->RefLines); + /* If this symbol is exported as a condes, and the condes type declares a + * forced import, add this import to the object module. + */ + for (I = 0; I < CD_TYPE_COUNT; ++I) { + const ConDesImport* CDI; + if (E->ConDes[I] != CD_PRIO_NONE && (CDI = ConDesGetImport (I)) != 0) { + + unsigned J; + + /* Generate a new import and insert it */ + Import* Imp = InsertImport (GenImport (CDI->Name, CDI->AddrSize)); + + /* Add line info for the config file and for the export that is + * actually the condes that forces the import. + */ + CollAppend (&Imp->RefLines, GenLineInfo (&CDI->Pos)); + for (J = 0; J < CollCount (&E->DefLines); ++J) { + CollAppend (&Imp->RefLines, DupLineInfo (CollAt (&E->DefLines, J))); + } + } + } + /* Return the new export */ return E; } diff --git a/src/ld65/lineinfo.c b/src/ld65/lineinfo.c index c7af64996..3e7817803 100644 --- a/src/ld65/lineinfo.c +++ b/src/ld65/lineinfo.c @@ -49,7 +49,7 @@ /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ @@ -87,6 +87,25 @@ void FreeLineInfo (LineInfo* LI) +LineInfo* DupLineInfo (const LineInfo* LI) +/* Creates a duplicate of a line info structure */ +{ + /* Allocate memory */ + LineInfo* New = xmalloc (sizeof (LineInfo)); + + /* Copy the fields (leave id invalid) */ + New->Id = LI->Id; + New->File = LI->File; + New->Type = LI->Type; + New->Pos = LI->Pos; + New->Spans = DupSpanList (LI->Spans); + + /* Return the copy */ + return New; +} + + + LineInfo* GenLineInfo (const FilePos* Pos) /* Generate a new (internally used) line info with the given information */ { diff --git a/src/ld65/lineinfo.h b/src/ld65/lineinfo.h index db4f84f4a..d9f2cf691 100644 --- a/src/ld65/lineinfo.h +++ b/src/ld65/lineinfo.h @@ -97,6 +97,9 @@ LineInfo* ReadLineInfo (FILE* F, struct ObjData* O); void FreeLineInfo (LineInfo* LI); /* Free a LineInfo structure. */ +LineInfo* DupLineInfo (const LineInfo* LI); +/* Creates a duplicate of a line info structure */ + void ReadLineInfoList (FILE* F, struct ObjData* O, Collection* LineInfos); /* Read a list of line infos stored as a list of indices in the object file, * make real line infos from them and place them into the passed collection. diff --git a/src/ld65/span.c b/src/ld65/span.c index 0ff1e7e1a..19bf8abe1 100644 --- a/src/ld65/span.c +++ b/src/ld65/span.c @@ -139,6 +139,23 @@ unsigned* ReadSpanList (FILE* F) +unsigned* DupSpanList (const unsigned* S) +/* Duplicate a span list */ +{ + unsigned Size; + + /* The list may be empty */ + if (S == 0) { + return 0; + } + + /* Allocate memory, copy and return the new list */ + Size = (*S + 1) * sizeof (*S); + return memcpy (xmalloc (Size), S, Size); +} + + + void FreeSpan (Span* S) /* Free a span structure */ { diff --git a/src/ld65/span.h b/src/ld65/span.h index 0125beda2..d8382a028 100644 --- a/src/ld65/span.h +++ b/src/ld65/span.h @@ -82,6 +82,9 @@ unsigned* ReadSpanList (FILE* F); * the span ids. If the number of spans is zero, NULL is returned. */ +unsigned* DupSpanList (const unsigned* S); +/* Duplicate a span list */ + void FreeSpan (Span* S); /* Free a span structure */ -- 2.39.5