From 4555fdcad17b14439dc4876ec1ac275accdb5c14 Mon Sep 17 00:00:00 2001 From: cuz Date: Tue, 11 Nov 2003 13:57:30 +0000 Subject: [PATCH] Rewrote expression evaluation. More smaller changes. git-svn-id: svn://svn.cc65.org/cc65/trunk@2638 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ca65/asserts.c | 7 +- src/ca65/condasm.c | 4 +- src/ca65/error.c | 4 +- src/ca65/expr.c | 956 +++++++++++++++++++++++++------------------- src/ca65/expr.h | 17 +- src/ca65/instr.c | 4 +- src/ca65/objcode.c | 18 +- src/ca65/scanner.c | 14 +- src/ca65/scanner.h | 11 +- src/ca65/segment.c | 61 ++- src/ca65/symentry.c | 97 ++--- src/ca65/symentry.h | 20 +- src/ca65/symtab.c | 85 +--- src/ca65/symtab.h | 7 +- 14 files changed, 668 insertions(+), 637 deletions(-) diff --git a/src/ca65/asserts.c b/src/ca65/asserts.c index 25f5178fc..a5f8af593 100644 --- a/src/ca65/asserts.c +++ b/src/ca65/asserts.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -118,9 +118,6 @@ void WriteAssertions (void) /* Get the next assertion */ Assertion* A = CollAtUnchecked (&Assertions, I); - /* Finalize the expression */ - A->Expr = FinalizeExpr (A->Expr); - /* Write it to the file */ WriteExpr (A->Expr); ObjWriteVar (A->Action); @@ -134,4 +131,4 @@ void WriteAssertions (void) - + diff --git a/src/ca65/condasm.c b/src/ca65/condasm.c index 0aef3b364..88d7716f7 100644 --- a/src/ca65/condasm.c +++ b/src/ca65/condasm.c @@ -295,7 +295,7 @@ void DoConditionals (void) NextTok (); if (IfCond) { ExprNode* Expr = Expression(); - SetIfCond (D, IsConstExpr (Expr)); + SetIfCond (D, IsConstExpr (Expr, 0)); FreeExpr (Expr); } IfCond = GetCurrentIfCond (); @@ -330,7 +330,7 @@ void DoConditionals (void) NextTok (); if (IfCond) { ExprNode* Expr = Expression(); - SetIfCond (D, !IsConstExpr (Expr)); + SetIfCond (D, !IsConstExpr (Expr, 0)); FreeExpr (Expr); } IfCond = GetCurrentIfCond (); diff --git a/src/ca65/error.c b/src/ca65/error.c index f4cda093d..06bbf2615 100644 --- a/src/ca65/error.c +++ b/src/ca65/error.c @@ -181,8 +181,8 @@ void Internal (const char* Format, ...) /* Print a message about an internal compiler error and die. */ { va_list ap; - va_start (ap, Format); - fprintf (stderr, "Internal assembler error\n"); + va_start (ap, Format); + fprintf (stderr, "Internal assembler error:\n"); vfprintf (stderr, Format, ap); va_end (ap); fprintf (stderr, "\n"); diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 3c73fd19b..cf5f5e537 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -41,6 +41,7 @@ #include "cpu.h" #include "exprdefs.h" #include "print.h" +#include "shift.h" #include "tgttrans.h" #include "version.h" #include "xmalloc.h" @@ -73,8 +74,21 @@ * using the Left link. */ #define MAX_FREE_NODES 64 -static ExprNode* FreeExprNodes = 0; -static unsigned FreeNodeCount = 0; +static ExprNode* FreeExprNodes = 0; +static unsigned FreeNodeCount = 0; + +/* Structure for parsing expression trees */ +typedef struct ExprDesc ExprDesc; +struct ExprDesc { + long Val; /* The offset value */ + long Left; /* Left value for StudyBinaryExpr */ + int TooComplex; /* Expression is too complex to evaluate */ + long SymCount; /* Symbol reference count */ + long SecCount; /* Section reference count */ + SymEntry* SymRef; /* Symbol reference if any */ + unsigned SecRef; /* Section reference if any */ +}; + @@ -84,6 +98,26 @@ static unsigned FreeNodeCount = 0; +static ExprDesc* InitExprDesc (ExprDesc* ED) +/* Initialize an ExprDesc structure for use with StudyExpr */ +{ + ED->Val = 0; + ED->TooComplex = 0; + ED->SymCount = 0; + ED->SecCount = 0; + return ED; +} + + + +static int ExprDescIsConst (const ExprDesc* ED) +/* Return true if the expression is constant */ +{ + return (ED->TooComplex == 0 && ED->SymCount == 0 && ED->SecCount == 0); +} + + + static ExprNode* NewExprNode (unsigned Op) /* Create a new expression node */ { @@ -194,7 +228,7 @@ static int FuncConst (void) ExprNode* Expr = Expression (); /* Check the constness of the expression */ - int Result = IsConstExpr (Expr); + int Result = IsConstExpr (Expr, 0); /* Free the expression */ FreeExpr (Expr); @@ -534,6 +568,12 @@ static ExprNode* Factor (void) N->Left = Factor (); break; + case TOK_BANK: + NextTok (); + N = NewExprNode (EXPR_BYTE2); + N->Left = Factor (); + break; + case TOK_LPAREN: NextTok (); N = Expr0 (); @@ -722,13 +762,13 @@ static ExprNode* Expr2 (void) ExprNode* Root = BoolExpr (); /* Handle booleans */ - while (Tok == TOK_BAND || Tok == TOK_BXOR) { + while (Tok == TOK_BOOLAND || Tok == TOK_BOOLXOR) { /* Create the new node */ ExprNode* Left = Root; switch (Tok) { - case TOK_BAND: Root = NewExprNode (EXPR_BAND); break; - case TOK_BXOR: Root = NewExprNode (EXPR_BXOR); break; + case TOK_BOOLAND: Root = NewExprNode (EXPR_BOOLAND); break; + case TOK_BOOLXOR: Root = NewExprNode (EXPR_BOOLXOR); break; default: Internal ("Invalid token"); } Root->Left = Left; @@ -754,12 +794,12 @@ static ExprNode* Expr1 (void) ExprNode* Root = Expr2 (); /* Handle booleans */ - while (Tok == TOK_BOR) { + while (Tok == TOK_BOOLOR) { /* Create the new node */ ExprNode* Left = Root; switch (Tok) { - case TOK_BOR: Root = NewExprNode (EXPR_BOR); break; + case TOK_BOOLOR: Root = NewExprNode (EXPR_BOOLOR); break; default: Internal ("Invalid token"); } Root->Left = Left; @@ -784,10 +824,10 @@ static ExprNode* Expr0 (void) ExprNode* Root; /* Handle booleans */ - if (Tok == TOK_BNOT) { + if (Tok == TOK_BOOLNOT) { /* Create the new node */ - Root = NewExprNode (EXPR_BNOT); + Root = NewExprNode (EXPR_BOOLNOT); /* Skip the operator token */ NextTok (); @@ -808,22 +848,440 @@ static ExprNode* Expr0 (void) -static ExprNode* SimplifyExpr (ExprNode* Root) +static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign); +static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D) +/* Study a binary expression subtree */ +{ + StudyExpr (Expr->Left, D, 1); + if (ExprDescIsConst (D)) { + D->Left = D->Val; + D->Val = 0; + StudyExpr (Expr->Right, D, 1); + if (!ExprDescIsConst (D)) { + D->TooComplex = 1; + } + } else { + D->TooComplex = 1; + } +} + + + +static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign) +/* Study an expression tree and place the contents into D */ +{ + SymEntry* Sym; + unsigned Sec; + ExprDesc SD; + ExprDesc SD1; + + /* Initialize SD. This is not needed in all cases, but it's rather cheap + * and simplifies the code below. + */ + InitExprDesc (&SD); + + /* Study this expression node */ + switch (Expr->Op) { + + case EXPR_LITERAL: + D->Val += (Sign * Expr->V.Val); + break; + + case EXPR_SYMBOL: + Sym = Expr->V.Sym; + if (SymIsImport (Sym)) { + if (D->SymCount == 0) { + D->SymCount += Sign; + D->SymRef = Sym; + } else if (D->SymRef == Sym) { + /* Same symbol */ + D->SymCount += Sign; + } else { + /* More than one import */ + D->TooComplex = 1; + } + } else if (SymHasExpr (Sym)) { + if (SymHasUserMark (Sym)) { + if (Verbosity > 0) { + DumpExpr (Expr, SymResolve); + } + PError (GetSymPos (Sym), + "Circular reference in definition of symbol `%s'", + GetSymName (Sym)); + D->TooComplex = 1; + } else { + SymMarkUser (Sym); + StudyExpr (GetSymExpr (Sym), D, Sign); + SymUnmarkUser (Sym); + } + } else { + D->TooComplex = 1; + } + break; + + case EXPR_SECTION: + Sec = Expr->V.SegNum; + if (D->SecCount == 0) { + D->SecCount += Sign; + D->SecRef = Sec; + } else if (D->SecRef == Sec) { + /* Same section */ + D->SecCount += Sign; + } else { + /* More than one section */ + D->TooComplex = 1; + } + break; + + case EXPR_ULABEL: + if (ULabCanResolve ()) { + /* We can resolve the label */ + StudyExpr (ULabResolve (Expr->V.Val), D, Sign); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_PLUS: + StudyExpr (Expr->Left, D, Sign); + StudyExpr (Expr->Right, D, Sign); + break; + + case EXPR_MINUS: + StudyExpr (Expr->Left, D, Sign); + StudyExpr (Expr->Right, D, -Sign); + break; + + case EXPR_MUL: + InitExprDesc (&SD1); + StudyExpr (Expr->Left, &SD, 1); + StudyExpr (Expr->Right, &SD1, 1); + if (SD.TooComplex == 0 && SD1.TooComplex == 0) { + /* First calculate SD = SD*SD1 if possible */ + if (ExprDescIsConst (&SD)) { + /* Left is a constant */ + SD1.Val *= SD.Val; + SD1.SymCount *= SD.Val; + SD1.SecCount *= SD.Val; + SD = SD1; + } else if (ExprDescIsConst (&SD1)) { + /* Right is constant */ + SD.Val *= SD1.Val; + SD.SymCount *= SD1.Val; + SD.SecCount *= SD1.Val; + } else { + D->TooComplex = 1; + } + /* Now calculate D * Sign * SD */ + if (!D->TooComplex) { + if ((D->SymCount == 0 || SD.SymCount == 0 || D->SymRef == SD.SymRef) && + (D->SecCount == 0 || SD.SecCount == 0 || D->SecRef == SD.SecRef)) { + D->Val += (Sign * SD.Val); + if (D->SymCount == 0) { + D->SymRef = SD.SymRef; + } + D->SymCount += (Sign * SD.SymCount); + if (D->SecCount == 0) { + D->SecRef = SD.SecRef; + } + D->SecCount += (Sign * SD.SecCount); + } + } else { + D->TooComplex = 1; + } + } else { + D->TooComplex = 1; + } + break; + + case EXPR_DIV: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + if (SD.Val == 0) { + Error ("Division by zero"); + D->TooComplex = 1; + } else { + D->Val += Sign * (SD.Left / SD.Val); + } + } else { + D->TooComplex = 1; + } + break; + + case EXPR_MOD: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + if (SD.Val == 0) { + Error ("Modulo operation with zero"); + D->TooComplex = 1; + } else { + D->Val += Sign * (SD.Left % SD.Val); + } + } else { + D->TooComplex = 1; + } + break; + + case EXPR_OR: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + D->Val += Sign * (SD.Left | SD.Val); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_XOR: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + D->Val += Sign * (SD.Left ^ SD.Val); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_AND: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + D->Val += Sign * (SD.Left & SD.Val); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_SHL: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + D->Val += (Sign * shl_l (SD.Left, (unsigned) SD.Val)); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_SHR: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + D->Val += (Sign * shr_l (SD.Left, (unsigned) SD.Val)); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_EQ: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + D->Val += Sign * (SD.Left == SD.Val); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_NE: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + D->Val += Sign * (SD.Left != SD.Val); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_LT: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + D->Val += Sign * (SD.Left < SD.Val); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_GT: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + D->Val += Sign * (SD.Left > SD.Val); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_LE: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + D->Val += Sign * (SD.Left <= SD.Val); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_GE: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + D->Val += Sign * (SD.Left >= SD.Val); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_BOOLAND: + StudyExpr (Expr->Left, &SD, 1); + if (ExprDescIsConst (&SD)) { + if (SD.Val != 0) { /* Shortcut op */ + SD.Val = 0; + StudyExpr (Expr->Right, &SD, 1); + if (ExprDescIsConst (&SD)) { + D->Val += Sign * (SD.Val != 0); + } else { + D->TooComplex = 1; + } + } + } else { + D->TooComplex = 1; + } + break; + + case EXPR_BOOLOR: + StudyExpr (Expr->Left, &SD, 1); + if (ExprDescIsConst (&SD)) { + if (SD.Val == 0) { /* Shortcut op */ + StudyExpr (Expr->Right, &SD, 1); + if (ExprDescIsConst (&SD)) { + D->Val += Sign * (SD.Val != 0); + } else { + D->TooComplex = 1; + } + } else { + D->Val += Sign; + } + } else { + D->TooComplex = 1; + } + break; + + case EXPR_BOOLXOR: + StudyBinaryExpr (Expr, &SD); + if (!SD.TooComplex) { + D->Val += Sign * ((SD.Left != 0) ^ (SD.Val != 0)); + } + break; + + case EXPR_UNARY_MINUS: + StudyExpr (Expr->Left, D, -Sign); + break; + + case EXPR_NOT: + StudyExpr (Expr->Left, &SD, 1); + if (ExprDescIsConst (&SD)) { + D->Val += (Sign * ~SD.Val); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_SWAP: + StudyExpr (Expr->Left, &SD, 1); + if (ExprDescIsConst (&SD)) { + D->Val += Sign * (((SD.Val >> 8) & 0x00FF) | ((SD.Val << 8) & 0xFF00)); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_BOOLNOT: + StudyExpr (Expr->Left, &SD, 1); + if (ExprDescIsConst (&SD)) { + D->Val += Sign * (SD.Val != 0); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_FORCEWORD: + case EXPR_FORCEFAR: + /* Ignore */ + StudyExpr (Expr->Left, D, Sign); + break; + + case EXPR_BYTE0: + StudyExpr (Expr->Left, &SD, 1); + if (ExprDescIsConst (&SD)) { + D->Val += Sign * (SD.Val & 0xFF); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_BYTE1: + StudyExpr (Expr->Left, &SD, 1); + if (ExprDescIsConst (&SD)) { + D->Val += Sign * ((SD.Val >> 8) & 0xFF); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_BYTE2: + StudyExpr (Expr->Left, &SD, 1); + if (ExprDescIsConst (&SD)) { + D->Val += Sign * ((SD.Val >> 16) & 0xFF); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_BYTE3: + StudyExpr (Expr->Left, &SD, 1); + if (ExprDescIsConst (&SD)) { + D->Val += Sign * ((SD.Val >> 24) & 0xFF); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_WORD0: + StudyExpr (Expr->Left, &SD, 1); + if (ExprDescIsConst (&SD)) { + D->Val += Sign * (SD.Val & 0xFFFF); + } else { + D->TooComplex = 1; + } + break; + + case EXPR_WORD1: + StudyExpr (Expr->Left, &SD, 1); + if (ExprDescIsConst (&SD)) { + D->Val += Sign * ((SD.Val >> 16) & 0xFFFF); + } else { + D->TooComplex = 1; + } + break; + + default: + Internal ("Unknown Op type: %u", Expr->Op); + break; + } +} + + + +static ExprNode* SimplifyExpr (ExprNode* Expr) /* Try to simplify the given expression tree */ { - if (Root) { - Root->Left = SimplifyExpr (Root->Left); - Root->Right = SimplifyExpr (Root->Right); - if (IsConstExpr (Root)) { - /* The complete expression is constant */ - Root->V.Val = GetExprVal (Root); - Root->Op = EXPR_LITERAL; - FreeExpr (Root->Left); - FreeExpr (Root->Right); - Root->Left = Root->Right = 0; - } + if (Expr && Expr->Op != EXPR_LITERAL) { + + /* Create an expression description and initialize it */ + ExprDesc D; + InitExprDesc (&D); + + /* Study the expression */ + StudyExpr (Expr, &D, 1); + + /* Now check if we can generate a literal value */ + if (ExprDescIsConst (&D)) { + /* No external references */ + FreeExpr (Expr); + Expr = GenLiteralExpr (D.Val); + } } - return Root; + return Expr; } @@ -833,7 +1291,16 @@ ExprNode* Expression (void) * a pointer to the root of the tree. */ { +#if 1 return SimplifyExpr (Expr0 ()); +#else + /* Test code */ + ExprNode* Expr = Expr0 (); + printf ("Before: "); DumpExpr (Expr, SymResolve); + Expr = SimplifyExpr (Expr); + printf ("After: "); DumpExpr (Expr, SymResolve); + return Expr; +#endif } @@ -844,24 +1311,28 @@ long ConstExpression (void) * not constant. */ { - long Val; +#if 1 + /* Read the expression */ + ExprNode* Expr = Expr0 (); +#else + /* Test code */ + ExprNode* Expr = Expression (); +#endif - /* Read the expression, and call finalize (exception here, since we - * expect a const). - */ - ExprNode* Expr = FinalizeExpr (Expression ()); + /* Study the expression */ + ExprDesc D; + InitExprDesc (&D); + StudyExpr (Expr, &D, 1); - /* Get the value */ - if (IsConstExpr (Expr)) { - Val = GetExprVal (Expr); - } else { + /* Check if the expression is constant */ + if (!ExprDescIsConst (&D)) { Error ("Constant expression expected"); - Val = 0; + D.Val = 0; } /* Free the expression tree and return the value */ FreeExpr (Expr); - return Val; + return D.Val; } @@ -951,7 +1422,7 @@ ExprNode* GenBranchExpr (unsigned Offs) if (RelocMode) { N = NewExprNode (EXPR_PLUS); N->Left = GenSectionExpr (GetCurrentSegNum ()); - N->Right = GenLiteralExpr (GetPC () + Offs); + N->Right = GenLiteralExpr (GetPC () + Offs); } else { N = GenLiteralExpr (GetPC () + Offs); } @@ -1020,80 +1491,25 @@ ExprNode* GenNE (ExprNode* Expr, long Val) -int IsConstExpr (ExprNode* Root) +int IsConstExpr (ExprNode* Expr, long* Val) /* Return true if the given expression is a constant expression, that is, one - * with no references to external symbols. + * with no references to external symbols. If Val is not NULL and the + * expression is constant, the constant value is stored here. */ { - int Const; - SymEntry* Sym; - - if (EXPR_IS_LEAF (Root->Op)) { - switch (Root->Op) { - - case EXPR_LITERAL: - return 1; - - case EXPR_SYMBOL: - Sym = Root->V.Sym; - if (SymHasUserMark (Sym)) { - if (Verbosity > 0) { - DumpExpr (Root); - } - PError (GetSymPos (Sym), "Circular reference in symbol definition"); - Const = 0; - } else { - SymMarkUser (Sym); - Const = SymIsConst (Sym); - SymUnmarkUser (Sym); - } - return Const; - - default: - return 0; - - } - } else if (EXPR_IS_UNARY (Root->Op)) { - - return IsConstExpr (Root->Left); + /* Study the expression */ + ExprDesc D; + InitExprDesc (&D); + StudyExpr (Expr, &D, 1); + /* Check if the expression is constant */ + if (ExprDescIsConst (&D)) { + if (Val) { + *Val = D.Val; + } + return 1; } else { - - /* We must handle shortcut boolean expressions here */ - switch (Root->Op) { - - case EXPR_BAND: - if (IsConstExpr (Root->Left)) { - /* lhs is const, if it is zero, don't eval right */ - if (GetExprVal (Root->Left) == 0) { - return 1; - } else { - return IsConstExpr (Root->Right); - } - } else { - /* lhs not const --> tree not const */ - return 0; - } - break; - - case EXPR_BOR: - if (IsConstExpr (Root->Left)) { - /* lhs is const, if it is not zero, don't eval right */ - if (GetExprVal (Root->Left) != 0) { - return 1; - } else { - return IsConstExpr (Root->Right); - } - } else { - /* lhs not const --> tree not const */ - return 0; - } - break; - - default: - /* All others are handled normal */ - return IsConstExpr (Root->Left) && IsConstExpr (Root->Right); - } + return 0; } } @@ -1105,7 +1521,7 @@ static void CheckByteExpr (const ExprNode* N, int* IsByte) */ { if (N) { - switch (N->Op & EXPR_TYPEMASK) { + switch (N->Op & EXPR_TYPEMASK) { case EXPR_LEAFNODE: switch (N->Op) { @@ -1149,12 +1565,10 @@ int IsByteExpr (ExprNode* Root) /* Return true if this is a byte expression */ { int IsByte; + long Val; - if (IsConstExpr (Root)) { - if (Root->Op != EXPR_LITERAL) { - SimplifyExpr (Root); - } - return IsByteRange (GetExprVal (Root)); + if (IsConstExpr (Root, &Val)) { + IsByte = IsByteRange (Val); } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 || Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) { /* Symbol forced to have byte range */ @@ -1174,307 +1588,6 @@ int IsByteExpr (ExprNode* Root) -long GetExprVal (ExprNode* Expr) -/* Get the value of a constant expression */ -{ - long Right, Left; - - switch (Expr->Op) { - - case EXPR_LITERAL: - return Expr->V.Val; - - case EXPR_SYMBOL: - return GetSymVal (Expr->V.Sym); - - case EXPR_PLUS: - return GetExprVal (Expr->Left) + GetExprVal (Expr->Right); - - case EXPR_MINUS: - return GetExprVal (Expr->Left) - GetExprVal (Expr->Right); - - case EXPR_MUL: - return GetExprVal (Expr->Left) * GetExprVal (Expr->Right); - - case EXPR_DIV: - Left = GetExprVal (Expr->Left); - Right = GetExprVal (Expr->Right); - if (Right == 0) { - Error ("Division by zero"); - return 0; - } - return Left / Right; - - case EXPR_MOD: - Left = GetExprVal (Expr->Left); - Right = GetExprVal (Expr->Right); - if (Right == 0) { - Error ("Modulo operation with zero"); - return 0; - } - return Left % Right; - - case EXPR_OR: - return GetExprVal (Expr->Left) | GetExprVal (Expr->Right); - - case EXPR_XOR: - return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right); - - case EXPR_AND: - return GetExprVal (Expr->Left) & GetExprVal (Expr->Right); - - case EXPR_SHL: - return GetExprVal (Expr->Left) << GetExprVal (Expr->Right); - - case EXPR_SHR: - return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right); - - case EXPR_EQ: - return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right)); - - case EXPR_NE: - return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right)); - - case EXPR_LT: - return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right)); - - case EXPR_GT: - return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right)); - - case EXPR_LE: - return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right)); - - case EXPR_GE: - return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right)); - - case EXPR_UNARY_MINUS: - return -GetExprVal (Expr->Left); - - case EXPR_NOT: - return ~GetExprVal (Expr->Left); - - case EXPR_BYTE0: - return GetExprVal (Expr->Left) & 0xFF; - - case EXPR_BYTE1: - return (GetExprVal (Expr->Left) >> 8) & 0xFF; - - case EXPR_BYTE2: - return (GetExprVal (Expr->Left) >> 16) & 0xFF; - - case EXPR_BYTE3: - return (GetExprVal (Expr->Left) >> 24) & 0xFF; - - case EXPR_SWAP: - Left = GetExprVal (Expr->Left); - return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00); - - case EXPR_BAND: - return GetExprVal (Expr->Left) && GetExprVal (Expr->Right); - - case EXPR_BOR: - return GetExprVal (Expr->Left) || GetExprVal (Expr->Right); - - case EXPR_BXOR: - return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0); - - case EXPR_BNOT: - return !GetExprVal (Expr->Left); - - case EXPR_ULABEL: - Internal ("GetExprVal called for EXPR_ULABEL"); - /* NOTREACHED */ - return 0; - - default: - Internal ("Unknown Op type: %u", Expr->Op); - /* NOTREACHED */ - return 0; - } -} - - - -static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone) -/* Remove resolved symbols from the tree by cloning symbol expressions */ -{ - /* Accept NULL pointers */ - if (Expr == 0) { - return 0; - } - - /* Special node handling */ - switch (Expr->Op) { - - case EXPR_SYMBOL: - if (SymHasExpr (Expr->V.Sym)) { - /* The symbol has an expression tree */ - SymEntry* Sym = Expr->V.Sym; - if (SymHasUserMark (Sym)) { - /* Circular definition */ - if (Verbosity) { - DumpExpr (Expr); - } - PError (GetSymPos (Sym), "Circular reference in symbol definition"); - return GenLiteralExpr (0); /* Return a dummy value */ - } - SymMarkUser (Sym); - Expr = RemoveSyms (GetSymExpr (Sym), 1); - SymUnmarkUser (Sym); - return Expr; - } else if (SymIsConst (Expr->V.Sym)) { - /* The symbol is a constant */ - return GenLiteralExpr (GetSymVal (Expr->V.Sym)); - } - break; - - case EXPR_ULABEL: - if (ULabCanResolve ()) { - ExprNode* NewExpr = ULabResolve (Expr->V.Val); - FreeExpr (Expr); - Expr = NewExpr; - } - break; - - } - - /* Clone the current node if needed */ - if (MustClone) { - - ExprNode* Clone; - - /* Clone the expression tree */ - switch (Expr->Op) { - - case EXPR_LITERAL: - Clone = GenLiteralExpr (Expr->V.Val); - break; - - case EXPR_ULABEL: - Clone = GenULabelExpr (Expr->V.Val); - break; - - case EXPR_SYMBOL: - Clone = GenSymExpr (Expr->V.Sym); - break; - - case EXPR_SECTION: - Clone = GenSectionExpr (Expr->V.SegNum); - break; - - default: - Clone = NewExprNode (Expr->Op); - Clone->Left = RemoveSyms (Expr->Left, 1); - Clone->Right = RemoveSyms (Expr->Right, 1); - break; - - } - - /* Done */ - return Clone; - - } else { - - /* Nothing to clone */ - Expr->Left = RemoveSyms (Expr->Left, 0); - Expr->Right = RemoveSyms (Expr->Right, 0); - - /* Done */ - return Expr; - } -} - - - -static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign) -/* Extract and evaluate all constant factors in an subtree that has only - * additions and subtractions. - */ -{ - if (Expr->Op == EXPR_LITERAL) { - if (Sign < 0) { - *Val -= Expr->V.Val; - } else { - *Val += Expr->V.Val; - } - FreeExprNode (Expr); - return 0; - } - - if (Expr->Op == EXPR_PLUS || Expr->Op == EXPR_MINUS) { - ExprNode* Left; - ExprNode* Right; - Left = ConstExtract (Expr->Left, Val, Sign); - if (Expr->Op == EXPR_MINUS) { - Sign = -Sign; - } - Right = ConstExtract (Expr->Right, Val, Sign); - if (Left == 0 && Right == 0) { - FreeExprNode (Expr); - return 0; - } else if (Left == 0) { - FreeExprNode (Expr); - return Right; - } else if (Right == 0) { - FreeExprNode (Expr); - return Left; - } else { - /* Check for SEG - SEG which is now possible */ - if (Left->Op == EXPR_SECTION && Right->Op == EXPR_SECTION && - Left->V.SegNum == Right->V.SegNum) { - /* SEG - SEG, remove it completely */ - FreeExprNode (Left); - FreeExprNode (Right); - FreeExprNode (Expr); - return 0; - } else { - Expr->Left = Left; - Expr->Right = Right; - return Expr; - } - } - } - - /* Some other sort of node, finalize the terms */ - if (Expr->Left) { - Expr->Left = FinalizeExpr (Expr->Left); - } - if (Expr->Right) { - Expr->Right = FinalizeExpr (Expr->Right); - } - - return Expr; -} - - - -ExprNode* FinalizeExpr (ExprNode* Expr) -/* Resolve any symbols by cloning the symbol expression tree instead of the - * symbol reference, then try to simplify the expression as much as possible. - * This function must only be called if all symbols are resolved (no undefined - * symbol errors). - */ -{ - long Val = 0; - ExprNode* N; - - Expr = RemoveSyms (Expr, 0); - Expr = ConstExtract (Expr, &Val, 1); - if (Expr == 0) { - /* Reduced to a literal value */ - Expr = GenLiteralExpr (Val); - } else if (Val) { - /* Extracted a value */ - N = NewExprNode (EXPR_PLUS); - N->Left = Expr; - N->Right = GenLiteralExpr (Val); - Expr = N; - } - return Expr; -} - - - ExprNode* CloneExpr (ExprNode* Expr) /* Clone the given expression tree. The function will simply clone symbol * nodes, it will not resolve them. @@ -1526,38 +1639,41 @@ void WriteExpr (ExprNode* Expr) { /* Null expressions are encoded by a type byte of zero */ if (Expr == 0) { - ObjWrite8 (0); + ObjWrite8 (EXPR_NULL); return; } - /* Write the expression code */ - ObjWrite8 (Expr->Op); - /* If the is a leafnode, write the expression attribute, otherwise * write the expression operands. */ switch (Expr->Op) { case EXPR_LITERAL: + ObjWrite8 (EXPR_LITERAL); ObjWrite32 (Expr->V.Val); break; case EXPR_SYMBOL: - /* Maybe we should use a code here? */ - CHECK (SymIsImport (Expr->V.Sym)); /* Safety */ - ObjWriteVar (GetSymIndex (Expr->V.Sym)); + if (SymIsImport (Expr->V.Sym)) { + ObjWrite8 (EXPR_SYMBOL); + ObjWriteVar (GetSymIndex (Expr->V.Sym)); + } else { + WriteExpr (GetSymExpr (Expr->V.Sym)); + } break; case EXPR_SECTION: + ObjWrite8 (EXPR_SECTION); ObjWrite8 (Expr->V.SegNum); break; case EXPR_ULABEL: - Internal ("WriteExpr: Cannot write EXPR_ULABEL nodes"); + WriteExpr (ULabResolve (Expr->V.Val)); break; default: /* Not a leaf node */ + ObjWrite8 (Expr->Op); WriteExpr (Expr->Left); WriteExpr (Expr->Right); break; diff --git a/src/ca65/expr.h b/src/ca65/expr.h index b08dd39ed..2edff0e1d 100644 --- a/src/ca65/expr.h +++ b/src/ca65/expr.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -92,30 +92,21 @@ ExprNode* GenWordExpr (ExprNode* Expr); ExprNode* GenNE (ExprNode* Expr, long Val); /* Generate an expression that compares Expr and Val for inequality */ -int IsConstExpr (ExprNode* Root); +int IsConstExpr (ExprNode* Expr, long* Val); /* Return true if the given expression is a constant expression, that is, one - * with no references to external symbols. + * with no references to external symbols. If Val is not NULL and the + * expression is constant, the constant value is stored here. */ int IsByteExpr (ExprNode* Root); /* Return true if this is a byte expression */ -long GetExprVal (ExprNode* Expr); -/* Get the value of a constant expression */ - int IsByteRange (long Val); /* Return true if this is a byte value */ int IsWordRange (long Val); /* Return true if this is a word value */ -ExprNode* FinalizeExpr (ExprNode* Expr); -/* Resolve any symbols by cloning the symbol expression tree instead of the - * symbol reference, then try to simplify the expression as much as possible. - * This function must only be called if all symbols are resolved (no undefined - * symbol errors). - */ - ExprNode* CloneExpr (ExprNode* Expr); /* Clone the given expression tree. The function will simply clone symbol * nodes, it will not resolve them. diff --git a/src/ca65/instr.c b/src/ca65/instr.c index 784c52311..f5dfff89b 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -673,8 +673,8 @@ static long PutImmed8 (const InsDesc* Ins) } /* If we have an expression and it's const, get it's value */ - if (A.Expr && IsConstExpr (A.Expr)) { - Val = GetExprVal (A.Expr); + if (A.Expr) { + (void) IsConstExpr (A.Expr, &Val); } /* Check how many extension bytes are needed and output the instruction */ diff --git a/src/ca65/objcode.c b/src/ca65/objcode.c index 9a2225b69..890b52cee 100644 --- a/src/ca65/objcode.c +++ b/src/ca65/objcode.c @@ -144,10 +144,10 @@ void EmitData (const unsigned char* Data, unsigned Size) void EmitByte (ExprNode* Expr) /* Emit one byte */ -{ - if (IsConstExpr (Expr)) { +{ + long Val; + if (IsConstExpr (Expr, &Val)) { /* Constant expression, emit literal byte */ - long Val = GetExprVal (Expr); FreeExpr (Expr); if ((Val & ~0xFF) != 0) { Error ("Range error"); @@ -167,9 +167,9 @@ void EmitByte (ExprNode* Expr) void EmitWord (ExprNode* Expr) /* Emit one word */ { - if (IsConstExpr (Expr)) { + long Val; + if (IsConstExpr (Expr, &Val)) { /* Constant expression, emit literal byte */ - long Val = GetExprVal (Expr); FreeExpr (Expr); if ((Val & ~0xFFFF) != 0) { Error ("Range error"); @@ -190,9 +190,9 @@ void EmitWord (ExprNode* Expr) void EmitFarAddr (ExprNode* Expr) /* Emit a 24 bit expression */ { - if (IsConstExpr (Expr)) { + long Val; + if (IsConstExpr (Expr, &Val)) { /* Constant expression, emit literal byte */ - long Val = GetExprVal (Expr); FreeExpr (Expr); if ((Val & ~0xFFFFFF) != 0) { Error ("Range error"); @@ -214,9 +214,9 @@ void EmitFarAddr (ExprNode* Expr) void EmitDWord (ExprNode* Expr) /* Emit one dword */ { - if (IsConstExpr (Expr)) { + long Val; + if (IsConstExpr (Expr, &Val)) { /* Constant expression, emit literal byte */ - long Val = GetExprVal (Expr); FreeExpr (Expr); Emit0 (Val & 0xFF); Emit0 ((Val >> 8) & 0xFF); diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 8bc847dec..b1a3b522d 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -122,7 +122,7 @@ struct DotKeyword { { ".A8", TOK_A8 }, { ".ADDR", TOK_ADDR }, { ".ALIGN", TOK_ALIGN }, - { ".AND", TOK_BAND }, + { ".AND", TOK_BOOLAND }, { ".ASCIIZ", TOK_ASCIIZ }, { ".ASSERT", TOK_ASSERT }, { ".AUTOIMPORT", TOK_AUTOIMPORT }, @@ -206,9 +206,9 @@ struct DotKeyword { { ".MATCH", TOK_MATCH }, { ".MID", TOK_MID }, { ".MOD", TOK_MOD }, - { ".NOT", TOK_BNOT }, + { ".NOT", TOK_BOOLNOT }, { ".NULL", TOK_NULL }, - { ".OR", TOK_BOR }, + { ".OR", TOK_BOOLOR }, { ".ORG", TOK_ORG }, { ".OUT", TOK_OUT }, { ".P02", TOK_P02 }, @@ -247,7 +247,7 @@ struct DotKeyword { { ".WARNING", TOK_WARNING }, { ".WORD", TOK_WORD }, { ".XMATCH", TOK_XMATCH }, - { ".XOR", TOK_BXOR }, + { ".XOR", TOK_BOOLXOR }, { ".ZEROPAGE", TOK_ZEROPAGE }, }; @@ -875,7 +875,7 @@ CharAgain: NextChar (); if (C == '&') { NextChar (); - Tok = TOK_BAND; + Tok = TOK_BOOLAND; } else { Tok = TOK_AND; } @@ -885,7 +885,7 @@ CharAgain: NextChar (); if (C == '|') { NextChar (); - Tok = TOK_BOR; + Tok = TOK_BOOLOR; } else { Tok = TOK_OR; } @@ -989,7 +989,7 @@ CharAgain: case '!': NextChar (); - Tok = TOK_BNOT; + Tok = TOK_BOOLNOT; return; case '>': diff --git a/src/ca65/scanner.h b/src/ca65/scanner.h index ecaf01e10..38a2b2d95 100644 --- a/src/ca65/scanner.h +++ b/src/ca65/scanner.h @@ -77,10 +77,10 @@ enum Token { TOK_LE, /* <= */ TOK_GE, /* >= */ - TOK_BAND, /* .and */ - TOK_BOR, /* .or */ - TOK_BXOR, /* .xor */ - TOK_BNOT, /* .not */ + TOK_BOOLAND, /* .and */ + TOK_BOOLOR, /* .or */ + TOK_BOOLXOR, /* .xor */ + TOK_BOOLNOT, /* .not */ TOK_PLUS, /* + */ TOK_MINUS, /* - */ @@ -90,6 +90,7 @@ enum Token { TOK_MOD, /* ! */ TOK_OR, /* | */ TOK_XOR, /* ^ */ + TOK_BANK = TOK_XOR, /* Alias */ TOK_AND, /* & */ TOK_SHL, /* << */ TOK_SHR, /* >> */ @@ -192,7 +193,7 @@ enum Token { TOK_MID, TOK_NULL, TOK_ORG, - TOK_OUT, + TOK_OUT, TOK_P02, TOK_P816, TOK_PAGELENGTH, diff --git a/src/ca65/segment.c b/src/ca65/segment.c index 6642eb5bf..b1ea4da56 100644 --- a/src/ca65/segment.c +++ b/src/ca65/segment.c @@ -290,13 +290,12 @@ void SegCheck (void) Fragment* F = S->Root; while (F) { if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) { - F->V.Expr = FinalizeExpr (F->V.Expr); - if (IsConstExpr (F->V.Expr)) { - /* We are able to evaluate the expression. Get the value - * and check for range errors. + long Val; + if (IsConstExpr (F->V.Expr, &Val)) { + /* We are able to evaluate the expression. Check for + * range errors. */ unsigned I; - long Val = GetExprVal (F->V.Expr); int Abs = (F->Type != FRAG_SEXPR); if (F->Len == 1) { @@ -317,36 +316,36 @@ void SegCheck (void) if (Val > 65535) { PError (&F->Pos, "Range error"); } - } else { - /* PC relative value */ - if (Val < -32768 || Val > 32767) { - PError (&F->Pos, "Range error"); - } - } - } + } else { + /* PC relative value */ + if (Val < -32768 || Val > 32767) { + PError (&F->Pos, "Range error"); + } + } + } /* We don't need the expression tree any longer */ FreeExpr (F->V.Expr); - /* Convert the fragment into a literal fragment */ - for (I = 0; I < F->Len; ++I) { - F->V.Data [I] = Val & 0xFF; - Val >>= 8; + /* Convert the fragment into a literal fragment */ + for (I = 0; I < F->Len; ++I) { + F->V.Data [I] = Val & 0xFF; + Val >>= 8; } - F->Type = FRAG_LITERAL; - } else { - /* We cannot evaluate the expression now, leave the job for - * the linker. However, we are able to check for explicit - * byte expressions and we will do so. - */ - if (F->Type == FRAG_EXPR && F->Len == 1 && !IsByteExpr (F->V.Expr)) { - PError (&F->Pos, "Range error"); - } - } - } - F = F->Next; - } - S = S->List; + F->Type = FRAG_LITERAL; + } else { + /* We cannot evaluate the expression now, leave the job for + * the linker. However, we are able to check for explicit + * byte expressions and we will do so. + */ + if (F->Type == FRAG_EXPR && F->Len == 1 && !IsByteExpr (F->V.Expr)) { + PError (&F->Pos, "Range error"); + } + } + } + F = F->Next; + } + S = S->List; } } @@ -378,7 +377,7 @@ void SegDump (void) } else if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) { State = 1; printf ("\n Expression (%u): ", F->Len); - DumpExpr (F->V.Expr); + DumpExpr (F->V.Expr, SymResolve); } else if (F->Type == FRAG_FILL) { State = 1; printf ("\n Fill bytes (%u)", F->Len); diff --git a/src/ca65/symentry.c b/src/ca65/symentry.c index 9fe7f154f..2c1600760 100644 --- a/src/ca65/symentry.c +++ b/src/ca65/symentry.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -160,15 +160,7 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags) } /* Set the symbol value */ - if (IsConstExpr (Expr)) { - /* Expression is const, store the value */ - S->Flags |= SF_CONST; - S->V.Val = GetExprVal (Expr); - FreeExpr (Expr); - } else { - /* Not const, store the expression */ - S->V.Expr = Expr; - } + S->V.Expr = Expr; /* If the symbol is marked as global, export it */ if (S->Flags & SF_GLOBAL) { @@ -182,7 +174,10 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags) /* If the symbol is exported, check the address sizes */ if (S->Flags & SF_EXPORT) { - if (S->AddrSize > S->ExportSize) { + if (S->ExportSize == ADDR_SIZE_DEFAULT) { + /* Use the real size of the symbol */ + S->ExportSize = S->AddrSize; + } else if (S->AddrSize > S->ExportSize) { Warning (1, "Address size mismatch for symbol `%s'", GetSymName (S)); } } @@ -262,11 +257,6 @@ void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags) return; } - /* Map a default address size to a real value */ - if (AddrSize == ADDR_SIZE_DEFAULT) { - AddrSize = SymAddrSize (S); - } - /* If the symbol was already marked as an export or global, check if * this was done specifiying the same address size. In case of a global * declaration, silently remove the global flag. @@ -283,7 +273,10 @@ void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags) * exported size. */ if (S->Flags & SF_DEFINED) { - if (S->AddrSize > S->ExportSize) { + if (S->ExportSize == ADDR_SIZE_DEFAULT) { + /* Use the real size of the symbol */ + S->ExportSize = S->AddrSize; + } else if (S->AddrSize > S->ExportSize) { Warning (1, "Address size mismatch for symbol `%s'", GetSymName (S)); } } @@ -374,6 +367,22 @@ int SymIsImport (const SymEntry* S) +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 */ { @@ -383,26 +392,7 @@ int SymHasExpr (const SymEntry* S) } /* Check the expression */ - return ((S->Flags & SF_DEFINED) != 0 && - (S->Flags & SF_IMPORT) == 0 && - (S->Flags & SF_CONST) == 0); -} - - - -void SymFinalize (SymEntry* S) -/* Finalize a symbol expression if there is one */ -{ - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - - /* Check if we have an expression */ - if ((S->Flags & SF_FINALIZED) == 0 && SymHasExpr (S)) { - S->V.Expr = FinalizeExpr (S->V.Expr); - S->Flags |= SF_FINALIZED; - } + return ((S->Flags & (SF_DEFINED|SF_IMPORT)) == SF_DEFINED); } @@ -449,20 +439,6 @@ int SymHasUserMark (SymEntry* S) -long GetSymVal (SymEntry* S) -/* Return the symbol value */ -{ - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - - PRECONDITION ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_CONST) != 0); - return S->V.Val; -} - - - struct ExprNode* GetSymExpr (SymEntry* S) /* Get the expression for a non-const symbol */ { @@ -471,12 +447,27 @@ struct ExprNode* GetSymExpr (SymEntry* S) S = S->V.Sym; } - PRECONDITION (S != 0 && (S->Flags & SF_CONST) == 0); + PRECONDITION (S != 0 && SymHasExpr (S)); return S->V.Expr; } +const struct ExprNode* SymResolve (const SymEntry* S) +/* Helper function for DumpExpr. Resolves a symbol into an expression or return + * 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 (SymEntry* S) /* Return the name of the symbol */ { @@ -496,7 +487,7 @@ unsigned GetSymIndex (SymEntry* S) if (S->Flags & SF_TRAMPOLINE) { S = S->V.Sym; } - PRECONDITION (S != 0 && (S->Flags & SF_INDEXED)); + PRECONDITION (S != 0 && (S->Flags & SF_INDEXED) != 0); return S->Index; } diff --git a/src/ca65/symentry.h b/src/ca65/symentry.h index 80289058a..11584a881 100644 --- a/src/ca65/symentry.h +++ b/src/ca65/symentry.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -60,9 +60,7 @@ #define SF_GLOBAL 0x0010 /* Global symbol */ #define SF_LABEL 0x0080 /* Used as a label */ #define SF_FORCED 0x0100 /* Forced import, SF_IMPORT also set */ -#define SF_FINALIZED 0x0200 /* Symbol is finalized */ #define SF_INDEXED 0x0800 /* Index is valid */ -#define SF_CONST 0x1000 /* The symbol has a constant value */ #define SF_MULTDEF 0x2000 /* Multiply defined symbol */ #define SF_DEFINED 0x4000 /* Defined */ #define SF_REFERENCED 0x8000 /* Referenced */ @@ -164,12 +162,14 @@ int SymIsRef (const SymEntry* Sym); int SymIsImport (const SymEntry* Sym); /* Return true if the given symbol is marked as import */ +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); /* Return true if the given symbol has an associated expression */ -void SymFinalize (SymEntry* S); -/* Finalize a symbol expression if there is one */ - void SymMarkUser (SymEntry* Sym); /* Set a user mark on the specified symbol */ @@ -179,12 +179,14 @@ void SymUnmarkUser (SymEntry* Sym); int SymHasUserMark (SymEntry* Sym); /* Return the state of the user mark for the specified symbol */ -long GetSymVal (SymEntry* Sym); -/* Return the symbol value */ - struct ExprNode* GetSymExpr (SymEntry* Sym); /* Get the expression for a non-const symbol */ +const struct ExprNode* SymResolve (const SymEntry* Sym); +/* Helper function for DumpExpr. Resolves a symbol into an expression or return + * NULL. Do not call in other contexts! + */ + const char* GetSymName (SymEntry* Sym); /* Return the name of the symbol */ diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index f6055591e..6af89a97e 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -434,30 +434,6 @@ void SymConDes (const char* Name, unsigned Type, unsigned Prio) -int SymIsConst (SymEntry* S) -/* Return true if the given symbol has a constant value */ -{ - /* Resolve trampoline entries */ - if (S->Flags & SF_TRAMPOLINE) { - S = S->V.Sym; - } - - /* Check for constness */ - if (S->Flags & SF_CONST) { - return 1; - } else if ((S->Flags & SF_DEFINED) && IsConstExpr (S->V.Expr)) { - /* Constant expression, remember the value */ - ExprNode* Expr = S->V.Expr; - S->Flags |= SF_CONST; - S->V.Val = GetExprVal (Expr); - FreeExpr (Expr); - return 1; - } - return 0; -} - - - int SymIsZP (SymEntry* S) /* Return true if the symbol is explicitly marked as zeropage symbol */ { @@ -705,26 +681,6 @@ void WriteImports (void) -static unsigned char GetExportExprMask (SymEntry* S) -/* Return the expression bits for the given symbol table entry */ -{ - unsigned char ExprMask; - - /* Check if the symbol is const */ - ExprMask = (SymIsConst (S))? EXP_CONST : EXP_EXPR; - - /* Add zeropage/abs bits */ - ExprMask |= (S->ExportSize == ADDR_SIZE_ZP)? EXP_ZP : EXP_ABS; - - /* Add the label/equate bits */ - ExprMask |= (S->Flags & SF_LABEL)? EXP_LABEL : EXP_EQUATE; - - /* Return the mask */ - return ExprMask; -} - - - void WriteExports (void) /* Write the exports list to the object file */ { @@ -741,13 +697,13 @@ void WriteExports (void) S = SymList; while (S) { if ((S->Flags & SF_EXPMASK) == SF_EXPVAL) { - unsigned char ExprMask; - /* Finalize an associated expression if we have one */ - SymFinalize (S); + long ConstVal; /* Get the expression bits */ - ExprMask = GetExportExprMask (S); + unsigned char ExprMask = SymIsConst (S, &ConstVal)? EXP_CONST : EXP_EXPR; + ExprMask |= (S->ExportSize == ADDR_SIZE_ZP)? EXP_ZP : EXP_ABS; + ExprMask |= (S->Flags & SF_LABEL)? EXP_LABEL : EXP_EQUATE; /* Count the number of ConDes types */ for (Type = 0; Type < CD_TYPE_COUNT; ++Type) { @@ -775,7 +731,7 @@ void WriteExports (void) /* Write the value */ if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) { /* Constant value */ - ObjWrite32 (S->V.Val); + ObjWrite32 (ConstVal); } else { /* Expression involved */ WriteExpr (S->V.Expr); @@ -793,26 +749,6 @@ void WriteExports (void) -static unsigned char GetDbgExprMask (SymEntry* S) -/* Return the expression bits for the given symbol table entry */ -{ - unsigned char ExprMask; - - /* Check if the symbol is const */ - ExprMask = (SymIsConst (S))? EXP_CONST : EXP_EXPR; - - /* Add zeropage/abs bits */ - ExprMask |= (S->AddrSize == ADDR_SIZE_ZP)? EXP_ZP : EXP_ABS; - - /* Add the label/equate bits */ - ExprMask |= (S->Flags & SF_LABEL)? EXP_LABEL : EXP_EQUATE; - - /* Return the mask */ - return ExprMask; -} - - - void WriteDbgSyms (void) /* Write a list of all symbols to the object file */ { @@ -842,13 +778,13 @@ void WriteDbgSyms (void) S = SymList; while (S) { if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) { - unsigned char ExprMask; - /* Finalize an associated expression if we have one */ - SymFinalize (S); + long ConstVal; /* Get the expression bits */ - ExprMask = GetDbgExprMask (S); + unsigned char ExprMask = (SymIsConst (S, &ConstVal))? EXP_CONST : EXP_EXPR; + ExprMask |= (S->AddrSize == ADDR_SIZE_ZP)? EXP_ZP : EXP_ABS; + ExprMask |= (S->Flags & SF_LABEL)? EXP_LABEL : EXP_EQUATE; /* Write the type */ ObjWrite8 (ExprMask); @@ -859,7 +795,7 @@ void WriteDbgSyms (void) /* Write the value */ if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) { /* Constant value */ - ObjWrite32 (S->V.Val); + ObjWrite32 (ConstVal); } else { /* Expression involved */ WriteExpr (S->V.Expr); @@ -885,3 +821,4 @@ void WriteDbgSyms (void) + diff --git a/src/ca65/symtab.h b/src/ca65/symtab.h index 7debe5be0..fc28def44 100644 --- a/src/ca65/symtab.h +++ b/src/ca65/symtab.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -54,7 +54,7 @@ -/* Symbol table flags */ +/* Symbol table flags */ #define ST_NONE 0x00 /* No flags */ #define ST_DEFINED 0x01 /* Scope has been defined */ @@ -107,9 +107,6 @@ void SymConDes (const char* Name, unsigned Type, unsigned Prio); * mark the symbol as an export. Initializers may never be zero page symbols. */ -int SymIsConst (SymEntry* Sym); -/* Return true if the given symbol has a constant value */ - int SymIsZP (SymEntry* Sym); /* Return true if the symbol is explicitly marked as zeropage symbol */