1
0
mirror of https://github.com/cc65/cc65.git synced 2025-01-14 16:33:00 +00:00

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
This commit is contained in:
uz 2012-11-03 21:37:19 +00:00
parent 77e6bb483f
commit 77bd3169f6
8 changed files with 265 additions and 86 deletions

View File

@ -1,15 +1,15 @@
/*****************************************************************************/ /*****************************************************************************/
/* */ /* */
/* condes.h */ /* condes.c */
/* */ /* */
/* Module constructor/destructor support */ /* Module constructor/destructor support */
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2008 Ullrich von Bassewitz */ /* (C) 2000-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@ -39,6 +39,7 @@
#include "addrsize.h" #include "addrsize.h"
#include "check.h" #include "check.h"
#include "coll.h" #include "coll.h"
#include "filepos.h"
#include "fragdefs.h" #include "fragdefs.h"
#include "xmalloc.h" #include "xmalloc.h"
@ -62,20 +63,64 @@ typedef struct ConDesDesc ConDesDesc;
struct ConDesDesc { struct ConDesDesc {
Collection ExpList; /* List of exported symbols */ Collection ExpList; /* List of exported symbols */
unsigned SegName; /* Name of segment the table is in */ 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 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 */ /* Array for all types */
static ConDesDesc ConDes[CD_TYPE_COUNT] = { 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,
{ STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing }, INVALID_STRING_ID,
{ STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing }, INVALID_STRING_ID,
{ STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing }, INVALID_STRING_ID,
{ STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing }, 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) void ConDesSetLabel (unsigned Type, unsigned Name)
/* Set the label for the given ConDes type */ /* Set the label for the given ConDes type */
{ {

View File

@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2003 Ullrich von Bassewitz */ /* (C) 2000-2012, Ullrich von Bassewitz */
/* Römerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@ -38,6 +38,11 @@
/* common */
#include "filepos.h"
/*****************************************************************************/ /*****************************************************************************/
/* Forwards */ /* Forwards */
/*****************************************************************************/ /*****************************************************************************/
@ -60,6 +65,14 @@ typedef enum {
cdDecreasing /* Decreasing priority */ cdDecreasing /* Decreasing priority */
} ConDesOrder; } 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); void ConDesSetSegName (unsigned Type, unsigned SegName);
/* Set the segment name where the table should go */ /* 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); void ConDesSetLabel (unsigned Type, unsigned Name);
/* Set the label for the given ConDes type */ /* Set the label for the given ConDes type */

View File

