From 7e44224dd0a094ef1bbdec1593ab3743b6cc95f3 Mon Sep 17 00:00:00 2001 From: cuz Date: Wed, 19 Nov 2003 22:54:30 +0000 Subject: [PATCH] Moved StudyExpr + helpers into its own module git-svn-id: svn://svn.cc65.org/cc65/trunk@2675 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ca65/expr.c | 462 +----------------------------------- src/ca65/make/gcc.mak | 1 + src/ca65/make/watcom.mak | 1 + src/ca65/studyexpr.c | 488 +++++++++++++++++++++++++++++++++++++++ src/ca65/studyexpr.h | 88 +++++++ 5 files changed, 581 insertions(+), 459 deletions(-) create mode 100644 src/ca65/studyexpr.c create mode 100644 src/ca65/studyexpr.h diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 3a13f4c8f..09e3dc3b9 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -55,6 +55,7 @@ #include "objfile.h" #include "segment.h" #include "struct.h" +#include "studyexpr.h" #include "symbol.h" #include "symtab.h" #include "toklist.h" @@ -76,60 +77,16 @@ */ #define MAX_FREE_NODES 64 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 */ -}; - - - - -/*****************************************************************************/ -/* Forwards */ -/*****************************************************************************/ - - - -static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign); -/* Study an expression tree and place the contents into D */ +static unsigned FreeNodeCount = 0; /*****************************************************************************/ -/* Helpers */ +/* Helpers */ /*****************************************************************************/ -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 */ { @@ -1150,419 +1107,6 @@ static ExprNode* Expr0 (void) -static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D) -/* Study a binary expression subtree. Helper function for StudyExpr. */ -{ - 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; - } -} - - - ExprNode* Expression (void) /* Evaluate an expression, build the expression tree on the heap and return * a pointer to the root of the tree. diff --git a/src/ca65/make/gcc.mak b/src/ca65/make/gcc.mak index baaf3257c..2d3669649 100644 --- a/src/ca65/make/gcc.mak +++ b/src/ca65/make/gcc.mak @@ -40,6 +40,7 @@ OBJS = anonname.o \ segment.o \ spool.o \ struct.o \ + studyexpr.o \ symentry.o \ symbol.o \ symtab.o \ diff --git a/src/ca65/make/watcom.mak b/src/ca65/make/watcom.mak index dd04e44df..f9e73406c 100644 --- a/src/ca65/make/watcom.mak +++ b/src/ca65/make/watcom.mak @@ -89,6 +89,7 @@ OBJS = anonname.obj \ segment.obj \ spool.obj \ struct.obj \ + studyexpr.obj \ symbol.obj \ symentry.obj \ symtab.obj \ diff --git a/src/ca65/studyexpr.c b/src/ca65/studyexpr.c new file mode 100644 index 000000000..e125dec99 --- /dev/null +++ b/src/ca65/studyexpr.c @@ -0,0 +1,488 @@ +/*****************************************************************************/ +/* */ +/* studyexpr.c */ +/* */ +/* Study an expression tree */ +/* */ +/* */ +/* */ +/* (C) 2003 Ullrich von Bassewitz */ +/* Römerstraße 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +/* common */ +#include "check.h" +#include "print.h" +#include "shift.h" + +/* ca65 */ +#include "error.h" +#include "segment.h" +#include "studyexpr.h" +#include "symtab.h" +#include "ulabel.h" + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +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; +} + + + +int ExprDescIsConst (const ExprDesc* ED) +/* Return true if the expression is constant */ +{ + return (ED->TooComplex == 0 && ED->SymCount == 0 && ED->SecCount == 0); +} + + + +static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D) +/* Study a binary expression subtree. Helper function for StudyExpr. */ +{ + 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; + } +} + + + +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; + } +} + + + diff --git a/src/ca65/studyexpr.h b/src/ca65/studyexpr.h new file mode 100644 index 000000000..8921733b4 --- /dev/null +++ b/src/ca65/studyexpr.h @@ -0,0 +1,88 @@ +/*****************************************************************************/ +/* */ +/* studyexpr.h */ +/* */ +/* Study an expression tree */ +/* */ +/* */ +/* */ +/* (C) 2003 Ullrich von Bassewitz */ +/* Römerstraße 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#ifndef STUDYEXPR_H +#define STUDYEXPR_H + + + +/* common */ +#include "exprdefs.h" + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* 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 */ + struct SymEntry* SymRef; /* Symbol reference if any */ + unsigned SecRef; /* Section reference if any */ +}; + + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +ExprDesc* InitExprDesc (ExprDesc* ED); +/* Initialize an ExprDesc structure for use with StudyExpr */ + +int ExprDescIsConst (const ExprDesc* ED); +/* Return true if the expression is constant */ + +void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign); +/* Study an expression tree and place the contents into D */ + + + +/* End of studyexpr.h */ +#endif + + + -- 2.39.5