From bb24d025f6a68c0d1475f82c473ff5102a351db3 Mon Sep 17 00:00:00 2001 From: cuz Date: Fri, 6 Jun 2003 12:45:19 +0000 Subject: [PATCH] Added assertions git-svn-id: svn://svn.cc65.org/cc65/trunk@2202 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ar65/objfile.c | 12 +++- src/ca65/error.c | 1 + src/ca65/error.h | 1 + src/ca65/main.c | 4 ++ src/ca65/make/gcc.mak | 1 + src/ca65/make/watcom.mak | 1 + src/ca65/objfile.c | 22 ++++++- src/ca65/objfile.h | 6 ++ src/ca65/pseudo.c | 60 ++++++++++++++++++-- src/ca65/scanner.c | 1 + src/ca65/scanner.h | 3 +- src/common/objdefs.h | 4 +- src/ld65/config.c | 77 ++++++++++++++----------- src/ld65/config.h | 1 + src/ld65/expr.c | 93 +++++++++++++++++------------- src/ld65/fileinfo.c | 4 +- src/ld65/fileio.c | 23 ++++++++ src/ld65/fileio.h | 6 ++ src/ld65/library.c | 44 +++++--------- src/ld65/main.c | 4 ++ src/ld65/make/gcc.mak | 3 +- src/ld65/make/watcom.mak | 3 +- src/ld65/objdata.c | 20 +++++++ src/ld65/objdata.h | 11 +++- src/ld65/objfile.c | 120 +++++++++++++++++++++++++++------------ src/ld65/objfile.h | 31 +++++----- src/ld65/segments.c | 23 ++++---- src/ld65/segments.h | 5 +- src/od65/fileio.c | 2 + 29 files changed, 404 insertions(+), 182 deletions(-) diff --git a/src/ar65/objfile.c b/src/ar65/objfile.c index a7675e7d0..e165fc167 100644 --- a/src/ar65/objfile.c +++ b/src/ar65/objfile.c @@ -111,6 +111,8 @@ void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name) H->LineInfoSize = Read32 (Obj); H->StrPoolOffs = Read32 (Obj); H->StrPoolSize = Read32 (Obj); + H->AssertOffs = Read32 (Obj); + H->AssertSize = Read32 (Obj); } @@ -137,6 +139,8 @@ void ObjWriteHeader (FILE* Obj, ObjHeader* H) Write32 (Obj, H->LineInfoSize); Write32 (Obj, H->StrPoolOffs); Write32 (Obj, H->StrPoolSize); + Write32 (Obj, H->AssertOffs); + Write32 (Obj, H->AssertSize); } @@ -201,7 +205,7 @@ void ObjAdd (const char* Name) O->StringCount = ReadVar (Obj); O->Strings = xmalloc (O->StringCount * sizeof (char*)); for (I = 0; I < O->StringCount; ++I) { - O->Strings[I] = ReadStr (Obj); + O->Strings[I] = ReadStr (Obj); } /* Skip the object file header */ @@ -219,6 +223,8 @@ void ObjAdd (const char* Name) H.FileOffs = LibCopyTo (Obj, H.FileSize) - O->Start; fseek (Obj, H.LineInfoOffs, SEEK_SET); H.LineInfoOffs = LibCopyTo (Obj, H.LineInfoSize) - O->Start; + fseek (Obj, H.AssertOffs, SEEK_SET); + H.AssertOffs = LibCopyTo (Obj, H.AssertSize) - O->Start; /* Calculate the amount of data written */ O->Size = ftell (NewLib) - O->Start; @@ -270,7 +276,7 @@ void ObjExtract (const char* Name) Error ("Cannot open target file `%s': %s", Name, strerror (errno)); } - /* Copy the first four segments including the header to the new file */ + /* Copy anything to the new file that has no special handling */ LibCopyFrom (O->Start, O->Size, Obj); /* Write imports and exports */ @@ -284,7 +290,7 @@ void ObjExtract (const char* Name) WriteVar (Obj, O->StringCount); for (I = 0; I < O->StringCount; ++I) { WriteStr (Obj, O->Strings[I]); - } + } StrPoolSize = ftell (Obj) - StrPoolStart; /* Seek back and read the header */ diff --git a/src/ca65/error.c b/src/ca65/error.c index 162080d7b..ce5212638 100644 --- a/src/ca65/error.c +++ b/src/ca65/error.c @@ -162,6 +162,7 @@ void ErrorMsg (const FilePos* Pos, unsigned ErrNum, va_list ap) "Illegal macro package name", "Illegal emulation feature", "Illegal scope specifier", + "Illegal assert action", "Syntax error", "Symbol `%s' is already defined", "Undefined symbol `%s'", diff --git a/src/ca65/error.h b/src/ca65/error.h index ca7ef370e..1d6611318 100644 --- a/src/ca65/error.h +++ b/src/ca65/error.h @@ -103,6 +103,7 @@ enum Errors { ERR_ILLEGAL_MACPACK, ERR_ILLEGAL_FEATURE, ERR_ILLEGAL_SCOPE, + ERR_ILLEGAL_ASSERT_ACTION, ERR_SYNTAX, ERR_SYM_ALREADY_DEFINED, ERR_SYM_UNDEFINED, diff --git a/src/ca65/main.c b/src/ca65/main.c index f3ae99809..31dfef069 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -56,6 +56,7 @@ #include "incpath.h" #include "instr.h" #include "istack.h" +#include "ldassert.h" #include "lineinfo.h" #include "listing.h" #include "macro.h" @@ -484,6 +485,9 @@ static void CreateObjFile (void) /* Write the string pool */ WriteStrPool (); + /* Write the assertions */ + WriteAssertions (); + /* Write an updated header and close the file */ ObjClose (); } diff --git a/src/ca65/make/gcc.mak b/src/ca65/make/gcc.mak index dc0502be6..12efb6503 100644 --- a/src/ca65/make/gcc.mak +++ b/src/ca65/make/gcc.mak @@ -22,6 +22,7 @@ OBJS = condasm.o \ incpath.o \ instr.o \ istack.o \ + ldassert.o \ lineinfo.o \ listing.o \ macpack.o \ diff --git a/src/ca65/make/watcom.mak b/src/ca65/make/watcom.mak index 3e9bec5b0..ac2ca050e 100644 --- a/src/ca65/make/watcom.mak +++ b/src/ca65/make/watcom.mak @@ -55,6 +55,7 @@ OBJS = condasm.obj \ incpath.obj \ instr.obj \ istack.obj \ + ldassert.obj \ lineinfo.obj \ listing.obj \ macpack.obj \ diff --git a/src/ca65/objfile.c b/src/ca65/objfile.c index 840dd6d54..50bcafcf4 100644 --- a/src/ca65/objfile.c +++ b/src/ca65/objfile.c @@ -81,7 +81,9 @@ static ObjHeader Header = { 0, /* 32: Offset to list of line infos */ 0, /* 32: Size of line infos */ 0, /* 32: Offset to string pool */ - 0 /* 32: Size of string pool */ + 0, /* 32: Size of string pool */ + 0, /* 32: Offset to assertion table */ + 0 /* 32: Size of assertion table */ }; @@ -134,6 +136,8 @@ static void ObjWriteHeader (void) ObjWrite32 (Header.LineInfoSize); ObjWrite32 (Header.StrPoolOffs); ObjWrite32 (Header.StrPoolSize); + ObjWrite32 (Header.AssertOffs); + ObjWrite32 (Header.AssertSize); } @@ -442,3 +446,19 @@ void ObjEndStrPool (void) +void ObjStartAssertions (void) +/* Mark the start of the assertion table */ +{ + Header.AssertOffs = ftell (F); +} + + + +void ObjEndAssertions (void) +/* Mark the end of the assertion table */ +{ + Header.AssertSize = ftell (F) - Header.AssertOffs; +} + + + diff --git a/src/ca65/objfile.h b/src/ca65/objfile.h index b6d8d6e34..c0edde240 100644 --- a/src/ca65/objfile.h +++ b/src/ca65/objfile.h @@ -133,6 +133,12 @@ void ObjStartStrPool (void); void ObjEndStrPool (void); /* Mark the end of the string pool section */ +void ObjStartAssertions (void); +/* Mark the start of the assertion table */ + +void ObjEndAssertions (void); +/* Mark the end of the assertion table */ + /* End of objfile.h */ diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index d3918ec62..407cf5e7f 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -56,15 +56,17 @@ #include "global.h" #include "incpath.h" #include "instr.h" +#include "ldassert.h" #include "listing.h" #include "macpack.h" #include "macro.h" #include "nexttok.h" #include "objcode.h" #include "options.h" +#include "pseudo.h" #include "repeat.h" +#include "spool.h" #include "symtab.h" -#include "pseudo.h" @@ -326,6 +328,55 @@ static void DoASCIIZ (void) +static void DoAssert (void) +/* Add an assertion */ +{ + static const char* ActionTab [] = { + "WARN", "WARNING", + "ERROR" + }; + + int Action; + + + /* First we have the expression that has to evaluated */ + ExprNode* Expr = Expression (); + ConsumeComma (); + + /* Action follows */ + if (Tok != TOK_IDENT) { + ErrorSkip (ERR_IDENT_EXPECTED); + return; + } + Action = GetSubKey (ActionTab, sizeof (ActionTab) / sizeof (ActionTab[0])); + switch (Action) { + + case 0: + case 1: + /* Warning */ + break; + + case 2: + /* Error */ + break; + + default: + Error (ERR_ILLEGAL_SEG_ATTR); + } + NextTok (); + ConsumeComma (); + + /* Read the message */ + if (Tok != TOK_STRCON) { + ErrorSkip (ERR_STRCON_EXPECTED); + } else { + AddAssertion (Expr, Action, GetStringId (SVal)); + NextTok (); + } +} + + + static void DoAutoImport (void) /* Mark unresolved symbols as imported */ { @@ -1078,7 +1129,7 @@ static void DoMacPack (void) /* Insert the package */ InsertMacPack (Package); -} +} @@ -1403,11 +1454,11 @@ enum { }; /* Control command table */ -struct CtrlDesc_ { +typedef struct CtrlDesc CtrlDesc; +struct CtrlDesc { unsigned Flags; /* Flags for this directive */ void (*Handler) (void); /* Command handler */ }; -typedef struct CtrlDesc_ CtrlDesc; #define PSEUDO_COUNT (sizeof (CtrlCmdTab) / sizeof (CtrlCmdTab [0])) static CtrlDesc CtrlCmdTab [] = { @@ -1416,6 +1467,7 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoAddr }, /* .ADDR */ { ccNone, DoAlign }, { ccNone, DoASCIIZ }, + { ccNone, DoAssert }, { ccNone, DoAutoImport }, { ccNone, DoUnexpected }, /* .BLANK */ { ccNone, DoBss }, diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 1e485fc5c..39f04174d 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -123,6 +123,7 @@ struct DotKeyword { { ".ALIGN", TOK_ALIGN }, { ".AND", TOK_BAND }, { ".ASCIIZ", TOK_ASCIIZ }, + { ".ASSERT", TOK_ASSERT }, { ".AUTOIMPORT", TOK_AUTOIMPORT }, { ".BITAND", TOK_AND }, { ".BITNOT", TOK_NOT }, diff --git a/src/ca65/scanner.h b/src/ca65/scanner.h index 442affa76..46549b91e 100644 --- a/src/ca65/scanner.h +++ b/src/ca65/scanner.h @@ -115,6 +115,7 @@ enum Token { TOK_ADDR, TOK_ALIGN, TOK_ASCIIZ, + TOK_ASSERT, TOK_AUTOIMPORT, TOK_BLANK, TOK_BSS, @@ -235,7 +236,7 @@ extern int ForcedEnd; /* Force end of assembly */ /*****************************************************************************/ - + void NewInputFile (const char* Name); /* Open a new input file */ diff --git a/src/common/objdefs.h b/src/common/objdefs.h index aae965362..ebf414a7c 100644 --- a/src/common/objdefs.h +++ b/src/common/objdefs.h @@ -49,7 +49,7 @@ #define OBJ_VERSION 0x000A /* Size of an object file header */ -#define OBJ_HDR_SIZE 72 +#define OBJ_HDR_SIZE (20*4) /* Flag bits */ #define OBJ_FLAGS_DBGINFO 0x0001 /* File has debug info */ @@ -78,6 +78,8 @@ struct ObjHeader { unsigned long LineInfoSize; /* 32: Size of line infos */ unsigned long StrPoolOffs; /* 32: Offset to string pool */ unsigned long StrPoolSize; /* 32: Size of string pool */ + unsigned long AssertOffs; /* 32: Offset to assertion table */ + unsigned long AssertSize; /* 32: Size of assertion table */ }; diff --git a/src/ld65/config.c b/src/ld65/config.c index 19f42f23f..8d5a8ecf7 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -287,18 +287,19 @@ static Memory* NewMemory (unsigned Name) M = xmalloc (sizeof (Memory)); /* Initialize the fields */ - M->Name = Name; - M->Next = 0; - M->FNext = 0; - M->Attr = 0; - M->Flags = 0; - M->Start = 0; - M->Size = 0; - M->FillLevel = 0; - M->FillVal = 0; - M->SegList = 0; - M->SegLast = 0; - M->F = 0; + M->Name = Name; + M->Next = 0; + M->FNext = 0; + M->Attr = 0; + M->Flags = 0; + M->Start = 0; + M->Size = 0; + M->FillLevel = 0; + M->FillVal = 0; + M->Relocatable = 0; + M->SegList = 0; + M->SegLast = 0; + M->F = 0; /* Insert the struct into the list */ if (MemoryLast == 0) { @@ -992,7 +993,7 @@ static void ParseFormats (void) /* Map the identifier to a token */ cfgtok_t FormatTok; CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format"); - FormatTok = CfgTok; + FormatTok = CfgTok; /* Skip the name and the following colon */ CfgNextTok (); @@ -1432,11 +1433,16 @@ void CfgAssignSegments (void) Memory* M = MemoryList; while (M) { + MemListNode* N; + /* Get the start address of this memory area */ unsigned long Addr = M->Start; + /* Remember if this is a relocatable memory area */ + M->Relocatable = RelocatableBinFmt (M->F->Format); + /* Walk through the segments in this memory area */ - MemListNode* N = M->SegList; + N = M->SegList; while (N) { /* Get the segment from the node */ @@ -1444,32 +1450,35 @@ void CfgAssignSegments (void) /* Handle ALIGN and OFFSET/START */ if (S->Flags & SF_ALIGN) { - /* Align the address */ - unsigned long Val = (0x01UL << S->Align) - 1; - Addr = (Addr + Val) & ~Val; + /* Align the address */ + unsigned long Val = (0x01UL << S->Align) - 1; + Addr = (Addr + Val) & ~Val; } else if (S->Flags & (SF_OFFSET | SF_START)) { - /* Give the segment a fixed starting address */ - unsigned long NewAddr = S->Addr; - if (S->Flags & SF_OFFSET) { - /* An offset was given, no address, make an address */ - NewAddr += M->Start; - } + /* Give the segment a fixed starting address */ + unsigned long NewAddr = S->Addr; + if (S->Flags & SF_OFFSET) { + /* An offset was given, no address, make an address */ + NewAddr += M->Start; + } if (Addr > NewAddr) { - /* Offset already too large */ - if (S->Flags & SF_OFFSET) { - Error ("Offset too small in `%s', segment `%s'", - GetString (M->Name), GetString (S->Name)); - } else { - Error ("Start address too low in `%s', segment `%s'", - GetString (M->Name), GetString (S->Name)); - } - } - Addr = NewAddr; + /* Offset already too large */ + if (S->Flags & SF_OFFSET) { + Error ("Offset too small in `%s', segment `%s'", + GetString (M->Name), GetString (S->Name)); + } else { + Error ("Start address too low in `%s', segment `%s'", + GetString (M->Name), GetString (S->Name)); + } + } + Addr = NewAddr; } - /* If this is the run area, set the start address of this segment */ + /* If this is the run area, set the start address of this segment + * and remember if the segment is in a relocatable file or not. + */ if (S->Run == M) { S->Seg->PC = Addr; + S->Seg->Relocatable = M->Relocatable; } /* Increment the fill level of the memory area and check for an diff --git a/src/ld65/config.h b/src/ld65/config.h index f815fc398..58036d5f3 100644 --- a/src/ld65/config.h +++ b/src/ld65/config.h @@ -78,6 +78,7 @@ struct Memory { unsigned long Size; /* Length of memory section */ unsigned long FillLevel; /* Actual fill level of segment */ unsigned char FillVal; /* Value used to fill rest of seg */ + unsigned char Relocatable; /* Memory are is relocatable */ MemListNode* SegList; /* List of segments for this section */ MemListNode* SegLast; /* Last segment in this section */ File* F; /* File that contains the entry */ diff --git a/src/ld65/expr.c b/src/ld65/expr.c index 9006826dd..425ee93f8 100644 --- a/src/ld65/expr.c +++ b/src/ld65/expr.c @@ -101,8 +101,9 @@ int IsConstExpr (ExprNode* Root) * with no references to external symbols. */ { - int Const; - Export* E; + int Const; + Export* E; + Section* S; if (EXPR_IS_LEAF (Root->Op)) { switch (Root->Op) { @@ -111,23 +112,39 @@ int IsConstExpr (ExprNode* Root) return 1; case EXPR_SYMBOL: - /* Get the referenced export */ + /* Get the referenced export */ E = GetExprExport (Root); - /* If this export has a mark set, we've already encountered it. - * This means that the export is used to define it's own value, - * which in turn means, that we have a circular reference. - */ - if (ExportHasMark (E)) { + /* If this export has a mark set, we've already encountered it. + * This means that the export is used to define it's own value, + * which in turn means, that we have a circular reference. + */ + if (ExportHasMark (E)) { CircularRefError (E); - Const = 0; - } else { - MarkExport (E); - Const = IsConstExport (E); - UnmarkExport (E); - } - return Const; + Const = 0; + } else { + MarkExport (E); + Const = IsConstExport (E); + UnmarkExport (E); + } + return Const; + + case EXPR_SECTION: + /* A section expression is const if the segment it is in is + * not relocatable. + */ + S = GetExprSection (Root); + return !S->Seg->Relocatable; + + case EXPR_SEGMENT: + /* A segment is const if it is not relocatable */ + return !Root->V.Seg->Relocatable; + + case EXPR_MEMAREA: + /* A memory area is const if it is not relocatable */ + return !Root->V.Mem->Relocatable; default: + /* Anything else is not const */ return 0; } @@ -213,7 +230,7 @@ Section* GetExprSection (ExprNode* Expr) */ if (Expr->Obj) { /* Return the export */ - return Expr->Obj->Sections [Expr->V.SegNum]; + return Expr->Obj->Sections[Expr->V.SegNum]; } else { return Expr->V.Sec; } @@ -231,47 +248,47 @@ long GetExprVal (ExprNode* Expr) switch (Expr->Op) { case EXPR_LITERAL: - return Expr->V.Val; + return Expr->V.Val; case EXPR_SYMBOL: - /* Get the referenced export */ + /* Get the referenced export */ E = GetExprExport (Expr); - /* If this export has a mark set, we've already encountered it. - * This means that the export is used to define it's own value, - * which in turn means, that we have a circular reference. - */ - if (ExportHasMark (E)) { - CircularRefError (E); - Val = 0; - } else { - MarkExport (E); - Val = GetExportVal (E); - UnmarkExport (E); - } - return Val; + /* If this export has a mark set, we've already encountered it. + * This means that the export is used to define it's own value, + * which in turn means, that we have a circular reference. + */ + if (ExportHasMark (E)) { + CircularRefError (E); + Val = 0; + } else { + MarkExport (E); + Val = GetExportVal (E); + UnmarkExport (E); + } + return Val; case EXPR_SECTION: S = GetExprSection (Expr); - return S->Offs + S->Seg->PC; + return S->Offs + S->Seg->PC; - case EXPR_SEGMENT: + case EXPR_SEGMENT: return Expr->V.Seg->PC; case EXPR_MEMAREA: return Expr->V.Mem->Start; case EXPR_PLUS: - return GetExprVal (Expr->Left) + GetExprVal (Expr->Right); + return GetExprVal (Expr->Left) + GetExprVal (Expr->Right); case EXPR_MINUS: - return GetExprVal (Expr->Left) - GetExprVal (Expr->Right); + return GetExprVal (Expr->Left) - GetExprVal (Expr->Right); case EXPR_MUL: - return GetExprVal (Expr->Left) * GetExprVal (Expr->Right); + return GetExprVal (Expr->Left) * GetExprVal (Expr->Right); case EXPR_DIV: - Left = GetExprVal (Expr->Left); - Right = GetExprVal (Expr->Right); + Left = GetExprVal (Expr->Left); + Right = GetExprVal (Expr->Right); if (Right == 0) { Error ("Division by zero"); } diff --git a/src/ld65/fileinfo.c b/src/ld65/fileinfo.c index 2aeb5284b..58b5826b1 100644 --- a/src/ld65/fileinfo.c +++ b/src/ld65/fileinfo.c @@ -60,14 +60,14 @@ static FileInfo* NewFileInfo (void) -FileInfo* ReadFileInfo (FILE* F, ObjData* O attribute ((unused))) +FileInfo* ReadFileInfo (FILE* F, ObjData* O) /* Read a file info from a file and return it */ { /* Allocate a new FileInfo structure */ FileInfo* FI = NewFileInfo (); /* Read the fields from the file */ - FI->Name = ReadVar (F); + FI->Name = MakeGlobalStringId (O, ReadVar (F)); FI->MTime = Read32 (F); FI->Size = Read32 (F); diff --git a/src/ld65/fileio.c b/src/ld65/fileio.c index 6ddc17158..b2e93bea6 100644 --- a/src/ld65/fileio.c +++ b/src/ld65/fileio.c @@ -34,6 +34,7 @@ #include +#include /* common */ #include "xmalloc.h" @@ -51,6 +52,28 @@ +void FileSetPos (FILE* F, unsigned long Pos) +/* Seek to the given absolute position, fail on errors */ +{ + if (fseek (F, Pos, SEEK_SET) != 0) { + Error ("Cannot seek: %s", strerror (errno)); + } +} + + + +unsigned long FileGetPos (FILE* F) +/* Return the current file position, fail on errors */ +{ + long Pos = ftell (F); + if (Pos < 0) { + Error ("Error in ftell: %s", strerror (errno)); + } + return Pos; +} + + + void Write8 (FILE* F, unsigned Val) /* Write an 8 bit value to the file */ { diff --git a/src/ld65/fileio.h b/src/ld65/fileio.h index b8dd2b1ec..7bcc96f30 100644 --- a/src/ld65/fileio.h +++ b/src/ld65/fileio.h @@ -51,6 +51,12 @@ +void FileSetPos (FILE* F, unsigned long Pos); +/* Seek to the given absolute position, fail on errors */ + +unsigned long FileGetPos (FILE* F); +/* Return the current file position, fail on errors */ + void Write8 (FILE* F, unsigned Val); /* Write an 8 bit value to the file */ diff --git a/src/ld65/library.c b/src/ld65/library.c index 98ff05e0b..55c3656bc 100644 --- a/src/ld65/library.c +++ b/src/ld65/library.c @@ -105,6 +105,8 @@ static void LibReadObjHeader (ObjData* O, const char* LibName) O->Header.LineInfoSize = Read32 (Lib); O->Header.StrPoolOffs = Read32 (Lib); O->Header.StrPoolSize = Read32 (Lib); + O->Header.AssertOffs = Read32 (Lib); + O->Header.AssertSize = Read32 (Lib); } @@ -112,8 +114,6 @@ static void LibReadObjHeader (ObjData* O, const char* LibName) static ObjData* ReadIndexEntry (void) /* Read one entry in the index */ { - unsigned I; - /* Create a new entry and insert it into the list */ ObjData* O = NewObjData (); @@ -127,23 +127,15 @@ static ObjData* ReadIndexEntry (void) Read32 (Lib); /* Skip Size */ /* Read the string pool */ - ObjReadStrPool (Lib, O); + ObjReadStrPool (Lib, FileGetPos (Lib), O); /* Skip the export size, then read the exports */ (void) ReadVar (Lib); - O->ExportCount = ReadVar (Lib); - O->Exports = xmalloc (O->ExportCount * sizeof (Export*)); - for (I = 0; I < O->ExportCount; ++I) { - O->Exports[I] = ReadExport (Lib, O); - } + ObjReadExports (Lib, FileGetPos (Lib), O); /* Skip the import size, then read the imports */ (void) ReadVar (Lib); - O->ImportCount = ReadVar (Lib); - O->Imports = xmalloc (O->ImportCount * sizeof (Import*)); - for (I = 0; I < O->ImportCount; ++I) { - O->Imports[I] = ReadImport (Lib, O); - } + ObjReadImports (Lib, FileGetPos (Lib), O); /* Done */ return O; @@ -158,7 +150,7 @@ static void ReadIndex (void) /* Read the object file count and allocate memory */ ModuleCount = ReadVar (Lib); - Index = xmalloc (ModuleCount * sizeof (ObjData*)); + Index = xmalloc (ModuleCount * sizeof (Index[0])); /* Read all entries in the index */ for (I = 0; I < ModuleCount; ++I) { @@ -192,14 +184,7 @@ static void LibCheckExports (ObjData* O) /* If we need this module, insert the imports and exports */ if (O->Flags & OBJ_REF) { - /* Insert the exports */ - for (I = 0; I < O->ExportCount; ++I) { - InsertExport (O->Exports[I]); - } - /* Insert the imports */ - for (I = 0; I < O->ImportCount; ++I) { - InsertImport (O->Imports[I]); - } + InsertObjGlobals (O); } } @@ -265,23 +250,22 @@ void LibAdd (FILE* F, const char* Name) LibReadObjHeader (O, Name); /* Seek to the start of the files list and read the files list */ - fseek (Lib, O->Start + O->Header.FileOffs, SEEK_SET); - ObjReadFiles (Lib, O); + ObjReadFiles (Lib, O->Start + O->Header.FileOffs, O); /* Seek to the start of the debug info and read the debug info */ - fseek (Lib, O->Start + O->Header.DbgSymOffs, SEEK_SET); - ObjReadDbgSyms (Lib, O); + ObjReadDbgSyms (Lib, O->Start + O->Header.DbgSymOffs, O); /* Seek to the start of the line infos and read them */ - fseek (Lib, O->Start + O->Header.LineInfoOffs, SEEK_SET); - ObjReadLineInfos (Lib, O); + ObjReadLineInfos (Lib, O->Start + O->Header.LineInfoOffs, O); + + /* Read the assertions from the object file */ + ObjReadAssertions (Lib, O->Start + O->Header.AssertOffs, O); /* Seek to the start of the segment list and read the segments. * This must be last, since the data here may reference other * stuff. */ - fseek (Lib, O->Start + O->Header.SegOffs, SEEK_SET); - ObjReadSections (Lib, O); + ObjReadSections (Lib, O->Start + O->Header.SegOffs, O); /* Add a pointer to the library name */ O->LibName = LibName; diff --git a/src/ld65/main.c b/src/ld65/main.c index c92d96a54..0c87cf1d3 100644 --- a/src/ld65/main.c +++ b/src/ld65/main.c @@ -49,6 +49,7 @@ #include "xmalloc.h" /* ld65 */ +#include "asserts.h" #include "binfmt.h" #include "condes.h" #include "config.h" @@ -509,6 +510,9 @@ int main (int argc, char* argv []) /* Assign start addresses for the segments, define linker symbols */ CfgAssignSegments (); + /* Check module assertions */ + CheckAssertions (); + /* Create the output file */ CfgWriteTarget (); diff --git a/src/ld65/make/gcc.mak b/src/ld65/make/gcc.mak index cb74a5112..24260bb76 100644 --- a/src/ld65/make/gcc.mak +++ b/src/ld65/make/gcc.mak @@ -18,7 +18,8 @@ CVT=cfg/cvt-cfg.pl # ----------------------------------------------------------------------------- # List of all object files -OBJS = bin.o \ +OBJS = asserts.o \ + bin.o \ binfmt.o \ condes.o \ config.o \ diff --git a/src/ld65/make/watcom.mak b/src/ld65/make/watcom.mak index 35820b14e..37b016522 100644 --- a/src/ld65/make/watcom.mak +++ b/src/ld65/make/watcom.mak @@ -43,7 +43,8 @@ CFLAGS += -i=..\common # ------------------------------------------------------------------------------ # All OBJ files -OBJS = bin.obj \ +OBJS = asserts.obj \ + bin.obj \ binfmt.obj \ condes.obj \ config.obj \ diff --git a/src/ld65/objdata.c b/src/ld65/objdata.c index c962c5164..2a4c1f674 100644 --- a/src/ld65/objdata.c +++ b/src/ld65/objdata.c @@ -88,6 +88,8 @@ ObjData* NewObjData (void) O->LineInfos = 0; O->StringCount = 0; O->Strings = 0; + O->AssertionCount = 0; + O->Assertions = 0; /* Return the new entry */ return O; @@ -135,6 +137,24 @@ void InsertObjData (ObjData* O) +void InsertObjGlobals (ObjData* O) +/* Insert imports and exports from the object file into the global import and + * export lists. + */ +{ + unsigned I; + + /* Insert exports and imports */ + for (I = 0; I < O->ExportCount; ++I) { + InsertExport (O->Exports[I]); + } + for (I = 0; I < O->ImportCount; ++I) { + InsertImport (O->Imports[I]); + } +} + + + unsigned MakeGlobalStringId (const ObjData* O, unsigned Index) /* Convert a local string id into a global one and return it. */ { diff --git a/src/ld65/objdata.h b/src/ld65/objdata.h index d1e5414a6..5adbce6b3 100644 --- a/src/ld65/objdata.h +++ b/src/ld65/objdata.h @@ -66,17 +66,19 @@ struct ObjData { unsigned FileCount; /* Input file count */ struct FileInfo** Files; /* List of input files */ unsigned SectionCount; /* Count of sections in this object */ - struct Section** Sections; /* List of all sections */ + struct Section** Sections; /* List of all sections */ unsigned ExportCount; /* Count of exports */ struct Export** Exports; /* List of all exports */ unsigned ImportCount; /* Count of imports */ - struct Import** Imports; /* List of all imports */ + struct Import** Imports; /* List of all imports */ unsigned DbgSymCount; /* Count of debug symbols */ struct DbgSym** DbgSyms; /* List of debug symbols */ unsigned LineInfoCount; /* Count of additional line infos */ struct LineInfo** LineInfos; /* List of additional line infos */ unsigned StringCount; /* Count of strings */ unsigned* Strings; /* List of global string indices */ + unsigned AssertionCount; /* Count of module assertions */ + struct Assertion** Assertions; /* List of module assertions */ }; @@ -109,6 +111,11 @@ void FreeObjStrings (ObjData* O); void InsertObjData (ObjData* O); /* Insert the ObjData object into the collection of used ObjData objects. */ +void InsertObjGlobals (ObjData* O); +/* Insert imports and exports from the object file into the global import and + * export lists. + */ + unsigned MakeGlobalStringId (const ObjData* O, unsigned Index); /* Convert a local string id into a global one and return it. */ diff --git a/src/ld65/objfile.c b/src/ld65/objfile.c index 313977973..a8c389cd7 100644 --- a/src/ld65/objfile.c +++ b/src/ld65/objfile.c @@ -44,6 +44,7 @@ #include "xmalloc.h" /* ld65 */ +#include "asserts.h" #include "dbgsyms.h" #include "error.h" #include "exports.h" @@ -101,15 +102,21 @@ static void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name) H->LineInfoSize = Read32 (Obj); H->StrPoolOffs = Read32 (Obj); H->StrPoolSize = Read32 (Obj); + H->AssertOffs = Read32 (Obj); + H->AssertSize = Read32 (Obj); } -void ObjReadFiles (FILE* F, ObjData* O) -/* Read the files list from a file at the current position */ +void ObjReadFiles (FILE* F, unsigned long Pos, ObjData* O) +/* Read the files list from a file at the given position */ { unsigned I; + /* Seek to the correct position */ + FileSetPos (F, Pos); + + /* Read the data */ O->FileCount = ReadVar (F); O->Files = xmalloc (O->FileCount * sizeof (O->Files[0])); for (I = 0; I < O->FileCount; ++I) { @@ -119,41 +126,69 @@ void ObjReadFiles (FILE* F, ObjData* O) -void ObjReadImports (FILE* F, ObjData* O) -/* Read the imports from a file at the current position */ +void ObjReadSections (FILE* F, unsigned long Pos, ObjData* O) +/* Read the section data from a file at the given position */ +{ + unsigned I; + + /* Seek to the correct position */ + FileSetPos (F, Pos); + + /* Read the data */ + O->SectionCount = ReadVar (F); + O->Sections = xmalloc (O->SectionCount * sizeof (O->Sections[0])); + for (I = 0; I < O->SectionCount; ++I) { + O->Sections [I] = ReadSection (F, O); + } +} + + + +void ObjReadImports (FILE* F, unsigned long Pos, ObjData* O) +/* Read the imports from a file at the given position */ { unsigned I; + /* Seek to the correct position */ + FileSetPos (F, Pos); + + /* Read the data */ O->ImportCount = ReadVar (F); O->Imports = xmalloc (O->ImportCount * sizeof (O->Imports[0])); for (I = 0; I < O->ImportCount; ++I) { O->Imports [I] = ReadImport (F, O); - InsertImport (O->Imports [I]); } } -void ObjReadExports (FILE* F, ObjData* O) -/* Read the exports from a file at the current position */ +void ObjReadExports (FILE* F, unsigned long Pos, ObjData* O) +/* Read the exports from a file at the given position */ { unsigned I; + /* Seek to the correct position */ + FileSetPos (F, Pos); + + /* Read the data */ O->ExportCount = ReadVar (F); O->Exports = xmalloc (O->ExportCount * sizeof (O->Exports[0])); for (I = 0; I < O->ExportCount; ++I) { O->Exports [I] = ReadExport (F, O); - InsertExport (O->Exports [I]); } } -void ObjReadDbgSyms (FILE* F, ObjData* O) -/* Read the debug symbols from a file at the current position */ +void ObjReadDbgSyms (FILE* F, unsigned long Pos, ObjData* O) +/* Read the debug symbols from a file at the given position */ { unsigned I; + /* Seek to the correct position */ + FileSetPos (F, Pos); + + /* Read the data */ O->DbgSymCount = ReadVar (F); O->DbgSyms = xmalloc (O->DbgSymCount * sizeof (O->DbgSyms[0])); for (I = 0; I < O->DbgSymCount; ++I) { @@ -163,11 +198,15 @@ void ObjReadDbgSyms (FILE* F, ObjData* O) -void ObjReadLineInfos (FILE* F, ObjData* O) -/* Read the line infos from a file at the current position */ +void ObjReadLineInfos (FILE* F, unsigned long Pos, ObjData* O) +/* Read the line infos from a file at the given position */ { unsigned I; + /* Seek to the correct position */ + FileSetPos (F, Pos); + + /* Read the data */ O->LineInfoCount = ReadVar (F); O->LineInfos = xmalloc (O->LineInfoCount * sizeof (O->LineInfos[0])); for (I = 0; I < O->LineInfoCount; ++I) { @@ -177,11 +216,15 @@ void ObjReadLineInfos (FILE* F, ObjData* O) -void ObjReadStrPool (FILE* F, ObjData* O) -/* Read the string pool from a file at the current position */ +void ObjReadStrPool (FILE* F, unsigned long Pos, ObjData* O) +/* Read the string pool from a file at the given position */ { unsigned I; + /* Seek to the correct position */ + FileSetPos (F, Pos); + + /* Read the data */ O->StringCount = ReadVar (F); O->Strings = xmalloc (O->StringCount * sizeof (O->Strings[0])); for (I = 0; I < O->StringCount; ++I) { @@ -191,15 +234,19 @@ void ObjReadStrPool (FILE* F, ObjData* O) -void ObjReadSections (FILE* F, ObjData* O) -/* Read the section data from a file at the current position */ +void ObjReadAssertions (FILE* F, unsigned long Pos, ObjData* O) +/* Read the assertions from a file at the given offset */ { unsigned I; - O->SectionCount = ReadVar (F); - O->Sections = xmalloc (O->SectionCount * sizeof (O->Sections[0])); - for (I = 0; I < O->SectionCount; ++I) { - O->Sections [I] = ReadSection (F, O); + /* Seek to the correct position */ + FileSetPos (F, Pos); + + /* Read the data */ + O->AssertionCount = ReadVar (F); + O->Assertions = xmalloc (O->AssertionCount * sizeof (O->Assertions[0])); + for (I = 0; I < O->AssertionCount; ++I) { + O->Assertions[I] = ReadAssertion (F, O); } } @@ -221,35 +268,31 @@ void ObjAdd (FILE* Obj, const char* Name) O->Name = GetModule (Name); /* Read the string pool from the object file */ - fseek (Obj, O->Header.StrPoolOffs, SEEK_SET); - ObjReadStrPool (Obj, O); + ObjReadStrPool (Obj, O->Header.StrPoolOffs, O); /* Read the files list from the object file */ - fseek (Obj, O->Header.FileOffs, SEEK_SET); - ObjReadFiles (Obj, O); + ObjReadFiles (Obj, O->Header.FileOffs, O); /* Read the imports list from the object file */ - fseek (Obj, O->Header.ImportOffs, SEEK_SET); - ObjReadImports (Obj, O); + ObjReadImports (Obj, O->Header.ImportOffs, O); /* Read the object file exports and insert them into the exports list */ - fseek (Obj, O->Header.ExportOffs, SEEK_SET); - ObjReadExports (Obj, O); + ObjReadExports (Obj, O->Header.ExportOffs, O); /* Read the object debug symbols from the object file */ - fseek (Obj, O->Header.DbgSymOffs, SEEK_SET); - ObjReadDbgSyms (Obj, O); + ObjReadDbgSyms (Obj, O->Header.DbgSymOffs, O); /* Read the line infos from the object file */ - fseek (Obj, O->Header.LineInfoOffs, SEEK_SET); - ObjReadLineInfos (Obj, O); + ObjReadLineInfos (Obj, O->Header.LineInfoOffs, O); + + /* Read the assertions from the object file */ + ObjReadAssertions (Obj, O->Header.AssertOffs, O); /* Read the segment list from the object file. This must be last, since * the expressions stored in the code may reference segments or imported * symbols. */ - fseek (Obj, O->Header.SegOffs, SEEK_SET); - ObjReadSections (Obj, O); + ObjReadSections (Obj, O->Header.SegOffs, O); /* Mark this object file as needed */ O->Flags |= OBJ_REF; @@ -257,13 +300,16 @@ void ObjAdd (FILE* Obj, const char* Name) /* Done, close the file (we read it only, so no error check) */ fclose (Obj); + /* Insert the imports and exports to the global lists */ + InsertObjGlobals (O); + + /* Insert the object into the list of all used object files */ + InsertObjData (O); + /* All references to strings are now resolved, so we can delete the module * string pool. */ FreeObjStrings (O); - - /* Insert the object into the list of all used object files */ - InsertObjData (O); } diff --git a/src/ld65/objfile.h b/src/ld65/objfile.h index 1c05d5761..f3bdf4cac 100644 --- a/src/ld65/objfile.h +++ b/src/ld65/objfile.h @@ -54,26 +54,29 @@ -void ObjReadFiles (FILE* F, ObjData* O); -/* Read the files list from a file at the current position */ +void ObjReadFiles (FILE* F, unsigned long Pos, ObjData* O); +/* Read the files list from a file at the given position */ -void ObjReadImports (FILE* F, ObjData* O); -/* Read the imports from a file at the current position */ +void ObjReadSections (FILE* F, unsigned long Pos, ObjData* O); +/* Read the section data from a file at the given position */ -void ObjReadExports (FILE* F, ObjData* O); -/* Read the exports from a file at the current position */ +void ObjReadImports (FILE* F, unsigned long Pos, ObjData* O); +/* Read the imports from a file at the given position */ -void ObjReadDbgSyms (FILE* F, ObjData* O); -/* Read the debug symbols from a file at the current position */ +void ObjReadExports (FILE* F, unsigned long Pos, ObjData* O); +/* Read the exports from a file at the given position */ -void ObjReadLineInfos (FILE* F, ObjData* O); -/* Read the line infos from a file at the current position */ +void ObjReadDbgSyms (FILE* F, unsigned long Pos, ObjData* O); +/* Read the debug symbols from a file at the given position */ -void ObjReadStrPool (FILE* F, ObjData* O); -/* Read the string pool from a file at the current position */ +void ObjReadLineInfos (FILE* F, unsigned long Pos, ObjData* O); +/* Read the line infos from a file at the given position */ -void ObjReadSections (FILE* F, ObjData* O); -/* Read the section data from a file at the current position */ +void ObjReadStrPool (FILE* F, unsigned long Pos, ObjData* O); +/* Read the string pool from a file at the given position */ + +void ObjReadAssertions (FILE* F, unsigned long Pos, ObjData* O); +/* Read the assertions from a file at the given offset */ void ObjAdd (FILE* F, const char* Name); /* Add an object file to the module list */ diff --git a/src/ld65/segments.c b/src/ld65/segments.c index c685ac48e..d834641d8 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -89,17 +89,18 @@ static Segment* NewSegment (unsigned Name, unsigned char Type) Segment* S = xmalloc (sizeof (Segment)); /* Initialize the fields */ - S->Name = Name; - S->Next = 0; - S->SecRoot = 0; - S->SecLast = 0; - S->PC = 0; - S->Size = 0; - S->AlignObj = 0; - S->Align = 0; - S->FillVal = 0; - S->Type = Type; - S->Dumped = 0; + S->Name = Name; + S->Next = 0; + S->SecRoot = 0; + S->SecLast = 0; + S->PC = 0; + S->Size = 0; + S->AlignObj = 0; + S->Align = 0; + S->FillVal = 0; + S->Type = Type; + S->Relocatable = 0; + S->Dumped = 0; /* Insert the segment into the segment list */ S->List = SegRoot; diff --git a/src/ld65/segments.h b/src/ld65/segments.h index 23b21bd12..660ed78d1 100644 --- a/src/ld65/segments.h +++ b/src/ld65/segments.h @@ -65,7 +65,8 @@ struct Segment { unsigned char Align; /* Alignment needed */ unsigned char FillVal; /* Value to use for fill bytes */ unsigned char Type; /* Type of segment */ - char Dumped; /* Did we dump this segment? */ + unsigned char Relocatable; /* True if the segment is relocatable */ + unsigned char Dumped; /* Did we dump this segment? */ }; @@ -156,5 +157,5 @@ void CheckSegments (void); #endif - + diff --git a/src/od65/fileio.c b/src/od65/fileio.c index b7f36f6d7..43a34ad92 100644 --- a/src/od65/fileio.c +++ b/src/od65/fileio.c @@ -225,6 +225,8 @@ void ReadObjHeader (FILE* F, ObjHeader* H) H->LineInfoSize = Read32 (F); H->StrPoolOffs = Read32 (F); H->StrPoolSize = Read32 (F); + H->AssertOffs = Read32 (F); + H->AssertSize = Read32 (F); } -- 2.39.5