Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Static Public Attributes | List of all members
SkSL::SwitchStatement Class Referencefinal

#include <SkSLSwitchStatement.h>

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

Public Member Functions

 SwitchStatement (Position pos, std::unique_ptr< Expression > value, std::unique_ptr< Statement > caseBlock)
 
std::unique_ptr< Expression > & value ()
 
const std::unique_ptr< Expression > & value () const
 
std::unique_ptr< Statement > & caseBlock ()
 
const std::unique_ptr< Statement > & caseBlock () const
 
StatementArraycases ()
 
const StatementArraycases () 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 ()
 
 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, std::unique_ptr< Expression > value, ExpressionArray caseValues, StatementArray caseStatements, std::unique_ptr< SymbolTable > symbolTable)
 
static std::unique_ptr< StatementMake (const Context &context, Position pos, std::unique_ptr< Expression > value, std::unique_ptr< Statement > caseBlock)
 
- 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::kSwitch
 

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 'switch' statement.

Definition at line 30 of file SkSLSwitchStatement.h.

Constructor & Destructor Documentation

◆ SwitchStatement()

SkSL::SwitchStatement::SwitchStatement ( Position  pos,
std::unique_ptr< Expression value,
std::unique_ptr< Statement caseBlock 
)
inline

Definition at line 34 of file SkSLSwitchStatement.h.

37 : INHERITED(pos, kIRNodeKind)
38 , fValue(std::move(value))
39 , fCaseBlock(std::move(caseBlock)) {}
SkPoint pos
std::unique_ptr< Expression > & value()
static constexpr Kind kIRNodeKind
std::unique_ptr< Statement > & caseBlock()

Member Function Documentation

◆ caseBlock() [1/2]

std::unique_ptr< Statement > & SkSL::SwitchStatement::caseBlock ( )
inline

Definition at line 66 of file SkSLSwitchStatement.h.

66 {
67 return fCaseBlock;
68 }

◆ caseBlock() [2/2]

const std::unique_ptr< Statement > & SkSL::SwitchStatement::caseBlock ( ) const
inline

Definition at line 70 of file SkSLSwitchStatement.h.

70 {
71 return fCaseBlock;
72 }

◆ cases() [1/2]

StatementArray & SkSL::SwitchStatement::cases ( )
inline

Definition at line 74 of file SkSLSwitchStatement.h.

74 {
75 return fCaseBlock->as<Block>().children();
76 }

◆ cases() [2/2]

const StatementArray & SkSL::SwitchStatement::cases ( ) const
inline

Definition at line 78 of file SkSLSwitchStatement.h.

78 {
79 return fCaseBlock->as<Block>().children();
80 }

◆ Convert()

std::unique_ptr< Statement > SkSL::SwitchStatement::Convert ( const Context context,
Position  pos,
std::unique_ptr< Expression value,
ExpressionArray  caseValues,
StatementArray  caseStatements,
std::unique_ptr< SymbolTable symbolTable 
)
static

Definition at line 148 of file SkSLSwitchStatement.cpp.

153 {
154 SkASSERT(caseValues.size() == caseStatements.size());
155
156 value = context.fTypes.fInt->coerceExpression(std::move(value), context);
157 if (!value) {
158 return nullptr;
159 }
160
162 for (int i = 0; i < caseValues.size(); ++i) {
163 if (caseValues[i]) {
164 Position casePos = caseValues[i]->fPosition;
165 // Case values must be constant integers of the same type as the switch value
166 std::unique_ptr<Expression> caseValue = value->type().coerceExpression(
167 std::move(caseValues[i]), context);
168 if (!caseValue) {
169 return nullptr;
170 }
171 SKSL_INT intValue;
172 if (!ConstantFolder::GetConstantInt(*caseValue, &intValue)) {
173 context.fErrors->error(casePos, "case value must be a constant integer");
174 return nullptr;
175 }
176 cases.push_back(SwitchCase::Make(casePos, intValue, std::move(caseStatements[i])));
177 } else {
178 cases.push_back(SwitchCase::MakeDefault(pos, std::move(caseStatements[i])));
179 }
180 }
181
182 // Detect duplicate `case` labels and report an error.
183 // (Using forward_list here to optimize for the common case of no results.)
184 std::forward_list<const SwitchCase*> duplicateCases = find_duplicate_case_values(cases);
185 if (!duplicateCases.empty()) {
186 duplicateCases.reverse();
187 for (const SwitchCase* sc : duplicateCases) {
188 if (sc->isDefault()) {
189 context.fErrors->error(sc->fPosition, "duplicate default case");
190 } else {
191 context.fErrors->error(sc->fPosition, "duplicate case value '" +
192 std::to_string(sc->value()) + "'");
193 }
194 }
195 return nullptr;
196 }
197
198 return SwitchStatement::Make(context,
199 pos,
200 std::move(value),
201 Block::MakeBlock(pos,
202 std::move(cases),
203 Block::Kind::kBracedScope,
204 std::move(symbolTable)));
205}
#define SkASSERT(cond)
Definition SkAssert.h:116
int64_t SKSL_INT
Definition SkSLDefines.h:16
static bool GetConstantInt(const Expression &value, SKSL_INT *out)
static std::unique_ptr< SwitchCase > MakeDefault(Position pos, std::unique_ptr< Statement > statement)
static std::unique_ptr< SwitchCase > Make(Position pos, SKSL_INT value, std::unique_ptr< Statement > statement)
static std::unique_ptr< Statement > Make(const Context &context, Position pos, std::unique_ptr< Expression > value, std::unique_ptr< Statement > caseBlock)
StatementArray & cases()
skia_private::STArray< 2, std::unique_ptr< Statement > > StatementArray
Definition SkSLDefines.h:34
static std::forward_list< const SwitchCase * > find_duplicate_case_values(const StatementArray &cases)

