ir_hv_accept.cpp revision 748f81a8eacabf07e1d26372a61683e6759a61a3
1/* 2 * Copyright © 2010 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#include "ir.h" 25 26/** 27 * \file ir_hv_accept.cpp 28 * Implementations of all hierarchical visitor accept methods for IR 29 * instructions. 30 */ 31 32/** 33 * Process a list of nodes using a hierarchical vistor 34 * 35 * \warning 36 * This function will operate correctly if a node being processed is removed 37 * from the list. However, if nodes are added to the list after the node being 38 * processed, some of the added nodes may not be processed. 39 */ 40ir_visitor_status 41visit_list_elements(ir_hierarchical_visitor *v, exec_list *l) 42{ 43 ir_instruction *prev_base_ir = v->base_ir; 44 45 foreach_list_safe(n, l) { 46 ir_instruction *const ir = (ir_instruction *) n; 47 v->base_ir = ir; 48 ir_visitor_status s = ir->accept(v); 49 50 if (s != visit_continue) 51 return s; 52 } 53 v->base_ir = prev_base_ir; 54 55 return visit_continue; 56} 57 58 59ir_visitor_status 60ir_variable::accept(ir_hierarchical_visitor *v) 61{ 62 return v->visit(this); 63} 64 65 66ir_visitor_status 67ir_loop::accept(ir_hierarchical_visitor *v) 68{ 69 ir_visitor_status s = v->visit_enter(this); 70 71 if (s != visit_continue) 72 return (s == visit_continue_with_parent) ? visit_continue : s; 73 74 s = visit_list_elements(v, &this->body_instructions); 75 if (s == visit_stop) 76 return s; 77 78 if (s != visit_continue_with_parent) { 79 if (this->from) { 80 s = this->from->accept(v); 81 if (s != visit_continue) 82 return (s == visit_continue_with_parent) ? visit_continue : s; 83 } 84 85 if (this->to) { 86 s = this->to->accept(v); 87 if (s != visit_continue) 88 return (s == visit_continue_with_parent) ? visit_continue : s; 89 } 90 91 if (this->increment) { 92 s = this->increment->accept(v); 93 if (s != visit_continue) 94 return (s == visit_continue_with_parent) ? visit_continue : s; 95 } 96 } 97 98 return v->visit_leave(this); 99} 100 101 102ir_visitor_status 103ir_loop_jump::accept(ir_hierarchical_visitor *v) 104{ 105 return v->visit(this); 106} 107 108 109ir_visitor_status 110ir_function_signature::accept(ir_hierarchical_visitor *v) 111{ 112 ir_visitor_status s = v->visit_enter(this); 113 if (s != visit_continue) 114 return (s == visit_continue_with_parent) ? visit_continue : s; 115 116 s = visit_list_elements(v, &this->parameters); 117 if (s == visit_stop) 118 return s; 119 120 s = visit_list_elements(v, &this->body); 121 return (s == visit_stop) ? s : v->visit_leave(this); 122} 123 124 125ir_visitor_status 126ir_function::accept(ir_hierarchical_visitor *v) 127{ 128 ir_visitor_status s = v->visit_enter(this); 129 if (s != visit_continue) 130 return (s == visit_continue_with_parent) ? visit_continue : s; 131 132 s = visit_list_elements(v, &this->signatures); 133 return (s == visit_stop) ? s : v->visit_leave(this); 134} 135 136 137ir_visitor_status 138ir_expression::accept(ir_hierarchical_visitor *v) 139{ 140 ir_visitor_status s = v->visit_enter(this); 141 142 if (s != visit_continue) 143 return (s == visit_continue_with_parent) ? visit_continue : s; 144 145 for (unsigned i = 0; i < this->get_num_operands(); i++) { 146 switch (this->operands[i]->accept(v)) { 147 case visit_continue: 148 break; 149 150 case visit_continue_with_parent: 151 // I wish for Java's labeled break-statement here. 152 goto done; 153 154 case visit_stop: 155 return s; 156 } 157 } 158 159done: 160 return v->visit_leave(this); 161} 162 163ir_visitor_status 164ir_texture::accept(ir_hierarchical_visitor *v) 165{ 166 ir_visitor_status s = v->visit_enter(this); 167 if (s != visit_continue) 168 return (s == visit_continue_with_parent) ? visit_continue : s; 169 170 s = this->sampler->accept(v); 171 if (s != visit_continue) 172 return (s == visit_continue_with_parent) ? visit_continue : s; 173 174 s = this->coordinate->accept(v); 175 if (s != visit_continue) 176 return (s == visit_continue_with_parent) ? visit_continue : s; 177 178 if (this->projector) { 179 s = this->projector->accept(v); 180 if (s != visit_continue) 181 return (s == visit_continue_with_parent) ? visit_continue : s; 182 } 183 184 if (this->shadow_comparitor) { 185 s = this->shadow_comparitor->accept(v); 186 if (s != visit_continue) 187 return (s == visit_continue_with_parent) ? visit_continue : s; 188 } 189 190 switch (this->op) { 191 case ir_tex: 192 break; 193 case ir_txb: 194 s = this->lod_info.bias->accept(v); 195 if (s != visit_continue) 196 return (s == visit_continue_with_parent) ? visit_continue : s; 197 break; 198 case ir_txl: 199 case ir_txf: 200 s = this->lod_info.lod->accept(v); 201 if (s != visit_continue) 202 return (s == visit_continue_with_parent) ? visit_continue : s; 203 break; 204 case ir_txd: 205 s = this->lod_info.grad.dPdx->accept(v); 206 if (s != visit_continue) 207 return (s == visit_continue_with_parent) ? visit_continue : s; 208 209 s = this->lod_info.grad.dPdy->accept(v); 210 if (s != visit_continue) 211 return (s == visit_continue_with_parent) ? visit_continue : s; 212 break; 213 } 214 215 return (s == visit_stop) ? s : v->visit_leave(this); 216} 217 218 219ir_visitor_status 220ir_swizzle::accept(ir_hierarchical_visitor *v) 221{ 222 ir_visitor_status s = v->visit_enter(this); 223 if (s != visit_continue) 224 return (s == visit_continue_with_parent) ? visit_continue : s; 225 226 s = this->val->accept(v); 227 return (s == visit_stop) ? s : v->visit_leave(this); 228} 229 230 231ir_visitor_status 232ir_dereference_variable::accept(ir_hierarchical_visitor *v) 233{ 234 return v->visit(this); 235} 236 237 238ir_visitor_status 239ir_dereference_array::accept(ir_hierarchical_visitor *v) 240{ 241 ir_visitor_status s = v->visit_enter(this); 242 if (s != visit_continue) 243 return (s == visit_continue_with_parent) ? visit_continue : s; 244 245 s = this->array_index->accept(v); 246 if (s != visit_continue) 247 return (s == visit_continue_with_parent) ? visit_continue : s; 248 249 s = this->array->accept(v); 250 return (s == visit_stop) ? s : v->visit_leave(this); 251} 252 253 254ir_visitor_status 255ir_dereference_record::accept(ir_hierarchical_visitor *v) 256{ 257 ir_visitor_status s = v->visit_enter(this); 258 if (s != visit_continue) 259 return (s == visit_continue_with_parent) ? visit_continue : s; 260 261 s = this->record->accept(v); 262 return (s == visit_stop) ? s : v->visit_leave(this); 263} 264 265 266ir_visitor_status 267ir_assignment::accept(ir_hierarchical_visitor *v) 268{ 269 ir_visitor_status s = v->visit_enter(this); 270 if (s != visit_continue) 271 return (s == visit_continue_with_parent) ? visit_continue : s; 272 273 s = this->lhs->accept(v); 274 if (s != visit_continue) 275 return (s == visit_continue_with_parent) ? visit_continue : s; 276 277 s = this->rhs->accept(v); 278 if (s != visit_continue) 279 return (s == visit_continue_with_parent) ? visit_continue : s; 280 281 if (this->condition) 282 s = this->condition->accept(v); 283 284 return (s == visit_stop) ? s : v->visit_leave(this); 285} 286 287 288ir_visitor_status 289ir_constant::accept(ir_hierarchical_visitor *v) 290{ 291 return v->visit(this); 292} 293 294 295ir_visitor_status 296ir_call::accept(ir_hierarchical_visitor *v) 297{ 298 ir_visitor_status s = v->visit_enter(this); 299 if (s != visit_continue) 300 return (s == visit_continue_with_parent) ? visit_continue : s; 301 302 s = visit_list_elements(v, &this->actual_parameters); 303 if (s == visit_stop) 304 return s; 305 306 return v->visit_leave(this); 307} 308 309 310ir_visitor_status 311ir_return::accept(ir_hierarchical_visitor *v) 312{ 313 ir_visitor_status s = v->visit_enter(this); 314 if (s != visit_continue) 315 return (s == visit_continue_with_parent) ? visit_continue : s; 316 317 ir_rvalue *val = this->get_value(); 318 if (val) { 319 s = val->accept(v); 320 if (s != visit_continue) 321 return (s == visit_continue_with_parent) ? visit_continue : s; 322 } 323 324 return v->visit_leave(this); 325} 326 327 328ir_visitor_status 329ir_discard::accept(ir_hierarchical_visitor *v) 330{ 331 ir_visitor_status s = v->visit_enter(this); 332 if (s != visit_continue) 333 return (s == visit_continue_with_parent) ? visit_continue : s; 334 335 if (this->condition != NULL) { 336 s = this->condition->accept(v); 337 if (s != visit_continue) 338 return (s == visit_continue_with_parent) ? visit_continue : s; 339 } 340 341 return v->visit_leave(this); 342} 343 344 345ir_visitor_status 346ir_if::accept(ir_hierarchical_visitor *v) 347{ 348 ir_visitor_status s = v->visit_enter(this); 349 if (s != visit_continue) 350 return (s == visit_continue_with_parent) ? visit_continue : s; 351 352 s = this->condition->accept(v); 353 if (s != visit_continue) 354 return (s == visit_continue_with_parent) ? visit_continue : s; 355 356 if (s != visit_continue_with_parent) { 357 s = visit_list_elements(v, &this->then_instructions); 358 if (s == visit_stop) 359 return s; 360 } 361 362 if (s != visit_continue_with_parent) { 363 s = visit_list_elements(v, &this->else_instructions); 364 if (s == visit_stop) 365 return s; 366 } 367 368 return v->visit_leave(this); 369} 370