Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Public Types | Public Member Functions | Static Public Member Functions | Static Public Attributes | List of all members
SkSL::IndexExpression Class Referencefinal

#include <SkSLIndexExpression.h>

Inheritance diagram for SkSL::IndexExpression:
SkSL::Expression SkSL::IRNode SkSL::Poolable

Public Types

using INHERITED = Expression
 
- Public Types inherited from SkSL::Expression
enum class  ComparisonResult { kUnknown = -1 , kNotEqual , kEqual }
 
using Kind = ExpressionKind
 

Public Member Functions

 IndexExpression (const Context &context, Position pos, std::unique_ptr< Expression > base, std::unique_ptr< Expression > index)
 
std::unique_ptr< Expression > & base ()
 
const std::unique_ptr< Expression > & base () const
 
std::unique_ptr< Expression > & index ()
 
const std::unique_ptr< Expression > & index () const
 
std::unique_ptr< Expressionclone (Position pos) const override
 
std::string description (OperatorPrecedence) const override
 
- Public Member Functions inherited from SkSL::Expression
 Expression (Position pos, Kind kind, const Type *type)
 
Kind kind () const
 
const Typetype () const
 
bool isAnyConstructor () const
 
bool isIntLiteral () const
 
bool isFloatLiteral () const
 
bool isBoolLiteral () const
 
AnyConstructorasAnyConstructor ()
 
const AnyConstructorasAnyConstructor () const
 
bool isIncomplete (const Context &context) const
 
virtual ComparisonResult compareConstant (const Expression &other) const
 
CoercionCost coercionCost (const Type &target) const
 
virtual bool supportsConstantValues () const
 
virtual std::optional< double > getConstantValue (int n) const
 
virtual std::unique_ptr< Expressionclone (Position pos) const =0
 
std::unique_ptr< Expressionclone () const
 
std::string description () const final
 
virtual std::string description (OperatorPrecedence parentPrecedence) const =0
 
- Public Member Functions inherited from SkSL::IRNode
virtual ~IRNode ()
 
virtual std::string description () const =0
 
 IRNode (const IRNode &)=delete
 
IRNodeoperator= (const IRNode &)=delete
 
Position position () const
 
void setPosition (Position p)
 
template<typename T >
bool is () const
 
template<typename T >
const Tas () const
 
template<typename T >
Tas ()
 

Static Public Member Functions

static std::unique_ptr< ExpressionConvert (const Context &context, Position pos, std::unique_ptr< Expression > base, std::unique_ptr< Expression > index)
 
static std::unique_ptr< ExpressionMake (const Context &context, Position pos, std::unique_ptr< Expression > base, std::unique_ptr< Expression > index)
 
static const TypeIndexType (const Context &context, const Type &type)
 
- Static Public Member Functions inherited from SkSL::Poolable
static void * operator new (const size_t size)
 
static void operator delete (void *ptr)
 

Static Public Attributes

static constexpr Kind kIRNodeKind = Kind::kIndex
 

Additional Inherited Members

- Public Attributes inherited from SkSL::IRNode
Position fPosition
 
- Protected Member Functions inherited from SkSL::IRNode
 IRNode (Position position, int kind)
 
- Protected Attributes inherited from SkSL::IRNode
int fKind
 

Detailed Description

An expression which extracts a value from an array, vector or matrix, as in 'm[2]'.

Definition at line 29 of file SkSLIndexExpression.h.

Member Typedef Documentation

◆ INHERITED

Definition at line 80 of file SkSLIndexExpression.h.

Constructor & Destructor Documentation

◆ IndexExpression()

SkSL::IndexExpression::IndexExpression ( const Context context,
Position  pos,
std::unique_ptr< Expression base,
std::unique_ptr< Expression index 
)
inline

Definition at line 33 of file SkSLIndexExpression.h.

35 : INHERITED(pos, kIRNodeKind, &IndexType(context, base->type()))
36 , fBase(std::move(base))
37 , fIndex(std::move(index)) {}
SkPoint pos
static constexpr Kind kIRNodeKind
static const Type & IndexType(const Context &context, const Type &type)
std::unique_ptr< Expression > & index()

Member Function Documentation

◆ base() [1/2]

std::unique_ptr< Expression > & SkSL::IndexExpression::base ( )
inline

Definition at line 56 of file SkSLIndexExpression.h.