@ -1042,11 +1042,12 @@ static void ParseConDes (void)
/* Parse the CONDES feature */ /* Parse the CONDES feature */
{ {
static const IdentTok Attributes [] = { static const IdentTok Attributes [] = {
{ "SEGMENT", CFGTOK_SEGMENT },
{ "LABEL", CFGTOK_LABEL },
{ "COUNT", CFGTOK_COUNT }, { "COUNT", CFGTOK_COUNT },
{ "TYPE", CFGTOK_TYPE }, { "IMPORT", CFGTOK_IMPORT },
{ "LABEL", CFGTOK_LABEL },
{ "ORDER", CFGTOK_ORDER }, { "ORDER", CFGTOK_ORDER },
{ "SEGMENT", CFGTOK_SEGMENT },
{ "TYPE", CFGTOK_TYPE },
}; };
static const IdentTok Types [] = { static const IdentTok Types [] = {
@ -1061,9 +1062,10 @@ static void ParseConDes (void)
}; };
/* Attribute values. */ /* Attribute values. */
unsigned SegName = INVALID_STRING_ID;
unsigned Label = INVALID_STRING_ID;
unsigned Count = 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: */ /* Initialize to avoid gcc warnings: */
int Type = -1; int Type = -1;
ConDesOrder Order = cdIncreasing; ConDesOrder Order = cdIncreasing;
@ -1071,11 +1073,12 @@ static void ParseConDes (void)
/* Bitmask to remember the attributes we got already */ /* Bitmask to remember the attributes we got already */
enum { enum {
atNone = 0x0000, atNone = 0x0000,
atSegName = 0x0001, atCount = 0x0001,
atLabel = 0x0002, atImport = 0x0002,
atCount = 0x0004, atLabel = 0x0004,
atType = 0x0008, atOrder = 0x0008,
atOrder = 0x0010 atSegName = 0x0010,
atType = 0x0020,
}; };
unsigned AttrFlags = atNone; unsigned AttrFlags = atNone;
@ -1094,50 +1097,34 @@ static void ParseConDes (void)
/* Check which attribute was given */ /* Check which attribute was given */
switch (AttrTok) { switch (AttrTok) {
case CFGTOK_SEGMENT: case CFGTOK_COUNT:
/* Don't allow this twice */ /* Don't allow this twice */
FlagAttr (&AttrFlags, atSegName, "SEGMENT"); FlagAttr (&AttrFlags, atCount, "COUNT");
/* We expect an identifier */ /* We expect an identifier */
CfgAssureIdent (); CfgAssureIdent ();
/* Remember the value for later */ /* Remember the value for later */
SegName = GetStrBufId (&CfgSVal); Count = GetStrBufId (&CfgSVal);
break;
case CFGTOK_IMPORT:
/* Don't allow this twice */
FlagAttr (&AttrFlags, atImport, "IMPORT");
/* We expect an identifier */
CfgAssureIdent ();
/* Remember value and position for later */
Import.Name = GetStrBufId (&CfgSVal);
Import.Pos = CfgErrorPos;
Import.AddrSize = ADDR_SIZE_ABS;
break; break;
case CFGTOK_LABEL: case CFGTOK_LABEL:
/* Don't allow this twice */ /* Don't allow this twice */
FlagAttr (&AttrFlags, atLabel, "LABEL"); FlagAttr (&AttrFlags, atLabel, "LABEL");
/* We expect an identifier */ /* We expect an identifier */
CfgAssureIdent (); CfgAssureIdent ();
/* Remember the value for later */ /* Remember the value for later */
Label = GetStrBufId (&CfgSVal); Label = GetStrBufId (&CfgSVal);
break; break;
case CFGTOK_COUNT:
/* Don't allow this twice */
FlagAttr (&AttrFlags, atCount, "COUNT");
/* 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;
case CFGTOK_ORDER: case CFGTOK_ORDER:
/* Don't allow this twice */ /* Don't allow this twice */
@ -1150,6 +1137,33 @@ static void ParseConDes (void)
} }
break; 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: default:
FAIL ("Unexpected attribute token"); FAIL ("Unexpected attribute token");
@ -1184,6 +1198,9 @@ static void ParseConDes (void)
if (AttrFlags & atCount) { if (AttrFlags & atCount) {
ConDesSetCountSym (Type, Count); ConDesSetCountSym (Type, Count);
} }
if (AttrFlags & atImport) {
ConDesSetImport (Type, &Import);
}
if (AttrFlags & atOrder) { if (AttrFlags & atOrder) {
ConDesSetOrder (Type, Order); ConDesSetOrder (Type, Order);
} }

View File

@ -301,6 +301,8 @@ static Export* NewExport (unsigned Type, unsigned char AddrSize,
unsigned Name, ObjData* Obj) unsigned Name, ObjData* Obj)
/* Create a new export and initialize it */ /* Create a new export and initialize it */
{ {
unsigned I;
/* Allocate memory */ /* Allocate memory */
Export* E = xmalloc (sizeof (Export)); Export* E = xmalloc (sizeof (Export));
@ -318,7 +320,9 @@ static Export* NewExport (unsigned Type, unsigned char AddrSize,
E->DbgSymId = ~0U; E->DbgSymId = ~0U;
E->Type = Type | SYM_EXPORT; E->Type = Type | SYM_EXPORT;
E->AddrSize = AddrSize; 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 the new entry */
return E; return E;
@ -351,8 +355,9 @@ void FreeExport (Export* E)
Export* ReadExport (FILE* F, ObjData* O) Export* ReadExport (FILE* F, ObjData* O)
/* Read an export from a file */ /* Read an export from a file */
{ {
unsigned ConDesCount; unsigned ConDesCount;
Export* E; unsigned I;
Export* E;
/* Read the type */ /* Read the type */
unsigned Type = ReadVar (F); unsigned Type = ReadVar (F);
@ -367,23 +372,18 @@ Export* ReadExport (FILE* F, ObjData* O)
ConDesCount = SYM_GET_CONDES_COUNT (Type); ConDesCount = SYM_GET_CONDES_COUNT (Type);
if (ConDesCount > 0) { if (ConDesCount > 0) {
unsigned char ConDes[CD_TYPE_COUNT]; unsigned char ConDes[CD_TYPE_COUNT];
unsigned I;
/* Read the data into temp storage */ /* Read the data into temp storage */
ReadData (F, ConDes, ConDesCount); ReadData (F, ConDes, ConDesCount);
/* Re-order the data. In the file, each decl is encoded into a byte /* 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 * which contains the type and the priority. In memory, we will use
* an array of types which contain the priority. This array was * an array of types which contain the priority.
* cleared by the constructor (NewExport), so we must only set the */
* fields that contain values. for (I = 0; I < ConDesCount; ++I) {
*/ E->ConDes[CD_GET_TYPE (ConDes[I])] = CD_GET_PRIO (ConDes[I]);
for (I = 0; I < ConDesCount; ++I) { }
unsigned ConDesType = CD_GET_TYPE (ConDes[I]);
unsigned ConDesPrio = CD_GET_PRIO (ConDes[I]);
E->ConDes[ConDesType] = ConDesPrio;
}
} }
/* Read the name */ /* Read the name */
@ -393,7 +393,7 @@ Export* ReadExport (FILE* F, ObjData* O)
if (SYM_IS_EXPR (Type)) { if (SYM_IS_EXPR (Type)) {
E->Expr = ReadExpr (F, O); E->Expr = ReadExpr (F, O);
} else { } else {
E->Expr = LiteralExpr (Read32 (F), O); E->Expr = LiteralExpr (Read32 (F), O);
} }
/* Read the size */ /* Read the size */
@ -405,6 +405,28 @@ Export* ReadExport (FILE* F, ObjData* O)
ReadLineInfoList (F, O, &E->DefLines); ReadLineInfoList (F, O, &E->DefLines);
ReadLineInfoList (F, O, &E->RefLines); 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 the new export */
return E; return E;
} }

View File

@ -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) LineInfo* GenLineInfo (const FilePos* Pos)
/* Generate a new (internally used) line info with the given information */ /* Generate a new (internally used) line info with the given information */
{ {

View File

@ -97,6 +97,9 @@ LineInfo* ReadLineInfo (FILE* F, struct ObjData* O);
void FreeLineInfo (LineInfo* LI); void FreeLineInfo (LineInfo* LI);
/* Free a LineInfo structure. */ /* 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); 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, /* 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. * make real line infos from them and place them into the passed collection.

View File

@ -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) void FreeSpan (Span* S)
/* Free a span structure */ /* Free a span structure */
{ {

View File

@ -82,6 +82,9 @@ unsigned* ReadSpanList (FILE* F);
* the span ids. If the number of spans is zero, NULL is returned. * 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); void FreeSpan (Span* S);
/* Free a span structure */ /* Free a span structure */