• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkSpan.h"
9 #include "include/core/SkTypes.h"
10 #include "include/private/SkSLDefines.h"
11 #include "include/private/SkSLIRNode.h"
12 #include "include/private/base/SkTArray.h"
13 #include "include/sksl/SkSLOperator.h"
14 #include "src/sksl/SkSLAnalysis.h"
15 #include "src/sksl/ir/SkSLConstructor.h"
16 #include "src/sksl/ir/SkSLExpression.h"
17 #include "src/sksl/ir/SkSLFieldAccess.h"
18 #include "src/sksl/ir/SkSLIndexExpression.h"
19 #include "src/sksl/ir/SkSLLiteral.h"
20 #include "src/sksl/ir/SkSLPrefixExpression.h"
21 #include "src/sksl/ir/SkSLSwizzle.h"
22 #include "src/sksl/ir/SkSLType.h"
23 #include "src/sksl/ir/SkSLVariableReference.h"
24 
25 #include <cstddef>
26 #include <memory>
27 
28 namespace SkSL {
29 
IsSameExpressionTree(const Expression & left,const Expression & right)30 bool Analysis::IsSameExpressionTree(const Expression& left, const Expression& right) {
31     if (left.kind() != right.kind() || !left.type().matches(right.type())) {
32         return false;
33     }
34 
35     // This isn't a fully exhaustive list of expressions by any stretch of the imagination; for
36     // instance, `x[y+1] = x[y+1]` isn't detected because we don't look at BinaryExpressions.
37     // Since this is intended to be used for optimization purposes, handling the common cases is
38     // sufficient.
39     switch (left.kind()) {
40         case Expression::Kind::kLiteral:
41             return left.as<Literal>().value() == right.as<Literal>().value();
42 
43         case Expression::Kind::kConstructorArray:
44         case Expression::Kind::kConstructorArrayCast:
45         case Expression::Kind::kConstructorCompound:
46         case Expression::Kind::kConstructorCompoundCast:
47         case Expression::Kind::kConstructorDiagonalMatrix:
48         case Expression::Kind::kConstructorMatrixResize:
49         case Expression::Kind::kConstructorScalarCast:
50         case Expression::Kind::kConstructorStruct:
51         case Expression::Kind::kConstructorSplat: {
52             if (left.kind() != right.kind()) {
53                 return false;
54             }
55             const AnyConstructor& leftCtor = left.asAnyConstructor();
56             const AnyConstructor& rightCtor = right.asAnyConstructor();
57             const auto leftSpan = leftCtor.argumentSpan();
58             const auto rightSpan = rightCtor.argumentSpan();
59             if (leftSpan.size() != rightSpan.size()) {
60                 return false;
61             }
62             for (size_t index = 0; index < leftSpan.size(); ++index) {
63                 if (!IsSameExpressionTree(*leftSpan[index], *rightSpan[index])) {
64                     return false;
65                 }
66             }
67             return true;
68         }
69         case Expression::Kind::kFieldAccess:
70             return left.as<FieldAccess>().fieldIndex() == right.as<FieldAccess>().fieldIndex() &&
71                    IsSameExpressionTree(*left.as<FieldAccess>().base(),
72                                         *right.as<FieldAccess>().base());
73 
74         case Expression::Kind::kIndex:
75             return IsSameExpressionTree(*left.as<IndexExpression>().index(),
76                                         *right.as<IndexExpression>().index()) &&
77                    IsSameExpressionTree(*left.as<IndexExpression>().base(),
78                                         *right.as<IndexExpression>().base());
79 
80         case Expression::Kind::kPrefix:
81             return (left.as<PrefixExpression>().getOperator().kind() ==
82                     right.as<PrefixExpression>().getOperator().kind()) &&
83                    IsSameExpressionTree(*left.as<PrefixExpression>().operand(),
84                                         *right.as<PrefixExpression>().operand());
85 
86         case Expression::Kind::kSwizzle:
87             return left.as<Swizzle>().components() == right.as<Swizzle>().components() &&
88                    IsSameExpressionTree(*left.as<Swizzle>().base(), *right.as<Swizzle>().base());
89 
90         case Expression::Kind::kVariableReference:
91             return left.as<VariableReference>().variable() ==
92                    right.as<VariableReference>().variable();
93 
94         default:
95             return false;
96     }
97 }
98 
99 }  // namespace SkSL
100