1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/third_party/compiler/ArrayBoundsClamper.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,109 @@ 1.4 +/* 1.5 + * Copyright (C) 2012 Apple Inc. All rights reserved. 1.6 + * 1.7 + * Redistribution and use in source and binary forms, with or without 1.8 + * modification, are permitted provided that the following conditions 1.9 + * are met: 1.10 + * 1. Redistributions of source code must retain the above copyright 1.11 + * notice, this list of conditions and the following disclaimer. 1.12 + * 2. Redistributions in binary form must reproduce the above copyright 1.13 + * notice, this list of conditions and the following disclaimer in the 1.14 + * documentation and/or other materials provided with the distribution. 1.15 + * 1.16 + * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY 1.17 + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.18 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1.19 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, INC. OR 1.20 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 1.21 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 1.22 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 1.23 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 1.24 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.25 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.26 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.27 + */ 1.28 + 1.29 +#include "third_party/compiler/ArrayBoundsClamper.h" 1.30 + 1.31 +// The built-in 'clamp' instruction only accepts floats and returns a float. I 1.32 +// iterated a few times with our driver team who examined the output from our 1.33 +// compiler - they said the multiple casts generates more code than a single 1.34 +// function call. An inline ternary operator might have been better, but since 1.35 +// the index value might be an expression itself, we'd have to make temporary 1.36 +// variables to avoid evaluating the expression multiple times. And making 1.37 +// temporary variables was difficult because ANGLE would then need to make more 1.38 +// brutal changes to the expression tree. 1.39 + 1.40 +const char* kIntClampBegin = "// BEGIN: Generated code for array bounds clamping\n\n"; 1.41 +const char* kIntClampEnd = "// END: Generated code for array bounds clamping\n\n"; 1.42 +const char* kIntClampDefinition = "int webgl_int_clamp(int value, int minValue, int maxValue) { return ((value < minValue) ? minValue : ((value > maxValue) ? maxValue : value)); }\n\n"; 1.43 + 1.44 +namespace { 1.45 + 1.46 +class ArrayBoundsClamperMarker : public TIntermTraverser { 1.47 +public: 1.48 + ArrayBoundsClamperMarker() 1.49 + : mNeedsClamp(false) 1.50 + { 1.51 + } 1.52 + 1.53 + virtual bool visitBinary(Visit visit, TIntermBinary* node) 1.54 + { 1.55 + if (node->getOp() == EOpIndexIndirect) 1.56 + { 1.57 + TIntermTyped* left = node->getLeft(); 1.58 + if (left->isArray() || left->isVector() || left->isMatrix()) 1.59 + { 1.60 + node->setAddIndexClamp(); 1.61 + mNeedsClamp = true; 1.62 + } 1.63 + } 1.64 + return true; 1.65 + } 1.66 + 1.67 + bool GetNeedsClamp() { return mNeedsClamp; } 1.68 + 1.69 +private: 1.70 + bool mNeedsClamp; 1.71 +}; 1.72 + 1.73 +} // anonymous namespace 1.74 + 1.75 +ArrayBoundsClamper::ArrayBoundsClamper() 1.76 + : mClampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC) 1.77 + , mArrayBoundsClampDefinitionNeeded(false) 1.78 +{ 1.79 +} 1.80 + 1.81 +void ArrayBoundsClamper::SetClampingStrategy(ShArrayIndexClampingStrategy clampingStrategy) 1.82 +{ 1.83 + ASSERT(clampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC || 1.84 + clampingStrategy == SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION); 1.85 + 1.86 + mClampingStrategy = clampingStrategy; 1.87 +} 1.88 + 1.89 +void ArrayBoundsClamper::MarkIndirectArrayBoundsForClamping(TIntermNode* root) 1.90 +{ 1.91 + ASSERT(root); 1.92 + 1.93 + ArrayBoundsClamperMarker clamper; 1.94 + root->traverse(&clamper); 1.95 + if (clamper.GetNeedsClamp()) 1.96 + { 1.97 + SetArrayBoundsClampDefinitionNeeded(); 1.98 + } 1.99 +} 1.100 + 1.101 +void ArrayBoundsClamper::OutputClampingFunctionDefinition(TInfoSinkBase& out) const 1.102 +{ 1.103 + if (!mArrayBoundsClampDefinitionNeeded) 1.104 + { 1.105 + return; 1.106 + } 1.107 + if (mClampingStrategy != SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION) 1.108 + { 1.109 + return; 1.110 + } 1.111 + out << kIntClampBegin << kIntClampDefinition << kIntClampEnd; 1.112 +}