98    const Visitor *called_by = 
nullptr;
 
  109    virtual profile_t init_apply(
const IR::Node *root);
 
  110    profile_t init_apply(
const IR::Node *root, 
const Context *parent_context);
 
  115    virtual void end_apply();
 
  116    virtual void end_apply(
const IR::Node *root);
 
  121    virtual const IR::Node *apply_visitor(
const IR::Node *n, 
const char *name = 0) = 0;
 
  122    void visit(
const IR::Node *&n, 
const char *name = 0) { n = apply_visitor(n, name); }
 
  123    void visit(
const IR::Node *
const &n, 
const char *name = 0) {
 
  124        auto t = apply_visitor(n, name);
 
  125        if (t != n) visitor_const_error();
 
  127    void visit(
const IR::Node *&n, 
const char *name, 
int cidx) {
 
  128        ctxt->child_index = cidx;
 
  129        n = apply_visitor(n, name);
 
  131    void visit(
const IR::Node *
const &n, 
const char *name, 
int cidx) {
 
  132        ctxt->child_index = cidx;
 
  133        auto t = apply_visitor(n, name);
 
  134        if (t != n) visitor_const_error();
 
  136    void visit(
IR::Node *&, 
const char * = 0, 
int = 0) { BUG(
"Can't visit non-const pointer"); }
 
  137#define DECLARE_VISIT_FUNCTIONS(CLASS, BASE)                           \ 
  138    void visit(const IR::CLASS *&n, const char *name = 0);             \ 
  139    void visit(const IR::CLASS *const &n, const char *name = 0);       \ 
  140    void visit(const IR::CLASS *&n, const char *name, int cidx);       \ 
  141    void visit(const IR::CLASS *const &n, const char *name, int cidx); \ 
  142    void visit(IR::CLASS *&, const char * = 0, int = 0) { BUG("Can't visit non-const pointer"); } 
  143    IRNODE_ALL_SUBCLASSES(DECLARE_VISIT_FUNCTIONS)
 
  144#undef DECLARE_VISIT_FUNCTIONS 
  145    void visit(
IR::Node &n, 
const char *name = 0) {
 
  146        if (name && ctxt) ctxt->child_name = name;
 
  147        n.visit_children(*
this);
 
  149    void visit(
const IR::Node &n, 
const char *name = 0) {
 
  150        if (name && ctxt) ctxt->child_name = name;
 
  151        n.visit_children(*
this);
 
  153    void visit(
IR::Node &n, 
const char *name, 
int cidx) {
 
  155            ctxt->child_name = name;
 
  156            ctxt->child_index = cidx;
 
  158        n.visit_children(*
this);
 
  160    void visit(
const IR::Node &n, 
const char *name, 
int cidx) {
 
  162            ctxt->child_name = name;
 
  163            ctxt->child_index = cidx;
 
  165        n.visit_children(*
this);
 
  168    void parallel_visit(
IR::Vector<T> &v, 
const char *name = 0) {
 
  169        if (name && ctxt) ctxt->child_name = name;
 
  170        v.parallel_visit_children(*
this);
 
  173    void parallel_visit(
const IR::Vector<T> &v, 
const char *name = 0) {
 
  174        if (name && ctxt) ctxt->child_name = name;
 
  175        v.parallel_visit_children(*
this);
 
  178    void parallel_visit(
IR::Vector<T> &v, 
const char *name, 
int cidx) {
 
  180            ctxt->child_name = name;
 
  181            ctxt->child_index = cidx;
 
  183        v.parallel_visit_children(*
this);
 
  186    void parallel_visit(
const IR::Vector<T> &v, 
const char *name, 
int cidx) {
 
  188            ctxt->child_name = name;
 
  189            ctxt->child_index = cidx;
 
  191        v.parallel_visit_children(*
this);
 
  194    virtual Visitor *clone()
 const {
 
  195        BUG(
"need %s::clone method", name());
 
  198    virtual bool check_clone(
const Visitor *a) { 
return typeid(*this) == 
typeid(*a); }
 
  202    virtual Visitor &flow_clone() { 
return *
this; }
 
  205    Visitor() : split_link(split_link_mem) {}
 
  211    virtual bool flow_merge_closure(
Visitor &) { BUG(
"%s pass does not support loops", name()); }
 
  214    virtual void flow_merge_global_from(
cstring) {}
 
  215    virtual void erase_global(
cstring) {}
 
  216    virtual bool check_global(
cstring) { 
return false; }
 
  217    virtual void clear_globals() {}
 
  218    virtual bool has_flow_joins()
 const { 
return false; }
 
  220    static cstring demangle(
const char *);
 
  221    virtual const char *name()
 const {
 
  222        if (!internalName) internalName = demangle(
typeid(*this).name());
 
  223        return internalName.c_str();
 
  225    void setName(
const char *name) { internalName = 
cstring(name); }
 
  226    void print_context() 
const;  
 
  233    const IR::Node *getOriginal()
 const { 
return ctxt->original; }
 
  235    const T *getOriginal()
 const {
 
  236        CHECK_NULL(ctxt->original);
 
  237        BUG_CHECK(ctxt->original->
is<T>(), 
"%1% does not have the expected type %2%",
 
  238                  ctxt->original, demangle(
typeid(T).name()));
 
  239        return ctxt->original->
to<T>();
 
  241    const Context *getChildContext()
 const { 
return ctxt; }
 
  242    const Context *getContext()
 const { 
return ctxt->parent; }
 
  244    const T *getParent()
 const {
 
  245        return ctxt->parent ? ctxt->parent->node->
to<T>() : nullptr;
 
  247    int getChildrenVisited()
 const { 
return ctxt->child_index; }
 
  248    int getContextDepth()
 const { 
return ctxt->depth - 1; }
 
  250    inline const T *findContext(
const Context *&c)
 const {
 
  252        if (!c) 
return nullptr;
 
  253        while ((c = c->parent))
 
  254            if (
auto *rv = c->node->to<T>()) 
return rv;
 
  258    inline const T *findContext()
 const {
 
  259        const Context *c = ctxt;
 
  260        return findContext<T>(c);
 
  263    inline const T *findOrigCtxt(
const Context *&c)
 const {
 
  265        if (!c) 
return nullptr;
 
  266        while ((c = c->parent))
 
  267            if (
auto *rv = c->original->to<T>()) 
return rv;
 
  271    inline const T *findOrigCtxt()
 const {
 
  272        const Context *c = ctxt;
 
  273        return findOrigCtxt<T>(c);
 
  275    inline bool isInContext(
const IR::Node *n)
 const {
 
  276        for (
auto *c = ctxt; c; c = c->parent) {
 
  277            if (c->node == n || c->original == n) 
return true;
 
  288        return ctxt->node ? ctxt->node->
to<T>() : nullptr;
 
  298    template <
class T, 
typename = std::enable_if_t<Util::has_SourceInfo_v<T>>, 
class... Args>
 
  299    void warn(
const int kind, 
const char *format, 
const T *node, Args &&...args) {
 
  300        if (
warning_enabled(kind)) ::warning(kind, format, node, std::forward<Args>(args)...);
 
  304    template <
class T, 
typename = std::enable_if_t<Util::has_SourceInfo_v<T>>, 
class... Args>
 
  305    void warn(
const int kind, 
const char *format, 
const T &node, Args &&...args) {
 
  306        if (
warning_enabled(kind)) ::warning(kind, format, node, std::forward<Args>(args)...);
 
 
  314    bool visitDagOnce = 
true;
 
  315    bool dontForwardChildrenBeforePreorder = 
false;
 
  319    bool joinFlows = 
false;
 
  321    virtual void init_join_flows(
const IR::Node *) {
 
  322        BUG(
"joinFlows only supported in ControlFlowVisitor currently");
 
  350    void visit_children(
const IR::Node *, std::function<
void()> fn) { fn(); }
 
  356    virtual void visitOnce()
 const { BUG(
"do not know how to handle request"); }
 
  357    virtual void visitAgain()
 const { BUG(
"do not know how to handle request"); }
 
  360    virtual void visitor_const_error();
 
  361    const Context *ctxt = 
nullptr;  
 
 
  460    std::map<cstring, ControlFlowVisitor &> &globals;
 
  470            int exist = 0, visited = 0;
 
  472        std::map<const IR::Node *, ctrs_t> parents;
 
 
  475    typedef std::map<const IR::Node *, flow_join_info_t> flow_join_points_t;
 
  477    friend std::ostream &operator<<(std::ostream &, 
const flow_join_points_t &);
 
  480    friend void dump(
const flow_join_points_t &);
 
  481    friend void dump(
const flow_join_points_t *);
 
  486    bool unreachable = 
false;
 
  488    flow_join_points_t *flow_join_points = 0;
 
  491        flow_join_points_t &join_points;
 
  492        bool preorder(
const IR::Node *n)
 override {
 
  493            BUG_CHECK(join_points.count(n) == 0, 
"oops");
 
  495            auto *ctxt = getContext();
 
  496            join_points[n].parents[ctxt ? ctxt->original : 
nullptr].exist++;
 
  500        void revisit(
const IR::Node *n)
 override {
 
  501            ++join_points[n].count;
 
  503            auto *ctxt = getContext();
 
  504            join_points[n].parents[ctxt ? ctxt->original : 
nullptr].exist++;
 
  509        explicit SetupJoinPoints(flow_join_points_t &fjp) : join_points(fjp) {}
 
 
  511    bool BackwardsCompatibleBroken = 
false;  
 
  514    virtual void applySetupJoinPoints(
const IR::Node *root) {
 
  517    void init_join_flows(
const IR::Node *root) 
override;
 
  535        BUG(
"%s pass does not support loops", name());
 
  538    void setUnreachable() { unreachable = 
true; }
 
  539    bool isUnreachable() { 
return unreachable; }
 
  541        if (globals.count(key))
 
  542            globals.at(key).flow_merge(*
this);
 
  544            globals.emplace(key, flow_clone());
 
 
  546    void flow_merge_global_from(
cstring key)
 override {
 
  547        if (globals.count(key)) 
flow_merge(globals.at(key));
 
  549    void erase_global(
cstring key)
 override { globals.erase(key); }
 
  550    bool check_global(
cstring key)
 override { 
return globals.count(key) != 0; }
 
  551    void clear_globals()
 override { globals.clear(); }
 
  552    std::pair<cstring, ControlFlowVisitor *> save_global(
cstring key) {
 
  554        if (
auto i = globals.find(key); i != globals.end()) {
 
  558        return std::make_pair(key, cfv);
 
  560    void restore_global(std::pair<cstring, ControlFlowVisitor *> saved) {
 
  561        globals.erase(saved.first);
 
  562        if (saved.second) globals.emplace(saved.first, *saved.second);
 
  572            BUG_CHECK(!self.check_global(key), 
"ControlFlowVisitor global %s in use", key);
 
 
  579        std::vector<std::pair<cstring, ControlFlowVisitor *>> saved;
 
  583            saved.push_back(self.save_global(key));
 
  586            saved.push_back(self.save_global(k1));
 
  587            saved.push_back(self.save_global(k2));
 
  590            for (
auto it = saved.rbegin(); it != saved.rend(); ++it) self.restore_global(*it);
 
 
  594    bool has_flow_joins()
 const override { 
return !!flow_join_points; }
 
  595    const flow_join_info_t *flow_join_status(
const IR::Node *n)
 const {
 
  596        if (!flow_join_points || !flow_join_points->count(n)) 
return nullptr;
 
  597        return &flow_join_points->at(n);
 
 
  613    std::vector<Visitor *> visitors;
 
  614    int visit_next = 0, start_index = 0;
 
  623    void *
operator new(size_t);  
 
  628    bool finished() { 
return size_t(visit_next) >= visitors.size(); }
 
  629    virtual bool ready() { 
return !finished() && !paused; }
 
  630    void pause() { paused = 
true; }
 
  631    void unpause() { paused = 
false; }
 
  632    virtual void do_visit() = 0;
 
  633    virtual void run_visit() {
 
  634        auto *ctxt = v.getChildContext();
 
  635        start_index = ctxt ? ctxt->child_index : 0;
 
  637        while (!finished()) do_visit();
 
  638        for (
auto *cl : visitors) {
 
  642    virtual void dbprint(std::ostream &) 
const = 0;
 
 
  648    std::vector<const N **> nodes;
 
  649    std::vector<const N *const *> const_nodes;
 
  653    void addNode(
const N *&node) {
 
  654        BUG_CHECK(const_nodes.empty(), 
"Mixing const and non-const in SplitFlowVisit");
 
  655        BUG_CHECK(visitors.size() == nodes.size(), 
"size mismatch in SplitFlowVisit");
 
  656        BUG_CHECK(visit_next == 0, 
"Can't addNode to SplitFlowVisit after visiting started");
 
  657        visitors.push_back(visitors.empty() ? &v : &v.flow_clone());
 
  658        nodes.emplace_back(&node);
 
  660    void addNode(
const N *
const &node) {
 
  661        BUG_CHECK(nodes.empty(), 
"Mixing const and non-const in SplitFlowVisit");
 
  662        BUG_CHECK(visitors.size() == const_nodes.size(), 
"size mismatch in SplitFlowVisit");
 
  663        BUG_CHECK(visit_next == 0, 
"Can't addNode to SplitFlowVisit after visiting started");
 
  664        visitors.push_back(visitors.empty() ? &v : &v.flow_clone());
 
  665        const_nodes.emplace_back(&node);
 
  667    template <
class T1, 
class T2, 
class... Args>
 
  668    void addNode(T1 &&t1, T2 &&t2, Args &&...args) {
 
  669        addNode(std::forward<T1>(t1));
 
  670        addNode(std::forward<T2>(t2), std::forward<Args>(args)...);
 
  672    template <
class... Args>
 
  674        addNode(std::forward<Args>(args)...);
 
  676    void do_visit()
 override {
 
  678            BUG_CHECK(!paused, 
"trying to visit paused split_flow_visitor");
 
  679            int idx = visit_next++;
 
  681                visitors.at(idx)->visit(*const_nodes.at(idx), 
nullptr, start_index + idx);
 
  683                visitors.at(idx)->visit(*nodes.at(idx), 
nullptr, start_index + idx);
 
  686    void dbprint(std::ostream &out)
 const override {
 
  687        out << 
"SplitFlowVisit processed " << visit_next << 
" of " << visitors.size();
 
 
  695    std::vector<const IR::Node *> result;
 
  696    void init_visit(
size_t size) {
 
  697        if (size > 0) visitors.push_back(&v);
 
  698        while (visitors.size() < size) visitors.push_back(&v.flow_clone());
 
  703        result.resize(vec.size());
 
  704        init_visit(vec.size());
 
  708        init_visit(vec.size());
 
  710    void do_visit()
 override {
 
  712            BUG_CHECK(!paused, 
"trying to visit paused split_flow_visitor");
 
  713            int idx = visit_next++;
 
  715                result[idx] = visitors.at(idx)->apply_visitor(vec->at(idx));
 
  717                visitors.at(idx)->visit(const_vec->at(idx), 
nullptr, start_index + idx);
 
  720    void run_visit()
 override {
 
  721        SplitFlowVisit_base::run_visit();
 
  724            for (
auto i = vec->begin(); i != vec->end(); ++idx) {
 
  725                if (!result[idx] && *i) {
 
  727                } 
else if (result[idx] == *i) {
 
  729                } 
else if (
auto l = result[idx]->
template to<
IR::Vector<N>>()) {
 
  731                    i = vec->insert(i, l->begin(), l->end());
 
  733                } 
else if (
auto v = result[idx]->
template to<IR::VectorBase>()) {
 
  737                        i = vec->insert(i, v->size() - 1, 
nullptr);
 
  740                            if (
auto e = el->template to<N>())
 
  743                                BUG(
"visitor returned invalid type %s for Vector<%s>",
 
  744                                    el->node_type_name(), N::static_type_name());
 
  747                } 
else if (
auto e = result[idx]->
template to<N>()) {
 
  750                    CHECK_NULL(result[idx]);
 
  751                    BUG(
"visitor returned invalid type %s for Vector<%s>",
 
  752                        result[idx]->node_type_name(), N::static_type_name());
 
  757    void dbprint(std::ostream &out)
 const override {
 
  758        out << 
"SplitFlowVisitVector processed " << visit_next << 
" of " << visitors.size();
 
 
  811const RootType *modifyAllMatching(
const RootType *root, Func &&function) {
 
void warn(const int kind, const char *format, const T &node, Args &&...args)
The const ref variant of the above.
Definition visitor.h:305