Represent array constructors with a dedicated ConstructorArray class.

Change-Id: Ia8c8a3476202257ecc100f9cb31e6d0095135aa1
Bug: skia:11032
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/391919
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
John Stiles 2021-04-01 13:48:15 -04:00 committed by Skia Commit-Bot
parent 358858fe4c
commit 7384b37576
19 changed files with 250 additions and 93 deletions

View File

@ -94,6 +94,8 @@ skia_sksl_sources = [
"$_src/sksl/ir/SkSLBreakStatement.h",
"$_src/sksl/ir/SkSLConstructor.cpp",
"$_src/sksl/ir/SkSLConstructor.h",
"$_src/sksl/ir/SkSLConstructorArray.cpp",
"$_src/sksl/ir/SkSLConstructorArray.h",
"$_src/sksl/ir/SkSLConstructorDiagonalMatrix.cpp",
"$_src/sksl/ir/SkSLConstructorDiagonalMatrix.h",
"$_src/sksl/ir/SkSLContinueStatement.h",

View File

@ -747,25 +747,23 @@ bool Analysis::IsSameExpressionTree(const Expression& left, const Expression& ri
case Expression::Kind::kBoolLiteral:
return left.as<BoolLiteral>().value() == right.as<BoolLiteral>().value();
case Expression::Kind::kConstructor: {
const Constructor& leftCtor = left.as<Constructor>();
const Constructor& rightCtor = right.as<Constructor>();
if (leftCtor.arguments().count() != rightCtor.arguments().count()) {
case Expression::Kind::kConstructor:
case Expression::Kind::kConstructorArray:
case Expression::Kind::kConstructorDiagonalMatrix: {
const AnyConstructor& leftCtor = left.asAnyConstructor();
const AnyConstructor& rightCtor = right.asAnyConstructor();
const auto leftSpan = leftCtor.argumentSpan();
const auto rightSpan = rightCtor.argumentSpan();
if (leftSpan.size() != rightSpan.size()) {
return false;
}
for (int index = 0; index < leftCtor.arguments().count(); ++index) {
if (!IsSameExpressionTree(*leftCtor.arguments()[index],
*rightCtor.arguments()[index])) {
for (size_t index = 0; index < leftSpan.size(); ++index) {
if (!IsSameExpressionTree(*leftSpan[index], *rightSpan[index])) {
return false;
}
}
return true;
}
case Expression::Kind::kConstructorDiagonalMatrix: {
const ConstructorDiagonalMatrix& leftCtor = left.as<ConstructorDiagonalMatrix>();
const ConstructorDiagonalMatrix& rightCtor = right.as<ConstructorDiagonalMatrix>();
return IsSameExpressionTree(*leftCtor.argument(), *rightCtor.argument());
}
case Expression::Kind::kFieldAccess:
return left.as<FieldAccess>().fieldIndex() == right.as<FieldAccess>().fieldIndex() &&
IsSameExpressionTree(*left.as<FieldAccess>().base(),
@ -1019,6 +1017,7 @@ public:
// ... expressions composed of both of the above
case Expression::Kind::kBinary:
case Expression::Kind::kConstructor:
case Expression::Kind::kConstructorArray:
case Expression::Kind::kConstructorDiagonalMatrix:
case Expression::Kind::kFieldAccess:
case Expression::Kind::kIndex:
@ -1141,16 +1140,15 @@ template <typename T> bool TProgramVisitor<T>::visitExpression(typename T::Expre
return (b.left() && this->visitExpressionPtr(b.left())) ||
(b.right() && this->visitExpressionPtr(b.right()));
}
case Expression::Kind::kConstructor: {
auto& c = e.template as<Constructor>();
for (auto& arg : c.arguments()) {
case Expression::Kind::kConstructor:
case Expression::Kind::kConstructorArray:
case Expression::Kind::kConstructorDiagonalMatrix: {
auto& c = e.asAnyConstructor();
for (auto& arg : c.argumentSpan()) {
if (this->visitExpressionPtr(arg)) { return true; }
}
return false;
}
case Expression::Kind::kConstructorDiagonalMatrix: {
return this->visitExpressionPtr(e.template as<ConstructorDiagonalMatrix>().argument());
}
case Expression::Kind::kExternalFunctionCall: {
auto& c = e.template as<ExternalFunctionCall>();
for (auto& arg : c.arguments()) {

View File

@ -16,6 +16,7 @@
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBreakStatement.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLContinueStatement.h"
#include "src/sksl/ir/SkSLDiscardStatement.h"
@ -288,6 +289,12 @@ void Dehydrator::write(const Expression* e) {
this->writeExpressionSpan(e->as<Constructor>().argumentSpan());
break;
case Expression::Kind::kConstructorArray:
this->writeCommand(Rehydrator::kConstructorArray_Command);
this->write(e->type());
this->writeExpressionSpan(e->as<ConstructorArray>().argumentSpan());
break;
case Expression::Kind::kConstructorDiagonalMatrix:
this->writeCommand(Rehydrator::kConstructorDiagonalMatrix_Command);
this->write(e->type());

View File

@ -10,6 +10,8 @@
#include <memory>
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLExpressionStatement.h"
#include "src/sksl/ir/SkSLExtension.h"
#include "src/sksl/ir/SkSLIndexExpression.h"
@ -199,8 +201,9 @@ void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence paren
case Expression::Kind::kConstructor:
this->writeConstructor(expr.as<Constructor>(), parentPrecedence);
break;
case Expression::Kind::kConstructorArray:
case Expression::Kind::kConstructorDiagonalMatrix:
this->writeAnyConstructor(expr.as<ConstructorDiagonalMatrix>(), parentPrecedence);
this->writeAnyConstructor(expr.asAnyConstructor(), parentPrecedence);
break;
case Expression::Kind::kIntLiteral:
this->writeIntLiteral(expr.as<IntLiteral>());

View File

@ -21,7 +21,6 @@
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLDoStatement.h"
#include "src/sksl/ir/SkSLExtension.h"
#include "src/sksl/ir/SkSLFieldAccess.h"

View File

@ -17,6 +17,7 @@
#include "src/sksl/ir/SkSLBoolLiteral.h"
#include "src/sksl/ir/SkSLBreakStatement.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLContinueStatement.h"
#include "src/sksl/ir/SkSLDiscardStatement.h"
@ -313,6 +314,12 @@ std::unique_ptr<Expression> Inliner::inlineExpression(int offset,
SkASSERT(inlinedCtor);
return inlinedCtor;
}
case Expression::Kind::kConstructorArray: {
const ConstructorArray& ctor = expression.as<ConstructorArray>();
return ConstructorArray::Make(*fContext, offset,
*ctor.type().clone(symbolTableForExpression),
argList(ctor.arguments()));
}
case Expression::Kind::kConstructorDiagonalMatrix: {
const ConstructorDiagonalMatrix& ctor = expression.as<ConstructorDiagonalMatrix>();
return ConstructorDiagonalMatrix::Make(*fContext, offset,
@ -913,18 +920,15 @@ public:
}
break;
}
case Expression::Kind::kConstructor: {
Constructor& constructorExpr = (*expr)->as<Constructor>();
for (std::unique_ptr<Expression>& arg : constructorExpr.arguments()) {
case Expression::Kind::kConstructor:
case Expression::Kind::kConstructorArray:
case Expression::Kind::kConstructorDiagonalMatrix: {
AnyConstructor& constructorExpr = (*expr)->asAnyConstructor();
for (std::unique_ptr<Expression>& arg : constructorExpr.argumentSpan()) {
this->visitExpression(&arg);
}
break;
}
case Expression::Kind::kConstructorDiagonalMatrix: {
ConstructorDiagonalMatrix& ctorExpr = (*expr)->as<ConstructorDiagonalMatrix>();
this->visitExpression(&ctorExpr.argument());
break;
}
case Expression::Kind::kExternalFunctionCall: {
ExternalFunctionCall& funcCallExpr = (*expr)->as<ExternalFunctionCall>();
for (std::unique_ptr<Expression>& arg : funcCallExpr.arguments()) {

View File

@ -10,6 +10,8 @@
#include "src/core/SkScopeExit.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLMemoryLayout.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLExpressionStatement.h"
#include "src/sksl/ir/SkSLExtension.h"
#include "src/sksl/ir/SkSLIndexExpression.h"
@ -171,6 +173,9 @@ void MetalCodeGenerator::writeExpression(const Expression& expr, Precedence pare
case Expression::Kind::kConstructor:
this->writeConstructor(expr.as<Constructor>(), parentPrecedence);
break;
case Expression::Kind::kConstructorArray:
this->writeConstructorArray(expr.as<ConstructorArray>(), parentPrecedence);
break;
case Expression::Kind::kConstructorDiagonalMatrix:
this->writeSingleArgumentConstructor(expr.as<ConstructorDiagonalMatrix>(),
parentPrecedence);
@ -1041,6 +1046,8 @@ bool MetalCodeGenerator::matrixConstructHelperIsNeeded(const Constructor& c) {
void MetalCodeGenerator::writeConstructor(const Constructor& c, Precedence parentPrecedence) {
const Type& constructorType = c.type();
SkASSERT(!constructorType.isArray());
// Handle special cases for single-argument constructors.
if (c.arguments().size() == 1) {
// If the type is coercible, emit it directly.
@ -1082,7 +1089,7 @@ void MetalCodeGenerator::writeConstructor(const Constructor& c, Precedence paren
// Explicitly invoke the constructor, passing in the necessary arguments.
this->writeType(constructorType);
this->write(constructorType.isArray() ? "{" : "(");
this->write("(");
const char* separator = "";
int scalarCount = 0;
for (const std::unique_ptr<Expression>& arg : c.arguments()) {
@ -1105,7 +1112,7 @@ void MetalCodeGenerator::writeConstructor(const Constructor& c, Precedence paren
scalarCount = 0;
}
}
this->write(constructorType.isArray() ? "}" : ")");
this->write(")");
}
void MetalCodeGenerator::writeSingleArgumentConstructor(const SingleArgumentConstructor& c,
@ -1116,6 +1123,19 @@ void MetalCodeGenerator::writeSingleArgumentConstructor(const SingleArgumentCons
this->write(")");
}
void MetalCodeGenerator::writeConstructorArray(const ConstructorArray& c,
Precedence parentPrecedence) {
this->writeType(c.type());
this->write("{");
const char* separator = "";
for (const std::unique_ptr<Expression>& arg : c.arguments()) {
this->write(separator);
separator = ", ";
this->writeExpression(*arg, Precedence::kSequence);
}
this->write("}");
}
void MetalCodeGenerator::writeFragCoord() {
if (fRTHeightName.length()) {
this->write("float4(_fragCoord.x, ");
@ -2238,17 +2258,16 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expressi
}
return result;
}
case Expression::Kind::kConstructor: {
const Constructor& c = e->as<Constructor>();
case Expression::Kind::kConstructor:
case Expression::Kind::kConstructorArray:
case Expression::Kind::kConstructorDiagonalMatrix: {
const AnyConstructor& c = e->asAnyConstructor();
Requirements result = kNo_Requirements;
for (const auto& arg : c.argumentSpan()) {
result |= this->requirements(arg.get());
}
return result;
}
case Expression::Kind::kConstructorDiagonalMatrix: {
return this->requirements(e->as<ConstructorDiagonalMatrix>().argument().get());
}
case Expression::Kind::kFieldAccess: {
const FieldAccess& f = e->as<FieldAccess>();
if (FieldAccess::OwnerKind::kAnonymousInterfaceBlock == f.ownerKind()) {

View File

@ -22,7 +22,7 @@
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLDoStatement.h"
#include "src/sksl/ir/SkSLExtension.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
@ -230,6 +230,8 @@ protected:
void writeConstructor(const Constructor& c, Precedence parentPrecedence);
void writeConstructorArray(const ConstructorArray& c, Precedence parentPrecedence);
void writeSingleArgumentConstructor(const SingleArgumentConstructor& c,
Precedence parentPrecedence);

View File

@ -14,6 +14,7 @@
#include "src/sksl/SkSLStringStream.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLExpressionStatement.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
@ -409,10 +410,9 @@ void PipelineStageCodeGenerator::writeExpression(const Expression& expr,
this->write(expr.description());
break;
case Expression::Kind::kConstructor:
this->writeAnyConstructor(expr.as<Constructor>(), parentPrecedence);
break;
case Expression::Kind::kConstructorArray:
case Expression::Kind::kConstructorDiagonalMatrix:
this->writeAnyConstructor(expr.as<ConstructorDiagonalMatrix>(), parentPrecedence);
this->writeAnyConstructor(expr.asAnyConstructor(), parentPrecedence);
break;
case Expression::Kind::kFieldAccess:
this->writeFieldAccess(expr.as<FieldAccess>());

View File

@ -711,6 +711,8 @@ SpvId SPIRVCodeGenerator::writeExpression(const Expression& expr, OutputStream&
return this->writeBoolLiteral(expr.as<BoolLiteral>());
case Expression::Kind::kConstructor:
return this->writeConstructor(expr.as<Constructor>(), out);
case Expression::Kind::kConstructorArray:
return this->writeArrayConstructor(expr.as<ConstructorArray>(), out);
case Expression::Kind::kConstructorDiagonalMatrix:
return this->writeConstructorDiagonalMatrix(expr.as<ConstructorDiagonalMatrix>(), out);
case Expression::Kind::kIntLiteral:
@ -1643,7 +1645,7 @@ SpvId SPIRVCodeGenerator::writeVectorConstructor(const Constructor& c, OutputStr
return result;
}
SpvId SPIRVCodeGenerator::writeArrayConstructor(const Constructor& c, OutputStream& out) {
SpvId SPIRVCodeGenerator::writeArrayConstructor(const ConstructorArray& c, OutputStream& out) {
const Type& type = c.type();
SkASSERT(type.isArray());
// go ahead and write the arguments so we don't try to write new instructions in the middle of
@ -1682,8 +1684,6 @@ SpvId SPIRVCodeGenerator::writeConstructor(const Constructor& c, OutputStream& o
return this->writeVectorConstructor(c, out);
case Type::TypeKind::kMatrix:
return this->writeMatrixConstructor(c, out);
case Type::TypeKind::kArray:
return this->writeArrayConstructor(c, out);
default:
fErrors.error(c.fOffset, "unsupported constructor: " + c.description());
return -1;

View File

@ -22,6 +22,7 @@
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLDoStatement.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
@ -284,7 +285,7 @@ private:
SpvId writeVectorConstructor(const Constructor& c, OutputStream& out);
SpvId writeArrayConstructor(const Constructor& c, OutputStream& out);
SpvId writeArrayConstructor(const ConstructorArray& c, OutputStream& out);
SpvId writeConstructor(const Constructor& c, OutputStream& out);

View File

@ -18,6 +18,7 @@
#include "src/sksl/ir/SkSLBoolLiteral.h"
#include "src/sksl/ir/SkSLBreakStatement.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLContinueStatement.h"
#include "src/sksl/ir/SkSLDoStatement.h"
@ -1452,6 +1453,8 @@ Value SkVMGenerator::writeExpression(const Expression& e) {
return fBuilder->splat(e.as<BoolLiteral>().value() ? ~0 : 0);
case Expression::Kind::kConstructor:
return this->writeConstructor(e.as<Constructor>());
case Expression::Kind::kConstructorArray:
return this->writeMultiArgumentConstructor(e.as<ConstructorArray>());
case Expression::Kind::kConstructorDiagonalMatrix:
return this->writeConstructorDiagonalMatrix(e.as<ConstructorDiagonalMatrix>());
case Expression::Kind::kFieldAccess:

View File

@ -8,6 +8,7 @@
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLFloatLiteral.h"
#include "src/sksl/ir/SkSLIntLiteral.h"
@ -33,7 +34,7 @@ std::unique_ptr<Expression> Constructor::Convert(const Context& context,
return MakeCompoundConstructor(context, offset, type, std::move(args));
}
if (type.isArray() && type.columns() > 0) {
return MakeArrayConstructor(context, offset, type, std::move(args));
return ConstructorArray::Convert(context, offset, type, std::move(args));
}
context.fErrors.error(offset, "cannot construct '" + type.displayName() + "'");
@ -182,39 +183,6 @@ std::unique_ptr<Expression> Constructor::MakeCompoundConstructor(const Context&
return std::make_unique<Constructor>(offset, type, std::move(args));
}
std::unique_ptr<Expression> Constructor::MakeArrayConstructor(const Context& context,
int offset,
const Type& type,
ExpressionArray args) {
SkASSERTF(type.isArray() && type.columns() > 0, "%s", type.description().c_str());
// ES2 doesn't support first-class array types.
if (context.fConfig->strictES2Mode()) {
context.fErrors.error(offset, "construction of array type '" + type.displayName() +
"' is not supported");
return nullptr;
}
// Check that the number of constructor arguments matches the array size.
if (type.columns() != args.count()) {
context.fErrors.error(offset, String::printf("invalid arguments to '%s' constructor "
"(expected %d elements, but found %d)",
type.displayName().c_str(), type.columns(),
args.count()));
return nullptr;
}
// Convert each constructor argument to the array's component type.
const Type& baseType = type.componentType();
for (std::unique_ptr<Expression>& argument : args) {
argument = baseType.coerceExpression(std::move(argument), context);
if (!argument) {
return nullptr;
}
}
return std::make_unique<Constructor>(offset, type, std::move(args));
}
std::unique_ptr<Expression> Constructor::SimplifyConversion(const Type& constructorType,
const Expression& expr) {
if (expr.is<IntLiteral>()) {
@ -306,17 +274,6 @@ Expression::ComparisonResult Constructor::compareConstant(const Expression& othe
return ComparisonResult::kEqual;
}
if (myType.isArray()) {
SkASSERT(myType.columns() == c.type().columns());
for (int col = 0; col < myType.columns(); col++) {
ComparisonResult check = this->arguments()[col]->compareConstant(*c.arguments()[col]);
if (check != ComparisonResult::kEqual) {
return check;
}
}
return ComparisonResult::kEqual;
}
SkDEBUGFAILF("compareConstant unexpected type: %s", myType.description().c_str());
return ComparisonResult::kUnknown;
}
@ -487,4 +444,14 @@ bool Constructor::getConstantBool() const {
(bool)expr.getConstantFloat();
}
AnyConstructor& Expression::asAnyConstructor() {
SkASSERT(this->isAnyConstructor());
return static_cast<AnyConstructor&>(*this);
}
const AnyConstructor& Expression::asAnyConstructor() const {
SkASSERT(this->isAnyConstructor());
return static_cast<const AnyConstructor&>(*this);
}
} // namespace SkSL

View File

@ -242,11 +242,6 @@ private:
const Type& type,
ExpressionArray args);
static std::unique_ptr<Expression> MakeArrayConstructor(const Context& context,
int offset,
const Type& type,
ExpressionArray args);
template <typename ResultType> ResultType getConstantValue(const Expression& expr) const;
template <typename ResultType>

View File

@ -0,0 +1,84 @@
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLFloatLiteral.h"
#include "src/sksl/ir/SkSLIntLiteral.h"
#include "src/sksl/ir/SkSLPrefixExpression.h"
#include "src/sksl/ir/SkSLType.h"
namespace SkSL {
std::unique_ptr<Expression> ConstructorArray::Convert(const Context& context,
int offset,
const Type& type,
ExpressionArray args) {
SkASSERTF(type.isArray() && type.columns() > 0, "%s", type.description().c_str());
// ES2 doesn't support first-class array types.
if (context.fConfig->strictES2Mode()) {
context.fErrors.error(offset, "construction of array type '" + type.displayName() +
"' is not supported");
return nullptr;
}
// Check that the number of constructor arguments matches the array size.
if (type.columns() != args.count()) {
context.fErrors.error(offset, String::printf("invalid arguments to '%s' constructor "
"(expected %d elements, but found %d)",
type.displayName().c_str(), type.columns(),
args.count()));
return nullptr;
}
// Convert each constructor argument to the array's component type.
const Type& baseType = type.componentType();
for (std::unique_ptr<Expression>& argument : args) {
argument = baseType.coerceExpression(std::move(argument), context);
if (!argument) {
return nullptr;
}
}
return ConstructorArray::Make(context, offset, type, std::move(args));
}
std::unique_ptr<Expression> ConstructorArray::Make(const Context& context,
int offset,
const Type& type,
ExpressionArray args) {
SkASSERT(!context.fConfig->strictES2Mode());
SkASSERT(type.columns() == args.count());
SkASSERT(std::all_of(args.begin(), args.end(), [&](const std::unique_ptr<Expression>& arg) {
return type.componentType() == arg->type();
}));
return std::make_unique<ConstructorArray>(offset, type, std::move(args));
}
Expression::ComparisonResult ConstructorArray::compareConstant(const Expression& other) const {
// There is only one array-constructor type, so if this comparison had type-checked
// successfully, `other` should be a ConstructorArray with the same array size.
const ConstructorArray& otherArray = other.as<ConstructorArray>();
int numColumns = this->type().columns();
SkASSERT(numColumns == otherArray.type().columns());
ComparisonResult check = ComparisonResult::kEqual;
for (int index = 0; index < numColumns; index++) {
check = this->arguments()[index]->compareConstant(*otherArray.arguments()[index]);
if (check != ComparisonResult::kEqual) {
break;
}
}
return check;
}
} // namespace SkSL

View File

@ -0,0 +1,50 @@
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_CONSTRUCTOR_ARRAY
#define SKSL_CONSTRUCTOR_ARRAY
#include "src/sksl/ir/SkSLConstructor.h"
namespace SkSL {
/**
* Represents the construction of an array type, such as "float[5](x, y, z, w, 1)".
*/
class ConstructorArray final : public MultiArgumentConstructor {
public:
static constexpr Kind kExpressionKind = Kind::kConstructorArray;
ConstructorArray(int offset, const Type& type, ExpressionArray arguments)
: INHERITED(offset, kExpressionKind, &type, std::move(arguments)) {}
// ConstructorArray::Convert will typecheck and create array-constructor expressions.
// Reports errors via the ErrorReporter; returns null on error.
static std::unique_ptr<Expression> Convert(const Context& context,
int offset,
const Type& type,
ExpressionArray args);
// ConstructorArray::Make creates array-constructor expressions; errors reported via SkASSERT.
static std::unique_ptr<Expression> Make(const Context& context,
int offset,
const Type& type,
ExpressionArray args);
std::unique_ptr<Expression> clone() const override {
return std::make_unique<ConstructorArray>(fOffset, this->type(), this->cloneArguments());
}
ComparisonResult compareConstant(const Expression& other) const override;
private:
using INHERITED = MultiArgumentConstructor;
};
} // namespace SkSL
#endif

View File

@ -16,6 +16,7 @@
namespace SkSL {
class AnyConstructor;
class Expression;
class IRGenerator;
class Variable;
@ -30,6 +31,7 @@ public:
kBoolLiteral,
kCodeString,
kConstructor,
kConstructorArray,
kConstructorDiagonalMatrix,
kDefined,
kExternalFunctionCall,
@ -80,6 +82,12 @@ public:
return this->kind() == T::kExpressionKind;
}
bool isAnyConstructor() const {
static_assert((int)Kind::kConstructorDiagonalMatrix + 1 == (int)Kind::kDefined);
return this->kind() >= Kind::kConstructor &&
this->kind() <= Kind::kConstructorDiagonalMatrix;
}
/**
* Use as<T> to downcast expressions: e.g. replace `(IntLiteral&) i` with `i.as<IntLiteral>()`.
*/
@ -95,6 +103,9 @@ public:
return static_cast<T&>(*this);
}
AnyConstructor& asAnyConstructor();
const AnyConstructor& asAnyConstructor() const;
/**
* Returns true if this expression is constant. compareConstant must be implemented for all
* constants!

View File

@ -10,6 +10,7 @@
#include "src/sksl/SkSLConstantFolder.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLFloatLiteral.h"
#include "src/sksl/ir/SkSLIntLiteral.h"
@ -44,6 +45,16 @@ static std::unique_ptr<Expression> negate_operand(const Context& context,
}
break;
case Expression::Kind::kConstructorArray:
// Convert `-array[N](literal, ...)` into `array[N](-literal, ...)`.
if (context.fConfig->fSettings.fOptimize && value->isCompileTimeConstant()) {
ConstructorArray& ctor = operand->as<ConstructorArray>();
return ConstructorArray::Make(
context, ctor.fOffset, ctor.type(),
negate_operands(context, std::move(ctor.arguments())));
}
break;
case Expression::Kind::kConstructorDiagonalMatrix:
// Convert `-matrix(literal)` into `matrix(-literal)`.
if (context.fConfig->fSettings.fOptimize && value->isCompileTimeConstant()) {

View File

@ -11,6 +11,7 @@
#include "include/private/SkSLModifiers.h"
#include "include/private/SkSLSymbol.h"
#include "src/sksl/SkSLPosition.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLType.h"
#include "src/sksl/ir/SkSLVariableReference.h"