Ejemplo n.º 1
0
/**
 * \brief
 * judge e is unreducable value
 *
 * @param e
 *      target node
 * @param allowSymbolAddr
 *      set to 1 and symbol address will be treated as constant
 * @return
 *      0:no, 1:yes
 */
PRIVATE_STATIC int
isUnreducableConst(CExpr *e, int allowSymbolAddr)
{
    if(EXPR_CODE(e) == EC_GCC_BLTIN_OFFSET_OF)
        return 1;

    if(EXPR_CODE(e) == EC_FUNCTION_CALL) {
        CExprOfTypeDesc *td = resolveType(EXPR_B(e)->e_nodes[0]);
        if(td == NULL)
            return 0;
        td = getRefType(td);
        if(ETYP_IS_POINTER(td))
            td = EXPR_T(td->e_typeExpr);
        if(ETYP_IS_FUNC(td) == 0)
            return 0;
        //treat static+inline+const func with
        //constant argument as constant.
        //this code needs to compile the linux kernel.
        //ex) case __fswab16(0x0800):
        int isConst = (td->e_sc.esc_isStatic &&
            td->e_tq.etq_isInline &&
            (td->e_tq.etq_isConst || td->e_isGccConst));
        if(isConst &&
            isConstExpr(EXPR_B(e)->e_nodes[1], allowSymbolAddr))
            return 1;
    }

    return 0;
}
Ejemplo n.º 2
0
bool ValidateLimitations::validateForLoopCond(TIntermLoop *node,
                                              int indexSymbolId)
{
    TIntermNode *cond = node->getCondition();
    if (cond == NULL)
    {
        error(node->getLine(), "Missing condition", "for");
        return false;
    }
    //
    // condition has the form:
    //     loop_index relational_operator constant_expression
    //
    TIntermBinary *binOp = cond->getAsBinaryNode();
    if (binOp == NULL)
    {
        error(node->getLine(), "Invalid condition", "for");
        return false;
    }
    // Loop index should be to the left of relational operator.
    TIntermSymbol *symbol = binOp->getLeft()->getAsSymbolNode();
    if (symbol == NULL)
    {
        error(binOp->getLine(), "Invalid condition", "for");
        return false;
    }
    if (symbol->getId() != indexSymbolId)
    {
        error(symbol->getLine(),
              "Expected loop index", symbol->getSymbol().c_str());
        return false;
    }
    // Relational operator is one of: > >= < <= == or !=.
    switch (binOp->getOp())
    {
      case EOpEqual:
      case EOpNotEqual:
      case EOpLessThan:
      case EOpGreaterThan:
      case EOpLessThanEqual:
      case EOpGreaterThanEqual:
        break;
      default:
        error(binOp->getLine(),
              "Invalid relational operator",
              GetOperatorString(binOp->getOp()));
        break;
    }
    // Loop index must be compared with a constant.
    if (!isConstExpr(binOp->getRight()))
    {
        error(binOp->getLine(),
              "Loop index cannot be compared with non-constant expression",
              symbol->getSymbol().c_str());
        return false;
    }

    return true;
}
Ejemplo n.º 3
0
int ValidateLimitations::validateForLoopInit(TIntermLoop *node)
{
    TIntermNode *init = node->getInit();
    if (init == NULL)
    {
        error(node->getLine(), "Missing init declaration", "for");
        return -1;
    }

    //
    // init-declaration has the form:
    //     type-specifier identifier = constant-expression
    //
    TIntermAggregate *decl = init->getAsAggregate();
    if ((decl == NULL) || (decl->getOp() != EOpDeclaration))
    {
        error(init->getLine(), "Invalid init declaration", "for");
        return -1;
    }
    // To keep things simple do not allow declaration list.
    TIntermSequence &declSeq = decl->getSequence();
    if (declSeq.size() != 1)
    {
        error(decl->getLine(), "Invalid init declaration", "for");
        return -1;
    }
    TIntermBinary *declInit = declSeq[0]->getAsBinaryNode();
    if ((declInit == NULL) || (declInit->getOp() != EOpInitialize))
    {
        error(decl->getLine(), "Invalid init declaration", "for");
        return -1;
    }
    TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode();
    if (symbol == NULL)
    {
        error(declInit->getLine(), "Invalid init declaration", "for");
        return -1;
    }
    // The loop index has type int or float.
    TBasicType type = symbol->getBasicType();
    if ((type != EbtInt) && (type != EbtFloat))
    {
        error(symbol->getLine(),
              "Invalid type for loop index", getBasicString(type));
        return -1;
    }
    // The loop index is initialized with constant expression.
    if (!isConstExpr(declInit->getRight()))
    {
        error(declInit->getLine(),
              "Loop index cannot be initialized with non-constant expression",
              symbol->getSymbol().c_str());
        return -1;
    }

    return symbol->getId();
}
Ejemplo n.º 4
0
bool ValidateLimitations::validateForLoopExpr(TIntermLoop *node,
                                              int indexSymbolId)
{
    TIntermNode *expr = node->getExpression();
    if (expr == NULL)
    {
        error(node->getLine(), "Missing expression", "for");
        return false;
    }

    // for expression has one of the following forms:
    //     loop_index++
    //     loop_index--
    //     loop_index += constant_expression
    //     loop_index -= constant_expression
    //     ++loop_index
    //     --loop_index
    // The last two forms are not specified in the spec, but I am assuming
    // its an oversight.
    TIntermUnary *unOp = expr->getAsUnaryNode();
    TIntermBinary *binOp = unOp ? NULL : expr->getAsBinaryNode();

    TOperator op = EOpNull;
    TIntermSymbol *symbol = NULL;
    if (unOp != NULL)
    {
        op = unOp->getOp();
        symbol = unOp->getOperand()->getAsSymbolNode();
    }
    else if (binOp != NULL)
    {
        op = binOp->getOp();
        symbol = binOp->getLeft()->getAsSymbolNode();
    }

    // The operand must be loop index.
    if (symbol == NULL)
    {
        error(expr->getLine(), "Invalid expression", "for");
        return false;
    }
    if (symbol->getId() != indexSymbolId)
    {
        error(symbol->getLine(),
              "Expected loop index", symbol->getSymbol().c_str());
        return false;
    }

    // The operator is one of: ++ -- += -=.
    switch (op)
    {
      case EOpPostIncrement:
      case EOpPostDecrement:
      case EOpPreIncrement:
      case EOpPreDecrement:
        ASSERT((unOp != NULL) && (binOp == NULL));
        break;
      case EOpAddAssign:
      case EOpSubAssign:
        ASSERT((unOp == NULL) && (binOp != NULL));
        break;
      default:
        error(expr->getLine(), "Invalid operator", GetOperatorString(op));
        return false;
    }

    // Loop index must be incremented/decremented with a constant.
    if (binOp != NULL)
    {
        if (!isConstExpr(binOp->getRight()))
        {
            error(binOp->getLine(),
                  "Loop index cannot be modified by non-constant expression",
                  symbol->getSymbol().c_str());
            return false;
        }
    }

    return true;
}
Ejemplo n.º 5
0
/**
 * \brief
 * judge e is constant value
 *
 * @param e
 *      target node
 * @param allowSymbolAddr
 *      set to 1 and symbol address will be treated as constant
 * @return
 *      0:no, 1:yes
 */
