// Copyright 2021 The Tint Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "src/tint/resolver/resolver.h" #include "gmock/gmock.h" #include "src/tint/resolver/resolver_test_helper.h" #include "src/tint/sem/struct.h" using namespace tint::number_suffixes; // NOLINT namespace tint::resolver { namespace { using ResolverStructLayoutTest = ResolverTest; TEST_F(ResolverStructLayoutTest, Scalars) { auto* s = Structure("S", utils::Vector{ Member("a", ty.f32()), Member("b", ty.u32()), Member("c", ty.i32()), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 12u); EXPECT_EQ(sem->SizeNoPadding(), 12u); EXPECT_EQ(sem->Align(), 4u); ASSERT_EQ(sem->Members().size(), 3u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Align(), 4u); EXPECT_EQ(sem->Members()[0]->Size(), 4u); EXPECT_EQ(sem->Members()[1]->Offset(), 4u); EXPECT_EQ(sem->Members()[1]->Align(), 4u); EXPECT_EQ(sem->Members()[1]->Size(), 4u); EXPECT_EQ(sem->Members()[2]->Offset(), 8u); EXPECT_EQ(sem->Members()[2]->Align(), 4u); EXPECT_EQ(sem->Members()[2]->Size(), 4u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } TEST_F(ResolverStructLayoutTest, ScalarsWithF16) { Enable(ast::Extension::kF16); auto* s = Structure("S", utils::Vector{ Member("a", ty.f32()), Member("b", ty.f16()), Member("c", ty.u32()), Member("d", ty.f16()), Member("e", ty.f16()), Member("f", ty.i32()), Member("g", ty.f16()), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 24u); EXPECT_EQ(sem->SizeNoPadding(), 22u); EXPECT_EQ(sem->Align(), 4u); ASSERT_EQ(sem->Members().size(), 7u); // f32 EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Align(), 4u); EXPECT_EQ(sem->Members()[0]->Size(), 4u); // f16 EXPECT_EQ(sem->Members()[1]->Offset(), 4u); EXPECT_EQ(sem->Members()[1]->Align(), 2u); EXPECT_EQ(sem->Members()[1]->Size(), 2u); // u32 EXPECT_EQ(sem->Members()[2]->Offset(), 8u); EXPECT_EQ(sem->Members()[2]->Align(), 4u); EXPECT_EQ(sem->Members()[2]->Size(), 4u); // f16 EXPECT_EQ(sem->Members()[3]->Offset(), 12u); EXPECT_EQ(sem->Members()[3]->Align(), 2u); EXPECT_EQ(sem->Members()[3]->Size(), 2u); // f16 EXPECT_EQ(sem->Members()[4]->Offset(), 14u); EXPECT_EQ(sem->Members()[4]->Align(), 2u); EXPECT_EQ(sem->Members()[4]->Size(), 2u); // i32 EXPECT_EQ(sem->Members()[5]->Offset(), 16u); EXPECT_EQ(sem->Members()[5]->Align(), 4u); EXPECT_EQ(sem->Members()[5]->Size(), 4u); // f16 EXPECT_EQ(sem->Members()[6]->Offset(), 20u); EXPECT_EQ(sem->Members()[6]->Align(), 2u); EXPECT_EQ(sem->Members()[6]->Size(), 2u); } TEST_F(ResolverStructLayoutTest, Alias) { auto* alias_a = Alias("a", ty.f32()); auto* alias_b = Alias("b", ty.f32()); auto* s = Structure("S", utils::Vector{ Member("a", ty.Of(alias_a)), Member("b", ty.Of(alias_b)), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 8u); EXPECT_EQ(sem->SizeNoPadding(), 8u); EXPECT_EQ(sem->Align(), 4u); ASSERT_EQ(sem->Members().size(), 2u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Align(), 4u); EXPECT_EQ(sem->Members()[0]->Size(), 4u); EXPECT_EQ(sem->Members()[1]->Offset(), 4u); EXPECT_EQ(sem->Members()[1]->Align(), 4u); EXPECT_EQ(sem->Members()[1]->Size(), 4u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } TEST_F(ResolverStructLayoutTest, ImplicitStrideArrayStaticSize) { Enable(ast::Extension::kF16); auto* s = Structure("S", utils::Vector{ Member("a", ty.array()), Member("b", ty.array()), Member("c", ty.array()), Member("d", ty.array()), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 52u); EXPECT_EQ(sem->SizeNoPadding(), 52u); EXPECT_EQ(sem->Align(), 4u); ASSERT_EQ(sem->Members().size(), 4u); // array EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Align(), 4u); EXPECT_EQ(sem->Members()[0]->Size(), 12u); // array EXPECT_EQ(sem->Members()[1]->Offset(), 12u); EXPECT_EQ(sem->Members()[1]->Align(), 4u); EXPECT_EQ(sem->Members()[1]->Size(), 20u); // array EXPECT_EQ(sem->Members()[2]->Offset(), 32u); EXPECT_EQ(sem->Members()[2]->Align(), 2u); EXPECT_EQ(sem->Members()[2]->Size(), 14u); // array EXPECT_EQ(sem->Members()[3]->Offset(), 48u); EXPECT_EQ(sem->Members()[3]->Align(), 4u); EXPECT_EQ(sem->Members()[3]->Size(), 4u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } TEST_F(ResolverStructLayoutTest, ExplicitStrideArrayStaticSize) { Enable(ast::Extension::kF16); auto* s = Structure("S", utils::Vector{ Member("a", ty.array(/*stride*/ 8)), Member("b", ty.array(/*stride*/ 16)), Member("c", ty.array(/*stride*/ 4)), Member("d", ty.array(/*stride*/ 32)), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 164u); EXPECT_EQ(sem->SizeNoPadding(), 164u); EXPECT_EQ(sem->Align(), 4u); ASSERT_EQ(sem->Members().size(), 4u); // array, stride = 8 EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Align(), 4u); EXPECT_EQ(sem->Members()[0]->Size(), 24u); // array, stride = 16 EXPECT_EQ(sem->Members()[1]->Offset(), 24u); EXPECT_EQ(sem->Members()[1]->Align(), 4u); EXPECT_EQ(sem->Members()[1]->Size(), 80u); // array, stride = 4 EXPECT_EQ(sem->Members()[2]->Offset(), 104u); EXPECT_EQ(sem->Members()[2]->Align(), 2u); EXPECT_EQ(sem->Members()[2]->Size(), 28u); // array, stride = 32 EXPECT_EQ(sem->Members()[3]->Offset(), 132u); EXPECT_EQ(sem->Members()[3]->Align(), 4u); EXPECT_EQ(sem->Members()[3]->Size(), 32u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } TEST_F(ResolverStructLayoutTest, ImplicitStrideArrayRuntimeSized) { auto* s = Structure("S", utils::Vector{ Member("c", ty.array()), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 4u); EXPECT_EQ(sem->SizeNoPadding(), 4u); EXPECT_EQ(sem->Align(), 4u); ASSERT_EQ(sem->Members().size(), 1u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Align(), 4u); EXPECT_EQ(sem->Members()[0]->Size(), 4u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } TEST_F(ResolverStructLayoutTest, ExplicitStrideArrayRuntimeSized) { auto* s = Structure("S", utils::Vector{ Member("c", ty.array(/*stride*/ 32)), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 32u); EXPECT_EQ(sem->SizeNoPadding(), 32u); EXPECT_EQ(sem->Align(), 4u); ASSERT_EQ(sem->Members().size(), 1u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Align(), 4u); EXPECT_EQ(sem->Members()[0]->Size(), 32u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } TEST_F(ResolverStructLayoutTest, ImplicitStrideArrayOfExplicitStrideArray) { auto* inner = ty.array(/*stride*/ 16); // size: 32 auto* outer = ty.array(inner, 12_u); // size: 12 * 32 auto* s = Structure("S", utils::Vector{ Member("c", outer), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 384u); EXPECT_EQ(sem->SizeNoPadding(), 384u); EXPECT_EQ(sem->Align(), 4u); ASSERT_EQ(sem->Members().size(), 1u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Align(), 4u); EXPECT_EQ(sem->Members()[0]->Size(), 384u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } TEST_F(ResolverStructLayoutTest, ImplicitStrideArrayOfStructure) { auto* inner = Structure("Inner", utils::Vector{ Member("a", ty.vec2()), Member("b", ty.vec3()), Member("c", ty.vec4()), }); // size: 48 auto* outer = ty.array(ty.Of(inner), 12_u); // size: 12 * 48 auto* s = Structure("S", utils::Vector{ Member("c", outer), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 576u); EXPECT_EQ(sem->SizeNoPadding(), 576u); EXPECT_EQ(sem->Align(), 16u); ASSERT_EQ(sem->Members().size(), 1u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Align(), 16u); EXPECT_EQ(sem->Members()[0]->Size(), 576u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } TEST_F(ResolverStructLayoutTest, Vector) { auto* s = Structure("S", utils::Vector{ Member("a", ty.vec2()), Member("b", ty.vec3()), Member("c", ty.vec4()), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 48u); EXPECT_EQ(sem->SizeNoPadding(), 48u); EXPECT_EQ(sem->Align(), 16u); ASSERT_EQ(sem->Members().size(), 3u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u); // vec2 EXPECT_EQ(sem->Members()[0]->Align(), 8u); EXPECT_EQ(sem->Members()[0]->Size(), 8u); EXPECT_EQ(sem->Members()[1]->Offset(), 16u); // vec3 EXPECT_EQ(sem->Members()[1]->Align(), 16u); EXPECT_EQ(sem->Members()[1]->Size(), 12u); EXPECT_EQ(sem->Members()[2]->Offset(), 32u); // vec4 EXPECT_EQ(sem->Members()[2]->Align(), 16u); EXPECT_EQ(sem->Members()[2]->Size(), 16u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } TEST_F(ResolverStructLayoutTest, Matrix) { Enable(ast::Extension::kF16); auto* s = Structure("S", utils::Vector{ Member("a_1", ty.mat2x2()), Member("a_2", ty.mat2x2()), Member("b_1", ty.mat2x3()), Member("b_2", ty.mat2x3()), Member("c_1", ty.mat2x4()), Member("c_2", ty.mat2x4()), Member("d_1", ty.mat3x2()), Member("d_2", ty.mat3x2()), Member("e_1", ty.mat3x3()), Member("e_2", ty.mat3x3()), Member("f_1", ty.mat3x4()), Member("f_2", ty.mat3x4()), Member("g_1", ty.mat4x2()), Member("g_2", ty.mat4x2()), Member("h_1", ty.mat4x3()), Member("h_2", ty.mat4x3()), Member("i_1", ty.mat4x4()), Member("i_2", ty.mat4x4()), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 576u); EXPECT_EQ(sem->SizeNoPadding(), 576u); EXPECT_EQ(sem->Align(), 16u); ASSERT_EQ(sem->Members().size(), 18u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u); // mat2x2 EXPECT_EQ(sem->Members()[0]->Align(), 8u); EXPECT_EQ(sem->Members()[0]->Size(), 16u); EXPECT_EQ(sem->Members()[1]->Offset(), 16u); // mat2x2 EXPECT_EQ(sem->Members()[1]->Align(), 4u); EXPECT_EQ(sem->Members()[1]->Size(), 8u); EXPECT_EQ(sem->Members()[2]->Offset(), 32u); // mat2x3 EXPECT_EQ(sem->Members()[2]->Align(), 16u); EXPECT_EQ(sem->Members()[2]->Size(), 32u); EXPECT_EQ(sem->Members()[3]->Offset(), 64u); // mat2x3 EXPECT_EQ(sem->Members()[3]->Align(), 8u); EXPECT_EQ(sem->Members()[3]->Size(), 16u); EXPECT_EQ(sem->Members()[4]->Offset(), 80u); // mat2x4 EXPECT_EQ(sem->Members()[4]->Align(), 16u); EXPECT_EQ(sem->Members()[4]->Size(), 32u); EXPECT_EQ(sem->Members()[5]->Offset(), 112u); // mat2x4 EXPECT_EQ(sem->Members()[5]->Align(), 8u); EXPECT_EQ(sem->Members()[5]->Size(), 16u); EXPECT_EQ(sem->Members()[6]->Offset(), 128u); // mat3x2 EXPECT_EQ(sem->Members()[6]->Align(), 8u); EXPECT_EQ(sem->Members()[6]->Size(), 24u); EXPECT_EQ(sem->Members()[7]->Offset(), 152u); // mat3x2 EXPECT_EQ(sem->Members()[7]->Align(), 4u); EXPECT_EQ(sem->Members()[7]->Size(), 12u); EXPECT_EQ(sem->Members()[8]->Offset(), 176u); // mat3x3 EXPECT_EQ(sem->Members()[8]->Align(), 16u); EXPECT_EQ(sem->Members()[8]->Size(), 48u); EXPECT_EQ(sem->Members()[9]->Offset(), 224u); // mat3x3 EXPECT_EQ(sem->Members()[9]->Align(), 8u); EXPECT_EQ(sem->Members()[9]->Size(), 24u); EXPECT_EQ(sem->Members()[10]->Offset(), 256u); // mat3x4 EXPECT_EQ(sem->Members()[10]->Align(), 16u); EXPECT_EQ(sem->Members()[10]->Size(), 48u); EXPECT_EQ(sem->Members()[11]->Offset(), 304u); // mat3x4 EXPECT_EQ(sem->Members()[11]->Align(), 8u); EXPECT_EQ(sem->Members()[11]->Size(), 24u); EXPECT_EQ(sem->Members()[12]->Offset(), 328u); // mat4x2 EXPECT_EQ(sem->Members()[12]->Align(), 8u); EXPECT_EQ(sem->Members()[12]->Size(), 32u); EXPECT_EQ(sem->Members()[13]->Offset(), 360u); // mat4x2 EXPECT_EQ(sem->Members()[13]->Align(), 4u); EXPECT_EQ(sem->Members()[13]->Size(), 16u); EXPECT_EQ(sem->Members()[14]->Offset(), 384u); // mat4x3 EXPECT_EQ(sem->Members()[14]->Align(), 16u); EXPECT_EQ(sem->Members()[14]->Size(), 64u); EXPECT_EQ(sem->Members()[15]->Offset(), 448u); // mat4x3 EXPECT_EQ(sem->Members()[15]->Align(), 8u); EXPECT_EQ(sem->Members()[15]->Size(), 32u); EXPECT_EQ(sem->Members()[16]->Offset(), 480u); // mat4x4 EXPECT_EQ(sem->Members()[16]->Align(), 16u); EXPECT_EQ(sem->Members()[16]->Size(), 64u); EXPECT_EQ(sem->Members()[17]->Offset(), 544u); // mat4x4 EXPECT_EQ(sem->Members()[17]->Align(), 8u); EXPECT_EQ(sem->Members()[17]->Size(), 32u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } TEST_F(ResolverStructLayoutTest, NestedStruct) { auto* inner = Structure("Inner", utils::Vector{ Member("a", ty.mat3x3()), }); auto* s = Structure("S", utils::Vector{ Member("a", ty.i32()), Member("b", ty.Of(inner)), Member("c", ty.i32()), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 80u); EXPECT_EQ(sem->SizeNoPadding(), 68u); EXPECT_EQ(sem->Align(), 16u); ASSERT_EQ(sem->Members().size(), 3u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Align(), 4u); EXPECT_EQ(sem->Members()[0]->Size(), 4u); EXPECT_EQ(sem->Members()[1]->Offset(), 16u); EXPECT_EQ(sem->Members()[1]->Align(), 16u); EXPECT_EQ(sem->Members()[1]->Size(), 48u); EXPECT_EQ(sem->Members()[2]->Offset(), 64u); EXPECT_EQ(sem->Members()[2]->Align(), 4u); EXPECT_EQ(sem->Members()[2]->Size(), 4u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } TEST_F(ResolverStructLayoutTest, SizeAttributes) { auto* inner = Structure("Inner", utils::Vector{ Member("a", ty.f32(), utils::Vector{MemberSize(8_a)}), Member("b", ty.f32(), utils::Vector{MemberSize(16_a)}), Member("c", ty.f32(), utils::Vector{MemberSize(8_a)}), }); auto* s = Structure("S", utils::Vector{ Member("a", ty.f32(), utils::Vector{MemberSize(4_a)}), Member("b", ty.u32(), utils::Vector{MemberSize(8_a)}), Member("c", ty.Of(inner)), Member("d", ty.i32(), utils::Vector{MemberSize(32_a)}), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 76u); EXPECT_EQ(sem->SizeNoPadding(), 76u); EXPECT_EQ(sem->Align(), 4u); ASSERT_EQ(sem->Members().size(), 4u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Align(), 4u); EXPECT_EQ(sem->Members()[0]->Size(), 4u); EXPECT_EQ(sem->Members()[1]->Offset(), 4u); EXPECT_EQ(sem->Members()[1]->Align(), 4u); EXPECT_EQ(sem->Members()[1]->Size(), 8u); EXPECT_EQ(sem->Members()[2]->Offset(), 12u); EXPECT_EQ(sem->Members()[2]->Align(), 4u); EXPECT_EQ(sem->Members()[2]->Size(), 32u); EXPECT_EQ(sem->Members()[3]->Offset(), 44u); EXPECT_EQ(sem->Members()[3]->Align(), 4u); EXPECT_EQ(sem->Members()[3]->Size(), 32u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } TEST_F(ResolverStructLayoutTest, AlignAttributes) { auto* inner = Structure("Inner", utils::Vector{ Member("a", ty.f32(), utils::Vector{MemberAlign(8_i)}), Member("b", ty.f32(), utils::Vector{MemberAlign(16_i)}), Member("c", ty.f32(), utils::Vector{MemberAlign(4_i)}), }); auto* s = Structure("S", utils::Vector{ Member("a", ty.f32(), utils::Vector{MemberAlign(4_i)}), Member("b", ty.u32(), utils::Vector{MemberAlign(8_i)}), Member("c", ty.Of(inner)), Member("d", ty.i32(), utils::Vector{MemberAlign(32_i)}), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 96u); EXPECT_EQ(sem->SizeNoPadding(), 68u); EXPECT_EQ(sem->Align(), 32u); ASSERT_EQ(sem->Members().size(), 4u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Align(), 4u); EXPECT_EQ(sem->Members()[0]->Size(), 4u); EXPECT_EQ(sem->Members()[1]->Offset(), 8u); EXPECT_EQ(sem->Members()[1]->Align(), 8u); EXPECT_EQ(sem->Members()[1]->Size(), 4u); EXPECT_EQ(sem->Members()[2]->Offset(), 16u); EXPECT_EQ(sem->Members()[2]->Align(), 16u); EXPECT_EQ(sem->Members()[2]->Size(), 32u); EXPECT_EQ(sem->Members()[3]->Offset(), 64u); EXPECT_EQ(sem->Members()[3]->Align(), 32u); EXPECT_EQ(sem->Members()[3]->Size(), 4u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } TEST_F(ResolverStructLayoutTest, StructWithLotsOfPadding) { auto* s = Structure("S", utils::Vector{ Member("a", ty.i32(), utils::Vector{MemberAlign(1024_i)}), }); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = TypeOf(s)->As(); ASSERT_NE(sem, nullptr); EXPECT_EQ(sem->Size(), 1024u); EXPECT_EQ(sem->SizeNoPadding(), 4u); EXPECT_EQ(sem->Align(), 1024u); ASSERT_EQ(sem->Members().size(), 1u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Align(), 1024u); EXPECT_EQ(sem->Members()[0]->Size(), 4u); for (auto& m : sem->Members()) { EXPECT_EQ(m->Struct()->Declaration(), s); } } } // namespace } // namespace tint::resolver