18895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick/* -*- c++ -*- */ 28895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick/* 38895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * Copyright © 2010 Intel Corporation 48895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * 58895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * Permission is hereby granted, free of charge, to any person obtaining a 68895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * copy of this software and associated documentation files (the "Software"), 78895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * to deal in the Software without restriction, including without limitation 88895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * the rights to use, copy, modify, merge, publish, distribute, sublicense, 98895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * and/or sell copies of the Software, and to permit persons to whom the 108895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * Software is furnished to do so, subject to the following conditions: 118895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * 128895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * The above copyright notice and this permission notice (including the next 138895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * paragraph) shall be included in all copies or substantial portions of the 148895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * Software. 158895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * 168895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 178895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 188895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 198895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 208895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 218895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 228895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * DEALINGS IN THE SOFTWARE. 238895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick */ 248895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick 258895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick#pragma once 268895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick#ifndef IR_HIERARCHICAL_VISITOR_H 278895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick#define IR_HIERARCHICAL_VISITOR_H 288895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick 298895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick/** 308895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * Enumeration values returned by visit methods to guide processing 318895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick */ 328895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanickenum ir_visitor_status { 338895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick visit_continue, /**< Continue visiting as normal. */ 348895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick visit_continue_with_parent, /**< Don't visit siblings, continue w/parent. */ 358895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick visit_stop /**< Stop visiting immediately. */ 368895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick}; 378895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick 388895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick 398895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick/** 408895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * Base class of hierarchical visitors of IR instruction trees 418895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * 428895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * Hierarchical visitors differ from traditional visitors in a couple of 438895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * important ways. Rather than having a single \c visit method for each 448895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * subclass in the composite, there are three kinds of visit methods. 458895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * Leaf-node classes have a traditional \c visit method. Internal-node 468895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * classes have a \c visit_enter method, which is invoked just before 478895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * processing child nodes, and a \c visit_leave method which is invoked just 488895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * after processing child nodes. 498895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * 508895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * In addition, each visit method and the \c accept methods in the composite 518895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * have a return value which guides the navigation. Any of the visit methods 528895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * can choose to continue visiting the tree as normal (by returning \c 538895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * visit_continue), terminate visiting any further nodes immediately (by 548895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * returning \c visit_stop), or stop visiting sibling nodes (by returning \c 558895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * visit_continue_with_parent). 568895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * 578895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * These two changes combine to allow nagivation of children to be implemented 588895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * in the composite's \c accept method. The \c accept method for a leaf-node 598895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * class will simply call the \c visit method, as usual, and pass its return 608895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * value on. The \c accept method for internal-node classes will call the \c 618895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * visit_enter method, call the \c accpet method of each child node, and, 628895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * finally, call the \c visit_leave method. If any of these return a value 638895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * other that \c visit_continue, the correct action must be taken. 648895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * 658895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * The final benefit is that the hierarchical visitor base class need not be 668895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * abstract. Default implementations of every \c visit, \c visit_enter, and 678895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * \c visit_leave method can be provided. By default each of these methods 688895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * simply returns \c visit_continue. This allows a significant reduction in 698895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * derived class code. 708895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * 718895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * For more information about hierarchical visitors, see: 728895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * 738895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * http://c2.com/cgi/wiki?HierarchicalVisitorPattern 748895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * http://c2.com/cgi/wiki?HierarchicalVisitorDiscussion 758895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick */ 768895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick 778895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanickclass ir_hierarchical_visitor { 788895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanickpublic: 797c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick ir_hierarchical_visitor(); 807c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick 818895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick /** 828895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * \name Visit methods for leaf-node classes 838895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick */ 848895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick /*@{*/ 85807e967c615dc80a264af5a89af7649f95481744Kenneth Graunke virtual ir_visitor_status visit(class ir_rvalue *); 868895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit(class ir_variable *); 878895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit(class ir_constant *); 888895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit(class ir_loop_jump *); 89f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick 90f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick /** 91f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick * ir_dereference_variable isn't technically a leaf, but it is treated as a 92f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick * leaf here for a couple reasons. By not automatically visiting the one 93f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick * child ir_variable node from the ir_dereference_variable, ir_variable 94f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick * nodes can always be handled as variable declarations. Code that used 95f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick * non-hierarchical visitors had to set an "in a dereference" flag to 96f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick * determine how to handle an ir_variable. By forcing the visitor to 97a22426dc4c934673e8f0af5c70a67505a4de7aadCarl Worth * handle the ir_variable within the ir_dereference_variable visitor, this 98f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick * kludge can be avoided. 99f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick * 100f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick * In addition, I can envision no use for having separate enter and leave 101f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick * methods. Anything that could be done in the enter and leave methods 102f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick * that couldn't just be done in the visit method. 103f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick */ 104f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick virtual ir_visitor_status visit(class ir_dereference_variable *); 1058895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick /*@}*/ 1068895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick 1078895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick /** 1088895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * \name Visit methods for internal-node classes 1098895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick */ 1108895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick /*@{*/ 1118895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_enter(class ir_loop *); 1128895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_leave(class ir_loop *); 1138895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_enter(class ir_function_signature *); 1148895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_leave(class ir_function_signature *); 1158895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_enter(class ir_function *); 1168895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_leave(class ir_function *); 1178895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_enter(class ir_expression *); 1188895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_leave(class ir_expression *); 11926d74cd1d140786b8f4b1ccbaf500a16e68eec3cKenneth Graunke virtual ir_visitor_status visit_enter(class ir_texture *); 12026d74cd1d140786b8f4b1ccbaf500a16e68eec3cKenneth Graunke virtual ir_visitor_status visit_leave(class ir_texture *); 1218895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_enter(class ir_swizzle *); 1228895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_leave(class ir_swizzle *); 123f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick virtual ir_visitor_status visit_enter(class ir_dereference_array *); 124f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick virtual ir_visitor_status visit_leave(class ir_dereference_array *); 125f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick virtual ir_visitor_status visit_enter(class ir_dereference_record *); 126f3a002b503542fe2544025c6a42d552fdc4907c2Ian Romanick virtual ir_visitor_status visit_leave(class ir_dereference_record *); 1278895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_enter(class ir_assignment *); 1288895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_leave(class ir_assignment *); 1298895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_enter(class ir_call *); 1308895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_leave(class ir_call *); 1318895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_enter(class ir_return *); 1328895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_leave(class ir_return *); 13316efab1c4dee6e6a827ba5f1c482378159545ae5Kenneth Graunke virtual ir_visitor_status visit_enter(class ir_discard *); 13416efab1c4dee6e6a827ba5f1c482378159545ae5Kenneth Graunke virtual ir_visitor_status visit_leave(class ir_discard *); 1358895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_enter(class ir_if *); 1368895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick virtual ir_visitor_status visit_leave(class ir_if *); 1378895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick /*@}*/ 1388895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick 1398895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick 1408895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick /** 1418895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick * Utility function to process a linked list of instructions with a visitor 1428895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick */ 1438895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick void run(struct exec_list *instructions); 1447c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick 1458a1f186cc55979bb9df0a88b48da8d81460c3e7cEric Anholt /* Some visitors may need to insert new variable declarations and 1468a1f186cc55979bb9df0a88b48da8d81460c3e7cEric Anholt * assignments for portions of a subtree, which means they need a 1478a1f186cc55979bb9df0a88b48da8d81460c3e7cEric Anholt * pointer to the current instruction in the stream, not just their 1488a1f186cc55979bb9df0a88b48da8d81460c3e7cEric Anholt * node in the tree rooted at that instruction. 1498a1f186cc55979bb9df0a88b48da8d81460c3e7cEric Anholt * 1508a1f186cc55979bb9df0a88b48da8d81460c3e7cEric Anholt * This is implemented by visit_list_elements -- if the visitor is 1518a1f186cc55979bb9df0a88b48da8d81460c3e7cEric Anholt * not called by it, nothing good will happen. 1528a1f186cc55979bb9df0a88b48da8d81460c3e7cEric Anholt */ 1538a1f186cc55979bb9df0a88b48da8d81460c3e7cEric Anholt class ir_instruction *base_ir; 1548a1f186cc55979bb9df0a88b48da8d81460c3e7cEric Anholt 1557c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick /** 1567c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick * Callback function that is invoked on entry to each node visited. 1577c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick * 1587c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick * \warning 1597c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick * Visitor classes derived from \c ir_hierarchical_visitor \b may \b not 1607c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick * invoke this function. This can be used, for example, to cause the 1617c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick * callback to be invoked on every node type execpt one. 1627c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick */ 1637c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick void (*callback)(class ir_instruction *ir, void *data); 1647c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick 1657c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick /** 1667c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick * Extra data parameter passed to the per-node callback function 1677c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick */ 1687c09576a97be3490fe36fff9241b9c148ba558cbIan Romanick void *data; 169c8ee8e07f7cc8f18d367ffcec065b45f8a6976f4Ian Romanick 170c8ee8e07f7cc8f18d367ffcec065b45f8a6976f4Ian Romanick /** 171c8ee8e07f7cc8f18d367ffcec065b45f8a6976f4Ian Romanick * Currently in the LHS of an assignment? 172c8ee8e07f7cc8f18d367ffcec065b45f8a6976f4Ian Romanick * 173c8ee8e07f7cc8f18d367ffcec065b45f8a6976f4Ian Romanick * This is set and cleared by the \c ir_assignment::accept method. 174c8ee8e07f7cc8f18d367ffcec065b45f8a6976f4Ian Romanick */ 175c8ee8e07f7cc8f18d367ffcec065b45f8a6976f4Ian Romanick bool in_assignee; 1768895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick}; 1778895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick 178f66ba4f3579d69841176bfe7ced9df80eac57a80Eric Anholtvoid visit_tree(ir_instruction *ir, 179f66ba4f3579d69841176bfe7ced9df80eac57a80Eric Anholt void (*callback)(class ir_instruction *ir, void *data), 180f66ba4f3579d69841176bfe7ced9df80eac57a80Eric Anholt void *data); 181f66ba4f3579d69841176bfe7ced9df80eac57a80Eric Anholt 182cc81eb09b928389f926b3512c18b3298777d2928Paul Berryir_visitor_status visit_list_elements(ir_hierarchical_visitor *v, exec_list *l, 183cc81eb09b928389f926b3512c18b3298777d2928Paul Berry bool statement_list = true); 1848a1f186cc55979bb9df0a88b48da8d81460c3e7cEric Anholt 1858895bae55ba8d9f62dd59cbd924ac37c8a7dcdb1Ian Romanick#endif /* IR_HIERARCHICAL_VISITOR_H */ 186