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