1/*
2 * Copyright 2016 Google Inc.
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#ifndef SKSL_BINARYEXPRESSION
9#define SKSL_BINARYEXPRESSION
10
11#include "src/sksl/SkSLCompiler.h"
12#include "src/sksl/SkSLIRGenerator.h"
13#include "src/sksl/SkSLLexer.h"
14#include "src/sksl/ir/SkSLExpression.h"
15#include "src/sksl/ir/SkSLFieldAccess.h"
16#include "src/sksl/ir/SkSLIndexExpression.h"
17#include "src/sksl/ir/SkSLSwizzle.h"
18#include "src/sksl/ir/SkSLTernaryExpression.h"
19
20namespace SkSL {
21
22static inline bool check_ref(Expression* expr) {
23 switch (expr->fKind) {
24 case Expression::kExternalValue_Kind:
25 return true;
26 case Expression::kFieldAccess_Kind:
27 return check_ref(((FieldAccess*) expr)->fBase.get());
28 case Expression::kIndex_Kind:
29 return check_ref(((IndexExpression*) expr)->fBase.get());
30 case Expression::kSwizzle_Kind:
31 return check_ref(((Swizzle*) expr)->fBase.get());
32 case Expression::kTernary_Kind: {
33 TernaryExpression* t = (TernaryExpression*) expr;
34 return check_ref(t->fIfTrue.get()) && check_ref(t->fIfFalse.get());
35 }
36 case Expression::kVariableReference_Kind: {
37 VariableReference* ref = (VariableReference*) expr;
38 return ref->fRefKind == VariableReference::kWrite_RefKind ||
39 ref->fRefKind == VariableReference::kReadWrite_RefKind;
40 }
41 default:
42 return false;
43 }
44}
45
46/**
47 * A binary operation.
48 */
49struct BinaryExpression : public Expression {
50 BinaryExpression(int offset, std::unique_ptr<Expression> left, Token::Kind op,
51 std::unique_ptr<Expression> right, const Type& type)
52 : INHERITED(offset, kBinary_Kind, type)
53 , fLeft(std::move(left))
54 , fOperator(op)
55 , fRight(std::move(right)) {
56 // If we are assigning to a VariableReference, ensure that it is set to Write or ReadWrite
57 SkASSERT(!Compiler::IsAssignment(op) || check_ref(fLeft.get()));
58 }
59
60 bool isConstantOrUniform() const override {
61 return fLeft->isConstantOrUniform() && fRight->isConstantOrUniform();
62 }
63
64 std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
65 const DefinitionMap& definitions) override {
66 return irGenerator.constantFold(*fLeft,
67 fOperator,
68 *fRight);
69 }
70
71 bool hasProperty(Property property) const override {
72 if (property == Property::kSideEffects && Compiler::IsAssignment(fOperator)) {
73 return true;
74 }
75 return fLeft->hasProperty(property) || fRight->hasProperty(property);
76 }
77
78 int nodeCount() const override {
79 return 1 + fLeft->nodeCount() + fRight->nodeCount();
80 }
81
82 std::unique_ptr<Expression> clone() const override {
83 return std::unique_ptr<Expression>(new BinaryExpression(fOffset, fLeft->clone(), fOperator,
84 fRight->clone(), fType));
85 }
86
87 String description() const override {
88 return "(" + fLeft->description() + " " + Compiler::OperatorName(fOperator) + " " +
89 fRight->description() + ")";
90 }
91
92 std::unique_ptr<Expression> fLeft;
93 const Token::Kind fOperator;
94 std::unique_ptr<Expression> fRight;
95
96 typedef Expression INHERITED;
97};
98
99} // namespace SkSL
100
101#endif
102