mirror of
https://github.com/cc65/cc65.git
synced 2024-12-23 04:30:10 +00:00
Merge pull request #2344 from acqn/Cleanup
[cc65] Cleanup for symbol types and flags
This commit is contained in:
commit
8c329dfd1a
@ -80,9 +80,9 @@ static void AsmErrorSkip (void)
|
||||
|
||||
|
||||
|
||||
static SymEntry* AsmGetSym (unsigned Arg, unsigned Type)
|
||||
/* Find the symbol with the name currently in NextTok. The symbol must be of
|
||||
** the given type. On errors, NULL is returned.
|
||||
static SymEntry* AsmGetSym (unsigned Arg, int OnStack)
|
||||
/* Find the symbol with the name currently in NextTok. The symbol must be on
|
||||
** the stack if OnStack is true. On errors, NULL is returned.
|
||||
*/
|
||||
{
|
||||
SymEntry* Sym;
|
||||
@ -110,8 +110,8 @@ static SymEntry* AsmGetSym (unsigned Arg, unsigned Type)
|
||||
/* We found the symbol - skip the name token */
|
||||
NextToken ();
|
||||
|
||||
/* Check if we have a global symbol */
|
||||
if ((Sym->Flags & Type) != Type) {
|
||||
/* Check if the symbol is on the stack */
|
||||
if ((Sym->Flags & SC_STORAGEMASK) != SC_AUTO ? OnStack : !OnStack) {
|
||||
Error ("Type of argument %u differs from format specifier", Arg);
|
||||
AsmErrorSkip ();
|
||||
return 0;
|
||||
@ -218,23 +218,24 @@ static void ParseGVarArg (StrBuf* T, unsigned Arg)
|
||||
*/
|
||||
{
|
||||
/* Parse the symbol name parameter and check the type */
|
||||
SymEntry* Sym = AsmGetSym (Arg, SC_STATIC);
|
||||
SymEntry* Sym = AsmGetSym (Arg, 0);
|
||||
if (Sym == 0) {
|
||||
/* Some sort of error */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for external linkage */
|
||||
if (Sym->Flags & (SC_EXTERN | SC_STORAGE | SC_FUNC)) {
|
||||
/* External linkage or a function */
|
||||
/* Get the correct asm name */
|
||||
if ((Sym->Flags & SC_TYPEMASK) == SC_FUNC || SymIsGlobal (Sym)) {
|
||||
/* External or internal linkage or a function */
|
||||
SB_AppendChar (T, '_');
|
||||
SB_AppendStr (T, Sym->Name);
|
||||
} else if (Sym->Flags & SC_REGISTER) {
|
||||
} else if ((Sym->Flags & SC_STORAGEMASK) == SC_REGISTER) {
|
||||
/* Register variable */
|
||||
char Buf[32];
|
||||
xsprintf (Buf, sizeof (Buf), "regbank+%d", Sym->V.R.RegOffs);
|
||||
SB_AppendStr (T, Buf);
|
||||
} else {
|
||||
/* Static variable */
|
||||
/* Local static variable */
|
||||
SB_AppendStr (T, LocalDataLabelName (Sym->V.L.Label));
|
||||
}
|
||||
}
|
||||
@ -248,7 +249,7 @@ static void ParseLVarArg (StrBuf* T, unsigned Arg)
|
||||
char Buf [16];
|
||||
|
||||
/* Parse the symbol name parameter and check the type */
|
||||
SymEntry* Sym = AsmGetSym (Arg, SC_AUTO);
|
||||
SymEntry* Sym = AsmGetSym (Arg, 1);
|
||||
if (Sym == 0) {
|
||||
/* Some sort of error */
|
||||
return;
|
||||
|
@ -121,15 +121,13 @@ static void Parse (void)
|
||||
}
|
||||
|
||||
/* Read the declaration specifier */
|
||||
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_INT, SC_EXTERN | SC_STATIC);
|
||||
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_INT, SC_NONE);
|
||||
|
||||
/* Don't accept illegal storage classes */
|
||||
if ((Spec.StorageClass & SC_TYPEMASK) == 0) {
|
||||
if ((Spec.StorageClass & SC_AUTO) != 0 ||
|
||||
(Spec.StorageClass & SC_REGISTER) != 0) {
|
||||
if ((Spec.StorageClass & SC_STORAGEMASK) == SC_AUTO ||
|
||||
(Spec.StorageClass & SC_STORAGEMASK) == SC_REGISTER) {
|
||||
Error ("Illegal storage class");
|
||||
Spec.StorageClass = SC_EXTERN | SC_STATIC;
|
||||
}
|
||||
Spec.StorageClass &= ~SC_STORAGEMASK;
|
||||
}
|
||||
|
||||
/* Check if this is only a type declaration */
|
||||
@ -172,26 +170,26 @@ static void Parse (void)
|
||||
** - if the storage class is explicitly specified as static,
|
||||
** - or if there is an initialization.
|
||||
**
|
||||
** This means that "extern int i;" will not get storage allocated.
|
||||
** This means that "extern int i;" will not get storage allocated
|
||||
** in this translation unit.
|
||||
*/
|
||||
if ((Decl.StorageClass & SC_FUNC) != SC_FUNC &&
|
||||
if ((Decl.StorageClass & SC_TYPEMASK) != SC_FUNC &&
|
||||
(Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF) {
|
||||
if ((Spec.Flags & DS_DEF_STORAGE) != 0 ||
|
||||
(Decl.StorageClass & (SC_EXTERN|SC_STATIC)) == SC_STATIC ||
|
||||
((Decl.StorageClass & SC_EXTERN) != 0 &&
|
||||
/* The variable is visible in the file scope */
|
||||
if ((Decl.StorageClass & SC_STORAGEMASK) == SC_NONE ||
|
||||
(Decl.StorageClass & SC_STORAGEMASK) == SC_STATIC ||
|
||||
((Decl.StorageClass & SC_STORAGEMASK) == SC_EXTERN &&
|
||||
CurTok.Tok == TOK_ASSIGN)) {
|
||||
/* We will allocate storage */
|
||||
Decl.StorageClass |= SC_STORAGE;
|
||||
} else {
|
||||
/* It's a declaration */
|
||||
Decl.StorageClass |= SC_DECL;
|
||||
/* We will allocate storage in this translation unit */
|
||||
Decl.StorageClass |= SC_TU_STORAGE;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is a function declarator that is not followed by a comma
|
||||
** or semicolon, it must be followed by a function body.
|
||||
*/
|
||||
if ((Decl.StorageClass & SC_FUNC) != 0) {
|
||||
if ((Decl.StorageClass & SC_TYPEMASK) == SC_FUNC) {
|
||||
/* The function is now visible in the file scope */
|
||||
if (CurTok.Tok == TOK_LCURLY) {
|
||||
/* A definition */
|
||||
Decl.StorageClass |= SC_DEF;
|
||||
@ -205,8 +203,6 @@ static void Parse (void)
|
||||
}
|
||||
} else {
|
||||
/* Just a declaration */
|
||||
Decl.StorageClass |= SC_DECL;
|
||||
|
||||
FuncDef = GetFuncDesc (Decl.Type);
|
||||
if ((FuncDef->Flags & (FD_EMPTY | FD_OLDSTYLE)) == FD_OLDSTYLE) {
|
||||
/* A parameter list without types is only allowed in a
|
||||
@ -224,7 +220,7 @@ static void Parse (void)
|
||||
SymUseAttr (Sym, &Decl);
|
||||
|
||||
/* Reserve storage for the variable if we need to */
|
||||
if (Decl.StorageClass & SC_STORAGE) {
|
||||
if (Decl.StorageClass & SC_TU_STORAGE) {
|
||||
|
||||
/* Get the size of the variable */
|
||||
unsigned Size = SizeOf (Decl.Type);
|
||||
@ -327,11 +323,15 @@ static void Parse (void)
|
||||
}
|
||||
|
||||
/* Make the symbol zeropage according to the segment address size */
|
||||
if ((Sym->Flags & SC_STATIC) != 0) {
|
||||
if ((Sym->Flags & SC_TYPEMASK) == SC_NONE) {
|
||||
if (SymIsGlobal (Sym) ||
|
||||
(Sym->Flags & SC_STORAGEMASK) == SC_STATIC ||
|
||||
(Sym->Flags & SC_STORAGEMASK) == SC_REGISTER) {
|
||||
if (GetSegAddrSize (GetSegName (CS->CurDSeg)) == ADDR_SIZE_ZP) {
|
||||
Sym->Flags |= SC_ZEROPAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -517,7 +517,10 @@ void Compile (const char* FileName)
|
||||
** global variables.
|
||||
*/
|
||||
for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) {
|
||||
if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) {
|
||||
/* Is it a global (with or without static) tentative declaration of
|
||||
** an uninitialized variable?
|
||||
*/
|
||||
if ((Entry->Flags & (SC_TU_STORAGE | SC_DEF)) == SC_TU_STORAGE) {
|
||||
/* Assembly definition of uninitialized global variable */
|
||||
SymEntry* TagSym = GetESUTagSym (Entry->Type);
|
||||
unsigned Size = SizeOf (Entry->Type);
|
||||
@ -552,9 +555,9 @@ void Compile (const char* FileName)
|
||||
Entry->Name,
|
||||
GetFullTypeName (Entry->Type));
|
||||
}
|
||||
} else if (!SymIsDef (Entry) && (Entry->Flags & SC_FUNC) == SC_FUNC) {
|
||||
} else if (!SymIsDef (Entry) && (Entry->Flags & SC_TYPEMASK) == SC_FUNC) {
|
||||
/* Check for undefined functions */
|
||||
if ((Entry->Flags & (SC_EXTERN | SC_STATIC)) == SC_STATIC && SymIsRef (Entry)) {
|
||||
if ((Entry->Flags & SC_STORAGEMASK) == SC_STATIC && SymIsRef (Entry)) {
|
||||
Warning ("Static function '%s' used but never defined",
|
||||
Entry->Name);
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ static unsigned ParseOneStorageClass (void)
|
||||
switch (CurTok.Tok) {
|
||||
|
||||
case TOK_EXTERN:
|
||||
StorageClass = SC_EXTERN | SC_STATIC;
|
||||
StorageClass = SC_EXTERN;
|
||||
NextToken ();
|
||||
break;
|
||||
|
||||
@ -101,7 +101,7 @@ static unsigned ParseOneStorageClass (void)
|
||||
break;
|
||||
|
||||
case TOK_REGISTER:
|
||||
StorageClass = SC_REGISTER | SC_STATIC;
|
||||
StorageClass = SC_REGISTER;
|
||||
NextToken ();
|
||||
break;
|
||||
|
||||
@ -136,9 +136,9 @@ static int ParseStorageClass (DeclSpec* Spec)
|
||||
}
|
||||
|
||||
while (StorageClass != 0) {
|
||||
if (Spec->StorageClass == 0) {
|
||||
Spec->StorageClass = StorageClass;
|
||||
} else if (Spec->StorageClass == StorageClass) {
|
||||
if ((Spec->StorageClass & SC_STORAGEMASK) == 0) {
|
||||
Spec->StorageClass |= StorageClass;
|
||||
} else if ((Spec->StorageClass & SC_STORAGEMASK) == StorageClass) {
|
||||
Warning ("Duplicate storage class specifier");
|
||||
} else {
|
||||
Error ("Conflicting storage class specifier");
|
||||
@ -618,12 +618,12 @@ static SymEntry* ForwardESU (const char* Name, unsigned Flags, unsigned* DSFlags
|
||||
*/
|
||||
SymEntry* TagEntry = FindTagSym (Name);
|
||||
if (TagEntry == 0) {
|
||||
if ((Flags & SC_ESUTYPEMASK) != SC_ENUM) {
|
||||
if ((Flags & SC_TYPEMASK) != SC_ENUM) {
|
||||
TagEntry = AddStructSym (Name, Flags, 0, 0, DSFlags);
|
||||
} else {
|
||||
TagEntry = AddEnumSym (Name, Flags, 0, 0, DSFlags);
|
||||
}
|
||||
} else if ((TagEntry->Flags & SC_TYPEMASK) != (Flags & SC_ESUTYPEMASK)) {
|
||||
} else if ((TagEntry->Flags & SC_TYPEMASK) != (Flags & SC_TYPEMASK)) {
|
||||
/* Already defined, but not the same type class */
|
||||
Error ("Symbol '%s' is already different kind", Name);
|
||||
}
|
||||
@ -798,7 +798,7 @@ static SymEntry* ParseEnumSpec (const char* Name, unsigned* DSFlags)
|
||||
}
|
||||
|
||||
/* Add an entry of the enumerator to the symbol table */
|
||||
AddConstSym (Ident, NewType, SC_ENUMERATOR | SC_CONST, EnumVal);
|
||||
AddConstSym (Ident, NewType, SC_DEF | SC_ENUMERATOR, EnumVal);
|
||||
|
||||
/* Use this type for following members */
|
||||
MemberType = NewType;
|
||||
@ -1825,8 +1825,8 @@ static void ParseOldStyleParamDeclList (FuncDesc* F attribute ((unused)))
|
||||
/* We accept only auto and register as storage class specifiers, but
|
||||
** we ignore all this, since we use auto anyway.
|
||||
*/
|
||||
if ((Spec.StorageClass & SC_AUTO) == 0 &&
|
||||
(Spec.StorageClass & SC_REGISTER) == 0) {
|
||||
if ((Spec.StorageClass & SC_STORAGEMASK) != SC_AUTO &&
|
||||
(Spec.StorageClass & SC_STORAGEMASK) != SC_REGISTER) {
|
||||
Error ("Illegal storage class");
|
||||
}
|
||||
|
||||
@ -1942,12 +1942,12 @@ static void ParseAnsiParamList (FuncDesc* F)
|
||||
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_NONE, SC_AUTO);
|
||||
|
||||
/* We accept only auto and register as storage class specifiers */
|
||||
if ((Spec.StorageClass & SC_AUTO) == SC_AUTO) {
|
||||
Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
|
||||
} else if ((Spec.StorageClass & SC_REGISTER) == SC_REGISTER) {
|
||||
Spec.StorageClass = SC_REGISTER | SC_STATIC | SC_PARAM | SC_DEF;
|
||||
if ((Spec.StorageClass & SC_STORAGEMASK) == SC_REGISTER) {
|
||||
Spec.StorageClass = SC_REGISTER | SC_PARAM | SC_DEF;
|
||||
} else {
|
||||
if ((Spec.StorageClass & SC_STORAGEMASK) != SC_AUTO) {
|
||||
Error ("Illegal storage class");
|
||||
}
|
||||
Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
|
||||
}
|
||||
|
||||
@ -2355,7 +2355,9 @@ int ParseDecl (DeclSpec* Spec, Declarator* D, declmode_t Mode)
|
||||
D->StorageClass = Spec->StorageClass;
|
||||
|
||||
/* If we have a function, add a special symbol type */
|
||||
if (IsTypeFunc (D->Type)) {
|
||||
if (Mode != DM_ACCEPT_PARAM_IDENT &&
|
||||
IsTypeFunc (D->Type) &&
|
||||
(D->StorageClass & SC_TYPEMASK) == SC_NONE) {
|
||||
D->StorageClass |= SC_FUNC;
|
||||
}
|
||||
|
||||
@ -2479,9 +2481,9 @@ void ParseDeclSpec (DeclSpec* Spec, typespec_t TSFlags, unsigned DefStorage)
|
||||
ParseTypeSpec (Spec, TSFlags | TS_STORAGE_CLASS_SPEC | TS_FUNCTION_SPEC);
|
||||
|
||||
/* If no explicit storage class is given, use the default */
|
||||
if (Spec->StorageClass == 0) {
|
||||
if ((Spec->StorageClass & SC_STORAGEMASK) == 0) {
|
||||
Spec->Flags |= DS_DEF_STORAGE;
|
||||
Spec->StorageClass = DefStorage;
|
||||
Spec->StorageClass |= DefStorage;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1223,8 +1223,8 @@ static void Primary (ExprDesc* E)
|
||||
NextToken ();
|
||||
|
||||
/* Check for illegal symbol types */
|
||||
CHECK ((Sym->Flags & SC_LABEL) != SC_LABEL);
|
||||
if (Sym->Flags & SC_ESUTYPEMASK) {
|
||||
CHECK ((Sym->Flags & SC_TYPEMASK) != SC_LABEL);
|
||||
if ((Sym->Flags & SC_TYPEMASK) == SC_TYPEDEF) {
|
||||
/* Cannot use type symbols */
|
||||
Error ("Variable identifier expected");
|
||||
/* Assume an int type to make E valid */
|
||||
@ -1244,7 +1244,7 @@ static void Primary (ExprDesc* E)
|
||||
/* Enum or some other numeric constant */
|
||||
E->Flags = E_LOC_NONE | E_RTYPE_RVAL;
|
||||
E->IVal = Sym->V.ConstVal;
|
||||
} else if ((Sym->Flags & SC_AUTO) == SC_AUTO) {
|
||||
} else if ((Sym->Flags & SC_STORAGEMASK) == SC_AUTO) {
|
||||
/* Local variable. If this is a parameter for a variadic
|
||||
** function, we have to add some address calculations, and the
|
||||
** address is not const.
|
||||
@ -1258,25 +1258,24 @@ static void Primary (ExprDesc* E)
|
||||
E->Flags = E_LOC_STACK | E_RTYPE_LVAL;
|
||||
E->IVal = Sym->V.Offs;
|
||||
}
|
||||
} else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
|
||||
} else if ((Sym->Flags & SC_TYPEMASK) == SC_FUNC) {
|
||||
/* Function */
|
||||
E->Flags = E_LOC_GLOBAL | E_RTYPE_LVAL;
|
||||
E->Name = (uintptr_t) Sym->Name;
|
||||
} else if ((Sym->Flags & SC_REGISTER) == SC_REGISTER) {
|
||||
} else if ((Sym->Flags & SC_STORAGEMASK) == SC_REGISTER) {
|
||||
/* Register variable, zero page based */
|
||||
E->Flags = E_LOC_REGISTER | E_RTYPE_LVAL;
|
||||
E->Name = Sym->V.R.RegOffs;
|
||||
} else if ((Sym->Flags & SC_STATIC) == SC_STATIC) {
|
||||
/* Static variable */
|
||||
if (Sym->Flags & (SC_EXTERN | SC_STORAGE | SC_DECL)) {
|
||||
} else if (SymIsGlobal (Sym)) {
|
||||
/* Global variable */
|
||||
E->Flags = E_LOC_GLOBAL | E_RTYPE_LVAL;
|
||||
E->Name = (uintptr_t) Sym->Name;
|
||||
} else {
|
||||
} else if ((Sym->Flags & SC_STORAGEMASK) == SC_STATIC) {
|
||||
/* Local static variable */
|
||||
E->Flags = E_LOC_STATIC | E_RTYPE_LVAL;
|
||||
E->Name = Sym->V.L.Label;
|
||||
}
|
||||
} else {
|
||||
/* Local static variable */
|
||||
/* Other */
|
||||
E->Flags = E_LOC_STATIC | E_RTYPE_LVAL;
|
||||
E->Name = Sym->V.Offs;
|
||||
}
|
||||
@ -1311,7 +1310,7 @@ static void Primary (ExprDesc* E)
|
||||
} else {
|
||||
Warning ("Call to undeclared function '%s'", Ident);
|
||||
}
|
||||
Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC);
|
||||
Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_REF | SC_FUNC);
|
||||
E->Type = Sym->Type;
|
||||
E->Flags = E_LOC_GLOBAL | E_RTYPE_RVAL;
|
||||
E->Name = (uintptr_t) Sym->Name;
|
||||
|
@ -98,7 +98,7 @@ enum {
|
||||
E_LOC_NONE = 0x0000, /* Pure rvalue with no storage */
|
||||
E_LOC_ABS = 0x0001, /* Absolute numeric addressed variable */
|
||||
E_LOC_GLOBAL = 0x0002, /* Global variable */
|
||||
E_LOC_STATIC = 0x0004, /* Static variable */
|
||||
E_LOC_STATIC = 0x0004, /* Local static variable */
|
||||
E_LOC_REGISTER = 0x0008, /* Register variable */
|
||||
E_LOC_STACK = 0x0010, /* Value on the stack */
|
||||
E_LOC_PRIMARY = 0x0020, /* Temporary in primary register */
|
||||
|
@ -92,7 +92,7 @@ void GotoStatement (void)
|
||||
|
||||
/* Find array size */
|
||||
if (!IsTypeArray (arr->Type) || SizeOf (arr->Type) == 0 ||
|
||||
!(arr->Flags & SC_STATIC) ||
|
||||
(arr->Flags & SC_STORAGEMASK) != SC_STATIC ||
|
||||
SizeOf (GetElementType(arr->Type)) != 2) {
|
||||
Error ("Expected a static array");
|
||||
} else if (GetElementCount (arr->Type) > 127) {
|
||||
|
@ -304,7 +304,7 @@ static void ParseAutoDecl (Declarator* Decl)
|
||||
|
||||
|
||||
/* Static local variables. */
|
||||
Decl->StorageClass = (Decl->StorageClass & ~SC_AUTO) | SC_STATIC;
|
||||
Decl->StorageClass = (Decl->StorageClass & ~SC_STORAGEMASK) | SC_STATIC;
|
||||
|
||||
/* Generate a label, but don't define it */
|
||||
DataLabel = GetLocalDataLabel ();
|
||||
@ -451,24 +451,27 @@ static int ParseOneDecl (DeclSpec* Spec)
|
||||
/* Read the declarator */
|
||||
NeedClean = ParseDecl (Spec, &Decl, DM_IDENT_OR_EMPTY);
|
||||
|
||||
/* Check if there are any non-extern storage classes set for function
|
||||
** declarations. Function can only be declared inside functions with the
|
||||
** 'extern' storage class specifier or no storage class specifier at all.
|
||||
/* Check if there are explicitly specified non-external storage classes
|
||||
** for function declarations.
|
||||
*/
|
||||
if ((Decl.StorageClass & SC_TYPEMASK) == SC_FUNC) {
|
||||
/* Function can only be declared inside functions with the 'extern'
|
||||
** storage class specifier or no storage class specifier at all.
|
||||
** Note: this declaration is always checked for compatibility with
|
||||
** other declarations of the same symbol, but does not necessarily
|
||||
** make the symbol globally visible. This is tricky.
|
||||
*/
|
||||
if ((Decl.StorageClass & SC_FUNC) == SC_FUNC) {
|
||||
|
||||
/* Check if there are explicitly specified non-external storage classes */
|
||||
if ((Spec->Flags & DS_DEF_STORAGE) != DS_DEF_STORAGE &&
|
||||
(Decl.StorageClass & SC_EXTERN) == 0 &&
|
||||
(Decl.StorageClass & SC_STORAGEMASK) != SC_EXTERN &&
|
||||
(Decl.StorageClass & SC_STORAGEMASK) != 0) {
|
||||
Error ("Illegal storage class on function");
|
||||
}
|
||||
|
||||
/* The default storage class could be wrong. Just clear them */
|
||||
Decl.StorageClass &= ~SC_STORAGEMASK;
|
||||
|
||||
/* This is always an extern declaration */
|
||||
Decl.StorageClass |= SC_DECL | SC_EXTERN;
|
||||
} else if ((Decl.StorageClass & SC_STORAGEMASK) != SC_EXTERN) {
|
||||
/* If the symbol is not marked as external, it will be defined now */
|
||||
Decl.StorageClass |= SC_DEF;
|
||||
}
|
||||
|
||||
/* If we don't have a name, this was flagged as an error earlier.
|
||||
@ -478,12 +481,6 @@ static int ParseOneDecl (DeclSpec* Spec)
|
||||
AnonName (Decl.Ident, "param");
|
||||
}
|
||||
|
||||
/* If the symbol is not marked as external, it will be defined now */
|
||||
if ((Decl.StorageClass & SC_DECL) == 0 &&
|
||||
(Decl.StorageClass & SC_EXTERN) == 0) {
|
||||
Decl.StorageClass |= SC_DEF;
|
||||
}
|
||||
|
||||
/* Handle anything that needs storage (no functions, no typdefs) */
|
||||
if ((Decl.StorageClass & SC_DEF) == SC_DEF &&
|
||||
(Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF) {
|
||||
@ -492,20 +489,20 @@ static int ParseOneDecl (DeclSpec* Spec)
|
||||
** convert the declaration to "auto" if this is not possible.
|
||||
*/
|
||||
int Reg = 0; /* Initialize to avoid gcc complains */
|
||||
if ((Decl.StorageClass & SC_REGISTER) != 0 &&
|
||||
if ((Decl.StorageClass & SC_STORAGEMASK) == SC_REGISTER &&
|
||||
(Reg = F_AllocRegVar (CurrentFunc, Decl.Type)) < 0) {
|
||||
/* No space for this register variable, convert to auto */
|
||||
Decl.StorageClass = (Decl.StorageClass & ~SC_REGISTER) | SC_AUTO;
|
||||
Decl.StorageClass = (Decl.StorageClass & ~SC_STORAGEMASK) | SC_AUTO;
|
||||
}
|
||||
|
||||
/* Check the variable type */
|
||||
if ((Decl.StorageClass & SC_REGISTER) == SC_REGISTER) {
|
||||
if ((Decl.StorageClass & SC_STORAGEMASK) == SC_REGISTER) {
|
||||
/* Register variable */
|
||||
ParseRegisterDecl (&Decl, Reg);
|
||||
} else if ((Decl.StorageClass & SC_AUTO) == SC_AUTO) {
|
||||
} else if ((Decl.StorageClass & SC_STORAGEMASK) == SC_AUTO) {
|
||||
/* Auto variable */
|
||||
ParseAutoDecl (&Decl);
|
||||
} else if ((Decl.StorageClass & SC_STATIC) == SC_STATIC) {
|
||||
} else if ((Decl.StorageClass & SC_STORAGEMASK) == SC_STATIC) {
|
||||
/* Static variable */
|
||||
ParseStaticDecl (&Decl);
|
||||
} else {
|
||||
@ -514,7 +511,7 @@ static int ParseOneDecl (DeclSpec* Spec)
|
||||
|
||||
} else {
|
||||
|
||||
if ((Decl.StorageClass & SC_EXTERN) == SC_EXTERN) {
|
||||
if ((Decl.StorageClass & SC_STORAGEMASK) == SC_EXTERN) {
|
||||
/* External identifier - may not get initialized */
|
||||
if (CurTok.Tok == TOK_ASSIGN) {
|
||||
Error ("Cannot initialize extern variable '%s'", Decl.Ident);
|
||||
@ -524,8 +521,8 @@ static int ParseOneDecl (DeclSpec* Spec)
|
||||
}
|
||||
}
|
||||
|
||||
if ((Decl.StorageClass & SC_EXTERN) == SC_EXTERN ||
|
||||
(Decl.StorageClass & SC_FUNC) == SC_FUNC) {
|
||||
if ((Decl.StorageClass & SC_STORAGEMASK) == SC_EXTERN ||
|
||||
(Decl.StorageClass & SC_TYPEMASK) == SC_FUNC) {
|
||||
/* Add the global symbol to both of the global and local symbol
|
||||
** tables.
|
||||
*/
|
||||
|
@ -630,7 +630,7 @@ static void WrappedCallPragma (pragma_scope_t Scope, StrBuf* B)
|
||||
Entry = FindSym(Name);
|
||||
|
||||
/* Check if the name is valid */
|
||||
if (Entry && (Entry->Flags & SC_FUNC) == SC_FUNC) {
|
||||
if (Entry && (Entry->Flags & SC_TYPEMASK) == SC_FUNC) {
|
||||
|
||||
PushWrappedCall(Entry, (unsigned int) Val);
|
||||
Entry->Flags |= SC_REF;
|
||||
|
@ -88,7 +88,7 @@ void FreeSymEntry (SymEntry* E)
|
||||
TypeFree (E->Type);
|
||||
xfree (E->AsmName);
|
||||
|
||||
if (E->Flags & SC_LABEL) {
|
||||
if ((E->Flags & SC_TYPEMASK) == SC_LABEL) {
|
||||
for (i = 0; i < CollCount (E->V.L.DefsOrRefs); i++) {
|
||||
xfree (CollAt (E->V.L.DefsOrRefs, i));
|
||||
}
|
||||
@ -109,21 +109,17 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
|
||||
unsigned Val;
|
||||
} SCFlagTable;
|
||||
|
||||
static SCFlagTable ESUTypes[] = {
|
||||
{ "SC_TYPEDEF", SC_TYPEDEF },
|
||||
{ "SC_UNION", SC_UNION },
|
||||
{ "SC_STRUCT", SC_STRUCT },
|
||||
{ "SC_ENUM", SC_ENUM },
|
||||
};
|
||||
|
||||
static SCFlagTable Types[] = {
|
||||
{ "SC_BITFIELD", SC_BITFIELD },
|
||||
{ "SC_STRUCTFIELD", SC_STRUCTFIELD },
|
||||
{ "SC_ENUMERATOR", SC_ENUMERATOR },
|
||||
{ "SC_CONST", SC_CONST },
|
||||
{ "SC_NONE", SC_NONE },
|
||||
{ "SC_STRUCT", SC_STRUCT },
|
||||
{ "SC_UNION", SC_UNION },
|
||||
{ "SC_ENUM", SC_ENUM },
|
||||
{ "SC_LABEL", SC_LABEL },
|
||||
{ "SC_PARAM", SC_PARAM },
|
||||
{ "SC_BITFIELD", SC_BITFIELD },
|
||||
{ "SC_TYPEDEF", SC_TYPEDEF },
|
||||
{ "SC_ENUMERATOR", SC_ENUMERATOR },
|
||||
{ "SC_FUNC", SC_FUNC },
|
||||
{ "SC_ARRAY", SC_ARRAY },
|
||||
};
|
||||
|
||||
static SCFlagTable Storages[] = {
|
||||
@ -131,11 +127,31 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
|
||||
{ "SC_REGISTER", SC_REGISTER },
|
||||
{ "SC_STATIC", SC_STATIC },
|
||||
{ "SC_EXTERN", SC_EXTERN },
|
||||
{ "SC_STORAGE", SC_STORAGE },
|
||||
};
|
||||
|
||||
static SCFlagTable Properties[] = {
|
||||
{ "SC_CONST", SC_CONST },
|
||||
{ "SC_STRUCTFIELD", SC_STRUCTFIELD },
|
||||
{ "SC_PARAM", SC_PARAM },
|
||||
{ "SC_DEFTYPE", SC_DEFTYPE },
|
||||
{ "SC_ZEROPAGE", SC_ZEROPAGE },
|
||||
{ "SC_DECL", SC_DECL },
|
||||
{ "SC_HAVEALIGN", SC_HAVEALIGN },
|
||||
{ "SC_HAVEATTR", SC_HAVEATTR },
|
||||
{ "SC_TU_STORAGE", SC_TU_STORAGE },
|
||||
{ "SC_ASSIGN_INIT", SC_ASSIGN_INIT },
|
||||
{ "SC_ALIAS", SC_ALIAS },
|
||||
{ "SC_FICTITIOUS", SC_FICTITIOUS },
|
||||
{ "SC_HAVEFAM", SC_HAVEFAM },
|
||||
{ "SC_HAVECONST", SC_HAVECONST },
|
||||
};
|
||||
|
||||
static SCFlagTable Status[] = {
|
||||
{ "SC_DEF", SC_DEF },
|
||||
{ "SC_REF", SC_REF },
|
||||
{ "SC_GOTO", SC_GOTO },
|
||||
{ "SC_GOTO_IND", SC_GOTO_IND },
|
||||
{ "SC_LOCALSCOPE", SC_LOCALSCOPE },
|
||||
{ "SC_NOINLINEDEF", SC_NOINLINEDEF },
|
||||
};
|
||||
|
||||
unsigned I;
|
||||
@ -152,28 +168,38 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
|
||||
/* Print the flags */
|
||||
SymFlags = E->Flags;
|
||||
fprintf (F, " Flags:");
|
||||
/* Enum, struct, union and typedefs */
|
||||
if ((SymFlags & SC_ESUTYPEMASK) != 0) {
|
||||
for (I = 0; I < sizeof (ESUTypes) / sizeof (ESUTypes[0]); ++I) {
|
||||
if ((SymFlags & SC_ESUTYPEMASK) == ESUTypes[I].Val) {
|
||||
SymFlags &= ~SC_ESUTYPEMASK;
|
||||
fprintf (F, " %s", ESUTypes[I].Name);
|
||||
/* Symbol types */
|
||||
if ((SymFlags & SC_TYPEMASK) != 0) {
|
||||
for (I = 0; I < sizeof (Types) / sizeof (Types[0]); ++I) {
|
||||
if ((SymFlags & SC_TYPEMASK) == Types[I].Val) {
|
||||
SymFlags &= ~SC_TYPEMASK;
|
||||
fprintf (F, " %s", Types[I].Name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Other type flags */
|
||||
for (I = 0; I < sizeof (Types) / sizeof (Types[0]) && SymFlags != 0; ++I) {
|
||||
if ((SymFlags & Types[I].Val) == Types[I].Val) {
|
||||
SymFlags &= ~Types[I].Val;
|
||||
fprintf (F, " %s", Types[I].Name);
|
||||
}
|
||||
}
|
||||
/* Storage flags */
|
||||
for (I = 0; I < sizeof (Storages) / sizeof (Storages[0]) && SymFlags != 0; ++I) {
|
||||
if ((SymFlags & Storages[I].Val) == Storages[I].Val) {
|
||||
SymFlags &= ~Storages[I].Val;
|
||||
/* Storage classes */
|
||||
if ((SymFlags & SC_STORAGEMASK) != 0) {
|
||||
for (I = 0; I < sizeof (Storages) / sizeof (Storages[0]); ++I) {
|
||||
if ((SymFlags & SC_STORAGEMASK) == Storages[I].Val) {
|
||||
SymFlags &= ~SC_STORAGEMASK;
|
||||
fprintf (F, " %s", Storages[I].Name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Special property flags */
|
||||
for (I = 0; I < sizeof (Properties) / sizeof (Properties[0]) && SymFlags != 0; ++I) {
|
||||
if ((SymFlags & Properties[I].Val) == Properties[I].Val) {
|
||||
SymFlags &= ~Properties[I].Val;
|
||||
fprintf (F, " %s", Properties[I].Name);
|
||||
}
|
||||
}
|
||||
/* Status flags */
|
||||
for (I = 0; I < sizeof (Status) / sizeof (Status[0]) && SymFlags != 0; ++I) {
|
||||
if ((SymFlags & Status[I].Val) == Status[I].Val) {
|
||||
SymFlags &= ~Status[I].Val;
|
||||
fprintf (F, " %s", Status[I].Name);
|
||||
}
|
||||
}
|
||||
if (SymFlags != 0) {
|
||||
@ -201,7 +227,8 @@ int SymIsOutputFunc (const SymEntry* Sym)
|
||||
*/
|
||||
return IsTypeFunc (Sym->Type) &&
|
||||
SymIsDef (Sym) &&
|
||||
(Sym->Flags & (SC_REF | SC_EXTERN));
|
||||
((Sym->Flags & SC_REF) ||
|
||||
(Sym->Flags & SC_STORAGEMASK) != SC_STATIC);
|
||||
}
|
||||
|
||||
|
||||
@ -272,7 +299,7 @@ void SymCvtRegVarToAuto (SymEntry* Sym)
|
||||
/* Convert a register variable to an auto variable */
|
||||
{
|
||||
/* Change the storage class */
|
||||
Sym->Flags = (Sym->Flags & ~(SC_REGISTER | SC_STATIC | SC_EXTERN)) | SC_AUTO;
|
||||
Sym->Flags = (Sym->Flags & ~SC_STORAGEMASK) | SC_AUTO;
|
||||
|
||||
/* Transfer the stack offset from register save area to actual offset */
|
||||
Sym->V.Offs = Sym->V.R.SaveOffs;
|
||||
|
@ -68,47 +68,88 @@ struct CodeEntry;
|
||||
|
||||
|
||||
|
||||
/* Storage classes and flags */
|
||||
/* Symbol types and flags */
|
||||
#define SC_NONE 0x0000U /* Nothing */
|
||||
#define SC_STRUCT 0x0001U /* Struct */
|
||||
#define SC_UNION 0x0002U /* Union */
|
||||
#define SC_ENUM 0x0003U /* Enum */
|
||||
#define SC_TYPEDEF 0x0004U /* Typedef */
|
||||
#define SC_ESUTYPEMASK 0x0007U /* Mask for above types */
|
||||
#define SC_ENUMERATOR 0x0008U /* An enumerator */
|
||||
#define SC_BITFIELD 0x0010U /* A bit-field inside a struct or union */
|
||||
#define SC_TYPEMASK 0x001FU /* Mask for above types */
|
||||
|
||||
#define SC_FUNC 0x0020U /* A function */
|
||||
#define SC_LABEL 0x0040U /* A goto code label */
|
||||
#define SC_CONST 0x0080U /* A numeric constant with a type */
|
||||
#define SC_PARAM 0x0100U /* A function parameter */
|
||||
#define SC_DEFTYPE 0x0200U /* Parameter has default type (=int, old style) */
|
||||
#define SC_STRUCTFIELD 0x0400U /* Struct or union field */
|
||||
/* Types of symbols */
|
||||
#define SC_STRUCT 0x0001U /* Struct tag */
|
||||
#define SC_UNION 0x0002U /* Union tag */
|
||||
#define SC_ENUM 0x0003U /* Enum tag */
|
||||
#define SC_LABEL 0x0004U /* A goto code label */
|
||||
#define SC_BITFIELD 0x0005U /* A bit-field inside a struct or union */
|
||||
#define SC_TYPEDEF 0x0006U /* A typedef */
|
||||
#define SC_ENUMERATOR 0x0007U /* An enumerator */
|
||||
|
||||
#define SC_ZEROPAGE 0x0800U /* Symbol marked as zeropage */
|
||||
/* Note: These symbol types might be checked as bit-flags occasionally.
|
||||
** So don't share their unique bits with other symbol types.
|
||||
*/
|
||||
#define SC_FUNC 0x0008U /* A function */
|
||||
#define SC_ARRAY 0x0010U /* UNUSED: An array */
|
||||
#define SC_TYPEMASK 0x001FU /* Mask for symbol types all above */
|
||||
|
||||
#define SC_DEF 0x1000U /* Symbol is defined */
|
||||
#define SC_REF 0x2000U /* Symbol is referenced */
|
||||
#define SC_DECL 0x4000U /* Symbol is declared in global scope */
|
||||
#define SC_STORAGE 0x8000U /* Symbol with associated storage */
|
||||
/* Additional property of the symbols */
|
||||
#define SC_CONST 0x0020U /* A numeric constant with a type */
|
||||
#define SC_STRUCTFIELD 0x0040U /* A struct or union field */
|
||||
#define SC_PARAM 0x0080U /* A function parameter */
|
||||
#define SC_DEFTYPE 0x0100U /* An old-style parameter with default type (=int) */
|
||||
|
||||
#define SC_AUTO 0x010000U /* Auto variable */
|
||||
#define SC_REGISTER 0x020000U /* Register variable */
|
||||
#define SC_STATIC 0x040000U /* Static - not to be confused with other *_STATIC */
|
||||
#define SC_EXTERN 0x080000U /* Extern linkage */
|
||||
#define SC_STORAGEMASK 0x0F0000U /* Storage type mask */
|
||||
/* Address property of the symbol */
|
||||
#define SC_ZEROPAGE 0x0200U /* Symbol marked as on zeropage */
|
||||
|
||||
#define SC_HAVEATTR 0x100000U /* Symbol has attributes */
|
||||
/* Additional attributes of the symbol */
|
||||
#define SC_HAVEALIGN 0x0400U /* UNUSED: Symbol has special alignment */
|
||||
#define SC_HAVEATTR 0x0800U /* Symbol has attributes */
|
||||
|
||||
#define SC_GOTO 0x200000U
|
||||
#define SC_SPADJUSTMENT 0x400000U
|
||||
#define SC_GOTO_IND 0x800000U /* Indirect goto */
|
||||
/* Special property of declaration */
|
||||
#define SC_TU_STORAGE 0x1000U /* Symbol has allocated storage in the TU */
|
||||
#define SC_ASSIGN_INIT 0x2000U /* Symbol is to be initialized with assignment code */
|
||||
|
||||
#define SC_ALIAS 0x01000000U /* Alias of global or anonymous field */
|
||||
#define SC_FICTITIOUS 0x02000000U /* Symbol is fictitious (for error recovery) */
|
||||
#define SC_HAVEFAM 0x04000000U /* Type has a Flexible Array Member */
|
||||
#define SC_HAVECONST 0x08000000U /* Type has a const member */
|
||||
#define SC_ALIAS 0x4000U /* Symbol is an alias */
|
||||
#define SC_FICTITIOUS 0x8000U /* Symbol is fictitious (for error recovery) */
|
||||
#define SC_HAVEFAM 0x010000U /* Struct/union has a Flexible Array Member */
|
||||
#define SC_HAVECONST 0x020000U /* Struct/union has a const member */
|
||||
|
||||
/* Status of the symbol */
|
||||
#define SC_DEF 0x040000U /* Symbol is defined */
|
||||
#define SC_REF 0x080000U /* Symbol is referenced */
|
||||
#define SC_GOTO 0x100000U /* Symbol is destination of a goto */
|
||||
#define SC_GOTO_IND 0x200000U /* Symbol is destination of an indirect goto */
|
||||
#define SC_LOCALSCOPE 0x400000U /* Symbol is invisible in file scope */
|
||||
#define SC_NOINLINEDEF 0x800000U /* Symbol may never have an inline definition */
|
||||
|
||||
/* To figure out the linkage of an object or function symbol Sym:
|
||||
** - external linkage:
|
||||
** SymIsGlobal (Sym) && (Sym->Flags & SC_STORAGEMASK) != SC_STATIC
|
||||
** - internal linkage:
|
||||
** SymIsGlobal (Sym) && (Sym->Flags & SC_STORAGEMASK) == SC_STATIC
|
||||
** - no linkage:
|
||||
** !SymIsGlobal (Sym)
|
||||
**
|
||||
** To figure out the storage class of a symbol by its SC_ flags:
|
||||
**
|
||||
** - no explicit storage class specifiers (in file scope):
|
||||
** (flags & SC_STORAGEMASK) == SC_NONE
|
||||
** - no explicit storage class specifiers (in block scope):
|
||||
** (flags & SC_STORAGEMASK) == SC_AUTO
|
||||
** - extern:
|
||||
** (flags & SC_STORAGEMASK) == SC_EXTERN
|
||||
** - static:
|
||||
** (flags & SC_STORAGEMASK) == SC_STATIC
|
||||
** - auto:
|
||||
** (flags & SC_STORAGEMASK) == SC_AUTO
|
||||
** - register:
|
||||
** (flags & SC_STORAGEMASK) == SC_REGISTER
|
||||
** - typedef (per ISO C):
|
||||
** (flags & SC_TYPEMASK) == SC_TYPEDEF
|
||||
**
|
||||
** Note: SC_TYPEDEF can be also used as a flag.
|
||||
*/
|
||||
#define SC_AUTO 0x01000000U /* Auto storage class */
|
||||
#define SC_REGISTER 0x02000000U /* Register storage class */
|
||||
#define SC_STATIC 0x03000000U /* Static storage class */
|
||||
#define SC_EXTERN 0x04000000U /* Extern storage class */
|
||||
#define SC_THREAD 0x08000000U /* UNSUPPORTED: Thread-local storage class */
|
||||
#define SC_STORAGEMASK 0x0F000000U /* Storage type mask */
|
||||
|
||||
|
||||
|
||||
@ -214,14 +255,37 @@ void FreeSymEntry (SymEntry* E);
|
||||
void DumpSymEntry (FILE* F, const SymEntry* E);
|
||||
/* Dump the given symbol table entry to the file in readable form */
|
||||
|
||||
int SymIsOutputFunc (const SymEntry* Sym);
|
||||
/* Return true if this is a function that must be output */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymIsArray (const SymEntry* Sym)
|
||||
/* Return true if the given entry is an array entry */
|
||||
{
|
||||
return ((Sym->Flags & SC_TYPEMASK) == SC_ARRAY);
|
||||
}
|
||||
#else
|
||||
# define SymIsArray(Sym) (((Sym)->Flags & SC_TYPEMASK) == SC_ARRAY)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymIsBitField (const SymEntry* Sym)
|
||||
/* Return true if the given entry is a bit-field entry */
|
||||
{
|
||||
return ((Sym->Flags & SC_BITFIELD) == SC_BITFIELD);
|
||||
return ((Sym->Flags & SC_TYPEMASK) == SC_BITFIELD);
|
||||
}
|
||||
#else
|
||||
# define SymIsBitField(Sym) (((Sym)->Flags & SC_BITFIELD) == SC_BITFIELD)
|
||||
# define SymIsBitField(Sym) (((Sym)->Flags & SC_TYPEMASK) == SC_BITFIELD)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymIsLabel (const SymEntry* Sym)
|
||||
/* Return true if the given entry is a label entry */
|
||||
{
|
||||
return ((Sym)->Flags & SC_TYPEMASK) == SC_LABEL;
|
||||
}
|
||||
#else
|
||||
# define SymIsLabel(Sym) (((Sym)->Flags & SC_TYPEMASK) == SC_LABEL)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
@ -257,17 +321,13 @@ INLINE int SymIsRef (const SymEntry* Sym)
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymIsRegVar (const SymEntry* Sym)
|
||||
/* Return true if the given entry is a register variable */
|
||||
/* ### HACK! Fix the ugly type flags! */
|
||||
{
|
||||
return ((Sym->Flags & (SC_REGISTER | SC_TYPEMASK)) == SC_REGISTER);
|
||||
return ((Sym->Flags & (SC_STORAGEMASK | SC_TYPEMASK)) == (SC_REGISTER | SC_NONE));
|
||||
}
|
||||
#else
|
||||
# define SymIsRegVar(Sym) (((Sym)->Flags & (SC_REGISTER | SC_TYPEMASK)) == SC_REGISTER)
|
||||
# define SymIsRegVar(Sym) (((Sym)->Flags & (SC_STORAGEMASK | SC_TYPEMASK)) == (SC_REGISTER | SC_NONE))
|
||||
#endif
|
||||
|
||||
int SymIsOutputFunc (const SymEntry* Sym);
|
||||
/* Return true if this is a function that must be output */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymHasFlexibleArrayMember (const SymEntry* Sym)
|
||||
/* Return true if the given entry has a flexible array member */
|
||||
|
@ -165,22 +165,22 @@ static void CheckSymTable (SymTable* Tab)
|
||||
/* Ignore typedef entries */
|
||||
if (!SymIsTypeDef (Entry)) {
|
||||
|
||||
/* Check if the symbol is one with storage, and it if it was
|
||||
** defined but not used.
|
||||
*/
|
||||
if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) {
|
||||
/* Check if the symbol has non-external linkage and is defined but not used */
|
||||
if (!SymIsGlobal (Entry) || (Flags & SC_STORAGEMASK) == SC_STATIC) {
|
||||
if (SymIsDef (Entry) && !SymIsRef (Entry) &&
|
||||
!SymHasAttr (Entry, atUnused)) {
|
||||
if (Flags & SC_PARAM) {
|
||||
if (IS_Get (&WarnUnusedParam)) {
|
||||
Warning ("Parameter '%s' is never used", Entry->Name);
|
||||
}
|
||||
} else if (Flags & SC_FUNC) {
|
||||
} else if ((Flags & SC_TYPEMASK) == SC_FUNC) {
|
||||
if (IS_Get (&WarnUnusedFunc)) {
|
||||
Warning ("Function '%s' is defined but never used", Entry->Name);
|
||||
}
|
||||
} else if (!IsAnonName (Entry->Name)) {
|
||||
if (IS_Get (&WarnUnusedVar)) {
|
||||
} else if ((Flags & SC_TYPEMASK) == SC_NONE) {
|
||||
if (IS_Get (&WarnUnusedVar) &&
|
||||
!IsAnonName (Entry->Name) &&
|
||||
(Flags & SC_CONST) != SC_CONST) {
|
||||
Warning ("Variable '%s' is defined but never used", Entry->Name);
|
||||
}
|
||||
}
|
||||
@ -188,7 +188,7 @@ 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_TYPEMASK) == SC_LABEL) {
|
||||
if (!SymIsDef (Entry)) {
|
||||
/* Undefined label */
|
||||
Error ("Undefined label: '%s'", Entry->Name);
|
||||
@ -716,7 +716,7 @@ static int HandleSymRedefinition (SymEntry* Sym, const Type* T, unsigned Flags)
|
||||
Sym = 0;
|
||||
}
|
||||
|
||||
} else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
|
||||
} else if ((Sym->Flags & SC_TYPEMASK) == SC_FUNC) {
|
||||
|
||||
/* In case of a function, use the new type descriptor, since it
|
||||
** contains pointers to the new symbol tables that are needed if
|
||||
@ -863,7 +863,6 @@ SymEntry* AddEnumSym (const char* Name, unsigned Flags, const Type* Type, SymTab
|
||||
} else {
|
||||
TagEntry->V.E.SymTab = Tab;
|
||||
TagEntry->V.E.Type = Type;
|
||||
TagEntry->Flags &= ~SC_DECL;
|
||||
TagEntry->Flags |= SC_DEF;
|
||||
|
||||
/* Remember this is the first definition of this type */
|
||||
@ -1047,7 +1046,7 @@ SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val
|
||||
SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
|
||||
|
||||
if (Entry) {
|
||||
if ((Entry->Flags & SC_CONST) != SC_CONST) {
|
||||
if ((Entry->Flags & SC_TYPEMASK) != (Flags & SC_TYPEMASK)) {
|
||||
Error ("Symbol '%s' is already different kind", Name);
|
||||
} else {
|
||||
Error ("Multiple definition for constant '%s'", Name);
|
||||
@ -1056,7 +1055,7 @@ SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val
|
||||
}
|
||||
|
||||
/* Create a new entry */
|
||||
Entry = NewSymEntry (Name, Flags);
|
||||
Entry = NewSymEntry (Name, Flags | SC_CONST);
|
||||
|
||||
/* We only have integer constants for now */
|
||||
Entry->Type = TypeDup (T);
|
||||
@ -1167,7 +1166,7 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
|
||||
/* Optimizer will need the information about the value of SP adjustment
|
||||
** later, so let's preserve it.
|
||||
*/
|
||||
E = NewSymEntry (LocalDataLabelName (DOR->LateSP_Label), SC_SPADJUSTMENT);
|
||||
E = NewSymEntry (LocalDataLabelName (DOR->LateSP_Label), 0);
|
||||
E->V.SPAdjustment = StackPtr - DOR->StackPtr;
|
||||
AddSymEntry (SPAdjustTab, E);
|
||||
}
|
||||
@ -1236,38 +1235,32 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
|
||||
Entry = FindSymInTable (Tab, Name, HashStr (Name));
|
||||
|
||||
if (Entry) {
|
||||
int CheckExtern = 0;
|
||||
if ((Flags & SC_STRUCTFIELD) == 0) {
|
||||
while (Entry && (Entry->Flags & SC_ALIAS) == SC_ALIAS) {
|
||||
/* Get the aliased entry */
|
||||
Entry = Entry->V.A.Field;
|
||||
/* Check for conflict with local storage class */
|
||||
CheckExtern = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* We have a symbol with this name already */
|
||||
if (HandleSymRedefinition (Entry, T, Flags)) {
|
||||
Entry = 0;
|
||||
} else if ((Flags & SC_ESUTYPEMASK) != SC_TYPEDEF) {
|
||||
} else if ((Flags & SC_TYPEMASK) != SC_TYPEDEF) {
|
||||
/* Redefinitions are not allowed */
|
||||
if (SymIsDef (Entry) && (Flags & SC_DEF) == SC_DEF) {
|
||||
Error ("Multiple definition of '%s'", Entry->Name);
|
||||
Entry = 0;
|
||||
} else if (CheckExtern) {
|
||||
if ((Flags & (SC_AUTO | SC_REGISTER)) != 0) {
|
||||
Error ("Declaration of '%s' with no linkage follows extern declaration", Name);
|
||||
Entry = 0;
|
||||
} else if ((Flags & SC_DEF) != 0 && (Flags & SC_EXTERN) == 0) {
|
||||
/* If a static declaration follows a non-static declaration,
|
||||
** then it is an error.
|
||||
*/
|
||||
Error ("Static declaration of '%s' follows extern declaration", Name);
|
||||
Entry = 0;
|
||||
}
|
||||
} else if ((Flags & SC_STRUCTFIELD) != 0) {
|
||||
Error ("Duplicate member '%s'", Entry->Name);
|
||||
Entry = 0;
|
||||
} else if (Entry->Owner == SymTab0) {
|
||||
if ((Flags & SC_STORAGEMASK) == SC_AUTO ||
|
||||
(Flags & SC_STORAGEMASK) == SC_REGISTER ||
|
||||
(Flags & SC_STORAGEMASK) == SC_STATIC) {
|
||||
Error ("Declaration of '%s' with no linkage follows extern declaration",
|
||||
Name);
|
||||
Entry = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1290,20 +1283,20 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
|
||||
Entry->Type = TypeDup (T);
|
||||
|
||||
if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD ||
|
||||
(Flags & SC_ESUTYPEMASK) == SC_TYPEDEF) {
|
||||
(Flags & SC_TYPEMASK) == SC_TYPEDEF) {
|
||||
if ((Flags & SC_ALIAS) != SC_ALIAS) {
|
||||
Entry->V.Offs = Offs;
|
||||
}
|
||||
} else if ((Flags & SC_AUTO) == SC_AUTO) {
|
||||
} else if ((Flags & SC_STORAGEMASK) == SC_AUTO) {
|
||||
Entry->V.Offs = Offs;
|
||||
} else if ((Flags & SC_REGISTER) == SC_REGISTER) {
|
||||
} else if ((Flags & SC_STORAGEMASK) == SC_REGISTER) {
|
||||
Entry->V.R.RegOffs = Offs;
|
||||
Entry->V.R.SaveOffs = StackPtr;
|
||||
} else if ((Flags & SC_EXTERN) == SC_EXTERN ||
|
||||
(Flags & SC_FUNC) == SC_FUNC) {
|
||||
} else if ((Flags & SC_STORAGEMASK) == SC_EXTERN ||
|
||||
(Flags & SC_TYPEMASK) == SC_FUNC) {
|
||||
Entry->V.L.Label = Offs;
|
||||
SymSetAsmName (Entry);
|
||||
} else if ((Flags & SC_STATIC) == SC_STATIC) {
|
||||
} else if ((Flags & SC_STORAGEMASK) == SC_STATIC) {
|
||||
/* Generate the assembler name from the data label number */
|
||||
Entry->V.L.Label = Offs;
|
||||
Entry->AsmName = xstrdup (LocalDataLabelName (Entry->V.L.Label));
|
||||
@ -1348,49 +1341,63 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
||||
Entry = FindGlobalSym (Name);
|
||||
}
|
||||
|
||||
/* Do we have a symbol with this name already? */
|
||||
if (Entry) {
|
||||
/* We have a symbol with this name already */
|
||||
/* Check if the symbol refers to some different type of things */
|
||||
if (HandleSymRedefinition (Entry, T, Flags)) {
|
||||
Entry = 0;
|
||||
} else if ((Entry->Flags & (SC_AUTO | SC_REGISTER)) != 0) {
|
||||
/* Check for local storage class conflict */
|
||||
} else if (Entry->Owner != SymTab0) {
|
||||
/* The previous declaration has no linkage. The current declaration
|
||||
** has either external or internal linkage. Either way it is an
|
||||
** error since the two declarations would be referring to different
|
||||
** objects with the same identifier.
|
||||
*/
|
||||
Error ("Extern declaration of '%s' follows declaration with no linkage",
|
||||
Name);
|
||||
Entry = 0;
|
||||
} else if ((Flags & SC_ESUTYPEMASK) != SC_TYPEDEF) {
|
||||
/* If a static declaration follows a non-static declaration, then
|
||||
** the result is undefined.
|
||||
** Most compilers choose to either give an error at compile time,
|
||||
** or remove the extern property for a link time error if used.
|
||||
} else if ((Flags & SC_TYPEMASK) != SC_TYPEDEF) {
|
||||
/* The C standard specifies that the result is undefined if the
|
||||
** same thing has both internal and external linkage. Most
|
||||
** compilers choose to either give an error at compile time, or
|
||||
** remove the external linkage for a link time error if used
|
||||
** outside the current translation unit. We choose to give an
|
||||
** error at compile time in this case.
|
||||
*/
|
||||
if (SymTab == SymTab0 &&
|
||||
(Flags & SC_EXTERN) == 0 &&
|
||||
(Entry->Flags & SC_EXTERN) != 0) {
|
||||
Error ("Static declaration of '%s' follows non-static declaration", Name);
|
||||
Entry = 0;
|
||||
} else if ((Flags & SC_EXTERN) != 0 &&
|
||||
(Entry->Owner == SymTab0 || (Entry->Flags & SC_DEF) != 0) &&
|
||||
(Entry->Flags & SC_EXTERN) == 0) {
|
||||
/* It is OK if a global extern declaration follows a global
|
||||
** non-static declaration, but an error if either of them is
|
||||
** local, as the two would be referring to different objects.
|
||||
** It is an error as well if a global non-static declaration
|
||||
** follows a global static declaration.
|
||||
if ((Entry->Flags & SC_STORAGEMASK) != SC_STATIC) {
|
||||
/* The previous declaration is a non-static declaration of an
|
||||
** object or function that has external linkage.
|
||||
*/
|
||||
if (Entry->Owner == SymTab0) {
|
||||
if ((Flags & SC_STORAGE) == 0) {
|
||||
/* The C standard specifies that a later extern declaration will keep
|
||||
** the previously declared internal or external linkage unchanged.
|
||||
** Though not required by the standard, we are warning on this case.
|
||||
if ((Flags & SC_STORAGEMASK) == SC_STATIC) {
|
||||
/* It is a static declaration of an object or function that
|
||||
** has internal linkage. Conflicted wih the previous one.
|
||||
*/
|
||||
Flags &= ~SC_EXTERN;
|
||||
Warning ("Extern declaration of '%s' follows static declaration, linkage unchanged", Name);
|
||||
} else {
|
||||
Error ("Non-static declaration of '%s' follows static declaration", Name);
|
||||
Error ("Static declaration of '%s' follows non-static declaration",
|
||||
Name);
|
||||
Entry = 0;
|
||||
}
|
||||
} else {
|
||||
Error ("Extern declaration of '%s' follows static declaration", Name);
|
||||
} else if ((Flags & SC_STORAGEMASK) != SC_STATIC) {
|
||||
/* The previous declaration is a static declaration of an
|
||||
** object or function that has internal linkage.
|
||||
*/
|
||||
if ((Flags & SC_STORAGEMASK) == SC_EXTERN ||
|
||||
(Flags & SC_TYPEMASK) == SC_FUNC) {
|
||||
/* The C standard specifies that an extern declaration
|
||||
** shall keep the previously declared internal linkage
|
||||
** unchanged. For a function declaration with no storage
|
||||
** class specifiers, it is treated as if with 'extern'.
|
||||
** We give a warning although it is not required by the
|
||||
** standard.
|
||||
*/
|
||||
Flags &= ~SC_STORAGEMASK;
|
||||
Warning ("Extern declaration of '%s' follows static declaration",
|
||||
Name);
|
||||
} else if ((Flags & SC_STORAGEMASK) == SC_NONE) {
|
||||
/* It is a non-extern-or-static declaration of an object in
|
||||
** file scope that has external linkage. Conflicted wih the
|
||||
** previous one.
|
||||
*/
|
||||
Error ("Non-static declaration of '%s' follows static declaration",
|
||||
Name);
|
||||
Entry = 0;
|
||||
}
|
||||
}
|
||||
@ -1486,14 +1493,22 @@ SymTable* GetLabelSymTab (void)
|
||||
|
||||
|
||||
|
||||
int SymIsLocal (SymEntry* Sym)
|
||||
/* Return true if the symbol is defined in the highest lexical level */
|
||||
int SymIsLocal (const SymEntry* Sym)
|
||||
/* Return true if the symbol is declared in the highest lexical level */
|
||||
{
|
||||
return (Sym->Owner == SymTab || Sym->Owner == TagTab);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int SymIsGlobal (const SymEntry* Sym)
|
||||
/* Return true if the symbol is declared in the file scope level */
|
||||
{
|
||||
return (Sym->Owner == SymTab0 || Sym->Owner == TagTab0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MakeZPSym (const char* Name)
|
||||
/* Mark the given symbol as zero page symbol */
|
||||
{
|
||||
@ -1553,7 +1568,9 @@ void EmitExternals (void)
|
||||
Entry = SymTab->SymHead;
|
||||
while (Entry) {
|
||||
unsigned Flags = Entry->Flags;
|
||||
if (Flags & SC_EXTERN) {
|
||||
if (Entry->Owner == SymTab0 &&
|
||||
(Flags & SC_STORAGEMASK) != SC_STATIC &&
|
||||
((Flags & SC_TYPEMASK) == SC_FUNC || (Flags & SC_TYPEMASK) == SC_NONE)) {
|
||||
/* Only defined or referenced externs */
|
||||
if (SymIsRef (Entry) && !SymIsDef (Entry)) {
|
||||
/* An import */
|
||||
@ -1587,18 +1604,18 @@ void EmitDebugInfo (void)
|
||||
}
|
||||
Sym = SymTab->SymHead;
|
||||
while (Sym) {
|
||||
if ((Sym->Flags & (SC_CONST | SC_TYPEMASK)) == 0) {
|
||||
if (Sym->Flags & SC_AUTO) {
|
||||
if ((Sym->Flags & SC_TYPEMASK) == 0) {
|
||||
if ((Sym->Flags & SC_STORAGEMASK) == SC_AUTO) {
|
||||
AddTextLine ("%s, \"%s\", \"00\", auto, %d",
|
||||
Head, Sym->Name, Sym->V.Offs);
|
||||
} else if (Sym->Flags & SC_REGISTER) {
|
||||
} else if ((Sym->Flags & SC_STORAGEMASK) == SC_REGISTER) {
|
||||
AddTextLine ("%s, \"%s\", \"00\", register, \"regbank\", %d",
|
||||
Head, Sym->Name, Sym->V.R.RegOffs);
|
||||
|
||||
} else if (SymIsRef (Sym) && !SymIsDef (Sym)) {
|
||||
AddTextLine ("%s, \"%s\", \"00\", %s, \"%s\"",
|
||||
Head, Sym->Name,
|
||||
(Sym->Flags & SC_EXTERN)? "extern" : "static",
|
||||
(Sym->Flags & SC_STORAGEMASK) != SC_STATIC ? "extern" : "static",
|
||||
Sym->AsmName);
|
||||
}
|
||||
}
|
||||
|
@ -211,8 +211,11 @@ SymTable* GetFieldSymTab (void);
|
||||
SymTable* GetLabelSymTab (void);
|
||||
/* Return the label symbol table */
|
||||
|
||||
int SymIsLocal (SymEntry* Sym);
|
||||
/* Return true if the symbol is defined in the highest lexical level */
|
||||
int SymIsLocal (const SymEntry* Sym);
|
||||
/* Return true if the symbol is declared in the highest lexical level */
|
||||
|
||||
int SymIsGlobal (const SymEntry* Sym);
|
||||
/* Return true if the symbol is declared in the file scope level */
|
||||
|
||||
void MakeZPSym (const char* Name);
|
||||
/* Mark the given symbol as zero page symbol */
|
||||
|
Loading…
Reference in New Issue
Block a user