blob: b9cf90894e6e8e3ab2c626b359416c36a96fc42f [file] [log] [blame]
//
// 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.
//
// Symbol.h: Symbols representing variables, functions, structures and interface blocks.
//
#ifndef COMPILER_TRANSLATOR_SYMBOL_H_
#define COMPILER_TRANSLATOR_SYMBOL_H_
#include "common/angleutils.h"
#include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/ImmutableString.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/SymbolUniqueId.h"
namespace sh
{
class TSymbolTable;
// Symbol base class. (Can build functions or variables out of these...)
class TSymbol : angle::NonCopyable
{
public:
POOL_ALLOCATOR_NEW_DELETE
TSymbol(TSymbolTable *symbolTable,
const ImmutableString &name,
SymbolType symbolType,
SymbolClass symbolClass,
TExtension extension = TExtension::UNDEFINED);
// Note that we can't have a virtual destructor in order to support constexpr symbols. Data is
// either statically allocated or pool allocated.
~TSymbol() = default;
// Calling name() for empty symbols (symbolType == SymbolType::Empty) generates a similar name
// as for internal variables.
ImmutableString name() const;
// Don't call getMangledName() for empty symbols (symbolType == SymbolType::Empty).
ImmutableString getMangledName() const;
bool isFunction() const { return mSymbolClass == SymbolClass::Function; }
bool isVariable() const { return mSymbolClass == SymbolClass::Variable; }
bool isStruct() const { return mSymbolClass == SymbolClass::Struct; }
bool isInterfaceBlock() const { return mSymbolClass == SymbolClass::InterfaceBlock; }
const TSymbolUniqueId &uniqueId() const { return mUniqueId; }
SymbolType symbolType() const { return mSymbolType; }
TExtension extension() const { return mExtension; }
protected:
constexpr TSymbol(const TSymbolUniqueId &id,
const ImmutableString &name,
SymbolType symbolType,
TExtension extension,
SymbolClass symbolClass)
: mName(name),
mUniqueId(id),
mSymbolType(symbolType),
mExtension(extension),
mSymbolClass(symbolClass)
{}
const ImmutableString mName;
private:
const TSymbolUniqueId mUniqueId;
const SymbolType mSymbolType;
const TExtension mExtension;
// We use this instead of having virtual functions for querying the class in order to support
// constexpr symbols.
const SymbolClass mSymbolClass;
};
// Variable.
// May store the value of a constant variable of any type (float, int, bool or struct).
class TVariable : public TSymbol
{
public:
TVariable(TSymbolTable *symbolTable,
const ImmutableString &name,
const TType *type,
SymbolType symbolType,
TExtension ext = TExtension::UNDEFINED);
const TType &getType() const { return *mType; }
const TConstantUnion *getConstPointer() const { return unionArray; }
void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; }
// Note: only to be used for built-in variables with autogenerated ids!
constexpr TVariable(const TSymbolUniqueId &id,
const ImmutableString &name,
SymbolType symbolType,
TExtension extension,
const TType *type)
: TSymbol(id, name, symbolType, extension, SymbolClass::Variable),
mType(type),
unionArray(nullptr)
{}
private:
const TType *mType;
const TConstantUnion *unionArray;
};
// Struct type.
class TStructure : public TSymbol, public TFieldListCollection
{
public:
TStructure(TSymbolTable *symbolTable,
const ImmutableString &name,
const TFieldList *fields,
SymbolType symbolType);
// The char arrays passed in must be pool allocated or static.
void createSamplerSymbols(const char *namePrefix,
const TString &apiNamePrefix,
TVector<const TVariable *> *outputSymbols,
TMap<const TVariable *, TString> *outputSymbolsToAPINames,
TSymbolTable *symbolTable) const;
void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; }
bool atGlobalScope() const { return mAtGlobalScope; }
private:
friend class TSymbolTable;
// For creating built-in structs.
TStructure(const TSymbolUniqueId &id,
const ImmutableString &name,
TExtension extension,
const TFieldList *fields);
// TODO(zmo): Find a way to get rid of the const_cast in function
// setName(). At the moment keep this function private so only
// friend class RegenerateStructNames may call it.
friend class RegenerateStructNames;
void setName(const ImmutableString &name);
bool mAtGlobalScope;
};
// Interface block. Note that this contains the block name, not the instance name. Interface block
// instances are stored as TVariable.
class TInterfaceBlock : public TSymbol, public TFieldListCollection
{
public:
TInterfaceBlock(TSymbolTable *symbolTable,
const ImmutableString &name,
const TFieldList *fields,
const TLayoutQualifier &layoutQualifier,
SymbolType symbolType,
TExtension extension = TExtension::UNDEFINED);
TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
int blockBinding() const { return mBinding; }
private:
friend class TSymbolTable;
// For creating built-in interface blocks.
TInterfaceBlock(const TSymbolUniqueId &id,
const ImmutableString &name,
TExtension extension,
const TFieldList *fields);
TLayoutBlockStorage mBlockStorage;
int mBinding;
// Note that we only record matrix packing on a per-field granularity.
};
// Parameter class used for parsing user-defined function parameters.
struct TParameter
{
// Destructively converts to TVariable.
// This method resets name and type to nullptrs to make sure
// their content cannot be modified after the call.
const TVariable *createVariable(TSymbolTable *symbolTable)
{
const ImmutableString constName(name);
const TType *constType = type;
name = nullptr;
type = nullptr;
return new TVariable(symbolTable, constName, constType,
constName.empty() ? SymbolType::Empty : SymbolType::UserDefined);
}
const char *name; // either pool allocated or static.
TType *type;
};
// The function sub-class of a symbol.
class TFunction : public TSymbol
{
public:
// User-defined function
TFunction(TSymbolTable *symbolTable,
const ImmutableString &name,
SymbolType symbolType,
const TType *retType,
bool knownToNotHaveSideEffects);
void addParameter(const TVariable *p);
void shareParameters(const TFunction &parametersSource);
ImmutableString getFunctionMangledName() const
{
ASSERT(symbolType() != SymbolType::BuiltIn);
if (mMangledName.empty())
{
mMangledName = buildMangledName();
}
return mMangledName;
}
const TType &getReturnType() const { return *returnType; }
TOperator getBuiltInOp() const { return mOp; }
void setDefined() { defined = true; }
bool isDefined() { return defined; }
void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; }
bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; }
size_t getParamCount() const { return mParamCount; }
const TVariable *getParam(size_t i) const { return mParameters[i]; }
bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; }
bool isMain() const;
bool isImageFunction() const;
bool isAtomicCounterFunction() const;
bool hasSamplerInStructOrArrayParams() const;
bool hasSamplerInStructOrArrayOfArrayParams() const;
// Note: Only to be used for static built-in functions!
constexpr TFunction(const TSymbolUniqueId &id,
const ImmutableString &name,
TExtension extension,
const TVariable *const *parameters,
size_t paramCount,
const TType *retType,
TOperator op,
bool knownToNotHaveSideEffects)
: TSymbol(id, name, SymbolType::BuiltIn, extension, SymbolClass::Function),
mParametersVector(nullptr),
mParameters(parameters),
mParamCount(paramCount),
returnType(retType),
mMangledName(nullptr),
mOp(op),
defined(false),
mHasPrototypeDeclaration(false),
mKnownToNotHaveSideEffects(knownToNotHaveSideEffects)
{}
private:
ImmutableString buildMangledName() const;
typedef TVector<const TVariable *> TParamVector;
TParamVector *mParametersVector;
const TVariable *const *mParameters;
size_t mParamCount;
const TType *const returnType;
mutable ImmutableString mMangledName;
const TOperator mOp; // Only set for built-ins
bool defined;
bool mHasPrototypeDeclaration;
bool mKnownToNotHaveSideEffects;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_SYMBOL_H_