Edit

kc3-lang/angle/src/compiler/Compiler.cpp

Branch :

  • Show log

    Commit

  • Author : alokp@chromium.org
    Date : 2010-11-24 18:38:33
    Hash : b59a778c
    Message : Implemented validation for loop and indexing limitations specified by GLSL ES spec 1.0 Appendix A Section 4 and 5. A couple of things to note: - This CL only validates the "form" of loop and indexing. It does not detect number-of-iterations or out-of-bound access. This will require more involved analysis/heuristics. - I haved combined SH_VALIDATE_CONTROL_FLOW and SH_VALIDATE_INDEXING into one flag - SH_VALIDATE_LOOP_INDEXING. Validating both together is much easier. BUG=48 Review URL: http://codereview.appspot.com/3225041 git-svn-id: https://angleproject.googlecode.com/svn/trunk@491 736b8ea6-26fd-11df-bfd4-992fa37f6226

  • src/compiler/Compiler.cpp
  • //
    // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    #include "compiler/Initialize.h"
    #include "compiler/ParseHelper.h"
    #include "compiler/ShHandle.h"
    #include "compiler/ValidateLimitations.h"
    
    namespace {
    bool InitializeSymbolTable(
        const TBuiltInStrings& builtInStrings,
        ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
        TInfoSink& infoSink, TSymbolTable& symbolTable)
    {
        TIntermediate intermediate(infoSink);
        TExtensionBehavior extBehavior;
        TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, infoSink);
    
        GlobalParseContext = &parseContext;
    
        assert(symbolTable.isEmpty());       
        //
        // Parse the built-ins.  This should only happen once per
        // language symbol table.
        //
        // Push the symbol table to give it an initial scope.  This
        // push should not have a corresponding pop, so that built-ins
        // are preserved, and the test for an empty table fails.
        //
        symbolTable.push();
    
        for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
        {
            const char* builtInShaders = i->c_str();
            int builtInLengths = static_cast<int>(i->size());
            if (builtInLengths <= 0)
              continue;
    
            if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
            {
                infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
                return false;
            }
        }
    
        IdentifyBuiltIns(type, spec, resources, symbolTable);
    
        return true;
    }
    
    class TScopedPoolAllocator {
    public:
        TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
            : mAllocator(allocator), mPushPopAllocator(pushPop) {
            if (mPushPopAllocator) mAllocator->push();
            SetGlobalPoolAllocator(mAllocator);
        }
        ~TScopedPoolAllocator() {
            SetGlobalPoolAllocator(NULL);
            if (mPushPopAllocator) mAllocator->pop();
        }
    
    private:
        TPoolAllocator* mAllocator;
        bool mPushPopAllocator;
    };
    }  // namespace
    
    TShHandleBase::TShHandleBase() {
        allocator.push();
        SetGlobalPoolAllocator(&allocator);
    }
    
    TShHandleBase::~TShHandleBase() {
        SetGlobalPoolAllocator(NULL);
        allocator.popAll();
    }
    
    TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
        : shaderType(type),
          shaderSpec(spec) 
    {
    }
    
    TCompiler::~TCompiler()
    {
    }
    
    bool TCompiler::Init(const ShBuiltInResources& resources)
    {
        TScopedPoolAllocator scopedAlloc(&allocator, false);
    
        // Generate built-in symbol table.
        if (!InitBuiltInSymbolTable(resources))
            return false;
        InitExtensionBehavior(resources, extensionBehavior);
    
        return true;
    }
    
    bool TCompiler::compile(const char* const shaderStrings[],
                            const int numStrings,
                            int compileOptions)
    {
        TScopedPoolAllocator scopedAlloc(&allocator, true);
        clearResults();
    
        if (numStrings == 0)
            return true;
    
        // If compiling for WebGL, validate loop and indexing as well.
        if (shaderSpec == SH_WEBGL_SPEC)
            compileOptions |= SH_VALIDATE_LOOP_INDEXING;
    
        TIntermediate intermediate(infoSink);
        TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
                                   shaderType, shaderSpec, infoSink);
        GlobalParseContext = &parseContext;
    
        // We preserve symbols at the built-in level from compile-to-compile.
        // Start pushing the user-defined symbols at global level.
        symbolTable.push();
        if (!symbolTable.atGlobalLevel())
            infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
    
        // Parse shader.
        bool success =
            (PaParseStrings(numStrings, shaderStrings, NULL, &parseContext) == 0) &&
            (parseContext.treeRoot != NULL);
        if (success) {
            TIntermNode* root = parseContext.treeRoot;
            success = intermediate.postProcess(root);
    
            if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
                success = validateLimitations(root);
    
            if (success && (compileOptions & SH_INTERMEDIATE_TREE))
                intermediate.outputTree(root);
    
            if (success && (compileOptions & SH_OBJECT_CODE))
                translate(root);
    
            if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
                collectAttribsUniforms(root);
        }
    
        // Cleanup memory.
        intermediate.remove(parseContext.treeRoot);
        // Ensure symbol table is returned to the built-in level,
        // throwing away all but the built-ins.
        while (!symbolTable.atBuiltInLevel())
            symbolTable.pop();
    
        return success;
    }
    
    bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
    {
        TBuiltIns builtIns;
    
        builtIns.initialize(shaderType, shaderSpec, resources);
        return InitializeSymbolTable(builtIns.getBuiltInStrings(),
            shaderType, shaderSpec, resources, infoSink, symbolTable);
    }
    
    void TCompiler::clearResults()
    {
        infoSink.info.erase();
        infoSink.obj.erase();
        infoSink.debug.erase();
    
        attribs.clear();
        uniforms.clear();
    }
    
    bool TCompiler::validateLimitations(TIntermNode* root) {
        ValidateLimitations validate(shaderType, infoSink.info);
        root->traverse(&validate);
        return validate.numErrors() == 0;
    }
    
    void TCompiler::collectAttribsUniforms(TIntermNode* root)
    {
        CollectAttribsUniforms collect(attribs, uniforms);
        root->traverse(&collect);
    }