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