int
isConstExpr(CExpr *e, int allowSymbolAddr)
{
    if(e == NULL)
        return 1;
    if(EXPR_ISCONSTVALUECHECKED(e) || EXPR_ISERROR(e))
        return EXPR_ISCONSTVALUE(e);
    EXPR_ISCONSTVALUECHECKED(e) = 1;

    switch(EXPR_CODE(e)) {
    case EC_SIZE_OF:
    case EC_GCC_ALIGN_OF:
    case EC_XMP_DESC_OF:
        goto end;
    case EC_FUNCTION_CALL: {
            if(isUnreducableConst(e, allowSymbolAddr) == 0)
                return 0;
            goto end;
        }
    case EC_GCC_BLTIN_VA_ARG:
    case EC_POINTER_REF:
    case EC_POINTS_AT:
    case EC_MEMBER_REF: {
            assert(EXPRS_TYPE(e));
            CExprOfTypeDesc *tdo = getRefType(EXPRS_TYPE(e));
            if(ETYP_IS_ARRAY(tdo))
                goto end;
            CExpr *parent = EXPR_PARENT(e);
            if(isExprCodeChildOf(e, EC_ADDR_OF, parent, NULL) == 0)
                return 0;
            goto end;
        }
    case EC_IDENT:
        switch(EXPR_SYMBOL(e)->e_symType) {
        case ST_ENUM:
        case ST_MEMBER:
            goto end;
        default:
            if(allowSymbolAddr) {
                CExprOfTypeDesc *td = EXPRS_TYPE(e);
                CExprOfTypeDesc *tdo = getRefType(EXPRS_TYPE(e));
                assert(td);
                CExpr *parent = EXPR_PARENT(e);

                if(ETYP_IS_FUNC(tdo)) {
                    if(isExprCodeChildOf(e, EC_FUNCTION_CALL, parent, NULL))
                        return 0;
                    CExprOfTypeDesc *ptd = allocPointerTypeDesc(td);
                    exprSetExprsType(e, ptd);
                    addTypeDesc(ptd);
                } else if(ETYP_IS_ARRAY(tdo)) {
                    CExpr *pp;
                    if(isExprCodeChildOf(e, EC_ARRAY_REF, parent, &pp)) {
                        if(isExprCodeChildOf(e, EC_ARRAY_REF, pp, NULL) == 0 &&
                            isExprCodeChildOf(e, EC_ADDR_OF, parent, NULL) == 0)
                            return 0;
                    }
                } else if(ETYP_IS_POINTER(tdo) == 0) {
                    if(isExprCodeChildOf(e, EC_ADDR_OF, parent, NULL) == 0)
                        return 0;
                }
            } else {
                return 0;
            }
        }
        break;
    case EC_CONDEXPR: {
            CExpr *cond = exprListHeadData(e);
            if(isConstExpr(cond, allowSymbolAddr) == 0)
                return 0;
            goto end;
        }
    default:
        break;
    }

    CExprIterator ite;
    EXPR_FOREACH_MULTI(ite, e) {
        if(isConstExpr(ite.node, allowSymbolAddr) == 0)
            return 0;
    }

  end:

    EXPR_ISCONSTVALUE(e) = 1;
    return 1;
}