]> git.sur5r.net Git - cc65/blob - src/ca65/studyexpr.c
Code cleanup
[cc65] / src / ca65 / studyexpr.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                studyexpr.c                                */
4 /*                                                                           */
5 /*                         Study an expression tree                          */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2003      Ullrich von Bassewitz                                       */
10 /*               Römerstraße 52                                              */
11 /*               D-70794 Filderstadt                                         */
12 /* EMail:        uz@cc65.org                                                 */
13 /*                                                                           */
14 /*                                                                           */
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.                                    */
18 /*                                                                           */
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:                            */
22 /*                                                                           */
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              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <string.h>
37
38 /* common */
39 #include "check.h"
40 #include "print.h"
41 #include "shift.h"
42 #include "xmalloc.h"
43
44 /* ca65 */
45 #include "error.h"
46 #include "segment.h"
47 #include "studyexpr.h"
48 #include "symtab.h"
49 #include "ulabel.h"
50
51
52
53 /*****************************************************************************/
54 /*                              struct ExprDesc                              */
55 /*****************************************************************************/
56
57
58
59 ExprDesc* ED_Init (ExprDesc* ED)
60 /* Initialize an ExprDesc structure for use with StudyExpr */
61 {
62     ED->Flags     = ED_OK;
63     ED->AddrSize  = ADDR_SIZE_DEFAULT;
64     ED->Val       = 0;
65     ED->SymCount  = 0;
66     ED->SymLimit  = 0;
67     ED->SymRef    = 0;
68     ED->SecCount  = 0;
69     ED->SecLimit  = 0;
70     ED->SecRef    = 0;
71     return ED;
72 }
73
74
75
76 void ED_Done (ExprDesc* ED)
77 /* Delete allocated memory for an ExprDesc. */
78 {
79     xfree (ED->SymRef);
80     xfree (ED->SecRef);
81 }
82
83
84
85 int ED_IsConst (const ExprDesc* D)
86 /* Return true if the expression is constant */
87 {
88     unsigned I;
89
90     if (D->Flags & ED_TOO_COMPLEX) {
91         return 0;
92     }
93     for (I = 0; I < D->SymCount; ++I) {
94         if (D->SymRef[I].Count != 0) {
95             return 0;
96         }
97     }
98     for (I = 0; I < D->SecCount; ++I) {
99         if (D->SecRef[I].Count != 0) {
100             return 0;
101         }
102     }
103     return 1;
104 }
105
106
107
108 static int ED_IsValid (const ExprDesc* D)
109 /* Return true if the expression is valid, that is, the TOO_COMPLEX flag is
110  * not set
111  */
112 {
113     return ((D->Flags & ED_TOO_COMPLEX) == 0);
114 }
115
116
117
118 static void ED_Invalidate (ExprDesc* D)
119 /* Set the TOO_COMPLEX flag for D */
120 {
121     D->Flags |= ED_TOO_COMPLEX;
122 }
123
124
125
126 static void ED_UpdateAddrSize (ExprDesc* ED, unsigned char AddrSize)
127 /* Update the address size of the expression */
128 {
129     if (ED->AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) {
130         ED->AddrSize = AddrSize;
131     }
132 }
133
134
135
136 static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym)
137 /* Find a symbol reference and return it. Return NULL if the reference does
138  * not exist.
139  */
140 {
141     unsigned I;
142     ED_SymRef* SymRef;
143     for (I = 0, SymRef = ED->SymRef; I < ED->SymCount; ++I, ++SymRef) {
144         if (SymRef->Ref == Sym) {
145             return SymRef;
146         }
147     }
148     return 0;
149 }
150
151
152
153 static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec)
154 /* Find a section reference and return it. Return NULL if the reference does
155  * not exist.
156  */
157 {
158     unsigned I;
159     ED_SecRef* SecRef;
160     for (I = 0, SecRef = ED->SecRef; I < ED->SecCount; ++I, ++SecRef) {
161         if (SecRef->Ref == Sec) {
162             return SecRef;
163         }
164     }
165     return 0;
166 }
167
168
169
170 static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym)
171 /* Allocate a new symbol reference and return it. The count of the new
172  * reference will be set to zero, and the reference itself to Sym.
173  */
174 {
175     ED_SymRef* SymRef;
176
177     /* Make sure we have enough SymRef slots */
178     if (ED->SymCount >= ED->SymLimit) {
179         ED->SymLimit *= 2;
180         if (ED->SymLimit == 0) {
181             ED->SymLimit = 2;
182         }
183         ED->SymRef = xrealloc (ED->SymRef, ED->SymLimit * sizeof (ED->SymRef[0]));
184     }
185
186     /* Allocate a new slot */
187     SymRef = ED->SymRef + ED->SymCount++;
188
189     /* Initialize the new struct and return it */
190     SymRef->Count = 1;
191     SymRef->Ref   = Sym;
192     return SymRef;
193 }
194
195
196
197 static ED_SecRef* ED_AllocSecRef (ExprDesc* ED, unsigned Sec)
198 /* Allocate a new section reference and return it. The count of the new
199  * reference will be set to zero, and the reference itself to Sec.
200  */
201 {
202     ED_SecRef* SecRef;
203
204     /* Make sure we have enough SecRef slots */
205     if (ED->SecCount >= ED->SecLimit) {
206         ED->SecLimit *= 2;
207         if (ED->SecLimit == 0) {
208             ED->SecLimit = 2;
209         }
210         ED->SecRef = xrealloc (ED->SecRef, ED->SecLimit * sizeof (ED->SecRef[0]));
211     }
212
213     /* Allocate a new slot */
214     SecRef = ED->SecRef + ED->SecCount++;
215
216     /* Initialize the new struct and return it */
217     SecRef->Count = 0;
218     SecRef->Ref   = Sec;
219     return SecRef;
220 }
221
222
223
224 static ED_SymRef* ED_GetSymRef (ExprDesc* ED, SymEntry* Sym)
225 /* Get a symbol reference and return it. If the symbol reference does not
226  * exist, a new one is created and returned.
227  */
228 {
229     ED_SymRef* SymRef = ED_FindSymRef (ED, Sym);
230     if (SymRef == 0) {
231         SymRef = ED_AllocSymRef (ED, Sym);
232     }
233     return SymRef;
234 }
235
236
237
238 static ED_SecRef* ED_GetSecRef (ExprDesc* ED, unsigned Sec)
239 /* Get a section reference and return it. If the section reference does not
240  * exist, a new one is created and returned.
241  */
242 {
243     ED_SecRef* SecRef = ED_FindSecRef (ED, Sec);
244     if (SecRef == 0) {
245         SecRef = ED_AllocSecRef (ED, Sec);
246     }
247     return SecRef;
248 }
249
250
251
252 static void ED_MergeSymRefs (ExprDesc* ED, const ExprDesc* New)
253 /* Merge the symbol references from New into ED */
254 {
255     unsigned I;
256     for (I = 0; I < New->SymCount; ++I) {
257
258         /* Get a pointer to the SymRef entry */
259         const ED_SymRef* NewRef = New->SymRef + I;
260
261         /* Get the corresponding entry in ED */
262         ED_SymRef* SymRef = ED_GetSymRef (ED, NewRef->Ref);
263
264         /* Sum up the references */
265         SymRef->Count += NewRef->Count;
266     }
267 }
268
269
270
271 static void ED_MergeSecRefs (ExprDesc* ED, const ExprDesc* New)
272 /* Merge the section references from New into ED */
273 {
274     unsigned I;
275     for (I = 0; I < New->SecCount; ++I) {
276
277         /* Get a pointer to the SymRef entry */
278         const ED_SecRef* NewRef = New->SecRef + I;
279
280         /* Get the corresponding entry in ED */
281         ED_SecRef* SecRef = ED_GetSecRef (ED, NewRef->Ref);
282
283         /* Sum up the references */
284         SecRef->Count += NewRef->Count;
285     }
286 }
287
288
289
290 static void ED_MergeRefs (ExprDesc* ED, const ExprDesc* New)
291 /* Merge all references from New into ED */
292 {
293     ED_MergeSymRefs (ED, New);
294     ED_MergeSecRefs (ED, New);
295 }
296
297
298
299 static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
300 /* Calculate ED = ED + Right, update address size in ED */
301 {
302     ED->Val += Right->Val;
303     ED_MergeRefs (ED, Right);
304     ED_UpdateAddrSize (ED, Right->AddrSize);
305 }
306
307
308
309 static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
310 /* Calculate ED = ED * Right, update address size in ED */
311 {
312     unsigned I;
313
314     ED->Val *= Right->Val;
315     for (I = 0; I < ED->SymCount; ++I) {
316         ED->SymRef[I].Count *= Right->Val;
317     }
318     for (I = 0; I < ED->SecCount; ++I) {
319         ED->SecRef[I].Count *= Right->Val;
320     }
321     ED_UpdateAddrSize (ED, Right->AddrSize);
322 }
323
324
325
326 static void ED_Neg (ExprDesc* D)
327 /* Negate an expression */
328 {
329     unsigned I;
330
331     D->Val = -D->Val;
332     for (I = 0; I < D->SymCount; ++I) {
333         D->SymRef[I].Count = -D->SymRef[I].Count;
334     }
335     for (I = 0; I < D->SecCount; ++I) {
336         D->SecRef[I].Count = -D->SecRef[I].Count;
337     }
338 }
339
340
341
342 static void ED_Move (ExprDesc* From, ExprDesc* To)
343 /* Move the data from one ExprDesc to another. Old data is freed, and From
344  * is prepared to that ED_Done may be called safely.
345  */
346 {
347     /* Delete old data */
348     ED_Done (To);
349
350     /* Move the data */
351     *To = *From;
352
353     /* Cleanup From */
354     ED_Init (From);
355 }
356
357
358
359 /*****************************************************************************/
360 /*                                   Code                                    */
361 /*****************************************************************************/
362
363
364
365 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D);
366 /* Study an expression tree and place the contents into D */
367
368
369
370 static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
371 /* Study a binary expression subtree. This is a helper function for StudyExpr
372  * used for operations that succeed when both operands are known and constant.
373  * It evaluates the two subtrees and checks if they are constant. If they
374  * aren't constant, it will set the TOO_COMPLEX flag, and merge references.
375  * Otherwise the first value is returned in D->Val, the second one in D->Right,
376  * so the actual operation can be done by the caller.
377  */
378 {
379     ExprDesc Right;
380
381     /* Study the left side of the expression */
382     StudyExprInternal (Expr->Left, D);
383
384     /* Study the right side of the expression */
385     ED_Init (&Right);
386     StudyExprInternal (Expr->Right, &Right);
387
388     /* Check if we can handle the operation */
389     if (ED_IsConst (D) && ED_IsConst (&Right)) {
390
391         /* Remember the constant value from Right */
392         D->Right = Right.Val;
393
394     } else {
395
396         /* Cannot evaluate */
397         ED_Invalidate (D);
398
399         /* Merge references and update address size */
400         ED_MergeRefs (D, &Right);
401         ED_UpdateAddrSize (D, Right.AddrSize);
402
403     }
404
405     /* Cleanup Right */
406     ED_Done (&Right);
407 }
408
409
410
411 static void StudyLiteral (ExprNode* Expr, ExprDesc* D)
412 /* Study a literal expression node */
413 {
414     /* This one is easy */
415     D->Val = Expr->V.Val;
416 }
417
418
419
420 static void StudySymbol (ExprNode* Expr, ExprDesc* D)
421 /* Study a symbol expression node */
422 {
423     /* Get the symbol from the expression */
424     SymEntry* Sym = Expr->V.Sym;
425
426     /* If the symbol is defined somewhere, it has an expression associated.
427      * In this case, just study the expression associated with the symbol,
428      * but mark the symbol so if we encounter it twice, we know that we have
429      * a circular reference.
430      */
431     if (SymHasExpr (Sym)) {
432         if (SymHasUserMark (Sym)) {
433             if (Verbosity > 0) {
434                 DumpExpr (Expr, SymResolve);
435             }
436             PError (GetSymPos (Sym),
437                     "Circular reference in definition of symbol `%s'",
438                     GetSymName (Sym));
439             ED_Invalidate (D);
440         } else {
441
442             unsigned char AddrSize;
443
444             /* Mark the symbol and study its associated expression */
445             SymMarkUser (Sym);
446             StudyExprInternal (GetSymExpr (Sym), D);
447             SymUnmarkUser (Sym);
448
449             /* If the symbol has an explicit address size, use it. This may
450              * lead to range errors later (maybe even in the linker stage), if
451              * the user lied about the address size, but for now we trust the
452              * user.
453              */
454             AddrSize = GetSymAddrSize (Sym);
455             if (AddrSize != ADDR_SIZE_DEFAULT) {
456                 D->AddrSize = AddrSize;
457             }
458         }
459     } else {
460         /* The symbol is either undefined or an import. In both cases, track
461          * the symbols used and update the address size, but in case of an
462          * undefined symbol also set the "too complex" flag, since we cannot
463          * evaluate the final result.
464          */
465         ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
466         ++SymRef->Count;
467         ED_UpdateAddrSize (D, GetSymAddrSize (Sym));
468         if (!SymIsImport (Sym)) {
469             /* Cannot handle */
470             ED_Invalidate (D);
471         }
472     }
473 }
474
475
476
477 static void StudySection (ExprNode* Expr, ExprDesc* D)
478 /* Study a section expression node */
479 {
480     /* Get the section reference */
481     ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SegNum);
482
483     /* Update the data and the address size */
484     ++SecRef->Count;
485     ED_UpdateAddrSize (D, GetSegAddrSize (SecRef->Ref));
486 }
487
488
489
490 static void StudyULabel (ExprNode* Expr, ExprDesc* D)
491 /* Study an unnamed label expression node */
492 {
493     /* If we can resolve the label, study the expression associated with it,
494      * otherwise mark the expression as too complex to evaluate.
495      */
496     if (ULabCanResolve ()) {
497         /* We can resolve the label */
498         StudyExprInternal (ULabResolve (Expr->V.Val), D);
499     } else {
500         ED_Invalidate (D);
501     }
502 }
503
504
505
506 static void StudyPlus (ExprNode* Expr, ExprDesc* D)
507 /* Study an EXPR_PLUS binary expression node */
508 {
509     ExprDesc Right;
510
511     /* Study the left side of the expression */
512     StudyExprInternal (Expr->Left, D);
513
514     /* Study the right side of the expression */
515     ED_Init (&Right);
516     StudyExprInternal (Expr->Right, &Right);
517
518     /* Check if we can handle the operation */
519     if (ED_IsValid (D) || ED_IsValid (&Right)) {
520
521         /* Add both */
522         ED_Add (D, &Right);
523
524     } else {
525
526         /* Cannot evaluate */
527         ED_Invalidate (D);
528
529         /* Merge references and update address size */
530         ED_MergeRefs (D, &Right);
531         ED_UpdateAddrSize (D, Right.AddrSize);
532
533     }
534
535     /* Done */
536     ED_Done (&Right);
537 }
538
539
540
541 static void StudyMinus (ExprNode* Expr, ExprDesc* D)
542 /* Study an EXPR_MINUS binary expression node */
543 {
544     ExprDesc Right;
545
546     /* Study the left side of the expression */
547     StudyExprInternal (Expr->Left, D);
548
549     /* Study the right side of the expression */
550     ED_Init (&Right);
551     StudyExprInternal (Expr->Right, &Right);
552
553     /* Check if we can handle the operation */
554     if (ED_IsValid (D) || ED_IsValid (&Right)) {
555
556         /* Subtract both */
557         ED_Neg (&Right);
558         ED_Add (D, &Right);
559
560     } else {
561
562         /* Cannot evaluate */
563         ED_Invalidate (D);
564
565         /* Merge references and update address size */
566         ED_MergeRefs (D, &Right);
567         ED_UpdateAddrSize (D, Right.AddrSize);
568
569     }
570
571     /* Done */
572     ED_Done (&Right);
573 }
574
575
576
577 static void StudyMul (ExprNode* Expr, ExprDesc* D)
578 /* Study an EXPR_MUL binary expression node */
579 {
580     ExprDesc Right;
581
582     /* Study the left side of the expression */
583     StudyExprInternal (Expr->Left, D);
584
585     /* Study the right side of the expression */
586     ED_Init (&Right);
587     StudyExprInternal (Expr->Right, &Right);
588
589     /* We can handle the operation if at least one of both operands is const
590      * and the other one is valid.
591      */
592     if (ED_IsConst (D) && ED_IsValid (&Right)) {
593
594         /* Multiplicate both, result goes into Right */
595         ED_Mul (&Right, D);
596
597         /* Move result into D */
598         ED_Move (&Right, D);
599
600     } else if (ED_IsConst (&Right) && ED_IsValid (D)) {
601
602         /* Multiplicate both */
603         ED_Mul (D, &Right);
604
605     } else {
606
607         /* Cannot handle this operation */
608         ED_Invalidate (D);
609
610     }
611
612     /* If we could not handle the op, merge references and update address size */
613     if (!ED_IsValid (D)) {
614         ED_MergeRefs (D, &Right);
615         ED_UpdateAddrSize (D, Right.AddrSize);
616     }
617
618     /* Done */
619     ED_Done (&Right);
620 }
621
622
623
624 static void StudyDiv (ExprNode* Expr, ExprDesc* D)
625 /* Study an EXPR_DIV binary expression node */
626 {
627     /* Use helper function */
628     StudyBinaryExpr (Expr, D);
629
630     /* If the result is valid, apply the operation */
631     if (ED_IsValid (D)) {
632         if (D->Right == 0) {
633             Error ("Division by zero");
634             ED_Invalidate (D);
635         } else {
636             D->Val /= D->Right;
637         }
638     }
639 }
640
641
642
643 static void StudyMod (ExprNode* Expr, ExprDesc* D)
644 /* Study an EXPR_MOD binary expression node */
645 {
646     /* Use helper function */
647     StudyBinaryExpr (Expr, D);
648
649     /* If the result is valid, apply the operation */
650     if (ED_IsValid (D)) {
651         if (D->Right == 0) {
652             Error ("Modulo operation with zero");
653             ED_Invalidate (D);
654         } else {
655             D->Val %= D->Right;
656         }
657     }
658 }
659
660
661
662 static void StudyOr (ExprNode* Expr, ExprDesc* D)
663 /* Study an EXPR_OR binary expression node */
664 {
665     /* Use helper function */
666     StudyBinaryExpr (Expr, D);
667
668     /* If the result is valid, apply the operation */
669     if (ED_IsValid (D)) {
670         D->Val |= D->Right;
671     }
672 }
673
674
675
676 static void StudyXor (ExprNode* Expr, ExprDesc* D)
677 /* Study an EXPR_XOR binary expression node */
678 {
679     /* Use helper function */
680     StudyBinaryExpr (Expr, D);
681
682     /* If the result is valid, apply the operation */
683     if (ED_IsValid (D)) {
684         D->Val ^= D->Right;
685     }
686 }
687
688
689
690 static void StudyAnd (ExprNode* Expr, ExprDesc* D)
691 /* Study an EXPR_AND binary expression node */
692 {
693     /* Use helper function */
694     StudyBinaryExpr (Expr, D);
695
696     /* If the result is valid, apply the operation */
697     if (ED_IsValid (D)) {
698         D->Val &= D->Right;
699     }
700 }
701
702
703
704 static void StudyShl (ExprNode* Expr, ExprDesc* D)
705 /* Study an EXPR_SHL binary expression node */
706 {
707     /* Use helper function */
708     StudyBinaryExpr (Expr, D);
709
710     /* If the result is valid, apply the operation */
711     if (ED_IsValid (D)) {
712         D->Val = shl_l (D->Val, D->Right);
713     }
714 }
715
716
717
718 static void StudyShr (ExprNode* Expr, ExprDesc* D)
719 /* Study an EXPR_SHR binary expression node */
720 {
721     /* Use helper function */
722     StudyBinaryExpr (Expr, D);
723
724     /* If the result is valid, apply the operation */
725     if (ED_IsValid (D)) {
726         D->Val = shr_l (D->Val, D->Right);
727     }
728 }
729
730
731
732 static void StudyEQ (ExprNode* Expr, ExprDesc* D)
733 /* Study an EXPR_EQ binary expression node */
734 {
735     /* Use helper function */
736     StudyBinaryExpr (Expr, D);
737
738     /* If the result is valid, apply the operation */
739     if (ED_IsValid (D)) {
740         D->Val = (D->Val == D->Right);
741     }
742
743     /* In any case, the result is 0 or 1 */
744     D->AddrSize = ADDR_SIZE_ZP;
745 }
746
747
748
749 static void StudyNE (ExprNode* Expr, ExprDesc* D)
750 /* Study an EXPR_NE binary expression node */
751 {
752     /* Use helper function */
753     StudyBinaryExpr (Expr, D);
754
755     /* If the result is valid, apply the operation */
756     if (ED_IsValid (D)) {
757         D->Val = (D->Val != D->Right);
758     }
759
760     /* In any case, the result is 0 or 1 */
761     D->AddrSize = ADDR_SIZE_ZP;
762 }
763
764
765
766 static void StudyLT (ExprNode* Expr, ExprDesc* D)
767 /* Study an EXPR_LT binary expression node */
768 {
769     /* Use helper function */
770     StudyBinaryExpr (Expr, D);
771
772     /* If the result is valid, apply the operation */
773     if (ED_IsValid (D)) {
774         D->Val = (D->Val < D->Right);
775     }
776
777     /* In any case, the result is 0 or 1 */
778     D->AddrSize = ADDR_SIZE_ZP;
779 }
780
781
782
783 static void StudyGT (ExprNode* Expr, ExprDesc* D)
784 /* Study an EXPR_GT binary expression node */
785 {
786     /* Use helper function */
787     StudyBinaryExpr (Expr, D);
788
789     /* If the result is valid, apply the operation */
790     if (ED_IsValid (D)) {
791         D->Val = (D->Val > D->Right);
792     }
793
794     /* In any case, the result is 0 or 1 */
795     D->AddrSize = ADDR_SIZE_ZP;
796 }
797
798
799
800 static void StudyLE (ExprNode* Expr, ExprDesc* D)
801 /* Study an EXPR_LE binary expression node */
802 {
803     /* Use helper function */
804     StudyBinaryExpr (Expr, D);
805
806     /* If the result is valid, apply the operation */
807     if (ED_IsValid (D)) {
808         D->Val = (D->Val <= D->Right);
809     }
810
811     /* In any case, the result is 0 or 1 */
812     D->AddrSize = ADDR_SIZE_ZP;
813 }
814
815
816
817 static void StudyGE (ExprNode* Expr, ExprDesc* D)
818 /* Study an EXPR_GE binary expression node */
819 {
820     /* Use helper function */
821     StudyBinaryExpr (Expr, D);
822
823     /* If the result is valid, apply the operation */
824     if (ED_IsValid (D)) {
825         D->Val = (D->Val >= D->Right);
826     }
827
828     /* In any case, the result is 0 or 1 */
829     D->AddrSize = ADDR_SIZE_ZP;
830 }
831
832
833
834 static void StudyBoolAnd (ExprNode* Expr, ExprDesc* D)
835 /* Study an EXPR_BOOLAND binary expression node */
836 {
837     StudyExprInternal (Expr->Left, D);
838     if (ED_IsConst (D)) {
839         if (D->Val != 0) {   /* Shortcut op */
840             ED_Done (D);
841             ED_Init (D);
842             StudyExprInternal (Expr->Right, D);
843             if (ED_IsConst (D)) {
844                 D->Val = (D->Val != 0);
845             } else {
846                 ED_Invalidate (D);
847             }
848         }
849     } else {
850         ED_Invalidate (D);
851     }
852
853     /* In any case, the result is 0 or 1 */
854     D->AddrSize = ADDR_SIZE_ZP;
855 }
856
857
858
859 static void StudyBoolOr (ExprNode* Expr, ExprDesc* D)
860 /* Study an EXPR_BOOLOR binary expression node */
861 {
862     StudyExprInternal (Expr->Left, D);
863     if (ED_IsConst (D)) {
864         if (D->Val == 0) {   /* Shortcut op */
865             ED_Done (D);
866             ED_Init (D);
867             StudyExprInternal (Expr->Right, D);
868             if (ED_IsConst (D)) {
869                 D->Val = (D->Val != 0);
870             } else {
871                 ED_Invalidate (D);
872             }
873         } else {
874             D->Val = 1;
875         }
876     } else {
877         ED_Invalidate (D);
878     }
879
880     /* In any case, the result is 0 or 1 */
881     D->AddrSize = ADDR_SIZE_ZP;
882 }
883
884
885
886 static void StudyBoolXor (ExprNode* Expr, ExprDesc* D)
887 /* Study an EXPR_BOOLXOR binary expression node */
888 {
889     /* Use helper function */
890     StudyBinaryExpr (Expr, D);
891
892     /* If the result is valid, apply the operation */
893     if (ED_IsValid (D)) {
894         D->Val = (D->Val != 0) ^ (D->Right != 0);
895     }
896
897     /* In any case, the result is 0 or 1 */
898     D->AddrSize = ADDR_SIZE_ZP;
899 }
900
901
902
903 static void StudyUnaryMinus (ExprNode* Expr, ExprDesc* D)
904 /* Study an EXPR_UNARY_MINUS expression node */
905 {
906     /* Study the expression */
907     StudyExprInternal (Expr->Left, D);
908
909     /* If it is valid, negate it */
910     if (ED_IsValid (D)) {
911         ED_Neg (D);
912     }
913 }
914
915
916
917 static void StudyNot (ExprNode* Expr, ExprDesc* D)
918 /* Study an EXPR_NOT expression node */
919 {
920     /* Study the expression */
921     StudyExprInternal (Expr->Left, D);
922
923     /* We can handle only const expressions */
924     if (ED_IsConst (D)) {
925         D->Val = ~D->Val;
926     } else {
927         ED_Invalidate (D);
928     }
929 }
930
931
932
933 static void StudySwap (ExprNode* Expr, ExprDesc* D)
934 /* Study an EXPR_SWAP expression node */
935 {
936     /* Study the expression */
937     StudyExprInternal (Expr->Left, D);
938
939     /* We can handle only const expressions */
940     if (ED_IsConst (D)) {
941         D->Val = (D->Val & ~0xFFFFUL) | ((D->Val >> 8) & 0xFF) | ((D->Val << 8) & 0xFF00);
942     } else {
943         ED_Invalidate (D);
944     }
945 }
946
947
948
949 static void StudyBoolNot (ExprNode* Expr, ExprDesc* D)
950 /* Study an EXPR_BOOLNOT expression node */
951 {
952     /* Study the expression */
953     StudyExprInternal (Expr->Left, D);
954
955     /* We can handle only const expressions */
956     if (ED_IsConst (D)) {
957         D->Val = (D->Val == 0);
958     } else {
959         ED_Invalidate (D);
960     }
961
962     /* In any case, the result is 0 or 1 */
963     D->AddrSize = ADDR_SIZE_ZP;
964 }
965
966
967
968 static void StudyByte0 (ExprNode* Expr, ExprDesc* D)
969 /* Study an EXPR_BYTE0 expression node */
970 {
971     /* Study the expression */
972     StudyExprInternal (Expr->Left, D);
973
974     /* We can handle only const expressions */
975     if (ED_IsConst (D)) {
976         D->Val = (D->Val & 0xFF);
977     } else {
978         ED_Invalidate (D);
979     }
980
981     /* In any case, the result is a zero page expression */
982     D->AddrSize = ADDR_SIZE_ZP;
983 }
984
985
986
987 static void StudyByte1 (ExprNode* Expr, ExprDesc* D)
988 /* Study an EXPR_BYTE1 expression node */
989 {
990     /* Study the expression */
991     StudyExprInternal (Expr->Left, D);
992
993     /* We can handle only const expressions */
994     if (ED_IsConst (D)) {
995         D->Val = (D->Val >> 8) & 0xFF;
996     } else {
997         ED_Invalidate (D);
998     }
999
1000     /* In any case, the result is a zero page expression */
1001     D->AddrSize = ADDR_SIZE_ZP;
1002 }
1003
1004
1005
1006 static void StudyByte2 (ExprNode* Expr, ExprDesc* D)
1007 /* Study an EXPR_BYTE2 expression node */
1008 {
1009     /* Study the expression */
1010     StudyExprInternal (Expr->Left, D);
1011
1012     /* We can handle only const expressions */
1013     if (ED_IsConst (D)) {
1014         D->Val = (D->Val >> 16) & 0xFF;
1015     } else {
1016         ED_Invalidate (D);
1017     }
1018
1019     /* In any case, the result is a zero page expression */
1020     D->AddrSize = ADDR_SIZE_ZP;
1021 }
1022
1023
1024
1025 static void StudyByte3 (ExprNode* Expr, ExprDesc* D)
1026 /* Study an EXPR_BYTE3 expression node */
1027 {
1028     /* Study the expression */
1029     StudyExprInternal (Expr->Left, D);
1030
1031     /* We can handle only const expressions */
1032     if (ED_IsConst (D)) {
1033         D->Val = (D->Val >> 24) & 0xFF;
1034     } else {
1035         ED_Invalidate (D);
1036     }
1037
1038     /* In any case, the result is a zero page expression */
1039     D->AddrSize = ADDR_SIZE_ZP;
1040 }
1041
1042
1043
1044 static void StudyWord0 (ExprNode* Expr, ExprDesc* D)
1045 /* Study an EXPR_WORD0 expression node */
1046 {
1047     /* Study the expression */
1048     StudyExprInternal (Expr->Left, D);
1049
1050     /* We can handle only const expressions */
1051     if (ED_IsConst (D)) {
1052         D->Val = (D->Val & 0xFFFFL);
1053     } else {
1054         ED_Invalidate (D);
1055     }
1056
1057     /* In any case, the result is an absolute expression */
1058     D->AddrSize = ADDR_SIZE_ABS;
1059 }
1060
1061
1062
1063 static void StudyWord1 (ExprNode* Expr, ExprDesc* D)
1064 /* Study an EXPR_WORD1 expression node */
1065 {
1066     /* Study the expression */
1067     StudyExprInternal (Expr->Left, D);
1068
1069     /* We can handle only const expressions */
1070     if (ED_IsConst (D)) {
1071         D->Val = (D->Val >> 16) & 0xFFFFL;
1072     } else {
1073         ED_Invalidate (D);
1074     }
1075
1076     /* In any case, the result is an absolute expression */
1077     D->AddrSize = ADDR_SIZE_ABS;
1078 }
1079
1080
1081
1082 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
1083 /* Study an expression tree and place the contents into D */
1084 {
1085     /* Study this expression node */
1086     switch (Expr->Op) {
1087
1088         case EXPR_LITERAL:
1089             StudyLiteral (Expr, D);
1090             break;
1091
1092         case EXPR_SYMBOL:
1093             StudySymbol (Expr, D);
1094             break;
1095
1096         case EXPR_SECTION:
1097             StudySection (Expr, D);
1098             break;
1099
1100         case EXPR_ULABEL:
1101             StudyULabel (Expr, D);
1102             break;
1103
1104         case EXPR_PLUS:
1105             StudyPlus (Expr, D);
1106             break;
1107
1108         case EXPR_MINUS:
1109             StudyMinus (Expr, D);
1110             break;
1111
1112         case EXPR_MUL:
1113             StudyMul (Expr, D);
1114             break;
1115
1116         case EXPR_DIV:
1117             StudyDiv (Expr, D);
1118             break;
1119
1120         case EXPR_MOD:
1121             StudyMod (Expr, D);
1122             break;
1123
1124         case EXPR_OR:
1125             StudyOr (Expr, D);
1126             break;
1127
1128         case EXPR_XOR:
1129             StudyXor (Expr, D);
1130             break;
1131
1132         case EXPR_AND:
1133             StudyAnd (Expr, D);
1134             break;
1135
1136         case EXPR_SHL:
1137             StudyShl (Expr, D);
1138             break;
1139
1140         case EXPR_SHR:
1141             StudyShr (Expr, D);
1142             break;
1143
1144         case EXPR_EQ:
1145             StudyEQ (Expr, D);
1146             break;
1147
1148         case EXPR_NE:
1149             StudyNE (Expr, D);
1150             break;
1151
1152         case EXPR_LT:
1153             StudyLT (Expr, D);
1154             break;
1155
1156         case EXPR_GT:
1157             StudyGT (Expr, D);
1158             break;
1159
1160         case EXPR_LE:
1161             StudyLE (Expr, D);
1162             break;
1163
1164         case EXPR_GE:
1165             StudyGE (Expr, D);
1166             break;
1167
1168         case EXPR_BOOLAND:
1169             StudyBoolAnd (Expr, D);
1170             break;
1171
1172         case EXPR_BOOLOR:
1173             StudyBoolOr (Expr, D);
1174             break;
1175
1176         case EXPR_BOOLXOR:
1177             StudyBoolXor (Expr, D);
1178             break;
1179
1180         case EXPR_UNARY_MINUS:
1181             StudyUnaryMinus (Expr, D);
1182             break;
1183
1184         case EXPR_NOT:
1185             StudyNot (Expr, D);
1186             break;
1187
1188         case EXPR_SWAP:
1189             StudySwap (Expr, D);
1190             break;
1191
1192         case EXPR_BOOLNOT:
1193             StudyBoolNot (Expr, D);
1194             break;
1195
1196         case EXPR_BYTE0:
1197             StudyByte0 (Expr, D);
1198             break;
1199
1200         case EXPR_BYTE1:
1201             StudyByte1 (Expr, D);
1202             break;
1203
1204         case EXPR_BYTE2:
1205             StudyByte2 (Expr, D);
1206             break;
1207
1208         case EXPR_BYTE3:
1209             StudyByte3 (Expr, D);
1210             break;
1211
1212         case EXPR_WORD0:
1213             StudyWord0 (Expr, D);
1214             break;
1215
1216         case EXPR_WORD1:
1217             StudyWord1 (Expr, D);
1218             break;
1219
1220         default:
1221             Internal ("Unknown Op type: %u", Expr->Op);
1222             break;
1223     }
1224 }
1225
1226
1227
1228 void StudyExpr (ExprNode* Expr, ExprDesc* D)
1229 /* Study an expression tree and place the contents into D */
1230 {
1231     unsigned I;
1232
1233     /* Call the internal function */
1234     StudyExprInternal (Expr, D);
1235
1236     /* Remove symbol references with count zero */
1237     I = 0;
1238     while (I < D->SymCount) {
1239         if (D->SymRef[I].Count == 0) {
1240             /* Delete the entry */
1241             --D->SymCount;
1242             memmove (D->SymRef + I, D->SymRef + I + 1,
1243                      (D->SymCount - I) * sizeof (D->SymRef[0]));
1244         } else {
1245             /* Next entry */
1246             ++I;
1247         }
1248     }
1249
1250     /* Remove section references with count zero */
1251     I = 0;
1252     while (I < D->SecCount) {
1253         if (D->SecRef[I].Count == 0) {
1254             /* Delete the entry */
1255             --D->SecCount;
1256             memmove (D->SecRef + I, D->SecRef + I + 1,
1257                      (D->SecCount - I) * sizeof (D->SecRef[0]));
1258         } else {
1259             /* Next entry */
1260             ++I;
1261         }
1262     }
1263
1264     /* If we don't have an address size, assign one of the expression is a
1265      * constant.
1266      */
1267     if (D->AddrSize == ADDR_SIZE_DEFAULT) {
1268         if (ED_IsConst (D)) {
1269             if ((D->Val & ~0xFFL) == 0) {
1270                 D->AddrSize = ADDR_SIZE_ZP;
1271             } else if ((D->Val & ~0xFFFFL) == 0) {
1272                 D->AddrSize = ADDR_SIZE_ABS;
1273             } else if ((D->Val & 0xFFFFFFL) == 0) {
1274                 D->AddrSize = ADDR_SIZE_FAR;
1275             } else {
1276                 D->AddrSize = ADDR_SIZE_LONG;
1277             }
1278         }
1279     }
1280
1281 #if 0
1282     printf ("StudyExpr: "); DumpExpr (Expr, SymResolve);
1283     if (!ED_IsValid (D)) {
1284         printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize));
1285     } else {
1286         printf ("Valid:   %s\n", AddrSizeToStr (D->AddrSize));
1287         printf ("%u symbols:\n", D->SymCount);
1288         printf ("%u sections:\n", D->SecCount);
1289     }
1290 #endif
1291 }
1292
1293
1294