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
This commit is contained in:
@@ -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)
|
static ExprNode* Factor (void)
|
||||||
{
|
{
|
||||||
ExprNode* L;
|
ExprNode* L;
|
||||||
ExprNode* N;
|
ExprNode* N;
|
||||||
SymEntry* S;
|
|
||||||
long Val;
|
long Val;
|
||||||
|
|
||||||
switch (Tok) {
|
switch (Tok) {
|
||||||
@@ -555,24 +575,14 @@ static ExprNode* Factor (void)
|
|||||||
|
|
||||||
case TOK_NAMESPACE:
|
case TOK_NAMESPACE:
|
||||||
case TOK_IDENT:
|
case TOK_IDENT:
|
||||||
/* Search for the symbol */
|
N = Symbol (ParseScopedSymName (SYM_ALLOC_NEW));
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TOK_LOCAL_IDENT:
|
||||||
|
N = Symbol (SymFindLocal (SVal, SYM_ALLOC_NEW));
|
||||||
|
NextTok ();
|
||||||
|
break;
|
||||||
|
|
||||||
case TOK_ULABEL:
|
case TOK_ULABEL:
|
||||||
N = ULabRef (IVal);
|
N = ULabRef (IVal);
|
||||||
NextTok ();
|
NextTok ();
|
||||||
|
|||||||
@@ -38,7 +38,9 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
|
#include "addrsize.h"
|
||||||
#include "assertdefs.h"
|
#include "assertdefs.h"
|
||||||
|
#include "attrib.h"
|
||||||
#include "bitops.h"
|
#include "bitops.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
|
||||||
@@ -69,7 +71,8 @@ static void PutBlockMove (const InsDesc* Ins);
|
|||||||
static void PutBitBranch (const InsDesc* Ins);
|
static void PutBitBranch (const InsDesc* Ins);
|
||||||
static void PutREP (const InsDesc* Ins);
|
static void PutREP (const InsDesc* Ins);
|
||||||
static void PutSEP (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);
|
static void PutAll (const InsDesc* Ins);
|
||||||
|
|
||||||
|
|
||||||
@@ -109,7 +112,7 @@ static const struct {
|
|||||||
{ "INC", 0x000006c, 0x00, 4, PutAll },
|
{ "INC", 0x000006c, 0x00, 4, PutAll },
|
||||||
{ "INX", 0x0000001, 0xe8, 0, PutAll },
|
{ "INX", 0x0000001, 0xe8, 0, PutAll },
|
||||||
{ "INY", 0x0000001, 0xc8, 0, PutAll },
|
{ "INY", 0x0000001, 0xc8, 0, PutAll },
|
||||||
{ "JMP", 0x0000808, 0x4c, 6, PutJmp },
|
{ "JMP", 0x0000808, 0x4c, 6, PutJMP },
|
||||||
{ "JSR", 0x0000008, 0x20, 7, PutAll },
|
{ "JSR", 0x0000008, 0x20, 7, PutAll },
|
||||||
{ "LDA", 0x080A26C, 0xa0, 0, PutAll },
|
{ "LDA", 0x080A26C, 0xa0, 0, PutAll },
|
||||||
{ "LDX", 0x080030C, 0xa2, 1, PutAll },
|
{ "LDX", 0x080030C, 0xa2, 1, PutAll },
|
||||||
@@ -403,7 +406,7 @@ static const struct {
|
|||||||
{ "ROR", 0x000006F, 0x62, 1, PutAll },
|
{ "ROR", 0x000006F, 0x62, 1, PutAll },
|
||||||
{ "RTI", 0x0000001, 0x40, 0, PutAll },
|
{ "RTI", 0x0000001, 0x40, 0, PutAll },
|
||||||
{ "RTL", 0x0000001, 0x6b, 0, PutAll },
|
{ "RTL", 0x0000001, 0x6b, 0, PutAll },
|
||||||
{ "RTS", 0x0000001, 0x60, 0, PutAll },
|
{ "RTS", 0x0000001, 0x60, 0, PutRTS },
|
||||||
{ "SBC", 0x0b8f6fc, 0xe0, 0, PutAll },
|
{ "SBC", 0x0b8f6fc, 0xe0, 0, PutAll },
|
||||||
{ "SEC", 0x0000001, 0x38, 0, PutAll },
|
{ "SEC", 0x0000001, 0x38, 0, PutAll },
|
||||||
{ "SED", 0x0000001, 0xf8, 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
|
/* 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
|
* 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
|
* 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)
|
static void PutAll (const InsDesc* Ins)
|
||||||
/* Handle all other instructions */
|
/* Handle all other instructions */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -390,63 +390,58 @@ static void OneLine (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Assemble the line */
|
/* Assemble the line */
|
||||||
if (Tok == TOK_IDENT) {
|
if (Tok == TOK_LOCAL_IDENT || (Tok == TOK_IDENT && !IsMacro (SVal))) {
|
||||||
|
|
||||||
/* Is it a macro? */
|
/* Did we have whitespace before the ident? */
|
||||||
if (IsMacro (SVal)) {
|
int HadWS = WS;
|
||||||
|
|
||||||
/* Yes, start a macro expansion */
|
/* Generate the symbol table entry, then skip the name */
|
||||||
MacExpandStart ();
|
SymEntry* Sym;
|
||||||
Done = 1;
|
if (Tok == TOK_IDENT) {
|
||||||
|
Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
|
||||||
|
} else {
|
||||||
|
Sym = SymFindLocal (SVal, SYM_ALLOC_NEW);
|
||||||
|
}
|
||||||
|
NextTok ();
|
||||||
|
|
||||||
} else {
|
/* If a colon follows, this is a label definition. If there
|
||||||
|
* is no colon, it's an assignment.
|
||||||
/* No, label. Remember the identifier, then skip it */
|
*/
|
||||||
int HadWS = WS; /* Did we have whitespace before the ident? */
|
if (Tok == TOK_EQ || Tok == TOK_ASSIGN) {
|
||||||
|
/* If it's an assign token, we have a label */
|
||||||
/* Generate the symbol table entry, then skip the name */
|
unsigned Flags = (Tok == TOK_ASSIGN)? SF_LABEL : SF_NONE;
|
||||||
SymEntry* Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
|
/* Skip the '=' */
|
||||||
NextTok ();
|
NextTok ();
|
||||||
|
/* Define the symbol with the expression following the '=' */
|
||||||
/* If a colon follows, this is a label definition. If there
|
SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags);
|
||||||
* is no colon, it's an assignment.
|
/* Don't allow anything after a symbol definition */
|
||||||
*/
|
Done = 1;
|
||||||
if (Tok == TOK_EQ || Tok == TOK_ASSIGN) {
|
} else {
|
||||||
/* If it's an assign token, we have a label */
|
/* Define a label */
|
||||||
unsigned Flags = (Tok == TOK_ASSIGN)? SF_LABEL : SF_NONE;
|
SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
|
||||||
/* Skip the '=' */
|
/* Skip the colon. If NoColonLabels is enabled, allow labels
|
||||||
NextTok ();
|
* without a colon if there is no whitespace before the
|
||||||
/* Define the symbol with the expression following the '=' */
|
* identifier.
|
||||||
SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags);
|
*/
|
||||||
/* Don't allow anything after a symbol definition */
|
if (Tok != TOK_COLON) {
|
||||||
Done = 1;
|
if (HadWS || !NoColonLabels) {
|
||||||
} else {
|
Error ("`:' expected");
|
||||||
/* Define a label */
|
/* Try some smart error recovery */
|
||||||
SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
|
if (Tok == TOK_NAMESPACE) {
|
||||||
/* Skip the colon. If NoColonLabels is enabled, allow labels
|
NextTok ();
|
||||||
* without a colon if there is no whitespace before the
|
}
|
||||||
* identifier.
|
}
|
||||||
*/
|
} else {
|
||||||
if (Tok != TOK_COLON) {
|
/* Skip the colon */
|
||||||
if (HadWS || !NoColonLabels) {
|
NextTok ();
|
||||||
Error ("`:' expected");
|
}
|
||||||
}
|
}
|
||||||
if (Tok == TOK_NAMESPACE) {
|
|
||||||
/* Smart :: handling */
|
|
||||||
NextTok ();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Skip the colon */
|
|
||||||
NextTok ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Done) {
|
if (!Done) {
|
||||||
|
|
||||||
if (TokIsPseudo (Tok)) {
|
if (Tok >= TOK_FIRSTPSEUDO && Tok <= TOK_LASTPSEUDO) {
|
||||||
/* A control command, IVal is index into table */
|
/* A control command */
|
||||||
HandlePseudo ();
|
HandlePseudo ();
|
||||||
} else if (Tok == TOK_MNEMO) {
|
} else if (Tok == TOK_MNEMO) {
|
||||||
/* A mnemonic - assemble one instruction */
|
/* 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 no memory model was given, use the default */
|
||||||
if (MemoryModel == MMODEL_UNKNOWN) {
|
if (MemoryModel == MMODEL_UNKNOWN) {
|
||||||
MemoryModel = MMODEL_NEAR;
|
SetMemoryModel (MMODEL_NEAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Intialize the target translation tables */
|
/* Intialize the target translation tables */
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ static void FuncString (void)
|
|||||||
ConsumeLParen ();
|
ConsumeLParen ();
|
||||||
|
|
||||||
/* Accept identifiers or numeric expressions */
|
/* Accept identifiers or numeric expressions */
|
||||||
if (Tok == TOK_IDENT) {
|
if (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT) {
|
||||||
/* Save the identifier, then skip it */
|
/* Save the identifier, then skip it */
|
||||||
strcpy (Buf, SVal);
|
strcpy (Buf, SVal);
|
||||||
NextTok ();
|
NextTok ();
|
||||||
|
|||||||
@@ -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)
|
void HandlePseudo (void)
|
||||||
/* Handle a pseudo instruction */
|
/* Handle a pseudo instruction */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2002 Ullrich von Bassewitz */
|
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* R<EFBFBD>merstra<EFBFBD>e 52 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* 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);
|
void HandlePseudo (void);
|
||||||
/* Handle a pseudo instruction */
|
/* Handle a pseudo instruction */
|
||||||
|
|
||||||
|
|||||||
@@ -769,8 +769,8 @@ Again:
|
|||||||
goto Again;
|
goto Again;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* An identifier */
|
/* A local identifier */
|
||||||
Tok = TOK_IDENT;
|
Tok = TOK_LOCAL_IDENT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1098,7 +1098,7 @@ CharAgain:
|
|||||||
int TokHasSVal (enum Token Tok)
|
int TokHasSVal (enum Token Tok)
|
||||||
/* Return true if the given token has an attached SVal */
|
/* 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ enum Token {
|
|||||||
TOK_EOF, /* End of input file */
|
TOK_EOF, /* End of input file */
|
||||||
TOK_SEP, /* Separator (usually newline) */
|
TOK_SEP, /* Separator (usually newline) */
|
||||||
TOK_IDENT, /* An identifier */
|
TOK_IDENT, /* An identifier */
|
||||||
|
TOK_LOCAL_IDENT, /* A cheap local identifier */
|
||||||
TOK_MNEMO, /* A mnemonic */
|
TOK_MNEMO, /* A mnemonic */
|
||||||
|
|
||||||
TOK_INTCON, /* Integer constant */
|
TOK_INTCON, /* Integer constant */
|
||||||
|
|||||||
@@ -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)
|
void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags)
|
||||||
/* Define a new symbol */
|
/* 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)
|
void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||||
/* Mark the given symbol as an imported symbol */
|
/* 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) {
|
if (S->Flags & SF_DEFINED) {
|
||||||
Error ("Symbol `%s' is already defined", GetSymName (S));
|
Error ("Symbol `%s' is already defined", GetSymName (S));
|
||||||
S->Flags |= SF_MULTDEF;
|
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)
|
void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||||
/* Mark the given symbol as an exported symbol */
|
/* 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 */
|
/* Check if it's ok to export the symbol */
|
||||||
if (S->Flags & SF_IMPORT) {
|
if (S->Flags & SF_IMPORT) {
|
||||||
/* The symbol is already marked as imported external symbol */
|
/* 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.
|
* 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.
|
/* If the symbol is already marked as import, the address size must match.
|
||||||
* Apart from that, ignore the global declaration.
|
* Apart from that, ignore the global declaration.
|
||||||
*/
|
*/
|
||||||
@@ -456,12 +464,6 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
|
|||||||
#endif
|
#endif
|
||||||
CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX);
|
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 */
|
/* Check for errors */
|
||||||
if (S->Flags & SF_IMPORT) {
|
if (S->Flags & SF_IMPORT) {
|
||||||
/* The symbol is already marked as imported external symbol */
|
/* 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)
|
int SymIsConst (SymEntry* S, long* Val)
|
||||||
/* Return true if the given symbol has a constant value. If Val is not NULL
|
/* 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.
|
* 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 */
|
/* Check for constness */
|
||||||
return (SymHasExpr (S) && IsConstExpr (S->V.Expr, Val));
|
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)
|
struct ExprNode* GetSymExpr (SymEntry* S)
|
||||||
/* Get the expression for a non-const symbol */
|
/* 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));
|
PRECONDITION (S != 0 && SymHasExpr (S));
|
||||||
return S->V.Expr;
|
return S->V.Expr;
|
||||||
}
|
}
|
||||||
@@ -630,41 +536,11 @@ const struct ExprNode* SymResolve (const SymEntry* S)
|
|||||||
* NULL. Do not call in other contexts!
|
* 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;
|
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)
|
long GetSymVal (SymEntry* S)
|
||||||
/* Return the value of a symbol assuming it's constant. FAIL will be called
|
/* Return the value of a symbol assuming it's constant. FAIL will be called
|
||||||
* in case the symbol is undefined or not constant.
|
* in case the symbol is undefined or not constant.
|
||||||
@@ -680,27 +556,9 @@ long GetSymVal (SymEntry* S)
|
|||||||
unsigned GetSymIndex (const SymEntry* S)
|
unsigned GetSymIndex (const SymEntry* S)
|
||||||
/* Return the symbol index for the given symbol */
|
/* 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);
|
PRECONDITION (S != 0 && (S->Flags & SF_INDEXED) != 0);
|
||||||
return S->Index;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,10 @@
|
|||||||
#include "cddefs.h"
|
#include "cddefs.h"
|
||||||
#include "coll.h"
|
#include "coll.h"
|
||||||
#include "filepos.h"
|
#include "filepos.h"
|
||||||
|
#include "inline.h"
|
||||||
|
|
||||||
|
/* ca65 */
|
||||||
|
#include "spool.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -54,7 +58,7 @@
|
|||||||
/* Bits for the Flags value in SymEntry */
|
/* Bits for the Flags value in SymEntry */
|
||||||
#define SF_NONE 0x0000 /* Empty flag set */
|
#define SF_NONE 0x0000 /* Empty flag set */
|
||||||
#define SF_USER 0x0001 /* User bit */
|
#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_EXPORT 0x0004 /* Export this symbol */
|
||||||
#define SF_IMPORT 0x0008 /* Import this symbol */
|
#define SF_IMPORT 0x0008 /* Import this symbol */
|
||||||
#define SF_GLOBAL 0x0010 /* Global 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)
|
#define SymDelExprRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr)
|
||||||
#endif
|
#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);
|
void SymDef (SymEntry* Sym, ExprNode* Expr, unsigned char AddrSize, unsigned Flags);
|
||||||
/* Mark a symbol as defined */
|
/* 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.
|
* 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 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 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 */
|
/* 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);
|
int SymIsConst (SymEntry* Sym, long* Val);
|
||||||
/* Return true if the given symbol has a constant value. If Val is not NULL
|
/* 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.
|
* 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 */
|
/* 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 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 */
|
/* 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 */
|
/* 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);
|
struct ExprNode* GetSymExpr (SymEntry* Sym);
|
||||||
/* Get the expression for a non-const symbol */
|
/* 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!
|
* 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 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 address size of the symbol. Beware: This function will just
|
||||||
* return the AddrSize member, it will not look at the expression!
|
* 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);
|
long GetSymVal (SymEntry* Sym);
|
||||||
/* Return the value of a symbol assuming it's constant. FAIL will be called
|
/* 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);
|
unsigned GetSymIndex (const SymEntry* Sym);
|
||||||
/* Return the symbol index for the given symbol */
|
/* 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 the position of first occurence in the source for the given symbol */
|
||||||
|
{
|
||||||
|
return &S->Pos;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define GetSymPos(S) (&(S)->Pos)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -64,9 +64,7 @@
|
|||||||
/* Combined symbol entry flags used within this module */
|
/* Combined symbol entry flags used within this module */
|
||||||
#define SF_UNDEFMASK (SF_REFERENCED | SF_DEFINED | SF_IMPORT)
|
#define SF_UNDEFMASK (SF_REFERENCED | SF_DEFINED | SF_IMPORT)
|
||||||
#define SF_UNDEFVAL (SF_REFERENCED)
|
#define SF_UNDEFVAL (SF_REFERENCED)
|
||||||
#define SF_EXPMASK (SF_TRAMPOLINE | SF_EXPORT)
|
#define SF_DBGINFOMASK (SF_UNUSED | SF_DEFINED | SF_EXPORT | SF_IMPORT)
|
||||||
#define SF_EXPVAL (SF_EXPORT)
|
|
||||||
#define SF_DBGINFOMASK (SF_TRAMPOLINE | SF_DEFINED | SF_EXPORT | SF_IMPORT)
|
|
||||||
#define SF_DBGINFOVAL (SF_DEFINED)
|
#define SF_DBGINFOVAL (SF_DEFINED)
|
||||||
|
|
||||||
/* Symbol tables */
|
/* Symbol tables */
|
||||||
@@ -74,8 +72,8 @@ SymTable* CurrentScope = 0; /* Pointer to current symbol table */
|
|||||||
SymTable* RootScope = 0; /* Root symbol table */
|
SymTable* RootScope = 0; /* Root symbol table */
|
||||||
|
|
||||||
/* Symbol table variables */
|
/* Symbol table variables */
|
||||||
static unsigned ImportCount = 0;/* Counter for import symbols */
|
static unsigned ImportCount = 0; /* Counter for import symbols */
|
||||||
static unsigned ExportCount = 0;/* Counter for export symbols */
|
static unsigned ExportCount = 0; /* Counter for export symbols */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -257,6 +255,54 @@ SymTable* SymFindAnyScope (SymTable* Parent, const char* Name)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* 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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
|
SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
|
||||||
/* Find a new symbol table entry in the given table. If AllocNew is given and
|
/* 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
|
* the entry is not found, create a new one. Return the entry found, or the
|
||||||
@@ -264,78 +310,33 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
SymEntry* S;
|
SymEntry* S;
|
||||||
int Cmp;
|
|
||||||
|
|
||||||
if (IsLocalName (Name)) {
|
/* Global symbol: Get the hash value for the name */
|
||||||
|
unsigned Hash = HashStr (Name) % Scope->TableSlots;
|
||||||
|
|
||||||
/* Local symbol, get the table */
|
/* Search for the entry */
|
||||||
if (!SymLast) {
|
int Cmp = SymSearchTree (Scope->Table[Hash], Name, &S);
|
||||||
/* 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 */
|
/* If we found an entry, return it */
|
||||||
Cmp = SymSearchTree (SymLast->Locals, Name, &S);
|
if (Cmp == 0) {
|
||||||
|
return S;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we found an entry, return it */
|
if (AllocNew) {
|
||||||
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;
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
} 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);
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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. */
|
/* 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)
|
int SymIsZP (SymEntry* S)
|
||||||
/* Return true if the symbol is explicitly marked as zeropage symbol */
|
/* 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
|
/* 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
|
* enclosing scope for a symbol with the same name, and return the ZP
|
||||||
* attribute of this symbol if we find one.
|
* attribute of this symbol if we find one.
|
||||||
@@ -443,28 +439,50 @@ static void SymCheckUndefined (SymEntry* S)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Sym) {
|
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
|
/* We found the symbol in a higher level. Transfer the flags and
|
||||||
* case it wouldn't be undefined.
|
* address size from the local symbol to that in the higher level
|
||||||
*/
|
* and check for problems.
|
||||||
if (S->Flags & SF_EXPORT) {
|
*/
|
||||||
|
if (S->Flags & SF_EXPORT) {
|
||||||
if (Sym->Flags & SF_IMPORT) {
|
if (Sym->Flags & SF_IMPORT) {
|
||||||
/* The symbol is already marked as imported external symbol */
|
/* The symbol is already marked as import */
|
||||||
PError (&S->Pos, "Symbol `%s' is already an import", GetString (S->Name));
|
PError (&S->Pos, "Symbol `%s' is already an import",
|
||||||
|
GetString (Sym->Name));
|
||||||
}
|
}
|
||||||
Sym->Flags |= (S->Flags & SF_EXPORT);
|
if (Sym->Flags & SF_EXPORT) {
|
||||||
Sym->ExportSize = S->ExportSize;
|
/* 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 the referenced flag */
|
/* Transfer all expression references */
|
||||||
Sym->Flags |= (S->Flags & SF_REFERENCED);
|
SymTransferExprRefs (S, Sym);
|
||||||
|
|
||||||
|
/* Mark the symbol as unused removing all other flags */
|
||||||
|
S->Flags = SF_UNUSED;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* The symbol is definitely undefined */
|
/* The symbol is definitely undefined */
|
||||||
@@ -474,12 +492,12 @@ static void SymCheckUndefined (SymEntry* S)
|
|||||||
GetString (S->Name));
|
GetString (S->Name));
|
||||||
} else {
|
} else {
|
||||||
if (AutoImport) {
|
if (AutoImport) {
|
||||||
/* Mark as import, will be indexed later */
|
/* Mark as import, will be indexed later */
|
||||||
S->Flags |= SF_IMPORT;
|
S->Flags |= SF_IMPORT;
|
||||||
/* Use the address size for code */
|
/* Use the address size for code */
|
||||||
S->AddrSize = CodeAddrSize;
|
S->AddrSize = CodeAddrSize;
|
||||||
} else {
|
} else {
|
||||||
/* Error */
|
/* Error */
|
||||||
PError (&S->Pos, "Symbol `%s' is undefined", GetString (S->Name));
|
PError (&S->Pos, "Symbol `%s' is undefined", GetString (S->Name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -509,9 +527,9 @@ void SymCheck (void)
|
|||||||
if (S->Flags & SF_GLOBAL) {
|
if (S->Flags & SF_GLOBAL) {
|
||||||
S->Flags &= ~SF_GLOBAL;
|
S->Flags &= ~SF_GLOBAL;
|
||||||
if (S->Flags & SF_DEFINED) {
|
if (S->Flags & SF_DEFINED) {
|
||||||
S->Flags |= SF_EXPORT;
|
S->Flags |= SF_EXPORT;
|
||||||
} else {
|
} 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
|
/* 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.
|
* we handled them in the last pass, too.
|
||||||
*/
|
*/
|
||||||
S = SymList;
|
S = SymList;
|
||||||
while (S) {
|
while (S) {
|
||||||
if ((S->Flags & SF_TRAMPOLINE) == 0 &&
|
if ((S->Flags & SF_UNUSED) == 0 &&
|
||||||
(S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) {
|
(S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) {
|
||||||
if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
|
if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
|
||||||
/* Symbol was defined but never referenced */
|
/* Symbol was defined but never referenced */
|
||||||
PWarning (&S->Pos, 2,
|
PWarning (&S->Pos, 2,
|
||||||
"Symbol `%s' is defined but never used",
|
"Symbol `%s' is defined but never used",
|
||||||
GetString (S->Name));
|
GetString (S->Name));
|
||||||
}
|
}
|
||||||
if (S->Flags & SF_IMPORT) {
|
if (S->Flags & SF_IMPORT) {
|
||||||
if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
|
if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
|
||||||
/* Imported symbol is not referenced */
|
/* Imported symbol is not referenced */
|
||||||
PWarning (&S->Pos, 2,
|
PWarning (&S->Pos, 2,
|
||||||
"Symbol `%s' is imported but never used",
|
"Symbol `%s' is imported but never used",
|
||||||
GetString (S->Name));
|
GetString (S->Name));
|
||||||
} else {
|
} else {
|
||||||
/* Give the import an index, count imports */
|
/* Give the import an index, count imports */
|
||||||
S->Index = ImportCount++;
|
S->Index = ImportCount++;
|
||||||
S->Flags |= SF_INDEXED;
|
S->Flags |= SF_INDEXED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (S->Flags & SF_EXPORT) {
|
if (S->Flags & SF_EXPORT) {
|
||||||
/* Give the export an index, count exports */
|
/* Give the export an index, count exports */
|
||||||
S->Index = ExportCount++;
|
S->Index = ExportCount++;
|
||||||
S->Flags |= SF_INDEXED;
|
S->Flags |= SF_INDEXED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -571,8 +589,8 @@ void SymDump (FILE* F)
|
|||||||
SymEntry* S = SymList;
|
SymEntry* S = SymList;
|
||||||
|
|
||||||
while (S) {
|
while (S) {
|
||||||
/* Ignore trampoline symbols */
|
/* Ignore unused symbols */
|
||||||
if ((S->Flags & SF_TRAMPOLINE) != 0) {
|
if ((S->Flags & SF_UNUSED) != 0) {
|
||||||
fprintf (F,
|
fprintf (F,
|
||||||
"%-24s %s %s %s %s %s\n",
|
"%-24s %s %s %s %s %s\n",
|
||||||
GetString (S->Name),
|
GetString (S->Name),
|
||||||
@@ -607,7 +625,7 @@ void WriteImports (void)
|
|||||||
*/
|
*/
|
||||||
S = SymList;
|
S = SymList;
|
||||||
while (S) {
|
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) {
|
(S->Flags & (SF_REFERENCED | SF_FORCED)) != 0) {
|
||||||
|
|
||||||
ObjWrite8 (S->AddrSize);
|
ObjWrite8 (S->AddrSize);
|
||||||
@@ -638,7 +656,7 @@ void WriteExports (void)
|
|||||||
/* Walk throught list and write all exports to the file */
|
/* Walk throught list and write all exports to the file */
|
||||||
S = SymList;
|
S = SymList;
|
||||||
while (S) {
|
while (S) {
|
||||||
if ((S->Flags & SF_EXPMASK) == SF_EXPVAL) {
|
if ((S->Flags & (SF_UNUSED | SF_EXPORT)) == SF_EXPORT) {
|
||||||
|
|
||||||
long ConstVal;
|
long ConstVal;
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,12 @@ SymTable* SymFindAnyScope (SymTable* Parent, const char* Name);
|
|||||||
* scope.
|
* 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);
|
SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew);
|
||||||
/* Find a new symbol table entry in the given table. If AllocNew is given and
|
/* 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
|
* the entry is not found, create a new one. Return the entry found, or the
|
||||||
|
|||||||
Reference in New Issue
Block a user