// // 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. // #ifndef COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_SYMBOLENV_H_ #define COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_SYMBOLENV_H_ #include #include "compiler/translator/Compiler.h" #include "compiler/translator/TranslatorMetalDirect/Name.h" #include "compiler/translator/TranslatorMetalDirect/Reference.h" #include "compiler/translator/Types.h" namespace sh { enum class AddressSpace { Constant, Device, Thread, }; char const *toString(AddressSpace space); class VarField { public: VarField(const TVariable &var) : mVariable(&var) {} VarField(const TField &field) : mField(&field) {} ANGLE_INLINE const TVariable *variable() const { return mVariable; } ANGLE_INLINE const TField *field() const { return mField; } ANGLE_INLINE bool operator==(const VarField &other) const { return mVariable == other.mVariable && mField == other.mField; } private: const TVariable *mVariable = nullptr; const TField *mField = nullptr; }; } // namespace sh namespace std { template <> struct hash { size_t operator()(const sh::VarField &x) const { const sh::TVariable *var = x.variable(); if (var) { return std::hash()(var); } const sh::TField *field = x.field(); return std::hash()(field); } }; } // namespace std namespace sh { class TemplateArg { public: enum class Kind { Bool, Int, UInt, Type, }; union Value { Value(bool value) : b(value) {} Value(int value) : i(value) {} Value(unsigned value) : u(value) {} Value(const TType &value) : t(&value) {} bool b; int i; unsigned u; const TType *t; }; TemplateArg(bool value); TemplateArg(int value); TemplateArg(unsigned value); TemplateArg(const TType &value); bool operator==(const TemplateArg &other) const; bool operator<(const TemplateArg &other) const; Kind kind() const { return mKind; } Value value() const { return mValue; } public: Kind mKind; Value mValue; }; // An environment for creating and uniquely sharing TSymbol objects. class SymbolEnv { class TemplateName { Name baseName; std::vector templateArgs; public: bool operator==(const TemplateName &other) const; bool operator<(const TemplateName &other) const; bool empty() const; void clear(); Name fullName(std::string &buffer) const; void assign(const Name &name, size_t argCount, const TemplateArg *args); }; using TypeRef = CRef; using Sig = std::vector; // Param0, Param1, ... ParamN, Return using SigToFunc = std::map; using Overloads = std::map; using AngleStructs = std::map; using TextureStructs = std::map; public: SymbolEnv(TCompiler &compiler, TIntermBlock &root); TSymbolTable &symbolTable() { return mSymbolTable; } // There exist Angle rewrites that can lead to incoherent structs // // Example // struct A { ... } // struct B { A' a; } // A' has same name as A but is not identical. // becomes // struct A { ... } // struct B { A a; } // // This notably happens when A contains a sampler in the original GLSL code but is rewritten to // not have a sampler, yet the A' struct field still contains the sampler field. const TStructure &remap(const TStructure &s) const; // Like `TStructure &remap(const TStructure &s)` but additionally maps null to null. const TStructure *remap(const TStructure *s) const; const TFunction &getFunctionOverload(const Name &name, const TType &returnType, size_t paramCount, const TType **paramTypes, size_t templateArgCount = 0, const TemplateArg *templateArgs = nullptr); TIntermAggregate &callFunctionOverload(const Name &name, const TType &returnType, TIntermSequence &args, size_t templateArgCount = 0, const TemplateArg *templateArgs = nullptr); const TStructure &newStructure(const Name &name, TFieldList &fields); const TStructure &getTextureEnv(TBasicType samplerType); const TStructure &getSamplerStruct(); void markAsPointer(VarField x, AddressSpace space); void removePointer(VarField x); const AddressSpace *isPointer(VarField x) const; void markAsReference(VarField x, AddressSpace space); void removeAsReference(VarField x); const AddressSpace *isReference(VarField x) const; void markAsPacked(const TField &field); bool isPacked(const TField &field) const; void markAsUBO(VarField x); bool isUBO(VarField x) const; private: const TFunction &getFunctionOverloadImpl(); void markSpace(VarField x, AddressSpace space, std::unordered_map &map); void removeSpace(VarField x, std::unordered_map &map); const AddressSpace *isSpace(VarField x, const std::unordered_map &map) const; private: TSymbolTable &mSymbolTable; std::map mNameToStruct; Overloads mOverloads; Sig mReusableSigBuffer; TemplateName mReusableTemplateNameBuffer; std::string mReusableStringBuffer; AngleStructs mAngleStructs; std::unordered_map mTextureEnvs; const TStructure *mSampler = nullptr; std::unordered_map mPointers; std::unordered_map mReferences; std::unordered_set mPackedFields; std::unordered_set mUboFields; }; Name GetTextureTypeName(TBasicType samplerType); } // namespace sh #endif // COMPILER_TRANSLATOR_TRANSLATORMETALDIRECT_SYMBOLENV_H_