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>
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index ade9b3f..0f174d4 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -821,12 +821,12 @@
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 @@
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 @@
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 @@
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) {
diff --git a/src/sksl/SkSLInliner.cpp b/src/sksl/SkSLInliner.cpp
index 6d32357..9c67af0 100644
--- a/src/sksl/SkSLInliner.cpp
+++ b/src/sksl/SkSLInliner.cpp
@@ -345,7 +345,7 @@
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>();
diff --git a/src/sksl/SkSLRehydrator.cpp b/src/sksl/SkSLRehydrator.cpp
index 107fd7c..8007c92 100644
--- a/src/sksl/SkSLRehydrator.cpp
+++ b/src/sksl/SkSLRehydrator.cpp
@@ -469,7 +469,7 @@
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();
diff --git a/src/sksl/dsl/priv/DSLWriter.cpp b/src/sksl/dsl/priv/DSLWriter.cpp
index c4a7f0b..7d5bd8b 100644
--- a/src/sksl/dsl/priv/DSLWriter.cpp
+++ b/src/sksl/dsl/priv/DSLWriter.cpp
@@ -135,7 +135,7 @@
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,
diff --git a/src/sksl/ir/SkSLFieldAccess.cpp b/src/sksl/ir/SkSLFieldAccess.cpp
new file mode 100644
index 0000000..3be4ca1
--- /dev/null
+++ b/src/sksl/ir/SkSLFieldAccess.cpp
@@ -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
diff --git a/src/sksl/ir/SkSLFieldAccess.h b/src/sksl/ir/SkSLFieldAccess.h
index 3291c11..6e9d941 100644
--- a/src/sksl/ir/SkSLFieldAccess.h
+++ b/src/sksl/ir/SkSLFieldAccess.h
@@ -36,6 +36,17 @@
, 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;
}