File: | root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp |
Warning: | line 447, column 17 Value stored to 'visit' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | // |
2 | // Copyright 2002 The ANGLE Project Authors. All rights reserved. |
3 | // Use of this source code is governed by a BSD-style license that can be |
4 | // found in the LICENSE file. |
5 | // |
6 | |
7 | #include "compiler/translator/tree_util/IntermTraverse.h" |
8 | |
9 | #include "compiler/translator/Compiler.h" |
10 | #include "compiler/translator/InfoSink.h" |
11 | #include "compiler/translator/SymbolTable.h" |
12 | #include "compiler/translator/tree_util/IntermNode_util.h" |
13 | #include "compiler/translator/util.h" |
14 | |
15 | namespace sh |
16 | { |
17 | |
18 | // Traverse the intermediate representation tree, and call a node type specific visit function for |
19 | // each node. Traversal is done recursively through the node member function traverse(). Nodes with |
20 | // children can have their whole subtree skipped if preVisit is turned on and the type specific |
21 | // function returns false. |
22 | template <typename T> |
23 | void TIntermTraverser::traverse(T *node) |
24 | { |
25 | ScopedNodeInTraversalPath addToPath(this, node); |
26 | if (!addToPath.isWithinDepthLimit()) |
27 | return; |
28 | |
29 | bool visit = true; |
30 | |
31 | // Visit the node before children if pre-visiting. |
32 | if (preVisit) |
33 | visit = node->visit(PreVisit, this); |
34 | |
35 | if (visit) |
36 | { |
37 | size_t childIndex = 0; |
38 | size_t childCount = node->getChildCount(); |
39 | |
40 | while (childIndex < childCount && visit) |
41 | { |
42 | mCurrentChildIndex = childIndex; |
43 | node->getChildNode(childIndex)->traverse(this); |
44 | mCurrentChildIndex = childIndex; |
45 | |
46 | if (inVisit && childIndex != childCount - 1) |
47 | { |
48 | visit = node->visit(InVisit, this); |
49 | } |
50 | ++childIndex; |
51 | } |
52 | |
53 | if (visit && postVisit) |
54 | node->visit(PostVisit, this); |
55 | } |
56 | } |
57 | |
58 | // Instantiate template for RewriteAtomicFunctionExpressions, in case this gets inlined thus not |
59 | // exported from the TU. |
60 | template void TIntermTraverser::traverse(TIntermNode *); |
61 | |
62 | void TIntermNode::traverse(TIntermTraverser *it) |
63 | { |
64 | it->traverse(this); |
65 | } |
66 | |
67 | void TIntermSymbol::traverse(TIntermTraverser *it) |
68 | { |
69 | TIntermTraverser::ScopedNodeInTraversalPath addToPath(it, this); |
70 | it->visitSymbol(this); |
71 | } |
72 | |
73 | void TIntermConstantUnion::traverse(TIntermTraverser *it) |
74 | { |
75 | TIntermTraverser::ScopedNodeInTraversalPath addToPath(it, this); |
76 | it->visitConstantUnion(this); |
77 | } |
78 | |
79 | void TIntermFunctionPrototype::traverse(TIntermTraverser *it) |
80 | { |
81 | TIntermTraverser::ScopedNodeInTraversalPath addToPath(it, this); |
82 | it->visitFunctionPrototype(this); |
83 | } |
84 | |
85 | void TIntermBinary::traverse(TIntermTraverser *it) |
86 | { |
87 | it->traverseBinary(this); |
88 | } |
89 | |
90 | void TIntermUnary::traverse(TIntermTraverser *it) |
91 | { |
92 | it->traverseUnary(this); |
93 | } |
94 | |
95 | void TIntermFunctionDefinition::traverse(TIntermTraverser *it) |
96 | { |
97 | it->traverseFunctionDefinition(this); |
98 | } |
99 | |
100 | void TIntermBlock::traverse(TIntermTraverser *it) |
101 | { |
102 | it->traverseBlock(this); |
103 | } |
104 | |
105 | void TIntermAggregate::traverse(TIntermTraverser *it) |
106 | { |
107 | it->traverseAggregate(this); |
108 | } |
109 | |
110 | void TIntermLoop::traverse(TIntermTraverser *it) |
111 | { |
112 | it->traverseLoop(this); |
113 | } |
114 | |
115 | void TIntermPreprocessorDirective::traverse(TIntermTraverser *it) |
116 | { |
117 | it->visitPreprocessorDirective(this); |
118 | } |
119 | |
120 | bool TIntermSymbol::visit(Visit visit, TIntermTraverser *it) |
121 | { |
122 | it->visitSymbol(this); |
123 | return false; |
124 | } |
125 | |
126 | bool TIntermConstantUnion::visit(Visit visit, TIntermTraverser *it) |
127 | { |
128 | it->visitConstantUnion(this); |
129 | return false; |
130 | } |
131 | |
132 | bool TIntermFunctionPrototype::visit(Visit visit, TIntermTraverser *it) |
133 | { |
134 | it->visitFunctionPrototype(this); |
135 | return false; |
136 | } |
137 | |
138 | bool TIntermFunctionDefinition::visit(Visit visit, TIntermTraverser *it) |
139 | { |
140 | return it->visitFunctionDefinition(visit, this); |
141 | } |
142 | |
143 | bool TIntermUnary::visit(Visit visit, TIntermTraverser *it) |
144 | { |
145 | return it->visitUnary(visit, this); |
146 | } |
147 | |
148 | bool TIntermSwizzle::visit(Visit visit, TIntermTraverser *it) |
149 | { |
150 | return it->visitSwizzle(visit, this); |
151 | } |
152 | |
153 | bool TIntermBinary::visit(Visit visit, TIntermTraverser *it) |
154 | { |
155 | return it->visitBinary(visit, this); |
156 | } |
157 | |
158 | bool TIntermTernary::visit(Visit visit, TIntermTraverser *it) |
159 | { |
160 | return it->visitTernary(visit, this); |
161 | } |
162 | |
163 | bool TIntermAggregate::visit(Visit visit, TIntermTraverser *it) |
164 | { |
165 | return it->visitAggregate(visit, this); |
166 | } |
167 | |
168 | bool TIntermDeclaration::visit(Visit visit, TIntermTraverser *it) |
169 | { |
170 | return it->visitDeclaration(visit, this); |
171 | } |
172 | |
173 | bool TIntermGlobalQualifierDeclaration::visit(Visit visit, TIntermTraverser *it) |
174 | { |
175 | return it->visitGlobalQualifierDeclaration(visit, this); |
176 | } |
177 | |
178 | bool TIntermBlock::visit(Visit visit, TIntermTraverser *it) |
179 | { |
180 | return it->visitBlock(visit, this); |
181 | } |
182 | |
183 | bool TIntermIfElse::visit(Visit visit, TIntermTraverser *it) |
184 | { |
185 | return it->visitIfElse(visit, this); |
186 | } |
187 | |
188 | bool TIntermLoop::visit(Visit visit, TIntermTraverser *it) |
189 | { |
190 | return it->visitLoop(visit, this); |
191 | } |
192 | |
193 | bool TIntermBranch::visit(Visit visit, TIntermTraverser *it) |
194 | { |
195 | return it->visitBranch(visit, this); |
196 | } |
197 | |
198 | bool TIntermSwitch::visit(Visit visit, TIntermTraverser *it) |
199 | { |
200 | return it->visitSwitch(visit, this); |
201 | } |
202 | |
203 | bool TIntermCase::visit(Visit visit, TIntermTraverser *it) |
204 | { |
205 | return it->visitCase(visit, this); |
206 | } |
207 | |
208 | bool TIntermPreprocessorDirective::visit(Visit visit, TIntermTraverser *it) |
209 | { |
210 | it->visitPreprocessorDirective(this); |
211 | return false; |
212 | } |
213 | |
214 | TIntermTraverser::TIntermTraverser(bool preVisit, |
215 | bool inVisit, |
216 | bool postVisit, |
217 | TSymbolTable *symbolTable) |
218 | : preVisit(preVisit), |
219 | inVisit(inVisit), |
220 | postVisit(postVisit), |
221 | mMaxDepth(0), |
222 | mMaxAllowedDepth(std::numeric_limits<int>::max()), |
223 | mInGlobalScope(true), |
224 | mSymbolTable(symbolTable), |
225 | mCurrentChildIndex(0) |
226 | { |
227 | // Only enabling inVisit is not supported. |
228 | ASSERT(!(inVisit && !preVisit && !postVisit))(!(inVisit && !preVisit && !postVisit) ? static_cast <void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage (::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv ::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 228, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 228 << "): " << "!(inVisit && !preVisit && !postVisit)" )); |
229 | } |
230 | |
231 | TIntermTraverser::~TIntermTraverser() {} |
232 | |
233 | void TIntermTraverser::setMaxAllowedDepth(int depth) |
234 | { |
235 | mMaxAllowedDepth = depth; |
236 | } |
237 | |
238 | const TIntermBlock *TIntermTraverser::getParentBlock() const |
239 | { |
240 | if (!mParentBlockStack.empty()) |
241 | { |
242 | return mParentBlockStack.back().node; |
243 | } |
244 | return nullptr; |
245 | } |
246 | |
247 | void TIntermTraverser::pushParentBlock(TIntermBlock *node) |
248 | { |
249 | mParentBlockStack.push_back(ParentBlock(node, 0)); |
250 | } |
251 | |
252 | void TIntermTraverser::incrementParentBlockPos() |
253 | { |
254 | ++mParentBlockStack.back().pos; |
255 | } |
256 | |
257 | void TIntermTraverser::popParentBlock() |
258 | { |
259 | ASSERT(!mParentBlockStack.empty())(!mParentBlockStack.empty() ? static_cast<void>(0) : (! ((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL) )) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify () & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 259, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 259 << "): " << "!mParentBlockStack.empty()" )); |
260 | mParentBlockStack.pop_back(); |
261 | } |
262 | |
263 | void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions) |
264 | { |
265 | TIntermSequence emptyInsertionsAfter; |
266 | insertStatementsInParentBlock(insertions, emptyInsertionsAfter); |
267 | } |
268 | |
269 | void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore, |
270 | const TIntermSequence &insertionsAfter) |
271 | { |
272 | ASSERT(!mParentBlockStack.empty())(!mParentBlockStack.empty() ? static_cast<void>(0) : (! ((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL) )) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify () & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 272, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 272 << "): " << "!mParentBlockStack.empty()" )); |
273 | ParentBlock &parentBlock = mParentBlockStack.back(); |
274 | if (mPath.back() == parentBlock.node) |
275 | { |
276 | ASSERT(mParentBlockStack.size() >= 2u)(mParentBlockStack.size() >= 2u ? static_cast<void>( 0) : (!((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL ))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify () & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 276, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 276 << "): " << "mParentBlockStack.size() >= 2u" )); |
277 | // The current node is a block node, so the parent block is not the topmost one in the block |
278 | // stack, but the one below that. |
279 | parentBlock = mParentBlockStack.at(mParentBlockStack.size() - 2u); |
280 | } |
281 | NodeInsertMultipleEntry insert(parentBlock.node, parentBlock.pos, insertionsBefore, |
282 | insertionsAfter); |
283 | mInsertions.push_back(insert); |
284 | } |
285 | |
286 | void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement) |
287 | { |
288 | TIntermSequence insertions; |
289 | insertions.push_back(statement); |
290 | insertStatementsInParentBlock(insertions); |
291 | } |
292 | |
293 | void TIntermTraverser::insertStatementsInBlockAtPosition(TIntermBlock *parent, |
294 | size_t position, |
295 | const TIntermSequence &insertionsBefore, |
296 | const TIntermSequence &insertionsAfter) |
297 | { |
298 | ASSERT(parent)(parent ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage (::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv ::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 298, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 298 << "): " << "parent")); |
299 | ASSERT(position >= 0)(position >= 0 ? static_cast<void>(0) : (!((::gl::priv ::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast <void>(0) : ::gl::priv::LogMessageVoidify() & (::gl ::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 299, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 299 << "): " << "position >= 0" )); |
300 | ASSERT(position < parent->getChildCount())(position < parent->getChildCount() ? static_cast<void >(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage(::gl ::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify () & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 300, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 300 << "): " << "position < parent->getChildCount()" )); |
301 | |
302 | mInsertions.emplace_back(parent, position, insertionsBefore, insertionsAfter); |
303 | } |
304 | |
305 | void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter) |
306 | { |
307 | mInFunctionCallOutParameter = inOutParameter; |
308 | } |
309 | |
310 | bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const |
311 | { |
312 | return mInFunctionCallOutParameter; |
313 | } |
314 | |
315 | void TIntermTraverser::traverseBinary(TIntermBinary *node) |
316 | { |
317 | traverse(node); |
318 | } |
319 | |
320 | void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node) |
321 | { |
322 | ScopedNodeInTraversalPath addToPath(this, node); |
323 | if (!addToPath.isWithinDepthLimit()) |
324 | return; |
325 | |
326 | bool visit = true; |
327 | |
328 | // visit the node before children if pre-visiting. |
329 | if (preVisit) |
330 | visit = node->visit(PreVisit, this); |
331 | |
332 | // Visit the children, in the right order. |
333 | if (visit) |
334 | { |
335 | if (node->isAssignment()) |
336 | { |
337 | ASSERT(!isLValueRequiredHere())(!isLValueRequiredHere() ? static_cast<void>(0) : (!((:: gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 337, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 337 << "): " << "!isLValueRequiredHere()" )); |
338 | setOperatorRequiresLValue(true); |
339 | } |
340 | |
341 | node->getLeft()->traverse(this); |
342 | |
343 | if (node->isAssignment()) |
344 | setOperatorRequiresLValue(false); |
345 | |
346 | if (inVisit) |
347 | visit = node->visit(InVisit, this); |
348 | |
349 | if (visit) |
350 | { |
351 | // Some binary operations like indexing can be inside an expression which must be an |
352 | // l-value. |
353 | bool parentOperatorRequiresLValue = operatorRequiresLValue(); |
354 | bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter(); |
355 | |
356 | // Index is not required to be an l-value even when the surrounding expression is |
357 | // required to be an l-value. |
358 | TOperator op = node->getOp(); |
359 | if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock || |
360 | op == EOpIndexDirectStruct || op == EOpIndexIndirect) |
361 | { |
362 | setOperatorRequiresLValue(false); |
363 | setInFunctionCallOutParameter(false); |
364 | } |
365 | |
366 | node->getRight()->traverse(this); |
367 | |
368 | setOperatorRequiresLValue(parentOperatorRequiresLValue); |
369 | setInFunctionCallOutParameter(parentInFunctionCallOutParameter); |
370 | |
371 | // Visit the node after the children, if requested and the traversal |
372 | // hasn't been cancelled yet. |
373 | if (postVisit) |
374 | visit = node->visit(PostVisit, this); |
375 | } |
376 | } |
377 | } |
378 | |
379 | void TIntermTraverser::traverseUnary(TIntermUnary *node) |
380 | { |
381 | traverse(node); |
382 | } |
383 | |
384 | void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node) |
385 | { |
386 | ScopedNodeInTraversalPath addToPath(this, node); |
387 | if (!addToPath.isWithinDepthLimit()) |
388 | return; |
389 | |
390 | bool visit = true; |
391 | |
392 | if (preVisit) |
393 | visit = node->visit(PreVisit, this); |
394 | |
395 | if (visit) |
396 | { |
397 | ASSERT(!operatorRequiresLValue())(!operatorRequiresLValue() ? static_cast<void>(0) : (!( (::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL)) ) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify () & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 397, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 397 << "): " << "!operatorRequiresLValue()" )); |
398 | switch (node->getOp()) |
399 | { |
400 | case EOpPostIncrement: |
401 | case EOpPostDecrement: |
402 | case EOpPreIncrement: |
403 | case EOpPreDecrement: |
404 | setOperatorRequiresLValue(true); |
405 | break; |
406 | default: |
407 | break; |
408 | } |
409 | |
410 | node->getOperand()->traverse(this); |
411 | |
412 | setOperatorRequiresLValue(false); |
413 | |
414 | if (postVisit) |
415 | visit = node->visit(PostVisit, this); |
416 | } |
417 | } |
418 | |
419 | // Traverse a function definition node. This keeps track of global scope. |
420 | void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node) |
421 | { |
422 | ScopedNodeInTraversalPath addToPath(this, node); |
423 | if (!addToPath.isWithinDepthLimit()) |
424 | return; |
425 | |
426 | bool visit = true; |
427 | |
428 | if (preVisit) |
429 | visit = node->visit(PreVisit, this); |
430 | |
431 | if (visit) |
432 | { |
433 | mCurrentChildIndex = 0; |
434 | node->getFunctionPrototype()->traverse(this); |
435 | mCurrentChildIndex = 0; |
436 | |
437 | if (inVisit) |
438 | visit = node->visit(InVisit, this); |
439 | if (visit) |
440 | { |
441 | mInGlobalScope = false; |
442 | mCurrentChildIndex = 1; |
443 | node->getBody()->traverse(this); |
444 | mCurrentChildIndex = 1; |
445 | mInGlobalScope = true; |
446 | if (postVisit) |
447 | visit = node->visit(PostVisit, this); |
Value stored to 'visit' is never read | |
448 | } |
449 | } |
450 | } |
451 | |
452 | // Traverse a block node. This keeps track of the position of traversed child nodes within the block |
453 | // so that nodes may be inserted before or after them. |
454 | void TIntermTraverser::traverseBlock(TIntermBlock *node) |
455 | { |
456 | ScopedNodeInTraversalPath addToPath(this, node); |
457 | if (!addToPath.isWithinDepthLimit()) |
458 | return; |
459 | |
460 | pushParentBlock(node); |
461 | |
462 | bool visit = true; |
463 | |
464 | TIntermSequence *sequence = node->getSequence(); |
465 | |
466 | if (preVisit) |
467 | visit = node->visit(PreVisit, this); |
468 | |
469 | if (visit) |
470 | { |
471 | for (size_t childIndex = 0; childIndex < sequence->size(); ++childIndex) |
472 | { |
473 | TIntermNode *child = (*sequence)[childIndex]; |
474 | if (visit) |
475 | { |
476 | mCurrentChildIndex = childIndex; |
477 | child->traverse(this); |
478 | mCurrentChildIndex = childIndex; |
479 | |
480 | if (inVisit) |
481 | { |
482 | if (child != sequence->back()) |
483 | visit = node->visit(InVisit, this); |
484 | } |
485 | |
486 | incrementParentBlockPos(); |
487 | } |
488 | } |
489 | |
490 | if (visit && postVisit) |
491 | visit = node->visit(PostVisit, this); |
492 | } |
493 | |
494 | popParentBlock(); |
495 | } |
496 | |
497 | void TIntermTraverser::traverseAggregate(TIntermAggregate *node) |
498 | { |
499 | traverse(node); |
500 | } |
501 | |
502 | bool TIntermTraverser::CompareInsertion(const NodeInsertMultipleEntry &a, |
503 | const NodeInsertMultipleEntry &b) |
504 | { |
505 | if (a.parent != b.parent) |
506 | { |
507 | return a.parent < b.parent; |
508 | } |
509 | return a.position < b.position; |
510 | } |
511 | |
512 | bool TIntermTraverser::updateTree(TCompiler *compiler, TIntermNode *node) |
513 | { |
514 | // Sort the insertions so that insertion position is increasing and same position insertions are |
515 | // not reordered. The insertions are processed in reverse order so that multiple insertions to |
516 | // the same parent node are handled correctly. |
517 | std::stable_sort(mInsertions.begin(), mInsertions.end(), CompareInsertion); |
518 | for (size_t ii = 0; ii < mInsertions.size(); ++ii) |
519 | { |
520 | // If two insertions are to the same position, insert them in the order they were specified. |
521 | // The std::stable_sort call above will automatically guarantee this. |
522 | const NodeInsertMultipleEntry &insertion = mInsertions[mInsertions.size() - ii - 1]; |
523 | ASSERT(insertion.parent)(insertion.parent ? static_cast<void>(0) : (!((::gl::priv ::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast <void>(0) : ::gl::priv::LogMessageVoidify() & (::gl ::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 523, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 523 << "): " << "insertion.parent" )); |
524 | if (!insertion.insertionsAfter.empty()) |
525 | { |
526 | bool inserted = insertion.parent->insertChildNodes(insertion.position + 1, |
527 | insertion.insertionsAfter); |
528 | ASSERT(inserted)(inserted ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage (::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv ::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 528, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 528 << "): " << "inserted" )); |
529 | } |
530 | if (!insertion.insertionsBefore.empty()) |
531 | { |
532 | bool inserted = |
533 | insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore); |
534 | ASSERT(inserted)(inserted ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage (::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv ::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 534, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 534 << "): " << "inserted" )); |
535 | } |
536 | } |
537 | for (size_t ii = 0; ii < mReplacements.size(); ++ii) |
538 | { |
539 | const NodeUpdateEntry &replacement = mReplacements[ii]; |
540 | ASSERT(replacement.parent)(replacement.parent ? static_cast<void>(0) : (!((::gl:: priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast <void>(0) : ::gl::priv::LogMessageVoidify() & (::gl ::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 540, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 540 << "): " << "replacement.parent" )); |
541 | bool replaced = |
542 | replacement.parent->replaceChildNode(replacement.original, replacement.replacement); |
543 | ASSERT(replaced)(replaced ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage (::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv ::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 543, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 543 << "): " << "replaced" )); |
544 | |
545 | // Make sure the precision is not accidentally dropped. It's ok if the precision is not the |
546 | // same, as the transformations are allowed to replace an expression with one that is |
547 | // temporarily evaluated at a different (likely higher) precision. |
548 | TIntermTyped *originalAsTyped = replacement.original->getAsTyped(); |
549 | TIntermTyped *replacementAsTyped = |
550 | replacement.replacement ? replacement.replacement->getAsTyped() : nullptr; |
551 | if (originalAsTyped != nullptr && replacementAsTyped != nullptr) |
552 | { |
553 | const TType &originalType = originalAsTyped->getType(); |
554 | const TType &replacementType = replacementAsTyped->getType(); |
555 | ASSERT(!IsPrecisionApplicableToType(originalType.getBasicType()) ||(!IsPrecisionApplicableToType(originalType.getBasicType()) || !IsPrecisionApplicableToType(replacementType.getBasicType()) || originalType.getPrecision() == EbpUndefined || replacementType .getPrecision() != EbpUndefined ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL ))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify () & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 558, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 558 << "): " << "!IsPrecisionApplicableToType(originalType.getBasicType()) || !IsPrecisionApplicableToType(replacementType.getBasicType()) || originalType.getPrecision() == EbpUndefined || replacementType.getPrecision() != EbpUndefined" )) |
556 | !IsPrecisionApplicableToType(replacementType.getBasicType()) ||(!IsPrecisionApplicableToType(originalType.getBasicType()) || !IsPrecisionApplicableToType(replacementType.getBasicType()) || originalType.getPrecision() == EbpUndefined || replacementType .getPrecision() != EbpUndefined ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL ))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify () & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 558, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 558 << "): " << "!IsPrecisionApplicableToType(originalType.getBasicType()) || !IsPrecisionApplicableToType(replacementType.getBasicType()) || originalType.getPrecision() == EbpUndefined || replacementType.getPrecision() != EbpUndefined" )) |
557 | originalType.getPrecision() == EbpUndefined ||(!IsPrecisionApplicableToType(originalType.getBasicType()) || !IsPrecisionApplicableToType(replacementType.getBasicType()) || originalType.getPrecision() == EbpUndefined || replacementType .getPrecision() != EbpUndefined ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL ))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify () & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 558, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 558 << "): " << "!IsPrecisionApplicableToType(originalType.getBasicType()) || !IsPrecisionApplicableToType(replacementType.getBasicType()) || originalType.getPrecision() == EbpUndefined || replacementType.getPrecision() != EbpUndefined" )) |
558 | replacementType.getPrecision() != EbpUndefined)(!IsPrecisionApplicableToType(originalType.getBasicType()) || !IsPrecisionApplicableToType(replacementType.getBasicType()) || originalType.getPrecision() == EbpUndefined || replacementType .getPrecision() != EbpUndefined ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL ))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify () & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 558, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 558 << "): " << "!IsPrecisionApplicableToType(originalType.getBasicType()) || !IsPrecisionApplicableToType(replacementType.getBasicType()) || originalType.getPrecision() == EbpUndefined || replacementType.getPrecision() != EbpUndefined" )); |
559 | } |
560 | |
561 | if (!replacement.originalBecomesChildOfReplacement) |
562 | { |
563 | // In AST traversing, a parent is visited before its children. |
564 | // After we replace a node, if its immediate child is to |
565 | // be replaced, we need to make sure we don't update the replaced |
566 | // node; instead, we update the replacement node. |
567 | for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj) |
568 | { |
569 | NodeUpdateEntry &replacement2 = mReplacements[jj]; |
570 | if (replacement2.parent == replacement.original) |
571 | replacement2.parent = replacement.replacement; |
572 | } |
573 | } |
574 | } |
575 | for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii) |
576 | { |
577 | const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii]; |
578 | ASSERT(replacement.parent)(replacement.parent ? static_cast<void>(0) : (!((::gl:: priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast <void>(0) : ::gl::priv::LogMessageVoidify() & (::gl ::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 578, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 578 << "): " << "replacement.parent" )); |
579 | bool replaced = replacement.parent->replaceChildNodeWithMultiple(replacement.original, |
580 | replacement.replacements); |
581 | ASSERT(replaced)(replaced ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage (::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv ::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 581, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 581 << "): " << "replaced" )); |
582 | } |
583 | |
584 | clearReplacementQueue(); |
585 | |
586 | return compiler->validateAST(node); |
587 | } |
588 | |
589 | void TIntermTraverser::clearReplacementQueue() |
590 | { |
591 | mReplacements.clear(); |
592 | mMultiReplacements.clear(); |
593 | mInsertions.clear(); |
594 | } |
595 | |
596 | void TIntermTraverser::queueReplacement(TIntermNode *replacement, OriginalNode originalStatus) |
597 | { |
598 | queueReplacementWithParent(getParentNode(), mPath.back(), replacement, originalStatus); |
599 | } |
600 | |
601 | void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent, |
602 | TIntermNode *original, |
603 | TIntermNode *replacement, |
604 | OriginalNode originalStatus) |
605 | { |
606 | bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD); |
607 | mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild)); |
608 | } |
609 | |
610 | void TIntermTraverser::queueAccessChainReplacement(TIntermTyped *replacement) |
611 | { |
612 | uint32_t ancestorIndex = 0; |
613 | TIntermTyped *toReplace = nullptr; |
614 | while (true) |
615 | { |
616 | TIntermNode *ancestor = getAncestorNode(ancestorIndex); |
617 | ASSERT(ancestor != nullptr)(ancestor != nullptr ? static_cast<void>(0) : (!((::gl:: priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast <void>(0) : ::gl::priv::LogMessageVoidify() & (::gl ::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 617, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 617 << "): " << "ancestor != nullptr" )); |
618 | |
619 | TIntermBinary *asBinary = ancestor->getAsBinaryNode(); |
620 | if (asBinary == nullptr || |
621 | (asBinary->getOp() != EOpIndexDirect && asBinary->getOp() != EOpIndexIndirect)) |
622 | { |
623 | break; |
624 | } |
625 | |
626 | replacement = new TIntermBinary(asBinary->getOp(), replacement, asBinary->getRight()); |
627 | toReplace = asBinary; |
628 | |
629 | ++ancestorIndex; |
630 | } |
631 | |
632 | if (toReplace == nullptr) |
633 | { |
634 | queueReplacement(replacement, OriginalNode::IS_DROPPED); |
635 | } |
636 | else |
637 | { |
638 | queueReplacementWithParent(getAncestorNode(ancestorIndex), toReplace, replacement, |
639 | OriginalNode::IS_DROPPED); |
640 | } |
641 | } |
642 | |
643 | TLValueTrackingTraverser::TLValueTrackingTraverser(bool preVisitIn, |
644 | bool inVisitIn, |
645 | bool postVisitIn, |
646 | TSymbolTable *symbolTable) |
647 | : TIntermTraverser(preVisitIn, inVisitIn, postVisitIn, symbolTable), |
648 | mOperatorRequiresLValue(false), |
649 | mInFunctionCallOutParameter(false) |
650 | { |
651 | ASSERT(symbolTable)(symbolTable ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage (::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv ::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 651, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 651 << "): " << "symbolTable" )); |
652 | } |
653 | |
654 | void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node) |
655 | { |
656 | ScopedNodeInTraversalPath addToPath(this, node); |
657 | if (!addToPath.isWithinDepthLimit()) |
658 | return; |
659 | |
660 | bool visit = true; |
661 | |
662 | TIntermSequence *sequence = node->getSequence(); |
663 | |
664 | if (preVisit) |
665 | visit = node->visit(PreVisit, this); |
666 | |
667 | if (visit) |
668 | { |
669 | size_t paramIndex = 0u; |
670 | for (auto *child : *sequence) |
671 | { |
672 | if (visit) |
673 | { |
674 | if (node->getFunction()) |
675 | { |
676 | // Both built-ins and user defined functions should have the function symbol |
677 | // set. |
678 | ASSERT(paramIndex < node->getFunction()->getParamCount())(paramIndex < node->getFunction()->getParamCount() ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage (::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv ::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 678, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 678 << "): " << "paramIndex < node->getFunction()->getParamCount()" )); |
679 | TQualifier qualifier = |
680 | node->getFunction()->getParam(paramIndex)->getType().getQualifier(); |
681 | setInFunctionCallOutParameter(qualifier == EvqParamOut || |
682 | qualifier == EvqParamInOut); |
683 | ++paramIndex; |
684 | } |
685 | else |
686 | { |
687 | ASSERT(node->isConstructor())(node->isConstructor() ? static_cast<void>(0) : (!(( ::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify () & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" , __FUNCTION__, 687, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in " << __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp" << ":" << 687 << "): " << "node->isConstructor()" )); |
688 | } |
689 | child->traverse(this); |
690 | if (inVisit) |
691 | { |
692 | if (child != sequence->back()) |
693 | visit = node->visit(InVisit, this); |
694 | } |
695 | } |
696 | } |
697 | setInFunctionCallOutParameter(false); |
698 | |
699 | if (visit && postVisit) |
700 | visit = node->visit(PostVisit, this); |
701 | } |
702 | } |
703 | |
704 | void TIntermTraverser::traverseLoop(TIntermLoop *node) |
705 | { |
706 | traverse(node); |
707 | } |
708 | } // namespace sh |