1 /*****************************************************************************/
5 /* Expression evaluation for the ca65 macroassembler */
9 /* (C) 1998-2002 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 */
202 static const char* Keys[] = {
208 char Name [sizeof (SVal)];
212 /* First argument is a symbol name */
213 if (Tok != TOK_IDENT) {
214 Error (ERR_IDENT_EXPECTED);
215 if (Tok != TOK_RPAREN) {
221 /* Remember the name, then skip it */
225 /* Comma and scope spec may follow */
226 if (Tok == TOK_COMMA) {
231 /* An identifier must follow */
232 if (Tok != TOK_IDENT) {
233 Error (ERR_IDENT_EXPECTED);
237 /* Get the scope, then skip it */
238 Scope = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
241 /* Check if we got a valid keyword */
243 Error (ERR_ILLEGAL_SCOPE);
249 case 0: Scope = SCOPE_ANY; break;
250 case 1: Scope = SCOPE_GLOBAL; break;
251 case 2: Scope = SCOPE_LOCAL; break;
252 default: Internal ("Invalid scope: %d", Scope);
262 /* Search for the symbol */
263 Result = SymIsDef (SVal, Scope);
271 static int DoMatch (enum TC EqualityLevel)
272 /* Handle the .MATCH and .XMATCH builtin functions */
279 /* A list of tokens follows. Read this list and remember it building a
280 * single linked list of tokens including attributes. The list is
281 * terminated by a comma.
283 while (Tok != TOK_COMMA) {
285 /* We may not end-of-line of end-of-file here */
286 if (Tok == TOK_SEP || Tok == TOK_EOF) {
287 Error (ERR_UNEXPECTED_EOL);
291 /* Get a node with this token */
292 Node = NewTokNode ();
294 /* Insert the node into the list */
309 /* Read the second list which is terminated by the right parenthesis and
310 * compare each token against the one in the first list.
314 while (Tok != TOK_RPAREN) {
316 /* We may not end-of-line of end-of-file here */
317 if (Tok == TOK_SEP || Tok == TOK_EOF) {
318 Error (ERR_UNEXPECTED_EOL);
322 /* Compare the tokens if the result is not already known */
325 /* The second list is larger than the first one */
327 } else if (TokCmp (Node) < EqualityLevel) {
328 /* Tokens do not match */
333 /* Next token in first list */
338 /* Next token in current list */
342 /* Check if there are remaining tokens in the first list */
347 /* Free the token list */
354 /* Done, return the result */
360 static int FuncMatch (void)
361 /* Handle the .MATCH function */
363 return DoMatch (tcSameToken);
368 static int FuncReferenced (void)
369 /* Handle the .REFERENCED builtin function */
373 if (Tok != TOK_IDENT) {
374 Error (ERR_IDENT_EXPECTED);
375 if (Tok != TOK_RPAREN) {
379 Result = SymIsRef (SVal, SCOPE_ANY);
389 static int FuncStrAt (void)
390 /* Handle the .STRAT function */
392 char Str [sizeof(SVal)];
395 /* String constant expected */
396 if (Tok != TOK_STRCON) {
397 Error (ERR_STRCON_EXPECTED);
403 /* Remember the string and skip it */
407 /* Comma must follow */
410 /* Expression expected */
411 Index = ConstExpression ();
413 /* Must be a valid index */
414 if (Index >= (long) strlen (Str)) {
419 /* Return the char, handle as unsigned. Be sure to translate it into
420 * the target character set.
422 return (unsigned char) TgtTranslateChar (Str [(size_t)Index]);
427 static int FuncStrLen (void)
428 /* Handle the .STRLEN function */
430 /* String constant expected */
431 if (Tok != TOK_STRCON) {
433 Error (ERR_STRCON_EXPECTED);
434 /* Smart error recovery */
435 if (Tok != TOK_RPAREN) {
442 /* Get the length of the string */
443 int Len = strlen (SVal);
445 /* Skip the string */
448 /* Return the length */
456 static int FuncTCount (void)
457 /* Handle the .TCOUNT function */
459 /* We have a list of tokens that ends with the closing paren. Skip
460 * the tokens, handling nested braces and count them.
464 while (Parens != 0 || Tok != TOK_RPAREN) {
466 /* Check for end of line or end of input. Since the calling function
467 * will check for the closing paren, we don't need to print an error
468 * here, just bail out.
470 if (Tok == TOK_SEP || Tok == TOK_EOF) {
477 /* Keep track of the nesting level */
479 case TOK_LPAREN: ++Parens; break;
480 case TOK_RPAREN: --Parens; break;
488 /* Return the number of tokens */
494 static int FuncXMatch (void)
495 /* Handle the .XMATCH function */
497 return DoMatch (tcIdentical);
502 static ExprNode* Function (int (*F) (void))
503 /* Handle builtin functions */
507 /* Skip the keyword */
510 /* Expression must be enclosed in braces */
511 if (Tok != TOK_LPAREN) {
512 Error (ERR_LPAREN_EXPECTED);
514 return LiteralExpr (0);
518 /* Call the function itself */
521 /* Closing brace must follow */
524 /* Return an expression node with the boolean code */
525 return LiteralExpr (Result);
530 static ExprNode* Factor (void)
538 N = LiteralExpr (IVal);
543 N = LiteralExpr (TgtTranslateChar (IVal));
549 if (Tok != TOK_IDENT) {
550 Error (ERR_IDENT_EXPECTED);
551 N = LiteralExpr (0); /* Dummy */
553 S = SymRef (SVal, SCOPE_GLOBAL);
554 if (SymIsConst (S)) {
555 /* Use the literal value instead */
556 N = LiteralExpr (GetSymVal (S));
558 /* Create symbol node */
568 S = SymRef (SVal, SCOPE_LOCAL);
569 if (SymIsConst (S)) {
570 /* Use the literal value instead */
571 N = LiteralExpr (GetSymVal (S));
573 /* Create symbol node */
590 N->Op = EXPR_UNARY_MINUS;
627 N = Function (FuncBlank);
631 N = Function (FuncConst);
635 N = LiteralExpr (GetCPU());
640 N = Function (FuncDefined);
644 N = Function (FuncMatch);
648 N = Function (FuncReferenced);
652 N = Function (FuncStrAt);
656 N = Function (FuncStrLen);
660 N = Function (FuncTCount);
664 N = Function (FuncXMatch);
668 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
669 /* A character constant */
670 N = LiteralExpr (TgtTranslateChar (SVal[0]));
672 N = LiteralExpr (0); /* Dummy */
683 static ExprNode* Term (void)
687 /* Read left hand side */
690 /* Handle multiplicative operations */
691 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
692 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
695 /* Create a new node and insert the left expression */
696 ExprNode* Left = Root;
697 Root = NewExprNode ();
700 /* Determine the operator token */
702 case TOK_MUL: Root->Op = EXPR_MUL; break;
703 case TOK_DIV: Root->Op = EXPR_DIV; break;
704 case TOK_MOD: Root->Op = EXPR_MOD; break;
705 case TOK_AND: Root->Op = EXPR_AND; break;
706 case TOK_XOR: Root->Op = EXPR_XOR; break;
707 case TOK_SHL: Root->Op = EXPR_SHL; break;
708 case TOK_SHR: Root->Op = EXPR_SHR; break;
709 default: Internal ("Invalid token");
713 /* Parse the right hand side */
714 Root->Right = Factor ();
718 /* Return the expression tree we've created */
724 static ExprNode* SimpleExpr (void)
728 /* Read left hand side */
731 /* Handle additive operations */
732 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
734 /* Create a new node and insert the left expression */
735 ExprNode* Left = Root;
736 Root = NewExprNode ();
739 /* Determine the operator token */
741 case TOK_PLUS: Root->Op = EXPR_PLUS; break;
742 case TOK_MINUS: Root->Op = EXPR_MINUS; break;
743 case TOK_OR: Root->Op = EXPR_OR; break;
744 default: Internal ("Invalid token");
748 /* Parse the right hand side */
749 Root->Right = Term ();
753 /* Return the expression tree we've created */
759 static ExprNode* BoolExpr (void)
760 /* Evaluate a boolean expression */
762 /* Read left hand side */
763 ExprNode* Root = SimpleExpr ();
765 /* Handle booleans */
766 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
767 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
769 /* Create a new node and insert the left expression */
770 ExprNode* Left = Root;
771 Root = NewExprNode ();
774 /* Determine the operator token */
776 case TOK_EQ: Root->Op = EXPR_EQ; break;
777 case TOK_NE: Root->Op = EXPR_NE; break;
778 case TOK_LT: Root->Op = EXPR_LT; break;
779 case TOK_GT: Root->Op = EXPR_GT; break;
780 case TOK_LE: Root->Op = EXPR_LE; break;
781 case TOK_GE: Root->Op = EXPR_GE; break;
782 default: Internal ("Invalid token");
786 /* Parse the right hand side */
787 Root->Right = SimpleExpr ();
791 /* Return the expression tree we've created */
797 static ExprNode* Expr2 (void)
798 /* Boolean operators: AND and XOR */
800 /* Read left hand side */
801 ExprNode* Root = BoolExpr ();
803 /* Handle booleans */
804 while (Tok == TOK_BAND || Tok == TOK_BXOR) {
806 /* Create a new node and insert the left expression */
807 ExprNode* Left = Root;
808 Root = NewExprNode ();
811 /* Determine the operator token */
813 case TOK_BAND: Root->Op = EXPR_BAND; break;
814 case TOK_BXOR: Root->Op = EXPR_BXOR; break;
815 default: Internal ("Invalid token");
819 /* Parse the right hand side */
820 Root->Right = BoolExpr ();
824 /* Return the expression tree we've created */
830 static ExprNode* Expr1 (void)
831 /* Boolean operators: OR */
833 /* Read left hand side */
834 ExprNode* Root = Expr2 ();
836 /* Handle booleans */
837 while (Tok == TOK_BOR) {
839 /* Create a new node and insert the left expression */
840 ExprNode* Left = Root;
841 Root = NewExprNode ();
844 /* Determine the operator token */
846 case TOK_BOR: Root->Op = EXPR_BOR; break;
847 default: Internal ("Invalid token");
851 /* Parse the right hand side */
852 Root->Right = Expr2 ();
856 /* Return the expression tree we've created */
862 static ExprNode* Expr0 (void)
863 /* Boolean operators: NOT */
867 /* Handle booleans */
868 if (Tok == TOK_BNOT) {
870 /* Create a new node */
871 Root = NewExprNode ();
873 /* Determine the operator token */
875 case TOK_BNOT: Root->Op = EXPR_BNOT; break;
876 default: Internal ("Invalid token");
880 /* Parse the left hand side, allow more BNOTs */
881 Root->Left = Expr0 ();
885 /* Read left hand side */
890 /* Return the expression tree we've created */
896 static ExprNode* SimplifyExpr (ExprNode* Root)
897 /* Try to simplify the given expression tree */
900 SimplifyExpr (Root->Left);
901 SimplifyExpr (Root->Right);
902 if (IsConstExpr (Root)) {
903 /* The complete expression is constant */
904 Root->V.Val = GetExprVal (Root);
905 Root->Op = EXPR_LITERAL;
906 FreeExpr (Root->Left);
907 FreeExpr (Root->Right);
908 Root->Left = Root->Right = 0;
916 ExprNode* Expression (void)
917 /* Evaluate an expression, build the expression tree on the heap and return
918 * a pointer to the root of the tree.
921 return SimplifyExpr (Expr0 ());
926 long ConstExpression (void)
927 /* Parse an expression. Check if the expression is const, and print an error
928 * message if not. Return the value of the expression, or a dummy, if it is
932 /* Read the expression, and call finalize (exception here, since we
935 ExprNode* Expr = FinalizeExpr (Expression ());
937 /* Return the value */
938 if (IsConstExpr (Expr)) {
939 return GetExprVal (Expr);
941 Error (ERR_CONSTEXPR_EXPECTED);
948 ExprNode* LiteralExpr (long Val)
949 /* Return an expression tree that encodes the given literal value */
951 ExprNode* Expr = NewExprNode ();
952 Expr->Op = EXPR_LITERAL;
959 ExprNode* CurrentPC (void)
960 /* Return the current program counter as expression */
966 /* Create SegmentBase + Offset */
967 Left = NewExprNode ();
968 Left->Op = EXPR_SEGMENT;
969 Left->V.SegNum = GetSegNum ();
971 Root = NewExprNode ();
973 Root->Right = LiteralExpr (GetPC ());
974 Root->Op = EXPR_PLUS;
976 /* Absolute mode, just return PC value */
977 Root = LiteralExpr (GetPC ());
985 ExprNode* SwapExpr (ExprNode* Expr)
986 /* Return an extended expression with lo and hi bytes swapped */
988 ExprNode* N = NewExprNode ();
996 ExprNode* BranchExpr (unsigned Offs)
997 /* Return an expression that encodes the difference between current PC plus
998 * offset and the target expression (that is, Expression() - (*+Offs) ).
1007 Left = NewExprNode ();
1008 Left->Op = EXPR_SEGMENT;
1009 Left->V.SegNum = GetSegNum ();
1013 N->Right = LiteralExpr (GetPC () + Offs);
1016 N = LiteralExpr (GetPC () + Offs);
1019 /* Create the root node */
1020 Root = NewExprNode ();
1021 Root->Left = Expression ();
1023 Root->Op = EXPR_MINUS;
1025 /* Return the result */
1026 return SimplifyExpr (Root);
1031 ExprNode* ULabelExpr (unsigned Num)
1032 /* Return an expression for an unnamed label with the given index */
1034 /* Get an expression node */
1035 ExprNode* Node = NewExprNode ();
1037 /* Set the values */
1038 Node->Op = EXPR_ULABEL;
1041 /* Return the new node */
1047 void FreeExpr (ExprNode* Root)
1048 /* Free the expression, Root is pointing to. */
1051 FreeExpr (Root->Left);
1052 FreeExpr (Root->Right);
1053 FreeExprNode (Root);
1059 ExprNode* ForceWordExpr (ExprNode* Expr)
1060 /* Force the given expression into a word and return the result. */
1062 /* And the expression by $FFFF to force it into word size */
1063 ExprNode* Root = NewExprNode ();
1065 Root->Op = EXPR_AND;
1066 Root->Right = LiteralExpr (0xFFFF);
1068 /* Return the result */
1074 int IsConstExpr (ExprNode* Root)
1075 /* Return true if the given expression is a constant expression, that is, one
1076 * with no references to external symbols.
1082 if (EXPR_IS_LEAF (Root->Op)) {
1090 if (SymHasUserMark (Sym)) {
1091 if (Verbosity > 0) {
1094 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1098 Const = SymIsConst (Sym);
1099 SymUnmarkUser (Sym);
1107 } else if (EXPR_IS_UNARY (Root->Op)) {
1109 return IsConstExpr (Root->Left);
1113 /* We must handle shortcut boolean expressions here */
1117 if (IsConstExpr (Root->Left)) {
1118 /* lhs is const, if it is zero, don't eval right */
1119 if (GetExprVal (Root->Left) == 0) {
1122 return IsConstExpr (Root->Right);
1125 /* lhs not const --> tree not const */
1131 if (IsConstExpr (Root->Left)) {
1132 /* lhs is const, if it is not zero, don't eval right */
1133 if (GetExprVal (Root->Left) != 0) {
1136 return IsConstExpr (Root->Right);
1139 /* lhs not const --> tree not const */
1145 /* All others are handled normal */
1146 return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
1153 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1154 /* Internal routine that is recursively called to check if there is a zeropage
1155 * symbol in the expression tree.
1159 switch (N->Op & EXPR_TYPEMASK) {
1165 if (SymIsZP (N->V.Sym)) {
1167 } else if (SymHasExpr (N->V.Sym)) {
1168 /* Check if this expression is a byte expression */
1169 *IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
1174 if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
1182 case EXPR_UNARYNODE:
1183 CheckByteExpr (N->Left, IsByte);
1186 case EXPR_BINARYNODE:
1187 CheckByteExpr (N->Left, IsByte);
1188 CheckByteExpr (N->Right, IsByte);
1192 Internal ("Unknown expression op: %02X", N->Op);
1199 int IsByteExpr (ExprNode* Root)
1200 /* Return true if this is a byte expression */
1204 if (IsConstExpr (Root)) {
1205 if (Root->Op != EXPR_LITERAL) {
1206 SimplifyExpr (Root);
1208 return IsByteRange (GetExprVal (Root));
1209 } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
1210 Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
1211 /* Symbol forced to have byte range */
1214 /* We have undefined symbols in the expression. Assume that the
1215 * expression is a byte expression if there is at least one symbol
1216 * declared as zeropage in it. Being wrong here is not a very big
1217 * problem since the linker knows about all symbols and detects
1218 * error like mixing absolute and zeropage labels.
1221 CheckByteExpr (Root, &IsByte);
1228 long GetExprVal (ExprNode* Expr)
1229 /* Get the value of a constant expression */
1239 return GetSymVal (Expr->V.Sym);
1242 return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
1245 return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
1248 return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
1251 Left = GetExprVal (Expr->Left);
1252 Right = GetExprVal (Expr->Right);
1254 Error (ERR_DIV_BY_ZERO);
1257 return Left / Right;
1260 Left = GetExprVal (Expr->Left);
1261 Right = GetExprVal (Expr->Right);
1263 Error (ERR_MOD_BY_ZERO);
1266 return Left % Right;
1269 return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
1272 return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
1275 return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
1278 return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
1281 return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
1284 return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));
1287 return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));
1290 return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));
1293 return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));
1296 return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));
1299 return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));
1301 case EXPR_UNARY_MINUS:
1302 return -GetExprVal (Expr->Left);
1305 return ~GetExprVal (Expr->Left);
1308 return GetExprVal (Expr->Left) & 0xFF;
1311 return (GetExprVal (Expr->Left) >> 8) & 0xFF;
1314 return (GetExprVal (Expr->Left) >> 16) & 0xFF;
1317 return (GetExprVal (Expr->Left) >> 24) & 0xFF;
1320 Left = GetExprVal (Expr->Left);
1321 return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
1324 return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
1327 return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
1330 return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
1333 return !GetExprVal (Expr->Left);
1336 Internal ("GetExprVal called for EXPR_ULABEL");
1341 Internal ("Unknown Op type: %u", Expr->Op);
1349 static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
1350 /* Remove resolved symbols from the tree by cloning symbol expressions */
1352 /* Accept NULL pointers */
1357 /* Special node handling */
1361 if (SymHasExpr (Expr->V.Sym)) {
1362 /* The symbol has an expression tree */
1363 SymEntry* Sym = Expr->V.Sym;
1364 if (SymHasUserMark (Sym)) {
1365 /* Circular definition */
1369 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1370 return LiteralExpr (0); /* Return a dummy value */
1373 Expr = RemoveSyms (GetSymExpr (Sym), 1);
1374 SymUnmarkUser (Sym);
1376 } else if (SymIsConst (Expr->V.Sym)) {
1377 /* The symbol is a constant */
1378 return LiteralExpr (GetSymVal (Expr->V.Sym));
1383 if (ULabCanResolve ()) {
1384 ExprNode* NewExpr = ULabResolve (Expr->V.Val);
1392 /* Clone the current node if needed */
1395 /* Create a new node */
1396 ExprNode* Clone = NewExprNode ();
1398 /* Clone the operation */
1399 Clone->Op = Expr->Op;
1401 /* Clone the attribute if needed */
1406 Clone->V.Val = Expr->V.Val;
1410 Clone->V.Sym = Expr->V.Sym;
1414 Clone->V.SegNum = Expr->V.SegNum;
1419 /* Clone the tree nodes */
1420 Clone->Left = RemoveSyms (Expr->Left, MustClone);
1421 Clone->Right = RemoveSyms (Expr->Right, MustClone);
1428 /* Nothing to clone */
1429 Expr->Left = RemoveSyms (Expr->Left, MustClone);
1430 Expr->Right = RemoveSyms (Expr->Right, MustClone);
1440 static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
1441 /* Extract and evaluate all constant factors in an subtree that has only
1442 * additions and subtractions.
1445 if (Expr->Op == EXPR_LITERAL) {
1447 *Val -= Expr->V.Val;
1449 *Val += Expr->V.Val;
1451 FreeExprNode (Expr);
1455 if (Expr->Op == EXPR_PLUS || Expr->Op == EXPR_MINUS) {
1458 Left = ConstExtract (Expr->Left, Val, Sign);
1459 if (Expr->Op == EXPR_MINUS) {
1462 Right = ConstExtract (Expr->Right, Val, Sign);
1463 if (Left == 0 && Right == 0) {
1464 FreeExprNode (Expr);
1466 } else if (Left == 0) {
1467 FreeExprNode (Expr);
1469 } else if (Right == 0) {
1470 FreeExprNode (Expr);
1473 /* Check for SEG - SEG which is now possible */
1474 if (Left->Op == EXPR_SEGMENT && Right->Op == EXPR_SEGMENT &&
1475 Left->V.SegNum == Right->V.SegNum) {
1476 /* SEG - SEG, remove it completely */
1477 FreeExprNode (Left);
1478 FreeExprNode (Right);
1479 FreeExprNode (Expr);
1483 Expr->Right = Right;
1489 /* Some other sort of node, finalize the terms */
1491 Expr->Left = FinalizeExpr (Expr->Left);
1494 Expr->Right = FinalizeExpr (Expr->Right);
1502 ExprNode* FinalizeExpr (ExprNode* Expr)
1503 /* Resolve any symbols by cloning the symbol expression tree instead of the
1504 * symbol reference, then try to simplify the expression as much as possible.
1505 * This function must only be called if all symbols are resolved (no undefined
1512 Expr = RemoveSyms (Expr, 0);
1513 Expr = ConstExtract (Expr, &Val, 1);
1515 /* Reduced to a literal value */
1516 Expr = LiteralExpr (Val);
1518 /* Extracted a value */
1522 N->Right = LiteralExpr (Val);
1530 ExprNode* CloneExpr (ExprNode* Expr)
1531 /* Clone the given expression tree. The function will simply clone symbol
1532 * nodes, it will not resolve them.
1537 /* Accept NULL pointers */
1542 /* Get a new node */
1543 Clone = NewExprNode ();
1545 /* Clone the operation */
1546 Clone->Op = Expr->Op;
1548 /* Clone the attribute if needed */
1553 Clone->V.Val = Expr->V.Val;
1557 Clone->V.Sym = Expr->V.Sym;
1561 Clone->V.SegNum = Expr->V.SegNum;
1566 /* Clone the tree nodes */
1567 Clone->Left = CloneExpr (Expr->Left);
1568 Clone->Right = CloneExpr (Expr->Right);
1576 void WriteExpr (ExprNode* Expr)
1577 /* Write the given expression to the object file */
1579 /* Null expressions are encoded by a type byte of zero */
1585 /* Write the expression code */
1586 ObjWrite8 (Expr->Op);
1588 /* If the is a leafnode, write the expression attribute, otherwise
1589 * write the expression operands.
1594 ObjWrite32 (Expr->V.Val);
1598 /* Maybe we should use a code here? */
1599 CHECK (SymIsImport (Expr->V.Sym)); /* Safety */
1600 ObjWrite16 (GetSymIndex (Expr->V.Sym));
1604 ObjWrite8 (Expr->V.SegNum);
1608 Internal ("WriteExpr: Cannot write EXPR_ULABEL nodes");
1612 /* Not a leaf node */
1613 WriteExpr (Expr->Left);
1614 WriteExpr (Expr->Right);