blob: 6dc3354dcd7cf0f54fe839e29faa3554ed570f79 [file] [log] [blame]
//
// 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_MSL_SYMBOLENV_H_
#define COMPILER_TRANSLATOR_MSL_SYMBOLENV_H_
#include <unordered_set>
#include "compiler/translator/Compiler.h"
#include "compiler/translator/Name.h"
#include "compiler/translator/Types.h"
#include "compiler/translator/msl/Reference.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<sh::VarField>
{
size_t operator()(const sh::VarField &x) const
{
const sh::TVariable *var = x.variable();
if (var)
{
return std::hash<const sh::TVariable *>()(var);
}
const sh::TField *field = x.field();
return std::hash<const sh::TField *>()(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<TemplateArg> 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<TType>;
using Sig = std::vector<TypeRef>; // Param0, Param1, ... ParamN, Return
using SigToFunc = std::map<Sig, TFunction *>;
using Overloads = std::map<TemplateName, SigToFunc>;
using AngleStructs = std::map<ImmutableString, TStructure *>;
using TextureStructs = std::map<TBasicType, TStructure *>;
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<VarField, AddressSpace> &map);
void removeSpace(VarField x, std::unordered_map<VarField, AddressSpace> &map);
const AddressSpace *isSpace(VarField x,
const std::unordered_map<VarField, AddressSpace> &map) const;
private:
TSymbolTable &mSymbolTable;
std::map<Name, const TStructure *> mNameToStruct;
Overloads mOverloads;
Sig mReusableSigBuffer;
TemplateName mReusableTemplateNameBuffer;
std::string mReusableStringBuffer;
AngleStructs mAngleStructs;
std::unordered_map<TBasicType, const TStructure *> mTextureEnvs;
const TStructure *mSampler = nullptr;
std::unordered_map<VarField, AddressSpace> mPointers;
std::unordered_map<VarField, AddressSpace> mReferences;
std::unordered_set<const TField *> mPackedFields;
std::unordered_set<VarField> mUboFields;
};
Name GetTextureTypeName(TBasicType samplerType);
} // namespace sh
#endif // COMPILER_TRANSLATOR_MSL_SYMBOLENV_H_