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>
diff --git a/src/ast/struct.cc b/src/ast/struct.cc
index 01344b6..c16632e 100644
--- a/src/ast/struct.cc
+++ b/src/ast/struct.cc
@@ -19,13 +19,19 @@
Struct::Struct() : Node() {}
-Struct::Struct(StructDecoration decoration, StructMemberList members)
- : Node(), decoration_(decoration), members_(std::move(members)) {}
+Struct::Struct(StructMemberList 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,
- StructDecoration decoration,
+ StructDecorationList decorations,
StructMemberList members)
- : Node(source), decoration_(decoration), members_(std::move(members)) {}
+ : Node(source), decorations_(decorations), members_(std::move(members)) {}
Struct::Struct(Struct&&) = default;
@@ -40,7 +46,21 @@
return nullptr;
}
+bool Struct::IsBlockDecorated() const {
+ for (auto deco : decorations_) {
+ if (deco == StructDecoration::kBlock) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool Struct::IsValid() const {
+ for (auto deco : decorations_) {
+ if (deco == StructDecoration::kNone) {
+ return false;
+ }
+ }
for (const auto& mem : members_) {
if (mem == nullptr || !mem->IsValid()) {
return false;
@@ -51,10 +71,11 @@
void Struct::to_str(std::ostream& out, size_t indent) const {
make_indent(out, indent);
- if (decoration_ != StructDecoration::kNone) {
- out << "[[" << decoration_ << "]] ";
- }
out << "Struct{" << std::endl;
+ for (auto deco : decorations_) {
+ make_indent(out, indent + 2);
+ out << "[[" << deco << "]]" << std::endl;
+ }
for (const auto& member : members_) {
member->to_str(out, indent + 2);
}
diff --git a/src/ast/struct.h b/src/ast/struct.h
index e12cfd5..8a55b8d 100644
--- a/src/ast/struct.h
+++ b/src/ast/struct.h
@@ -32,15 +32,22 @@
/// Create a new empty struct statement
Struct();
/// Create a new struct statement
- /// @param decoration The struct decorations
/// @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
/// @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
Struct(const Source& source,
- StructDecoration decoration,
+ StructDecorationList decorations,
StructMemberList members);
/// Move constructor
Struct(Struct&&);
@@ -48,10 +55,12 @@
~Struct() override;
/// Sets the struct decoration
- /// @param deco the decoration to set
- void set_decoration(StructDecoration deco) { decoration_ = deco; }
- /// @returns the struct decoration
- StructDecoration decoration() const { return decoration_; }
+ /// @param decos the list of decorations to set
+ void set_decorations(StructDecorationList decos) {
+ decorations_ = std::move(decos);
+ }
+ /// @returns the struct decorations
+ const StructDecorationList& decorations() const { return decorations_; }
/// Sets the struct members
/// @param members the members to set
@@ -64,6 +73,9 @@
/// @returns the struct member or nullptr if not found
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
bool IsValid() const override;
@@ -75,7 +87,7 @@
private:
Struct(const Struct&) = delete;
- StructDecoration decoration_ = StructDecoration::kNone;
+ StructDecorationList decorations_;
StructMemberList members_;
};
diff --git a/src/ast/struct_decoration.h b/src/ast/struct_decoration.h
index fab582c..fecea8a 100644
--- a/src/ast/struct_decoration.h
+++ b/src/ast/struct_decoration.h
@@ -25,6 +25,9 @@
std::ostream& operator<<(std::ostream& out, StructDecoration stage);
+/// List of struct decorations
+using StructDecorationList = std::vector<StructDecoration>;
+
} // namespace ast
} // namespace tint
diff --git a/src/ast/struct_test.cc b/src/ast/struct_test.cc
index 0b416a2..d3bc623 100644
--- a/src/ast/struct_test.cc
+++ b/src/ast/struct_test.cc
@@ -35,23 +35,45 @@
members.push_back(
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.decoration(), StructDecoration::kNone);
+ EXPECT_TRUE(s.decorations().empty());
EXPECT_EQ(s.line(), 0u);
EXPECT_EQ(s.column(), 0u);
}
-TEST_F(StructTest, CreationWithSource) {
+TEST_F(StructTest, Creation_WithDecorations) {
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;
members.emplace_back(
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.decoration(), StructDecoration::kNone);
+ ASSERT_EQ(s.decorations().size(), 1u);
+ EXPECT_EQ(s.decorations()[0], StructDecoration::kBlock);
EXPECT_EQ(s.line(), 27u);
EXPECT_EQ(s.column(), 4u);
}
@@ -63,37 +85,57 @@
TEST_F(StructTest, IsValid_Null_StructMember) {
type::I32Type i32;
+
StructMemberList members;
members.push_back(
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
members.push_back(nullptr);
- Struct s{StructDecoration::kNone, std::move(members)};
+ Struct s{std::move(members)};
EXPECT_FALSE(s.IsValid());
}
TEST_F(StructTest, IsValid_Invalid_StructMember) {
type::I32Type i32;
+
StructMemberList members;
members.push_back(
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());
}
TEST_F(StructTest, ToStr) {
type::I32Type i32;
- Source source{27, 4};
+
StructMemberList members;
members.emplace_back(
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;
s.to_str(out, 2);
EXPECT_EQ(out.str(), R"( Struct{
+ [[block]]
StructMember{a: __i32}
}
)");
diff --git a/src/ast/type/struct_type.h b/src/ast/type/struct_type.h
index 97cb4f2..6a41e67 100644
--- a/src/ast/type/struct_type.h
+++ b/src/ast/type/struct_type.h
@@ -42,9 +42,7 @@
const std::string& name() const { return name_; }
/// @returns true if the struct has a block decoration
- bool IsBlockDecorated() const {
- return struct_->decoration() == StructDecoration::kBlock;
- }
+ bool IsBlockDecorated() const { return struct_->IsBlockDecorated(); }
/// @returns true if the type is a struct type
bool IsStruct() const override;
diff --git a/src/reader/spirv/function_memory_test.cc b/src/reader/spirv/function_memory_test.cc
index 5d4a436..267ae07 100644
--- a/src/reader/spirv/function_memory_test.cc
+++ b/src/reader/spirv/function_memory_test.cc
@@ -806,7 +806,8 @@
}
RTArr -> __array__u32_stride_4
S -> __struct_S
- [[block]] Struct{
+ Struct{
+ [[block]]
StructMember{[[ offset 0 ]] field0: __u32}
StructMember{[[ offset 4 ]] field1: __alias_RTArr__array__u32_stride_4}
})"));
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index a21bf6d..92c6a29 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -789,13 +789,13 @@
const spvtools::opt::analysis::Struct* struct_ty) {
// Compute the struct decoration.
auto struct_decorations = this->GetDecorationsFor(type_id);
- auto ast_struct_decoration = ast::StructDecoration::kNone;
+ ast::StructDecorationList ast_struct_decorations;
if (struct_decorations.size() == 1) {
const auto decoration = struct_decorations[0][0];
if (decoration == SpvDecorationBlock) {
- ast_struct_decoration = ast::StructDecoration::kBlock;
+ ast_struct_decorations.push_back(ast::StructDecoration::kBlock);
} 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);
} else {
Fail() << "struct with ID " << type_id
@@ -859,8 +859,8 @@
}
// Now make the struct.
- auto ast_struct = std::make_unique<ast::Struct>(ast_struct_decoration,
- std::move(ast_members));
+ auto ast_struct = std::make_unique<ast::Struct>(
+ std::move(ast_struct_decorations), std::move(ast_members));
// The struct type will be assigned a name during EmitAliasTypes.
auto ast_struct_type =
std::make_unique<ast::type::StructType>(std::move(ast_struct));
diff --git a/src/reader/spirv/parser_impl_convert_type_test.cc b/src/reader/spirv/parser_impl_convert_type_test.cc
index 8ee2f1d..3f18da7 100644
--- a/src/reader/spirv/parser_impl_convert_type_test.cc
+++ b/src/reader/spirv/parser_impl_convert_type_test.cc
@@ -582,7 +582,8 @@
EXPECT_TRUE(type->IsStruct());
std::stringstream ss;
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}
}
)"));
diff --git a/src/reader/spirv/parser_impl_module_var_test.cc b/src/reader/spirv/parser_impl_module_var_test.cc
index 139358e..06a81c8 100644
--- a/src/reader/spirv/parser_impl_module_var_test.cc
+++ b/src/reader/spirv/parser_impl_module_var_test.cc
@@ -1311,7 +1311,8 @@
__alias_S__struct_S
}
S -> __struct_S
- [[block]] Struct{
+ Struct{
+ [[block]]
StructMember{field0: __u32}
StructMember{field1: __f32}
StructMember{field2: __array__u32_2}
@@ -1338,7 +1339,8 @@
__alias_S__struct_S
}
S -> __struct_S
- [[block]] Struct{
+ Struct{
+ [[block]]
StructMember{field0: __u32}
StructMember{field1: __f32}
StructMember{field2: __array__u32_2}
@@ -1369,7 +1371,8 @@
__alias_S__struct_S
}
S -> __struct_S
- [[block]] Struct{
+ Struct{
+ [[block]]
StructMember{field0: __mat_2_3__f32}
}
})")) << module_str;
@@ -1398,7 +1401,8 @@
__alias_S__struct_S
}
S -> __struct_S
- [[block]] Struct{
+ Struct{
+ [[block]]
StructMember{field0: __mat_2_3__f32}
}
})")) << module_str;
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index 26044d4..a91712f 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -1445,14 +1445,21 @@
}
// 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() {
auto t = peek();
auto source = t.source();
- auto deco = struct_decoration_decl();
- if (has_error())
- return nullptr;
+ ast::StructDecorationList decos;
+ for (;;) {
+ size_t s = decos.size();
+ if (!struct_decoration_decl(decos)) {
+ return nullptr;
+ }
+ if (decos.size() == s) {
+ break;
+ }
+ }
t = next();
if (!t.IsStruct()) {
@@ -1466,22 +1473,25 @@
}
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
// : ATTR_LEFT struct_decoration ATTR_RIGHT
-ast::StructDecoration ParserImpl::struct_decoration_decl() {
+bool ParserImpl::struct_decoration_decl(ast::StructDecorationList& decos) {
auto t = peek();
- if (!t.IsAttrLeft())
- return ast::StructDecoration::kNone;
+ if (!t.IsAttrLeft()) {
+ return true;
+ }
auto deco = struct_decoration(peek(1));
- if (has_error())
- return ast::StructDecoration::kNone;
- if (deco == ast::StructDecoration::kNone) {
- return deco;
+ if (has_error()) {
+ return false;
}
+ if (deco == ast::StructDecoration::kNone) {
+ return true;
+ }
+ decos.push_back(deco);
next(); // Consume the peek of [[
next(); // Consume the peek from the struct_decoration
@@ -1489,10 +1499,10 @@
t = next();
if (!t.IsAttrRight()) {
set_error(t, "missing ]] for struct decoration");
- return ast::StructDecoration::kNone;
+ return false;
}
- return deco;
+ return true;
}
// struct_decoration
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index 5cc5248..bd7ae82 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -155,9 +155,11 @@
/// Parses a `struct_decl` grammar element
/// @returns the struct type or nullptr on error
std::unique_ptr<ast::type::StructType> struct_decl();
- /// Parses a `struct_decoration_decl` grammar element
- /// @returns the struct decoration or StructDecoraton::kNone
- ast::StructDecoration struct_decoration_decl();
+ /// Parses a `struct_decoration_decl` grammar element, appending newly
+ /// parsed decorations to the end of |decos|.
+ /// @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
/// @param t the current token
/// @returns the struct decoration or StructDecoraton::kNone if none matched
@@ -177,7 +179,8 @@
/// Parses a `function_decl` grammar element
/// @returns the parsed function, nullptr otherwise
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
/// @returns true on successful parse; false otherwise
bool function_decoration_decl(ast::FunctionDecorationList& decos);
diff --git a/src/reader/wgsl/parser_impl_struct_decl_test.cc b/src/reader/wgsl/parser_impl_struct_decl_test.cc
index b1480e1..178b3a5 100644
--- a/src/reader/wgsl/parser_impl_struct_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_decl_test.cc
@@ -48,6 +48,26 @@
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(), 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) {
diff --git a/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc b/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc
index bd64e51..5c0ef8e 100644
--- a/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc
@@ -23,14 +23,17 @@
TEST_F(ParserImplTest, StructDecorationDecl_Parses) {
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());
- EXPECT_EQ(d, ast::StructDecoration::kBlock);
+ EXPECT_EQ(decos.size(), 1u);
+ EXPECT_EQ(decos[0], ast::StructDecoration::kBlock);
}
TEST_F(ParserImplTest, StructDecorationDecl_MissingAttrRight) {
auto* p = parser("[[block");
- p->struct_decoration_decl();
+ ast::StructDecorationList decos;
+ ASSERT_FALSE(p->struct_decoration_decl(decos));
ASSERT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:8: missing ]] for struct decoration");
}
@@ -38,8 +41,10 @@
// Note, this isn't an error because it could be an array decoration
TEST_F(ParserImplTest, StructDecorationDecl_InvalidDecoration) {
auto* p = parser("[[invalid]]");
- p->struct_decoration_decl();
+ ast::StructDecorationList decos;
+ ASSERT_TRUE(p->struct_decoration_decl(decos));
ASSERT_FALSE(p->has_error());
+ EXPECT_TRUE(decos.empty());
}
} // namespace
diff --git a/src/transform/vertex_pulling_transform.cc b/src/transform/vertex_pulling_transform.cc
index fe12192..5e4d7ce 100644
--- a/src/transform/vertex_pulling_transform.cc
+++ b/src/transform/vertex_pulling_transform.cc
@@ -226,9 +226,12 @@
members.push_back(std::make_unique<ast::StructMember>(
kStructBufferName, internal_array_type, std::move(member_dec)));
- auto* struct_type = ctx_->type_mgr().Get(
- std::make_unique<ast::type::StructType>(std::make_unique<ast::Struct>(
- ast::StructDecoration::kBlock, std::move(members))));
+ ast::StructDecorationList decos;
+ decos.push_back(ast::StructDecoration::kBlock);
+
+ 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) {
// The decorated variable with struct type
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index 74adef9..4b11bf4 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -1022,8 +1022,7 @@
members.push_back(std::make_unique<ast::StructMember>("second_member", &f32,
std::move(decos)));
- auto strct = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto strct = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType st(std::move(strct));
@@ -1058,8 +1057,7 @@
members.push_back(std::make_unique<ast::StructMember>("second_member", &f32,
std::move(decos)));
- auto strct = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto strct = std::make_unique<ast::Struct>(std::move(members));
auto st = std::make_unique<ast::type::StructType>(std::move(strct));
ast::type::AliasType alias("alias", st.get());
@@ -1164,8 +1162,7 @@
b_members.push_back(
std::make_unique<ast::StructMember>("foo", &vec4, std::move(decos)));
- auto strctB = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(b_members));
+ auto strctB = std::make_unique<ast::Struct>(std::move(b_members));
ast::type::StructType stB(std::move(strctB));
stB.set_name("B");
@@ -1175,8 +1172,7 @@
a_members.push_back(
std::make_unique<ast::StructMember>("mem", &vecB, std::move(decos)));
- auto strctA = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(a_members));
+ auto strctA = std::make_unique<ast::Struct>(std::move(a_members));
ast::type::StructType stA(std::move(strctA));
stA.set_name("A");
diff --git a/src/writer/hlsl/generator_impl_type_test.cc b/src/writer/hlsl/generator_impl_type_test.cc
index 4a5b76d..85bbda4 100644
--- a/src/writer/hlsl/generator_impl_type_test.cc
+++ b/src/writer/hlsl/generator_impl_type_test.cc
@@ -261,9 +261,11 @@
members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
- auto str = std::make_unique<ast::Struct>();
- str->set_members(std::move(members));
- str->set_decoration(ast::StructDecoration::kBlock);
+ ast::StructDecorationList decos;
+ decos.push_back(ast::StructDecoration::kBlock);
+
+ auto str =
+ std::make_unique<ast::Struct>(std::move(decos), std::move(members));
ast::type::StructType s(std::move(str));
diff --git a/src/writer/msl/generator_impl_type_test.cc b/src/writer/msl/generator_impl_type_test.cc
index 6d4f8d1..02a0581 100644
--- a/src/writer/msl/generator_impl_type_test.cc
+++ b/src/writer/msl/generator_impl_type_test.cc
@@ -296,9 +296,10 @@
members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
- auto str = std::make_unique<ast::Struct>();
- str->set_members(std::move(members));
- str->set_decoration(ast::StructDecoration::kBlock);
+ ast::StructDecorationList decos;
+ decos.push_back(ast::StructDecoration::kBlock);
+ auto str =
+ std::make_unique<ast::Struct>(std::move(decos), std::move(members));
ast::type::StructType s(std::move(str));
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 45b8e34..c10f957 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -2384,14 +2384,9 @@
OperandList ops;
ops.push_back(result);
- if (impl->decoration() == ast::StructDecoration::kBlock) {
+ if (impl->IsBlockDecorated()) {
push_annot(spv::Op::OpDecorate,
{Operand::Int(struct_id), Operand::Int(SpvDecorationBlock)});
- } else {
- if (impl->decoration() != ast::StructDecoration::kNone) {
- error_ = "unknown struct decoration";
- return false;
- }
}
auto& members = impl->members();
diff --git a/src/writer/spirv/builder_accessor_expression_test.cc b/src/writer/spirv/builder_accessor_expression_test.cc
index 44b5038..7bafbed 100644
--- a/src/writer/spirv/builder_accessor_expression_test.cc
+++ b/src/writer/spirv/builder_accessor_expression_test.cc
@@ -305,8 +305,7 @@
members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(decos)));
- auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct");
@@ -363,15 +362,15 @@
inner_members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(decos)));
- ast::type::StructType inner_struct(std::make_unique<ast::Struct>(
- ast::StructDecoration::kNone, std::move(inner_members)));
+ ast::type::StructType inner_struct(
+ std::make_unique<ast::Struct>(std::move(inner_members)));
ast::StructMemberList outer_members;
outer_members.push_back(std::make_unique<ast::StructMember>(
"inner", &inner_struct, std::move(decos)));
- ast::type::StructType s_type(std::make_unique<ast::Struct>(
- ast::StructDecoration::kNone, std::move(outer_members)));
+ ast::type::StructType s_type(
+ std::make_unique<ast::Struct>(std::move(outer_members)));
s_type.set_name("my_struct");
ast::Variable var("ident", ast::StorageClass::kFunction, &s_type);
@@ -431,8 +430,8 @@
inner_members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(decos)));
- ast::type::StructType inner_struct(std::make_unique<ast::Struct>(
- ast::StructDecoration::kNone, std::move(inner_members)));
+ ast::type::StructType inner_struct(
+ std::make_unique<ast::Struct>(std::move(inner_members)));
ast::type::AliasType alias("Inner", &inner_struct);
@@ -440,8 +439,8 @@
outer_members.push_back(
std::make_unique<ast::StructMember>("inner", &alias, std::move(decos)));
- ast::type::StructType s_type(std::make_unique<ast::Struct>(
- ast::StructDecoration::kNone, std::move(outer_members)));
+ ast::type::StructType s_type(
+ std::make_unique<ast::Struct>(std::move(outer_members)));
s_type.set_name("my_struct");
ast::Variable var("ident", ast::StorageClass::kFunction, &s_type);
@@ -501,15 +500,15 @@
inner_members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(decos)));
- ast::type::StructType inner_struct(std::make_unique<ast::Struct>(
- ast::StructDecoration::kNone, std::move(inner_members)));
+ ast::type::StructType inner_struct(
+ std::make_unique<ast::Struct>(std::move(inner_members)));
ast::StructMemberList outer_members;
outer_members.push_back(std::make_unique<ast::StructMember>(
"inner", &inner_struct, std::move(decos)));
- ast::type::StructType s_type(std::make_unique<ast::Struct>(
- ast::StructDecoration::kNone, std::move(outer_members)));
+ ast::type::StructType s_type(
+ std::make_unique<ast::Struct>(std::move(outer_members)));
s_type.set_name("my_struct");
ast::Variable var("ident", ast::StorageClass::kFunction, &s_type);
@@ -576,15 +575,15 @@
inner_members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(decos)));
- ast::type::StructType inner_struct(std::make_unique<ast::Struct>(
- ast::StructDecoration::kNone, std::move(inner_members)));
+ ast::type::StructType inner_struct(
+ std::make_unique<ast::Struct>(std::move(inner_members)));
ast::StructMemberList outer_members;
outer_members.push_back(std::make_unique<ast::StructMember>(
"inner", &inner_struct, std::move(decos)));
- ast::type::StructType s_type(std::make_unique<ast::Struct>(
- ast::StructDecoration::kNone, std::move(outer_members)));
+ ast::type::StructType s_type(
+ std::make_unique<ast::Struct>(std::move(outer_members)));
s_type.set_name("my_struct");
ast::Variable var("ident", ast::StorageClass::kFunction, &s_type);
@@ -863,15 +862,13 @@
ast::StructMemberList members;
members.push_back(
std::make_unique<ast::StructMember>("baz", &vec3, std::move(decos)));
- auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType c_type(std::move(s));
c_type.set_name("C");
members.push_back(
std::make_unique<ast::StructMember>("bar", &c_type, std::move(decos)));
- s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType b_type(std::move(s));
b_type.set_name("B");
@@ -879,8 +876,7 @@
members.push_back(std::make_unique<ast::StructMember>("foo", &b_ary_type,
std::move(decos)));
- s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType a_type(std::move(s));
a_type.set_name("A");
diff --git a/src/writer/spirv/builder_assign_test.cc b/src/writer/spirv/builder_assign_test.cc
index d81af3b..ef36625 100644
--- a/src/writer/spirv/builder_assign_test.cc
+++ b/src/writer/spirv/builder_assign_test.cc
@@ -269,8 +269,7 @@
members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(decos)));
- auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct");
diff --git a/src/writer/spirv/builder_constructor_expression_test.cc b/src/writer/spirv/builder_constructor_expression_test.cc
index db910e7..2624086 100644
--- a/src/writer/spirv/builder_constructor_expression_test.cc
+++ b/src/writer/spirv/builder_constructor_expression_test.cc
@@ -1747,8 +1747,7 @@
members.push_back(
std::make_unique<ast::StructMember>("b", &vec, std::move(decos)));
- auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct");
@@ -1959,8 +1958,7 @@
members.push_back(
std::make_unique<ast::StructMember>("a", &f32, std::move(decos)));
- auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct");
diff --git a/src/writer/spirv/builder_intrinsic_test.cc b/src/writer/spirv/builder_intrinsic_test.cc
index a16c21e..f89c0e3 100644
--- a/src/writer/spirv/builder_intrinsic_test.cc
+++ b/src/writer/spirv/builder_intrinsic_test.cc
@@ -2732,8 +2732,7 @@
members.push_back(
std::make_unique<ast::StructMember>("a", &ary, std::move(decos)));
- auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct");
@@ -2792,8 +2791,7 @@
members.push_back(
std::make_unique<ast::StructMember>("a", &ary, std::move(decos)));
- auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct");
@@ -2854,8 +2852,7 @@
members.push_back(
std::make_unique<ast::StructMember>("a", &ary, std::move(decos)));
- auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct");
diff --git a/src/writer/spirv/builder_type_test.cc b/src/writer/spirv/builder_type_test.cc
index 4e2ae08..3a7e84d 100644
--- a/src/writer/spirv/builder_type_test.cc
+++ b/src/writer/spirv/builder_type_test.cc
@@ -328,8 +328,7 @@
members.push_back(
std::make_unique<ast::StructMember>("a", &f32, std::move(decos)));
- auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct");
@@ -355,7 +354,10 @@
members.push_back(
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));
ast::type::StructType s_type(std::move(s));
s_type.set_name("my_struct");
@@ -390,8 +392,7 @@
members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(b_decos)));
- auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType s_type(std::move(s));
ast::Module mod;
@@ -429,8 +430,7 @@
members.push_back(std::make_unique<ast::StructMember>("c", &glsl_mat4x4,
std::move(empty_c)));
- auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType s_type(std::move(s));
ast::Module mod;
@@ -477,8 +477,7 @@
members.push_back(std::make_unique<ast::StructMember>("c", &glsl_mat4x4,
std::move(c_decos)));
- auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType s_type(std::move(s));
ast::Module mod;
@@ -543,8 +542,7 @@
members.push_back(std::make_unique<ast::StructMember>("c", &glsl_mat4x4,
std::move(c_decos)));
- auto s = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
- std::move(members));
+ auto s = std::make_unique<ast::Struct>(std::move(members));
ast::type::StructType s_type(std::move(s));
ast::Module mod;
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index a8a4a88..446c92b 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -437,8 +437,8 @@
}
} else if (type->IsStruct()) {
auto* str = type->AsStruct()->impl();
- if (str->decoration() != ast::StructDecoration::kNone) {
- out_ << "[[" << str->decoration() << "]] ";
+ for (auto deco : str->decorations()) {
+ out_ << "[[" << deco << "]]" << std::endl;
}
out_ << "struct {" << std::endl;
diff --git a/src/writer/wgsl/generator_impl_type_test.cc b/src/writer/wgsl/generator_impl_type_test.cc
index c6e1352..495e1e4 100644
--- a/src/writer/wgsl/generator_impl_type_test.cc
+++ b/src/writer/wgsl/generator_impl_type_test.cc
@@ -160,15 +160,18 @@
members.push_back(
std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
- auto str = std::make_unique<ast::Struct>();
- str->set_members(std::move(members));
- str->set_decoration(ast::StructDecoration::kBlock);
+ ast::StructDecorationList decos;
+ decos.push_back(ast::StructDecoration::kBlock);
+
+ auto str =
+ std::make_unique<ast::Struct>(std::move(decos), std::move(members));
ast::type::StructType s(std::move(str));
GeneratorImpl g;
ASSERT_TRUE(g.EmitType(&s)) << g.error();
- EXPECT_EQ(g.result(), R"([[block]] struct {
+ EXPECT_EQ(g.result(), R"([[block]]
+struct {
a : i32;
[[offset(4)]] b : f32;
})");