11591693c7b415e9869157c711fe11263c95d74eDavid Li/* -*- c++ -*- */
21591693c7b415e9869157c711fe11263c95d74eDavid Li/*
31591693c7b415e9869157c711fe11263c95d74eDavid Li * Copyright © 2010 Intel Corporation
41591693c7b415e9869157c711fe11263c95d74eDavid Li *
51591693c7b415e9869157c711fe11263c95d74eDavid Li * Permission is hereby granted, free of charge, to any person obtaining a
61591693c7b415e9869157c711fe11263c95d74eDavid Li * copy of this software and associated documentation files (the "Software"),
71591693c7b415e9869157c711fe11263c95d74eDavid Li * to deal in the Software without restriction, including without limitation
81591693c7b415e9869157c711fe11263c95d74eDavid Li * the rights to use, copy, modify, merge, publish, distribute, sublicense,
91591693c7b415e9869157c711fe11263c95d74eDavid Li * and/or sell copies of the Software, and to permit persons to whom the
101591693c7b415e9869157c711fe11263c95d74eDavid Li * Software is furnished to do so, subject to the following conditions:
111591693c7b415e9869157c711fe11263c95d74eDavid Li *
121591693c7b415e9869157c711fe11263c95d74eDavid Li * The above copyright notice and this permission notice (including the next
131591693c7b415e9869157c711fe11263c95d74eDavid Li * paragraph) shall be included in all copies or substantial portions of the
141591693c7b415e9869157c711fe11263c95d74eDavid Li * Software.
151591693c7b415e9869157c711fe11263c95d74eDavid Li *
161591693c7b415e9869157c711fe11263c95d74eDavid Li * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171591693c7b415e9869157c711fe11263c95d74eDavid Li * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
181591693c7b415e9869157c711fe11263c95d74eDavid Li * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
191591693c7b415e9869157c711fe11263c95d74eDavid Li * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
201591693c7b415e9869157c711fe11263c95d74eDavid Li * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
211591693c7b415e9869157c711fe11263c95d74eDavid Li * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
221591693c7b415e9869157c711fe11263c95d74eDavid Li * DEALINGS IN THE SOFTWARE.
231591693c7b415e9869157c711fe11263c95d74eDavid Li */
241591693c7b415e9869157c711fe11263c95d74eDavid Li
251591693c7b415e9869157c711fe11263c95d74eDavid Li#pragma once
261591693c7b415e9869157c711fe11263c95d74eDavid Li#ifndef IR_HIERARCHICAL_VISITOR_H
271591693c7b415e9869157c711fe11263c95d74eDavid Li#define IR_HIERARCHICAL_VISITOR_H
281591693c7b415e9869157c711fe11263c95d74eDavid Li
291591693c7b415e9869157c711fe11263c95d74eDavid Li/**
301591693c7b415e9869157c711fe11263c95d74eDavid Li * Enumeration values returned by visit methods to guide processing
311591693c7b415e9869157c711fe11263c95d74eDavid Li */
321591693c7b415e9869157c711fe11263c95d74eDavid Lienum ir_visitor_status {
331591693c7b415e9869157c711fe11263c95d74eDavid Li   visit_continue,		/**< Continue visiting as normal. */
341591693c7b415e9869157c711fe11263c95d74eDavid Li   visit_continue_with_parent,	/**< Don't visit siblings, continue w/parent. */
351591693c7b415e9869157c711fe11263c95d74eDavid Li   visit_stop			/**< Stop visiting immediately. */
361591693c7b415e9869157c711fe11263c95d74eDavid Li};
371591693c7b415e9869157c711fe11263c95d74eDavid Li
381591693c7b415e9869157c711fe11263c95d74eDavid Li
391591693c7b415e9869157c711fe11263c95d74eDavid Li/**
401591693c7b415e9869157c711fe11263c95d74eDavid Li * Base class of hierarchical visitors of IR instruction trees
411591693c7b415e9869157c711fe11263c95d74eDavid Li *
421591693c7b415e9869157c711fe11263c95d74eDavid Li * Hierarchical visitors differ from traditional visitors in a couple of
431591693c7b415e9869157c711fe11263c95d74eDavid Li * important ways.  Rather than having a single \c visit method for each
441591693c7b415e9869157c711fe11263c95d74eDavid Li * subclass in the composite, there are three kinds of visit methods.
451591693c7b415e9869157c711fe11263c95d74eDavid Li * Leaf-node classes have a traditional \c visit method.  Internal-node
461591693c7b415e9869157c711fe11263c95d74eDavid Li * classes have a \c visit_enter method, which is invoked just before
471591693c7b415e9869157c711fe11263c95d74eDavid Li * processing child nodes, and a \c visit_leave method which is invoked just
481591693c7b415e9869157c711fe11263c95d74eDavid Li * after processing child nodes.
491591693c7b415e9869157c711fe11263c95d74eDavid Li *
501591693c7b415e9869157c711fe11263c95d74eDavid Li * In addition, each visit method and the \c accept methods in the composite
511591693c7b415e9869157c711fe11263c95d74eDavid Li * have a return value which guides the navigation.  Any of the visit methods
521591693c7b415e9869157c711fe11263c95d74eDavid Li * can choose to continue visiting the tree as normal (by returning \c
531591693c7b415e9869157c711fe11263c95d74eDavid Li * visit_continue), terminate visiting any further nodes immediately (by
541591693c7b415e9869157c711fe11263c95d74eDavid Li * returning \c visit_stop), or stop visiting sibling nodes (by returning \c
551591693c7b415e9869157c711fe11263c95d74eDavid Li * visit_continue_with_parent).
561591693c7b415e9869157c711fe11263c95d74eDavid Li *
571591693c7b415e9869157c711fe11263c95d74eDavid Li * These two changes combine to allow nagivation of children to be implemented
581591693c7b415e9869157c711fe11263c95d74eDavid Li * in the composite's \c accept method.  The \c accept method for a leaf-node
591591693c7b415e9869157c711fe11263c95d74eDavid Li * class will simply call the \c visit method, as usual, and pass its return
601591693c7b415e9869157c711fe11263c95d74eDavid Li * value on.  The \c accept method for internal-node classes will call the \c
611591693c7b415e9869157c711fe11263c95d74eDavid Li * visit_enter method, call the \c accpet method of each child node, and,
621591693c7b415e9869157c711fe11263c95d74eDavid Li * finally, call the \c visit_leave method.  If any of these return a value
631591693c7b415e9869157c711fe11263c95d74eDavid Li * other that \c visit_continue, the correct action must be taken.
641591693c7b415e9869157c711fe11263c95d74eDavid Li *
651591693c7b415e9869157c711fe11263c95d74eDavid Li * The final benefit is that the hierarchical visitor base class need not be
661591693c7b415e9869157c711fe11263c95d74eDavid Li * abstract.  Default implementations of every \c visit, \c visit_enter, and
671591693c7b415e9869157c711fe11263c95d74eDavid Li * \c visit_leave method can be provided.  By default each of these methods
681591693c7b415e9869157c711fe11263c95d74eDavid Li * simply returns \c visit_continue.  This allows a significant reduction in
691591693c7b415e9869157c711fe11263c95d74eDavid Li * derived class code.
701591693c7b415e9869157c711fe11263c95d74eDavid Li *
711591693c7b415e9869157c711fe11263c95d74eDavid Li * For more information about hierarchical visitors, see:
721591693c7b415e9869157c711fe11263c95d74eDavid Li *
731591693c7b415e9869157c711fe11263c95d74eDavid Li *    http://c2.com/cgi/wiki?HierarchicalVisitorPattern
741591693c7b415e9869157c711fe11263c95d74eDavid Li *    http://c2.com/cgi/wiki?HierarchicalVisitorDiscussion
751591693c7b415e9869157c711fe11263c95d74eDavid Li */
761591693c7b415e9869157c711fe11263c95d74eDavid Li
771591693c7b415e9869157c711fe11263c95d74eDavid Liclass ir_hierarchical_visitor {
781591693c7b415e9869157c711fe11263c95d74eDavid Lipublic:
791591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_hierarchical_visitor();
80d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li   virtual ~ir_hierarchical_visitor() { } // GCC error about accessible nonvirtual dctor
811591693c7b415e9869157c711fe11263c95d74eDavid Li
821591693c7b415e9869157c711fe11263c95d74eDavid Li   /**
831591693c7b415e9869157c711fe11263c95d74eDavid Li    * \name Visit methods for leaf-node classes
841591693c7b415e9869157c711fe11263c95d74eDavid Li    */
851591693c7b415e9869157c711fe11263c95d74eDavid Li   /*@{*/
861591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit(class ir_variable *);
871591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit(class ir_constant *);
881591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit(class ir_loop_jump *);
891591693c7b415e9869157c711fe11263c95d74eDavid Li
901591693c7b415e9869157c711fe11263c95d74eDavid Li   /**
911591693c7b415e9869157c711fe11263c95d74eDavid Li    * ir_dereference_variable isn't technically a leaf, but it is treated as a
921591693c7b415e9869157c711fe11263c95d74eDavid Li    * leaf here for a couple reasons.  By not automatically visiting the one
931591693c7b415e9869157c711fe11263c95d74eDavid Li    * child ir_variable node from the ir_dereference_variable, ir_variable
941591693c7b415e9869157c711fe11263c95d74eDavid Li    * nodes can always be handled as variable declarations.  Code that used
951591693c7b415e9869157c711fe11263c95d74eDavid Li    * non-hierarchical visitors had to set an "in a dereference" flag to
961591693c7b415e9869157c711fe11263c95d74eDavid Li    * determine how to handle an ir_variable.  By forcing the visitor to
971591693c7b415e9869157c711fe11263c95d74eDavid Li    * handle the ir_variable within the ir_dereference_variable visitor, this
981591693c7b415e9869157c711fe11263c95d74eDavid Li    * kludge can be avoided.
991591693c7b415e9869157c711fe11263c95d74eDavid Li    *
1001591693c7b415e9869157c711fe11263c95d74eDavid Li    * In addition, I can envision no use for having separate enter and leave
1011591693c7b415e9869157c711fe11263c95d74eDavid Li    * methods.  Anything that could be done in the enter and leave methods
1021591693c7b415e9869157c711fe11263c95d74eDavid Li    * that couldn't just be done in the visit method.
1031591693c7b415e9869157c711fe11263c95d74eDavid Li    */
1041591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit(class ir_dereference_variable *);
1051591693c7b415e9869157c711fe11263c95d74eDavid Li   /*@}*/
1061591693c7b415e9869157c711fe11263c95d74eDavid Li
1071591693c7b415e9869157c711fe11263c95d74eDavid Li   /**
1081591693c7b415e9869157c711fe11263c95d74eDavid Li    * \name Visit methods for internal-node classes
1091591693c7b415e9869157c711fe11263c95d74eDavid Li    */
1101591693c7b415e9869157c711fe11263c95d74eDavid Li   /*@{*/
1111591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_loop *);
1121591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_loop *);
1131591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_function_signature *);
1141591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_function_signature *);
1151591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_function *);
1161591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_function *);
1171591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_expression *);
1181591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_expression *);
1191591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_texture *);
1201591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_texture *);
1211591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_swizzle *);
1221591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_swizzle *);
1231591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_dereference_array *);
1241591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_dereference_array *);
1251591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_dereference_record *);
1261591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_dereference_record *);
1271591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_assignment *);
1281591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_assignment *);
1291591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_call *);
1301591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_call *);
1311591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_return *);
1321591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_return *);
1331591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_discard *);
1341591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_discard *);
1351591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_if *);
1361591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_if *);
1371591693c7b415e9869157c711fe11263c95d74eDavid Li   /*@}*/
1381591693c7b415e9869157c711fe11263c95d74eDavid Li
1391591693c7b415e9869157c711fe11263c95d74eDavid Li
1401591693c7b415e9869157c711fe11263c95d74eDavid Li   /**
1411591693c7b415e9869157c711fe11263c95d74eDavid Li    * Utility function to process a linked list of instructions with a visitor
1421591693c7b415e9869157c711fe11263c95d74eDavid Li    */
1431591693c7b415e9869157c711fe11263c95d74eDavid Li   void run(struct exec_list *instructions);
1441591693c7b415e9869157c711fe11263c95d74eDavid Li
1451591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Some visitors may need to insert new variable declarations and
1461591693c7b415e9869157c711fe11263c95d74eDavid Li    * assignments for portions of a subtree, which means they need a
1471591693c7b415e9869157c711fe11263c95d74eDavid Li    * pointer to the current instruction in the stream, not just their
1481591693c7b415e9869157c711fe11263c95d74eDavid Li    * node in the tree rooted at that instruction.
1491591693c7b415e9869157c711fe11263c95d74eDavid Li    *
1501591693c7b415e9869157c711fe11263c95d74eDavid Li    * This is implemented by visit_list_elements -- if the visitor is
1511591693c7b415e9869157c711fe11263c95d74eDavid Li    * not called by it, nothing good will happen.
1521591693c7b415e9869157c711fe11263c95d74eDavid Li    */
1531591693c7b415e9869157c711fe11263c95d74eDavid Li   class ir_instruction *base_ir;
1541591693c7b415e9869157c711fe11263c95d74eDavid Li
1551591693c7b415e9869157c711fe11263c95d74eDavid Li   /**
1561591693c7b415e9869157c711fe11263c95d74eDavid Li    * Callback function that is invoked on entry to each node visited.
1571591693c7b415e9869157c711fe11263c95d74eDavid Li    *
1581591693c7b415e9869157c711fe11263c95d74eDavid Li    * \warning
1591591693c7b415e9869157c711fe11263c95d74eDavid Li    * Visitor classes derived from \c ir_hierarchical_visitor \b may \b not
1601591693c7b415e9869157c711fe11263c95d74eDavid Li    * invoke this function.  This can be used, for example, to cause the
1611591693c7b415e9869157c711fe11263c95d74eDavid Li    * callback to be invoked on every node type execpt one.
1621591693c7b415e9869157c711fe11263c95d74eDavid Li    */
1631591693c7b415e9869157c711fe11263c95d74eDavid Li   void (*callback)(class ir_instruction *ir, void *data);
1641591693c7b415e9869157c711fe11263c95d74eDavid Li
1651591693c7b415e9869157c711fe11263c95d74eDavid Li   /**
1661591693c7b415e9869157c711fe11263c95d74eDavid Li    * Extra data parameter passed to the per-node callback function
1671591693c7b415e9869157c711fe11263c95d74eDavid Li    */
1681591693c7b415e9869157c711fe11263c95d74eDavid Li   void *data;
1691591693c7b415e9869157c711fe11263c95d74eDavid Li
1701591693c7b415e9869157c711fe11263c95d74eDavid Li   /**
1711591693c7b415e9869157c711fe11263c95d74eDavid Li    * Currently in the LHS of an assignment?
1721591693c7b415e9869157c711fe11263c95d74eDavid Li    *
1731591693c7b415e9869157c711fe11263c95d74eDavid Li    * This is set and cleared by the \c ir_assignment::accept method.
1741591693c7b415e9869157c711fe11263c95d74eDavid Li    */
1751591693c7b415e9869157c711fe11263c95d74eDavid Li   bool in_assignee;
1761591693c7b415e9869157c711fe11263c95d74eDavid Li};
1771591693c7b415e9869157c711fe11263c95d74eDavid Li
1781591693c7b415e9869157c711fe11263c95d74eDavid Livoid visit_tree(ir_instruction *ir,
1791591693c7b415e9869157c711fe11263c95d74eDavid Li		void (*callback)(class ir_instruction *ir, void *data),
1801591693c7b415e9869157c711fe11263c95d74eDavid Li		void *data);
1811591693c7b415e9869157c711fe11263c95d74eDavid Li
1821591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status visit_list_elements(ir_hierarchical_visitor *v, exec_list *l);
1831591693c7b415e9869157c711fe11263c95d74eDavid Li
1841591693c7b415e9869157c711fe11263c95d74eDavid Li#endif /* IR_HIERARCHICAL_VISITOR_H */
185