mirror of
https://github.com/cc65/cc65.git
synced 2025-01-11 11:30:13 +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:
parent
e8174aaa25
commit
e6484f85c7
@ -40,6 +40,7 @@
|
||||
#include "codeopt.h"
|
||||
#include "codeseg.h"
|
||||
#include "dataseg.h"
|
||||
#include "segments.h"
|
||||
#include "symtab.h"
|
||||
#include "asmcode.h"
|
||||
|
||||
@ -62,7 +63,7 @@ void AddCodeHint (const char* Hint)
|
||||
CodeMark GetCodePos (void)
|
||||
/* 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)
|
||||
/* Remove all code after the given code marker */
|
||||
{
|
||||
DelCodeSegAfter (CS, 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");
|
||||
DelCodeSegAfter (CS->Code, M);
|
||||
}
|
||||
|
||||
|
||||
@ -96,9 +82,9 @@ void WriteOutput (FILE* F)
|
||||
SymTable* SymTab;
|
||||
SymEntry* Entry;
|
||||
|
||||
/* Output the data segment (the global code segment should be empty) */
|
||||
OutputDataSeg (F, DS);
|
||||
CHECK (GetCodeSegEntries (CS) == 0);
|
||||
/* Output the global data segment */
|
||||
CHECK (GetCodeSegEntries (CS->Code) == 0);
|
||||
OutputSegments (CS, F);
|
||||
|
||||
/* Output all global or referenced functions */
|
||||
SymTab = GetGlobalSymTab ();
|
||||
@ -108,13 +94,9 @@ void WriteOutput (FILE* F)
|
||||
(Entry->Flags & SC_DEF) != 0 &&
|
||||
(Entry->Flags & (SC_REF | SC_EXTERN)) != 0) {
|
||||
/* Function which is defined and referenced or extern */
|
||||
PrintFunctionHeader (F, Entry);
|
||||
MergeCodeLabels (Entry->V.F.CS);
|
||||
RunOpt (Entry->V.F.CS);
|
||||
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);
|
||||
MergeCodeLabels (Entry->V.F.Seg->Code);
|
||||
RunOpt (Entry->V.F.Seg->Code);
|
||||
OutputSegments (Entry->V.F.Seg, F);
|
||||
}
|
||||
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 */
|
||||
{
|
||||
const OPCDesc* D;
|
||||
@ -129,7 +129,7 @@ void OutputCodeEntry (FILE* F, const CodeEntry* E)
|
||||
unsigned LabelCount = CollCount (&E->Labels);
|
||||
unsigned I;
|
||||
for (I = 0; I < LabelCount; ++I) {
|
||||
OutputCodeLabel (F, CollConstAt (&E->Labels, I));
|
||||
OutputCodeLabel (CollConstAt (&E->Labels, I), F);
|
||||
}
|
||||
|
||||
/* Get the opcode description */
|
||||
|
@ -91,7 +91,7 @@ void FreeCodeEntry (CodeEntry* E);
|
||||
int CodeEntryHasLabel (const CodeEntry* E);
|
||||
/* 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 */
|
||||
|
||||
|
||||
|
1510
src/cc65/codegen.c
1510
src/cc65/codegen.c
File diff suppressed because it is too large
Load Diff
@ -38,14 +38,8 @@
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Forwards */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
struct CodeSeg;
|
||||
struct DataSeg;
|
||||
/* cc65 */
|
||||
#include "segments.h"
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
/* Switch to the read only data segment */
|
||||
|
||||
@ -124,18 +112,6 @@ void g_usedata (void);
|
||||
void g_usebss (void);
|
||||
/* 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 */
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* cc65 */
|
||||
/* cc65 */
|
||||
#include "codeent.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 */
|
||||
{
|
||||
fprintf (F, "%s:", L->Name);
|
||||
|
@ -95,7 +95,7 @@ void AddLabelRef (CodeLabel* L, struct CodeEntry* E);
|
||||
unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E);
|
||||
/* 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 */
|
||||
|
||||
|
||||
|
@ -88,7 +88,7 @@ static void OptDeadJumps (CodeSeg* S)
|
||||
if (E->AM == AM_BRA && E->JumpTo && E->JumpTo->Owner == CollAt (&S->Entries, I+1)) {
|
||||
|
||||
/* Delete the dead jump */
|
||||
DelCodeSegLine (S, I);
|
||||
DelCodeEntry (S, I);
|
||||
|
||||
/* Keep the number of entries updated */
|
||||
--Count;
|
||||
@ -140,7 +140,7 @@ static void OptDeadCode (CodeSeg* S)
|
||||
!CodeEntryHasLabel (CollAt (&S->Entries, I+1))) {
|
||||
|
||||
/* Delete the next entry */
|
||||
DelCodeSegLine (S, I+1);
|
||||
DelCodeEntry (S, I+1);
|
||||
|
||||
/* Keep the number of entries updated */
|
||||
--Count;
|
||||
|
@ -52,17 +52,6 @@
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Pointer to current code segment */
|
||||
CodeSeg* CS = 0;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* 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 */
|
||||
{
|
||||
unsigned I;
|
||||
@ -318,9 +307,8 @@ CodeSeg* NewCodeSeg (const char* SegName, const char* FuncName)
|
||||
CodeSeg* S = xmalloc (sizeof (CodeSeg));
|
||||
|
||||
/* Initialize the fields */
|
||||
S->Next = 0;
|
||||
S->SegName = xstrdup (SegName);
|
||||
S->FuncName = xstrdup (FuncName);
|
||||
S->Func = Func;
|
||||
InitCollection (&S->Entries);
|
||||
InitCollection (&S->Labels);
|
||||
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)
|
||||
/* Free a code segment including all code entries */
|
||||
{
|
||||
FAIL ("Not implemented");
|
||||
Internal ("Not implemented");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PushCodeSeg (CodeSeg* S)
|
||||
/* 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, ...)
|
||||
void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap)
|
||||
/* Add a line to the given code segment */
|
||||
{
|
||||
const char* L;
|
||||
@ -376,11 +337,8 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...)
|
||||
char Token[64];
|
||||
|
||||
/* Format the line */
|
||||
va_list ap;
|
||||
char Buf [256];
|
||||
va_start (ap, Format);
|
||||
xvsprintf (Buf, sizeof (Buf), Format, ap);
|
||||
va_end (ap);
|
||||
|
||||
/* Skip whitespace */
|
||||
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
|
||||
* labels, removing references to labels and even removing the referenced labels
|
||||
* 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 */
|
||||
{
|
||||
unsigned I;
|
||||
@ -600,31 +558,26 @@ void OutputCodeSeg (FILE* F, const CodeSeg* S)
|
||||
/* Get the number of entries in this segment */
|
||||
unsigned Count = CollCount (&S->Entries);
|
||||
|
||||
fprintf (F, "; Labels: ");
|
||||
for (I = 0; I < CS_LABEL_HASH_SIZE; ++I) {
|
||||
const CodeLabel* L = S->LabelHash[I];
|
||||
while (L) {
|
||||
fprintf (F, "%s ", L->Name);
|
||||
L = L->Next;
|
||||
}
|
||||
/* If the code segment is empty, bail out here */
|
||||
if (Count == 0) {
|
||||
return;
|
||||
}
|
||||
fprintf (F, "\n");
|
||||
|
||||
/* Output the segment directive */
|
||||
fprintf (F, ".segment\t\"%s\"\n\n", S->SegName);
|
||||
|
||||
/* If this is a segment for a function, enter a function */
|
||||
if (S->FuncName[0] != '\0') {
|
||||
fprintf (F, ".proc\t_%s\n\n", S->FuncName);
|
||||
if (S->Func) {
|
||||
fprintf (F, ".proc\t_%s\n\n", S->Func->Name);
|
||||
}
|
||||
|
||||
/* Output all entries */
|
||||
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 (S->FuncName[0] != '\0') {
|
||||
if (S->Func) {
|
||||
fprintf (F, "\n.endproc\n\n");
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,8 @@
|
||||
#define CODESEG_H
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* common */
|
||||
@ -46,11 +47,12 @@
|
||||
|
||||
/* cc65 */
|
||||
#include "codelab.h"
|
||||
#include "symentry.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -61,41 +63,31 @@
|
||||
/* Code segment structure */
|
||||
typedef struct CodeSeg CodeSeg;
|
||||
struct CodeSeg {
|
||||
CodeSeg* Next; /* Pointer to next CodeSeg */
|
||||
char* SegName; /* Segment name */
|
||||
char* FuncName; /* Name of function */
|
||||
SymEntry* Func; /* Owner function */
|
||||
Collection Entries; /* List of code entries */
|
||||
Collection Labels; /* Labels for next insn */
|
||||
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 */
|
||||
|
||||
void FreeCodeSeg (CodeSeg* S);
|
||||
/* Free a code segment including all code entries */
|
||||
|
||||
void PushCodeSeg (CodeSeg* S);
|
||||
/* 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)));
|
||||
void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap) attribute ((format(printf,2,0)));
|
||||
/* 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
|
||||
* labels, removing references to labels and even removing the referenced labels
|
||||
* if the reference count drops to zero.
|
||||
@ -113,7 +105,7 @@ void AddCodeSegHint (CodeSeg* S, unsigned Hint);
|
||||
void DelCodeSegAfter (CodeSeg* S, unsigned Last);
|
||||
/* 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 */
|
||||
|
||||
CodeLabel* FindCodeLabel (CodeSeg* S, const char* Name, unsigned Hash);
|
||||
|
@ -39,36 +39,26 @@
|
||||
#include "xsprintf.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "error.h"
|
||||
#include "dataseg.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Pointer to current data segment */
|
||||
DataSeg* DS = 0;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
DataSeg* NewDataSeg (const char* Name)
|
||||
DataSeg* NewDataSeg (const char* Name, SymEntry* Func)
|
||||
/* Create a new data segment, initialize and return it */
|
||||
{
|
||||
/* Allocate memory */
|
||||
DataSeg* S = xmalloc (sizeof (DataSeg));
|
||||
DataSeg* S = xmalloc (sizeof (DataSeg));
|
||||
|
||||
/* Initialize the fields */
|
||||
S->Next = 0;
|
||||
S->Name = xstrdup (Name);
|
||||
S->SegName = xstrdup (Name);
|
||||
S->Func = Func;
|
||||
InitCollection (&S->Lines);
|
||||
|
||||
/* Return the new struct */
|
||||
@ -80,50 +70,7 @@ DataSeg* NewDataSeg (const char* Name)
|
||||
void FreeDataSeg (DataSeg* S)
|
||||
/* Free a data segment including all line entries */
|
||||
{
|
||||
unsigned I, Count;
|
||||
|
||||
/* 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;
|
||||
Internal ("Not implemented");
|
||||
}
|
||||
|
||||
|
||||
@ -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 */
|
||||
{
|
||||
va_list ap;
|
||||
char Buf [256];
|
||||
|
||||
/* Format the line */
|
||||
va_start (ap, Format);
|
||||
char Buf [256];
|
||||
xvsprintf (Buf, sizeof (Buf), Format, ap);
|
||||
va_end (ap);
|
||||
|
||||
/* Add a copy to the data segment */
|
||||
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 */
|
||||
{
|
||||
unsigned I;
|
||||
@ -167,10 +110,21 @@ void OutputDataSeg (FILE* F, const DataSeg* S)
|
||||
/* Get the number of entries in this segment */
|
||||
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 */
|
||||
for (I = 0; I < Count; ++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>
|
||||
|
||||
/* common */
|
||||
#include "attrib.h"
|
||||
#include "coll.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "symentry.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
typedef struct DataSeg DataSeg;
|
||||
struct DataSeg {
|
||||
DataSeg* Next; /* Pointer to next DataSeg */
|
||||
char* Name; /* Segment name */
|
||||
char* SegName; /* Segment name */
|
||||
SymEntry* Func; /* Owner function */
|
||||
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 */
|
||||
|
||||
void FreeDataSeg (DataSeg* S);
|
||||
/* 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);
|
||||
/* 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 */
|
||||
|
||||
void OutputDataSeg (FILE* F, const DataSeg* S);
|
||||
void OutputDataSeg (const DataSeg* S, FILE* F);
|
||||
/* Output the data segment data to a file */
|
||||
|
||||
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "litpool.h"
|
||||
#include "locals.h"
|
||||
#include "scanner.h"
|
||||
#include "segments.h"
|
||||
#include "stmt.h"
|
||||
#include "symtab.h"
|
||||
#include "function.h"
|
||||
@ -246,7 +247,7 @@ void NewFunc (SymEntry* Func)
|
||||
InitRegVars ();
|
||||
|
||||
/* 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 (IsFastCallFunc (Func->Type) && D->ParamCount > 0) {
|
||||
@ -336,7 +337,7 @@ void NewFunc (SymEntry* Func)
|
||||
LeaveFunctionLevel ();
|
||||
|
||||
/* Switch back to the old segments */
|
||||
g_popseg ();
|
||||
PopSegments ();
|
||||
|
||||
/* Reset the current function pointer */
|
||||
FreeFunction (CurrentFunc);
|
||||
|
@ -59,7 +59,7 @@
|
||||
#include "input.h"
|
||||
#include "macrotab.h"
|
||||
#include "scanner.h"
|
||||
#include "segname.h"
|
||||
#include "segments.h"
|
||||
|
||||
|
||||
|
||||
|
@ -56,14 +56,14 @@ OBJS = anonname.o \
|
||||
opcodes.o \
|
||||
preproc.o \
|
||||
pragma.o \
|
||||
scanner.o \
|
||||
segname.o \
|
||||
stdfunc.o \
|
||||
stmt.o \
|
||||
symentry.o \
|
||||
symtab.o \
|
||||
typecmp.o \
|
||||
util.o
|
||||
scanner.o \
|
||||
segments.o \
|
||||
stdfunc.o \
|
||||
stmt.o \
|
||||
symentry.o \
|
||||
symtab.o \
|
||||
typecmp.o \
|
||||
util.o
|
||||
|
||||
LIBS = $(COMMON)/common.a
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2000 Ullrich von Bassewitz */
|
||||
/* (C) 1998-2001 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -37,13 +37,12 @@
|
||||
#include <string.h>
|
||||
|
||||
/* cc65 */
|
||||
#include "codegen.h"
|
||||
#include "error.h"
|
||||
#include "expr.h"
|
||||
#include "global.h"
|
||||
#include "litpool.h"
|
||||
#include "scanner.h"
|
||||
#include "segname.h"
|
||||
#include "segments.h"
|
||||
#include "symtab.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 */
|
||||
{
|
||||
if (curtok != TOK_SCONST) {
|
||||
@ -150,8 +149,8 @@ static void SegNamePragma (void (*Func) (const char*))
|
||||
/* Check if the name is valid */
|
||||
if (ValidSegName (Name)) {
|
||||
|
||||
/* Call the given function to set the name */
|
||||
Func (Name);
|
||||
/* Set the new name */
|
||||
NewSegName (Seg, Name);
|
||||
|
||||
} else {
|
||||
|
||||
@ -216,7 +215,7 @@ void DoPragma (void)
|
||||
switch (Pragma) {
|
||||
|
||||
case PR_BSSSEG:
|
||||
SegNamePragma (g_bssname);
|
||||
SegNamePragma (SEG_BSS);
|
||||
break;
|
||||
|
||||
case PR_CHECKSTACK:
|
||||
@ -224,11 +223,11 @@ void DoPragma (void)
|
||||
break;
|
||||
|
||||
case PR_CODESEG:
|
||||
SegNamePragma (g_codename);
|
||||
SegNamePragma (SEG_CODE);
|
||||
break;
|
||||
|
||||
case PR_DATASEG:
|
||||
SegNamePragma (g_dataname);
|
||||
SegNamePragma (SEG_DATA);
|
||||
break;
|
||||
|
||||
case PR_REGVARADDR:
|
||||
@ -236,7 +235,7 @@ void DoPragma (void)
|
||||
break;
|
||||
|
||||
case PR_RODATASEG:
|
||||
SegNamePragma (g_rodataname);
|
||||
SegNamePragma (SEG_RODATA);
|
||||
break;
|
||||
|
||||
case PR_SIGNEDCHARS:
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2001 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* 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>
|
||||
|
||||
/* cc65 */
|
||||
#include "datatype.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* struct SymEntry */
|
||||
/* Forwards */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
struct Segments;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* struct SymEntry */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Storage classes and flags */
|
||||
#define SC_AUTO 0x0001U
|
||||
#define SC_AUTO 0x0001U
|
||||
#define SC_REGISTER 0x0002U /* Register variable, is in static storage */
|
||||
#define SC_STATIC 0x0004U
|
||||
#define SC_EXTERN 0x0008U
|
||||
|
||||
#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_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_DEFAULT 0x0800U /* Flag: default storage class was used */
|
||||
@ -83,7 +94,7 @@ struct SymEntry {
|
||||
SymEntry* NextHash; /* Next entry in hash list */
|
||||
SymEntry* PrevSym; /* Previous symbol in dl 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 */
|
||||
unsigned Flags; /* Symbol flags */
|
||||
type* Type; /* Symbol type */
|
||||
@ -109,18 +120,17 @@ struct SymEntry {
|
||||
/* Data for functions */
|
||||
struct {
|
||||
struct FuncDesc* Func; /* Function descriptor */
|
||||
struct CodeSeg* CS; /* Code for function */
|
||||
struct DataSeg* DS; /* Data segment for function */
|
||||
struct Segments* Seg; /* Segments for this function */
|
||||
} F;
|
||||
|
||||
} 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) {
|
||||
Entry->V.F.Func = GetFuncDesc (Entry->Type);
|
||||
Entry->V.F.CS = 0;
|
||||
Entry->V.F.DS = 0;
|
||||
Entry->V.F.Seg = 0;
|
||||
}
|
||||
|
||||
/* Add the entry to the symbol table */
|
||||
|
Loading…
x
Reference in New Issue
Block a user