mirror of
https://github.com/cc65/cc65.git
synced 2025-08-08 06:25:17 +00:00
Working on the new backend
git-svn-id: svn://svn.cc65.org/cc65/trunk@715 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -40,6 +40,7 @@
|
|||||||
#include "codeopt.h"
|
#include "codeopt.h"
|
||||||
#include "codeseg.h"
|
#include "codeseg.h"
|
||||||
#include "dataseg.h"
|
#include "dataseg.h"
|
||||||
|
#include "segments.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "asmcode.h"
|
#include "asmcode.h"
|
||||||
|
|
||||||
@@ -62,7 +63,7 @@ void AddCodeHint (const char* Hint)
|
|||||||
CodeMark GetCodePos (void)
|
CodeMark GetCodePos (void)
|
||||||
/* Get a marker pointing to the current output position */
|
/* Get a marker pointing to the current output position */
|
||||||
{
|
{
|
||||||
return GetCodeSegEntries (CS);
|
return GetCodeSegEntries (CS->Code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -70,22 +71,7 @@ CodeMark GetCodePos (void)
|
|||||||
void RemoveCode (CodeMark M)
|
void RemoveCode (CodeMark M)
|
||||||
/* Remove all code after the given code marker */
|
/* Remove all code after the given code marker */
|
||||||
{
|
{
|
||||||
DelCodeSegAfter (CS, M);
|
DelCodeSegAfter (CS->Code, M);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void PrintFunctionHeader (FILE* F, SymEntry* Entry)
|
|
||||||
{
|
|
||||||
/* Print a comment with the function signature */
|
|
||||||
fprintf (F,
|
|
||||||
"; ---------------------------------------------------------------\n"
|
|
||||||
"; ");
|
|
||||||
PrintFuncSig (F, Entry->Name, Entry->Type);
|
|
||||||
fprintf (F,
|
|
||||||
"\n"
|
|
||||||
"; ---------------------------------------------------------------\n"
|
|
||||||
"\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -96,9 +82,9 @@ void WriteOutput (FILE* F)
|
|||||||
SymTable* SymTab;
|
SymTable* SymTab;
|
||||||
SymEntry* Entry;
|
SymEntry* Entry;
|
||||||
|
|
||||||
/* Output the data segment (the global code segment should be empty) */
|
/* Output the global data segment */
|
||||||
OutputDataSeg (F, DS);
|
CHECK (GetCodeSegEntries (CS->Code) == 0);
|
||||||
CHECK (GetCodeSegEntries (CS) == 0);
|
OutputSegments (CS, F);
|
||||||
|
|
||||||
/* Output all global or referenced functions */
|
/* Output all global or referenced functions */
|
||||||
SymTab = GetGlobalSymTab ();
|
SymTab = GetGlobalSymTab ();
|
||||||
@@ -108,13 +94,9 @@ void WriteOutput (FILE* F)
|
|||||||
(Entry->Flags & SC_DEF) != 0 &&
|
(Entry->Flags & SC_DEF) != 0 &&
|
||||||
(Entry->Flags & (SC_REF | SC_EXTERN)) != 0) {
|
(Entry->Flags & (SC_REF | SC_EXTERN)) != 0) {
|
||||||
/* Function which is defined and referenced or extern */
|
/* Function which is defined and referenced or extern */
|
||||||
PrintFunctionHeader (F, Entry);
|
MergeCodeLabels (Entry->V.F.Seg->Code);
|
||||||
MergeCodeLabels (Entry->V.F.CS);
|
RunOpt (Entry->V.F.Seg->Code);
|
||||||
RunOpt (Entry->V.F.CS);
|
OutputSegments (Entry->V.F.Seg, F);
|
||||||
fprintf (F, "; Data segment for function %s:\n", Entry->Name);
|
|
||||||
OutputDataSeg (F, Entry->V.F.DS);
|
|
||||||
fprintf (F, "; Code segment for function %s:\n", Entry->Name);
|
|
||||||
OutputCodeSeg (F, Entry->V.F.CS);
|
|
||||||
}
|
}
|
||||||
Entry = Entry->NextSym;
|
Entry = Entry->NextSym;
|
||||||
}
|
}
|
||||||
|
@@ -119,7 +119,7 @@ int CodeEntryHasLabel (const CodeEntry* E)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void OutputCodeEntry (FILE* F, const CodeEntry* E)
|
void OutputCodeEntry (const CodeEntry* E, FILE* F)
|
||||||
/* Output the code entry to a file */
|
/* Output the code entry to a file */
|
||||||
{
|
{
|
||||||
const OPCDesc* D;
|
const OPCDesc* D;
|
||||||
@@ -129,7 +129,7 @@ void OutputCodeEntry (FILE* F, const CodeEntry* E)
|
|||||||
unsigned LabelCount = CollCount (&E->Labels);
|
unsigned LabelCount = CollCount (&E->Labels);
|
||||||
unsigned I;
|
unsigned I;
|
||||||
for (I = 0; I < LabelCount; ++I) {
|
for (I = 0; I < LabelCount; ++I) {
|
||||||
OutputCodeLabel (F, CollConstAt (&E->Labels, I));
|
OutputCodeLabel (CollConstAt (&E->Labels, I), F);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the opcode description */
|
/* Get the opcode description */
|
||||||
|
@@ -91,7 +91,7 @@ void FreeCodeEntry (CodeEntry* E);
|
|||||||
int CodeEntryHasLabel (const CodeEntry* E);
|
int CodeEntryHasLabel (const CodeEntry* E);
|
||||||
/* Check if the given code entry has labels attached */
|
/* Check if the given code entry has labels attached */
|
||||||
|
|
||||||
void OutputCodeEntry (FILE* F, const CodeEntry* E);
|
void OutputCodeEntry (const CodeEntry* E, FILE* F);
|
||||||
/* Output the code entry to a file */
|
/* Output the code entry to a file */
|
||||||
|
|
||||||
|
|
||||||
|
1510
src/cc65/codegen.c
1510
src/cc65/codegen.c
File diff suppressed because it is too large
Load Diff
@@ -38,14 +38,8 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/* cc65 */
|
||||||
/* Forwards */
|
#include "segments.h"
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct CodeSeg;
|
|
||||||
struct DataSeg;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -109,12 +103,6 @@ void g_preamble (void);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void g_pushseg (struct CodeSeg** CS, struct DataSeg** DS, const char* FuncName);
|
|
||||||
/* Push the current segments and generate new ones for the given function */
|
|
||||||
|
|
||||||
void g_popseg (void);
|
|
||||||
/* Restore the old segments */
|
|
||||||
|
|
||||||
void g_userodata (void);
|
void g_userodata (void);
|
||||||
/* Switch to the read only data segment */
|
/* Switch to the read only data segment */
|
||||||
|
|
||||||
@@ -124,18 +112,6 @@ void g_usedata (void);
|
|||||||
void g_usebss (void);
|
void g_usebss (void);
|
||||||
/* Switch to the bss segment */
|
/* Switch to the bss segment */
|
||||||
|
|
||||||
void g_codename (const char* Name);
|
|
||||||
/* Set the name of the CODE segment */
|
|
||||||
|
|
||||||
void g_rodataname (const char* Name);
|
|
||||||
/* Set the name of the RODATA segment */
|
|
||||||
|
|
||||||
void g_dataname (const char* Name);
|
|
||||||
/* Set the name of the DATA segment */
|
|
||||||
|
|
||||||
void g_bssname (const char* Name);
|
|
||||||
/* Set the name of the BSS segment */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@@ -36,7 +36,7 @@
|
|||||||
/* common */
|
/* common */
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "codeent.h"
|
#include "codeent.h"
|
||||||
#include "codelab.h"
|
#include "codelab.h"
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void OutputCodeLabel (FILE* F, const CodeLabel* L)
|
void OutputCodeLabel (const CodeLabel* L, FILE* F)
|
||||||
/* Output the code label to a file */
|
/* Output the code label to a file */
|
||||||
{
|
{
|
||||||
fprintf (F, "%s:", L->Name);
|
fprintf (F, "%s:", L->Name);
|
||||||
|
@@ -95,7 +95,7 @@ void AddLabelRef (CodeLabel* L, struct CodeEntry* E);
|
|||||||
unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E);
|
unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E);
|
||||||
/* Remove a reference to this label, return the number of remaining references */
|
/* Remove a reference to this label, return the number of remaining references */
|
||||||
|
|
||||||
void OutputCodeLabel (FILE* F, const CodeLabel* L);
|
void OutputCodeLabel (const CodeLabel* L, FILE* F);
|
||||||
/* Output the code label to a file */
|
/* Output the code label to a file */
|
||||||
|
|
||||||
|
|
||||||
|
@@ -88,7 +88,7 @@ static void OptDeadJumps (CodeSeg* S)
|
|||||||
if (E->AM == AM_BRA && E->JumpTo && E->JumpTo->Owner == CollAt (&S->Entries, I+1)) {
|
if (E->AM == AM_BRA && E->JumpTo && E->JumpTo->Owner == CollAt (&S->Entries, I+1)) {
|
||||||
|
|
||||||
/* Delete the dead jump */
|
/* Delete the dead jump */
|
||||||
DelCodeSegLine (S, I);
|
DelCodeEntry (S, I);
|
||||||
|
|
||||||
/* Keep the number of entries updated */
|
/* Keep the number of entries updated */
|
||||||
--Count;
|
--Count;
|
||||||
@@ -140,7 +140,7 @@ static void OptDeadCode (CodeSeg* S)
|
|||||||
!CodeEntryHasLabel (CollAt (&S->Entries, I+1))) {
|
!CodeEntryHasLabel (CollAt (&S->Entries, I+1))) {
|
||||||
|
|
||||||
/* Delete the next entry */
|
/* Delete the next entry */
|
||||||
DelCodeSegLine (S, I+1);
|
DelCodeEntry (S, I+1);
|
||||||
|
|
||||||
/* Keep the number of entries updated */
|
/* Keep the number of entries updated */
|
||||||
--Count;
|
--Count;
|
||||||
|
@@ -52,17 +52,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Data */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Pointer to current code segment */
|
|
||||||
CodeSeg* CS = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Functions for parsing instructions */
|
/* Functions for parsing instructions */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -309,7 +298,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
CodeSeg* NewCodeSeg (const char* SegName, const char* FuncName)
|
CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func)
|
||||||
/* Create a new code segment, initialize and return it */
|
/* Create a new code segment, initialize and return it */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
@@ -318,9 +307,8 @@ CodeSeg* NewCodeSeg (const char* SegName, const char* FuncName)
|
|||||||
CodeSeg* S = xmalloc (sizeof (CodeSeg));
|
CodeSeg* S = xmalloc (sizeof (CodeSeg));
|
||||||
|
|
||||||
/* Initialize the fields */
|
/* Initialize the fields */
|
||||||
S->Next = 0;
|
|
||||||
S->SegName = xstrdup (SegName);
|
S->SegName = xstrdup (SegName);
|
||||||
S->FuncName = xstrdup (FuncName);
|
S->Func = Func;
|
||||||
InitCollection (&S->Entries);
|
InitCollection (&S->Entries);
|
||||||
InitCollection (&S->Labels);
|
InitCollection (&S->Labels);
|
||||||
for (I = 0; I < sizeof(S->LabelHash) / sizeof(S->LabelHash[0]); ++I) {
|
for (I = 0; I < sizeof(S->LabelHash) / sizeof(S->LabelHash[0]); ++I) {
|
||||||
@@ -336,39 +324,12 @@ CodeSeg* NewCodeSeg (const char* SegName, const char* FuncName)
|
|||||||
void FreeCodeSeg (CodeSeg* S)
|
void FreeCodeSeg (CodeSeg* S)
|
||||||
/* Free a code segment including all code entries */
|
/* Free a code segment including all code entries */
|
||||||
{
|
{
|
||||||
FAIL ("Not implemented");
|
Internal ("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PushCodeSeg (CodeSeg* S)
|
void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap)
|
||||||
/* Push the given code segment onto the stack */
|
|
||||||
{
|
|
||||||
S->Next = CS;
|
|
||||||
CS = S;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CodeSeg* PopCodeSeg (void)
|
|
||||||
/* Remove the current code segment from the stack and return it */
|
|
||||||
{
|
|
||||||
/* Remember the current code segment */
|
|
||||||
CodeSeg* S = CS;
|
|
||||||
|
|
||||||
/* Cannot pop on empty stack */
|
|
||||||
PRECONDITION (S != 0);
|
|
||||||
|
|
||||||
/* Pop */
|
|
||||||
CS = S->Next;
|
|
||||||
|
|
||||||
/* Return the popped code segment */
|
|
||||||
return S;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AddCodeSegLine (CodeSeg* S, const char* Format, ...)
|
|
||||||
/* Add a line to the given code segment */
|
/* Add a line to the given code segment */
|
||||||
{
|
{
|
||||||
const char* L;
|
const char* L;
|
||||||
@@ -376,11 +337,8 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...)
|
|||||||
char Token[64];
|
char Token[64];
|
||||||
|
|
||||||
/* Format the line */
|
/* Format the line */
|
||||||
va_list ap;
|
|
||||||
char Buf [256];
|
char Buf [256];
|
||||||
va_start (ap, Format);
|
|
||||||
xvsprintf (Buf, sizeof (Buf), Format, ap);
|
xvsprintf (Buf, sizeof (Buf), Format, ap);
|
||||||
va_end (ap);
|
|
||||||
|
|
||||||
/* Skip whitespace */
|
/* Skip whitespace */
|
||||||
L = SkipSpace (Buf);
|
L = SkipSpace (Buf);
|
||||||
@@ -436,7 +394,7 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void DelCodeSegLine (CodeSeg* S, unsigned Index)
|
void DelCodeEntry (CodeSeg* S, unsigned Index)
|
||||||
/* Delete an entry from the code segment. This includes deleting any associated
|
/* Delete an entry from the code segment. This includes deleting any associated
|
||||||
* labels, removing references to labels and even removing the referenced labels
|
* labels, removing references to labels and even removing the referenced labels
|
||||||
* if the reference count drops to zero.
|
* if the reference count drops to zero.
|
||||||
@@ -592,7 +550,7 @@ void DelCodeSegAfter (CodeSeg* S, unsigned Last)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void OutputCodeSeg (FILE* F, const CodeSeg* S)
|
void OutputCodeSeg (const CodeSeg* S, FILE* F)
|
||||||
/* Output the code segment data to a file */
|
/* Output the code segment data to a file */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
@@ -600,31 +558,26 @@ void OutputCodeSeg (FILE* F, const CodeSeg* S)
|
|||||||
/* Get the number of entries in this segment */
|
/* Get the number of entries in this segment */
|
||||||
unsigned Count = CollCount (&S->Entries);
|
unsigned Count = CollCount (&S->Entries);
|
||||||
|
|
||||||
fprintf (F, "; Labels: ");
|
/* If the code segment is empty, bail out here */
|
||||||
for (I = 0; I < CS_LABEL_HASH_SIZE; ++I) {
|
if (Count == 0) {
|
||||||
const CodeLabel* L = S->LabelHash[I];
|
return;
|
||||||
while (L) {
|
|
||||||
fprintf (F, "%s ", L->Name);
|
|
||||||
L = L->Next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fprintf (F, "\n");
|
|
||||||
|
|
||||||
/* Output the segment directive */
|
/* Output the segment directive */
|
||||||
fprintf (F, ".segment\t\"%s\"\n\n", S->SegName);
|
fprintf (F, ".segment\t\"%s\"\n\n", S->SegName);
|
||||||
|
|
||||||
/* If this is a segment for a function, enter a function */
|
/* If this is a segment for a function, enter a function */
|
||||||
if (S->FuncName[0] != '\0') {
|
if (S->Func) {
|
||||||
fprintf (F, ".proc\t_%s\n\n", S->FuncName);
|
fprintf (F, ".proc\t_%s\n\n", S->Func->Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output all entries */
|
/* Output all entries */
|
||||||
for (I = 0; I < Count; ++I) {
|
for (I = 0; I < Count; ++I) {
|
||||||
OutputCodeEntry (F, CollConstAt (&S->Entries, I));
|
OutputCodeEntry (CollConstAt (&S->Entries, I), F);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is a segment for a function, leave the function */
|
/* If this is a segment for a function, leave the function */
|
||||||
if (S->FuncName[0] != '\0') {
|
if (S->Func) {
|
||||||
fprintf (F, "\n.endproc\n\n");
|
fprintf (F, "\n.endproc\n\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,8 @@
|
|||||||
#define CODESEG_H
|
#define CODESEG_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
@@ -46,11 +47,12 @@
|
|||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "codelab.h"
|
#include "codelab.h"
|
||||||
|
#include "symentry.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
@@ -61,41 +63,31 @@
|
|||||||
/* Code segment structure */
|
/* Code segment structure */
|
||||||
typedef struct CodeSeg CodeSeg;
|
typedef struct CodeSeg CodeSeg;
|
||||||
struct CodeSeg {
|
struct CodeSeg {
|
||||||
CodeSeg* Next; /* Pointer to next CodeSeg */
|
|
||||||
char* SegName; /* Segment name */
|
char* SegName; /* Segment name */
|
||||||
char* FuncName; /* Name of function */
|
SymEntry* Func; /* Owner function */
|
||||||
Collection Entries; /* List of code entries */
|
Collection Entries; /* List of code entries */
|
||||||
Collection Labels; /* Labels for next insn */
|
Collection Labels; /* Labels for next insn */
|
||||||
CodeLabel* LabelHash [CS_LABEL_HASH_SIZE]; /* Label hash table */
|
CodeLabel* LabelHash [CS_LABEL_HASH_SIZE]; /* Label hash table */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Pointer to current code segment */
|
|
||||||
extern CodeSeg* CS;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CodeSeg* NewCodeSeg (const char* SegName, const char* FuncName);
|
CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func);
|
||||||
/* Create a new code segment, initialize and return it */
|
/* Create a new code segment, initialize and return it */
|
||||||
|
|
||||||
void FreeCodeSeg (CodeSeg* S);
|
void FreeCodeSeg (CodeSeg* S);
|
||||||
/* Free a code segment including all code entries */
|
/* Free a code segment including all code entries */
|
||||||
|
|
||||||
void PushCodeSeg (CodeSeg* S);
|
void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap) attribute ((format(printf,2,0)));
|
||||||
/* Push the given code segment onto the stack */
|
|
||||||
|
|
||||||
CodeSeg* PopCodeSeg (void);
|
|
||||||
/* Remove the current code segment from the stack and return it */
|
|
||||||
|
|
||||||
void AddCodeSegLine (CodeSeg* S, const char* Format, ...) attribute ((format(printf,2,3)));
|
|
||||||
/* Add a line to the given code segment */
|
/* Add a line to the given code segment */
|
||||||
|
|
||||||
void DelCodeSegLine (CodeSeg* S, unsigned Index);
|
void DelCodeEntry (CodeSeg* S, unsigned Index);
|
||||||
/* Delete an entry from the code segment. This includes deleting any associated
|
/* Delete an entry from the code segment. This includes deleting any associated
|
||||||
* labels, removing references to labels and even removing the referenced labels
|
* labels, removing references to labels and even removing the referenced labels
|
||||||
* if the reference count drops to zero.
|
* if the reference count drops to zero.
|
||||||
@@ -113,7 +105,7 @@ void AddCodeSegHint (CodeSeg* S, unsigned Hint);
|
|||||||
void DelCodeSegAfter (CodeSeg* S, unsigned Last);
|
void DelCodeSegAfter (CodeSeg* S, unsigned Last);
|
||||||
/* Delete all entries including the given one */
|
/* Delete all entries including the given one */
|
||||||
|
|
||||||
void OutputCodeSeg (FILE* F, const CodeSeg* S);
|
void OutputCodeSeg (const CodeSeg* S, FILE* F);
|
||||||
/* Output the code segment data to a file */
|
/* Output the code segment data to a file */
|
||||||
|
|
||||||
CodeLabel* FindCodeLabel (CodeSeg* S, const char* Name, unsigned Hash);
|
CodeLabel* FindCodeLabel (CodeSeg* S, const char* Name, unsigned Hash);
|
||||||
|
@@ -39,36 +39,26 @@
|
|||||||
#include "xsprintf.h"
|
#include "xsprintf.h"
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
|
#include "error.h"
|
||||||
#include "dataseg.h"
|
#include "dataseg.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Data */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Pointer to current data segment */
|
|
||||||
DataSeg* DS = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DataSeg* NewDataSeg (const char* Name)
|
DataSeg* NewDataSeg (const char* Name, SymEntry* Func)
|
||||||
/* Create a new data segment, initialize and return it */
|
/* Create a new data segment, initialize and return it */
|
||||||
{
|
{
|
||||||
/* Allocate memory */
|
/* Allocate memory */
|
||||||
DataSeg* S = xmalloc (sizeof (DataSeg));
|
DataSeg* S = xmalloc (sizeof (DataSeg));
|
||||||
|
|
||||||
/* Initialize the fields */
|
/* Initialize the fields */
|
||||||
S->Next = 0;
|
S->SegName = xstrdup (Name);
|
||||||
S->Name = xstrdup (Name);
|
S->Func = Func;
|
||||||
InitCollection (&S->Lines);
|
InitCollection (&S->Lines);
|
||||||
|
|
||||||
/* Return the new struct */
|
/* Return the new struct */
|
||||||
@@ -80,50 +70,7 @@ DataSeg* NewDataSeg (const char* Name)
|
|||||||
void FreeDataSeg (DataSeg* S)
|
void FreeDataSeg (DataSeg* S)
|
||||||
/* Free a data segment including all line entries */
|
/* Free a data segment including all line entries */
|
||||||
{
|
{
|
||||||
unsigned I, Count;
|
Internal ("Not implemented");
|
||||||
|
|
||||||
/* Free the name */
|
|
||||||
xfree (S->Name);
|
|
||||||
|
|
||||||
/* Free the lines */
|
|
||||||
Count = CollCount (&S->Lines);
|
|
||||||
for (I = 0; I < Count; ++I) {
|
|
||||||
xfree (CollAt (&S->Lines, I));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free the collection */
|
|
||||||
DoneCollection (&S->Lines);
|
|
||||||
|
|
||||||
/* Free the struct */
|
|
||||||
xfree (S);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PushDataSeg (DataSeg* S)
|
|
||||||
/* Push the given data segment onto the stack */
|
|
||||||
{
|
|
||||||
/* Push */
|
|
||||||
S->Next = DS;
|
|
||||||
DS = S;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DataSeg* PopDataSeg (void)
|
|
||||||
/* Remove the current data segment from the stack and return it */
|
|
||||||
{
|
|
||||||
/* Remember the current data segment */
|
|
||||||
DataSeg* S = DS;
|
|
||||||
|
|
||||||
/* Cannot pop on empty stack */
|
|
||||||
PRECONDITION (S != 0);
|
|
||||||
|
|
||||||
/* Pop */
|
|
||||||
DS = S->Next;
|
|
||||||
|
|
||||||
/* Return the popped data segment */
|
|
||||||
return S;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -142,16 +89,12 @@ void AppendDataSeg (DataSeg* Target, const DataSeg* Source)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AddDataSegLine (DataSeg* S, const char* Format, ...)
|
void AddDataEntry (DataSeg* S, const char* Format, va_list ap)
|
||||||
/* Add a line to the given data segment */
|
/* Add a line to the given data segment */
|
||||||
{
|
{
|
||||||
va_list ap;
|
|
||||||
char Buf [256];
|
|
||||||
|
|
||||||
/* Format the line */
|
/* Format the line */
|
||||||
va_start (ap, Format);
|
char Buf [256];
|
||||||
xvsprintf (Buf, sizeof (Buf), Format, ap);
|
xvsprintf (Buf, sizeof (Buf), Format, ap);
|
||||||
va_end (ap);
|
|
||||||
|
|
||||||
/* Add a copy to the data segment */
|
/* Add a copy to the data segment */
|
||||||
CollAppend (&S->Lines, xstrdup (Buf));
|
CollAppend (&S->Lines, xstrdup (Buf));
|
||||||
@@ -159,7 +102,7 @@ void AddDataSegLine (DataSeg* S, const char* Format, ...)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void OutputDataSeg (FILE* F, const DataSeg* S)
|
void OutputDataSeg (const DataSeg* S, FILE* F)
|
||||||
/* Output the data segment data to a file */
|
/* Output the data segment data to a file */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
@@ -167,10 +110,21 @@ void OutputDataSeg (FILE* F, const DataSeg* S)
|
|||||||
/* Get the number of entries in this segment */
|
/* Get the number of entries in this segment */
|
||||||
unsigned Count = CollCount (&S->Lines);
|
unsigned Count = CollCount (&S->Lines);
|
||||||
|
|
||||||
|
/* If the segment is actually empty, bail out */
|
||||||
|
if (Count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Output the segment directive */
|
||||||
|
fprintf (F, ".segment\t\"%s\"\n\n", S->SegName);
|
||||||
|
|
||||||
/* Output all entries */
|
/* Output all entries */
|
||||||
for (I = 0; I < Count; ++I) {
|
for (I = 0; I < Count; ++I) {
|
||||||
fprintf (F, "%s\n", (const char*) CollConstAt (&S->Lines, I));
|
fprintf (F, "%s\n", (const char*) CollConstAt (&S->Lines, I));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add an additional newline after the segment output */
|
||||||
|
fprintf (F, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -38,30 +38,31 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "attrib.h"
|
#include "attrib.h"
|
||||||
#include "coll.h"
|
#include "coll.h"
|
||||||
|
|
||||||
|
/* cc65 */
|
||||||
|
#include "symentry.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct DataSeg DataSeg;
|
typedef struct DataSeg DataSeg;
|
||||||
struct DataSeg {
|
struct DataSeg {
|
||||||
DataSeg* Next; /* Pointer to next DataSeg */
|
char* SegName; /* Segment name */
|
||||||
char* Name; /* Segment name */
|
SymEntry* Func; /* Owner function */
|
||||||
Collection Lines; /* List of code lines */
|
Collection Lines; /* List of code lines */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Pointer to current data segment */
|
|
||||||
extern DataSeg* DS;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -70,25 +71,19 @@ extern DataSeg* DS;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
DataSeg* NewDataSeg (const char* Name);
|
DataSeg* NewDataSeg (const char* SegName, SymEntry* Func);
|
||||||
/* Create a new data segment, initialize and return it */
|
/* Create a new data segment, initialize and return it */
|
||||||
|
|
||||||
void FreeDataSeg (DataSeg* S);
|
void FreeDataSeg (DataSeg* S);
|
||||||
/* Free a data segment including all line entries */
|
/* Free a data segment including all line entries */
|
||||||
|
|
||||||
void PushDataSeg (DataSeg* S);
|
|
||||||
/* Push the given data segment onto the stack */
|
|
||||||
|
|
||||||
DataSeg* PopDataSeg (void);
|
|
||||||
/* Remove the current data segment from the stack and return it */
|
|
||||||
|
|
||||||
void AppendDataSeg (DataSeg* Target, const DataSeg* Source);
|
void AppendDataSeg (DataSeg* Target, const DataSeg* Source);
|
||||||
/* Append the data from Source to Target. */
|
/* Append the data from Source to Target. */
|
||||||
|
|
||||||
void AddDataSegLine (DataSeg* S, const char* Format, ...) attribute ((format(printf,2,3)));
|
void AddDataEntry (DataSeg* S, const char* Format, va_list ap) attribute ((format(printf,2,0)));
|
||||||
/* Add a line to the given data segment */
|
/* Add a line to the given data segment */
|
||||||
|
|
||||||
void OutputDataSeg (FILE* F, const DataSeg* S);
|
void OutputDataSeg (const DataSeg* S, FILE* F);
|
||||||
/* Output the data segment data to a file */
|
/* Output the data segment data to a file */
|
||||||
|
|
||||||
|
|
||||||
|
@@ -47,6 +47,7 @@
|
|||||||
#include "litpool.h"
|
#include "litpool.h"
|
||||||
#include "locals.h"
|
#include "locals.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
|
#include "segments.h"
|
||||||
#include "stmt.h"
|
#include "stmt.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "function.h"
|
#include "function.h"
|
||||||
@@ -246,7 +247,7 @@ void NewFunc (SymEntry* Func)
|
|||||||
InitRegVars ();
|
InitRegVars ();
|
||||||
|
|
||||||
/* Allocate code and data segments for this function */
|
/* Allocate code and data segments for this function */
|
||||||
g_pushseg (&Func->V.F.CS, &Func->V.F.DS, Func->Name);
|
Func->V.F.Seg = PushSegments (Func);
|
||||||
|
|
||||||
/* If this is a fastcall function, push the last parameter onto the stack */
|
/* If this is a fastcall function, push the last parameter onto the stack */
|
||||||
if (IsFastCallFunc (Func->Type) && D->ParamCount > 0) {
|
if (IsFastCallFunc (Func->Type) && D->ParamCount > 0) {
|
||||||
@@ -336,7 +337,7 @@ void NewFunc (SymEntry* Func)
|
|||||||
LeaveFunctionLevel ();
|
LeaveFunctionLevel ();
|
||||||
|
|
||||||
/* Switch back to the old segments */
|
/* Switch back to the old segments */
|
||||||
g_popseg ();
|
PopSegments ();
|
||||||
|
|
||||||
/* Reset the current function pointer */
|
/* Reset the current function pointer */
|
||||||
FreeFunction (CurrentFunc);
|
FreeFunction (CurrentFunc);
|
||||||
|
@@ -59,7 +59,7 @@
|
|||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "macrotab.h"
|
#include "macrotab.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "segname.h"
|
#include "segments.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -56,14 +56,14 @@ OBJS = anonname.o \
|
|||||||
opcodes.o \
|
opcodes.o \
|
||||||
preproc.o \
|
preproc.o \
|
||||||
pragma.o \
|
pragma.o \
|
||||||
scanner.o \
|
scanner.o \
|
||||||
segname.o \
|
segments.o \
|
||||||
stdfunc.o \
|
stdfunc.o \
|
||||||
stmt.o \
|
stmt.o \
|
||||||
symentry.o \
|
symentry.o \
|
||||||
symtab.o \
|
symtab.o \
|
||||||
typecmp.o \
|
typecmp.o \
|
||||||
util.o
|
util.o
|
||||||
|
|
||||||
LIBS = $(COMMON)/common.a
|
LIBS = $(COMMON)/common.a
|
||||||
|
|
||||||
|
@@ -6,10 +6,10 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2000 Ullrich von Bassewitz */
|
/* (C) 1998-2001 Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Wacholderweg 14 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70597 Stuttgart */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
@@ -37,13 +37,12 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "codegen.h"
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "litpool.h"
|
#include "litpool.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "segname.h"
|
#include "segments.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "pragma.h"
|
#include "pragma.h"
|
||||||
|
|
||||||
@@ -138,7 +137,7 @@ static void StringPragma (void (*Func) (const char*))
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void SegNamePragma (void (*Func) (const char*))
|
static void SegNamePragma (segment_t Seg)
|
||||||
/* Handle a pragma that expects a segment name parameter */
|
/* Handle a pragma that expects a segment name parameter */
|
||||||
{
|
{
|
||||||
if (curtok != TOK_SCONST) {
|
if (curtok != TOK_SCONST) {
|
||||||
@@ -150,8 +149,8 @@ static void SegNamePragma (void (*Func) (const char*))
|
|||||||
/* Check if the name is valid */
|
/* Check if the name is valid */
|
||||||
if (ValidSegName (Name)) {
|
if (ValidSegName (Name)) {
|
||||||
|
|
||||||
/* Call the given function to set the name */
|
/* Set the new name */
|
||||||
Func (Name);
|
NewSegName (Seg, Name);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -216,7 +215,7 @@ void DoPragma (void)
|
|||||||
switch (Pragma) {
|
switch (Pragma) {
|
||||||
|
|
||||||
case PR_BSSSEG:
|
case PR_BSSSEG:
|
||||||
SegNamePragma (g_bssname);
|
SegNamePragma (SEG_BSS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PR_CHECKSTACK:
|
case PR_CHECKSTACK:
|
||||||
@@ -224,11 +223,11 @@ void DoPragma (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PR_CODESEG:
|
case PR_CODESEG:
|
||||||
SegNamePragma (g_codename);
|
SegNamePragma (SEG_CODE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PR_DATASEG:
|
case PR_DATASEG:
|
||||||
SegNamePragma (g_dataname);
|
SegNamePragma (SEG_DATA);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PR_REGVARADDR:
|
case PR_REGVARADDR:
|
||||||
@@ -236,7 +235,7 @@ void DoPragma (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PR_RODATASEG:
|
case PR_RODATASEG:
|
||||||
SegNamePragma (g_rodataname);
|
SegNamePragma (SEG_RODATA);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PR_SIGNEDCHARS:
|
case PR_SIGNEDCHARS:
|
||||||
|
@@ -6,10 +6,10 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998 Ullrich von Bassewitz */
|
/* (C) 1998-2001 Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Wacholderweg 14 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70597 Stuttgart */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
250
src/cc65/segments.c
Normal file
250
src/cc65/segments.c
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* segments.c */
|
||||||
|
/* */
|
||||||
|
/* Lightweight segment management stuff */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* (C) 2001 Ullrich von Bassewitz */
|
||||||
|
/* Wacholderweg 14 */
|
||||||
|
/* D-70597 Stuttgart */
|
||||||
|
/* EMail: uz@cc65.org */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
/* warranty. In no event will the authors be held liable for any damages */
|
||||||
|
/* arising from the use of this software. */
|
||||||
|
/* */
|
||||||
|
/* Permission is granted to anyone to use this software for any purpose, */
|
||||||
|
/* including commercial applications, and to alter it and redistribute it */
|
||||||
|
/* freely, subject to the following restrictions: */
|
||||||
|
/* */
|
||||||
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||||
|
/* claim that you wrote the original software. If you use this software */
|
||||||
|
/* in a product, an acknowledgment in the product documentation would be */
|
||||||
|
/* appreciated but is not required. */
|
||||||
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||||
|
/* be misrepresented as being the original software. */
|
||||||
|
/* 3. This notice may not be removed or altered from any source */
|
||||||
|
/* distribution. */
|
||||||
|
/* */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* common */
|
||||||
|
#include "chartype.h"
|
||||||
|
#include "check.h"
|
||||||
|
#include "coll.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
/* cc65 */
|
||||||
|
#include "codeseg.h"
|
||||||
|
#include "dataseg.h"
|
||||||
|
#include "segments.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Data */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Pointer to the current segment list. Output goes here. */
|
||||||
|
Segments* CS = 0;
|
||||||
|
|
||||||
|
/* Actual names for the segments */
|
||||||
|
static char* SegmentNames[SEG_COUNT];
|
||||||
|
|
||||||
|
/* We're using a collection for the stack instead of a linked list. Since
|
||||||
|
* functions may not be nested (at least in the current implementation), the
|
||||||
|
* maximum stack depth is 2, so there is not really a need for a better
|
||||||
|
* implementation.
|
||||||
|
*/
|
||||||
|
static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Code */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void InitSegNames (void)
|
||||||
|
/* Initialize the segment names */
|
||||||
|
{
|
||||||
|
SegmentNames [SEG_BSS] = xstrdup ("BSS");
|
||||||
|
SegmentNames [SEG_CODE] = xstrdup ("CODE");
|
||||||
|
SegmentNames [SEG_DATA] = xstrdup ("DATA");
|
||||||
|
SegmentNames [SEG_RODATA] = xstrdup ("RODATA");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void NewSegName (segment_t Seg, const char* Name)
|
||||||
|
/* Set a new name for a segment */
|
||||||
|
{
|
||||||
|
/* Free the old name and set a new one */
|
||||||
|
xfree (SegmentNames [Seg]);
|
||||||
|
SegmentNames [Seg] = xstrdup (Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int ValidSegName (const char* Name)
|
||||||
|
/* Return true if the given segment name is valid, return false otherwise */
|
||||||
|
{
|
||||||
|
/* Must start with '_' or a letter */
|
||||||
|
if ((*Name != '_' && !IsAlpha(*Name)) || strlen(Name) > 80) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can have letters, digits or the underline */
|
||||||
|
while (*++Name) {
|
||||||
|
if (*Name != '_' && !IsAlNum(*Name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Name is ok */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static Segments* NewSegments (SymEntry* Func)
|
||||||
|
/* Initialize a Segments structure (set all fields to NULL) */
|
||||||
|
{
|
||||||
|
/* Allocate memory */
|
||||||
|
Segments* S = xmalloc (sizeof (Segments));
|
||||||
|
|
||||||
|
/* Initialize the fields */
|
||||||
|
S->Code = NewCodeSeg (SegmentNames[SEG_CODE], Func);
|
||||||
|
S->Data = NewDataSeg (SegmentNames[SEG_DATA], Func);
|
||||||
|
S->ROData = NewDataSeg (SegmentNames[SEG_RODATA], Func);
|
||||||
|
S->BSS = NewDataSeg (SegmentNames[SEG_BSS], Func);
|
||||||
|
S->CurDSeg = SEG_DATA;
|
||||||
|
|
||||||
|
/* Return the new struct */
|
||||||
|
return S;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Segments* PushSegments (SymEntry* Func)
|
||||||
|
/* Make the new segment list current but remember the old one */
|
||||||
|
{
|
||||||
|
/* Push the current pointer onto the stack */
|
||||||
|
CollAppend (&SegmentStack, CS);
|
||||||
|
|
||||||
|
/* Create a new Segments structure */
|
||||||
|
CS = NewSegments (Func);
|
||||||
|
|
||||||
|
/* Return the new struct */
|
||||||
|
return CS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void PopSegments (void)
|
||||||
|
/* Pop the old segment list (make it current) */
|
||||||
|
{
|
||||||
|
/* Must have something on the stack */
|
||||||
|
PRECONDITION (CollCount (&SegmentStack) > 0);
|
||||||
|
|
||||||
|
/* Pop the last segment and set it as current */
|
||||||
|
CS = CollPop (&SegmentStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void UseDataSeg (segment_t DSeg)
|
||||||
|
/* For the current segment list, use the data segment DSeg */
|
||||||
|
{
|
||||||
|
/* Check the input */
|
||||||
|
PRECONDITION (CS && DSeg != SEG_CODE);
|
||||||
|
|
||||||
|
/* Set the new segment to use */
|
||||||
|
CS->CurDSeg = DSeg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct DataSeg* GetDataSeg (void)
|
||||||
|
/* Return the current data segment */
|
||||||
|
{
|
||||||
|
PRECONDITION (CS != 0);
|
||||||
|
switch (CS->CurDSeg) {
|
||||||
|
case SEG_BSS: return CS->BSS;
|
||||||
|
case SEG_DATA: return CS->Data;
|
||||||
|
case SEG_RODATA: return CS->ROData;
|
||||||
|
default: FAIL ("Invalid data segment");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void AddCodeLine (const char* Format, ...)
|
||||||
|
/* Add a line of code to the current code segment */
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start (ap, Format);
|
||||||
|
CHECK (CS != 0);
|
||||||
|
AddCodeEntry (CS->Code, Format, ap);
|
||||||
|
va_end (ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void AddDataLine (const char* Format, ...)
|
||||||
|
/* Add a line of data to the current data segment */
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start (ap, Format);
|
||||||
|
CHECK (CS != 0);
|
||||||
|
AddDataEntry (GetDataSeg(), Format, ap);
|
||||||
|
va_end (ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void PrintFunctionHeader (const SymEntry* Entry, FILE* F)
|
||||||
|
{
|
||||||
|
/* Print a comment with the function signature */
|
||||||
|
fprintf (F,
|
||||||
|
"; ---------------------------------------------------------------\n"
|
||||||
|
"; ");
|
||||||
|
PrintFuncSig (F, Entry->Name, Entry->Type);
|
||||||
|
fprintf (F,
|
||||||
|
"\n"
|
||||||
|
"; ---------------------------------------------------------------\n"
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OutputSegments (const Segments* S, FILE* F)
|
||||||
|
/* Output the given segments to the file */
|
||||||
|
{
|
||||||
|
/* If the code segment is associated with a function, print a function header */
|
||||||
|
if (S->Code->Func) {
|
||||||
|
PrintFunctionHeader (S->Code->Func, F);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Output the three data segments */
|
||||||
|
OutputDataSeg (S->Data, F);
|
||||||
|
OutputDataSeg (S->ROData, F);
|
||||||
|
OutputDataSeg (S->BSS, F);
|
||||||
|
|
||||||
|
/* Output the code segment */
|
||||||
|
OutputCodeSeg (S->Code, F);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
132
src/cc65/segments.h
Normal file
132
src/cc65/segments.h
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* segments.h */
|
||||||
|
/* */
|
||||||
|
/* Segment management */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* (C) 2000-2001 Ullrich von Bassewitz */
|
||||||
|
/* Wacholderweg 14 */
|
||||||
|
/* D-70597 Stuttgart */
|
||||||
|
/* EMail: uz@cc65.org */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
/* warranty. In no event will the authors be held liable for any damages */
|
||||||
|
/* arising from the use of this software. */
|
||||||
|
/* */
|
||||||
|
/* Permission is granted to anyone to use this software for any purpose, */
|
||||||
|
/* including commercial applications, and to alter it and redistribute it */
|
||||||
|
/* freely, subject to the following restrictions: */
|
||||||
|
/* */
|
||||||
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||||
|
/* claim that you wrote the original software. If you use this software */
|
||||||
|
/* in a product, an acknowledgment in the product documentation would be */
|
||||||
|
/* appreciated but is not required. */
|
||||||
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||||
|
/* be misrepresented as being the original software. */
|
||||||
|
/* 3. This notice may not be removed or altered from any source */
|
||||||
|
/* distribution. */
|
||||||
|
/* */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SEGMENTS_H
|
||||||
|
#define SEGMENTS_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* common */
|
||||||
|
#include "attrib.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Forwards */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct CodeSeg;
|
||||||
|
struct DataSeg;
|
||||||
|
struct SymEntry;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Data */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Segment types */
|
||||||
|
typedef enum segment_t {
|
||||||
|
SEG_CODE,
|
||||||
|
SEG_RODATA,
|
||||||
|
SEG_DATA,
|
||||||
|
SEG_BSS,
|
||||||
|
SEG_COUNT
|
||||||
|
} segment_t;
|
||||||
|
|
||||||
|
/* A list of all segments used when generating code */
|
||||||
|
typedef struct Segments Segments;
|
||||||
|
struct Segments {
|
||||||
|
struct CodeSeg* Code; /* Code segment */
|
||||||
|
struct DataSeg* Data; /* Data segment */
|
||||||
|
struct DataSeg* ROData; /* Readonly data segment */
|
||||||
|
struct DataSeg* BSS; /* Segment for uninitialized data */
|
||||||
|
segment_t CurDSeg; /* Current data segment */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Pointer to the current segment list. Output goes here. */
|
||||||
|
extern Segments* CS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Code */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void InitSegNames (void);
|
||||||
|
/* Initialize the segment names */
|
||||||
|
|
||||||
|
void NewSegName (segment_t Seg, const char* Name);
|
||||||
|
/* Set a new name for a segment */
|
||||||
|
|
||||||
|
int ValidSegName (const char* Name);
|
||||||
|
/* Return true if the given segment name is valid, return false otherwise */
|
||||||
|
|
||||||
|
Segments* PushSegments (struct SymEntry* Func);
|
||||||
|
/* Make the new segment list current but remember the old one */
|
||||||
|
|
||||||
|
void PopSegments (void);
|
||||||
|
/* Pop the old segment list (make it current) */
|
||||||
|
|
||||||
|
void UseDataSeg (segment_t DSeg);
|
||||||
|
/* For the current segment list, use the data segment DSeg */
|
||||||
|
|
||||||
|
struct DataSeg* GetDataSeg (void);
|
||||||
|
/* Return the current data segment */
|
||||||
|
|
||||||
|
void AddCodeLine (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
||||||
|
/* Add a line of code to the current code segment */
|
||||||
|
|
||||||
|
void AddDataLine (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
||||||
|
/* Add a line of data to the current data segment */
|
||||||
|
|
||||||
|
void OutputSegments (const Segments* S, FILE* F);
|
||||||
|
/* Output the given segments to the file */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* End of segments.h */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@@ -40,27 +40,38 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* cc65 */
|
||||||
#include "datatype.h"
|
#include "datatype.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* struct SymEntry */
|
/* Forwards */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct Segments;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* struct SymEntry */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Storage classes and flags */
|
/* Storage classes and flags */
|
||||||
#define SC_AUTO 0x0001U
|
#define SC_AUTO 0x0001U
|
||||||
#define SC_REGISTER 0x0002U /* Register variable, is in static storage */
|
#define SC_REGISTER 0x0002U /* Register variable, is in static storage */
|
||||||
#define SC_STATIC 0x0004U
|
#define SC_STATIC 0x0004U
|
||||||
#define SC_EXTERN 0x0008U
|
#define SC_EXTERN 0x0008U
|
||||||
|
|
||||||
#define SC_ENUM 0x0030U /* An enum (numeric constant) */
|
#define SC_ENUM 0x0030U /* An enum (numeric constant) */
|
||||||
#define SC_CONST 0x0020U /* A numeric constant with a type */
|
#define SC_CONST 0x0020U /* A numeric constant with a type */
|
||||||
#define SC_LABEL 0x0040U /* A goto label */
|
#define SC_LABEL 0x0040U /* A goto label */
|
||||||
#define SC_PARAM 0x0080U /* This is a function parameter */
|
#define SC_PARAM 0x0080U /* This is a function parameter */
|
||||||
#define SC_FUNC 0x0100U /* Function entry */
|
#define SC_FUNC 0x0100U /* Function entry */
|
||||||
|
|
||||||
#define SC_STORAGE 0x0400U /* Symbol with associated storage */
|
#define SC_STORAGE 0x0400U /* Symbol with associated storage */
|
||||||
#define SC_DEFAULT 0x0800U /* Flag: default storage class was used */
|
#define SC_DEFAULT 0x0800U /* Flag: default storage class was used */
|
||||||
@@ -83,7 +94,7 @@ struct SymEntry {
|
|||||||
SymEntry* NextHash; /* Next entry in hash list */
|
SymEntry* NextHash; /* Next entry in hash list */
|
||||||
SymEntry* PrevSym; /* Previous symbol in dl list */
|
SymEntry* PrevSym; /* Previous symbol in dl list */
|
||||||
SymEntry* NextSym; /* Next symbol double linked list */
|
SymEntry* NextSym; /* Next symbol double linked list */
|
||||||
SymEntry* Link; /* General purpose single linked list */
|
SymEntry* Link; /* General purpose single linked list */
|
||||||
struct SymTable* Owner; /* Symbol table the symbol is in */
|
struct SymTable* Owner; /* Symbol table the symbol is in */
|
||||||
unsigned Flags; /* Symbol flags */
|
unsigned Flags; /* Symbol flags */
|
||||||
type* Type; /* Symbol type */
|
type* Type; /* Symbol type */
|
||||||
@@ -109,18 +120,17 @@ struct SymEntry {
|
|||||||
/* Data for functions */
|
/* Data for functions */
|
||||||
struct {
|
struct {
|
||||||
struct FuncDesc* Func; /* Function descriptor */
|
struct FuncDesc* Func; /* Function descriptor */
|
||||||
struct CodeSeg* CS; /* Code for function */
|
struct Segments* Seg; /* Segments for this function */
|
||||||
struct DataSeg* DS; /* Data segment for function */
|
|
||||||
} F;
|
} F;
|
||||||
|
|
||||||
} V;
|
} V;
|
||||||
char Name[1]; /* Name, dynamically allocated */
|
char Name[1]; /* Name, dynamically allocated */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
@@ -744,8 +744,7 @@ SymEntry* AddGlobalSym (const char* Name, const type* Type, unsigned Flags)
|
|||||||
*/
|
*/
|
||||||
if (IsFunc) {
|
if (IsFunc) {
|
||||||
Entry->V.F.Func = GetFuncDesc (Entry->Type);
|
Entry->V.F.Func = GetFuncDesc (Entry->Type);
|
||||||
Entry->V.F.CS = 0;
|
Entry->V.F.Seg = 0;
|
||||||
Entry->V.F.DS = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the entry to the symbol table */
|
/* Add the entry to the symbol table */
|
||||||
|
Reference in New Issue
Block a user