mirror of
https://github.com/cc65/cc65.git
synced 2025-01-11 11:30:13 +00:00
First finished implementation of the condes feature
git-svn-id: svn://svn.cc65.org/cc65/trunk@456 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
7646787a6e
commit
518220f9cf
@ -36,10 +36,10 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/* common */
|
||||
#include "xmalloc.h"
|
||||
|
||||
|
||||
/* ld65 */
|
||||
#include "global.h"
|
||||
#include "error.h"
|
||||
@ -140,7 +140,7 @@ static void BinWriteMem (BinDesc* D, Memory* M)
|
||||
* in the linker.
|
||||
*/
|
||||
Warning ("Segment `%s' in module `%s' requires larger alignment",
|
||||
S->Name, S->Seg->AlignObj->Name);
|
||||
S->Name, GetObjFileName (S->Seg->AlignObj));
|
||||
}
|
||||
|
||||
/* Handle ALIGN and OFFSET/START */
|
||||
|
@ -33,20 +33,24 @@
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "check.h"
|
||||
#include "coll.h"
|
||||
#include "segdefs.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* ld65 */
|
||||
#include "exports.h"
|
||||
#include "fragment.h"
|
||||
#include "segments.h"
|
||||
#include "condes.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -55,24 +59,134 @@
|
||||
typedef struct ConDesDesc ConDesDesc;
|
||||
struct ConDesDesc {
|
||||
Collection ExpList; /* List of exported symbols */
|
||||
char* Label; /* Name of table label */
|
||||
char* SegName; /* Name of segment the table is in */
|
||||
unsigned char Enable; /* Table enabled */
|
||||
char* Label; /* Name of table label */
|
||||
char* CountSym; /* Name of symbol for entry count */
|
||||
unsigned char Order; /* Table order (increasing/decreasing) */
|
||||
};
|
||||
|
||||
/* Array for all types */
|
||||
static ConDesDesc ConDes[CD_TYPE_COUNT] = {
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Internally used function to create the condes tables */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int ConDesCompare (void* Data, const void* E1, const void* E2)
|
||||
/* Compare function to sort the exports */
|
||||
{
|
||||
int Cmp;
|
||||
|
||||
/* Data is actually a pointer to a ConDesDesc from the table, E1 and
|
||||
* E2 are exports from the collection. Get the condes type and cast
|
||||
* the void pointers to object pointers.
|
||||
*/
|
||||
ConDesDesc* CD = ((ConDesDesc*) Data);
|
||||
int Type = CD - ConDes;
|
||||
const Export* Exp1 = (const Export*) E1;
|
||||
const Export* Exp2 = (const Export*) E2;
|
||||
|
||||
/* Get the priorities of the two exports */
|
||||
unsigned Prio1 = Exp1->ConDes[Type];
|
||||
unsigned Prio2 = Exp2->ConDes[Type];
|
||||
|
||||
/* Compare the priorities for this condes type */
|
||||
if (Prio1 < Prio2) {
|
||||
Cmp = -1;
|
||||
} else if (Prio1 > Prio2) {
|
||||
Cmp = 1;
|
||||
} else {
|
||||
/* Use the name in this case */
|
||||
Cmp = strcmp (Exp1->Name, Exp2->Name);
|
||||
}
|
||||
|
||||
/* Reverse the result for decreasing order */
|
||||
if (CD->Order == cdIncreasing) {
|
||||
return Cmp;
|
||||
} else {
|
||||
return -Cmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ConDesCreateOne (ConDesDesc* CD)
|
||||
/* Create one table if requested */
|
||||
{
|
||||
Segment* Seg; /* Segment for table */
|
||||
Section* Sec; /* Section for table */
|
||||
unsigned Count; /* Number of exports */
|
||||
unsigned I;
|
||||
|
||||
/* Check if this table has a segment and table label defined. If not,
|
||||
* creation was not requested in the config file - ignore it.
|
||||
*/
|
||||
if (CD->SegName == 0 || CD->Label == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if there is an import for the table label. If not, there is no
|
||||
* reference to the table and we would just waste memory creating the
|
||||
* table.
|
||||
*/
|
||||
if (!IsUnresolved (CD->Label)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sort the collection of exports according to priority */
|
||||
CollSort (&CD->ExpList, ConDesCompare, CD);
|
||||
|
||||
/* Get the segment for the table, create it if needed */
|
||||
Seg = GetSegment (CD->SegName, SEGTYPE_ABS, 0);
|
||||
|
||||
/* Create a new section for the table */
|
||||
Sec = NewSection (Seg, 1, SEGTYPE_ABS);
|
||||
|
||||
/* Walk over the exports and create a fragment for each one. We will use
|
||||
* the exported expression without copying it, since it's cheap and there
|
||||
* is currently no place where it gets changed (hope this will not hunt
|
||||
* me later...).
|
||||
*/
|
||||
Count = CollCount (&CD->ExpList);
|
||||
for (I = 0; I < Count; ++I) {
|
||||
|
||||
/* Get the export */
|
||||
Export* E = CollAt (&CD->ExpList, I);
|
||||
|
||||
/* Create the fragment */
|
||||
Fragment* F = NewFragment (FRAG_EXPR, 2, Sec);
|
||||
|
||||
/* Set the expression pointer */
|
||||
F->Expr = E->Expr;
|
||||
}
|
||||
|
||||
/* Define the table start as an export, offset into section is zero
|
||||
* (the section only contains the table).
|
||||
*/
|
||||
CreateSegExport (CD->Label, Sec, 0);
|
||||
|
||||
/* If we have a CountSym name given AND if it is referenced, define it
|
||||
* with the number of elements in the table.
|
||||
*/
|
||||
if (CD->CountSym) {
|
||||
CreateConstExport (CD->CountSym, Count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
@ -86,8 +200,8 @@ void ConDesAddExport (struct Export* E)
|
||||
|
||||
/* Insert the export into all tables for which declarations exist */
|
||||
for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
|
||||
unsigned Prio = E->ConDes[Type];
|
||||
if (Prio != CD_PRIO_NONE) {
|
||||
unsigned Prio = E->ConDes[Type];
|
||||
if (Prio != CD_PRIO_NONE) {
|
||||
CollAppend (&ConDes[Type].ExpList, E);
|
||||
}
|
||||
}
|
||||
@ -125,26 +239,29 @@ void ConDesSetLabel (unsigned Type, const char* Name)
|
||||
|
||||
|
||||
|
||||
const char* ConDesGetSegName (unsigned Type)
|
||||
/* Return the segment name for the given ConDes type */
|
||||
void ConDesSetCountSym (unsigned Type, const char* Name)
|
||||
/* Set the name for the given ConDes count symbol */
|
||||
{
|
||||
/* Check the parameters */
|
||||
PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
|
||||
PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX && Name != 0);
|
||||
|
||||
/* Return the name */
|
||||
return ConDes[Type].SegName;
|
||||
/* Setting the symbol twice is bad */
|
||||
CHECK (ConDes[Type].CountSym == 0);
|
||||
|
||||
/* Set the name */
|
||||
ConDes[Type].CountSym = xstrdup (Name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char* ConDesGetLabel (unsigned Type)
|
||||
/* Return the label for the given ConDes type */
|
||||
void ConDesSetOrder (unsigned Type, ConDesOrder Order)
|
||||
/* Set the sorting oder for the given ConDes table */
|
||||
{
|
||||
/* Check the parameters */
|
||||
PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
|
||||
|
||||
/* Return the name */
|
||||
return ConDes[Type].Label;
|
||||
/* Set the order */
|
||||
ConDes[Type].Order = Order;
|
||||
}
|
||||
|
||||
|
||||
@ -152,7 +269,10 @@ const char* ConDesGetLabel (unsigned Type)
|
||||
int ConDesHasSegName (unsigned Type)
|
||||
/* Return true if a segment name is already defined for this ConDes type */
|
||||
{
|
||||
return (ConDesGetSegName(Type) != 0);
|
||||
/* Check the parameters */
|
||||
PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
|
||||
|
||||
return (ConDes[Type].SegName != 0);
|
||||
}
|
||||
|
||||
|
||||
@ -160,7 +280,10 @@ int ConDesHasSegName (unsigned Type)
|
||||
int ConDesHasLabel (unsigned Type)
|
||||
/* Return true if a label is already defined for this ConDes type */
|
||||
{
|
||||
return (ConDesGetLabel(Type) != 0);
|
||||
/* Check the parameters */
|
||||
PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
|
||||
|
||||
return (ConDes[Type].Label != 0);
|
||||
}
|
||||
|
||||
|
||||
@ -168,6 +291,12 @@ int ConDesHasLabel (unsigned Type)
|
||||
void ConDesCreate (void)
|
||||
/* Create the condes tables if requested */
|
||||
{
|
||||
unsigned Type;
|
||||
|
||||
/* Walk over the descriptor array and create a table for each entry */
|
||||
for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
|
||||
ConDesCreateOne (ConDes + Type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -48,6 +48,20 @@ struct Export;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Order of the tables */
|
||||
typedef enum {
|
||||
cdIncreasing, /* Increasing priority - default */
|
||||
cdDecreasing /* Decreasing priority */
|
||||
} ConDesOrder;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
@ -63,11 +77,11 @@ void ConDesSetSegName (unsigned Type, const char* SegName);
|
||||
void ConDesSetLabel (unsigned Type, const char* Name);
|
||||
/* Set the label for the given ConDes type */
|
||||
|
||||
const char* ConDesGetSegName (unsigned Type);
|
||||
/* Return the segment name for the given ConDes type */
|
||||
void ConDesSetCountSym (unsigned Type, const char* Name);
|
||||
/* Set the name for the given ConDes count symbol */
|
||||
|
||||
const char* ConDesGetLabel (unsigned Type);
|
||||
/* Return the label for the given ConDes type */
|
||||
void ConDesSetOrder (unsigned Type, ConDesOrder Order);
|
||||
/* Set the sorting oder for the given ConDes table */
|
||||
|
||||
int ConDesHasSegName (unsigned Type);
|
||||
/* Return true if a segment name is already defined for this ConDes type */
|
||||
|
@ -958,7 +958,9 @@ static void ParseConDes (void)
|
||||
static const IdentTok Attributes [] = {
|
||||
{ "SEGMENT", CFGTOK_SEGMENT },
|
||||
{ "LABEL", CFGTOK_LABEL },
|
||||
{ "COUNT", CFGTOK_COUNT },
|
||||
{ "TYPE", CFGTOK_TYPE },
|
||||
{ "ORDER", CFGTOK_ORDER },
|
||||
};
|
||||
|
||||
static const IdentTok Types [] = {
|
||||
@ -966,17 +968,27 @@ static void ParseConDes (void)
|
||||
{ "DESTRUCTOR", CFGTOK_DESTRUCTOR },
|
||||
};
|
||||
|
||||
static const IdentTok Orders [] = {
|
||||
{ "DECREASING", CFGTOK_DECREASING },
|
||||
{ "INCREASING", CFGTOK_INCREASING },
|
||||
};
|
||||
|
||||
/* Attribute values. */
|
||||
char SegName[sizeof (CfgSVal)];
|
||||
char Label[sizeof (CfgSVal)];
|
||||
int Type = -1; /* Initialize to avoid gcc warnings */
|
||||
char Count[sizeof (CfgSVal)];
|
||||
/* Initialize to avoid gcc warnings: */
|
||||
int Type = -1;
|
||||
ConDesOrder Order = cdIncreasing;
|
||||
|
||||
/* Bitmask to remember the attributes we got already */
|
||||
enum {
|
||||
atNone = 0x0000,
|
||||
atSegName = 0x0001,
|
||||
atLabel = 0x0002,
|
||||
atType = 0x0004
|
||||
atCount = 0x0004,
|
||||
atType = 0x0008,
|
||||
atOrder = 0x0010
|
||||
};
|
||||
unsigned AttrFlags = atNone;
|
||||
|
||||
@ -1013,6 +1025,14 @@ static void ParseConDes (void)
|
||||
strcpy (Label, CfgSVal);
|
||||
break;
|
||||
|
||||
case CFGTOK_COUNT:
|
||||
/* Don't allow this twice */
|
||||
FlagAttr (&AttrFlags, atCount, "COUNT");
|
||||
/* We expect an identifier */
|
||||
CfgAssureIdent ();
|
||||
/* Remember the value for later */
|
||||
strcpy (Count, CfgSVal);
|
||||
break;
|
||||
|
||||
case CFGTOK_TYPE:
|
||||
/* Don't allow this twice */
|
||||
@ -1031,6 +1051,17 @@ static void ParseConDes (void)
|
||||
}
|
||||
break;
|
||||
|
||||
case CFGTOK_ORDER:
|
||||
/* Don't allow this twice */
|
||||
FlagAttr (&AttrFlags, atOrder, "ORDER");
|
||||
CfgSpecialToken (Orders, ENTRY_COUNT (Orders), "Order");
|
||||
switch (CfgTok) {
|
||||
case CFGTOK_DECREASING: Order = cdDecreasing; break;
|
||||
case CFGTOK_INCREASING: Order = cdIncreasing; break;
|
||||
default: FAIL ("Unexpected order token");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FAIL ("Unexpected attribute token");
|
||||
|
||||
@ -1060,6 +1091,12 @@ static void ParseConDes (void)
|
||||
/* Define the attributes */
|
||||
ConDesSetSegName (Type, SegName);
|
||||
ConDesSetLabel (Type, Label);
|
||||
if (AttrFlags & atCount) {
|
||||
ConDesSetCountSym (Type, Count);
|
||||
}
|
||||
if (AttrFlags & atOrder) {
|
||||
ConDesSetOrder (Type, Order);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -170,7 +170,8 @@ Import* ReadImport (FILE* F, ObjData* Obj)
|
||||
/* Read the import type and check it */
|
||||
unsigned char Type = Read8 (F);
|
||||
if (Type != IMP_ZP && Type != IMP_ABS) {
|
||||
Error ("Unknown import type in module `%s': %02X", Obj->Name, Type);
|
||||
Error ("Unknown import type in module `%s': %02X",
|
||||
GetObjFileName (Obj), Type);
|
||||
}
|
||||
|
||||
/* Create a new import */
|
||||
@ -349,7 +350,7 @@ Export* CreateConstExport (const char* Name, long Value)
|
||||
/* Create an export for a literal date */
|
||||
{
|
||||
/* Create a new export */
|
||||
Export* E = NewExport (EXP_ABS, Name, 0);
|
||||
Export* E = NewExport (EXP_ABS | EXP_CONST, Name, 0);
|
||||
|
||||
/* Assign the value */
|
||||
E->Expr = LiteralExpr (Value, 0);
|
||||
@ -367,7 +368,7 @@ Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs)
|
||||
/* Create an relative export for a memory area offset */
|
||||
{
|
||||
/* Create a new export */
|
||||
Export* E = NewExport (EXP_ABS, Name, 0);
|
||||
Export* E = NewExport (EXP_ABS | EXP_EXPR, Name, 0);
|
||||
|
||||
/* Assign the value */
|
||||
E->Expr = MemExpr (Mem, Offs, 0);
|
||||
@ -381,6 +382,24 @@ Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs)
|
||||
|
||||
|
||||
|
||||
Export* CreateSegExport (const char* Name, Section* Sec, unsigned long Offs)
|
||||
/* Create a relative export to a segment (section) */
|
||||
{
|
||||
/* Create a new export */
|
||||
Export* E = NewExport (EXP_ABS | EXP_EXPR, Name, 0);
|
||||
|
||||
/* Assign the value */
|
||||
E->Expr = SegExpr (Sec, Offs, 0);
|
||||
|
||||
/* Insert the export */
|
||||
InsertExport (E);
|
||||
|
||||
/* Return the new export */
|
||||
return E;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Export* FindExport (const char* Name)
|
||||
/* Check for an identifier in the list. Return 0 if not found, otherwise
|
||||
* return a pointer to the export.
|
||||
@ -453,13 +472,13 @@ static void CheckSymType (const Export* E)
|
||||
/* User defined export */
|
||||
Warning ("Type mismatch for `%s', export in "
|
||||
"%s(%lu), import in %s(%lu)",
|
||||
E->Name, E->Obj->Files [Imp->Pos.Name],
|
||||
E->Pos.Line, Imp->Obj->Files [Imp->Pos.Name],
|
||||
E->Name, GetSourceFileName (E->Obj, Imp->Pos.Name),
|
||||
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)",
|
||||
E->Name, Imp->Obj->Files [Imp->Pos.Name],
|
||||
E->Name, GetSourceFileName (Imp->Obj, Imp->Pos.Name),
|
||||
Imp->Pos.Line);
|
||||
}
|
||||
}
|
||||
@ -503,7 +522,7 @@ static void PrintUnresolved (ExpCheckFunc F, void* Data)
|
||||
"Unresolved external `%s' referenced in:\n",
|
||||
E->Name);
|
||||
while (Imp) {
|
||||
const char* Name = Imp->Obj->Files [Imp->Pos.Name];
|
||||
const char* Name = GetSourceFileName (Imp->Obj, Imp->Pos.Name);
|
||||
fprintf (stderr, " %s(%lu)\n", Name, Imp->Pos.Line);
|
||||
Imp = Imp->Next;
|
||||
}
|
||||
@ -580,7 +599,7 @@ void PrintExportMap (FILE* F)
|
||||
const Export* E = ExpPool [I];
|
||||
|
||||
/* Print unreferenced symbols only if explictly requested */
|
||||
if (VerboseMap || E->ImpCount > 0) {
|
||||
if (VerboseMap || E->ImpCount > 0 || IS_EXP_CONDES (E->Type)) {
|
||||
fprintf (F,
|
||||
"%-25s %06lX %c%c%c ",
|
||||
E->Name,
|
||||
@ -616,17 +635,11 @@ void PrintImportMap (FILE* F)
|
||||
*/
|
||||
if (VerboseMap || Exp->ImpCount > 0) {
|
||||
|
||||
/* Get the name of the object file that exports the symbol.
|
||||
* Beware: There may be no object file if the symbol is a linker
|
||||
* generated symbol.
|
||||
*/
|
||||
const char* ObjName = (Exp->Obj != 0)? Exp->Obj->Name : "linker generated";
|
||||
|
||||
/* Print the export */
|
||||
fprintf (F,
|
||||
"%s (%s):\n",
|
||||
Exp->Name,
|
||||
ObjName);
|
||||
GetObjFileName (Exp->Obj));
|
||||
|
||||
/* Print all imports for this symbol */
|
||||
Imp = Exp->ImpList;
|
||||
@ -635,8 +648,8 @@ void PrintImportMap (FILE* F)
|
||||
/* Print the import */
|
||||
fprintf (F,
|
||||
" %-25s %s(%lu)\n",
|
||||
Imp->Obj->Name,
|
||||
Imp->Obj->Files [Imp->Pos.Name],
|
||||
GetObjFileName (Imp->Obj),
|
||||
GetSourceFileName (Imp->Obj, Imp->Pos.Name),
|
||||
Imp->Pos.Line);
|
||||
|
||||
/* Next import */
|
||||
@ -691,7 +704,7 @@ 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)",
|
||||
E->Name, E->Obj->Files [E->Pos.Name], E->Pos.Line);
|
||||
E->Name, GetSourceFileName (E->Obj, E->Pos.Name), E->Pos.Line);
|
||||
}
|
||||
|
||||
|
||||
|
@ -82,7 +82,7 @@ struct Export {
|
||||
Import* ImpList; /* List of imports for this symbol */
|
||||
FilePos Pos; /* File position of definition */
|
||||
ExprNode* Expr; /* Expression (0 if not def'd) */
|
||||
unsigned char Type; /* Type of export */
|
||||
unsigned char Type; /* Type of export */
|
||||
unsigned char ConDes[CD_TYPE_COUNT]; /* Constructor/destructor decls */
|
||||
char* Name; /* Name - dynamically allocated */
|
||||
};
|
||||
@ -123,6 +123,9 @@ Export* CreateConstExport (const char* Name, long Value);
|
||||
Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs);
|
||||
/* Create an relative export for a memory area offset */
|
||||
|
||||
Export* CreateSegExport (const char* Name, Section* S, unsigned long Offs);
|
||||
/* Create a relative export to a segment (section) */
|
||||
|
||||
int IsUnresolved (const char* Name);
|
||||
/* Check if this symbol is an unresolved export */
|
||||
|
||||
|
@ -119,7 +119,8 @@ int IsConstExpr (ExprNode* Root)
|
||||
*/
|
||||
if (ExportHasMark (E)) {
|
||||
Error ("Circular reference for symbol `%s', %s(%lu)",
|
||||
E->Name, E->Obj->Files [E->Pos.Name], E->Pos.Line);
|
||||
E->Name, GetSourceFileName (E->Obj, E->Pos.Name),
|
||||
E->Pos.Line);
|
||||
Const = 0;
|
||||
} else {
|
||||
MarkExport (E);
|
||||
@ -208,8 +209,16 @@ Section* GetExprSection (ExprNode* Expr)
|
||||
/* Check that this is really a segment node */
|
||||
PRECONDITION (Expr->Op == EXPR_SEGMENT);
|
||||
|
||||
/* Return the export */
|
||||
return Expr->Obj->Sections [Expr->V.SegNum];
|
||||
/* If we have an object file, get the section from it, otherwise
|
||||
* (internally generated expressions), get the section from the
|
||||
* section pointer.
|
||||
*/
|
||||
if (Expr->Obj) {
|
||||
/* Return the export */
|
||||
return Expr->Obj->Sections [Expr->V.SegNum];
|
||||
} else {
|
||||
return Expr->V.Sec;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -381,6 +390,25 @@ ExprNode* MemExpr (Memory* Mem, long Offs, ObjData* O)
|
||||
|
||||
|
||||
|
||||
ExprNode* SegExpr (Section* Sec, long Offs, ObjData* O)
|
||||
/* Return an expression tree that encodes an offset into a segment */
|
||||
{
|
||||
ExprNode* Root;
|
||||
|
||||
ExprNode* Expr = NewExprNode (O);
|
||||
Expr->Op = EXPR_SEGMENT;
|
||||
Expr->V.Sec = Sec;
|
||||
|
||||
Root = NewExprNode (O);
|
||||
Root->Op = EXPR_PLUS;
|
||||
Root->Left = Expr;
|
||||
Root->Right = LiteralExpr (Offs, O);
|
||||
|
||||
return Root;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ExprNode* ReadExpr (FILE* F, ObjData* O)
|
||||
/* Read an expression from the given file */
|
||||
{
|
||||
@ -461,8 +489,8 @@ int EqualExpr (ExprNode* E1, ExprNode* E2)
|
||||
return (E1->V.ImpNum == E2->V.ImpNum);
|
||||
|
||||
case EXPR_SEGMENT:
|
||||
/* Segment number must be identical */
|
||||
return (E1->V.SegNum == E2->V.SegNum);
|
||||
/* Section must be identical */
|
||||
return (GetExprSection (E1) == GetExprSection (E2));
|
||||
|
||||
case EXPR_MEMAREA:
|
||||
/* Memory area must be identical */
|
||||
|
@ -40,7 +40,7 @@
|
||||
|
||||
/* common */
|
||||
#include "exprdefs.h"
|
||||
|
||||
|
||||
/* ld65 */
|
||||
#include "objdata.h"
|
||||
#include "exports.h"
|
||||
@ -80,6 +80,9 @@ ExprNode* LiteralExpr (long Val, ObjData* O);
|
||||
ExprNode* MemExpr (Memory* Mem, long Offs, ObjData* O);
|
||||
/* Return an expression tree that encodes an offset into the memory area */
|
||||
|
||||
ExprNode* SegExpr (Section* Sec, long Offs, ObjData* O);
|
||||
/* Return an expression tree that encodes an offset into a segment */
|
||||
|
||||
void DumpExpr (const ExprNode* Expr);
|
||||
/* Dump an expression tree to stdout */
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "xmalloc.h"
|
||||
@ -59,9 +59,10 @@ Fragment* NewFragment (unsigned char Type, unsigned long Size, Section* S)
|
||||
F->Obj = 0;
|
||||
F->Size = Size;
|
||||
F->Expr = 0;
|
||||
InitFilePos (&F->Pos);
|
||||
F->Type = Type;
|
||||
|
||||
/* Insert the code fragment into the segment */
|
||||
/* Insert the code fragment into the section */
|
||||
if (S->FragRoot == 0) {
|
||||
/* First fragment */
|
||||
S->FragRoot = F;
|
||||
@ -69,8 +70,13 @@ Fragment* NewFragment (unsigned char Type, unsigned long Size, Section* S)
|
||||
S->FragLast->Next = F;
|
||||
}
|
||||
S->FragLast = F;
|
||||
|
||||
/* Increment the size of the section by the size of the fragment */
|
||||
S->Size += Size;
|
||||
|
||||
/* Increment the size of the segment that contains the section */
|
||||
S->Seg->Size += Size;
|
||||
|
||||
/* Return the new fragment */
|
||||
return F;
|
||||
}
|
||||
|
@ -80,12 +80,13 @@ static void LibReadObjHeader (ObjData* O)
|
||||
{
|
||||
O->Header.Magic = Read32 (Lib);
|
||||
if (O->Header.Magic != OBJ_MAGIC) {
|
||||
Error ("Object file `%s' in library `%s' is invalid", O->Name, LibName);
|
||||
Error ("Object file `%s' in library `%s' is invalid",
|
||||
GetObjFileName (O), LibName);
|
||||
}
|
||||
O->Header.Version = Read16 (Lib);
|
||||
if (O->Header.Version != OBJ_VERSION) {
|
||||
Error ("Object file `%s' in library `%s' has wrong version",
|
||||
O->Name, LibName);
|
||||
GetObjFileName (O), LibName);
|
||||
}
|
||||
O->Header.Flags = Read16 (Lib);
|
||||
O->Header.OptionOffs = Read32 (Lib);
|
||||
@ -281,7 +282,3 @@ void LibAdd (FILE* F, const char* Name)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -75,9 +75,9 @@ void CreateMapFile (void)
|
||||
/* We've linked this module */
|
||||
if (O->LibName) {
|
||||
/* The file is from a library */
|
||||
fprintf (F, "%s(%s):\n", O->LibName, O->Name);
|
||||
fprintf (F, "%s(%s):\n", O->LibName, GetObjFileName (O));
|
||||
} else {
|
||||
fprintf (F, "%s:\n", O->Name);
|
||||
fprintf (F, "%s:\n", GetObjFileName (O));
|
||||
}
|
||||
for (I = 0; I < O->SectionCount; ++I) {
|
||||
const Section* S = O->Sections [I];
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -35,8 +35,11 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/xmalloc.h"
|
||||
/* common */
|
||||
#include "check.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* ld65 */
|
||||
#include "error.h"
|
||||
#include "objdata.h"
|
||||
|
||||
@ -111,3 +114,38 @@ void FreeObjData (ObjData* O)
|
||||
|
||||
|
||||
|
||||
const char* GetObjFileName (const ObjData* O)
|
||||
/* Get the name of the object file. Return "(linker generated)" if the object
|
||||
* file is NULL.
|
||||
*/
|
||||
{
|
||||
return O? O->Name : "(linker generated)";
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char* GetSourceFileName (const ObjData* O, unsigned Index)
|
||||
/* Get the name of the source file with the given index. If O is NULL, return
|
||||
* "(linker generated)" as the file name.
|
||||
*/
|
||||
{
|
||||
/* Check if we have an object file */
|
||||
if (O == 0) {
|
||||
|
||||
/* No object file */
|
||||
return "(linker generated)";
|
||||
|
||||
} else {
|
||||
|
||||
/* Check the parameter */
|
||||
PRECONDITION (Index < O->FileCount);
|
||||
|
||||
/* Return the name */
|
||||
return O->Files[Index];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -97,6 +97,16 @@ ObjData* NewObjData (void);
|
||||
void FreeObjData (ObjData* O);
|
||||
/* Free a complete struct */
|
||||
|
||||
const char* GetObjFileName (const ObjData* O);
|
||||
/* Get the name of the object file. Return "(linker generated)" if the object
|
||||
* file is NULL.
|
||||
*/
|
||||
|
||||
const char* GetSourceFileName (const ObjData* O, unsigned Index);
|
||||
/* Get the name of the source file with the given index. If O is NULL, return
|
||||
* "(linker generated)" as the file name.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of objdata.h */
|
||||
|
@ -104,8 +104,14 @@ typedef enum {
|
||||
CFGTOK_CONDES,
|
||||
CFGTOK_SEGMENT,
|
||||
CFGTOK_LABEL,
|
||||
CFGTOK_COUNT,
|
||||
CFGTOK_ORDER,
|
||||
|
||||
CFGTOK_CONSTRUCTOR,
|
||||
CFGTOK_DESTRUCTOR
|
||||
CFGTOK_DESTRUCTOR,
|
||||
|
||||
CFGTOK_DECREASING,
|
||||
CFGTOK_INCREASING
|
||||
|
||||
} cfgtok_t;
|
||||
|
||||
|
@ -75,7 +75,26 @@ static Segment* SegRoot = 0; /* List of all segments */
|
||||
|
||||
|
||||
|
||||
static Segment* NewSegment (const char* Name, unsigned char Type)
|
||||
static Segment* SegFindInternal (const char* Name, unsigned HashVal)
|
||||
/* Try to find the segment with the given name, return a pointer to the
|
||||
* segment structure, or 0 if not found.
|
||||
*/
|
||||
{
|
||||
Segment* S = HashTab [HashVal];
|
||||
while (S) {
|
||||
if (strcmp (Name, S->Name) == 0) {
|
||||
/* Found */
|
||||
break;
|
||||
}
|
||||
S = S->Next;
|
||||
}
|
||||
/* Not found */
|
||||
return S;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Segment* NewSegment (const char* Name, unsigned HashVal, unsigned char Type)
|
||||
/* Create a new segment and initialize it */
|
||||
{
|
||||
/* Get the length of the symbol name */
|
||||
@ -103,13 +122,50 @@ static Segment* NewSegment (const char* Name, unsigned char Type)
|
||||
SegRoot = S;
|
||||
++SegCount;
|
||||
|
||||
/* Insert the segment into the segment hash list */
|
||||
S->Next = HashTab [HashVal];
|
||||
HashTab [HashVal] = S;
|
||||
|
||||
/* Return the new entry */
|
||||
return S;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type)
|
||||
Segment* GetSegment (const char* Name, unsigned char Type, const char* ObjName)
|
||||
/* Search for a segment and return an existing one. If the segment does not
|
||||
* exist, create a new one and return that. ObjName is only used for the error
|
||||
* message and may be NULL if the segment is linker generated.
|
||||
*/
|
||||
{
|
||||
/* Create a hash over the name and try to locate the segment in the table */
|
||||
unsigned HashVal = HashStr (Name) % HASHTAB_SIZE;
|
||||
Segment* S = SegFindInternal (Name, HashVal);
|
||||
|
||||
/* If we don't have that segment already, allocate it using the type of
|
||||
* the first section.
|
||||
*/
|
||||
if (S == 0) {
|
||||
/* Create a new segment */
|
||||
S = NewSegment (Name, HashVal, Type);
|
||||
} else {
|
||||
/* Check if the existing segment has the requested type */
|
||||
if (S->Type != Type) {
|
||||
/* Allow an empty object name */
|
||||
if (ObjName == 0) {
|
||||
ObjName = "(linker generated)";
|
||||
}
|
||||
Error ("Module `%s': Type mismatch for segment `%s'", ObjName, Name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the segment */
|
||||
return S;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type)
|
||||
/* Create a new section for the given segment */
|
||||
{
|
||||
unsigned long V;
|
||||
@ -123,7 +179,7 @@ static Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Typ
|
||||
S->Seg = Seg;
|
||||
S->FragRoot = 0;
|
||||
S->FragLast = 0;
|
||||
S->Size = 0;
|
||||
S->Size = 0;
|
||||
S->Align = Align;
|
||||
S->Type = Type;
|
||||
|
||||
@ -150,29 +206,9 @@ static Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Typ
|
||||
|
||||
|
||||
|
||||
static Segment* SegFindInternal (const char* Name, unsigned HashVal)
|
||||
/* Try to find the segment with the given name, return a pointer to the
|
||||
* segment structure, or 0 if not found.
|
||||
*/
|
||||
{
|
||||
Segment* S = HashTab [HashVal];
|
||||
while (S) {
|
||||
if (strcmp (Name, S->Name) == 0) {
|
||||
/* Found */
|
||||
break;
|
||||
}
|
||||
S = S->Next;
|
||||
}
|
||||
/* Not found */
|
||||
return S;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Section* ReadSection (FILE* F, ObjData* O)
|
||||
/* Read a section from a file */
|
||||
{
|
||||
unsigned HashVal;
|
||||
char* Name;
|
||||
unsigned long Size;
|
||||
unsigned char Align;
|
||||
@ -195,22 +231,11 @@ Section* ReadSection (FILE* F, ObjData* O)
|
||||
/* Print some data */
|
||||
if (Verbose > 1) {
|
||||
printf ("Module `%s': Found segment `%s', size = %lu, align = %u, type = %u\n",
|
||||
O->Name, Name, Size, Align, Type);
|
||||
GetObjFileName (O), Name, Size, Align, Type);
|
||||
}
|
||||
|
||||
/* Create a hash over the name and try to locate the segment in the table */
|
||||
HashVal = HashStr (Name) % HASHTAB_SIZE;
|
||||
S = SegFindInternal (Name, HashVal);
|
||||
|
||||
/* If we don't have that segment already, allocate it using the type of
|
||||
* the first section.
|
||||
*/
|
||||
if (S == 0) {
|
||||
/* Create a new segment and insert it */
|
||||
S = NewSegment (Name, Type);
|
||||
S->Next = HashTab [HashVal];
|
||||
HashTab [HashVal] = S;
|
||||
}
|
||||
/* Get the segment for this section */
|
||||
S = GetSegment (Name, Type, GetObjFileName (O));
|
||||
|
||||
/* We have the segment and don't need the name any longer */
|
||||
xfree (Name);
|
||||
@ -218,12 +243,6 @@ Section* ReadSection (FILE* F, ObjData* O)
|
||||
/* Allocate the section we will return later */
|
||||
Sec = NewSection (S, Align, Type);
|
||||
|
||||
/* Check if the section has the same type as the segment */
|
||||
if (Sec->Type != S->Type) {
|
||||
/* OOPS */
|
||||
Error ("Module `%s': Type mismatch for segment `%s'", O->Name, S->Name);
|
||||
}
|
||||
|
||||
/* Set up the minimum segment alignment */
|
||||
if (Sec->Align > S->Align) {
|
||||
/* Section needs larger alignment, use this one */
|
||||
@ -264,7 +283,7 @@ Section* ReadSection (FILE* F, ObjData* O)
|
||||
|
||||
default:
|
||||
Error ("Unknown fragment type in module `%s', segment `%s': %02X",
|
||||
O->Name, S->Name, Type);
|
||||
GetObjFileName (O), S->Name, Type);
|
||||
/* NOTREACHED */
|
||||
return 0;
|
||||
}
|
||||
@ -296,9 +315,6 @@ Section* ReadSection (FILE* F, ObjData* O)
|
||||
Size -= Frag->Size;
|
||||
}
|
||||
|
||||
/* Increment the segment size by the section size */
|
||||
S->Size += Sec->Size;
|
||||
|
||||
/* Return the section */
|
||||
return Sec;
|
||||
}
|
||||
@ -489,12 +505,14 @@ void SegWrite (FILE* Tgt, Segment* S, SegWriteFunc F, void* Data)
|
||||
|
||||
case SEG_EXPR_RANGE_ERROR:
|
||||
Error ("Range error in module `%s', line %lu",
|
||||
Frag->Obj->Files [Frag->Pos.Name], Frag->Pos.Line);
|
||||
GetSourceFileName (Frag->Obj, Frag->Pos.Name),
|
||||
Frag->Pos.Line);
|
||||
break;
|
||||
|
||||
case SEG_EXPR_TOO_COMPLEX:
|
||||
Error ("Expression too complex in module `%s', line %lu",
|
||||
Frag->Obj->Files [Frag->Pos.Name], Frag->Pos.Line);
|
||||
GetSourceFileName (Frag->Obj, Frag->Pos.Name),
|
||||
Frag->Pos.Line);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -107,6 +107,15 @@ typedef unsigned (*SegWriteFunc) (ExprNode* E, /* The expression to write
|
||||
|
||||
|
||||
|
||||
Segment* GetSegment (const char* Name, unsigned char Type, const char* ObjName);
|
||||
/* Search for a segment and return an existing one. If the segment does not
|
||||
* exist, create a new one and return that. ObjName is only used for the error
|
||||
* message and may be NULL if the segment is linker generated.
|
||||
*/
|
||||
|
||||
Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type);
|
||||
/* Create a new section for the given segment */
|
||||
|
||||
Section* ReadSection (FILE* F, struct ObjData* O);
|
||||
/* Read a section from a file */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user