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 /*****************************************************************************/
54 /*****************************************************************************/
56 /*****************************************************************************/
60 /* Since all expressions are first packed into expression trees, and each
61 * expression tree node is allocated on the heap, we add some type of special
62 * purpose memory allocation here: Instead of freeing the nodes, we save some
63 * number of freed nodes for later and remember them in a single linked list
64 * using the Left link.
66 #define MAX_FREE_NODES 64
67 static ExprNode* FreeExprNodes = 0;
68 static unsigned FreeNodeCount = 0;
72 /*****************************************************************************/
74 /*****************************************************************************/
78 static ExprNode* NewExprNode (void)
79 /* Create a new expression node */
83 /* Do we have some nodes in the list already? */
85 /* Use first node from list */
87 FreeExprNodes = N->Left;
89 /* Allocate fresh memory */
90 N = xmalloc (sizeof (ExprNode));
93 N->Left = N->Right = 0;
101 static void FreeExprNode (ExprNode* E)
105 if (FreeNodeCount < MAX_FREE_NODES) {
106 /* Remember this node for later */
107 E->Left = FreeExprNodes;
110 /* Free the memory */
118 /*****************************************************************************/
120 /*****************************************************************************/
124 static ExprNode* Expr0 (void);
128 int IsByteRange (long Val)
129 /* Return true if this is a byte value */
131 return (Val & ~0xFFL) == 0;
136 int IsWordRange (long Val)
137 /* Return true if this is a word value */
139 return (Val & ~0xFFFF) == 0;
144 static int FuncBlank (void)
145 /* Handle the .BLANK builtin function */
147 /* Assume no tokens if the closing brace follows (this is not correct in
148 * all cases, since the token may be the closing brace, but this will
149 * give a syntax error anyway and may not be handled by .BLANK.
151 if (Tok == TOK_RPAREN) {
155 /* Skip any tokens */
157 while (Tok != TOK_SEP && Tok != TOK_EOF) {
158 if (Tok == TOK_LPAREN) {
160 } else if (Tok == TOK_RPAREN) {
176 static int FuncConst (void)
177 /* Handle the .CONST builtin function */
179 /* Read an expression */
180 ExprNode* Expr = Expression ();
182 /* Check the constness of the expression */
183 int Result = IsConstExpr (Expr);
185 /* Free the expression */
194 static int FuncDefined (void)
195 /* Handle the .DEFINED builtin function */
199 if (Tok != TOK_IDENT) {
200 Error (ERR_IDENT_EXPECTED);
201 if (Tok != TOK_RPAREN) {
205 Result = SymIsDef (SVal);
215 static int DoMatch (enum TC EqualityLevel)
216 /* Handle the .MATCH and .XMATCH builtin functions */
223 /* A list of tokens follows. Read this list and remember it building a
224 * single linked list of tokens including attributes. The list is
225 * terminated by a comma.
227 while (Tok != TOK_COMMA) {
229 /* We may not end-of-line of end-of-file here */
230 if (Tok == TOK_SEP || Tok == TOK_EOF) {
231 Error (ERR_UNEXPECTED_EOL);
235 /* Get a node with this token */
236 Node = NewTokNode ();
238 /* Insert the node into the list */
253 /* Read the second list which is terminated by the right parenthesis and
254 * compare each token against the one in the first list.
258 while (Tok != TOK_RPAREN) {
260 /* We may not end-of-line of end-of-file here */
261 if (Tok == TOK_SEP || Tok == TOK_EOF) {
262 Error (ERR_UNEXPECTED_EOL);
266 /* Compare the tokens if the result is not already known */
269 /* The second list is larger than the first one */
271 } else if (TokCmp (Node) < EqualityLevel) {
272 /* Tokens do not match */
277 /* Next token in first list */
282 /* Next token in current list */
286 /* Check if there are remaining tokens in the first list */
291 /* Free the token list */
298 /* Done, return the result */
304 static int FuncMatch (void)
305 /* Handle the .MATCH function */
307 return DoMatch (tcSameToken);
312 static int FuncReferenced (void)
313 /* Handle the .REFERENCED builtin function */
317 if (Tok != TOK_IDENT) {
318 Error (ERR_IDENT_EXPECTED);
319 if (Tok != TOK_RPAREN) {
323 Result = SymIsRef (SVal);
333 static int FuncStrAt (void)
334 /* Handle the .STRAT function */
336 char Str [sizeof(SVal)];
339 /* String constant expected */
340 if (Tok != TOK_STRCON) {
341 Error (ERR_STRCON_EXPECTED);
347 /* Remember the string and skip it */
351 /* Comma must follow */
354 /* Expression expected */
355 Index = ConstExpression ();
357 /* Must be a valid index */
358 if (Index >= strlen (Str)) {
363 /* Return the char, handle as unsigned */
364 return (unsigned char) Str[(size_t)Index];
369 static int FuncStrLen (void)
370 /* Handle the .STRLEN function */
372 /* String constant expected */
373 if (Tok != TOK_STRCON) {
375 Error (ERR_STRCON_EXPECTED);
376 /* Smart error recovery */
377 if (Tok != TOK_RPAREN) {
384 /* Get the length of the string */
385 int Len = strlen (SVal);
387 /* Skip the string */
390 /* Return the length */
398 static int FuncTCount (void)
399 /* Handle the .TCOUNT function */
401 /* We have a list of tokens that ends with the closing paren. Skip
402 * the tokens, handling nested braces and count them.
406 while (Parens != 0 || Tok != TOK_RPAREN) {
408 /* Check for end of line or end of input. Since the calling function
409 * will check for the closing paren, we don't need to print an error
410 * here, just bail out.
412 if (Tok == TOK_SEP || Tok == TOK_EOF) {
419 /* Keep track of the nesting level */
421 case TOK_LPAREN: ++Parens; break;
422 case TOK_RPAREN: --Parens; break;
430 /* Return the number of tokens */
436 static int FuncXMatch (void)
437 /* Handle the .XMATCH function */
439 return DoMatch (tcIdentical);
444 static ExprNode* Function (int (*F) (void))
445 /* Handle builtin functions */
449 /* Skip the keyword */
452 /* Expression must be enclosed in braces */
453 if (Tok != TOK_LPAREN) {
454 Error (ERR_LPAREN_EXPECTED);
456 return LiteralExpr (0);
460 /* Call the function itself */
463 /* Closing brace must follow */
466 /* Return an expression node with the boolean code */
467 return LiteralExpr (Result);
472 static ExprNode* Factor (void)
481 N = LiteralExpr (IVal);
487 if (Tok != TOK_IDENT) {
488 Error (ERR_IDENT_EXPECTED);
489 N = LiteralExpr (0); /* Dummy */
491 S = SymRefGlobal (SVal);
492 if (SymIsConst (S)) {
493 /* Use the literal value instead */
494 N = LiteralExpr (GetSymVal (S));
496 /* Create symbol node */
507 if (SymIsConst (S)) {
508 /* Use the literal value instead */
509 N = LiteralExpr (GetSymVal (S));
511 /* Create symbol node */
528 N->Op = EXPR_UNARY_MINUS;
565 N = Function (FuncBlank);
569 N = Function (FuncConst);
573 N = LiteralExpr (GetCPU());
578 N = Function (FuncDefined);
582 N = Function (FuncMatch);
586 N = Function (FuncReferenced);
590 N = Function (FuncStrAt);
594 N = Function (FuncStrLen);
598 N = Function (FuncTCount);
602 N = Function (FuncXMatch);
606 N = LiteralExpr (0); /* Dummy */
616 static ExprNode* Term (void)
620 /* Read left hand side */
623 /* Handle multiplicative operations */
624 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
625 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
628 /* Create a new node and insert the left expression */
629 ExprNode* Left = Root;
630 Root = NewExprNode ();
633 /* Determine the operator token */
635 case TOK_MUL: Root->Op = EXPR_MUL; break;
636 case TOK_DIV: Root->Op = EXPR_DIV; break;
637 case TOK_MOD: Root->Op = EXPR_MOD; break;
638 case TOK_AND: Root->Op = EXPR_AND; break;
639 case TOK_XOR: Root->Op = EXPR_XOR; break;
640 case TOK_SHL: Root->Op = EXPR_SHL; break;
641 case TOK_SHR: Root->Op = EXPR_SHR; break;
642 default: Internal ("Invalid token");
646 /* Parse the right hand side */
647 Root->Right = Factor ();
651 /* Return the expression tree we've created */
657 static ExprNode* SimpleExpr (void)
661 /* Read left hand side */
664 /* Handle additive operations */
665 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
667 /* Create a new node and insert the left expression */
668 ExprNode* Left = Root;
669 Root = NewExprNode ();
672 /* Determine the operator token */
674 case TOK_PLUS: Root->Op = EXPR_PLUS; break;
675 case TOK_MINUS: Root->Op = EXPR_MINUS; break;
676 case TOK_OR: Root->Op = EXPR_OR; break;
677 default: Internal ("Invalid token");
681 /* Parse the right hand side */
682 Root->Right = Term ();
686 /* Return the expression tree we've created */
692 static ExprNode* BoolExpr (void)
693 /* Evaluate a boolean expression */
695 /* Read left hand side */
696 ExprNode* Root = SimpleExpr ();
698 /* Handle booleans */
699 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
700 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
702 /* Create a new node and insert the left expression */
703 ExprNode* Left = Root;
704 Root = NewExprNode ();
707 /* Determine the operator token */
709 case TOK_EQ: Root->Op = EXPR_EQ; break;
710 case TOK_NE: Root->Op = EXPR_NE; break;
711 case TOK_LT: Root->Op = EXPR_LT; break;
712 case TOK_GT: Root->Op = EXPR_GT; break;
713 case TOK_LE: Root->Op = EXPR_LE; break;
714 case TOK_GE: Root->Op = EXPR_GE; break;
715 default: Internal ("Invalid token");
719 /* Parse the right hand side */
720 Root->Right = SimpleExpr ();
724 /* Return the expression tree we've created */
730 static ExprNode* Expr2 (void)
731 /* Boolean operators: AND and XOR */
733 /* Read left hand side */
734 ExprNode* Root = BoolExpr ();
736 /* Handle booleans */
737 while (Tok == TOK_BAND || Tok == TOK_BXOR) {
739 /* Create a new node and insert the left expression */
740 ExprNode* Left = Root;
741 Root = NewExprNode ();
744 /* Determine the operator token */
746 case TOK_BAND: Root->Op = EXPR_BAND; break;
747 case TOK_BXOR: Root->Op = EXPR_BXOR; break;
748 default: Internal ("Invalid token");
752 /* Parse the right hand side */
753 Root->Right = BoolExpr ();
757 /* Return the expression tree we've created */
763 static ExprNode* Expr1 (void)
764 /* Boolean operators: OR */
766 /* Read left hand side */
767 ExprNode* Root = Expr2 ();
769 /* Handle booleans */
770 while (Tok == TOK_BOR) {
772 /* Create a new node and insert the left expression */
773 ExprNode* Left = Root;
774 Root = NewExprNode ();
777 /* Determine the operator token */
779 case TOK_BOR: Root->Op = EXPR_BOR; break;
780 default: Internal ("Invalid token");
784 /* Parse the right hand side */
785 Root->Right = Expr2 ();
789 /* Return the expression tree we've created */
795 static ExprNode* Expr0 (void)
796 /* Boolean operators: NOT */
800 /* Handle booleans */
801 if (Tok == TOK_BNOT) {
803 /* Create a new node */
804 Root = NewExprNode ();
806 /* Determine the operator token */
808 case TOK_BNOT: Root->Op = EXPR_BNOT; break;
809 default: Internal ("Invalid token");
813 /* Parse the left hand side, allow more BNOTs */
814 Root->Left = Expr0 ();
818 /* Read left hand side */
823 /* Return the expression tree we've created */
829 static ExprNode* SimplifyExpr (ExprNode* Root)
830 /* Try to simplify the given expression tree */
833 SimplifyExpr (Root->Left);
834 SimplifyExpr (Root->Right);
835 if (IsConstExpr (Root)) {
836 /* The complete expression is constant */
837 Root->V.Val = GetExprVal (Root);
838 Root->Op = EXPR_LITERAL;
839 FreeExpr (Root->Left);
840 FreeExpr (Root->Right);
841 Root->Left = Root->Right = 0;
849 ExprNode* Expression (void)
850 /* Evaluate an expression, build the expression tree on the heap and return
851 * a pointer to the root of the tree.
854 return SimplifyExpr (Expr0 ());
859 long ConstExpression (void)
860 /* Parse an expression. Check if the expression is const, and print an error
861 * message if not. Return the value of the expression, or a dummy, if it is
865 /* Read the expression, and call finalize (exception here, since we
868 ExprNode* Expr = FinalizeExpr (Expression ());
870 /* Return the value */
871 if (IsConstExpr (Expr)) {
872 return GetExprVal (Expr);
874 Error (ERR_CONSTEXPR_EXPECTED);
881 ExprNode* LiteralExpr (long Val)
882 /* Return an expression tree that encodes the given literal value */
884 ExprNode* Expr = NewExprNode ();
885 Expr->Op = EXPR_LITERAL;
892 ExprNode* CurrentPC (void)
893 /* Return the current program counter as expression */
899 /* Create SegmentBase + Offset */
900 Left = NewExprNode ();
901 Left->Op = EXPR_SEGMENT;
902 Left->V.SegNum = GetSegNum ();
904 Root = NewExprNode ();
906 Root->Right = LiteralExpr (GetPC ());
907 Root->Op = EXPR_PLUS;
909 /* Absolute mode, just return PC value */
910 Root = LiteralExpr (GetPC ());
918 ExprNode* SwapExpr (ExprNode* Expr)
919 /* Return an extended expression with lo and hi bytes swapped */
921 ExprNode* N = NewExprNode ();
929 ExprNode* BranchExpr (unsigned Offs)
930 /* Return an expression that encodes the difference between current PC plus
931 * offset and the target expression (that is, Expression() - (*+Offs) ).
940 Left = NewExprNode ();
941 Left->Op = EXPR_SEGMENT;
942 Left->V.SegNum = GetSegNum ();
946 N->Right = LiteralExpr (GetPC () + Offs);
949 N = LiteralExpr (GetPC () + Offs);
952 /* Create the root node */
953 Root = NewExprNode ();
954 Root->Left = Expression ();
956 Root->Op = EXPR_MINUS;
958 /* Return the result */
959 return SimplifyExpr (Root);
964 ExprNode* ULabelExpr (unsigned Num)
965 /* Return an expression for an unnamed label with the given index */
967 /* Get an expression node */
968 ExprNode* Node = NewExprNode ();
971 Node->Op = EXPR_ULABEL;
974 /* Return the new node */
980 void FreeExpr (ExprNode* Root)
981 /* Free the expression, Root is pointing to. */
984 FreeExpr (Root->Left);
985 FreeExpr (Root->Right);
992 ExprNode* ForceWordExpr (ExprNode* Expr)
993 /* Force the given expression into a word and return the result. */
995 /* And the expression by $FFFF to force it into word size */
996 ExprNode* Root = NewExprNode ();
999 Root->Right = LiteralExpr (0xFFFF);
1001 /* Return the result */
1007 int IsConstExpr (ExprNode* Root)
1008 /* Return true if the given expression is a constant expression, that is, one
1009 * with no references to external symbols.
1015 if (EXPR_IS_LEAF (Root->Op)) {
1023 if (SymHasUserMark (Sym)) {
1027 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1031 Const = SymIsConst (Sym);
1032 SymUnmarkUser (Sym);
1040 } else if (EXPR_IS_UNARY (Root->Op)) {
1042 return IsConstExpr (Root->Left);
1046 /* We must handle shortcut boolean expressions here */
1050 if (IsConstExpr (Root->Left)) {
1051 /* lhs is const, if it is zero, don't eval right */
1052 if (GetExprVal (Root->Left) == 0) {
1055 return IsConstExpr (Root->Right);
1058 /* lhs not const --> tree not const */
1064 if (IsConstExpr (Root->Left)) {
1065 /* lhs is const, if it is not zero, don't eval right */
1066 if (GetExprVal (Root->Left) != 0) {
1069 return IsConstExpr (Root->Right);
1072 /* lhs not const --> tree not const */
1078 /* All others are handled normal */
1079 return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
1086 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1087 /* Internal routine that is recursively called to check if there is a zeropage
1088 * symbol in the expression tree.
1092 switch (N->Op & EXPR_TYPEMASK) {
1098 if (SymIsZP (N->V.Sym)) {
1104 if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
1112 case EXPR_UNARYNODE:
1113 CheckByteExpr (N->Left, IsByte);
1116 case EXPR_BINARYNODE:
1117 CheckByteExpr (N->Left, IsByte);
1118 CheckByteExpr (N->Right, IsByte);
1122 Internal ("Unknown expression op: %02X", N->Op);
1129 int IsByteExpr (ExprNode* Root)
1130 /* Return true if this is a byte expression */
1134 if (IsConstExpr (Root)) {
1135 if (Root->Op != EXPR_LITERAL) {
1136 SimplifyExpr (Root);
1138 return IsByteRange (GetExprVal (Root));
1139 } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
1140 Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
1141 /* Symbol forced to have byte range */
1144 /* We have undefined symbols in the expression. Assume that the
1145 * expression is a byte expression if there is at least one symbol
1146 * declared as zeropage in it. Being wrong here is not a very big
1147 * problem since the linker knows about all symbols and detects
1148 * error like mixing absolute and zeropage labels.
1151 CheckByteExpr (Root, &IsByte);
1158 long GetExprVal (ExprNode* Expr)
1159 /* Get the value of a constant expression */
1169 return GetSymVal (Expr->V.Sym);
1172 return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
1175 return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
1178 return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
1181 Left = GetExprVal (Expr->Left);
1182 Right = GetExprVal (Expr->Right);
1184 Error (ERR_DIV_BY_ZERO);
1187 return Left / Right;
1190 Left = GetExprVal (Expr->Left);
1191 Right = GetExprVal (Expr->Right);
1193 Error (ERR_MOD_BY_ZERO);
1196 return Left % Right;
1199 return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
1202 return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
1205 return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
1208 return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
1211 return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
1214 return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));
1217 return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));
1220 return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));
1223 return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));
1226 return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));
1229 return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));
1231 case EXPR_UNARY_MINUS:
1232 return -GetExprVal (Expr->Left);
1235 return ~GetExprVal (Expr->Left);
1238 return GetExprVal (Expr->Left) & 0xFF;
1241 return (GetExprVal (Expr->Left) >> 8) & 0xFF;
1244 return (GetExprVal (Expr->Left) >> 16) & 0xFF;
1247 return (GetExprVal (Expr->Left) >> 24) & 0xFF;
1250 Left = GetExprVal (Expr->Left);
1251 return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
1254 return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
1257 return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
1260 return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
1263 return !GetExprVal (Expr->Left);
1266 Internal ("GetExprVal called for EXPR_ULABEL");
1271 Internal ("Unknown Op type: %u", Expr->Op);
1279 static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
1280 /* Remove resolved symbols from the tree by cloning symbol expressions */
1282 /* Accept NULL pointers */
1287 /* Special node handling */
1291 if (SymHasExpr (Expr->V.Sym)) {
1292 /* The symbol has an expression tree */
1293 SymEntry* Sym = Expr->V.Sym;
1294 if (SymHasUserMark (Sym)) {
1295 /* Circular definition */
1299 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1300 return LiteralExpr (0); /* Return a dummy value */
1303 Expr = RemoveSyms (GetSymExpr (Sym), 1);
1304 SymUnmarkUser (Sym);
1306 } else if (SymIsConst (Expr->V.Sym)) {
1307 /* The symbol is a constant */
1308 return LiteralExpr (GetSymVal (Expr->V.Sym));
1313 if (ULabCanResolve ()) {
1314 ExprNode* NewExpr = ULabResolve (Expr->V.Val);
1322 /* Clone the current node if needed */
1325 /* Create a new node */
1326 ExprNode* Clone = NewExprNode ();
1328 /* Clone the operation */
1329 Clone->Op = Expr->Op;
1331 /* Clone the attribute if needed */
1336 Clone->V.Val = Expr->V.Val;
1340 Clone->V.Sym = Expr->V.Sym;
1344 Clone->V.SegNum = Expr->V.SegNum;
1349 /* Clone the tree nodes */
1350 Clone->Left = RemoveSyms (Expr->Left, MustClone);
1351 Clone->Right = RemoveSyms (Expr->Right, MustClone);
1358 /* Nothing to clone */
1359 Expr->Left = RemoveSyms (Expr->Left, MustClone);
1360 Expr->Right = RemoveSyms (Expr->Right, MustClone);
1370 static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
1371 /* Extract and evaluate all constant factors in an subtree that has only
1372 * additions and subtractions.
1375 if (Expr->Op == EXPR_LITERAL) {
1377 *Val -= Expr->V.Val;
1379 *Val += Expr->V.Val;
1381 FreeExprNode (Expr);
1385 if (Expr->Op == EXPR_PLUS || Expr->Op == EXPR_MINUS) {
1388 Left = ConstExtract (Expr->Left, Val, Sign);
1389 if (Expr->Op == EXPR_MINUS) {
1392 Right = ConstExtract (Expr->Right, Val, Sign);
1393 if (Left == 0 && Right == 0) {
1394 FreeExprNode (Expr);
1396 } else if (Left == 0) {
1397 FreeExprNode (Expr);
1399 } else if (Right == 0) {
1400 FreeExprNode (Expr);
1403 /* Check for SEG - SEG which is now possible */
1404 if (Left->Op == EXPR_SEGMENT && Right->Op == EXPR_SEGMENT &&
1405 Left->V.SegNum == Right->V.SegNum) {
1406 /* SEG - SEG, remove it completely */
1407 FreeExprNode (Left);
1408 FreeExprNode (Right);
1409 FreeExprNode (Expr);
1413 Expr->Right = Right;
1419 /* Some other sort of node, finalize the terms */
1421 Expr->Left = FinalizeExpr (Expr->Left);
1424 Expr->Right = FinalizeExpr (Expr->Right);
1432 ExprNode* FinalizeExpr (ExprNode* Expr)
1433 /* Resolve any symbols by cloning the symbol expression tree instead of the
1434 * symbol reference, then try to simplify the expression as much as possible.
1435 * This function must only be called if all symbols are resolved (no undefined
1442 Expr = RemoveSyms (Expr, 0);
1443 Expr = ConstExtract (Expr, &Val, 1);
1445 /* Reduced to a literal value */
1446 Expr = LiteralExpr (Val);
1448 /* Extracted a value */
1452 N->Right = LiteralExpr (Val);
1460 ExprNode* CloneExpr (ExprNode* Expr)
1461 /* Clone the given expression tree. The function will simply clone symbol
1462 * nodes, it will not resolve them.
1467 /* Accept NULL pointers */
1472 /* Get a new node */
1473 Clone = NewExprNode ();
1475 /* Clone the operation */
1476 Clone->Op = Expr->Op;
1478 /* Clone the attribute if needed */
1483 Clone->V.Val = Expr->V.Val;
1487 Clone->V.Sym = Expr->V.Sym;
1491 Clone->V.SegNum = Expr->V.SegNum;
1496 /* Clone the tree nodes */
1497 Clone->Left = CloneExpr (Expr->Left);
1498 Clone->Right = CloneExpr (Expr->Right);
1506 void WriteExpr (ExprNode* Expr)
1507 /* Write the given expression to the object file */
1509 /* Null expressions are encoded by a type byte of zero */
1515 /* Write the expression code */
1516 ObjWrite8 (Expr->Op);
1518 /* If the is a leafnode, write the expression attribute, otherwise
1519 * write the expression operands.
1524 ObjWrite32 (Expr->V.Val);
1528 /* Maybe we should use a code here? */
1529 CHECK (SymIsImport (Expr->V.Sym)); /* Safety */
1530 ObjWrite16 (GetSymIndex (Expr->V.Sym));
1534 ObjWrite8 (Expr->V.SegNum);
1538 Internal ("WriteExpr: Cannot write EXPR_ULABEL nodes");
1542 /* Not a leaf node */
1543 WriteExpr (Expr->Left);
1544 WriteExpr (Expr->Right);