Add GetConstantValue, fix const-variable ES2 loop bounds

Prior to this fix, the new test cases would report that the various loop
terms needed to be constant expressions.

Bug: skia:12472
Change-Id: Ic377ed0c4598136ae38fb2b65c93b6d8609d54cb
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452276
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
This commit is contained in:
Brian Osman 2021-09-23 11:36:15 -04:00 committed by SkCQ
parent e405d7c8e5
commit 448b2d5795
7 changed files with 43 additions and 28 deletions

View File

@ -1,17 +1,19 @@
uniform half4 colorRed, colorGreen;
// Should return 5
const float kZero = 0;
float return_loop() {
for (float i = 0; i < 10; ++i) {
for (float i = kZero; i < 10; ++i) {
if (i == 5) { return i; }
}
return 0;
}
// Should return 35
const float kTen = kZero + 10;
float continue_loop() {
float sum = 0;
for (float i = 0; i < 10; ++i) {
for (float i = 0; i < kTen; ++i) {
if (i < 5) { continue; }
sum += i;
}
@ -21,7 +23,8 @@ float continue_loop() {
// Should return 15
float break_loop() {
float sum = 0;
for (float i = 0; i < 10; ++i) {
const float kOne = 1;
for (float i = 0; i < 10; i += kOne) {
if (i > 5) { break; }
sum += i;
}

View File

@ -1,17 +1,19 @@
uniform half4 colorRed, colorGreen;
// Should return 5
const int kZero = 0;
int return_loop() {
for (int i = 0; i < 10; ++i) {
for (int i = kZero; i < 10; ++i) {
if (i == 5) { return i; }
}
return 0;
}
// Should return 35
const int kTen = kZero + 10;
int continue_loop() {
int sum = 0;
for (int i = 0; i < 10; ++i) {
for (int i = 0; i < kTen; ++i) {
if (i < 5) { continue; }
sum += i;
}
@ -21,7 +23,8 @@ int continue_loop() {
// Should return 15
int break_loop() {
int sum = 0;
for (int i = 0; i < 10; ++i) {
const int kOne = 1;
for (int i = 0; i < 10; i += kOne) {
if (i > 5) { break; }
sum += i;
}

View File

@ -15,6 +15,7 @@
#include "include/sksl/SkSLErrorReporter.h"
#include "src/core/SkSafeMath.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLConstantFolder.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLProgram.h"
@ -1009,19 +1010,6 @@ bool Analysis::IsSameExpressionTree(const Expression& left, const Expression& ri
}
}
static bool get_constant_value(const Expression& expr, double* val) {
const Expression* valExpr = expr.getConstantSubexpression(0);
if (!valExpr) {
return false;
}
if (valExpr->is<Literal>()) {
*val = valExpr->as<Literal>().value();
return true;
}
SkDEBUGFAILF("unexpected constant type (%s)", expr.type().description().c_str());
return false;
}
static const char* invalid_for_ES2(int offset,
const Statement* loopInitializer,
const Expression* loopTest,
@ -1047,7 +1035,7 @@ static const char* invalid_for_ES2(int offset,
if (!initDecl.value()) {
return "missing loop index initializer";
}
if (!get_constant_value(*initDecl.value(), &loopInfo.fStart)) {
if (!ConstantFolder::GetConstantValue(*initDecl.value(), &loopInfo.fStart)) {
return "loop index initializer must be a constant expression";
}
@ -1084,7 +1072,7 @@ static const char* invalid_for_ES2(int offset,
return "invalid relational operator";
}
double loopEnd = 0;
if (!get_constant_value(*cond.right(), &loopEnd)) {
if (!ConstantFolder::GetConstantValue(*cond.right(), &loopEnd)) {
return "loop index must be compared with a constant expression";
}
@ -1106,7 +1094,7 @@ static const char* invalid_for_ES2(int offset,
if (!is_loop_index(next.left())) {
return "expected loop index in loop expression";
}
if (!get_constant_value(*next.right(), &loopInfo.fDelta)) {
if (!ConstantFolder::GetConstantValue(*next.right(), &loopInfo.fDelta)) {
return "loop index must be modified by a constant expression";
}
switch (next.getOperator().kind()) {

View File

@ -145,6 +145,15 @@ bool ConstantFolder::GetConstantInt(const Expression& value, SKSL_INT* out) {
return true;
}
bool ConstantFolder::GetConstantValue(const Expression& value, double* out) {
const Expression* expr = GetConstantValueForVariable(value);
if (!expr->is<Literal>()) {
return false;
}
*out = expr->as<Literal>().value();
return true;
}
static bool is_constant_scalar_value(const Expression& inExpr, double match) {
const Expression* expr = ConstantFolder::GetConstantValueForVariable(inExpr);
return (expr->is<Literal>() && expr->as<Literal>().value() == match);

View File

@ -30,6 +30,12 @@ public:
*/
static bool GetConstantInt(const Expression& value, SKSL_INT* out);
/**
* If value is a literal or const scalar variable with a known value, returns true and stores
* the value in out. Otherwise returns false.
*/
static bool GetConstantValue(const Expression& value, double* out);
/**
* If the expression is a const variable with a known compile-time-constant value, returns that
* value. If not, returns the original expression as-is.

View File

@ -1,8 +1,10 @@
uniform half4 colorRed;
uniform half4 colorGreen;
const float kZero_0 = 0.0;
const float kTen_0 = 10.0;
float return_loop_0()
{
for (float i = 0.0;i < 10.0; ++i)
for (float i = kZero_0;i < 10.0; ++i)
{
if (i == 5.0)
{
@ -14,7 +16,7 @@ float return_loop_0()
float continue_loop_0()
{
float sum = 0.0;
for (float i = 0.0;i < 10.0; ++i)
for (float i = 0.0;i < kTen_0; ++i)
{
if (i < 5.0)
{
@ -27,7 +29,8 @@ float continue_loop_0()
float break_loop_0()
{
float sum = 0.0;
for (float i = 0.0;i < 10.0; ++i)
const float kOne = 1.0;
for (float i = 0.0;i < 10.0; i += kOne)
{
if (i > 5.0)
{

View File

@ -1,8 +1,10 @@
uniform half4 colorRed;
uniform half4 colorGreen;
const int kZero_0 = 0;
const int kTen_0 = 10;
int return_loop_0()
{
for (int i = 0;i < 10; ++i)
for (int i = kZero_0;i < 10; ++i)
{
if (i == 5)
{
@ -14,7 +16,7 @@ int return_loop_0()
int continue_loop_0()
{
int sum = 0;
for (int i = 0;i < 10; ++i)
for (int i = 0;i < kTen_0; ++i)
{
if (i < 5)
{
@ -27,7 +29,8 @@ int continue_loop_0()
int break_loop_0()
{
int sum = 0;
for (int i = 0;i < 10; ++i)
const int kOne = 1;
for (int i = 0;i < 10; i += kOne)
{
if (i > 5)
{