]> git.sur5r.net Git - cc65/commitdiff
Added a new attribute IMPORT to the CONDES definition of the FEATURES section.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 3 Nov 2012 21:37:19 +0000 (21:37 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 3 Nov 2012 21:37:19 +0000 (21:37 +0000)
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
src/ld65/condes.h
src/ld65/config.c
src/ld65/exports.c
src/ld65/lineinfo.c
src/ld65/lineinfo.h
src/ld65/span.c
src/ld65/span.h

index 836c9a58a8bf9ffe8c6fad9a53b8b781c92e9523..ebf1bdecb8162fdaa6de2c81a0d5b204f190e100 100644 (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 */
 {
index d9960817644cad92cf13b3d5a8705bb32f430c25..8ff2687f34509266b86e7b954ff36b23197cbecb 100644 (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       */
 
 
 
+/* 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 */
 
index 12d8753219f656b0e701a0f23b656194f9d1e049..4aaa7d99dcc71d022e84bf18f08756615f164abe 100644 (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_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);
     }
index fe95721f5dfca40df53ddbccc95e5e8f66f0ee7a..a25d26af06f1451354c06fa5ad9a6b26713acd69 100644 (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;
 }
index c7af64996c96e34e1d89d4630776df293ad17a47..3e7817803607e9e2355db77fc81705d83aa6974b 100644 (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 */
 {
index db4f84f4a615f1f9a0fd4ce7aaf51aa61a2d4f06..d9f2cf691b53e237db37f266fdf97f43d61291f2 100644 (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.
index 0ff1e7e1a4f935655cbd767877f0b296d745b915..19bf8abe1d86d85675d45880e581266f9ee2023d 100644 (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 */
 {
index 0125beda2e917708048371cfba3c15efef2f83a6..d8382a0283249a38d7674de7aa3497b5e589e522 100644 (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 */