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:
parent
358858fe4c
commit
7384b37576
@ -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",
|
||||
|
@ -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()) {
|
||||
|
@ -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());
|
||||
|
@ -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>());
|
||||
|
@ -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"
|
||||
|
@ -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()) {
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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>());
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
84
src/sksl/ir/SkSLConstructorArray.cpp
Normal file
84
src/sksl/ir/SkSLConstructorArray.cpp
Normal 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
|
50
src/sksl/ir/SkSLConstructorArray.h
Normal file
50
src/sksl/ir/SkSLConstructorArray.h
Normal 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
|
@ -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!
|
||||
|
@ -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()) {
|
||||
|
@ -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"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user