mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-21 18:59:21 +00:00
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:
committed by
Dawn LUCI CQ
parent
d5f53ab580
commit
63e6f820d8
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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&);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user