// // Copyright 2020 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/translator/tree_ops/msl/HoistConstants.h" #include "compiler/translator/IntermRebuild.h" #include "compiler/translator/msl/Layout.h" #include "compiler/translator/tree_util/FindFunction.h" #include "compiler/translator/tree_util/ReplaceVariable.h" #include "compiler/translator/util.h" using namespace sh; //////////////////////////////////////////////////////////////////////////////// namespace { class Rewriter : private TIntermRebuild { private: const size_t mMinRequiredSize; TIntermSequence mHoistedDeclNodes; public: Rewriter(TCompiler &compiler, size_t minRequiredSize) : TIntermRebuild(compiler, true, false), mMinRequiredSize(minRequiredSize) {} PreResult visitDeclarationPre(TIntermDeclaration &declNode) override { if (getParentFunction()) { Declaration decl = ViewDeclaration(declNode); const TType &type = decl.symbol.getType(); if (type.getQualifier() == TQualifier::EvqConst) { if (decl.initExpr && decl.initExpr->hasConstantValue()) { const size_t size = MetalLayoutOf(type).sizeOf; if (size >= mMinRequiredSize) { mHoistedDeclNodes.push_back(&declNode); return nullptr; } } } } return {declNode, VisitBits::Neither}; } bool rewrite(TIntermBlock &root, IdGen &idGen) { if (!rebuildRoot(root)) { return false; } if (mHoistedDeclNodes.empty()) { return true; } root.insertChildNodes(FindFirstFunctionDefinitionIndex(&root), mHoistedDeclNodes); for (TIntermNode *opaqueDeclNode : mHoistedDeclNodes) { TIntermDeclaration *declNode = opaqueDeclNode->getAsDeclarationNode(); ASSERT(declNode); const TVariable &oldVar = ViewDeclaration(*declNode).symbol.variable(); const Name newName = idGen.createNewName(oldVar.name()); auto *newVar = new TVariable(&mSymbolTable, newName.rawName(), &oldVar.getType(), newName.symbolType()); if (!ReplaceVariable(&mCompiler, &root, &oldVar, newVar)) { return false; } } return true; } }; } // anonymous namespace //////////////////////////////////////////////////////////////////////////////// bool sh::HoistConstants(TCompiler &compiler, TIntermBlock &root, IdGen &idGen, size_t minRequiredSize) { return Rewriter(compiler, minRequiredSize).rewrite(root, idGen); }