Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/compiler_tests/ConstantFolding_test.cpp
1693 views
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
// ConstantFolding_test.cpp:
7
// Tests for constant folding
8
//
9
10
#include "tests/test_utils/ConstantFoldingTest.h"
11
12
using namespace sh;
13
14
// Test that zero, true or false are not found in AST when they are not expected. This is to make
15
// sure that the subsequent tests run correctly.
16
TEST_F(ConstantFoldingExpressionTest, FoldFloatTestCheck)
17
{
18
const std::string &floatString = "1.0";
19
evaluateFloat(floatString);
20
ASSERT_FALSE(constantFoundInAST(0.0f));
21
ASSERT_FALSE(constantFoundInAST(true));
22
ASSERT_FALSE(constantFoundInAST(false));
23
}
24
25
TEST_F(ConstantFoldingTest, FoldIntegerAdd)
26
{
27
const std::string &shaderString =
28
"#version 300 es\n"
29
"precision mediump float;\n"
30
"out int my_Int;\n"
31
"void main() {\n"
32
" const int i = 1124 + 5;\n"
33
" my_Int = i;\n"
34
"}\n";
35
compileAssumeSuccess(shaderString);
36
ASSERT_FALSE(constantFoundInAST(1124));
37
ASSERT_FALSE(constantFoundInAST(5));
38
ASSERT_TRUE(constantFoundInAST(1129));
39
}
40
41
TEST_F(ConstantFoldingTest, FoldIntegerSub)
42
{
43
const std::string &shaderString =
44
"#version 300 es\n"
45
"precision mediump float;\n"
46
"out int my_Int;\n"
47
"void main() {\n"
48
" const int i = 1124 - 5;\n"
49
" my_Int = i;\n"
50
"}\n";
51
compileAssumeSuccess(shaderString);
52
ASSERT_FALSE(constantFoundInAST(1124));
53
ASSERT_FALSE(constantFoundInAST(5));
54
ASSERT_TRUE(constantFoundInAST(1119));
55
}
56
57
TEST_F(ConstantFoldingTest, FoldIntegerMul)
58
{
59
const std::string &shaderString =
60
"#version 300 es\n"
61
"precision mediump float;\n"
62
"out int my_Int;\n"
63
"void main() {\n"
64
" const int i = 1124 * 5;\n"
65
" my_Int = i;\n"
66
"}\n";
67
compileAssumeSuccess(shaderString);
68
ASSERT_FALSE(constantFoundInAST(1124));
69
ASSERT_FALSE(constantFoundInAST(5));
70
ASSERT_TRUE(constantFoundInAST(5620));
71
}
72
73
TEST_F(ConstantFoldingTest, FoldIntegerDiv)
74
{
75
const std::string &shaderString =
76
"#version 300 es\n"
77
"precision mediump float;\n"
78
"out int my_Int;\n"
79
"void main() {\n"
80
" const int i = 1124 / 5;\n"
81
" my_Int = i;\n"
82
"}\n";
83
compileAssumeSuccess(shaderString);
84
ASSERT_FALSE(constantFoundInAST(1124));
85
ASSERT_FALSE(constantFoundInAST(5));
86
// Rounding mode of division is undefined in the spec but ANGLE can be expected to round down.
87
ASSERT_TRUE(constantFoundInAST(224));
88
}
89
90
TEST_F(ConstantFoldingTest, FoldIntegerModulus)
91
{
92
const std::string &shaderString =
93
"#version 300 es\n"
94
"precision mediump float;\n"
95
"out int my_Int;\n"
96
"void main() {\n"
97
" const int i = 1124 % 5;\n"
98
" my_Int = i;\n"
99
"}\n";
100
compileAssumeSuccess(shaderString);
101
ASSERT_FALSE(constantFoundInAST(1124));
102
ASSERT_FALSE(constantFoundInAST(5));
103
ASSERT_TRUE(constantFoundInAST(4));
104
}
105
106
TEST_F(ConstantFoldingTest, FoldVectorCrossProduct)
107
{
108
const std::string &shaderString =
109
"#version 300 es\n"
110
"precision mediump float;\n"
111
"out vec3 my_Vec3;"
112
"void main() {\n"
113
" const vec3 v3 = cross(vec3(1.0f, 1.0f, 1.0f), vec3(1.0f, -1.0f, 1.0f));\n"
114
" my_Vec3 = v3;\n"
115
"}\n";
116
compileAssumeSuccess(shaderString);
117
std::vector<float> input1(3, 1.0f);
118
ASSERT_FALSE(constantVectorFoundInAST(input1));
119
std::vector<float> input2;
120
input2.push_back(1.0f);
121
input2.push_back(-1.0f);
122
input2.push_back(1.0f);
123
ASSERT_FALSE(constantVectorFoundInAST(input2));
124
std::vector<float> result;
125
result.push_back(2.0f);
126
result.push_back(0.0f);
127
result.push_back(-2.0f);
128
ASSERT_TRUE(constantVectorFoundInAST(result));
129
}
130
131
// FoldMxNMatrixInverse tests check if the matrix 'inverse' operation
132
// on MxN matrix is constant folded when argument is constant expression and also
133
// checks the correctness of the result returned by the constant folding operation.
134
// All the matrices including matrices in the shader code are in column-major order.
135
TEST_F(ConstantFoldingTest, Fold2x2MatrixInverse)
136
{
137
const std::string &shaderString =
138
"#version 300 es\n"
139
"precision mediump float;\n"
140
"in float i;\n"
141
"out vec2 my_Vec;\n"
142
"void main() {\n"
143
" const mat2 m2 = inverse(mat2(2.0f, 3.0f,\n"
144
" 5.0f, 7.0f));\n"
145
" mat2 m = m2 * mat2(i);\n"
146
" my_Vec = m[0];\n"
147
"}\n";
148
compileAssumeSuccess(shaderString);
149
float inputElements[] = {2.0f, 3.0f, 5.0f, 7.0f};
150
std::vector<float> input(inputElements, inputElements + 4);
151
ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));
152
float outputElements[] = {-7.0f, 3.0f, 5.0f, -2.0f};
153
std::vector<float> result(outputElements, outputElements + 4);
154
ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
155
}
156
157
// Check if the matrix 'inverse' operation on 3x3 matrix is constant folded.
158
TEST_F(ConstantFoldingTest, Fold3x3MatrixInverse)
159
{
160
const std::string &shaderString =
161
"#version 300 es\n"
162
"precision mediump float;\n"
163
"in float i;\n"
164
"out vec3 my_Vec;\n"
165
"void main() {\n"
166
" const mat3 m3 = inverse(mat3(11.0f, 13.0f, 19.0f,\n"
167
" 23.0f, 29.0f, 31.0f,\n"
168
" 37.0f, 41.0f, 43.0f));\n"
169
" mat3 m = m3 * mat3(i);\n"
170
" my_Vec = m[0];\n"
171
"}\n";
172
compileAssumeSuccess(shaderString);
173
float inputElements[] = {11.0f, 13.0f, 19.0f, 23.0f, 29.0f, 31.0f, 37.0f, 41.0f, 43.0f};
174
std::vector<float> input(inputElements, inputElements + 9);
175
ASSERT_FALSE(constantVectorFoundInAST(input));
176
float outputElements[] = {3.0f / 85.0f, -11.0f / 34.0f, 37.0f / 170.0f,
177
-79.0f / 340.0f, 23.0f / 68.0f, -12.0f / 85.0f,
178
13.0f / 68.0f, -3.0f / 68.0f, -1.0f / 34.0f};
179
std::vector<float> result(outputElements, outputElements + 9);
180
const float floatFaultTolerance = 0.000001f;
181
ASSERT_TRUE(constantVectorNearFoundInAST(result, floatFaultTolerance));
182
}
183
184
// Check if the matrix 'inverse' operation on 4x4 matrix is constant folded.
185
TEST_F(ConstantFoldingTest, Fold4x4MatrixInverse)
186
{
187
const std::string &shaderString =
188
"#version 300 es\n"
189
"precision mediump float;\n"
190
"in float i;\n"
191
"out vec4 my_Vec;\n"
192
"void main() {\n"
193
" const mat4 m4 = inverse(mat4(29.0f, 31.0f, 37.0f, 41.0f,\n"
194
" 43.0f, 47.0f, 53.0f, 59.0f,\n"
195
" 61.0f, 67.0f, 71.0f, 73.0f,\n"
196
" 79.0f, 83.0f, 89.0f, 97.0f));\n"
197
" mat4 m = m4 * mat4(i);\n"
198
" my_Vec = m[0];\n"
199
"}\n";
200
compileAssumeSuccess(shaderString);
201
float inputElements[] = {29.0f, 31.0f, 37.0f, 41.0f, 43.0f, 47.0f, 53.0f, 59.0f,
202
61.0f, 67.0f, 71.0f, 73.0f, 79.0f, 83.0f, 89.0f, 97.0f};
203
std::vector<float> input(inputElements, inputElements + 16);
204
ASSERT_FALSE(constantVectorFoundInAST(input));
205
float outputElements[] = {43.0f / 126.0f, -11.0f / 21.0f, -2.0f / 21.0f, 31.0f / 126.0f,
206
-5.0f / 7.0f, 9.0f / 14.0f, 1.0f / 14.0f, -1.0f / 7.0f,
207
85.0f / 126.0f, -11.0f / 21.0f, 43.0f / 210.0f, -38.0f / 315.0f,
208
-2.0f / 7.0f, 5.0f / 14.0f, -6.0f / 35.0f, 3.0f / 70.0f};
209
std::vector<float> result(outputElements, outputElements + 16);
210
const float floatFaultTolerance = 0.00001f;
211
ASSERT_TRUE(constantVectorNearFoundInAST(result, floatFaultTolerance));
212
}
213
214
// FoldMxNMatrixDeterminant tests check if the matrix 'determinant' operation
215
// on MxN matrix is constant folded when argument is constant expression and also
216
// checks the correctness of the result returned by the constant folding operation.
217
// All the matrices including matrices in the shader code are in column-major order.
218
TEST_F(ConstantFoldingTest, Fold2x2MatrixDeterminant)
219
{
220
const std::string &shaderString =
221
"#version 300 es\n"
222
"precision mediump float;\n"
223
"out float my_Float;"
224
"void main() {\n"
225
" const float f = determinant(mat2(2.0f, 3.0f,\n"
226
" 5.0f, 7.0f));\n"
227
" my_Float = f;\n"
228
"}\n";
229
compileAssumeSuccess(shaderString);
230
float inputElements[] = {2.0f, 3.0f, 5.0f, 7.0f};
231
std::vector<float> input(inputElements, inputElements + 4);
232
ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));
233
ASSERT_TRUE(constantFoundInAST(-1.0f));
234
}
235
236
// Check if the matrix 'determinant' operation on 3x3 matrix is constant folded.
237
TEST_F(ConstantFoldingTest, Fold3x3MatrixDeterminant)
238
{
239
const std::string &shaderString =
240
"#version 300 es\n"
241
"precision mediump float;\n"
242
"out float my_Float;"
243
"void main() {\n"
244
" const float f = determinant(mat3(11.0f, 13.0f, 19.0f,\n"
245
" 23.0f, 29.0f, 31.0f,\n"
246
" 37.0f, 41.0f, 43.0f));\n"
247
" my_Float = f;\n"
248
"}\n";
249
compileAssumeSuccess(shaderString);
250
float inputElements[] = {11.0f, 13.0f, 19.0f, 23.0f, 29.0f, 31.0f, 37.0f, 41.0f, 43.0f};
251
std::vector<float> input(inputElements, inputElements + 9);
252
ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));
253
ASSERT_TRUE(constantFoundInAST(-680.0f));
254
}
255
256
// Check if the matrix 'determinant' operation on 4x4 matrix is constant folded.
257
TEST_F(ConstantFoldingTest, Fold4x4MatrixDeterminant)
258
{
259
const std::string &shaderString =
260
"#version 300 es\n"
261
"precision mediump float;\n"
262
"out float my_Float;"
263
"void main() {\n"
264
" const float f = determinant(mat4(29.0f, 31.0f, 37.0f, 41.0f,\n"
265
" 43.0f, 47.0f, 53.0f, 59.0f,\n"
266
" 61.0f, 67.0f, 71.0f, 73.0f,\n"
267
" 79.0f, 83.0f, 89.0f, 97.0f));\n"
268
" my_Float = f;\n"
269
"}\n";
270
compileAssumeSuccess(shaderString);
271
float inputElements[] = {29.0f, 31.0f, 37.0f, 41.0f, 43.0f, 47.0f, 53.0f, 59.0f,
272
61.0f, 67.0f, 71.0f, 73.0f, 79.0f, 83.0f, 89.0f, 97.0f};
273
std::vector<float> input(inputElements, inputElements + 16);
274
ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));
275
ASSERT_TRUE(constantFoundInAST(-2520.0f));
276
}
277
278
// Check if the matrix 'transpose' operation on 3x3 matrix is constant folded.
279
// All the matrices including matrices in the shader code are in column-major order.
280
TEST_F(ConstantFoldingTest, Fold3x3MatrixTranspose)
281
{
282
const std::string &shaderString =
283
"#version 300 es\n"
284
"precision mediump float;\n"
285
"in float i;\n"
286
"out vec3 my_Vec;\n"
287
"void main() {\n"
288
" const mat3 m3 = transpose(mat3(11.0f, 13.0f, 19.0f,\n"
289
" 23.0f, 29.0f, 31.0f,\n"
290
" 37.0f, 41.0f, 43.0f));\n"
291
" mat3 m = m3 * mat3(i);\n"
292
" my_Vec = m[0];\n"
293
"}\n";
294
compileAssumeSuccess(shaderString);
295
float inputElements[] = {11.0f, 13.0f, 19.0f, 23.0f, 29.0f, 31.0f, 37.0f, 41.0f, 43.0f};
296
std::vector<float> input(inputElements, inputElements + 9);
297
ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));
298
float outputElements[] = {11.0f, 23.0f, 37.0f, 13.0f, 29.0f, 41.0f, 19.0f, 31.0f, 43.0f};
299
std::vector<float> result(outputElements, outputElements + 9);
300
ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
301
}
302
303
// Test that 0xFFFFFFFF wraps to -1 when parsed as integer.
304
// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42
305
// means that any 32-bit unsigned integer value is a valid literal.
306
TEST_F(ConstantFoldingTest, ParseWrappedHexIntLiteral)
307
{
308
const std::string &shaderString =
309
"#version 300 es\n"
310
"precision mediump float;\n"
311
"precision highp int;\n"
312
"uniform int inInt;\n"
313
"out vec4 my_Vec;\n"
314
"void main() {\n"
315
" const int i = 0xFFFFFFFF;\n"
316
" my_Vec = vec4(i * inInt);\n"
317
"}\n";
318
compileAssumeSuccess(shaderString);
319
ASSERT_TRUE(constantFoundInAST(-1));
320
}
321
322
// Test that 3000000000 wraps to -1294967296 when parsed as integer.
323
// This is featured in the examples of GLSL 4.5, and ESSL behavior should match
324
// desktop GLSL when it comes to integer parsing.
325
TEST_F(ConstantFoldingTest, ParseWrappedDecimalIntLiteral)
326
{
327
const std::string &shaderString =
328
"#version 300 es\n"
329
"precision mediump float;\n"
330
"precision highp int;\n"
331
"uniform int inInt;\n"
332
"out vec4 my_Vec;\n"
333
"void main() {\n"
334
" const int i = 3000000000;\n"
335
" my_Vec = vec4(i * inInt);\n"
336
"}\n";
337
compileAssumeSuccess(shaderString);
338
ASSERT_TRUE(constantFoundInAST(-1294967296));
339
}
340
341
// Test that 0xFFFFFFFFu is parsed correctly as an unsigned integer literal.
342
// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42
343
// means that any 32-bit unsigned integer value is a valid literal.
344
TEST_F(ConstantFoldingTest, ParseMaxUintLiteral)
345
{
346
const std::string &shaderString =
347
"#version 300 es\n"
348
"precision mediump float;\n"
349
"precision highp int;\n"
350
"uniform uint inInt;\n"
351
"out vec4 my_Vec;\n"
352
"void main() {\n"
353
" const uint i = 0xFFFFFFFFu;\n"
354
" my_Vec = vec4(i * inInt);\n"
355
"}\n";
356
compileAssumeSuccess(shaderString);
357
ASSERT_TRUE(constantFoundInAST(0xFFFFFFFFu));
358
}
359
360
// Test that unary minus applied to unsigned int is constant folded correctly.
361
// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42
362
// means that any 32-bit unsigned integer value is a valid literal.
363
TEST_F(ConstantFoldingTest, FoldUnaryMinusOnUintLiteral)
364
{
365
const std::string &shaderString =
366
"#version 300 es\n"
367
"precision mediump float;\n"
368
"precision highp int;\n"
369
"uniform uint inInt;\n"
370
"out vec4 my_Vec;\n"
371
"void main() {\n"
372
" const uint i = -1u;\n"
373
" my_Vec = vec4(i * inInt);\n"
374
"}\n";
375
compileAssumeSuccess(shaderString);
376
ASSERT_TRUE(constantFoundInAST(0xFFFFFFFFu));
377
}
378
379
// Test that constant mat2 initialization with a mat2 parameter works correctly.
380
TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingMat2)
381
{
382
const std::string &shaderString =
383
"precision mediump float;\n"
384
"uniform float mult;\n"
385
"void main() {\n"
386
" const mat2 cm = mat2(mat2(0.0, 1.0, 2.0, 3.0));\n"
387
" mat2 m = cm * mult;\n"
388
" gl_FragColor = vec4(m[0], m[1]);\n"
389
"}\n";
390
compileAssumeSuccess(shaderString);
391
float outputElements[] = {0.0f, 1.0f, 2.0f, 3.0f};
392
std::vector<float> result(outputElements, outputElements + 4);
393
ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
394
}
395
396
// Test that constant mat2 initialization with an int parameter works correctly.
397
TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingScalar)
398
{
399
const std::string &shaderString =
400
"precision mediump float;\n"
401
"uniform float mult;\n"
402
"void main() {\n"
403
" const mat2 cm = mat2(3);\n"
404
" mat2 m = cm * mult;\n"
405
" gl_FragColor = vec4(m[0], m[1]);\n"
406
"}\n";
407
compileAssumeSuccess(shaderString);
408
float outputElements[] = {3.0f, 0.0f, 0.0f, 3.0f};
409
std::vector<float> result(outputElements, outputElements + 4);
410
ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
411
}
412
413
// Test that constant mat2 initialization with a mix of parameters works correctly.
414
TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingMix)
415
{
416
const std::string &shaderString =
417
"precision mediump float;\n"
418
"uniform float mult;\n"
419
"void main() {\n"
420
" const mat2 cm = mat2(-1, vec2(0.0, 1.0), vec4(2.0));\n"
421
" mat2 m = cm * mult;\n"
422
" gl_FragColor = vec4(m[0], m[1]);\n"
423
"}\n";
424
compileAssumeSuccess(shaderString);
425
float outputElements[] = {-1.0, 0.0f, 1.0f, 2.0f};
426
std::vector<float> result(outputElements, outputElements + 4);
427
ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
428
}
429
430
// Test that constant mat2 initialization with a mat3 parameter works correctly.
431
TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingMat3)
432
{
433
const std::string &shaderString =
434
"precision mediump float;\n"
435
"uniform float mult;\n"
436
"void main() {\n"
437
" const mat2 cm = mat2(mat3(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0));\n"
438
" mat2 m = cm * mult;\n"
439
" gl_FragColor = vec4(m[0], m[1]);\n"
440
"}\n";
441
compileAssumeSuccess(shaderString);
442
float outputElements[] = {0.0f, 1.0f, 3.0f, 4.0f};
443
std::vector<float> result(outputElements, outputElements + 4);
444
ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
445
}
446
447
// Test that constant mat4x3 initialization with a mat3x2 parameter works correctly.
448
TEST_F(ConstantFoldingTest, FoldMat4x3ConstructorTakingMat3x2)
449
{
450
const std::string &shaderString =
451
"#version 300 es\n"
452
"precision mediump float;\n"
453
"uniform float mult;\n"
454
"out vec4 my_FragColor;\n"
455
"void main() {\n"
456
" const mat4x3 cm = mat4x3(mat3x2(1.0, 2.0,\n"
457
" 3.0, 4.0,\n"
458
" 5.0, 6.0));\n"
459
" mat4x3 m = cm * mult;\n"
460
" my_FragColor = vec4(m[0], m[1][0]);\n"
461
"}\n";
462
compileAssumeSuccess(shaderString);
463
float outputElements[] = {1.0f, 2.0f, 0.0f, 3.0f, 4.0f, 0.0f,
464
5.0f, 6.0f, 1.0f, 0.0f, 0.0f, 0.0f};
465
std::vector<float> result(outputElements, outputElements + 12);
466
ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
467
}
468
469
// Test that constant mat2 initialization with a vec4 parameter works correctly.
470
TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingVec4)
471
{
472
const std::string &shaderString =
473
"precision mediump float;\n"
474
"uniform float mult;\n"
475
"void main() {\n"
476
" const mat2 cm = mat2(vec4(0.0, 1.0, 2.0, 3.0));\n"
477
" mat2 m = cm * mult;\n"
478
" gl_FragColor = vec4(m[0], m[1]);\n"
479
"}\n";
480
compileAssumeSuccess(shaderString);
481
float outputElements[] = {0.0f, 1.0f, 2.0f, 3.0f};
482
std::vector<float> result(outputElements, outputElements + 4);
483
ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
484
}
485
486
// Test that equality comparison of two different structs with a nested struct inside returns false.
487
TEST_F(ConstantFoldingTest, FoldNestedDifferentStructEqualityComparison)
488
{
489
const std::string &shaderString =
490
"precision mediump float;\n"
491
"struct nested {\n"
492
" float f\n;"
493
"};\n"
494
"struct S {\n"
495
" nested a;\n"
496
" float f;\n"
497
"};\n"
498
"uniform vec4 mult;\n"
499
"void main()\n"
500
"{\n"
501
" const S s1 = S(nested(0.0), 2.0);\n"
502
" const S s2 = S(nested(0.0), 3.0);\n"
503
" gl_FragColor = (s1 == s2 ? 1.0 : 0.5) * mult;\n"
504
"}\n";
505
compileAssumeSuccess(shaderString);
506
ASSERT_TRUE(constantFoundInAST(0.5f));
507
}
508
509
// Test that equality comparison of two identical structs with a nested struct inside returns true.
510
TEST_F(ConstantFoldingTest, FoldNestedIdenticalStructEqualityComparison)
511
{
512
const std::string &shaderString =
513
"precision mediump float;\n"
514
"struct nested {\n"
515
" float f\n;"
516
"};\n"
517
"struct S {\n"
518
" nested a;\n"
519
" float f;\n"
520
" int i;\n"
521
"};\n"
522
"uniform vec4 mult;\n"
523
"void main()\n"
524
"{\n"
525
" const S s1 = S(nested(0.0), 2.0, 3);\n"
526
" const S s2 = S(nested(0.0), 2.0, 3);\n"
527
" gl_FragColor = (s1 == s2 ? 1.0 : 0.5) * mult;\n"
528
"}\n";
529
compileAssumeSuccess(shaderString);
530
ASSERT_TRUE(constantFoundInAST(1.0f));
531
}
532
533
// Test that right elements are chosen from non-square matrix
534
TEST_F(ConstantFoldingTest, FoldNonSquareMatrixIndexing)
535
{
536
const std::string &shaderString =
537
"#version 300 es\n"
538
"precision mediump float;\n"
539
"out vec4 my_FragColor;\n"
540
"void main()\n"
541
"{\n"
542
" my_FragColor = mat3x4(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)[1];\n"
543
"}\n";
544
compileAssumeSuccess(shaderString);
545
float outputElements[] = {4.0f, 5.0f, 6.0f, 7.0f};
546
std::vector<float> result(outputElements, outputElements + 4);
547
ASSERT_TRUE(constantVectorFoundInAST(result));
548
}
549
550
// Test that folding outer product of vectors with non-matching lengths works.
551
TEST_F(ConstantFoldingTest, FoldNonSquareOuterProduct)
552
{
553
const std::string &shaderString =
554
"#version 300 es\n"
555
"precision mediump float;\n"
556
"out vec4 my_FragColor;\n"
557
"void main()\n"
558
"{\n"
559
" mat3x2 prod = outerProduct(vec2(2.0, 3.0), vec3(5.0, 7.0, 11.0));\n"
560
" my_FragColor = vec4(prod[0].x);\n"
561
"}\n";
562
compileAssumeSuccess(shaderString);
563
// clang-format off
564
float outputElements[] =
565
{
566
10.0f, 15.0f,
567
14.0f, 21.0f,
568
22.0f, 33.0f
569
};
570
// clang-format on
571
std::vector<float> result(outputElements, outputElements + 6);
572
ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));
573
}
574
575
// Test that folding bit shift left with non-matching signedness works.
576
TEST_F(ConstantFoldingTest, FoldBitShiftLeftDifferentSignedness)
577
{
578
const std::string &shaderString =
579
"#version 300 es\n"
580
"precision mediump float;\n"
581
"out vec4 my_FragColor;\n"
582
"void main()\n"
583
"{\n"
584
" uint u = 0xffffffffu << 31;\n"
585
" my_FragColor = vec4(u);\n"
586
"}\n";
587
compileAssumeSuccess(shaderString);
588
ASSERT_TRUE(constantFoundInAST(0x80000000u));
589
}
590
591
// Test that folding bit shift right with non-matching signedness works.
592
TEST_F(ConstantFoldingTest, FoldBitShiftRightDifferentSignedness)
593
{
594
const std::string &shaderString =
595
"#version 300 es\n"
596
"precision mediump float;\n"
597
"out vec4 my_FragColor;\n"
598
"void main()\n"
599
"{\n"
600
" uint u = 0xffffffffu >> 30;\n"
601
" my_FragColor = vec4(u);\n"
602
"}\n";
603
compileAssumeSuccess(shaderString);
604
ASSERT_TRUE(constantFoundInAST(0x3u));
605
}
606
607
// Test that folding signed bit shift right extends the sign bit.
608
// ESSL 3.00.6 section 5.9 Expressions.
609
TEST_F(ConstantFoldingTest, FoldBitShiftRightExtendSignBit)
610
{
611
const std::string &shaderString =
612
"#version 300 es\n"
613
"precision mediump float;\n"
614
"out vec4 my_FragColor;\n"
615
"void main()\n"
616
"{\n"
617
" const int i = 0x8fffe000 >> 6;\n"
618
" uint u = uint(i);"
619
" my_FragColor = vec4(u);\n"
620
"}\n";
621
compileAssumeSuccess(shaderString);
622
// The bits of the operand are 0x8fffe000 = 1000 1111 1111 1111 1110 0000 0000 0000
623
// After shifting, they become 1111 1110 0011 1111 1111 1111 1000 0000 = 0xfe3fff80
624
ASSERT_TRUE(constantFoundInAST(0xfe3fff80u));
625
}
626
627
// Signed bit shift left should interpret its operand as a bit pattern. As a consequence a number
628
// may turn from positive to negative when shifted left.
629
// ESSL 3.00.6 section 5.9 Expressions.
630
TEST_F(ConstantFoldingTest, FoldBitShiftLeftInterpretedAsBitPattern)
631
{
632
const std::string &shaderString =
633
"#version 300 es\n"
634
"precision mediump float;\n"
635
"out vec4 my_FragColor;\n"
636
"void main()\n"
637
"{\n"
638
" const int i = 0x1fffffff << 3;\n"
639
" uint u = uint(i);"
640
" my_FragColor = vec4(u);\n"
641
"}\n";
642
compileAssumeSuccess(shaderString);
643
ASSERT_TRUE(constantFoundInAST(0xfffffff8u));
644
}
645
646
// Test that dividing the minimum signed integer by -1 works.
647
// ESSL 3.00.6 section 4.1.3 Integers:
648
// "However, for the case where the minimum representable value is divided by -1, it is allowed to
649
// return either the minimum representable value or the maximum representable value."
650
TEST_F(ConstantFoldingTest, FoldDivideMinimumIntegerByMinusOne)
651
{
652
const std::string &shaderString =
653
"#version 300 es\n"
654
"precision mediump float;\n"
655
"out vec4 my_FragColor;\n"
656
"void main()\n"
657
"{\n"
658
" int i = 0x80000000 / (-1);\n"
659
" my_FragColor = vec4(i);\n"
660
"}\n";
661
compileAssumeSuccess(shaderString);
662
ASSERT_TRUE(constantFoundInAST(0x7fffffff) || constantFoundInAST(-0x7fffffff - 1));
663
}
664
665
// Test that folding an unsigned integer addition that overflows works.
666
// ESSL 3.00.6 section 4.1.3 Integers:
667
// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
668
// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
669
// n is the size in bits of the integer."
670
TEST_F(ConstantFoldingTest, FoldUnsignedIntegerAddOverflow)
671
{
672
const std::string &shaderString =
673
"#version 300 es\n"
674
"precision mediump float;\n"
675
"out vec4 my_FragColor;\n"
676
"void main()\n"
677
"{\n"
678
" uint u = 0xffffffffu + 43u;\n"
679
" my_FragColor = vec4(u);\n"
680
"}\n";
681
compileAssumeSuccess(shaderString);
682
ASSERT_TRUE(constantFoundInAST(42u));
683
}
684
685
// Test that folding a signed integer addition that overflows works.
686
// ESSL 3.00.6 section 4.1.3 Integers:
687
// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
688
// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
689
// n is the size in bits of the integer."
690
TEST_F(ConstantFoldingTest, FoldSignedIntegerAddOverflow)
691
{
692
const std::string &shaderString =
693
"#version 300 es\n"
694
"precision mediump float;\n"
695
"out vec4 my_FragColor;\n"
696
"void main()\n"
697
"{\n"
698
" int i = 0x7fffffff + 4;\n"
699
" my_FragColor = vec4(i);\n"
700
"}\n";
701
compileAssumeSuccess(shaderString);
702
ASSERT_TRUE(constantFoundInAST(-0x7ffffffd));
703
}
704
705
// Test that folding an unsigned integer subtraction that overflows works.
706
// ESSL 3.00.6 section 4.1.3 Integers:
707
// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
708
// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
709
// n is the size in bits of the integer."
710
TEST_F(ConstantFoldingTest, FoldUnsignedIntegerDiffOverflow)
711
{
712
const std::string &shaderString =
713
"#version 300 es\n"
714
"precision mediump float;\n"
715
"out vec4 my_FragColor;\n"
716
"void main()\n"
717
"{\n"
718
" uint u = 0u - 5u;\n"
719
" my_FragColor = vec4(u);\n"
720
"}\n";
721
compileAssumeSuccess(shaderString);
722
ASSERT_TRUE(constantFoundInAST(0xfffffffbu));
723
}
724
725
// Test that folding a signed integer subtraction that overflows works.
726
// ESSL 3.00.6 section 4.1.3 Integers:
727
// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
728
// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
729
// n is the size in bits of the integer."
730
TEST_F(ConstantFoldingTest, FoldSignedIntegerDiffOverflow)
731
{
732
const std::string &shaderString =
733
"#version 300 es\n"
734
"precision mediump float;\n"
735
"out vec4 my_FragColor;\n"
736
"void main()\n"
737
"{\n"
738
" int i = -0x7fffffff - 7;\n"
739
" my_FragColor = vec4(i);\n"
740
"}\n";
741
compileAssumeSuccess(shaderString);
742
ASSERT_TRUE(constantFoundInAST(0x7ffffffa));
743
}
744
745
// Test that folding an unsigned integer multiplication that overflows works.
746
// ESSL 3.00.6 section 4.1.3 Integers:
747
// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
748
// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
749
// n is the size in bits of the integer."
750
TEST_F(ConstantFoldingTest, FoldUnsignedIntegerMultiplyOverflow)
751
{
752
const std::string &shaderString =
753
"#version 300 es\n"
754
"precision mediump float;\n"
755
"out vec4 my_FragColor;\n"
756
"void main()\n"
757
"{\n"
758
" uint u = 0xffffffffu * 10u;\n"
759
" my_FragColor = vec4(u);\n"
760
"}\n";
761
compileAssumeSuccess(shaderString);
762
ASSERT_TRUE(constantFoundInAST(0xfffffff6u));
763
}
764
765
// Test that folding a signed integer multiplication that overflows works.
766
// ESSL 3.00.6 section 4.1.3 Integers:
767
// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
768
// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
769
// n is the size in bits of the integer."
770
TEST_F(ConstantFoldingTest, FoldSignedIntegerMultiplyOverflow)
771
{
772
const std::string &shaderString =
773
"#version 300 es\n"
774
"precision mediump float;\n"
775
"out vec4 my_FragColor;\n"
776
"void main()\n"
777
"{\n"
778
" int i = 0x7fffffff * 42;\n"
779
" my_FragColor = vec4(i);\n"
780
"}\n";
781
compileAssumeSuccess(shaderString);
782
ASSERT_TRUE(constantFoundInAST(-42));
783
}
784
785
// Test that folding of negating the minimum representable integer works. Note that in the test
786
// "0x80000000" is a negative literal, and the minus sign before it is the negation operator.
787
// ESSL 3.00.6 section 4.1.3 Integers:
788
// "For all precisions, operations resulting in overflow or underflow will not cause any exception,
789
// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where
790
// n is the size in bits of the integer."
791
TEST_F(ConstantFoldingTest, FoldMinimumSignedIntegerNegation)
792
{
793
const std::string &shaderString =
794
"#version 300 es\n"
795
"precision mediump float;\n"
796
"out vec4 my_FragColor;\n"
797
"void main()\n"
798
"{\n"
799
" int i = -0x80000000;\n"
800
" my_FragColor = vec4(i);\n"
801
"}\n";
802
compileAssumeSuccess(shaderString);
803
// Negating the minimum signed integer overflows the positive range, so it wraps back to itself.
804
ASSERT_TRUE(constantFoundInAST(-0x7fffffff - 1));
805
}
806
807
// Test that folding of shifting the minimum representable integer works.
808
TEST_F(ConstantFoldingTest, FoldMinimumSignedIntegerRightShift)
809
{
810
const std::string &shaderString =
811
"#version 300 es\n"
812
"precision mediump float;\n"
813
"out vec4 my_FragColor;\n"
814
"void main()\n"
815
"{\n"
816
" int i = (0x80000000 >> 1);\n"
817
" int j = (0x80000000 >> 7);\n"
818
" my_FragColor = vec4(i, j, i, j);\n"
819
"}\n";
820
compileAssumeSuccess(shaderString);
821
ASSERT_TRUE(constantFoundInAST(-0x40000000));
822
ASSERT_TRUE(constantFoundInAST(-0x01000000));
823
}
824
825
// Test that folding of shifting by 0 works.
826
TEST_F(ConstantFoldingTest, FoldShiftByZero)
827
{
828
const std::string &shaderString =
829
"#version 300 es\n"
830
"precision mediump float;\n"
831
"out vec4 my_FragColor;\n"
832
"void main()\n"
833
"{\n"
834
" int i = (3 >> 0);\n"
835
" int j = (73 << 0);\n"
836
" my_FragColor = vec4(i, j, i, j);\n"
837
"}\n";
838
compileAssumeSuccess(shaderString);
839
ASSERT_TRUE(constantFoundInAST(3));
840
ASSERT_TRUE(constantFoundInAST(73));
841
}
842
843
// Test that folding IsInf results in true when the parameter is an out-of-range float literal.
844
// ESSL 3.00.6 section 4.1.4 Floats:
845
// "If the value of the floating point number is too large (small) to be stored as a single
846
// precision value, it is converted to positive (negative) infinity."
847
// ESSL 3.00.6 section 12.4:
848
// "Mandate support for signed infinities."
849
TEST_F(ConstantFoldingTest, FoldIsInfOutOfRangeFloatLiteral)
850
{
851
const std::string &shaderString =
852
"#version 300 es\n"
853
"precision mediump float;\n"
854
"out vec4 my_FragColor;\n"
855
"void main()\n"
856
"{\n"
857
" bool b = isinf(1.0e2048);\n"
858
" my_FragColor = vec4(b);\n"
859
"}\n";
860
compileAssumeSuccess(shaderString);
861
ASSERT_TRUE(constantFoundInAST(true));
862
}
863
864
// Regression test case of unary + constant folding of a void struct member.
865
TEST_F(ConstantFoldingTest, VoidStructMember)
866
{
867
constexpr const char *kShaderString = "struct U{void t;}n(){+U().t";
868
ASSERT_FALSE(compile(kShaderString));
869
}
870
871
// Test that floats that are too small to be represented get flushed to zero.
872
// ESSL 3.00.6 section 4.1.4 Floats:
873
// "A value with a magnitude too small to be represented as a mantissa and exponent is converted to
874
// zero."
875
TEST_F(ConstantFoldingExpressionTest, FoldTooSmallFloat)
876
{
877
const std::string &floatString = "1.0e-2048";
878
evaluateFloat(floatString);
879
ASSERT_TRUE(constantFoundInAST(0.0f));
880
}
881
882
// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
883
// lim radians(x) x -> inf = inf
884
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
885
TEST_F(ConstantFoldingExpressionTest, FoldRadiansInfinity)
886
{
887
const std::string &floatString = "radians(1.0e2048)";
888
evaluateFloat(floatString);
889
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
890
}
891
892
// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
893
// lim degrees(x) x -> inf = inf
894
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
895
TEST_F(ConstantFoldingExpressionTest, FoldDegreesInfinity)
896
{
897
const std::string &floatString = "degrees(1.0e2048)";
898
evaluateFloat(floatString);
899
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
900
}
901
902
// IEEE 754 dictates that sinh(inf) = inf.
903
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
904
TEST_F(ConstantFoldingExpressionTest, FoldSinhInfinity)
905
{
906
const std::string &floatString = "sinh(1.0e2048)";
907
evaluateFloat(floatString);
908
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
909
}
910
911
// IEEE 754 dictates that sinh(-inf) = -inf.
912
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
913
TEST_F(ConstantFoldingExpressionTest, FoldSinhNegativeInfinity)
914
{
915
const std::string &floatString = "sinh(-1.0e2048)";
916
evaluateFloat(floatString);
917
ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
918
}
919
920
// IEEE 754 dictates that cosh(inf) = inf.
921
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
922
TEST_F(ConstantFoldingExpressionTest, FoldCoshInfinity)
923
{
924
const std::string &floatString = "cosh(1.0e2048)";
925
evaluateFloat(floatString);
926
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
927
}
928
929
// IEEE 754 dictates that cosh(-inf) = inf.
930
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
931
TEST_F(ConstantFoldingExpressionTest, FoldCoshNegativeInfinity)
932
{
933
const std::string &floatString = "cosh(-1.0e2048)";
934
evaluateFloat(floatString);
935
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
936
}
937
938
// IEEE 754 dictates that asinh(inf) = inf.
939
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
940
TEST_F(ConstantFoldingExpressionTest, FoldAsinhInfinity)
941
{
942
const std::string &floatString = "asinh(1.0e2048)";
943
evaluateFloat(floatString);
944
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
945
}
946
947
// IEEE 754 dictates that asinh(-inf) = -inf.
948
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
949
TEST_F(ConstantFoldingExpressionTest, FoldAsinhNegativeInfinity)
950
{
951
const std::string &floatString = "asinh(-1.0e2048)";
952
evaluateFloat(floatString);
953
ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
954
}
955
956
// IEEE 754 dictates that acosh(inf) = inf.
957
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
958
TEST_F(ConstantFoldingExpressionTest, FoldAcoshInfinity)
959
{
960
const std::string &floatString = "acosh(1.0e2048)";
961
evaluateFloat(floatString);
962
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
963
}
964
965
// IEEE 754 dictates that pow or powr(0, inf) = 0.
966
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
967
TEST_F(ConstantFoldingExpressionTest, FoldPowInfinity)
968
{
969
const std::string &floatString = "pow(0.0, 1.0e2048)";
970
evaluateFloat(floatString);
971
ASSERT_TRUE(constantFoundInAST(0.0f));
972
}
973
974
// IEEE 754 dictates that exp(inf) = inf.
975
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
976
TEST_F(ConstantFoldingExpressionTest, FoldExpInfinity)
977
{
978
const std::string &floatString = "exp(1.0e2048)";
979
evaluateFloat(floatString);
980
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
981
}
982
983
// IEEE 754 dictates that exp(-inf) = 0.
984
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
985
TEST_F(ConstantFoldingExpressionTest, FoldExpNegativeInfinity)
986
{
987
const std::string &floatString = "exp(-1.0e2048)";
988
evaluateFloat(floatString);
989
ASSERT_TRUE(constantFoundInAST(0.0f));
990
}
991
992
// IEEE 754 dictates that log(inf) = inf.
993
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
994
TEST_F(ConstantFoldingExpressionTest, FoldLogInfinity)
995
{
996
const std::string &floatString = "log(1.0e2048)";
997
evaluateFloat(floatString);
998
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
999
}
1000
1001
// IEEE 754 dictates that exp2(inf) = inf.
1002
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1003
TEST_F(ConstantFoldingExpressionTest, FoldExp2Infinity)
1004
{
1005
const std::string &floatString = "exp2(1.0e2048)";
1006
evaluateFloat(floatString);
1007
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
1008
}
1009
1010
// IEEE 754 dictates that exp2(-inf) = 0.
1011
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1012
TEST_F(ConstantFoldingExpressionTest, FoldExp2NegativeInfinity)
1013
{
1014
const std::string &floatString = "exp2(-1.0e2048)";
1015
evaluateFloat(floatString);
1016
ASSERT_TRUE(constantFoundInAST(0.0f));
1017
}
1018
1019
// IEEE 754 dictates that log2(inf) = inf.
1020
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1021
TEST_F(ConstantFoldingExpressionTest, FoldLog2Infinity)
1022
{
1023
const std::string &floatString = "log2(1.0e2048)";
1024
evaluateFloat(floatString);
1025
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
1026
}
1027
1028
// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
1029
// lim sqrt(x) x -> inf = inf
1030
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1031
TEST_F(ConstantFoldingExpressionTest, FoldSqrtInfinity)
1032
{
1033
const std::string &floatString = "sqrt(1.0e2048)";
1034
evaluateFloat(floatString);
1035
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
1036
}
1037
1038
// IEEE 754 dictates that rSqrt(inf) = 0
1039
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1040
TEST_F(ConstantFoldingExpressionTest, FoldInversesqrtInfinity)
1041
{
1042
const std::string &floatString = "inversesqrt(1.0e2048)";
1043
evaluateFloat(floatString);
1044
ASSERT_TRUE(constantFoundInAST(0.0f));
1045
}
1046
1047
// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
1048
// lim length(x) x -> inf = inf
1049
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1050
TEST_F(ConstantFoldingExpressionTest, FoldLengthInfinity)
1051
{
1052
const std::string &floatString = "length(1.0e2048)";
1053
evaluateFloat(floatString);
1054
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
1055
}
1056
1057
// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
1058
// lim dot(x, y) x -> inf, y > 0 = inf
1059
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1060
TEST_F(ConstantFoldingExpressionTest, FoldDotInfinity)
1061
{
1062
const std::string &floatString = "dot(1.0e2048, 1.0)";
1063
evaluateFloat(floatString);
1064
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
1065
}
1066
1067
// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
1068
// lim dot(vec2(x, y), vec2(z)) x -> inf, finite y, z > 0 = inf
1069
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1070
TEST_F(ConstantFoldingExpressionTest, FoldDotInfinity2)
1071
{
1072
const std::string &floatString = "dot(vec2(1.0e2048, -1.0), vec2(1.0))";
1073
evaluateFloat(floatString);
1074
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
1075
}
1076
1077
// Faceforward behavior with infinity as a parameter can be derived from dot().
1078
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1079
TEST_F(ConstantFoldingExpressionTest, FoldFaceForwardInfinity)
1080
{
1081
const std::string &floatString = "faceforward(4.0, 1.0e2048, 1.0)";
1082
evaluateFloat(floatString);
1083
ASSERT_TRUE(constantFoundInAST(-4.0f));
1084
}
1085
1086
// Faceforward behavior with infinity as a parameter can be derived from dot().
1087
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1088
TEST_F(ConstantFoldingExpressionTest, FoldFaceForwardInfinity2)
1089
{
1090
const std::string &floatString = "faceforward(vec2(4.0), vec2(1.0e2048, -1.0), vec2(1.0)).x";
1091
evaluateFloat(floatString);
1092
ASSERT_TRUE(constantFoundInAST(-4.0f));
1093
}
1094
1095
// Test that infinity - finite value evaluates to infinity.
1096
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1097
TEST_F(ConstantFoldingExpressionTest, FoldInfinityMinusFinite)
1098
{
1099
const std::string &floatString = "1.0e2048 - 1.0e20";
1100
evaluateFloat(floatString);
1101
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
1102
}
1103
1104
// Test that -infinity + finite value evaluates to -infinity.
1105
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1106
TEST_F(ConstantFoldingExpressionTest, FoldMinusInfinityPlusFinite)
1107
{
1108
const std::string &floatString = "(-1.0e2048) + 1.0e20";
1109
evaluateFloat(floatString);
1110
ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
1111
}
1112
1113
// Test that infinity * finite value evaluates to infinity.
1114
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1115
TEST_F(ConstantFoldingExpressionTest, FoldInfinityMultipliedByFinite)
1116
{
1117
const std::string &floatString = "1.0e2048 * 1.0e-20";
1118
evaluateFloat(floatString);
1119
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
1120
}
1121
1122
// Test that infinity * infinity evaluates to infinity.
1123
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1124
TEST_F(ConstantFoldingExpressionTest, FoldInfinityMultipliedByInfinity)
1125
{
1126
const std::string &floatString = "1.0e2048 * 1.0e2048";
1127
evaluateFloat(floatString);
1128
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
1129
}
1130
1131
// Test that infinity * negative infinity evaluates to negative infinity.
1132
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1133
TEST_F(ConstantFoldingExpressionTest, FoldInfinityMultipliedByNegativeInfinity)
1134
{
1135
const std::string &floatString = "1.0e2048 * (-1.0e2048)";
1136
evaluateFloat(floatString);
1137
ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
1138
}
1139
1140
// Test that dividing by minus zero results in the appropriately signed infinity.
1141
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1142
// "If both positive and negative zeros are implemented, the correctly signed Inf will be
1143
// generated".
1144
TEST_F(ConstantFoldingExpressionTest, FoldDivideByNegativeZero)
1145
{
1146
const std::string &floatString = "1.0 / (-0.0)";
1147
evaluateFloat(floatString);
1148
ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
1149
ASSERT_TRUE(hasWarning());
1150
}
1151
1152
// Test that infinity divided by zero evaluates to infinity.
1153
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1154
TEST_F(ConstantFoldingExpressionTest, FoldInfinityDividedByZero)
1155
{
1156
const std::string &floatString = "1.0e2048 / 0.0";
1157
evaluateFloat(floatString);
1158
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
1159
ASSERT_TRUE(hasWarning());
1160
}
1161
1162
// Test that negative infinity divided by zero evaluates to negative infinity.
1163
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1164
TEST_F(ConstantFoldingExpressionTest, FoldMinusInfinityDividedByZero)
1165
{
1166
const std::string &floatString = "(-1.0e2048) / 0.0";
1167
evaluateFloat(floatString);
1168
ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
1169
ASSERT_TRUE(hasWarning());
1170
}
1171
1172
// Test that dividing a finite number by infinity results in zero.
1173
// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
1174
TEST_F(ConstantFoldingExpressionTest, FoldDivideByInfinity)
1175
{
1176
const std::string &floatString = "1.0e30 / 1.0e2048";
1177
evaluateFloat(floatString);
1178
ASSERT_TRUE(constantFoundInAST(0.0f));
1179
}
1180
1181
// Test that unsigned bitfieldExtract is folded correctly.
1182
TEST_F(ConstantFoldingExpressionTest, FoldUnsignedBitfieldExtract)
1183
{
1184
const std::string &uintString = "bitfieldExtract(0x00110000u, 16, 5)";
1185
evaluateUint(uintString);
1186
ASSERT_TRUE(constantFoundInAST(0x11u));
1187
}
1188
1189
// Test that unsigned bitfieldExtract to extract 32 bits is folded correctly.
1190
TEST_F(ConstantFoldingExpressionTest, FoldUnsignedBitfieldExtract32Bits)
1191
{
1192
const std::string &uintString = "bitfieldExtract(0xff0000ffu, 0, 32)";
1193
evaluateUint(uintString);
1194
ASSERT_TRUE(constantFoundInAST(0xff0000ffu));
1195
}
1196
1197
// Test that signed bitfieldExtract is folded correctly. The higher bits should be set to 1 if the
1198
// most significant bit of the extracted value is 1.
1199
TEST_F(ConstantFoldingExpressionTest, FoldSignedBitfieldExtract)
1200
{
1201
const std::string &intString = "bitfieldExtract(0x00110000, 16, 5)";
1202
evaluateInt(intString);
1203
// 0xfffffff1 == -15
1204
ASSERT_TRUE(constantFoundInAST(-15));
1205
}
1206
1207
// Test that bitfieldInsert is folded correctly.
1208
TEST_F(ConstantFoldingExpressionTest, FoldBitfieldInsert)
1209
{
1210
const std::string &uintString = "bitfieldInsert(0x04501701u, 0x11u, 8, 5)";
1211
evaluateUint(uintString);
1212
ASSERT_TRUE(constantFoundInAST(0x04501101u));
1213
}
1214
1215
// Test that bitfieldInsert to insert 32 bits is folded correctly.
1216
TEST_F(ConstantFoldingExpressionTest, FoldBitfieldInsert32Bits)
1217
{
1218
const std::string &uintString = "bitfieldInsert(0xff0000ffu, 0x11u, 0, 32)";
1219
evaluateUint(uintString);
1220
ASSERT_TRUE(constantFoundInAST(0x11u));
1221
}
1222
1223
// Test that bitfieldReverse is folded correctly.
1224
TEST_F(ConstantFoldingExpressionTest, FoldBitfieldReverse)
1225
{
1226
const std::string &uintString = "bitfieldReverse((1u << 4u) | (1u << 7u))";
1227
evaluateUint(uintString);
1228
uint32_t flag1 = 1u << (31u - 4u);
1229
uint32_t flag2 = 1u << (31u - 7u);
1230
ASSERT_TRUE(constantFoundInAST(flag1 | flag2));
1231
}
1232
1233
// Test that bitCount is folded correctly.
1234
TEST_F(ConstantFoldingExpressionTest, FoldBitCount)
1235
{
1236
const std::string &intString = "bitCount(0x17103121u)";
1237
evaluateInt(intString);
1238
ASSERT_TRUE(constantFoundInAST(10));
1239
}
1240
1241
// Test that findLSB is folded correctly.
1242
TEST_F(ConstantFoldingExpressionTest, FoldFindLSB)
1243
{
1244
const std::string &intString = "findLSB(0x80010000u)";
1245
evaluateInt(intString);
1246
ASSERT_TRUE(constantFoundInAST(16));
1247
}
1248
1249
// Test that findLSB is folded correctly when the operand is zero.
1250
TEST_F(ConstantFoldingExpressionTest, FoldFindLSBZero)
1251
{
1252
const std::string &intString = "findLSB(0u)";
1253
evaluateInt(intString);
1254
ASSERT_TRUE(constantFoundInAST(-1));
1255
}
1256
1257
// Test that findMSB is folded correctly.
1258
TEST_F(ConstantFoldingExpressionTest, FoldFindMSB)
1259
{
1260
const std::string &intString = "findMSB(0x01000008u)";
1261
evaluateInt(intString);
1262
ASSERT_TRUE(constantFoundInAST(24));
1263
}
1264
1265
// Test that findMSB is folded correctly when the operand is zero.
1266
TEST_F(ConstantFoldingExpressionTest, FoldFindMSBZero)
1267
{
1268
const std::string &intString = "findMSB(0u)";
1269
evaluateInt(intString);
1270
ASSERT_TRUE(constantFoundInAST(-1));
1271
}
1272
1273
// Test that findMSB is folded correctly for a negative integer.
1274
// It is supposed to return the index of the most significant bit set to 0.
1275
TEST_F(ConstantFoldingExpressionTest, FoldFindMSBNegativeInt)
1276
{
1277
const std::string &intString = "findMSB(-8)";
1278
evaluateInt(intString);
1279
ASSERT_TRUE(constantFoundInAST(2));
1280
}
1281
1282
// Test that findMSB is folded correctly for -1.
1283
TEST_F(ConstantFoldingExpressionTest, FoldFindMSBMinusOne)
1284
{
1285
const std::string &intString = "findMSB(-1)";
1286
evaluateInt(intString);
1287
ASSERT_TRUE(constantFoundInAST(-1));
1288
}
1289
1290
// Test that packUnorm4x8 is folded correctly for a vector of zeroes.
1291
TEST_F(ConstantFoldingExpressionTest, FoldPackUnorm4x8Zero)
1292
{
1293
const std::string &intString = "packUnorm4x8(vec4(0.0))";
1294
evaluateUint(intString);
1295
ASSERT_TRUE(constantFoundInAST(0u));
1296
}
1297
1298
// Test that packUnorm4x8 is folded correctly for a vector of ones.
1299
TEST_F(ConstantFoldingExpressionTest, FoldPackUnorm4x8One)
1300
{
1301
const std::string &intString = "packUnorm4x8(vec4(1.0))";
1302
evaluateUint(intString);
1303
ASSERT_TRUE(constantFoundInAST(0xffffffffu));
1304
}
1305
1306
// Test that packSnorm4x8 is folded correctly for a vector of zeroes.
1307
TEST_F(ConstantFoldingExpressionTest, FoldPackSnorm4x8Zero)
1308
{
1309
const std::string &intString = "packSnorm4x8(vec4(0.0))";
1310
evaluateUint(intString);
1311
ASSERT_TRUE(constantFoundInAST(0u));
1312
}
1313
1314
// Test that packSnorm4x8 is folded correctly for a vector of ones.
1315
TEST_F(ConstantFoldingExpressionTest, FoldPackSnorm4x8One)
1316
{
1317
const std::string &intString = "packSnorm4x8(vec4(1.0))";
1318
evaluateUint(intString);
1319
ASSERT_TRUE(constantFoundInAST(0x7f7f7f7fu));
1320
}
1321
1322
// Test that packSnorm4x8 is folded correctly for a vector of minus ones.
1323
TEST_F(ConstantFoldingExpressionTest, FoldPackSnorm4x8MinusOne)
1324
{
1325
const std::string &intString = "packSnorm4x8(vec4(-1.0))";
1326
evaluateUint(intString);
1327
ASSERT_TRUE(constantFoundInAST(0x81818181u));
1328
}
1329
1330
// Test that unpackSnorm4x8 is folded correctly when it needs to clamp the result.
1331
TEST_F(ConstantFoldingExpressionTest, FoldUnpackSnorm4x8Clamp)
1332
{
1333
const std::string &floatString = "unpackSnorm4x8(0x00000080u).x";
1334
evaluateFloat(floatString);
1335
ASSERT_TRUE(constantFoundInAST(-1.0f));
1336
}
1337
1338
// Test that unpackUnorm4x8 is folded correctly.
1339
TEST_F(ConstantFoldingExpressionTest, FoldUnpackUnorm4x8)
1340
{
1341
const std::string &floatString = "unpackUnorm4x8(0x007bbeefu).z";
1342
evaluateFloat(floatString);
1343
ASSERT_TRUE(constantFoundInAST(123.0f / 255.0f));
1344
}
1345
1346
// Test that ldexp is folded correctly.
1347
TEST_F(ConstantFoldingExpressionTest, FoldLdexp)
1348
{
1349
const std::string &floatString = "ldexp(0.625, 1)";
1350
evaluateFloat(floatString);
1351
ASSERT_TRUE(constantFoundInAST(1.25f));
1352
}
1353
1354
// Fold a ternary operator.
1355
TEST_F(ConstantFoldingTest, FoldTernary)
1356
{
1357
const std::string &shaderString =
1358
R"(#version 300 es
1359
precision highp int;
1360
uniform int u;
1361
out int my_FragColor;
1362
void main()
1363
{
1364
my_FragColor = (true ? 1 : u);
1365
})";
1366
compileAssumeSuccess(shaderString);
1367
ASSERT_TRUE(constantFoundInAST(1));
1368
ASSERT_FALSE(symbolFoundInMain("u"));
1369
}
1370
1371
// Fold a ternary operator inside a consuming expression.
1372
TEST_F(ConstantFoldingTest, FoldTernaryInsideExpression)
1373
{
1374
const std::string &shaderString =
1375
R"(#version 300 es
1376
precision highp int;
1377
uniform int u;
1378
out int my_FragColor;
1379
void main()
1380
{
1381
my_FragColor = ivec2((true ? 1 : u) + 2, 4).x;
1382
})";
1383
compileAssumeSuccess(shaderString);
1384
ASSERT_TRUE(constantFoundInAST(3));
1385
ASSERT_FALSE(symbolFoundInMain("u"));
1386
}
1387
1388
// Fold indexing into an array constructor.
1389
TEST_F(ConstantFoldingExpressionTest, FoldArrayConstructorIndexing)
1390
{
1391
const std::string &floatString = "(float[3](-1.0, 1.0, 2.0))[2]";
1392
evaluateFloat(floatString);
1393
ASSERT_FALSE(constantFoundInAST(-1.0f));
1394
ASSERT_FALSE(constantFoundInAST(1.0f));
1395
ASSERT_TRUE(constantFoundInAST(2.0f));
1396
}
1397
1398
// Fold indexing into an array of arrays constructor.
1399
TEST_F(ConstantFoldingExpressionTest, FoldArrayOfArraysConstructorIndexing)
1400
{
1401
const std::string &floatString = "(float[2][2](float[2](-1.0, 1.0), float[2](2.0, 3.0)))[1][0]";
1402
evaluateFloat(floatString);
1403
ASSERT_FALSE(constantFoundInAST(-1.0f));
1404
ASSERT_FALSE(constantFoundInAST(1.0f));
1405
ASSERT_FALSE(constantFoundInAST(3.0f));
1406
ASSERT_TRUE(constantFoundInAST(2.0f));
1407
}
1408
1409
// Fold indexing into a named constant array.
1410
TEST_F(ConstantFoldingTest, FoldNamedArrayIndexing)
1411
{
1412
const std::string &shaderString =
1413
R"(#version 300 es
1414
precision highp float;
1415
const float[3] arr = float[3](-1.0, 1.0, 2.0);
1416
out float my_FragColor;
1417
void main()
1418
{
1419
my_FragColor = arr[1];
1420
})";
1421
compileAssumeSuccess(shaderString);
1422
ASSERT_FALSE(constantFoundInAST(-1.0f));
1423
ASSERT_FALSE(constantFoundInAST(2.0f));
1424
ASSERT_TRUE(constantFoundInAST(1.0f));
1425
// The variable should be pruned out since after folding the indexing, there are no more
1426
// references to it.
1427
ASSERT_FALSE(symbolFoundInAST("arr"));
1428
}
1429
1430
// Fold indexing into a named constant array of arrays.
1431
TEST_F(ConstantFoldingTest, FoldNamedArrayOfArraysIndexing)
1432
{
1433
const std::string &shaderString =
1434
R"(#version 310 es
1435
precision highp float;
1436
const float[2][2] arr = float[2][2](float[2](-1.0, 1.0), float[2](2.0, 3.0));
1437
out float my_FragColor;
1438
void main()
1439
{
1440
my_FragColor = arr[0][1];
1441
})";
1442
compileAssumeSuccess(shaderString);
1443
ASSERT_FALSE(constantFoundInAST(-1.0f));
1444
ASSERT_FALSE(constantFoundInAST(2.0f));
1445
ASSERT_FALSE(constantFoundInAST(3.0f));
1446
ASSERT_TRUE(constantFoundInAST(1.0f));
1447
// The variable should be pruned out since after folding the indexing, there are no more
1448
// references to it.
1449
ASSERT_FALSE(symbolFoundInAST("arr"));
1450
}
1451
1452
// Fold indexing into an array constructor where some of the arguments are constant and others are
1453
// non-constant but without side effects.
1454
TEST_F(ConstantFoldingTest, FoldArrayConstructorIndexingWithMixedArguments)
1455
{
1456
const std::string &shaderString =
1457
R"(#version 300 es
1458
precision highp float;
1459
uniform float u;
1460
out float my_FragColor;
1461
void main()
1462
{
1463
my_FragColor = float[2](u, 1.0)[1];
1464
})";
1465
compileAssumeSuccess(shaderString);
1466
ASSERT_TRUE(constantFoundInAST(1.0f));
1467
ASSERT_FALSE(constantFoundInAST(1));
1468
ASSERT_FALSE(symbolFoundInMain("u"));
1469
}
1470
1471
// Indexing into an array constructor where some of the arguments have side effects can't be folded.
1472
TEST_F(ConstantFoldingTest, CantFoldArrayConstructorIndexingWithSideEffects)
1473
{
1474
const std::string &shaderString =
1475
R"(#version 300 es
1476
precision highp float;
1477
out float my_FragColor;
1478
void main()
1479
{
1480
float sideEffectTarget = 0.0;
1481
float f = float[3](sideEffectTarget = 1.0, 1.0, 2.0)[1];
1482
my_FragColor = f + sideEffectTarget;
1483
})";
1484
compileAssumeSuccess(shaderString);
1485
// All of the array constructor arguments should be present in the final AST.
1486
ASSERT_TRUE(constantFoundInAST(1.0f));
1487
ASSERT_TRUE(constantFoundInAST(2.0f));
1488
}
1489
1490
// Fold comparing two array constructors.
1491
TEST_F(ConstantFoldingTest, FoldArrayConstructorEquality)
1492
{
1493
const std::string &shaderString =
1494
R"(#version 300 es
1495
precision highp float;
1496
out float my_FragColor;
1497
void main()
1498
{
1499
const bool b = (float[3](2.0, 1.0, -1.0) == float[3](2.0, 1.0, -1.0));
1500
my_FragColor = b ? 3.0 : 4.0;
1501
})";
1502
compileAssumeSuccess(shaderString);
1503
ASSERT_TRUE(constantFoundInAST(3.0f));
1504
ASSERT_FALSE(constantFoundInAST(4.0f));
1505
}
1506
1507
// Fold comparing two named constant arrays.
1508
TEST_F(ConstantFoldingExpressionTest, FoldNamedArrayEquality)
1509
{
1510
const std::string &shaderString =
1511
R"(#version 300 es
1512
precision highp float;
1513
const float[3] arrA = float[3](-1.0, 1.0, 2.0);
1514
const float[3] arrB = float[3](-1.0, 1.0, 2.0);
1515
out float my_FragColor;
1516
void main()
1517
{
1518
const bool b = (arrA == arrB);
1519
my_FragColor = b ? 3.0 : 4.0;
1520
})";
1521
compileAssumeSuccess(shaderString);
1522
ASSERT_TRUE(constantFoundInAST(3.0f));
1523
ASSERT_FALSE(constantFoundInAST(4.0f));
1524
}
1525
1526
// Fold comparing two array of arrays constructors.
1527
TEST_F(ConstantFoldingTest, FoldArrayOfArraysConstructorEquality)
1528
{
1529
const std::string &shaderString =
1530
R"(#version 310 es
1531
precision highp float;
1532
out float my_FragColor;
1533
void main()
1534
{
1535
const bool b = (float[2][2](float[2](-1.0, 1.0), float[2](2.0, 3.0)) ==
1536
float[2][2](float[2](-1.0, 1.0), float[2](2.0, 1000.0)));
1537
my_FragColor = b ? 4.0 : 5.0;
1538
})";
1539
compileAssumeSuccess(shaderString);
1540
ASSERT_TRUE(constantFoundInAST(5.0f));
1541
ASSERT_FALSE(constantFoundInAST(4.0f));
1542
}
1543
1544
// Test that casting a negative float to uint results in a warning. ESSL 3.00.6 section 5.4.1
1545
// specifies this as an undefined conversion.
1546
TEST_F(ConstantFoldingExpressionTest, FoldNegativeFloatToUint)
1547
{
1548
const std::string &uintString = "uint(-1.0)";
1549
evaluateUint(uintString);
1550
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<unsigned int>::max()));
1551
ASSERT_TRUE(hasWarning());
1552
}
1553
1554
// Test that casting a negative float to uint inside a uvec constructor results in a warning. ESSL
1555
// 3.00.6 section 5.4.1 specifies this as an undefined conversion.
1556
TEST_F(ConstantFoldingExpressionTest, FoldNegativeFloatToUvec)
1557
{
1558
const std::string &uintString = "uvec4(2.0, 1.0, vec2(0.0, -1.0)).w";
1559
evaluateUint(uintString);
1560
ASSERT_TRUE(constantFoundInAST(std::numeric_limits<unsigned int>::max()));
1561
ASSERT_TRUE(hasWarning());
1562
}
1563
1564
// Test that a negative float doesn't result in a warning when it is inside a constructor but isn't
1565
// actually converted.
1566
TEST_F(ConstantFoldingExpressionTest, NegativeFloatInsideUvecConstructorButOutOfRange)
1567
{
1568
const std::string &uintString = "uvec2(1.0, vec2(0.0, -1.0)).x";
1569
evaluateUint(uintString);
1570
ASSERT_FALSE(hasWarning());
1571
}
1572
1573
// Test that a large float (above max int32_t) is converted to unsigned integer correctly.
1574
TEST_F(ConstantFoldingExpressionTest, LargeFloatToUint)
1575
{
1576
const std::string &uintString = "uint(3221225472.0)";
1577
evaluateUint(uintString);
1578
ASSERT_TRUE(constantFoundInAST(3221225472u));
1579
ASSERT_FALSE(hasWarning());
1580
}
1581
1582
// Test that folding % with a negative dividend generates a warning.
1583
TEST_F(ConstantFoldingExpressionTest, IntegerModulusNegativeDividend)
1584
{
1585
const std::string &intString = "(-5) % 3";
1586
evaluateInt(intString);
1587
ASSERT_TRUE(hasWarning());
1588
}
1589
1590
// Test that folding % with a negative divisor generates a warning.
1591
TEST_F(ConstantFoldingExpressionTest, IntegerModulusNegativeDivisor)
1592
{
1593
const std::string &intString = "5 % (-3)";
1594
evaluateInt(intString);
1595
ASSERT_TRUE(hasWarning());
1596
}
1597
1598