Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | Static Public Attributes | List of all members
SkSL::ForStatement Class Referencefinal

#include <SkSLForStatement.h>

Inheritance diagram for SkSL::ForStatement:
SkSL::Statement SkSL::IRNode SkSL::Poolable

Public Member Functions

 ForStatement (Position pos, ForLoopPositions forLoopPositions, std::unique_ptr< Statement > initializer, std::unique_ptr< Expression > test, std::unique_ptr< Expression > next, std::unique_ptr< Statement > statement, std::unique_ptr< LoopUnrollInfo > unrollInfo, std::unique_ptr< SymbolTable > symbols)
 
ForLoopPositions forLoopPositions () const
 
std::unique_ptr< Statement > & initializer ()
 
const std::unique_ptr< Statement > & initializer () const
 
std::unique_ptr< Expression > & test ()
 
const std::unique_ptr< Expression > & test () const
 
std::unique_ptr< Expression > & next ()
 
const std::unique_ptr< Expression > & next () const
 
std::unique_ptr< Statement > & statement ()
 
const std::unique_ptr< Statement > & statement () const
 
SymbolTablesymbols () const
 
const LoopUnrollInfounrollInfo () const
 
std::string description () const override
 
- Public Member Functions inherited from SkSL::Statement
 Statement (Position pos, Kind kind)
 
Kind kind () const
 
virtual bool isEmpty () const
 
- 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< StatementConvert (const Context &context, Position pos, ForLoopPositions forLoopPositions, std::unique_ptr< Statement > initializer, std::unique_ptr< Expression > test, std::unique_ptr< Expression > next, std::unique_ptr< Statement > statement, std::unique_ptr< SymbolTable > symbolTable)
 
static std::unique_ptr< StatementConvertWhile (const Context &context, Position pos, std::unique_ptr< Expression > test, std::unique_ptr< Statement > statement)
 
static std::unique_ptr< StatementMake (const Context &context, Position pos, ForLoopPositions forLoopPositions, std::unique_ptr< Statement > initializer, std::unique_ptr< Expression > test, std::unique_ptr< Expression > next, std::unique_ptr< Statement > statement, std::unique_ptr< LoopUnrollInfo > unrollInfo, std::unique_ptr< SymbolTable > symbolTable)
 
- 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::kFor
 

Additional Inherited Members

- Public Types inherited from SkSL::Statement
using Kind = StatementKind
 
- 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

A 'for' statement.

Definition at line 39 of file SkSLForStatement.h.

Constructor & Destructor Documentation

◆ ForStatement()

SkSL::ForStatement::ForStatement ( Position  pos,
ForLoopPositions  forLoopPositions,
std::unique_ptr< Statement initializer,
std::unique_ptr< Expression test,
std::unique_ptr< Expression next,
std::unique_ptr< Statement statement,
std::unique_ptr< LoopUnrollInfo unrollInfo,
std::unique_ptr< SymbolTable symbols 
)
inline

Definition at line 43 of file SkSLForStatement.h.

51 : INHERITED(pos, kIRNodeKind)
52 , fForLoopPositions(forLoopPositions)
53 , fSymbolTable(std::move(symbols))
54 , fInitializer(std::move(initializer))
55 , fTest(std::move(test))
56 , fNext(std::move(next))
57 , fStatement(std::move(statement))
58 , fUnrollInfo(std::move(unrollInfo)) {}
SkPoint pos
std::unique_ptr< Statement > & statement()
std::unique_ptr< Expression > & next()
static constexpr Kind kIRNodeKind
std::unique_ptr< Statement > & initializer()
SymbolTable * symbols() const
const LoopUnrollInfo * unrollInfo() const
ForLoopPositions forLoopPositions() const

Member Function Documentation

◆ Convert()

std::unique_ptr< Statement > SkSL::ForStatement::Convert ( const Context context,
Position  pos,
ForLoopPositions  forLoopPositions,
std::unique_ptr< Statement initializer,
std::unique_ptr< Expression test,
std::unique_ptr< Expression next,
std::unique_ptr< Statement statement,
std::unique_ptr< SymbolTable symbolTable 
)
static

Definition at line 102 of file SkSLForStatement.cpp.

