Home | History | Annotate | Download | only in MachineIndependent
      1 //
      2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
      3 // Copyright (C) 2013 LunarG, Inc.
      4 // Copyright (c) 2002-2010 The ANGLE Project Authors.
      5 //
      6 // All rights reserved.
      7 //
      8 // Redistribution and use in source and binary forms, with or without
      9 // modification, are permitted provided that the following conditions
     10 // are met:
     11 //
     12 //    Redistributions of source code must retain the above copyright
     13 //    notice, this list of conditions and the following disclaimer.
     14 //
     15 //    Redistributions in binary form must reproduce the above
     16 //    copyright notice, this list of conditions and the following
     17 //    disclaimer in the documentation and/or other materials provided
     18 //    with the distribution.
     19 //
     20 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
     21 //    contributors may be used to endorse or promote products derived
     22 //    from this software without specific prior written permission.
     23 //
     24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     27 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     28 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     29 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     30 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     31 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     32 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     34 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35 // POSSIBILITY OF SUCH DAMAGE.
     36 //
     37 
     38 #include "../Include/intermediate.h"
     39 
     40 namespace glslang {
     41 
     42 //
     43 // Traverse the intermediate representation tree, and
     44 // call a node type specific function for each node.
     45 // Done recursively through the member function Traverse().
     46 // Node types can be skipped if their function to call is 0,
     47 // but their subtree will still be traversed.
     48 // Nodes with children can have their whole subtree skipped
     49 // if preVisit is turned on and the type specific function
     50 // returns false.
     51 //
     52 // preVisit, postVisit, and rightToLeft control what order
     53 // nodes are visited in.
     54 //
     55 
     56 //
     57 // Traversal functions for terminals are straightforward....
     58 //
     59 void TIntermMethod::traverse(TIntermTraverser*)
     60 {
     61     // Tree should always resolve all methods as a non-method.
     62 }
     63 
     64 void TIntermSymbol::traverse(TIntermTraverser *it)
     65 {
     66     it->visitSymbol(this);
     67 }
     68 
     69 void TIntermConstantUnion::traverse(TIntermTraverser *it)
     70 {
     71     it->visitConstantUnion(this);
     72 }
     73 
     74 //
     75 // Traverse a binary node.
     76 //
     77 void TIntermBinary::traverse(TIntermTraverser *it)
     78 {
     79     bool visit = true;
     80 
     81     //
     82     // visit the node before children if pre-visiting.
     83     //
     84     if (it->preVisit)
     85         visit = it->visitBinary(EvPreVisit, this);
     86 
     87     //
     88     // Visit the children, in the right order.
     89     //
     90     if (visit) {
     91         it->incrementDepth(this);
     92 
     93         if (it->rightToLeft) {
     94             if (right)
     95                 right->traverse(it);
     96 
     97             if (it->inVisit)
     98                 visit = it->visitBinary(EvInVisit, this);
     99 
    100             if (visit && left)
    101                 left->traverse(it);
    102         } else {
    103             if (left)
    104                 left->traverse(it);
    105 
    106             if (it->inVisit)
    107                 visit = it->visitBinary(EvInVisit, this);
    108 
    109             if (visit && right)
    110                 right->traverse(it);
    111         }
    112 
    113         it->decrementDepth();
    114     }
    115 
    116     //
    117     // Visit the node after the children, if requested and the traversal
    118     // hasn't been canceled yet.
    119     //
    120     if (visit && it->postVisit)
    121         it->visitBinary(EvPostVisit, this);
    122 }
    123 
    124 //
    125 // Traverse a unary node.  Same comments in binary node apply here.
    126 //
    127 void TIntermUnary::traverse(TIntermTraverser *it)
    128 {
    129     bool visit = true;
    130 
    131     if (it->preVisit)
    132         visit = it->visitUnary(EvPreVisit, this);
    133 
    134     if (visit) {
    135         it->incrementDepth(this);
    136         operand->traverse(it);
    137         it->decrementDepth();
    138     }
    139 
    140     if (visit && it->postVisit)
    141         it->visitUnary(EvPostVisit, this);
    142 }
    143 
    144 //
    145 // Traverse an aggregate node.  Same comments in binary node apply here.
    146 //
    147 void TIntermAggregate::traverse(TIntermTraverser *it)
    148 {
    149     bool visit = true;
    150 
    151     if (it->preVisit)
    152         visit = it->visitAggregate(EvPreVisit, this);
    153 
    154     if (visit) {
    155         it->incrementDepth(this);
    156 
    157         if (it->rightToLeft) {
    158             for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) {
    159                 (*sit)->traverse(it);
    160 
    161                 if (visit && it->inVisit) {
    162                     if (*sit != sequence.front())
    163                         visit = it->visitAggregate(EvInVisit, this);
    164                 }
    165             }
    166         } else {
    167             for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) {
    168                 (*sit)->traverse(it);
    169 
    170                 if (visit && it->inVisit) {
    171                     if (*sit != sequence.back())
    172                         visit = it->visitAggregate(EvInVisit, this);
    173                 }
    174             }
    175         }
    176 
    177         it->decrementDepth();
    178     }
    179 
    180     if (visit && it->postVisit)
    181         it->visitAggregate(EvPostVisit, this);
    182 }
    183 
    184 //
    185 // Traverse a selection node.  Same comments in binary node apply here.
    186 //
    187 void TIntermSelection::traverse(TIntermTraverser *it)
    188 {
    189     bool visit = true;
    190 
    191     if (it->preVisit)
    192         visit = it->visitSelection(EvPreVisit, this);
    193 
    194     if (visit) {
    195         it->incrementDepth(this);
    196         if (it->rightToLeft) {
    197             if (falseBlock)
    198                 falseBlock->traverse(it);
    199             if (trueBlock)
    200                 trueBlock->traverse(it);
    201             condition->traverse(it);
    202         } else {
    203             condition->traverse(it);
    204             if (trueBlock)
    205                 trueBlock->traverse(it);
    206             if (falseBlock)
    207                 falseBlock->traverse(it);
    208         }
    209         it->decrementDepth();
    210     }
    211 
    212     if (visit && it->postVisit)
    213         it->visitSelection(EvPostVisit, this);
    214 }
    215 
    216 //
    217 // Traverse a loop node.  Same comments in binary node apply here.
    218 //
    219 void TIntermLoop::traverse(TIntermTraverser *it)
    220 {
    221     bool visit = true;
    222 
    223     if (it->preVisit)
    224         visit = it->visitLoop(EvPreVisit, this);
    225 
    226     if (visit) {
    227         it->incrementDepth(this);
    228 
    229         if (it->rightToLeft) {
    230             if (terminal)
    231                 terminal->traverse(it);
    232 
    233             if (body)
    234                 body->traverse(it);
    235 
    236             if (test)
    237                 test->traverse(it);
    238         } else {
    239             if (test)
    240                 test->traverse(it);
    241 
    242             if (body)
    243                 body->traverse(it);
    244 
    245             if (terminal)
    246                 terminal->traverse(it);
    247         }
    248 
    249         it->decrementDepth();
    250     }
    251 
    252     if (visit && it->postVisit)
    253         it->visitLoop(EvPostVisit, this);
    254 }
    255 
    256 //
    257 // Traverse a branch node.  Same comments in binary node apply here.
    258 //
    259 void TIntermBranch::traverse(TIntermTraverser *it)
    260 {
    261     bool visit = true;
    262 
    263     if (it->preVisit)
    264         visit = it->visitBranch(EvPreVisit, this);
    265 
    266     if (visit && expression) {
    267         it->incrementDepth(this);
    268         expression->traverse(it);
    269         it->decrementDepth();
    270     }
    271 
    272     if (visit && it->postVisit)
    273         it->visitBranch(EvPostVisit, this);
    274 }
    275 
    276 //
    277 // Traverse a switch node.
    278 //
    279 void TIntermSwitch::traverse(TIntermTraverser* it)
    280 {
    281     bool visit = true;
    282 
    283     if (it->preVisit)
    284         visit = it->visitSwitch(EvPreVisit, this);
    285 
    286     if (visit) {
    287         it->incrementDepth(this);
    288         if (it->rightToLeft) {
    289             body->traverse(it);
    290             condition->traverse(it);
    291         } else {
    292             condition->traverse(it);
    293             body->traverse(it);
    294         }
    295         it->decrementDepth();
    296     }
    297 
    298     if (visit && it->postVisit)
    299         it->visitSwitch(EvPostVisit, this);
    300 }
    301 
    302 } // end namespace glslang
    303