Revert "skslc switch support"

This reverts commit 2b1e468dab.

Reason for revert: bot breakage

Original change's description:
> skslc switch support
> 
> BUG=skia:
> 
> Change-Id: Ida7f9e80139aa1e4f43804cafbcac640e47fab25
> Reviewed-on: https://skia-review.googlesource.com/8771
> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
> Reviewed-by: Ben Wagner <benjaminwagner@google.com>
> 

TBR=benjaminwagner@google.com,ethannicholas@google.com,reviews@skia.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=skia:

Change-Id: Iaaa35d10a15704279c6883d4d68f6d4ad5078320
Reviewed-on: https://skia-review.googlesource.com/8792
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2017-02-23 16:18:54 +00:00 committed by Skia Commit-Bot
parent d196cbe9c2
commit 7d975fc200
19 changed files with 314 additions and 853 deletions

View File

@ -20,7 +20,6 @@
#include "ir/SkSLPrefixExpression.h"
#include "ir/SkSLReturnStatement.h"
#include "ir/SkSLSwizzle.h"
#include "ir/SkSLSwitchStatement.h"
#include "ir/SkSLTernaryExpression.h"
#include "ir/SkSLVarDeclarationsStatement.h"
#include "ir/SkSLWhileStatement.h"
@ -153,17 +152,13 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
constantPropagate, e, nullptr });
break;
case Expression::kPrefix_Kind: {
PrefixExpression* p = (PrefixExpression*) e->get();
this->addExpression(cfg, &p->fOperand, constantPropagate &&
p->fOperator != Token::PLUSPLUS &&
p->fOperator != Token::MINUSMINUS);
case Expression::kPrefix_Kind:
this->addExpression(cfg, &((PrefixExpression*) e->get())->fOperand, constantPropagate);
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
constantPropagate, e, nullptr });
break;
}
case Expression::kPostfix_Kind:
this->addExpression(cfg, &((PostfixExpression*) e->get())->fOperand, false);
this->addExpression(cfg, &((PostfixExpression*) e->get())->fOperand, constantPropagate);
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
constantPropagate, e, nullptr });
break;
@ -350,34 +345,6 @@ void CFGGenerator::addStatement(CFG& cfg, const Statement* s) {
cfg.fCurrent = loopExit;
break;
}
case Statement::kSwitch_Kind: {
SwitchStatement* ss = (SwitchStatement*) s;
this->addExpression(cfg, &ss->fValue, true);
BlockId start = cfg.fCurrent;
BlockId switchExit = cfg.newIsolatedBlock();
fLoopExits.push(switchExit);
for (const auto& c : ss->fCases) {
cfg.newBlock();
cfg.addExit(start, cfg.fCurrent);
if (c->fValue) {
// technically this should go in the start block, but it doesn't actually matter
// because it must be constant. Not worth running two loops for.
this->addExpression(cfg, &c->fValue, true);
}
for (const auto& caseStatement : c->fStatements) {
this->addStatement(cfg, caseStatement.get());
}
}
cfg.addExit(cfg.fCurrent, switchExit);
// note that unlike GLSL, our grammar requires the default case to be last
if (0 == ss->fCases.size() || ss->fCases[ss->fCases.size() - 1]->fValue) {
// switch does not have a default clause, mark that it can skip straight to the end
cfg.addExit(start, switchExit);
}
fLoopExits.pop();
cfg.fCurrent = switchExit;
break;
}
default:
printf("statement: %s\n", s->description().c_str());
ABORT("unsupported statement kind");

View File

@ -286,12 +286,8 @@ void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
if (e1 != e2) {
// definition has changed, merge and add exit block to worklist
workList->insert(exitId);
if (e1 && e2) {
exit.fBefore[pair.first] =
exit.fBefore[pair.first] =
(std::unique_ptr<Expression>*) &fContext.fDefined_Expression;
} else {
exit.fBefore[pair.first] = nullptr;
}
}
}
}

View File

