1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* -*- c++ -*- */
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright © 2010 Intel Corporation
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"),
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or sell copies of the Software, and to permit persons to whom the
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software is furnished to do so, subject to the following conditions:
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the next
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * paragraph) shall be included in all copies or substantial portions of the
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software.
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * DEALINGS IN THE SOFTWARE.
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#pragma once
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef IR_HIERARCHICAL_VISITOR_H
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define IR_HIERARCHICAL_VISITOR_H
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Enumeration values returned by visit methods to guide processing
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgenum ir_visitor_status {
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   visit_continue,		/**< Continue visiting as normal. */
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   visit_continue_with_parent,	/**< Don't visit siblings, continue w/parent. */
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   visit_stop			/**< Stop visiting immediately. */
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Base class of hierarchical visitors of IR instruction trees
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Hierarchical visitors differ from traditional visitors in a couple of
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * important ways.  Rather than having a single \c visit method for each
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * subclass in the composite, there are three kinds of visit methods.
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Leaf-node classes have a traditional \c visit method.  Internal-node
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * classes have a \c visit_enter method, which is invoked just before
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * processing child nodes, and a \c visit_leave method which is invoked just
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * after processing child nodes.
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * In addition, each visit method and the \c accept methods in the composite
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * have a return value which guides the navigation.  Any of the visit methods
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * can choose to continue visiting the tree as normal (by returning \c
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * visit_continue), terminate visiting any further nodes immediately (by
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * returning \c visit_stop), or stop visiting sibling nodes (by returning \c
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * visit_continue_with_parent).
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * These two changes combine to allow nagivation of children to be implemented
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * in the composite's \c accept method.  The \c accept method for a leaf-node
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * class will simply call the \c visit method, as usual, and pass its return
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * value on.  The \c accept method for internal-node classes will call the \c
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * visit_enter method, call the \c accpet method of each child node, and,
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * finally, call the \c visit_leave method.  If any of these return a value
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * other that \c visit_continue, the correct action must be taken.
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The final benefit is that the hierarchical visitor base class need not be
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * abstract.  Default implementations of every \c visit, \c visit_enter, and
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \c visit_leave method can be provided.  By default each of these methods
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * simply returns \c visit_continue.  This allows a significant reduction in
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * derived class code.
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * For more information about hierarchical visitors, see:
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    http://c2.com/cgi/wiki?HierarchicalVisitorPattern
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    http://c2.com/cgi/wiki?HierarchicalVisitorDiscussion
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass ir_hierarchical_visitor {
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_hierarchical_visitor();
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * \name Visit methods for leaf-node classes
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /*@{*/
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit(class ir_rvalue *);
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit(class ir_variable *);
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit(class ir_constant *);
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit(class ir_loop_jump *);
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * ir_dereference_variable isn't technically a leaf, but it is treated as a
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * leaf here for a couple reasons.  By not automatically visiting the one
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * child ir_variable node from the ir_dereference_variable, ir_variable
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * nodes can always be handled as variable declarations.  Code that used
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * non-hierarchical visitors had to set an "in a dereference" flag to
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * determine how to handle an ir_variable.  By forcing the visitor to
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * handle the ir_variable within the ir_dereference_variable visitor, this
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * kludge can be avoided.
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * In addition, I can envision no use for having separate enter and leave
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * methods.  Anything that could be done in the enter and leave methods
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * that couldn't just be done in the visit method.
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit(class ir_dereference_variable *);
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /*@}*/
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * \name Visit methods for internal-node classes
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /*@{*/
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_loop *);
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_loop *);
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_function_signature *);
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_function_signature *);
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_function *);
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_function *);
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_expression *);
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_expression *);
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_texture *);
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_texture *);
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_swizzle *);
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_swizzle *);
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_dereference_array *);
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_dereference_array *);
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_dereference_record *);
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_dereference_record *);
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_assignment *);
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_assignment *);
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_call *);
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_call *);
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_return *);
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_return *);
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_discard *);
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_discard *);
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_if *);
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_if *);
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /*@}*/
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Utility function to process a linked list of instructions with a visitor
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void run(struct exec_list *instructions);
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Some visitors may need to insert new variable declarations and
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * assignments for portions of a subtree, which means they need a
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * pointer to the current instruction in the stream, not just their
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * node in the tree rooted at that instruction.
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * This is implemented by visit_list_elements -- if the visitor is
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * not called by it, nothing good will happen.
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   class ir_instruction *base_ir;
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Callback function that is invoked on entry to each node visited.
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * \warning
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Visitor classes derived from \c ir_hierarchical_visitor \b may \b not
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * invoke this function.  This can be used, for example, to cause the
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * callback to be invoked on every node type execpt one.
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void (*callback)(class ir_instruction *ir, void *data);
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Extra data parameter passed to the per-node callback function
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *data;
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Currently in the LHS of an assignment?
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * This is set and cleared by the \c ir_assignment::accept method.
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool in_assignee;
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid visit_tree(ir_instruction *ir,
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		void (*callback)(class ir_instruction *ir, void *data),
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		void *data);
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status visit_list_elements(ir_hierarchical_visitor *v, exec_list *l,
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                      bool statement_list = true);
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif /* IR_HIERARCHICAL_VISITOR_H */
186