56 {
57 return fBase;
58 }

◆ base() [2/2]

const std::unique_ptr< Expression > & SkSL::IndexExpression::base ( ) const
inline

Definition at line 60 of file SkSLIndexExpression.h.

60 {
61 return fBase;
62 }

◆ clone()

std::unique_ptr< Expression > SkSL::IndexExpression::clone ( Position  pos) const
inlineoverridevirtual

Implements SkSL::Expression.

Definition at line 72 of file SkSLIndexExpression.h.

72 {
73 return std::unique_ptr<Expression>(new IndexExpression(pos, this->base()->clone(),
74 this->index()->clone(),
75 &this->type()));
76 }
std::unique_ptr< Expression > clone() const
const Type & type() const
std::unique_ptr< Expression > & base()
IndexExpression(const Context &context, Position pos, std::unique_ptr< Expression > base, std::unique_ptr< Expression > index)

◆ Convert()

std::unique_ptr< Expression > SkSL::IndexExpression::Convert ( const Context context,
Position  pos,
std::unique_ptr< Expression base,
std::unique_ptr< Expression index 
)
static

Definition at line 67 of file SkSLIndexExpression.cpp.

70 {
71 // Convert an array type reference: `int[10]`.
72 if (base->is<TypeReference>()) {
73 const Type& baseType = base->as<TypeReference>().value();
74 SKSL_INT arraySize = baseType.convertArraySize(context, pos, std::move(index));
75 if (!arraySize) {
76 return nullptr;
77 }
79 context,
80 pos,
81 context.fSymbolTable->addArrayDimension(context, &baseType, arraySize));
82 }
83 // Convert an index expression with an expression inside of it: `arr[a * 3]`.
84 const Type& baseType = base->type();
85 if (!baseType.isArray() && !baseType.isMatrix() && !baseType.isVector()) {
86 context.fErrors->error(base->fPosition,
87 "expected array, but found '" + baseType.displayName() + "'");
88 return nullptr;
89 }
90 if (!index->type().isInteger()) {
91 index = context.fTypes.fInt->coerceExpression(std::move(index), context);
92 if (!index) {
93 return nullptr;
94 }
95 }
96 // Perform compile-time bounds checking on constant-expression indices.
98 if (indexExpr->isIntLiteral()) {
99 SKSL_INT indexValue = indexExpr->as<Literal>().intValue();
100 if (index_out_of_range(context, index->fPosition, indexValue, *base)) {
101 return nullptr;
102 }
103 }
104 return IndexExpression::Make(context, pos, std::move(base), std::move(index));
105}
int64_t SKSL_INT
Definition: SkSLDefines.h:16
static const Expression * GetConstantValueForVariable(const Expression &value)
Expression(Position pos, Kind kind, const Type *type)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, std::unique_ptr< Expression > base, std::unique_ptr< Expression > index)
static std::unique_ptr< TypeReference > Convert(const Context &context, Position pos, const Type *type)
uint8_t value
static bool index_out_of_range(const Context &context, Position pos, SKSL_INT index, const Expression &base)

◆ description()

std::string SkSL::IndexExpression::description ( OperatorPrecedence  ) const
overridevirtual

Implements SkSL::Expression.

Definition at line 172 of file SkSLIndexExpression.cpp.

172 {
173 return this->base()->description(OperatorPrecedence::kPostfix) + "[" +
174 this->index()->description(OperatorPrecedence::kExpression) + "]";
175}

◆ index() [1/2]

std::unique_ptr< Expression > & SkSL::IndexExpression::index ( )
inline

Definition at line 64 of file SkSLIndexExpression.h.

64 {
65 return fIndex;
66 }

◆ index() [2/2]

const std::unique_ptr< Expression > & SkSL::IndexExpression::index ( ) const
inline

Definition at line 68 of file SkSLIndexExpression.h.

68 {
69 return fIndex;
70 }

◆ IndexType()

const Type & SkSL::IndexExpression::IndexType ( const Context context,
const Type type 
)
static

Given a type, returns the type that will result from extracting an array value from it.

Definition at line 46 of file SkSLIndexExpression.cpp.

