gfx/angle/src/compiler/DetectCallDepth.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 //
     2 // Copyright (c) 2002-2011 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 //
     7 #include "compiler/DetectCallDepth.h"
     8 #include "compiler/InfoSink.h"
    10 DetectCallDepth::FunctionNode::FunctionNode(const TString& fname)
    11     : name(fname),
    12       visit(PreVisit)
    13 {
    14 }
    16 const TString& DetectCallDepth::FunctionNode::getName() const
    17 {
    18     return name;
    19 }
    21 void DetectCallDepth::FunctionNode::addCallee(
    22     DetectCallDepth::FunctionNode* callee)
    23 {
    24     for (size_t i = 0; i < callees.size(); ++i) {
    25         if (callees[i] == callee)
    26             return;
    27     }
    28     callees.push_back(callee);
    29 }
    31 int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth)
    32 {
    33     ASSERT(visit == PreVisit);
    34     ASSERT(detectCallDepth);
    36     int maxDepth = depth;
    37     visit = InVisit;
    38     for (size_t i = 0; i < callees.size(); ++i) {
    39         switch (callees[i]->visit) {
    40             case InVisit:
    41                 // cycle detected, i.e., recursion detected.
    42                 return kInfiniteCallDepth;
    43             case PostVisit:
    44                 break;
    45             case PreVisit: {
    46                 // Check before we recurse so we don't go too depth
    47                 if (detectCallDepth->checkExceedsMaxDepth(depth))
    48                     return depth;
    49                 int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1);
    50                 // Check after we recurse so we can exit immediately and provide info.
    51                 if (detectCallDepth->checkExceedsMaxDepth(callDepth)) {
    52                     detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName();
    53                     return callDepth;
    54                 }
    55                 maxDepth = std::max(callDepth, maxDepth);
    56                 break;
    57             }
    58             default:
    59                 UNREACHABLE();
    60                 break;
    61         }
    62     }
    63     visit = PostVisit;
    64     return maxDepth;
    65 }
    67 void DetectCallDepth::FunctionNode::reset()
    68 {
    69     visit = PreVisit;
    70 }
    72 DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth)
    73     : TIntermTraverser(true, false, true, false),
    74       currentFunction(NULL),
    75       infoSink(infoSink),
    76       maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth)
    77 {
    78 }
    80 DetectCallDepth::~DetectCallDepth()
    81 {
    82     for (size_t i = 0; i < functions.size(); ++i)
    83         delete functions[i];
    84 }
    86 bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node)
    87 {
    88     switch (node->getOp())
    89     {
    90         case EOpPrototype:
    91             // Function declaration.
    92             // Don't add FunctionNode here because node->getName() is the
    93             // unmangled function name.
    94             break;
    95         case EOpFunction: {
    96             // Function definition.
    97             if (visit == PreVisit) {
    98                 currentFunction = findFunctionByName(node->getName());
    99                 if (currentFunction == NULL) {
   100                     currentFunction = new FunctionNode(node->getName());
   101                     functions.push_back(currentFunction);
   102                 }
   103             } else if (visit == PostVisit) {
   104                 currentFunction = NULL;
   105             }
   106             break;
   107         }
   108         case EOpFunctionCall: {
   109             // Function call.
   110             if (visit == PreVisit) {
   111                 FunctionNode* func = findFunctionByName(node->getName());
   112                 if (func == NULL) {
   113                     func = new FunctionNode(node->getName());
   114                     functions.push_back(func);
   115                 }
   116                 if (currentFunction)
   117                     currentFunction->addCallee(func);
   118             }
   119             break;
   120         }
   121         default:
   122             break;
   123     }
   124     return true;
   125 }
   127 bool DetectCallDepth::checkExceedsMaxDepth(int depth)
   128 {
   129     return depth >= maxDepth;
   130 }
   132 void DetectCallDepth::resetFunctionNodes()
   133 {
   134     for (size_t i = 0; i < functions.size(); ++i) {
   135         functions[i]->reset();
   136     }
   137 }
   139 DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func)
   140 {
   141     currentFunction = NULL;
   142     resetFunctionNodes();
   144     int maxCallDepth = func->detectCallDepth(this, 1);
   146     if (maxCallDepth == FunctionNode::kInfiniteCallDepth)
   147         return kErrorRecursion;
   149     if (maxCallDepth >= maxDepth)
   150         return kErrorMaxDepthExceeded;
   152     return kErrorNone;
   153 }
   155 DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth()
   156 {
   157     if (maxDepth != FunctionNode::kInfiniteCallDepth) {
   158         // Check all functions because the driver may fail on them
   159         // TODO: Before detectingRecursion, strip unused functions.
   160         for (size_t i = 0; i < functions.size(); ++i) {
   161             ErrorCode error = detectCallDepthForFunction(functions[i]);
   162             if (error != kErrorNone)
   163                 return error;
   164         }
   165     } else {
   166         FunctionNode* main = findFunctionByName("main(");
   167         if (main == NULL)
   168             return kErrorMissingMain;
   170         return detectCallDepthForFunction(main);
   171     }
   173     return kErrorNone;
   174 }
   176 DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName(
   177     const TString& name)
   178 {
   179     for (size_t i = 0; i < functions.size(); ++i) {
   180         if (functions[i]->getName() == name)
   181             return functions[i];
   182     }
   183     return NULL;
   184 }

mercurial