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

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

Bug fixes for reassociation pass.

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