Ejemplo n.º 1
0
void SLintVisitor::visit(const ast::ListExp & e)
{
    auto range = preCheck(e);
    e.getStart().accept(*this);
    if (e.hasExplicitStep())
    {
        e.getStep().accept(*this);
    }
    e.getEnd().accept(*this);
    postCheck(e, range);
}
Ejemplo n.º 2
0
 void GlobalsCollector::visit(ast::ListExp & e)
 {
     e.getStart().accept(*this);
     e.getStep().accept(*this);
     e.getEnd().accept(*this);
 }
void AnalysisVisitor::visit(ast::ListExp & e)
{
    logger.log(L"ListExp", e.getLocation());
    if (e.getParent()->isVarDec())
    {
        visitInVarDecCtxt(e);
        return;
    }

    e.getStart().accept(*this);
    Result & Rstart = e.getStart().getDecorator().getResult();
    e.getEnd().accept(*this);
    Result & Rend = e.getEnd().getDecorator().getResult();
    e.getStep().accept(*this);
    Result & Rstep = e.getStep().getDecorator().getResult();

    double start = 1;
    double step = 1;
    double end = 1;
    if (Rstart.getConstant().getDblValue(start) && Rstep.getConstant().getDblValue(step) && Rend.getConstant().getDblValue(end))
    {
        // Start, Step & End are constant !
        double out;
        int type = ForList64::checkList(start, end, step, out);

        switch (type)
        {
            case 0:
                e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
                break;
            case 1:
                e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::DOUBLE), -1));
                break;
            case 2:
            {
                const uint64_t N = ForList64::size(start, end, step);
                TIType T(dm.getGVN(), TIType::DOUBLE, 1, N);
                if (N == 1)
                {
                    out = start;
                }
                e.getDecorator().setResult(Result(T, dm.getTmpId(T, false)));
                break;
            }
            default:
                break;
        }
        e.setValues(start, step, end, out);
        setResult(e.getDecorator().res);

        return;
    }

    if (step == 0 || tools::isNaN(step) || !tools::isFinite(step)
            || tools::isNaN(start) || !tools::isFinite(start)
            ||  tools::isNaN(end) || !tools::isFinite(end))
    {
        e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
        return;
    }

    if (!Rstep.getConstant().getDblValue(step) || (step != -1 && step != 1))
    {
        Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
        setResult(res);
        return;
    }

    if (!Rstart.getType().isscalar() || !Rend.getType().isscalar())
    {
        Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
        setResult(res);
        return;
    }

    GVN::Value * gvnStart;
    if (Rstart.getConstant().getDblValue(start))
    {
        if (tools::getIntType(start) == tools::NOTANINT)
        {
            gvnStart = getGVN().getValue((double)tools::cast<int>(start + step));
        }
        else
        {
            gvnStart = getGVN().getValue((double)tools::cast<int>(start));
        }
    }
    else
    {
        gvnStart = Rstart.getConstant().getGVNValue();
        if (!gvnStart)
        {
            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
            setResult(res);
            return;
        }
    }

    GVN::Value * gvnEnd;

    if (Rend.getConstant().getDblValue(end))
    {
        if (tools::getIntType(end) == tools::NOTANINT)
        {
            gvnEnd = getGVN().getValue((double)tools::cast<int>(end - step));
        }
        else
        {
            gvnEnd = getGVN().getValue((double)tools::cast<int>(end));
        }
    }
    else
    {
        gvnEnd = Rend.getConstant().getGVNValue();
        if (!gvnEnd)
        {
            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
            setResult(res);
            return;
        }
    }

    GVN::Value * ONEValue = getGVN().getValue(int64_t(1));
    SymbolicDimension ONE(getGVN(), ONEValue);
    GVN::Value * v;

    if (gvnStart->value == gvnEnd->value)
    {
        Result & res = e.getDecorator().setResult(Result(TIType(getGVN(), TIType::DOUBLE, ONE, ONE)));
        setResult(res);
        return;
    }

    if (step == 1)
    {
        v = getGVN().getValue(OpValue::Kind::MINUS, *gvnEnd, *gvnStart);
    }
    else
    {
        v = getGVN().getValue(OpValue::Kind::MINUS, *gvnStart, *gvnEnd);
    }
    v = getGVN().getValue(OpValue::Kind::PLUS, *v, *ONEValue);

    if (v->poly->constant < 0 && v->poly->isCoeffNegative(false))
    {
        TIType type(getGVN(), TIType::EMPTY);
        e.getDecorator().res = Result(type);
    }
    else
    {
        bool res = getCM().check(ConstraintManager::POSITIVE, v);
        if (res)
        {
            TIType type(getGVN(), TIType::DOUBLE, ONE, SymbolicDimension(getGVN(), v));
            e.getDecorator().setResult(type);
        }
        else
        {
            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
            setResult(res);
            return;
        }
    }

    setResult(e.getDecorator().res);
}
bool SymbolicList::get(AnalysisVisitor & visitor, ast::ListExp & le, SymbolicList & sl)
{
    le.getStart().accept(visitor);
    Result Rstart = visitor.getResult();
    le.getEnd().accept(visitor);
    Result Rend = visitor.getResult();
    le.getStep().accept(visitor);
    Result & Rstep = visitor.getResult();

    double start, step, end;
    if (Rstart.getConstant().getDblValue(start) && Rstep.getConstant().getDblValue(step) && Rend.getConstant().getDblValue(end))
    {
        if (tools::isAnInt(start) && tools::isAnInt(step) && tools::isAnInt(end))
        {
            sl = SymbolicList(start, step, end);
            return true;
        }
        return false;
    }

    GVN::Value * gvnStart, * gvnStep, * gvnEnd;
    if (Rstart.getConstant().getDblValue(start))
    {
        int64_t _start;
        if (tools::asInteger(start, _start))
        {
            gvnStart = visitor.getGVN().getValue(_start);
        }
        else
        {
            return false;
        }
    }
    else if (GVN::Value * v = Rstart.getConstant().getGVNValue())
    {
        gvnStart = v;
    }
    else
    {
        return false;
    }

    if (Rstep.getConstant().getDblValue(step))
    {
        int64_t _step;
        if (tools::asInteger(step, _step))
        {
            gvnStep = visitor.getGVN().getValue(_step);
        }
        else
        {
            return false;
        }
    }
    else if (GVN::Value * v = Rstep.getConstant().getGVNValue())
    {
        gvnStep = v;
    }
    else
    {
        return false;
    }

    if (Rend.getConstant().getDblValue(end))
    {
        int64_t _end;
        if (tools::asInteger(end, _end))
        {
            gvnEnd = visitor.getGVN().getValue(_end);
        }
        else
        {
            return false;
        }
    }
    else if (GVN::Value * v = Rend.getConstant().getGVNValue())
    {
        gvnEnd = v;
    }
    else
    {
        return false;
    }

    sl = SymbolicList(gvnStart, gvnStep, gvnEnd);

    return true;
}
void AnalysisVisitor::visitInVarDecCtxt(ast::ListExp & e)
{
    e.getStart().accept(*this);
    Result & Rstart = e.getStart().getDecorator().getResult();
    e.getEnd().accept(*this);
    Result & Rend = e.getEnd().getDecorator().getResult();
    e.getStep().accept(*this);
    Result & Rstep = e.getStep().getDecorator().getResult();

    double start = 1;
    double step = 1;
    double end = 1;
    if ((Rstart.getConstant().getDblValue(start) || Rstep.getConstant().getDblValue(step)
            || Rend.getConstant().getDblValue(end)) &&
            (step == 0 || tools::isNaN(step) || !tools::isFinite(step)
             || tools::isNaN(start) || !tools::isFinite(start)
             ||  tools::isNaN(end) || !tools::isFinite(end)))
    {
        // We have an invalid list
        e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
        return;
    }

    ast::VarDec & vd = *static_cast<ast::VarDec *>(e.getParent());
    const symbol::Symbol & sym = vd.getSymbol();
    GVN::Value * startRange = nullptr;
    GVN::Value * endRange = nullptr;
    Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::DOUBLE), -1));

    if (Rstart.getConstant().getGVNValue(getGVN(), startRange) && Rend.getConstant().getGVNValue(getGVN(), endRange))
    {
        // Start & End are GVN values
        res.setRange(SymbolicRange(getGVN(), startRange, endRange));
    }
    else
    {
        SymbolicRange & rangeStart = Rstart.getRange();
        if (rangeStart.isValid())
        {
            // Start is an iterator: for i=1:N, for j=i:N, ... in the second for "i" in "i:n" is an iterator
            if (endRange || Rend.getConstant().getGVNValue(getGVN(), endRange))
            {
                // Start is an iterator and End is GVN value
                res.setRange(SymbolicRange(getGVN(), rangeStart.getStart(), endRange));
            }
            else
            {
                SymbolicRange & rangeEnd = Rend.getRange();
                if (rangeEnd.isValid())
                {
                    // Start & End are iterators
                    res.setRange(SymbolicRange(getGVN(), rangeStart.getStart(), rangeEnd.getEnd()));
                }
            }
        }
        else if (startRange || Rstart.getConstant().getGVNValue(getGVN(), startRange))
        {
            // Start is a GVN value
            SymbolicRange & rangeEnd = Rend.getRange();
            if (rangeEnd.isValid())
            {
                // Start is a GVN value and End is an iterator
                res.setRange(SymbolicRange(getGVN(), startRange, rangeEnd.getEnd()));
            }
        }
    }

    setResult(res);
}