◆ description()

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

Implements SkSL::IRNode.

Definition at line 37 of file SkSLSwitchStatement.cpp.

37 {
38 return "switch (" + this->value()->description() + ") " + this->caseBlock()->description();
39}

◆ Make()

std::unique_ptr< Statement > SkSL::SwitchStatement::Make ( const Context context,
Position  pos,
std::unique_ptr< Expression value,
std::unique_ptr< Statement caseBlock 
)
static

Definition at line 207 of file SkSLSwitchStatement.cpp.

210 {
211 // Confirm that every statement in `cases` is a SwitchCase.
212 const StatementArray& cases = caseBlock->as<Block>().children();
213 SkASSERT(std::all_of(cases.begin(), cases.end(), [&](const std::unique_ptr<Statement>& stmt) {
214 return stmt->is<SwitchCase>();
215 }));
216
217 // Confirm that every switch-case value is unique.
219
220 // Flatten switch statements if we're optimizing, and the value is known
221 if (context.fConfig->fSettings.fOptimize) {
222 SKSL_INT switchValue;
223 if (ConstantFolder::GetConstantInt(*value, &switchValue)) {
224 SwitchCase* defaultCase = nullptr;
225 SwitchCase* matchingCase = nullptr;
226 for (const std::unique_ptr<Statement>& stmt : cases) {
227 SwitchCase& sc = stmt->as<SwitchCase>();
228 if (sc.isDefault()) {
229 defaultCase = &sc;
230 continue;
231 }
232
233 if (sc.value() == switchValue) {
234 matchingCase = &sc;
235 break;
236 }
237 }
238
239 if (!matchingCase) {
240 // No case value matches the switch value.
241 if (!defaultCase) {
242 // No default switch-case exists; the switch had no effect.
243 // We can eliminate the entire switch!
244 return Nop::Make();
245 }
246 // We had a default case; that's what we matched with.
247 matchingCase = defaultCase;
248 }
249
250 // Strip down our case block to contain only the matching case, if we can.
251 if (block_for_case(caseBlock.get(), matchingCase)) {
252 return caseBlock;
253 }
254 }
255 }
256
257 // The switch couldn't be optimized away; emit it normally.
258 auto stmt = std::make_unique<SwitchStatement>(pos, std::move(value), std::move(caseBlock));
259
260 // If a switch-case has variable declarations at its top level, we want to create a scoped block
261 // around the switch, then move the variable declarations out of the switch body and into the
262 // outer scope. This prevents scoping issues in backends which don't offer a native switch.
263 // (skia:14375)
264 return Transform::HoistSwitchVarDeclarationsAtTopLevel(context, std::move(stmt));
265}
static std::unique_ptr< Statement > Make()
Definition SkSLNop.h:26
EMSCRIPTEN_KEEPALIVE void empty()
std::unique_ptr< Statement > HoistSwitchVarDeclarationsAtTopLevel(const Context &, std::unique_ptr< SwitchStatement >)
static bool block_for_case(Statement *caseBlock, SwitchCase *caseToCapture)

◆ value() [1/2]

std::unique_ptr< Expression > & SkSL::SwitchStatement::value ( )
inline

Definition at line 58 of file SkSLSwitchStatement.h.

58 {
59 return fValue;
60 }

◆ value() [2/2]

const std::unique_ptr< Expression > & SkSL::SwitchStatement::value ( ) const
inline

Definition at line 62 of file SkSLSwitchStatement.h.

62 {
63 return fValue;
64 }

Member Data Documentation

◆ kIRNodeKind

constexpr Kind SkSL::SwitchStatement::kIRNodeKind = Kind::kSwitch
inlinestaticconstexpr

Definition at line 32 of file SkSLSwitchStatement.h.


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