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 /*****************************************************************************/
55 /*****************************************************************************/
57 /*****************************************************************************/
61 /* Since all expressions are first packed into expression trees, and each
62 * expression tree node is allocated on the heap, we add some type of special
63 * purpose memory allocation here: Instead of freeing the nodes, we save some
64 * number of freed nodes for later and remember them in a single linked list
65 * using the Left link.
67 #define MAX_FREE_NODES 64
68 static ExprNode* FreeExprNodes = 0;
69 static unsigned FreeNodeCount = 0;
73 /*****************************************************************************/
75 /*****************************************************************************/
79 static ExprNode* NewExprNode (void)
80 /* Create a new expression node */
84 /* Do we have some nodes in the list already? */
86 /* Use first node from list */
88 FreeExprNodes = N->Left;
90 /* Allocate fresh memory */
91 N = xmalloc (sizeof (ExprNode));
94 N->Left = N->Right = 0;
102 static void FreeExprNode (ExprNode* E)
106 if (FreeNodeCount < MAX_FREE_NODES) {
107 /* Remember this node for later */
108 E->Left = FreeExprNodes;
111 /* Free the memory */
119 /*****************************************************************************/
121 /*****************************************************************************/
125 static ExprNode* Expr0 (void);
129 int IsByteRange (long Val)
130 /* Return true if this is a byte value */
132 return (Val & ~0xFFL) == 0;
137 int IsWordRange (long Val)
138 /* Return true if this is a word value */
140 return (Val & ~0xFFFF) == 0;
145 static int FuncBlank (void)
146 /* Handle the .BLANK builtin function */
148 /* Assume no tokens if the closing brace follows (this is not correct in
149 * all cases, since the token may be the closing brace, but this will
150 * give a syntax error anyway and may not be handled by .BLANK.
152 if (Tok == TOK_RPAREN) {
156 /* Skip any tokens */
158 while (Tok != TOK_SEP && Tok != TOK_EOF) {
159 if (Tok == TOK_LPAREN) {
161 } else if (Tok == TOK_RPAREN) {
177 static int FuncConst (void)
178 /* Handle the .CONST builtin function */
180 /* Read an expression */
181 ExprNode* Expr = Expression ();
183 /* Check the constness of the expression */
184 int Result = IsConstExpr (Expr);
186 /* Free the expression */
195 static int FuncDefined (void)
196 /* Handle the .DEFINED builtin function */
200 if (Tok != TOK_IDENT) {
201 Error (ERR_IDENT_EXPECTED);
202 if (Tok != TOK_RPAREN) {
206 Result = SymIsDef (SVal);
216 static int DoMatch (enum TC EqualityLevel)
217 /* Handle the .MATCH and .XMATCH builtin functions */
224 /* A list of tokens follows. Read this list and remember it building a
225 * single linked list of tokens including attributes. The list is
226 * terminated by a comma.
228 while (Tok != TOK_COMMA) {
230 /* We may not end-of-line of end-of-file here */
231 if (Tok == TOK_SEP || Tok == TOK_EOF) {
232 Error (ERR_UNEXPECTED_EOL);
236 /* Get a node with this token */
237 Node = NewTokNode ();
239 /* Insert the node into the list */
254 /* Read the second list which is terminated by the right parenthesis and
255 * compare each token against the one in the first list.
259 while (Tok != TOK_RPAREN) {
261 /* We may not end-of-line of end-of-file here */
262 if (Tok == TOK_SEP || Tok == TOK_EOF) {
263 Error (ERR_UNEXPECTED_EOL);
267 /* Compare the tokens if the result is not already known */
270 /* The second list is larger than the first one */
272 } else if (TokCmp (Node) < EqualityLevel) {
273 /* Tokens do not match */
278 /* Next token in first list */
283 /* Next token in current list */
287 /* Check if there are remaining tokens in the first list */
292 /* Free the token list */
299 /* Done, return the result */
305 static int FuncMatch (void)
306 /* Handle the .MATCH function */
308 return DoMatch (tcSameToken);
313 static int FuncReferenced (void)
314 /* Handle the .REFERENCED builtin function */
318 if (Tok != TOK_IDENT) {
319 Error (ERR_IDENT_EXPECTED);
320 if (Tok != TOK_RPAREN) {
324 Result = SymIsRef (SVal);
334 static int FuncStrAt (void)
335 /* Handle the .STRAT function */
337 char Str [sizeof(SVal)];
340 /* String constant expected */
341 if (Tok != TOK_STRCON) {
342 Error (ERR_STRCON_EXPECTED);
348 /* Remember the string and skip it */
352 /* Comma must follow */
355 /* Expression expected */
356 Index = ConstExpression ();
358 /* Must be a valid index */
359 if (Index >= strlen (Str)) {
364 /* Return the char, handle as unsigned */
365 return (unsigned char) Str[(size_t)Index];
370 static int FuncStrLen (void)
371 /* Handle the .STRLEN function */
373 /* String constant expected */
374 if (Tok != TOK_STRCON) {
376 Error (ERR_STRCON_EXPECTED);
377 /* Smart error recovery */
378 if (Tok != TOK_RPAREN) {
385 /* Get the length of the string */
386 int Len = strlen (SVal);
388 /* Skip the string */
391 /* Return the length */
399 static int FuncTCount (void)
400 /* Handle the .TCOUNT function */
402 /* We have a list of tokens that ends with the closing paren. Skip
403 * the tokens, handling nested braces and count them.
407 while (Parens != 0 || Tok != TOK_RPAREN) {
409 /* Check for end of line or end of input. Since the calling function
410 * will check for the closing paren, we don't need to print an error
411 * here, just bail out.
413 if (Tok == TOK_SEP || Tok == TOK_EOF) {
420 /* Keep track of the nesting level */
422 case TOK_LPAREN: ++Parens; break;
423 case TOK_RPAREN: --Parens; break;
431 /* Return the number of tokens */
437 static int FuncXMatch (void)
438 /* Handle the .XMATCH function */
440 return DoMatch (tcIdentical);
445 static ExprNode* Function (int (*F) (void))
446 /* Handle builtin functions */
450 /* Skip the keyword */
453 /* Expression must be enclosed in braces */
454 if (Tok != TOK_LPAREN) {
455 Error (ERR_LPAREN_EXPECTED);
457 return LiteralExpr (0);
461 /* Call the function itself */
464 /* Closing brace must follow */
467 /* Return an expression node with the boolean code */
468 return LiteralExpr (Result);
473 static ExprNode* Factor (void)
482 N = LiteralExpr (IVal);
488 if (Tok != TOK_IDENT) {
489 Error (ERR_IDENT_EXPECTED);
490 N = LiteralExpr (0); /* Dummy */
492 S = SymRefGlobal (SVal);
493 if (SymIsConst (S)) {
494 /* Use the literal value instead */
495 N = LiteralExpr (GetSymVal (S));
497 /* Create symbol node */
508 if (SymIsConst (S)) {
509 /* Use the literal value instead */
510 N = LiteralExpr (GetSymVal (S));
512 /* Create symbol node */
529 N->Op = EXPR_UNARY_MINUS;
566 N = Function (FuncBlank);
570 N = Function (FuncConst);
574 N = LiteralExpr (GetCPU());
579 N = Function (FuncDefined);
583 N = Function (FuncMatch);
587 N = Function (FuncReferenced);
591 N = Function (FuncStrAt);
595 N = Function (FuncStrLen);
599 N = Function (FuncTCount);
603 N = Function (FuncXMatch);
607 N = LiteralExpr (0); /* Dummy */
617 static ExprNode* Term (void)
621 /* Read left hand side */
624 /* Handle multiplicative operations */
625 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
626 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
629 /* Create a new node and insert the left expression */
630 ExprNode* Left = Root;
631 Root = NewExprNode ();
634 /* Determine the operator token */
636 case TOK_MUL: Root->Op = EXPR_MUL; break;
637 case TOK_DIV: Root->Op = EXPR_DIV; break;
638 case TOK_MOD: Root->Op = EXPR_MOD; break;
639 case TOK_AND: Root->Op = EXPR_AND; break;
640 case TOK_XOR: Root->Op = EXPR_XOR; break;
641 case TOK_SHL: Root->Op = EXPR_SHL; break;
642 case TOK_SHR: Root->Op = EXPR_SHR; break;
643 default: Internal ("Invalid token");
647 /* Parse the right hand side */
648 Root->Right = Factor ();
652 /* Return the expression tree we've created */
658 static ExprNode* SimpleExpr (void)
662 /* Read left hand side */
665 /* Handle additive operations */
666 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
668 /* Create a new node and insert the left expression */
669 ExprNode* Left = Root;
670 Root = NewExprNode ();
673 /* Determine the operator token */
675 case TOK_PLUS: Root->Op = EXPR_PLUS; break;
676 case TOK_MINUS: Root->Op = EXPR_MINUS; break;
677 case TOK_OR: Root->Op = EXPR_OR; break;
678 default: Internal ("Invalid token");
682 /* Parse the right hand side */
683 Root->Right = Term ();
687 /* Return the expression tree we've created */
693 static ExprNode* BoolExpr (void)
694 /* Evaluate a boolean expression */
696 /* Read left hand side */
697 ExprNode* Root = SimpleExpr ();
699 /* Handle booleans */
700 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
701 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
703 /* Create a new node and insert the left expression */
704 ExprNode* Left = Root;
705 Root = NewExprNode ();
708 /* Determine the operator token */
710 case TOK_EQ: Root->Op = EXPR_EQ; break;
711 case TOK_NE: Root->Op = EXPR_NE; break;
712 case TOK_LT: Root->Op = EXPR_LT; break;
713 case TOK_GT: Root->Op = EXPR_GT; break;
714 case TOK_LE: Root->Op = EXPR_LE; break;
715 case TOK_GE: Root->Op = EXPR_GE; break;
716 default: Internal ("Invalid token");
720 /* Parse the right hand side */
721 Root->Right = SimpleExpr ();
725 /* Return the expression tree we've created */
731 static ExprNode* Expr2 (void)
732 /* Boolean operators: AND and XOR */
734 /* Read left hand side */
735 ExprNode* Root = BoolExpr ();
737 /* Handle booleans */
738 while (Tok == TOK_BAND || Tok == TOK_BXOR) {
740 /* Create a new node and insert the left expression */
741 ExprNode* Left = Root;
742 Root = NewExprNode ();
745 /* Determine the operator token */
747 case TOK_BAND: Root->Op = EXPR_BAND; break;
748 case TOK_BXOR: Root->Op = EXPR_BXOR; break;
749 default: Internal ("Invalid token");
753 /* Parse the right hand side */
754 Root->Right = BoolExpr ();
758 /* Return the expression tree we've created */
764 static ExprNode* Expr1 (void)
765 /* Boolean operators: OR */
767 /* Read left hand side */
768 ExprNode* Root = Expr2 ();
770 /* Handle booleans */
771 while (Tok == TOK_BOR) {
773 /* Create a new node and insert the left expression */
774 ExprNode* Left = Root;
775 Root = NewExprNode ();
778 /* Determine the operator token */
780 case TOK_BOR: Root->Op = EXPR_BOR; break;
781 default: Internal ("Invalid token");
785 /* Parse the right hand side */
786 Root->Right = Expr2 ();
790 /* Return the expression tree we've created */
796 static ExprNode* Expr0 (void)
797 /* Boolean operators: NOT */
801 /* Handle booleans */
802 if (Tok == TOK_BNOT) {
804 /* Create a new node */
805 Root = NewExprNode ();
807 /* Determine the operator token */
809 case TOK_BNOT: Root->Op = EXPR_BNOT; break;
810 default: Internal ("Invalid token");
814 /* Parse the left hand side, allow more BNOTs */
815 Root->Left = Expr0 ();
819 /* Read left hand side */
824 /* Return the expression tree we've created */
830 static ExprNode* SimplifyExpr (ExprNode* Root)
831 /* Try to simplify the given expression tree */
834 SimplifyExpr (Root->Left);
835 SimplifyExpr (Root->Right);
836 if (IsConstExpr (Root)) {
837 /* The complete expression is constant */
838 Root->V.Val = GetExprVal (Root);
839 Root->Op = EXPR_LITERAL;
840 FreeExpr (Root->Left);
841 FreeExpr (Root->Right);
842 Root->Left = Root->Right = 0;
850 ExprNode* Expression (void)
851 /* Evaluate an expression, build the expression tree on the heap and return
852 * a pointer to the root of the tree.
855 return SimplifyExpr (Expr0 ());
860 long ConstExpression (void)
861 /* Parse an expression. Check if the expression is const, and print an error
862 * message if not. Return the value of the expression, or a dummy, if it is
866 /* Read the expression, and call finalize (exception here, since we
869 ExprNode* Expr = FinalizeExpr (Expression ());
871 /* Return the value */
872 if (IsConstExpr (Expr)) {
873 return GetExprVal (Expr);
875 Error (ERR_CONSTEXPR_EXPECTED);
882 ExprNode* LiteralExpr (long Val)
883 /* Return an expression tree that encodes the given literal value */
885 ExprNode* Expr = NewExprNode ();
886 Expr->Op = EXPR_LITERAL;
893 ExprNode* CurrentPC (void)
894 /* Return the current program counter as expression */
900 /* Create SegmentBase + Offset */
901 Left = NewExprNode ();
902 Left->Op = EXPR_SEGMENT;
903 Left->V.SegNum = GetSegNum ();
905 Root = NewExprNode ();
907 Root->Right = LiteralExpr (GetPC ());
908 Root->Op = EXPR_PLUS;
910 /* Absolute mode, just return PC value */
911 Root = LiteralExpr (GetPC ());
919 ExprNode* SwapExpr (ExprNode* Expr)
920 /* Return an extended expression with lo and hi bytes swapped */
922 ExprNode* N = NewExprNode ();
930 ExprNode* BranchExpr (unsigned Offs)
931 /* Return an expression that encodes the difference between current PC plus
932 * offset and the target expression (that is, Expression() - (*+Offs) ).
941 Left = NewExprNode ();
942 Left->Op = EXPR_SEGMENT;
943 Left->V.SegNum = GetSegNum ();
947 N->Right = LiteralExpr (GetPC () + Offs);
950 N = LiteralExpr (GetPC () + Offs);
953 /* Create the root node */
954 Root = NewExprNode ();
955 Root->Left = Expression ();
957 Root->Op = EXPR_MINUS;
959 /* Return the result */
960 return SimplifyExpr (Root);
965 ExprNode* ULabelExpr (unsigned Num)
966 /* Return an expression for an unnamed label with the given index */
968 /* Get an expression node */
969 ExprNode* Node = NewExprNode ();
972 Node->Op = EXPR_ULABEL;
975 /* Return the new node */
981 void FreeExpr (ExprNode* Root)
982 /* Free the expression, Root is pointing to. */
985 FreeExpr (Root->Left);
986 FreeExpr (Root->Right);
993 ExprNode* ForceWordExpr (ExprNode* Expr)
994 /* Force the given expression into a word and return the result. */
996 /* And the expression by $FFFF to force it into word size */
997 ExprNode* Root = NewExprNode ();
1000 Root->Right = LiteralExpr (0xFFFF);
1002 /* Return the result */
1008 int IsConstExpr (ExprNode* Root)
1009 /* Return true if the given expression is a constant expression, that is, one
1010 * with no references to external symbols.
1016 if (EXPR_IS_LEAF (Root->Op)) {
1024 if (SymHasUserMark (Sym)) {
1028 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1032 Const = SymIsConst (Sym);
1033 SymUnmarkUser (Sym);
1041 } else if (EXPR_IS_UNARY (Root->Op)) {
1043 return IsConstExpr (Root->Left);
1047 /* We must handle shortcut boolean expressions here */
1051 if (IsConstExpr (Root->Left)) {
1052 /* lhs is const, if it is zero, don't eval right */
1053 if (GetExprVal (Root->Left) == 0) {
1056 return IsConstExpr (Root->Right);
1059 /* lhs not const --> tree not const */
1065 if (IsConstExpr (Root->Left)) {
1066 /* lhs is const, if it is not zero, don't eval right */
1067 if (GetExprVal (Root->Left) != 0) {
1070 return IsConstExpr (Root->Right);
1073 /* lhs not const --> tree not const */
1079 /* All others are handled normal */
1080 return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
1087 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1088 /* Internal routine that is recursively called to check if there is a zeropage
1089 * symbol in the expression tree.
1093 switch (N->Op & EXPR_TYPEMASK) {
1099 if (SymIsZP (N->V.Sym)) {
1105 if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
1113 case EXPR_UNARYNODE:
1114 CheckByteExpr (N->Left, IsByte);
1117 case EXPR_BINARYNODE:
1118 CheckByteExpr (N->Left, IsByte);
1119 CheckByteExpr (N->Right, IsByte);
1123 Internal ("Unknown expression op: %02X", N->Op);
1130 int IsByteExpr (ExprNode* Root)
1131 /* Return true if this is a byte expression */
1135 if (IsConstExpr (Root)) {
1136 if (Root->Op != EXPR_LITERAL) {
1137 SimplifyExpr (Root);
1139 return IsByteRange (GetExprVal (Root));
1140 } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
1141 Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
1142 /* Symbol forced to have byte range */
1145 /* We have undefined symbols in the expression. Assume that the
1146 * expression is a byte expression if there is at least one symbol
1147 * declared as zeropage in it. Being wrong here is not a very big
1148 * problem since the linker knows about all symbols and detects
1149 * error like mixing absolute and zeropage labels.
1152 CheckByteExpr (Root, &IsByte);
1159 long GetExprVal (ExprNode* Expr)
1160 /* Get the value of a constant expression */
1170 return GetSymVal (Expr->V.Sym);
1173 return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
1176 return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
1179 return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
1182 Left = GetExprVal (Expr->Left);
1183 Right = GetExprVal (Expr->Right);
1185 Error (ERR_DIV_BY_ZERO);
1188 return Left / Right;
1191 Left = GetExprVal (Expr->Left);
1192 Right = GetExprVal (Expr->Right);
1194 Error (ERR_MOD_BY_ZERO);
1197 return Left % Right;
1200 return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
1203 return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
1206 return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
1209 return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
1212 return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
1215 return (GetExprVal (Expr->Left) == GetExprVal (Expr->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));
1232 case EXPR_UNARY_MINUS:
1233 return -GetExprVal (Expr->Left);
1236 return ~GetExprVal (Expr->Left);
1239 return GetExprVal (Expr->Left) & 0xFF;
1242 return (GetExprVal (Expr->Left) >> 8) & 0xFF;
1245 return (GetExprVal (Expr->Left) >> 16) & 0xFF;
1248 return (GetExprVal (Expr->Left) >> 24) & 0xFF;
1251 Left = GetExprVal (Expr->Left);
1252 return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
1255 return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
1258 return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
1261 return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
1264 return !GetExprVal (Expr->Left);
1267 Internal ("GetExprVal called for EXPR_ULABEL");
1272 Internal ("Unknown Op type: %u", Expr->Op);
1280 static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
1281 /* Remove resolved symbols from the tree by cloning symbol expressions */
1283 /* Accept NULL pointers */
1288 /* Special node handling */
1292 if (SymHasExpr (Expr->V.Sym)) {
1293 /* The symbol has an expression tree */
1294 SymEntry* Sym = Expr->V.Sym;
1295 if (SymHasUserMark (Sym)) {
1296 /* Circular definition */
1300 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1301 return LiteralExpr (0); /* Return a dummy value */
1304 Expr = RemoveSyms (GetSymExpr (Sym), 1);
1305 SymUnmarkUser (Sym);
1307 } else if (SymIsConst (Expr->V.Sym)) {
1308 /* The symbol is a constant */
1309 return LiteralExpr (GetSymVal (Expr->V.Sym));
1314 if (ULabCanResolve ()) {
1315 ExprNode* NewExpr = ULabResolve (Expr->V.Val);
1323 /* Clone the current node if needed */
1326 /* Create a new node */
1327 ExprNode* Clone = NewExprNode ();
1329 /* Clone the operation */
1330 Clone->Op = Expr->Op;
1332 /* Clone the attribute if needed */
1337 Clone->V.Val = Expr->V.Val;
1341 Clone->V.Sym = Expr->V.Sym;
1345 Clone->V.SegNum = Expr->V.SegNum;
1350 /* Clone the tree nodes */
1351 Clone->Left = RemoveSyms (Expr->Left, MustClone);
1352 Clone->Right = RemoveSyms (Expr->Right, MustClone);
1359 /* Nothing to clone */
1360 Expr->Left = RemoveSyms (Expr->Left, MustClone);
1361 Expr->Right = RemoveSyms (Expr->Right, MustClone);
1371 static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
1372 /* Extract and evaluate all constant factors in an subtree that has only
1373 * additions and subtractions.
1376 if (Expr->Op == EXPR_LITERAL) {
1378 *Val -= Expr->V.Val;
1380 *Val += Expr->V.Val;
1382 FreeExprNode (Expr);
1386 if (Expr->Op == EXPR_PLUS || Expr->Op == EXPR_MINUS) {
1389 Left = ConstExtract (Expr->Left, Val, Sign);
1390 if (Expr->Op == EXPR_MINUS) {
1393 Right = ConstExtract (Expr->Right, Val, Sign);
1394 if (Left == 0 && Right == 0) {
1395 FreeExprNode (Expr);
1397 } else if (Left == 0) {
1398 FreeExprNode (Expr);
1400 } else if (Right == 0) {
1401 FreeExprNode (Expr);
1404 /* Check for SEG - SEG which is now possible */
1405 if (Left->Op == EXPR_SEGMENT && Right->Op == EXPR_SEGMENT &&
1406 Left->V.SegNum == Right->V.SegNum) {
1407 /* SEG - SEG, remove it completely */
1408 FreeExprNode (Left);
1409 FreeExprNode (Right);
1410 FreeExprNode (Expr);
1414 Expr->Right = Right;
1420 /* Some other sort of node, finalize the terms */
1422 Expr->Left = FinalizeExpr (Expr->Left);
1425 Expr->Right = FinalizeExpr (Expr->Right);
1433 ExprNode* FinalizeExpr (ExprNode* Expr)
1434 /* Resolve any symbols by cloning the symbol expression tree instead of the
1435 * symbol reference, then try to simplify the expression as much as possible.
1436 * This function must only be called if all symbols are resolved (no undefined
1443 Expr = RemoveSyms (Expr, 0);
1444 Expr = ConstExtract (Expr, &Val, 1);
1446 /* Reduced to a literal value */
1447 Expr = LiteralExpr (Val);
1449 /* Extracted a value */
1453 N->Right = LiteralExpr (Val);
1461 ExprNode* CloneExpr (ExprNode* Expr)
1462 /* Clone the given expression tree. The function will simply clone symbol
1463 * nodes, it will not resolve them.
1468 /* Accept NULL pointers */
1473 /* Get a new node */
1474 Clone = NewExprNode ();
1476 /* Clone the operation */
1477 Clone->Op = Expr->Op;
1479 /* Clone the attribute if needed */
1484 Clone->V.Val = Expr->V.Val;
1488 Clone->V.Sym = Expr->V.Sym;
1492 Clone->V.SegNum = Expr->V.SegNum;
1497 /* Clone the tree nodes */
1498 Clone->Left = CloneExpr (Expr->Left);
1499 Clone->Right = CloneExpr (Expr->Right);
1507 void WriteExpr (ExprNode* Expr)
1508 /* Write the given expression to the object file */
1510 /* Null expressions are encoded by a type byte of zero */
1516 /* Write the expression code */
1517 ObjWrite8 (Expr->Op);
1519 /* If the is a leafnode, write the expression attribute, otherwise
1520 * write the expression operands.
1525 ObjWrite32 (Expr->V.Val);
1529 /* Maybe we should use a code here? */
1530 CHECK (SymIsImport (Expr->V.Sym)); /* Safety */
1531 ObjWrite16 (GetSymIndex (Expr->V.Sym));
1535 ObjWrite8 (Expr->V.SegNum);
1539 Internal ("WriteExpr: Cannot write EXPR_ULABEL nodes");
1543 /* Not a leaf node */
1544 WriteExpr (Expr->Left);
1545 WriteExpr (Expr->Right);