bool IsscalarAnalyzer::analyze(AnalysisVisitor & visitor, const unsigned int lhs, ast::CallExp & e) { if (lhs != 1) { return false; } const ast::exps_t args = e.getArgs(); if (args.size() != 1) { return false; } ast::Exp * first = args.front(); first->accept(visitor); Result & R1 = visitor.getResult(); TIType & type1 = R1.getType(); if (!type1.ismatrix()) { return false; } if (type1.isscalar()) { TIType type(visitor.getGVN(), TIType::BOOLEAN); Result & res = e.getDecorator().setResult(type); res.getConstant() = new types::Bool(1); e.getDecorator().setCall(L"isscalar"); visitor.setResult(res); return true; } return false; }
void DeprecatedChecker::__Mfprintf::preCheckNode(const ast::Exp & e, SLintContext & context, SLintResult & result) { const ast::CallExp & ce = static_cast<const ast::CallExp &>(e); const ast::exps_t args = ce.getArgs(); if (args.size() != 0) { const ast::Exp & first = *args.front(); if (first.isDoubleExp() && static_cast<const ast::DoubleExp &>(first).getValue() == -1) { result.report(context, e.getLocation(), *this, _("mfprintf(-1, ...) is deprecated.")); } } }
void DeprecatedChecker::__Svd::preCheckNode(const ast::Exp & e, SLintContext & context, SLintResult & result) { const ast::CallExp & ce = static_cast<const ast::CallExp &>(e); const ast::exps_t args = ce.getArgs(); if (args.size() == 2) { const ast::Exp & second = *args.back(); if (second.isDoubleExp() && static_cast<const ast::DoubleExp &>(second).getValue() == 0) { result.report(context, e.getLocation(), *this, _("svd(..., 0) is deprecated.")); } } }
bool MatrixAnalyzer::analyze(AnalysisVisitor & visitor, const unsigned int lhs, ast::CallExp & e) { if (lhs > 1) { return false; } const ast::exps_t args = e.getArgs(); const unsigned int size = args.size(); if (size != 2 && size != 3) { return false; } if (size == 2) { return analyze2Args(visitor, args, e); } ast::Exp * first = args[0]; ast::Exp * second = args[1]; ast::Exp * third = args[2]; first->accept(visitor); Result R1 = visitor.getResult(); if (!R1.getType().ismatrix()) { return false; } second->accept(visitor); Result R2 = visitor.getResult(); third->accept(visitor); Result & R3 = visitor.getResult(); double val; SymbolicDimension rows; SymbolicDimension cols; if (R2.getConstant().getDblValue(val)) { const int nrows = tools::cast<int>(val); if (nrows <= 0) { return false; } else { rows = SymbolicDimension(visitor.getGVN(), nrows); } } else if (GVN::Value * gvnValue = R2.getConstant().getGVNValue()) { if (gvnValue->poly->isConstant() && gvnValue->poly->constant <= 0) { return false; } rows.setValue(gvnValue); rows.setGVN(&visitor.getGVN()); } else { return false; } if (R3.getConstant().getDblValue(val)) { const int ncols = tools::cast<int>(val); if (ncols <= 0) { return false; } else { cols = SymbolicDimension(visitor.getGVN(), ncols); } } else if (GVN::Value * gvnValue = R3.getConstant().getGVNValue()) { if (gvnValue->poly->isConstant() && gvnValue->poly->constant <= 0) { return false; } cols.setValue(gvnValue); cols.setGVN(&visitor.getGVN()); } else { return false; } const TIType & type = R1.getType(); SymbolicDimension prod1 = type.rows * type.cols; SymbolicDimension prod2 = rows * cols; bool res = visitor.getCM().check(ConstraintManager::EQUAL, prod1.getValue(), prod2.getValue()); if (res) { res = visitor.getCM().check(ConstraintManager::POSITIVE, rows.getValue()); if (!res) { return false; } } else { return false; } TIType resT(visitor.getGVN(), R1.getType().type, rows, cols); int tempId; if (R1.getTempId() != -1) { tempId = R1.getTempId(); } else { tempId = visitor.getDM().getTmpId(resT, false); } Result & _res = e.getDecorator().setResult(Result(resT, tempId)); visitor.setResult(_res); return true; }
bool MatrixAnalyzer::analyze2Args(AnalysisVisitor & visitor, const ast::exps_t & args, ast::CallExp & e) { ast::Exp * first = args[0]; ast::Exp * second = args[1]; first->accept(visitor); Result R1 = visitor.getResult(); if (!R1.getType().ismatrix()) { return false; } SymbolicDimension rows; SymbolicDimension cols; bool hasRC = false; if (second->isCallExp()) { ast::CallExp & ce = static_cast<ast::CallExp &>(*second); if (ce.getName().isSimpleVar()) { ast::SimpleVar & var = static_cast<ast::SimpleVar &>(ce.getName()); const symbol::Symbol & sym = var.getSymbol(); const std::wstring & name = sym.getName(); if (name == L"size" && visitor.getCM().checkGlobalConstant(sym)) { const ast::exps_t size_args = ce.getArgs(); if (size_args.size() == 1) { ast::Exp * e = size_args[0]; e->accept(visitor); Result & res = visitor.getResult(); if (res.getType().ismatrix()) { rows = res.getType().rows; cols = res.getType().cols; hasRC = true; } } } } } if (hasRC) { const TIType & type = R1.getType(); SymbolicDimension prod1 = type.rows * type.cols; SymbolicDimension prod2 = rows * cols; bool res = visitor.getCM().check(ConstraintManager::EQUAL, prod1.getValue(), prod2.getValue()); if (res) { TIType resT(visitor.getGVN(), R1.getType().type, rows, cols); int tempId; if (R1.getTempId() != -1) { tempId = R1.getTempId(); } else { tempId = visitor.getDM().getTmpId(resT, false); } Result & _res = e.getDecorator().setResult(Result(resT, tempId)); visitor.setResult(_res); return true; } } return false; }
bool MemInitAnalyzer::analyze(AnalysisVisitor & visitor, const unsigned int lhs, ast::CallExp & e) { const ast::exps_t args = e.getArgs(); if (args.size() == 2) { ast::Exp * first = *args.begin(); ast::Exp * second = *std::next(args.begin()); first->accept(visitor); Result R1 = visitor.getResult(); visitor.getDM().releaseTmp(R1.getTempId(), first); second->accept(visitor); Result & R2 = visitor.getResult(); visitor.getDM().releaseTmp(R2.getTempId(), second); double val; SymbolicDimension rows, cols; bool empty = false; if (R1.getConstant().getDblValue(val)) { const int nrows = tools::cast<int>(val); if (nrows <= 0) { empty = true; } else { rows = SymbolicDimension(visitor.getGVN(), nrows); } } else if (GVN::Value * gvnValue = R1.getConstant().getGVNValue()) { rows.setValue(gvnValue); rows.setGVN(&visitor.getGVN()); } else { return false; } if (!empty) { if (R2.getConstant().getDblValue(val)) { const int ncols = tools::cast<int>(val); if (ncols <= 0) { empty = true; } else { cols = SymbolicDimension(visitor.getGVN(), ncols); } } else if (GVN::Value * gvnValue = R2.getConstant().getGVNValue()) { cols.setValue(gvnValue); cols.setGVN(&visitor.getGVN()); } else { return false; } } if (empty) { e.getDecorator().setResult(TIType(visitor.getGVN(), TIType::EMPTY)); } else { bool res = visitor.getCM().check(ConstraintManager::POSITIVE, rows.getValue()); if (res) { res = visitor.getCM().check(ConstraintManager::POSITIVE, cols.getValue()); if (!res) { return false; } } else { return false; } TIType resT(visitor.getGVN(), TIType::DOUBLE, rows, cols); e.getDecorator().setResult(Result(resT, visitor.getDM().getTmpId(resT, false))); } visitor.setResult(e.getDecorator().res); return true; } return false; }
bool IconvertAnalyzer::analyze(AnalysisVisitor & visitor, const unsigned int lhs, ast::CallExp & e) { if (lhs != 1) { return false; } const ast::exps_t args = e.getArgs(); if (args.size() != 2) { return false; } ast::Exp * first = args.front(); ast::Exp * second = args.back(); first->accept(visitor); Result R1 = visitor.getResult(); TIType & type1 = R1.getType(); if (!type1.ismatrix()) { return false; } second->accept(visitor); Result & R2 = visitor.getResult(); double val; unsigned char ival; if (R2.getConstant().getDblValue(val) && tools::asInteger<unsigned char>(val, ival)) { TIType::Type type; switch (ival) { case 0: type = TIType::DOUBLE; break; case 1: type = TIType::INT8; break; case 2: type = TIType::INT16; break; case 4: type = TIType::INT32; break; case 8: type = TIType::INT64; break; case 11: type = TIType::UINT8; break; case 12: type = TIType::UINT16; break; case 14: type = TIType::UINT32; break; case 18: type = TIType::UINT64; break; default: return false; } TIType typ(visitor.getGVN(), type, type1.rows, type1.cols); Result & res = e.getDecorator().setResult(typ); e.getDecorator().setCall(L"iconvert"); visitor.setResult(res); return true; } return false; }
void AnalysisVisitor::visit(ast::IfExp & e) { logger.log(L"IfExp", e.getLocation()); ast::Exp * shortcutExp = nullptr; // we apply the ConstantVisitor e.getTest().accept(cv); ast::Exp & test = e.getTest(); if (cv.getResult() && test.isConstExp()) { e.accept(cv); // we have a constant ! ast::ConstExp & ce = static_cast<ast::ConstExp &>(test); types::InternalType * pIT = ce.getConstant(); if (!pIT) { test.accept(cv.getExec()); pIT = ce.getConstant(); } if (pIT) { const bool result = pIT->isTrue(); if (result) { shortcutExp = &e.getThen(); e.getExps()[1] = nullptr; } else { shortcutExp = &e.getElse(); e.getExps()[2] = nullptr; } } } else { ast::Exp * val = nullptr; bool isEq; if (test.isOpExp()) { ast::OpExp & oe = static_cast<ast::OpExp &>(test); isEq = oe.getOper() == ast::OpExp::eq; if (isEq || oe.getOper() == ast::OpExp::ne) { if (oe.getLeft().isDoubleExp()) { ast::DoubleExp & de = static_cast<ast::DoubleExp &>(oe.getLeft()); if (types::InternalType * pIT = de.getConstant()) { if (pIT->isDouble()) { types::Double * pDbl = static_cast<types::Double *>(pIT); if (pDbl->isEmpty()) { val = &oe.getRight(); } } } } else if (oe.getRight().isDoubleExp()) { ast::DoubleExp & de = static_cast<ast::DoubleExp &>(oe.getRight()); if (types::InternalType * pIT = de.getConstant()) { if (pIT->isDouble()) { types::Double * pDbl = static_cast<types::Double *>(pIT); if (pDbl->isEmpty()) { val = &oe.getLeft(); } } } } } } else { ast::CallExp * ce = nullptr; if (test.isNotExp()) { ast::NotExp & ne = static_cast<ast::NotExp &>(test); if (ne.getExp().isCallExp()) { ce = &static_cast<ast::CallExp &>(ne.getExp()); isEq = false; } } else if (test.isCallExp()) { ce = &static_cast<ast::CallExp &>(test); isEq = true; } if (ce && ce->getName().isSimpleVar()) { ast::SimpleVar & var = static_cast<ast::SimpleVar &>(ce->getName()); const symbol::Symbol & sym = var.getSymbol(); const std::wstring & name = sym.getName(); if (name == L"isempty" && getCM().checkGlobalConstant(sym)) { const ast::exps_t args = ce->getArgs(); if (args.size() == 1) { val = args.front(); } } } } if (val) { // test is something like val == [], isempty(val), val ~= [], ~isempty(val) val->accept(*this); Result & res = getResult(); TIType & ty = res.getType(); if ((ty.ismatrix() && ty.isscalar()) || (getCM().check(ConstraintManager::STRICT_POSITIVE, ty.rows.getValue()) || getCM().check(ConstraintManager::STRICT_POSITIVE, ty.cols.getValue()))) { if (isEq) { shortcutExp = &e.getElse(); e.getExps()[2] = nullptr; } else { shortcutExp = &e.getThen(); e.getExps()[1] = nullptr; } } } } if (shortcutExp) { e.replace(shortcutExp); shortcutExp->accept(*this); } else { dm.addBlock(Block::EXCLUSIVE, &e); e.getTest().accept(*this); dm.releaseTmp(getResult().getTempId()); dm.addBlock(Block::NORMAL, &e.getThen()); e.getThen().accept(*this); dm.finalizeBlock(); dm.addBlock(Block::NORMAL, e.hasElse() ? &e.getElse() : nullptr); if (e.hasElse()) { e.getElse().accept(*this); } dm.finalizeBlock(); dm.finalizeBlock(); } }
bool AnalysisVisitor::analyzeIndices(TIType & type, ast::CallExp & ce) { const ast::exps_t args = ce.getArgs(); const unsigned int size = args.size(); if (size >= 3) { // Not handle yet... // TODO return false; } if (size == 0) { Result & res = ce.getDecorator().setResult(type); setResult(res); return true; } SymbolicDimension first, second; bool safe, ret; argIndices.emplace(static_cast<ast::SimpleVar &>(ce.getName()), size, 1); if (size == 1) { // when there is one argument, a(?) is equivalent to A(?,1) // where A = matrix(a, r_a * c_a, 1) SymbolicDimension rows(type.rows); second = SymbolicDimension(getGVN(), 1); if (type.cols != 1) { rows *= type.cols; } ret = getDimension(rows, *args.front(), safe, first); } else { bool _safe; ret = getDimension(type.rows, *args.front(), _safe, first); if (ret) { argIndices.top().getIndex() = 2; ret = getDimension(type.cols, *args.back(), safe, second); safe = safe && _safe; } else { safe = _safe; } } argIndices.pop(); if (ret) { TIType typ(getGVN(), type.type, first, second); Result & _res = ce.getDecorator().setResult(typ); setResult(_res); ce.getDecorator().safe = safe; } return ret; }
bool SizeAnalyzer::analyze(AnalysisVisitor & visitor, const unsigned int lhs, ast::CallExp & e) { if (lhs > 2) { return false; } const ast::exps_t args = e.getArgs(); enum Kind { ROWS, COLS, ROWSTIMESCOLS, ROWSCOLS, ONE, BOTH, DUNNO } kind = DUNNO; const std::size_t size = args.size(); if (size == 0 || size >= 3) { return false; } ast::Exp * first = *args.begin(); if (!first) { return false; } first->accept(visitor); Result & res = visitor.getResult(); if (!res.getType().ismatrix()) { visitor.getDM().releaseTmp(res.getTempId(), first); return false; } switch (size) { case 1: if (lhs == 1) { kind = BOTH; } else if (lhs == 2) { kind = ROWSCOLS; } break; case 2: { ast::Exp * second = *std::next(args.begin()); if (second && lhs == 1) { if (second->isStringExp()) { const std::wstring & arg2 = static_cast<ast::StringExp *>(second)->getValue(); if (arg2 == L"r") { kind = ROWS; } else if (arg2 == L"c") { kind = COLS; } else if (arg2 == L"*") { kind = ROWSTIMESCOLS; } else { visitor.getDM().releaseTmp(res.getTempId(), first); return false; } } else if (second->isDoubleExp()) { const double arg2 = static_cast<ast::DoubleExp *>(second)->getValue(); if (arg2 == 1) { kind = ROWS; } else if (arg2 == 2) { kind = COLS; } else if (arg2 >= 3) { // TODO: we should handle hypermatrix kind = ONE; } else { visitor.getDM().releaseTmp(res.getTempId(), first); return false; } } } else { visitor.getDM().releaseTmp(res.getTempId(), first); return false; } break; } default: visitor.getDM().releaseTmp(res.getTempId(), first); return false; } TIType type(visitor.getGVN(), TIType::DOUBLE); switch (kind) { case ROWS: { SymbolicDimension & rows = res.getType().rows; Result & _res = e.getDecorator().setResult(type); _res.getConstant() = rows.getValue(); e.getDecorator().setCall(new SizeCall(SizeCall::R)); visitor.setResult(_res); break; } case COLS: { SymbolicDimension & cols = res.getType().cols; Result & _res = e.getDecorator().setResult(type); _res.getConstant() = cols.getValue(); e.getDecorator().setCall(new SizeCall(SizeCall::C)); visitor.setResult(_res); break; } case ROWSTIMESCOLS: { SymbolicDimension & rows = res.getType().rows; SymbolicDimension & cols = res.getType().cols; SymbolicDimension prod = rows * cols; Result & _res = e.getDecorator().setResult(type); _res.getConstant() = prod.getValue(); e.getDecorator().setCall(new SizeCall(SizeCall::RC)); visitor.setResult(_res); break; } case ROWSCOLS: { SymbolicDimension & rows = res.getType().rows; SymbolicDimension & cols = res.getType().cols; std::vector<Result> & mlhs = visitor.getLHSContainer(); mlhs.clear(); mlhs.reserve(2); mlhs.emplace_back(type); mlhs.back().getConstant() = rows.getValue(); mlhs.emplace_back(type); mlhs.back().getConstant() = cols.getValue(); e.getDecorator().setCall(new SizeCall(SizeCall::R_C)); break; } case ONE: { Result & _res = e.getDecorator().setResult(type); _res.getConstant() = new types::Double(1); e.getDecorator().setCall(new SizeCall(SizeCall::ONE)); visitor.setResult(_res); break; } case BOTH: { TIType _type(visitor.getGVN(), TIType::DOUBLE, 1, 2); Result & _res = e.getDecorator().setResult(_type); e.getDecorator().setCall(new SizeCall(SizeCall::BOTH)); visitor.setResult(_res); break; } default: return false; } return true; }