1 /*****************************************************************************/
5 /* Expression evaluation for the ca65 macroassembler */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
10 /* Römerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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 /*****************************************************************************/
61 /*****************************************************************************/
63 /*****************************************************************************/
67 /* Since all expressions are first packed into expression trees, and each
68 * expression tree node is allocated on the heap, we add some type of special
69 * purpose memory allocation here: Instead of freeing the nodes, we save some
70 * number of freed nodes for later and remember them in a single linked list
71 * using the Left link.
73 #define MAX_FREE_NODES 64
74 static ExprNode* FreeExprNodes = 0;
75 static unsigned FreeNodeCount = 0;
79 /*****************************************************************************/
81 /*****************************************************************************/
85 static ExprNode* NewExprNode (void)
86 /* Create a new expression node */
90 /* Do we have some nodes in the list already? */
92 /* Use first node from list */
94 FreeExprNodes = N->Left;
96 /* Allocate fresh memory */
97 N = xmalloc (sizeof (ExprNode));
100 N->Left = N->Right = 0;
108 static void FreeExprNode (ExprNode* E)
112 if (FreeNodeCount < MAX_FREE_NODES) {
113 /* Remember this node for later */
114 E->Left = FreeExprNodes;
117 /* Free the memory */
125 /*****************************************************************************/
127 /*****************************************************************************/
131 static ExprNode* Expr0 (void);
135 int IsByteRange (long Val)
136 /* Return true if this is a byte value */
138 return (Val & ~0xFFL) == 0;
143 int IsWordRange (long Val)
144 /* Return true if this is a word value */
146 return (Val & ~0xFFFF) == 0;
151 static int FuncBlank (void)
152 /* Handle the .BLANK builtin function */
154 /* Assume no tokens if the closing brace follows (this is not correct in
155 * all cases, since the token may be the closing brace, but this will
156 * give a syntax error anyway and may not be handled by .BLANK.
158 if (Tok == TOK_RPAREN) {
162 /* Skip any tokens */
164 while (!TokIsSep (Tok)) {
165 if (Tok == TOK_LPAREN) {
167 } else if (Tok == TOK_RPAREN) {
183 static int FuncConst (void)
184 /* Handle the .CONST builtin function */
186 /* Read an expression */
187 ExprNode* Expr = Expression ();
189 /* Check the constness of the expression */
190 int Result = IsConstExpr (Expr);
192 /* Free the expression */
201 static int FuncDefined (void)
202 /* Handle the .DEFINED builtin function */
204 static const char* Keys[] = {
210 char Name [sizeof (SVal)];
214 /* First argument is a symbol name */
215 if (Tok != TOK_IDENT) {
216 Error (ERR_IDENT_EXPECTED);
217 if (Tok != TOK_RPAREN) {
223 /* Remember the name, then skip it */
227 /* Comma and scope spec may follow */
228 if (Tok == TOK_COMMA) {
233 /* An identifier must follow */
234 if (Tok != TOK_IDENT) {
235 Error (ERR_IDENT_EXPECTED);
239 /* Get the scope, then skip it */
240 Scope = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
243 /* Check if we got a valid keyword */
245 Error (ERR_ILLEGAL_SCOPE);
251 case 0: Scope = SCOPE_ANY; break;
252 case 1: Scope = SCOPE_GLOBAL; break;
253 case 2: Scope = SCOPE_LOCAL; break;
254 default: Internal ("Invalid scope: %d", Scope);
264 /* Search for the symbol */
265 Result = SymIsDef (SVal, Scope);
273 static int DoMatch (enum TC EqualityLevel)
274 /* Handle the .MATCH and .XMATCH builtin functions */
281 /* A list of tokens follows. Read this list and remember it building a
282 * single linked list of tokens including attributes. The list is
283 * terminated by a comma.
285 while (Tok != TOK_COMMA) {
287 /* We may not end-of-line of end-of-file here */
288 if (TokIsSep (Tok)) {
289 Error (ERR_UNEXPECTED_EOL);
293 /* Get a node with this token */
294 Node = NewTokNode ();
296 /* Insert the node into the list */
311 /* Read the second list which is terminated by the right parenthesis and
312 * compare each token against the one in the first list.
316 while (Tok != TOK_RPAREN) {
318 /* We may not end-of-line of end-of-file here */
319 if (TokIsSep (Tok)) {
320 Error (ERR_UNEXPECTED_EOL);
324 /* Compare the tokens if the result is not already known */
327 /* The second list is larger than the first one */
329 } else if (TokCmp (Node) < EqualityLevel) {
330 /* Tokens do not match */
335 /* Next token in first list */
340 /* Next token in current list */
344 /* Check if there are remaining tokens in the first list */
349 /* Free the token list */
356 /* Done, return the result */
362 static int FuncMatch (void)
363 /* Handle the .MATCH function */
365 return DoMatch (tcSameToken);
370 static int FuncReferenced (void)
371 /* Handle the .REFERENCED builtin function */
375 if (Tok != TOK_IDENT) {
376 Error (ERR_IDENT_EXPECTED);
377 if (Tok != TOK_RPAREN) {
381 Result = SymIsRef (SVal, SCOPE_ANY);
391 static int FuncStrAt (void)
392 /* Handle the .STRAT function */
394 char Str [sizeof(SVal)];
397 /* String constant expected */
398 if (Tok != TOK_STRCON) {
399 Error (ERR_STRCON_EXPECTED);
405 /* Remember the string and skip it */
409 /* Comma must follow */
412 /* Expression expected */
413 Index = ConstExpression ();
415 /* Must be a valid index */
416 if (Index >= (long) strlen (Str)) {
421 /* Return the char, handle as unsigned. Be sure to translate it into
422 * the target character set.
424 return (unsigned char) TgtTranslateChar (Str [(size_t)Index]);
429 static int FuncStrLen (void)
430 /* Handle the .STRLEN function */
432 /* String constant expected */
433 if (Tok != TOK_STRCON) {
435 Error (ERR_STRCON_EXPECTED);
436 /* Smart error recovery */
437 if (Tok != TOK_RPAREN) {
444 /* Get the length of the string */
445 int Len = strlen (SVal);
447 /* Skip the string */
450 /* Return the length */
458 static int FuncTCount (void)
459 /* Handle the .TCOUNT function */
461 /* We have a list of tokens that ends with the closing paren. Skip
462 * the tokens, handling nested braces and count them.
466 while (Parens != 0 || Tok != TOK_RPAREN) {
468 /* Check for end of line or end of input. Since the calling function
469 * will check for the closing paren, we don't need to print an error
470 * here, just bail out.
472 if (TokIsSep (Tok)) {
479 /* Keep track of the nesting level */
481 case TOK_LPAREN: ++Parens; break;
482 case TOK_RPAREN: --Parens; break;
490 /* Return the number of tokens */
496 static int FuncXMatch (void)
497 /* Handle the .XMATCH function */
499 return DoMatch (tcIdentical);
504 static ExprNode* Function (int (*F) (void))
505 /* Handle builtin functions */
509 /* Skip the keyword */
512 /* Expression must be enclosed in braces */
513 if (Tok != TOK_LPAREN) {
514 Error (ERR_LPAREN_EXPECTED);
516 return GenLiteralExpr (0);
520 /* Call the function itself */
523 /* Closing brace must follow */
526 /* Return an expression node with the boolean code */
527 return GenLiteralExpr (Result);
532 static ExprNode* Factor (void)
540 N = GenLiteralExpr (IVal);
545 N = GenLiteralExpr (TgtTranslateChar (IVal));
551 if (Tok != TOK_IDENT) {
552 Error (ERR_IDENT_EXPECTED);
553 N = GenLiteralExpr (0); /* Dummy */
555 S = SymRef (SVal, SCOPE_GLOBAL);
556 if (SymIsConst (S)) {
557 /* Use the literal value instead */
558 N = GenLiteralExpr (GetSymVal (S));
560 /* Create symbol node */
570 S = SymRef (SVal, SCOPE_LOCAL);
571 if (SymIsConst (S)) {
572 /* Use the literal value instead */
573 N = GenLiteralExpr (GetSymVal (S));
575 /* Create symbol node */
592 N->Op = EXPR_UNARY_MINUS;
629 N = Function (FuncBlank);
633 N = Function (FuncConst);
637 N = GenLiteralExpr (GetCPU());
642 N = Function (FuncDefined);
646 N = Function (FuncMatch);
650 N = Function (FuncReferenced);
654 N = Function (FuncStrAt);
658 N = Function (FuncStrLen);
662 N = Function (FuncTCount);
666 N = GenLiteralExpr (time (0));
671 N = GenLiteralExpr (VERSION);
677 N = Function (FuncXMatch);
681 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
682 /* A character constant */
683 N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
685 N = GenLiteralExpr (0); /* Dummy */
696 static ExprNode* Term (void)
700 /* Read left hand side */
703 /* Handle multiplicative operations */
704 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
705 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
708 /* Create a new node and insert the left expression */
709 ExprNode* Left = Root;
710 Root = NewExprNode ();
713 /* Determine the operator token */
715 case TOK_MUL: Root->Op = EXPR_MUL; break;
716 case TOK_DIV: Root->Op = EXPR_DIV; break;
717 case TOK_MOD: Root->Op = EXPR_MOD; break;
718 case TOK_AND: Root->Op = EXPR_AND; break;
719 case TOK_XOR: Root->Op = EXPR_XOR; break;
720 case TOK_SHL: Root->Op = EXPR_SHL; break;
721 case TOK_SHR: Root->Op = EXPR_SHR; break;
722 default: Internal ("Invalid token");
726 /* Parse the right hand side */
727 Root->Right = Factor ();
731 /* Return the expression tree we've created */
737 static ExprNode* SimpleExpr (void)
741 /* Read left hand side */
744 /* Handle additive operations */
745 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
747 /* Create a new node and insert the left expression */
748 ExprNode* Left = Root;
749 Root = NewExprNode ();
752 /* Determine the operator token */
754 case TOK_PLUS: Root->Op = EXPR_PLUS; break;
755 case TOK_MINUS: Root->Op = EXPR_MINUS; break;
756 case TOK_OR: Root->Op = EXPR_OR; break;
757 default: Internal ("Invalid token");
761 /* Parse the right hand side */
762 Root->Right = Term ();
766 /* Return the expression tree we've created */
772 static ExprNode* BoolExpr (void)
773 /* Evaluate a boolean expression */
775 /* Read left hand side */
776 ExprNode* Root = SimpleExpr ();
778 /* Handle booleans */
779 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
780 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
782 /* Create a new node and insert the left expression */
783 ExprNode* Left = Root;
784 Root = NewExprNode ();
787 /* Determine the operator token */
789 case TOK_EQ: Root->Op = EXPR_EQ; break;
790 case TOK_NE: Root->Op = EXPR_NE; break;
791 case TOK_LT: Root->Op = EXPR_LT; break;
792 case TOK_GT: Root->Op = EXPR_GT; break;
793 case TOK_LE: Root->Op = EXPR_LE; break;
794 case TOK_GE: Root->Op = EXPR_GE; break;
795 default: Internal ("Invalid token");
799 /* Parse the right hand side */
800 Root->Right = SimpleExpr ();
804 /* Return the expression tree we've created */
810 static ExprNode* Expr2 (void)
811 /* Boolean operators: AND and XOR */
813 /* Read left hand side */
814 ExprNode* Root = BoolExpr ();
816 /* Handle booleans */
817 while (Tok == TOK_BAND || Tok == TOK_BXOR) {
819 /* Create a new node and insert the left expression */
820 ExprNode* Left = Root;
821 Root = NewExprNode ();
824 /* Determine the operator token */
826 case TOK_BAND: Root->Op = EXPR_BAND; break;
827 case TOK_BXOR: Root->Op = EXPR_BXOR; break;
828 default: Internal ("Invalid token");
832 /* Parse the right hand side */
833 Root->Right = BoolExpr ();
837 /* Return the expression tree we've created */
843 static ExprNode* Expr1 (void)
844 /* Boolean operators: OR */
846 /* Read left hand side */
847 ExprNode* Root = Expr2 ();
849 /* Handle booleans */
850 while (Tok == TOK_BOR) {
852 /* Create a new node and insert the left expression */
853 ExprNode* Left = Root;
854 Root = NewExprNode ();
857 /* Determine the operator token */
859 case TOK_BOR: Root->Op = EXPR_BOR; break;
860 default: Internal ("Invalid token");
864 /* Parse the right hand side */
865 Root->Right = Expr2 ();
869 /* Return the expression tree we've created */
875 static ExprNode* Expr0 (void)
876 /* Boolean operators: NOT */
880 /* Handle booleans */
881 if (Tok == TOK_BNOT) {
883 /* Create a new node */
884 Root = NewExprNode ();
886 /* Determine the operator token */
888 case TOK_BNOT: Root->Op = EXPR_BNOT; break;
889 default: Internal ("Invalid token");
893 /* Parse the left hand side, allow more BNOTs */
894 Root->Left = Expr0 ();
898 /* Read left hand side */
903 /* Return the expression tree we've created */
909 static ExprNode* SimplifyExpr (ExprNode* Root)
910 /* Try to simplify the given expression tree */
913 SimplifyExpr (Root->Left);
914 SimplifyExpr (Root->Right);
915 if (IsConstExpr (Root)) {
916 /* The complete expression is constant */
917 Root->V.Val = GetExprVal (Root);
918 Root->Op = EXPR_LITERAL;
919 FreeExpr (Root->Left);
920 FreeExpr (Root->Right);
921 Root->Left = Root->Right = 0;
929 ExprNode* Expression (void)
930 /* Evaluate an expression, build the expression tree on the heap and return
931 * a pointer to the root of the tree.
934 return SimplifyExpr (Expr0 ());
939 long ConstExpression (void)
940 /* Parse an expression. Check if the expression is const, and print an error
941 * message if not. Return the value of the expression, or a dummy, if it is
945 /* Read the expression, and call finalize (exception here, since we
948 ExprNode* Expr = FinalizeExpr (Expression ());
950 /* Return the value */
951 if (IsConstExpr (Expr)) {
952 return GetExprVal (Expr);
954 Error (ERR_CONSTEXPR_EXPECTED);
961 void FreeExpr (ExprNode* Root)
962 /* Free the expression, Root is pointing to. */
965 FreeExpr (Root->Left);
966 FreeExpr (Root->Right);
973 ExprNode* GenLiteralExpr (long Val)
974 /* Return an expression tree that encodes the given literal value */
976 ExprNode* Expr = NewExprNode ();
977 Expr->Op = EXPR_LITERAL;
984 ExprNode* GenCurrentPC (void)
985 /* Return the current program counter as expression */
991 /* Create SegmentBase + Offset */
992 Left = NewExprNode ();
993 Left->Op = EXPR_SECTION;
994 Left->V.SegNum = GetSegNum ();
996 Root = NewExprNode ();
998 Root->Right = GenLiteralExpr (GetPC ());
999 Root->Op = EXPR_PLUS;
1001 /* Absolute mode, just return PC value */
1002 Root = GenLiteralExpr (GetPC ());
1010 ExprNode* GenSwapExpr (ExprNode* Expr)
1011 /* Return an extended expression with lo and hi bytes swapped */
1013 ExprNode* N = NewExprNode ();
1021 ExprNode* GenBranchExpr (unsigned Offs)
1022 /* Return an expression that encodes the difference between current PC plus
1023 * offset and the target expression (that is, Expression() - (*+Offs) ).
1032 Left = NewExprNode ();
1033 Left->Op = EXPR_SECTION;
1034 Left->V.SegNum = GetSegNum ();
1038 N->Right = GenLiteralExpr (GetPC () + Offs);
1041 N = GenLiteralExpr (GetPC () + Offs);
1044 /* Create the root node */
1045 Root = NewExprNode ();
1046 Root->Left = Expression ();
1048 Root->Op = EXPR_MINUS;
1050 /* Return the result */
1051 return SimplifyExpr (Root);
1056 ExprNode* GenULabelExpr (unsigned Num)
1057 /* Return an expression for an unnamed label with the given index */
1059 /* Get an expression node */
1060 ExprNode* Node = NewExprNode ();
1062 /* Set the values */
1063 Node->Op = EXPR_ULABEL;
1066 /* Return the new node */
1072 ExprNode* GenByteExpr (ExprNode* Expr)
1073 /* Force the given expression into a byte and return the result */
1075 /* Use the low byte operator to force the expression into byte size */
1076 ExprNode* Root = NewExprNode ();
1078 Root->Op = EXPR_BYTE0;
1080 /* Return the result */
1086 ExprNode* GenWordExpr (ExprNode* Expr)
1087 /* Force the given expression into a word and return the result. */
1089 /* AND the expression by $FFFF to force it into word size */
1090 ExprNode* Root = NewExprNode ();
1092 Root->Op = EXPR_AND;
1093 Root->Right = GenLiteralExpr (0xFFFF);
1095 /* Return the result */
1101 ExprNode* GenNE (ExprNode* Expr, long Val)
1102 /* Generate an expression that compares Expr and Val for inequality */
1104 /* Generate a compare node */
1105 ExprNode* Root = NewExprNode ();
1108 Root->Right = GenLiteralExpr (Val);
1110 /* Return the result */
1116 int IsConstExpr (ExprNode* Root)
1117 /* Return true if the given expression is a constant expression, that is, one
1118 * with no references to external symbols.
1124 if (EXPR_IS_LEAF (Root->Op)) {
1132 if (SymHasUserMark (Sym)) {
1133 if (Verbosity > 0) {
1136 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1140 Const = SymIsConst (Sym);
1141 SymUnmarkUser (Sym);
1149 } else if (EXPR_IS_UNARY (Root->Op)) {
1151 return IsConstExpr (Root->Left);
1155 /* We must handle shortcut boolean expressions here */
1159 if (IsConstExpr (Root->Left)) {
1160 /* lhs is const, if it is zero, don't eval right */
1161 if (GetExprVal (Root->Left) == 0) {
1164 return IsConstExpr (Root->Right);
1167 /* lhs not const --> tree not const */
1173 if (IsConstExpr (Root->Left)) {
1174 /* lhs is const, if it is not zero, don't eval right */
1175 if (GetExprVal (Root->Left) != 0) {
1178 return IsConstExpr (Root->Right);
1181 /* lhs not const --> tree not const */
1187 /* All others are handled normal */
1188 return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
1195 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1196 /* Internal routine that is recursively called to check if there is a zeropage
1197 * symbol in the expression tree.
1201 switch (N->Op & EXPR_TYPEMASK) {
1207 if (SymIsZP (N->V.Sym)) {
1209 } else if (SymHasExpr (N->V.Sym)) {
1210 /* Check if this expression is a byte expression */
1211 *IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
1216 if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
1224 case EXPR_UNARYNODE:
1225 CheckByteExpr (N->Left, IsByte);
1228 case EXPR_BINARYNODE:
1229 CheckByteExpr (N->Left, IsByte);
1230 CheckByteExpr (N->Right, IsByte);
1234 Internal ("Unknown expression op: %02X", N->Op);
1241 int IsByteExpr (ExprNode* Root)
1242 /* Return true if this is a byte expression */
1246 if (IsConstExpr (Root)) {
1247 if (Root->Op != EXPR_LITERAL) {
1248 SimplifyExpr (Root);
1250 return IsByteRange (GetExprVal (Root));
1251 } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
1252 Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
1253 /* Symbol forced to have byte range */
1256 /* We have undefined symbols in the expression. Assume that the
1257 * expression is a byte expression if there is at least one symbol
1258 * declared as zeropage in it. Being wrong here is not a very big
1259 * problem since the linker knows about all symbols and detects
1260 * error like mixing absolute and zeropage labels.
1263 CheckByteExpr (Root, &IsByte);
1270 long GetExprVal (ExprNode* Expr)
1271 /* Get the value of a constant expression */
1281 return GetSymVal (Expr->V.Sym);
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 Left = GetExprVal (Expr->Left);
1294 Right = GetExprVal (Expr->Right);
1296 Error (ERR_DIV_BY_ZERO);
1299 return Left / Right;
1302 Left = GetExprVal (Expr->Left);
1303 Right = GetExprVal (Expr->Right);
1305 Error (ERR_MOD_BY_ZERO);
1308 return Left % Right;
1311 return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
1314 return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
1317 return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
1320 return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
1323 return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
1326 return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));
1329 return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));
1332 return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));
1335 return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));
1338 return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));
1341 return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));
1343 case EXPR_UNARY_MINUS:
1344 return -GetExprVal (Expr->Left);
1347 return ~GetExprVal (Expr->Left);
1350 return GetExprVal (Expr->Left) & 0xFF;
1353 return (GetExprVal (Expr->Left) >> 8) & 0xFF;
1356 return (GetExprVal (Expr->Left) >> 16) & 0xFF;
1359 return (GetExprVal (Expr->Left) >> 24) & 0xFF;
1362 Left = GetExprVal (Expr->Left);
1363 return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
1366 return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
1369 return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
1372 return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
1375 return !GetExprVal (Expr->Left);
1378 Internal ("GetExprVal called for EXPR_ULABEL");
1383 Internal ("Unknown Op type: %u", Expr->Op);
1391 static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
1392 /* Remove resolved symbols from the tree by cloning symbol expressions */
1394 /* Accept NULL pointers */
1399 /* Special node handling */
1403 if (SymHasExpr (Expr->V.Sym)) {
1404 /* The symbol has an expression tree */
1405 SymEntry* Sym = Expr->V.Sym;
1406 if (SymHasUserMark (Sym)) {
1407 /* Circular definition */
1411 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1412 return GenLiteralExpr (0); /* Return a dummy value */
1415 Expr = RemoveSyms (GetSymExpr (Sym), 1);
1416 SymUnmarkUser (Sym);
1418 } else if (SymIsConst (Expr->V.Sym)) {
1419 /* The symbol is a constant */
1420 return GenLiteralExpr (GetSymVal (Expr->V.Sym));
1425 if (ULabCanResolve ()) {
1426 ExprNode* NewExpr = ULabResolve (Expr->V.Val);
1434 /* Clone the current node if needed */
1437 /* Create a new node */
1438 ExprNode* Clone = NewExprNode ();
1440 /* Clone the operation */
1441 Clone->Op = Expr->Op;
1443 /* Clone the attribute if needed */
1448 Clone->V.Val = Expr->V.Val;
1452 Clone->V.Sym = Expr->V.Sym;
1456 Clone->V.SegNum = Expr->V.SegNum;
1461 /* Clone the tree nodes */
1462 Clone->Left = RemoveSyms (Expr->Left, MustClone);
1463 Clone->Right = RemoveSyms (Expr->Right, MustClone);
1470 /* Nothing to clone */
1471 Expr->Left = RemoveSyms (Expr->Left, MustClone);
1472 Expr->Right = RemoveSyms (Expr->Right, MustClone);
1482 static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
1483 /* Extract and evaluate all constant factors in an subtree that has only
1484 * additions and subtractions.
1487 if (Expr->Op == EXPR_LITERAL) {
1489 *Val -= Expr->V.Val;
1491 *Val += Expr->V.Val;
1493 FreeExprNode (Expr);
1497 if (Expr->Op == EXPR_PLUS || Expr->Op == EXPR_MINUS) {
1500 Left = ConstExtract (Expr->Left, Val, Sign);
1501 if (Expr->Op == EXPR_MINUS) {
1504 Right = ConstExtract (Expr->Right, Val, Sign);
1505 if (Left == 0 && Right == 0) {
1506 FreeExprNode (Expr);
1508 } else if (Left == 0) {
1509 FreeExprNode (Expr);
1511 } else if (Right == 0) {
1512 FreeExprNode (Expr);
1515 /* Check for SEG - SEG which is now possible */
1516 if (Left->Op == EXPR_SECTION && Right->Op == EXPR_SECTION &&
1517 Left->V.SegNum == Right->V.SegNum) {
1518 /* SEG - SEG, remove it completely */
1519 FreeExprNode (Left);
1520 FreeExprNode (Right);
1521 FreeExprNode (Expr);
1525 Expr->Right = Right;
1531 /* Some other sort of node, finalize the terms */
1533 Expr->Left = FinalizeExpr (Expr->Left);
1536 Expr->Right = FinalizeExpr (Expr->Right);
1544 ExprNode* FinalizeExpr (ExprNode* Expr)
1545 /* Resolve any symbols by cloning the symbol expression tree instead of the
1546 * symbol reference, then try to simplify the expression as much as possible.
1547 * This function must only be called if all symbols are resolved (no undefined
1554 Expr = RemoveSyms (Expr, 0);
1555 Expr = ConstExtract (Expr, &Val, 1);
1557 /* Reduced to a literal value */
1558 Expr = GenLiteralExpr (Val);
1560 /* Extracted a value */
1564 N->Right = GenLiteralExpr (Val);
1572 ExprNode* CloneExpr (ExprNode* Expr)
1573 /* Clone the given expression tree. The function will simply clone symbol
1574 * nodes, it will not resolve them.
1579 /* Accept NULL pointers */
1584 /* Get a new node */
1585 Clone = NewExprNode ();
1587 /* Clone the operation */
1588 Clone->Op = Expr->Op;
1590 /* Clone the attribute if needed */
1595 Clone->V.Val = Expr->V.Val;
1599 Clone->V.Sym = Expr->V.Sym;
1603 Clone->V.SegNum = Expr->V.SegNum;
1608 /* Clone the tree nodes */
1609 Clone->Left = CloneExpr (Expr->Left);
1610 Clone->Right = CloneExpr (Expr->Right);
1618 void WriteExpr (ExprNode* Expr)
1619 /* Write the given expression to the object file */
1621 /* Null expressions are encoded by a type byte of zero */
1627 /* Write the expression code */
1628 ObjWrite8 (Expr->Op);
1630 /* If the is a leafnode, write the expression attribute, otherwise
1631 * write the expression operands.
1636 ObjWrite32 (Expr->V.Val);
1640 /* Maybe we should use a code here? */
1641 CHECK (SymIsImport (Expr->V.Sym)); /* Safety */
1642 ObjWriteVar (GetSymIndex (Expr->V.Sym));
1646 ObjWrite8 (Expr->V.SegNum);
1650 Internal ("WriteExpr: Cannot write EXPR_ULABEL nodes");
1654 /* Not a leaf node */
1655 WriteExpr (Expr->Left);
1656 WriteExpr (Expr->Right);