1
0
mirror of https://github.com/cc65/cc65.git synced 2025-01-10 19:29:45 +00:00

Reenable register variables

git-svn-id: svn://svn.cc65.org/cc65/trunk@1625 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2002-11-24 23:31:54 +00:00
parent b6898c3f1e
commit ede471904c
15 changed files with 380 additions and 88 deletions

View File

@ -93,7 +93,7 @@ void WriteOutput (FILE* F)
Entry = SymTab->SymHead; Entry = SymTab->SymHead;
while (Entry) { while (Entry) {
if (IsTypeFunc (Entry->Type) && if (IsTypeFunc (Entry->Type) &&
(Entry->Flags & SC_DEF) != 0 && SymIsDef (Entry) &&
(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 */
CS_MergeLabels (Entry->V.F.Seg->Code); CS_MergeLabels (Entry->V.F.Seg->Code);

View File

@ -3981,6 +3981,21 @@ void g_zerobytes (unsigned n)
void g_initregister (unsigned Label, unsigned Reg, unsigned Size)
/* Initialize a register variable from static initialization data */
{
/* Register variables do always have less than 128 bytes */
unsigned CodeLabel = GetLocalLabel ();
ldxconst (Size-1);
g_defcodelabel (CodeLabel);
AddCodeLine ("lda %s,x", GetLabelName (CF_STATIC, Label, 0));
AddCodeLine ("sta %s,x", GetLabelName (CF_REGVAR, Reg, 0));
AddCodeLine ("dex");
AddCodeLine ("bpl %s", LocalLabelName (CodeLabel));
}
void g_initauto (unsigned Label, unsigned Size) void g_initauto (unsigned Label, unsigned Size)
/* Initialize a local variable at stack offset zero from static data */ /* Initialize a local variable at stack offset zero from static data */
{ {

View File

@ -432,6 +432,9 @@ void g_defbytes (const void* bytes, unsigned count);
void g_zerobytes (unsigned n); void g_zerobytes (unsigned n);
/* Output n bytes of data initialized with zero */ /* Output n bytes of data initialized with zero */
void g_initregister (unsigned Label, unsigned Reg, unsigned Size);
/* Initialize a register variable from static initialization data */
void g_initauto (unsigned Label, unsigned Size); void g_initauto (unsigned Label, unsigned Size);
/* Initialize a local variable at stack offset zero from static data */ /* Initialize a local variable at stack offset zero from static data */

View File

@ -1391,7 +1391,8 @@ static OptFunc DOpt65C02Ind = { Opt65C02Ind, "Opt65C02Ind", 100, 0,
static OptFunc DOpt65C02Stores = { Opt65C02Stores, "Opt65C02Stores", 100, 0, 0, 0, 0, 0 }; static OptFunc DOpt65C02Stores = { Opt65C02Stores, "Opt65C02Stores", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd1 = { OptAdd1, "OptAdd1", 125, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd1 = { OptAdd1, "OptAdd1", 125, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd2 = { OptAdd2, "OptAdd2", 200, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd2 = { OptAdd2, "OptAdd2", 200, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd3 = { OptAdd3, "OptAdd3", 40, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd3 = { OptAdd3, "OptAdd3", 90, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd4 = { OptAdd4, "OptAdd4", 40, 0, 0, 0, 0, 0 };
static OptFunc DOptBoolTrans = { OptBoolTrans, "OptBoolTrans", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptBoolTrans = { OptBoolTrans, "OptBoolTrans", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptBranchDist = { OptBranchDist, "OptBranchDist", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptBranchDist = { OptBranchDist, "OptBranchDist", 0, 0, 0, 0, 0, 0 };
static OptFunc DOptCmp1 = { OptCmp1, "OptCmp1", 85, 0, 0, 0, 0, 0 }; static OptFunc DOptCmp1 = { OptCmp1, "OptCmp1", 85, 0, 0, 0, 0, 0 };
@ -1454,6 +1455,7 @@ static OptFunc* OptFuncs[] = {
&DOptAdd1, &DOptAdd1,
&DOptAdd2, &DOptAdd2,
&DOptAdd3, &DOptAdd3,
&DOptAdd4,
&DOptBoolTrans, &DOptBoolTrans,
&DOptBranchDist, &DOptBranchDist,
&DOptCmp1, &DOptCmp1,
@ -1752,6 +1754,7 @@ static unsigned RunOptGroup1 (CodeSeg* S)
Changes += RunOptFunc (S, &DOptNegAX4, 1); Changes += RunOptFunc (S, &DOptNegAX4, 1);
Changes += RunOptFunc (S, &DOptAdd1, 1); Changes += RunOptFunc (S, &DOptAdd1, 1);
Changes += RunOptFunc (S, &DOptAdd2, 1); Changes += RunOptFunc (S, &DOptAdd2, 1);
Changes += RunOptFunc (S, &DOptAdd3, 1);
Changes += RunOptFunc (S, &DOptShift1, 1); Changes += RunOptFunc (S, &DOptShift1, 1);
Changes += RunOptFunc (S, &DOptShift2, 1); Changes += RunOptFunc (S, &DOptShift2, 1);
Changes += RunOptFunc (S, &DOptShift3, 1); Changes += RunOptFunc (S, &DOptShift3, 1);

View File

@ -231,16 +231,16 @@ static void Parse (void)
/* Function */ /* Function */
if (!comma) { if (!comma) {
if (CurTok.Tok == TOK_SEMI) { if (CurTok.Tok == TOK_SEMI) {
/* Prototype only */ /* Prototype only */
NextToken (); NextToken ();
} else if (Entry) {
} else { /* Function body definition */
if (Entry) { if (SymIsDef (Entry)) {
NewFunc (Entry); Error ("Body for function `%s' has already been defined",
Entry->Name);
} }
NewFunc (Entry);
} }
} }

View File

@ -284,6 +284,95 @@ unsigned OptAdd2 (CodeSeg* S)
unsigned OptAdd3 (CodeSeg* S) unsigned OptAdd3 (CodeSeg* S)
/* Search for the sequence
*
* jsr pushax
* lda xxx
* ldy yyy
* jsr tosaddax
*
* and replace it by
*
* clc
* adc xxx
* pha
* txa
* adc yyy
* tax
* pla
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[4];
/* Get next entry */
L[0] = CS_GetEntry (S, I);
/* Check for the sequence */
if (CE_IsCallTo (L[0], "pushax") &&
CS_GetEntries (S, L+1, I+1, 3) &&
!CS_RangeHasLabel (S, I+1, 3) &&
L[1]->OPC == OP65_LDA &&
(L[1]->AM == AM65_ABS || L[1]->AM == AM65_ZP) &&
L[2]->OPC == OP65_LDX &&
(L[2]->AM == AM65_ABS || L[2]->AM == AM65_ZP) &&
CE_IsCallTo (L[3], "tosaddax")) {
CodeEntry* X;
/* Insert new code behind the sequence */
X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[3]->LI);
CS_InsertEntry (S, X, I+4);
/* adc xxx */
X = NewCodeEntry (OP65_ADC, L[1]->AM, L[1]->Arg, 0, L[3]->LI);
CS_InsertEntry (S, X, I+5);
/* pha */
X = NewCodeEntry (OP65_PHA, AM65_IMP, 0, 0, L[3]->LI);
CS_InsertEntry (S, X, I+6);
/* txa */
X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, L[3]->LI);
CS_InsertEntry (S, X, I+7);
/* adc yyy */
X = NewCodeEntry (OP65_ADC, L[2]->AM, L[2]->Arg, 0, L[3]->LI);
CS_InsertEntry (S, X, I+8);
/* tax */
X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[3]->LI);
CS_InsertEntry (S, X, I+9);
/* pla */
X = NewCodeEntry (OP65_PLA, AM65_IMP, 0, 0, L[3]->LI);
CS_InsertEntry (S, X, I+10);
/* Delete the old code */
CS_DelEntries (S, I, 4);
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
unsigned OptAdd4 (CodeSeg* S)
/* Search for the sequence /* Search for the sequence
* *
* adc ... * adc ...
@ -335,4 +424,3 @@ unsigned OptAdd3 (CodeSeg* S)

View File

@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2001 Ullrich von Bassewitz */ /* (C) 2001-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */ /* Wacholderweg 14 */
/* D-70597 Stuttgart */ /* D-70597 Stuttgart */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@ -97,6 +97,25 @@ unsigned OptAdd2 (CodeSeg* S);
*/ */
unsigned OptAdd3 (CodeSeg* S); unsigned OptAdd3 (CodeSeg* S);
/* Search for the sequence
*
* jsr pushax
* lda xxx
* ldy yyy
* jsr tosaddax
*
* and replace it by
*
* clc
* adc xxx
* pha
* txa
* adc yyy
* tax
* pla
*/
unsigned OptAdd4 (CodeSeg* S);
/* Search for the sequence /* Search for the sequence
* *
* adc ... * adc ...

View File

@ -42,6 +42,7 @@
/* common */ /* common */
#include "attrib.h" #include "attrib.h"
#include "inline.h"
/* cc65 */ /* cc65 */
#include "funcdesc.h" #include "funcdesc.h"

View File

@ -297,8 +297,11 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
Declaration Decl; Declaration Decl;
ParseDecl (&Spec, &Decl, 0); ParseDecl (&Spec, &Decl, 0);
/* Get the offset of this field */
Offs = (StructType == T_STRUCT)? Size : 0;
/* Add a field entry to the table */ /* Add a field entry to the table */
AddLocalSym (Decl.Ident, Decl.Type, SC_SFLD, (StructType == T_STRUCT)? Size : 0); AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
/* Calculate offset of next field/size of the union */ /* Calculate offset of next field/size of the union */
Offs = CheckedSizeOf (Decl.Type); Offs = CheckedSizeOf (Decl.Type);
@ -516,7 +519,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
case TOK_IDENT: case TOK_IDENT:
Entry = FindSym (CurTok.Ident); Entry = FindSym (CurTok.Ident);
if (Entry && IsTypeDef (Entry)) { if (Entry && SymIsTypeDef (Entry)) {
/* It's a typedef */ /* It's a typedef */
NextToken (); NextToken ();
TypeCpy (D->Type, Entry->Type); TypeCpy (D->Type, Entry->Type);
@ -746,7 +749,7 @@ static FuncDesc* ParseFuncDecl (const DeclSpec* Spec)
* if it's some other identifier, it's an old style parameter list. * if it's some other identifier, it's an old style parameter list.
*/ */
Sym = FindSym (CurTok.Ident); Sym = FindSym (CurTok.Ident);
if (Sym == 0 || !IsTypeDef (Sym)) { if (Sym == 0 || !SymIsTypeDef (Sym)) {
/* Old style (K&R) function. Assume variable param list. */ /* Old style (K&R) function. Assume variable param list. */
F->Flags |= (FD_OLDSTYLE | FD_VARIADIC); F->Flags |= (FD_OLDSTYLE | FD_VARIADIC);

View File

@ -437,7 +437,7 @@ static int istypeexpr (void)
(NextTok.Tok == TOK_CONST) || (NextTok.Tok == TOK_CONST) ||
(NextTok.Tok == TOK_IDENT && (NextTok.Tok == TOK_IDENT &&
(Entry = FindSym (NextTok.Ident)) != 0 && (Entry = FindSym (NextTok.Ident)) != 0 &&
IsTypeDef (Entry))); SymIsTypeDef (Entry)));
} }
@ -941,7 +941,7 @@ static int primary (ExprDesc* lval)
} else if ((Sym->Flags & SC_REGISTER) == SC_REGISTER) { } else if ((Sym->Flags & SC_REGISTER) == SC_REGISTER) {
/* Register variable, zero page based */ /* Register variable, zero page based */
lval->Flags = E_MGLOBAL | E_MCONST | E_TREGISTER; lval->Flags = E_MGLOBAL | E_MCONST | E_TREGISTER;
lval->Name = Sym->V.Offs; lval->Name = Sym->V.R.RegOffs;
lval->ConstVal = 0; lval->ConstVal = 0;
} else if ((Sym->Flags & SC_STATIC) == SC_STATIC) { } else if ((Sym->Flags & SC_STATIC) == SC_STATIC) {
/* Static variable */ /* Static variable */

View File

@ -101,28 +101,25 @@ void DoneRegVars (void)
static int AllocRegVar (const SymEntry* Sym, const type* tarray) static int AllocRegVar (const type* Type)
/* Allocate a register variable with the given amount of storage. If the /* Allocate a register variable for the given variable type. If the allocation
* allocation was successful, return the offset of the register variable in * was successful, return the offset of the register variable in the register
* the register bank (zero page storage). If there is no register space left, * bank (zero page storage). If there is no register space left, return -1.
* return -1.
*/ */
{ {
/* Maybe register variables are disabled... */ /* Maybe register variables are disabled... */
if (EnableRegVars) { if (EnableRegVars) {
/* Get the size of the variable */ /* Get the size of the variable */
unsigned Size = CheckedSizeOf (tarray); unsigned Size = CheckedSizeOf (Type);
/* Do we have space left? */ /* Do we have space left? */
if (RegOffs >= Size) { if (RegOffs >= Size) {
/* Space left. We allocate the variables from high to low addresses, /* Space left. We allocate the variables from high to low addresses,
* so the adressing is compatible with the saved values on stack. * so the adressing is compatible with the saved values on stack.
* This allows shorter code when saving/restoring the variables. * This allows shorter code when saving/restoring the variables.
*/ */
RegOffs -= Size; RegOffs -= Size;
RegSyms [RegSymCount++] = Sym;
return RegOffs; return RegOffs;
} }
} }
@ -133,6 +130,96 @@ static int AllocRegVar (const SymEntry* Sym, const type* tarray)
static void RememberRegVar (const SymEntry* Sym)
/* Remember the given register variable */
{
RegSyms[RegSymCount++] = Sym;
}
static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg)
/* Parse the declaration of a register variable. The function returns the
* symbol data, which is the offset of the variable in the register bank.
*/
{
unsigned Flags;
unsigned InitLabel;
/* Determine if this is a compound variable */
int IsCompound = IsClassStruct (Decl->Type) || IsTypeArray (Decl->Type);
/* Get the size of the variable */
unsigned Size = SizeOf (Decl->Type);
/* Save the current contents of the register variable on stack */
F_AllocLocalSpace (CurrentFunc);
g_save_regvars (Reg, Size);
/* Check for an optional initialization */
if (CurTok.Tok == TOK_ASSIGN) {
ExprDesc lval;
/* Skip the '=' */
NextToken ();
/* Special handling for compound types */
if (IsCompound) {
/* Switch to read only data */
g_userodata ();
/* Define a label for the initialization data */
InitLabel = GetLocalLabel ();
g_defdatalabel (InitLabel);
/* Parse the initialization generating a memory image of the
* data in the RODATA segment.
*/
ParseInit (Decl->Type);
/* Generate code to copy this data into the variable space */
g_initregister (InitLabel, Reg, Size);
} else {
/* Setup the type flags for the assignment */
Flags = CF_REGVAR;
if (Size == SIZEOF_CHAR) {
Flags |= CF_FORCECHAR;
}
/* Get the expression into the primary */
if (evalexpr (Flags, hie1, &lval) == 0) {
/* Constant expression. Adjust the types */
assignadjust (Decl->Type, &lval);
Flags |= CF_CONST;
} else {
/* Expression is not constant and in the primary */
assignadjust (Decl->Type, &lval);
}
/* Store the value into the variable */
g_putstatic (Flags | TypeOf (Decl->Type), Reg, 0);
}
/* Mark the variable as referenced */
*SC |= SC_REF;
}
/* Cannot allocate a variable of zero size */
if (Size == 0) {
Error ("Variable `%s' has unknown size", Decl->Ident);
}
/* Return the symbol data */
return Reg;
}
static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC)
/* Parse the declaration of an auto variable. The function returns the symbol /* Parse the declaration of an auto variable. The function returns the symbol
* data, which is the offset for variables on the stack, and the label for * data, which is the offset for variables on the stack, and the label for
@ -152,8 +239,7 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC)
/* Check if this is a variable on the stack or in static memory */ /* Check if this is a variable on the stack or in static memory */
if (StaticLocals == 0) { if (StaticLocals == 0) {
/* Change SC in case it was register */ /* Check for an optional initialization */
*SC = (*SC & ~SC_REGISTER) | SC_AUTO;
if (CurTok.Tok == TOK_ASSIGN) { if (CurTok.Tok == TOK_ASSIGN) {
ExprDesc lval; ExprDesc lval;
@ -226,7 +312,7 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC)
} else { } else {
/* Static local variables. */ /* Static local variables. */
*SC = (*SC & ~(SC_REGISTER | SC_AUTO)) | SC_STATIC; *SC = (*SC & ~SC_AUTO) | SC_STATIC;
/* Put them into the BSS */ /* Put them into the BSS */
g_usebss (); g_usebss ();
@ -370,6 +456,8 @@ static void ParseOneDecl (const DeclSpec* Spec)
unsigned SC; /* Storage class for symbol */ unsigned SC; /* Storage class for symbol */
unsigned SymData = 0; /* Symbol data (offset, label name, ...) */ unsigned SymData = 0; /* Symbol data (offset, label name, ...) */
Declaration Decl; /* Declaration data structure */ Declaration Decl; /* Declaration data structure */
SymEntry* Sym; /* Symbol declared */
/* Remember the storage class for the new symbol */ /* Remember the storage class for the new symbol */
SC = Spec->StorageClass; SC = Spec->StorageClass;
@ -397,27 +485,42 @@ static void ParseOneDecl (const DeclSpec* Spec)
/* Handle anything that needs storage (no functions, no typdefs) */ /* Handle anything that needs storage (no functions, no typdefs) */
if ((SC & SC_FUNC) != SC_FUNC && (SC & SC_TYPEDEF) != SC_TYPEDEF) { if ((SC & SC_FUNC) != SC_FUNC && (SC & SC_TYPEDEF) != SC_TYPEDEF) {
/* */ /* If we have a register variable, try to allocate a register and
if (SC & (SC_AUTO | SC_REGISTER)) { * convert the declaration to "auto" if this is not possible.
*/
int Reg = 0; /* Initialize to avoid gcc complains */
if ((SC & SC_REGISTER) != 0 && (Reg = AllocRegVar (Decl.Type)) < 0) {
/* No space for this register variable, convert to auto */
SC = (SC & ~SC_REGISTER) | SC_AUTO;
}
/* Check the variable type */
if (SC & SC_REGISTER) {
/* Register variable */
SymData = ParseRegisterDecl (&Decl, &SC, Reg);
} else if (SC & SC_AUTO) {
/* Auto variable */ /* Auto variable */
SymData = ParseAutoDecl (&Decl, &SC); SymData = ParseAutoDecl (&Decl, &SC);
} else if (SC & SC_STATIC) {
} else if ((SC & SC_STATIC) == SC_STATIC) {
/* Static variable */ /* Static variable */
SymData = ParseStaticDecl (&Decl, &SC); SymData = ParseStaticDecl (&Decl, &SC);
} else {
Internal ("Invalid storage class in ParseOneDecl: %04X", SC);
} }
} }
/* If the symbol is not marked as external, it will be defined */ /* If the symbol is not marked as external, it will be defined now */
if ((SC & SC_EXTERN) == 0) { if ((SC & SC_EXTERN) == 0) {
SC |= SC_DEF; SC |= SC_DEF;
} }
/* Add the symbol to the symbol table */ /* Add the symbol to the symbol table */
AddLocalSym (Decl.Ident, Decl.Type, SC, SymData); Sym = AddLocalSym (Decl.Ident, Decl.Type, SC, SymData);
/* If we had declared a register variable, remember it now */
if (SC & SC_REGISTER) {
RememberRegVar (Sym);
}
} }
@ -511,7 +614,7 @@ void RestoreRegVars (int HaveResult)
/* Check for more than one variable */ /* Check for more than one variable */
const SymEntry* Sym = RegSyms[I]; const SymEntry* Sym = RegSyms[I];
Offs = Sym->V.Offs; Offs = Sym->V.R.SaveOffs;
Bytes = CheckedSizeOf (Sym->Type); Bytes = CheckedSizeOf (Sym->Type);
J = I+1; J = I+1;
@ -524,7 +627,7 @@ void RestoreRegVars (int HaveResult)
int Size = CheckedSizeOf (NextSym->Type); int Size = CheckedSizeOf (NextSym->Type);
/* Adjacent variable? */ /* Adjacent variable? */
if (NextSym->V.Offs + Size != Offs) { if (NextSym->V.R.SaveOffs + Size != Offs) {
/* No */ /* No */
break; break;
} }
@ -537,7 +640,7 @@ void RestoreRegVars (int HaveResult)
} }
/* Restore the memory range */ /* Restore the memory range */
g_restore_regvars (Offs, Sym->V.Offs, Bytes); g_restore_regvars (Offs, Sym->V.R.RegOffs, Bytes);
/* Next round */ /* Next round */
I = J; I = J;

View File

@ -91,6 +91,7 @@ static void Usage (void)
" -h\t\t\tHelp (this text)\n" " -h\t\t\tHelp (this text)\n"
" -j\t\t\tDefault characters are signed\n" " -j\t\t\tDefault characters are signed\n"
" -o name\t\tName the output file\n" " -o name\t\tName the output file\n"
" -r\t\t\tEnable register variables\n"
" -t sys\t\tSet the target system\n" " -t sys\t\tSet the target system\n"
" -v\t\t\tIncrease verbosity\n" " -v\t\t\tIncrease verbosity\n"
"\n" "\n"
@ -112,6 +113,7 @@ static void Usage (void)
" --help\t\tHelp (this text)\n" " --help\t\tHelp (this text)\n"
" --include-dir dir\tSet an include directory search path\n" " --include-dir dir\tSet an include directory search path\n"
" --list-opt-steps\tList all optimizer steps and exit\n" " --list-opt-steps\tList all optimizer steps and exit\n"
" --register-vars\tEnable register variables\n"
" --rodata-name seg\tSet the name of the RODATA segment\n" " --rodata-name seg\tSet the name of the RODATA segment\n"
" --signed-chars\tDefault characters are signed\n" " --signed-chars\tDefault characters are signed\n"
" --static-locals\tMake local variables static\n" " --static-locals\tMake local variables static\n"
@ -528,6 +530,15 @@ static void OptListOptSteps (const char* Opt attribute ((unused)),
static void OptRegisterVars (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Handle the --register-vars option */
{
EnableRegVars = 1;
}
static void OptRodataName (const char* Opt attribute ((unused)), const char* Arg) static void OptRodataName (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --rodata-name option */ /* Handle the --rodata-name option */
{ {
@ -607,6 +618,7 @@ int main (int argc, char* argv[])
{ "--help", 0, OptHelp }, { "--help", 0, OptHelp },
{ "--include-dir", 1, OptIncludeDir }, { "--include-dir", 1, OptIncludeDir },
{ "--list-opt-steps", 0, OptListOptSteps }, { "--list-opt-steps", 0, OptListOptSteps },
{ "--register-vars", 0, OptRegisterVars },
{ "--rodata-name", 1, OptRodataName }, { "--rodata-name", 1, OptRodataName },
{ "--signed-chars", 0, OptSignedChars }, { "--signed-chars", 0, OptSignedChars },
{ "--static-locals", 0, OptStaticLocals }, { "--static-locals", 0, OptStaticLocals },
@ -666,6 +678,10 @@ int main (int argc, char* argv[])
OutputFile = GetArg (&I, 2); OutputFile = GetArg (&I, 2);
break; break;
case 'r':
OptRegisterVars (Arg, 0);
break;
case 't': case 't':
OptTarget (Arg, GetArg (&I, 2)); OptTarget (Arg, GetArg (&I, 2));
break; break;

View File

@ -95,7 +95,7 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
} Flags [] = { } Flags [] = {
/* Beware: Order is important! */ /* Beware: Order is important! */
{ "SC_TYPEDEF", SC_TYPEDEF }, { "SC_TYPEDEF", SC_TYPEDEF },
{ "SC_SFLD", SC_SFLD }, { "SC_STRUCTFIELD", SC_STRUCTFIELD },
{ "SC_STRUCT", SC_STRUCT }, { "SC_STRUCT", SC_STRUCT },
{ "SC_AUTO", SC_AUTO }, { "SC_AUTO", SC_AUTO },
{ "SC_REGISTER", SC_REGISTER }, { "SC_REGISTER", SC_REGISTER },
@ -149,14 +149,6 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
int IsTypeDef (const SymEntry* E)
/* Return true if the given entry is a typedef entry */
{
return ((E->Flags & SC_TYPEDEF) == SC_TYPEDEF);
}
void ChangeSymType (SymEntry* Entry, type* Type) void ChangeSymType (SymEntry* Entry, type* Type)
/* Change the type of the given symbol */ /* Change the type of the given symbol */
{ {

View File

@ -40,6 +40,9 @@
#include <stdio.h> #include <stdio.h>
/* common */
#include "inline.h"
/* cc65 */ /* cc65 */
#include "datatype.h" #include "datatype.h"
@ -81,7 +84,7 @@ struct Segments;
#define SC_TYPE 0x4000U /* This is a type, struct, typedef, etc. */ #define SC_TYPE 0x4000U /* This is a type, struct, typedef, etc. */
#define SC_STRUCT 0x4001U /* Struct or union */ #define SC_STRUCT 0x4001U /* Struct or union */
#define SC_SFLD 0x4002U /* Struct or union field */ #define SC_STRUCTFIELD 0x4002U /* Struct or union field */
#define SC_TYPEDEF 0x4003U /* A typedef */ #define SC_TYPEDEF 0x4003U /* A typedef */
#define SC_ZEROPAGE 0x8000U /* Symbol marked as zeropage */ #define SC_ZEROPAGE 0x8000U /* Symbol marked as zeropage */
@ -109,6 +112,14 @@ struct SymEntry {
/* Label name for static symbols */ /* Label name for static symbols */
unsigned Label; unsigned Label;
/* Register bank offset and offset of the saved copy on stack for
* register variables.
*/
struct {
int RegOffs;
int SaveOffs;
} R;
/* Value for constants (including enums) */ /* Value for constants (including enums) */
long ConstVal; long ConstVal;
@ -145,8 +156,35 @@ void FreeSymEntry (SymEntry* E);
void DumpSymEntry (FILE* F, const SymEntry* E); void DumpSymEntry (FILE* F, const SymEntry* E);
/* Dump the given symbol table entry to the file in readable form */ /* Dump the given symbol table entry to the file in readable form */
int IsTypeDef (const SymEntry* E); #if defined(HAVE_INLINE)
INLINE int SymIsTypeDef (const SymEntry* Sym)
/* Return true if the given entry is a typedef entry */ /* Return true if the given entry is a typedef entry */
{
return ((Sym->Flags & SC_TYPEDEF) == SC_TYPEDEF);
}
#else
# define SymIsTypeDef(Sym) (((Sym)->Flags & SC_TYPEDEF) == SC_TYPEDEF)
#endif
#if defined(HAVE_INLINE)
INLINE int SymIsDef (const SymEntry* Sym)
/* Return true if the given entry is defined */
{
return ((Sym->Flags & SC_DEF) == SC_DEF);
}
#else
# define SymIsDef(Sym) (((Sym)->Flags & SC_DEF) == SC_DEF)
#endif
#if defined(HAVE_INLINE)
INLINE int SymIsRef (const SymEntry* Sym)
/* Return true if the given entry is referenced */
{
return ((Sym->Flags & SC_REF) == SC_REF);
}
#else
# define SymIsRef(Sym) (((Sym)->Flags & SC_REF) == SC_REF)
#endif
void ChangeSymType (SymEntry* Entry, type* Type); void ChangeSymType (SymEntry* Entry, type* Type);
/* Change the type of the given symbol */ /* Change the type of the given symbol */

View File

@ -163,7 +163,7 @@ static void CheckSymTable (SymTable* Tab)
* defined but not used. * defined but not used.
*/ */
if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) { if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) {
if ((Flags & SC_DEF) && !(Flags & SC_REF)) { if (SymIsDef (Entry) && !SymIsRef (Entry)) {
if (Flags & SC_PARAM) { if (Flags & SC_PARAM) {
Warning ("Parameter `%s' is never used", Entry->Name); Warning ("Parameter `%s' is never used", Entry->Name);
} else { } else {
@ -174,10 +174,10 @@ static void CheckSymTable (SymTable* Tab)
/* If the entry is a label, check if it was defined in the function */ /* If the entry is a label, check if it was defined in the function */
if (Flags & SC_LABEL) { if (Flags & SC_LABEL) {
if ((Flags & SC_DEF) == 0) { if (!SymIsDef (Entry)) {
/* Undefined label */ /* Undefined label */
Error ("Undefined label: `%s'", Entry->Name); Error ("Undefined label: `%s'", Entry->Name);
} else if ((Flags & SC_REF) == 0) { } else if (!SymIsRef (Entry)) {
/* Defined but not used */ /* Defined but not used */
Warning ("`%s' is defined but never used", Entry->Name); Warning ("`%s' is defined but never used", Entry->Name);
} }
@ -614,7 +614,7 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name)); SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name));
if (Entry) { if (Entry) {
if ((Entry->Flags & SC_DEF) != 0 && (Flags & SC_DEF) != 0) { if (SymIsDef (Entry) && (Flags & SC_DEF) != 0) {
/* Trying to define the label more than once */ /* Trying to define the label more than once */
Error ("Label `%s' is defined more than once", Name); Error ("Label `%s' is defined more than once", Name);
} }
@ -656,7 +656,18 @@ SymEntry* AddLocalSym (const char* Name, const type* Type, unsigned Flags, int O
/* Set the symbol attributes */ /* Set the symbol attributes */
Entry->Type = TypeDup (Type); Entry->Type = TypeDup (Type);
if ((Flags & SC_AUTO) == SC_AUTO) {
Entry->V.Offs = Offs; Entry->V.Offs = Offs;
} else if ((Flags & SC_REGISTER) == SC_REGISTER) {
Entry->V.R.RegOffs = Offs;
Entry->V.R.SaveOffs = oursp; /* ### Cleaner! */
} else if ((Flags & SC_STATIC) == SC_STATIC) {
Entry->V.Label = Offs;
} else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) {
Entry->V.Offs = Offs;
} else {
Internal ("Invalid flags in AddLocalSym: %04X", Flags);
}
/* Add the entry to the symbol table */ /* Add the entry to the symbol table */
AddSymEntry (SymTab, Entry); AddSymEntry (SymTab, Entry);
@ -856,10 +867,10 @@ void EmitExternals (void)
unsigned Flags = Entry->Flags; unsigned Flags = Entry->Flags;
if (Flags & SC_EXTERN) { if (Flags & SC_EXTERN) {
/* Only defined or referenced externs */ /* Only defined or referenced externs */
if ((Flags & SC_REF) != 0 && (Flags & SC_DEF) == 0) { if (SymIsRef (Entry) && !SymIsDef (Entry)) {
/* An import */ /* An import */
g_defimport (Entry->Name, Flags & SC_ZEROPAGE); g_defimport (Entry->Name, Flags & SC_ZEROPAGE);
} else if (Flags & SC_DEF) { } else if (SymIsDef (Entry)) {
/* An export */ /* An export */
g_defexport (Entry->Name, Flags & SC_ZEROPAGE); g_defexport (Entry->Name, Flags & SC_ZEROPAGE);
} }