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>
This commit is contained in:
Ben Clayton
2022-07-07 17:49:02 +00:00
committed by Dawn LUCI CQ
parent d5f53ab580
commit 63e6f820d8
35 changed files with 2822 additions and 2780 deletions

View File

@@ -1976,7 +1976,8 @@ sem::Expression* Resolver::MemberAccessor(const ast::MemberAccessorExpression* e
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 @@ sem::Expression* Resolver::MemberAccessor(const ast::MemberAccessorExpression* e
// 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);
}

View File

@@ -218,6 +218,9 @@ class Resolver {
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&);

View File

@@ -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 @@ const sem::Constant* Resolver::EvaluateIndexValue(const sem::Expression* obj_exp
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;

View File

@@ -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 @@ TEST_F(ResolverConstantsTest, Vec3_Index_OOB_Low) {
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);

View File

@@ -35,7 +35,7 @@ class Expression : public Castable<Expression, Node> {
/// @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,

View File

@@ -35,7 +35,7 @@ class IndexAccessorExpression final : public Castable<IndexAccessorExpression, E
/// @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,

View File

@@ -26,32 +26,36 @@ namespace tint::sem {
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;

View File

@@ -38,12 +38,14 @@ class MemberAccessorExpression : public Castable<MemberAccessorExpression, Expre
/// @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 @@ class StructMemberAccess final : public Castable<StructMemberAccess, MemberAcces
/// @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 @@ class StructMemberAccess final : public Castable<StructMemberAccess, MemberAcces
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 @@ class Swizzle final : public Castable<Swizzle, MemberAccessorExpression> {
/// @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 @@ class Swizzle final : public Castable<Swizzle, MemberAccessorExpression> {
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,

View File

@@ -47,7 +47,7 @@ class Variable : public Castable<Variable, Node> {
/// @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 @@ class LocalVariable final : public Castable<LocalVariable, Variable> {
/// @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 @@ class GlobalVariable final : public Castable<GlobalVariable, Variable> {
/// @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,