Home | History | Annotate | Download | only in compiler
      1 //
      2 // Copyright (c) 2002-2010 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/Initialize.h"
      8 #include "compiler/ParseHelper.h"
      9 #include "compiler/ShHandle.h"
     10 #include "compiler/ValidateLimitations.h"
     11 
     12 namespace {
     13 bool InitializeSymbolTable(
     14     const TBuiltInStrings& builtInStrings,
     15     ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
     16     TInfoSink& infoSink, TSymbolTable& symbolTable)
     17 {
     18     TIntermediate intermediate(infoSink);
     19     TExtensionBehavior extBehavior;
     20     TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, infoSink);
     21 
     22     GlobalParseContext = &parseContext;
     23 
     24     assert(symbolTable.isEmpty());
     25     //
     26     // Parse the built-ins.  This should only happen once per
     27     // language symbol table.
     28     //
     29     // Push the symbol table to give it an initial scope.  This
     30     // push should not have a corresponding pop, so that built-ins
     31     // are preserved, and the test for an empty table fails.
     32     //
     33     symbolTable.push();
     34 
     35     for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
     36     {
     37         const char* builtInShaders = i->c_str();
     38         int builtInLengths = static_cast<int>(i->size());
     39         if (builtInLengths <= 0)
     40           continue;
     41 
     42         if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
     43         {
     44             infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
     45             return false;
     46         }
     47     }
     48 
     49     IdentifyBuiltIns(type, spec, resources, symbolTable);
     50 
     51     return true;
     52 }
     53 
     54 class TScopedPoolAllocator {
     55 public:
     56     TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
     57         : mAllocator(allocator), mPushPopAllocator(pushPop) {
     58         if (mPushPopAllocator) mAllocator->push();
     59         SetGlobalPoolAllocator(mAllocator);
     60     }
     61     ~TScopedPoolAllocator() {
     62         SetGlobalPoolAllocator(NULL);
     63         if (mPushPopAllocator) mAllocator->pop();
     64     }
     65 
     66 private:
     67     TPoolAllocator* mAllocator;
     68     bool mPushPopAllocator;
     69 };
     70 }  // namespace
     71 
     72 TShHandleBase::TShHandleBase() {
     73     allocator.push();
     74     SetGlobalPoolAllocator(&allocator);
     75 }
     76 
     77 TShHandleBase::~TShHandleBase() {
     78     SetGlobalPoolAllocator(NULL);
     79     allocator.popAll();
     80 }
     81 
     82 TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
     83     : shaderType(type),
     84       shaderSpec(spec)
     85 {
     86 }
     87 
     88 TCompiler::~TCompiler()
     89 {
     90 }
     91 
     92 bool TCompiler::Init(const ShBuiltInResources& resources)
     93 {
     94     TScopedPoolAllocator scopedAlloc(&allocator, false);
     95 
     96     // Generate built-in symbol table.
     97     if (!InitBuiltInSymbolTable(resources))
     98         return false;
     99     InitExtensionBehavior(resources, extensionBehavior);
    100 
    101     return true;
    102 }
    103 
    104 bool TCompiler::compile(const char* const shaderStrings[],
    105                         const int numStrings,
    106                         int compileOptions)
    107 {
    108     TScopedPoolAllocator scopedAlloc(&allocator, true);
    109     clearResults();
    110 
    111     if (numStrings == 0)
    112         return true;
    113 
    114     // If compiling for WebGL, validate loop and indexing as well.
    115     if (shaderSpec == SH_WEBGL_SPEC)
    116         compileOptions |= SH_VALIDATE_LOOP_INDEXING;
    117 
    118     TIntermediate intermediate(infoSink);
    119     TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
    120                                shaderType, shaderSpec, infoSink);
    121     GlobalParseContext = &parseContext;
    122 
    123     // We preserve symbols at the built-in level from compile-to-compile.
    124     // Start pushing the user-defined symbols at global level.
    125     symbolTable.push();
    126     if (!symbolTable.atGlobalLevel())
    127         infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
    128 
    129     // Parse shader.
    130     bool success =
    131         (PaParseStrings(numStrings, shaderStrings, NULL, &parseContext) == 0) &&
    132         (parseContext.treeRoot != NULL);
    133     if (success) {
    134         TIntermNode* root = parseContext.treeRoot;
    135         success = intermediate.postProcess(root);
    136 
    137         if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
    138             success = validateLimitations(root);
    139 
    140         if (success && (compileOptions & SH_INTERMEDIATE_TREE))
    141             intermediate.outputTree(root);
    142 
    143         if (success && (compileOptions & SH_OBJECT_CODE))
    144             translate(root);
    145 
    146         if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
    147             collectAttribsUniforms(root);
    148     }
    149 
    150     // Cleanup memory.
    151     intermediate.remove(parseContext.treeRoot);
    152     // Ensure symbol table is returned to the built-in level,
    153     // throwing away all but the built-ins.
    154     while (!symbolTable.atBuiltInLevel())
    155         symbolTable.pop();
    156 
    157     return success;
    158 }
    159 
    160 bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
    161 {
    162     TBuiltIns builtIns;
    163 
    164     builtIns.initialize(shaderType, shaderSpec, resources);
    165     return InitializeSymbolTable(builtIns.getBuiltInStrings(),
    166         shaderType, shaderSpec, resources, infoSink, symbolTable);
    167 }
    168 
    169 void TCompiler::clearResults()
    170 {
    171     infoSink.info.erase();
    172     infoSink.obj.erase();
    173     infoSink.debug.erase();
    174 
    175     attribs.clear();
    176     uniforms.clear();
    177 }
    178 
    179 bool TCompiler::validateLimitations(TIntermNode* root) {
    180     ValidateLimitations validate(shaderType, infoSink.info);
    181     root->traverse(&validate);
    182     return validate.numErrors() == 0;
    183 }
    184 
    185 void TCompiler::collectAttribsUniforms(TIntermNode* root)
    186 {
    187     CollectAttribsUniforms collect(attribs, uniforms);
    188     root->traverse(&collect);
    189 }
    190