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 /*****************************************************************************/
56 /*****************************************************************************/
58 /*****************************************************************************/
62 /* Since all expressions are first packed into expression trees, and each
63 * expression tree node is allocated on the heap, we add some type of special
64 * purpose memory allocation here: Instead of freeing the nodes, we save some
65 * number of freed nodes for later and remember them in a single linked list
66 * using the Left link.
68 #define MAX_FREE_NODES 64
69 static ExprNode* FreeExprNodes = 0;
70 static unsigned FreeNodeCount = 0;
74 /*****************************************************************************/
76 /*****************************************************************************/
80 static ExprNode* NewExprNode (void)
81 /* Create a new expression node */
85 /* Do we have some nodes in the list already? */
87 /* Use first node from list */
89 FreeExprNodes = N->Left;
91 /* Allocate fresh memory */
92 N = xmalloc (sizeof (ExprNode));
95 N->Left = N->Right = 0;
103 static void FreeExprNode (ExprNode* E)
107 if (FreeNodeCount < MAX_FREE_NODES) {
108 /* Remember this node for later */
109 E->Left = FreeExprNodes;
112 /* Free the memory */
120 /*****************************************************************************/
122 /*****************************************************************************/
126 static ExprNode* Expr0 (void);
130 int IsByteRange (long Val)
131 /* Return true if this is a byte value */
133 return (Val & ~0xFFL) == 0;
138 int IsWordRange (long Val)
139 /* Return true if this is a word value */
141 return (Val & ~0xFFFF) == 0;
146 static int FuncBlank (void)
147 /* Handle the .BLANK builtin function */
149 /* Assume no tokens if the closing brace follows (this is not correct in
150 * all cases, since the token may be the closing brace, but this will
151 * give a syntax error anyway and may not be handled by .BLANK.
153 if (Tok == TOK_RPAREN) {
157 /* Skip any tokens */
159 while (Tok != TOK_SEP && Tok != TOK_EOF) {
160 if (Tok == TOK_LPAREN) {
162 } else if (Tok == TOK_RPAREN) {
178 static int FuncConst (void)
179 /* Handle the .CONST builtin function */
181 /* Read an expression */
182 ExprNode* Expr = Expression ();
184 /* Check the constness of the expression */
185 int Result = IsConstExpr (Expr);
187 /* Free the expression */
196 static int FuncDefined (void)
197 /* Handle the .DEFINED builtin function */
201 if (Tok != TOK_IDENT) {
202 Error (ERR_IDENT_EXPECTED);
203 if (Tok != TOK_RPAREN) {
207 Result = SymIsDef (SVal);
217 static int DoMatch (enum TC EqualityLevel)
218 /* Handle the .MATCH and .XMATCH builtin functions */
225 /* A list of tokens follows. Read this list and remember it building a
226 * single linked list of tokens including attributes. The list is
227 * terminated by a comma.
229 while (Tok != TOK_COMMA) {
231 /* We may not end-of-line of end-of-file here */
232 if (Tok == TOK_SEP || Tok == TOK_EOF) {
233 Error (ERR_UNEXPECTED_EOL);
237 /* Get a node with this token */
238 Node = NewTokNode ();
240 /* Insert the node into the list */
255 /* Read the second list which is terminated by the right parenthesis and
256 * compare each token against the one in the first list.
260 while (Tok != TOK_RPAREN) {
262 /* We may not end-of-line of end-of-file here */
263 if (Tok == TOK_SEP || Tok == TOK_EOF) {
264 Error (ERR_UNEXPECTED_EOL);
268 /* Compare the tokens if the result is not already known */
271 /* The second list is larger than the first one */
273 } else if (TokCmp (Node) < EqualityLevel) {
274 /* Tokens do not match */
279 /* Next token in first list */
284 /* Next token in current list */
288 /* Check if there are remaining tokens in the first list */
293 /* Free the token list */
300 /* Done, return the result */
306 static int FuncMatch (void)
307 /* Handle the .MATCH function */
309 return DoMatch (tcSameToken);
314 static int FuncReferenced (void)
315 /* Handle the .REFERENCED builtin function */
319 if (Tok != TOK_IDENT) {
320 Error (ERR_IDENT_EXPECTED);
321 if (Tok != TOK_RPAREN) {
325 Result = SymIsRef (SVal);
335 static int FuncStrAt (void)
336 /* Handle the .STRAT function */
338 char Str [sizeof(SVal)];
341 /* String constant expected */
342 if (Tok != TOK_STRCON) {
343 Error (ERR_STRCON_EXPECTED);
349 /* Remember the string and skip it */
353 /* Comma must follow */
356 /* Expression expected */
357 Index = ConstExpression ();
359 /* Must be a valid index */
360 if (Index >= strlen (Str)) {
365 /* Return the char, handle as unsigned */
366 return (unsigned char) Str[(size_t)Index];
371 static int FuncStrLen (void)
372 /* Handle the .STRLEN function */
374 /* String constant expected */
375 if (Tok != TOK_STRCON) {
377 Error (ERR_STRCON_EXPECTED);
378 /* Smart error recovery */
379 if (Tok != TOK_RPAREN) {
386 /* Get the length of the string */
387 int Len = strlen (SVal);
389 /* Skip the string */
392 /* Return the length */
400 static int FuncTCount (void)
401 /* Handle the .TCOUNT function */
403 /* We have a list of tokens that ends with the closing paren. Skip
404 * the tokens, handling nested braces and count them.
408 while (Parens != 0 || Tok != TOK_RPAREN) {
410 /* Check for end of line or end of input. Since the calling function
411 * will check for the closing paren, we don't need to print an error
412 * here, just bail out.
414 if (Tok == TOK_SEP || Tok == TOK_EOF) {
421 /* Keep track of the nesting level */
423 case TOK_LPAREN: ++Parens; break;
424 case TOK_RPAREN: --Parens; break;
432 /* Return the number of tokens */
438 static int FuncXMatch (void)
439 /* Handle the .XMATCH function */
441 return DoMatch (tcIdentical);
446 static ExprNode* Function (int (*F) (void))
447 /* Handle builtin functions */
451 /* Skip the keyword */
454 /* Expression must be enclosed in braces */
455 if (Tok != TOK_LPAREN) {
456 Error (ERR_LPAREN_EXPECTED);
458 return LiteralExpr (0);
462 /* Call the function itself */
465 /* Closing brace must follow */
468 /* Return an expression node with the boolean code */
469 return LiteralExpr (Result);
474 static ExprNode* Factor (void)
482 N = LiteralExpr (IVal);
487 N = LiteralExpr (TgtTranslateChar (IVal));
493 if (Tok != TOK_IDENT) {
494 Error (ERR_IDENT_EXPECTED);
495 N = LiteralExpr (0); /* Dummy */
497 S = SymRefGlobal (SVal);
498 if (SymIsConst (S)) {
499 /* Use the literal value instead */
500 N = LiteralExpr (GetSymVal (S));
502 /* Create symbol node */
513 if (SymIsConst (S)) {
514 /* Use the literal value instead */
515 N = LiteralExpr (GetSymVal (S));
517 /* Create symbol node */
534 N->Op = EXPR_UNARY_MINUS;
571 N = Function (FuncBlank);
575 N = Function (FuncConst);
579 N = LiteralExpr (GetCPU());
584 N = Function (FuncDefined);
588 N = Function (FuncMatch);
592 N = Function (FuncReferenced);
596 N = Function (FuncStrAt);
600 N = Function (FuncStrLen);
604 N = Function (FuncTCount);
608 N = Function (FuncXMatch);
612 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
613 /* A character constant */
614 N = LiteralExpr (TgtTranslateChar (SVal[0]));
616 N = LiteralExpr (0); /* Dummy */
627 static ExprNode* Term (void)
631 /* Read left hand side */
634 /* Handle multiplicative operations */
635 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
636 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
639 /* Create a new node and insert the left expression */
640 ExprNode* Left = Root;
641 Root = NewExprNode ();
644 /* Determine the operator token */
646 case TOK_MUL: Root->Op = EXPR_MUL; break;
647 case TOK_DIV: Root->Op = EXPR_DIV; break;
648 case TOK_MOD: Root->Op = EXPR_MOD; break;
649 case TOK_AND: Root->Op = EXPR_AND; break;
650 case TOK_XOR: Root->Op = EXPR_XOR; break;
651 case TOK_SHL: Root->Op = EXPR_SHL; break;
652 case TOK_SHR: Root->Op = EXPR_SHR; break;
653 default: Internal ("Invalid token");
657 /* Parse the right hand side */
658 Root->Right = Factor ();
662 /* Return the expression tree we've created */
668 static ExprNode* SimpleExpr (void)
672 /* Read left hand side */
675 /* Handle additive operations */
676 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
678 /* Create a new node and insert the left expression */
679 ExprNode* Left = Root;
680 Root = NewExprNode ();
683 /* Determine the operator token */
685 case TOK_PLUS: Root->Op = EXPR_PLUS; break;
686 case TOK_MINUS: Root->Op = EXPR_MINUS; break;
687 case TOK_OR: Root->Op = EXPR_OR; break;
688 default: Internal ("Invalid token");
692 /* Parse the right hand side */
693 Root->Right = Term ();
697 /* Return the expression tree we've created */
703 static ExprNode* BoolExpr (void)
704 /* Evaluate a boolean expression */
706 /* Read left hand side */
707 ExprNode* Root = SimpleExpr ();
709 /* Handle booleans */
710 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
711 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
713 /* Create a new node and insert the left expression */
714 ExprNode* Left = Root;
715 Root = NewExprNode ();
718 /* Determine the operator token */
720 case TOK_EQ: Root->Op = EXPR_EQ; break;
721 case TOK_NE: Root->Op = EXPR_NE; break;
722 case TOK_LT: Root->Op = EXPR_LT; break;
723 case TOK_GT: Root->Op = EXPR_GT; break;
724 case TOK_LE: Root->Op = EXPR_LE; break;
725 case TOK_GE: Root->Op = EXPR_GE; break;
726 default: Internal ("Invalid token");
730 /* Parse the right hand side */
731 Root->Right = SimpleExpr ();
735 /* Return the expression tree we've created */
741 static ExprNode* Expr2 (void)
742 /* Boolean operators: AND and XOR */
744 /* Read left hand side */
745 ExprNode* Root = BoolExpr ();
747 /* Handle booleans */
748 while (Tok == TOK_BAND || Tok == TOK_BXOR) {
750 /* Create a new node and insert the left expression */
751 ExprNode* Left = Root;
752 Root = NewExprNode ();
755 /* Determine the operator token */
757 case TOK_BAND: Root->Op = EXPR_BAND; break;
758 case TOK_BXOR: Root->Op = EXPR_BXOR; break;
759 default: Internal ("Invalid token");
763 /* Parse the right hand side */
764 Root->Right = BoolExpr ();
768 /* Return the expression tree we've created */
774 static ExprNode* Expr1 (void)
775 /* Boolean operators: OR */
777 /* Read left hand side */
778 ExprNode* Root = Expr2 ();
780 /* Handle booleans */
781 while (Tok == TOK_BOR) {
783 /* Create a new node and insert the left expression */
784 ExprNode* Left = Root;
785 Root = NewExprNode ();
788 /* Determine the operator token */
790 case TOK_BOR: Root->Op = EXPR_BOR; break;
791 default: Internal ("Invalid token");
795 /* Parse the right hand side */
796 Root->Right = Expr2 ();
800 /* Return the expression tree we've created */
806 static ExprNode* Expr0 (void)
807 /* Boolean operators: NOT */
811 /* Handle booleans */
812 if (Tok == TOK_BNOT) {
814 /* Create a new node */
815 Root = NewExprNode ();
817 /* Determine the operator token */
819 case TOK_BNOT: Root->Op = EXPR_BNOT; break;
820 default: Internal ("Invalid token");
824 /* Parse the left hand side, allow more BNOTs */
825 Root->Left = Expr0 ();
829 /* Read left hand side */
834 /* Return the expression tree we've created */
840 static ExprNode* SimplifyExpr (ExprNode* Root)
841 /* Try to simplify the given expression tree */
844 SimplifyExpr (Root->Left);
845 SimplifyExpr (Root->Right);
846 if (IsConstExpr (Root)) {
847 /* The complete expression is constant */
848 Root->V.Val = GetExprVal (Root);
849 Root->Op = EXPR_LITERAL;
850 FreeExpr (Root->Left);
851 FreeExpr (Root->Right);
852 Root->Left = Root->Right = 0;
860 ExprNode* Expression (void)
861 /* Evaluate an expression, build the expression tree on the heap and return
862 * a pointer to the root of the tree.
865 return SimplifyExpr (Expr0 ());
870 long ConstExpression (void)
871 /* Parse an expression. Check if the expression is const, and print an error
872 * message if not. Return the value of the expression, or a dummy, if it is
876 /* Read the expression, and call finalize (exception here, since we
879 ExprNode* Expr = FinalizeExpr (Expression ());
881 /* Return the value */
882 if (IsConstExpr (Expr)) {
883 return GetExprVal (Expr);
885 Error (ERR_CONSTEXPR_EXPECTED);
892 ExprNode* LiteralExpr (long Val)
893 /* Return an expression tree that encodes the given literal value */
895 ExprNode* Expr = NewExprNode ();
896 Expr->Op = EXPR_LITERAL;
903 ExprNode* CurrentPC (void)
904 /* Return the current program counter as expression */
910 /* Create SegmentBase + Offset */
911 Left = NewExprNode ();
912 Left->Op = EXPR_SEGMENT;
913 Left->V.SegNum = GetSegNum ();
915 Root = NewExprNode ();
917 Root->Right = LiteralExpr (GetPC ());
918 Root->Op = EXPR_PLUS;
920 /* Absolute mode, just return PC value */
921 Root = LiteralExpr (GetPC ());
929 ExprNode* SwapExpr (ExprNode* Expr)
930 /* Return an extended expression with lo and hi bytes swapped */
932 ExprNode* N = NewExprNode ();
940 ExprNode* BranchExpr (unsigned Offs)
941 /* Return an expression that encodes the difference between current PC plus
942 * offset and the target expression (that is, Expression() - (*+Offs) ).
951 Left = NewExprNode ();
952 Left->Op = EXPR_SEGMENT;
953 Left->V.SegNum = GetSegNum ();
957 N->Right = LiteralExpr (GetPC () + Offs);
960 N = LiteralExpr (GetPC () + Offs);
963 /* Create the root node */
964 Root = NewExprNode ();
965 Root->Left = Expression ();
967 Root->Op = EXPR_MINUS;
969 /* Return the result */
970 return SimplifyExpr (Root);
975 ExprNode* ULabelExpr (unsigned Num)
976 /* Return an expression for an unnamed label with the given index */
978 /* Get an expression node */
979 ExprNode* Node = NewExprNode ();
982 Node->Op = EXPR_ULABEL;
985 /* Return the new node */
991 void FreeExpr (ExprNode* Root)
992 /* Free the expression, Root is pointing to. */
995 FreeExpr (Root->Left);
996 FreeExpr (Root->Right);
1003 ExprNode* ForceWordExpr (ExprNode* Expr)
1004 /* Force the given expression into a word and return the result. */
1006 /* And the expression by $FFFF to force it into word size */
1007 ExprNode* Root = NewExprNode ();
1009 Root->Op = EXPR_AND;
1010 Root->Right = LiteralExpr (0xFFFF);
1012 /* Return the result */
1018 int IsConstExpr (ExprNode* Root)
1019 /* Return true if the given expression is a constant expression, that is, one
1020 * with no references to external symbols.
1026 if (EXPR_IS_LEAF (Root->Op)) {
1034 if (SymHasUserMark (Sym)) {
1038 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1042 Const = SymIsConst (Sym);
1043 SymUnmarkUser (Sym);
1051 } else if (EXPR_IS_UNARY (Root->Op)) {
1053 return IsConstExpr (Root->Left);
1057 /* We must handle shortcut boolean expressions here */
1061 if (IsConstExpr (Root->Left)) {
1062 /* lhs is const, if it is zero, don't eval right */
1063 if (GetExprVal (Root->Left) == 0) {
1066 return IsConstExpr (Root->Right);
1069 /* lhs not const --> tree not const */
1075 if (IsConstExpr (Root->Left)) {
1076 /* lhs is const, if it is not zero, don't eval right */
1077 if (GetExprVal (Root->Left) != 0) {
1080 return IsConstExpr (Root->Right);
1083 /* lhs not const --> tree not const */
1089 /* All others are handled normal */
1090 return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
1097 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1098 /* Internal routine that is recursively called to check if there is a zeropage
1099 * symbol in the expression tree.
1103 switch (N->Op & EXPR_TYPEMASK) {
1109 if (SymIsZP (N->V.Sym)) {
1115 if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
1123 case EXPR_UNARYNODE:
1124 CheckByteExpr (N->Left, IsByte);
1127 case EXPR_BINARYNODE:
1128 CheckByteExpr (N->Left, IsByte);
1129 CheckByteExpr (N->Right, IsByte);
1133 Internal ("Unknown expression op: %02X", N->Op);
1140 int IsByteExpr (ExprNode* Root)
1141 /* Return true if this is a byte expression */
1145 if (IsConstExpr (Root)) {
1146 if (Root->Op != EXPR_LITERAL) {
1147 SimplifyExpr (Root);
1149 return IsByteRange (GetExprVal (Root));
1150 } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
1151 Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
1152 /* Symbol forced to have byte range */
1155 /* We have undefined symbols in the expression. Assume that the
1156 * expression is a byte expression if there is at least one symbol
1157 * declared as zeropage in it. Being wrong here is not a very big
1158 * problem since the linker knows about all symbols and detects
1159 * error like mixing absolute and zeropage labels.
1162 CheckByteExpr (Root, &IsByte);
1169 long GetExprVal (ExprNode* Expr)
1170 /* Get the value of a constant expression */
1180 return GetSymVal (Expr->V.Sym);
1183 return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
1186 return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
1189 return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
1192 Left = GetExprVal (Expr->Left);
1193 Right = GetExprVal (Expr->Right);
1195 Error (ERR_DIV_BY_ZERO);
1198 return Left / Right;
1201 Left = GetExprVal (Expr->Left);
1202 Right = GetExprVal (Expr->Right);
1204 Error (ERR_MOD_BY_ZERO);
1207 return Left % Right;
1210 return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
1213 return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
1216 return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
1219 return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
1222 return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
1225 return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));
1228 return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));
1231 return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));
1234 return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));
1237 return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));
1240 return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));
1242 case EXPR_UNARY_MINUS:
1243 return -GetExprVal (Expr->Left);
1246 return ~GetExprVal (Expr->Left);
1249 return GetExprVal (Expr->Left) & 0xFF;
1252 return (GetExprVal (Expr->Left) >> 8) & 0xFF;
1255 return (GetExprVal (Expr->Left) >> 16) & 0xFF;
1258 return (GetExprVal (Expr->Left) >> 24) & 0xFF;
1261 Left = GetExprVal (Expr->Left);
1262 return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
1265 return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
1268 return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
1271 return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
1274 return !GetExprVal (Expr->Left);
1277 Internal ("GetExprVal called for EXPR_ULABEL");
1282 Internal ("Unknown Op type: %u", Expr->Op);
1290 static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
1291 /* Remove resolved symbols from the tree by cloning symbol expressions */
1293 /* Accept NULL pointers */
1298 /* Special node handling */
1302 if (SymHasExpr (Expr->V.Sym)) {
1303 /* The symbol has an expression tree */
1304 SymEntry* Sym = Expr->V.Sym;
1305 if (SymHasUserMark (Sym)) {
1306 /* Circular definition */
1310 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1311 return LiteralExpr (0); /* Return a dummy value */
1314 Expr = RemoveSyms (GetSymExpr (Sym), 1);
1315 SymUnmarkUser (Sym);
1317 } else if (SymIsConst (Expr->V.Sym)) {
1318 /* The symbol is a constant */
1319 return LiteralExpr (GetSymVal (Expr->V.Sym));
1324 if (ULabCanResolve ()) {
1325 ExprNode* NewExpr = ULabResolve (Expr->V.Val);
1333 /* Clone the current node if needed */
1336 /* Create a new node */
1337 ExprNode* Clone = NewExprNode ();
1339 /* Clone the operation */
1340 Clone->Op = Expr->Op;
1342 /* Clone the attribute if needed */
1347 Clone->V.Val = Expr->V.Val;
1351 Clone->V.Sym = Expr->V.Sym;
1355 Clone->V.SegNum = Expr->V.SegNum;
1360 /* Clone the tree nodes */
1361 Clone->Left = RemoveSyms (Expr->Left, MustClone);
1362 Clone->Right = RemoveSyms (Expr->Right, MustClone);
1369 /* Nothing to clone */
1370 Expr->Left = RemoveSyms (Expr->Left, MustClone);
1371 Expr->Right = RemoveSyms (Expr->Right, MustClone);
1381 static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
1382 /* Extract and evaluate all constant factors in an subtree that has only
1383 * additions and subtractions.
1386 if (Expr->Op == EXPR_LITERAL) {
1388 *Val -= Expr->V.Val;
1390 *Val += Expr->V.Val;
1392 FreeExprNode (Expr);
1396 if (Expr->Op == EXPR_PLUS || Expr->Op == EXPR_MINUS) {
1399 Left = ConstExtract (Expr->Left, Val, Sign);
1400 if (Expr->Op == EXPR_MINUS) {
1403 Right = ConstExtract (Expr->Right, Val, Sign);
1404 if (Left == 0 && Right == 0) {
1405 FreeExprNode (Expr);
1407 } else if (Left == 0) {
1408 FreeExprNode (Expr);
1410 } else if (Right == 0) {
1411 FreeExprNode (Expr);
1414 /* Check for SEG - SEG which is now possible */
1415 if (Left->Op == EXPR_SEGMENT && Right->Op == EXPR_SEGMENT &&
1416 Left->V.SegNum == Right->V.SegNum) {
1417 /* SEG - SEG, remove it completely */
1418 FreeExprNode (Left);
1419 FreeExprNode (Right);
1420 FreeExprNode (Expr);
1424 Expr->Right = Right;
1430 /* Some other sort of node, finalize the terms */
1432 Expr->Left = FinalizeExpr (Expr->Left);
1435 Expr->Right = FinalizeExpr (Expr->Right);
1443 ExprNode* FinalizeExpr (ExprNode* Expr)
1444 /* Resolve any symbols by cloning the symbol expression tree instead of the
1445 * symbol reference, then try to simplify the expression as much as possible.
1446 * This function must only be called if all symbols are resolved (no undefined
1453 Expr = RemoveSyms (Expr, 0);
1454 Expr = ConstExtract (Expr, &Val, 1);
1456 /* Reduced to a literal value */
1457 Expr = LiteralExpr (Val);
1459 /* Extracted a value */
1463 N->Right = LiteralExpr (Val);
1471 ExprNode* CloneExpr (ExprNode* Expr)
1472 /* Clone the given expression tree. The function will simply clone symbol
1473 * nodes, it will not resolve them.
1478 /* Accept NULL pointers */
1483 /* Get a new node */
1484 Clone = NewExprNode ();
1486 /* Clone the operation */
1487 Clone->Op = Expr->Op;
1489 /* Clone the attribute if needed */
1494 Clone->V.Val = Expr->V.Val;
1498 Clone->V.Sym = Expr->V.Sym;
1502 Clone->V.SegNum = Expr->V.SegNum;
1507 /* Clone the tree nodes */
1508 Clone->Left = CloneExpr (Expr->Left);
1509 Clone->Right = CloneExpr (Expr->Right);
1517 void WriteExpr (ExprNode* Expr)
1518 /* Write the given expression to the object file */
1520 /* Null expressions are encoded by a type byte of zero */
1526 /* Write the expression code */
1527 ObjWrite8 (Expr->Op);
1529 /* If the is a leafnode, write the expression attribute, otherwise
1530 * write the expression operands.
1535 ObjWrite32 (Expr->V.Val);
1539 /* Maybe we should use a code here? */
1540 CHECK (SymIsImport (Expr->V.Sym)); /* Safety */
1541 ObjWrite16 (GetSymIndex (Expr->V.Sym));
1545 ObjWrite8 (Expr->V.SegNum);
1549 Internal ("WriteExpr: Cannot write EXPR_ULABEL nodes");
1553 /* Not a leaf node */
1554 WriteExpr (Expr->Left);
1555 WriteExpr (Expr->Right);