Home | History | Annotate | Download | only in MachineIndependent
      1 //
      2 // Copyright (C) 2016 LunarG, Inc.
      3 //
      4 // All rights reserved.
      5 //
      6 // Redistribution and use in source and binary forms, with or without
      7 // modification, are permitted provided that the following conditions
      8 // are met:
      9 //
     10 //    Redistributions of source code must retain the above copyright
     11 //    notice, this list of conditions and the following disclaimer.
     12 //
     13 //    Redistributions in binary form must reproduce the above
     14 //    copyright notice, this list of conditions and the following
     15 //    disclaimer in the documentation and/or other materials provided
     16 //    with the distribution.
     17 //
     18 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
     19 //    contributors may be used to endorse or promote products derived
     20 //    from this software without specific prior written permission.
     21 //
     22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     23 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     24 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     25 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     26 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     27 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     28 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     29 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     30 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     32 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     33 // POSSIBILITY OF SUCH DAMAGE.
     34 //
     35 
     36 #pragma once
     37 
     38 #include "../Include/Common.h"
     39 #include "reflection.h"
     40 #include "localintermediate.h"
     41 
     42 #include "gl_types.h"
     43 
     44 #include <list>
     45 #include <unordered_set>
     46 
     47 namespace glslang {
     48 
     49 //
     50 // The traverser: mostly pass through, except
     51 //  - processing function-call nodes to push live functions onto the stack of functions to process
     52 //  - processing selection nodes to trim semantically dead code
     53 //
     54 // This is in the glslang namespace directly so it can be a friend of TReflection.
     55 // This can be derived from to implement reflection database traversers or
     56 // binding mappers: anything that wants to traverse the live subset of the tree.
     57 //
     58 
     59 class TLiveTraverser : public TIntermTraverser {
     60 public:
     61     TLiveTraverser(const TIntermediate& i, bool traverseAll = false,
     62                    bool preVisit = true, bool inVisit = false, bool postVisit = false) :
     63         TIntermTraverser(preVisit, inVisit, postVisit),
     64         intermediate(i), traverseAll(traverseAll)
     65     { }
     66 
     67     //
     68     // Given a function name, find its subroot in the tree, and push it onto the stack of
     69     // functions left to process.
     70     //
     71     void pushFunction(const TString& name)
     72     {
     73         TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence();
     74         for (unsigned int f = 0; f < globals.size(); ++f) {
     75             TIntermAggregate* candidate = globals[f]->getAsAggregate();
     76             if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) {
     77                 functions.push_back(candidate);
     78                 break;
     79             }
     80         }
     81     }
     82 
     83     typedef std::list<TIntermAggregate*> TFunctionStack;
     84     TFunctionStack functions;
     85 
     86 protected:
     87     // To catch which function calls are not dead, and hence which functions must be visited.
     88     virtual bool visitAggregate(TVisit, TIntermAggregate* node)
     89     {
     90         if (!traverseAll)
     91             if (node->getOp() == EOpFunctionCall)
     92                 addFunctionCall(node);
     93 
     94         return true; // traverse this subtree
     95     }
     96 
     97     // To prune semantically dead paths.
     98     virtual bool visitSelection(TVisit /* visit */,  TIntermSelection* node)
     99     {
    100         if (traverseAll)
    101             return true; // traverse all code
    102 
    103         TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion();
    104         if (constant) {
    105             // cull the path that is dead
    106             if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock())
    107                 node->getTrueBlock()->traverse(this);
    108             if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock())
    109                 node->getFalseBlock()->traverse(this);
    110 
    111             return false; // don't traverse any more, we did it all above
    112         } else
    113             return true; // traverse the whole subtree
    114     }
    115 
    116     // Track live functions as well as uniforms, so that we don't visit dead functions
    117     // and only visit each function once.
    118     void addFunctionCall(TIntermAggregate* call)
    119     {
    120         // // just use the map to ensure we process each function at most once
    121         if (liveFunctions.find(call->getName()) == liveFunctions.end()) {
    122             liveFunctions.insert(call->getName());
    123             pushFunction(call->getName());
    124         }
    125     }
    126 
    127     const TIntermediate& intermediate;
    128     typedef std::unordered_set<TString> TLiveFunctions;
    129     TLiveFunctions liveFunctions;
    130     bool traverseAll;
    131 
    132 private:
    133     // prevent copy & copy construct
    134     TLiveTraverser(TLiveTraverser&);
    135     TLiveTraverser& operator=(TLiveTraverser&);
    136 };
    137 
    138 } // namespace glslang
    139