1 /*****************************************************************************/
5 /* Expression evaluation for the ca65 macroassembler */
9 /* (C) 1998-2012, Ullrich von Bassewitz */
10 /* Roemerstrasse 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 #include "studyexpr.h"
69 /*****************************************************************************/
71 /*****************************************************************************/
75 /* Since all expressions are first packed into expression trees, and each
76 ** expression tree node is allocated on the heap, we add some type of special
77 ** purpose memory allocation here: Instead of freeing the nodes, we save some
78 ** number of freed nodes for later and remember them in a single linked list
79 ** using the Left link.
81 #define MAX_FREE_NODES 64
82 static ExprNode* FreeExprNodes = 0;
83 static unsigned FreeNodeCount = 0;
87 /*****************************************************************************/
89 /*****************************************************************************/
93 static ExprNode* NewExprNode (unsigned Op)
94 /* Create a new expression node */
98 /* Do we have some nodes in the list already? */
100 /* Use first node from list */
102 FreeExprNodes = N->Left;
105 /* Allocate fresh memory */
106 N = xmalloc (sizeof (ExprNode));
109 N->Left = N->Right = 0;
117 static void FreeExprNode (ExprNode* E)
121 if (E->Op == EXPR_SYMBOL) {
122 /* Remove the symbol reference */
123 SymDelExprRef (E->V.Sym, E);
125 /* Place the symbol into the free nodes list if possible */
126 if (FreeNodeCount < MAX_FREE_NODES) {
127 /* Remember this node for later */
128 E->Left = FreeExprNodes;
132 /* Free the memory */
140 /*****************************************************************************/
142 /*****************************************************************************/
146 static ExprNode* Expr0 (void);
150 int IsByteRange (long Val)
151 /* Return true if this is a byte value */
153 return (Val & ~0xFFL) == 0;
158 int IsWordRange (long Val)
159 /* Return true if this is a word value */
161 return (Val & ~0xFFFFL) == 0;
166 int IsFarRange (long Val)
167 /* Return true if this is a far (24 bit) value */
169 return (Val & ~0xFFFFFFL) == 0;
174 int IsEasyConst (const ExprNode* E, long* Val)
175 /* Do some light checking if the given node is a constant. Don't care if E is
176 ** a complex expression. If E is a constant, return true and place its value
177 ** into Val, provided that Val is not NULL.
180 /* Resolve symbols, follow symbol chains */
181 while (E->Op == EXPR_SYMBOL) {
182 E = SymResolve (E->V.Sym);
184 /* Could not resolve */
189 /* Symbols resolved, check for a literal */
190 if (E->Op == EXPR_LITERAL) {
197 /* Not found to be a const according to our tests */
203 static ExprNode* LoByte (ExprNode* Operand)
204 /* Return the low byte of the given expression */
209 /* Special handling for const expressions */
210 if (IsEasyConst (Operand, &Val)) {
212 Expr = GenLiteralExpr (Val & 0xFF);
214 /* Extract byte #0 */
215 Expr = NewExprNode (EXPR_BYTE0);
216 Expr->Left = Operand;
223 static ExprNode* HiByte (ExprNode* Operand)
224 /* Return the high byte of the given expression */
229 /* Special handling for const expressions */
230 if (IsEasyConst (Operand, &Val)) {
232 Expr = GenLiteralExpr ((Val >> 8) & 0xFF);
234 /* Extract byte #1 */
235 Expr = NewExprNode (EXPR_BYTE1);
236 Expr->Left = Operand;
243 static ExprNode* Bank (ExprNode* Operand)
244 /* Return the bank of the given segmented expression */
246 /* Generate the bank expression */
247 ExprNode* Expr = NewExprNode (EXPR_BANK);
248 Expr->Left = Operand;
250 /* Return the result */
256 static ExprNode* BankByte (ExprNode* Operand)
257 /* Return the bank byte of the given expression */
262 /* Special handling for const expressions */
263 if (IsEasyConst (Operand, &Val)) {
265 Expr = GenLiteralExpr ((Val >> 16) & 0xFF);
267 /* Extract byte #2 */
268 Expr = NewExprNode (EXPR_BYTE2);
269 Expr->Left = Operand;
276 static ExprNode* LoWord (ExprNode* Operand)
277 /* Return the low word of the given expression */
282 /* Special handling for const expressions */
283 if (IsEasyConst (Operand, &Val)) {
285 Expr = GenLiteralExpr (Val & 0xFFFF);
287 /* Extract word #0 */
288 Expr = NewExprNode (EXPR_WORD0);
289 Expr->Left = Operand;
296 static ExprNode* HiWord (ExprNode* Operand)
297 /* Return the high word of the given expression */
302 /* Special handling for const expressions */
303 if (IsEasyConst (Operand, &Val)) {
305 Expr = GenLiteralExpr ((Val >> 16) & 0xFFFF);
307 /* Extract word #1 */
308 Expr = NewExprNode (EXPR_WORD1);
309 Expr->Left = Operand;
316 static ExprNode* Symbol (SymEntry* S)
317 /* Reference a symbol and return an expression for it */
320 /* Some weird error happened before */
321 return GenLiteralExpr (0);
323 /* Mark the symbol as referenced */
325 /* If the symbol is a variable, return just its value, otherwise
326 ** return a reference to the symbol.
329 return CloneExpr (GetSymExpr (S));
331 /* Create symbol node */
332 return GenSymExpr (S);
339 ExprNode* FuncBank (void)
340 /* Handle the .BANK builtin function */
342 return Bank (Expression ());
347 ExprNode* FuncBankByte (void)
348 /* Handle the .BANKBYTE builtin function */
350 return BankByte (Expression ());
355 static ExprNode* FuncBlank (void)
356 /* Handle the .BLANK builtin function */
358 /* We have a list of tokens that ends with the closing paren. Skip
359 ** the tokens, and count them. Allow optionally curly braces.
361 token_t Term = GetTokListTerm (TOK_RPAREN);
363 while (CurTok.Tok != Term) {
365 /* Check for end of line or end of input. Since the calling function
366 ** will check for the closing paren, we don't need to print an error
367 ** here, just bail out.
369 if (TokIsSep (CurTok.Tok)) {
380 /* If the list was enclosed in curly braces, skip the closing brace */
381 if (Term == TOK_RCURLY && CurTok.Tok == TOK_RCURLY) {
385 /* Return true if the list was empty */
386 return GenLiteralExpr (Count == 0);
391 static ExprNode* FuncConst (void)
392 /* Handle the .CONST builtin function */
394 /* Read an expression */
395 ExprNode* Expr = Expression ();
397 /* Check the constness of the expression */
398 ExprNode* Result = GenLiteralExpr (IsConstExpr (Expr, 0));
400 /* Free the expression */
409 static ExprNode* FuncDefined (void)
410 /* Handle the .DEFINED builtin function */
412 /* Parse the symbol name and search for the symbol */
413 SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
415 /* Check if the symbol is defined */
416 return GenLiteralExpr (Sym != 0 && SymIsDef (Sym));
421 static ExprNode* FuncDefinedMacro (void)
422 /* Handle the .DEFINEDMACRO builtin function */
426 /* Check if the identifier is a macro */
428 if (CurTok.Tok == TOK_IDENT) {
429 Mac = FindMacro (&CurTok.SVal);
431 Error ("Identifier expected.");
436 return GenLiteralExpr (Mac != 0);
441 ExprNode* FuncHiByte (void)
442 /* Handle the .HIBYTE builtin function */
444 return HiByte (Expression ());
449 static ExprNode* FuncHiWord (void)
450 /* Handle the .HIWORD builtin function */
452 return HiWord (Expression ());
457 static ExprNode* FuncIsMnemonic (void)
458 /* Handle the .ISMNEMONIC, .ISMNEM builtin function */
462 /* Check for a macro or an instruction depending on UbiquitousIdents */
464 if (CurTok.Tok == TOK_IDENT) {
465 if (UbiquitousIdents) {
466 /* Macros CAN be instructions, so check for them first */
467 if (FindMacro (&CurTok.SVal) == 0) {
468 Instr = FindInstruction (&CurTok.SVal);
472 /* Macros and symbols may NOT use the names of instructions, so just check for the instruction */
473 Instr = FindInstruction (&CurTok.SVal);
477 Error ("Identifier expected.");
482 return GenLiteralExpr (Instr > 0);
487 ExprNode* FuncLoByte (void)
488 /* Handle the .LOBYTE builtin function */
490 return LoByte (Expression ());
495 static ExprNode* FuncLoWord (void)
496 /* Handle the .LOWORD builtin function */
498 return LoWord (Expression ());
503 static ExprNode* DoMatch (enum TC EqualityLevel)
504 /* Handle the .MATCH and .XMATCH builtin functions */
511 /* A list of tokens follows. Read this list and remember it building a
512 ** single linked list of tokens including attributes. The list is
513 ** either enclosed in curly braces, or terminated by a comma.
515 token_t Term = GetTokListTerm (TOK_COMMA);
516 while (CurTok.Tok != Term) {
518 /* We may not end-of-line of end-of-file here */
519 if (TokIsSep (CurTok.Tok)) {
520 Error ("Unexpected end of line");
521 return GenLiteral0 ();
524 /* Get a node with this token */
525 Node = NewTokNode ();
527 /* Insert the node into the list */
539 /* Skip the terminator token*/
542 /* If the token list was enclosed in curly braces, we expect a comma */
543 if (Term == TOK_RCURLY) {
547 /* Read the second list which is optionally enclosed in curly braces and
548 ** terminated by the right parenthesis. Compare each token against the
549 ** one in the first list.
551 Term = GetTokListTerm (TOK_RPAREN);
554 while (CurTok.Tok != Term) {
556 /* We may not end-of-line of end-of-file here */
557 if (TokIsSep (CurTok.Tok)) {
558 Error ("Unexpected end of line");
559 return GenLiteral0 ();
562 /* Compare the tokens if the result is not already known */
565 /* The second list is larger than the first one */
567 } else if (TokCmp (Node) < EqualityLevel) {
568 /* Tokens do not match */
573 /* Next token in first list */
578 /* Next token in current list */
582 /* If the token list was enclosed in curly braces, eat the closing brace */
583 if (Term == TOK_RCURLY) {
587 /* Check if there are remaining tokens in the first list */
592 /* Free the token list */
599 /* Done, return the result */
600 return GenLiteralExpr (Result);
605 static ExprNode* FuncMatch (void)
606 /* Handle the .MATCH function */
608 return DoMatch (tcSameToken);
613 static ExprNode* FuncMax (void)
614 /* Handle the .MAX function */
619 long LeftVal, RightVal;
621 /* Two arguments to the pseudo function */
622 Left = Expression ();
624 Right = Expression ();
626 /* Check if we can evaluate the value immediately */
627 if (IsEasyConst (Left, &LeftVal) && IsEasyConst (Right, &RightVal)) {
630 Expr = GenLiteralExpr ((LeftVal > RightVal)? LeftVal : RightVal);
632 /* Make an expression node */
633 Expr = NewExprNode (EXPR_MAX);
642 static ExprNode* FuncMin (void)
643 /* Handle the .MIN function */
648 long LeftVal, RightVal;
650 /* Two arguments to the pseudo function */
651 Left = Expression ();
653 Right = Expression ();
655 /* Check if we can evaluate the value immediately */
656 if (IsEasyConst (Left, &LeftVal) && IsEasyConst (Right, &RightVal)) {
659 Expr = GenLiteralExpr ((LeftVal < RightVal)? LeftVal : RightVal);
661 /* Make an expression node */
662 Expr = NewExprNode (EXPR_MIN);
671 static ExprNode* FuncReferenced (void)
672 /* Handle the .REFERENCED builtin function */
674 /* Parse the symbol name and search for the symbol */
675 SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
677 /* Check if the symbol is referenced */
678 return GenLiteralExpr (Sym != 0 && SymIsRef (Sym));
683 static ExprNode* FuncAddrSize (void)
684 /* Handle the .ADDRSIZE function */
686 StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
687 StrBuf Name = STATIC_STRBUF_INITIALIZER;
693 /* Assume we don't know the size */
696 /* Check for a cheap local which needs special handling */
697 if (CurTok.Tok == TOK_LOCAL_IDENT) {
699 /* Cheap local symbol */
700 Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
702 Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
704 AddrSize = Sym->AddrSize;
707 /* Remember and skip SVal, terminate ScopeName so it is empty */
708 SB_Copy (&Name, &CurTok.SVal);
710 SB_Terminate (&ScopeName);
714 /* Parse the scope and the name */
715 SymTable* ParentScope = ParseScopedIdent (&Name, &ScopeName);
717 /* Check if the parent scope is valid */
718 if (ParentScope == 0) {
720 SB_Done (&ScopeName);
722 return GenLiteral0 ();
725 /* If ScopeName is empty, no explicit scope was specified. We have to
726 ** search upper scope levels in this case.
728 NoScope = SB_IsEmpty (&ScopeName);
730 /* If we did find a scope with the name, read the symbol defining the
731 ** size, otherwise search for a symbol entry with the name and scope.
734 Sym = SymFindAny (ParentScope, &Name);
736 Sym = SymFind (ParentScope, &Name, SYM_FIND_EXISTING);
738 /* If we found the symbol retrieve the size, otherwise complain */
740 AddrSize = Sym->AddrSize;
742 Error ("Unknown symbol or scope: `%m%p%m%p'", &ScopeName, &Name);
748 Warning (1, "Unknown address size: `%m%p%m%p'", &ScopeName, &Name);
751 /* Free the string buffers */
752 SB_Done (&ScopeName);
755 /* Return the size. */
757 return GenLiteralExpr (AddrSize);
762 static ExprNode* FuncSizeOf (void)
763 /* Handle the .SIZEOF function */
765 StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
766 StrBuf Name = STATIC_STRBUF_INITIALIZER;
774 /* Assume an error */
777 /* Check for a cheap local which needs special handling */
778 if (CurTok.Tok == TOK_LOCAL_IDENT) {
780 /* Cheap local symbol */
781 Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
783 Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
785 SizeSym = GetSizeOfSymbol (Sym);
788 /* Remember and skip SVal, terminate ScopeName so it is empty */
789 SB_Copy (&Name, &CurTok.SVal);
791 SB_Terminate (&ScopeName);
795 /* Parse the scope and the name */
796 SymTable* ParentScope = ParseScopedIdent (&Name, &ScopeName);
798 /* Check if the parent scope is valid */
799 if (ParentScope == 0) {
801 SB_Done (&ScopeName);
803 return GenLiteral0 ();
806 /* If ScopeName is empty, no explicit scope was specified. We have to
807 ** search upper scope levels in this case.
809 NoScope = SB_IsEmpty (&ScopeName);
811 /* First search for a scope with the given name */
813 Scope = SymFindAnyScope (ParentScope, &Name);
815 Scope = SymFindScope (ParentScope, &Name, SYM_FIND_EXISTING);
818 /* If we did find a scope with the name, read the symbol defining the
819 ** size, otherwise search for a symbol entry with the name and scope.
822 /* Yep, it's a scope */
823 SizeSym = GetSizeOfScope (Scope);
826 Sym = SymFindAny (ParentScope, &Name);
828 Sym = SymFind (ParentScope, &Name, SYM_FIND_EXISTING);
831 /* If we found the symbol retrieve the size, otherwise complain */
833 SizeSym = GetSizeOfSymbol (Sym);
835 Error ("Unknown symbol or scope: `%m%p%m%p'",
841 /* Check if we have a size */
842 if (SizeSym == 0 || !SymIsConst (SizeSym, &Size)) {
843 Error ("Size of `%m%p%m%p' is unknown", &ScopeName, &Name);
847 /* Free the string buffers */
848 SB_Done (&ScopeName);
851 /* Return the size */
852 return GenLiteralExpr (Size);
857 static ExprNode* FuncStrAt (void)
858 /* Handle the .STRAT function */
860 StrBuf Str = STATIC_STRBUF_INITIALIZER;
864 /* String constant expected */
865 if (CurTok.Tok != TOK_STRCON) {
866 Error ("String constant expected");
871 /* Remember the string and skip it */
872 SB_Copy (&Str, &CurTok.SVal);
875 /* Comma must follow */
878 /* Expression expected */
879 Index = ConstExpression ();
881 /* Must be a valid index */
882 if (Index >= (long) SB_GetLen (&Str)) {
883 Error ("Range error");
887 /* Get the char, handle as unsigned. Be sure to translate it into
888 ** the target character set.
890 C = TgtTranslateChar (SB_At (&Str, (unsigned)Index));
893 /* Free string buffer memory */
896 /* Return the char expression */
897 return GenLiteralExpr (C);
902 static ExprNode* FuncStrLen (void)
903 /* Handle the .STRLEN function */
907 /* String constant expected */
908 if (CurTok.Tok != TOK_STRCON) {
910 Error ("String constant expected");
911 /* Smart error recovery */
912 if (CurTok.Tok != TOK_RPAREN) {
919 /* Get the length of the string */
920 Len = SB_GetLen (&CurTok.SVal);
922 /* Skip the string */
926 /* Return the length */
927 return GenLiteralExpr (Len);
932 static ExprNode* FuncTCount (void)
933 /* Handle the .TCOUNT function */
935 /* We have a list of tokens that ends with the closing paren. Skip
936 ** the tokens, and count them. Allow optionally curly braces.
938 token_t Term = GetTokListTerm (TOK_RPAREN);
940 while (CurTok.Tok != Term) {
942 /* Check for end of line or end of input. Since the calling function
943 ** will check for the closing paren, we don't need to print an error
944 ** here, just bail out.
946 if (TokIsSep (CurTok.Tok)) {
957 /* If the list was enclosed in curly braces, skip the closing brace */
958 if (Term == TOK_RCURLY && CurTok.Tok == TOK_RCURLY) {
962 /* Return the number of tokens */
963 return GenLiteralExpr (Count);
968 static ExprNode* FuncXMatch (void)
969 /* Handle the .XMATCH function */
971 return DoMatch (tcIdentical);
976 static ExprNode* Function (ExprNode* (*F) (void))
977 /* Handle builtin functions */
981 /* Skip the keyword */
984 /* Expression must be enclosed in braces */
985 if (CurTok.Tok != TOK_LPAREN) {
986 Error ("'(' expected");
988 return GenLiteral0 ();
992 /* Call the function itself */
995 /* Closing brace must follow */
998 /* Return the result of the actual function */
1004 static ExprNode* Factor (void)
1010 switch (CurTok.Tok) {
1013 N = GenLiteralExpr (CurTok.IVal);
1018 N = GenLiteralExpr (TgtTranslateChar (CurTok.IVal));
1024 case TOK_LOCAL_IDENT:
1025 N = Symbol (ParseAnySymName (SYM_ALLOC_NEW));
1029 N = ULabRef (CurTok.IVal);
1041 if (IsEasyConst (L, &Val)) {
1043 N = GenLiteralExpr (-Val);
1045 N = NewExprNode (EXPR_UNARY_MINUS);
1053 if (IsEasyConst (L, &Val)) {
1055 N = GenLiteralExpr (~Val);
1057 N = NewExprNode (EXPR_NOT);
1065 N = GenCurrentPC ();
1070 N = LoByte (Factor ());
1075 N = HiByte (Factor ());
1079 /* ^ means the bank byte of an expression */
1081 N = BankByte (Factor ());
1091 N = Function (FuncBank);
1095 N = Function (FuncBankByte);
1099 N = Function (FuncAddrSize);
1103 N = Function (FuncBlank);
1107 N = Function (FuncConst);
1111 N = GenLiteralExpr (CPUIsets[CPU]);
1116 N = Function (FuncDefined);
1119 case TOK_DEFINEDMACRO:
1120 N = Function (FuncDefinedMacro);
1124 N = Function (FuncHiByte);
1128 N = Function (FuncHiWord);
1131 case TOK_ISMNEMONIC:
1132 N = Function (FuncIsMnemonic);
1136 N = Function (FuncLoByte);
1140 N = Function (FuncLoWord);
1144 N = Function (FuncMatch);
1148 N = Function (FuncMax);
1152 N = Function (FuncMin);
1155 case TOK_REFERENCED:
1156 N = Function (FuncReferenced);
1160 N = Function (FuncSizeOf);
1164 N = Function (FuncStrAt);
1168 N = Function (FuncStrLen);
1172 N = Function (FuncTCount);
1176 N = GenLiteralExpr ((long) time (0));
1181 N = GenLiteralExpr (GetVersionAsNumber ());
1186 N = Function (FuncXMatch);
1190 if (LooseCharTerm && CurTok.Tok == TOK_STRCON &&
1191 SB_GetLen (&CurTok.SVal) == 1) {
1192 /* A character constant */
1193 N = GenLiteralExpr (TgtTranslateChar (SB_At (&CurTok.SVal, 0)));
1195 N = GenLiteral0 (); /* Dummy */
1196 Error ("Syntax error");
1206 static ExprNode* Term (void)
1208 /* Read left hand side */
1209 ExprNode* Root = Factor ();
1211 /* Handle multiplicative operations */
1212 while (CurTok.Tok == TOK_MUL || CurTok.Tok == TOK_DIV ||
1213 CurTok.Tok == TOK_MOD || CurTok.Tok == TOK_AND ||
1214 CurTok.Tok == TOK_XOR || CurTok.Tok == TOK_SHL ||
1215 CurTok.Tok == TOK_SHR) {
1217 long LVal, RVal, Val;
1221 /* Remember the token and skip it */
1222 token_t T = CurTok.Tok;
1225 /* Move root to left side and read the right side */
1229 /* If both expressions are constant, we can evaluate the term */
1230 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1239 Error ("Division by zero");
1248 Error ("Modulo operation with zero");
1264 Val = shl_l (LVal, RVal);
1268 Val = shr_l (LVal, RVal);
1272 Internal ("Invalid token");
1275 /* Generate a literal expression and delete the old left and
1280 Root = GenLiteralExpr (Val);
1284 /* Generate an expression tree */
1287 case TOK_MUL: Op = EXPR_MUL; break;
1288 case TOK_DIV: Op = EXPR_DIV; break;
1289 case TOK_MOD: Op = EXPR_MOD; break;
1290 case TOK_AND: Op = EXPR_AND; break;
1291 case TOK_XOR: Op = EXPR_XOR; break;
1292 case TOK_SHL: Op = EXPR_SHL; break;
1293 case TOK_SHR: Op = EXPR_SHR; break;
1294 default: Internal ("Invalid token");
1296 Root = NewExprNode (Op);
1298 Root->Right = Right;
1304 /* Return the expression tree we've created */
1310 static ExprNode* SimpleExpr (void)
1312 /* Read left hand side */
1313 ExprNode* Root = Term ();
1315 /* Handle additive operations */
1316 while (CurTok.Tok == TOK_PLUS ||
1317 CurTok.Tok == TOK_MINUS ||
1318 CurTok.Tok == TOK_OR) {
1320 long LVal, RVal, Val;
1324 /* Remember the token and skip it */
1325 token_t T = CurTok.Tok;
1328 /* Move root to left side and read the right side */
1332 /* If both expressions are constant, we can evaluate the term */
1333 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1336 case TOK_PLUS: Val = LVal + RVal; break;
1337 case TOK_MINUS: Val = LVal - RVal; break;
1338 case TOK_OR: Val = LVal | RVal; break;
1339 default: Internal ("Invalid token");
1342 /* Generate a literal expression and delete the old left and
1347 Root = GenLiteralExpr (Val);
1351 /* Generate an expression tree */
1354 case TOK_PLUS: Op = EXPR_PLUS; break;
1355 case TOK_MINUS: Op = EXPR_MINUS; break;
1356 case TOK_OR: Op = EXPR_OR; break;
1357 default: Internal ("Invalid token");
1359 Root = NewExprNode (Op);
1361 Root->Right = Right;
1366 /* Return the expression tree we've created */
1372 static ExprNode* BoolExpr (void)
1373 /* Evaluate a boolean expression */
1375 /* Read left hand side */
1376 ExprNode* Root = SimpleExpr ();
1378 /* Handle booleans */
1379 while (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_NE ||
1380 CurTok.Tok == TOK_LT || CurTok.Tok == TOK_GT ||
1381 CurTok.Tok == TOK_LE || CurTok.Tok == TOK_GE) {
1383 long LVal, RVal, Val;
1387 /* Remember the token and skip it */
1388 token_t T = CurTok.Tok;
1391 /* Move root to left side and read the right side */
1393 Right = SimpleExpr ();
1395 /* If both expressions are constant, we can evaluate the term */
1396 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1399 case TOK_EQ: Val = (LVal == RVal); break;
1400 case TOK_NE: Val = (LVal != RVal); break;
1401 case TOK_LT: Val = (LVal < RVal); break;
1402 case TOK_GT: Val = (LVal > RVal); break;
1403 case TOK_LE: Val = (LVal <= RVal); break;
1404 case TOK_GE: Val = (LVal >= RVal); break;
1405 default: Internal ("Invalid token");
1408 /* Generate a literal expression and delete the old left and
1413 Root = GenLiteralExpr (Val);
1417 /* Generate an expression tree */
1420 case TOK_EQ: Op = EXPR_EQ; break;
1421 case TOK_NE: Op = EXPR_NE; break;
1422 case TOK_LT: Op = EXPR_LT; break;
1423 case TOK_GT: Op = EXPR_GT; break;
1424 case TOK_LE: Op = EXPR_LE; break;
1425 case TOK_GE: Op = EXPR_GE; break;
1426 default: Internal ("Invalid token");
1428 Root = NewExprNode (Op);
1430 Root->Right = Right;
1435 /* Return the expression tree we've created */
1441 static ExprNode* Expr2 (void)
1442 /* Boolean operators: AND and XOR */
1444 /* Read left hand side */
1445 ExprNode* Root = BoolExpr ();
1447 /* Handle booleans */
1448 while (CurTok.Tok == TOK_BOOLAND || CurTok.Tok == TOK_BOOLXOR) {
1450 long LVal, RVal, Val;
1454 /* Remember the token and skip it */
1455 token_t T = CurTok.Tok;
1458 /* Move root to left side and read the right side */
1460 Right = BoolExpr ();
1462 /* If both expressions are constant, we can evaluate the term */
1463 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1466 case TOK_BOOLAND: Val = ((LVal != 0) && (RVal != 0)); break;
1467 case TOK_BOOLXOR: Val = ((LVal != 0) ^ (RVal != 0)); break;
1468 default: Internal ("Invalid token");
1471 /* Generate a literal expression and delete the old left and
1476 Root = GenLiteralExpr (Val);
1480 /* Generate an expression tree */
1483 case TOK_BOOLAND: Op = EXPR_BOOLAND; break;
1484 case TOK_BOOLXOR: Op = EXPR_BOOLXOR; break;
1485 default: Internal ("Invalid token");
1487 Root = NewExprNode (Op);
1489 Root->Right = Right;
1494 /* Return the expression tree we've created */
1500 static ExprNode* Expr1 (void)
1501 /* Boolean operators: OR */
1503 /* Read left hand side */
1504 ExprNode* Root = Expr2 ();
1506 /* Handle booleans */
1507 while (CurTok.Tok == TOK_BOOLOR) {
1509 long LVal, RVal, Val;
1513 /* Remember the token and skip it */
1514 token_t T = CurTok.Tok;
1517 /* Move root to left side and read the right side */
1521 /* If both expressions are constant, we can evaluate the term */
1522 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1525 case TOK_BOOLOR: Val = ((LVal != 0) || (RVal != 0)); break;
1526 default: Internal ("Invalid token");
1529 /* Generate a literal expression and delete the old left and
1534 Root = GenLiteralExpr (Val);
1538 /* Generate an expression tree */
1541 case TOK_BOOLOR: Op = EXPR_BOOLOR; break;
1542 default: Internal ("Invalid token");
1544 Root = NewExprNode (Op);
1546 Root->Right = Right;
1551 /* Return the expression tree we've created */
1557 static ExprNode* Expr0 (void)
1558 /* Boolean operators: NOT */
1562 /* Handle booleans */
1563 if (CurTok.Tok == TOK_BOOLNOT) {
1568 /* Skip the operator token */
1571 /* Read the argument */
1574 /* If the argument is const, evaluate it directly */
1575 if (IsEasyConst (Left, &Val)) {
1577 Root = GenLiteralExpr (!Val);
1579 Root = NewExprNode (EXPR_BOOLNOT);
1585 /* Read left hand side */
1590 /* Return the expression tree we've created */
1596 ExprNode* Expression (void)
1597 /* Evaluate an expression, build the expression tree on the heap and return
1598 ** a pointer to the root of the tree.
1606 long ConstExpression (void)
1607 /* Parse an expression. Check if the expression is const, and print an error
1608 ** message if not. Return the value of the expression, or a dummy, if it is
1614 /* Read the expression */
1615 ExprNode* Expr = Expression ();
1617 /* Study the expression */
1620 StudyExpr (Expr, &D);
1622 /* Check if the expression is constant */
1623 if (ED_IsConst (&D)) {
1626 Error ("Constant expression expected");
1630 /* Free the expression tree and allocated memory for D */
1634 /* Return the value */
1640 void FreeExpr (ExprNode* Root)
1641 /* Free the expression, Root is pointing to. */
1644 FreeExpr (Root->Left);
1645 FreeExpr (Root->Right);
1646 FreeExprNode (Root);
1652 ExprNode* SimplifyExpr (ExprNode* Expr, const ExprDesc* D)
1653 /* Try to simplify the given expression tree */
1655 if (Expr->Op != EXPR_LITERAL && ED_IsConst (D)) {
1656 /* No external references */
1658 Expr = GenLiteralExpr (D->Val);
1665 ExprNode* GenLiteralExpr (long Val)
1666 /* Return an expression tree that encodes the given literal value */
1668 ExprNode* Expr = NewExprNode (EXPR_LITERAL);
1675 ExprNode* GenLiteral0 (void)
1676 /* Return an expression tree that encodes the the number zero */
1678 return GenLiteralExpr (0);
1683 ExprNode* GenSymExpr (SymEntry* Sym)
1684 /* Return an expression node that encodes the given symbol */
1686 ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
1688 SymAddExprRef (Sym, Expr);
1694 static ExprNode* GenSectionExpr (unsigned SecNum)
1695 /* Return an expression node for the given section */
1697 ExprNode* Expr = NewExprNode (EXPR_SECTION);
1698 Expr->V.SecNum = SecNum;
1704 static ExprNode* GenBankExpr (unsigned SecNum)
1705 /* Return an expression node for the given bank */
1707 ExprNode* Expr = NewExprNode (EXPR_BANK);
1708 Expr->V.SecNum = SecNum;
1714 ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right)
1715 /* Generate an addition from the two operands */
1718 if (IsEasyConst (Left, &Val) && Val == 0) {
1721 } else if (IsEasyConst (Right, &Val) && Val == 0) {
1725 ExprNode* Root = NewExprNode (EXPR_PLUS);
1727 Root->Right = Right;
1734 ExprNode* GenCurrentPC (void)
1735 /* Return the current program counter as expression */
1739 if (GetRelocMode ()) {
1740 /* Create SegmentBase + Offset */
1741 Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
1742 GenLiteralExpr (GetPC ()));
1744 /* Absolute mode, just return PC value */
1745 Root = GenLiteralExpr (GetPC ());
1753 ExprNode* GenSwapExpr (ExprNode* Expr)
1754 /* Return an extended expression with lo and hi bytes swapped */
1756 ExprNode* N = NewExprNode (EXPR_SWAP);
1763 ExprNode* GenBranchExpr (unsigned Offs)
1764 /* Return an expression that encodes the difference between current PC plus
1765 ** offset and the target expression (that is, Expression() - (*+Offs) ).
1772 /* Read Expression() */
1775 /* If the expression is a cheap constant, generate a simpler tree */
1776 if (IsEasyConst (N, &Val)) {
1778 /* Free the constant expression tree */
1781 /* Generate the final expression:
1783 ** Val - ((Seg + PC) + Offs)
1784 ** Val - Seg - PC - Offs
1785 ** (Val - PC - Offs) - Seg
1787 Root = GenLiteralExpr (Val - GetPC () - Offs);
1788 if (GetRelocMode ()) {
1790 Root = NewExprNode (EXPR_MINUS);
1792 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1797 /* Generate the expression:
1799 ** N - ((Seg + PC) + Offs)
1800 ** N - Seg - PC - Offs
1801 ** N - (PC + Offs) - Seg
1803 Root = NewExprNode (EXPR_MINUS);
1805 Root->Right = GenLiteralExpr (GetPC () + Offs);
1806 if (GetRelocMode ()) {
1808 Root = NewExprNode (EXPR_MINUS);
1810 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1814 /* Return the result */
1820 ExprNode* GenULabelExpr (unsigned Num)
1821 /* Return an expression for an unnamed label with the given index */
1823 ExprNode* Node = NewExprNode (EXPR_ULABEL);
1826 /* Return the new node */
1832 ExprNode* GenByteExpr (ExprNode* Expr)
1833 /* Force the given expression into a byte and return the result */
1835 /* Use the low byte operator to force the expression into byte size */
1836 return LoByte (Expr);
1841 ExprNode* GenWordExpr (ExprNode* Expr)
1842 /* Force the given expression into a word and return the result. */
1844 /* Use the low byte operator to force the expression into word size */
1845 return LoWord (Expr);
1850 ExprNode* GenFarAddrExpr (ExprNode* Expr)
1851 /* Force the given expression into a far address and return the result. */
1855 /* Special handling for const expressions */
1856 if (IsEasyConst (Expr, &Val)) {
1858 Expr = GenLiteralExpr (Val & 0xFFFFFF);
1860 ExprNode* Operand = Expr;
1861 Expr = NewExprNode (EXPR_FARADDR);
1862 Expr->Left = Operand;
1869 ExprNode* GenDWordExpr (ExprNode* Expr)
1870 /* Force the given expression into a dword and return the result. */
1874 /* Special handling for const expressions */
1875 if (IsEasyConst (Expr, &Val)) {
1877 Expr = GenLiteralExpr (Val & 0xFFFFFFFF);
1879 ExprNode* Operand = Expr;
1880 Expr = NewExprNode (EXPR_DWORD);
1881 Expr->Left = Operand;
1888 ExprNode* GenNE (ExprNode* Expr, long Val)
1889 /* Generate an expression that compares Expr and Val for inequality */
1891 /* Generate a compare node */
1892 ExprNode* Root = NewExprNode (EXPR_NE);
1894 Root->Right = GenLiteralExpr (Val);
1896 /* Return the result */
1902 int IsConstExpr (ExprNode* Expr, long* Val)
1903 /* Return true if the given expression is a constant expression, that is, one
1904 ** with no references to external symbols. If Val is not NULL and the
1905 ** expression is constant, the constant value is stored here.
1910 /* Study the expression */
1913 StudyExpr (Expr, &D);
1915 /* Check if the expression is constant */
1916 IsConst = ED_IsConst (&D);
1917 if (IsConst && Val != 0) {
1921 /* Delete allocated memory and return the result */
1928 ExprNode* CloneExpr (ExprNode* Expr)
1929 /* Clone the given expression tree. The function will simply clone symbol
1930 ** nodes, it will not resolve them.
1935 /* Accept NULL pointers */
1940 /* Clone the node */
1944 Clone = GenLiteralExpr (Expr->V.IVal);
1948 Clone = GenULabelExpr (Expr->V.IVal);
1952 Clone = GenSymExpr (Expr->V.Sym);
1956 Clone = GenSectionExpr (Expr->V.SecNum);
1960 Clone = GenBankExpr (Expr->V.SecNum);
1964 /* Generate a new node */
1965 Clone = NewExprNode (Expr->Op);
1966 /* Clone the tree nodes */
1967 Clone->Left = CloneExpr (Expr->Left);
1968 Clone->Right = CloneExpr (Expr->Right);
1978 void WriteExpr (ExprNode* Expr)
1979 /* Write the given expression to the object file */
1981 /* Null expressions are encoded by a type byte of zero */
1983 ObjWrite8 (EXPR_NULL);
1987 /* If the is a leafnode, write the expression attribute, otherwise
1988 ** write the expression operands.
1993 ObjWrite8 (EXPR_LITERAL);
1994 ObjWrite32 (Expr->V.IVal);
1998 if (SymIsImport (Expr->V.Sym)) {
1999 ObjWrite8 (EXPR_SYMBOL);
2000 ObjWriteVar (GetSymImportId (Expr->V.Sym));
2002 WriteExpr (GetSymExpr (Expr->V.Sym));
2007 ObjWrite8 (EXPR_SECTION);
2008 ObjWriteVar (Expr->V.SecNum);
2012 WriteExpr (ULabResolve (Expr->V.IVal));
2016 /* Not a leaf node */
2017 ObjWrite8 (Expr->Op);
2018 WriteExpr (Expr->Left);
2019 WriteExpr (Expr->Right);
2027 void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize)
2028 /* Mark the address size of the given expression tree as guessed. The address
2029 ** size passed as argument is the one NOT used, because the actual address
2030 ** size wasn't known. Example: Zero page addressing was not used because symbol
2031 ** is undefined, and absolute addressing was available.
2032 ** This function will actually parse the expression tree for undefined symbols,
2033 ** and mark these symbols accordingly.
2036 /* Accept NULL expressions */
2041 /* Check the type code */
2042 switch (EXPR_NODETYPE (Expr->Op)) {
2045 if (Expr->Op == EXPR_SYMBOL) {
2046 if (!SymIsDef (Expr->V.Sym)) {
2047 /* Symbol is undefined, mark it */
2048 SymGuessedAddrSize (Expr->V.Sym, AddrSize);
2053 case EXPR_BINARYNODE:
2054 ExprGuessedAddrSize (Expr->Right, AddrSize);
2057 case EXPR_UNARYNODE:
2058 ExprGuessedAddrSize (Expr->Left, AddrSize);
2065 ExprNode* MakeBoundedExpr (ExprNode* Expr, unsigned Size)
2066 /* Force the given expression into a specific size of ForceRange is true */
2070 case 1: Expr = GenByteExpr (Expr); break;
2071 case 2: Expr = GenWordExpr (Expr); break;
2072 case 3: Expr = GenFarAddrExpr (Expr); break;
2073 case 4: Expr = GenDWordExpr (Expr); break;
2074 default: Internal ("Invalid size in BoundedExpr: %u", Size);
2082 ExprNode* BoundedExpr (ExprNode* (*ExprFunc) (void), unsigned Size)
2083 /* Parse an expression and force it within a given size if ForceRange is true */
2085 return MakeBoundedExpr (ExprFunc (), Size);