@ -681,9 +681,6 @@ void GLSLCodeGenerator::writeStatement(const Statement& s) {
case Statement::kDo_Kind:
this->writeDoStatement((DoStatement&) s);
break;
case Statement::kSwitch_Kind:
this->writeSwitchStatement((SwitchStatement&) s);
break;
case Statement::kBreak_Kind:
this->write("break;");
break;
@ -753,30 +750,6 @@ void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
this->write(");");
}
void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
this->write("switch (");
this->writeExpression(*s.fValue, kTopLevel_Precedence);
this->writeLine(") {");
fIndentation++;
for (const auto& c : s.fCases) {
if (c->fValue) {
this->write("case ");
this->writeExpression(*c->fValue, kTopLevel_Precedence);
this->writeLine(":");
} else {
this->writeLine("default:");
}
fIndentation++;
for (const auto& stmt : c->fStatements) {
this->writeStatement(*stmt);
this->writeLine();
}
fIndentation--;
}
fIndentation--;
this->write("}");
}
void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
this->write("return");
if (r.fExpression) {

View File

@ -34,7 +34,6 @@
#include "ir/SkSLProgramElement.h"
#include "ir/SkSLReturnStatement.h"
#include "ir/SkSLStatement.h"
#include "ir/SkSLSwitchStatement.h"
#include "ir/SkSLSwizzle.h"
#include "ir/SkSLTernaryExpression.h"
#include "ir/SkSLVarDeclarations.h"
@ -156,8 +155,6 @@ private:
void writeDoStatement(const DoStatement& d);
void writeSwitchStatement(const SwitchStatement& s);
void writeReturnStatement(const ReturnStatement& r);
const Context& fContext;

View File

@ -8,7 +8,6 @@
#include "SkSLIRGenerator.h"
#include "limits.h"
#include <unordered_set>
#include "SkSLCompiler.h"
#include "ast/SkSLASTBoolLiteral.h"
@ -40,8 +39,6 @@
#include "ir/SkSLPostfixExpression.h"
#include "ir/SkSLPrefixExpression.h"
#include "ir/SkSLReturnStatement.h"
#include "ir/SkSLSwitchCase.h"
#include "ir/SkSLSwitchStatement.h"
#include "ir/SkSLSwizzle.h"
#include "ir/SkSLTernaryExpression.h"
#include "ir/SkSLUnresolvedFunction.h"
@ -84,27 +81,12 @@ public:
IRGenerator* fIR;
};
class AutoSwitchLevel {
public:
AutoSwitchLevel(IRGenerator* ir)
: fIR(ir) {
fIR->fSwitchLevel++;
}
~AutoSwitchLevel() {
fIR->fSwitchLevel--;
}
IRGenerator* fIR;
};
IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
ErrorReporter& errorReporter)
: fContext(*context)
, fCurrentFunction(nullptr)
, fSymbolTable(std::move(symbolTable))
, fLoopLevel(0)
, fSwitchLevel(0)
, fErrors(errorReporter) {}
void IRGenerator::pushSymbolTable() {
@ -171,8 +153,6 @@ std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& sta
return this->convertWhile((ASTWhileStatement&) statement);
case ASTStatement::kDo_Kind:
return this->convertDo((ASTDoStatement&) statement);
case ASTStatement::kSwitch_Kind:
return this->convertSwitch((ASTSwitchStatement&) statement);
case ASTStatement::kReturn_Kind:
return this->convertReturn((ASTReturnStatement&) statement);
case ASTStatement::kBreak_Kind:
@ -377,60 +357,6 @@ std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
std::move(test)));
}
std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTSwitchStatement& s) {
AutoSwitchLevel level(this);
std::unique_ptr<Expression> value = this->convertExpression(*s.fValue);
if (!value) {
return nullptr;
}
if (value->fType != *fContext.fUInt_Type) {
value = this->coerce(std::move(value), *fContext.fInt_Type);
if (!value) {
return nullptr;
}
}
AutoSymbolTable table(this);
std::unordered_set<int> caseValues;
std::vector<std::unique_ptr<SwitchCase>> cases;
for (const auto& c : s.fCases) {
std::unique_ptr<Expression> caseValue;
if (c->fValue) {
caseValue = this->convertExpression(*c->fValue);
if (!caseValue) {
return nullptr;
}
if (caseValue->fType != *fContext.fUInt_Type) {
caseValue = this->coerce(std::move(caseValue), *fContext.fInt_Type);
if (!caseValue) {
return nullptr;
}
}
if (!caseValue->isConstant()) {
fErrors.error(caseValue->fPosition, "case value must be a constant");
return nullptr;
}
ASSERT(caseValue->fKind == Expression::kIntLiteral_Kind);
int64_t v = ((IntLiteral&) *caseValue).fValue;
if (caseValues.find(v) != caseValues.end()) {
fErrors.error(caseValue->fPosition, "duplicate case value");
}
caseValues.insert(v);
}
std::vector<std::unique_ptr<Statement>> statements;
for (const auto& s : c->fStatements) {
std::unique_ptr<Statement> converted = this->convertStatement(*s);
if (!converted) {
return nullptr;
}
statements.push_back(std::move(converted));
}
cases.emplace_back(new SwitchCase(c->fPosition, std::move(caseValue),
std::move(statements)));
}
return std::unique_ptr<Statement>(new SwitchStatement(s.fPosition, std::move(value),
std::move(cases)));
}
std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(
const ASTExpressionStatement& s) {
std::unique_ptr<Expression> e = this->convertExpression(*s.fExpression);
@ -467,10 +393,10 @@ std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement&
}
std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) {
if (fLoopLevel > 0 || fSwitchLevel > 0) {
if (fLoopLevel > 0) {
return std::unique_ptr<Statement>(new BreakStatement(b.fPosition));
} else {
fErrors.error(b.fPosition, "break statement must be inside a loop or switch");
fErrors.error(b.fPosition, "break statement must be inside a loop");
return nullptr;
}
}

View File

@ -29,7 +29,6 @@
#include "ast/SkSLASTReturnStatement.h"
#include "ast/SkSLASTStatement.h"
#include "ast/SkSLASTSuffixExpression.h"
#include "ast/SkSLASTSwitchStatement.h"
#include "ast/SkSLASTTernaryExpression.h"
#include "ast/SkSLASTVarDeclaration.h"
#include "ast/SkSLASTVarDeclarationStatement.h"
@ -141,7 +140,6 @@ private:
std::unique_ptr<Statement> convertContinue(const ASTContinueStatement& c);
std::unique_ptr<Statement> convertDiscard(const ASTDiscardStatement& d);
std::unique_ptr<Statement> convertDo(const ASTDoStatement& d);
std::unique_ptr<Statement> convertSwitch(const ASTSwitchStatement& s);
std::unique_ptr<Expression> convertBinaryExpression(const ASTBinaryExpression& expression);
std::unique_ptr<Extension> convertExtension(const ASTExtension& e);
std::unique_ptr<Statement> convertExpressionStatement(const ASTExpressionStatement& s);
@ -172,12 +170,10 @@ private:
std::unordered_map<SkString, CapValue> fCapsMap;
std::shared_ptr<SymbolTable> fSymbolTable;
int fLoopLevel;
int fSwitchLevel;
ErrorReporter& fErrors;
friend class AutoSymbolTable;
friend class AutoLoopLevel;
friend class AutoSwitchLevel;
friend class Compiler;
};

