#include "dataseg.h"
/* cc65 */
+#include "symtab.h"
#include "asmcode.h"
+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");
+}
+
+
+
void WriteOutput (FILE* F)
/* Write the final output to a file */
{
- OutputDataSeg (F, DS);
+ SymTable* SymTab;
+ SymEntry* Entry;
+
+ /* Output the global code and data segments */
MergeCodeLabels (CS);
+ OutputDataSeg (F, DS);
OutputCodeSeg (F, CS);
+
+ /* Output all global or referenced functions */
+ SymTab = GetGlobalSymTab ();
+ Entry = SymTab->SymHead;
+ while (Entry) {
+ if (IsTypeFunc (Entry->Type) &&
+ (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);
+ OutputDataSeg (F, Entry->V.F.DS);
+ OutputCodeSeg (F, Entry->V.F.CS);
+ }
+ Entry = Entry->NextSym;
+ }
}
/* (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 */
/* Generate the assembler code preamble */
{
/* Generate the global segments and push them */
- PushCodeSeg (NewCodeSeg (""));
+ PushCodeSeg (NewCodeSeg (SegmentNames[SEG_CODE], ""));
PushDataSeg (NewDataSeg (""));
-
+
/* Identify the compiler version */
AddDataSegLine (DS, "; File generated by cc65 v %u.%u.%u",
VER_MAJOR, VER_MINOR, VER_PATCH);
+void g_pushseg (struct CodeSeg** FCS, struct DataSeg** FDS, const char* FuncName)
+/* Push the current segments and generate new ones for the given function */
+{
+ PushCodeSeg (NewCodeSeg (SegmentNames[SEG_CODE], FuncName));
+ *FCS = CS;
+ PushDataSeg (NewDataSeg (FuncName));
+ *FDS = DS;
+}
+
+
+
+void g_popseg (void)
+/* Restore the old segments */
+{
+ PopCodeSeg ();
+ PopDataSeg ();
+}
+
+
+
void g_usecode (void)
/* Switch to the code segment */
{
} while (Chunk);
/* Output the line */
- AddCodeSegLine (CS, Buf);
+ AddDataSegLine (DS, Buf);
}
}
/*****************************************************************************/
-/* data */
+/* Forwards */
+/*****************************************************************************/
+
+
+
+struct CodeSeg;
+struct DataSeg;
+
+
+
+/*****************************************************************************/
+/* Data */
/*****************************************************************************/
+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_usecode (void);
/* Switch to the code segment */
-CodeSeg* NewCodeSeg (const char* Name)
+CodeSeg* NewCodeSeg (const char* SegName, const char* FuncName)
/* Create a new code segment, initialize and return it */
{
unsigned I;
CodeSeg* S = xmalloc (sizeof (CodeSeg));
/* Initialize the fields */
- S->Next = 0;
- S->Name = xstrdup (Name);
+ S->Next = 0;
+ S->SegName = xstrdup (SegName);
+ S->FuncName = xstrdup (FuncName);
InitCollection (&S->Entries);
InitCollection (&S->Labels);
for (I = 0; I < sizeof(S->LabelHash) / sizeof(S->LabelHash[0]); ++I) {
{
unsigned I, Count;
- /* Free the name */
- xfree (S->Name);
+ /* Free the names */
+ xfree (S->SegName);
+ xfree (S->FuncName);
/* Free the entries */
Count = CollCount (&S->Entries);
unsigned Count = CollCount (&S->Entries);
/* Output the segment directive */
- fprintf (F, ".segment\t\"%s\"\n", S->Name);
+ 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);
+ }
/* Output all entries */
for (I = 0; I < Count; ++I) {
OutputCodeEntry (F, CollConstAt (&S->Entries, I));
}
+
+ /* If this is a segment for a function, leave the function */
+ if (S->FuncName[0] != '\0') {
+ fprintf (F, "\n.endproc\n\n");
+ }
}
typedef struct CodeSeg CodeSeg;
struct CodeSeg {
CodeSeg* Next; /* Pointer to next CodeSeg */
- char* Name; /* Segment name */
+ char* SegName; /* Segment name */
+ char* FuncName; /* Name of function */
Collection Entries; /* List of code entries */
Collection Labels; /* Labels for next insn */
CodeLabel* LabelHash [CS_LABEL_HASH_SIZE]; /* Label hash table */
-CodeSeg* NewCodeSeg (const char* Name);
+CodeSeg* NewCodeSeg (const char* SegName, const char* FuncName);
/* Create a new code segment, initialize and return it */
void FreeCodeSeg (CodeSeg* S);
/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (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 */
/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (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 */
T = PrintTypeComp (F, T, T_QUAL_CONST, "const");
T = PrintTypeComp (F, T, T_QUAL_VOLATILE, "volatile");
- /* Signedness */
- T = PrintTypeComp (F, T, T_SIGN_SIGNED, "signed");
+ /* Signedness. Omit the signedness specifier for long and int */
+ if ((T & T_MASK_TYPE) != T_TYPE_INT && (T & T_MASK_TYPE) != T_TYPE_LONG) {
+ T = PrintTypeComp (F, T, T_SIGN_SIGNED, "signed");
+ }
T = PrintTypeComp (F, T, T_SIGN_UNSIGNED, "unsigned");
/* Now check the real type */
switch (T & T_MASK_TYPE) {
case T_TYPE_CHAR:
- fprintf (F, "char\n");
+ fprintf (F, "char");
break;
case T_TYPE_SHORT:
- fprintf (F, "short\n");
+ fprintf (F, "short");
break;
case T_TYPE_INT:
- fprintf (F, "int\n");
+ fprintf (F, "int");
break;
case T_TYPE_LONG:
- fprintf (F, "long\n");
+ fprintf (F, "long");
break;
case T_TYPE_LONGLONG:
- fprintf (F, "long long\n");
+ fprintf (F, "long long");
break;
case T_TYPE_FLOAT:
- fprintf (F, "float\n");
+ fprintf (F, "float");
break;
case T_TYPE_DOUBLE:
- fprintf (F, "double\n");
+ fprintf (F, "double");
break;
case T_TYPE_VOID:
- fprintf (F, "void\n");
+ fprintf (F, "void");
break;
case T_TYPE_STRUCT:
- fprintf (F, "struct %s\n", ((SymEntry*) DecodePtr (Type))->Name);
+ fprintf (F, "struct %s", ((SymEntry*) DecodePtr (Type))->Name);
Type += DECODE_SIZE;
break;
case T_TYPE_UNION:
- fprintf (F, "union %s\n", ((SymEntry*) DecodePtr (Type))->Name);
+ fprintf (F, "union %s", ((SymEntry*) DecodePtr (Type))->Name);
Type += DECODE_SIZE;
break;
case T_TYPE_ARRAY:
Type += DECODE_SIZE;
break;
default:
- fprintf (F, "unknown type: %04X\n", T);
+ fprintf (F, "unknown type: %04X", T);
}
}
+void PrintFuncSig (FILE* F, const char* Name, type* Type)
+/* Print a function signature. */
+{
+ /* Get the function descriptor */
+ const FuncDesc* D = GetFuncDesc (Type);
+
+ /* Print a comment with the function signature */
+ PrintType (F, GetFuncReturn (Type));
+ if (D->Flags & FD_FASTCALL) {
+ fprintf (F, " __fastcall__");
+ }
+ fprintf (F, " %s (", Name);
+
+ /* Parameters */
+ if (D->Flags & FD_VOID_PARAM) {
+ fprintf (F, "void");
+ } else {
+ unsigned I;
+ SymEntry* E = D->SymTab->SymHead;
+ for (I = 0; I < D->ParamCount; ++I) {
+ if (I > 0) {
+ fprintf (F, ", ");
+ }
+ PrintType (F, E->Type);
+ E = E->NextSym;
+ }
+ }
+
+ /* End of parameter list */
+ fprintf (F, ")");
+}
+
+
+
void PrintRawType (FILE* F, const type* Type)
/* Print a type string in raw format (for debugging) */
{
+type* GetFuncReturn (type* T)
+/* Return a pointer to the return type of a function or pointer-to-function type */
+{
+ if (T[0] == T_PTR) {
+ /* Pointer to function */
+ ++T;
+ }
+
+ /* Be sure it's a function type */
+ CHECK (T[0] == T_FUNC);
+
+ /* Return a pointer to the return type */
+ return T + 1 + DECODE_SIZE;
+
+}
+
+
void PrintRawType (FILE* F, const type* Type);
/* Print a type string in raw format (for debugging) */
+void PrintFuncSig (FILE* F, const char* Name, type* Type);
+/* Print a function signature. */
+
void Encode (type* Type, unsigned long Val);
/* Encode an unsigned long into a type array */
FuncDesc* GetFuncDesc (const type* T) attribute ((const));
/* Get the FuncDesc pointer from a function or pointer-to-function type */
+type* GetFuncReturn (type* T) attribute ((const));
+/* Return a pointer to the return type of a function or pointer-to-function type */
+
/* End of datatype.h */
/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (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 */
/* Structure that holds all data needed for function activation */
struct Function {
struct SymEntry* FuncEntry; /* Symbol table entry */
- type* ReturnType; /* Function return type */
+ type* ReturnType; /* Function return type */
struct FuncDesc* Desc; /* Function descriptor */
int Reserved; /* Reserved local space */
unsigned RetLab; /* Return code label */
/* Initialize the fields */
F->FuncEntry = Sym;
- F->ReturnType = Sym->Type + 1 + DECODE_SIZE;
+ F->ReturnType = GetFuncReturn (Sym->Type);
F->Desc = (FuncDesc*) DecodePtr (Sym->Type + 1);
F->Reserved = 0;
F->RetLab = GetLocalLabel ();
unsigned Flags;
/* Get the function descriptor from the function entry */
- FuncDesc* D = (FuncDesc*) DecodePtr (Func->Type+1);
+ FuncDesc* D = Func->V.F.Func;
/* Allocate the function activation record for the function */
CurrentFunc = NewFunction (Func);
/* Setup register variables */
InitRegVars ();
- /* Switch to the code segment and define the function name label */
- g_usecode ();
- g_defgloblabel (Func->Name);
+ /* Allocate code and data segments for this function */
+ g_pushseg (&Func->V.F.CS, &Func->V.F.DS, Func->Name);
/* If this is a fastcall function, push the last parameter onto the stack */
if (IsFastCallFunc (Func->Type) && D->ParamCount > 0) {
/* Leave the lexical level */
LeaveFunctionLevel ();
+ /* Switch back to the old segments */
+ g_popseg ();
+
/* Reset the current function pointer */
FreeFunction (CurrentFunc);
CurrentFunc = 0;
-
/* (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 */
/* (C) 2000-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 */
/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (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 */
#include "incpath.h"
#include "input.h"
#include "macrotab.h"
-/* #include "optimize.h" */
#include "scanner.h"
#include "segname.h"
Optimize = 1;
P = Arg + 2;
while (*P) {
- switch (*P++) {
+ switch (*P++) {
#if 0
case 'f':
sscanf (P, "%lx", (long*) &OptDisable);
/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (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 */
if (E->Type) {
PrintType (F, E->Type);
} else {
- fprintf (F, "(none)\n");
+ fprintf (F, "(none)");
}
+ fprintf (F, "\n");
}
/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (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 */
} S;
/* Data for functions */
- struct FuncDesc* Func; /* Function descriptor */
+ struct {
+ struct FuncDesc* Func; /* Function descriptor */
+ struct CodeSeg* CS; /* Code for function */
+ struct DataSeg* DS; /* Data segment for function */
+ } F;
} V;
char Name[1]; /* Name, dynamically allocated */
/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (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 */
/* Dump the tables if requested */
if (Debug) {
- PrintSymTable (SymTab0, stdout, "Global symbol table");
- PrintSymTable (TagTab0, stdout, "Global tag table");
+ PrintSymTable (SymTab0, stdout, "Global symbol table");
+ PrintSymTable (TagTab0, stdout, "Global tag table");
}
/* Don't delete the symbol and struct tables! */
- SymTab0 = SymTab = 0;
- TagTab0 = TagTab = 0;
+ SymTab = 0;
+ TagTab = 0;
}
SymEntry* AddGlobalSym (const char* Name, const type* Type, unsigned Flags)
/* Add an external or global symbol to the symbol table and return the entry */
{
+ /* There is some special handling for functions, so check if it is one */
+ int IsFunc = IsTypeFunc (Type);
+
/* Functions must be inserted in the global symbol table */
- SymTable* Tab = IsTypeFunc (Type)? SymTab0 : SymTab;
+ SymTable* Tab = IsFunc? SymTab0 : SymTab;
/* Do we have an entry with this name already? */
SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
* contains pointers to the new symbol tables that are needed if
* an actual function definition follows.
*/
- if (IsTypeFunc (Type)) {
- CopyEncode (Type+1, EType+1);
+ if (IsFunc) {
+ /* Get the function descriptor from the new type */
+ FuncDesc* F = GetFuncDesc (Type);
+ /* Use this new function descriptor */
+ Entry->V.F.Func = F;
+ EncodePtr (EType+1, F);
}
}
/* Set the symbol attributes */
Entry->Type = TypeDup (Type);
+ /* If this is a function, set the function descriptor and clear
+ * additional fields.
+ */
+ if (IsFunc) {
+ Entry->V.F.Func = GetFuncDesc (Entry->Type);
+ Entry->V.F.CS = 0;
+ Entry->V.F.DS = 0;
+ }
+
/* Add the entry to the symbol table */
AddSymEntry (Tab, Entry);
}
+SymTable* GetGlobalSymTab (void)
+/* Return the global symbol table */
+{
+ return SymTab0;
+}
+
+
+
int SymIsLocal (SymEntry* Sym)
/* Return true if the symbol is defined in the highest lexical level */
{
SymTable* GetSymTab (void);
/* Return the current symbol table */
+SymTable* GetGlobalSymTab (void);
+/* Return the global symbol table */
+
int SymIsLocal (SymEntry* Sym);
/* Return true if the symbol is defined in the highest lexical level */