tint: Implement const eval of unary complement
Bug: tint:1581 Bug: chromium:1343242 Change-Id: I76b4f041494ceb2afcf5a604fcda32e046ffca35 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/96100 Reviewed-by: Antonio Maiorano <amaiorano@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
83bd738ab4
commit
ac660c2794
|
@ -131,6 +131,7 @@ match f32f16: f32 | f16
|
|||
match fiu32: f32 | i32 | u32
|
||||
match fi32: f32 | i32
|
||||
match iu32: i32 | u32
|
||||
match aiu32: ai | i32 | u32
|
||||
match scalar: f32 | f16 | i32 | u32 | bool
|
||||
match abstract_or_scalar: ai | af | f32 | f16 | i32 | u32 | bool
|
||||
match af_f32: af | f32
|
||||
|
@ -816,8 +817,8 @@ ctor mat4x4<T: af_f32f16>(vec4<T>, vec4<T>, vec4<T>, vec4<T>) -> mat4x4<T>
|
|||
op ! (bool) -> bool
|
||||
op ! <N: num> (vec<N, bool>) -> vec<N, bool>
|
||||
|
||||
op ~ <T: iu32>(T) -> T
|
||||
op ~ <T: iu32, N: num> (vec<N, T>) -> vec<N, T>
|
||||
@const op ~ <T: aiu32>(T) -> T
|
||||
@const op ~ <T: aiu32, N: num> (vec<N, T>) -> vec<N, T>
|
||||
|
||||
op - <T: fi32>(T) -> T
|
||||
op - <T: fi32, N: num> (vec<N, T>) -> vec<N, T>
|
||||
|
|
|
@ -64,6 +64,20 @@ auto TypeDispatch(const sem::Type* type, F&& f) {
|
|||
[&](const sem::Bool*) { return f(static_cast<bool>(0)); });
|
||||
}
|
||||
|
||||
/// IntegerDispatch is a helper for calling the function `f`, passing the integer value of the
|
||||
/// constant c.
|
||||
/// @returns the value returned by calling `f`.
|
||||
/// @note `c` must be of an integer type. Other types will not call `f`, and will return the
|
||||
/// zero-initialized value of the return type for `f`
|
||||
template <typename F>
|
||||
auto IntegerDispatch(const sem::Constant* c, F&& f) {
|
||||
return Switch(
|
||||
c->Type(), //
|
||||
[&](const sem::AbstractInt*) { return f(c->As<AInt>()); }, //
|
||||
[&](const sem::I32*) { return f(c->As<i32>()); }, //
|
||||
[&](const sem::U32*) { return f(c->As<u32>()); });
|
||||
}
|
||||
|
||||
/// @returns `value` if `T` is not a Number, otherwise ValueOf returns the inner value of the
|
||||
/// Number.
|
||||
template <typename T>
|
||||
|
@ -100,6 +114,9 @@ const Constant* CreateComposite(ProgramBuilder& builder,
|
|||
/// Element implements the Constant interface.
|
||||
template <typename T>
|
||||
struct Element : Constant {
|
||||
static_assert(!std::is_same_v<UnwrapNumber<T>, T> || std::is_same_v<T, bool>,
|
||||
"T must be a Number or bool");
|
||||
|
||||
Element(const sem::Type* t, T v) : type(t), value(v) {}
|
||||
~Element() override = default;
|
||||
const sem::Type* Type() const override { return type; }
|
||||
|
@ -395,6 +412,23 @@ const Constant* CreateComposite(ProgramBuilder& builder,
|
|||
}
|
||||
}
|
||||
|
||||
/// TransformElements constructs a new constant by applying the transformation function 'f' on each
|
||||
/// of the most deeply nested elements of 'c'.
|
||||
template <typename F>
|
||||
const Constant* TransformElements(ProgramBuilder& builder, const sem::Constant* c, F&& f) {
|
||||
uint32_t n = 0;
|
||||
auto* ty = c->Type();
|
||||
auto* el_ty = sem::Type::ElementOf(ty, &n);
|
||||
if (el_ty == ty) {
|
||||
return f(c);
|
||||
}
|
||||
std::vector<const sem::Constant*> els(n);
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
els[i] = TransformElements(builder, c->Index(i), f);
|
||||
}
|
||||
return CreateComposite(builder, c->Type(), std::move(els));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ConstEval::ConstEval(ProgramBuilder& b) : builder(b) {}
|
||||
|
@ -478,7 +512,9 @@ const sem::Constant* ConstEval::Identity(const sem::Type*, ArgumentList args, si
|
|||
return args[0]->ConstantValue();
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::VecSplat(const sem::Type* ty, ArgumentList args, size_t) {
|
||||
const sem::Constant* ConstEval::VecSplat(const sem::Type* ty,
|
||||
sem::Expression const* const* args,
|
||||
size_t) {
|
||||
if (auto* arg = args[0]->ConstantValue()) {
|
||||
return builder.create<Splat>(ty, arg, static_cast<const sem::Vector*>(ty)->Width());
|
||||
}
|
||||
|
@ -603,6 +639,16 @@ const sem::Constant* ConstEval::Bitcast(const sem::Type*, const sem::Expression*
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::OpComplement(const sem::Type*,
|
||||
sem::Expression const* const* args,
|
||||
size_t) {
|
||||
return TransformElements(builder, args[0]->ConstantValue(), [&](const sem::Constant* c) {
|
||||
return IntegerDispatch(c, [&](auto i) { //
|
||||
return CreateElement(builder, c->Type(), decltype(i)(~i.value));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
utils::Result<const sem::Constant*> ConstEval::Convert(const sem::Type* target_ty,
|
||||
const sem::Constant* value,
|
||||
const Source& source) {
|
||||
|
|
|
@ -174,6 +174,19 @@ class ConstEval {
|
|||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* MatCtorV(const sem::Type* ty, ArgumentList args, size_t num_args);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Operators
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Complement operator '~'
|
||||
/// @param ty the integer type
|
||||
/// @param args the input arguments
|
||||
/// @param num_args the number of input arguments (must be 1)
|
||||
/// @return the result value, or null if the value cannot be calculated
|
||||
const sem::Constant* OpComplement(const sem::Type* ty,
|
||||
sem::Expression const* const* args,
|
||||
size_t num_args);
|
||||
|
||||
private:
|
||||
/// Adds the given error message to the diagnostics
|
||||
void AddError(const std::string& msg, const Source& source) const;
|
||||
|
|
|
@ -26,13 +26,13 @@ using namespace tint::number_suffixes; // NOLINT
|
|||
namespace tint::resolver {
|
||||
namespace {
|
||||
|
||||
using ResolverConstantsTest = ResolverTest;
|
||||
using ResolverConstEvalTest = ResolverTest;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Construction
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST_F(ResolverConstantsTest, Scalar_i32) {
|
||||
TEST_F(ResolverConstEvalTest, Scalar_i32) {
|
||||
auto* expr = Expr(99_i);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -48,7 +48,7 @@ TEST_F(ResolverConstantsTest, Scalar_i32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->As<AInt>(), 99);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Scalar_u32) {
|
||||
TEST_F(ResolverConstEvalTest, Scalar_u32) {
|
||||
auto* expr = Expr(99_u);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -64,7 +64,7 @@ TEST_F(ResolverConstantsTest, Scalar_u32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->As<AInt>(), 99u);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Scalar_f32) {
|
||||
TEST_F(ResolverConstEvalTest, Scalar_f32) {
|
||||
auto* expr = Expr(9.9_f);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -80,7 +80,7 @@ TEST_F(ResolverConstantsTest, Scalar_f32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->As<AFloat>().value, 9.9f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Scalar_f16) {
|
||||
TEST_F(ResolverConstEvalTest, Scalar_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = Expr(9.9_h);
|
||||
|
@ -99,7 +99,7 @@ TEST_F(ResolverConstantsTest, Scalar_f16) {
|
|||
EXPECT_EQ(sem->ConstantValue()->As<AFloat>(), 9.8984375f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Scalar_bool) {
|
||||
TEST_F(ResolverConstEvalTest, Scalar_bool) {
|
||||
auto* expr = Expr(true);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -115,7 +115,7 @@ TEST_F(ResolverConstantsTest, Scalar_bool) {
|
|||
EXPECT_EQ(sem->ConstantValue()->As<bool>(), true);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_ZeroInit_i32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_ZeroInit_i32) {
|
||||
auto* expr = vec3<i32>();
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -148,7 +148,7 @@ TEST_F(ResolverConstantsTest, Vec3_ZeroInit_i32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AInt>(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_ZeroInit_u32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_ZeroInit_u32) {
|
||||
auto* expr = vec3<u32>();
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -181,7 +181,7 @@ TEST_F(ResolverConstantsTest, Vec3_ZeroInit_u32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AInt>(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_ZeroInit_f32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_ZeroInit_f32) {
|
||||
auto* expr = vec3<f32>();
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -214,7 +214,7 @@ TEST_F(ResolverConstantsTest, Vec3_ZeroInit_f32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AFloat>(), 0._a);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_ZeroInit_f16) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_ZeroInit_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = vec3<f16>();
|
||||
|
@ -249,7 +249,7 @@ TEST_F(ResolverConstantsTest, Vec3_ZeroInit_f16) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AFloat>(), 0._a);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_ZeroInit_bool) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_ZeroInit_bool) {
|
||||
auto* expr = vec3<bool>();
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -282,7 +282,7 @@ TEST_F(ResolverConstantsTest, Vec3_ZeroInit_bool) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<bool>(), false);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Splat_i32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Splat_i32) {
|
||||
auto* expr = vec3<i32>(99_i);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -315,7 +315,7 @@ TEST_F(ResolverConstantsTest, Vec3_Splat_i32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AInt>(), 99);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Splat_u32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Splat_u32) {
|
||||
auto* expr = vec3<u32>(99_u);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -348,7 +348,7 @@ TEST_F(ResolverConstantsTest, Vec3_Splat_u32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AInt>(), 99u);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Splat_f32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Splat_f32) {
|
||||
auto* expr = vec3<f32>(9.9_f);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -381,7 +381,7 @@ TEST_F(ResolverConstantsTest, Vec3_Splat_f32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AFloat>(), 9.9f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Splat_f16) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Splat_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = vec3<f16>(9.9_h);
|
||||
|
@ -417,7 +417,7 @@ TEST_F(ResolverConstantsTest, Vec3_Splat_f16) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AFloat>(), 9.8984375f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Splat_bool) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Splat_bool) {
|
||||
auto* expr = vec3<bool>(true);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -450,7 +450,7 @@ TEST_F(ResolverConstantsTest, Vec3_Splat_bool) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<bool>(), true);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_FullConstruct_i32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_FullConstruct_i32) {
|
||||
auto* expr = vec3<i32>(1_i, 2_i, 3_i);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -483,7 +483,7 @@ TEST_F(ResolverConstantsTest, Vec3_FullConstruct_i32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AInt>(), 3);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_FullConstruct_u32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_FullConstruct_u32) {
|
||||
auto* expr = vec3<u32>(1_u, 2_u, 3_u);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -516,7 +516,7 @@ TEST_F(ResolverConstantsTest, Vec3_FullConstruct_u32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AInt>(), 3);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_FullConstruct_f32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_FullConstruct_f32) {
|
||||
auto* expr = vec3<f32>(1_f, 2_f, 3_f);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -549,7 +549,7 @@ TEST_F(ResolverConstantsTest, Vec3_FullConstruct_f32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AFloat>(), 3.f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_FullConstruct_f16) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_FullConstruct_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = vec3<f16>(1_h, 2_h, 3_h);
|
||||
|
@ -584,7 +584,7 @@ TEST_F(ResolverConstantsTest, Vec3_FullConstruct_f16) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AFloat>(), 3.f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_FullConstruct_bool) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_FullConstruct_bool) {
|
||||
auto* expr = vec3<bool>(true, false, true);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -617,7 +617,7 @@ TEST_F(ResolverConstantsTest, Vec3_FullConstruct_bool) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<bool>(), true);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_i32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_i32) {
|
||||
auto* expr = vec3<i32>(1_i, vec2<i32>(2_i, 3_i));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -650,7 +650,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_i32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AInt>(), 3);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_u32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_u32) {
|
||||
auto* expr = vec3<u32>(vec2<u32>(1_u, 2_u), 3_u);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -683,7 +683,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_u32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AInt>(), 3);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f32) {
|
||||
auto* expr = vec3<f32>(1_f, vec2<f32>(2_f, 3_f));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -716,7 +716,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AFloat>(), 3.f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f32_all_10) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f32_all_10) {
|
||||
auto* expr = vec3<f32>(10_f, vec2<f32>(10_f, 10_f));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -749,7 +749,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f32_all_10) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<f32>(), 10_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f32_all_positive_0) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f32_all_positive_0) {
|
||||
auto* expr = vec3<f32>(0_f, vec2<f32>(0_f, 0_f));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -782,7 +782,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f32_all_positive_0) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<f32>(), 0_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f32_all_negative_0) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f32_all_negative_0) {
|
||||
auto* expr = vec3<f32>(vec2<f32>(-0_f, -0_f), -0_f);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -815,7 +815,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f32_all_negative_0) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<f32>(), -0_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f32_mixed_sign_0) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f32_mixed_sign_0) {
|
||||
auto* expr = vec3<f32>(0_f, vec2<f32>(-0_f, 0_f));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -848,7 +848,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f32_mixed_sign_0) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<f32>(), 0_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f16) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = vec3<f16>(1_h, vec2<f16>(2_h, 3_h));
|
||||
|
@ -883,7 +883,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f16) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AFloat>(), 3.f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f16_all_10) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f16_all_10) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = vec3<f16>(10_h, vec2<f16>(10_h, 10_h));
|
||||
|
@ -918,7 +918,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f16_all_10) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<f16>(), 10_h);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f16_all_positive_0) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f16_all_positive_0) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = vec3<f16>(0_h, vec2<f16>(0_h, 0_h));
|
||||
|
@ -953,7 +953,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f16_all_positive_0) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<f16>(), 0_h);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f16_all_negative_0) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f16_all_negative_0) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = vec3<f16>(vec2<f16>(-0_h, -0_h), -0_h);
|
||||
|
@ -988,7 +988,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f16_all_negative_0) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<f16>(), -0_h);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f16_mixed_sign_0) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_f16_mixed_sign_0) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = vec3<f16>(0_h, vec2<f16>(-0_h, 0_h));
|
||||
|
@ -1023,7 +1023,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f16_mixed_sign_0) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<f16>(), 0_h);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_bool) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_bool) {
|
||||
auto* expr = vec3<bool>(vec2<bool>(true, false), true);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1056,7 +1056,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_bool) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<bool>(), true);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_all_true) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_all_true) {
|
||||
auto* expr = vec3<bool>(true, vec2<bool>(true, true));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1089,7 +1089,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_all_true) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<bool>(), true);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_all_false) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_MixConstruct_all_false) {
|
||||
auto* expr = vec3<bool>(false, vec2<bool>(false, false));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1122,7 +1122,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_all_false) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<bool>(), false);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Convert_f32_to_i32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Convert_f32_to_i32) {
|
||||
auto* expr = vec3<i32>(vec3<f32>(1.1_f, 2.2_f, 3.3_f));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1155,7 +1155,7 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_f32_to_i32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AInt>(), 3);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Convert_u32_to_f32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Convert_u32_to_f32) {
|
||||
auto* expr = vec3<f32>(vec3<u32>(10_u, 20_u, 30_u));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1188,7 +1188,7 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_u32_to_f32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AFloat>(), 30.f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Convert_f16_to_i32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Convert_f16_to_i32) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = vec3<i32>(vec3<f16>(1.1_h, 2.2_h, 3.3_h));
|
||||
|
@ -1223,7 +1223,7 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_f16_to_i32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AInt>(), 3_i);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Convert_u32_to_f16) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Convert_u32_to_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = vec3<f16>(vec3<u32>(10_u, 20_u, 30_u));
|
||||
|
@ -1258,7 +1258,7 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_u32_to_f16) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AFloat>(), 30.f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Convert_Large_f32_to_i32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Convert_Large_f32_to_i32) {
|
||||
auto* expr = vec3<i32>(vec3<f32>(1e10_f, -1e20_f, 1e30_f));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1291,7 +1291,7 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_Large_f32_to_i32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AInt>(), i32::kHighest);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Convert_Large_f32_to_u32) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Convert_Large_f32_to_u32) {
|
||||
auto* expr = vec3<u32>(vec3<f32>(1e10_f, -1e20_f, 1e30_f));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1324,7 +1324,7 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_Large_f32_to_u32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AInt>(), u32::kHighest);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Convert_Large_f32_to_f16) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Convert_Large_f32_to_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = vec3<f16>(vec3<f32>(1e10_f, -1e20_f, 1e30_f));
|
||||
|
@ -1361,7 +1361,7 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_Large_f32_to_f16) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<AFloat>(), kInf);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Convert_Small_f32_to_f16) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Convert_Small_f32_to_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = vec3<f16>(vec3<f32>(1e-20_f, -2e-30_f, 3e-40_f));
|
||||
|
@ -1399,7 +1399,7 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_Small_f32_to_f16) {
|
|||
EXPECT_FALSE(std::signbit(sem->ConstantValue()->Index(2)->As<AFloat>().value));
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Mat2x3_ZeroInit_f32) {
|
||||
TEST_F(ResolverConstEvalTest, Mat2x3_ZeroInit_f32) {
|
||||
auto* expr = mat2x3<f32>();
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1448,7 +1448,7 @@ TEST_F(ResolverConstantsTest, Mat2x3_ZeroInit_f32) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->As<f32>(), 0._f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Mat2x3_ZeroInit_f16) {
|
||||
TEST_F(ResolverConstEvalTest, Mat2x3_ZeroInit_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* expr = mat2x3<f16>();
|
||||
|
@ -1499,7 +1499,7 @@ TEST_F(ResolverConstantsTest, Mat2x3_ZeroInit_f16) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->As<f16>(), 0._h);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Mat3x2_Construct_Scalars_af) {
|
||||
TEST_F(ResolverConstEvalTest, Mat3x2_Construct_Scalars_af) {
|
||||
auto* expr = Construct(ty.mat(nullptr, 3, 2), 1.0_a, 2.0_a, 3.0_a, 4.0_a, 5.0_a, 6.0_a);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1548,7 +1548,7 @@ TEST_F(ResolverConstantsTest, Mat3x2_Construct_Scalars_af) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->Index(1)->As<AFloat>(), 6._a);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Mat3x2_Construct_Columns_af) {
|
||||
TEST_F(ResolverConstEvalTest, Mat3x2_Construct_Columns_af) {
|
||||
auto* expr = Construct(ty.mat(nullptr, 3, 2), //
|
||||
vec(nullptr, 2u, 1.0_a, 2.0_a), //
|
||||
vec(nullptr, 2u, 3.0_a, 4.0_a), //
|
||||
|
@ -1600,7 +1600,7 @@ TEST_F(ResolverConstantsTest, Mat3x2_Construct_Columns_af) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->Index(1)->As<AFloat>(), 6._a);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Array_i32_Zero) {
|
||||
TEST_F(ResolverConstEvalTest, Array_i32_Zero) {
|
||||
auto* expr = Construct(ty.array<i32, 4>());
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1638,7 +1638,7 @@ TEST_F(ResolverConstantsTest, Array_i32_Zero) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(3)->As<i32>(), 0_i);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Array_f32_Zero) {
|
||||
TEST_F(ResolverConstEvalTest, Array_f32_Zero) {
|
||||
auto* expr = Construct(ty.array<f32, 4>());
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1676,7 +1676,7 @@ TEST_F(ResolverConstantsTest, Array_f32_Zero) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(3)->As<f32>(), 0_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Array_vec3_f32_Zero) {
|
||||
TEST_F(ResolverConstEvalTest, Array_vec3_f32_Zero) {
|
||||
auto* expr = Construct(ty.array(ty.vec3<f32>(), 2_u));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1724,7 +1724,7 @@ TEST_F(ResolverConstantsTest, Array_vec3_f32_Zero) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->As<f32>(), 0_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Array_Struct_f32_Zero) {
|
||||
TEST_F(ResolverConstEvalTest, Array_Struct_f32_Zero) {
|
||||
Structure("S", {
|
||||
Member("m1", ty.f32()),
|
||||
Member("m2", ty.f32()),
|
||||
|
@ -1766,7 +1766,7 @@ TEST_F(ResolverConstantsTest, Array_Struct_f32_Zero) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->As<f32>(), 0_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Array_i32_Elements) {
|
||||
TEST_F(ResolverConstEvalTest, Array_i32_Elements) {
|
||||
auto* expr = Construct(ty.array<i32, 4>(), 10_i, 20_i, 30_i, 40_i);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1804,7 +1804,7 @@ TEST_F(ResolverConstantsTest, Array_i32_Elements) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(3)->As<i32>(), 40_i);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Array_f32_Elements) {
|
||||
TEST_F(ResolverConstEvalTest, Array_f32_Elements) {
|
||||
auto* expr = Construct(ty.array<f32, 4>(), 10_f, 20_f, 30_f, 40_f);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -1842,7 +1842,7 @@ TEST_F(ResolverConstantsTest, Array_f32_Elements) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(3)->As<f32>(), 40_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Array_vec3_f32_Elements) {
|
||||
TEST_F(ResolverConstEvalTest, Array_vec3_f32_Elements) {
|
||||
auto* expr = Construct(ty.array(ty.vec3<f32>(), 2_u), //
|
||||
vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f));
|
||||
WrapInFunction(expr);
|
||||
|
@ -1867,7 +1867,7 @@ TEST_F(ResolverConstantsTest, Array_vec3_f32_Elements) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->As<f32>(), 6_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Array_Struct_f32_Elements) {
|
||||
TEST_F(ResolverConstEvalTest, Array_Struct_f32_Elements) {
|
||||
Structure("S", {
|
||||
Member("m1", ty.f32()),
|
||||
Member("m2", ty.f32()),
|
||||
|
@ -1911,7 +1911,7 @@ TEST_F(ResolverConstantsTest, Array_Struct_f32_Elements) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->As<f32>(), 4_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Struct_I32s_ZeroInit) {
|
||||
TEST_F(ResolverConstEvalTest, Struct_I32s_ZeroInit) {
|
||||
Structure("S", {Member("m1", ty.i32()), Member("m2", ty.i32()), Member("m3", ty.i32())});
|
||||
auto* expr = Construct(ty.type_name("S"));
|
||||
WrapInFunction(expr);
|
||||
|
@ -1948,7 +1948,7 @@ TEST_F(ResolverConstantsTest, Struct_I32s_ZeroInit) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<i32>(), 0_i);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Struct_MixedScalars_ZeroInit) {
|
||||
TEST_F(ResolverConstEvalTest, Struct_MixedScalars_ZeroInit) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
Structure("S", {
|
||||
|
@ -2005,7 +2005,7 @@ TEST_F(ResolverConstantsTest, Struct_MixedScalars_ZeroInit) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(4)->As<bool>(), false);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Struct_VectorF32s_ZeroInit) {
|
||||
TEST_F(ResolverConstEvalTest, Struct_VectorF32s_ZeroInit) {
|
||||
Structure("S", {
|
||||
Member("m1", ty.vec3<f32>()),
|
||||
Member("m2", ty.vec3<f32>()),
|
||||
|
@ -2055,7 +2055,7 @@ TEST_F(ResolverConstantsTest, Struct_VectorF32s_ZeroInit) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->Index(2)->As<f32>(), 0._f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Struct_MixedVectors_ZeroInit) {
|
||||
TEST_F(ResolverConstEvalTest, Struct_MixedVectors_ZeroInit) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
Structure("S", {
|
||||
|
@ -2126,7 +2126,7 @@ TEST_F(ResolverConstantsTest, Struct_MixedVectors_ZeroInit) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(4)->Index(1)->As<bool>(), false);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Struct_Struct_ZeroInit) {
|
||||
TEST_F(ResolverConstEvalTest, Struct_Struct_ZeroInit) {
|
||||
Structure("Inner", {
|
||||
Member("m1", ty.i32()),
|
||||
Member("m2", ty.u32()),
|
||||
|
@ -2170,7 +2170,7 @@ TEST_F(ResolverConstantsTest, Struct_Struct_ZeroInit) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->As<f32>(), 0_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Struct_MixedScalars_Construct) {
|
||||
TEST_F(ResolverConstEvalTest, Struct_MixedScalars_Construct) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
Structure("S", {
|
||||
|
@ -2227,7 +2227,7 @@ TEST_F(ResolverConstantsTest, Struct_MixedScalars_Construct) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(4)->As<bool>(), false);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Struct_MixedVectors_Construct) {
|
||||
TEST_F(ResolverConstEvalTest, Struct_MixedVectors_Construct) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
Structure("S", {
|
||||
|
@ -2299,7 +2299,7 @@ TEST_F(ResolverConstantsTest, Struct_MixedVectors_Construct) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(4)->Index(1)->As<bool>(), false);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Struct_Struct_Construct) {
|
||||
TEST_F(ResolverConstEvalTest, Struct_Struct_Construct) {
|
||||
Structure("Inner", {
|
||||
Member("m1", ty.i32()),
|
||||
Member("m2", ty.u32()),
|
||||
|
@ -2345,7 +2345,7 @@ TEST_F(ResolverConstantsTest, Struct_Struct_Construct) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->As<f32>(), 6_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Struct_Array_Construct) {
|
||||
TEST_F(ResolverConstEvalTest, Struct_Array_Construct) {
|
||||
Structure("S", {
|
||||
Member("m1", ty.array<i32, 2>()),
|
||||
Member("m2", ty.array<f32, 3>()),
|
||||
|
@ -2388,7 +2388,7 @@ TEST_F(ResolverConstantsTest, Struct_Array_Construct) {
|
|||
// Indexing
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Index) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Index) {
|
||||
auto* expr = IndexAccessor(vec3<i32>(1_i, 2_i, 3_i), 2_i);
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -2404,7 +2404,7 @@ TEST_F(ResolverConstantsTest, Vec3_Index) {
|
|||
EXPECT_EQ(sem->ConstantValue()->As<i32>(), 3_i);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Index_OOB_High) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Index_OOB_High) {
|
||||
auto* expr = IndexAccessor(vec3<i32>(1_i, 2_i, 3_i), Expr(Source{{12, 34}}, 3_i));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -2421,7 +2421,7 @@ TEST_F(ResolverConstantsTest, Vec3_Index_OOB_High) {
|
|||
EXPECT_EQ(sem->ConstantValue()->As<i32>(), 3_i);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Index_OOB_Low) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Index_OOB_Low) {
|
||||
auto* expr = IndexAccessor(vec3<i32>(1_i, 2_i, 3_i), Expr(Source{{12, 34}}, -3_i));
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -2438,7 +2438,7 @@ TEST_F(ResolverConstantsTest, Vec3_Index_OOB_Low) {
|
|||
EXPECT_EQ(sem->ConstantValue()->As<i32>(), 1_i);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Swizzle_Scalar) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Swizzle_Scalar) {
|
||||
auto* expr = MemberAccessor(vec3<i32>(1_i, 2_i, 3_i), "y");
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -2454,7 +2454,7 @@ TEST_F(ResolverConstantsTest, Vec3_Swizzle_Scalar) {
|
|||
EXPECT_EQ(sem->ConstantValue()->As<i32>(), 2_i);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Swizzle_Vector) {
|
||||
TEST_F(ResolverConstEvalTest, Vec3_Swizzle_Vector) {
|
||||
auto* expr = MemberAccessor(vec3<i32>(1_i, 2_i, 3_i), "zx");
|
||||
WrapInFunction(expr);
|
||||
|
||||
|
@ -2478,7 +2478,7 @@ TEST_F(ResolverConstantsTest, Vec3_Swizzle_Vector) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(1)->As<f32>(), 1._a);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Vec3_Swizzle_Chain) {
|
||||
TEST_F(ResolverConstEvalTest, 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);
|
||||
|
@ -2495,7 +2495,7 @@ TEST_F(ResolverConstantsTest, Vec3_Swizzle_Chain) {
|
|||
EXPECT_EQ(sem->ConstantValue()->As<i32>(), 2_i);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Mat3x2_Index) {
|
||||
TEST_F(ResolverConstEvalTest, 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);
|
||||
WrapInFunction(expr);
|
||||
|
@ -2520,7 +2520,7 @@ TEST_F(ResolverConstantsTest, Mat3x2_Index) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(1)->As<f32>(), 6._a);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Mat3x2_Index_OOB_High) {
|
||||
TEST_F(ResolverConstEvalTest, Mat3x2_Index_OOB_High) {
|
||||
auto* expr = IndexAccessor(
|
||||
mat3x2<f32>(vec2<f32>(1._a, 2._a), vec2<f32>(3._a, 4._a), vec2<f32>(5._a, 6._a)),
|
||||
Expr(Source{{12, 34}}, 3_i));
|
||||
|
@ -2547,7 +2547,7 @@ TEST_F(ResolverConstantsTest, Mat3x2_Index_OOB_High) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(1)->As<f32>(), 6._a);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Mat3x2_Index_OOB_Low) {
|
||||
TEST_F(ResolverConstEvalTest, Mat3x2_Index_OOB_Low) {
|
||||
auto* expr = IndexAccessor(
|
||||
mat3x2<f32>(vec2<f32>(1._a, 2._a), vec2<f32>(3._a, 4._a), vec2<f32>(5._a, 6._a)),
|
||||
Expr(Source{{12, 34}}, -3_i));
|
||||
|
@ -2574,7 +2574,7 @@ TEST_F(ResolverConstantsTest, Mat3x2_Index_OOB_Low) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(1)->As<f32>(), 2._a);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Array_vec3_f32_Index) {
|
||||
TEST_F(ResolverConstEvalTest, Array_vec3_f32_Index) {
|
||||
auto* expr = IndexAccessor(Construct(ty.array(ty.vec3<f32>(), 2_u), //
|
||||
vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f)),
|
||||
1_i);
|
||||
|
@ -2606,7 +2606,7 @@ TEST_F(ResolverConstantsTest, Array_vec3_f32_Index) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<f32>(), 6_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Array_vec3_f32_Index_OOB_High) {
|
||||
TEST_F(ResolverConstEvalTest, Array_vec3_f32_Index_OOB_High) {
|
||||
auto* expr = IndexAccessor(Construct(ty.array(ty.vec3<f32>(), 2_u), //
|
||||
vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f)),
|
||||
Expr(Source{{12, 34}}, 2_i));
|
||||
|
@ -2639,7 +2639,7 @@ TEST_F(ResolverConstantsTest, Array_vec3_f32_Index_OOB_High) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<f32>(), 6_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, Array_vec3_f32_Index_OOB_Low) {
|
||||
TEST_F(ResolverConstEvalTest, Array_vec3_f32_Index_OOB_Low) {
|
||||
auto* expr = IndexAccessor(Construct(ty.array(ty.vec3<f32>(), 2_u), //
|
||||
vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f)),
|
||||
Expr(Source{{12, 34}}, -2_i));
|
||||
|
@ -2675,7 +2675,7 @@ TEST_F(ResolverConstantsTest, Array_vec3_f32_Index_OOB_Low) {
|
|||
EXPECT_EQ(sem->ConstantValue()->Index(2)->As<f32>(), 3_f);
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, ChainedIndex) {
|
||||
TEST_F(ResolverConstEvalTest, ChainedIndex) {
|
||||
auto* arr_expr = Construct(ty.array(ty.mat2x3<f32>(), 2_u), // array<mat2x3<f32>, 2u>
|
||||
mat2x3<f32>(vec3<f32>(1_f, 2_f, 3_f), //
|
||||
vec3<f32>(4_f, 5_f, 6_f)), //
|
||||
|
@ -2771,7 +2771,7 @@ TEST_F(ResolverConstantsTest, ChainedIndex) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_F(ResolverConstantsTest, ChainedIndex_OOB) {
|
||||
TEST_F(ResolverConstEvalTest, ChainedIndex_OOB) {
|
||||
auto* arr_expr = Construct(ty.array(ty.mat2x3<f32>(), 2_u), // array<mat2x3<f32>, 2u>
|
||||
mat2x3<f32>(vec3<f32>(1_f, 2_f, 3_f), //
|
||||
vec3<f32>(4_f, 5_f, 6_f)), //
|
||||
|
@ -2874,7 +2874,7 @@ TEST_F(ResolverConstantsTest, ChainedIndex_OOB) {
|
|||
// Member accessing
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST_F(ResolverConstantsTest, MemberAccess) {
|
||||
TEST_F(ResolverConstEvalTest, MemberAccess) {
|
||||
Structure("Inner", {
|
||||
Member("i1", ty.i32()),
|
||||
Member("i2", ty.u32()),
|
||||
|
@ -2924,5 +2924,83 @@ TEST_F(ResolverConstantsTest, MemberAccess) {
|
|||
EXPECT_EQ(i2->ConstantValue()->As<u32>(), 2_u);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Unary op
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace unary_op {
|
||||
|
||||
template <typename T>
|
||||
struct Values {
|
||||
T input;
|
||||
T expect;
|
||||
};
|
||||
|
||||
struct Case {
|
||||
std::variant<Values<AInt>, Values<u32>, Values<i32>> values;
|
||||
};
|
||||
|
||||
static std::ostream& operator<<(std::ostream& o, const Case& c) {
|
||||
std::visit([&](auto&& v) { o << v.input; }, c.values);
|
||||
return o;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Case C(T input, T expect) {
|
||||
return Case{Values<T>{input, expect}};
|
||||
}
|
||||
|
||||
using ResolverConstEvalUnaryOpTest = ResolverTestWithParam<std::tuple<ast::UnaryOp, Case>>;
|
||||
|
||||
TEST_P(ResolverConstEvalUnaryOpTest, Test) {
|
||||
auto op = std::get<0>(GetParam());
|
||||
auto c = std::get<1>(GetParam());
|
||||
std::visit(
|
||||
[&](auto&& values) {
|
||||
using T = decltype(values.expect);
|
||||
auto* expr = create<ast::UnaryOpExpression>(op, Expr(values.input));
|
||||
GlobalConst("C", nullptr, expr);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = Sem().Get(expr);
|
||||
const sem::Constant* value = sem->ConstantValue();
|
||||
ASSERT_NE(value, nullptr);
|
||||
EXPECT_TYPE(value->Type(), sem->Type());
|
||||
EXPECT_EQ(value->As<T>(), values.expect);
|
||||
|
||||
if constexpr (IsInteger<UnwrapNumber<T>>) {
|
||||
// Check that the constant's integer doesn't contain unexpected data in the MSBs
|
||||
// that are outside of the bit-width of T.
|
||||
EXPECT_EQ(value->As<AInt>(), AInt(values.expect));
|
||||
}
|
||||
},
|
||||
c.values);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(Complement,
|
||||
ResolverConstEvalUnaryOpTest,
|
||||
testing::Combine(testing::Values(ast::UnaryOp::kComplement),
|
||||
testing::ValuesIn({
|
||||
// AInt
|
||||
C(0_a, 0xffffffffffffffff_a),
|
||||
C(0xffffffffffffffff_a, 0_a),
|
||||
C(0xf0f0f0f0f0f0f0f0_a, 0x0f0f0f0f0f0f0f0f_a),
|
||||
C(0xaaaaaaaaaaaaaaaa_a, 0x5555555555555555_a),
|
||||
C(0x5555555555555555_a, 0xaaaaaaaaaaaaaaaa_a),
|
||||
// u32
|
||||
C(0_u, 0xffffffff_u),
|
||||
C(0xffffffff_u, 0_u),
|
||||
C(0xf0f0f0f0_u, 0x0f0f0f0f_u),
|
||||
C(0xaaaaaaaa_u, 0x55555555_u),
|
||||
C(0x55555555_u, 0xaaaaaaaa_u),
|
||||
// i32
|
||||
C(0_i, -1_i),
|
||||
C(-1_i, 0_i),
|
||||
C(1_i, -2_i),
|
||||
C(-2_i, 1_i),
|
||||
C(2_i, -3_i),
|
||||
C(-3_i, 2_i),
|
||||
})));
|
||||
} // namespace unary_op
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::resolver
|
||||
|
|
|
@ -1164,7 +1164,11 @@ IntrinsicTable::UnaryOperator Impl::Lookup(ast::UnaryOp op,
|
|||
return {};
|
||||
}
|
||||
|
||||
return UnaryOperator{match.return_type, match.parameters[0].type};
|
||||
return UnaryOperator{
|
||||
match.return_type,
|
||||
match.parameters[0].type,
|
||||
match.overload->const_eval_fn,
|
||||
};
|
||||
}
|
||||
|
||||
IntrinsicTable::BinaryOperator Impl::Lookup(ast::BinaryOp op,
|
||||
|
@ -1235,7 +1239,12 @@ IntrinsicTable::BinaryOperator Impl::Lookup(ast::BinaryOp op,
|
|||
return {};
|
||||
}
|
||||
|
||||
return BinaryOperator{match.return_type, match.parameters[0].type, match.parameters[1].type};
|
||||
return BinaryOperator{
|
||||
match.return_type,
|
||||
match.parameters[0].type,
|
||||
match.parameters[1].type,
|
||||
match.overload->const_eval_fn,
|
||||
};
|
||||
}
|
||||
|
||||
IntrinsicTable::CtorOrConv Impl::Lookup(CtorConvIntrinsic type,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -103,7 +103,7 @@ constexpr OverloadInfo kOverloads[] = {
|
|||
{{- end }}
|
||||
{{- if $o.IsDeprecated}}, OverloadFlag::kIsDeprecated{{end }}),
|
||||
/* const eval */
|
||||
{{- if $o.ConstEvalFunction }} &ConstEval::{{$o.ConstEvalFunction}},
|
||||
{{- if $o.ConstEvalFunction }} {{template "ConstEvalFn" $o}},
|
||||
{{- else }} nullptr,
|
||||
{{- end }}
|
||||
},
|
||||
|
@ -137,7 +137,7 @@ constexpr IntrinsicInfo kUnaryOperators[] = {
|
|||
};
|
||||
|
||||
{{- range $i, $o := .UnaryOperators }}
|
||||
constexpr uint8_t kUnaryOperator{{template "OperatorName" $o.Name}} = {{$i}};
|
||||
constexpr uint8_t kUnaryOperator{{ template "ExpandName" $o.Name}} = {{$i}};
|
||||
{{- end }}
|
||||
|
||||
constexpr IntrinsicInfo kBinaryOperators[] = {
|
||||
|
@ -154,7 +154,7 @@ constexpr IntrinsicInfo kBinaryOperators[] = {
|
|||
};
|
||||
|
||||
{{- range $i, $o := .BinaryOperators }}
|
||||
constexpr uint8_t kBinaryOperator{{template "OperatorName" $o.Name}} = {{$i}};
|
||||
constexpr uint8_t kBinaryOperator{{ template "ExpandName" $o.Name}} = {{$i}};
|
||||
{{- end }}
|
||||
|
||||
constexpr IntrinsicInfo kConstructorsAndConverters[] = {
|
||||
|
@ -455,7 +455,7 @@ Matchers::~Matchers() = default;
|
|||
{{- end -}}
|
||||
|
||||
{{- /* ------------------------------------------------------------------ */ -}}
|
||||
{{- define "OperatorName" -}}
|
||||
{{- define "ExpandName" -}}
|
||||
{{- /* ------------------------------------------------------------------ */ -}}
|
||||
{{- if eq . "<<" -}}ShiftLeft
|
||||
{{- else if eq . "&" -}}And
|
||||
|
@ -478,6 +478,16 @@ Matchers::~Matchers() = default;
|
|||
{{- else if eq . "*" -}}Star
|
||||
{{- else if eq . "/" -}}Divide
|
||||
{{- else if eq . "%" -}}Modulo
|
||||
{{- else -}}<unknown-{{.}}>
|
||||
{{- else -}}{{.}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
|
||||
{{- /* ------------------------------------------------------------------ */ -}}
|
||||
{{- define "ConstEvalFn" -}}
|
||||
{{- /* ------------------------------------------------------------------ */ -}}
|
||||
&ConstEval::
|
||||
{{- if eq .Kind "operator" -}}Op{{end -}}
|
||||
{{template "ExpandName" .ConstEvalFunction}}
|
||||
{{- end -}}
|
||||
|
||||
|
|
|
@ -1508,7 +1508,7 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
|||
current_statement_, value, has_side_effects);
|
||||
};
|
||||
|
||||
// ct_ctor_or_conv is a helper for building a sem::TypeConstructor for an array or structure
|
||||
// arr_or_str_ctor is a helper for building a sem::TypeConstructor for an array or structure
|
||||
// constructor call target.
|
||||
auto arr_or_str_ctor = [&](const sem::Type* ty,
|
||||
const sem::CallTarget* call_target) -> sem::Call* {
|
||||
|
@ -1523,15 +1523,18 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
|||
if (!value) {
|
||||
// Constant evaluation failed.
|
||||
// Can happen for expressions that will fail validation (later).
|
||||
// Use the kRuntime EvaluationStage, as kConstant will trigger an assertion in the
|
||||
// sem::Expression constructor, which checks that kConstant is paired with a
|
||||
// constant value.
|
||||
stage = sem::EvaluationStage::kRuntime;
|
||||
}
|
||||
}
|
||||
|
||||
return builder_->create<sem::Call>(expr, call_target, stage, std::move(args),
|
||||
current_statement_, std::move(value), has_side_effects);
|
||||
current_statement_, value, has_side_effects);
|
||||
};
|
||||
|
||||
// ct_ctor_or_conv is a helper for building either a sem::TypeConstructor or sem::TypeConversion
|
||||
// ty_ctor_or_conv is a helper for building either a sem::TypeConstructor or sem::TypeConversion
|
||||
// call for the given semantic type.
|
||||
auto ty_ctor_or_conv = [&](const sem::Type* ty) {
|
||||
return Switch(
|
||||
|
@ -1710,7 +1713,12 @@ sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
|||
}
|
||||
|
||||
auto stage = builtin.sem->Stage();
|
||||
if (stage == sem::EvaluationStage::kConstant) {
|
||||
if (stage == sem::EvaluationStage::kConstant) { // <-- Optimization
|
||||
// If the builtin is not annotated with @const, then it can only be evaluated
|
||||
// at runtime, in which case there's no point checking the evaluation stage of the
|
||||
// arguments.
|
||||
|
||||
// The builtin is @const annotated. Check all arguments are also constant.
|
||||
for (auto* arg : args) {
|
||||
stage = sem::EarliestStage(stage, arg->Stage());
|
||||
}
|
||||
|
@ -1718,7 +1726,7 @@ sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
|||
|
||||
// If the builtin is @const, and all arguments have constant values, evaluate the builtin now.
|
||||
const sem::Constant* value = nullptr;
|
||||
if (stage == sem::EvaluationStage::kConstant && builtin.const_eval_fn) {
|
||||
if (stage == sem::EvaluationStage::kConstant) {
|
||||
value = (const_eval_.*builtin.const_eval_fn)(builtin.sem->ReturnType(), args.data(),
|
||||
args.size());
|
||||
}
|
||||
|
@ -2129,7 +2137,7 @@ sem::Expression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
|
|||
const sem::Type* ty = nullptr;
|
||||
const sem::Variable* source_var = nullptr;
|
||||
const sem::Constant* value = nullptr;
|
||||
auto stage = sem::EvaluationStage::kRuntime; // TODO(crbug.com/tint/1581)
|
||||
auto stage = sem::EvaluationStage::kRuntime;
|
||||
|
||||
switch (unary->op) {
|
||||
case ast::UnaryOp::kAddressOf:
|
||||
|
@ -2181,10 +2189,15 @@ sem::Expression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
ty = op.result;
|
||||
if (op.const_eval_fn) {
|
||||
value = (const_eval_.*op.const_eval_fn)(ty, &expr, 1u);
|
||||
stage = expr->Stage();
|
||||
if (stage == sem::EvaluationStage::kConstant) {
|
||||
if (op.const_eval_fn) {
|
||||
value = (const_eval_.*op.const_eval_fn)(ty, &expr, 1u);
|
||||
} else {
|
||||
stage = sem::EvaluationStage::kRuntime;
|
||||
}
|
||||
}
|
||||
ty = op.result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -560,8 +560,8 @@ bool Validator::LocalVariable(const sem::Variable* v) const {
|
|||
|
||||
bool Validator::GlobalVariable(
|
||||
const sem::GlobalVariable* global,
|
||||
std::unordered_map<uint32_t, const sem::Variable*> constant_ids,
|
||||
std::unordered_map<const sem::Type*, const Source&> atomic_composite_info) const {
|
||||
const std::unordered_map<uint32_t, const sem::Variable*>& constant_ids,
|
||||
const std::unordered_map<const sem::Type*, const Source&>& atomic_composite_info) const {
|
||||
auto* decl = global->Declaration();
|
||||
bool ok = Switch(
|
||||
decl, //
|
||||
|
@ -759,8 +759,9 @@ bool Validator::Let(const sem::Variable* v) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Validator::Override(const sem::Variable* v,
|
||||
std::unordered_map<uint32_t, const sem::Variable*> constant_ids) const {
|
||||
bool Validator::Override(
|
||||
const sem::Variable* v,
|
||||
const std::unordered_map<uint32_t, const sem::Variable*>& constant_ids) const {
|
||||
auto* decl = v->Declaration();
|
||||
auto* storage_ty = v->Type()->UnwrapRef();
|
||||
|
||||
|
|
|
@ -239,8 +239,8 @@ class Validator {
|
|||
/// @returns true on success, false otherwise
|
||||
bool GlobalVariable(
|
||||
const sem::GlobalVariable* var,
|
||||
std::unordered_map<uint32_t, const sem::Variable*> constant_ids,
|
||||
std::unordered_map<const sem::Type*, const Source&> atomic_composite_info) const;
|
||||
const std::unordered_map<uint32_t, const sem::Variable*>& constant_ids,
|
||||
const std::unordered_map<const sem::Type*, const Source&>& atomic_composite_info) const;
|
||||
|
||||
/// Validates an if statement
|
||||
/// @param stmt the statement to validate
|
||||
|
@ -374,7 +374,7 @@ class Validator {
|
|||
/// @param constant_ids the set of constant ids in the module
|
||||
/// @returns true on success, false otherwise.
|
||||
bool Override(const sem::Variable* v,
|
||||
std::unordered_map<uint32_t, const sem::Variable*> constant_ids) const;
|
||||
const std::unordered_map<uint32_t, const sem::Variable*>& constant_ids) const;
|
||||
|
||||
/// Validates a 'const' variable declaration
|
||||
/// @param v the variable to validate
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
var<private>o=bool(~1);
|
|
@ -0,0 +1,7 @@
|
|||
#version 310 es
|
||||
|
||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||
void unused_entry_point() {
|
||||
return;
|
||||
}
|
||||
bool o = true;
|
|
@ -0,0 +1,6 @@
|
|||
[numthreads(1, 1, 1)]
|
||||
void unused_entry_point() {
|
||||
return;
|
||||
}
|
||||
|
||||
static bool o = true;
|
|
@ -0,0 +1,3 @@
|
|||
#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
|
@ -0,0 +1,21 @@
|
|||
; SPIR-V
|
||||
; Version: 1.3
|
||||
; Generator: Google Tint Compiler; 0
|
||||
; Bound: 9
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
|
||||
OpExecutionMode %unused_entry_point LocalSize 1 1 1
|
||||
OpName %o "o"
|
||||
OpName %unused_entry_point "unused_entry_point"
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
%_ptr_Private_bool = OpTypePointer Private %bool
|
||||
%o = OpVariable %_ptr_Private_bool Private %true
|
||||
%void = OpTypeVoid
|
||||
%5 = OpTypeFunction %void
|
||||
%unused_entry_point = OpFunction %void None %5
|
||||
%8 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
|
@ -0,0 +1 @@
|
|||
var<private> o = bool(~(1));
|
Loading…
Reference in New Issue