From: cuz Date: Sun, 24 Nov 2002 23:31:54 +0000 (+0000) Subject: Reenable register variables X-Git-Tag: V2.12.0~2013 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=ede471904c740b4f58112f7101beccfbc41571fe;p=cc65 Reenable register variables git-svn-id: svn://svn.cc65.org/cc65/trunk@1625 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/cc65/asmcode.c b/src/cc65/asmcode.c index 39092092f..788dd5bec 100644 --- a/src/cc65/asmcode.c +++ b/src/cc65/asmcode.c @@ -72,7 +72,7 @@ void MoveCode (CodeMark Start, CodeMark End, CodeMark Target) /* Move the code between Start (inclusive) and End (exclusive) to * (before) Target. */ -{ +{ CS_MoveEntries (CS->Code, Start, End - Start, Target); } @@ -93,7 +93,7 @@ void WriteOutput (FILE* F) Entry = SymTab->SymHead; while (Entry) { if (IsTypeFunc (Entry->Type) && - (Entry->Flags & SC_DEF) != 0 && + SymIsDef (Entry) && (Entry->Flags & (SC_REF | SC_EXTERN)) != 0) { /* Function which is defined and referenced or extern */ CS_MergeLabels (Entry->V.F.Seg->Code); diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index c4a50b139..6e05351d0 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -134,7 +134,7 @@ static const char* GetLabelName (unsigned Flags, unsigned long Label, long Offs) default: Internal ("Invalid address flags"); } - + /* Return a pointer to the static buffer */ return Buf; } @@ -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) /* Initialize a local variable at stack offset zero from static data */ { diff --git a/src/cc65/codegen.h b/src/cc65/codegen.h index 68e15b189..649d5e789 100644 --- a/src/cc65/codegen.h +++ b/src/cc65/codegen.h @@ -432,6 +432,9 @@ void g_defbytes (const void* bytes, unsigned count); void g_zerobytes (unsigned n); /* 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); /* Initialize a local variable at stack offset zero from static data */ diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index b58acc6f9..88672fc1c 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -1391,7 +1391,8 @@ static OptFunc DOpt65C02Ind = { Opt65C02Ind, "Opt65C02Ind", 100, 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 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 DOptBranchDist = { OptBranchDist, "OptBranchDist", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptCmp1 = { OptCmp1, "OptCmp1", 85, 0, 0, 0, 0, 0 }; @@ -1454,6 +1455,7 @@ static OptFunc* OptFuncs[] = { &DOptAdd1, &DOptAdd2, &DOptAdd3, + &DOptAdd4, &DOptBoolTrans, &DOptBranchDist, &DOptCmp1, @@ -1752,6 +1754,7 @@ static unsigned RunOptGroup1 (CodeSeg* S) Changes += RunOptFunc (S, &DOptNegAX4, 1); Changes += RunOptFunc (S, &DOptAdd1, 1); Changes += RunOptFunc (S, &DOptAdd2, 1); + Changes += RunOptFunc (S, &DOptAdd3, 1); Changes += RunOptFunc (S, &DOptShift1, 1); Changes += RunOptFunc (S, &DOptShift2, 1); Changes += RunOptFunc (S, &DOptShift3, 1); diff --git a/src/cc65/compile.c b/src/cc65/compile.c index 0e751edf9..f194cb1aa 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -231,16 +231,16 @@ static void Parse (void) /* Function */ if (!comma) { - if (CurTok.Tok == TOK_SEMI) { - /* Prototype only */ NextToken (); - - } else { - if (Entry) { - NewFunc (Entry); - } + } else if (Entry) { + /* Function body definition */ + if (SymIsDef (Entry)) { + Error ("Body for function `%s' has already been defined", + Entry->Name); + } + NewFunc (Entry); } } diff --git a/src/cc65/coptadd.c b/src/cc65/coptadd.c index 3fa886fed..3a11a9c6a 100644 --- a/src/cc65/coptadd.c +++ b/src/cc65/coptadd.c @@ -284,6 +284,95 @@ unsigned OptAdd2 (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 * * adc ... @@ -306,7 +395,7 @@ unsigned OptAdd3 (CodeSeg* S) CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ - if (E->OPC == OP65_ADC && + if (E->OPC == OP65_ADC && CS_GetEntries (S, L, I+1, 3) && (L[0]->OPC == OP65_BCC || L[0]->OPC == OP65_JCC) && L[0]->JumpTo != 0 && @@ -335,4 +424,3 @@ unsigned OptAdd3 (CodeSeg* S) - diff --git a/src/cc65/coptadd.h b/src/cc65/coptadd.h index 545552bcd..accf3d831 100644 --- a/src/cc65/coptadd.h +++ b/src/cc65/coptadd.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2001 Ullrich von Bassewitz */ +/* (C) 2001-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ @@ -97,6 +97,25 @@ unsigned OptAdd2 (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 * * adc ... diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index 75892f0f1..94ae9ec4a 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -42,6 +42,7 @@ /* common */ #include "attrib.h" +#include "inline.h" /* cc65 */ #include "funcdesc.h" diff --git a/src/cc65/declare.c b/src/cc65/declare.c index e2770e1ca..0c647c835 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -297,8 +297,11 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType) Declaration Decl; ParseDecl (&Spec, &Decl, 0); + /* Get the offset of this field */ + Offs = (StructType == T_STRUCT)? Size : 0; + /* 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 */ Offs = CheckedSizeOf (Decl.Type); @@ -516,7 +519,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default) case TOK_IDENT: Entry = FindSym (CurTok.Ident); - if (Entry && IsTypeDef (Entry)) { + if (Entry && SymIsTypeDef (Entry)) { /* It's a typedef */ NextToken (); 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. */ Sym = FindSym (CurTok.Ident); - if (Sym == 0 || !IsTypeDef (Sym)) { + if (Sym == 0 || !SymIsTypeDef (Sym)) { /* Old style (K&R) function. Assume variable param list. */ F->Flags |= (FD_OLDSTYLE | FD_VARIADIC); diff --git a/src/cc65/expr.c b/src/cc65/expr.c index aacc96891..afdcf42a7 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -183,7 +183,7 @@ static unsigned typeadjust (ExprDesc* lhs, ExprDesc* rhs, int NoPush) } flags = g_typeadjust (ltype, rtype); - /* Set the type of the result */ + /* Set the type of the result */ lhs->Type = promoteint (lhst, rhst); /* Return the code generator flags */ @@ -437,7 +437,7 @@ static int istypeexpr (void) (NextTok.Tok == TOK_CONST) || (NextTok.Tok == TOK_IDENT && (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) { /* Register variable, zero page based */ lval->Flags = E_MGLOBAL | E_MCONST | E_TREGISTER; - lval->Name = Sym->V.Offs; + lval->Name = Sym->V.R.RegOffs; lval->ConstVal = 0; } else if ((Sym->Flags & SC_STATIC) == SC_STATIC) { /* Static variable */ diff --git a/src/cc65/locals.c b/src/cc65/locals.c index fcadb4e9a..ad87c3ebd 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -101,28 +101,25 @@ void DoneRegVars (void) -static int AllocRegVar (const SymEntry* Sym, const type* tarray) -/* Allocate a register variable with the given amount of storage. If the - * allocation was successful, return the offset of the register variable in - * the register bank (zero page storage). If there is no register space left, - * return -1. +static int AllocRegVar (const type* Type) +/* Allocate a register variable for the given variable type. If the allocation + * was successful, return the offset of the register variable in the register + * bank (zero page storage). If there is no register space left, return -1. */ { /* Maybe register variables are disabled... */ if (EnableRegVars) { /* Get the size of the variable */ - unsigned Size = CheckedSizeOf (tarray); + unsigned Size = CheckedSizeOf (Type); /* Do we have space left? */ if (RegOffs >= Size) { - /* Space left. We allocate the variables from high to low addresses, * so the adressing is compatible with the saved values on stack. * This allows shorter code when saving/restoring the variables. */ RegOffs -= Size; - RegSyms [RegSymCount++] = Sym; 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) /* 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 @@ -152,8 +239,7 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) /* Check if this is a variable on the stack or in static memory */ if (StaticLocals == 0) { - /* Change SC in case it was register */ - *SC = (*SC & ~SC_REGISTER) | SC_AUTO; + /* Check for an optional initialization */ if (CurTok.Tok == TOK_ASSIGN) { ExprDesc lval; @@ -226,7 +312,7 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) } else { /* Static local variables. */ - *SC = (*SC & ~(SC_REGISTER | SC_AUTO)) | SC_STATIC; + *SC = (*SC & ~SC_AUTO) | SC_STATIC; /* Put them into the BSS */ g_usebss (); @@ -369,7 +455,9 @@ static void ParseOneDecl (const DeclSpec* Spec) { unsigned SC; /* Storage class for symbol */ 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 */ SC = Spec->StorageClass; @@ -391,33 +479,48 @@ static void ParseOneDecl (const DeclSpec* Spec) * To avoid problems later, use an anonymous name here. */ if (Decl.Ident[0] == '\0') { - AnonName (Decl.Ident, "param"); + AnonName (Decl.Ident, "param"); } /* Handle anything that needs storage (no functions, no typdefs) */ if ((SC & SC_FUNC) != SC_FUNC && (SC & SC_TYPEDEF) != SC_TYPEDEF) { - /* */ - if (SC & (SC_AUTO | SC_REGISTER)) { + /* If we have a register variable, try to allocate a register and + * 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 */ SymData = ParseAutoDecl (&Decl, &SC); - - } else if ((SC & SC_STATIC) == SC_STATIC) { - + } else if (SC & SC_STATIC) { /* Static variable */ 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) { - SC |= SC_DEF; + SC |= SC_DEF; } /* 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); + } } @@ -510,8 +613,8 @@ void RestoreRegVars (int HaveResult) while (I < RegSymCount) { /* Check for more than one variable */ - const SymEntry* Sym = RegSyms[I]; - Offs = Sym->V.Offs; + const SymEntry* Sym = RegSyms[I]; + Offs = Sym->V.R.SaveOffs; Bytes = CheckedSizeOf (Sym->Type); J = I+1; @@ -524,7 +627,7 @@ void RestoreRegVars (int HaveResult) int Size = CheckedSizeOf (NextSym->Type); /* Adjacent variable? */ - if (NextSym->V.Offs + Size != Offs) { + if (NextSym->V.R.SaveOffs + Size != Offs) { /* No */ break; } @@ -537,7 +640,7 @@ void RestoreRegVars (int HaveResult) } /* Restore the memory range */ - g_restore_regvars (Offs, Sym->V.Offs, Bytes); + g_restore_regvars (Offs, Sym->V.R.RegOffs, Bytes); /* Next round */ I = J; diff --git a/src/cc65/main.c b/src/cc65/main.c index da92fcd72..c79f52acf 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -91,6 +91,7 @@ static void Usage (void) " -h\t\t\tHelp (this text)\n" " -j\t\t\tDefault characters are signed\n" " -o name\t\tName the output file\n" + " -r\t\t\tEnable register variables\n" " -t sys\t\tSet the target system\n" " -v\t\t\tIncrease verbosity\n" "\n" @@ -112,6 +113,7 @@ static void Usage (void) " --help\t\tHelp (this text)\n" " --include-dir dir\tSet an include directory search path\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" " --signed-chars\tDefault characters are signed\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) /* Handle the --rodata-name option */ { @@ -607,10 +618,11 @@ int main (int argc, char* argv[]) { "--help", 0, OptHelp }, { "--include-dir", 1, OptIncludeDir }, { "--list-opt-steps", 0, OptListOptSteps }, + { "--register-vars", 0, OptRegisterVars }, { "--rodata-name", 1, OptRodataName }, { "--signed-chars", 0, OptSignedChars }, { "--static-locals", 0, OptStaticLocals }, - { "--target", 1, OptTarget }, + { "--target", 1, OptTarget }, { "--verbose", 0, OptVerbose }, { "--version", 0, OptVersion }, }; @@ -666,6 +678,10 @@ int main (int argc, char* argv[]) OutputFile = GetArg (&I, 2); break; + case 'r': + OptRegisterVars (Arg, 0); + break; + case 't': OptTarget (Arg, GetArg (&I, 2)); break; @@ -690,8 +706,8 @@ int main (int argc, char* argv[]) OptStaticLocals (Arg, 0); break; default: - UnknownOption (Arg); - break; + UnknownOption (Arg); + break; } } break; diff --git a/src/cc65/symentry.c b/src/cc65/symentry.c index 8882cdb62..6745680d3 100644 --- a/src/cc65/symentry.c +++ b/src/cc65/symentry.c @@ -94,22 +94,22 @@ void DumpSymEntry (FILE* F, const SymEntry* E) unsigned Val; } Flags [] = { /* Beware: Order is important! */ - { "SC_TYPEDEF", SC_TYPEDEF }, - { "SC_SFLD", SC_SFLD }, - { "SC_STRUCT", SC_STRUCT }, - { "SC_AUTO", SC_AUTO }, - { "SC_REGISTER", SC_REGISTER }, - { "SC_STATIC", SC_STATIC }, - { "SC_EXTERN", SC_EXTERN }, - { "SC_ENUM", SC_ENUM }, - { "SC_CONST", SC_CONST }, - { "SC_LABEL", SC_LABEL }, - { "SC_PARAM", SC_PARAM }, - { "SC_FUNC", SC_FUNC }, - { "SC_STORAGE", SC_STORAGE }, - { "SC_DEF", SC_DEF }, - { "SC_REF", SC_REF }, - { "SC_ZEROPAGE", SC_ZEROPAGE }, + { "SC_TYPEDEF", SC_TYPEDEF }, + { "SC_STRUCTFIELD", SC_STRUCTFIELD }, + { "SC_STRUCT", SC_STRUCT }, + { "SC_AUTO", SC_AUTO }, + { "SC_REGISTER", SC_REGISTER }, + { "SC_STATIC", SC_STATIC }, + { "SC_EXTERN", SC_EXTERN }, + { "SC_ENUM", SC_ENUM }, + { "SC_CONST", SC_CONST }, + { "SC_LABEL", SC_LABEL }, + { "SC_PARAM", SC_PARAM }, + { "SC_FUNC", SC_FUNC }, + { "SC_STORAGE", SC_STORAGE }, + { "SC_DEF", SC_DEF }, + { "SC_REF", SC_REF }, + { "SC_ZEROPAGE", SC_ZEROPAGE }, }; unsigned I; @@ -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) /* Change the type of the given symbol */ { diff --git a/src/cc65/symentry.h b/src/cc65/symentry.h index 299b0b08e..e81945d64 100644 --- a/src/cc65/symentry.h +++ b/src/cc65/symentry.h @@ -40,6 +40,9 @@ #include +/* common */ +#include "inline.h" + /* cc65 */ #include "datatype.h" @@ -81,7 +84,7 @@ struct Segments; #define SC_TYPE 0x4000U /* This is a type, struct, typedef, etc. */ #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_ZEROPAGE 0x8000U /* Symbol marked as zeropage */ @@ -103,13 +106,21 @@ struct SymEntry { /* Data that differs for the different symbol types */ union { - /* Offset for locals or struct members */ - int Offs; + /* Offset for locals or struct members */ + int Offs; + + /* Label name for static symbols */ + unsigned Label; - /* Label name for static symbols */ - 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; /* Data for structs/unions */ @@ -145,8 +156,35 @@ void FreeSymEntry (SymEntry* E); void DumpSymEntry (FILE* F, const SymEntry* E); /* 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 ((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); /* Change the type of the given symbol */ diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index eca971f65..988190cd6 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -163,7 +163,7 @@ static void CheckSymTable (SymTable* Tab) * defined but not used. */ 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) { Warning ("Parameter `%s' is never used", Entry->Name); } 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 (Flags & SC_LABEL) { - if ((Flags & SC_DEF) == 0) { + if (!SymIsDef (Entry)) { /* Undefined label */ Error ("Undefined label: `%s'", Entry->Name); - } else if ((Flags & SC_REF) == 0) { + } else if (!SymIsRef (Entry)) { /* Defined but not used */ 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)); 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 */ 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 */ Entry->Type = TypeDup (Type); - Entry->V.Offs = Offs; + if ((Flags & SC_AUTO) == SC_AUTO) { + 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 */ AddSymEntry (SymTab, Entry); @@ -856,10 +867,10 @@ void EmitExternals (void) unsigned Flags = Entry->Flags; if (Flags & SC_EXTERN) { /* Only defined or referenced externs */ - if ((Flags & SC_REF) != 0 && (Flags & SC_DEF) == 0) { + if (SymIsRef (Entry) && !SymIsDef (Entry)) { /* An import */ g_defimport (Entry->Name, Flags & SC_ZEROPAGE); - } else if (Flags & SC_DEF) { + } else if (SymIsDef (Entry)) { /* An export */ g_defexport (Entry->Name, Flags & SC_ZEROPAGE); }