// // 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. // // Compile-time instances of many common TType values. These are looked up // (statically or dynamically) through the methods defined in the namespace. // #ifndef COMPILER_TRANSLATOR_STATIC_TYPE_H_ #define COMPILER_TRANSLATOR_STATIC_TYPE_H_ #include "compiler/translator/Types.h" namespace sh { namespace StaticType { namespace Helpers { // // Generation and static allocation of type mangled name values. // // Size of the constexpr-generated mangled name. // If this value is too small, the compiler will produce errors. static constexpr size_t kStaticMangledNameLength = TBasicMangledName::mangledNameSize + 1; // Type which holds the mangled names for constexpr-generated TTypes. // This simple struct is needed so that a char array can be returned by value. struct StaticMangledName { // If this array is too small, the compiler will produce errors. char name[kStaticMangledNameLength + 1] = {}; }; // Generates a mangled name for a TType given its parameters. constexpr StaticMangledName BuildStaticMangledName(TBasicType basicType, TPrecision precision, TQualifier qualifier, uint8_t primarySize, uint8_t secondarySize) { StaticMangledName name = {}; name.name[0] = TType::GetSizeMangledName(primarySize, secondarySize); TBasicMangledName typeName(basicType); char *mangledName = typeName.getName(); static_assert(TBasicMangledName::mangledNameSize == 2, "Mangled name size is not 2"); name.name[1] = mangledName[0]; name.name[2] = mangledName[1]; name.name[3] = '\0'; return name; } // Similar mangled name builder but for array types. Currently, only single-dimension arrays of // single-digit size are necessary and supported. static constexpr size_t kStaticArrayMangledNameLength = kStaticMangledNameLength + 2; struct StaticArrayMangledName { char name[kStaticArrayMangledNameLength + 1] = {}; }; constexpr StaticArrayMangledName BuildStaticArrayMangledName(TBasicType basicType, TPrecision precision, TQualifier qualifier, uint8_t primarySize, uint8_t secondarySize, const unsigned int *arraySizes, size_t numArraySizes) { StaticMangledName nonArrayName = BuildStaticMangledName(basicType, precision, qualifier, primarySize, secondarySize); StaticArrayMangledName arrayName = {}; static_assert(kStaticMangledNameLength == 3, "Static mangled name size is not 3"); arrayName.name[0] = nonArrayName.name[0]; arrayName.name[1] = nonArrayName.name[1]; arrayName.name[2] = nonArrayName.name[2]; arrayName.name[3] = 'x'; arrayName.name[4] = static_cast('0' + arraySizes[0]); arrayName.name[5] = '\0'; return arrayName; } // This "variable" contains the mangled names for every constexpr-generated TType. // If kMangledNameInstance is used anywhere (specifally // in instance, below), this is where the appropriate type will be stored. template static constexpr StaticMangledName kMangledNameInstance = BuildStaticMangledName(basicType, precision, qualifier, primarySize, secondarySize); // Same as kMangledNameInstance, but for array types. template static constexpr StaticArrayMangledName kMangledNameArrayInstance = BuildStaticArrayMangledName(basicType, precision, qualifier, primarySize, secondarySize, arraySizes, numArraySizes); // // Generation and static allocation of TType values. // // This "variable" contains every constexpr-generated TType. // If instance is used anywhere (specifally // in Get, below), this is where the appropriate type will be stored. // // TODO(crbug.com/981610): This is constexpr but doesn't follow the kConstant naming convention // because TType has a mutable member that prevents it from being in .data.rel.ro and makes the // Android Binary Size builder complain when ANGLE is rolled in Chromium. template static constexpr TType instance = TType(basicType, precision, qualifier, primarySize, secondarySize, TSpan(), kMangledNameInstance.name); // Same as instance, but for array types. template static constexpr TType arrayInstance = TType(basicType, precision, qualifier, primarySize, secondarySize, TSpan(arraySizes, numArraySizes), kMangledNameArrayInstance.name); } // namespace Helpers // // Fully-qualified type lookup. // template constexpr const TType *Get() { static_assert(1 <= primarySize && primarySize <= 4, "primarySize out of bounds"); static_assert(1 <= secondarySize && secondarySize <= 4, "secondarySize out of bounds"); return &Helpers::instance; } template constexpr const TType *GetArray() { static_assert(1 <= primarySize && primarySize <= 4, "primarySize out of bounds"); static_assert(1 <= secondarySize && secondarySize <= 4, "secondarySize out of bounds"); static_assert(numArraySizes == 1, "only single-dimension static types are supported"); static_assert(arraySizes[0] < 10, "only single-digit dimensions are supported in static types"); return &Helpers::arrayInstance; } // // Overloads // template constexpr const TType *GetBasic() { return Get(); } template constexpr const TType *GetTemporary() { return Get(); } template const TType *GetQualified() { return Get(); } // Dynamic lookup methods (convert runtime values to template args) namespace Helpers { // Helper which takes secondarySize statically but primarySize dynamically. template constexpr const TType *GetForVecMatHelper(uint8_t primarySize) { static_assert(basicType == EbtFloat || basicType == EbtInt || basicType == EbtUInt || basicType == EbtBool, "unsupported basicType"); switch (primarySize) { case 1: return Get(); case 2: return Get(); case 3: return Get(); case 4: return Get(); default: UNREACHABLE(); return GetBasic(); } } } // namespace Helpers template constexpr const TType *GetForVecMat(uint8_t primarySize, uint8_t secondarySize = 1) { static_assert(basicType == EbtFloat || basicType == EbtInt || basicType == EbtUInt || basicType == EbtBool, "unsupported basicType"); switch (secondarySize) { case 1: return Helpers::GetForVecMatHelper(primarySize); case 2: return Helpers::GetForVecMatHelper(primarySize); case 3: return Helpers::GetForVecMatHelper(primarySize); case 4: return Helpers::GetForVecMatHelper(primarySize); default: UNREACHABLE(); return GetBasic(); } } template constexpr const TType *GetForVec(TQualifier qualifier, uint8_t size) { switch (qualifier) { case EvqGlobal: return Helpers::GetForVecMatHelper(size); case EvqParamOut: return Helpers::GetForVecMatHelper(size); default: UNREACHABLE(); return GetBasic(); } } } // namespace StaticType } // namespace sh #endif // COMPILER_TRANSLATOR_STATIC_TYPE_H_