46 {
47 if (type.isMatrix()) {
48 if (type.componentType().matches(*context.fTypes.fFloat)) {
49 switch (type.rows()) {
50 case 2: return *context.fTypes.fFloat2;
51 case 3: return *context.fTypes.fFloat3;
52 case 4: return *context.fTypes.fFloat4;
53 default: SkASSERT(false);
54 }
55 } else if (type.componentType().matches(*context.fTypes.fHalf)) {
56 switch (type.rows()) {
57 case 2: return *context.fTypes.fHalf2;
58 case 3: return *context.fTypes.fHalf3;
59 case 4: return *context.fTypes.fHalf4;
60 default: SkASSERT(false);
61 }
62 }
63 }
64 return type.componentType();
65}
#define SkASSERT(cond)
Definition: SkAssert.h:116
virtual int rows() const
Definition: SkSLType.h:438
virtual const Type & componentType() const
Definition: SkSLType.h:404
bool matches(const Type &other) const
Definition: SkSLType.h:269
virtual bool isMatrix() const
Definition: SkSLType.h:528

◆ Make()

std::unique_ptr< Expression > SkSL::IndexExpression::Make ( const Context context,
Position  pos,
std::unique_ptr< Expression base,
std::unique_ptr< Expression index 
)
static

Definition at line 107 of file SkSLIndexExpression.cpp.

110 {
111 const Type& baseType = base->type();
112 SkASSERT(baseType.isArray() || baseType.isMatrix() || baseType.isVector());
113 SkASSERT(index->type().isInteger());
114
116 if (indexExpr->isIntLiteral()) {
117 SKSL_INT indexValue = indexExpr->as<Literal>().intValue();
118 if (!index_out_of_range(context, index->fPosition, indexValue, *base)) {
119 if (baseType.isVector()) {
120 // Constant array indexes on vectors can be converted to swizzles: `v[2]` --> `v.z`.
121 // Swizzling is harmless and can unlock further simplifications for some base types.
122 return Swizzle::Make(context, pos, std::move(base),
123 ComponentArray{(int8_t)indexValue});
124 }
125
126 if (baseType.isArray() && !Analysis::HasSideEffects(*base)) {
127 // Indexing an constant array constructor with a constant index can just pluck out
128 // the requested value from the array.
130 if (baseExpr->is<ConstructorArray>()) {
131 const ConstructorArray& arrayCtor = baseExpr->as<ConstructorArray>();
132 const ExpressionArray& arguments = arrayCtor.arguments();
133 SkASSERT(arguments.size() == baseType.columns());
134
135 return arguments[indexValue]->clone(pos);
136 }
137 }
138
139 if (baseType.isMatrix() && !Analysis::HasSideEffects(*base)) {
140 // Matrices can be constructed with vectors that don't line up on column boundaries,
141 // so extracting out the values from the constructor can be tricky. Fortunately, we
142 // can reconstruct an equivalent vector using `getConstantValue`. If we
143 // can't extract the data using `getConstantValue`, it wasn't constant and
144 // we're not obligated to simplify anything.
146 int vecWidth = baseType.rows();
147 const Type& vecType = baseType.columnType(context);
148 indexValue *= vecWidth;
149
150 double ctorArgs[4];
151 bool allConstant = true;
152 for (int slot = 0; slot < vecWidth; ++slot) {
153 std::optional<double> slotVal = baseExpr->getConstantValue(indexValue + slot);
154 if (slotVal.has_value()) {
155 ctorArgs[slot] = *slotVal;
156 } else {
157 allConstant = false;
158 break;
159 }
160 }
161
162 if (allConstant) {
163 return ConstructorCompound::MakeFromConstants(context, pos, vecType, ctorArgs);
164 }
165 }
166 }
167 }
168
169 return std::make_unique<IndexExpression>(context, pos, std::move(base), std::move(index));
170}
static std::unique_ptr< Expression > MakeFromConstants(const Context &context, Position pos, const Type &type, const double values[])
static std::unique_ptr< Expression > Make(const Context &context, Position pos, std::unique_ptr< Expression > expr, ComponentArray inComponents)
bool HasSideEffects(const Expression &expr)
skia_private::FixedArray< 4, int8_t > ComponentArray
Definition: SkSLSwizzle.h:46

Member Data Documentation

◆ kIRNodeKind

constexpr Kind SkSL::IndexExpression::kIRNodeKind = Kind::kIndex
inlinestaticconstexpr

Definition at line 31 of file SkSLIndexExpression.h.


The documentation for this class was generated from the following files: