1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2010 Intel Corporation 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21b8e80941Smrg * DEALINGS IN THE SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg#include "ir.h" 25b8e80941Smrg 26b8e80941Smrg/** 27b8e80941Smrg * \file ir_hv_accept.cpp 28b8e80941Smrg * Implementations of all hierarchical visitor accept methods for IR 29b8e80941Smrg * instructions. 30b8e80941Smrg */ 31b8e80941Smrg 32b8e80941Smrg/** 33b8e80941Smrg * Process a list of nodes using a hierarchical vistor. 34b8e80941Smrg * 35b8e80941Smrg * If statement_list is true (the default), this is a list of statements, so 36b8e80941Smrg * v->base_ir will be set to point to each statement just before iterating 37b8e80941Smrg * over it, and restored after iteration is complete. If statement_list is 38b8e80941Smrg * false, this is a list that appears inside a statement (e.g. a parameter 39b8e80941Smrg * list), so v->base_ir will be left alone. 40b8e80941Smrg * 41b8e80941Smrg * \warning 42b8e80941Smrg * This function will operate correctly if a node being processed is removed 43b8e80941Smrg * from the list. However, if nodes are added to the list after the node being 44b8e80941Smrg * processed, some of the added nodes may not be processed. 45b8e80941Smrg */ 46b8e80941Smrgir_visitor_status 47b8e80941Smrgvisit_list_elements(ir_hierarchical_visitor *v, exec_list *l, 48b8e80941Smrg bool statement_list) 49b8e80941Smrg{ 50b8e80941Smrg ir_instruction *prev_base_ir = v->base_ir; 51b8e80941Smrg 52b8e80941Smrg foreach_in_list_safe(ir_instruction, ir, l) { 53b8e80941Smrg if (statement_list) 54b8e80941Smrg v->base_ir = ir; 55b8e80941Smrg ir_visitor_status s = ir->accept(v); 56b8e80941Smrg 57b8e80941Smrg if (s != visit_continue) 58b8e80941Smrg return s; 59b8e80941Smrg } 60b8e80941Smrg if (statement_list) 61b8e80941Smrg v->base_ir = prev_base_ir; 62b8e80941Smrg 63b8e80941Smrg return visit_continue; 64b8e80941Smrg} 65b8e80941Smrg 66b8e80941Smrg 67b8e80941Smrgir_visitor_status 68b8e80941Smrgir_rvalue::accept(ir_hierarchical_visitor *v) 69b8e80941Smrg{ 70b8e80941Smrg return v->visit(this); 71b8e80941Smrg} 72b8e80941Smrg 73b8e80941Smrg 74b8e80941Smrgir_visitor_status 75b8e80941Smrgir_variable::accept(ir_hierarchical_visitor *v) 76b8e80941Smrg{ 77b8e80941Smrg return v->visit(this); 78b8e80941Smrg} 79b8e80941Smrg 80b8e80941Smrg 81b8e80941Smrgir_visitor_status 82b8e80941Smrgir_loop::accept(ir_hierarchical_visitor *v) 83b8e80941Smrg{ 84b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 85b8e80941Smrg 86b8e80941Smrg if (s != visit_continue) 87b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 88b8e80941Smrg 89b8e80941Smrg s = visit_list_elements(v, &this->body_instructions); 90b8e80941Smrg if (s == visit_stop) 91b8e80941Smrg return s; 92b8e80941Smrg 93b8e80941Smrg return v->visit_leave(this); 94b8e80941Smrg} 95b8e80941Smrg 96b8e80941Smrg 97b8e80941Smrgir_visitor_status 98b8e80941Smrgir_loop_jump::accept(ir_hierarchical_visitor *v) 99b8e80941Smrg{ 100b8e80941Smrg return v->visit(this); 101b8e80941Smrg} 102b8e80941Smrg 103b8e80941Smrg 104b8e80941Smrgir_visitor_status 105b8e80941Smrgir_function_signature::accept(ir_hierarchical_visitor *v) 106b8e80941Smrg{ 107b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 108b8e80941Smrg if (s != visit_continue) 109b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 110b8e80941Smrg 111b8e80941Smrg s = visit_list_elements(v, &this->parameters); 112b8e80941Smrg if (s == visit_stop) 113b8e80941Smrg return s; 114b8e80941Smrg 115b8e80941Smrg s = visit_list_elements(v, &this->body); 116b8e80941Smrg return (s == visit_stop) ? s : v->visit_leave(this); 117b8e80941Smrg} 118b8e80941Smrg 119b8e80941Smrg 120b8e80941Smrgir_visitor_status 121b8e80941Smrgir_function::accept(ir_hierarchical_visitor *v) 122b8e80941Smrg{ 123b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 124b8e80941Smrg if (s != visit_continue) 125b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 126b8e80941Smrg 127b8e80941Smrg s = visit_list_elements(v, &this->signatures, false); 128b8e80941Smrg return (s == visit_stop) ? s : v->visit_leave(this); 129b8e80941Smrg} 130b8e80941Smrg 131b8e80941Smrg 132b8e80941Smrgir_visitor_status 133b8e80941Smrgir_expression::accept(ir_hierarchical_visitor *v) 134b8e80941Smrg{ 135b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 136b8e80941Smrg 137b8e80941Smrg if (s != visit_continue) 138b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 139b8e80941Smrg 140b8e80941Smrg for (unsigned i = 0; i < this->num_operands; i++) { 141b8e80941Smrg switch (this->operands[i]->accept(v)) { 142b8e80941Smrg case visit_continue: 143b8e80941Smrg break; 144b8e80941Smrg 145b8e80941Smrg case visit_continue_with_parent: 146b8e80941Smrg // I wish for Java's labeled break-statement here. 147b8e80941Smrg goto done; 148b8e80941Smrg 149b8e80941Smrg case visit_stop: 150b8e80941Smrg return visit_stop; 151b8e80941Smrg } 152b8e80941Smrg } 153b8e80941Smrg 154b8e80941Smrgdone: 155b8e80941Smrg return v->visit_leave(this); 156b8e80941Smrg} 157b8e80941Smrg 158b8e80941Smrgir_visitor_status 159b8e80941Smrgir_texture::accept(ir_hierarchical_visitor *v) 160b8e80941Smrg{ 161b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 162b8e80941Smrg if (s != visit_continue) 163b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 164b8e80941Smrg 165b8e80941Smrg s = this->sampler->accept(v); 166b8e80941Smrg if (s != visit_continue) 167b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 168b8e80941Smrg 169b8e80941Smrg if (this->coordinate) { 170b8e80941Smrg s = this->coordinate->accept(v); 171b8e80941Smrg if (s != visit_continue) 172b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 173b8e80941Smrg } 174b8e80941Smrg 175b8e80941Smrg if (this->projector) { 176b8e80941Smrg s = this->projector->accept(v); 177b8e80941Smrg if (s != visit_continue) 178b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 179b8e80941Smrg } 180b8e80941Smrg 181b8e80941Smrg if (this->shadow_comparator) { 182b8e80941Smrg s = this->shadow_comparator->accept(v); 183b8e80941Smrg if (s != visit_continue) 184b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 185b8e80941Smrg } 186b8e80941Smrg 187b8e80941Smrg if (this->offset) { 188b8e80941Smrg s = this->offset->accept(v); 189b8e80941Smrg if (s != visit_continue) 190b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 191b8e80941Smrg } 192b8e80941Smrg 193b8e80941Smrg switch (this->op) { 194b8e80941Smrg case ir_tex: 195b8e80941Smrg case ir_lod: 196b8e80941Smrg case ir_query_levels: 197b8e80941Smrg case ir_texture_samples: 198b8e80941Smrg case ir_samples_identical: 199b8e80941Smrg break; 200b8e80941Smrg case ir_txb: 201b8e80941Smrg s = this->lod_info.bias->accept(v); 202b8e80941Smrg if (s != visit_continue) 203b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 204b8e80941Smrg break; 205b8e80941Smrg case ir_txl: 206b8e80941Smrg case ir_txf: 207b8e80941Smrg case ir_txs: 208b8e80941Smrg s = this->lod_info.lod->accept(v); 209b8e80941Smrg if (s != visit_continue) 210b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 211b8e80941Smrg break; 212b8e80941Smrg case ir_txf_ms: 213b8e80941Smrg s = this->lod_info.sample_index->accept(v); 214b8e80941Smrg if (s != visit_continue) 215b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 216b8e80941Smrg break; 217b8e80941Smrg case ir_txd: 218b8e80941Smrg s = this->lod_info.grad.dPdx->accept(v); 219b8e80941Smrg if (s != visit_continue) 220b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 221b8e80941Smrg 222b8e80941Smrg s = this->lod_info.grad.dPdy->accept(v); 223b8e80941Smrg if (s != visit_continue) 224b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 225b8e80941Smrg break; 226b8e80941Smrg case ir_tg4: 227b8e80941Smrg s = this->lod_info.component->accept(v); 228b8e80941Smrg if (s != visit_continue) 229b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 230b8e80941Smrg break; 231b8e80941Smrg } 232b8e80941Smrg 233b8e80941Smrg assert(s == visit_continue); 234b8e80941Smrg return v->visit_leave(this); 235b8e80941Smrg} 236b8e80941Smrg 237b8e80941Smrg 238b8e80941Smrgir_visitor_status 239b8e80941Smrgir_swizzle::accept(ir_hierarchical_visitor *v) 240b8e80941Smrg{ 241b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 242b8e80941Smrg if (s != visit_continue) 243b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 244b8e80941Smrg 245b8e80941Smrg s = this->val->accept(v); 246b8e80941Smrg return (s == visit_stop) ? s : v->visit_leave(this); 247b8e80941Smrg} 248b8e80941Smrg 249b8e80941Smrg 250b8e80941Smrgir_visitor_status 251b8e80941Smrgir_dereference_variable::accept(ir_hierarchical_visitor *v) 252b8e80941Smrg{ 253b8e80941Smrg return v->visit(this); 254b8e80941Smrg} 255b8e80941Smrg 256b8e80941Smrg 257b8e80941Smrgir_visitor_status 258b8e80941Smrgir_dereference_array::accept(ir_hierarchical_visitor *v) 259b8e80941Smrg{ 260b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 261b8e80941Smrg if (s != visit_continue) 262b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 263b8e80941Smrg 264b8e80941Smrg /* The array index is not the target of the assignment, so clear the 265b8e80941Smrg * 'in_assignee' flag. Restore it after returning from the array index. 266b8e80941Smrg */ 267b8e80941Smrg const bool was_in_assignee = v->in_assignee; 268b8e80941Smrg v->in_assignee = false; 269b8e80941Smrg s = this->array_index->accept(v); 270b8e80941Smrg v->in_assignee = was_in_assignee; 271b8e80941Smrg 272b8e80941Smrg if (s != visit_continue) 273b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 274b8e80941Smrg 275b8e80941Smrg s = this->array->accept(v); 276b8e80941Smrg return (s == visit_stop) ? s : v->visit_leave(this); 277b8e80941Smrg} 278b8e80941Smrg 279b8e80941Smrg 280b8e80941Smrgir_visitor_status 281b8e80941Smrgir_dereference_record::accept(ir_hierarchical_visitor *v) 282b8e80941Smrg{ 283b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 284b8e80941Smrg if (s != visit_continue) 285b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 286b8e80941Smrg 287b8e80941Smrg s = this->record->accept(v); 288b8e80941Smrg return (s == visit_stop) ? s : v->visit_leave(this); 289b8e80941Smrg} 290b8e80941Smrg 291b8e80941Smrg 292b8e80941Smrgir_visitor_status 293b8e80941Smrgir_assignment::accept(ir_hierarchical_visitor *v) 294b8e80941Smrg{ 295b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 296b8e80941Smrg if (s != visit_continue) 297b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 298b8e80941Smrg 299b8e80941Smrg v->in_assignee = true; 300b8e80941Smrg s = this->lhs->accept(v); 301b8e80941Smrg v->in_assignee = false; 302b8e80941Smrg if (s != visit_continue) 303b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 304b8e80941Smrg 305b8e80941Smrg s = this->rhs->accept(v); 306b8e80941Smrg if (s != visit_continue) 307b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 308b8e80941Smrg 309b8e80941Smrg if (this->condition) 310b8e80941Smrg s = this->condition->accept(v); 311b8e80941Smrg 312b8e80941Smrg return (s == visit_stop) ? s : v->visit_leave(this); 313b8e80941Smrg} 314b8e80941Smrg 315b8e80941Smrg 316b8e80941Smrgir_visitor_status 317b8e80941Smrgir_constant::accept(ir_hierarchical_visitor *v) 318b8e80941Smrg{ 319b8e80941Smrg return v->visit(this); 320b8e80941Smrg} 321b8e80941Smrg 322b8e80941Smrg 323b8e80941Smrgir_visitor_status 324b8e80941Smrgir_call::accept(ir_hierarchical_visitor *v) 325b8e80941Smrg{ 326b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 327b8e80941Smrg if (s != visit_continue) 328b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 329b8e80941Smrg 330b8e80941Smrg if (this->return_deref != NULL) { 331b8e80941Smrg v->in_assignee = true; 332b8e80941Smrg s = this->return_deref->accept(v); 333b8e80941Smrg v->in_assignee = false; 334b8e80941Smrg if (s != visit_continue) 335b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 336b8e80941Smrg } 337b8e80941Smrg 338b8e80941Smrg s = visit_list_elements(v, &this->actual_parameters, false); 339b8e80941Smrg if (s == visit_stop) 340b8e80941Smrg return s; 341b8e80941Smrg 342b8e80941Smrg return v->visit_leave(this); 343b8e80941Smrg} 344b8e80941Smrg 345b8e80941Smrg 346b8e80941Smrgir_visitor_status 347b8e80941Smrgir_return::accept(ir_hierarchical_visitor *v) 348b8e80941Smrg{ 349b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 350b8e80941Smrg if (s != visit_continue) 351b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 352b8e80941Smrg 353b8e80941Smrg ir_rvalue *val = this->get_value(); 354b8e80941Smrg if (val) { 355b8e80941Smrg s = val->accept(v); 356b8e80941Smrg if (s != visit_continue) 357b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 358b8e80941Smrg } 359b8e80941Smrg 360b8e80941Smrg return v->visit_leave(this); 361b8e80941Smrg} 362b8e80941Smrg 363b8e80941Smrg 364b8e80941Smrgir_visitor_status 365b8e80941Smrgir_discard::accept(ir_hierarchical_visitor *v) 366b8e80941Smrg{ 367b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 368b8e80941Smrg if (s != visit_continue) 369b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 370b8e80941Smrg 371b8e80941Smrg if (this->condition != NULL) { 372b8e80941Smrg s = this->condition->accept(v); 373b8e80941Smrg if (s != visit_continue) 374b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 375b8e80941Smrg } 376b8e80941Smrg 377b8e80941Smrg return v->visit_leave(this); 378b8e80941Smrg} 379b8e80941Smrg 380b8e80941Smrg 381b8e80941Smrgir_visitor_status 382b8e80941Smrgir_if::accept(ir_hierarchical_visitor *v) 383b8e80941Smrg{ 384b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 385b8e80941Smrg if (s != visit_continue) 386b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 387b8e80941Smrg 388b8e80941Smrg s = this->condition->accept(v); 389b8e80941Smrg if (s != visit_continue) 390b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 391b8e80941Smrg 392b8e80941Smrg if (s != visit_continue_with_parent) { 393b8e80941Smrg s = visit_list_elements(v, &this->then_instructions); 394b8e80941Smrg if (s == visit_stop) 395b8e80941Smrg return s; 396b8e80941Smrg } 397b8e80941Smrg 398b8e80941Smrg if (s != visit_continue_with_parent) { 399b8e80941Smrg s = visit_list_elements(v, &this->else_instructions); 400b8e80941Smrg if (s == visit_stop) 401b8e80941Smrg return s; 402b8e80941Smrg } 403b8e80941Smrg 404b8e80941Smrg return v->visit_leave(this); 405b8e80941Smrg} 406b8e80941Smrg 407b8e80941Smrgir_visitor_status 408b8e80941Smrgir_emit_vertex::accept(ir_hierarchical_visitor *v) 409b8e80941Smrg{ 410b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 411b8e80941Smrg if (s != visit_continue) 412b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 413b8e80941Smrg 414b8e80941Smrg s = this->stream->accept(v); 415b8e80941Smrg if (s != visit_continue) 416b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 417b8e80941Smrg 418b8e80941Smrg assert(s == visit_continue); 419b8e80941Smrg return v->visit_leave(this); 420b8e80941Smrg} 421b8e80941Smrg 422b8e80941Smrg 423b8e80941Smrgir_visitor_status 424b8e80941Smrgir_end_primitive::accept(ir_hierarchical_visitor *v) 425b8e80941Smrg{ 426b8e80941Smrg ir_visitor_status s = v->visit_enter(this); 427b8e80941Smrg if (s != visit_continue) 428b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 429b8e80941Smrg 430b8e80941Smrg s = this->stream->accept(v); 431b8e80941Smrg if (s != visit_continue) 432b8e80941Smrg return (s == visit_continue_with_parent) ? visit_continue : s; 433b8e80941Smrg 434b8e80941Smrg assert(s == visit_continue); 435b8e80941Smrg return v->visit_leave(this); 436b8e80941Smrg} 437b8e80941Smrg 438b8e80941Smrgir_visitor_status 439b8e80941Smrgir_barrier::accept(ir_hierarchical_visitor *v) 440b8e80941Smrg{ 441b8e80941Smrg return v->visit(this); 442b8e80941Smrg} 443