1 /*****************************************************************************/
5 /* Expression evaluation for the ca65 macroassembler */
9 /* (C) 1998-2000 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
59 /*****************************************************************************/
61 /*****************************************************************************/
65 /* Since all expressions are first packed into expression trees, and each
66 * expression tree node is allocated on the heap, we add some type of special
67 * purpose memory allocation here: Instead of freeing the nodes, we save some
68 * number of freed nodes for later and remember them in a single linked list
69 * using the Left link.
71 #define MAX_FREE_NODES 64
72 static ExprNode* FreeExprNodes = 0;
73 static unsigned FreeNodeCount = 0;
77 /*****************************************************************************/
79 /*****************************************************************************/
83 static ExprNode* NewExprNode (void)
84 /* Create a new expression node */
88 /* Do we have some nodes in the list already? */
90 /* Use first node from list */
92 FreeExprNodes = N->Left;
94 /* Allocate fresh memory */
95 N = xmalloc (sizeof (ExprNode));
98 N->Left = N->Right = 0;
106 static void FreeExprNode (ExprNode* E)
110 if (FreeNodeCount < MAX_FREE_NODES) {
111 /* Remember this node for later */
112 E->Left = FreeExprNodes;
115 /* Free the memory */
123 /*****************************************************************************/
125 /*****************************************************************************/
129 static ExprNode* Expr0 (void);
133 int IsByteRange (long Val)
134 /* Return true if this is a byte value */
136 return (Val & ~0xFFL) == 0;
141 int IsWordRange (long Val)
142 /* Return true if this is a word value */
144 return (Val & ~0xFFFF) == 0;
149 static int FuncBlank (void)
150 /* Handle the .BLANK builtin function */
152 /* Assume no tokens if the closing brace follows (this is not correct in
153 * all cases, since the token may be the closing brace, but this will
154 * give a syntax error anyway and may not be handled by .BLANK.
156 if (Tok == TOK_RPAREN) {
160 /* Skip any tokens */
162 while (Tok != TOK_SEP && Tok != TOK_EOF) {
163 if (Tok == TOK_LPAREN) {
165 } else if (Tok == TOK_RPAREN) {
181 static int FuncConst (void)
182 /* Handle the .CONST builtin function */
184 /* Read an expression */
185 ExprNode* Expr = Expression ();
187 /* Check the constness of the expression */
188 int Result = IsConstExpr (Expr);
190 /* Free the expression */
199 static int FuncDefined (void)
200 /* Handle the .DEFINED builtin function */
204 if (Tok != TOK_IDENT) {
205 Error (ERR_IDENT_EXPECTED);
206 if (Tok != TOK_RPAREN) {
210 Result = SymIsDef (SVal);
220 static int DoMatch (enum TC EqualityLevel)
221 /* Handle the .MATCH and .XMATCH builtin functions */
228 /* A list of tokens follows. Read this list and remember it building a
229 * single linked list of tokens including attributes. The list is
230 * terminated by a comma.
232 while (Tok != TOK_COMMA) {
234 /* We may not end-of-line of end-of-file here */
235 if (Tok == TOK_SEP || Tok == TOK_EOF) {
236 Error (ERR_UNEXPECTED_EOL);
240 /* Get a node with this token */
241 Node = NewTokNode ();
243 /* Insert the node into the list */
258 /* Read the second list which is terminated by the right parenthesis and
259 * compare each token against the one in the first list.
263 while (Tok != TOK_RPAREN) {
265 /* We may not end-of-line of end-of-file here */
266 if (Tok == TOK_SEP || Tok == TOK_EOF) {
267 Error (ERR_UNEXPECTED_EOL);
271 /* Compare the tokens if the result is not already known */
274 /* The second list is larger than the first one */
276 } else if (TokCmp (Node) < EqualityLevel) {
277 /* Tokens do not match */
282 /* Next token in first list */
287 /* Next token in current list */
291 /* Check if there are remaining tokens in the first list */
296 /* Free the token list */
303 /* Done, return the result */
309 static int FuncMatch (void)
310 /* Handle the .MATCH function */
312 return DoMatch (tcSameToken);
317 static int FuncReferenced (void)
318 /* Handle the .REFERENCED builtin function */
322 if (Tok != TOK_IDENT) {
323 Error (ERR_IDENT_EXPECTED);
324 if (Tok != TOK_RPAREN) {
328 Result = SymIsRef (SVal);
338 static int FuncStrAt (void)
339 /* Handle the .STRAT function */
341 char Str [sizeof(SVal)];
344 /* String constant expected */
345 if (Tok != TOK_STRCON) {
346 Error (ERR_STRCON_EXPECTED);
352 /* Remember the string and skip it */
356 /* Comma must follow */
359 /* Expression expected */
360 Index = ConstExpression ();
362 /* Must be a valid index */
363 if (Index >= (long) strlen (Str)) {
368 /* Return the char, handle as unsigned. Be sure to translate it into
369 * the target character set.
371 return (unsigned char) TgtTranslateChar (Str [(size_t)Index]);
376 static int FuncStrLen (void)
377 /* Handle the .STRLEN function */
379 /* String constant expected */
380 if (Tok != TOK_STRCON) {
382 Error (ERR_STRCON_EXPECTED);
383 /* Smart error recovery */
384 if (Tok != TOK_RPAREN) {
391 /* Get the length of the string */
392 int Len = strlen (SVal);
394 /* Skip the string */
397 /* Return the length */
405 static int FuncTCount (void)
406 /* Handle the .TCOUNT function */
408 /* We have a list of tokens that ends with the closing paren. Skip
409 * the tokens, handling nested braces and count them.
413 while (Parens != 0 || Tok != TOK_RPAREN) {
415 /* Check for end of line or end of input. Since the calling function
416 * will check for the closing paren, we don't need to print an error
417 * here, just bail out.
419 if (Tok == TOK_SEP || Tok == TOK_EOF) {
426 /* Keep track of the nesting level */
428 case TOK_LPAREN: ++Parens; break;
429 case TOK_RPAREN: --Parens; break;
437 /* Return the number of tokens */
443 static int FuncXMatch (void)
444 /* Handle the .XMATCH function */
446 return DoMatch (tcIdentical);
451 static ExprNode* Function (int (*F) (void))
452 /* Handle builtin functions */
456 /* Skip the keyword */
459 /* Expression must be enclosed in braces */
460 if (Tok != TOK_LPAREN) {
461 Error (ERR_LPAREN_EXPECTED);
463 return LiteralExpr (0);
467 /* Call the function itself */
470 /* Closing brace must follow */
473 /* Return an expression node with the boolean code */
474 return LiteralExpr (Result);
479 static ExprNode* Factor (void)
487 N = LiteralExpr (IVal);
492 N = LiteralExpr (TgtTranslateChar (IVal));
498 if (Tok != TOK_IDENT) {
499 Error (ERR_IDENT_EXPECTED);
500 N = LiteralExpr (0); /* Dummy */
502 S = SymRefGlobal (SVal);
503 if (SymIsConst (S)) {
504 /* Use the literal value instead */
505 N = LiteralExpr (GetSymVal (S));
507 /* Create symbol node */
518 if (SymIsConst (S)) {
519 /* Use the literal value instead */
520 N = LiteralExpr (GetSymVal (S));
522 /* Create symbol node */
539 N->Op = EXPR_UNARY_MINUS;
576 N = Function (FuncBlank);
580 N = Function (FuncConst);
584 N = LiteralExpr (GetCPU());
589 N = Function (FuncDefined);
593 N = Function (FuncMatch);
597 N = Function (FuncReferenced);
601 N = Function (FuncStrAt);
605 N = Function (FuncStrLen);
609 N = Function (FuncTCount);
613 N = Function (FuncXMatch);
617 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
618 /* A character constant */
619 N = LiteralExpr (TgtTranslateChar (SVal[0]));
621 N = LiteralExpr (0); /* Dummy */
632 static ExprNode* Term (void)
636 /* Read left hand side */
639 /* Handle multiplicative operations */
640 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
641 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
644 /* Create a new node and insert the left expression */
645 ExprNode* Left = Root;
646 Root = NewExprNode ();
649 /* Determine the operator token */
651 case TOK_MUL: Root->Op = EXPR_MUL; break;
652 case TOK_DIV: Root->Op = EXPR_DIV; break;
653 case TOK_MOD: Root->Op = EXPR_MOD; break;
654 case TOK_AND: Root->Op = EXPR_AND; break;
655 case TOK_XOR: Root->Op = EXPR_XOR; break;
656 case TOK_SHL: Root->Op = EXPR_SHL; break;
657 case TOK_SHR: Root->Op = EXPR_SHR; break;
658 default: Internal ("Invalid token");
662 /* Parse the right hand side */
663 Root->Right = Factor ();
667 /* Return the expression tree we've created */
673 static ExprNode* SimpleExpr (void)
677 /* Read left hand side */
680 /* Handle additive operations */
681 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
683 /* Create a new node and insert the left expression */
684 ExprNode* Left = Root;
685 Root = NewExprNode ();
688 /* Determine the operator token */
690 case TOK_PLUS: Root->Op = EXPR_PLUS; break;
691 case TOK_MINUS: Root->Op = EXPR_MINUS; break;
692 case TOK_OR: Root->Op = EXPR_OR; break;
693 default: Internal ("Invalid token");
697 /* Parse the right hand side */
698 Root->Right = Term ();
702 /* Return the expression tree we've created */
708 static ExprNode* BoolExpr (void)
709 /* Evaluate a boolean expression */
711 /* Read left hand side */
712 ExprNode* Root = SimpleExpr ();
714 /* Handle booleans */
715 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
716 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
718 /* Create a new node and insert the left expression */
719 ExprNode* Left = Root;
720 Root = NewExprNode ();
723 /* Determine the operator token */
725 case TOK_EQ: Root->Op = EXPR_EQ; break;
726 case TOK_NE: Root->Op = EXPR_NE; break;
727 case TOK_LT: Root->Op = EXPR_LT; break;
728 case TOK_GT: Root->Op = EXPR_GT; break;
729 case TOK_LE: Root->Op = EXPR_LE; break;
730 case TOK_GE: Root->Op = EXPR_GE; break;
731 default: Internal ("Invalid token");
735 /* Parse the right hand side */
736 Root->Right = SimpleExpr ();
740 /* Return the expression tree we've created */
746 static ExprNode* Expr2 (void)
747 /* Boolean operators: AND and XOR */
749 /* Read left hand side */
750 ExprNode* Root = BoolExpr ();
752 /* Handle booleans */
753 while (Tok == TOK_BAND || Tok == TOK_BXOR) {
755 /* Create a new node and insert the left expression */
756 ExprNode* Left = Root;
757 Root = NewExprNode ();
760 /* Determine the operator token */
762 case TOK_BAND: Root->Op = EXPR_BAND; break;
763 case TOK_BXOR: Root->Op = EXPR_BXOR; break;
764 default: Internal ("Invalid token");
768 /* Parse the right hand side */
769 Root->Right = BoolExpr ();
773 /* Return the expression tree we've created */
779 static ExprNode* Expr1 (void)
780 /* Boolean operators: OR */
782 /* Read left hand side */
783 ExprNode* Root = Expr2 ();
785 /* Handle booleans */
786 while (Tok == TOK_BOR) {
788 /* Create a new node and insert the left expression */
789 ExprNode* Left = Root;
790 Root = NewExprNode ();
793 /* Determine the operator token */
795 case TOK_BOR: Root->Op = EXPR_BOR; break;
796 default: Internal ("Invalid token");
800 /* Parse the right hand side */
801 Root->Right = Expr2 ();
805 /* Return the expression tree we've created */
811 static ExprNode* Expr0 (void)
812 /* Boolean operators: NOT */
816 /* Handle booleans */
817 if (Tok == TOK_BNOT) {
819 /* Create a new node */
820 Root = NewExprNode ();
822 /* Determine the operator token */
824 case TOK_BNOT: Root->Op = EXPR_BNOT; break;
825 default: Internal ("Invalid token");
829 /* Parse the left hand side, allow more BNOTs */
830 Root->Left = Expr0 ();
834 /* Read left hand side */
839 /* Return the expression tree we've created */
845 static ExprNode* SimplifyExpr (ExprNode* Root)
846 /* Try to simplify the given expression tree */
849 SimplifyExpr (Root->Left);
850 SimplifyExpr (Root->Right);
851 if (IsConstExpr (Root)) {
852 /* The complete expression is constant */
853 Root->V.Val = GetExprVal (Root);
854 Root->Op = EXPR_LITERAL;
855 FreeExpr (Root->Left);
856 FreeExpr (Root->Right);
857 Root->Left = Root->Right = 0;
865 ExprNode* Expression (void)
866 /* Evaluate an expression, build the expression tree on the heap and return
867 * a pointer to the root of the tree.
870 return SimplifyExpr (Expr0 ());
875 long ConstExpression (void)
876 /* Parse an expression. Check if the expression is const, and print an error
877 * message if not. Return the value of the expression, or a dummy, if it is
881 /* Read the expression, and call finalize (exception here, since we
884 ExprNode* Expr = FinalizeExpr (Expression ());
886 /* Return the value */
887 if (IsConstExpr (Expr)) {
888 return GetExprVal (Expr);
890 Error (ERR_CONSTEXPR_EXPECTED);
897 ExprNode* LiteralExpr (long Val)
898 /* Return an expression tree that encodes the given literal value */
900 ExprNode* Expr = NewExprNode ();
901 Expr->Op = EXPR_LITERAL;
908 ExprNode* CurrentPC (void)
909 /* Return the current program counter as expression */
915 /* Create SegmentBase + Offset */
916 Left = NewExprNode ();
917 Left->Op = EXPR_SEGMENT;
918 Left->V.SegNum = GetSegNum ();
920 Root = NewExprNode ();
922 Root->Right = LiteralExpr (GetPC ());
923 Root->Op = EXPR_PLUS;
925 /* Absolute mode, just return PC value */
926 Root = LiteralExpr (GetPC ());
934 ExprNode* SwapExpr (ExprNode* Expr)
935 /* Return an extended expression with lo and hi bytes swapped */
937 ExprNode* N = NewExprNode ();
945 ExprNode* BranchExpr (unsigned Offs)
946 /* Return an expression that encodes the difference between current PC plus
947 * offset and the target expression (that is, Expression() - (*+Offs) ).
956 Left = NewExprNode ();
957 Left->Op = EXPR_SEGMENT;
958 Left->V.SegNum = GetSegNum ();
962 N->Right = LiteralExpr (GetPC () + Offs);
965 N = LiteralExpr (GetPC () + Offs);
968 /* Create the root node */
969 Root = NewExprNode ();
970 Root->Left = Expression ();
972 Root->Op = EXPR_MINUS;
974 /* Return the result */
975 return SimplifyExpr (Root);
980 ExprNode* ULabelExpr (unsigned Num)
981 /* Return an expression for an unnamed label with the given index */
983 /* Get an expression node */
984 ExprNode* Node = NewExprNode ();
987 Node->Op = EXPR_ULABEL;
990 /* Return the new node */
996 void FreeExpr (ExprNode* Root)
997 /* Free the expression, Root is pointing to. */
1000 FreeExpr (Root->Left);
1001 FreeExpr (Root->Right);
1002 FreeExprNode (Root);
1008 ExprNode* ForceWordExpr (ExprNode* Expr)
1009 /* Force the given expression into a word and return the result. */
1011 /* And the expression by $FFFF to force it into word size */
1012 ExprNode* Root = NewExprNode ();
1014 Root->Op = EXPR_AND;
1015 Root->Right = LiteralExpr (0xFFFF);
1017 /* Return the result */
1023 int IsConstExpr (ExprNode* Root)
1024 /* Return true if the given expression is a constant expression, that is, one
1025 * with no references to external symbols.
1031 if (EXPR_IS_LEAF (Root->Op)) {
1039 if (SymHasUserMark (Sym)) {
1040 if (Verbosity > 0) {
1043 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1047 Const = SymIsConst (Sym);
1048 SymUnmarkUser (Sym);
1056 } else if (EXPR_IS_UNARY (Root->Op)) {
1058 return IsConstExpr (Root->Left);
1062 /* We must handle shortcut boolean expressions here */
1066 if (IsConstExpr (Root->Left)) {
1067 /* lhs is const, if it is zero, don't eval right */
1068 if (GetExprVal (Root->Left) == 0) {
1071 return IsConstExpr (Root->Right);
1074 /* lhs not const --> tree not const */
1080 if (IsConstExpr (Root->Left)) {
1081 /* lhs is const, if it is not zero, don't eval right */
1082 if (GetExprVal (Root->Left) != 0) {
1085 return IsConstExpr (Root->Right);
1088 /* lhs not const --> tree not const */
1094 /* All others are handled normal */
1095 return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
1102 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1103 /* Internal routine that is recursively called to check if there is a zeropage
1104 * symbol in the expression tree.
1108 switch (N->Op & EXPR_TYPEMASK) {
1114 if (SymIsZP (N->V.Sym)) {
1116 } else if (SymHasExpr (N->V.Sym)) {
1117 /* Check if this expression is a byte expression */
1118 *IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
1123 if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
1131 case EXPR_UNARYNODE:
1132 CheckByteExpr (N->Left, IsByte);
1135 case EXPR_BINARYNODE:
1136 CheckByteExpr (N->Left, IsByte);
1137 CheckByteExpr (N->Right, IsByte);
1141 Internal ("Unknown expression op: %02X", N->Op);
1148 int IsByteExpr (ExprNode* Root)
1149 /* Return true if this is a byte expression */
1153 if (IsConstExpr (Root)) {
1154 if (Root->Op != EXPR_LITERAL) {
1155 SimplifyExpr (Root);
1157 return IsByteRange (GetExprVal (Root));
1158 } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
1159 Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
1160 /* Symbol forced to have byte range */
1163 /* We have undefined symbols in the expression. Assume that the
1164 * expression is a byte expression if there is at least one symbol
1165 * declared as zeropage in it. Being wrong here is not a very big
1166 * problem since the linker knows about all symbols and detects
1167 * error like mixing absolute and zeropage labels.
1170 CheckByteExpr (Root, &IsByte);
1177 long GetExprVal (ExprNode* Expr)
1178 /* Get the value of a constant expression */
1188 return GetSymVal (Expr->V.Sym);
1191 return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
1194 return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
1197 return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
1200 Left = GetExprVal (Expr->Left);
1201 Right = GetExprVal (Expr->Right);
1203 Error (ERR_DIV_BY_ZERO);
1206 return Left / Right;
1209 Left = GetExprVal (Expr->Left);
1210 Right = GetExprVal (Expr->Right);
1212 Error (ERR_MOD_BY_ZERO);
1215 return Left % Right;
1218 return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
1221 return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
1224 return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
1227 return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
1230 return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
1233 return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));
1236 return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));
1239 return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));
1242 return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));
1245 return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));
1248 return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));
1250 case EXPR_UNARY_MINUS:
1251 return -GetExprVal (Expr->Left);
1254 return ~GetExprVal (Expr->Left);
1257 return GetExprVal (Expr->Left) & 0xFF;
1260 return (GetExprVal (Expr->Left) >> 8) & 0xFF;
1263 return (GetExprVal (Expr->Left) >> 16) & 0xFF;
1266 return (GetExprVal (Expr->Left) >> 24) & 0xFF;
1269 Left = GetExprVal (Expr->Left);
1270 return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
1273 return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
1276 return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
1279 return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
1282 return !GetExprVal (Expr->Left);
1285 Internal ("GetExprVal called for EXPR_ULABEL");
1290 Internal ("Unknown Op type: %u", Expr->Op);
1298 static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
1299 /* Remove resolved symbols from the tree by cloning symbol expressions */
1301 /* Accept NULL pointers */
1306 /* Special node handling */
1310 if (SymHasExpr (Expr->V.Sym)) {
1311 /* The symbol has an expression tree */
1312 SymEntry* Sym = Expr->V.Sym;
1313 if (SymHasUserMark (Sym)) {
1314 /* Circular definition */
1318 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1319 return LiteralExpr (0); /* Return a dummy value */
1322 Expr = RemoveSyms (GetSymExpr (Sym), 1);
1323 SymUnmarkUser (Sym);
1325 } else if (SymIsConst (Expr->V.Sym)) {
1326 /* The symbol is a constant */
1327 return LiteralExpr (GetSymVal (Expr->V.Sym));
1332 if (ULabCanResolve ()) {
1333 ExprNode* NewExpr = ULabResolve (Expr->V.Val);
1341 /* Clone the current node if needed */
1344 /* Create a new node */
1345 ExprNode* Clone = NewExprNode ();
1347 /* Clone the operation */
1348 Clone->Op = Expr->Op;
1350 /* Clone the attribute if needed */
1355 Clone->V.Val = Expr->V.Val;
1359 Clone->V.Sym = Expr->V.Sym;
1363 Clone->V.SegNum = Expr->V.SegNum;
1368 /* Clone the tree nodes */
1369 Clone->Left = RemoveSyms (Expr->Left, MustClone);
1370 Clone->Right = RemoveSyms (Expr->Right, MustClone);
1377 /* Nothing to clone */
1378 Expr->Left = RemoveSyms (Expr->Left, MustClone);
1379 Expr->Right = RemoveSyms (Expr->Right, MustClone);
1389 static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
1390 /* Extract and evaluate all constant factors in an subtree that has only
1391 * additions and subtractions.
1394 if (Expr->Op == EXPR_LITERAL) {
1396 *Val -= Expr->V.Val;
1398 *Val += Expr->V.Val;
1400 FreeExprNode (Expr);
1404 if (Expr->Op == EXPR_PLUS || Expr->Op == EXPR_MINUS) {
1407 Left = ConstExtract (Expr->Left, Val, Sign);
1408 if (Expr->Op == EXPR_MINUS) {
1411 Right = ConstExtract (Expr->Right, Val, Sign);
1412 if (Left == 0 && Right == 0) {
1413 FreeExprNode (Expr);
1415 } else if (Left == 0) {
1416 FreeExprNode (Expr);
1418 } else if (Right == 0) {
1419 FreeExprNode (Expr);
1422 /* Check for SEG - SEG which is now possible */
1423 if (Left->Op == EXPR_SEGMENT && Right->Op == EXPR_SEGMENT &&
1424 Left->V.SegNum == Right->V.SegNum) {
1425 /* SEG - SEG, remove it completely */
1426 FreeExprNode (Left);
1427 FreeExprNode (Right);
1428 FreeExprNode (Expr);
1432 Expr->Right = Right;
1438 /* Some other sort of node, finalize the terms */
1440 Expr->Left = FinalizeExpr (Expr->Left);
1443 Expr->Right = FinalizeExpr (Expr->Right);
1451 ExprNode* FinalizeExpr (ExprNode* Expr)
1452 /* Resolve any symbols by cloning the symbol expression tree instead of the
1453 * symbol reference, then try to simplify the expression as much as possible.
1454 * This function must only be called if all symbols are resolved (no undefined
1461 Expr = RemoveSyms (Expr, 0);
1462 Expr = ConstExtract (Expr, &Val, 1);
1464 /* Reduced to a literal value */
1465 Expr = LiteralExpr (Val);
1467 /* Extracted a value */
1471 N->Right = LiteralExpr (Val);
1479 ExprNode* CloneExpr (ExprNode* Expr)
1480 /* Clone the given expression tree. The function will simply clone symbol
1481 * nodes, it will not resolve them.
1486 /* Accept NULL pointers */
1491 /* Get a new node */
1492 Clone = NewExprNode ();
1494 /* Clone the operation */
1495 Clone->Op = Expr->Op;
1497 /* Clone the attribute if needed */
1502 Clone->V.Val = Expr->V.Val;
1506 Clone->V.Sym = Expr->V.Sym;
1510 Clone->V.SegNum = Expr->V.SegNum;
1515 /* Clone the tree nodes */
1516 Clone->Left = CloneExpr (Expr->Left);
1517 Clone->Right = CloneExpr (Expr->Right);
1525 void WriteExpr (ExprNode* Expr)
1526 /* Write the given expression to the object file */
1528 /* Null expressions are encoded by a type byte of zero */
1534 /* Write the expression code */
1535 ObjWrite8 (Expr->Op);
1537 /* If the is a leafnode, write the expression attribute, otherwise
1538 * write the expression operands.
1543 ObjWrite32 (Expr->V.Val);
1547 /* Maybe we should use a code here? */
1548 CHECK (SymIsImport (Expr->V.Sym)); /* Safety */
1549 ObjWrite16 (GetSymIndex (Expr->V.Sym));
1553 ObjWrite8 (Expr->V.SegNum);
1557 Internal ("WriteExpr: Cannot write EXPR_ULABEL nodes");
1561 /* Not a leaf node */
1562 WriteExpr (Expr->Left);
1563 WriteExpr (Expr->Right);