Update structs to allow multiple decorations

This CL updates to match the spec change allowing multiple struct
decorations.

Bug: tint:240
Change-Id: Id859c6a331c67c46597fc3c70de06d6cc0f486ec
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/29260
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
dan sinclair 2020-10-08 18:33:25 +00:00 committed by Commit Bot service account
parent 007dc42cbb
commit 1a63c49b4e
25 changed files with 246 additions and 138 deletions

View File

@ -19,13 +19,19 @@ namespace ast {
Struct::Struct() : Node() {} Struct::Struct() : Node() {}
Struct::Struct(StructDecoration decoration, StructMemberList members) Struct::Struct(StructMemberList members)
: Node(), decoration_(decoration), members_(std::move(members)) {} : Node(), members_(std::move(members)) {}
Struct::Struct(StructDecorationList decorations, StructMemberList members)
: Node(), decorations_(decorations), members_(std::move(members)) {}
Struct::Struct(const Source& source, StructMemberList members)
: Node(source), members_(std::move(members)) {}
Struct::Struct(const Source& source, Struct::Struct(const Source& source,
StructDecoration decoration, StructDecorationList decorations,
StructMemberList members) StructMemberList members)
: Node(source), decoration_(decoration), members_(std::move(members)) {} : Node(source), decorations_(decorations), members_(std::move(members)) {}
Struct::Struct(Struct&&) = default; Struct::Struct(Struct&&) = default;
@ -40,7 +46,21 @@ StructMember* Struct::get_member(const std::string& name) const {
return nullptr; return nullptr;
} }
bool Struct::IsBlockDecorated() const {
for (auto deco : decorations_) {
if (deco == StructDecoration::kBlock) {
return true;
}
}
return false;
}
bool Struct::IsValid() const { bool Struct::IsValid() const {
for (auto deco : decorations_) {
if (deco == StructDecoration::kNone) {
return false;
}
}
for (const auto& mem : members_) { for (const auto& mem : members_) {
if (mem == nullptr || !mem->IsValid()) { if (mem == nullptr || !mem->IsValid()) {
return false; return false;
@ -51,10 +71,11 @@ bool Struct::IsValid() const {
void Struct::to_str(std::ostream& out, size_t indent) const { void Struct::to_str(std::ostream& out, size_t indent) const {
make_indent(out, indent); make_indent(out, indent);
if (decoration_ != StructDecoration::kNone) {
out << "[[" << decoration_ << "]] ";
}
out << "Struct{" << std::endl; out << "Struct{" << std::endl;
for (auto deco : decorations_) {
make_indent(out, indent + 2);
out << "[[" << deco << "]]" << std::endl;
}
for (const auto& member : members_) { for (const auto& member : members_) {
member->to_str(out, indent + 2); member->to_str(out, indent + 2);
} }

View File

@ -32,15 +32,22 @@ class Struct : public Node {
/// Create a new empty struct statement /// Create a new empty struct statement
Struct(); Struct();
/// Create a new struct statement /// Create a new struct statement
/// @param decoration The struct decorations
/// @param members The struct members /// @param members The struct members
Struct(StructDecoration decoration, StructMemberList members); explicit Struct(StructMemberList members);
/// Create a new struct statement
/// @param decorations The struct decorations
/// @param members The struct members
Struct(StructDecorationList decorations, StructMemberList members);
/// Create a new struct statement /// Create a new struct statement
/// @param source The input source for the import statement /// @param source The input source for the import statement
/// @param decoration The struct decorations /// @param members The struct members
Struct(const Source& source, StructMemberList members);
/// Create a new struct statement
/// @param source The input source for the import statement
/// @param decorations The struct decorations
/// @param members The struct members /// @param members The struct members
Struct(const Source& source, Struct(const Source& source,
StructDecoration decoration, StructDecorationList decorations,
StructMemberList members); StructMemberList members);
/// Move constructor /// Move constructor
Struct(Struct&&); Struct(Struct&&);
@ -48,10 +55,12 @@ class Struct : public Node {
~Struct() override; ~Struct() override;
/// Sets the struct decoration /// Sets the struct decoration
/// @param deco the decoration to set /// @param decos the list of decorations to set
void set_decoration(StructDecoration deco) { decoration_ = deco; } void set_decorations(StructDecorationList decos) {
/// @returns the struct decoration decorations_ = std::move(decos);
StructDecoration decoration() const { return decoration_; } }
/// @returns the struct decorations
const StructDecorationList& decorations() const { return decorations_; }
/// Sets the struct members /// Sets the struct members
/// @param members the members to set /// @param members the members to set
@ -64,6 +73,9 @@ class Struct : public Node {
/// @returns the struct member or nullptr if not found /// @returns the struct member or nullptr if not found
StructMember* get_member(const std::string& name) const; StructMember* get_member(const std::string& name) const;
/// @returns true if the struct is block decorated
bool IsBlockDecorated() const;
/// @returns true if the node is valid /// @returns true if the node is valid
bool IsValid() const override; bool IsValid() const override;
@ -75,7 +87,7 @@ class Struct : public Node {
private: private:
Struct(const Struct&) = delete; Struct(const Struct&) = delete;
StructDecoration decoration_ = StructDecoration::kNone; StructDecorationList decorations_;
StructMemberList members_; StructMemberList members_;
}; };

View File

@ -25,6 +25,9 @@ enum class StructDecoration { kNone = -1, kBlock };
std::ostream& operator<<(std::ostream& out, StructDecoration stage); std::ostream& operator<<(std::ostream& out, StructDecoration stage);
/// List of struct decorations
using StructDecorationList = std::vector<StructDecoration>;
} // namespace ast } // namespace ast
} // namespace tint } // namespace tint

View File

@ -35,23 +35,45 @@ TEST_F(StructTest, Creation) {
members.push_back( members.push_back(
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList())); std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
Struct s{StructDecoration::kNone, std::move(members)}; Struct s{std::move(members)};
EXPECT_EQ(s.members().size(), 1u); EXPECT_EQ(s.members().size(), 1u);
EXPECT_EQ(s.decoration(), StructDecoration::kNone); EXPECT_TRUE(s.decorations().empty());
EXPECT_EQ(s.line(), 0u); EXPECT_EQ(s.line(), 0u);
EXPECT_EQ(s.column(), 0u); EXPECT_EQ(s.column(), 0u);
} }
TEST_F(StructTest, CreationWithSource) { TEST_F(StructTest, Creation_WithDecorations) {
type::I32Type i32; type::I32Type i32;
Source source{27, 4};
StructMemberList members;
members.push_back(
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
StructDecorationList decos;
decos.push_back(StructDecoration::kBlock);
Struct s{std::move(decos), std::move(members)};
EXPECT_EQ(s.members().size(), 1u);
ASSERT_EQ(s.decorations().size(), 1u);
EXPECT_EQ(s.decorations()[0], StructDecoration::kBlock);
EXPECT_EQ(s.line(), 0u);
EXPECT_EQ(s.column(), 0u);
}
TEST_F(StructTest, CreationWithSourceAndDecorations) {
type::I32Type i32;
StructMemberList members; StructMemberList members;
members.emplace_back( members.emplace_back(
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList())); std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
Struct s{source, StructDecoration::kNone, std::move(members)}; StructDecorationList decos;
decos.push_back(StructDecoration::kBlock);
Struct s{Source{27, 4}, std::move(decos), std::move(members)};
EXPECT_EQ(s.members().size(), 1u); EXPECT_EQ(s.members().size(), 1u);
EXPECT_EQ(s.decoration(), StructDecoration::kNone); ASSERT_EQ(s.decorations().size(), 1u);
EXPECT_EQ(s.decorations()[0], StructDecoration::kBlock);
EXPECT_EQ(s.line(), 27u); EXPECT_EQ(s.line(), 27u);
EXPECT_EQ(s.column(), 4u); EXPECT_EQ(s.column(), 4u);
} }
@ -63,37 +85,57 @@ TEST_F(StructTest, IsValid) {
TEST_F(StructTest, IsValid_Null_StructMember) { TEST_F(StructTest, IsValid_Null_StructMember) {
type::I32Type i32; type::I32Type i32;
StructMemberList members; StructMemberList members;
members.push_back( members.push_back(
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList())); std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
members.push_back(nullptr); members.push_back(nullptr);
Struct s{StructDecoration::kNone, std::move(members)}; Struct s{std::move(members)};
EXPECT_FALSE(s.IsValid()); EXPECT_FALSE(s.IsValid());
} }
TEST_F(StructTest, IsValid_Invalid_StructMember) { TEST_F(StructTest, IsValid_Invalid_StructMember) {
type::I32Type i32; type::I32Type i32;
StructMemberList members; StructMemberList members;
members.push_back( members.push_back(
std::make_unique<StructMember>("", &i32, StructMemberDecorationList())); std::make_unique<StructMember>("", &i32, StructMemberDecorationList()));
Struct s{StructDecoration::kNone, std::move(members)}; Struct s{std::move(members)};
EXPECT_FALSE(s.IsValid());
}
TEST_F(StructTest, IsValid_NoneDecoration) {
type::I32Type i32;
StructMemberList members;
members.push_back(
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
StructDecorationList decos;
decos.push_back(StructDecoration::kNone);
Struct s{std::move(decos), std::move(members)};
EXPECT_FALSE(s.IsValid()); EXPECT_FALSE(s.IsValid());
} }
TEST_F(StructTest, ToStr) { TEST_F(StructTest, ToStr) {
type::I32Type i32; type::I32Type i32;
Source source{27, 4};
StructMemberList members; StructMemberList members;
members.emplace_back( members.emplace_back(
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList())); std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
Struct s{source, StructDecoration::kNone, std::move(members)}; StructDecorationList decos;
decos.push_back(StructDecoration::kBlock);
Struct s{std::move(decos), std::move(members)};
std::ostringstream out; std::ostringstream out;
s.to_str(out, 2); s.to_str(out, 2);
EXPECT_EQ(out.str(), R"( Struct{ EXPECT_EQ(out.str(), R"( Struct{
[[block]]
StructMember{a: __i32} StructMember{a: __i32}
} }
)"); )");

View File

@ -42,9 +42,7 @@ class StructType : public Type {
const std::string& name() const { return name_; } const std::string& name() const { return name_; }
/// @returns true if the struct has a block decoration /// @returns true if the struct has a block decoration
bool IsBlockDecorated() const { bool IsBlockDecorated() const { return struct_->IsBlockDecorated(); }
return struct_->decoration() == StructDecoration::kBlock;
}
/// @returns true if the type is a struct type /// @returns true if the type is a struct type
bool IsStruct() const override; bool IsStruct() const override;

View File

@ -806,7 +806,8 @@ TEST_F(SpvParserTest, RemapStorageBuffer_TypesAndVarDeclarations) {
} }
RTArr -> __array__u32_stride_4 RTArr -> __array__u32_stride_4
S -> __struct_S S -> __struct_S
[[block]] Struct{ Struct{
[[block]]
StructMember{[[ offset 0 ]] field0: __u32} StructMember{[[ offset 0 ]] field0: __u32}
StructMember{[[ offset 4 ]] field1: __alias_RTArr__array__u32_stride_4} StructMember{[[ offset 4 ]] field1: __alias_RTArr__array__u32_stride_4}
})")); })"));

View File

@ -789,13 +789,13 @@ ast::type::Type* ParserImpl::ConvertType(
const spvtools::opt::analysis::Struct* struct_ty) { const spvtools::opt::analysis::Struct* struct_ty) {
// Compute the struct decoration. // Compute the struct decoration.
auto struct_decorations = this->GetDecorationsFor(type_id); auto struct_decorations = this->GetDecorationsFor(type_id);
auto ast_struct_decoration = ast::StructDecoration::kNone; ast::StructDecorationList ast_struct_decorations;
if (struct_decorations.size() == 1) { if (struct_decorations.size() == 1) {
const auto decoration = struct_decorations[0][0]; const auto decoration = struct_decorations[0][0];
if (decoration == SpvDecorationBlock) { if (decoration == SpvDecorationBlock) {
ast_struct_decoration = ast::StructDecoration::kBlock; ast_struct_decorations.push_back(ast::StructDecoration::kBlock);
} else if (decoration == SpvDecorationBufferBlock) { } else if (decoration == SpvDecorationBufferBlock) {
ast_struct_decoration = ast::StructDecoration::kBlock; ast_struct_decorations.push_back(ast::StructDecoration::kBlock);
remap_buffer_block_type_.insert(type_id); remap_buffer_block_type_.insert(type_id);
} else { } else {
Fail() << "struct with ID " << type_id Fail() << "struct with ID " << type_id
@ -859,8 +859,8 @@ ast::type::Type* ParserImpl::ConvertType(
} }
// Now make the struct. // Now make the struct.
auto ast_struct = std::make_unique<ast::Struct>(ast_struct_decoration, auto ast_struct = std::make_unique<ast::Struct>(
std::move(ast_members)); std::move(ast_struct_decorations), std::move(ast_members));
// The struct type will be assigned a name during EmitAliasTypes. // The struct type will be assigned a name during EmitAliasTypes.
auto ast_struct_type = auto ast_struct_type =
std::make_unique<ast::type::StructType>(std::move(ast_struct)); std::make_unique<ast::type::StructType>(std::move(ast_struct));

View File

@ -582,7 +582,8 @@ TEST_F(SpvParserTest, ConvertType_StructWithBlockDecoration) {
EXPECT_TRUE(type->IsStruct()); EXPECT_TRUE(type->IsStruct());
std::stringstream ss; std::stringstream ss;
type->AsStruct()->impl()->to_str(ss, 0); type->AsStruct()->impl()->to_str(ss, 0);
EXPECT_THAT(ss.str(), Eq(R"([[block]] Struct{ EXPECT_THAT(ss.str(), Eq(R"(Struct{
[[block]]
StructMember{field0: __u32} StructMember{field0: __u32}
} }
)")); )"));

View File

@ -1311,7 +1311,8 @@ TEST_F(SpvParserTest, ModuleScopeVar_NonReadableDecoration_DroppedForNow) {
__alias_S__struct_S __alias_S__struct_S
} }
S -> __struct_S S -> __struct_S
[[block]] Struct{ Struct{
[[block]]
StructMember{field0: __u32} StructMember{field0: __u32}
StructMember{field1: __f32} StructMember{field1: __f32}
StructMember{field2: __array__u32_2} StructMember{field2: __array__u32_2}
@ -1338,7 +1339,8 @@ TEST_F(SpvParserTest, ModuleScopeVar_NonWritableDecoration_DroppedForNow) {
__alias_S__struct_S __alias_S__struct_S
} }
S -> __struct_S S -> __struct_S
[[block]] Struct{ Struct{
[[block]]
StructMember{field0: __u32} StructMember{field0: __u32}
StructMember{field1: __f32} StructMember{field1: __f32}
StructMember{field2: __array__u32_2} StructMember{field2: __array__u32_2}
@ -1369,7 +1371,8 @@ TEST_F(SpvParserTest, ModuleScopeVar_ColMajorDecoration_Dropped) {
__alias_S__struct_S __alias_S__struct_S
} }
S -> __struct_S S -> __struct_S
[[block]] Struct{ Struct{
[[block]]
StructMember{field0: __mat_2_3__f32} StructMember{field0: __mat_2_3__f32}
} }
})")) << module_str; })")) << module_str;
@ -1398,7 +1401,8 @@ TEST_F(SpvParserTest, ModuleScopeVar_MatrixStrideDecoration_Dropped) {
__alias_S__struct_S __alias_S__struct_S
} }
S -> __struct_S S -> __struct_S
[[block]] Struct{ Struct{
[[block]]
StructMember{field0: __mat_2_3__f32} StructMember{field0: __mat_2_3__f32}
} }
})")) << module_str; })")) << module_str;

View File

@ -1445,14 +1445,21 @@ ast::StorageClass ParserImpl::storage_class() {
} }
// struct_decl // struct_decl
// : struct_decoration_decl? STRUCT struct_body_decl // : struct_decoration_decl* STRUCT struct_body_decl
std::unique_ptr<ast::type::StructType> ParserImpl::struct_decl() { std::unique_ptr<ast::type::StructType> ParserImpl::struct_decl() {
auto t = peek(); auto t = peek();
auto source = t.source(); auto source = t.source();
auto deco = struct_decoration_decl(); ast::StructDecorationList decos;
if (has_error()) for (;;) {
return nullptr; size_t s = decos.size();
if (!struct_decoration_decl(decos)) {
return nullptr;
}
if (decos.size() == s) {
break;
}
}
t = next(); t = next();
if (!t.IsStruct()) { if (!t.IsStruct()) {
@ -1466,22 +1473,25 @@ std::unique_ptr<ast::type::StructType> ParserImpl::struct_decl() {
} }
return std::make_unique<ast::type::StructType>( return std::make_unique<ast::type::StructType>(
std::make_unique<ast::Struct>(source, deco, std::move(body))); std::make_unique<ast::Struct>(source, std::move(decos), std::move(body)));
} }
// struct_decoration_decl // struct_decoration_decl
// : ATTR_LEFT struct_decoration ATTR_RIGHT // : ATTR_LEFT struct_decoration ATTR_RIGHT
ast::StructDecoration ParserImpl::struct_decoration_decl() { bool ParserImpl::struct_decoration_decl(ast::StructDecorationList& decos) {
auto t = peek(); auto t = peek();
if (!t.IsAttrLeft()) if (!t.IsAttrLeft()) {
return ast::StructDecoration::kNone; return true;
}
auto deco = struct_decoration(peek(1)); auto deco = struct_decoration(peek(1));
if (has_error()) if (has_error()) {
return ast::StructDecoration::kNone; return false;
if (deco == ast::StructDecoration::kNone) {
return deco;
} }
if (deco == ast::StructDecoration::kNone) {
return true;
}
decos.push_back(deco);
next(); // Consume the peek of [[ next(); // Consume the peek of [[
next(); // Consume the peek from the struct_decoration next(); // Consume the peek from the struct_decoration
@ -1489,10 +1499,10 @@ ast::StructDecoration ParserImpl::struct_decoration_decl() {
t = next(); t = next();
if (!t.IsAttrRight()) { if (!t.IsAttrRight()) {
set_error(t, "missing ]] for struct decoration"); set_error(t, "missing ]] for struct decoration");
return ast::StructDecoration::kNone; return false;
} }
return deco; return true;
} }
// struct_decoration // struct_decoration

View File

@ -155,9 +155,11 @@ class ParserImpl {
/// Parses a `struct_decl` grammar element /// Parses a `struct_decl` grammar element
/// @returns the struct type or nullptr on error /// @returns the struct type or nullptr on error
std::unique_ptr<ast::type::StructType> struct_decl(); std::unique_ptr<ast::type::StructType> struct_decl();
/// Parses a `struct_decoration_decl` grammar element /// Parses a `struct_decoration_decl` grammar element, appending newly
/// @returns the struct decoration or StructDecoraton::kNone /// parsed decorations to the end of |decos|.
ast::StructDecoration struct_decoration_decl(); /// @param decos list to store the parsed decorations
/// @returns the true on successful parse; false otherwise
bool struct_decoration_decl(ast::StructDecorationList& decos);
/// Parses a `struct_decoration` grammar element /// Parses a `struct_decoration` grammar element
/// @param t the current token /// @param t the current token
/// @returns the struct decoration or StructDecoraton::kNone if none matched /// @returns the struct decoration or StructDecoraton::kNone if none matched
@ -177,7 +179,8 @@ class ParserImpl {
/// Parses a `function_decl` grammar element /// Parses a `function_decl` grammar element
/// @returns the parsed function, nullptr otherwise /// @returns the parsed function, nullptr otherwise
std::unique_ptr<ast::Function> function_decl(); std::unique_ptr<ast::Function> function_decl();
/// Parses a `function_decoration_decl` grammar element /// Parses a `function_decoration_decl` grammar element, appending newly
/// parsed decorations to the end of |decos|.
/// @param decos list to store the parsed decorations /// @param decos list to store the parsed decorations
/// @returns true on successful parse; false otherwise /// @returns true on successful parse; false otherwise
bool function_decoration_decl(ast::FunctionDecorationList& decos); bool function_decoration_decl(ast::FunctionDecorationList& decos);

View File

@ -48,6 +48,26 @@ TEST_F(ParserImplTest, StructDecl_ParsesWithDecoration) {
ASSERT_EQ(s->impl()->members().size(), 2u); ASSERT_EQ(s->impl()->members().size(), 2u);
EXPECT_EQ(s->impl()->members()[0]->name(), "a"); EXPECT_EQ(s->impl()->members()[0]->name(), "a");
EXPECT_EQ(s->impl()->members()[1]->name(), "b"); EXPECT_EQ(s->impl()->members()[1]->name(), "b");
ASSERT_EQ(s->impl()->decorations().size(), 1u);
EXPECT_EQ(s->impl()->decorations()[0], ast::StructDecoration::kBlock);
}
TEST_F(ParserImplTest, StructDecl_ParsesWithMultipleDecoration) {
auto* p = parser(R"(
[[block]]
[[block]] struct {
a : f32;
b : f32;
})");
auto s = p->struct_decl();
ASSERT_FALSE(p->has_error());
ASSERT_NE(s, nullptr);
ASSERT_EQ(s->impl()->members().size(), 2u);
EXPECT_EQ(s->impl()->members()[0]->name(), "a");
EXPECT_EQ(s->impl()->members()[1]->name(), "b");
ASSERT_EQ(s->impl()->decorations().size(), 2u);
EXPECT_EQ(s->impl()->decorations()[0], ast::StructDecoration::kBlock);
EXPECT_EQ(s->impl()->decorations()[1], ast::StructDecoration::kBlock);
} }
TEST_F(ParserImplTest, StructDecl_EmptyMembers) { TEST_F(ParserImplTest, StructDecl_EmptyMembers) {

View File

@ -23,14 +23,17 @@ namespace {
TEST_F(ParserImplTest, StructDecorationDecl_Parses) { TEST_F(ParserImplTest, StructDecorationDecl_Parses) {
auto* p = parser("[[block]]"); auto* p = parser("[[block]]");
auto d = p->struct_decoration_decl(); ast::StructDecorationList decos;
ASSERT_TRUE(p->struct_decoration_decl(decos));
ASSERT_FALSE(p->has_error()); ASSERT_FALSE(p->has_error());
EXPECT_EQ(d, ast::StructDecoration::kBlock); EXPECT_EQ(decos.size(), 1u);
EXPECT_EQ(decos[0], ast::StructDecoration::kBlock);
} }
TEST_F(ParserImplTest, StructDecorationDecl_MissingAttrRight) { TEST_F(ParserImplTest, StructDecorationDecl_MissingAttrRight) {
auto* p = parser("[[block"); auto* p = parser("[[block");
p->struct_decoration_decl(); ast::StructDecorationList decos;
ASSERT_FALSE(p->struct_decoration_decl(decos));
ASSERT_TRUE(p->has_error()); ASSERT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:8: missing ]] for struct decoration"); EXPECT_EQ(p->error(), "1:8: missing ]] for struct decoration");
} }
@ -38,8 +41,10 @@ TEST_F(ParserImplTest, StructDecorationDecl_MissingAttrRight) {
// Note, this isn't an error because it could be an array decoration // Note, this isn't an error because it could be an array decoration
TEST_F(ParserImplTest, StructDecorationDecl_InvalidDecoration) { TEST_F(ParserImplTest, StructDecorationDecl_InvalidDecoration) {
auto* p = parser("[[invalid]]"); auto* p = parser("[[invalid]]");
p->struct_decoration_decl(); ast::StructDecorationList decos;
ASSERT_TRUE(p->struct_decoration_decl(decos));
ASSERT_FALSE(p->has_error()); ASSERT_FALSE(p->has_error());
EXPECT_TRUE(decos.empty());
} }
} // namespace } // namespace

View File

@ -226,9 +226,12 @@ void VertexPullingTransform::AddVertexStorageBuffers() {
members.push_back(std::make_unique<ast::StructMember>( members.push_back(std::make_unique<ast::StructMember>(
kStructBufferName, internal_array_type, std::move(member_dec))); kStructBufferName, internal_array_type, std::move(member_dec)));
auto* struct_type = ctx_->type_mgr().Get( ast::StructDecorationList decos;
std::make_unique<ast::type::StructType>(std::make_unique<ast::Struct>( decos.push_back(ast::StructDecoration::kBlock);
ast::StructDecoration::kBlock, std::move(members))));
auto* struct_type =
ctx_->type_mgr().Get(std::make_unique<ast::type::StructType>(
std::make_unique<ast::Struct>(std::move(decos), std::move(members))));
for (uint32_t i = 0; i < vertex_state_->vertex_buffers.size(); ++i) { for (uint32_t i = 0; i < vertex_state_->vertex_buffers.size(); ++i) {
// The decorated variable with struct type // The decorated variable with struct type

View File

@ -1022,8 +1022,7 @@ TEST_F(TypeDeterminerTest, Expr_MemberAccessor_Struct) {
members.push_back(std::make_unique<ast::StructMember>("second_member", &f32, members.push_back(std::make_unique<ast::StructMember>("second_member", &f32,
std::move(decos))); std::move(decos)));
auto strct = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto strct = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType st(std::move(strct)); ast::type::StructType st(std::move(strct));
@ -1058,8 +1057,7 @@ TEST_F(TypeDeterminerTest, Expr_MemberAccessor_Struct_Alias) {
members.push_back(std::make_unique<ast::StructMember>("second_member", &f32, members.push_back(std::make_unique<ast::StructMember>("second_member", &f32,
std::move(decos))); std::move(decos)));
auto strct = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto strct = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
auto st = std::make_unique<ast::type::StructType>(std::move(strct)); auto st = std::make_unique<ast::type::StructType>(std::move(strct));
ast::type::AliasType alias("alias", st.get()); ast::type::AliasType alias("alias", st.get());
@ -1164,8 +1162,7 @@ TEST_F(TypeDeterminerTest, Expr_Accessor_MultiLevel) {
b_members.push_back( b_members.push_back(
std::make_unique<ast::StructMember>("foo", &vec4, std::move(decos))); std::make_unique<ast::StructMember>("foo", &vec4, std::move(decos)));
auto strctB = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto strctB = std::make_unique<ast::Struct>(std::move(b_members));
std::move(b_members));
ast::type::StructType stB(std::move(strctB)); ast::type::StructType stB(std::move(strctB));
stB.set_name("B"); stB.set_name("B");
@ -1175,8 +1172,7 @@ TEST_F(TypeDeterminerTest, Expr_Accessor_MultiLevel) {
a_members.push_back( a_members.push_back(
std::make_unique<ast::StructMember>("mem", &vecB, std::move(decos))); std::make_unique<ast::StructMember>("mem", &vecB, std::move(decos)));
auto strctA = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto strctA = std::make_unique<ast::Struct>(std::move(a_members));
std::move(a_members));
ast::type::StructType stA(std::move(strctA)); ast::type::StructType stA(std::move(strctA));
stA.set_name("A"); stA.set_name("A");

View File

@ -261,9 +261,11 @@ TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_Struct_WithDecoration) {
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco))); std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
auto str = std::make_unique<ast::Struct>(); ast::StructDecorationList decos;
str->set_members(std::move(members)); decos.push_back(ast::StructDecoration::kBlock);
str->set_decoration(ast::StructDecoration::kBlock);
auto str =
std::make_unique<ast::Struct>(std::move(decos), std::move(members));
ast::type::StructType s(std::move(str)); ast::type::StructType s(std::move(str));

View File

@ -296,9 +296,10 @@ TEST_F(MslGeneratorImplTest, DISABLED_EmitType_Struct_WithDecoration) {
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco))); std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
auto str = std::make_unique<ast::Struct>(); ast::StructDecorationList decos;
str->set_members(std::move(members)); decos.push_back(ast::StructDecoration::kBlock);
str->set_decoration(ast::StructDecoration::kBlock); auto str =
std::make_unique<ast::Struct>(std::move(decos), std::move(members));
ast::type::StructType s(std::move(str)); ast::type::StructType s(std::move(str));

View File

@ -2384,14 +2384,9 @@ bool Builder::GenerateStructType(ast::type::StructType* struct_type,
OperandList ops; OperandList ops;
ops.push_back(result); ops.push_back(result);
if (impl->decoration() == ast::StructDecoration::kBlock) { if (impl->IsBlockDecorated()) {
push_annot(spv::Op::OpDecorate, push_annot(spv::Op::OpDecorate,
{Operand::Int(struct_id), Operand::Int(SpvDecorationBlock)}); {Operand::Int(struct_id), Operand::Int(SpvDecorationBlock)});
} else {
if (impl->decoration() != ast::StructDecoration::kNone) {
error_ = "unknown struct decoration";
return false;
}
} }
auto& members = impl->members(); auto& members = impl->members();

View File

@ -305,8 +305,7 @@ TEST_F(BuilderTest, MemberAccessor) {
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(decos))); std::make_unique<ast::StructMember>("b", &f32, std::move(decos)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType s_type(std::move(s)); ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct"); s_type.set_name("my_struct");
@ -363,15 +362,15 @@ TEST_F(BuilderTest, MemberAccessor_Nested) {
inner_members.push_back( inner_members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(decos))); std::make_unique<ast::StructMember>("b", &f32, std::move(decos)));
ast::type::StructType inner_struct(std::make_unique<ast::Struct>( ast::type::StructType inner_struct(
ast::StructDecoration::kNone, std::move(inner_members))); std::make_unique<ast::Struct>(std::move(inner_members)));
ast::StructMemberList outer_members; ast::StructMemberList outer_members;
outer_members.push_back(std::make_unique<ast::StructMember>( outer_members.push_back(std::make_unique<ast::StructMember>(
"inner", &inner_struct, std::move(decos))); "inner", &inner_struct, std::move(decos)));
ast::type::StructType s_type(std::make_unique<ast::Struct>( ast::type::StructType s_type(
ast::StructDecoration::kNone, std::move(outer_members))); std::make_unique<ast::Struct>(std::move(outer_members)));
s_type.set_name("my_struct"); s_type.set_name("my_struct");
ast::Variable var("ident", ast::StorageClass::kFunction, &s_type); ast::Variable var("ident", ast::StorageClass::kFunction, &s_type);
@ -431,8 +430,8 @@ TEST_F(BuilderTest, MemberAccessor_Nested_WithAlias) {
inner_members.push_back( inner_members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(decos))); std::make_unique<ast::StructMember>("b", &f32, std::move(decos)));
ast::type::StructType inner_struct(std::make_unique<ast::Struct>( ast::type::StructType inner_struct(
ast::StructDecoration::kNone, std::move(inner_members))); std::make_unique<ast::Struct>(std::move(inner_members)));
ast::type::AliasType alias("Inner", &inner_struct); ast::type::AliasType alias("Inner", &inner_struct);
@ -440,8 +439,8 @@ TEST_F(BuilderTest, MemberAccessor_Nested_WithAlias) {
outer_members.push_back( outer_members.push_back(
std::make_unique<ast::StructMember>("inner", &alias, std::move(decos))); std::make_unique<ast::StructMember>("inner", &alias, std::move(decos)));
ast::type::StructType s_type(std::make_unique<ast::Struct>( ast::type::StructType s_type(
ast::StructDecoration::kNone, std::move(outer_members))); std::make_unique<ast::Struct>(std::move(outer_members)));
s_type.set_name("my_struct"); s_type.set_name("my_struct");
ast::Variable var("ident", ast::StorageClass::kFunction, &s_type); ast::Variable var("ident", ast::StorageClass::kFunction, &s_type);
@ -501,15 +500,15 @@ TEST_F(BuilderTest, MemberAccessor_Nested_Assignment_LHS) {
inner_members.push_back( inner_members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(decos))); std::make_unique<ast::StructMember>("b", &f32, std::move(decos)));
ast::type::StructType inner_struct(std::make_unique<ast::Struct>( ast::type::StructType inner_struct(
ast::StructDecoration::kNone, std::move(inner_members))); std::make_unique<ast::Struct>(std::move(inner_members)));
ast::StructMemberList outer_members; ast::StructMemberList outer_members;
outer_members.push_back(std::make_unique<ast::StructMember>( outer_members.push_back(std::make_unique<ast::StructMember>(
"inner", &inner_struct, std::move(decos))); "inner", &inner_struct, std::move(decos)));
ast::type::StructType s_type(std::make_unique<ast::Struct>( ast::type::StructType s_type(
ast::StructDecoration::kNone, std::move(outer_members))); std::make_unique<ast::Struct>(std::move(outer_members)));
s_type.set_name("my_struct"); s_type.set_name("my_struct");
ast::Variable var("ident", ast::StorageClass::kFunction, &s_type); ast::Variable var("ident", ast::StorageClass::kFunction, &s_type);
@ -576,15 +575,15 @@ TEST_F(BuilderTest, MemberAccessor_Nested_Assignment_RHS) {
inner_members.push_back( inner_members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(decos))); std::make_unique<ast::StructMember>("b", &f32, std::move(decos)));
ast::type::StructType inner_struct(std::make_unique<ast::Struct>( ast::type::StructType inner_struct(
ast::StructDecoration::kNone, std::move(inner_members))); std::make_unique<ast::Struct>(std::move(inner_members)));
ast::StructMemberList outer_members; ast::StructMemberList outer_members;
outer_members.push_back(std::make_unique<ast::StructMember>( outer_members.push_back(std::make_unique<ast::StructMember>(
"inner", &inner_struct, std::move(decos))); "inner", &inner_struct, std::move(decos)));
ast::type::StructType s_type(std::make_unique<ast::Struct>( ast::type::StructType s_type(
ast::StructDecoration::kNone, std::move(outer_members))); std::make_unique<ast::Struct>(std::move(outer_members)));
s_type.set_name("my_struct"); s_type.set_name("my_struct");
ast::Variable var("ident", ast::StorageClass::kFunction, &s_type); ast::Variable var("ident", ast::StorageClass::kFunction, &s_type);
@ -863,15 +862,13 @@ TEST_F(BuilderTest, Accessor_Mixed_ArrayAndMember) {
ast::StructMemberList members; ast::StructMemberList members;
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("baz", &vec3, std::move(decos))); std::make_unique<ast::StructMember>("baz", &vec3, std::move(decos)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType c_type(std::move(s)); ast::type::StructType c_type(std::move(s));
c_type.set_name("C"); c_type.set_name("C");
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("bar", &c_type, std::move(decos))); std::make_unique<ast::StructMember>("bar", &c_type, std::move(decos)));
s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType b_type(std::move(s)); ast::type::StructType b_type(std::move(s));
b_type.set_name("B"); b_type.set_name("B");
@ -879,8 +876,7 @@ TEST_F(BuilderTest, Accessor_Mixed_ArrayAndMember) {
members.push_back(std::make_unique<ast::StructMember>("foo", &b_ary_type, members.push_back(std::make_unique<ast::StructMember>("foo", &b_ary_type,
std::move(decos))); std::move(decos)));
s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType a_type(std::move(s)); ast::type::StructType a_type(std::move(s));
a_type.set_name("A"); a_type.set_name("A");

View File

@ -269,8 +269,7 @@ TEST_F(BuilderTest, Assign_StructMember) {
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(decos))); std::make_unique<ast::StructMember>("b", &f32, std::move(decos)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType s_type(std::move(s)); ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct"); s_type.set_name("my_struct");

View File

@ -1747,8 +1747,7 @@ TEST_F(BuilderTest, Constructor_Type_Struct) {
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("b", &vec, std::move(decos))); std::make_unique<ast::StructMember>("b", &vec, std::move(decos)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType s_type(std::move(s)); ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct"); s_type.set_name("my_struct");
@ -1959,8 +1958,7 @@ TEST_F(BuilderTest, Constructor_Type_ZeroInit_Struct) {
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("a", &f32, std::move(decos))); std::make_unique<ast::StructMember>("a", &f32, std::move(decos)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType s_type(std::move(s)); ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct"); s_type.set_name("my_struct");

View File

@ -2732,8 +2732,7 @@ TEST_F(BuilderTest, Call_ArrayLength) {
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("a", &ary, std::move(decos))); std::make_unique<ast::StructMember>("a", &ary, std::move(decos)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType s_type(std::move(s)); ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct"); s_type.set_name("my_struct");
@ -2792,8 +2791,7 @@ TEST_F(BuilderTest, Call_ArrayLength_OtherMembersInStruct) {
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("a", &ary, std::move(decos))); std::make_unique<ast::StructMember>("a", &ary, std::move(decos)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType s_type(std::move(s)); ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct"); s_type.set_name("my_struct");
@ -2854,8 +2852,7 @@ TEST_F(BuilderTest, DISABLED_Call_ArrayLength_Ptr) {
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("a", &ary, std::move(decos))); std::make_unique<ast::StructMember>("a", &ary, std::move(decos)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType s_type(std::move(s)); ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct"); s_type.set_name("my_struct");

View File

@ -328,8 +328,7 @@ TEST_F(BuilderTest_Type, GenerateStruct) {
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("a", &f32, std::move(decos))); std::make_unique<ast::StructMember>("a", &f32, std::move(decos)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType s_type(std::move(s)); ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct"); s_type.set_name("my_struct");
@ -355,7 +354,10 @@ TEST_F(BuilderTest_Type, GenerateStruct_Decorated) {
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("a", &f32, std::move(decos))); std::make_unique<ast::StructMember>("a", &f32, std::move(decos)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kBlock, ast::StructDecorationList struct_decos;
struct_decos.push_back(ast::StructDecoration::kBlock);
auto s = std::make_unique<ast::Struct>(std::move(struct_decos),
std::move(members)); std::move(members));
ast::type::StructType s_type(std::move(s)); ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct"); s_type.set_name("my_struct");
@ -390,8 +392,7 @@ TEST_F(BuilderTest_Type, GenerateStruct_DecoratedMembers) {
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(b_decos))); std::make_unique<ast::StructMember>("b", &f32, std::move(b_decos)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType s_type(std::move(s)); ast::type::StructType s_type(std::move(s));
ast::Module mod; ast::Module mod;
@ -429,8 +430,7 @@ TEST_F(BuilderTest_Type, GenerateStruct_NonLayout_Matrix) {
members.push_back(std::make_unique<ast::StructMember>("c", &glsl_mat4x4, members.push_back(std::make_unique<ast::StructMember>("c", &glsl_mat4x4,
std::move(empty_c))); std::move(empty_c)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType s_type(std::move(s)); ast::type::StructType s_type(std::move(s));
ast::Module mod; ast::Module mod;
@ -477,8 +477,7 @@ TEST_F(BuilderTest_Type, GenerateStruct_DecoratedMembers_LayoutMatrix) {
members.push_back(std::make_unique<ast::StructMember>("c", &glsl_mat4x4, members.push_back(std::make_unique<ast::StructMember>("c", &glsl_mat4x4,
std::move(c_decos))); std::move(c_decos)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType s_type(std::move(s)); ast::type::StructType s_type(std::move(s));
ast::Module mod; ast::Module mod;
@ -543,8 +542,7 @@ TEST_F(BuilderTest_Type, GenerateStruct_DecoratedMembers_LayoutArraysOfMatrix) {
members.push_back(std::make_unique<ast::StructMember>("c", &glsl_mat4x4, members.push_back(std::make_unique<ast::StructMember>("c", &glsl_mat4x4,
std::move(c_decos))); std::move(c_decos)));
auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone, auto s = std::make_unique<ast::Struct>(std::move(members));
std::move(members));
ast::type::StructType s_type(std::move(s)); ast::type::StructType s_type(std::move(s));
ast::Module mod; ast::Module mod;

View File

@ -437,8 +437,8 @@ bool GeneratorImpl::EmitType(ast::type::Type* type) {
} }
} else if (type->IsStruct()) { } else if (type->IsStruct()) {
auto* str = type->AsStruct()->impl(); auto* str = type->AsStruct()->impl();
if (str->decoration() != ast::StructDecoration::kNone) { for (auto deco : str->decorations()) {
out_ << "[[" << str->decoration() << "]] "; out_ << "[[" << deco << "]]" << std::endl;
} }
out_ << "struct {" << std::endl; out_ << "struct {" << std::endl;

View File

@ -160,15 +160,18 @@ TEST_F(WgslGeneratorImplTest, EmitType_Struct_WithDecoration) {
members.push_back( members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco))); std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
auto str = std::make_unique<ast::Struct>(); ast::StructDecorationList decos;
str->set_members(std::move(members)); decos.push_back(ast::StructDecoration::kBlock);
str->set_decoration(ast::StructDecoration::kBlock);
auto str =
std::make_unique<ast::Struct>(std::move(decos), std::move(members));
ast::type::StructType s(std::move(str)); ast::type::StructType s(std::move(str));
GeneratorImpl g; GeneratorImpl g;
ASSERT_TRUE(g.EmitType(&s)) << g.error(); ASSERT_TRUE(g.EmitType(&s)) << g.error();
EXPECT_EQ(g.result(), R"([[block]] struct { EXPECT_EQ(g.result(), R"([[block]]
struct {
a : i32; a : i32;
[[offset(4)]] b : f32; [[offset(4)]] b : f32;
})"); })");