source: icGREP/icgrep-devel/icgrep/pablo/analysis/pabloverifier.cpp @ 4771

Last change on this file since 4771 was 4771, checked in by nmedfort, 4 years ago

Bug fixes for reassociation pass; passes make check.

File size: 2.7 KB
Line 
1#include "pabloverifier.hpp"
2#include <pablo/function.h>
3#include <pablo/codegenstate.h>
4#include <pablo/printer_pablos.h>
5#include <unordered_set>
6
7namespace pablo {
8
9struct OrderingVerifier {
10    OrderingVerifier() : mParent(nullptr) {}
11    OrderingVerifier(const OrderingVerifier & parent) : mParent(&parent) {}
12    bool count(const PabloAST * expr) const {
13        if (mSet.count(expr)) {
14            return true;
15        } else if (mParent) {
16            return mParent->count(expr);
17        }
18        return false;
19    }
20    void insert(const PabloAST * expr) {
21        mSet.insert(expr);
22    }
23private:
24    const OrderingVerifier * const mParent;
25    std::unordered_set<const PabloAST *> mSet;
26};
27
28void isTopologicallyOrdered(const PabloBlock & block, const OrderingVerifier & parent, const bool ignoreUnusedStatements) {
29    OrderingVerifier ov(parent);
30    for (const Statement * stmt : block) {
31        if (stmt->getNumUses() == 0 && ignoreUnusedStatements) {
32            continue;
33        }
34        if (LLVM_UNLIKELY(isa<While>(stmt))) {
35            isTopologicallyOrdered(cast<While>(stmt)->getBody(), ov, ignoreUnusedStatements);
36            for (const Next * var : cast<While>(stmt)->getVariants()) {
37                ov.insert(var);
38            }
39        }
40        for (unsigned i = 0; i != stmt->getNumOperands(); ++i) {
41            const PabloAST * op = stmt->getOperand(i);
42            if ((isa<Statement>(op) || isa<Var>(op)) && ov.count(op) == false) {
43                // TODO: make this actually test whether the operand is ever defined,
44                // or if it was defined in a scope that cannot be reached?
45                std::string tmp;
46                raw_string_ostream str(tmp);
47                str << "PabloVerifier: function is not topologically ordered! ";
48                PabloPrinter::print(stmt->getOperand(i), str);
49                str << " was used before definition!";
50                throw std::runtime_error(str.str());
51            }
52        }
53        ov.insert(stmt);
54        if (LLVM_UNLIKELY(isa<If>(stmt))) {
55            isTopologicallyOrdered(cast<If>(stmt)->getBody(), ov, ignoreUnusedStatements);
56            for (const Assign * def : cast<If>(stmt)->getDefined()) {
57                ov.insert(def);
58            }
59        }
60    }
61}
62
63void isTopologicallyOrdered(const PabloFunction & function, const bool ignoreUnusedStatements) {
64    OrderingVerifier ov;
65    for (unsigned i = 0; i != function.getNumOfParameters(); ++i) {
66        ov.insert(function.getParameter(i));
67    }
68    isTopologicallyOrdered(function.getEntryBlock(), ov, ignoreUnusedStatements);
69}
70
71void PabloVerifier::verify(const PabloFunction & function, const bool ignoreUnusedStatements) {
72    isTopologicallyOrdered(function, ignoreUnusedStatements);
73}
74
75}
Note: See TracBrowser for help on using the repository browser.