ir_hv_accept.cpp revision 16efab1c4dee6e6a827ba5f1c482378159545ae5
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 list. However, if nodes are added to the list after the node being 38 * processed, some of the added noded may not be processed. 39 */ 40static ir_visitor_status 41visit_list_elements(ir_hierarchical_visitor *v, exec_list *l) 42{ 43 exec_node *next; 44 45 for (exec_node *n = l->head; n->next != NULL; n = next) { 46 next = n->next; 47 48 ir_instruction *const ir = (ir_instruction *) n; 49 ir_visitor_status s = ir->accept(v); 50 51 if (s != visit_continue) 52 return s; 53 } 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->body); 117 return (s == visit_stop) ? s : v->visit_leave(this); 118} 119 120 121ir_visitor_status 122ir_function::accept(ir_hierarchical_visitor *v) 123{ 124 ir_visitor_status s = v->visit_enter(this); 125 if (s != visit_continue) 126 return (s == visit_continue_with_parent) ? visit_continue : s; 127 128 s = visit_list_elements(v, &this->signatures); 129 return (s == visit_stop) ? s : v->visit_leave(this); 130} 131 132 133ir_visitor_status 134ir_expression::accept(ir_hierarchical_visitor *v) 135{ 136 ir_visitor_status s = v->visit_enter(this); 137 138 if (s != visit_continue) 139 return (s == visit_continue_with_parent) ? visit_continue : s; 140 141 for (unsigned i = 0; i < this->get_num_operands(); i++) { 142 switch (this->operands[i]->accept(v)) { 143 case visit_continue: 144 break; 145 146 case visit_continue_with_parent: 147 // I wish for Java's labeled break-statement here. 148 goto done; 149 150 case visit_stop: 151 return s; 152 } 153 } 154 155done: 156 return v->visit_leave(this); 157} 158 159ir_visitor_status 160ir_texture::accept(ir_hierarchical_visitor *v) 161{ 162 ir_visitor_status s = v->visit_enter(this); 163 if (s != visit_continue) 164 return (s == visit_continue_with_parent) ? visit_continue : s; 165 166 s = this->sampler->accept(v); 167 if (s != visit_continue) 168 return (s == visit_continue_with_parent) ? visit_continue : s; 169 170 s = this->coordinate->accept(v); 171 if (s != visit_continue) 172 return (s == visit_continue_with_parent) ? visit_continue : s; 173 174 if (this->projector) { 175 s = this->projector->accept(v); 176 if (s != visit_continue) 177 return (s == visit_continue_with_parent) ? visit_continue : s; 178 } 179 180 if (this->shadow_comparitor) { 181 s = this->shadow_comparitor->accept(v); 182 if (s != visit_continue) 183 return (s == visit_continue_with_parent) ? visit_continue : s; 184 } 185 186 switch (this->op) { 187 case ir_tex: 188 break; 189 case ir_txb: 190 s = this->lod_info.bias->accept(v); 191 if (s != visit_continue) 192 return (s == visit_continue_with_parent) ? visit_continue : s; 193 break; 194 case ir_txl: 195 case ir_txf: 196 s = this->lod_info.lod->accept(v); 197 if (s != visit_continue) 198 return (s == visit_continue_with_parent) ? visit_continue : s; 199 break; 200 case ir_txd: 201 s = this->lod_info.grad.dPdx->accept(v); 202 if (s != visit_continue) 203 return (s == visit_continue_with_parent) ? visit_continue : s; 204 205 s = this->lod_info.grad.dPdy->accept(v); 206 if (s != visit_continue) 207 return (s == visit_continue_with_parent) ? visit_continue : s; 208 break; 209 } 210 211 return visit_continue_with_parent; 212} 213 214 215ir_visitor_status 216ir_swizzle::accept(ir_hierarchical_visitor *v) 217{ 218 ir_visitor_status s = v->visit_enter(this); 219 if (s != visit_continue) 220 return (s == visit_continue_with_parent) ? visit_continue : s; 221 222 s = this->val->accept(v); 223 return (s == visit_stop) ? s : v->visit_leave(this); 224} 225 226 227ir_visitor_status 228ir_dereference_variable::accept(ir_hierarchical_visitor *v) 229{ 230 return v->visit(this); 231} 232 233 234ir_visitor_status 235ir_dereference_array::accept(ir_hierarchical_visitor *v) 236{ 237 ir_visitor_status s = v->visit_enter(this); 238 if (s != visit_continue) 239 return (s == visit_continue_with_parent) ? visit_continue : s; 240 241 s = this->array_index->accept(v); 242 if (s != visit_continue) 243 return (s == visit_continue_with_parent) ? visit_continue : s; 244 245 s = this->array->accept(v); 246 return (s == visit_stop) ? s : v->visit_leave(this); 247} 248 249 250ir_visitor_status 251ir_dereference_record::accept(ir_hierarchical_visitor *v) 252{ 253 ir_visitor_status s = v->visit_enter(this); 254 if (s != visit_continue) 255 return (s == visit_continue_with_parent) ? visit_continue : s; 256 257 s = this->record->accept(v); 258 return (s == visit_stop) ? s : v->visit_leave(this); 259} 260 261 262ir_visitor_status 263ir_assignment::accept(ir_hierarchical_visitor *v) 264{ 265 ir_visitor_status s = v->visit_enter(this); 266 if (s != visit_continue) 267 return (s == visit_continue_with_parent) ? visit_continue : s; 268 269 s = this->lhs->accept(v); 270 if (s != visit_continue) 271 return (s == visit_continue_with_parent) ? visit_continue : s; 272 273 s = this->rhs->accept(v); 274 if (s != visit_continue) 275 return (s == visit_continue_with_parent) ? visit_continue : s; 276 277 if (this->condition) 278 s = this->condition->accept(v); 279 280 return (s == visit_stop) ? s : v->visit_leave(this); 281} 282 283 284ir_visitor_status 285ir_constant::accept(ir_hierarchical_visitor *v) 286{ 287 return v->visit(this); 288} 289 290 291ir_visitor_status 292ir_call::accept(ir_hierarchical_visitor *v) 293{ 294 ir_visitor_status s = v->visit_enter(this); 295 if (s != visit_continue) 296 return (s == visit_continue_with_parent) ? visit_continue : s; 297 298 s = visit_list_elements(v, &this->actual_parameters); 299 if (s == visit_stop) 300 return s; 301 302 return v->visit_leave(this); 303} 304 305 306ir_visitor_status 307ir_return::accept(ir_hierarchical_visitor *v) 308{ 309 ir_visitor_status s = v->visit_enter(this); 310 if (s != visit_continue) 311 return (s == visit_continue_with_parent) ? visit_continue : s; 312 313 ir_rvalue *val = this->get_value(); 314 if (val) { 315 s = val->accept(v); 316 if (s != visit_continue) 317 return (s == visit_continue_with_parent) ? visit_continue : s; 318 } 319 320 return v->visit_leave(this); 321} 322 323 324ir_visitor_status 325ir_discard::accept(ir_hierarchical_visitor *v) 326{ 327 ir_visitor_status s = v->visit_enter(this); 328 if (s != visit_continue) 329 return (s == visit_continue_with_parent) ? visit_continue : s; 330 331 if (this->condition != NULL) { 332 s = this->condition->accept(v); 333 if (s != visit_continue) 334 return (s == visit_continue_with_parent) ? visit_continue : s; 335 } 336 337 return v->visit_leave(this); 338} 339 340 341ir_visitor_status 342ir_if::accept(ir_hierarchical_visitor *v) 343{ 344 ir_visitor_status s = v->visit_enter(this); 345 if (s != visit_continue) 346 return (s == visit_continue_with_parent) ? visit_continue : s; 347 348 s = this->condition->accept(v); 349 if (s != visit_continue) 350 return (s == visit_continue_with_parent) ? visit_continue : s; 351 352 if (s != visit_continue_with_parent) { 353 s = visit_list_elements(v, &this->then_instructions); 354 if (s == visit_stop) 355 return s; 356 } 357 358 if (s != visit_continue_with_parent) { 359 s = visit_list_elements(v, &this->else_instructions); 360 if (s == visit_stop) 361 return s; 362 } 363 364 return v->visit_leave(this); 365} 366