intrinsics: Add new struct form of modf(), frexp()

Implement these for all the writers.
SPIR-V reader not implemented (the old overloads weren't implemented either).

Deprecate the old overloads.

Fixed: tint:54
Change-Id: If66d26dbac3389ff604734f31b426abe47868b91
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/59302
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
Ben Clayton
2021-07-23 16:43:01 +00:00
parent 465c5aa51d
commit 053559d051
236 changed files with 5861 additions and 2658 deletions

View File

@@ -156,11 +156,11 @@ TEST_F(ResolverInferredTypeTest, InferStruct_Pass) {
auto* member = Member("x", ty.i32());
auto* str = Structure("S", {member}, {create<ast::StructBlockDecoration>()});
auto* expected_type =
create<sem::Struct>(str,
sem::StructMemberList{create<sem::StructMember>(
member, create<sem::I32>(), 0, 0, 0, 4)},
0, 4, 4);
auto* expected_type = create<sem::Struct>(
str, str->name(),
sem::StructMemberList{create<sem::StructMember>(
member, member->symbol(), create<sem::I32>(), 0, 0, 0, 4)},
0, 4, 4);
auto* ctor_expr = Construct(ty.Of(str));

View File

@@ -828,7 +828,7 @@ TEST_F(ResolverIntrinsicDataTest, Normalize_Error_NoParams) {
)");
}
TEST_F(ResolverIntrinsicDataTest, FrexpScalar) {
TEST_F(ResolverIntrinsicDataTest, DEPRECATED_FrexpScalar) {
Global("exp", ty.i32(), ast::StorageClass::kWorkgroup);
auto* call = Call("frexp", 1.0f, AddressOf("exp"));
WrapInFunction(call);
@@ -839,7 +839,7 @@ TEST_F(ResolverIntrinsicDataTest, FrexpScalar) {
EXPECT_TRUE(TypeOf(call)->Is<sem::F32>());
}
TEST_F(ResolverIntrinsicDataTest, FrexpVector) {
TEST_F(ResolverIntrinsicDataTest, DEPRECATED_FrexpVector) {
Global("exp", ty.vec3<i32>(), ast::StorageClass::kWorkgroup);
auto* call = Call("frexp", vec3<f32>(1.0f, 2.0f, 3.0f), AddressOf("exp"));
WrapInFunction(call);
@@ -851,6 +851,68 @@ TEST_F(ResolverIntrinsicDataTest, FrexpVector) {
EXPECT_TRUE(TypeOf(call)->As<sem::Vector>()->type()->Is<sem::F32>());
}
TEST_F(ResolverIntrinsicDataTest, FrexpScalar) {
auto* call = Call("frexp", 1.0f);
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
ASSERT_NE(TypeOf(call), nullptr);
auto* ty = TypeOf(call)->As<sem::Struct>();
ASSERT_NE(ty, nullptr);
ASSERT_EQ(ty->Members().size(), 2u);
auto* sig = ty->Members()[0];
EXPECT_TRUE(sig->Type()->Is<sem::F32>());
EXPECT_EQ(sig->Offset(), 0u);
EXPECT_EQ(sig->Size(), 4u);
EXPECT_EQ(sig->Align(), 4u);
EXPECT_EQ(sig->Name(), Sym("sig"));
auto* exp = ty->Members()[1];
EXPECT_TRUE(exp->Type()->Is<sem::I32>());
EXPECT_EQ(exp->Offset(), 4u);
EXPECT_EQ(exp->Size(), 4u);
EXPECT_EQ(exp->Align(), 4u);
EXPECT_EQ(exp->Name(), Sym("exp"));
EXPECT_EQ(ty->Size(), 8u);
EXPECT_EQ(ty->SizeNoPadding(), 8u);
}
TEST_F(ResolverIntrinsicDataTest, FrexpVector) {
auto* call = Call("frexp", vec3<f32>());
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
ASSERT_NE(TypeOf(call), nullptr);
auto* ty = TypeOf(call)->As<sem::Struct>();
ASSERT_NE(ty, nullptr);
ASSERT_EQ(ty->Members().size(), 2u);
auto* sig = ty->Members()[0];
ASSERT_TRUE(sig->Type()->Is<sem::Vector>());
EXPECT_EQ(sig->Type()->As<sem::Vector>()->Width(), 3u);
EXPECT_TRUE(sig->Type()->As<sem::Vector>()->type()->Is<sem::F32>());
EXPECT_EQ(sig->Offset(), 0u);
EXPECT_EQ(sig->Size(), 12u);
EXPECT_EQ(sig->Align(), 16u);
EXPECT_EQ(sig->Name(), Sym("sig"));
auto* exp = ty->Members()[1];
ASSERT_TRUE(exp->Type()->Is<sem::Vector>());
EXPECT_EQ(exp->Type()->As<sem::Vector>()->Width(), 3u);
EXPECT_TRUE(exp->Type()->As<sem::Vector>()->type()->Is<sem::I32>());
EXPECT_EQ(exp->Offset(), 16u);
EXPECT_EQ(exp->Size(), 12u);
EXPECT_EQ(exp->Align(), 16u);
EXPECT_EQ(exp->Name(), Sym("exp"));
EXPECT_EQ(ty->Size(), 32u);
EXPECT_EQ(ty->SizeNoPadding(), 28u);
}
TEST_F(ResolverIntrinsicDataTest, Frexp_Error_FirstParamInt) {
Global("exp", ty.i32(), ast::StorageClass::kWorkgroup);
auto* call = Call("frexp", 1, AddressOf("exp"));
@@ -862,9 +924,11 @@ TEST_F(ResolverIntrinsicDataTest, Frexp_Error_FirstParamInt) {
r()->error(),
R"(error: no matching call to frexp(i32, ptr<workgroup, i32, read_write>)
2 candidate functions:
4 candidate functions:
frexp(f32, ptr<S, i32, A>) -> f32 where: S is function, private or workgroup
frexp(vecN<f32>, ptr<S, vecN<i32>, A>) -> vecN<f32> where: S is function, private or workgroup
frexp(f32) -> _frexp_result
frexp(vecN<f32>) -> _frexp_result_vecN
)");
}
@@ -879,9 +943,11 @@ TEST_F(ResolverIntrinsicDataTest, Frexp_Error_SecondParamFloatPtr) {
r()->error(),
R"(error: no matching call to frexp(f32, ptr<workgroup, f32, read_write>)
2 candidate functions:
4 candidate functions:
frexp(f32, ptr<S, i32, A>) -> f32 where: S is function, private or workgroup
frexp(f32) -> _frexp_result
frexp(vecN<f32>, ptr<S, vecN<i32>, A>) -> vecN<f32> where: S is function, private or workgroup
frexp(vecN<f32>) -> _frexp_result_vecN
)");
}
@@ -893,9 +959,11 @@ TEST_F(ResolverIntrinsicDataTest, Frexp_Error_SecondParamNotAPointer) {
EXPECT_EQ(r()->error(), R"(error: no matching call to frexp(f32, i32)
2 candidate functions:
4 candidate functions:
frexp(f32, ptr<S, i32, A>) -> f32 where: S is function, private or workgroup
frexp(f32) -> _frexp_result
frexp(vecN<f32>, ptr<S, vecN<i32>, A>) -> vecN<f32> where: S is function, private or workgroup
frexp(vecN<f32>) -> _frexp_result_vecN
)");
}
@@ -910,13 +978,15 @@ TEST_F(ResolverIntrinsicDataTest, Frexp_Error_VectorSizesDontMatch) {
r()->error(),
R"(error: no matching call to frexp(vec2<f32>, ptr<workgroup, vec4<i32>, read_write>)
2 candidate functions:
4 candidate functions:
frexp(vecN<f32>, ptr<S, vecN<i32>, A>) -> vecN<f32> where: S is function, private or workgroup
frexp(vecN<f32>) -> _frexp_result_vecN
frexp(f32, ptr<S, i32, A>) -> f32 where: S is function, private or workgroup
frexp(f32) -> _frexp_result
)");
}
TEST_F(ResolverIntrinsicDataTest, ModfScalar) {
TEST_F(ResolverIntrinsicDataTest, DEPRECATED_ModfScalar) {
Global("whole", ty.f32(), ast::StorageClass::kWorkgroup);
auto* call = Call("modf", 1.0f, AddressOf("whole"));
WrapInFunction(call);
@@ -927,7 +997,7 @@ TEST_F(ResolverIntrinsicDataTest, ModfScalar) {
EXPECT_TRUE(TypeOf(call)->Is<sem::F32>());
}
TEST_F(ResolverIntrinsicDataTest, ModfVector) {
TEST_F(ResolverIntrinsicDataTest, DEPRECATED_ModfVector) {
Global("whole", ty.vec3<f32>(), ast::StorageClass::kWorkgroup);
auto* call = Call("modf", vec3<f32>(1.0f, 2.0f, 3.0f), AddressOf("whole"));
WrapInFunction(call);
@@ -939,6 +1009,68 @@ TEST_F(ResolverIntrinsicDataTest, ModfVector) {
EXPECT_TRUE(TypeOf(call)->As<sem::Vector>()->type()->Is<sem::F32>());
}
TEST_F(ResolverIntrinsicDataTest, ModfScalar) {
auto* call = Call("modf", 1.0f);
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
ASSERT_NE(TypeOf(call), nullptr);
auto* ty = TypeOf(call)->As<sem::Struct>();
ASSERT_NE(ty, nullptr);
ASSERT_EQ(ty->Members().size(), 2u);
auto* fract = ty->Members()[0];
EXPECT_TRUE(fract->Type()->Is<sem::F32>());
EXPECT_EQ(fract->Offset(), 0u);
EXPECT_EQ(fract->Size(), 4u);
EXPECT_EQ(fract->Align(), 4u);
EXPECT_EQ(fract->Name(), Sym("fract"));
auto* whole = ty->Members()[1];
EXPECT_TRUE(whole->Type()->Is<sem::F32>());
EXPECT_EQ(whole->Offset(), 4u);
EXPECT_EQ(whole->Size(), 4u);
EXPECT_EQ(whole->Align(), 4u);
EXPECT_EQ(whole->Name(), Sym("whole"));
EXPECT_EQ(ty->Size(), 8u);
EXPECT_EQ(ty->SizeNoPadding(), 8u);
}
TEST_F(ResolverIntrinsicDataTest, ModfVector) {
auto* call = Call("modf", vec3<f32>());
WrapInFunction(call);
EXPECT_TRUE(r()->Resolve()) << r()->error();
ASSERT_NE(TypeOf(call), nullptr);
auto* ty = TypeOf(call)->As<sem::Struct>();
ASSERT_NE(ty, nullptr);
ASSERT_EQ(ty->Members().size(), 2u);
auto* fract = ty->Members()[0];
ASSERT_TRUE(fract->Type()->Is<sem::Vector>());
EXPECT_EQ(fract->Type()->As<sem::Vector>()->Width(), 3u);
EXPECT_TRUE(fract->Type()->As<sem::Vector>()->type()->Is<sem::F32>());
EXPECT_EQ(fract->Offset(), 0u);
EXPECT_EQ(fract->Size(), 12u);
EXPECT_EQ(fract->Align(), 16u);
EXPECT_EQ(fract->Name(), Sym("fract"));
auto* whole = ty->Members()[1];
ASSERT_TRUE(whole->Type()->Is<sem::Vector>());
EXPECT_EQ(whole->Type()->As<sem::Vector>()->Width(), 3u);
EXPECT_TRUE(whole->Type()->As<sem::Vector>()->type()->Is<sem::F32>());
EXPECT_EQ(whole->Offset(), 16u);
EXPECT_EQ(whole->Size(), 12u);
EXPECT_EQ(whole->Align(), 16u);
EXPECT_EQ(whole->Name(), Sym("whole"));
EXPECT_EQ(ty->Size(), 32u);
EXPECT_EQ(ty->SizeNoPadding(), 28u);
}
TEST_F(ResolverIntrinsicDataTest, Modf_Error_FirstParamInt) {
Global("whole", ty.f32(), ast::StorageClass::kWorkgroup);
auto* call = Call("modf", 1, AddressOf("whole"));
@@ -950,9 +1082,11 @@ TEST_F(ResolverIntrinsicDataTest, Modf_Error_FirstParamInt) {
r()->error(),
R"(error: no matching call to modf(i32, ptr<workgroup, f32, read_write>)
2 candidate functions:
4 candidate functions:
modf(f32, ptr<S, f32, A>) -> f32 where: S is function, private or workgroup
modf(vecN<f32>, ptr<S, vecN<f32>, A>) -> vecN<f32> where: S is function, private or workgroup
modf(f32) -> _modf_result
modf(vecN<f32>) -> _modf_result_vecN
)");
}
@@ -967,9 +1101,11 @@ TEST_F(ResolverIntrinsicDataTest, Modf_Error_SecondParamIntPtr) {
r()->error(),
R"(error: no matching call to modf(f32, ptr<workgroup, i32, read_write>)
2 candidate functions:
4 candidate functions:
modf(f32, ptr<S, f32, A>) -> f32 where: S is function, private or workgroup
modf(f32) -> _modf_result
modf(vecN<f32>, ptr<S, vecN<f32>, A>) -> vecN<f32> where: S is function, private or workgroup
modf(vecN<f32>) -> _modf_result_vecN
)");
}
@@ -981,9 +1117,11 @@ TEST_F(ResolverIntrinsicDataTest, Modf_Error_SecondParamNotAPointer) {
EXPECT_EQ(r()->error(), R"(error: no matching call to modf(f32, f32)
2 candidate functions:
4 candidate functions:
modf(f32, ptr<S, f32, A>) -> f32 where: S is function, private or workgroup
modf(f32) -> _modf_result
modf(vecN<f32>, ptr<S, vecN<f32>, A>) -> vecN<f32> where: S is function, private or workgroup
modf(vecN<f32>) -> _modf_result_vecN
)");
}
@@ -998,9 +1136,11 @@ TEST_F(ResolverIntrinsicDataTest, Modf_Error_VectorSizesDontMatch) {
r()->error(),
R"(error: no matching call to modf(vec2<f32>, ptr<workgroup, vec4<f32>, read_write>)
2 candidate functions:
4 candidate functions:
modf(vecN<f32>, ptr<S, vecN<f32>, A>) -> vecN<f32> where: S is function, private or workgroup
modf(vecN<f32>) -> _modf_result_vecN
modf(f32, ptr<S, f32, A>) -> f32 where: S is function, private or workgroup
modf(f32) -> _modf_result
)");
}

View File

@@ -2998,7 +2998,7 @@ bool Resolver::MemberAccessor(ast::MemberAccessorExpression* expr) {
const sem::StructMember* member = nullptr;
for (auto* m : str->Members()) {
if (m->Declaration()->symbol() == symbol) {
if (m->Name() == symbol) {
ret = m->Type();
member = m;
break;
@@ -4088,7 +4088,7 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) {
offset = utils::RoundUp(align, offset);
auto* sem_member = builder_->create<sem::StructMember>(
member, const_cast<sem::Type*>(type),
member, member->symbol(), const_cast<sem::Type*>(type),
static_cast<uint32_t>(sem_members.size()), offset, align, size);
builder_->Sem().Add(member, sem_member);
sem_members.emplace_back(sem_member);
@@ -4100,8 +4100,9 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) {
auto size_no_padding = struct_size;
struct_size = utils::RoundUp(struct_align, struct_size);
auto* out = builder_->create<sem::Struct>(str, sem_members, struct_align,
struct_size, size_no_padding);
auto* out =
builder_->create<sem::Struct>(str, str->name(), sem_members, struct_align,
struct_size, size_no_padding);
// Keep track of atomic members for validation after all usages have been
// determined.