예제 #1
0
 virtual void VisitExpr( const  SymbolicExpr& v) 
  { 
     SymbolicVal in1, fr1;
     bool _hasfrac = hasfrac;
     SymbolicExpr::OpdIterator opds = v.GetOpdIterator();
     for ( ; !opds.ReachEnd(); ++opds) {
        if (operator()(v.Term2Val(*opds), inp, frp)) {
              _hasfrac = true;
                break;  
        }
     }
     if (opds.ReachEnd()) {
        if (inp != 0) *inp = v;
     }
     else {
         if (inp == 0 && frp == 0)
             return;
         SymbolicExpr* inv = (inp == 0)? 0 : v.DistributeExpr(SYMOP_NIL, SymbolicVal());
         SymbolicExpr* frv = (frp == 0)? 0 : v.DistributeExpr(SYMOP_NIL, SymbolicVal());
         SymbolicExpr::OpdIterator opd1 = v.GetOpdIterator();
         for ( ; opd1 != opds ; ++opd1) {
             if (inv != 0)
                 inv->AddOpd(*opd1);
             if (frv != 0)
                 frv->AddOpd(*opd1);
           }
          if (inv != 0)
              inv->ApplyOpd(*inp);
          if (frv != 0)
              frv->ApplyOpd(*frp);
          for (++opd1; !opd1.ReachEnd(); ++opd1) {
             SymbolicVal cur = v.Term2Val(*opd1);
             if (operator()(cur, inp, frp)) {
                if (inv != 0)
                    inv->ApplyOpd(*inp);
                if (frv != 0)
                    frv->ApplyOpd(*frp);
             }
             else {
                if (inv != 0)
                    inv->AddOpd(*opd1);
                if (frv != 0)
                    frv->AddOpd(*opd1);
             }
          }   
          if (inp != 0) 
               *inp = GetExprVal(inv);
          if (frp != 0)
               *frp = GetExprVal(frv);
    }
    hasfrac = _hasfrac;
  }
