Add Convert/Make factory functions to FieldAccess.

Change-Id: Ib1f5296c017374b833654f988ff89d11d8f78b4d
Bug: skia:11342
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/380458
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
John Stiles 2021-03-08 09:18:21 -05:00
parent ece1bf0afb
commit 06d600fb9d
7 changed files with 65 additions and 30 deletions

View File

@ -105,6 +105,7 @@ skia_sksl_sources = [
"$_src/sksl/ir/SkSLExternalFunctionCall.h",
"$_src/sksl/ir/SkSLExternalFunctionReference.h",
"$_src/sksl/ir/SkSLField.h",
"$_src/sksl/ir/SkSLFieldAccess.cpp",
"$_src/sksl/ir/SkSLFieldAccess.h",
"$_src/sksl/ir/SkSLFloatLiteral.h",
"$_src/sksl/ir/SkSLForStatement.cpp",

View File

@ -821,12 +821,12 @@ std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
VariableReference::RefKind::kWrite);
};
auto Field = [&](const Variable* var, int idx) -> std::unique_ptr<Expression> {
return std::make_unique<FieldAccess>(Ref(var), idx,
FieldAccess::OwnerKind::kAnonymousInterfaceBlock);
return FieldAccess::Make(fContext, Ref(var), idx,
FieldAccess::OwnerKind::kAnonymousInterfaceBlock);
};
auto Pos = [&]() -> std::unique_ptr<Expression> {
return std::make_unique<FieldAccess>(WRef(skPerVertex), 0,
FieldAccess::OwnerKind::kAnonymousInterfaceBlock);
return FieldAccess::Make(fContext, WRef(skPerVertex), 0,
FieldAccess::OwnerKind::kAnonymousInterfaceBlock);
};
auto Adjust = [&]() -> std::unique_ptr<Expression> {
return fRTAdjustInterfaceBlock ? Field(fRTAdjustInterfaceBlock, fRTAdjustFieldIndex)
@ -1577,9 +1577,8 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(int offset, StringFra
const Field* field = &result->as<Field>();
auto base = std::make_unique<VariableReference>(offset, &field->owner(),
VariableReference::RefKind::kRead);
return std::make_unique<FieldAccess>(std::move(base),
field->fieldIndex(),
FieldAccess::OwnerKind::kAnonymousInterfaceBlock);
return FieldAccess::Make(fContext, std::move(base), field->fieldIndex(),
FieldAccess::OwnerKind::kAnonymousInterfaceBlock);
}
case Symbol::Kind::kType: {
const Type* t = &result->as<Type>();
@ -1837,21 +1836,6 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
return PrefixExpression::Convert(fContext, expression.getOperator(), std::move(base));
}
std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
StringFragment field) {
const Type& baseType = base->type();
auto fields = baseType.fields();
for (size_t i = 0; i < fields.size(); i++) {
if (fields[i].fName == field) {
return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
}
}
this->errorReporter().error(
base->fOffset,
"type '" + baseType.displayName() + "' does not have a field named '" + field + "'");
return nullptr;
}
// Swizzles are complicated due to constant components. The most difficult case is a mask like
// '.x1w0'. A naive approach might turn that into 'float4(base.x, 1, base.w, 0)', but that evaluates
// 'base' twice. We instead group the swizzle mask ('xw') and constants ('1, 0') together and use a
@ -2045,12 +2029,10 @@ std::unique_ptr<Expression> IRGenerator::convertFieldExpression(const ASTNode& f
if (baseType == *fContext.fTypes.fSkCaps) {
return Setting::Convert(fContext, fieldNode.fOffset, field);
}
switch (baseType.typeKind()) {
case Type::TypeKind::kStruct:
return this->convertField(std::move(base), field);
default:
return this->convertSwizzle(std::move(base), field);
if (baseType.isStruct()) {
return FieldAccess::Convert(fContext, std::move(base), field);
}
return this->convertSwizzle(std::move(base), field);
}
std::unique_ptr<Expression> IRGenerator::convertScopeExpression(const ASTNode& scopeNode) {

View File

@ -345,7 +345,7 @@ std::unique_ptr<Expression> Inliner::inlineExpression(int offset,
return expression.clone();
case Expression::Kind::kFieldAccess: {
const FieldAccess& f = expression.as<FieldAccess>();
return std::make_unique<FieldAccess>(expr(f.base()), f.fieldIndex(), f.ownerKind());
return FieldAccess::Make(*fContext, expr(f.base()), f.fieldIndex(), f.ownerKind());
}
case Expression::Kind::kFunctionCall: {
const FunctionCall& funcCall = expression.as<FunctionCall>();

View File

@ -469,7 +469,7 @@ std::unique_ptr<Expression> Rehydrator::expression() {
std::unique_ptr<Expression> base = this->expression();
int index = this->readU8();
FieldAccess::OwnerKind ownerKind = (FieldAccess::OwnerKind) this->readU8();
return std::make_unique<FieldAccess>(std::move(base), index, ownerKind);
return FieldAccess::Make(fContext, std::move(base), index, ownerKind);
}
case Rehydrator::kFloatLiteral_Command: {
const Type* type = this->type();

View File

@ -135,7 +135,7 @@ std::unique_ptr<SkSL::Expression> DSLWriter::ConvertBinary(std::unique_ptr<Expre
std::unique_ptr<SkSL::Expression> DSLWriter::ConvertField(std::unique_ptr<Expression> base,
const char* name) {
return IRGenerator().convertField(std::move(base), name);
return FieldAccess::Convert(Context(), std::move(base), name);
}
std::unique_ptr<SkSL::Expression> DSLWriter::ConvertIndex(std::unique_ptr<Expression> base,

View File

@ -0,0 +1,41 @@
/*
* 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/SkSLContext.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
namespace SkSL {
std::unique_ptr<Expression> FieldAccess::Convert(const Context& context,
std::unique_ptr<Expression> base,
StringFragment field) {
const Type& baseType = base->type();
if (baseType.isStruct()) {
const std::vector<Type::Field>& fields = baseType.fields();
for (size_t i = 0; i < fields.size(); i++) {
if (fields[i].fName == field) {
return FieldAccess::Make(context, std::move(base), (int) i);
}
}
}
context.fErrors.error(base->fOffset, "type '" + baseType.displayName() +
"' does not have a field named '" + field + "'");
return nullptr;
}
std::unique_ptr<Expression> FieldAccess::Make(const Context& context,
std::unique_ptr<Expression> base,
int fieldIndex,
OwnerKind ownerKind) {
SkASSERT(base->type().isStruct());
SkASSERT(fieldIndex >= 0);
SkASSERT(fieldIndex < (int) base->type().fields().size());
return std::make_unique<FieldAccess>(std::move(base), fieldIndex, ownerKind);
}
} // namespace SkSL

View File

@ -36,6 +36,17 @@ public:
, fOwnerKind(ownerKind)
, fBase(std::move(base)) {}
// Returns a field-access expression; reports errors via the ErrorReporter.
static std::unique_ptr<Expression> Convert(const Context& context,
std::unique_ptr<Expression> base,
StringFragment field);
// Returns a field-access expression; reports errors via ASSERT.
static std::unique_ptr<Expression> Make(const Context& context,
std::unique_ptr<Expression> base,
int fieldIndex,
OwnerKind ownerKind = OwnerKind::kDefault);
std::unique_ptr<Expression>& base() {
return fBase;
}