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 /*****************************************************************************/
59 #include "studyexpr.h"
67 /*****************************************************************************/
69 /*****************************************************************************/
73 /* Since all expressions are first packed into expression trees, and each
74 * expression tree node is allocated on the heap, we add some type of special
75 * purpose memory allocation here: Instead of freeing the nodes, we save some
76 * number of freed nodes for later and remember them in a single linked list
77 * using the Left link.
79 #define MAX_FREE_NODES 64
80 static ExprNode* FreeExprNodes = 0;
81 static unsigned FreeNodeCount = 0;
85 /*****************************************************************************/
87 /*****************************************************************************/
91 static ExprNode* NewExprNode (unsigned Op)
92 /* Create a new expression node */
96 /* Do we have some nodes in the list already? */
98 /* Use first node from list */
100 FreeExprNodes = N->Left;
102 /* Allocate fresh memory */
103 N = xmalloc (sizeof (ExprNode));
106 N->Left = N->Right = 0;
114 static void FreeExprNode (ExprNode* E)
118 if (E->Op == EXPR_SYMBOL) {
119 /* Remove the symbol reference */
120 SymDelExprRef (E->V.Sym, E);
122 /* Place the symbol into the free nodes list if possible */
123 if (FreeNodeCount < MAX_FREE_NODES) {
124 /* Remember this node for later */
125 E->Left = FreeExprNodes;
128 /* Free the memory */
136 /*****************************************************************************/
138 /*****************************************************************************/
142 static ExprNode* Expr0 (void);
146 int IsByteRange (long Val)
147 /* Return true if this is a byte value */
149 return (Val & ~0xFFL) == 0;
154 int IsWordRange (long Val)
155 /* Return true if this is a word value */
157 return (Val & ~0xFFFFL) == 0;
162 int IsFarRange (long Val)
163 /* Return true if this is a far (24 bit) value */
165 return (Val & ~0xFFFFFFL) == 0;
170 static int IsEasyConst (const ExprNode* E, long* Val)
171 /* Do some light checking if the given node is a constant. Don't care if E is
172 * a complex expression. If E is a constant, return true and place its value
173 * into Val, provided that Val is not NULL.
176 /* Resolve symbols, follow symbol chains */
177 while (E->Op == EXPR_SYMBOL) {
178 E = SymResolve (E->V.Sym);
180 /* Could not resolve */
185 /* Symbols resolved, check for a literal */
186 if (E->Op == EXPR_LITERAL) {
193 /* Not found to be a const according to our tests */
199 static ExprNode* LoByte (ExprNode* Operand)
200 /* Return the low byte of the given expression */
205 /* Special handling for const expressions */
206 if (IsEasyConst (Operand, &Val)) {
208 Expr = GenLiteralExpr (Val & 0xFF);
210 /* Extract byte #0 */
211 Expr = NewExprNode (EXPR_BYTE0);
212 Expr->Left = Operand;
219 static ExprNode* HiByte (ExprNode* Operand)
220 /* Return the high byte of the given expression */
225 /* Special handling for const expressions */
226 if (IsEasyConst (Operand, &Val)) {
228 Expr = GenLiteralExpr ((Val >> 8) & 0xFF);
230 /* Extract byte #1 */
231 Expr = NewExprNode (EXPR_BYTE1);
232 Expr->Left = Operand;
239 static ExprNode* BankByte (ExprNode* Operand)
240 /* Return the bank byte of the given expression */
245 /* Special handling for const expressions */
246 if (IsEasyConst (Operand, &Val)) {
248 Expr = GenLiteralExpr ((Val >> 16) & 0xFF);
250 /* Extract byte #2 */
251 Expr = NewExprNode (EXPR_BYTE2);
252 Expr->Left = Operand;
259 static ExprNode* LoWord (ExprNode* Operand)
260 /* Return the low word of the given expression */
265 /* Special handling for const expressions */
266 if (IsEasyConst (Operand, &Val)) {
268 Expr = GenLiteralExpr (Val & 0xFFFF);
270 /* Extract word #0 */
271 Expr = NewExprNode (EXPR_WORD0);
272 Expr->Left = Operand;
279 static ExprNode* HiWord (ExprNode* Operand)
280 /* Return the high word of the given expression */
285 /* Special handling for const expressions */
286 if (IsEasyConst (Operand, &Val)) {
288 Expr = GenLiteralExpr ((Val >> 16) & 0xFFFF);
290 /* Extract word #1 */
291 Expr = NewExprNode (EXPR_WORD1);
292 Expr->Left = Operand;
299 static ExprNode* Symbol (SymEntry* S)
300 /* Reference a symbol and return an expression for it */
303 /* Some weird error happened before */
304 return GenLiteralExpr (0);
306 /* Mark the symbol as referenced */
308 /* Create symbol node */
309 return GenSymExpr (S);
315 static ExprNode* FuncBankByte (void)
316 /* Handle the .BANKBYTE builtin function */
318 return BankByte (Expression ());
323 static ExprNode* FuncBlank (void)
324 /* Handle the .BLANK builtin function */
328 /* Assume no tokens if the closing brace follows (this is not correct in
329 * all cases, since the token may be the closing brace, but this will
330 * give a syntax error anyway and may not be handled by .BLANK.
332 if (Tok != TOK_RPAREN) {
333 /* Skip any tokens */
335 while (!TokIsSep (Tok)) {
336 if (Tok == TOK_LPAREN) {
338 } else if (Tok == TOK_RPAREN) {
350 return GenLiteralExpr (Result);
355 static ExprNode* FuncConst (void)
356 /* Handle the .CONST builtin function */
358 /* Read an expression */
359 ExprNode* Expr = Expression ();
361 /* Check the constness of the expression */
362 ExprNode* Result = GenLiteralExpr (IsConstExpr (Expr, 0));
364 /* Free the expression */
373 static ExprNode* FuncDefined (void)
374 /* Handle the .DEFINED builtin function */
376 /* Parse the symbol name and search for the symbol */
377 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
379 /* Check if the symbol is defined */
380 return GenLiteralExpr (Sym != 0 && SymIsDef (Sym));
385 static ExprNode* FuncHiByte (void)
386 /* Handle the .HIBYTE builtin function */
388 return HiByte (Expression ());
393 static ExprNode* FuncHiWord (void)
394 /* Handle the .HIWORD builtin function */
396 return HiWord (Expression ());
401 static ExprNode* FuncLoByte (void)
402 /* Handle the .LOBYTE builtin function */
404 return LoByte (Expression ());
409 static ExprNode* FuncLoWord (void)
410 /* Handle the .LOWORD builtin function */
412 return LoWord (Expression ());
417 static ExprNode* DoMatch (enum TC EqualityLevel)
418 /* Handle the .MATCH and .XMATCH builtin functions */
425 /* A list of tokens follows. Read this list and remember it building a
426 * single linked list of tokens including attributes. The list is
427 * terminated by a comma.
429 while (Tok != TOK_COMMA) {
431 /* We may not end-of-line of end-of-file here */
432 if (TokIsSep (Tok)) {
433 Error ("Unexpected end of line");
434 return GenLiteralExpr (0);
437 /* Get a node with this token */
438 Node = NewTokNode ();
440 /* Insert the node into the list */
455 /* Read the second list which is terminated by the right parenthesis and
456 * compare each token against the one in the first list.
460 while (Tok != TOK_RPAREN) {
462 /* We may not end-of-line of end-of-file here */
463 if (TokIsSep (Tok)) {
464 Error ("Unexpected end of line");
465 return GenLiteralExpr (0);
468 /* Compare the tokens if the result is not already known */
471 /* The second list is larger than the first one */
473 } else if (TokCmp (Node) < EqualityLevel) {
474 /* Tokens do not match */
479 /* Next token in first list */
484 /* Next token in current list */
488 /* Check if there are remaining tokens in the first list */
493 /* Free the token list */
500 /* Done, return the result */
501 return GenLiteralExpr (Result);
506 static ExprNode* FuncMatch (void)
507 /* Handle the .MATCH function */
509 return DoMatch (tcSameToken);
514 static ExprNode* FuncReferenced (void)
515 /* Handle the .REFERENCED builtin function */
517 /* Parse the symbol name and search for the symbol */
518 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
520 /* Check if the symbol is referenced */
521 return GenLiteralExpr (Sym != 0 && SymIsRef (Sym));
526 static ExprNode* FuncSizeOf (void)
527 /* Handle the .SIZEOF function */
529 StrBuf ScopeName = AUTO_STRBUF_INITIALIZER;
530 char Name[sizeof (SVal)];
538 /* Assume an error */
541 /* Check for a cheap local which needs special handling */
542 if (Tok == TOK_LOCAL_IDENT) {
544 /* Cheap local symbol */
545 Sym = SymFindLocal (SymLast, SVal, SYM_FIND_EXISTING);
547 Error ("Unknown symbol or scope: `%s'", SVal);
549 SizeSym = GetSizeOfSymbol (Sym);
552 /* Remember and skip SVal, terminate ScopeName so it is empty */
555 SB_Terminate (&ScopeName);
559 /* Parse the scope and the name */
560 SymTable* ParentScope = ParseScopedIdent (Name, &ScopeName);
562 /* Check if the parent scope is valid */
563 if (ParentScope == 0) {
565 DoneStrBuf (&ScopeName);
566 return GenLiteralExpr (0);
569 /* If ScopeName is empty, no explicit scope was specified. We have to
570 * search upper scope levels in this case.
572 NoScope = SB_IsEmpty (&ScopeName);
574 /* First search for a scope with the given name */
576 Scope = SymFindAnyScope (ParentScope, Name);
578 Scope = SymFindScope (ParentScope, Name, SYM_FIND_EXISTING);
581 /* If we did find a scope with the name, read the symbol defining the
582 * size, otherwise search for a symbol entry with the name and scope.
585 /* Yep, it's a scope */
586 SizeSym = GetSizeOfScope (Scope);
589 Sym = SymFindAny (ParentScope, Name);
591 Sym = SymFind (ParentScope, Name, SYM_FIND_EXISTING);
594 /* If we found the symbol retrieve the size, otherwise complain */
596 SizeSym = GetSizeOfSymbol (Sym);
598 Error ("Unknown symbol or scope: `%s%s'",
599 SB_GetConstBuf (&ScopeName), Name);
604 /* Check if we have a size */
605 if (SizeSym == 0 || !SymIsConst (SizeSym, &Size)) {
606 Error ("Size of `%s%s' is unknown", SB_GetConstBuf (&ScopeName), Name);
610 /* Free the scope name */
611 DoneStrBuf (&ScopeName);
613 /* Return the size */
614 return GenLiteralExpr (Size);
619 static ExprNode* FuncStrAt (void)
620 /* Handle the .STRAT function */
622 char Str [sizeof(SVal)];
626 /* String constant expected */
627 if (Tok != TOK_STRCON) {
628 Error ("String constant expected");
634 /* Remember the string and skip it */
638 /* Comma must follow */
641 /* Expression expected */
642 Index = ConstExpression ();
644 /* Must be a valid index */
645 if (Index >= (long) strlen (Str)) {
646 Error ("Range error");
647 return GenLiteralExpr (0);
650 /* Get the char, handle as unsigned. Be sure to translate it into
651 * the target character set.
653 C = TgtTranslateChar (Str [(size_t)Index]);
655 /* Return the char expression */
656 return GenLiteralExpr (C);
661 static ExprNode* FuncStrLen (void)
662 /* Handle the .STRLEN function */
666 /* String constant expected */
667 if (Tok != TOK_STRCON) {
669 Error ("String constant expected");
670 /* Smart error recovery */
671 if (Tok != TOK_RPAREN) {
678 /* Get the length of the string */
681 /* Skip the string */
685 /* Return the length */
686 return GenLiteralExpr (Len);
691 static ExprNode* FuncTCount (void)
692 /* Handle the .TCOUNT function */
694 /* We have a list of tokens that ends with the closing paren. Skip
695 * the tokens, handling nested braces and count them.
699 while (Parens != 0 || Tok != TOK_RPAREN) {
701 /* Check for end of line or end of input. Since the calling function
702 * will check for the closing paren, we don't need to print an error
703 * here, just bail out.
705 if (TokIsSep (Tok)) {
712 /* Keep track of the nesting level */
714 case TOK_LPAREN: ++Parens; break;
715 case TOK_RPAREN: --Parens; break;
723 /* Return the number of tokens */
724 return GenLiteralExpr (Count);
729 static ExprNode* FuncXMatch (void)
730 /* Handle the .XMATCH function */
732 return DoMatch (tcIdentical);
737 static ExprNode* Function (ExprNode* (*F) (void))
738 /* Handle builtin functions */
742 /* Skip the keyword */
745 /* Expression must be enclosed in braces */
746 if (Tok != TOK_LPAREN) {
747 Error ("'(' expected");
749 return GenLiteralExpr (0);
753 /* Call the function itself */
756 /* Closing brace must follow */
759 /* Return the result of the actual function */
765 static ExprNode* Factor (void)
774 N = GenLiteralExpr (IVal);
779 N = GenLiteralExpr (TgtTranslateChar (IVal));
785 N = Symbol (ParseScopedSymName (SYM_ALLOC_NEW));
788 case TOK_LOCAL_IDENT:
789 N = Symbol (SymFindLocal (SymLast, SVal, SYM_ALLOC_NEW));
801 if (IsEasyConst (L, &Val)) {
803 N = GenLiteralExpr (-Val);
805 N = NewExprNode (EXPR_UNARY_MINUS);
813 if (IsEasyConst (L, &Val)) {
815 N = GenLiteralExpr (~Val);
817 N = NewExprNode (EXPR_NOT);
830 N = LoByte (Factor ());
835 N = HiByte (Factor ());
840 N = BankByte (Factor ());
850 N = Function (FuncBankByte);
854 N = Function (FuncBlank);
858 N = Function (FuncConst);
862 N = GenLiteralExpr (CPUIsets[CPU]);
867 N = Function (FuncDefined);
871 N = Function (FuncHiByte);
875 N = Function (FuncHiWord);
879 N = Function (FuncLoByte);
883 N = Function (FuncLoWord);
887 N = Function (FuncMatch);
891 N = Function (FuncReferenced);
895 N = Function (FuncSizeOf);
899 N = Function (FuncStrAt);
903 N = Function (FuncStrLen);
907 N = Function (FuncTCount);
911 N = GenLiteralExpr (time (0));
916 N = GenLiteralExpr (VERSION);
921 N = Function (FuncXMatch);
925 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
926 /* A character constant */
927 N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
929 N = GenLiteralExpr (0); /* Dummy */
930 Error ("Syntax error");
940 static ExprNode* Term (void)
942 /* Read left hand side */
943 ExprNode* Root = Factor ();
945 /* Handle multiplicative operations */
946 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
947 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
950 long LVal, RVal, Val;
954 /* Remember the token and skip it */
958 /* Move root to left side and read the right side */
962 /* If both expressions are constant, we can evaluate the term */
963 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
972 Error ("Division by zero");
981 Error ("Modulo operation with zero");
997 Val = shl_l (LVal, RVal);
1001 Val = shr_l (LVal, RVal);
1005 Internal ("Invalid token");
1008 /* Generate a literal expression and delete the old left and
1013 Root = GenLiteralExpr (Val);
1017 /* Generate an expression tree */
1020 case TOK_MUL: Op = EXPR_MUL; break;
1021 case TOK_DIV: Op = EXPR_DIV; break;
1022 case TOK_MOD: Op = EXPR_MOD; break;
1023 case TOK_AND: Op = EXPR_AND; break;
1024 case TOK_XOR: Op = EXPR_XOR; break;
1025 case TOK_SHL: Op = EXPR_SHL; break;
1026 case TOK_SHR: Op = EXPR_SHR; break;
1027 default: Internal ("Invalid token");
1029 Root = NewExprNode (Op);
1031 Root->Right = Right;
1037 /* Return the expression tree we've created */
1043 static ExprNode* SimpleExpr (void)
1045 /* Read left hand side */
1046 ExprNode* Root = Term ();
1048 /* Handle additive operations */
1049 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
1051 long LVal, RVal, Val;
1055 /* Remember the token and skip it */
1059 /* Move root to left side and read the right side */
1063 /* If both expressions are constant, we can evaluate the term */
1064 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1067 case TOK_PLUS: Val = LVal + RVal; break;
1068 case TOK_MINUS: Val = LVal - RVal; break;
1069 case TOK_OR: Val = LVal | RVal; break;
1070 default: Internal ("Invalid token");
1073 /* Generate a literal expression and delete the old left and
1078 Root = GenLiteralExpr (Val);
1082 /* Generate an expression tree */
1085 case TOK_PLUS: Op = EXPR_PLUS; break;
1086 case TOK_MINUS: Op = EXPR_MINUS; break;
1087 case TOK_OR: Op = EXPR_OR; break;
1088 default: Internal ("Invalid token");
1090 Root = NewExprNode (Op);
1092 Root->Right = Right;
1097 /* Return the expression tree we've created */
1103 static ExprNode* BoolExpr (void)
1104 /* Evaluate a boolean expression */
1106 /* Read left hand side */
1107 ExprNode* Root = SimpleExpr ();
1109 /* Handle booleans */
1110 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
1111 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
1113 long LVal, RVal, Val;
1117 /* Remember the token and skip it */
1121 /* Move root to left side and read the right side */
1123 Right = SimpleExpr ();
1125 /* If both expressions are constant, we can evaluate the term */
1126 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1129 case TOK_EQ: Val = (LVal == RVal); break;
1130 case TOK_NE: Val = (LVal != RVal); break;
1131 case TOK_LT: Val = (LVal < RVal); break;
1132 case TOK_GT: Val = (LVal > RVal); break;
1133 case TOK_LE: Val = (LVal <= RVal); break;
1134 case TOK_GE: Val = (LVal >= RVal); break;
1135 default: Internal ("Invalid token");
1138 /* Generate a literal expression and delete the old left and
1143 Root = GenLiteralExpr (Val);
1147 /* Generate an expression tree */
1150 case TOK_EQ: Op = EXPR_EQ; break;
1151 case TOK_NE: Op = EXPR_NE; break;
1152 case TOK_LT: Op = EXPR_LT; break;
1153 case TOK_GT: Op = EXPR_GT; break;
1154 case TOK_LE: Op = EXPR_LE; break;
1155 case TOK_GE: Op = EXPR_GE; break;
1156 default: Internal ("Invalid token");
1158 Root = NewExprNode (Op);
1160 Root->Right = Right;
1165 /* Return the expression tree we've created */
1171 static ExprNode* Expr2 (void)
1172 /* Boolean operators: AND and XOR */
1174 /* Read left hand side */
1175 ExprNode* Root = BoolExpr ();
1177 /* Handle booleans */
1178 while (Tok == TOK_BOOLAND || Tok == TOK_BOOLXOR) {
1180 long LVal, RVal, Val;
1184 /* Remember the token and skip it */
1188 /* Move root to left side and read the right side */
1190 Right = BoolExpr ();
1192 /* If both expressions are constant, we can evaluate the term */
1193 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1196 case TOK_BOOLAND: Val = ((LVal != 0) && (RVal != 0)); break;
1197 case TOK_BOOLXOR: Val = ((LVal != 0) ^ (RVal != 0)); break;
1198 default: Internal ("Invalid token");
1201 /* Generate a literal expression and delete the old left and
1206 Root = GenLiteralExpr (Val);
1210 /* Generate an expression tree */
1213 case TOK_BOOLAND: Op = EXPR_BOOLAND; break;
1214 case TOK_BOOLXOR: Op = EXPR_BOOLXOR; break;
1215 default: Internal ("Invalid token");
1217 Root = NewExprNode (Op);
1219 Root->Right = Right;
1224 /* Return the expression tree we've created */
1230 static ExprNode* Expr1 (void)
1231 /* Boolean operators: OR */
1233 /* Read left hand side */
1234 ExprNode* Root = Expr2 ();
1236 /* Handle booleans */
1237 while (Tok == TOK_BOOLOR) {
1239 long LVal, RVal, Val;
1243 /* Remember the token and skip it */
1247 /* Move root to left side and read the right side */
1251 /* If both expressions are constant, we can evaluate the term */
1252 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1255 case TOK_BOOLOR: Val = ((LVal != 0) || (RVal != 0)); break;
1256 default: Internal ("Invalid token");
1259 /* Generate a literal expression and delete the old left and
1264 Root = GenLiteralExpr (Val);
1268 /* Generate an expression tree */
1271 case TOK_BOOLOR: Op = EXPR_BOOLOR; break;
1272 default: Internal ("Invalid token");
1274 Root = NewExprNode (Op);
1276 Root->Right = Right;
1281 /* Return the expression tree we've created */
1287 static ExprNode* Expr0 (void)
1288 /* Boolean operators: NOT */
1292 /* Handle booleans */
1293 if (Tok == TOK_BOOLNOT) {
1298 /* Skip the operator token */
1301 /* Read the argument */
1304 /* If the argument is const, evaluate it directly */
1305 if (IsEasyConst (Left, &Val)) {
1307 Root = GenLiteralExpr (!Val);
1309 Root = NewExprNode (EXPR_BOOLNOT);
1315 /* Read left hand side */
1320 /* Return the expression tree we've created */
1326 ExprNode* Expression (void)
1327 /* Evaluate an expression, build the expression tree on the heap and return
1328 * a pointer to the root of the tree.
1336 long ConstExpression (void)
1337 /* Parse an expression. Check if the expression is const, and print an error
1338 * message if not. Return the value of the expression, or a dummy, if it is
1344 /* Read the expression */
1345 ExprNode* Expr = Expression ();
1347 /* Study the expression */
1350 StudyExpr (Expr, &D);
1352 /* Check if the expression is constant */
1353 if (ED_IsConst (&D)) {
1356 Error ("Constant expression expected");
1360 /* Free the expression tree and allocated memory for D */
1364 /* Return the value */
1370 void FreeExpr (ExprNode* Root)
1371 /* Free the expression, Root is pointing to. */
1374 FreeExpr (Root->Left);
1375 FreeExpr (Root->Right);
1376 FreeExprNode (Root);
1382 ExprNode* SimplifyExpr (ExprNode* Expr, const ExprDesc* D)
1383 /* Try to simplify the given expression tree */
1385 if (Expr->Op != EXPR_LITERAL && ED_IsConst (D)) {
1386 /* No external references */
1388 Expr = GenLiteralExpr (D->Val);
1395 ExprNode* GenLiteralExpr (long Val)
1396 /* Return an expression tree that encodes the given literal value */
1398 ExprNode* Expr = NewExprNode (EXPR_LITERAL);
1405 ExprNode* GenSymExpr (SymEntry* Sym)
1406 /* Return an expression node that encodes the given symbol */
1408 ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
1410 SymAddExprRef (Sym, Expr);
1416 static ExprNode* GenSectionExpr (unsigned SegNum)
1417 /* Return an expression node for the given section */
1419 ExprNode* Expr = NewExprNode (EXPR_SECTION);
1420 Expr->V.SegNum = SegNum;
1426 ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right)
1427 /* Generate an addition from the two operands */
1430 if (IsEasyConst (Left, &Val) && Val == 0) {
1433 } else if (IsEasyConst (Right, &Val) && Val == 0) {
1437 ExprNode* Root = NewExprNode (EXPR_PLUS);
1439 Root->Right = Right;
1446 ExprNode* GenCurrentPC (void)
1447 /* Return the current program counter as expression */
1452 /* Create SegmentBase + Offset */
1453 Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
1454 GenLiteralExpr (GetPC ()));
1456 /* Absolute mode, just return PC value */
1457 Root = GenLiteralExpr (GetPC ());
1465 ExprNode* GenSwapExpr (ExprNode* Expr)
1466 /* Return an extended expression with lo and hi bytes swapped */
1468 ExprNode* N = NewExprNode (EXPR_SWAP);
1475 ExprNode* GenBranchExpr (unsigned Offs)
1476 /* Return an expression that encodes the difference between current PC plus
1477 * offset and the target expression (that is, Expression() - (*+Offs) ).
1484 /* Read Expression() */
1487 /* If the expression is a cheap constant, generate a simpler tree */
1488 if (IsEasyConst (N, &Val)) {
1490 /* Free the constant expression tree */
1493 /* Generate the final expression:
1495 * Val - ((Seg + PC) + Offs)
1496 * Val - Seg - PC - Offs
1497 * (Val - PC - Offs) - Seg
1499 Root = GenLiteralExpr (Val - GetPC () - Offs);
1502 Root = NewExprNode (EXPR_MINUS);
1504 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1509 /* Generate the expression:
1511 * N - ((Seg + PC) + Offs)
1512 * N - Seg - PC - Offs
1513 * N - (PC + Offs) - Seg
1515 Root = NewExprNode (EXPR_MINUS);
1517 Root->Right = GenLiteralExpr (GetPC () + Offs);
1520 Root = NewExprNode (EXPR_MINUS);
1522 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1526 /* Return the result */
1532 ExprNode* GenULabelExpr (unsigned Num)
1533 /* Return an expression for an unnamed label with the given index */
1535 ExprNode* Node = NewExprNode (EXPR_ULABEL);
1538 /* Return the new node */
1544 ExprNode* GenByteExpr (ExprNode* Expr)
1545 /* Force the given expression into a byte and return the result */
1547 /* Use the low byte operator to force the expression into byte size */
1548 return LoByte (Expr);
1553 ExprNode* GenWordExpr (ExprNode* Expr)
1554 /* Force the given expression into a word and return the result. */
1556 /* Use the low byte operator to force the expression into word size */
1557 return LoWord (Expr);
1562 ExprNode* GenNE (ExprNode* Expr, long Val)
1563 /* Generate an expression that compares Expr and Val for inequality */
1565 /* Generate a compare node */
1566 ExprNode* Root = NewExprNode (EXPR_NE);
1568 Root->Right = GenLiteralExpr (Val);
1570 /* Return the result */
1576 int IsConstExpr (ExprNode* Expr, long* Val)
1577 /* Return true if the given expression is a constant expression, that is, one
1578 * with no references to external symbols. If Val is not NULL and the
1579 * expression is constant, the constant value is stored here.
1584 /* Study the expression */
1587 StudyExpr (Expr, &D);
1589 /* Check if the expression is constant */
1590 IsConst = ED_IsConst (&D);
1591 if (IsConst && Val != 0) {
1595 /* Delete allocated memory and return the result */
1602 ExprNode* CloneExpr (ExprNode* Expr)
1603 /* Clone the given expression tree. The function will simply clone symbol
1604 * nodes, it will not resolve them.
1609 /* Accept NULL pointers */
1614 /* Clone the node */
1618 Clone = GenLiteralExpr (Expr->V.Val);
1622 Clone = GenULabelExpr (Expr->V.Val);
1626 Clone = GenSymExpr (Expr->V.Sym);
1630 Clone = GenSectionExpr (Expr->V.SegNum);
1634 /* Generate a new node */
1635 Clone = NewExprNode (Expr->Op);
1636 /* Clone the tree nodes */
1637 Clone->Left = CloneExpr (Expr->Left);
1638 Clone->Right = CloneExpr (Expr->Right);
1648 void WriteExpr (ExprNode* Expr)
1649 /* Write the given expression to the object file */
1651 /* Null expressions are encoded by a type byte of zero */
1653 ObjWrite8 (EXPR_NULL);
1657 /* If the is a leafnode, write the expression attribute, otherwise
1658 * write the expression operands.
1663 ObjWrite8 (EXPR_LITERAL);
1664 ObjWrite32 (Expr->V.Val);
1668 if (SymIsImport (Expr->V.Sym)) {
1669 ObjWrite8 (EXPR_SYMBOL);
1670 ObjWriteVar (GetSymIndex (Expr->V.Sym));
1672 WriteExpr (GetSymExpr (Expr->V.Sym));
1677 ObjWrite8 (EXPR_SECTION);
1678 ObjWrite8 (Expr->V.SegNum);
1682 WriteExpr (ULabResolve (Expr->V.Val));
1686 /* Not a leaf node */
1687 ObjWrite8 (Expr->Op);
1688 WriteExpr (Expr->Left);
1689 WriteExpr (Expr->Right);