49 struct AppendRTAdjustFixupHelper :
public IRHelpers {
52 , fRTAdjust(rtAdjust) {
53 fSkPositionField = &
fContext.fSymbolTable->find(Compiler::POSITION_NAME)
57 std::unique_ptr<Expression> Pos()
const {
58 return Field(&fSkPositionField->owner(), fSkPositionField->fieldIndex());
61 std::unique_ptr<Expression> Adjust()
const {
65 std::unique_ptr<Statement> makeFixupStmt()
const {
71 CtorXYZW(Add(Mul(
Swizzle(Pos(), {SwizzleComponent::X, SwizzleComponent::Y}),
72 Swizzle(Adjust(), {SwizzleComponent::X, SwizzleComponent::Z})),
73 Mul(
Swizzle(Pos(), {SwizzleComponent::W, SwizzleComponent::W}),
74 Swizzle(Adjust(), {SwizzleComponent::Y, SwizzleComponent::W}))),
76 Swizzle(Pos(), {SwizzleComponent::W})));
83 AppendRTAdjustFixupHelper helper(context, rtAdjust);
91 std::unique_ptr<Statement> body,
100 this->addLocalVariable(var,
pos);
104 ~Finalizer()
override {
106 SkASSERT(fContinuableLevel == std::forward_list<int>{0});
111 fContext.fErrors->error(
pos,
"unsized arrays are not permitted here");
118 size_t prevSlotsUsed = fSlotsUsed;
122 if (prevSlotsUsed < kVariableSlotLimit && fSlotsUsed >= kVariableSlotLimit) {
124 "' exceeds the stack size limit");
128 void fuseVariableDeclarationsWithInitialization(std::unique_ptr<Statement>& stmt) {
129 switch (stmt->kind()) {
130 case Statement::Kind::kNop:
131 case Statement::Kind::kBlock:
137 case Statement::Kind::kVarDeclaration:
140 fUninitializedVarDecl = &decl;
148 fUninitializedVarDecl =
nullptr;
151 case Statement::Kind::kExpression: {
154 if (fUninitializedVarDecl) {
156 fUninitializedVarDecl =
nullptr;
181 if (Analysis::ContainsVariable(*binaryExpr.
right(), *varRef.
variable())) {
186 vardecl->
value() = std::move(binaryExpr.
right());
196 bool functionReturnsValue()
const {
197 return !fFunction.returnType().isVoid();
200 bool visitExpressionPtr(std::unique_ptr<Expression>& expr)
override {
205 bool visitStatementPtr(std::unique_ptr<Statement>& stmt)
override {
209 if (
fContext.fConfig->fSettings.fOptimize) {
210 this->fuseVariableDeclarationsWithInitialization(stmt);
214 switch (stmt->kind()) {
215 case Statement::Kind::kVarDeclaration:
219 case Statement::Kind::kReturn: {
223 if (ProgramConfig::IsVertex(
fContext.fConfig->fKind) && fFunction.isMain()) {
226 "early returns from vertex programs are not supported");
232 if (this->functionReturnsValue()) {
234 returnStmt.
setExpression(fFunction.returnType().coerceExpression(
239 "may not return a value from a void function");
243 if (this->functionReturnsValue()) {
246 "expected function to return '" +
247 fFunction.returnType().displayName() +
"'");
252 case Statement::Kind::kDo:
253 case Statement::Kind::kFor: {
255 ++fContinuableLevel.front();
256 bool result = INHERITED::visitStatementPtr(stmt);
257 --fContinuableLevel.front();
261 case Statement::Kind::kSwitch: {
263 fContinuableLevel.push_front(0);
264 bool result = INHERITED::visitStatementPtr(stmt);
265 fContinuableLevel.pop_front();
269 case Statement::Kind::kBreak:
270 if (fBreakableLevel == 0) {
271 fContext.fErrors->error(stmt->fPosition,
272 "break statement must be inside a loop or switch");
276 case Statement::Kind::kContinue:
277 if (fContinuableLevel.front() == 0) {
278 if (std::any_of(fContinuableLevel.begin(),
279 fContinuableLevel.end(),
280 [](
int level) { return level > 0; })) {
281 fContext.fErrors->error(stmt->fPosition,
282 "continue statement cannot be used in a switch");
284 fContext.fErrors->error(stmt->fPosition,
285 "continue statement must be inside a loop");
293 return INHERITED::visitStatementPtr(stmt);
300 int fBreakableLevel = 0;
302 size_t fSlotsUsed = 0;
305 std::forward_list<int> fContinuableLevel{0};
318 "' should not have a definition");
326 "' must be a braced block");
333 "' was already defined");
346 "' can exit without returning a value");
SymbolTable * fSymbolTable