[wgsl-reader] Allow array decorations to have multiple blocks.
This CL updates the WGSL parser to allow array decorations to accept
multiple blocks. The stride decoration on arrays was turned into a
proper decoration object instead of just storing the stride directly.
Bug: tint:240
Change-Id: I6cdc7400d8847e3e043b846ea5c9f86cb795cf86
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/29780
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: Sarah Mashayekhi <sarahmashay@google.com>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 5913650..e2a8237 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -219,6 +219,8 @@
sources = [
"src/ast/array_accessor_expression.cc",
"src/ast/array_accessor_expression.h",
+ "src/ast/array_decoration.cc",
+ "src/ast/array_decoration.h",
"src/ast/assignment_statement.cc",
"src/ast/assignment_statement.h",
"src/ast/binary_expression.cc",
@@ -303,6 +305,8 @@
"src/ast/statement.h",
"src/ast/storage_class.cc",
"src/ast/storage_class.h",
+ "src/ast/stride_decoration.cc",
+ "src/ast/stride_decoration.h",
"src/ast/struct.cc",
"src/ast/struct.h",
"src/ast/struct_decoration.cc",
@@ -727,6 +731,7 @@
"src/ast/set_decoration_test.cc",
"src/ast/sint_literal_test.cc",
"src/ast/stage_decoration_test.cc",
+ "src/ast/stride_decoration_test.cc",
"src/ast/struct_member_offset_decoration_test.cc",
"src/ast/struct_member_test.cc",
"src/ast/struct_test.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cb04a05..c4b003f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -40,6 +40,8 @@
../include/tint/tint.h
ast/array_accessor_expression.cc
ast/array_accessor_expression.h
+ ast/array_decoration.cc
+ ast/array_decoration.h
ast/assignment_statement.cc
ast/assignment_statement.h
ast/binary_expression.cc
@@ -124,10 +126,12 @@
ast/statement.h
ast/storage_class.cc
ast/storage_class.h
- ast/struct_decoration.cc
- ast/struct_decoration.h
+ ast/stride_decoration.cc
+ ast/stride_decoration.h
ast/struct.cc
ast/struct.h
+ ast/struct_decoration.cc
+ ast/struct_decoration.h
ast/struct_member.cc
ast/struct_member.h
ast/struct_member_decoration.cc
@@ -337,6 +341,7 @@
ast/set_decoration_test.cc
ast/sint_literal_test.cc
ast/stage_decoration_test.cc
+ ast/stride_decoration_test.cc
ast/struct_member_test.cc
ast/struct_member_offset_decoration_test.cc
ast/struct_test.cc
diff --git a/src/ast/array_decoration.cc b/src/ast/array_decoration.cc
new file mode 100644
index 0000000..8402439
--- /dev/null
+++ b/src/ast/array_decoration.cc
@@ -0,0 +1,38 @@
+// Copyright 2020 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/ast/array_decoration.h"
+
+#include <assert.h>
+
+#include "src/ast/stride_decoration.h"
+
+namespace tint {
+namespace ast {
+
+ArrayDecoration::ArrayDecoration() = default;
+
+ArrayDecoration::~ArrayDecoration() = default;
+
+bool ArrayDecoration::IsStride() const {
+ return false;
+}
+
+StrideDecoration* ArrayDecoration::AsStride() {
+ assert(IsStride());
+ return static_cast<StrideDecoration*>(this);
+}
+
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/array_decoration.h b/src/ast/array_decoration.h
new file mode 100644
index 0000000..579668b
--- /dev/null
+++ b/src/ast/array_decoration.h
@@ -0,0 +1,51 @@
+// Copyright 2020 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.
+
+#ifndef SRC_AST_ARRAY_DECORATION_H_
+#define SRC_AST_ARRAY_DECORATION_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace tint {
+namespace ast {
+
+class StrideDecoration;
+
+/// A decoration attached to an array
+class ArrayDecoration {
+ public:
+ virtual ~ArrayDecoration();
+
+ /// @returns true if this is a stride decoration
+ virtual bool IsStride() const;
+
+ /// @returns the decoration as a stride decoration
+ StrideDecoration* AsStride();
+
+ /// @returns the decoration as a string
+ virtual std::string to_str() const = 0;
+
+ protected:
+ ArrayDecoration();
+};
+
+/// A list of unique array decorations
+using ArrayDecorationList = std::vector<std::unique_ptr<ArrayDecoration>>;
+
+} // namespace ast
+} // namespace tint
+
+#endif // SRC_AST_ARRAY_DECORATION_H_
diff --git a/src/ast/stride_decoration.cc b/src/ast/stride_decoration.cc
new file mode 100644
index 0000000..a68cbcd
--- /dev/null
+++ b/src/ast/stride_decoration.cc
@@ -0,0 +1,33 @@
+// Copyright 2020 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/ast/stride_decoration.h"
+
+namespace tint {
+namespace ast {
+
+StrideDecoration::StrideDecoration(uint32_t stride) : stride_(stride) {}
+
+bool StrideDecoration::IsStride() const {
+ return true;
+}
+
+StrideDecoration::~StrideDecoration() = default;
+
+std::string StrideDecoration::to_str() const {
+ return "stride " + std::to_string(stride_);
+}
+
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/stride_decoration.h b/src/ast/stride_decoration.h
new file mode 100644
index 0000000..a8a9cb2
--- /dev/null
+++ b/src/ast/stride_decoration.h
@@ -0,0 +1,51 @@
+// Copyright 2020 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.
+
+#ifndef SRC_AST_STRIDE_DECORATION_H_
+#define SRC_AST_STRIDE_DECORATION_H_
+
+#include <stddef.h>
+
+#include <string>
+
+#include "src/ast/array_decoration.h"
+
+namespace tint {
+namespace ast {
+
+/// A stride decoration
+class StrideDecoration : public ArrayDecoration {
+ public:
+ /// constructor
+ /// @param stride the stride value
+ explicit StrideDecoration(uint32_t stride);
+ ~StrideDecoration() override;
+
+ /// @returns true if this is a stride decoration
+ bool IsStride() const override;
+
+ /// @returns the stride value
+ uint32_t stride() const { return stride_; }
+
+ /// @returns the decoration as a string
+ std::string to_str() const override;
+
+ private:
+ uint32_t stride_;
+};
+
+} // namespace ast
+} // namespace tint
+
+#endif // SRC_AST_STRIDE_DECORATION_H_
diff --git a/src/ast/stride_decoration_test.cc b/src/ast/stride_decoration_test.cc
new file mode 100644
index 0000000..8209c3d
--- /dev/null
+++ b/src/ast/stride_decoration_test.cc
@@ -0,0 +1,37 @@
+// Copyright 2020 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/ast/stride_decoration.h"
+
+#include "gtest/gtest.h"
+
+namespace tint {
+namespace ast {
+namespace {
+
+using StrideDecorationTest = testing::Test;
+
+TEST_F(StrideDecorationTest, Creation) {
+ StrideDecoration d{2};
+ EXPECT_EQ(2u, d.stride());
+}
+
+TEST_F(StrideDecorationTest, Is) {
+ StrideDecoration d{2};
+ EXPECT_TRUE(d.IsStride());
+}
+
+} // namespace
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/struct_decoration.h b/src/ast/struct_decoration.h
index fecea8a..20139ac 100644
--- a/src/ast/struct_decoration.h
+++ b/src/ast/struct_decoration.h
@@ -16,6 +16,7 @@
#define SRC_AST_STRUCT_DECORATION_H_
#include <ostream>
+#include <vector>
namespace tint {
namespace ast {
diff --git a/src/ast/type/array_type.cc b/src/ast/type/array_type.cc
index 683f6aa..71b3861 100644
--- a/src/ast/type/array_type.cc
+++ b/src/ast/type/array_type.cc
@@ -14,6 +14,8 @@
#include "src/ast/type/array_type.h"
+#include "src/ast/stride_decoration.h"
+
namespace tint {
namespace ast {
namespace type {
@@ -31,6 +33,24 @@
return true;
}
+uint32_t ArrayType::array_stride() const {
+ for (const auto& deco : decos_) {
+ if (deco->IsStride()) {
+ return deco->AsStride()->stride();
+ }
+ }
+ return 0;
+}
+
+bool ArrayType::has_array_stride() const {
+ for (const auto& deco : decos_) {
+ if (deco->IsStride()) {
+ return true;
+ }
+ }
+ return false;
+}
+
std::string ArrayType::type_name() const {
assert(subtype_);
@@ -38,7 +58,7 @@
if (!IsRuntimeArray())
type_name += "_" + std::to_string(size_);
if (has_array_stride())
- type_name += "_stride_" + std::to_string(array_stride_);
+ type_name += "_stride_" + std::to_string(array_stride());
return type_name;
}
diff --git a/src/ast/type/array_type.h b/src/ast/type/array_type.h
index e89684c..9a84d1e 100644
--- a/src/ast/type/array_type.h
+++ b/src/ast/type/array_type.h
@@ -19,6 +19,7 @@
#include <string>
+#include "src/ast/array_decoration.h"
#include "src/ast/type/type.h"
namespace tint {
@@ -45,13 +46,18 @@
/// i.e. the size is determined at runtime
bool IsRuntimeArray() const { return size_ == 0; }
- /// Sets the array stride
- /// @param stride the stride to set
- void set_array_stride(uint32_t stride) { array_stride_ = stride; }
+ /// Sets the array decorations
+ /// @param decos the decorations to set
+ void set_decorations(ast::ArrayDecorationList decos) {
+ decos_ = std::move(decos);
+ }
+ /// @returns the array decorations
+ const ArrayDecorationList& decorations() const { return decos_; }
+
/// @returns the array stride or 0 if none set.
- uint32_t array_stride() const { return array_stride_; }
+ uint32_t array_stride() const;
/// @returns true if the array has a stride set
- bool has_array_stride() const { return array_stride_ != 0; }
+ bool has_array_stride() const;
/// @returns the array type
Type* type() const { return subtype_; }
@@ -64,7 +70,7 @@
private:
Type* subtype_ = nullptr;
uint32_t size_ = 0;
- uint32_t array_stride_ = 0;
+ ast::ArrayDecorationList decos_;
};
} // namespace type
diff --git a/src/ast/type/array_type_test.cc b/src/ast/type/array_type_test.cc
index 4783330..b76cb08 100644
--- a/src/ast/type/array_type_test.cc
+++ b/src/ast/type/array_type_test.cc
@@ -15,6 +15,7 @@
#include "src/ast/type/array_type.h"
#include "gtest/gtest.h"
+#include "src/ast/stride_decoration.h"
#include "src/ast/type/i32_type.h"
#include "src/ast/type/u32_type.h"
@@ -75,8 +76,11 @@
TEST_F(ArrayTypeTest, TypeName_WithStride) {
I32Type i32;
+ ArrayDecorationList decos;
+ decos.push_back(std::make_unique<StrideDecoration>(16));
+
ArrayType arr{&i32, 3};
- arr.set_array_stride(16);
+ arr.set_decorations(std::move(decos));
EXPECT_EQ(arr.type_name(), "__array__i32_3_stride_16");
}
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index 92c6a29..0861b24 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -45,6 +45,7 @@
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/set_decoration.h"
#include "src/ast/sint_literal.h"
+#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
#include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h"
@@ -772,7 +773,9 @@
return Fail() << "invalid array type ID " << type_id
<< ": multiple ArrayStride decorations";
}
- ast_type->set_array_stride(stride);
+ ast::ArrayDecorationList decos;
+ decos.push_back(std::make_unique<ast::StrideDecoration>(stride));
+ ast_type->set_decorations(std::move(decos));
} else {
return Fail() << "invalid array type ID " << type_id
<< ": unknown decoration "
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index 032c14c..362219c 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -41,6 +41,7 @@
#include "src/ast/set_decoration.h"
#include "src/ast/sint_literal.h"
#include "src/ast/stage_decoration.h"
+#include "src/ast/stride_decoration.h"
#include "src/ast/struct_member_offset_decoration.h"
#include "src/ast/switch_statement.h"
#include "src/ast/type/alias_type.h"
@@ -1105,9 +1106,9 @@
// | VEC3 LESS_THAN type_decl GREATER_THAN
// | VEC4 LESS_THAN type_decl GREATER_THAN
// | PTR LESS_THAN storage_class, type_decl GREATER_THAN
-// | array_decoration_list? ARRAY LESS_THAN type_decl COMMA
+// | array_decoration_list* ARRAY LESS_THAN type_decl COMMA
// INT_LITERAL GREATER_THAN
-// | array_decoration_list? ARRAY LESS_THAN type_decl
+// | array_decoration_list* ARRAY LESS_THAN type_decl
// GREATER_THAN
// | MAT2x2 LESS_THAN type_decl GREATER_THAN
// | MAT2x3 LESS_THAN type_decl GREATER_THAN
@@ -1153,19 +1154,28 @@
return type_decl_pointer(t);
}
- auto deco = array_decoration_list();
+ ast::ArrayDecorationList decos;
+ for (;;) {
+ size_t s = decos.size();
+ if (!array_decoration_list(decos)) {
+ return nullptr;
+ }
+ if (decos.size() == s) {
+ break;
+ }
+ }
if (has_error()) {
return nullptr;
}
- if (deco != 0) {
+ if (!decos.empty()) {
t = peek();
}
- if (deco != 0 && !t.IsArray()) {
+ if (!decos.empty() && !t.IsArray()) {
set_error(t, "found array decoration but no array");
return nullptr;
}
if (t.IsArray()) {
- return type_decl_array(t, deco);
+ return type_decl_array(t, std::move(decos));
}
if (t.IsMat2x2() || t.IsMat2x3() || t.IsMat2x4() || t.IsMat3x2() ||
t.IsMat3x3() || t.IsMat3x4() || t.IsMat4x2() || t.IsMat4x3() ||
@@ -1258,7 +1268,8 @@
std::make_unique<ast::type::VectorType>(subtype, count));
}
-ast::type::Type* ParserImpl::type_decl_array(Token t, uint32_t stride) {
+ast::type::Type* ParserImpl::type_decl_array(Token t,
+ ast::ArrayDecorationList decos) {
next(); // Consume the peek
t = next();
@@ -1296,9 +1307,7 @@
}
auto ty = std::make_unique<ast::type::ArrayType>(subtype, size);
- if (stride != 0) {
- ty->set_array_stride(stride);
- }
+ ty->set_decorations(std::move(decos));
return ctx_.type_mgr().Get(std::move(ty));
}
@@ -1309,48 +1318,62 @@
//
// As there is currently only one decoration I'm combining these for now.
// we can split apart later if needed.
-uint32_t ParserImpl::array_decoration_list() {
+bool ParserImpl::array_decoration_list(ast::ArrayDecorationList& decos) {
auto t = peek();
if (!t.IsAttrLeft()) {
- return 0;
+ return true;
}
t = peek(1);
if (!t.IsStride()) {
- return 0;
+ return true;
}
next(); // consume the peek of [[
- next(); // consume the peek of stride
- t = next();
- if (!t.IsParenLeft()) {
- set_error(t, "missing ( for stride attribute");
- return 0;
- }
+ for (;;) {
+ t = next();
+ if (!t.IsStride()) {
+ set_error(t, "unknown array decoration");
+ return false;
+ }
- t = next();
- if (!t.IsSintLiteral()) {
- set_error(t, "missing value for stride decoration");
- return 0;
- }
- if (t.to_i32() < 0) {
- set_error(t, "invalid stride value: " + t.to_str());
- return 0;
- }
- uint32_t stride = static_cast<uint32_t>(t.to_i32());
+ t = next();
+ if (!t.IsParenLeft()) {
+ set_error(t, "missing ( for stride attribute");
+ return false;
+ }
- t = next();
- if (!t.IsParenRight()) {
- set_error(t, "missing ) for stride attribute");
- return 0;
+ t = next();
+ if (!t.IsSintLiteral()) {
+ set_error(t, "missing value for stride decoration");
+ return false;
+ }
+ if (t.to_i32() < 0) {
+ set_error(t, "invalid stride value: " + t.to_str());
+ return false;
+ }
+ uint32_t stride = static_cast<uint32_t>(t.to_i32());
+ decos.push_back(std::make_unique<ast::StrideDecoration>(stride));
+
+ t = next();
+ if (!t.IsParenRight()) {
+ set_error(t, "missing ) for stride attribute");
+ return false;
+ }
+
+ t = peek();
+ if (!t.IsComma()) {
+ break;
+ }
+ next(); // Consume the peek
}
t = next();
if (!t.IsAttrRight()) {
set_error(t, "missing ]] for array decoration");
- return 0;
+ return false;
}
- return stride;
+ return true;
}
ast::type::Type* ParserImpl::type_decl_matrix(Token t) {
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index 2d53423..b4a1bbc 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -21,6 +21,7 @@
#include <unordered_map>
#include <utility>
+#include "src/ast/array_decoration.h"
#include "src/ast/assignment_statement.h"
#include "src/ast/builtin.h"
#include "src/ast/call_statement.h"
@@ -172,8 +173,8 @@
std::unique_ptr<ast::StructMember> struct_member();
/// Parses a `struct_member_decoration_decl` grammar element, appending newly
/// parsed decorations to the end of |decos|.
- /// @params decos the decoration list
- /// @returns the list of decorations
+ /// @param decos the decoration list
+ /// @returns true if parsing was successful.
bool struct_member_decoration_decl(ast::StructMemberDecorationList& decos);
/// Parses a `struct_member_decoration` grammar element
/// @returns the decoration or nullptr if none found
@@ -395,8 +396,8 @@
private:
ast::type::Type* type_decl_pointer(Token t);
ast::type::Type* type_decl_vector(Token t);
- ast::type::Type* type_decl_array(Token t, uint32_t stride);
- uint32_t array_decoration_list();
+ ast::type::Type* type_decl_array(Token t, ast::ArrayDecorationList decos);
+ bool array_decoration_list(ast::ArrayDecorationList& decos);
ast::type::Type* type_decl_matrix(Token t);
std::unique_ptr<ast::ConstructorExpression> const_expr_internal(
diff --git a/src/reader/wgsl/parser_impl_type_decl_test.cc b/src/reader/wgsl/parser_impl_type_decl_test.cc
index b4c96aa..f384803 100644
--- a/src/reader/wgsl/parser_impl_type_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_type_decl_test.cc
@@ -13,6 +13,7 @@
// limitations under the License.
#include "gtest/gtest.h"
+#include "src/ast/stride_decoration.h"
#include "src/ast/type/alias_type.h"
#include "src/ast/type/array_type.h"
#include "src/ast/type/bool_type.h"
@@ -423,6 +424,44 @@
EXPECT_EQ(a->array_stride(), 16u);
}
+TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_OneBlock) {
+ auto* p = parser("[[stride(16), stride(32)]] array<f32>");
+ auto* t = p->type_decl();
+ ASSERT_NE(t, nullptr) << p->error();
+ ASSERT_FALSE(p->has_error());
+ ASSERT_TRUE(t->IsArray());
+
+ auto* a = t->AsArray();
+ ASSERT_TRUE(a->IsRuntimeArray());
+ ASSERT_TRUE(a->type()->IsF32());
+
+ auto& decos = a->decorations();
+ ASSERT_EQ(decos.size(), 2u);
+ EXPECT_TRUE(decos[0]->IsStride());
+ EXPECT_EQ(decos[0]->AsStride()->stride(), 16u);
+ EXPECT_TRUE(decos[1]->IsStride());
+ EXPECT_EQ(decos[1]->AsStride()->stride(), 32u);
+}
+
+TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_MultipleBlocks) {
+ auto* p = parser("[[stride(16)]] [[stride(32)]] array<f32>");
+ auto* t = p->type_decl();
+ ASSERT_NE(t, nullptr) << p->error();
+ ASSERT_FALSE(p->has_error());
+ ASSERT_TRUE(t->IsArray());
+
+ auto* a = t->AsArray();
+ ASSERT_TRUE(a->IsRuntimeArray());
+ ASSERT_TRUE(a->type()->IsF32());
+
+ auto& decos = a->decorations();
+ ASSERT_EQ(decos.size(), 2u);
+ EXPECT_TRUE(decos[0]->IsStride());
+ EXPECT_EQ(decos[0]->AsStride()->stride(), 16u);
+ EXPECT_TRUE(decos[1]->IsStride());
+ EXPECT_EQ(decos[1]->AsStride()->stride(), 32u);
+}
+
TEST_F(ParserImplTest, TypeDecl_Array_Decoration_MissingArray) {
auto* p = parser("[[stride(16)]] f32");
auto* t = p->type_decl();
diff --git a/src/transform/vertex_pulling_transform.cc b/src/transform/vertex_pulling_transform.cc
index 5e4d7ce..303a062 100644
--- a/src/transform/vertex_pulling_transform.cc
+++ b/src/transform/vertex_pulling_transform.cc
@@ -21,6 +21,7 @@
#include "src/ast/decorated_variable.h"
#include "src/ast/member_accessor_expression.h"
#include "src/ast/scalar_constructor_expression.h"
+#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
#include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h"
@@ -215,7 +216,10 @@
// TODO(idanr): Make this readonly https://github.com/gpuweb/gpuweb/issues/935
// The array inside the struct definition
auto internal_array = std::make_unique<ast::type::ArrayType>(GetU32Type());
- internal_array->set_array_stride(4u);
+ ast::ArrayDecorationList ary_decos;
+ ary_decos.push_back(std::make_unique<ast::StrideDecoration>(4u));
+ internal_array->set_decorations(std::move(ary_decos));
+
auto* internal_array_type = ctx_->type_mgr().Get(std::move(internal_array));
// Creating the struct type
diff --git a/src/writer/hlsl/generator_impl_member_accessor_test.cc b/src/writer/hlsl/generator_impl_member_accessor_test.cc
index 040804c..a55bedd 100644
--- a/src/writer/hlsl/generator_impl_member_accessor_test.cc
+++ b/src/writer/hlsl/generator_impl_member_accessor_test.cc
@@ -24,6 +24,7 @@
#include "src/ast/module.h"
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/sint_literal.h"
+#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
#include "src/ast/struct_member.h"
#include "src/ast/struct_member_offset_decoration.h"
@@ -525,7 +526,9 @@
ast::type::F32Type f32;
ast::type::I32Type i32;
ast::type::ArrayType ary(&i32, 5);
- ary.set_array_stride(4);
+ ast::ArrayDecorationList decos;
+ decos.push_back(std::make_unique<ast::StrideDecoration>(4));
+ ary.set_decorations(std::move(decos));
ast::StructMemberList members;
ast::StructMemberDecorationList a_deco;
@@ -573,7 +576,9 @@
ast::type::F32Type f32;
ast::type::I32Type i32;
ast::type::ArrayType ary(&i32, 5);
- ary.set_array_stride(4);
+ ast::ArrayDecorationList decos;
+ decos.push_back(std::make_unique<ast::StrideDecoration>(4));
+ ary.set_decorations(std::move(decos));
ast::StructMemberList members;
ast::StructMemberDecorationList a_deco;
@@ -684,7 +689,9 @@
ast::type::F32Type f32;
ast::type::I32Type i32;
ast::type::ArrayType ary(&i32, 5);
- ary.set_array_stride(4);
+ ast::ArrayDecorationList decos;
+ decos.push_back(std::make_unique<ast::StrideDecoration>(4));
+ ary.set_decorations(std::move(decos));
ast::StructMemberList members;
ast::StructMemberDecorationList a_deco;
@@ -937,7 +944,9 @@
data.set_name("Data");
ast::type::ArrayType ary(&data, 4);
- ary.set_array_stride(32);
+ ast::ArrayDecorationList decos;
+ decos.push_back(std::make_unique<ast::StrideDecoration>(32));
+ ary.set_decorations(std::move(decos));
deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0));
members.push_back(
@@ -1010,7 +1019,9 @@
data.set_name("Data");
ast::type::ArrayType ary(&data, 4);
- ary.set_array_stride(32);
+ ast::ArrayDecorationList decos;
+ decos.push_back(std::make_unique<ast::StrideDecoration>(32));
+ ary.set_decorations(std::move(decos));
deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0));
members.push_back(
@@ -1086,7 +1097,9 @@
data.set_name("Data");
ast::type::ArrayType ary(&data, 4);
- ary.set_array_stride(32);
+ ast::ArrayDecorationList decos;
+ decos.push_back(std::make_unique<ast::StrideDecoration>(32));
+ ary.set_decorations(std::move(decos));
deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0));
members.push_back(
@@ -1161,7 +1174,9 @@
data.set_name("Data");
ast::type::ArrayType ary(&data, 4);
- ary.set_array_stride(32);
+ ast::ArrayDecorationList decos;
+ decos.push_back(std::make_unique<ast::StrideDecoration>(32));
+ ary.set_decorations(std::move(decos));
deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0));
members.push_back(
@@ -1237,7 +1252,9 @@
data.set_name("Data");
ast::type::ArrayType ary(&data, 4);
- ary.set_array_stride(32);
+ ast::ArrayDecorationList decos;
+ decos.push_back(std::make_unique<ast::StrideDecoration>(32));
+ ary.set_decorations(std::move(decos));
deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0));
members.push_back(
@@ -1329,7 +1346,9 @@
data.set_name("Data");
ast::type::ArrayType ary(&data, 4);
- ary.set_array_stride(32);
+ ast::ArrayDecorationList decos;
+ decos.push_back(std::make_unique<ast::StrideDecoration>(32));
+ ary.set_decorations(std::move(decos));
deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0));
members.push_back(
diff --git a/src/writer/spirv/builder_type_test.cc b/src/writer/spirv/builder_type_test.cc
index 3a7e84d..7c2ef16 100644
--- a/src/writer/spirv/builder_type_test.cc
+++ b/src/writer/spirv/builder_type_test.cc
@@ -16,6 +16,7 @@
#include "gtest/gtest.h"
#include "src/ast/identifier_expression.h"
+#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
#include "src/ast/struct_member.h"
#include "src/ast/struct_member_offset_decoration.h"
@@ -128,8 +129,12 @@
TEST_F(BuilderTest_Type, GenerateArray_WithStride) {
ast::type::I32Type i32;
+
+ ast::ArrayDecorationList decos;
+ decos.push_back(std::make_unique<ast::StrideDecoration>(16u));
+
ast::type::ArrayType ary(&i32, 4);
- ary.set_array_stride(16u);
+ ary.set_decorations(std::move(decos));
ast::Module mod;
Builder b(&mod);
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index 187d06e..ae92972 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -46,6 +46,7 @@
#include "src/ast/sint_literal.h"
#include "src/ast/stage_decoration.h"
#include "src/ast/statement.h"
+#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
#include "src/ast/struct_member.h"
#include "src/ast/struct_member_offset_decoration.h"
@@ -395,8 +396,10 @@
} else if (type->IsArray()) {
auto* ary = type->AsArray();
- if (ary->has_array_stride()) {
- out_ << "[[stride(" << ary->array_stride() << ")]] ";
+ for (const auto& deco : ary->decorations()) {
+ if (deco->IsStride()) {
+ out_ << "[[stride(" << deco->AsStride()->stride() << ")]] ";
+ }
}
out_ << "array<";
diff --git a/src/writer/wgsl/generator_impl_type_test.cc b/src/writer/wgsl/generator_impl_type_test.cc
index d7360b3..456c478 100644
--- a/src/writer/wgsl/generator_impl_type_test.cc
+++ b/src/writer/wgsl/generator_impl_type_test.cc
@@ -13,6 +13,7 @@
// limitations under the License.
#include "gtest/gtest.h"
+#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
#include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h"
@@ -60,16 +61,33 @@
EXPECT_EQ(g.result(), "array<bool, 4>");
}
-TEST_F(WgslGeneratorImplTest, EmitType_Array_WithStride) {
+TEST_F(WgslGeneratorImplTest, EmitType_Array_Decoration) {
ast::type::BoolType b;
+ ast::ArrayDecorationList decos;
+ decos.push_back(std::make_unique<ast::StrideDecoration>(16u));
+
ast::type::ArrayType a(&b, 4);
- a.set_array_stride(16);
+ a.set_decorations(std::move(decos));
GeneratorImpl g;
ASSERT_TRUE(g.EmitType(&a)) << g.error();
EXPECT_EQ(g.result(), "[[stride(16)]] array<bool, 4>");
}
+TEST_F(WgslGeneratorImplTest, EmitType_Array_MultipleDecorations) {
+ ast::type::BoolType b;
+ ast::ArrayDecorationList decos;
+ decos.push_back(std::make_unique<ast::StrideDecoration>(16u));
+ decos.push_back(std::make_unique<ast::StrideDecoration>(32u));
+
+ ast::type::ArrayType a(&b, 4);
+ a.set_decorations(std::move(decos));
+
+ GeneratorImpl g;
+ ASSERT_TRUE(g.EmitType(&a)) << g.error();
+ EXPECT_EQ(g.result(), "[[stride(16)]] [[stride(32)]] array<bool, 4>");
+}
+
TEST_F(WgslGeneratorImplTest, EmitType_RuntimeArray) {
ast::type::BoolType b;
ast::type::ArrayType a(&b);