Store struct member location into the sem.

This CL adds the `@location` of a Struct Member into the
`StructMember` sem object as a `std::optional<uint32_t>`. The
resolver then populates the location value if an attribute is
found during resolution.

This will provide a place to store the evaluated expression value
for a location in the future.

Bug: tint:1633
Change-Id: I6f696968dddf95af1f933d96cdb4a7630badac2e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/101062
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
dan sinclair 2022-09-06 14:41:16 +00:00 committed by Dawn LUCI CQ
parent 8dc97a8e3d
commit 97c9e0ba9f
8 changed files with 72 additions and 16 deletions

View File

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

View File

@ -793,7 +793,8 @@ const sem::Struct* build_struct(MatchState& state,
/* index */ static_cast<uint32_t>(members.size()),
/* offset */ offset,
/* align */ align,
/* size */ size));
/* size */ size,
/* location */ std::nullopt));
offset += size;
}
uint32_t size_without_padding = offset;

View File

@ -2747,6 +2747,7 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) {
bool has_offset_attr = false;
bool has_align_attr = false;
bool has_size_attr = false;
std::optional<uint32_t> location;
for (auto* attr : member->attributes) {
Mark(attr);
if (auto* o = attr->As<ast::StructMemberOffsetAttribute>()) {
@ -2760,11 +2761,7 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) {
align = 1;
has_offset_attr = true;
} else if (auto* a = attr->As<ast::StructMemberAlignAttribute>()) {
const auto* expr = Expression(a->align);
if (!expr) {
return nullptr;
}
auto* materialized = Materialize(expr);
auto* materialized = Materialize(Expression(a->align));
if (!materialized) {
return nullptr;
}
@ -2790,6 +2787,8 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) {
}
size = s->size;
has_size_attr = true;
} else if (auto* l = attr->As<ast::LocationAttribute>()) {
location = l->value;
}
}
@ -2811,7 +2810,7 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) {
auto* sem_member = builder_->create<sem::StructMember>(
member, member->symbol, type, static_cast<uint32_t>(sem_members.size()),
static_cast<uint32_t>(offset), static_cast<uint32_t>(align),
static_cast<uint32_t>(size));
static_cast<uint32_t>(size), location);
builder_->Sem().Add(member, sem_member);
sem_members.emplace_back(sem_member);

View File

@ -174,6 +174,20 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderParamViaAlias) {
UnorderedElementsAre(sem::PipelineStageUsage::kFragmentInput));
}
TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderParamLocationSet) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{Location(3)})});
Func("main", utils::Vector{Param("param", ty.Of(s))}, ty.void_(), utils::Empty,
utils::Vector{Stage(ast::PipelineStage::kFragment)});
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr);
ASSERT_EQ(1u, sem->Members().size());
EXPECT_EQ(3u, sem->Members()[0]->Location());
}
TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderReturnTypeViaAlias) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{Location(0)})});
auto* s_alias = Alias("S_alias", ty.Of(s));
@ -190,5 +204,19 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderReturnTypeViaAlias) {
UnorderedElementsAre(sem::PipelineStageUsage::kFragmentOutput));
}
TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderReturnTypeLocationSet) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{Location(3)})});
Func("main", utils::Empty, ty.Of(s), utils::Vector{Return(Construct(ty.Of(s), Expr(0_f)))},
utils::Vector{Stage(ast::PipelineStage::kFragment)});
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr);
ASSERT_EQ(1u, sem->Members().size());
EXPECT_EQ(3u, sem->Members()[0]->Location());
}
} // namespace
} // namespace tint::resolver

View File

@ -105,5 +105,23 @@ TEST_F(StructTest, Layout) {
/* */ };)");
}
TEST_F(StructTest, Location) {
auto* st = Structure("st", utils::Vector{
Member("a", ty.i32(), utils::Vector{Location(1u)}),
Member("b", ty.u32()),
});
auto p = Build();
ASSERT_TRUE(p.IsValid()) << p.Diagnostics().str();
auto* sem = p.Sem().Get(st);
ASSERT_EQ(2u, sem->Members().size());
EXPECT_TRUE(sem->Members()[0]->Location().has_value());
EXPECT_EQ(sem->Members()[0]->Location().value(), 1u);
EXPECT_FALSE(sem->Members()[1]->Location().has_value());
}
} // namespace
} // namespace tint::sem

View File

@ -161,14 +161,16 @@ StructMember::StructMember(const ast::StructMember* declaration,
uint32_t index,
uint32_t offset,
uint32_t align,
uint32_t size)
uint32_t size,
std::optional<uint32_t> location)
: declaration_(declaration),
name_(name),
type_(type),
index_(index),
offset_(offset),
align_(align),
size_(size) {}
size_(size),
location_(location) {}
StructMember::~StructMember() = default;

View File

@ -17,6 +17,7 @@
#include <stdint.h>
#include <optional>
#include <string>
#include <unordered_set>
#include <vector>
@ -180,13 +181,15 @@ class StructMember final : public Castable<StructMember, Node> {
/// @param offset the byte offset from the base of the structure
/// @param align the byte alignment of the member
/// @param size the byte size of the member
/// @param location the location attribute, if present
StructMember(const ast::StructMember* declaration,
Symbol name,
const sem::Type* type,
uint32_t index,
uint32_t offset,
uint32_t align,
uint32_t size);
uint32_t size,
std::optional<uint32_t> location);
/// Destructor
~StructMember() override;
@ -219,6 +222,9 @@ class StructMember final : public Castable<StructMember, Node> {
/// @returns byte size
uint32_t Size() const { return size_; }
/// @returns the location, if set
std::optional<uint32_t> Location() const { return location_; }
private:
const ast::StructMember* const declaration_;
const Symbol name_;
@ -228,6 +234,7 @@ class StructMember final : public Castable<StructMember, Node> {
const uint32_t offset_;
const uint32_t align_;
const uint32_t size_;
const std::optional<uint32_t> location_;
};
} // namespace tint::sem

View File

@ -54,7 +54,8 @@ struct TypeTest : public TestHelper {
/* index */ 0u,
/* offset */ 0u,
/* align */ 4u,
/* size */ 4u),
/* size */ 4u,
/* location */ std::nullopt),
},
/* align*/ 4u,
/* size*/ 4u,