// // Copyright 2017 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. // // RunAtTheEndOfShader.cpp: Add code to be run at the end of the shader. In case main() contains a // return statement, this is done by replacing the main() function with another function that calls // the old main, like this: // // void main() { body } // => // void main0() { body } // void main() // { // main0(); // codeToRun // } // // This way the code will get run even if the return statement inside main is executed. // // This is done if main ends in an unconditional |discard| as well, to help with SPIR-V generation // that expects no dead-code to be present after branches in a block. To avoid bugs when |discard| // is wrapped in unconditional blocks, any |discard| in main() is used as a signal to wrap it. // #include "compiler/translator/tree_util/RunAtTheEndOfShader.h" #include "compiler/translator/Compiler.h" #include "compiler/translator/IntermNode.h" #include "compiler/translator/StaticType.h" #include "compiler/translator/SymbolTable.h" #include "compiler/translator/tree_util/FindMain.h" #include "compiler/translator/tree_util/IntermNode_util.h" #include "compiler/translator/tree_util/IntermTraverse.h" namespace sh { namespace { constexpr const ImmutableString kMainString("main"); class ContainsReturnOrDiscardTraverser : public TIntermTraverser { … }; bool ContainsReturnOrDiscard(TIntermNode *node) { … } void WrapMainAndAppend(TIntermBlock *root, TIntermFunctionDefinition *main, TIntermNode *codeToRun, TSymbolTable *symbolTable) { … } } // anonymous namespace bool RunAtTheEndOfShader(TCompiler *compiler, TIntermBlock *root, TIntermNode *codeToRun, TSymbolTable *symbolTable) { … } } // namespace sh