109 {
110 bool isSimpleInitializer = is_simple_initializer(initializer.get());
111 bool isVardeclBlockInitializer = !isSimpleInitializer &&
113
114 if (!isSimpleInitializer && !isVardeclBlockInitializer) {
115 context.fErrors->error(initializer->fPosition, "invalid for loop initializer");
116 return nullptr;
117 }
118
119 if (test) {
120 test = context.fTypes.fBool->coerceExpression(std::move(test), context);
121 if (!test) {
122 return nullptr;
123 }
124 }
125
126 // The type of the next-expression doesn't matter, but it needs to be a complete expression.
127 // Report an error on intermediate expressions like FunctionReference or TypeReference.
128 if (next && next->isIncomplete(context)) {
129 return nullptr;
130 }
131
132 std::unique_ptr<LoopUnrollInfo> unrollInfo;
133 if (context.fConfig->strictES2Mode()) {
134 // In strict-ES2, loops must be unrollable or it's an error.
135 unrollInfo = Analysis::GetLoopUnrollInfo(context, pos, positions, initializer.get(), &test,
136 next.get(), statement.get(), context.fErrors);
137 if (!unrollInfo) {
138 return nullptr;
139 }
140 } else {
141 // In ES3, loops don't have to be unrollable, but we can use the unroll information for
142 // optimization purposes.
143 unrollInfo = Analysis::GetLoopUnrollInfo(context, pos, positions, initializer.get(), &test,
144 next.get(), statement.get(), /*errors=*/nullptr);
145 }
146
148 return nullptr;
149 }
150
151 if (isVardeclBlockInitializer) {
152 // If the initializer statement of a for loop contains multiple variables, this causes
153 // difficulties for several of our backends; e.g. Metal doesn't have a way to express arrays
154 // of different size in the same decl-stmt, because the array-size is part of the type. It's
155 // conceptually equivalent to synthesize a scope, declare the variables, and then emit a for
156 // statement with an empty init-stmt. (Note that we can't just do this transformation
157 // unilaterally for all for-statements, because the resulting for loop isn't ES2-compliant.)
158 std::unique_ptr<SymbolTable> hoistedSymbols = symbolTable->insertNewParent();
160 symbolTable.get(), hoistedSymbols.get());
161 StatementArray scope;
162 scope.push_back(std::move(initializer));
163 scope.push_back(ForStatement::Make(context,
164 pos,
165 positions,
166 /*initializer=*/nullptr,
167 std::move(test),
168 std::move(next),
169 std::move(statement),
170 std::move(unrollInfo),
171 std::move(symbolTable)));
172 return Block::Make(pos,
173 std::move(scope),
174 Block::Kind::kBracedScope,
175 std::move(hoistedSymbols));
176 }
177
178 return ForStatement::Make(context,
179 pos,
180 positions,
181 std::move(initializer),
182 std::move(test),
183 std::move(next),
184 std::move(statement),
185 std::move(unrollInfo),
186 std::move(symbolTable));
187}
static std::unique_ptr< Statement > Make(Position pos, StatementArray statements, Kind kind=Kind::kBracedScope, std::unique_ptr< SymbolTable > symbols=nullptr)
Definition: SkSLBlock.cpp:14
static std::unique_ptr< Statement > Make(const Context &context, Position pos, ForLoopPositions forLoopPositions, std::unique_ptr< Statement > initializer, std::unique_ptr< Expression > test, std::unique_ptr< Expression > next, std::unique_ptr< Statement > statement, std::unique_ptr< LoopUnrollInfo > unrollInfo, std::unique_ptr< SymbolTable > symbolTable)
std::unique_ptr< LoopUnrollInfo > GetLoopUnrollInfo(const Context &context, Position pos, const ForLoopPositions &positions, const Statement *loopInitializer, std::unique_ptr< Expression > *loopTestPtr, const Expression *loopNext, const Statement *loopStatement, ErrorReporter *errors)
bool DetectVarDeclarationWithoutScope(const Statement &stmt, ErrorReporter *errors=nullptr)
static bool is_vardecl_block_initializer(const Statement *stmt)
skia_private::STArray< 2, std::unique_ptr< Statement > > StatementArray
Definition: SkSLDefines.h:32
static bool is_simple_initializer(const Statement *stmt)
static void hoist_vardecl_symbols_into_outer_scope(const Context &context, const Block &initBlock, SymbolTable *innerSymbols, SymbolTable *hoistedSymbols)

◆ ConvertWhile()

std::unique_ptr< Statement > SkSL::ForStatement::ConvertWhile ( const Context context,
Position  pos,
std::unique_ptr< Expression test,
std::unique_ptr< Statement statement 
)
static

Definition at line 189 of file SkSLForStatement.cpp.

192 {
193 if (context.fConfig->strictES2Mode()) {
194 context.fErrors->error(pos, "while loops are not supported");
195 return nullptr;
196 }
197 return ForStatement::Convert(context,
198 pos,
199 ForLoopPositions(),
200 /*initializer=*/nullptr,
201 std::move(test),
202 /*next=*/nullptr,
203 std::move(statement),
204 /*symbolTable=*/nullptr);
205}
static std::unique_ptr< Statement > Convert(const Context &context, Position pos, ForLoopPositions forLoopPositions, std::unique_ptr< Statement > initializer, std::unique_ptr< Expression > test, std::unique_ptr< Expression > next, std::unique_ptr< Statement > statement, std::unique_ptr< SymbolTable > symbolTable)

◆ description()

