1 /*****************************************************************************/
5 /* Expression evaluation for the ca65 macroassembler */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
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 /*****************************************************************************/
64 /*****************************************************************************/
66 /*****************************************************************************/
70 /* Since all expressions are first packed into expression trees, and each
71 * expression tree node is allocated on the heap, we add some type of special
72 * purpose memory allocation here: Instead of freeing the nodes, we save some
73 * number of freed nodes for later and remember them in a single linked list
74 * using the Left link.
76 #define MAX_FREE_NODES 64
77 static ExprNode* FreeExprNodes = 0;
78 static unsigned FreeNodeCount = 0;
80 /* Structure for parsing expression trees */
81 typedef struct ExprDesc ExprDesc;
83 long Val; /* The offset value */
84 long Left; /* Left value for StudyBinaryExpr */
85 int TooComplex; /* Expression is too complex to evaluate */
86 long SymCount; /* Symbol reference count */
87 long SecCount; /* Section reference count */
88 SymEntry* SymRef; /* Symbol reference if any */
89 unsigned SecRef; /* Section reference if any */
95 /*****************************************************************************/
97 /*****************************************************************************/
101 static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign);
102 /* Study an expression tree and place the contents into D */
106 /*****************************************************************************/
108 /*****************************************************************************/
112 static ExprDesc* InitExprDesc (ExprDesc* ED)
113 /* Initialize an ExprDesc structure for use with StudyExpr */
124 static int ExprDescIsConst (const ExprDesc* ED)
125 /* Return true if the expression is constant */
127 return (ED->TooComplex == 0 && ED->SymCount == 0 && ED->SecCount == 0);
132 static ExprNode* NewExprNode (unsigned Op)
133 /* Create a new expression node */
137 /* Do we have some nodes in the list already? */
139 /* Use first node from list */
141 FreeExprNodes = N->Left;
143 /* Allocate fresh memory */
144 N = xmalloc (sizeof (ExprNode));
147 N->Left = N->Right = 0;
155 static void FreeExprNode (ExprNode* E)
159 if (E->Op == EXPR_SYMBOL) {
160 /* Remove the symbol reference */
161 SymDelExprRef (E->V.Sym, E);
163 /* Place the symbol into the free nodes list if possible */
164 if (FreeNodeCount < MAX_FREE_NODES) {
165 /* Remember this node for later */
166 E->Left = FreeExprNodes;
169 /* Free the memory */
177 /*****************************************************************************/
179 /*****************************************************************************/
183 static ExprNode* Expr0 (void);
187 int IsByteRange (long Val)
188 /* Return true if this is a byte value */
190 return (Val & ~0xFFL) == 0;
195 int IsWordRange (long Val)
196 /* Return true if this is a word value */
198 return (Val & ~0xFFFF) == 0;
203 static int IsEasyConst (const ExprNode* E, long* Val)
204 /* Do some light checking if the given node is a constant. Don't care if E is
205 * a complex expression. If E is a constant, return true and place its value
206 * into Val, provided that Val is not NULL.
209 /* Resolve symbols, follow symbol chains */
210 while (E->Op == EXPR_SYMBOL) {
211 E = SymResolve (E->V.Sym);
213 /* Could not resolve */
218 /* Symbols resolved, check for a literal */
219 if (E->Op == EXPR_LITERAL) {
226 /* Not found to be a const according to our tests */
232 static int FuncBlank (void)
233 /* Handle the .BLANK builtin function */
235 /* Assume no tokens if the closing brace follows (this is not correct in
236 * all cases, since the token may be the closing brace, but this will
237 * give a syntax error anyway and may not be handled by .BLANK.
239 if (Tok == TOK_RPAREN) {
243 /* Skip any tokens */
245 while (!TokIsSep (Tok)) {
246 if (Tok == TOK_LPAREN) {
248 } else if (Tok == TOK_RPAREN) {
264 static int FuncConst (void)
265 /* Handle the .CONST builtin function */
267 /* Read an expression */
268 ExprNode* Expr = Expression ();
270 /* Check the constness of the expression */
271 int Result = IsConstExpr (Expr, 0);
273 /* Free the expression */
282 static int FuncDefined (void)
283 /* Handle the .DEFINED builtin function */
285 /* Parse the symbol name and search for the symbol */
286 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
288 /* Check if the symbol is defined */
289 return (Sym != 0 && SymIsDef (Sym));
294 static int DoMatch (enum TC EqualityLevel)
295 /* Handle the .MATCH and .XMATCH builtin functions */
302 /* A list of tokens follows. Read this list and remember it building a
303 * single linked list of tokens including attributes. The list is
304 * terminated by a comma.
306 while (Tok != TOK_COMMA) {
308 /* We may not end-of-line of end-of-file here */
309 if (TokIsSep (Tok)) {
310 Error ("Unexpected end of line");
314 /* Get a node with this token */
315 Node = NewTokNode ();
317 /* Insert the node into the list */
332 /* Read the second list which is terminated by the right parenthesis and
333 * compare each token against the one in the first list.
337 while (Tok != TOK_RPAREN) {
339 /* We may not end-of-line of end-of-file here */
340 if (TokIsSep (Tok)) {
341 Error ("Unexpected end of line");
345 /* Compare the tokens if the result is not already known */
348 /* The second list is larger than the first one */
350 } else if (TokCmp (Node) < EqualityLevel) {
351 /* Tokens do not match */
356 /* Next token in first list */
361 /* Next token in current list */
365 /* Check if there are remaining tokens in the first list */
370 /* Free the token list */
377 /* Done, return the result */
383 static int FuncMatch (void)
384 /* Handle the .MATCH function */
386 return DoMatch (tcSameToken);
391 static int FuncReferenced (void)
392 /* Handle the .REFERENCED builtin function */
394 /* Parse the symbol name and search for the symbol */
395 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
397 /* Check if the symbol is referenced */
398 return (Sym != 0 && SymIsRef (Sym));
403 static int FuncStrAt (void)
404 /* Handle the .STRAT function */
406 char Str [sizeof(SVal)];
409 /* String constant expected */
410 if (Tok != TOK_STRCON) {
411 Error ("String constant expected");
417 /* Remember the string and skip it */
421 /* Comma must follow */
424 /* Expression expected */
425 Index = ConstExpression ();
427 /* Must be a valid index */
428 if (Index >= (long) strlen (Str)) {
429 Error ("Range error");
433 /* Return the char, handle as unsigned. Be sure to translate it into
434 * the target character set.
436 return (unsigned char) TgtTranslateChar (Str [(size_t)Index]);
441 static int FuncStrLen (void)
442 /* Handle the .STRLEN function */
444 /* String constant expected */
445 if (Tok != TOK_STRCON) {
447 Error ("String constant expected");
448 /* Smart error recovery */
449 if (Tok != TOK_RPAREN) {
456 /* Get the length of the string */
457 int Len = strlen (SVal);
459 /* Skip the string */
462 /* Return the length */
470 static int FuncTCount (void)
471 /* Handle the .TCOUNT function */
473 /* We have a list of tokens that ends with the closing paren. Skip
474 * the tokens, handling nested braces and count them.
478 while (Parens != 0 || Tok != TOK_RPAREN) {
480 /* Check for end of line or end of input. Since the calling function
481 * will check for the closing paren, we don't need to print an error
482 * here, just bail out.
484 if (TokIsSep (Tok)) {
491 /* Keep track of the nesting level */
493 case TOK_LPAREN: ++Parens; break;
494 case TOK_RPAREN: --Parens; break;
502 /* Return the number of tokens */
508 static int FuncXMatch (void)
509 /* Handle the .XMATCH function */
511 return DoMatch (tcIdentical);
516 static ExprNode* Function (int (*F) (void))
517 /* Handle builtin functions */
521 /* Skip the keyword */
524 /* Expression must be enclosed in braces */
525 if (Tok != TOK_LPAREN) {
526 Error ("'(' expected");
528 return GenLiteralExpr (0);
532 /* Call the function itself */
535 /* Closing brace must follow */
538 /* Return an expression node with the boolean code */
539 return GenLiteralExpr (Result);
544 static ExprNode* Factor (void)
554 N = GenLiteralExpr (IVal);
559 N = GenLiteralExpr (TgtTranslateChar (IVal));
565 /* Search for the symbol */
566 S = ParseScopedSymName (SYM_ALLOC_NEW);
568 /* Some weird error happened before */
569 N = GenLiteralExpr (0);
571 /* Mark the symbol as referenced */
573 /* Remove the symbol if possible */
574 if (SymHasExpr (S)) {
575 N = CloneExpr (GetSymExpr (S));
577 /* Create symbol node */
591 if (IsEasyConst (L, &Val)) {
593 N = GenLiteralExpr (-Val);
595 N = NewExprNode (EXPR_UNARY_MINUS);
603 if (IsEasyConst (L, &Val)) {
605 N = GenLiteralExpr (~Val);
607 N = NewExprNode (EXPR_NOT);
621 if (IsEasyConst (L, &Val)) {
623 N = GenLiteralExpr (Val & 0xFF);
625 N = NewExprNode (EXPR_BYTE0);
633 if (IsEasyConst (L, &Val)) {
635 N = GenLiteralExpr ((Val >> 8) & 0xFF);
637 N = NewExprNode (EXPR_BYTE1);
645 if (IsEasyConst (L, &Val)) {
647 N = GenLiteralExpr ((Val >> 16) & 0xFF);
649 N = NewExprNode (EXPR_BYTE2);
661 N = Function (FuncBlank);
665 N = Function (FuncConst);
669 N = GenLiteralExpr (CPUIsets[CPU]);
674 N = Function (FuncDefined);
678 N = Function (FuncMatch);
682 N = Function (FuncReferenced);
686 N = Function (FuncStrAt);
690 N = Function (FuncStrLen);
694 N = Function (FuncTCount);
698 N = GenLiteralExpr (time (0));
703 N = GenLiteralExpr (VERSION);
708 N = Function (FuncXMatch);
712 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
713 /* A character constant */
714 N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
716 N = GenLiteralExpr (0); /* Dummy */
717 Error ("Syntax error");
727 static ExprNode* Term (void)
729 /* Read left hand side */
730 ExprNode* Root = Factor ();
732 /* Handle multiplicative operations */
733 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
734 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
737 long LVal, RVal, Val;
741 /* Remember the token and skip it */
745 /* Move root to left side and read the right side */
749 /* If both expressions are constant, we can evaluate the term */
750 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
759 Error ("Division by zero");
768 Error ("Modulo operation with zero");
784 Val = shl_l (LVal, RVal);
788 Val = shr_l (LVal, RVal);
792 Internal ("Invalid token");
795 /* Generate a literal expression and delete the old left and
800 Root = GenLiteralExpr (Val);
804 /* Generate an expression tree */
807 case TOK_MUL: Op = EXPR_MUL; break;
808 case TOK_DIV: Op = EXPR_DIV; break;
809 case TOK_MOD: Op = EXPR_MOD; break;
810 case TOK_AND: Op = EXPR_AND; break;
811 case TOK_XOR: Op = EXPR_XOR; break;
812 case TOK_SHL: Op = EXPR_SHL; break;
813 case TOK_SHR: Op = EXPR_SHR; break;
814 default: Internal ("Invalid token");
816 Root = NewExprNode (Op);
824 /* Return the expression tree we've created */
830 static ExprNode* SimpleExpr (void)
832 /* Read left hand side */
833 ExprNode* Root = Term ();
835 /* Handle additive operations */
836 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
838 long LVal, RVal, Val;
842 /* Remember the token and skip it */
846 /* Move root to left side and read the right side */
850 /* If both expressions are constant, we can evaluate the term */
851 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
854 case TOK_PLUS: Val = LVal + RVal; break;
855 case TOK_MINUS: Val = LVal - RVal; break;
856 case TOK_OR: Val = LVal | RVal; break;
857 default: Internal ("Invalid token");
860 /* Generate a literal expression and delete the old left and
865 Root = GenLiteralExpr (Val);
869 /* Generate an expression tree */
872 case TOK_PLUS: Op = EXPR_PLUS; break;
873 case TOK_MINUS: Op = EXPR_MINUS; break;
874 case TOK_OR: Op = EXPR_OR; break;
875 default: Internal ("Invalid token");
877 Root = NewExprNode (Op);
884 /* Return the expression tree we've created */
890 static ExprNode* BoolExpr (void)
891 /* Evaluate a boolean expression */
893 /* Read left hand side */
894 ExprNode* Root = SimpleExpr ();
896 /* Handle booleans */
897 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
898 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
900 long LVal, RVal, Val;
904 /* Remember the token and skip it */
908 /* Move root to left side and read the right side */
910 Right = SimpleExpr ();
912 /* If both expressions are constant, we can evaluate the term */
913 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
916 case TOK_EQ: Val = (LVal == RVal); break;
917 case TOK_NE: Val = (LVal != RVal); break;
918 case TOK_LT: Val = (LVal < RVal); break;
919 case TOK_GT: Val = (LVal > RVal); break;
920 case TOK_LE: Val = (LVal <= RVal); break;
921 case TOK_GE: Val = (LVal >= RVal); break;
922 default: Internal ("Invalid token");
925 /* Generate a literal expression and delete the old left and
930 Root = GenLiteralExpr (Val);
934 /* Generate an expression tree */
937 case TOK_EQ: Op = EXPR_EQ; break;
938 case TOK_NE: Op = EXPR_NE; break;
939 case TOK_LT: Op = EXPR_LT; break;
940 case TOK_GT: Op = EXPR_GT; break;
941 case TOK_LE: Op = EXPR_LE; break;
942 case TOK_GE: Op = EXPR_GE; break;
943 default: Internal ("Invalid token");
945 Root = NewExprNode (Op);
952 /* Return the expression tree we've created */
958 static ExprNode* Expr2 (void)
959 /* Boolean operators: AND and XOR */
961 /* Read left hand side */
962 ExprNode* Root = BoolExpr ();
964 /* Handle booleans */
965 while (Tok == TOK_BOOLAND || Tok == TOK_BOOLXOR) {
967 long LVal, RVal, Val;
971 /* Remember the token and skip it */
975 /* Move root to left side and read the right side */
979 /* If both expressions are constant, we can evaluate the term */
980 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
983 case TOK_BOOLAND: Val = ((LVal != 0) && (RVal != 0)); break;
984 case TOK_BOOLXOR: Val = ((LVal != 0) ^ (RVal != 0)); break;
985 default: Internal ("Invalid token");
988 /* Generate a literal expression and delete the old left and
993 Root = GenLiteralExpr (Val);
997 /* Generate an expression tree */
1000 case TOK_BOOLAND: Op = EXPR_BOOLAND; break;
1001 case TOK_BOOLXOR: Op = EXPR_BOOLXOR; break;
1002 default: Internal ("Invalid token");
1004 Root = NewExprNode (Op);
1006 Root->Right = Right;
1011 /* Return the expression tree we've created */
1017 static ExprNode* Expr1 (void)
1018 /* Boolean operators: OR */
1020 /* Read left hand side */
1021 ExprNode* Root = Expr2 ();
1023 /* Handle booleans */
1024 while (Tok == TOK_BOOLOR) {
1026 long LVal, RVal, Val;
1030 /* Remember the token and skip it */
1034 /* Move root to left side and read the right side */
1038 /* If both expressions are constant, we can evaluate the term */
1039 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1042 case TOK_BOOLOR: Val = ((LVal != 0) || (RVal != 0)); break;
1043 default: Internal ("Invalid token");
1046 /* Generate a literal expression and delete the old left and
1051 Root = GenLiteralExpr (Val);
1055 /* Generate an expression tree */
1058 case TOK_BOOLOR: Op = EXPR_BOOLOR; break;
1059 default: Internal ("Invalid token");
1061 Root = NewExprNode (Op);
1063 Root->Right = Right;
1068 /* Return the expression tree we've created */
1074 static ExprNode* Expr0 (void)
1075 /* Boolean operators: NOT */
1079 /* Handle booleans */
1080 if (Tok == TOK_BOOLNOT) {
1085 /* Skip the operator token */
1088 /* Read the argument */
1091 /* If the argument is const, evaluate it directly */
1092 if (IsEasyConst (Left, &Val)) {
1094 Root = GenLiteralExpr (!Val);
1096 Root = NewExprNode (EXPR_BOOLNOT);
1102 /* Read left hand side */
1107 /* Return the expression tree we've created */
1113 static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
1114 /* Study a binary expression subtree. Helper function for StudyExpr. */
1116 StudyExpr (Expr->Left, D, 1);
1117 if (ExprDescIsConst (D)) {
1120 StudyExpr (Expr->Right, D, 1);
1121 if (!ExprDescIsConst (D)) {
1131 static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign)
1132 /* Study an expression tree and place the contents into D */
1139 /* Initialize SD. This is not needed in all cases, but it's rather cheap
1140 * and simplifies the code below.
1144 /* Study this expression node */
1148 D->Val += (Sign * Expr->V.Val);
1153 if (SymIsImport (Sym)) {
1154 if (D->SymCount == 0) {
1155 D->SymCount += Sign;
1157 } else if (D->SymRef == Sym) {
1159 D->SymCount += Sign;
1161 /* More than one import */
1164 } else if (SymHasExpr (Sym)) {
1165 if (SymHasUserMark (Sym)) {
1166 if (Verbosity > 0) {
1167 DumpExpr (Expr, SymResolve);
1169 PError (GetSymPos (Sym),
1170 "Circular reference in definition of symbol `%s'",
1175 StudyExpr (GetSymExpr (Sym), D, Sign);
1176 SymUnmarkUser (Sym);
1184 Sec = Expr->V.SegNum;
1185 if (D->SecCount == 0) {
1186 D->SecCount += Sign;
1188 } else if (D->SecRef == Sec) {
1190 D->SecCount += Sign;
1192 /* More than one section */
1198 if (ULabCanResolve ()) {
1199 /* We can resolve the label */
1200 StudyExpr (ULabResolve (Expr->V.Val), D, Sign);
1207 StudyExpr (Expr->Left, D, Sign);
1208 StudyExpr (Expr->Right, D, Sign);
1212 StudyExpr (Expr->Left, D, Sign);
1213 StudyExpr (Expr->Right, D, -Sign);
1217 InitExprDesc (&SD1);
1218 StudyExpr (Expr->Left, &SD, 1);
1219 StudyExpr (Expr->Right, &SD1, 1);
1220 if (SD.TooComplex == 0 && SD1.TooComplex == 0) {
1221 /* First calculate SD = SD*SD1 if possible */
1222 if (ExprDescIsConst (&SD)) {
1223 /* Left is a constant */
1225 SD1.SymCount *= SD.Val;
1226 SD1.SecCount *= SD.Val;
1228 } else if (ExprDescIsConst (&SD1)) {
1229 /* Right is constant */
1231 SD.SymCount *= SD1.Val;
1232 SD.SecCount *= SD1.Val;
1236 /* Now calculate D * Sign * SD */
1237 if (!D->TooComplex) {
1238 if ((D->SymCount == 0 || SD.SymCount == 0 || D->SymRef == SD.SymRef) &&
1239 (D->SecCount == 0 || SD.SecCount == 0 || D->SecRef == SD.SecRef)) {
1240 D->Val += (Sign * SD.Val);
1241 if (D->SymCount == 0) {
1242 D->SymRef = SD.SymRef;
1244 D->SymCount += (Sign * SD.SymCount);
1245 if (D->SecCount == 0) {
1246 D->SecRef = SD.SecRef;
1248 D->SecCount += (Sign * SD.SecCount);
1259 StudyBinaryExpr (Expr, &SD);
1260 if (!SD.TooComplex) {
1262 Error ("Division by zero");
1265 D->Val += Sign * (SD.Left / SD.Val);
1273 StudyBinaryExpr (Expr, &SD);
1274 if (!SD.TooComplex) {
1276 Error ("Modulo operation with zero");
1279 D->Val += Sign * (SD.Left % SD.Val);
1287 StudyBinaryExpr (Expr, &SD);
1288 if (!SD.TooComplex) {
1289 D->Val += Sign * (SD.Left | SD.Val);
1296 StudyBinaryExpr (Expr, &SD);
1297 if (!SD.TooComplex) {
1298 D->Val += Sign * (SD.Left ^ SD.Val);
1305 StudyBinaryExpr (Expr, &SD);
1306 if (!SD.TooComplex) {
1307 D->Val += Sign * (SD.Left & SD.Val);
1314 StudyBinaryExpr (Expr, &SD);
1315 if (!SD.TooComplex) {
1316 D->Val += (Sign * shl_l (SD.Left, (unsigned) SD.Val));
1323 StudyBinaryExpr (Expr, &SD);
1324 if (!SD.TooComplex) {
1325 D->Val += (Sign * shr_l (SD.Left, (unsigned) SD.Val));
1332 StudyBinaryExpr (Expr, &SD);
1333 if (!SD.TooComplex) {
1334 D->Val += Sign * (SD.Left == SD.Val);
1341 StudyBinaryExpr (Expr, &SD);
1342 if (!SD.TooComplex) {
1343 D->Val += Sign * (SD.Left != SD.Val);
1350 StudyBinaryExpr (Expr, &SD);
1351 if (!SD.TooComplex) {
1352 D->Val += Sign * (SD.Left < SD.Val);
1359 StudyBinaryExpr (Expr, &SD);
1360 if (!SD.TooComplex) {
1361 D->Val += Sign * (SD.Left > SD.Val);
1368 StudyBinaryExpr (Expr, &SD);
1369 if (!SD.TooComplex) {
1370 D->Val += Sign * (SD.Left <= SD.Val);
1377 StudyBinaryExpr (Expr, &SD);
1378 if (!SD.TooComplex) {
1379 D->Val += Sign * (SD.Left >= SD.Val);
1386 StudyExpr (Expr->Left, &SD, 1);
1387 if (ExprDescIsConst (&SD)) {
1388 if (SD.Val != 0) { /* Shortcut op */
1390 StudyExpr (Expr->Right, &SD, 1);
1391 if (ExprDescIsConst (&SD)) {
1392 D->Val += Sign * (SD.Val != 0);
1403 StudyExpr (Expr->Left, &SD, 1);
1404 if (ExprDescIsConst (&SD)) {
1405 if (SD.Val == 0) { /* Shortcut op */
1406 StudyExpr (Expr->Right, &SD, 1);
1407 if (ExprDescIsConst (&SD)) {
1408 D->Val += Sign * (SD.Val != 0);
1421 StudyBinaryExpr (Expr, &SD);
1422 if (!SD.TooComplex) {
1423 D->Val += Sign * ((SD.Left != 0) ^ (SD.Val != 0));
1427 case EXPR_UNARY_MINUS:
1428 StudyExpr (Expr->Left, D, -Sign);
1432 StudyExpr (Expr->Left, &SD, 1);
1433 if (ExprDescIsConst (&SD)) {
1434 D->Val += (Sign * ~SD.Val);
1441 StudyExpr (Expr->Left, &SD, 1);
1442 if (ExprDescIsConst (&SD)) {
1443 D->Val += Sign * (((SD.Val >> 8) & 0x00FF) | ((SD.Val << 8) & 0xFF00));
1450 StudyExpr (Expr->Left, &SD, 1);
1451 if (ExprDescIsConst (&SD)) {
1452 D->Val += Sign * (SD.Val != 0);
1458 case EXPR_FORCEWORD:
1461 StudyExpr (Expr->Left, D, Sign);
1465 StudyExpr (Expr->Left, &SD, 1);
1466 if (ExprDescIsConst (&SD)) {
1467 D->Val += Sign * (SD.Val & 0xFF);
1474 StudyExpr (Expr->Left, &SD, 1);
1475 if (ExprDescIsConst (&SD)) {
1476 D->Val += Sign * ((SD.Val >> 8) & 0xFF);
1483 StudyExpr (Expr->Left, &SD, 1);
1484 if (ExprDescIsConst (&SD)) {
1485 D->Val += Sign * ((SD.Val >> 16) & 0xFF);
1492 StudyExpr (Expr->Left, &SD, 1);
1493 if (ExprDescIsConst (&SD)) {
1494 D->Val += Sign * ((SD.Val >> 24) & 0xFF);
1501 StudyExpr (Expr->Left, &SD, 1);
1502 if (ExprDescIsConst (&SD)) {
1503 D->Val += Sign * (SD.Val & 0xFFFF);
1510 StudyExpr (Expr->Left, &SD, 1);
1511 if (ExprDescIsConst (&SD)) {
1512 D->Val += Sign * ((SD.Val >> 16) & 0xFFFF);
1519 Internal ("Unknown Op type: %u", Expr->Op);
1526 static ExprNode* SimplifyExpr (ExprNode* Expr)
1527 /* Try to simplify the given expression tree */
1529 if (Expr && Expr->Op != EXPR_LITERAL) {
1531 /* Create an expression description and initialize it */
1535 /* Study the expression */
1536 StudyExpr (Expr, &D, 1);
1538 /* Now check if we can generate a literal value */
1539 if (ExprDescIsConst (&D)) {
1540 /* No external references */
1542 Expr = GenLiteralExpr (D.Val);
1550 ExprNode* Expression (void)
1551 /* Evaluate an expression, build the expression tree on the heap and return
1552 * a pointer to the root of the tree.
1556 return SimplifyExpr (Expr0 ());
1559 ExprNode* Expr = Expr0 ();
1560 printf ("Before: "); DumpExpr (Expr, SymResolve);
1561 Expr = SimplifyExpr (Expr);
1562 printf ("After: "); DumpExpr (Expr, SymResolve);
1569 long ConstExpression (void)
1570 /* Parse an expression. Check if the expression is const, and print an error
1571 * message if not. Return the value of the expression, or a dummy, if it is
1576 /* Read the expression */
1577 ExprNode* Expr = Expr0 ();
1580 ExprNode* Expr = Expression ();
1583 /* Study the expression */
1586 StudyExpr (Expr, &D, 1);
1588 /* Check if the expression is constant */
1589 if (!ExprDescIsConst (&D)) {
1590 Error ("Constant expression expected");
1594 /* Free the expression tree and return the value */
1601 void FreeExpr (ExprNode* Root)
1602 /* Free the expression, Root is pointing to. */
1605 FreeExpr (Root->Left);
1606 FreeExpr (Root->Right);
1607 FreeExprNode (Root);
1613 ExprNode* GenLiteralExpr (long Val)
1614 /* Return an expression tree that encodes the given literal value */
1616 ExprNode* Expr = NewExprNode (EXPR_LITERAL);
1623 ExprNode* GenSymExpr (SymEntry* Sym)
1624 /* Return an expression node that encodes the given symbol */
1626 ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
1628 SymAddExprRef (Sym, Expr);
1634 static ExprNode* GenSectionExpr (unsigned SegNum)
1635 /* Return an expression node for the given section */
1637 ExprNode* Expr = NewExprNode (EXPR_SECTION);
1638 Expr->V.SegNum = SegNum;
1644 ExprNode* GenCurrentPC (void)
1645 /* Return the current program counter as expression */
1650 /* Create SegmentBase + Offset */
1651 Root = NewExprNode (EXPR_PLUS);
1652 Root->Left = GenSectionExpr (GetCurrentSegNum ());
1653 Root->Right = GenLiteralExpr (GetPC ());
1655 /* Absolute mode, just return PC value */
1656 Root = GenLiteralExpr (GetPC ());
1664 ExprNode* GenSwapExpr (ExprNode* Expr)
1665 /* Return an extended expression with lo and hi bytes swapped */
1667 ExprNode* N = NewExprNode (EXPR_SWAP);
1674 ExprNode* GenBranchExpr (unsigned Offs)
1675 /* Return an expression that encodes the difference between current PC plus
1676 * offset and the target expression (that is, Expression() - (*+Offs) ).
1683 /* Read Expression() */
1686 /* If the expression is a cheap constant, generate a simpler tree */
1687 if (IsEasyConst (N, &Val)) {
1689 /* Free the constant expression tree */
1692 /* Generate the final expression:
1694 * Val - ((Seg + PC) + Offs)
1695 * Val - Seg - PC - Offs
1696 * (Val - PC - Offs) - Seg
1698 Root = GenLiteralExpr (Val - GetPC () - Offs);
1701 Root = NewExprNode (EXPR_MINUS);
1703 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1708 /* Generate the expression:
1710 * N - ((Seg + PC) + Offs)
1711 * N - Seg - PC - Offs
1712 * N - (PC + Offs) - Seg
1714 Root = NewExprNode (EXPR_MINUS);
1716 Root->Right = GenLiteralExpr (GetPC () + Offs);
1719 Root = NewExprNode (EXPR_MINUS);
1721 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1725 /* Return the result */
1731 ExprNode* GenULabelExpr (unsigned Num)
1732 /* Return an expression for an unnamed label with the given index */
1734 ExprNode* Node = NewExprNode (EXPR_ULABEL);
1737 /* Return the new node */
1743 ExprNode* GenByteExpr (ExprNode* Expr)
1744 /* Force the given expression into a byte and return the result */
1746 /* Use the low byte operator to force the expression into byte size */
1747 ExprNode* Root = NewExprNode (EXPR_BYTE0);
1750 /* Return the result */
1756 ExprNode* GenWordExpr (ExprNode* Expr)
1757 /* Force the given expression into a word and return the result. */
1759 /* AND the expression by $FFFF to force it into word size */
1760 ExprNode* Root = NewExprNode (EXPR_AND);
1762 Root->Right = GenLiteralExpr (0xFFFF);
1764 /* Return the result */
1770 ExprNode* GenNE (ExprNode* Expr, long Val)
1771 /* Generate an expression that compares Expr and Val for inequality */
1773 /* Generate a compare node */
1774 ExprNode* Root = NewExprNode (EXPR_NE);
1776 Root->Right = GenLiteralExpr (Val);
1778 /* Return the result */
1784 int IsConstExpr (ExprNode* Expr, long* Val)
1785 /* Return true if the given expression is a constant expression, that is, one
1786 * with no references to external symbols. If Val is not NULL and the
1787 * expression is constant, the constant value is stored here.
1790 /* Study the expression */
1793 StudyExpr (Expr, &D, 1);
1795 /* Check if the expression is constant */
1796 if (ExprDescIsConst (&D)) {
1808 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1809 /* Internal routine that is recursively called to check if there is a zeropage
1810 * symbol in the expression tree.
1814 switch (N->Op & EXPR_TYPEMASK) {
1820 if (SymIsZP (N->V.Sym)) {
1822 } else if (SymHasExpr (N->V.Sym)) {
1823 /* Check if this expression is a byte expression */
1824 CheckByteExpr (GetSymExpr (N->V.Sym), IsByte);
1829 if (GetSegAddrSize (N->V.SegNum) == ADDR_SIZE_ZP) {
1837 case EXPR_UNARYNODE:
1838 CheckByteExpr (N->Left, IsByte);
1841 case EXPR_BINARYNODE:
1842 CheckByteExpr (N->Left, IsByte);
1843 CheckByteExpr (N->Right, IsByte);
1847 Internal ("Unknown expression op: %02X", N->Op);
1854 int IsByteExpr (ExprNode* Root)
1855 /* Return true if this is a byte expression */
1860 if (IsConstExpr (Root, &Val)) {
1861 IsByte = IsByteRange (Val);
1862 } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
1863 Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
1864 /* Symbol forced to have byte range */
1867 /* We have undefined symbols in the expression. Assume that the
1868 * expression is a byte expression if there is at least one symbol
1869 * declared as zeropage in it. Being wrong here is not a very big
1870 * problem since the linker knows about all symbols and detects
1871 * error like mixing absolute and zeropage labels.
1874 CheckByteExpr (Root, &IsByte);
1881 ExprNode* CloneExpr (ExprNode* Expr)
1882 /* Clone the given expression tree. The function will simply clone symbol
1883 * nodes, it will not resolve them.
1888 /* Accept NULL pointers */
1893 /* Clone the node */
1897 Clone = GenLiteralExpr (Expr->V.Val);
1901 Clone = GenULabelExpr (Expr->V.Val);
1905 Clone = GenSymExpr (Expr->V.Sym);
1909 Clone = GenSectionExpr (Expr->V.SegNum);
1913 /* Generate a new node */
1914 Clone = NewExprNode (Expr->Op);
1915 /* Clone the tree nodes */
1916 Clone->Left = CloneExpr (Expr->Left);
1917 Clone->Right = CloneExpr (Expr->Right);
1927 void WriteExpr (ExprNode* Expr)
1928 /* Write the given expression to the object file */
1930 /* Null expressions are encoded by a type byte of zero */
1932 ObjWrite8 (EXPR_NULL);
1936 /* If the is a leafnode, write the expression attribute, otherwise
1937 * write the expression operands.
1942 ObjWrite8 (EXPR_LITERAL);
1943 ObjWrite32 (Expr->V.Val);
1947 if (SymIsImport (Expr->V.Sym)) {
1948 ObjWrite8 (EXPR_SYMBOL);
1949 ObjWriteVar (GetSymIndex (Expr->V.Sym));
1951 WriteExpr (GetSymExpr (Expr->V.Sym));
1956 ObjWrite8 (EXPR_SECTION);
1957 ObjWrite8 (Expr->V.SegNum);
1961 WriteExpr (ULabResolve (Expr->V.Val));
1965 /* Not a leaf node */
1966 ObjWrite8 (Expr->Op);
1967 WriteExpr (Expr->Left);
1968 WriteExpr (Expr->Right);