From c5cc4e15360ffac494ead549c341dcc746c546d3 Mon Sep 17 00:00:00 2001 From: cuz Date: Sat, 29 Nov 2003 07:53:26 +0000 Subject: [PATCH] Don't use SF_TRAMPOLINE, change symbol references instead. In smart mode, use RTL instead of RTS if the enclosing .PROC is far. More address size changes. git-svn-id: svn://svn.cc65.org/cc65/trunk@2696 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ca65/expr.c | 44 +++++--- src/ca65/instr.c | 25 ++++- src/ca65/main.c | 99 +++++++++--------- src/ca65/nexttok.c | 2 +- src/ca65/pseudo.c | 8 -- src/ca65/pseudo.h | 11 +- src/ca65/scanner.c | 8 +- src/ca65/scanner.h | 3 +- src/ca65/symentry.c | 194 +++++------------------------------ src/ca65/symentry.h | 105 ++++++++++++++++--- src/ca65/symtab.c | 244 ++++++++++++++++++++++++-------------------- src/ca65/symtab.h | 6 ++ 12 files changed, 362 insertions(+), 387 deletions(-) diff --git a/src/ca65/expr.c b/src/ca65/expr.c index dcb2f681e..3af3ea309 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -534,11 +534,31 @@ static ExprNode* Function (ExprNode* (*F) (void)) +static ExprNode* Symbol (SymEntry* S) +/* Reference a symbol and return an expression for it */ +{ + if (S == 0) { + /* Some weird error happened before */ + return GenLiteralExpr (0); + } else { + /* Mark the symbol as referenced */ + SymRef (S); + /* Remove the symbol if possible */ + if (SymHasExpr (S)) { + return CloneExpr (GetSymExpr (S)); + } else { + /* Create symbol node */ + return GenSymExpr (S); + } + } +} + + + static ExprNode* Factor (void) { ExprNode* L; ExprNode* N; - SymEntry* S; long Val; switch (Tok) { @@ -555,24 +575,14 @@ static ExprNode* Factor (void) case TOK_NAMESPACE: case TOK_IDENT: - /* Search for the symbol */ - S = ParseScopedSymName (SYM_ALLOC_NEW); - if (S == 0) { - /* Some weird error happened before */ - N = GenLiteralExpr (0); - } else { - /* Mark the symbol as referenced */ - SymRef (S); - /* Remove the symbol if possible */ - if (SymHasExpr (S)) { - N = CloneExpr (GetSymExpr (S)); - } else { - /* Create symbol node */ - N = GenSymExpr (S); - } - } + N = Symbol (ParseScopedSymName (SYM_ALLOC_NEW)); break; + case TOK_LOCAL_IDENT: + N = Symbol (SymFindLocal (SVal, SYM_ALLOC_NEW)); + NextTok (); + break; + case TOK_ULABEL: N = ULabRef (IVal); NextTok (); diff --git a/src/ca65/instr.c b/src/ca65/instr.c index f5dfff89b..4c5d66786 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -38,7 +38,9 @@ #include /* common */ +#include "addrsize.h" #include "assertdefs.h" +#include "attrib.h" #include "bitops.h" #include "check.h" @@ -69,7 +71,8 @@ static void PutBlockMove (const InsDesc* Ins); static void PutBitBranch (const InsDesc* Ins); static void PutREP (const InsDesc* Ins); static void PutSEP (const InsDesc* Ins); -static void PutJmp (const InsDesc* Ins); +static void PutJMP (const InsDesc* Ins); +static void PutRTS (const InsDesc* Ins); static void PutAll (const InsDesc* Ins); @@ -109,7 +112,7 @@ static const struct { { "INC", 0x000006c, 0x00, 4, PutAll }, { "INX", 0x0000001, 0xe8, 0, PutAll }, { "INY", 0x0000001, 0xc8, 0, PutAll }, - { "JMP", 0x0000808, 0x4c, 6, PutJmp }, + { "JMP", 0x0000808, 0x4c, 6, PutJMP }, { "JSR", 0x0000008, 0x20, 7, PutAll }, { "LDA", 0x080A26C, 0xa0, 0, PutAll }, { "LDX", 0x080030C, 0xa2, 1, PutAll }, @@ -403,7 +406,7 @@ static const struct { { "ROR", 0x000006F, 0x62, 1, PutAll }, { "RTI", 0x0000001, 0x40, 0, PutAll }, { "RTL", 0x0000001, 0x6b, 0, PutAll }, - { "RTS", 0x0000001, 0x60, 0, PutAll }, + { "RTS", 0x0000001, 0x60, 0, PutRTS }, { "SBC", 0x0b8f6fc, 0xe0, 0, PutAll }, { "SEC", 0x0000001, 0x38, 0, PutAll }, { "SED", 0x0000001, 0xf8, 0, PutAll }, @@ -788,7 +791,7 @@ static void PutSEP (const InsDesc* Ins) -static void PutJmp (const InsDesc* Ins) +static void PutJMP (const InsDesc* Ins) /* Handle the jump instruction for the 6502. Problem is that these chips have * a bug: If the address crosses a page, the upper byte gets not corrected and * the instruction will fail. The PutJmp function will add a linker assertion @@ -823,6 +826,20 @@ static void PutJmp (const InsDesc* Ins) +static void PutRTS (const InsDesc* Ins attribute ((unused))) +/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if + * the enclosing scope is FAR. + */ +{ + if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) { + Emit0 (0x6B); /* RTL */ + } else { + Emit0 (0x60); /* RTS */ + } +} + + + static void PutAll (const InsDesc* Ins) /* Handle all other instructions */ { diff --git a/src/ca65/main.c b/src/ca65/main.c index 31c92a198..9a159a1a4 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -390,63 +390,58 @@ static void OneLine (void) } /* Assemble the line */ - if (Tok == TOK_IDENT) { + if (Tok == TOK_LOCAL_IDENT || (Tok == TOK_IDENT && !IsMacro (SVal))) { - /* Is it a macro? */ - if (IsMacro (SVal)) { + /* Did we have whitespace before the ident? */ + int HadWS = WS; - /* Yes, start a macro expansion */ - MacExpandStart (); - Done = 1; - - } else { - - /* No, label. Remember the identifier, then skip it */ - int HadWS = WS; /* Did we have whitespace before the ident? */ - - /* Generate the symbol table entry, then skip the name */ - SymEntry* Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW); - NextTok (); - - /* If a colon follows, this is a label definition. If there - * is no colon, it's an assignment. - */ - if (Tok == TOK_EQ || Tok == TOK_ASSIGN) { - /* If it's an assign token, we have a label */ - unsigned Flags = (Tok == TOK_ASSIGN)? SF_LABEL : SF_NONE; - /* Skip the '=' */ - NextTok (); - /* Define the symbol with the expression following the '=' */ - SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags); - /* Don't allow anything after a symbol definition */ - Done = 1; - } else { - /* Define a label */ - SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL); - /* Skip the colon. If NoColonLabels is enabled, allow labels - * without a colon if there is no whitespace before the - * identifier. - */ - if (Tok != TOK_COLON) { - if (HadWS || !NoColonLabels) { - Error ("`:' expected"); - } - if (Tok == TOK_NAMESPACE) { - /* Smart :: handling */ - NextTok (); - } - } else { - /* Skip the colon */ - NextTok (); - } - } - } + /* Generate the symbol table entry, then skip the name */ + SymEntry* Sym; + if (Tok == TOK_IDENT) { + Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW); + } else { + Sym = SymFindLocal (SVal, SYM_ALLOC_NEW); + } + NextTok (); + + /* If a colon follows, this is a label definition. If there + * is no colon, it's an assignment. + */ + if (Tok == TOK_EQ || Tok == TOK_ASSIGN) { + /* If it's an assign token, we have a label */ + unsigned Flags = (Tok == TOK_ASSIGN)? SF_LABEL : SF_NONE; + /* Skip the '=' */ + NextTok (); + /* Define the symbol with the expression following the '=' */ + SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags); + /* Don't allow anything after a symbol definition */ + Done = 1; + } else { + /* Define a label */ + SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL); + /* Skip the colon. If NoColonLabels is enabled, allow labels + * without a colon if there is no whitespace before the + * identifier. + */ + if (Tok != TOK_COLON) { + if (HadWS || !NoColonLabels) { + Error ("`:' expected"); + /* Try some smart error recovery */ + if (Tok == TOK_NAMESPACE) { + NextTok (); + } + } + } else { + /* Skip the colon */ + NextTok (); + } + } } if (!Done) { - if (TokIsPseudo (Tok)) { - /* A control command, IVal is index into table */ + if (Tok >= TOK_FIRSTPSEUDO && Tok <= TOK_LASTPSEUDO) { + /* A control command */ HandlePseudo (); } else if (Tok == TOK_MNEMO) { /* A mnemonic - assemble one instruction */ @@ -670,7 +665,7 @@ int main (int argc, char* argv []) /* If no memory model was given, use the default */ if (MemoryModel == MMODEL_UNKNOWN) { - MemoryModel = MMODEL_NEAR; + SetMemoryModel (MMODEL_NEAR); } /* Intialize the target translation tables */ diff --git a/src/ca65/nexttok.c b/src/ca65/nexttok.c index 5be1dfc8a..0b1fbcd2a 100644 --- a/src/ca65/nexttok.c +++ b/src/ca65/nexttok.c @@ -339,7 +339,7 @@ static void FuncString (void) ConsumeLParen (); /* Accept identifiers or numeric expressions */ - if (Tok == TOK_IDENT) { + if (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT) { /* Save the identifier, then skip it */ strcpy (Buf, SVal); NextTok (); diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index b7059a7fe..8a277b955 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -1736,14 +1736,6 @@ static CtrlDesc CtrlCmdTab [] = { -int TokIsPseudo (unsigned Tok) -/* Return true if the given token is a pseudo instruction token */ -{ - return (Tok >= TOK_FIRSTPSEUDO && Tok <= TOK_LASTPSEUDO); -} - - - void HandlePseudo (void) /* Handle a pseudo instruction */ { diff --git a/src/ca65/pseudo.h b/src/ca65/pseudo.h index b9ebd3164..40ff9df38 100644 --- a/src/ca65/pseudo.h +++ b/src/ca65/pseudo.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2002 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 1998-2003 Ullrich von Bassewitz */ +/* Römerstraße 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -58,9 +58,6 @@ extern unsigned OpenIfs; -int TokIsPseudo (unsigned Tok); -/* Return true if the given token is a pseudo instruction token */ - void HandlePseudo (void); /* Handle a pseudo instruction */ diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 56aadd74c..d06e3d0e7 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -769,8 +769,8 @@ Again: goto Again; } - /* An identifier */ - Tok = TOK_IDENT; + /* A local identifier */ + Tok = TOK_LOCAL_IDENT; return; } @@ -1098,7 +1098,7 @@ CharAgain: int TokHasSVal (enum Token Tok) /* Return true if the given token has an attached SVal */ { - return (Tok == TOK_IDENT || Tok == TOK_STRCON); + return (Tok == TOK_IDENT || TOK_LOCAL_IDENT || Tok == TOK_STRCON); } @@ -1127,7 +1127,7 @@ int GetSubKey (const char** Keys, unsigned Count) if (!IgnoreCase) { UpcaseSVal (); } - + /* Do a linear search (a binary search is not worth the effort) */ for (I = 0; I < Count; ++I) { if (strcmp (SVal, Keys [I]) == 0) { diff --git a/src/ca65/scanner.h b/src/ca65/scanner.h index 71084168c..c958e2464 100644 --- a/src/ca65/scanner.h +++ b/src/ca65/scanner.h @@ -56,6 +56,7 @@ enum Token { TOK_EOF, /* End of input file */ TOK_SEP, /* Separator (usually newline) */ TOK_IDENT, /* An identifier */ + TOK_LOCAL_IDENT, /* A cheap local identifier */ TOK_MNEMO, /* A mnemonic */ TOK_INTCON, /* Integer constant */ @@ -214,7 +215,7 @@ enum Token { TOK_RODATA, TOK_SCOPE, TOK_SEGMENT, - TOK_SETCPU, + TOK_SETCPU, TOK_SIZEOF, TOK_SMART, TOK_STRAT, diff --git a/src/ca65/symentry.c b/src/ca65/symentry.c index 6f67ec015..257265101 100644 --- a/src/ca65/symentry.c +++ b/src/ca65/symentry.c @@ -177,6 +177,32 @@ void SymRef (SymEntry* S) +void SymTransferExprRefs (SymEntry* From, SymEntry* To) +/* Transfer all expression references from one symbol to another. */ +{ + unsigned I; + + for (I = 0; I < CollCount (&From->ExprRefs); ++I) { + + /* Get the expression node */ + ExprNode* E = CollAtUnchecked (&From->ExprRefs, I); + + /* Safety */ + CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == From); + + /* Replace the symbol reference */ + E->V.Sym = To; + + /* Add the expression reference */ + SymAddExprRef (To, E); + } + + /* Remove all symbol references from the old symbol */ + CollDeleteAll (&From->ExprRefs); +} + + + void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags) /* Define a new symbol */ { @@ -248,12 +274,6 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags) /* Mark the given symbol as an imported symbol */ { - /* Don't accept local symbols */ - if (IsLocalNameId (S->Name)) { - Error ("Illegal use of a local symbol"); - return; - } - if (S->Flags & SF_DEFINED) { Error ("Symbol `%s' is already defined", GetSymName (S)); S->Flags |= SF_MULTDEF; @@ -300,12 +320,6 @@ void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags) void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags) /* Mark the given symbol as an exported symbol */ { - /* Don't accept local symbols */ - if (IsLocalNameId (S->Name)) { - Error ("Illegal use of a local symbol"); - return; - } - /* Check if it's ok to export the symbol */ if (S->Flags & SF_IMPORT) { /* The symbol is already marked as imported external symbol */ @@ -359,12 +373,6 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags) * either imported or exported. */ { - /* Don't accept local symbols */ - if (IsLocalNameId (S->Name)) { - Error ("Illegal use of a local symbol"); - return; - } - /* If the symbol is already marked as import, the address size must match. * Apart from that, ignore the global declaration. */ @@ -456,12 +464,6 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri #endif CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX); - /* Don't accept local symbols */ - if (IsLocalNameId (S->Name)) { - Error ("Illegal use of a local symbol"); - return; - } - /* Check for errors */ if (S->Flags & SF_IMPORT) { /* The symbol is already marked as imported external symbol */ @@ -509,116 +511,20 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri -int SymIsDef (const SymEntry* S) -/* Return true if the given symbol is already defined */ -{ - return (S->Flags & SF_DEFINED) != 0; -} - - - -int SymIsRef (const SymEntry* S) -/* Return true if the given symbol has been referenced */ -{ - return (S->Flags & SF_REFERENCED) != 0; -} - - - -int SymIsImport (const SymEntry* S) -/* Return true if the given symbol is marked as import */ -{ - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - - /* Check the import flag */ - return (S->Flags & SF_IMPORT) != 0; -} - - - int SymIsConst (SymEntry* S, long* Val) /* Return true if the given symbol has a constant value. If Val is not NULL * and the symbol has a constant value, store it's value there. */ { - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - /* Check for constness */ return (SymHasExpr (S) && IsConstExpr (S->V.Expr, Val)); } -int SymHasExpr (const SymEntry* S) -/* Return true if the given symbol has an associated expression */ -{ - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - - /* Check the expression */ - return ((S->Flags & (SF_DEFINED|SF_IMPORT)) == SF_DEFINED); -} - - - -void SymMarkUser (SymEntry* S) -/* Set a user mark on the specified symbol */ -{ - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - - /* Set the bit */ - S->Flags |= SF_USER; -} - - - -void SymUnmarkUser (SymEntry* S) -/* Remove a user mark from the specified symbol */ -{ - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - - /* Reset the bit */ - S->Flags &= ~SF_USER; -} - - - -int SymHasUserMark (SymEntry* S) -/* Return the state of the user mark for the specified symbol */ -{ - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - - /* Check the bit */ - return (S->Flags & SF_USER) != 0; -} - - - struct ExprNode* GetSymExpr (SymEntry* S) /* Get the expression for a non-const symbol */ { - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - PRECONDITION (S != 0 && SymHasExpr (S)); return S->V.Expr; } @@ -630,41 +536,11 @@ const struct ExprNode* SymResolve (const SymEntry* S) * NULL. Do not call in other contexts! */ { - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - return SymHasExpr (S)? S->V.Expr : 0; } -const char* GetSymName (const SymEntry* S) -/* Return the name of the symbol */ -{ - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - return GetString (S->Name); -} - - - -unsigned char GetSymAddrSize (const SymEntry* S) -/* Return the address size of the symbol. Beware: This function will just - * return the AddrSize member, it will not look at the expression! - */ -{ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - return S->AddrSize; -} - - - long GetSymVal (SymEntry* S) /* Return the value of a symbol assuming it's constant. FAIL will be called * in case the symbol is undefined or not constant. @@ -680,27 +556,9 @@ long GetSymVal (SymEntry* S) unsigned GetSymIndex (const SymEntry* S) /* Return the symbol index for the given symbol */ { - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } PRECONDITION (S != 0 && (S->Flags & SF_INDEXED) != 0); return S->Index; } -const FilePos* GetSymPos (const SymEntry* S) -/* Return the position of first occurence in the source for the given symbol */ -{ - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - PRECONDITION (S != 0); - return &S->Pos; -} - - - - diff --git a/src/ca65/symentry.h b/src/ca65/symentry.h index a7b3bf330..ce342a830 100644 --- a/src/ca65/symentry.h +++ b/src/ca65/symentry.h @@ -42,6 +42,10 @@ #include "cddefs.h" #include "coll.h" #include "filepos.h" +#include "inline.h" + +/* ca65 */ +#include "spool.h" @@ -54,7 +58,7 @@ /* Bits for the Flags value in SymEntry */ #define SF_NONE 0x0000 /* Empty flag set */ #define SF_USER 0x0001 /* User bit */ -#define SF_TRAMPOLINE 0x0002 /* Trampoline entry */ +#define SF_UNUSED 0x0002 /* Unused entry */ #define SF_EXPORT 0x0004 /* Export this symbol */ #define SF_IMPORT 0x0008 /* Import this symbol */ #define SF_GLOBAL 0x0010 /* Global symbol */ @@ -145,6 +149,9 @@ INLINE void SymDelExprRef (SymEntry* Sym, struct ExprNode* Expr) #define SymDelExprRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr) #endif +void SymTransferExprRefs (SymEntry* From, SymEntry* To); +/* Transfer all expression references from one symbol to another. */ + void SymDef (SymEntry* Sym, ExprNode* Expr, unsigned char AddrSize, unsigned Flags); /* Mark a symbol as defined */ @@ -167,31 +174,85 @@ void SymConDes (SymEntry* Sym, unsigned char AddrSize, unsigned Type, unsigned P * mark the symbol as an export. Initializers may never be zero page symbols. */ -int SymIsDef (const SymEntry* Sym); +#if defined(HAVE_INLINE) +INLINE int SymIsDef (const SymEntry* S) /* Return true if the given symbol is already defined */ +{ + return (S->Flags & SF_DEFINED) != 0; +} +#else +# define SymIsDef(S) (((S)->Flags & SF_DEFINED) != 0) +#endif -int SymIsRef (const SymEntry* Sym); +#if defined(HAVE_INLINE) +INLINE int SymIsRef (const SymEntry* S) /* Return true if the given symbol has been referenced */ +{ + return (S->Flags & SF_REFERENCED) != 0; +} +#else +# define SymIsRef(S) (((S)->Flags & SF_REFERENCED) != 0) +#endif -int SymIsImport (const SymEntry* Sym); +#if defined(HAVE_INLINE) +INLINE int SymIsImport (const SymEntry* S) /* Return true if the given symbol is marked as import */ +{ + /* Check the import flag */ + return (S->Flags & SF_IMPORT) != 0; +} +#else +# define SymIsImport(S) (((S)->Flags & SF_IMPORT) != 0) +#endif int SymIsConst (SymEntry* Sym, long* Val); /* Return true if the given symbol has a constant value. If Val is not NULL * and the symbol has a constant value, store it's value there. */ -int SymHasExpr (const SymEntry* Sym); +#if defined(HAVE_INLINE) +INLINE int SymHasExpr (const SymEntry* S) /* Return true if the given symbol has an associated expression */ +{ + /* Check the expression */ + return ((S->Flags & (SF_DEFINED|SF_IMPORT)) == SF_DEFINED); +} +#else +# define SymHasExpr(S) (((S)->Flags & (SF_DEFINED|SF_IMPORT)) != SF_DEFINED) +#endif -void SymMarkUser (SymEntry* Sym); +#if defined(HAVE_INLINE) +INLINE void SymMarkUser (SymEntry* S) /* Set a user mark on the specified symbol */ +{ + /* Set the bit */ + S->Flags |= SF_USER; +} +#else +# define SymMarkUser(S) ((S)->Flags |= SF_USER) +#endif -void SymUnmarkUser (SymEntry* Sym); +#if defined(HAVE_INLINE) +INLINE void SymUnmarkUser (SymEntry* S) /* Remove a user mark from the specified symbol */ +{ + /* Reset the bit */ + S->Flags &= ~SF_USER; +} +#else +# define SymUnmarkUser(S) ((S)->Flags &= ~SF_USER) +#endif -int SymHasUserMark (SymEntry* Sym); +#if defined(HAVE_INLINE) +INLINE int SymHasUserMark (SymEntry* S) /* Return the state of the user mark for the specified symbol */ +{ + /* Check the bit */ + return (S->Flags & SF_USER) != 0; +} +#else +# define SymHasUserMark(S) (((S)->Flags & SF_USER) != 0) +#endif struct ExprNode* GetSymExpr (SymEntry* Sym); /* Get the expression for a non-const symbol */ @@ -201,13 +262,27 @@ const struct ExprNode* SymResolve (const SymEntry* Sym); * NULL. Do not call in other contexts! */ -const char* GetSymName (const SymEntry* Sym); +#if defined(HAVE_INLINE) +INLINE const char* GetSymName (const SymEntry* S) /* Return the name of the symbol */ +{ + return GetString (S->Name); +} +#else +# define GetSymName(S) GetString ((S)->Name) +#endif -unsigned char GetSymAddrSize (const SymEntry* Sym); +#if defined(HAVE_INLINE) +INLINE unsigned char GetSymAddrSize (const SymEntry* S) /* Return the address size of the symbol. Beware: This function will just * return the AddrSize member, it will not look at the expression! */ +{ + return S->AddrSize; +} +#else +# define GetSymAddrSize(S) ((S)->AddrSize) +#endif long GetSymVal (SymEntry* Sym); /* Return the value of a symbol assuming it's constant. FAIL will be called @@ -217,9 +292,15 @@ long GetSymVal (SymEntry* Sym); unsigned GetSymIndex (const SymEntry* Sym); /* Return the symbol index for the given symbol */ -const FilePos* GetSymPos (const SymEntry* Sym); +#if defined(HAVE_INLINE) +INLINE const FilePos* GetSymPos (const SymEntry* S) /* Return the position of first occurence in the source for the given symbol */ - +{ + return &S->Pos; +} +#else +# define GetSymPos(S) (&(S)->Pos) +#endif diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index bf6a3da81..674d92590 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -64,9 +64,7 @@ /* Combined symbol entry flags used within this module */ #define SF_UNDEFMASK (SF_REFERENCED | SF_DEFINED | SF_IMPORT) #define SF_UNDEFVAL (SF_REFERENCED) -#define SF_EXPMASK (SF_TRAMPOLINE | SF_EXPORT) -#define SF_EXPVAL (SF_EXPORT) -#define SF_DBGINFOMASK (SF_TRAMPOLINE | SF_DEFINED | SF_EXPORT | SF_IMPORT) +#define SF_DBGINFOMASK (SF_UNUSED | SF_DEFINED | SF_EXPORT | SF_IMPORT) #define SF_DBGINFOVAL (SF_DEFINED) /* Symbol tables */ @@ -74,8 +72,8 @@ SymTable* CurrentScope = 0; /* Pointer to current symbol table */ SymTable* RootScope = 0; /* Root symbol table */ /* Symbol table variables */ -static unsigned ImportCount = 0;/* Counter for import symbols */ -static unsigned ExportCount = 0;/* Counter for export symbols */ +static unsigned ImportCount = 0; /* Counter for import symbols */ +static unsigned ExportCount = 0; /* Counter for export symbols */ @@ -257,85 +255,88 @@ SymTable* SymFindAnyScope (SymTable* Parent, const char* Name) -SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew) -/* Find a new symbol table entry in the given table. If AllocNew is given and - * the entry is not found, create a new one. Return the entry found, or the - * new entry created, or - in case AllocNew is zero - return 0. +SymEntry* SymFindLocal (const char* Name, int AllocNew) +/* Find a cheap local symbol. If AllocNew is given and the entry is not + * found, create a new one. Return the entry found, or the new entry created, + * or - in case AllocNew is zero - return 0. */ { SymEntry* S; int Cmp; - if (IsLocalName (Name)) { + /* Local symbol, get the table */ + if (!SymLast) { + /* No last global, so there's no local table */ + Error ("No preceeding global symbol"); + if (AllocNew) { + return NewSymEntry (Name); + } else { + return 0; + } + } - /* Local symbol, get the table */ - if (!SymLast) { - /* No last global, so there's no local table */ - Error ("No preceeding global symbol"); - if (AllocNew) { - return NewSymEntry (Name); - } else { - return 0; - } - } + /* Search for the symbol if we have a table */ + Cmp = SymSearchTree (SymLast->Locals, Name, &S); - /* Search for the symbol if we have a table */ - Cmp = SymSearchTree (SymLast->Locals, Name, &S); + /* If we found an entry, return it */ + if (Cmp == 0) { + return S; + } - /* If we found an entry, return it */ - if (Cmp == 0) { - return S; - } + if (AllocNew) { - if (AllocNew) { + /* Otherwise create a new entry, insert and return it */ + SymEntry* N = NewSymEntry (Name); + if (S == 0) { + SymLast->Locals = N; + } else if (Cmp < 0) { + S->Left = N; + } else { + S->Right = N; + } + return N; + } - /* Otherwise create a new entry, insert and return it */ - SymEntry* N = NewSymEntry (Name); - if (S == 0) { - SymLast->Locals = N; - } else if (Cmp < 0) { - S->Left = N; - } else { - S->Right = N; - } - return N; - } + /* We did not find the entry and AllocNew is false. */ + return 0; +} - } else { - /* Global symbol: Get the hash value for the name */ - unsigned Hash = HashStr (Name) % Scope->TableSlots; - /* Search for the entry */ - Cmp = SymSearchTree (Scope->Table[Hash], Name, &S); +SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew) +/* Find a new symbol table entry in the given table. If AllocNew is given and + * the entry is not found, create a new one. Return the entry found, or the + * new entry created, or - in case AllocNew is zero - return 0. + */ +{ + SymEntry* S; - /* If we found an entry, return it */ - if (Cmp == 0) { - /* Check for a trampoline entry, in this case return the real - * symbol. - */ - while (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - return S; - } + /* Global symbol: Get the hash value for the name */ + unsigned Hash = HashStr (Name) % Scope->TableSlots; - if (AllocNew) { + /* Search for the entry */ + int Cmp = SymSearchTree (Scope->Table[Hash], Name, &S); - /* Otherwise create a new entry, insert and return it */ - SymEntry* N = NewSymEntry (Name); - if (S == 0) { - Scope->Table[Hash] = N; - } else if (Cmp < 0) { - S->Left = N; - } else { - S->Right = N; - } - N->SymTab = Scope; - ++Scope->TableEntries; - return N; + /* If we found an entry, return it */ + if (Cmp == 0) { + return S; + } + + if (AllocNew) { + + /* Otherwise create a new entry, insert and return it */ + SymEntry* N = NewSymEntry (Name); + if (S == 0) { + Scope->Table[Hash] = N; + } else if (Cmp < 0) { + S->Left = N; + } else { + S->Right = N; + } + N->SymTab = Scope; + ++Scope->TableEntries; + return N; - } } /* We did not find the entry and AllocNew is false. */ @@ -372,11 +373,6 @@ static SymEntry* SymFindAny (SymTable* Scope, const char* Name) int SymIsZP (SymEntry* S) /* Return true if the symbol is explicitly marked as zeropage symbol */ { - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - /* If the symbol is not a global symbol, was not defined before, check the * enclosing scope for a symbol with the same name, and return the ZP * attribute of this symbol if we find one. @@ -443,28 +439,50 @@ static void SymCheckUndefined (SymEntry* S) } } } + if (Sym) { - /* We found the symbol in a higher level. Make S a trampoline - * symbol. Beware: We have to transfer the symbol attributes to - * the real symbol and check for any conflicts. - */ - S->Flags |= SF_TRAMPOLINE; - S->V.Sym = Sym; - /* Transfer the flags. Note: S may not be imported, since in that - * case it wouldn't be undefined. - */ - if (S->Flags & SF_EXPORT) { + /* We found the symbol in a higher level. Transfer the flags and + * address size from the local symbol to that in the higher level + * and check for problems. + */ + if (S->Flags & SF_EXPORT) { if (Sym->Flags & SF_IMPORT) { - /* The symbol is already marked as imported external symbol */ - PError (&S->Pos, "Symbol `%s' is already an import", GetString (S->Name)); + /* The symbol is already marked as import */ + PError (&S->Pos, "Symbol `%s' is already an import", + GetString (Sym->Name)); } - Sym->Flags |= (S->Flags & SF_EXPORT); - Sym->ExportSize = S->ExportSize; - } + if (Sym->Flags & SF_EXPORT) { + /* The symbol is already marked as an export. */ + if (Sym->AddrSize > S->ExportSize) { + /* We're exporting a symbol smaller than it actually is */ + PWarning (&S->Pos, 1, "Symbol `%s' is %s but exported %s", + GetSymName (Sym), AddrSizeToStr (Sym->AddrSize), + AddrSizeToStr (S->ExportSize)); + } + } else { + /* Mark the symbol as an export */ + Sym->Flags |= SF_EXPORT; + Sym->ExportSize = S->ExportSize; + if (Sym->ExportSize == ADDR_SIZE_DEFAULT) { + /* Use the actual size of the symbol */ + Sym->ExportSize = Sym->AddrSize; + } + if (Sym->AddrSize > Sym->ExportSize) { + /* We're exporting a symbol smaller than it actually is */ + PWarning (&S->Pos, 1, "Symbol `%s' is %s but exported %s", + GetSymName (Sym), AddrSizeToStr (Sym->AddrSize), + AddrSizeToStr (Sym->ExportSize)); + } + } + } + Sym->Flags |= (S->Flags & SF_REFERENCED); + + /* Transfer all expression references */ + SymTransferExprRefs (S, Sym); - /* Transfer the referenced flag */ - Sym->Flags |= (S->Flags & SF_REFERENCED); + /* Mark the symbol as unused removing all other flags */ + S->Flags = SF_UNUSED; } else { /* The symbol is definitely undefined */ @@ -474,12 +492,12 @@ static void SymCheckUndefined (SymEntry* S) GetString (S->Name)); } else { if (AutoImport) { - /* Mark as import, will be indexed later */ - S->Flags |= SF_IMPORT; + /* Mark as import, will be indexed later */ + S->Flags |= SF_IMPORT; /* Use the address size for code */ S->AddrSize = CodeAddrSize; } else { - /* Error */ + /* Error */ PError (&S->Pos, "Symbol `%s' is undefined", GetString (S->Name)); } } @@ -509,9 +527,9 @@ void SymCheck (void) if (S->Flags & SF_GLOBAL) { S->Flags &= ~SF_GLOBAL; if (S->Flags & SF_DEFINED) { - S->Flags |= SF_EXPORT; + S->Flags |= SF_EXPORT; } else { - S->Flags |= SF_IMPORT; + S->Flags |= SF_IMPORT; } } @@ -526,35 +544,35 @@ void SymCheck (void) } /* Second pass: Walk again through the symbols. Ignore undefined's, since - * we handled them in the last pass, and ignore trampoline symbols, since + * we handled them in the last pass, and ignore unused symbols, since * we handled them in the last pass, too. */ S = SymList; while (S) { - if ((S->Flags & SF_TRAMPOLINE) == 0 && + if ((S->Flags & SF_UNUSED) == 0 && (S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) { if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) { - /* Symbol was defined but never referenced */ - PWarning (&S->Pos, 2, + /* Symbol was defined but never referenced */ + PWarning (&S->Pos, 2, "Symbol `%s' is defined but never used", GetString (S->Name)); } if (S->Flags & SF_IMPORT) { - if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) { - /* Imported symbol is not referenced */ - PWarning (&S->Pos, 2, + if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) { + /* Imported symbol is not referenced */ + PWarning (&S->Pos, 2, "Symbol `%s' is imported but never used", GetString (S->Name)); - } else { - /* Give the import an index, count imports */ - S->Index = ImportCount++; - S->Flags |= SF_INDEXED; - } + } else { + /* Give the import an index, count imports */ + S->Index = ImportCount++; + S->Flags |= SF_INDEXED; + } } if (S->Flags & SF_EXPORT) { - /* Give the export an index, count exports */ - S->Index = ExportCount++; - S->Flags |= SF_INDEXED; + /* Give the export an index, count exports */ + S->Index = ExportCount++; + S->Flags |= SF_INDEXED; } } @@ -571,8 +589,8 @@ void SymDump (FILE* F) SymEntry* S = SymList; while (S) { - /* Ignore trampoline symbols */ - if ((S->Flags & SF_TRAMPOLINE) != 0) { + /* Ignore unused symbols */ + if ((S->Flags & SF_UNUSED) != 0) { fprintf (F, "%-24s %s %s %s %s %s\n", GetString (S->Name), @@ -607,7 +625,7 @@ void WriteImports (void) */ S = SymList; while (S) { - if ((S->Flags & (SF_TRAMPOLINE | SF_IMPORT)) == SF_IMPORT && + if ((S->Flags & (SF_UNUSED | SF_IMPORT)) == SF_IMPORT && (S->Flags & (SF_REFERENCED | SF_FORCED)) != 0) { ObjWrite8 (S->AddrSize); @@ -638,7 +656,7 @@ void WriteExports (void) /* Walk throught list and write all exports to the file */ S = SymList; while (S) { - if ((S->Flags & SF_EXPMASK) == SF_EXPVAL) { + if ((S->Flags & (SF_UNUSED | SF_EXPORT)) == SF_EXPORT) { long ConstVal; diff --git a/src/ca65/symtab.h b/src/ca65/symtab.h index 20aa2a354..bc32a2c79 100644 --- a/src/ca65/symtab.h +++ b/src/ca65/symtab.h @@ -111,6 +111,12 @@ SymTable* SymFindAnyScope (SymTable* Parent, const char* Name); * scope. */ +SymEntry* SymFindLocal (const char* Name, int AllocNew); +/* Find a cheap local symbol. If AllocNew is given and the entry is not + * found, create a new one. Return the entry found, or the new entry created, + * or - in case AllocNew is zero - return 0. + */ + SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew); /* Find a new symbol table entry in the given table. If AllocNew is given and * the entry is not found, create a new one. Return the entry found, or the -- 2.39.5