Commit 5fec7ab2 by Olli Etuaho Committed by Commit Bot

Identify functions by unique id in BuiltInFunctionEmulator

Now that unique ids of all builtins are compile-time constants, we can use them to look up functions in BuiltInFunctionEmulator. This is simpler than using a custom struct with the name and parameters for identifying functions. This requires that we store a reference to a TFunction in those TIntermUnary nodes that were created based on a function. This decreases shader_translator binary size by about 6 KB on Windows. BUG=angleproject:2267 BUG=chromium:823856 TEST=angle_unittests Change-Id: Idd5a00c772c6f26dd36fdbbfbe161d22ab27c2fe Reviewed-on: https://chromium-review.googlesource.com/995372Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent f3614370
......@@ -156,6 +156,15 @@ generators = {
],
'script': 'src/libANGLE/renderer/vulkan/gen_vk_mandatory_format_support_table.py',
},
'Emulated HLSL functions': {
'inputs': [
'src/compiler/translator/emulated_builtin_function_data_hlsl.json'
],
'outputs': [
'src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp'
],
'script': 'src/compiler/translator/gen_emulated_builtin_function_tables.py'
},
'ESSL static builtins': {
'inputs': [
'src/compiler/translator/builtin_function_declarations.txt',
......
......@@ -68,7 +68,6 @@
'compiler/translator/Operator.h',
'compiler/translator/OutputTree.cpp',
'compiler/translator/OutputTree.h',
'compiler/translator/ParamType.h',
'compiler/translator/ParseContext.cpp',
'compiler/translator/ParseContext.h',
'compiler/translator/ParseContext_autogen.h',
......
......@@ -8,82 +8,15 @@
#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/ParamType.h"
namespace sh
{
struct MiniFunctionId
{
constexpr MiniFunctionId(TOperator op = EOpNull,
ParamType paramType1 = ParamType::Void,
ParamType paramType2 = ParamType::Void,
ParamType paramType3 = ParamType::Void,
ParamType paramType4 = ParamType::Void)
: op(op),
paramType1(paramType1),
paramType2(paramType2),
paramType3(paramType3),
paramType4(paramType4)
{
}
TOperator op;
ParamType paramType1;
ParamType paramType2;
ParamType paramType3;
ParamType paramType4;
};
class FunctionId final
{
public:
FunctionId();
FunctionId(TOperator op, const TType *param);
FunctionId(TOperator op, const TType *param1, const TType *param2);
FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3);
FunctionId(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4);
class TIntermNode;
class TFunction;
class TSymbolUniqueId;
FunctionId(const FunctionId &) = default;
FunctionId &operator=(const FunctionId &) = default;
bool operator==(const FunctionId &other) const;
bool operator<(const FunctionId &other) const;
FunctionId getCopy() const;
private:
friend bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId);
TOperator mOp;
// The memory that these TType objects use is freed by PoolAllocator. The
// BuiltInFunctionEmulator's lifetime can extend until after the memory pool is freed, but
// that's not an issue since this class never destructs these objects.
const TType *mParam1;
const TType *mParam2;
const TType *mParam3;
const TType *mParam4;
};
inline bool operator==(ParamType paramType, const TType *type)
{
return SameParamType(paramType, type->getBasicType(), type->getNominalSize(),
type->getSecondarySize());
}
inline bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId)
{
return miniId.op == functionId.mOp && miniId.paramType1 == functionId.mParam1 &&
miniId.paramType2 == functionId.mParam2 && miniId.paramType3 == functionId.mParam3 &&
miniId.paramType4 == functionId.mParam4;
}
using BuiltinQueryFunc = const char *(const FunctionId &);
using BuiltinQueryFunc = const char *(int);
//
// This class decides which built-in functions need to be replaced with the emulated ones. It can be
......@@ -108,37 +41,12 @@ class BuiltInFunctionEmulator
void outputEmulatedFunctions(TInfoSinkBase &out) const;
// Add functions that need to be emulated.
FunctionId addEmulatedFunction(TOperator op,
const TType *param,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
TOperator op,
const TType *param1,
const TType *param2,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4,
const char *emulatedFunctionDefinition);
void addEmulatedFunction(const TSymbolUniqueId &uniqueId,
const char *emulatedFunctionDefinition);
void addEmulatedFunctionWithDependency(const TSymbolUniqueId &dependency,
const TSymbolUniqueId &uniqueId,
const char *emulatedFunctionDefinition);
void addFunctionMap(BuiltinQueryFunc queryFunc);
......@@ -148,31 +56,20 @@ class BuiltInFunctionEmulator
// Records that a function is called by the shader and might need to be emulated. If the
// function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function
// call needs to be replaced with an emulated one.
bool setFunctionCalled(TOperator op, const TType &param);
bool setFunctionCalled(TOperator op, const TType &param1, const TType &param2);
bool setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2,
const TType &param3);
bool setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2,
const TType &param3,
const TType &param4);
bool setFunctionCalled(const FunctionId &functionId);
bool setFunctionCalled(const TFunction *function);
bool setFunctionCalled(int uniqueId);
const char *findEmulatedFunction(const FunctionId &functionId) const;
const char *findEmulatedFunction(int uniqueId) const;
// Map from function id to emulated function definition
std::map<FunctionId, std::string> mEmulatedFunctions;
// Map from function unique id to emulated function definition
std::map<int, std::string> mEmulatedFunctions;
// Map from dependent functions to their dependencies. This structure allows each function to
// have at most one dependency.
std::map<FunctionId, FunctionId> mFunctionDependencies;
std::map<int, int> mFunctionDependencies;
// Called function ids
std::vector<FunctionId> mFunctions;
std::vector<int> mFunctions;
// Constexpr function tables.
std::vector<BuiltinQueryFunc *> mQueryFunctions;
......
......@@ -7,9 +7,8 @@
#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
#include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/VersionGLSL.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh
{
......@@ -19,8 +18,7 @@ void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *e
{
if (shaderType == GL_VERTEX_SHADER)
{
const TType *int1 = StaticType::GetBasic<EbtInt>();
emu->addEmulatedFunction(EOpAbs, int1, "int abs_emu(int x) { return x * sign(x); }");
emu->addEmulatedFunction(BuiltInId::abs_Int1, "int abs_emu(int x) { return x * sign(x); }");
}
}
......@@ -31,17 +29,12 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
if (targetGLSLVersion < GLSL_VERSION_130)
return;
const TType *float1 = StaticType::GetBasic<EbtFloat>();
const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
const TType *float3 = StaticType::GetBasic<EbtFloat, 3>();
const TType *float4 = StaticType::GetBasic<EbtFloat, 4>();
// !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false.
emu->addEmulatedFunction(
EOpIsnan, float1,
BuiltInId::isnan_Float1,
"bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
emu->addEmulatedFunction(
EOpIsnan, float2,
BuiltInId::isnan_Float2,
"bvec2 isnan_emu(vec2 x)\n"
"{\n"
" bvec2 isnan;\n"
......@@ -52,7 +45,7 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
" return isnan;\n"
"}\n");
emu->addEmulatedFunction(
EOpIsnan, float3,
BuiltInId::isnan_Float3,
"bvec3 isnan_emu(vec3 x)\n"
"{\n"
" bvec3 isnan;\n"
......@@ -63,7 +56,7 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
" return isnan;\n"
"}\n");
emu->addEmulatedFunction(
EOpIsnan, float4,
BuiltInId::isnan_Float4,
"bvec4 isnan_emu(vec4 x)\n"
"{\n"
" bvec4 isnan;\n"
......@@ -77,27 +70,21 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu)
{
const TType *float1 = StaticType::GetBasic<EbtFloat>();
auto floatFuncId = emu->addEmulatedFunction(
EOpAtan, float1, float1,
"emu_precision float atan_emu(emu_precision float y, emu_precision "
"float x)\n"
"{\n"
" if (x > 0.0) return atan(y / x);\n"
" else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
" else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
" else return 1.57079632 * sign(y);\n"
"}\n");
static const std::array<const TType *, 5> floatVecs = {
nullptr,
nullptr,
StaticType::GetBasic<EbtFloat, 2>(),
StaticType::GetBasic<EbtFloat, 3>(),
StaticType::GetBasic<EbtFloat, 4>(),
emu->addEmulatedFunction(BuiltInId::atan_Float1_Float1,
"emu_precision float atan_emu(emu_precision float y, emu_precision "
"float x)\n"
"{\n"
" if (x > 0.0) return atan(y / x);\n"
" else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
" else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
" else return 1.57079632 * sign(y);\n"
"}\n");
static const std::array<TSymbolUniqueId, 4> ids = {
BuiltInId::atan_Float1_Float1, BuiltInId::atan_Float2_Float2, BuiltInId::atan_Float3_Float3,
BuiltInId::atan_Float4_Float4,
};
for (int dim = 2; dim <= 4; ++dim)
{
const TType *floatVec = floatVecs[dim];
std::stringstream ss;
ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim
<< " y, emu_precision vec" << dim << " x)\n"
......@@ -114,7 +101,7 @@ void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *
}
ss << ");\n"
"}\n";
emu->addEmulatedFunctionWithDependency(floatFuncId, EOpAtan, floatVec, floatVec,
emu->addEmulatedFunctionWithDependency(BuiltInId::atan_Float1_Float1, ids[dim - 1],
ss.str().c_str());
}
}
......@@ -127,11 +114,8 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
// Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10)
if (targetGLSLVersion < GLSL_VERSION_410)
{
const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
const TType *uint1 = StaticType::GetBasic<EbtUInt>();
// clang-format off
emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
emu->addEmulatedFunction(BuiltInId::packUnorm2x16_Float2,
"uint packUnorm2x16_emu(vec2 v)\n"
"{\n"
" int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n"
......@@ -139,7 +123,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" return uint((y << 16) | (x & 0xFFFF));\n"
"}\n");
emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
emu->addEmulatedFunction(BuiltInId::unpackUnorm2x16_UInt1,
"vec2 unpackUnorm2x16_emu(uint u)\n"
"{\n"
" float x = float(u & 0xFFFFu) / 65535.0;\n"
......@@ -153,11 +137,8 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
// by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30).
if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420)
{
const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
const TType *uint1 = StaticType::GetBasic<EbtUInt>();
// clang-format off
emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
emu->addEmulatedFunction(BuiltInId::packSnorm2x16_Float2,
"uint packSnorm2x16_emu(vec2 v)\n"
"{\n"
" #if defined(GL_ARB_shading_language_packing)\n"
......@@ -168,7 +149,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" return uint((y << 16) | (x & 0xFFFF));\n"
" #endif\n"
"}\n");
emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
emu->addEmulatedFunction(BuiltInId::unpackSnorm2x16_UInt1,
"#if !defined(GL_ARB_shading_language_packing)\n"
" float fromSnorm(uint x)\n"
" {\n"
......@@ -189,7 +170,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
"}\n");
// Functions uint f32tof16(float val) and float f16tof32(uint val) are
// based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL".
emu->addEmulatedFunction(EOpPackHalf2x16, float2,
emu->addEmulatedFunction(BuiltInId::packHalf2x16_Float2,
"#if !defined(GL_ARB_shading_language_packing)\n"
" uint f32tof16(float val)\n"
" {\n"
......@@ -236,7 +217,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" return (y << 16) | x;\n"
" #endif\n"
"}\n");
emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
emu->addEmulatedFunction(BuiltInId::unpackHalf2x16_UInt1,
"#if !defined(GL_ARB_shading_language_packing)\n"
" float f16tof32(uint val)\n"
" {\n"
......
......@@ -4,17 +4,17 @@
// found in the LICENSE file.
//
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/VersionGLSL.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh
{
// Defined in emulated_builtin_functions_hlsl_autogen.cpp.
const char *FindHLSLFunction(const FunctionId &functionID);
const char *FindHLSLFunction(int uniqueId);
void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
int targetGLSLVersion)
......@@ -22,12 +22,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
if (targetGLSLVersion < GLSL_VERSION_130)
return;
TType *float1 = new TType(EbtFloat);
TType *float2 = new TType(EbtFloat, 2);
TType *float3 = new TType(EbtFloat, 3);
TType *float4 = new TType(EbtFloat, 4);
emu->addEmulatedFunction(EOpIsnan, float1,
emu->addEmulatedFunction(BuiltInId::isnan_Float1,
"bool isnan_emu(float x)\n"
"{\n"
" return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
......@@ -35,7 +30,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"\n");
emu->addEmulatedFunction(
EOpIsnan, float2,
BuiltInId::isnan_Float2,
"bool2 isnan_emu(float2 x)\n"
"{\n"
" bool2 isnan;\n"
......@@ -47,7 +42,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"}\n");
emu->addEmulatedFunction(
EOpIsnan, float3,
BuiltInId::isnan_Float3,
"bool3 isnan_emu(float3 x)\n"
"{\n"
" bool3 isnan;\n"
......@@ -59,7 +54,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"}\n");
emu->addEmulatedFunction(
EOpIsnan, float4,
BuiltInId::isnan_Float4,
"bool4 isnan_emu(float4 x)\n"
"{\n"
" bool4 isnan;\n"
......@@ -73,43 +68,35 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
{
TType *int1 = new TType(EbtInt);
TType *int2 = new TType(EbtInt, 2);
TType *int3 = new TType(EbtInt, 3);
TType *int4 = new TType(EbtInt, 4);
TType *uint1 = new TType(EbtUInt);
TType *uint2 = new TType(EbtUInt, 2);
TType *uint3 = new TType(EbtUInt, 3);
TType *uint4 = new TType(EbtUInt, 4);
emu->addFunctionMap(FindHLSLFunction);
// (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32
// Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because:
// a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000
FunctionId umulExtendedUint1 = emu->addEmulatedFunction(
EOpUmulExtended, uint1, uint1, uint1, uint1,
"void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
"{\n"
" lsb = x * y;\n"
" uint a = (x & 0xffffu);\n"
" uint b = (x >> 16);\n"
" uint c = (y & 0xffffu);\n"
" uint d = (y >> 16);\n"
" uint ad = a * d + ((a * c) >> 16);\n"
" uint bc = b * c;\n"
" uint carry = uint(ad > (0xffffffffu - bc));\n"
" msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
"}\n");
emu->addEmulatedFunction(BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
"void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
"{\n"
" lsb = x * y;\n"
" uint a = (x & 0xffffu);\n"
" uint b = (x >> 16);\n"
" uint c = (y & 0xffffu);\n"
" uint d = (y >> 16);\n"
" uint ad = a * d + ((a * c) >> 16);\n"
" uint bc = b * c;\n"
" uint carry = uint(ad > (0xffffffffu - bc));\n"
" msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
"}\n");
emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpUmulExtended, uint2, uint2, uint2, uint2,
BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
BuiltInId::umulExtended_UInt2_UInt2_UInt2_UInt2,
"void umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n"
"{\n"
" umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
"}\n");
emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpUmulExtended, uint3, uint3, uint3, uint3,
BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
BuiltInId::umulExtended_UInt3_UInt3_UInt3_UInt3,
"void umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n"
"{\n"
" umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
......@@ -117,7 +104,8 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
"}\n");
emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpUmulExtended, uint4, uint4, uint4, uint4,
BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
BuiltInId::umulExtended_UInt4_UInt4_UInt4_UInt4,
"void umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n"
"{\n"
" umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
......@@ -130,8 +118,9 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
// result needs to be negative.
// TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is
// -2^31. abs(-2^31) is undefined.
FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1,
emu->addEmulatedFunctionWithDependency(
BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
BuiltInId::imulExtended_Int1_Int1_Int1_Int1,
"void imulExtended_emu(int x, int y, out int msb, out int lsb)\n"
"{\n"
" uint unsignedMsb;\n"
......@@ -156,14 +145,14 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" }\n"
"}\n");
emu->addEmulatedFunctionWithDependency(
imulExtendedInt1, EOpImulExtended, int2, int2, int2, int2,
BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int2_Int2_Int2_Int2,
"void imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n"
"{\n"
" imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
"}\n");
emu->addEmulatedFunctionWithDependency(
imulExtendedInt1, EOpImulExtended, int3, int3, int3, int3,
BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int3_Int3_Int3_Int3,
"void imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n"
"{\n"
" imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
......@@ -171,7 +160,7 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
"}\n");
emu->addEmulatedFunctionWithDependency(
imulExtendedInt1, EOpImulExtended, int4, int4, int4, int4,
BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int4_Int4_Int4_Int4,
"void imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n"
"{\n"
" imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
......
......@@ -588,7 +588,7 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
{
RemovePow(root);
RemovePow(root, &symbolTable);
}
if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
......
......@@ -809,7 +809,9 @@ TIntermBinary::TIntermBinary(const TIntermBinary &node)
}
TIntermUnary::TIntermUnary(const TIntermUnary &node)
: TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction)
: TIntermOperator(node),
mUseEmulatedFunction(node.mUseEmulatedFunction),
mFunction(node.mFunction)
{
TIntermTyped *operandCopy = node.mOperand->deepCopy();
ASSERT(operandCopy != nullptr);
......@@ -1049,8 +1051,8 @@ TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzl
promote();
}
TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand)
: TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false)
TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function)
: TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false), mFunction(function)
{
promote();
}
......
......@@ -505,7 +505,7 @@ class TIntermBinary : public TIntermOperator
class TIntermUnary : public TIntermOperator
{
public:
TIntermUnary(TOperator op, TIntermTyped *operand);
TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function);
TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
......@@ -518,6 +518,8 @@ class TIntermUnary : public TIntermOperator
TIntermTyped *getOperand() { return mOperand; }
TIntermTyped *fold(TDiagnostics *diagnostics) override;
const TFunction *getFunction() const { return mFunction; }
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
......@@ -528,6 +530,8 @@ class TIntermUnary : public TIntermOperator
// to work around driver bugs.
bool mUseEmulatedFunction;
const TFunction *const mFunction;
private:
void promote();
......
//
// 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.
//
// ParamType:
// Helper type for built-in function emulator tables. Defines types for parameters.
#ifndef COMPILER_TRANSLATOR_PARAMTYPE_H_
#define COMPILER_TRANSLATOR_PARAMTYPE_H_
#include "common/angleutils.h"
#include "compiler/translator/BaseTypes.h"
namespace sh
{
enum class ParamType : uint8_t
{
Void,
Bool1,
Bool2,
Bool3,
Bool4,
Float1,
Float2,
Float3,
Float4,
Int1,
Int2,
Int3,
Int4,
Mat2,
Mat3,
Mat4,
Uint1,
Uint2,
Uint3,
Uint4,
Last,
};
struct ParamTypeInfo
{
ParamType self;
TBasicType basicType;
int primarySize;
int secondarySize;
};
constexpr ParamTypeInfo g_ParamTypeInfo[] = {
{ParamType::Void, EbtVoid, 1, 1}, {ParamType::Bool1, EbtBool, 1, 1},
{ParamType::Bool2, EbtBool, 2, 1}, {ParamType::Bool3, EbtBool, 3, 1},
{ParamType::Bool4, EbtBool, 4, 1}, {ParamType::Float1, EbtFloat, 1, 1},
{ParamType::Float2, EbtFloat, 2, 1}, {ParamType::Float3, EbtFloat, 3, 1},
{ParamType::Float4, EbtFloat, 4, 1}, {ParamType::Int1, EbtInt, 1, 1},
{ParamType::Int2, EbtInt, 2, 1}, {ParamType::Int3, EbtInt, 3, 1},
{ParamType::Int4, EbtInt, 4, 1}, {ParamType::Mat2, EbtFloat, 2, 2},
{ParamType::Mat3, EbtFloat, 3, 3}, {ParamType::Mat4, EbtFloat, 4, 4},
{ParamType::Uint1, EbtUInt, 1, 1}, {ParamType::Uint2, EbtUInt, 2, 1},
{ParamType::Uint3, EbtUInt, 3, 1}, {ParamType::Uint4, EbtUInt, 4, 1},
};
constexpr size_t ParamTypeIndex(ParamType paramType)
{
return static_cast<size_t>(paramType);
}
constexpr size_t NumParamTypes()
{
return ParamTypeIndex(ParamType::Last);
}
static_assert(ArraySize(g_ParamTypeInfo) == NumParamTypes(), "Invalid array size");
constexpr TBasicType GetBasicType(ParamType paramType)
{
return g_ParamTypeInfo[ParamTypeIndex(paramType)].basicType;
}
constexpr int GetPrimarySize(ParamType paramType)
{
return g_ParamTypeInfo[ParamTypeIndex(paramType)].primarySize;
}
constexpr int GetSecondarySize(ParamType paramType)
{
return g_ParamTypeInfo[ParamTypeIndex(paramType)].secondarySize;
}
constexpr bool SameParamType(ParamType paramType,
TBasicType basicType,
int primarySize,
int secondarySize)
{
return GetBasicType(paramType) == basicType && primarySize == GetPrimarySize(paramType) &&
secondarySize == GetSecondarySize(paramType);
}
} // namespace sh
#endif // COMPILER_TRANSLATOR_PARAMTYPE_H_
......@@ -4859,7 +4859,8 @@ TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
TIntermTyped *TParseContext::createUnaryMath(TOperator op,
TIntermTyped *child,
const TSourceLoc &loc)
const TSourceLoc &loc,
const TFunction *func)
{
ASSERT(child != nullptr);
......@@ -4907,7 +4908,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
}
markStaticReadIfSymbol(child);
TIntermUnary *node = new TIntermUnary(op, child);
TIntermUnary *node = new TIntermUnary(op, child, func);
node->setLine(loc);
return node->fold(mDiagnostics);
......@@ -4916,7 +4917,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
{
ASSERT(op != EOpNull);
TIntermTyped *node = createUnaryMath(op, child, loc);
TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
if (node == nullptr)
{
return child;
......@@ -5779,7 +5780,7 @@ TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc
}
else
{
TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode);
TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode, nullptr);
node->setLine(loc);
return node->fold(mDiagnostics);
}
......@@ -5837,7 +5838,8 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCa
{
// Treat it like a built-in unary operator.
TIntermNode *unaryParamNode = fnCall->arguments().front();
TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
TIntermTyped *callNode =
createUnaryMath(op, unaryParamNode->getAsTyped(), loc, fnCandidate);
ASSERT(callNode != nullptr);
return callNode;
}
......
......@@ -549,7 +549,10 @@ class TParseContext : angle::NonCopyable
TIntermTyped *left,
TIntermTyped *right,
const TSourceLoc &loc);
TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
TIntermTyped *createUnaryMath(TOperator op,
TIntermTyped *child,
const TSourceLoc &loc,
const TFunction *func);
TIntermTyped *addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc);
TIntermTyped *addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -22,11 +22,6 @@ TSymbolUniqueId::TSymbolUniqueId(const TSymbol &symbol) : mId(symbol.uniqueId().
TSymbolUniqueId &TSymbolUniqueId::operator=(const TSymbolUniqueId &) = default;
int TSymbolUniqueId::get() const
{
return mId;
}
bool TSymbolUniqueId::operator==(const TSymbolUniqueId &other) const
{
return mId == other.mId;
......
......@@ -25,7 +25,7 @@ class TSymbolUniqueId
TSymbolUniqueId &operator=(const TSymbolUniqueId &);
bool operator==(const TSymbolUniqueId &) const;
int get() const;
constexpr int get() const { return mId; }
private:
friend class TSymbolTable;
......
cc849405cb2fd922f9a269ab6594cb9b
\ No newline at end of file
e7cb1a4f677413aec61815b10019f608
\ No newline at end of file
......@@ -68,7 +68,7 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch)
"""
# The header file has a "get" function for each variable. They are used in traversers.
# Note that we don't currently include get_function_declarations, as they are unused.
# It also declares id values of built-ins with human readable names, so they can be used to identify built-ins.
template_builtin_header = """// GENERATED FILE - DO NOT EDIT.
// Generated by {script_name} using data from {variable_data_source_name} and
// {function_data_source_name}.
......@@ -83,11 +83,21 @@ template_builtin_header = """// GENERATED FILE - DO NOT EDIT.
#ifndef COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_
#define COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_
#include "compiler/translator/SymbolUniqueId.h"
namespace sh
{{
class TVariable;
class BuiltInId
{{
public:
{builtin_id_declarations}
}}; // class BuiltInId
namespace BuiltInVariable
{{
......@@ -144,23 +154,15 @@ template_symboltable_cpp = """// GENERATED FILE - DO NOT EDIT.
#include "compiler/translator/SymbolTable.h"
#include "angle_gl.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
#include "compiler/translator/ImmutableString.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/SymbolUniqueId.h"
#include "compiler/translator/SymbolTable.h"
namespace sh
{{
class BuiltInId
{{
public:
{builtin_id_declarations}
}}; // namespace BuiltInId
// Since some of the BuiltInId declarations are used outside of constexpr expressions, we need to
// have these definitions without an initializer. C++17 should eventually remove the need for this.
{builtin_id_definitions}
......@@ -455,6 +457,13 @@ class TType:
mangled_name += get_basic_mangled_name(self.data['basic'])
return mangled_name
def get_human_readable_name(self):
name = self.data['basic']
name += str(self.data['primarySize'])
if self.data['secondarySize'] > 1:
name += 'x' + str(self.data['secondarySize'])
return name
def is_vector(self):
return self.data['primarySize'] > 1 and self.data['secondarySize'] == 1
......@@ -758,6 +767,12 @@ def get_function_mangled_name(function_name, parameters):
mangled_name += param.get_mangled_name()
return mangled_name
def get_function_human_readable_name(function_name, parameters):
name = function_name
for param in parameters:
name += '_' + param.get_human_readable_name()
return name
ttype_mangled_name_variants = []
for basic_type in basic_types_enumeration:
primary_sizes = [1]
......@@ -966,10 +981,13 @@ def process_single_function_group(condition, group_name, group):
template_args['param_count'] = len(parameters)
template_args['return_type'] = function_props['returnType'].get_statictype_string()
template_args['mangled_name'] = get_function_mangled_name(function_name, parameters)
template_args['human_readable_name'] = get_function_human_readable_name(template_args['name_with_suffix'], parameters)
template_args['mangled_name_length'] = len(template_args['mangled_name'])
template_builtin_id_declaration = ' static constexpr const TSymbolUniqueId {unique_name} = TSymbolUniqueId({id});'
template_builtin_id_declaration = ' static constexpr const TSymbolUniqueId {human_readable_name} = TSymbolUniqueId({id});'
builtin_id_declarations.append(template_builtin_id_declaration.format(**template_args))
template_builtin_id_definition = 'constexpr const TSymbolUniqueId BuiltInId::{human_readable_name};'
builtin_id_definitions.append(template_builtin_id_definition.format(**template_args))
parameters_list = []
for param in parameters:
......@@ -998,7 +1016,7 @@ def process_single_function_group(condition, group_name, group):
template_parameter_list_declaration = 'constexpr const TVariable **{parameters_var_name} = nullptr;'
parameter_declarations[template_args['parameters_var_name']] = template_parameter_list_declaration.format(**template_args)
template_function_declaration = 'constexpr const TFunction kFunction_{unique_name}(BuiltInId::{unique_name}, BuiltInName::{name_with_suffix}, TExtension::{extension}, BuiltInParameters::{parameters_var_name}, {param_count}, {return_type}, EOp{op}, {known_to_not_have_side_effects});'
template_function_declaration = 'constexpr const TFunction kFunction_{unique_name}(BuiltInId::{human_readable_name}, BuiltInName::{name_with_suffix}, TExtension::{extension}, BuiltInParameters::{parameters_var_name}, {param_count}, {return_type}, EOp{op}, {known_to_not_have_side_effects});'
function_declarations.append(template_function_declaration.format(**template_args))
# If we can make sure that there's no other mangled name with the same length, function
......
......@@ -21,6 +21,7 @@ template_emulated_builtin_functions_hlsl = """// GENERATED FILE - DO NOT EDIT.
// HLSL code for emulating GLSL builtin functions not present in HLSL.
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh
{{
......@@ -30,11 +31,11 @@ namespace
struct FunctionPair
{{
constexpr FunctionPair(const MiniFunctionId &idIn, const char *bodyIn) : id(idIn), body(bodyIn)
constexpr FunctionPair(const TSymbolUniqueId &idIn, const char *bodyIn) : id(idIn.get()), body(bodyIn)
{{
}}
MiniFunctionId id;
int id;
const char *body;
}};
......@@ -42,12 +43,12 @@ constexpr FunctionPair g_hlslFunctions[] = {{
{emulated_functions}}};
}} // anonymous namespace
const char *FindHLSLFunction(const FunctionId &functionID)
const char *FindHLSLFunction(int uniqueId)
{{
for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index)
{{
const auto &function = g_hlslFunctions[index];
if (function.id == functionID)
if (function.id == uniqueId)
{{
return function.body;
}}
......@@ -74,26 +75,18 @@ def load_json(path):
return json.loads(file_data, object_pairs_hook=reject_duplicate_keys)
def enum_type(arg):
# handle 'argtype argname' and 'out argtype argname'
chunks = arg.split(' ')
arg_type = chunks[0]
if len(chunks) == 3:
arg_type = chunks[1]
if arg_type == "float2x2":
return "Mat2"
elif arg_type == "float3x3":
return "Mat3"
elif arg_type == "float4x4":
return "Mat4"
suffix = ""
if not arg_type[-1].isdigit():
suffix = '1'
return arg_type.capitalize() + suffix
def caps(op):
return op[0].upper() + op[1:]
# handle 'argtype argname' and 'out argtype argname'
chunks = arg.split(' ')
arg_type = chunks[0]
if len(chunks) == 3:
arg_type = chunks[1]
suffix = ""
if not arg_type[-1].isdigit():
suffix = '1'
if arg_type[0:4] == 'uint':
return 'UI' + arg_type[2:] + suffix
return arg_type.capitalize() + suffix
input_script = "emulated_builtin_function_data_hlsl.json"
hlsl_json = load_json(input_script)
......@@ -109,7 +102,7 @@ def gen_emulated_function(data):
body = [ sig, '{' ] + [' ' + line for line in data['body']] + ['}']
func += "{\n"
func += "{ EOp" + caps(data['op']) + ", " + ", ".join("ParamType::" + enum_type(arg) for arg in data['args']) + " },\n"
func += "BuiltInId::" + data['op'] + "_" + "_".join([enum_type(arg) for arg in data['args']]) + ",\n"
if 'helper' in data:
func += '"' + '\\n"\n"'.join(data['helper']) + '\\n"\n'
func += '"' + '\\n"\n"'.join(body) + '\\n"\n'
......
......@@ -114,7 +114,8 @@ void AddArrayZeroInitForLoop(const TIntermTyped *initializedNode,
TIntermConstantUnion *arraySizeNode = CreateIndexNode(initializedNode->getOutermostArraySize());
TIntermBinary *indexSmallerThanSize =
new TIntermBinary(EOpLessThan, indexSymbolNode->deepCopy(), arraySizeNode);
TIntermUnary *indexIncrement = new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy());
TIntermUnary *indexIncrement =
new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy(), nullptr);
TIntermBlock *forLoopBody = new TIntermBlock();
TIntermSequence *forLoopBodySeq = forLoopBody->getSequence();
......
......@@ -11,6 +11,7 @@
#include "compiler/translator/tree_ops/RemovePow.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
......@@ -34,7 +35,7 @@ bool IsProblematicPow(TIntermTyped *node)
class RemovePowTraverser : public TIntermTraverser
{
public:
RemovePowTraverser();
RemovePowTraverser(TSymbolTable *symbolTable);
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
......@@ -45,8 +46,8 @@ class RemovePowTraverser : public TIntermTraverser
bool mNeedAnotherIteration;
};
RemovePowTraverser::RemovePowTraverser()
: TIntermTraverser(true, false, false), mNeedAnotherIteration(false)
RemovePowTraverser::RemovePowTraverser(TSymbolTable *symbolTable)
: TIntermTraverser(true, false, false, symbolTable), mNeedAnotherIteration(false)
{
}
......@@ -57,14 +58,18 @@ bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
TIntermTyped *x = node->getSequence()->at(0)->getAsTyped();
TIntermTyped *y = node->getSequence()->at(1)->getAsTyped();
TIntermUnary *log = new TIntermUnary(EOpLog2, x);
TIntermSequence *logArgs = new TIntermSequence();
logArgs->push_back(x);
TIntermTyped *log = CreateBuiltInFunctionCallNode("log2", logArgs, *mSymbolTable, 100);
log->setLine(node->getLine());
TOperator op = TIntermBinary::GetMulOpBasedOnOperands(y->getType(), log->getType());
TIntermBinary *mul = new TIntermBinary(op, y, log);
mul->setLine(node->getLine());
TIntermUnary *exp = new TIntermUnary(EOpExp2, mul);
TIntermSequence *expArgs = new TIntermSequence();
expArgs->push_back(mul);
TIntermTyped *exp = CreateBuiltInFunctionCallNode("exp2", expArgs, *mSymbolTable, 100);
exp->setLine(node->getLine());
queueReplacement(exp, OriginalNode::IS_DROPPED);
......@@ -82,9 +87,9 @@ bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
} // namespace
void RemovePow(TIntermNode *root)
void RemovePow(TIntermNode *root, TSymbolTable *symbolTable)
{
RemovePowTraverser traverser;
RemovePowTraverser traverser(symbolTable);
// Iterate as necessary, and reset the traverser between iterations.
do
{
......
......@@ -14,8 +14,9 @@
namespace sh
{
class TIntermNode;
class TSymbolTable;
void RemovePow(TIntermNode *root);
void RemovePow(TIntermNode *root, TSymbolTable *symbolTable);
} // namespace sh
#endif // COMPILER_TRANSLATOR_TREEOPS_REMOVEPOW_H_
......@@ -96,7 +96,7 @@ class DoWhileRewriter : public TIntermTraverser
breakBlock->getSequence()->push_back(breakStatement);
TIntermUnary *negatedCondition =
new TIntermUnary(EOpLogicalNot, loop->getCondition());
new TIntermUnary(EOpLogicalNot, loop->getCondition(), nullptr);
TIntermIfElse *innerIf = new TIntermIfElse(negatedCondition, breakBlock, nullptr);
......
......@@ -92,7 +92,8 @@ TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
}
TIntermSymbol *conditionSymbolElse = CreateTempSymbolNode(conditionVariable);
TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse);
TIntermUnary *negatedCondition =
new TIntermUnary(EOpLogicalNot, conditionSymbolElse, nullptr);
TIntermIfElse *falseIfElse =
new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
falseBlock = EnsureBlock(falseIfElse);
......
......@@ -75,7 +75,7 @@ bool Traverser::visitUnary(Visit visit, TIntermUnary *node)
// Potential problem case detected, apply workaround: -(int) -> ~(int) + 1.
// ~(int)
TIntermUnary *bitwiseNot = new TIntermUnary(EOpBitwiseNot, opr);
TIntermUnary *bitwiseNot = new TIntermUnary(EOpBitwiseNot, opr, nullptr);
bitwiseNot->setLine(opr->getLine());
// Constant 1 (or 1u)
......@@ -109,4 +109,4 @@ void RewriteUnaryMinusOperatorInt(TIntermNode *root)
Traverser::Apply(root);
}
} // namespace sh
\ No newline at end of file
} // namespace sh
......@@ -88,7 +88,7 @@ bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node)
CreateTempAssignmentNode(resultVariable, node->getRight()));
TIntermUnary *notTempSymbol =
new TIntermUnary(EOpLogicalNot, CreateTempSymbolNode(resultVariable));
new TIntermUnary(EOpLogicalNot, CreateTempSymbolNode(resultVariable), nullptr);
TIntermIfElse *ifNode = new TIntermIfElse(notTempSymbol, assignRightBlock, nullptr);
insertions.push_back(ifNode);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -261,7 +261,7 @@ TIntermTyped *CreateBuiltInFunctionCallNode(const char *name,
TOperator op = fn->getBuiltInOp();
if (op != EOpCallBuiltInFunction && arguments->size() == 1)
{
return new TIntermUnary(op, arguments->at(0)->getAsTyped());
return new TIntermUnary(op, arguments->at(0)->getAsTyped(), fn);
}
return TIntermAggregate::CreateBuiltInFunctionCall(*fn, arguments);
}
......
......@@ -196,7 +196,7 @@ TEST_F(IntermNodeTest, DeepCopyUnaryNode)
{
TType type(EbtFloat, EbpHigh);
TIntermUnary *original = new TIntermUnary(EOpPreIncrement, createTestSymbol());
TIntermUnary *original = new TIntermUnary(EOpPreIncrement, createTestSymbol(), nullptr);
original->setLine(getTestSourceLoc());
TIntermTyped *copyTyped = original->deepCopy();
TIntermUnary *copy = copyTyped->getAsUnaryNode();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment