1 /*****************************************************************************/
5 /* Expression evaluation for the ld65 linker */
9 /* (C) 1998-2011, 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 /*****************************************************************************/
51 /*****************************************************************************/
53 /*****************************************************************************/
57 ExprNode* NewExprNode (ObjData* O, unsigned char Op)
58 /* Create a new expression node */
60 /* Allocate fresh memory */
61 ExprNode* N = xmalloc (sizeof (ExprNode));
73 static void FreeExprNode (ExprNode* E)
82 void FreeExpr (ExprNode* Root)
83 /* Free the expression, Root is pointing to. */
86 FreeExpr (Root->Left);
87 FreeExpr (Root->Right);
94 int IsConstExpr (ExprNode* Root)
95 /* Return true if the given expression is a constant expression, that is, one
96 * with no references to external symbols.
103 if (EXPR_IS_LEAF (Root->Op)) {
110 /* Get the referenced export */
111 E = GetExprExport (Root);
112 /* If this export has a mark set, we've already encountered it.
113 * This means that the export is used to define it's own value,
114 * which in turn means, that we have a circular reference.
116 if (ExportHasMark (E)) {
117 CircularRefError (E);
121 Const = IsConstExport (E);
127 /* A section expression is const if the segment it is in is
128 * not relocatable and already placed.
130 S = GetExprSection (Root);
131 return !S->Seg->Relocatable && S->Seg->Placed;
134 /* A segment is const if it is not relocatable and placed */
135 return !Root->V.Seg->Relocatable && Root->V.Seg->Placed;
138 /* A memory area is const if it is not relocatable and placed */
139 return !Root->V.Mem->Relocatable &&
140 (Root->V.Mem->Flags & MF_PLACED);
143 /* Anything else is not const */
147 } else if (EXPR_IS_UNARY (Root->Op)) {
149 return IsConstExpr (Root->Left);
153 /* We must handle shortcut boolean expressions here */
157 if (IsConstExpr (Root->Left)) {
158 /* lhs is const, if it is zero, don't eval right */
159 if (GetExprVal (Root->Left) == 0) {
162 return IsConstExpr (Root->Right);
165 /* lhs not const --> tree not const */
171 if (IsConstExpr (Root->Left)) {
172 /* lhs is const, if it is not zero, don't eval right */
173 if (GetExprVal (Root->Left) != 0) {
176 return IsConstExpr (Root->Right);
179 /* lhs not const --> tree not const */
185 /* All others are handled normal */
186 return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
193 Import* GetExprImport (ExprNode* Expr)
194 /* Get the import data structure for a symbol expression node */
196 /* Check that this is really a symbol */
197 PRECONDITION (Expr->Op == EXPR_SYMBOL);
199 /* If we have an object file, get the import from it, otherwise
200 * (internally generated expressions), get the import from the
204 /* Return the Import */
205 return GetObjImport (Expr->Obj, Expr->V.ImpNum);
213 Export* GetExprExport (ExprNode* Expr)
214 /* Get the exported symbol for a symbol expression node */
216 /* Check that this is really a symbol */
217 PRECONDITION (Expr->Op == EXPR_SYMBOL);
219 /* Return the export for an import*/
220 return GetExprImport (Expr)->Exp;
225 Section* GetExprSection (ExprNode* Expr)
226 /* Get the segment for a section expression node */
228 /* Check that this is really a section node */
229 PRECONDITION (Expr->Op == EXPR_SECTION);
231 /* If we have an object file, get the section from it, otherwise
232 * (internally generated expressions), get the section from the
236 /* Return the export */
237 return CollAt (&Expr->Obj->Sections, Expr->V.SecNum);
245 long GetExprVal (ExprNode* Expr)
246 /* Get the value of a constant expression */
248 long Right, Left, Val;
258 /* Get the referenced export */
259 E = GetExprExport (Expr);
260 /* If this export has a mark set, we've already encountered it.
261 * This means that the export is used to define it's own value,
262 * which in turn means, that we have a circular reference.
264 if (ExportHasMark (E)) {
265 CircularRefError (E);
269 Val = GetExportVal (E);
275 S = GetExprSection (Expr);
276 return S->Offs + S->Seg->PC;
279 return Expr->V.Seg->PC;
282 return Expr->V.Mem->Start;
285 return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
288 return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
291 return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
294 Left = GetExprVal (Expr->Left);
295 Right = GetExprVal (Expr->Right);
297 Error ("Division by zero");
302 Left = GetExprVal (Expr->Left);
303 Right = GetExprVal (Expr->Right);
305 Error ("Modulo operation with zero");
310 return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
313 return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
316 return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
319 return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
322 return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
325 return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));
328 return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));
331 return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));
334 return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));
337 return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));
340 return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));
343 return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
346 return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
349 return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
352 Left = GetExprVal (Expr->Left);
353 Right = GetExprVal (Expr->Right);
354 return (Left > Right)? Left : Right;
357 Left = GetExprVal (Expr->Left);
358 Right = GetExprVal (Expr->Right);
359 return (Left < Right)? Left : Right;
361 case EXPR_UNARY_MINUS:
362 return -GetExprVal (Expr->Left);
365 return ~GetExprVal (Expr->Left);
368 Left = GetExprVal (Expr->Left);
369 return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
372 return !GetExprVal (Expr->Left);
375 return GetExprVal (Expr->Left) & 0xFF;
378 return (GetExprVal (Expr->Left) >> 8) & 0xFF;
381 return (GetExprVal (Expr->Left) >> 16) & 0xFF;
384 return (GetExprVal (Expr->Left) >> 24) & 0xFF;
387 return GetExprVal (Expr->Left) & 0xFFFF;
390 return (GetExprVal (Expr->Left) >> 16) & 0xFFFF;
393 Internal ("Unknown expression Op type: %u", Expr->Op);
401 static void GetSegExprValInternal (ExprNode* Expr, SegExprDesc* D, int Sign)
402 /* Check if the given expression consists of a segment reference and only
403 * constant values, additions and subtractions. If anything else is found,
404 * set D->TooComplex to true.
405 * Internal, recursive routine.
413 D->Val += (Sign * Expr->V.IVal);
417 /* Get the referenced export */
418 E = GetExprExport (Expr);
419 /* If this export has a mark set, we've already encountered it.
420 * This means that the export is used to define it's own value,
421 * which in turn means, that we have a circular reference.
423 if (ExportHasMark (E)) {
424 CircularRefError (E);
427 GetSegExprValInternal (E->Expr, D, Sign);
434 /* We cannot handle more than one segment reference in o65 */
437 /* Get the section from the expression */
438 Section* S = GetExprSection (Expr);
439 /* Remember the segment reference */
441 /* Add the offset of the section to the constant value */
442 D->Val += Sign * (S->Offs + D->Seg->PC);
448 /* We cannot handle more than one segment reference in o65 */
451 /* Remember the segment reference */
452 D->Seg = Expr->V.Seg;
453 /* Add the offset of the segment to the constant value */
454 D->Val += (Sign * D->Seg->PC);
459 GetSegExprValInternal (Expr->Left, D, Sign);
460 GetSegExprValInternal (Expr->Right, D, Sign);
464 GetSegExprValInternal (Expr->Left, D, Sign);
465 GetSegExprValInternal (Expr->Right, D, -Sign);
469 /* Expression contains illegal operators */
478 void GetSegExprVal (ExprNode* Expr, SegExprDesc* D)
479 /* Check if the given expression consists of a segment reference and only
480 * constant values, additions and subtractions. If anything else is found,
481 * set D->TooComplex to true. The function will initialize D.
484 /* Initialize the given structure */
489 /* Call our recursive calculation routine */
490 GetSegExprValInternal (Expr, D, 1);
495 ExprNode* LiteralExpr (long Val, ObjData* O)
496 /* Return an expression tree that encodes the given literal value */
498 ExprNode* Expr = NewExprNode (O, EXPR_LITERAL);
505 ExprNode* MemoryExpr (MemoryArea* Mem, long Offs, ObjData* O)
506 /* Return an expression tree that encodes an offset into a memory area */
510 ExprNode* Expr = NewExprNode (O, EXPR_MEMAREA);
514 Root = NewExprNode (O, EXPR_PLUS);
516 Root->Right = LiteralExpr (Offs, O);
526 ExprNode* SegmentExpr (Segment* Seg, long Offs, ObjData* O)
527 /* Return an expression tree that encodes an offset into a segment */
531 ExprNode* Expr = NewExprNode (O, EXPR_SEGMENT);
535 Root = NewExprNode (O, EXPR_PLUS);
537 Root->Right = LiteralExpr (Offs, O);
547 ExprNode* SectionExpr (Section* Sec, long Offs, ObjData* O)
548 /* Return an expression tree that encodes an offset into a section */
552 ExprNode* Expr = NewExprNode (O, EXPR_SECTION);
556 Root = NewExprNode (O, EXPR_PLUS);
558 Root->Right = LiteralExpr (Offs, O);
568 ExprNode* ReadExpr (FILE* F, ObjData* O)
569 /* Read an expression from the given file */
573 /* Read the node tag and handle NULL nodes */
574 unsigned char Op = Read8 (F);
575 if (Op == EXPR_NULL) {
579 /* Create a new node */
580 Expr = NewExprNode (O, Op);
582 /* Check the tag and handle the different expression types */
583 if (EXPR_IS_LEAF (Op)) {
587 Expr->V.IVal = Read32Signed (F);
591 /* Read the import number */
592 Expr->V.ImpNum = ReadVar (F);
596 /* Read the segment number */
597 Expr->V.SecNum = Read8 (F);
601 Error ("Invalid expression op: %02X", Op);
607 /* Not a leaf node */
608 Expr->Left = ReadExpr (F, O);
609 Expr->Right = ReadExpr (F, O);
613 /* Return the tree */
619 int EqualExpr (ExprNode* E1, ExprNode* E2)
620 /* Check if two expressions are identical. */
622 /* If one pointer is NULL, both must be NULL */
623 if ((E1 == 0) ^ (E2 == 0)) {
630 /* Both pointers not NULL, check OP */
631 if (E1->Op != E2->Op) {
635 /* OPs are identical, check data for leafs, or subtrees */
639 /* Value must be identical */
640 return (E1->V.IVal == E2->V.IVal);
643 /* Import must be identical */
644 return (GetExprImport (E1) == GetExprImport (E2));
647 /* Section must be identical */
648 return (GetExprSection (E1) == GetExprSection (E2));
651 /* Segment must be identical */
652 return (E1->V.Seg == E2->V.Seg);
655 /* Memory area must be identical */
656 return (E1->V.Mem == E2->V.Mem);
659 /* Not a leaf node */
660 return EqualExpr (E1->Left, E2->Left) && EqualExpr (E1->Right, E2->Right);