repeat.o \
scanner.o \
segment.o \
+ segrange.o \
sizeof.o \
spool.o \
struct.o \
repeat.obj \
scanner.obj \
segment.obj \
+ segrange.obj \
sizeof.obj \
spool.obj \
struct.obj \
static void DoEndProc (void)
/* Leave a lexical level */
{
- if (CurrentScope == RootScope || GetCurrentSymTabType () != ST_PROC) {
+ if (GetCurrentSymTabType () != ST_PROC) {
/* No local scope */
ErrorSkip ("No open .PROC");
} else {
static void DoEndScope (void)
/* Leave a lexical level */
{
- if (CurrentScope == RootScope || GetCurrentSymTabType () != ST_SCOPE) {
+ if ( GetCurrentSymTabType () != ST_SCOPE) {
/* No local scope */
ErrorSkip ("No open .SCOPE");
} else {
static void DoTag (void)
/* Allocate space for a struct */
-{
+{
SymEntry* SizeSym;
long Size;
static unsigned SegmentCount = 6;
/* List of all segments */
-static Segment* SegmentList = &CodeSeg;
+Segment* SegmentList = &CodeSeg;
static Segment* SegmentLast = &NullSeg;
/* Currently active segment */
extern SegDef RODataSegDef;
extern SegDef CodeSegDef;
+/* List of all segments */
+extern Segment* SegmentList;
+
/* Currently active segment */
extern Segment* ActiveSeg;
#include "objfile.h"
#include "scanner.h"
#include "segment.h"
+#include "sizeof.h"
#include "spool.h"
#include "symtab.h"
S->Left = 0;
S->Right = 0;
S->Childs = 0;
+ S->SegRanges = AUTO_COLLECTION_INITIALIZER;
S->Flags = ST_NONE;
S->AddrSize = ADDR_SIZE_DEFAULT;
S->Type = ST_UNDEF;
CurrentScope->Flags |= ST_DEFINED;
CurrentScope->AddrSize = AddrSize;
CurrentScope->Type = Type;
+
+ /* If this is a scope that allows to emit data into segments, add segment
+ * ranges for all currently existing segments. Doing this for just a few
+ * scope types is not really necessary but an optimization, because it
+ * does not allocate memory for useless data (unhandled types here don't
+ * occupy space in any segment).
+ */
+ if (CurrentScope->Type <= ST_SCOPE_HAS_DATA) {
+ AddSegRanges (&CurrentScope->SegRanges);
+ }
}
void SymLeaveLevel (void)
/* Leave the current lexical level */
{
+ /* Close the segment ranges. We don't care about the scope type here,
+ * since types without segment ranges will just have an empty list.
+ */
+ CloseSegRanges (&CurrentScope->SegRanges);
+
+ /* If we have segment ranges, the first one is the segment that was
+ * active, when the scope was opened. Set the size of the scope to the
+ * number of data bytes emitted into this segment.
+ */
+ if (CollCount (&CurrentScope->SegRanges) > 0) {
+ const SegRange* R = CollAtUnchecked (&CurrentScope->SegRanges, 0);
+ DefSizeOfScope (CurrentScope, GetSegRangeSize (R));
+ }
+
+ /* Leave the scope */
CurrentScope = CurrentScope->Parent;
}
#include "inline.h"
/* ca65 */
+#include "segrange.h"
#include "symentry.h"
#define ST_DEFINED 0x01 /* Scope has been defined */
/* Symbol table types */
-#define ST_GLOBAL 0x00 /* Root level */
-#define ST_PROC 0x01 /* .PROC */
-#define ST_SCOPE 0x02 /* .SCOPE */
-#define ST_STRUCT 0x03 /* .STRUCT/.UNION */
-#define ST_ENUM 0x04 /* .ENUM */
-#define ST_UNDEF 0xFF
+enum {
+ ST_GLOBAL, /* Root level */
+ ST_PROC, /* .PROC */
+ ST_SCOPE, /* .SCOPE */
+ ST_SCOPE_HAS_DATA = ST_SCOPE, /* Last scope that contains data */
+ ST_STRUCT, /* .STRUCT/.UNION */
+ ST_ENUM, /* .ENUM */
+ ST_UNDEF = 0xFF
+};
/* A symbol table */
typedef struct SymTable SymTable;
SymTable* Right; /* Pointer to greater entry */
SymTable* Parent; /* Link to enclosing scope if any */
SymTable* Childs; /* Pointer to child scopes */
+ Collection SegRanges; /* Segment ranges for this scope */
unsigned short Flags; /* Symbol table flags */
- unsigned char AddrSize; /* Address size */
+ unsigned char AddrSize; /* Address size */
unsigned char Type; /* Type of the scope */
unsigned Level; /* Lexical level */
unsigned TableSlots; /* Number of hash table slots */
- unsigned TableEntries; /* Number of entries in the table */
+ unsigned TableEntries; /* Number of entries in the table */
unsigned Name; /* Name of the scope */
SymEntry* Table[1]; /* Dynamic allocation */
};
-