ExpressionPtr buildPtrOperation(BasicGenerator::Operator op, const ExpressionPtr& ptrExpr) { assert_true(isReference(ptrExpr) && isPointer(core::analysis::getReferencedType(ptrExpr->getType()))) << "Trying to build a unary pointer operation with non-ref<ptr>."; IRBuilder builder(ptrExpr->getNodeManager()); auto& pExt = ptrExpr->getNodeManager().getLangExtension<PointerExtension>(); switch(op) { case BasicGenerator::Operator::PostInc: return builder.callExpr(pExt.getPtrPostInc(), ptrExpr); case BasicGenerator::Operator::PostDec: return builder.callExpr(pExt.getPtrPostDec(), ptrExpr); case BasicGenerator::Operator::PreInc: return builder.callExpr(pExt.getPtrPreInc(), ptrExpr); case BasicGenerator::Operator::PreDec: return builder.callExpr(pExt.getPtrPreDec(), ptrExpr); default: break; } assert_fail() << "Unsupported unary pointer operation " << op; return ExpressionPtr(); }
void makeFatalMeth(FileScope& file, AnalysisResultConstPtr ar, const std::string& msg, int line, Meth meth) { auto labelScope = std::make_shared<LabelScope>(); auto r = Location::Range(line, 0, line, 0); BlockScopePtr scope; auto args = std::make_shared<ExpressionList>(scope, r); args->addElement(Expression::MakeScalarExpression(ar, scope, r, msg)); auto e = std::make_shared<SimpleFunctionCall>(scope, r, "throw_fatal", false, args, ExpressionPtr()); meth(e); auto exp = std::make_shared<ExpStatement>(scope, labelScope, r, e); auto stmts = std::make_shared<StatementList>(scope, labelScope, r); stmts->addElement(exp); FunctionScopePtr fs = file.setTree(ar, stmts); fs->setOuterScope(file.shared_from_this()); fs->getStmt()->resetScope(fs); exp->copyLocationTo(fs->getStmt()); file.setOuterScope(const_cast<AnalysisResult*>(ar.get())->shared_from_this()); }
ExpressionPtr FileScope::getEffectiveImpl(AnalysisResultConstPtr ar) const { if (m_tree) return m_tree->getEffectiveImpl(ar); return ExpressionPtr(); }
ExpressionPtr buildPtrOperation(BasicGenerator::Operator op, const ExpressionPtr& lhs, const ExpressionPtr& rhs) { auto& basic = lhs->getNodeManager().getLangBasic(); auto& pExt = lhs->getNodeManager().getLangExtension<PointerExtension>(); IRBuilder builder(lhs->getNodeManager()); auto assertPtr = [&](const ExpressionPtr& exp) { assert_pred1(isPointer, exp) << "Trying to build a ptr operation from non-ptr:" << "\n lhs: " << *lhs << "\n - of type: " << *lhs->getType() << "\n rhs: " << *rhs << "\n - of type: " << *rhs->getType() << "\n op: " << op; }; auto assertInt = [&](const ExpressionPtr& exp) { assert_pred1(basic.isInt, exp->getType()) << "Trying to build a ptr add/sub with non-int" << "\n lhs: " << *lhs << "\n - of type: " << *lhs->getType() << "\n rhs: " << *rhs << "\n - of type: " << *rhs->getType() << "\n op: " << op; }; auto buildInt8Cast = [&](const ExpressionPtr& exp) { if(!core::types::isSubTypeOf(exp->getType(), basic.getInt8())) { return builder.numericCast(exp, basic.getInt8()); } return exp; }; // arithmetic operations switch(op) { case BasicGenerator::Operator::Add: { if(!isPointer(lhs)) { assertPtr(rhs); assertInt(lhs); return builder.callExpr(pExt.getPtrAdd(), rhs, buildInt8Cast(lhs)); } assertPtr(lhs); assertInt(rhs); return builder.callExpr(pExt.getPtrAdd(), lhs, buildInt8Cast(rhs)); } case BasicGenerator::Operator::Sub: { // minus is only supported with ptr on the lhs assertPtr(lhs); if(!isPointer(rhs)) { assertInt(rhs); return builder.callExpr(pExt.getPtrSub(), lhs, buildInt8Cast(rhs)); } else { return builder.callExpr(pExt.getPtrDiff(), lhs, rhs); } } default: break; } // comparison operations assertPtr(lhs); assertPtr(rhs); switch(op) { case BasicGenerator::Operator::Eq: return builder.callExpr(pExt.getPtrEqual(), lhs, rhs); case BasicGenerator::Operator::Ne: return builder.callExpr(pExt.getPtrNotEqual(), lhs, rhs); case BasicGenerator::Operator::Le: return builder.callExpr(pExt.getPtrLessEqual(), lhs, rhs); case BasicGenerator::Operator::Lt: return builder.callExpr(pExt.getPtrLessThan(), lhs, rhs); case BasicGenerator::Operator::Ge: return builder.callExpr(pExt.getPtrGreaterEqual(), lhs, rhs); case BasicGenerator::Operator::Gt: return builder.callExpr(pExt.getPtrGreaterThan(), lhs, rhs); default: break; } assert_fail() << "Unsupported binary pointer operation " << op; return ExpressionPtr(); }
ExpressionPtr UnaryOpExpression::preOptimize(AnalysisResultConstPtr ar) { Variant value; Variant result; if (m_exp && ar->getPhase() >= AnalysisResult::FirstPreOptimize) { if (m_op == T_UNSET) { if (m_exp->isScalar() || (m_exp->is(KindOfExpressionList) && static_pointer_cast<ExpressionList>(m_exp)->getCount() == 0)) { recomputeEffects(); return CONSTANT("null"); } return ExpressionPtr(); } } if (m_op == T_ISSET && m_exp->is(KindOfExpressionList) && static_pointer_cast<ExpressionList>(m_exp)->getListKind() == ExpressionList::ListKindParam) { auto el = static_pointer_cast<ExpressionList>(m_exp); result = true; int i = 0, n = el->getCount(); for (; i < n; i++) { ExpressionPtr e((*el)[i]); if (!e || !e->isScalar() || !e->getScalarValue(value)) break; if (value.isNull()) { result = false; } } if (i == n) { return replaceValue(makeScalarExpression(ar, result)); } } else if (m_op != T_ARRAY && m_exp && m_exp->isScalar() && m_exp->getScalarValue(value) && preCompute(value, result)) { return replaceValue(makeScalarExpression(ar, result)); } else if (m_op == T_BOOL_CAST) { switch (m_exp->getKindOf()) { default: break; case KindOfBinaryOpExpression: { int op = static_pointer_cast<BinaryOpExpression>(m_exp)->getOp(); switch (op) { case T_LOGICAL_OR: case T_BOOLEAN_OR: case T_LOGICAL_AND: case T_BOOLEAN_AND: case T_LOGICAL_XOR: case T_INSTANCEOF: case '<': case T_IS_SMALLER_OR_EQUAL: case '>': case T_IS_GREATER_OR_EQUAL: case T_SPACESHIP: case T_IS_IDENTICAL: case T_IS_NOT_IDENTICAL: case T_IS_EQUAL: case T_IS_NOT_EQUAL: return m_exp; } break; } case KindOfUnaryOpExpression: { int op = static_pointer_cast<UnaryOpExpression>(m_exp)->getOp(); switch (op) { case T_BOOL_CAST: case '!': case T_ISSET: case T_EMPTY: case T_PRINT: return m_exp; } break; } } } return ExpressionPtr(); }