View File

@ -63,8 +63,6 @@
#include "ast/SkSLASTReturnStatement.h"
#include "ast/SkSLASTStatement.h"
#include "ast/SkSLASTSuffixExpression.h"
#include "ast/SkSLASTSwitchCase.h"
#include "ast/SkSLASTSwitchStatement.h"
#include "ast/SkSLASTTernaryExpression.h"
#include "ast/SkSLASTType.h"
#include "ast/SkSLASTVarDeclaration.h"
@ -772,8 +770,6 @@ std::unique_ptr<ASTStatement> Parser::statement() {
return this->doStatement();
case Token::WHILE:
return this->whileStatement();
case Token::SWITCH:
return this->switchStatement();
case Token::RETURN:
return this->returnStatement();
case Token::BREAK:
@ -979,85 +975,6 @@ std::unique_ptr<ASTWhileStatement> Parser::whileStatement() {
std::move(statement)));
}
/* CASE expression COLON statement* */
std::unique_ptr<ASTSwitchCase> Parser::switchCase() {
if (!this->expect(Token::CASE, "'case'")) {
return nullptr;
}
std::unique_ptr<ASTExpression> value = this->expression();
if (!value) {
return nullptr;
}
if (!this->expect(Token::COLON, "':'")) {
return nullptr;
}
std::vector<std::unique_ptr<ASTStatement>> statements;
while (this->peek().fKind != Token::RBRACE && this->peek().fKind != Token::CASE &&
this->peek().fKind != Token::DEFAULT) {
std::unique_ptr<ASTStatement> s = this->statement();
if (!s) {
return nullptr;
}
statements.push_back(std::move(s));
}
return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(value->fPosition, std::move(value),
std::move(statements)));
}
/* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
std::unique_ptr<ASTStatement> Parser::switchStatement() {
Token start;
if (!this->expect(Token::SWITCH, "'switch'", &start)) {
return nullptr;
}
if (!this->expect(Token::LPAREN, "'('")) {
return nullptr;
}
std::unique_ptr<ASTExpression> value(this->expression());
if (!value) {
return nullptr;
}
if (!this->expect(Token::RPAREN, "')'")) {
return nullptr;
}
if (!this->expect(Token::LBRACE, "'{'")) {
return nullptr;
}
std::vector<std::unique_ptr<ASTSwitchCase>> cases;
while (this->peek().fKind == Token::CASE) {
std::unique_ptr<ASTSwitchCase> c = this->switchCase();
if (!c) {
return nullptr;
}
cases.push_back(std::move(c));
}
// Requiring default: to be last (in defiance of C and GLSL) was a deliberate decision. Other
// parts of the compiler may rely upon this assumption.
if (this->peek().fKind == Token::DEFAULT) {
Token defaultStart;
SkAssertResult(this->expect(Token::DEFAULT, "'default'", &defaultStart));
if (!this->expect(Token::COLON, "':'")) {
return nullptr;
}
std::vector<std::unique_ptr<ASTStatement>> statements;
while (this->peek().fKind != Token::RBRACE) {
std::unique_ptr<ASTStatement> s = this->statement();
if (!s) {
return nullptr;
}
statements.push_back(std::move(s));
}
cases.emplace_back(new ASTSwitchCase(defaultStart.fPosition, nullptr,
std::move(statements)));
}
if (!this->expect(Token::RBRACE, "'}'")) {
return nullptr;
}
return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fPosition,
std::move(value),
std::move(cases)));
}
/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
STATEMENT */
std::unique_ptr<ASTForStatement> Parser::forStatement() {

View File

@ -37,8 +37,6 @@ struct ASTPrecision;
struct ASTReturnStatement;
struct ASTStatement;
struct ASTSuffix;
struct ASTSwitchCase;
struct ASTSwitchStatement;
struct ASTType;
struct ASTWhileStatement;
struct ASTVarDeclarations;
@ -145,10 +143,6 @@ private:
std::unique_ptr<ASTForStatement> forStatement();
std::unique_ptr<ASTSwitchCase> switchCase();
std::unique_ptr<ASTStatement> switchStatement();
std::unique_ptr<ASTReturnStatement> returnStatement();
std::unique_ptr<ASTBreakStatement> breakStatement();

View File

@ -82,9 +82,6 @@ struct Token {
FOR,
WHILE,
DO,
SWITCH,
CASE,
DEFAULT,
RETURN,
BREAK,
CONTINUE,

View File

@ -26,7 +26,6 @@ struct ASTStatement : public ASTPositionNode {
kFor_Kind,
kWhile_Kind,
kDo_Kind,
kSwitch_Kind,
kReturn_Kind,
kBreak_Kind,
kContinue_Kind,

View File

@ -1,48 +0,0 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTSWITCHCASE
#define SKSL_ASTSWITCHCASE
#include "SkSLASTStatement.h"
namespace SkSL {
/**
* A single case of a 'switch' statement.
*/
struct ASTSwitchCase : public ASTStatement {
// a null value means "default:"
ASTSwitchCase(Position position, std::unique_ptr<ASTExpression> value,
std::vector<std::unique_ptr<ASTStatement>> statements)
: INHERITED(position, kSwitch_Kind)
, fValue(std::move(value))
, fStatements(std::move(statements)) {}
SkString description() const override {
SkString result;
if (fValue) {
result.appendf("case %s:\n", fValue->description().c_str());
} else {
result += "default:\n";
}
for (const auto& s : fStatements) {
result += s->description() + "\n";
}
return result;
}
// null value implies "default" case
const std::unique_ptr<ASTExpression> fValue;
const std::vector<std::unique_ptr<ASTStatement>> fStatements;
typedef ASTStatement INHERITED;
};
} // namespace
#endif

View File

@ -1,43 +0,0 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTSWITCHSTATEMENT
#define SKSL_ASTSWITCHSTATEMENT
#include "SkSLASTStatement.h"
#include "SkSLASTSwitchCase.h"
namespace SkSL {
/**
* A 'switch' statement.
*/
struct ASTSwitchStatement : public ASTStatement {
ASTSwitchStatement(Position position, std::unique_ptr<ASTExpression> value,
std::vector<std::unique_ptr<ASTSwitchCase>> cases)
: INHERITED(position, kSwitch_Kind)
, fValue(std::move(value))
, fCases(std::move(cases)) {}
SkString description() const override {
SkString result = SkStringPrintf("switch (%s) {\n", + fValue->description().c_str());
for (const auto& c : fCases) {
result += c->description();
}
result += "}";
return result;
}
const std::unique_ptr<ASTExpression> fValue;
const std::vector<std::unique_ptr<ASTSwitchCase>> fCases;
typedef ASTStatement INHERITED;
};
} // namespace
#endif

View File

@ -27,7 +27,6 @@ struct Statement : public IRNode {
kFor_Kind,
kIf_Kind,
kReturn_Kind,
kSwitch_Kind,
kVarDeclarations_Kind,
kWhile_Kind
};

View File

@ -1,47 +0,0 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_SWITCHCASE
#define SKSL_SWITCHCASE
#include "SkSLStatement.h"
namespace SkSL {
/**
* A single case of a 'switch' statement.
*/
struct SwitchCase : public Statement {
SwitchCase(Position position, std::unique_ptr<Expression> value,
std::vector<std::unique_ptr<Statement>> statements)
: INHERITED(position, kSwitch_Kind)
, fValue(std::move(value))
, fStatements(std::move(statements)) {}
SkString description() const override {
SkString result;
if (fValue) {
result.appendf("case %s:\n", fValue->description().c_str());
} else {
result += "default:\n";
}
for (const auto& s : fStatements) {
result += s->description() + "\n";
}
return result;
}
// null value implies "default" case
std::unique_ptr<Expression> fValue;
std::vector<std::unique_ptr<Statement>> fStatements;
typedef Statement INHERITED;
};
} // namespace
#endif

View File

@ -1,43 +0,0 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_SWITCHSTATEMENT
#define SKSL_SWITCHSTATEMENT
#include "SkSLStatement.h"
#include "SkSLSwitchCase.h"
namespace SkSL {
/**
* A 'switch' statement.
*/
struct SwitchStatement : public Statement {
SwitchStatement(Position position, std::unique_ptr<Expression> value,
std::vector<std::unique_ptr<SwitchCase>> cases)
: INHERITED(position, kSwitch_Kind)
, fValue(std::move(value))
, fCases(std::move(cases)) {}
SkString description() const override {
SkString result = SkStringPrintf("switch (%s) {\n", + fValue->description().c_str());
for (const auto& c : fCases) {
result += c->description();
}
result += "}";
return result;
}
std::unique_ptr<Expression> fValue;
std::vector<std::unique_ptr<SwitchCase>> fCases;
typedef Statement INHERITED;
};
} // namespace
#endif

File diff suppressed because it is too large Load Diff

View File

@ -46,12 +46,6 @@ while { return SkSL::Token::WHILE; }
do { return SkSL::Token::DO; }
switch { return SkSL::Token::SWITCH; }
case { return SkSL::Token::CASE; }
default { return SkSL::Token::DEFAULT; }
break { return SkSL::Token::BREAK; }
continue { return SkSL::Token::CONTINUE; }

View File

@ -337,10 +337,6 @@ DEF_TEST(SkSLUseWithoutInitialize, r) {
test_failure(r,
"void main() { bool x; if (true && (false || x)) return; }",
"error: 1: 'x' has not been assigned\n1 error\n");
test_failure(r,
"void main() { int x; switch (3) { case 0: x = 0; case 1: x = 1; }"
"sk_FragColor = vec4(x); }",
"error: 1: 'x' has not been assigned\n1 error\n");
}
DEF_TEST(SkSLUnreachable, r) {
@ -370,16 +366,13 @@ DEF_TEST(SkSLNoReturn, r) {
DEF_TEST(SkSLBreakOutsideLoop, r) {
test_failure(r,
"void foo() { while(true) {} if (true) break; }",
"error: 1: break statement must be inside a loop or switch\n1 error\n");
"error: 1: break statement must be inside a loop\n1 error\n");
}
DEF_TEST(SkSLContinueOutsideLoop, r) {
test_failure(r,
"void foo() { for(;;); continue; }",
"error: 1: continue statement must be inside a loop\n1 error\n");
test_failure(r,
"void foo() { switch (1) { default: continue; } }",
"error: 1: continue statement must be inside a loop\n1 error\n");
}
DEF_TEST(SkSLStaticIfError, r) {
@ -437,25 +430,4 @@ DEF_TEST(SkSLUnsupportedGLSLIdentifiers, r) {
"error: 1: unknown identifier 'gl_FragColor'\n1 error\n");
}
DEF_TEST(SkSLWrongSwitchTypes, r) {
test_failure(r,
"void main() { switch (vec2(1)) { case 1: break; } }",
"error: 1: expected 'int', but found 'vec2'\n1 error\n");
test_failure(r,
"void main() { switch (1) { case vec2(1): break; } }",
"error: 1: expected 'int', but found 'vec2'\n1 error\n");
}
DEF_TEST(SkSLNonConstantCase, r) {
test_failure(r,
"void main() { int x = 1; switch (1) { case x: break; } }",
"error: 1: case value must be a constant\n1 error\n");
}
DEF_TEST(SkSLDuplicateCase, r) {
test_failure(r,
"void main() { switch (1) { case 0: case 1: case 0: break; } }",
"error: 1: duplicate case value\n1 error\n");
}
#endif

View File

@ -777,91 +777,4 @@ DEF_TEST(SkSLGeometry, r) {
SkSL::Program::kGeometry_Kind);
}
DEF_TEST(SkSLSwitch, r) {
test(r,
"void main() {"
" float x;"
" switch (1) {"
" case 0:"
" x = 0.0;"
" break;"
" case 1:"
" x = 1.0;"
" break;"
" default:"
" x = 2.0;"
" }"
" sk_FragColor = vec4(x);"
"}",
*SkSL::ShaderCapsFactory::Default(),
"#version 400\n"
"out vec4 sk_FragColor;\n"
"void main() {\n"
" float x;\n"
" switch (1) {\n"
" case 0:\n"
" x = 0.0;\n"
" break;\n"
" case 1:\n"
" x = 1.0;\n"
" break;\n"
" default:\n"
" x = 2.0;\n"
" }\n"
" sk_FragColor = vec4(x);\n"
"}\n");
test(r,
"void main() {"
" float x;"
" switch (2) {"
" case 0:"
" x = 0.0;"
" case 1:"
" x = 1.0;"
" default:"
" x = 2.0;"
" }"
" sk_FragColor = vec4(x);"
"}",
*SkSL::ShaderCapsFactory::Default(),
"#version 400\n"
"out vec4 sk_FragColor;\n"
"void main() {\n"
" float x;\n"
" switch (2) {\n"
" case 0:\n"
" x = 0.0;\n"
" case 1:\n"
" x = 1.0;\n"
" default:\n"
" x = 2.0;\n"
" }\n"
" sk_FragColor = vec4(2.0);\n"
"}\n");
test(r,
"void main() {"
" float x = 0.0;"
" switch (3) {"
" case 0:"
" x = 0.0;"
" case 1:"
" x = 1.0;"
" }"
" sk_FragColor = vec4(x);"
"}",
*SkSL::ShaderCapsFactory::Default(),
"#version 400\n"
"out vec4 sk_FragColor;\n"
"void main() {\n"
" float x = 0.0;\n"
" switch (3) {\n"
" case 0:\n"
" x = 0.0;\n"
" case 1:\n"
" x = 1.0;\n"
" }\n"
" sk_FragColor = vec4(x);\n"
"}\n");
}
#endif