From c13f40a9f146947f2186cc3bcca3cbed3378cc51 Mon Sep 17 00:00:00 2001 From: cuz Date: Sun, 9 Apr 2006 10:56:23 +0000 Subject: [PATCH] Emit warnings for symbols that were used suboptimal because of forward definitions. For example a zero page symbol that is used as absolute because it was undefined when encountered. git-svn-id: svn://svn.cc65.org/cc65/trunk@3724 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ca65/expr.c | 45 +++++++++++++++++++++++++++++++++++++---- src/ca65/expr.h | 11 +++++++++- src/ca65/instr.c | 16 +++++++++++---- src/ca65/symentry.c | 49 ++++++++++++++++++++++++++++++++++++--------- src/ca65/symentry.h | 43 +++++++++++++++++++++++++-------------- src/ca65/symtab.c | 21 ++++++++++++++++++- 6 files changed, 151 insertions(+), 34 deletions(-) diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 86729c021..f9258c531 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2004 Ullrich von Bassewitz */ +/* (C) 1998-2006 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -1695,11 +1695,11 @@ void WriteExpr (ExprNode* Expr) case EXPR_LITERAL: ObjWrite8 (EXPR_LITERAL); - ObjWrite32 (Expr->V.Val); - break; + ObjWrite32 (Expr->V.Val); + break; case EXPR_SYMBOL: - if (SymIsImport (Expr->V.Sym)) { + if (SymIsImport (Expr->V.Sym)) { ObjWrite8 (EXPR_SYMBOL); ObjWriteVar (GetSymIndex (Expr->V.Sym)); } else { @@ -1728,4 +1728,41 @@ void WriteExpr (ExprNode* Expr) +void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize) +/* Mark the address size of the given expression tree as guessed. The address + * size passed as argument is the one NOT used, because the actual address + * size wasn't known. Example: Zero page addressing was not used because symbol + * is undefined, and absolute addressing was available. + * This function will actually parse the expression tree for undefined symbols, + * and mark these symbols accordingly. + */ +{ + /* Accept NULL expressions */ + if (Expr == 0) { + return; + } + + /* Check the type code */ + switch (Expr->Op & EXPR_TYPEMASK) { + + case EXPR_LEAFNODE: + if (Expr->Op == EXPR_SYMBOL) { + if (!SymIsDef (Expr->V.Sym)) { + /* Symbol is undefined, mark it */ + SymGuessedAddrSize (Expr->V.Sym, AddrSize); + } + } + return; + + case EXPR_BINARYNODE: + ExprGuessedAddrSize (Expr->Right, AddrSize); + /* FALLTHROUGH */ + + case EXPR_UNARYNODE: + ExprGuessedAddrSize (Expr->Left, AddrSize); + break; + } +} + + diff --git a/src/ca65/expr.h b/src/ca65/expr.h index 4e6c7988d..43a70a09e 100644 --- a/src/ca65/expr.h +++ b/src/ca65/expr.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2003 Ullrich von Bassewitz */ +/* (C) 1998-2006 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -137,6 +137,15 @@ ExprNode* CloneExpr (ExprNode* Expr); void WriteExpr (ExprNode* Expr); /* Write the given expression to the object file */ +void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize); +/* Mark the address size of the given expression tree as guessed. The address + * size passed as argument is the one NOT used, because the actual address + * size wasn't known. Example: Zero page addressing was not used because symbol + * is undefined, and absolute addressing was available. + * This function will actually parse the expression tree for undefined symbols, + * and mark these symbols accordingly. + */ + /* End of expr.h */ diff --git a/src/ca65/instr.c b/src/ca65/instr.c index bebc0ae9b..89cdaf5e8 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2005, Ullrich von Bassewitz */ +/* (C) 1998-2006, Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -946,11 +946,19 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A) /* Simplify it if possible */ A->Expr = SimplifyExpr (A->Expr, &ED); - /* If we don't know how big the expression is, assume the default - * address size for data. - */ if (ED.AddrSize == ADDR_SIZE_DEFAULT) { + /* If we don't know how big the expression is, assume the + * default address size for data. If this default address + * size is unequal to zero page addressing, but zero page + * addressing is allowed by the instruction, mark all symbols + * in the expression tree. This mark will be checked at end + * of assembly, and a warning is issued, if a zero page symbol + * was guessed wrong here. + */ ED.AddrSize = DataAddrSize; + if (ED.AddrSize > ADDR_SIZE_ZP && (A->AddrModeSet & AM65_SET_ZP)) { + ExprGuessedAddrSize (A->Expr, ADDR_SIZE_ZP); + } } /* Check the size */ diff --git a/src/ca65/symentry.c b/src/ca65/symentry.c index 8fcd5c0a5..077ddd0d3 100644 --- a/src/ca65/symentry.c +++ b/src/ca65/symentry.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2004 Ullrich von Bassewitz */ +/* (C) 1998-2006 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -75,16 +75,21 @@ SymEntry* SymLast = 0; SymEntry* NewSymEntry (const char* Name, unsigned Flags) /* Allocate a symbol table entry, initialize and return it */ { + unsigned I; + /* Allocate memory */ SymEntry* S = xmalloc (sizeof (SymEntry)); /* Initialize the entry */ - S->Left = 0; - S->Right = 0; - S->Locals = 0; - S->SymTab = 0; - S->Pos = CurPos; - S->Flags = Flags; + S->Left = 0; + S->Right = 0; + S->Locals = 0; + S->SymTab = 0; + S->Pos = CurPos; + for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) { + S->GuessedUse[I] = 0; + } + S->Flags = Flags; S->Expr = 0; S->ExprRefs = AUTO_COLLECTION_INITIALIZER; S->ExportSize = ADDR_SIZE_DEFAULT; @@ -193,7 +198,7 @@ static void SymReplaceExprRefs (SymEntry* S) /* Safety */ CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == S); - /* We cannot touch the root node, since there are pointers to it. + /* We cannot touch the root node, since there are pointers to it. * Replace it by a literal node. */ E->Op = EXPR_LITERAL; @@ -252,7 +257,7 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags /* Set the symbol value */ S->Expr = Expr; - /* In case of a variable symbol, walk over all expressions containing + /* In case of a variable symbol, walk over all expressions containing * this symbol and replace the (sub-)expression by the literal value of * the tree. Be sure to replace the expression node in place, since there * may be pointers to it. @@ -549,6 +554,32 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri +void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize) +/* Mark the address size of the given symbol as guessed. The address size + * passed as argument is the one NOT used, because the actual address size + * wasn't known. Example: Zero page addressing was not used because symbol + * is undefined, and absolute addressing was available. + */ +{ + /* We must have a valid address size passed */ + PRECONDITION (AddrSize != ADDR_SIZE_DEFAULT); + + /* We do not support all address sizes currently */ + if (AddrSize > sizeof (Sym->GuessedUse) / sizeof (Sym->GuessedUse[0])) { + return; + } + + /* We can only remember one such occurance */ + if (Sym->GuessedUse[AddrSize-1]) { + return; + } + + /* Ok, remember the file position */ + Sym->GuessedUse[AddrSize-1] = xdup (&CurPos, sizeof (CurPos)); +} + + + void SymExportFromGlobal (SymEntry* S) /* Called at the end of assembly. Converts a global symbol that is defined * into an export. diff --git a/src/ca65/symentry.h b/src/ca65/symentry.h index a5d745dd8..b30d07241 100644 --- a/src/ca65/symentry.h +++ b/src/ca65/symentry.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2004 Ullrich von Bassewitz */ +/* (C) 1998-2006 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -78,21 +78,27 @@ /* Structure of a symbol table entry */ typedef struct SymEntry SymEntry; struct SymEntry { - SymEntry* Left; /* Lexically smaller entry */ - SymEntry* Right; /* Lexically larger entry */ - SymEntry* List; /* List of all entries */ - SymEntry* Locals; /* Root of subtree for local symbols */ - struct SymTable* SymTab; /* Table this symbol is in, 0 for locals */ - FilePos Pos; /* File position for this symbol */ - unsigned Flags; /* Symbol flags */ - unsigned Index; /* Index of import/export entries */ - struct ExprNode* Expr; /* Symbol expression */ - Collection ExprRefs; /* Expressions using this symbol */ - unsigned char ExportSize; /* Export address size */ - unsigned char AddrSize; /* Address size of label */ - unsigned char ConDesPrio[CD_TYPE_COUNT]; /* ConDes priorities... */ + SymEntry* Left; /* Lexically smaller entry */ + SymEntry* Right; /* Lexically larger entry */ + SymEntry* List; /* List of all entries */ + SymEntry* Locals; /* Root of subtree for local symbols */ + struct SymTable* SymTab; /* Table this symbol is in, 0 for locals */ + FilePos Pos; /* File position for this symbol */ + FilePos* GuessedUse[1]; /* File position where symbol + * address size was guessed, and the + * smallest possible addressing was NOT + * used. Currently only for zero page + * addressing + */ + unsigned Flags; /* Symbol flags */ + unsigned Index; /* Index of import/export entries */ + struct ExprNode* Expr; /* Symbol expression */ + Collection ExprRefs; /* Expressions using this symbol */ + unsigned char ExportSize; /* Export address size */ + unsigned char AddrSize; /* Address size of label */ + unsigned char ConDesPrio[CD_TYPE_COUNT]; /* ConDes priorities... */ /* ...actually value+1 (used as flag) */ - unsigned Name; /* Name index in global string pool */ + unsigned Name; /* Name index in global string pool */ }; /* List of all symbol table entries */ @@ -166,6 +172,13 @@ void SymConDes (SymEntry* Sym, unsigned char AddrSize, unsigned Type, unsigned P * mark the symbol as an export. Initializers may never be zero page symbols. */ +void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize); +/* Mark the address size of the given symbol as guessed. The address size + * passed as argument is the one NOT used, because the actual address size + * wasn't known. Example: Zero page addressing was not used because symbol + * is undefined, and absolute addressing was available. + */ + void SymExportFromGlobal (SymEntry* S); /* Called at the end of assembly. Converts a global symbol that is defined * into an export. diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index ec853248c..8193fe33c 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2004 Ullrich von Bassewitz */ +/* (C) 1998-2006 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -600,6 +600,25 @@ void SymCheck (void) } ED_Done (&ED); } + + /* If the address size of the symbol was guessed, check the guess + * against the actual address size and print a warning if the two + * differ. + */ + if (S->AddrSize != ADDR_SIZE_DEFAULT) { + /* Do we have data for this address size? */ + if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) { + /* Get the file position where the symbol was used */ + const FilePos* P = S->GuessedUse[S->AddrSize - 1]; + if (P) { + PWarning (P, 0, + "Didn't use %s addressing for `%s'", + AddrSizeToStr (S->AddrSize), + GetSymName (S)); + } + } + } + } /* Next symbol */