Example #1
0
static void
PrintConstantDecl(FILE *f, AST *ast)
{
    const char *name = ast->d.string;
    AST *expr = NULL;
    Symbol *sym;

    if (!IsConstExpr(ast)) {
        ERROR(ast, "%s is not constant", name);
        return;
    }
    sym = LookupSymbol(name);
    if (!sym) {
        ERROR(ast, "constant symbol %s not declared??", name);
        return;
    }
    expr = (AST *)sym->val;
    if (gl_ccode) {
        fprintf(f, "#define %s (", ast->d.string);
        PrintConstant(f, expr);
        fprintf(f, ")\n");
    } else {
        fprintf(f, "  static const int %s = ", ast->d.string);
        PrintConstant(f, expr);
        fprintf(f, ";\n");
    }
}
Example #2
0
static void SymReplaceExprRefs (SymEntry* S)
/* Replace the references to this symbol by a copy of the symbol expression */
{
    unsigned I;
    long     Val;

    /* Check if the expression is const and get its value */
    int IsConst = IsConstExpr (S->Expr, &Val);
    CHECK (IsConst);

    /* Loop over all references */
    for (I = 0; I < CollCount (&S->ExprRefs); ++I) {

        /* Get the expression node */
        ExprNode* E = CollAtUnchecked (&S->ExprRefs, I);

        /* Safety */
        CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == S);

        /* We cannot touch the root node, since there are pointers to it.
        ** Replace it by a literal node.
        */
        E->Op = EXPR_LITERAL;
        E->V.IVal = Val;
    }

    /* Remove all symbol references from the symbol */
    CollDeleteAll (&S->ExprRefs);
}
Example #3
0
int SymIsConst (const SymEntry* S, long* Val)
/* Return true if the given symbol has a constant value. If Val is not NULL
** and the symbol has a constant value, store it's value there.
*/
{
    /* Check for constness */
    return (SymHasExpr (S) && IsConstExpr (S->Expr, Val));
}
Example #4
0
long GetSymVal (SymEntry* S)
/* Return the value of a symbol assuming it's constant. FAIL will be called
** in case the symbol is undefined or not constant.
*/
{
    long Val;
    CHECK (S != 0 && SymHasExpr (S) && IsConstExpr (GetSymExpr (S), &Val));
    return Val;
}
Example #5
0
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;
            }
        }
    }
}
Example #6
0
int IsConstExport (const Export* E)
/* Return true if the expression associated with this export is const */
{
    if (E->Expr == 0) {
     	/* External symbols cannot be const */
     	return 0;
    } else {
        return IsConstExpr (E->Expr);
    }
}
Example #7
0
void CheckAssertions (void)
/* Check all assertions and evaluate the ones we can evaluate here. */
{
    unsigned I;

    /* Get the number of assertions */
    unsigned Count = CollCount (&Assertions);

    /* Check the assertions */
    for (I = 0; I < Count; ++I) {

        long Val;

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

        /* Ignore it, if it should only be evaluated by the linker */
        if (!AssertAtAsmTime (A->Action)) {
            continue;
        }

        /* Can we evaluate the expression? */
        if (IsConstExpr (A->Expr, &Val) && Val == 0) {
            /* Apply the action */
            const char* Msg = GetString (A->Msg);
            switch (A->Action) {

            case ASSERT_ACT_WARN:
                LIWarning (&A->LI, 0, "%s", Msg);
                break;

            case ASSERT_ACT_ERROR:
                LIError (&A->LI, "%s", Msg);
                break;

            default:
                Internal ("Illegal assert action specifier");
                break;
            }
        }
    }
}
Example #8
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);
        }
    }
}
Example #9
0
void DoConditionals (void)
/* Catch all for conditional directives */
{
    IfDesc* D;

    do {

        switch (CurTok.Tok) {

            case TOK_ELSE:
                D = GetCurrentIf ();

                /* Allow an .ELSE */
                ElseClause (D, ".ELSE");

                /* Remember the data for the .ELSE */
                if (D) {
                    ReleaseFullLineInfo (&D->LineInfos);
                    GetFullLineInfo (&D->LineInfos);
                    D->Name = ".ELSE";
                }

                /* Calculate the new overall condition */
                CalcOverallIfCond ();

                /* Skip .ELSE */
                NextTok ();
                ExpectSep ();
                break;

            case TOK_ELSEIF:
                D = GetCurrentIf ();
                /* Handle as if there was an .ELSE first */
                ElseClause (D, ".ELSEIF");

                /* Calculate the new overall if condition */
                CalcOverallIfCond ();

                /* Allocate and prepare a new descriptor */
                D = AllocIf (".ELSEIF", 0);
                NextTok ();

                /* Ignore the new condition if we are inside a false .ELSE
                ** branch. This way we won't get any errors about undefined
                ** symbols or similar...
                */
                if (IfCond) {
                    SetIfCond (D, ConstExpression ());
                    ExpectSep ();
                }

                /* Get the new overall condition */
                CalcOverallIfCond ();
                break;

            case TOK_ENDIF:
                /* We're done with this .IF.. - remove the descriptor(s) */
                FreeIf ();

                /* Be sure not to read the next token until the .IF stack
                ** has been cleanup up, since we may be at end of file.
                */
                NextTok ();
                ExpectSep ();

                /* Get the new overall condition */
                CalcOverallIfCond ();
                break;

            case TOK_IF:
                D = AllocIf (".IF", 1);
                NextTok ();
                if (IfCond) {
                    SetIfCond (D, ConstExpression ());
                    ExpectSep ();
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFBLANK:
                D = AllocIf (".IFBLANK", 1);
                NextTok ();
                if (IfCond) {
                    if (TokIsSep (CurTok.Tok)) {
                        SetIfCond (D, 1);
                    } else {
                        SetIfCond (D, 0);
                        SkipUntilSep ();
                    }
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFCONST:
                D = AllocIf (".IFCONST", 1);
                NextTok ();
                if (IfCond) {
                    ExprNode* Expr = Expression();
                    SetIfCond (D, IsConstExpr (Expr, 0));
                    FreeExpr (Expr);
                    ExpectSep ();
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFDEF:
                D = AllocIf (".IFDEF", 1);
                NextTok ();
                if (IfCond) {
                    SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
                    SetIfCond (D, Sym != 0 && SymIsDef (Sym));
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFNBLANK:
                D = AllocIf (".IFNBLANK", 1);
                NextTok ();
                if (IfCond) {
                    if (TokIsSep (CurTok.Tok)) {
                        SetIfCond (D, 0);
                    } else {
                        SetIfCond (D, 1);
                        SkipUntilSep ();
                    }
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFNCONST:
                D = AllocIf (".IFNCONST", 1);
                NextTok ();
                if (IfCond) {
                    ExprNode* Expr = Expression();
                    SetIfCond (D, !IsConstExpr (Expr, 0));
                    FreeExpr (Expr);
                    ExpectSep ();
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFNDEF:
                D = AllocIf (".IFNDEF", 1);
                NextTok ();
                if (IfCond) {
                    SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
                    SetIfCond (D, Sym == 0 || !SymIsDef (Sym));
                    ExpectSep ();
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFNREF:
                D = AllocIf (".IFNREF", 1);
                NextTok ();
                if (IfCond) {
                    SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
                    SetIfCond (D, Sym == 0 || !SymIsRef (Sym));
                    ExpectSep ();
                }
                CalcOverallIfCond ();
                break;

            case TOK_IFP02:
                D = AllocIf (".IFP02", 1);
                NextTok ();
                if (IfCond) {
                    SetIfCond (D, GetCPU() == CPU_6502);
                }
                ExpectSep ();
                CalcOverallIfCond ();
                break;

            case TOK_IFP4510:
                D = AllocIf (".IFP4510", 1);
                NextTok ();
                if (IfCond) {
                    SetIfCond (D, GetCPU() == CPU_4510);
                }
                ExpectSep ();
                CalcOverallIfCond ();
                break;

            case TOK_IFP816:
                D = AllocIf (".IFP816", 1);
                NextTok ();
                if (IfCond) {
                    SetIfCond (D, GetCPU() == CPU_65816);
                }
                ExpectSep ();
                CalcOverallIfCond ();
                break;

            case TOK_IFPC02:
                D = AllocIf (".IFPC02", 1);
                NextTok ();
                if (IfCond) {
                    SetIfCond (D, GetCPU() == CPU_65C02);
                }
                ExpectSep ();
                CalcOverallIfCond ();
                break;

            case TOK_IFPSC02:
                D = AllocIf (".IFPSC02", 1);
                NextTok ();
                if (IfCond) {
                    SetIfCond (D, GetCPU() == CPU_65SC02);
                }
                ExpectSep ();
                CalcOverallIfCond ();
                break;

            case TOK_IFREF:
                D = AllocIf (".IFREF", 1);
                NextTok ();
                if (IfCond) {
                    SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
                    SetIfCond (D, Sym != 0 && SymIsRef (Sym));
                    ExpectSep ();
                }
                CalcOverallIfCond ();
                break;

            default:
                /* Skip tokens */
                NextTok ();

        }

    } while (IfCond == 0 && CurTok.Tok != TOK_EOF);
}