1
0
mirror of https://github.com/cc65/cc65.git synced 2024-11-19 06:31:31 +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

@ -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);

View File

@ -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 */
{

View File

@ -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 */

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 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);

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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 ...

View File

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

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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 */
{

View File

@ -40,6 +40,9 @@
#include <stdio.h>
/* 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;
/* Value for constants (including enums) */
/* 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) */
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 */

View File

@ -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);
}