/* Move the code between Start (inclusive) and End (exclusive) to
* (before) Target.
*/
-{
+{
CS_MoveEntries (CS->Code, Start, End - Start, Target);
}
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);
default:
Internal ("Invalid address flags");
}
-
+
/* Return a pointer to the static buffer */
return Buf;
}
+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 */
{
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 */
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 };
&DOptAdd1,
&DOptAdd2,
&DOptAdd3,
+ &DOptAdd4,
&DOptBoolTrans,
&DOptBranchDist,
&DOptCmp1,
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);
/* 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);
}
}
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 ...
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 &&
-
/* */
/* */
/* */
-/* (C) 2001 Ullrich von Bassewitz */
+/* (C) 2001-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@cc65.org */
*/
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 ...
/* common */
#include "attrib.h"
+#include "inline.h"
/* cc65 */
#include "funcdesc.h"
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);
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);
* 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);
}
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 */
(NextTok.Tok == TOK_CONST) ||
(NextTok.Tok == TOK_IDENT &&
(Entry = FindSym (NextTok.Ident)) != 0 &&
- IsTypeDef (Entry)));
+ SymIsTypeDef (Entry)));
}
} 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 */
-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;
}
}
+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
/* 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;
} 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 ();
{
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;
* 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);
+ }
}
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;
int Size = CheckedSizeOf (NextSym->Type);
/* Adjacent variable? */
- if (NextSym->V.Offs + Size != Offs) {
+ if (NextSym->V.R.SaveOffs + Size != Offs) {
/* No */
break;
}
}
/* 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;
" -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"
" --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"
+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 */
{
{ "--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 },
};
OutputFile = GetArg (&I, 2);
break;
+ case 'r':
+ OptRegisterVars (Arg, 0);
+ break;
+
case 't':
OptTarget (Arg, GetArg (&I, 2));
break;
OptStaticLocals (Arg, 0);
break;
default:
- UnknownOption (Arg);
- break;
+ UnknownOption (Arg);
+ break;
}
}
break;
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;
-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 */
{
#include <stdio.h>
+/* common */
+#include "inline.h"
+
/* cc65 */
#include "datatype.h"
#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 */
/* 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 */
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 */
* 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 {
/* 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);
}
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);
}
/* 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);
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);
}