LCOV - code coverage report
Current view: top level - gfx/angle/src/compiler/translator - Compiler.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 470 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 51 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2002-2014 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/Compiler.h"
       8             : 
       9             : #include <sstream>
      10             : 
      11             : #include "angle_gl.h"
      12             : #include "common/utilities.h"
      13             : #include "compiler/translator/AddAndTrueToLoopCondition.h"
      14             : #include "compiler/translator/Cache.h"
      15             : #include "compiler/translator/CallDAG.h"
      16             : #include "compiler/translator/DeferGlobalInitializers.h"
      17             : #include "compiler/translator/EmulateGLFragColorBroadcast.h"
      18             : #include "compiler/translator/EmulatePrecision.h"
      19             : #include "compiler/translator/Initialize.h"
      20             : #include "compiler/translator/InitializeParseContext.h"
      21             : #include "compiler/translator/InitializeVariables.h"
      22             : #include "compiler/translator/ParseContext.h"
      23             : #include "compiler/translator/PruneEmptyDeclarations.h"
      24             : #include "compiler/translator/RegenerateStructNames.h"
      25             : #include "compiler/translator/RemoveInvariantDeclaration.h"
      26             : #include "compiler/translator/RemovePow.h"
      27             : #include "compiler/translator/RewriteDoWhile.h"
      28             : #include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
      29             : #include "compiler/translator/UnfoldShortCircuitAST.h"
      30             : #include "compiler/translator/UseInterfaceBlockFields.h"
      31             : #include "compiler/translator/ValidateLimitations.h"
      32             : #include "compiler/translator/ValidateMaxParameters.h"
      33             : #include "compiler/translator/ValidateOutputs.h"
      34             : #include "compiler/translator/VariablePacker.h"
      35             : #include "third_party/compiler/ArrayBoundsClamper.h"
      36             : 
      37             : namespace sh
      38             : {
      39             : 
      40             : namespace
      41             : {
      42             : 
      43             : #if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
      44             : void DumpFuzzerCase(char const *const *shaderStrings,
      45             :                     size_t numStrings,
      46             :                     uint32_t type,
      47             :                     uint32_t spec,
      48             :                     uint32_t output,
      49             :                     uint64_t options)
      50             : {
      51             :     static int fileIndex = 0;
      52             : 
      53             :     std::ostringstream o;
      54             :     o << "corpus/" << fileIndex++ << ".sample";
      55             :     std::string s = o.str();
      56             : 
      57             :     // Must match the input format of the fuzzer
      58             :     FILE *f = fopen(s.c_str(), "w");
      59             :     fwrite(&type, sizeof(type), 1, f);
      60             :     fwrite(&spec, sizeof(spec), 1, f);
      61             :     fwrite(&output, sizeof(output), 1, f);
      62             :     fwrite(&options, sizeof(options), 1, f);
      63             : 
      64             :     char zero[128 - 20] = {0};
      65             :     fwrite(&zero, 128 - 20, 1, f);
      66             : 
      67             :     for (size_t i = 0; i < numStrings; i++)
      68             :     {
      69             :         fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);
      70             :     }
      71             :     fwrite(&zero, 1, 1, f);
      72             : 
      73             :     fclose(f);
      74             : }
      75             : #endif  // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
      76             : }  // anonymous namespace
      77             : 
      78           0 : bool IsWebGLBasedSpec(ShShaderSpec spec)
      79             : {
      80           0 :     return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC);
      81             : }
      82             : 
      83           0 : bool IsGLSL130OrNewer(ShShaderOutput output)
      84             : {
      85           0 :     return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
      86           0 :             output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
      87           0 :             output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
      88           0 :             output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
      89           0 :             output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
      90             : }
      91             : 
      92           0 : bool IsGLSL420OrNewer(ShShaderOutput output)
      93             : {
      94           0 :     return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
      95           0 :             output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
      96             : }
      97             : 
      98           0 : bool IsGLSL410OrOlder(ShShaderOutput output)
      99             : {
     100           0 :     return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
     101           0 :             output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
     102           0 :             output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
     103             : }
     104             : 
     105           0 : bool RemoveInvariant(sh::GLenum shaderType,
     106             :                      int shaderVersion,
     107             :                      ShShaderOutput outputType,
     108             :                      ShCompileOptions compileOptions)
     109             : {
     110           0 :     if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 &&
     111           0 :         shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
     112           0 :         return true;
     113             : 
     114           0 :     if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
     115           0 :         shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER)
     116           0 :         return true;
     117             : 
     118           0 :     return false;
     119             : }
     120             : 
     121           0 : size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
     122             : {
     123             :     // WebGL defines a max token length of 256, while ES2 leaves max token
     124             :     // size undefined. ES3 defines a max size of 1024 characters.
     125           0 :     switch (spec)
     126             :     {
     127             :         case SH_WEBGL_SPEC:
     128           0 :             return 256;
     129             :         default:
     130           0 :             return 1024;
     131             :     }
     132             : }
     133             : 
     134             : namespace {
     135             : 
     136             : class TScopedPoolAllocator
     137             : {
     138             :   public:
     139           0 :     TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator)
     140             :     {
     141           0 :         mAllocator->push();
     142           0 :         SetGlobalPoolAllocator(mAllocator);
     143           0 :     }
     144           0 :     ~TScopedPoolAllocator()
     145           0 :     {
     146           0 :         SetGlobalPoolAllocator(NULL);
     147           0 :         mAllocator->pop();
     148           0 :     }
     149             : 
     150             :   private:
     151             :     TPoolAllocator* mAllocator;
     152             : };
     153             : 
     154             : class TScopedSymbolTableLevel
     155             : {
     156             :   public:
     157           0 :     TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table)
     158             :     {
     159           0 :         ASSERT(mTable->atBuiltInLevel());
     160           0 :         mTable->push();
     161           0 :     }
     162           0 :     ~TScopedSymbolTableLevel()
     163           0 :     {
     164           0 :         while (!mTable->atBuiltInLevel())
     165           0 :             mTable->pop();
     166           0 :     }
     167             : 
     168             :   private:
     169             :     TSymbolTable* mTable;
     170             : };
     171             : 
     172           0 : int MapSpecToShaderVersion(ShShaderSpec spec)
     173             : {
     174           0 :     switch (spec)
     175             :     {
     176             :         case SH_GLES2_SPEC:
     177             :         case SH_WEBGL_SPEC:
     178           0 :             return 100;
     179             :         case SH_GLES3_SPEC:
     180             :         case SH_WEBGL2_SPEC:
     181           0 :             return 300;
     182             :         case SH_GLES3_1_SPEC:
     183             :         case SH_WEBGL3_SPEC:
     184           0 :             return 310;
     185             :         default:
     186           0 :             UNREACHABLE();
     187             :             return 0;
     188             :     }
     189             : }
     190             : 
     191             : }  // namespace
     192             : 
     193           0 : TShHandleBase::TShHandleBase()
     194             : {
     195           0 :     allocator.push();
     196           0 :     SetGlobalPoolAllocator(&allocator);
     197           0 : }
     198             : 
     199           0 : TShHandleBase::~TShHandleBase()
     200             : {
     201           0 :     SetGlobalPoolAllocator(NULL);
     202           0 :     allocator.popAll();
     203           0 : }
     204             : 
     205           0 : TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
     206             :     : variablesCollected(false),
     207             :       shaderType(type),
     208             :       shaderSpec(spec),
     209             :       outputType(output),
     210             :       maxUniformVectors(0),
     211             :       maxExpressionComplexity(0),
     212             :       maxCallStackDepth(0),
     213             :       maxFunctionParameters(0),
     214             :       fragmentPrecisionHigh(false),
     215             :       clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
     216             :       builtInFunctionEmulator(),
     217             :       mSourcePath(NULL),
     218             :       mComputeShaderLocalSizeDeclared(false),
     219           0 :       mTemporaryIndex(0)
     220             : {
     221           0 :     mComputeShaderLocalSize.fill(1);
     222           0 : }
     223             : 
     224           0 : TCompiler::~TCompiler()
     225             : {
     226           0 : }
     227             : 
     228           0 : bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const
     229             : {
     230             :     // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
     231             :     // validate loop and indexing as well (to verify that the shader only uses minimal functionality
     232             :     // of ESSL 1.00 as in Appendix A of the spec).
     233           0 :     return (IsWebGLBasedSpec(shaderSpec) && shaderVersion == 100) ||
     234           0 :            (compileOptions & SH_VALIDATE_LOOP_INDEXING);
     235             : }
     236             : 
     237           0 : bool TCompiler::Init(const ShBuiltInResources& resources)
     238             : {
     239           0 :     shaderVersion = 100;
     240           0 :     maxUniformVectors = (shaderType == GL_VERTEX_SHADER) ?
     241             :         resources.MaxVertexUniformVectors :
     242             :         resources.MaxFragmentUniformVectors;
     243           0 :     maxExpressionComplexity = resources.MaxExpressionComplexity;
     244           0 :     maxCallStackDepth       = resources.MaxCallStackDepth;
     245           0 :     maxFunctionParameters   = resources.MaxFunctionParameters;
     246             : 
     247           0 :     SetGlobalPoolAllocator(&allocator);
     248             : 
     249             :     // Generate built-in symbol table.
     250           0 :     if (!InitBuiltInSymbolTable(resources))
     251           0 :         return false;
     252           0 :     InitExtensionBehavior(resources, extensionBehavior);
     253           0 :     fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
     254             : 
     255           0 :     arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
     256           0 :     clampingStrategy = resources.ArrayIndexClampingStrategy;
     257             : 
     258           0 :     hashFunction = resources.HashFunction;
     259             : 
     260           0 :     return true;
     261             : }
     262             : 
     263           0 : TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
     264             :                                                size_t numStrings,
     265             :                                                ShCompileOptions compileOptions)
     266             : {
     267           0 :     return compileTreeImpl(shaderStrings, numStrings, compileOptions);
     268             : }
     269             : 
     270           0 : TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
     271             :                                          size_t numStrings,
     272             :                                          const ShCompileOptions compileOptions)
     273             : {
     274           0 :     clearResults();
     275             : 
     276           0 :     ASSERT(numStrings > 0);
     277           0 :     ASSERT(GetGlobalPoolAllocator());
     278             : 
     279             :     // Reset the extension behavior for each compilation unit.
     280           0 :     ResetExtensionBehavior(extensionBehavior);
     281             : 
     282             :     // First string is path of source file if flag is set. The actual source follows.
     283           0 :     size_t firstSource = 0;
     284           0 :     if (compileOptions & SH_SOURCE_PATH)
     285             :     {
     286           0 :         mSourcePath = shaderStrings[0];
     287           0 :         ++firstSource;
     288             :     }
     289             : 
     290             :     TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec,
     291           0 :                                compileOptions, true, infoSink, getResources());
     292             : 
     293           0 :     parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
     294           0 :     SetGlobalParseContext(&parseContext);
     295             : 
     296             :     // We preserve symbols at the built-in level from compile-to-compile.
     297             :     // Start pushing the user-defined symbols at global level.
     298           0 :     TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
     299             : 
     300             :     // Parse shader.
     301             :     bool success =
     302           0 :         (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr, &parseContext) == 0) &&
     303           0 :         (parseContext.getTreeRoot() != nullptr);
     304             : 
     305           0 :     shaderVersion = parseContext.getShaderVersion();
     306           0 :     if (success && MapSpecToShaderVersion(shaderSpec) < shaderVersion)
     307             :     {
     308           0 :         infoSink.info.prefix(EPrefixError);
     309           0 :         infoSink.info << "unsupported shader version";
     310           0 :         success = false;
     311             :     }
     312             : 
     313           0 :     TIntermBlock *root = nullptr;
     314             : 
     315           0 :     if (success)
     316             :     {
     317           0 :         mPragma = parseContext.pragma();
     318           0 :         symbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
     319             : 
     320           0 :         mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
     321           0 :         mComputeShaderLocalSize         = parseContext.getComputeShaderLocalSize();
     322             : 
     323           0 :         root = parseContext.getTreeRoot();
     324             : 
     325             :         // Highp might have been auto-enabled based on shader version
     326           0 :         fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
     327             : 
     328             :         // Disallow expressions deemed too complex.
     329           0 :         if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
     330           0 :             success = limitExpressionComplexity(root);
     331             : 
     332             :         // Create the function DAG and check there is no recursion
     333           0 :         if (success)
     334           0 :             success = initCallDag(root);
     335             : 
     336           0 :         if (success && (compileOptions & SH_LIMIT_CALL_STACK_DEPTH))
     337           0 :             success = checkCallDepth();
     338             : 
     339             :         // Checks which functions are used and if "main" exists
     340           0 :         if (success)
     341             :         {
     342           0 :             functionMetadata.clear();
     343           0 :             functionMetadata.resize(mCallDag.size());
     344           0 :             success = tagUsedFunctions();
     345             :         }
     346             : 
     347           0 :         if (success && !(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
     348           0 :             success = pruneUnusedFunctions(root);
     349             : 
     350             :         // Prune empty declarations to work around driver bugs and to keep declaration output simple.
     351           0 :         if (success)
     352           0 :             PruneEmptyDeclarations(root);
     353             : 
     354           0 :         if (success && shaderVersion == 300 && shaderType == GL_FRAGMENT_SHADER)
     355           0 :             success = validateOutputs(root);
     356             : 
     357           0 :         if (success && shouldRunLoopAndIndexingValidation(compileOptions))
     358           0 :             success = validateLimitations(root);
     359             : 
     360             :         // Fail compilation if precision emulation not supported.
     361           0 :         if (success && getResources().WEBGL_debug_shader_precision &&
     362           0 :             getPragma().debugShaderPrecision)
     363             :         {
     364           0 :             if (!EmulatePrecision::SupportedInLanguage(outputType))
     365             :             {
     366           0 :                 infoSink.info.prefix(EPrefixError);
     367           0 :                 infoSink.info << "Precision emulation not supported for this output type.";
     368           0 :                 success = false;
     369             :             }
     370             :         }
     371             : 
     372             :         // Built-in function emulation needs to happen after validateLimitations pass.
     373           0 :         if (success)
     374             :         {
     375             :             // TODO(jmadill): Remove global pool allocator.
     376           0 :             GetGlobalPoolAllocator()->lock();
     377           0 :             initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
     378           0 :             GetGlobalPoolAllocator()->unlock();
     379           0 :             builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
     380             :         }
     381             : 
     382             :         // Clamping uniform array bounds needs to happen after validateLimitations pass.
     383           0 :         if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
     384           0 :             arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
     385             : 
     386             :         // gl_Position is always written in compatibility output mode
     387           0 :         if (success && shaderType == GL_VERTEX_SHADER &&
     388           0 :             ((compileOptions & SH_INIT_GL_POSITION) ||
     389           0 :              (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
     390           0 :             initializeGLPosition(root);
     391             : 
     392           0 :         if (success && RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions))
     393           0 :             sh::RemoveInvariantDeclaration(root);
     394             : 
     395             :         // This pass might emit short circuits so keep it before the short circuit unfolding
     396           0 :         if (success && (compileOptions & SH_REWRITE_DO_WHILE_LOOPS))
     397           0 :             RewriteDoWhile(root, getTemporaryIndex());
     398             : 
     399           0 :         if (success && (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION))
     400           0 :             sh::AddAndTrueToLoopCondition(root);
     401             : 
     402           0 :         if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT))
     403             :         {
     404           0 :             UnfoldShortCircuitAST unfoldShortCircuit;
     405           0 :             root->traverse(&unfoldShortCircuit);
     406           0 :             unfoldShortCircuit.updateTree();
     407             :         }
     408             : 
     409           0 :         if (success && (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT))
     410             :         {
     411           0 :             RemovePow(root);
     412             :         }
     413             : 
     414           0 :         if (success && shouldCollectVariables(compileOptions))
     415             :         {
     416           0 :             collectVariables(root);
     417           0 :             if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
     418             :             {
     419           0 :                 useAllMembersInUnusedStandardAndSharedBlocks(root);
     420             :             }
     421           0 :             if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
     422             :             {
     423           0 :                 success = enforcePackingRestrictions();
     424           0 :                 if (!success)
     425             :                 {
     426           0 :                     infoSink.info.prefix(EPrefixError);
     427           0 :                     infoSink.info << "too many uniforms";
     428             :                 }
     429             :             }
     430           0 :             if (success && (compileOptions & SH_INIT_OUTPUT_VARIABLES))
     431             :             {
     432           0 :                 initializeOutputVariables(root);
     433             :             }
     434             :         }
     435             : 
     436           0 :         if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS))
     437             :         {
     438           0 :             ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh,
     439           0 :                                               &mTemporaryIndex);
     440             :         }
     441             : 
     442           0 :         if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES))
     443             :         {
     444           0 :             RegenerateStructNames gen(symbolTable, shaderVersion);
     445           0 :             root->traverse(&gen);
     446             :         }
     447             : 
     448           0 :         if (success && shaderType == GL_FRAGMENT_SHADER && shaderVersion == 100 &&
     449           0 :             compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 &&
     450           0 :             IsExtensionEnabled(extensionBehavior, "GL_EXT_draw_buffers"))
     451             :         {
     452           0 :             EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables);
     453             :         }
     454             : 
     455           0 :         if (success)
     456             :         {
     457           0 :             DeferGlobalInitializers(root);
     458             :         }
     459             :     }
     460             : 
     461           0 :     SetGlobalParseContext(NULL);
     462           0 :     if (success)
     463           0 :         return root;
     464             : 
     465           0 :     return NULL;
     466             : }
     467             : 
     468           0 : bool TCompiler::compile(const char *const shaderStrings[],
     469             :                         size_t numStrings,
     470             :                         ShCompileOptions compileOptionsIn)
     471             : {
     472             : #if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
     473             :     DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn);
     474             : #endif  // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
     475             : 
     476           0 :     if (numStrings == 0)
     477           0 :         return true;
     478             : 
     479           0 :     ShCompileOptions compileOptions = compileOptionsIn;
     480             : 
     481             :     // Apply key workarounds.
     482           0 :     if (shouldFlattenPragmaStdglInvariantAll())
     483             :     {
     484             :         // This should be harmless to do in all cases, but for the moment, do it only conditionally.
     485           0 :         compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
     486             :     }
     487             : 
     488           0 :     TScopedPoolAllocator scopedAlloc(&allocator);
     489           0 :     TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
     490             : 
     491           0 :     if (root)
     492             :     {
     493           0 :         if (compileOptions & SH_INTERMEDIATE_TREE)
     494           0 :             TIntermediate::outputTree(root, infoSink.info);
     495             : 
     496           0 :         if (compileOptions & SH_OBJECT_CODE)
     497           0 :             translate(root, compileOptions);
     498             : 
     499             :         // The IntermNode tree doesn't need to be deleted here, since the
     500             :         // memory will be freed in a big chunk by the PoolAllocator.
     501           0 :         return true;
     502             :     }
     503           0 :     return false;
     504             : }
     505             : 
     506           0 : bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
     507             : {
     508           0 :     if (resources.MaxDrawBuffers < 1)
     509             :     {
     510           0 :         return false;
     511             :     }
     512           0 :     if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)
     513             :     {
     514           0 :         return false;
     515             :     }
     516             : 
     517           0 :     compileResources = resources;
     518           0 :     setResourceString();
     519             : 
     520           0 :     assert(symbolTable.isEmpty());
     521           0 :     symbolTable.push();   // COMMON_BUILTINS
     522           0 :     symbolTable.push();   // ESSL1_BUILTINS
     523           0 :     symbolTable.push();   // ESSL3_BUILTINS
     524           0 :     symbolTable.push();   // ESSL3_1_BUILTINS
     525             : 
     526             :     TPublicType integer;
     527           0 :     integer.initializeBasicType(EbtInt);
     528             : 
     529             :     TPublicType floatingPoint;
     530           0 :     floatingPoint.initializeBasicType(EbtFloat);
     531             : 
     532           0 :     switch (shaderType)
     533             :     {
     534             :         case GL_FRAGMENT_SHADER:
     535           0 :             symbolTable.setDefaultPrecision(integer, EbpMedium);
     536           0 :             break;
     537             :         case GL_VERTEX_SHADER:
     538           0 :             symbolTable.setDefaultPrecision(integer, EbpHigh);
     539           0 :             symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
     540           0 :             break;
     541             :         case GL_COMPUTE_SHADER:
     542           0 :             symbolTable.setDefaultPrecision(integer, EbpHigh);
     543           0 :             symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
     544           0 :             break;
     545             :         default:
     546           0 :             assert(false && "Language not supported");
     547             :     }
     548             :     // Set defaults for sampler types that have default precision, even those that are
     549             :     // only available if an extension exists.
     550             :     // New sampler types in ESSL3 don't have default precision. ESSL1 types do.
     551           0 :     initSamplerDefaultPrecision(EbtSampler2D);
     552           0 :     initSamplerDefaultPrecision(EbtSamplerCube);
     553             :     // SamplerExternalOES is specified in the extension to have default precision.
     554           0 :     initSamplerDefaultPrecision(EbtSamplerExternalOES);
     555             :     // It isn't specified whether Sampler2DRect has default precision.
     556           0 :     initSamplerDefaultPrecision(EbtSampler2DRect);
     557             : 
     558           0 :     InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
     559             : 
     560           0 :     IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
     561             : 
     562           0 :     return true;
     563             : }
     564             : 
     565           0 : void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType)
     566             : {
     567           0 :     ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd);
     568             :     TPublicType sampler;
     569           0 :     sampler.initializeBasicType(samplerType);
     570           0 :     symbolTable.setDefaultPrecision(sampler, EbpLow);
     571           0 : }
     572             : 
     573           0 : void TCompiler::setResourceString()
     574             : {
     575           0 :     std::ostringstream strstream;
     576             : 
     577             :     // clang-format off
     578           0 :     strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
     579           0 :         << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
     580           0 :         << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
     581           0 :         << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
     582           0 :         << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
     583           0 :         << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
     584           0 :         << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
     585           0 :         << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
     586           0 :         << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
     587           0 :         << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
     588           0 :         << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3
     589           0 :         << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external
     590           0 :         << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
     591           0 :         << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
     592           0 :         << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
     593           0 :         << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
     594           0 :         << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
     595           0 :         << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters
     596           0 :         << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended
     597           0 :         << ":EXT_frag_depth:" << compileResources.EXT_frag_depth
     598           0 :         << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
     599           0 :         << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
     600           0 :         << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
     601           0 :         << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
     602           0 :         << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
     603           0 :         << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
     604           0 :         << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
     605           0 :         << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
     606           0 :         << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
     607           0 :         << ":NV_draw_buffers:" << compileResources.NV_draw_buffers
     608           0 :         << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision
     609           0 :         << ":MaxImageUnits:" << compileResources.MaxImageUnits
     610           0 :         << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms
     611           0 :         << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms
     612           0 :         << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms
     613           0 :         << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms
     614           0 :         << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources
     615           0 :         << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0]
     616           0 :         << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1]
     617           0 :         << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2]
     618           0 :         << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0]
     619           0 :         << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1]
     620           0 :         << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2]
     621           0 :         << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents
     622           0 :         << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits
     623           0 :         << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters
     624           0 :         << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers
     625           0 :         << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters
     626           0 :         << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters
     627           0 :         << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters
     628           0 :         << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings
     629           0 :         << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers
     630           0 :         << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
     631           0 :         << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
     632           0 :         << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize;
     633             :     // clang-format on
     634             : 
     635           0 :     builtInResourcesString = strstream.str();
     636           0 : }
     637             : 
     638           0 : void TCompiler::clearResults()
     639             : {
     640           0 :     arrayBoundsClamper.Cleanup();
     641           0 :     infoSink.info.erase();
     642           0 :     infoSink.obj.erase();
     643           0 :     infoSink.debug.erase();
     644             : 
     645           0 :     attributes.clear();
     646           0 :     outputVariables.clear();
     647           0 :     uniforms.clear();
     648           0 :     expandedUniforms.clear();
     649           0 :     varyings.clear();
     650           0 :     interfaceBlocks.clear();
     651           0 :     variablesCollected = false;
     652             : 
     653           0 :     builtInFunctionEmulator.Cleanup();
     654             : 
     655           0 :     nameMap.clear();
     656             : 
     657           0 :     mSourcePath = NULL;
     658           0 :     mTemporaryIndex = 0;
     659           0 : }
     660             : 
     661           0 : bool TCompiler::initCallDag(TIntermNode *root)
     662             : {
     663           0 :     mCallDag.clear();
     664             : 
     665           0 :     switch (mCallDag.init(root, &infoSink.info))
     666             :     {
     667             :         case CallDAG::INITDAG_SUCCESS:
     668           0 :             return true;
     669             :         case CallDAG::INITDAG_RECURSION:
     670           0 :             infoSink.info.prefix(EPrefixError);
     671           0 :             infoSink.info << "Function recursion detected";
     672           0 :             return false;
     673             :         case CallDAG::INITDAG_UNDEFINED:
     674           0 :             infoSink.info.prefix(EPrefixError);
     675           0 :             infoSink.info << "Unimplemented function detected";
     676           0 :             return false;
     677             :     }
     678             : 
     679           0 :     UNREACHABLE();
     680             :     return true;
     681             : }
     682             : 
     683           0 : bool TCompiler::checkCallDepth()
     684             : {
     685           0 :     std::vector<int> depths(mCallDag.size());
     686             : 
     687           0 :     for (size_t i = 0; i < mCallDag.size(); i++)
     688             :     {
     689           0 :         int depth = 0;
     690           0 :         auto &record = mCallDag.getRecordFromIndex(i);
     691             : 
     692           0 :         for (auto &calleeIndex : record.callees)
     693             :         {
     694           0 :             depth = std::max(depth, depths[calleeIndex] + 1);
     695             :         }
     696             : 
     697           0 :         depths[i] = depth;
     698             : 
     699           0 :         if (depth >= maxCallStackDepth)
     700             :         {
     701             :             // Trace back the function chain to have a meaningful info log.
     702           0 :             infoSink.info.prefix(EPrefixError);
     703           0 :             infoSink.info << "Call stack too deep (larger than " << maxCallStackDepth
     704           0 :                           << ") with the following call chain: " << record.name;
     705             : 
     706           0 :             int currentFunction = static_cast<int>(i);
     707           0 :             int currentDepth = depth;
     708             : 
     709           0 :             while (currentFunction != -1)
     710             :             {
     711           0 :                 infoSink.info << " -> " << mCallDag.getRecordFromIndex(currentFunction).name;
     712             : 
     713           0 :                 int nextFunction = -1;
     714           0 :                 for (auto& calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
     715             :                 {
     716           0 :                     if (depths[calleeIndex] == currentDepth - 1)
     717             :                     {
     718           0 :                         currentDepth--;
     719           0 :                         nextFunction = calleeIndex;
     720             :                     }
     721             :                 }
     722             : 
     723           0 :                 currentFunction = nextFunction;
     724             :             }
     725             : 
     726           0 :             return false;
     727             :         }
     728             :     }
     729             : 
     730           0 :     return true;
     731             : }
     732             : 
     733           0 : bool TCompiler::tagUsedFunctions()
     734             : {
     735             :     // Search from main, starting from the end of the DAG as it usually is the root.
     736           0 :     for (size_t i = mCallDag.size(); i-- > 0;)
     737             :     {
     738           0 :         if (mCallDag.getRecordFromIndex(i).name == "main(")
     739             :         {
     740           0 :             internalTagUsedFunction(i);
     741           0 :             return true;
     742             :         }
     743             :     }
     744             : 
     745           0 :     infoSink.info.prefix(EPrefixError);
     746           0 :     infoSink.info << "Missing main()\n";
     747           0 :     return false;
     748             : }
     749             : 
     750           0 : void TCompiler::internalTagUsedFunction(size_t index)
     751             : {
     752           0 :     if (functionMetadata[index].used)
     753             :     {
     754           0 :         return;
     755             :     }
     756             : 
     757           0 :     functionMetadata[index].used = true;
     758             : 
     759           0 :     for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
     760             :     {
     761           0 :         internalTagUsedFunction(calleeIndex);
     762             :     }
     763             : }
     764             : 
     765             : // A predicate for the stl that returns if a top-level node is unused
     766             : class TCompiler::UnusedPredicate
     767             : {
     768             :   public:
     769           0 :     UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
     770           0 :         : mCallDag(callDag), mMetadatas(metadatas)
     771             :     {
     772           0 :     }
     773             : 
     774           0 :     bool operator ()(TIntermNode *node)
     775             :     {
     776           0 :         const TIntermAggregate *asAggregate = node->getAsAggregate();
     777           0 :         const TIntermFunctionDefinition *asFunction = node->getAsFunctionDefinition();
     778             : 
     779           0 :         const TFunctionSymbolInfo *functionInfo = nullptr;
     780             : 
     781           0 :         if (asFunction)
     782             :         {
     783           0 :             functionInfo = asFunction->getFunctionSymbolInfo();
     784             :         }
     785           0 :         else if (asAggregate)
     786             :         {
     787           0 :             if (asAggregate->getOp() == EOpPrototype)
     788             :             {
     789           0 :                 functionInfo = asAggregate->getFunctionSymbolInfo();
     790             :             }
     791             :         }
     792           0 :         if (functionInfo == nullptr)
     793             :         {
     794           0 :             return false;
     795             :         }
     796             : 
     797           0 :         size_t callDagIndex = mCallDag->findIndex(functionInfo);
     798           0 :         if (callDagIndex == CallDAG::InvalidIndex)
     799             :         {
     800             :             // This happens only for unimplemented prototypes which are thus unused
     801           0 :             ASSERT(asAggregate && asAggregate->getOp() == EOpPrototype);
     802           0 :             return true;
     803             :         }
     804             : 
     805           0 :         ASSERT(callDagIndex < mMetadatas->size());
     806           0 :         return !(*mMetadatas)[callDagIndex].used;
     807             :     }
     808             : 
     809             :   private:
     810             :     const CallDAG *mCallDag;
     811             :     const std::vector<FunctionMetadata> *mMetadatas;
     812             : };
     813             : 
     814           0 : bool TCompiler::pruneUnusedFunctions(TIntermBlock *root)
     815             : {
     816           0 :     UnusedPredicate isUnused(&mCallDag, &functionMetadata);
     817           0 :     TIntermSequence *sequence = root->getSequence();
     818             : 
     819           0 :     if (!sequence->empty())
     820             :     {
     821           0 :         sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused), sequence->end());
     822             :     }
     823             : 
     824           0 :     return true;
     825             : }
     826             : 
     827           0 : bool TCompiler::validateOutputs(TIntermNode* root)
     828             : {
     829           0 :     ValidateOutputs validateOutputs(getExtensionBehavior(), compileResources.MaxDrawBuffers);
     830           0 :     root->traverse(&validateOutputs);
     831           0 :     return (validateOutputs.validateAndCountErrors(infoSink.info) == 0);
     832             : }
     833             : 
     834           0 : bool TCompiler::validateLimitations(TIntermNode* root)
     835             : {
     836           0 :     ValidateLimitations validate(shaderType, &infoSink.info);
     837           0 :     root->traverse(&validate);
     838           0 :     return validate.numErrors() == 0;
     839             : }
     840             : 
     841           0 : bool TCompiler::limitExpressionComplexity(TIntermNode* root)
     842             : {
     843           0 :     TMaxDepthTraverser traverser(maxExpressionComplexity + 1);
     844           0 :     root->traverse(&traverser);
     845             : 
     846           0 :     if (traverser.getMaxDepth() > maxExpressionComplexity)
     847             :     {
     848           0 :         infoSink.info << "Expression too complex.";
     849           0 :         return false;
     850             :     }
     851             : 
     852           0 :     if (!ValidateMaxParameters::validate(root, maxFunctionParameters))
     853             :     {
     854           0 :         infoSink.info << "Function has too many parameters.";
     855           0 :         return false;
     856             :     }
     857             : 
     858           0 :     return true;
     859             : }
     860             : 
     861           0 : void TCompiler::collectVariables(TIntermNode* root)
     862             : {
     863           0 :     if (!variablesCollected)
     864             :     {
     865             :         sh::CollectVariables collect(&attributes, &outputVariables, &uniforms, &varyings,
     866             :                                      &interfaceBlocks, hashFunction, symbolTable,
     867           0 :                                      extensionBehavior);
     868           0 :         root->traverse(&collect);
     869             : 
     870             :         // This is for enforcePackingRestriction().
     871           0 :         sh::ExpandUniforms(uniforms, &expandedUniforms);
     872           0 :         variablesCollected = true;
     873             :     }
     874           0 : }
     875             : 
     876           0 : bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
     877             : {
     878           0 :     return (compileOptions & SH_VARIABLES) != 0;
     879             : }
     880             : 
     881           0 : bool TCompiler::wereVariablesCollected() const
     882             : {
     883           0 :     return variablesCollected;
     884             : }
     885             : 
     886           0 : bool TCompiler::enforcePackingRestrictions()
     887             : {
     888           0 :     VariablePacker packer;
     889           0 :     return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, expandedUniforms);
     890             : }
     891             : 
     892           0 : void TCompiler::initializeGLPosition(TIntermNode* root)
     893             : {
     894           0 :     InitVariableList list;
     895           0 :     sh::ShaderVariable var(GL_FLOAT_VEC4, 0);
     896           0 :     var.name = "gl_Position";
     897           0 :     list.push_back(var);
     898           0 :     InitializeVariables(root, list, symbolTable);
     899           0 : }
     900             : 
     901           0 : void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermNode *root)
     902             : {
     903           0 :     sh::InterfaceBlockList list;
     904             : 
     905           0 :     for (auto block : interfaceBlocks)
     906             :     {
     907           0 :         if (!block.staticUse &&
     908           0 :             (block.layout == sh::BLOCKLAYOUT_STANDARD || block.layout == sh::BLOCKLAYOUT_SHARED))
     909             :         {
     910           0 :             list.push_back(block);
     911             :         }
     912             :     }
     913             : 
     914           0 :     sh::UseInterfaceBlockFields(root, list, symbolTable);
     915           0 : }
     916             : 
     917           0 : void TCompiler::initializeOutputVariables(TIntermNode *root)
     918             : {
     919           0 :     InitVariableList list;
     920           0 :     if (shaderType == GL_VERTEX_SHADER)
     921             :     {
     922           0 :         for (auto var : varyings)
     923             :         {
     924           0 :             list.push_back(var);
     925             :         }
     926             :     }
     927             :     else
     928             :     {
     929           0 :         ASSERT(shaderType == GL_FRAGMENT_SHADER);
     930           0 :         for (auto var : outputVariables)
     931             :         {
     932           0 :             list.push_back(var);
     933             :         }
     934             :     }
     935           0 :     InitializeVariables(root, list, symbolTable);
     936           0 : }
     937             : 
     938           0 : const TExtensionBehavior& TCompiler::getExtensionBehavior() const
     939             : {
     940           0 :     return extensionBehavior;
     941             : }
     942             : 
     943           0 : const char *TCompiler::getSourcePath() const
     944             : {
     945           0 :     return mSourcePath;
     946             : }
     947             : 
     948           0 : const ShBuiltInResources& TCompiler::getResources() const
     949             : {
     950           0 :     return compileResources;
     951             : }
     952             : 
     953           0 : const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
     954             : {
     955           0 :     return arrayBoundsClamper;
     956             : }
     957             : 
     958           0 : ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
     959             : {
     960           0 :     return clampingStrategy;
     961             : }
     962             : 
     963           0 : const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
     964             : {
     965           0 :     return builtInFunctionEmulator;
     966             : }
     967             : 
     968           0 : void TCompiler::writePragma(ShCompileOptions compileOptions)
     969             : {
     970           0 :     if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL))
     971             :     {
     972           0 :         TInfoSinkBase &sink = infoSink.obj;
     973           0 :         if (mPragma.stdgl.invariantAll)
     974           0 :             sink << "#pragma STDGL invariant(all)\n";
     975             :     }
     976           0 : }
     977             : 
     978           0 : bool TCompiler::isVaryingDefined(const char *varyingName)
     979             : {
     980           0 :     ASSERT(variablesCollected);
     981           0 :     for (size_t ii = 0; ii < varyings.size(); ++ii)
     982             :     {
     983           0 :         if (varyings[ii].name == varyingName)
     984             :         {
     985           0 :             return true;
     986             :         }
     987             :     }
     988             : 
     989           0 :     return false;
     990             : }
     991             : 
     992             : }  // namespace sh

Generated by: LCOV version 1.13