コード例 #1
0
ファイル: datatype.c プロジェクト: josch1710/cc65
unsigned SizeOf (const Type* T)
/* Compute size of object represented by type array. */
{
    switch (UnqualifiedType (T->C)) {

        case T_VOID:
            return 0;   /* Assume voids have size zero */

        case T_SCHAR:
        case T_UCHAR:
            return SIZEOF_CHAR;

        case T_SHORT:
        case T_USHORT:
            return SIZEOF_SHORT;

        case T_INT:
        case T_UINT:
            return SIZEOF_INT;

        case T_PTR:
        case T_FUNC:    /* Maybe pointer to function */
            return SIZEOF_PTR;

        case T_LONG:
        case T_ULONG:
            return SIZEOF_LONG;

        case T_LONGLONG:
        case T_ULONGLONG:
            return SIZEOF_LONGLONG;

        case T_ENUM:
            return SIZEOF_INT;

        case T_FLOAT:
            return SIZEOF_FLOAT;

        case T_DOUBLE:
            return SIZEOF_DOUBLE;

        case T_STRUCT:
        case T_UNION:
            return ((SymEntry*) T->A.P)->V.S.Size;

        case T_ARRAY:
            if (T->A.L == UNSPECIFIED) {
                /* Array with unspecified size */
                return 0;
            } else {
                return T->A.L * SizeOf (T + 1);
            }

        default:
            Internal ("Unknown type in SizeOf: %04lX", T->C);
            return 0;

    }
}
コード例 #2
0
ファイル: datatype.c プロジェクト: josch1710/cc65
Type* GetFuncReturn (Type* T)
/* Return a pointer to the return type of a function or pointer-to-function type */
{
    if (UnqualifiedType (T->C) == T_PTR) {
        /* Pointer to function */
        ++T;
    }

    /* Be sure it's a function type */
    CHECK (IsClassFunc (T));

    /* Return a pointer to the return type */
    return T + 1;
}
コード例 #3
0
ファイル: datatype.c プロジェクト: josch1710/cc65
void SetFuncDesc (Type* T, FuncDesc* F)
/* Set the FuncDesc pointer in a function or pointer-to-function type */
{
    if (UnqualifiedType (T->C) == T_PTR) {
        /* Pointer to function */
        ++T;
    }

    /* Be sure it's a function type */
    CHECK (IsClassFunc (T));

    /* Set the function descriptor */
    T->A.P = F;
}
コード例 #4
0
ファイル: datatype.c プロジェクト: josch1710/cc65
FuncDesc* GetFuncDesc (const Type* T)
/* Get the FuncDesc pointer from a function or pointer-to-function type */
{
    if (UnqualifiedType (T->C) == T_PTR) {
        /* Pointer to function */
        ++T;
    }

    /* Be sure it's a function type */
    CHECK (IsClassFunc (T));

    /* Get the function descriptor from the type attributes */
    return T->A.P;
}
コード例 #5
0
ファイル: datatype.c プロジェクト: josch1710/cc65
unsigned TypeOf (const Type* T)
/* Get the code generator base type of the object */
{
    switch (UnqualifiedType (T->C)) {

        case T_SCHAR:
            return CF_CHAR;

        case T_UCHAR:
            return CF_CHAR | CF_UNSIGNED;

        case T_SHORT:
        case T_INT:
        case T_ENUM:
            return CF_INT;

        case T_USHORT:
        case T_UINT:
        case T_PTR:
        case T_ARRAY:
            return CF_INT | CF_UNSIGNED;

        case T_LONG:
            return CF_LONG;

        case T_ULONG:
            return CF_LONG | CF_UNSIGNED;

        case T_FLOAT:
        case T_DOUBLE:
            /* These two are identical in the backend */
            return CF_FLOAT;

        case T_FUNC:
            return (((FuncDesc*) T->A.P)->Flags & FD_VARIADIC)? 0 : CF_FIXARGC;

        case T_STRUCT:
        case T_UNION:
            /* Address of ... */
            return CF_INT | CF_UNSIGNED;

        default:
            Error ("Illegal type %04lX", T->C);
            return CF_INT;
    }
}
コード例 #6
0
ファイル: swstmt.c プロジェクト: PanchoManera/cc65
void SwitchStatement (void)
/* Handle a switch statement for chars with a cmp cascade for the selector */
{
    ExprDesc    SwitchExpr;     /* Switch statement expression */
    CodeMark    CaseCodeStart;  /* Start of code marker */
    CodeMark    SwitchCodeStart;/* Start of switch code */
    CodeMark    SwitchCodeEnd;  /* End of switch code */
    unsigned    ExitLabel;      /* Exit label */
    unsigned    SwitchCodeLabel;/* Label for the switch code */
    int         HaveBreak = 0;  /* True if the last statement had a break */
    int         RCurlyBrace;    /* True if last token is right curly brace */
    SwitchCtrl* OldSwitch;      /* Pointer to old switch control data */
    SwitchCtrl  SwitchData;     /* New switch data */


    /* Eat the "switch" token */
    NextToken ();

    /* Read the switch expression and load it into the primary. It must have
     * integer type.
     */
    ConsumeLParen ();
    Expression0 (&SwitchExpr);
    if (!IsClassInt (SwitchExpr.Type))  {
        Error ("Switch quantity is not an integer");
        /* To avoid any compiler errors, make the expression a valid int */
        ED_MakeConstAbsInt (&SwitchExpr, 1);
    }
    ConsumeRParen ();

    /* Add a jump to the switch code. This jump is usually unnecessary,
     * because the switch code will moved up just behind the switch
     * expression. However, in rare cases, there's a label at the end of
     * the switch expression. This label will not get moved, so the code
     * jumps around the switch code, and after moving the switch code,
     * things look really weird. If we add a jump here, we will never have
     * a label attached to the current code position, and the jump itself
     * will get removed by the optimizer if it is unnecessary.
     */
    SwitchCodeLabel = GetLocalLabel ();
    g_jump (SwitchCodeLabel);

    /* Remember the current code position. We will move the switch code
     * to this position later.
     */
    GetCodePos (&CaseCodeStart);

    /* Setup the control structure, save the old and activate the new one */
    SwitchData.Nodes        = NewCollection ();
    SwitchData.ExprType     = UnqualifiedType (SwitchExpr.Type[0].C);
    SwitchData.Depth        = SizeOf (SwitchExpr.Type);
    SwitchData.DefaultLabel = 0;
    OldSwitch = Switch;
    Switch = &SwitchData;

    /* Get the exit label for the switch statement */
    ExitLabel = GetLocalLabel ();

    /* Create a loop so we may use break. */
    AddLoop (ExitLabel, 0);

    /* Make sure a curly brace follows */
    if (CurTok.Tok != TOK_LCURLY) {
        Error ("`{' expected");
    }

    /* Parse the following statement, which will actually be a compound
     * statement because of the curly brace at the current input position
     */
    HaveBreak = Statement (&RCurlyBrace);

    /* Check if we had any labels */
    if (CollCount (SwitchData.Nodes) == 0 && SwitchData.DefaultLabel == 0) {
        Warning ("No case labels");
    }

    /* If the last statement did not have a break, we may have an open
     * label (maybe from an if or similar). Emitting code and then moving
     * this code to the top will also move the label to the top which is
     * wrong. So if the last statement did not have a break (which would
     * carry the label), add a jump to the exit. If it is useless, the
     * optimizer will remove it later.
     */
    if (!HaveBreak) {
        g_jump (ExitLabel);
    }

    /* Remember the current position */
    GetCodePos (&SwitchCodeStart);

    /* Output the switch code label */
    g_defcodelabel (SwitchCodeLabel);

    /* Generate code */
    if (SwitchData.DefaultLabel == 0) {
        /* No default label, use switch exit */
        SwitchData.DefaultLabel = ExitLabel;
    }
    g_switch (SwitchData.Nodes, SwitchData.DefaultLabel, SwitchData.Depth);

    /* Move the code to the front */
    GetCodePos (&SwitchCodeEnd);
    MoveCode (&SwitchCodeStart, &SwitchCodeEnd, &CaseCodeStart);

    /* Define the exit label */
    g_defcodelabel (ExitLabel);

    /* Exit the loop */
    DelLoop ();

    /* Switch back to the enclosing switch statement if any */
    Switch = OldSwitch;

    /* Free the case value tree */
    FreeCaseNodeColl (SwitchData.Nodes);

    /* If the case statement was (correctly) terminated by a closing curly
     * brace, skip it now.
     */
    if (RCurlyBrace) {
        NextToken ();
    }
}