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 /*****************************************************************************/
60 /*****************************************************************************/
62 /*****************************************************************************/
66 /* Since all expressions are first packed into expression trees, and each
67 * expression tree node is allocated on the heap, we add some type of special
68 * purpose memory allocation here: Instead of freeing the nodes, we save some
69 * number of freed nodes for later and remember them in a single linked list
70 * using the Left link.
72 #define MAX_FREE_NODES 64
73 static ExprNode* FreeExprNodes = 0;
74 static unsigned FreeNodeCount = 0;
78 /*****************************************************************************/
80 /*****************************************************************************/
84 static ExprNode* NewExprNode (void)
85 /* Create a new expression node */
89 /* Do we have some nodes in the list already? */
91 /* Use first node from list */
93 FreeExprNodes = N->Left;
95 /* Allocate fresh memory */
96 N = xmalloc (sizeof (ExprNode));
99 N->Left = N->Right = 0;
107 static void FreeExprNode (ExprNode* E)
111 if (FreeNodeCount < MAX_FREE_NODES) {
112 /* Remember this node for later */
113 E->Left = FreeExprNodes;
116 /* Free the memory */
124 /*****************************************************************************/
126 /*****************************************************************************/
130 static ExprNode* Expr0 (void);
134 int IsByteRange (long Val)
135 /* Return true if this is a byte value */
137 return (Val & ~0xFFL) == 0;
142 int IsWordRange (long Val)
143 /* Return true if this is a word value */
145 return (Val & ~0xFFFF) == 0;
150 static int FuncBlank (void)
151 /* Handle the .BLANK builtin function */
153 /* Assume no tokens if the closing brace follows (this is not correct in
154 * all cases, since the token may be the closing brace, but this will
155 * give a syntax error anyway and may not be handled by .BLANK.
157 if (Tok == TOK_RPAREN) {
161 /* Skip any tokens */
163 while (!TokIsSep (Tok)) {
164 if (Tok == TOK_LPAREN) {
166 } else if (Tok == TOK_RPAREN) {
182 static int FuncConst (void)
183 /* Handle the .CONST builtin function */
185 /* Read an expression */
186 ExprNode* Expr = Expression ();
188 /* Check the constness of the expression */
189 int Result = IsConstExpr (Expr);
191 /* Free the expression */
200 static int FuncDefined (void)
201 /* Handle the .DEFINED builtin function */
203 static const char* Keys[] = {
209 char Name [sizeof (SVal)];
213 /* First argument is a symbol name */
214 if (Tok != TOK_IDENT) {
215 Error (ERR_IDENT_EXPECTED);
216 if (Tok != TOK_RPAREN) {
222 /* Remember the name, then skip it */
226 /* Comma and scope spec may follow */
227 if (Tok == TOK_COMMA) {
232 /* An identifier must follow */
233 if (Tok != TOK_IDENT) {
234 Error (ERR_IDENT_EXPECTED);
238 /* Get the scope, then skip it */
239 Scope = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
242 /* Check if we got a valid keyword */
244 Error (ERR_ILLEGAL_SCOPE);
250 case 0: Scope = SCOPE_ANY; break;
251 case 1: Scope = SCOPE_GLOBAL; break;
252 case 2: Scope = SCOPE_LOCAL; break;
253 default: Internal ("Invalid scope: %d", Scope);
263 /* Search for the symbol */
264 Result = SymIsDef (SVal, Scope);
272 static int DoMatch (enum TC EqualityLevel)
273 /* Handle the .MATCH and .XMATCH builtin functions */
280 /* A list of tokens follows. Read this list and remember it building a
281 * single linked list of tokens including attributes. The list is
282 * terminated by a comma.
284 while (Tok != TOK_COMMA) {
286 /* We may not end-of-line of end-of-file here */
287 if (TokIsSep (Tok)) {
288 Error (ERR_UNEXPECTED_EOL);
292 /* Get a node with this token */
293 Node = NewTokNode ();
295 /* Insert the node into the list */
310 /* Read the second list which is terminated by the right parenthesis and
311 * compare each token against the one in the first list.
315 while (Tok != TOK_RPAREN) {
317 /* We may not end-of-line of end-of-file here */
318 if (TokIsSep (Tok)) {
319 Error (ERR_UNEXPECTED_EOL);
323 /* Compare the tokens if the result is not already known */
326 /* The second list is larger than the first one */
328 } else if (TokCmp (Node) < EqualityLevel) {
329 /* Tokens do not match */
334 /* Next token in first list */
339 /* Next token in current list */
343 /* Check if there are remaining tokens in the first list */
348 /* Free the token list */
355 /* Done, return the result */
361 static int FuncMatch (void)
362 /* Handle the .MATCH function */
364 return DoMatch (tcSameToken);
369 static int FuncReferenced (void)
370 /* Handle the .REFERENCED builtin function */
374 if (Tok != TOK_IDENT) {
375 Error (ERR_IDENT_EXPECTED);
376 if (Tok != TOK_RPAREN) {
380 Result = SymIsRef (SVal, SCOPE_ANY);
390 static int FuncStrAt (void)
391 /* Handle the .STRAT function */
393 char Str [sizeof(SVal)];
396 /* String constant expected */
397 if (Tok != TOK_STRCON) {
398 Error (ERR_STRCON_EXPECTED);
404 /* Remember the string and skip it */
408 /* Comma must follow */
411 /* Expression expected */
412 Index = ConstExpression ();
414 /* Must be a valid index */
415 if (Index >= (long) strlen (Str)) {
420 /* Return the char, handle as unsigned. Be sure to translate it into
421 * the target character set.
423 return (unsigned char) TgtTranslateChar (Str [(size_t)Index]);
428 static int FuncStrLen (void)
429 /* Handle the .STRLEN function */
431 /* String constant expected */
432 if (Tok != TOK_STRCON) {
434 Error (ERR_STRCON_EXPECTED);
435 /* Smart error recovery */
436 if (Tok != TOK_RPAREN) {
443 /* Get the length of the string */
444 int Len = strlen (SVal);
446 /* Skip the string */
449 /* Return the length */
457 static int FuncTCount (void)
458 /* Handle the .TCOUNT function */
460 /* We have a list of tokens that ends with the closing paren. Skip
461 * the tokens, handling nested braces and count them.
465 while (Parens != 0 || Tok != TOK_RPAREN) {
467 /* Check for end of line or end of input. Since the calling function
468 * will check for the closing paren, we don't need to print an error
469 * here, just bail out.
471 if (TokIsSep (Tok)) {
478 /* Keep track of the nesting level */
480 case TOK_LPAREN: ++Parens; break;
481 case TOK_RPAREN: --Parens; break;
489 /* Return the number of tokens */
495 static int FuncXMatch (void)
496 /* Handle the .XMATCH function */
498 return DoMatch (tcIdentical);
503 static ExprNode* Function (int (*F) (void))
504 /* Handle builtin functions */
508 /* Skip the keyword */
511 /* Expression must be enclosed in braces */
512 if (Tok != TOK_LPAREN) {
513 Error (ERR_LPAREN_EXPECTED);
515 return GenLiteralExpr (0);
519 /* Call the function itself */
522 /* Closing brace must follow */
525 /* Return an expression node with the boolean code */
526 return GenLiteralExpr (Result);
531 static ExprNode* Factor (void)
539 N = GenLiteralExpr (IVal);
544 N = GenLiteralExpr (TgtTranslateChar (IVal));
550 if (Tok != TOK_IDENT) {
551 Error (ERR_IDENT_EXPECTED);
552 N = GenLiteralExpr (0); /* Dummy */
554 S = SymRef (SVal, SCOPE_GLOBAL);
555 if (SymIsConst (S)) {
556 /* Use the literal value instead */
557 N = GenLiteralExpr (GetSymVal (S));
559 /* Create symbol node */
569 S = SymRef (SVal, SCOPE_LOCAL);
570 if (SymIsConst (S)) {
571 /* Use the literal value instead */
572 N = GenLiteralExpr (GetSymVal (S));
574 /* Create symbol node */
591 N->Op = EXPR_UNARY_MINUS;
628 N = Function (FuncBlank);
632 N = Function (FuncConst);
636 N = GenLiteralExpr (GetCPU());
641 N = Function (FuncDefined);
645 N = Function (FuncMatch);
649 N = Function (FuncReferenced);
653 N = Function (FuncStrAt);
657 N = Function (FuncStrLen);
661 N = Function (FuncTCount);
665 N = GenLiteralExpr (time (0));
670 N = Function (FuncXMatch);
674 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
675 /* A character constant */
676 N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
678 N = GenLiteralExpr (0); /* Dummy */
689 static ExprNode* Term (void)
693 /* Read left hand side */
696 /* Handle multiplicative operations */
697 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
698 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
701 /* Create a new node and insert the left expression */
702 ExprNode* Left = Root;
703 Root = NewExprNode ();
706 /* Determine the operator token */
708 case TOK_MUL: Root->Op = EXPR_MUL; break;
709 case TOK_DIV: Root->Op = EXPR_DIV; break;
710 case TOK_MOD: Root->Op = EXPR_MOD; break;
711 case TOK_AND: Root->Op = EXPR_AND; break;
712 case TOK_XOR: Root->Op = EXPR_XOR; break;
713 case TOK_SHL: Root->Op = EXPR_SHL; break;
714 case TOK_SHR: Root->Op = EXPR_SHR; break;
715 default: Internal ("Invalid token");
719 /* Parse the right hand side */
720 Root->Right = Factor ();
724 /* Return the expression tree we've created */
730 static ExprNode* SimpleExpr (void)
734 /* Read left hand side */
737 /* Handle additive operations */
738 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
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_PLUS: Root->Op = EXPR_PLUS; break;
748 case TOK_MINUS: Root->Op = EXPR_MINUS; break;
749 case TOK_OR: Root->Op = EXPR_OR; break;
750 default: Internal ("Invalid token");
754 /* Parse the right hand side */
755 Root->Right = Term ();
759 /* Return the expression tree we've created */
765 static ExprNode* BoolExpr (void)
766 /* Evaluate a boolean expression */
768 /* Read left hand side */
769 ExprNode* Root = SimpleExpr ();
771 /* Handle booleans */
772 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
773 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
775 /* Create a new node and insert the left expression */
776 ExprNode* Left = Root;
777 Root = NewExprNode ();
780 /* Determine the operator token */
782 case TOK_EQ: Root->Op = EXPR_EQ; break;
783 case TOK_NE: Root->Op = EXPR_NE; break;
784 case TOK_LT: Root->Op = EXPR_LT; break;
785 case TOK_GT: Root->Op = EXPR_GT; break;
786 case TOK_LE: Root->Op = EXPR_LE; break;
787 case TOK_GE: Root->Op = EXPR_GE; break;
788 default: Internal ("Invalid token");
792 /* Parse the right hand side */
793 Root->Right = SimpleExpr ();
797 /* Return the expression tree we've created */
803 static ExprNode* Expr2 (void)
804 /* Boolean operators: AND and XOR */
806 /* Read left hand side */
807 ExprNode* Root = BoolExpr ();
809 /* Handle booleans */
810 while (Tok == TOK_BAND || Tok == TOK_BXOR) {
812 /* Create a new node and insert the left expression */
813 ExprNode* Left = Root;
814 Root = NewExprNode ();
817 /* Determine the operator token */
819 case TOK_BAND: Root->Op = EXPR_BAND; break;
820 case TOK_BXOR: Root->Op = EXPR_BXOR; break;
821 default: Internal ("Invalid token");
825 /* Parse the right hand side */
826 Root->Right = BoolExpr ();
830 /* Return the expression tree we've created */
836 static ExprNode* Expr1 (void)
837 /* Boolean operators: OR */
839 /* Read left hand side */
840 ExprNode* Root = Expr2 ();
842 /* Handle booleans */
843 while (Tok == TOK_BOR) {
845 /* Create a new node and insert the left expression */
846 ExprNode* Left = Root;
847 Root = NewExprNode ();
850 /* Determine the operator token */
852 case TOK_BOR: Root->Op = EXPR_BOR; break;
853 default: Internal ("Invalid token");
857 /* Parse the right hand side */
858 Root->Right = Expr2 ();
862 /* Return the expression tree we've created */
868 static ExprNode* Expr0 (void)
869 /* Boolean operators: NOT */
873 /* Handle booleans */
874 if (Tok == TOK_BNOT) {
876 /* Create a new node */
877 Root = NewExprNode ();
879 /* Determine the operator token */
881 case TOK_BNOT: Root->Op = EXPR_BNOT; break;
882 default: Internal ("Invalid token");
886 /* Parse the left hand side, allow more BNOTs */
887 Root->Left = Expr0 ();
891 /* Read left hand side */
896 /* Return the expression tree we've created */
902 static ExprNode* SimplifyExpr (ExprNode* Root)
903 /* Try to simplify the given expression tree */
906 SimplifyExpr (Root->Left);
907 SimplifyExpr (Root->Right);
908 if (IsConstExpr (Root)) {
909 /* The complete expression is constant */
910 Root->V.Val = GetExprVal (Root);
911 Root->Op = EXPR_LITERAL;
912 FreeExpr (Root->Left);
913 FreeExpr (Root->Right);
914 Root->Left = Root->Right = 0;
922 ExprNode* Expression (void)
923 /* Evaluate an expression, build the expression tree on the heap and return
924 * a pointer to the root of the tree.
927 return SimplifyExpr (Expr0 ());
932 long ConstExpression (void)
933 /* Parse an expression. Check if the expression is const, and print an error
934 * message if not. Return the value of the expression, or a dummy, if it is
938 /* Read the expression, and call finalize (exception here, since we
941 ExprNode* Expr = FinalizeExpr (Expression ());
943 /* Return the value */
944 if (IsConstExpr (Expr)) {
945 return GetExprVal (Expr);
947 Error (ERR_CONSTEXPR_EXPECTED);
954 void FreeExpr (ExprNode* Root)
955 /* Free the expression, Root is pointing to. */
958 FreeExpr (Root->Left);
959 FreeExpr (Root->Right);
966 ExprNode* GenLiteralExpr (long Val)
967 /* Return an expression tree that encodes the given literal value */
969 ExprNode* Expr = NewExprNode ();
970 Expr->Op = EXPR_LITERAL;
977 ExprNode* GenCurrentPC (void)
978 /* Return the current program counter as expression */
984 /* Create SegmentBase + Offset */
985 Left = NewExprNode ();
986 Left->Op = EXPR_SECTION;
987 Left->V.SegNum = GetSegNum ();
989 Root = NewExprNode ();
991 Root->Right = GenLiteralExpr (GetPC ());
992 Root->Op = EXPR_PLUS;
994 /* Absolute mode, just return PC value */
995 Root = GenLiteralExpr (GetPC ());
1003 ExprNode* GenSwapExpr (ExprNode* Expr)
1004 /* Return an extended expression with lo and hi bytes swapped */
1006 ExprNode* N = NewExprNode ();
1014 ExprNode* GenBranchExpr (unsigned Offs)
1015 /* Return an expression that encodes the difference between current PC plus
1016 * offset and the target expression (that is, Expression() - (*+Offs) ).
1025 Left = NewExprNode ();
1026 Left->Op = EXPR_SECTION;
1027 Left->V.SegNum = GetSegNum ();
1031 N->Right = GenLiteralExpr (GetPC () + Offs);
1034 N = GenLiteralExpr (GetPC () + Offs);
1037 /* Create the root node */
1038 Root = NewExprNode ();
1039 Root->Left = Expression ();
1041 Root->Op = EXPR_MINUS;
1043 /* Return the result */
1044 return SimplifyExpr (Root);
1049 ExprNode* GenULabelExpr (unsigned Num)
1050 /* Return an expression for an unnamed label with the given index */
1052 /* Get an expression node */
1053 ExprNode* Node = NewExprNode ();
1055 /* Set the values */
1056 Node->Op = EXPR_ULABEL;
1059 /* Return the new node */
1065 ExprNode* GenByteExpr (ExprNode* Expr)
1066 /* Force the given expression into a byte and return the result */
1068 /* Use the low byte operator to force the expression into byte size */
1069 ExprNode* Root = NewExprNode ();
1071 Root->Op = EXPR_BYTE0;
1073 /* Return the result */
1079 ExprNode* GenWordExpr (ExprNode* Expr)
1080 /* Force the given expression into a word and return the result. */
1082 /* AND the expression by $FFFF to force it into word size */
1083 ExprNode* Root = NewExprNode ();
1085 Root->Op = EXPR_AND;
1086 Root->Right = GenLiteralExpr (0xFFFF);
1088 /* Return the result */
1094 ExprNode* GenNE (ExprNode* Expr, long Val)
1095 /* Generate an expression that compares Expr and Val for inequality */
1097 /* Generate a compare node */
1098 ExprNode* Root = NewExprNode ();
1101 Root->Right = GenLiteralExpr (Val);
1103 /* Return the result */
1109 int IsConstExpr (ExprNode* Root)
1110 /* Return true if the given expression is a constant expression, that is, one
1111 * with no references to external symbols.
1117 if (EXPR_IS_LEAF (Root->Op)) {
1125 if (SymHasUserMark (Sym)) {
1126 if (Verbosity > 0) {
1129 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1133 Const = SymIsConst (Sym);
1134 SymUnmarkUser (Sym);
1142 } else if (EXPR_IS_UNARY (Root->Op)) {
1144 return IsConstExpr (Root->Left);
1148 /* We must handle shortcut boolean expressions here */
1152 if (IsConstExpr (Root->Left)) {
1153 /* lhs is const, if it is zero, don't eval right */
1154 if (GetExprVal (Root->Left) == 0) {
1157 return IsConstExpr (Root->Right);
1160 /* lhs not const --> tree not const */
1166 if (IsConstExpr (Root->Left)) {
1167 /* lhs is const, if it is not zero, don't eval right */
1168 if (GetExprVal (Root->Left) != 0) {
1171 return IsConstExpr (Root->Right);
1174 /* lhs not const --> tree not const */
1180 /* All others are handled normal */
1181 return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
1188 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1189 /* Internal routine that is recursively called to check if there is a zeropage
1190 * symbol in the expression tree.
1194 switch (N->Op & EXPR_TYPEMASK) {
1200 if (SymIsZP (N->V.Sym)) {
1202 } else if (SymHasExpr (N->V.Sym)) {
1203 /* Check if this expression is a byte expression */
1204 *IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
1209 if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
1217 case EXPR_UNARYNODE:
1218 CheckByteExpr (N->Left, IsByte);
1221 case EXPR_BINARYNODE:
1222 CheckByteExpr (N->Left, IsByte);
1223 CheckByteExpr (N->Right, IsByte);
1227 Internal ("Unknown expression op: %02X", N->Op);
1234 int IsByteExpr (ExprNode* Root)
1235 /* Return true if this is a byte expression */
1239 if (IsConstExpr (Root)) {
1240 if (Root->Op != EXPR_LITERAL) {
1241 SimplifyExpr (Root);
1243 return IsByteRange (GetExprVal (Root));
1244 } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
1245 Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
1246 /* Symbol forced to have byte range */
1249 /* We have undefined symbols in the expression. Assume that the
1250 * expression is a byte expression if there is at least one symbol
1251 * declared as zeropage in it. Being wrong here is not a very big
1252 * problem since the linker knows about all symbols and detects
1253 * error like mixing absolute and zeropage labels.
1256 CheckByteExpr (Root, &IsByte);
1263 long GetExprVal (ExprNode* Expr)
1264 /* Get the value of a constant expression */
1274 return GetSymVal (Expr->V.Sym);
1277 return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
1280 return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
1283 return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
1286 Left = GetExprVal (Expr->Left);
1287 Right = GetExprVal (Expr->Right);
1289 Error (ERR_DIV_BY_ZERO);
1292 return Left / Right;
1295 Left = GetExprVal (Expr->Left);
1296 Right = GetExprVal (Expr->Right);
1298 Error (ERR_MOD_BY_ZERO);
1301 return Left % Right;
1304 return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
1307 return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
1310 return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
1313 return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
1316 return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
1319 return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));
1322 return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));
1325 return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));
1328 return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));
1331 return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));
1334 return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));
1336 case EXPR_UNARY_MINUS:
1337 return -GetExprVal (Expr->Left);
1340 return ~GetExprVal (Expr->Left);
1343 return GetExprVal (Expr->Left) & 0xFF;
1346 return (GetExprVal (Expr->Left) >> 8) & 0xFF;
1349 return (GetExprVal (Expr->Left) >> 16) & 0xFF;
1352 return (GetExprVal (Expr->Left) >> 24) & 0xFF;
1355 Left = GetExprVal (Expr->Left);
1356 return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
1359 return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
1362 return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
1365 return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
1368 return !GetExprVal (Expr->Left);
1371 Internal ("GetExprVal called for EXPR_ULABEL");
1376 Internal ("Unknown Op type: %u", Expr->Op);
1384 static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
1385 /* Remove resolved symbols from the tree by cloning symbol expressions */
1387 /* Accept NULL pointers */
1392 /* Special node handling */
1396 if (SymHasExpr (Expr->V.Sym)) {
1397 /* The symbol has an expression tree */
1398 SymEntry* Sym = Expr->V.Sym;
1399 if (SymHasUserMark (Sym)) {
1400 /* Circular definition */
1404 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1405 return GenLiteralExpr (0); /* Return a dummy value */
1408 Expr = RemoveSyms (GetSymExpr (Sym), 1);
1409 SymUnmarkUser (Sym);
1411 } else if (SymIsConst (Expr->V.Sym)) {
1412 /* The symbol is a constant */
1413 return GenLiteralExpr (GetSymVal (Expr->V.Sym));
1418 if (ULabCanResolve ()) {
1419 ExprNode* NewExpr = ULabResolve (Expr->V.Val);
1427 /* Clone the current node if needed */
1430 /* Create a new node */
1431 ExprNode* Clone = NewExprNode ();
1433 /* Clone the operation */
1434 Clone->Op = Expr->Op;
1436 /* Clone the attribute if needed */
1441 Clone->V.Val = Expr->V.Val;
1445 Clone->V.Sym = Expr->V.Sym;
1449 Clone->V.SegNum = Expr->V.SegNum;
1454 /* Clone the tree nodes */
1455 Clone->Left = RemoveSyms (Expr->Left, MustClone);
1456 Clone->Right = RemoveSyms (Expr->Right, MustClone);
1463 /* Nothing to clone */
1464 Expr->Left = RemoveSyms (Expr->Left, MustClone);
1465 Expr->Right = RemoveSyms (Expr->Right, MustClone);
1475 static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
1476 /* Extract and evaluate all constant factors in an subtree that has only
1477 * additions and subtractions.
1480 if (Expr->Op == EXPR_LITERAL) {
1482 *Val -= Expr->V.Val;
1484 *Val += Expr->V.Val;
1486 FreeExprNode (Expr);
1490 if (Expr->Op == EXPR_PLUS || Expr->Op == EXPR_MINUS) {
1493 Left = ConstExtract (Expr->Left, Val, Sign);
1494 if (Expr->Op == EXPR_MINUS) {
1497 Right = ConstExtract (Expr->Right, Val, Sign);
1498 if (Left == 0 && Right == 0) {
1499 FreeExprNode (Expr);
1501 } else if (Left == 0) {
1502 FreeExprNode (Expr);
1504 } else if (Right == 0) {
1505 FreeExprNode (Expr);
1508 /* Check for SEG - SEG which is now possible */
1509 if (Left->Op == EXPR_SECTION && Right->Op == EXPR_SECTION &&
1510 Left->V.SegNum == Right->V.SegNum) {
1511 /* SEG - SEG, remove it completely */
1512 FreeExprNode (Left);
1513 FreeExprNode (Right);
1514 FreeExprNode (Expr);
1518 Expr->Right = Right;
1524 /* Some other sort of node, finalize the terms */
1526 Expr->Left = FinalizeExpr (Expr->Left);
1529 Expr->Right = FinalizeExpr (Expr->Right);
1537 ExprNode* FinalizeExpr (ExprNode* Expr)
1538 /* Resolve any symbols by cloning the symbol expression tree instead of the
1539 * symbol reference, then try to simplify the expression as much as possible.
1540 * This function must only be called if all symbols are resolved (no undefined
1547 Expr = RemoveSyms (Expr, 0);
1548 Expr = ConstExtract (Expr, &Val, 1);
1550 /* Reduced to a literal value */
1551 Expr = GenLiteralExpr (Val);
1553 /* Extracted a value */
1557 N->Right = GenLiteralExpr (Val);
1565 ExprNode* CloneExpr (ExprNode* Expr)
1566 /* Clone the given expression tree. The function will simply clone symbol
1567 * nodes, it will not resolve them.
1572 /* Accept NULL pointers */
1577 /* Get a new node */
1578 Clone = NewExprNode ();
1580 /* Clone the operation */
1581 Clone->Op = Expr->Op;
1583 /* Clone the attribute if needed */
1588 Clone->V.Val = Expr->V.Val;
1592 Clone->V.Sym = Expr->V.Sym;
1596 Clone->V.SegNum = Expr->V.SegNum;
1601 /* Clone the tree nodes */
1602 Clone->Left = CloneExpr (Expr->Left);
1603 Clone->Right = CloneExpr (Expr->Right);
1611 void WriteExpr (ExprNode* Expr)
1612 /* Write the given expression to the object file */
1614 /* Null expressions are encoded by a type byte of zero */
1620 /* Write the expression code */
1621 ObjWrite8 (Expr->Op);
1623 /* If the is a leafnode, write the expression attribute, otherwise
1624 * write the expression operands.
1629 ObjWrite32 (Expr->V.Val);
1633 /* Maybe we should use a code here? */
1634 CHECK (SymIsImport (Expr->V.Sym)); /* Safety */
1635 ObjWriteVar (GetSymIndex (Expr->V.Sym));
1639 ObjWrite8 (Expr->V.SegNum);
1643 Internal ("WriteExpr: Cannot write EXPR_ULABEL nodes");
1647 /* Not a leaf node */
1648 WriteExpr (Expr->Left);
1649 WriteExpr (Expr->Right);