| // |
| // 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/TranslatorMetalDirect/Name.h" |
| #include "common/debug.h" |
| #include "compiler/translator/tree_util/IntermTraverse.h" |
| |
| using namespace sh; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| template <typename T> |
| static ImmutableString GetName(T const &object) |
| { |
| if (object.symbolType() == SymbolType::Empty) |
| { |
| return kEmptyImmutableString; |
| } |
| return object.name(); |
| } |
| |
| Name::Name(const TField &field) : Name(GetName(field), field.symbolType()) {} |
| |
| Name::Name(const TSymbol &symbol) : Name(GetName(symbol), symbol.symbolType()) {} |
| |
| bool Name::operator==(const Name &other) const |
| { |
| return mRawName == other.mRawName && mSymbolType == other.mSymbolType; |
| } |
| |
| bool Name::operator!=(const Name &other) const |
| { |
| return !(*this == other); |
| } |
| |
| bool Name::operator<(const Name &other) const |
| { |
| if (mRawName < other.mRawName) |
| { |
| return true; |
| } |
| if (other.mRawName < mRawName) |
| { |
| return false; |
| } |
| return mSymbolType < other.mSymbolType; |
| } |
| |
| bool Name::empty() const |
| { |
| return mSymbolType == SymbolType::Empty; |
| } |
| |
| bool Name::beginsWith(const Name &prefix) const |
| { |
| if (mSymbolType != prefix.mSymbolType) |
| { |
| return false; |
| } |
| return mRawName.beginsWith(prefix.mRawName); |
| } |
| |
| void Name::emit(TInfoSinkBase &out) const |
| { |
| switch (mSymbolType) |
| { |
| case SymbolType::BuiltIn: |
| case SymbolType::UserDefined: |
| ASSERT(!mRawName.empty()); |
| out << mRawName; |
| break; |
| |
| case SymbolType::AngleInternal: |
| ASSERT(!mRawName.empty()); |
| if (mRawName.beginsWith(kAngleInternalPrefix)) |
| { |
| out << mRawName; |
| } |
| else if (mRawName[0] != '_') |
| { |
| out << kAngleInternalPrefix << '_' << mRawName; |
| } |
| else |
| { |
| out << kAngleInternalPrefix << mRawName; |
| } |
| break; |
| |
| case SymbolType::Empty: |
| UNREACHABLE(); |
| break; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| namespace |
| { |
| |
| // NOTE: This matches more things than FindSymbolNode. |
| class ExpressionContainsNameVisitor : public TIntermTraverser |
| { |
| Name mName; |
| bool mFoundName = false; |
| |
| public: |
| ExpressionContainsNameVisitor(const Name &name) |
| : TIntermTraverser(true, false, false), mName(name) |
| {} |
| |
| bool foundName() const { return mFoundName; } |
| |
| void visitSymbol(TIntermSymbol *node) override |
| { |
| if (Name(node->variable()) == mName) |
| { |
| mFoundName = true; |
| } |
| } |
| |
| bool visitSwizzle(Visit, TIntermSwizzle *) override { return !mFoundName; } |
| |
| bool visitBinary(Visit visit, TIntermBinary *node) override { return !mFoundName; } |
| |
| bool visitUnary(Visit visit, TIntermUnary *node) override { return !mFoundName; } |
| |
| bool visitTernary(Visit visit, TIntermTernary *node) override { return !mFoundName; } |
| |
| bool visitAggregate(Visit visit, TIntermAggregate *node) override |
| { |
| if (node->isConstructor()) |
| { |
| const TType &type = node->getType(); |
| const TStructure *structure = type.getStruct(); |
| if (structure && Name(*structure) == mName) |
| { |
| mFoundName = true; |
| } |
| } |
| else |
| { |
| const TFunction *func = node->getFunction(); |
| if (func && Name(*func) == mName) |
| { |
| mFoundName = true; |
| } |
| } |
| return !mFoundName; |
| } |
| |
| bool visitIfElse(Visit visit, TIntermIfElse *node) override |
| { |
| UNREACHABLE(); |
| return false; |
| } |
| |
| bool visitSwitch(Visit, TIntermSwitch *) override |
| { |
| UNREACHABLE(); |
| return false; |
| } |
| bool visitCase(Visit, TIntermCase *) override |
| { |
| UNREACHABLE(); |
| return false; |
| } |
| |
| void visitFunctionPrototype(TIntermFunctionPrototype *) override { UNREACHABLE(); } |
| |
| bool visitFunctionDefinition(Visit, TIntermFunctionDefinition *) override |
| { |
| UNREACHABLE(); |
| return false; |
| } |
| |
| bool visitBlock(Visit, TIntermBlock *) override |
| { |
| UNREACHABLE(); |
| return false; |
| } |
| |
| bool visitGlobalQualifierDeclaration(Visit, TIntermGlobalQualifierDeclaration *) override |
| { |
| UNREACHABLE(); |
| return false; |
| } |
| |
| bool visitDeclaration(Visit, TIntermDeclaration *) override |
| { |
| UNREACHABLE(); |
| return false; |
| } |
| |
| bool visitLoop(Visit, TIntermLoop *) override |
| { |
| UNREACHABLE(); |
| return false; |
| } |
| |
| bool visitBranch(Visit, TIntermBranch *) override |
| { |
| UNREACHABLE(); |
| return false; |
| } |
| |
| void visitPreprocessorDirective(TIntermPreprocessorDirective *) override { UNREACHABLE(); } |
| }; |
| |
| } // anonymous namespace |
| |
| bool sh::ExpressionContainsName(const Name &name, TIntermTyped &node) |
| { |
| ExpressionContainsNameVisitor visitor(name); |
| node.traverse(&visitor); |
| return visitor.foundName(); |
| } |