Home | History | Annotate | Download | only in glsl
      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  */
     40 ir_visitor_status
     41 visit_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 
     59 ir_visitor_status
     60 ir_variable::accept(ir_hierarchical_visitor *v)
     61 {
     62    return v->visit(this);
     63 }
     64 
     65 
     66 ir_visitor_status
     67 ir_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 
    102 ir_visitor_status
    103 ir_loop_jump::accept(ir_hierarchical_visitor *v)
    104 {
    105    return v->visit(this);
    106 }
    107 
    108 
    109 ir_visitor_status
    110 ir_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 
    125 ir_visitor_status
    126 ir_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 
    137 ir_visitor_status
    138 ir_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 
    159 done:
    160    return v->visit_leave(this);
    161 }
    162 
    163 ir_visitor_status
    164 ir_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 
    219 ir_visitor_status
    220 ir_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 
    231 ir_visitor_status
    232 ir_dereference_variable::accept(ir_hierarchical_visitor *v)
    233 {
    234    return v->visit(this);
    235 }
    236 
    237 
    238 ir_visitor_status
    239 ir_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    /* The array index is not the target of the assignment, so clear the
    246     * 'in_assignee' flag.  Restore it after returning from the array index.
    247     */
    248    const bool was_in_assignee = v->in_assignee;
    249    v->in_assignee = false;
    250    s = this->array_index->accept(v);
    251    v->in_assignee = was_in_assignee;
    252 
    253    if (s != visit_continue)
    254       return (s == visit_continue_with_parent) ? visit_continue : s;
    255 
    256    s = this->array->accept(v);
    257    return (s == visit_stop) ? s : v->visit_leave(this);
    258 }
    259 
    260 
    261 ir_visitor_status
    262 ir_dereference_record::accept(ir_hierarchical_visitor *v)
    263 {
    264    ir_visitor_status s = v->visit_enter(this);
    265    if (s != visit_continue)
    266       return (s == visit_continue_with_parent) ? visit_continue : s;
    267 
    268    s = this->record->accept(v);
    269    return (s == visit_stop) ? s : v->visit_leave(this);
    270 }
    271 
    272 
    273 ir_visitor_status
    274 ir_assignment::accept(ir_hierarchical_visitor *v)
    275 {
    276    ir_visitor_status s = v->visit_enter(this);
    277    if (s != visit_continue)
    278       return (s == visit_continue_with_parent) ? visit_continue : s;
    279 
    280    v->in_assignee = true;
    281    s = this->lhs->accept(v);
    282    v->in_assignee = false;
    283    if (s != visit_continue)
    284       return (s == visit_continue_with_parent) ? visit_continue : s;
    285 
    286    s = this->rhs->accept(v);
    287    if (s != visit_continue)
    288       return (s == visit_continue_with_parent) ? visit_continue : s;
    289 
    290    if (this->condition)
    291       s = this->condition->accept(v);
    292 
    293    return (s == visit_stop) ? s : v->visit_leave(this);
    294 }
    295 
    296 
    297 ir_visitor_status
    298 ir_constant::accept(ir_hierarchical_visitor *v)
    299 {
    300    return v->visit(this);
    301 }
    302 
    303 
    304 ir_visitor_status
    305 ir_call::accept(ir_hierarchical_visitor *v)
    306 {
    307    ir_visitor_status s = v->visit_enter(this);
    308    if (s != visit_continue)
    309       return (s == visit_continue_with_parent) ? visit_continue : s;
    310 
    311    s = visit_list_elements(v, &this->actual_parameters);
    312    if (s == visit_stop)
    313       return s;
    314 
    315    return v->visit_leave(this);
    316 }
    317 
    318 
    319 ir_visitor_status
    320 ir_return::accept(ir_hierarchical_visitor *v)
    321 {
    322    ir_visitor_status s = v->visit_enter(this);
    323    if (s != visit_continue)
    324       return (s == visit_continue_with_parent) ? visit_continue : s;
    325 
    326    ir_rvalue *val = this->get_value();
    327    if (val) {
    328       s = val->accept(v);
    329       if (s != visit_continue)
    330 	 return (s == visit_continue_with_parent) ? visit_continue : s;
    331    }
    332 
    333    return v->visit_leave(this);
    334 }
    335 
    336 
    337 ir_visitor_status
    338 ir_discard::accept(ir_hierarchical_visitor *v)
    339 {
    340    ir_visitor_status s = v->visit_enter(this);
    341    if (s != visit_continue)
    342       return (s == visit_continue_with_parent) ? visit_continue : s;
    343 
    344    if (this->condition != NULL) {
    345       s = this->condition->accept(v);
    346       if (s != visit_continue)
    347 	 return (s == visit_continue_with_parent) ? visit_continue : s;
    348    }
    349 
    350    return v->visit_leave(this);
    351 }
    352 
    353 
    354 ir_visitor_status
    355 ir_if::accept(ir_hierarchical_visitor *v)
    356 {
    357    ir_visitor_status s = v->visit_enter(this);
    358    if (s != visit_continue)
    359       return (s == visit_continue_with_parent) ? visit_continue : s;
    360 
    361    s = this->condition->accept(v);
    362    if (s != visit_continue)
    363       return (s == visit_continue_with_parent) ? visit_continue : s;
    364 
    365    if (s != visit_continue_with_parent) {
    366       s = visit_list_elements(v, &this->then_instructions);
    367       if (s == visit_stop)
    368 	 return s;
    369    }
    370 
    371    if (s != visit_continue_with_parent) {
    372       s = visit_list_elements(v, &this->else_instructions);
    373       if (s == visit_stop)
    374 	 return s;
    375    }
    376 
    377    return v->visit_leave(this);
    378 }
    379