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 /*****************************************************************************/
54 /* #include "objcode.h" */
63 /*****************************************************************************/
65 /*****************************************************************************/
69 /* Since all expressions are first packed into expression trees, and each
70 * expression tree node is allocated on the heap, we add some type of special
71 * purpose memory allocation here: Instead of freeing the nodes, we save some
72 * number of freed nodes for later and remember them in a single linked list
73 * using the Left link.
75 #define MAX_FREE_NODES 64
76 static ExprNode* FreeExprNodes = 0;
77 static unsigned FreeNodeCount = 0;
81 /*****************************************************************************/
83 /*****************************************************************************/
87 static ExprNode* NewExprNode (unsigned Op)
88 /* Create a new expression node */
92 /* Do we have some nodes in the list already? */
94 /* Use first node from list */
96 FreeExprNodes = N->Left;
98 /* Allocate fresh memory */
99 N = xmalloc (sizeof (ExprNode));
102 N->Left = N->Right = 0;
110 static void FreeExprNode (ExprNode* E)
114 if (FreeNodeCount < MAX_FREE_NODES) {
115 /* Remember this node for later */
116 E->Left = FreeExprNodes;
119 /* Free the memory */
127 /*****************************************************************************/
129 /*****************************************************************************/
133 static ExprNode* Expr0 (void);
137 int IsByteRange (long Val)
138 /* Return true if this is a byte value */
140 return (Val & ~0xFFL) == 0;
145 int IsWordRange (long Val)
146 /* Return true if this is a word value */
148 return (Val & ~0xFFFF) == 0;
153 static int FuncBlank (void)
154 /* Handle the .BLANK builtin function */
156 /* Assume no tokens if the closing brace follows (this is not correct in
157 * all cases, since the token may be the closing brace, but this will
158 * give a syntax error anyway and may not be handled by .BLANK.
160 if (Tok == TOK_RPAREN) {
164 /* Skip any tokens */
166 while (!TokIsSep (Tok)) {
167 if (Tok == TOK_LPAREN) {
169 } else if (Tok == TOK_RPAREN) {
185 static int FuncConst (void)
186 /* Handle the .CONST builtin function */
188 /* Read an expression */
189 ExprNode* Expr = Expression ();
191 /* Check the constness of the expression */
192 int Result = IsConstExpr (Expr);
194 /* Free the expression */
203 static int FuncDefined (void)
204 /* Handle the .DEFINED builtin function */
206 static const char* Keys[] = {
212 char Name [sizeof (SVal)];
216 /* First argument is a symbol name */
217 if (Tok != TOK_IDENT) {
218 Error (ERR_IDENT_EXPECTED);
219 if (Tok != TOK_RPAREN) {
225 /* Remember the name, then skip it */
229 /* Comma and scope spec may follow */
230 if (Tok == TOK_COMMA) {
235 /* An identifier must follow */
236 if (Tok != TOK_IDENT) {
237 Error (ERR_IDENT_EXPECTED);
241 /* Get the scope, then skip it */
242 Scope = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
245 /* Check if we got a valid keyword */
247 Error (ERR_ILLEGAL_SCOPE);
253 case 0: Scope = SCOPE_ANY; break;
254 case 1: Scope = SCOPE_GLOBAL; break;
255 case 2: Scope = SCOPE_LOCAL; break;
256 default: Internal ("Invalid scope: %d", Scope);
266 /* Search for the symbol */
267 Result = SymIsDef (SVal, Scope);
275 static int DoMatch (enum TC EqualityLevel)
276 /* Handle the .MATCH and .XMATCH builtin functions */
283 /* A list of tokens follows. Read this list and remember it building a
284 * single linked list of tokens including attributes. The list is
285 * terminated by a comma.
287 while (Tok != TOK_COMMA) {
289 /* We may not end-of-line of end-of-file here */
290 if (TokIsSep (Tok)) {
291 Error (ERR_UNEXPECTED_EOL);
295 /* Get a node with this token */
296 Node = NewTokNode ();
298 /* Insert the node into the list */
313 /* Read the second list which is terminated by the right parenthesis and
314 * compare each token against the one in the first list.
318 while (Tok != TOK_RPAREN) {
320 /* We may not end-of-line of end-of-file here */
321 if (TokIsSep (Tok)) {
322 Error (ERR_UNEXPECTED_EOL);
326 /* Compare the tokens if the result is not already known */
329 /* The second list is larger than the first one */
331 } else if (TokCmp (Node) < EqualityLevel) {
332 /* Tokens do not match */
337 /* Next token in first list */
342 /* Next token in current list */
346 /* Check if there are remaining tokens in the first list */
351 /* Free the token list */
358 /* Done, return the result */
364 static int FuncMatch (void)
365 /* Handle the .MATCH function */
367 return DoMatch (tcSameToken);
372 static int FuncReferenced (void)
373 /* Handle the .REFERENCED builtin function */
377 if (Tok != TOK_IDENT) {
378 Error (ERR_IDENT_EXPECTED);
379 if (Tok != TOK_RPAREN) {
383 Result = SymIsRef (SVal, SCOPE_ANY);
393 static int FuncStrAt (void)
394 /* Handle the .STRAT function */
396 char Str [sizeof(SVal)];
399 /* String constant expected */
400 if (Tok != TOK_STRCON) {
401 Error (ERR_STRCON_EXPECTED);
407 /* Remember the string and skip it */
411 /* Comma must follow */
414 /* Expression expected */
415 Index = ConstExpression ();
417 /* Must be a valid index */
418 if (Index >= (long) strlen (Str)) {
423 /* Return the char, handle as unsigned. Be sure to translate it into
424 * the target character set.
426 return (unsigned char) TgtTranslateChar (Str [(size_t)Index]);
431 static int FuncStrLen (void)
432 /* Handle the .STRLEN function */
434 /* String constant expected */
435 if (Tok != TOK_STRCON) {
437 Error (ERR_STRCON_EXPECTED);
438 /* Smart error recovery */
439 if (Tok != TOK_RPAREN) {
446 /* Get the length of the string */
447 int Len = strlen (SVal);
449 /* Skip the string */
452 /* Return the length */
460 static int FuncTCount (void)
461 /* Handle the .TCOUNT function */
463 /* We have a list of tokens that ends with the closing paren. Skip
464 * the tokens, handling nested braces and count them.
468 while (Parens != 0 || Tok != TOK_RPAREN) {
470 /* Check for end of line or end of input. Since the calling function
471 * will check for the closing paren, we don't need to print an error
472 * here, just bail out.
474 if (TokIsSep (Tok)) {
481 /* Keep track of the nesting level */
483 case TOK_LPAREN: ++Parens; break;
484 case TOK_RPAREN: --Parens; break;
492 /* Return the number of tokens */
498 static int FuncXMatch (void)
499 /* Handle the .XMATCH function */
501 return DoMatch (tcIdentical);
506 static ExprNode* Function (int (*F) (void))
507 /* Handle builtin functions */
511 /* Skip the keyword */
514 /* Expression must be enclosed in braces */
515 if (Tok != TOK_LPAREN) {
516 Error (ERR_LPAREN_EXPECTED);
518 return GenLiteralExpr (0);
522 /* Call the function itself */
525 /* Closing brace must follow */
528 /* Return an expression node with the boolean code */
529 return GenLiteralExpr (Result);
534 static ExprNode* Factor (void)
542 N = GenLiteralExpr (IVal);
547 N = GenLiteralExpr (TgtTranslateChar (IVal));
553 if (Tok != TOK_IDENT) {
554 Error (ERR_IDENT_EXPECTED);
555 N = GenLiteralExpr (0); /* Dummy */
557 S = SymRef (SVal, SCOPE_GLOBAL);
558 if (SymIsConst (S)) {
559 /* Use the literal value instead */
560 N = GenLiteralExpr (GetSymVal (S));
562 /* 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 */
588 N = NewExprNode (EXPR_UNARY_MINUS);
594 N = NewExprNode (EXPR_NOT);
606 N = NewExprNode (EXPR_BYTE0);
612 N = NewExprNode (EXPR_BYTE1);
623 N = Function (FuncBlank);
627 N = Function (FuncConst);
631 N = GenLiteralExpr (CPUIsets[CPU]);
636 N = Function (FuncDefined);
640 N = Function (FuncMatch);
644 N = Function (FuncReferenced);
648 N = Function (FuncStrAt);
652 N = Function (FuncStrLen);
656 N = Function (FuncTCount);
660 N = GenLiteralExpr (time (0));
665 N = GenLiteralExpr (VERSION);
671 N = Function (FuncXMatch);
675 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
676 /* A character constant */
677 N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
679 N = GenLiteralExpr (0); /* Dummy */
690 static ExprNode* Term (void)
692 /* Read left hand side */
693 ExprNode* Root = Factor ();
695 /* Handle multiplicative operations */
696 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
697 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
700 /* Create the new node */
701 ExprNode* Left = Root;
703 case TOK_MUL: Root = NewExprNode (EXPR_MUL); break;
704 case TOK_DIV: Root = NewExprNode (EXPR_DIV); break;
705 case TOK_MOD: Root = NewExprNode (EXPR_MOD); break;
706 case TOK_AND: Root = NewExprNode (EXPR_AND); break;
707 case TOK_XOR: Root = NewExprNode (EXPR_XOR); break;
708 case TOK_SHL: Root = NewExprNode (EXPR_SHL); break;
709 case TOK_SHR: Root = NewExprNode (EXPR_SHR); break;
710 default: Internal ("Invalid token");
714 /* Skip the operator token */
717 /* Parse the right hand side */
718 Root->Right = Factor ();
722 /* Return the expression tree we've created */
728 static ExprNode* SimpleExpr (void)
730 /* Read left hand side */
731 ExprNode* Root = Term ();
733 /* Handle additive operations */
734 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
736 /* Create the new node */
737 ExprNode* Left = Root;
739 case TOK_PLUS: Root = NewExprNode (EXPR_PLUS); break;
740 case TOK_MINUS: Root = NewExprNode (EXPR_MINUS); break;
741 case TOK_OR: Root = NewExprNode (EXPR_OR); break;
742 default: Internal ("Invalid token");
746 /* Skip the operator token */
749 /* Parse the right hand side */
750 Root->Right = Term ();
754 /* Return the expression tree we've created */
760 static ExprNode* BoolExpr (void)
761 /* Evaluate a boolean expression */
763 /* Read left hand side */
764 ExprNode* Root = SimpleExpr ();
766 /* Handle booleans */
767 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
768 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
770 /* Create the new node */
771 ExprNode* Left = Root;
773 case TOK_EQ: Root = NewExprNode (EXPR_EQ); break;
774 case TOK_NE: Root = NewExprNode (EXPR_NE); break;
775 case TOK_LT: Root = NewExprNode (EXPR_LT); break;
776 case TOK_GT: Root = NewExprNode (EXPR_GT); break;
777 case TOK_LE: Root = NewExprNode (EXPR_LE); break;
778 case TOK_GE: Root = NewExprNode (EXPR_GE); break;
779 default: Internal ("Invalid token");
783 /* Skip the operator 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 the new node */
807 ExprNode* Left = Root;
809 case TOK_BAND: Root = NewExprNode (EXPR_BAND); break;
810 case TOK_BXOR: Root = NewExprNode (EXPR_BXOR); break;
811 default: Internal ("Invalid token");
815 /* Skip the operator token */
818 /* Parse the right hand side */
819 Root->Right = BoolExpr ();
823 /* Return the expression tree we've created */
829 static ExprNode* Expr1 (void)
830 /* Boolean operators: OR */
832 /* Read left hand side */
833 ExprNode* Root = Expr2 ();
835 /* Handle booleans */
836 while (Tok == TOK_BOR) {
838 /* Create the new node */
839 ExprNode* Left = Root;
841 case TOK_BOR: Root = NewExprNode (EXPR_BOR); break;
842 default: Internal ("Invalid token");
846 /* Skip the operator token */
849 /* Parse the right hand side */
850 Root->Right = Expr2 ();
854 /* Return the expression tree we've created */
860 static ExprNode* Expr0 (void)
861 /* Boolean operators: NOT */
865 /* Handle booleans */
866 if (Tok == TOK_BNOT) {
868 /* Create the new node */
869 Root = NewExprNode (EXPR_BNOT);
871 /* Skip the operator token */
874 /* Parse the left hand side, allow more BNOTs */
875 Root->Left = Expr0 ();
879 /* Read left hand side */
884 /* Return the expression tree we've created */
890 static ExprNode* SimplifyExpr (ExprNode* Root)
891 /* Try to simplify the given expression tree */
894 Root->Left = SimplifyExpr (Root->Left);
895 Root->Right = SimplifyExpr (Root->Right);
896 if (IsConstExpr (Root)) {
897 /* The complete expression is constant */
898 Root->V.Val = GetExprVal (Root);
899 Root->Op = EXPR_LITERAL;
900 FreeExpr (Root->Left);
901 FreeExpr (Root->Right);
902 Root->Left = Root->Right = 0;
910 ExprNode* Expression (void)
911 /* Evaluate an expression, build the expression tree on the heap and return
912 * a pointer to the root of the tree.
915 return SimplifyExpr (Expr0 ());
920 long ConstExpression (void)
921 /* Parse an expression. Check if the expression is const, and print an error
922 * message if not. Return the value of the expression, or a dummy, if it is
928 /* Read the expression, and call finalize (exception here, since we
931 ExprNode* Expr = FinalizeExpr (Expression ());
934 if (IsConstExpr (Expr)) {
935 Val = GetExprVal (Expr);
937 Error (ERR_CONSTEXPR_EXPECTED);
941 /* Free the expression tree and return the value */
948 void FreeExpr (ExprNode* Root)
949 /* Free the expression, Root is pointing to. */
952 FreeExpr (Root->Left);
953 FreeExpr (Root->Right);
954 if (Root->Op == EXPR_SYMBOL) {
955 /* Remove the symbol reference */
956 SymDelRef (Root->V.Sym, Root);
964 ExprNode* GenLiteralExpr (long Val)
965 /* Return an expression tree that encodes the given literal value */
967 ExprNode* Expr = NewExprNode (EXPR_LITERAL);
974 ExprNode* GenSymExpr (SymEntry* Sym)
975 /* Return an expression node that encodes the given symbol */
977 ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
979 SymAddRef (Sym, Expr);
985 static ExprNode* GenSectionExpr (unsigned SegNum)
986 /* Return an expression node for the given section */
988 ExprNode* Expr = NewExprNode (EXPR_SECTION);
989 Expr->V.SegNum = SegNum;
995 ExprNode* GenCurrentPC (void)
996 /* Return the current program counter as expression */
1001 /* Create SegmentBase + Offset */
1002 Root = NewExprNode (EXPR_PLUS);
1003 Root->Left = GenSectionExpr (GetSegNum ());
1004 Root->Right = GenLiteralExpr (GetPC ());
1006 /* Absolute mode, just return PC value */
1007 Root = GenLiteralExpr (GetPC ());
1015 ExprNode* GenSwapExpr (ExprNode* Expr)
1016 /* Return an extended expression with lo and hi bytes swapped */
1018 ExprNode* N = NewExprNode (EXPR_SWAP);
1025 ExprNode* GenBranchExpr (unsigned Offs)
1026 /* Return an expression that encodes the difference between current PC plus
1027 * offset and the target expression (that is, Expression() - (*+Offs) ).
1035 N = NewExprNode (EXPR_PLUS);
1036 N->Left = GenSectionExpr (GetSegNum ());
1037 N->Right = GenLiteralExpr (GetPC () + Offs);
1039 N = GenLiteralExpr (GetPC () + Offs);
1042 /* Create the root node */
1043 Root = NewExprNode (EXPR_MINUS);
1044 Root->Left = Expression ();
1047 /* Return the result */
1048 return SimplifyExpr (Root);
1053 ExprNode* GenULabelExpr (unsigned Num)
1054 /* Return an expression for an unnamed label with the given index */
1056 ExprNode* Node = NewExprNode (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 (EXPR_BYTE0);
1072 /* Return the result */
1078 ExprNode* GenWordExpr (ExprNode* Expr)
1079 /* Force the given expression into a word and return the result. */
1081 /* AND the expression by $FFFF to force it into word size */
1082 ExprNode* Root = NewExprNode (EXPR_AND);
1084 Root->Right = GenLiteralExpr (0xFFFF);
1086 /* Return the result */
1092 ExprNode* GenNE (ExprNode* Expr, long Val)
1093 /* Generate an expression that compares Expr and Val for inequality */
1095 /* Generate a compare node */
1096 ExprNode* Root = NewExprNode (EXPR_NE);
1098 Root->Right = GenLiteralExpr (Val);
1100 /* Return the result */
1106 int IsConstExpr (ExprNode* Root)
1107 /* Return true if the given expression is a constant expression, that is, one
1108 * with no references to external symbols.
1114 if (EXPR_IS_LEAF (Root->Op)) {
1122 if (SymHasUserMark (Sym)) {
1123 if (Verbosity > 0) {
1126 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1130 Const = SymIsConst (Sym);
1131 SymUnmarkUser (Sym);
1139 } else if (EXPR_IS_UNARY (Root->Op)) {
1141 return IsConstExpr (Root->Left);
1145 /* We must handle shortcut boolean expressions here */
1149 if (IsConstExpr (Root->Left)) {
1150 /* lhs is const, if it is zero, don't eval right */
1151 if (GetExprVal (Root->Left) == 0) {
1154 return IsConstExpr (Root->Right);
1157 /* lhs not const --> tree not const */
1163 if (IsConstExpr (Root->Left)) {
1164 /* lhs is const, if it is not zero, don't eval right */
1165 if (GetExprVal (Root->Left) != 0) {
1168 return IsConstExpr (Root->Right);
1171 /* lhs not const --> tree not const */
1177 /* All others are handled normal */
1178 return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
1185 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1186 /* Internal routine that is recursively called to check if there is a zeropage
1187 * symbol in the expression tree.
1191 switch (N->Op & EXPR_TYPEMASK) {
1197 if (SymIsZP (N->V.Sym)) {
1199 } else if (SymHasExpr (N->V.Sym)) {
1200 /* Check if this expression is a byte expression */
1201 *IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
1206 if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
1214 case EXPR_UNARYNODE:
1215 CheckByteExpr (N->Left, IsByte);
1218 case EXPR_BINARYNODE:
1219 CheckByteExpr (N->Left, IsByte);
1220 CheckByteExpr (N->Right, IsByte);
1224 Internal ("Unknown expression op: %02X", N->Op);
1231 int IsByteExpr (ExprNode* Root)
1232 /* Return true if this is a byte expression */
1236 if (IsConstExpr (Root)) {
1237 if (Root->Op != EXPR_LITERAL) {
1238 SimplifyExpr (Root);
1240 return IsByteRange (GetExprVal (Root));
1241 } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
1242 Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
1243 /* Symbol forced to have byte range */
1246 /* We have undefined symbols in the expression. Assume that the
1247 * expression is a byte expression if there is at least one symbol
1248 * declared as zeropage in it. Being wrong here is not a very big
1249 * problem since the linker knows about all symbols and detects
1250 * error like mixing absolute and zeropage labels.
1253 CheckByteExpr (Root, &IsByte);
1260 long GetExprVal (ExprNode* Expr)
1261 /* Get the value of a constant expression */
1271 return GetSymVal (Expr->V.Sym);
1274 return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
1277 return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
1280 return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
1283 Left = GetExprVal (Expr->Left);
1284 Right = GetExprVal (Expr->Right);
1286 Error (ERR_DIV_BY_ZERO);
1289 return Left / Right;
1292 Left = GetExprVal (Expr->Left);
1293 Right = GetExprVal (Expr->Right);
1295 Error (ERR_MOD_BY_ZERO);
1298 return Left % Right;
1301 return GetExprVal (Expr->Left) | GetExprVal (Expr->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));
1333 case EXPR_UNARY_MINUS:
1334 return -GetExprVal (Expr->Left);
1337 return ~GetExprVal (Expr->Left);
1340 return GetExprVal (Expr->Left) & 0xFF;
1343 return (GetExprVal (Expr->Left) >> 8) & 0xFF;
1346 return (GetExprVal (Expr->Left) >> 16) & 0xFF;
1349 return (GetExprVal (Expr->Left) >> 24) & 0xFF;
1352 Left = GetExprVal (Expr->Left);
1353 return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
1356 return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
1359 return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
1362 return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
1365 return !GetExprVal (Expr->Left);
1368 Internal ("GetExprVal called for EXPR_ULABEL");
1373 Internal ("Unknown Op type: %u", Expr->Op);
1381 static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
1382 /* Remove resolved symbols from the tree by cloning symbol expressions */
1384 /* Accept NULL pointers */
1389 /* Special node handling */
1393 if (SymHasExpr (Expr->V.Sym)) {
1394 /* The symbol has an expression tree */
1395 SymEntry* Sym = Expr->V.Sym;
1396 if (SymHasUserMark (Sym)) {
1397 /* Circular definition */
1401 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1402 return GenLiteralExpr (0); /* Return a dummy value */
1405 Expr = RemoveSyms (GetSymExpr (Sym), 1);
1406 SymUnmarkUser (Sym);
1408 } else if (SymIsConst (Expr->V.Sym)) {
1409 /* The symbol is a constant */
1410 return GenLiteralExpr (GetSymVal (Expr->V.Sym));
1415 if (ULabCanResolve ()) {
1416 ExprNode* NewExpr = ULabResolve (Expr->V.Val);
1424 /* Clone the current node if needed */
1429 /* Clone the expression tree */
1433 Clone = GenLiteralExpr (Expr->V.Val);
1437 Clone = GenULabelExpr (Expr->V.Val);
1441 Clone = GenSymExpr (Expr->V.Sym);
1445 Clone = GenSectionExpr (Expr->V.SegNum);
1449 Clone = NewExprNode (Expr->Op);
1450 Clone->Left = RemoveSyms (Expr->Left, 1);
1451 Clone->Right = RemoveSyms (Expr->Right, 1);
1461 /* Nothing to clone */
1462 Expr->Left = RemoveSyms (Expr->Left, 0);
1463 Expr->Right = RemoveSyms (Expr->Right, 0);
1472 static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
1473 /* Extract and evaluate all constant factors in an subtree that has only
1474 * additions and subtractions.
1477 if (Expr->Op == EXPR_LITERAL) {
1479 *Val -= Expr->V.Val;
1481 *Val += Expr->V.Val;
1483 FreeExprNode (Expr);
1487 if (Expr->Op == EXPR_PLUS || Expr->Op == EXPR_MINUS) {
1490 Left = ConstExtract (Expr->Left, Val, Sign);
1491 if (Expr->Op == EXPR_MINUS) {
1494 Right = ConstExtract (Expr->Right, Val, Sign);
1495 if (Left == 0 && Right == 0) {
1496 FreeExprNode (Expr);
1498 } else if (Left == 0) {
1499 FreeExprNode (Expr);
1501 } else if (Right == 0) {
1502 FreeExprNode (Expr);
1505 /* Check for SEG - SEG which is now possible */
1506 if (Left->Op == EXPR_SECTION && Right->Op == EXPR_SECTION &&
1507 Left->V.SegNum == Right->V.SegNum) {
1508 /* SEG - SEG, remove it completely */
1509 FreeExprNode (Left);
1510 FreeExprNode (Right);
1511 FreeExprNode (Expr);
1515 Expr->Right = Right;
1521 /* Some other sort of node, finalize the terms */
1523 Expr->Left = FinalizeExpr (Expr->Left);
1526 Expr->Right = FinalizeExpr (Expr->Right);
1534 ExprNode* FinalizeExpr (ExprNode* Expr)
1535 /* Resolve any symbols by cloning the symbol expression tree instead of the
1536 * symbol reference, then try to simplify the expression as much as possible.
1537 * This function must only be called if all symbols are resolved (no undefined
1544 Expr = RemoveSyms (Expr, 0);
1545 Expr = ConstExtract (Expr, &Val, 1);
1547 /* Reduced to a literal value */
1548 Expr = GenLiteralExpr (Val);
1550 /* Extracted a value */
1551 N = NewExprNode (EXPR_PLUS);
1553 N->Right = GenLiteralExpr (Val);
1561 ExprNode* CloneExpr (ExprNode* Expr)
1562 /* Clone the given expression tree. The function will simply clone symbol
1563 * nodes, it will not resolve them.
1568 /* Accept NULL pointers */
1573 /* Clone the node */
1577 Clone = GenLiteralExpr (Expr->V.Val);
1581 Clone = GenULabelExpr (Expr->V.Val);
1585 Clone = GenSymExpr (Expr->V.Sym);
1589 Clone = GenSectionExpr (Expr->V.SegNum);
1593 /* Generate a new node */
1594 Clone = NewExprNode (Expr->Op);
1595 /* Clone the tree nodes */
1596 Clone->Left = CloneExpr (Expr->Left);
1597 Clone->Right = CloneExpr (Expr->Right);
1607 void WriteExpr (ExprNode* Expr)
1608 /* Write the given expression to the object file */
1610 /* Null expressions are encoded by a type byte of zero */
1616 /* Write the expression code */
1617 ObjWrite8 (Expr->Op);
1619 /* If the is a leafnode, write the expression attribute, otherwise
1620 * write the expression operands.
1625 ObjWrite32 (Expr->V.Val);
1629 /* Maybe we should use a code here? */
1630 CHECK (SymIsImport (Expr->V.Sym)); /* Safety */
1631 ObjWriteVar (GetSymIndex (Expr->V.Sym));
1635 ObjWrite8 (Expr->V.SegNum);
1639 Internal ("WriteExpr: Cannot write EXPR_ULABEL nodes");
1643 /* Not a leaf node */
1644 WriteExpr (Expr->Left);
1645 WriteExpr (Expr->Right);