ir_hv_accept.cpp revision d884f60861f270cdcf7d9d47765efcf1e1de30b6
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 * If statement_list is true (the default), this is a list of statements, so 36 * v->base_ir will be set to point to each statement just before iterating 37 * over it, and restored after iteration is complete. If statement_list is 38 * false, this is a list that appears inside a statement (e.g. a parameter 39 * list), so v->base_ir will be left alone. 40 * 41 * \warning 42 * This function will operate correctly if a node being processed is removed 43 * from the list. However, if nodes are added to the list after the node being 44 * processed, some of the added nodes may not be processed. 45 */ 46ir_visitor_status 47visit_list_elements(ir_hierarchical_visitor *v, exec_list *l, 48 bool statement_list) 49{ 50 ir_instruction *prev_base_ir = v->base_ir; 51 52 foreach_list_safe(n, l) { 53 ir_instruction *const ir = (ir_instruction *) n; 54 if (statement_list) 55 v->base_ir = ir; 56 ir_visitor_status s = ir->accept(v); 57 58 if (s != visit_continue) 59 return s; 60 } 61 if (statement_list) 62 v->base_ir = prev_base_ir; 63 64 return visit_continue; 65} 66 67 68ir_visitor_status 69ir_rvalue::accept(ir_hierarchical_visitor *v) 70{ 71 return v->visit(this); 72} 73 74 75ir_visitor_status 76ir_variable::accept(ir_hierarchical_visitor *v) 77{ 78 return v->visit(this); 79} 80 81 82ir_visitor_status 83ir_loop::accept(ir_hierarchical_visitor *v) 84{ 85 ir_visitor_status s = v->visit_enter(this); 86 87 if (s != visit_continue) 88 return (s == visit_continue_with_parent) ? visit_continue : s; 89 90 s = visit_list_elements(v, &this->body_instructions); 91 if (s == visit_stop) 92 return s; 93 94 if (s != visit_continue_with_parent) { 95 if (this->from) { 96 s = this->from->accept(v); 97 if (s != visit_continue) 98 return (s == visit_continue_with_parent) ? visit_continue : s; 99 } 100 101 if (this->to) { 102 s = this->to->accept(v); 103 if (s != visit_continue) 104 return (s == visit_continue_with_parent) ? visit_continue : s; 105 } 106 107 if (this->increment) { 108 s = this->increment->accept(v); 109 if (s != visit_continue) 110 return (s == visit_continue_with_parent) ? visit_continue : s; 111 } 112 } 113 114 return v->visit_leave(this); 115} 116 117 118ir_visitor_status 119ir_loop_jump::accept(ir_hierarchical_visitor *v) 120{ 121 return v->visit(this); 122} 123 124 125ir_visitor_status 126ir_function_signature::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->parameters); 133 if (s == visit_stop) 134 return s; 135 136 s = visit_list_elements(v, &this->body); 137 return (s == visit_stop) ? s : v->visit_leave(this); 138} 139 140 141ir_visitor_status 142ir_function::accept(ir_hierarchical_visitor *v) 143{ 144 ir_visitor_status s = v->visit_enter(this); 145 if (s != visit_continue) 146 return (s == visit_continue_with_parent) ? visit_continue : s; 147 148 s = visit_list_elements(v, &this->signatures, false); 149 return (s == visit_stop) ? s : v->visit_leave(this); 150} 151 152 153ir_visitor_status 154ir_expression::accept(ir_hierarchical_visitor *v) 155{ 156 ir_visitor_status s = v->visit_enter(this); 157 158 if (s != visit_continue) 159 return (s == visit_continue_with_parent) ? visit_continue : s; 160 161 for (unsigned i = 0; i < this->get_num_operands(); i++) { 162 switch (this->operands[i]->accept(v)) { 163 case visit_continue: 164 break; 165 166 case visit_continue_with_parent: 167 // I wish for Java's labeled break-statement here. 168 goto done; 169 170 case visit_stop: 171 return s; 172 } 173 } 174 175done: 176 return v->visit_leave(this); 177} 178 179ir_visitor_status 180ir_texture::accept(ir_hierarchical_visitor *v) 181{ 182 ir_visitor_status s = v->visit_enter(this); 183 if (s != visit_continue) 184 return (s == visit_continue_with_parent) ? visit_continue : s; 185 186 s = this->sampler->accept(v); 187 if (s != visit_continue) 188 return (s == visit_continue_with_parent) ? visit_continue : s; 189 190 if (this->coordinate) { 191 s = this->coordinate->accept(v); 192 if (s != visit_continue) 193 return (s == visit_continue_with_parent) ? visit_continue : s; 194 } 195 196 if (this->projector) { 197 s = this->projector->accept(v); 198 if (s != visit_continue) 199 return (s == visit_continue_with_parent) ? visit_continue : s; 200 } 201 202 if (this->shadow_comparitor) { 203 s = this->shadow_comparitor->accept(v); 204 if (s != visit_continue) 205 return (s == visit_continue_with_parent) ? visit_continue : s; 206 } 207 208 if (this->offset) { 209 s = this->offset->accept(v); 210 if (s != visit_continue) 211 return (s == visit_continue_with_parent) ? visit_continue : s; 212 } 213 214 switch (this->op) { 215 case ir_tex: 216 break; 217 case ir_txb: 218 s = this->lod_info.bias->accept(v); 219 if (s != visit_continue) 220 return (s == visit_continue_with_parent) ? visit_continue : s; 221 break; 222 case ir_txl: 223 case ir_txf: 224 case ir_txs: 225 s = this->lod_info.lod->accept(v); 226 if (s != visit_continue) 227 return (s == visit_continue_with_parent) ? visit_continue : s; 228 break; 229 case ir_txd: 230 s = this->lod_info.grad.dPdx->accept(v); 231 if (s != visit_continue) 232 return (s == visit_continue_with_parent) ? visit_continue : s; 233 234 s = this->lod_info.grad.dPdy->accept(v); 235 if (s != visit_continue) 236 return (s == visit_continue_with_parent) ? visit_continue : s; 237 break; 238 } 239 240 return (s == visit_stop) ? s : v->visit_leave(this); 241} 242 243 244ir_visitor_status 245ir_swizzle::accept(ir_hierarchical_visitor *v) 246{ 247 ir_visitor_status s = v->visit_enter(this); 248 if (s != visit_continue) 249 return (s == visit_continue_with_parent) ? visit_continue : s; 250 251 s = this->val->accept(v); 252 return (s == visit_stop) ? s : v->visit_leave(this); 253} 254 255 256ir_visitor_status 257ir_dereference_variable::accept(ir_hierarchical_visitor *v) 258{ 259 return v->visit(this); 260} 261 262 263ir_visitor_status 264ir_dereference_array::accept(ir_hierarchical_visitor *v) 265{ 266 ir_visitor_status s = v->visit_enter(this); 267 if (s != visit_continue) 268 return (s == visit_continue_with_parent) ? visit_continue : s; 269 270 /* The array index is not the target of the assignment, so clear the 271 * 'in_assignee' flag. Restore it after returning from the array index. 272 */ 273 const bool was_in_assignee = v->in_assignee; 274 v->in_assignee = false; 275 s = this->array_index->accept(v); 276 v->in_assignee = was_in_assignee; 277 278 if (s != visit_continue) 279 return (s == visit_continue_with_parent) ? visit_continue : s; 280 281 s = this->array->accept(v); 282 return (s == visit_stop) ? s : v->visit_leave(this); 283} 284 285 286ir_visitor_status 287ir_dereference_record::accept(ir_hierarchical_visitor *v) 288{ 289 ir_visitor_status s = v->visit_enter(this); 290 if (s != visit_continue) 291 return (s == visit_continue_with_parent) ? visit_continue : s; 292 293 s = this->record->accept(v); 294 return (s == visit_stop) ? s : v->visit_leave(this); 295} 296 297 298ir_visitor_status 299ir_assignment::accept(ir_hierarchical_visitor *v) 300{ 301 ir_visitor_status s = v->visit_enter(this); 302 if (s != visit_continue) 303 return (s == visit_continue_with_parent) ? visit_continue : s; 304 305 v->in_assignee = true; 306 s = this->lhs->accept(v); 307 v->in_assignee = false; 308 if (s != visit_continue) 309 return (s == visit_continue_with_parent) ? visit_continue : s; 310 311 s = this->rhs->accept(v); 312 if (s != visit_continue) 313 return (s == visit_continue_with_parent) ? visit_continue : s; 314 315 if (this->condition) 316 s = this->condition->accept(v); 317 318 return (s == visit_stop) ? s : v->visit_leave(this); 319} 320 321 322ir_visitor_status 323ir_constant::accept(ir_hierarchical_visitor *v) 324{ 325 return v->visit(this); 326} 327 328 329ir_visitor_status 330ir_call::accept(ir_hierarchical_visitor *v) 331{ 332 ir_visitor_status s = v->visit_enter(this); 333 if (s != visit_continue) 334 return (s == visit_continue_with_parent) ? visit_continue : s; 335 336 if (this->return_deref != NULL) { 337 v->in_assignee = true; 338 s = this->return_deref->accept(v); 339 v->in_assignee = false; 340 if (s != visit_continue) 341 return (s == visit_continue_with_parent) ? visit_continue : s; 342 } 343 344 s = visit_list_elements(v, &this->actual_parameters, false); 345 if (s == visit_stop) 346 return s; 347 348 return v->visit_leave(this); 349} 350 351 352ir_visitor_status 353ir_return::accept(ir_hierarchical_visitor *v) 354{ 355 ir_visitor_status s = v->visit_enter(this); 356 if (s != visit_continue) 357 return (s == visit_continue_with_parent) ? visit_continue : s; 358 359 ir_rvalue *val = this->get_value(); 360 if (val) { 361 s = val->accept(v); 362 if (s != visit_continue) 363 return (s == visit_continue_with_parent) ? visit_continue : s; 364 } 365 366 return v->visit_leave(this); 367} 368 369 370ir_visitor_status 371ir_discard::accept(ir_hierarchical_visitor *v) 372{ 373 ir_visitor_status s = v->visit_enter(this); 374 if (s != visit_continue) 375 return (s == visit_continue_with_parent) ? visit_continue : s; 376 377 if (this->condition != NULL) { 378 s = this->condition->accept(v); 379 if (s != visit_continue) 380 return (s == visit_continue_with_parent) ? visit_continue : s; 381 } 382 383 return v->visit_leave(this); 384} 385 386 387ir_visitor_status 388ir_if::accept(ir_hierarchical_visitor *v) 389{ 390 ir_visitor_status s = v->visit_enter(this); 391 if (s != visit_continue) 392 return (s == visit_continue_with_parent) ? visit_continue : s; 393 394 s = this->condition->accept(v); 395 if (s != visit_continue) 396 return (s == visit_continue_with_parent) ? visit_continue : s; 397 398 if (s != visit_continue_with_parent) { 399 s = visit_list_elements(v, &this->then_instructions); 400 if (s == visit_stop) 401 return s; 402 } 403 404 if (s != visit_continue_with_parent) { 405 s = visit_list_elements(v, &this->else_instructions); 406 if (s == visit_stop) 407 return s; 408 } 409 410 return v->visit_leave(this); 411} 412