tint/resolver: Evaluate const-expr swizzles
Bug: chromium:1341475
Change-Id: I2ac44824b08c460df759a96d0ba96f6045b60f74
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/95765
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index 42cd0bb..9891f29 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -1976,7 +1976,8 @@
ret = builder_->create<sem::Reference>(ret, ref->StorageClass(), ref->Access());
}
- return builder_->create<sem::StructMemberAccess>(expr, ret, current_statement_, object,
+ sem::Constant* val = nullptr; // TODO(crbug.com/tint/1611): Add structure support.
+ return builder_->create<sem::StructMemberAccess>(expr, ret, current_statement_, val, object,
member, has_side_effects, source_var);
}
@@ -2043,7 +2044,8 @@
// the swizzle.
ret = builder_->create<sem::Vector>(vec->type(), static_cast<uint32_t>(size));
}
- return builder_->create<sem::Swizzle>(expr, ret, current_statement_, object,
+ auto* val = EvaluateSwizzleValue(object, ret, swizzle);
+ return builder_->create<sem::Swizzle>(expr, ret, current_statement_, val, object,
std::move(swizzle), has_side_effects, source_var);
}
diff --git a/src/tint/resolver/resolver.h b/src/tint/resolver/resolver.h
index 7c1f838..9a9811f 100644
--- a/src/tint/resolver/resolver.h
+++ b/src/tint/resolver/resolver.h
@@ -218,6 +218,9 @@
const sem::Type* ty); // Note: ty is not an array or structure
const sem::Constant* EvaluateIndexValue(const sem::Expression* obj, const sem::Expression* idx);
const sem::Constant* EvaluateLiteralValue(const ast::LiteralExpression*, const sem::Type*);
+ const sem::Constant* EvaluateSwizzleValue(const sem::Expression* vector,
+ const sem::Type* type,
+ const std::vector<uint32_t>& indices);
const sem::Constant* EvaluateUnaryValue(const sem::Expression*,
const IntrinsicTable::UnaryOperator&);
diff --git a/src/tint/resolver/resolver_constants.cc b/src/tint/resolver/resolver_constants.cc
index 0c314cb..30c00e2 100644
--- a/src/tint/resolver/resolver_constants.cc
+++ b/src/tint/resolver/resolver_constants.cc
@@ -19,6 +19,7 @@
#include "src/tint/sem/abstract_float.h"
#include "src/tint/sem/abstract_int.h"
#include "src/tint/sem/constant.h"
+#include "src/tint/sem/member_accessor_expression.h"
#include "src/tint/sem/type_constructor.h"
#include "src/tint/utils/compiler_macros.h"
#include "src/tint/utils/transform.h"
@@ -537,6 +538,22 @@
return obj_val->Index(static_cast<size_t>(idx));
}
+const sem::Constant* Resolver::EvaluateSwizzleValue(const sem::Expression* vec_expr,
+ const sem::Type* type,
+ const std::vector<uint32_t>& indices) {
+ auto* vec_val = vec_expr->ConstantValue();
+ if (!vec_val) {
+ return nullptr;
+ }
+ if (indices.size() == 1) {
+ return static_cast<const Constant*>(vec_val->Index(indices[0]));
+ } else {
+ auto values = utils::Transform(
+ indices, [&](uint32_t i) { return static_cast<const Constant*>(vec_val->Index(i)); });
+ return CreateComposite(*builder_, type, std::move(values));
+ }
+}
+
const sem::Constant* Resolver::EvaluateBitcastValue(const sem::Expression*, const sem::Type*) {
// TODO(crbug.com/tint/1581): Implement @const intrinsics
return nullptr;
diff --git a/src/tint/resolver/resolver_constants_test.cc b/src/tint/resolver/resolver_constants_test.cc
index ff8a189..b8ef1b1 100644
--- a/src/tint/resolver/resolver_constants_test.cc
+++ b/src/tint/resolver/resolver_constants_test.cc
@@ -20,6 +20,7 @@
#include "src/tint/resolver/resolver_test_helper.h"
#include "src/tint/sem/expression.h"
#include "src/tint/sem/index_accessor_expression.h"
+#include "src/tint/sem/member_accessor_expression.h"
#include "src/tint/sem/test_helper.h"
using namespace tint::number_suffixes; // NOLINT
@@ -1869,6 +1870,63 @@
EXPECT_EQ(sem->ConstantValue()->As<i32>(), 1_i);
}
+TEST_F(ResolverConstantsTest, Vec3_Swizzle_Scalar) {
+ auto* expr = MemberAccessor(vec3<i32>(1_i, 2_i, 3_i), "y");
+ WrapInFunction(expr);
+
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* sem = Sem().Get(expr);
+ ASSERT_NE(sem, nullptr);
+ ASSERT_TRUE(sem->Type()->Is<sem::I32>());
+ EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
+ EXPECT_TRUE(sem->ConstantValue()->AllEqual());
+ EXPECT_FALSE(sem->ConstantValue()->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->AllZero());
+ EXPECT_EQ(sem->ConstantValue()->As<i32>(), 2_i);
+}
+
+TEST_F(ResolverConstantsTest, Vec3_Swizzle_Vector) {
+ auto* expr = MemberAccessor(vec3<i32>(1_i, 2_i, 3_i), "zx");
+ WrapInFunction(expr);
+
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* sem = Sem().Get(expr);
+ ASSERT_NE(sem, nullptr);
+ auto* vec = sem->Type()->As<sem::Vector>();
+ ASSERT_NE(vec, nullptr);
+ EXPECT_EQ(vec->Width(), 2u);
+ EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
+
+ EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllEqual());
+ EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
+ EXPECT_EQ(sem->ConstantValue()->Index(0)->As<f32>(), 3._a);
+
+ EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllEqual());
+ EXPECT_FALSE(sem->ConstantValue()->Index(1)->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
+ EXPECT_EQ(sem->ConstantValue()->Index(1)->As<f32>(), 1._a);
+}
+
+TEST_F(ResolverConstantsTest, Vec3_Swizzle_Chain) {
+ auto* expr = // (1, 2, 3) -> (2, 3, 1) -> (3, 2) -> 2
+ MemberAccessor(MemberAccessor(MemberAccessor(vec3<i32>(1_i, 2_i, 3_i), "gbr"), "yx"), "y");
+ WrapInFunction(expr);
+
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* sem = Sem().Get(expr);
+ ASSERT_NE(sem, nullptr);
+ ASSERT_TRUE(sem->Type()->Is<sem::I32>());
+ EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
+ EXPECT_TRUE(sem->ConstantValue()->AllEqual());
+ EXPECT_FALSE(sem->ConstantValue()->AnyZero());
+ EXPECT_FALSE(sem->ConstantValue()->AllZero());
+ EXPECT_EQ(sem->ConstantValue()->As<i32>(), 2_i);
+}
+
TEST_F(ResolverConstantsTest, Mat3x2_Index) {
auto* expr = IndexAccessor(
mat3x2<f32>(vec2<f32>(1._a, 2._a), vec2<f32>(3._a, 4._a), vec2<f32>(5._a, 6._a)), 2_i);
diff --git a/src/tint/sem/expression.h b/src/tint/sem/expression.h
index 05e5dac..45a67ca 100644
--- a/src/tint/sem/expression.h
+++ b/src/tint/sem/expression.h
@@ -35,7 +35,7 @@
/// @param declaration the AST node
/// @param type the resolved type of the expression
/// @param statement the statement that owns this expression
- /// @param constant the constant value of the expression. May be invalid
+ /// @param constant the constant value of the expression. May be null
/// @param has_side_effects true if this expression may have side-effects
/// @param source_var the (optional) source variable for this expression
Expression(const ast::Expression* declaration,
diff --git a/src/tint/sem/index_accessor_expression.h b/src/tint/sem/index_accessor_expression.h
index 233b0fa..3ba10ea 100644
--- a/src/tint/sem/index_accessor_expression.h
+++ b/src/tint/sem/index_accessor_expression.h
@@ -35,7 +35,7 @@
/// @param object the object expression that is being indexed
/// @param index the index expression
/// @param statement the statement that owns this expression
- /// @param constant the constant value of the expression. May be invalid
+ /// @param constant the constant value of the expression. May be null
/// @param has_side_effects whether this expression may have side effects
/// @param source_var the (optional) source variable for this expression
IndexAccessorExpression(const ast::IndexAccessorExpression* declaration,
diff --git a/src/tint/sem/member_accessor_expression.cc b/src/tint/sem/member_accessor_expression.cc
index f9929c7..7c31b0e 100644
--- a/src/tint/sem/member_accessor_expression.cc
+++ b/src/tint/sem/member_accessor_expression.cc
@@ -26,32 +26,36 @@
MemberAccessorExpression::MemberAccessorExpression(const ast::MemberAccessorExpression* declaration,
const sem::Type* type,
const Statement* statement,
+ const Constant* constant,
const Expression* object,
bool has_side_effects,
const Variable* source_var /* = nullptr */)
- : Base(declaration, type, statement, nullptr, has_side_effects, source_var), object_(object) {}
+ : Base(declaration, type, statement, constant, has_side_effects, source_var), object_(object) {}
MemberAccessorExpression::~MemberAccessorExpression() = default;
StructMemberAccess::StructMemberAccess(const ast::MemberAccessorExpression* declaration,
const sem::Type* type,
const Statement* statement,
+ const Constant* constant,
const Expression* object,
const StructMember* member,
bool has_side_effects,
const Variable* source_var /* = nullptr */)
- : Base(declaration, type, statement, object, has_side_effects, source_var), member_(member) {}
+ : Base(declaration, type, statement, constant, object, has_side_effects, source_var),
+ member_(member) {}
StructMemberAccess::~StructMemberAccess() = default;
Swizzle::Swizzle(const ast::MemberAccessorExpression* declaration,
const sem::Type* type,
const Statement* statement,
+ const Constant* constant,
const Expression* object,
std::vector<uint32_t> indices,
bool has_side_effects,
const Variable* source_var /* = nullptr */)
- : Base(declaration, type, statement, object, has_side_effects, source_var),
+ : Base(declaration, type, statement, constant, object, has_side_effects, source_var),
indices_(std::move(indices)) {}
Swizzle::~Swizzle() = default;
diff --git a/src/tint/sem/member_accessor_expression.h b/src/tint/sem/member_accessor_expression.h
index 3d60816..d8484a8 100644
--- a/src/tint/sem/member_accessor_expression.h
+++ b/src/tint/sem/member_accessor_expression.h
@@ -38,12 +38,14 @@
/// @param declaration the AST node
/// @param type the resolved type of the expression
/// @param statement the statement that owns this expression
+ /// @param constant the constant value of the expression. May be null.
/// @param object the object that holds the member being accessed
/// @param has_side_effects whether this expression may have side effects
/// @param source_var the (optional) source variable for this expression
MemberAccessorExpression(const ast::MemberAccessorExpression* declaration,
const sem::Type* type,
const Statement* statement,
+ const Constant* constant,
const Expression* object,
bool has_side_effects,
const Variable* source_var = nullptr);
@@ -67,6 +69,7 @@
/// @param declaration the AST node
/// @param type the resolved type of the expression
/// @param statement the statement that owns this expression
+ /// @param constant the constant value of the expression. May be null
/// @param object the object that holds the member being accessed
/// @param member the structure member
/// @param has_side_effects whether this expression may have side effects
@@ -74,6 +77,7 @@
StructMemberAccess(const ast::MemberAccessorExpression* declaration,
const sem::Type* type,
const Statement* statement,
+ const Constant* constant,
const Expression* object,
const StructMember* member,
bool has_side_effects,
@@ -97,6 +101,7 @@
/// @param declaration the AST node
/// @param type the resolved type of the expression
/// @param statement the statement that owns this expression
+ /// @param constant the constant value of the expression. May be null
/// @param object the object that holds the member being accessed
/// @param indices the swizzle indices
/// @param has_side_effects whether this expression may have side effects
@@ -104,6 +109,7 @@
Swizzle(const ast::MemberAccessorExpression* declaration,
const sem::Type* type,
const Statement* statement,
+ const Constant* constant,
const Expression* object,
std::vector<uint32_t> indices,
bool has_side_effects,
diff --git a/src/tint/sem/variable.h b/src/tint/sem/variable.h
index 28e8f97..e5a5cec 100644
--- a/src/tint/sem/variable.h
+++ b/src/tint/sem/variable.h
@@ -47,7 +47,7 @@
/// @param type the variable type
/// @param storage_class the variable storage class
/// @param access the variable access control type
- /// @param constant_value the constant value for the variable. May be invalid
+ /// @param constant_value the constant value for the variable. May be null
Variable(const ast::Variable* declaration,
const sem::Type* type,
ast::StorageClass storage_class,
@@ -105,7 +105,7 @@
/// @param storage_class the variable storage class
/// @param access the variable access control type
/// @param statement the statement that declared this local variable
- /// @param constant_value the constant value for the variable. May be invalid
+ /// @param constant_value the constant value for the variable. May be null
LocalVariable(const ast::Variable* declaration,
const sem::Type* type,
ast::StorageClass storage_class,
@@ -139,7 +139,7 @@
/// @param type the variable type
/// @param storage_class the variable storage class
/// @param access the variable access control type
- /// @param constant_value the constant value for the variable. May be invalid
+ /// @param constant_value the constant value for the variable. May be null
/// @param binding_point the optional resource binding point of the variable
GlobalVariable(const ast::Variable* declaration,
const sem::Type* type,