1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-09 06:29:38 +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 */
/* */
/* */
/* */
/* (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 */
{

View File

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

View File

@ -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_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;
case CFGTOK_LABEL:
/* Don't allow this twice */
FlagAttr (&AttrFlags, atLabel, "LABEL");
FlagAttr (&AttrFlags, atLabel, "LABEL");
/* We expect an identifier */
CfgAssureIdent ();
/* Remember the value for later */
Label = GetStrBufId (&CfgSVal);
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;
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);
}

View File

@ -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;
}

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)
/* 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);
/* 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.

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)
/* 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.
*/
unsigned* DupSpanList (const unsigned* S);
/* Duplicate a span list */
void FreeSpan (Span* S);
/* Free a span structure */