std::string SkSL::ForStatement::description ( ) const
overridevirtual

Implements SkSL::IRNode.

Definition at line 51 of file SkSLForStatement.cpp.

51 {
52 std::string result("for (");
53 if (this->initializer()) {
54 result += this->initializer()->description();
55 } else {
56 result += ";";
57 }
58 result += " ";
59 if (this->test()) {
60 result += this->test()->description();
61 }
62 result += "; ";
63 if (this->next()) {
64 result += this->next()->description();
65 }
66 result += ") " + this->statement()->description();
67 return result;
68}
std::unique_ptr< Expression > & test()
GAsyncResult * result

◆ forLoopPositions()

ForLoopPositions SkSL::ForStatement::forLoopPositions ( ) const
inline

Definition at line 87 of file SkSLForStatement.h.

87 {
88 return fForLoopPositions;
89 }

◆ initializer() [1/2]

std::unique_ptr< Statement > & SkSL::ForStatement::initializer ( )
inline

Definition at line 91 of file SkSLForStatement.h.

91 {
92 return fInitializer;
93 }

◆ initializer() [2/2]

const std::unique_ptr< Statement > & SkSL::ForStatement::initializer ( ) const
inline

Definition at line 95 of file SkSLForStatement.h.

95 {
96 return fInitializer;
97 }

◆ Make()

std::unique_ptr< Statement > SkSL::ForStatement::Make ( const Context context,
Position  pos,
ForLoopPositions  forLoopPositions,
std::unique_ptr< Statement initializer,
std::unique_ptr< Expression test,
std::unique_ptr< Expression next,
std::unique_ptr< Statement statement,
std::unique_ptr< LoopUnrollInfo unrollInfo,
std::unique_ptr< SymbolTable symbolTable 
)
static

Definition at line 207 of file SkSLForStatement.cpp.

215 {
218 SkASSERT(!test || test->type().matches(*context.fTypes.fBool));
220 SkASSERT(unrollInfo || !context.fConfig->strictES2Mode());
221
222 // Unrollable loops are easy to optimize because we know initializer, test and next don't have
223 // interesting side effects.
224 if (unrollInfo) {
225 // A zero-iteration unrollable loop can be replaced with Nop.
226 // An unrollable loop with an empty body can be replaced with Nop.
227 if (unrollInfo->fCount <= 0 || statement->isEmpty()) {
228 return Nop::Make();
229 }
230 }
231
232 return std::make_unique<ForStatement>(pos,
233 positions,
234 std::move(initializer),
235 std::move(test),
236 std::move(next),
237 std::move(statement),
238 std::move(unrollInfo),
239 std::move(symbolTable));
240}
#define SkASSERT(cond)
Definition: SkAssert.h:116
static std::unique_ptr< Statement > Make()
Definition: SkSLNop.h:26

◆ next() [1/2]

std::unique_ptr< Expression > & SkSL::ForStatement::next ( )
inline

Definition at line 107 of file SkSLForStatement.h.

107 {
108 return fNext;
109 }

◆ next() [2/2]

const std::unique_ptr< Expression > & SkSL::ForStatement::next ( ) const
inline

Definition at line 111 of file SkSLForStatement.h.

111 {
112 return fNext;
113 }

◆ statement() [1/2]

std::unique_ptr< Statement > & SkSL::ForStatement::statement ( )
inline

Definition at line 115 of file SkSLForStatement.h.

115 {
116 return fStatement;
117 }

◆ statement() [2/2]

const std::unique_ptr< Statement > & SkSL::ForStatement::statement ( ) const
inline

Definition at line 119 of file SkSLForStatement.h.

119 {
120 return fStatement;
121 }

◆ symbols()

SymbolTable * SkSL::ForStatement::symbols ( ) const
inline

Definition at line 123 of file SkSLForStatement.h.

123 {
124 return fSymbolTable.get();
125 }

◆ test() [1/2]

std::unique_ptr< Expression > & SkSL::ForStatement::test ( )
inline

Definition at line 99 of file SkSLForStatement.h.

99 {
100 return fTest;
101 }

◆ test() [2/2]

const std::unique_ptr< Expression > & SkSL::ForStatement::test ( ) const
inline

Definition at line 103 of file SkSLForStatement.h.

103 {
104 return fTest;
105 }

◆ unrollInfo()

const LoopUnrollInfo * SkSL::ForStatement::unrollInfo ( ) const
inline

Loop-unroll information is only supported in strict-ES2 code. Null is returned in ES3+.

Definition at line 128 of file SkSLForStatement.h.

128 {
129 return fUnrollInfo.get();
130 }

Member Data Documentation

◆ kIRNodeKind

constexpr Kind SkSL::ForStatement::kIRNodeKind = Kind::kFor
inlinestaticconstexpr

Definition at line 41 of file SkSLForStatement.h.


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