xref: /aosp_15_r20/external/skia/src/sksl/ir/SkSLLiteral.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2016 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SKSL_FLOATLITERAL
9*c8dee2aaSAndroid Build Coastguard Worker #define SKSL_FLOATLITERAL
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLBuiltinTypes.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLContext.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLDefines.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLPosition.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLExpression.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLIRNode.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLType.h"
19*c8dee2aaSAndroid Build Coastguard Worker 
20*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
21*c8dee2aaSAndroid Build Coastguard Worker #include <cinttypes>
22*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
23*c8dee2aaSAndroid Build Coastguard Worker #include <optional>
24*c8dee2aaSAndroid Build Coastguard Worker #include <string>
25*c8dee2aaSAndroid Build Coastguard Worker 
26*c8dee2aaSAndroid Build Coastguard Worker namespace SkSL {
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker enum class OperatorPrecedence : uint8_t;
29*c8dee2aaSAndroid Build Coastguard Worker 
30*c8dee2aaSAndroid Build Coastguard Worker /**
31*c8dee2aaSAndroid Build Coastguard Worker  * A literal value. These can contain ints, floats, or booleans.
32*c8dee2aaSAndroid Build Coastguard Worker  */
33*c8dee2aaSAndroid Build Coastguard Worker 
34*c8dee2aaSAndroid Build Coastguard Worker class Literal : public Expression {
35*c8dee2aaSAndroid Build Coastguard Worker public:
36*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr Kind kIRNodeKind = Kind::kLiteral;
37*c8dee2aaSAndroid Build Coastguard Worker 
Literal(Position pos,double value,const Type * type)38*c8dee2aaSAndroid Build Coastguard Worker     Literal(Position pos, double value, const Type* type)
39*c8dee2aaSAndroid Build Coastguard Worker         : INHERITED(pos, kIRNodeKind, type)
40*c8dee2aaSAndroid Build Coastguard Worker         , fValue(value) {}
41*c8dee2aaSAndroid Build Coastguard Worker 
42*c8dee2aaSAndroid Build Coastguard Worker     // Makes a literal of $floatLiteral type.
MakeFloat(const Context & context,Position pos,float value)43*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<Literal> MakeFloat(const Context& context, Position pos, float value) {
44*c8dee2aaSAndroid Build Coastguard Worker         return std::make_unique<Literal>(pos, value, context.fTypes.fFloatLiteral.get());
45*c8dee2aaSAndroid Build Coastguard Worker     }
46*c8dee2aaSAndroid Build Coastguard Worker 
47*c8dee2aaSAndroid Build Coastguard Worker     // Makes a float literal of the specified type.
MakeFloat(Position pos,float value,const Type * type)48*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<Literal> MakeFloat(Position pos, float value, const Type* type) {
49*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(type->isFloat());
50*c8dee2aaSAndroid Build Coastguard Worker         return std::make_unique<Literal>(pos, value, type);
51*c8dee2aaSAndroid Build Coastguard Worker     }
52*c8dee2aaSAndroid Build Coastguard Worker 
53*c8dee2aaSAndroid Build Coastguard Worker     // Makes a literal of $intLiteral type.
MakeInt(const Context & context,Position pos,SKSL_INT value)54*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<Literal> MakeInt(const Context& context, Position pos, SKSL_INT value) {
55*c8dee2aaSAndroid Build Coastguard Worker         return std::make_unique<Literal>(pos, value, context.fTypes.fIntLiteral.get());
56*c8dee2aaSAndroid Build Coastguard Worker     }
57*c8dee2aaSAndroid Build Coastguard Worker 
58*c8dee2aaSAndroid Build Coastguard Worker     // Makes an int literal of the specified type.
MakeInt(Position pos,SKSL_INT value,const Type * type)59*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<Literal> MakeInt(Position pos, SKSL_INT value, const Type* type) {
60*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(type->isInteger());
61*c8dee2aaSAndroid Build Coastguard Worker         SkASSERTF(value >= type->minimumValue(), "Value %" PRId64 " does not fit in type %s",
62*c8dee2aaSAndroid Build Coastguard Worker                                                  value, type->description().c_str());
63*c8dee2aaSAndroid Build Coastguard Worker         SkASSERTF(value <= type->maximumValue(), "Value %" PRId64 " does not fit in type %s",
64*c8dee2aaSAndroid Build Coastguard Worker                                                  value, type->description().c_str());
65*c8dee2aaSAndroid Build Coastguard Worker         return std::make_unique<Literal>(pos, value, type);
66*c8dee2aaSAndroid Build Coastguard Worker     }
67*c8dee2aaSAndroid Build Coastguard Worker 
68*c8dee2aaSAndroid Build Coastguard Worker     // Makes a literal of boolean type.
MakeBool(const Context & context,Position pos,bool value)69*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<Literal> MakeBool(const Context& context, Position pos, bool value) {
70*c8dee2aaSAndroid Build Coastguard Worker         return std::make_unique<Literal>(pos, value, context.fTypes.fBool.get());
71*c8dee2aaSAndroid Build Coastguard Worker     }
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker     // Makes a literal of boolean type. (Functionally identical to the above, but useful if you
74*c8dee2aaSAndroid Build Coastguard Worker     // don't have access to the Context.)
MakeBool(Position pos,bool value,const Type * type)75*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<Literal> MakeBool(Position pos, bool value, const Type* type) {
76*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(type->isBoolean());
77*c8dee2aaSAndroid Build Coastguard Worker         return std::make_unique<Literal>(pos, value, type);
78*c8dee2aaSAndroid Build Coastguard Worker     }
79*c8dee2aaSAndroid Build Coastguard Worker 
80*c8dee2aaSAndroid Build Coastguard Worker     // Makes a literal of the specified type, rounding as needed.
Make(Position pos,double value,const Type * type)81*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<Literal> Make(Position pos, double value, const Type* type) {
82*c8dee2aaSAndroid Build Coastguard Worker         if (type->isFloat()) {
83*c8dee2aaSAndroid Build Coastguard Worker             return MakeFloat(pos, value, type);
84*c8dee2aaSAndroid Build Coastguard Worker         }
85*c8dee2aaSAndroid Build Coastguard Worker         if (type->isInteger()) {
86*c8dee2aaSAndroid Build Coastguard Worker             return MakeInt(pos, value, type);
87*c8dee2aaSAndroid Build Coastguard Worker         }
88*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(type->isBoolean());
89*c8dee2aaSAndroid Build Coastguard Worker         return MakeBool(pos, value, type);
90*c8dee2aaSAndroid Build Coastguard Worker     }
91*c8dee2aaSAndroid Build Coastguard Worker 
floatValue()92*c8dee2aaSAndroid Build Coastguard Worker     float floatValue() const {
93*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->type().isFloat());
94*c8dee2aaSAndroid Build Coastguard Worker         return (SKSL_FLOAT)fValue;
95*c8dee2aaSAndroid Build Coastguard Worker     }
96*c8dee2aaSAndroid Build Coastguard Worker 
intValue()97*c8dee2aaSAndroid Build Coastguard Worker     SKSL_INT intValue() const {
98*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->type().isInteger());
99*c8dee2aaSAndroid Build Coastguard Worker         return (SKSL_INT)fValue;
100*c8dee2aaSAndroid Build Coastguard Worker     }
101*c8dee2aaSAndroid Build Coastguard Worker 
boolValue()102*c8dee2aaSAndroid Build Coastguard Worker     SKSL_INT boolValue() const {
103*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->type().isBoolean());
104*c8dee2aaSAndroid Build Coastguard Worker         return (bool)fValue;
105*c8dee2aaSAndroid Build Coastguard Worker     }
106*c8dee2aaSAndroid Build Coastguard Worker 
value()107*c8dee2aaSAndroid Build Coastguard Worker     double value() const {
108*c8dee2aaSAndroid Build Coastguard Worker         return fValue;
109*c8dee2aaSAndroid Build Coastguard Worker     }
110*c8dee2aaSAndroid Build Coastguard Worker 
description(OperatorPrecedence)111*c8dee2aaSAndroid Build Coastguard Worker     std::string description(OperatorPrecedence) const override;
112*c8dee2aaSAndroid Build Coastguard Worker 
113*c8dee2aaSAndroid Build Coastguard Worker     ComparisonResult compareConstant(const Expression& other) const override {
114*c8dee2aaSAndroid Build Coastguard Worker         if (!other.is<Literal>() || this->type().numberKind() != other.type().numberKind()) {
115*c8dee2aaSAndroid Build Coastguard Worker             return ComparisonResult::kUnknown;
116*c8dee2aaSAndroid Build Coastguard Worker         }
117*c8dee2aaSAndroid Build Coastguard Worker         return this->value() == other.as<Literal>().value()
118*c8dee2aaSAndroid Build Coastguard Worker                        ? ComparisonResult::kEqual
119*c8dee2aaSAndroid Build Coastguard Worker                        : ComparisonResult::kNotEqual;
120*c8dee2aaSAndroid Build Coastguard Worker     }
121*c8dee2aaSAndroid Build Coastguard Worker 
clone(Position pos)122*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<Expression> clone(Position pos) const override {
123*c8dee2aaSAndroid Build Coastguard Worker         return std::make_unique<Literal>(pos, this->value(), &this->type());
124*c8dee2aaSAndroid Build Coastguard Worker     }
125*c8dee2aaSAndroid Build Coastguard Worker 
supportsConstantValues()126*c8dee2aaSAndroid Build Coastguard Worker     bool supportsConstantValues() const override {
127*c8dee2aaSAndroid Build Coastguard Worker         return true;
128*c8dee2aaSAndroid Build Coastguard Worker     }
129*c8dee2aaSAndroid Build Coastguard Worker 
getConstantValue(int n)130*c8dee2aaSAndroid Build Coastguard Worker     std::optional<double> getConstantValue(int n) const override {
131*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(n == 0);
132*c8dee2aaSAndroid Build Coastguard Worker         return fValue;
133*c8dee2aaSAndroid Build Coastguard Worker     }
134*c8dee2aaSAndroid Build Coastguard Worker 
135*c8dee2aaSAndroid Build Coastguard Worker private:
136*c8dee2aaSAndroid Build Coastguard Worker     double fValue;
137*c8dee2aaSAndroid Build Coastguard Worker 
138*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = Expression;
139*c8dee2aaSAndroid Build Coastguard Worker };
140*c8dee2aaSAndroid Build Coastguard Worker 
141*c8dee2aaSAndroid Build Coastguard Worker }  // namespace SkSL
142*c8dee2aaSAndroid Build Coastguard Worker 
143*c8dee2aaSAndroid Build Coastguard Worker #endif
144