예제 #2
0
파일: segments.c 프로젝트: cc65/cc65
int IsBSSType (Segment* S)
/* Check if the given segment is a BSS style segment, that is, it does not
** contain non-zero data.
*/
{
    /* Loop over all sections */
    unsigned I;
    for (I = 0; I < CollCount (&S->Sections); ++I) {

        /* Get the next section */
        Section* Sec = CollAtUnchecked (&S->Sections, I);

        /* Loop over all fragments */
        Fragment* F = Sec->FragRoot;
        while (F) {
            if (F->Type == FRAG_LITERAL) {
                unsigned char* Data = F->LitBuf;
                unsigned long Count = F->Size;
                while (Count--) {
                    if (*Data++ != 0) {
                        return 0;
                    }
                }
            } else if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) {
                if (GetExprVal (F->Expr) != 0) {
                    return 0;
                }
            }
            F = F->Next;
        }
    }
    return 1;
}
예제 #3
0
long GetExportVal (const Export* E)
/* Get the value of this export */
{
    if (E->Expr == 0) {
     	/* OOPS */
       	Internal ("`%s' is an undefined external", GetString (E->Name));
    }
    return GetExprVal (E->Expr);
}
예제 #4
0
파일: asserts.c 프로젝트: eakmeister/cc65
void CheckAssertions (void)
/* Check all assertions */
{
    unsigned I;

    /* Walk over all assertions */
    for (I = 0; I < CollCount (&Assertions); ++I) {

        const LineInfo* LI;
        const char* Module;
        unsigned Line;

        /* Get the assertion */
        Assertion* A = CollAtUnchecked (&Assertions, I);

        /* Ignore assertions that shouldn't be handled at link time */
        if (!AssertAtLinkTime (A->Action)) {
            continue;
        }

        /* Retrieve the relevant line info for this assertion */
        LI = CollConstAt (&A->LineInfos, 0);

        /* Get file name and line number from the source */
        Module = GetSourceName (LI);
        Line   = GetSourceLine (LI);

        /* If the expression is not constant, we're not able to handle it */
        if (!IsConstExpr (A->Expr)) {
            Warning ("Cannot evaluate assertion in module `%s', line %u",
                     Module, Line);
        } else if (GetExprVal (A->Expr) == 0) {

            /* Assertion failed */
            const char* Message = GetString (A->Msg);

            switch (A->Action) {

                case ASSERT_ACT_WARN:
                case ASSERT_ACT_LDWARN:
                    Warning ("%s(%u): %s", Module, Line, Message);
                    break;

                case ASSERT_ACT_ERROR:
                case ASSERT_ACT_LDERROR:
                    Error ("%s(%u): %s", Module, Line, Message);
                    break;

                default:
                    Internal ("Invalid assertion action (%u) in module `%s', "
                              "line %u (file corrupt?)",
                              A->Action, Module, Line);
                    break;
            }
        }
    }
}
예제 #5
0
파일: segments.c 프로젝트: cc65/cc65
unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size)
/* Write a supposedly constant expression to the target file. Do a range
** check and return one of the SEG_EXPR_xxx codes.
*/
{
    static const unsigned long U_Hi[4] = {
        0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL
    };
    static const long S_Hi[4] = {
        0x0000007FL, 0x00007FFFL, 0x007FFFFFL, 0x7FFFFFFFL
    };
    static const long S_Lo[4] = {
        ~0x0000007FL, ~0x00007FFFL, ~0x007FFFFFL, ~0x7FFFFFFFL
    };


    /* Get the expression value */
    long Val = GetExprVal (E);

    /* Check the size */
    CHECK (Size >= 1 && Size <= 4);

    /* Check for a range error */
    if (Signed) {
        if (Val > S_Hi[Size-1] || Val < S_Lo[Size-1]) {
            /* Range error */
            return SEG_EXPR_RANGE_ERROR;
        }
    } else {
        if (((unsigned long)Val) > U_Hi[Size-1]) {
            /* Range error */
            return SEG_EXPR_RANGE_ERROR;
        }
    }

    /* Write the value to the file */
    WriteVal (F, Val, Size);

    /* Success */
    return SEG_EXPR_OK;
}
예제 #6
0
int IsConstExpr (ExprNode* Root)
/* Return true if the given expression is a constant expression, that is, one
 * with no references to external symbols.
 */
{
    int         Const;
    Export*     E;
    Section*    S;
    MemoryArea* M;

    if (EXPR_IS_LEAF (Root->Op)) {
        switch (Root->Op) {

            case EXPR_LITERAL:
                return 1;

            case EXPR_SYMBOL:
                /* Get the referenced export */
                E = GetExprExport (Root);
                /* If this export has a mark set, we've already encountered it.
                 * This means that the export is used to define it's own value,
                 * which in turn means, that we have a circular reference.
                 */
                if (ExportHasMark (E)) {
                    CircularRefError (E);
                    Const = 0;
                } else {
                    MarkExport (E);
                    Const = IsConstExport (E);
                    UnmarkExport (E);
                }
                return Const;

            case EXPR_SECTION:
                /* A section expression is const if the segment it is in is
                 * not relocatable and already placed.
                 */
                S = GetExprSection (Root);
                M = S->Seg->MemArea;
                return M != 0 && (M->Flags & MF_PLACED) != 0 && !M->Relocatable;

            case EXPR_SEGMENT:
                /* A segment is const if it is not relocatable and placed */
                M = Root->V.Seg->MemArea;
                return M != 0 && (M->Flags & MF_PLACED) != 0 && !M->Relocatable;

            case EXPR_MEMAREA:
                /* A memory area is const if it is not relocatable and placed */
                return !Root->V.Mem->Relocatable &&
                       (Root->V.Mem->Flags & MF_PLACED);

            default:
                /* Anything else is not const */
                return 0;

        }

    } else if (EXPR_IS_UNARY (Root->Op)) {

        SegExprDesc D;

        /* Special handling for the BANK pseudo function */
        switch (Root->Op) {

            case EXPR_BANK:
                /* Get segment references for the expression */
                GetSegExprVal (Root->Left, &D);

                /* The expression is const if the expression contains exactly
                 * one segment that is assigned to a memory area which has a
                 * bank attribute that is constant.
                 */
                return (D.TooComplex              == 0  &&
                        D.Seg                     != 0  &&
                        D.Seg->MemArea            != 0  &&
                        D.Seg->MemArea->BankExpr  != 0  &&
                        IsConstExpr (D.Seg->MemArea->BankExpr));

            default:
                /* All others handled normal */
                return IsConstExpr (Root->Left);

        }

    } else {

        /* We must handle shortcut boolean expressions here */
        switch (Root->Op) {

            case EXPR_BOOLAND:
                if (IsConstExpr (Root->Left)) {
                    /* lhs is const, if it is zero, don't eval right */
                    if (GetExprVal (Root->Left) == 0) {
                        return 1;
                    } else {
                        return IsConstExpr (Root->Right);
                    }
                } else {
                    /* lhs not const --> tree not const */
                    return 0;
                }
                break;

            case EXPR_BOOLOR:
                if (IsConstExpr (Root->Left)) {
                    /* lhs is const, if it is not zero, don't eval right */
                    if (GetExprVal (Root->Left) != 0) {
                        return 1;
                    } else {
                        return IsConstExpr (Root->Right);
                    }
                } else {
                    /* lhs not const --> tree not const */
                    return 0;
                }
                break;

            default:
                /* All others are handled normal */
                return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
        }
    }
}
예제 #7
0
long GetExprVal (ExprNode* Expr)
/* Get the value of a constant expression */
{
    long        Right;
    long        Left;
    long        Val;
    Section*    S;
    Export*     E;
    SegExprDesc D;

    switch (Expr->Op) {

        case EXPR_LITERAL:
            return Expr->V.IVal;

        case EXPR_SYMBOL:
            /* Get the referenced export */
            E = GetExprExport (Expr);
            /* If this export has a mark set, we've already encountered it.
             * This means that the export is used to define it's own value,
             * which in turn means, that we have a circular reference.
             */
            if (ExportHasMark (E)) {
                CircularRefError (E);
                Val = 0;
            } else {
                MarkExport (E);
                Val = GetExportVal (E);
                UnmarkExport (E);
            }
            return Val;

        case EXPR_SECTION:
            S = GetExprSection (Expr);
            return S->Offs + S->Seg->PC;

        case EXPR_SEGMENT:
            return Expr->V.Seg->PC;

        case EXPR_MEMAREA:
            return Expr->V.Mem->Start;

        case EXPR_PLUS:
            return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);

        case EXPR_MINUS:
            return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);

        case EXPR_MUL:
            return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);

        case EXPR_DIV:
            Left  = GetExprVal (Expr->Left);
            Right = GetExprVal (Expr->Right);
            if (Right == 0) {
                Error ("Division by zero");
            }
            return Left / Right;

        case EXPR_MOD:
            Left  = GetExprVal (Expr->Left);
            Right = GetExprVal (Expr->Right);
            if (Right == 0) {
                Error ("Modulo operation with zero");
            }
            return Left % Right;

        case EXPR_OR:
            return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);

        case EXPR_XOR:
            return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);

        case EXPR_AND:
            return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);

        case EXPR_SHL:
            return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);

        case EXPR_SHR:
            return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);

        case EXPR_EQ:
            return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));

        case EXPR_NE:
            return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));

        case EXPR_LT:
            return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));

        case EXPR_GT:
            return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));

        case EXPR_LE:
            return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));

        case EXPR_GE:
            return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));

        case EXPR_BOOLAND:
            return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);

        case EXPR_BOOLOR:
            return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);

        case EXPR_BOOLXOR:
            return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);

        case EXPR_MAX:
            Left = GetExprVal (Expr->Left);
            Right = GetExprVal (Expr->Right);
            return (Left > Right)? Left : Right;

        case EXPR_MIN:
            Left = GetExprVal (Expr->Left);
            Right = GetExprVal (Expr->Right);
            return (Left < Right)? Left : Right;

        case EXPR_UNARY_MINUS:
            return -GetExprVal (Expr->Left);

        case EXPR_NOT:
            return ~GetExprVal (Expr->Left);

        case EXPR_SWAP:
            Left = GetExprVal (Expr->Left);
            return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);

        case EXPR_BOOLNOT:
            return !GetExprVal (Expr->Left);

        case EXPR_BANK:
            GetSegExprVal (Expr->Left, &D);
            if (D.TooComplex || D.Seg == 0) {
                Error ("Argument for .BANK is not segment relative or too complex");
            }
            if (D.Seg->MemArea == 0) {
                Error ("Segment `%s' is referenced by .BANK but "
                       "not assigned to a memory area",
                       GetString (D.Seg->Name));
            }
            if (D.Seg->MemArea->BankExpr == 0) {
                Error ("Memory area `%s' is referenced by .BANK but "
                       "has no BANK attribute",
                       GetString (D.Seg->MemArea->Name));
            }
            return GetExprVal (D.Seg->MemArea->BankExpr);

        case EXPR_BYTE0:
            return GetExprVal (Expr->Left) & 0xFF;

        case EXPR_BYTE1:
            return (GetExprVal (Expr->Left) >> 8) & 0xFF;

        case EXPR_BYTE2:
            return (GetExprVal (Expr->Left) >> 16) & 0xFF;

        case EXPR_BYTE3:
            return (GetExprVal (Expr->Left) >> 24) & 0xFF;

        case EXPR_WORD0:
            return GetExprVal (Expr->Left) & 0xFFFF;

        case EXPR_WORD1:
            return (GetExprVal (Expr->Left) >> 16) & 0xFFFF;

        case EXPR_FARADDR:
            return GetExprVal (Expr->Left) & 0xFFFFFF;

        case EXPR_DWORD:
            return GetExprVal (Expr->Left) & 0xFFFFFFFF;

        default:
            Internal ("Unknown expression Op type: %u", Expr->Op);
            /* NOTREACHED */
            return 0;
    }
}