xref: /aosp_15_r20/external/angle/src/tests/compiler_tests/IntermNode_test.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // IntermNode_test.cpp:
7 //   Unit tests for the AST node classes.
8 //
9 
10 #include "compiler/translator/IntermNode.h"
11 #include "angle_gl.h"
12 #include "compiler/translator/InfoSink.h"
13 #include "compiler/translator/PoolAlloc.h"
14 #include "compiler/translator/StaticType.h"
15 #include "compiler/translator/SymbolTable.h"
16 #include "gtest/gtest.h"
17 
18 using namespace sh;
19 
20 class IntermNodeTest : public testing::Test
21 {
22   public:
IntermNodeTest()23     IntermNodeTest() : mUniqueIndex(0) {}
24 
25   protected:
SetUp()26     void SetUp() override
27     {
28         allocator.push();
29         SetGlobalPoolAllocator(&allocator);
30     }
31 
TearDown()32     void TearDown() override
33     {
34         SetGlobalPoolAllocator(nullptr);
35         allocator.pop();
36     }
37 
createTestSymbol(const TType & type)38     TIntermSymbol *createTestSymbol(const TType &type)
39     {
40         std::stringstream symbolNameOut;
41         symbolNameOut << "test" << mUniqueIndex;
42         ImmutableString symbolName(symbolNameOut.str());
43         ++mUniqueIndex;
44 
45         // We're using a mock symbol table here, don't need to assign proper symbol ids to these
46         // nodes.
47         TSymbolTable symbolTable;
48         TType *variableType = new TType(type);
49         variableType->setQualifier(EvqTemporary);
50         TVariable *variable =
51             new TVariable(&symbolTable, symbolName, variableType, SymbolType::AngleInternal);
52         TIntermSymbol *node = new TIntermSymbol(variable);
53         node->setLine(createUniqueSourceLoc());
54         return node;
55     }
56 
createTestSymbol()57     TIntermSymbol *createTestSymbol()
58     {
59         TType type(EbtFloat, EbpHigh);
60         return createTestSymbol(type);
61     }
62 
createTestFunction(const TType & returnType,const TIntermSequence & args)63     TFunction *createTestFunction(const TType &returnType, const TIntermSequence &args)
64     {
65         // We're using a mock symbol table similarly as for creating symbol nodes.
66         const ImmutableString name("testFunc");
67         TSymbolTable symbolTable;
68         TFunction *func = new TFunction(&symbolTable, name, SymbolType::UserDefined,
69                                         new TType(returnType), false);
70         for (TIntermNode *arg : args)
71         {
72             const TType *type = new TType(arg->getAsTyped()->getType());
73             func->addParameter(new TVariable(&symbolTable, ImmutableString("param"), type,
74                                              SymbolType::UserDefined));
75         }
76         return func;
77     }
78 
checkTypeEqualWithQualifiers(const TType & original,const TType & copy)79     void checkTypeEqualWithQualifiers(const TType &original, const TType &copy)
80     {
81         ASSERT_EQ(original, copy);
82         ASSERT_EQ(original.getPrecision(), copy.getPrecision());
83         ASSERT_EQ(original.getQualifier(), copy.getQualifier());
84     }
85 
checkSymbolCopy(TIntermNode * aOriginal,TIntermNode * aCopy)86     void checkSymbolCopy(TIntermNode *aOriginal, TIntermNode *aCopy)
87     {
88         ASSERT_NE(aOriginal, aCopy);
89         TIntermSymbol *copy     = aCopy->getAsSymbolNode();
90         TIntermSymbol *original = aOriginal->getAsSymbolNode();
91         ASSERT_NE(nullptr, copy);
92         ASSERT_NE(nullptr, original);
93         ASSERT_NE(original, copy);
94         ASSERT_EQ(&original->variable(), &copy->variable());
95         ASSERT_EQ(original->uniqueId(), copy->uniqueId());
96         ASSERT_EQ(original->getName(), copy->getName());
97         checkTypeEqualWithQualifiers(original->getType(), copy->getType());
98         ASSERT_EQ(original->getLine().first_file, copy->getLine().first_file);
99         ASSERT_EQ(original->getLine().first_line, copy->getLine().first_line);
100         ASSERT_EQ(original->getLine().last_file, copy->getLine().last_file);
101         ASSERT_EQ(original->getLine().last_line, copy->getLine().last_line);
102     }
103 
createUniqueSourceLoc()104     TSourceLoc createUniqueSourceLoc()
105     {
106         TSourceLoc loc;
107         loc.first_file = mUniqueIndex;
108         loc.first_line = mUniqueIndex + 1;
109         loc.last_file  = mUniqueIndex + 2;
110         loc.last_line  = mUniqueIndex + 3;
111         ++mUniqueIndex;
112         return loc;
113     }
114 
getTestSourceLoc()115     static TSourceLoc getTestSourceLoc()
116     {
117         TSourceLoc loc;
118         loc.first_file = 1;
119         loc.first_line = 2;
120         loc.last_file  = 3;
121         loc.last_line  = 4;
122         return loc;
123     }
124 
checkTestSourceLoc(const TSourceLoc & loc)125     static void checkTestSourceLoc(const TSourceLoc &loc)
126     {
127         ASSERT_EQ(1, loc.first_file);
128         ASSERT_EQ(2, loc.first_line);
129         ASSERT_EQ(3, loc.last_file);
130         ASSERT_EQ(4, loc.last_line);
131     }
132 
133   private:
134     angle::PoolAllocator allocator;
135     int mUniqueIndex;
136 };
137 
138 // Check that the deep copy of a symbol node is an actual copy with the same attributes as the
139 // original.
TEST_F(IntermNodeTest,DeepCopySymbolNode)140 TEST_F(IntermNodeTest, DeepCopySymbolNode)
141 {
142     const TType *type = StaticType::Get<EbtInt, EbpHigh, EvqTemporary, 1, 1>();
143 
144     // We're using a mock symbol table here, don't need to assign proper symbol ids to these nodes.
145     TSymbolTable symbolTable;
146 
147     TVariable *variable =
148         new TVariable(&symbolTable, ImmutableString("name"), type, SymbolType::AngleInternal);
149     TIntermSymbol *original = new TIntermSymbol(variable);
150     original->setLine(getTestSourceLoc());
151     TIntermTyped *copy = original->deepCopy();
152     checkSymbolCopy(original, copy);
153     checkTestSourceLoc(copy->getLine());
154 }
155 
156 // Check that the deep copy of a constant union node is an actual copy with the same attributes as
157 // the original.
TEST_F(IntermNodeTest,DeepCopyConstantUnionNode)158 TEST_F(IntermNodeTest, DeepCopyConstantUnionNode)
159 {
160     TType type(EbtInt, EbpHigh);
161     TConstantUnion *constValue = new TConstantUnion[1];
162     constValue[0].setIConst(101);
163     TIntermConstantUnion *original = new TIntermConstantUnion(constValue, type);
164     original->setLine(getTestSourceLoc());
165     TIntermTyped *copyTyped    = original->deepCopy();
166     TIntermConstantUnion *copy = copyTyped->getAsConstantUnion();
167     ASSERT_NE(nullptr, copy);
168     ASSERT_NE(original, copy);
169     checkTestSourceLoc(copy->getLine());
170     checkTypeEqualWithQualifiers(original->getType(), copy->getType());
171     ASSERT_EQ(101, copy->getIConst(0));
172 }
173 
174 // Check that the deep copy of a binary node is an actual copy with the same attributes as the
175 // original. Child nodes also need to be copies with the same attributes as the original children.
TEST_F(IntermNodeTest,DeepCopyBinaryNode)176 TEST_F(IntermNodeTest, DeepCopyBinaryNode)
177 {
178     TType type(EbtFloat, EbpHigh);
179 
180     TIntermBinary *original = new TIntermBinary(EOpAdd, createTestSymbol(), createTestSymbol());
181     original->setLine(getTestSourceLoc());
182     TIntermTyped *copyTyped = original->deepCopy();
183     TIntermBinary *copy     = copyTyped->getAsBinaryNode();
184     ASSERT_NE(nullptr, copy);
185     ASSERT_NE(original, copy);
186     checkTestSourceLoc(copy->getLine());
187     checkTypeEqualWithQualifiers(original->getType(), copy->getType());
188 
189     checkSymbolCopy(original->getLeft(), copy->getLeft());
190     checkSymbolCopy(original->getRight(), copy->getRight());
191 }
192 
193 // Check that the deep copy of a unary node is an actual copy with the same attributes as the
194 // original. The child node also needs to be a copy with the same attributes as the original child.
TEST_F(IntermNodeTest,DeepCopyUnaryNode)195 TEST_F(IntermNodeTest, DeepCopyUnaryNode)
196 {
197     TType type(EbtFloat, EbpHigh);
198 
199     TIntermUnary *original = new TIntermUnary(EOpPreIncrement, createTestSymbol(), nullptr);
200     original->setLine(getTestSourceLoc());
201     TIntermTyped *copyTyped = original->deepCopy();
202     TIntermUnary *copy      = copyTyped->getAsUnaryNode();
203     ASSERT_NE(nullptr, copy);
204     ASSERT_NE(original, copy);
205     checkTestSourceLoc(copy->getLine());
206     checkTypeEqualWithQualifiers(original->getType(), copy->getType());
207 
208     checkSymbolCopy(original->getOperand(), copy->getOperand());
209 }
210 
211 // Check that the deep copy of an aggregate node is an actual copy with the same attributes as the
212 // original. Child nodes also need to be copies with the same attributes as the original children.
TEST_F(IntermNodeTest,DeepCopyAggregateNode)213 TEST_F(IntermNodeTest, DeepCopyAggregateNode)
214 {
215     TIntermSequence *originalSeq = new TIntermSequence();
216     originalSeq->push_back(createTestSymbol());
217     originalSeq->push_back(createTestSymbol());
218     originalSeq->push_back(createTestSymbol());
219 
220     TFunction *testFunc =
221         createTestFunction(originalSeq->back()->getAsTyped()->getType(), *originalSeq);
222 
223     TIntermAggregate *original = TIntermAggregate::CreateFunctionCall(*testFunc, originalSeq);
224     original->setLine(getTestSourceLoc());
225 
226     TIntermTyped *copyTyped = original->deepCopy();
227     TIntermAggregate *copy  = copyTyped->getAsAggregate();
228     ASSERT_NE(nullptr, copy);
229     ASSERT_NE(original, copy);
230     checkTestSourceLoc(copy->getLine());
231     checkTypeEqualWithQualifiers(original->getType(), copy->getType());
232 
233     ASSERT_EQ(original->getSequence()->size(), copy->getSequence()->size());
234     TIntermSequence::size_type i = 0;
235     for (auto *copyChild : *copy->getSequence())
236     {
237         TIntermNode *originalChild = original->getSequence()->at(i);
238         checkSymbolCopy(originalChild, copyChild);
239         ++i;
240     }
241 }
242 
243 // Check that the deep copy of a ternary node is an actual copy with the same attributes as the
244 // original. Child nodes also need to be copies with the same attributes as the original children.
TEST_F(IntermNodeTest,DeepCopyTernaryNode)245 TEST_F(IntermNodeTest, DeepCopyTernaryNode)
246 {
247     TType type(EbtFloat, EbpHigh);
248 
249     TIntermTernary *original = new TIntermTernary(createTestSymbol(TType(EbtBool, EbpUndefined)),
250                                                   createTestSymbol(), createTestSymbol());
251     original->setLine(getTestSourceLoc());
252     TIntermTyped *copyTyped = original->deepCopy();
253     TIntermTernary *copy    = copyTyped->getAsTernaryNode();
254     ASSERT_NE(nullptr, copy);
255     ASSERT_NE(original, copy);
256     checkTestSourceLoc(copy->getLine());
257     checkTypeEqualWithQualifiers(original->getType(), copy->getType());
258 
259     checkSymbolCopy(original->getCondition(), copy->getCondition());
260     checkSymbolCopy(original->getTrueExpression(), copy->getTrueExpression());
261     checkSymbolCopy(original->getFalseExpression(), copy->getFalseExpression());
262 }
263