示例#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;
}
 CvType getCvTypeAsRef (CvType const & cv_type)
 {
   CvType res_cv_type = cv_type;
   if (res_cv_type.getType ()->getKind () != REF_TYPE)
   {
     res_cv_type = CvType (getRefType (res_cv_type));
   }
   return res_cv_type;
 }
示例#3
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;
}
示例#4
0
/**
 * \brief
 * do constant folding
 *
 * @param expr
 *      target node
 * @param[out] result
 *      result value
 * @return
 *      0:is not constant, 1:constant
 */
int
getConstNumValue(CExpr *expr, CNumValueWithType *result)
{
    memset(result, 0, sizeof(CNumValueWithType));

    if(EXPR_ISNULL(expr) || EXPR_ISERROR(expr)) {
        result->nvt_numValue.ll = 0;
        result->nvt_basicType = BT_INT;
        result->nvt_numKind = getNumValueKind(result->nvt_basicType);
        return 1;
    }

    if(EXPR_CODE(expr) == EC_XMP_DESC_OF) return 0; /* not constant */

    CNumValueWithType n1, n2, n3;
    int use2 = 0, use3 = 0, isConst2 = 0, isConst3 = 0;

    switch(EXPR_STRUCT(expr)) {
    case STRUCT_CExprOfUnaryNode: {
            CExpr *node = EXPR_U(expr)->e_node;

            if(EXPR_CODE(expr) == EC_SIZE_OF || 
	       EXPR_CODE(expr) == EC_GCC_ALIGN_OF) {
                CExprOfTypeDesc *td = resolveType(node);

                if(td == NULL)
                    return 0;

                result->nvt_isConstButMutable = 1;
                result->nvt_basicType = BT_INT;
                result->nvt_numKind = getNumValueKind(result->nvt_basicType);
                if(EXPR_CODE(expr) == EC_SIZE_OF)
                    result->nvt_numValue.ll = getTypeSize(td);
                else {
                    assertExpr((CExpr*)td, getTypeAlign(td));
                    result->nvt_numValue.ll = getTypeAlign(td);
                }
                return 1;
            }

            if(getConstNumValue(node, &n1) == 0) {
                mergeConstFlag(result, &n1);
                return 0;
            }
        }
        break;

    case STRUCT_CExprOfBinaryNode: {
            if(isUnreducableConst(expr, 1)) {
                result->nvt_isConstButUnreducable = 1;
                return 0;
            }

            CExpr *node1 = EXPR_B(expr)->e_nodes[0];
            CExpr *node2 = EXPR_B(expr)->e_nodes[1];

            if(EXPR_CODE(node1) == EC_TYPE_DESC) {
                if(getConstNumValue(node2, &n2) == 0)
                    return 0;
                else
                    n1 = n2;
            } else {
                if(getConstNumValue(node1, &n1) == 0) {
                    mergeConstFlag(result, &n1);
                    return 0;
                }

                if(getConstNumValue(node2, &n2) == 0) {
                    mergeConstFlag(result, &n1);
                    mergeConstFlag(result, &n2);
                    return 0;
                }
                use2 = 1;
            }
        }
        break;

    case STRUCT_CExprOfList:
        if(EXPR_CODE(expr) == EC_CONDEXPR) {
            if(getConstNumValue(exprListNextNData(expr, 0), &n1) == 0) {
                mergeConstFlag(result, &n1);
                return 0;
            }
            isConst2 = getConstNumValue(exprListNextNData(expr, 1), &n2);
            isConst3 = getConstNumValue(exprListNextNData(expr, 2), &n3);
            use2 = use3 = 1;
        } else {
            //maybe comma expr
            if(getConstNumValue(exprListTailData(expr), &n1) == 0) {
                mergeConstFlag(result, &n1);
                return 0;
            }
        }
        break;

    case STRUCT_CExprOfCharConst:
        //wide char is not supported
        result->nvt_numValue.ll = EXPR_CHARCONST(expr)->e_token[0];
        result->nvt_basicType = BT_CHAR;
        result->nvt_numKind = getNumValueKind(result->nvt_basicType);
        return 1;

    case STRUCT_CExprOfNumberConst:
        constToNumValueWithType(EXPR_NUMBERCONST(expr), result);
        return 1;

    case STRUCT_CExprOfSymbol: {
            CExprOfSymbol *tsym = findSymbolByGroup(EXPR_SYMBOL(expr)->e_symName, STB_IDENT);
            if(tsym == NULL || (tsym->e_symType != ST_ENUM) ||
                tsym->e_isConstButUnreducable ||
                (tsym && getConstNumValue(tsym->e_valueExpr, &n1) == 0)) {
                if(tsym && tsym->e_isConstButUnreducable)
                    result->nvt_isConstButUnreducable = 1;
                mergeConstFlag(result, &n1);
                return 0;
            }
        }
        break;

    case STRUCT_CExprOfArrayDecl:
    case STRUCT_CExprOfTypeDesc:
    case STRUCT_CExprOfErrorNode:
    case STRUCT_CExprOfGeneralCode:
    case STRUCT_CExprOfNull:
        return 0;

    default:
        assertExpr(expr, 0);
        ABORT();
    }

    int r = 1;
    int isCondExpr = (EXPR_CODE(expr) == EC_CONDEXPR);
    //for lshift/rshift
    int ni2 = 0;
    mergeConstFlag(result, &n1);
    
    if(use2) {
        ni2 = (int)getCastedLongValue(&n2);
        if(fixNumValueType(&n1, &n2) == 0 && isCondExpr == 0)
            return 0;
        mergeConstFlag(result, &n2);
    }

    if(use3) {
        if(fixNumValueType(&n1, &n3) == 0 && isCondExpr == 0)
            return 0;
        mergeConstFlag(result, &n3);
    }

    //now n1/n2/n3 have same basicType and numKind
    CNumValueKind nk = n1.nvt_numKind;
    CNumValue *nvr = &result->nvt_numValue;
    CNumValue *nv1 = &n1.nvt_numValue;
    CNumValue *nv2 = &n2.nvt_numValue;
    CNumValue *nv3 = &n3.nvt_numValue;

    switch(EXPR_CODE(expr)) {
    case EC_EXPRS:
        //last expression
        switch(nk) {
        case NK_LL:  nvr->ll  = nv1->ll; break;
        case NK_ULL: nvr->ull = nv1->ull; break;
        case NK_LD:  nvr->ld  = nv1->ld; break;
        }
        break;
    case EC_BRACED_EXPR:
    case EC_IDENT: // enumerator
        switch(nk) {
        case NK_LL:  nvr->ll  = nv1->ll; break;
        case NK_ULL: nvr->ull = nv1->ull; break;
        case NK_LD:  nvr->ld  = nv1->ld; break;
        }
        break;
    case EC_UNARY_MINUS:
        switch(nk) {
        case NK_LL:  nvr->ll  = -nv1->ll; break;
        case NK_ULL: nvr->ull = -nv1->ull; break;
        case NK_LD:  nvr->ld  = -nv1->ld; break;
        }
        break;
    case EC_BIT_NOT:
        switch(nk) {
        case NK_LL:  nvr->ll  = ~nv1->ll; break;
        case NK_ULL: nvr->ull = ~nv1->ull; break;
        case NK_LD:  return 0;
        }
        break;
    case EC_LOG_NOT:
        switch(nk) {
        case NK_LL:  nvr->ll  = !nv1->ll; break;
        case NK_ULL: nvr->ull = !nv1->ull; break;
        case NK_LD:  nvr->ld  = !nv1->ld; break;
        }
        break;
    case EC_CAST: {
            CExprOfTypeDesc *td = resolveType(EXPR_B(expr)->e_nodes[0]);
            if(td == NULL)
                return 0;
            CExprOfTypeDesc *tdo = getRefType(td);
            if(castNumValue(&n1, tdo->e_basicType) == 0) {
                addError(expr, CERR_016);
                EXPR_ISERROR(expr) = 1;
                return 0;
            }
            switch(n1.nvt_numKind) {
            case NK_LL:  nvr->ll  = nv1->ll;  break;
            case NK_ULL: nvr->ull = nv1->ull; break;
            case NK_LD:  nvr->ld  = nv1->ld;  break;
            }
        }
        break;
    case EC_LSHIFT:
        switch(nk) {
        case NK_LL:  nvr->ll  = nv1->ll  << ni2; break;
        case NK_ULL: nvr->ull = nv1->ull << ni2; break;
        case NK_LD:  return 0;
        }
        break;
    case EC_RSHIFT:
        switch(nk) {
        case NK_LL:  nvr->ll  = nv1->ll  >> ni2; break;
        case NK_ULL: nvr->ull = nv1->ull >> ni2; break;
        case NK_LD:  return 0;
        }
        break;
    case EC_PLUS:
        switch(nk) {
        case NK_LL:  nvr->ll  = nv1->ll  + nv2->ll; break;
        case NK_ULL: nvr->ull = nv1->ull + nv2->ull; break;
        case NK_LD:  nvr->ld  = nv1->ld  + nv2->ld; break;
        }
        break;
    case EC_MINUS:
        switch(nk) {
        case NK_LL:  nvr->ll  = nv1->ll  - nv2->ll; break;
        case NK_ULL: nvr->ull = nv1->ull - nv2->ull; break;
        case NK_LD:  nvr->ld  = nv1->ld  - nv2->ld; break;
        }
        break;
    case EC_MUL:
        switch(nk) {
        case NK_LL:  nvr->ll  = nv1->ll  * nv2->ll; break;
        case NK_ULL: nvr->ull = nv1->ull * nv2->ull; break;
        case NK_LD:  nvr->ld  = nv1->ld  * nv2->ld; break;
        }
        break;
    case EC_DIV:
        if(checkDivisionByZero(expr, nk, nv2))
            return 0;
        switch(nk) {
        case NK_LL:  nvr->ll  = nv1->ll  / nv2->ll; break;
        case NK_ULL: nvr->ull = nv1->ull / nv2->ull; break;
        case NK_LD:  nvr->ld  = nv1->ld  / nv2->ld; break;
        }
        break;
    case EC_MOD:
        if(checkDivisionByZero(expr, nk, nv2))
            return 0;
        switch(nk) {
        case NK_LL:  nvr->ll  = nv1->ll  % nv2->ll; break;
        case NK_ULL: nvr->ull = nv1->ull % nv2->ull; break;
        case NK_LD:  return 0;
        }
        break;
    case EC_ARITH_EQ:
        switch(nk) {
        case NK_LL:  nvr->ll  = (nv1->ll  == nv2->ll); break;
        case NK_ULL: nvr->ull = (nv1->ull == nv2->ull); break;
        case NK_LD:  nvr->ld  = (nv1->ld  == nv2->ld); break;
        }
        break;
    case EC_ARITH_NE:
        switch(nk) {
        case NK_LL:  nvr->ll  = (nv1->ll  != nv2->ll); break;
        case NK_ULL: nvr->ull = (nv1->ull != nv2->ull); break;
        case NK_LD:  nvr->ld  = (nv1->ld  != nv2->ld); break;
        }
        break;
    case EC_ARITH_GE:
        switch(nk) {
        case NK_LL:  nvr->ll  = (nv1->ll  >= nv2->ll); break;
        case NK_ULL: nvr->ull = (nv1->ull >= nv2->ull); break;
        case NK_LD:  nvr->ld  = (nv1->ld  >= nv2->ld); break;
        }
        break;
    case EC_ARITH_GT:
        switch(nk) {
        case NK_LL:  nvr->ll  = (nv1->ll  > nv2->ll); break;
        case NK_ULL: nvr->ull = (nv1->ull > nv2->ull); break;
        case NK_LD:  nvr->ld  = (nv1->ld  > nv2->ld); break;
        }
        break;
    case EC_ARITH_LE:
        switch(nk) {
        case NK_LL:  nvr->ll  = (nv1->ll  <= nv2->ll); break;
        case NK_ULL: nvr->ull = (nv1->ull <= nv2->ull); break;
        case NK_LD:  nvr->ld  = (nv1->ld  <= nv2->ld); break;
        }
        break;
    case EC_ARITH_LT:
        switch(nk) {
        case NK_LL:  nvr->ll  = (nv1->ll  < nv2->ll); break;
        case NK_ULL: nvr->ull = (nv1->ull < nv2->ull); break;
        case NK_LD:  nvr->ld  = (nv1->ld  < nv2->ld); break;
        }
        break;
    case EC_LOG_AND:
        switch(nk) {
        case NK_LL:  nvr->ll  = (nv1->ll  && nv2->ll); break;
        case NK_ULL: nvr->ull = (nv1->ull && nv2->ull); break;
        case NK_LD:  return 0;
        }
        break;
    case EC_LOG_OR:
        switch(nk) {
        case NK_LL:  nvr->ll  = (nv1->ll  || nv2->ll); break;
        case NK_ULL: nvr->ull = (nv1->ull || nv2->ull); break;
        case NK_LD:  return 0;
        }
        break;
    case EC_BIT_AND:
        switch(nk) {
        case NK_LL:  nvr->ll  = (nv1->ll  & nv2->ll); break;
        case NK_ULL: nvr->ull = (nv1->ull & nv2->ull); break;
        case NK_LD:  return 0;
        }
        break;
    case EC_BIT_OR:
        switch(nk) {
        case NK_LL:  nvr->ll  = (nv1->ll  | nv2->ll); break;
        case NK_ULL: nvr->ull = (nv1->ull | nv2->ull); break;
        case NK_LD:  return 0;
        }
        break;
    case EC_BIT_XOR:
        switch(nk) {
        case NK_LL:  nvr->ll  = (nv1->ll  ^ nv2->ll); break;
        case NK_ULL: nvr->ull = (nv1->ull ^ nv2->ull); break;
        case NK_LD:  return 0;
        }
        break;
    case EC_CONDEXPR:
        switch(nk) {
        case NK_LL:  nvr->ll  = nv1->ll  ? nv2->ll  : nv3->ll;
            r = (nv1->ll) ? isConst2 : isConst3; break;
        case NK_ULL: nvr->ull = nv1->ull ? nv2->ull : nv3->ull;
            r = (nv1->ull) ? isConst2 : isConst3; break;
        case NK_LD:  nvr->ld  = nv1->ld  ? nv2->ld  : nv3->ld;
            r = (nv1->ld) ? isConst2 : isConst3; break;
        }
        break;
    default:
        return 0;
    }

    result->nvt_basicType = n1.nvt_basicType;
    result->nvt_numKind = n1.nvt_numKind;

    return r;
}