tint: Use type::Struct where possible
type::Struct does not have an ast::Struct declaration, so use that for builtin structures. Fix up logic that assumed sem::Struct for both user-declared and builtin structures to use type::Struct instead. Assert in the sem::Struct and sem::StructMember that the AST node is not nullptr. Change-Id: Ic8fcf27d5610c814ea3b504694c6a94db6cf1191 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/129483 Reviewed-by: Dan Sinclair <dsinclair@chromium.org> Commit-Queue: Ben Clayton <bclayton@google.com> Kokoro: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
576ba1c493
commit
bc9e422728
|
@ -33,19 +33,18 @@ struct NameAndType {
|
|||
const type::Type* type;
|
||||
};
|
||||
|
||||
sem::Struct* BuildStruct(ProgramBuilder& b,
|
||||
builtin::Builtin name,
|
||||
std::initializer_list<NameAndType> member_names_and_types) {
|
||||
type::Struct* BuildStruct(ProgramBuilder& b,
|
||||
builtin::Builtin name,
|
||||
std::initializer_list<NameAndType> member_names_and_types) {
|
||||
uint32_t offset = 0;
|
||||
uint32_t max_align = 0;
|
||||
utils::Vector<const sem::StructMember*, 4> members;
|
||||
utils::Vector<const type::StructMember*, 4> members;
|
||||
for (auto& m : member_names_and_types) {
|
||||
uint32_t align = std::max<uint32_t>(m.type->Align(), 1);
|
||||
uint32_t size = m.type->Size();
|
||||
offset = utils::RoundUp(align, offset);
|
||||
max_align = std::max(max_align, align);
|
||||
members.Push(b.create<sem::StructMember>(
|
||||
/* declaration */ nullptr,
|
||||
members.Push(b.create<type::StructMember>(
|
||||
/* source */ Source{},
|
||||
/* name */ b.Sym(m.name),
|
||||
/* type */ m.type,
|
||||
|
@ -58,8 +57,7 @@ sem::Struct* BuildStruct(ProgramBuilder& b,
|
|||
}
|
||||
uint32_t size_without_padding = offset;
|
||||
uint32_t size_with_padding = utils::RoundUp(max_align, offset);
|
||||
return b.create<sem::Struct>(
|
||||
/* declaration */ nullptr,
|
||||
return b.create<type::Struct>(
|
||||
/* source */ Source{},
|
||||
/* name */ b.Sym(name),
|
||||
/* members */ std::move(members),
|
||||
|
@ -85,7 +83,7 @@ constexpr std::array kModfVecAbstractNames{
|
|||
builtin::Builtin::kModfResultVec4Abstract,
|
||||
};
|
||||
|
||||
sem::Struct* CreateModfResult(ProgramBuilder& b, const type::Type* ty) {
|
||||
type::Struct* CreateModfResult(ProgramBuilder& b, const type::Type* ty) {
|
||||
return Switch(
|
||||
ty,
|
||||
[&](const type::F32*) {
|
||||
|
@ -157,7 +155,7 @@ constexpr std::array kFrexpVecAbstractNames{
|
|||
builtin::Builtin::kFrexpResultVec3Abstract,
|
||||
builtin::Builtin::kFrexpResultVec4Abstract,
|
||||
};
|
||||
sem::Struct* CreateFrexpResult(ProgramBuilder& b, const type::Type* ty) {
|
||||
type::Struct* CreateFrexpResult(ProgramBuilder& b, const type::Type* ty) {
|
||||
return Switch(
|
||||
ty, //
|
||||
[&](const type::F32*) {
|
||||
|
@ -222,7 +220,7 @@ sem::Struct* CreateFrexpResult(ProgramBuilder& b, const type::Type* ty) {
|
|||
});
|
||||
}
|
||||
|
||||
sem::Struct* CreateAtomicCompareExchangeResult(ProgramBuilder& b, const type::Type* ty) {
|
||||
type::Struct* CreateAtomicCompareExchangeResult(ProgramBuilder& b, const type::Type* ty) {
|
||||
return Switch(
|
||||
ty, //
|
||||
[&](const type::I32*) {
|
||||
|
|
|
@ -19,10 +19,8 @@
|
|||
namespace tint {
|
||||
class ProgramBuilder;
|
||||
} // namespace tint
|
||||
namespace tint::sem {
|
||||
class Struct;
|
||||
} // namespace tint::sem
|
||||
namespace tint::type {
|
||||
class Struct;
|
||||
class Type;
|
||||
} // namespace tint::type
|
||||
|
||||
|
@ -32,19 +30,19 @@ namespace tint::resolver {
|
|||
* @param ty the type of the `fract` and `whole` struct members.
|
||||
* @return the builtin struct type for a modf() builtin call.
|
||||
*/
|
||||
sem::Struct* CreateModfResult(ProgramBuilder& b, const type::Type* ty);
|
||||
type::Struct* CreateModfResult(ProgramBuilder& b, const type::Type* ty);
|
||||
|
||||
/**
|
||||
* @param fract the type of the `fract` struct member.
|
||||
* @return the builtin struct type for a frexp() builtin call.
|
||||
*/
|
||||
sem::Struct* CreateFrexpResult(ProgramBuilder& b, const type::Type* fract);
|
||||
type::Struct* CreateFrexpResult(ProgramBuilder& b, const type::Type* fract);
|
||||
|
||||
/**
|
||||
* @param ty the type of the `old_value` struct member.
|
||||
* @return the builtin struct type for a atomic_compare_exchange() builtin call.
|
||||
*/
|
||||
sem::Struct* CreateAtomicCompareExchangeResult(ProgramBuilder& b, const type::Type* ty);
|
||||
type::Struct* CreateAtomicCompareExchangeResult(ProgramBuilder& b, const type::Type* ty);
|
||||
|
||||
} // namespace tint::resolver
|
||||
|
||||
|
|
|
@ -34,10 +34,10 @@ TEST_P(ResolverBuiltinStructs, Resolve) {
|
|||
auto* var = GlobalVar("p", ty(GetParam()), builtin::AddressSpace::kPrivate);
|
||||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
auto* str = As<sem::Struct>(TypeOf(var)->UnwrapRef());
|
||||
auto* str = As<type::Struct>(TypeOf(var)->UnwrapRef());
|
||||
ASSERT_NE(str, nullptr);
|
||||
EXPECT_EQ(str->Name().Name(), utils::ToString(GetParam()));
|
||||
EXPECT_EQ(str->Declaration(), nullptr);
|
||||
EXPECT_FALSE(Is<sem::Struct>(str));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(,
|
||||
|
|
|
@ -925,7 +925,7 @@ TEST_F(ResolverBuiltinFloatTest, FrexpScalar_f32) {
|
|||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
ASSERT_NE(TypeOf(call), nullptr);
|
||||
auto* ty = TypeOf(call)->As<sem::Struct>();
|
||||
auto* ty = TypeOf(call)->As<type::Struct>();
|
||||
ASSERT_NE(ty, nullptr);
|
||||
ASSERT_EQ(ty->Members().Length(), 2u);
|
||||
|
||||
|
@ -956,7 +956,7 @@ TEST_F(ResolverBuiltinFloatTest, FrexpScalar_f16) {
|
|||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
ASSERT_NE(TypeOf(call), nullptr);
|
||||
auto* ty = TypeOf(call)->As<sem::Struct>();
|
||||
auto* ty = TypeOf(call)->As<type::Struct>();
|
||||
ASSERT_NE(ty, nullptr);
|
||||
ASSERT_EQ(ty->Members().Length(), 2u);
|
||||
|
||||
|
@ -985,7 +985,7 @@ TEST_F(ResolverBuiltinFloatTest, FrexpVector_f32) {
|
|||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
ASSERT_NE(TypeOf(call), nullptr);
|
||||
auto* ty = TypeOf(call)->As<sem::Struct>();
|
||||
auto* ty = TypeOf(call)->As<type::Struct>();
|
||||
ASSERT_NE(ty, nullptr);
|
||||
ASSERT_EQ(ty->Members().Length(), 2u);
|
||||
|
||||
|
@ -1020,7 +1020,7 @@ TEST_F(ResolverBuiltinFloatTest, FrexpVector_f16) {
|
|||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
ASSERT_NE(TypeOf(call), nullptr);
|
||||
auto* ty = TypeOf(call)->As<sem::Struct>();
|
||||
auto* ty = TypeOf(call)->As<type::Struct>();
|
||||
ASSERT_NE(ty, nullptr);
|
||||
ASSERT_EQ(ty->Members().Length(), 2u);
|
||||
|
||||
|
@ -1174,7 +1174,7 @@ TEST_F(ResolverBuiltinFloatTest, ModfScalar_f32) {
|
|||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
ASSERT_NE(TypeOf(call), nullptr);
|
||||
auto* ty = TypeOf(call)->As<sem::Struct>();
|
||||
auto* ty = TypeOf(call)->As<type::Struct>();
|
||||
ASSERT_NE(ty, nullptr);
|
||||
ASSERT_EQ(ty->Members().Length(), 2u);
|
||||
|
||||
|
@ -1205,7 +1205,7 @@ TEST_F(ResolverBuiltinFloatTest, ModfScalar_f16) {
|
|||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
ASSERT_NE(TypeOf(call), nullptr);
|
||||
auto* ty = TypeOf(call)->As<sem::Struct>();
|
||||
auto* ty = TypeOf(call)->As<type::Struct>();
|
||||
ASSERT_NE(ty, nullptr);
|
||||
ASSERT_EQ(ty->Members().Length(), 2u);
|
||||
|
||||
|
@ -1234,7 +1234,7 @@ TEST_F(ResolverBuiltinFloatTest, ModfVector_f32) {
|
|||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
ASSERT_NE(TypeOf(call), nullptr);
|
||||
auto* ty = TypeOf(call)->As<sem::Struct>();
|
||||
auto* ty = TypeOf(call)->As<type::Struct>();
|
||||
ASSERT_NE(ty, nullptr);
|
||||
ASSERT_EQ(ty->Members().Length(), 2u);
|
||||
|
||||
|
@ -1269,7 +1269,7 @@ TEST_F(ResolverBuiltinFloatTest, ModfVector_f16) {
|
|||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
ASSERT_NE(TypeOf(call), nullptr);
|
||||
auto* ty = TypeOf(call)->As<sem::Struct>();
|
||||
auto* ty = TypeOf(call)->As<type::Struct>();
|
||||
ASSERT_NE(ty, nullptr);
|
||||
ASSERT_EQ(ty->Members().Length(), 2u);
|
||||
|
||||
|
|
|
@ -948,7 +948,7 @@ TEST_F(ResolverBuiltinsValidationTest, Frexp_Scalar) {
|
|||
WrapInFunction(builtin);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
auto* res_ty = TypeOf(builtin)->As<sem::Struct>();
|
||||
auto* res_ty = TypeOf(builtin)->As<type::Struct>();
|
||||
ASSERT_TRUE(res_ty != nullptr);
|
||||
auto members = res_ty->Members();
|
||||
ASSERT_EQ(members.Length(), 2u);
|
||||
|
@ -961,7 +961,7 @@ TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec2) {
|
|||
WrapInFunction(builtin);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
auto* res_ty = TypeOf(builtin)->As<sem::Struct>();
|
||||
auto* res_ty = TypeOf(builtin)->As<type::Struct>();
|
||||
ASSERT_TRUE(res_ty != nullptr);
|
||||
auto members = res_ty->Members();
|
||||
ASSERT_EQ(members.Length(), 2u);
|
||||
|
@ -978,7 +978,7 @@ TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec3) {
|
|||
WrapInFunction(builtin);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
auto* res_ty = TypeOf(builtin)->As<sem::Struct>();
|
||||
auto* res_ty = TypeOf(builtin)->As<type::Struct>();
|
||||
ASSERT_TRUE(res_ty != nullptr);
|
||||
auto members = res_ty->Members();
|
||||
ASSERT_EQ(members.Length(), 2u);
|
||||
|
@ -995,7 +995,7 @@ TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec4) {
|
|||
WrapInFunction(builtin);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
auto* res_ty = TypeOf(builtin)->As<sem::Struct>();
|
||||
auto* res_ty = TypeOf(builtin)->As<type::Struct>();
|
||||
ASSERT_TRUE(res_ty != nullptr);
|
||||
auto members = res_ty->Members();
|
||||
ASSERT_EQ(members.Length(), 2u);
|
||||
|
@ -1012,7 +1012,7 @@ TEST_F(ResolverBuiltinsValidationTest, Modf_Scalar) {
|
|||
WrapInFunction(builtin);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
auto* res_ty = TypeOf(builtin)->As<sem::Struct>();
|
||||
auto* res_ty = TypeOf(builtin)->As<type::Struct>();
|
||||
ASSERT_TRUE(res_ty != nullptr);
|
||||
auto members = res_ty->Members();
|
||||
ASSERT_EQ(members.Length(), 2u);
|
||||
|
@ -1025,7 +1025,7 @@ TEST_F(ResolverBuiltinsValidationTest, Modf_Vec2) {
|
|||
WrapInFunction(builtin);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
auto* res_ty = TypeOf(builtin)->As<sem::Struct>();
|
||||
auto* res_ty = TypeOf(builtin)->As<type::Struct>();
|
||||
ASSERT_TRUE(res_ty != nullptr);
|
||||
auto members = res_ty->Members();
|
||||
ASSERT_EQ(members.Length(), 2u);
|
||||
|
@ -1042,7 +1042,7 @@ TEST_F(ResolverBuiltinsValidationTest, Modf_Vec3) {
|
|||
WrapInFunction(builtin);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
auto* res_ty = TypeOf(builtin)->As<sem::Struct>();
|
||||
auto* res_ty = TypeOf(builtin)->As<type::Struct>();
|
||||
ASSERT_TRUE(res_ty != nullptr);
|
||||
auto members = res_ty->Members();
|
||||
ASSERT_EQ(members.Length(), 2u);
|
||||
|
@ -1059,7 +1059,7 @@ TEST_F(ResolverBuiltinsValidationTest, Modf_Vec4) {
|
|||
WrapInFunction(builtin);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
auto* res_ty = TypeOf(builtin)->As<sem::Struct>();
|
||||
auto* res_ty = TypeOf(builtin)->As<type::Struct>();
|
||||
ASSERT_TRUE(res_ty != nullptr);
|
||||
auto members = res_ty->Members();
|
||||
ASSERT_EQ(members.Length(), 2u);
|
||||
|
|
|
@ -166,7 +166,7 @@ TEST_P(ResolverConstEvalBuiltinTest, Test) {
|
|||
ASSERT_NE(value, nullptr);
|
||||
EXPECT_TYPE(value->Type(), sem->Type());
|
||||
|
||||
if (value->Type()->Is<sem::Struct>()) {
|
||||
if (value->Type()->Is<type::Struct>()) {
|
||||
// The result type of the constant-evaluated expression is a structure.
|
||||
// Compare each of the fields individually.
|
||||
for (size_t i = 0; i < expected_case.values.Length(); i++) {
|
||||
|
|
|
@ -1445,7 +1445,7 @@ TEST_F(ResolverConstEvalTest, Array_Struct_f32_Zero) {
|
|||
ASSERT_NE(sem, nullptr);
|
||||
auto* arr = sem->Type()->As<type::Array>();
|
||||
ASSERT_NE(arr, nullptr);
|
||||
EXPECT_TRUE(arr->ElemType()->Is<sem::Struct>());
|
||||
EXPECT_TRUE(arr->ElemType()->Is<type::Struct>());
|
||||
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
|
||||
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
|
||||
EXPECT_TRUE(sem->ConstantValue()->AllZero());
|
||||
|
@ -1662,7 +1662,7 @@ TEST_F(ResolverConstEvalTest, Array_Struct_f32_Elements) {
|
|||
ASSERT_NE(sem, nullptr);
|
||||
auto* arr = sem->Type()->As<type::Array>();
|
||||
ASSERT_NE(arr, nullptr);
|
||||
EXPECT_TRUE(arr->ElemType()->Is<sem::Struct>());
|
||||
EXPECT_TRUE(arr->ElemType()->Is<type::Struct>());
|
||||
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
|
||||
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
|
||||
EXPECT_FALSE(sem->ConstantValue()->AllZero());
|
||||
|
@ -1787,7 +1787,7 @@ TEST_F(ResolverConstEvalTest, Struct_I32s_ZeroInit) {
|
|||
|
||||
auto* sem = Sem().Get(expr);
|
||||
ASSERT_NE(sem, nullptr);
|
||||
auto* str = sem->Type()->As<sem::Struct>();
|
||||
auto* str = sem->Type()->As<type::Struct>();
|
||||
ASSERT_NE(str, nullptr);
|
||||
EXPECT_EQ(str->Members().Length(), 3u);
|
||||
ASSERT_NE(sem->ConstantValue(), nullptr);
|
||||
|
@ -1828,7 +1828,7 @@ TEST_F(ResolverConstEvalTest, Struct_MixedScalars_ZeroInit) {
|
|||
|
||||
auto* sem = Sem().Get(expr);
|
||||
ASSERT_NE(sem, nullptr);
|
||||
auto* str = sem->Type()->As<sem::Struct>();
|
||||
auto* str = sem->Type()->As<type::Struct>();
|
||||
ASSERT_NE(str, nullptr);
|
||||
EXPECT_EQ(str->Members().Length(), 5u);
|
||||
ASSERT_NE(sem->ConstantValue(), nullptr);
|
||||
|
@ -1875,7 +1875,7 @@ TEST_F(ResolverConstEvalTest, Struct_VectorF32s_ZeroInit) {
|
|||
|
||||
auto* sem = Sem().Get(expr);
|
||||
ASSERT_NE(sem, nullptr);
|
||||
auto* str = sem->Type()->As<sem::Struct>();
|
||||
auto* str = sem->Type()->As<type::Struct>();
|
||||
ASSERT_NE(str, nullptr);
|
||||
EXPECT_EQ(str->Members().Length(), 3u);
|
||||
ASSERT_NE(sem->ConstantValue(), nullptr);
|
||||
|
@ -1928,7 +1928,7 @@ TEST_F(ResolverConstEvalTest, Struct_MixedVectors_ZeroInit) {
|
|||
|
||||
auto* sem = Sem().Get(expr);
|
||||
ASSERT_NE(sem, nullptr);
|
||||
auto* str = sem->Type()->As<sem::Struct>();
|
||||
auto* str = sem->Type()->As<type::Struct>();
|
||||
ASSERT_NE(str, nullptr);
|
||||
EXPECT_EQ(str->Members().Length(), 5u);
|
||||
ASSERT_NE(sem->ConstantValue(), nullptr);
|
||||
|
@ -1999,7 +1999,7 @@ TEST_F(ResolverConstEvalTest, Struct_Struct_ZeroInit) {
|
|||
|
||||
auto* sem = Sem().Get(expr);
|
||||
ASSERT_NE(sem, nullptr);
|
||||
auto* str = sem->Type()->As<sem::Struct>();
|
||||
auto* str = sem->Type()->As<type::Struct>();
|
||||
ASSERT_NE(str, nullptr);
|
||||
EXPECT_EQ(str->Members().Length(), 2u);
|
||||
ASSERT_NE(sem->ConstantValue(), nullptr);
|
||||
|
@ -2009,14 +2009,14 @@ TEST_F(ResolverConstEvalTest, Struct_Struct_ZeroInit) {
|
|||
|
||||
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AnyZero());
|
||||
EXPECT_TRUE(sem->ConstantValue()->Index(0)->AllZero());
|
||||
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Type()->Is<sem::Struct>());
|
||||
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Type()->Is<type::Struct>());
|
||||
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(0)->ValueAs<i32>(), 0_i);
|
||||
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<u32>(), 0_u);
|
||||
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(2)->ValueAs<f32>(), 0_f);
|
||||
|
||||
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
|
||||
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AllZero());
|
||||
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Type()->Is<sem::Struct>());
|
||||
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Type()->Is<type::Struct>());
|
||||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(0)->ValueAs<i32>(), 0_i);
|
||||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->ValueAs<u32>(), 0_u);
|
||||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->ValueAs<f32>(), 0_f);
|
||||
|
@ -2039,7 +2039,7 @@ TEST_F(ResolverConstEvalTest, Struct_MixedScalars_Construct) {
|
|||
|
||||
auto* sem = Sem().Get(expr);
|
||||
ASSERT_NE(sem, nullptr);
|
||||
auto* str = sem->Type()->As<sem::Struct>();
|
||||
auto* str = sem->Type()->As<type::Struct>();
|
||||
ASSERT_NE(str, nullptr);
|
||||
EXPECT_EQ(str->Members().Length(), 5u);
|
||||
ASSERT_NE(sem->ConstantValue(), nullptr);
|
||||
|
@ -2091,7 +2091,7 @@ TEST_F(ResolverConstEvalTest, Struct_MixedVectors_Construct) {
|
|||
|
||||
auto* sem = Sem().Get(expr);
|
||||
ASSERT_NE(sem, nullptr);
|
||||
auto* str = sem->Type()->As<sem::Struct>();
|
||||
auto* str = sem->Type()->As<type::Struct>();
|
||||
ASSERT_NE(str, nullptr);
|
||||
EXPECT_EQ(str->Members().Length(), 5u);
|
||||
ASSERT_NE(sem->ConstantValue(), nullptr);
|
||||
|
@ -2163,7 +2163,7 @@ TEST_F(ResolverConstEvalTest, Struct_Struct_Construct) {
|
|||
|
||||
auto* sem = Sem().Get(expr);
|
||||
ASSERT_NE(sem, nullptr);
|
||||
auto* str = sem->Type()->As<sem::Struct>();
|
||||
auto* str = sem->Type()->As<type::Struct>();
|
||||
ASSERT_NE(str, nullptr);
|
||||
EXPECT_EQ(str->Members().Length(), 2u);
|
||||
ASSERT_NE(sem->ConstantValue(), nullptr);
|
||||
|
@ -2173,14 +2173,14 @@ TEST_F(ResolverConstEvalTest, Struct_Struct_Construct) {
|
|||
|
||||
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AnyZero());
|
||||
EXPECT_FALSE(sem->ConstantValue()->Index(0)->AllZero());
|
||||
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Type()->Is<sem::Struct>());
|
||||
EXPECT_TRUE(sem->ConstantValue()->Index(0)->Type()->Is<type::Struct>());
|
||||
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(0)->ValueAs<i32>(), 1_i);
|
||||
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(1)->ValueAs<u32>(), 2_u);
|
||||
EXPECT_EQ(sem->ConstantValue()->Index(0)->Index(2)->ValueAs<f32>(), 3_f);
|
||||
|
||||
EXPECT_TRUE(sem->ConstantValue()->Index(1)->AnyZero());
|
||||
EXPECT_FALSE(sem->ConstantValue()->Index(1)->AllZero());
|
||||
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Type()->Is<sem::Struct>());
|
||||
EXPECT_TRUE(sem->ConstantValue()->Index(1)->Type()->Is<type::Struct>());
|
||||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(0)->ValueAs<i32>(), 4_i);
|
||||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(1)->ValueAs<u32>(), 0_u);
|
||||
EXPECT_EQ(sem->ConstantValue()->Index(1)->Index(2)->ValueAs<f32>(), 6_f);
|
||||
|
@ -2199,7 +2199,7 @@ TEST_F(ResolverConstEvalTest, Struct_Array_Construct) {
|
|||
|
||||
auto* sem = Sem().Get(expr);
|
||||
ASSERT_NE(sem, nullptr);
|
||||
auto* str = sem->Type()->As<sem::Struct>();
|
||||
auto* str = sem->Type()->As<type::Struct>();
|
||||
ASSERT_NE(str, nullptr);
|
||||
EXPECT_EQ(str->Members().Length(), 2u);
|
||||
ASSERT_NE(sem->ConstantValue(), nullptr);
|
||||
|
|
|
@ -41,7 +41,7 @@ TEST_F(ResolverConstEvalTest, StructMemberAccess) {
|
|||
|
||||
auto* outer = Sem().Get(outer_expr);
|
||||
ASSERT_NE(outer, nullptr);
|
||||
auto* str = outer->Type()->As<sem::Struct>();
|
||||
auto* str = outer->Type()->As<type::Struct>();
|
||||
ASSERT_NE(str, nullptr);
|
||||
EXPECT_EQ(str->Members().Length(), 2u);
|
||||
ASSERT_NE(outer->ConstantValue(), nullptr);
|
||||
|
@ -53,7 +53,7 @@ TEST_F(ResolverConstEvalTest, StructMemberAccess) {
|
|||
ASSERT_NE(o1->ConstantValue(), nullptr);
|
||||
EXPECT_FALSE(o1->ConstantValue()->AnyZero());
|
||||
EXPECT_FALSE(o1->ConstantValue()->AllZero());
|
||||
EXPECT_TRUE(o1->ConstantValue()->Type()->Is<sem::Struct>());
|
||||
EXPECT_TRUE(o1->ConstantValue()->Type()->Is<type::Struct>());
|
||||
EXPECT_EQ(o1->ConstantValue()->Index(0)->ValueAs<i32>(), 1_i);
|
||||
EXPECT_EQ(o1->ConstantValue()->Index(1)->ValueAs<u32>(), 2_u);
|
||||
EXPECT_EQ(o1->ConstantValue()->Index(2)->ValueAs<f32>(), 3_f);
|
||||
|
|
|
@ -820,25 +820,25 @@ bool match_atomic_compare_exchange_result(MatchState&, const type::Type* ty, con
|
|||
return false;
|
||||
}
|
||||
|
||||
const sem::Struct* build_modf_result(MatchState& state, const type::Type* el) {
|
||||
const type::Struct* build_modf_result(MatchState& state, const type::Type* el) {
|
||||
return CreateModfResult(state.builder, el);
|
||||
}
|
||||
|
||||
const sem::Struct* build_modf_result_vec(MatchState& state, Number& n, const type::Type* el) {
|
||||
const type::Struct* build_modf_result_vec(MatchState& state, Number& n, const type::Type* el) {
|
||||
auto* vec = state.builder.create<type::Vector>(el, n.Value());
|
||||
return CreateModfResult(state.builder, vec);
|
||||
}
|
||||
|
||||
const sem::Struct* build_frexp_result(MatchState& state, const type::Type* el) {
|
||||
const type::Struct* build_frexp_result(MatchState& state, const type::Type* el) {
|
||||
return CreateFrexpResult(state.builder, el);
|
||||
}
|
||||
|
||||
const sem::Struct* build_frexp_result_vec(MatchState& state, Number& n, const type::Type* el) {
|
||||
const type::Struct* build_frexp_result_vec(MatchState& state, Number& n, const type::Type* el) {
|
||||
auto* vec = state.builder.create<type::Vector>(el, n.Value());
|
||||
return CreateFrexpResult(state.builder, vec);
|
||||
}
|
||||
|
||||
const sem::Struct* build_atomic_compare_exchange_result(MatchState& state, const type::Type* ty) {
|
||||
const type::Struct* build_atomic_compare_exchange_result(MatchState& state, const type::Type* ty) {
|
||||
return CreateAtomicCompareExchangeResult(state.builder, ty);
|
||||
}
|
||||
|
||||
|
|
|
@ -1253,11 +1253,11 @@ TEST_F(MaterializeAbstractStructure, Modf_Scalar_DefaultType) {
|
|||
auto* sem = Sem().Get(call);
|
||||
ASSERT_TRUE(sem->Is<sem::Materialize>());
|
||||
auto* materialize = sem->As<sem::Materialize>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<type::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<type::F32>());
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<type::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<type::AbstractFloat>());
|
||||
}
|
||||
|
||||
|
@ -1269,12 +1269,12 @@ TEST_F(MaterializeAbstractStructure, Modf_Vector_DefaultType) {
|
|||
auto* sem = Sem().Get(call);
|
||||
ASSERT_TRUE(sem->Is<sem::Materialize>());
|
||||
auto* materialize = sem->As<sem::Materialize>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<type::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<type::Vector>());
|
||||
ASSERT_TRUE(concrete_str->Members()[0]->Type()->As<type::Vector>()->type()->Is<type::F32>());
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<type::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<type::Vector>());
|
||||
ASSERT_TRUE(
|
||||
abstract_str->Members()[0]->Type()->As<type::Vector>()->type()->Is<type::AbstractFloat>());
|
||||
|
@ -1291,11 +1291,11 @@ TEST_F(MaterializeAbstractStructure, Modf_Scalar_ExplicitType) {
|
|||
auto* sem = Sem().Get(call);
|
||||
ASSERT_TRUE(sem->Is<sem::Materialize>());
|
||||
auto* materialize = sem->As<sem::Materialize>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<type::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<type::F16>());
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<type::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<type::AbstractFloat>());
|
||||
}
|
||||
|
||||
|
@ -1309,12 +1309,12 @@ TEST_F(MaterializeAbstractStructure, Modf_Vector_ExplicitType) {
|
|||
auto* sem = Sem().Get(call);
|
||||
ASSERT_TRUE(sem->Is<sem::Materialize>());
|
||||
auto* materialize = sem->As<sem::Materialize>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<type::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<type::Vector>());
|
||||
ASSERT_TRUE(concrete_str->Members()[0]->Type()->As<type::Vector>()->type()->Is<type::F16>());
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<type::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<type::Vector>());
|
||||
ASSERT_TRUE(
|
||||
abstract_str->Members()[0]->Type()->As<type::Vector>()->type()->Is<type::AbstractFloat>());
|
||||
|
@ -1328,12 +1328,12 @@ TEST_F(MaterializeAbstractStructure, Frexp_Scalar_DefaultType) {
|
|||
auto* sem = Sem().Get(call);
|
||||
ASSERT_TRUE(sem->Is<sem::Materialize>());
|
||||
auto* materialize = sem->As<sem::Materialize>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<type::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<type::F32>());
|
||||
ASSERT_TRUE(concrete_str->Members()[1]->Type()->Is<type::I32>());
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<type::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<type::AbstractFloat>());
|
||||
ASSERT_TRUE(abstract_str->Members()[1]->Type()->Is<type::AbstractInt>());
|
||||
}
|
||||
|
@ -1346,14 +1346,14 @@ TEST_F(MaterializeAbstractStructure, Frexp_Vector_DefaultType) {
|
|||
auto* sem = Sem().Get(call);
|
||||
ASSERT_TRUE(sem->Is<sem::Materialize>());
|
||||
auto* materialize = sem->As<sem::Materialize>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<type::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<type::Vector>());
|
||||
ASSERT_TRUE(concrete_str->Members()[1]->Type()->Is<type::Vector>());
|
||||
ASSERT_TRUE(concrete_str->Members()[0]->Type()->As<type::Vector>()->type()->Is<type::F32>());
|
||||
ASSERT_TRUE(concrete_str->Members()[1]->Type()->As<type::Vector>()->type()->Is<type::I32>());
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<type::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<type::Vector>());
|
||||
ASSERT_TRUE(
|
||||
abstract_str->Members()[0]->Type()->As<type::Vector>()->type()->Is<type::AbstractFloat>());
|
||||
|
@ -1372,12 +1372,12 @@ TEST_F(MaterializeAbstractStructure, Frexp_Scalar_ExplicitType) {
|
|||
auto* sem = Sem().Get(call);
|
||||
ASSERT_TRUE(sem->Is<sem::Materialize>());
|
||||
auto* materialize = sem->As<sem::Materialize>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<type::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<type::F16>());
|
||||
ASSERT_TRUE(concrete_str->Members()[1]->Type()->Is<type::I32>());
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<type::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<type::AbstractFloat>());
|
||||
ASSERT_TRUE(abstract_str->Members()[1]->Type()->Is<type::AbstractInt>());
|
||||
}
|
||||
|
@ -1392,14 +1392,14 @@ TEST_F(MaterializeAbstractStructure, Frexp_Vector_ExplicitType) {
|
|||
auto* sem = Sem().Get(call);
|
||||
ASSERT_TRUE(sem->Is<sem::Materialize>());
|
||||
auto* materialize = sem->As<sem::Materialize>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Type()->Is<type::Struct>());
|
||||
auto* concrete_str = materialize->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<type::Vector>());
|
||||
ASSERT_TRUE(concrete_str->Members()[1]->Type()->Is<type::Vector>());
|
||||
ASSERT_TRUE(concrete_str->Members()[0]->Type()->As<type::Vector>()->type()->Is<type::F16>());
|
||||
ASSERT_TRUE(concrete_str->Members()[1]->Type()->As<type::Vector>()->type()->Is<type::I32>());
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
|
||||
ASSERT_TRUE(materialize->Expr()->Type()->Is<type::Struct>());
|
||||
auto* abstract_str = materialize->Expr()->Type()->As<type::Struct>();
|
||||
ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<type::Vector>());
|
||||
ASSERT_TRUE(
|
||||
abstract_str->Members()[0]->Type()->As<type::Vector>()->type()->Is<type::AbstractFloat>());
|
||||
|
|
|
@ -997,7 +997,7 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
|
|||
func->AddParameter(p);
|
||||
|
||||
auto* p_ty = const_cast<type::Type*>(p->Type());
|
||||
if (auto* str = p_ty->As<sem::Struct>()) {
|
||||
if (auto* str = p_ty->As<type::Struct>()) {
|
||||
switch (decl->PipelineStage()) {
|
||||
case ast::PipelineStage::kVertex:
|
||||
str->AddUsage(type::PipelineStageUsage::kVertexInput);
|
||||
|
@ -1096,7 +1096,7 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
|
|||
}
|
||||
}
|
||||
|
||||
if (auto* str = return_type->As<sem::Struct>()) {
|
||||
if (auto* str = return_type->As<type::Struct>()) {
|
||||
if (!ApplyAddressSpaceUsageToType(builtin::AddressSpace::kUndefined, str, decl->source)) {
|
||||
AddNote("while instantiating return type for " + decl->name->symbol.Name(),
|
||||
decl->source);
|
||||
|
@ -1761,7 +1761,7 @@ const type::Type* Resolver::ConcreteType(const type::Type* ty,
|
|||
}
|
||||
return nullptr;
|
||||
},
|
||||
[&](const sem::Struct* s) -> const type::Type* {
|
||||
[&](const type::Struct* s) -> const type::Type* {
|
||||
if (auto tys = s->ConcreteTypes(); !tys.IsEmpty()) {
|
||||
return target_ty ? target_ty : tys[0];
|
||||
}
|
||||
|
@ -2143,7 +2143,7 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
|||
}
|
||||
return call;
|
||||
},
|
||||
[&](const sem::Struct* str) -> sem::Call* {
|
||||
[&](const type::Struct* str) -> sem::Call* {
|
||||
auto* call_target = struct_ctors_.GetOrCreate(
|
||||
StructConstructorSig{{str, args.Length(), args_stage}},
|
||||
[&]() -> sem::ValueConstructor* {
|
||||
|
@ -3248,10 +3248,10 @@ sem::ValueExpression* Resolver::MemberAccessor(const ast::MemberAccessorExpressi
|
|||
|
||||
return Switch(
|
||||
storage_ty, //
|
||||
[&](const sem::Struct* str) -> sem::ValueExpression* {
|
||||
[&](const type::Struct* str) -> sem::ValueExpression* {
|
||||
auto symbol = expr->member->symbol;
|
||||
|
||||
const sem::StructMember* member = nullptr;
|
||||
const type::StructMember* member = nullptr;
|
||||
for (auto* m : str->Members()) {
|
||||
if (m->Name() == symbol) {
|
||||
member = m;
|
||||
|
|
|
@ -560,7 +560,7 @@ class Resolver {
|
|||
// It is a tuple of the structure type, number of arguments provided and earliest evaluation
|
||||
// stage.
|
||||
using StructConstructorSig =
|
||||
utils::UnorderedKeyWrapper<std::tuple<const sem::Struct*, size_t, sem::EvaluationStage>>;
|
||||
utils::UnorderedKeyWrapper<std::tuple<const type::Struct*, size_t, sem::EvaluationStage>>;
|
||||
|
||||
/// ExprEvalStageConstraint describes a constraint on when expressions can be evaluated.
|
||||
struct ExprEvalStageConstraint {
|
||||
|
|
|
@ -1265,7 +1265,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct) {
|
|||
EXPECT_TRUE(sma->Member()->Type()->Is<type::F32>());
|
||||
EXPECT_EQ(sma->Object()->Declaration(), mem->object);
|
||||
EXPECT_EQ(sma->Member()->Index(), 1u);
|
||||
EXPECT_EQ(sma->Member()->Declaration()->name->symbol, Symbols().Get("second_member"));
|
||||
EXPECT_EQ(sma->Member()->Name().Name(), "second_member");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) {
|
||||
|
|
|
@ -32,7 +32,7 @@ TEST_F(ResolverAddressSpaceUseTest, UnreachableStruct) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_TRUE(sem->AddressSpaceUsage().empty());
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ TEST_F(ResolverAddressSpaceUseTest, StructReachableFromParameter) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(builtin::AddressSpace::kUndefined));
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ TEST_F(ResolverAddressSpaceUseTest, StructReachableFromReturnType) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(builtin::AddressSpace::kUndefined));
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ TEST_F(ResolverAddressSpaceUseTest, StructReachableFromGlobal) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(builtin::AddressSpace::kPrivate));
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ TEST_F(ResolverAddressSpaceUseTest, StructReachableViaGlobalAlias) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(builtin::AddressSpace::kPrivate));
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ TEST_F(ResolverAddressSpaceUseTest, StructReachableViaGlobalStruct) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(builtin::AddressSpace::kPrivate));
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ TEST_F(ResolverAddressSpaceUseTest, StructReachableViaGlobalArray) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(builtin::AddressSpace::kPrivate));
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ TEST_F(ResolverAddressSpaceUseTest, StructReachableFromLocal) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(builtin::AddressSpace::kFunction));
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ TEST_F(ResolverAddressSpaceUseTest, StructReachableViaLocalAlias) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(builtin::AddressSpace::kFunction));
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ TEST_F(ResolverAddressSpaceUseTest, StructReachableViaLocalStruct) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(builtin::AddressSpace::kFunction));
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ TEST_F(ResolverAddressSpaceUseTest, StructReachableViaLocalArray) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(builtin::AddressSpace::kFunction));
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ TEST_F(ResolverAddressSpaceUseTest, StructMultipleAddressSpaceUses) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(builtin::AddressSpace::kUniform,
|
||||
builtin::AddressSpace::kStorage,
|
||||
|
|
|
@ -34,7 +34,7 @@ TEST_F(ResolverPipelineStageUseTest, UnusedStruct) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_TRUE(sem->PipelineStageUses().empty());
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsNonEntryPointParam) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_TRUE(sem->PipelineStageUses().empty());
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsNonEntryPointReturnType) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_TRUE(sem->PipelineStageUses().empty());
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsVertexShaderParam) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->PipelineStageUses(),
|
||||
UnorderedElementsAre(type::PipelineStageUsage::kVertexInput));
|
||||
|
@ -90,7 +90,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsVertexShaderReturnType) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->PipelineStageUses(),
|
||||
UnorderedElementsAre(type::PipelineStageUsage::kVertexOutput));
|
||||
|
@ -104,7 +104,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsFragmentShaderParam) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->PipelineStageUses(),
|
||||
UnorderedElementsAre(type::PipelineStageUsage::kFragmentInput));
|
||||
|
@ -118,7 +118,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsFragmentShaderReturnType) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->PipelineStageUses(),
|
||||
UnorderedElementsAre(type::PipelineStageUsage::kFragmentOutput));
|
||||
|
@ -135,7 +135,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsComputeShaderParam) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->PipelineStageUses(),
|
||||
UnorderedElementsAre(type::PipelineStageUsage::kComputeInput));
|
||||
|
@ -154,7 +154,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedMultipleStages) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->PipelineStageUses(),
|
||||
UnorderedElementsAre(type::PipelineStageUsage::kVertexOutput,
|
||||
|
@ -170,7 +170,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderParamViaAlias) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->PipelineStageUses(),
|
||||
UnorderedElementsAre(type::PipelineStageUsage::kFragmentInput));
|
||||
|
@ -184,7 +184,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderParamLocationSet) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
ASSERT_EQ(1u, sem->Members().Length());
|
||||
EXPECT_EQ(3u, sem->Members()[0]->Attributes().location);
|
||||
|
@ -200,7 +200,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderReturnTypeViaAlias) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
EXPECT_THAT(sem->PipelineStageUses(),
|
||||
UnorderedElementsAre(type::PipelineStageUsage::kFragmentOutput));
|
||||
|
@ -214,7 +214,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderReturnTypeLocationSet) {
|
|||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||
auto* sem = TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_NE(sem, nullptr);
|
||||
ASSERT_EQ(1u, sem->Members().Length());
|
||||
EXPECT_EQ(3u, sem->Members()[0]->Attributes().location);
|
||||
|
|
|
@ -200,7 +200,7 @@ bool Validator::AddDiagnostic(builtin::DiagnosticRule rule,
|
|||
// https://gpuweb.github.io/gpuweb/wgsl/#plain-types-section
|
||||
bool Validator::IsPlain(const type::Type* type) const {
|
||||
return type->is_scalar() ||
|
||||
type->IsAnyOf<type::Atomic, type::Vector, type::Matrix, type::Array, sem::Struct>();
|
||||
type->IsAnyOf<type::Atomic, type::Vector, type::Matrix, type::Array, type::Struct>();
|
||||
}
|
||||
|
||||
// https://gpuweb.github.io/gpuweb/wgsl/#fixed-footprint-types
|
||||
|
@ -214,7 +214,7 @@ bool Validator::IsFixedFootprint(const type::Type* type) const {
|
|||
return !arr->Count()->Is<type::RuntimeArrayCount>() &&
|
||||
IsFixedFootprint(arr->ElemType());
|
||||
},
|
||||
[&](const sem::Struct* str) {
|
||||
[&](const type::Struct* str) {
|
||||
for (auto* member : str->Members()) {
|
||||
if (!IsFixedFootprint(member->Type())) {
|
||||
return false;
|
||||
|
@ -235,7 +235,7 @@ bool Validator::IsHostShareable(const type::Type* type) const {
|
|||
[&](const type::Vector* vec) { return IsHostShareable(vec->type()); },
|
||||
[&](const type::Matrix* mat) { return IsHostShareable(mat->type()); },
|
||||
[&](const type::Array* arr) { return IsHostShareable(arr->ElemType()); },
|
||||
[&](const sem::Struct* str) {
|
||||
[&](const type::Struct* str) {
|
||||
for (auto* member : str->Members()) {
|
||||
if (!IsHostShareable(member->Type())) {
|
||||
return false;
|
||||
|
@ -397,11 +397,11 @@ bool Validator::AddressSpaceLayout(const type::Type* store_ty,
|
|||
|
||||
auto is_uniform_struct_or_array = [address_space](const type::Type* ty) {
|
||||
return address_space == builtin::AddressSpace::kUniform &&
|
||||
ty->IsAnyOf<type::Array, sem::Struct>();
|
||||
ty->IsAnyOf<type::Array, type::Struct>();
|
||||
};
|
||||
|
||||
auto is_uniform_struct = [address_space](const type::Type* ty) {
|
||||
return address_space == builtin::AddressSpace::kUniform && ty->Is<sem::Struct>();
|
||||
return address_space == builtin::AddressSpace::kUniform && ty->Is<type::Struct>();
|
||||
};
|
||||
|
||||
auto required_alignment_of = [&](const type::Type* ty) {
|
||||
|
@ -413,7 +413,7 @@ bool Validator::AddressSpaceLayout(const type::Type* store_ty,
|
|||
return required_align;
|
||||
};
|
||||
|
||||
auto member_name_of = [](const sem::StructMember* sm) { return sm->Name().Name(); };
|
||||
auto member_name_of = [](const type::StructMember* sm) { return sm->Name().Name(); };
|
||||
|
||||
// Only validate the [type + address space] once
|
||||
if (!valid_type_storage_layouts_.Add(TypeAndAddressSpace{store_ty, address_space})) {
|
||||
|
@ -1138,12 +1138,12 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
|
|||
}
|
||||
|
||||
if (IsValidationEnabled(attrs, ast::DisabledValidation::kEntryPointParameter)) {
|
||||
if (is_struct_member && ty->Is<sem::Struct>()) {
|
||||
if (is_struct_member && ty->Is<type::Struct>()) {
|
||||
AddError("nested structures cannot be used for entry point IO", source);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ty->Is<sem::Struct>() && !pipeline_io_attribute) {
|
||||
if (!ty->Is<type::Struct>() && !pipeline_io_attribute) {
|
||||
std::string err = "missing entry point IO attribute";
|
||||
if (!is_struct_member) {
|
||||
err += (param_or_ret == ParamOrRetType::kParameter ? " on parameter"
|
||||
|
@ -1763,7 +1763,7 @@ bool Validator::FunctionCall(const sem::Call* call, sem::Statement* current_stat
|
|||
}
|
||||
|
||||
bool Validator::StructureInitializer(const ast::CallExpression* ctor,
|
||||
const sem::Struct* struct_type) const {
|
||||
const type::Struct* struct_type) const {
|
||||
if (!struct_type->IsConstructible()) {
|
||||
AddError("structure constructor has non-constructible type", ctor->source);
|
||||
return false;
|
||||
|
@ -2564,8 +2564,8 @@ bool Validator::CheckTypeAccessAddressSpace(
|
|||
}
|
||||
return true;
|
||||
},
|
||||
[&](const sem::Struct*) { return check_sub_atomics(); }, //
|
||||
[&](const type::Array*) { return check_sub_atomics(); }, //
|
||||
[&](const type::Struct*) { return check_sub_atomics(); }, //
|
||||
[&](const type::Array*) { return check_sub_atomics(); }, //
|
||||
[&](Default) { return true; });
|
||||
}
|
||||
|
||||
|
|
|
@ -397,7 +397,7 @@ class Validator {
|
|||
/// @param struct_type the type of the structure
|
||||
/// @returns true on success, false otherwise
|
||||
bool StructureInitializer(const ast::CallExpression* ctor,
|
||||
const sem::Struct* struct_type) const;
|
||||
const type::Struct* struct_type) const;
|
||||
|
||||
/// Validates a switch statement
|
||||
/// @param s the switch to validate
|
||||
|
|
|
@ -81,8 +81,8 @@ TEST_F(ResolverVariableTest, LocalVar_NoInitializer) {
|
|||
EXPECT_TRUE(TypeOf(f)->As<type::Reference>()->StoreType()->Is<type::F32>());
|
||||
EXPECT_TRUE(TypeOf(h)->As<type::Reference>()->StoreType()->Is<type::F16>());
|
||||
EXPECT_TRUE(TypeOf(b)->As<type::Reference>()->StoreType()->Is<type::Bool>());
|
||||
EXPECT_TRUE(TypeOf(s)->As<type::Reference>()->StoreType()->Is<sem::Struct>());
|
||||
EXPECT_TRUE(TypeOf(a)->As<type::Reference>()->StoreType()->Is<sem::Struct>());
|
||||
EXPECT_TRUE(TypeOf(s)->As<type::Reference>()->StoreType()->Is<type::Struct>());
|
||||
EXPECT_TRUE(TypeOf(a)->As<type::Reference>()->StoreType()->Is<type::Struct>());
|
||||
|
||||
EXPECT_EQ(Sem().Get(i)->Initializer(), nullptr);
|
||||
EXPECT_EQ(Sem().Get(u)->Initializer(), nullptr);
|
||||
|
@ -161,8 +161,8 @@ TEST_F(ResolverVariableTest, LocalVar_WithInitializer) {
|
|||
EXPECT_TRUE(TypeOf(f)->As<type::Reference>()->StoreType()->Is<type::F32>());
|
||||
EXPECT_TRUE(TypeOf(h)->As<type::Reference>()->StoreType()->Is<type::F16>());
|
||||
EXPECT_TRUE(TypeOf(b)->As<type::Reference>()->StoreType()->Is<type::Bool>());
|
||||
EXPECT_TRUE(TypeOf(s)->As<type::Reference>()->StoreType()->Is<sem::Struct>());
|
||||
EXPECT_TRUE(TypeOf(a)->As<type::Reference>()->StoreType()->Is<sem::Struct>());
|
||||
EXPECT_TRUE(TypeOf(s)->As<type::Reference>()->StoreType()->Is<type::Struct>());
|
||||
EXPECT_TRUE(TypeOf(a)->As<type::Reference>()->StoreType()->Is<type::Struct>());
|
||||
|
||||
EXPECT_EQ(Sem().Get(i)->Initializer()->Declaration(), i_c);
|
||||
EXPECT_EQ(Sem().Get(u)->Initializer()->Declaration(), u_c);
|
||||
|
@ -444,8 +444,8 @@ TEST_F(ResolverVariableTest, LocalLet) {
|
|||
ASSERT_TRUE(TypeOf(f)->Is<type::F32>());
|
||||
ASSERT_TRUE(TypeOf(h)->Is<type::F16>());
|
||||
ASSERT_TRUE(TypeOf(b)->Is<type::Bool>());
|
||||
ASSERT_TRUE(TypeOf(s)->Is<sem::Struct>());
|
||||
ASSERT_TRUE(TypeOf(a)->Is<sem::Struct>());
|
||||
ASSERT_TRUE(TypeOf(s)->Is<type::Struct>());
|
||||
ASSERT_TRUE(TypeOf(a)->Is<type::Struct>());
|
||||
ASSERT_TRUE(TypeOf(p)->Is<type::Pointer>());
|
||||
ASSERT_TRUE(TypeOf(p)->As<type::Pointer>()->StoreType()->Is<type::I32>());
|
||||
|
||||
|
@ -924,7 +924,7 @@ TEST_F(ResolverVariableTest, LocalConst_ExplicitType_Decls) {
|
|||
ASSERT_TRUE(TypeOf(c_vu32)->Is<type::Vector>());
|
||||
ASSERT_TRUE(TypeOf(c_vf32)->Is<type::Vector>());
|
||||
ASSERT_TRUE(TypeOf(c_mf32)->Is<type::Matrix>());
|
||||
ASSERT_TRUE(TypeOf(c_s)->Is<sem::Struct>());
|
||||
ASSERT_TRUE(TypeOf(c_s)->Is<type::Struct>());
|
||||
|
||||
EXPECT_TRUE(Sem().Get(c_i32)->ConstantValue()->AllZero());
|
||||
EXPECT_TRUE(Sem().Get(c_u32)->ConstantValue()->AllZero());
|
||||
|
@ -987,7 +987,7 @@ TEST_F(ResolverVariableTest, LocalConst_ImplicitType_Decls) {
|
|||
ASSERT_TRUE(TypeOf(c_vaf)->Is<type::Vector>());
|
||||
ASSERT_TRUE(TypeOf(c_mf32)->Is<type::Matrix>());
|
||||
ASSERT_TRUE(TypeOf(c_maf32)->Is<type::Matrix>());
|
||||
ASSERT_TRUE(TypeOf(c_s)->Is<sem::Struct>());
|
||||
ASSERT_TRUE(TypeOf(c_s)->Is<type::Struct>());
|
||||
|
||||
EXPECT_TRUE(Sem().Get(c_i32)->ConstantValue()->AllZero());
|
||||
EXPECT_TRUE(Sem().Get(c_u32)->ConstantValue()->AllZero());
|
||||
|
|
|
@ -41,7 +41,7 @@ StructMemberAccess::StructMemberAccess(const ast::MemberAccessorExpression* decl
|
|||
const Statement* statement,
|
||||
const constant::Value* constant,
|
||||
const ValueExpression* object,
|
||||
const StructMember* member,
|
||||
const type::StructMember* member,
|
||||
bool has_side_effects,
|
||||
const Variable* root_ident /* = nullptr */)
|
||||
: Base(declaration,
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
namespace tint::ast {
|
||||
class MemberAccessorExpression;
|
||||
} // namespace tint::ast
|
||||
namespace tint::sem {
|
||||
namespace tint::type {
|
||||
class StructMember;
|
||||
} // namespace tint::sem
|
||||
} // namespace tint::type
|
||||
|
||||
namespace tint::sem {
|
||||
|
||||
|
@ -81,7 +81,7 @@ class StructMemberAccess final
|
|||
const Statement* statement,
|
||||
const constant::Value* constant,
|
||||
const ValueExpression* object,
|
||||
const StructMember* member,
|
||||
const type::StructMember* member,
|
||||
bool has_side_effects,
|
||||
const Variable* root_ident = nullptr);
|
||||
|
||||
|
@ -89,10 +89,10 @@ class StructMemberAccess final
|
|||
~StructMemberAccess() override;
|
||||
|
||||
/// @returns the structure member
|
||||
StructMember const* Member() const { return member_; }
|
||||
type::StructMember const* Member() const { return member_; }
|
||||
|
||||
private:
|
||||
StructMember const* const member_;
|
||||
type::StructMember const* const member_;
|
||||
};
|
||||
|
||||
/// Swizzle holds the semantic information for a ast::MemberAccessorExpression
|
||||
|
|
|
@ -28,7 +28,9 @@ Struct::Struct(const ast::Struct* declaration,
|
|||
uint32_t align,
|
||||
uint32_t size,
|
||||
uint32_t size_no_padding)
|
||||
: Base(source, name, members, align, size, size_no_padding), declaration_(declaration) {}
|
||||
: Base(source, name, members, align, size, size_no_padding), declaration_(declaration) {
|
||||
TINT_ASSERT(Semantic, declaration != nullptr);
|
||||
}
|
||||
|
||||
Struct::~Struct() = default;
|
||||
|
||||
|
@ -41,7 +43,9 @@ StructMember::StructMember(const ast::StructMember* declaration,
|
|||
uint32_t align,
|
||||
uint32_t size,
|
||||
const type::StructMemberAttributes& attributes)
|
||||
: Base(source, name, type, index, offset, align, size, attributes), declaration_(declaration) {}
|
||||
: Base(source, name, type, index, offset, align, size, attributes), declaration_(declaration) {
|
||||
TINT_ASSERT(Semantic, declaration != nullptr);
|
||||
}
|
||||
|
||||
StructMember::~StructMember() = default;
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ class StructMember;
|
|||
namespace tint::sem {
|
||||
|
||||
/// Struct holds the semantic information for structures.
|
||||
/// Unlike type::Struct, sem::Struct has an AST declaration node.
|
||||
class Struct final : public utils::Castable<Struct, type::Struct> {
|
||||
public:
|
||||
/// Constructor
|
||||
|
@ -47,8 +48,7 @@ class Struct final : public utils::Castable<Struct, type::Struct> {
|
|||
/// @param members the structure members
|
||||
/// @param align the byte alignment of the structure
|
||||
/// @param size the byte size of the structure
|
||||
/// @param size_no_padding size of the members without the end of structure
|
||||
/// alignment padding
|
||||
/// @param size_no_padding size of the members without the end of structure alignment padding
|
||||
Struct(const ast::Struct* declaration,
|
||||
tint::Source source,
|
||||
Symbol name,
|
||||
|
@ -73,6 +73,7 @@ class Struct final : public utils::Castable<Struct, type::Struct> {
|
|||
};
|
||||
|
||||
/// StructMember holds the semantic information for structure members.
|
||||
/// Unlike type::StructMember, sem::StructMember has an AST declaration node.
|
||||
class StructMember final : public utils::Castable<StructMember, type::StructMember> {
|
||||
public:
|
||||
/// Constructor
|
||||
|
|
|
@ -147,7 +147,7 @@ struct ArrayLengthFromUniform::State {
|
|||
const ast::Expression* total_size = total_storage_buffer_size;
|
||||
auto* storage_buffer_type = storage_buffer_sem->Type()->UnwrapRef();
|
||||
const type::Array* array_type = nullptr;
|
||||
if (auto* str = storage_buffer_type->As<sem::Struct>()) {
|
||||
if (auto* str = storage_buffer_type->As<type::Struct>()) {
|
||||
// The variable is a struct, so subtract the byte offset of the array
|
||||
// member.
|
||||
auto* array_member_sem = str->Members().Back();
|
||||
|
|
|
@ -204,7 +204,7 @@ Transform::ApplyResult CalculateArrayLength::Apply(const Program* src,
|
|||
|
||||
const type::Array* array_type = Switch(
|
||||
storage_buffer_type->StoreType(),
|
||||
[&](const sem::Struct* str) {
|
||||
[&](const type::Struct* str) {
|
||||
// The variable is a struct, so subtract the byte offset of
|
||||
// the array member.
|
||||
auto* array_member_sem = str->Members().Back();
|
||||
|
|
|
@ -371,7 +371,7 @@ struct CanonicalizeEntryPointIO::State {
|
|||
// list to pass them through to the inner function.
|
||||
utils::Vector<const ast::Expression*, 8> inner_struct_values;
|
||||
for (auto* member : str->Members()) {
|
||||
if (TINT_UNLIKELY(member->Type()->Is<sem::Struct>())) {
|
||||
if (TINT_UNLIKELY(member->Type()->Is<type::Struct>())) {
|
||||
TINT_ICE(Transform, ctx.dst->Diagnostics()) << "nested IO struct";
|
||||
continue;
|
||||
}
|
||||
|
@ -400,7 +400,7 @@ struct CanonicalizeEntryPointIO::State {
|
|||
bool do_interpolate = func_ast->PipelineStage() != ast::PipelineStage::kFragment;
|
||||
if (auto* str = inner_ret_type->As<sem::Struct>()) {
|
||||
for (auto* member : str->Members()) {
|
||||
if (TINT_UNLIKELY(member->Type()->Is<sem::Struct>())) {
|
||||
if (TINT_UNLIKELY(member->Type()->Is<type::Struct>())) {
|
||||
TINT_ICE(Transform, ctx.dst->Diagnostics()) << "nested IO struct";
|
||||
continue;
|
||||
}
|
||||
|
@ -639,7 +639,7 @@ struct CanonicalizeEntryPointIO::State {
|
|||
// aggregated into a single structure.
|
||||
if (!func_sem->Parameters().IsEmpty()) {
|
||||
for (auto* param : func_sem->Parameters()) {
|
||||
if (param->Type()->Is<sem::Struct>()) {
|
||||
if (param->Type()->Is<type::Struct>()) {
|
||||
ProcessStructParameter(param);
|
||||
} else {
|
||||
ProcessNonStructParameter(param);
|
||||
|
|
|
@ -522,7 +522,7 @@ struct DecomposeMemoryAccess::State {
|
|||
auto* offset = b.Add("offset", u32(i * mat_ty->ColumnStride()));
|
||||
values.Push(b.Call(load, offset));
|
||||
}
|
||||
} else if (auto* str = el_ty->As<sem::Struct>()) {
|
||||
} else if (auto* str = el_ty->As<type::Struct>()) {
|
||||
for (auto* member : str->Members()) {
|
||||
auto* offset = b.Add("offset", u32(member->Offset()));
|
||||
Symbol load = LoadFunc(member->Type()->UnwrapRef(), address_space, buffer);
|
||||
|
@ -607,7 +607,7 @@ struct DecomposeMemoryAccess::State {
|
|||
}
|
||||
return stmts;
|
||||
},
|
||||
[&](const sem::Struct* str) {
|
||||
[&](const type::Struct* str) {
|
||||
utils::Vector<const ast::Statement*, 8> stmts;
|
||||
for (auto* member : str->Members()) {
|
||||
auto* offset = b.Add("offset", u32(member->Offset()));
|
||||
|
@ -660,8 +660,8 @@ struct DecomposeMemoryAccess::State {
|
|||
|
||||
// For intrinsics that return a struct, there is no AST node for it, so create one now.
|
||||
if (intrinsic->Type() == builtin::Function::kAtomicCompareExchangeWeak) {
|
||||
auto* str = intrinsic->ReturnType()->As<sem::Struct>();
|
||||
TINT_ASSERT(Transform, str && str->Declaration() == nullptr);
|
||||
auto* str = intrinsic->ReturnType()->As<type::Struct>();
|
||||
TINT_ASSERT(Transform, str);
|
||||
|
||||
utils::Vector<const ast::StructMember*, 8> ast_members;
|
||||
ast_members.Reserve(str->Members().Length());
|
||||
|
@ -869,7 +869,7 @@ Transform::ApplyResult DecomposeMemoryAccess::Apply(const Program* src,
|
|||
}
|
||||
} else {
|
||||
if (auto access = state.TakeAccess(accessor->object)) {
|
||||
auto* str_ty = access.type->As<sem::Struct>();
|
||||
auto* str_ty = access.type->As<type::Struct>();
|
||||
auto* member = str_ty->FindMember(accessor->member->symbol);
|
||||
auto offset = member->Offset();
|
||||
state.AddAccess(accessor, {
|
||||
|
|
|
@ -70,7 +70,7 @@ Transform::ApplyResult DecomposeStridedMatrix::Apply(const Program* src,
|
|||
// Scan the program for all storage and uniform structure matrix members with
|
||||
// a custom stride attribute. Replace these matrices with an equivalent array,
|
||||
// and populate the `decomposed` map with the members that have been replaced.
|
||||
utils::Hashmap<const ast::StructMember*, MatrixInfo, 8> decomposed;
|
||||
utils::Hashmap<const type::StructMember*, MatrixInfo, 8> decomposed;
|
||||
for (auto* node : src->ASTNodes().Objects()) {
|
||||
if (auto* str = node->As<ast::Struct>()) {
|
||||
auto* str_ty = src->Sem().Get(str);
|
||||
|
@ -98,7 +98,7 @@ Transform::ApplyResult DecomposeStridedMatrix::Apply(const Program* src,
|
|||
auto* replacement =
|
||||
b.Member(member->Offset(), ctx.Clone(member->Name()), info.array(ctx.dst));
|
||||
ctx.Replace(member->Declaration(), replacement);
|
||||
decomposed.Add(member->Declaration(), info);
|
||||
decomposed.Add(member, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ Transform::ApplyResult DecomposeStridedMatrix::Apply(const Program* src,
|
|||
ctx.ReplaceAll(
|
||||
[&](const ast::IndexAccessorExpression* expr) -> const ast::IndexAccessorExpression* {
|
||||
if (auto* access = src->Sem().Get<sem::StructMemberAccess>(expr->object)) {
|
||||
if (decomposed.Contains(access->Member()->Declaration())) {
|
||||
if (decomposed.Contains(access->Member())) {
|
||||
auto* obj = ctx.CloneWithoutTransform(expr->object);
|
||||
auto* idx = ctx.Clone(expr->index);
|
||||
return b.IndexAccessor(obj, idx);
|
||||
|
@ -131,7 +131,7 @@ Transform::ApplyResult DecomposeStridedMatrix::Apply(const Program* src,
|
|||
std::unordered_map<MatrixInfo, Symbol, MatrixInfo::Hasher> mat_to_arr;
|
||||
ctx.ReplaceAll([&](const ast::AssignmentStatement* stmt) -> const ast::Statement* {
|
||||
if (auto* access = src->Sem().Get<sem::StructMemberAccess>(stmt->lhs)) {
|
||||
if (auto info = decomposed.Find(access->Member()->Declaration())) {
|
||||
if (auto info = decomposed.Find(access->Member())) {
|
||||
auto fn = utils::GetOrCreate(mat_to_arr, *info, [&] {
|
||||
auto name =
|
||||
b.Symbols().New("mat" + std::to_string(info->matrix->columns()) + "x" +
|
||||
|
@ -170,7 +170,7 @@ Transform::ApplyResult DecomposeStridedMatrix::Apply(const Program* src,
|
|||
std::unordered_map<MatrixInfo, Symbol, MatrixInfo::Hasher> arr_to_mat;
|
||||
ctx.ReplaceAll([&](const ast::MemberAccessorExpression* expr) -> const ast::Expression* {
|
||||
if (auto* access = src->Sem().Get(expr)->UnwrapLoad()->As<sem::StructMemberAccess>()) {
|
||||
if (auto info = decomposed.Find(access->Member()->Declaration())) {
|
||||
if (auto info = decomposed.Find(access->Member())) {
|
||||
auto fn = utils::GetOrCreate(arr_to_mat, *info, [&] {
|
||||
auto name =
|
||||
b.Symbols().New("arr_to_mat" + std::to_string(info->matrix->columns()) +
|
||||
|
|
|
@ -186,7 +186,7 @@ Transform::ApplyResult DemoteToHelper::Apply(const Program* src, const DataMap&,
|
|||
// original member values over to it.
|
||||
|
||||
// Declare a struct to hold the result values.
|
||||
auto* result_struct = sem_call->Type()->As<sem::Struct>();
|
||||
auto* result_struct = sem_call->Type()->As<type::Struct>();
|
||||
auto* atomic_ty = result_struct->Members()[0]->Type();
|
||||
result_ty = b.ty(
|
||||
utils::GetOrCreate(atomic_cmpxchg_result_types, atomic_ty, [&]() {
|
||||
|
|
|
@ -79,7 +79,7 @@ Transform::ApplyResult FirstIndexOffset::Apply(const Program* src,
|
|||
|
||||
// Map of builtin usages
|
||||
std::unordered_map<const sem::Variable*, const char*> builtin_vars;
|
||||
std::unordered_map<const sem::StructMember*, const char*> builtin_members;
|
||||
std::unordered_map<const type::StructMember*, const char*> builtin_members;
|
||||
|
||||
bool has_vertex_or_instance_index = false;
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ struct LocalizeStructArrayAssignment::State {
|
|||
continue;
|
||||
}
|
||||
auto og = GetOriginatingTypeAndAddressSpace(assign_stmt);
|
||||
if (!(og.first->Is<sem::Struct>() &&
|
||||
if (!(og.first->Is<type::Struct>() &&
|
||||
(og.second == builtin::AddressSpace::kFunction ||
|
||||
og.second == builtin::AddressSpace::kPrivate))) {
|
||||
continue;
|
||||
|
|
|
@ -54,7 +54,7 @@ bool ContainsMatrix(const type::Type* type) {
|
|||
return true;
|
||||
} else if (auto* ary = type->As<type::Array>()) {
|
||||
return ContainsMatrix(ary->ElemType());
|
||||
} else if (auto* str = type->As<sem::Struct>()) {
|
||||
} else if (auto* str = type->As<type::Struct>()) {
|
||||
for (auto* member : str->Members()) {
|
||||
if (ContainsMatrix(member->Type())) {
|
||||
return true;
|
||||
|
@ -85,11 +85,6 @@ struct ModuleScopeVarToEntryPointParam::State {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!str->Declaration()) {
|
||||
// The struct is a built-in structure that we do not need to declare.
|
||||
return;
|
||||
}
|
||||
|
||||
// Recurse into members.
|
||||
for (auto* member : str->Members()) {
|
||||
CloneStructTypes(member->Type());
|
||||
|
|
|
@ -99,10 +99,7 @@ Transform::ApplyResult NumWorkgroupsFromUniform::Apply(const Program* src,
|
|||
}
|
||||
|
||||
for (auto* member : str->Members()) {
|
||||
auto* builtin =
|
||||
ast::GetAttribute<ast::BuiltinAttribute>(member->Declaration()->attributes);
|
||||
if (!builtin ||
|
||||
src->Sem().Get(builtin)->Value() != builtin::BuiltinValue::kNumWorkgroups) {
|
||||
if (member->Attributes().builtin != builtin::BuiltinValue::kNumWorkgroups) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ struct PackedVec3::State {
|
|||
}
|
||||
return {};
|
||||
},
|
||||
[&](const sem::Struct* str) -> ast::Type {
|
||||
[&](const type::Struct* str) -> ast::Type {
|
||||
if (ContainsVec3(str)) {
|
||||
auto name = rewritten_structs.GetOrCreate(str, [&]() {
|
||||
utils::Vector<const ast::StructMember*, 4> members;
|
||||
|
@ -170,12 +170,14 @@ struct PackedVec3::State {
|
|||
// Copy the member attributes.
|
||||
bool needs_align = true;
|
||||
utils::Vector<const ast::Attribute*, 4> attributes;
|
||||
for (auto* attr : member->Declaration()->attributes) {
|
||||
if (attr->IsAnyOf<ast::StructMemberAlignAttribute,
|
||||
ast::StructMemberOffsetAttribute>()) {
|
||||
needs_align = false;
|
||||
if (auto* sem_mem = member->As<sem::StructMember>()) {
|
||||
for (auto* attr : sem_mem->Declaration()->attributes) {
|
||||
if (attr->IsAnyOf<ast::StructMemberAlignAttribute,
|
||||
ast::StructMemberOffsetAttribute>()) {
|
||||
needs_align = false;
|
||||
}
|
||||
attributes.Push(ctx.Clone(attr));
|
||||
}
|
||||
attributes.Push(ctx.Clone(attr));
|
||||
}
|
||||
// If the alignment wasn't already specified, add an attribute to
|
||||
// make sure that we don't alter the alignment when using the packed
|
||||
|
@ -187,12 +189,17 @@ struct PackedVec3::State {
|
|||
std::move(attributes)));
|
||||
} else {
|
||||
// No vec3s, just clone the member as is.
|
||||
members.Push(ctx.Clone(member->Declaration()));
|
||||
if (auto* sem_mem = member->As<sem::StructMember>()) {
|
||||
members.Push(ctx.Clone(sem_mem->Declaration()));
|
||||
} else {
|
||||
members.Push(b.Member(ctx.Clone(member->Name()), new_type,
|
||||
utils::Empty));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create the new structure.
|
||||
auto struct_name = b.Symbols().New(str->Declaration()->name->symbol.Name() +
|
||||
"_tint_packed_vec3");
|
||||
auto struct_name =
|
||||
b.Symbols().New(str->Name().Name() + "_tint_packed_vec3");
|
||||
b.Structure(struct_name, std::move(members));
|
||||
return struct_name;
|
||||
});
|
||||
|
@ -246,7 +253,7 @@ struct PackedVec3::State {
|
|||
[&](const type::Matrix* mat) {
|
||||
copy_array_elements(mat->columns(), mat->ColumnType());
|
||||
},
|
||||
[&](const sem::Struct* str) {
|
||||
[&](const type::Struct* str) {
|
||||
// Copy the struct members over one at a time, packing/unpacking as necessary.
|
||||
for (auto* member : str->Members()) {
|
||||
const ast::Expression* element =
|
||||
|
|
|
@ -4328,7 +4328,7 @@ fn main() {
|
|||
// The first member should have an alignment of 16 bytes, a size of 12 bytes, and the second
|
||||
// member should have an offset of 12 bytes.
|
||||
auto* sem_str = got.program.Sem().Get(vars[0]);
|
||||
auto* str_ty = sem_str->Type()->UnwrapRef()->As<sem::Struct>();
|
||||
auto* str_ty = sem_str->Type()->UnwrapRef()->As<type::Struct>();
|
||||
ASSERT_NE(str_ty, nullptr);
|
||||
ASSERT_EQ(str_ty->Members().Length(), 2u);
|
||||
EXPECT_EQ(str_ty->Members()[0]->Align(), 16u);
|
||||
|
|
|
@ -84,7 +84,7 @@ Transform::ApplyResult PadStructs::Apply(const Program* src, const DataMap&, Dat
|
|||
new_members.Push(b.Member(name, type));
|
||||
|
||||
uint32_t size = ty->Size();
|
||||
if (ty->Is<sem::Struct>() && str->UsedAs(builtin::AddressSpace::kUniform)) {
|
||||
if (ty->Is<type::Struct>() && str->UsedAs(builtin::AddressSpace::kUniform)) {
|
||||
// std140 structs should be padded out to 16 bytes.
|
||||
size = utils::RoundUp(16u, size);
|
||||
} else if (auto* array_ty = ty->As<type::Array>()) {
|
||||
|
|
|
@ -160,12 +160,12 @@ struct PreservePadding::State {
|
|||
return body;
|
||||
});
|
||||
},
|
||||
[&](const sem::Struct* str) {
|
||||
[&](const type::Struct* str) {
|
||||
// Call a helper function that assigns each member separately.
|
||||
return call_helper([&]() {
|
||||
utils::Vector<const ast::Statement*, 8> body;
|
||||
for (auto member : str->Members()) {
|
||||
auto name = member->Declaration()->name->symbol.Name();
|
||||
auto name = member->Name().Name();
|
||||
body.Push(MakeAssignment(member->Type(),
|
||||
b.MemberAccessor(b.Deref(kDestParamName), name),
|
||||
b.MemberAccessor(kValueParamName, name)));
|
||||
|
@ -199,7 +199,7 @@ struct PreservePadding::State {
|
|||
}
|
||||
return HasPadding(col_ty);
|
||||
},
|
||||
[&](const sem::Struct* str) {
|
||||
[&](const type::Struct* str) {
|
||||
uint32_t current_offset = 0;
|
||||
for (auto* member : str->Members()) {
|
||||
if (member->Offset() > current_offset) {
|
||||
|
|
|
@ -1281,8 +1281,8 @@ Transform::ApplyResult Renamer::Apply(const Program* src,
|
|||
if (sem->Is<sem::Swizzle>()) {
|
||||
preserved_identifiers.Add(accessor->member);
|
||||
} else if (auto* str_expr = src->Sem().GetVal(accessor->object)) {
|
||||
if (auto* ty = str_expr->Type()->UnwrapRef()->As<sem::Struct>()) {
|
||||
if (ty->Declaration() == nullptr) { // Builtin structure
|
||||
if (auto* ty = str_expr->Type()->UnwrapRef()->As<type::Struct>()) {
|
||||
if (!ty->Is<sem::Struct>()) { // Builtin structure
|
||||
preserved_identifiers.Add(accessor->member);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ struct SpirvAtomic::State {
|
|||
ProgramBuilder b;
|
||||
/// The clone context
|
||||
CloneContext ctx = {&b, src, /* auto_clone_symbols */ true};
|
||||
std::unordered_map<const ast::Struct*, ForkedStruct> forked_structs;
|
||||
std::unordered_map<const type::Struct*, ForkedStruct> forked_structs;
|
||||
std::unordered_set<const sem::Variable*> atomic_variables;
|
||||
utils::UniqueVector<const sem::ValueExpression*, 8> atomic_expressions;
|
||||
|
||||
|
@ -123,7 +123,8 @@ struct SpirvAtomic::State {
|
|||
if (!forked_structs.empty()) {
|
||||
ctx.ReplaceAll([&](const ast::Struct* str) {
|
||||
// Is `str` a structure we need to fork?
|
||||
if (auto it = forked_structs.find(str); it != forked_structs.end()) {
|
||||
auto* str_ty = ctx.src->Sem().Get(str);
|
||||
if (auto it = forked_structs.find(str_ty); it != forked_structs.end()) {
|
||||
const auto& forked = it->second;
|
||||
|
||||
// Re-create the structure swapping in the atomic-flavoured members
|
||||
|
@ -154,10 +155,10 @@ struct SpirvAtomic::State {
|
|||
}
|
||||
|
||||
private:
|
||||
ForkedStruct& Fork(const ast::Struct* str) {
|
||||
ForkedStruct& Fork(const type::Struct* str) {
|
||||
auto& forked = forked_structs[str];
|
||||
if (!forked.name.IsValid()) {
|
||||
forked.name = b.Symbols().New(str->name->symbol.Name() + "_atomic");
|
||||
forked.name = b.Symbols().New(str->Name().Name() + "_atomic");
|
||||
}
|
||||
return forked;
|
||||
}
|
||||
|
@ -179,7 +180,7 @@ struct SpirvAtomic::State {
|
|||
// Fork the struct (the first time) and mark member(s) that need to be made
|
||||
// atomic.
|
||||
auto* member = access->Member();
|
||||
Fork(member->Struct()->Declaration()).atomic_members.emplace(member->Index());
|
||||
Fork(member->Struct()).atomic_members.emplace(member->Index());
|
||||
atomic_expressions.Add(access->Object());
|
||||
},
|
||||
[&](const sem::IndexAccessorExpression* index) {
|
||||
|
@ -198,7 +199,7 @@ struct SpirvAtomic::State {
|
|||
ty, //
|
||||
[&](const type::I32*) { return b.ty.atomic(CreateASTTypeFor(ctx, ty)); },
|
||||
[&](const type::U32*) { return b.ty.atomic(CreateASTTypeFor(ctx, ty)); },
|
||||
[&](const sem::Struct* str) { return b.ty(Fork(str->Declaration()).name); },
|
||||
[&](const type::Struct* str) { return b.ty(Fork(str).name); },
|
||||
[&](const type::Array* arr) {
|
||||
if (arr->Count()->Is<type::RuntimeArrayCount>()) {
|
||||
return b.ty.array(AtomicTypeFor(arr->ElemType()));
|
||||
|
@ -231,7 +232,7 @@ struct SpirvAtomic::State {
|
|||
(atomic_variables.count(e->RootIdentifier()) != 0)) {
|
||||
// If it's a struct member, make sure it's one we marked as atomic
|
||||
if (auto* ma = e->As<sem::StructMemberAccess>()) {
|
||||
auto it = forked_structs.find(ma->Member()->Struct()->Declaration());
|
||||
auto it = forked_structs.find(ma->Member()->Struct());
|
||||
if (it != forked_structs.end()) {
|
||||
auto& forked = it->second;
|
||||
return forked.atomic_members.count(ma->Member()->Index()) != 0;
|
||||
|
|
|
@ -144,7 +144,7 @@ struct Std140::State {
|
|||
|
||||
// Scan structures for members that need forking
|
||||
for (auto* ty : src->Types()) {
|
||||
if (auto* str = ty->As<sem::Struct>()) {
|
||||
if (auto* str = ty->As<type::Struct>()) {
|
||||
if (str->UsedAs(builtin::AddressSpace::kUniform)) {
|
||||
for (auto* member : str->Members()) {
|
||||
if (needs_fork(member->Type())) {
|
||||
|
@ -226,11 +226,11 @@ struct Std140::State {
|
|||
utils::Hashset<const sem::Variable*, 8> std140_uniforms;
|
||||
|
||||
// Map of original structure to 'std140' forked structure
|
||||
utils::Hashmap<const sem::Struct*, Symbol, 8> std140_structs;
|
||||
utils::Hashmap<const type::Struct*, Symbol, 8> std140_structs;
|
||||
|
||||
// Map of structure member in src of a matrix type, to list of decomposed column
|
||||
// members in ctx.dst.
|
||||
utils::Hashmap<const sem::StructMember*, utils::Vector<const ast::StructMember*, 4>, 8>
|
||||
utils::Hashmap<const type::StructMember*, utils::Vector<const ast::StructMember*, 4>, 8>
|
||||
std140_mat_members;
|
||||
|
||||
/// Describes a matrix that has been forked to a std140-structure holding the decomposed column
|
||||
|
@ -403,7 +403,7 @@ struct Std140::State {
|
|||
ast::Type Std140Type(const type::Type* ty) {
|
||||
return Switch(
|
||||
ty, //
|
||||
[&](const sem::Struct* str) {
|
||||
[&](const type::Struct* str) {
|
||||
if (auto std140 = std140_structs.Find(str)) {
|
||||
return b.ty(*std140);
|
||||
}
|
||||
|
@ -631,7 +631,7 @@ struct Std140::State {
|
|||
const std::string ConvertSuffix(const type::Type* ty) {
|
||||
return Switch(
|
||||
ty, //
|
||||
[&](const sem::Struct* str) { return str->Name().Name(); },
|
||||
[&](const type::Struct* str) { return str->Name().Name(); },
|
||||
[&](const type::Array* arr) {
|
||||
auto count = arr->ConstantCount();
|
||||
if (TINT_UNLIKELY(!count)) {
|
||||
|
@ -694,7 +694,7 @@ struct Std140::State {
|
|||
|
||||
Switch(
|
||||
ty, //
|
||||
[&](const sem::Struct* str) {
|
||||
[&](const type::Struct* str) {
|
||||
// Convert each of the structure members using either a converter function
|
||||
// call, or by reassembling a std140 matrix from column vector members.
|
||||
utils::Vector<const ast::Expression*, 8> args;
|
||||
|
@ -832,7 +832,7 @@ struct Std140::State {
|
|||
// As this is accessing only part of the matrix, we just need to pick the right column
|
||||
// vector member.
|
||||
auto column_idx = std::get<u32>(chain.indices[std140_mat_idx + 1]);
|
||||
if (auto* str = tint::As<sem::Struct>(ty)) {
|
||||
if (auto* str = tint::As<type::Struct>(ty)) {
|
||||
// Structure member matrix. The columns are decomposed into the structure.
|
||||
auto mat_member_idx = std::get<u32>(chain.indices[std140_mat_idx]);
|
||||
auto* mat_member = str->Members()[mat_member_idx];
|
||||
|
@ -913,7 +913,7 @@ struct Std140::State {
|
|||
}
|
||||
}
|
||||
|
||||
if (auto* str = tint::As<sem::Struct>(ty)) {
|
||||
if (auto* str = tint::As<type::Struct>(ty)) {
|
||||
// Structure member matrix. The columns are decomposed into the structure.
|
||||
auto mat_member_idx = std::get<u32>(chain.indices[std140_mat_idx]);
|
||||
auto* mat_member = str->Members()[mat_member_idx];
|
||||
|
@ -1012,7 +1012,7 @@ struct Std140::State {
|
|||
stmts.Push(b.Decl(let));
|
||||
|
||||
utils::Vector<const ast::MemberAccessorExpression*, 4> columns;
|
||||
if (auto* str = tint::As<sem::Struct>(ty)) {
|
||||
if (auto* str = tint::As<type::Struct>(ty)) {
|
||||
// Structure member matrix. The columns are decomposed into the structure.
|
||||
auto mat_member_idx = std::get<u32>(chain.indices[std140_mat_idx]);
|
||||
auto* mat_member = str->Members()[mat_member_idx];
|
||||
|
@ -1133,7 +1133,7 @@ struct Std140::State {
|
|||
auto idx = std::get<u32>(access);
|
||||
return Switch(
|
||||
ty, //
|
||||
[&](const sem::Struct* str) -> ExprTypeName {
|
||||
[&](const type::Struct* str) -> ExprTypeName {
|
||||
auto* member = str->Members()[idx];
|
||||
auto member_name = member->Name().Name();
|
||||
auto* expr = b.MemberAccessor(lhs, member_name);
|
||||
|
|
|
@ -143,7 +143,7 @@ ast::Type Transform::CreateASTTypeFor(CloneContext& ctx, const type::Type* ty) {
|
|||
}
|
||||
return ctx.dst->ty.array(el, u32(count.value()), std::move(attrs));
|
||||
}
|
||||
if (auto* s = ty->As<sem::Struct>()) {
|
||||
if (auto* s = ty->As<type::Struct>()) {
|
||||
return ctx.dst->ty(ctx.Clone(s->Name()));
|
||||
}
|
||||
if (auto* s = ty->As<type::Reference>()) {
|
||||
|
|
|
@ -168,19 +168,16 @@ struct ZeroInitWorkgroupMemory::State {
|
|||
}
|
||||
}
|
||||
|
||||
if (auto* str = sem.Get(param)->Type()->As<sem::Struct>()) {
|
||||
if (auto* str = sem.Get(param)->Type()->As<type::Struct>()) {
|
||||
for (auto* member : str->Members()) {
|
||||
if (auto* builtin_attr = ast::GetAttribute<ast::BuiltinAttribute>(
|
||||
member->Declaration()->attributes)) {
|
||||
auto builtin = sem.Get(builtin_attr)->Value();
|
||||
if (builtin == builtin::BuiltinValue::kLocalInvocationIndex) {
|
||||
local_index = [=] {
|
||||
auto* param_expr = b.Expr(ctx.Clone(param->name->symbol));
|
||||
auto* member_name = ctx.Clone(member->Declaration()->name);
|
||||
return b.MemberAccessor(param_expr, member_name);
|
||||
};
|
||||
break;
|
||||
}
|
||||
if (member->Attributes().builtin ==
|
||||
builtin::BuiltinValue::kLocalInvocationIndex) {
|
||||
local_index = [=] {
|
||||
auto* param_expr = b.Expr(ctx.Clone(param->name->symbol));
|
||||
auto member_name = ctx.Clone(member->Name());
|
||||
return b.MemberAccessor(param_expr, member_name);
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -318,9 +315,9 @@ struct ZeroInitWorkgroupMemory::State {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (auto* str = ty->As<sem::Struct>()) {
|
||||
if (auto* str = ty->As<type::Struct>()) {
|
||||
for (auto* member : str->Members()) {
|
||||
auto name = ctx.Clone(member->Declaration()->name->symbol);
|
||||
auto name = ctx.Clone(member->Name());
|
||||
auto get_member = [&](uint32_t num_values) {
|
||||
auto s = get_expr(num_values);
|
||||
if (!s) {
|
||||
|
@ -444,7 +441,7 @@ struct ZeroInitWorkgroupMemory::State {
|
|||
if (ty->Is<type::Atomic>()) {
|
||||
return false;
|
||||
}
|
||||
if (auto* str = ty->As<sem::Struct>()) {
|
||||
if (auto* str = ty->As<type::Struct>()) {
|
||||
for (auto* member : str->Members()) {
|
||||
if (!CanTriviallyZero(member->Type())) {
|
||||
return false;
|
||||
|
|
|
@ -814,7 +814,7 @@ void GeneratorImpl::EmitWorkgroupAtomicCall(utils::StringStream& out,
|
|||
return;
|
||||
}
|
||||
case builtin::Function::kAtomicCompareExchangeWeak: {
|
||||
EmitStructType(&helpers_, builtin->ReturnType()->As<sem::Struct>());
|
||||
EmitStructType(&helpers_, builtin->ReturnType()->As<type::Struct>());
|
||||
|
||||
auto* dest = expr->args[0];
|
||||
auto* compare_value = expr->args[1];
|
||||
|
@ -1043,7 +1043,7 @@ void GeneratorImpl::EmitModfCall(utils::StringStream& out,
|
|||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
// Emit the builtin return type unique to this overload. This does not
|
||||
// exist in the AST, so it will not be generated in Generate().
|
||||
EmitStructType(&helpers_, builtin->ReturnType()->As<sem::Struct>());
|
||||
EmitStructType(&helpers_, builtin->ReturnType()->As<type::Struct>());
|
||||
|
||||
{
|
||||
auto l = line(b);
|
||||
|
@ -1064,7 +1064,7 @@ void GeneratorImpl::EmitFrexpCall(utils::StringStream& out,
|
|||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
// Emit the builtin return type unique to this overload. This does not
|
||||
// exist in the AST, so it will not be generated in Generate().
|
||||
EmitStructType(&helpers_, builtin->ReturnType()->As<sem::Struct>());
|
||||
EmitStructType(&helpers_, builtin->ReturnType()->As<type::Struct>());
|
||||
|
||||
{
|
||||
auto l = line(b);
|
||||
|
@ -1769,7 +1769,7 @@ void GeneratorImpl::EmitGlobalVariable(const ast::Variable* global) {
|
|||
|
||||
void GeneratorImpl::EmitUniformVariable(const ast::Var* var, const sem::Variable* sem) {
|
||||
auto* type = sem->Type()->UnwrapRef();
|
||||
auto* str = type->As<sem::Struct>();
|
||||
auto* str = type->As<type::Struct>();
|
||||
if (TINT_UNLIKELY(!str)) {
|
||||
TINT_ICE(Writer, builder_.Diagnostics()) << "storage variable must be of struct type";
|
||||
return;
|
||||
|
@ -1788,7 +1788,7 @@ void GeneratorImpl::EmitUniformVariable(const ast::Var* var, const sem::Variable
|
|||
|
||||
void GeneratorImpl::EmitStorageVariable(const ast::Var* var, const sem::Variable* sem) {
|
||||
auto* type = sem->Type()->UnwrapRef();
|
||||
auto* str = type->As<sem::Struct>();
|
||||
auto* str = type->As<type::Struct>();
|
||||
if (TINT_UNLIKELY(!str)) {
|
||||
TINT_ICE(Writer, builder_.Diagnostics()) << "storage variable must be of struct type";
|
||||
return;
|
||||
|
@ -2040,7 +2040,7 @@ void GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) {
|
|||
for (auto* var : func->params) {
|
||||
auto* sem = builder_.Sem().Get(var);
|
||||
auto* type = sem->Type();
|
||||
if (TINT_UNLIKELY(!type->Is<sem::Struct>())) {
|
||||
if (TINT_UNLIKELY(!type->Is<type::Struct>())) {
|
||||
// ICE likely indicates that the CanonicalizeEntryPointIO transform was
|
||||
// not run, or a builtin parameter was added after it was run.
|
||||
TINT_ICE(Writer, diagnostics_) << "Unsupported non-struct entry point parameter";
|
||||
|
@ -2132,7 +2132,7 @@ void GeneratorImpl::EmitConstant(utils::StringStream& out, const constant::Value
|
|||
EmitConstant(out, constant->Index(i));
|
||||
}
|
||||
},
|
||||
[&](const sem::Struct* s) {
|
||||
[&](const type::Struct* s) {
|
||||
EmitStructType(&helpers_, s);
|
||||
|
||||
out << StructName(s);
|
||||
|
@ -2210,7 +2210,7 @@ void GeneratorImpl::EmitZeroValue(utils::StringStream& out, const type::Type* ty
|
|||
}
|
||||
EmitZeroValue(out, mat->type());
|
||||
}
|
||||
} else if (auto* str = type->As<sem::Struct>()) {
|
||||
} else if (auto* str = type->As<type::Struct>()) {
|
||||
EmitType(out, type, builtin::AddressSpace::kUndefined, builtin::Access::kUndefined, "");
|
||||
bool first = true;
|
||||
ScopedParen sp(out);
|
||||
|
@ -2568,7 +2568,7 @@ void GeneratorImpl::EmitType(utils::StringStream& out,
|
|||
TINT_ICE(Writer, diagnostics_) << "Attempting to emit pointer type. These should have been "
|
||||
"removed with the SimplifyPointers transform";
|
||||
} else if (type->Is<type::Sampler>()) {
|
||||
} else if (auto* str = type->As<sem::Struct>()) {
|
||||
} else if (auto* str = type->As<type::Struct>()) {
|
||||
out << StructName(str);
|
||||
} else if (auto* tex = type->As<type::Texture>()) {
|
||||
if (TINT_UNLIKELY(tex->Is<type::ExternalTexture>())) {
|
||||
|
@ -2669,7 +2669,7 @@ void GeneratorImpl::EmitTypeAndName(utils::StringStream& out,
|
|||
}
|
||||
}
|
||||
|
||||
void GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) {
|
||||
void GeneratorImpl::EmitStructType(TextBuffer* b, const type::Struct* str) {
|
||||
auto it = emitted_structs_.emplace(str);
|
||||
if (!it.second) {
|
||||
return;
|
||||
|
@ -2682,7 +2682,7 @@ void GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) {
|
|||
line(b);
|
||||
}
|
||||
|
||||
void GeneratorImpl::EmitStructMembers(TextBuffer* b, const sem::Struct* str) {
|
||||
void GeneratorImpl::EmitStructMembers(TextBuffer* b, const type::Struct* str) {
|
||||
ScopedIndent si(b);
|
||||
for (auto* mem : str->Members()) {
|
||||
auto name = mem->Name().Name();
|
||||
|
|
|
@ -383,11 +383,11 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// this function will simply return `true` without emitting anything.
|
||||
/// @param buffer the text buffer that the type declaration will be written to
|
||||
/// @param ty the struct to generate
|
||||
void EmitStructType(TextBuffer* buffer, const sem::Struct* ty);
|
||||
void EmitStructType(TextBuffer* buffer, const type::Struct* ty);
|
||||
/// Handles generating the members of a structure
|
||||
/// @param buffer the text buffer that the struct members will be written to
|
||||
/// @param ty the struct to generate
|
||||
void EmitStructMembers(TextBuffer* buffer, const sem::Struct* ty);
|
||||
void EmitStructMembers(TextBuffer* buffer, const type::Struct* ty);
|
||||
/// Handles a unary op expression
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the expression to emit
|
||||
|
@ -460,7 +460,7 @@ class GeneratorImpl : public TextGenerator {
|
|||
std::unordered_map<const type::Vector*, std::string> dynamic_vector_write_;
|
||||
std::unordered_map<const type::Vector*, std::string> int_dot_funcs_;
|
||||
std::unordered_map<BinaryOperandType, std::string> float_modulo_funcs_;
|
||||
std::unordered_set<const sem::Struct*> emitted_structs_;
|
||||
std::unordered_set<const type::Struct*> emitted_structs_;
|
||||
bool requires_oes_sample_variables_ = false;
|
||||
bool requires_default_precision_qualifier_ = false;
|
||||
bool requires_f16_extension_ = false;
|
||||
|
|
|
@ -170,8 +170,8 @@ TEST_F(GlslGeneratorImplTest_Type, EmitType_StructDecl) {
|
|||
GeneratorImpl& gen = Build();
|
||||
|
||||
TextGenerator::TextBuffer buf;
|
||||
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
|
||||
gen.EmitStructType(&buf, sem_s);
|
||||
auto* str = program->TypeOf(s)->As<type::Struct>();
|
||||
gen.EmitStructType(&buf, str);
|
||||
EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
|
||||
EXPECT_EQ(buf.String(), R"(struct S {
|
||||
int a;
|
||||
|
@ -190,9 +190,9 @@ TEST_F(GlslGeneratorImplTest_Type, EmitType_Struct) {
|
|||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
|
||||
auto* str = program->TypeOf(s)->As<type::Struct>();
|
||||
utils::StringStream out;
|
||||
gen.EmitType(out, sem_s, builtin::AddressSpace::kUndefined, builtin::Access::kReadWrite, "");
|
||||
gen.EmitType(out, str, builtin::AddressSpace::kUndefined, builtin::Access::kReadWrite, "");
|
||||
EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
|
||||
EXPECT_EQ(out.str(), "S");
|
||||
}
|
||||
|
@ -224,8 +224,8 @@ TEST_F(GlslGeneratorImplTest_Type, EmitType_Struct_WithOffsetAttributes) {
|
|||
GeneratorImpl& gen = Build();
|
||||
|
||||
TextGenerator::TextBuffer buf;
|
||||
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
|
||||
gen.EmitStructType(&buf, sem_s);
|
||||
auto* str = program->TypeOf(s)->As<type::Struct>();
|
||||
gen.EmitStructType(&buf, str);
|
||||
EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
|
||||
EXPECT_EQ(buf.String(), R"(struct S {
|
||||
int a;
|
||||
|
|
|
@ -1094,7 +1094,7 @@ bool GeneratorImpl::EmitValueConstructor(utils::StringStream& out,
|
|||
}
|
||||
}
|
||||
|
||||
bool brackets = type->IsAnyOf<type::Array, sem::Struct>();
|
||||
bool brackets = type->IsAnyOf<type::Array, type::Struct>();
|
||||
|
||||
// For single-value vector initializers, swizzle the scalar to the right
|
||||
// vector dimension using .x
|
||||
|
@ -1887,7 +1887,7 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(utils::StringStream& out,
|
|||
return true;
|
||||
}
|
||||
case builtin::Function::kAtomicCompareExchangeWeak: {
|
||||
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<sem::Struct>())) {
|
||||
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<type::Struct>())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2004,7 +2004,7 @@ bool GeneratorImpl::EmitModfCall(utils::StringStream& out,
|
|||
|
||||
// Emit the builtin return type unique to this overload. This does not
|
||||
// exist in the AST, so it will not be generated in Generate().
|
||||
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<sem::Struct>())) {
|
||||
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<type::Struct>())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2037,7 +2037,7 @@ bool GeneratorImpl::EmitFrexpCall(utils::StringStream& out,
|
|||
|
||||
// Emit the builtin return type unique to this overload. This does not
|
||||
// exist in the AST, so it will not be generated in Generate().
|
||||
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<sem::Struct>())) {
|
||||
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<type::Struct>())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3287,7 +3287,7 @@ bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) {
|
|||
for (auto* var : func->params) {
|
||||
auto* sem = builder_.Sem().Get(var);
|
||||
auto* type = sem->Type();
|
||||
if (TINT_UNLIKELY(!type->Is<sem::Struct>())) {
|
||||
if (TINT_UNLIKELY(!type->Is<type::Struct>())) {
|
||||
// ICE likely indicates that the CanonicalizeEntryPointIO transform was
|
||||
// not run, or a builtin parameter was added after it was run.
|
||||
TINT_ICE(Writer, diagnostics_) << "Unsupported non-struct entry point parameter";
|
||||
|
@ -3437,7 +3437,7 @@ bool GeneratorImpl::EmitConstant(utils::StringStream& out,
|
|||
|
||||
return true;
|
||||
},
|
||||
[&](const sem::Struct* s) {
|
||||
[&](const type::Struct* s) {
|
||||
if (!EmitStructType(&helpers_, s)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -3580,7 +3580,7 @@ bool GeneratorImpl::EmitValue(utils::StringStream& out, const type::Type* type,
|
|||
}
|
||||
return true;
|
||||
},
|
||||
[&](const sem::Struct*) {
|
||||
[&](const type::Struct*) {
|
||||
out << "(";
|
||||
TINT_DEFER(out << ")" << value);
|
||||
return EmitType(out, type, builtin::AddressSpace::kUndefined,
|
||||
|
@ -4077,7 +4077,7 @@ bool GeneratorImpl::EmitType(utils::StringStream& out,
|
|||
out << "State";
|
||||
return true;
|
||||
},
|
||||
[&](const sem::Struct* str) {
|
||||
[&](const type::Struct* str) {
|
||||
out << StructName(str);
|
||||
return true;
|
||||
},
|
||||
|
@ -4202,7 +4202,7 @@ bool GeneratorImpl::EmitTypeAndName(utils::StringStream& out,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) {
|
||||
bool GeneratorImpl::EmitStructType(TextBuffer* b, const type::Struct* str) {
|
||||
auto it = emitted_structs_.emplace(str);
|
||||
if (!it.second) {
|
||||
return true;
|
||||
|
|
|
@ -449,7 +449,7 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// @param buffer the text buffer that the type declaration will be written to
|
||||
/// @param ty the struct to generate
|
||||
/// @returns true if the struct is emitted
|
||||
bool EmitStructType(TextBuffer* buffer, const sem::Struct* ty);
|
||||
bool EmitStructType(TextBuffer* buffer, const type::Struct* ty);
|
||||
/// Handles a unary op expression
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the expression to emit
|
||||
|
@ -568,7 +568,7 @@ class GeneratorImpl : public TextGenerator {
|
|||
std::unordered_map<const type::Matrix*, std::string> dynamic_matrix_vector_write_;
|
||||
std::unordered_map<const type::Matrix*, std::string> dynamic_matrix_scalar_write_;
|
||||
std::unordered_map<const type::Type*, std::string> value_or_one_if_zero_;
|
||||
std::unordered_set<const sem::Struct*> emitted_structs_;
|
||||
std::unordered_set<const type::Struct*> emitted_structs_;
|
||||
};
|
||||
|
||||
} // namespace tint::writer::hlsl
|
||||
|
|
|
@ -171,8 +171,8 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_StructDecl) {
|
|||
GeneratorImpl& gen = Build();
|
||||
|
||||
TextGenerator::TextBuffer buf;
|
||||
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.Diagnostics();
|
||||
auto* str = program->TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
|
||||
EXPECT_EQ(buf.String(), R"(struct S {
|
||||
int a;
|
||||
float b;
|
||||
|
@ -203,10 +203,10 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct) {
|
|||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
|
||||
auto* str = program->TypeOf(s)->As<type::Struct>();
|
||||
utils::StringStream out;
|
||||
ASSERT_TRUE(gen.EmitType(out, sem_s, builtin::AddressSpace::kUndefined,
|
||||
builtin::Access::kReadWrite, ""))
|
||||
ASSERT_TRUE(
|
||||
gen.EmitType(out, str, builtin::AddressSpace::kUndefined, builtin::Access::kReadWrite, ""))
|
||||
<< gen.Diagnostics();
|
||||
EXPECT_EQ(out.str(), "S");
|
||||
}
|
||||
|
@ -238,8 +238,8 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_WithOffsetAttributes) {
|
|||
GeneratorImpl& gen = Build();
|
||||
|
||||
TextGenerator::TextBuffer buf;
|
||||
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.Diagnostics();
|
||||
auto* str = program->TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
|
||||
EXPECT_EQ(buf.String(), R"(struct S {
|
||||
int a;
|
||||
float b;
|
||||
|
|
|
@ -363,7 +363,7 @@ bool GeneratorImpl::Generate() {
|
|||
}
|
||||
|
||||
bool GeneratorImpl::EmitTypeDecl(const type::Type* ty) {
|
||||
if (auto* str = ty->As<sem::Struct>()) {
|
||||
if (auto* str = ty->As<type::Struct>()) {
|
||||
if (!EmitStructType(current_buffer_, str)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -826,7 +826,7 @@ bool GeneratorImpl::EmitTypeInitializer(utils::StringStream& out,
|
|||
terminator = "}";
|
||||
return true;
|
||||
},
|
||||
[&](const sem::Struct*) {
|
||||
[&](const type::Struct*) {
|
||||
out << "{";
|
||||
terminator = "}";
|
||||
return true;
|
||||
|
@ -848,10 +848,9 @@ bool GeneratorImpl::EmitTypeInitializer(utils::StringStream& out,
|
|||
out << ", ";
|
||||
}
|
||||
|
||||
if (auto* struct_ty = type->As<sem::Struct>()) {
|
||||
if (auto* struct_ty = type->As<type::Struct>()) {
|
||||
// Emit field designators for structures to account for padding members.
|
||||
auto* member = struct_ty->Members()[i]->Declaration();
|
||||
auto name = member->name->symbol.Name();
|
||||
auto name = struct_ty->Members()[i]->Name().Name();
|
||||
out << "." << name << "=";
|
||||
}
|
||||
|
||||
|
@ -922,11 +921,11 @@ bool GeneratorImpl::EmitAtomicCall(utils::StringStream& out,
|
|||
case builtin::Function::kAtomicCompareExchangeWeak: {
|
||||
auto* ptr_ty = TypeOf(expr->args[0])->UnwrapRef()->As<type::Pointer>();
|
||||
auto sc = ptr_ty->AddressSpace();
|
||||
auto* str = builtin->ReturnType()->As<sem::Struct>();
|
||||
auto* str = builtin->ReturnType()->As<type::Struct>();
|
||||
|
||||
auto func = utils::GetOrCreate(
|
||||
atomicCompareExchangeWeak_, ACEWKeyType{{sc, str}}, [&]() -> std::string {
|
||||
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<sem::Struct>())) {
|
||||
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<type::Struct>())) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
@ -937,7 +936,7 @@ bool GeneratorImpl::EmitAtomicCall(utils::StringStream& out,
|
|||
|
||||
{
|
||||
auto f = line(&buf);
|
||||
auto str_name = StructName(builtin->ReturnType()->As<sem::Struct>());
|
||||
auto str_name = StructName(builtin->ReturnType()->As<type::Struct>());
|
||||
f << str_name << " " << name << "(";
|
||||
if (!EmitTypeAndName(f, atomic_ty, "atomic")) {
|
||||
return "";
|
||||
|
@ -1361,11 +1360,11 @@ bool GeneratorImpl::EmitModfCall(utils::StringStream& out,
|
|||
|
||||
// Emit the builtin return type unique to this overload. This does not
|
||||
// exist in the AST, so it will not be generated in Generate().
|
||||
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<sem::Struct>())) {
|
||||
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<type::Struct>())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
line(b) << StructName(builtin->ReturnType()->As<sem::Struct>()) << " result;";
|
||||
line(b) << StructName(builtin->ReturnType()->As<type::Struct>()) << " result;";
|
||||
line(b) << "result.fract = modf(" << in << ", result.whole);";
|
||||
line(b) << "return result;";
|
||||
return true;
|
||||
|
@ -1387,11 +1386,11 @@ bool GeneratorImpl::EmitFrexpCall(utils::StringStream& out,
|
|||
|
||||
// Emit the builtin return type unique to this overload. This does not
|
||||
// exist in the AST, so it will not be generated in Generate().
|
||||
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<sem::Struct>())) {
|
||||
if (!EmitStructType(&helpers_, builtin->ReturnType()->As<type::Struct>())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
line(b) << StructName(builtin->ReturnType()->As<sem::Struct>()) << " result;";
|
||||
line(b) << StructName(builtin->ReturnType()->As<type::Struct>()) << " result;";
|
||||
line(b) << "result.fract = frexp(" << in << ", result.exp);";
|
||||
line(b) << "return result;";
|
||||
return true;
|
||||
|
@ -1658,7 +1657,7 @@ bool GeneratorImpl::EmitZeroValue(utils::StringStream& out, const type::Type* ty
|
|||
out << "{}";
|
||||
return true;
|
||||
},
|
||||
[&](const sem::Struct*) {
|
||||
[&](const type::Struct*) {
|
||||
out << "{}";
|
||||
return true;
|
||||
},
|
||||
|
@ -1763,7 +1762,7 @@ bool GeneratorImpl::EmitConstant(utils::StringStream& out, const constant::Value
|
|||
|
||||
return true;
|
||||
},
|
||||
[&](const sem::Struct* s) {
|
||||
[&](const type::Struct* s) {
|
||||
if (!EmitStructType(&helpers_, s)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2636,7 +2635,7 @@ bool GeneratorImpl::EmitType(utils::StringStream& out,
|
|||
out << "sampler";
|
||||
return true;
|
||||
},
|
||||
[&](const sem::Struct* str) {
|
||||
[&](const type::Struct* str) {
|
||||
// The struct type emits as just the name. The declaration would be
|
||||
// emitted as part of emitting the declared types.
|
||||
out << StructName(str);
|
||||
|
@ -2791,7 +2790,7 @@ bool GeneratorImpl::EmitAddressSpace(utils::StringStream& out, builtin::AddressS
|
|||
return false;
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) {
|
||||
bool GeneratorImpl::EmitStructType(TextBuffer* b, const type::Struct* str) {
|
||||
auto it = emitted_structs_.emplace(str);
|
||||
if (!it.second) {
|
||||
return true;
|
||||
|
@ -3186,7 +3185,7 @@ GeneratorImpl::SizeAndAlign GeneratorImpl::MslPackedTypeSizeAndAlign(const type:
|
|||
return SizeAndAlign{};
|
||||
},
|
||||
|
||||
[&](const sem::Struct* str) {
|
||||
[&](const type::Struct* str) {
|
||||
// TODO(crbug.com/tint/650): There's an assumption here that MSL's
|
||||
// default structure size and alignment matches WGSL's. We need to
|
||||
// confirm this.
|
||||
|
|
|
@ -340,7 +340,7 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// @param buffer the text buffer that the type declaration will be written to
|
||||
/// @param str the struct to generate
|
||||
/// @returns true if the struct is emitted
|
||||
bool EmitStructType(TextBuffer* buffer, const sem::Struct* str);
|
||||
bool EmitStructType(TextBuffer* buffer, const type::Struct* str);
|
||||
/// Handles a unary op expression
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the expression to emit
|
||||
|
@ -418,7 +418,7 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// Name of atomicCompareExchangeWeak() helper for the given pointer storage
|
||||
/// class and struct return type
|
||||
using ACEWKeyType =
|
||||
utils::UnorderedKeyWrapper<std::tuple<builtin::AddressSpace, const sem::Struct*>>;
|
||||
utils::UnorderedKeyWrapper<std::tuple<builtin::AddressSpace, const type::Struct*>>;
|
||||
std::unordered_map<ACEWKeyType, std::string> atomicCompareExchangeWeak_;
|
||||
|
||||
/// Unique name of the 'TINT_INVARIANT' preprocessor define.
|
||||
|
@ -440,7 +440,7 @@ class GeneratorImpl : public TextGenerator {
|
|||
std::unordered_map<const sem::Builtin*, std::string> builtins_;
|
||||
std::unordered_map<const type::Type*, std::string> unary_minus_funcs_;
|
||||
std::unordered_map<uint32_t, std::string> int_dot_funcs_;
|
||||
std::unordered_set<const sem::Struct*> emitted_structs_;
|
||||
std::unordered_set<const type::Struct*> emitted_structs_;
|
||||
};
|
||||
|
||||
} // namespace tint::writer::msl
|
||||
|
|
|
@ -245,8 +245,8 @@ TEST_F(MslGeneratorImplTest, EmitType_StructDecl) {
|
|||
GeneratorImpl& gen = Build();
|
||||
|
||||
TextGenerator::TextBuffer buf;
|
||||
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.Diagnostics();
|
||||
auto* str = program->TypeOf(s)->As<type::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
|
||||
EXPECT_EQ(buf.String(), R"(struct S {
|
||||
int a;
|
||||
float b;
|
||||
|
@ -292,8 +292,8 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_NonComposites) {
|
|||
GeneratorImpl& gen = Build();
|
||||
|
||||
TextGenerator::TextBuffer buf;
|
||||
auto* sem_s = program->TypeOf(type)->As<sem::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.Diagnostics();
|
||||
auto* str = program->TypeOf(type)->As<type::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
|
||||
|
||||
// ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
|
||||
// for each field of the structure s.
|
||||
|
@ -401,8 +401,8 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_Structures) {
|
|||
GeneratorImpl& gen = Build();
|
||||
|
||||
TextGenerator::TextBuffer buf;
|
||||
auto* sem_s = program->TypeOf(type)->As<sem::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.Diagnostics();
|
||||
auto* str = program->TypeOf(type)->As<type::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
|
||||
|
||||
// ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
|
||||
// for each field of the structure s.
|
||||
|
@ -493,8 +493,8 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_ArrayDefaultStride) {
|
|||
GeneratorImpl& gen = Build();
|
||||
|
||||
TextGenerator::TextBuffer buf;
|
||||
auto* sem_s = program->TypeOf(type)->As<sem::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.Diagnostics();
|
||||
auto* str = program->TypeOf(type)->As<type::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
|
||||
|
||||
// ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
|
||||
// for each field of the structure s.
|
||||
|
@ -577,8 +577,8 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_ArrayVec3DefaultStride) {
|
|||
GeneratorImpl& gen = Build();
|
||||
|
||||
TextGenerator::TextBuffer buf;
|
||||
auto* sem_s = program->TypeOf(type)->As<sem::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.Diagnostics();
|
||||
auto* str = program->TypeOf(type)->As<type::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
|
||||
|
||||
// ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
|
||||
// for each field of the structure s.
|
||||
|
@ -639,8 +639,8 @@ TEST_F(MslGeneratorImplTest, AttemptTintPadSymbolCollision) {
|
|||
GeneratorImpl& gen = Build();
|
||||
|
||||
TextGenerator::TextBuffer buf;
|
||||
auto* sem_s = program->TypeOf(type)->As<sem::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.Diagnostics();
|
||||
auto* str = program->TypeOf(type)->As<type::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
|
||||
EXPECT_EQ(buf.String(), R"(struct S {
|
||||
/* 0x0000 */ int tint_pad_2;
|
||||
/* 0x0004 */ tint_array<int8_t, 124> tint_pad_10;
|
||||
|
@ -698,8 +698,8 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_WithAttribute) {
|
|||
GeneratorImpl& gen = Build();
|
||||
|
||||
TextGenerator::TextBuffer buf;
|
||||
auto* sem_s = program->TypeOf(type)->As<sem::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.Diagnostics();
|
||||
auto* str = program->TypeOf(type)->As<type::Struct>();
|
||||
ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
|
||||
EXPECT_EQ(buf.String(), R"(struct S {
|
||||
/* 0x0000 */ int a;
|
||||
/* 0x0004 */ float b;
|
||||
|
|
|
@ -790,8 +790,8 @@ bool Builder::GenerateGlobalVariable(const ast::Variable* v) {
|
|||
ops.push_back(Operand(init_id));
|
||||
} else {
|
||||
auto* st = type->As<type::StorageTexture>();
|
||||
if (st || type->Is<sem::Struct>()) {
|
||||
// type is a sem::Struct or a type::StorageTexture
|
||||
if (st || type->Is<type::Struct>()) {
|
||||
// type is a type::Struct or a type::StorageTexture
|
||||
auto access = st ? st->access() : sem->Access();
|
||||
switch (access) {
|
||||
case builtin::Access::kWrite:
|
||||
|
@ -1353,7 +1353,7 @@ uint32_t Builder::GenerateValueConstructorOrConversion(const sem::Call* call,
|
|||
// If the result is not a vector then we should have validated that the
|
||||
// value type is a correctly sized vector so we can just use it directly.
|
||||
if (result_type == value_type || result_type->Is<type::Matrix>() ||
|
||||
result_type->Is<type::Array>() || result_type->Is<sem::Struct>()) {
|
||||
result_type->Is<type::Array>() || result_type->Is<type::Struct>()) {
|
||||
ops.push_back(Operand(id));
|
||||
continue;
|
||||
}
|
||||
|
@ -1715,7 +1715,7 @@ uint32_t Builder::GenerateConstantIfNeeded(const constant::Value* constant) {
|
|||
}
|
||||
return composite(count.value());
|
||||
},
|
||||
[&](const sem::Struct* s) { return composite(s->Members().Length()); },
|
||||
[&](const type::Struct* s) { return composite(s->Members().Length()); },
|
||||
[&](Default) {
|
||||
error_ = "unhandled constant type: " + builder_.FriendlyName(ty);
|
||||
return 0;
|
||||
|
@ -2391,13 +2391,12 @@ uint32_t Builder::GenerateBuiltinCall(const sem::Call* call, const sem::Builtin*
|
|||
params.push_back(Operand(struct_id));
|
||||
|
||||
auto* type = TypeOf(accessor->object)->UnwrapRef();
|
||||
if (!type->Is<sem::Struct>()) {
|
||||
if (!type->Is<type::Struct>()) {
|
||||
error_ = "invalid type (" + type->FriendlyName() + ") for runtime array length";
|
||||
return 0;
|
||||
}
|
||||
// Runtime array must be the last member in the structure
|
||||
params.push_back(
|
||||
Operand(uint32_t(type->As<sem::Struct>()->Declaration()->members.Length() - 1)));
|
||||
params.push_back(Operand(uint32_t(type->As<type::Struct>()->Members().Length() - 1)));
|
||||
|
||||
if (!push_function_inst(spv::Op::OpArrayLength, params)) {
|
||||
return 0;
|
||||
|
@ -3702,7 +3701,7 @@ uint32_t Builder::GenerateTypeIfNeeded(const type::Type* type) {
|
|||
[&](const type::Reference* ref) { //
|
||||
return GenerateReferenceType(ref, result);
|
||||
},
|
||||
[&](const sem::Struct* str) { //
|
||||
[&](const type::Struct* str) { //
|
||||
return GenerateStructType(str, result);
|
||||
},
|
||||
[&](const type::U32*) {
|
||||
|
@ -3914,7 +3913,7 @@ bool Builder::GenerateReferenceType(const type::Reference* ref, const Operand& r
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Builder::GenerateStructType(const sem::Struct* struct_type, const Operand& result) {
|
||||
bool Builder::GenerateStructType(const type::Struct* struct_type, const Operand& result) {
|
||||
auto struct_id = std::get<uint32_t>(result);
|
||||
|
||||
if (struct_type->Name().IsValid()) {
|
||||
|
@ -3924,9 +3923,11 @@ bool Builder::GenerateStructType(const sem::Struct* struct_type, const Operand&
|
|||
OperandList ops;
|
||||
ops.push_back(result);
|
||||
|
||||
auto* decl = struct_type->Declaration();
|
||||
if (decl && ast::HasAttribute<transform::AddBlockAttribute::BlockAttribute>(decl->attributes)) {
|
||||
push_annot(spv::Op::OpDecorate, {Operand(struct_id), U32Operand(SpvDecorationBlock)});
|
||||
if (auto* sem_str = struct_type->As<sem::Struct>()) {
|
||||
auto* decl = sem_str->Declaration();
|
||||
if (ast::HasAttribute<transform::AddBlockAttribute::BlockAttribute>(decl->attributes)) {
|
||||
push_annot(spv::Op::OpDecorate, {Operand(struct_id), U32Operand(SpvDecorationBlock)});
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < struct_type->Members().Length(); ++i) {
|
||||
|
@ -3944,7 +3945,7 @@ bool Builder::GenerateStructType(const sem::Struct* struct_type, const Operand&
|
|||
|
||||
uint32_t Builder::GenerateStructMember(uint32_t struct_id,
|
||||
uint32_t idx,
|
||||
const sem::StructMember* member) {
|
||||
const type::StructMember* member) {
|
||||
push_debug(spv::Op::OpMemberName,
|
||||
{Operand(struct_id), Operand(idx), Operand(member->Name().Name())});
|
||||
|
||||
|
|
|
@ -496,7 +496,7 @@ class Builder {
|
|||
/// @param struct_type the vector to generate
|
||||
/// @param result the result operand
|
||||
/// @returns true if the vector was successfully generated
|
||||
bool GenerateStructType(const sem::Struct* struct_type, const Operand& result);
|
||||
bool GenerateStructType(const type::Struct* struct_type, const Operand& result);
|
||||
/// Generates a struct member
|
||||
/// @param struct_id the id of the parent structure
|
||||
/// @param idx the index of the member
|
||||
|
@ -504,7 +504,7 @@ class Builder {
|
|||
/// @returns the id of the struct member or 0 on error.
|
||||
uint32_t GenerateStructMember(uint32_t struct_id,
|
||||
uint32_t idx,
|
||||
const sem::StructMember* member);
|
||||
const type::StructMember* member);
|
||||
/// Generates a variable declaration statement
|
||||
/// @param stmt the statement to generate
|
||||
/// @returns true on successfull generation
|
||||
|
|
|
@ -30,7 +30,7 @@ std::string TextGenerator::UniqueIdentifier(const std::string& prefix) {
|
|||
return builder_.Symbols().New(prefix).Name();
|
||||
}
|
||||
|
||||
std::string TextGenerator::StructName(const sem::Struct* s) {
|
||||
std::string TextGenerator::StructName(const type::Struct* s) {
|
||||
auto name = s->Name().Name();
|
||||
if (name.size() > 1 && name[0] == '_' && name[1] == '_') {
|
||||
name = utils::GetOrCreate(builtin_struct_names_, s,
|
||||
|
|
|
@ -112,7 +112,7 @@ class TextGenerator {
|
|||
/// structures that start with double underscores. If the structure is a
|
||||
/// builtin, then the returned name will be a unique name without the leading
|
||||
/// underscores.
|
||||
std::string StructName(const sem::Struct* s);
|
||||
std::string StructName(const type::Struct* s);
|
||||
|
||||
/// @param str the string
|
||||
/// @param suffix the suffix to remove
|
||||
|
@ -221,7 +221,7 @@ class TextGenerator {
|
|||
/// The primary text buffer that the generator will emit
|
||||
TextBuffer main_buffer_;
|
||||
/// Map of builtin structure to unique generated name
|
||||
std::unordered_map<const sem::Struct*, std::string> builtin_struct_names_;
|
||||
std::unordered_map<const type::Struct*, std::string> builtin_struct_names_;
|
||||
};
|
||||
|
||||
} // namespace tint::writer
|
||||
|
|
Loading…
Reference in New Issue