From bfd81096a5e641a24f520afca422674c76dde57d Mon Sep 17 00:00:00 2001 From: dan sinclair Date: Tue, 27 Oct 2020 18:50:59 +0000 Subject: [PATCH] [ast] Add AccessControlType. This CL adds the AST for an AccessControlType. This type contains an access control (ReadOnly, WriteOnly, or ReadWrite) along with another type pointer. Bug: tint:208 tint:108 Change-Id: I2eed03f8760239f7e71dc2edd4a19a7c1661746e Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31060 Reviewed-by: David Neto Reviewed-by: Ryan Harrison Commit-Queue: David Neto --- BUILD.gn | 3 + src/CMakeLists.txt | 3 + src/ast/type/access_control_type.cc | 57 ++++++++++++ src/ast/type/access_control_type.h | 74 +++++++++++++++ src/ast/type/access_control_type_test.cc | 89 +++++++++++++++++++ src/ast/type/alias_type_test.cc | 1 + src/ast/type/array_type_test.cc | 1 + src/ast/type/bool_type_test.cc | 1 + src/ast/type/depth_texture_type_test.cc | 1 + src/ast/type/f32_type_test.cc | 1 + src/ast/type/i32_type_test.cc | 1 + src/ast/type/matrix_type_test.cc | 1 + .../type/multisampled_texture_type_test.cc | 1 + src/ast/type/pointer_type_test.cc | 1 + src/ast/type/sampled_texture_type_test.cc | 1 + src/ast/type/sampler_type_test.cc | 1 + src/ast/type/storage_texture_type_test.cc | 1 + src/ast/type/struct_type_test.cc | 1 + src/ast/type/type.cc | 15 ++++ src/ast/type/type.h | 7 ++ src/ast/type/u32_type_test.cc | 1 + src/ast/type/vector_type_test.cc | 1 + 22 files changed, 263 insertions(+) create mode 100644 src/ast/type/access_control_type.cc create mode 100644 src/ast/type/access_control_type.h create mode 100644 src/ast/type/access_control_type_test.cc diff --git a/BUILD.gn b/BUILD.gn index 6881312c0e..103c94169b 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -319,6 +319,8 @@ source_set("libtint_core_src") { "src/ast/struct_member_offset_decoration.h", "src/ast/switch_statement.cc", "src/ast/switch_statement.h", + "src/ast/type/access_control_type.cc", + "src/ast/type/access_control_type.h", "src/ast/type/alias_type.cc", "src/ast/type/alias_type.h", "src/ast/type/array_type.cc", @@ -740,6 +742,7 @@ source_set("tint_unittests_core_src") { "src/ast/struct_member_test.cc", "src/ast/struct_test.cc", "src/ast/switch_statement_test.cc", + "src/ast/type/access_control_type_test.cc", "src/ast/type/alias_type_test.cc", "src/ast/type/array_type_test.cc", "src/ast/type/bool_type_test.cc", diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 13a2937111..7a04fc7333 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -142,6 +142,8 @@ set(TINT_LIB_SRCS ast/switch_statement.h ast/type_constructor_expression.h ast/type_constructor_expression.cc + ast/type/access_control_type.cc + ast/type/access_control_type.h ast/type/alias_type.cc ast/type/alias_type.h ast/type/array_type.cc @@ -350,6 +352,7 @@ set(TINT_TEST_SRCS ast/struct_member_offset_decoration_test.cc ast/struct_test.cc ast/switch_statement_test.cc + ast/type/access_control_type_test.cc ast/type/alias_type_test.cc ast/type/array_type_test.cc ast/type/bool_type_test.cc diff --git a/src/ast/type/access_control_type.cc b/src/ast/type/access_control_type.cc new file mode 100644 index 0000000000..1abae24d70 --- /dev/null +++ b/src/ast/type/access_control_type.cc @@ -0,0 +1,57 @@ +// 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/type/access_control_type.h" + +#include + +namespace tint { +namespace ast { +namespace type { + +AccessControlType::AccessControlType(AccessControl access, Type* subtype) + : access_(access), subtype_(subtype) { + assert(subtype_); + assert(!subtype_->IsAccessControl()); +} + +AccessControlType::~AccessControlType() = default; + +bool AccessControlType::IsAccessControl() const { + return true; +} + +std::string AccessControlType::type_name() const { + std::string name = "__access_control_"; + switch (access_) { + case AccessControl::kReadOnly: + name += "read_only"; + break; + case AccessControl::kWriteOnly: + name += "write_only"; + break; + case AccessControl::kReadWrite: + name += "read_write"; + break; + } + return name + subtype_->type_name(); +} + +uint64_t AccessControlType::MinBufferBindingSize() const { + return subtype_->MinBufferBindingSize(); +} + +} // namespace type +} // namespace ast +} // namespace tint diff --git a/src/ast/type/access_control_type.h b/src/ast/type/access_control_type.h new file mode 100644 index 0000000000..5e696fd4ae --- /dev/null +++ b/src/ast/type/access_control_type.h @@ -0,0 +1,74 @@ +// 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_TYPE_ACCESS_CONTROL_TYPE_H_ +#define SRC_AST_TYPE_ACCESS_CONTROL_TYPE_H_ + +#include "src/ast/type/type.h" + +namespace tint { +namespace ast { +namespace type { + +/// The access control settings +enum class AccessControl { + /// Read only + kReadOnly = 0, + /// Write only + kWriteOnly, + /// Read write + kReadWrite +}; + +/// An access control type. Holds an access setting and pointer to another type. +class AccessControlType : public Type { + public: + /// Constructor + /// @param access the access control setting + /// @param subtype the access controlled type + AccessControlType(AccessControl access, Type* subtype); + /// Move constructor + AccessControlType(AccessControlType&&) = default; + ~AccessControlType() override; + + /// @returns true if the type is an access control type + bool IsAccessControl() const override; + + /// @returns true if the access control is read only + bool IsReadOnly() const { return access_ == AccessControl::kReadOnly; } + /// @returns true if the access control is write only + bool IsWriteOnly() const { return access_ == AccessControl::kWriteOnly; } + /// @returns true if the access control is read/write + bool IsReadWrite() const { return access_ == AccessControl::kReadWrite; } + + /// @returns the subtype type + Type* type() const { return subtype_; } + + /// @returns the name for this type + std::string type_name() const override; + + /// @returns minimum size required for this type, in bytes. + /// 0 for non-host shareable types. + uint64_t MinBufferBindingSize() const override; + + private: + AccessControl access_ = AccessControl::kReadOnly; + Type* subtype_ = nullptr; +}; + +} // namespace type +} // namespace ast +} // namespace tint + +#endif // SRC_AST_TYPE_ACCESS_CONTROL_TYPE_H_ diff --git a/src/ast/type/access_control_type_test.cc b/src/ast/type/access_control_type_test.cc new file mode 100644 index 0000000000..0f31121d0b --- /dev/null +++ b/src/ast/type/access_control_type_test.cc @@ -0,0 +1,89 @@ +// 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/type/access_control_type.h" + +#include "gtest/gtest.h" +#include "src/ast/storage_class.h" +#include "src/ast/type/i32_type.h" +#include "src/ast/type/pointer_type.h" +#include "src/ast/type/u32_type.h" + +namespace tint { +namespace ast { +namespace type { +namespace { + +using AccessControlTypeTest = testing::Test; + +TEST_F(AccessControlTypeTest, Create) { + U32Type u32; + AccessControlType a{AccessControl::kReadWrite, &u32}; + EXPECT_TRUE(a.IsReadWrite()); + EXPECT_EQ(a.type(), &u32); +} + +TEST_F(AccessControlTypeTest, Is) { + I32Type i32; + + AccessControlType at{AccessControl::kReadOnly, &i32}; + EXPECT_TRUE(at.IsAccessControl()); + EXPECT_FALSE(at.IsAlias()); + EXPECT_FALSE(at.IsArray()); + EXPECT_FALSE(at.IsBool()); + EXPECT_FALSE(at.IsF32()); + EXPECT_FALSE(at.IsI32()); + EXPECT_FALSE(at.IsMatrix()); + EXPECT_FALSE(at.IsPointer()); + EXPECT_FALSE(at.IsSampler()); + EXPECT_FALSE(at.IsStruct()); + EXPECT_FALSE(at.IsTexture()); + EXPECT_FALSE(at.IsU32()); + EXPECT_FALSE(at.IsVector()); +} + +TEST_F(AccessControlTypeTest, AccessRead) { + I32Type i32; + AccessControlType at{AccessControl::kReadOnly, &i32}; + EXPECT_TRUE(at.IsReadOnly()); + EXPECT_FALSE(at.IsWriteOnly()); + EXPECT_FALSE(at.IsReadWrite()); + + EXPECT_EQ(at.type_name(), "__access_control_read_only__i32"); +} + +TEST_F(AccessControlTypeTest, AccessWrite) { + I32Type i32; + AccessControlType at{AccessControl::kWriteOnly, &i32}; + EXPECT_FALSE(at.IsReadOnly()); + EXPECT_TRUE(at.IsWriteOnly()); + EXPECT_FALSE(at.IsReadWrite()); + + EXPECT_EQ(at.type_name(), "__access_control_write_only__i32"); +} + +TEST_F(AccessControlTypeTest, AccessReadWrite) { + I32Type i32; + AccessControlType at{AccessControl::kReadWrite, &i32}; + EXPECT_FALSE(at.IsReadOnly()); + EXPECT_FALSE(at.IsWriteOnly()); + EXPECT_TRUE(at.IsReadWrite()); + + EXPECT_EQ(at.type_name(), "__access_control_read_write__i32"); +} + +} // namespace +} // namespace type +} // namespace ast +} // namespace tint diff --git a/src/ast/type/alias_type_test.cc b/src/ast/type/alias_type_test.cc index ac021ae03b..76b547a4c7 100644 --- a/src/ast/type/alias_type_test.cc +++ b/src/ast/type/alias_type_test.cc @@ -38,6 +38,7 @@ TEST_F(AliasTypeTest, Is) { I32Type i32; AliasType at{"a", &i32}; + EXPECT_FALSE(at.IsAccessControl()); EXPECT_TRUE(at.IsAlias()); EXPECT_FALSE(at.IsArray()); EXPECT_FALSE(at.IsBool()); diff --git a/src/ast/type/array_type_test.cc b/src/ast/type/array_type_test.cc index b76cb081ee..71b4343983 100644 --- a/src/ast/type/array_type_test.cc +++ b/src/ast/type/array_type_test.cc @@ -48,6 +48,7 @@ TEST_F(ArrayTypeTest, Is) { I32Type i32; ArrayType arr{&i32, 3}; + EXPECT_FALSE(arr.IsAccessControl()); EXPECT_FALSE(arr.IsAlias()); EXPECT_TRUE(arr.IsArray()); EXPECT_FALSE(arr.IsBool()); diff --git a/src/ast/type/bool_type_test.cc b/src/ast/type/bool_type_test.cc index f3cc9664b4..4bcf4821da 100644 --- a/src/ast/type/bool_type_test.cc +++ b/src/ast/type/bool_type_test.cc @@ -25,6 +25,7 @@ using BoolTypeTest = testing::Test; TEST_F(BoolTypeTest, Is) { BoolType b; + EXPECT_FALSE(b.IsAccessControl()); EXPECT_FALSE(b.IsAlias()); EXPECT_FALSE(b.IsArray()); EXPECT_TRUE(b.IsBool()); diff --git a/src/ast/type/depth_texture_type_test.cc b/src/ast/type/depth_texture_type_test.cc index 6e79d414de..e8b5d59937 100644 --- a/src/ast/type/depth_texture_type_test.cc +++ b/src/ast/type/depth_texture_type_test.cc @@ -25,6 +25,7 @@ using DepthTextureTypeTest = testing::Test; TEST_F(DepthTextureTypeTest, Is) { DepthTextureType d(TextureDimension::kCube); + EXPECT_FALSE(d.IsAccessControl()); EXPECT_FALSE(d.IsAlias()); EXPECT_FALSE(d.IsArray()); EXPECT_FALSE(d.IsBool()); diff --git a/src/ast/type/f32_type_test.cc b/src/ast/type/f32_type_test.cc index fc42b00840..88bef620c4 100644 --- a/src/ast/type/f32_type_test.cc +++ b/src/ast/type/f32_type_test.cc @@ -25,6 +25,7 @@ using F32TypeTest = testing::Test; TEST_F(F32TypeTest, Is) { F32Type f; + EXPECT_FALSE(f.IsAccessControl()); EXPECT_FALSE(f.IsAlias()); EXPECT_FALSE(f.IsArray()); EXPECT_FALSE(f.IsBool()); diff --git a/src/ast/type/i32_type_test.cc b/src/ast/type/i32_type_test.cc index f69958d8ee..12e0795f2d 100644 --- a/src/ast/type/i32_type_test.cc +++ b/src/ast/type/i32_type_test.cc @@ -25,6 +25,7 @@ using I32TypeTest = testing::Test; TEST_F(I32TypeTest, Is) { I32Type i; + EXPECT_FALSE(i.IsAccessControl()); EXPECT_FALSE(i.IsAlias()); EXPECT_FALSE(i.IsArray()); EXPECT_FALSE(i.IsBool()); diff --git a/src/ast/type/matrix_type_test.cc b/src/ast/type/matrix_type_test.cc index c659e40fb7..0ab07aca83 100644 --- a/src/ast/type/matrix_type_test.cc +++ b/src/ast/type/matrix_type_test.cc @@ -35,6 +35,7 @@ TEST_F(MatrixTypeTest, Creation) { TEST_F(MatrixTypeTest, Is) { I32Type i32; MatrixType m{&i32, 2, 3}; + EXPECT_FALSE(m.IsAccessControl()); EXPECT_FALSE(m.IsAlias()); EXPECT_FALSE(m.IsArray()); EXPECT_FALSE(m.IsBool()); diff --git a/src/ast/type/multisampled_texture_type_test.cc b/src/ast/type/multisampled_texture_type_test.cc index c50cef9cbf..4d3d059603 100644 --- a/src/ast/type/multisampled_texture_type_test.cc +++ b/src/ast/type/multisampled_texture_type_test.cc @@ -27,6 +27,7 @@ using MultisampledTextureTypeTest = testing::Test; TEST_F(MultisampledTextureTypeTest, Is) { F32Type f32; MultisampledTextureType s(TextureDimension::kCube, &f32); + EXPECT_FALSE(s.IsAccessControl()); EXPECT_FALSE(s.IsAlias()); EXPECT_FALSE(s.IsArray()); EXPECT_FALSE(s.IsBool()); diff --git a/src/ast/type/pointer_type_test.cc b/src/ast/type/pointer_type_test.cc index 0d825f58b9..9f10ac92d9 100644 --- a/src/ast/type/pointer_type_test.cc +++ b/src/ast/type/pointer_type_test.cc @@ -34,6 +34,7 @@ TEST_F(PointerTypeTest, Creation) { TEST_F(PointerTypeTest, Is) { I32Type i32; PointerType p{&i32, StorageClass::kFunction}; + EXPECT_FALSE(p.IsAccessControl()); EXPECT_FALSE(p.IsAlias()); EXPECT_FALSE(p.IsArray()); EXPECT_FALSE(p.IsBool()); diff --git a/src/ast/type/sampled_texture_type_test.cc b/src/ast/type/sampled_texture_type_test.cc index ce10639d61..a464459be0 100644 --- a/src/ast/type/sampled_texture_type_test.cc +++ b/src/ast/type/sampled_texture_type_test.cc @@ -27,6 +27,7 @@ using SampledTextureTypeTest = testing::Test; TEST_F(SampledTextureTypeTest, Is) { F32Type f32; SampledTextureType s(TextureDimension::kCube, &f32); + EXPECT_FALSE(s.IsAccessControl()); EXPECT_FALSE(s.IsAlias()); EXPECT_FALSE(s.IsArray()); EXPECT_FALSE(s.IsBool()); diff --git a/src/ast/type/sampler_type_test.cc b/src/ast/type/sampler_type_test.cc index 60921eda07..34f835cec7 100644 --- a/src/ast/type/sampler_type_test.cc +++ b/src/ast/type/sampler_type_test.cc @@ -36,6 +36,7 @@ TEST_F(SamplerTypeTest, Creation_ComparisonSampler) { TEST_F(SamplerTypeTest, Is) { SamplerType s{SamplerKind::kSampler}; + EXPECT_FALSE(s.IsAccessControl()); EXPECT_FALSE(s.IsAlias()); EXPECT_FALSE(s.IsArray()); EXPECT_FALSE(s.IsBool()); diff --git a/src/ast/type/storage_texture_type_test.cc b/src/ast/type/storage_texture_type_test.cc index bc0f5032d3..bbc999bf3c 100644 --- a/src/ast/type/storage_texture_type_test.cc +++ b/src/ast/type/storage_texture_type_test.cc @@ -29,6 +29,7 @@ using StorageTextureTypeTest = testing::Test; TEST_F(StorageTextureTypeTest, Is) { StorageTextureType s(TextureDimension::k2dArray, StorageAccess::kRead, ImageFormat::kRgba32Float); + EXPECT_FALSE(s.IsAccessControl()); EXPECT_FALSE(s.IsAlias()); EXPECT_FALSE(s.IsArray()); EXPECT_FALSE(s.IsBool()); diff --git a/src/ast/type/struct_type_test.cc b/src/ast/type/struct_type_test.cc index 3b11b4aaff..775c9e95c2 100644 --- a/src/ast/type/struct_type_test.cc +++ b/src/ast/type/struct_type_test.cc @@ -36,6 +36,7 @@ TEST_F(StructTypeTest, Creation) { TEST_F(StructTypeTest, Is) { auto impl = std::make_unique(); StructType s{"S", std::move(impl)}; + EXPECT_FALSE(s.IsAccessControl()); EXPECT_FALSE(s.IsAlias()); EXPECT_FALSE(s.IsArray()); EXPECT_FALSE(s.IsBool()); diff --git a/src/ast/type/type.cc b/src/ast/type/type.cc index ee8fa423fb..7f596afa30 100644 --- a/src/ast/type/type.cc +++ b/src/ast/type/type.cc @@ -16,6 +16,7 @@ #include +#include "src/ast/type/access_control_type.h" #include "src/ast/type/alias_type.h" #include "src/ast/type/array_type.h" #include "src/ast/type/bool_type.h" @@ -57,6 +58,10 @@ Type* Type::UnwrapAliasPtrAlias() { return UnwrapAliasesIfNeeded()->UnwrapPtrIfNeeded()->UnwrapAliasesIfNeeded(); } +bool Type::IsAccessControl() const { + return false; +} + bool Type::IsAlias() const { return false; } @@ -157,6 +162,11 @@ bool Type::is_integer_scalar_or_vector() { return is_unsigned_scalar_or_vector() || is_signed_scalar_or_vector(); } +const AccessControlType* Type::AsAccessControl() const { + assert(IsAccessControl()); + return static_cast(this); +} + const AliasType* Type::AsAlias() const { assert(IsAlias()); return static_cast(this); @@ -222,6 +232,11 @@ const VoidType* Type::AsVoid() const { return static_cast(this); } +AccessControlType* Type::AsAccessControl() { + assert(IsAccessControl()); + return static_cast(this); +} + AliasType* Type::AsAlias() { assert(IsAlias()); return static_cast(this); diff --git a/src/ast/type/type.h b/src/ast/type/type.h index aabde8d569..ff02f281f4 100644 --- a/src/ast/type/type.h +++ b/src/ast/type/type.h @@ -21,6 +21,7 @@ namespace tint { namespace ast { namespace type { +class AccessControlType; class AliasType; class ArrayType; class BoolType; @@ -42,6 +43,8 @@ class Type { Type(Type&&) = default; virtual ~Type(); + /// @returns true if the type is an access control type + virtual bool IsAccessControl() const; /// @returns true if the type is an alias type virtual bool IsAlias() const; /// @returns true if the type is an array type @@ -117,6 +120,8 @@ class Type { /// @returns true if this type is an integer scalar or vector bool is_integer_scalar_or_vector(); + /// @returns the type as an access control type + const AccessControlType* AsAccessControl() const; /// @returns the type as an alias type const AliasType* AsAlias() const; /// @returns the type as an array type @@ -144,6 +149,8 @@ class Type { /// @returns the type as a void type const VoidType* AsVoid() const; + /// @returns the type as an access control type + AccessControlType* AsAccessControl(); /// @returns the type as an alias type AliasType* AsAlias(); /// @returns the type as an array type diff --git a/src/ast/type/u32_type_test.cc b/src/ast/type/u32_type_test.cc index 7c42772820..ef0ff20656 100644 --- a/src/ast/type/u32_type_test.cc +++ b/src/ast/type/u32_type_test.cc @@ -25,6 +25,7 @@ using U32TypeTest = testing::Test; TEST_F(U32TypeTest, Is) { U32Type u; + EXPECT_FALSE(u.IsAccessControl()); EXPECT_FALSE(u.IsAlias()); EXPECT_FALSE(u.IsArray()); EXPECT_FALSE(u.IsBool()); diff --git a/src/ast/type/vector_type_test.cc b/src/ast/type/vector_type_test.cc index baa1342a3b..1cc53901c4 100644 --- a/src/ast/type/vector_type_test.cc +++ b/src/ast/type/vector_type_test.cc @@ -34,6 +34,7 @@ TEST_F(VectorTypeTest, Creation) { TEST_F(VectorTypeTest, Is) { I32Type i32; VectorType v{&i32, 4}; + EXPECT_FALSE(v.IsAccessControl()); EXPECT_FALSE(v.IsAlias()); EXPECT_FALSE(v.IsArray()); EXPECT_FALSE(v.IsBool());